[
  {
    "path": ".gitignore",
    "content": "#.gitignore for java\n*.class\n\n# Package Files #\n*.jar\n*.war\n*.ear\n**/target/\n**/output/\n**/META-INF/\n# logs\n/stacktrace.log\n/test/reports\nlogs/\n*.log\n*.log.*\n\n## .gitignore for intellij\n*.iml\n*.ipr\n*.iws\n.idea/\n.mvn/\n\n## .gitignore for eclipse\n*.pydevproject\n.project\n.metadata\nbin/**\ntmp/**\ntmp/**/*\n*.tmp\n*.bak\n*.swp\n*~.nib\nlocal.properties\n.classpath\n.settings/\n.loadpath\n\n/*.settings\npolaris-agent/*.project\npolaris-agent/polaris-agent-api/*.classpath\npolaris-agent/polaris-agent-api/*.project\n.DS_Store\n.gitversion\n**/.flattened-pom.xml"
  },
  {
    "path": "README.md",
    "content": "<img src=\"./doc/file/KnowSearch.png\" width=\"300\"/>\n\n# 1.KnowSearch简介\n\nKnowSearch是面向Elasticsearch研发与运维人员，围绕集群、索引构建的零侵入、多租户的Elasticsearch GUI管控平台。历经滴滴PB级海量索引数据考验、金融级1000+ES集群运营实战打磨，围绕Elasticsearch构建的可见、可管、可控的服务体系。\n\n- 围绕ES用户，构建了自助服务体系\n  - 量贩式集群/索引资源申请与管理\n  - 低门槛数据建模\n  - DSL/SQL灵活数据探查\n  - 基于DSL查询模板，自助问题诊断\n\n- 围绕ES运维，构建了场景化运维服务体系\n  - 基于Dashboard集群问题主动发现\n  - 基于集群看板高频问题快速诊断\n  - 基于集群管理，存量5.X+版本集群全量纳管、高频集群与索引变更批量支持\n  - 基于原生ES网关，零侵入、插件化的构建查询/写入限流、权限校验、跨集群访问、DSL查询模板分析与管控能力\n\n体验地址 http://101.43.178.205 ，用户名/密码：admin/admin123\n<br/>\nGrafana地址 http://101.43.178.205:3000\n\n# 2.KnowSearch特性\n\n滴滴内部大量使用 ES 来支撑日志探查与安全分析、交易数据近实时检索、企业SKU搜索与推荐等业务场景的基础搜索服务。在开源 Elasticsearch 基础上提供离线索引快速导入、跨集群复制、索引模板服务的企业特性，平台整体具有以下特点：\n\n- 5.X、6.X、7.X、8.X 众多主流Elasticsearch版本零侵入、统一纳管，多集群统一管理\n- 集群、节点、索引维度，30+ 稳定性、性能风险点主动巡检，Dashboard统一呈现\n- 集群、节点、索引维度，200+指标探查、同环比趋势分析、场景化指标筛选，助力问题高效诊断\n- 应用视角、索引视角、查询模板视角、ClientNode视角 30+ 用户写入、查询网关指标同环比监控分析\n- 集群动态配置管理、Sense 运维场景化命令集成、SearchProfiler集群慢查分析、集群快捷命令GUI集成\n- 索引Mapping/Setting/别名管理、RollOver/Shrink/Split/FroceMerge/读写禁用高频操作GUI批量执行\n\n# 3.KnowSearch产品图\n\nDashBoard、集群看板、网关看板、集群管理、索引管理核心产品功能图如下：\n\n<img src=\"./doc/file/KnowSearch-Dashboard.png\" style=\"zoom:50%;\" />\n<img src=\"./doc/file/KnowSearch-IndexBoard.png\"  style=\"zoom:50%;\" />\n<img src=\"./doc/file/KnowSearch-GateWay-Metric.png\"  style=\"zoom:50%;\"/>\n<img src=\"./doc/file/KnowSearch-ClusterManager.png\" style=\"zoom:50%;\" />\n<img src=\"./doc/file/KnowSearch-IndexManager.png\"  style=\"zoom:50%;\" />\n\n# 4.文档资源\n\n- [KnowSearch用户手册](doc/KnowSearch用户手册.md)\n- [KnowSearch安装部署文档](doc/KnowSearch安装部署文档.md)\n- [KnowSearch设计说明](doc/KnowSearch设计说明.md)\n- [KnowSearch-GateWay设计说明](doc/KnowSearch-GateWay设计文档.md)\n- [KnowSearch源码编译运行文档](doc/KnowSearch源码编译运行文档.md)\n- [ElasticSearch最佳实践](doc/ElasticSearch最佳实践.md)\n- [KnowSearch常见FAQ](doc/KnowSearch常见FAQ.md)\n\n# 5.技术交流\n\n微信加群：添加`PenceXie`的微信号备注KnowSearch加群，加群之前有劳点一下 Star，一个小小的 Star 是对KnowSearch作者们努力建设社区的动力。\n如果有商业合作需求，也欢迎咨询。\n\n"
  },
  {
    "path": "Releases_Notes.md",
    "content": "# v0.3.1\n\n版本上线时间：2022-12-30\n\n## 能力提升\n- KnowSearch工程，基于Metrics构建观测体系，指标通过Grafana展示\n- 物理集群接入流程加入Kibana/Cerebro外联地址，集群详情支持跳转到对应地址\n- 指标场景化设计，将指标看板细分为读写黄金指标、读写性能指标、读写热点指标、读写内存指标\n\n## 体验优化\n- 检索查询页面体验优化\n- 物理集群-快捷命令操作体验优化\n- 索引模板-禁用读写操作用户侧变更为工单形式\n- 子页面详情页支持打开多个\n- 一级二级页面展示优化，UI统一\n- 用户管理新增删除能力，新增用户密码展示\n- 指标看板支持对象多选\n- 查询模板中【启/禁用】、【修改限流值】加入工单审批流程\n- 下线kibana依赖\n- 模块改动，将低频模块转移至【系统管理】中\n\n## BUG修复\n- 脚本初始化后，需要还原平台配置默认值\n- 指标看板展示性能问题解决\n- 实例名称兼容中文\n\n\n\n# v0.2.3\n\n版本上线时间：2022-04-24\n\n## 能力提升\n\n- 集群看板—索引视图中增加以.开头的系统索引。\n- 集群看板增加指标监控项：stored_fields_memory。\n- 集群看板—索引视图指标优化：索引写入耗时优化为单条文档耗时，merge\\flush\\refresh耗时优化为单次耗时。\n- 指标拆解：网关写入量条/min拆为为写入吞吐量/min、写入请求量/min。\n- 物理集群—接入集群节点校验是否属于一个集群。\n- 编辑mapping不同步当前索引，在下次创建分区时生效。\n- 增加模块：Dashboard。\n- 集群看板—节点视图增加堆内存young/old区监控。\n- 优化指标看板中起始位置曲线尖刺。\n\n## 体验优化\n\n- 集群看板—节点视图选择节点时，支持一次选择多个节点。\n- 集群看板—总览视图指标查看时，多个图表可以联动显示。\n- 指标布局优化，统一write queue与search queue的名称。\n- 指标看板节点列表按指标大小排序。\n- 集群总览自动刷新支持全页面刷新。\n- 查询模板详情增加md5信息。\n- 搜索框输入内容去除前后空格。\n- 集群看板，时间筛选器起止时间跨度限制为7天内。\n- 新建模板未开启索引模板服务时置灰相关项mapping和setting。\n- 平台配置中的【值】长度上限修改为1000。\n- 索引模板操作记录分类，mapping编辑部分优化。\n- 搜索框支持回车查询。\n- 总览视图新增堆内存使用率。\n- 索引名称、索引模板名称展示优化（索引50 模板30字符）。\n- 指标看板搜索框宽度，集群看板索引视图50字符，索引模板30字符，网关看板索引视图50字符。\n\n## BUG修复\n\n- 集群看板—节点视图merge,flush,refresh展示每分钟的次数（次/min）。\n- DCDR版本校验、任务失败后可再次提交。\n- 索引模板升版本，新增的版本号只加到当天分区，第二天新建的分区不加版本号后缀。\n\n\n\n# v0.2.2\n\n版本上线时间：2022-03-14\n\n## 能力提升\n\n- DCDR特性去除对Rack依赖，优化DCDR链路创建规范，新建链路时可以进行rack选择。\n- admin和gateway中 xxx.yml 或者 xxx.properties中配置项port说明不明确。应该指明是http port 还是tcp port。\n- 索引删除逻辑优化（索引管理页面新增close和open按钮，作用是打开或者关闭索引，用户可以选择close索引）。\n- Elasticsearch元数据集群专项治理（包括增加routing以及索引index sort）。\n- GateWay日志优化+Get Node Task记录，整体写入与查询问题。\n- 2.3.3 存量ES集群版本全纳管，索引管理模板中check禁用读、禁用写。\n- 网关原生模式：支持限流（支持appid粒度）、支持gateway对请求token校验。\n- Kibana的DisCover模块代理逻辑（非dsl控制台也要数据隔离，带上物理集群名到gateway查询）。\n- 增加Sense管控的集群路由能力。\n- 元信息指标读写都在GateWay，网关看板指标保障准确（网关看板添加clientNode视图）。\n- 指标看板-topN算法优化。\n- 指标看板新增索引模板视图的指标监控。\n\n## 体验优化\n\n- 平台搜索框需要具备记录能力，切换不清空。\n- 接入集群端口放开，不限制只能4位。之前是限制4位，后面放开为0-25535。\n- 集群版本管理体验优化 ，新增版本标识：滴滴内部、开源。\n- 集群名称默认物理名称+集群版本号（输入框加提示，规范用户操作）。\n- 平台配置项的说明文档优化，配置说明优化（跳转至github文档说明）。\n- 模板管理的操作项将平台能力与索引模板服务区分展示。\n- 插件管理定义（物理集群插件管理分为平台能力插件、ES能能力插件）。\n- 索引模板详情 Mapping、 Setting  、DCDR TAB页体验页面优化。\n- 全平台集群下拉框需要支持搜索能力。\n- 检索查询--索引查新--SQL查询页面体验优化。\n- 指标配置新增黄金指标配置，点击一键勾选黄金指标。\n- 容量规划概念统一为索引RollOver（shard调整和indexRollover 统一，索引模版服务名称由容量规划改为索引规划）。\n- 索引模板管理页面加入物理集群筛选项。\n- 指标图表可以同类中进行拖拽，指标配置顺序同步修改。\n- 接入集群记录主机分为两种模式：自动获取、全量录入。\n- LogIEM全平台列表排序支持全局排序。\n- 新建集群增加节点规格输入框，物理集群详情-节点划分新增节点规格展示列。\n- 筛选分片过多的集群 ：物理集群列表增加一列”活跃分片数“，支持排序。\n- 索引模板mapping、setting等更新操作需要保留记录（旧mapping、setting和修改后的mapping setting）。\n- 逻辑集群增加等级标识：核心、重要、一般。索引模板支持业务等级与逻辑集群绑定，新建模板时默认与所选集群业务等级一致，支持修改，升降等级均可。\n- 集群接入增加所属资源类型：acs、vmware、信创（tce）。\n- 检索查询-DSL模板改成查询诊断。\n- 总览视图和节点视图中涉及到数量趋势、TASK耗时的指标名称改为（节点）执行任务数量、（节点）执行任务数耗时。\n\n## bug修复\n\n- 修复dcdr采集任务报错，自己的元数据es引擎根本没有DCDR的actionplugin。\n- 修复DSL查询切换集群时报错问题（GET  _cluster/health?v）。\n- 修复网关看板--查询模板点击事件消失问题（可能是代码未合到主分支导致）。\n- 统一集群看板的节点角色概念和物理集群详情中节点划分的角色概念。\n- 集群状态statustype 0，1，2统一标准。\n- 索引模板名称不支持大写字母，前端修复。\n"
  },
  {
    "path": "arius-admin/README.md",
    "content": "## 1. 项目背景\n    arius-admin-v2 致力于实现一套于对Elasticsearch元数据的管控平台，负责维护项目（APPID）、索引、Elasticsearch集群资源等信息的管理，并维护三者之前的关系；对外暴露restFul接口，以提供查询管控元数据的能力。\n## 2. 模块划分\narius-admin-v2由10个主要的工程和扩展增值服务组成:\n\n```java\narius-admin-rest            表现层1，可以直接封装Manager接口暴露成restful接口 \narius-admin-task            表现层2，提供auv-job定时调度任务入口, 任务实现在arius-admin-biz/arius-admin-core中 \narius-admin-common          基础组件层1，存放业务需要数据结构, 如Java POJO(entity、po)、公共工具方法、事件等 \narius-admin-client          基础组件层2，存放业务需要的POJO(vo、dto)、枚举等, 并且提供客户端请求响应的数据实体。 \narius-admin-biz             业务层1，负责对arius-admin-core中各种的业务逻辑进行聚合处理，提供表现层所需要的数据实体 \narius-admin-extend          业务层2，扩展服务, 如容量规划等 \narius-admin-core            核心层1，提供核心的管控能力, 主要的业务逻辑实现, 如集群、索引、项目等 \narius-admin-metadata        核心层2，负责对Elasticsearch的元数据采集，如索引指标统计、节点指标统计, 提供的能力包括但不限于DSL分析、健康检查等 \narius-admin-persistence     数据层1，负责对MySQL和Elasticsearch中的数据进行操作 \narius-admin-remote          数据层2，获取第三方服务数据, 如访问文件存储系统、企业部门系统等\n```\n\n名词定义：\n\n```java\nresource:       逻辑资源\ncluster:        物理ES集群\nregion:         一组ES DataNode组成的最小资源分配单位\n```\n\n\n​    \n## 3. 如何使用\n    可单独部署，也可配合网关 arius-gateway-v2 一同使用，致力于更高效的管控 Elasticsearch 元数据\n\n### 3.1 配置\n    配置环境文件：application-xxx.properties\n#### 3.1.1 更新ES数据集群名称\n```java\nes.update.cluster.name: {name}\nes.client.cluster.port: {port}\n```\n\n#### 3.1.2 网关配置\n    es.gateway.url: {host}\n    es.gateway.port: {port}\n    es.appid: {appId1},{appId2},{appId3}\n    es.password: {passwd},{passwd},{passwd}\n\n#### 3.1.3 数据源配置\n    datasource:\n        name: data\n        type: com.alibaba.druid.pool.DruidDataSource \n        druid:\n          driver-class-name: com.mysql.jdbc.Driver\n          url: jdbc:mysql://{host}:{port}/{dbName}?useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=true&allowMultiQueries=true&useSSL=false\n        username: {username}\n        password: {password}\n    auv-job:\n        jdbc-url: jdbc:mysql://{host}:{port}/{dbName}?useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=true&allowMultiQueries=true&useSSL=false\n        username: {username}\n        password: {password}\n\n### 3.2 打包\n    mvn clean package -Dmaven.test.skip=true\n\n### 3.3 运行\n    java -jar arius-admin-rest.jar --spring.profiles.active=xxx (test、dev)"
  },
  {
    "path": "arius-admin/arius-admin-biz/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <artifactId>arius-admin</artifactId>\n         <version>${revision}${sha1}${changelist}</version>\n    </parent>\n\n    <artifactId>arius-admin-biz</artifactId>\n\n    <dependencies>\n       \n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-common</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-remote</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-persistence</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-metadata</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-lang3</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.guava</groupId>\n            <artifactId>guava</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-collections4</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-elasticsearch-client</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-email</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.sun.mail</groupId>\n                    <artifactId>javax.mail</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-context-support</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.reflections</groupId>\n            <artifactId>reflections</artifactId>\n        </dependency>\n\n    </dependencies>\n\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ClusterContextManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogicContext;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhyContext;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by linyunan on 2021-06-08\n * 后续下线\n * {@see 0.3.2}\n */\n@Deprecated\npublic interface ClusterContextManager {\n    /**\n     * 刷新物理集群上下文\n     * @param clusterPhyName  物理集群名称\n     * @return ClusterPhyContext 物理集群上下文\n     */\n    ClusterPhyContext flushClusterPhyContext(String clusterPhyName);\n\n    /**\n     * 刷新逻辑集群上下文\n     * @param clusterLogicId   逻辑集群Id\n     * @return ClusterLogicContext 逻辑集群上下文     \n     */\n    ClusterLogicContext flushClusterLogicContext(Long clusterLogicId);\n\n    /**\n     * 根据region信息更新集群上下文\n     * @param clusterRegion\n     */\n    void flushClusterContextByClusterRegion(ClusterRegion clusterRegion);\n\n    /**\n     * 校验逻辑集群是可否关联物理集群, 不同类型的逻辑集群, 校验规则不一样\n     * @param clusterLogicId\n     * @param clusterPhyName\n     * @param regionId\n     * @param clusterLogicType     \n     */\n    Result<Boolean> canClusterLogicAssociatedPhyCluster(Long clusterLogicId, String clusterPhyName, Long regionId,\n                                                        Integer clusterLogicType);\n\n    /**\n     * 获取可关联的物理集群名称列表, 针对新建逻辑集群、逻辑集群关联region等操作\n     * @param clusterLogicIdclusterLogicType \n     * @param clusterLogicId\n     */\n    Result<List<String>> getCanBeAssociatedClustersPhys(Integer clusterLogicType, Long clusterLogicId);\n\n    /**\n     * 获取集群关联逻辑集群名称列表\n     * @param clusterPhyName     \n     */\n    List<String> getClusterPhyAssociatedClusterLogicNames(String clusterPhyName);\n\n    /**\n     * 构建物理集群上下文\n     * @param cluster\n     * @return ClusterPhyContext \n     */\n    ClusterPhyContext getClusterPhyContext(String cluster);\n\n     /**\n     * 从缓存中获取物理集群上下文\n     * @param cluster\n     * @return ClusterPhyContext \n     */\n    ClusterPhyContext getClusterPhyContextCache(String cluster);\n\n    /**\n     * 获取物理集群对应的上下文信息Map\n     * @return key-> 物理集群名称, value 上下文信息\n     */\n    Map<String, ClusterPhyContext> listClusterPhyContextMap();\n\n    /**\n     * 从缓存中获取逻辑集群上下文\n     *\n     * @param clusterLogicId 逻辑集群Id\n     * @return ClusterLogicContext 逻辑集群上下文\n     */\n    ClusterLogicContext getClusterLogicContextCache(Long clusterLogicId);\n\n    /**\n     * 构建逻辑集群上下文\n     * @param clusterLogicId 逻辑集群Id\n     * @return ClusterLogicContext 逻辑集群上下文\n     */\n    ClusterLogicContext getClusterLogicContext(Long clusterLogicId);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ClusterIndexManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport java.util.List;\n\n/**\n * 索引业务相关.\n *\n * @ClassName ClusterIndexManager\n * @Author gyp\n * @Date 2022/6/13\n * @Version 1.0\n */\npublic interface ClusterIndexManager {\n    /**\n     * 获取逻辑集群索引列表\n     *\n     * @param clusterId 集群id\n     * @param projectId 项目id\n     * @return {@link Result}<{@link List}<{@link ESClusterRoleHostVO}>>\n     */\n    Result<List<ESClusterRoleHostVO>> listClusterLogicIndices(Integer clusterId, Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ClusterLogicManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterJoinDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterWithRegionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateClearDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterLogicTemplateIndexCountVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterLogicVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterPhyVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterPhyWithLogicClusterVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.PluginVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm.ESClusterNodeSepcVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport java.util.List;\n\n/**\n * @description: 逻辑集群manager\n * @author gyp\n * @date 2022/5/31 16:26\n * @version 1.0\n */\npublic interface ClusterLogicManager {\n\n    /**\n     * 构建运维页面的逻辑集群VO\n     * @param logicClusters     逻辑集群列表\n     * @return List<ClusterLogicVO> 逻辑集群VO列表\n     */\n    List<ClusterLogicVO> buildClusterLogics(List<ClusterLogic> logicClusters);\n\n    /**\n     * 构建运维页面的逻辑集群VO\n     * @param clusterLogic    逻辑集群\n     * @return ClusterLogicVO 逻辑集群VO\n     */\n    ClusterLogicVO buildClusterLogic(ClusterLogic clusterLogic);\n\n    /**\n     * 获取project拥有的逻辑集群id和名称列表\n     * @param projectId 应用id\n     * @return\n     */\n    Result<List<Tuple<Long/*逻辑集群Id*/, String/*逻辑集群名称*/>>> listProjectClusterLogicIdsAndNames(Integer projectId);\n\n    /**\n     * 获取项目下的逻辑集群信息\n     *\n     * @param projectId 项目id\n     * @return\n     */\n    Result<List<ClusterLogicVO>> getLogicClustersByProjectId(Integer projectId);\n\n    /**\n     * 根据项目和集群类型获取逻辑集群(项目对其有管理权限)名称列表\n     * @param projectId 项目id\n     * @param type 集群类型\n     * @return\n     */\n    Result<List<ClusterLogicVO>> getProjectLogicClusterInfoByType(Integer projectId, Integer type);\n\n\n\n    /**\n     * 获取当前集群支持的套餐列表\n     * @return\n     */\n    Result<List<ESClusterNodeSepcVO>> listMachineSpec();\n\n    /**\n     * clearIndices\n     * @param clearDTO\n     * @param operator\n     * @return\n     * @throws ESOperateException\n     */\n    Result<Void> clearIndices(TemplateClearDTO clearDTO, String operator) throws ESOperateException;\n\n    /**\n     * 获取逻辑集群分派的物理集群列表\n     *\n     * @param logicClusterId 逻辑集群ID\n     * @return ClusterPhy 物理集群\n     */\n    ClusterPhy getLogicClusterAssignedPhysicalClusters(Long logicClusterId);\n\n\n\n    /**\n     *  获取单个逻辑集群overView信息\n     * @param clusterLogicId 逻辑集群id\n     * @param currentProjectId 当前登录项目\n     * @return ClusterLogicVO 逻辑集群VO\n     */\n    ClusterLogicVO getClusterLogic(Long clusterLogicId, Integer currentProjectId);\n\n    /**\n     * 新建逻辑集群, 关联 logicCluster 关联 region\n     *\n     * @param param    集群信息\n     * @param operator 操作人\n     * @return 成功或失败\n     */\n    Result<Void> addLogicClusterAndClusterRegions(ESLogicClusterWithRegionDTO param,\n                                                  String operator) throws AdminOperateException;\n\n    /**\n     * 逻辑集群下线\n     * @param logicClusterId 逻辑集群id\n     * @param operator 操作人\n     * @param projectId projectId 项目id\n     * @return 成功或者失败\n     * @throws AdminOperateException\n     */\n    Result<Void> deleteLogicCluster(Long logicClusterId, String operator,\n                                    Integer projectId) ;\n\n    /**\n     *  修改逻辑集群信息\n     * @param param 逻辑集群dto\n     * @param operator 操作人\n     * @param projectId projectId\n     * @return 成功或者失败\n     */\n    Result<Void> editLogicCluster(ESLogicClusterDTO param, String operator, Integer projectId);\n\n    /**\n     * 组合查询带分页信息的逻辑集群列表\n     * @param condition\n     * @param projectId 项目id\n     * @return\n     */\n    PaginationResult<ClusterLogicVO> pageGetClusterLogics(ClusterLogicConditionDTO condition,\n                                                          Integer projectId) throws NotFindSubclassException, ESOperateException;\n\n    /**\n     * 更新逻辑集群状态\n     * @param clusterLogicId\n     * @return\n     */\n    boolean updateClusterLogicHealth(Long clusterLogicId);\n\n    /**\n     * 获取我的集群下索引和模板的数量\n     * @param clusterId\n     * @param operator\n     * @param projectId 项目id\n     * @return\n     */\n    Result<ClusterLogicTemplateIndexCountVO> indexTemplateCount(Long clusterId, String operator, Integer projectId);\n\n    /**\n     * 获取预估磁盘大小\n     * @param clusterLogicId 逻辑集群id\n     * @param count\n     * @return\n     */\n    Result<Long> estimatedDiskSize(Long clusterLogicId, Integer count);\n\n    /**\n     * 获取当前逻辑集群对应region的机器规格\n     * @param clusterLogicId 逻辑集群id\n     * @return\n     */\n    Result<String> getClusterDataNodeSpec(Long clusterLogicId);\n\n    /**\n     * 根据projectId获取项目下的逻辑集群\n     * @param projectId 项目id\n     * @return\n     */\n    Result<List<String>> listClusterLogicNameByProjectId(Integer projectId);\n\n    /**\n     * 根据项目id获取集群的映射关系\n     * @param projectId 项目id\n     * @return\n     */\n    Result<List<Tuple<String, ClusterPhyVO>>> getClusterRelationByProjectId(Integer projectId);\n\n    /**\n     *  获取逻辑集群插件列表\n     * @param clusterId 逻辑集群id\n     * @return 插件列表\n     */\n    Result<List<PluginVO>> getClusterLogicPlugins(Long clusterId);\n\n    /**\n     * 检查逻辑集群的reigon是否不为空\n     *\n     * @param logicClusterId 逻辑集群id\n     * @return {@link Result}<{@link Boolean}>\n     */\n    Result<Boolean> isLogicClusterRegionIsNotEmpty(Long logicClusterId);\n    \n     /**\n     * 根据level获取逻辑集群VO列表\n     *\n     * @param level\n     * @return {@link Result}<{@link List<ClusterLogicVO>}>\n     */\n    Result<List<ClusterLogicVO>> getLogicClustersByLevel(Integer level);\n    \n    /**\n     * 验证集群逻辑的参数\n     *\n     * @param param 要验证的参数对象。\n     * @param operation OperationEnum.ADD、OperationEnum.UPDATE、OperationEnum.DELETE\n     * @param projectId 项目编号\n     * @return 返回类型是 Result<Void>，它是操作结果的包装类。\n     */\n    Result<Void> validateClusterLogicParams(ESLogicClusterDTO param, OperationEnum operation, Integer projectId);\n    \n    \n   \n    /**\n     * 加入逻辑集群\n     *\n     * @param logicClusterId 要加入的逻辑集群 ID。\n     * @param joinProjectId 待加入的项目ID\n     * @return 返回类型是 Result<Void>，它是操作结果的包装类。\n     */\n    Result<Void> joinClusterLogic(Long logicClusterId, Integer joinProjectId);\n   \n    /**\n     * 返回与给定物理集群名称关联的逻辑集群名称列表\n     *\n     * @param phyClusterName 物理集群的名称。\n     * @return List<String> 与给定集群物理名称关联的集群逻辑名称列表。\n     */\n    List<String> getClusterPhyAssociatedClusterLogicNames(String phyClusterName);\n\n    /**\n     * 根据物理集群名获取对应的逻辑集群列表，若传入为空，则返回全量\n     * @param phyClusterName 物理集群的名称\n     * @return List<String> 逻辑集群名称列表\n     */\n    List<String> listClusterLogicNameByPhyName(String phyClusterName);\n\n    /**\n     * 根据项目id获取对应的逻辑集群列表\n     * @param projectId 项目id\n     * @return List<String> 逻辑集群名称列表\n     */\n    List<String> listClusterLogicNameByApp(Integer projectId);\n    \n     /**\n     * 加入物理集群并创建逻辑集群\n     *\n     * @param param ClusterJoinDTO\n     * @param projectId 项目编号\n     * @return joinClusterPhyAndCreateLogicCluster 方法的结果。\n     */\n    Result<Long> joinClusterPhyAndCreateLogicCluster(ClusterJoinDTO param, Integer projectId)\n            throws AdminOperateException;\n    \n    /**\n     * 列出一个项目中的所有物理集群及其对应的逻辑集群\n     *\n     * @param projectId 项目编号\n     * @return 列表<ClusterPhyWithLogicClusterVO>\n     */\n    Result<List<ClusterPhyWithLogicClusterVO>> listLogicClusterWithClusterPhyByProjectId(Integer projectId);\n    \n    /**\n     * 根据物理集群名获取其对应的逻辑集群\n     *\n     * @param phyClusterName 物理集群名\n     * @return 列表<ClusterLogicVO>\n     */\n    Result<List<ClusterLogicVO>> listClusterLogicByPhyName(String phyClusterName);\n\n    /**\n     * 删除从模板及索引数据\n     * @param clusterLogicId 逻辑集群id\n     * @param projectId 项目编号\n     * @param operator 操作人\n     * @return\n     */\n    Result<Void> deleteTemplatesIndicesInfo(Long clusterLogicId,Integer projectId,String operator);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ClusterNodeManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionWithNodeInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterNodeInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostWithRegionInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport java.util.List;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-30\n */\npublic interface ClusterNodeManager {\n    /**\n     * 获取可划分至region的节点信息\n     * @param clusterId   物理集群Id\n     * @return            Result<List<ESClusterRoleHostVO>>\n     */\n    Result<List<ESClusterRoleHostWithRegionInfoVO>> listDivide2ClusterNodeInfo(Long clusterId);\n\n    /**\n     * 划分指定节点至region\n     *\n     * @param params    集群带节点信息的Region实体\n     * @param operator  操作者\n     * @param projectId\n     * @return Result<Long>\n     */\n    Result<List<Long>> createMultiNode2Region(List<ClusterRegionWithNodeInfoDTO> params, String operator,\n                                              Integer projectId) throws AdminOperateException;\n\n    /**\n     * 编辑节点的region属性\n     *\n     * @param params        集群带节点信息的Region实体\n     * @param operator      操作者\n     * @param projectId\n     * @param operationEnum\n     * @return Result<Boolean>\n     */\n    Result<Boolean> editMultiNode2Region(List<ClusterRegionWithNodeInfoDTO> params, String operator,\n                                         Integer projectId, OperationEnum operationEnum) throws AdminOperateException;\n\n    /**\n     * 获取物理集群节点列表\n     *\n     * @param clusterId 集群id\n     * @return {@link Result}<{@link List}<{@link ESClusterRoleHostVO}>>\n     */\n    Result<List<ESClusterRoleHostVO>> listClusterPhyNode(Integer clusterId);\n\n    /**\n     * 获取逻辑集群节点列表\n     *\n     * @param clusterId 集群id\n     * @return {@link Result}<{@link List}<{@link ESClusterRoleHostVO}>>\n     */\n    Result<List<ESClusterRoleHostVO>> listClusterLogicNode(Integer clusterId);\n\n    /**\n     * 通过逻辑集群名称获取节点\n     * @param clusterLogicName\n     * @return\n     */\n    Result listClusterLogicNodeByName(String clusterLogicName);\n\n    /**\n     * 通过逻辑集群名称获取节点信息\n     * @param clusterLogicName\n     * @return\n     */\n    Result<List<ClusterNodeInfoVO>> listClusterLogicNodeInfosByName(String clusterLogicName);\n\n    /**\n     * 通过逻辑集群ID获取节点信息\n     * @param regionId\n     * @return\n     */\n    Result<List<ESClusterRoleHostVO>> listClusterRoleHostByRegionId(Long regionId);\n\n    /**\n     * 采集集群节点数据\n     *\n     * @param cluster 集群\n     * @return boolean\n     * @throws AdminTaskException 管理任务异常\n     */\n    boolean collectNodeSettings(String cluster) throws AdminTaskException;\n    \n    /**\n     * > 该功能用于删除集群节点，但该节点必须离线且未绑定 region\n     *\n     * @param ids       要删除的节点的 id\n     * @param projectId 项目编号\n     * @param operator  操作员是执行操作的用户。\n     */\n    Result<Void> delete(List<Integer> ids, Integer projectId, String operator);\n\n    /**\n     * 校验节点的region划分\n     * @param params\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Boolean> checkMultiNode2Region(List<ClusterRegionWithNodeInfoDTO> params, String operator, Integer projectId);\n\n    /**\n     * 通过物理集群获取带角色的节点信息\n     * @param clusterPhyName\n     * @return\n     */\n    Result<List<ClusterNodeInfoVO>> listClusterPhyNodeInfosByName(String clusterPhyName);\n\n    /**\n     * 获取当前平台所有集群节点的机器规格\n     * @return\n     */\n    Result<List<String>> listAllMachineSpecs();\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ClusterPhyManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterJoinDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterPhyVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.PluginVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterConnectionStatusWithTemplateEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterDynamicConfigsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleThree;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n *\n * @author ohushenglin_v\n * @date 2022-05-10\n */\npublic interface ClusterPhyManager {\n\n    /**\n     * 对集群下所有模板执行拷贝索引的mapping到模板操作\n     * @param cluster 集群\n     * @param retryCount 重试次数\n     * @return true/false\n     */\n    boolean copyMapping(String cluster, int retryCount);\n    TupleThree</*dcdrExist*/Boolean,/*pipelineExist*/ Boolean,/*existColdRegion*/ Boolean> getDCDRAndPipelineAndColdRegionTupleByClusterPhyWithCache(String clusterPhy);\n     /**\n      * 它返回集群和缓存之间的连接状态。\n      *\n      * @param clusterPhy 集群的物理名称。\n      * @return 正在返回 ClusterConnectionStatusWithTemplateEnum。\n      */\n     ClusterConnectionStatusWithTemplateEnum getClusterConnectionStatusWithCache(String clusterPhy);\n    \n\n    /**\n     * 同步元数据\n     * @param cluster    集群名称\n     * @param retryCount 重试次数\n     * @return\n     */\n    void syncTemplateMetaData(String cluster, int retryCount) throws ESOperateException;\n\n    /**\n     * 集群是否存在\n     * @param clusterName 集群名字\n     * @return true 存在\n     */\n\n    boolean isClusterExists(String clusterName);\n\n    /**\n     * 获取控制台物理集群信息列表(ZH有使用)\n     * @param param 查询参数\n     * @return 物理集群列表\n     */\n    List<ClusterPhyVO> listClusterPhys(ClusterPhyDTO param);\n\n    /**\n     * 构建客户端需要的数据\n     *\n     * @param clusterPhyList  集群列表源数据\n     * @return\n     */\n    List<ClusterPhyVO> buildClusterInfo(List<ClusterPhy> clusterPhyList);\n\n    /**\n     * 获取单个物理集群overView信息\n     * @param clusterId 物理集群id\n     * @param currentProjectId 当前登录项目\n     * @return 物理集群信息\n     */\n    ClusterPhyVO getClusterPhyOverview(Integer clusterId, Integer currentProjectId);\n\n    /**\n     * 获取逻辑集群可关联region的物理集群名称列表\n     * @param clusterLogicType 逻辑集群类型\n     * @param clusterLogicId   逻辑集群Id\n     * @see ClusterResourceTypeEnum\n     * @return 物理集群名称\n     */\n    Result<List<String>> listCanBeAssociatedRegionOfClustersPhys(Integer clusterLogicType, Long clusterLogicId);\n\n    /**\n     * 获取新建逻辑集群可关联的物理集群名称\n     * @param clusterLogicType  逻辑集群类型\n     * @see ClusterResourceTypeEnum\n     * @return 物理集群名称\n     */\n    Result<List<String>> listCanBeAssociatedClustersPhys(Integer clusterLogicType);\n\n    /**\n     * 集群接入\n     *\n     * @param param     逻辑集群Id, 物理集群名称\n     * @param operator  操作人\n     * @param projectId\n     * @return ClusterPhyVO\n     */\n    Result<ClusterPhyVO> joinCluster(ClusterJoinDTO param, String operator, Integer projectId);\n\n    /**\n     * 删除接入集群 删除顺序: region ——> clusterLogic ——> clusterHost ——> clusterRole  ——> cluster\n     *\n     * @param clusterId 集群id\n     * @param operator  操作人\n     * @param projectId\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> deleteClusterJoin(Integer clusterId, String operator, Integer projectId);\n\n    /**\n     * 插件列表\n     *\n     * @param cluster 集群\n     * @return {@link Result}<{@link List}<{@link PluginVO}>>\n     */\n    Result<List<PluginVO>> listPlugins(String cluster);\n\n    /**\n     * 获取集群下的动态配置信息\n     * @param cluster 物理集群的名称\n     * @return 动态配置信息 Map中的String见于动态配置的字段，例如cluster.routing.allocation.awareness.attributes\n     */\n    Result<Map<ClusterDynamicConfigsTypeEnum, Map<String, Object>>> getPhyClusterDynamicConfigs(String cluster)\n\t\t    throws ESOperateException;\n\n    /**\n     * 更新集群下的动态配置信息\n     *\n     * @param param     配置信息参数\n     * @param operator\n     * @param projectId\n     * @return result\n     */\n    Result<Boolean> updatePhyClusterDynamicConfig(ClusterSettingDTO param, String operator, Integer projectId) throws ESOperateException ;\n\n    /**\n     * 获取集群下的属性配置\n     * @param cluster 集群名称\n     * @return result\n     */\n    Result<Set<String>> getRoutingAllocationAwarenessAttributes(String cluster);\n\n    /**\n     * 获取APP有管理、读写、读权限的物理集群名称列表\n     *\n     * @param projectId projectId\n     * @return {@link List}<{@link String}>\n     */\n    List<String> listClusterPhyNameByProjectId(Integer projectId);\n\n    /**\n     * 根据模板所在集群，获取与该集群相同版本号的集群名称列表\n     * @param projectId      projectId\n     * @param templateId 模板id\n     * @return {@link Result}<{@link List}<{@link String}>>\n     */\n    Result<List<String>> getTemplateSameVersionClusterNamesByTemplateId(Integer projectId, Integer templateId);\n    \n    Result<List<String>> getTemplateSameVersionClusterNamesByTemplateIdExistDCDR(Integer projectId, Integer templateId);\n\n\n    /**\n     * 获取物理集群节点名称列表\n     * @param clusterPhyName 集群phy名称\n     * @return {@link List}<{@link String}>\n     */\n    List<String> listClusterPhyNodeName(String clusterPhyName);\n\n    /**\n     * 构建单个物理集群统计信息\n     * @param cluster 集群\n     */\n    void buildPhyClusterStatics(ClusterPhyVO cluster);\n\n    /**\n     * 获取APP可查看的物理集群节点名称列表\n     * @param projectId projectId\n     * @return {@link List}<{@link String}>\n     */\n    List<String> listNodeNameByProjectId(Integer projectId);\n\n    /**\n     * 物理集群信息删除 (host信息、角色信息、集群信息、region信息)\n     *\n     * @param clusterPhyId 物理集群ID\n     * @param operator     操作人\n     * @param projectId\n     * @return {@link Result}<{@link Boolean}>\n     */\n    Result<Boolean> deleteCluster(Integer clusterPhyId, String operator, Integer projectId);\n\n    /**\n     * 添加集群\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @param projectId    projectId\n     * @return {@link Result}<{@link Boolean}>\n     */\n    Result<Boolean> addCluster(ClusterPhyDTO param, String operator, Integer projectId);\n\n    /**\n     * 编辑集群\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @return {@link Result}<{@link Boolean}>\n     */\n    Result<Boolean> editCluster(ClusterPhyDTO param, String operator);\n\n    /**\n     * 条件组合、分页查询\n     * @param condition\n     * @param projectId\n     * @return\n     */\n    PaginationResult<ClusterPhyVO> pageGetClusterPhys(ClusterPhyConditionDTO condition,\n                                                      Integer projectId) throws NotFindSubclassException;\n\n    /**\n     * 根据projectId获取超级项目下的物理集群列表\n     * @param projectId 项目id\n     * @return Result<List<String>>\n     */\n    Result<List<String>> listClusterPhyNameBySuperApp(Integer projectId);\n\n    /**\n     * 构建物理集群角色信息\n     * @param cluster\n     */\n    void buildClusterRole(ClusterPhyVO cluster);\n\n    /**\n     * 构建集群作用\n     *\n     * @param cluster      集群\n     * @param clusterRoleInfos 集群角色\n     */\n    void buildClusterRole(ClusterPhyVO cluster, List<ClusterRoleInfo> clusterRoleInfos);\n\n    /**\n     * 更新物理集群状态\n     * @param clusterPhyName   物理集群名称\n     * @param operator         操作者\n     * @return\n     */\n    boolean updateClusterHealth(String clusterPhyName, String operator);\n\n    /**\n     * 更新集群资源信息\n     * @param cluster\n     * @param operator\n     * @return\n     */\n    boolean updateClusterInfo(String cluster, String operator);\n\n    /**\n     * 校验集群状态是否有效\n     * @param clusterPhyName\n     * @param operator\n     * @return\n     */\n    Result<Boolean> checkClusterHealth(String clusterPhyName, String operator);\n\n    /**\n     * 集群是否存在\n     * @param clusterPhyName\n     * @param operator\n     * @return\n     */\n    Result<Boolean> checkClusterIsExit(String clusterPhyName, String operator);\n\n    /**\n     * 删除存在集群\n     * @param clusterPhyName\n     * @param projectId\n     * @param operator\n     * @return\n     */\n    Result<Boolean> deleteClusterExit(String clusterPhyName, Integer projectId, String operator);\n\n    /**\n     *  根据逻辑集群类型和已选中的物理集群名称筛选出es版本一致的物理集群名称列表\n     *  @param hasSelectedClusterNameWhenBind 用户在新建逻辑集群阶段已选择的物理集群名称\n     *  @param clusterLogicType 逻辑集群类型\n     *  @return 同版本的物理集群名称列表\n     */\n    Result<List<String>> getPhyClusterNameWithSameEsVersion(Integer clusterLogicType,\n                                                            String hasSelectedClusterNameWhenBind);\n\n    /**\n     * 根据已经创建的逻辑集群id筛选出物理集群版本一致的物理集群名称列表\n     * @param clusterLogicId 逻辑集群id\n     * @return 同版本的物理集群名称列表\n     */\n    Result<List<String>> getPhyClusterNameWithSameEsVersionAfterBuildLogic(Long clusterLogicId);\n\n    /**\n     * 更新集群网关\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @return {@link Result}<{@link ClusterPhyVO}>\n     */\n    Result<ClusterPhyVO> updateClusterGateway(ClusterPhyDTO param, String operator);\n\n    /**\n     * 根据集群ID获取物理集群角色\n     *\n     * @param clusterId 集群id\n     * @return {@link List}<{@link ClusterRoleInfo}>\n     */\n    List<ClusterRoleInfo> listClusterRolesByClusterId(Integer clusterId);\n\n    /**\n     * 根据集群名称获获取集群节点列表\n     *\n     * @param cluster 集群名称\n     * @return {@link List}<{@link ClusterRoleHost}>\n     */\n    List<ClusterRoleHost> listClusterRoleHostByCluster(String cluster);\n    /**\n     * 按照资源类型查询物理集群名称列表\n     *\n     * @param clusterResourceType 集群资源类型\n     * @param projectId           项目id\n     * @return {@link Result}<{@link List}<{@link String}>>\n     */\n    Result<List<String>> listClusterPhyNameByResourceType(Integer clusterResourceType, Integer projectId);\n    \n    Result<ClusterPhy> getClusterByName(String masterCluster);\n    \n    boolean ensureDCDRRemoteCluster(String cluster, String remoteCluster) throws ESOperateException;\n    \n    /**\n     * 它返回满足条件的总数。\n     *\n     * @param condition 查询的条件。\n     * @return 长\n     */\n    Long fuzzyClusterPhyHitByCondition(ClusterPhyConditionDTO condition);\n    \n    /**\n     * 按条件获取集群物理信息\n     *\n     * @param condition 查询的条件。\n     * @return 列表<ClusterPhy>\n     */\n    List<ClusterPhy> pagingGetClusterPhyByCondition(ClusterPhyConditionDTO condition);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ClusterPhyQuickCommandManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyQuickCommandIndicesQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyQuickCommandShardsQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.IndicesDistributionVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.NodeStateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.PendingTaskAnalysisVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.ShardAssignmentDescriptionVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.ShardDistributionVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.TaskMissionAnalysisVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport java.util.List;\n\n/**\n * 快捷指令.\n *\n * @ClassName QuickCommandManager\n * @Author gyp\n * @Date 2022/6/1\n * @Version 1.0\n */\npublic interface ClusterPhyQuickCommandManager {\n    \n    /**\n     * node_state分析\n     *\n     * @param clusterId\n     * @return\n     */\n    Result<List<NodeStateVO>> nodeStateAnalysis(String clusterId);\n    \n    /**\n     * indices分布\n     *\n     * @param cluster\n     * @return\n     */\n    Result<List<IndicesDistributionVO>> indicesDistribution(String cluster);\n    \n    /**\n     * pending task分析\n     *\n     * @param cluster\n     * @return\n     */\n    Result<List<PendingTaskAnalysisVO>> pendingTaskAnalysis(String cluster);\n    \n    /**\n     * task任务分析\n     *\n     * @param cluster\n     * @return\n     */\n    Result<List<TaskMissionAnalysisVO>> taskMissionAnalysis(String cluster);\n    \n    /**\n     * 热点线程分析\n     *\n     * @param cluster\n     * @return\n     */\n    Result<String> hotThreadAnalysis(String cluster);\n    \n    /**\n     * shard分配说明\n     *\n     * @param cluster\n     * @return\n     */\n    Result<ShardAssignmentDescriptionVO> shardAssignmentDescription(String cluster);\n    \n    /**\n     * 异常shard分配重试\n     *\n     * @param cluster\n     * @return\n     */\n    Result<Void> abnormalShardAllocationRetry(String cluster);\n    \n    /**\n     * 清除fielddata内存\n     *\n     * @param cluster\n     * @return\n     */\n    Result<Void> clearFieldDataMemory(String cluster);\n    \n    /**\n     * 条件获取索引列表信息 ,携带可读可写标志位\n     *\n     * @param condition 查询条件\n     * @param projectId 项目\n     * @return IndicesDistributionVO\n     */\n    List<IndicesDistributionVO> indicesDistributionPage(ClusterPhyQuickCommandIndicesQueryDTO condition,\n                                                                    Integer projectId) throws NotFindSubclassException;\n    \n    /**\n     * 条件获取shard列表信息 ,携带可读可写标志位\n     *\n     * @param condition 查询条件\n     * @param projectId 项目\n     * @return ShardDistributionVO\n     */\n    List<ShardDistributionVO> shardDistributionPage(ClusterPhyQuickCommandShardsQueryDTO condition,\n                                                                Integer projectId) throws ESOperateException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ClusterPluginManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.PluginDTO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\n\npublic interface ClusterPluginManager {\n\n    /**\n     * 上传插件，涉及ES能力插件和平台能力插件\n     *\n     * @param plugin    插件信息\n     * @param projectId\n     * @return result\n     */\n    Result<Long> addPlugins(PluginDTO plugin, Integer projectId) throws NotFindSubclassException;\n\n    /**\n     * 删除指定的插件\n     *\n     * @param id        插件id\n     * @param operator  操作人员\n     * @param projectId\n     * @return result\n     */\n    Result<Long> deletePluginById(Long id, String operator, Integer projectId) throws NotFindSubclassException;\n\n    /**\n     * 编辑插件的描述信息\n     *\n     * @param pluginDTO 插件信息\n     * @param operator  操作人员\n     * @param projectId\n     * @return result\n     */\n    Result<Void> editPluginDesc(PluginDTO pluginDTO, String operator, Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ClusterRegionManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicSpecCondition;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterWithRegionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterRegionVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterRegionWithNodeInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport java.util.List;\n\npublic interface ClusterRegionManager {\n\n    /**\n     * 构建regionVO\n     * @param regions region列表\n     * @return\n     */\n    List<ClusterRegionVO> buildLogicClusterRegionVO(List<ClusterRegion> regions);\n\n    /**\n     * 根据逻辑集群的类型筛选出可以绑定的region信息，返回的region列表中不包含cold region\n     * @param clusterLogicType 逻辑集群类型\n     * @param phyCluster 物理集群名称\n     * @return 筛选后的region列表\n     */\n    @Deprecated\n    Result<List<ClusterRegionVO>> listPhyClusterRegionsByLogicClusterTypeAndCluster(String phyCluster,\n                                                                                    Integer clusterLogicType);\n\n    /**\n     * 逻辑集群绑定同一个物理集群的region的时候需要根据类型进行过滤，之后再根据cold、region节点数量、节点规格进行过滤\n     * @param phyCluster 物理集群名称\n     * @param clusterLogicType 逻辑集群类型\n     * @param condition 用户侧申请的集群规格（节点数量、机器规格）\n     * @return\n     */\n    Result<List<ClusterRegionVO>> listPhyClusterRegionsByCondition(String phyCluster,\n                                                                   Integer clusterLogicType,\n                                                                   ClusterLogicSpecCondition condition);\n\n    /**\n     * 构建regionVO\n     * @param region region\n     * @return\n     */\n    ClusterRegionVO buildLogicClusterRegionVO(ClusterRegion region);\n\n    /**\n     * 逻辑集群批量绑定region\n     *\n     * @param isAddClusterLogicFlag 是否要添加逻辑集群\n     */\n    Result<Void> batchBindRegionToClusterLogic(ESLogicClusterWithRegionDTO param, String operator,\n                                               boolean isAddClusterLogicFlag) throws AdminOperateException;\n\n    /**\n     * 根据物理集群名称获region信息（包含空节点region），包含region中的数据节点信息\n     * @param clusterName          物理集群名称\n     * @return                     Result<List<ClusterRegionWithNodeInfoVO>>\n     */\n    Result<List<ClusterRegionWithNodeInfoVO>> listClusterRegionWithNodeInfoByClusterName(String clusterName);\n\n    /**\n     * 获取可分配至dcdr的物理集群名称获region列表, 不包含空节点region\n     *\n     * @param clusterName         物理集群名称\n     * @return                    Result<List<ClusterRegionVO>>\n     */\n    Result<List<ClusterRegionVO>> listNotEmptyClusterRegionByClusterName(String clusterName);\n\n    /**\n     * 删除物理集群region\n     * @param regionId\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Void> deletePhyClusterRegion(Long regionId, String operator, Integer projectId) throws AdminOperateException;\n\n    \n    /**\n     * 通过物理集群获取冷region\n     *\n     * @param phyCluster 物理集群名称\n     * @return ClusterRegion 对象列表\n     */\n    List<ClusterRegion> getColdRegionByPhyCluster(String phyCluster);\n    /**\n     * 列出物理集群的所有region\n     *\n     * @param phyCluster 物理集群名称\n     * @return ClusterRegion 对象列表\n     */\n    List<ClusterRegion> listRegionByPhyCluster(String phyCluster);\n    \n    /**\n     * > 通过逻辑集群 id 构建逻辑集群region vo\n     *\n     * @param logicClusterId 逻辑集群 ID\n     * @return 列表<ClusterRegionVO>\n     */\n    Result<List<ClusterRegionVO>> buildLogicClusterRegionVOByLogicClusterId(Long logicClusterId);\n    \n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ESClusterConfigManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm.ESConfigVO;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * esclusterconfig\n *\n * @author shizeying\n * @date 2022/07/11\n */\npublic interface ESClusterConfigManager {\n    /**\n     * 编辑configdesc\n     *\n     * @param param     入参\n     * @param operator  操作人或角色\n     * @param projectId 项目id\n     * @return {@code Result<Void>}\n     */\n    Result<Void> editConfigDesc(ESConfigDTO param, String operator, Integer projectId);\n\n    /**\n     * 获取ES集群模板config\n     *\n     * @param type 类型\n     * @return {@code Result<ESConfigVO>}\n     */\n    Result<ESConfigVO> getEsClusterTemplateConfig(String type);\n\n    Result<Set<String>> gainEsClusterRoles(Long clusterId);\n\n    /**\n     * 获取ES集群config通过id\n     *\n     * @param configId configid\n     * @return {@code Result<ESConfigVO>}\n     */\n    Result<ESConfigVO> getEsClusterConfigById(Long configId);\n\n    /**\n     * 获得ES集群配置\n     *\n     * @param clusterId 集群id\n     * @return {@code Result<List<ESConfigVO>>}\n     */\n    Result<List<ESConfigVO>> gainEsClusterConfigs(Long clusterId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/impl/ClusterContextManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.EXCLUSIVE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.PRIVATE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.PUBLIC;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.UNKNOWN;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.DATA_NODE;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterContextManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogicContext;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhyContext;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.threadpool.AriusScheduleThreadPool;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.jetbrains.annotations.NotNull;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * 集群上下文类, 包含以下信息:\n * 1. 包括逻辑集群（共享、独享、独占）关联的物理集群信息（region、node、project消息等）\n * 2. 物理集群信息关联逻辑集群（共享、独享、独占）信息\n * 3. 校验模型 ————> 获取逻辑集群可绑定的物理集群列表\n *\n * Created by linyunan on 2021-06-08\n */\n@Component\npublic class ClusterContextManagerImpl implements ClusterContextManager {\n    private static final ILog                    LOGGER                          = LogFactory\n        .getLog(ClusterContextManagerImpl.class);\n\n    /**\n     * key-> 逻辑集群Id\n     */\n    private final Map<Long, ClusterLogicContext> id2ClusterLogicContextMap       = Maps.newConcurrentMap();\n\n    /**\n     * key-> 物理集群名称, value 上下文信息\n     */\n    private final Map<String, ClusterPhyContext> name2ClusterPhyContextMap       = Maps.newConcurrentMap();\n\n    private static final Integer                 LOGIC_ASSOCIATED_PHY_MAX_NUMBER = 2 << 9;\n\n    private static final Integer                 PHY_ASSOCIATED_LOGIC_MAX_NUMBER = 2 << 9;\n\n    @Autowired\n    private ClusterLogicService                  clusterLogicService;\n\n    @Autowired\n    private ClusterPhyService                    clusterPhyService;\n\n    @Autowired\n    private ClusterRegionService                 clusterRegionService;\n\n    @Autowired\n    private ClusterRoleHostService               clusterRoleHostService;\n\n    @Autowired\n    private AriusScheduleThreadPool              ariusScheduleThreadPool;\n\n    @Autowired\n    private ProjectService                       projectService;\n\n    @PostConstruct\n    private void init() {\n        ariusScheduleThreadPool.submitScheduleAtFixedDelayTask(this::flushClusterLogicContexts, 60, 120);\n        ariusScheduleThreadPool.submitScheduleAtFixedDelayTask(this::flushClusterPhyContexts, 120, 120);\n    }\n\n    @Override\n    public ClusterPhyContext flushClusterPhyContext(String clusterPhyName) {\n        try {\n            ClusterPhyContext clusterPhyContext = getClusterPhyContext(clusterPhyName);\n            if (null != clusterPhyContext) {\n                name2ClusterPhyContextMap.put(clusterPhyContext.getClusterName(), clusterPhyContext);\n                return clusterPhyContext;\n            }\n        } catch (Exception e) {\n            Thread.currentThread().interrupt();\n            LOGGER.error(\"class=ClusterContextManagerImpl||method=flushClusterPhyContext||clusterPhyName={}||errMsg={}\",\n                clusterPhyName, e.getMessage(), e);\n        }\n\n        return null;\n    }\n\n    @Override\n    public ClusterLogicContext flushClusterLogicContext(Long clusterLogicId) {\n        try {\n            ClusterLogicContext clusterLogicContext = getClusterLogicContext(clusterLogicId);\n            if (null != clusterLogicContext) {\n                id2ClusterLogicContextMap.put(clusterLogicContext.getClusterLogicId(), clusterLogicContext);\n                return clusterLogicContext;\n            }\n\n        } catch (Exception e) {\n            Thread.currentThread().interrupt();\n            LOGGER.error(\n                \"class=ClusterContextManagerImpl||method=flushClusterLogicContext||clusterLogicId={}||errMsg={}\",\n                clusterLogicId, e.getMessage(), e);\n\n        }\n\n        return null;\n    }\n\n    @Override\n    public void flushClusterContextByClusterRegion(ClusterRegion clusterRegion) {\n        if (null == clusterRegion) {\n            return;\n        }\n\n        flushClusterPhyContext(clusterRegion.getPhyClusterName());\n\n        // 一个物理集群可以关联多个逻辑集群\n        List<Long> logicClusterIds = ListUtils.string2LongList(clusterRegion.getLogicClusterIds());\n        if (!CollectionUtils.isEmpty(logicClusterIds)) {\n            logicClusterIds.forEach(this::flushClusterLogicContext);\n        }\n    }\n\n    @Override\n    public Result<Boolean> canClusterLogicAssociatedPhyCluster(Long clusterLogicId, String clusterPhyName,\n                                                               Long regionId, Integer clusterLogicType) {\n        //新建时clusterLogicId为空, 防止NPE\n        if (AriusObjUtils.isNull(clusterLogicId)) {\n            clusterLogicId = -1L;\n        }\n\n        ClusterLogicContext clusterLogicContext = getClusterLogicContext(clusterLogicId);\n        ClusterPhyContext clusterPhyContext = getClusterPhyContext(clusterPhyName);\n\n        int associatedPhyNum = 0;\n        int associatedLogicNum = 0;\n        if (null != clusterLogicContext) {\n            associatedPhyNum = clusterLogicContext.getAssociatedPhyNum();\n        }\n        if (null != clusterPhyContext) {\n            associatedLogicNum = clusterPhyContext.getAssociatedLogicNum();\n        }\n\n        return doValid(associatedPhyNum, associatedLogicNum, clusterLogicId, clusterPhyName, regionId,\n            clusterLogicType);\n    }\n\n    /**\n     *   1. Type为独立, LP = 1, PL = 1\n     *   2. Type为共享, LP = n, PL = 1\n     * \t 3. Type为独享, LP = n, PL = 1\n     */\n    @Override\n    public Result<List<String>> getCanBeAssociatedClustersPhys(Integer clusterLogicType, Long clusterLogicId) {\n        if (!ClusterResourceTypeEnum.isExist(clusterLogicType)) {\n            return Result.buildParamIllegal(\"逻辑集群类型非法\");\n        }\n\n        List<String> canBeAssociatedClustersPhyNames = Lists.newArrayList();\n\n        if (PRIVATE.getCode() == clusterLogicType) {\n            handleClusterLogicTypePrivate(clusterLogicId, canBeAssociatedClustersPhyNames);\n        }\n\n        if (PUBLIC.getCode() == clusterLogicType) {\n            handleClusterLogicTypePublic(clusterLogicId, canBeAssociatedClustersPhyNames);\n        }\n\n        if (EXCLUSIVE.getCode() == clusterLogicType) {\n            handleClusterLogicTypeExclusive(clusterLogicId, canBeAssociatedClustersPhyNames);\n        }\n\n        return Result.buildSucc(canBeAssociatedClustersPhyNames);\n    }\n\n    @Override\n    public List<String> getClusterPhyAssociatedClusterLogicNames(String clusterPhyName) {\n        ClusterPhyContext clusterPhyContext = getClusterPhyContext(clusterPhyName);\n        if (null == clusterPhyContext) {\n            return Lists.newArrayList();\n        }\n\n        List<Long> clusterLogicIds = clusterPhyContext.getAssociatedClusterLogicIds();\n        if (CollectionUtils.isEmpty(clusterLogicIds)) {\n            return Lists.newArrayList();\n        }\n\n        return clusterLogicIds.stream().map(r -> clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(r ))\n                .map(ClusterLogic::getName)\n            .distinct().collect(Collectors.toList());\n    }\n\n    @Override\n    public ClusterPhyContext getClusterPhyContext(String clusterPhyName) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterPhyName);\n        if (null == clusterPhy) {\n            LOGGER.error(\n                \"class=ClusterContextManagerImpl||method=flushClusterPhyContext||clusterPhyName={}||msg=clusterPhy is empty\",\n                clusterPhyName);\n            return null;\n        }\n\n        ClusterPhyContext build = ClusterPhyContext.builder().clusterPhyId(clusterPhy.getId().longValue())\n            .clusterName(clusterPhy.getCluster()).associatedLogicNumMax(PHY_ASSOCIATED_LOGIC_MAX_NUMBER).build();\n\n        setClusterPhyNodeInfo(build);\n        setRegionAndClusterLogicInfoAndProjectId(build);\n        return build;\n    }\n\n    @Override\n    public ClusterPhyContext getClusterPhyContextCache(String cluster) {\n        return name2ClusterPhyContextMap.get(cluster);\n    }\n\n    @Override\n    public Map<String, ClusterPhyContext> listClusterPhyContextMap() {\n        return name2ClusterPhyContextMap;\n    }\n\n    @Override\n    public ClusterLogicContext getClusterLogicContextCache(Long clusterLogicId) {\n        return id2ClusterLogicContextMap.get(clusterLogicId);\n    }\n\n    @Override\n    public ClusterLogicContext getClusterLogicContext(Long clusterLogicId) {\n        ClusterLogic clusterLogic =\n                clusterLogicService.listClusterLogicByIdThatProjectIdStrConvertProjectIdList(clusterLogicId).stream().findFirst().orElse(null);\n        if (null == clusterLogic) {\n            LOGGER.error(\n                \"class=ClusterContextManagerImpl||method=flushClusterLogicContext||clusterLogicId={}||msg=clusterLogic is empty\",\n                clusterLogicId);\n            return null;\n        }\n\n        ClusterLogicContext build = buildInitESClusterLogicContextByType(clusterLogic);\n        setAssociatedClusterPhyInfo(build);\n        setRegionAndAssociatedClusterPhyDataNodeInfo(build);\n        return build;\n    }\n\n    /***********************************************private*********************************************/\n    public void flushClusterPhyContexts() {\n        LOGGER.info(\"class=ClusterContextManagerImpl||method=flushClusterPhyContexts||msg=start...\");\n        long currentTimeMillis = System.currentTimeMillis();\n        List<ClusterPhy> clusterPhyList = clusterPhyService.listAllClusters();\n        if (CollectionUtils.isEmpty(clusterPhyList)) {\n            LOGGER.info(\n                \"class=ClusterContextManagerImpl||method=flushClusterLogicContexts||msg=finish...||consumingTime={}\",\n                System.currentTimeMillis() - currentTimeMillis);\n            return;\n        }\n\n        // regionk信息按【cluster】分组\n        List<ClusterRegion> clusterRegionList = clusterRegionService.listAllBoundRegions();\n        Map<String/*phyClusterName*/, List<ClusterRegion>> phyClusterName2ClusterLogicRackListMap = ConvertUtil\n            .list2MapOfList(clusterRegionList, ClusterRegion::getPhyClusterName, clusterRegion -> clusterRegion);\n\n        // clusterLogic信息按主键分组\n        List<ClusterLogic> clusterLogicList = clusterLogicService.listAllClusterLogics();\n        Map<Long, ClusterLogic> id2ClusterLogicMap = ConvertUtil.list2Map(clusterLogicList, ClusterLogic::getId);\n\n        // host信息按【cluster】分组\n        List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService.listAllNode();\n        Map<String, List<ClusterRoleHost>> cluster2RoleListMap = ConvertUtil.list2MapOfList(clusterRoleHosts,\n            ClusterRoleHost::getCluster, clusterRoleHost -> clusterRoleHost);\n\n        // project信息分组\n        final List<ProjectBriefVO> briefVOS = projectService.getProjectBriefList();\n        Map<Integer/*projectId*/, String/*projectName*/> projectId2ProjectNameMap = ConvertUtil.list2Map(briefVOS,\n            ProjectBriefVO::getId, ProjectBriefVO::getProjectName);\n\n        for (ClusterPhy phy : clusterPhyList) {\n            // 初始化\n            ClusterPhyContext clusterPhyContext = ClusterPhyContext.builder().clusterPhyId(phy.getId().longValue())\n                .clusterName(phy.getCluster()).associatedLogicNumMax(PHY_ASSOCIATED_LOGIC_MAX_NUMBER).build();\n\n            List<ClusterRoleHost> hostList = cluster2RoleListMap.get(phy.getCluster());\n            if (CollectionUtils.isEmpty(hostList)) {\n                name2ClusterPhyContextMap.put(phy.getCluster(), clusterPhyContext);\n                continue;\n            }\n\n            // 设置物理集群管理的host信息, 这里暂时不去区分单机器多es实例的场景\n            List<ClusterRoleHost> dataNodes = hostList.stream()\n                .filter(r -> Objects.nonNull(r) && DATA_NODE.getCode() == r.getRole()).collect(Collectors.toList());\n\n            clusterPhyContext.setAssociatedDataNodeNum(dataNodes.size());\n            clusterPhyContext\n                .setAssociatedDataNodeIps(dataNodes.stream().map(ClusterRoleHost::getIp).collect(Collectors.toList()));\n            clusterPhyContext\n                .setAssociatedNodeIps(hostList.stream().map(ClusterRoleHost::getIp).collect(Collectors.toList()));\n\n            // 设置region信息\n            List<ClusterRegion> clusterRegions = phyClusterName2ClusterLogicRackListMap.get(phy.getCluster());\n            if (CollectionUtils.isEmpty(clusterRegions)) {\n                name2ClusterPhyContextMap.put(phy.getCluster(), clusterPhyContext);\n                continue;\n            }\n\n            clusterPhyContext\n                .setAssociatedRegionIds(clusterRegions.stream().map(ClusterRegion::getId).collect(Collectors.toList()));\n\n            // 设置关联逻辑集群信息\n            List<String> associatedClusterLogicIdsStr = clusterRegions.stream()\n                .filter(r -> Objects.nonNull(r)\n                             && !AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID.equals(r.getLogicClusterIds()))\n                .map(ClusterRegion::getLogicClusterIds).distinct().collect(Collectors.toList());\n            Set<Long> associatedClusterLogicIds = Sets.newHashSet();\n            for (String associatedClusterLogicIdStr : associatedClusterLogicIdsStr) {\n                associatedClusterLogicIds.addAll(ListUtils.string2LongList(associatedClusterLogicIdStr));\n            }\n            clusterPhyContext.setAssociatedClusterLogicIds(Lists.newArrayList(associatedClusterLogicIds));\n            clusterPhyContext.setAssociatedLogicNum(associatedClusterLogicIds.size());\n\n            // 设置project信息\n            Set<Integer> projectIdSet = Sets.newHashSet();\n            Set<String> projectNameSet = Sets.newHashSet();\n            for (Long associatedClusterLogicId : associatedClusterLogicIds) {\n                ClusterLogic clusterLogic = id2ClusterLogicMap.get(associatedClusterLogicId);\n                if (null == clusterLogic) {\n                    continue;\n                }\n                projectIdSet.add(clusterLogic.getProjectId());\n\n                String projectName = projectId2ProjectNameMap.get(clusterLogic.getProjectId());\n                if (AriusObjUtils.isBlack(projectName)) {\n                    continue;\n                }\n                projectNameSet.add(projectName);\n            }\n            clusterPhyContext.setAssociatedProjectIds(Lists.newArrayList(projectIdSet));\n            clusterPhyContext.setAssociatedProjectNames(Lists.newArrayList(projectNameSet));\n\n            name2ClusterPhyContextMap.put(phy.getCluster(), clusterPhyContext);\n        }\n        LOGGER.info(\"class=ClusterContextManagerImpl||method=flushClusterPhyContexts||msg=finish...||consumingTime={}\",\n            System.currentTimeMillis() - currentTimeMillis);\n    }\n\n    /**\n     * 刷新逻辑集群上下文，其中包括 关联的物理集群信息、 region信息、 host信息等\n     */\n    public void flushClusterLogicContexts() {\n        LOGGER.info(\"class=ClusterContextManagerImpl||method=flushClusterLogicContexts||msg=start...\");\n        long currentTimeMillis = System.currentTimeMillis();\n\n        List<ClusterLogic> clusterLogics = clusterLogicService.listAllClusterLogics();\n        if (CollectionUtils.isEmpty(clusterLogics)) {\n            LOGGER.info(\n                \"class=ClusterContextManagerImpl||method=flushClusterLogicContexts||msg=finish...||consumingTime={}\",\n                System.currentTimeMillis() - currentTimeMillis);\n            return;\n        }\n\n        // 获取全量逻辑集群绑定的Region信息\n        Map<Long, List<ClusterRegion>> clusterLogicId2ClusterLogicRackListMap = getClusterLogicId2ClusterRegionListMap();\n\n        // host信息按【regionId】分组\n        Map<Integer, List<ClusterRoleHost>> regionId2HostListMap = getRegionId2HostListMap();\n\n        for (ClusterLogic clusterLogic : clusterLogics) {\n            // 构建初始化上下文, 按照逻辑集群类型限制上下文信息数量\n            ClusterLogicContext clusterLogicContext = buildInitESClusterLogicContextByType(clusterLogic);\n\n            // 设置关联集群信息\n            List<ClusterRegion> clusterRegions = clusterLogicId2ClusterLogicRackListMap.get(clusterLogic.getId());\n            if (CollectionUtils.isEmpty(clusterRegions)) {\n                id2ClusterLogicContextMap.put(clusterLogic.getId(), clusterLogicContext);\n                continue;\n            }\n\n            List<String> associatedClusterPhyNameList = clusterRegions.stream().map(ClusterRegion::getPhyClusterName)\n                .distinct().collect(Collectors.toList());\n\n            clusterLogicContext.setAssociatedClusterPhyNames(associatedClusterPhyNameList);\n            clusterLogicContext.setAssociatedPhyNum(associatedClusterPhyNameList.size());\n            // 遇到异常数据，先简单去打印错误日志\n            if (clusterLogicContext.getAssociatedPhyNumMax() < associatedClusterPhyNameList.size()) {\n                LOGGER.error(\"class=ClusterContextManagerImpl||method=flushClusterLogicContexts\"\n                             + \"||logicClusterType={}||esClusterLogicId={}||msg=集群间关联超过最大限制数{}, 请纠正\",\n                    clusterLogicContext.getLogicClusterType(), clusterLogicContext.getClusterLogicId(),\n                    clusterLogicContext.getAssociatedPhyNumMax());\n            }\n\n            // 获取逻辑集群已关联的Region信息\n            clusterLogicContext\n                .setAssociatedRegionIds(clusterRegions.stream().map(ClusterRegion::getId).collect(Collectors.toList()));\n\n            // 获取逻辑集群关联region下的rack节点信息\n            List<ClusterRoleHost> associatedRegionDataNodeList = Lists.newArrayList();\n            for (ClusterRegion clusterRegion : clusterRegions) {\n                List<ClusterRoleHost> dataNodeList = regionId2HostListMap.get(clusterRegion.getId().intValue());\n                if (CollectionUtils.isEmpty(dataNodeList)) {\n                    continue;\n                }\n\n                associatedRegionDataNodeList.addAll(dataNodeList);\n            }\n\n            //设置数据节点总数\n            clusterLogicContext.setAssociatedDataNodeNum(associatedRegionDataNodeList.size());\n\n            //设置数据节点Ip地址\n            clusterLogicContext.setAssociatedDataNodeIps(\n                associatedRegionDataNodeList.stream().map(ClusterRoleHost::getIp).collect(Collectors.toList()));\n\n            id2ClusterLogicContextMap.put(clusterLogic.getId(), clusterLogicContext);\n        }\n\n        LOGGER.info(\n            \"class=ClusterContextManagerImpl||method=flushClusterLogicContexts||msg=finish...||consumingTime={}\",\n            System.currentTimeMillis() - currentTimeMillis);\n    }\n\n    /**\n     * 获取全量逻辑集群绑定的Region信息\n     * @return  key -> clusterLogicId   value -> List<ClusterRegion>\n     */\n    @NotNull\n    private Map<Long, List<ClusterRegion>> getClusterLogicId2ClusterRegionListMap() {\n        List<ClusterRegion> clusterRegionList = clusterRegionService.listAllBoundRegions();\n        Map<String/*clusterLogicIds 逗号分隔*/, List<ClusterRegion>> clusterLogicIds2ClusterRegionListMap = ConvertUtil\n            .list2MapOfList(clusterRegionList, ClusterRegion::getLogicClusterIds, region -> region);\n\n        // 按【逻辑集群Id】分组, 特殊处理table中clusterLogicIds列的数据\n        Map<Long/*clusterLogicId*/, List<ClusterRegion>> clusterLogicId2ClusterLogicRackListMap = Maps.newHashMap();\n        for (Map.Entry<String, List<ClusterRegion>> e : clusterLogicIds2ClusterRegionListMap.entrySet()) {\n            String key = e.getKey();\n            List<ClusterRegion> clusterRegions = e.getValue();\n            List<Long> clusterLogicIdList = ListUtils.string2LongList(key);\n            for (Long clusterLogicId : clusterLogicIdList) {\n                clusterLogicId2ClusterLogicRackListMap.put(clusterLogicId, clusterRegions);\n            }\n        }\n        return clusterLogicId2ClusterLogicRackListMap;\n    }\n\n    /**\n     * host信息按【regionId】分组\n     * @return key -> regionId  value -> List<RoleClusterHost>\n     */\n    @NotNull\n    private Map<Integer, List<ClusterRoleHost>> getRegionId2HostListMap() {\n        List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService.listAllNodeByRole(DATA_NODE.getCode());\n        if (CollectionUtils.isEmpty(clusterRoleHosts)) {\n            return Maps.newHashMap();\n        }\n        return ConvertUtil.list2MapOfList(clusterRoleHosts, ClusterRoleHost::getRegionId, node -> node);\n    }\n\n    /**\n     *   定义规则:\n     *   1. Type为独立, LP = 1, PL = 1\n     *   2. Type为共享, LP = n, PL = 1 ,  1 <= n <= 1024   多个逻辑集群共享一个物理集群, 每个逻辑集群关联物理集群一部分region,不可跨其他物理集群，\n     *                                                    多个逻辑集群可关联同一部分region。\n     *   3. Type为独占, LP = 1, PL = n ,  1 <= n <= 1024   一个逻辑集群独占一个或者多个物理集群\n     */\n    private ClusterLogicContext buildInitESClusterLogicContextByType(ClusterLogic clusterLogic) {\n\n        if (PRIVATE.getCode() == clusterLogic.getType() || EXCLUSIVE.getCode() == clusterLogic.getType()) {\n            return ClusterLogicContext.builder().clusterLogicName(clusterLogic.getName())\n                .clusterLogicId(clusterLogic.getId()).logicClusterType(clusterLogic.getType()).associatedPhyNumMax(1)\n                .build();\n        } else if (PUBLIC.getCode() == clusterLogic.getType()) {\n            return ClusterLogicContext.builder().clusterLogicName(clusterLogic.getName())\n                .clusterLogicId(clusterLogic.getId()).logicClusterType(clusterLogic.getType())\n                .associatedPhyNumMax(LOGIC_ASSOCIATED_PHY_MAX_NUMBER).build();\n        } else {\n            LOGGER.error(\n                \"class=ClusterContextManagerImpl||method=buildInitESClusterLogicContextByType||esClusterLogicId={}||msg={}\",\n                clusterLogic.getId(), String.format(\"请确认逻辑集群%s类型是否存在\", clusterLogic.getType()));\n\n            return ClusterLogicContext.builder().clusterLogicName(clusterLogic.getName())\n                .clusterLogicId(clusterLogic.getId()).logicClusterType(clusterLogic.getType()).associatedPhyNumMax(-1)\n                .build();\n        }\n    }\n\n    private void setAssociatedClusterPhyInfo(ClusterLogicContext build) {\n        List<String> clusterPhyNames = clusterRegionService.listPhysicClusterNames(build.getClusterLogicId());\n        if (build.getAssociatedPhyNumMax() < clusterPhyNames.size()) {\n            LOGGER.error(\"class=ClusterContextManagerImpl||method=setAssociatedClusterPhyInfo\"\n                         + \"||logicClusterType={}||esClusterLogicId={}||msg=集群间关联超过最大限制数{}, 请纠正\",\n                build.getLogicClusterType(), build.getClusterLogicId(), build.getAssociatedPhyNumMax());\n            return;\n        }\n\n        build.setAssociatedClusterPhyNames(clusterPhyNames);\n        build.setAssociatedPhyNum(clusterPhyNames.size());\n    }\n\n    private void setRegionAndAssociatedClusterPhyDataNodeInfo(ClusterLogicContext build) {\n        //获取逻辑集群已关联的Region信息\n        List<ClusterRegion> regions = clusterRegionService.getClusterRegionsByLogicIds(Collections.singletonList(build.getClusterLogicId()));\n        build.setAssociatedRegionIds(regions.stream().map(ClusterRegion::getId).collect(Collectors.toList()));\n\n        //获取逻辑集群关联region下的rack节点信息\n        List<ClusterRoleHost> associatedRackClusterHosts = Lists.newArrayList();\n        for (ClusterRegion region : regions) {\n            Result<List<ClusterRoleHost>> regionDataNodeListRet = clusterRoleHostService\n                .listByRegionId(region.getId().intValue());\n            if (regionDataNodeListRet.failed()) {\n                LOGGER.warn(\n                    \"class=ClusterContextManagerImpl||method=setRegionAndAssociatedClusterPhyDataNodeInfo||regionId={}||msg=failed to get regionDataNodeList:{}\",\n                    region.getId(), regionDataNodeListRet.getMessage());\n                continue;\n            }\n            associatedRackClusterHosts.addAll(regionDataNodeListRet.getData());\n        }\n\n        //设置数据节点总数\n        build.setAssociatedDataNodeNum(associatedRackClusterHosts.size());\n\n        //设置数据节点Ip地址\n        build.setAssociatedDataNodeIps(\n            associatedRackClusterHosts.stream().map(ClusterRoleHost::getIp).collect(Collectors.toList()));\n    }\n\n    private void setRegionAndClusterLogicInfoAndProjectId(ClusterPhyContext build) {\n        // 1. set region\n        List<ClusterRegion> regions = clusterRegionService.listPhyClusterRegions(build.getClusterName());\n        build.setAssociatedRegionIds(regions.stream().map(ClusterRegion::getId).collect(Collectors.toList()));\n\n        // 2. set ClusterLogicInfo\n        Set<Long> associatedClusterLogicIds = Sets.newHashSet();\n        for (ClusterRegion clusterRegion : regions) {\n            // 添加每一个物理集群下每一个region所被绑定的逻辑集群\n            List<Long> logicClusterIds = ListUtils.string2LongList(clusterRegion.getLogicClusterIds());\n            if (!CollectionUtils.isEmpty(logicClusterIds)\n                && !logicClusterIds.contains(Long.parseLong(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID))) {\n                associatedClusterLogicIds.addAll(logicClusterIds);\n            }\n        }\n\n        build.setAssociatedClusterLogicIds(Lists.newArrayList(associatedClusterLogicIds));\n        build.setAssociatedLogicNum(associatedClusterLogicIds.size());\n\n        // 3. set projectId\n        Set<Integer> projectIdSet = new HashSet<>();\n        Set<String> clusterLogicSet = new HashSet<>();\n        if (!CollectionUtils.isEmpty(associatedClusterLogicIds)) {\n            for (Long associatedClusterLogicId : associatedClusterLogicIds) {\n                clusterLogicService.listClusterLogicByIdThatProjectIdStrConvertProjectIdList(associatedClusterLogicId).stream().filter(Objects::nonNull)\n                        .filter(clusterLogic -> null != clusterLogic.getProjectId() && null != clusterLogic.getName())\n                        .forEach(clusterLogic -> {\n                            projectIdSet.add(clusterLogic.getProjectId());\n                            clusterLogicSet.add(clusterLogic.getName());\n                        });\n                \n            }\n        }\n\n        build.setAssociatedProjectIds(Lists.newArrayList(projectIdSet));\n        build.setAssociatedProjectNames(Lists.newArrayList(clusterLogicSet));\n    }\n\n    private void setClusterPhyNodeInfo(ClusterPhyContext build) {\n        List<ClusterRoleHost> nodes = clusterRoleHostService.getNodesByCluster(build.getClusterName());\n        List<ClusterRoleHost> dataNodes = nodes.stream().filter(r -> DATA_NODE.getCode() == r.getRole())\n            .collect(Collectors.toList());\n\n        build.setAssociatedDataNodeNum(dataNodes.size());\n        build.setAssociatedDataNodeIps(dataNodes.stream().map(ClusterRoleHost::getIp).collect(Collectors.toList()));\n        build.setAssociatedNodeIps(nodes.stream().map(ClusterRoleHost::getIp).collect(Collectors.toList()));\n    }\n\n    /**\n     * 具体校验逻辑\n     * @param associatedPhyNumber    逻辑集群关联物理集群个数\n     * @param associatedLogicNumber  物理集群关联逻辑集群个数\n     * @param regionId               需要绑定的regionId\n     * @param clusterLogicType       逻辑集群类型\n     */\n    private Result<Boolean> doValid(int associatedPhyNumber, int associatedLogicNumber, Long clusterLogicId,\n                                    String clusterPhyName, Long regionId, Integer clusterLogicType) {\n\n        if (AriusObjUtils.isNull(clusterLogicType)) {\n            return Result.buildParamIllegal(\"逻辑集群类型为空\");\n        }\n\n        if (UNKNOWN.getCode() == ClusterResourceTypeEnum.valueOf(clusterLogicType).getCode()) {\n            return Result.buildParamIllegal(\"无法识别逻辑集群类型\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterPhyName);\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildFail(\"物理集群不存在\");\n        }\n\n        if (PRIVATE.getCode() == clusterLogicType\n            && !canClusterLogicBoundRegion(regionId, clusterPhyName, clusterLogicId)) {\n            //先判断logic -> phy, 二次关联region需要先校验逻辑集群对应的物理集群数据是否合理\n            if (associatedPhyNumber > 0) {\n                return Result.buildParamIllegal(String.format(\"集群间关联失败 ,该独立逻辑集群%s已有关联物理集群\", clusterLogicId));\n            }\n            //在判断phy -> logic\n            if (associatedLogicNumber > 0) {\n                return Result.buildFail(String.format(\"集群间关联失败, 物理集群%s已有关联逻辑集群\", clusterPhyName));\n            }\n        }\n\n        return Result.buildSucc(Boolean.TRUE);\n    }\n\n    /**\n     * 判断指定的物理集群下的region是否被对应的逻辑集群绑定\n     * @param regionId regionId\n     * @param clusterPhyName 物理集群名称\n     * @param clusterLogicId 逻辑集群id\n     * @return  true of false\n     */\n    private boolean canClusterLogicBoundRegion(Long regionId, String clusterPhyName, Long clusterLogicId) {\n        ClusterRegion region = clusterRegionService.getRegionById(regionId);\n        ClusterPhyContext clusterPhyContext = getClusterPhyContext(clusterPhyName);\n        List<Long> clusterLogicIds = clusterPhyContext.getAssociatedClusterLogicIds();\n        if (CollectionUtils.isNotEmpty(clusterLogicIds) && !clusterLogicIds.contains(clusterLogicId)) {\n            return false;\n        }\n\n        if (!region.getLogicClusterIds().equals(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID)) {\n            return false;\n        }\n\n        return region.getPhyClusterName().equals(clusterPhyName);\n    }\n\n    /**\n     * LP = 1 , PL = 1\n     * @param clusterLogicId    逻辑集群Id\n     * @param clusterPhyContext 物理集群上下文\n     * @return                  true/false\n     */\n    private boolean checkForPrivate(Long clusterLogicId, ClusterPhyContext clusterPhyContext) {\n        //采集测associatedLogicNumber 会存在null问题\n        if (null == clusterPhyContext.getAssociatedLogicNum()) {\n            return true;\n        }\n        if (null == clusterLogicId) {\n            if (0 == clusterPhyContext.getAssociatedLogicNum()) {\n                return true;\n            } else if (clusterPhyContext.getAssociatedLogicNum() >= 1) {\n                return false;\n            }\n\n            return false;\n        } else {\n            ClusterLogicContext clusterLogicContext = getClusterLogicContext(clusterLogicId);\n            if (0 == clusterLogicContext.getAssociatedPhyNum() && 0 == clusterPhyContext.getAssociatedLogicNum()) {\n                return true;\n            } else {\n                return 1 == clusterLogicContext.getAssociatedPhyNum() && clusterLogicContext\n                    .getAssociatedClusterPhyNames().contains(clusterPhyContext.getClusterName());\n            }\n        }\n    }\n\n    /**\n     * 校验当前的物理集群可否被指定的共享类型的逻辑集群关联\n     * @param clusterLogicId    逻辑集群Id\n     * @param clusterPhyContext 物理集群上下文\n     * @return                  true/false\n     */\n    private boolean checkForPublic(Long clusterLogicId, ClusterPhyContext clusterPhyContext) {\n        //采集测associatedLogicNumber 会存在null问题\n        if (null == clusterPhyContext.getAssociatedLogicNum()) {\n            return true;\n        }\n        if (null == clusterLogicId) {\n            if (0 == clusterPhyContext.getAssociatedLogicNum()) {\n                return true;\n            } else {\n                return !hasClusterPhyContextAssociatedLogicTypeIsCode(clusterPhyContext, PRIVATE.getCode());\n            }\n        } else {\n            ClusterLogicContext clusterLogicContext = id2ClusterLogicContextMap.get(clusterLogicId);\n            //不允许一个逻辑集群绑定多个物理集群\n            if (1 < clusterLogicContext.getAssociatedPhyNum()) {\n                return false;\n            }\n\n            //逻辑集群绑定物理集群数为0 且 物理集群无逻辑集群绑定\n            if (0 == clusterLogicContext.getAssociatedPhyNum() && 0 == clusterPhyContext.getAssociatedLogicNum()) {\n                return true;\n            } else {\n                return clusterLogicContext.getAssociatedPhyNum() == 1\n                       && hasBelongClusterLogicContextAssociatedClusterNames(clusterLogicContext,\n                           clusterPhyContext.getClusterName())\n                       || clusterPhyContext.getAssociatedLogicNum() > 0\n                          && !hasClusterPhyContextAssociatedLogicTypeIsCode(clusterPhyContext, PRIVATE.getCode());\n            }\n        }\n    }\n\n    /**\n     * 校验当前的物理集群可否被指定的独享类型的逻辑集群关联\n     * @param clusterLogicId    逻辑集群Id\n     * @param clusterPhyContext 物理集群上下文\n     * @return                  true/false\n     */\n    private boolean checkForExclusive(Long clusterLogicId, ClusterPhyContext clusterPhyContext) {\n        //采集测associatedLogicNumber 会存在null问题\n        if (null == clusterPhyContext.getAssociatedLogicNum()) {\n            return true;\n        }\n        if (null == clusterLogicId) {\n            if (0 == clusterPhyContext.getAssociatedLogicNum()) {\n                return true;\n            } else {\n                return !hasClusterPhyContextAssociatedLogicTypeIsCode(clusterPhyContext, PRIVATE.getCode());\n            }\n        } else {\n            ClusterLogicContext clusterLogicContext = id2ClusterLogicContextMap.get(clusterLogicId);\n            //不允许一个逻辑集群绑定多个物理集群\n            if (1 < clusterLogicContext.getAssociatedPhyNum()) {\n                return false;\n            }\n\n            //逻辑集群绑定物理集群数为0 且 物理集群无逻辑集群绑定\n            if (0 == clusterLogicContext.getAssociatedPhyNum() && 0 == clusterPhyContext.getAssociatedLogicNum()) {\n                return true;\n            } else {\n                return clusterLogicContext.getAssociatedPhyNum() == 1\n                       && hasBelongClusterLogicContextAssociatedClusterNames(clusterLogicContext,\n                           clusterPhyContext.getClusterName())\n                       || clusterPhyContext.getAssociatedLogicNum() > 0\n                          && !hasClusterPhyContextAssociatedLogicTypeIsCode(clusterPhyContext, PRIVATE.getCode());\n            }\n        }\n    }\n\n    /**\n     * 物理集群上下文中的逻辑集群类型是否全为传入类型\n     * @param clusterPhyContext  物理集群上下文\n     * @param code               逻辑集群类型\n     * @return                   true/false\n     */\n    private boolean hasClusterPhyContextAssociatedLogicTypeIsCode(ClusterPhyContext clusterPhyContext, int code) {\n        Set<Integer> typeSet = clusterPhyContext.getAssociatedClusterLogicIds().stream()\n            .map(this::getClusterLogicContext).map(ClusterLogicContext::getLogicClusterType)\n            .collect(Collectors.toSet());\n\n        return 1 == typeSet.size() && typeSet.contains(code);\n    }\n\n    /**\n     * 逻辑集群上下文中是否包含此物理集群\n     * @param clusterLogicContext  逻辑集群上下文\n     * @param clusterName          物理集群名称\n     * @return                     true/false\n     */\n    private boolean hasBelongClusterLogicContextAssociatedClusterNames(ClusterLogicContext clusterLogicContext,\n                                                                       String clusterName) {\n        return clusterLogicContext.getAssociatedClusterPhyNames().contains(clusterName);\n    }\n\n    private void handleClusterLogicTypeExclusive(Long clusterLogicId, List<String> canBeAssociatedClustersPhyNames) {\n        if (hasClusterLogicContextMapEmpty()) {\n            return;\n        }\n        if (hasClusterPhyContextMapEmpty()) {\n            return;\n        }\n\n        for (ClusterPhyContext clusterPhyContext : name2ClusterPhyContextMap.values()) {\n            if (checkForExclusive(clusterLogicId, clusterPhyContext)) {\n                canBeAssociatedClustersPhyNames.add(clusterPhyContext.getClusterName());\n            }\n        }\n    }\n\n    private void handleClusterLogicTypePublic(Long clusterLogicId, List<String> canBeAssociatedClustersPhyNames) {\n        if (hasClusterLogicContextMapEmpty()) {\n            return;\n        }\n        if (hasClusterPhyContextMapEmpty()) {\n            return;\n        }\n\n        for (ClusterPhyContext clusterPhyContext : name2ClusterPhyContextMap.values()) {\n            if (checkForPublic(clusterLogicId, clusterPhyContext)) {\n                canBeAssociatedClustersPhyNames.add(clusterPhyContext.getClusterName());\n            }\n        }\n    }\n\n    private void handleClusterLogicTypePrivate(Long clusterLogicId, List<String> canBeAssociatedClustersPhyNames) {\n        if (hasClusterLogicContextMapEmpty()) {\n            return;\n        }\n        if (hasClusterPhyContextMapEmpty()) {\n            return;\n        }\n\n        for (ClusterPhyContext clusterPhyContext : name2ClusterPhyContextMap.values()) {\n            if (checkForPrivate(clusterLogicId, clusterPhyContext)) {\n                canBeAssociatedClustersPhyNames.add(clusterPhyContext.getClusterName());\n            }\n        }\n    }\n\n    private boolean hasClusterPhyContextMapEmpty() {\n        return name2ClusterPhyContextMap.isEmpty();\n    }\n\n    private boolean hasClusterLogicContextMapEmpty() {\n        return id2ClusterLogicContextMap.isEmpty();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/impl/ClusterIndexManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterIndexManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName ClusterIndexManagerImpl\n * @Author gyp\n * @Date 2022/6/13\n * @Version 1.0\n */\n@Component\npublic class ClusterIndexManagerImpl implements ClusterIndexManager {\n    @Autowired\n    private ClusterLogicService     clusterLogicService;\n\n    @Autowired\n    private ClusterRegionService    clusterRegionService;\n\n    @Autowired\n    private ClusterRoleHostService  clusterRoleHostService;\n\n   \n\n    @Autowired\n    private IndexTemplatePhyService indexTemplatePhyService;\n\n    @Override\n    public Result<List<ESClusterRoleHostVO>> listClusterLogicIndices(Integer clusterId, Integer projectId) {\n        ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdAndProjectId(Long.valueOf(clusterId), projectId);\n        if (AriusObjUtils.isNull(clusterLogic)) {\n            return Result.buildFail(String.format(\"集群[%s]不存在\", clusterId));\n        }\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogic.getId());\n        Result<List<ClusterRoleHost>> result = clusterRoleHostService\n            .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n\n        Result<List<IndexTemplatePhy>> indexTemplatePhy = indexTemplatePhyService\n            .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n        if (indexTemplatePhy.failed()) {\n            return Result.buildFail(indexTemplatePhy.getMessage());\n        }\n\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/impl/ClusterLogicManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum.CLUSTER_LOGIC;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum.*;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.DATA_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.util.SizeUtil.getUnitSize;\n\nimport java.util.*;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.ElasticsearchTimeoutException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.transaction.interceptor.TransactionAspectSupport;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterLogicManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterNodeManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterRegionManager;\nimport com.didichuxing.datachannel.arius.admin.biz.page.ClusterLogicPageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.common.Triple;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionWithNodeInfoDTO.ClusterRegionWithNodeInfoDTOBuilder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterWithRegionDTO.ESLogicClusterWithRegionDTOBuilder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateClearDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogicStatis;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESMachineNormsPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm.ESClusterNodeSepcVO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.resource.ClusterLogicEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESMachineNormsService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectClusterLogicAuthService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESGatewayClient;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.ElasticsearchTimeoutException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.transaction.interceptor.TransactionAspectSupport;\n\n@Component\npublic class ClusterLogicManagerImpl implements ClusterLogicManager {\n\n    private static final ILog              LOGGER       = LogFactory.getLog(ClusterLogicManagerImpl.class);\n\n    @Autowired\n    private ESIndexService                 esIndexService;\n\n    @Autowired\n    private ClusterPhyService              clusterPhyService;\n\n    @Autowired\n    private ClusterLogicService            clusterLogicService;\n\n    @Autowired\n    private ClusterRegionService           clusterRegionService;\n\n    @Autowired\n    private ClusterRoleHostService         clusterRoleHostService;\n\n    @Autowired\n    private IndexTemplateService           indexTemplateService;\n\n\n    @Autowired\n    private IndexTemplatePhyService        indexTemplatePhyService;\n\n    @Autowired\n    private ProjectClusterLogicAuthService projectClusterLogicAuthService;\n\n    @Autowired\n    private OperateRecordService           operateRecordService;\n\n    @Autowired\n    private ESMachineNormsService          esMachineNormsService;\n\n    @Autowired\n    private ProjectService                 projectService;\n\n    @Autowired\n    private ESGatewayClient                esGatewayClient;\n\n    @Autowired\n    private ClusterRegionManager           clusterRegionManager;\n\n \n\n    @Autowired\n    private ESClusterService               esClusterService;\n\n    @Autowired\n    private HandleFactory                  handleFactory;\n\n\n    @Autowired\n    private ESIndexCatService              esIndexCatService;\n\n    @Autowired\n    private ESClusterNodeService eSClusterNodeService;\n    @Autowired\n    private ClusterPhyManager    clusterPhyManager;\n    @Autowired\n    private ClusterNodeManager clusterNodeManager;\n    \n    private static final FutureUtil<Void>         FUTURE_UTIL        = FutureUtil.init(\"ClusterLogicManager\", 10, 10,\n            100);\n\n    private static final Long              UNKNOWN_SIZE = -1L;\n\n    /**\n     * 构建运维页面的逻辑集群VO\n     * @param logicClusters     逻辑集群列表\n     * @return 逻辑集群列表\n     */\n    @Override\n    public List<ClusterLogicVO> buildClusterLogics(List<ClusterLogic> logicClusters) {\n        if (CollectionUtils.isEmpty(logicClusters)) {\n            return Lists.newArrayList();\n        }\n\n        List<ClusterLogicVO> clusterLogicVOS = Lists.newArrayList();\n        for (ClusterLogic logicCluster : logicClusters) {\n            clusterLogicVOS.add(buildClusterLogic(logicCluster));\n        }\n\n        Collections.sort(clusterLogicVOS);\n        return clusterLogicVOS;\n    }\n\n    /**\n     * 构建运维页面的逻辑集群VO\n     * @param clusterLogic    逻辑集群\n     * @return ClusterLogicVO\n     */\n    @Override\n    public ClusterLogicVO buildClusterLogic(ClusterLogic clusterLogic) {\n        ClusterLogicVO clusterLogicVO = ConvertUtil.obj2Obj(clusterLogic, ClusterLogicVO.class);\n\n        FUTURE_UTIL.runnableTask(() -> buildLogicClusterStatus(clusterLogicVO, clusterLogic))\n            .runnableTask(() -> buildLogicRole(clusterLogicVO, clusterLogic))\n            .runnableTask(() -> buildConsoleClusterVersions(clusterLogicVO));\n\n        buildClusterNodeInfo(clusterLogicVO);\n        Optional.ofNullable(projectService.getProjectBriefByProjectId(clusterLogic.getProjectId()))\n            .map(ProjectBriefVO::getProjectName).ifPresent(clusterLogicVO::setProjectName);\n\n        return clusterLogicVO;\n    }\n\n    @Override\n    public Result<Void> clearIndices(TemplateClearDTO clearDTO, String operator) throws ESOperateException {\n        if (AriusObjUtils.isNull(operator)) {\n            return Result.buildParamIllegal(\"操作人为空\");\n        }\n\n        if (CollectionUtils.isEmpty(clearDTO.getDelIndices())) {\n            return Result.buildParamIllegal(\"删除索引为空\");\n        }\n        final TupleTwo<Result<Void>, Integer> resultIntegerTuple2 = checkIndices(clearDTO.getDelIndices(),\n            clearDTO.getLogicId());\n        Result<Void> checkResult = resultIntegerTuple2.v1;\n        if (checkResult.failed()) {\n            return checkResult;\n        }\n\n        LOGGER.info(\"class=TemplateLogicServiceImpl||method=clearIndex||\"\n                    + \"operator={}||logicId={}||delIndices={}||delQueryDsl={}\",\n            operator, clearDTO.getLogicId(), JSON.toJSONString(clearDTO.getDelIndices()), clearDTO.getDelQueryDsl());\n\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(clearDTO.getLogicId());\n\n        if (StringUtils.isNotBlank(clearDTO.getDelQueryDsl())) {\n            Result<Void> deleteResult = batchDeletePhysicalTemplateIndicesByQuery(\n                templateLogicWithPhysical.getPhysicals(), clearDTO.getDelQueryDsl(), clearDTO.getDelIndices());\n            if (deleteResult.failed()) {\n                return deleteResult;\n            }\n        } else {\n            Result<Void> deleteIndicesResult = batchDeletePhysicalTemplateIndices(\n                templateLogicWithPhysical.getPhysicals(), clearDTO.getDelIndices());\n            if (deleteIndicesResult.failed()) {\n                return deleteIndicesResult;\n            }\n        }\n\n        if (StringUtils.isNotBlank(clearDTO.getDelQueryDsl())) {\n            String delIndices = String.join(\",\", clearDTO.getDelIndices());\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"需要清理的索引列表:%s; 删除条件:%s\", delIndices, clearDTO.getDelQueryDsl()),\n                    operator, resultIntegerTuple2.v2, clearDTO.getLogicId(), OperateTypeEnum.TEMPLATE_SERVICE_CLEAN);\n\n            return Result.buildSucWithTips(\"删除任务下发成功，请到sense中执行查询语句，确认删除进度\");\n        } else {\n            return Result.buildSucWithTips(\"索引删除成功\");\n        }\n    }\n\n    /**\n     * 获取逻辑集群分派的物理集群列表\n     *\n     * @param logicClusterId 逻辑集群ID\n     * @return 物理集群集合\n     */\n    @Override\n    public ClusterPhy getLogicClusterAssignedPhysicalClusters(Long logicClusterId) {\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(logicClusterId);\n        if (clusterRegion == null) {\n            return null;\n        }\n\n        return clusterPhyService.getClusterByName(clusterRegion.getPhyClusterName());\n    }\n\n    @Override\n    public Result<List<ClusterLogicVO>> getLogicClustersByProjectId(Integer projectId) {\n        List<ClusterLogicVO> list = ConvertUtil\n            .list2List(clusterLogicService.getHasAuthClusterLogicsByProjectId(projectId), ClusterLogicVO.class);\n        for (ClusterLogicVO clusterLogicVO : list) {\n            List<String> clusterPhyNames = clusterRegionService.listPhysicClusterNames(clusterLogicVO.getId());\n            clusterLogicVO.setPhyClusterAssociated(!AriusObjUtils.isEmptyList(clusterPhyNames));\n            clusterLogicVO.setAssociatedPhyClusterName(clusterPhyNames);\n            Optional.ofNullable(clusterLogicVO.getProjectId()).map(projectService::getProjectBriefByProjectId)\n                .map(ProjectBriefVO::getProjectName).ifPresent(clusterLogicVO::setProjectName);\n        }\n        return Result.buildSucc(list);\n    }\n    \n    /**\n     * 验证集群逻辑的参数\n     *\n     * @param param     要验证的参数对象。\n     * @param operation OperationEnum.ADD、OperationEnum.UPDATE、OperationEnum.DELETE\n     * @param projectId 项目编号\n     */\n    @Override\n    public Result<Void> validateClusterLogicParams(ESLogicClusterDTO param, OperationEnum operation,\n                                                   Integer projectId) {\n        return clusterLogicService.validateClusterLogicParams(param,operation,projectId);\n    }\n\n    /**\n     * “将具有给定 id 的集群加入到具有给定 id 的项目中。”\n     * <p>\n     * 函数的第一行是注释。编译器会忽略注释\n     *\n     * @param logicClusterId            要加入的集群的 ID。\n     * @param joinProjectId 加入的项目ID\n     * @return 返回类型是 Result<Void>\n     */\n    @Override\n    public Result<Void> joinClusterLogic(Long logicClusterId, Integer joinProjectId) {\n        final ESLogicClusterDTO param = new ESLogicClusterDTO();\n        param.setId(logicClusterId);\n        param.setProjectId(joinProjectId);\n        param.setType(clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(logicClusterId).getType());\n        return Result.buildFrom(clusterLogicService.joinClusterLogic(param));\n    }\n    /**\n     * @param level level\n     * @return Result<List<ClusterLogicVO>>\n     */\n    @Override\n    public Result<List<ClusterLogicVO>> getLogicClustersByLevel(Integer level) {\n    \n        List<ClusterLogicVO> list = ConvertUtil.list2List(clusterLogicService.listLogicClustersByLevelThatProjectIdStrConvertProjectIdList(level),\n                ClusterLogicVO.class);\n        for (ClusterLogicVO clusterLogicVO : list) {\n            List<String> clusterPhyNames = clusterRegionService.listPhysicClusterNames(clusterLogicVO.getId());\n            clusterLogicVO.setPhyClusterAssociated(!AriusObjUtils.isEmptyList(clusterPhyNames));\n            clusterLogicVO.setAssociatedPhyClusterName(clusterPhyNames);\n            Optional.ofNullable(clusterLogicVO.getProjectId()).map(projectService::getProjectBriefByProjectId)\n                    .map(ProjectBriefVO::getProjectName).ifPresent(clusterLogicVO::setProjectName);\n        }\n        return Result.buildSucc(list);\n    }\n    \n    @Override\n    public Result<List<Tuple<Long/*逻辑集群Id*/, String/*逻辑集群名称*/>>> listProjectClusterLogicIdsAndNames(Integer projectId) {\n        List<Tuple<Long/*逻辑集群Id*/, String/*逻辑集群名称*/>> res = Lists.newArrayList();\n        List<ClusterLogic> tempAuthLogicClusters = Lists.newArrayList();\n\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            tempAuthLogicClusters.addAll(clusterLogicService.listAllClusterLogics());\n        } else {\n            tempAuthLogicClusters.addAll(clusterLogicService.getHasAuthClusterLogicsByProjectId(projectId));\n        }\n\n        for (ClusterLogic clusterLogic : tempAuthLogicClusters) {\n            Tuple<Long, String> logicClusterId2logicClusterNameTuple = new Tuple<>();\n            logicClusterId2logicClusterNameTuple.setV1(clusterLogic.getId());\n            logicClusterId2logicClusterNameTuple.setV2(clusterLogic.getName());\n            res.add(logicClusterId2logicClusterNameTuple);\n        }\n        return Result.buildSucc(res);\n    }\n\n    @Override\n    public Result<List<ClusterLogicVO>> getProjectLogicClusterInfoByType(Integer projectId, Integer type) {\n        ESLogicClusterDTO logicClusterDTO = new ESLogicClusterDTO();\n        if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            logicClusterDTO.setProjectId(projectId);\n        }\n\n        logicClusterDTO.setType(type);\n        return Result.buildSucc(\n            ConvertUtil.list2List(clusterLogicService.listClusterLogics(logicClusterDTO), ClusterLogicVO.class));\n    }\n\n\n\n    @Override\n    public Result<List<ESClusterNodeSepcVO>> listMachineSpec() {\n        List<ESMachineNormsPO> esMachineNormsPOS = esMachineNormsService.listMachineNorms();\n        return Result.buildSucc(ConvertUtil.list2List(esMachineNormsPOS, ESClusterNodeSepcVO.class));\n    }\n\n\n\n    @Override\n    public ClusterLogicVO getClusterLogic(Long clusterLogicId, Integer currentProjectId) {\n        ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdAndProjectId(clusterLogicId, currentProjectId);\n        ClusterLogicVO clusterLogicVO = ConvertUtil.obj2Obj(clusterLogic, ClusterLogicVO.class);\n\n        FUTURE_UTIL.runnableTask(() -> buildConsoleClusterVersions(clusterLogicVO))\n            .runnableTask(() -> buildOpLogicClusterPermission(clusterLogicVO, currentProjectId))\n            .runnableTask(\n                () -> Optional.ofNullable(projectService.getProjectBriefByProjectId(clusterLogicVO.getProjectId()))\n                    .map(ProjectBriefVO::getProjectName).ifPresent(clusterLogicVO::setProjectName))\n            .runnableTask(() -> buildClusterNodeInfo(clusterLogicVO)).waitExecute();\n\n        return clusterLogicVO;\n    }\n\n    @Override\n    public Result<Void> addLogicClusterAndClusterRegions(ESLogicClusterWithRegionDTO param,\n                                                         String operator) throws AdminOperateException {\n        return clusterRegionManager.batchBindRegionToClusterLogic(param, operator, Boolean.TRUE);\n    }\n    \n    /**\n     * 删除逻辑集群 这里是及其容易触发操作超时的，\n     * 1.如果模板没有下线干净，那么这里就不能把逻辑集群下线干净，\n     * 2.如果索引没有下线干净，那么逻辑集群也是不能下线的，否则系统和数据库共同残留下来，业务侧就出现了问题\n     *\n     * @param logicClusterId logicclusterid\n     * @param operator\n     * @param projectId      projectid\n     * @return {@link Result}<{@link Void}>\n     * @throws AdminOperateException\n     */\n    @Transactional(rollbackFor = Exception.class)\n    @Override\n    public Result<Void> deleteLogicCluster(Long logicClusterId, String operator,\n                                           Integer projectId) {\n        //一个逻辑集群对应了多个项目的情况\n        final List<ClusterLogic> clusterLogicList = clusterLogicService.listClusterLogicByIdThatProjectIdStrConvertProjectIdList(logicClusterId);\n        if (CollectionUtils.isEmpty(clusterLogicList)) {\n            return Result.buildSucc();\n        }\n        final ClusterLogic clusterLogic = clusterLogicList.stream()\n                .filter(c -> Objects.equals(c.getProjectId(), projectId)).findFirst()\n                .orElse(null);\n        if (Objects.isNull(clusterLogic)) {\n            return Result.buildFail(String.format(\"项目【%s】不存在逻辑集群\",\n                    projectService.getProjectBriefByProjectId(projectId).getProjectName()));\n        }\n      \n        final Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(ClusterLogic::getProjectId,\n            clusterLogic, projectId);\n        if (checkProjectCorrectly.failed()) {\n            return checkProjectCorrectly;\n        }\n        \n        //获取逻辑模板和索引\n        ClusterLogicTemplateIndexDetailDTO templateIndexVO = getTemplateIndexVO(clusterLogic, projectId);\n        try {\n          \n            //但是索引下线没有完成，导致了脏数据的产生\n            if (CollectionUtils.isNotEmpty( templateIndexVO.getCatIndexResults())||\n                CollectionUtils.isNotEmpty(templateIndexVO.getTemplates())){\n                return Result.buildFail(String.format(\n                        \"该集群下还有%d项模板资源、%d项索引资源，如需下线集群，请前往模板管理、索引管理下线掉对应的模板及索引\",\n                        Optional.ofNullable(templateIndexVO.getTemplates()).orElse(Collections.emptyList()).size(),\n                        Optional.ofNullable(templateIndexVO.getCatIndexResults()).orElse(Collections.emptyList()).size()\n                ));\n            }\n          \n            if (clusterLogicList.size() == 1) {\n                //将region解绑\n                ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(logicClusterId);\n                if (Objects.nonNull(clusterRegion)) {\n                    //将region解绑\n                    Result<Void> unbindRes = clusterRegionService.unbindRegion(clusterRegion.getId(), logicClusterId,\n                            operator);\n                    if (unbindRes.failed()) {\n                       throw new AdminOperateException(unbindRes.getMessage());\n                    }\n                }\n            }\n            //删除逻辑集群\n            Result<Void> result = clusterLogicService.deleteClusterLogicById(logicClusterId, operator, projectId);\n            if (result.success()) {\n                SpringTool.publish(new ClusterLogicEvent(logicClusterId, projectId));\n                //操作记录 集群下线\n                operateRecordService.saveOperateRecordWithManualTrigger(clusterLogic.getName(), operator, projectId, logicClusterId,\n                        OperateTypeEnum.MY_CLUSTER_OFFLINE);\n                return Result.buildSuccWithTips(result.getData(),\n                        String.format(\"逻辑集群%s下线成功\", clusterLogic.getName()));\n            }\n            return Result.buildFailWithMsg(result.getData(),String.format(\"逻辑集群%s下线失败,%s\", clusterLogic.getName(),\n                    result.getMessage()));\n        } catch (AdminOperateException | ElasticsearchTimeoutException e) {\n            LOGGER.error(\"class={}||method=deleteLogicCluster||clusterLogic={}||es operation errMsg={}\",\n                    getClass().getSimpleName(), clusterLogic.getName(), e);\n            // 这里必须显示事务回滚\n            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();\n            return Result.buildFail(String.format(\"逻辑集群%s下线失败,, 请重新尝试下线集群,多次重试不成功,请联系管理员\", clusterLogic.getName()));\n        } catch (Exception e) {\n            LOGGER.error(\"class={}||method=deleteLogicCluster||clusterLogic={}||es operation errMsg={}\",\n                    getClass().getSimpleName(), clusterLogic.getName(), e);\n            // 这里必须显示事务回滚\n            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();\n            return Result.buildFail(\"操作失败,请联系管理员\");\n        }\n        \n    }\n\n    private ClusterLogicTemplateIndexDetailDTO getTemplateIndexVO(ClusterLogic clusterLogic,Integer projectId) {\n        IndexTemplateDTO param = new IndexTemplateDTO();\n        param.setResourceId(clusterLogic.getId());\n        param.setProjectId(projectId);\n        List<IndexTemplate> indexTemplates = indexTemplateService.listLogicTemplates(param);\n        //通过逻辑集群获取index\n        List<IndexCatCellDTO> catIndexResults = esIndexCatService.syncGetIndexByCluster(clusterLogic.getName(),projectId);\n        ClusterLogicTemplateIndexDetailDTO templateIndexVO = new ClusterLogicTemplateIndexDetailDTO();\n        templateIndexVO.setCatIndexResults(catIndexResults);\n        templateIndexVO.setTemplates(indexTemplates);\n        return templateIndexVO;\n    }\n\n    @Override\n    public Result<Void> editLogicCluster(ESLogicClusterDTO param, String operator, Integer projectId) {\n        final ClusterLogic logic = clusterLogicService.getClusterLogicByIdAndProjectId(param.getId(), projectId);\n        Result<Void> result = clusterLogicService.editClusterLogic(param, operator, projectId);\n        if (result.success()) {\n            SpringTool.publish(new ClusterLogicEvent(param.getId(), projectId));\n            //操作记录 我的集群信息修改\n            if (StringUtils.isNotBlank(param.getMemo())) {\n                 operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"%s 修改集群描述，%s-->%s\", logic.getName(), logic.getMemo(),\n                         param.getMemo()), operator, projectId, param.getId(),OperateTypeEnum.MY_CLUSTER_INFO_MODIFY);\n            \n            }\n        }\n        return result;\n    }\n    \n \n    \n    @Override\n    public PaginationResult<ClusterLogicVO> pageGetClusterLogics(ClusterLogicConditionDTO condition,\n                                                                 Integer projectId) throws NotFindSubclassException, ESOperateException {\n        BaseHandle baseHandle = handleFactory.getByHandlerNamePer(CLUSTER_LOGIC.getPageSearchType());\n        if (baseHandle instanceof ClusterLogicPageSearchHandle) {\n            ClusterLogicPageSearchHandle pageSearchHandle = (ClusterLogicPageSearchHandle) baseHandle;\n            return pageSearchHandle.doPage(condition, projectId);\n        }\n\n        LOGGER.warn(\n            \"class=ClusterLogicManagerImpl||method=pageGetConsoleClusterVOS||msg=failed to get the ClusterLogicPageSearchHandle\");\n        return PaginationResult.buildFail(\"分页获取逻辑集群信息失败\");\n    }\n\n    @Override\n    public boolean updateClusterLogicHealth(Long clusterLogicId) {\n        ESLogicClusterDTO updateLogicClusterDTO = new ESLogicClusterDTO();\n        Set<Integer> clusterHealthSet = Sets.newHashSet();\n        updateLogicClusterDTO.setId(clusterLogicId);\n        try {\n            final ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogicId);\n            if (Objects.isNull(clusterRegion)) {\n                LOGGER.error(\n                    \"class=ClusterLogicManagerImpl||method=updateClusterLogicHealth||clusterLogicId={}||errMsg=clusterLogicContext is empty\",\n                    clusterLogicId);\n                clusterHealthSet.add(UNKNOWN.getCode());\n            } else {\n                clusterHealthSet.add(esClusterService.syncGetClusterHealthEnum(clusterRegion.getPhyClusterName()).getCode());\n            }\n\n            updateLogicClusterDTO.setHealth(ClusterUtils.getClusterLogicHealthByClusterHealth(clusterHealthSet));\n            setClusterLogicInfo(updateLogicClusterDTO,clusterRegion);\n            clusterLogicService.editClusterLogicNotCheck(updateLogicClusterDTO);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ClusterLogicManagerImpl||method=updateClusterLogicHealth||clusterLogicId={}||errMsg={}\",\n                    clusterLogicId, e.getMessage(), e);\n            return false;\n        }\n\n        return true;\n    }\n\n    @Override\n    public Result<ClusterLogicTemplateIndexCountVO> indexTemplateCount(Long clusterId, String operator,\n                                                                       Integer projectId) {\n        ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdAndProjectId(clusterId,projectId);\n        ClusterLogicTemplateIndexDetailDTO detailVO = getTemplateIndexVO(clusterLogic,projectId);\n        ClusterLogicTemplateIndexCountVO countVO = new ClusterLogicTemplateIndexCountVO();\n        countVO.setCatIndexResults(detailVO.getCatIndexResults().size());\n        countVO.setTemplateLogicAggregates(detailVO.getTemplates().size());\n        return Result.buildSucc(countVO);\n    }\n\n    @Override\n    public Result<Long> estimatedDiskSize(Long clusterLogicId, Integer count) {\n        ClusterLogic clusterLogic =\n                clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(clusterLogicId);\n        if (Objects.isNull(clusterLogic)){\n            return Result.buildFail(\"逻辑集群不存在\");\n        }\n        String nodeSpec = clusterLogic.getDataNodeSpec();\n        if (StringUtils.isNotBlank(nodeSpec)) {\n            return Result.buildSucc(getUnitSize(nodeSpec.split(\"-\")[2]) * count);\n        }\n        return Result.buildSucc(UNKNOWN_SIZE);\n    }\n\n    @Override\n    public Result<String> getClusterDataNodeSpec(Long clusterLogicId){\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogicId);\n        Result<List<ClusterRoleHost>> result = clusterRoleHostService.listByRegionId(clusterRegion.getId().intValue());\n        ClusterRoleHost clusterRoleHost = result.getData().stream().findFirst().orElse(null);\n        return Result.buildSucc(clusterRoleHost.getMachineSpec());\n    }\n\n    @Override\n    public Result<List<String>> listClusterLogicNameByProjectId(Integer projectId) {\n        List<ClusterLogic> tempAuthLogicClusters = Lists.newArrayList();\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            tempAuthLogicClusters.addAll(clusterLogicService.listAllClusterLogics());\n        } else {\n            tempAuthLogicClusters.addAll(clusterLogicService.getHasAuthClusterLogicsByProjectId(projectId));\n        }\n        List<String> names = tempAuthLogicClusters.stream().map(ClusterLogic::getName).collect(Collectors.toList());\n        if (CollectionUtils.isEmpty(names)){\n            return Result.buildFail(\"无集群信息，请前往集群管理-->我的集群，进行集群申请。\");\n        }\n        return Result.buildSucc(names);\n    }\n\n    @Override\n    public Result<List<Tuple<String, ClusterPhyVO>>> getClusterRelationByProjectId(Integer projectId) {\n\n        List<Tuple<String, ClusterPhyVO>> collect;\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            List<ClusterPhy> phyList = clusterPhyService.listAllClusters();\n            collect = phyList.stream().map(\n                clusterPhy -> new Tuple<>(clusterPhy.getCluster(), ConvertUtil.obj2Obj(clusterPhy, ClusterPhyVO.class)))\n                .collect(Collectors.toList());\n        } else {\n            List<ClusterLogic> logicList = clusterLogicService.getOwnedClusterLogicListByProjectId(projectId);\n            collect = logicList.stream()\n                .map(clusterLogic -> new Tuple<>(clusterLogic.getName(), getPhyNameByLogic(clusterLogic.getId())))\n                .collect(Collectors.toList());\n        }\n        return Result.buildSucc(collect);\n    }\n\n    @Override\n    public Result<List<PluginVO>> getClusterLogicPlugins(Long clusterId) {\n        return Result\n            .buildSucc(ConvertUtil.list2List(clusterLogicService.getClusterLogicPlugins(clusterId), PluginVO.class));\n    }\n\n    @Override\n    public Result<Boolean> isLogicClusterRegionIsNotEmpty(Long logicClusterId) {\n        if (!clusterLogicService.existClusterLogicById(logicClusterId)) {\n            return Result.buildWithMsg(false, \"逻辑集群不存在！\");\n        }\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(logicClusterId);\n        if (null == clusterRegion) {\n            return Result.buildWithMsg(false, \"逻辑集群Region不存在！\");\n        }\n        Result<List<ClusterRoleHost>> roleHostResult = clusterRoleHostService\n            .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n\n        return Result.buildSucc(roleHostResult.success() && CollectionUtils.isNotEmpty(roleHostResult.getData()));\n    }\n\n    /**************************************************** private method ****************************************************/\n\n    /**\n     * 设置磁盘使用信息\n     * @param clusterDTO\n     */\n    public void setClusterLogicInfo(ESLogicClusterDTO clusterDTO,ClusterRegion clusterRegion) {\n        Result<List<ClusterRoleHost>> result = clusterRoleHostService\n                .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n        if (result.success()) {\n            List<String> clusterRoleHostList = result.getData().stream().map(ClusterRoleHost::getNodeSet).collect(Collectors.toList());\n\n            Long diskTotal = 0L;\n            Long diskUsage = 0L;\n            Map<String, Triple<Long, Long, Double>> map = eSClusterNodeService\n                    .syncGetNodesDiskUsage(clusterRegion.getPhyClusterName());\n            Set<Map.Entry<String, Triple<Long, Long, Double>>> entries = map.entrySet();\n            for (Map.Entry<String, Triple<Long, Long, Double>> entry : entries) {\n                if (clusterRoleHostList.contains(entry.getKey())) {\n                    diskTotal += entry.getValue().v1();\n                    diskUsage += entry.getValue().v2();\n                }\n            }\n            //设置节点数\n            clusterDTO.setDataNodeNum(clusterRoleHostList.size());\n            clusterDTO.setDiskTotal(diskTotal);\n            clusterDTO.setDiskUsage(diskUsage);\n            double diskUsagePercent = diskUsage != 0L && diskTotal != 0L ? CommonUtils.divideDoubleAndFormatDouble(\n                    diskUsage,\n                    diskTotal, 2, 1) : 0.0;\n            clusterDTO.setDiskUsagePercent(diskUsagePercent);\n        }\n\n        //设置es集群版本\n        ClusterPhy physicalCluster = getLogicClusterAssignedPhysicalClusters(clusterDTO.getId());\n        if (physicalCluster == null) {\n            return;\n        }\n        clusterDTO.setEsClusterVersion(physicalCluster.getEsVersion());\n\n    }\n\n    private ClusterPhyVO getPhyNameByLogic(Long clusterLogicId) {\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogicId);\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterRegion.getPhyClusterName());\n        return ConvertUtil.obj2Obj(clusterPhy, ClusterPhyVO.class);\n    }\n\n    /**\n     * 构建OP逻辑集群权限\n     * @param clusterLogicVO  逻辑集群\n     * @param projectIdForAuthJudge 用于判断权限的应用id（供应用管理页面获取关联集群列表使用）\n     *                          ，为null则权限为运维人员权限（管理权限）\n     */\n    private void buildOpLogicClusterPermission(ClusterLogicVO clusterLogicVO, Integer projectIdForAuthJudge) {\n        if (clusterLogicVO == null) {\n            return;\n        }\n\n        if (projectIdForAuthJudge == null) {\n            // 未指定需要判断权限的app，取运维人员权限\n            clusterLogicVO.setAuthId(null);\n            clusterLogicVO.setAuthType(ProjectClusterLogicAuthEnum.OWN.getCode());\n            clusterLogicVO.setPermissions(ProjectClusterLogicAuthEnum.OWN.getDesc());\n        } else {\n            // 指定了需要判断权限的app\n            buildLogicClusterPermission(clusterLogicVO, projectIdForAuthJudge);\n        }\n    }\n\n    /**\n     * 根据物理集群名获取对应的逻辑集群列表，若传入为空，则返回全量\n     * @param phyClusterName 物理集群的名称\n     * @return List<String> 逻辑集群名称列表\n     */\n    @Override\n    public List<String> listClusterLogicNameByPhyName(String phyClusterName) {\n        //若传入为空，则返回全量\n        if (null == phyClusterName) {\n            return clusterLogicService.listAllClusterLogics()\n                    .stream()\n                    .map(ClusterLogic::getName)\n                    .distinct()\n                    .collect(Collectors.toList());\n        } else {\n           return getClusterPhyAssociatedClusterLogicNames(phyClusterName);\n        }\n    }\n\n    /**\n     * 返回与给定应用关联的逻辑集群名称列表\n     *\n     * @param projectId 项目id\n     * @return List<String> 逻辑集群名称列表\n     */\n    @Override\n    public List<String> listClusterLogicNameByApp(Integer projectId) {\n        List<ClusterLogic> clusterLogicList = clusterLogicService.getHasAuthClusterLogicsByProjectId(projectId);\n        List<String> names = Lists.newArrayList();\n        for (ClusterLogic clusterLogic : clusterLogicList) {\n            names.add(clusterLogic.getName());\n        }\n        return names;\n    }\n\n    /**\n     * 返回与给定物理集群名称关联的逻辑集群名称列表\n     *\n     * @param phyClusterName 物理集群的名称。\n     * @return 与给定集群物理名称关联的集群逻辑名称列表。\n     */\n    @Override\n    public List<String> getClusterPhyAssociatedClusterLogicNames(String phyClusterName) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(phyClusterName);\n        if (null == clusterPhy) {\n            LOGGER.error(\n                    \"class=ClusterContextManagerImpl||method=flushClusterPhyContext||clusterPhyName={}||msg=clusterPhy is empty\",\n                    phyClusterName);\n            return Collections.emptyList();\n        }\n\n        final List<Long> logicIds = clusterRegionManager.listRegionByPhyCluster(phyClusterName).stream()\n                .filter(clusterRegion -> Objects.nonNull(clusterRegion.getLogicClusterIds()))\n                .map(clusterRegion -> ListUtils.string2LongList(clusterRegion.getLogicClusterIds()))\n                .filter(CollectionUtils::isNotEmpty).flatMap(Collection::stream)\n                .filter(logicId -> !Objects.equals(logicId,\n                        Long.parseLong(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID))).distinct()\n                .collect(Collectors.toList());\n        if (CollectionUtils.isEmpty(logicIds)){\n            return Collections.emptyList();\n        }\n       return clusterLogicService.getClusterLogicListByIds(logicIds)\n                .stream()\n                .map(ClusterLogic::getName)\n                .distinct()\n                .collect(Collectors.toList());\n\n    }\n    \n    /**\n     * 加入物理集群并创建逻辑集群\n     *\n     * @param param     ClusterJoinDTO\n     * @param projectId 项目编号\n     * @return joinClusterPhyAndCreateLogicCluster 方法的结果。\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Long> joinClusterPhyAndCreateLogicCluster(ClusterJoinDTO param, Integer projectId)\n            throws AdminOperateException {\n        final Result<ClusterPhyVO> voResult = clusterPhyManager.joinCluster(param, AriusUser.SYSTEM.getDesc(), projectId);\n        if (voResult.failed()) {\n            return Result.buildFrom(voResult);\n        }\n        final Integer clusterPhyId = voResult.getData().getId();\n        final Result<List<ESClusterRoleHostWithRegionInfoVO>> listResult = clusterNodeManager.listDivide2ClusterNodeInfo(\n                clusterPhyId.longValue());\n        if (listResult.failed()) {\n            return Result.buildFrom(listResult);\n        }\n        final List<Integer> regionIds = listResult.getData().stream()\n                .map(ESClusterRoleHostVO::getId).distinct().map(Long::intValue).collect(Collectors.toList());\n        final ClusterRegionWithNodeInfoDTO clusterRegionWithNodeInfoDTO =\n                new ClusterRegionWithNodeInfoDTOBuilder()\n                .withBindingNodeIds(regionIds).withName(param.getCluster()).withLogicClusterIds(\"-1\")\n                .withPhyClusterName(param.getCluster()).build();\n    \n        final Result<List<Long>> result = clusterNodeManager.createMultiNode2Region(\n                Lists.newArrayList(clusterRegionWithNodeInfoDTO), AriusUser.SYSTEM.getDesc(), projectId);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n        final Long regionId = result.getData().get(0);\n        ClusterRegionDTO clusterRegionDTO = ClusterRegionDTO.builder().id(regionId).logicClusterIds(\"-1\")\n                .phyClusterName(param.getCluster()).name(param.getCluster()).build();\n        final ESLogicClusterWithRegionDTO esLogicClusterWithRegionDTO = new ESLogicClusterWithRegionDTOBuilder()\n                .withProjectId(AuthConstant.DEFAULT_METADATA_PROJECT_ID).withName(clusterRegionDTO.getName()).withLevel(1).withType(1)\n                .withDataNodeSpec(\"\").withClusterRegionDTOS(Lists.newArrayList(clusterRegionDTO)).build();\n       \n        final Result<Void> voidResult = addLogicClusterAndClusterRegions(esLogicClusterWithRegionDTO, AriusUser.SYSTEM.getDesc());\n        if (voidResult.failed()) {\n            return Result.buildFrom(voidResult);\n        }\n        final ClusterLogic logic = clusterLogicService.getClusterLogicByNameThatNotContainsProjectId(\n                param.getCluster());\n    \n        return Result.buildSucc(logic.getId());\n    }\n    \n    @Override\n    public Result<List<ClusterPhyWithLogicClusterVO>> listLogicClusterWithClusterPhyByProjectId(Integer projectId) {\n        List<ClusterLogic> clusterLogics = clusterLogicService.getOwnedClusterLogicListByProjectId(projectId);\n        if (CollectionUtils.isEmpty(clusterLogics)) {\n            return Result.buildSucc(Collections.emptyList());\n        }\n        Map<Long, String> clusterLogicId2ClusterLogicNameMap = ConvertUtil.list2Map(clusterLogics, ClusterLogic::getId,\n                ClusterLogic::getName);\n        List<Long> logicClusterIdList = clusterLogics.stream().map(ClusterLogic::getId).distinct()\n                .collect(Collectors.toList());\n        List<ClusterRegion> regions = clusterRegionService.getClusterRegionsByLogicIds(logicClusterIdList);\n        if (CollectionUtils.isEmpty(regions)) {\n            return Result.buildSucc(Collections.emptyList());\n        }\n        // 逻辑集群 -》region 1-1 所以\n        Function<ClusterRegion, List<TupleTwo<Long, String>>> logicClusterIds2logicClusterIdLongWithClusterPhyFunc = clusterRegion -> Arrays.stream(\n                        StringUtils.split(clusterRegion.getLogicClusterIds(), \",\")).filter(StringUtils::isNumeric)\n                .map(Long::parseLong)\n                .map(logicClusterId -> Tuples.of(logicClusterId, clusterRegion.getPhyClusterName()))\n                .collect(Collectors.toList());\n        // 转换\n        Function<TupleTwo</*clusterLogicId*/Long,/*clusterPhy*/ String>, ClusterPhyWithLogicClusterVO> clusterLogicId2clusterPhyFunc = tuple -> {\n            Long logicId = tuple.v1;\n            String clusterPhy = tuple.v2;\n            if (clusterLogicId2ClusterLogicNameMap.containsKey(logicId)) {\n                return ClusterPhyWithLogicClusterVO.builder().clusterPhy(clusterPhy).clusterLogicId(logicId)\n                        .clusterLogic(clusterLogicId2ClusterLogicNameMap.get(logicId)).build();\n            }\n        \n            return null;\n        };\n    \n        List<ClusterPhyWithLogicClusterVO> clusterPhyWithLogicClusterList = regions.stream()\n                .map(logicClusterIds2logicClusterIdLongWithClusterPhyFunc).flatMap(Collection::stream).distinct()\n                .map(clusterLogicId2clusterPhyFunc).filter(Objects::nonNull).collect(Collectors.toList());\n        return Result.buildSucc(clusterPhyWithLogicClusterList);\n    }\n\n    @Override\n    public Result<List<ClusterLogicVO>> listClusterLogicByPhyName(String phyClusterName) {\n        if (StringUtils.isNotBlank(phyClusterName)) {\n            ClusterPhy clusterPhy = clusterPhyService.getClusterByName(phyClusterName);\n            if (null == clusterPhy) {\n                LOGGER.error(\n                    \"class=ClusterContextManagerImpl||method=flushClusterPhyContext||clusterPhyName={}||msg=clusterPhy is empty\",\n                    phyClusterName);\n                return Result.buildFail(\"物理集群不存在！\");\n            }\n\n            final List<Long> logicIds = clusterRegionManager.listRegionByPhyCluster(phyClusterName).stream()\n                .filter(clusterRegion -> Objects.nonNull(clusterRegion.getLogicClusterIds()))\n                .map(clusterRegion -> ListUtils.string2LongList(clusterRegion.getLogicClusterIds()))\n                .filter(CollectionUtils::isNotEmpty).flatMap(Collection::stream)\n                .filter(logicId -> !Objects.equals(logicId,\n                    Long.parseLong(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID)))\n                .distinct().collect(Collectors.toList());\n            if (CollectionUtils.isNotEmpty(logicIds)) {\n                return Result.buildSucc(ConvertUtil.list2List(clusterLogicService.getClusterLogicListByIds(logicIds),\n                    ClusterLogicVO.class));\n            }\n            return Result.buildSucc(Collections.emptyList());\n        }\n        //若传入为空，则返回全量\n        return Result\n            .buildSucc(ConvertUtil.list2List(clusterLogicService.listAllClusterLogics(), ClusterLogicVO.class));\n    }\n\n    /**\n     * 构建ES集群版本\n     * @param logicCluster 逻辑集群\n     */\n    private void buildConsoleClusterVersions(ClusterLogicVO logicCluster) {\n        try {\n            if (logicCluster != null) {\n                ClusterPhy physicalCluster = getLogicClusterAssignedPhysicalClusters(logicCluster.getId());\n                if (physicalCluster == null) {\n                    return;\n                }\n                logicCluster.setEsClusterVersion(physicalCluster.getEsVersion());\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\"class=LogicClusterManager||method=buildConsoleClusterVersions||logicClusterId={}\",\n                logicCluster.getId(), e);\n        }\n    }\n\n    /**\n     * 设置app对指定逻辑集群的权限\n     * @param logicClusterVO      逻辑集群\n     * @param projectIdForAuthJudge 需要判断的app的ID\n     */\n    private void buildLogicClusterPermission(ClusterLogicVO logicClusterVO, Integer projectIdForAuthJudge) {\n        try {\n            if (logicClusterVO == null || projectIdForAuthJudge == null) {\n                return;\n            }\n            if (AuthConstant.SUPER_PROJECT_ID.equals(projectIdForAuthJudge)) {\n                logicClusterVO.setAuthType(ProjectClusterLogicAuthEnum.OWN.getCode());\n                logicClusterVO.setPermissions(ProjectClusterLogicAuthEnum.OWN.getDesc());\n                return;\n            }\n\n            ProjectClusterLogicAuth auth = projectClusterLogicAuthService.getLogicClusterAuth(projectIdForAuthJudge,\n                logicClusterVO.getId());\n\n            if (auth == null) {\n                // 没有权限\n                logicClusterVO.setAuthId(null);\n                logicClusterVO.setAuthType(ProjectClusterLogicAuthEnum.NO_PERMISSIONS.getCode());\n                logicClusterVO.setPermissions(ProjectClusterLogicAuthEnum.NO_PERMISSIONS.getDesc());\n            } else {\n                // 有权限\n                logicClusterVO.setAuthId(auth.getId());\n                logicClusterVO.setAuthType(ProjectClusterLogicAuthEnum.valueOf(auth.getType()).getCode());\n                logicClusterVO.setPermissions(ProjectClusterLogicAuthEnum.valueOf(auth.getType()).getDesc());\n            }\n\n        } catch (Exception e) {\n            LOGGER.warn(\"class=LogicClusterManager||method=buildLogicClusterPermission||logicClusterId={}\",\n                logicClusterVO.getId(), e);\n        }\n    }\n\n    /**\n     * 更新逻辑集群状态信息\n     */\n    private void buildLogicClusterStatus(ClusterLogicVO logicCluster, ClusterLogic clusterLogic) {\n        ClusterLogicStatis esClusterLogicStatus = buildDefaultLogicStatus();\n        try {\n            ClusterLogicStatis clusterLogicStatus = getClusterLogicStatus(clusterLogic.getId());\n            if (null != clusterLogicStatus) {\n                esClusterLogicStatus = clusterLogicStatus;\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=ClusterLogicManagerImpl||method=buildLogicClusterStatus||logicClusterId={}\",\n                logicCluster.getId(), e);\n        }\n\n        logicCluster.setClusterStatus(ConvertUtil.obj2Obj(esClusterLogicStatus, ConsoleClusterStatusVO.class));\n    }\n\n    /**\n     * 创建默认逻辑集群状态\n     * @return  ClusterLogicStatis\n     */\n    private ClusterLogicStatis buildDefaultLogicStatus() {\n        ClusterLogicStatis logicStatus = new ClusterLogicStatis();\n        logicStatus.setStatus(ClusterHealthEnum.RED.getDesc());\n        logicStatus.setDocNu(0.0);\n        logicStatus.setIndexNu(0);\n        logicStatus.setTotalDisk(0.0);\n        logicStatus.setUsedDisk(0.0);\n        return logicStatus;\n    }\n\n    private void buildLogicRole(ClusterLogicVO logicCluster, ClusterLogic clusterLogic) {\n        if (logicCluster != null) {\n            try {\n                Long logicClusterId = logicCluster.getId();\n\n                List<String> phyClusterNames = clusterRegionService.listPhysicClusterNames(logicClusterId);\n                if (CollectionUtils.isEmpty(phyClusterNames)) {\n                    return;\n                }\n\n                //拿第一个物理集群的client、master信息，因为只有Arius维护的大公共共享集群才会有一个逻辑集群映射成多个物理集群\n                ClusterPhy clusterPhy = clusterPhyService.getClusterByName(phyClusterNames.get(0));\n                if (null == clusterPhy) {\n                    return;\n                }\n\n                List<ClusterRoleInfo> esRolePhyClusters = clusterPhy.getClusterRoleInfos();\n                List<ClusterRoleHost> esRolePhyClusterHosts = clusterPhy.getClusterRoleHosts();\n\n                logicCluster.setEsClusterRoleVOS(\n                    buildESRoleClusterVOList(clusterLogic, logicClusterId, esRolePhyClusters, esRolePhyClusterHosts));\n            } catch (Exception e) {\n                LOGGER.warn(\"class=LogicClusterManager||method=buildLogicRole||logicClusterId={}\", logicCluster.getId(),\n                    e);\n            }\n        }\n    }\n\n    private List<ESClusterRoleVO> buildESRoleClusterVOList(ClusterLogic clusterLogic, Long logicClusterId,\n                                                           List<ClusterRoleInfo> esRolePhyClusters,\n                                                           List<ClusterRoleHost> esRolePhyClusterHosts) {\n        List<ESClusterRoleVO> esClusterRoleVOS = new ArrayList<>();\n        for (ClusterRoleInfo clusterRoleInfo : esRolePhyClusters) {\n            ESClusterRoleVO esClusterRoleVO = ConvertUtil.obj2Obj(clusterRoleInfo, ESClusterRoleVO.class);\n\n            List<ESClusterRoleHostVO> esClusterRoleHostVOS = new ArrayList<>();\n\n            //如果是datanode节点，那么使用逻辑集群申请的节点个数和阶段规格配置\n            if (DATA_NODE.getDesc().equals(clusterRoleInfo.getRoleClusterName())) {\n                buildEsClusterRoleHostVOList(clusterLogic, logicClusterId, esClusterRoleVO, esClusterRoleHostVOS);\n            } else {\n                for (ClusterRoleHost clusterRoleHost : esRolePhyClusterHosts) {\n                    if (clusterRoleHost.getRoleClusterId().longValue() == clusterRoleInfo.getId().longValue()) {\n                        esClusterRoleHostVOS.add(ConvertUtil.obj2Obj(clusterRoleHost, ESClusterRoleHostVO.class));\n                    }\n                }\n            }\n\n            esClusterRoleVO.setEsClusterRoleHostVO(esClusterRoleHostVOS);\n            esClusterRoleVO.setPodNumber(esClusterRoleHostVOS.size());\n            esClusterRoleVOS.add(esClusterRoleVO);\n        }\n        return esClusterRoleVOS;\n    }\n\n    private void buildEsClusterRoleHostVOList(ClusterLogic clusterLogic, Long logicClusterId,\n                                              ESClusterRoleVO esClusterRoleVO,\n                                              List<ESClusterRoleHostVO> esClusterRoleHostVOS) {\n        esClusterRoleVO.setPodNumber(clusterLogic.getDataNodeNum());\n        esClusterRoleVO.setMachineSpec(clusterLogic.getDataNodeSpec());\n\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(logicClusterId);\n        if (null != clusterRegion) {\n            Result<List<ClusterRoleHost>> ret = clusterRoleHostService.listByRegionId(clusterRegion.getId().intValue());\n            if (ret.success() && CollectionUtils.isNotEmpty(ret.getData())) {\n                for (ClusterRoleHost clusterRoleHost : ret.getData()) {\n                    ESClusterRoleHostVO esClusterRoleHostVO = new ESClusterRoleHostVO();\n                    esClusterRoleHostVO.setHostname(clusterRoleHost.getIp());\n                    esClusterRoleHostVO.setRole(DATA_NODE.getCode());\n\n                    esClusterRoleHostVOS.add(esClusterRoleHostVO);\n                }\n            }\n        }\n    }\n\n    /**\n     * 构建节点信息:\n     * 1. 是否关联物理集群\n     * 2. 获取关联物理集群列表\n     * 3. 逻辑集群拥有的数据节点数\n     * 4. 防止没有关联物理集群, 或者取消关联region, 逻辑集群状态为red\n     * 5. 获取gateway地址\n     */\n    private void buildClusterNodeInfo(ClusterLogicVO clusterLogicVO) {\n        //获取gateway地址\n        clusterLogicVO.setGatewayAddress(esGatewayClient.getGatewayAddress());\n        //获取活跃分片数\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogicVO.getId());\n        AtomicReference<Long> activeShardNum = new AtomicReference<>(0L);\n        if (Objects.nonNull(clusterRegion)){\n            Map<String/*node*/, Long /*shardNum*/>  nodeShardsNum = eSClusterNodeService.syncGetNode2ShardNumMap(clusterRegion.getPhyClusterName());\n            Result<List<ESClusterRoleHostVO>>  ESClusterRoleHostVORes =clusterNodeManager.listClusterLogicNode(Math.toIntExact(clusterLogicVO.getId()));\n            ESClusterRoleHostVORes.getData().stream().forEach(node->{\n                activeShardNum.updateAndGet(v -> v + nodeShardsNum.get(node.getNodeSet()));\n            });\n        }\n\n        clusterLogicVO.setActiveShardNum(activeShardNum.get());\n    }\n\n    private TupleTwo<Result<Void>, /*projectId*/Integer> checkIndices(List<String> delIndices, Integer logicId) {\n        for (String index : delIndices) {\n            if (index.endsWith(\"*\")) {\n                return Tuples.of(Result.buildParamIllegal(\"索引名字不能以*结尾\"), null);\n            }\n        }\n\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n        IndexTemplatePhy templatePhysical = templateLogicWithPhysical.getMasterPhyTemplate();\n\n        List<String> matchIndices = indexTemplatePhyService.getMatchNoVersionIndexNames(templatePhysical.getId());\n        for (String index : delIndices) {\n            if (!matchIndices.contains(index)) {\n                return Tuples.of(Result.buildParamIllegal(index + \"不属于该索引模板\"), null);\n            }\n        }\n        return Tuples.of(Result.buildSucc(), templateLogicWithPhysical.getProjectId());\n    }\n\n    /**\n     * 批量删除物理模板对应分区索引\n     * @param physicals 物理模板列表\n     * @param delIndices 待删除分区索引列表\n     * @return 成功/失败\n     */\n    private Result<Void> batchDeletePhysicalTemplateIndices(List<IndexTemplatePhy> physicals, List<String> delIndices) {\n        for (IndexTemplatePhy templatePhysical : physicals) {\n            if (templatePhysical.getVersion() > 0) {\n                List<String> delIndicesWithVersion = genDeleteIndicesWithVersion(delIndices);\n\n                LOGGER.info(\n                    \"class=TemplateLogicServiceImpl||method=clearIndex||templateName={}||version={}||indices={}\",\n                    templatePhysical.getName(), templatePhysical.getVersion(), delIndicesWithVersion);\n\n                if (CollectionUtils.isNotEmpty(delIndicesWithVersion)) {\n                    esIndexService.syncBatchDeleteIndices(templatePhysical.getCluster(), delIndicesWithVersion, 3);\n                }\n            }\n\n            int count = delIndices.size();\n            if (count != esIndexService.syncBatchDeleteIndices(templatePhysical.getCluster(), delIndices, 3)) {\n                return Result.buildFail(\"删除索引失败，请重试\");\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 通过请求的方式批量删除物理模板分区索引\n     * @param physicals 物理模板\n     * @param delQueryDsl DSL语句\n     * @param delIndices 删除索引列表\n     * @return 成功/失败\n     */\n    private Result<Void> batchDeletePhysicalTemplateIndicesByQuery(List<IndexTemplatePhy> physicals, String delQueryDsl,\n                                                                   List<String> delIndices) throws ESOperateException {\n        if (StringUtils.isNotBlank(delQueryDsl)) {\n            for (IndexTemplatePhy templatePhysical : physicals) {\n                if (!esIndexService.syncDeleteByQuery(templatePhysical.getCluster(), delIndices, delQueryDsl)) {\n                    return Result.buildFail(\"删除索引失败，请重试\");\n                }\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 生成带有版本模式的待删除索引列表\n     *\n     * @param delIndices 待删除索引列表\n     * @return 索引名称列表\n     */\n    private List<String> genDeleteIndicesWithVersion(List<String> delIndices) {\n        List<String> indicesWithVersion = new ArrayList<>();\n        if (CollectionUtils.isNotEmpty(delIndices)) {\n            for (String delIndex : delIndices) {\n                indicesWithVersion.add(delIndex + \"_v*\");\n            }\n        }\n\n        return indicesWithVersion;\n    }\n\n    private ClusterLogicStatis getClusterLogicStatus(Long logicClusterId) {\n        ClusterLogicStatis clusterLogicStatis = new ClusterLogicStatis();\n\n        //获取集群上下文\n        //todo 暂时留存\n        //ClusterLogicContext clusterLogicContext = clusterContextManager.getClusterLogicContext(logicClusterId);\n        //if (null == clusterLogicContext) {\n        //    return null;\n        //}\n        ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(\n                logicClusterId);\n        if (Objects.isNull(clusterLogic)){\n            return null;\n        }\n\n        //设置逻辑集群名称\n        //clusterLogicStatis.setName(clusterLogicService.getClusterLogicName());\n        clusterLogicStatis.setName(clusterLogic.getName());\n        clusterLogicStatis.setId(logicClusterId);\n\n        List<ESClusterStatsResponse> esClusterStatsResponseList =\n                //clusterLogicContext.getAssociatedClusterPhyNames()\n        clusterRegionService.listPhysicClusterNames(clusterLogic.getId())\n            .stream().map(esClusterService::syncGetClusterStats).collect(Collectors.toList());\n\n        //设置基础数据\n        clusterLogicStatis\n            .setIndexNu(esClusterStatsResponseList.stream().mapToLong(ESClusterStatsResponse::getIndexCount).sum());\n        clusterLogicStatis\n            .setDocNu(esClusterStatsResponseList.stream().mapToDouble(ESClusterStatsResponse::getDocsCount).sum());\n        clusterLogicStatis\n            .setTotalDisk(esClusterStatsResponseList.stream().mapToDouble(item -> item.getTotalFs().getBytes()).sum());\n        clusterLogicStatis.setUsedDisk(esClusterStatsResponseList.stream()\n            .mapToDouble(item -> item.getTotalFs().getBytes() - item.getFreeFs().getBytes()).sum());\n\n        //设置逻辑集群状态\n        Set<String> statusSet = esClusterStatsResponseList.stream().map(ESClusterStatsResponse::getStatus)\n            .collect(Collectors.toSet());\n        clusterLogicStatis.setStatus(getClusterLogicStatus(statusSet));\n        return clusterLogicStatis;\n    }\n\n    @Override\n    public Result<Void> deleteTemplatesIndicesInfo(Long clusterLogicId,Integer projectId,String operator) {\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogicId);\n        ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdAndProjectId(clusterLogicId,projectId);\n        if (Objects.isNull(clusterRegion)){\n            return Result.buildFail(\"该逻辑集群未绑定region!\");\n        }\n        //获取物理模板\n        Result<List<IndexTemplatePhy>> indexTemplatePhys = indexTemplatePhyService.listByRegionId(Math.toIntExact(clusterRegion.getId()));\n        //获取逻辑模板\n        Result<List<IndexTemplate>> indexTemplates = indexTemplateService.listByRegionId(Math.toIntExact(clusterRegion.getId()));\n        List<String> indices = esIndexCatService.syncGetIndexListByProjectId(projectId,clusterLogic.getName());\n        if (indexTemplatePhys.getData().size() == 0&&indexTemplates.getData().size() == 0&&indices.size()==0){\n            return Result.buildFail(\"该逻辑集群下无数据!\");\n        }\n        //删除数据\n        for (IndexTemplate indexTemplate:indexTemplates.getData()) {\n            try {\n                indexTemplateService.delTemplate(indexTemplate.getId(),operator);\n                indexTemplatePhyService.delTemplateByLogicId(indexTemplate.getId(),operator);\n            } catch (AdminOperateException e) {\n                return Result.buildFail(\"数据删除错误!\");\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    /**\n     * 获取逻辑集群状态\n     * @return ClusterStatusEnum\n     */\n    private String getClusterLogicStatus(Set<String> statusSet) {\n        if (statusSet.contains(RED.getDesc())) {\n            return RED.getDesc();\n        }\n\n        if (statusSet.size() == 1 && statusSet.contains(GREEN.getDesc())) {\n            return GREEN.getDesc();\n        }\n\n        if (statusSet.contains(YELLOW.getDesc())) {\n            return YELLOW.getDesc();\n        }\n        return RED.getDesc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/impl/ClusterNodeManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.DATA_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType.FAIL;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterNodeManager;\nimport com.didichuxing.datachannel.arius.admin.common.Triple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionWithNodeInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterNodeInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostWithRegionInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.region.RegionEditEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Multimap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-30\n */\n@Component\npublic class ClusterNodeManagerImpl implements ClusterNodeManager {\n\n    private static final ILog      LOGGER = LogFactory.getLog(ClusterNodeManager.class);\n\n    @Autowired\n    private ClusterRoleHostService clusterRoleHostService;\n\n    @Autowired\n    private ClusterRegionService   clusterRegionService;\n\n    @Autowired\n    private ClusterPhyService      clusterPhyService;\n\n    @Autowired\n    private ESClusterNodeService   esClusterNodeService;\n\n    @Autowired\n    private OperateRecordService   operateRecordService;\n\n    @Autowired\n    private ClusterLogicService    clusterLogicService;\n    @Autowired\n    private ProjectService projectService;\n\n    @Override\n    public Result<List<ESClusterRoleHostWithRegionInfoVO>> listDivide2ClusterNodeInfo(Long clusterId) {\n        List<ClusterRoleHost> clusterRoleHostList = null;\n        try {\n            clusterRoleHostList = clusterRoleHostService.getByRoleAndClusterId(clusterId, DATA_NODE.getDesc());\n        } catch (Exception e) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=listDivide2ClusterNodeInfo||clusterId={}||errMsg={}\",\n                clusterId, e.getMessage(), e);\n        }\n        List<ESClusterRoleHostWithRegionInfoVO> esClusterRoleHostWithRegionInfoVOS = ConvertUtil\n            .list2List(clusterRoleHostList, ESClusterRoleHostWithRegionInfoVO.class);\n\n        // 根据regionId获取region名称\n        List<Integer> regionIdList = esClusterRoleHostWithRegionInfoVOS.stream()\n            .map(ESClusterRoleHostWithRegionInfoVO::getRegionId).distinct().collect(Collectors.toList());\n\n        if (CollectionUtils.isEmpty(regionIdList)) {\n            return Result.buildSucc(esClusterRoleHostWithRegionInfoVOS);\n        }\n\n        Map<Integer, String> regionId2RegionNameMap = Maps.newHashMap();\n        for (Integer regionId : regionIdList) {\n            ClusterRegion clusterRegion = clusterRegionService.getRegionById(regionId.longValue());\n            if (null == clusterRegion) {\n                continue;\n            }\n\n            regionId2RegionNameMap.put(regionId, clusterRegion.getName());\n        }\n\n        for (ESClusterRoleHostWithRegionInfoVO clusterRoleHostWithRegionInfoVO : esClusterRoleHostWithRegionInfoVOS) {\n            clusterRoleHostWithRegionInfoVO\n                .setRegionName(regionId2RegionNameMap.get(clusterRoleHostWithRegionInfoVO.getRegionId()));\n        }\n        return Result.buildSucc(esClusterRoleHostWithRegionInfoVOS);\n    }\n\n    @Override\n    public Result<Boolean> checkMultiNode2Region(List<ClusterRegionWithNodeInfoDTO> params, String operator, Integer projectId) {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        for(ClusterRegionWithNodeInfoDTO param : params){\n            Result<Boolean> checkRet = baseCheckParamValid(param,OperationEnum.ADD);\n            if (checkRet.failed()) {\n                return checkRet;\n            }\n\n            if (CollectionUtils.isEmpty(param.getBindingNodeIds())) {\n                return Result.buildFail(String.format(\"region名称[%s], errMsg=%s\", param.getName(), \"划分至该region的节点为空\"));\n            }\n        }\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    public Result<List<ClusterNodeInfoVO>> listClusterPhyNodeInfosByName(String clusterPhyName) {\n        if (null == clusterPhyName) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=getAppClusterPhyNodeNames||errMsg=集群名称为空\");\n            return Result.buildFail(\"集群名称为空\");\n        }\n        List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService.getNodesByCluster(clusterPhyName);\n        //节点信息列表\n        return Result.buildSucc(clusterRoleHosts.stream().map(clusterRoleHost->new ClusterNodeInfoVO(clusterRoleHost.getNodeSet(),clusterRoleHost.getRole()))\n                .collect(Collectors.toList()));\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<List<Long>> createMultiNode2Region(List<ClusterRegionWithNodeInfoDTO> params, String operator,\n                                                     Integer projectId) throws AdminOperateException {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n\n        List<Long> regionIdLis = Lists.newArrayList();\n        for (ClusterRegionWithNodeInfoDTO param : params) {\n            Result<Boolean> checkRet = baseCheckParamValid(param,OperationEnum.ADD);\n            if (checkRet.failed()) {\n                throw new AdminOperateException(checkRet.getMessage());\n            }\n\n            if (CollectionUtils.isEmpty(param.getBindingNodeIds())) {\n                throw new AdminOperateException(\n                    String.format(\"region名称[%s], errMsg=%s\", param.getName(), \"划分至该region的节点为空\"));\n            }\n\n            Result<Long> addRegionRet = clusterRegionService.createPhyClusterRegion(param, operator);\n\n            if (addRegionRet.success()) {\n                param.setId(addRegionRet.getData());\n                // 调用扩缩容region接口来添加region\n                Result<Boolean> booleanResult = editNode2Region(param);\n                if (booleanResult.success()) {\n                    // 2. 操作记录 :Region变更\n                     operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"新增 region[%s]\", param.getName()), operator, projectId,\n                            param.getId(), OperateTypeEnum.PHYSICAL_CLUSTER_REGION_CHANGE);\n                    regionIdLis.add(addRegionRet.getData());\n                } else {\n                    throw new AdminOperateException(addRegionRet.getMessage());\n                }\n            }\n        }\n        return Result.buildSucc(regionIdLis);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Boolean> editMultiNode2Region(List<ClusterRegionWithNodeInfoDTO> params, String operator,\n                                                Integer projectId, OperationEnum operationEnum) throws AdminOperateException {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        for (ClusterRegionWithNodeInfoDTO param : params) {\n            Result<Boolean> checkRet = baseCheckParamValid(param,operationEnum);\n            if (checkRet.failed()) {\n                throw new AdminOperateException(checkRet.getMessage(), FAIL);\n            }\n\n            Result<Boolean> editNode2RegionRet = editNode2Region(param);\n            if (editNode2RegionRet.failed()) {\n                throw new AdminOperateException(editNode2RegionRet.getMessage(), FAIL);\n            }\n        }\n\n        // 发布region变更的事件，对模板和索引生效\n        List<Long> regionIdList = params.stream().distinct().map(ClusterRegionWithNodeInfoDTO::getId)\n            .collect(Collectors.toList());\n        SpringTool.publish(new RegionEditEvent(this, regionIdList));\n\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    public Result<List<ESClusterRoleHostVO>> listClusterPhyNode(Integer clusterId) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(clusterId);\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildFail(String.format(\"集群[%s]不存在\", clusterId));\n        }\n        List<ClusterRoleHost> clusterRoleHostList = clusterRoleHostService.getNodesByCluster(clusterPhy.getCluster());\n        return Result.buildSucc(buildClusterRoleHostStats(clusterPhy.getCluster(), clusterRoleHostList));\n    }\n\n    @Override\n    public Result<List<ESClusterRoleHostVO>> listClusterLogicNode(Integer clusterId) {\n        if (!clusterLogicService.existClusterLogicById(clusterId.longValue())) {\n            return Result.buildFail(String.format(\"集群[%s]不存在\", clusterId));\n        }\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterId.longValue());\n        if (clusterRegion == null) {\n            return Result.buildFail(String.format(\"集群[%s]未绑定region\", clusterId));\n        }\n        Result<List<ClusterRoleHost>> result = clusterRoleHostService\n            .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        //节点名称列表\n        return Result.buildSucc(buildClusterRoleHostStats(clusterRegion.getPhyClusterName(), result.getData()));\n    }\n\n    @Override\n    public Result listClusterLogicNodeByName(String clusterLogicName) {\n        ClusterLogic clusterLogic =\n                clusterLogicService.listClusterLogicByNameThatProjectIdStrConvertProjectIdList(clusterLogicName).stream().findFirst().orElse(null);\n        if (AriusObjUtils.isNull(clusterLogic)) {\n            return Result.buildFail(String.format(\"集群[%s]不存在\", clusterLogicName));\n        }\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogic.getId());\n        Result<List<ClusterRoleHost>> result = clusterRoleHostService\n            .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n\n        //节点名称列表\n        return Result\n            .buildSucc(result.getData().stream().map(ClusterRoleHost::getNodeSet).collect(Collectors.toList()));\n    }\n\n    @Override\n    public Result<List<ClusterNodeInfoVO>> listClusterLogicNodeInfosByName(String clusterLogicName) {\n        ClusterLogic clusterLogic =\n                clusterLogicService.listClusterLogicByNameThatProjectIdStrConvertProjectIdList(clusterLogicName).stream().findFirst().orElse(null);\n        if (AriusObjUtils.isNull(clusterLogic)) {\n            return Result.buildFail(String.format(\"集群[%s]不存在\", clusterLogicName));\n        }\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogic.getId());\n        if (clusterRegion == null) {\n            return Result.buildFail(String.format(\"集群[%s]未绑定region\", clusterLogic.getId()));\n        }\n        Result<List<ClusterRoleHost>> result = clusterRoleHostService\n                .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        //节点信息列表\n        return Result.buildSucc(result.getData().stream().map(clusterRoleHost->new ClusterNodeInfoVO(clusterRoleHost.getNodeSet(),clusterRoleHost.getRole()))\n                .collect(Collectors.toList()));\n    }\n    @Override\n    public boolean collectNodeSettings(String cluster) throws AdminTaskException {\n        return clusterRoleHostService.collectClusterNodeSettings(cluster);\n    }\n    \n  \n    /**\n     * > 该功能用于删除集群节点，但该节点必须离线且未绑定region\n     *\n     * @param ids 要删除的节点的id\n     * @param projectId 项目编号\n     * @param operator 操作员是执行操作的用户。\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> delete(List<Integer> ids, Integer projectId, String operator) {\n        Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (checkProjectCorrectly.failed()) {\n            return checkProjectCorrectly;\n        }\n    \n        List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService.listById(ids);\n        if (CollectionUtils.isEmpty(clusterRoleHosts)) {\n            return Result.buildSucc();\n        }\n        //1. 校验当前节点是否 bind region, 如果是则不允许下线\n        if (!clusterRoleHosts.stream().allMatch(clusterRoleHost -> Objects.equals(clusterRoleHost.getRegionId(), -1))) {\n            return Result.buildFail(\"当前选中的节点绑定了 region，请先下线 region\");\n        }\n        //2. 检验当前节点是否都离线\n        if (!clusterRoleHosts.stream().allMatch(clusterRoleHost -> Objects.equals(clusterRoleHost.getStatus(),\n                ESClusterNodeStatusEnum.OFFLINE.getCode()))) {\n            return Result.buildFail(\"只可以下线离线状态的节点，当前选中的节点存在非离线状态的节点\");\n        }\n        //3. 下线离线的节点\n        List<String> clusterPhies = clusterRoleHosts.stream().map(ClusterRoleHost::getCluster).distinct()\n                .collect(Collectors.toList());\n        List<ClusterPhy> clusterPhyList = clusterPhyService.listClustersByNames(clusterPhies);\n    \n        boolean delete = clusterRoleHostService.deleteByIds(ids);\n        if (delete) {\n            Map<String, Integer> clusterPhy2ClusterId = ConvertUtil.list2Map(clusterPhyList, ClusterPhy::getCluster,\n                    ClusterPhy::getId);\n            Multimap<String, Long> clusterPhy2NodeIds = ConvertUtil.list2MulMap(clusterRoleHosts,\n                    ClusterRoleHost::getCluster, ClusterRoleHost::getId);\n            Map<Long, String> nodeId2IpMap = ConvertUtil.list2Map(clusterRoleHosts, ClusterRoleHost::getId,\n                    ClusterRoleHost::getIp);\n            for (Entry<String, Integer> clusterPhy2ClusterIdEntry : clusterPhy2ClusterId.entrySet()) {\n                Integer clusterId = clusterPhy2ClusterIdEntry.getValue();\n                String ipStr = clusterPhy2NodeIds.get(clusterPhy2ClusterIdEntry.getKey()).stream()\n                        .map(nodeId2IpMap::get).distinct().collect(Collectors.joining(\",\"));\n                // 2. 操作记录 : 节点下线\n                 operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"下线节点的 ip 列表 ：[%s]\", ipStr), operator, projectId, clusterId,\n                        OperateTypeEnum.PHYSICAL_CLUSTER_NODE_CHANGE);\n            }\n        }\n        return Result.build(delete);\n    }\n\n    /**\n     * @param regionId\n     * @return\n     */\n    @Override\n    public Result<List<ESClusterRoleHostVO>> listClusterRoleHostByRegionId(Long regionId) {\n        ClusterRegion region = clusterRegionService.getRegionById(regionId);\n        if (region == null) {\n            return Result.buildFail(\"region不存在\");\n        }\n        Result<List<ClusterRoleHost>> ret = clusterRoleHostService.listByRegionId(region.getId().intValue());\n        if (ret.failed()) {\n            return Result.buildFail(\"获取host失败\");\n\n        }\n        return Result.buildSucc(ConvertUtil.list2List(ret.getData(), ESClusterRoleHostVO.class));\n    }\n\n    /**\n     * 获取当前平台所有集群节点的机器规格\n     * @return\n     */\n    @Override\n    public Result<List<String>> listAllMachineSpecs() {\n        List<ClusterRoleHost> clusterRoleHostList = clusterRoleHostService.listAllNodeByRole(DATA_NODE.getCode());\n        if(AriusObjUtils.isEmptyList(clusterRoleHostList)){\n            return Result.buildFail(\"当前集群还没有任何节点\");\n        }\n        List<String> machineSpecs = clusterRoleHostList.stream()\n                .filter(clusterRoleHost -> StringUtils.isNotBlank(clusterRoleHost.getMachineSpec()))\n                .map(ClusterRoleHost::getMachineSpec)\n                .distinct().collect(Collectors.toList());\n        machineSpecs.sort(this::machineSpecSort);\n        return Result.buildSucc(machineSpecs);\n    }\n\n    /**************************************** private method ***************************************************/\n\n    /**\n     * 对节点规格（如4c-125g-500g）进行排序展示，方便用户查看选择\n     * @param s1\n     * @param s2\n     * @return\n     */\n    private int machineSpecSort(String s1, String s2) {\n        int c1 = Integer.valueOf(s1.substring(0, s1.indexOf('c')));\n        int c2 = Integer.valueOf(s2.substring(0, s2.indexOf('c')));\n        if(c1 == c2){\n            int g1 = Integer.valueOf(s1.substring(s1.indexOf('c')+2, s1.indexOf('g')));\n            int g2 = Integer.valueOf(s2.substring(s2.indexOf('c')+2, s2.indexOf('g')));\n            if(g1 == g2){\n                int gg1 = Integer.valueOf(s1.substring(s1.indexOf('g')+2, s1.length()-1));\n                int gg2 = Integer.valueOf(s2.substring(s2.indexOf('g')+2, s2.length()-1));\n                if(gg1 == gg2){\n                    return 0;\n                }\n                return gg1 > gg2 ? 1 : -1;\n            }\n            return g1 > g2 ? 1 : -1;\n        }\n        return c1 > c2 ? 1 : -1;\n    }\n\n    private List<ESClusterRoleHostVO> buildClusterRoleHostStats(String cluster,\n                                                                List<ClusterRoleHost> clusterRoleHostList) {\n        List<ESClusterRoleHostVO> roleHostList = ConvertUtil.list2List(clusterRoleHostList, ESClusterRoleHostVO.class);\n        if (CollectionUtils.isNotEmpty(roleHostList)) {\n            Map<String, String> regionMap = roleHostList.stream().map(ESClusterRoleHostVO::getRegionId)\n                .filter(regionId -> null != regionId && regionId > 0).distinct()\n                .map(regionId -> clusterRegionService.getRegionById(regionId.longValue())).filter(Objects::nonNull)\n                .collect(\n                    Collectors.toMap(region -> String.valueOf(region.getId()), ClusterRegion::getName, (r1, r2) -> r1));\n\n            Map<String, Triple<Long, Long, Double>> nodeDiskUsageMap = esClusterNodeService\n                .syncGetNodesDiskUsage(cluster);\n            roleHostList.forEach(vo -> {\n                Optional.ofNullable(regionMap.get(String.valueOf(vo.getRegionId()))).ifPresent(vo::setRegionName);\n                Optional.ofNullable(nodeDiskUsageMap.get(vo.getNodeSet())).ifPresent(triple -> {\n                    vo.setDiskTotal(triple.v1());\n                    vo.setDiskUsage(triple.v2());\n                    vo.setDiskUsagePercent(triple.v3());\n                });\n            });\n        }\n        return roleHostList;\n    }\n\n    private Result<Boolean> baseCheckParamValid(ClusterRegionWithNodeInfoDTO param, OperationEnum operationEnum) {\n        if (null == param) {\n            return Result.buildFail(\"参数为空\");\n        }\n        if (operationEnum.equals(OperationEnum.ADD)) {\n            if (AriusObjUtils.isBlank(param.getName())) {\n                return Result.buildFail(\"region名称不允许为空或者空字符串\");\n            }\n            if (clusterRegionService.isExistByRegionName(param.getName())) {\n                return Result.buildFail(String.format(\"region名称[%s]已经存在\", param.getName()));\n            }\n            if (CollectionUtils.isEmpty(param.getBindingNodeIds())) {\n                return Result.buildFail(\"不允许绑定空region\");\n            }\n        }\n        if (operationEnum.equals(OperationEnum.EDIT)) {\n            if (Objects.isNull(param.getId())) {\n                return Result.buildFail(\"编辑id不能为空\");\n            }\n            if (!clusterRegionService.isExistByRegionId(Math.toIntExact(param.getId()))) {\n                return Result.buildFail(String.format(\"编辑的region %d 不存在\", param.getId()));\n            }\n        }\n\n        if (!clusterPhyService.isClusterExists(param.getPhyClusterName())) {\n            return Result.buildFail(String.format(\"物理集群[%s]不存在\", param.getPhyClusterName()));\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Boolean> editNode2Region(ClusterRegionWithNodeInfoDTO param) throws AdminOperateException {\n       \n        // 校验bindingNodeIds 和 unBindingNodeIds的重复性\n        List<Integer> bindingNodeIds = param.getBindingNodeIds();\n        List<Integer> unBindingNodeIds = param.getUnBindingNodeIds();\n        if (CollectionUtils.isNotEmpty(bindingNodeIds)) {\n            for (Integer bindingNodeId : bindingNodeIds) {\n                if (CollectionUtils.isNotEmpty(unBindingNodeIds) && unBindingNodeIds.contains(bindingNodeId)) {\n                    return Result.buildFail(\"region中绑定节点类别和解绑节点列表不能有相同节点\");\n                }\n            }\n        }\n\n        if (CollectionUtils.isNotEmpty(bindingNodeIds)) {\n            // 绑定node 到指定 region\n            boolean editBingingNodeRegionIdFlag = clusterRoleHostService.editNodeRegionId(bindingNodeIds,\n                param.getId().intValue());\n            if (!editBingingNodeRegionIdFlag) {\n                return Result.buildFail(String.format(\"新增region节点[%s]失败\", bindingNodeIds));\n            }\n        }\n\n        if (CollectionUtils.isNotEmpty(unBindingNodeIds)) {\n            // 解绑node 到指定 region\n            boolean editUnBingingNodeRegionFlag = clusterRoleHostService.editNodeRegionId(unBindingNodeIds, -1);\n            if (!editUnBingingNodeRegionFlag) {\n                return Result.buildFail(String.format(\"删除region节点[%s]失败\", unBindingNodeIds));\n            }\n        }\n        return Result.build(true);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/impl/ClusterPhyManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.DEFAULT_CLUSTER_HEALTH;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.DEFAULT_CLUSTER_IDC;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.JOIN_MASTER_NODE_MIN_NUMBER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum.CLUSTER_PHY;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.EXCLUSIVE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.PRIVATE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.PUBLIC;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.CLIENT_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.DATA_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.MASTER_NODE;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.page.ClusterPhyPageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplatePhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping.TemplatePhyMappingManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.pipeline.PipelineManager;\nimport com.didichuxing.datachannel.arius.admin.common.Triple;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterJoinDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleHostDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterTag;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting.ESClusterGetSettingsAllResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterLogicVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterLogicVOWithProjects;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterPhyVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterRegionVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.PluginVO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.DataCenterEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.RunModeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterConnectionStatus;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterConnectionStatusWithTemplateEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterDynamicConfigsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterDynamicConfigsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterCreateSourceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterImportRuleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ResourceLogicLevelEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.resource.ClusterPhyEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.threadpool.AriusScheduleThreadPool;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleThree;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ClusterUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ESVersionUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESGatewayClient;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpClient;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.ZeusClusterRemoteService;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.base.Strings;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\n\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Consumer;\nimport java.util.function.Predicate;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.ElasticsearchTimeoutException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.transaction.interceptor.TransactionAspectSupport;\n\n/**\n *\n * @author ohushenglin_v\n * @date 2022-05-10\n */\n@Component\npublic class ClusterPhyManagerImpl implements ClusterPhyManager {\n\n    private static final ILog                                    LOGGER                                      = LogFactory\n        .getLog(ClusterPhyManagerImpl.class);\n\n    private static final String                                  NODE_NOT_EXISTS_TIPS                        = \"集群缺少类型为%s的节点\";\n\n    private static final String                                  IP_DUPLICATE_TIPS                           = \"集群ip:%s重复, 请重新输入\";\n    /**\n     * Map< cluster , Triple< diskUsage , diskTotal , diskUsagePercent >>\n     */\n    private static final Map<String, Triple<Long, Long, Double>> CLUSTER_NAME_TO_ES_CLUSTER_STATS_TRIPLE_MAP = Maps\n        .newConcurrentMap();\n    public static final String                                   SEPARATOR_CHARS                             = \",\";\n    private static final String COLD             = \"cold\";\n    public static final  String ZEUS_AGENTS_LIST = \"zeus_agents_list\";\n\n    \n\n    @Autowired\n    private ESGatewayClient                                      esGatewayClient;\n\n    @Autowired\n    private ESTemplateService                                    esTemplateService;\n\n    @Autowired\n    private ClusterPhyService                                    clusterPhyService;\n\n    @Autowired\n    private ClusterLogicService                                  clusterLogicService;\n\n    @Autowired\n    private ClusterRoleService                                   clusterRoleService;\n\n    @Autowired\n    private ClusterRoleHostService                               clusterRoleHostService;\n\n    @Autowired\n    private IndexTemplatePhyService                              indexTemplatePhyService;\n\n    @Autowired\n    private TemplatePhyMappingManager                            templatePhyMappingManager;\n\n    @Autowired\n    private PipelineManager                                      templatePipelineManager;\n\n    @Autowired\n    private IndexTemplateService                                 indexTemplateService;\n\n    @Autowired\n    private TemplatePhyManager                                   templatePhyManager;\n\n    @Autowired\n    private ClusterRegionService                                 clusterRegionService;\n\n    \n\n    @Autowired\n    private ProjectService                                       projectService;\n\n    @Autowired\n    private OperateRecordService                                 operateRecordService;\n\n    @Autowired\n    private ESClusterNodeService                                 esClusterNodeService;\n\n    @Autowired\n    private ESClusterService                                     esClusterService;\n\n    @Autowired\n    private HandleFactory                                        handleFactory;\n\n    @Autowired\n    private AriusScheduleThreadPool                              ariusScheduleThreadPool;\n\n    @Autowired\n    private ESOpClient                                           esOpClient;\n\n    @Autowired\n    private RoleTool                 roleTool;\n    @Autowired\n    private ZeusClusterRemoteService zeusClusterRemoteService;\n    \n    private static final FutureUtil<Void>         FUTURE_UTIL               = FutureUtil.init(\n            \"ClusterPhyManagerImpl\", 20, 40, 100);\n    private static final Cache</*clusterPhy*/String, TupleThree</*dcdrExist*/Boolean,/*pipelineExist*/ Boolean,/*existColdRegion*/ Boolean>> CLUSTER_PHY_DCDR_PIPELINE   = CacheBuilder.newBuilder()\n            .expireAfterWrite(10, TimeUnit.MINUTES).maximumSize(10000).build();\n    private static final Cache</*clusterPhy*/String, ClusterConnectionStatusWithTemplateEnum> CLUSTER_PHY_CONNECTION_ENUM = CacheBuilder.newBuilder()\n            .expireAfterWrite(10, TimeUnit.MINUTES).maximumSize(10000).build();\n    public static final Cache</*zeus_agents_list*/String, /*agents_list*/ List<String>> ZEUS_AGENTS_LIST_CACHE = CacheBuilder.newBuilder()\n            .expireAfterWrite(45, TimeUnit.MINUTES).build();\n    @PostConstruct\n    private void init() {\n        ariusScheduleThreadPool.submitScheduleAtFixedDelayTask(this::refreshClusterDistInfo, 60, 180);\n        ariusScheduleThreadPool.submitScheduleAtFixedDelayTask(this::refreshClusterPhyInfoWithCache, 60, 10 * 60L);\n        ariusScheduleThreadPool.submitScheduleAtFixedDelayTask(this::refreshWhitIpList, 60, 45 * 60L);\n    \n    }\n    \n    /**\n     * 每45分钟全量更新一遍集群\n     */\n    private synchronized void refreshClusterPhyInfoWithCache() {\n    \n        for (String clusterName : clusterPhyService.listClusterNames()) {\n            CLUSTER_PHY_DCDR_PIPELINE.put(clusterName, getDCDRAndPipelineTupleByClusterPhy(clusterName));\n            CLUSTER_PHY_CONNECTION_ENUM.put(clusterName, getClusterConnectionStatus(clusterName));\n        }\n    }\n\n  \n    \n    /**\n     * @param clusterPhy\n     */\n    @Override\n    public TupleThree</*dcdrExist*/Boolean,/*pipelineExist*/ Boolean,/*existColdRegion*/ Boolean> getDCDRAndPipelineAndColdRegionTupleByClusterPhyWithCache(\n            String clusterPhy) {\n        try {\n           return CLUSTER_PHY_DCDR_PIPELINE.get(\n                clusterPhy,()->getDCDRAndPipelineTupleByClusterPhy(clusterPhy));\n        }catch (Exception e){\n            return Tuples.of(false, false, false);\n        }\n    }\n    \n    @Override\n    public ClusterConnectionStatusWithTemplateEnum getClusterConnectionStatusWithCache(String clusterPhy) {\n        try {\n            return CLUSTER_PHY_CONNECTION_ENUM.get(clusterPhy, () -> getClusterConnectionStatus(clusterPhy));\n        } catch (Exception e) {\n            return ClusterConnectionStatusWithTemplateEnum.DISCONNECTED;\n        }\n    }\n    \n   \n    \n    @Override\n    public boolean copyMapping(String cluster, int retryCount) {\n        // 获取物理集群下的所有物理模板\n        List<IndexTemplatePhy> physicals = indexTemplatePhyService.getNormalTemplateByCluster(cluster);\n        if (CollectionUtils.isEmpty(physicals)) {\n            LOGGER.info(\"class=ESClusterPhyServiceImpl||method=copyMapping||cluster={}||msg=copyMapping no template\",\n                cluster);\n            return true;\n        }\n\n        int succeedCount = 0;\n        // 遍历物理模板，copy mapping\n        for (IndexTemplatePhy physical : physicals) {\n            try {\n                // 获取物理模板对应的逻辑模板\n                IndexTemplate templateLogic = indexTemplateService.getLogicTemplateById(physical.getLogicId());\n                // 同步索引的mapping到模板\n                Result<MappingConfig> result = templatePhyMappingManager.syncMappingConfig(cluster, physical.getName(),\n                    physical.getExpression(), templateLogic.getDateFormat());\n\n                if (result.success()) {\n                    succeedCount++;\n                    if (!setTemplateSettingSingleType(cluster, physical.getName())) {\n                        LOGGER.error(\n                            \"class=ESClusterPhyServiceImpl||method=copyMapping||errMsg=failedUpdateSingleType||cluster={}||template={}\",\n                            cluster, physical.getName());\n                    }\n                } else {\n                    LOGGER.warn(\n                        \"class=ESClusterPhyServiceImpl||method=copyMapping||cluster={}||template={}||msg=copyMapping fail\",\n                        cluster, physical.getName());\n                }\n            } catch (Exception e) {\n                LOGGER.error(\"class=ESClusterPhyServiceImpl||method=copyMapping||errMsg={}||cluster={}||template={}\",\n                    e.getMessage(), cluster, physical.getName(), e);\n            }\n        }\n\n        return succeedCount * 1.0 / physicals.size() > 0.7;\n    }\n\n    @Override\n    public void syncTemplateMetaData(String cluster, int retryCount) {\n        // 获取物理集群下的所有物理模板\n        List<IndexTemplatePhy> physicals = indexTemplatePhyService.getNormalTemplateByCluster(cluster);\n        if (CollectionUtils.isEmpty(physicals)) {\n            LOGGER.info(\n                \"class=ESClusterPhyServiceImpl||method=syncTemplateMetaData||cluster={}||msg=syncTemplateMetaData no template\",\n                cluster);\n            return;\n        }\n\n        // 遍历物理模板\n        for (IndexTemplatePhy physical : physicals) {\n            try {\n                // 同步模板元数据到ES集群（修改ES集群中的模板）\n                templatePhyManager.syncMeta(physical.getId(), retryCount);\n                // 同步最新元数据到ES集群pipeline\n                templatePipelineManager.syncPipeline(physical.getLogicId());\n            } catch (Exception e) {\n                LOGGER.error(\n                    \"class=ESClusterPhyServiceImpl||method=syncTemplateMetaData||errMsg={}||cluster={}||template={}\",\n                    e.getMessage(), cluster, physical.getName(), e);\n            }\n        }\n    }\n\n    @Override\n    public boolean isClusterExists(String clusterName) {\n        return clusterPhyService.isClusterExists(clusterName);\n    }\n\n    @Override\n    public List<ClusterPhyVO> listClusterPhys(ClusterPhyDTO param) {\n        List<ClusterPhy> phyClusters = clusterPhyService.listClustersByCondt(param);\n        return buildClusterInfo(phyClusters);\n    }\n\n    @Override\n    public List<ClusterPhyVO> buildClusterInfo(List<ClusterPhy> clusterPhyList) {\n        if (CollectionUtils.isEmpty(clusterPhyList)) {\n            return Lists.newArrayList();\n        }\n\n        List<ClusterPhyVO> clusterPhyVOList = ConvertUtil.list2List(clusterPhyList, ClusterPhyVO.class);\n\n        List<Integer> clusterIds = clusterPhyVOList.stream().map(ClusterPhyVO::getId).collect(Collectors.toList());\n        Map<Long, List<ClusterRoleInfo>> roleListMap = clusterRoleService.getAllRoleClusterByClusterIds(clusterIds);\n        //3. 设置集群基本统计信息：磁盘使用信息\n        long timeForBuildClusterDiskInfo = System.currentTimeMillis();\n        List<String> ipList = ipListWithCache();\n        final List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService.listAllNode();\n        final Map<String, List<String>> clusterPhy2IpListMap = ConvertUtil.list2MapOfList(clusterRoleHosts,\n                ClusterRoleHost::getCluster, ClusterRoleHost::getIp);\n        for (ClusterPhyVO clusterPhyVO : clusterPhyVOList) {\n            FUTURE_UTIL.runnableTask(\n                            () -> buildClusterRole(clusterPhyVO, roleListMap.get(clusterPhyVO.getId().longValue())))\n                    // 判断集群是否支持 zeus，并设置对应的参数值\n                    .runnableTask(() -> buildSupportZeusByClusterPhy(clusterPhyVO,\n                            clusterPhy2IpListMap.get(clusterPhyVO.getCluster()), ipList))\n            \n            ;\n        }\n        buildClusterPhyWithLogicAndRegion(clusterPhyVOList);\n        FUTURE_UTIL.waitExecute();\n        LOGGER.info(\n            \"class=ClusterPhyManagerImpl||method=buildClusterInfo||msg=consumed build cluster belongProjectIds and ProjectName time is {} ms\",\n            System.currentTimeMillis() - timeForBuildClusterDiskInfo);\n\n        return clusterPhyVOList;\n    }\n\n    private long buildClusterPhyWithLogicAndRegion(List<ClusterPhyVO> clusterPhyVOList) {\n        List<ClusterRegion> regions = clusterRegionService.listRegionByPhyClusterNames(\n            clusterPhyVOList.stream().map(ClusterPhyVO::getCluster).distinct().collect(Collectors.toList()));\n        Map<String, Set<Long>> phyCluster2logicClusterIds = Maps.newHashMap();\n        final List<ProjectBriefVO> projectBriefList = projectService.getProjectBriefList();\n        final Map<Integer, String> projectId2ProjectNameMap = ConvertUtil.list2Map(projectBriefList, ProjectBriefVO::getId,\n                ProjectBriefVO::getProjectName);\n        Map<Long,  List<ClusterLogicVO>> logicClusterId2LogicClusterList = Maps.newHashMap();\n        Map<Long, ClusterRegionVO> logicClusterId2Region = Maps.newHashMap();\n        List<Long> logicIds = Lists.newArrayList();\n        regions.stream()\n            .filter(region -> StringUtils.isNotBlank(region.getPhyClusterName())\n                              && StringUtils.isNotBlank(region.getLogicClusterIds())\n                              && !AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID.equals(region.getLogicClusterIds()))\n            .forEach(region -> {\n                String idStr = region.getLogicClusterIds();\n                List<Long> list = Lists.newArrayList();\n                for (String id : StringUtils.split(idStr, SEPARATOR_CHARS)) {\n                    if (StringUtils.isNumeric(id)) {\n                        list.add(Long.valueOf(id));\n                    }\n                }\n                Set<Long> ids = phyCluster2logicClusterIds.getOrDefault(region.getPhyClusterName(), Sets.newHashSet());\n                ids.addAll(list);\n                phyCluster2logicClusterIds.put(region.getPhyClusterName(), ids);\n                list.forEach(id -> logicClusterId2Region.put(id, ConvertUtil.obj2Obj(region, ClusterRegionVO.class, regionVO -> regionVO.setClusterName(region.getPhyClusterName()))));\n                logicIds.addAll(list);\n            });\n        if (CollectionUtils.isNotEmpty(logicIds)) {\n            List<ClusterLogic> clusterLogicList = clusterLogicService.getClusterLogicListByIds(logicIds);\n    \n            logicClusterId2LogicClusterList = ConvertUtil.list2MapOfList(clusterLogicList, ClusterLogic::getId,\n                    clusterLogic -> ConvertUtil.obj2Obj(clusterLogic, ClusterLogicVO.class,\n                            clusterLogicVO -> clusterLogicVO.setProjectName(\n                                    projectId2ProjectNameMap.get(clusterLogicVO.getProjectId()))));\n        }\n        \n        //3. 设置集群基本统计信息：磁盘使用信息\n        long timeForBuildClusterDiskInfo = System.currentTimeMillis();\n        for (ClusterPhyVO clusterPhyVO : clusterPhyVOList) {\n            Set<Long> set = phyCluster2logicClusterIds.getOrDefault(clusterPhyVO.getCluster(), Sets.newHashSet());\n            Map<Long, List<ClusterLogicVO>> finalLogicClusterId2Vo = logicClusterId2LogicClusterList;\n            FUTURE_UTIL.runnableTask(()-> {\n                set.forEach(id -> {\n                    List<ClusterLogicVO> clusterLogicVOList = finalLogicClusterId2Vo.get(id);\n                    if (CollectionUtils.isNotEmpty(clusterLogicVOList)) {\n                        List<String> projectNames = clusterLogicVOList.stream().map(ClusterLogicVO::getProjectName).collect(Collectors.toList());\n                        ClusterLogicVOWithProjects clusterLogicVOWithProjects = ConvertUtil.obj2Obj(clusterLogicVOList.get(0),\n                                ClusterLogicVOWithProjects.class, cp -> cp.setProjectNameList(projectNames));\n                        clusterPhyVO.addLogicCluster(clusterLogicVOWithProjects, logicClusterId2Region.get(id));\n                    }\n        \n                });\n                Optional.ofNullable(clusterPhyVO.getLogicClusterAndRegionList())\n                        .map(logicClusterAndRegionList -> logicClusterAndRegionList.stream().map(Tuple::getV1).map(ClusterLogicVOWithProjects::getName).distinct().collect(Collectors.toList()))\n                        .ifPresent(clusterPhyVO::setBindLogicCluster);\n            });\n        }\n        FUTURE_UTIL.waitExecute();\n        return timeForBuildClusterDiskInfo;\n    }\n\n    @Override\n    public ClusterPhyVO getClusterPhyOverview(Integer clusterId, Integer currentProjectId) {\n        // 获取基本信息\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(clusterId);\n        if (clusterPhy == null) {\n            return new ClusterPhyVO();\n        }\n\n        ClusterPhyVO clusterPhyVO = ConvertUtil.obj2Obj(clusterPhy, ClusterPhyVO.class);\n        // 构建overView信息\n        buildPhyCluster(clusterPhyVO,clusterPhy);\n        return clusterPhyVO;\n    }\n\n    @Override\n    public Result<List<String>> listCanBeAssociatedRegionOfClustersPhys(Integer clusterLogicType, Long clusterLogicId) {\n        if (!ClusterResourceTypeEnum.isExist(clusterLogicType)) {\n            return Result.buildParamIllegal(\"集群资源类型非法\");\n        }\n        List<String> clusters = Lists.newArrayList();\n        ClusterLogic clusterLogic =\n                clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(clusterLogicId );\n        if (clusterLogic == null) {\n            return Result.buildFail(\"选定的逻辑集群不存在\");\n        }\n\n        ClusterRegion logicClusterRegions = clusterRegionService.getRegionByLogicClusterId(clusterLogic.getId());\n        if (null != logicClusterRegions) {\n            return Result.buildSucc(clusters);\n        }\n        return listCanBeAssociatedClustersPhys(clusterLogicType);\n    }\n\n    @Override\n    public Result<List<String>> listCanBeAssociatedClustersPhys(Integer clusterLogicType) {\n        if (!ClusterResourceTypeEnum.isExist(clusterLogicType)) {\n            return Result.buildParamIllegal(\"集群资源类型非法\");\n        }\n\n        List<String> clusters = Lists.newArrayList();\n        ClusterPhyDTO clusterPhyDTO = new ClusterPhyDTO();\n        clusterPhyDTO.setResourceType(clusterLogicType);\n        List<ClusterPhy> list = clusterPhyService.listClustersByCondt(clusterPhyDTO);\n\n        if (PUBLIC.getCode() == clusterLogicType) {\n            //共享\n            clusters = list.stream().map(ClusterPhy::getCluster).collect(Collectors.toList());\n        } else if (EXCLUSIVE.getCode() == clusterLogicType) {\n            //独享，需要查询是否有未绑定的region和节点\n            clusters = list.stream().filter(cluster -> {\n                List<ClusterRegion> regions = clusterRegionService.listPhyClusterRegions(cluster.getCluster());\n                if (regions.stream().anyMatch(region -> !clusterRegionService.isRegionBound(region))) {\n                    return true;\n                }\n                List<ClusterRoleHost> roleHostList = clusterRoleHostService\n                    .getByRoleAndClusterId(Long.valueOf(cluster.getId()), DATA_NODE.getDesc());\n                return roleHostList.stream().anyMatch(node -> node.getRegionId() == -1);\n            }).map(ClusterPhy::getCluster).collect(Collectors.toList());\n        } else if (PRIVATE.getCode() == clusterLogicType) {\n            //独立，未绑定逻辑集群\n            clusters = list.stream().filter(cluster -> {\n                Set<Long> logicIds = clusterRegionService.getLogicClusterIdByPhyClusterId(cluster.getId());\n                return CollectionUtils.isEmpty(logicIds);\n            }).map(ClusterPhy::getCluster).collect(Collectors.toList());\n        }\n\n        return Result.buildSucc(clusters);\n    }\n\n    private final Consumer<ESClusterRoleHostDTO> roleClusterHostsTrimHostnameAndPort = esClusterRoleHostDTO -> {\n        esClusterRoleHostDTO.setCluster(StringUtils.trim(esClusterRoleHostDTO.getCluster()));\n        esClusterRoleHostDTO.setHostname(StringUtils.trim(esClusterRoleHostDTO.getHostname()));\n        esClusterRoleHostDTO.setIp(StringUtils.trim(esClusterRoleHostDTO.getIp()));\n        esClusterRoleHostDTO.setPort(StringUtils.trim(esClusterRoleHostDTO.getPort()));\n\n    };\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<ClusterPhyVO> joinCluster(ClusterJoinDTO param, String operator, Integer projectId) {\n        if (param.getProjectId() == null) {\n            param.setProjectId(projectId);\n        }\n        //这里其实是需要一个内置trim 用来保证传输进行的roleClusterHosts是正确的\n        param.getRoleClusterHosts().forEach(roleClusterHostsTrimHostnameAndPort);\n        Result<Void> checkResult = checkClusterJoin(param, operator);\n        if (checkResult.failed()) {\n            return Result.buildFail(checkResult.getMessage());\n        }\n        String esClientHttpAddressesStr = clusterRoleHostService\n            .buildESClientHttpAddressesStr(param.getRoleClusterHosts());\n        for (ESClusterRoleHostDTO roleClusterHost : param.getRoleClusterHosts()) {\n            if (roleClusterHost.getRegionId() == null) {\n                roleClusterHost.setRegionId(-1);\n            }\n        }\n        Result<Void> initResult = initClusterJoin(param, esClientHttpAddressesStr);\n        if (initResult.failed()) {\n            return Result.buildFail(initResult.getMessage());\n        }\n\n        try {\n\n            // 1.保存物理集群信息(集群、角色、节点)\n            Result<ClusterPhyVO> saveClusterResult = saveClusterPhy(param, operator);\n\n            if (saveClusterResult.failed()) {\n                throw new AdminOperateException(saveClusterResult.getMessage());\n            } else {\n    \n                postProcessingForClusterJoin(param);\n                SpringTool.publish(new ClusterPhyEvent(param.getCluster(), operator));\n                 operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"集群接入：%s\", saveClusterResult.getData().getCluster()), operator,\n                        AuthConstant.SUPER_PROJECT_ID, saveClusterResult.getData().getId(),\n                        OperateTypeEnum.PHYSICAL_CLUSTER_JOIN);\n            }\n\n            return saveClusterResult;\n        } catch (AdminOperateException | ElasticsearchTimeoutException e) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=clusterJoin||clusterPhy={}||es operation errMsg={}\",\n                param.getCluster(), e);\n            // 这里必须显示事务回滚\n            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();\n            return Result.buildFail(\"接入失败, 请重新尝试接入集群,多次重试不成功,请联系管理员\");\n        } catch (NullPointerException e) {\n            LOGGER.error(\n                \"class=ClusterPhyManagerImpl||method=clusterJoin||clusterPhy={}||join cluster operation null point exception errMsg={}\",\n                param.getCluster(), e);\n            // 这里必须显示事务回滚\n            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();\n            return Result.buildFail(\"接入集群发生致命错误,请联系管理员\");\n        } catch (Exception e) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=clusterJoin||clusterPhy={}||errMsg={}\",\n                param.getCluster(), e);\n            // 这里必须显示事务回滚\n            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();\n            return Result.buildFail(\"操作失败,请联系管理员\");\n        }\n\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> deleteClusterJoin(Integer clusterId, String operator, Integer projectId) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(clusterId);\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildParamIllegal(\"物理集群不存在\");\n        }\n\n        try {\n            doDeleteClusterJoin(clusterPhy, operator, projectId);\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=deleteClusterJoin||errMsg={}||e={}||clusterId={}\",\n                e.getMessage(), e, clusterId);\n            // 这里显示回滚处理特殊异常场景\n            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();\n            return Result.buildFail(e.getMessage());\n        }\n         operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"删除接入集群：%s\", clusterPhy.getCluster()), operator, projectId, clusterId,\n                OperateTypeEnum.PHYSICAL_CLUSTER_JOIN);\n    \n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<List<PluginVO>> listPlugins(String cluster) {\n        return Result.buildSucc(ConvertUtil.list2List(clusterPhyService.listClusterPlugins(cluster), PluginVO.class));\n    }\n\n    @Override\n    public Result<Map<ClusterDynamicConfigsTypeEnum, Map<String, Object>>> getPhyClusterDynamicConfigs(String cluster)\n            throws ESOperateException {\n        if (!isClusterExists(cluster)) {\n            return Result.buildFail(String.format(\"集群[%s]不存在\", cluster));\n        }\n\n        ESClusterGetSettingsAllResponse clusterSetting = esClusterService.syncGetClusterSetting(cluster);\n        if (null == clusterSetting) {\n            return Result.buildFail(String.format(\"获取集群动态配置信息失败, 请确认是否集群[%s]是否正常\", cluster));\n        }\n\n        // 构建defaults和persistent的配置信息，transient中的配置信息并非是动态配置的内容\n        Map<String, Object> clusterConfigMap = new HashMap<>(16);\n        clusterConfigMap.putAll(ConvertUtil.directFlatObject(clusterSetting.getDefaults()));\n        clusterConfigMap.putAll(ConvertUtil.directFlatObject(clusterSetting.getPersistentObj()));\n\n        // Map<ClusterDynamicConfigsTypeEnum, Map<String, Object>>中Map的String表示的是动态配置的字段，例如cluster.routing.allocation.awareness.attributes\n        // Object则是对应动态配置字段的值\n        Map<ClusterDynamicConfigsTypeEnum, Map<String, Object>> clusterDynamicConfigsTypeEnumMapMap = initClusterDynamicConfigs();\n        for (ClusterDynamicConfigsEnum param : ClusterDynamicConfigsEnum.valuesWithoutUnknown()) {\n            Map<String, Object> dynamicConfig = clusterDynamicConfigsTypeEnumMapMap\n                .get(param.getClusterDynamicConfigsType());\n            dynamicConfig.put(param.getName(), clusterConfigMap.get(param.getName()));\n        }\n\n        return Result.buildSucc(clusterDynamicConfigsTypeEnumMapMap);\n    }\n\n    @Override\n    public Result<Boolean> updatePhyClusterDynamicConfig(ClusterSettingDTO param, String operator, Integer projectId)\n            throws ESOperateException {\n        final Result<Void> resultCheck = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (resultCheck.failed()) {\n            return Result.buildFail(resultCheck.getMessage());\n        }\n        final Result<Map<ClusterDynamicConfigsTypeEnum, Map<String, Object>>> beforeChangeConfigs = getPhyClusterDynamicConfigs(\n            param.getClusterName());\n        String changeKey = param.getKey();\n        Object beforeValue = beforeChangeConfigs.getData().values().stream()\n            .filter(\n                clusterDynamicConfigsTypeEnumMapValues -> clusterDynamicConfigsTypeEnumMapValues.containsKey(changeKey))\n            .map(clusterDynamicConfigsTypeEnumMapValues -> clusterDynamicConfigsTypeEnumMapValues.get(changeKey))\n            .findFirst().orElse(\"\");\n        Object changeValue = param.getValue();\n        final ClusterPhy clusterByName = clusterPhyService.getClusterByName(param.getClusterName());\n        final Result<Boolean> result = clusterPhyService.updatePhyClusterDynamicConfig(param);\n        if (result.success()) {\n             operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"%s:%s->%s\", changeKey, beforeValue, changeValue), operator,\n                    AuthConstant.SUPER_PROJECT_ID, clusterByName.getId(),\n                    OperateTypeEnum.PHYSICAL_CLUSTER_DYNAMIC_CONF_CHANGE);\n        }\n        return result;\n    }\n\n    @Override\n    public Result<Set<String>> getRoutingAllocationAwarenessAttributes(String cluster) {\n        return Result.buildSucc(clusterPhyService.getRoutingAllocationAwarenessAttributes(cluster));\n    }\n\n    @Override\n    public List<String> listClusterPhyNameByProjectId(Integer projectId) {\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            //超级projectId返回所有的集群\n            List<ClusterPhy> phyList = clusterPhyService.listAllClusters();\n            return phyList.stream().map(ClusterPhy::getCluster).distinct().sorted(Comparator.naturalOrder())\n                .collect(Collectors.toList());\n        }\n        // 非超级管理员，获取拥有的逻辑集群对应的物理集群列表\n        List<ClusterLogic> clusterLogicList = clusterLogicService.getOwnedClusterLogicListByProjectId(projectId);\n        //项目下的有管理权限逻辑集群会关联多个物理集群\n        List<ClusterRegion> regions = clusterRegionService.getClusterRegionsByLogicIds(\n            clusterLogicList.stream().map(ClusterLogic::getId).collect(Collectors.toList()));\n        return regions.stream().map(ClusterRegion::getPhyClusterName).distinct().sorted(Comparator.naturalOrder())\n            .collect(Collectors.toList());\n    }\n    \n    /**\n     * @param clusterPhy\n     * @return\n     */\n    @Override\n    public Result<ClusterPhy> getClusterByName(String clusterPhy) {\n        return Result.buildSucc(clusterPhyService.getClusterByName(clusterPhy));\n    }\n    \n    /**\n     * @param cluster\n     * @param remoteCluster\n     * @return\n     */\n    @Override\n    public boolean ensureDCDRRemoteCluster(String cluster, String remoteCluster) throws ESOperateException {\n        return clusterPhyService.ensureDCDRRemoteCluster(cluster,remoteCluster);\n    }\n    \n    @Override\n    public Result<List<String>> listClusterPhyNameByResourceType(Integer clusterResourceType, Integer projectId) {\n\n        if (null != clusterResourceType && !ClusterResourceTypeEnum.isExist(clusterResourceType)) {\n            return Result.buildParamIllegal(\"集群资源类型非法\");\n        }\n        List<String> clusters;\n        List<ClusterPhy> clusterPhyList;\n        if (null != clusterResourceType) {\n            ClusterPhyDTO clusterPhyDTO = new ClusterPhyDTO();\n            clusterPhyDTO.setResourceType(clusterResourceType);\n            clusterPhyList = clusterPhyService.listClustersByCondt(clusterPhyDTO);\n\n        } else {\n            clusterPhyList = clusterPhyService.listAllClusters();\n        }\n        Set<String> clusterNameSet = ConvertUtil.list2Set(clusterPhyList, ClusterPhy::getCluster);\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            clusters = clusterPhyList.stream().map(ClusterPhy::getCluster).distinct().sorted(Comparator.naturalOrder())\n                .collect(Collectors.toList());\n        } else {\n            List<ClusterLogic> clusterLogicList = clusterLogicService.getOwnedClusterLogicListByProjectId(projectId);\n            //项目下的有管理权限逻辑集群会关联多个物理集群\n            List<ClusterRegion> regions = clusterRegionService.getClusterRegionsByLogicIds(\n                clusterLogicList.stream().map(ClusterLogic::getId).collect(Collectors.toList()));\n            clusters = regions.stream().map(ClusterRegion::getPhyClusterName).distinct()\n                .filter(clusterNameSet::contains).sorted(Comparator.naturalOrder()).collect(Collectors.toList());\n        }\n        return Result.buildSucc(clusters);\n    }\n    \n    @Override\n    public Result<List<String>> getTemplateSameVersionClusterNamesByTemplateId(Integer projectId, Integer templateId) {\n        List<String> clusterPhyNameList = listClusterPhyNameByProjectId(projectId);\n        // No permission, cut branches and return\n        if (CollectionUtils.isEmpty(clusterPhyNameList)) {\n            return Result.buildSucc();\n        }\n\n        IndexTemplateWithPhyTemplates logicTemplateWithPhysicals = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(templateId);\n        if (null == logicTemplateWithPhysicals) {\n            return Result.buildFail(String.format(\"templateId[%s] is not exist\", templateId));\n        }\n\n        IndexTemplatePhy masterPhyTemplate = logicTemplateWithPhysicals.getMasterPhyTemplate();\n        if (null == masterPhyTemplate) {\n            return Result.buildFail(String.format(\"the physicals of templateId[%s] is empty\", templateId));\n        }\n\n        String cluster = masterPhyTemplate.getCluster();\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(cluster);\n        if (null == clusterPhy) {\n            return Result.buildFail(String.format(\"the cluster[%s] from templateId[%s] is empty\", cluster, templateId));\n        }\n        \n        String esVersion = clusterPhy.getEsVersion();\n\n        List<ClusterPhy> clusterPhies = clusterPhyService.listAllClusters();\n\n        Predicate<ClusterPhy> matchingSameVersionESVersionPredicate =\n                cp -> ESVersionUtil.compareBigVersionConsistency(esVersion,cp.getEsVersion());\n        List<String> sameVersionClusterNameList = clusterPhies.stream().filter(Objects::nonNull)\n                .filter(r-> !ClusterHealthEnum.UNKNOWN.getCode().equals(r.getHealth()))\n            .filter(r -> clusterPhyNameList.contains(r.getCluster()))\n            .filter(rCluster -> !StringUtils.equals(logicTemplateWithPhysicals.getMasterPhyTemplate().getCluster(),\n                rCluster.getCluster()))\n            .filter(matchingSameVersionESVersionPredicate).map(ClusterPhy::getCluster)\n                .distinct()\n            .collect(Collectors.toList());\n\n        return Result.buildSucc(sameVersionClusterNameList);\n    }\n    \n    /**\n     * @param projectId\n     * @param templateId\n     * @return\n     */\n    @Override\n    public Result<List<String>> getTemplateSameVersionClusterNamesByTemplateIdExistDCDR(Integer projectId,\n                                                                                        Integer templateId) {\n        final Result<List<String>> clusterPhyListRes = getTemplateSameVersionClusterNamesByTemplateId(projectId,\n                templateId);\n        if (clusterPhyListRes.failed()) {\n            return clusterPhyListRes;\n        }\n        final List<String> existDCDRPluginClusterPhyList = clusterPhyListRes.getData().stream()\n                .filter(clusterPhy -> Boolean.TRUE.equals(\n                        getDCDRAndPipelineAndColdRegionTupleByClusterPhyWithCache(clusterPhy).v1))\n                .collect(Collectors.toList());\n        return Result.buildSucc(existDCDRPluginClusterPhyList);\n    }\n    \n    @Override\n    public List<String> listClusterPhyNodeName(String clusterPhyName) {\n        if (null == clusterPhyName) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=getAppClusterPhyNodeNames||errMsg=集群名称为空\");\n            return Lists.newArrayList();\n        }\n        return esClusterNodeService.syncGetNodeNames(clusterPhyName);\n    }\n\n    @Override\n    public List<String> listNodeNameByProjectId(Integer projectId) {\n        List<String> appAuthNodeNames = Lists.newCopyOnWriteArrayList();\n\n        List<String> appClusterPhyNames = listClusterPhyNameByProjectId(projectId);\n        appClusterPhyNames\n            .forEach(clusterPhyName -> appAuthNodeNames.addAll(esClusterNodeService.syncGetNodeNames(clusterPhyName)));\n\n        return appAuthNodeNames;\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Boolean> deleteCluster(Integer clusterPhyId, String operator, Integer projectId) {\n        if (!roleTool.isAdmin(operator) || !AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            return Result.buildFail(\"当前登录人或项目没有权限进行该操作！\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(clusterPhyId);\n        if (null == clusterPhy) {\n            return Result.buildFail(String.format(\"物理集群Id[%s]不存在\", clusterPhyId));\n        }\n\n        Set<Long> clusterLogicIdList = clusterRegionService.getLogicClusterIdByPhyClusterId(clusterPhyId);\n        if (CollectionUtils.isNotEmpty(clusterLogicIdList)) {\n            List<ClusterLogic> clusterLogicList = clusterLogicService\n                .getClusterLogicListByIds(Lists.newArrayList(clusterLogicIdList));\n            return Result.buildFail(String.format(\"物理集群[%s]和逻辑集群[%s]关联\", clusterPhy.getCluster(),\n                ConvertUtil.list2String(Lists.newArrayList(clusterLogicList), \",\", ClusterLogic::getName)));\n        }\n\n        List<String> templatePhyNameList = indexTemplatePhyService.getNormalTemplateByCluster(clusterPhy.getCluster())\n            .stream().map(IndexTemplatePhy::getName).collect(Collectors.toList());\n        if (CollectionUtils.isNotEmpty(templatePhyNameList)) {\n            return Result.buildFail(String.format(\"物理集群[%s]中已经存在模板[%s]\", clusterPhy.getCluster(),\n                ListUtils.strList2String(templatePhyNameList)));\n        }\n\n        Result<Boolean> deleteClusterResult = deleteClusterInner(clusterPhyId, projectId);\n        if (deleteClusterResult.failed()) {\n            return Result.buildFrom(deleteClusterResult);\n        }\n\n        SpringTool.publish(new ClusterPhyEvent(clusterPhy.getCluster(), operator));\n         operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"删除集群：%s\", clusterPhy.getCluster()), operator,\n                AuthConstant.SUPER_PROJECT_ID, clusterPhyId, OperateTypeEnum.PHYSICAL_CLUSTER_OFFLINE);\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    public Result<Boolean> addCluster(ClusterPhyDTO param, String operator, Integer projectId) {\n        Result<Boolean> result = clusterPhyService.createCluster(param, operator);\n\n        if (result.success()) {\n            SpringTool.publish(new ClusterPhyEvent(param.getCluster(), operator));\n             operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"新建集群：%s\", param.getCluster()), operator, projectId, param.getId(),\n                    OperateTypeEnum.PHYSICAL_CLUSTER_NEW);\n        }\n        return result;\n    }\n\n    @Override\n    public Result<Boolean> editCluster(ClusterPhyDTO param, String operator) {\n        final ClusterPhy oldClusterPhy = clusterPhyService.getClusterById(param.getId());\n        final Result<Boolean> result = clusterPhyService.editCluster(param, operator);\n        if (result.success()) {\n\n            if (!StringUtils.equals(oldClusterPhy.getDesc(), param.getDesc())) {\n                 operateRecordService.saveOperateRecordWithManualTrigger(\n                        String.format(\"%s, 修改集群描述:%s-->%s\", oldClusterPhy.getCluster(), oldClusterPhy.getDesc(),\n                                param.getDesc()), operator, AuthConstant.SUPER_PROJECT_ID, param.getId(),\n                        OperateTypeEnum.PHYSICAL_CLUSTER_INFO_MODIFY);\n            }\n\n        }\n        return result;\n    }\n\n    @Override\n    public PaginationResult<ClusterPhyVO> pageGetClusterPhys(ClusterPhyConditionDTO condition,\n                                                             Integer projectId) throws NotFindSubclassException {\n        BaseHandle baseHandle = handleFactory.getByHandlerNamePer(CLUSTER_PHY.getPageSearchType());\n        if (baseHandle instanceof ClusterPhyPageSearchHandle) {\n            ClusterPhyPageSearchHandle pageSearchHandle = (ClusterPhyPageSearchHandle) baseHandle;\n            return pageSearchHandle.doPage(condition, projectId);\n        }\n\n        LOGGER.warn(\n            \"class=ClusterPhyManagerImpl||method=pageGetConsoleClusterVOS||msg=failed to get the ClusterPhyPageSearchHandle\");\n\n        return PaginationResult.buildFail(\"分页获取物理集群信息失败\");\n    }\n\n    @Override\n    public Result<List<String>> listClusterPhyNameBySuperApp(Integer projectId) {\n        List<String> names = Lists.newArrayList();\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            names.addAll(clusterPhyService.listClusterNames());\n        } else {\n            return Result.buildFail(\"非超级项目，不能查看物理集群列表\");\n        }\n        if (names.size()==0){\n            return Result.buildFail(\"超级项目无集群信息，请前往集群管理-->物理集群，进行新建集群或者接入集群。\");\n        }\n        return Result.buildSucc(names);\n    }\n\n    /**\n     * 构建用户控制台统计信息: 集群使用率\n     */\n    @Override\n    public void buildPhyClusterStatics(ClusterPhyVO cluster) {\n        try {\n            Triple<Long, Long, Double> esClusterStaticInfoTriple = getESClusterStaticInfoTriple(cluster.getCluster());\n            cluster.setDiskTotal(esClusterStaticInfoTriple.v1());\n            cluster.setDiskUsage(esClusterStaticInfoTriple.v2());\n            cluster.setDiskUsagePercent(esClusterStaticInfoTriple.v3());\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ClusterPhyManagerImpl||method=buildPhyClusterResourceUsage||logicClusterId={}\",\n                cluster.getId(), e);\n        }\n    }\n\n    @Override\n    public void buildClusterRole(ClusterPhyVO cluster) {\n        try {\n            List<ClusterRoleInfo> clusterRoleInfos = clusterRoleService.getAllRoleClusterByClusterId(cluster.getId());\n\n            buildClusterRole(cluster, clusterRoleInfos);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ClusterPhyManagerImpl||method=buildClusterRole||logicClusterId={}\", cluster.getId(), e);\n        }\n    }\n\n    @Override\n    public void buildClusterRole(ClusterPhyVO cluster, List<ClusterRoleInfo> clusterRoleInfos) {\n        try {\n            List<ESClusterRoleVO> roleClusters = ConvertUtil.list2List(clusterRoleInfos, ESClusterRoleVO.class);\n\n            List<Long> roleClusterIds = roleClusters.stream().map(ESClusterRoleVO::getId).collect(Collectors.toList());\n            Map<Long, List<ClusterRoleHost>> roleIdsMap = clusterRoleHostService.getByRoleClusterIds(roleClusterIds);\n\n            for (ESClusterRoleVO esClusterRoleVO : roleClusters) {\n                List<ClusterRoleHost> clusterRoleHosts = roleIdsMap.get(esClusterRoleVO.getId());\n                List<ESClusterRoleHostVO> esClusterRoleHosts = ConvertUtil.list2List(clusterRoleHosts,\n                    ESClusterRoleHostVO.class);\n                esClusterRoleVO.setEsClusterRoleHostVO(esClusterRoleHosts);\n            }\n\n            cluster.setEsClusterRoleVOS(roleClusters);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ClusterPhyManagerImpl||method=buildClusterRole||logicClusterId={}\", cluster.getId(), e);\n        }\n    }\n\n    @Override\n    public boolean updateClusterHealth(String clusterPhyName, String operator) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterPhyName);\n        if (null == clusterPhy) {\n            LOGGER.warn(\n                \"class=ClusterPhyManagerImpl||method=updateClusterHealth||clusterPhyName={}||msg=clusterPhy is empty\",\n                clusterPhyName);\n            return false;\n        }\n\n        ClusterPhyDTO esClusterDTO = new ClusterPhyDTO();\n        ClusterHealthEnum clusterHealthEnum = null;\n        try {\n            clusterHealthEnum = esClusterService.syncGetClusterHealthEnum(clusterPhyName);\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=updateClusterHealth||clusterPhyName={}||errMsg={}\",\n                    clusterPhyName, e.getMessage());\n            return false;\n        }\n\n        esClusterDTO.setId(clusterPhy.getId());\n        esClusterDTO.setHealth(clusterHealthEnum.getCode());\n        Result<Boolean> editClusterResult = clusterPhyService.editCluster(esClusterDTO, operator);\n        if (editClusterResult.failed()) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=updateClusterHealth||clusterPhyName={}||errMsg={}\",\n                clusterPhyName, editClusterResult.getMessage());\n            return false;\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean updateClusterInfo(String cluster, String operator) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(cluster);\n        if (null == clusterPhy) {\n            LOGGER.warn(\n                \"class=ClusterPhyManagerImpl||method=updateClusterInfo||clusterPhyName={}||msg=clusterPhy is empty\",\n                cluster);\n            return false;\n        }\n\n        ESClusterStatsResponse clusterStats = esClusterService.syncGetClusterStats(cluster);\n        long totalFsBytes = clusterStats.getTotalFs().getBytes();\n        long usageFsBytes = clusterStats.getTotalFs().getBytes() - clusterStats.getFreeFs().getBytes();\n\n        double diskFreePercent = 0d;\n        double clusterTotalFs = clusterStats.getTotalFs().getGbFrac();\n        if(clusterTotalFs > 0){\n            diskFreePercent = clusterStats.getFreeFs().getGbFrac() / clusterTotalFs;\n            diskFreePercent = CommonUtils.formatDouble(1 - diskFreePercent, 5);\n        }\n\n        ClusterPhyDTO esClusterDTO = new ClusterPhyDTO();\n        esClusterDTO.setId(clusterPhy.getId());\n        esClusterDTO.setDiskTotal(totalFsBytes);\n        esClusterDTO.setDiskUsage(usageFsBytes);\n        esClusterDTO.setDiskUsagePercent(diskFreePercent);\n        Result<Boolean> editClusterResult = clusterPhyService.editCluster(esClusterDTO, operator);\n        if (editClusterResult.failed()) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=updateClusterInfo||clusterPhyName={}||errMsg={}\", cluster,\n                editClusterResult.getMessage());\n            return false;\n        }\n\n        return true;\n    }\n\n    @Override\n    public Result<Boolean> checkClusterHealth(String clusterPhyName, String operator) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterPhyName);\n        if (null == clusterPhy) {\n            return Result.buildFail();\n        }\n\n        if (ClusterHealthEnum.GREEN.getCode().equals(clusterPhy.getHealth())\n            || ClusterHealthEnum.YELLOW.getCode().equals(clusterPhy.getHealth())) {\n            return Result.buildSucc(true);\n        }\n\n        updateClusterHealth(clusterPhyName, operator);\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Boolean> checkClusterIsExit(String clusterPhyName, String operator) {\n        return Result.build(clusterPhyService.isClusterExists(clusterPhyName));\n    }\n\n    @Override\n    public Result<Boolean> deleteClusterExit(String clusterPhyName, Integer projectId, String operator) {\n        if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            return Result.buildFail(\"无权限删除集群\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterPhyName);\n        if (null == clusterPhy) {\n            return Result.buildSucc(true);\n        }\n\n        return deleteClusterInner(clusterPhy.getId(), projectId);\n    }\n\n    @Override\n    public Result<List<String>> getPhyClusterNameWithSameEsVersion(Integer clusterLogicType,\n                                                                   /*用户在新建逻辑集群阶段已选择的物理集群名称*/String hasSelectedClusterNameWhenBind) {\n        //获取可以绑定的物理集群名称列表\n        Result<List<String>> canBeAssociatedClustersPhyNamesResult = validLogicAndReturnPhyNamesWhenBindPhy(null,\n            clusterLogicType);\n        if (canBeAssociatedClustersPhyNamesResult.failed()) {\n            return Result.buildFrom(canBeAssociatedClustersPhyNamesResult);\n        }\n\n        //没有指定物理集群名称，则返回全量的匹配数据，不做版本的筛选\n        if (AriusObjUtils.isNull(hasSelectedClusterNameWhenBind)) {\n            return canBeAssociatedClustersPhyNamesResult;\n        }\n\n        //根据已绑定的物理集群的版本进行筛选\n        return Result.buildSucc(getPhyClusterNameWithSameEsVersion(hasSelectedClusterNameWhenBind,\n            canBeAssociatedClustersPhyNamesResult.getData()));\n    }\n\n    @Override\n    public Result<List<String>> getPhyClusterNameWithSameEsVersionAfterBuildLogic(Long clusterLogicId) {\n        //获取可以绑定的物理集群名称列表\n        Result<List<String>> canBeAssociatedClustersPhyNamesResult = validLogicAndReturnPhyNamesWhenBindPhy(\n            clusterLogicId, null);\n        if (canBeAssociatedClustersPhyNamesResult.failed()) {\n            return Result.buildFrom(canBeAssociatedClustersPhyNamesResult);\n        }\n\n        //获取逻辑集群已绑定的物理集群信息\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogicId);\n        if (null == clusterRegion) {\n            return canBeAssociatedClustersPhyNamesResult;\n        }\n\n        //根据已绑定的物理集群的版本进行筛选\n        return Result.buildSucc(getPhyClusterNameWithSameEsVersion(clusterRegion.getPhyClusterName(),\n            canBeAssociatedClustersPhyNamesResult.getData()));\n    }\n\n    @Override\n    public Result<ClusterPhyVO> updateClusterGateway(ClusterPhyDTO param, String operator) {\n        ClusterPhyDTO clusterPhyDTO = new ClusterPhyDTO();\n        clusterPhyDTO.setId(param.getId());\n        clusterPhyDTO.setGatewayUrl(param.getGatewayUrl());\n        ClusterPhy oldCluster = clusterPhyService.getClusterById(param.getId());\n        Result<Boolean> result = clusterPhyService.editCluster(clusterPhyDTO, operator);\n        if (result.failed()) {\n            return Result.buildFail(\"编辑gateway失败！\");\n        }\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(param.getId());\n         operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"%s, 绑定 gateway 集群 gateway_cluster:%s\", oldCluster.getCluster(),\n                        param.getGatewayUrl()), operator, AuthConstant.SUPER_PROJECT_ID, param.getId(),\n                OperateTypeEnum.PHYSICAL_CLUSTER_GATEWAY_CHANGE);\n        return Result.buildSucc(ConvertUtil.obj2Obj(clusterPhy, ClusterPhyVO.class));\n    }\n    \n   \n    \n    @Override\n    public List<ClusterRoleInfo> listClusterRolesByClusterId(Integer clusterId) {\n        return clusterRoleService.getAllRoleClusterByClusterId(clusterId);\n    }\n\n    @Override\n    public  List<ClusterRoleHost> listClusterRoleHostByCluster(String cluster) {\n        return clusterRoleHostService.getNodesByCluster(cluster);\n    }\n    \n    /**\n     * 它返回满足条件的总数。\n     *\n     * @param condition 查询的条件。\n     * @return 长\n     */\n    @Override\n    public Long fuzzyClusterPhyHitByCondition(ClusterPhyConditionDTO condition) {\n        return clusterPhyService.fuzzyClusterPhyHitByCondition(condition);\n    }\n    \n    /**\n     * 按条件获取集群物理信息\n     *\n     * @param condition 查询的条件。\n     * @return 列表<ClusterPhy>\n     */\n    @Override\n    public List<ClusterPhy> pagingGetClusterPhyByCondition(ClusterPhyConditionDTO condition) {\n        return  clusterPhyService.pagingGetClusterPhyByCondition(condition);\n    }\n\n    /**************************************** private method ***************************************************/\n\n    private Result<Boolean> deleteClusterInner(Integer clusterPhyId, Integer projectId) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(clusterPhyId);\n        if (null == clusterPhy) {\n            return Result.buildFail(String.format(\"物理集群Id[%s]不存在\", clusterPhyId));\n        }\n        try {\n            List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService.getNodesByCluster(clusterPhy.getCluster());\n            // 该物理集群有采集到host数据才执行删除操作\n            if (!CollectionUtils.isEmpty(clusterRoleHosts)) {\n                Result<Void> deleteHostResult = clusterRoleHostService.deleteByCluster(clusterPhy.getCluster(),\n                    projectId);\n                if (deleteHostResult.failed()) {\n                    throw new AdminOperateException(String.format(\"删除集群[%s]节点信息失败\", clusterPhy.getCluster()));\n                }\n            }\n\n            Result<Void> deleteRoleResult = clusterRoleService.deleteRoleClusterByClusterId(clusterPhy.getId(),\n                projectId);\n            if (deleteRoleResult.failed()) {\n                throw new AdminOperateException(String.format(\"删除集群[%s]角色信息失败\", clusterPhy.getCluster()));\n            }\n\n            List<ClusterRegion> clusterRegionList = clusterRegionService.listPhyClusterRegions(clusterPhy.getCluster());\n            if (!AriusObjUtils.isEmptyList(clusterRegionList)) {\n                // 该物理集群有Region才删除\n                Result<Void> deletePhyClusterRegionResult = clusterRegionService\n                    .deleteByClusterPhy(clusterPhy.getCluster());\n                if (deletePhyClusterRegionResult.failed()) {\n                    throw new AdminOperateException(String.format(\"删除集群[%s]Region新失败\", clusterPhy.getCluster()));\n                }\n            }\n\n            Result<Boolean> deleteClusterResult = clusterPhyService.deleteClusterById(clusterPhyId, projectId);\n            if (deleteClusterResult.failed()) {\n                throw new AdminOperateException(String.format(\"删除集群[%s]信息失败\", clusterPhy.getCluster()));\n            }\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=deleteClusterInfo||clusterName={}||errMsg={}||e={}\",\n                clusterPhy.getCluster(), e.getMessage(), e);\n            // 这里显示回滚处理特殊异常场景\n            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();\n            return Result.buildFail(\"删除物理集群失败\");\n        }\n        return Result.buildSucc(true);\n    }\n\n    /**\n     * 更新物理模板setting single_type为true\n     * @param cluster  集群\n     * @param template 物理模板\n     * @return\n     */\n    private boolean setTemplateSettingSingleType(String cluster, String template) {\n        Map<String, String> setting = new HashMap<>(2);\n        try {\n            return esTemplateService.syncUpsertSetting(cluster, template, setting, 3);\n        } catch (ESOperateException e) {\n            LOGGER.warn(\n                \"class=ClusterPhyManagerImpl||method=setTemplateSettingSingleType||errMsg={}||e={}||cluster={}||template={}\",\n                e.getMessage(), e, cluster, template);\n        }\n\n        return false;\n    }\n\n    /**\n     * 新建逻辑集群和已创建逻辑集群时绑定物理集群时进行校验,并且获取可以绑定的物理集群民称列表\n     * @param clusterLogicId 逻辑集群id\n     * @param clusterLogicType 逻辑集群类型\n     * @return 可以绑定的物理集群民称列表\n     */\n    Result<List<String>> validLogicAndReturnPhyNamesWhenBindPhy(Long clusterLogicId, Integer clusterLogicType) {\n        if (clusterLogicId == null && clusterLogicType == null) {\n            return Result.buildFail(\"传入的参数错误\");\n        }\n        Result<List<String>> canBeAssociatedClustersPhyNames = Result.buildSucc(Lists.newArrayList());\n        if (clusterLogicId != null) {\n            ClusterLogic clusterLogicById =\n                    clusterLogicService.listClusterLogicByIdThatProjectIdStrConvertProjectIdList(clusterLogicId).stream().findFirst().orElse(null);\n            if (clusterLogicById == null) {\n                return Result.buildFail(\"选定的逻辑集群不存在\");\n            }\n            clusterLogicType = clusterLogicById.getType();\n            canBeAssociatedClustersPhyNames = listCanBeAssociatedRegionOfClustersPhys(clusterLogicType, clusterLogicId);\n        } else {\n            canBeAssociatedClustersPhyNames = listCanBeAssociatedClustersPhys(clusterLogicType);\n        }\n\n        if (!ClusterResourceTypeEnum.isExist(clusterLogicType)) {\n            return Result.buildParamIllegal(\"逻辑集群类型非法\");\n        }\n\n        if (canBeAssociatedClustersPhyNames.failed()) {\n            LOGGER.warn(\n                \"class=ClusterPhyManagerImpl||method=getPhyClusterNameWithSameEsVersionAfterBuildLogic||errMsg={}\",\n                canBeAssociatedClustersPhyNames.getMessage());\n            Result.buildFail(\"无法获取对应的物理集群名称列表\");\n        }\n\n        return canBeAssociatedClustersPhyNames;\n    }\n\n    /**\n     * 根据已经选定的物理集群筛选出版本相同的可以绑定的物理集群名称列表\n     * @param hasSelectedPhyClusterName 已经选择的物理集群名称\n     * @param canBeAssociatedClustersPhyNames 可以匹配的物理集群名称列表（待筛选状态）\n     * @return 物理集群名称列表\n     */\n    private List<String> getPhyClusterNameWithSameEsVersion(String hasSelectedPhyClusterName,\n                                                            List<String> canBeAssociatedClustersPhyNames) {\n        //获取用户已选择的物理集群的信息\n        ClusterPhy hasSelectedCluster = clusterPhyService.getClusterByName(hasSelectedPhyClusterName);\n        //如果指定的物理集群名称为null，则返回全量的物理集群名称列表\n        if (AriusObjUtils.isNull(hasSelectedPhyClusterName) || AriusObjUtils.isNull(hasSelectedCluster)\n            || CollectionUtils.isEmpty(canBeAssociatedClustersPhyNames)) {\n            return null;\n        }\n\n        //筛选出和用户以指定的物理集群的版本号相同的物理集群名称列表\n        List<String> canBeAssociatedPhyClusterNameWithSameEsVersion = Lists.newArrayList();\n        for (String canBeAssociatedClustersPhyName : canBeAssociatedClustersPhyNames) {\n            ClusterPhy canBeAssociatedClustersPhy = clusterPhyService.getClusterByName(canBeAssociatedClustersPhyName);\n            if (!AriusObjUtils.isNull(canBeAssociatedClustersPhy)\n                && !AriusObjUtils.isNull(canBeAssociatedClustersPhy.getEsVersion())\n                && !AriusObjUtils.isNull(canBeAssociatedClustersPhy.getCluster())\n                && canBeAssociatedClustersPhy.getEsVersion().equals(hasSelectedCluster.getEsVersion())) {\n                canBeAssociatedPhyClusterNameWithSameEsVersion.add(canBeAssociatedClustersPhy.getCluster());\n            }\n        }\n\n        return canBeAssociatedPhyClusterNameWithSameEsVersion;\n    }\n\n    /**\n     * 构建物理集群详情\n     * @param clusterPhyVO 物理集群元数据信息\n     * @return\n     */\n    private void buildPhyCluster(ClusterPhyVO clusterPhyVO,ClusterPhy clusterPhy) {\n        if (!AriusObjUtils.isNull(clusterPhyVO)) {\n            clusterPhyVO.setGatewayUrl(esGatewayClient.getSingleGatewayAddress());\n            buildPhyClusterStatics(clusterPhyVO);\n            buildClusterRole(clusterPhyVO);\n            buildClusterPhyWithLogicAndRegion(Collections.singletonList(clusterPhyVO));\n        }\n    }\n\n    private Result<ClusterPhyVO> saveClusterPhy(ClusterJoinDTO param, String operator) {\n        //保存集群信息\n        ClusterPhyDTO clusterDTO = buildPhyClusters(param, operator);\n        Result<Boolean> addClusterRet = clusterPhyService.createCluster(clusterDTO, operator);\n        if (addClusterRet.failed()) {\n            return Result.buildFrom(addClusterRet);\n        }\n        return Result.buildSucc(ConvertUtil.obj2Obj(clusterDTO, ClusterPhyVO.class));\n    }\n\n    private ClusterPhyDTO buildPhyClusters(ClusterJoinDTO param, String operator) {\n        ClusterPhyDTO clusterDTO = ConvertUtil.obj2Obj(param, ClusterPhyDTO.class);\n        String clientAddress = \"\";\n        if (StringUtils.isNotBlank(param.getProxyAddress())){\n            clientAddress = param.getProxyAddress();\n        }else {\n            clientAddress = clusterRoleHostService.buildESClientHttpAddressesStr(param.getRoleClusterHosts());\n        }\n\n        clusterDTO.setDesc(param.getPhyClusterDesc());\n        if (StringUtils.isBlank(clusterDTO.getDataCenter())) {\n            clusterDTO.setDataCenter(DataCenterEnum.CN.getCode());\n        }\n        if (null == clusterDTO.getType()) {\n            clusterDTO.setType(ESClusterTypeEnum.ES_HOST.getCode());\n        }\n        clusterDTO.setHttpAddress(clientAddress);\n        clusterDTO.setHttpWriteAddress(clientAddress);\n        clusterDTO.setIdc(DEFAULT_CLUSTER_IDC);\n        clusterDTO.setLevel(ResourceLogicLevelEnum.NORMAL.getCode());\n        clusterDTO.setImageName(\"\");\n        clusterDTO.setPackageId(-1L);\n        clusterDTO.setNsTree(\"\");\n        clusterDTO.setPlugIds(\"\");\n        clusterDTO.setCreator(operator);\n        clusterDTO.setRunMode(RunModeEnum.READ_WRITE_SHARE.getRunMode());\n        clusterDTO.setHealth(DEFAULT_CLUSTER_HEALTH);\n        clusterDTO.setEcmAccess(Boolean.FALSE);\n        clusterDTO.setComponentId(-1);\n        return clusterDTO;\n    }\n\n    /**\n     * 集群接入参数校验\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @return {@link Result}<{@link Void}>\n     */\n    private Result<Void> checkClusterJoin(ClusterJoinDTO param, String operator) {\n        if (AriusObjUtils.isNull(param)) {\n            return Result.buildParamIllegal(\"参数为空\");\n        }\n        ClusterTag clusterTag = ConvertUtil.str2ObjByJson(param.getTags(), ClusterTag.class);\n\n        if (AriusObjUtils.isNull(operator)) {\n            return Result.buildParamIllegal(\"操作人不存在\");\n        }\n\n        if (!ESClusterTypeEnum.validCode(param.getType())) {\n            return Result.buildParamIllegal(\"非支持的集群类型\");\n        }\n\n        if (!ClusterResourceTypeEnum.isExist(param.getResourceType())) {\n            return Result.buildParamIllegal(\"非支持的集群资源类型\");\n        }\n\n        if (ESClusterCreateSourceEnum.ES_IMPORT != ESClusterCreateSourceEnum.valueOf(clusterTag.getCreateSource())) {\n            return Result.buildParamIllegal(\"非集群接入来源\");\n        }\n\n        if (!ESClusterImportRuleEnum.validCode(param.getImportRule())) {\n            return Result.buildParamIllegal(\"非支持的接入规则\");\n        }\n\n        return checkClusterNodes(param);\n    }\n\n    private Result<Void> checkClusterNodes(ClusterJoinDTO param) {\n        List<ESClusterRoleHostDTO> roleClusterHosts = param.getRoleClusterHosts();\n        if (CollectionUtils.isEmpty(roleClusterHosts)) {\n            return Result.buildParamIllegal(\"集群节点信息为空\");\n        }\n\n        // 对于接入集群的节点端口进行校验\n        Set<String> wrongPortSet = roleClusterHosts.stream().map(ESClusterRoleHostDTO::getPort)\n            .filter(this::wrongPortDetect).collect(Collectors.toSet());\n        if (!CollectionUtils.isEmpty(wrongPortSet)) {\n            return Result.buildParamIllegal(\"接入集群中端口号存在异常\" + wrongPortSet);\n        }\n\n        if (ESClusterImportRuleEnum.FULL_IMPORT.getCode() == param.getImportRule()) {\n            Set<Integer> roleForNode = roleClusterHosts.stream().map(ESClusterRoleHostDTO::getRole)\n                .collect(Collectors.toSet());\n\n            if (!roleForNode.contains(MASTER_NODE.getCode())) {\n                return Result.buildParamIllegal(String.format(NODE_NOT_EXISTS_TIPS, MASTER_NODE.getDesc()));\n            }\n\n            Map<Integer, List<String>> role2IpsMap = ConvertUtil.list2MapOfList(roleClusterHosts,\n                ESClusterRoleHostDTO::getRole, ESClusterRoleHostDTO::getIp);\n\n            List<String> masterIps = role2IpsMap.get(MASTER_NODE.getCode());\n            if (masterIps.size() < JOIN_MASTER_NODE_MIN_NUMBER) {\n                return Result.buildParamIllegal(String.format(\"集群%s的masternode角色节点个数要求大于等于1，且不重复\", param.getCluster()));\n            }\n\n            String duplicateIpForMaster = ClusterUtils.getDuplicateIp(masterIps);\n            if (!AriusObjUtils.isBlack(duplicateIpForMaster)) {\n                return Result.buildParamIllegal(String.format(IP_DUPLICATE_TIPS, duplicateIpForMaster));\n            }\n\n            String duplicateIpForClient = ClusterUtils.getDuplicateIp(role2IpsMap.get(CLIENT_NODE.getCode()));\n            if (!AriusObjUtils.isBlack(duplicateIpForClient)) {\n                return Result.buildParamIllegal(String.format(IP_DUPLICATE_TIPS, duplicateIpForClient));\n            }\n\n            String duplicateIpForData = ClusterUtils.getDuplicateIp(role2IpsMap.get(DATA_NODE.getCode()));\n            if (!AriusObjUtils.isBlack(duplicateIpForData)) {\n                return Result.buildParamIllegal(String.format(IP_DUPLICATE_TIPS, duplicateIpForData));\n            }\n        } else {\n\n            List<String> ips = roleClusterHosts.stream().map(ESClusterRoleHostDTO::getIp)\n                .filter(StringUtils::isNotBlank).collect(Collectors.toList());\n            if (ips.size() < JOIN_MASTER_NODE_MIN_NUMBER) {\n                return Result.buildParamIllegal(String.format(\"集群%s的节点个数要求大于等于1，且不重复\", param.getCluster()));\n            }\n\n            String duplicateIpForMaster = ClusterUtils.getDuplicateIp(ips);\n            if (!AriusObjUtils.isBlack(duplicateIpForMaster)) {\n                return Result.buildParamIllegal(String.format(IP_DUPLICATE_TIPS, duplicateIpForMaster));\n            }\n        }\n\n        if (clusterPhyService.isClusterExists(param.getCluster())) {\n            return Result.buildParamIllegal(String.format(\"物理集群名称:%s已存在\", param.getCluster()));\n        }\n\n        String esClientHttpAddressesStr = clusterRoleHostService.buildESClientHttpAddressesStr(roleClusterHosts);\n\n        // 密码验证\n        Result<Void> passwdResult = checkClusterWithoutPasswd(param, esClientHttpAddressesStr);\n        if (passwdResult.failed()) {\n            return passwdResult;\n        }\n        // 同集群验证\n        Result<Void> sameClusterResult = checkSameCluster(param.getPassword(),\n            clusterRoleHostService.buildESAllRoleHttpAddressesList(roleClusterHosts));\n        if (sameClusterResult.failed()) {\n            return Result.buildParamIllegal(\"禁止同时接入超过两个不同集群节点\");\n        }\n\n        // 校验 是否接入同一集群\n        Result<Void> checkSameClientOrMasterClusterRet = checkSameESClientHttpAddresses(esClientHttpAddressesStr);\n        if (checkSameClientOrMasterClusterRet.failed()) {\n            return Result.buildFrom(checkSameClientOrMasterClusterRet);\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 检查ESClientHttpAddresses是否已经存在\n     * @param esClientHttpAddressesStr\n     * @return\n     */\n    private Result<Void> checkSameESClientHttpAddresses(String esClientHttpAddressesStr) {\n        List<ClusterPhy> clusterPhies = clusterPhyService.listAllClusters();\n        if (CollectionUtils.isEmpty(clusterPhies)) {\n            return Result.buildSucc();\n        }\n\n        // 过滤出目前平台存在的ES集群链接ip:port\n        List<String> existClusterHttpAddress = Lists.newArrayList();\n        List<String> clusterHttpAddressList = clusterPhies.stream().map(ClusterPhy::getHttpAddress)\n            .collect(Collectors.toList());\n        for (String clusterHttpAddress : clusterHttpAddressList) {\n            for (String httpAddress : ListUtils.string2StrList(clusterHttpAddress)) {\n                if (!existClusterHttpAddress.contains(httpAddress.trim())) {\n                    existClusterHttpAddress.add(httpAddress.trim());\n                }\n            }\n        }\n\n        List<String> esClientHttpAddressesFromJoin = ListUtils.string2StrList(esClientHttpAddressesStr);\n        for (String esClientHttpAddressFromJoin : esClientHttpAddressesFromJoin) {\n            if (existClusterHttpAddress.contains(esClientHttpAddressFromJoin.trim())) {\n                return Result.buildFail(String.format(\"平台已经存在相同的集群，连接信息为[%s], 不允许重复接入\", esClientHttpAddressFromJoin));\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> initClusterJoin(ClusterJoinDTO param, String esClientHttpAddressesStr) {\n        //获取设置es版本\n        Result<Void> esVersionSetResult = initESVersionForClusterJoin(param, esClientHttpAddressesStr);\n        if (esVersionSetResult.failed()) {\n            return esVersionSetResult;\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 检测「未设置密码的集群」接入时是否携带账户信息\n     */\n    private Result<Void> checkClusterWithoutPasswd(ClusterJoinDTO param, String esClientHttpAddressesStr) {\n        ClusterConnectionStatus status = esClusterService.checkClusterPassword(esClientHttpAddressesStr, null);\n        if (ClusterConnectionStatus.DISCONNECTED == status) {\n            return Result.buildParamIllegal(\"集群离线未能连通\");\n        }\n\n        if (!Strings.isNullOrEmpty(param.getPassword())) {\n            if (ClusterConnectionStatus.NORMAL == status) {\n                return Result.buildParamIllegal(\"未设置密码的集群，请勿输入账户信息\");\n            }\n            status = esClusterService.checkClusterPassword(esClientHttpAddressesStr, param.getPassword());\n            if (ClusterConnectionStatus.UNAUTHORIZED == status) {\n                return Result.buildParamIllegal(\"集群的账户信息错误\");\n            }\n        } else {\n            if (ClusterConnectionStatus.UNAUTHORIZED == status) {\n                return Result.buildParamIllegal(\"集群设置有密码，请输入账户信息\");\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkSameCluster(String passwd, List<String> esClientHttpAddressesList) {\n        return esClusterService.checkSameCluster(passwd, esClientHttpAddressesList);\n    }\n\n    /**\n     * 初始化集群版本\n     * @param param\n     * @param esClientHttpAddressesStr\n     * @return\n     */\n    private Result<Void> initESVersionForClusterJoin(ClusterJoinDTO param, String esClientHttpAddressesStr) {\n        String esVersion = esClusterService.synGetESVersionByHttpAddress(esClientHttpAddressesStr, param.getPassword());\n        if (Strings.isNullOrEmpty(esVersion)) {\n            return Result.buildParamIllegal(String.format(\"%s无法获取es版本\", esClientHttpAddressesStr));\n        }\n        param.setEsVersion(esVersion);\n        return Result.buildSucc();\n    }\n\n    private void doDeleteClusterJoin(ClusterPhy clusterPhy, String operator,\n                                     Integer projectId) throws AdminOperateException {\n        \n           // 1. set region\n        List<ClusterRegion> regions = clusterRegionService.listPhyClusterRegions(clusterPhy.getCluster());\n        if (CollectionUtils.isEmpty(regions)) {\n            return;\n        }\n    \n        List<Long> associatedRegionIds = regions.stream().map(ClusterRegion::getId).collect(Collectors.toList());\n        for (Long associatedRegionId : associatedRegionIds) {\n            final ClusterRegion region = clusterRegionService.getRegionById(associatedRegionId);\n            Result<Void> unbindRegionResult = clusterRegionService.unbindRegion(associatedRegionId, null, operator);\n            if (unbindRegionResult.failed()) {\n                throw new AdminOperateException(String.format(\"解绑region(%s)失败\", associatedRegionId));\n            } else {\n                \n                //解绑region\n                 operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"解绑 region：%s\", region.getName()), operator, projectId,\n                        clusterPhy.getId(), OperateTypeEnum.PHYSICAL_CLUSTER_REGION_CHANGE);\n            }\n            Result<Void> deletePhyClusterRegionResult = clusterRegionService.deletePhyClusterRegion(associatedRegionId,\n                operator);\n            if (deletePhyClusterRegionResult.failed()) {\n                throw new AdminOperateException(String.format(\"删除region(%s)失败\", associatedRegionId));\n            } else {\n                \n                //删除region\n                 operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"删除 region：%s\", region.getName()), operator, projectId,\n                        clusterPhy.getId(), OperateTypeEnum.PHYSICAL_CLUSTER_REGION_CHANGE);\n            }\n        }\n\n        List<Long> clusterLogicIds =regions.stream()\n                .filter(clusterRegion -> Objects.nonNull(clusterRegion.getLogicClusterIds()))\n                .map(clusterRegion -> ListUtils.string2LongList(clusterRegion.getLogicClusterIds()))\n                .filter(CollectionUtils::isNotEmpty).flatMap(Collection::stream)\n                .filter(logicId -> Objects.equals(logicId,\n                        Long.parseLong(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID))).distinct()\n                .collect(Collectors.toList());\n        for (Long clusterLogicId : clusterLogicIds) {\n            final ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(clusterLogicId);\n            if (Objects.isNull(clusterLogic)){\n                continue;\n            }\n            Result<Void> deleteLogicClusterResult = clusterLogicService.deleteClusterLogicById(clusterLogicId, operator,\n                projectId);\n            if (deleteLogicClusterResult.failed()) {\n                throw new AdminOperateException(String.format(\"删除逻辑集群(%s)失败\", clusterLogicId));\n            } else {\n                //删除逻辑集群\n                 operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"删除逻辑集群：%s\", clusterLogic.getName()), operator, projectId,\n                        clusterPhy.getId(), OperateTypeEnum.MY_CLUSTER_OFFLINE);\n            }\n        }\n\n        Result<Boolean> deleteClusterResult = clusterPhyService.deleteClusterById(clusterPhy.getId(), projectId);\n        if (deleteClusterResult.failed()) {\n            throw new AdminOperateException(String.format(\"删除物理集群(%s)失败\", clusterPhy.getCluster()));\n        } else {\n            //删除物理集群\n             operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"cluster:[%s] 删除\", clusterPhy.getCluster()), operator, projectId,\n                    clusterPhy.getId(), OperateTypeEnum.PHYSICAL_CLUSTER_OFFLINE);\n        }\n\n        Result<Void> deleteRoleClusterResult = clusterRoleService.deleteRoleClusterByClusterId(clusterPhy.getId(),\n            projectId);\n        if (deleteRoleClusterResult.failed()) {\n            throw new AdminOperateException(String.format(\"删除物理集群角色(%s)失败\", clusterPhy.getCluster()));\n        } else {\n            //删除物理集群角色\n              operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"cluster:[%s]删除物理集群角色;[%d]\", clusterPhy.getCluster(), clusterPhy.getId()), operator,\n                    projectId, clusterPhy.getId(), OperateTypeEnum.PHYSICAL_CLUSTER_OFFLINE);\n        }\n\n        Result<Void> deleteRoleClusterHostResult = clusterRoleHostService.deleteByCluster(clusterPhy.getCluster(),\n            projectId);\n        if (deleteRoleClusterHostResult.failed()) {\n            throw new AdminOperateException(String.format(\"删除物理集群节点(%s)失败\", clusterPhy.getCluster()));\n        } else {\n            //删除物理集群角色\n             operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"cluster:[%s] 删除物理集群节点\", clusterPhy.getCluster()), operator,\n                    projectId, clusterPhy.getId(), OperateTypeEnum.PHYSICAL_CLUSTER_OFFLINE);\n        }\n    }\n\n    /**\n     * 初始化物理集群配置信息\n     * @return Map<ClusterDynamicConfigsTypeEnum, Map<String, Object>>中Map的String表示的是动态配置的字段，例如cluster.routing.allocation.awareness.attributes\n     * Object则是对应动态配置字段的值\n     */\n    private Map<ClusterDynamicConfigsTypeEnum, Map<String, Object>> initClusterDynamicConfigs() {\n        Map<ClusterDynamicConfigsTypeEnum, Map<String, Object>> esClusterPhyDynamicConfig = Maps.newHashMap();\n        for (ClusterDynamicConfigsTypeEnum clusterDynamicConfigsTypeEnum : ClusterDynamicConfigsTypeEnum\n            .valuesWithoutUnknown()) {\n            esClusterPhyDynamicConfig.put(clusterDynamicConfigsTypeEnum, Maps.newHashMap());\n        }\n\n        return esClusterPhyDynamicConfig;\n    }\n\n    private Triple<Long/*diskTotal*/, Long/*diskUsage*/, Double/*diskUsagePercent*/> getESClusterStaticInfoTriple(String cluster) {\n        Triple<Long, Long, Double> initTriple = buildInitTriple();\n        if (!clusterPhyService.isClusterExists(cluster)) {\n            LOGGER.error(\n                \"class=ClusterPhyManagerImpl||method=getESClusterStaticInfoTriple||clusterName={}||msg=cluster is empty\",\n                cluster);\n            return initTriple;\n        }\n\n        return getClusterStatsTriple(cluster, initTriple);\n    }\n\n    private Triple<Long, Long, Double> getClusterStatsTriple(String cluster, Triple<Long, Long, Double> initTriple) {\n        if (CLUSTER_NAME_TO_ES_CLUSTER_STATS_TRIPLE_MAP.containsKey(cluster)) {\n            return CLUSTER_NAME_TO_ES_CLUSTER_STATS_TRIPLE_MAP.get(cluster);\n        } else {\n            refreshClusterStats(cluster, initTriple);\n            return initTriple;\n        }\n    }\n\n    private Triple<Long/*diskTotal*/, Long/*diskTotal*/, Double/*diskUsagePercent*/> buildInitTriple() {\n        Triple<Long/*diskTotal*/, Long/*diskTotal*/, Double/*diskUsagePercent*/> triple = new Triple<>();\n        triple.setV1(0L);\n        triple.setV2(0L);\n        triple.setV3(0d);\n        return triple;\n    }\n\n    private void postProcessingForClusterJoin(ClusterJoinDTO param) throws AdminTaskException {\n        esOpClient.connect(param.getCluster());\n\n        if (ESClusterImportRuleEnum.AUTO_IMPORT == ESClusterImportRuleEnum.valueOf(param.getImportRule())) {\n            clusterRoleHostService.collectClusterNodeSettings(param.getCluster());\n        } else if (ESClusterImportRuleEnum.FULL_IMPORT == ESClusterImportRuleEnum.valueOf(param.getImportRule())) {\n            //1.先持久化用户输入的节点信息\n            clusterRoleHostService.saveClusterNodeSettings(param);\n            //2.直接拉es 更新节点信息，去除因为定时任务触发导致的更新延时\n            clusterRoleHostService.collectClusterNodeSettings(param.getCluster());\n        }\n        updateClusterHealth(param.getCluster(), AriusUser.SYSTEM.getDesc());\n\n    }\n\n    private void refreshClusterDistInfo() {\n        List<String> clusterNameList = clusterPhyService.listAllClusters().stream().map(ClusterPhy::getCluster)\n            .collect(Collectors.toList());\n        for (String clusterName : clusterNameList) {\n            Triple<Long, Long, Double> initTriple = buildInitTriple();\n            refreshClusterStats(clusterName, initTriple);\n        }\n    }\n\n    private void refreshClusterStats(String clusterName, Triple<Long, Long, Double> initTriple) {\n        ESClusterStatsResponse clusterStats = esClusterService.syncGetClusterStats(clusterName);\n        if (null != clusterStats && null != clusterStats.getFreeFs() && null != clusterStats.getTotalFs()\n            && clusterStats.getTotalFs().getBytes() > 0 && clusterStats.getFreeFs().getBytes() > 0) {\n            initTriple.setV1(clusterStats.getTotalFs().getBytes());\n            initTriple.setV2(clusterStats.getTotalFs().getBytes() - clusterStats.getFreeFs().getBytes());\n            double diskFreePercent = clusterStats.getFreeFs().getGbFrac() / clusterStats.getTotalFs().getGbFrac();\n            initTriple.setV3(1 - diskFreePercent);\n        }\n\n        CLUSTER_NAME_TO_ES_CLUSTER_STATS_TRIPLE_MAP.put(clusterName, initTriple);\n    }\n\n    /**\n     * 对于异常的端口号的检测\n     * @param port 端口号\n     * @return 校验结果\n     */\n    private boolean wrongPortDetect(String port) {\n        try {\n            int portValue = Integer.parseInt(port);\n            return portValue < AdminConstant.MIN_BIND_PORT_VALUE || portValue > AdminConstant.MAX_BIND_PORT_VALUE;\n        } catch (NumberFormatException e) {\n            LOGGER.error(\"class=ClusterPhyManagerImpl||method=wrongPortDetect||port={}||msg=Integer format error\",\n                port);\n            return true;\n        }\n    }\n    \n    private TupleThree</*dcdrExist*/Boolean,/*pipelineExist*/ Boolean,/*existColdRegion*/ Boolean> getDCDRAndPipelineTupleByClusterPhy(\n            String clusterPhy) {\n        TupleTwo<Boolean, Boolean> tupleTwo = esClusterNodeService.existDCDRAndPipelineModule(clusterPhy);\n        return Tuples.of(tupleTwo.v1,tupleTwo.v2,CollectionUtils.isNotEmpty(getColdRegionByPhyCluster(clusterPhy)));\n    }\n    \n    private ClusterConnectionStatusWithTemplateEnum getClusterConnectionStatus(String clusterPhy) {\n        return esClusterService.isConnectionStatus(clusterPhy)\n                ? ClusterConnectionStatusWithTemplateEnum.NORMAL\n                : ClusterConnectionStatusWithTemplateEnum.DISCONNECTED;\n    }\n    \n   \n    \n     public List<ClusterRegion> getColdRegionByPhyCluster(String phyCluster) {\n        List<ClusterRegion> clusterRegions = clusterRegionService.listPhyClusterRegions(phyCluster);\n        //冷region是不会保存在逻辑集群侧的，所以这里关联的region肯定是大于1的，如果是小于1，那么是一定不会具备的\n        if (clusterRegions.size()<=1){\n            return Collections.emptyList();\n        }\n          return clusterRegions.stream().filter(coldTruePreByClusterRegion).collect(Collectors.toList());\n    }\n     private final static Predicate<ClusterRegion> coldTruePreByClusterRegion = clusterRegion -> {\n        if (StringUtils.isBlank(clusterRegion.getConfig())) {\n            return Boolean.FALSE;\n        }\n        try {\n            return JSON.parseObject(clusterRegion.getConfig()).getBoolean(COLD);\n        \n        } catch (Exception e) {\n            return Boolean.FALSE;\n        }\n    \n    };\n    \n    /**\n     * > 该函数用于获取存储 zeus 部署的 ip 列表的缓存 return List<String>\n     */\n    private List<String> ipListWithCache() {\n        return ZEUS_AGENTS_LIST_CACHE.getIfPresent(ZEUS_AGENTS_LIST);\n    }\n    \n    private void refreshWhitIpList() {\n        ZEUS_AGENTS_LIST_CACHE.put(ZEUS_AGENTS_LIST, getIpList());\n    }\n\n    /**\n     * > 该函数用于缓存初次获取zeus部署的agents list\n     *return List<String>\n     */\n    private List<String> getIpList() {\n        Result<List<String>> result = zeusClusterRemoteService.getAgentsList();\n        //如果获取zeus失败则返回空列表\n        if (result.failed()) {\n            return Collections.emptyList();\n        }\n        return result.getData();\n    }\n        /**\n     * > 该函数用于构建支持zeus by cluster phy\n     *\n     * @param clusterPhyVO 集群物理信息\n     */\n        private void buildSupportZeusByClusterPhy(ClusterPhyVO clusterPhyVO, List<String> ipList,\n                                                  List<String> zeusAgentsList) {\n            // 物理集群上所有的节点都需要在 zeus 的 ip 列表上，那么它才属于支持 zeus 的，一旦发现有一个不在就是不支持，不再遍历\n            clusterPhyVO.setSupportZeus(\n                    CollectionUtils.isNotEmpty(ipList) && Sets.newHashSet(zeusAgentsList).containsAll(ipList));\n        }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/impl/ClusterPhyQuickCommandManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster.impl;\n\nimport com.baomidou.mybatisplus.core.conditions.interfaces.Func;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyQuickCommandManager;\nimport com.didichuxing.datachannel.arius.admin.biz.page.QuickCommandIndicesDistributionPageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.biz.page.QuickCommandShardsDistributionPageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyQuickCommandIndicesQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyQuickCommandShardsQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.shard.ShardCatCellPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.*;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.SizeUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.*;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\n/**\n * 快捷指令实现.\n *\n * @ClassName QuickCommandManagerImpl\n * @Author gyp\n * @Date 2022/6/1\n * @Version 1.0\n */\n@Component\npublic class ClusterPhyQuickCommandManagerImpl implements ClusterPhyQuickCommandManager {\n\n    private static final ILog LOGGER            = LogFactory.getLog(ClusterPhyQuickCommandManagerImpl.class);\n    \n    @Autowired\n    protected ClusterPhyService clusterPhyService;\n    \n    @Autowired\n    protected ESClusterService     esClusterService;\n    @Autowired\n    protected ESClusterNodeService esClusterNodeService;\n    \n    @Autowired\n    protected ESIndexService esIndexService;\n    \n    @Autowired\n    protected ESShardCatService esShardCatService;\n    \n    @Autowired\n    protected ESShardService esShardService;\n    \n    @Autowired\n    private HandleFactory handleFactory;\n    \n    @Override\n    public Result<List<NodeStateVO>> nodeStateAnalysis(String cluster) {\n        Result<Void> checkResult = checkClusterExistence(cluster);\n        if (checkResult.failed()) {\n            return Result.buildFail(checkResult.getMessage());\n        }\n        return Result.buildSucc(esClusterNodeService.syncNodeStateAnalysis(cluster));\n    }\n    \n    @Override\n    public Result<List<IndicesDistributionVO>> indicesDistribution(String cluster) {\n        Result<Void> checkResult = checkClusterExistence(cluster);\n        if (checkResult.failed()) {\n            return Result.buildFail(checkResult.getMessage());\n        }\n        // 把 List<CatIndexResult> 转为 List<IndicesDistributionVO>\n        List<CatIndexResult> catIndexResultList = esIndexService.syncIndicesDistribution(cluster);\n        return Result.buildSucc(ConvertUtil.list2List(catIndexResultList, IndicesDistributionVO.class));\n    }\n    \n    @Override\n    public Result<List<PendingTaskAnalysisVO>> pendingTaskAnalysis(String cluster) {\n        Result<Void> checkResult = checkClusterExistence(cluster);\n        if (checkResult.failed()) {\n            return Result.buildFail(checkResult.getMessage());\n        }\n        List<PendingTaskAnalysisVO> vos = esClusterService.syncPendingTaskAnalysis(cluster);\n        if (vos == null) {\n            return Result.buildFail();\n        }\n        return Result.buildSucc(vos);\n    }\n    \n    @Override\n    public Result<List<TaskMissionAnalysisVO>> taskMissionAnalysis(String cluster) {\n        Result<Void> checkResult = checkClusterExistence(cluster);\n        if (checkResult.failed()) {\n            return Result.buildFail(checkResult.getMessage());\n        }\n        List<TaskMissionAnalysisVO> vos = esClusterService.syncTaskMissionAnalysis(cluster);\n        if (vos == null) {\n            return Result.buildFail();\n        }\n        return Result.buildSucc(vos);\n    }\n    \n    @Override\n    public Result<String> hotThreadAnalysis(String cluster) {\n        Result<Void> checkResult = checkClusterExistence(cluster);\n        if (checkResult.failed()) {\n            return Result.buildFail(checkResult.getMessage());\n        }\n        return Result.buildSucc(esClusterService.syncHotThreadAnalysis(cluster));\n    }\n    \n    @Override\n    public Result<ShardAssignmentDescriptionVO> shardAssignmentDescription(String cluster) {\n        Result<Void> checkResult = checkClusterExistence(cluster);\n        if (checkResult.failed()) {\n            return Result.buildFail(checkResult.getMessage());\n        }\n        ShardAssignmentDescriptionVO shardAssignmentDescriptionVO = new ShardAssignmentDescriptionVO();\n        try {\n            shardAssignmentDescriptionVO = esShardService.syncShardAssignmentDescription(cluster);\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=IndicesManagerImpl||method=editMapping||errMsg={}\", e.getMessage(), e);\n            return Result.buildFail(e.getMessage() + \":\" + e.getCause());\n        }\n        if (shardAssignmentDescriptionVO == null) {\n            return Result.buildFail();\n        }\n        return Result.buildSucc(shardAssignmentDescriptionVO);\n    }\n    \n    @Override\n    public Result<Void> abnormalShardAllocationRetry(String cluster) {\n        Result<Void> checkResult = checkClusterExistence(cluster);\n        if (checkResult.failed()) {\n            return Result.buildFail(checkResult.getMessage());\n        }\n        boolean result = esClusterService.syncAbnormalShardAllocationRetry(cluster);\n        if (result) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail();\n    }\n    \n    @Override\n    public Result<Void> clearFieldDataMemory(String cluster) {\n        Result<Void> checkResult = checkClusterExistence(cluster);\n        if (checkResult.failed()) {\n            return Result.buildFail(checkResult.getMessage());\n        }\n        boolean result = esClusterService.syncClearFieldDataMemory(cluster);\n        if (result) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail();\n    }\n    \n    @Override\n    public List<IndicesDistributionVO> indicesDistributionPage(\n            ClusterPhyQuickCommandIndicesQueryDTO condition, Integer projectId) {\n        List<IndicesDistributionVO> indicesDistributionVOS = new ArrayList<>();\n        List<CatIndexResult> catIndexResultList = esIndexService.syncIndicesDistribution(condition.getCluster());\n        catIndexResultList.forEach(catIndexResult -> {\n            IndicesDistributionVO indicesDistributionVO = ConvertUtil.obj2Obj(catIndexResult, IndicesDistributionVO.class);\n            indicesDistributionVO.setPriStoreSize(SizeUtil.getUnitSize(catIndexResult.getPriStoreSize()));\n            indicesDistributionVO.setStoreSize(SizeUtil.getUnitSize(catIndexResult.getStoreSize()));\n            if (StringUtils.isNotBlank(condition.getKeyword())) {\n                String index = Objects.isNull(indicesDistributionVO.getIndex())?\"\":indicesDistributionVO.getIndex();\n                if (index.contains(condition.getKeyword())) {\n                    indicesDistributionVOS.add(indicesDistributionVO);\n                }\n            } else {\n                indicesDistributionVOS.add(indicesDistributionVO);\n            }\n        });\n        return indicesDistributionVOS;\n    }\n    \n    @Override\n    public List<ShardDistributionVO> shardDistributionPage(ClusterPhyQuickCommandShardsQueryDTO condition,Integer projectId)\n            throws ESOperateException {\n        List<ShardCatCellPO> shardCatCellPOS =  esShardCatService.syncShardDistribution(condition.getCluster(),System.currentTimeMillis());\n        List<ShardDistributionVO> shardDistributionVOS = new ArrayList<>();\n        shardCatCellPOS.forEach(shardCatCellPO -> {\n            ShardDistributionVO shardDistributionVO = ConvertUtil.obj2Obj(shardCatCellPO, ShardDistributionVO.class);\n            shardDistributionVO.setStore(SizeUtil.getUnitSize(shardCatCellPO.getStore()));\n            if (StringUtils.isNotBlank(condition.getKeyword())) {\n                String node = Objects.isNull(shardDistributionVO.getNode())?\"\":shardDistributionVO.getNode();\n                String index = Objects.isNull(shardDistributionVO.getIndex())?\"\":shardDistributionVO.getIndex();\n                if (node.contains(condition.getKeyword()) || index.contains(condition.getKeyword())) {\n                    shardDistributionVOS.add(shardDistributionVO);\n                }\n            }else {\n                shardDistributionVOS.add(shardDistributionVO);\n            }\n        });\n        return shardDistributionVOS;\n    }\n    \n    private Result<Void> checkClusterExistence(String cluster) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(cluster);\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildFail(String.format(\"集群[%s]不存在\", cluster));\n        }\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/impl/ClusterPluginManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPluginManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.PluginDTO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPluginService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class ClusterPluginManagerImpl implements ClusterPluginManager {\n    @Autowired\n    private ESPluginService esPluginService;\n\n    @Override\n    public Result<Long> addPlugins(PluginDTO plugin, Integer projectId) throws NotFindSubclassException {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        return esPluginService.addESPlugin(plugin);\n    }\n\n    @Override\n    public Result<Long> deletePluginById(Long id, String operator, Integer projectId) throws NotFindSubclassException {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        return esPluginService.deletePluginById(id, operator);\n    }\n\n    @Override\n    public Result<Void> editPluginDesc(PluginDTO pluginDTO, String operator, Integer projectId) {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        return esPluginService.updateESPluginDesc(pluginDTO, operator);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/impl/ClusterRegionManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.EXCLUSIVE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.PRIVATE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.PUBLIC;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum.UNKNOWN;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.DATA_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType.FAIL;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterNodeManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterRegionManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicSpecCondition;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionWithNodeInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterWithRegionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogicContext;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhyContext;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterRegionVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterRegionWithNodeInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.function.Predicate;\nimport java.util.stream.Collectors;\n\nimport io.swagger.models.auth.In;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Component\npublic class ClusterRegionManagerImpl implements ClusterRegionManager {\n\n    private static final ILog      LOGGER = LogFactory.getLog(ClusterRegionManagerImpl.class);\n\n    @Autowired\n    private ClusterRegionService   clusterRegionService;\n\n \n\n    @Autowired\n    private ClusterLogicService    clusterLogicService;\n\n    @Autowired\n    private ClusterPhyService      clusterPhyService;\n\n\n    @Autowired\n    private ClusterRoleHostService clusterRoleHostService;\n\n    @Autowired\n    private ClusterNodeManager     clusterNodeManager;\n\n    @Autowired\n    private OperateRecordService   operateRecordService;\n    @Autowired\n    private ProjectService         projectService;\n    private static final String COLD = \"cold\";\n    private static final Integer LOGIC_ASSOCIATED_PHY_MAX_NUMBER = 2 << 9;\n    private static final Integer PHY_ASSOCIATED_LOGIC_MAX_NUMBER = 2 << 9;\n    /**\n     * 构建regionVO\n     * @param regions region列表\n     * @return\n     */\n    @Override\n    public List<ClusterRegionVO> buildLogicClusterRegionVO(List<ClusterRegion> regions) {\n        if (CollectionUtils.isEmpty(regions)) {\n            return new ArrayList<>();\n        }\n\n        return regions.stream().filter(Objects::nonNull).map(this::buildLogicClusterRegionVO)\n            .collect(Collectors.toList());\n    }\n\n    /**\n     * 逻辑集群绑定同一个物理集群的region的时候需要根据类型进行过滤，返回的region不包含cold region\n     * @param phyCluster 物理集群名称\n     * @param clusterLogicType 逻辑集群类型\n     * @return\n     */\n    @Deprecated\n    @Override\n    public Result<List<ClusterRegionVO>> listPhyClusterRegionsByLogicClusterTypeAndCluster(String phyCluster,\n                                                                                           Integer clusterLogicType) {\n        if (!ClusterResourceTypeEnum.isExist(clusterLogicType)) {\n            return Result.buildFail(\"逻辑集群类型不存在\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(phyCluster);\n        if (null == clusterPhy) {\n            return Result.buildFail(String.format(\"物理集群[%s]不存在\", phyCluster));\n        }\n\n        int resourceType = clusterPhy.getResourceType();\n        if (clusterLogicType != resourceType) {\n            return Result.buildFail(\n                String.format(\"物理集群[%s]类型为[%s], 不满足逻辑集群类型[%s], 请调整类型一致\", phyCluster, resourceType, clusterLogicType));\n        }\n\n        List<ClusterRegion> clusterRegions = clusterRegionService.listPhyClusterRegions(phyCluster).stream().filter(notColdTruePreByClusterRegion)\n                                                                 .filter(clusterRegion -> clusterRegionService.isRegionCanBeBound(clusterRegion,clusterLogicType)).collect(Collectors.toList());\n\n        if (CollectionUtils.isEmpty(clusterRegions)) {\n            return Result.buildFail(String.format(\"物理集群[%s]无可用region, 请前往物理集群-region划分进行region创建\", phyCluster));\n        }\n        return Result.buildSucc(ConvertUtil.list2List(clusterRegions, ClusterRegionVO.class,\n            regionVO -> regionVO.setClusterName(phyCluster)));\n    }\n\n    /**\n     * 逻辑集群绑定同一个物理集群的region的时候需要根据类型进行过滤，之后再根据cold、region节点数量、节点规格进行过滤\n     * @param phyCluster 物理集群名称\n     * @param clusterLogicType 逻辑集群类型\n     * @param condition 用户侧申请的集群规格（节点数量、机器规格）\n     * @return\n     */\n    @Override\n    public Result<List<ClusterRegionVO>> listPhyClusterRegionsByCondition(String phyCluster,\n                                                                          Integer clusterLogicType,\n                                                                          ClusterLogicSpecCondition condition) {\n        if (!ClusterResourceTypeEnum.isExist(clusterLogicType)) {\n            return Result.buildFail(\"逻辑集群类型不存在\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(phyCluster);\n        if (null == clusterPhy) {\n            return Result.buildFail(String.format(\"物理集群[%s]不存在\", phyCluster));\n        }\n\n        int resourceType = clusterPhy.getResourceType();\n        if (clusterLogicType != resourceType) {\n            return Result.buildFail(\n                    String.format(\"物理集群[%s]类型为[%s], 不满足逻辑集群类型[%s], 请调整类型一致\", phyCluster, resourceType, clusterLogicType));\n        }\n\n        // 三层过滤：cold、region节点数量、region节点规格\n        List<ClusterRegion> clusterRegions = clusterRegionService.listPhyClusterRegions(phyCluster).stream()\n                .filter(notColdTruePreByClusterRegion)\n                .filter(clusterRegion -> checkRegionHostNumAndSpec(clusterRegion.getId(), condition))\n                .filter(clusterRegion -> clusterRegionService.isRegionCanBeBound(clusterRegion,clusterLogicType)).collect(Collectors.toList());\n\n        if (CollectionUtils.isEmpty(clusterRegions)) {\n            return Result.buildFail(String.format(\"物理集群[%s]无可用region, 请前往物理集群-region划分进行region创建\", phyCluster));\n        }\n        return Result.buildSucc(ConvertUtil.list2List(clusterRegions, ClusterRegionVO.class,\n                regionVO -> regionVO.setClusterName(phyCluster)));\n    }\n\n\n    /**\n     * 构建regionVO\n     * @param region region\n     * @return\n     */\n    @Override\n    public ClusterRegionVO buildLogicClusterRegionVO(ClusterRegion region) {\n        if (region == null) {\n            return null;\n        }\n\n        ClusterRegionVO logicClusterRegionVO = ConvertUtil.obj2Obj(region, ClusterRegionVO.class, regionVO -> {\n            regionVO.setClusterName(region.getPhyClusterName());\n        });\n        logicClusterRegionVO.setId(region.getId());\n        logicClusterRegionVO.setLogicClusterIds(region.getLogicClusterIds());\n        logicClusterRegionVO.setClusterName(region.getPhyClusterName());\n        return logicClusterRegionVO;\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> batchBindRegionToClusterLogic(ESLogicClusterWithRegionDTO param, String operator,\n                                                      boolean isAddClusterLogicFlag) throws AdminOperateException {\n        //1. 前置校验\n        if (AriusObjUtils.isNull(param)) {\n            return Result.buildParamIllegal(\"参数为空\");\n        }\n        if (CollectionUtils.isEmpty(param.getClusterRegionDTOS())) {\n            return Result.buildParamIllegal(\"逻辑集群关联region信息为空\");\n        }\n       \n        //2. 集群合法关联性校验\n        for (int i = 0; i < param.getClusterRegionDTOS().size(); i++) {\n            checkCanBeBound(param.getId(), param.getClusterRegionDTOS().get(i), param.getType());\n        }\n      \n\n        //3. 逻辑集群绑定的物理集群版本一致性校验\n        Result<Void> phyClusterVersionsResult = boundPhyClusterVersionsCheck(param);\n        if (phyClusterVersionsResult.failed()) {\n            return Result.buildFrom(phyClusterVersionsResult);\n        }\n\n        //4. 是否要创建逻辑集群\n        if (isAddClusterLogicFlag) {\n            param.setDataCenter(EnvUtil.getDC().getCode());\n            Result<Long> createLogicClusterResult = clusterLogicService.createClusterLogic(param);\n            if (createLogicClusterResult.failed()) {\n                return Result.buildFrom(createLogicClusterResult);\n            }\n            param.setId(createLogicClusterResult.getData());\n        }\n    \n\n        //6. 为逻辑集群绑定region\n        return doBindRegionToClusterLogic(param, operator);\n    }\n\n    @Override\n    public Result<List<ClusterRegionWithNodeInfoVO>> listClusterRegionWithNodeInfoByClusterName(String clusterName) {\n        List<ClusterRegion> clusterRegions = clusterRegionService.listRegionsByClusterName(clusterName);\n        if (CollectionUtils.isEmpty(clusterRegions)) {\n            return Result.buildSucc();\n        }\n\n        // 构建region中的节点信息\n        List<ClusterRegionWithNodeInfoVO> clusterRegionWithNodeInfoVOS = ConvertUtil.list2List(clusterRegions,\n            ClusterRegionWithNodeInfoVO.class, region -> region.setClusterName(clusterName));\n        for (ClusterRegionWithNodeInfoVO clusterRegionWithNodeInfoVO : clusterRegionWithNodeInfoVOS) {\n            Result<List<ClusterRoleHost>> ret = clusterRoleHostService\n                .listByRegionId(clusterRegionWithNodeInfoVO.getId().intValue());\n            if (ret.success() && CollectionUtils.isNotEmpty(ret.getData())) {\n                List<ClusterRoleHost> data = ret.getData();\n                List<String> nodeNameList = data.stream().filter(Objects::nonNull).map(ClusterRoleHost::getNodeSet)\n                    .distinct().collect(Collectors.toList());\n                String nodeNames = ListUtils.strList2String(nodeNameList);\n                clusterRegionWithNodeInfoVO.setNodeNames(nodeNames);\n            }\n        }\n\n        return Result.buildSucc(clusterRegionWithNodeInfoVOS.stream().filter(r -> !AriusObjUtils.isBlank(r.getName()))\n            .distinct().collect(Collectors.toList()));\n    }\n\n    @Override\n    public Result<List<ClusterRegionVO>> listNotEmptyClusterRegionByClusterName(String clusterName) {\n        Result<List<ClusterRegionWithNodeInfoVO>> ret = listClusterRegionWithNodeInfoByClusterName(clusterName);\n        if (ret.failed()) {\n            return Result.buildFrom(ret);\n        }\n\n        List<ClusterRegionWithNodeInfoVO> data = ret.getData();\n        if (CollectionUtils.isEmpty(data)) {\n            return Result.buildSucc();\n        }\n\n        // 过滤空region\n        List<ClusterRegionVO> validClusterRegionVOList = data.stream()\n            .filter(r -> Objects.nonNull(r) && !AriusObjUtils.isBlank(r.getNodeNames())).collect(Collectors.toList());\n\n        return Result.buildSucc(validClusterRegionVOList);\n    }\n\n    /**\n     * @param regionId\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> deletePhyClusterRegion(Long regionId, String operator,\n                                               Integer projectId) throws AdminOperateException {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return result;\n        }\n        ClusterRegion region = clusterRegionService.getRegionById(regionId);\n        if (null == region) {\n            return Result.buildFail(String.format(\"region[%s]不存在\", regionId));\n        }\n\n        Result<Void> deletResult = clusterRegionService.deletePhyClusterRegion(regionId, operator);\n        if (deletResult.success()) {\n            // 释放region中的节点\n            Result<List<ClusterRoleHost>> ret = clusterRoleHostService.listByRegionId(regionId.intValue());\n            if (ret.failed()) {\n                throw new AdminOperateException(String.format(\"删除region失败, msg:%s\", ret.getMessage()));\n            }\n            List<ClusterRoleHost> nodeList = ret.getData();\n            if (CollectionUtils.isNotEmpty(nodeList)) {\n                List<Integer> unBindingNodeIds = nodeList.stream().map(ClusterRoleHost::getId).map(Long::intValue)\n                    .collect(Collectors.toList());\n                ClusterRegionWithNodeInfoDTO clusterRegionWithNodeInfoDTO = new ClusterRegionWithNodeInfoDTO();\n                clusterRegionWithNodeInfoDTO.setId(regionId);\n                clusterRegionWithNodeInfoDTO.setUnBindingNodeIds(unBindingNodeIds);\n                clusterRegionWithNodeInfoDTO.setPhyClusterName(region.getPhyClusterName());\n                clusterRegionWithNodeInfoDTO.setName(region.getName());\n\n                Result<Boolean> editMultiNode2RegionRet = clusterNodeManager\n                    .editMultiNode2Region(Lists.newArrayList(clusterRegionWithNodeInfoDTO), operator, projectId, OperationEnum.DELETE);\n                if (editMultiNode2RegionRet.failed()) {\n                    throw new AdminOperateException(\n                        String.format(\"删除region失败, msg:%s\", editMultiNode2RegionRet.getMessage()));\n                }\n            }\n\n            //CLUSTER_REGION, DELETE, regionId, \"\", operator\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"集群: %s, region 删除：%s, 删除的 regionId：%s\", region.getPhyClusterName(),\n                            region.getName(), regionId), operator, AuthConstant.SUPER_PROJECT_ID, regionId,\n                    OperateTypeEnum.PHYSICAL_CLUSTER_REGION_CHANGE);\n        }\n\n        return deletResult;\n    }\n\n    \n    \n\n    /**\n     * @param phyCluster\n     * @return\n     */\n    @Override\n    public List<ClusterRegion> getColdRegionByPhyCluster(String phyCluster) {\n        List<ClusterRegion> clusterRegions = clusterRegionService.listPhyClusterRegions(phyCluster);\n        //冷region是不会保存在逻辑集群侧的，所以这里关联的region肯定是大于1的，如果是小于1，那么是一定不会具备的\n        if (clusterRegions.size()<=1){\n            return Collections.emptyList();\n        }\n          return clusterRegions.stream().filter(coldTruePreByClusterRegion).collect(Collectors.toList());\n    }\n    \n    /**\n     * @param phyCluster\n     * @return\n     */\n    @Override\n    public List<ClusterRegion> listRegionByPhyCluster(String phyCluster) {\n        return clusterRegionService.listPhyClusterRegions(phyCluster);\n    }\n    \n    \n    \n    /**\n     * > 通过逻辑集群 id 构建逻辑集群region vo\n     *\n     * @param logicClusterId 逻辑集群 ID\n     * @return 列表<ClusterRegionVO>\n     */\n    @Override\n    public Result<List<ClusterRegionVO>> buildLogicClusterRegionVOByLogicClusterId(Long logicClusterId) {\n        final ClusterRegion region = clusterRegionService.getRegionByLogicClusterId(logicClusterId);\n    \n        return Result.buildSucc(buildLogicClusterRegionVO(Collections.singletonList(region)));\n    }\n    \n    \n    /***************************************** private method ****************************************************/\n     private final static Predicate<ClusterRegion> coldTruePreByClusterRegion = clusterRegion -> {\n        if (StringUtils.isBlank(clusterRegion.getConfig())) {\n            return Boolean.FALSE;\n        }\n        try {\n            return JSON.parseObject(clusterRegion.getConfig()).getBoolean(COLD);\n        \n        } catch (Exception e) {\n            return Boolean.FALSE;\n        }\n    \n    };\n\n    private final static Predicate<ClusterRegion> notColdTruePreByClusterRegion = clusterRegion -> {\n        if (StringUtils.isBlank(clusterRegion.getConfig())) {\n            return Boolean.TRUE;\n        }\n        try {\n            return !JSON.parseObject(clusterRegion.getConfig()).getBoolean(COLD);\n        } catch (Exception e) {\n            return Boolean.TRUE;\n        }\n\n    };\n\n    private Boolean checkRegionHostNumAndSpec(Long regionId, ClusterLogicSpecCondition condition){\n        Result<List<ClusterRoleHost>> result = clusterRoleHostService.listByRegionId(regionId.intValue());\n        if(result.failed()){\n            return Boolean.FALSE;\n        }\n\n        // 要求region节点数要大于等于申请的逻辑集群节点数\n        List<ClusterRoleHost> data = result.getData();\n        if(AriusObjUtils.isEmptyList(data) || data.size() < condition.getHostNum()){\n            return Boolean.FALSE;\n        }\n\n        // 要求region的节点规格都要是申请的逻辑集群的节点规格\n        boolean specCheck = data.stream().allMatch(s -> s.getMachineSpec().equals(condition.getMachineSpec()));\n        if(Boolean.FALSE.equals(specCheck)){\n            return Boolean.FALSE;\n        }\n\n        return Boolean.TRUE;\n    }\n\n    /**\n     * 对于逻辑集群绑定的物理集群的版本进行一致性校验\n     *\n     * @param param     逻辑集群Region\n     * @return\n     */\n    private Result<Void> boundPhyClusterVersionsCheck(ESLogicClusterWithRegionDTO param) {\n        Set<String> boundPhyClusterVersions = Sets.newHashSet();\n        for (ClusterRegionDTO clusterRegionDTO : param.getClusterRegionDTOS()) {\n            ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterRegionDTO.getPhyClusterName());\n            if (clusterPhy == null) {\n                return Result.buildFail(\"region对应的物理集群信息为空\");\n            }\n\n            if (clusterPhy.getEsVersion() == null) {\n                return Result.buildFail(\"region对应的物理集群信息对应的版本号不不存在\");\n            }\n            boundPhyClusterVersions.add(clusterPhy.getEsVersion());\n        }\n\n        if (boundPhyClusterVersions.size() != 1) {\n            return Result.buildFail(\"逻辑集群绑定的物理集群的版本号应该一致\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 校验region是否可以被逻辑集群绑定\n     * @param clusterLogicId         逻辑集群Id\n     * @param clusterRegionDTO       region信息\n     * @param clusterLogicType       逻辑集群类型\n     */\n    private void checkCanBeBound(Long clusterLogicId, ClusterRegionDTO clusterRegionDTO,\n                                 Integer clusterLogicType) throws AdminOperateException {\n        Result<Boolean> validResult = canClusterLogicAssociatedPhyCluster(clusterLogicId,\n            clusterRegionDTO.getPhyClusterName(), clusterRegionDTO.getId(), clusterLogicType);\n        if (validResult.failed()) {\n            throw new AdminOperateException(validResult.getMessage(), FAIL);\n        }\n    }\n    public Result<Boolean> canClusterLogicAssociatedPhyCluster(Long clusterLogicId, String clusterPhyName,\n                                                               Long regionId, Integer clusterLogicType) {\n        //新建时clusterLogicId为空, 防止NPE\n        if (AriusObjUtils.isNull(clusterLogicId)) {\n            clusterLogicId = -1L;\n        }\n        /** todo 后续下线\n         ClusterLogicContext clusterLogicContext = getClusterLogicContext(clusterLogicId);\n         ClusterPhyContext clusterPhyContext = getClusterPhyContext(clusterPhyName);\n         int associatedPhyNum = 0;\n         int associatedLogicNum = 0;\n         if (null != clusterLogicContext) {\n         associatedPhyNum = clusterLogicContext.getAssociatedPhyNum();\n         }\n         if (null != clusterPhyContext) {\n         associatedLogicNum = clusterPhyContext.getAssociatedLogicNum();\n         }**/\n        int associatedPhyNum = getAssociatedPhyNumByLogicId(clusterLogicId);\n       \n        int associatedLogicNum =getAssociatedLogicNumByClusterPhy(clusterPhyName);\n       \n\n        return doValid(associatedPhyNum, associatedLogicNum, clusterLogicId, clusterPhyName, regionId,\n            clusterLogicType);\n    }\n    \n    private int getAssociatedLogicNumByClusterPhy(String clusterPhyName) {\n         // 1. set region\n        List<ClusterRegion> regions = clusterRegionService.listPhyClusterRegions(clusterPhyName);\n\n        // 2. set ClusterLogicInfo\n        Set<Long> associatedClusterLogicIds = Sets.newHashSet();\n        for (ClusterRegion clusterRegion : regions) {\n            // 添加每一个物理集群下每一个region所被绑定的逻辑集群\n            List<Long> logicClusterIds = ListUtils.string2LongList(clusterRegion.getLogicClusterIds());\n            if (!CollectionUtils.isEmpty(logicClusterIds)\n                && !logicClusterIds.contains(Long.parseLong(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID))) {\n                associatedClusterLogicIds.addAll(logicClusterIds);\n            }\n        }\n        return associatedClusterLogicIds.size();\n    }\n    \n    private int getAssociatedPhyNumByLogicId(Long clusterLogicId) {\n        if (Objects.equals(clusterLogicId,-1L)){\n            return 0;\n        }\n         // 获取逻辑集群已关联的 Region 信息\n        List<ClusterRegion> regions = clusterRegionService.getClusterRegionsByLogicIds(\n                Collections.singletonList(clusterLogicId));\n         // 获取逻辑集群关联 region 下的 rack 节点信息\n        List<ClusterRoleHost> associatedRackClusterHosts = Lists.newArrayList();\n        for (ClusterRegion region : regions) {\n            Result<List<ClusterRoleHost>> regionDataNodeListRet = clusterRoleHostService.listByRegionId(\n                    region.getId().intValue());\n            if (regionDataNodeListRet.failed()) {\n                LOGGER.warn(\n                        \"class=ClusterContextManagerImpl||method=setRegionAndAssociatedClusterPhyDataNodeInfo||regionId={}||msg=failed to get regionDataNodeList:{}\",\n                        region.getId(), regionDataNodeListRet.getMessage());\n                continue;\n            }\n            associatedRackClusterHosts.addAll(regionDataNodeListRet.getData());\n        }\n        \n        // 设置数据节点总数\n       \n        return associatedRackClusterHosts.size();\n    }\n    \n    /**\n     * 具体校验逻辑\n     * @param associatedPhyNumber    逻辑集群关联物理集群个数\n     * @param associatedLogicNumber  物理集群关联逻辑集群个数\n     * @param regionId               需要绑定的regionId\n     * @param clusterLogicType       逻辑集群类型\n     */\n    private Result<Boolean> doValid(int associatedPhyNumber, int associatedLogicNumber, Long clusterLogicId,\n                                    String clusterPhyName, Long regionId, Integer clusterLogicType) {\n\n        if (AriusObjUtils.isNull(clusterLogicType)) {\n            return Result.buildParamIllegal(\"逻辑集群类型为空\");\n        }\n\n        if (UNKNOWN.getCode() == ClusterResourceTypeEnum.valueOf(clusterLogicType).getCode()) {\n            return Result.buildParamIllegal(\"无法识别逻辑集群类型\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterPhyName);\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildFail(\"物理集群不存在\");\n        }\n\n        if (PRIVATE.getCode() == clusterLogicType\n            && !canClusterLogicBoundRegion(regionId, clusterPhyName, clusterLogicId)) {\n            //先判断logic -> phy, 二次关联region需要先校验逻辑集群对应的物理集群数据是否合理\n            if (associatedPhyNumber > 0) {\n                return Result.buildParamIllegal(String.format(\"集群间关联失败 ,该独立逻辑集群%s已有关联物理集群\", clusterLogicId));\n            }\n            //在判断phy -> logic\n            if (associatedLogicNumber > 0) {\n                return Result.buildFail(String.format(\"集群间关联失败, 物理集群%s已有关联逻辑集群\", clusterPhyName));\n            }\n        }\n\n        return Result.buildSucc(Boolean.TRUE);\n    }\n        /**\n     * 判断指定的物理集群下的region是否被对应的逻辑集群绑定\n     * @param regionId regionId\n     * @param clusterPhyName 物理集群名称\n     * @param clusterLogicId 逻辑集群id\n     * @return  true of false\n     */\n    private boolean canClusterLogicBoundRegion(Long regionId, String clusterPhyName, Long clusterLogicId) {\n        ClusterRegion region = clusterRegionService.getRegionById(regionId);\n        ClusterPhyContext clusterPhyContext = getClusterPhyContext(clusterPhyName);\n        List<Long> clusterLogicIds = Optional.ofNullable(clusterPhyContext)\n                .map(ClusterPhyContext::getAssociatedClusterLogicIds).orElse(Collections.emptyList());\n        if (CollectionUtils.isNotEmpty(clusterLogicIds) && !clusterLogicIds.contains(clusterLogicId)) {\n            return false;\n        }\n\n        if (!region.getLogicClusterIds().equals(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID)) {\n            return false;\n        }\n\n        return region.getPhyClusterName().equals(clusterPhyName);\n    }\n    private ClusterLogicContext getClusterLogicContext(Long clusterLogicId) {\n        ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(clusterLogicId);\n        if (null == clusterLogic) {\n            LOGGER.error(\n                    \"class=ClusterContextManagerImpl||method=flushClusterLogicContext||clusterLogicId={}||msg=clusterLogic is empty\",\n                    clusterLogicId);\n            return null;\n        }\n        \n        ClusterLogicContext build = buildInitESClusterLogicContextByType(clusterLogic);\n        setAssociatedClusterPhyInfo(build);\n        setRegionAndAssociatedClusterPhyDataNodeInfo(build);\n        return build;\n    }\n    /**\n     *   定义规则:\n     *   1. Type为独立, LP = 1, PL = 1\n     *   2. Type为共享, LP = n, PL = 1 ,  1 <= n <= 1024   多个逻辑集群共享一个物理集群, 每个逻辑集群关联物理集群一部分region,不可跨其他物理集群，\n     *                                                    多个逻辑集群可关联同一部分region。\n     *   3. Type为独占, LP = 1, PL = n ,  1 <= n <= 1024   一个逻辑集群独占一个或者多个物理集群\n     */\n    private ClusterLogicContext buildInitESClusterLogicContextByType(ClusterLogic clusterLogic) {\n\n        if (PRIVATE.getCode() == clusterLogic.getType() || EXCLUSIVE.getCode() == clusterLogic.getType()) {\n            return ClusterLogicContext.builder().clusterLogicName(clusterLogic.getName())\n                .clusterLogicId(clusterLogic.getId()).logicClusterType(clusterLogic.getType()).associatedPhyNumMax(1)\n                .build();\n        } else if (PUBLIC.getCode() == clusterLogic.getType()) {\n            return ClusterLogicContext.builder().clusterLogicName(clusterLogic.getName())\n                .clusterLogicId(clusterLogic.getId()).logicClusterType(clusterLogic.getType())\n                .associatedPhyNumMax(LOGIC_ASSOCIATED_PHY_MAX_NUMBER).build();\n        } else {\n            LOGGER.error(\n                \"class=ClusterContextManagerImpl||method=buildInitESClusterLogicContextByType||esClusterLogicId={}||msg={}\",\n                clusterLogic.getId(), String.format(\"请确认逻辑集群%s类型是否存在\", clusterLogic.getType()));\n\n            return ClusterLogicContext.builder().clusterLogicName(clusterLogic.getName())\n                .clusterLogicId(clusterLogic.getId()).logicClusterType(clusterLogic.getType()).associatedPhyNumMax(-1)\n                .build();\n        }\n    }\n    \n    private void setAssociatedClusterPhyInfo(ClusterLogicContext build) {\n        List<String> clusterPhyNames = clusterRegionService.listPhysicClusterNames(build.getClusterLogicId());\n        if (build.getAssociatedPhyNumMax() < clusterPhyNames.size()) {\n            LOGGER.error(\"class=ClusterContextManagerImpl||method=setAssociatedClusterPhyInfo\"\n                         + \"||logicClusterType={}||esClusterLogicId={}||msg= 集群间关联超过最大限制数 {}, 请纠正\",\n                    build.getLogicClusterType(), build.getClusterLogicId(), build.getAssociatedPhyNumMax());\n            return;\n        }\n        \n        build.setAssociatedClusterPhyNames(clusterPhyNames);\n        build.setAssociatedPhyNum(clusterPhyNames.size());\n    }\n    \n    private void setRegionAndAssociatedClusterPhyDataNodeInfo(ClusterLogicContext build) {\n        // 获取逻辑集群已关联的 Region 信息\n        List<ClusterRegion> regions = clusterRegionService.getClusterRegionsByLogicIds(\n                Collections.singletonList(build.getClusterLogicId()));\n        build.setAssociatedRegionIds(regions.stream().map(ClusterRegion::getId).collect(Collectors.toList()));\n        \n        // 获取逻辑集群关联 region 下的 rack 节点信息\n        List<ClusterRoleHost> associatedRackClusterHosts = Lists.newArrayList();\n        for (ClusterRegion region : regions) {\n            Result<List<ClusterRoleHost>> regionDataNodeListRet = clusterRoleHostService.listByRegionId(\n                    region.getId().intValue());\n            if (regionDataNodeListRet.failed()) {\n                LOGGER.warn(\n                        \"class=ClusterContextManagerImpl||method=setRegionAndAssociatedClusterPhyDataNodeInfo||regionId={}||msg=failed to get regionDataNodeList:{}\",\n                        region.getId(), regionDataNodeListRet.getMessage());\n                continue;\n            }\n            associatedRackClusterHosts.addAll(regionDataNodeListRet.getData());\n        }\n        \n        // 设置数据节点总数\n        build.setAssociatedDataNodeNum(associatedRackClusterHosts.size());\n        \n        // 设置数据节点 Ip 地址\n        build.setAssociatedDataNodeIps(\n                associatedRackClusterHosts.stream().map(ClusterRoleHost::getIp).collect(Collectors.toList()));\n    }\n    \n    private ClusterPhyContext getClusterPhyContext(String clusterPhyName) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterPhyName);\n        if (null == clusterPhy) {\n            LOGGER.error(\n                    \"class=ClusterContextManagerImpl||method=flushClusterPhyContext||clusterPhyName={}||msg=clusterPhy is empty\",\n                    clusterPhyName);\n            return null;\n        }\n        \n        ClusterPhyContext build = ClusterPhyContext.builder().clusterPhyId(clusterPhy.getId().longValue())\n                .clusterName(clusterPhy.getCluster()).associatedLogicNumMax(PHY_ASSOCIATED_LOGIC_MAX_NUMBER).build();\n        \n        setClusterPhyNodeInfo(build);\n        setRegionAndClusterLogicInfoAndProjectId(build);\n        return build;\n    }\n     private void setRegionAndClusterLogicInfoAndProjectId(ClusterPhyContext build) {\n        // 1. set region\n        List<ClusterRegion> regions = clusterRegionService.listPhyClusterRegions(build.getClusterName());\n        build.setAssociatedRegionIds(regions.stream().map(ClusterRegion::getId).collect(Collectors.toList()));\n\n        // 2. set ClusterLogicInfo\n        Set<Long> associatedClusterLogicIds = Sets.newHashSet();\n        for (ClusterRegion clusterRegion : regions) {\n            // 添加每一个物理集群下每一个region所被绑定的逻辑集群\n            List<Long> logicClusterIds = ListUtils.string2LongList(clusterRegion.getLogicClusterIds());\n            if (!CollectionUtils.isEmpty(logicClusterIds)\n                && !logicClusterIds.contains(Long.parseLong(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID))) {\n                associatedClusterLogicIds.addAll(logicClusterIds);\n            }\n        }\n\n        build.setAssociatedClusterLogicIds(Lists.newArrayList(associatedClusterLogicIds));\n        build.setAssociatedLogicNum(associatedClusterLogicIds.size());\n\n        // 3. set projectId\n        Set<Integer> projectIdSet = new HashSet<>();\n        Set<String> clusterLogicSet = new HashSet<>();\n        if (!CollectionUtils.isEmpty(associatedClusterLogicIds)) {\n            for (Long associatedClusterLogicId : associatedClusterLogicIds) {\n                clusterLogicService.listClusterLogicByIdThatProjectIdStrConvertProjectIdList(associatedClusterLogicId).stream().filter(Objects::nonNull)\n                        .filter(clusterLogic -> null != clusterLogic.getProjectId() && null != clusterLogic.getName())\n                        .forEach(clusterLogic -> {\n                            projectIdSet.add(clusterLogic.getProjectId());\n                            clusterLogicSet.add(clusterLogic.getName());\n                        });\n                \n            }\n        }\n\n        build.setAssociatedProjectIds(Lists.newArrayList(projectIdSet));\n        build.setAssociatedProjectNames(Lists.newArrayList(clusterLogicSet));\n    }\n    private void setClusterPhyNodeInfo(ClusterPhyContext build) {\n        List<ClusterRoleHost> nodes = clusterRoleHostService.getNodesByCluster(build.getClusterName());\n        List<ClusterRoleHost> dataNodes = nodes.stream().filter(r -> DATA_NODE.getCode() == r.getRole())\n            .collect(Collectors.toList());\n\n        build.setAssociatedDataNodeNum(dataNodes.size());\n        build.setAssociatedDataNodeIps(dataNodes.stream().map(ClusterRoleHost::getIp).collect(Collectors.toList()));\n        build.setAssociatedNodeIps(nodes.stream().map(ClusterRoleHost::getIp).collect(Collectors.toList()));\n    }\n    private Result<Void> doBindRegionToClusterLogic(ESLogicClusterWithRegionDTO param,\n                                                    String operator) throws AdminOperateException {\n        List<ClusterRegionDTO> clusterRegionDTOS = param.getClusterRegionDTOS();\n        if (CollectionUtils.isEmpty(clusterRegionDTOS)) {\n            return Result.buildParamIllegal(\"region相关参数非法\");\n        }\n\n        for (ClusterRegionDTO clusterRegionDTO : clusterRegionDTOS) {\n            Result<Void> bindRegionResult = clusterRegionService.bindRegion(clusterRegionDTO.getId(), param.getId(),\n                null, operator);\n            if (bindRegionResult.failed()) {\n                throw new AdminOperateException(bindRegionResult.getMessage(), FAIL);\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n\n\n\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/cluster/impl/ESClusterConfigManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.cluster.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ESClusterConfigManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.esconfig.ESConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm.ESConfigVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESClusterConfigService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class ESClusterConfigManagerImpl implements ESClusterConfigManager {\n    @Autowired\n    private ESClusterConfigService esClusterConfigService;\n    @Autowired\n    private OperateRecordService   operateRecordService;\n    @Autowired\n    private ClusterRoleService     clusterRoleService;\n\n    /**\n     * 编辑configdesc\n     *\n     * @param param     入参\n     * @param operator  操作人或角色\n     * @param projectId 项目id\n     * @return {@code Result<Void>}\n     */\n    @Override\n    public Result<Void> editConfigDesc(ESConfigDTO param, String operator, Integer projectId) {\n        final Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (checkProjectCorrectly.failed()) {\n            return checkProjectCorrectly;\n        }\n        final ESConfig oldEsConfig = esClusterConfigService.getEsClusterConfigById(param.getId());\n        final Result<Void> result = esClusterConfigService.editConfigDesc(param);\n        if (result.success()) {\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"描述变更：【%s】->【%s】\", oldEsConfig.getDesc(), param.getDesc()), operator, projectId,\n                    param.getId(), OperateTypeEnum.PHYSICAL_CLUSTER_CONF_FILE_CHANGE);\n        }\n        return result;\n    }\n\n    /**\n     * 获取ES集群模板config\n     *\n     * @param type 类型\n     * @return {@code Result<ESConfigVO>}\n     */\n    @Override\n    public Result<ESConfigVO> getEsClusterTemplateConfig(String type) {\n        return Result\n            .buildSucc(ConvertUtil.obj2Obj(esClusterConfigService.getEsClusterTemplateConfig(type), ESConfigVO.class));\n\n    }\n\n    /**\n     * @param clusterId\n     * @return\n     */\n    @Override\n    public Result<Set<String>> gainEsClusterRoles(Long clusterId) {\n        List<ClusterRoleInfo> clusterRoleInfos = clusterRoleService.getAllRoleClusterByClusterId(clusterId.intValue());\n        return Result.buildSucc(clusterRoleInfos.stream().filter(Objects::nonNull).map(ClusterRoleInfo::getRole)\n            .collect(Collectors.toSet()));\n    }\n\n    /**\n     * @param configId\n     * @return\n     */\n    @Override\n    public Result<ESConfigVO> getEsClusterConfigById(Long configId) {\n        return Result\n            .buildSucc(ConvertUtil.obj2Obj(esClusterConfigService.getEsClusterConfigById(configId), ESConfigVO.class));\n    }\n\n    /**\n     * 获得ES集群配置\n     *\n     * @param clusterId 集群id\n     * @return {@code Result<List<ESConfigVO>>}\n     */\n    @Override\n    public Result<List<ESConfigVO>> gainEsClusterConfigs(Long clusterId) {\n        Result<List<ESConfig>> listResult = esClusterConfigService.listEsClusterConfigByClusterId(clusterId);\n        return Result.buildSucc(ConvertUtil.list2List(listResult.getData(), ESConfigVO.class));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/component/MetricsValueConvertUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.component;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyNodeMetricsEnum.getPercentMetricsType;\n\nimport java.util.List;\n\nimport org.apache.commons.collections4.CollectionUtils;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContentCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.percentiles.ESPercentileMetricsVO;\n\n/**\n * Created by linyunan on 2021-09-07\n */\npublic class MetricsValueConvertUtils {\n\n    private MetricsValueConvertUtils() {\n    }\n\n    /**\n     * uniform cluster overview percentage unit\n     *\n     * @param esClusterOverviewMetricsVO\n     */\n    public static void convertClusterOverviewMetricsPercent(ESClusterOverviewMetricsVO esClusterOverviewMetricsVO) {\n        List<DiskUsageMetricsVO> diskUsagesMetrics = esClusterOverviewMetricsVO.getDiskUsage();\n        if (CollectionUtils.isEmpty(diskUsagesMetrics)) {\n            return;\n        }\n\n        diskUsagesMetrics.forEach(element -> {\n            element.setAggType(element.getAggType() * 100);\n            element.setSt99(element.getSt99() * 100);\n            element.setSt95(element.getSt95() * 100);\n            element.setSt75(element.getSt75() * 100);\n            element.setSt55(element.getSt55() * 100);\n        });\n    }\n\n    /**\n     * uniform clusterPhy node percentage unit\n     * @param variousLineChartMetrics\n     */\n    public static void convertClusterPhyMetricsPercent(List<VariousLineChartMetrics> variousLineChartMetrics) {\n        variousLineChartMetrics.parallelStream().filter(element -> getPercentMetricsType().contains(element.getType()))\n            .forEach(MetricsValueConvertUtils::convertCell);\n    }\n\n    /***************************************************cluster overview**********************************************************/\n    public static void doOptimizeForWriteTps(List<WriteTPSMetricsVO> writeTpsList) {\n        if (CollectionUtils.isEmpty(writeTpsList)) {\n            return;\n        }\n\n        for (int i = 0; i < writeTpsList.size(); i++) {\n            WriteTPSMetricsVO currentMetrics = writeTpsList.get(i);\n            WriteTPSMetricsVO frontMetrics = null;\n            WriteTPSMetricsVO backMetrics = null;\n            WriteTPSMetricsVO backNextMetrics = null;\n\n            if (i == 0) {\n                backMetrics = writeTpsList.get(i + 1);\n            } else if (i == writeTpsList.size() - 1) {\n                frontMetrics = writeTpsList.get(i - 1);\n            } else {\n                if (i != writeTpsList.size() - 2) {\n                    backNextMetrics = writeTpsList.get(i + 2);\n                }\n                backMetrics = writeTpsList.get(i + 1);\n                frontMetrics = writeTpsList.get(i - 1);\n            }\n\n            if (currentMetrics.getWriteTps() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getWriteTps() : 0;\n                double backValue = null != backMetrics ? backMetrics.getWriteTps() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getWriteTps() : 0;\n                currentMetrics.setWriteTps(compute(currentMetrics.getWriteTps(), frontValue, backValue, backNextValue));\n            }\n        }\n    }\n\n    public static void doOptimizeForReadTps(List<ReadQPSMetricsVO> readTpsList) {\n        if (CollectionUtils.isEmpty(readTpsList)) {\n            return;\n        }\n\n        for (int i = 0; i < readTpsList.size(); i++) {\n            ReadQPSMetricsVO currentMetrics = readTpsList.get(i);\n            ReadQPSMetricsVO frontMetrics = null;\n            ReadQPSMetricsVO backMetrics = null;\n            ReadQPSMetricsVO backNextMetrics = null;\n\n            if (i == 0) {\n                backMetrics = readTpsList.get(i + 1);\n            } else if (i == readTpsList.size() - 1) {\n                frontMetrics = readTpsList.get(i - 1);\n            } else {\n                if (i != readTpsList.size() - 2) {\n                    backNextMetrics = readTpsList.get(i + 2);\n                }\n                backMetrics = readTpsList.get(i + 1);\n                frontMetrics = readTpsList.get(i - 1);\n            }\n\n            if (currentMetrics.getReadTps() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getReadTps() : 0;\n                double backValue = null != backMetrics ? backMetrics.getReadTps() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getReadTps() : 0;\n                currentMetrics.setReadTps(compute(currentMetrics.getReadTps(), frontValue, backValue, backNextValue));\n            }\n        }\n    }\n\n    public static void doOptimizeForShardNu(List<ShardInfoMetricsVO> shardNuList) {\n        if (CollectionUtils.isEmpty(shardNuList)) {\n            return;\n        }\n\n        for (int i = 0; i < shardNuList.size(); i++) {\n            ShardInfoMetricsVO currentMetrics = shardNuList.get(i);\n            ShardInfoMetricsVO frontMetrics = null;\n            ShardInfoMetricsVO backMetrics = null;\n            ShardInfoMetricsVO backNextMetrics = null;\n\n            if (i == 0) {\n                backMetrics = shardNuList.get(i + 1);\n            } else if (i == shardNuList.size() - 1) {\n                frontMetrics = shardNuList.get(i - 1);\n            } else {\n                if (i != shardNuList.size() - 2) {\n                    backNextMetrics = shardNuList.get(i + 2);\n                }\n                backMetrics = shardNuList.get(i + 1);\n                frontMetrics = shardNuList.get(i - 1);\n            }\n\n            if (currentMetrics.getUnAssignedShards() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getUnAssignedShards() : 0;\n                double backValue = null != backMetrics ? backMetrics.getUnAssignedShards() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getUnAssignedShards() : 0;\n                currentMetrics.setUnAssignedShards(\n                    (long) compute(currentMetrics.getUnAssignedShards(), frontValue, backValue, backNextValue));\n            }\n\n            if (currentMetrics.getShardNu() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getShardNu() : 0;\n                double backValue = null != backMetrics ? backMetrics.getShardNu() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getShardNu() : 0;\n                currentMetrics\n                    .setShardNu((long) compute(currentMetrics.getShardNu(), frontValue, backValue, backNextValue));\n            }\n        }\n    }\n\n    public static void doOptimizeForDiskInfo(List<DiskInfoMetricsVO> diskInfoList) {\n        if (CollectionUtils.isEmpty(diskInfoList)) {\n            return;\n        }\n\n        for (int i = 0; i < diskInfoList.size(); i++) {\n            DiskInfoMetricsVO currentMetrics = diskInfoList.get(i);\n            DiskInfoMetricsVO frontMetrics = null;\n            DiskInfoMetricsVO backMetrics = null;\n            DiskInfoMetricsVO backNextMetrics = null;\n\n            if (i == 0) {\n                backMetrics = diskInfoList.get(i + 1);\n            } else if (i == diskInfoList.size() - 1) {\n                frontMetrics = diskInfoList.get(i - 1);\n            } else {\n                if (i != diskInfoList.size() - 2) {\n                    backNextMetrics = diskInfoList.get(i + 2);\n                }\n                backMetrics = diskInfoList.get(i + 1);\n                frontMetrics = diskInfoList.get(i - 1);\n            }\n\n            if (currentMetrics.getFreeStoreSize() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getFreeStoreSize() : 0;\n                double backValue = null != backMetrics ? backMetrics.getFreeStoreSize() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getFreeStoreSize() : 0;\n                currentMetrics\n                    .setFreeStoreSize(compute(currentMetrics.getFreeStoreSize(), frontValue, backValue, backNextValue));\n            }\n\n            if (currentMetrics.getStoreSize() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getStoreSize() : 0;\n                double backValue = null != backMetrics ? backMetrics.getStoreSize() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getStoreSize() : 0;\n                currentMetrics\n                    .setStoreSize(compute(currentMetrics.getStoreSize(), frontValue, backValue, backNextValue));\n            }\n\n            if (currentMetrics.getTotalStoreSize() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getTotalStoreSize() : 0;\n                double backValue = null != backMetrics ? backMetrics.getTotalStoreSize() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getTotalStoreSize() : 0;\n                currentMetrics.setTotalStoreSize(\n                    compute(currentMetrics.getTotalStoreSize(), frontValue, backValue, backNextValue));\n            }\n        }\n    }\n\n    public static void doOptimizeForSendTransSize(List<SendTransMetricsVO> sendTransSizeList) {\n        if (CollectionUtils.isEmpty(sendTransSizeList)) {\n            return;\n        }\n\n        for (int i = 0; i < sendTransSizeList.size(); i++) {\n            SendTransMetricsVO currentMetrics = sendTransSizeList.get(i);\n            SendTransMetricsVO frontMetrics = null;\n            SendTransMetricsVO backMetrics = null;\n            SendTransMetricsVO backNextMetrics = null;\n\n            if (i == 0) {\n                backMetrics = sendTransSizeList.get(i + 1);\n            } else if (i == sendTransSizeList.size() - 1) {\n                frontMetrics = sendTransSizeList.get(i - 1);\n            } else {\n                if (i != sendTransSizeList.size() - 2) {\n                    backNextMetrics = sendTransSizeList.get(i + 2);\n                }\n                backMetrics = sendTransSizeList.get(i + 1);\n                frontMetrics = sendTransSizeList.get(i - 1);\n            }\n\n            if (currentMetrics.getSendTransSize() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getSendTransSize() : 0;\n                double backValue = null != backMetrics ? backMetrics.getSendTransSize() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getSendTransSize() : 0;\n                currentMetrics\n                    .setSendTransSize(compute(currentMetrics.getSendTransSize(), frontValue, backValue, backNextValue));\n            }\n        }\n    }\n\n    public static void doOptimizeForRecvTransSize(List<RecvTransMetricsVO> recvTransSizeList) {\n        if (CollectionUtils.isEmpty(recvTransSizeList)) {\n            return;\n        }\n\n        for (int i = 0; i < recvTransSizeList.size(); i++) {\n            RecvTransMetricsVO currentMetrics = recvTransSizeList.get(i);\n            RecvTransMetricsVO frontMetrics = null;\n            RecvTransMetricsVO backMetrics = null;\n            RecvTransMetricsVO backNextMetrics = null;\n\n            if (i == 0) {\n                backMetrics = recvTransSizeList.get(i + 1);\n            } else if (i == recvTransSizeList.size() - 1) {\n                frontMetrics = recvTransSizeList.get(i - 1);\n            } else {\n                if (i != recvTransSizeList.size() - 2) {\n                    backNextMetrics = recvTransSizeList.get(i + 2);\n                }\n                backMetrics = recvTransSizeList.get(i + 1);\n                frontMetrics = recvTransSizeList.get(i - 1);\n            }\n\n            if (currentMetrics.getRecvTransSize() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getRecvTransSize() : 0;\n                double backValue = null != backMetrics ? backMetrics.getRecvTransSize() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getRecvTransSize() : 0;\n                currentMetrics\n                    .setRecvTransSize(compute(currentMetrics.getRecvTransSize(), frontValue, backValue, backNextValue));\n            }\n        }\n    }\n\n    public static void doOptimizeForPercentiles(List<? extends ESPercentileMetricsVO> percentilesMetricsVOList) {\n        if (CollectionUtils.isEmpty(percentilesMetricsVOList)) {\n            return;\n        }\n\n        for (int i = 0; i < percentilesMetricsVOList.size(); i++) {\n            ESPercentileMetricsVO currentMetrics = percentilesMetricsVOList.get(i);\n            ESPercentileMetricsVO frontMetrics = null;\n            ESPercentileMetricsVO backMetrics = null;\n            // The forward second time point of the current time slice is still zero\n            ESPercentileMetricsVO backNextMetrics = null;\n\n            if (i == 0) {\n                backMetrics = percentilesMetricsVOList.get(i + 1);\n            } else if (i == percentilesMetricsVOList.size() - 1) {\n                frontMetrics = percentilesMetricsVOList.get(i - 1);\n            } else {\n                if (i != percentilesMetricsVOList.size() - 2) {\n                    backNextMetrics = percentilesMetricsVOList.get(i + 2);\n                }\n                backMetrics = percentilesMetricsVOList.get(i + 1);\n                frontMetrics = percentilesMetricsVOList.get(i - 1);\n            }\n\n            //compute avgst\n            if (currentMetrics.getAggType() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getAggType() : 0;\n                double backValue = null != backMetrics ? backMetrics.getAggType() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getAggType() : 0;\n                currentMetrics.setAggType(compute(currentMetrics.getAggType(), frontValue, backValue, backNextValue));\n            }\n\n            //compute 99st\n            if (currentMetrics.getSt99() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getSt99() : 0;\n                double backValue = null != backMetrics ? backMetrics.getSt99() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getSt99() : 0;\n                currentMetrics.setSt99(compute(currentMetrics.getSt99(), frontValue, backValue, backNextValue));\n            }\n\n            //compute 95st\n            if (currentMetrics.getSt95() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getSt95() : 0;\n                double backValue = null != backMetrics ? backMetrics.getSt95() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getSt95() : 0;\n                currentMetrics.setSt95(compute(currentMetrics.getSt95(), frontValue, backValue, backNextValue));\n            }\n\n            //compute 75st\n            if (currentMetrics.getSt75() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getSt75() : 0;\n                double backValue = null != backMetrics ? backMetrics.getSt75() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getSt75() : 0;\n                currentMetrics.setSt75(compute(currentMetrics.getSt75(), frontValue, backValue, backNextValue));\n            }\n\n            //compute 55st\n            if (currentMetrics.getSt55() <= 0) {\n                double frontValue = null != frontMetrics ? frontMetrics.getSt55() : 0;\n                double backValue = null != backMetrics ? backMetrics.getSt55() : 0;\n                double backNextValue = null != backNextMetrics ? backNextMetrics.getSt55() : 0;\n                currentMetrics.setSt55(compute(currentMetrics.getSt55(), frontValue, backValue, backNextValue));\n            }\n        }\n    }\n\n    /***************************************************cluster node*************************************************/\n    public static void doOptimizeQueryBurrForNodeOrIndicesMetrics(List<VariousLineChartMetrics> variousLineChartMetrics) {\n        if (CollectionUtils.isEmpty(variousLineChartMetrics)) {\n            return;\n        }\n        //multiple view\n        variousLineChartMetrics.parallelStream().forEach(variousLineChartMetric -> {\n            List<MetricsContent> metricsContentList = variousLineChartMetric.getMetricsContents();\n            if (CollectionUtils.isEmpty(metricsContentList)) {\n                return;\n            }\n            //multiple line\n            for (MetricsContent metricsContent : metricsContentList) {\n\n                //multiple port\n                List<MetricsContentCell> metricsContentCellList = metricsContent.getMetricsContentCells();\n                if (CollectionUtils.isEmpty(metricsContentCellList)) {\n                    return;\n                }\n\n                for (int i = 0; i < metricsContentCellList.size(); i++) {\n                    compensateAbnormalValue(metricsContentCellList, i);\n                }\n            }\n        });\n    }\n\n    private static void compensateAbnormalValue(List<MetricsContentCell> metricsContentCellList, int i) {\n        MetricsContentCell currentMetrics = metricsContentCellList.get(i);\n        double frontValue = i == 0 ? 0 : metricsContentCellList.get(i - 1).getValue();\n        double backValue = i == metricsContentCellList.size() - 1 ? 0 : metricsContentCellList.get(i + 1).getValue();\n        double compensateValue;\n\n        if (i == 0) {\n            // 处理头部掉底\n            compensateValue = backValue;\n        } else if (i == metricsContentCellList.size() - 1) {\n            // 处理尾部掉底\n            compensateValue = frontValue;\n        } else {\n            // 处理中部掉底\n            compensateValue = Math.min(frontValue, backValue);\n        }\n\n        if (currentMetrics.getValue() <= 0) {\n            currentMetrics.setValue(compensateValue);\n        }\n    }\n\n    /***************************************************cluster indices*************************************************/\n    private static double compute(double currentValue, double frontValue, double backValue, double backNextValue) {\n        if (0 >= backNextValue) {\n            return 0;\n        }\n\n        double tempMax;\n        double finalMax;\n        if (0 >= frontValue) {\n            tempMax = Math.max(currentValue, 0);\n        } else {\n            tempMax = Math.max(currentValue, frontValue);\n        }\n\n        if (0 >= backValue) {\n            finalMax = Math.max(tempMax, 0);\n        } else {\n            finalMax = Math.max(tempMax, backValue);\n        }\n\n        return finalMax;\n    }\n\n    private static void convertCell(VariousLineChartMetrics variousLineChartMetrics) {\n        List<MetricsContent> metricsContents = variousLineChartMetrics.getMetricsContents();\n        metricsContents.forEach(metricsContent -> metricsContent.getMetricsContentCells()\n            .forEach(cell -> cell.setValue(cell.getValue() * 100)));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/dsl/DslMetricsManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslTemplateVO;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.SearchDslTemplateResponseVO;\nimport java.util.List;\n\npublic interface DslMetricsManager {\n    /**\n     * 根据projectId获取dsl的指标信息\n     * @param projectId 应用账号\n     * @param startDate 开始时刻\n     * @param endDate 结束时刻\n     * @return list\n     */\n    Result<List<DslTemplateVO>> getDSLMetricsInfoByProjectId(Integer projectId, Long startDate, Long endDate);\n\n    /**\n     * 获取批量dslMetrics接口\n     * @param projectId 应用账号\n     * @param dslTemplateMd5 查询模板MD5\n     * @param startDate 开始时刻\n     * @param endDate 结束时刻\n     * @return list\n     */\n    Result<List<DslMetricsVO>> getDetailMetrics(Integer projectId, String dslTemplateMd5, Long startDate, Long endDate);\n\n    /**\n     * 根据查询条件获取查询模板数据\n     *\n     * @param projectId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    Result<SearchDslTemplateResponseVO> getDslTemplateByCondition(Integer projectId, String searchKeyword,\n                                                                  String dslTag, String sortInfo, Long from, Long size,\n                                                                  Long startDate, Long endDate);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/dsl/DslTemplateManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.DslQueryLimitDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.template.DslTemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.UserConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\n\nimport java.util.List;\n\n/**\n * @author cjm\n */\npublic interface DslTemplateManager {\n\n    /**\n     * 根据appid修改查询模版限流值\n     *\n     * @param dslTemplateList dsl模板限流值信息，待修改限流值\n     * @return Result<Boolean>\n     */\n    Result<Boolean> updateDslTemplateQueryLimit(Integer projectId,String operator,List<DslQueryLimitDTO> dslTemplateList);\n\n    /**\n     * 更新查询模版的 启用|停用 状态\n     *\n     * @param projectId          查询模板对应的projectId\n     * @param dslTemplateMd5 dsl模板MD5\n     * @return Result<Boolean>\n     */\n    Result<Boolean> changeDslTemplateStatus(Integer projectId,String operator, String dslTemplateMd5);\n\n    /**\n     * 根据dslTemplateMd5查找DSL模版详情\n     * @param projectId 应用账号\n     * @param dslTemplateMd5 dsl模板MD5\n     * @return Result<DslTemplateVO>\n     */\n    Result<DslTemplateVO> getDslTemplateDetail(Integer projectId, String dslTemplateMd5);\n\n    /**\n     * 分页获取DSL模版列表信息\n     * @param projectId 应用id\n     * @param queryDTO 查询条件\n     * @return 分页数据\n     */\n    PaginationResult<DslTemplateVO> getDslTemplatePage(Integer projectId,\n                                                       DslTemplateConditionDTO queryDTO) throws NotFindSubclassException;\n\n    /**\n     * 查询查询模板个性化配置\n     * @param param 配置类型\n     * @param operator 用户\n     * @param projectId 用户所属应用\n     * @return\n     */\n    List<String> listConfigDslTemplateFields(UserConfigInfoDTO param, String operator, Integer projectId);\n\n    /**\n     * 更新查询模板个性化配置\n     * @param userConfigInfoDTO\n     * @param userName\n     * @param projectId\n     * @return\n     */\n    Result<Integer> updateConfigDslTemplateFields(UserConfigInfoDTO userConfigInfoDTO, String userName, Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/dsl/impl/DslMetricsManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.dsl.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.dsl.DslMetricsManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.SearchDslTemplateResponseVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.SearchDslTemplateResponse;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.DslMetricsService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n@Component\npublic class DslMetricsManagerImpl implements DslMetricsManager {\n\n    @Autowired\n    private DslMetricsService dslMetricsService;\n\n    @Override\n    public Result<List<DslTemplateVO>> getDSLMetricsInfoByProjectId(Integer projectId, Long startDate, Long endDate) {\n        return Result.buildSucc(ConvertUtil.list2List(\n            dslMetricsService.getDSLMetricsInfoByProjectId(projectId, startDate, endDate).getData(),\n            DslTemplateVO.class));\n    }\n\n    @Override\n    public Result<List<DslMetricsVO>> getDetailMetrics(Integer projectId, String dslTemplateMd5, Long startDate,\n                                                       Long endDate) {\n        return Result.buildSucc(ConvertUtil.list2List(\n            dslMetricsService.getDetailMetrics(projectId, dslTemplateMd5, startDate, endDate).getData(),\n            DslMetricsVO.class));\n    }\n\n    @Override\n    public Result<SearchDslTemplateResponseVO> getDslTemplateByCondition(Integer projectId, String searchKeyword,\n                                                                         String dslTag, String sortInfo, Long from,\n                                                                         Long size, Long startDate, Long endDate) {\n        SearchDslTemplateResponse data = dslMetricsService\n            .getDslTemplateByCondition(projectId, searchKeyword, dslTag, sortInfo, from, size, startDate, endDate)\n            .getData();\n        return Result.buildSucc(ConvertUtil.obj2Obj(data, SearchDslTemplateResponseVO.class));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/dsl/impl/DslTemplateManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.dsl.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum.DSL_TEMPLATE;\n\nimport com.didichuxing.datachannel.arius.admin.biz.dsl.DslTemplateManager;\nimport com.didichuxing.datachannel.arius.admin.biz.page.DslTemplatePageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.DslQueryLimitDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.template.DslTemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.UserConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ConfigTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.metrics.UserConfigService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.DslTemplateService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.StringUtils;\n\n/**\n * @author cjm\n */\n@Component\npublic class DslTemplateManagerImpl implements DslTemplateManager {\n\n    private static final ILog    LOGGER = LogFactory.getLog(DslTemplateManagerImpl.class);\n\n    @Autowired\n    private DslTemplateService   dslTemplateService;\n    @Autowired\n    private OperateRecordService operateRecordService;\n\n\n    @Autowired\n    private HandleFactory        handleFactory;\n    @Autowired\n    private UserConfigService userConfigService;\n    @Override\n    public Result<Boolean> updateDslTemplateQueryLimit(Integer projectId,String operator,List<DslQueryLimitDTO> dslTemplateList) {\n        Boolean succeed =  dslTemplateService.updateDslTemplateQueryLimit(dslTemplateList);\n        if (Boolean.TRUE.equals(succeed)) {\n            for (DslQueryLimitDTO entry : dslTemplateList) {\n                operateRecordService.saveOperateRecordWithManualTrigger(\n                        String.format(\"queryLimit %s->%s\", entry.getDslTemplateMd5(), entry.getQueryLimit()), operator,\n                        projectId, entry.getProjectIdDslTemplateMd5(),\n                        OperateTypeEnum.QUERY_TEMPLATE_DSL_CURRENT_LIMIT_ADJUSTMENT);\n            }\n\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Boolean> changeDslTemplateStatus(Integer projectId,String operator, String dslTemplateMd5) {\n        if (StringUtils.isEmpty(dslTemplateMd5)) {\n            return Result.build(true);\n        }\n       Boolean succeed = dslTemplateService.updateDslTemplateStatus(projectId, dslTemplateMd5);\n        if (Boolean.TRUE.equals(succeed)) {\n            operateRecordService.saveOperateRecordWithManualTrigger(\"变更状态:\" + dslTemplateMd5, operator, projectId,\n                    dslTemplateMd5, OperateTypeEnum.QUERY_TEMPLATE_DISABLE);\n        }\n        return Result.build(succeed);\n    }\n    @Override\n    public Result<DslTemplateVO> getDslTemplateDetail(Integer projectId, String dslTemplateMd5) {\n        if (StringUtils.isEmpty(dslTemplateMd5)) {\n            return Result.buildSucc();\n        }\n        DslTemplatePO dslTemplatePO = dslTemplateService.getDslTemplateDetail(projectId, dslTemplateMd5);\n        return Result.buildSucc(ConvertUtil.obj2Obj(dslTemplatePO, DslTemplateVO.class));\n    }\n\n    @Override\n    public PaginationResult<DslTemplateVO> getDslTemplatePage(Integer projectId,\n                                                              DslTemplateConditionDTO queryDTO) throws NotFindSubclassException {\n        BaseHandle baseHandle = handleFactory.getByHandlerNamePer(DSL_TEMPLATE.getPageSearchType());\n        if (baseHandle instanceof DslTemplatePageSearchHandle) {\n            DslTemplatePageSearchHandle handle = (DslTemplatePageSearchHandle) baseHandle;\n            return handle.doPage(queryDTO, projectId);\n        }\n\n        LOGGER.warn(\n            \"class=DslTemplateManagerImpl||method=getDslTemplatePage||msg=failed to get the DslTemplatePageSearchHandle\");\n\n        return PaginationResult.buildFail(\"分页获取DSL查询模版信息失败\");\n    }\n\n    @Override\n    public List<String> listConfigDslTemplateFields(UserConfigInfoDTO userConfigInfoDTO, String userName, Integer projectId) {\n        userConfigInfoDTO.setUserName(userName);\n        userConfigInfoDTO.setProjectId(projectId);\n        userConfigInfoDTO.setConfigType(ConfigTypeEnum.RETRIEVE_TEMPLATE.getCode());\n        return userConfigService.getUserConfigByConfigTypeAndUserNameAndProjectId(userConfigInfoDTO);\n    }\n\n    @Override\n    public Result<Integer> updateConfigDslTemplateFields(UserConfigInfoDTO param, String userName, Integer projectId) {\n        param.setUserName(userName);\n        param.setProjectId(projectId);\n        param.setConfigType(ConfigTypeEnum.RETRIEVE_TEMPLATE.getCode());\n        Result<Integer> result = userConfigService.updateUserConfigByConfigTypeAndUserNameAndProjectId(param);\n        if (result.failed()) {\n            LOGGER.warn(\"class=DslTemplateManagerImpl||method=updateConfigDslTemplateFields||errMsg={}\",\n                    \"用户查询模板字段配置信息更新出错\");\n        }\n        return result;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/espackage/ESPackageManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.espackage;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESPackageDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.espackage.ESPackage;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.espackage.ESPackageVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.espackage.AriusESPackageEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusOptional;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ESVersionUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPackageService;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author linyunan\n * @date 2021-05-19\n */\n@Component\npublic class ESPackageManager {\n\n    @Autowired\n    private ESPackageService packageService;\n\n    /**\n     * 获取所有的package列表\n     * @return package列表\n     */\n    public Result<List<ESPackageVO>> listESPackage() {\n        List<ESPackage> esPackageList = packageService.listESPackage();\n        if (CollectionUtils.isEmpty(esPackageList)) {\n            return Result.buildSucc();\n        }\n\n        return Result.buildSucc(esPackageList.stream().map(this::buildESPackageVO).collect(Collectors.toList()));\n    }\n\n    /**\n     * 根据id获取es package\n     * @param id 安装包id\n     * @return 安装包\n     */\n    public Result<ESPackageVO> getESPackageById(Long id) {\n        return AriusOptional.ofObjNullable(buildESPackageVO(packageService.getESPackagePOById(id)))\n            .orGetResult(() -> Result.buildFail(\"ES安装包不存在\"));\n    }\n\n    /**\n     * 创建一个Package\n     *\n     * @param esPackageDTO dto\n     * @param operator     操作者\n     * @param projectId\n     * @return 创建数量\n     */\n    public Result<Long> addESPackage(ESPackageDTO esPackageDTO, String operator, Integer projectId) {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(id -> id, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        return packageService.addESPackage(esPackageDTO, operator);\n    }\n\n    /**\n     * 修改ES package\n     *\n     * @param esPackageDTO dto\n     * @param operator     操作者\n     * @param projectId\n     * @return 更新的es package\n     */\n    public Result<ESPackageVO> updateESPackage(ESPackageDTO esPackageDTO, String operator, Integer projectId) {\n\n        Result<ESPackage> esPackageResult = packageService.updateESPackage(esPackageDTO, operator, projectId);\n        if (esPackageResult.failed()) {\n            return Result.buildFail(esPackageResult.getMessage());\n        }\n\n        return Result.buildSucc(buildESPackageVO(esPackageResult.getData()));\n    }\n\n    /**\n     * 构建es package vo\n     * @param esPackage es安装包\n     * @return\n     */\n    private ESPackageVO buildESPackageVO(ESPackage esPackage) {\n        ESPackageVO esPackageVO = ConvertUtil.obj2Obj(esPackage, ESPackageVO.class);\n\n        // 根据es程序包的版本号判断是否为滴滴内部版本，当版本号为四位时，表示为滴滴内部版本，否则为外部开源的版本\n        esPackageVO.setPackageType(\n            AriusESPackageEnum.valueOfLength(ESVersionUtil.getVersionLength(esPackage.getEsVersion())).getCode());\n\n        return esPackageVO;\n    }\n\n    /**\n     * 删除es对应的package\n     *\n     * @param id        插件包\n     * @param operator  操作人\n     * @param projectId\n     * @return\n     */\n    public Result<Long> deleteESPackage(Long id, String operator, Integer projectId) throws NotFindSubclassException {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        return packageService.deleteESPackage(id, operator);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/extend/foctory/ExtendServiceFactory.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.extend.foctory;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ExtendServiceNotSupportException;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\n\n/**\n * 获取扩展服务接口的实现类\n *\n * 配置文件中配置的是扩展服务的前缀，查找时就按着前缀匹配去找实现类，如果没有找到就找default开头的；如果都没有就报错\n *\n * @author d06679\n * @date 2019/4/29\n */\n@Component\n@NoArgsConstructor\npublic class ExtendServiceFactory {\n\n    private static final String DEFAULT = \"default\";\n\n    @Value(\"${extend.service}\")\n    private String              extendService;\n\n    public <T> Result<T> getExtend(Class<T> tClass) throws ExtendServiceNotSupportException {\n        Map<String, T> beans = SpringTool.getBeansOfType(tClass);\n\n        if (beans.isEmpty()) {\n            throw new ExtendServiceNotSupportException(\"扩展接口无任何实现: \" + tClass.getSimpleName());\n        }\n\n        Set<String> extendServiceSet = Sets.newHashSet(extendService.split(\",\"));\n\n        for (Map.Entry<String, T> bean : beans.entrySet()) {\n            for (String namePre : extendServiceSet) {\n                if (StringUtils.isNotBlank(namePre) && StringUtils.startsWith(bean.getKey(), namePre)) {\n                    return Result.buildSucc(bean.getValue());\n                }\n            }\n        }\n\n        return Result.buildNotExist(\"扩展服务不存在\");\n    }\n\n    public <T> T getDefault(Class<T> tClass) throws ExtendServiceNotSupportException {\n        Map<String, T> beans = SpringTool.getBeansOfType(tClass);\n\n        if (beans.isEmpty()) {\n            throw new ExtendServiceNotSupportException(\"扩展服务不存在: \" + tClass.getSimpleName());\n        }\n\n        T first = null;\n        for (Map.Entry<String, T> entry : beans.entrySet()) {\n            if (first == null) {\n                first = entry.getValue();\n            }\n            if (StringUtils.startsWith(entry.getKey(), DEFAULT)) {\n                return entry.getValue();\n            }\n        }\n\n        return first;\n    }\n\n    public <T> List<T> getAll(Class<T> tClass) throws ExtendServiceNotSupportException {\n        Map<String, T> beans = SpringTool.getBeansOfType(tClass);\n\n        if (beans.isEmpty()) {\n            throw new ExtendServiceNotSupportException(\"扩展服务不存在: \" + tClass.getSimpleName());\n        }\n\n        Set<String> extendServiceSet = Sets.newHashSet(extendService.split(\",\"));\n        extendServiceSet.add(DEFAULT);\n\n        List<T> result = Lists.newArrayList();\n        for (Map.Entry<String, T> entry : beans.entrySet()) {\n            for (String namePre : extendServiceSet) {\n                if (StringUtils.isNotBlank(namePre) && StringUtils.startsWith(entry.getKey(), namePre)) {\n                    result.add(entry.getValue());\n                }\n            }\n        }\n\n        return result;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/gateway/GatewayJoinLogManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.gateway;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.GatewayJoinQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayJoinVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\n\nimport java.util.List;\n\npublic interface GatewayJoinLogManager {\n    /**\n     * 获取projectId的错误gateway请求日志\n     * @param projectId 应用账号\n     * @param startDate 开始时刻\n     * @param endDate 结束时刻\n     * @return list\n     */\n    Result<List<GatewayJoinVO>> getGatewayErrorList(Long projectId, Long startDate, Long endDate);\n\n    /**\n     * 获取projectId的慢查gateway请求日志\n     * @param projectId 应用账号\n     * @param startDate 开始时刻\n     * @param endDate 结束时刻\n     * @return list\n     */\n    Result<List<GatewayJoinVO>> getGatewaySlowList(Long projectId, Long startDate, Long endDate);\n\n    /**\n     * 根据projectId获取指定数据中心一段时间查询量\n     *\n     * @param dataCenter\n     * @param projectId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    Result<Long> getSearchCountByProjectId(String dataCenter, Long projectId, Long startDate, Long endDate);\n\n    /**\n     * 获取指定索引的DSL\n     *\n     * @param projectId 项目编号\n     * @param indexName 索引的名称\n     * @return Result<String>\n     */\n    Result<String> getDSLByProjectIdAndIndexName(Integer projectId, String indexName);\n\n    /**\n     * 分页查询\n     * @param projectId\n     * @param queryDTO\n     * @return\n     */\n    PaginationResult<GatewayJoinVO> getGatewayJoinPage(Integer projectId, GatewayJoinQueryDTO queryDTO) throws NotFindSubclassException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/gateway/GatewayManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.gateway;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.GatewayHeartbeat;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.IndexTemplateAliasDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateRequest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.gateway.GatewayClusterNodeVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.GatewayESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplateDeployInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplatePhysicalVO;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author didi\n */\npublic interface GatewayManager {\n\n    /**\n     * gateway心跳接口\n     * @param heartbeat 心跳对象\n     * @return Result<Void>\n     */\n    Result<Void> heartbeat(GatewayHeartbeat heartbeat);\n\n    /**\n     * gateway存活接口\n     * @param clusterName 集群名\n     * @return Result<Integer>\n     */\n    Result<Integer> heartbeat(String clusterName);\n\n    /**\n     * 获取gateway存活节点列表接口\n     * @param clusterName 集群名\n     * @return Result<List<GatewayNodeVO>>\n     */\n    Result<List<GatewayClusterNodeVO>> getGatewayAliveNode(String clusterName);\n\n    /**\n     * 获取gateway存活节点列表接口\n     * @param clusterName 集群名\n     * @return Result<List<String>>\n     */\n    Result<List<String>> getGatewayAliveNodeNames(String clusterName);\n\n    /**\n     * 获取app列表,包含APP全部元信息\n     *\n     * @return Result<List < GatewayESUserVO>>\n     */\n    Result<List<GatewayESUserVO>> listESUserByProject();\n\n    /**\n     * 以map结构组织,key是表达式\n     * @param cluster 集群\n     * @return Result<Map<String, GatewayTemplatePhysicalVO>>\n     */\n    Result<Map<String, GatewayTemplatePhysicalVO>> getTemplateMap(String cluster);\n\n    /**\n     * 获取模板信息，包含主主从结构组织\n     *\n     * @return Result<Map < String, GatewayTemplateDeployInfoVO>>\n     */\n    Result<Map<String, GatewayTemplateDeployInfoVO>> listDeployInfo();\n\n    /**\n     * 滚动获取查询模板数据\n     * @param request 请求\n     * @return Result<ScrollDslTemplateResponse>\n     */\n    Result<ScrollDslTemplateResponse> scrollSearchDslTemplate(ScrollDslTemplateRequest request);\n\n    /**\n     * addAlias\n     * @param indexTemplateAliasDTO 模板dto\n     * @return Result<Boolean>\n     */\n    Result<Boolean> addAlias(IndexTemplateAliasDTO indexTemplateAliasDTO);\n\n    /**\n     * delAlias\n     * @param indexTemplateAliasDTO 模板dto\n     * @return Result<Boolean>\n     */\n    Result<Boolean> delAlias(IndexTemplateAliasDTO indexTemplateAliasDTO);\n\n    /**\n     * sql语句翻译\n     *\n     * @param sql            sql查询语句\n     * @param phyClusterName\n     * @param projectId      项目id\n     * @return 翻译结果\n     */\n    Result<String> sqlExplain(String sql, String phyClusterName, Integer projectId);\n\n    /**\n     * sql语句直接查询\n     * @param sql sql查询语句\n     * @param phyClusterName 指定查询物理集群名\n     * @param projectId 项目id\n     * @return 数据查询结果\n     */\n    Result<String> directSqlSearch(String sql, String phyClusterName, Integer projectId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/gateway/impl/GatewayJoinLogManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.gateway.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.dsl.impl.DslTemplateManagerImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.gateway.GatewayJoinLogManager;\nimport com.didichuxing.datachannel.arius.admin.biz.page.DslTemplatePageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.biz.page.GatewayJoinPageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.GatewayJoinQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.GatewayJoin;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayJoinVO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectConfigService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.GatewayJoinLogService;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.CollectionUtils;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum.DSL_TEMPLATE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum.GATEWAY_JOIN;\n\n@Component\npublic class GatewayJoinLogManagerImpl implements GatewayJoinLogManager {\n\n    private static final ILog LOGGER = LogFactory.getLog(GatewayJoinLogManagerImpl.class);\n    @Autowired\n    private GatewayJoinLogService gatewayJoinLogService;\n    @Autowired\n    private ProjectConfigService projectConfigService;\n    @Autowired\n    private HandleFactory handleFactory;\n    @Override\n    public Result<List<GatewayJoinVO>> getGatewayErrorList(Long projectId, Long startDate, Long endDate) {\n        return Result.buildSucc(ConvertUtil.list2List(\n            gatewayJoinLogService.getGatewayErrorList(projectId, startDate, endDate).getData(), GatewayJoinVO.class));\n    }\n\n    @Override\n    public Result<List<GatewayJoinVO>> getGatewaySlowList(Long projectId, Long startDate, Long endDate) {\n        return Result.buildSucc(ConvertUtil.list2List(\n            gatewayJoinLogService.getGatewaySlowList(projectId, startDate, endDate).getData(), GatewayJoinVO.class));\n    }\n\n    @Override\n    public Result<Long> getSearchCountByProjectId(String dataCenter, Long projectId, Long startDate, Long endDate) {\n        return gatewayJoinLogService.getSearchCountByProjectId(projectId, startDate, endDate);\n    }\n\n    @Override\n    public Result<String> getDSLByProjectIdAndIndexName(Integer projectId, String indexName) {\n    \n        return Result.buildSucc(gatewayJoinLogService.getOneDSLByProjectIdAndIndexName(projectId, indexName));\n    }\n\n    @Override\n    public PaginationResult<GatewayJoinVO> getGatewayJoinPage(Integer projectId, GatewayJoinQueryDTO queryDTO) throws NotFindSubclassException {\n        BaseHandle baseHandle = handleFactory.getByHandlerNamePer(GATEWAY_JOIN.getPageSearchType());\n        if (baseHandle instanceof GatewayJoinPageSearchHandle) {\n            GatewayJoinPageSearchHandle handle = (GatewayJoinPageSearchHandle) baseHandle;\n            return handle.doPage(queryDTO, projectId);\n        }\n\n        LOGGER.warn(\n                \"class=GatewayJoinLogManagerImpl||method=getGatewayJoinPage||msg=failed to get the GatewayJoinPageSearchHandle\");\n\n        return PaginationResult.buildFail(\"分页获取查询诊断信息失败\");\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/gateway/impl/GatewayManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.gateway.impl;\n\nimport java.util.*;\nimport java.util.Map.Entry;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.gateway.GatewayManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.TemplateSrvManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.aliases.TemplateLogicAliasManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Alias;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.GatewayHeartbeat;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.IndexTemplatePhysicalConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.IndexTemplateAliasDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateRequest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.gateway.GatewayClusterNode;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateAlias;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.gateway.GatewayClusterNodeVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.GatewayESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplateDeployInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplatePhysicalDeployVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplatePhysicalVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.GatewaySqlConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.TemplateUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.gateway.GatewayService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ESUserService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectConfigService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.TemplateLogicAliasService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.DslStatisticsService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Multimap;\n\n/**\n * @author didi\n */\n@Component\npublic class GatewayManagerImpl implements GatewayManager {\n\n    private static final ILog               LOGGER                 = LogFactory.getLog(GatewayManagerImpl.class);\n\n    private static final int                TIMEOUT                = 10 * 60 * 1000;\n\n    @Autowired\n    private ESUserService                   esUserService;\n    @Autowired\n    private ProjectService                  projectService;\n\n    @Autowired\n    private ProjectLogicTemplateAuthService projectLogicTemplateAuthService;\n\n    @Autowired\n    private IndexTemplateService            indexTemplateService;\n\n    @Autowired\n    private IndexTemplatePhyService         indexTemplatePhyService;\n\n    @Autowired\n    private TemplateLogicAliasManager       templateLogicAliasManager;\n\n    @Autowired\n    private GatewayService                  gatewayService;\n\n    @Autowired\n    private ClusterPhyService clusterPhyService;\n    @Autowired\n    private AriusConfigInfoService          ariusConfigInfoService;\n\n    @Autowired\n    private DslStatisticsService            dslStatisticsService;\n\n    @Autowired\n    private TemplateSrvManager              templateSrvManager;\n\n    @Autowired\n    private TemplateLogicAliasService       templateLogicAliasService;\n    @Autowired\n    private ProjectConfigService            projectConfigService;\n\n    private final Cache<String, Object>     projectESUserListCache = CacheBuilder.newBuilder()\n        .expireAfterWrite(1, TimeUnit.MINUTES).maximumSize(100).build();\n\n    @Override\n    public Result<Void> heartbeat(GatewayHeartbeat heartbeat) {\n        return gatewayService.heartbeat(heartbeat);\n    }\n\n    @Override\n    public Result<Integer> heartbeat(String clusterName) {\n        return gatewayService.aliveCount(clusterName, TIMEOUT);\n    }\n\n    @Override\n    public Result<List<GatewayClusterNodeVO>> getGatewayAliveNode(String clusterName) {\n        return Result.buildSucc(\n            ConvertUtil.list2List(gatewayService.getAliveNode(clusterName, TIMEOUT), GatewayClusterNodeVO.class));\n    }\n\n    @Override\n    public Result<List<String>> getGatewayAliveNodeNames(String clusterName) {\n        List<GatewayClusterNode> aliveNodes = gatewayService.getAliveNode(clusterName, TIMEOUT);\n        List<String> list = Lists.newArrayList();\n        if (aliveNodes != null && !aliveNodes.isEmpty()) {\n            list = aliveNodes.stream().map(GatewayClusterNode::getHostName).collect(Collectors.toList());\n        }\n        return Result.buildSucc(list);\n    }\n\n    private List<ESUser> listESUsers() {\n        final List<Integer> projectIds = projectService.getProjectBriefList().stream().map(ProjectBriefVO::getId)\n            .collect(Collectors.toList());\n        return esUserService.listESUsers(projectIds);\n    }\n\n    private Map<Integer, String> listProject() {\n        return projectService.getProjectBriefList().stream()\n            .collect(Collectors.toMap(ProjectBriefVO::getId, ProjectBriefVO::getProjectName));\n    }\n\n    private Map<Integer, String> listProjectWithCache() {\n        try {\n            return (Map<Integer, String>) projectESUserListCache.get(\"listProject\", this::listProject);\n        } catch (ExecutionException e) {\n            return listProject();\n        }\n    }\n\n    private List<ESUser> listESUserWithCache() {\n        try {\n            return (List<ESUser>) projectESUserListCache.get(\"listESUsers\", this::listESUsers);\n        } catch (ExecutionException e) {\n            return listESUsers();\n        }\n    }\n\n    private Map<Integer/*projectId*/, ProjectConfig> listProjectConfig() {\n\n        return projectConfigService.projectId2ProjectConfigMap();\n    }\n\n    private Map<Integer/*projectId*/, ProjectConfig> listProjectConfigWithCache() {\n        try {\n            return (Map<Integer/*projectId*/, ProjectConfig>) projectESUserListCache.get(\"listProjectConfig\",\n                this::listProjectConfig);\n        } catch (ExecutionException e) {\n            return listProjectConfig();\n        }\n    }\n\n    @Override\n    public Result<List<GatewayESUserVO>> listESUserByProject() {\n        // 查询出所有的应用\n        List<ESUser> esUsers = listESUserWithCache();\n        final Map<Integer/*projectId*/, /*es user*/List<Integer>> projectIdEsUsersMap = esUsers.stream().collect(\n            Collectors.groupingBy(ESUser::getProjectId, Collectors.mapping(ESUser::getId, Collectors.toList())));\n        final Map<Integer/*projectId*/, String/*projectName*/> projectId2ProjectNameMap = listProjectWithCache();\n        Map<Integer/*projectId*/, ProjectConfig> projectId2ProjectConfigMap = listProjectConfigWithCache();\n\n        // 查询出所有的权限\n        Map<Integer/*projectId*/, Collection<ProjectTemplateAuth>> projectId2ProjectTemplateAuthsMap = projectLogicTemplateAuthService\n            .getAllProjectTemplateAuths();\n        Map<Integer/*es user*/, Collection<ProjectTemplateAuth>> esUser2ProjectTemplateAuthsMap = Maps.newHashMap();\n        Map<Integer/*es user*/, String/*projectName*/> esUser2ProjectNameMap = Maps.newHashMap();\n        Map<Integer/*es user*/, ProjectConfig> esUser2ESUserConfigMap = Maps.newHashMap();\n        //转换\n        for (Entry<Integer, List<Integer>> projectIdESUsersEntry : projectIdEsUsersMap.entrySet()) {\n            final Integer projectId = projectIdESUsersEntry.getKey();\n            for (Integer esuser : projectIdESUsersEntry.getValue()) {\n                Optional.ofNullable(projectId2ProjectTemplateAuthsMap.get(projectId)).ifPresent(\n                    projectTemplateAuths -> esUser2ProjectTemplateAuthsMap.put(esuser, projectTemplateAuths));\n                Optional.ofNullable(projectId2ProjectNameMap.get(projectId))\n                    .ifPresent(projectName -> esUser2ProjectNameMap.put(esuser, projectName));\n                Optional.ofNullable(projectId2ProjectConfigMap.get(projectId))\n                    .ifPresent(projectConfig -> esUser2ESUserConfigMap.put(esuser, projectConfig));\n            }\n        }\n\n        Map<Integer/*id*/, IndexTemplate> templateId2IndexTemplateLogicMap = indexTemplateService\n            .getAllLogicTemplatesMap();\n\n        Map<Integer/*logicId*/, List<String>> aliasMap = templateLogicAliasService.listAliasMapWithCache();\n\n        List<GatewayESUserVO> appVOList = esUsers.parallelStream().map(user -> {\n            try {\n                final GatewayESUserVO gatewayESUserVO = buildESUserVO(user, esUser2ProjectTemplateAuthsMap,\n                    esUser2ESUserConfigMap, templateId2IndexTemplateLogicMap, \"\", aliasMap);\n                final Integer esUser = gatewayESUserVO.getId();\n                if (esUser2ProjectNameMap.containsKey(esUser)) {\n                    gatewayESUserVO.setName(esUser2ProjectNameMap.get(esUser));\n                }\n                return gatewayESUserVO;\n            } catch (Exception e) {\n                LOGGER.warn(\"class=GatewayManagerImpl||method=listApp||errMsg={}||stackTrace={}\", e.getMessage(),\n                    JSON.toJSONString(e.getStackTrace()), e);\n            }\n            return null;\n        }).filter(Objects::nonNull).collect(Collectors.toList());\n        return Result.buildSucc(appVOList);\n    }\n\n    @Override\n    public Result<Map<String, GatewayTemplatePhysicalVO>> getTemplateMap(String cluster) {\n        List<IndexTemplatePhy> indexTemplatePhysicalInfos = indexTemplatePhyService.getNormalTemplateByCluster(cluster);\n\n        if (CollectionUtils.isEmpty(indexTemplatePhysicalInfos)) {\n            return Result.buildSucc(Maps.newHashMap());\n        }\n\n        Map<Integer, IndexTemplate> templateId2IndexTemplateLogicMap = indexTemplateService.getAllLogicTemplatesMap();\n\n        List<IndexTemplateAlias> aliases = templateLogicAliasManager.listAlias();\n        Multimap<Integer, IndexTemplateAlias> logicId2IndexTemplateAliasMultiMap = ConvertUtil.list2MulMap(aliases,\n            IndexTemplateAlias::getLogicId);\n\n        Map<String, GatewayTemplatePhysicalVO> result = Maps.newHashMap();\n        for (IndexTemplatePhy templatePhysical : indexTemplatePhysicalInfos) {\n            try {\n                GatewayTemplatePhysicalVO templatePhysicalVO = ConvertUtil.obj2Obj(templatePhysical,\n                    GatewayTemplatePhysicalVO.class);\n\n                templatePhysicalVO\n                    .setDataCenter(templateId2IndexTemplateLogicMap.get(templatePhysical.getLogicId()).getDataCenter());\n\n                Collection<IndexTemplateAlias> indexTemplateAliases = logicId2IndexTemplateAliasMultiMap\n                    .get(templatePhysical.getLogicId());\n                if (CollectionUtils.isEmpty(indexTemplateAliases)) {\n                    templatePhysicalVO.setAliases(Lists.newArrayList());\n                } else {\n                    templatePhysicalVO\n                        .setAliases(ConvertUtil.list2List(Lists.newArrayList(indexTemplateAliases), Alias.class));\n                }\n\n                result.put(templatePhysicalVO.getExpression(), templatePhysicalVO);\n            } catch (Exception e) {\n                LOGGER.warn(\"class=GatewayManagerImpl||method=getTemplateMap||cluster={}||errMsg={}\", cluster,\n                    e.getMessage(), e);\n            }\n        }\n\n        return Result.buildSucc(result);\n    }\n\n    @Override\n    public Result<Map<String, GatewayTemplateDeployInfoVO>> listDeployInfo() {\n        List<IndexTemplateWithPhyTemplates> logicWithPhysicals = indexTemplateService\n            .listTemplateWithPhysical();\n\n        List<IndexTemplateAlias> logicWithAliases = templateLogicAliasManager.listAlias(logicWithPhysicals);\n        Multimap<Integer, IndexTemplateAlias> logicId2IndexTemplateAliasMultiMap = ConvertUtil\n            .list2MulMap(logicWithAliases, IndexTemplateAlias::getLogicId);\n\n        Map<String, GatewayTemplateDeployInfoVO> result = Maps.newHashMap();\n        for (IndexTemplateWithPhyTemplates logicWithPhysical : logicWithPhysicals) {\n            if (logicWithPhysical.hasPhysicals()) {\n                try {\n                    GatewayTemplateDeployInfoVO gatewayTemplateDeployInfoVO = buildGatewayTemplateDeployInfoVO(\n                        logicWithPhysical, logicId2IndexTemplateAliasMultiMap);\n\n                    if (null != gatewayTemplateDeployInfoVO) {\n                        result.put(logicWithPhysical.getName(), gatewayTemplateDeployInfoVO);\n                    }\n                } catch (Exception e) {\n                    LOGGER.warn(\n                        \"class=GatewayManagerImpl||method=listDeployInfo||||templateName={}||errMsg={}\",\n                         logicWithPhysical.getName(), e.getMessage(), e);\n                }\n            }\n        }\n\n        return Result.buildSucc(result);\n    }\n\n    @Override\n    public Result<ScrollDslTemplateResponse> scrollSearchDslTemplate(ScrollDslTemplateRequest request) {\n        return dslStatisticsService.scrollSearchDslTemplate(request);\n    }\n\n    @Override\n    public Result<Boolean> addAlias(IndexTemplateAliasDTO indexTemplateAliasDTO) {\n        return templateLogicAliasService.addAlias(indexTemplateAliasDTO);\n    }\n\n    @Override\n    public Result<Boolean> delAlias(IndexTemplateAliasDTO indexTemplateAliasDTO) {\n        return templateLogicAliasService.delAlias(indexTemplateAliasDTO);\n    }\n\n    @Override\n    public Result<String> sqlExplain(String sql, String phyClusterName, Integer projectId) {\n        if (projectId == null || !esUserService.checkDefaultESUserByProject(projectId)) {\n            return Result.buildParamIllegal(\"对应的projectId字段非法\");\n        }\n        if (!clusterPhyService.isClusterExists(phyClusterName)) {\n            return Result.buildNotExist(\"集群不存在\");\n        }\n        final ESUser esUser = esUserService.getDefaultESUserByProject(projectId);\n\n        return gatewayService.sqlOperate(sql, phyClusterName, esUser, GatewaySqlConstant.SQL_EXPLAIN);\n    }\n\n    @Override\n    public Result<String> directSqlSearch(String sql, String phyClusterName, Integer projectId) {\n        if (projectId == null || !esUserService.checkDefaultESUserByProject(projectId)) {\n            return Result.buildParamIllegal(\"对应的projectId字段非法\");\n        }\n        if (!clusterPhyService.isClusterExists(phyClusterName)) {\n            return Result.buildNotExist(\"集群不存在\");\n        }\n        final ESUser esUser = esUserService.getDefaultESUserByProject(projectId);\n        return gatewayService.sqlOperate(sql, phyClusterName, esUser, GatewaySqlConstant.SQL_SEARCH);\n    }\n\n    /**************************************** private method *************************************************/\n    private GatewayTemplatePhysicalDeployVO buildPhysicalDeployVO(IndexTemplatePhy physical) {\n        if (physical == null) {\n            return null;\n        }\n\n        GatewayTemplatePhysicalDeployVO deployVO = new GatewayTemplatePhysicalDeployVO();\n        deployVO.setTemplateName(physical.getName());\n        deployVO.setCluster(physical.getCluster());\n        deployVO.setRack(physical.getRack());\n        deployVO.setShardNum(physical.getShard());\n        deployVO.setGroupId(physical.getGroupId());\n        deployVO.setDefaultWriterFlags(physical.fetchDefaultWriterFlags());\n\n        if (StringUtils.isNotBlank(physical.getConfig())) {\n            IndexTemplatePhysicalConfig config = JSON.parseObject(physical.getConfig(),\n                IndexTemplatePhysicalConfig.class);\n            deployVO.setTopic(config.getKafkaTopic());\n            deployVO.setAccessProjects(config.getAccessProjects());\n            deployVO.setMappingIndexNameEnable(config.getMappingIndexNameEnable());\n            deployVO.setTypeIndexMapping(config.getTypeIndexMapping());\n        }\n\n        return deployVO;\n    }\n\n    private GatewayESUserVO buildESUserVO(ESUser esUser,\n                                          Map<Integer/*es user*/, Collection<ProjectTemplateAuth>> esUser2ProjectTemplateAuthsMap,\n                                          Map<Integer, ProjectConfig> esUser2ESUserConfigMap,\n                                          Map<Integer, IndexTemplate> templateId2IndexTemplateLogicMap,\n                                          String defaultReadPermissionIndexes, Map<Integer, List<String>> aliasMap) {\n\n        GatewayESUserVO gatewayESUserVO = ConvertUtil.obj2Obj(esUser, GatewayESUserVO.class);\n\n        if (StringUtils.isBlank(gatewayESUserVO.getDataCenter())) {\n            gatewayESUserVO.setDataCenter(\"cn\");\n        }\n\n        if (StringUtils.isNotBlank(esUser.getIp())) {\n            gatewayESUserVO.setIp(Lists.newArrayList(esUser.getIp().split(\",\")));\n        } else {\n            gatewayESUserVO.setIp(Lists.newArrayList());\n        }\n\n        gatewayESUserVO.setIsRoot(esUser.getIsRoot());\n        if (AdminConstant.YES.equals(esUser.getIsRoot())) {\n            gatewayESUserVO.setIndexExp(Lists.newArrayList(\"*\"));\n            gatewayESUserVO.setWIndexExp(Lists.newArrayList(\"*\"));\n        } else {\n            List<String> readPermissionIndexExpressions = new ArrayList<>();\n            List<String> writePermissionIndexExpressions = new ArrayList<>();\n\n            if (StringUtils.isNotBlank(esUser.getIndexExp())) {\n                readPermissionIndexExpressions.addAll(Lists.newArrayList(esUser.getIndexExp().split(\",\")));\n            }\n            readPermissionIndexExpressions.addAll(Arrays.asList(defaultReadPermissionIndexes.split(\",\")));\n            //判断key 是否属于该项目下的es user\n            if (esUser2ProjectTemplateAuthsMap.containsKey(esUser.getId())) {\n                //获取该项目下的es user\n                Collection<ProjectTemplateAuth> templateAuthCollection = esUser2ProjectTemplateAuthsMap\n                    .get(esUser.getId());\n                if (!templateAuthCollection.isEmpty()) {\n\n                    fetchPermissionIndexExpressions(esUser.getId(), templateAuthCollection,\n                        templateId2IndexTemplateLogicMap, aliasMap, readPermissionIndexExpressions,\n                        writePermissionIndexExpressions);\n                } else {\n                    LOGGER.warn(\"class=GatewayManagerImpl||method=buildAppVO||esUser={}||msg=esUser has no permission.\",\n                        esUser.getId());\n                }\n            }\n\n            gatewayESUserVO.setIndexExp(readPermissionIndexExpressions);\n            gatewayESUserVO.setWIndexExp(writePermissionIndexExpressions);\n        }\n\n        ProjectConfig config = esUser2ESUserConfigMap.get(esUser.getId());\n        if (config != null) {\n            gatewayESUserVO.setDslAnalyzeEnable(config.getDslAnalyzeEnable());\n            gatewayESUserVO.setAggrAnalyzeEnable(config.getAggrAnalyzeEnable());\n            gatewayESUserVO.setAnalyzeResponseEnable(config.getAnalyzeResponseEnable());\n        } else {\n            LOGGER.warn(\"class=GatewayManagerImpl||method=buildAppVO||esUser={}||msg=esUser config is not exists.\",\n                esUser.getId());\n        }\n\n        return gatewayESUserVO;\n    }\n\n    /**\n     * 获取当前项目所有读写权限索引列表\n     * @param esUserId es user\n     * @param projectTemplateAuthCollection project模板权限集合\n     * @param templateId2IndexTemplateLogicMap  模板Id跟模板详情映射\n     * @param indexExpressions  当前esUser读权限列表\n     * @param writeExpressions  当前esUser写权限列表\n     */\n    private void fetchPermissionIndexExpressions(Integer esUserId,\n                                                 Collection<ProjectTemplateAuth> projectTemplateAuthCollection,\n                                                 Map<Integer, IndexTemplate> templateId2IndexTemplateLogicMap,\n                                                 Map<Integer, List<String>> aliasMap, List<String> indexExpressions,\n                                                 List<String> writeExpressions) {\n        if (CollectionUtils.isNotEmpty(projectTemplateAuthCollection)) {\n            projectTemplateAuthCollection.stream().forEach(auth -> {\n                List<String> alias = aliasMap.getOrDefault(auth.getTemplateId(), new ArrayList<>(0));\n                String expression;\n                try {\n                    expression = templateId2IndexTemplateLogicMap.get(auth.getTemplateId()).getExpression();\n                } catch (Exception e) {\n                    LOGGER.warn(\n                        \"class=GatewayManagerImpl||method=fetchPermissionIndexExpressions||projectId={}||templateId={}||msg=template not exists.\",\n                        esUserId, auth.getTemplateId());\n                    return;\n                }\n                indexExpressions.add(expression);\n                indexExpressions.addAll(alias);\n                if (ProjectTemplateAuthEnum.OWN.getCode().equals(auth.getType())\n                    || ProjectTemplateAuthEnum.RW.getCode().equals(auth.getType())) {\n                    writeExpressions.add(expression);\n                    writeExpressions.addAll(alias);\n                }\n            });\n        }\n    }\n\n    private GatewayTemplateDeployInfoVO buildGatewayTemplateDeployInfoVO(IndexTemplateWithPhyTemplates logicWithPhysical,\n                                                                         Multimap<Integer, IndexTemplateAlias> logicId2IndexTemplateAliasMultiMap) {\n        if (null == logicWithPhysical || null == logicWithPhysical.getMasterPhyTemplate()) {\n            return null;\n        }\n\n        GatewayTemplateVO baseInfo = ConvertUtil.obj2Obj(logicWithPhysical, GatewayTemplateVO.class);\n        baseInfo.setDeployStatus(TemplateUtils.genDeployStatus(logicWithPhysical));\n        baseInfo.setAliases(logicId2IndexTemplateAliasMultiMap.get(logicWithPhysical.getId()).stream()\n            .map(IndexTemplateAlias::getName).collect(Collectors.toList()));\n        baseInfo.setVersion(logicWithPhysical.getMasterPhyTemplate().getVersion());\n        \n        GatewayTemplatePhysicalDeployVO masterInfo = genMasterInfo(logicWithPhysical);\n        List<GatewayTemplatePhysicalDeployVO> slaveInfos = genSlaveInfos(logicWithPhysical);\n\n        GatewayTemplateDeployInfoVO deployInfoVO = new GatewayTemplateDeployInfoVO();\n        deployInfoVO.setBaseInfo(baseInfo);\n        deployInfoVO.setMasterInfo(masterInfo);\n        deployInfoVO.setSlaveInfos(slaveInfos);\n        \n        if (!TemplateServiceEnum.strContainsSrv(logicWithPhysical.getOpenSrv(), TemplateServiceEnum.TEMPLATE_PIPELINE)) {\n            deployInfoVO.getBaseInfo().setIngestPipeline(\"\");\n        }\n\n        return deployInfoVO;\n    }\n\n    private GatewayTemplatePhysicalDeployVO genMasterInfo(IndexTemplateWithPhyTemplates logicWithPhysical) {\n        return buildPhysicalDeployVO(logicWithPhysical.getMasterPhyTemplate());\n    }\n\n    private List<GatewayTemplatePhysicalDeployVO> genSlaveInfos(IndexTemplateWithPhyTemplates logicWithPhysical) {\n        List<GatewayTemplatePhysicalDeployVO> slavesInfos = Lists.newArrayList();\n        for (IndexTemplatePhy physical : logicWithPhysical.getPhysicals()) {\n            if (physical.getRole().equals(TemplateDeployRoleEnum.MASTER.getCode())) {\n                continue;\n            }\n            slavesInfos.add(buildPhysicalDeployVO(physical));\n        }\n        return slavesInfos;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/indices/IndicesManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.indices;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndicesBlockSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.manage.IndexCatCellWithConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.srv.IndexForceMergeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.srv.IndexRolloverDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexCatCellVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexCatCellWithTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexMappingVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexSettingVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexShardInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport java.util.List;\nimport java.util.function.BiFunction;\n\n/**\n * @author lyn\n * @date 2021/09/28\n **/\npublic interface IndicesManager {\n    /**\n     * 条件获取索引列表信息 ,携带可读可写标志位\n     * @param condition     查询条件\n     * @param projectId         项目\n     * @return              List<IndexCatInfoVO>\n     */\n    PaginationResult<IndexCatCellVO> pageGetIndex(IndexQueryDTO condition,\n                                                  Integer projectId) throws NotFindSubclassException;\n\n    /**\n     * 创建索引\n     *\n     * @param indexCreateDTO\n     * @param projectId\n     * @param operator\n     */\n    Result<Void> createIndex(IndexCatCellWithConfigDTO indexCreateDTO, Integer projectId, String operator)\n            throws AdminOperateException;\n\n    /**\n     * 删除索引\n     * @param params     删除索引信息\n     * @param projectId      项目\n     * @param operator   操作人\n     * @return           Boolean\n     */\n    Result<Boolean> deleteIndex(List<IndexCatCellDTO> params, Integer projectId, String operator);\n\n    /**\n     * 批量更新索引状态\n     *\n     * @param params   索引信息\n     * @param projectId    项目id\n     * @param function 操作函数\n     * @return {@link Result}<{@link Boolean}>\n     */\n    <T, U, R> Result<Boolean> batchOperateIndex(List<IndexCatCellDTO> params, Integer projectId,\n                                                BiFunction<String, List<String>, Result<Void>> function);\n\n    /**\n     * 开启索引\n     *\n     * @param params   索引信息\n     * @param projectId    项目id\n     * @param operator 操作人\n     * @return {@link Result}<{@link Boolean}>\n     */\n    Result<Boolean> openIndex(List<IndexCatCellDTO> params, Integer projectId, String operator);\n\n    /**\n     * 关闭索引\n     *\n     * @param params   索引信息\n     * @param projectId    项目id\n     * @param operator 操作人\n     * @return {@link Result}<{@link Boolean}>\n     */\n    Result<Boolean> closeIndex(List<IndexCatCellDTO> params, Integer projectId, String operator);\n\n    /**\n     * 配合删除真实集群索引使用\n     * <p>\n     * 1. 批量设置存储索引cat/index信息的元数据索引中的文档标志位（deleteFlag）为true 2. 采集任务不采集已删除索引\n     *\n     * @param cluster       物理集群\n     * @param indexNameList 索引名称列表\n     * @return\n     */\n    Result<Void> updateIndexFlagInvalid(String cluster, List<String> indexNameList);\n\n    /**\n     * 编辑索引setting阻塞信息\n     *\n     * @param params    索引信息列表\n     * @param projectId 项目\n     * @param operator  操作人\n     * @return Boolean\n     */\n    Result<Void> editIndexBlockSetting(List<IndicesBlockSettingDTO> params, Integer projectId, String operator);\n\n    /**\n     * 获取索引mapping\n     *\n     * @param cluster   集群\n     * @param indexName 索引名称\n     * @param projectId              项目\n     * @return IndexMappingVO\n     */\n    Result<IndexMappingVO> getMapping(String cluster, String indexName, Integer projectId);\n\n    /**\n     * 更新索引mapping\n     *\n     * @param param\n     * @param projectId\n     * @param operate\n     * @return\n     */\n    Result<Void> editMapping(IndexCatCellWithConfigDTO param, Integer projectId, String operate)\n            throws AdminOperateException;\n\n    /**\n     * 获取索引setting信息\n     *\n     * @param projectId     项目\n     * @param cluster   集群\n     * @param indexName 索引名称\n     * @return IndexSettingVO\n     */\n    Result<IndexSettingVO> getSetting(String cluster, String indexName, Integer projectId);\n\n    /**\n     * 更新索引setting\n     *\n     * @param param\n     * @param projectId\n     * @param operator\n     * @return\n     */\n    Result<Void> editSetting(IndexCatCellWithConfigDTO param, Integer projectId,\n                             String operator) throws ESOperateException;\n\n    /**\n     * 获取索引shard分配信息\n     * @param cluster 集群\n     * @param indexName         索引名称\n     * @param projectId             项目\n     * @return\n     */\n    Result<List<IndexShardInfoVO>> getIndexShardsInfo(String cluster, String indexName, Integer projectId);\n\n    /**\n     * 获取单个索引的详情信息\n     * @param cluster 集群名称\n     * @param indexName 索引名称\n     * @param projectId 项目\n     * @return\n     */\n    Result<IndexCatCellVO> getIndexCatInfo(String cluster, String indexName, Integer projectId);\n\n    /**\n     * 新增别名\n     *\n     * @param param\n     * @param projectId 项目\n     * @param operator\n     * @return\n     */\n    Result<Void> addIndexAliases(IndexCatCellWithConfigDTO param, Integer projectId, String operator);\n\n    /**\n     * 删除别名\n     *\n     * @param param\n     * @param projectId 项目\n     * @param operator\n     * @return\n     */\n    Result<Void> deleteIndexAliases(IndexCatCellWithConfigDTO param, Integer projectId, String operator);\n\n    /**\n     * 获取索引别名\n     *\n     * @param cluster   集群\n     * @param indexName 索引名称\n     * @param projectId     项目\n     * @return {@link Result}<{@link String}>\n     */\n    Result<List<String>> getIndexAliases(String cluster, String indexName, Integer projectId);\n\n    /**\n     * rollover\n     *\n     * @param param\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Void> rollover(IndexRolloverDTO param, String operator, Integer projectId);\n\n    /**\n     * shrink\n     *\n     * @param param\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Void> shrink(IndexCatCellWithConfigDTO param, String operator, Integer projectId);\n\n    /**\n     * split\n     *\n     * @param param\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Void> split(IndexCatCellWithConfigDTO param, String operator, Integer projectId);\n\n    /**\n     * forceMerge\n     *\n     * @param param\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Void> forceMerge(IndexForceMergeDTO param, String operator, Integer projectId);\n\n    /**\n     * 获取物理集群中的索引列表\n     */\n    Result<List<String>> getClusterPhyIndexName(String clusterPhyName, Integer projectId, String index);\n\n    /**\n     * 获取逻辑集群下的索引列表\n     *\n     * @param clusterLogicName\n     * @param projectId\n     * @param index\n     * @return\n     */\n    Result<List<String>> getClusterLogicIndexName(String clusterLogicName, Integer projectId, String index);\n\n    /**\n     * 判断索引是否存在\n     *\n     * @param cluster   集群\n     * @param indexName 索引名称\n     * @param projectId     应用程序id\n     * @return {@link Result}<{@link Boolean}>\n     */\n    Result<Boolean> isExists(String cluster, String indexName, Integer projectId);\n\n    /**\n     * 查询物理模版所有匹配的索引，包含升版本与脏索引\n     *\n     * @param physicalId 物理模板id\n     * @return {@link List}<{@link String}>\n     */\n    List<IndexCatCellWithTemplateVO> listIndexCatCellWithTemplateByTemplatePhyId(Long physicalId);\n\n    /**\n     * 获取物理模版所有匹配的索引catinfo\n     *\n     * @param physicalId 物理模版id\n     * @return {@link List}<{@link CatIndexResult}>\n     */\n    List<CatIndexResult> listIndexCatInfoByTemplatePhyId(Long physicalId);\n    \n    Result<Void> deleteIndexByCLusterPhy(String clusterPhy, List<String> indexNameList, Integer projectId, String operator);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/indices/IndicesManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.indices;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.baomidou.mybatisplus.core.toolkit.CollectionUtils;\nimport com.didichuxing.datachannel.arius.admin.biz.page.IndexPageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndicesBlockSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.manage.IndexCatCellWithConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.srv.IndexForceMergeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.srv.IndexRolloverDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexCatCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.IndexShardInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.operaterecord.template.TemplateMappingOperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.operaterecord.template.TemplateSettingOperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.*;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.index.IndexBlockEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.index.RefreshCatIndexInfoEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusIndexTemplateSetting;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.IndexCatInfoCollector;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.IndexConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.MultiIndexsConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.utils.JsonUtils;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.time.LocalDateTime;\nimport java.time.ZoneOffset;\nimport java.util.*;\nimport java.util.function.BiFunction;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.PRIMARY;\n\n/**\n * @author lyn\n * @date 2021/09/28\n **/\n@Component\npublic class IndicesManagerImpl implements IndicesManager {\n    public static final String      START             = \"*\";\n    private static final ILog       LOGGER            = LogFactory.getLog(IndicesManagerImpl.class);\n    public static final int         RETRY_COUNT       = 3;\n    private static final String     PROPERTIES        = \"\\\"properties\\\"\";\n    private static final String CONDITIONS = \"conditions\";\n    private static final String MAX_AGE=\"max_age\";\n    private static final String MAX_DOCS=\"max_docs\";\n    private static final String MAX_SIZE=\"max_size\";\n    @Autowired\n    private ProjectService          projectService;\n\n    @Autowired\n    private ESIndexCatService       esIndexCatService;\n    @Autowired\n    private ESClusterService esClusterService;\n\n    @Autowired\n    private ESIndexService          esIndexService;\n\n    @Autowired\n    private ClusterPhyService       clusterPhyService;\n\n    @Autowired\n    private IndexTemplatePhyService indexTemplatePhyService;\n\n    @Autowired\n    private OperateRecordService    operateRecordService;\n\n    @Autowired\n    private IndexCatInfoCollector   indexCatInfoCollector;\n\n    @Autowired\n    private HandleFactory           handleFactory;\n\n    @Autowired\n    private ClusterLogicService     clusterLogicService;\n\n    @Autowired\n    private ClusterRegionService    clusterRegionService;\n\n    private static final FutureUtil<Result<Void>> FUTURE_UTIL_RESULT = FutureUtil.init(\"IndicesManagerImpl\", 10, 10,\n            100);\n\n    @Override\n    public PaginationResult<IndexCatCellVO> pageGetIndex(IndexQueryDTO condition,\n                                                         Integer projectId) throws NotFindSubclassException {\n        BaseHandle baseHandle = handleFactory.getByHandlerNamePer(PageSearchHandleTypeEnum.INDEX.getPageSearchType());\n        if (baseHandle instanceof IndexPageSearchHandle) {\n            IndexPageSearchHandle handle = (IndexPageSearchHandle) baseHandle;\n            return handle.doPage(condition, projectId);\n        }\n\n        LOGGER.warn(\n            \"class=TemplateLogicManagerImpl||method=pageGetConsoleClusterVOS||msg=failed to get the TemplateLogicPageSearchHandle\");\n\n        return PaginationResult.buildFail(\"获取索引分页信息失败\");\n    }\n\n    @Override\n    public Result<Void> createIndex(IndexCatCellWithConfigDTO indexCreateDTO, Integer projectId, String operator)\n            throws AdminOperateException {\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(indexCreateDTO.getCluster(), projectId);\n        if (getClusterRet.failed()) { return Result.buildFrom(getClusterRet);}\n\n        String realPhyCluster = getClusterRet.getData();\n\n        // 校验创建索引在平台的合法性\n        Result<Void> checkValidRet = checkValid(indexCreateDTO, realPhyCluster);\n        if (checkValidRet.failed()) { return checkValidRet;}\n\n        // 初始化分配集群信息\n        Result<Void> initRet = initIndexCreateDTO(indexCreateDTO, projectId);\n        if (initRet.failed()) { return initRet;}\n\n        // 处理索引 mapping\n        IndexConfig indexConfig = new IndexConfig();\n        if (StringUtils.isNotBlank(indexCreateDTO.getMapping())) {\n            Result<MappingConfig> mappingResult = AriusIndexMappingConfigUtils\n                .parseMappingConfig(indexCreateDTO.getMapping());\n            if (mappingResult.failed()) {\n                return Result.buildFrom(mappingResult);\n            }\n            indexConfig.setMappings(mappingResult.getData());\n        }\n\n        // 处理索引 setting\n        if (StringUtils.isNotBlank(indexCreateDTO.getSetting())) {\n            indexConfig.setSettings(AriusIndexTemplateSetting.flat(JSON.parseObject(indexCreateDTO.getSetting())));\n        }\n        boolean succ = false;\n        try {\n            // 1. es创建真实索引\n            boolean syncCreateIndexRet = esIndexService.syncCreateIndex(realPhyCluster, indexCreateDTO.getIndex(),\n                    indexConfig, RETRY_COUNT);\n\n            // 2. 同步在元数据Cat_index系统索引中添加此索引元数据文档\n            if (syncCreateIndexRet) {\n                //在分页查询的时候被强制要求deleteFlag=false，如果数据不存在deleteFlag会导致查询不到；\n                indexCreateDTO.setDeleteFlag(false);\n                indexCreateDTO.setTimestamp(LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli());\n                succ = esIndexCatService.syncInsertCatIndex(Lists.newArrayList(indexCreateDTO), RETRY_COUNT);\n            }\n\n            if (succ) {\n                operateRecordService.saveOperateRecordWithManualTrigger(\n                        String.format(\"物理集群:[%s], 创建索引：[%s]\", indexCreateDTO.getCluster(),\n                                indexCreateDTO.getIndex()), operator, projectId, indexCreateDTO.getIndex(), OperateTypeEnum.INDEX_MANAGEMENT_CREATE);\n            }\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=IndicesManagerImpl||method=createIndex||msg=create index failed||index={}\",\n                    indexCreateDTO.getIndex(), e);\n            return Result.buildFail(String.format(\"索引创建失败, %s\", e.getMessage()));\n        }\n        if (succ) { return Result.buildSuccWithMsg(\"索引创建成功\");}\n\n        return Result.buildFail(\"创建索引失败, 请检查集群是否异常\");\n    }\n\n    @Override\n    public Result<Boolean> deleteIndex(List<IndexCatCellDTO> params, Integer projectId, String operator) {\n        return batchOperateIndex(params, projectId, (cluster, indexNameList) -> {\n            if (indexNameList.size() == esIndexService.syncBatchDeleteIndices(cluster, indexNameList, RETRY_COUNT)) {\n                Result<Void> batchSetIndexFlagInvalidResult = updateIndexFlagInvalid(cluster, indexNameList);\n                if (batchSetIndexFlagInvalidResult.success()) {\n                    for (String indexName : indexNameList) {\n    \n                        operateRecordService.saveOperateRecordWithManualTrigger(\n                                String.format(\"删除索引：【%s】\", indexName), operator, projectId, indexName,\n                                OperateTypeEnum.INDEX_MANAGEMENT_DELETE);\n                    }\n\n                }\n            }\n            return Result.buildSucc();\n        });\n    }\n\n    /**\n     * 批处理操作指数\n     *\n     * @param params    参数个数 {@link IndexCatCellDTO#getCluster()}这里使用此参数作为集群名称；如果是超级项目，就是物理集群，反之为逻辑集群\n     * @param projectId 项目id\n     * @param function  函数\n     * @return {@code Result<Boolean>}\n     */\n    @Override\n    public <T, U, R> Result<Boolean> batchOperateIndex(List<IndexCatCellDTO> params, Integer projectId,\n                                                       BiFunction<String, List<String>, Result<Void>> function) {\n        for (IndexCatCellDTO param : params) {\n            Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(param.getCluster(), projectId);\n            if (getClusterRet.failed()) {\n                return Result.buildFrom(getClusterRet);\n            }\n            String phyCluster = getClusterRet.getData();\n            param.setCluster(phyCluster);\n            Result<Void> ret = basicCheckParam(param.getCluster(), param.getIndex(), projectId);\n            if (ret.failed()) {\n                return Result.buildFrom(ret);\n            }\n        }\n\n        Map<String, List<String>> cluster2IndexNameListMap = ConvertUtil.list2MapOfList(params,\n            IndexCatCellDTO::getCluster, IndexCatCellDTO::getIndex);\n\n        for (Map.Entry<String, List<String>> entry : cluster2IndexNameListMap.entrySet()) {\n            String cluster = entry.getKey();\n            List<String> indexNameList = entry.getValue();\n            FUTURE_UTIL_RESULT.callableTask(() -> function.apply(cluster, indexNameList));\n        }\n        Optional<Result<Void>> voidResult = FUTURE_UTIL_RESULT.waitResult().stream().filter(Result::failed).findAny();\n        if (voidResult.isPresent()) {\n            return Result.buildFrom(voidResult.get());\n        }\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    public Result<Boolean> openIndex(List<IndexCatCellDTO> params, Integer projectId, String operator) {\n        return this.batchOperateIndex(params, projectId, (cluster, indexNameList) -> {\n            try {\n\n                boolean syncOpenOrCloseResult = esIndexService.syncBatchOpenIndices(cluster, indexNameList, 3);\n                if (!syncOpenOrCloseResult) {\n                    return Result.buildFail(\"批量开启索引失败\");\n                }\n\n                Result<Boolean> setCatIndexResult = updateIndicesStatus(cluster, indexNameList, \"open\");\n                if (!setCatIndexResult.success()) {\n                    return Result.buildFail(\"批量更新索引状态失败\");\n                }\n                for (String indexName : indexNameList) {\n        \n                    operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"开启索引：【%s】\", indexName),\n                            operator, projectId, indexName, OperateTypeEnum.INDEX_SERVICE_OP_INDEX);\n                }\n\n            } catch (ESOperateException e) {\n                LOGGER.error(\n                    \"class=IndicesManagerImpl||method=closeIndicesStatus||cluster={}||indexNameList={}||errMsg={}\",\n                    cluster, ListUtils.strList2String(indexNameList), e.getMessage(), e);\n                return Result.buildFail(e.getMessage());\n            }\n\n            return Result.buildSucc();\n        });\n    }\n\n    @Override\n    public Result<Boolean> closeIndex(List<IndexCatCellDTO> params, Integer projectId, String operator) {\n        return this.batchOperateIndex(params, projectId, (cluster, indexNameList) -> {\n            try {\n\n                boolean syncOpenOrCloseResult = esIndexService.syncBatchCloseIndices(cluster, indexNameList, 3);\n                if (!syncOpenOrCloseResult) {\n                    return Result.buildFail(\"批量关闭索引失败\");\n                }\n\n                Result<Boolean> setCatIndexResult = updateIndicesStatus(cluster, indexNameList, \"close\");\n                if (!setCatIndexResult.success()) {\n                    return Result.buildFail(\"批量更新索引状态失败\");\n                }\n                for (String indexName : indexNameList) {\n                    operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"关闭索引：【%s】\", indexName),\n                            operator, projectId, indexName, OperateTypeEnum.INDEX_SERVICE_OP_INDEX);\n                }\n\n            } catch (ESOperateException e) {\n                LOGGER.error(\n                    \"class=IndicesManagerImpl||method=closeIndicesStatus||cluster={}||indexNameList={}||errMsg={}\",\n                    cluster, ListUtils.strList2String(indexNameList), e.getMessage(), e);\n                return Result.buildFail(e.getMessage());\n            }\n\n            return Result.buildSucc();\n        });\n    }\n\n    @Override\n    public Result<Void> updateIndexFlagInvalid(String cluster, List<String> indexNameList) {\n        //不采集已删除索引\n        indexCatInfoCollector.updateNotCollectorIndexNames(cluster, indexNameList);\n        //更新存储cat/index信息的元信息索引中对应文档删除标识位为true\n        boolean succ = indexNameList.size() == esIndexCatService.syncUpdateCatIndexDeleteFlag(cluster, indexNameList,\n            3);\n        if (!succ) {\n            LOGGER.error(\n                \"class=IndicesManagerImpl||method=batchSetIndexFlagInvalid||cluster={}||indexNameList={}||errMsg=failed to batchSetIndexFlagInvalid\",\n                cluster, ListUtils.strList2String(indexNameList));\n        }\n        return Result.build(succ);\n    }\n\n    private Result<Boolean> updateIndicesStatus(String cluster, List<String> indexNameList, String status) {\n        boolean succ = indexNameList.size() == esIndexCatService.syncUpdateCatIndexStatus(cluster, indexNameList,\n            status, 3);\n        if (!succ) {\n            LOGGER.error(\n                \"class=IndicesManagerImpl||method=batchSetIndexStatus||cluster={}||indexNameList={}||errMsg=failed to batchSetIndexStatus\",\n                cluster, ListUtils.strList2String(indexNameList));\n        }\n        return Result.build(succ);\n    }\n\n    @Override\n    public Result<Void> editIndexBlockSetting(List<IndicesBlockSettingDTO> params, Integer projectId, String operator) {\n        for (IndicesBlockSettingDTO param : params) {\n            Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(param.getCluster(), projectId);\n            if (getClusterRet.failed()) {\n                return Result.buildFrom(getClusterRet);\n            }\n            String phyCluster = getClusterRet.getData();\n            param.setCluster(phyCluster);\n        }\n        Result<Void> checkResult = checkEditIndexBlockSetting(params, projectId);\n        if (checkResult.failed()) {\n            return checkResult;\n        }\n\n        Map<String, List<IndicesBlockSettingDTO>> cluster2IndicesBlockSettingListMap = ConvertUtil.list2MapOfList(\n            params, IndicesBlockSettingDTO::getCluster, indicesBlockSettingDTO -> indicesBlockSettingDTO);\n\n        cluster2IndicesBlockSettingListMap.forEach((cluster, indicesBlockSettingList) -> {\n            for (IndicesBlockSettingDTO indicesBlockSetting : indicesBlockSettingList) {\n                try {\n                    boolean succ = false;\n                    if (IndexBlockEnum.READ.getType().equals(indicesBlockSetting.getType())) {\n                        succ = esIndexService.syncBatchBlockIndexRead(cluster,\n                            Lists.newArrayList(indicesBlockSetting.getIndex()), indicesBlockSetting.getValue(), 3);\n                    }\n\n                    if (IndexBlockEnum.WRITE.getType().equals(indicesBlockSetting.getType())) {\n                        succ = esIndexService.syncBatchBlockIndexWrite(cluster,\n                            Lists.newArrayList(indicesBlockSetting.getIndex()), indicesBlockSetting.getValue(), 3);\n                    }\n\n                    if (succ) {\n                        String writeOrRead=StringUtils.equals(indicesBlockSetting.getType(),\"write\")?\"写\":\"读\";\n                        String value=indicesBlockSetting.getValue().equals(Boolean.FALSE)?\"启用\":\"禁用\";\n                     \n                        \n                        for (IndicesBlockSettingDTO param : params) {\n                            String operateContent = String.format(\"【%s】:%s%s\", param.getIndex(), value, writeOrRead);\n                            operateRecordService.saveOperateRecordWithManualTrigger(operateContent, operator, projectId,\n                                    param.getIndex(), OperateTypeEnum.INDEX_SERVICE_READ_WRITE_CHANGE);\n                        }\n\n                    }\n                } catch (ESOperateException e) {\n                    LOGGER.error(\n                        \"class=IndicesManagerImpl||method=editIndexBlockSetting||cluster={}||index={}||errMsg={}\",\n                        cluster, indicesBlockSetting.getIndex(), e.getMessage(), e);\n                }\n            }\n        });\n\n        return Result.build(true);\n    }\n\n    @Override\n    public Result<IndexMappingVO> getMapping(String cluster, String indexName, Integer projectId) {\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(cluster, projectId);\n        if (getClusterRet.failed()) {\n            return Result.buildFrom(getClusterRet);\n        }\n        String phyCluster = getClusterRet.getData();\n        Result<Void> ret = basicCheckParam(phyCluster, indexName, projectId);\n        if (ret.failed()) {\n            return Result.buildFrom(ret);\n        }\n\n        IndexMappingVO indexMappingVO = new IndexMappingVO();\n        String mappingConfig = esIndexService.syncGetIndexMapping(phyCluster, indexName);\n        indexMappingVO.setMappings(mappingConfig);\n        indexMappingVO.setIndexName(indexName);\n        return Result.buildSucc(indexMappingVO);\n    }\n\n    @Override\n    public Result<Void> editMapping(IndexCatCellWithConfigDTO param, Integer projectId, String operate)\n            throws AdminOperateException {\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(param.getCluster(), projectId);\n        if (getClusterRet.failed()) {\n            return Result.buildFrom(getClusterRet);\n        }\n        String phyCluster = getClusterRet.getData();\n        String indexName = param.getIndex();\n        String mapping = param.getMapping();\n        Result<Void> ret = basicCheckParam(phyCluster, indexName, projectId);\n        if (ret.failed()) {\n            return Result.buildFrom(ret);\n        }\n        if (StringUtils.isBlank(mapping)) {\n            return Result.buildFail(\"请传入索引Mapping\");\n        }\n        final Result<IndexMappingVO> beforeMapping = getMapping(param.getCluster(), indexName, projectId);\n        Result<MappingConfig> mappingRet;\n        if (!StringUtils.contains(mapping, PROPERTIES)) {\n            //这里为了兼容多 type索引，前端进针对用户输入的内容做封装，所以后端解析封装\n            JSONObject jsonObject = new JSONObject();\n            jsonObject.put(\"properties\", mapping);\n            mappingRet = AriusIndexMappingConfigUtils.parseMappingConfig(jsonObject.toJSONString());\n        } else {\n            mappingRet = AriusIndexMappingConfigUtils.parseMappingConfig(mapping);\n        }\n        if (mappingRet.failed()) {\n            return Result.buildFail(\"mapping 转换异常\");\n        }\n\n        try {\n            final boolean syncUpdateIndexMapping = esIndexService.syncUpdateIndexMapping(phyCluster, indexName,\n                mappingRet.getData());\n            if (syncUpdateIndexMapping) {\n\n                final Result<IndexMappingVO> afterMapping = getMapping(param.getCluster(), indexName, projectId);\n    \n                operateRecordService.saveOperateRecordWithManualTrigger(\n                        new TemplateMappingOperateRecord(beforeMapping.getData(), afterMapping.getData()).toString(),\n                        operate, projectId, indexName, OperateTypeEnum.INDEX_TEMPLATE_MANAGEMENT_EDIT_MAPPING);\n            }\n\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=IndicesManagerImpl||method=editMapping||errMsg={}\", e.getMessage(), e);\n            return Result.buildFail(e.getMessage() + \":\" + e.getCause());\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<IndexSettingVO> getSetting(String cluster, String indexName, Integer projectId) {\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(cluster, projectId);\n        if (getClusterRet.failed()) {\n            return Result.buildFrom(getClusterRet);\n        }\n        String phyCluster = getClusterRet.getData();\n        Result<Void> ret = basicCheckParam(phyCluster, indexName, projectId);\n        if (ret.failed()) {\n            return Result.buildFrom(ret);\n        }\n\n        IndexSettingVO indexSettingVO = new IndexSettingVO();\n        MultiIndexsConfig multiIndexsConfig = esIndexService.syncGetIndexConfigs(phyCluster, indexName);\n        if (null == multiIndexsConfig) {\n            LOGGER.warn(\n                \"class=IndicesManagerImpl||method=getSetting||cluster={}||index={}||errMsg=get empty Index configs \",\n                phyCluster, indexName);\n            return Result.buildSucc(indexSettingVO);\n        }\n\n        IndexConfig indexConfig = multiIndexsConfig.getIndexConfig(indexName);\n        if (null == indexConfig) {\n            LOGGER.warn(\n                \"class=IndicesManagerImpl||method=getSetting||cluster={}||index={}||errMsg=get empty Index configs \",\n                phyCluster, indexName);\n            return Result.buildSucc(indexSettingVO);\n        }\n        indexSettingVO.setProperties(JsonUtils.reFlat(indexConfig.getSettings()));\n        indexSettingVO.setIndexName(indexName);\n        return Result.buildSucc(indexSettingVO);\n    }\n\n    @Override\n    public Result<Void> editSetting(IndexCatCellWithConfigDTO param, Integer projectId,\n                                    String operator) throws ESOperateException {\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(param.getCluster(), projectId);\n        if (getClusterRet.failed()) {\n            return Result.buildFrom(getClusterRet);\n        }\n        String phyCluster = getClusterRet.getData();\n        String indexName = param.getIndex();\n        Result<Void> ret = basicCheckParam(phyCluster, indexName, projectId);\n        if (ret.failed()) {\n            return Result.buildFrom(ret);\n        }\n        \n        \n    \n        final Result<IndexSettingVO> beforeSetting = getSetting(param.getCluster(), indexName, projectId);\n        IndexSettingsUtil.checkImmutableSettingAndCorrectSetting(param.getSetting(),beforeSetting.getData(),projectId);\n        JSONObject settingObj = JSON.parseObject(param.getSetting());\n        if (null == settingObj) {\n            return Result.buildFail(\"setting 配置非法\");\n        }\n        \n        Map<String, IndexConfig> configMap = esIndexService.syncGetIndexSetting(phyCluster,\n            Lists.newArrayList(indexName), RETRY_COUNT);\n        Map<String, String> sourceSettings = AriusOptional.ofObjNullable(configMap.get(indexName))\n            .map(IndexConfig::getSettings).orElse(Maps.newHashMap());\n        final Map<String, String> finalSettingMap = IndexSettingsUtil.getChangedSettings(sourceSettings,\n            JsonUtils.flat(settingObj));\n        boolean syncPutIndexSettings = true;\n        if (finalSettingMap.size() > 0) {\n            syncPutIndexSettings = esIndexService.syncPutIndexSettings(phyCluster,\n                    Lists.newArrayList(indexName), finalSettingMap, RETRY_COUNT);\n            if (syncPutIndexSettings) {\n                final Result<IndexSettingVO> afterSetting = getSetting(param.getCluster(), indexName, projectId);\n                operateRecordService.saveOperateRecordWithManualTrigger(\n                        new TemplateSettingOperateRecord(beforeSetting.getData(), afterSetting.getData()).toString(),\n                        operator, projectId, indexName, OperateTypeEnum.INDEX_TEMPLATE_MANAGEMENT_EDIT_SETTING);\n            }\n        }\n\n\n        return Result.build(syncPutIndexSettings);\n    }\n\n    @Override\n    public Result<List<IndexShardInfoVO>> getIndexShardsInfo(String cluster, String indexName, Integer projectId) {\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(cluster, projectId);\n        if (getClusterRet.failed()) {\n            return Result.buildFrom(getClusterRet);\n        }\n        String phyCluster = getClusterRet.getData();\n        Result<Void> ret = basicCheckParam(phyCluster, indexName, projectId);\n        if (ret.failed()) {\n            return Result.buildFrom(ret);\n        }\n\n        List<IndexShardInfo> indexShardInfoList = null;\n        try {\n            indexShardInfoList = esIndexCatService.syncGetIndexShardInfo(phyCluster, indexName);\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=IndicesManagerImpl||method=getIndexShardsInfo||clusterName={}||errMsg=fail to get indexShardInfo\",\n                    cluster);\n            return Result.buildFail(\"获取索引shard(主)在节点中的分布详情异常\");\n        }\n        List<IndexShardInfoVO> indexNodeShardVOList = indexShardInfoList.stream().filter(this::filterPrimaryShard)\n                .map(this::coverUnit).collect(Collectors.toList());\n        return Result.buildSucc(indexNodeShardVOList);\n    }\n\n    @Override\n    public Result<IndexCatCellVO> getIndexCatInfo(String cluster, String indexName, Integer projectId) {\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(cluster, projectId);\n        if (getClusterRet.failed()) {\n            return Result.buildFrom(getClusterRet);\n        }\n        String phyCluster = getClusterRet.getData();\n    \n        IndexCatCell indexCatCell = esIndexCatService.syncGetCatIndexInfoById(phyCluster, indexName);\n        if (Objects.isNull(indexCatCell)) {\n            return Result.buildFail(\"获取单个索引详情信息失败\");\n        }\n        //设置索引阻塞信息\n        List<IndexCatCell> finalIndexCatCellList = esIndexService.buildIndexAliasesAndBlockInfo(phyCluster,\n                Collections.singletonList(indexCatCell));\n        List<IndexCatCellVO> indexCatCellVOList = ConvertUtil.list2List(finalIndexCatCellList, IndexCatCellVO.class);\n    \n        return Result.buildSucc(indexCatCellVOList.get(0));\n    }\n\n    @Override\n    public Result<Void> addIndexAliases(IndexCatCellWithConfigDTO param, Integer projectId, String operator) {\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(param.getCluster(), projectId);\n        if (getClusterRet.failed()) {\n            return Result.buildFrom(getClusterRet);\n        }\n        String phyCluster = getClusterRet.getData();\n        Result<Void> result = esIndexService.addAliases(phyCluster, param.getIndex(), param.getAliases());\n        if (result.success()) {\n    \n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"index:【%s】, 添加别名：【%s】\", param.getIndex(), param.getAliases()), operator,\n                    projectId, param.getIndex(), OperateTypeEnum.INDEX_MANAGEMENT_ALIAS_MODIFY);\n        }\n        return result;\n    }\n\n    @Override\n    public Result<Void> deleteIndexAliases(IndexCatCellWithConfigDTO param, Integer projectId, String operator) {\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(param.getCluster(), projectId);\n        if (getClusterRet.failed()) {\n            return Result.buildFrom(getClusterRet);\n        }\n        String phyCluster = getClusterRet.getData();\n        Result<Void> result = esIndexService.deleteAliases(phyCluster, param.getIndex(), param.getAliases());\n        if (result.success()) {\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"index:【%s】删除别名：【%s】\", param.getIndex(), param.getAliases()), operator, projectId,\n                    param.getIndex(), OperateTypeEnum.INDEX_MANAGEMENT_ALIAS_MODIFY);\n        }\n        return result;\n    }\n\n    @Override\n    public Result<List<String>> getIndexAliases(String cluster, String indexName, Integer projectId) {\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(cluster, projectId);\n        if (getClusterRet.failed()) {\n            return Result.buildFrom(getClusterRet);\n        }\n        String phyCluster = getClusterRet.getData();\n        Map<String, List<String>> aliasMap = esIndexService.syncGetIndexAliasesByIndices(phyCluster, indexName);\n        return Result.buildSucc(aliasMap.getOrDefault(indexName, Lists.newArrayList()));\n    }\n\n    @Override\n    public Result<Void> rollover(IndexRolloverDTO param, String operator, Integer projectId) {\n        if (null == param.getIndices()) {\n            return Result.buildFail(\"索引为空\");\n        }\n        JSONArray resultMessage=new JSONArray();\n        for (IndexCatCellDTO indexCatCellDTO : param.getIndices()) {\n            String cluster = indexCatCellDTO.getCluster();\n            if (!RegexUtils.checkEndWithHyphenNumbers(indexCatCellDTO.getIndex())) {\n                return Result.buildFail(\"索引后缀必须按照横杠加数字为结尾才可以进行 rollover, 如：test-1\");\n            }\n            final List<String> aliasList = esIndexService.syncGetIndexAliasesByExpression(cluster,\n                    indexCatCellDTO.getIndex()).stream().map(Tuple::getV2).collect(Collectors.toList());\n            if (AriusObjUtils.isEmptyList(aliasList)) {\n                return Result.buildFail(\"alias 为空\");\n            }\n            final String aliasName = aliasList.stream()\n                    .map(alias -> Tuples.of(alias, esIndexService.countIndexByAlias(cluster, alias)))\n                    .filter(aliasTuples -> aliasTuples.v2.success())\n                    .map(aliasTuples -> Tuples.of(aliasTuples.v1, aliasTuples.v2().getData()))\n                    .filter(aliasTuples -> aliasTuples.v2 == 1).findFirst().map(TupleTwo::v1).orElse(null);\n    \n            if (Objects.isNull(aliasName)) {\n                return Result.buildFail(String.format(\"索引 %s 没有匹配到具有唯一性的别名，rollover 操作无法执行\",\n                        indexCatCellDTO.getIndex()));\n            }\n\n            Result<Void> rolloverResult = esIndexService.rollover(cluster, aliasName,\n                param.getContent());\n            if (rolloverResult.failed()) {\n                return rolloverResult;\n            }\n            resultMessage.add(rolloverResult.getMessage());\n            //操作记录\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"【%s】使用别名{%s}执行rollover\",indexCatCellDTO.getIndex(),aliasName), operator, projectId,\n                    indexCatCellDTO.getIndex(), OperateTypeEnum.INDEXING_SERVICE_RUN);\n        }\n\n        return Result.buildSuccWithMsg(resultMessage.toJSONString());\n    }\n\n    @Override\n    public Result<Void> shrink(IndexCatCellWithConfigDTO param, String operator, Integer projectId) {\n        final Result<Void> result = esIndexService.shrink(param.getCluster(), param.getIndex(), param.getTargetIndex(),\n                param.getExtra());\n        if (result.success()) {\n            //操作记录\n            operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"【%s】执行 shrink\", param.getIndex()),\n                    operator, projectId, param.getIndex(), OperateTypeEnum.INDEXING_SERVICE_RUN);\n        }\n        return result;\n       \n    }\n\n    @Override\n    public Result<Void> split(IndexCatCellWithConfigDTO param, String operator, Integer projectId) {\n        final Result<Void> result = esIndexService.split(param.getCluster(), param.getIndex(), param.getTargetIndex(),\n                param.getExtra());\n        if (result.success()){\n              //操作记录\n            operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"【%s】执行split\",param.getIndex()),\n                    operator, projectId, param.getIndex(), OperateTypeEnum.INDEXING_SERVICE_RUN);\n        }\n        return result;\n      \n    }\n\n    @Override\n    public Result<Void> forceMerge(IndexForceMergeDTO param, String operator, Integer projectId) {\n        if (null == param.getIndices()) {\n            return Result.buildFail(\"索引为空\");\n        }\n        JSONArray resultMessage=new JSONArray();\n        List<TupleTwo</*cluster*/String,/*index*/String>> clusterIndexTuple=Lists.newArrayList();\n        for (IndexCatCellDTO indexCatCellDTO : param.getIndices()) {\n            Result<Void> forceMergeResult = esIndexService.forceMerge(indexCatCellDTO.getCluster(),\n                indexCatCellDTO.getIndex(), param.getMaxNumSegments(), param.getOnlyExpungeDeletes());\n            if (forceMergeResult.failed()) {\n                return Result.buildFrom(forceMergeResult);\n            }\n                 //操作记录\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"【%s】执行 forceMerge\", indexCatCellDTO.getIndex()), operator, projectId,\n                    indexCatCellDTO.getIndex(), OperateTypeEnum.INDEXING_SERVICE_RUN);\n            clusterIndexTuple.add(Tuples.of(indexCatCellDTO.getCluster(), indexCatCellDTO.getIndex()));\n            resultMessage.add(JSON.parseObject(forceMergeResult.getMessage()));\n        }\n        //需要发布事件进行arius_cat_index_info 采集更新信息，尽可能保证数据的时效性\n        SpringTool.publish(new RefreshCatIndexInfoEvent(this, clusterIndexTuple));\n        return Result.buildSuccWithMsg(resultMessage.toJSONString());\n    }\n\n    @Override\n    public Result<List<String>> getClusterPhyIndexName(String clusterPhyName, Integer projectId, String index) {\n        if (!projectService.checkProjectExist(projectId)) {\n            return Result.buildParamIllegal(String.format(\"There is no projectId:%s\", projectId));\n        }\n\n        return Result.buildSucc(esIndexCatService.syncGetIndexListByProjectIdAndFuzzyIndexAndClusterPhy( clusterPhyName,index ));\n    }\n\n    @Override\n    public Result<List<String>> getClusterLogicIndexName(String clusterLogicName, Integer projectId, String index) {\n        List<String> indexNames = esIndexCatService.syncGetIndexListByProjectIdAndFuzzyIndexAndClusterLogic(projectId, clusterLogicName,index );\n        return Result.buildSucc(indexNames);\n    }\n\n    @Override\n    public Result<Boolean> isExists(String cluster, String indexName, Integer projectId) {\n        if (!projectService.checkProjectExist(projectId)) {\n            return Result.buildParamIllegal(String.format(\"当前登录项目Id[%s]不存在, 无权限操作\", projectId));\n        }\n        Result<String> getClusterRet = getClusterPhyByClusterNameAndProjectId(cluster, projectId);\n        if (getClusterRet.failed()) {\n            return Result.buildFrom(getClusterRet);\n        }\n        String phyClusterName = getClusterRet.getData();\n        if (!clusterPhyService.isClusterExists(phyClusterName)) {\n            return Result.buildParamIllegal(String.format(\"物理集群[%s]不存在\", phyClusterName));\n        }\n\n        // 判断索引名称是否和集群模版名称前缀匹配\n        IndexCatCellWithConfigDTO indexWithConfigDTO = new IndexCatCellWithConfigDTO();\n        indexWithConfigDTO.setIndex(indexName);\n        Result<Void> checkValidRet = checkValid(indexWithConfigDTO, phyClusterName);\n        if (checkValidRet.failed()) {\n            return Result.buildFrom(checkValidRet);\n        }\n\n        return Result.buildSucc(esIndexService.syncIsIndexExist(phyClusterName, indexName));\n    }\n\n    @Override\n    public List<IndexCatCellWithTemplateVO> listIndexCatCellWithTemplateByTemplatePhyId(Long physicalId) {\n        List<CatIndexResult> indices = listIndexCatInfoByTemplatePhyId(physicalId);\n        if (CollectionUtils.isEmpty(indices)) {\n            return Lists.newArrayList();\n        }\n        return ConvertUtil.list2List(indices,IndexCatCellWithTemplateVO.class);\n    }\n\n    @Override\n    public List<CatIndexResult> listIndexCatInfoByTemplatePhyId(Long physicalId) {\n        IndexTemplatePhyWithLogic templatePhysicalWithLogic = indexTemplatePhyService\n            .getTemplateWithLogicById(physicalId);\n        if (templatePhysicalWithLogic == null) {\n            return Lists.newArrayList();\n        }\n        String expression = templatePhysicalWithLogic.getExpression();\n        if (templatePhysicalWithLogic.getVersion() != null && templatePhysicalWithLogic.getVersion() > 0\n            && !expression.endsWith(START)) {\n            expression = expression + START;\n        }\n        return esIndexService.syncCatIndexByExpression(templatePhysicalWithLogic.getCluster(), expression);\n    }\n    \n    /**\n     * @param clusterPhy\n     * @param indexNameList\n     * @param projectId\n     * @param operator\n     * @return\n     */\n    @Override\n    public Result<Void> deleteIndexByCLusterPhy(String clusterPhy, List<String> indexNameList, Integer projectId,\n                                                String operator) {\n        if (indexNameList.size() == esIndexService.syncBatchDeleteIndices(clusterPhy, indexNameList, RETRY_COUNT)) {\n            Result<Void> batchSetIndexFlagInvalidResult = updateIndexFlagInvalid(clusterPhy, indexNameList);\n            if (batchSetIndexFlagInvalidResult.success()) {\n                for (String indexName : indexNameList) {\n                    operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"删除索引：【%s】\", indexName),\n                            operator, projectId, indexName, OperateTypeEnum.INDEX_MANAGEMENT_DELETE);\n                }\n            \n            }\n            \n        }\n        \n        \n        return Result.buildSucc();\n    }\n    \n    /***************************************************private**********************************************************/\n    private Result<Void> basicCheckParam(String cluster, String index, Integer projectId) {\n        if (!projectService.checkProjectExist(projectId)) {\n            return Result.buildParamIllegal(String.format(\"当前登录项目Id[%s]不存在, 无权限操作\", projectId));\n        }\n\n        if (!clusterPhyService.isClusterExists(cluster)) {\n            return Result.buildParamIllegal(String.format(\"物理集群[%s]不存在\", cluster));\n        }\n\n        if (!esIndexService.syncIsIndexExist(cluster, index)) {\n            return Result.buildParamIllegal(String.format(\"集群[%s]中的索引[%s]不存在\", cluster, index));\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkEditIndexBlockSetting(List<IndicesBlockSettingDTO> params, Integer projectId) {\n        for (IndicesBlockSettingDTO param : params) {\n            Result<Void> ret = basicCheckParam(param.getCluster(), param.getIndex(), projectId);\n            if (ret.failed()) {\n                return ret;\n            }\n\n            if (!IndexBlockEnum.isIndexBlockExit(param.getType())) {\n                return Result.buildParamIllegal(String.format(\"阻塞类型%s不存在\", param.getType()));\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    private boolean filterPrimaryShard(IndexShardInfo indexShardInfo) {\n        if (null == indexShardInfo) {\n            return false;\n        }\n\n        return PRIMARY.equals(indexShardInfo.getPrirep());\n    }\n\n    /**\n     * 统一单位 byte\n     * @param indexShardInfo\n     * @return\n     */\n    private IndexShardInfoVO coverUnit(IndexShardInfo indexShardInfo) {\n        IndexShardInfoVO indexShardInfoVO = ConvertUtil.obj2Obj(indexShardInfo, IndexShardInfoVO.class);\n        indexShardInfoVO.setStoreInByte(SizeUtil.getUnitSize(indexShardInfo.getStore()));\n        return indexShardInfoVO;\n    }\n\n    /**\n     * 注意， 这里普通用户侧前端传输cluster值是：逻辑集群名称，运维侧是：物理集群名称\n     * @param cluster\n     * @param projectId\n     * @return\n     */\n    private Result<String> getClusterPhyByClusterNameAndProjectId(String cluster, Integer projectId) {\n        String phyClusterName;\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            phyClusterName = cluster;\n        } else {\n            ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByNameAndProjectId(cluster,projectId );\n            if (null == clusterLogic) {\n                return Result.buildParamIllegal(String.format(\"逻辑集群[%s]不存在\", cluster));\n            }\n            ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogic.getId());\n            if (null == clusterRegion) {\n                return Result.buildParamIllegal(\"逻辑集群未绑定Region\");\n            }\n            phyClusterName = clusterRegion.getPhyClusterName();\n            if (!esClusterService.isConnectionStatus(phyClusterName)){\n                return Result.buildFail(String.format(\"%s 集群不正常\",cluster));\n            }\n        }\n        return Result.buildSucc(phyClusterName);\n    }\n\n    private Result<Void> initIndexCreateDTO(IndexCatCellWithConfigDTO indexCreateDTO, Integer projectId) {\n        if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByNameAndProjectId(indexCreateDTO.getCluster(), projectId);\n            if (null == clusterLogic) {\n                return Result.buildParamIllegal(String.format(\"逻辑集群[%s]不存在\", indexCreateDTO.getCluster()));\n            }\n            ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogic.getId());\n            if (null == clusterRegion) { return Result.buildParamIllegal(\"逻辑集群未绑定Region\");}\n\n            // 这里用户侧，传逻辑集群名称 这里先补丁适配\n            indexCreateDTO.setClusterLogic(clusterLogic.getName());\n            indexCreateDTO.setResourceId(clusterLogic.getId());\n            indexCreateDTO.setCluster(clusterRegion.getPhyClusterName());\n        }\n\n        indexCreateDTO.setPlatformCreateFlag(true);\n        indexCreateDTO.setProjectId(projectId);\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkValid(IndexCatCellWithConfigDTO params, String phyCluster) {\n        String index = params.getIndex();\n        String key   = phyCluster + \"@\" + index;\n\n        List<IndexTemplatePhy> indexTemplatePhyList = indexTemplatePhyService.listTemplate();\n        if (CollectionUtils.isEmpty(indexTemplatePhyList)) { return Result.buildSucc();}\n\n        List<String> existKeyList = indexTemplatePhyList.stream().map(r -> r.getCluster() + \"@\" + r.getName())\n                .distinct().collect(Collectors.toList());\n        for (String existKey : existKeyList) {\n            if (existKey.startsWith(key) || key.startsWith(existKey)) {\n                return Result.buildFail(String.format(\"创建的索引名称[%s]不允许和该集群模板名称[%s]存在相互前缀的匹配, 请修改索引名称\",\n                        index, existKey.split(\"@\")[1]));\n            }\n        }\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/ApplicationRetryListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.EventException;\nimport com.didichuxing.datachannel.arius.admin.common.util.EventRetryExecutor;\nimport lombok.SneakyThrows;\nimport org.jetbrains.annotations.NotNull;\nimport org.springframework.context.ApplicationEvent;\nimport org.springframework.context.ApplicationListener;\n\nimport java.util.function.Predicate;\n\npublic abstract class ApplicationRetryListener<E extends ApplicationEvent> implements ApplicationListener<E> {\n\n    /**\n     * @param event\n     */\n    @SneakyThrows\n    @Override\n    public void onApplicationEvent(@NotNull E event) {\n        // onApplicationRetryEvent 如果抛出异常则进行重试\n        EventRetryExecutor.eventRetryExecute( \"ApplicationRetryListener\",\n                () -> {onApplicationRetryEvent(event); return null;},\n                3);\n    }\n\n    /**\n     * 支持重试的时间处理逻辑, 如果抛出异常则进行重试\n     * @param event\n     * @return\n     * @throws EventException\n     */\n    public abstract void onApplicationRetryEvent(E event) throws EventException;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/ClusterLogicChangeListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterLogicManager;\nimport com.didichuxing.datachannel.arius.admin.common.exception.EventException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport com.didichuxing.datachannel.arius.admin.common.event.resource.ClusterLogicEvent;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * Created by linyunan on 2021-06-03\n */\n@Component\npublic class ClusterLogicChangeListener extends ApplicationRetryListener<ClusterLogicEvent> {\n\n    private static final ILog     LOGGER = LogFactory.getLog(ClusterLogicChangeListener.class);\n\n    @Autowired\n    private ClusterLogicManager   clusterLogicManager;\n\n    @Override\n    public void onApplicationRetryEvent(ClusterLogicEvent event) throws EventException {\n        if(!clusterLogicManager.updateClusterLogicHealth(event.getClusterLogicId())){\n            LOGGER.error(\n                    \"class=ClusterPhyChangeListener||method=onApplicationEvent||projectId={}||clusterPhyName={}||ErrorMsg={}\",\n                    event.getProjectId(), event.getClusterLogicId());\n            throw new EventException(\"e.getMessage(), e\");\n        }\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/ClusterPhyChangeListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterContextManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.event.resource.ClusterPhyEvent;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author linyunan\n * @date 2021-06-03\n */\n@Component\npublic class ClusterPhyChangeListener implements ApplicationListener<ClusterPhyEvent> {\n\n    private static final ILog     LOGGER = LogFactory.getLog(ClusterPhyChangeListener.class);\n\n    @Autowired\n    private ClusterContextManager clusterContextManager;\n\n    @Autowired\n    private ClusterPhyManager     clusterPhyManager;\n\n    @Override\n    public void onApplicationEvent(ClusterPhyEvent event) {\n        try {\n            //保证数据已经刷到数据库，如果立即执行，会存在获取不到数据库中数据的状态\n            Thread.sleep(5000);\n            clusterContextManager.flushClusterPhyContext(event.getClusterPhyName());\n\n            clusterPhyManager.updateClusterHealth(event.getClusterPhyName(), AriusUser.SYSTEM.getDesc());\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=ClusterPhyChangeListener||method=onApplicationEvent||operator={}||clusterPhyName={}||ErrorMsg={}\",\n                event.getOperator(), event.getClusterPhyName(), e.getMessage());\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/ClusterPhyHealthListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Component;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.event.resource.ClusterPhyHealthEvent;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpClient;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n@Component\npublic class ClusterPhyHealthListener implements ApplicationListener<ClusterPhyHealthEvent> {\n\n    private static final ILog LOGGER = LogFactory.getLog(ClusterPhyHealthListener.class);\n\n    @Autowired\n    private ESOpClient        esOpClient;\n\n    @Autowired\n    private ClusterPhyManager clusterPhyManager;\n\n    @Override\n    public void onApplicationEvent(ClusterPhyHealthEvent event) {\n        if (event.getClusterPhyName() == null) {\n            return;\n        }\n        try {\n            // 刷新es-client中的map连接信息\n            esOpClient.connect(event.getClusterPhyName());\n            // 修改物理集群对应的状态\n            clusterPhyManager.updateClusterHealth(event.getClusterPhyName(), AriusUser.SYSTEM.getDesc());\n        } catch (Exception e) {\n            LOGGER.error(\"class=ClusterPhyHealthListener||method=onApplicationEvent||cluster={},errMsg={}\",\n                event.getClusterPhyName(), e.getMessage());\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/DCDRLinkAbnormalIndicesRebuildListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.dcdr.TemplateDCDRManager;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.DCDRLinkAbnormalIndicesRebuildEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.logging.log4j.core.tools.picocli.CommandLine.Command;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Component;\n\n/**\n * 这个类是监听 `DCDRLinkAbnormalIndicesRebuildEvent` 事件的监听器\n *\n * @author shizeying\n * @date 2022/09/26\n */\n@Component\npublic class DCDRLinkAbnormalIndicesRebuildListener\n        implements ApplicationListener<DCDRLinkAbnormalIndicesRebuildEvent> {\n    private static final ILog                LOGGER = LogFactory.getLog(DCDRLinkAbnormalIndicesRebuildListener.class);\n    @Autowired\n    private              TemplateDCDRManager templateDCDRManager;\n    \n    /**\n     * @param event\n     */\n    @Override\n    public void onApplicationEvent(DCDRLinkAbnormalIndicesRebuildEvent event) {\n        try {\n            \n            templateDCDRManager.rebuildDCDRLinkAbnormalIndices(event.getCluster(), event.getTargetCluster(), event.getIndices());\n        } catch (ESOperateException e) {\n            LOGGER.error(\n                    \"class={}||method=onApplicationEvent||cluster={}||targetCluster={}||indices={}\",\n                    getClass().getSimpleName(), event.getCluster(), event.getTargetCluster(),\n                    String.join(\",\", event.getIndices()));\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/LoggingListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;\nimport org.springframework.boot.context.logging.LoggingApplicationListener;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.stereotype.Component;\n\n/**\n * 读取yml配置传递到log4jXml中\n *\n * @author slhu\n */\n@Component\npublic class LoggingListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {\n\n    private static final String SPRING_LOGI_JOB_ES_PREFIX = \"spring.logi-job.elasticsearch-\";\n    private static final String[] CONFIG_KEYS = {\"address\", \"port\", \"user\", \"password\", \"index-name\", \"type-name\"};\n\n    @Override\n    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEvent) {\n        ConfigurableEnvironment environment = applicationEvent.getEnvironment();\n        for (String config : CONFIG_KEYS) {\n            //提供给日志文件读取配置的key，使用时需要在前面加上 sys:\n            String key = SPRING_LOGI_JOB_ES_PREFIX + config;\n            String val = environment.getProperty(key);\n            if (StringUtils.isNotBlank(val)) {\n                System.setProperty(key, val);\n            }\n        }\n    }\n\n    @Override\n    public int getOrder() {\n        // 当前监听器的启动顺序需要在日志配置监听器的前面，所以此处减 1\n        return LoggingApplicationListener.DEFAULT_ORDER - 1;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/LogicTemplateCreatePipelineListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.pipeline.PipelineManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.LogicTemplateCreatePipelineEvent;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.concurrent.TimeUnit;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Component;\n\n/**\n * 逻辑模板创建pipeline\n *\n * @author shizeying\n * @date 2022/07/22\n */\n@Component\npublic class LogicTemplateCreatePipelineListener implements ApplicationListener<LogicTemplateCreatePipelineEvent> {\n    private static final ILog            LOGGER = LogFactory.getLog(LogicTemplateCreatePipelineListener.class);\n    @Autowired\n    private              PipelineManager pipelineManager;\n    @Autowired\n    private IndexTemplateService indexTemplateService;\n    \n    /**\n     * @param logicTemplateCreatePipelineEvent\n     */\n    @Override\n    public void onApplicationEvent(LogicTemplateCreatePipelineEvent logicTemplateCreatePipelineEvent) {\n        try {\n             //保证数据已经刷到数据库，如果立即执行，会存在获取不到数据库中数据的状态，所以等待3s\n            TimeUnit.SECONDS.sleep(3);\n            Long masterTemplateId = indexTemplateService.getMasterTemplatePhyIdByLogicTemplateId(\n                    logicTemplateCreatePipelineEvent.getLogicTemplateId());\n            if (masterTemplateId == null) {\n                LOGGER.error(\n                        \"class=LogicTemplateCreatePipelineListener||method=onApplicationEvent||{} get templatePhy is null\",\n                        logicTemplateCreatePipelineEvent.getLogicTemplateId());\n                return;\n            }\n            final Result<Void> result = pipelineManager.createPipeline(\n                    masterTemplateId.intValue());\n            if (result.failed()) {\n                LOGGER.warn(\n                        \"class=LogicTemplateCreatePipelineListener||method=onApplicationEvent||logicTemplateI={}||msg={}\",\n                        logicTemplateCreatePipelineEvent.getLogicTemplateId()\n                \n                );\n            }\n            \n        } catch (Exception e) {\n                LOGGER.error(\n                \"class=LogicTemplateCreatePipelineListener||method=onApplicationEvent\",\n                e);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/ReBuildTomorrowIndexListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.precreate.PreCreateManager;\nimport com.didichuxing.datachannel.arius.admin.common.event.index.ReBuildTomorrowIndexEvent;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class ReBuildTomorrowIndexListener implements ApplicationListener<ReBuildTomorrowIndexEvent> {\n\tprivate static final ILog             LOGGER = LogFactory.getLog(ClusterLogicChangeListener.class);\n\t@Autowired\n\tprivate              PreCreateManager templatePreCreateManager;\n\t\n\t/**\n\t * @param reBuildTomorrowIndexEvent\n\t */\n\t@Override\n\tpublic void onApplicationEvent(ReBuildTomorrowIndexEvent reBuildTomorrowIndexEvent) {\n\t\ttry {\n\t\t\t //保证数据已经刷到数据库，如果立即执行，会存在获取不到数据库中数据的状态，所以等待5000millis\n\t\t\tThread.sleep(5000);\n\t\t\tboolean tomorrowIndex = templatePreCreateManager.reBuildTomorrowIndex(reBuildTomorrowIndexEvent.getLogicId(), 3);\n\t\t\tif (Boolean.TRUE.equals(tomorrowIndex)){\n\t\t\t\tLOGGER.info(\n\t\t\t\t\t\"class=ReBuildTomorrowIndexListener||method=onApplicationEvent||logicId={}||error=success rebuild\",\n\t\t\t\t\treBuildTomorrowIndexEvent.getLogicId());\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tLOGGER.error(\n\t\t\t\t\t\"class=ReBuildTomorrowIndexListener||method=onApplicationEvent||logicId={}\",\n\t\t\t\t\treBuildTomorrowIndexEvent.getLogicId(),e);\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/RefreshCatIndexListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.event.index.RefreshCatIndexInfoEvent;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Component;\n\n/**\n * 此事件主要用于平台操作之后， arius_cat_index_info进行实时的异步写入， 从而保证平台操作是可以近实时看到，\n * 目前只包含了_forcemerge操作之后对shard和segment的更新策略\n *\n * @author shizeying\n * @date 2022/07/30\n */\n@Component\npublic class RefreshCatIndexListener implements ApplicationListener<RefreshCatIndexInfoEvent> {\n\tprivate static final ILog LOGGER = LogFactory.getLog(RefreshCatIndexListener.class);\n\t\n\t@Autowired\n\tprivate ESIndexCatService esIndexCatService;\n\t\n\t/**\n\t * @param refreshCatIndexInfoEvent\n\t */\n\t@Override\n\tpublic void onApplicationEvent(RefreshCatIndexInfoEvent refreshCatIndexInfoEvent) {\n\t\tMap<String, Set<String>> clusterPhy2IndexSetMap = refreshCatIndexInfoEvent.getClusterIndexTupleList().stream()\n\t\t\t\t.distinct()\n\t\t\t\t.collect(Collectors.groupingBy(TupleTwo::v1,\n\t\t\t\t\t\tCollectors.mapping(TupleTwo::v2, Collectors.toSet())\n\t\t\t\t));\n\t\t\n\t\tfor (Entry<String, Set<String>> clusterPhy2IndexEntry : clusterPhy2IndexSetMap.entrySet()) {\n\t\t\tString clusterPhy = clusterPhy2IndexEntry.getKey();\n\t\t\tSet<String> indexList = clusterPhy2IndexEntry.getValue();\n\t\t\t\n\t\t\tResult<List<IndexCatCellDTO>> result = esIndexCatService.syncGetSegmentsIndexList(clusterPhy, indexList);\n\t\t\tif (result.failed()) {\n\t\t\t\tLOGGER.warn(\"class={}||method=onApplicationEvent||cluster={}||msg={}\", getClass().getSimpleName(),\n\t\t\t\t\t\tclusterPhy, result.getMessage());\n\t\t\t}\n\t\t\tList<IndexCatCellDTO> indexCatCellList = result.getData();\n\t\t\tif (CollectionUtils.isEmpty(indexCatCellList)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t\n\t\t\ttry {\n\t\t\t\tesIndexCatService.syncUpsertCatIndex(indexCatCellList, 3);\n\t\t\t} catch (Exception e) {\n\t\t\t\tLOGGER.error(\"class={}||method=onApplicationEvent||cluster={}\", getClass().getSimpleName(), clusterPhy,\n\t\t\t\t\t\te);\n\t\t\t}\n\t\t\t\n\t\t}\n\t\t\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/RegionEditEventListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant;\nimport com.didichuxing.datachannel.arius.admin.common.event.region.RegionEditEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.Data;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Component;\n\nimport java.util.*;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.COMMA;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.HISTORY_TEMPLATE_PHYSIC_INDICES_ALLOCATION_IS_EFFECTIVE_DEFAULT_VALUE;\n\n/**\n * @author didi\n * @date 2022-05-23 2:46 下午\n */\n@Component\npublic class RegionEditEventListener implements ApplicationListener<RegionEditEvent> {\n\n    private static final ILog       LOGGER                           = LogFactory.getLog(RegionEditEventListener.class);\n\n    @Autowired\n    private ClusterRegionService    clusterRegionService;\n\n    @Autowired\n    private ClusterRoleHostService  clusterRoleHostService;\n\n    @Autowired\n    private IndexTemplatePhyService indexTemplatePhyService;\n\n    @Autowired\n    private AriusConfigInfoService  ariusConfigInfoService;\n\n    @Autowired\n    private ESTemplateService       esTemplateService;\n\n    @Autowired\n    private ESIndexService          esIndexService;\n\n    public static final String      TEMPLATE_INDEX_INCLUDE_NODE_NAME = \"index.routing.allocation.include._name\";\n\n    public static final String      NOT_BIND_LOGIC_CLUSTER_ID        = \"-1\";\n\n    public static final int         RETRY_COUNT                      = 2;\n\n    @Override\n    public void onApplicationEvent(RegionEditEvent regionEditEvent) {\n        if (CollectionUtils.isEmpty(regionEditEvent.getRegionIdList())) {\n            LOGGER.warn(\"class=RegionEditEventListener||method=onApplicationEvent,warnMsg=region is null\");\n            return;\n        }\n\n        /**\n         * key是集群名，value是TemplateWithNodeNames\n         */\n        Map<String, List<TemplateWithNodeNames>> cluster2TemplateWithNodeNames = new HashMap<String, List<TemplateWithNodeNames>>(\n            16);\n        try {\n            regionEditEvent.getRegionIdList().forEach(regionId -> {\n                ClusterRegion clusterRegion = clusterRegionService.getRegionById(regionId);\n                Set<String> nodeNames = new HashSet<>();\n                Result<List<ClusterRoleHost>> result = clusterRoleHostService.listByRegionId(Math.toIntExact(regionId));\n                if (result.failed()) {\n                    LOGGER.error(\"class=RegionEditEventListener||method=onApplicationEvent,warnMsg={}\",\n                        result.getMessage());\n                    return;\n                }\n                result.getData().stream().forEach(clusterRoleHost -> nodeNames.add(clusterRoleHost.getNodeSet()));\n                buildCluster2TemplateWithNodeNamesSetMap(cluster2TemplateWithNodeNames, clusterRegion, nodeNames);\n            });\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=RegionEditEventListener||method=onApplicationEvent,warnMsg=build cluster template map error,\",\n                e);\n            return;\n        }\n\n        cluster2TemplateWithNodeNames.entrySet().forEach(entry -> {\n            for (TemplateWithNodeNames templateWithNodeNames : entry.getValue()) {\n                try {\n                    if (templateWithNodeNames.getNodeNames().isEmpty()) {\n                        LOGGER.warn(\"class=RegionEditEventListener||method=onApplicationEvent,template={}, errMsg={}\",\n                            templateWithNodeNames.getTemplateName(), \"has no node names\");\n                        continue;\n                    }\n                    updateTemplateAllocationSetting(entry.getKey(), templateWithNodeNames.getTemplateName(),\n                        templateWithNodeNames.getNodeNames());\n                    updateIndicesAllocationSetting(entry.getKey(), templateWithNodeNames.getTemplateName(),\n                        templateWithNodeNames.getNodeNames());\n                } catch (Exception e) {\n                    LOGGER.error(\"class=RegionEditEventListener||method=onApplicationEvent,template={}, errMsg={}\",\n                        templateWithNodeNames.getTemplateName(), e.getMessage());\n                }\n            }\n\n        });\n\n    }\n\n    /**\n     * 构建集群->模板以及对应的节点名称\n     * @param cluster2TemplateWithNodeNames map\n     * @param clusterRegion region\n     * @param nodeNames 节点名称\n     */\n    private void buildCluster2TemplateWithNodeNamesSetMap(Map<String, List<TemplateWithNodeNames>> cluster2TemplateWithNodeNames,\n                                                          ClusterRegion clusterRegion, Set<String> nodeNames) {\n        Result<List<IndexTemplatePhy>> templatePhyListResult = indexTemplatePhyService\n            .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n        if (templatePhyListResult.failed()) {\n            LOGGER.error(\n                \"class=RegionEditEventListener||method=buildCluster2TemplateWithNodeNamesSetMap||region={}||err={}\",\n                clusterRegion.getId(), \"update indices setting failed\");\n            return;\n        }\n\n        List<TemplateWithNodeNames> templateWithNodeNamesList = cluster2TemplateWithNodeNames\n            .get(clusterRegion.getPhyClusterName());\n        if (null == templateWithNodeNamesList) {\n            templateWithNodeNamesList = new ArrayList<>();\n            cluster2TemplateWithNodeNames.put(clusterRegion.getPhyClusterName(), templateWithNodeNamesList);\n        }\n\n        for (IndexTemplatePhy indexTemplatePhy : templatePhyListResult.getData()) {\n            TemplateWithNodeNames templateWithNodeNames = new TemplateWithNodeNames();\n            templateWithNodeNames.setNodeNames(nodeNames);\n            templateWithNodeNames.setTemplateName(indexTemplatePhy.getName());\n            templateWithNodeNamesList.add(templateWithNodeNames);\n        }\n    }\n\n    /**\n     * region改动后更新索引的setting\n     * @param cluster 集群名\n     * @param templateName 模板名\n     * @param nodeNames 节点名\n     * @throws ESOperateException\n     */\n    private void updateIndicesAllocationSetting(String cluster, String templateName,\n                                                Set<String> nodeNames) throws ESOperateException {\n        if (ariusConfigInfoService.booleanSetting(AriusConfigConstant.ARIUS_TEMPLATE_GROUP,\n            AriusConfigConstant.HISTORY_TEMPLATE_PHYSIC_INDICES_ALLOCATION_IS_EFFECTIVE, HISTORY_TEMPLATE_PHYSIC_INDICES_ALLOCATION_IS_EFFECTIVE_DEFAULT_VALUE)) {\n            boolean response = esIndexService.syncPutIndexSetting(cluster,\n                Collections.singletonList(templateName + \"*\"), TEMPLATE_INDEX_INCLUDE_NODE_NAME,\n                String.join(COMMA, nodeNames), \"\", RETRY_COUNT);\n            if (!response) {\n                LOGGER.error(\"class=RegionEditEventListener||method=onApplicationEvent,template={}, errMsg={}\",\n                    templateName, \"update indices setting failed\");\n            }\n        }\n    }\n\n    /**\n     * 更新模板分配setting\n     * @param cluster 集群名\n     * @param templateName 模板名\n     * @param nodeNames\n     * @throws ESOperateException\n     */\n    private void updateTemplateAllocationSetting(String cluster, String templateName,\n                                                 Set<String> nodeNames) throws ESOperateException {\n        Map<String, String> setting = new HashMap<>(16);\n        setting.put(TEMPLATE_INDEX_INCLUDE_NODE_NAME, String.join(COMMA, nodeNames));\n        boolean response = esTemplateService.syncUpsertSetting(cluster, templateName, setting, RETRY_COUNT);\n        if (!response) {\n            LOGGER.error(\"class=RegionEditEventListener||method=onApplicationEvent,template={}, errMsg={}\",\n                templateName, \"update template setting failed\");\n        }\n    }\n\n    @Data\n    public class TemplateWithNodeNames {\n        private String      templateName;\n        private Set<String> nodeNames;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/TemplateEventClearIndexListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.didichuxing.datachannel.arius.admin.biz.indices.IndicesManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.event.index.IndexDeleteEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.EventException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * 模板事件:删除模板之后，发布事件删除关联的列表\n *\n * @author shizeying\n * @date 2022/07/18\n */\n@Component\npublic class TemplateEventClearIndexListener extends ApplicationRetryListener<IndexDeleteEvent> {\n\tprivate static final ILog           LOGGER = LogFactory.getLog(TemplateEventClearIndexListener.class);\n\n\t@Autowired\n\tprivate              IndicesManager indicesManager;\n\n\t@Override\n\tpublic void onApplicationRetryEvent(@NotNull IndexDeleteEvent event) throws EventException {\n\t\tfinal Map<String, List<String>> clusterPhy2IndexListMap = ConvertUtil.list2MapOfList(event.getCatCellList(),\n\t\t\t\tIndexCatCellDTO::getCluster, IndexCatCellDTO::getIndex);\n\n\t\tfor (Entry<String, List<String>> clusterPhy2IndexList : clusterPhy2IndexListMap.entrySet()) {\n\t\t\tdeleteIndexByCLusterPhy(clusterPhy2IndexList.getKey(),clusterPhy2IndexList.getValue(),event.getProjectId(), event.getOperator());\n\t\t}\n\t}\n\n\tprivate void deleteIndexByCLusterPhy(String clusterPhy, List<String> indexNameList, Integer projectId, String operator) throws EventException{\n\t\tResult<Void> result = indicesManager.deleteIndexByCLusterPhy(clusterPhy, indexNameList, projectId, operator);\n\t\tif(null == result || result.failed()){\n\t\t\tLOGGER.error(\n\t\t\t\t\t\"method=deleteIndexByCLusterPhy||projectId={}||index={}||ErrorMsg={}\",\n\t\t\t\t\tclusterPhy, indexNameList, \"deleteIndexByCLusterPhy error!\");\n\t\t\tthrow new EventException(\"deleteIndexByCLusterPhy error!\");\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/TemplateEventPipelineListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.pipeline.PipelineManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.LogicTemplateModifyEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.PhysicalTemplateAddEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.PhysicalTemplateDeleteEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.PhysicalTemplateModifyEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.TemplateEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Component;\n\n/**\n * 处理模板pipeline\n *\n *\n * @author d06679\n * @date 2019-09-03\n */\n@Component\npublic class TemplateEventPipelineListener implements ApplicationListener<TemplateEvent> {\n\n    private static final ILog LOGGER = LogFactory.getLog(TemplateEventPipelineListener.class);\n\n    @Autowired\n    private PipelineManager   templatePipelineManager;\n\n    /**\n     * Handle an application event.\n     *\n     * @param event the event to respond to\n     */\n    @Override\n    public void onApplicationEvent(TemplateEvent event) {\n        try {\n            if (event instanceof PhysicalTemplateAddEvent) {\n                handlePhysicalTemplateAddEvent((PhysicalTemplateAddEvent) event);\n            } else if (event instanceof PhysicalTemplateDeleteEvent) {\n                handlePhysicalTemplateDeleteEvent((PhysicalTemplateDeleteEvent) event);\n            } else if (event instanceof LogicTemplateModifyEvent) {\n                handleLogicTemplateModifyEvent((LogicTemplateModifyEvent) event);\n            } else if (event instanceof PhysicalTemplateModifyEvent) {\n                handlePhysicalTemplateModifyEvent((PhysicalTemplateModifyEvent) event);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=TemplateEventPipelineProcessor||method=onApplicationEvent||errMsg={}\", e.getMessage(),\n                e);\n        }\n    }\n\n    /****************************************************** private methods ******************************************************/\n    private void handlePhysicalTemplateModifyEvent(PhysicalTemplateModifyEvent event) throws ESOperateException {\n        PhysicalTemplateModifyEvent e = event;\n        LOGGER.info(\n            \"class=TemplateEventPipelineListener||method=onApplicationEvent||msg=PhysicalTemplateModifyEvent||templateName={}\",\n            e.getOldTemplate().getName());\n        if (templatePipelineManager.editFromTemplatePhysical(e.getOldTemplate(), e.getNewTemplate(),\n            e.getLogicWithPhysical())) {\n            LOGGER.info(\n                \"class=TemplateEventPipelineListener||method=onApplicationEvent||msg=PhysicalTemplateModifyEvent||templateName={}||msg=succ\",\n                e.getOldTemplate().getName());\n        } else {\n            LOGGER.warn(\n                \"class=TemplateEventPipelineListener||method=onApplicationEvent||msg=PhysicalTemplateModifyEvent||templateName={}||msg=fail\",\n                e.getOldTemplate().getName());\n        }\n    }\n\n    private void handleLogicTemplateModifyEvent(LogicTemplateModifyEvent event) {\n        LogicTemplateModifyEvent e = event;\n        final Result<Void> result = templatePipelineManager.editFromTemplateLogic(e.getOldTemplate(),\n            e.getNewTemplate());\n        if (result.success()) {\n            LOGGER.info(\n                \"class=TemplateEventPipelineListener||method=onApplicationEvent||msg=LogicTemplateModifyEvent||templateName={}||msg=succ\",\n                e.getOldTemplate().getName());\n        } else {\n            LOGGER.warn(\n                \"class=TemplateEventPipelineListener||method=onApplicationEvent||msg=LogicTemplateModifyEvent||templateName={}||msg=fail\",\n                e.getOldTemplate().getName());\n        }\n    }\n\n    private void handlePhysicalTemplateDeleteEvent(PhysicalTemplateDeleteEvent event) throws ESOperateException {\n        PhysicalTemplateDeleteEvent e = event;\n        Result<Void> result = templatePipelineManager.deletePipeline(e.getDelTemplate().getId().intValue());\n        if (result.success()) {\n            LOGGER.info(\n                \"class=TemplateEventPipelineListener||method=onApplicationEvent||msg=PhysicalTemplateDeleteEvent||templateName={}||msg=succ\",\n                e.getDelTemplate().getName());\n        } else {\n            LOGGER.warn(\n                \"class=TemplateEventPipelineListener||method=onApplicationEvent||msg=PhysicalTemplateDeleteEvent||templateName={}||msg={}\",\n                e.getDelTemplate().getName(),result.getMessage());\n        }\n    }\n\n    private void handlePhysicalTemplateAddEvent(PhysicalTemplateAddEvent event) throws ESOperateException {\n        PhysicalTemplateAddEvent e = event;\n        if (templatePipelineManager.createPipeline(e.getNewTemplate(), e.getLogicWithPhysical())) {\n            LOGGER.info(\n                \"class=TemplateEventPipelineListener||method=onApplicationEvent||msg=PhysicalTemplateAddEvent||templateName={}||msg=succ\",\n                e.getNewTemplate().getName());\n        } else {\n            LOGGER.warn(\n                \"class=TemplateEventPipelineListener||method=onApplicationEvent||msg=PhysicalTemplateAddEvent||templateName={}||msg=fail\",\n                e.getNewTemplate().getName());\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/TemplatePhyMetaChangedListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.physical.metadata.PhysicalMetaDataModifyEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.physical.metadata.PhysicalTemplateAliasModifyEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.physical.metadata.PhysicalTemplatePropertiesTypesModifyEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.physical.metadata.PhysicalTemplateSettingsModifyEvent;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class TemplatePhyMetaChangedListener implements ApplicationListener<PhysicalMetaDataModifyEvent> {\n\n    private static final ILog LOGGER = LogFactory.getLog(TemplatePhyMetaChangedListener.class);\n\n    @Override\n    public void onApplicationEvent(PhysicalMetaDataModifyEvent modifyEvent) {\n        if (modifyEvent instanceof PhysicalTemplateAliasModifyEvent) {\n            PhysicalTemplateAliasModifyEvent aliasModifyEvent = (PhysicalTemplateAliasModifyEvent) modifyEvent;\n            LOGGER\n                .info(\"class=PhysicalTemplateMetaChangedListener||method=onApplicationEvent||msg=templateAliasesChanged\"\n                      + \"||cluster={}||templateName={}||beforeUpdateAliases={}||afterUpdateAliases={}\",\n                    aliasModifyEvent.getCluster(), aliasModifyEvent.getTemplateName(),\n                    JSON.toJSONString(aliasModifyEvent.getBeforeUpdateAlias()),\n                    JSON.toJSONString(aliasModifyEvent.getAfterUpdateAlias()));\n\n        } else if (modifyEvent instanceof PhysicalTemplatePropertiesTypesModifyEvent) {\n            PhysicalTemplatePropertiesTypesModifyEvent typesModifyModifyEvent = (PhysicalTemplatePropertiesTypesModifyEvent) modifyEvent;\n\n            LOGGER.info(\"class=PhysicalTemplateMetaChangedListener||method=onApplicationEvent||msg=templateTypesChanged\"\n                        + \"||cluster={}||templateName={}||beforeUpdateTypes={}||afterUpdateTypes={}\",\n                typesModifyModifyEvent.getCluster(), typesModifyModifyEvent.getTemplateName(),\n                JSON.toJSONString(typesModifyModifyEvent.getBeforeUpdateTypes()),\n                JSON.toJSONString(typesModifyModifyEvent.getAfterUpdateTypes()));\n        } else if (modifyEvent instanceof PhysicalTemplateSettingsModifyEvent) {\n            PhysicalTemplateSettingsModifyEvent settingsModifyEvent = (PhysicalTemplateSettingsModifyEvent) modifyEvent;\n            LOGGER.info(\n                \"class=PhysicalTemplateMetaChangedListener||method=onApplicationEvent||msg=templateSettingsChanged\"\n                        + \"||cluster={}||templateName={}||beforeChangedSettings={}||afterChangedSettings={}\",\n                settingsModifyEvent.getCluster(), settingsModifyEvent.getTemplateName(),\n                JSON.toJSONString(settingsModifyEvent.getBeforeUpdateSettings()),\n                JSON.toJSONString(settingsModifyEvent.getAfterUpdateSettings()));\n        }\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/listener/TemplateProjectIdChangedListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.listener;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.LogicTemplateModifyEvent;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class TemplateProjectIdChangedListener implements ApplicationListener<LogicTemplateModifyEvent> {\n    private static final ILog               LOGGER = LogFactory.getLog(TemplateProjectIdChangedListener.class);\n\n    @Autowired\n    private ProjectLogicTemplateAuthService projectLogicTemplateAuthService;\n\n    @Override\n    public void onApplicationEvent(LogicTemplateModifyEvent logicTemplateEvent) {\n        if (null == logicTemplateEvent.getOldTemplate()) {\n            return;\n        }\n        if (null == logicTemplateEvent.getNewTemplate()) {\n            return;\n        }\n\n        //在模板的projectId发生变更的时候，处理权限问题\n        handleTemplateProjectId(logicTemplateEvent.getOldTemplate(), logicTemplateEvent.getNewTemplate());\n    }\n\n    /**************************************** private method ****************************************************/\n    private void handleTemplateProjectId(IndexTemplate oldIndexTemplate, IndexTemplate newIndexTemplate) {\n        Integer logicTemplateId = oldIndexTemplate.getId();\n\n        LOGGER.debug(\n                \"class=LogicTemplateModifyEventListener||method=handleTemplateProjectId||oldIndexTemplate={}||newIndexTemplate={}\",\n                JSON.toJSONString(oldIndexTemplate), JSON.toJSONString(newIndexTemplate));\n\n        if (null == newIndexTemplate) {\n            return;\n        }\n        if (newIndexTemplate.getProjectId().intValue() == oldIndexTemplate.getProjectId().intValue()) {\n            return;\n        }\n\n        //如果模板的projectid发生变更了，代表模板的管理权限发生变更，但是原projectid还要拥有模板的读写权限\n        //给原projectid赋予索引的读写权限\n        Result<Void> result = projectLogicTemplateAuthService.ensureSetLogicTemplateAuth(\n            oldIndexTemplate.getProjectId(), logicTemplateId, ProjectTemplateAuthEnum.RW,\n             AriusUser.SYSTEM.getDesc());\n\n        LOGGER.debug(\"class=LogicTemplateModifyEventListener||method=handleTemplateProjectId||result={}\", result.success());\n\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/ClusterPhyMetricsManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.ESClusterTaskDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyTypeMetricsEnum;\n\n/**\n * @author Created by linyunan on 2021-07-30\n *\n *  * 物理集群指标看板业务类\n *  * 1. 查询集群维度指标数据\n *  * 2. 查询集群节点维度指标数据\n *  * 3. 查询集群索引维度指标数据\n */\npublic interface ClusterPhyMetricsManager {\n\n    /**\n     * 获取一级指标类型列表 key:type value:code\n     * @param type 类型\n     * @see ClusterPhyTypeMetricsEnum\n     * @return {@code List<String>}\n     */\n    List<String> getMetricsCode2TypeMap(String type);\n\n    /**\n     * 获取指定类型的指标\n     * @param userName 账号\n     * @param projectId projectId\n     * @param param 物理集群指标\n     * @param metricsTypeEnum 指标处理器类型\n     * @return result\n     */\n    <T> Result<T> getClusterMetricsByMetricsType(MetricsClusterPhyDTO param, Integer projectId, String userName,\n                                                 ClusterPhyTypeMetricsEnum metricsTypeEnum);\n\n    /**\n     * 获取物理集群多个节点的指标信息\n     * @param param 物理集群指标\n     * @param projectId projectId\n     * @param userName 账号\n     * @param metricsTypeEnum 指标处理器类型\n     * @return result\n     */\n    Result<List<VariousLineChartMetricsVO>> getMultiClusterMetrics(MultiMetricsClusterPhyNodeDTO param,\n                                                                   Integer projectId, String userName,\n                                                                   ClusterPhyTypeMetricsEnum metricsTypeEnum);\n\n\n    /**\n     * 获取物理集群多个索引的指标信息\n     * @param param 物理集群索引指标\n     * @param projectId projectId\n     * @param userName 账号\n     * @param metricsTypeEnum 指标处理器类型\n     * @return result\n     */\n    Result<List<VariousLineChartMetricsVO>> getMultiClusterIndicesMetrics(MultiMetricsClusterPhyIndicesDTO param,\n                                                                          Integer projectId, String userName,\n                                                                          ClusterPhyTypeMetricsEnum metricsTypeEnum);\n\n    /**\n     * 获取物理集群多个模版的指标信息\n     * @param param 物理集群模版指标\n     * @param projectId projectId\n     * @param userName 账号\n     * @param metricsTypeEnum 指标处理器类型\n     * @return result\n     */\n    Result<List<VariousLineChartMetricsVO>> getMultiClusterTemplatesMetrics(MultiMetricsClusterPhyTemplateDTO param,\n                                                                            Integer projectId, String userName,\n                                                                            ClusterPhyTypeMetricsEnum metricsTypeEnum);\n\n    /**\n     * 获取用户配置指标\n     *\n     @return {@code List<String>}\n      * @param param 入参\n     * @param userName 用户名\n     * @param projectId\n     */\n    List<String> listConfigMetricsByCondition(UserConfigInfoDTO param, String userName, Integer projectId);\n\n    /**\n     * 更新账号下已配置的指标类型\n     @return {@code Result<Integer>}\n      * @param param 入参\n     * @param userName 用户名\n     * @param projectId\n     */\n    Result<Integer> updateConfigMetricsByCondition(UserConfigInfoDTO param, String userName, Integer projectId);\n\n    /**\n     * 获取物理集群中的索引列表\n     @param clusterPhyName 集群phy名称\n     @param node 节点\n     @param startTime 开始时间\n     @param endTime 结束时间\n     @param projectId 应用程序id\n     @return {@code Result<List<ESClusterTaskDetailVO>>}\n     */\n    Result<List<ESClusterTaskDetailVO>> getClusterPhyTaskDetail(String clusterPhyName, String node, String startTime,\n                                                                String endTime, Integer projectId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/DashboardMetricsManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardListDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardTopNDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.config.AriusConfigInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.list.MetricListVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.dashboard.ClusterPhyHealthMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 3/14/22\n *\n * 平台dashboard监控大盘\n */\npublic interface DashboardMetricsManager {\n\n    /**\n     * 获取dashboard大盘健康状态信息\n     * @param projectId  项目\n     * @return       ClusterPhyHealthMetricsVO\n     */\n    Result<ClusterPhyHealthMetricsVO> getClusterHealthInfo(Integer projectId);\n\n    /**\n     * 获取dashboard大盘TopN指标信息\n     * @param param MetricsDashboardTopNDTO\n     * @param projectId 项目\n     * @return      批量指标信息\n     */\n    Result<List<VariousLineChartMetricsVO>> getTopClusterMetricsInfo(MetricsDashboardTopNDTO param, Integer projectId);\n\n    Result<List<VariousLineChartMetricsVO>> getTopNodeMetricsInfo(MetricsDashboardTopNDTO param, Integer projectId);\n\n    Result<List<VariousLineChartMetricsVO>> getTopTemplateMetricsInfo(MetricsDashboardTopNDTO param, Integer projectId);\n\n    Result<List<VariousLineChartMetricsVO>> getTopIndexMetricsInfo(MetricsDashboardTopNDTO param, Integer projectId);\n\n    Result<List<VariousLineChartMetricsVO>> getTopClusterThreadPoolQueueMetricsInfo(MetricsDashboardTopNDTO param,\n                                                                                    Integer projectId);\n\n    /**\n     * 获取dashboard大盘list列表指标信息\n     * @param param  MetricsDashboardListDTO\n     * @param projectId  项目\n     * @return       批量指标信息\n     */\n    Result<List<MetricListVO>> getListClusterMetricsInfo(MetricsDashboardListDTO param, Integer projectId);\n\n    Result<List<MetricListVO>> getListNodeMetricsInfo(MetricsDashboardListDTO param, Integer projectId);\n\n    Result<List<MetricListVO>> getListTemplateMetricsInfo(MetricsDashboardListDTO param, Integer projectId);\n\n    Result<List<MetricListVO>> getListIndexMetricsInfo(MetricsDashboardListDTO param, Integer projectId);\n\n    /**\n     * 获取dashboard配置列表\n     * @return\n     */\n    List<AriusConfigInfoVO> dashboardThresholds();\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/GatewayMetricsManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.gateway.GatewayOverviewMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\n\n/**\n * Created by fitz on 2021-08-11\n *\n *  网关看板业务类\n */\npublic interface GatewayMetricsManager {\n\n    /**\n     * 获取gateway不同组的指标项\n     */\n    Result<List<String>> getGatewayMetricsEnums(String group);\n\n    /**\n     * 获取某个projectId下的dslMd5列表\n     */\n    Result<List<String>> getDslMd5List(Integer projectId, Long startTime, Long endTime);\n\n    /**\n     * 获取gateway全局维度指标信息\n     */\n    Result<List<GatewayOverviewMetricsVO>> getGatewayOverviewMetrics(GatewayOverviewDTO dto);\n\n    /**\n     * 获取gateway节点维度指标信息\n     */\n    Result<List<VariousLineChartMetricsVO>> getGatewayNodeMetrics(GatewayNodeDTO dto, Integer projectId);\n\n    /**\n     * 获取多节点gateway节点维度指标信息\n     */\n    Result<List<VariousLineChartMetricsVO>> getMultiGatewayNodesMetrics(MultiGatewayNodesDTO dto, Integer projectId);\n\n    /**\n     * 获取client节点维度指标信息\n     */\n    Result<List<VariousLineChartMetricsVO>> getClientNodeMetrics(ClientNodeDTO dto, Integer projectId);\n\n    /**\n     * 获取gateway索引维度指标信息\n     */\n    Result<List<VariousLineChartMetricsVO>> getGatewayIndexMetrics(GatewayIndexDTO dto, Integer projectId);\n\n    /**\n     * 获取gateway项目纬度指标信息\n     */\n    Result<List<VariousLineChartMetricsVO>> getGatewayAppMetrics(GatewayProjectDTO dto);\n\n    /**\n     * 获取gatewayDSL模版查询指标信息\n     */\n    Result<List<VariousLineChartMetricsVO>> getGatewayDslMetrics(GatewayDslDTO dto, Integer projectId);\n\n    /**\n     * 获取clientNode ip信息\n     */\n    Result<List<Tuple<String, String>>> getClientNodeIdList(String gatewayNode, Long startTime, Long endTime, Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/MetricsDictionaryManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricDictionaryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.dictionary.MetricsDictionaryVO;\nimport java.util.List;\n\n/**\n * @description: 指标字典manager\n * @author gyp\n * @date 2022/9/28 10:01\n * @version 1.0\n */\npublic interface MetricsDictionaryManager {\n    \n    /**\n     * 条件筛选字典数据\n     * @param param 筛选条件\n     * @return\n     */\n    Result<List<MetricsDictionaryVO>> listByCondition(MetricDictionaryDTO param);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/handle/BaseClusterMetricsHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.handle;\n\nimport com.didichuxing.datachannel.arius.admin.biz.component.MetricsValueConvertUtils;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.MetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.entity.user.User;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.*;\n\n/**\n * 抽象类集群指标处理\n *\n * @author\n * @date 2022/05/24\n */\npublic abstract class BaseClusterMetricsHandle implements BaseHandle {\n    private static final ILog      LOGGER      = LogFactory.getLog(BaseClusterMetricsHandle.class);\n\n    protected static final Integer MAX_TOP_NUM = 20;\n    protected static final Integer MIN_TOP_NUM = 5;\n\n    @Autowired\n    private ProjectService         projectService;\n\n    @Autowired\n    private UserService            userService;\n\n    /**\n     * 获取物理集群节点、节点任务、模板或者节点任务的指标信息\n     * @param userName 账号\n     * @param projectId projectId\n     * @param param 物理集群指标信息\n     * @return 对应视图板块下的时序指标信息列表\n     */\n    public Result<List<VariousLineChartMetricsVO>> getClusterPhyRelatedCurveMetrics(MetricsClusterPhyDTO param,\n                                                                                    Integer projectId,\n                                                                                    String userName) {\n        //1. verification\n        Result<Void> checkParamResult = checkParamForClusterPhyMetrics(param, projectId, userName);\n        if (checkParamResult.failed()) {\n            LOGGER.warn(\"class=ClusterBaseMetricsHandle||method=getClusterPhyMetrics||msg=check param fail\");\n            return Result.buildFrom(checkParamResult);\n        }\n\n        //2. initialization\n        init(param);\n\n        //3. get metrics from es engine\n        List<VariousLineChartMetrics> variousLineChartMetrics = getAggClusterPhyMetrics(param);\n\n        //4. uniform percentage unit\n        MetricsValueConvertUtils.convertClusterPhyMetricsPercent(variousLineChartMetrics);\n\n        //5. optimize query burr\n        MetricsValueConvertUtils.doOptimizeQueryBurrForNodeOrIndicesMetrics(variousLineChartMetrics);\n\n        return Result.buildSucc(ConvertUtil.list2List(variousLineChartMetrics, VariousLineChartMetricsVO.class));\n    }\n\n    /**\n     * 获取当前时刻集群的整体指标,其中包含非曲线数据，例如集群总览视图指标\n     * @param param 物理集群指标信息\n     * @param projectId projectId\n     * @param userName 账号类型\n     * @return 当前时刻下的集群整体指标\n     */\n    public Result<MetricsVO> getOtherClusterPhyRelatedMetricsVO(MetricsClusterPhyDTO param, Integer projectId,\n                                                                String userName) {\n        //1. verification\n        Result<Void> checkParamResult = checkParamForClusterPhyMetrics(param, projectId, userName);\n        if (checkParamResult.failed()) {\n            LOGGER.warn(\"class=ClusterBaseMetricsHandle||method=getMetricsVO||msg=check param fail\");\n            return Result.buildFrom(checkParamResult);\n        }\n\n        //2. initialization\n        init(param);\n        if (StringUtils.isNotBlank(param.getClusterLogicName())){\n            return Result.buildSucc(buildClusterLogicMetricsVO(param));\n        }\n        return Result.buildSucc(buildClusterPhyMetricsVO(param));\n    }\n\n    private Result<Void> checkParamForClusterPhyMetrics(MetricsClusterPhyDTO param, Integer projectId,\n                                                        String userName) {\n        Result<Void> checkCommonParam = checkCommonParam(param, projectId, userName);\n        if (checkCommonParam.failed()) {\n            return checkCommonParam;\n        }\n\n        Result<Void> checkSpecialParamResult = checkSpecialParam(param);\n        if (checkSpecialParamResult.failed()) {\n            return checkSpecialParamResult;\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkCommonParam(MetricsClusterPhyDTO param, Integer projectId, String userName) {\n        if (null == param) {\n            return Result.buildParamIllegal(\"param is empty\");\n        }\n        final User user = userService.getUserByUserName(userName);\n        if (Objects.isNull(user)) {\n            return Result.buildParamIllegal(\"user info is empty\");\n        }\n        return Result.buildSucc();\n    }\n\n    private void init(MetricsClusterPhyDTO param) {\n        initCommonParam(param);\n        initMetricsClusterPhy(param);\n    }\n\n    private void initCommonParam(MetricsClusterPhyDTO param) {\n        if (AriusObjUtils.isBlack(param.getClusterPhyName())) {\n            param.setClusterPhyName(ALL_CLUSTER);\n        }\n\n        if (0 == param.getEndTime() || null == param.getEndTime()) {\n            param.setEndTime(System.currentTimeMillis());\n        }\n\n        if (0 == param.getStartTime() || null == param.getStartTime()) {\n            param.setStartTime(param.getEndTime() - DEFAULT_TIME_INTERVAL);\n        }\n\n        //防止内存打爆, 触发熔断, 兜底方案, 结束时间近一周\n        long intervalTime = param.getEndTime() - param.getStartTime();\n        if (intervalTime > MAX_TIME_INTERVAL) {\n            param.setStartTime(param.getEndTime() - MAX_TIME_INTERVAL);\n        }\n\n        if (null != param.getTopNu()) {\n            if (param.getTopNu() <= 0) {\n                param.setTopNu(MIN_TOP_NUM);\n            }\n\n            if (param.getTopNu() > MAX_TOP_NUM) {\n                param.setTopNu(MAX_TOP_NUM);\n            }\n        }\n    }\n\n    /**\n     * 构建物理集群的整体指标\n     *\n     * @param param 物理集群指标\n     * @return 集群指标类型视图\n     */\n    protected MetricsVO buildClusterPhyMetricsVO(MetricsClusterPhyDTO param) {\n        return null;\n    }\n\n    /**\n     * 构建逻辑集群的整体指标\n     *\n     * @param param 物理集群指标\n     * @return 集群指标类型视图\n     */\n    protected MetricsVO buildClusterLogicMetricsVO(MetricsClusterPhyDTO param) {\n        return null;\n    }\n\n    /**\n     * 从ES引擎中获取对应的物理指标类型\n     *\n     * @param param 物理集群指标\n     * @return 对应指标下的时序信息列表\n     */\n    protected List<VariousLineChartMetrics> getAggClusterPhyMetrics(MetricsClusterPhyDTO param) {\n        return new ArrayList<>();\n    }\n\n    /**\n     * 不同视图间自有的校验规则\n     *\n     * @param param 物理集群指标\n     * @return 校验结果\n     */\n    protected abstract Result<Void> checkSpecialParam(MetricsClusterPhyDTO param);\n\n    /**\n     * 初始化物理指标信息DTO\n     *\n     * @param param 物理集群指标\n     */\n    protected abstract void initMetricsClusterPhy(MetricsClusterPhyDTO param);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/handle/ClusterLogicOverviewMetricsHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.handle;\n\nimport com.baomidou.mybatisplus.core.toolkit.CollectionUtils;\nimport com.didichuxing.datachannel.arius.admin.biz.component.MetricsValueConvertUtils;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.percentiles.BasePercentileMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.*;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.*;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.ESClusterPhyStatsService;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.fs.FSNode;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.fs.FSTotal;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.jvm.JvmMem;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.jvm.JvmNode;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport io.swagger.models.auth.In;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.math.BigDecimal;\nimport java.util.*;\nimport java.util.function.Consumer;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.BIG_SHARD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.LOGIC_CLUSTER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.PHY_CLUSTER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.*;\n\n/**\n * Created by linyunan on 2021-08-02\n */\n@Component\npublic class ClusterLogicOverviewMetricsHandle {\n\n    private static final ILog LOGGER                        = LogFactory\n        .getLog(ClusterLogicOverviewMetricsHandle.class);\n\n    @Autowired\n    private ESClusterPhyStatsService      esClusterPhyStatsService;\n\n    @Autowired\n    private ESClusterService              esClusterService;\n\n    @Autowired\n    private ESClusterNodeService          esClusterNodeService;\n\n    @Autowired\n    private ESShardService                esShardService;\n\n    @Autowired\n    private ClusterRoleHostService        clusterRoleHostService;\n\n    @Autowired\n    private ESTemplateService             esTemplateService;\n\n    @Autowired\n    private AriusConfigInfoService        ariusConfigInfoService;\n    @Autowired\n    private ESIndexCatService             esIndexCatService;\n\n    @Autowired\n    private IndexTemplatePhyService       indexTemplatePhyService;\n    @Autowired\n    private ESIndexService                esIndexService;\n\n    @Autowired\n    private ClusterLogicService           clusterLogicService;\n\n    @Autowired\n    private ClusterRegionService          clusterRegionService;\n\n    @Autowired\n    private IndexTemplateService          indexTemplateService;\n\n\n    private static final FutureUtil<Void> getMultipleMetricFutureUtil   = FutureUtil.init(\"getMultipleMetricFutureUtil\",\n        10, 10, 100);\n    private static final FutureUtil<Void> getClusterBasicInfoFutureUtil = FutureUtil\n        .init(\"getClusterBasicInfoFutureUtil\", 10, 10, 50);\n    private static final FutureUtil<Void> optimizeQueryBurrFutureUtil   = FutureUtil.init(\"optimizeQueryBurrFutureUtil\",\n        10, 10, 50);\n\n    /**\n     *         metricsTypes 物理集群二级指标类型\n     * @see    ClusterPhyClusterMetricsEnum\n     * @return ESClusterOverviewMetricsVO\n     */\n    public ESClusterOverviewMetricsVO buildClusterLogicOverviewMetrics(MetricsClusterPhyDTO metricsClusterPhyDTO) {\n\n        //1. building base objects\n        ESClusterOverviewMetricsVO esClusterOverviewMetricsVO = initESClusterPhyOverviewMetricsVO(metricsClusterPhyDTO);\n\n        //2. 从ES中获取指标, 同时获取多个\n        for (String metricsType : metricsClusterPhyDTO.getMetricsTypes()) {\n            getMultipleMetricFutureUtil.runnableTask(() -> aggClusterLogicOverviewMetrics(esClusterOverviewMetricsVO,\n                metricsType, metricsClusterPhyDTO.getAggType(), metricsClusterPhyDTO.getStartTime(),\n                metricsClusterPhyDTO.getEndTime(),metricsClusterPhyDTO.getItemNamesUnderClusterLogic(),\n                    metricsClusterPhyDTO.getClusterLogicName(),metricsClusterPhyDTO.getProjectId()));\n        }\n        getMultipleMetricFutureUtil.waitExecute();\n        //3.非超级项目进行大索引过滤\n        filterESClusterOverviewMetricsVOByProjectIdAndClusterLogicName(esClusterOverviewMetricsVO,\n                metricsClusterPhyDTO.getProjectId(), metricsClusterPhyDTO.getClusterLogicName());\n        //4. uniform percentage unit\n        MetricsValueConvertUtils.convertClusterOverviewMetricsPercent(esClusterOverviewMetricsVO);\n\n        //5. optimize query burr\n        optimizeQueryBurrForClusterOverviewMetrics(esClusterOverviewMetricsVO);\n        \n        return esClusterOverviewMetricsVO;\n    }\n\n    /******************************************private*******************************************************/\n\n    private void filterESClusterOverviewMetricsVOByProjectIdAndClusterLogicName(\n            ESClusterOverviewMetricsVO esClusterOverviewMetricsVO, Integer projectId, String clusterLogicName) {\n        if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId) && StringUtils.isNotBlank(clusterLogicName)) {\n            List<String> belongToProjectIdIndexList = esIndexCatService.syncGetIndexListByProjectId(projectId,\n                    clusterLogicName);\n            if (CollectionUtils.isEmpty(belongToProjectIdIndexList)) {\n                esClusterOverviewMetricsVO.setBigIndices(Collections.emptyList());\n                esClusterOverviewMetricsVO.setBigShards(Collections.emptyList());\n                return;\n            }\n            \n            //过滤出项目所属大索引, 大于10亿文档数的索引\n            List<BigIndexMetricsVO> filterProjectIdBigIndex = Optional.ofNullable(\n                            esClusterOverviewMetricsVO.getBigIndices()).orElse(Collections.emptyList()).stream()\n                    .filter(i -> belongToProjectIdIndexList.contains(i.getIndexName())).collect(Collectors.toList());\n            esClusterOverviewMetricsVO.setBigIndices(filterProjectIdBigIndex);\n            //过滤出项目所属大shard列表\n            List<BigShardMetricsVO> bigShardMetricsVOS = Optional.ofNullable(esClusterOverviewMetricsVO.getBigShards())\n                    .orElse(Collections.emptyList()).stream()\n                    .filter(i -> belongToProjectIdIndexList.contains(i.getIndex())).collect(Collectors.toList());\n            esClusterOverviewMetricsVO.setBigShards(bigShardMetricsVOS);\n        }\n    \n    }\n\n    /**\n     * optimize query burr , compare the corresponding values of the front and\n     * back slices of a single time slice to find the maximum value\n     * @param esClusterOverviewMetricsVO\n     */\n    private void optimizeQueryBurrForClusterOverviewMetrics(ESClusterOverviewMetricsVO esClusterOverviewMetricsVO) {\n        optimizeQueryBurrFutureUtil\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getCpuUsage()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getCpuLoad1M()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getCpuLoad5M()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getCpuLoad15M()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getDiskUsage()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getSearchLatency()))\n            .runnableTask(() -> MetricsValueConvertUtils\n                .doOptimizeForPercentiles(esClusterOverviewMetricsVO.getIndexingLatency()))\n            .runnableTask(() -> MetricsValueConvertUtils\n                .doOptimizeForRecvTransSize(esClusterOverviewMetricsVO.getRecvTransSize()))\n            .runnableTask(() -> MetricsValueConvertUtils\n                .doOptimizeForSendTransSize(esClusterOverviewMetricsVO.getSendTransSize()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForDiskInfo(esClusterOverviewMetricsVO.getDiskInfo()))\n            .runnableTask(() -> MetricsValueConvertUtils.doOptimizeForShardNu(esClusterOverviewMetricsVO.getShardNu()))\n            .runnableTask(() -> MetricsValueConvertUtils.doOptimizeForReadTps(esClusterOverviewMetricsVO.getReadTps()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForWriteTps(esClusterOverviewMetricsVO.getWriteTps()))\n            .waitExecute();\n    }\n\n    private ESClusterOverviewMetricsVO initESClusterPhyOverviewMetricsVO(MetricsClusterPhyDTO metricsClusterPhyDTO) {\n        ESClusterOverviewMetricsVO esClusterOverviewMetricsVO = new ESClusterOverviewMetricsVO();\n        ESClusterPhyBasicMetricsVO basicMetricsVO = new ESClusterPhyBasicMetricsVO();\n        esClusterOverviewMetricsVO.setClusterName(metricsClusterPhyDTO.getClusterPhyName());\n        esClusterOverviewMetricsVO.setPhysicCluster(PHY_CLUSTER);\n        esClusterOverviewMetricsVO.setDataCenter(EnvUtil.getDC().getCode());\n        esClusterOverviewMetricsVO.setBasic(basicMetricsVO);\n        esClusterOverviewMetricsVO.setCurrentTime(DateTimeUtil.formatTimestamp(System.currentTimeMillis()));\n        esClusterOverviewMetricsVO.setBigShardThreshold(ariusConfigInfoService.doubleSetting(AriusConfigConstant.ARIUS_COMMON_GROUP,\n                AriusConfigConstant.BIG_SHARD_THRESHOLD, BIG_SHARD));\n        return esClusterOverviewMetricsVO;\n    }\n\n    private void aggClusterLogicOverviewMetrics(ESClusterOverviewMetricsVO metrics, String metricsType, String aggType,\n                                                Long startTime, Long endTime, List<String> itemNamesUnderClusterLogic, String clusterLogic, Integer projectId) {\n        try {\n            switch (ClusterPhyClusterMetricsEnum.valueOfType(metricsType)) {\n                /*************************基本状态指标(状态类型)***************************/\n                case BASIC:\n                    getBasicMetrics(metrics,itemNamesUnderClusterLogic,clusterLogic,projectId);\n                    return;\n                case ELAPSEDTIME:\n                    getElapsedTimeMetrics(metrics);\n                    return;\n\n                /****************************业务指标(列表类型)*****************************/\n                case PENDING_TASKS:\n                    getPendingTasksMetrics(metrics);\n                    return;\n                case MOVING_SHARDS:\n                    getMovingShardsMetrics(metrics);\n                    return;\n                case UNASSIGN_SHARDS:\n                    getUnassignedShardsMetrics(metrics);\n                    return;\n                case INVALID_NODES:\n                    getInvalidNodesMetrics(metrics);\n                    return;\n                case BIG_INDICES:\n                    getBigIndicesMetrics(metrics);\n                    return;\n                case BIG_SHARDS:\n                    getBigShardsMetrics(metrics);\n                    return;\n\n                /********************************分位图类型*******************************/\n                case CPU_USAGE:\n                    aggPercentilesMetrics(metrics,LOGIC_CLUSTER, CPU_USAGE.getType(), aggType, startTime, endTime,\n                        b -> metrics.setCpuUsage(ConvertUtil.list2List(b, CpuUsageMetricsVO.class)));\n                    return;\n                case CPU_LOAD_1M:\n                    aggPercentilesMetrics(metrics,LOGIC_CLUSTER, CPU_LOAD_1M.getType(), aggType, startTime, endTime,\n                        b -> metrics.setCpuLoad1M(ConvertUtil.list2List(b, CpuLoadFor1MinMetricsVO.class)));\n                    return;\n                case CPU_LOAD_5M:\n                    aggPercentilesMetrics(metrics,LOGIC_CLUSTER, CPU_LOAD_5M.getType(), aggType, startTime, endTime,\n                        b -> metrics.setCpuLoad5M(ConvertUtil.list2List(b, CpuLoadFor5MinMetricsVO.class)));\n                    return;\n                case CPU_LOAD_15M:\n                    aggPercentilesMetrics(metrics,LOGIC_CLUSTER, CPU_LOAD_15M.getType(), aggType, startTime, endTime,\n                        b -> metrics.setCpuLoad15M(ConvertUtil.list2List(b, CpuLoadFor15MinMetricsVO.class)));\n                    return;\n                case DISK_USAGE:\n                    aggPercentilesMetrics(metrics,LOGIC_CLUSTER, DISK_USAGE.getType(), aggType, startTime, endTime,\n                        b -> metrics.setDiskUsage(ConvertUtil.list2List(b, DiskUsageMetricsVO.class)));\n                    return;\n                case SEARCH_LATENCY:\n                    aggPercentilesMetrics(metrics,LOGIC_CLUSTER, SEARCH_LATENCY.getType(), aggType, startTime, endTime,\n                        b -> metrics.setSearchLatency(ConvertUtil.list2List(b, SearchLatencyMetricsVO.class)));\n                    return;\n                case INDEXING_LATENCY:\n                    aggPercentilesMetrics(metrics,LOGIC_CLUSTER, INDEXING_LATENCY.getType(), aggType, startTime, endTime,\n                        b -> metrics.setIndexingLatency(ConvertUtil.list2List(b, IndexingLatencyMetricsVO.class)));\n                    return;\n\n                case TASK_COST:\n                    aggPercentilesMetrics(metrics,LOGIC_CLUSTER, TASK_COST.getType(), aggType, startTime, endTime,\n                        b -> metrics.setTaskCost(ConvertUtil.list2List(b, TaskCostMetricVO.class)));\n                    return;\n\n                /********************************普通指标(折线图)*******************************/\n                case DISK_INFO:\n                    aggDiskInfoMetrics(metrics,LOGIC_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case SHARD_NUM:\n                    aggShardNuMetrics(metrics,LOGIC_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case READ_QPS:\n                    aggReadTpsMetrics(metrics,LOGIC_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case WRITE_TPS:\n                    aggWriteTpsMetrics(metrics,LOGIC_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case RECV_TRANS_SIZE:\n                    aggRecvTransMetrics(metrics,LOGIC_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case SEND_TRANS_SIZE:\n                    aggSendTransMetrics(metrics,LOGIC_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case NODES_FOR_DISK_USAGE_GTE_75PERCENT:\n                    aggNodesForDiskUsageGte75PercentMetrics(metrics);\n                    return;\n                case TASK_NUM:\n                    aggTaskCount(metrics,LOGIC_CLUSTER, aggType, startTime, endTime);\n                    return;\n                default:\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=ClusterLogicOverviewMetricsHandle||method=aggClusterLogicOverviewMetrics||errMsg={}\",\n                e.getMessage());\n        }\n    }\n\n    private void getInvalidNodesMetrics(ESClusterOverviewMetricsVO metrics) {\n        List<String> nodeHostsFromES = esClusterNodeService.syncGetNodeHosts(metrics.getClusterName());\n        List<ClusterRoleHost> nodesByCluster = clusterRoleHostService.getNodesByCluster(metrics.getClusterName());\n        List<ClusterRoleHost> invalidNodeIps = Lists.newArrayList();\n        nodesByCluster.forEach(nodeFromDb -> {\n            if (!nodeHostsFromES.contains(nodeFromDb.getIp())) {\n                invalidNodeIps.add(nodeFromDb);\n            }\n        });\n\n        metrics.setInvalidNodes(invalidNodeIps);\n    }\n\n    private void getBigShardsMetrics(ESClusterOverviewMetricsVO metrics) throws ESOperateException {\n        List<ShardMetrics> shardMetrics = esShardService.syncGetBigShards(metrics.getClusterName());\n        metrics.setBigShards(ConvertUtil.list2List(shardMetrics, BigShardMetricsVO.class));\n    }\n\n    private void getBigIndicesMetrics(ESClusterOverviewMetricsVO metrics) throws ESOperateException {\n        List<BigIndexMetrics> bigIndexMetrics = esClusterNodeService.syncGetBigIndices(metrics.getClusterName());\n        metrics.setBigIndices(ConvertUtil.list2List(bigIndexMetrics, BigIndexMetricsVO.class));\n    }\n\n    private void getMovingShardsMetrics(ESClusterOverviewMetricsVO metrics) throws ESOperateException {\n        List<MovingShardMetrics> movingShardsMetrics = esShardService.syncGetMovingShards(metrics.getClusterName());\n        metrics.setMovingShards(ConvertUtil.list2List(movingShardsMetrics, MovingShardMetricsVO.class));\n    }\n\n    private void getUnassignedShardsMetrics(ESClusterOverviewMetricsVO metrics) throws ESOperateException {\n        List<UnAssignShardMetrics> unAssignShardMetrics = esShardService.syncGetUnAssignShards(metrics.getClusterName());\n        metrics.setUnAssignShards(ConvertUtil.list2List(unAssignShardMetrics, UnAssignShardMetricsVO.class));\n    }\n\n    private void getPendingTasksMetrics(ESClusterOverviewMetricsVO metrics) throws ESOperateException {\n        List<PendingTask> pendingTaskFromES = esClusterNodeService.syncGetPendingTask(metrics.getClusterName());\n        metrics.setPendingTasks(ConvertUtil.list2List(pendingTaskFromES, PendingTaskVO.class));\n    }\n\n    private void getElapsedTimeMetrics(ESClusterOverviewMetricsVO metrics) {\n        ESClusterPhyBasicMetricsVO basic = metrics.getBasic();\n        getClusterBasicInfoFutureUtil\n            .runnableTask(() -> buildBasicMetricsFromEsClusterNodeInfo(basic, metrics.getClusterName()))\n            .runnableTask(() -> buildBasicMetricsFromEsClusterMemInfo(basic, metrics.getClusterName())).waitExecute();\n    }\n\n    private void getBasicMetrics(ESClusterOverviewMetricsVO metrics,List<String> itemNamesUnderClusterLogic,String clusterLogic, Integer projectId) {\n        ESClusterPhyBasicMetricsVO basic = metrics.getBasic();\n        getClusterBasicInfoFutureUtil\n            .runnableTask(() -> buildBasicMetricsFromClusterStats(basic, metrics.getClusterName(),itemNamesUnderClusterLogic,clusterLogic,projectId))\n            .runnableTask(() -> buildBasicMetricsFromEsClusterTemplate(basic, clusterLogic,projectId))\n            .runnableTask(() -> buildBasicMetricsFromEsClusterNodeInfo(basic, metrics.getClusterName()))\n            .runnableTask(() -> buildBasicMetricsFromEsClusterMemInfo(basic, metrics.getClusterName())).waitExecute();\n    }\n\n    /**\n     * 设置集群总览视图中内存的基础信息，兼容2.3.3低版本的es集群\n     * @param basicVO 集群总览基础视图\n     * @param clusterName  物理集群名称\n     */\n    private void buildBasicMetricsFromEsClusterMemInfo(ESClusterPhyBasicMetricsVO basicVO, String clusterName) {\n        ClusterMemInfo clusterMemInfo = esClusterNodeService.synGetClusterMem(clusterName);\n        if (AriusObjUtils.isNull(clusterMemInfo)) {\n            LOGGER.warn(\n                \"class=ClusterLogicOverviewMetricsHandle||method=buildBasicMetricsFromEsClusterMemInfo||mem info is empty\");\n            return;\n        }\n\n        // 设置内存信息\n        basicVO.setMemTotal(clusterMemInfo.getMemTotal());\n        basicVO.setMemFree(clusterMemInfo.getMemFree());\n        basicVO.setMemUsed(clusterMemInfo.getMemUsed());\n        basicVO.setMemFreePercent(clusterMemInfo.getMemFreePercent());\n        basicVO.setMemUsedPercent(clusterMemInfo.getMemUsedPercent());\n    }\n\n    /**\n     * 构建集群基本指标信息\n     * @param basicVO\n     * @param clusterName\n     */\n    private void buildBasicMetricsFromClusterStats(ESClusterPhyBasicMetricsVO basicVO, String clusterName,\n                                                   List<String> itemNamesUnderClusterLogic,String clusterLogic, Integer projectId) {\n        List<ClusterNodeStats> nodeStats = esClusterNodeService.syncGetNodeStats(clusterName);\n        Map<String, Long> node2ShardNum = esClusterNodeService.syncGetNode2ShardNumMap(clusterName);\n        List<String> indies = esIndexCatService.syncGetIndexListByProjectId(projectId,clusterLogic);\n        List<CatIndexResult> catIndexResults = esIndexService.syncCatIndex(clusterName, 3);\n        ESClusterStatsResponse clusterStats = esClusterService.syncGetClusterStats(clusterName);\n\n        //shard数\n        long shardNum = itemNamesUnderClusterLogic.stream().mapToLong(node2ShardNum::get).filter(Objects::nonNull).sum();\n        long indicesStoreSize = catIndexResults.stream().filter(index->indies.contains(index.getIndex())).mapToLong(index->SizeUtil.getUnitSize(index.getStoreSize())).sum();\n        long docCount =  catIndexResults.stream().filter(index->indies.contains(index.getIndex())).mapToLong(index->Long.parseLong(index.getDocsCount())).sum();\n        //磁盘信息\n        long totalInBytes = nodeStats.stream().filter(nodeStat->itemNamesUnderClusterLogic.contains(nodeStat.getName())).mapToLong(this::getTotalInBytes).sum();\n        long availableInBytes = nodeStats.stream().filter(nodeStat->itemNamesUnderClusterLogic.contains(nodeStat.getName())).mapToLong(this::getAvailableInBytes).sum();\n        long freeInBytes = nodeStats.stream().filter(nodeStat->itemNamesUnderClusterLogic.contains(nodeStat.getName())).mapToLong(this::getFreeInBytes).sum();\n        //设置堆内存使用率信息\n        long heapUsedInBytes = nodeStats.stream().filter(nodeStat->itemNamesUnderClusterLogic.contains(nodeStat.getName())).mapToLong(this::getHeapUsedInBytes).sum();\n        long nonHeapUsedInBytes =  nodeStats.stream().filter(nodeStat->itemNamesUnderClusterLogic.contains(nodeStat.getName())).mapToLong(this::getNonHeapUsedInBytes).sum();\n\n        //设置状态\n        basicVO.setStatus(clusterStats.getStatus());\n        //设置基础信息\n        basicVO.setNumberNodes((long) itemNamesUnderClusterLogic.size());\n        basicVO.setTotalIndicesNu((long) indies.size());\n        basicVO.setShardNu((long) shardNum);\n        basicVO.setTotalDocNu(docCount);\n        basicVO.setIndicesStoreSize(indicesStoreSize);\n        basicVO.setUnassignedShardNum(clusterStats.getUnassignedShardNum());\n\n        //设置集群磁盘信息\n        basicVO.setStoreSize(availableInBytes);\n        basicVO.setTotalStoreSize(totalInBytes);\n        basicVO.setFreeStoreSize(freeInBytes);\n        //保留小数点后3位\n        BigDecimal storeSizeDec = new BigDecimal(availableInBytes);\n        BigDecimal totalSizeDec = new BigDecimal(totalInBytes);\n        basicVO.setStoreUsage(storeSizeDec.divide(totalSizeDec, 5, 1).doubleValue() * 100);\n        basicVO.setStoreFreeUsage((100 - basicVO.getStoreUsage()));\n\n        //设置堆内存使用率信息\n        long heapTotalSize = nonHeapUsedInBytes + heapUsedInBytes;\n        basicVO.setHeapMemFree(nonHeapUsedInBytes);\n        basicVO.setHeapMemTotal(heapTotalSize);\n        basicVO.setHeapMemUsed(heapUsedInBytes);\n        //保留小数点后3位\n        BigDecimal storeHeapMemSizeDec = new BigDecimal(heapUsedInBytes);\n        BigDecimal totalHeapMemSizeDec = new BigDecimal(heapTotalSize);\n        basicVO.setHeapUsage(storeHeapMemSizeDec.divide(totalHeapMemSizeDec, 5, 1).doubleValue() * 100);\n        basicVO.setHeapFreeUsage((100 - basicVO.getHeapUsage()));\n        //设置集群节点信息\n        basicVO.setNumberMasterNodes(clusterStats.getNumberMasterNodes());\n        basicVO.setNumberDataNodes((long) itemNamesUnderClusterLogic.size());\n        basicVO.setNumberClientNodes(clusterStats.getNumberClientNodes());\n        basicVO.setNumberIngestNodes(clusterStats.getNumberIngestNodes());\n        basicVO.setNumberCoordinatingOnlyNodes(clusterStats.getNumberCoordinatingOnly());\n    }\n\n    /**\n     * 设置集群有效、无效节点数\n     * @param basicVO\n     * @param clusterName\n     */\n    private void buildBasicMetricsFromEsClusterNodeInfo(ESClusterPhyBasicMetricsVO basicVO, String clusterName) {\n        List<String> esHost = esClusterNodeService.syncGetNodeHosts(clusterName);\n        long invalidNodeCount = 0;\n        long activeNodeCount = 0;\n        List<ClusterRoleHost> nodesByCluster = clusterRoleHostService.getNodesByCluster(clusterName);\n        Set<String> nodeIps = nodesByCluster.stream().map(ClusterRoleHost::getIp).collect(Collectors.toSet());\n        for (String ip : nodeIps) {\n            if (!esHost.contains(ip)) {\n                invalidNodeCount++;\n            } else {\n                activeNodeCount++;\n            }\n        }\n        basicVO.setActiveNodeNu(activeNodeCount);\n        basicVO.setInvalidNodeNu(invalidNodeCount);\n        basicVO.setTotalNodeNu(nodeIps.size());\n\n        BigDecimal activeNodeNu = new BigDecimal(activeNodeCount);\n        BigDecimal totalNodeNu = new BigDecimal(nodeIps.size());\n        basicVO.setActiveNodeNuPercent(activeNodeNu.divide(totalNodeNu, 3, 1).doubleValue() * 100);\n        basicVO.setInvalidNodeNuPercent(100 - basicVO.getActiveNodeNuPercent());\n    }\n\n    /**\n     * 设置集群真实模板数量\n     * @param basicVO\n     * @param clusterName\n     */\n    private void buildBasicMetricsFromEsClusterTemplate(ESClusterPhyBasicMetricsVO basicVO, String clusterName, Integer projectId) {\n\n        ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByNameAndProjectId(clusterName,projectId);\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogic.getId());\n        if (Objects.isNull(clusterRegion)){\n            basicVO.setTotalTemplateNu(0L);\n        }else {\n            basicVO.setTotalTemplateNu(Long.valueOf(indexTemplateService.listByRegionId(Math.toIntExact(clusterRegion.getId())).getData().size()));\n        }\n    }\n\n    /**\n     * 获取集群维度分位统计信息\n     */\n    private void aggPercentilesMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String clusterMetricsType, String aggType,\n                                       Long startTime, Long endTime, Consumer<List<BasePercentileMetrics>> function) {\n\n        List<BasePercentileMetrics> aggPercentilesMetrics = esClusterPhyStatsService\n            .getAggPercentilesMetrics(metrics.getClusterName(),clusterType, clusterMetricsType, aggType, startTime, endTime);\n\n        Collections.sort(aggPercentilesMetrics);\n\n        function.accept(aggPercentilesMetrics);\n    }\n\n    private void aggNodesForDiskUsageGte75PercentMetrics(ESClusterOverviewMetricsVO metrics) {\n        metrics.setNodesForDiskUsageGte75Percent(getNodeInfoForDiskUsageGte75Percent(metrics.getClusterName()));\n    }\n\n    private void aggDiskInfoMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<DiskInfoMetrics> diskInfoMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, DiskInfoMetrics.class);\n        List<DiskInfoMetricsVO> diskInfoMetricsVOS = ConvertUtil.list2List(diskInfoMetrics, DiskInfoMetricsVO.class);\n        Collections.sort(diskInfoMetricsVOS);\n        metrics.setDiskInfo(diskInfoMetricsVOS);\n    }\n\n    private void aggShardNuMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<ShardInfoMetrics> shardInfoMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, ShardInfoMetrics.class);\n\n        List<ShardInfoMetricsVO> shardInfoMetricsVOS = ConvertUtil.list2List(shardInfoMetrics,\n            ShardInfoMetricsVO.class);\n        Collections.sort(shardInfoMetricsVOS);\n        metrics.setShardNu(shardInfoMetricsVOS);\n    }\n\n    private void aggTaskCount(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<TaskCountMetrics> taskCountMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, TaskCountMetrics.class);\n\n        List<TaskCountMetricVO> taskCountMetricVOS = ConvertUtil.list2List(taskCountMetrics, TaskCountMetricVO.class);\n        Collections.sort(taskCountMetricVOS);\n        metrics.setTaskCount(taskCountMetricVOS);\n    }\n\n    private void aggWriteTpsMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<WriteTPSMetrics> writeTPSMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, WriteTPSMetrics.class);\n\n        List<WriteTPSMetricsVO> writeTPSMetricsVOS = ConvertUtil.list2List(writeTPSMetrics, WriteTPSMetricsVO.class);\n        Collections.sort(writeTPSMetricsVOS);\n        metrics.setWriteTps(writeTPSMetricsVOS);\n    }\n\n    private void aggReadTpsMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<ReadQPSMetrics> readQPSMetrics = esClusterPhyStatsService.getAggClusterPhyMetrics(metrics.getClusterName(),clusterType,\n            aggType, startTime, endTime, ReadQPSMetrics.class);\n\n        List<ReadQPSMetricsVO> readQPSMetricsVOS = ConvertUtil.list2List(readQPSMetrics, ReadQPSMetricsVO.class);\n        Collections.sort(readQPSMetricsVOS);\n        metrics.setReadTps(readQPSMetricsVOS);\n    }\n\n    private void aggSendTransMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<SendTransMetrics> readQPSMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, SendTransMetrics.class);\n\n        List<SendTransMetricsVO> sendTransMetricsVOS = ConvertUtil.list2List(readQPSMetrics, SendTransMetricsVO.class);\n        Collections.sort(sendTransMetricsVOS);\n        metrics.setSendTransSize(sendTransMetricsVOS);\n    }\n\n    private void aggRecvTransMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<RecvTransMetrics> readQPSMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, RecvTransMetrics.class);\n\n        List<RecvTransMetricsVO> recvTransMetricsVOS = ConvertUtil.list2List(readQPSMetrics, RecvTransMetricsVO.class);\n        Collections.sort(recvTransMetricsVOS);\n        metrics.setRecvTransSize(recvTransMetricsVOS);\n    }\n\n    /**\n     * 获取磁盘使用率大于75%的节点名称,所在集群ip\n     * @param clusterName\n     */\n    private List<NodeInfoForDiskUsageGte75PercentVO> getNodeInfoForDiskUsageGte75Percent(String clusterName) {\n        Map<String, ClusterNodeStats> clusterNodeStatsMap = esClusterNodeService.syncGetNodeFsStatsMap(clusterName);\n        List<NodeInfoForDiskUsageGte75PercentVO> nodeInfoForDiskUsageGte75PercentVOS = Lists.newArrayList();\n\n        //可添加使用率\n        clusterNodeStatsMap.values().parallelStream().forEach(nodeStats -> {\n            BigDecimal freeInBytesDec = new BigDecimal(nodeStats.getFs().getTotal().getFreeInBytes());\n            BigDecimal totalInBytesDec = new BigDecimal(nodeStats.getFs().getTotal().getTotalInBytes());\n            double freePercent = freeInBytesDec.divide(totalInBytesDec, 5, 1).doubleValue() * 100;\n            if (100 - freePercent >= 75) {\n                NodeInfoForDiskUsageGte75PercentVO build = new NodeInfoForDiskUsageGte75PercentVO();\n                build.setNodeIp(nodeStats.getHost());\n                build.setNodeName(nodeStats.getName());\n                build.setValue(100 - freePercent);\n                nodeInfoForDiskUsageGte75PercentVOS.add(build);\n            }\n        });\n        //倒序排列\n        nodeInfoForDiskUsageGte75PercentVOS.stream()\n                .sorted(Comparator.comparing(NodeInfoForDiskUsageGte75PercentVO::getValue))\n                .collect(Collectors.toList());\n\n        return nodeInfoForDiskUsageGte75PercentVOS;\n    }\n\n\n    /**\n     * > 从集群节点统计中获取以字节为单位使用的非堆内存\n     *\n     * @param clusterNodeStats 包含 JVM 统计信息的 ClusterNodeStats 对象。\n     * @return 以字节为单位使用的非堆内存。\n     */\n    private long getNonHeapUsedInBytes(ClusterNodeStats clusterNodeStats) {\n        return Optional.of(clusterNodeStats).map(ClusterNodeStats::getJvm).map(JvmNode::getMem).map(JvmMem::getNonHeapUsedInBytes).orElse(0L);\n    }\n\n    /**\n     * > 从集群节点统计中获取堆使用的字节数\n     *\n     * @param clusterNodeStats 包含 JVM 统计信息的 ClusterNodeStats 对象。\n     * @return 以字节为单位使用的堆。\n     */\n    private long getHeapUsedInBytes(ClusterNodeStats clusterNodeStats) {\n        return Optional.of(clusterNodeStats).map(ClusterNodeStats::getJvm).map(JvmNode::getMem).map(JvmMem::getHeapUsedInBytes).orElse(0L);\n    }\n\n    /**\n     * > 从集群节点统计中获取可用空间（以字节为单位）\n     *\n     * @param clusterNodeStats 包含节点信息的 ClusterNodeStats 对象。\n     * @return 集群节点的可用空间（以字节为单位）。\n     */\n    private long getFreeInBytes(ClusterNodeStats clusterNodeStats) {\n        return Optional.of(clusterNodeStats).map(ClusterNodeStats::getFs).map(FSNode::getTotal).map(FSTotal::getFreeInBytes).orElse(0L);\n    }\n\n    /**\n     * > 从集群节点统计中获取可用空间（以字节为单位）\n     *\n     * @param clusterNodeStats 包含节点信息的 ClusterNodeStats 对象。\n     * @return 可用空间（以字节为单位）。\n     */\n    private long getAvailableInBytes(ClusterNodeStats clusterNodeStats) {\n        return Optional.of(clusterNodeStats).map(ClusterNodeStats::getFs).map(FSNode::getTotal).map(FSTotal::getAvailableInBytes).orElse(0L);\n    }\n\n    /**\n     * “获取集群节点统计信息的总字节数，如果集群节点统计信息为空，则为 0。”\n     *\n     * 该函数比这要复杂一些，但这就是它的要点\n     *\n     * @param clusterNodeStats 包含节点信息的 ClusterNodeStats 对象。\n     * @return 文件系统中的总字节数。\n     */\n    private long getTotalInBytes(ClusterNodeStats clusterNodeStats) {\n        return Optional.of(clusterNodeStats).map(ClusterNodeStats::getFs).map(FSNode::getTotal).map(FSTotal::getTotalInBytes).orElse(0L);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/handle/ClusterOverviewMetricsHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.handle;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.BIG_SHARD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.PHY_CLUSTER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.CPU_LOAD_15M;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.CPU_LOAD_1M;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.CPU_LOAD_5M;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.CPU_USAGE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.DISK_USAGE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.INDEXING_LATENCY;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.SEARCH_LATENCY;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.TASK_COST;\n\nimport com.baomidou.mybatisplus.core.toolkit.CollectionUtils;\nimport com.didichuxing.datachannel.arius.admin.biz.component.MetricsValueConvertUtils;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.DiskInfoMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.ReadQPSMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.RecvTransMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.SendTransMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.ShardInfoMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.TaskCountMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.WriteTPSMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.BigIndexMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ClusterMemInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.MovingShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.PendingTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.UnAssignShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.percentiles.BasePercentileMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.BigIndexMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.BigShardMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.CpuLoadFor15MinMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.CpuLoadFor1MinMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.CpuLoadFor5MinMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.CpuUsageMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.DiskInfoMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.DiskUsageMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.ESClusterOverviewMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.ESClusterPhyBasicMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.IndexingLatencyMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.MovingShardMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.NodeInfoForDiskUsageGte75PercentVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.PendingTaskVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.ReadQPSMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.RecvTransMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.SearchLatencyMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.SendTransMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.ShardInfoMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.TaskCostMetricVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.TaskCountMetricVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.UnAssignShardMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.WriteTPSMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.DateTimeUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESShardService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.ESClusterPhyStatsService;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport java.math.BigDecimal;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.function.Consumer;\nimport java.util.stream.Collectors;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * Created by linyunan on 2021-08-02\n */\n@Component\npublic class ClusterOverviewMetricsHandle {\n\n    private static final ILog             LOGGER                        = LogFactory\n        .getLog(ClusterOverviewMetricsHandle.class);\n\n    @Autowired\n    private ESClusterPhyStatsService      esClusterPhyStatsService;\n\n    @Autowired\n    private ESClusterService              esClusterService;\n\n    @Autowired\n    private ESClusterNodeService          esClusterNodeService;\n\n    @Autowired\n    private ESShardService                esShardService;\n\n    @Autowired\n    private ClusterRoleHostService        clusterRoleHostService;\n\n    @Autowired\n    private ESTemplateService             esTemplateService;\n\n    @Autowired\n    private AriusConfigInfoService        ariusConfigInfoService;\n    @Autowired\n    private ESIndexCatService             esIndexCatService;\n\n    @Autowired\n    private IndexTemplatePhyService       indexTemplatePhyService;\n\n    private static final FutureUtil<Void> getMultipleMetricFutureUtil   = FutureUtil.init(\"getMultipleMetricFutureUtil\",\n        10, 10, 100);\n    private static final FutureUtil<Void> getClusterBasicInfoFutureUtil = FutureUtil\n        .init(\"getClusterBasicInfoFutureUtil\", 10, 10, 50);\n    private static final FutureUtil<Void> optimizeQueryBurrFutureUtil   = FutureUtil.init(\"optimizeQueryBurrFutureUtil\",\n        10, 10, 50);\n\n    /**\n     *         metricsTypes 物理集群二级指标类型\n     * @see    ClusterPhyClusterMetricsEnum\n     * @return ESClusterOverviewMetricsVO\n     */\n    public ESClusterOverviewMetricsVO buildClusterPhyOverviewMetrics(MetricsClusterPhyDTO metricsClusterPhyDTO) {\n\n        //1. building base objects\n        ESClusterOverviewMetricsVO esClusterOverviewMetricsVO = initESClusterPhyOverviewMetricsVO(metricsClusterPhyDTO);\n\n        //2. 从ES中获取指标, 同时获取多个\n        for (String metricsType : metricsClusterPhyDTO.getMetricsTypes()) {\n            getMultipleMetricFutureUtil.runnableTask(() -> aggClusterPhyOverviewMetrics(esClusterOverviewMetricsVO,\n                metricsType, metricsClusterPhyDTO.getAggType(), metricsClusterPhyDTO.getStartTime(),\n                metricsClusterPhyDTO.getEndTime()));\n        }\n        getMultipleMetricFutureUtil.waitExecute();\n        //3.非超级项目进行大索引过滤\n        filterESClusterOverviewMetricsVOByProjectIdAndClusterLogicName(esClusterOverviewMetricsVO,\n                metricsClusterPhyDTO.getProjectId(), metricsClusterPhyDTO.getClusterLogicName());\n        //4. uniform percentage unit\n        MetricsValueConvertUtils.convertClusterOverviewMetricsPercent(esClusterOverviewMetricsVO);\n\n        //5. optimize query burr\n        optimizeQueryBurrForClusterOverviewMetrics(esClusterOverviewMetricsVO);\n        \n        return esClusterOverviewMetricsVO;\n    }\n\n    /******************************************private*******************************************************/\n\n    private void filterESClusterOverviewMetricsVOByProjectIdAndClusterLogicName(\n            ESClusterOverviewMetricsVO esClusterOverviewMetricsVO, Integer projectId, String clusterLogicName) {\n        if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId) && StringUtils.isNotBlank(clusterLogicName)) {\n            List<String> belongToProjectIdIndexList = esIndexCatService.syncGetIndexListByProjectId(projectId,\n                    clusterLogicName);\n            if (CollectionUtils.isEmpty(belongToProjectIdIndexList)) {\n                esClusterOverviewMetricsVO.setBigIndices(Collections.emptyList());\n                esClusterOverviewMetricsVO.setBigShards(Collections.emptyList());\n                return;\n            }\n            \n            //过滤出项目所属大索引, 大于10亿文档数的索引\n            List<BigIndexMetricsVO> filterProjectIdBigIndex = Optional.ofNullable(\n                            esClusterOverviewMetricsVO.getBigIndices()).orElse(Collections.emptyList()).stream()\n                    .filter(i -> belongToProjectIdIndexList.contains(i.getIndexName())).collect(Collectors.toList());\n            esClusterOverviewMetricsVO.setBigIndices(filterProjectIdBigIndex);\n            //过滤出项目所属大shard列表\n            List<BigShardMetricsVO> bigShardMetricsVOS = Optional.ofNullable(esClusterOverviewMetricsVO.getBigShards())\n                    .orElse(Collections.emptyList()).stream()\n                    .filter(i -> belongToProjectIdIndexList.contains(i.getIndex())).collect(Collectors.toList());\n            esClusterOverviewMetricsVO.setBigShards(bigShardMetricsVOS);\n        }\n    \n    }\n\n    /**\n     * optimize query burr , compare the corresponding values of the front and\n     * back slices of a single time slice to find the maximum value\n     * @param esClusterOverviewMetricsVO\n     */\n    private void optimizeQueryBurrForClusterOverviewMetrics(ESClusterOverviewMetricsVO esClusterOverviewMetricsVO) {\n        optimizeQueryBurrFutureUtil\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getCpuUsage()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getCpuLoad1M()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getCpuLoad5M()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getCpuLoad15M()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getDiskUsage()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForPercentiles(esClusterOverviewMetricsVO.getSearchLatency()))\n            .runnableTask(() -> MetricsValueConvertUtils\n                .doOptimizeForPercentiles(esClusterOverviewMetricsVO.getIndexingLatency()))\n            .runnableTask(() -> MetricsValueConvertUtils\n                .doOptimizeForRecvTransSize(esClusterOverviewMetricsVO.getRecvTransSize()))\n            .runnableTask(() -> MetricsValueConvertUtils\n                .doOptimizeForSendTransSize(esClusterOverviewMetricsVO.getSendTransSize()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForDiskInfo(esClusterOverviewMetricsVO.getDiskInfo()))\n            .runnableTask(() -> MetricsValueConvertUtils.doOptimizeForShardNu(esClusterOverviewMetricsVO.getShardNu()))\n            .runnableTask(() -> MetricsValueConvertUtils.doOptimizeForReadTps(esClusterOverviewMetricsVO.getReadTps()))\n            .runnableTask(\n                () -> MetricsValueConvertUtils.doOptimizeForWriteTps(esClusterOverviewMetricsVO.getWriteTps()))\n            .waitExecute();\n    }\n\n    private ESClusterOverviewMetricsVO initESClusterPhyOverviewMetricsVO(MetricsClusterPhyDTO metricsClusterPhyDTO) {\n        ESClusterOverviewMetricsVO esClusterOverviewMetricsVO = new ESClusterOverviewMetricsVO();\n        ESClusterPhyBasicMetricsVO basicMetricsVO = new ESClusterPhyBasicMetricsVO();\n        esClusterOverviewMetricsVO.setClusterName(metricsClusterPhyDTO.getClusterPhyName());\n        esClusterOverviewMetricsVO.setPhysicCluster(PHY_CLUSTER);\n        esClusterOverviewMetricsVO.setDataCenter(EnvUtil.getDC().getCode());\n        esClusterOverviewMetricsVO.setBasic(basicMetricsVO);\n        esClusterOverviewMetricsVO.setCurrentTime(DateTimeUtil.formatTimestamp(System.currentTimeMillis()));\n        esClusterOverviewMetricsVO.setBigShardThreshold(ariusConfigInfoService.doubleSetting(AriusConfigConstant.ARIUS_COMMON_GROUP,\n                AriusConfigConstant.BIG_SHARD_THRESHOLD, BIG_SHARD));\n        return esClusterOverviewMetricsVO;\n    }\n\n    private void aggClusterPhyOverviewMetrics(ESClusterOverviewMetricsVO metrics, String metricsType, String aggType,\n                                              Long startTime, Long endTime) {\n        try {\n            switch (ClusterPhyClusterMetricsEnum.valueOfType(metricsType)) {\n                /*************************基本状态指标(状态类型)***************************/\n                case BASIC:\n                    getBasicMetrics(metrics);\n                    return;\n                case ELAPSEDTIME:\n                    getElapsedTimeMetrics(metrics);\n                    return;\n\n                /****************************业务指标(列表类型)*****************************/\n                case PENDING_TASKS:\n                    getPendingTasksMetrics(metrics);\n                    return;\n                case MOVING_SHARDS:\n                    getMovingShardsMetrics(metrics);\n                    return;\n                case UNASSIGN_SHARDS:\n                    getUnassignedShardsMetrics(metrics);\n                    return;\n                case INVALID_NODES:\n                    getInvalidNodesMetrics(metrics);\n                    return;\n                case BIG_INDICES:\n                    getBigIndicesMetrics(metrics);\n                    return;\n                case BIG_SHARDS:\n                    getBigShardsMetrics(metrics);\n                    return;\n\n                /********************************分位图类型*******************************/\n                case CPU_USAGE:\n                    aggPercentilesMetrics(metrics,PHY_CLUSTER, CPU_USAGE.getType(), aggType, startTime, endTime,\n                        b -> metrics.setCpuUsage(ConvertUtil.list2List(b, CpuUsageMetricsVO.class)));\n                    return;\n                case CPU_LOAD_1M:\n                    aggPercentilesMetrics(metrics,PHY_CLUSTER, CPU_LOAD_1M.getType(), aggType, startTime, endTime,\n                        b -> metrics.setCpuLoad1M(ConvertUtil.list2List(b, CpuLoadFor1MinMetricsVO.class)));\n                    return;\n                case CPU_LOAD_5M:\n                    aggPercentilesMetrics(metrics,PHY_CLUSTER, CPU_LOAD_5M.getType(), aggType, startTime, endTime,\n                        b -> metrics.setCpuLoad5M(ConvertUtil.list2List(b, CpuLoadFor5MinMetricsVO.class)));\n                    return;\n                case CPU_LOAD_15M:\n                    aggPercentilesMetrics(metrics,PHY_CLUSTER, CPU_LOAD_15M.getType(), aggType, startTime, endTime,\n                        b -> metrics.setCpuLoad15M(ConvertUtil.list2List(b, CpuLoadFor15MinMetricsVO.class)));\n                    return;\n                case DISK_USAGE:\n                    aggPercentilesMetrics(metrics,PHY_CLUSTER, DISK_USAGE.getType(), aggType, startTime, endTime,\n                        b -> metrics.setDiskUsage(ConvertUtil.list2List(b, DiskUsageMetricsVO.class)));\n                    return;\n                case SEARCH_LATENCY:\n                    aggPercentilesMetrics(metrics,PHY_CLUSTER, SEARCH_LATENCY.getType(), aggType, startTime, endTime,\n                        b -> metrics.setSearchLatency(ConvertUtil.list2List(b, SearchLatencyMetricsVO.class)));\n                    return;\n                case INDEXING_LATENCY:\n                    aggPercentilesMetrics(metrics,PHY_CLUSTER, INDEXING_LATENCY.getType(), aggType, startTime, endTime,\n                        b -> metrics.setIndexingLatency(ConvertUtil.list2List(b, IndexingLatencyMetricsVO.class)));\n                    return;\n\n                case TASK_COST:\n                    aggPercentilesMetrics(metrics,PHY_CLUSTER, TASK_COST.getType(), aggType, startTime, endTime,\n                        b -> metrics.setTaskCost(ConvertUtil.list2List(b, TaskCostMetricVO.class)));\n                    return;\n\n                /********************************普通指标(折线图)*******************************/\n                case DISK_INFO:\n                    aggDiskInfoMetrics(metrics,PHY_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case SHARD_NUM:\n                    aggShardNuMetrics(metrics,PHY_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case READ_QPS:\n                    aggReadTpsMetrics(metrics,PHY_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case WRITE_TPS:\n                    aggWriteTpsMetrics(metrics,PHY_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case RECV_TRANS_SIZE:\n                    aggRecvTransMetrics(metrics,PHY_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case SEND_TRANS_SIZE:\n                    aggSendTransMetrics(metrics,PHY_CLUSTER, aggType, startTime, endTime);\n                    return;\n                case NODES_FOR_DISK_USAGE_GTE_75PERCENT:\n                    aggNodesForDiskUsageGte75PercentMetrics(metrics);\n                    return;\n                case TASK_NUM:\n                    aggTaskCount(metrics,PHY_CLUSTER, aggType, startTime, endTime);\n                    return;\n                default:\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=ClusterPhyOverviewMetricsHandle||method=aggClusterPhyOverviewMetrics||errMsg={}\",\n                e.getMessage());\n        }\n    }\n\n    private void getInvalidNodesMetrics(ESClusterOverviewMetricsVO metrics) {\n        List<String> nodeHostsFromES = esClusterNodeService.syncGetNodeHosts(metrics.getClusterName());\n        List<ClusterRoleHost> nodesByCluster = clusterRoleHostService.getNodesByCluster(metrics.getClusterName());\n        List<ClusterRoleHost> invalidNodeIps = Lists.newArrayList();\n        nodesByCluster.forEach(nodeFromDb -> {\n            if (!nodeHostsFromES.contains(nodeFromDb.getIp())) {\n                invalidNodeIps.add(nodeFromDb);\n            }\n        });\n\n        metrics.setInvalidNodes(invalidNodeIps);\n    }\n\n    private void getBigShardsMetrics(ESClusterOverviewMetricsVO metrics) throws ESOperateException {\n        List<ShardMetrics> shardMetrics = esShardService.syncGetBigShards(metrics.getClusterName());\n        metrics.setBigShards(ConvertUtil.list2List(shardMetrics, BigShardMetricsVO.class));\n    }\n\n    private void getBigIndicesMetrics(ESClusterOverviewMetricsVO metrics) throws ESOperateException {\n        List<BigIndexMetrics> bigIndexMetrics = esClusterNodeService.syncGetBigIndices(metrics.getClusterName());\n        metrics.setBigIndices(ConvertUtil.list2List(bigIndexMetrics, BigIndexMetricsVO.class));\n    }\n\n    private void getMovingShardsMetrics(ESClusterOverviewMetricsVO metrics) throws ESOperateException {\n        List<MovingShardMetrics> movingShardsMetrics = esShardService.syncGetMovingShards(metrics.getClusterName());\n        metrics.setMovingShards(ConvertUtil.list2List(movingShardsMetrics, MovingShardMetricsVO.class));\n    }\n\n    private void getUnassignedShardsMetrics(ESClusterOverviewMetricsVO metrics) throws ESOperateException {\n        List<UnAssignShardMetrics> unAssignShardMetrics = esShardService.syncGetUnAssignShards(metrics.getClusterName());\n        metrics.setUnAssignShards(ConvertUtil.list2List(unAssignShardMetrics, UnAssignShardMetricsVO.class));\n    }\n\n    private void getPendingTasksMetrics(ESClusterOverviewMetricsVO metrics) throws ESOperateException {\n        List<PendingTask> pendingTaskFromES = esClusterNodeService.syncGetPendingTask(metrics.getClusterName());\n        metrics.setPendingTasks(ConvertUtil.list2List(pendingTaskFromES, PendingTaskVO.class));\n    }\n\n    private void getElapsedTimeMetrics(ESClusterOverviewMetricsVO metrics) {\n        ESClusterPhyBasicMetricsVO basic = metrics.getBasic();\n        getClusterBasicInfoFutureUtil\n            .runnableTask(() -> buildBasicMetricsFromClusterStats(basic, metrics.getClusterName()))\n            .runnableTask(() -> buildBasicMetricsFromEsClusterTemplate(basic, metrics.getClusterName()))\n            .runnableTask(() -> buildBasicMetricsFromEsClusterNodeInfo(basic, metrics.getClusterName()))\n            .runnableTask(() -> buildBasicMetricsFromEsClusterMemInfo(basic, metrics.getClusterName())).waitExecute();\n    }\n\n    private void getBasicMetrics(ESClusterOverviewMetricsVO metrics) {\n        ESClusterPhyBasicMetricsVO basic = metrics.getBasic();\n        getClusterBasicInfoFutureUtil\n            .runnableTask(() -> buildBasicMetricsFromClusterStats(basic, metrics.getClusterName()))\n            .runnableTask(() -> buildBasicMetricsFromEsClusterTemplate(basic, metrics.getClusterName()))\n            .runnableTask(() -> buildBasicMetricsFromEsClusterNodeInfo(basic, metrics.getClusterName()))\n            .runnableTask(() -> buildBasicMetricsFromEsClusterMemInfo(basic, metrics.getClusterName())).waitExecute();\n    }\n\n    /**\n     * 设置集群总览视图中内存的基础信息，兼容2.3.3低版本的es集群\n     * @param basicVO 集群总览基础视图\n     * @param clusterName  物理集群名称\n     */\n    private void buildBasicMetricsFromEsClusterMemInfo(ESClusterPhyBasicMetricsVO basicVO, String clusterName) {\n        ClusterMemInfo clusterMemInfo = esClusterNodeService.synGetClusterMem(clusterName);\n        if (AriusObjUtils.isNull(clusterMemInfo)) {\n            LOGGER.warn(\n                \"class=ClusterPhyOverviewMetricsHandle||method=buildBasicMetricsFromEsClusterMemInfo||mem info is empty\");\n            return;\n        }\n\n        // 设置内存信息\n        basicVO.setMemTotal(clusterMemInfo.getMemTotal());\n        basicVO.setMemFree(clusterMemInfo.getMemFree());\n        basicVO.setMemUsed(clusterMemInfo.getMemUsed());\n        basicVO.setMemFreePercent(clusterMemInfo.getMemFreePercent());\n        basicVO.setMemUsedPercent(clusterMemInfo.getMemUsedPercent());\n    }\n\n    /**\n     * 构建集群基本指标信息\n     * @param basicVO\n     * @param clusterName\n     */\n    private void buildBasicMetricsFromClusterStats(ESClusterPhyBasicMetricsVO basicVO, String clusterName) {\n        ESClusterStatsResponse clusterStats = esClusterService.syncGetClusterStats(clusterName);\n        if (null == clusterStats) {\n            return;\n        }\n\n        //设置状态\n        basicVO.setStatus(clusterStats.getStatus());\n\n        //设置基础信息\n        basicVO.setNumberNodes(clusterStats.getTotalNodes());\n        basicVO.setTotalIndicesNu(clusterStats.getIndexCount());\n        basicVO.setShardNu(clusterStats.getTotalShard());\n        basicVO.setTotalDocNu(clusterStats.getDocsCount());\n        basicVO.setIndicesStoreSize(clusterStats.getIndicesStoreSize().getBytes());\n        basicVO.setUnassignedShardNum(clusterStats.getUnassignedShardNum());\n\n        //设置集群磁盘信息\n        long storeSize = clusterStats.getTotalFs().getBytes() - clusterStats.getFreeFs().getBytes();\n        basicVO.setStoreSize(storeSize);\n        basicVO.setTotalStoreSize(clusterStats.getTotalFs().getBytes());\n        basicVO.setFreeStoreSize(clusterStats.getFreeFs().getBytes());\n        //保留小数点后3位\n        BigDecimal storeSizeDec = new BigDecimal(storeSize);\n        BigDecimal totalSizeDec = new BigDecimal(clusterStats.getTotalFs().getBytes());\n        basicVO.setStoreUsage(storeSizeDec.divide(totalSizeDec, 5, 1).doubleValue() * 100);\n        basicVO.setStoreFreeUsage((100 - basicVO.getStoreUsage()));\n\n        //设置堆内存使用率信息\n        long heapFreeSize = clusterStats.getTotalHeapMem().getBytes() - clusterStats.getUsedHeapMem().getBytes();\n        basicVO.setHeapMemFree(heapFreeSize);\n        basicVO.setHeapMemTotal(clusterStats.getTotalHeapMem().getBytes());\n        basicVO.setHeapMemUsed(clusterStats.getUsedHeapMem().getBytes());\n        //保留小数点后3位\n        BigDecimal storeHeapMemSizeDec = new BigDecimal(clusterStats.getUsedHeapMem().getBytes());\n        BigDecimal totalHeapMemSizeDec = new BigDecimal(clusterStats.getTotalHeapMem().getBytes());\n        basicVO.setHeapUsage(storeHeapMemSizeDec.divide(totalHeapMemSizeDec, 5, 1).doubleValue() * 100);\n        basicVO.setHeapFreeUsage((100 - basicVO.getHeapUsage()));\n\n        //设置集群节点信息\n        basicVO.setNumberMasterNodes(clusterStats.getNumberMasterNodes());\n        basicVO.setNumberDataNodes(clusterStats.getNumberDataNodes());\n        basicVO.setNumberClientNodes(clusterStats.getNumberClientNodes());\n        basicVO.setNumberIngestNodes(clusterStats.getNumberIngestNodes());\n        basicVO.setNumberCoordinatingOnlyNodes(clusterStats.getNumberCoordinatingOnly());\n    }\n\n    /**\n     * 设置集群有效、无效节点数\n     * @param basicVO\n     * @param clusterName\n     */\n    private void buildBasicMetricsFromEsClusterNodeInfo(ESClusterPhyBasicMetricsVO basicVO, String clusterName) {\n        List<String> esHost = esClusterNodeService.syncGetNodeHosts(clusterName);\n        long invalidNodeCount = 0;\n        long activeNodeCount = 0;\n        List<ClusterRoleHost> nodesByCluster = clusterRoleHostService.getNodesByCluster(clusterName);\n        Set<String> nodeIps = nodesByCluster.stream().map(ClusterRoleHost::getIp).collect(Collectors.toSet());\n        for (String ip : nodeIps) {\n            if (!esHost.contains(ip)) {\n                invalidNodeCount++;\n            } else {\n                activeNodeCount++;\n            }\n        }\n        basicVO.setActiveNodeNu(activeNodeCount);\n        basicVO.setInvalidNodeNu(invalidNodeCount);\n        basicVO.setTotalNodeNu(nodeIps.size());\n\n        BigDecimal activeNodeNu = new BigDecimal(activeNodeCount);\n        BigDecimal totalNodeNu = new BigDecimal(nodeIps.size());\n        basicVO.setActiveNodeNuPercent(activeNodeNu.divide(totalNodeNu, 3, 1).doubleValue() * 100);\n        basicVO.setInvalidNodeNuPercent(100 - basicVO.getActiveNodeNuPercent());\n    }\n\n    /**\n     * 设置集群真实模板数量\n     * @param basicVO\n     * @param clusterName\n     */\n    private void buildBasicMetricsFromEsClusterTemplate(ESClusterPhyBasicMetricsVO basicVO, String clusterName) {\n        basicVO.setTotalTemplateNu((long) indexTemplatePhyService.getNormalTemplateByCluster(clusterName).size());\n    }\n\n    /**\n     * 获取集群维度分位统计信息\n     */\n    private void aggPercentilesMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String clusterMetricsType, String aggType,\n                                       Long startTime, Long endTime, Consumer<List<BasePercentileMetrics>> function) {\n\n        List<BasePercentileMetrics> aggPercentilesMetrics = esClusterPhyStatsService\n            .getAggPercentilesMetrics(metrics.getClusterName(),clusterType, clusterMetricsType, aggType, startTime, endTime);\n\n        Collections.sort(aggPercentilesMetrics);\n\n        function.accept(aggPercentilesMetrics);\n    }\n\n    private void aggNodesForDiskUsageGte75PercentMetrics(ESClusterOverviewMetricsVO metrics) {\n        metrics.setNodesForDiskUsageGte75Percent(getNodeInfoForDiskUsageGte75Percent(metrics.getClusterName()));\n    }\n\n    private void aggDiskInfoMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<DiskInfoMetrics> diskInfoMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, DiskInfoMetrics.class);\n        List<DiskInfoMetricsVO> diskInfoMetricsVOS = ConvertUtil.list2List(diskInfoMetrics, DiskInfoMetricsVO.class);\n        Collections.sort(diskInfoMetricsVOS);\n        metrics.setDiskInfo(diskInfoMetricsVOS);\n    }\n\n    private void aggShardNuMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<ShardInfoMetrics> shardInfoMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, ShardInfoMetrics.class);\n\n        List<ShardInfoMetricsVO> shardInfoMetricsVOS = ConvertUtil.list2List(shardInfoMetrics,\n            ShardInfoMetricsVO.class);\n        Collections.sort(shardInfoMetricsVOS);\n        metrics.setShardNu(shardInfoMetricsVOS);\n    }\n\n    private void aggTaskCount(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<TaskCountMetrics> taskCountMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, TaskCountMetrics.class);\n\n        List<TaskCountMetricVO> taskCountMetricVOS = ConvertUtil.list2List(taskCountMetrics, TaskCountMetricVO.class);\n        Collections.sort(taskCountMetricVOS);\n        metrics.setTaskCount(taskCountMetricVOS);\n    }\n\n    private void aggWriteTpsMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<WriteTPSMetrics> writeTPSMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(), clusterType,aggType, startTime, endTime, WriteTPSMetrics.class);\n\n        List<WriteTPSMetricsVO> writeTPSMetricsVOS = ConvertUtil.list2List(writeTPSMetrics, WriteTPSMetricsVO.class);\n        Collections.sort(writeTPSMetricsVOS);\n        metrics.setWriteTps(writeTPSMetricsVOS);\n    }\n\n    private void aggReadTpsMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<ReadQPSMetrics> readQPSMetrics = esClusterPhyStatsService.getAggClusterPhyMetrics(metrics.getClusterName(),clusterType,\n            aggType, startTime, endTime, ReadQPSMetrics.class);\n\n        List<ReadQPSMetricsVO> readQPSMetricsVOS = ConvertUtil.list2List(readQPSMetrics, ReadQPSMetricsVO.class);\n        Collections.sort(readQPSMetricsVOS);\n        metrics.setReadTps(readQPSMetricsVOS);\n    }\n\n    private void aggSendTransMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<SendTransMetrics> readQPSMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, SendTransMetrics.class);\n\n        List<SendTransMetricsVO> sendTransMetricsVOS = ConvertUtil.list2List(readQPSMetrics, SendTransMetricsVO.class);\n        Collections.sort(sendTransMetricsVOS);\n        metrics.setSendTransSize(sendTransMetricsVOS);\n    }\n\n    private void aggRecvTransMetrics(ESClusterOverviewMetricsVO metrics,long clusterType, String aggType, Long startTime, Long endTime) {\n        List<RecvTransMetrics> readQPSMetrics = esClusterPhyStatsService\n            .getAggClusterPhyMetrics(metrics.getClusterName(),clusterType, aggType, startTime, endTime, RecvTransMetrics.class);\n\n        List<RecvTransMetricsVO> recvTransMetricsVOS = ConvertUtil.list2List(readQPSMetrics, RecvTransMetricsVO.class);\n        Collections.sort(recvTransMetricsVOS);\n        metrics.setRecvTransSize(recvTransMetricsVOS);\n    }\n\n    /**\n     * 获取磁盘使用率大于75%的节点名称,所在集群ip\n     * @param clusterName\n     */\n    private List<NodeInfoForDiskUsageGte75PercentVO> getNodeInfoForDiskUsageGte75Percent(String clusterName) {\n        Map<String, ClusterNodeStats> clusterNodeStatsMap = esClusterNodeService.syncGetNodeFsStatsMap(clusterName);\n        List<NodeInfoForDiskUsageGte75PercentVO> nodeInfoForDiskUsageGte75PercentVOS = Lists.newArrayList();\n\n        //可添加使用率\n        clusterNodeStatsMap.values().parallelStream().forEach(nodeStats -> {\n            BigDecimal freeInBytesDec = new BigDecimal(nodeStats.getFs().getTotal().getFreeInBytes());\n            BigDecimal totalInBytesDec = new BigDecimal(nodeStats.getFs().getTotal().getTotalInBytes());\n            double freePercent = freeInBytesDec.divide(totalInBytesDec, 5, 1).doubleValue() * 100;\n            if (100 - freePercent >= 75) {\n                NodeInfoForDiskUsageGte75PercentVO build = new NodeInfoForDiskUsageGte75PercentVO();\n                build.setNodeIp(nodeStats.getHost());\n                build.setNodeName(nodeStats.getName());\n                build.setValue(100 - freePercent);\n                nodeInfoForDiskUsageGte75PercentVOS.add(build);\n            }\n        });\n        //倒序排列\n        nodeInfoForDiskUsageGte75PercentVOS.stream()\n                .sorted(Comparator.comparing(NodeInfoForDiskUsageGte75PercentVO::getValue))\n                .collect(Collectors.toList());\n\n        return nodeInfoForDiskUsageGte75PercentVOS;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/handle/handler/PhyIndicesClusterMetricsHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.handle.handler;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyIndicesMetricsEnum.getClusterPhyIndicesMetricsType;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.handle.BaseClusterMetricsHandle;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyIndicesDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.AggMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyIndicesMetricsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.ESIndicesStatsService;\nimport java.util.List;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * phy集群指数指标\n *\n * @author\n * @date 2022/05/24\n */\n@Service(\"clusterPhyIndicesMetricsHandler\")\npublic class PhyIndicesClusterMetricsHandler extends BaseClusterMetricsHandle {\n    @Autowired\n    private ESIndicesStatsService esIndicesStatsService;\n    @Autowired\n    private              ESIndexCatService        esIndexCatService;\n    @Override\n    protected Result<Void> checkSpecialParam(MetricsClusterPhyDTO param) {\n        for (String metricsType : param.getMetricsTypes()) {\n            if (!ClusterPhyIndicesMetricsEnum.hasExist(metricsType)) {\n                return Result.buildParamIllegal(\"metricsType is error\");\n            }\n        }\n\n        return Result.buildSucc();\n    }\n    \n    @Override\n    protected List<VariousLineChartMetrics> getAggClusterPhyMetrics(MetricsClusterPhyDTO param) {\n        //这里其实需要做修改；1.普通项目侧，我们从cat index info中获取项目侧创建的索引后，再然后再通过指标去查询，\n        if (!AuthConstant.SUPER_PROJECT_ID.equals(param.getProjectId()) && StringUtils.isNotBlank(\n                param.getClusterLogicName()) && StringUtils.isBlank(\n                ((MetricsClusterPhyIndicesDTO) param).getIndexName())) {\n            //找到平台侧属于该项目的索引\n            List<String> belongToProjectIndexName = esIndexCatService.syncGetIndexListByProjectId(param.getProjectId(),\n                    param.getClusterLogicName());\n            return esIndicesStatsService.getAggClusterPhyIndicesMetrics((MetricsClusterPhyIndicesDTO) param,\n                    belongToProjectIndexName);\n            \n        } else {\n            //2.超级项目侧/有索引带入的时候，直接查询\n            return esIndicesStatsService.getAggClusterPhyIndicesMetrics((MetricsClusterPhyIndicesDTO) param);\n            \n        }\n        \n    }\n\n    @Override\n    protected void initMetricsClusterPhy(MetricsClusterPhyDTO param) {\n        param.setAggType(AggMetricsTypeEnum.MAX.getType());\n        //指标类型为空, 获取默认指标\n        if (CollectionUtils.isEmpty(param.getMetricsTypes())) {\n            param.setMetricsTypes(getClusterPhyIndicesMetricsType());\n        }\n\n        MetricsClusterPhyIndicesDTO clusterPhyIndicesDTO = (MetricsClusterPhyIndicesDTO) param;\n        if (!AriusObjUtils.isBlack(clusterPhyIndicesDTO.getIndexName())) {\n            param.setTopNu(null);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/handle/handler/PhyNodeClusterMetricsHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.handle.handler;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyNodeMetricsEnum.getClusterPhyNodeMetricsType;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.handle.BaseClusterMetricsHandle;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyNodeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.AggMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyNodeMetricsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.NodeStatsService;\nimport java.util.List;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n *\n *\n * @author\n * @date 2022/05/24\n */\n@Service(\"clusterPhyNodeMetricsHandler\")\npublic class PhyNodeClusterMetricsHandler extends BaseClusterMetricsHandle {\n    @Autowired\n    private NodeStatsService nodeStatsService;\n\n    @Override\n    protected Result<Void> checkSpecialParam(MetricsClusterPhyDTO param) {\n        for (String metricsType : param.getMetricsTypes()) {\n            if (!ClusterPhyNodeMetricsEnum.hasExist(metricsType)) {\n                return Result.buildParamIllegal(String.format(\"metricsType:%s is error\", metricsType));\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected List<VariousLineChartMetrics> getAggClusterPhyMetrics(MetricsClusterPhyDTO param) {\n        return nodeStatsService.getAggClusterPhyNodeMetrics((MetricsClusterPhyNodeDTO) param);\n    }\n\n    @Override\n    protected void initMetricsClusterPhy(MetricsClusterPhyDTO param) {\n        param.setAggType(AggMetricsTypeEnum.MAX.getType());\n        //指标类型为空, 获取默认指标\n        if (CollectionUtils.isEmpty(param.getMetricsTypes())) {\n            param.setMetricsTypes(getClusterPhyNodeMetricsType());\n        }\n\n        MetricsClusterPhyNodeDTO clusterPhyNodeDTO = (MetricsClusterPhyNodeDTO) param;\n        if (!AriusObjUtils.isBlack(clusterPhyNodeDTO.getNodeName())) {\n            param.setTopNu(null);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/handle/handler/PhyNodesTaskClusterMetricsHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.handle.handler;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyNodeMetricsEnum.getClusterPhyNodeMetricsType;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.handle.BaseClusterMetricsHandle;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyNodeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyNodeTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.AggMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyNodeMetricsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.NodeStatsService;\nimport java.util.List;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n *\n *\n * @author\n * @date 2022/05/24\n */\n@Service(\"clusterPhyNodesTaskMetricsHandler\")\npublic class PhyNodesTaskClusterMetricsHandler extends BaseClusterMetricsHandle {\n    @Autowired\n    private NodeStatsService nodeStatsService;\n\n    @Override\n    protected Result<Void> checkSpecialParam(MetricsClusterPhyDTO param) {\n        for (String metricsType : param.getMetricsTypes()) {\n            if (!ClusterPhyNodeMetricsEnum.hasExist(metricsType)) {\n                return Result.buildParamIllegal(String.format(\"metricsType:%s is error\", metricsType));\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected List<VariousLineChartMetrics> getAggClusterPhyMetrics(MetricsClusterPhyDTO param) {\n        return nodeStatsService.getAggClusterPhyNodeTaskMetrics((MetricsClusterPhyNodeTaskDTO) param);\n    }\n\n    @Override\n    protected void initMetricsClusterPhy(MetricsClusterPhyDTO param) {\n        param.setAggType(AggMetricsTypeEnum.MAX.getType());\n        //指标类型为空, 获取默认指标\n        if (CollectionUtils.isEmpty(param.getMetricsTypes())) {\n            param.setMetricsTypes(getClusterPhyNodeMetricsType());\n        }\n\n        MetricsClusterPhyNodeDTO clusterPhyNodeDTO = (MetricsClusterPhyNodeDTO) param;\n        if (!AriusObjUtils.isBlack(clusterPhyNodeDTO.getNodeName())) {\n            param.setTopNu(null);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/handle/handler/PhyOverviewClusterMetricsHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.handle.handler;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.getDefaultClusterPhyMetricsCode;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.handle.BaseClusterMetricsHandle;\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.handle.ClusterLogicOverviewMetricsHandle;\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.handle.ClusterOverviewMetricsHandle;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.MetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.AggMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n *\n *\n * @author\n * @date 2022/05/24\n */\n@Service(\"clusterPhyOverviewMetricsHandler\")\npublic class PhyOverviewClusterMetricsHandler extends BaseClusterMetricsHandle {\n    @Autowired\n    private ClusterOverviewMetricsHandle clusterOverviewMetricsHandle;\n\n    @Autowired\n    private ClusterLogicOverviewMetricsHandle clusterLogicOverviewMetricsHandle;\n\n    @Override\n    protected Result<Void> checkSpecialParam(MetricsClusterPhyDTO param) {\n        for (String metricsType : param.getMetricsTypes()) {\n            if (!ClusterPhyClusterMetricsEnum.hasExist(metricsType)) {\n                return Result.buildParamIllegal(\"metricsType is error\");\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected void initMetricsClusterPhy(MetricsClusterPhyDTO param) {\n        param.setAggType(AggMetricsTypeEnum.MAX.getType());\n        //指标类型为空, 获取默认指标\n        if (CollectionUtils.isEmpty(param.getMetricsTypes())) {\n            param.setMetricsTypes(getDefaultClusterPhyMetricsCode());\n        }\n    }\n\n    @Override\n    protected MetricsVO buildClusterPhyMetricsVO(MetricsClusterPhyDTO param) {\n        return clusterOverviewMetricsHandle.buildClusterPhyOverviewMetrics(param);\n    }\n\n    @Override\n    protected MetricsVO buildClusterLogicMetricsVO(MetricsClusterPhyDTO param) {\n        return clusterLogicOverviewMetricsHandle.buildClusterLogicOverviewMetrics(param);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/handle/handler/PhyTemplateClusterMetricsHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.handle.handler;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyIndicesMetricsEnum.getClusterPhyIndicesMetricsType;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.handle.BaseClusterMetricsHandle;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyIndicesDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyIndicesMetricsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.ESIndicesStatsService;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n *\n *\n * @author\n * @date 2022/05/24\n */\n@Service(\"clusterPhyTemplateMetricsHandler\")\npublic class PhyTemplateClusterMetricsHandler extends BaseClusterMetricsHandle {\n    @Autowired\n    private ESIndicesStatsService esIndicesStatsService;\n\n    @Autowired\n    private IndexTemplateService  indexTemplateService;\n    \n    private static final FutureUtil<TupleTwo</*logicTemplateId*/String,/*name*/String>> OPTIMIZE_QUERY_BURR_FUTURE_UTIL =\n            FutureUtil.init(\n            \"PhyTemplateClusterMetricsHandler\",\n            10, 10, 50);\n\n    @Override\n    protected Result<Void> checkSpecialParam(MetricsClusterPhyDTO param) {\n        for (String metricsType : param.getMetricsTypes()) {\n            if (!ClusterPhyIndicesMetricsEnum.hasExist(metricsType)) {\n                return Result.buildParamIllegal(\"metricsType is error\");\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected List<VariousLineChartMetrics> getAggClusterPhyMetrics(MetricsClusterPhyDTO param) {\n        List<VariousLineChartMetrics> aggClusterPhyTemplateMetrics =null;\n        //先去查项目所属的逻辑模板id\n        if (!AuthConstant.SUPER_PROJECT_ID.equals(param.getProjectId()) && Objects.isNull(\n                ((MetricsClusterPhyTemplateDTO) param).getLogicTemplateId())) {\n            List<Integer> belongToProjectIdLogicTemplateIdList = indexTemplateService.getLogicTemplateIdListByProjectId(\n                    param.getProjectId());\n            aggClusterPhyTemplateMetrics = esIndicesStatsService.getAggClusterPhyTemplateMetrics(\n                    (MetricsClusterPhyTemplateDTO) param, belongToProjectIdLogicTemplateIdList);\n        } else {\n            aggClusterPhyTemplateMetrics = esIndicesStatsService.getAggClusterPhyTemplateMetrics(\n                    (MetricsClusterPhyTemplateDTO) param);\n        }\n        \n        \n        \n        // 逻辑模板id转化为逻辑模板名称\n        convertTemplateIdToName(aggClusterPhyTemplateMetrics);\n\n        return aggClusterPhyTemplateMetrics;\n    }\n\n    @Override\n    protected void initMetricsClusterPhy(MetricsClusterPhyDTO param) {\n        //指标类型为空, 获取默认指标\n        if (CollectionUtils.isEmpty(param.getMetricsTypes())) {\n            param.setMetricsTypes(getClusterPhyIndicesMetricsType());\n        }\n\n        MetricsClusterPhyIndicesDTO clusterPhyIndicesDTO = (MetricsClusterPhyIndicesDTO) param;\n        if (!AriusObjUtils.isBlack(clusterPhyIndicesDTO.getIndexName())) {\n            param.setTopNu(null);\n        }\n    }\n\n    /**\n     * 将采集数据中的逻辑模板id转化为对应的逻辑模板名称\n     * @param aggClusterPhyTemplateMetrics 聚合的模板指标数据列表\n     */\n    private void convertTemplateIdToName(List<VariousLineChartMetrics> aggClusterPhyTemplateMetrics) {\n        //获取所有的模版id\n        final List<Integer> logicTemplateIds = aggClusterPhyTemplateMetrics.stream()\n                .map(VariousLineChartMetrics::getMetricsContents).filter(CollectionUtils::isNotEmpty)\n                .flatMap(Collection::stream).map(MetricsContent::getName).filter(StringUtils::isNumeric)\n                .map(Integer::parseInt).distinct().collect(Collectors.toList());\n        //并行查询所有的模版\n        for (Integer logicTemplateId : logicTemplateIds) {\n            OPTIMIZE_QUERY_BURR_FUTURE_UTIL.callableTask(() -> {\n                String logicTemplate = indexTemplateService.getNameByTemplateLogicId(logicTemplateId);\n                return Tuples.of(logicTemplateId.toString(), logicTemplate);\n            \n            });\n        }\n        final Map<String, String> logicTemplateId2Name = ConvertUtil.list2Map(\n                OPTIMIZE_QUERY_BURR_FUTURE_UTIL.waitResult(), TupleTwo::v1, TupleTwo::v2);\n        //设置模版名称\n        aggClusterPhyTemplateMetrics.stream().map(VariousLineChartMetrics::getMetricsContents)\n                .filter(CollectionUtils::isNotEmpty).flatMap(Collection::stream)\n                .forEach(metricsContent -> metricsContent.setName(logicTemplateId2Name.get(metricsContent.getName())));\n       \n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/impl/ClusterPhyMetricsManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.ClusterPhyMetricsManager;\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.handle.BaseClusterMetricsHandle;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.MetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.ESClusterTaskDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyTypeMetricsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ConfigTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.metrics.UserConfigService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.NodeStatsService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyClusterMetricsEnum.getClusterPhyMetricsType;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyIndicesMetricsEnum.getClusterPhyIndicesMetricsType;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyNodeMetricsEnum.getClusterPhyNodeMetricsType;\n\n/**\n * @author Created by linyunan on\n * @date 2021-07-30\n */\n@Component\npublic class ClusterPhyMetricsManagerImpl implements ClusterPhyMetricsManager {\n\n    private static final ILog        LOGGER = LogFactory.getLog(ClusterPhyMetricsManagerImpl.class);\n\n    @Autowired\n    private ProjectService           projectService;\n\n    @Autowired\n    private UserConfigService userConfigService;\n\n    @Autowired\n    private NodeStatsService         nodeStatsService;\n\n    @Autowired\n    private HandleFactory            handleFactory;\n\n    @Autowired\n    private ClusterLogicService      clusterLogicService;\n\n    @Autowired\n    private ClusterRegionService     clusterRegionService;\n\n    @Autowired\n    private ClusterRoleHostService   clusterRoleHostService;\n\n    @Autowired\n    private IndexTemplateService     indexTemplateService;\n\n    @Autowired\n    private ESIndexService           esIndexService;\n    @Autowired\n    private ESIndexCatService        esIndexCatService;\n\n    @Override\n    public List<String> getMetricsCode2TypeMap(String type) {\n        switch (ClusterPhyTypeMetricsEnum.valueOfType(type)) {\n            case CLUSTER:\n                return getClusterPhyMetricsType();\n            case NODE:\n                return getClusterPhyNodeMetricsType();\n            case INDICES:\n            case TEMPLATES:\n                return getClusterPhyIndicesMetricsType();\n            default:\n                return Lists.newArrayList();\n        }\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public <T> Result<T> getClusterMetricsByMetricsType(MetricsClusterPhyDTO param, Integer projectId, String userName,\n                                                        ClusterPhyTypeMetricsEnum metricsTypeEnum) {\n        try {\n            param.setProjectId(projectId);\n            if (StringUtils.isNotBlank(param.getClusterLogicName())) {\n                ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByNameThatNotContainsProjectId(param.getClusterLogicName());\n                if (clusterLogic==null){\n                    return Result.buildFail();\n                }\n                ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogic.getId());\n                if (clusterRegion == null) {\n                    return Result.buildFail();\n                }\n                List<String> itemNamesUnderClusterLogic;\n                //获取逻辑集群下面的节点，索引，模板的名称列表\n                itemNamesUnderClusterLogic = buildItemsUnderClusterLogic(metricsTypeEnum, clusterRegion);\n                param.setItemNamesUnderClusterLogic(itemNamesUnderClusterLogic);\n                param.setClusterPhyName(clusterRegion.getPhyClusterName());\n            }\n            T result;\n            BaseClusterMetricsHandle metricsHandle = (BaseClusterMetricsHandle) handleFactory\n                .getByHandlerNamePer(metricsTypeEnum.getType());\n            if (AriusObjUtils.isNull(metricsHandle)) {\n                LOGGER.warn(\n                    \"class=ClusterPhyMetricsManagerImpl||method=getClusterMetricsFromEs||errMsg=cannot get metricsHandle\");\n                return Result.buildFail();\n            }\n\n            if (metricsTypeEnum.isCollectCurveMetricsList()) {\n                // 折线图数据\n                Result<List<VariousLineChartMetricsVO>> clusterPhyMetricsResult = metricsHandle\n                    .getClusterPhyRelatedCurveMetrics(param, projectId, userName);\n                if (clusterPhyMetricsResult.failed()) {\n                    return Result.buildFrom(clusterPhyMetricsResult);\n                }\n                result = (T) clusterPhyMetricsResult.getData();\n            } else {\n                // 折线图和列表图数据\n                Result<MetricsVO> metricsVoResult = metricsHandle.getOtherClusterPhyRelatedMetricsVO(param, projectId,\n                    userName);\n                if (metricsVoResult.failed()) {\n                    return Result.buildFrom(metricsVoResult);\n                }\n                result = (T) metricsVoResult.getData();\n            }\n\n            return Result.buildSucc(result);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ClusterPhyMetricsManagerImpl||method=getClusterMetricsFromEs||errMsg={}\", e);\n            return Result.buildFail();\n        }\n    }\n\n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getMultiClusterMetrics(MultiMetricsClusterPhyNodeDTO param,\n                                                                          Integer projectId, String userName,\n                                                                          ClusterPhyTypeMetricsEnum metricsTypeEnum) {\n        MetricsClusterPhyNodeDTO phyNodeDTO;\n        if (metricsTypeEnum == ClusterPhyTypeMetricsEnum.NODE) {\n            phyNodeDTO = ConvertUtil.obj2Obj(param, MetricsClusterPhyNodeDTO.class);\n        } else {\n            phyNodeDTO = ConvertUtil.obj2Obj(param, MetricsClusterPhyNodeTaskDTO.class);\n        }\n        if (AriusObjUtils.isEmptyList(param.getNodeNames())) {\n            return getClusterMetricsByMetricsType(phyNodeDTO, projectId, userName, metricsTypeEnum);\n        }\n\n        List<VariousLineChartMetricsVO> result = new ArrayList<>();\n        for (String nodeName : param.getNodeNames()) {\n            try {\n                phyNodeDTO.setNodeName(nodeName);\n                Result<List<VariousLineChartMetricsVO>> nodeMetrics = getClusterMetricsByMetricsType(phyNodeDTO,\n                    projectId, userName, metricsTypeEnum);\n                if (nodeMetrics.success()) {\n                    result.addAll(nodeMetrics.getData());\n                }\n            } catch (Exception e) {\n                LOGGER.warn(\"class=ClusterPhyMetricsManagerImpl||method=getMultiClusterMetrics||errMsg={}\", e);\n            }\n        }\n        return Result.buildSucc(MetricsUtils.joinDuplicateTypeVOs(result));\n    }\n\n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getMultiClusterIndicesMetrics(MultiMetricsClusterPhyIndicesDTO param,\n                                                                          Integer projectId, String userName,\n                                                                          ClusterPhyTypeMetricsEnum metricsTypeEnum){\n        MetricsClusterPhyIndicesDTO phyIndicesDTO = ConvertUtil.obj2Obj(param, MetricsClusterPhyIndicesDTO.class);\n        if(AriusObjUtils.isEmptyList(param.getIndexNames())){\n            return getClusterMetricsByMetricsType(phyIndicesDTO, projectId, userName, metricsTypeEnum);\n        }\n\n        List<VariousLineChartMetricsVO> result = new ArrayList<>();\n        for (String indexName : param.getIndexNames()) {\n            try {\n                phyIndicesDTO.setIndexName(indexName);\n                Result<List<VariousLineChartMetricsVO>> indexMetrics = getClusterMetricsByMetricsType(phyIndicesDTO,\n                        projectId, userName, metricsTypeEnum);\n                if(indexMetrics.success()) {\n                    result.addAll(indexMetrics.getData());\n                }\n            } catch (Exception e) {\n                LOGGER.warn(\"class=ClusterPhyMetricsManagerImpl||method=getMultiClusterIndicesMetrics||errMsg={}\", e);\n            }\n        }\n\n        return Result.buildSucc(MetricsUtils.joinDuplicateTypeVOs(result));\n    }\n\n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getMultiClusterTemplatesMetrics(MultiMetricsClusterPhyTemplateDTO param,\n                                                                                 Integer projectId, String userName,\n                                                                                 ClusterPhyTypeMetricsEnum metricsTypeEnum){\n        MetricsClusterPhyTemplateDTO phyTemplateDTO = ConvertUtil.obj2Obj(param, MetricsClusterPhyTemplateDTO.class);\n        if(AriusObjUtils.isEmptyList(param.getTemplateIdList())){\n            return getClusterMetricsByMetricsType(phyTemplateDTO, projectId, userName, metricsTypeEnum);\n        }\n\n        List<VariousLineChartMetricsVO> result = new ArrayList<>();\n        for (Integer templateId : param.getTemplateIdList()) {\n            try {\n                phyTemplateDTO.setLogicTemplateId(templateId);\n                Result<List<VariousLineChartMetricsVO>> templateMetrics = getClusterMetricsByMetricsType(phyTemplateDTO,\n                        projectId, userName, metricsTypeEnum);\n                if(templateMetrics.success()) {\n                    result.addAll(templateMetrics.getData());\n                }\n            } catch (Exception e) {\n                LOGGER.warn(\"class=ClusterPhyMetricsManagerImpl||method=getMultiClusterTemplatesMetrics||errMsg={}\", e);\n            }\n        }\n\n        return Result.buildSucc(MetricsUtils.joinDuplicateTypeVOs(result));\n    }\n\n    @Override\n    public List<String> listConfigMetricsByCondition(UserConfigInfoDTO userConfigInfoDTO, String userName, Integer projectId) {\n        userConfigInfoDTO.setUserName(userName);\n        userConfigInfoDTO.setProjectId(projectId);\n        userConfigInfoDTO.setConfigType(ConfigTypeEnum.DASHBOARD_AND_METRICS_BOARD.getCode());\n        return userConfigService.getUserConfigByConfigTypeAndUserNameAndProjectId(userConfigInfoDTO);\n    }\n\n    @Override\n    public Result<Integer> updateConfigMetricsByCondition(UserConfigInfoDTO param, String userName, Integer projectId) {\n        param.setUserName(userName);\n        param.setProjectId(projectId);\n        param.setConfigType(ConfigTypeEnum.DASHBOARD_AND_METRICS_BOARD.getCode());\n        Result<Integer> result = userConfigService.updateUserConfigByConfigTypeAndUserNameAndProjectId(param);\n        if (result.failed()) {\n            LOGGER.warn(\"class=ClusterPhyMetricsManagerImpl||method=updateDomainAccountConfigMetrics||errMsg={}\",\n                \"用户指标配置信息更新出错\");\n        }\n        return result;\n    }\n\n    @Override\n    public Result<List<ESClusterTaskDetailVO>> getClusterPhyTaskDetail(String clusterPhyName, String node,\n                                                                       String startTime, String endTime,\n                                                                       Integer projectId) {\n        if (!projectService.checkProjectExist(projectId)) {\n            return Result.buildParamIllegal(String.format(\"There is no project id:%s\", projectId));\n        }\n        return Result.buildSucc(ConvertUtil.list2List(nodeStatsService.getClusterTaskDetail(clusterPhyName, node,\n            Long.parseLong(startTime), Long.parseLong(endTime)), ESClusterTaskDetailVO.class));\n    }\n\n    /**\n     * 获取逻辑集群下的节点，索引，模板信息\n     * @param metricsTypeEnum 类型\n     * @param clusterRegion 逻辑集群关联的region\n     * @return  节点，索引，模板信息 名称集合\n     */\n    private List<String> buildItemsUnderClusterLogic(ClusterPhyTypeMetricsEnum metricsTypeEnum,\n                                                     ClusterRegion clusterRegion) {\n        //节点名称列表\n        if (Objects.equals(metricsTypeEnum, ClusterPhyTypeMetricsEnum.NODE)||Objects.equals(metricsTypeEnum, ClusterPhyTypeMetricsEnum.CLUSTER)) {\n            Result<List<ClusterRoleHost>> result = clusterRoleHostService\n                    .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n            return result.getData().stream().map(ClusterRoleHost::getNodeSet)\n                    .collect(Collectors.toList());\n        }\n        return Lists.newArrayList();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/impl/DashboardMetricsManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.impl;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.component.MetricsValueConvertUtils;\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.DashboardMetricsManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.DashBoardMetricThresholdDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardListDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardTopNDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.config.AriusConfigInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.list.MetricList;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.list.MetricListContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.ClusterPhyHealthMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.config.AriusConfigInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.list.MetricListVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.dashboard.ClusterPhyHealthMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.*;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.SizeUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.DashBoardMetricsService;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.jetbrains.annotations.NotNull;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.*;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.ARIUS_DASHBOARD_THRESHOLD_GROUP;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricThresholdValueNameEnum.getAllDefaultThresholdValue;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricTopTypeEnum.CLUSTER_SHARD_NUM;\n\n/**\n * Created by linyunan on 3/14/22\n */\n@Component\npublic class DashboardMetricsManagerImpl implements DashboardMetricsManager {\n    \n    private static final FutureUtil<Void> futureUtil = FutureUtil.init(\"DashboardMetricsManagerImpl\", 10, 10, 500);\n    \n    @Autowired\n    private ProjectService projectService;\n    \n    @Autowired\n    private DashBoardMetricsService dashBoardMetricsService;\n    \n    @Autowired\n    private AriusConfigInfoService ariusConfigInfoService;\n\n    @Autowired\n    private ESIndexCatService esIndexCatService;\n\n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getTopClusterMetricsInfo(MetricsDashboardTopNDTO param,\n                                                                            Integer projectId) {\n        param.init();\n        String oneLevelType = OneLevelTypeEnum.CLUSTER.getType();\n        return commonGetTopInfoByOneLevelType(param, projectId, oneLevelType);\n    }\n    \n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getTopNodeMetricsInfo(MetricsDashboardTopNDTO param,\n                                                                         Integer projectId) {\n        param.init();\n        String oneLevelType = OneLevelTypeEnum.NODE.getType();\n        return commonGetTopInfoByOneLevelType(param, projectId, oneLevelType);\n    }\n    \n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getTopTemplateMetricsInfo(MetricsDashboardTopNDTO param,\n                                                                             Integer projectId) {\n        param.init();\n        String oneLevelType = OneLevelTypeEnum.TEMPLATE.getType();\n        return commonGetTopInfoByOneLevelType(param, projectId, oneLevelType);\n    }\n    \n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getTopIndexMetricsInfo(MetricsDashboardTopNDTO param,\n                                                                          Integer projectId) {\n        param.init();\n        String oneLevelType = OneLevelTypeEnum.INDEX.getType();\n        return commonGetTopInfoByOneLevelType(param, projectId, oneLevelType);\n    }\n    \n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getTopClusterThreadPoolQueueMetricsInfo(\n            MetricsDashboardTopNDTO param, Integer projectId) {\n        param.init();\n        String oneLevelType = OneLevelTypeEnum.CLUSTER_THREAD_POOL_QUEUE.getType();\n        return commonGetTopInfoByOneLevelType(param, projectId, oneLevelType);\n    }\n    \n    @Override\n    public Result<List<MetricListVO>> getListClusterMetricsInfo(MetricsDashboardListDTO param, Integer projectId) {\n        String oneLevelType = OneLevelTypeEnum.CLUSTER.getType();\n        return commonGetListInfoByOneLevelType(param, projectId, oneLevelType);\n    }\n    \n    @Override\n    public Result<List<MetricListVO>> getListNodeMetricsInfo(MetricsDashboardListDTO param, Integer projectId) {\n        String oneLevelType = OneLevelTypeEnum.NODE.getType();\n        return commonGetListInfoByOneLevelType(param, projectId, oneLevelType);\n    }\n    \n    @Override\n    public Result<List<MetricListVO>> getListTemplateMetricsInfo(MetricsDashboardListDTO param, Integer projectId) {\n        String oneLevelType = OneLevelTypeEnum.TEMPLATE.getType();\n        return commonGetListInfoByOneLevelType(param, projectId, oneLevelType);\n    }\n    \n    @Override\n    public Result<List<MetricListVO>> getListIndexMetricsInfo(MetricsDashboardListDTO param, Integer projectId) {\n        String oneLevelType = OneLevelTypeEnum.INDEX.getType();\n        return commonGetListInfoByOneLevelType(param, projectId, oneLevelType);\n    }\n\n    @Override\n    public List<AriusConfigInfoVO> dashboardThresholds() {\n        List<AriusConfigInfo> ariusConfigInfos = ariusConfigInfoService.getConfigByGroup(ARIUS_DASHBOARD_THRESHOLD_GROUP);\n        return ConvertUtil.list2List(ariusConfigInfos,AriusConfigInfoVO.class);\n    }\n\n    @Override\n    public Result<ClusterPhyHealthMetricsVO> getClusterHealthInfo(Integer projectId) {\n        Result<Void> checkCommonParamResult = checkCommonParam(MetricsConstant.CLUSTER, new BaseDTO(), projectId);\n        if (checkCommonParamResult.failed()) {\n            return Result.buildFrom(checkCommonParamResult);\n        }\n        \n        ClusterPhyHealthMetrics clusterHealthInfo = dashBoardMetricsService.getClusterHealthInfo();\n        // 计算平台各种集群状态的百分比\n        clusterHealthInfo.computePercent();\n        \n        // 格式化 ClusterPhyHealthMetrics 中的异常集群列表\n        ClusterPhyHealthMetricsVO clusterPhyHealthMetricsVO = ConvertUtil.obj2Obj(clusterHealthInfo,\n                ClusterPhyHealthMetricsVO.class);\n        String unknownClusterListStr = clusterHealthInfo.getUnknownClusterListStr();\n        String redClusterListStr = clusterHealthInfo.getRedClusterListStr();\n        String yellowClusterListStr = clusterHealthInfo.getYellowClusterListStr();\n        String greenClusterListStr = clusterHealthInfo.getGreenClusterListStr();\n        \n        clusterPhyHealthMetricsVO.setUnknownClusterList(ListUtils.string2StrList(unknownClusterListStr));\n        clusterPhyHealthMetricsVO.setRedClusterList(ListUtils.string2StrList(redClusterListStr));\n        clusterPhyHealthMetricsVO.setYellowClusterList(ListUtils.string2StrList(yellowClusterListStr));\n        clusterPhyHealthMetricsVO.setGreenClusterList(ListUtils.string2StrList(greenClusterListStr));\n        return Result.buildSucc(clusterPhyHealthMetricsVO);\n    }\n    \n    /***************************************************private**********************************************/\n    /**\n     * @param param        MetricsDashboardTopNDTO\n     * @param projectId    项目\n     * @param oneLevelType OneLevelTypeEnum\n     * @return\n     */\n    private Result<List<VariousLineChartMetricsVO>> commonGetTopInfoByOneLevelType(MetricsDashboardTopNDTO param,\n                                                                                   Integer projectId,\n                                                                                   String oneLevelType) {\n        Result<Void> checkCommonParamResult = checkCommonParam(oneLevelType, param, projectId);\n        if (checkCommonParamResult.failed()) {\n            return Result.buildFrom(checkCommonParamResult);\n        }\n        \n        List<VariousLineChartMetrics> variousLineChartMetrics = dashBoardMetricsService.getToNMetrics(param,\n                oneLevelType);\n\n        // 毛刺点优化\n        MetricsValueConvertUtils.doOptimizeQueryBurrForNodeOrIndicesMetrics(variousLineChartMetrics);\n        \n        return Result.buildSucc(ConvertUtil.list2List(variousLineChartMetrics, VariousLineChartMetricsVO.class));\n    }\n    \n    /**\n     * @param param        MetricsDashboardListDTO\n     * @param projectId    项目\n     * @param oneLevelType OneLevelTypeEnum\n     * @return\n     */\n    private Result<List<MetricListVO>> commonGetListInfoByOneLevelType(MetricsDashboardListDTO param, Integer projectId,\n                                                                       String oneLevelType) {\n        Result<Void> checkCommonParamResult = checkCommonParam(oneLevelType, param, projectId);\n        if (checkCommonParamResult.failed()) {\n            return Result.buildFrom(checkCommonParamResult);\n        }\n        List<String> faultTypeList = DashBoardMetricListTypeEnum.getFaultTypeList();\n        List<String> valueTypeList = DashBoardMetricListTypeEnum.getValueTypeList();\n        List<MetricList> listMetrics = Lists.newCopyOnWriteArrayList();\n        for (String metricsType : param.getMetricsTypes()) {\n            futureUtil.runnableTask(() -> {\n                if (faultTypeList.contains(metricsType)) {\n                    listMetrics.add(\n                            dashBoardMetricsService.getListFaultMetrics(oneLevelType, metricsType, param.getAggType(),\n                                    param.getOrderByDesc()));\n                } else if (valueTypeList.contains(metricsType)) {\n                    listMetrics.add(\n                            dashBoardMetricsService.getListValueMetrics(oneLevelType, metricsType, param.getAggType(),\n                                    param.getOrderByDesc()));\n                }\n            });\n        }\n        futureUtil.waitExecute();\n        //设置索引数量\n        setClusterIndexCount(listMetrics, oneLevelType);\n\n        filterBySystemConfiguration(listMetrics, oneLevelType);\n        return Result.buildSucc(ConvertUtil.list2List(listMetrics, MetricListVO.class));\n    }\n    \n    /**\n     * 根据系统配置筛选\n     */\n    private void filterBySystemConfiguration(List<MetricList> listMetrics, String oneLevelType) {\n        Map<DashBoardMetricListTypeEnum, DashBoardMetricThresholdDTO> thresholdValues = getDashBoardMetricThresholdValues();\n        \n        for (MetricList metric : listMetrics) {\n            DashBoardMetricListTypeEnum key = DashBoardMetricListTypeEnum.valueOfTypeAndOneLevelType(metric.getType(),oneLevelType);\n            final DashBoardMetricThresholdDTO dashBoardMetricThresholdDTO = thresholdValues.get(key);\n            if (Objects.nonNull(dashBoardMetricThresholdDTO)) {\n                DashBoardMetricThresholdDTO thresholdDTO = thresholdValues.get(key);\n                 Double value = Double.parseDouble(String.valueOf(SizeUtil.getDasboardUnitSize(thresholdDTO.getValue().intValue()+thresholdDTO.getUnit().toLowerCase())));\n                \n                metric.setMetricListContents(metric.getMetricListContents().stream()\n                        .filter(Objects::nonNull)\n                        .filter(metricListContent -> metricListContent.getValue() != null)\n                        .filter(metricListContent -> judgeMetricListContent(metricListContent.getValue(),value,thresholdDTO.getCompare()))\n                        .collect(Collectors.toList()));\n            }\n        }\n    }\n\n    /**\n     * 根据符号判断\n     * @param metricValue 统计值\n     * @param configValue 配置值\n     * @param compare 比较单位\n     * @return\n     */\n    private boolean judgeMetricListContent(Double metricValue, Double configValue, String compare) {\n        boolean res = true;\n        if (Objects.isNull(configValue)) {\n            return res;\n        }\n        switch (compare) {\n            case \">\":\n                res = metricValue > configValue;\n                break;\n            case \"<\":\n                res = metricValue < configValue;\n                break;\n            default:\n                break;\n        }\n        return res;\n    }\n\n    /**\n     * 获取dashboard指标阈值\n     *\n     * @return\n     */\n    @NotNull\n    public Map<DashBoardMetricListTypeEnum, DashBoardMetricThresholdDTO> getDashBoardMetricThresholdValues() {\n        Map<DashBoardMetricListTypeEnum, DashBoardMetricThresholdDTO> thresholdValues = new HashMap<>();\n        List<DashBoardMetricThresholdValueNameEnum> thresholdValueNameEnums = getAllDefaultThresholdValue();\n        List<AriusConfigInfo> ariusConfigInfos = ariusConfigInfoService.getConfigByGroup(ARIUS_DASHBOARD_THRESHOLD_GROUP);\n        Map<String,String> ariusConfigInfoMap =ariusConfigInfos.stream().collect(Collectors.toMap(AriusConfigInfo::getValueName,AriusConfigInfo::getValue));\n\n        for (DashBoardMetricThresholdValueNameEnum threshold : thresholdValueNameEnums) {\n\n            DashBoardMetricThresholdDTO thresholdDTO = JSONObject.parseObject(threshold.getDefaultValue(),DashBoardMetricThresholdDTO.class);\n            String configValue = Objects.nonNull(ariusConfigInfoMap.get(threshold.getConfigName()))?ariusConfigInfoMap.get(threshold.getConfigName()):\"\";\n            if (StringUtils.isNotBlank(configValue)){\n                try {\n                    DashBoardMetricThresholdDTO configThreshold = JSONObject.parseObject(configValue,DashBoardMetricThresholdDTO.class);\n                    thresholdDTO.setCompare(configThreshold.getCompare());\n                    thresholdDTO.setUnit(configThreshold.getUnit());\n                    thresholdDTO.setValue(configThreshold.getValue());\n                }catch (Exception e){\n                    continue;\n                }\n        }\n            thresholdValues.put(threshold.getTypeEnum(),thresholdDTO);\n        }\n        return thresholdValues;\n    }\n\n    /**\n     * 合法性检测\n     *\n     * @param oneLevelType OneLevelTypeEnum\n     * @param param        instanceof MetricsDashboardTopNDTO or MetricsDashboardListDTO\n     * @param projectId    项目\n     * @return\n     */\n    private Result<Void> checkCommonParam(String oneLevelType, BaseDTO param, Integer projectId) {\n        if (null == param) {\n            return Result.buildParamIllegal(\"指标项为空\");\n        }\n        \n        if (null == projectId) {\n            return Result.buildParamIllegal(\"projectId is empty\");\n        }\n        \n        if (!projectService.checkProjectExist(projectId)) {\n            return Result.buildParamIllegal(String.format(\"There is no projectId:%s\", projectId));\n        }\n        \n        if (param instanceof MetricsDashboardTopNDTO) {\n            MetricsDashboardTopNDTO metricsDashboardTopNDTO = (MetricsDashboardTopNDTO) param;\n            \n            if (CollectionUtils.isEmpty(metricsDashboardTopNDTO.getMetricsTypes())) {\n                return Result.buildParamIllegal(\"指标项为空\");\n            }\n            for (String metricsType : metricsDashboardTopNDTO.getMetricsTypes()) {\n                if (!DashBoardMetricTopTypeEnum.hasExist(oneLevelType, metricsType)) {\n                    return Result.buildParamIllegal(String.format(\"TopN类型指标项[%s]不存在\", metricsType));\n                }\n            }\n        }\n        \n        if (param instanceof MetricsDashboardListDTO) {\n            MetricsDashboardListDTO metricsDashboardListDTO = (MetricsDashboardListDTO) param;\n            \n            if (CollectionUtils.isEmpty(metricsDashboardListDTO.getMetricsTypes())) {\n                return Result.buildParamIllegal(\"指标项为空\");\n            }\n            for (String metricsType : metricsDashboardListDTO.getMetricsTypes()) {\n                if (!DashBoardMetricListTypeEnum.hasExist(oneLevelType, metricsType)) {\n                    return Result.buildParamIllegal(String.format(\"列表类型指标项[%s]不存在\", metricsType));\n                }\n            }\n        }\n        \n        return Result.buildSucc();\n    }\n    \n    private <R> R conversionType(String value, Function<String, R> convertFunc, String errMsg)\n            throws AdminOperateException {\n        try {\n            return convertFunc.apply(value);\n        } catch (Exception e) {\n            throw new AdminOperateException(errMsg);\n        }\n    }\n\n    /**\n     * 当为dashboard的shard数的时候，设置indexCount\n     * @param listMetrics\n     * @param oneLevelType\n     */\n    private void setClusterIndexCount(List<MetricList> listMetrics, String oneLevelType) {\n        if (CollectionUtils.isEmpty(listMetrics)){\n            return;\n        }\n        final List<String> clusterPhyList = listMetrics.stream()\n                .filter(v -> CLUSTER_SHARD_NUM.getType().equals(v.getType()) && oneLevelType.equals(\n                        CLUSTER_SHARD_NUM.getOneLevelTypeEnum().getType())).map(MetricList::getMetricListContents)\n                .flatMap(Collection::stream).map(MetricListContent::getClusterPhyName).filter(StringUtils::isNotBlank)\n                .distinct().collect(Collectors.toList());\n        final Map</*clusterPhy*/String,/*index count*/ Integer> ClusterPhy2CountMap =\n                esIndexCatService.syncGetByClusterPhyList(clusterPhyList);\n\n\n\n        listMetrics.stream()\n               .filter(v -> CLUSTER_SHARD_NUM.getType().equals(v.getType()) && oneLevelType.equals(\n                        CLUSTER_SHARD_NUM.getOneLevelTypeEnum().getType()))\n                .map(MetricList::getMetricListContents)\n                .flatMap(Collection::stream)\n\n                .forEach(metricsContent->metricsContent.setIndexCount(ClusterPhy2CountMap.getOrDefault(metricsContent.getClusterPhyName(),0).longValue()));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/impl/GatewayMetricsManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.impl;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport com.didichuxing.datachannel.arius.admin.biz.gateway.GatewayManager;\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.GatewayMetricsManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplateLogicManager;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.GlobalParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.GatewayOverviewMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContentCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.gateway.GatewayOverviewMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.GatewayMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.MetricsConstant;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.GatewayMetricsService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\n\n@Component\npublic class GatewayMetricsManagerImpl implements GatewayMetricsManager {\n\n    private static final ILog     LOGGER  = LogFactory.getLog(GatewayMetricsManagerImpl.class);\n\n    private static final String   COMMON  = \"common\";\n    private static final String   WRITE   = \"write\";\n    private static final String   SEARCH  = \"search\";\n    private static final Long             ONE_DAY     = 24 * 60 * 60 * 1000L;\n    private static final FutureUtil<Void> FUTURE_UTIL = FutureUtil.init(\"GatewayMetricsManagerImpl\", 10, 10, 500);\n    @Autowired\n    private              GatewayMetricsService gatewayMetricsService;\n\n    @Autowired\n    private GatewayManager        gatewayManager;\n\n    @Autowired\n    private ProjectService        projectService;\n\n    @Autowired\n    private TemplateLogicManager  templateLogicManager;\n\n    @Override\n    public Result<List<String>> getGatewayMetricsEnums(String group) {\n        return Result.buildSucc(GatewayMetricsTypeEnum.getMetricsByGroup(group));\n    }\n\n    @Override\n    public Result<List<String>> getDslMd5List(Integer projectId, Long startTime, Long endTime) {\n        projectId = projectId != null ? projectId : GlobalParam.CURRENT_PROJECT_ID.get();\n        if (endTime == null) {\n            endTime = System.currentTimeMillis();\n        }\n        if (startTime == null) {\n            startTime = endTime - ONE_DAY;\n        }\n        //超过一周时间容易引起熔断，不允许\n        if ((endTime - startTime) > ONE_DAY * 7) {\n            return Result.buildFail(\"时间跨度不要超过一周\");\n\n        }\n        return Result.buildSucc(gatewayMetricsService.getDslMd5List(startTime, endTime, projectId));\n    }\n\n    @Override\n    public Result<List<GatewayOverviewMetricsVO>> getGatewayOverviewMetrics(GatewayOverviewDTO dto) {\n        List<GatewayOverviewMetrics> result = Lists.newCopyOnWriteArrayList();\n        List<String> rawMetricsTypes = new ArrayList<>(dto.getMetricsTypes());\n        Long startTime = dto.getStartTime();\n        Long endTime = dto.getEndTime();\n        //commonMetrics 只需要查一次， 就可以查出来若干个指标， 一个DSL搞定。\n        List<String> commonMetrics = dto.getMetricsTypes().stream()\n            .filter(GatewayMetricsTypeEnum.commonOverviewMetrics::contains).collect(Collectors.toList());\n\n        if (!commonMetrics.isEmpty()) {\n            dto.getMetricsTypes().removeAll(commonMetrics);\n            dto.getMetricsTypes().add(COMMON);\n        }\n        //写入指标也可以一次性查出来。\n        List<String> writeMetrics = dto.getMetricsTypes().stream()\n            .filter(GatewayMetricsTypeEnum.writeOverviewMetrics::contains).collect(Collectors.toList());\n\n        if (!writeMetrics.isEmpty()) {\n            dto.getMetricsTypes().removeAll(writeMetrics);\n            dto.getMetricsTypes().add(WRITE);\n        }\n\n        dto.getMetricsTypes().parallelStream().forEach(metricsType -> {\n            if (COMMON.equals(metricsType)) {\n                List<GatewayOverviewMetrics> overviewCommonMetrics = gatewayMetricsService\n                    .getOverviewCommonMetrics(commonMetrics, startTime, endTime);\n                result.addAll(overviewCommonMetrics);\n            } else if (WRITE.equals(metricsType)) {\n                List<GatewayOverviewMetrics> overviewWriteMetrics = gatewayMetricsService\n                    .getOverviewWriteMetrics(writeMetrics, startTime, endTime);\n                result.addAll(overviewWriteMetrics);\n            } else if (GatewayMetricsTypeEnum.READ_DOC_COUNT.getType().equals(metricsType)) {\n                GatewayOverviewMetrics overviewRequestTypeMetrics = gatewayMetricsService\n                    .getOverviewReadCountMetrics(startTime, endTime);\n                result.add(overviewRequestTypeMetrics);\n            } else if (GatewayMetricsTypeEnum.QUERY_SEARCH_TYPE.getType().equals(metricsType)) {\n                GatewayOverviewMetrics overviewSearchTypeMetrics = gatewayMetricsService\n                    .getOverviewSearchTypeMetrics(startTime, endTime);\n                result.add(overviewSearchTypeMetrics);\n            }\n        });\n\n        //补充没有数据的指标\n        List<Long> timeRange = getTimeRange(startTime, endTime);\n        List<MetricsContentCell> list = timeRange.stream().map(e -> new MetricsContentCell(0.0, e))\n            .collect(Collectors.toList());\n        List<String> currentMetrics = result.stream().map(GatewayOverviewMetrics::getType).collect(Collectors.toList());\n\n        rawMetricsTypes.stream().filter(x -> !currentMetrics.contains(x)).forEach(x -> {\n            GatewayOverviewMetrics metrics = new GatewayOverviewMetrics();\n            metrics.setType(x);\n            metrics.setMetrics(list);\n            result.add(metrics);\n        });\n        for (GatewayOverviewMetrics metrics : result) {\n            if (metrics.getMetrics() == null || metrics.getMetrics().isEmpty()) {\n                metrics.setMetrics(list);\n            }\n        }\n        sortByList(rawMetricsTypes, result);\n\n        return Result.buildSucc(ConvertUtil.list2List(result, GatewayOverviewMetricsVO.class));\n    }\n\n    \n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getMultiGatewayNodesMetrics(MultiGatewayNodesDTO dto,\n                                                                               Integer projectId) {\n        List<VariousLineChartMetricsVO> result = new ArrayList<>();\n        GatewayNodeDTO gatewayNodeDTO = ConvertUtil.obj2Obj(dto, GatewayNodeDTO.class);\n        if (AriusObjUtils.isEmptyList(dto.getNodeIps())) {\n            return getGatewayNodeMetrics(gatewayNodeDTO, projectId);\n        }\n\n        for (String nodeIp : dto.getNodeIps()) {\n            try {\n                gatewayNodeDTO.setNodeIp(nodeIp);\n                Result<List<VariousLineChartMetricsVO>> nodeMetrics = getGatewayNodeMetrics(gatewayNodeDTO,\n                    getProjectIdIsNotAdmin(projectId));\n                if (nodeMetrics.success()) {\n                    result.addAll(nodeMetrics.getData());\n                }\n            } catch (Exception e) {\n                LOGGER.warn(\"class=GatewayMetricsManagerImpl||method=getMultiGatewayNodesMetrics||errMsg={}\", e);\n            }\n        }\n        return Result.buildSucc(MetricsUtils.joinDuplicateTypeVOs(result));\n    }\n    \n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getClientNodeMetrics(ClientNodeDTO dto, Integer projectId) {\n        final List<VariousLineChartMetrics> result = commonGetTopInfoByOneLevelType(dto, projectId,\n                MetricsConstant.CLIENT_NODE);\n        List<String> rawMetricsTypes = dto.getMetricsTypes();\n        Long startTime = dto.getStartTime();\n        Long endTime = dto.getEndTime();\n        // 补齐数据用的\n         List<String> clientNodeIpList = Lists.newArrayList();\n        if (StringUtils.isNotBlank(dto.getClientNodeIp())) {\n            clientNodeIpList.add(dto.getClientNodeIp());\n        } else {\n            gatewayMetricsService.getEsClientNodeIpListByGatewayNode(dto.getNodeIp(), dto.getStartTime(),\n                dto.getEndTime(), getProjectIdIsNotAdmin(projectId)).stream().map(Tuple::getV2)\n                .forEach(clientNodeIpList::add);\n        }\n        fillSortData(result, rawMetricsTypes, clientNodeIpList, startTime, endTime, dto.getTopNu());\n        return Result.buildSucc(ConvertUtil.list2List(result, VariousLineChartMetricsVO.class));\n    }\n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getGatewayNodeMetrics(GatewayNodeDTO dto, Integer projectId) {\n        List<String> rawMetricsTypes = dto.getMetricsTypes();\n        Long startTime = dto.getStartTime();\n        Long endTime = dto.getEndTime();\n        final List<VariousLineChartMetrics> result = commonGetTopInfoByOneLevelType(dto, projectId, MetricsConstant.NODE);\n        // 补齐数据用的\n        List<String> nameList = Lists.newArrayList();\n        if (StringUtils.isNotBlank(dto.getNodeIp())) {\n            nameList.add(dto.getNodeIp());\n        } else {\n            // 获取nodeNameList\n            nameList.addAll(gatewayManager.getGatewayAliveNodeNames(\"Normal\").getData());\n        }\n        fillSortData(result, rawMetricsTypes, nameList, startTime, endTime, dto.getTopNu());\n        return Result.buildSucc(ConvertUtil.list2List(result, VariousLineChartMetricsVO.class));\n    }\n    \n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getGatewayIndexMetrics(GatewayIndexDTO dto, Integer projectId) {\n        List<String> rawMetricsTypes = Lists.newArrayList(dto.getMetricsTypes());\n        Long startTime = dto.getStartTime();\n        Long endTime = dto.getEndTime();\n        // 补齐数据用的\n        List<String> nameList = Lists.newArrayList();\n        List<VariousLineChartMetrics> result = commonGetTopInfoByOneLevelType(dto, projectId, MetricsConstant.INDEX);\n        if (StringUtils.isNotBlank(dto.getIndexName())) {\n            nameList.add(dto.getIndexName());\n        } else {\n            // 补齐数据\n            nameList.addAll(templateLogicManager.getTemplateLogicNames(projectId));\n        }\n        fillSortData(result, rawMetricsTypes, nameList, startTime, endTime, dto.getTopNu() == 0 ? 1 : dto.getTopNu());\n        return Result.buildSucc(ConvertUtil.list2List(result, VariousLineChartMetricsVO.class));}\n\n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getGatewayAppMetrics(GatewayProjectDTO dto) {\n        List<VariousLineChartMetrics> result = commonGetTopInfoByOneLevelType(dto, dto.getGroup());\n        List<String> rawMetricsTypes = dto.getMetricsTypes();\n        Long startTime = dto.getStartTime();\n        Long endTime = dto.getEndTime();    // 补齐数据用的\n        List<String> nameList = Lists.newArrayList();\n        if (StringUtils.isNotBlank(dto.getProjectId())) {\n            nameList.add(dto.getProjectId());\n        } else {\n            // 获取所有projectid\n            List<String> projectIds = projectService.getProjectBriefList().stream().map(ProjectBriefVO::getId)\n                    .map(String::valueOf).collect(Collectors.toList());\n            nameList.addAll(projectIds);\n        }\n        fillSortData(result, rawMetricsTypes, nameList, startTime, endTime, dto.getTopNu() == 0 ? 1 : dto.getTopNu());\n        return Result.buildSucc(ConvertUtil.list2List(result, VariousLineChartMetricsVO.class));\n    \n    }\n    \n    @Override\n    public Result<List<VariousLineChartMetricsVO>> getGatewayDslMetrics(GatewayDslDTO dto, Integer projectId) {\n        List<String> rawMetricsTypes = dto.getMetricsTypes();\n        Long startTime = dto.getStartTime();\n        Long endTime = dto.getEndTime();\n        // 补齐数据用的\n        List<String> nameList = Lists.newArrayList();\n        if (StringUtils.isNotBlank(dto.getDslMd5())) {\n            nameList.add(dto.getDslMd5());\n        } else {          // 获取所有dslMD5\n            nameList.addAll(getDslMd5List(projectId, null, null).getData());\n        }\n        List<VariousLineChartMetrics> result = commonGetTopInfoByOneLevelType(dto, projectId,\n                MetricsConstant.DSL);    // 获取\n        fillSortData(result, rawMetricsTypes, nameList, startTime, endTime, dto.getTopNu() == 0 ? 1 : dto.getTopNu());\n        return Result.buildSucc(ConvertUtil.list2List(result, VariousLineChartMetricsVO.class));\n    }\n\n    @Override\n    public Result<List<Tuple<String, String>>> getClientNodeIdList(String gatewayNode, Long startTime, Long endTime,\n                                                                   Integer projectId) {\n        long oneHour = 60 * 60 * 1000L;\n        if (endTime == null) {\n            endTime = System.currentTimeMillis();\n        }\n        if (startTime == null) {\n            startTime = endTime - oneHour;\n        }\n        // 超过一周时间容易引起熔断，不允许\n        if ((endTime - startTime) > oneHour * 24 * 7) {\n            return Result.buildFail(\"时间跨度不要超过一周\");\n        }\n        return Result.buildSucc(\n            gatewayMetricsService.getEsClientNodeIpListByGatewayNode(gatewayNode, startTime, endTime, getProjectIdIsNotAdmin(projectId)));\n    }\n\n    /********************************************************** private methods **********************************************************/\n    /**\n     * 填充没有数据的指标和缺失的指标\n     * @param result 返回的结果\n     * @param rawMetricsTypes 所有指标type\n     * @param nameList 待添加展示空数据的线条nameList\n     * @param startTime 时间段start\n     * @param endTime 时间段end\n     * @param topN 获取线条个数\n     */\n    private void fillSortData(List<VariousLineChartMetrics> result, List<String> rawMetricsTypes, List<String> nameList,\n                              long startTime, long endTime, Integer topN) {\n        List<String> currentMetrics = result.stream().map(VariousLineChartMetrics::getType)\n            .collect(Collectors.toList());\n        // 获取指标展示时间分段信息\n        List<Long> timeRange = getTimeRange(startTime, endTime);\n        // 让时间节点由小到大 getTimeRange 获取默认是大到小\n        Collections.reverse(timeRange);\n        List<MetricsContentCell> list = timeRange.stream().map(e -> new MetricsContentCell(0.0, e))\n            .collect(Collectors.toList());\n\n        // 补充没有数据的指标（三个指标，但是result只有两个指标的数据）\n        rawMetricsTypes.stream().filter(x -> !currentMetrics.contains(x)).forEach(x -> {\n            VariousLineChartMetrics metrics = new VariousLineChartMetrics();\n            metrics.setType(x);\n            metrics.setMetricsContents(Lists.newArrayList());\n            result.add(metrics);\n        });\n\n        // 补充某个指标下，折线展示不全的问题（某个指标下，一共有5条折线数据可展示，用户想要展示top3，但是返回只有2个数据，所以要补齐另3个）\n        for (VariousLineChartMetrics metrics : result) {\n            // 补齐当前指标类型下，某数据的时间段数据不齐全（时间段有k个，但是数据个数<k）\n            List<MetricsContent> metricsContentList = metrics.getMetricsContents();\n            for (MetricsContent metricsContent : metricsContentList) {\n                // 补齐剩下的时间段数据\n                for (int i = metricsContent.getMetricsContentCells().size(); i < timeRange.size(); i++) {\n                    metricsContent.getMetricsContentCells().add(new MetricsContentCell(0.0, timeRange.get(i)));\n                }\n            }\n\n            if (metrics.getMetricsContents().size() >= topN) {\n                // 如果达到了用户所需展示的个数\n                continue;\n            }\n\n            // 不达到用户所需展示的个数，补齐缺少的\n            int cnt = topN - metrics.getMetricsContents().size();\n            // 获取该指标类型下有数据的线条name集合\n            Set<String> hasDataNameSet = metrics.getMetricsContents().stream().map(MetricsContent::getName)\n                .collect(Collectors.toSet());\n            // 过滤掉有数据的线条name\n            nameList = nameList.stream().filter(x -> !hasDataNameSet.contains(x)).collect(Collectors.toList());\n            for (int i = 0; i < cnt && i < nameList.size(); i++) {\n                MetricsContent content = new MetricsContent();\n                content.setName(nameList.get(i));\n                content.setMetricsContentCells(list);\n                metrics.getMetricsContents().add(content);\n            }\n        }\n        // 根据前端传过来的指标展示顺序进行排序\n        result.sort(((o1, o2) -> {\n            int io1 = rawMetricsTypes.indexOf(o1.getType());\n            int io2 = rawMetricsTypes.indexOf(o2.getType());\n            return io1 - io2;\n        }));\n    }\n\n    private List<Long> getTimeRange(Long startTime, Long endTime) {\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n        List<Long> timeRange;\n        if (MetricsUtils.Interval.ONE_MIN.getStr().equals(interval)) {\n            timeRange = MetricsUtils.timeRange(startTime, endTime, 1L, Calendar.MINUTE);\n        } else if (MetricsUtils.Interval.TWENTY_MIN.getStr().equals(interval)) {\n            timeRange = MetricsUtils.timeRange(startTime, endTime, 20L, Calendar.MINUTE);\n        } else if (MetricsUtils.Interval.ONE_HOUR.getStr().equals(interval)) {\n            timeRange = MetricsUtils.timeRange(startTime, endTime, 1L, Calendar.HOUR);\n        } else {\n            timeRange = MetricsUtils.timeRange(startTime, endTime, 1L, Calendar.MINUTE);\n        }\n        return timeRange;\n    }\n\n    /**\n     * 根据orderList的顺序，排序targetList\n     * @param orderList\n     * @param targetList\n     */\n    private void sortByList(List<String> orderList, List<GatewayOverviewMetrics> targetList) {\n        targetList.sort(((o1, o2) -> {\n            int io1 = orderList.indexOf(o1.getType());\n            int io2 = orderList.indexOf(o2.getType());\n            return io1 - io2;\n        }));\n    }\n    \n    /**\n     * 通过指定的{@link GatewayMetricsTypeEnum#getGroup()} 进行匹配 * * * @param dto dto * @param projectId 应用程序id * @param groupType\n     * {@link GatewayMetricsTypeEnum#getGroup()} * @return {@link List}<{@link VariousLineChartMetrics}>\n     */\n    private <T extends GatewayMetricsDTO> List<VariousLineChartMetrics> commonGetTopInfoByOneLevelType(T dto,\n                                                                                                       Integer projectId,\n                                                                                                       String groupType) {\n        List<String> rawMetricsTypes = dto.getMetricsTypes().stream().distinct().collect(Collectors.toList());\n        if (CollectionUtils.isEmpty(rawMetricsTypes)) {\n            return Collections.emptyList();\n        }\n        List<VariousLineChartMetrics> result = Lists.newCopyOnWriteArrayList();\n        for (String metricsType : rawMetricsTypes) {\n            final Optional<GatewayMetricsTypeEnum> metricsTypeEnumOptional = getEnumByTypeAndGroupOptional(groupType,\n                    metricsType);\n            if (!metricsTypeEnumOptional.isPresent()) {\n                return Collections.emptyList();\n            }\n            FUTURE_UTIL.runnableTask(() -> gatewayMetricsService.getTopNMetrics(getProjectIdIsNotAdmin(projectId), dto,\n                    metricsTypeEnumOptional.get()).filter(CollectionUtils::isNotEmpty).ifPresent(result::addAll));\n        }\n        FUTURE_UTIL.waitExecute();\n        return result;\n    }\n    \n    /**\n     * 通过指定的\n     * {@link GatewayMetricsTypeEnum#getGroup()}\n     * 进行匹配 *\n     * @param dto dto\n     * @param groupType\n     * {@linkplain  GatewayMetricsTypeEnum group} * @return {@link List}<{@link VariousLineChartMetrics}>\n     */\n    private <T extends GatewayMetricsDTO> List<VariousLineChartMetrics> commonGetTopInfoByOneLevelType(T dto,\n                                                                                                       String groupType) {\n        List<String> rawMetricsTypes = dto.getMetricsTypes().stream().distinct().collect(Collectors.toList());\n        if (CollectionUtils.isEmpty(rawMetricsTypes)) {\n            return Collections.emptyList();\n        }\n        List<VariousLineChartMetrics> result = Lists.newCopyOnWriteArrayList();\n        for (String metricsType : rawMetricsTypes) {\n            final Optional<GatewayMetricsTypeEnum> metricsTypeEnumOptional = getEnumByTypeAndGroupOptional(groupType,\n                    metricsType);\n            if (!metricsTypeEnumOptional.isPresent()) {\n                return Collections.emptyList();\n            }\n            FUTURE_UTIL.runnableTask(() -> gatewayMetricsService.getTopNMetrics(dto, metricsTypeEnumOptional.get())\n                    .filter(CollectionUtils::isNotEmpty).ifPresent(result::addAll));\n        }\n        FUTURE_UTIL.waitExecute();\n        return result;\n    }\n    \n    private Optional<GatewayMetricsTypeEnum> getEnumByTypeAndGroupOptional(String groupType, String metricsType) {\n        return Arrays.stream(GatewayMetricsTypeEnum.values())\n                .filter(enumValue -> enumValue.getType().equals(metricsType) && enumValue.getGroup().equals(groupType))\n                .findFirst();\n    }\n\n    private Integer getProjectIdIsNotAdmin(Integer projectId) {\n        return !AuthConstant.SUPER_PROJECT_ID.equals(projectId) ? projectId : null;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/metrics/impl/MetricsDictionaryManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.MetricsDictionaryManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricDictionaryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.dictionary.MetricsDictionaryVO;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.metrics.MetricsDictionaryService;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName MetricsDictionaryManagerImpl\n * @Author gyp\n * @Date 2022/9/28\n * @Version 1.0\n */\n@Component\npublic class MetricsDictionaryManagerImpl implements MetricsDictionaryManager {\n    @Autowired\n    private MetricsDictionaryService metricsDictionaryService;\n\n    \n    @Override\n    public Result<List<MetricsDictionaryVO>> listByCondition(MetricDictionaryDTO param) {\n        return Result.buildSucc(ConvertUtil.list2List(metricsDictionaryService.listByCondition(param), MetricsDictionaryVO.class));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/AbstractPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-27\n */\npublic abstract class AbstractPageSearchHandle<T extends PageDTO, R> implements BaseHandle {\n    protected final ILog     LOGGER = LogFactory.getLog(this.getClass());\n    @Autowired\n    protected ProjectService projectService;\n\n    /**\n     * 处理模糊分页查询\n     * @param condition     查询条件\n     * @param projectId       项目\n     * @return            PaginationResult<R>\n     */\n    public PaginationResult<R> doPage(T condition, Integer projectId) {\n        Result<Boolean> validCheckForConditionResult = baseCheckCondition(condition, projectId);\n        if (validCheckForConditionResult.failed()) {\n            return PaginationResult.buildParamIllegal(validCheckForConditionResult.getMessage());\n        }\n\n        initCondition(condition, projectId);\n\n        return buildPageData(condition, projectId);\n    }\n\n    /**\n     * 校验模糊查询的实体参数合法性\n     *\n     * @param condition 带分页信息的条件查询实体\n     * @param projectId\n     * @return Result<Boolean>\n     */\n    protected Result<Boolean> baseCheckCondition(T condition, Integer projectId) {\n        if (AriusObjUtils.isNull(projectId) || !projectService.checkProjectExist(projectId)) {\n            return Result.buildParamIllegal(\"项目不存在\");\n        }\n        if (AriusObjUtils.isNull(condition)) {\n            return Result.buildParamIllegal(\"查询参数不存在\");\n        }\n        return checkCondition(condition, projectId);\n    }\n\n    /**\n     * 校验模糊查询的实体参数合法性\n     *\n     * @param condition 带分页信息的条件查询实体\n     * @param projectId\n     * @return Result<Boolean>\n     */\n    protected abstract Result<Boolean> checkCondition(T condition, Integer projectId);\n\n    /**\n     * 初始化条件\n     *\n     * @param condition 条件\n     * @param projectId     应用程序id\n     */\n    protected abstract void initCondition(T condition, Integer projectId);\n\n    /**\n     * 获取模糊查询结果\n     *\n     * @param condition 带分页信息的条件查询实体\n     * @param projectId   项目\n     * @return PaginationResult<R>   需要构建的分页结果\n     */\n    protected abstract PaginationResult<R> buildPageData(T condition, Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/ClusterLogicPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.common.Triple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterLogicVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.SortConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.math.BigDecimal;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * Created by linyunan on 2021-10-14\n */\n@Component\npublic class ClusterLogicPageSearchHandle extends AbstractPageSearchHandle<ClusterLogicConditionDTO, ClusterLogicVO> {\n    private static final ILog             LOGGER                  = LogFactory\n        .getLog(ClusterLogicPageSearchHandle.class);\n\n    @Autowired\n    private ClusterLogicService           clusterLogicService;\n\n  \n\n    @Autowired\n    private ClusterRegionService          clusterRegionService;\n\n    @Autowired\n    private ESClusterNodeService          eSClusterNodeService;\n\n\n\n    /**\n     * 1. 设置项目名称\n     * 2. 关联物理集群标识\n     * 3. 集群版本\n     *\n     * @param clusterLogicVO 逻辑集群源信息\n     */\n    private void setClusterLogicBasicInfo(ClusterLogicVO clusterLogicVO) {\n        if (null == clusterLogicVO) {\n            return;\n        }\n        setDiskUsedInfo(clusterLogicVO);\n    }\n\n    private void setDiskUsedInfo(ClusterLogicVO clusterLogicVO) {\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogicVO.getId());\n        long diskTotal = 0L;\n        long diskUsage = 0L;\n        if (clusterRegion != null) {\n            Map<String, Triple<Long, Long, Double>> map = eSClusterNodeService\n                .syncGetNodesDiskUsage(clusterRegion.getPhyClusterName());\n            Set<Map.Entry<String, Triple<Long, Long, Double>>> entries = map.entrySet();\n            for (Map.Entry<String, Triple<Long, Long, Double>> entry : entries) {\n                diskTotal += entry.getValue().v1();\n                diskUsage += entry.getValue().v2();\n            }\n        }\n        clusterLogicVO.setDiskTotal(diskTotal);\n        clusterLogicVO.setDiskUsage(diskUsage);\n        clusterLogicVO.setDiskUsagePercent(\n            new BigDecimal((double) diskUsage / diskTotal).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());\n    }\n\n    @Override\n    protected Result<Boolean> checkCondition(ClusterLogicConditionDTO clusterLogicConditionDTO, Integer projectId) {\n\n        Integer status = clusterLogicConditionDTO.getHealth();\n        if (null != status && !ClusterHealthEnum.isExitByCode(status)) {\n            return Result.buildParamIllegal(\"逻辑集群状态类型不存在\");\n        }\n\n        if (null != clusterLogicConditionDTO.getType()\n            && !ClusterResourceTypeEnum.isExist(clusterLogicConditionDTO.getType())) {\n            return Result.buildParamIllegal(\"逻辑集群类型不存在\");\n        }\n\n        if (null != clusterLogicConditionDTO.getProjectId()\n            && !projectService.checkProjectExist(clusterLogicConditionDTO.getProjectId())) {\n            return Result.buildParamIllegal(\"逻辑集群所属项目不存在\");\n        }\n\n        String clusterLogicName = clusterLogicConditionDTO.getName();\n        if (!AriusObjUtils.isBlack(clusterLogicName)\n            && (clusterLogicName.startsWith(\"*\") || clusterLogicName.startsWith(\"?\"))) {\n            return Result.buildParamIllegal(\"逻辑集群名称不允许带类似*, ?等通配符查询\");\n        }\n\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    protected void initCondition(ClusterLogicConditionDTO condition, Integer projectId) {\n        if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            // 非超级管理员，获取拥有的逻辑集群对应的物理集群列表\n            condition.setProjectId(projectId);\n        }\n        String sortTerm = null == condition.getSortTerm() ? SortConstant.ID : condition.getSortTerm();\n        String sortType = condition.getOrderByDesc() ? SortConstant.DESC : SortConstant.ASC;\n        condition.setSortTerm(sortTerm);\n        condition.setSortType(sortType);\n        condition.setFrom((condition.getPage() - 1) * condition.getSize());\n    }\n\n    @Override\n    protected PaginationResult<ClusterLogicVO> buildPageData(ClusterLogicConditionDTO condition, Integer projectId) {\n        if(StringUtils.isNotBlank(condition.getMemo())){\n            condition.setMemo(CommonUtils.sqlFuzzyQueryTransfer(condition.getMemo()));\n        }\n        List<ClusterLogic> pagingGetClusterLogicList = clusterLogicService.pagingGetClusterLogicByCondition(condition);\n        List<ClusterLogicVO> clusterLogicVOS = ConvertUtil.list2List(pagingGetClusterLogicList,ClusterLogicVO.class);\n        long totalHit = clusterLogicService.fuzzyClusterLogicHitByCondition(condition);\n        return PaginationResult.buildSucc(clusterLogicVOS, totalHit, condition.getPage(), condition.getSize());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/ClusterPhyPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterPhyVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.SortConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.SortTermEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.resource.ClusterPhyEvent;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n *\n * @author ohushenglin_v\n * @date 2022-05-27\n */\n@Component\npublic class ClusterPhyPageSearchHandle extends AbstractPageSearchHandle<ClusterPhyConditionDTO, ClusterPhyVO> {\n\n    private static final ILog           LOGGER         = LogFactory.getLog(ClusterPhyPageSearchHandle.class);\n    private static final CharSequence[] CHAR_SEQUENCES = { \"*\", \"?\" };\n    \n\n   \n    @Autowired\n    private ClusterLogicService         clusterLogicService;\n    @Autowired\n    private ClusterPhyManager           clusterPhyManager;\n    @Autowired\n    private ClusterRegionService        clusterRegionService;\n\n   \n    \n    @PostConstruct\n    private void init() {\n    }\n\n    @Override\n    protected Result<Boolean> checkCondition(ClusterPhyConditionDTO condition, Integer projectId) {\n\n        Integer status = condition.getHealth();\n        if (null != status && !ClusterHealthEnum.isExitByCode(status)) {\n            return Result.buildParamIllegal(\"集群状态类型不存在\");\n        }\n\n        String clusterPhyName = condition.getCluster();\n        if (StringUtils.containsAny(clusterPhyName, CHAR_SEQUENCES)) {\n            return Result.buildParamIllegal(\"物理集群名称不允许带类似*, ?等通配符查询\");\n        }\n\n        if (null != condition.getSortTerm() && !SortTermEnum.isExit(condition.getSortTerm())) {\n            return Result.buildParamIllegal(String.format(\"暂且不支持排序字段[%s]\", condition.getSortTerm()));\n        }\n\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    protected void initCondition(ClusterPhyConditionDTO condition, Integer projectId) {\n        List<String> clusterNames = null;\n        Integer queryProjectId = null;\n        String logicClusterName = condition.getLogicClusterName();\n        if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            // 非超级管理员，获取拥有的逻辑集群对应的物理集群列表\n            queryProjectId = projectId;\n        }\n        List<ClusterLogic> clusterLogicList = null;\n        if (StringUtils.isNotBlank(logicClusterName) || null != queryProjectId) {\n            //根据项目ID或者集群名称获取逻辑集群，当项目为超级项目时不需要传入项目ID\n            clusterLogicList = clusterLogicService.listClusterLogicByProjectIdAndName(queryProjectId, logicClusterName);\n            clusterNames = Lists.newArrayList();\n        }\n        if (CollectionUtils.isNotEmpty(clusterLogicList)) {\n            //项目下的有管理权限逻辑集群会关联多个物理集群\n            List<ClusterRegion> regions = clusterRegionService.getClusterRegionsByLogicIds(\n                clusterLogicList.stream().map(ClusterLogic::getId).collect(Collectors.toList()));\n            clusterNames = regions.stream().map(ClusterRegion::getPhyClusterName).distinct()\n                .collect(Collectors.toList());\n        }\n        if (null != clusterNames) {\n            //这里默认给个空字符串，确保没有查询到逻辑集群的查询条件下无法查询出数据\n            clusterNames.add(\"\");\n            condition.setClusterNames(clusterNames);\n        }\n        String sortTerm = null == condition.getSortTerm() ? SortConstant.ID : condition.getSortTerm();\n        String sortType = condition.getOrderByDesc() ? SortConstant.DESC : SortConstant.ASC;\n        condition.setSortTerm(sortTerm);\n        condition.setSortType(sortType);\n        condition.setFrom((condition.getPage() - 1) * condition.getSize());\n    }\n\n    @Override\n    protected PaginationResult<ClusterPhyVO> buildPageData(ClusterPhyConditionDTO condition, Integer projectId) {\n\n        List<ClusterPhy> pagingGetClusterPhyList = clusterPhyManager.pagingGetClusterPhyByCondition(condition);\n\n        List<ClusterPhyVO> clusterPhyVOList = clusterPhyManager.buildClusterInfo(pagingGetClusterPhyList);\n\n        long totalHit = clusterPhyManager.fuzzyClusterPhyHitByCondition(condition);\n        List<ClusterPhyVO> clusterPhyList = clusterPhyVOList.stream()\n            .filter(clusterPhyVO -> ClusterHealthEnum.UNKNOWN.getCode().equals(clusterPhyVO.getHealth()))\n            .collect(Collectors.toList());\n        //非正常集群需要重新发事件\n        for (ClusterPhyVO clusterPhyVO : clusterPhyList) {\n            SpringTool.publish(new ClusterPhyEvent(clusterPhyVO.getCluster(), AriusUser.SYSTEM.getDesc()));\n        }\n        \n        return PaginationResult.buildSucc(clusterPhyVOList, totalHit, condition.getPage(), condition.getSize());\n    }\n\n\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/DslTemplatePageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.template.DslTemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.DslTemplateService;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName DslTemplatePageSearchHandle\n * @Author gyp\n * @Date 2022/6/13\n * @Version 1.0\n */\n@Component\npublic class DslTemplatePageSearchHandle extends AbstractPageSearchHandle<DslTemplateConditionDTO, DslTemplateVO> {\n\n    @Autowired\n    private DslTemplateService dslTemplateService;\n\n    @Override\n    protected Result<Boolean> checkCondition(DslTemplateConditionDTO condition, Integer projectId) {\n\n        String queryIndex = condition.getQueryIndex();\n        if (!AriusObjUtils.isBlack(queryIndex) && (queryIndex.startsWith(\"*\") || queryIndex.startsWith(\"?\"))) {\n            return Result.buildParamIllegal(\"查询索引名称不允许带类似*, ?等通配符\");\n        }\n\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    protected void initCondition(DslTemplateConditionDTO condition, Integer projectId) {\n        // Do nothing\n    }\n\n    @Override\n    protected PaginationResult<DslTemplateVO> buildPageData(DslTemplateConditionDTO condition, Integer projectId) {\n        Tuple<Long, List<DslTemplatePO>> tuple;\n        //普通项目只能查该项目下的dsl模板\n        try {\n        \n            if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n                tuple = dslTemplateService.getDslTemplatePage(projectId, condition);\n                // 超级项目不带 projectId 条件查询时，可查到所有项目的 dsl 模板\n            } else {\n                tuple = dslTemplateService.getDslTemplatePage(condition.getProjectId(), condition);\n            }\n        } catch (ESOperateException e) {\n            return PaginationResult.buildFail(e.getMessage());\n        }\n\n        if (tuple == null) {\n            return PaginationResult.buildSucc(new ArrayList<>(), 0L, condition.getPage(), condition.getSize());\n        }\n        List<DslTemplateVO> dslTemplateVOList = ConvertUtil.list2List(tuple.v2(), DslTemplateVO.class);\n        return PaginationResult.buildSucc(dslTemplateVOList, tuple.v1(), condition.getPage(), condition.getSize());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/GatewayJoinPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.GatewayJoinQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.GatewayJoin;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayJoinPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayJoinVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.QueryDiagnosisTabNameEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectConfigService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.GatewayJoinLogService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n@Component\npublic class GatewayJoinPageSearchHandle extends AbstractPageSearchHandle<GatewayJoinQueryDTO, GatewayJoinVO>{\n    @Autowired\n    private GatewayJoinLogService gatewayJoinLogService;\n    @Autowired\n    private ProjectConfigService projectConfigService;\n\n    private static final Long             QUERY_COUNT_THRESHOLD = 10000L;\n\n    @Override\n    protected Result<Boolean> checkCondition(GatewayJoinQueryDTO condition, Integer projectId) {\n        String queryIndex = condition.getQueryIndex();\n        if (!AriusObjUtils.isBlack(queryIndex) && (queryIndex.startsWith(\"*\") || queryIndex.startsWith(\"?\"))) {\n            return Result.buildParamIllegal(\"查询索引名称不允许带类似*, ?等通配符\");\n        }\n        // 只允许查询前10000条数据\n        long startNum = (condition.getPage() - 1) * condition.getSize();\n        if(startNum >= QUERY_COUNT_THRESHOLD) {\n            return Result.buildParamIllegal(String.format(\"查询条数不能超过%d条\", QUERY_COUNT_THRESHOLD));\n        }\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    protected void initCondition(GatewayJoinQueryDTO condition, Integer projectId) {\n        //do nothing\n    }\n\n    @Override\n    protected PaginationResult<GatewayJoinVO> buildPageData(GatewayJoinQueryDTO condition, Integer projectId) {\n        Tuple<Long, List<GatewayJoinPO>> tuple = null;\n        try {\n            if (QueryDiagnosisTabNameEnum.SLOW_QUERY.getTabName().equals(condition.getTabName())) {\n                ProjectConfig projectConfig = projectConfigService.getProjectConfig(projectId);\n                if(AriusObjUtils.isNull(projectConfig)){\n                    return PaginationResult.buildFail(\"项目配置不存在\");\n                }\n                Integer slowQueryTime = projectConfig.getSlowQueryTimes();\n                tuple = gatewayJoinLogService.getGatewayJoinSlowQueryLogPage(projectId, condition, slowQueryTime);\n            } else {\n                tuple = gatewayJoinLogService.getGatewayJoinErrorLogPage(projectId, condition);\n            }\n        } catch (ESOperateException e) {\n            return PaginationResult.buildFail(e.getMessage());\n        }\n\n        if (tuple == null) {\n            return PaginationResult.buildSucc(new ArrayList<>(), 0L, condition.getPage(), condition.getSize());\n        }\n        List<GatewayJoinVO> gatewayJoinVOList = ConvertUtil.list2List(tuple.v2(), GatewayJoinVO.class);\n        return PaginationResult.buildSucc(gatewayJoinVOList, tuple.v1(), condition.getPage(), condition.getSize());\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/IndexPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexCatCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexCatCellVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.index.IndexStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport java.util.Map;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class IndexPageSearchHandle extends AbstractPageSearchHandle<IndexQueryDTO, IndexCatCellVO> {\n    private static final String           DEFAULT_SORT_TERM  = \"timestamp\";\n\n    private static final Long             QUERY_COUNT_THRESHOLD = 10000L;\n\n    @Autowired\n    private ESIndexCatService             esIndexCatService;\n\n    @Autowired\n    private ESIndexService                esIndexService;\n    private static final FutureUtil<List<IndexCatCell>> INDEX_BUILD_FUTURE = FutureUtil.init(\"INDEX_BUILD_FUTURE\", 10, 10, 100);\n    @Override\n    protected Result<Boolean> checkCondition(IndexQueryDTO condition, Integer projectId) {\n\n        if (StringUtils.isNotBlank(condition.getHealth()) && !IndexStatusEnum.isStatusExit(condition.getHealth())) {\n            return Result.buildParamIllegal(String.format(\"健康状态%s非法\", condition.getHealth()));\n        }\n\n        String indexName = condition.getIndex();\n        if (!AriusObjUtils.isBlack(indexName) && (indexName.startsWith(\"*\") || indexName.startsWith(\"?\"))) {\n            return Result.buildParamIllegal(\"索引名称不允许带类似*, ?等通配符查询\");\n        }\n\n        // 只允许查询前10000条数据\n        long startNum = (condition.getPage() - 1) * condition.getSize();\n        if(startNum >= QUERY_COUNT_THRESHOLD) {\n            return Result.buildParamIllegal(String.format(\"查询条数不能超过%d条\", QUERY_COUNT_THRESHOLD));\n        }\n\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    protected void initCondition(IndexQueryDTO condition, Integer projectId) {\n        if (null == condition.getPage()) {\n            condition.setPage(1L);\n        }\n\n        if (null == condition.getSize() || 0 == condition.getSize()) {\n            condition.setSize(10L);\n        }\n\n        if (AriusObjUtils.isBlack(condition.getSortTerm())) {\n            condition.setSortTerm(DEFAULT_SORT_TERM);\n        }\n    }\n\n    /**\n     * 获取索引Cat/index信息\n     *\n     * 业务上限制ES深分页(不考虑10000条之后的数据), 由前端限制\n     */\n    @Override\n    protected PaginationResult<IndexCatCellVO> buildPageData(IndexQueryDTO condition, Integer projectId) {\n        try {\n            String queryCluster = condition.getCluster();\n            // 使用超级项目访问时，queryProjectId为null\n            Integer queryProjectId = null;\n            if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId)) { queryProjectId = projectId;}\n\n            Tuple<Long, List<IndexCatCell>> totalHitAndIndexCatCellListTuple = esIndexCatService.syncGetCatIndexInfo(\n                queryCluster, condition.getIndex(), condition.getHealth(), condition.getStatus(), queryProjectId,\n                (condition.getPage() - 1) * condition.getSize(), condition.getSize(), condition.getSortTerm(),\n                condition.getOrderByDesc());\n            if (null == totalHitAndIndexCatCellListTuple) {\n                LOGGER.warn(\"class=IndicesPageSearchHandle||method=getIndexCatCellsFromES||clusters={}||index={}||\"\n                            + \"errMsg=get empty index cat info from es\",\n                    condition.getCluster(), condition.getIndex());\n                return PaginationResult.buildSucc(Lists.newArrayList(), 0, condition.getPage(), condition.getSize());\n            }\n\n            //设置索引阻塞信息\n            List<IndexCatCell> finalIndexCatCellList = batchFetchIndexAliasesAndBlockInfo(\n                totalHitAndIndexCatCellListTuple.getV2());\n            List<IndexCatCellVO> indexCatCellVOList = ConvertUtil.list2List(finalIndexCatCellList,\n                IndexCatCellVO.class);\n\n            return PaginationResult.buildSucc(indexCatCellVOList, totalHitAndIndexCatCellListTuple.getV1(),\n                condition.getPage(), condition.getSize());\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=IndicesPageSearchHandle||method=getIndexCatCellsFromES||clusters={}||index={}||errMsg={}\",\n                condition.getCluster(), condition.getIndex(), e.getMessage(), e);\n            return PaginationResult.buildFail(\"获取分页索引列表失败\");\n        }\n    }\n\n    /**\n     * 批量构建索引实时数据(包含block和aliases)\n     * @param catCellList    索引cat/index基本信息\n     * @return               List<IndexCatCell>\n     */\n    private List<IndexCatCell> batchFetchIndexAliasesAndBlockInfo(List<IndexCatCell> catCellList) {\n        List<IndexCatCell> finalIndexCatCellList = Lists.newCopyOnWriteArrayList(catCellList);\n        Map<String, List<IndexCatCell>> cluster2IndexCatCellListMap = ConvertUtil.list2MapOfList(finalIndexCatCellList,\n            IndexCatCell::getCluster, indexCatCell -> indexCatCell);\n        if (MapUtils.isEmpty(cluster2IndexCatCellListMap)) {\n            return finalIndexCatCellList;\n        }\n\n        cluster2IndexCatCellListMap.forEach((cluster, indexCatCellList) -> {\n            INDEX_BUILD_FUTURE.runnableTask(() -> {\n                esIndexService.buildIndexAliasesAndBlockInfo(cluster, indexCatCellList);\n            });\n        });\n        INDEX_BUILD_FUTURE.waitExecute();\n\n        return finalIndexCatCellList;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/OperateRecordPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.operaterecord.OperateRecordVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport java.util.Collections;\nimport java.util.List;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName DslTemplatePageSearchHandle\n * @Author gyp\n * @Date 2022/6/13\n * @Version 1.0\n */\n@Component\npublic class OperateRecordPageSearchHandle extends AbstractPageSearchHandle<OperateRecordDTO, OperateRecordVO> {\n    private static final ILog    LOGGER = LogFactory.getLog(OperateRecordPageSearchHandle.class);\n\n    @Autowired\n    private OperateRecordService operateRecordService;\n\n    @Override\n    protected Result<Boolean> checkCondition(OperateRecordDTO condition, Integer projectId) {\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected void initCondition(OperateRecordDTO condition, Integer projectId) {\n        if (StringUtils.isBlank(condition.getProjectName())) {\n            if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n                final ProjectBriefVO projectBriefVO = projectService.getProjectBriefByProjectId(projectId);\n                condition.setProjectName(projectBriefVO.getProjectName());\n            }\n        }\n        condition.setFrom((condition.getPage() - 1) * condition.getSize());\n\n        // Do nothing\n    }\n\n    @Override\n    protected PaginationResult<OperateRecordVO> buildPageData(OperateRecordDTO pageDTO, Integer projectId) {\n\n        final Tuple<Long, List<OperateRecordVO>> tuple = operateRecordService\n            .pagingGetOperateRecordByCondition(pageDTO);\n        if (tuple == null) {\n            return PaginationResult.buildSucc(Collections.emptyList(), 0L, pageDTO.getPage(), pageDTO.getSize());\n        }\n        return PaginationResult.buildSucc(tuple.getV2(), tuple.v1(), pageDTO.getPage(), pageDTO.getSize());\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/QuickCommandIndicesDistributionPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyQuickCommandIndicesQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexCatCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.IndicesDistributionVO;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n * 快捷命令索引分布.\n *\n * @ClassName QuickCommandIndicesDistributionPageSearchHandle\n * @Author gyp\n * @Date 2022/7/6\n * @Version 1.0\n */\n@Component\npublic class QuickCommandIndicesDistributionPageSearchHandle extends AbstractPageSearchHandle<ClusterPhyQuickCommandIndicesQueryDTO, IndicesDistributionVO> {\n    private static final String DEFAULT_SORT_TERM = \"timestamp\";\n\n    @Autowired\n    private ESIndexCatService   esIndexCatService;\n\n    @Override\n    protected Result<Boolean> checkCondition(ClusterPhyQuickCommandIndicesQueryDTO condition, Integer projectId) {\n        if (StringUtils.isBlank(condition.getCluster())) {\n            return Result.buildParamIllegal(String.format(\"集群名称不能为空\"));\n        }\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    protected void initCondition(ClusterPhyQuickCommandIndicesQueryDTO condition, Integer projectId) {\n        if (null == condition.getPage()) {\n            condition.setPage(1L);\n        }\n\n        if (null == condition.getSize() || 0 == condition.getSize()) {\n            condition.setSize(10L);\n        }\n\n        if (AriusObjUtils.isBlack(condition.getSortTerm())) {\n            condition.setSortTerm(DEFAULT_SORT_TERM);\n        }\n    }\n\n    @Override\n    protected PaginationResult<IndicesDistributionVO> buildPageData(ClusterPhyQuickCommandIndicesQueryDTO condition, Integer projectId) {\n        try {\n            String queryCluster = condition.getCluster();\n            // 使用超级项目访问时，queryProjectId为null\n            Integer queryProjectId = null;\n            Tuple<Long, List<IndexCatCell>> totalHitAndIndexCatCellListTuple = esIndexCatService.syncGetCatIndexInfo(\n                    queryCluster, condition.getKeyword(), condition.getHealth(),condition.getStatus(), queryProjectId,\n                    (condition.getPage() - 1) * condition.getSize(), condition.getSize(), condition.getSortTerm(),\n                    condition.getOrderByDesc());\n            if (null == totalHitAndIndexCatCellListTuple) {\n                LOGGER.warn(\"class=IndicesPageSearchHandle||method=getIndexCatCellsFromES||clusters={}||index={}||\"\n                                + \"errMsg=get empty index cat info from es\",\n                        condition.getCluster(), condition.getIndex());\n                return PaginationResult.buildSucc(Lists.newArrayList(), 0, condition.getPage(), condition.getSize());\n            }\n\n            List<IndicesDistributionVO> indexCatCellVOList = ConvertUtil.list2List(totalHitAndIndexCatCellListTuple.getV2(), IndicesDistributionVO.class);\n\n            return PaginationResult.buildSucc(indexCatCellVOList, totalHitAndIndexCatCellListTuple.getV1(),\n                    condition.getPage(), condition.getSize());\n        } catch (Exception e) {\n            LOGGER.error(\n                    \"class=IndicesPageSearchHandle||method=getIndexCatCellsFromES||clusters={}||index={}||errMsg={}\",\n                    condition.getCluster(), condition.getIndex(), e.getMessage(), e);\n            return PaginationResult.buildFail(\"获取分页索引列表失败\");\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/QuickCommandShardsDistributionPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyQuickCommandShardsQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.ShardDistributionVO;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESShardCatService;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n * 快捷命令shard分布.\n *\n * @ClassName QuickCommandShardsDistributionPageSearchHandle\n * @Author gyp\n * @Date 2022/7/6\n * @Version 1.0\n */\n@Component\npublic class QuickCommandShardsDistributionPageSearchHandle extends AbstractPageSearchHandle<ClusterPhyQuickCommandShardsQueryDTO, ShardDistributionVO> {\n    private static final String DEFAULT_SORT_TERM = \"timestamp\";\n\n    @Autowired\n    private ESShardCatService esShardCatService;\n\n    @Override\n    protected Result<Boolean> checkCondition(ClusterPhyQuickCommandShardsQueryDTO condition, Integer projectId) {\n        if (StringUtils.isBlank(condition.getCluster())) {\n            return Result.buildParamIllegal(String.format(\"集群名称不能为空\"));\n        }\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    protected void initCondition(ClusterPhyQuickCommandShardsQueryDTO condition, Integer projectId) {\n        if (null == condition.getPage()) {\n            condition.setPage(1L);\n        }\n\n        if (null == condition.getSize() || 0 == condition.getSize()) {\n            condition.setSize(10L);\n        }\n\n        if (AriusObjUtils.isBlack(condition.getSortTerm())) {\n            condition.setSortTerm(DEFAULT_SORT_TERM);\n        }\n    }\n\n    @Override\n    protected PaginationResult<ShardDistributionVO> buildPageData(ClusterPhyQuickCommandShardsQueryDTO condition, Integer projectId) {\n        try {\n            String queryCluster = condition.getCluster();\n            // 使用超级项目访问时，queryProjectId为null\n            Integer queryProjectId = null;\n            Tuple<Long, List<ShardDistributionVO>> totalHitAndIndexCatCellListTuple = esShardCatService.syncGetCatShardInfo(\n                    queryCluster, queryProjectId, condition.getKeyword(),\n                    (condition.getPage() - 1) * condition.getSize(), condition.getSize(), condition.getSortTerm(),\n                    condition.getOrderByDesc());\n            if (null == totalHitAndIndexCatCellListTuple) {\n                return PaginationResult.buildSucc(Lists.newArrayList(), 0, condition.getPage(), condition.getSize());\n            }\n\n            List<ShardDistributionVO> indexCatCellVOList = ConvertUtil.list2List(totalHitAndIndexCatCellListTuple.getV2(), ShardDistributionVO.class);\n\n            return PaginationResult.buildSucc(indexCatCellVOList, totalHitAndIndexCatCellListTuple.getV1(),\n                    condition.getPage(), condition.getSize());\n        } catch (Exception e) {\n            return PaginationResult.buildFail(\"获取分页shard列表失败\");\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/TaskPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.OpTaskVO;\nimport com.didichuxing.datachannel.arius.admin.core.service.task.OpTaskService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Collections;\nimport java.util.List;\n\n@Component\npublic class TaskPageSearchHandle extends AbstractPageSearchHandle<OpTaskQueryDTO, OpTaskVO>{\n    private static final ILog LOGGER = LogFactory.getLog(TaskPageSearchHandle.class);\n    @Autowired\n    private OpTaskService opTaskService;\n    @Override\n    protected Result<Boolean> checkCondition(OpTaskQueryDTO condition, Integer projectId) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected void initCondition(OpTaskQueryDTO condition, Integer projectId) {\n        //do nothing\n    }\n\n    @Override\n    protected PaginationResult<OpTaskVO> buildPageData(OpTaskQueryDTO queryDTO, Integer projectId) {\n        Tuple<Long, List<OpTaskVO>> tuple = opTaskService.pagingGetTasksByCondition(queryDTO);\n        if (tuple == null) {\n            return PaginationResult.buildSucc(Collections.emptyList(), 0L, queryDTO.getPage(), queryDTO.getSize());\n        }\n        return PaginationResult.buildSucc(tuple.getV2(), tuple.v1(), queryDTO.getPage(), queryDTO.getSize());\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/TemplateLogicPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.SortTermEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * Created by linyunan on 2021-10-14\n */\n@Component\npublic class TemplateLogicPageSearchHandle extends AbstractPageSearchHandle<TemplateConditionDTO, ConsoleTemplateVO> {\n\n    @Autowired\n    private IndexTemplateService          indexTemplateService;\n\n    @Autowired\n    private ClusterLogicService           clusterLogicService;\n\n    private static final FutureUtil<Void> BUILD_BELONG_CLUSTER_FUTURE_UTIL = FutureUtil\n        .init(\"BUILD_BELONG_CLUSTER_FUTURE_UTIL\", 10, 10, 100);\n\n\n\n    @Override\n    protected Result<Boolean> checkCondition(TemplateConditionDTO templateConditionDTO, Integer projectId) {\n\n        if (null != templateConditionDTO.getDataType() && !DataTypeEnum.isExit(templateConditionDTO.getDataType())) {\n            return Result.buildParamIllegal(\"数据类型不存在\");\n        }\n\n        String templateName = templateConditionDTO.getName();\n        if (!AriusObjUtils.isBlack(templateName) && (templateName.startsWith(\"*\") || templateName.startsWith(\"?\"))) {\n            return Result.buildParamIllegal(\"模板名称不允许带类似*, ?等通配符查询\");\n        }\n\n        if (null != templateConditionDTO.getSortTerm() && !SortTermEnum.isExit(templateConditionDTO.getSortTerm())) {\n            return Result.buildParamIllegal(String.format(\"暂不支持排序类型[%s]\", templateConditionDTO.getSortTerm()));\n        }\n\n        return Result.buildSucc(true);\n\n    }\n\n    @Override\n    protected void initCondition(TemplateConditionDTO condition, Integer projectId) {\n        if (!AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            condition.setProjectId(projectId);\n        }\n\n    }\n\n    @Override\n    protected PaginationResult<ConsoleTemplateVO> buildPageData(TemplateConditionDTO condition, Integer projectId) {\n        if(StringUtils.isNotBlank(condition.getName())){\n            condition.setName(CommonUtils.sqlFuzzyQueryTransfer(condition.getName()));\n        }\n        if(StringUtils.isNotBlank(condition.getDesc())){\n            condition.setDesc(CommonUtils.sqlFuzzyQueryTransfer(condition.getDesc()));\n        }\n        List<IndexTemplate> matchIndexTemplate = indexTemplateService.pagingGetLogicTemplatesByCondition(condition);\n        Integer totalHit = indexTemplateService.fuzzyLogicTemplatesHitByCondition(condition).intValue();\n\n        List<ConsoleTemplateVO> consoleTemplateVOList = buildOtherInfo(matchIndexTemplate);\n      \n        return PaginationResult.buildSucc(consoleTemplateVOList, totalHit, condition.getPage(), condition.getSize());\n    }\n    \n  \n    /******************************************private***********************************************/\n    private List<ConsoleTemplateVO> buildOtherInfo(List<IndexTemplate> indexTemplateList) {\n        if (CollectionUtils.isEmpty(indexTemplateList)) {\n            return Lists.newArrayList();\n        }\n        List<ConsoleTemplateVO> consoleTemplateVOList = ConvertUtil.list2List(indexTemplateList,\n            ConsoleTemplateVO.class);\n       \n        //1. 设置逻辑集群\n        setTemplateClusterName(consoleTemplateVOList);\n        return consoleTemplateVOList;\n    }\n\n    private void setTemplateClusterName(List<ConsoleTemplateVO> consoleTemplateVOList) {\n        if (CollectionUtils.isEmpty(consoleTemplateVOList)) {\n            return;\n        }\n        for (ConsoleTemplateVO consoleTemplateVO : consoleTemplateVOList) {\n            BUILD_BELONG_CLUSTER_FUTURE_UTIL.runnableTask(() -> {\n                Optional.ofNullable(consoleTemplateVO.getProjectId()).map(projectService::getProjectBriefByProjectId)\n                        .map(ProjectBriefVO::getProjectName).ifPresent(consoleTemplateVO::setProjectName);\n                ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdAndProjectId(\n                        consoleTemplateVO.getResourceId(), consoleTemplateVO.getProjectId());\n                if (null != clusterLogic) {\n                    consoleTemplateVO.setCluster(clusterLogic.getName());\n                }\n            });\n            consoleTemplateVO.setIsPartition(\n                    Objects.nonNull(consoleTemplateVO.getExpression()) && consoleTemplateVO.getExpression()\n                            .endsWith(\"*\"));\n        }\n        BUILD_BELONG_CLUSTER_FUTURE_UTIL.waitExecute();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/page/TemplateSrvPageSearchHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.page;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.impl.ClusterPhyManagerImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.TemplateSrvManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv.TemplateQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.srv.TemplateSrv;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterConnectionStatusWithTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.srv.TemplateSrvVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.srv.TemplateWithSrvVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.srv.UnavailableTemplateSrvVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterConnectionStatusWithTemplateEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleThree;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author chengxiang\n * @date 2022/5/18\n */\n@Component\npublic class TemplateSrvPageSearchHandle extends AbstractPageSearchHandle<TemplateQueryDTO, TemplateWithSrvVO> {\n     private static final ILog                          LOGGER                                                    = LogFactory\n        .getLog(ClusterPhyManagerImpl.class);\n    private static final  FutureUtil<TemplateWithSrvVO> TEMPLATE_SRV_PAGE_SEARCH_HANDLE_BUILD_CLUSTER_FUTURE_UTIL =\n            FutureUtil\n        .init(\"TEMPLATE_SRV_PAGE_SEARCH_HANDLE_BUILD_CLUSTER_FUTURE_UTIL\", 10, 10, 100);\n    \n    private static final String HEALTH      = \"health\";\n    private static final String CHECK_POINT_DIFF = \"check_point_diff\";\n    @Autowired\n    private IndexTemplateService          indexTemplateService;\n\n    @Autowired\n    private IndexTemplatePhyService       indexTemplatePhyService;\n\n    @Autowired\n    private TemplateSrvManager            templateSrvManager;\n    @Autowired\n    private   ClusterRegionService clusterRegionService;\n    @Autowired\n    protected ClusterPhyManager clusterPhyManager;\n\n    @Override\n    protected Result<Boolean> checkCondition(TemplateQueryDTO condition, Integer projectId) {\n\n        String templateName = condition.getName();\n        if (!AriusObjUtils.isBlack(templateName) && (templateName.startsWith(\"*\") || templateName.startsWith(\"?\"))) {\n            return Result.buildParamIllegal(\"模板名称不能以*或者?开头\");\n        }\n\n        return Result.buildSucc(Boolean.TRUE);\n    }\n\n    @Override\n    protected void initCondition(TemplateQueryDTO condition, Integer projectId) {\n        // nothing to do\n    }\n\n    @Override\n    protected PaginationResult<TemplateWithSrvVO> buildPageData(TemplateQueryDTO condition, Integer projectId) {\n        Integer totalHit ;\n        List<IndexTemplate> matchIndexTemplateList;\n        if(StringUtils.isNotBlank(condition.getName())){\n            condition.setName(CommonUtils.sqlFuzzyQueryTransfer(condition.getName()));\n        }\n        // 如果存物理集群，则需要通过物理集群找到指定的逻辑集群\n        if (StringUtils.isNotBlank(condition.getCluster())) {\n            List<Integer> logicClusterIdList = clusterRegionService.listPhyClusterRegions(condition.getCluster())\n                    .stream().map(ClusterRegion::getLogicClusterIds)\n                    .filter(clusterLogicId -> !AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID.equals(clusterLogicId))\n                    .map(ListUtils::string2IntList).flatMap(Collection::stream).distinct().collect(Collectors.toList());\n            if (CollectionUtils.isEmpty(logicClusterIdList)) {\n                return PaginationResult.buildSucc(Collections.emptyList(),0,condition.getPage(),condition.getSize());\n            }\n            totalHit = indexTemplateService.fuzzyLogicTemplatesHitByConditionAndLogicClusterIdList(condition,\n                    logicClusterIdList).intValue();\n            matchIndexTemplateList =\n                    indexTemplateService.pagingGetTemplateSrvByConditionAndLogicClusterIdList(condition,logicClusterIdList);\n        } else {\n            totalHit = indexTemplateService.fuzzyLogicTemplatesHitByCondition(condition).intValue();\n            matchIndexTemplateList = indexTemplateService.pagingGetTemplateSrvByCondition(condition);\n        }\n        List<TemplateWithSrvVO> templateWithSrvVOList = buildExtraAttribute(matchIndexTemplateList);\n        \n        \n        \n        return PaginationResult.buildSucc(templateWithSrvVOList, totalHit, condition.getPage(), condition.getSize());\n    }\n\n \n    private List<TemplateWithSrvVO> buildExtraAttribute(List<IndexTemplate> templateList) {\n        if (CollectionUtils.isEmpty(templateList)) {\n            return Lists.newArrayList();\n        }\n        final Map<Integer, String> projectId2ProjectName = ConvertUtil.list2Map(projectService.getProjectBriefList(),\n                ProjectBriefVO::getId, ProjectBriefVO::getProjectName);\n        List<Integer> logicTemplateIds =\n                templateList.stream().map(IndexTemplate::getId).distinct().collect(Collectors.toList());\n        List<IndexTemplatePhy> templatePhies = indexTemplatePhyService.getTemplateByLogicIds(logicTemplateIds);\n        Map<Integer, List<IndexTemplatePhy>> logicId2IndexTemplatePhyListMap = ConvertUtil.list2MapOfList(templatePhies,\n                IndexTemplatePhy::getLogicId, i -> i);\n        List<String> clusterPhyList = templatePhies.stream().map(IndexTemplatePhy::getCluster).distinct()\n                .collect(Collectors.toList());\n        Map<String, ClusterConnectionStatusWithTemplateEnum> cluster2ClusterConnectionStatusWithTemplateEnumMap = Maps.newConcurrentMap();\n        Map<String, TupleThree</*dcdrExist*/Boolean,/*pipelineExist*/ Boolean,/*existColdRegion*/ Boolean>> cluster2ExistDCDRAndPipelineModuleMap= Maps.newConcurrentMap();\n        for (String clusterPhy : clusterPhyList) {\n            TEMPLATE_SRV_PAGE_SEARCH_HANDLE_BUILD_CLUSTER_FUTURE_UTIL.runnableTask(() -> {\n                cluster2ClusterConnectionStatusWithTemplateEnumMap.put(clusterPhy,\n                        clusterPhyManager.getClusterConnectionStatusWithCache(clusterPhy));\n                cluster2ExistDCDRAndPipelineModuleMap.put(clusterPhy,\n                        clusterPhyManager.getDCDRAndPipelineAndColdRegionTupleByClusterPhyWithCache(clusterPhy));\n            });\n        }\n        TEMPLATE_SRV_PAGE_SEARCH_HANDLE_BUILD_CLUSTER_FUTURE_UTIL.waitExecute();\n       \n        // 构建基础信息\n    \n        return templateList.stream().map(template -> buildTemplateWithSrvVO(template, projectId2ProjectName,\n                logicId2IndexTemplatePhyListMap, cluster2ClusterConnectionStatusWithTemplateEnumMap,\n                cluster2ExistDCDRAndPipelineModuleMap)).collect(Collectors.toList());\n    }\n    \n    private TemplateWithSrvVO buildTemplateWithSrvVO(IndexTemplate template, Map<Integer, String> projectId2ProjectName,\n                                                     Map<Integer, List<IndexTemplatePhy>> logicId2IndexTemplatePhyListMap,\n                                                     Map<String, ClusterConnectionStatusWithTemplateEnum> cluster2ClusterConnectionStatusWithTemplateEnumMap,\n                                                     Map<String, TupleThree<Boolean, Boolean, Boolean>> cluster2ExistDCDRAndPipelineModuleMap) {\n        TemplateWithSrvVO templateWithSrvVO = ConvertUtil.obj2Obj(template, TemplateWithSrvVO.class);\n        templateWithSrvVO.setCluster(Lists.newArrayList());\n        templateWithSrvVO.setOpenSrv(\n                ConvertUtil.list2List(TemplateSrv.codeStr2SrvList(template.getOpenSrv()), TemplateSrvVO.class));\n        Optional.ofNullable(template).map(IndexTemplate::getProjectId).map(projectId2ProjectName::get)\n                .ifPresent(templateWithSrvVO::setProjectName);\n        templateWithSrvVO.setPartition(StringUtils.endsWith(template.getExpression(), \"*\"));\n        //这里整改为只要校验master即可，原因是由于我们在创建链路/获取相同版本出得集群的时候，进行插件的校验，不能放在这里，会损耗性能\n        final List<IndexTemplatePhy> indexTemplatePhies = logicId2IndexTemplatePhyListMap.get(templateWithSrvVO.getId());\n        if (Objects.isNull(indexTemplatePhies)) {\n            LOGGER.warn(\"class={}||method=buildTemplateWithSrvVO||logicTemplateId={} 未匹配到物理模板，属于脏数据\",\n                    getClass().getSimpleName(), templateWithSrvVO.getId());\n            return templateWithSrvVO;\n        }\n        indexTemplatePhies.stream().filter(i -> TemplateDeployRoleEnum.MASTER.getCode().equals(i.getRole()))\n\n                .map(IndexTemplatePhy::getCluster)\n                .map(cluster -> templateSrvManager.getUnavailableSrvByTemplateAndMasterPhy(template,\n                        cluster2ExistDCDRAndPipelineModuleMap.get(cluster)))\n                .map(unavailableTemplateSrvs -> ConvertUtil.list2List(Lists.newArrayList(unavailableTemplateSrvs),\n                        UnavailableTemplateSrvVO.class)).findFirst().ifPresent(templateWithSrvVO::setUnavailableSrv);\n        indexTemplatePhies.stream().map(IndexTemplatePhy::getCluster).distinct()\n                .forEach(templateWithSrvVO.getCluster()::add);\n\n        final List<ClusterConnectionStatusWithTemplateVO> statusWithTemplateList = indexTemplatePhies.stream()\n                //获取到主副本集群的连通状态\n                .map(indexTemplatePhy -> new ClusterConnectionStatusWithTemplateVO(indexTemplatePhy.getCluster(),\n                        cluster2ClusterConnectionStatusWithTemplateEnumMap.get(indexTemplatePhy.getCluster())))\n                .collect(Collectors.toList());\n    \n        templateWithSrvVO.setClusterConnectionStatus(statusWithTemplateList);\n        return templateWithSrvVO;\n        \n    }\n\n   \n\n\n\n    /**\n     * 对全量查询结果根据分页条件进行过滤\n     *\n     * @param condition 分页条件\n     * @param source    全量查询结果\n     * @return\n     */\n    <T> List<T> filterFullDataByPage(List<T> source, PageDTO condition) {\n        //这里页码和前端对应起来，第一页页码是1 而不是0\n        long fromIndex = condition.getSize() * (condition.getPage() - 1);\n        long toIndex = getLastPageSize(condition, source.size());\n        return source.subList((int) fromIndex, (int) toIndex);\n    }\n\n    /**\n     * 获取最后一条数据的index，以防止数组溢出\n     *\n     * @param condition      分页条件\n     * @param pageSizeFromDb 查询结果\n     * @return\n     */\n    long getLastPageSize(PageDTO condition, Integer pageSizeFromDb) {\n        //分页最后一条数据的index\n        long size = condition.getPage() * condition.getSize();\n        if (pageSizeFromDb < size) {\n            size = pageSizeFromDb;\n        }\n        return size;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/ESUserManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ESUserDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ConsoleESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ConsoleESUserWithVerifyCodeVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ESUserVO;\nimport com.didiglobal.knowframework.security.common.po.ProjectPO;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectVO;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * es user 操作\n *\n * @author shizeying\n * @date 2022/05/25\n */\npublic interface ESUserManager {\n\n    /**\n     * 通过项目id获取es user 列表\n     *\n     * @param projectIdStr {@link ProjectPO#getId()}\n     * @param request   操作者属于{@link ProjectVO#getUserList()}\n     * @return {@code List<ESUser>}\n     */\n    Result<List<ESUserVO>> listESUsersByProjectId(String projectIdStr, HttpServletRequest request);\n\n    /**\n     * 新建APP\n     *\n     * @param appDTO    dto\n     * @param projectId {@link ProjectPO#getId()}\n     * @param operator  操作人 {@link   com.didichuxing.datachannel.arius.admin.core.component.RoleTool#isAdmin}\n     * @return 成功 true  失败 false\n     */\n    Result<Integer> registerESUser(ESUserDTO appDTO, Integer projectId, String operator);\n\n    /**\n     * 编辑es user\n     *\n     * @param esUserDTO\n     * @param operator 操作人 {@link   com.didichuxing.datachannel.arius.admin.core.component.RoleTool#isAdmin}\n     * @return {@code Result<Void>}\n     */\n    Result<Void> editESUser(ESUserDTO esUserDTO, String operator);\n\n    /**\n     * 设置es User为应用默认es User\n     *\n     * @param esUserName ES用户\n     * @param projectId {@link ProjectPO#getId()}\n     * @param operator 操作人 {@link   com.didichuxing.datachannel.arius.admin.core.component.RoleTool#isAdmin}\n     * @return {@code Result<Void>}\n     */\n    Result<Void> setDefaultDisplay(int esUserName, int projectId, String operator);\n\n    /**\n     * 删除项目下的指定es user\n     *\n     * @param esUser ES用户\n     * @param projectId {@link ProjectPO#getId()}\n     * @param operator 操作人 {@link   com.didichuxing.datachannel.arius.admin.core.component.RoleTool#isAdmin}\n     * @return {@code Result<Void>}\n     */\n    Result<Void> deleteESUserByProject(int esUser, int projectId, String operator);\n\n    /**\n     * 删除项目下所有的es user\n     *\n     * @param projectId {@link ProjectPO#getId()}\n     * @param operator 操作人 {@link   com.didichuxing.datachannel.arius.admin.core.component.RoleTool#isAdmin}\n     * @return {@code Result<Void>}\n     */\n    Result<Void> deleteAllESUserByProject(int projectId, String operator);\n\n    /**\n     * 校验验证码\n     * @param esUserName es user\n     * @param verifyCode 验证码\n     * @return result\n     */\n    Result<Void> verifyAppCode(Integer esUserName, String verifyCode);\n\n    /**\n     * 获取\n     *\n     * @param esUser ES用户\n     * @return {@code Result<ConsoleESUserVO>}\n     */\n    Result<ConsoleESUserVO> get(Integer esUser);\n\n    /**\n     * 获取没有\n     *\n     * @param projectId\n     * @param operator\n     * @return {@code Result<List<ConsoleESUserWithVerifyCodeVO>>}\n     */\n    Result<List<ConsoleESUserWithVerifyCodeVO>> getNoCodeESUser(Integer projectId, String operator);\n\n    /**\n     * 获取原生模式下项目的访问集群列表\n     *\n     * @param projectId\n     * @return {@code Result<List<String>> }\n     */\n    Result<List<String>> listClusterByAppInPrimitiveType(Integer projectId);\n\n    /**\n     * 获取集群模式下项目的访问集群列表\n     *\n     * @param projectId\n     * @return {@code Result<List<String>> }\n     */\n    Result<List<String>> listClusterByAppInClusterType(Integer projectId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/LoginManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.OperateForbiddenException;\nimport com.didiglobal.knowframework.security.common.Result;\nimport com.didiglobal.knowframework.security.common.dto.account.AccountLoginDTO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.io.IOException;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * 登录管理器\n *\n * @author shizeying\n * @date 2022/06/16\n */\npublic interface LoginManager {\n\n    /**\n     * 验证登录信息（验证前密码先用Base64解码再用RSA解密） 登录前会检查账户激活状态\n     *\n     * @param loginDTO 登陆信息\n     * @param request  请求信息\n     * @return token\n     */\n    Result<UserBriefVO> verifyLogin(AccountLoginDTO loginDTO, HttpServletRequest request, HttpServletResponse response);\n\n    /**\n     * 登出接口\n     *\n     * @param request\n     * @param response\n     * @return\n     */\n    Result<Boolean> logout(HttpServletRequest request, HttpServletResponse response);\n\n    /**\n     * 拦截器检查 检查登陆\n     *\n     * @param request             请求\n     * @param response            响应\n     * @param requestMappingValue 请求映射value\n     * @param whiteMappingValues  白名单\n     * @return boolean\n     * @throws IOException ioexception\n     */\n    boolean interceptorCheck(HttpServletRequest request, HttpServletResponse response, String requestMappingValue,\n                             List<String> whiteMappingValues) throws IOException, OperateForbiddenException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/OperateRecordManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.UserConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.operaterecord.OperateRecordVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\n\nimport java.util.List;\n\npublic interface OperateRecordManager {\n    /**\n     * oplogvo\n     *\n     * @param queryDTO  查询dto\n     * @param projectId\n     * @return {@code PagingResult<OplogVO>}\n     */\n    PaginationResult<OperateRecordVO> pageOplogPage(OperateRecordDTO queryDTO,\n                                                    Integer projectId) throws NotFindSubclassException;\n\n    /**\n     * 获取oplog\n     *\n     * @param id id\n     * @return {@code Result<OplogVO>}\n     */\n    Result<OperateRecordVO> getOplogDetailByOplogId(Integer id);\n\n    /**\n     * 获取DSL kibana操作记录 默认前30条\n     * @return\n     * @param queryDTO\n     */\n    Result<List<String>> listSenseOperateRecord(OperateRecordDTO queryDTO, String operator, Integer projectId);\n\n    /**\n     * 更新sense操作记录\n     * @param operateRecordDTO\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Integer> updateSenseOperateRecord(OperateRecordDTO operateRecordDTO, String operator, Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/PermissionExtendManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport com.didiglobal.knowframework.security.common.Result;\nimport com.didiglobal.knowframework.security.common.vo.permission.PermissionTreeVO;\n\n/**\n * 权限点扩展管理器\n *\n * @author shizeying\n * @date 2022/06/14\n */\npublic interface PermissionExtendManager {\n    /**\n     * 建立资源owner角色权限树\n     *\n     * @return {@code Result<PermissionTreeVO>}\n     */\n    Result<PermissionTreeVO> buildPermissionTreeByResourceOwn();\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/ProjectClusterLogicAuthManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport java.util.List;\n\n/**\n * Created by linyunan on 2021-10-17\n */\n\npublic interface ProjectClusterLogicAuthManager {\n\n    /**\n     * 获取当前项目对逻辑集群列表的权限信息\n     * @param projectId                    项目\n     * @param clusterLogicList         逻辑集群信息列表\n     * @return\n     */\n    List<ProjectClusterLogicAuth> getByClusterLogicListAndProjectId(Integer projectId,\n                                                                    List<ClusterLogic> clusterLogicList);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/ProjectConfigManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectConfigVO;\n\n/**\n * project config\n *\n * @author shizeying\n * @date 2022/05/30\n */\npublic interface ProjectConfigManager {\n    /**\n     * 获取esUserName配置信息\n     *\n     * @param projectId projectId\n     * @return 配置信息\n     */\n    Result<ProjectConfigVO> get(int projectId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/ProjectExtendManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectExtendSaveDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectQueryExtendDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectBriefExtendVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectExtendVO;\nimport com.didiglobal.knowframework.security.common.PagingResult;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectDeleteCheckVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * 基于logi的扩展能力\n *\n * @author shizeying\n * @date 2022/06/10\n */\npublic interface ProjectExtendManager {\n    /**\n     * 创建项目\n     *\n     * @param saveDTO    项目信息\n     * @param operator   请求信息\n     * @param operatorId\n     * @return 项目信息\n     */\n    Result<ProjectExtendVO> createProject(ProjectExtendSaveDTO saveDTO, String operator, Integer operatorId);\n\n    /**\n     * 获取项目详情，通过项目id\n     *\n     * @param projectId 项目id\n     * @return ProjectVo 项目信息\n     */\n    Result<ProjectExtendVO> getProjectDetailByProjectId(Integer projectId);\n\n    /**\n     * 获取所有项目简要信息\n     *\n     * @return 项目简要信息list\n     */\n    Result<List<ProjectBriefExtendVO>> getProjectBriefList();\n\n    /**\n     * 删除项目\n     *\n     * @param projectId 项目id\n     * @param operator  请求信息\n     * @return\n     */\n    Result<Void> deleteProjectByProjectId(Integer projectId, String operator);\n\n    /**\n     * 根据项目id获取项目简要信息\n     *\n     * @param projectId 项目id\n     * @return 项目简要信息\n     */\n    Result<ProjectBriefExtendVO> getProjectBriefByProjectId(Integer projectId);\n\n    /**\n     * 条件分页查询项目信息\n     *\n     * @param queryDTO 条件信息\n     * @param request\n     * @return 项目分页信息\n     */\n    PagingResult<ProjectExtendVO> getProjectPage(ProjectQueryExtendDTO queryDTO, HttpServletRequest request);\n\n    /**\n     * 更新项目信息\n     *\n     * @param saveDTO 项目信息\n     * @param operator 请求信息\n     */\n    Result<Void> updateProject(ProjectExtendSaveDTO saveDTO, String operator);\n\n    /**\n     * 更改项目运行状态，旧状态取反\n     *\n     * @param projectId 项目id\n     * @param operator 请求信息\n     */\n    Result<Void> changeProjectStatus(Integer projectId, String operator);\n\n    /**\n     * 增加项目成员\n     *\n     * @param projectId 项目id\n     * @param userIdList 项目id\n     * @param operator 请求信息\n     */\n    Result<Void> addProjectUser(Integer projectId, List<Integer> userIdList, String operator);\n\n    /**\n     * 删除项目成员\n     *\n     * @param projectId 项目id\n     * @param userId 项目id\n     * @param operator 请求信息\n     */\n    Result<Void> delProjectUser(Integer projectId, Integer userId, String operator);\n\n    /**\n     * 增加项目负责人\n     *\n     * @param projectId   项目id\n     * @param ownerIdList 负责人id\n     * @param operator    请求信息\n     */\n    Result<Void> addProjectOwner(Integer projectId, List<Integer> ownerIdList, String operator);\n\n    /**\n     * 删除项目负责人\n     *\n     * @param projectId 项目id\n     * @param ownerId 负责人id\n     * @param operator 请求信息\n     */\n    Result<Void> delProjectOwner(Integer projectId, Integer ownerId, String operator);\n\n    /**\n     * 项目删除前的检查\n     *\n     * @param projectId 项目id\n     * @return ProjectDeleteCheckVO 检查结果\n     */\n    Result<ProjectDeleteCheckVO> checkBeforeDelete(Integer projectId);\n\n    /**\n     * 校验项目是否存在\n     * @param projectId\n     * @return true:存在，false：不存在\n     */\n    Result<Void> checkProjectExist(Integer projectId);\n\n    /**\n     * 未分配项目的用户列表\n     *\n     * @param projectId         projectId\n     * @param containsAdminRole 是否包含管理员\n     * @return {@code Result}\n     */\n    Result<List<UserBriefVO>> unassignedByProjectId(Integer projectId, Boolean containsAdminRole);\n\n    /**\n     * 获取user下绑定的项目\n     *\n     * @param userId 用户id\n     * @return {@code Result<List<ProjectBriefVO>>}\n     */\n    Result<List<ProjectBriefExtendVO>> getProjectBriefByUserId(Integer userId);\n\n    /**\n     * 用户列表按项目id列表\n     *\n     * @param projectId 项目id\n     * @return {@code Result<List<UserBriefVO>>}\n     */\n    Result<List<UserBriefVO>> listUserListByProjectId(Integer projectId);\n    \n    \n    /**\n     * “检查一个项目的资源是否可用。”\n     *\n     * 函数定义如下：\n     *\n     * * 该函数返回一个 Result<Void> 对象。\n     * * 该函数接受一个参数，一个名为 projectId 的整数对象\n     *\n     * @param projectId 项目的 ID。\n     * @return 一个 Result 对象，里面有一个 Void 对象。\n     */\n    Result<Void> checkResourcesByProjectId(Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/ProjectLogicTemplateAuthManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectTemplateAuthDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectTemplateAuthVO;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 2021-06-15\n */\npublic interface ProjectLogicTemplateAuthManager {\n\n    /**\n     * 更新模板 更新模板权限\n     *\n     * @param authDTO  auth dto\n     * @param operator 操作符\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> updateTemplateAuth(ProjectTemplateAuthDTO authDTO, String operator);\n\n    /**\n     * 添加模板\n     *\n     * @param authDTO   auth dto\n     * @param operator  操作符\n     * @param projectId 项目id\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> addTemplateAuth(ProjectTemplateAuthDTO authDTO, String operator, Integer projectId);\n\n    /**\n     * 删除模板\n     *\n     * @param authId    身份验证id\n     * @param operator  操作符\n     * @param projectId 项目id\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> deleteTemplateAuth(Long authId, String operator, Integer projectId);\n\n    /**\n     * 删除冗余模板\n     *\n     * @param delete 删除\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> deleteRedundancyTemplateAuths(boolean delete);\n\n    /**\n     * 得到项目模板身份验证\n     *\n     * @param projectId 项目id\n     * @return {@link Result}<{@link List}<{@link ProjectTemplateAuthVO}>>\n     */\n    Result<List<ProjectTemplateAuthVO>> getProjectTemplateAuths(Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/RoleExtendManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.RoleExtendVO;\nimport com.didiglobal.knowframework.security.common.PagingResult;\nimport com.didiglobal.knowframework.security.common.dto.role.RoleAssignDTO;\nimport com.didiglobal.knowframework.security.common.dto.role.RoleQueryDTO;\nimport com.didiglobal.knowframework.security.common.dto.role.RoleSaveDTO;\nimport com.didiglobal.knowframework.security.common.vo.role.AssignInfoVO;\nimport com.didiglobal.knowframework.security.common.vo.role.RoleBriefVO;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * 角色扩展管理器\n *\n * @author shizeying\n * @date 2022/06/16\n */\npublic interface RoleExtendManager {\n    /**\n     * 删除角色通过角色id\n     *\n     * @param id      id\n     * @param request 请求\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> deleteRoleByRoleId(Integer id, HttpServletRequest request);\n\n    /**\n    * 获取角色详情（主要是获取角色所拥有的权限信息）\n    * @param roleId 角色id\n    * @return RoleVo 角色信息\n    */\n    Result<RoleExtendVO> getRoleDetailByRoleId(Integer roleId);\n\n    /**\n     * 分页获取角色列表\n     *\n     * @param queryDTO 查询角色列表条件\n     * @return 角色列表\n     */\n    PagingResult<RoleExtendVO> getRolePage(RoleQueryDTO queryDTO);\n\n    /**\n     * 保存角色\n     * @param saveDTO 角色信息\n     * @param request 请求信息\n     */\n    Result<Void> createRole(RoleSaveDTO saveDTO, HttpServletRequest request);\n\n    /**\n     * 删除角色\n     * @param roleId 角色id\n     * @param userId 用户id\n     * @param request 请求信息\n     */\n    Result<Void> deleteUserFromRole(Integer roleId, Integer userId, HttpServletRequest request);\n\n    /**\n     * 更新角色信息\n     * @param saveDTO 角色信息\n     * @param request 请求信息\n     */\n    Result<Void> updateRole(RoleSaveDTO saveDTO, HttpServletRequest request);\n\n    /**\n     * 分配角色给用户\n     * @param assignDTO 分配信息\n     * @param request 请求信息\n     */\n    Result<Void> assignRoles(RoleAssignDTO assignDTO, HttpServletRequest request);\n\n    /**\n     * 根据角色id，获取分配信息\n     * @param roleId 角色id\n     * @return 分配信息List\n     */\n    Result<List<AssignInfoVO>> getAssignInfoByRoleId(Integer roleId);\n\n    /**\n     * 根据角色名模糊查询\n     * @param roleName 角色名\n     * @return 角色简要信息list\n     */\n    Result<List<RoleBriefVO>> getRoleBriefListByRoleName(String roleName);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/UserExtendManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.UserExtendDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.UserQueryExtendDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.UserExtendVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.UserWithPwVO;\nimport com.didiglobal.knowframework.security.common.PagingResult;\nimport com.didiglobal.knowframework.security.common.dto.user.UserBriefQueryDTO;\nimport com.didiglobal.knowframework.security.common.dto.user.UserDTO;\nimport com.didiglobal.knowframework.security.common.entity.user.User;\nimport com.didiglobal.knowframework.security.common.vo.role.AssignInfoVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserVO;\nimport java.util.List;\n\n/**\n * 用户扩展管理器\n *\n * @author shizeying\n * @date 2022/06/16\n */\npublic interface UserExtendManager {\n    /**\n     * 添加用户\n     *\n     * @param param    入参\n     * @param operator 操作人或角色\n     * @return {@code Result<Void>}\n     */\n    Result<Void> addUser(UserDTO param, String operator);\n\n    /**\n     * 用户注册信息校验\n     * @param type\n     * @param value\n     * @return\n     */\n    Result<Void> check(Integer type, String value);\n\n    /**\n     * 分页获取用户信息\n     *\n     * @param queryDTO 条件信息\n     * @return 用户信息list\n     */\n    PagingResult<UserExtendVO> getUserPage(UserQueryExtendDTO queryDTO);\n\n    /**\n     * 分页获取用户简要信息\n     * @param queryDTO 条件信息\n     * @return 用户简要信息list\n     */\n    PagingResult<UserBriefVO> getUserBriefPage(UserBriefQueryDTO queryDTO);\n\n    /**\n     * 获取用户详情（主要是获取用户所拥有的权限信息）\n     *\n     * @param userId    用户id\n     * @param projectId\n     * @return 用户详情\n     * @throws LogiSecurityException 用户不存在\n     */\n    Result<UserWithPwVO> getUserDetailByUserId(Integer userId, Integer projectId) throws Exception;\n\n    /**\n     * 根据用户id删除用户\n     * @param userId\n     * @param projectId\n     * @param operator\n     * @return\n     */\n    Result<Void> deleteByUserId(Integer userId, Integer projectId, String operator);\n\n    /**\n     * 获取用户简要信息\n     * @param userName\n     * @return 用户简要信息\n     */\n    Result<UserBriefVO> getUserBriefByUserName(String userName);\n\n    /**\n     * 获取用户简要信息\n     * @param userName 用户名称\n     * @return 用户简要信息\n     */\n    Result<User> getUserByUserName(String userName);\n\n    /**\n     * 获取用户简要信息List\n     * @param userIdList 用户idList\n     * @return 用户简要信息List\n     */\n    Result<List<UserBriefVO>> getUserBriefListByUserIdList(List<Integer> userIdList);\n\n    /**\n     * 根据部门id获取用户list（获取该部门下所有的用户，包括各种子部门）\n     * @param deptId 部门id，如果为null，表示无部门用户\n     * @return 用户简要信息list\n     */\n    Result<List<UserBriefVO>> getUserBriefListByDeptId(Integer deptId);\n\n    /**\n     * 根据用户id和roleName获取角色list\n     * @param userId 用户id\n     * @return 分配角色或者分配用户/列表信息\n     */\n    Result<List<AssignInfoVO>> getAssignDataByUserId(Integer userId);\n\n    /**\n     * 根据角色id获取用户list\n     * @param roleId 角色Id\n     * @return 用户简要信息list\n     */\n    Result<List<UserBriefVO>> getUserBriefListByRoleId(Integer roleId);\n\n    /**\n     * 会分别以账户名和实名去模糊查询，返回两者的并集\n     * 创建项目，添加项目负责人的时候用到\n     * @param name 账户名或实名\n     * @return 用户简要信息list\n     */\n    Result<List<UserBriefVO>> getUserBriefListByUsernameOrRealName(String name);\n\n    /**\n     * 获取用户简要信息List并根据创建时间排序\n     * @param isAsc 是否升序\n     * @return 用户简要信息List\n     */\n    Result<List<UserBriefVO>> getAllUserBriefListOrderByCreateTime(boolean isAsc);\n\n    /**\n     * 会分别以账户名和实名去模糊查询，返回两者的并集\n     * @param name 账户名或实名\n     * @return 用户IdList\n     */\n    Result<List<Integer>> getUserIdListByUsernameOrRealName(String name);\n\n    /**\n     * 获取所有用户简要信息\n     * @return 用户简要信息List\n     */\n    Result<List<UserBriefVO>> getAllUserBriefList();\n\n    /**\n     * 编辑一个用户\n     * @param userDTO\n     * @param operator\n     * @return\n     */\n    Result<Void> editUser(UserExtendDTO userDTO, String operator);\n\n    Result<List<UserVO>> getUserDetailByUserIds(List<Integer> ids);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/impl/ESUserManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.EDIT;\nimport static com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil.obj2Obj;\nimport static com.didichuxing.datachannel.arius.admin.core.service.project.impl.ESUserServiceImpl.VERIFY_CODE_LENGTH;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.ESUserManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ESUserDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ConsoleESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ConsoleESUserWithVerifyCodeVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectSearchTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.VerifyCodeFactory;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ESUserService;\nimport java.util.Collections;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport javax.servlet.http.HttpServletRequest;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * es user\n * <blockquote>\n *     <pre>\n *         由于es user 的创建统一归 super admin 进行管理分配，那么系统所有创建es user的逻辑只需要校验用户是否是超级用户即可\n *     </pre>\n * </blockquote>\n * @author shizeying\n * @date 2022/05/25\n */\n@Component\npublic class ESUserManagerImpl implements ESUserManager {\n    private static final ILog    LOGGER = LogFactory.getLog(ESUserManagerImpl.class);\n    private static final String ES_USER_ERROR_MSG=\"应用下未匹配到逻辑集群，ES_User 不可以被设置为 %s 和 %s\";\n    @Autowired\n    private ProjectService       projectService;\n    @Autowired\n    private ESUserService        esUserService;\n    @Autowired\n    private OperateRecordService operateRecordService;\n    @Autowired\n    private RoleTool            roleTool;\n    @Autowired\n    private ClusterLogicService  clusterLogicService;\n    @Autowired\n    private ClusterPhyService    clusterPhyService;\n    @Autowired\n    private ClusterRegionService clusterRegionService;\n\n    /**\n     * @param projectIdStr\n     * @param request\n     * @return\n     */\n    @Override\n    public Result<List<ESUserVO>> listESUsersByProjectId(String projectIdStr, HttpServletRequest request) {\n\n        Integer projectId = null;\n        if (StringUtils.isNumeric(projectIdStr)) {\n            projectId = Integer.parseInt(projectIdStr);\n        } else {\n            projectId = HttpRequestUtil.getProjectId(request);\n        }\n\n        final String operator = HttpRequestUtil.getOperator(request);\n        if (Objects.isNull(projectId)) {\n            return Result.buildNotExist(\"未匹配到项目下的es user\");\n        }\n        ProjectVO projectVO = projectService.getProjectDetailByProjectId(projectId);\n\n        //确定当前操作者属于该项目成员或者是管理员\n        if (!(ProjectUtils.isUserNameBelongProjectMember(operator, projectVO)\n              || ProjectUtils.isUserNameBelongProjectResponsible(operator, projectVO) || roleTool.isAdmin(operator))) {\n            return Result.buildParamIllegal(String.format(\"项目:[%s]不存在成员:[%s]\", projectIdStr, request));\n        }\n        final List<ESUser> users = esUserService.listESUsers(Collections.singletonList(projectId));\n        for (ESUser user : users) {\n            user.setName(projectVO.getProjectName());\n\n        }\n        return Result.buildSucc(ConvertUtil.list2List(users, ESUserVO.class));\n    }\n\n    /**\n     * 新建APP\n     *\n     * @param appDTO    dto\n     * @param projectId\n     * @param operator  操作人 邮箱前缀\n     * @return 成功 true  失败 false\n     */\n    @Override\n    public Result<Integer> registerESUser(ESUserDTO appDTO, Integer projectId, String operator) {\n        if (Objects.isNull(appDTO)){\n            return Result.buildFail(\"es user为空\");\n        }\n        initESUser(appDTO, projectId);\n\n        //检查esuser选择的集群并设置集群\n        Result<Void> checkClusterResult = checkClusterAuthAndSetCluster(appDTO);\n        if (checkClusterResult.failed()){\n            LOGGER.warn(\"class=ESUserManagerImpl||method=registerESUser||fail msg={}\", checkClusterResult.getMessage());\n            return Result.buildFail(checkClusterResult.getMessage());\n        }\n\n        final TupleTwo</*创建的es user*/Result, /*创建的es user po*/ ESUserPO> resultESUserPOTuple = esUserService\n            .registerESUser(appDTO, operator);\n\n        if (resultESUserPOTuple.v1().success()) {\n            // 操作记录\n            saveOperateRecord(\n                    String.format(\"新增访问模式:[%s]\", ProjectSearchTypeEnum.valueOf(appDTO.getSearchType()).getDesc()),\n                    projectId, operator, OperateTypeEnum.APPLICATION_ACCESS_MODE);\n\n        }\n\n        return resultESUserPOTuple.v1();\n    }\n    \n   \n    \n    /**\n     * @param esUserName   esUser\n     * @param projectId\n     * @param operator  操作人\n     * @return {@code Result<Void>}\n     */\n    @Override\n    public Result<Void> setDefaultDisplay(int esUserName, int projectId, String operator) {\n        if (!projectService.checkProjectExist(projectId)) {\n            return Result.buildFail(\"应用不存在\");\n        }\n        if (esUserService.getEsUserById(esUserName) == null) {\n            return Result.buildFail(\"es User不存在\");\n        }\n        if (esUserService.getEsUserById(esUserName).getDefaultDisplay() == true) {\n            return Result.buildFail(\"该es User是应用默认es User，无需进行设置\");\n        }\n\n        //获取当前应用下所有的esuser，并将之前应用默认的es user进行解绑\n        List<ESUser> esUsers = esUserService.listESUsers(Collections.singletonList(projectId));\n        for (ESUser esUser : esUsers) {\n            if (esUser.getDefaultDisplay() == true && esUser.getId()!=esUserName) {\n                Result<Void> result = unBindDefaultDisplay(esUser.getId(), projectId, operator);\n                if (result.failed()) {\n                    return Result.buildFail(String.format(\"解绑应用默认es User:%s失败，不能设置%s为应用默认es User\", esUser.getId(), esUserName));\n                }\n            }\n        }\n        ESUser esUser = esUserService.getEsUserById(esUserName);\n        //将需要设置为默认应用的es user进行存储\n        esUser.setDefaultDisplay(true);\n        TupleTwo<Result<Void>/*更新的状态*/, ESUserPO/*更新之后的的ESUserPO*/> resultESUserTuple = esUserService\n                .editUser(obj2Obj(esUser, ESUserDTO.class));\n        if (resultESUserTuple.v1().success()) {\n            //将操作记录进行保存\n            saveOperateRecord(String.format(\"将项目[%s]中es user:[%s]设置为项目默认的es user\", projectId, esUser),\n                    projectId, operator, OperateTypeEnum.APPLICATION_ACCESS_CHANGE);\n        }\n        return resultESUserTuple.v1();\n    }\n\n    /**\n     * @param esUserDTO   es user dto\n     * @param operator 操作人或角色\n     * @return {@code Result<Void>}\n     */\n    @Override\n    public Result<Void> editESUser(ESUserDTO esUserDTO, String operator) {\n        if (!projectService.checkProjectExist(esUserDTO.getProjectId())) {\n            return Result.buildFail(\"应用不存在\");\n        }\n        Result<Void> checkResult = esUserService.validateESUser(esUserDTO, EDIT);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=ESUserManagerImpl||method=editESUser||fail msg={}\", checkResult.getMessage());\n            return checkResult;\n        }\n        Result<Void> checkClusterResult = checkClusterAuthAndSetCluster(esUserDTO);\n        if (checkClusterResult.failed()) {\n            LOGGER.warn(\"class=ESUserManagerImpl||method=editESUser||fail msg={}\", checkClusterResult.getMessage());\n            return checkClusterResult;\n        }\n\n        //获取更新之前的po\n        final ESUser oldESUser = esUserService.getEsUserById(esUserDTO.getId());\n        //校验当前esUserDTO中的projectId是否存在于esUser\n        if (esUserDTO.getId() == 1) {\n            esUserDTO.setIsRoot(AdminConstant.YES);\n        }\n        //更新之后的结果获取\n        final TupleTwo<Result<Void>/*更新的状态*/, ESUserPO/*更新之后的的ESUserPO*/> resultESUserTuple = esUserService\n                .editUser(esUserDTO);\n\n        if (resultESUserTuple.v1().success()) {\n            // 操作记录\n            saveOperateRecord(String.format(\"修改访问模式:%s-->%s,修改访问集群:%s-->%s\",\n                            ProjectSearchTypeEnum.valueOf(oldESUser.getSearchType()).getDesc(),\n                            ProjectSearchTypeEnum.valueOf(esUserDTO.getSearchType()).getDesc(),oldESUser.getCluster(), esUserDTO.getCluster()), oldESUser.getProjectId(),\n                    operator, OperateTypeEnum.APPLICATION_ACCESS_CHANGE);\n        }\n        return resultESUserTuple.v1();\n    }\n\n    /**\n     * 删除项目下指定的es user\n     *\n     * @param esUser    esUser\n     * @param projectId\n     * @param operator  操作人\n     * @return 成功 true  失败 false\n     */\n    @Override\n    public Result<Void> deleteESUserByProject(int esUser, int projectId, String operator) {\n        if (!roleTool.isAdmin(operator)) {\n            return Result.buildFail(\"当前操作者权限不足,需要管理员权限\");\n        }\n        //校验当前项目下所有的es user\n        final List<ESUser> esUsers = esUserService.listESUsers(Collections.singletonList(projectId));\n\n        //校验当前项目中存在该es user\n        if (esUsers.stream().map(ESUser::getId).noneMatch(esUserName -> Objects.equals(esUserName, esUser))) {\n            return Result.buildParamIllegal(String.format(\"当前项目[%s]不存在es user:[%s]\", projectId,\n                esUsers.stream().map(ESUser::getId).collect(Collectors.toList())));\n        }\n        //判断删除之后的es user是否为项目使用的es user,如果是项目使用的默认es user，则需要解绑项目默认的es user 后才能进行es user的删除\n        if (esUsers.stream().anyMatch(oldESUser -> Objects.equals(oldESUser.getId(), esUser)\n                                                   && Boolean.TRUE.equals(oldESUser.getDefaultDisplay()))) {\n\n            return Result.buildFail(String.format(\"项目[%s]中es user:[%s],属于项目默认的es user,请先进行解绑\", projectId, esUser));\n        }\n        //进行es user的删除\n        final TupleTwo<Result<Void>, ESUserPO> resultESUserPOTuple = esUserService.deleteESUserById(esUser);\n        if (resultESUserPOTuple.v1().success()) {\n            // 操作记录\n            saveOperateRecord(String.format(\"删除访问模式:%s\",\n                            ProjectSearchTypeEnum.valueOf(resultESUserPOTuple.v2().getSearchType()).getDesc()), projectId,\n                    operator, OperateTypeEnum.APPLICATION_ACCESS_MODE);\n        }\n        return resultESUserPOTuple.v1();\n    }\n\n    /**\n     * 删除项目下所有的es user\n     *\n     * @param projectId 项目id\n     * @param operator  操作人或角色\n     * @return {@code Result<Void>}\n     */\n    @Override\n    public Result<Void> deleteAllESUserByProject(int projectId, String operator) {\n        if (!roleTool.isAdmin(operator)) {\n            return Result.buildFail(\"当前操作者权限不足,需要管理员权限\");\n        }\n\n        final TupleTwo<Result<Void>, List<ESUserPO>> resultListTuple = esUserService.deleteByESUsers(projectId);\n        if (resultListTuple.v1().success()) {\n            // 操作记录\n            saveOperateRecord(\"删除访问模式\", projectId, operator, OperateTypeEnum.APPLICATION_ACCESS_MODE);\n        }\n        return resultListTuple.v1();\n    }\n\n    /**\n     * 校验验证码\n     *\n     * @param esUserName app\n     * @param verifyCode 验证码\n     * @return result\n     */\n    @Override\n    public Result<Void> verifyAppCode(Integer esUserName, String verifyCode) {\n        return esUserService.verifyAppCode(esUserName, verifyCode);\n    }\n\n    @Override\n    public Result<ConsoleESUserVO> get(Integer esUser) {\n        return Result.buildSucc(ConvertUtil.obj2Obj(esUserService.getEsUserById(esUser), ConsoleESUserVO.class));\n    }\n\n    /**\n     * @param projectId\n     * @param operator\n     * @return\n     */\n    @Override\n    public Result<List<ConsoleESUserWithVerifyCodeVO>> getNoCodeESUser(Integer projectId, String operator) {\n\n        final ProjectVO projectVO = projectService.getProjectDetailByProjectId(projectId);\n        if (!(ProjectUtils.isUserNameBelongProjectMember(operator, projectVO)\n              || ProjectUtils.isUserNameBelongProjectResponsible(operator, projectVO) || roleTool.isAdmin(operator))) {\n            return Result.buildFail(\"权限不足\");\n        }\n        List<ESUser> users = esUserService.listESUsers(Collections.singletonList(projectId));\n        for (ESUser user : users) {\n            user.setName(projectVO.getProjectName());\n\n        }\n        return Result.buildSucc(ConvertUtil.list2List(users, ConsoleESUserWithVerifyCodeVO.class));\n\n    }\n     private void saveOperateRecord(String content, Integer projectId, String operator,\n                                   OperateTypeEnum operateTypeEnum) {\n        operateRecordService.saveOperateRecordWithManualTrigger(content,operator,projectId,projectId,operateTypeEnum);\n    }\n\n    /**\n     * 获取原生模式下项目的访问集群列表\n     * @param projectId\n     * @return Result<List<String>>\n     */\n    @Override\n    public Result<List<String>> listClusterByAppInPrimitiveType(Integer projectId) {\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            //超级projectId返回对应的独立的物理集群\n            List<String> clusterPhyList = clusterPhyService.listAllClusters().stream()\n                    .filter(clusterPhy -> ClusterResourceTypeEnum.PRIVATE.getCode() == clusterPhy.getResourceType())\n                    .map(ClusterPhy::getCluster)\n                    .distinct()\n                    .collect(Collectors.toList());\n            return Result.buildSucc(clusterPhyList);\n        } else {\n            //普通项目返回对应的独立的逻辑集群\n            List<String> clusterLogicList = clusterLogicService.getHasAuthClusterLogicsByProjectId(projectId).stream()\n                    .filter(clusterLogic -> ClusterResourceTypeEnum.PRIVATE.getCode() == clusterLogic.getType())\n                    .map(ClusterLogic::getName)\n                    .distinct().collect(Collectors.toList());\n            return Result.buildSucc(clusterLogicList);\n        }\n    }\n\n    /**\n     * 获取集群模式下项目的访问集群列表\n     * @param projectId\n     * @return Result<List<String>>\n     */\n    @Override\n    public Result<List<String>> listClusterByAppInClusterType(Integer projectId) {\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            //超级projectId返回对应的物理集群\n            List<String> clusterPhyList = clusterPhyService.listAllClusters().stream()\n                    .map(ClusterPhy::getCluster)\n                    .distinct()\n                    .collect(Collectors.toList());\n            return Result.buildSucc(clusterPhyList);\n        } else {\n            //普通项目返回对应的物理集群\n            List<Long> logicClusterIds = clusterLogicService.getHasAuthClusterLogicsByProjectId(projectId).stream()\n                    .map(ClusterLogic::getId)\n                    .distinct().collect(Collectors.toList());\n\n            // 找到 region\n            List<ClusterRegion> regions = clusterRegionService.getClusterRegionsByLogicIds(logicClusterIds);\n            if (CollectionUtils.isEmpty(regions)) {\n                return Result.buildFail(String.format(ES_USER_ERROR_MSG,\n                        ProjectSearchTypeEnum.PRIMITIVE.getDesc(), ProjectSearchTypeEnum.CLUSTER.getDesc()));\n            }\n            // 找到物理集群\n            List<String> clusterPhyList = regions.stream().map(ClusterRegion::getPhyClusterName).distinct()\n                    .collect(Collectors.toList());\n\n            return Result.buildSucc(clusterPhyList);\n        }\n    }\n\n    /**\n     * 对被设置为应用默认的es user进行解绑\n     *\n     * @param esUserName ES用户\n     * @param projectId\n     * @param operator 操作人 {@link   com.didichuxing.datachannel.arius.admin.core.component.RoleTool#isAdmin}\n     * @return {@code Result<Void>}\n     */\n    private Result<Void> unBindDefaultDisplay(int esUserName, int projectId, String operator) {\n        if (!roleTool.isAdmin(operator)) {\n            return Result.buildFail(\"当前操作者权限不足,需要管理员权限\");\n        }\n        if (!projectService.checkProjectExist(projectId)) {\n            return Result.buildFail(\"应用不存在\");\n        }\n        //获取需要进行解绑的默认es user并进行解绑\n        ESUser esUser = esUserService.getEsUserById(esUserName);\n        esUser.setDefaultDisplay(false);\n        TupleTwo<Result<Void>/*更新的状态*/, ESUserPO/*更新之后的的ESUserPO*/> resultESUserTuple = esUserService\n                .editUser(obj2Obj(esUser, ESUserDTO.class));\n        if (resultESUserTuple.v1().success()) {\n            //将操作记录进行保存\n            saveOperateRecord(String.format(\"项目[%s]中es user:[%s],属于项目默认的es user,对其进行解绑\", projectId, esUser),\n                    projectId, operator, OperateTypeEnum.APPLICATION_ACCESS_CHANGE);\n        }\n        return resultESUserTuple.v1();\n    }\n\n    /**\n     *  检查集群并设置集群\n     *\n     * @param esUserDTO 要创建的用户信息\n     */\n    private Result<Void> checkClusterAuthAndSetCluster(ESUserDTO esUserDTO) {\n        // 如果这里是集群模式或者原生模式，那么有且仅当项目下的物理集群唯一时，才可以被设置成功\n        Integer projectId = esUserDTO.getProjectId();\n       \n        ProjectSearchTypeEnum searchTypeEnum = ProjectSearchTypeEnum.valueOf(esUserDTO.getSearchType());\n       \n        if (!searchTypeEnum.equals(ProjectSearchTypeEnum.TEMPLATE)) {\n            //默认必须传集群\n            if (StringUtils.isBlank(esUserDTO.getCluster())) {\n                return Result.buildFail(String.format(ES_USER_ERROR_MSG,\n                        ProjectSearchTypeEnum.PRIMITIVE.getDesc(), ProjectSearchTypeEnum.CLUSTER.getDesc()));\n            }\n            // 如果是超级项目\n            if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n                return Result.buildSucc();\n            }\n            // 获取项目下的物理集群\n            ESLogicClusterDTO esLogicClusterDTO = new ESLogicClusterDTO();\n            esLogicClusterDTO.setProjectId(projectId);\n            List<ClusterLogic> clusterLogics = clusterLogicService.listClusterLogics(esLogicClusterDTO);\n            if (CollectionUtils.isEmpty(clusterLogics)) {\n                return Result.buildFail(String.format(ES_USER_ERROR_MSG,\n                        ProjectSearchTypeEnum.PRIMITIVE.getDesc(), ProjectSearchTypeEnum.CLUSTER.getDesc()));\n            }\n            List<Long> logicClusterIds = clusterLogics.stream().map(ClusterLogic::getId).distinct()\n                    .collect(Collectors.toList());\n            // 找到 region\n            List<ClusterRegion> regions = clusterRegionService.getClusterRegionsByLogicIds(logicClusterIds);\n            if (CollectionUtils.isEmpty(regions)) {\n                return Result.buildFail(String.format(ES_USER_ERROR_MSG,\n                        ProjectSearchTypeEnum.PRIMITIVE.getDesc(), ProjectSearchTypeEnum.CLUSTER.getDesc()));\n            }\n            // 找到物理集群\n            List<String> clusterPhyList = regions.stream().map(ClusterRegion::getPhyClusterName).distinct()\n                    .collect(Collectors.toList());\n          \n            // 如果存在 cluster 且没有匹配到具有权限的物理集群\n            if (StringUtils.isNotBlank(esUserDTO.getCluster()) && clusterPhyList.stream()\n                    .noneMatch(cp -> StringUtils.equals(cp, esUserDTO.getCluster()))) {\n                return Result.buildFail(String.format(\"应用没有 %s 集群的权限\", esUserDTO.getCluster()));\n            }\n        }\n        // 索引模式默认集群设置未 null\n        if (searchTypeEnum.equals(ProjectSearchTypeEnum.TEMPLATE)) {\n            esUserDTO.setCluster(\"\");\n        }\n        return Result.buildSucc();\n    }\n    \n    private static void initESUser(ESUserDTO appDTO, Integer projectId) {\n        appDTO.setProjectId(projectId);\n        appDTO.setVerifyCode(VerifyCodeFactory.get(VERIFY_CODE_LENGTH));\n        appDTO.setIsActive(1);\n        if (Objects.isNull(appDTO.getQueryThreshold())) {\n            appDTO.setQueryThreshold(1000);\n        }\n        if (Objects.isNull(appDTO.getIsRoot())) {\n            appDTO.setIsRoot(0);\n        }\n        appDTO.setMemo(\"新增\");\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/impl/LoginManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project.impl;\n\nimport static com.didiglobal.knowframework.security.util.HttpRequestUtil.COOKIE_OR_SESSION_MAX_AGE_UNIT_SEC;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.LoginManager;\nimport com.didichuxing.datachannel.arius.admin.common.exception.OperateForbiddenException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleThree;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didiglobal.knowframework.security.common.Result;\nimport com.didiglobal.knowframework.security.common.dto.account.AccountLoginDTO;\nimport com.didiglobal.knowframework.security.common.enums.ResultCode;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.exception.KfSecurityException;\nimport com.didiglobal.knowframework.security.service.LoginService;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.util.AESUtils;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Objects;\nimport javax.servlet.http.Cookie;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * 登录管理器\n *\n * @author shizeying\n * @date 2022/06/16\n */\n@Component\npublic class LoginManagerImpl implements LoginManager {\n    @Autowired\n    private LoginService        loginService;\n    @Autowired\n    private ProjectService      projectService;\n    @Autowired\n    private RoleTool            roleTool;\n    public static final String  KNOW_SEARCH_TOKEN = \"knowSearchToken\";\n    private static final String STRING_SPLIT      = \"||\";\n\n    /**\n     * 验证登录信息（验证前密码先用Base64解码再用RSA解密） 登录前会检查账户激活状态\n     *\n     * @param loginDTO 登陆信息\n     * @param request  请求信息\n     * @param response\n     * @return token\n     */\n    @Override\n    public Result<UserBriefVO> verifyLogin(AccountLoginDTO loginDTO, HttpServletRequest request,\n                                           HttpServletResponse response) {\n\n        try {\n            UserBriefVO userBriefVO = loginService.verifyLogin(loginDTO, request, response);\n            //response设置平台独有cookie\n            addCookieByKnowSearch(userBriefVO.getUserName(), response);\n            return Result.success(userBriefVO);\n        } catch (KfSecurityException e) {\n            return Result.fail(e);\n        }\n    }\n\n    /**\n     * 登出接口\n     *\n     * @param request\n     * @param response\n     * @return\n     */\n    @Override\n    public Result<Boolean> logout(HttpServletRequest request, HttpServletResponse response) {\n        return loginService.logout(request, response);\n    }\n\n    /**\n     * @param request\n     * @param response\n     * @param requestMappingValue\n     * @param whiteMappingValues\n     * @return\n     * @throws IOException\n     */\n    @Override\n    public boolean interceptorCheck(HttpServletRequest request, HttpServletResponse response,\n                                    String requestMappingValue,\n                                    List<String> whiteMappingValues) throws IOException, OperateForbiddenException {\n        boolean interceptorCheck = loginService.interceptorCheck(request, response, requestMappingValue,\n            whiteMappingValues);\n        TupleThree</*username*/String, /*userId*/Integer, /*projectId*/Integer> userNameAndUserIdAndProjectIdTuple3 = getRequestByHead(\n            request);\n        //当用户登录成功/或者跳过白名单之后，就默认用户已经存在了header cookie等信息，此时需要确认项目和用户的一致性\n        if (interceptorCheck) {\n\n            //跳过检查项目id和用户的正确性和匹配度\n            if (whiteMappingValues.stream()\n                .noneMatch(whiteMappingValue -> request.getServletPath().startsWith(whiteMappingValue))) {\n                if (hasLoginValidExtend(userNameAndUserIdAndProjectIdTuple3.v1, request)) {\n\n                    //项目id没有带\n                    if (Objects.isNull(userNameAndUserIdAndProjectIdTuple3.v3)) {\n\n                        throw new OperateForbiddenException(\n                            String.format(\"请携带项目信息,HTTP_HEADER_KEY:%s\", HttpRequestUtil.PROJECT_ID));\n                    }\n                    if (Objects.isNull(userNameAndUserIdAndProjectIdTuple3.v2)) {\n                        throw new OperateForbiddenException(\n                            String.format(\"请携带操作者id,HTTP_HEADER_KEY:%s\", HttpRequestUtil.USER_ID));\n\n                    }\n                    if (StringUtils.isBlank(userNameAndUserIdAndProjectIdTuple3.v1)) {\n                        throw new OperateForbiddenException(\n                            String.format(\"请携带操作者,HTTP_HEADER_KEY:%s\", HttpRequestUtil.USER));\n\n                    }\n\n                    if (!projectService.checkProjectExist(userNameAndUserIdAndProjectIdTuple3.v3)) {\n                        throw new KfSecurityException(ResultCode.PROJECT_NOT_EXISTS);\n                    }\n                    //判断用户在非管理员角色下，操作用户是否是当前项目成员或者拥有者\n                    if (!roleTool.isAdmin(userNameAndUserIdAndProjectIdTuple3.v2)) {\n                        final ProjectVO projectVO = projectService\n                            .getProjectDetailByProjectId(userNameAndUserIdAndProjectIdTuple3.v3);\n                        if (!(ProjectUtils.isUserNameBelongProjectMember(userNameAndUserIdAndProjectIdTuple3.v1,\n                            projectVO)\n                              || ProjectUtils.isUserNameBelongProjectResponsible(userNameAndUserIdAndProjectIdTuple3.v1,\n                                  projectVO))) {\n                            throw new KfSecurityException(ResultCode.NO_PERMISSION);\n                        }\n\n                    }\n\n                }\n            }\n        }\n\n        return interceptorCheck;\n    }\n\n    private void addCookieByKnowSearch(String userName, HttpServletResponse response) {\n        //这里对domainAccount 进行加密处理，避免用户通过自行修改domainAccount进行替换用户的场景\n        String plaintext = userName + STRING_SPLIT + System.currentTimeMillis();\n        String ciphertext = AESUtils.encrypt(plaintext);\n        Cookie cookieCiphertext = new Cookie(KNOW_SEARCH_TOKEN, ciphertext);\n        cookieCiphertext.setMaxAge(COOKIE_OR_SESSION_MAX_AGE_UNIT_SEC);\n        cookieCiphertext.setPath(\"/\");\n        response.addCookie(cookieCiphertext);\n    }\n\n    /**\n     * 扩展验证ks是否篡改登录信息\n     *\n     * @param userName 用户名\n     * @param request  请求\n     * @return boolean\n     */\n    private boolean hasLoginValidExtend(String userName, HttpServletRequest request) {\n        Cookie[] cookies = request.getCookies();\n        if (AriusObjUtils.isNull(cookies)) {\n            return false;\n        }\n        return Arrays.stream(cookies).filter(cookie -> KNOW_SEARCH_TOKEN.equals(cookie.getName()))\n            .map(cookie -> AESUtils.decrypt(cookie.getValue())).filter(Objects::nonNull)\n            .map(plaintext -> StringUtils.split(plaintext, STRING_SPLIT)).filter(plaintexts -> plaintexts.length == 2)\n            .map(plaintexts -> plaintexts[0])\n            .anyMatch(domainAccountInner -> StringUtils.equals(domainAccountInner, userName));\n    }\n\n    /**\n     * 通过请求头获取user name usernameId projectId\n     *\n     * @param request 请求\n     * @return {@code Tuple3<String, Integer, Integer>}\n     */\n    private TupleThree</*username*/String, /*userId*/Integer, /*projectId*/Integer> getRequestByHead(HttpServletRequest request) {\n        TupleThree<String, Integer, Integer> tuple3 = Tuples.of(null, null, null);\n        final String operator = HttpRequestUtil.getOperator(request);\n        final Integer operatorId = HttpRequestUtil.getOperatorId(request);\n        final Integer projectId = HttpRequestUtil.getProjectId(request);\n        if (StringUtils.isNotBlank(operator)) {\n            tuple3 = tuple3.update1(operator);\n        }\n        if (Objects.nonNull(operatorId) && operatorId > 0) {\n            tuple3 = tuple3.update2(operatorId);\n        }\n        if (Objects.nonNull(projectId) && projectId > 0) {\n            tuple3 = tuple3.update3(projectId);\n        }\n        return tuple3;\n\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/impl/OperateRecordManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.page.OperateRecordPageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.biz.project.OperateRecordManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.operaterecord.OperateRecordVO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.ModuleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Component;\n\nimport java.util.ArrayList;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.COMMA;\n\n/**\n * 操作记录\n *\n * @author shizeying\n * @date 2022/06/17\n */\n@Component\npublic class OperateRecordManagerImpl implements OperateRecordManager {\n    private static final ILog    LOGGER = LogFactory.getLog(OperateRecordManagerImpl.class);\n    private static final Long    FROM = 0L;\n    private static final Long    SIZE = 1L;\n    @Autowired\n    private HandleFactory        handleFactory;\n    @Autowired\n    private OperateRecordService   operateRecordService;\n    @Autowired\n    private AriusConfigInfoService ariusConfigInfoService;\n    @Autowired\n    private ProjectService projectService;\n    @Autowired\n    private UserService userService;\n    \n    /**\n     * 0 0 1 * * ? 每天凌晨 1 点执行该方法 定时删除操作日志，根据配置中指定的保存天数对操作日志进行保留\n     */\n    @Scheduled(cron = \"0 0 1 * * ?\")\n    public void scheduledDeletionOldOperateRecord() {\n        Date saveTime = getSaveTime();\n        LOGGER.info(\n                \"class=OperateRecordServiceImpl||method=scheduledDeletionOldOperateRecord||msg= 操作日志定时删除任务开始执行\");\n        try {\n            operateRecordService.deleteExprieData(saveTime);\n        } catch (Exception e) {\n            LOGGER.error(\"class=OperateRecordServiceImpl||method=scheduledDeletionOldOperateRecord||errMsg={}\",\n                    e.getMessage());\n        }\n    }\n\n    /**\n     * 获得配置中设置的保存时间\n     *\n     * @param\n     * @return Date\n     */\n    private Date getSaveTime() {\n        Date currentTime = new Date();\n        Date saveTime = new Date();\n        Calendar calendar = Calendar.getInstance();\n        calendar.setTime(currentTime);\n        calendar.add(Calendar.DAY_OF_MONTH,-ariusConfigInfoService.intSetting(\n                AriusConfigConstant.ARIUS_COMMON_GROUP,AriusConfigConstant.OPERATE_RECORD_SAVE_TIME,\n                AriusConfigConstant.OPERATE_RECORD_SAVE_TIME_DEFAULT_VALUE));\n        saveTime = calendar.getTime();\n        return saveTime;\n    }\n\n    /**\n     * oplogvo\n     *\n     * @param queryDTO  查询dto\n     * @param projectId\n     * @return {@code PagingResult<OplogVO>}\n     */\n    @Override\n    public PaginationResult<OperateRecordVO> pageOplogPage(OperateRecordDTO queryDTO,\n                                                           Integer projectId) throws NotFindSubclassException {\n        final BaseHandle baseHandle = handleFactory\n            .getByHandlerNamePer(PageSearchHandleTypeEnum.OPERATE_RECORD.getPageSearchType());\n        if (baseHandle instanceof OperateRecordPageSearchHandle) {\n            OperateRecordPageSearchHandle pageSearchHandle = (OperateRecordPageSearchHandle) baseHandle;\n            return pageSearchHandle.doPage(queryDTO, projectId);\n        }\n\n        LOGGER.warn(\n            \"class=OperateRecordManagerImpl||method=pageOplogPage||msg=failed to get the OperateRecordPageSearchHandle\");\n\n        return PaginationResult.buildFail(\"操作日志获取失败\");\n    }\n\n    /**\n     * 获取oplog\n     *\n     * @param id id\n     * @return {@code Result<OplogVO>}\n     */\n    @Override\n    public Result<OperateRecordVO> getOplogDetailByOplogId(Integer id) {\n\n        return Result.buildSucc(operateRecordService.getById(id));\n    }\n\n    /**\n     * sense查询记录\n     * @param queryDTO 查询条件\n     * @param operator 用户名称\n     * @param projectId 项目id\n     * @return\n     */\n    @Override\n    public Result<List<String>> listSenseOperateRecord(OperateRecordDTO queryDTO, String operator, Integer projectId) {\n        //组装查询条件\n        buildCommonOperateRecordDTO(projectId, queryDTO, operator);\n        queryDTO.setFrom(FROM);\n        queryDTO.setSize(SIZE);\n        List<OperateRecordVO> operateRecordVOList = operateRecordService.queryCondition(queryDTO);\n        List<String> operateRecordList = new ArrayList<>();\n        if(CollectionUtils.isEmpty(operateRecordVOList)){\n            //只有拥有管理员权限的才能被赋予默认命令\n            final List<UserBriefVO> userBriefListWithAdminRole = userService.getUserBriefListByRoleId(AuthConstant.ADMIN_ROLE_ID);\n            if(userBriefListWithAdminRole.stream().map(UserBriefVO::getUserName).anyMatch(userName->operator.equals(userName))\n                    && AuthConstant.SUPER_PROJECT_ID.equals(projectId)){\n                //查询平台配置中的超级应用的默认命令\n                List<String> superAppDefaultCommandList = new ArrayList<>(ariusConfigInfoService.stringSettingSplit2Set(AriusConfigConstant.ARIUS_COMMON_GROUP\n                        , AriusConfigConstant.SUPER_APP_DEFALT_DSL_COMMAND,\n                        AriusConfigConstant.SUPER_APP_DEFALT_DSL_COMMAND_VALUE, COMMA));\n                operateRecordList.addAll(superAppDefaultCommandList);\n            }\n        }else{\n            operateRecordList = operateRecordVOList.stream().map(OperateRecordVO::getContent).collect(Collectors.toList());\n        }\n        return Result.buildSucc(operateRecordList);\n    }\n\n    @Override\n    public Result<Integer> updateSenseOperateRecord(OperateRecordDTO operateRecordDTO, String operator, Integer projectId) {\n        buildCommonOperateRecordDTO(projectId, operateRecordDTO, operator);\n        Result<Integer> result = operateRecordService.updateOperateRecord(operateRecordDTO);\n        if (result.failed()) {\n            LOGGER.warn(\"class=OperateRecordManagerImpl||method=updateSenseOperateRecord||errMsg={}\",\n                    \"用户DSL查询记录更新出错\");\n        }\n        return result;\n    }\n\n    /**\n     * 组装参数\n     *\n     * @param projectId\n     * @param operateRecordDTO\n     * @param operator\n     */\n    private void buildCommonOperateRecordDTO(Integer projectId, OperateRecordDTO operateRecordDTO, String operator) {\n        String projectName = projectService.getProjectBriefByProjectId(projectId).getProjectName();\n        operateRecordDTO.setOperateId(OperateTypeEnum.DSL_QUERY_RECORD.getCode());\n        operateRecordDTO.setModuleId(ModuleEnum.DSL_QUERY.getCode());\n        operateRecordDTO.setTriggerWayId(TriggerWayEnum.MANUAL_TRIGGER.getCode());\n        operateRecordDTO.setUserOperation(operator);\n        operateRecordDTO.setProjectName(projectName);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/impl/PermissionExtendManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.PermissionExtendManager;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didiglobal.knowframework.security.common.Result;\nimport com.didiglobal.knowframework.security.common.vo.permission.PermissionTreeVO;\nimport com.didiglobal.knowframework.security.service.PermissionService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * 扩展管理器impl许可\n *\n * @author shizeying\n * @date 2022/06/14\n */\n@Component\npublic class PermissionExtendManagerImpl implements PermissionExtendManager {\n    @Autowired\n    private PermissionService permissionService;\n\n    /**\n     * 建立资源owner角色权限树\n     *\n     * @return {@code Result<PermissionTreeVO>}\n     */\n    @Override\n    public Result<PermissionTreeVO> buildPermissionTreeByResourceOwn() {\n        final PermissionTreeVO permissionTreeVO = permissionService\n            .buildPermissionTreeByRoleId(AuthConstant.RESOURCE_OWN_ROLE_ID);\n        return Result.buildSucc(permissionTreeVO);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/impl/ProjectClusterLogicAuthManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project.impl;\n\nimport com.baomidou.mybatisplus.core.toolkit.CollectionUtils;\nimport com.didichuxing.datachannel.arius.admin.biz.project.ProjectClusterLogicAuthManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectClusterLogicAuthService;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author linyunan\n * @date 2021-04-28\n */\n@Component\npublic class ProjectClusterLogicAuthManagerImpl implements ProjectClusterLogicAuthManager {\n    @Autowired\n    private ProjectService                 projectService;\n\n    @Autowired\n    private ProjectClusterLogicAuthService projectClusterLogicAuthService;\n\n    @Override\n    public List<ProjectClusterLogicAuth> getByClusterLogicListAndProjectId(Integer projectId,\n                                                                           List<ClusterLogic> clusterLogicList) {\n        List<ProjectClusterLogicAuth> projectClusterLogicAuthList = Lists.newArrayList();\n        if (CollectionUtils.isEmpty(clusterLogicList)) {\n            return projectClusterLogicAuthList;\n        }\n\n        if (!projectService.checkProjectExist(projectId)) {\n            projectClusterLogicAuthList = clusterLogicList.stream().map(r -> projectClusterLogicAuthService\n                .buildClusterLogicAuth(projectId, r.getId(), ProjectClusterLogicAuthEnum.NO_PERMISSIONS))\n                .collect(Collectors.toList());\n            return projectClusterLogicAuthList;\n        }\n\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            projectClusterLogicAuthList = clusterLogicList.stream().map(r -> projectClusterLogicAuthService\n                .buildClusterLogicAuth(projectId, r.getId(), ProjectClusterLogicAuthEnum.OWN))\n                .collect(Collectors.toList());\n            return projectClusterLogicAuthList;\n        }\n\n        projectClusterLogicAuthList = clusterLogicList.stream()\n            .map(clusterLogic -> projectClusterLogicAuthService.getLogicClusterAuth(projectId, clusterLogic.getId()))\n            .collect(Collectors.toList());\n\n        //处理无权限\n        for (ProjectClusterLogicAuth projectClusterLogicAuth : projectClusterLogicAuthList) {\n            if (null == projectClusterLogicAuth.getType()) {\n                projectClusterLogicAuth.setType(ProjectClusterLogicAuthEnum.NO_PERMISSIONS.getCode());\n            }\n        }\n        return projectClusterLogicAuthList;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/impl/ProjectConfigManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.ProjectConfigManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectConfigVO;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectConfigService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n *\n *\n * @author shizeying\n * @date 2022/06/06\n */\n@Component\npublic class ProjectConfigManagerImpl implements ProjectConfigManager {\n    @Autowired\n    private ProjectConfigService projectConfigService;\n\n    /**\n     * 获取esUserName配置信息\n     *\n     * @param projectId@return 配置信息\n     */\n    @Override\n    public Result<ProjectConfigVO> get(int projectId) {\n        final ProjectConfigVO projectConfigVo = ConvertUtil.obj2Obj(projectConfigService.getProjectConfig(projectId),\n            ProjectConfigVO.class);\n        return Result.buildSucc(projectConfigVo);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/impl/ProjectExtendManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.core.service.project.impl.ESUserServiceImpl.VERIFY_CODE_LENGTH;\n\nimport com.baomidou.mybatisplus.core.toolkit.ObjectUtils;\nimport com.didichuxing.datachannel.arius.admin.biz.project.ProjectExtendManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ESUserDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectExtendSaveDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectQueryExtendDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterLogicTemplateIndexDetailDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectBriefExtendVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectConfigVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectExtendVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectSearchTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.VerifyCodeFactory;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ESUserService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectConfigService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didiglobal.knowframework.security.common.PagingData;\nimport com.didiglobal.knowframework.security.common.PagingResult;\nimport com.didiglobal.knowframework.security.common.dto.project.ProjectQueryDTO;\nimport com.didiglobal.knowframework.security.common.dto.project.ProjectSaveDTO;\nimport com.didiglobal.knowframework.security.common.enums.project.ProjectUserCode;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectDeleteCheckVO;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectVO;\nimport com.didiglobal.knowframework.security.common.vo.role.RoleBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserVO;\nimport com.didiglobal.knowframework.security.exception.KfSecurityException;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.service.RoleService;\nimport com.didiglobal.knowframework.security.service.UserProjectService;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.function.BiConsumer;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\nimport java.util.stream.Collectors;\nimport javax.servlet.http.HttpServletRequest;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.jetbrains.annotations.NotNull;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * logi 项目的扩展能力 将logi中整体能力全部移动到这里\n *\n * @author shizeying\n * @date 2022/06/10\n */\n@Component\npublic class ProjectExtendManagerImpl implements ProjectExtendManager {\n\n    @Autowired\n    private ProjectConfigService projectConfigService;\n    @Autowired\n    private ProjectService       projectService;\n    @Autowired\n    private ESUserService        esUserService;\n    @Autowired\n    private OperateRecordService operateRecordService;\n    @Autowired\n    private ClusterLogicService  clusterLogicService;\n    @Autowired\n    private IndexTemplateService indexTemplateService;\n    @Autowired\n    private UserService          userService;\n    @Autowired\n    private UserProjectService   userProjectService;\n    @Autowired\n    private RoleService          roleService;\n    @Autowired\n    private RoleTool          roleTool;\n    @Autowired\n    private               ESIndexCatService esIndexCatService;\n    private static final FutureUtil<Void> FUTURE_UTIL = FutureUtil.init(\"ProjectExtendManagerImpl\", 10, 10, 100);\n    \n    /**\n     * “检查一个项目的资源是否可用。”\n     * <p>\n     * 函数定义如下：\n     * <p>\n     * * 该函数返回一个 Result<Void> 对象。 * 该函数接受一个参数，一个名为 projectId 的整数对象\n     *\n     * @param projectId 项目的 ID。\n     * @return 一个 Result 对象，里面有一个 Void 对象。\n     */\n    @Override\n    public Result<Void> checkResourcesByProjectId(Integer projectId) {\n        List<ClusterLogic> clusterLogics = clusterLogicService.getOwnedClusterLogicListByProjectId(projectId);\n        \n        List<ClusterLogicTemplateIndexDetailDTO> clusterLogicTemplateIndexDetailDTOS = clusterLogics.stream()\n                .map(clusterLogic -> getTemplateIndexVO(clusterLogic, projectId))\n                \n                .collect(Collectors.toList());\n        long templateSize = clusterLogicTemplateIndexDetailDTOS.stream()\n                .map(ClusterLogicTemplateIndexDetailDTO::getTemplates).filter(CollectionUtils::isNotEmpty)\n                .mapToLong(Collection::size).sum();\n        long indexSize = clusterLogicTemplateIndexDetailDTOS.stream()\n                .map(ClusterLogicTemplateIndexDetailDTO::getCatIndexResults).filter(CollectionUtils::isNotEmpty)\n                .mapToLong(Collection::size).sum();\n        if (CollectionUtils.isNotEmpty(clusterLogics) || templateSize != 0 || indexSize != 0) {\n            return Result.buildFail(String.format(\n                    \"无法删除 %s！如需删除，请下线掉应用关联的全部集群、模板、索引资源。\",\n                    projectService.getProjectDetailByProjectId(projectId).getProjectName()));\n        }\n        \n        return Result.buildSucc();\n    }\n    \n    @Override\n    public Result<ProjectExtendVO> createProject(ProjectExtendSaveDTO saveDTO, String operator, Integer operatorId) {\n        try {\n            // 1. 创建项目\n            ProjectSaveDTO project = saveDTO.getProject();\n            // 2. 创建项目配置\n            ProjectConfigDTO config = saveDTO.getConfig();\n            // 将项目中的所有者、用户提取出来后，使用biz层中的逻辑进行添加\n            List<Integer> ownerIdList = Optional.ofNullable(project.getOwnerIdList()).orElse(Lists.newArrayList());\n            List<Integer> userIdList = Optional.ofNullable(project.getUserIdList()).orElse(Lists.newArrayList());\n            project.setOwnerIdList(Collections.emptyList());\n            project.setUserIdList(Collections.emptyList());\n            //当所有者没有传入进来的时候\n            if (CollectionUtils.isEmpty(ownerIdList)) {\n                if (operatorId.equals(-1)) {\n                    return Result.buildFail(\"当前操作人id为空\");\n                }\n                ownerIdList.add(operatorId);\n\n            }\n            // 谁创建、谁包含\n            if (!ownerIdList.contains(operatorId)) {\n                ownerIdList.add(operatorId);\n            }\n            if (!userIdList.contains(operatorId)) {\n                userIdList.add(operatorId);\n            }\n\n            // 3. 创建项目\n            ProjectVO projectVO = projectService.createProject(project, operator);\n            // 4. 转换\n            ProjectExtendVO projectExtendVO = ConvertUtil.obj2Obj(projectVO, ProjectExtendVO.class);\n            // 5. 添加拥有者和成员\n            addOwnerAndUsers(operator, ownerIdList, userIdList, projectVO, projectExtendVO);\n\n            //5. 设置项目id\n            config.setProjectId(projectVO.getId());\n            // 6. 创建项目配置\n            TupleTwo<Result<Void>, ProjectConfigPO> resultProjectConfigTuple = projectConfigService\n                .updateOrInitProjectConfig(config, operator);\n        \n            // 全量获取具有管理员角色的用户\n            final List<UserBriefVO> userBriefListWithAdminRole = userService.getUserBriefListByRoleId(AuthConstant.ADMIN_ROLE_ID);\n            buildProjectExtendVO(projectExtendVO,userBriefListWithAdminRole);\n            // 设置项目配置\n            if (resultProjectConfigTuple.v1().success()) {\n                projectExtendVO.setConfig(ConvertUtil.obj2Obj(resultProjectConfigTuple.v2(), ProjectConfigVO.class));\n\n            }\n            //7. 写入操作日志\n            operateRecordService.save(new OperateRecord(project.getProjectName(), OperateTypeEnum.APPLICATION_CREATE,\n                TriggerWayEnum.MANUAL_TRIGGER, project.getProjectName(), operator));\n            //创建es user\n            createESUserDefault(projectVO, operator);\n            if (Objects.isNull(project.getId())) {\n                projectExtendVO.setId(projectExtendVO.getConfig().getProjectId());\n            }\n            return Result.<ProjectExtendVO> buildSucc(projectExtendVO);\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    private void addOwnerAndUsers(String operator, List<Integer> ownerIdList, List<Integer> userIdList,\n                                  ProjectVO projectVO, ProjectExtendVO projectExtendVO) {\n        if (CollectionUtils.isNotEmpty(ownerIdList)) {\n            addProjectOwner(projectVO.getId(), ownerIdList, operator);\n            Optional.ofNullable(userService.getUserBriefListByUserIdList(ownerIdList))\n                .ifPresent(projectExtendVO::setOwnerList);\n        }\n        if (CollectionUtils.isNotEmpty(userIdList)) {\n            addProjectUser(projectVO.getId(), userIdList, operator);\n            Optional.ofNullable(userService.getUserBriefListByUserIdList(userIdList))\n                .ifPresent(projectExtendVO::setUserList);\n        }\n    }\n\n    @Override\n    public Result<ProjectExtendVO> getProjectDetailByProjectId(Integer projectId) {\n        try {\n            ProjectVO projectVO = projectService.getProjectDetailByProjectId(projectId);\n            ProjectExtendVO projectExtendVO = ConvertUtil.obj2Obj(projectVO, ProjectExtendVO.class);\n            \n            // 全量获取具有管理员角色的用户\n            final List<UserBriefVO> userBriefListWithAdminRole =userService.getUserBriefListByRoleId(AuthConstant.ADMIN_ROLE_ID);\n            buildProjectExtendVO(projectExtendVO, userBriefListWithAdminRole);\n            ProjectConfig projectConfig = projectConfigService.getProjectConfig(projectId);\n            projectExtendVO.setConfig(ConvertUtil.obj2Obj(projectConfig, ProjectConfigVO.class));\n            return Result.buildSucc(projectExtendVO);\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    /**\n     * 设置超级项目\n     *\n     * @param projectExtendVO 项目延长签证官\n     */\n    private void buildProjectExtendVO(ProjectExtendVO projectExtendVO, List<UserBriefVO> userBriefListWithAdminRole) {\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectExtendVO.getId())) {\n    \n            projectExtendVO.setUserList(userBriefListWithAdminRole);\n            projectExtendVO.setOwnerList(userBriefListWithAdminRole);\n            projectExtendVO.setUserListWithBelongProjectAndAdminRole(userBriefListWithAdminRole);\n            projectExtendVO.setUserListWithAdminRole(userBriefListWithAdminRole);\n            \n            projectExtendVO.setIsAdmin(true);\n        } else {\n    \n            List<UserBriefVO> useList = Optional.ofNullable(projectExtendVO.getUserList()).orElse(Lists.newArrayList());\n            projectExtendVO.setUserList(useList.stream().filter(CommonUtils.distinctByKey(UserBriefVO::getId))\n                    .collect(Collectors.toList()));\n            projectExtendVO.setOwnerList(\n                    projectExtendVO.getOwnerList().stream().filter(CommonUtils.distinctByKey(UserBriefVO::getId))\n                            .collect(Collectors.toList()));\n            useList.addAll(userBriefListWithAdminRole);\n            // 具有管理员角色和持有项目用户的项目成员\n            final List<UserBriefVO> userListWithBelongProjectAndAdminRole = useList.stream()\n                    .filter(CommonUtils.distinctByKey(UserBriefVO::getId)).collect(Collectors.toList());\n            projectExtendVO.setUserListWithAdminRole(userBriefListWithAdminRole);\n            projectExtendVO.setUserListWithBelongProjectAndAdminRole(userListWithBelongProjectAndAdminRole);\n            \n        }\n    }\n\n    @Override\n    public Result<List<ProjectBriefExtendVO>> getProjectBriefList() {\n        List<ProjectBriefVO> projectBriefList = projectService.getProjectBriefList();\n        List<ProjectBriefExtendVO> projectBriefExtendList = ConvertUtil.list2List(projectBriefList,\n            ProjectBriefExtendVO.class);\n        return getListResult(projectBriefExtendList);\n    }\n\n    @Override\n    public Result<Void> deleteProjectByProjectId(Integer projectId, String operator) {\n        //项目删除前的检查\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            return Result.buildFail(\"系统内置项目，不能删除\");\n        }\n        // 校验项目绑定逻辑集群\n        Result<Void> result = checkResourcesByProjectId(projectId);\n        if (result.failed()) {\n            return result;\n        }\n        ProjectBriefVO projectBriefVO = projectService.getProjectBriefByProjectId(projectId);\n        projectService.deleteProjectByProjectId(projectId, operator);\n        //获取全部项目配置\n        List<ESUser> esUsers = esUserService.listESUsers(Collections.singletonList(projectId));\n\n        //删除es user\n        esUserService.deleteByESUsers(projectId);\n        for (ESUser esUser : esUsers) {\n            operateRecordService.save(new OperateRecord(projectBriefVO.getProjectName(),\n                OperateTypeEnum.APPLICATION_ACCESS_MODE, TriggerWayEnum.MANUAL_TRIGGER,\n                String.format(\"删除访问模式:%s\", ProjectSearchTypeEnum.valueOf(esUser.getSearchType()).getDesc()), operator));\n        }\n        operateRecordService.save(new OperateRecord(projectBriefVO.getProjectName(), OperateTypeEnum.APPLICATION_DELETE,\n            TriggerWayEnum.MANUAL_TRIGGER, projectBriefVO.getProjectName(), operator));\n        return Result.buildSucc();\n    }\n\n    /**\n     * 根据项目id获取项目简要信息\n     *\n     * @param projectId 项目id\n     * @return 项目简要信息\n     */\n    @Override\n    public Result<ProjectBriefExtendVO> getProjectBriefByProjectId(Integer projectId) {\n        final ProjectBriefVO projectBriefVO = projectService.getProjectBriefByProjectId(projectId);\n        final ProjectBriefExtendVO projectBriefExtendVO = ConvertUtil.obj2Obj(projectBriefVO,\n            ProjectBriefExtendVO.class);\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectBriefExtendVO.getId())) {\n            projectBriefExtendVO.setIsAdmin(true);\n        }\n        ProjectConfig projectConfig = projectConfigService.getProjectConfig(projectBriefExtendVO.getId());\n        projectBriefExtendVO.setConfig(ConvertUtil.obj2Obj(projectConfig, ProjectConfigVO.class));\n        return Result.buildSucc(projectBriefExtendVO);\n    }\n\n    /**\n     * 条件分页查询项目信息\n     *\n     * @param queryDTO 条件信息\n     * @param request\n     * @return 项目分页信息\n     */\n    @Override\n    public PagingResult<ProjectExtendVO> getProjectPage(ProjectQueryExtendDTO queryDTO, HttpServletRequest request) {\n        final Set<Integer> projectIds = Sets.newHashSet();\n        final List<Integer> esUserByProjectIds = Lists.newArrayList();\n        //当查询模式不为空\n        if (Objects.nonNull(queryDTO.getSearchType())) {\n            final List<Integer> projectIdBySearchType = esUserService\n                .getProjectIdBySearchType(queryDTO.getSearchType());\n            if (CollectionUtils.isEmpty(projectIdBySearchType)) {\n                return PagingResult\n                    .success(new PagingData<>(Collections.emptyList(), PagingData.Pagination.builder().build()));\n            } else {\n                esUserByProjectIds.addAll(projectIdBySearchType);\n\n            }\n        }\n        String operator = HttpRequestUtil.getOperator(request);\n        Integer operatorId = HttpRequestUtil.getOperatorId(request);\n        //如果当前操作人不是管理员的角色，则只应该获取属于自己的项目，不能获取全部的项目\n        if (StringUtils.isNotBlank(operator) && !roleTool.isAdmin(operator)) {\n\n            final List<Integer> operatorIdByProjectIds = userProjectService\n                .getProjectIdListByUserIdList(Collections.singletonList(operatorId));\n            //esUserByProjectIds、operatorIdByProjectIds取交集\n            if (CollectionUtils.isNotEmpty(esUserByProjectIds)) {\n                projectIds.addAll(\n                    Sets.intersection(Sets.newHashSet(esUserByProjectIds), Sets.newHashSet(operatorIdByProjectIds)));\n            } else {\n                projectIds.addAll(operatorIdByProjectIds);\n            }\n\n        } else {\n            projectIds.addAll(esUserByProjectIds);\n        }\n        /**\n         * 1.管理员角色的用户\n         * \t应用列表:全部展示()\n         * \t编辑能力:应该具备\n         * \t删除能力:应该具备\n         * 2.非管理员角色的用户:\n         * \t应用列表:\n         * \t\t非检索状态下:展示自己拥有的应用列表\n         * \t\t编辑能力:应该具备\n         * \t\t删除能力:应该具备\n         * \t\t检索状态下 :  假如A应用不属于当前的用户,是否可以被检索出来(不能)\n         * \t\t编辑能力   :  假如A应用不属于当前的用户,是否可以被编辑(不能)\n         * \t\t删除能力  :   假如A应用不属于当前的用户,是否可以被删除 (不能)\n         */\n        final ProjectQueryDTO projectQueryDTO = ConvertUtil.obj2Obj(queryDTO, ProjectQueryDTO.class);\n        if(StringUtils.isNotBlank(projectQueryDTO.getProjectName())){\n            projectQueryDTO.setProjectName(CommonUtils.sqlFuzzyQueryTransfer(projectQueryDTO.getProjectName()));\n        }\n        final PagingData<ProjectVO> projectPage = projectService.getProjectPage(projectQueryDTO, Lists.newArrayList(projectIds));\n        final List<ProjectExtendVO> projectExtendVOList = ConvertUtil.list2List(projectPage.getBizData(),\n            ProjectExtendVO.class);\n        //全量获取具有管理员角色的用户\n        final List<UserBriefVO> userBriefListWithAdminRole =\n                userService.getUserBriefListByRoleId(AuthConstant.ADMIN_ROLE_ID);\n        for (ProjectExtendVO projectExtendVO : projectExtendVOList) {\n            FUTURE_UTIL.runnableTask(() -> {\n                \n                buildProjectExtendVO(projectExtendVO,userBriefListWithAdminRole);\n                final ProjectConfig projectConfig = projectConfigService.getProjectConfig(projectExtendVO.getId());\n                projectExtendVO.setConfig(ConvertUtil.obj2Obj(projectConfig, ProjectConfigVO.class));\n            });\n        }\n        FUTURE_UTIL.waitExecute();\n        return PagingResult.success(new PagingData<>(projectExtendVOList, projectPage.getPagination()));\n    }\n\n    /**\n     * 更新项目信息 不支持更新责任人和成员\n     *\n     * @param saveDTO  项目信息\n     * @param operator 请求信息\n     */\n    @Override\n    public Result<Void> updateProject(ProjectExtendSaveDTO saveDTO, String operator) {\n        try {\n            final ProjectConfigDTO config = saveDTO.getConfig();\n            if (Objects.nonNull(config) && ObjectUtils.isNotEmpty(config)) {\n                final Integer id = saveDTO.getProject().getId();\n                config.setProjectId(id);\n                //只有success时候会存在tuple._2不为null\n                projectConfigService.updateOrInitProjectConfig(config, operator);\n            }\n            final ProjectSaveDTO project = saveDTO.getProject();\n         \n            project.setOwnerIdList(Collections.emptyList());\n            project.setUserIdList(Collections.emptyList());\n            //操作前的项目信息\n            projectService.updateProject(project, operator);\n            return Result.buildSucc();\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    /**\n     * 操作项目成员/项目拥有者\n     *\n     * @param operator        操作人或角色\n     * @param beforeProjectVo         操作前的项目id\n     * @param userOrOwnerList 添加/更新用户id列表\n     * @param operationConsumerFunc    更新/添加操作\n     * @param  operationFuncMapper      函数映射器 需要获取的mapper userList/ownerList\n     * @param operateTypeEnum 操作类型枚举\n     * @param operation       是否是删除操作\n     * @return {@code Result<Void>}\n     */\n    private Result<Void> operationProjectMemberOrOwner(String operator, ProjectVO beforeProjectVo,\n                                                       List<Integer> userOrOwnerList,\n                                                       BiConsumer<Integer, List<Integer>> operationConsumerFunc,\n                                                       Function<ProjectVO, List<UserBriefVO>> operationFuncMapper,\n                                                       OperateTypeEnum operateTypeEnum, OperationEnum operation) {\n        //超级项目侧校验添加的用户收否存在管理员角色\n        final Result<Void> result = checkProject(beforeProjectVo.getId(), userOrOwnerList, operation);\n        if (result.failed()) {\n            return result;\n        }\n    \n        final String projectName = beforeProjectVo.getProjectName();\n        List<UserBriefVO> beforeProjectUserList = Lists.newArrayList();\n        //操作前的\n        Optional.ofNullable(beforeProjectVo).map(operationFuncMapper).ifPresent(beforeProjectUserList::addAll);\n        //更新/add\n        operationConsumerFunc.accept(beforeProjectVo.getId(), userOrOwnerList);\n        //操作后\n        List<UserBriefVO> afterProjectUserList = Lists.newArrayList();\n        Optional.ofNullable(projectService.getProjectDetailByProjectId(beforeProjectVo.getId()))\n                .map(operationFuncMapper).ifPresent(afterProjectUserList::addAll);\n        TupleTwo</*beforeUserStr*/String, /*afterUserStr*/String> tuple2 = projectOwnerOrMemberChangeStr(\n                beforeProjectUserList, afterProjectUserList);\n        recordProjectOwnerOrUserChange(tuple2, projectName, operator, operateTypeEnum);\n        return Result.buildSucc();\n    }\n\n    /**\n     * 更改项目运行状态，旧状态取反\n     *\n     * @param projectId 项目id\n     * @param operator  请求信息\n     */\n    @Override\n    public Result<Void> changeProjectStatus(Integer projectId, String operator) {\n        try {\n            projectService.changeProjectStatus(projectId, operator);\n            return Result.buildSucc();\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    /**\n     * 增加项目成员\n     *\n     * @param projectId  项目id\n     * @param userIdList 项目id\n     * @param operator   请求信息\n     */\n    @Override\n    public Result<Void> addProjectUser(Integer projectId, List<Integer> userIdList, String operator) {\n        try {\n            final ProjectVO beforeProjectVo = projectService.getProjectDetailByProjectId(projectId);\n            final Result<Void> operationProjectUserResult = operationProjectMemberOrOwner(operator, beforeProjectVo,\n                userIdList, (id, userList) -> userProjectService.updateUserProject(id, userList), ProjectVO::getUserList,\n                OperateTypeEnum.APPLICATION_USER_CHANGE, OperationEnum.ADD);\n            if (operationProjectUserResult.failed()) {\n                return operationProjectUserResult;\n            }\n            return Result.buildSucc();\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n\n    }\n\n    /**\n     * 删除项目成员\n     *\n     * @param projectId 项目id\n     * @param userId    项目id\n     * @param operator  请求信息\n     */\n    @Override\n    public Result<Void> delProjectUser(Integer projectId, Integer userId, String operator) {\n        try {\n            //操作前\n            final ProjectVO beforeProjectVo = projectService.getProjectDetailByProjectId(projectId);\n            Consumer<TupleTwo</*projectId*/Integer, /*userId*/Integer>> delProjectUserConsumer = tupleTwo -> projectService\n                .delProjectUser(tupleTwo.v1, tupleTwo.v2, operator);\n            final Result<Void> operationProjectOwnerResult = operationProjectMemberOrOwner(operator, beforeProjectVo,\n                Collections.singletonList(userId),\n                (id, userList) -> userList.stream().map(user -> Tuples.of(id, user)).forEach(delProjectUserConsumer),\n                ProjectVO::getOwnerList, OperateTypeEnum.APPLICATION_USER_CHANGE, OperationEnum.DELETE\n\n            );\n            if (operationProjectOwnerResult.failed()) {\n                return operationProjectOwnerResult;\n            }\n            return Result.buildSucc();\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    /**\n     * 增加项目负责人\n     *\n     * @param projectId   项目id\n     * @param ownerIdList 负责人id\n     * @param operator    请求信息\n     */\n    @Override\n    public Result<Void> addProjectOwner(Integer projectId, List<Integer> ownerIdList, String operator) {\n        try {\n            final ProjectVO beforeProjectVo = projectService.getProjectDetailByProjectId(projectId);\n            final Result<Void> operationProjectOwnerResult = operationProjectMemberOrOwner(operator, beforeProjectVo,\n                ownerIdList, (id, ownerList) -> userProjectService.updateOwnerProject(id, ownerList),\n                ProjectVO::getOwnerList, OperateTypeEnum.APPLICATION_OWNER_CHANGE, OperationEnum.ADD\n\n            );\n            if (operationProjectOwnerResult.failed()) {\n                return operationProjectOwnerResult;\n            }\n\n            return Result.buildSucc();\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    /**\n     * 删除项目负责人\n     *\n     * @param projectId 项目id\n     * @param ownerId   负责人id\n     * @param operator  请求信息\n     */\n    @Override\n    public Result<Void> delProjectOwner(Integer projectId, Integer ownerId, String operator) {\n        try {\n            //操作前\n            final ProjectVO beforeProjectVo = projectService.getProjectDetailByProjectId(projectId);\n            Consumer<TupleTwo</*projectId*/Integer, /*ownerId*/Integer>> delProjectUserConsumer = tupleTwo -> projectService\n                .delProjectOwner(tupleTwo.v1, tupleTwo.v2, operator);\n            final Result<Void> operationProjectOwnerResult = operationProjectMemberOrOwner(operator, beforeProjectVo,\n                Collections.singletonList(ownerId),\n                (id, userList) -> userList.stream().map(user -> Tuples.of(id, user)).forEach(delProjectUserConsumer),\n                ProjectVO::getOwnerList, OperateTypeEnum.APPLICATION_USER_CHANGE, OperationEnum.DELETE\n\n            );\n            if (operationProjectOwnerResult.failed()) {\n                return operationProjectOwnerResult;\n            }\n\n            return Result.buildSucc();\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    /**\n     * 项目删除前的检查\n     *\n     * @param projectId 项目id\n     * @return ProjectDeleteCheckVO 检查结果\n     */\n    @Override\n    public Result<ProjectDeleteCheckVO> checkBeforeDelete(Integer projectId) {\n        return Result.buildSucc(projectService.checkBeforeDelete(projectId));\n    }\n\n    /**\n     * 校验项目是否存在\n     *\n     * @param projectId\n     * @return true:存在，false：不存在\n     */\n    @Override\n    public Result<Void> checkProjectExist(Integer projectId) {\n        if (projectService.checkProjectExist(projectId)) {\n            return Result.buildSucc();\n        } else {\n            return Result.buildFail(\"项目不存在\");\n        }\n    }\n\n    /**\n     * 未分配项目的用户列表\n     *\n     * @param projectId         projectId\n     * @param containsAdminRole\n     * @return {@code Result}\n     */\n    @Override\n    public Result<List<UserBriefVO>> unassignedByProjectId(Integer projectId, Boolean containsAdminRole) {\n        final com.didiglobal.knowframework.security.common.Result<List<UserBriefVO>> listResult = projectService\n            .unassignedByProjectId(projectId);\n        if (listResult.successed()) {\n            //如果为false则不包含管理员角色的用户\n            if (Boolean.FALSE.equals(containsAdminRole)){\n                final List<Integer> userBriefListWithAdminRole =\n                userService.getUserBriefListByRoleId(AuthConstant.ADMIN_ROLE_ID)\n                        .stream()\n                        .map(UserBriefVO::getId).distinct().collect(Collectors.toList());\n                final List<UserBriefVO> userBriefVOList = listResult.getData().stream()\n                        .filter(i -> !userBriefListWithAdminRole.contains(i.getId()))\n                        .distinct().collect(Collectors.toList());\n                return Result.buildSucc(userBriefVOList);\n            }\n            \n            \n            return Result.buildSucc(listResult.getData());\n        } else {\n            return Result.buildFail(listResult.getMessage());\n        }\n\n    }\n\n    /**\n     * @param projectId 项目id\n     * @return\n     */\n    @Override\n    public Result<List<UserBriefVO>> listUserListByProjectId(Integer projectId) {\n        final List<Integer> userIdLists = userProjectService.getUserIdListByProjectId(projectId,\n            ProjectUserCode.NORMAL);\n        userIdLists.addAll(userProjectService.getUserIdListByProjectId(projectId, ProjectUserCode.OWNER));\n        return Result.buildSucc(userService.getUserBriefListByUserIdList(userIdLists));\n    }\n\n    /**\n     * 获取user下绑定的项目\n     *\n     * @param userId 用户id\n     * @return {@code Result<List<ProjectBriefVO>>}\n     */\n    @Override\n    public Result<List<ProjectBriefExtendVO>> getProjectBriefByUserId(Integer userId) {\n        final com.didiglobal.knowframework.security.common.Result<List<ProjectBriefVO>> listResult = projectService\n            .getProjectBriefByUserId(userId);\n        if (listResult.successed()) {\n            final List<ProjectBriefExtendVO> dtoList = ConvertUtil.list2List(listResult.getData(),\n                ProjectBriefExtendVO.class).stream()\n                    .filter(CommonUtils.distinctByKey(ProjectBriefVO::getId)).collect(Collectors.toList());\n            return getListResult(dtoList);\n        } else {\n            return Result.buildFail(listResult.getMessage());\n        }\n    }\n\n    @NotNull\n    private Result<List<ProjectBriefExtendVO>> getListResult(List<ProjectBriefExtendVO> projectBriefExtendList) {\n        for (ProjectBriefExtendVO projectBriefExtendVO : projectBriefExtendList) {\n            if (AuthConstant.SUPER_PROJECT_ID.equals(projectBriefExtendVO.getId())) {\n                projectBriefExtendVO.setIsAdmin(true);\n            }\n            ProjectConfig projectConfig = projectConfigService.getProjectConfig(projectBriefExtendVO.getId());\n            projectBriefExtendVO.setConfig(ConvertUtil.obj2Obj(projectConfig, ProjectConfigVO.class));\n        }\n        return Result.buildSucc(projectBriefExtendList);\n    }\n\n    /**\n     * 新增默认的es user\n     *\n     * @param data 数据\n     */\n    private void createESUserDefault(ProjectVO data, String operator) {\n        ESUserDTO esUserDTO = new ESUserDTO();\n        esUserDTO.setIsRoot(0);\n        esUserDTO.setSearchType(ProjectSearchTypeEnum.TEMPLATE.getCode());\n        esUserDTO.setVerifyCode(VerifyCodeFactory.get(VERIFY_CODE_LENGTH));\n        esUserDTO.setMemo((data).getProjectName() + \"项目默认的es user\");\n        esUserDTO.setProjectId((data).getId());\n        esUserDTO.setMemo(\"创建项目es user\");\n        final TupleTwo<Result, ESUserPO> result = esUserService.registerESUser(esUserDTO, operator);\n        if (result.v1().success()) {\n            operateRecordService.save(new OperateRecord(data.getProjectName(), OperateTypeEnum.APPLICATION_ACCESS_MODE,\n                TriggerWayEnum.MANUAL_TRIGGER, String.format(\"新增访问模式:%s\", ProjectSearchTypeEnum.TEMPLATE.getDesc()),\n                operator, result.v2().getId()));\n\n        }\n    }\n\n    private Result<Void> checkProject(Integer projectId, List<Integer> userIdList, OperationEnum operation) {\n        if (operation.equals(OperationEnum.DELETE)) {\n            return Result.buildSucc();\n        }\n      \n        if (Objects.isNull(projectId)) {\n            return Result.buildParamIllegal(\"项目id不存在\");\n        }\n        if (!projectService.checkProjectExist(projectId)) {\n            return Result.buildParamIllegal(String.format(\"项目%s不存在\", projectId));\n        }\n        //校验当前用户id是否存在\n        final List<UserVO> userList = userIdList.stream().map(userService::getUserDetailByUserId)\n            .collect(Collectors.toList());\n        if (userList.size() != userIdList.size()) {\n            final List<Integer> idList = userList.stream().map(UserVO::getId).collect(Collectors.toList());\n            //不存在用户id集合\n            String notExitsIds = userIdList.stream().filter(id -> !idList.contains(id)).distinct().map(String::valueOf)\n                .collect(Collectors.joining(\"，\"));\n            return Result.buildParamIllegal(String.format(\"传入用户:%s不存在\", notExitsIds));\n        }\n        //超级项目侧校验添加的用户收否存在管理员角色\n        if (operation.equals(OperationEnum.EDIT)) {\n            if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n                Predicate<List<RoleBriefVO>> checkContainsAdminRoleFunc = roleBriefList -> roleBriefList.stream()\n                    .anyMatch(roleBriefVO -> AuthConstant.ADMIN_ROLE_ID.equals(roleBriefVO.getId()));\n                /*当前用户列表中存在管理员*/\n                if (CollectionUtils.isNotEmpty(userIdList)&&userIdList.stream().map(roleService::getRoleBriefListByUserId)\n                    .noneMatch(checkContainsAdminRoleFunc)) {\n                    return Result.buildFail(\"超级项目只被允许添加拥有管理员角色的用户\");\n\n                }\n            }\n\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 项目所有者或成员改变str\n     *\n     * @param beforeProjectAddOwnerOrUserList 之前项目添加所有者列表\n     * @param afterProjectAddOwnerUserList    在项目添加所有者列表\n     * @return {@code Tuple2<String, String>}\n     */\n    private TupleTwo</*beforeOwnerUserName*/String, /*afterOwnerUserName*/String> projectOwnerOrMemberChangeStr(List<UserBriefVO> beforeProjectAddOwnerOrUserList,\n                                                                                                                List<UserBriefVO> afterProjectAddOwnerUserList) {\n        String beforeOwnerUserName = beforeProjectAddOwnerOrUserList.stream().map(UserBriefVO::getUserName).sorted()\n            .collect(Collectors.joining(\",\"));\n        String afterOwnerUserName = afterProjectAddOwnerUserList.stream().map(UserBriefVO::getUserName).sorted()\n            .collect(Collectors.joining(\",\"));\n        return Tuples.of(beforeOwnerUserName, afterOwnerUserName);\n\n    }\n\n    /**\n     * 记录项目的所有者或者成员的变更\n     *\n     * @param tuple2      tuple2\n     * @param projectName 项目名称\n     * @param operator    操作人或角色\n     */\n    private void recordProjectOwnerOrUserChange(TupleTwo</*beforeOwnerOrUser*/String, /*afterOwnerOrUser*/String> tuple2,\n                                                String projectName, String operator, OperateTypeEnum operateTypeEnum) {\n        if (!StringUtils.equals(tuple2.v1, tuple2.v2)) {\n            String content=StringUtils.isBlank(tuple2.v1)?String.format(\"新增:【%s】\",tuple2.v2):\n                    StringUtils.isBlank(tuple2.v2)?String.format(\"删除:【%s】\",tuple2.v1):String.format(\"【%s】-->【%s】\",\n                            tuple2.v1,tuple2.v2 );\n            \n            operateRecordService.save(new OperateRecord.Builder()\n\n                .projectName(projectName).operationTypeEnum(operateTypeEnum)\n                .triggerWayEnum(TriggerWayEnum.MANUAL_TRIGGER).content(content)\n                .userOperation(operator).build());\n        }\n    }\n    \n   \n    \n    private ClusterLogicTemplateIndexDetailDTO getTemplateIndexVO(ClusterLogic clusterLogic, Integer projectId) {\n        IndexTemplateDTO param = new IndexTemplateDTO();\n        param.setResourceId(clusterLogic.getId());\n        param.setProjectId(projectId);\n        List<IndexTemplate> indexTemplates = indexTemplateService.listLogicTemplates(param);\n        // 通过逻辑集群获取 index\n        List<IndexCatCellDTO> catIndexResults = esIndexCatService.syncGetIndexByCluster(clusterLogic.getName(),\n                projectId);\n        ClusterLogicTemplateIndexDetailDTO templateIndexVO = new ClusterLogicTemplateIndexDetailDTO();\n        templateIndexVO.setCatIndexResults(catIndexResults);\n        templateIndexVO.setTemplates(indexTemplates);\n        return templateIndexVO;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/impl/ProjectLogicTemplateAuthManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.ProjectLogicTemplateAuthManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectTemplateAuthDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateLogicWithClusterAndMasterTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectTemplateAuthVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * Created by linyunan on 2021-06-15\n */\n@Component\npublic class ProjectLogicTemplateAuthManagerImpl implements ProjectLogicTemplateAuthManager {\n\n    @Autowired\n    private ProjectLogicTemplateAuthService projectLogicTemplateAuthService;\n    @Autowired\n    private ProjectService                  projectService;\n    @Autowired\n    private OperateRecordService            operateRecordService;\n    @Autowired\n    private IndexTemplateService            indexTemplateService;\n\n    /**\n     * @param authDTO\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    @Override\n    public Result<Void> addTemplateAuth(ProjectTemplateAuthDTO authDTO, String operator, Integer projectId) {\n        Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(ProjectTemplateAuthDTO::getProjectId,\n            authDTO, projectId);\n        if (checkProjectCorrectly.failed()) {\n            return checkProjectCorrectly;\n        }\n\n        Result<Void> voidResult = projectLogicTemplateAuthService.addTemplateAuth(authDTO);\n        if (voidResult.success()) {\n            final ProjectTemplateAuthEnum projectTemplateAuthEnum = ProjectTemplateAuthEnum.valueOf(authDTO.getType());\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"权限变更：%s\", projectTemplateAuthEnum.getDesc()), operator, projectId,\n                    authDTO.getId(), OperateTypeEnum.TEMPLATE_MANAGEMENT_INFO_MODIFY);\n\n        }\n        return voidResult;\n    }\n\n    /**\n     * @param delete\n     * @return\n     */\n    @Override\n    public Result<Void> deleteRedundancyTemplateAuths(boolean delete) {\n        return Result.build(projectLogicTemplateAuthService.deleteRedundancyTemplateAuths(true));\n    }\n\n    /**\n     * 得到app模板身份验证\n     *\n     * @param projectId 项目id\n     * @return {@link Result}<{@link List}<{@link ProjectTemplateAuthVO}>>\n     */\n    @Override\n    public Result<List<ProjectTemplateAuthVO>> getProjectTemplateAuths(Integer projectId) {\n        List<ProjectTemplateAuthVO> templateAuths = ConvertUtil.list2List(\n            projectLogicTemplateAuthService.getProjectActiveTemplateRWAndRAuths(projectId),\n            ProjectTemplateAuthVO.class);\n\n        fillTemplateAuthVO(templateAuths);\n        return Result.buildSucc(templateAuths);\n    }\n\n    /**\n     * @param authId\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    @Override\n    public Result<Void> deleteTemplateAuth(Long authId, String operator, Integer projectId) {\n        Integer belongToProject = projectLogicTemplateAuthService.getProjectIdById(authId);\n        Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(i -> i, belongToProject, projectId);\n        if (checkProjectCorrectly.failed()) {\n            return checkProjectCorrectly;\n        }\n        Result<Void> result = projectLogicTemplateAuthService.deleteTemplateAuth(authId);\n        if (result.success()) {\n    \n            operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"删除模板，模板 id：%s\", authId),\n                    operator, projectId, authId, OperateTypeEnum.TEMPLATE_MANAGEMENT_OFFLINE);\n        }\n        return result;\n    }\n\n    @Override\n    public Result<Void> updateTemplateAuth(ProjectTemplateAuthDTO authDTO, String operator) {\n        if (AriusObjUtils.isNull(authDTO)) {\n            return Result.buildFail(\"更新权限信息不存在\");\n        }\n\n        if (AriusObjUtils.isNull(authDTO.getType())) {\n            return Result.buildFail(\"更新权限类型不存在\");\n        }\n\n        List<Integer> appTemplateAuthCodes = ProjectTemplateAuthEnum.listAppTemplateAuthCodes();\n        if (!appTemplateAuthCodes.contains(authDTO.getType())) {\n            return Result.buildFail(\"更新权限类型不支持\");\n        }\n\n        ProjectTemplateAuth projectTemplateAuth = projectLogicTemplateAuthService\n            .getTemplateRWAuthByLogicTemplateIdAndProjectId(authDTO.getTemplateId(), authDTO.getProjectId());\n\n        if (AriusObjUtils.isNull(projectTemplateAuth)) {\n            return Result.buildFail(\"权限信息不存在\");\n        }\n\n        if (AriusObjUtils.isNull(projectTemplateAuth.getType())) {\n            return Result.buildFail(\"权限信息不存在\");\n        }\n\n        if (authDTO.getType().equals(projectTemplateAuth.getType())) {\n            return Result.buildSucc();\n        }\n\n        projectTemplateAuth.setType(authDTO.getType());\n        final Result<Void> result = projectLogicTemplateAuthService.updateTemplateAuth(\n                ConvertUtil.obj2Obj(projectTemplateAuth, ProjectTemplateAuthDTO.class));\n        if (result.success()) {\n            final ProjectTemplateAuthEnum projectTemplateAuthEnum = ProjectTemplateAuthEnum.valueOf(authDTO.getType());\n    \n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"权限变更：【%s】\", projectTemplateAuthEnum.getDesc()), operator, authDTO.getProjectId(),\n                    authDTO.getId(), OperateTypeEnum.TEMPLATE_MANAGEMENT_INFO_MODIFY);\n        }\n        return result;\n    \n    }\n\n    /**\n    * 给AppTemplateAuthVO设置所属逻辑集群ID、name，逻辑模板name\n    * @param templateAuths 模板权限列表\n    */\n    private void fillTemplateAuthVO(List<ProjectTemplateAuthVO> templateAuths) {\n        if (CollectionUtils.isEmpty(templateAuths)) {\n            return;\n        }\n\n        // 涉及的逻辑模板id\n        List<Integer> templateIds = templateAuths.stream().map(ProjectTemplateAuthVO::getTemplateId)\n            .collect(Collectors.toList());\n\n        Map<Integer, IndexTemplateLogicWithClusterAndMasterTemplate> logicTemplateMap = indexTemplateService\n            .getLogicTemplatesWithClusterAndMasterTemplateMap(new HashSet<>(templateIds));\n\n        for (ProjectTemplateAuthVO authVO : templateAuths) {\n            Integer templateId = authVO.getTemplateId();\n            IndexTemplateLogicWithClusterAndMasterTemplate logicTemplate = logicTemplateMap.get(templateId);\n            if (logicTemplate != null) {\n                // 逻辑模板信息\n                authVO.setTemplateName(logicTemplate.getName());\n                // 逻辑集群信息\n                ClusterLogic logicCluster = logicTemplate.getLogicCluster();\n                // 物理模板被删除后有可能没有集群信息\n                if (logicCluster != null) {\n                    authVO.setLogicClusterId(logicCluster.getId());\n                    authVO.setLogicClusterName(logicCluster.getName());\n                } else {\n                    authVO.setLogicClusterName(\"\");\n                }\n            } else {\n                authVO.setTemplateName(\"\");\n            }\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/impl/RoleExtendManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.RoleExtendManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.RoleExtendVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didiglobal.knowframework.security.common.PagingData;\nimport com.didiglobal.knowframework.security.common.PagingData.Pagination;\nimport com.didiglobal.knowframework.security.common.PagingResult;\nimport com.didiglobal.knowframework.security.common.dto.role.RoleAssignDTO;\nimport com.didiglobal.knowframework.security.common.dto.role.RoleQueryDTO;\nimport com.didiglobal.knowframework.security.common.dto.role.RoleSaveDTO;\nimport com.didiglobal.knowframework.security.common.vo.role.AssignInfoVO;\nimport com.didiglobal.knowframework.security.common.vo.role.RoleBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.role.RoleDeleteCheckVO;\nimport com.didiglobal.knowframework.security.common.vo.role.RoleVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.exception.KfSecurityException;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.service.RoleService;\nimport com.didiglobal.knowframework.security.service.UserProjectService;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport com.google.common.collect.Lists;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport javax.servlet.http.HttpServletRequest;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * 扩展管理器角色impl\n *\n * @author shizeying\n * @date 2022/06/16\n */\n@Component\npublic class RoleExtendManagerImpl implements RoleExtendManager {\n    @Autowired\n    private RoleService          roleService;\n    @Autowired\n    private OperateRecordService operateRecordService;\n    @Autowired\n    private UserProjectService   userProjectService;\n    @Autowired\n    private ProjectService       projectService;\n    @Autowired\n    private UserService          userService;\n\n    /**\n     * @param id\n     * @param request\n     * @return\n     */\n    @Override\n    public Result deleteRoleByRoleId(Integer id, HttpServletRequest request) {\n        if (AuthConstant.RESOURCE_OWN_ROLE_ID.equals(id) || AuthConstant.ADMIN_ROLE_ID.equals(id)) {\n            return Result.buildFail(String.format(\"属于内置角色:[%s]，不可以被删除\", id));\n        }\n        try {\n            final RoleBriefVO roleBriefByRoleId = roleService.getRoleBriefByRoleId(id);\n            final RoleDeleteCheckVO roleDeleteCheckVO = roleService.checkBeforeDelete(id);\n            if (CollectionUtils.isNotEmpty(roleDeleteCheckVO.getUserNameList())) {\n                final RoleVO roleVO = roleService.getRoleDetailByRoleId(id);\n                return Result.buildFailWithMsg(roleDeleteCheckVO,\n                    String.format(\"角色:[%s]已经分配给用了,不允许删除,请先解除分配的用户再试！\", roleVO.getRoleName()));\n            }\n            roleService.deleteRoleByRoleId(id, request);\n            saveOperateRecord(HttpRequestUtil.getOperator(request),\n                    String.format(\"删除角色:[%s]\", roleBriefByRoleId.getRoleName()),\n                    OperateTypeEnum.ROLE_MANAGER_DELETE);\n            return Result.buildSucc();\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    @Override\n    public Result<RoleExtendVO> getRoleDetailByRoleId(Integer roleId) {\n        final RoleVO roleVO = roleService.getRoleDetailByRoleId(roleId);\n        final RoleExtendVO roleExtendVO = ConvertUtil.obj2Obj(roleVO, RoleExtendVO.class);\n        if (Objects.equals(roleExtendVO.getId(), AuthConstant.RESOURCE_OWN_ROLE_ID)\n            || Objects.equals(roleExtendVO.getId(), AuthConstant.ADMIN_ROLE_ID)) {\n            roleExtendVO.setIsDefaultRole(true);\n        }\n        return Result.buildSucc(roleExtendVO);\n    }\n\n    @Override\n    public PagingResult<RoleExtendVO> getRolePage(RoleQueryDTO queryDTO) {\n        if(StringUtils.isNotBlank(queryDTO.getRoleName())){\n            queryDTO.setRoleName(CommonUtils.sqlFuzzyQueryTransfer(queryDTO.getRoleName()));\n        }\n        if(StringUtils.isNotBlank(queryDTO.getDescription())){\n            queryDTO.setDescription(CommonUtils.sqlFuzzyQueryTransfer(queryDTO.getDescription()));\n        }\n        final PagingData<RoleVO> rolePage = roleService.getRolePage(queryDTO);\n        final List<RoleVO> bizData = rolePage.getBizData();\n        final List<RoleExtendVO> roleExtendVOList = ConvertUtil.list2List(bizData, RoleExtendVO.class);\n        for (RoleExtendVO roleExtendVO : roleExtendVOList) {\n            if (Objects.equals(roleExtendVO.getId(), AuthConstant.RESOURCE_OWN_ROLE_ID)\n                || Objects.equals(roleExtendVO.getId(), AuthConstant.ADMIN_ROLE_ID)) {\n                roleExtendVO.setIsDefaultRole(true);\n            }\n        }\n        final Pagination pagination = rolePage.getPagination();\n        return PagingResult.success(new PagingData<>(roleExtendVOList, pagination));\n    }\n\n    @Override\n    public Result<Void> createRole(RoleSaveDTO saveDTO, HttpServletRequest request) {\n        try {\n            roleService.createRole(saveDTO, request);\n            saveOperateRecord(HttpRequestUtil.getOperator(request), String.format(\"新增角色:[%s]\", saveDTO.getRoleName()),\n                    OperateTypeEnum.ROLE_MANAGER_CREATE);\n            return Result.buildSucc();\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    @Override\n    public Result<Void> deleteUserFromRole(Integer roleId, Integer userId, HttpServletRequest request) {\n        try {\n            roleService.deleteUserFromRole(roleId, userId, request);\n            //如果改角色为超级管理员、那么需要一并删除超级项目的管理能力\n            if (AuthConstant.ADMIN_ROLE_ID.equals(roleId)) {\n                userProjectService.delOwnerProject(AuthConstant.SUPER_PROJECT_ID, Collections.singletonList(userId));\n                userProjectService.delUserProject(AuthConstant.SUPER_PROJECT_ID, Collections.singletonList(userId));\n            }\n            final RoleBriefVO roleBriefByRoleId = roleService.getRoleBriefByRoleId(roleId);\n            final UserBriefVO userBriefVO = userService.getUserBriefListByUserIdList(Collections.singletonList(userId))\n                .get(0);\n            saveOperateRecord(HttpRequestUtil.getOperator(request),\n                    String.format(\"角色:[%s] 解绑的用户:[%s]\", roleBriefByRoleId.getRoleName(),\n                            userBriefVO.getUserName()), OperateTypeEnum.ROLE_MANAGER_UNBIND_USER);\n            return Result.buildSucc();\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    @Override\n    public Result<Void> updateRole(RoleSaveDTO saveDTO, HttpServletRequest request) {\n        try {\n            roleService.updateRole(saveDTO, request);\n            return Result.buildSucc();\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    @Override\n    public Result<Void> assignRoles(RoleAssignDTO assignDTO, HttpServletRequest request) {\n        try {\n            roleService.assignRoles(assignDTO, request);\n\n            List<Integer> userIds = Lists.newArrayList();\n            List<Integer> roleIds = Lists.newArrayList();\n\n            if (Boolean.TRUE.equals(assignDTO.getFlag())) {\n                //true：N个角色分配给1个用户\n                userIds.add(assignDTO.getId());\n                roleIds.addAll(assignDTO.getIdList());\n\n            } else {\n                //false：1个角色分配给N个用户\n                userIds.addAll(assignDTO.getIdList());\n                roleIds.add(assignDTO.getId());\n\n            }\n            String roleNames = roleIds.stream().map(roleService::getRoleBriefByRoleId).map(RoleBriefVO::getRoleName)\n                .sorted().distinct().collect(Collectors.joining(\",\"));\n            String userNames = userService.getUserBriefListByUserIdList(userIds).stream().map(UserBriefVO::getUserName)\n                .sorted().distinct().collect(Collectors.joining(\",\"));\n            String operator = HttpRequestUtil.getOperator(request);\n            saveOperateRecord(operator, String.format(\"角色列表:[%s] 解绑的用户列表:[%s]\", roleNames, userNames),\n                    OperateTypeEnum.ROLE_MANAGER_BIND_USER);\n            return Result.buildSucc();\n\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n    \n   \n    \n    @Override\n    public Result<List<AssignInfoVO>> getAssignInfoByRoleId(Integer roleId) {\n        return Result.buildSucc(roleService.getAssignInfoByRoleId(roleId));\n    }\n\n    @Override\n    public Result<List<RoleBriefVO>> getRoleBriefListByRoleName(String roleName) {\n        return Result.buildSucc(roleService.getRoleBriefListByRoleName(roleName));\n    }\n    \n    private void saveOperateRecord(String operator, String content, OperateTypeEnum operateTypeEnum) {\n        operateRecordService.save(new OperateRecord.Builder().userOperation(operator).operationTypeEnum(operateTypeEnum)\n                .project(projectService.getProjectBriefByProjectId(AuthConstant.SUPER_PROJECT_ID)).content(content)\n                .triggerWayEnum(TriggerWayEnum.MANUAL_TRIGGER).build());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/project/impl/UserExtendManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.UserExtendManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.UserExtendDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.UserQueryExtendDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.UserExtendVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.UserWithPwVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didiglobal.knowframework.security.common.PagingData;\nimport com.didiglobal.knowframework.security.common.PagingData.Pagination;\nimport com.didiglobal.knowframework.security.common.PagingResult;\nimport com.didiglobal.knowframework.security.common.dto.user.UserBriefQueryDTO;\nimport com.didiglobal.knowframework.security.common.dto.user.UserDTO;\nimport com.didiglobal.knowframework.security.common.entity.UserProject;\nimport com.didiglobal.knowframework.security.common.entity.user.User;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVOWithUser;\nimport com.didiglobal.knowframework.security.common.vo.role.AssignInfoVO;\nimport com.didiglobal.knowframework.security.common.vo.role.RoleBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserVO;\nimport com.didiglobal.knowframework.security.dao.ProjectDao;\nimport com.didiglobal.knowframework.security.dao.UserDao;\nimport com.didiglobal.knowframework.security.dao.UserProjectDao;\nimport com.didiglobal.knowframework.security.exception.KfSecurityException;\nimport com.didiglobal.knowframework.security.service.PermissionService;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.service.RolePermissionService;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport com.didiglobal.knowframework.security.util.PWEncryptUtil;\nimport java.math.BigDecimal;\nimport java.math.RoundingMode;\nimport java.util.*;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.compress.utils.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * > 这个类是一个 Spring 组件，实现了 `UserExtendManager` 接口\n */\n@Component\npublic class UserExtendManagerImpl implements UserExtendManager {\n    @Autowired\n    private UserService           userService;\n    @Autowired\n    private ProjectService projectService;\n    @Autowired\n    private OperateRecordService  operateRecordService;\n    @Autowired\n    private RolePermissionService rolePermissionService;\n    @Autowired\n    private PermissionService     permissionService;\n    @Autowired\n    private UserProjectDao userProjectDao;\n    @Autowired\n    private UserDao userDao;\n    @Autowired\n    private ProjectDao projectDao;\n\n    private final static int NORMAL = 0;\n    private final static int OWNER  = 1;\n\n    private static final FutureUtil<Void> FUTURE_UTIL = FutureUtil.init(\"UserExtendManagerImpl\", 10, 10, 100);\n    /**\n     * 用户注册信息校验\n     *\n     * @param type\n     * @param value\n     * @return\n     */\n    @Override\n    public Result<Void> check(Integer type, String value) {\n        com.didiglobal.knowframework.security.common.Result<Void> check = userService.check(type, value);\n        if (check.failed()) {\n            return Result.build(check.getCode(), check.getMessage());\n        }\n        return Result.buildSucc();\n    }\n\n    /**\n     * 分页获取用户信息\n     *\n     * @param queryDTO 条件信息\n     * @return 用户信息list\n     */\n    @Override\n    public PagingResult<UserExtendVO> getUserPage(UserQueryExtendDTO queryDTO) {\n        if(StringUtils.isNotBlank(queryDTO.getUserName())){\n            queryDTO.setUserName(CommonUtils.sqlFuzzyQueryTransfer(queryDTO.getUserName()));\n        }\n        if(StringUtils.isNotBlank(queryDTO.getRealName())){\n            queryDTO.setRealName(CommonUtils.sqlFuzzyQueryTransfer(queryDTO.getRealName()));\n        }\n        final List<UserBriefVO> userBriefListByAdmin = userService.getUserBriefListByRoleId(\n                AuthConstant.ADMIN_ROLE_ID);\n        PagingData<UserExtendVO> userPage;\n        if (Boolean.FALSE.equals(queryDTO.getContainsAdminRole())) {\n            final int page = queryDTO.getPage();\n            final int pageSize = queryDTO.getSize();\n            final List<Integer> userBriefListWithAdminRole =userBriefListByAdmin.stream().map(UserBriefVO::getId).distinct()\n                    .collect(Collectors.toList());\n            // 获取全量的用户信息\n            final int size = userService.getAllUserBriefList().size();\n            queryDTO.setPage(1);\n            queryDTO.setSize(size);\n            final PagingData<UserVO> userPageAll = userService.getUserPage(queryDTO);\n            final List<UserVO> userListAll = userPageAll.getBizData().parallelStream()\n                    .filter(i -> !userBriefListWithAdminRole.contains(i.getId())).collect(Collectors.toList());\n\n            final List<UserExtendVO> userExtendVOS = ConvertUtil.list2List(userListAll, UserExtendVO.class,userExtendVO -> userExtendVO.setUserListWithAdminRole(userBriefListByAdmin));\n            final Pagination pagination = Pagination.builder().total(userListAll.size())\n                    .pages(new BigDecimal(userListAll.size()).divide(new BigDecimal(pageSize), 0, RoundingMode.UP)\n                            .intValue()\n\n                    ).pageNo(page).pageSize(pageSize).build();\n\n            userPage=new PagingData<>(userExtendVOS,pagination);\n        } else {\n            final PagingData<UserVO> userPageUserVo = userService.getUserPage(queryDTO);\n             final List<UserExtendVO> userExtendVOS = ConvertUtil.list2List(userPageUserVo.getBizData(),\n                     UserExtendVO.class,userExtendVO -> userExtendVO.setUserListWithAdminRole(userBriefListByAdmin));\n            userPage = new PagingData<>(userExtendVOS,userPageUserVo.getPagination()) ;\n\n        }\n        final List<UserExtendVO> userList = userPage.getBizData();\n        //提前获取一下，避免多次查库\n        final List<ProjectBriefVO> projectBriefList = projectService.getProjectBriefList();\n        Map<Integer, String> projectId2projectName = projectBriefList.stream()\n                .collect(Collectors.toMap(ProjectBriefVO::getId, ProjectBriefVO::getProjectName));\n        if (CollectionUtils.isNotEmpty(userList)) {\n            for (UserExtendVO userVO : userList) {\n                FUTURE_UTIL.runnableTask(() -> {\n                    //如果可以匹配到管理员角色\n                    List<ProjectBriefVO> briefList;\n                    final List<RoleBriefVO> roleList = userVO.getRoleList();\n                    if (CollectionUtils.isNotEmpty(roleList) && roleList.stream()\n                            .anyMatch(roleBrief -> Objects.equals(roleBrief.getId(), AuthConstant.ADMIN_ROLE_ID))) {\n                        briefList = projectBriefList;\n                    \n                    } else {\n                        briefList = Optional.ofNullable(userVO.getProjectList()).orElse(Collections.emptyList())\n                                .stream().filter(CommonUtils.distinctByKey(ProjectBriefVO::getId)).collect(Collectors.toList());\n                    \n                    }\n                    userVO.setProjectList(briefList);\n\n                    // 获取以当前user作为负责人的project列表\n                    List<String> ownProjectNameList = new ArrayList<>();\n                    List<Integer> ownProjectIdList = new ArrayList<>();\n                    List<Integer> projectIdListByUserId = userProjectDao\n                            .selectProjectIdListByUserIdList(Collections.singletonList(userVO.getId()));\n                    List<UserProject> userProjects = userProjectDao.selectByProjectIds(projectIdListByUserId);\n                    userProjects.forEach(userProject -> {\n                        if(userVO.getId().equals(userProject.getUserId()) && projectIdListByUserId\n                                .contains(userProject.getProjectId()) && userProject.getUserType() == OWNER) {\n                            ownProjectNameList.add(projectId2projectName.get(userProject.getProjectId()));\n                            ownProjectIdList.add(userProject.getProjectId());\n                        }\n                    });\n                    userVO.setOwnProjects(ownProjectNameList);\n\n                    // 获取以当前user为唯一负责人的项目列表\n                    if(!ownProjectIdList.isEmpty()){\n                        List<String> singleOwnerOfProjects = new ArrayList<>();\n                        List<ProjectBriefVOWithUser> projectBriefVOWithUsers = projectService.listProjectBriefVOWithUserByProjectIds(ownProjectIdList);\n                        projectBriefVOWithUsers.forEach(projectBriefVOWithUser -> {\n                            if(projectBriefVOWithUser.getOwnerList().size() == 1 &&\n                                    projectBriefVOWithUser.getOwnerList().get(0).getId().equals(userVO.getId())){\n                                singleOwnerOfProjects.add(projectBriefVOWithUser.getProjectName());\n                            }\n                        });\n                        userVO.setSingleOwnerOfProjects(singleOwnerOfProjects);\n                    }\n\n\n                });\n            \n            }\n            FUTURE_UTIL.waitExecute();\n        }\n        return PagingResult.success(userPage);\n    }\n\n    /**\n     * 分页获取用户简要信息\n     *\n     * @param queryDTO 条件信息\n     * @return 用户简要信息list\n     */\n    @Override\n    public PagingResult<UserBriefVO> getUserBriefPage(UserBriefQueryDTO queryDTO) {\n        PagingData<UserBriefVO> userBriefPage = userService.getUserBriefPage(queryDTO);\n        return PagingResult.success(userBriefPage);\n    }\n\n    /**\n     * 获取用户详情（主要是获取用户所拥有的权限信息）\n     *\n     * @param userId    用户id\n     * @param projectId\n     * @return 用户详情\n     * @throws LogiSecurityException 用户不存在\n     */\n    @Override\n    public Result<UserWithPwVO> getUserDetailByUserId(Integer userId, Integer projectId) throws Exception {\n        final UserVO userVO = userService.getUserDetailByUserId(userId);\n        final List<RoleBriefVO> roleList = Optional.ofNullable(userVO.getRoleList()).orElse(Lists.newArrayList());\n        final List<Integer> roleIds = roleList.stream().map(RoleBriefVO::getId).collect(Collectors.toList());\n        //传入项目id判断是否是超级项目,如果是则判断是否为管理员,然后返回权限点\n        if (Objects.nonNull(projectId)) {\n            if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)\n                && roleIds.stream().anyMatch(id -> Objects.equals(id, AuthConstant.ADMIN_ROLE_ID))) {\n                final List<Integer> hasPermissionIdList = rolePermissionService\n                    .getPermissionIdListByRoleIdList(Collections.singletonList(AuthConstant.ADMIN_ROLE_ID));\n                // 构建权限树\n                userVO.setPermissionTreeVO(permissionService.buildPermissionTreeWithHas(hasPermissionIdList));\n            } else {\n                //删除管理员id\n                List<Integer> notAdminIdLists = roleIds.stream().filter(id -> !AuthConstant.ADMIN_ROLE_ID.equals(id))\n                    .collect(Collectors.toList());\n                final List<Integer> hasPermissionIdList = rolePermissionService\n                    .getPermissionIdListByRoleIdList(notAdminIdLists);\n                // 构建权限树\n                userVO.setPermissionTreeVO(permissionService.buildPermissionTreeWithHas(hasPermissionIdList));\n            }\n\n        }\n        List<ProjectBriefVO> projectBriefList;\n        if (roleList.stream()\n                .anyMatch(roleBriefVO -> Objects.equals(roleBriefVO.getId(), AuthConstant.ADMIN_ROLE_ID))) {\n            projectBriefList = projectService.getProjectBriefList();\n        } else {\n            projectBriefList = Optional.ofNullable(userVO.getProjectList()).orElse(Collections.emptyList()).stream()\n                    .distinct().collect(Collectors.toList());\n        }\n    \n        userVO.setProjectList(projectBriefList);\n        UserWithPwVO userWithPwVO = ConvertUtil.obj2Obj(userVO, UserWithPwVO.class);\n        userWithPwVO.setPassword(PWEncryptUtil.decode(userDao.selectByUserId(userId).getPw()));\n\n        return Result.buildSucc(userWithPwVO);\n    }\n\n    /**\n     * 根据用户id删除用户\n     *\n     * @param userId\n     * @param operateProjectId\n     * @param operator\n     * @return\n     */\n    @Override\n    public Result<Void> deleteByUserId(Integer userId, Integer operateProjectId, String operator) {\n        String userName = userService.getUserDetailByUserId(userId).getUserName();\n        com.didiglobal.knowframework.security.common.Result<Void> deleteByUserId = userService.deleteByUserId(userId);\n        if (deleteByUserId.failed()) {\n            return Result.build(deleteByUserId.getCode(), deleteByUserId.getMessage());\n        }\n\n        final List<ProjectBriefVO> projectBriefList = projectService.getProjectBriefByUserId(userId).getData();\n        String operateContent;\n        if(projectBriefList.isEmpty()) {\n            operateContent = String.format(\"【%s】用户被删除\", userName);\n        }else {\n            Set<String> projectNameSet = new HashSet<>();\n            projectBriefList.forEach(projectBriefVO -> projectNameSet.add(projectBriefVO.getProjectName()));\n            String nameList = projectNameSet.stream().map(String::valueOf).collect(Collectors.joining(\",\"));\n            operateContent = String.format(\"【%s】用户被删除，其所属应用为【%s】\", userName, nameList);\n        }\n\n        // 获取该用户对应的所有应用id，删除相关应用下的该用户数据\n        final List<Integer> projectIdList = userProjectDao.selectProjectIdListByUserIdList(\n                Collections.singletonList(userId));\n        if(!AriusObjUtils.isEmptyList(projectIdList)){\n            List<UserProject> userProjectList = new ArrayList<>(projectIdList.size());\n            projectIdList.forEach(projectId -> {\n                UserProject userProject = new UserProject();\n                userProject.setProjectId(projectId);\n                userProject.setUserId(userId);\n                userProject.setUserType(NORMAL);\n                userProjectList.add(userProject);\n            });\n            userProjectDao.deleteUserProject(userProjectList);\n        }\n\n        operateRecordService.save(new OperateRecord(projectDao.selectByProjectId(operateProjectId).getProjectName(),\n                OperateTypeEnum.TENANT_DELETE, TriggerWayEnum.MANUAL_TRIGGER, operateContent, operator));\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 获取用户简要信息\n     *\n     * @param userName\n     * @return 用户简要信息\n     */\n    @Override\n    public Result<UserBriefVO> getUserBriefByUserName(String userName) {\n\n        return Result.buildSucc(userService.getUserBriefByUserName(userName));\n    }\n\n    /**\n     * 获取用户简要信息\n     *\n     * @param userName 用户名称\n     * @return 用户简要信息\n     */\n    @Override\n    public Result<User> getUserByUserName(String userName) {\n        return Result.buildSucc(userService.getUserByUserName(userName));\n    }\n\n    /**\n     * 获取用户简要信息List\n     *\n     * @param userIdList 用户idList\n     * @return 用户简要信息List\n     */\n    @Override\n    public Result<List<UserBriefVO>> getUserBriefListByUserIdList(List<Integer> userIdList) {\n        return Result.buildSucc(userService.getUserBriefListByUserIdList(userIdList));\n    }\n\n    /**\n     * 根据部门id获取用户list（获取该部门下所有的用户，包括各种子部门）\n     *\n     * @param deptId 部门id，如果为null，表示无部门用户\n     * @return 用户简要信息list\n     */\n    @Override\n    public Result<List<UserBriefVO>> getUserBriefListByDeptId(Integer deptId) {\n        return Result.buildSucc(userService.getUserBriefListByDeptId(deptId));\n    }\n\n    /**\n     * 根据用户id和roleName获取角色list\n     *\n     * @param userId 用户id\n     * @return 分配角色或者分配用户/列表信息\n     * @throws LogiSecurityException 用户id不可为null\n     */\n    @Override\n    public Result<List<AssignInfoVO>> getAssignDataByUserId(Integer userId) {\n        try {\n            return Result.buildSucc(userService.getAssignDataByUserId(userId));\n        } catch (KfSecurityException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    /**\n     * 根据角色id获取用户list\n     *\n     * @param roleId 角色Id\n     * @return 用户简要信息list\n     */\n    @Override\n    public Result<List<UserBriefVO>> getUserBriefListByRoleId(Integer roleId) {\n        return Result.buildSucc(userService.getUserBriefListByRoleId(roleId));\n    }\n\n    /**\n     * 会分别以账户名和实名去模糊查询，返回两者的并集 创建项目，添加项目负责人的时候用到\n     *\n     * @param name 账户名或实名\n     * @return 用户简要信息list\n     */\n    @Override\n    public Result<List<UserBriefVO>> getUserBriefListByUsernameOrRealName(String name) {\n        return Result.buildSucc(userService.getUserBriefListByUsernameOrRealName(name));\n    }\n\n    /**\n     * 获取用户简要信息List并根据创建时间排序\n     *\n     * @param isAsc 是否升序\n     * @return 用户简要信息List\n     */\n    @Override\n    public Result<List<UserBriefVO>> getAllUserBriefListOrderByCreateTime(boolean isAsc) {\n        return Result.buildSucc(userService.getAllUserBriefListOrderByCreateTime(isAsc));\n    }\n\n    /**\n     * 会分别以账户名和实名去模糊查询，返回两者的并集\n     *\n     * @param name 账户名或实名\n     * @return 用户IdList\n     */\n    @Override\n    public Result<List<Integer>> getUserIdListByUsernameOrRealName(String name) {\n        return Result.buildSucc(userService.getUserIdListByUsernameOrRealName(name));\n    }\n\n    /**\n     * 获取所有用户简要信息\n     *\n     * @return 用户简要信息List\n     */\n    @Override\n    public Result<List<UserBriefVO>> getAllUserBriefList() {\n        return Result.buildSucc(userService.getAllUserBriefList());\n    }\n\n    /**\n     * 编辑一个用户\n     *\n     * @param userDTO\n     * @param operator\n     * @return\n     */\n    @Override\n    public Result<Void> editUser(UserExtendDTO userDTO, String operator) {\n        User userBriefVO = userService.getUserByUserName(userDTO.getUserName());\n        if (Objects.isNull(userBriefVO)){\n            return Result.buildFail(\"用户不存在\");\n        }\n        String pw = userBriefVO.getPw();\n        if (StringUtils.isNotBlank(userDTO.getPw())) {\n            try {\n                String decode = PWEncryptUtil.decode(pw);\n                // 开启密码比对且数据库中的密码和传入进来的原始密码不一致的时候\n                if (Boolean.FALSE.equals(userDTO.isIgnorePasswordMatching()) && !StringUtils.equals(userDTO.getOldPw(),\n                        decode)) {\n                    return Result.buildFail(\"旧密码不正确\");\n                }\n            } catch (Exception ignore) {\n            \n            }\n        }\n    \n        com.didiglobal.knowframework.security.common.Result<Void> voidResult = userService.editUser(userDTO, operator);\n    \n        if (voidResult.failed()) {\n            return Result.build(voidResult.getCode(), voidResult.getMessage());\n        }\n        if (StringUtils.isNotBlank(userDTO.getEmail())) {\n            saveOperateRecord(operator, userBriefVO.getId(),\n                    String.format(\"修改 email:%s-->%s\", userBriefVO.getEmail(), userDTO.getEmail()));\n        }\n        if (StringUtils.isNotBlank(userDTO.getPhone())) {\n            saveOperateRecord(operator, userBriefVO.getId(),\n                    String.format(\"修改手机号:%s-->%s\", userBriefVO.getPhone(), userDTO.getPhone()));\n        }\n        if (StringUtils.isNotBlank(userDTO.getRealName())) {\n            saveOperateRecord(operator, userBriefVO.getId(),\n                    String.format(\"修改用户实名:%s-->%s\", userBriefVO.getRealName(), userDTO.getRealName()));\n        }\n        if (StringUtils.isNotBlank(userDTO.getPw())) {\n            saveOperateRecord(operator, userBriefVO.getId(), \"修改用户密码\");\n        }\n        return Result.buildSucc();\n    }\n    \n \n    \n    /**\n     * @param ids\n     * @return\n     */\n    @Override\n    public Result<List<UserVO>> getUserDetailByUserIds(List<Integer> ids) {\n        return Result.buildSucc(userService.getUserDetailByUserIds(ids).getData());\n    }\n\n    /**\n     * 添加用户\n     *\n     * @param param    入参\n     * @param operator 操作人或角色\n     * @return {@code Result<Void>}\n     */\n    @Override\n    public Result<Void> addUser(UserDTO param, String operator) {\n        param.setRoleIds(Collections.singletonList(AuthConstant.RESOURCE_OWN_ROLE_ID));\n        final com.didiglobal.knowframework.security.common.Result<Void> result = userService.addUser(param, operator);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        operateRecordService.save(new OperateRecord(OperateTypeEnum.TENANT_ADD, TriggerWayEnum.MANUAL_TRIGGER, param.getUserName(),\n                        operator));\n        return Result.buildSucc();\n\n    }\n    \n    private void saveOperateRecord(String operator, Integer bizId, String content) {\n        operateRecordService.save(\n                new OperateRecord(OperateTypeEnum.TENANT_INFO_MODIFY, TriggerWayEnum.MANUAL_TRIGGER, content, operator,\n                        bizId));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/security/resource/ResourceExtendManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.security.resource;\n\nimport com.didiglobal.knowframework.security.common.PagingData;\nimport com.didiglobal.knowframework.security.common.dto.resource.ResourceDTO;\nimport com.didiglobal.knowframework.security.extend.ResourceExtend;\nimport java.util.Collections;\nimport java.util.List;\nimport org.springframework.stereotype.Component;\n\n/**\n * resourceExtend的实现类在spring容器bean的名称， logi-security 中资源权限管理模块，需要获取具体资源的信息， 所以用户需实现 ResourceExtend\n * 接口并指定实现类在spring容器中bean的名称； 当前默认为空的实现的状态，在后期开发中会根据需求进行实现 其中配置为\n *\n * @author shizeying\n * @date 2022/05/23\n * @see ResourceExtend\n */\n@Component\npublic class ResourceExtendManager implements ResourceExtend {\n\n    /**\n     * 获取资源信息List，资源id指的是该资源所在服务对该资源的标识\n     *\n     * @param projectId      项目id（可为null）\n     * @param resourceTypeId 资源类型id（可为null，不为null则projectId必不为null）\n     * @param resourceName   资源名称（可为null，模糊查询条件）\n     * @param page           当前页（分页条件）\n     * @param size           页大小（分页条件）\n     * @return 资源信息List\n     */\n    @Override\n    public PagingData<ResourceDTO> getResourcePage(Integer projectId, Integer resourceTypeId, String resourceName,\n                                                   int page, int size) {\n        return null;\n    }\n\n    /**\n     * 获取资源信息List，资源id指的是该资源所在服务对该资源的标识\n     *\n     * @param projectId      项目id（可为null）\n     * @param resourceTypeId 资源类型id（可为null，不为null则projectId必不为null）\n     * @return 资源信息List\n     */\n    @Override\n    public List<ResourceDTO> getResourceList(Integer projectId, Integer resourceTypeId) {\n\n        return Collections.emptyList();\n    }\n\n    /**\n     * 获取具体资源个数，资源id指的是该资源所在服务对该资源的标识\n     *\n     * @param projectId      项目id（可为null）\n     * @param resourceTypeId 资源类型id（可为null，不为null则projectId必不为null）\n     * @return 资源信息List\n     */\n    @Override\n    public int getResourceCnt(Integer projectId, Integer resourceTypeId) {\n        return 0;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/OpTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\n\n/**\n * @author d06679\n * @date 2020/12/21\n */\npublic interface OpTaskHandler extends BaseHandle {\n\n    /**\n     * 创建一个任务\n     *\n     * 1、校验任务内容是否合法\n     * 2、提交任务\n     * @param opTask 任务数据\n     * @return result\n     */\n    Result<OpTask> addTask(OpTask opTask) throws NotFindSubclassException;\n\n    /**\n     * 判断一个任务是否存在，参数待定\n     *\n     @param key key\n     @param type 类型\n     @return boolean\n     */\n    boolean existUnClosedTask(String key, Integer type);\n\n    /**\n     * 处理任务\n     * @param opTask     任务\n     * @param step       处理状态\n     * @param status     状态\n     * @param expandData 扩展数据\n     * @return result\n     */\n    Result<Void> process(OpTask opTask, Integer step, String status, String expandData);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/OpTaskManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskProcessDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.OpTaskVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport java.util.List;\n\n/**\n * 任务 Service\n *\n * @author d06679\n * @date 2020/12/21\n */\npublic interface OpTaskManager {\n\n    /**\n     * 提交一个任务\n     *\n     * @param opTaskDTO 任务数据\n     * @param projectId\n     * @return Result\n     * @throws AdminOperateException 异常\n     */\n    Result<OpTask> addTask(OpTaskDTO opTaskDTO, Integer projectId) throws NotFindSubclassException;\n\n    /**\n     * 判断一个任务是否存在\n     * @param key 关键值\n     * @param type 任务类型\n     * @return\n     */\n    boolean existUnClosedTask(Integer key, Integer type) throws NotFindSubclassException;\n\n    /**\n     * 插入一条任务\n     * @param task task\n     * @return int\n     */\n    void insert(OpTask task);\n\n    /**\n     * 通过id更新任务\n     * @param task task\n     * @return int\n     */\n    void updateTask(OpTask task);\n\n    /**\n     * 通过id获取任务\n     *\n     * @param id 任务id\n     * @return TaskPO\n     */\n    Result<OpTask> getById(Integer id);\n\n    /**\n     * 获取所有的任务\n     *\n     * @return List<TaskPO>\n     */\n    Result<List<OpTask>> list();\n\n    /**\n     * 处理任务任务\n     *\n     * @param processDTO 任务\n     * @return Result\n     */\n    Result<Void> processTask(OpTaskProcessDTO processDTO) throws NotFindSubclassException;\n\n    /**获取最新任务\n     * 通过businessKey获取最新的任务\n     *\n     * @param businessKey 业务id\n     * @param taskType 任务类型\n     * @return {@link Result}<{@link OpTask}>\n     */\n    Result<OpTask> getLatestTask(String businessKey, Integer taskType);\n\n    /**\n     * 通过taskType获取待处理任务\n     *\n     * @param taskType 任务类型\n     * @return {@link List}<{@link OpTask}>\n     */\n    List<OpTask> getPendingTaskByType(Integer taskType);\n\n    /**\n     * 根据类型获取失败任务\n     * @param taskType\n     * @return\n     */\n    List<OpTask> getSuccessTaskByType(Integer taskType);\n\n    /**\n     * 任务中心分页查询\n     * @param projectId\n     * @param queryDTO\n     * @return\n     */\n    PaginationResult<OpTaskVO> pageGetTasks(Integer projectId, OpTaskQueryDTO queryDTO) throws NotFindSubclassException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/content/ClusterBaseContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Data\n@NoArgsConstructor\npublic class ClusterBaseContent {\n    /**\n     * type 3:docker 4:host\n     */\n    private int    type;\n\n    /**\n     * 物理集群名称\n     */\n    private String phyClusterName;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/content/ClusterConfigRestartContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.esconfig.ESConfig;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author lyn\n * @date 2021-01-21\n */\n@Data\n@NoArgsConstructor\npublic class ClusterConfigRestartContent extends ClusterRestartContent {\n    /**\n     * Es配置操作: 1.新增 2.编辑 3.删除\n     * @see EsConfigActionEnum\n     */\n    private Integer        actionType;\n\n    /**\n     * 新增Es配置\n     */\n    private List<ESConfig> newEsConfigs;\n\n    /**\n     * 原始配置\n     */\n    private List<ESConfig> originalConfigs;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/content/ClusterHostContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Data\n@NoArgsConstructor\npublic class ClusterHostContent extends ClusterBaseContent {\n    /**\n     * 集群角色 对应主机列表\n     */\n    private List<ESClusterRoleHost> clusterRoleHosts;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/content/ClusterIndecreaseDockerContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleDocker;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * 弹性云的集群扩缩容操作\n *\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Data\n@NoArgsConstructor\npublic class ClusterIndecreaseDockerContent extends ClusterBaseContent {\n    /**\n     * 物理集群id\n     */\n    private Long                      phyClusterId;\n\n    /**\n     * 2:扩容 3：缩容\n     */\n    private int                       operationType;\n\n    /**\n     * 集群变动之后的角色列表\n     */\n    private List<ESClusterRoleDocker> roleClusters;\n\n    /**\n     * 集群原始角色列表\n     */\n    private List<ESClusterRoleDocker> originRoleClusters;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/content/ClusterIndecreaseHostContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * 物理机的集群扩缩容操作\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Data\n@NoArgsConstructor\npublic class ClusterIndecreaseHostContent extends ClusterHostContent {\n    /**\n     * 物理集群id\n     */\n    private Long                    phyClusterId;\n\n    /**\n     * 2:扩容 3：缩容\n     */\n    private int                     operationType;\n\n    /**\n     * 单机实例数\n     */\n    private Integer                 pidCount;\n\n    /**\n     * 集群角色 对应的原始的主机列表\n     */\n    private List<ESClusterRoleHost> originClusterRoleHosts;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/content/ClusterNewDockerContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleDocker;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ResourceLogicLevelEnum;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Data\n@NoArgsConstructor\npublic class ClusterNewDockerContent extends ClusterBaseContent {\n\n    /**\n     * 数据中心\n     */\n    private String                    dataCenter;\n    /**\n     * 机器节点\n     */\n    private String                    nsTree;\n\n    /**\n     * 机房\n     */\n    private String                    idc;\n\n    /**\n     * es版本\n     */\n    private String                    esVersion;\n\n    /**\n     * 插件包ID列表\n     */\n    private String                    plugs;\n\n    /**\n     * 集群创建人\n     */\n    private String                    creator;\n\n    /**\n     * 描述\n     */\n    private String                    desc;\n\n    /**\n     * 服务等级\n     * @see ResourceLogicLevelEnum\n     */\n    private Integer                   level;\n\n    /**\n     * 集群角色列表\n     */\n    private List<ESClusterRoleDocker> roleClusters;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/content/ClusterNewHostContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ResourceLogicLevelEnum;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Data\n@NoArgsConstructor\npublic class ClusterNewHostContent extends ClusterHostContent {\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n    /**\n     * 机器节点\n     */\n    private String  nsTree;\n\n    /**\n     * 机房\n     */\n    private String  idc;\n\n    /**\n     * es版本\n     */\n    private String  esVersion;\n\n    /**\n     * 插件包ID列表\n     */\n    private String  plugs;\n\n    /**\n     * 集群创建人\n     */\n    private String  creator;\n\n    /**\n     * 描述\n     */\n    private String  desc;\n\n    /**\n     * 单节点实例数\n     */\n    private Integer pidCount;\n\n    /**\n     * 机器规格\n     */\n    private String  machineSpec;\n\n    /**\n     * 服务等级\n     * @see ResourceLogicLevelEnum\n     */\n    private Integer level;\n\n    /**\n     * 集群展示用属性标签，如「集群所属资源类型」等等\n     */\n    private String  tags;\n\n    private String  platformType;\n\n    /**\n     * @see ClusterResourceTypeEnum\n     */\n    private Integer resourceType;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/content/ClusterOfflineContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.content;\n\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.BaseContent;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Data\n@NoArgsConstructor\npublic class ClusterOfflineContent extends BaseContent {\n    /**\n     * 物理集群id\n     */\n    private Long   phyClusterId;\n    /**\n     * 物理集群名称\n     */\n    private String phyClusterName;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/content/ClusterRestartContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.content;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ClusterRestartContent extends ClusterHostContent {\n    /**\n     * 物理集群id\n     */\n    private Long   phyClusterId;\n\n    /**\n     * 角色顺序，如：airepo-masternode,airepo-clientnode,airepo-datanode\n     */\n    private String roleOrder;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/content/ClusterUpdateContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Data\n@NoArgsConstructor\npublic class ClusterUpdateContent extends ClusterHostContent {\n    /**\n     * 物理集群id\n     */\n    private Long   phyClusterId;\n\n    /**\n     * 集群版本\n     */\n    private String esVersion;\n\n    /**\n     * 角色顺序，如：airepo-masternode,airepo-clientnode,airepo-datanode\n     */\n    private String roleOrder;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/ecm/EcmTaskDetailManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmTaskDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmTaskDetailProgress;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmSubTaskLog;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\n\nimport java.util.List;\n\n/**\n * ES工单任务详情 服务类\n * @author didi\n * @since 2020-09-24\n */\npublic interface EcmTaskDetailManager {\n    int replace(EcmTaskDetail ecmTaskDetail);\n\n    /**\n     * 创建一个工单任务详情\n     * @param  esEcmTaskDetail 工单任务\n     * @return result\n     */\n    Result<Long> saveEcmTaskDetail(EcmTaskDetail esEcmTaskDetail);\n\n    /**\n     * 修改工单任务详情的taskId\n     * @param\n     * @return result\n     */\n    Result<Integer> updateByRoleAndOrderTaskId(Long workOrderTaskId, String roleName, Long taskId);\n\n    /**\n     * 根据工单任务ID获取详情列表\n     * @param  workOrderTaskId 工单任务ID\n     * @return List<EcmTaskDetailPO>\n     */\n    List<EcmTaskDetail> getEcmTaskDetailInOrder(Long workOrderTaskId);\n\n    /**\n     * 获取taskDetail\n     * @param  workOrderTaskId 工单任务ID\n     * @param  role  角色\n     * @return List\n     */\n    List<EcmTaskDetail> getByOrderIdAndRoleAndTaskId(Integer workOrderTaskId, String role, Integer taskId);\n\n    /**\n     * 根据工单任务详情ID获取对应日志\n     * @param  detailId 工单详情ID\n     * @param  operator 操作人\n     * @return result\n     */\n    Result<EcmSubTaskLog> getTaskDetailLog(Long detailId, String operator);\n\n    /**\n     * 根据工单任务ID获取详情列表 与 统计数据\n     * @param  workOrderTaskId 工单任务ID\n     * @return result\n     */\n    Result<EcmTaskDetailProgress> getEcmTaskDetailInfo(Long workOrderTaskId) throws AdminTaskException;\n\n    /**\n     * 获取waiting状态TaskDetail\n     * @param workOrderTaskId\n     * @return\n     */\n    EcmTaskDetailProgress buildInitialEcmTaskDetail(Long workOrderTaskId);\n\n    /**\n     * 编辑taskDetail\n     * @param buildEcmTaskDetail\n     * @return\n     */\n    Result<Long> editEcmTaskDetail(EcmTaskDetail buildEcmTaskDetail);\n\n    /**\n     * 获取ecm task Detail\n     * @param workOrderId\n     * @param hostname\n     * @return\n     */\n    EcmTaskDetail getByWorkOderIdAndHostName(Long workOrderId, String hostname);\n\n    /**\n     * 根据工单任务ID删除对应的任务详情信息\n     */\n    Result<Void> deleteEcmTaskDetailsByTaskOrder(Long workOrderTaskId);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/ecm/EcmTaskManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.ecm;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmTaskBasic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmOperateAppBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmTaskStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.ecm.EcmTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskPO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.EcmRemoteException;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.EcmActionEnum;\n\n/**\n * ES工单任务 服务类\n * @author didi\n * @since 2020-09-24\n */\npublic interface EcmTaskManager {\n    /**\n     * 校验同一个集群是否存在未完成任务\n     * @param  phyClusterId 物理集群ID\n     * @return true 存在\n     */\n    boolean existUnClosedEcmTask(Long phyClusterId);\n\n    /**\n     * 创建一个EcmTask\n     * @param  ecmTaskDTO 工单任务\n     * @return result\n     */\n    Result<Long> saveEcmTask(EcmTaskDTO ecmTaskDTO);\n\n    /**\n     * 查询全部的 EcmTask\n     * @param\n     * @return result\n     */\n    List<EcmTask> listEcmTask();\n\n    /**\n     * 查询处于running状态的ecm集群任务\n     * @return List<EcmTask>\n     */\n    List<EcmTask> listRunningEcmTask();\n\n    /**\n     * 查询 工单任务基本情况\n     * @param  taskId\n     * @return result\n     */\n    Result<EcmTaskBasic> getEcmTaskBasicByTaskId(Long taskId);\n\n    /**\n     * 创建ES集群任务:1. 先初始化集群信息, 再灰度创建master角色的节点, master节点两个一组启动\n     * @param  taskId  工单任务ID\n     * @param  operator  操作人\n     * @return result\n     */\n    Result<EcmOperateAppBase> savaAndActionEcmTask(Long taskId, String operator) throws EcmRemoteException;\n\n    /**\n     * 重试集群任务：将任务状态改为waiting 同时将zeus任务的id置空\n     * @param  taskId  工单任务ID\n     * @param  operator  操作人\n     * @return result\n     */\n    Result<Void> retryClusterEcmTask(Long taskId, String operator);\n\n    /**\n     * 根据taskId执行一个Ecm任务\n     * @param  taskId 工单任务ID\n     * @param  operator  操作人\n     * @return result\n     */\n    Result<EcmOperateAppBase> actionClusterEcmTask(Long taskId, String operator) throws EcmRemoteException;\n\n    /**\n     * 继续执行单个Ecm任务\n     * @param taskId\n     * @param ecmActionEnum\n     * @param hostname\n     * @param operator\n     * @return\n     */\n    Result<EcmOperateAppBase> actionClusterEcmTask(Long taskId, EcmActionEnum ecmActionEnum, String hostname,\n                                                   String operator) throws EcmRemoteException;\n\n    /**\n     * 取消工单部署集群节点\n     * @param  taskId 工单任务ID\n     * @param  operator  操作人\n     * @return result\n     */\n    Result<Void> cancelClusterEcmTask(Long taskId, String operator);\n\n    /**\n     * 暂停集群任务\n     * @param  taskId 工单任务ID\n     * @param  operator  操作人\n     * @return result\n     */\n    Result<Void> pauseClusterEcmTask(Long taskId, String operator);\n\n    /**\n     * 根据ID获取任务\n     * @param  id 任务ID\n     * @return result\n     */\n    EcmTask getEcmTask(Long id);\n\n    /**\n     * 刷新同步任务\n     * @param ecmTask\n     * @return\n     */\n    EcmTaskStatusEnum refreshEcmTask(EcmTask ecmTask) throws AdminTaskException;\n\n    /**\n     * 根据ID修改任务信息\n     * @param  ecmTask\n     * @return result\n     */\n    boolean updateEcmTask(EcmTask ecmTask);\n\n    /**\n     * 根据物理集群id获取正在执行或者等待执行的工单信息\n     * @param physicClusterId 物理集群id\n     * @return EcmTaskPO\n     */\n    EcmTaskPO getRunningEcmTaskByClusterId(Integer physicClusterId);\n\n    /**\n     * 对于单个集群任务节点进行操作\n     * @param taskId ecm任务执行id主键\n     * @param ecmActionEnum 集群任务的操作\n     * @param hostname 主机名称或者ip\n     * @param operator 操作人\n     * @return\n     */\n    Result<Void> actionClusterHostEcmTask(Long taskId, EcmActionEnum ecmActionEnum, String hostname, String operator);\n\n    /**\n     * 根据物理集群名称获取到正在执行或者等待执行的ecm任务\n     * @param clusterName 物理集群名称\n     * @return ecm任务\n     */\n    Result<EcmTask> getUsefulEcmTaskByClusterName(String clusterName);\n\n    /**\n     * 根据集群名称，获取当前正在运行的ecm任务的工单id(一个集群只能存在一个可执行或者待执行的ecm任务)\n     * @param cluster 物理集群名称\n     * @return ecm任务工单的contentObj内容\n     */\n    Result<String> getEcmTaskOrderDetailInfo(String cluster);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/ecm/impl/EcmTaskDetailManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.ecm.impl;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.utils.OpOrderTaskConverter;\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskDetailManager;\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmTaskDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmTaskDetailProgress;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmSubTaskLog;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.ecm.EcmTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskDetailPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmTaskStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.EcmHandleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.task.EcmTaskDetailDAO;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\n\n/**\n *ES工单任务管理详情 服务实现类\n * @author didi\n * @since 2020-09-24\n */\n@Service\npublic class EcmTaskDetailManagerImpl implements EcmTaskDetailManager {\n    private static final ILog LOGGER = LogFactory.getLog(EcmTaskDetailManagerImpl.class);\n\n    @Autowired\n    private EcmTaskDetailDAO       ecmTaskDetailDAO;\n\n    @Autowired\n    private ClusterRoleService     clusterRoleService;\n\n    @Autowired\n    private EcmTaskManager         ecmTaskManager;\n\n    @Autowired\n    private EcmHandleService       ecmHandleService;\n\n    @Autowired\n    private ClusterRoleHostService clusterRoleHostService;\n\n    @Override\n    public int replace(EcmTaskDetail ecmTaskDetail) {\n        return ecmTaskDetailDAO.replace(ConvertUtil.obj2Obj(ecmTaskDetail, EcmTaskDetailPO.class));\n    }\n\n    @Override\n    public Result<Long> saveEcmTaskDetail(EcmTaskDetail esEcmTaskDetail) {\n        EcmTaskDetailPO ecmTaskDetailPo = ConvertUtil.obj2Obj(esEcmTaskDetail, EcmTaskDetailPO.class);\n        initEcmTaskDetailParam(ecmTaskDetailPo);\n        boolean succ = (1 == ecmTaskDetailDAO.save(ecmTaskDetailPo));\n        return Result.build(succ, ecmTaskDetailPo.getId());\n    }\n\n    @Override\n    public Result<Integer> updateByRoleAndOrderTaskId(Long workOrdertaskId, String role, Long taskId) {\n        boolean succ = (1 == ecmTaskDetailDAO.updateTaskIdByRoleAndWorkOrderTaskId(workOrdertaskId, role, taskId));\n        return Result.build(succ);\n    }\n\n    @Override\n    public List<EcmTaskDetail> getEcmTaskDetailInOrder(Long workOrderTaskId) {\n        return ConvertUtil.list2List(ecmTaskDetailDAO.listByWorkOrderTaskId(workOrderTaskId), EcmTaskDetail.class);\n    }\n\n    @Override\n    public List<EcmTaskDetail> getByOrderIdAndRoleAndTaskId(Integer workOrderTaskId, String role, Integer taskId) {\n        List<EcmTaskDetailPO> ecmTaskDetailPo = ecmTaskDetailDAO.listByTaskIdAndRoleAndWorkOrderTaskId(workOrderTaskId,\n            role, taskId);\n        if (CollectionUtils.isEmpty(ecmTaskDetailPo)) {\n            return Lists.newArrayList();\n        }\n        return ConvertUtil.list2List(ecmTaskDetailPo, EcmTaskDetail.class);\n    }\n\n    @Override\n    public Result<EcmTaskDetailProgress> getEcmTaskDetailInfo(Long workOrderTaskId) throws AdminTaskException {\n        EcmTask ecmTask = ecmTaskManager.getEcmTask(workOrderTaskId);\n        if (AriusObjUtils.isNull(ecmTask)) {\n            return Result.buildFail(\"the ecm task is empty\");\n        }\n        // 获取初始信息\n        EcmTaskDetailProgress detailProgress = buildInitialEcmTaskDetail(workOrderTaskId);\n        if (EcmTaskStatusEnum.WAITING.getValue().equals(ecmTask.getStatus())) {\n            return Result.buildSucc(detailProgress);\n        }\n\n        if (EcmTaskStatusEnum.SUCCESS.getValue().equals(ecmTask.getStatus())) {\n            List<EcmTaskDetail> ecmTaskDetails = getEcmTaskDetailInOrder(workOrderTaskId);\n            detailProgress.setSum((long) ecmTaskDetails.size());\n        }\n\n        //任务正在执行，刷新列表\n        ecmTaskManager.refreshEcmTask(ecmTask);\n        ecmTask = ecmTaskManager.getEcmTask(workOrderTaskId);\n\n        // 获取信息\n        List<EcmTaskDetail> ecmTaskDetails = getEcmTaskDetailInOrder(workOrderTaskId);\n        detailProgress.setWaiting(detailProgress.getSum() - ecmTaskDetails.size());\n\n        // 状态统计\n        ecmTaskDetails.stream().filter(Objects::nonNull).forEachOrdered(detail -> {\n            // 角色详情\n            List<EcmTaskDetail> ecmTaskDetailList = detailProgress.getRoleNameTaskDetailMap()\n                .getOrDefault(detail.getRole(), Lists.newArrayList());\n            ecmTaskDetailList.add(detail);\n            detailProgress.getRoleNameTaskDetailMap().put(detail.getRole(), ecmTaskDetailList);\n            // 状态统计\n            if (EcmTaskStatusEnum.SUCCESS.getValue().equals(detail.getStatus())) {\n                detailProgress.setSuccess(detailProgress.getSuccess() + 1);\n            } else if (EcmTaskStatusEnum.FAILED.getValue().equals(detail.getStatus())) {\n                detailProgress.setFailed(detailProgress.getFailed() + 1);\n            } else if (EcmTaskStatusEnum.RUNNING.getValue().equals(detail.getStatus())) {\n                detailProgress.setCreating(detailProgress.getCreating() + 1);\n            } else if (EcmTaskStatusEnum.WAITING.getValue().equals(detail.getStatus())) {\n                detailProgress.setWaiting(detailProgress.getWaiting() + 1);\n            } else if (EcmTaskStatusEnum.CANCEL.getValue().equals(detail.getStatus())) {\n                detailProgress.setCancel(detailProgress.getCancel() + 1);\n            }\n        });\n\n        detailProgress.setStatus(ecmTask.getStatus());\n        detailProgress.setOrderType(ecmTask.getOrderType());\n        detailProgress.updatePercent();\n        return Result.buildSucc(detailProgress);\n    }\n\n    @Override\n    public Result<EcmSubTaskLog> getTaskDetailLog(Long detailId, String operator) {\n        EcmTaskDetailPO ecmTaskDetailPO = ecmTaskDetailDAO.getById(detailId);\n        if (AriusObjUtils.isNull(ecmTaskDetailPO)) {\n            return Result.buildFail(\"工单子任务不存在\");\n        }\n\n        EcmTask ecmTask = ecmTaskManager.getEcmTask(ecmTaskDetailPO.getWorkOrderTaskId());\n        if (AriusObjUtils.isNull(ecmTask)) {\n            return Result.buildFail(\"任务不存在\");\n        }\n\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask);\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            if (Objects.isNull(ecmParamBase.getTaskId())||!ecmTaskDetailPO.getTaskId().equals(ecmParamBase.getTaskId().longValue())) {\n                continue;\n            }\n            return ecmHandleService.getSubTaskLog(ecmParamBase, ecmTaskDetailPO.getHostname(), operator);\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public EcmTaskDetail getByWorkOderIdAndHostName(Long workOrderId, String hostname) {\n        return ConvertUtil.obj2Obj(ecmTaskDetailDAO.getByWorkOderIdAndHostName(workOrderId, hostname),\n            EcmTaskDetail.class);\n    }\n\n    @Override\n    public Result<Void> deleteEcmTaskDetailsByTaskOrder(Long workOrderTaskId) {\n        try {\n            ecmTaskDetailDAO.deleteEcmTaskDetailsByTaskOrder(workOrderTaskId);\n        } catch (Exception e) {\n            LOGGER.error(\"class=EcmTaskDetailManagerImpl||method=deleteEcmTaskDetailsByTaskOrder\", e);\n            return Result.buildFail(\"根据工单任务id删除对应任务详情信息失败\");\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Long> editEcmTaskDetail(EcmTaskDetail buildEcmTaskDetail) {\n        boolean succ = 1 == ecmTaskDetailDAO.update(ConvertUtil.obj2Obj(buildEcmTaskDetail, EcmTaskDetailPO.class));\n        return Result.build(succ, buildEcmTaskDetail.getId());\n    }\n\n    @Override\n    public EcmTaskDetailProgress buildInitialEcmTaskDetail(Long workOrderTaskId) {\n        EcmTask ecmTask = ecmTaskManager.getEcmTask(workOrderTaskId);\n        if (AriusObjUtils.isNull(ecmTask)) {\n            LOGGER.error(\"class=EcmTaskDetailManagerImpl||method=buildInitialEcmTaskDetail||orderTaskId={}||\"\n                         + \"msg=the ecm task is empty\",\n                workOrderTaskId);\n        }\n\n        EcmTaskDetailProgress ecmTaskDetailProgress = EcmTaskDetailProgress.newFieldInitializedInstance();\n        List<EcmParamBase> ecmParamBases = OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask);\n        if (CollectionUtils.isEmpty(ecmParamBases)) {\n            LOGGER.error(\"class=EcmTaskDetailManagerImpl||method=buildInitialEcmTaskDetail||orderTaskId={}||\"\n                         + \"msg=the convert ecm param is empty\",\n                workOrderTaskId);\n        }\n\n        Map<String, List<String>> role2HostNamesMap = getClusterHostNamesFromDbMap(\n            ecmTask.getPhysicClusterId().intValue());\n        //1.获取工单总量\n        Integer sum = ecmParamBases.stream().filter(r -> !AriusObjUtils.isNull(r) && r.getNodeNumber() != 0)\n            .mapToInt(EcmParamBase::getNodeNumber).sum();\n        ecmTaskDetailProgress.setSum(sum.longValue());\n\n        //2.状态计算\n        if (Objects.equals(OpTaskTypeEnum.CLUSTER_NEW.getType(), ecmTask.getOrderType())\n            || Objects.equals(OpTaskTypeEnum.CLUSTER_UPGRADE.getType(), ecmTask.getOrderType())\n            || Objects.equals(OpTaskTypeEnum.CLUSTER_RESTART.getType(), ecmTask.getOrderType())) {\n            ecmParamBases.stream().filter(Objects::nonNull).forEachOrdered(ecmParam -> ecmTaskDetailProgress\n                .getRoleNameTaskDetailMap().put(ecmParam.getRoleName(), Lists.newArrayList()));\n        }\n\n        //扩缩容获取变化的机器\n        if (Objects.equals(OpTaskTypeEnum.CLUSTER_EXPAND.getType(), ecmTask.getOrderType())\n            || Objects.equals(OpTaskTypeEnum.CLUSTER_SHRINK.getType(), ecmTask.getOrderType())) {\n\n            for (Map.Entry<String, List<String>> e : role2HostNamesMap.entrySet()) {\n                ecmParamBases.stream().filter(r -> !AriusObjUtils.isNull(r) && r.getRoleName().equals(e.getKey()))\n                    .forEachOrdered(ecmParam -> {\n                        ecmTaskDetailProgress.getRoleNameTaskDetailMap().put(ecmParam.getRoleName(),\n                            Lists.newArrayList());\n                    });\n            }\n        }\n\n        ecmTaskDetailProgress.setWaiting(ecmTaskDetailProgress.getSum());\n        ecmTaskDetailProgress.setStatus(ecmTask.getStatus());\n        ecmTaskDetailProgress.setOrderType(ecmTask.getOrderType());\n        ecmTaskDetailProgress.updatePercent();\n        return ecmTaskDetailProgress;\n    }\n\n    /*****************************************************private*********************************************************/\n    private Map</*角色属性*/String, /*角色对应的主机ip列表*/List<String>> getClusterHostNamesFromDbMap(int clusterId) {\n        List<ClusterRoleInfo> roles = clusterRoleService.getAllRoleClusterByClusterId(clusterId);\n        if (CollectionUtils.isEmpty(roles)) {\n            return Maps.newHashMap();\n        }\n\n        Map<String, List<String>> role2HostNamesMap = Maps.newHashMap();\n        roles.stream().filter(Objects::nonNull).forEachOrdered(role -> {\n            List<ClusterRoleHost> clusterHosts = clusterRoleHostService.getByRoleClusterId(role.getId());\n            if (CollectionUtils.isEmpty(clusterHosts)) {\n                LOGGER.warn(\"class=||method=getEcmTaskDetailInfo||msg=the cluster hosts is empty\");\n                return;\n            }\n\n            List<String> clusterHostNames = clusterHosts.stream()\n                .filter(r -> !AriusObjUtils.isNull(r) && !AriusObjUtils.isBlack(r.getIp()))\n                .map(ClusterRoleHost::getHostname).collect(Collectors.toList());\n            if (CollectionUtils.isEmpty(clusterHostNames)) {\n                LOGGER.warn(\"class=||method=getEcmTaskDetailInfo||msg=the cluster hosts name is empty\");\n                return;\n            }\n\n            role2HostNamesMap.put(role.getRole(), clusterHostNames);\n        });\n\n        return role2HostNamesMap;\n    }\n\n    private void initEcmTaskDetailParam(EcmTaskDetailPO ecmTaskDetailPo) {\n        if (ecmTaskDetailPo.getGrp() == null) {\n            ecmTaskDetailPo.setGrp(0);\n        }\n        if (ecmTaskDetailPo.getIdx() == null) {\n            ecmTaskDetailPo.setIdx(0);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/ecm/impl/EcmTaskManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.ecm.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmHostStatusEnum.CANCELLED;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmHostStatusEnum.FAILED;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmHostStatusEnum.KILL_FAILED;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmHostStatusEnum.SUCCESS;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmTaskStatusEnum.CANCEL;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.ADD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.EDIT;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.CLIENT_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.MASTER_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_DOCKER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_HOST;\nimport static com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.ZeusClusterActionEnum.EXPAND;\nimport static com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.ZeusClusterActionEnum.SHRINK;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskDetailManager;\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.WorkOrderManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.utils.OpOrderTaskConverter;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmTaskBasic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmTaskDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud.ElasticCloudCommonActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostCreateActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostScaleActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmOperateAppBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmTaskStatus;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.BaseClusterHostOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.ecm.EcmTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.detail.OrderDetailBaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmHostStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmTaskStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.ecm.EcmTaskEditEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.resource.ClusterPhyHealthEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.EcmRemoteException;\nimport com.didichuxing.datachannel.arius.admin.common.threadpool.AriusScheduleThreadPool;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.EcmHandleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.task.EcmTaskDAO;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.EcmActionEnum;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * ES工单任务管理\n * @author didi\n * @since 2020-08-24\n */\n@Service\n@NoArgsConstructor\npublic class EcmTaskManagerImpl implements EcmTaskManager {\n    private static final ILog LOGGER                = LogFactory.getLog(EcmTaskManagerImpl.class);\n    public static final long        DEFAULT_WORK_ORDER_ID = -1L;\n\n    @Value(\"${es.client.cluster.port}\")\n    private String                  esClusterClientPort;\n\n    @Autowired\n    private EcmTaskDAO              ecmTaskDao;\n\n    @Autowired\n    private EcmHandleService        ecmHandleService;\n\n    @Autowired\n    private ClusterPhyService       clusterPhyService;\n\n    @Autowired\n    private ClusterPhyManager       clusterPhyManager;\n\n    @Autowired\n    private ClusterRoleService      clusterRoleService;\n\n    @Autowired\n    private ClusterRoleHostService  clusterRoleHostService;\n\n    @Autowired\n    private EcmTaskDetailManager    ecmTaskDetailManager;\n\n    @Autowired\n    private ESClusterService        esClusterService;\n\n    @Autowired\n    private AriusScheduleThreadPool ariusScheduleThreadPool;\n\n    @Autowired\n    private WorkOrderManager        workOrderManager;\n    @Autowired\n    private ProjectService       projectService;\n    @Autowired\n    private OperateRecordService operateRecordService;\n\n    @Override\n    public boolean existUnClosedEcmTask(Long phyClusterId) {\n        List<EcmTaskPO> notFinishedTasks = ecmTaskDao.listUndoEcmTaskByClusterId(phyClusterId);\n        return !AriusObjUtils.isEmptyList(notFinishedTasks);\n    }\n\n    @Override\n    public Result<Long> saveEcmTask(EcmTaskDTO ecmTaskDTO) {\n        if (CollectionUtils.isEmpty(ecmTaskDTO.getEcmParamBaseList())) {\n            return Result.buildFail(\"工单数据为空\");\n        }\n        //过滤掉nodeNumber 为0的数据\n        List<EcmParamBase> filteredEcmParamBaseList = ecmTaskDTO.getEcmParamBaseList().stream()\n            .filter(elem -> elem.getNodeNumber() != null && elem.getNodeNumber() > 0).collect(Collectors.toList());\n\n        EcmTaskPO ecmTaskPO = ConvertUtil.obj2Obj(ecmTaskDTO, EcmTaskPO.class);\n        ecmTaskPO.setClusterNodeRole(ListUtils.strList2String(\n            filteredEcmParamBaseList.stream().map(EcmParamBase::getRoleName).collect(Collectors.toList())));\n        ecmTaskPO.setHandleData(ConvertUtil.obj2Json(filteredEcmParamBaseList));\n        //默认状态都是 待执行\n        ecmTaskPO.setStatus(EcmTaskStatusEnum.WAITING.getValue());\n        //设置默认的工单ID\n        if (null == ecmTaskPO.getWorkOrderId()) {\n            ecmTaskPO.setWorkOrderId(DEFAULT_WORK_ORDER_ID);\n        }\n        if (ecmTaskDao.save(ecmTaskPO) < 1) {\n            // 存储失败\n            return Result.buildFail(ecmTaskPO.getTitle());\n        }\n        return Result.buildSucc(ecmTaskPO.getId());\n    }\n\n    @Override\n    public List<EcmTask> listEcmTask() {\n        return ConvertUtil.list2List(ecmTaskDao.listAll(), EcmTask.class);\n    }\n\n    @Override\n    public List<EcmTask> listRunningEcmTask() {\n        return ConvertUtil.list2List(ecmTaskDao.listRunningTasks(), EcmTask.class);\n    }\n\n    @Override\n    public Result<EcmTaskBasic> getEcmTaskBasicByTaskId(Long taskId) {\n        EcmTaskPO ecmTaskPO = ecmTaskDao.getById(taskId);\n        if (ecmTaskPO == null) {\n            return Result.buildFail(\"任务不存在\");\n        }\n        EcmTask ecmTask = ConvertUtil.obj2Obj(ecmTaskPO, EcmTask.class);\n        EcmTaskBasic ecmTaskBasic = ConvertUtil.obj2Obj(ecmTaskPO, EcmTaskBasic.class);\n\n        if (Objects.equals(OpTaskTypeEnum.CLUSTER_NEW.getType(), ecmTaskPO.getOrderType())\n            && ESClusterTypeEnum.ES_HOST.getCode() == ecmTaskBasic.getType()) {\n            // 集群新建的工单, 该信息从参数中获取\n            Map<String, EcmParamBase> ecmParamBaseMap = OpOrderTaskConverter.convert2EcmParamBaseMap(ecmTask);\n            HostCreateActionParam ecmCreateParamBase = (HostCreateActionParam) ecmParamBaseMap\n                .getOrDefault(MASTER_NODE.getDesc(), new HostCreateActionParam());\n            ecmTaskBasic.setClusterName(ecmCreateParamBase.getPhyClusterName());\n            ecmTaskBasic.setIdc(ecmCreateParamBase.getIdc());\n            ecmTaskBasic.setNsTree(ecmCreateParamBase.getNsTree());\n            ecmTaskBasic.setDesc(ecmCreateParamBase.getDesc());\n            ecmTaskBasic.setEsVersion(ecmCreateParamBase.getEsVersion());\n            ecmTaskBasic.setImageName(ecmCreateParamBase.getImageName());\n            return Result.buildSucc(ecmTaskBasic);\n        }\n\n        // 集群已经新建完成, 集群信息已经入库\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(ecmTaskPO.getPhysicClusterId().intValue());\n        if (clusterPhy != null) {\n            ecmTaskBasic.setClusterName(clusterPhy.getCluster());\n            ecmTaskBasic.setIdc(clusterPhy.getIdc());\n            ecmTaskBasic.setNsTree(clusterPhy.getNsTree());\n            ecmTaskBasic.setDesc(clusterPhy.getDesc());\n            ecmTaskBasic.setEsVersion(clusterPhy.getEsVersion());\n            ecmTaskBasic.setImageName(clusterPhy.getImageName());\n        }\n\n        // 获取任务的创建时间和更新时间\n        ecmTaskBasic.setCreateTime(ecmTaskPO.getCreateTime());\n        List<EcmTaskDetail> ecmTaskDetails = ecmTaskDetailManager.getEcmTaskDetailInOrder(taskId);\n        Optional<Date> optionalDate = ecmTaskDetails.stream().map(EcmTaskDetail::getUpdateTime).distinct()\n            .max(Date::compareTo);\n        optionalDate.ifPresent(ecmTaskBasic::setUpdateTime);\n\n        return Result.buildSucc(ecmTaskBasic);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<EcmOperateAppBase> savaAndActionEcmTask(Long taskId, String operator) throws EcmRemoteException {\n        //1. 校验ECM任务有效性\n        EcmTask ecmTask = getEcmTask(taskId);\n        if (AriusObjUtils.isNull(ecmTask)) {\n            return Result.buildFail(\"Ecm任务不存在\");\n        }\n        if (EcmTaskStatusEnum.RUNNING.getValue().equals(ecmTask.getStatus())) {\n            return Result.buildFail(\"任务正在执行中, 请勿重复操作\");\n        }\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask);\n        if (CollectionUtils.isEmpty(ecmParamBaseList)) {\n            return Result.buildFail(\"转化工单数据失败\");\n        }\n\n        //2. 创建ES物理集群信息\n        Result<Long> saveResult = ecmHandleService.saveESCluster(ecmParamBaseList);\n        if (saveResult.failed()) {\n            return Result.buildFrom(saveResult);\n        }\n\n        //3. 回写ES集群Id到到ECMTask\n        ecmTask.setPhysicClusterId(saveResult.getData());\n        ecmTask.setHandleData(ConvertUtil.obj2Json(ecmParamBaseList));\n        updateEcmTask(ecmTask);\n\n        //4. 启动任务, 运行新建master节点的ECM任务\n        Result<EcmOperateAppBase> actionRet = actionEcmTaskForMasterNode(ecmParamBaseList, taskId, operator);\n        if (actionRet.failed()) {\n            //用于回滚物理集群保留信息\n            throw new EcmRemoteException(actionRet.getMessage());\n        }\n\n        return actionRet;\n    }\n\n    @Override\n    public Result<Void> retryClusterEcmTask(Long taskId, String operator) {\n        //1. 校验ECM任务有效性\n        EcmTask ecmTask = getEcmTask(taskId);\n        if (AriusObjUtils.isNull(ecmTask)) {\n            return Result.buildFail(\"Ecm任务不存在\");\n        }\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask);\n        if (CollectionUtils.isEmpty(ecmParamBaseList)) {\n            return Result.buildFail(\"转化工单数据失败\");\n        }\n\n        //2.将角色列表中的zeus任务id设置为空\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            HostParamBase hostParamBase = (HostParamBase) ecmParamBase;\n            hostParamBase.setTaskId(null);\n        }\n        ecmTask.setHandleData(JSONArray.toJSONString(ecmParamBaseList));\n\n        //3.删除task_detail表中的数据\n        ecmTaskDetailManager.deleteEcmTaskDetailsByTaskOrder(taskId);\n\n        //4.将arius_work_task和es_work_order_task中对应任务的状态设置为waiting\n        ecmTask.setStatus(EcmTaskStatusEnum.WAITING.getValue());\n        updateEcmTask(ecmTask);\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> actionClusterEcmTask(Long taskId, String operator) throws EcmRemoteException {\n        //1. 校验ECM任务有效性\n        EcmTask ecmTask = getEcmTask(taskId);\n        if (AriusObjUtils.isNull(ecmTask)) {\n            return Result.buildFail(\"Ecm任务不存在\");\n        }\n\n        if (EcmTaskStatusEnum.RUNNING.getValue().equals(ecmTask.getStatus())) {\n            return Result.buildParamIllegal(\"任务正在执行中, 请勿重复操作\");\n        }\n\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask);\n        if (CollectionUtils.isEmpty(ecmParamBaseList)) {\n            return Result.buildFail(\"转化工单数据失败\");\n        }\n\n        //2. 枚举处理每个角色任务信息\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            //2.1 过滤已运行任务\n            if (!AriusObjUtils.isNull(ecmParamBase.getTaskId())\n                && isTaskActed(EcmTaskStatusEnum.SUCCESS, ecmParamBase, ecmTask.getOrderType(), operator)) {\n                // 当前任务已经触发执行 & 任务已经完成\n                continue;\n            } else if (!AriusObjUtils.isNull(ecmParamBase.getTaskId())\n                       && !isTaskActed(EcmTaskStatusEnum.SUCCESS, ecmParamBase, ecmTask.getOrderType(), operator)) {\n                // 当前任务已经触发执行 & 任务未完成, 此时直接return成功\n                return Result.buildSucc();\n            }\n\n            //2.2 运行ECM任务\n            Result<EcmOperateAppBase> ret = runEcmTask(ecmParamBase, ecmTask.getOrderType(), operator);\n            if (ret.failed()) {\n                throw new EcmRemoteException(ret.getMessage());\n            }\n\n            //回写taskId至DB\n            ecmParamBase.setTaskId(ret.getData().getTaskId());\n            ecmTask.setStatus(EcmTaskStatusEnum.RUNNING.getValue());\n            ecmTask.setHandleData(ConvertUtil.obj2Json(ecmParamBaseList));\n            updateEcmTask(ecmTask);\n\n            return Result.buildSucc(ret.getData());\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> actionClusterEcmTask(Long taskId, EcmActionEnum ecmActionEnum, String hostname,\n                                                          String operator) throws EcmRemoteException {\n        EcmTaskPO ecmTask = ecmTaskDao.getById(taskId);\n        if (AriusObjUtils.isNull(ecmTask)) {\n            return Result.buildParamIllegal(\"集群任务不存在\");\n        }\n\n        //接口幂等判断\n        if (EcmTaskStatusEnum.RUNNING.getValue().equals(ecmTask.getStatus())) {\n            return Result.buildFail(\"当前集群任务正在执行, 请勿重复操作\");\n        }\n\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter\n            .convert2EcmParamBaseList(ConvertUtil.obj2Obj(ecmTask, EcmTask.class));\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            if (!AriusObjUtils.isNull(ecmParamBase.getTaskId())\n                && isTaskActed(EcmTaskStatusEnum.SUCCESS, ecmParamBase, ecmTask.getOrderType(), operator)) {\n                // 当前任务已经触发执行 & 任务已经完成\n                continue;\n            } else if (!AriusObjUtils.isNull(ecmParamBase.getTaskId())\n                       && !isTaskActed(EcmTaskStatusEnum.SUCCESS, ecmParamBase, ecmTask.getOrderType(), operator)) {\n                // 当前任务已经触发执行 & 任务未执行完成\n                // 更新ecm任务状态从pause变为running\n                ecmTask.setStatus(EcmTaskStatusEnum.RUNNING.getValue());\n                updateEcmTask(ConvertUtil.obj2Obj(ecmTask, EcmTask.class));\n                return ecmHandleService.actionUnfinishedESCluster(ecmActionEnum, ecmParamBase, hostname, operator);\n            }\n\n            // 任务未触发\n            if (EcmActionEnum.START.equals(ecmActionEnum)) {\n                // 下一个任务未触发执行的情况下, 收到continue之后, 则继续执行后续动作\n                return actionClusterEcmTask(taskId, operator);\n            }\n\n            // 其他情况直接返回操作失败\n            return Result.buildFail(\"任务已处于暂停状态, 操作无效\");\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> cancelClusterEcmTask(Long taskId, String operator) {\n        EcmTask ecmTask = getEcmTask(taskId);\n        if (AriusObjUtils.isNull(ecmTask)) {\n            return Result.buildParamIllegal(\"集群任务不存在\");\n        }\n\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter\n            .convert2EcmParamBaseList(ConvertUtil.obj2Obj(ecmTask, EcmTask.class));\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            if (!AriusObjUtils.isNull(ecmParamBase) && AriusObjUtils.isNull(ecmParamBase.getTaskId())) {\n                // 将没有进行创建zeus任务的以cancel状态插入到task_detail表中\n                saveTaskDetailInfoWithoutZeusTaskId(ecmParamBase, taskId, CANCEL);\n            } else if (!AriusObjUtils.isNull(ecmParamBase) && !AriusObjUtils.isNull(ecmParamBase.getTaskId())) {\n                ecmHandleService.actionUnfinishedESCluster(EcmActionEnum.CANCEL, ecmParamBase, null, operator);\n            }\n        }\n\n        //修改工单任务\n        ecmTask.setStatus(EcmTaskStatusEnum.CANCEL.getValue());\n        updateEcmTask(ecmTask);\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> pauseClusterEcmTask(Long taskId, String operator) {\n        EcmTaskPO ecmTask = ecmTaskDao.getById(taskId);\n        if (AriusObjUtils.isNull(ecmTask)) {\n            return Result.buildParamIllegal(\"集群任务不存在\");\n        }\n\n        //接口幂等判断\n        if (!EcmTaskStatusEnum.RUNNING.getValue().equals(ecmTask.getStatus())) {\n            return Result.buildFail(\"当前集群任务并非处于running状态, 无法进行暂停操作\");\n        }\n\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter\n            .convert2EcmParamBaseList(ConvertUtil.obj2Obj(ecmTask, EcmTask.class));\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            if (!AriusObjUtils.isNull(ecmParamBase)\n                && isTaskActed(EcmTaskStatusEnum.RUNNING, ecmParamBase, ecmTask.getOrderType(), operator)) {\n                ecmHandleService.actionUnfinishedESCluster(EcmActionEnum.PAUSE, ecmParamBase, null, operator);\n            }\n        }\n\n        // 任务未触发，不做任何操作，将任务的状态设置为暂停\n        ecmTask.setStatus(EcmTaskStatusEnum.PAUSE.getValue());\n        updateEcmTask(ConvertUtil.obj2Obj(ecmTask, EcmTask.class));\n        return Result.buildSucc();\n    }\n\n    @Override\n    public EcmTask getEcmTask(Long id) {\n        return ConvertUtil.obj2Obj(ecmTaskDao.getById(id), EcmTask.class);\n    }\n\n    @Override\n    public boolean updateEcmTask(EcmTask ecmTask) {\n        int ret = ecmTaskDao.update(ConvertUtil.obj2Obj(ecmTask, EcmTaskPO.class));\n        if (ret > 0) {\n            SpringTool.publish(new EcmTaskEditEvent(this, ecmTask));\n        }\n        return ret > 0;\n    }\n\n    @Override\n    public EcmTaskPO getRunningEcmTaskByClusterId(Integer physicClusterId) {\n        return ecmTaskDao.getUsefulEcmTaskByClusterId(physicClusterId);\n    }\n\n    @Override\n    public Result<Void> actionClusterHostEcmTask(Long taskId, EcmActionEnum ecmActionEnum, String hostname,\n                                                 String operator) {\n        EcmTaskPO ecmTask = ecmTaskDao.getById(taskId);\n        if (AriusObjUtils.isNull(ecmTask)) {\n            return Result.buildParamIllegal(\"集群任务不存在\");\n        }\n\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter\n            .convert2EcmParamBaseList(ConvertUtil.obj2Obj(ecmTask, EcmTask.class));\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            if (!AriusObjUtils.isNull(ecmParamBase)) {\n                ecmHandleService.actionUnfinishedESCluster(ecmActionEnum, ecmParamBase, hostname, operator);\n            }\n        }\n\n        // 将集群任务设置为RUNNING状态\n        ecmTask.setStatus(EcmTaskStatusEnum.RUNNING.getValue());\n        updateEcmTask(ConvertUtil.obj2Obj(ecmTask, EcmTask.class));\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<EcmTask> getUsefulEcmTaskByClusterName(String clusterName) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterName);\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildFail(\"物理名称对应的物理信息不存在\");\n        }\n        return Result\n            .buildSucc(ConvertUtil.obj2Obj(ecmTaskDao.getUsefulEcmTaskByClusterId(clusterPhy.getId()), EcmTask.class));\n    }\n\n    @Override\n    public Result<String> getEcmTaskOrderDetailInfo(String cluster) {\n        if (AriusObjUtils.isBlack(cluster)) {\n            return Result.buildFail(\"cluster name 为空\");\n        }\n\n        Result<EcmTask> usefulWorkOrderTaskByClusterName = getUsefulEcmTaskByClusterName(cluster);\n        if (usefulWorkOrderTaskByClusterName.failed()) {\n            return Result.buildFail(\"无法获取物理集群信息\");\n        }\n        EcmTask task = usefulWorkOrderTaskByClusterName.getData();\n        if (AriusObjUtils.isNull(task)) {\n            return Result.buildFail(\"当前集群没有待执行的工单任务\");\n        }\n\n        List<EcmParamBase> ecmParamBases = OpOrderTaskConverter.convert2EcmParamBaseList(task);\n        if (CollectionUtils.isEmpty(ecmParamBases)) {\n            return Result.buildFail(\"当前任务没有工单数据\");\n        }\n        OrderDetailBaseVO orderDetailBaseVO = workOrderManager.getById(task.getWorkOrderId()).getData();\n\n        return Result.buildSucc(orderDetailBaseVO.getDetail(), \"ecm任务对应的工单任务详细信息\");\n    }\n\n    @Override\n    public EcmTaskStatusEnum refreshEcmTask(EcmTask ecmTask) throws AdminTaskException {\n        if ((SUCCESS.getValue().equals(ecmTask.getStatus()) || CANCEL.getValue().equals(ecmTask.getStatus()))) {\n            return EcmTaskStatusEnum.SUCCESS;\n        }\n\n        List<EcmParamBase> ecmParamBases = OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask);\n        ecmParamBases.forEach(ecmParam -> ecmParam.setWorkOrderId(ecmTask.getId()));\n        Set<EcmTaskStatusEnum> subOrderTaskStatus = Sets.newHashSet();\n\n        long startTime = System.currentTimeMillis();\n        ecmParamBases.forEach(ecmParam -> subOrderTaskStatus.add(doRefreshEcmTask(ecmParam, ecmTask)));\n        LOGGER.info(\n            \"class=EcmTaskManagerImpl||method=refreshEcmTask||clusterId={}\" + \"||orderType={}||consumingTime={}\",\n            ecmTask.getPhysicClusterId(), ecmTask.getOrderType(), System.currentTimeMillis() - startTime);\n\n        EcmTaskStatusEnum mergedStatusEnum = EcmTaskStatusEnum.calTaskStatus(subOrderTaskStatus);\n\n        if (postProcess(ecmTask, mergedStatusEnum).failed()) {\n            mergedStatusEnum = EcmTaskStatusEnum.FAILED;\n        }\n\n        ecmTask.setStatus(mergedStatusEnum.getValue());\n        updateEcmTask(ecmTask);\n        return mergedStatusEnum;\n    }\n\n    /*************************************** private method ***************************************/\n    /**\n     * 灰度启动master角色的ES实例\n     * @param ecmParamBaseList    ES角色列表\n     * @param taskId              任务Id\n     * @param operator            操作人\n     * @return\n     */\n    private Result<EcmOperateAppBase> actionEcmTaskForMasterNode(List<EcmParamBase> ecmParamBaseList, Long taskId,\n                                                                 String operator) {\n        EcmTask ecmTask = getEcmTask(taskId);\n        if (null == ecmTask) {\n            return Result.buildFail(\"ECM任务为空\");\n        }\n        Map<String, EcmParamBase> role2EcmParamBaseMap = ConvertUtil.list2Map(ecmParamBaseList,\n            EcmParamBase::getRoleName, ecmParamBase -> ecmParamBase);\n\n        EcmParamBase ecmParamBase = role2EcmParamBaseMap.get(MASTER_NODE.getDesc());\n\n        Result<EcmOperateAppBase> runEcmTaskForMasterNodeRet = runEcmTask(ecmParamBase, ecmTask.getOrderType(),\n            operator);\n        if (runEcmTaskForMasterNodeRet.success()) {\n            //回写taskId至DB\n            ecmParamBase.setTaskId(runEcmTaskForMasterNodeRet.getData().getTaskId());\n            ecmTask.setStatus(EcmTaskStatusEnum.RUNNING.getValue());\n            ecmTask.setHandleData(ConvertUtil.obj2Json(ecmParamBaseList));\n            updateEcmTask(ecmTask);\n\n            //更新es role cluster note数量\n            updateRoleClusterNumber(ecmTask, ecmParamBase);\n            return Result.buildSucc(runEcmTaskForMasterNodeRet.getData());\n        }\n\n        return Result.buildFail();\n    }\n\n    private Result<EcmOperateAppBase> runEcmTask(EcmParamBase ecmParamBase, Integer orderType, String operator) {\n        Result<EcmOperateAppBase> result;\n        if (Objects.equals(OpTaskTypeEnum.CLUSTER_NEW.getType(), orderType)) {\n            result = ecmHandleService.startESCluster(ecmParamBase, operator);\n        } else if (Objects.equals(OpTaskTypeEnum.CLUSTER_EXPAND.getType(), orderType)) {\n            if (ecmParamBase instanceof HostScaleActionParam) {\n                HostScaleActionParam hostScaleActionParam = (HostScaleActionParam) ecmParamBase;\n                hostScaleActionParam.setAction(EXPAND.getValue());\n            }\n\n            result = ecmHandleService.scaleESCluster(ecmParamBase, operator);\n        } else if (Objects.equals(OpTaskTypeEnum.CLUSTER_SHRINK.getType(), orderType)) {\n            if (ecmParamBase instanceof HostScaleActionParam) {\n                HostScaleActionParam hostScaleActionParam = (HostScaleActionParam) ecmParamBase;\n                hostScaleActionParam.setAction(SHRINK.getValue());\n            }\n\n            result = ecmHandleService.scaleESCluster(ecmParamBase, operator);\n        } else if (Objects.equals(OpTaskTypeEnum.CLUSTER_RESTART.getType(), orderType)) {\n            result = ecmHandleService.restartESCluster(ecmParamBase, operator);\n        } else if (Objects.equals(OpTaskTypeEnum.CLUSTER_UPGRADE.getType(), orderType)) {\n            result = ecmHandleService.upgradeESCluster(ecmParamBase, operator);\n        } else {\n            return Result.buildFail(\"任务类型未知, 类型Code:\" + orderType);\n        }\n        return result;\n    }\n\n    /**任务执行过程进行EcmTask任务相关信息回写操作*/\n    private EcmTaskStatusEnum doRefreshEcmTask(EcmParamBase ecmParam, EcmTask ecmTask) {\n        if (AriusObjUtils.isNull(ecmParam.getTaskId())) {\n            return EcmTaskStatusEnum.PAUSE;\n        }\n        Result<List<EcmTaskStatus>> taskStatus;\n        List<EcmTaskStatus> remoteStatuses;\n        try {\n            //1.获取状态\n            taskStatus = ecmHandleService.getESClusterStatus(ecmParam, ecmTask.getOrderType(), null);\n            if (taskStatus.failed()) {\n                return EcmTaskStatusEnum.FAILED;\n            }\n\n            remoteStatuses = taskStatus.getData();\n            if (CollectionUtils.isEmpty(remoteStatuses)) {\n                return EcmTaskStatusEnum.SUCCESS;\n            }\n\n            if (!checkEcmTaskStatusValid(remoteStatuses)) {\n                return EcmTaskStatusEnum.RUNNING;\n            }\n            //2.更新taskDetail表\n            updateTaskDetailByTaskStatus(ecmParam, remoteStatuses);\n\n        } catch (Exception e) {\n            LOGGER.error(\"class=EcmTaskManagerImpl||method=doRefreshEcmTask||ecmTaskId={}||msg={}\", ecmTask.getId(),\n                e.getStackTrace());\n            return EcmTaskStatusEnum.FAILED;\n        }\n\n        //5.计算最终状态\n        Set<EcmTaskStatusEnum> ecmHostStatus = remoteStatuses.stream().map(r -> convertStatus(r.getStatusEnum()))\n            .collect(Collectors.toSet());\n        return EcmTaskStatusEnum.calTaskStatus(ecmHostStatus);\n    }\n\n    /**检查执行的任务是否处于指定的状态*/\n    private boolean isTaskActed(EcmTaskStatusEnum ecmTaskStatusEnum, EcmParamBase ecmParamBase, Integer orderType,\n                                String operator) {\n        Result<List<EcmTaskStatus>> result = ecmHandleService.getESClusterStatus(ecmParamBase, orderType, operator);\n        if (result.failed()) {\n            // 获取任务状态失败, 则直接返回false\n            return false;\n        }\n\n        Set<EcmTaskStatusEnum> statusEnumSet = new HashSet<>();\n        for (EcmTaskStatus ecmTaskStatus : result.getData()) {\n            statusEnumSet.add(convertStatus(ecmTaskStatus.getStatusEnum()));\n        }\n\n        EcmTaskStatusEnum getEcmTaskStatusEnum = EcmTaskStatusEnum.calTaskStatus(statusEnumSet);\n        return ecmTaskStatusEnum.equals(getEcmTaskStatusEnum);\n    }\n\n    /**更新taskDetail表*/\n    private void updateTaskDetailByTaskStatus(EcmParamBase ecmParam, List<EcmTaskStatus> remoteStatuses) {\n        Map<Long, EcmTaskStatus> id2ExistDetailMap = Maps.newHashMap();\n        List<EcmTaskDetail> taskDetailsFromDb = ecmTaskDetailManager.getByOrderIdAndRoleAndTaskId(\n            ecmParam.getWorkOrderId().intValue(), ecmParam.getRoleName(), ecmParam.getTaskId());\n\n        //获取已经存在Detail表的EcmTask\n        remoteStatuses.stream().filter(Objects::nonNull)\n            .forEach(r -> taskDetailsFromDb.stream().filter(Objects::nonNull).forEach(detailFromDb -> {\n                if (detailFromDb.getHostname().equals(r.getHostname())) {\n                    id2ExistDetailMap.put(detailFromDb.getId(), r);\n                }\n            }));\n\n        if (MapUtils.isNotEmpty(id2ExistDetailMap)) {\n            for (Map.Entry<Long, EcmTaskStatus> e : id2ExistDetailMap.entrySet()) {\n                ecmTaskDetailManager.editEcmTaskDetail(buildEcmTaskDetail(e.getValue(), e.getKey(), ecmParam, EDIT));\n            }\n        } else {\n            remoteStatuses.stream().filter(Objects::nonNull).forEach(\n                status -> ecmTaskDetailManager.saveEcmTaskDetail(buildEcmTaskDetail(status, null, ecmParam, ADD)));\n        }\n    }\n\n    /**\n     * 任务完成后续回写更新操作\n     * @param ecmTask             ECM任务\n     * @param mergedStatusEnum    任务状态\n     * @return\n     */\n    private Result<Void> postProcess(EcmTask ecmTask, EcmTaskStatusEnum mergedStatusEnum) throws AdminTaskException {\n        if (!SUCCESS.getValue().equals(mergedStatusEnum.getValue()) && !hasRemoteTaskFailed(mergedStatusEnum)) {\n            return Result.buildSucc();\n        }\n\n        List<EcmParamBase> ecmParamBases = OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask);\n\n        //1. 任务失败, 清理集群role表数据、data_source表数据\n        //cleanUpUselessClusterInfoFromDB(mergedStatusEnum, ecmParamBases);\n        if (hasRemoteTaskFailed(mergedStatusEnum)) {\n            return Result.buildSucc();\n        }\n\n        //2. 更新集群读写地址, 其中重启，升级 不需要更新读写地址\n        if (updateClusterAddressWhenIsValid(ecmTask, mergedStatusEnum, ecmParamBases).failed()) {\n            return Result.buildFail();\n        }\n\n        //3.根据ecm任务中内容插入es_cluster_role_host_info表中\n        saveOrEditHostInfoFromEcmTask(ecmTask, mergedStatusEnum);\n\n        //4. 设置30s的延迟时间，采集节点数据入集群host表中\n        delayCollectNodeSettingsTask(ecmParamBases);\n\n        //5. 升级, 更新集群版本\n        updateEsClusterVersion(mergedStatusEnum, ecmTask);\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 集群的新建，扩容，缩容任务需要修改es_role_host表信息\n     * @param ecmTask ecm任务\n     * @param mergedStatusEnum 总的任务执行情况\n     */\n    private void saveOrEditHostInfoFromEcmTask(EcmTask ecmTask,\n                                               EcmTaskStatusEnum mergedStatusEnum) throws AdminTaskException {\n        if (!EcmTaskStatusEnum.SUCCESS.equals(mergedStatusEnum)) {\n            return;\n        }\n\n        switch (OpTaskTypeEnum.valueOfType(ecmTask.getOrderType())) {\n            case CLUSTER_EXPAND:\n            case CLUSTER_NEW:\n                addHostInfoFromTaskOrder(ecmTask);\n                break;\n            case CLUSTER_SHRINK:\n                deleteRoleClusterAndHost(mergedStatusEnum, ecmTask);\n                break;\n            default:\n                break;\n        }\n    }\n\n    private void addHostInfoFromTaskOrder(EcmTask ecmTask) throws AdminTaskException {\n        // 从ecm任务的工单中获取节点全量的信息\n        Result<OrderDetailBaseVO> getOrderDetailResult = workOrderManager.getById(ecmTask.getWorkOrderId());\n        if (getOrderDetailResult.failed()) {\n            return;\n        }\n        BaseClusterHostOrderDetail baseClusterHostOrderDetail = (JSONObject\n            .parseObject(getOrderDetailResult.getData().getDetail(), BaseClusterHostOrderDetail.class));\n\n        // 保存全量节点信息到DB\n        clusterRoleHostService.createClusterNodeSettings(baseClusterHostOrderDetail.getRoleClusterHosts(),\n            baseClusterHostOrderDetail.getPhyClusterName());\n\n        // 更新es_cluster_role_info中的podNumber\n        for (EcmParamBase ecmParamBase : OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask)) {\n            HostParamBase hostParamBase = (HostParamBase) ecmParamBase;\n            if (CollectionUtils.isEmpty(hostParamBase.getHostList())) {\n                continue;\n            }\n\n            ClusterRoleInfo clusterRoleInfo = clusterRoleService\n                .getByClusterNameAndRole(baseClusterHostOrderDetail.getPhyClusterName(), hostParamBase.getRoleName());\n            if (clusterRoleInfo == null) {\n                continue;\n            }\n\n            updatePodNumbers(ecmTask, clusterRoleInfo);\n        }\n    }\n\n    private Result<Void> updateClusterAddressWhenIsValid(EcmTask ecmTask, EcmTaskStatusEnum mergedStatusEnum,\n                                                         List<EcmParamBase> ecmParamBases) {\n        if (!hasCallBackAddress(mergedStatusEnum, ecmTask)) {\n            return Result.buildSucc();\n        }\n        try {\n            boolean succ = ESOpTimeoutRetry.esRetryExecuteWithGivenTime(\"集群读写地址有效性检测\",\n                ClusterConstant.DEFAULT_RETRY_TIMES, () -> hasValidEsClusterReadAndWriteAddress(ecmTask, ecmParamBases),\n                ClusterConstant::defaultRetryTime);\n            if (succ) {\n                updateClusterReadAndWriteAddress(ecmTask, ecmParamBases);\n                // 物理集群读写地址更新完毕之后进行es-client的刷新\n                SpringTool.publish(new ClusterPhyHealthEvent(this, getClusterPhyNameFromEcmParamBases(ecmParamBases)));\n                return Result.buildSucc();\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=EcmTaskManagerImpl||method=postProcess||errMsg={}\", e.getMessage());\n        }\n        return Result.buildFail();\n    }\n\n    private void delayCollectNodeSettingsTask(List<EcmParamBase> ecmParamBases) {\n        ariusScheduleThreadPool.submitScheduleAtFixedDelayTask(() -> {\n            String clusterPhyName = getClusterPhyNameFromEcmParamBases(ecmParamBases);\n            try {\n                clusterRoleHostService.collectClusterNodeSettings(clusterPhyName);\n            } catch (AdminTaskException e) {\n                e.printStackTrace();\n            }\n        }, 30, 600);\n    }\n\n    private boolean hasValidEsClusterReadAndWriteAddress(EcmTask ecmTask, List<EcmParamBase> ecmParamBases) {\n        List<String> clusterAddress = Lists.newArrayList();\n        if (ES_DOCKER.getCode() == ecmTask.getType()) {\n            //docker类型待开发\n        } else if (ES_HOST.getCode() == ecmTask.getType()) {\n            clusterAddress = buildClusterReadAndWriteAddressForHost(ecmTask, ecmParamBases);\n        }\n\n        return esClusterService.syncGetClientAlivePercent(getClusterPhyNameFromEcmParamBases(ecmParamBases), null,\n            ListUtils.strList2String(clusterAddress)) > 0;\n    }\n\n    private String getClusterPhyNameFromEcmParamBases(List<EcmParamBase> ecmParamBases) {\n        String clusterPhyName = null;\n        for (EcmParamBase ecmParamBase : ecmParamBases) {\n            if (StringUtils.isNotBlank(ecmParamBase.getPhyClusterName())) {\n                clusterPhyName = ecmParamBase.getPhyClusterName();\n            }\n        }\n\n        return clusterPhyName;\n    }\n\n    private void updateClusterReadAndWriteAddress(EcmTask ecmTask, List<EcmParamBase> ecmParamBases) {\n        if (ES_DOCKER.getCode() == ecmTask.getType()) {\n            //docker类型待开发\n        } else if (ES_HOST.getCode() == ecmTask.getType()) {\n            List<String> clusterPhyAddress = buildClusterReadAndWriteAddressForHost(ecmTask, ecmParamBases);\n            if (CollectionUtils.isNotEmpty(clusterPhyAddress)) {\n                ClusterPhyDTO esClusterDTO = new ClusterPhyDTO();\n                esClusterDTO.setId(ecmTask.getPhysicClusterId().intValue());\n                esClusterDTO.setHttpAddress(ListUtils.strList2String(clusterPhyAddress));\n                esClusterDTO.setHttpWriteAddress(ListUtils.strList2String(clusterPhyAddress));\n                clusterPhyManager.editCluster(esClusterDTO, AriusUser.SYSTEM.getDesc());\n            }\n        }\n    }\n\n    private List<String> buildClusterReadAndWriteAddressForHost(EcmTask ecmTask, List<EcmParamBase> ecmParamBases) {\n        if (ecmTask.getOrderType().equals(OpTaskTypeEnum.CLUSTER_NEW.getType())) {\n            return buildClusterReadAndWriteAddressForHostWhenCreate(ecmParamBases);\n        }\n\n        if (ecmTask.getOrderType().equals(OpTaskTypeEnum.CLUSTER_SHRINK.getType())\n            || ecmTask.getOrderType().equals(OpTaskTypeEnum.CLUSTER_EXPAND.getType())) {\n            return buildClusterReadAndWriteAddressForHostWhenScale(ecmTask.getOrderType(), ecmTask.getPhysicClusterId(),\n                ecmParamBases);\n        }\n\n        if (ecmTask.getOrderType().equals(OpTaskTypeEnum.CLUSTER_RESTART.getType())) {\n            return buildClusterReadAndWriteAddressForHostWhenRestart(ecmTask.getPhysicClusterId());\n        }\n\n        return new ArrayList<>();\n    }\n\n    private List<String> buildClusterReadAndWriteAddressForHostWhenRestart(Long physicClusterId) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(Math.toIntExact(physicClusterId));\n        if (AriusObjUtils.isNull(clusterPhy) || AriusObjUtils.isNull(clusterPhy.getHttpAddress())) {\n            return Lists.newArrayList();\n        }\n\n        // 获取的当前集群可以使用的http地址，作为es服务有效性检测的地址池子\n        return ListUtils.string2StrList(clusterPhy.getHttpAddress());\n    }\n\n    private List<String> buildClusterReadAndWriteAddressForHostWhenCreate(List<EcmParamBase> ecmParamBases) {\n        List<String> clusterPhyAddress = Lists.newArrayList();\n        List<HostParamBase> hostParamBases = ConvertUtil.list2List(ecmParamBases, HostParamBase.class);\n        List<HostParamBase> builds = hostParamBases.stream()\n            .filter(hostParam -> filterValidHttpAddressEcmParamBase(CLIENT_NODE.getDesc(), hostParam))\n            .collect(Collectors.toList());\n        //没有client角色, 用master角色节点作为http读写地址\n        if (CollectionUtils.isEmpty(builds)) {\n            builds = hostParamBases.stream()\n                .filter(hostParam -> filterValidHttpAddressEcmParamBase(MASTER_NODE.getDesc(), hostParam))\n                .collect(Collectors.toList());\n        }\n\n        for (HostParamBase hostParamBase : builds) {\n            List<String> hostList = hostParamBase.getHostList();\n            hostList.forEach(host -> clusterPhyAddress.add(host + \":\" + hostParamBase.getPort()));\n        }\n\n        return clusterPhyAddress;\n    }\n\n    private List<String> buildClusterReadAndWriteAddressForHostWhenScale(Integer orderType, Long physicClusterId,\n                                                                         List<EcmParamBase> ecmParamBases) {\n        // 获取集群原有的clientnode和masternode的地址和端口号\n        List<String> clientHttpAddresses = getAddressesByByRoleAndClusterId(physicClusterId, CLIENT_NODE.getDesc());\n        List<String> masterHttpAddresses = getAddressesByByRoleAndClusterId(physicClusterId, MASTER_NODE.getDesc());\n\n        // 扩缩容的时候会在原始的角色地址列表中修改缩容的地址端口\n        List<HostParamBase> hostParamBases = ConvertUtil.list2List(ecmParamBases, HostParamBase.class);\n        for (HostParamBase hostParamBase : hostParamBases) {\n            if (CollectionUtils.isEmpty(hostParamBase.getHostList())) {\n                continue;\n            }\n\n            // 获取扩缩容中当前角色的地址端口列表\n            List<String> shouldOperateAddresses = hostParamBase.getHostList().stream()\n                .map(hostname -> hostname + \":\" + hostParamBase.getPort()).collect(Collectors.toList());\n\n            // 根据扩缩容和角色的类型对masternode和clientnode做对应删除增加操作\n            if (hostParamBase.getRoleName().equals(CLIENT_NODE.getDesc())) {\n                if (orderType.equals(OpTaskTypeEnum.CLUSTER_SHRINK.getType())) {\n                    clientHttpAddresses.removeAll(shouldOperateAddresses);\n                }\n\n                if (orderType.equals(OpTaskTypeEnum.CLUSTER_EXPAND.getType())) {\n                    clientHttpAddresses.addAll(shouldOperateAddresses);\n                }\n            }\n\n            if (hostParamBase.getRoleName().equals(MASTER_NODE.getDesc())) {\n                if (orderType.equals(OpTaskTypeEnum.CLUSTER_SHRINK.getType())) {\n                    masterHttpAddresses.removeAll(shouldOperateAddresses);\n                }\n\n                if (orderType.equals(OpTaskTypeEnum.CLUSTER_EXPAND.getType())) {\n                    masterHttpAddresses.addAll(shouldOperateAddresses);\n                }\n            }\n        }\n\n        // 如果client节点信息不为空，则使用client节点的ip地址, 否则使用matser节点信息\n        if (!CollectionUtils.isEmpty(clientHttpAddresses)) {\n            return clientHttpAddresses;\n        } else {\n            return masterHttpAddresses;\n        }\n    }\n\n    private List<String> getAddressesByByRoleAndClusterId(Long clusterId, String role) {\n        List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService.getByRoleAndClusterId(clusterId, role);\n        if (!CollectionUtils.isEmpty(clusterRoleHosts)) {\n            return clusterRoleHosts.stream()\n                .map(roleClusterHost -> roleClusterHost.getHostname() + \":\" + roleClusterHost.getPort())\n                .collect(Collectors.toList());\n        }\n        return Lists.newArrayList();\n    }\n\n    private boolean filterValidHttpAddressEcmParamBase(String role, HostParamBase hostParamBase) {\n        if (null == role) {\n            return false;\n        }\n\n        return role.equals(hostParamBase.getRoleName()) && CollectionUtils.isNotEmpty(hostParamBase.getHostList())\n               && null != hostParamBase.getPort();\n    }\n\n    /**\n     * 远程任务执行失败、取消、杀死判断为任务执行失败, 清理已插入集群Table的数据\n     * @param mergedStatusEnum 远程任务状态\n     * @return boolean\n     */\n    private boolean hasRemoteTaskFailed(EcmTaskStatusEnum mergedStatusEnum) {\n        return FAILED.getValue().equals(mergedStatusEnum.getValue())\n               || CANCELLED.getValue().equals(mergedStatusEnum.getValue())\n               || KILL_FAILED.getValue().equals(mergedStatusEnum.getValue());\n    }\n\n    /**\n     * 缩容操作，任务操作成功则硬删除对应集群角色的表数据\n     *\n     * @param mergedStatusEnum\n     * @param ecmTask\n     */\n    private void deleteRoleClusterAndHost(EcmTaskStatusEnum mergedStatusEnum, EcmTask ecmTask) {\n        for (EcmParamBase ecmParamBase : OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask)) {\n            HostParamBase hostParamBase = (HostParamBase) ecmParamBase;\n            if (CollectionUtils.isEmpty(hostParamBase.getHostList())) {\n                continue;\n            }\n\n            ClusterRoleInfo clusterRoleInfo = clusterRoleService\n                .getByClusterNameAndRole(hostParamBase.getPhyClusterName(), hostParamBase.getRoleName());\n            if (null == clusterRoleInfo) {\n                continue;\n            }\n\n            // 删除es_cluster_role_host_info数据\n            clusterRoleHostService.deleteByHostNameAndRoleId(hostParamBase.getHostList(), clusterRoleInfo.getId());\n\n            // 更新es_cluster_role_info数据中pod的数量 角色节点数目小于角色缩容数目相同，则返回\n            if (clusterRoleInfo.getPodNumber() < hostParamBase.getHostList().size()) {\n                return;\n            }\n\n            // 更新es_cluster_role_info数据中pod的数量 角色节点数目大于角色缩容数目，则做数目的更新\n            updatePodNumbers(ecmTask, clusterRoleInfo);\n        }\n    }\n\n    private void updatePodNumbers(EcmTask ecmTask, ClusterRoleInfo clusterRoleInfo) {\n        ClusterRoleInfo updateClusterRoleInfo = new ClusterRoleInfo();\n        updateClusterRoleInfo.setElasticClusterId(ecmTask.getPhysicClusterId());\n        updateClusterRoleInfo.setRole(clusterRoleInfo.getRole());\n        updateClusterRoleInfo.setPodNumber(clusterRoleHostService.getPodNumberByRoleId(clusterRoleInfo.getId()));\n        Result<Void> result = clusterRoleService.updatePodByClusterIdAndRole(updateClusterRoleInfo);\n        if (result.failed()) {\n            LOGGER.error(\"class=EcmTaskManagerImpl||method=deleteRoleCluster||clusterId={}||role={}\"\n                         + \"msg=failed to update roleCluster\",\n                ecmTask.getPhysicClusterId(), clusterRoleInfo.getRole());\n        }\n    }\n\n    /**\n     * 升级操作，回写集群版本到集群和角色\n     * @param mergedStatusEnum\n     * @param ecmTask\n     */\n    private void updateEsClusterVersion(EcmTaskStatusEnum mergedStatusEnum, EcmTask ecmTask) {\n        if (!SUCCESS.getValue().equals(mergedStatusEnum.getValue())) {\n            return;\n        }\n\n        if (!Objects.equals(OpTaskTypeEnum.CLUSTER_UPGRADE.getType(), ecmTask.getOrderType())) {\n            return;\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(ecmTask.getPhysicClusterId().intValue());\n        if (AriusObjUtils.isNull(clusterPhy) || AriusObjUtils.isBlack(clusterPhy.getCluster())) {\n            LOGGER.error(\"class=EcmTaskManagerImpl||method=callBackEsClusterVersion||clusterId={}||\"\n                         + \"msg=the es cluster or the cluster name is empty\",\n                ecmTask.getPhysicClusterId());\n            return;\n        }\n\n        List<EcmParamBase> ecmParamBases = OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask);\n\n        Tuple<String, String> tuple = new Tuple<>();\n        if (ecmTask.getType().equals(ESClusterTypeEnum.ES_HOST.getCode())) {\n            tuple = getImageAndVersion(ecmParamBases, HostParamBase::getImageName, HostParamBase::getEsVersion,\n                HostParamBase.class);\n        }\n\n        if (ecmTask.getType().equals(ESClusterTypeEnum.ES_DOCKER.getCode())) {\n            tuple = getImageAndVersion(ecmParamBases, ElasticCloudCommonActionParam::getImageName,\n                ElasticCloudCommonActionParam::getEsVersion, ElasticCloudCommonActionParam.class);\n        }\n\n        //1、更新集群角色的版本\n        for (String role : ecmTask.getClusterNodeRole().split(\",\")) {\n            Result<Void> result = clusterRoleService.updateVersionByClusterIdAndRole(ecmTask.getPhysicClusterId(), role,\n                tuple.getV2());\n            if (null != result && result.failed()) {\n                LOGGER.error(\n                    \"class=EcmTaskManagerImpl||method=callBackEsClusterVersion||clusterId={}||role={}||version={}\"\n                             + \"msg=failed to edit role cluster\",\n                    ecmTask.getPhysicClusterId(), role, tuple.getV2());\n            }\n        }\n\n        //2、更新集群的版本\n        ClusterPhyDTO esClusterDTO = new ClusterPhyDTO();\n        esClusterDTO.setId(ecmTask.getPhysicClusterId().intValue());\n        esClusterDTO.setImageName(tuple.getV1());\n        esClusterDTO.setEsVersion(tuple.getV2());\n        Result<Boolean> result = clusterPhyService.editCluster(esClusterDTO, AriusUser.SYSTEM.getDesc());\n        if (null != result && result.failed()) {\n            LOGGER.error(\"class=EcmTaskManagerImpl||method=callBackEsClusterVersion||clusterId={}||\"\n                         + \"msg=failed to edit cluster\",\n                ecmTask.getPhysicClusterId());\n        }\n    }\n\n    private <T> Tuple<String, String> getImageAndVersion(List<EcmParamBase> ecmParamBases, Function<T, String> funImage,\n                                                         Function<T, String> funVersion, Class<T> type) {\n        List<T> params = ConvertUtil.list2List(ecmParamBases, type);\n        String changeImageName = params.stream()\n            .filter(r -> !AriusObjUtils.isNull(r) && !AriusObjUtils.isBlack(funImage.apply(r))).map(funImage).findAny()\n            .orElse(null);\n\n        String changeEsVersion = params.stream()\n            .filter(r -> !AriusObjUtils.isNull(r) && !AriusObjUtils.isBlack(funVersion.apply(r))).map(funVersion)\n            .findAny().orElse(null);\n\n        return new Tuple<>(changeImageName, changeEsVersion);\n    }\n\n    private EcmTaskDetail buildEcmTaskDetail(EcmTaskStatus status, Long detailId, EcmParamBase ecmParamBase,\n                                             OperationEnum operation) {\n        EcmTaskDetail ecmTaskDetail = new EcmTaskDetail();\n        if (ADD.getCode() == operation.getCode()) {\n            ecmTaskDetail.setWorkOrderTaskId(ecmParamBase.getWorkOrderId());\n            ecmTaskDetail.setStatus(status.getStatusEnum().getValue());\n            ecmTaskDetail.setHostname(status.getHostname());\n            ecmTaskDetail.setRole(ecmParamBase.getRoleName());\n            ecmTaskDetail.setGrp(status.getGroup());\n            ecmTaskDetail.setIdx(status.getPodIndex());\n            ecmTaskDetail.setTaskId(status.getTaskId().longValue());\n        } else if (EDIT.getCode() == operation.getCode()) {\n            ecmTaskDetail.setId(detailId);\n            ecmTaskDetail.setStatus(status.getStatusEnum().getValue());\n            ecmTaskDetail.setGrp(status.getGroup());\n            ecmTaskDetail.setIdx(status.getPodIndex());\n        }\n        return ecmTaskDetail;\n    }\n\n    private boolean hasCallBackAddress(EcmTaskStatusEnum mergedStatusEnum, EcmTask ecmTask) {\n        return SUCCESS.getValue().equals(mergedStatusEnum.getValue())\n               && (Objects.equals(OpTaskTypeEnum.CLUSTER_NEW.getType(), ecmTask.getOrderType())\n                   || Objects.equals(OpTaskTypeEnum.CLUSTER_EXPAND.getType(), ecmTask.getOrderType())\n                   || Objects.equals(OpTaskTypeEnum.CLUSTER_SHRINK.getType(), ecmTask.getOrderType())\n                   || Objects.equals(OpTaskTypeEnum.CLUSTER_RESTART.getType(), ecmTask.getOrderType()));\n    }\n\n    private void updateRoleClusterNumber(EcmTask ecmTask, EcmParamBase ecmParamBase) {\n        if (hasCallBackRoleNumber(ecmTask)) {\n            ClusterRoleInfo clusterRoleInfo = ConvertUtil.obj2Obj(ecmParamBase, ClusterRoleInfo.class);\n            clusterRoleInfo.setElasticClusterId(ecmParamBase.getPhyClusterId());\n            clusterRoleInfo.setPodNumber(ecmParamBase.getNodeNumber());\n            clusterRoleInfo.setRole(ecmParamBase.getRoleName());\n            Result<Void> updateResult = clusterRoleService.updatePodByClusterIdAndRole(clusterRoleInfo);\n            if (updateResult.failed()) {\n                LOGGER.error(\"class=EcmTaskManagerImpl||method=updateRoleClusterNumber||clusterId={}\"\n                             + \"||msg=failed to update es role number\",\n                    ecmTask.getPhysicClusterId());\n            }\n        }\n    }\n\n    private boolean hasCallBackRoleNumber(EcmTask ecmTask) {\n        return Objects.equals(OpTaskTypeEnum.CLUSTER_EXPAND.getType(), ecmTask.getOrderType())\n               || Objects.equals(OpTaskTypeEnum.CLUSTER_SHRINK.getType(), ecmTask.getOrderType());\n    }\n\n    private EcmTaskStatusEnum convertStatus(EcmHostStatusEnum ecmHostStatusEnum) {\n        if (EcmHostStatusEnum.SUCCESS.equals(ecmHostStatusEnum)) {\n            return EcmTaskStatusEnum.SUCCESS;\n        }\n        if (EcmHostStatusEnum.UPDATED.equals(ecmHostStatusEnum)) {\n            return EcmTaskStatusEnum.SUCCESS;\n        }\n        if (EcmHostStatusEnum.KILL_FAILED.equals(ecmHostStatusEnum)\n            || EcmHostStatusEnum.TIMEOUT.equals(ecmHostStatusEnum)\n            || EcmHostStatusEnum.FAILED.equals(ecmHostStatusEnum)) {\n            return EcmTaskStatusEnum.FAILED;\n        }\n        if (EcmHostStatusEnum.KILLING.equals(ecmHostStatusEnum)\n            || EcmHostStatusEnum.RUNNING.equals(ecmHostStatusEnum)) {\n            return EcmTaskStatusEnum.RUNNING;\n        }\n        if (EcmHostStatusEnum.WAITING.equals(ecmHostStatusEnum)) {\n            return EcmTaskStatusEnum.WAITING;\n        }\n        if (EcmHostStatusEnum.READY.equals(ecmHostStatusEnum)) {\n            return EcmTaskStatusEnum.PAUSE;\n        }\n        if (EcmHostStatusEnum.IGNORE.equals(ecmHostStatusEnum)) {\n            return EcmTaskStatusEnum.IGNORE;\n        }\n        if (EcmHostStatusEnum.CANCELLED.equals(ecmHostStatusEnum)) {\n            return EcmTaskStatusEnum.CANCEL;\n        }\n        return EcmTaskStatusEnum.UNKNOWN;\n    }\n\n    private boolean checkEcmTaskStatusValid(List<EcmTaskStatus> ecmTaskStatuses) {\n        for (EcmTaskStatus status : ecmTaskStatuses) {\n            if (AriusObjUtils.isBlack(status.getPodIp()) && AriusObjUtils.isBlack(status.getHostname())) {\n                return Boolean.FALSE;\n            }\n        }\n\n        return Boolean.TRUE;\n    }\n\n    private void saveTaskDetailInfoWithoutZeusTaskId(EcmParamBase ecmParamBase, Long taskId,\n                                                     EcmTaskStatusEnum taskStatusEnum) {\n        HostParamBase hostParamBase = (HostParamBase) ecmParamBase;\n        for (String hostname : hostParamBase.getHostList()) {\n            EcmTaskDetail ecmTaskDetail = new EcmTaskDetail();\n            ecmTaskDetail.setWorkOrderTaskId(taskId);\n            ecmTaskDetail.setStatus(taskStatusEnum.getValue());\n            ecmTaskDetail.setHostname(hostname);\n            ecmTaskDetail.setRole(ecmParamBase.getRoleName());\n            ecmTaskDetail.setGrp(0);\n            ecmTaskDetail.setIdx(0);\n            ecmTaskDetail.setTaskId(0L);\n            ecmTaskDetailManager.saveEcmTaskDetail(ecmTaskDetail);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/handler/AbstractOpTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.WorkOrderManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESClusterConfigService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPluginService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport java.util.Date;\nimport org.springframework.beans.factory.annotation.Autowired;\n\npublic abstract class AbstractOpTaskHandler implements OpTaskHandler {\n\n    protected final ILog             LOGGER = LogFactory.getLog(this.getClass());\n\n    @Autowired\n    protected EcmTaskManager         ecmTaskManager;\n\n    @Autowired\n    protected OpTaskManager          opTaskManager;\n\n    @Autowired\n    protected ESClusterService       esClusterService;\n\n    @Autowired\n    protected ESClusterConfigService esClusterConfigService;\n\n    @Autowired\n    protected WorkOrderManager       workOrderManager;\n\n    @Autowired\n    protected ESPluginService        esPluginService;\n\n    @Autowired\n    protected ClusterPhyService      clusterPhyService;\n    @Autowired\n    protected ProjectService         projectService;\n    @Autowired\n    protected OperateRecordService   operateRecordService;\n\n    @Override\n    public Result<OpTask> addTask(OpTask opTask) throws NotFindSubclassException {\n        if (AriusObjUtils.isNull(opTask.getExpandData())) {\n            return Result.buildParamIllegal(\"提交内容为空\");\n        }\n\n        EcmTaskDTO ecmTaskDTO = ConvertUtil.str2ObjByJson(opTask.getExpandData(), EcmTaskDTO.class);\n        Result<Long> ret = ecmTaskManager.saveEcmTask(ecmTaskDTO);\n        if (ret.failed()) {\n            return Result.buildFrom(ret);\n        }\n\n        opTask.setBusinessKey(String.valueOf(ret.getData()));\n        opTask.setTitle(ecmTaskDTO.getTitle());\n        opTask.setCreateTime(new Date());\n        opTask.setUpdateTime(new Date());\n        opTask.setStatus(OpTaskStatusEnum.WAITING.getStatus());\n        opTask.setDeleteFlag(false);\n        opTaskManager.insert(opTask);\n\n        return Result.buildSucc(opTask);\n    }\n\n    @Override\n    public boolean existUnClosedTask(String key, Integer type) {\n        return ecmTaskManager.existUnClosedEcmTask(Long.valueOf(key));\n    }\n\n    @Override\n    public Result<Void> process(OpTask opTask, Integer step, String status, String expandData) {\n        if (AriusObjUtils.isNull(opTask.getExpandData())) {\n            return Result.buildParamIllegal(\"提交内容为空\");\n        }\n\n        EcmTaskPO ecmTaskPO = JSON.parseObject(opTask.getExpandData(), EcmTaskPO.class);\n\n        opTask.setStatus(status);\n        opTask.setUpdateTime(new Date());\n        opTask.setExpandData(JSON.toJSONString(ecmTaskPO));\n        opTaskManager.updateTask(opTask);\n\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/handler/DCDROpTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.detail.DCDRTaskDetail;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskDCDRProgressEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\n@Service(\"dcdrOpTaskHandler\")\npublic class DCDROpTaskHandler extends AbstractOpTaskHandler {\n    @Override\n    public Result<OpTask> addTask(OpTask opTask) {\n        if (AriusObjUtils.isNull(opTask.getBusinessKey())) {\n            return Result.buildParamIllegal(\"业务id为空\");\n        }\n        if (existUnClosedTask(opTask.getBusinessKey(), opTask.getTaskType())) {\n            return Result\n                .buildParamIllegal(String.format(\"模版列表[%s]存在未完成的dcdr模板主从切换任务，不允许再次创建\", opTask.getBusinessKey()));\n        }\n\n        opTask.setCreateTime(new Date());\n        opTask.setUpdateTime(new Date());\n        opTaskManager.insert(opTask);\n        boolean succ = Objects.nonNull(opTask.getId());\n        if (!succ) {\n            LOGGER.error(\n                \"class=DCDRWorkTaskHandler||method=addTask||taskType={}||businessKey={}||errMsg=failed to insert\",\n                opTask.getTaskType(), opTask.getBusinessKey());\n            return Result.buildFail();\n        }\n        return Result.buildSucc(opTask);\n    }\n\n    @Override\n    public boolean existUnClosedTask(String key, Integer type) {\n        List<OpTask> pengingTaskList = opTaskManager.getPendingTaskByType(type);\n        if (CollectionUtils.isEmpty(pengingTaskList)) {\n            return false;\n        }\n\n        List<String> businessKeyList = pengingTaskList.stream().map(OpTask::getBusinessKey)\n            .collect(Collectors.toList());\n\n        List<String> templateIdListToCreate = ListUtils.string2StrList(key);\n        for (String businessKey : businessKeyList) {\n            List<String> templateIdListFromDB = ListUtils.string2StrList(businessKey);\n            for (String templateIdFromDB : templateIdListFromDB) {\n                if (templateIdListToCreate.contains(templateIdFromDB)) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public Result<Void> process(OpTask opTask, Integer step, String status, String expandData) {\n        Result<OpTask> result = opTaskManager.getById(opTask.getId());\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n        OpTask updateOpTask = result.getData();\n        DCDRTaskDetail detail = JSON.parseObject(updateOpTask.getExpandData(), DCDRTaskDetail.class);\n        detail.setStatus(status);\n        detail.setTaskProgress(step);\n        updateOpTask.setExpandData(JSON.toJSONString(detail));\n        if (OpTaskStatusEnum.FAILED.getStatus().equals(status)\n            || step.equals(OpTaskDCDRProgressEnum.STEP_9.getProgress())) {\n            updateOpTask.setStatus(status);\n        }\n\n        opTaskManager.updateTask(updateOpTask);\n\n        return Result.buildSucc();\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/handler/ECMOpTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.handler;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport lombok.SneakyThrows;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Service;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.PhyClusterPluginOperationContent;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.utils.OpOrderTaskConverter;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EsConfigAction;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud.ElasticCloudCommonActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskProcessDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.esconfig.ESConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.ecm.EcmTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.detail.OrderDetailBaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmTaskStatusEnum;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.OperationTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.ecm.EcmTaskEditEvent;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.google.common.collect.Lists;\n\n/**\n * ecm工作任务处理程序\n *\n * @author\n * @date 2022/05/09\n */\n@Service(\"ecmOpTaskHandler\")\npublic class ECMOpTaskHandler extends AbstractOpTaskHandler implements ApplicationListener<EcmTaskEditEvent> {\n    @SneakyThrows\n    @Override\n    public void onApplicationEvent(EcmTaskEditEvent event) {\n        EcmTask ecmTask = event.getEditTask();\n\n        if (null == ecmTask) {\n            return;\n        }\n\n        handlerRestartPostConfig(ecmTask);\n        handlerRestartPostPlugin(ecmTask);\n\n        Result<OpTask> result = opTaskManager.getLatestTask(String.valueOf(ecmTask.getId()), ecmTask.getOrderType());\n        if (result.failed()) {\n            return;\n        }\n        OpTaskProcessDTO processDTO = new OpTaskProcessDTO();\n        processDTO.setStatus(ecmTask.getStatus());\n        processDTO.setTaskId(result.getData().getId());\n        processDTO.setExpandData(JSON.toJSONString(ecmTask));\n        opTaskManager.processTask(processDTO);\n\n        LOGGER.info(\"class=ECMWorkTaskHandler||method=onApplicationEvent||ecmTaskId={}||event=EcmEditTaskEvent\",\n            ecmTask.getId());\n    }\n\n    /**************************************** private methods ****************************************/\n    /**\n     * Ecm重启操作后处理Es集群配置相关信息\n     * @param ecmTask\n     */\n    private void handlerRestartPostConfig(EcmTask ecmTask) {\n        //1.判断是不是重启类型的工单\n        if (!Objects.equals(OpTaskTypeEnum.CLUSTER_RESTART.getType(), ecmTask.getOrderType())) {\n            return;\n        }\n        //2.判断重启类型是否成功\n        if (!EcmTaskStatusEnum.SUCCESS.getValue().equals(ecmTask.getStatus())) {\n            return;\n        }\n\n        //3.判断是不是配置重启类型的工单, configIds为空则为非配置重启\n        List<Long> actionEsConfigIds = Lists.newArrayList();\n        Integer actionType = Integer.MIN_VALUE;\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask);\n\n        if (ESClusterTypeEnum.ES_HOST.getCode() == ecmTask.getType()) {\n            List<HostParamBase> hostParamBases = ConvertUtil.list2List(ecmParamBaseList, HostParamBase.class);\n            for (HostParamBase hostParamBase : hostParamBases) {\n                if (null == hostParamBase.getEsConfigAction()) {\n                    return;\n                }\n            }\n            actionType = hostParamBases.stream().map(HostParamBase::getEsConfigAction)\n                .map(EsConfigAction::getActionType).findAny().orElse(null);\n\n            hostParamBases.stream()\n                .filter(r -> !AriusObjUtils.isNull(r) && !AriusObjUtils.isNull(r.getEsConfigAction())\n                             && CollectionUtils.isNotEmpty(r.getEsConfigAction().getActionEsConfigIds()))\n                .forEach(param -> actionEsConfigIds.addAll(param.getEsConfigAction().getActionEsConfigIds()));\n\n        } else if (ESClusterTypeEnum.ES_DOCKER.getCode() == ecmTask.getType()) {\n            List<ElasticCloudCommonActionParam> cloudCommonActionParams = ConvertUtil.list2List(ecmParamBaseList,\n                ElasticCloudCommonActionParam.class);\n            actionType = cloudCommonActionParams.stream().map(ElasticCloudCommonActionParam::getEsConfigActions)\n                .map(EsConfigAction::getActionType).findAny().orElse(null);\n\n            cloudCommonActionParams.stream()\n                .filter(r -> !AriusObjUtils.isNull(r) && !AriusObjUtils.isNull(r.getEsConfigActions())\n                             && CollectionUtils.isNotEmpty(r.getEsConfigActions().getActionEsConfigIds()))\n                .forEach(param -> actionEsConfigIds.addAll(param.getEsConfigActions().getActionEsConfigIds()));\n        } else {\n            LOGGER.error(\n                \"class=ECMWorkTaskHandler||method=handlerRestartConfig||ecmTaskId={}||msg=Type does not exist, require docker or host\",\n                ecmTask.getId());\n        }\n\n        if (CollectionUtils.isEmpty(actionEsConfigIds)) {\n            return;\n        }\n\n        try {\n            //4.任务成功进行配置回写处理\n            handleSuccessEcmConfigRestartTask(actionType, actionEsConfigIds, ecmTask);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ECMWorkTaskHandler||method=handlerRestartConfig||ecmTaskId={}||msg={}\", ecmTask.getId(),\n                e.getStackTrace());\n        }\n\n    }\n\n    private void handleSuccessEcmConfigRestartTask(Integer actionType, List<Long> actionEsConfigIds, EcmTask ecmTask) {\n        for (Long actionEsConfigId : actionEsConfigIds) {\n            ESConfig esConfig = esClusterConfigService.getEsConfigById(actionEsConfigId);\n            if (AriusObjUtils.isNull(esConfig)) {\n                LOGGER.error(\n                    \"class=ECMWorkTaskHandler||method=handlerRestartConfig||ecmTaskId={}||clusterId={}||msg=es config does not exist\",\n                    ecmTask.getId(), ecmTask.getPhysicClusterId());\n                return;\n            }\n            //删除操作, 删除当前集群角色配置类型下的所有信息\n            if (EsConfigActionEnum.DELETE.getCode() == actionType) {\n                ESConfig esConfigById = esClusterConfigService.getEsConfigById(actionEsConfigId);\n                Result<Void> result = esClusterConfigService.deleteByClusterIdAndTypeAndEngin(\n                    esConfigById.getClusterId(), esConfigById.getTypeName(), esConfigById.getEnginName());\n                if (result.failed()) {\n                    LOGGER.error(\n                        \"class=ECMWorkTaskHandler||method=handlerRestartConfig||ecmTaskId={}||clusterId={}||msg=fail to set new config valid\",\n                        ecmTask.getId(), ecmTask.getPhysicClusterId());\n                }\n                return;\n            }\n\n            //编辑操作, 设置当前版本为有效, 原版本为无效\n            Result<Void> result = esClusterConfigService.setConfigValid(actionEsConfigId);\n            if (result.failed()) {\n                LOGGER.error(\n                    \"class=ECMWorkTaskHandler||method=handlerRestartConfig||ecmTaskId={}||clusterId={}||msg=fail to set edit config valid\",\n                    ecmTask.getId(), ecmTask.getPhysicClusterId());\n            }\n\n            if (EsConfigActionEnum.EDIT.getCode() == actionType) {\n                esClusterConfigService.setOldConfigInvalid(esConfig);\n            }\n        }\n    }\n\n    /**\n     * Ecm重启操作后处理Es集群插件相关信息\n     * @param ecmTask 任务\n     */\n    private void handlerRestartPostPlugin(EcmTask ecmTask) {\n        // 1.判断是不是重启类型的工单\n        if (!Objects.equals(OpTaskTypeEnum.CLUSTER_RESTART.getType(), ecmTask.getOrderType())) {\n            return;\n        }\n        // 2.判断重启类型是否成功\n        if (!EcmTaskStatusEnum.SUCCESS.getValue().equals(ecmTask.getStatus())) {\n            return;\n        }\n\n        // 3.判断当前重启操作是否是插件安装或者卸载\n        List<EcmParamBase> ecmParamBases = OpOrderTaskConverter.convert2EcmParamBaseList(ecmTask);\n        if (CollectionUtils.isEmpty(ecmParamBases)) {\n            return;\n        }\n        HostParamBase hostParamBase = (HostParamBase) ecmParamBases.get(0);\n        if (AriusObjUtils.isNull(hostParamBase.getEsPluginAction())) {\n            return;\n        }\n\n        try {\n            // 4.任务成功进行插件回写处理\n            handleSuccessEcmPluginRestartTask(ecmTask);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ECMWorkTaskHandler||method=handlerRestartPlugin||ecmTaskId={}||msg={}\", ecmTask.getId(),\n                e.getStackTrace());\n        }\n    }\n\n    /**\n     * 当因插件操作任务而重启集群成功后，进行一些插件信息的回写\n     *\n     * @param ecmTask 任务\n     */\n    private void handleSuccessEcmPluginRestartTask(EcmTask ecmTask) throws ESOperateException {\n        OrderDetailBaseVO orderDetailBaseVO = workOrderManager.getById(ecmTask.getWorkOrderId()).getData();\n        PhyClusterPluginOperationContent content = JSON.parseObject(orderDetailBaseVO.getDetail(),\n            PhyClusterPluginOperationContent.class);\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(ecmTask.getPhysicClusterId().intValue());\n        List<Long> plugIdList = ListUtils.string2LongList(clusterPhy.getPlugIds());\n\n        String cluster = clusterPhyService.getClusterById(ecmTask.getPhysicClusterId().intValue()).getCluster();\n        Map</*节点名称*/String, /*插件名称列表*/List<String>> node2PluginMap = esClusterService.syncGetNode2PluginsMap(cluster);\n        if (null == node2PluginMap) {\n            LOGGER.warn(\n                \"class=ECMWorkTaskHandler||method=handleSuccessEcmPluginRestartTask||cluster={}||errMsg={node2PluginMap is null}\",\n                cluster);\n            return;\n        }\n        String pluginName = esPluginService.getESPluginById(content.getPluginId()).getName();\n\n        // 记录插件安装或者卸载失败的集群节点名称\n        List<String> failPluginOperationNodeNames = Lists.newArrayList();\n        if (OperationTypeEnum.INSTALL.getCode().equals(content.getOperationType())) {\n            for (Map.Entry<String, List<String>> entry : node2PluginMap.entrySet()) {\n                if (!entry.getValue().contains(pluginName)) {\n                    failPluginOperationNodeNames.add(entry.getKey());\n                }\n            }\n\n            if (!failPluginOperationNodeNames.isEmpty()) {\n                LOGGER.warn(\"class=ECMWorkTaskHandler||method=handleSuccessEcmPluginRestartTask||msg=节点列表{}插件{}安装失败\",\n                    failPluginOperationNodeNames, pluginName);\n                ecmTask.setStatus(EcmTaskStatusEnum.FAILED.getValue());\n                return;\n            }\n\n            // 将插件信息同步到物理集群中\n            plugIdList.add(content.getPluginId());\n        } else if (OperationTypeEnum.UNINSTALL.getCode().equals(content.getOperationType())) {\n            for (Map.Entry<String, List<String>> entry : node2PluginMap.entrySet()) {\n                if (entry.getValue().contains(pluginName)) {\n                    failPluginOperationNodeNames.add(entry.getKey());\n                }\n            }\n\n            if (!failPluginOperationNodeNames.isEmpty()) {\n                LOGGER.warn(\"class=ECMWorkTaskHandler||method=handleSuccessEcmPluginRestartTask||msg=节点列表{}插件{}卸载失败\",\n                    failPluginOperationNodeNames, pluginName);\n                ecmTask.setStatus(EcmTaskStatusEnum.FAILED.getValue());\n                return;\n            }\n\n            // 将插件信息同步到物理集群中\n            plugIdList.remove(content.getPluginId());\n        }\n        clusterPhyService.updatePluginIdsById(\n            ListUtils.longList2String(plugIdList.stream().distinct().collect(Collectors.toList())), clusterPhy.getId());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/handler/cluster/AbstractClusterTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.handler.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.*;\n\nimport java.util.Optional;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterBaseContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.handler.AbstractOpTaskHandler;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPackageService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.EcmHandleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\n\n/**\n * 集群处理器\n * 统一集群任务处理流程\n *\n * @author ohushenglin_v\n * @date 2022-05-20\n */\npublic abstract class AbstractClusterTaskHandler extends AbstractOpTaskHandler {\n    public static final Result<Void> CLUSTER_TYPE_NOT_SUPPORT = Result.buildFail(\"集群类型暂时不支持！\");\n    @Autowired\n    protected ESPackageService       esPackageService;\n    @Autowired\n    protected EcmHandleService       ecmHandleService;\n    @Autowired\n    protected ClusterRoleHostService clusterRoleHostService;\n\n    /**\n     * 统一处理集群任务\n     *\n     * @param opTask op任务\n     * @return {@link Result}<{@link OpTask}>\n     */\n    @Override\n    public Result<OpTask> addTask(OpTask opTask) throws NotFindSubclassException {\n        Result<Void> initResult = initParam(opTask);\n        if (initResult.failed()) {\n            return Result.buildFail(initResult.getMessage());\n        }\n        Result<Void> validateResult = validateParam(opTask.getExpandData());\n        if (validateResult.failed()) {\n            return Result.buildFail(validateResult.getMessage());\n        }\n        Result<OpTask> buildResult = buildOpTask(opTask);\n        if (buildResult.failed()) {\n            return Result.buildFail(buildResult.getMessage());\n        }\n        return super.addTask(buildResult.getData());\n\n    }\n\n    /**\n     * 初始化参数\n     *\n     * @param opTask op任务\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> initParam(OpTask opTask) {\n        //这里目前默认为Host，后续如果支持了其他的类型，修改默认为unknown\n        ESClusterTypeEnum type = Optional.ofNullable(opTask).map(OpTask::getExpandData).map(JSON::parseObject)\n            .map(jsonObject -> jsonObject.getInteger(\"type\")).map(ESClusterTypeEnum::valueOf).orElse(ES_HOST);\n\n        Result<Void> initResult = Result.buildSucc();\n        if (ES_HOST == type) {\n            Optional.ofNullable(opTask).map(OpTask::getExpandData).map(JSON::parseObject).ifPresent(jsonObject -> {\n                jsonObject.put(\"type\", ES_HOST.getCode());\n                opTask.setExpandData(jsonObject.toJSONString());\n            });\n            initResult = initHostParam(opTask);\n        } else if (ES_DOCKER == type) {\n            Optional.ofNullable(opTask).map(OpTask::getExpandData).map(JSON::parseObject).ifPresent(jsonObject -> {\n                jsonObject.put(\"type\", ES_DOCKER.getCode());\n                opTask.setExpandData(jsonObject.toJSONString());\n            });\n\n            initResult = initDockerParam(opTask);\n        }\n        return initResult;\n    }\n\n    /**\n     * 验证集群任务参数\n     *\n     * @param param 参数\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> validateParam(String param) throws NotFindSubclassException {\n        ESClusterTypeEnum type = Optional.ofNullable(param).map(JSON::parseObject)\n            .map(jsonObject -> jsonObject.getInteger(\"type\")).map(ESClusterTypeEnum::valueOf).orElse(UNKNOWN);\n\n        if (ES_HOST == type) {\n            return validateHostParam(param);\n        } else {\n            return CLUSTER_TYPE_NOT_SUPPORT;\n        }\n    }\n\n    /**\n     * 构建op任务参数\n     *\n     * @param opTask op任务\n     * @return {@link Result}<{@link OpTask}>\n     */\n    Result<OpTask> buildOpTask(OpTask opTask) {\n        ClusterBaseContent content = ConvertUtil.str2ObjByJson(opTask.getExpandData(), ClusterBaseContent.class);\n        EcmTaskDTO ecmTaskDTO = new EcmTaskDTO();\n        ecmTaskDTO\n            .setTitle(content.getPhyClusterName() + OpTaskTypeEnum.valueOfType(opTask.getTaskType()).getMessage());\n        ecmTaskDTO.setCreator(opTask.getCreator());\n        ecmTaskDTO.setType(content.getType());\n        ecmTaskDTO.setPhysicClusterId(ClusterConstant.INVALID_VALUE);\n\n        Result<Void> result = CLUSTER_TYPE_NOT_SUPPORT;\n        if (ES_DOCKER.getCode() == content.getType()) {\n            result = buildDockerEcmTaskDTO(ecmTaskDTO, opTask.getExpandData(), opTask.getCreator());\n        } else if (ES_HOST.getCode() == content.getType()) {\n            result = buildHostEcmTaskDTO(ecmTaskDTO, opTask.getExpandData(), opTask.getCreator());\n        }\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        opTask.setExpandData(JSON.toJSONString(ecmTaskDTO));\n        opTask.setTaskType(opTask.getTaskType());\n        return Result.buildSucc(opTask);\n    }\n\n    /**\n     * 初始化 ESHost集群任务参数\n     *\n     * @param opTask op任务\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> initHostParam(OpTask opTask) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 初始化 ESDocker集群任务参数\n     *\n     * @param opTask op任务\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> initDockerParam(OpTask opTask) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证 ESHost 集群任务参数\n     *\n     * @param param 参数\n     * @return {@link Result}<{@link Void}>\n     */\n    abstract Result<Void> validateHostParam(String param) throws NotFindSubclassException;\n\n    /**\n     * 构建ESHost的ecm任务信息\n     *\n     * @param ecmTaskDTO    ecm任务dto\n     * @param param    任务参数\n     * @param creator       任务创建人\n     * @return {@link Result}<{@link Void}>\n     */\n    abstract Result<Void> buildHostEcmTaskDTO(EcmTaskDTO ecmTaskDTO, String param, String creator);\n\n    /**\n     * 构建ESDocker的ecm任务信息\n     *\n     * @param ecmTaskDTO    ecm任务dto\n     * @param param    任务参数\n     * @param creator       任务创建人\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> buildDockerEcmTaskDTO(EcmTaskDTO ecmTaskDTO, String param, String creator) {\n        return Result.buildSucc();\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/handler/cluster/ClusterConfigRestartTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.handler.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum.ADD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum.DELETE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum.EDIT;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_DOCKER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_HOST;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterBaseContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterConfigRestartContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.esconfig.ESConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.operaterecord.template.ESConfigOperateRecode;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.google.common.collect.ArrayListMultimap;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Multimap;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Service(\"clusterConfigRestartTaskHandler\")\npublic class ClusterConfigRestartTaskHandler extends AbstractClusterTaskHandler {\n\n    @Override\n    Result<Void> validateHostParam(String param) throws NotFindSubclassException {\n        ClusterConfigRestartContent content = ConvertUtil.str2ObjByJson(param, ClusterConfigRestartContent.class);\n\n        if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n            return Result.buildParamIllegal(\"物理集群id为空\");\n        }\n\n        if (StringUtils.isBlank(content.getRoleOrder())) {\n            return Result.buildParamIllegal(\"物理集群重启角色顺序为空\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildParamIllegal(\"物理集群不存在\");\n        }\n\n        if (AriusObjUtils.isNull(content.getActionType())) {\n            return Result.buildParamIllegal(\"配置操作不存在\");\n        }\n\n        if (ADD.getCode() == content.getActionType() && CollectionUtils.isEmpty(content.getNewEsConfigs())) {\n            return Result.buildParamIllegal(\"新增配置为空\");\n        }\n\n        if (EsConfigActionEnum.EDIT.getCode() == content.getActionType()\n            && CollectionUtils.isEmpty(content.getOriginalConfigs())) {\n            return Result.buildParamIllegal(\"原始配置为空\");\n        }\n\n        if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n            OpTaskTypeEnum.CLUSTER_RESTART.getType())) {\n            return Result.buildParamIllegal(\"该集群上存在未完成的集群重启任务\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<OpTask> buildOpTask(OpTask opTask) {\n        ClusterBaseContent content = ConvertUtil.str2ObjByJson(opTask.getExpandData(), ClusterBaseContent.class);\n        EcmTaskDTO ecmTaskDTO = new EcmTaskDTO();\n        ecmTaskDTO\n            .setTitle(content.getPhyClusterName() + OpTaskTypeEnum.valueOfType(opTask.getTaskType()).getMessage());\n        ecmTaskDTO.setCreator(opTask.getCreator());\n        ecmTaskDTO.setType(content.getType());\n        ecmTaskDTO.setPhysicClusterId(ClusterConstant.INVALID_VALUE);\n\n        Result<Void> result = CLUSTER_TYPE_NOT_SUPPORT;\n        if (ES_DOCKER.getCode() == content.getType()) {\n            result = buildDockerEcmTaskDTO(ecmTaskDTO, opTask.getExpandData(), opTask.getCreator());\n        } else if (ES_HOST.getCode() == content.getType()) {\n            result = buildHostEcmTaskDTO(ecmTaskDTO, opTask.getExpandData(), opTask.getCreator());\n        }\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        opTask.setExpandData(JSON.toJSONString(ecmTaskDTO));\n        //这里由于历史原因，需要将配置变更的taskType设置为 CLUSTER_RESTART\n        opTask.setTaskType(OpTaskTypeEnum.CLUSTER_RESTART.getType());\n        return Result.buildSucc(opTask);\n    }\n\n    @Override\n    Result<Void> buildHostEcmTaskDTO(EcmTaskDTO ecmTaskDTO, String param, String creator) {\n        ClusterConfigRestartContent content = ConvertUtil.str2ObjByJson(param, ClusterConfigRestartContent.class);\n\n        ecmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n        ecmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_RESTART.getType());\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        ecmTaskDTO.setType(clusterPhy.getType());\n\n        List<String> roleNameList = Lists.newArrayList();\n        for (String roleClusterName : JSON.parseArray(content.getRoleOrder(), String.class)) {\n            String roleName = roleClusterName.replaceFirst(clusterPhy.getCluster() + \"-\", \"\");\n            roleNameList.add(roleName);\n        }\n\n        Multimap<String, Long> role2ConfigIdsMultiMap = saveEsConfigs(content, creator,\n            ecmTaskDTO.getPhysicClusterId());\n        Result<List<EcmParamBase>> buildEcmParamBasesResult = ecmHandleService.buildEcmParamBaseListWithConfigAction(\n            clusterPhy.getId(), roleNameList, role2ConfigIdsMultiMap, content.getActionType());\n\n        if (buildEcmParamBasesResult.failed()) {\n            return Result.buildFail(buildEcmParamBasesResult.getMessage());\n        }\n        ecmTaskDTO.setEcmParamBaseList(buildEcmParamBasesResult.getData());\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 保存并得到es配置id\n     *\n     * @param content         内容\n     * @param approver        审批人\n     * @param physicClusterId\n     * @return {@link Multimap}<{@link String}, {@link Long}>  Multimap<集群角色, 改动的配置id>\n     */\n    private Multimap<String, Long> saveEsConfigs(ClusterConfigRestartContent content, String approver,\n                                                 Long physicClusterId) {\n\n        final List<ESConfigOperateRecode> operateRecodeList = content.getNewEsConfigs().stream()\n            .filter(Objects::nonNull)\n            .map(esConfig -> ESConfigOperateRecode.sourceAndTargetConfigFunc.apply(esConfig,\n                esClusterConfigService::getEsClusterConfigById))\n            .map(tupleTwo -> ESConfigOperateRecode.sourceTargetDiff(tupleTwo, content.getActionType()))\n            .collect(Collectors.toList());\n        Multimap<String, Long> role2ConfigIdsMultiMap = ArrayListMultimap.create();\n        if (ADD.getCode() == content.getActionType()) {\n            List<ESConfigDTO> newEsConfigs = ConvertUtil.list2List(content.getNewEsConfigs(), ESConfigDTO.class);\n            newEsConfigs.stream().filter(Objects::nonNull).forEach(config -> {\n                Result<Long> result = esClusterConfigService.esClusterConfigAction(config, ADD, approver);\n                if (result.failed()) {\n                    LOGGER.error(\"class=ClusterConfigAddRestartTaskHandler||method=saveAndGetEsConfigIds||msg=\"\n                                 + \"failed to add es config\");\n                }\n                config.setId(result.getData());\n            });\n\n            role2ConfigIdsMultiMap = ConvertUtil.list2MulMap(newEsConfigs, ESConfigDTO::getEnginName,\n                ESConfigDTO::getId);\n        } else if (EDIT.getCode() == content.getActionType()) {\n            List<ESConfigDTO> editConfigs = ConvertUtil.list2List(content.getNewEsConfigs(), ESConfigDTO.class);\n            editConfigs.stream().filter(Objects::nonNull).forEach(config -> {\n                Result<Long> result = esClusterConfigService.esClusterConfigAction(config, EDIT, approver);\n                if (result.failed()) {\n                    LOGGER.error(\"class=ClusterConfigAddRestartTaskHandler||method=saveAndGetEsConfigIds||msg=\"\n                                 + \"failed to edit es config\");\n                    return;\n                }\n                config.setId(result.getData());\n            });\n\n            role2ConfigIdsMultiMap = ConvertUtil.list2MulMap(editConfigs, ESConfigDTO::getEnginName,\n                ESConfigDTO::getId);\n        } else if (DELETE.getCode() == content.getActionType()) {\n            role2ConfigIdsMultiMap = ConvertUtil.list2MulMap(content.getOriginalConfigs(), ESConfig::getEnginName,\n                ESConfig::getId);\n        }\n        //配置变更 保存到操作记录\n        for (ESConfigOperateRecode esConfigOperateRecode : operateRecodeList) {\n            final OperateRecord operateRecord = ESConfigOperateRecode.buildESConfigOperateRecode(approver,\n                projectService::getProjectBriefByProjectId, AuthConstant.SUPER_PROJECT_ID, esConfigOperateRecode,\n                physicClusterId);\n            operateRecordService.save(operateRecord);\n        }\n\n        return role2ConfigIdsMultiMap;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/handler/cluster/ClusterCreateTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.handler.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.CREATE_MASTER_NODE_MIN_NUMBER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.MASTER_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_HOST;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterNewDockerContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterNewHostContent;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.utils.OpOrderTaskConverter;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord.Builder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.google.common.collect.Maps;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-20\n */\n@Service(\"clusterCreateTaskHandler\")\npublic class ClusterCreateTaskHandler extends AbstractClusterTaskHandler {\n\n    private static final String PARAM_ILLEGAL_TIPS = \"集群缺少类型为%s的节点\";\n\n    @Override\n    Result<Void> initHostParam(OpTask opTask) {\n        ClusterNewHostContent clusterOpNewHostContent = ConvertUtil.str2ObjByJson(opTask.getExpandData(),\n            ClusterNewHostContent.class);\n        // 校验pid_count（单节点实例数字段）,如果为null，则设置默认值1\n        if (null == clusterOpNewHostContent.getPidCount()) {\n            clusterOpNewHostContent.setPidCount(ClusterConstant.DEFAULT_CLUSTER_PAID_COUNT);\n        }\n        if (StringUtils.isBlank(clusterOpNewHostContent.getCreator())) {\n            clusterOpNewHostContent.setCreator(opTask.getCreator());\n        }\n        // 对于address字段进行ip和端口号的拆分\n        List<ESClusterRoleHost> roleClusterHosts = clusterOpNewHostContent.getClusterRoleHosts();\n        for (ESClusterRoleHost esClusterRoleHost : roleClusterHosts) {\n            if (null == esClusterRoleHost.getAddress()) {\n                return Result.buildFail(\"传入节点的address不应该为空\");\n            }\n            // 将ip和port中hostname中拆分出来\n            String[] ipAndPort = esClusterRoleHost.getAddress().split(\":\");\n            if (ipAndPort.length < 2) {\n                return Result.buildFail(\"传入节点的address应该满足【ip:port】格式\");\n            }\n            esClusterRoleHost.setHostname(ipAndPort[0]);\n            esClusterRoleHost.setIp(ipAndPort[0]);\n            esClusterRoleHost.setPort(ipAndPort[1]);\n        }\n        opTask.setExpandData(JSON.toJSONString(clusterOpNewHostContent));\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> validateHostParam(String param) {\n        ClusterNewHostContent clusterOpNewHostContent = ConvertUtil.str2ObjByJson(param, ClusterNewHostContent.class);\n        if (AriusObjUtils.isNull(clusterOpNewHostContent.getPhyClusterName())) {\n            return Result.buildParamIllegal(\"物理集群名称为空\");\n        }\n\n        if (clusterPhyService.isClusterExists(clusterOpNewHostContent.getPhyClusterName())) {\n            return Result.buildParamIllegal(\"物理集群名称不能重复\");\n        }\n        List<ESClusterRoleHost> roleClusterHosts = clusterOpNewHostContent.getClusterRoleHosts();\n        if (CollectionUtils.isEmpty(roleClusterHosts)) {\n            return Result.buildParamIllegal(\"集群角色为空\");\n        }\n        Map<String, String> roleClusterPortMap = Maps.newHashMap();\n        for (ESClusterRoleHost esClusterRoleHost : roleClusterHosts) {\n            //ES同一个角色的端口号应该相同，拆解ip和port后进行校验\n            String port = roleClusterPortMap.getOrDefault(esClusterRoleHost.getRole(), \"\");\n\n            if (StringUtils.isNotBlank(port) && !port.equals(esClusterRoleHost.getPort())) {\n                return Result.buildFail(\"同一个集群中同一角色的端口号应该相同\");\n            }\n            roleClusterPortMap.put(esClusterRoleHost.getRole(), esClusterRoleHost.getPort());\n        }\n\n        Set<String> hostRoles = roleClusterHosts.stream().map(ESClusterRoleHost::getRole).collect(Collectors.toSet());\n        if (!hostRoles.contains(MASTER_NODE.getDesc())) {\n            return Result.buildParamIllegal(String.format(PARAM_ILLEGAL_TIPS, MASTER_NODE.getDesc()));\n        }\n\n        List<ESClusterRoleHost> masterNodes = roleClusterHosts.stream()\n            .filter(r -> MASTER_NODE.getDesc().equals(r.getRole())).collect(Collectors.toList());\n\n        if (masterNodes.size() < CREATE_MASTER_NODE_MIN_NUMBER) {\n            return Result.buildParamIllegal(\"master-node角色ip个数要求大于等于1\");\n        }\n        // es版本检查\n        if (null == esPackageService.getByVersionAndType(clusterOpNewHostContent.getEsVersion(), ES_HOST.getCode())) {\n            return Result.buildFail(ES_HOST.getDesc() + \"类型版本为\" + clusterOpNewHostContent.getEsVersion() + \"的程序包不存在\");\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> buildHostEcmTaskDTO(EcmTaskDTO ecmTaskDTO, String param, String creator) {\n        // 获取并且设置新建集群工单内容中的集群创建人信息\n        ClusterNewHostContent clusterOpNewHostContent = ConvertUtil.str2ObjByJson(param, ClusterNewHostContent.class);\n        if (StringUtils.isBlank(clusterOpNewHostContent.getCreator())) {\n            clusterOpNewHostContent.setCreator(creator);\n        }\n        ecmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_NEW.getType());\n\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ESClusterTypeEnum.ES_HOST,\n            OpTaskTypeEnum.CLUSTER_NEW, clusterOpNewHostContent);\n\n        ecmTaskDTO.setEcmParamBaseList(ecmParamBaseList);\n        //新建 操作记录\n        final OperateRecord operateRecord = new Builder().userOperation(creator)\n                .project(projectService.getProjectBriefByProjectId(AuthConstant.SUPER_PROJECT_ID))\n                .operationTypeEnum(OperateTypeEnum.PHYSICAL_CLUSTER_NEW)\n                .content(String.format(\"新建物理集群：【%s】\", clusterOpNewHostContent.getPhyClusterName()))\n                .bizId(ecmTaskDTO.getId()).buildDefaultManualTrigger();\n        operateRecordService.save(operateRecord);\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> buildDockerEcmTaskDTO(EcmTaskDTO ecmTaskDTO, String param, String creator) {\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ESClusterTypeEnum.ES_DOCKER,\n            OpTaskTypeEnum.CLUSTER_NEW, ConvertUtil.obj2ObjByJSON(param, ClusterNewDockerContent.class));\n\n        ecmTaskDTO.setEcmParamBaseList(ecmParamBaseList);\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/handler/cluster/ClusterOfflineTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.handler.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterOfflineContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport org.springframework.stereotype.Service;\n\n/**\n * 物理集群下线\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Service(\"clusterOfflineTaskHandler\")\npublic class ClusterOfflineTaskHandler extends AbstractClusterTaskHandler {\n    @Override\n    Result<Void> validateHostParam(String param) throws NotFindSubclassException {\n        ClusterOfflineContent content = ConvertUtil.obj2ObjByJSON(param, ClusterOfflineContent.class);\n\n        if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n            return Result.buildParamIllegal(\"物理集群id为空\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildParamIllegal(\"物理集群不存在\");\n        }\n\n        if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n            OpTaskTypeEnum.CLUSTER_OFFLINE.getType())) {\n            return Result.buildParamIllegal(\"该集群上存在未完成的任务\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> buildHostEcmTaskDTO(EcmTaskDTO ecmTaskDTO, String param, String creator) {\n        ClusterOfflineContent content = ConvertUtil.obj2ObjByJSON(param, ClusterOfflineContent.class);\n        ecmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n        ecmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_OFFLINE.getType());\n        //下线记录操作内容\n        operateRecordService.saveOperateRecordWithManualTrigger(\n                String.format(\"下线物理集群：【%s】\", content.getPhyClusterName()), creator, AuthConstant.SUPER_PROJECT_ID,\n                content.getPhyClusterId(), OperateTypeEnum.PHYSICAL_CLUSTER_OFFLINE);\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/handler/cluster/ClusterRestartTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.handler.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_HOST;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterRestartContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord.Builder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Service;\n\n/**\n * 重新启动集群任务处理\n *\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Service(\"clusterRestartTaskHandler\")\npublic class ClusterRestartTaskHandler extends AbstractClusterTaskHandler {\n    @Override\n    Result<Void> initHostParam(OpTask opTask) {\n        ClusterRestartContent content = ConvertUtil.str2ObjByJson(opTask.getExpandData(), ClusterRestartContent.class);\n        content.setType(ES_HOST.getCode());\n        opTask.setExpandData(JSON.toJSONString(content));\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> validateHostParam(String param) throws NotFindSubclassException {\n        ClusterRestartContent content = ConvertUtil.str2ObjByJson(param, ClusterRestartContent.class);\n\n        if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n            return Result.buildParamIllegal(\"物理集群id为空\");\n        }\n\n        if (StringUtils.isBlank(content.getRoleOrder())) {\n            return Result.buildParamIllegal(\"物理集群重启角色顺序为空\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildParamIllegal(\"物理集群不存在\");\n        }\n\n        if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n            OpTaskTypeEnum.CLUSTER_RESTART.getType())) {\n            return Result.buildParamIllegal(\"该集群上存在未完成的集群重启任务\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> buildHostEcmTaskDTO(EcmTaskDTO ecmTaskDTO, String param, String creator) {\n        ClusterRestartContent content = ConvertUtil.str2ObjByJson(param, ClusterRestartContent.class);\n\n        ecmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n        ecmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_RESTART.getType());\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        ecmTaskDTO.setType(clusterPhy.getType());\n\n        List<String> roleNameList = new ArrayList<>();\n        for (String roleClusterName : JSON.parseArray(content.getRoleOrder(), String.class)) {\n            String roleName = roleClusterName.replaceFirst(clusterPhy.getCluster() + \"-\", \"\");\n            roleNameList.add(roleName);\n        }\n        final Result<List<EcmParamBase>> listResult = ecmHandleService.buildEcmParamBaseList(clusterPhy.getId(),\n            roleNameList);\n        if (listResult.failed()) {\n            return Result.buildFrom(listResult);\n        }\n\n        ecmTaskDTO.setEcmParamBaseList(listResult.getData());\n        //集群重启进行操作记录\n        final OperateRecord operateRecord = new Builder().userOperation(creator)\n                //ecm的操作都是属于超级项目下的，所以这里直接采用内部机制\n                    .project(projectService.getProjectBriefByProjectId(AuthConstant.SUPER_PROJECT_ID))\n                .operationTypeEnum(OperateTypeEnum.PHYSICAL_CLUSTER_RESTART)\n                    .content(String.format(\"重启:【%s】\",content.getPhyClusterName()))\n                \n                .bizId(content.getPhyClusterId()).buildDefaultManualTrigger();\n                operateRecordService.save(operateRecord);\n\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/handler/cluster/ClusterScaleTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.handler.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_DOCKER;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterIndecreaseDockerContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterIndecreaseHostContent;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.utils.OpOrderTaskConverter;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord.Builder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostScaleActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.Getter;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Service;\n\n/**\n * 集群扩缩容\n *\n * @author ohushenglin_v\n * @date 2022-05-20\n */\n@Service(\"clusterScaleTaskHandler\")\npublic class ClusterScaleTaskHandler extends AbstractClusterTaskHandler {\n\n    @Override\n    Result<Void> initHostParam(OpTask opTask) {\n        ClusterIndecreaseHostContent clusterOpIndecreaseHostContent = ConvertUtil.str2ObjByJson(opTask.getExpandData(),\n            ClusterIndecreaseHostContent.class);\n        // 如果当前角色对应pid_count为null，则设置为默认值1\n        if (null == clusterOpIndecreaseHostContent.getPidCount()) {\n            clusterOpIndecreaseHostContent.setPidCount(ClusterConstant.DEFAULT_CLUSTER_PAID_COUNT);\n        }\n\n        // 填充工单中的ip字段,port端口号填充\n        Map<String, String> portOfRoleMapFromHost = getPortOfRoleMapFromHost(\n            clusterOpIndecreaseHostContent.getPhyClusterId());\n        for (ESClusterRoleHost esClusterRoleHost : clusterOpIndecreaseHostContent.getClusterRoleHosts()) {\n            esClusterRoleHost.setIp(Getter.strWithDefault(esClusterRoleHost.getIp(), esClusterRoleHost.getHostname()));\n            esClusterRoleHost.setPort(portOfRoleMapFromHost.get(esClusterRoleHost.getRole()));\n        }\n\n        opTask.setExpandData(JSON.toJSONString(clusterOpIndecreaseHostContent));\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> validateHostParam(String param) throws NotFindSubclassException {\n        ClusterIndecreaseHostContent content = ConvertUtil.str2ObjByJson(param, ClusterIndecreaseHostContent.class);\n\n        if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n            return Result.buildParamIllegal(\"物理集群id为空\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildParamIllegal(\"物理集群不存在\");\n        }\n\n        if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n            OpTaskTypeEnum.CLUSTER_EXPAND.getType())\n            || opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n                OpTaskTypeEnum.CLUSTER_SHRINK.getType())) {\n            return Result.buildParamIllegal(\"该集群上存在未完成的集群扩缩容任务\");\n        }\n\n        // 对于datanode的缩容，如果该节点上存在数据分片,做出警告\n        if (content.getOperationType() == OpTaskTypeEnum.CLUSTER_SHRINK.getType()) {\n            Map<String, Integer> segmentsOfIpByCluster = null;\n            try {\n                segmentsOfIpByCluster = esClusterService\n                        .synGetSegmentsOfIpByCluster(content.getPhyClusterName());\n            } catch (ESOperateException e) {\n                LOGGER.error(\"class=ClusterScaleTaskHandler||method=validateHostParam||errMsg=fail to get get segments of ip by cluster\",\n                        e);\n                Result.buildFail(\"获取集群ip上的segment数目异常\");\n            }\n\n            for (ESClusterRoleHost esClusterRoleHost : content.getClusterRoleHosts()) {\n                if (esClusterRoleHost.getRole().equals(ESClusterNodeRoleEnum.DATA_NODE.getDesc())\n                        && segmentsOfIpByCluster.containsKey(esClusterRoleHost.getHostname())\n                        && !segmentsOfIpByCluster.get(esClusterRoleHost.getHostname()).equals(0)) {\n                    return Result.buildFail(\"数据节点上存在分片，请迁移分片之后再进行该节点的缩容\");\n                }\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> buildHostEcmTaskDTO(EcmTaskDTO ecmTaskDTO, String param, String creator) {\n        ClusterIndecreaseHostContent content = ConvertUtil.str2ObjByJson(param, ClusterIndecreaseHostContent.class);\n        ecmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n        ecmTaskDTO.setOrderType(content.getOperationType());\n\n        final Result<List<EcmParamBase>> hostScaleParamBaseListResult = getHostScaleParamBaseList(\n            content.getPhyClusterId().intValue(), content.getClusterRoleHosts(), content.getPidCount());\n        if (hostScaleParamBaseListResult.failed()) {\n            return Result.buildFrom(hostScaleParamBaseListResult);\n        }\n        List<EcmParamBase> hostScaleParamBaseList = hostScaleParamBaseListResult.getData();\n\n        ecmTaskDTO.setClusterNodeRole(ListUtils.strList2String(\n            hostScaleParamBaseList.stream().map(EcmParamBase::getRoleName).collect(Collectors.toList())));\n        ecmTaskDTO.setEcmParamBaseList(hostScaleParamBaseList);\n        String hostOption=content.getOperationType()==2?\"扩容\":\"缩容\";\n        if (CollectionUtils.isEmpty(content.getOriginClusterRoleHosts())) {\n            return Result.buildFail(\"集群角色对应的原始的主机列表不能为空\");\n        }\n        final String clientNode = content.getOriginClusterRoleHosts().stream()\n                .filter(esClusterRoleHost -> StringUtils.equalsIgnoreCase(esClusterRoleHost.getRole(), \"clientnode\"))\n                .map(ESClusterRoleHost::getHostname).distinct().collect(Collectors.joining(\",\"));\n    \n        final String datanode = content.getOriginClusterRoleHosts().stream()\n                .filter(esClusterRoleHost -> StringUtils.equalsIgnoreCase(esClusterRoleHost.getRole(), \"datanode\"))\n                .map(ESClusterRoleHost::getHostname).distinct().collect(Collectors.joining(\",\"));\n        \n        //扩缩容操作记录\n         final OperateRecord operateRecord = new Builder().userOperation(creator)\n                .project(projectService.getProjectBriefByProjectId(AuthConstant.SUPER_PROJECT_ID))\n                .operationTypeEnum(OperateTypeEnum.PHYSICAL_CLUSTER_CAPACITY)\n                .content(String.format(\"集群%s:clientNode:【%s】;datanode:【%s】\",hostOption,clientNode,datanode))\n                .bizId(content.getPhyClusterId()).buildDefaultManualTrigger();\n        operateRecordService.save(operateRecord);\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> buildDockerEcmTaskDTO(EcmTaskDTO ecmTaskDTO, String param, String creator) {\n        ClusterIndecreaseDockerContent content = ConvertUtil.obj2ObjByJSON(param, ClusterIndecreaseDockerContent.class);\n        ecmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n        ecmTaskDTO.setOrderType(content.getOperationType());\n\n        List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ES_DOCKER,\n            OpTaskTypeEnum.valueOfType(content.getOperationType()), content);\n        ecmTaskDTO.setClusterNodeRole(ListUtils\n            .strList2String(ecmParamBaseList.stream().map(EcmParamBase::getRoleName).collect(Collectors.toList())));\n        ecmTaskDTO.setEcmParamBaseList(ecmParamBaseList);\n        return Result.buildSucc();\n    }\n\n    private Result<List<EcmParamBase>> getHostScaleParamBaseList(Integer phyClusterId,\n                                                                 List<ESClusterRoleHost> roleClusterHosts,\n                                                                 Integer pidCount) {\n        List<String> roleNameList = new ArrayList<>();\n        for (ESClusterRoleHost clusterRoleHost : roleClusterHosts) {\n            if (!roleNameList.contains(clusterRoleHost.getRole())) {\n                roleNameList.add(clusterRoleHost.getRole());\n            }\n        }\n        final Result<List<EcmParamBase>> listResult = ecmHandleService.buildEcmParamBaseList(phyClusterId,\n            roleNameList);\n        if (listResult.failed()) {\n            return Result.buildFrom(listResult);\n        }\n        List<EcmParamBase> ecmParamBaseList = listResult.getData();\n\n        return Result\n            .buildSucc(buildHostScaleParamBaseList(roleClusterHosts, pidCount, roleNameList, ecmParamBaseList));\n    }\n\n    private List<EcmParamBase> buildHostScaleParamBaseList(List<ESClusterRoleHost> roleClusterHosts, Integer pidCount,\n                                                           List<String> roleNameList,\n                                                           List<EcmParamBase> ecmParamBaseList) {\n\n        List<EcmParamBase> hostScaleParamBaseList = Lists.newArrayList();\n        for (String roleName : roleNameList) {\n            List<String> hostnameList = Lists.newArrayList();\n            for (ESClusterRoleHost clusterRoleHost : roleClusterHosts) {\n\n                if (StringUtils.equals(roleName, clusterRoleHost.getRole())) {\n                    if (AriusObjUtils.isBlank(clusterRoleHost.getHostname())) {\n                        continue;\n                    }\n                    hostnameList.add(clusterRoleHost.getHostname());\n                }\n            }\n            for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n                if (StringUtils.equals(roleName, ecmParamBase.getRoleName())) {\n                    HostParamBase hostParamBase = (HostParamBase) ecmParamBase;\n\n                    HostScaleActionParam hostScaleActionParam = ConvertUtil.obj2Obj(hostParamBase,\n                        HostScaleActionParam.class);\n                    hostScaleActionParam.setPidCount(pidCount);\n                    hostScaleActionParam.setHostList(hostnameList);\n                    hostScaleActionParam.setNodeNumber(hostnameList.size());\n\n                    hostScaleParamBaseList.add(hostScaleActionParam);\n                }\n            }\n        }\n        return hostScaleParamBaseList;\n    }\n\n    /**\n     * 从主机映射得到港口作用\n     * 从db中获取物理集群角色下的端口号信息\n     *\n     * @param phyClusterId phy集群id\n     * @return Map<String, String>   Map<角色名称,端口号> 物理集群下的角色端口map\n     */\n    private Map<String, String> getPortOfRoleMapFromHost(Long phyClusterId) {\n        Map<String, String> rolePortMap = new HashMap<>(ESClusterNodeRoleEnum.values().length);\n        for (ESClusterNodeRoleEnum param : ESClusterNodeRoleEnum.values()) {\n            if (param != ESClusterNodeRoleEnum.UNKNOWN) {\n                List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService.getByRoleAndClusterId(phyClusterId,\n                    param.getDesc());\n                // 默认采用8060端口进行es集群的搭建\n                rolePortMap.put(param.getDesc(),\n                    CollectionUtils.isEmpty(clusterRoleHosts) ? ClusterConstant.DEFAULT_PORT\n                        : clusterRoleHosts.get(0).getPort());\n            }\n        }\n\n        return rolePortMap;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/handler/cluster/ClusterUpgradeTaskHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.handler.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_HOST;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Service;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterUpdateContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud.ElasticCloudCommonActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.espackage.ESPackage;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\n\n/**\n * 集群升级任务处理\n *\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Service(\"clusterUpgradeTaskHandler\")\npublic class ClusterUpgradeTaskHandler extends AbstractClusterTaskHandler {\n    @Override\n    Result<Void> initHostParam(OpTask opTask) {\n        ClusterUpdateContent clusterOpIndecreaseHostContent = ConvertUtil.str2ObjByJson(opTask.getExpandData(),\n            ClusterUpdateContent.class);\n        clusterOpIndecreaseHostContent.setType(ES_HOST.getCode());\n        opTask.setExpandData(JSON.toJSONString(clusterOpIndecreaseHostContent));\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> validateHostParam(String param) throws NotFindSubclassException {\n        ClusterUpdateContent content = ConvertUtil.str2ObjByJson(param, ClusterUpdateContent.class);\n\n        if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n            return Result.buildParamIllegal(\"物理集群id为空\");\n        }\n\n        if (StringUtils.isBlank(content.getRoleOrder())) {\n            return Result.buildParamIllegal(\"物理集群升级角色顺序为空\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildParamIllegal(\"物理集群不存在\");\n        }\n\n        if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n            OpTaskTypeEnum.CLUSTER_UPGRADE.getType())) {\n            return Result.buildParamIllegal(\"该集群上存在未完成的任务\");\n        }\n        Result<List<EcmParamBase>> ecmParamBaseResult = ecmHandleService.buildEcmParamBaseList(\n            content.getPhyClusterId().intValue(), ConvertUtil.str2ObjArrayByJson(content.getRoleOrder(), String.class));\n        if (ecmParamBaseResult.failed()) {\n            return Result.buildFail(ecmParamBaseResult.getMessage());\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    Result<Void> buildHostEcmTaskDTO(EcmTaskDTO ecmTaskDTO, String param, String creator) {\n        ClusterUpdateContent content = ConvertUtil.str2ObjByJson(param, ClusterUpdateContent.class);\n        ecmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n        ecmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_UPGRADE.getType());\n\n        Result<List<EcmParamBase>> ecmParamBaseResult = ecmHandleService.buildEcmParamBaseList(\n            content.getPhyClusterId().intValue(), ConvertUtil.str2ObjArrayByJson(content.getRoleOrder(), String.class));\n        List<EcmParamBase> ecmParamBaseList = ecmParamBaseResult.getData();\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            // 补充version信息\n            ESPackage esPackage = esPackageService.getByVersionAndType(content.getEsVersion(), ecmParamBase.getType());\n\n            if (ecmParamBase.getType().equals(ES_HOST.getCode())) {\n                ((HostParamBase) ecmParamBase).setEsVersion(content.getEsVersion());\n                if (!AriusObjUtils.isNull(esPackage) && !AriusObjUtils.isBlack(esPackage.getUrl())) {\n                    ((HostParamBase) ecmParamBase).setImageName(esPackage.getUrl());\n                }\n            } else {\n                ((ElasticCloudCommonActionParam) ecmParamBase).setEsVersion(content.getEsVersion());\n                if (!AriusObjUtils.isNull(esPackage) && !AriusObjUtils.isBlack(esPackage.getUrl())) {\n                    ((ElasticCloudCommonActionParam) ecmParamBase).setImageName(esPackage.getUrl());\n                }\n            }\n        }\n\n        ecmTaskDTO.setType(content.getType());\n        ecmTaskDTO.setEcmParamBaseList(ecmParamBaseList);\n        return Result.buildSucc();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/task/impl/OpTaskManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.task.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.page.TaskPageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskProcessDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.OpTaskVO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskHandleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.service.task.OpTaskService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum.TASK;\n\n/**\n * @author d06679\n * @date 2020/12/21\n */\n@Service\npublic class OpTaskManagerImpl implements OpTaskManager {\n    private static final ILog    LOGGER = LogFactory.getLog(OpTaskManagerImpl.class);\n\n    @Autowired\n    private OpTaskService opTaskService;\n\n    @Autowired\n    private HandleFactory        handleFactory;\n\n    @Autowired\n    private UserService          userService;\n    \n\n    @Override\n    public Result<OpTask> addTask(OpTaskDTO opTaskDTO, Integer projectId) throws NotFindSubclassException {\n        if (AriusObjUtils.isNull(opTaskDTO.getCreator())) {\n            return Result.buildParamIllegal(\"提交人为空\");\n        }\n\n        OpTaskTypeEnum typeEnum = OpTaskTypeEnum.valueOfType(opTaskDTO.getTaskType());\n        if (OpTaskTypeEnum.UNKNOWN.equals(typeEnum)) {\n            return Result.buildNotExist(\"任务类型不存在\");\n        }\n\n        if (AriusObjUtils.isNull(userService.getUserBriefByUserName(opTaskDTO.getCreator()))) {\n            return Result.buildParamIllegal(\"提交人非法\");\n        }\n        OpTaskHandleEnum taskHandleEnum = OpTaskHandleEnum.valueOfType(opTaskDTO.getTaskType());\n\n        OpTaskHandler handler = (OpTaskHandler) handleFactory.getByHandlerNamePer(taskHandleEnum.getMessage());\n\n        return handler.addTask(ConvertUtil.obj2Obj(opTaskDTO, OpTask.class));\n    }\n\n    @Override\n    public boolean existUnClosedTask(Integer key, Integer type) throws NotFindSubclassException {\n        OpTaskHandleEnum taskHandleEnum = OpTaskHandleEnum.valueOfType(type);\n\n        OpTaskHandler handler = (OpTaskHandler) handleFactory.getByHandlerNamePer(taskHandleEnum.getMessage());\n        return handler.existUnClosedTask(String.valueOf(key), type);\n    }\n\n    @Override\n    public void insert(OpTask task) {\n        try {\n            opTaskService.insert(task);\n        } catch (Exception e) {\n            LOGGER.error(\"class=DCDRWorkTaskHandler||method=addTask||taskType={}||businessKey={}||errMsg={}\",\n                task.getTaskType(), task.getBusinessKey(), e.getStackTrace(), e);\n        }\n    }\n\n    @Override\n    public void updateTask(OpTask task) {\n        opTaskService.update(task);\n    }\n\n    @Override\n    public Result<OpTask> getById(Integer id) {\n        OpTask opTask = opTaskService.getById(id);\n        if (opTask == null) {\n            return Result.buildFail(ResultType.NOT_EXIST.getMessage());\n        }\n        return Result.buildSucc(opTask);\n    }\n\n    @Override\n    public PaginationResult<OpTaskVO> pageGetTasks(Integer projectId, OpTaskQueryDTO queryDTO) throws NotFindSubclassException {\n        BaseHandle baseHandle = handleFactory.getByHandlerNamePer(TASK.getPageSearchType());\n        if (baseHandle instanceof TaskPageSearchHandle) {\n            TaskPageSearchHandle handle = (TaskPageSearchHandle) baseHandle;\n            return handle.doPage(queryDTO, projectId);\n        }\n        LOGGER.warn(\n                \"class=OpTaskManagerImpl||method=pageGetTasks||msg=failed to get the TaskPageSearchHandle\");\n\n        return PaginationResult.buildFail(\"分页获取任务中心信息失败\");\n    }\n\n    @Override\n    public Result<List<OpTask>> list() {\n        final List<OpTask> tasks = opTaskService.listAll();\n      \n        return Result.buildSucc(tasks);\n    }\n\n    @Override\n    public Result<Void> processTask(OpTaskProcessDTO processDTO) throws NotFindSubclassException {\n        if (AriusObjUtils.isNull(processDTO.getTaskId())) {\n            return Result.buildParamIllegal(\"任务id为空\");\n        }\n        OpTask task = opTaskService.getById(processDTO.getTaskId());\n\n        OpTaskTypeEnum typeEnum = OpTaskTypeEnum.valueOfType(task.getTaskType());\n        if (OpTaskTypeEnum.UNKNOWN.equals(typeEnum)) {\n            return Result.buildNotExist(\"任务类型不存在\");\n        }\n\n        OpTaskHandleEnum taskHandleEnum = OpTaskHandleEnum.valueOfType(task.getTaskType());\n\n        OpTaskHandler handler = (OpTaskHandler) handleFactory.getByHandlerNamePer(taskHandleEnum.getMessage());\n\n        return handler.process(task, processDTO.getTaskProgress(),\n            processDTO.getStatus(), processDTO.getExpandData());\n    }\n\n    @Override\n    public Result<OpTask> getLatestTask(String businessKey, Integer taskType) {\n        OpTask opTask = opTaskService.getLatestTask(businessKey, taskType);\n        if (opTask == null) {\n            return Result.buildFail(ResultType.NOT_EXIST.getMessage());\n        }\n        return Result.buildSucc(opTask);\n    }\n\n    @Override\n    public List<OpTask> getPendingTaskByType(Integer taskType) {\n       return opTaskService.getPendingTaskByType(taskType);\n    }\n\n    @Override\n    public List<OpTask> getSuccessTaskByType(Integer taskType) {\n       return opTaskService.getSuccessTaskByType(taskType);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/TemplateLogicManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateRateLimitDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateWithCreateInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateClearDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateLogicAggregate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateClearVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateDeleteVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateRateLimitVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateCyclicalRollInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AmsRemoteException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport java.util.List;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * 逻辑模板管理Biz类\n *\n * @author wangshu\n * @date 2020/09/11\n */\n@Component\npublic interface TemplateLogicManager {\n\n    /**\n     * 默认模板价值分\n     */\n    int DEFAULT_TEMPLATE_VALUE = 61;\n\n    /**\n     * 获取最近访问该模板的project\n     *\n     * @param logicId logicId\n     * @return result\n     */\n    List<ProjectBriefVO> getLogicTemplateProjectAccess(Integer logicId) throws AmsRemoteException;\n\n    /**\n     * 新建逻辑模板\n     * @param param 模板信息\n     * @param operator 操作人\n     * @param projectId projectId\n     * @return result\n     */\n    @Transactional(rollbackFor = Exception.class)\n    Result<Void> create(IndexTemplateWithCreateInfoDTO param, String operator,\n                        Integer projectId) throws AdminOperateException;\n\n    /**\n     * 获取所有逻辑模板聚合\n     *\n     * @param projectId 当前projectId\n     * @return\n     */\n    List<IndexTemplateLogicAggregate> getAllTemplatesAggregate(Integer projectId);\n\n\n\n    /**\n     * 拼接集群名称\n     * @param logicClusters 逻辑集群详情列表\n     * @return\n     */\n    String jointCluster(List<ClusterLogic> logicClusters);\n\n    /**\n     *\n     * @param aggregates 聚合列表\n     * @return\n     */\n    List<ConsoleTemplateVO> fetchConsoleTemplates(List<IndexTemplateLogicAggregate> aggregates);\n\n    /**\n     * 获取模板VO\n     * @param aggregate 模板聚合\n     * @return\n     */\n    ConsoleTemplateVO fetchConsoleTemplate(IndexTemplateLogicAggregate aggregate);\n\n    /**\n     * 获取逻辑索引列表\n     */\n    List<ConsoleTemplateVO> getConsoleTemplatesVOS(Integer projectId);\n\n    /**\n     * 根据项目和权限类型获取模板信息\n     * @param projectId                 项目Id\n     * @param authType              权限类型\n     * @see   ProjectTemplateAuthEnum\n     * @return\n     */\n    List<IndexTemplate> getTemplatesByProjectIdAndAuthType(Integer projectId, Integer authType);\n\n    /**\n     * 根据项目获取有管理\\读写\\读权限的逻辑模版\n     */\n    List<String> getTemplateLogicNames(Integer projectId);\n\n    Result<Void> editTemplate(IndexTemplateDTO param, String operator, Integer projectId);\n\n    Result<Void> delTemplate(Integer logicTemplateId, String operator, Integer projectId) throws AdminOperateException;\n\n    /**\n     * 模糊（精确）/分页查询模板列表接口\n     * @param condition  查询条件\n     * @param projectId      项目\n     * @return\n     */\n    PaginationResult<ConsoleTemplateVO> pageGetConsoleTemplateVOS(TemplateConditionDTO condition,\n                                                                  Integer projectId) throws NotFindSubclassException;\n\n    /**\n     * 校验创建模板名称是否合法\n     * @param templateName   模板名称\n     * @return\n     */\n    Result<Void> checkTemplateValidForCreate(String templateName);\n\n    /**\n     * 校验模板mapping可否编辑\n     * @param templateId\n     * @return\n     */\n    Result<Boolean> checkTemplateEditMapping(Integer templateId);\n\n    /**\n     * 更改逻辑模版的rollover能力\n     *\n     * @param templateLogicId 逻辑模版id\n     * @param status          1 启用，0 禁用\n     * @param operator        操作者\n     * @param projectId\n     * @return\n     */\n    Result<Void> switchRolloverStatus(Integer templateLogicId, Integer status, String operator, Integer projectId);\n\n\n\n    /**\n     * 校验模板是否可以使用索引模板的相关服务，例如是否可以编辑mapping,setting\n     * @param templateId 逻辑模板id\n     * @param templateSrvId 索引模板服务id\n     * @return 校验的结果\n     */\n    Result<Boolean> checkTemplateEditService(Integer templateId, Integer templateSrvId);\n\n    /**\n     * 校验指定projectId能否对指定的逻辑模板进行操作\n     * @param logicId 逻辑模板id\n     * @param projectId projectId\n     * @return result\n     */\n    Result<Void> checkProjectAuthOnLogicTemplate(Integer logicId, Integer projectId);\n\n    /**\n     * 同步dcdr相关信息\n     * @param logicId\n     * @return\n     */\n    boolean updateDCDRInfo(Integer logicId);\n\n    /**\n     * 全量获取指定物理集群所关联的逻辑模板信息列表\n     *\n     * @param phyCluster 物理集群名称\n     * @return 物理集群下的全量模板信息列表视图\n     */\n    Result<List<ConsoleTemplateVO>> getTemplateVOByPhyCluster(String phyCluster);\n\n    /**\n     * 清除索引\n     */\n    Result<Void> clearIndices(TemplateClearDTO clearDTO, String operator, Integer projectId);\n\n    /**\n     * 执行调整shard 数量\n     *\n     * @param logicTemplateId 模板id\n     * @param shardNum        调整后的shard数量\n     * @param projectId\n     * @param operator\n     * @return 调整结果\n     */\n    Result<Void> adjustShard(Integer logicTemplateId, Integer shardNum, Integer projectId,\n                             String operator) throws AdminOperateException;\n\n    /**\n     * 模板升级\n     *\n     * @param templateId 模板id\n     * @param operator   操作者\n     * @param projectId\n     * @return\n     */\n    Result<Void> upgrade(Integer templateId, String operator, Integer projectId) throws AdminOperateException;\n\n    Result<List<ConsoleTemplateVO>> listTemplateVOByLogicCluster(String clusterLogicName, Integer projectId);\n\n    Result<List<Tuple<String, String>>> listLogicTemplatesByProjectId(Integer projectId);\n\n    Result<List<TemplateCyclicalRollInfoVO>> getCyclicalRollInfo(Integer logicId);\n\n    Result<ConsoleTemplateRateLimitVO> getTemplateRateLimit(Integer logicId);\n\n    Result<ConsoleTemplateDetailVO> getDetailVoByLogicId(Integer logicId, Integer projectId);\n\n    Result<ConsoleTemplateClearVO> getLogicTemplateClearInfo(Integer logicId) throws AmsRemoteException;\n\n    Result<ConsoleTemplateDeleteVO> getLogicTemplateDeleteInfo(Integer logicId) throws AmsRemoteException;\n\n    Result<Void> updateTemplateWriteRateLimit(ConsoleTemplateRateLimitDTO consoleTemplateRateLimitDTO, String operator,\n                                              Integer projectId);\n    \n    /**\n     * 它通过其逻辑 ID 更新模板的健康状况。\n     *\n     * @param logicId 模板的 logicId。\n     * @return 一个布尔值。\n     */\n    boolean updateTemplateHealthByLogicId(Integer logicId);\n    \n    /**\n     * 用索引模板的写操作。\n     *\n     * @param templateId 要操作的模板的 id\n     * @param status     0：否，1：是\n     * @param operator   触发操作的操作员\n     * @param projectId  项目编号\n     * @return Result<Void>\n     */\n    Result<Void> blockWrite(Integer templateId, Boolean status, String operator, Integer projectId);\n    \n    /**\n     * 用于索引模板的读取。\n     *\n     * @param templateId 要操作的模板的 id\n     * @param status     0：否，1：是\n     * @param operator   触发操作的用户\n     * @param projectId  项目编号\n     * @return Result<Void>\n     */\n    Result<Void> blockRead(Integer templateId, Boolean status, String operator, Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/TemplatePhyManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplatePhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplatePhysicalCopyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplatePhysicalUpgradeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplatePhyVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.IndexTemplatePhysicalVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport java.util.List;\nimport java.util.Set;\nimport org.springframework.transaction.annotation.Transactional;\n\npublic interface TemplatePhyManager {\n\n    /**\n     * 元数据校验\n     *\n     * @return\n     */\n    boolean checkMeta();\n\n    /**\n     * 元数据同步\n     *\n     * @param physicalId\n     * @return\n     */\n    void syncMeta(Long physicalId, int retryCount) throws ESOperateException;\n\n    /**\n     * 删除\n     *\n     * @param physicalId 物理模板id\n     * @param operator   操作人\n     * @return result\n     */\n    @Transactional(rollbackFor = Exception.class)\n    Result<Void> delTemplate(Long physicalId, String operator) throws ESOperateException;\n\n    /**\n     * 删除\n     *\n     * @param logicId  id\n     * @param operator 操作人\n     * @return result\n     * @throws ESOperateException e\n     */\n    Result<Void> delTemplateByLogicId(Integer logicId, String operator) throws ESOperateException;\n\n    /**\n     * 升版本\n     * <p>\n     * 1、修改数据库中的版本号 2、删除原版本明天的索引,如果指定了rack就按着rack创建,否则在源rack上创建 3、创建新版本明天的索引,按着模板rack创建\n     *\n     * @param param     参数\n     * @param operator  操作人\n     * @param projectId\n     * @return result\n     */\n    @Transactional(rollbackFor = Exception.class)\n    Result<Void> upgradeTemplate(TemplatePhysicalUpgradeDTO param, String operator,\n                                 Integer projectId) throws ESOperateException;\n\n    Result<Boolean> upgradeMultipleTemplate(List<TemplatePhysicalUpgradeDTO> params, String operator,\n                                            Integer projectId) throws ESOperateException;\n\n    Result<Void> rolloverUpgradeTemplate(TemplatePhysicalUpgradeDTO param, String operator) throws ESOperateException;\n\n    /**\n     * 复制 只在目标集群建立模板即可,模板管理的资源都是与逻辑模板id管理,与物理模板没有关系\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @return result\n     */\n    Result<Void> copyTemplate(TemplatePhysicalCopyDTO param, String operator) throws AdminOperateException;\n\n    /**\n     * 编辑\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @return result\n     */\n    Result<Void> editTemplate(IndexTemplatePhyDTO param, String operator) throws ESOperateException;\n\n    Result<Boolean> editMultipleTemplate(List<IndexTemplatePhyDTO> params, String operator) throws ESOperateException;\n\n    /**\n     * 批量新增物理模板\n     *\n     * @param logicId       逻辑模板id\n     * @param physicalInfos 物理模板信息\n     * @return result\n     */\n    @Transactional(rollbackFor = Exception.class)\n    Result<Void> addTemplatesWithoutCheck(Integer logicId,\n                                          List<IndexTemplatePhyDTO> physicalInfos) throws AdminOperateException;\n\n    /**\n     * 新建\n     *\n     * @param param 模板参数\n     * @return result\n     */\n    @Transactional(rollbackFor = Exception.class)\n    Result<Long> addTemplateWithoutCheck(IndexTemplatePhyDTO param) throws AdminOperateException;\n\n    /**\n     * 主从切换\n     *\n     * @param logicId                逻辑模板id\n     * @param expectMasterPhysicalId 期望的主\n     * @param operator               操作人\n     * @return result\n     */\n    @Transactional(rollbackFor = Exception.class)\n    Result<Void> switchMasterSlave(Integer logicId, Long expectMasterPhysicalId, String operator);\n\n    /**\n     *\n     * @param param\n     * @param operator\n     * @param retryCount\n     * @return\n     * @throws ESOperateException\n     */\n    Result<Void> editTemplateWithoutCheck(IndexTemplatePhyDTO param, String operator,\n                                          int retryCount) throws ESOperateException;\n\n    /**\n     * 根据逻辑模板和热数据保存天数或者过期天数来获取需要迁移到冷存的索引名称列表或者需要删除的索引名称列表\n     * @param physicalWithLogic 逻辑物理模板\n     * @param days 热数据保存天数\n     * @return 索引名称列表\n     */\n    Tuple</*存放冷存索引列表*/Set<String>, /*存放热存索引列表*/Set<String>> getHotAndColdIndexByBeforeDay(IndexTemplatePhyWithLogic physicalWithLogic,\n                                                                                          int days);\n\n    /**\n     * 获取指定天数外的索引列表\n     * @param physicalWithLogic 逻辑物理模板\n     * @param days  天数\n     * @return 索引名称列表\n     */\n    Set<String> getIndexByBeforeDay(IndexTemplatePhyWithLogic physicalWithLogic, int days);\n\n    /**\n     * 获取带有App权限信息的物理模板列表\n     * @param projectId 当前登录projectId\n     */\n    List<ConsoleTemplatePhyVO> getConsoleTemplatePhyVOS(IndexTemplatePhyDTO param, Integer projectId);\n\n    /**\n     * 根据项目获取有管理权限的物理模板\n     */\n    List<String> getTemplatePhyNames(Integer projectId);\n\n    /**\n     * 获取物理模板可复制的物理集群名称列表, 仅支持不同集群间模板复制\n     */\n    List<String> getCanCopyTemplatePhyClusterPhyNames(Long templatePhyId);\n\n    /**\n     * 根据逻辑模板Id获取多个物理模板信息\n     * @param logicId    逻辑集群Id\n     * @return           List<IndexTemplatePhysicalVO>\n     */\n    Result<List<IndexTemplatePhysicalVO>> getTemplatePhies(Integer logicId);\n\n    Result<List<IndexTemplatePhysicalVO>> listByRegionId(Integer regionId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/TemplatePhyStaticsManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ProjectIdTemplateAccessCountVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateStatsInfoVO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author d06679\n * @date 2019-06-24\n */\npublic interface TemplatePhyStaticsManager {\n    /**\n     * 根据模板id获取最近days天的projectid访问统计信息\n     * @param logicTemplateId 逻辑索引模板ID\n     * @param days 最近多少天\n     * @return map\n     */\n    Result<Map<Integer, Long>> getAccessStatsInfoByTemplateIdAndDays(int logicTemplateId, int days);\n\n    /**\n     * 根据模板id获取模板的基本统计信息\n     * @param logicTemplateId 模板id\n     * @return result\n     */\n    Result<TemplateStatsInfoVO> getTemplateBaseStatisticalInfoByLogicTemplateId(Long logicTemplateId);\n\n    /**\n     * 根据模板id获取模板的基本统计信息\n     * @param logicTemplateId 模板id\n     * @param startDate 开始时刻\n     * @param endDate 结束时刻\n     * @return list\n     */\n    Result<List<ESIndexStats>> getIndexStatics(Long logicTemplateId, Long startDate, Long endDate);\n\n    /**\n     * 根据模板Id获取[startDate, endDate]的projectid访问统计信息\n     * @param logicTemplateId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    Result<List<ProjectIdTemplateAccessCountVO>> getAccessAppInfos(int logicTemplateId, Long startDate, Long endDate);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/impl/TemplateLogicManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.DEFAULT_INDEX_MAPPING_TYPE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.G_PER_SHARD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum.TEMPLATE_LOGIC;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_NAME_CHAR_SET;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_NAME_SIZE_MAX;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_NAME_SIZE_MIN;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.ADD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum.OWN;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum.isTemplateAuthExitByCode;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType.FAIL;\nimport static com.didichuxing.datachannel.arius.admin.core.service.template.physic.impl.IndexTemplatePhyServiceImpl.NOT_CHECK;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.indices.IndicesManager;\nimport com.didichuxing.datachannel.arius.admin.biz.page.TemplateLogicPageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplateLogicManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplatePhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.cold.ColdManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.dcdr.TemplateDCDRManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.pipeline.PipelineManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.precreate.PreCreateManager;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.IndexTemplateValue;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateRateLimitDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplatePhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateWithCreateInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateClearDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateLogicAggregate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithCluster;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexCatCellWithTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateClearVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateDeleteVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateRateLimitVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateCyclicalRollInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESSettingConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TemplateOperateRecordEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.index.IndexDeleteEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.LogicTemplateCreatePipelineEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AmsRemoteException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.TemplateUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.TemplateStatsService;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.elasticsearch.client.utils.JsonUtils;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.UUID;\nimport java.util.function.BiFunction;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.transaction.interceptor.TransactionAspectSupport;\n\n@Component\npublic class TemplateLogicManagerImpl implements TemplateLogicManager {\n\n    private static final ILog               LOGGER                = LogFactory.getLog(TemplateLogicManager.class);\n    private static final String             INDEX_NOT_EXISTS_TIPS = \"索引不存在\";\n    private static final String DYNAMIC_TEMPLATES = \"dynamic_templates\";\n    private static final String PROPERTIES        = \"properties\";\n    @Autowired\n    private ProjectLogicTemplateAuthService projectLogicTemplateAuthService;\n\n    @Autowired\n    private TemplateStatsService            templateStatsService;\n\n  \n\n    @Autowired\n    private ColdManager                     templateColdManager;\n\n    @Autowired\n    private IndexTemplateService            indexTemplateService;\n\n    @Autowired\n    private IndexTemplatePhyService         indexTemplatePhyService;\n\n    @Autowired\n    private ClusterPhyService               clusterPhyService;\n\n    @Autowired\n    private ClusterRegionService            clusterRegionService;\n\n    @Autowired\n    private OperateRecordService            operateRecordService;\n\n    @Autowired\n    private ProjectService                  projectService;\n\n    @Autowired\n    private ESIndexService                  esIndexService;\n\n    @Autowired\n    private ESTemplateService               esTemplateService;\n\n    @Autowired\n    private TemplatePhyManager              templatePhyManager;\n\n    @Autowired\n    private HandleFactory                   handleFactory;\n\n    @Autowired\n    private TemplateDCDRManager             templateDcdrManager;\n\n    @Autowired\n    private PreCreateManager                preCreateManager;\n\n    @Autowired\n    private ClusterLogicService             clusterLogicService;\n\n    private final static Integer            RETRY_TIMES           = 3;\n    @Autowired\n    private IndicesManager                  indicesManager;\n    @Autowired\n    private PipelineManager                 templatePipelineManager;\n    \n    @Autowired\n    protected ESClusterNodeService esClusterNodeService;\n    @Autowired\n    private ESClusterService esClusterService;\n\n    public static final int                 MAX_PERCENT           = 10000;\n    public static final int                 MIN_PERCENT           = -99;\n\n    /**\n     * 获取最近访问该模板的project\n     *\n     * @param logicId logicId\n     * @return result\n     */\n    @Override\n    public List<ProjectBriefVO> getLogicTemplateProjectAccess(Integer logicId) throws AmsRemoteException {\n        Result<Map<Integer, Long>> result = templateStatsService.getTemplateAccessProjectIds(logicId, 7);\n        if (result.failed()) {\n            throw new AmsRemoteException(\"获取访问模板的project列表失败\");\n        }\n\n        if (null == result.getData() || 0 == result.getData().size()) {\n            return Lists.newArrayList();\n        }\n\n        return result.getData().keySet().stream().map(projectService::getProjectBriefByProjectId)\n            .filter(Objects::nonNull).collect(Collectors.toList());\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> create(IndexTemplateWithCreateInfoDTO param, String operator, Integer projectId)\n            throws AdminOperateException {\n        IndexTemplateDTO indexTemplateDTO = buildTemplateDTO(param, projectId);\n        Result<Void> validLogicTemplateResult = indexTemplateService.validateTemplate(indexTemplateDTO, ADD, projectId);\n        if (validLogicTemplateResult.failed()) {\n            return validLogicTemplateResult;\n        }\n    \n        Result<Void> validPhyTemplateResult = indexTemplatePhyService.validateTemplates(\n                indexTemplateDTO.getPhysicalInfos(), ADD);\n        if (validPhyTemplateResult.failed()) {\n            return validPhyTemplateResult;\n        }\n        final Map<String, String> setting = JsonUtils.flat(JSONObject.parseObject(param.getSetting()));\n        if (setting.containsKey(ESSettingConstant.INDEX_NUMBER_OF_SHARDS) || setting.containsKey(\n                ESSettingConstant.INDEX_ROUTING_ALLOCATION_INCLUDE_NAME)) {\n            return Result.buildFail(\n                    \"\\\"index.number_of_shards \\\"和 \\\"index.routing.allocation.include._name \\\"两个字段系统会自动计算，不支持用户自定义设置。\");\n        \n        }\n        \n    \n        try {\n            Result<Void> save2DBResult = indexTemplateService.addTemplateWithoutCheck(indexTemplateDTO);\n            if (save2DBResult.failed()) {\n                throw new AdminOperateException(String.format(\"创建模板失败:%s\", save2DBResult.getMessage()));\n            }\n        \n            Result<Void> save2PhyTemplateResult = templatePhyManager.addTemplatesWithoutCheck(indexTemplateDTO.getId(),\n                    indexTemplateDTO.getPhysicalInfos());\n            if (save2PhyTemplateResult.failed()) {\n                throw new AdminOperateException(String.format(\"创建模板失败:%s\", save2PhyTemplateResult.getMessage()));\n            }\n        \n            Result<Void> saveTemplateConfigResult = insertTemplateConfig(indexTemplateDTO);\n            if (saveTemplateConfigResult.failed()) {\n                throw new AdminOperateException(String.format(\"创建模板失败:%s\", saveTemplateConfigResult.getMessage()));\n            }\n    \n            operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"模版创建：%s\", param.getName()),\n                    operator, projectId, indexTemplateDTO.getId(), OperateTypeEnum.TEMPLATE_MANAGEMENT_CREATE);\n            //发布创建pipeline的事件\n            SpringTool.publish(new LogicTemplateCreatePipelineEvent(this,indexTemplateDTO.getId()));\n            return Result.buildSucc();\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=TemplateLogicManagerImpl||method=create\", e);\n            // 这里必须显示事务回滚\n            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();\n            return Result.buildFail(e.getMessage());\n        } catch (Exception e) {\n            LOGGER.error(\"class=TemplateLogicManagerImpl||method=create\", e);\n            // 这里必须显示事务回滚\n            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();\n            return Result.buildFail(\"模版创建失败，请重新尝试\");\n        }\n    \n        \n    }\n\n    /**\n     * 获取所有逻辑模板聚合\n     *\n     * @param projectId 当前project Id\n     * @return\n     */\n    @Override\n    public List<IndexTemplateLogicAggregate> getAllTemplatesAggregate(Integer projectId) {\n        List<IndexTemplateLogicAggregate> indexTemplateLogicAggregates = new ArrayList<>();\n        List<IndexTemplateWithCluster> logicTemplates = indexTemplateService.listAllLogicTemplateWithClusters();\n        \n\n        return indexTemplateLogicAggregates;\n    }\n\n\n\n    /**\n     * 拼接集群名称\n     * @param logicClusters 逻辑集群详情列表\n     * @return\n     */\n    @Override\n    public String jointCluster(List<ClusterLogic> logicClusters) {\n        if (CollectionUtils.isNotEmpty(logicClusters)) {\n            return String.join(\",\", logicClusters.stream().map(ClusterLogic::getName).collect(Collectors.toList()));\n        }\n\n        return StringUtils.EMPTY;\n    }\n\n    /**\n     *\n     * @param aggregates 聚合列表\n     * @return\n     */\n    @Override\n    public List<ConsoleTemplateVO> fetchConsoleTemplates(List<IndexTemplateLogicAggregate> aggregates) {\n        List<ConsoleTemplateVO> consoleTemplates = Lists.newArrayList();\n        if (CollectionUtils.isNotEmpty(aggregates)) {\n            Map<Integer, String> projectId2ProjectNameMap = Maps.newHashMap();\n\n            for (IndexTemplateLogicAggregate aggregate : aggregates) {\n                ConsoleTemplateVO consoleTemplateVO = fetchConsoleTemplate(aggregate);\n\n                //获取项目名称\n                Integer projectId = consoleTemplateVO.getProjectId();\n                if (projectId2ProjectNameMap.containsKey(projectId)) {\n                    consoleTemplateVO.setProjectName(projectId2ProjectNameMap.get(projectId));\n                } else {\n                    String projectName = Optional.ofNullable(projectService.getProjectBriefByProjectId(projectId))\n                        .map(ProjectBriefVO::getProjectName).orElse(null);\n                    if (!AriusObjUtils.isNull(projectName)) {\n                        consoleTemplateVO.setProjectName(projectName);\n                        projectId2ProjectNameMap.put(projectId, projectName);\n                    }\n                }\n\n                consoleTemplates.add(consoleTemplateVO);\n            }\n        }\n\n        Collections.sort(consoleTemplates);\n        return consoleTemplates;\n    }\n\n    /**\n     * 获取模板VO\n     * @param aggregate 模板聚合\n     * @return\n     */\n    @Override\n    public ConsoleTemplateVO fetchConsoleTemplate(IndexTemplateLogicAggregate aggregate) {\n        if (aggregate != null) {\n            ConsoleTemplateVO templateLogic = ConvertUtil.obj2Obj(aggregate.getIndexTemplateLogicWithCluster(),\n                ConsoleTemplateVO.class);\n            try {\n                templateLogic.setAuthType(ProjectTemplateAuthEnum.NO_PERMISSION.getCode());\n                if (aggregate.getProjectTemplateAuth() != null) {\n                    templateLogic.setAuthType(aggregate.getProjectTemplateAuth().getType());\n                }\n\n                templateLogic.setValue(DEFAULT_TEMPLATE_VALUE);\n                if (aggregate.getIndexTemplateValue() != null) {\n\n                    templateLogic.setValue(aggregate.getIndexTemplateValue().getValue());\n                }\n                templateLogic.setHasDCDR(templateLogic.getHasDCDR());\n\n                //设置模板关联物理集群\n                List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService\n                    .getTemplateByLogicId(templateLogic.getId());\n                if (CollectionUtils.isNotEmpty(templatePhyList)) {\n                    templateLogic.setClusterPhies(\n                        templatePhyList.stream().map(IndexTemplatePhy::getCluster).collect(Collectors.toList()));\n                }\n            } catch (Exception e) {\n                LOGGER.warn(\"class=TemplateLogicManager||method=fetchConsoleTemplate||aggregate={}\", aggregate, e);\n            }\n\n            return templateLogic;\n        }\n\n        return null;\n    }\n\n    @Override\n    public List<ConsoleTemplateVO> getConsoleTemplatesVOS(Integer projectId) {\n        return fetchConsoleTemplates(getAllTemplatesAggregate(projectId));\n    }\n\n    @Override\n    public List<IndexTemplate> getTemplatesByProjectIdAndAuthType(Integer projectId, Integer authType) {\n        if (!projectService.checkProjectExist(projectId)) {\n            return Lists.newArrayList();\n        }\n\n        //超级项目对所有模板都是管理权限\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId) && !OWN.getCode().equals(authType)) {\n            return Lists.newArrayList();\n        }\n\n        if (!isTemplateAuthExitByCode(authType)) {\n            return Lists.newArrayList();\n        }\n\n        switch (ProjectTemplateAuthEnum.valueOf(authType)) {\n            case OWN:\n                if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n                    return indexTemplateService.listAllLogicTemplates();\n                } else {\n                    return indexTemplateService.listProjectLogicTemplatesByProjectId(projectId);\n                }\n\n            case RW:\n                List<ProjectTemplateAuth> projectActiveTemplateRWAuths = projectLogicTemplateAuthService\n                    .getProjectActiveTemplateRWAuths(projectId);\n                return projectActiveTemplateRWAuths.stream()\n                    .map(r -> indexTemplateService.getLogicTemplateById(r.getTemplateId()))\n                    .collect(Collectors.toList());\n\n            case R:\n                List<ProjectTemplateAuth> projectActiveTemplateRAuths = projectLogicTemplateAuthService\n                    .getProjectActiveTemplateRAuths(projectId);\n                return projectActiveTemplateRAuths.stream()\n                    .map(r -> indexTemplateService.getLogicTemplateById(r.getTemplateId()))\n                    .collect(Collectors.toList());\n\n            case NO_PERMISSION:\n                List<IndexTemplate> allLogicTemplates = indexTemplateService.listAllLogicTemplates();\n                List<Integer> projectRAndRwAuthTemplateIdList = projectLogicTemplateAuthService\n                    .getProjectTemplateRWAndRAuthsWithoutCodec(projectId).stream()\n                    .map(ProjectTemplateAuth::getTemplateId).collect(Collectors.toList());\n\n                List<IndexTemplate> notAuthIndexTemplateList = allLogicTemplates.stream().filter(\n                    r -> !projectId.equals(r.getProjectId()) && !projectRAndRwAuthTemplateIdList.contains(r.getId()))\n                    .collect(Collectors.toList());\n                return notAuthIndexTemplateList;\n\n            default:\n                return Lists.newArrayList();\n\n        }\n    }\n\n    @Override\n    public List<String> getTemplateLogicNames(Integer projectId) {\n        List<IndexTemplate> templateLogics;\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            templateLogics = indexTemplateService.listAllLogicTemplates();\n        } else {\n            templateLogics = indexTemplateService.listProjectLogicTemplatesByProjectId(projectId);\n        }\n\n        return templateLogics.stream().map(IndexTemplate::getName).collect(Collectors.toList());\n    }\n\n    @Override\n    public Result<Void> editTemplate(IndexTemplateDTO param, String operator, Integer projectId) {\n        try {\n            final IndexTemplate oldIndexTemplate = indexTemplateService.getLogicTemplateById(param.getId());\n            final Result<Void> result = ProjectUtils.checkProjectCorrectly(IndexTemplate::getProjectId,\n                oldIndexTemplate, projectId);\n            if (result.failed()) {\n                return result;\n            }\n            final Result<Void> voidResult = indexTemplateService.editTemplateInfoTODB(param);\n            if (voidResult.success()) {\n                String dataTypeBefore= DataTypeEnum.valueOf(oldIndexTemplate.getDataType()).getDesc();\n                String dataTypeAfter= DataTypeEnum.valueOf(param.getDataType()).getDesc();\n                String descBefore=oldIndexTemplate.getDesc();\n                String descAfter=param.getDesc();\n    \n                operateRecordService.saveOperateRecordWithManualTrigger(\n                        String.format(\"数据类型变更：【%s】->【%s】; 描述变更:【%s】->【%s】\", dataTypeBefore, dataTypeAfter,\n                                descBefore, descAfter), operator, projectId, param.getId(),\n                        OperateTypeEnum.TEMPLATE_MANAGEMENT_INFO_MODIFY);\n            }\n\n            return voidResult;\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=TemplateLogicManagerImpl||method=newEditTemplate||msg=fail to editTemplate\");\n        }\n        return Result.buildFail(\"编辑模板失败\");\n    }\n\n    @Override\n    public Result<Void> delTemplate(Integer logicTemplateId, String operator,\n                                    Integer projectId) throws AdminOperateException {\n        Integer belongToProjectId = indexTemplateService.getProjectIdByTemplateLogicId(logicTemplateId);\n        final Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(i -> i, belongToProjectId,\n            projectId);\n        if (checkProjectCorrectly.failed()) {\n            return checkProjectCorrectly;\n        }\n        List<String> phyClusterList=indexTemplatePhyService.getPhyClusterByLogicTemplateId(logicTemplateId);\n       \n        Result<ConsoleTemplateClearVO> templateClearInfo = getLogicTemplateClearInfo(\n                logicTemplateId);\n       \n        String beforeDeleteName = indexTemplateService.getNameByTemplateLogicId(logicTemplateId);\n        Result<Void> result = indexTemplateService.delTemplate(logicTemplateId, operator);\n        if (result.success()) {\n            operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"模板【%s】下线\", beforeDeleteName),\n                    operator, projectId, logicTemplateId, OperateTypeEnum.TEMPLATE_MANAGEMENT_OFFLINE);\n            //一并下线模板关联的索引\n            /**\n             * [{\"cluster\":\"Zh_test3_cluster_7-6-0-1400\",\"index\":\"zh_test3_template3_2022-07-18\"}]\n             */\n            if (templateClearInfo.success() && CollectionUtils.isNotEmpty(templateClearInfo.getData().getIndices())&&CollectionUtils.isNotEmpty(phyClusterList)) {\n    \n                BiFunction</*index*/String,/*phyCluster*/String, IndexCatCellDTO> indexPhyClusterFunc = (index, phyCluster) -> {\n                    IndexCatCellDTO indexCatCellDTO = new IndexCatCellDTO();\n                    indexCatCellDTO.setIndex(index);\n                    indexCatCellDTO.setCluster(phyCluster);\n                    return indexCatCellDTO;\n                };\n                Function</*index*/String,List<IndexCatCellDTO>> phyClusterFunc=\n                        index->phyClusterList.stream().map(phyCluster->indexPhyClusterFunc.apply(index,phyCluster))\n                                       .collect(Collectors.toList());\n    \n                List<IndexCatCellDTO> catCellList = templateClearInfo.getData().getIndices()\n                       \n                        .stream()\n                        .map(IndexCatCellWithTemplateVO::getIndex)\n                        .map(phyClusterFunc).flatMap(Collection::stream)\n            \n                        .collect(Collectors.toList());\n                SpringTool.publish(new IndexDeleteEvent(this, catCellList, projectId, operator));\n            }\n        }\n        return result;\n    }\n    \n    \n    \n\n    @Override\n    public PaginationResult<ConsoleTemplateVO> pageGetConsoleTemplateVOS(TemplateConditionDTO condition,\n                                                                         Integer projectId) throws NotFindSubclassException {\n        BaseHandle baseHandle = handleFactory.getByHandlerNamePer(TEMPLATE_LOGIC.getPageSearchType());\n        if (baseHandle instanceof TemplateLogicPageSearchHandle) {\n            TemplateLogicPageSearchHandle handle = (TemplateLogicPageSearchHandle) baseHandle;\n            return handle.doPage(condition, projectId);\n        }\n\n        LOGGER.warn(\n            \"class=TemplateLogicManagerImpl||method=pageGetConsoleClusterVOS||msg=failed to get the TemplateLogicPageSearchHandle\");\n\n        return PaginationResult.buildFail(\"获取模板分页信息失败\");\n    }\n\n    @Override\n    public Result<Void> checkTemplateValidForCreate(String templateName) {\n        if (AriusObjUtils.isNull(templateName)) {\n            return Result.buildParamIllegal(\"名字为空\");\n        }\n\n        if (templateName.length() < TEMPLATE_NAME_SIZE_MIN || templateName.length() > TEMPLATE_NAME_SIZE_MAX) {\n            return Result\n                .buildParamIllegal(String.format(\"名称长度非法, %s-%s\", TEMPLATE_NAME_SIZE_MIN, TEMPLATE_NAME_SIZE_MAX));\n        }\n\n        for (Character c : templateName.toCharArray()) {\n            if (!TEMPLATE_NAME_CHAR_SET.contains(c)) {\n                return Result.buildParamIllegal(\"名称包含非法字符, 只能包含小写字母、数字、-、_和.\");\n            }\n        }\n\n        return indexTemplateService.preCheckTemplateName(templateName);\n    }\n\n    @Override\n    public Result<Boolean> checkTemplateEditMapping(Integer templateId) {\n        IndexTemplate indexTemplate = indexTemplateService.getLogicTemplateById(templateId);\n        if (null == indexTemplate) {\n            LOGGER.error(\n                \"class=TemplateLogicManagerImpl||method=checkTemplateEditMapping||templateId={}||msg=indexTemplateLogic is empty\",\n                templateId);\n            return Result.buildFail(\"模板不存在\");\n        }\n\n        List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.getTemplateByLogicId(indexTemplate.getId());\n        if (CollectionUtils.isEmpty(templatePhyList)) {\n            return Result.buildSucc(false);\n        }\n\n        List<String> clusterPhyNameList = templatePhyList.stream().map(IndexTemplatePhy::getCluster).distinct()\n            .collect(Collectors.toList());\n        for (String clusterPhyName : clusterPhyNameList) {\n            ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterPhyName);\n            if (null == clusterPhy) {\n                return Result.buildFail(String.format(\"模板归属集群[%s]不存在\", clusterPhyName));\n            }\n\n            \n        }\n\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    public Result<Void> switchRolloverStatus(Integer templateLogicId, Integer status, String operator,\n                                             Integer projectId) {\n        if (templateLogicId == null || status == null) {\n            return Result.buildSucc();\n        }\n        Boolean newDisable = status == 0;\n        IndexTemplateConfig templateConfig = indexTemplateService.getTemplateConfig(templateLogicId);\n        if (templateConfig == null) {\n            return Result.buildFail(\"模版不存在\");\n        }\n        final Integer projectIdByTemplateLogicId = indexTemplateService.getProjectIdByTemplateLogicId(templateLogicId);\n\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectIdByTemplateLogicId, projectId);\n        if (result.failed()) {\n            return result;\n        }\n        Boolean oldDisable = templateConfig.getDisableIndexRollover();\n        if (!newDisable.equals(oldDisable)) {\n            // 如果状态不同则更新状态\n            IndexTemplateConfigDTO indexTemplateConfigDTO = ConvertUtil.obj2Obj(templateConfig,\n                IndexTemplateConfigDTO.class);\n            indexTemplateConfigDTO.setDisableIndexRollover(newDisable);\n            Result<Void> updateStatusResult = indexTemplateService.updateTemplateConfig(indexTemplateConfigDTO,\n                operator);\n            if (updateStatusResult.success()) {\n                // rollover状态修改记录(兼容开启或者关闭)\n                operateRecordService.saveOperateRecordWithManualTrigger(\n                        String.format(\"%s:rollover 状态修改为:【%s】\", TemplateOperateRecordEnum.ROLLOVER.getDesc(),\n                                (newDisable ? \"关闭\" : \"开启\")), operator, projectId, templateLogicId,\n                        OperateTypeEnum.TEMPLATE_SERVICE);\n            }\n        }\n        return Result.buildSucc();\n    }\n\n   \n\n    @Override\n    public Result<Boolean> checkTemplateEditService(Integer templateId, Integer templateSrvId) {\n        // 根据逻辑模板id获取对应的逻辑物理模板信息\n        IndexTemplateWithPhyTemplates logicTemplateWithPhysicals = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(templateId);\n\n        if (AriusObjUtils.isNull(logicTemplateWithPhysicals)\n            || CollectionUtils.isEmpty(logicTemplateWithPhysicals.getPhysicals())) {\n            LOGGER.error(\n                \"class=TemplateLogicManagerImpl||method=checkTemplateEditService||templateId={}||msg=indexTemplateLogic is empty\",\n                templateId);\n            return Result.buildFail(\"逻辑模板信息为空\");\n        }\n\n        // 获取逻辑集群对应的物理模板的物理集群名称列表\n        final Optional<Result<Boolean>> resultOptional = logicTemplateWithPhysicals.getPhysicals().stream()\n                .map(IndexTemplatePhy::getCluster).distinct().map(this::checkExistClusterNamePhy).findFirst();\n        return resultOptional.map(booleanResult -> Result.buildFailWithMsg(false, booleanResult.getMessage()))\n                .orElseGet(() -> Result.buildSucc(true));\n    }\n\n    @Override\n    public Result<Void> checkProjectAuthOnLogicTemplate(Integer logicId, Integer projectId) {\n        if (AriusObjUtils.isNull(logicId)) {\n            return Result.buildParamIllegal(\"索引id为空\");\n        }\n\n        if (AriusObjUtils.isNull(projectId)) {\n            return Result.buildParamIllegal(\"应用Id为空\");\n        }\n\n        IndexTemplate templateLogic = indexTemplateService.getLogicTemplateById(logicId);\n        if (templateLogic == null) {\n            return Result.buildNotExist(\"索引不存在\");\n        }\n\n       \n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            return Result.buildSucc();\n        }\n\n        if (!templateLogic.getProjectId().equals(projectId)) {\n            return Result.buildOpForBidden(\"您无权对该索引进行操作\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public boolean updateDCDRInfo(Integer logicId) {\n        if (!indexTemplateService.exist(logicId)) {\n            return true;\n        }\n\n        // 1. 获取dcdr标识位\n        boolean dcdrFlag = false;\n        long totalIndexCheckPointDiff = 0;\n        try {\n            IndexTemplateWithPhyTemplates logicTemplateWithPhysicals = indexTemplateService\n                .getLogicTemplateWithPhysicalsById(logicId);\n            IndexTemplatePhy slavePhyTemplate = logicTemplateWithPhysicals.getSlavePhyTemplate();\n            IndexTemplatePhy masterPhyTemplate = logicTemplateWithPhysicals.getMasterPhyTemplate();\n            if (null != masterPhyTemplate && null != slavePhyTemplate) {\n                dcdrFlag = templateDcdrManager.syncExistTemplateDCDR(masterPhyTemplate.getId(),\n                        slavePhyTemplate.getCluster());\n                \n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class={}||method=updateDCDRInfo||templateName={}\",getClass().getSimpleName(), logicId, e);\n            return false;\n        }\n       \n       \n        // 2. 获取位点差dcdr\n        if (dcdrFlag) {\n            try {\n                Tuple<Long, Long> masterAndSlaveTemplateCheckPointTuple = templateDcdrManager\n                    .getMasterAndSlaveTemplateCheckPoint(logicId);\n                totalIndexCheckPointDiff = Math\n                    .abs(masterAndSlaveTemplateCheckPointTuple.getV1() - masterAndSlaveTemplateCheckPointTuple.getV2());\n            } catch (Exception e) {\n                LOGGER.error(\"class={}||method=updateDCDRInfo||templateId={}\",\n                    getClass().getSimpleName(),logicId,  e);\n                 return false;\n            }\n    \n        }\n\n        try {\n            IndexTemplateDTO indexTemplateDTO = new IndexTemplateDTO();\n            indexTemplateDTO.setId(logicId);\n            indexTemplateDTO.setHasDCDR(dcdrFlag);\n            //如果还存在dcdr链路，则未totalIndexCheckPointDiff 否则未-1\n            indexTemplateDTO.setCheckPointDiff(Boolean.TRUE.equals(dcdrFlag)?totalIndexCheckPointDiff:-1);\n            indexTemplateService.editTemplateInfoTODB(indexTemplateDTO);\n        } catch (AdminOperateException e) {\n            LOGGER.error(\n                \"class={}||method=updateDCDRInfo||templateId={}\",\n                getClass().getSimpleName(),logicId, e);\n        }\n\n        return true;\n    }\n\n    @Override\n    public Result<List<ConsoleTemplateVO>> getTemplateVOByPhyCluster(String phyCluster) {\n        // 根据物理集群名称获取全量逻辑模板列表\n        List<IndexTemplatePhyWithLogic> templateByPhyCluster = indexTemplatePhyService\n            .getTemplateByPhyCluster(phyCluster);\n\n        // 转化为视图列表展示\n        List<ConsoleTemplateVO> consoleTemplateVOLists = new ArrayList<>();\n        templateByPhyCluster.stream()\n            .filter(indexTemplatePhyWithLogic -> indexTemplatePhyWithLogic.getLogicTemplate() != null).forEach(\n                indexTemplatePhyWithLogic -> consoleTemplateVOLists.add(buildTemplateVO(indexTemplatePhyWithLogic)));\n        return Result.buildSucc(consoleTemplateVOLists);\n    }\n\n    @Override\n    public Result<Void> clearIndices(TemplateClearDTO clearDTO, String operator, Integer projectId) {\n        List<String> indices = clearDTO.getDelIndices();\n        Integer templateId = clearDTO.getLogicId();\n        if (CollectionUtils.isEmpty(indices)) {\n            return Result.buildParamIllegal(\"清理索引不能为空\");\n        }\n\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(templateId);\n        if (null != templateLogicWithPhysical && CollectionUtils.isEmpty(templateLogicWithPhysical.getPhysicals())) {\n            return Result.buildFail(String.format(\"模板[%d]不存在Arius平台\", templateId));\n        }\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(IndexTemplateWithPhyTemplates::getProjectId,\n            templateLogicWithPhysical, projectId);\n        if (result.failed()) {\n            return result;\n        }\n\n        boolean succ = false;\n        List<IndexTemplatePhy> indexTemplatePhyList = Optional.ofNullable(templateLogicWithPhysical)\n            .map(IndexTemplateWithPhyTemplates::getPhysicals).orElse(Lists.newArrayList());\n        List<String> clusterList = Lists.newArrayList();\n        for (IndexTemplatePhy templatePhysical : indexTemplatePhyList) {\n            succ = indices.size() == esIndexService.syncBatchDeleteIndices(templatePhysical.getCluster(), indices,\n                RETRY_TIMES);\n            clusterList.add(templatePhysical.getCluster());\n\n        }\n\n        for (String cluster : clusterList) {\n            indicesManager.updateIndexFlagInvalid(cluster, indices);\n\n        }\n        String name = Optional.ofNullable(templateLogicWithPhysical).map(IndexTemplateWithPhyTemplates::getName)\n            .orElse(\"\");\n        String clearIndices = String.join(\",\", indices);\n        operateRecordService.saveOperateRecordWithManualTrigger(\n                String.format(\"清理索引模板：%s 下的索引列表：【%s】\", name, clearIndices), operator, projectId,\n                clearDTO.getLogicId(), OperateTypeEnum.TEMPLATE_SERVICE_CLEAN);\n\n        return Result.build(succ);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> adjustShard(Integer logicTemplateId, Integer shardNum, Integer projectId,\n                                    String operator) throws AdminOperateException {\n        final Integer projectIdByTemplateLogicId = indexTemplateService.getProjectIdByTemplateLogicId(logicTemplateId);\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectIdByTemplateLogicId, projectId);\n        if (result.failed()) {\n            return result;\n        }\n        List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.getTemplateByLogicId(logicTemplateId);\n        IndexTemplatePhyDTO updateParam = new IndexTemplatePhyDTO();\n        for (IndexTemplatePhy templatePhy : templatePhyList) {\n            if (templatePhy.getShard().equals(shardNum)) {\n                throw new AdminOperateException(\"该模板已经是\" + shardNum + \"分片\", FAIL);\n            }\n    \n            updateParam.setId(templatePhy.getId());\n            updateParam.setShard(shardNum);\n            boolean succ = esTemplateService.syncUpdateShardNum(templatePhy.getCluster(), templatePhy.getName(),\n                    shardNum, RETRY_TIMES);\n            if (succ) {\n                Result<Void> updateDBResult = indexTemplatePhyService.update(updateParam);\n                if (updateDBResult.failed()) {\n                    throw new AdminOperateException(updateDBResult.getMessage(), FAIL);\n                }\n                operateRecordService.saveOperateRecordWithManualTrigger(\n                        String.format(\"同步修改 es 集群 [%s] 中模板[%s]shard 数[%d]\", templatePhy.getCluster(),\n                                templatePhy.getName(), shardNum), operator, projectId, logicTemplateId,\n                        OperateTypeEnum.TEMPLATE_SERVICE_CAPACITY);\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> upgrade(Integer templateId, String operator, Integer projectId) throws AdminOperateException {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return result;\n        }\n        List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.getTemplateByLogicId(templateId);\n        if (CollectionUtils.isEmpty(templatePhyList)) {\n            return Result.buildFail(\"模板不存在\");\n        }\n        //检测集群连通状态\n        final Optional<TupleTwo<String, Boolean>> clusterConnectionStatusOption = templatePhyList.stream()\n                .map(indexTemplatePhy -> Tuples.of(indexTemplatePhy.getCluster(),\n                        esClusterService.isConnectionStatus(indexTemplatePhy.getCluster())))\n                .filter(tuple -> Boolean.FALSE.equals(tuple.v2)).findFirst();\n        if (clusterConnectionStatusOption.isPresent()) {\n            return Result.buildFail(\n                    String.format(\"集群%s故障，请检查集群状态后重试。\", clusterConnectionStatusOption.get().v1()));\n        }\n        IndexTemplatePhyDTO updateParam = new IndexTemplatePhyDTO();\n        //这里为了保证逻辑模版下所有物理模版均创建最新索引后再进行pipeline切换，需要遍历两次\n        for (IndexTemplatePhy templatePhy : templatePhyList) {\n            int version = null != templatePhy.getVersion() ? templatePhy.getVersion() : 0;\n            version = version < 0 ? 1 : version + 1;\n            /*\n            这里提前创建当天索引\n             1.避免因为getTemplateConfig失败，导致升版本后不分区索引mapping异常\n             2.避免由于事务原因，导致当天最新版本的分区索引未被创建\n             */\n            if (!preCreateManager.syncCreateTodayIndexByPhysicalId(templatePhy.getId(), version)) {\n                return Result.buildFail(\"创建当前最新版本索引失败，请稍后重试！\");\n            }\n        }\n        for (IndexTemplatePhy templatePhy : templatePhyList) {\n            final Integer beforeVersion = templatePhy.getVersion();\n            final Integer afterVersion =beforeVersion + 1;\n            updateParam.setId(templatePhy.getId());\n            updateParam.setVersion(beforeVersion + 1);\n            Result<Void> editResult = templatePhyManager.editTemplateWithoutCheck(updateParam, operator, RETRY_TIMES);\n            if (editResult.failed()) {\n                throw new AdminOperateException(editResult.getMessage(), FAIL);\n            }\n\n            preCreateManager.asyncCreateTodayAndTomorrowIndexByPhysicalId(templatePhy.getId());\n    \n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"模板 [%s] 升版本 %d->%d\", templatePhy.getName(), beforeVersion, afterVersion),\n                    operator, projectId, templateId, OperateTypeEnum.TEMPLATE_SERVICE_UPGRADED_VERSION);\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<List<ConsoleTemplateVO>> listTemplateVOByLogicCluster(String clusterLogicName, Integer projectId) {\n        ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByNameAndProjectId(clusterLogicName, projectId);\n        if (clusterLogic == null) {\n            return Result.buildFail();\n        }\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogic.getId());\n        if (clusterRegion == null) {\n            return Result.buildFail();\n        }\n        Predicate<IndexTemplate> filterProjectId = indexTemplate -> AuthConstant.SUPER_PROJECT_ID.equals(projectId)\n                                                                    || Objects.equals(indexTemplate.getProjectId(),\n                projectId);\n        Result<List<IndexTemplate>> listResult = indexTemplateService\n            .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n        List<ConsoleTemplateVO> vos = listResult.getData().stream()\n                .filter(filterProjectId)\n                \n                .map(indexTemplate -> {\n            ConsoleTemplateVO vo = new ConsoleTemplateVO();\n            BeanUtils.copyProperties(indexTemplate, vo);\n            return vo;\n        }).collect(Collectors.toList());\n\n        return Result.buildSucc(vos);\n    }\n\n    /**\n     * @param projectId\n     * @return\n     */\n    @Override\n    public Result<List<Tuple<String, String>>> listLogicTemplatesByProjectId(Integer projectId) {\n        return indexTemplateService.listLogicTemplatesByProjectId(projectId);\n    }\n\n    /**\n     * @param logicId\n     * @return\n     */\n    @Override\n    public Result<List<TemplateCyclicalRollInfoVO>> getCyclicalRollInfo(Integer logicId) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n        if (templateLogicWithPhysical == null) {\n            return Result.buildParamIllegal(INDEX_NOT_EXISTS_TIPS);\n        }\n\n        List<CatIndexResult> catIndexResults = Lists.newArrayList();\n\n        List<IndexTemplatePhy> physicalMasters = templateLogicWithPhysical.fetchMasterPhysicalTemplates();\n        for (IndexTemplatePhy physicalMaster : physicalMasters) {\n            try {\n                catIndexResults.addAll(indicesManager.listIndexCatInfoByTemplatePhyId(physicalMaster.getId()));\n            } catch (Exception e) {\n                LOGGER.warn(\"class=TemplateLogicManagerImpl||method=getCyclicalRollInfo||logicId={}||errMsg={}\",\n                    logicId, e.getMessage(), e);\n            }\n        }\n        return Result.buildSucc(ConvertUtil.list2List(catIndexResults, TemplateCyclicalRollInfoVO.class));\n    }\n\n    /**\n     * @param logicId\n     * @return\n     */\n    @Override\n    public Result<ConsoleTemplateRateLimitVO> getTemplateRateLimit(Integer logicId) {\n        List<IndexTemplatePhy> indexTemplatePhysicalInfo = indexTemplatePhyService.getTemplateByLogicId(logicId);\n        ConsoleTemplateRateLimitVO consoleTemplateRateLimitVO = new ConsoleTemplateRateLimitVO();\n        IndexTemplatePhy indexTemplatePhysicalMasterInfo = new IndexTemplatePhy();\n        for (IndexTemplatePhy item : indexTemplatePhysicalInfo) {\n            if (TemplateDeployRoleEnum.MASTER.getCode().equals(item.getRole())) {\n                indexTemplatePhysicalMasterInfo = item;\n            }\n        }\n        consoleTemplateRateLimitVO.setRateLimit(templatePipelineManager.getRateLimit(indexTemplatePhysicalMasterInfo));\n        return Result.buildSucc(consoleTemplateRateLimitVO);\n    }\n\n    /**\n     * @param logicId\n     * @param projectId\n     * @return\n     */\n    @Override\n    public Result<ConsoleTemplateDetailVO> getDetailVoByLogicId(Integer logicId, Integer projectId) {\n        if (Objects.isNull(logicId)) {\n            return Result.buildSucc();\n        }\n        IndexTemplateWithCluster indexTemplateLogicWithCluster = indexTemplateService\n            .getLogicTemplateWithCluster(logicId);\n\n        if (null == indexTemplateLogicWithCluster) {\n            return Result.buildFail(\"模板对应资源不存在!\");\n        }\n\n        ConsoleTemplateDetailVO consoleTemplateDetail = ConvertUtil.obj2Obj(indexTemplateLogicWithCluster,\n            ConsoleTemplateDetailVO.class);\n\n        consoleTemplateDetail.setCyclicalRoll(indexTemplateLogicWithCluster.getExpression().endsWith(\"*\"));\n        //根据模板resourceId project获取逻辑集群\n         ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdAndProjectId(\n                    consoleTemplateDetail.getResourceId(), consoleTemplateDetail.getProjectId());\n        // supperApp显示物理集群，其他项目显示逻辑集群\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            List<IndexTemplatePhy> indexTemplatePhyList = indexTemplatePhyService.getTemplateByLogicId(logicId);\n            String phyClusters = indexTemplatePhyList.stream().sorted(Comparator.comparing(IndexTemplatePhy::getRole))\n                    .map(IndexTemplatePhy::getCluster).collect(Collectors.joining(\",\"));\n            consoleTemplateDetail.setCluster(phyClusters);\n        } else {\n            Optional.ofNullable(clusterLogic).map(ClusterLogic::getName).ifPresent(consoleTemplateDetail::setCluster);\n        }\n    \n        // 逻辑集群设置集群类型与等级\n        Optional.ofNullable(clusterLogic).ifPresent(cl -> {\n            consoleTemplateDetail.setClusterLevel(cl.getLevel());\n            consoleTemplateDetail.setClusterType(cl.getType());\n        });\n        consoleTemplateDetail.setAppName(\n                projectService.getProjectBriefByProjectId(indexTemplateLogicWithCluster.getProjectId())\n                        .getProjectName());\n        consoleTemplateDetail.setIndices(getLogicTemplateIndices(logicId));\n        consoleTemplateDetail.setEditable(true);\n        // 获取 indexRollover 功能开启状态\n        Optional.ofNullable(indexTemplateService.getTemplateConfig(logicId))\n                .map(IndexTemplateConfig::getDisableIndexRollover)\n                .ifPresent(consoleTemplateDetail::setDisableIndexRollover);\n        return Result.buildSucc(consoleTemplateDetail);\n    }\n\n    /**\n     * @param logicId\n     * @return\n     */\n    @Override\n    public Result<ConsoleTemplateClearVO> getLogicTemplateClearInfo(Integer logicId) throws AmsRemoteException {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (templateLogicWithPhysical == null) {\n            return Result.buildParamIllegal(INDEX_NOT_EXISTS_TIPS);\n        }\n\n        if (!templateLogicWithPhysical.hasPhysicals()) {\n            return Result.buildParamIllegal(\"索引没有部署\");\n        }\n\n        ConsoleTemplateClearVO consoleTemplateClearVO = new ConsoleTemplateClearVO();\n        consoleTemplateClearVO.setLogicId(templateLogicWithPhysical.getId());\n        consoleTemplateClearVO.setName(templateLogicWithPhysical.getName());\n        consoleTemplateClearVO.setIndices(\n            indicesManager.listIndexCatCellWithTemplateByTemplatePhyId(templateLogicWithPhysical.getMasterPhyTemplate().getId()));\n        consoleTemplateClearVO.setAccessApps(getLogicTemplateProjectAccess(logicId));\n\n        return Result.buildSucc(consoleTemplateClearVO);\n    }\n\n    /**\n     * @param logicId\n     * @return\n     */\n    @Override\n    public Result<ConsoleTemplateDeleteVO> getLogicTemplateDeleteInfo(Integer logicId) throws AmsRemoteException {\n        //与上清理索引信息接口实现合并\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n        if (templateLogicWithPhysical == null) {\n            return Result.buildParamIllegal(INDEX_NOT_EXISTS_TIPS);\n        }\n\n        ConsoleTemplateDeleteVO consoleTemplateDeleteVO = new ConsoleTemplateDeleteVO();\n        consoleTemplateDeleteVO.setLogicId(templateLogicWithPhysical.getId());\n        consoleTemplateDeleteVO.setName(templateLogicWithPhysical.getName());\n\n        if (!templateLogicWithPhysical.hasPhysicals()) {\n            return Result.buildParamIllegal(\"索引没有部署\");\n        }\n\n        consoleTemplateDeleteVO.setAccessApps(getLogicTemplateProjectAccess(logicId));\n\n        return Result.buildSucc(consoleTemplateDeleteVO);\n    }\n    \n    /**\n     *\n     * 它通过其逻辑 ID 更新模板的健康状况。\n     * {@link  TemplateHealthEnum}\n     * @param logicId 模板的 logicId。\n     * @return 一个布尔值。\n     */\n    @Override\n    public boolean updateTemplateHealthByLogicId(Integer logicId) {\n        if (!indexTemplateService.exist(logicId)) {\n            return true;\n        }\n        IndexTemplateWithPhyTemplates indexTemplateWithPhyTemplates = indexTemplateService.getLogicTemplateWithPhysicalsById(\n                logicId);\n        String masterCluster = Optional.ofNullable(indexTemplateWithPhyTemplates)\n                .map(IndexTemplateWithPhyTemplates::getMasterPhyTemplate).map(IndexTemplatePhy::getCluster)\n                .orElse(null);\n        if (Objects.isNull(masterCluster)) {\n            LOGGER.warn(\n                    \"class={}||method=updateTemplateHealthByLogicId||logicId={}||error=don't find index template cluster\",\n                    getClass().getSimpleName(), logicId);\n            return false;\n        }\n        final IndexTemplatePO templatePO = new IndexTemplatePO();\n        templatePO.setId(logicId);\n        if (!esClusterService.isConnectionStatus(masterCluster)) {\n            LOGGER.warn(\n                    \"class={}||method=updateTemplateHealthByLogicId||logicId={}||error=don't find index template cluster\",\n                    getClass().getSimpleName(), logicId);\n            /**\n             * {@link TemplateHealthEnum}\n             */\n            templatePO.setHealth(TemplateHealthEnum.UNKNOWN.getCode());\n            indexTemplateService.update(templatePO);\n            return true;\n        \n        }\n\n        // 通配符value\n        String wildcard = indexTemplateWithPhyTemplates.getMasterPhyTemplate().getName() + \"*\";\n        // 从 arius_stats_index_info 元数据索引中获取模版所有索引的health状态，根据index health确定模版health。\n        try {\n            Integer templateHealthCode = esTemplateService.getTemplateHealthCode(masterCluster, wildcard);\n            templatePO.setHealth(templateHealthCode);\n            boolean updateResult = indexTemplateService.update(templatePO);\n            if(!updateResult) {\n                LOGGER.error(\"class=TemplateLogicManagerImpl||method=updateTemplateHealthByLogicId||logicId={}, update DB failed!\", logicId);\n                return false;\n            }\n        }catch (Exception e) {\n            LOGGER.error(\"class=TemplateLogicManagerImpl||method=updateTemplateHealthByLogicId||logicId={}, update template health failed\", logicId);\n            return false;\n        }\n\n        return true;\n    }\n    \n    /**\n     * @param consoleTemplateRateLimitDTO\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    @Override\n    public Result<Void> updateTemplateWriteRateLimit(ConsoleTemplateRateLimitDTO consoleTemplateRateLimitDTO,\n                                                     String operator, Integer projectId) {\n        final Integer projectIdByTemplateLogicId = indexTemplateService\n            .getProjectIdByTemplateLogicId(consoleTemplateRateLimitDTO.getLogicId());\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectIdByTemplateLogicId, projectId);\n        if (result.failed()) {\n            return result;\n        }\n        // 判断调整比例是否在区间内\n        int percent = (int) Math.ceil(\n            100.0 * (consoleTemplateRateLimitDTO.getAdjustRateLimit() - consoleTemplateRateLimitDTO.getCurRateLimit())\n                                      / consoleTemplateRateLimitDTO.getCurRateLimit());\n        if (percent < MIN_PERCENT || percent > MAX_PERCENT) {\n            return Result.buildFail(\"限流调整值变化太大，一次调整比例在100倍以内\");\n        }\n        try {\n            Result<Void> updateTemplateWriteRateLimit = indexTemplateService\n                .updateTemplateWriteRateLimit(consoleTemplateRateLimitDTO);\n            if (updateTemplateWriteRateLimit.success()) {\n                operateRecordService.saveOperateRecordWithManualTrigger(\n                        String.format(\"数据库写入限流值修改 %s->%s\", consoleTemplateRateLimitDTO.getCurRateLimit(),\n                                consoleTemplateRateLimitDTO.getAdjustRateLimit()), operator, projectId,\n                        consoleTemplateRateLimitDTO.getLogicId(),\n                        OperateTypeEnum.QUERY_TEMPLATE_DSL_CURRENT_LIMIT_ADJUSTMENT);\n            }\n            return updateTemplateWriteRateLimit;\n        } catch (ESOperateException e) {\n            LOGGER.info(\"限流调整失败\", e);\n            return Result.buildFail(\"限流调整失败！\");\n        }\n    }\n    \n   \n    /**\n     * 用索引模板的写操作。\n     *\n     * @param templateId 要操作的模板的id\n     * @param status 0：否，1：是\n     * @param operator 触发操作的操作员\n     * @param projectId 项目编号\n     * @return Result<Void>\n     */\n    @Override\n    public Result<Void> blockWrite(Integer templateId, Boolean status, String operator, Integer projectId) {\n        IndexTemplatePO logicTemplate = indexTemplateService.getLogicTemplatePOById(templateId);\n    \n        if (Objects.isNull(logicTemplate)) {\n            return Result.buildFail(\"逻辑模板不存在\");\n        }\n        Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(IndexTemplatePO::getProjectId,\n                logicTemplate, projectId);\n        if (checkProjectCorrectly.failed()) {\n            return checkProjectCorrectly;\n        }\n    \n        Result<Void> result = indexTemplateService.updateBlockWriteState(templateId, status);\n        if (result.success()) {\n            // 是否禁写，0：否，1：是\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    Objects.equals(status, Boolean.TRUE) ? \"禁写\" : \"开启写\", operator, projectId, templateId,\n                    OperateTypeEnum.TEMPLATE_MANAGEMENT_CREATE);\n        }\n    \n        return result;\n    }\n    \n    \n    /**\n     * 用于索引模板的读取。\n     *\n     * @param templateId 要操作的模板的id\n     * @param status 0：否，1：是\n     * @param operator 触发操作的用户\n     * @param projectId 项目编号\n     * @return Result<Void>\n     */\n    @Override\n    public Result<Void> blockRead(Integer templateId, Boolean status, String operator, Integer projectId) {\n        IndexTemplatePO logicTemplate = indexTemplateService.getLogicTemplatePOById(templateId);\n    \n        if (Objects.isNull(logicTemplate)) {\n            return Result.buildFail(\"逻辑模板不存在\");\n        }\n        Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(IndexTemplatePO::getProjectId,\n                logicTemplate, projectId);\n        if (checkProjectCorrectly.failed()) {\n            return checkProjectCorrectly;\n        }\n        Result<Void> result = indexTemplateService.updateBlockReadState(templateId, status);\n        if (result.success()) {\n            // 是否禁写，0：否，1：是\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    Objects.equals(status, Boolean.TRUE) ? \"禁读\" : \"开启读\", operator, projectId, templateId,\n                    OperateTypeEnum.TEMPLATE_MANAGEMENT_CREATE);\n        }\n    \n        return result;\n    }\n    /**************************************** private method ***************************************************/\n    /**\n    * 获取逻辑模板索引列表\n    *\n    * @param logicId 逻辑ID\n    * @return\n    */\n    private List<String> getLogicTemplateIndices(Integer logicId) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (null != templateLogicWithPhysical && null != templateLogicWithPhysical.getMasterPhyTemplate()) {\n            return indexTemplatePhyService\n                .getMatchNoVersionIndexNames(templateLogicWithPhysical.getMasterPhyTemplate().getId());\n        }\n\n        return new ArrayList<>();\n    }\n\n    /**\n     * 校验逻辑模板Master ROLE物理模板是否存在\n     * @param templateLogic 逻辑模板\n     * @param projectIds 项目ids\n     * @return\n     */\n    private Result<Void> checkLogicTemplateMeta(IndexTemplate templateLogic, List<Integer> projectIds) {\n        List<String> errMsg = Lists.newArrayList();\n\n        if (!projectIds.contains(templateLogic.getProjectId())) {\n            errMsg.add(\"所属PROJECT ID不存在：\" + templateLogic.getProjectId());\n        }\n\n        List<IndexTemplatePhy> templatePhysicals = indexTemplatePhyService.getTemplateByLogicId(templateLogic.getId());\n\n        if (CollectionUtils.isNotEmpty(templatePhysicals)) {\n            List<IndexTemplatePhy> templatePhysicalsMaster = templatePhysicals.stream()\n                .filter(templatePhysical -> templatePhysical.getRole().equals(TemplateDeployRoleEnum.MASTER.getCode()))\n                .collect(Collectors.toList());\n\n            if (CollectionUtils.isEmpty(templatePhysicalsMaster)) {\n                errMsg.add(\"没有部署master：\" + templateLogic.getName() + \"(\" + templateLogic.getId() + \")\");\n            }\n        }\n\n        if (CollectionUtils.isEmpty(errMsg)) {\n            return Result.buildSucc();\n        }\n\n        return Result.build(ResultType.ADMIN_META_ERROR.getCode(), String.join(\",\", errMsg));\n    }\n\n    /**\n     * 构建逻辑模板视图\n     */\n    private ConsoleTemplateVO buildTemplateVO(IndexTemplatePhyWithLogic param) {\n        ConsoleTemplateVO consoleTemplateVO = new ConsoleTemplateVO();\n        if (param != null) {\n            consoleTemplateVO = ConvertUtil.obj2Obj(param.getLogicTemplate(), ConsoleTemplateVO.class);\n            consoleTemplateVO.setClusterPhies(Collections.singletonList(param.getCluster()));\n        }\n        return consoleTemplateVO;\n    }\n\n\n\n    /**\n     * 获取逻辑模板详情\n     *\n     * @param indexTemplateLogicWithCluster 逻辑集群\n     * @param projectTemplateAuths                 project模板权限\n     * @param logicTemplateValues              逻辑模板健康分\n     */\n    private IndexTemplateLogicAggregate fetchTemplateAggregate(IndexTemplateWithCluster indexTemplateLogicWithCluster,\n                                                               Map<Integer, ProjectTemplateAuth> projectTemplateAuths,\n                                                               Map<Integer, IndexTemplateValue> logicTemplateValues,\n                                                               List<Integer> hasDCDRLogicIds) {\n\n        IndexTemplateLogicAggregate indexTemplateLogicAggregate = new IndexTemplateLogicAggregate();\n\n        indexTemplateLogicAggregate.setIndexTemplateLogicWithCluster(indexTemplateLogicWithCluster);\n        indexTemplateLogicAggregate\n            .setProjectTemplateAuth(projectTemplateAuths.get(indexTemplateLogicWithCluster.getId()));\n        indexTemplateLogicAggregate\n            .setIndexTemplateValue(logicTemplateValues.get(indexTemplateLogicWithCluster.getId()));\n        indexTemplateLogicAggregate.setHasDCDR(hasDCDRLogicIds.contains(indexTemplateLogicWithCluster.getId()));\n\n        return indexTemplateLogicAggregate;\n    }\n\n\n\n    /**\n     * 校验物理集群的合法性\n     * @param clusterPhyName 物理集群\n     * @return 校验结果\n     */\n    private Result<Boolean> checkExistClusterNamePhy(String clusterPhyName) {\n        \n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterPhyName);\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildFail(String.format(\"模板归属集群[%s]不存在\", clusterPhyName));\n        }\n        return Result.buildSucc();\n    }\n\n    private IndexTemplateConfig getDefaultTemplateConfig(Integer logicId) {\n        IndexTemplateConfig indexTemplateConfig = new IndexTemplateConfig();\n        indexTemplateConfig.setLogicId(logicId);\n        indexTemplateConfig.setAdjustTpsFactor(1.0);\n        indexTemplateConfig.setAdjustShardFactor(1.0);\n        indexTemplateConfig.setDynamicLimitEnable(AdminConstant.YES);\n        indexTemplateConfig.setMappingImproveEnable(AdminConstant.NO);\n        indexTemplateConfig.setIsSourceSeparated(AdminConstant.NO);\n        indexTemplateConfig.setDisableSourceFlags(false);\n        indexTemplateConfig.setPreCreateFlags(true);\n        indexTemplateConfig.setShardNum(1);\n        indexTemplateConfig.setDisableIndexRollover(false);\n        return indexTemplateConfig;\n    }\n\n    /**\n     * 记录模板配置\n     * @param param 模板配置参数\n     */\n    private Result<Void> insertTemplateConfig(IndexTemplateDTO param) {\n        IndexTemplateConfig defaultTemplateConfig = getDefaultTemplateConfig(param.getId());\n        defaultTemplateConfig.setDisableSourceFlags(false);\n        if (param.getDisableIndexRollover() != null) {\n            defaultTemplateConfig.setDisableIndexRollover(param.getDisableIndexRollover());\n        }\n\n        if (param.getPreCreateFlags() != null) {\n            defaultTemplateConfig.setPreCreateFlags(param.getPreCreateFlags());\n        }\n\n        if (param.getShardNum() != null) {\n            defaultTemplateConfig.setShardNum(param.getShardNum());\n        }\n        return indexTemplateService.insertTemplateConfig(defaultTemplateConfig);\n    }\n\n    private IndexTemplateDTO buildTemplateDTO(IndexTemplateWithCreateInfoDTO param, Integer projectId) {\n        IndexTemplateDTO indexTemplateDTO = ConvertUtil.obj2Obj(param, IndexTemplateDTO.class);\n\n        indexTemplateDTO.setProjectId(projectId);\n\n        // 新建模版默认disableIndexRollover字段为true\n        indexTemplateDTO.setDisableIndexRollover(true);\n\n        buildExtraField(indexTemplateDTO);\n        buildCyclicalRoll(indexTemplateDTO, param);\n        buildShardNum(indexTemplateDTO, param);\n        buildPhysicalInfo(indexTemplateDTO, param);\n        //如果是分区模版\n        final boolean isExpression =\n                Optional.ofNullable(indexTemplateDTO.getExpression()).map(expression->expression.endsWith(\n                \"*\")).orElse(false);\n        List<Integer> openSrvList=Lists.newArrayList();\n        if (Boolean.TRUE.equals(isExpression)) {\n            openSrvList.add(TemplateServiceEnum.TEMPLATE_PRE_CREATE.getCode());\n            openSrvList.add(TemplateServiceEnum.TEMPLATE_DEL_EXPIRE.getCode());\n        }\n        final ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(\n                indexTemplateDTO.getResourceId());\n        final TupleTwo</*dcdrExist*/Boolean,/*pipelineExist*/ Boolean> existDCDRAndPipelineModule = esClusterNodeService.existDCDRAndPipelineModule(\n                clusterRegion.getPhyClusterName());\n        if (Boolean.TRUE.equals(existDCDRAndPipelineModule.v2)) {\n            openSrvList.add(TemplateServiceEnum.TEMPLATE_PIPELINE.getCode());\n        }\n        // 如果存在 dcdr 插件，则开启 dcdr 服务\n        if (Boolean.TRUE.equals(existDCDRAndPipelineModule.v1)) {\n            openSrvList.add(TemplateServiceEnum.TEMPLATE_DCDR.getCode());\n        }\n        if (CollectionUtils.isNotEmpty(openSrvList)) {\n            //如果集群支持pipeline\n            indexTemplateDTO.setOpenSrv(ConvertUtil.list2String(openSrvList, \",\"));\n        }\n      \n\n        return indexTemplateDTO;\n    }\n\n    private void buildExtraField(IndexTemplateDTO indexTemplateDTO) {\n        indexTemplateDTO.setIngestPipeline(indexTemplateDTO.getName());\n        indexTemplateDTO.setDiskSize(indexTemplateDTO.getDiskSize());\n        indexTemplateDTO.setQuota(indexTemplateDTO.getDiskSize());\n\n        if (null == indexTemplateDTO.getDesc()) {\n            indexTemplateDTO.setDesc(\"\");\n        }\n    }\n\n    private void buildCyclicalRoll(IndexTemplateDTO indexTemplateDTO, IndexTemplateWithCreateInfoDTO param) {\n        if (!param.getCyclicalRoll()) {\n            indexTemplateDTO.setExpression(param.getName());\n            indexTemplateDTO.setExpireTime(-1);\n        } else {\n            indexTemplateDTO.setExpression(param.getName() + \"*\");\n            // 数据不会过期，必须按月滚动\n            if (param.getExpireTime() < 0) {\n                indexTemplateDTO.setDateFormat(AdminConstant.YY_MM_DATE_FORMAT);\n            } else {\n                //每天的数据增量大于200G或者保存时长小于30天 按天存储\n                double incrementPerDay = param.getDiskSize() / param.getExpireTime();\n                if (incrementPerDay >= 200.0 || param.getExpireTime() <= 30) {\n                    if (StringUtils.isNotBlank(param.getDateField())\n                        && !AdminConstant.MM_DD_DATE_FORMAT.equals(param.getDateField())) {\n                        indexTemplateDTO.setDateFormat(AdminConstant.YY_MM_DD_DATE_FORMAT);\n                    }\n                } else {\n                    indexTemplateDTO.setDateFormat(AdminConstant.YY_MM_DATE_FORMAT);\n                }\n            }\n        }\n\n        if (null == indexTemplateDTO.getDateFormat()) {\n            indexTemplateDTO.setDateFormat(\"\");\n        }\n\n        if (null == indexTemplateDTO.getDateField()) {\n            indexTemplateDTO.setDateField(\"\");\n        }\n\n        if (null == indexTemplateDTO.getDateFieldFormat()) {\n            indexTemplateDTO.setDateFieldFormat(\"\");\n        }\n    }\n\n    private void buildPhysicalInfo(IndexTemplateDTO indexTemplateDTO, IndexTemplateWithCreateInfoDTO param) {\n        IndexTemplatePhyDTO indexTemplatePhyDTO = ConvertUtil.obj2Obj(indexTemplateDTO, IndexTemplatePhyDTO.class);\n\n        indexTemplatePhyDTO.setLogicId(NOT_CHECK);\n        indexTemplatePhyDTO.setGroupId(UUID.randomUUID().toString());\n        indexTemplatePhyDTO.setRole(TemplateDeployRoleEnum.MASTER.getCode());\n        indexTemplatePhyDTO.setShard(indexTemplateDTO.getShardNum());\n        indexTemplatePhyDTO.setDefaultWriterFlags(true);\n\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(param.getResourceId());\n        indexTemplatePhyDTO.setCluster(clusterRegion.getPhyClusterName());\n        indexTemplatePhyDTO.setRegionId(clusterRegion.getId().intValue());\n\n        Integer clusterSettingHotDay = templateColdManager.fetchClusterDefaultHotDay(clusterRegion.getPhyClusterName());\n        if (clusterSettingHotDay > 0) {\n            indexTemplateDTO.setHotTime(clusterSettingHotDay);\n        } else {\n            indexTemplateDTO.setHotTime(-1);\n        }\n\n        if (StringUtils.isNotBlank(param.getSetting())) {\n            indexTemplatePhyDTO.setSettings(param.getSetting());\n        } else {\n            indexTemplatePhyDTO.setSettings(\"{}\");\n        }\n\n        if (StringUtils.isNotBlank(param.getMapping())) {\n            AriusTypeProperty ariusTypeProperty = new AriusTypeProperty();\n           \n            ariusTypeProperty.setTypeName(DEFAULT_INDEX_MAPPING_TYPE);\n            final JSONObject mappings = JSON.parseObject(param.getMapping());\n            if (mappings.containsKey(DYNAMIC_TEMPLATES)) {\n                ariusTypeProperty.setDynamicTemplates(mappings.getJSONArray(DYNAMIC_TEMPLATES));\n            }\n            if (mappings.containsKey(PROPERTIES)){\n                ariusTypeProperty.setProperties(mappings.getJSONObject(PROPERTIES));\n            }\n            \n            \n            indexTemplatePhyDTO.setMappings(\n                ariusTypeProperty.toMappingJSON().getJSONObject(DEFAULT_INDEX_MAPPING_TYPE).toJSONString());\n        } else {\n            indexTemplatePhyDTO.setMappings(\"{}\");\n        }\n\n        indexTemplateDTO.setPhysicalInfos(Lists.newArrayList(indexTemplatePhyDTO));\n    }\n\n    private void buildShardNum(IndexTemplateDTO indexTemplateDTO, IndexTemplateWithCreateInfoDTO param) {\n        if (param.getCyclicalRoll()) {\n            int expireTime = param.getExpireTime();\n            if (expireTime < 0) {\n                // 如果数据永不过期，平台会按着180天来计算每日数据增量，最终用于生成模板shard\n                expireTime = 180;\n            }\n\n            if (TemplateUtils.isSaveByDay(indexTemplateDTO.getDateFormat())) {\n                // 按天滚动\n                indexTemplateDTO.setShardNum(genShardNumBySize(param.getDiskSize() / expireTime));\n            } else {\n                // 按月滚动\n                indexTemplateDTO.setShardNum(genShardNumBySize((param.getDiskSize() / expireTime) * 30));\n            }\n        } else {\n            indexTemplateDTO.setShardNum(genShardNumBySize(param.getDiskSize()));\n        }\n    }\n\n    private Integer genShardNumBySize(Double size) {\n        double shardNumCeil = Math.ceil(size / G_PER_SHARD);\n        return (int) shardNumCeil;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/impl/TemplatePhyManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.MILLIS_PER_DAY;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.EDIT;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum.MASTER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum.SLAVE;\nimport static com.didichuxing.datachannel.arius.admin.common.util.IndexNameFactory.genIndexNameClear;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.INDEX_SHARD_NUM;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.TEMPLATE_INDEX_INCLUDE_NODE_NAME;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplatePhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.precreate.PreCreateManager;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.IndexTemplatePhysicalConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplatePhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplatePhysicalCopyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplatePhysicalUpgradeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplatePhyVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.IndexTemplatePhysicalVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TemplateOperateRecordEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplatePhysicalStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.PhysicalTemplateAddEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.PhysicalTemplateModifyEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusIndexTemplateSetting;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusDateUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusIndexMappingConfigUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameFactory;\nimport com.didichuxing.datachannel.arius.admin.common.util.TemplateUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.impl.IndexTemplatePhyServiceImpl;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.TemplateConfig;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Sets;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Component\npublic class TemplatePhyManagerImpl implements TemplatePhyManager {\n\n    private static final ILog               LOGGER                       = LogFactory\n        .getLog(IndexTemplatePhyServiceImpl.class);\n\n    public static final Integer             NOT_CHECK                    = -100;\n    private static final Integer            INDEX_OP_OK                  = 0;\n    private static final Integer            TOMORROW_INDEX_NOT_CREATE    = 1;\n    private static final Integer            EXPIRE_INDEX_NOT_DELETE      = 2;\n    private static final Integer            INDEX_ALL_ERR                = TOMORROW_INDEX_NOT_CREATE\n                                                                           + EXPIRE_INDEX_NOT_DELETE;\n\n    private static final String             TEMPLATE_PHYSICAL_ID_IS_NULL = \"物理模板id为空\";\n\n    private static final String             TEMPLATE_PHYSICAL_NOT_EXISTS = \"物理模板不存在\";\n\n    private static final String             CHECK_FAIL_MSG               = \"check fail||msg={}\";\n\n    public static final int                 MIN_SHARD_NUM                = 1;\n    public static final int                 MAX_VERSION                  = 9;\n\n    @Autowired\n    private OperateRecordService            operateRecordService;\n\n    @Autowired\n    private ClusterPhyService               clusterPhyService;\n\n    \n\n    @Autowired\n    private ESTemplateService               esTemplateService;\n\n    @Autowired\n    private PreCreateManager                preCreateManager;\n\n    @Autowired\n    private ClusterRoleHostService          clusterRoleHostService;\n\n    @Autowired\n    private IndexTemplateService            indexTemplateService;\n\n    @Autowired\n    private IndexTemplatePhyService         indexTemplatePhyService;\n    @Autowired\n    private IndexTemplatePhyService         physicalService;\n\n    @Autowired\n    private ProjectLogicTemplateAuthService projectLogicTemplateAuthService;\n\n    @Autowired\n    private ProjectService                  projectService;\n\n    @Override\n    public boolean checkMeta() {\n        List<IndexTemplatePhy> templatePhysicals = indexTemplatePhyService.listTemplate();\n\n        List<IndexTemplate> templateLogics = indexTemplateService.listAllLogicTemplates();\n        Map<Integer, IndexTemplate> logicId2IndexTemplateLogicMap = ConvertUtil.list2Map(templateLogics,\n            IndexTemplate::getId);\n\n        Multimap<String, IndexTemplatePhy> cluster2IndexTemplatePhysicalMultiMap = ConvertUtil\n            .list2MulMap(templatePhysicals, IndexTemplatePhy::getCluster);\n\n        Set<String> esClusters = clusterPhyService.listAllClusters().stream().map(ClusterPhy::getCluster)\n            .collect(Collectors.toSet());\n\n        for (String cluster : cluster2IndexTemplatePhysicalMultiMap.keySet()) {\n            int tomorrowIndexNotCreateCount = 0;\n            int expireIndexNotDeleteCount = 0;\n\n            Collection<IndexTemplatePhy> clusterTemplates = cluster2IndexTemplatePhysicalMultiMap.get(cluster);\n\n            for (IndexTemplatePhy templatePhysical : clusterTemplates) {\n                try {\n                    Result<Void> result = checkMetaInner(templatePhysical, logicId2IndexTemplateLogicMap, esClusters);\n                    if (result.success()) {\n                        LOGGER.info(\"class=TemplatePhyManagerImpl||method=metaCheck||msg=succ||physicalId={}\",\n                            templatePhysical.getId());\n                    } else {\n                        LOGGER.warn(\n                            \"class=TemplatePhyManagerImpl||method=metaCheck||msg=fail||physicalId={}||failMsg={}\",\n                            templatePhysical.getId(), result.getMessage());\n                    }\n                    int indexOpResult = checkIndexCreateAndExpire(templatePhysical, logicId2IndexTemplateLogicMap);\n                    if (indexOpResult == TOMORROW_INDEX_NOT_CREATE || indexOpResult == INDEX_ALL_ERR) {\n                        tomorrowIndexNotCreateCount++;\n                    }\n                    if (indexOpResult == EXPIRE_INDEX_NOT_DELETE || indexOpResult == INDEX_ALL_ERR) {\n                        expireIndexNotDeleteCount++;\n                    }\n\n                } catch (Exception e) {\n                    LOGGER.error(\"class=TemplatePhyServiceImpl||method=metaCheck||errMsg={}||physicalId={}||\",\n                        e.getMessage(), templatePhysical.getId(), e);\n                }\n            }\n        }\n\n        return true;\n    }\n\n    @Override\n    public void syncMeta(Long physicalId, int retryCount) throws ESOperateException {\n\n        // 从数据库获取物理模板\n        IndexTemplatePhy indexTemplatePhy = indexTemplatePhyService.getTemplateById(physicalId);\n        if (indexTemplatePhy == null) {\n            return;\n        }\n\n        // 从ES集群获取模板配置\n        TemplateConfig templateConfig = esTemplateService.syncGetTemplateConfig(indexTemplatePhy.getCluster(),\n            indexTemplatePhy.getName());\n\n        if (templateConfig == null) {\n            // es集群中还没有模板，创建\n            esTemplateService.syncCreate(indexTemplatePhy.getCluster(), indexTemplatePhy.getName(),\n                indexTemplatePhy.getExpression(), indexTemplatePhy.getShard(), indexTemplatePhy.getShardRouting(),\n                retryCount);\n\n        } else {\n            // 校验表达式\n            if (!indexTemplatePhy.getExpression().equals(templateConfig.getTemplate())\n                && esTemplateService.syncUpdateExpression(indexTemplatePhy.getCluster(), indexTemplatePhy.getName(),\n                    indexTemplatePhy.getExpression(), retryCount)) {\n                // 表达式不同（表达式发生变化），同步到ES集群\n                LOGGER.info(\n                    \"class=TemplatePhyManagerImpl||method=syncMeta||msg=syncUpdateExpression succ||template={}||srcExp={}||tgtExp={}\",\n                    indexTemplatePhy.getName(), templateConfig.getTemplate(), indexTemplatePhy.getExpression());\n            }\n\n            // 标志shard是否需要修改\n            Map<String, String> settings = templateConfig.getSetttings();\n            String shardNum = settings.get(INDEX_SHARD_NUM);\n\n            // 校验shard个数\n            if (!String.valueOf(indexTemplatePhy.getShard()).equals(shardNum)) {\n                shardNum = String.valueOf(indexTemplatePhy.getShard());\n            }\n\n            if (esTemplateService.syncUpdateShard(indexTemplatePhy.getCluster(), indexTemplatePhy.getName(),\n                Integer.valueOf(shardNum), indexTemplatePhy.getShardRouting(), retryCount)) {\n                // 同步变化到ES集群\n                LOGGER.info(\n                    \"class=TemplatePhyManagerImpl||method=syncMeta||msg=syncUpdateShard succ||template={}||srcShard={}\",\n                    indexTemplatePhy.getName(), settings.get(INDEX_SHARD_NUM), shardNum);\n            }\n        }\n    }\n\n    @Override\n    public Result<Void> delTemplate(Long physicalId, String operator) throws ESOperateException {\n        return indexTemplatePhyService.delTemplate(physicalId, operator);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> delTemplateByLogicId(Integer logicId, String operator) throws ESOperateException {\n        List<IndexTemplatePhy> indexTemplatePhies = indexTemplatePhyService.getTemplateByLogicId(logicId);\n\n        boolean succ = true;\n        if (CollectionUtils.isEmpty(indexTemplatePhies)) {\n            LOGGER.info(\n                \"class=TemplatePhyManagerImpl||method=delTemplateByLogicId||logicId={}||msg=template no physical info!\",\n                logicId);\n        } else {\n            LOGGER.info(\n                \"class=TemplatePhyManagerImpl||method=delTemplateByLogicId||logicId={}||physicalSize={}||msg=template has physical info!\",\n                logicId, indexTemplatePhies.size());\n            for (IndexTemplatePhy indexTemplatePhy : indexTemplatePhies) {\n                if (delTemplate(indexTemplatePhy.getId(), operator).failed()) {\n                    succ = false;\n                }\n\n            }\n        }\n\n        return Result.build(succ);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> upgradeTemplate(TemplatePhysicalUpgradeDTO param, String operator,\n                                        Integer projectId) throws ESOperateException {\n        Result<Void> checkResult = checkUpgradeParam(param);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=TemplatePhyManagerImpl||method=upgradeTemplate||msg={}\",\n                CHECK_FAIL_MSG + checkResult.getMessage());\n            return checkResult;\n        } else {\n            IndexTemplatePhy oldIndexTemplatePhy = indexTemplatePhyService.getTemplateById(param.getPhysicalId());\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"模版 [%s] 升级版本：%s->%s\", oldIndexTemplatePhy.getName(),\n                            oldIndexTemplatePhy.getVersion(), param.getVersion()), operator, projectId,\n                    param.getLogicId(), OperateTypeEnum.TEMPLATE_SERVICE_UPGRADED_VERSION);\n\n        }\n\n        return upgradeTemplateWithCheck(param, operator, 0);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> rolloverUpgradeTemplate(TemplatePhysicalUpgradeDTO param,\n                                                String operator) throws ESOperateException {\n        //rollover 生版本号不需要对参数进行校验\n        return upgradeTemplateWithCheck(param, operator, 0);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Boolean> upgradeMultipleTemplate(List<TemplatePhysicalUpgradeDTO> params, String operator,\n                                                   Integer projectId) throws ESOperateException {\n        if (CollectionUtils.isEmpty(params)) {\n            Result.buildFail(\"参数为空\");\n        }\n\n        for (TemplatePhysicalUpgradeDTO param : params) {\n            Result<Void> ret = upgradeTemplate(param, operator, projectId);\n            if (ret.failed()) {\n                throw new ESOperateException(ret.getMessage());\n            }\n        }\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> copyTemplate(TemplatePhysicalCopyDTO param, String operator) throws AdminOperateException {\n        Result<Void> checkResult = checkCopyParam(param);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=TemplatePhyManagerImpl||method=copyTemplate||msg={}\",\n                CHECK_FAIL_MSG + checkResult.getMessage());\n            return checkResult;\n        }\n\n        IndexTemplatePhy indexTemplatePhy = indexTemplatePhyService.getTemplateById(param.getPhysicalId());\n        IndexTemplatePhyDTO tgtTemplateParam = ConvertUtil.obj2Obj(indexTemplatePhy, IndexTemplatePhyDTO.class);\n        tgtTemplateParam.setCluster(param.getCluster());\n        tgtTemplateParam.setRole(SLAVE.getCode());\n        tgtTemplateParam.setShard(param.getShard());\n        tgtTemplateParam.setVersion(indexTemplatePhy.getVersion());\n        tgtTemplateParam.setRegionId(param.getRegionId());\n\n        Result<Long> addResult = addTemplateWithoutCheck(tgtTemplateParam);\n        if (addResult.failed()) {\n            return Result.buildFrom(addResult);\n        }\n\n        // 记录操作记录\n        operateRecordService.saveOperateRecordWithManualTrigger(\n                String.format(\"复制【%s】物理模板至【%s】\", indexTemplatePhy.getCluster(), param.getCluster()), operator,\n                AuthConstant.SUPER_PROJECT_ID, indexTemplatePhy.getLogicId(), OperateTypeEnum.TEMPLATE_SERVICE);\n\n        if (esTemplateService.syncCopyMappingAndAlias(indexTemplatePhy.getCluster(), indexTemplatePhy.getName(),\n            tgtTemplateParam.getCluster(), tgtTemplateParam.getName(), 0)) {\n            LOGGER.info(\n                \"class=TemplatePhyManagerImpl||methood=copyTemplate||TemplatePhysicalCopyDTO={}||msg=syncCopyMappingAndAlias succ\",\n                param);\n        } else {\n            LOGGER.warn(\n                \"class=TemplatePhyManagerImpl||methood=copyTemplate||TemplatePhysicalCopyDTO={}||msg=syncCopyMappingAndAlias fail\",\n                param);\n        }\n\n        return Result.buildSucWithTips(\"模板部署集群变更!\");\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> editTemplate(IndexTemplatePhyDTO param, String operator) throws ESOperateException {\n        Result<Void> checkResult = indexTemplatePhyService.validateTemplate(param, EDIT);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=TemplatePhyManagerImpl||method=editTemplate||msg={}\",\n                CHECK_FAIL_MSG + checkResult.getMessage());\n            return checkResult;\n        }\n\n        IndexTemplatePhy oldIndexTemplatePhy = indexTemplatePhyService.getTemplateById(param.getId());\n        Result<Void> result = editTemplateWithoutCheck(param, operator, 0);\n        if (result.success()) {\n            String editContent = AriusObjUtils.findChangedWithClear(oldIndexTemplatePhy, param);\n            if (StringUtils.isNotBlank(editContent)) {\n                operateRecordService.saveOperateRecordWithManualTrigger(\n                        String.format(\"%s 变更:【%s】\", TemplateOperateRecordEnum.CONFIG.getDesc(), editContent),\n                        operator, AuthConstant.SUPER_PROJECT_ID, oldIndexTemplatePhy.getLogicId(),\n                        OperateTypeEnum.TEMPLATE_SERVICE);\n\n            }\n        }\n        return result;\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Boolean> editMultipleTemplate(List<IndexTemplatePhyDTO> params,\n                                                String operator) throws ESOperateException {\n        if (CollectionUtils.isEmpty(params)) {\n            Result.buildFail(\"参数为空\");\n        }\n\n        for (IndexTemplatePhyDTO param : params) {\n            Result<Void> ret = editTemplate(param, operator);\n            if (ret.failed()) {\n                throw new ESOperateException(String.format(\"编辑模板:%s失败\", param.getName()));\n            }\n        }\n\n        return Result.buildSucc(true);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> addTemplatesWithoutCheck(Integer logicId,\n                                                 List<IndexTemplatePhyDTO> physicalInfos) throws AdminOperateException {\n        for (IndexTemplatePhyDTO param : physicalInfos) {\n            param.setLogicId(logicId);\n            Result<Long> result = addTemplateWithoutCheck(param);\n            if (result.failed()) {\n                result.setMessage(result.getMessage() + \"; 集群:\" + param.getCluster() + \",模板:\" + param.getName());\n                return Result.buildFrom(result);\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Long> addTemplateWithoutCheck(IndexTemplatePhyDTO param) throws AdminOperateException {\n        if (null != indexTemplatePhyService.getTemplateByClusterAndName(param.getCluster(), param.getName())) {\n            return Result.buildParamIllegal(\"索引已经存在\");\n        }\n\n        initParamWhenAdd(param);\n\n        Result<Long> result = indexTemplatePhyService.insert(param);\n        Long physicalId = result.getData();\n        if (result.success()) {\n            //删除数据库中历史的脏数据\n            indexTemplatePhyService.deleteDirtyByClusterAndName(param.getCluster(), param.getName());\n\n            //创建索引模板\n            syncCreateIndexTemplateWithEs(param);\n\n            SpringTool.publish(new PhysicalTemplateAddEvent(this, indexTemplatePhyService.getTemplateById(physicalId),\n                buildIndexTemplateLogicWithPhysicalForNew(param)));\n        }\n\n        return Result.buildSucc(physicalId);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> switchMasterSlave(Integer logicId, Long expectMasterPhysicalId, String operator) {\n        List<IndexTemplatePhy> indexTemplatePhies = indexTemplatePhyService.getTemplateByLogicId(logicId);\n        if (CollectionUtils.isEmpty(indexTemplatePhies)) {\n            return Result.buildNotExist(\"模板不存在\");\n        }\n\n        IndexTemplatePhy oldMaster = null;\n        IndexTemplatePhy newMaster = null;\n\n        for (IndexTemplatePhy indexTemplatePhy : indexTemplatePhies) {\n            if (indexTemplatePhy.getRole().equals(MASTER.getCode())) {\n                if (oldMaster != null) {\n                    LOGGER.error(\"class=TemplatePhyServiceImpl||method=switchMasterSlave||errMsg=no master||logicId={}\",\n                        logicId);\n                }\n                oldMaster = indexTemplatePhy;\n            } else {\n                if (expectMasterPhysicalId == null && newMaster == null) {\n                    newMaster = indexTemplatePhy;\n                }\n\n                if (indexTemplatePhy.getId().equals(expectMasterPhysicalId)) {\n                    newMaster = indexTemplatePhy;\n                }\n            }\n        }\n\n        if (newMaster == null) {\n            return Result.buildNotExist(\"无法确定新的主\");\n        }\n\n        boolean succ = true;\n\n        if (oldMaster == null) {\n            LOGGER.error(\"class=TemplatePhyServiceImpl||method=switchMasterSlave||errMsg=no master||logicId={}\",\n                logicId);\n        } else {\n            succ = indexTemplatePhyService.updateTemplateRole(oldMaster, SLAVE, operator).success();\n        }\n\n        succ = succ && (indexTemplatePhyService.updateTemplateRole(newMaster, MASTER, operator).success());\n\n        return Result.build(succ);\n    }\n\n    @Override\n    public Result<Void> editTemplateWithoutCheck(IndexTemplatePhyDTO param, String operator,\n                                                 int retryCount) throws ESOperateException {\n        IndexTemplatePhy oldIndexTemplatePhy = indexTemplatePhyService.getTemplateById(param.getId());\n        //不需要shard比较\n        \n\n        boolean succ = indexTemplatePhyService.update(param).success();\n        String tips = \"\";\n        if (succ) {\n            SpringTool.publish(\n                new PhysicalTemplateModifyEvent(this, ConvertUtil.obj2Obj(oldIndexTemplatePhy, IndexTemplatePhy.class),\n                    indexTemplatePhyService.getTemplateById(oldIndexTemplatePhy.getId()),\n                    indexTemplateService.getLogicTemplateWithPhysicalsById(oldIndexTemplatePhy.getLogicId())));\n        }\n\n        return Result.buildWithTips(succ, tips);\n    }\n\n    @Override\n    public Tuple</*存放冷存索引列表*/Set<String>, /*存放热存索引列表*/Set<String>> getHotAndColdIndexByBeforeDay(IndexTemplatePhyWithLogic physicalWithLogic,\n                                                                                                 int days) {\n        try {\n            IndexTemplate logicTemplate = physicalWithLogic.getLogicTemplate();\n\n            if (!physicalWithLogic.getExpression().endsWith(\"*\")) {\n                return new Tuple<>();\n            }\n\n            if (!TemplateUtils.isSaveByDay(logicTemplate.getDateFormat())\n                && !TemplateUtils.isSaveByMonth(logicTemplate.getDateFormat())) {\n                return new Tuple<>();\n            }\n\n            List<String> indices = indexTemplatePhyService.getMatchIndexNames(physicalWithLogic.getId());\n            if (CollectionUtils.isEmpty(indices)) {\n                LOGGER.info(\n                    \"class=TemplatePhyManagerImpl||method=getIndexByBeforeDay||template={}||msg=no match indices\",\n                    logicTemplate.getName());\n                return new Tuple<>();\n            }\n\n            return getHotAndColdIndexSet( days, logicTemplate, indices);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=TemplatePhyManagerImpl||method=getIndexByBeforeDay||templateName={}||errMsg={}\",\n                physicalWithLogic.getName(), e.getMessage(), e);\n        }\n\n        return new Tuple<>();\n    }\n\n    @Override\n    public Set<String> getIndexByBeforeDay(IndexTemplatePhyWithLogic physicalWithLogic, int days) {\n        try {\n            IndexTemplate logicTemplate = physicalWithLogic.getLogicTemplate();\n\n            if (!physicalWithLogic.getExpression().endsWith(\"*\")) {\n                return Sets.newHashSet();\n            }\n\n            if (!TemplateUtils.isSaveByDay(logicTemplate.getDateFormat())\n                && !TemplateUtils.isSaveByMonth(logicTemplate.getDateFormat())) {\n                return Sets.newHashSet();\n            }\n\n            List<String> indices = indexTemplatePhyService.getMatchIndexNames(physicalWithLogic.getId());\n            if (CollectionUtils.isEmpty(indices)) {\n                LOGGER.info(\n                    \"class=TemplatePhyManagerImpl||method=getIndexByBeforeDay||template={}||msg=no match indices\",\n                    logicTemplate.getName());\n                return Sets.newHashSet();\n            }\n\n            return getFinalIndexSet( days, logicTemplate, indices);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=TemplatePhyManagerImpl||method=getIndexByBeforeDay||templateName={}||errMsg={}\",\n                physicalWithLogic.getName(), e.getMessage(), e);\n        }\n\n        return Sets.newHashSet();\n    }\n\n    @Override\n    public List<ConsoleTemplatePhyVO> getConsoleTemplatePhyVOS(IndexTemplatePhyDTO param, Integer projectId) {\n        List<ConsoleTemplatePhyVO> consoleTemplatePhyVOS = ConvertUtil\n            .list2List(indexTemplatePhyService.getByCondt(param), ConsoleTemplatePhyVO.class);\n\n        buildConsoleTemplatePhyVO(consoleTemplatePhyVOS, projectId);\n\n        return consoleTemplatePhyVOS;\n    }\n\n    @Override\n    public List<String> getTemplatePhyNames(Integer projectId) {\n        return getConsoleTemplatePhyVOS(null, projectId).parallelStream().map(ConsoleTemplatePhyVO::getName)\n            .collect(Collectors.toList());\n    }\n\n    @Override\n    public List<String> getCanCopyTemplatePhyClusterPhyNames(Long templatePhyId) {\n        List<String> canCopyClusterPhyNames = Lists.newArrayList();\n        IndexTemplatePhy templatePhy = indexTemplatePhyService.getTemplateById(templatePhyId);\n        if (null != templatePhy && null != templatePhy.getCluster()) {\n            clusterPhyService.listAllClusters().stream()\n                .filter(clusterPhy -> !templatePhy.getCluster().equals(clusterPhy.getCluster()))\n                .forEach(clusterPhy -> canCopyClusterPhyNames.add(clusterPhy.getCluster()));\n        }\n\n        return canCopyClusterPhyNames;\n    }\n\n    @Override\n    public Result<List<IndexTemplatePhysicalVO>> getTemplatePhies(Integer logicId) {\n        if (!indexTemplateService.exist(logicId)) {\n            return Result.buildFail(\"模板Id不存在\");\n        }\n        return Result.buildSucc(ConvertUtil.list2List(indexTemplatePhyService.getTemplateByLogicId(logicId),\n            IndexTemplatePhysicalVO.class));\n    }\n\n    /**\n     * @param regionId\n     * @return\n     */\n    @Override\n    public Result<List<IndexTemplatePhysicalVO>> listByRegionId(Integer regionId) {\n        Result<List<IndexTemplatePhy>> ret = physicalService.listByRegionId(regionId);\n        if (ret.failed()) {\n            return Result.buildFrom(ret);\n        }\n        return Result.buildSucc(ConvertUtil.list2List(ret.getData(), IndexTemplatePhysicalVO.class));\n    }\n\n    /**************************************** private method ****************************************************/\n    private void initParamWhenAdd(IndexTemplatePhyDTO param) {\n        IndexTemplate logic = indexTemplateService.getLogicTemplateById(param.getLogicId());\n\n        if (param.getName() == null) {\n            param.setName(logic.getName());\n        }\n        if (param.getExpression() == null) {\n            param.setExpression(logic.getExpression());\n        }\n        if (param.getStatus() == null) {\n            param.setStatus(TemplatePhysicalStatusEnum.NORMAL.getCode());\n        }\n\n        if (param.getRack() == null) {\n            param.setRack(\"\");\n        }\n\n        if (param.getVersion() == null) {\n            param.setVersion(0);\n        }\n\n        if (param.getConfig() == null) {\n            param.setConfig(\"\");\n        }\n        if (param.getShardRouting() == null) {\n            param.setShardRouting(1);\n        }\n\n        IndexTemplatePhysicalConfig indexTemplatePhysicalConfig = new IndexTemplatePhysicalConfig();\n        if (StringUtils.isNotBlank(param.getConfig())) {\n            indexTemplatePhysicalConfig = JSON.parseObject(param.getConfig(), IndexTemplatePhysicalConfig.class);\n        }\n\n        indexTemplatePhysicalConfig.setGroupId(param.getGroupId());\n        indexTemplatePhysicalConfig.setDefaultWriterFlags(param.getDefaultWriterFlags());\n\n        param.setConfig(JSON.toJSONString(indexTemplatePhysicalConfig));\n    }\n\n    private Result<Void> checkUpgradeParam(TemplatePhysicalUpgradeDTO param) {\n        if (AriusObjUtils.isNull(param)) {\n            return Result.buildParamIllegal(\"模板升版本信息为空\");\n        }\n        if (AriusObjUtils.isNull(param.getPhysicalId())) {\n            return Result.buildParamIllegal(TEMPLATE_PHYSICAL_ID_IS_NULL);\n        }\n        if (AriusObjUtils.isNull(param.getVersion())) {\n            return Result.buildParamIllegal(\"物理模板版本为空\");\n        }\n\n        IndexTemplatePhy oldIndexTemplatePhy = indexTemplatePhyService.getTemplateById(param.getPhysicalId());\n        if (oldIndexTemplatePhy == null) {\n            return Result.buildNotExist(TEMPLATE_PHYSICAL_NOT_EXISTS);\n        }\n        if (Objects.equals(param.getVersion(), oldIndexTemplatePhy.getVersion())\n            || (param.getVersion() > 0 && param.getVersion() < oldIndexTemplatePhy.getVersion())) {\n            return Result.buildParamIllegal(\"物理模板版本非法\");\n        }\n        if (param.getShard() != null && param.getShard() < MIN_SHARD_NUM) {\n            return Result.buildParamIllegal(\"shard个数非法\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> upgradeTemplateWithCheck(TemplatePhysicalUpgradeDTO param, String operator,\n                                                  int retryCount) throws ESOperateException {\n        IndexTemplatePhy indexTemplatePhy = indexTemplatePhyService.getTemplateById(param.getPhysicalId());\n       \n\n        IndexTemplate logic = indexTemplateService.getLogicTemplateById(indexTemplatePhy.getLogicId());\n        LOGGER.info(\"class=TemplatePhyManagerImpl||method=upgradeTemplateWithCheck||name={}||shard={}||version={}\",\n            logic.getName(), param.getShard(), param.getVersion());\n\n        IndexTemplatePhyDTO updateParam = new IndexTemplatePhyDTO();\n        updateParam.setId(indexTemplatePhy.getId());\n        updateParam.setVersion(param.getVersion());\n        /*\n        这里提前创建当天索引\n          1.避免因为getTemplateConfig失败，导致升版本后不分区索引mapping异常\n          2.避免由于事务原因，导致当天最新版本的分区索引未被创建\n        */\n        if (!preCreateManager.syncCreateTodayIndexByPhysicalId(updateParam.getId(), updateParam.getVersion())) {\n            return Result.buildFail(\"创建当前最新版本索引失败，请稍后重试！\");\n        }\n\n        Result<Void> editResult = editTemplateWithoutCheck(updateParam, operator, retryCount);\n\n        if (editResult.failed()) {\n            return editResult;\n        }\n\n        preCreateManager.asyncCreateTodayAndTomorrowIndexByPhysicalId(indexTemplatePhy.getId());\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkCopyParam(TemplatePhysicalCopyDTO param) {\n        if (AriusObjUtils.isNull(param)) {\n            return Result.buildParamIllegal(\"复制参数为空\");\n        }\n        if (AriusObjUtils.isNull(param.getPhysicalId())) {\n            return Result.buildParamIllegal(TEMPLATE_PHYSICAL_ID_IS_NULL);\n        }\n        if (AriusObjUtils.isNull(param.getCluster())) {\n            return Result.buildParamIllegal(\"目标集群为空\");\n        }\n        if (AriusObjUtils.isNull(param.getShard())) {\n            return Result.buildParamIllegal(\"shard为空\");\n        }\n\n        IndexTemplatePhy oldIndexTemplatePhy = indexTemplatePhyService.getTemplateById(param.getPhysicalId());\n        if (oldIndexTemplatePhy == null) {\n            return Result.buildNotExist(TEMPLATE_PHYSICAL_NOT_EXISTS);\n        }\n\n        if (!clusterPhyService.isClusterExists(param.getCluster())) {\n            return Result.buildNotExist(\"目标集群不存在\");\n        }\n\n        if (oldIndexTemplatePhy.getCluster().equals(param.getCluster())) {\n            return Result.buildParamIllegal(\"目标集群不能与源集群相同\");\n        }\n\n        if (param.getShard() < 1) {\n            return Result.buildParamIllegal(\"shard非法\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkMetaInner(IndexTemplatePhy templatePhysical,\n                                        Map<Integer, IndexTemplate> logicId2IndexTemplateLogicMap,\n                                        Set<String> esClusters) {\n        List<String> errMsgs = Lists.newArrayList();\n\n        if (!esClusters.contains(templatePhysical.getCluster())) {\n            errMsgs.add(\"物理集群不存在：\" + templatePhysical.getName() + \"(\" + templatePhysical.getId() + \")\");\n        }\n\n        if (!logicId2IndexTemplateLogicMap.containsKey(templatePhysical.getLogicId())) {\n            errMsgs.add(\"逻辑模板不存在：\" + templatePhysical.getName() + \"(\" + templatePhysical.getId() + \")\");\n        }\n    \n        TemplateConfig templateConfig = null;\n        try {\n            templateConfig = esTemplateService.syncGetTemplateConfig(templatePhysical.getCluster(),\n                    templatePhysical.getName());\n        } catch (ESOperateException e) {\n            errMsgs.add(String.format(\"获取 templateConfig 失败:%s\", e.getMessage()));\n        }\n    \n        if (templateConfig == null) {\n            errMsgs.add(\"es模板不存在：\" + templatePhysical.getName() + \"(\" + templatePhysical.getId() + \")\");\n        }\n\n        if (CollectionUtils.isEmpty(errMsgs)) {\n            return Result.buildSucc();\n        }\n\n        return Result.build(ResultType.ADMIN_META_ERROR.getCode(), String.join(\",\", errMsgs));\n\n    }\n\n    private int checkIndexCreateAndExpire(IndexTemplatePhy templatePhysical,\n                                          Map<Integer, IndexTemplate> logicId2IndexTemplateLogicMap) {\n        int result = INDEX_OP_OK;\n        if (templatePhysical.getCreateTime().before(AriusDateUtils.getZeroDate())) {\n            Set<String> indices = Sets\n                .newHashSet(indexTemplatePhyService.getMatchNoVersionIndexNames(templatePhysical.getId()));\n\n            IndexTemplate templateLogic = logicId2IndexTemplateLogicMap.get(templatePhysical.getLogicId());\n            String tomorrowIndexName = IndexNameFactory.getNoVersion(templateLogic.getExpression(),\n                templateLogic.getDateFormat(), 1);\n            String expireIndexName = IndexNameFactory.getNoVersion(templateLogic.getExpression(),\n                templateLogic.getDateFormat(), -1 * templateLogic.getExpireTime());\n\n            if (!indices.contains(tomorrowIndexName)) {\n                LOGGER.warn(\n                    \"class=TemplatePhyManagerImpl||method=checkIndexCreateAndExpire||cluster={}||template={}||msg=TOMORROW_INDEX_NOT_CREATE\",\n                    templatePhysical.getCluster(), templatePhysical.getName());\n                result = result + TOMORROW_INDEX_NOT_CREATE;\n            }\n\n            if (TemplateUtils.isSaveByDay(templateLogic.getDateFormat()) && indices.contains(expireIndexName)) {\n                LOGGER.warn(\n                    \"class=TemplatePhyManagerImpl||method=checkIndexCreateAndExpire||cluster={}||template={}||msg=EXPIRE_INDEX_NOT_DELETE\",\n                    templatePhysical.getCluster(), templatePhysical.getName());\n                result = result + EXPIRE_INDEX_NOT_DELETE;\n            }\n        }\n        return result;\n    }\n\n    private IndexTemplateWithPhyTemplates buildIndexTemplateLogicWithPhysicalForNew(IndexTemplatePhyDTO param) {\n        IndexTemplateWithPhyTemplates logicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(param.getLogicId());\n        if (CollectionUtils.isNotEmpty(param.getPhysicalInfos())) {\n            List<IndexTemplatePhy> physicals = ConvertUtil.list2List(param.getPhysicalInfos(), IndexTemplatePhy.class);\n            logicWithPhysical.setPhysicals(physicals);\n        }\n        return logicWithPhysical;\n    }\n\n    /**\n     * 判定是否是合法的shard number.\n     *\n     * @param shardNum\n     * @return\n     */\n    private boolean isValidShardNum(Integer shardNum) {\n        return (shardNum != null && shardNum > 0);\n    }\n\n    private void buildConsoleTemplatePhyVO(List<ConsoleTemplatePhyVO> params, Integer currentProjectId) {\n\n        Map<Integer, String> projectId2ProjectNameMap = Maps.newHashMap();\n\n        for (ConsoleTemplatePhyVO consoleTemplatePhyVO : params) {\n\n            IndexTemplate logicTemplate = indexTemplateService.getLogicTemplateById(consoleTemplatePhyVO.getLogicId());\n            if (AriusObjUtils.isNull(logicTemplate)) {\n                LOGGER.error(\n                    \"class=TemplatePhyServiceImpl||method=buildConsoleTemplatePhyVO||errMsg=IndexTemplateLogic is empty||logicId={}\",\n                    consoleTemplatePhyVO.getLogicId());\n                continue;\n            }\n\n            handleIndexTemplateLogic(currentProjectId, projectId2ProjectNameMap, consoleTemplatePhyVO, logicTemplate);\n\n        }\n    }\n\n    private void handleIndexTemplateLogic(Integer currentProjectId, Map<Integer, String> projectId2ProjectNameMap,\n                                          ConsoleTemplatePhyVO consoleTemplatePhyVO, IndexTemplate logicTemplate) {\n        //设置归属项目信息\n        Integer projectIdFromLogicTemplate = logicTemplate.getProjectId();\n        if (!AriusObjUtils.isNull(projectIdFromLogicTemplate)) {\n            consoleTemplatePhyVO.setProjectId(projectIdFromLogicTemplate);\n\n            if (projectId2ProjectNameMap.containsKey(projectIdFromLogicTemplate)) {\n                consoleTemplatePhyVO.setProjectName(projectId2ProjectNameMap.get(logicTemplate.getProjectId()));\n            } else {\n                String projectName = Optional\n                    .ofNullable(projectService.getProjectBriefByProjectId(logicTemplate.getProjectId()))\n                    .map(ProjectBriefVO::getProjectName).orElse(null);\n\n                if (!AriusObjUtils.isNull(projectName)) {\n                    consoleTemplatePhyVO.setProjectName(projectName);\n                    projectId2ProjectNameMap.put(projectIdFromLogicTemplate, projectName);\n                }\n            }\n        }\n\n        //设置逻辑模板名称\n        consoleTemplatePhyVO.setLogicName(logicTemplate.getName());\n\n        //设置描述信息, 是否要加一列描述信息\n        consoleTemplatePhyVO.setMemo(logicTemplate.getDesc());\n\n        //设置权限\n        if (AriusObjUtils.isNull(currentProjectId)) {\n            consoleTemplatePhyVO.setAuthType(ProjectTemplateAuthEnum.NO_PERMISSION.getCode());\n            return;\n        }\n        if (currentProjectId.equals(projectIdFromLogicTemplate)) {\n            consoleTemplatePhyVO.setAuthType(ProjectTemplateAuthEnum.OWN.getCode());\n        } else {\n            ProjectTemplateAuthEnum authEnum = projectLogicTemplateAuthService\n                .getAuthEnumByProjectIdAndLogicId(currentProjectId, projectIdFromLogicTemplate);\n            consoleTemplatePhyVO.setAuthType(authEnum.getCode());\n        }\n    }\n\n    private Set<String> getFinalIndexSet( int days,\n                                         IndexTemplate logicTemplate, List<String> indices) {\n        Set<String> finalIndexSet = Sets.newHashSet();\n        for (String indexName : indices) {\n            if (StringUtils.isBlank(indexName)) {\n                continue;\n            }\n\n            Date indexTime = IndexNameFactory.genIndexTimeByIndexName(\n                genIndexNameClear(indexName, logicTemplate.getExpression()), logicTemplate.getExpression(),\n                logicTemplate.getDateFormat());\n\n            if (indexTime == null) {\n                LOGGER.warn(\n                    \"class=TemplatePhyManagerImpl||method=getIndexByBeforeDay||template={}||indexName={}||msg=template parse index time fail\",\n                    logicTemplate.getName(), indexName);\n                continue;\n            }\n\n            if (TemplateUtils.isSaveByMonth(logicTemplate.getDateFormat())) {\n                // 需要将索引时间定为当月的最后一天 确保最后一天的数据能被保留到保存时长\n                indexTime = AriusDateUtils.getLastDayOfTheMonth(indexTime);\n            }\n\n            long timeIntervalDay = (System.currentTimeMillis() - indexTime.getTime()) / MILLIS_PER_DAY;\n            if (timeIntervalDay < days) {\n                LOGGER.info(\n                    \"class=TemplatePhyManagerImpl||method=getIndexByBeforeDay||template={}||indexName={}||timeIntervalDay={}||msg=index not match\",\n                    logicTemplate.getName(), indexName, timeIntervalDay);\n                continue;\n            }\n\n            LOGGER.info(\n                \"class=TemplatePhyManagerImpl||method=getIndexByBeforeDay||indexName={}||indexTime={}||timeIntervalDay={}\",\n                indexName, indexTime, timeIntervalDay);\n\n            finalIndexSet.add(indexName);\n        }\n        return finalIndexSet;\n    }\n\n    private void syncCreateIndexTemplateWithEs(IndexTemplatePhyDTO param) throws AdminOperateException {\n        IndexTemplate logic = indexTemplateService.getLogicTemplateById(param.getLogicId());\n        MappingConfig mappings = null;\n        if (StringUtils.isNotBlank(param.getMappings())) {\n            Result result = AriusIndexMappingConfigUtils.parseMappingConfig(param.getMappings());\n            if (result.success()) {\n                mappings = (MappingConfig) result.getData();\n            }\n        }\n        Map<String, String> settingsMap = getSettingsMap(param.getShard(), param.getRegionId(), param.getSettings());\n        boolean ret;\n        if (null != mappings || MapUtils.isNotEmpty(settingsMap)) {\n            ret = esTemplateService.syncCreate(settingsMap, param.getCluster(), param.getName(), logic.getExpression(),\n                mappings, 0);\n        } else {\n            ret = esTemplateService.syncCreate(param.getCluster(), param.getName(), logic.getExpression(),\n                param.getShard(), param.getShardRouting(), 0);\n        }\n        if (!ret) {\n            throw new ESOperateException(\"failed to create template!\");\n        }\n    }\n\n    private Map<String, String> getSettingsMap(Integer shard, Integer regionId,\n                                               String settings) throws AdminOperateException {\n        Map<String, String> settingsMap = new HashMap<>();\n        if (null != shard && shard > 0) {\n            settingsMap.put(INDEX_SHARD_NUM, String.valueOf(shard));\n        }\n\n        if (null != regionId) {\n            Result<List<ClusterRoleHost>> roleHostResult = clusterRoleHostService.listByRegionId(regionId);\n            if (roleHostResult.failed()) {\n                throw new AdminOperateException(String.format(\"获取region[%d]节点列表异常\", regionId));\n            }\n            List<ClusterRoleHost> data = roleHostResult.getData();\n            if (CollectionUtils.isEmpty(data)) {\n                throw new AdminOperateException(String.format(\"获取region[%d]节点列表为空, 请检查region中是否存在数据节点\", regionId));\n            }\n            List<String> nodeNames = data.stream().map(ClusterRoleHost::getNodeSet)\n                .filter(nodeName -> !AriusObjUtils.isBlank(nodeName)).distinct().collect(Collectors.toList());\n            settingsMap.put(TEMPLATE_INDEX_INCLUDE_NODE_NAME, String.join(\",\", nodeNames));\n        }\n\n        if (null != settings) {\n            settingsMap.putAll(AriusIndexTemplateSetting.flat(JSON.parseObject(settings)));\n        }\n\n        return settingsMap;\n    }\n\n    private Tuple</*存放冷存索引列表*/Set<String>, /*存放热存索引列表*/Set<String>> getHotAndColdIndexSet(\n                                                                                          int days,\n                                                                                          IndexTemplate logicTemplate,\n                                                                                          List<String> indices) {\n        Set<String> finalColdIndexSet = Sets.newHashSet();\n        Set<String> finalHotIndexSet = Sets.newHashSet();\n        for (String indexName : indices) {\n            if (StringUtils.isBlank(indexName)) {\n                continue;\n            }\n\n            Date indexTime = IndexNameFactory.genIndexTimeByIndexName(\n                genIndexNameClear(indexName, logicTemplate.getExpression()), logicTemplate.getExpression(),\n                logicTemplate.getDateFormat());\n\n            if (indexTime == null) {\n                LOGGER.warn(\n                    \"class=TemplatePhyManagerImpl||method=getIndexByBeforeDay||template={}||indexName={}||msg=template parse index time fail\",\n                    logicTemplate.getName(), indexName);\n                continue;\n            }\n\n            if (TemplateUtils.isSaveByMonth(logicTemplate.getDateFormat())) {\n                // 需要将索引时间定为当月的最后一天 确保最后一天的数据能被保留到保存时长\n                indexTime = AriusDateUtils.getLastDayOfTheMonth(indexTime);\n            }\n\n            long timeIntervalDay = (System.currentTimeMillis() - indexTime.getTime()) / MILLIS_PER_DAY;\n            if (timeIntervalDay < days) {\n                LOGGER.info(\n                    \"class=TemplatePhyManagerImpl||method=getIndexByBeforeDay||template={}||indexName={}||timeIntervalDay={}||msg=index not match\",\n                    logicTemplate.getName(), indexName, timeIntervalDay);\n                finalHotIndexSet.add(indexName);\n                continue;\n            }\n\n            LOGGER.info(\n                \"class=TemplatePhyManagerImpl||method=getIndexByBeforeDay||indexName={}||indexTime={}||timeIntervalDay={}\",\n                indexName, indexTime, timeIntervalDay);\n\n            finalColdIndexSet.add(indexName);\n        }\n        return new Tuple<>(finalColdIndexSet, finalHotIndexSet);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/impl/TemplatePhyStaticsManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplatePhyStaticsManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ProjectIdTemplateAccessCountVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateStatsInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.TemplateStatsService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.List;\nimport java.util.Map;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author d06679\n * @date 2019-06-24\n */\n@Service\npublic class TemplatePhyStaticsManagerImpl implements TemplatePhyStaticsManager {\n\n    private static final ILog    LOGGER = LogFactory.getLog(TemplatePhyStaticsManagerImpl.class);\n\n    @Autowired\n    private TemplateStatsService templateStatsService;\n\n   \n\n    @Override\n    public Result<Map<Integer, Long>> getAccessStatsInfoByTemplateIdAndDays(int logicTemplateId, int days) {\n        return templateStatsService.getAccessStatsInfoByTemplateIdAndDays(logicTemplateId, days);\n    }\n\n    @Override\n    public Result<TemplateStatsInfoVO> getTemplateBaseStatisticalInfoByLogicTemplateId(Long logicTemplateId) {\n        return Result.buildSucc(ConvertUtil.obj2Obj(\n            templateStatsService.getTemplateBaseStatisticalInfoByLogicTemplateId(logicTemplateId).getData(),\n            TemplateStatsInfoVO.class));\n    }\n\n    @Override\n    public Result<List<ESIndexStats>> getIndexStatics(Long logicTemplateId, Long startDate, Long endDate) {\n        return templateStatsService.getIndexStatis(logicTemplateId, startDate, endDate);\n    }\n\n    @Override\n    public Result<List<ProjectIdTemplateAccessCountVO>> getAccessAppInfos(int logicTemplateId, Long startDate,\n                                                                          Long endDate) {\n        return Result.buildSucc(\n            ConvertUtil.list2List(templateStatsService.getAccessAppInfos(logicTemplateId, startDate, endDate).getData(),\n                ProjectIdTemplateAccessCountVO.class));\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/TemplateSrvManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv.ColdSrvOpenDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv.TemplateQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.srv.TemplateSrv;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.srv.UnavailableTemplateSrv;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.srv.TemplateWithSrvVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleThree;\nimport java.util.List;\n\n/**\n * @author chengxiang\n * @date 2022/5/17\n */\npublic interface TemplateSrvManager {\n\n    /**\n     * 判断指定逻辑模板是否开启了该模板服务\n     * @param logicTemplateId 逻辑模板id\n     * @param templateSrvId 模板服务id\n     * @return\n     */\n    boolean isTemplateSrvOpen(Integer logicTemplateId, Integer templateSrvId);\n\n    /**\n     * 获取指定模板「开启的」服务\n     * @param logicTemplateId 逻辑模板id\n     * @return\n     */\n    Result<List<TemplateSrv>> getTemplateOpenSrv(Integer logicTemplateId);\n\n    /**\n     * 获取指定模板「不可用的」服务\n     *\n     * @param template        @return\n     * @param existDCDRAndPipelineModule\n     */\n    List<UnavailableTemplateSrv> getUnavailableSrvByTemplateAndMasterPhy(IndexTemplate template,  TupleThree<Boolean, Boolean, Boolean> existDCDRAndPipelineModule);\n\n    /**\n     * 分页模糊查询模板服务\n     *\n     * @param condition\n     * @param projectId\n     * @return\n     */\n    PaginationResult<TemplateWithSrvVO> pageGetTemplateWithSrv(TemplateQueryDTO condition, Integer projectId) throws NotFindSubclassException;\n\n    /**\n     * 开启模板服务\n     *\n     * @param srvCode        服务代码\n     * @param templateIdList 模板id列表\n     * @param operator\n     * @param projectId\n     * @param data\n     * @return\n     */\n    Result<Void> openSrv(Integer srvCode, List<Integer> templateIdList, String operator, Integer projectId,\n                         ColdSrvOpenDTO data);\n\n    /**\n     * 关闭模板服务\n     *\n     * @param srvCode        服务代码\n     * @param templateIdList 模板id列表\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Void> closeSrv(Integer srvCode, List<Integer> templateIdList, String operator, Integer projectId);\n    \n    /**\n     * 查询开启了某个索引服务的物理集群列表\n     *\n     * @param srvId\n     * @return\n     */\n    List<String> getPhyClusterByOpenTemplateSrv(int srvId);\n    \n    /**\n     * 查询开启了某个索引服务的索引模板列表\n     *\n     * @param srvId\n     * @return\n     */\n    List<String> getIndexTemplateContainsSrv(int srvId);\n\n    /**\n     * 用索引模板的写操作。\n     *\n     * @param templateId 要操作的模板的 id\n     * @param status     0：否，1：是\n     * @param operator   触发操作的操作员\n     * @param projectId  项目编号\n     * @return Result<Void>\n     */\n    Result<Void> blockWrite(Integer templateId, Boolean status, String operator, Integer projectId);\n\n    /**\n     * 用于索引模板的读取。\n     *\n     * @param templateId 要操作的模板的 id\n     * @param status     0：否，1：是\n     * @param operator   触发操作的用户\n     * @param projectId  项目编号\n     * @return Result<Void>\n     */\n    Result<Void> blockRead(Integer templateId, Boolean status, String operator, Integer projectId);\n\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/TemplateSrvManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.PageSearchHandleTypeEnum.TEMPLATE_SRV;\n\nimport com.didichuxing.datachannel.arius.admin.biz.page.TemplateSrvPageSearchHandle;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.BaseTemplateSrv;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.cold.ColdManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv.ColdSrvOpenDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv.TemplateQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.srv.TemplateSrv;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.srv.UnavailableTemplateSrv;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.srv.TemplateWithSrvVO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.SupportSrv;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleThree;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.DependsOn;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author chengxiang\n * @date 2022/5/9\n */\n@Service()\n@DependsOn(\"springTool\")\npublic class TemplateSrvManagerImpl implements TemplateSrvManager {\n    protected static final ILog                                         LOGGER                                                    = LogFactory\n        .getLog(TemplateSrvManagerImpl.class);\n\n    private static final String                                         NO_PERMISSION_CONTENT                                     = \"只有运维或者研发才有权限操作\";\n\n    private static final String                                         CLUSTER_LOGIC_NOT_EXISTS                                  = \"逻辑集群不存在\";\n    private static final String                                         PHYSICAL_CLUSTER_NOT_EXISTS                               = \"物理集群不存在\";\n\n    private final Map<Integer, BaseTemplateSrv>                         BASE_TEMPLATE_SRV_MAP                                     = Maps\n        .newConcurrentMap();\n\n\n\n    @Autowired\n    private IndexTemplateService                                        indexTemplateService;\n\n    @Autowired\n    private ClusterPhyService                                           clusterPhyService;\n\n    @Autowired\n    private HandleFactory                                               handleFactory;\n    @Autowired\n    private RoleTool                                                    roleTool;\n   \n    @Autowired\n    private ColdManager          coldManager;\n\n    @Autowired\n    private OperateRecordService operateRecordService;\n\n    @PostConstruct\n    public void init() {\n        Map<String, BaseTemplateSrv> strTemplateSrvHandleMap = SpringTool.getBeansOfType(BaseTemplateSrv.class);\n        strTemplateSrvHandleMap.forEach((k, v) -> {\n            try {\n                TemplateServiceEnum srvEnum = v.templateSrv();\n                BASE_TEMPLATE_SRV_MAP.put(srvEnum.getCode(), v);\n            } catch (Exception e) {\n                LOGGER.error(\"class=TemplateSrvManagerImpl||method=init||error=\", e);\n            }\n        });\n        LOGGER.info(\"class=TemplateSrvManagerImpl||method=init||init finish\");\n    }\n\n    @Override\n    public Result<List<TemplateSrv>> getTemplateOpenSrv(Integer logicTemplateId) {\n        try {\n            IndexTemplate template = indexTemplateService.getLogicTemplateById(logicTemplateId);\n            if (null == template) {\n                return Result.buildNotExist(\"逻辑模板不存在\");\n            }\n\n            return Result.buildSucc(TemplateSrv.codeStr2SrvList(template.getOpenSrv()));\n        } catch (Exception e) {\n            LOGGER.error(\"class=TemplateSrvManagerImpl||method=getTemplateOpenSrv||logicTemplateId={}\", logicTemplateId,\n                e);\n            return Result.buildFail(\"获取模板开启服务失败\");\n        }\n    }\n\n    @Override\n    public boolean isTemplateSrvOpen(Integer logicTemplateId, Integer srvCode) {\n        Result<List<TemplateSrv>> openSrvResult = getTemplateOpenSrv(logicTemplateId);\n        if (openSrvResult.failed()) {\n            return false;\n        }\n\n        List<TemplateSrv> openSrv = openSrvResult.getData();\n        for (TemplateSrv srv : openSrv) {\n            if (srvCode.equals(srv.getSrvCode())) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public List<UnavailableTemplateSrv> getUnavailableSrvByTemplateAndMasterPhy(IndexTemplate template,\n                                                                                TupleThree<Boolean, Boolean, Boolean> existDCDRAndPipelineModule) {\n        List<UnavailableTemplateSrv> unavailableSrvList = Lists.newCopyOnWriteArrayList();\n        List<TemplateServiceEnum> allSrvList = TemplateServiceEnum.allTemplateSrv();\n        //默认给一个srv就可以了\n        BaseTemplateSrv srvHandle = BASE_TEMPLATE_SRV_MAP.get(TemplateServiceEnum.TEMPLATE_COLD.getCode());\n        SupportSrv supportSrv =srvHandle.getSupportSrvByLogicTemplateAndMasterClusterPhy(template,\n                existDCDRAndPipelineModule);\n        final boolean dcdrSupport = supportSrv.isDcdrModuleExists();\n        final boolean pipelineSupport = supportSrv.isPipelineModuleExists();\n        boolean coldRegionSupport = supportSrv.isColdRegionExists();\n        //校验是否具备分区能力：冷热划分的能力、过期删除\n        // isPartition为true代表能分区，false不能分区\n        boolean isPartition =supportSrv.isPartition();\n        /**\n         * 预创建，过期删除（分区才可以操作），冷热分离（分区并且有冷region才能操作），dcdr和pipeline（es有对应module才能操作），rolloer没有限制但是产品侧有提示\n         */\n        for (TemplateServiceEnum srvEnum : allSrvList) {\n        \n           \n            //1.非分区模版不支持：预创建、过期删除、冷热划分的能力\n            if (Boolean.FALSE.equals(isPartition)&&TemplateServiceEnum.usePartitionService().contains(srvEnum)){\n                final UnavailableTemplateSrv unavailableTemplateSrv = new UnavailableTemplateSrv(srvEnum.getCode(),\n                        srvEnum.getServiceName(), srvEnum.getEsClusterVersion().getVersion(),\n                        String.format(\"非分区模版不支持%s能力\", srvEnum.getServiceName()));\n                unavailableSrvList.add(unavailableTemplateSrv);\n            } else\n                // 2.必须存在冷region才支持 少了一步判断 等待cold支持\n                if (Boolean.FALSE.equals(coldRegionSupport) && srvEnum.equals(TemplateServiceEnum.TEMPLATE_COLD)) {\n                    final UnavailableTemplateSrv unavailableTemplateSrv = new UnavailableTemplateSrv(srvEnum.getCode(),\n                            srvEnum.getServiceName(), srvEnum.getEsClusterVersion().getVersion(),\n                            \"集群没有冷region，不支持此能力\");\n                    unavailableSrvList.add(unavailableTemplateSrv);\n                    \n                } else\n                    //3.dcdr dcdrSupport==true支持\n                    if (Boolean.FALSE.equals(dcdrSupport) && srvEnum.equals(TemplateServiceEnum.TEMPLATE_DCDR)) {\n                        final UnavailableTemplateSrv unavailableTemplateSrv = new UnavailableTemplateSrv(\n                                srvEnum.getCode(), srvEnum.getServiceName(), srvEnum.getEsClusterVersion().getVersion(),\n                                \"无DCDR插件，不支持此能力\");\n                        unavailableSrvList.add(unavailableTemplateSrv);\n                    } else\n            //4.pipeline pipelineSupport==true支持\n            if (Boolean.FALSE.equals(pipelineSupport)&&srvEnum.equals(TemplateServiceEnum.TEMPLATE_PIPELINE)){\n                final UnavailableTemplateSrv unavailableTemplateSrv = new UnavailableTemplateSrv(srvEnum.getCode(),\n                        srvEnum.getServiceName(), srvEnum.getEsClusterVersion().getVersion(),\n                        \"集群中没有pipeline 插件，不支持此能力\");\n                unavailableSrvList.add(unavailableTemplateSrv);\n            }\n        }\n        return unavailableSrvList;\n    }\n\n    @Override\n    public PaginationResult<TemplateWithSrvVO> pageGetTemplateWithSrv(TemplateQueryDTO condition, Integer projectId) throws NotFindSubclassException {\n        BaseHandle baseHandle = handleFactory.getByHandlerNamePer(TEMPLATE_SRV.getPageSearchType());\n        if (baseHandle instanceof TemplateSrvPageSearchHandle) {\n            if (condition.getProjectId() == null && !AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n                condition.setProjectId(projectId);\n            }\n            TemplateSrvPageSearchHandle handler = (TemplateSrvPageSearchHandle) baseHandle;\n            return handler.doPage(condition, projectId);\n        }\n        return PaginationResult.buildFail(\"没有找到对应的处理器\");\n    }\n\n    @Override\n    public Result<Void> openSrv(Integer srvCode, List<Integer> templateIdList, String operator, Integer projectId,\n                                ColdSrvOpenDTO data) {\n        BaseTemplateSrv srvHandle = BASE_TEMPLATE_SRV_MAP.get(srvCode);\n        if (null == srvHandle) {\n            return Result.buildParamIllegal(\"未找到对应的服务\");\n        }\n\n        try {\n            if (Objects.nonNull(data)) {\n                Result<Integer> result = coldManager.batchChangeHotDay(data.getColdSaveDays(), operator, templateIdList,\n                    projectId);\n                if (result.failed()) {\n                    return Result.buildFrom(result);\n                }\n            }\n            return srvHandle.openSrv(templateIdList, operator, projectId);\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=TemplateSrvManagerImpl||method=openSrv||templateIdList={}||srvCode={}\"\n                         + \"||errMsg=failed to open template srv\",\n                ListUtils.intList2String(templateIdList), srvCode);\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    @Override\n    public Result<Void> closeSrv(Integer srvCode, List<Integer> templateIdList, String operator, Integer projectId) {\n        BaseTemplateSrv srvHandle = BASE_TEMPLATE_SRV_MAP.get(srvCode);\n        if (null == srvHandle) {\n            return Result.buildParamIllegal(\"未找到对应服务\");\n        }\n\n        try {\n            return srvHandle.closeSrv(templateIdList, operator, projectId);\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=TemplateSrvManagerImpl||method=closeSrv||templateIdList={}||srvCode={}\"\n                         + \"||errMsg=failed to open template srv\",\n                ListUtils.intList2String(templateIdList), srvCode);\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n\n    \n\n\n\n\n   \n\n\n\n    /**\n     * 查询开启了某个索引服务的物理集群列表\n     *\n     * @param srvId\n     * @return\n     */\n    @Override\n    public List<String> getPhyClusterByOpenTemplateSrv(int srvId) {\n        \n        return clusterPhyService.listAllClusters().stream().map(ClusterPhy::getCluster).collect(Collectors.toList());\n    }\n  \n    /**\n     * 查询开启了某个索引服务的索引模板列表\n     *\n     * @param srvId srvid\n     * @return {@link List}<{@link String}>\n     */\n      @Override\n    public List<String> getIndexTemplateContainsSrv(int srvId) {\n       return indexTemplateService.listAllLogicTemplatesWithCache()\n                .stream()\n                .filter(indexTemplate -> TemplateServiceEnum.strContainsSrv( indexTemplate.getOpenSrv(),TemplateServiceEnum.TEMPLATE_PIPELINE))\n                .map(IndexTemplate::getName)\n                .collect(Collectors.toList());\n    }\n\n    /**\n     * 用索引模板的写操作。\n     *\n     * @param templateId 要操作的模板的id\n     * @param status 0：否，1：是\n     * @param operator 触发操作的操作员\n     * @param projectId 项目编号\n     * @return Result<Void>\n     */\n    @Override\n    public Result<Void> blockWrite(Integer templateId, Boolean status, String operator, Integer projectId) {\n        IndexTemplatePO logicTemplate = indexTemplateService.getLogicTemplatePOById(templateId);\n\n        if (Objects.isNull(logicTemplate)) {\n            return Result.buildFail(\"索引模板不存在\");\n        }\n        Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(IndexTemplatePO::getProjectId,\n                logicTemplate, projectId);\n        if (checkProjectCorrectly.failed()) {\n            return checkProjectCorrectly;\n        }\n\n        Result<Void> result = indexTemplateService.updateBlockWriteState(templateId, status);\n        if (result.success()) {\n            // 是否禁写，0：否，1：是\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    Objects.equals(status, Boolean.TRUE) ? \"禁写\" : \"开启写\", operator, projectId, templateId,\n                    OperateTypeEnum.TEMPLATE_MANAGEMENT_CREATE);\n        }\n\n        return result;\n    }\n\n\n    /**\n     * 用于索引模板的读取。\n     *\n     * @param templateId 要操作的模板的id\n     * @param status 0：否，1：是\n     * @param operator 触发操作的用户\n     * @param projectId 项目编号\n     * @return Result<Void>\n     */\n    @Override\n    public Result<Void> blockRead(Integer templateId, Boolean status, String operator, Integer projectId) {\n        IndexTemplatePO logicTemplate = indexTemplateService.getLogicTemplatePOById(templateId);\n\n        if (Objects.isNull(logicTemplate)) {\n            return Result.buildFail(\"索引模板不存在\");\n        }\n        Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(IndexTemplatePO::getProjectId,\n                logicTemplate, projectId);\n        if (checkProjectCorrectly.failed()) {\n            return checkProjectCorrectly;\n        }\n        Result<Void> result = indexTemplateService.updateBlockReadState(templateId, status);\n        if (result.success()) {\n            // 是否禁写，0：否，1：是\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    Objects.equals(status, Boolean.TRUE) ? \"禁读\" : \"开启读\", operator, projectId, templateId,\n                    OperateTypeEnum.TEMPLATE_MANAGEMENT_CREATE);\n        }\n\n        return result;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/aliases/TemplateLogicAliasManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.aliases;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.ConsoleAliasDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.ConsoleLogicTemplateAliasesDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateAlias;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyAlias;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\n\nimport java.util.List;\n\npublic interface TemplateLogicAliasManager {\n\n    /**\n     * 获取别名\n     * @return list\n     */\n    List<IndexTemplateAlias> listAlias();\n\n    /**\n     * 获取别名\n     * @return list\n     */\n    List<IndexTemplateAlias> listAlias(List<IndexTemplateWithPhyTemplates> templateLogicList);\n\n    /**\n     * 根据逻辑模板ID获取对应别名详情列表\n     * @param logicId 逻辑ID\n     * @return\n     */\n    Result<List<IndexTemplatePhyAlias>> fetchTemplateAliasesByLogicId(Integer logicId);\n\n    /**\n     * 创建逻辑索引模板别名\n     * @param logicId 逻辑模板ID\n     * @param aliases 别名列表\n     * @return\n     */\n    Result<Void> createTemplateAliases(Integer logicId, List<ConsoleAliasDTO> aliases);\n\n    /**\n     * 更新逻辑模板别名\n     * @param logicId 逻辑模板ID\n     * @param aliases 别名列表\n     * @return\n     */\n    Result<Void> modifyTemplateAliases(Integer logicId, List<ConsoleAliasDTO> aliases);\n\n    /**\n     * 删除模板别名列表\n     * @param logicId 逻辑模板ID\n     * @param aliases 别名列表\n     * @return\n     */\n    Result<Void> deleteTemplateAliases(Integer logicId, List<String> aliases);\n\n    /**\n     * 获取别名\n     * @param logicId logicId\n     * @return list\n     */\n    List<IndexTemplateAlias> getAliasesById(Integer logicId);\n\n    /**\n     * getAliases\n     * @param logicId\n     * @return\n     */\n    Result<List<IndexTemplatePhyAlias>> getAliases(Integer logicId);\n\n    /**\n     * createAliases\n     * @param aliases\n     * @param operator\n     * @return\n     */\n    Result<Void> createAliases(ConsoleLogicTemplateAliasesDTO aliases, String operator);\n\n    /**\n     * modifyAliases\n     * @param aliases\n     * @param operator\n     * @return\n     */\n    Result<Void> modifyAliases(ConsoleLogicTemplateAliasesDTO aliases, String operator);\n\n    /**\n     * getAllTemplateAliasesByProjectId\n     * @param projectId\n     * @return\n     */\n    Result<List<Tuple<String/*index*/, String/*aliases*/>>> getAllTemplateAliasesByProjectId(Integer projectId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/aliases/TemplatePhyAliasManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.aliases;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyAlias;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 物理模板别名服务类\n * @author wangshu\n * @date 2020/08/24\n */\npublic interface TemplatePhyAliasManager {\n    /**\n     * 获取模板别名列表\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @return\n     */\n    List<IndexTemplatePhyAlias> fetchTemplateAliases(String cluster, String templateName) throws ESOperateException;\n\n    /**\n     * 获取所有模板别名列表\n     * @param clusters 集群名\n     * @return\n     * @throws ESOperateException\n     */\n    Map<String, List<IndexTemplatePhyAlias>> fetchAllTemplateAliases(List<String> clusters) throws ESOperateException;\n\n    /**\n     * 创建模板别名\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param templateAlias 模板别名\n     * @return\n     */\n    boolean createTemplateAlias(String cluster, String templateName,\n                                IndexTemplatePhyAlias templateAlias) throws ESOperateException;\n\n    /**\n     * 创建模板别名\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param templateAliases 模板别名\n     * @return\n     */\n    boolean batchCreateTemplateAliases(String cluster, String templateName,\n                                       List<IndexTemplatePhyAlias> templateAliases) throws ESOperateException;\n\n    /**\n     * 删除模板别名\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param alias 别名名称\n     * @return\n     * @throws ESOperateException\n     */\n    boolean deleteTemplateAlias(String cluster, String templateName, String alias) throws ESOperateException;\n\n    /**\n     * 删除模板别名列表\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param aliases 别名列表\n     * @return\n     * @throws ESOperateException\n     */\n    boolean deleteTemplateAliases(String cluster, String templateName, List<String> aliases) throws ESOperateException;\n\n    /**\n     * 删除物理模板所有别名\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @return\n     * @throws ESOperateException\n     */\n    boolean clearTemplateAliases(String cluster, String templateName) throws ESOperateException;\n\n    /**\n     * 更新模板别名信息\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param templateAlias 模板别名信息\n     * @return\n     * @throws ESOperateException\n     */\n    boolean modifyTemplateAlias(String cluster, String templateName,\n                                IndexTemplatePhyAlias templateAlias) throws ESOperateException;\n\n    /**\n     * 更新模板别名信息\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param templateAliases 模板别名信息\n     * @return\n     * @throws ESOperateException\n     */\n    boolean modifyTemplateAliases(String cluster, String templateName,\n                                  List<IndexTemplatePhyAlias> templateAliases) throws ESOperateException;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/aliases/impl/TemplateLogicAliasManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.aliases.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.aliases.TemplateLogicAliasManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.aliases.TemplatePhyAliasManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.impl.BaseTemplateSrvImpl;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.ConsoleAliasDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.ConsoleLogicTemplateAliasesDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateAlias;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyAlias;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Set;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author zqr\n * @date 2020-09-09\n */\n@Service\npublic class TemplateLogicAliasManagerImpl extends BaseTemplateSrvImpl implements TemplateLogicAliasManager {\n\n    private static final String             OPERATION_FAILED_TIPS = \"操作失败，请重试！\";\n\n    private static final String             OPERATOR_IS_NULL_TIPS = \"操作人为空\";\n\n    @Autowired\n    private TemplatePhyAliasManager         templatePhyAliasManager;\n\n    @Autowired\n    private ESIndexService                  esIndexService;\n\n    @Autowired\n    private ProjectLogicTemplateAuthService projectLogicTemplateAuthService;\n\n    /**\n     * @return\n     */\n    @Override\n    public TemplateServiceEnum templateSrv() {\n        return TemplateServiceEnum.TEMPLATE_ALIASES;\n    }\n\n    /**\n     * 获取别名\n     * 注意：模板量大, 耗时较久, 会一直占用线程无法释放, 持续请求进来会耗干资源\n     * @return list\n     */\n    @Override\n    public List<IndexTemplateAlias> listAlias() {\n        return listAlias(indexTemplateService.listAllLogicTemplateWithPhysicals());\n    }\n\n    /**\n     * 获取别名\n     *\n     * @return list\n     */\n    @Override\n    public List<IndexTemplateAlias> listAlias(List<IndexTemplateWithPhyTemplates> templateLogicList) {\n        List<IndexTemplateAlias> aliases = new ArrayList<>();\n        Set<String> clusters = new HashSet<>();\n        for (IndexTemplateWithPhyTemplates templateLogicWithPhyTemplates : templateLogicList) {\n            if (null != templateLogicWithPhyTemplates && null != templateLogicWithPhyTemplates.getMasterPhyTemplate()\n                && StringUtils.isNotBlank(templateLogicWithPhyTemplates.getMasterPhyTemplate().getCluster())) {\n                clusters.add(templateLogicWithPhyTemplates.getMasterPhyTemplate().getCluster());\n            }\n        }\n\n        try {\n            Map<String, List<IndexTemplatePhyAlias>> map = templatePhyAliasManager\n                .fetchAllTemplateAliases(new ArrayList<>(clusters));\n            for (IndexTemplateWithPhyTemplates templateLogic : templateLogicList) {\n                final List<IndexTemplatePhyAlias> indexTemplatePhyAliases = Optional.ofNullable(templateLogic)\n                    .map(IndexTemplate::getName).filter(map::containsKey).map(map::get).orElse(Lists.newArrayList());\n                for (IndexTemplatePhyAlias physicalAlias : indexTemplatePhyAliases) {\n                    aliases.add(fetchAlias(templateLogic.getId(), physicalAlias));\n                }\n            }\n\n        } catch (ESOperateException e) {\n            LOGGER.error(\n                \"class=TemplateLogicAliasesManagerImpl||method=listAlias||msg=esTemplateNotFound||clusters={}\",\n                clusters);\n        }\n\n        return aliases;\n    }\n\n    @Override\n    public Result<List<IndexTemplatePhyAlias>> fetchTemplateAliasesByLogicId(Integer logicId) {\n        Result<IndexTemplatePhy> result = fetchAnyOneLogicTemplateMasterPhysicalTemplate(logicId);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n\n        IndexTemplatePhy indexTemplatePhy = result.getData();\n\n        try {\n            return Result.buildSucc(templatePhyAliasManager.fetchTemplateAliases(indexTemplatePhy.getCluster(),\n                indexTemplatePhy.getName()));\n        } catch (ESOperateException e) {\n            LOGGER.warn(\"class=TemplateLogicAliasesManagerImpl||method=fetchTemplateAliasesByLogicId||\"\n                        + \"msg=failedFetchTemplateAliases||cluster={}||templateName={}\",\n                indexTemplatePhy.getCluster(), indexTemplatePhy.getName(), e);\n\n            return Result.buildFail(\"操作失败，请稍后重试：\" + e.getMessage());\n        }\n    }\n\n    @Override\n    public Result<Void> createTemplateAliases(Integer logicId, List<ConsoleAliasDTO> aliases) {\n        Result<IndexTemplatePhy> result = fetchAnyOneLogicTemplateMasterPhysicalTemplate(logicId);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n\n        IndexTemplatePhy indexTemplatePhy = result.getData();\n        if (!isTemplateSrvOpen(indexTemplatePhy.getLogicId())) {\n            return Result.buildFail(indexTemplatePhy.getName() + \"没有开启\" + templateServiceName());\n        }\n\n        try {\n            if (templatePhyAliasManager.batchCreateTemplateAliases(indexTemplatePhy.getCluster(),\n                indexTemplatePhy.getName(), convertAliases(aliases))) {\n                return Result.buildSucc();\n            }\n        } catch (ESOperateException e) {\n            return Result.buildFail(e.getMessage());\n        }\n\n        return Result.buildFail(OPERATION_FAILED_TIPS);\n    }\n\n    @Override\n    public Result<Void> modifyTemplateAliases(Integer logicId, List<ConsoleAliasDTO> aliases) {\n        Result<IndexTemplatePhy> result = fetchAnyOneLogicTemplateMasterPhysicalTemplate(logicId);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n\n        IndexTemplatePhy indexTemplatePhy = result.getData();\n        if (!isTemplateSrvOpen(indexTemplatePhy.getLogicId())) {\n            return Result.buildFail(indexTemplatePhy.getName() + \"没有开启\" + templateServiceName());\n        }\n\n        try {\n            if (templatePhyAliasManager.modifyTemplateAliases(indexTemplatePhy.getCluster(), indexTemplatePhy.getName(),\n                convertAliases(aliases))) {\n                return Result.buildSucc();\n            }\n        } catch (ESOperateException e) {\n            return Result.buildFail(e.getMessage());\n        }\n\n        return Result.buildFail(OPERATION_FAILED_TIPS);\n\n    }\n\n    /**\n     * 删除模板别名列表\n     * @param logicId 逻辑模板ID\n     * @param aliases 别名列表\n     * @return\n     */\n    @Override\n    public Result<Void> deleteTemplateAliases(Integer logicId, List<String> aliases) {\n        Result<IndexTemplatePhy> result = fetchAnyOneLogicTemplateMasterPhysicalTemplate(logicId);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n\n        IndexTemplatePhy indexTemplatePhy = result.getData();\n\n        if (!isTemplateSrvOpen(indexTemplatePhy.getLogicId())) {\n            return Result.buildFail(indexTemplatePhy.getName() + \"没有开启\" + templateServiceName());\n        }\n\n        try {\n            if (templatePhyAliasManager.deleteTemplateAliases(indexTemplatePhy.getCluster(), indexTemplatePhy.getName(),\n                aliases)) {\n                return Result.buildSucc();\n            }\n        } catch (ESOperateException e) {\n            return Result.buildFail(e.getMessage());\n        }\n\n        return Result.buildFail(OPERATION_FAILED_TIPS);\n    }\n\n    @Override\n    public List<IndexTemplateAlias> getAliasesById(Integer logicId) {\n        List<IndexTemplateAlias> templateAliases = new ArrayList<>();\n\n        Result<List<IndexTemplatePhyAlias>> result = fetchTemplateAliasesByLogicId(logicId);\n        if (result.success()) {\n            List<IndexTemplatePhyAlias> aliases = result.getData();\n            for (IndexTemplatePhyAlias physicalAlias : aliases) {\n                templateAliases.add(fetchAlias(logicId, physicalAlias));\n            }\n        }\n\n        return templateAliases;\n\n    }\n\n    @Override\n    public Result<List<IndexTemplatePhyAlias>> getAliases(Integer logicId) {\n        return fetchTemplateAliasesByLogicId(logicId);\n    }\n\n    @Override\n    public Result<Void> createAliases(ConsoleLogicTemplateAliasesDTO aliases, String operator) {\n        if (AriusObjUtils.isNull(operator)) {\n            return Result.buildParamIllegal(OPERATOR_IS_NULL_TIPS);\n        }\n\n        if (aliases == null || CollectionUtils.isEmpty(aliases.getAliases())) {\n            return Result.buildParamIllegal(\"别名信息非法\");\n        }\n\n        Result<Void> operationResult = createTemplateAliases(aliases.getLogicId(), aliases.getAliases());\n        if (operationResult.success()) {\n            operateRecordService.saveOperateRecordWithManualTrigger(\"别名创建\", operator, AuthConstant.SUPER_PROJECT_ID,\n                    aliases.getLogicId(), OperateTypeEnum.INDEX_MANAGEMENT_ALIAS_MODIFY);\n        }\n\n        return operationResult;\n\n    }\n\n    @Override\n    public Result<Void> modifyAliases(ConsoleLogicTemplateAliasesDTO aliases, String operator) {\n        if (AriusObjUtils.isNull(operator)) {\n            return Result.buildParamIllegal(OPERATOR_IS_NULL_TIPS);\n        }\n\n        if (aliases == null || CollectionUtils.isEmpty(aliases.getAliases())) {\n            return Result.buildParamIllegal(\"别名信息非法\");\n        }\n\n        Result<Void> operationResult = modifyTemplateAliases(aliases.getLogicId(), aliases.getAliases());\n        if (operationResult.success()) {\n            operateRecordService\n                .save(new OperateRecord.Builder().operationTypeEnum(OperateTypeEnum.INDEX_MANAGEMENT_ALIAS_MODIFY)\n                    .triggerWayEnum(TriggerWayEnum.MANUAL_TRIGGER).bizId(aliases.getLogicId()).content(\"别名修改\")\n                    .userOperation(operator).build());\n        }\n\n        return operationResult;\n    }\n\n    @Override\n    public Result<List<Tuple<String, String>>> getAllTemplateAliasesByProjectId(Integer projectId) {\n        List<Tuple<String, String>> aliases = new ArrayList<>();\n\n        List<ProjectTemplateAuth> projectTemplateAuths = projectLogicTemplateAuthService\n            .getTemplateAuthsByProjectId(projectId);\n        if (CollectionUtils.isEmpty(projectTemplateAuths)) {\n            return Result.build(true);\n        }\n\n        projectTemplateAuths.parallelStream().forEach(appTemplateAuth -> {\n            IndexTemplateWithPhyTemplates logicWithPhysical = this.indexTemplateService\n                .getLogicTemplateWithPhysicalsById(appTemplateAuth.getTemplateId());\n\n            if (null != logicWithPhysical && logicWithPhysical.hasPhysicals()) {\n                IndexTemplatePhy indexTemplatePhysicalInfo = logicWithPhysical.getPhysicals().get(0);\n\n                if (!isTemplateSrvOpen(indexTemplatePhysicalInfo.getLogicId())) {\n                    return;\n                }\n\n                aliases.addAll(esIndexService.syncGetIndexAliasesByExpression(indexTemplatePhysicalInfo.getCluster(),\n                    indexTemplatePhysicalInfo.getExpression()));\n            }\n        });\n\n        return Result.buildSucc(aliases);\n    }\n\n    /**************************************** private method ****************************************************/\n    /**\n     * 获取逻辑模板Master角色物理模板\n     * @param logicId 逻辑模板ID\n     * @return\n     */\n    private Result<IndexTemplatePhy> fetchAnyOneLogicTemplateMasterPhysicalTemplate(Integer logicId) {\n        if (logicId == null) {\n            return Result.buildNotExist(\"非法的逻辑ID： \" + logicId);\n        }\n\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (templateLogicWithPhysical == null) {\n            return Result.buildNotExist(\"逻辑模板不存在, ID:\" + logicId);\n        }\n\n        if (!templateLogicWithPhysical.hasPhysicals()) {\n            return Result.buildNotExist(\"物理模板不存在，ID:\" + logicId);\n        }\n\n        IndexTemplatePhy indexTemplatePhy = templateLogicWithPhysical.getMasterPhyTemplate();\n        if (indexTemplatePhy != null) {\n            return Result.buildSucc(indexTemplatePhy);\n        }\n\n        return Result.buildNotExist(\"逻辑模板不存在Master角色物理模板，ID:\" + logicId);\n    }\n\n    /**\n     * 解析生成别名\n     * @param logicId 逻辑模板ID\n     * @param alias 别名名称\n     * @return\n     */\n    private IndexTemplateAlias fetchAlias(Integer logicId, IndexTemplatePhyAlias alias) {\n        if (alias != null) {\n            IndexTemplateAlias templateAlias = new IndexTemplateAlias();\n            templateAlias.setName(alias.getAlias());\n            templateAlias.setLogicId(logicId);\n            return templateAlias;\n        }\n\n        return null;\n    }\n\n    /**\n     * 转换别名列表\n     * @param aliasList 别名DTO列表\n     * @return\n     */\n    private List<IndexTemplatePhyAlias> convertAliases(List<ConsoleAliasDTO> aliasList) {\n        List<IndexTemplatePhyAlias> aliases = new ArrayList<>();\n        if (CollectionUtils.isNotEmpty(aliasList)) {\n            for (ConsoleAliasDTO aliasDTO : aliasList) {\n                aliases.add(convertAlias(aliasDTO));\n            }\n        }\n        return aliases;\n    }\n\n    /**\n     * 转换别名\n     * @param aliasDTO 别名DTO\n     * @return\n     */\n    private IndexTemplatePhyAlias convertAlias(ConsoleAliasDTO aliasDTO) {\n        if (aliasDTO != null) {\n            IndexTemplatePhyAlias alias = new IndexTemplatePhyAlias();\n            alias.setAlias(aliasDTO.getAlias());\n            alias.setFilter(aliasDTO.getFilter());\n            return alias;\n        }\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/aliases/impl/TemplatePhyAliasManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.aliases.impl;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.aliases.TemplatePhyAliasManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyAlias;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyAliases;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminESOpRetryConstants;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.impl.IndexTemplateServiceImpl;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.TemplateConfig;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Maps;\nimport java.util.List;\nimport java.util.Map;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * 模板别名服务\n * @author wangshu\n * @date 2020/08/24\n */\n@Service\npublic class TemplatePhyAliasManagerImpl implements TemplatePhyAliasManager {\n\n    private static final ILog Logger = LogFactory.getLog(IndexTemplateServiceImpl.class);\n\n    @Autowired\n    private ESTemplateService esTemplateService;\n\n    /**\n     * 获取模板别名列表\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @return\n     */\n    @Override\n    public List<IndexTemplatePhyAlias> fetchTemplateAliases(String cluster,\n                                                            String templateName) throws ESOperateException {\n        TemplateConfig templateConfig = fetchTemplateConfig(cluster, templateName);\n\n        IndexTemplatePhyAliases templateAliases = new IndexTemplatePhyAliases(templateConfig.getAliases());\n        return templateAliases.parseTemplateAliases();\n    }\n\n    /**\n     * 获取所有模板别名列表\n     * @param clusters 集群名\n     * @return\n     * @throws ESOperateException\n     */\n    @Override\n    public Map<String, List<IndexTemplatePhyAlias>> fetchAllTemplateAliases(List<String> clusters) throws ESOperateException {\n        Map<String, TemplateConfig> templateConfigMap = fetchAllTemplateConfig(clusters);\n\n        Map<String, List<IndexTemplatePhyAlias>> templatePhyAliasMap = Maps.newHashMap();\n\n        templateConfigMap.forEach((x, y) -> {\n            IndexTemplatePhyAliases templateAliases = new IndexTemplatePhyAliases(y.getAliases());\n            templatePhyAliasMap.put(x, templateAliases.parseTemplateAliases());\n        });\n\n        return templatePhyAliasMap;\n    }\n\n    /**\n     * 创建模板别名\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param templateAlias 模板别名\n     * @return\n     */\n    @Override\n    public boolean createTemplateAlias(String cluster, String templateName,\n                                       IndexTemplatePhyAlias templateAlias) throws ESOperateException {\n        TemplateConfig templateConfig = fetchTemplateConfig(cluster, templateName);\n        IndexTemplatePhyAliases aliases = new IndexTemplatePhyAliases(templateConfig.getAliases());\n        if (!aliases.isAliasExists(templateAlias.getAlias())) {\n            aliases.putAlias(templateAlias.getAlias(), templateAlias.getFilter());\n            templateConfig.setAliases(aliases.getAliases());\n\n            return esTemplateService.syncUpdateTemplateConfig(cluster, templateName, templateConfig,\n                AdminESOpRetryConstants.DEFAULT_RETRY_COUNT);\n        } else {\n            throw new ESOperateException(\"别名已经存在，无法新建\");\n        }\n    }\n\n    @Override\n    public boolean batchCreateTemplateAliases(String cluster, String templateName,\n                                              List<IndexTemplatePhyAlias> templateAliases) throws ESOperateException {\n        TemplateConfig templateConfig = fetchTemplateConfig(cluster, templateName);\n        if (CollectionUtils.isNotEmpty(templateAliases)) {\n            IndexTemplatePhyAliases aliases = new IndexTemplatePhyAliases(templateConfig.getAliases());\n            for (IndexTemplatePhyAlias alias : templateAliases) {\n                aliases.putAlias(alias.getAlias(), alias.getFilter());\n                templateConfig.setAliases(aliases.getAliases());\n            }\n\n            return esTemplateService.syncUpdateTemplateConfig(cluster, templateName, templateConfig,\n                AdminESOpRetryConstants.DEFAULT_RETRY_COUNT);\n        }\n\n        throw new ESOperateException(\"模板别名列表不能为空\");\n    }\n\n    /**\n     * 删除模板别名\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param alias 别名名称\n     * @return\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean deleteTemplateAlias(String cluster, String templateName, String alias) throws ESOperateException {\n\n        TemplateConfig templateConfig = fetchTemplateConfig(cluster, templateName);\n\n        IndexTemplatePhyAliases aliases = new IndexTemplatePhyAliases(templateConfig.getAliases());\n        if (StringUtils.isNotBlank(alias) && aliases.isAliasExists(alias)) {\n            aliases.removeAlias(alias);\n            templateConfig.setAliases(aliases.getAliases());\n\n            return esTemplateService.syncUpdateTemplateConfig(cluster, templateName, templateConfig,\n                AdminESOpRetryConstants.DEFAULT_RETRY_COUNT);\n        }\n\n        return true;\n    }\n\n    /**\n     * 删除模板别名列表\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param aliases 别名列表\n     * @return\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean deleteTemplateAliases(String cluster, String templateName,\n                                         List<String> aliases) throws ESOperateException {\n        if (CollectionUtils.isEmpty(aliases)) {\n            throw new ESOperateException(\"待删除模板别名列表不能为空\");\n        }\n\n        TemplateConfig templateConfig = fetchTemplateConfig(cluster, templateName);\n        IndexTemplatePhyAliases physicalAliases = new IndexTemplatePhyAliases(templateConfig.getAliases());\n        for (String alias : aliases) {\n            physicalAliases.removeAlias(alias);\n        }\n\n        templateConfig.setAliases(physicalAliases.getAliases());\n        return esTemplateService.syncUpdateTemplateConfig(cluster, templateName, templateConfig,\n            AdminESOpRetryConstants.DEFAULT_RETRY_COUNT);\n    }\n\n    /**\n     * 删除物理模板所有别名\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @return\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean clearTemplateAliases(String cluster, String templateName) throws ESOperateException {\n\n        TemplateConfig templateConfig = fetchTemplateConfig(cluster, templateName);\n        templateConfig.setAliases(new JSONObject());\n        return esTemplateService.syncUpdateTemplateConfig(cluster, templateName, templateConfig,\n            AdminESOpRetryConstants.DEFAULT_RETRY_COUNT);\n    }\n\n    /**\n     * 更新模板别名信息\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param templateAlias 模板别名信息\n     * @return\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean modifyTemplateAlias(String cluster, String templateName,\n                                       IndexTemplatePhyAlias templateAlias) throws ESOperateException {\n        if (isValidAlias(cluster, templateName, templateAlias)) {\n            TemplateConfig templateConfig = fetchTemplateConfig(cluster, templateName);\n            IndexTemplatePhyAliases aliases = new IndexTemplatePhyAliases(templateConfig.getAliases());\n            if (aliases.isAliasExists(templateAlias.getAlias())) {\n                aliases.putAlias(templateAlias.getAlias(), templateAlias.getFilter());\n                templateConfig.setAliases(aliases.getAliases());\n                return esTemplateService.syncUpdateTemplateConfig(cluster, templateName, templateConfig,\n                    AdminESOpRetryConstants.DEFAULT_RETRY_COUNT);\n            }\n\n        }\n\n        return false;\n    }\n\n    /**\n     * 批量变更模板别名\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param templateAliases 模板别名信息\n     * @return\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean modifyTemplateAliases(String cluster, String templateName,\n                                         List<IndexTemplatePhyAlias> templateAliases) throws ESOperateException {\n        TemplateConfig templateConfig = fetchTemplateConfig(cluster, templateName);\n        if (CollectionUtils.isEmpty(templateAliases)) {\n            throw new ESOperateException(\"非法的参数\");\n        }\n\n        IndexTemplatePhyAliases aliases = new IndexTemplatePhyAliases(templateConfig.getAliases());\n        boolean isAliasesChanged = false;\n        for (IndexTemplatePhyAlias physicalAlias : templateAliases) {\n            if (aliases.isAliasExists(physicalAlias.getAlias())) {\n                aliases.putAlias(physicalAlias.getAlias(), physicalAlias.getFilter());\n                isAliasesChanged = true;\n            }\n        }\n\n        if (isAliasesChanged) {\n            templateConfig.setAliases(aliases.getAliases());\n            return esTemplateService.syncUpdateTemplateConfig(cluster, templateName, templateConfig,\n                AdminESOpRetryConstants.DEFAULT_RETRY_COUNT);\n        }\n\n        return true;\n    }\n\n    /**************************************** private method ****************************************************/\n    /**\n     * Check 是否是合法的别名\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @param templateAlias 模板别名\n     * @return\n     */\n    private boolean isValidAlias(String cluster, String templateName, IndexTemplatePhyAlias templateAlias) {\n        if (StringUtils.isBlank(cluster) || templateAlias == null || StringUtils.isBlank(templateName)\n            || StringUtils.isBlank(templateAlias.getAlias())) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * 获取模板配置\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @return\n     * @throws ESOperateException\n     */\n    private TemplateConfig fetchTemplateConfig(String cluster, String templateName) throws ESOperateException {\n        if (StringUtils.isBlank(cluster) || StringUtils.isBlank(templateName)) {\n            throw new ESOperateException(\"非法请求\");\n        }\n\n        TemplateConfig templateConfig = esTemplateService.syncGetTemplateConfig(cluster, templateName);\n        if (templateConfig == null) {\n            Logger.info(\"class=TemplatePhyAliasesManagerImpl||method=fetchTemplateConfig||\"\n                        + \"msg=templateNotFound||cluster={}||template={}\",\n                cluster, templateName);\n            throw new ESOperateException(\"模板配置不存在\");\n        }\n\n        return templateConfig;\n    }\n\n    private Map<String, TemplateConfig> fetchAllTemplateConfig(List<String> clusters) throws ESOperateException {\n        if (CollectionUtils.isEmpty(clusters)) {\n            throw new ESOperateException(\"非法请求\");\n        }\n\n        Map<String, TemplateConfig> templateConfigMap = esTemplateService.syncGetAllTemplates(clusters);\n        if (templateConfigMap == null) {\n            Logger.info(\"class=TemplatePhyAliasesManagerImpl||method=fetchAllTemplateConfig||\"\n                        + \"msg=templateNotFound||cluster={}\",\n                clusters);\n            throw new ESOperateException(\"模板配置不存在\");\n        }\n\n        return templateConfigMap;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/base/BaseTemplateSrv.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.base;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.SupportSrv;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleThree;\nimport java.util.List;\n\n/**\n * @author chengxiang\n * @date 2022/5/17\n */\npublic interface BaseTemplateSrv {\n\n    /**\n     * 判断指定逻辑模板是否开启了当前模板服务\n     * @param logicTemplateId 逻辑模板id\n     * @return 校验结果\n     */\n    boolean isTemplateSrvOpen(Integer logicTemplateId);\n\n    /**\n     * 获取当前模板服务的类型\n     *\n     * @return 指定的模板服务类型\n     */\n    TemplateServiceEnum templateSrv();\n\n    /**\n     * 获取当前模板服务的名称\n     * @return\n     */\n    String templateSrvName();\n\n    /**\n     * 开启指定逻辑模板的模板服务\n     *\n     * @param templateIdList\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Void> openSrv(List<Integer> templateIdList, String operator, Integer projectId) throws AdminOperateException;\n\n    /**\n     * 关闭指定逻辑模板的模板服务\n     *\n     * @param templateIdList\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Void> closeSrv(List<Integer> templateIdList, String operator,\n                          Integer projectId) throws AdminOperateException;\n\n    ///////////////////////////////////srv\n\n\n    /**\n     * 判断物理模板已经开启了当前索引服务（判断指定物理模板所在物理集群是否开启了当前索引服务）\n     * @param indexTemplatePhies 物理模板\n     * @return 校验结果\n     */\n    boolean isTemplateSrvOpen(List<IndexTemplatePhy> indexTemplatePhies);\n\n    /**\n     * 获取当前模板服务在模板服务集合类中的标识\n     * @see TemplateServiceEnum\n     * @return 模板服务描述\n     */\n    String templateServiceName();\n\n\n\n    \n    SupportSrv getSupportSrvByLogicTemplateAndMasterClusterPhy(IndexTemplate template,\n                                                               TupleThree</*dcdrExist*/Boolean,/*pipelineExist*/ Boolean,/*existColdRegion*/ Boolean> existDCDRAndPipelineModule);\n    \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/base/impl/BaseTemplateSrvImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.base.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterRegionManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplatePhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.TemplateSrvManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.BaseTemplateSrv;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.BaseResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateLogicWithClusterAndMasterTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.SupportSrv;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleThree;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport java.util.Objects;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author chengxiang\n * @date 2022/5/11\n */\npublic abstract class BaseTemplateSrvImpl implements BaseTemplateSrv {\n    protected static final ILog       LOGGER = LogFactory.getLog(BaseTemplateSrvImpl.class);\n\n    @Autowired\n    protected IndexTemplateService    indexTemplateService;\n\n    @Autowired\n    protected IndexTemplatePhyService indexTemplatePhyService;\n\n    @Autowired\n    protected TemplatePhyManager      templatePhyManager;\n    \n    @Autowired\n    protected TemplateSrvManager templateSrvManager;\n    \n    @Autowired\n    protected ClusterPhyManager      clusterPhyManager;\n    @Autowired\n    protected OperateRecordService   operateRecordService;\n    @Autowired\n    protected ProjectService         projectService;\n    @Autowired\n    protected AriusConfigInfoService ariusConfigInfoService;\n    @Autowired\n    protected ESClusterNodeService   esClusterNodeService;\n    @Autowired\n    protected ESClusterService       esClusterService;\n    @Autowired\n    protected ClusterRegionManager   clusterRegionManager;\n   \n    \n    @Override\n    public boolean isTemplateSrvOpen(Integer logicTemplateId) {\n        return templateSrvManager.isTemplateSrvOpen(logicTemplateId, templateSrv().getCode());\n    }\n\n    @Override\n    public String templateSrvName() {\n        return templateSrv().getServiceName();\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> openSrv(List<Integer> templateIdList, String operator,\n                                Integer projectId) throws AdminOperateException {\n        // 0.校验服务是否可以开启\n        for (Integer templateId : templateIdList) {\n            Result<Void> checkAvailableResult = checkSrvIsValid(templateId);\n            if (checkAvailableResult.failed()) {\n                return checkAvailableResult;\n            }\n        }\n\n        // 1.更新DB服务开启状态\n        Result<Void> updateResult = updateSrvStatus(templateIdList, Boolean.TRUE, operator, projectId);\n        if (updateResult.failed()) {\n            return updateResult;\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> closeSrv(List<Integer> templateIdList, String operator,\n                                 Integer projectId) throws AdminOperateException {\n        // 0.更新DB服务关闭状态\n        Result<Void> updateResult = updateSrvStatus(templateIdList, Boolean.FALSE, operator, projectId);\n        if (updateResult.failed()) {\n            return updateResult;\n        }\n\n        return Result.buildSucc();\n    }\n\n    protected Result<Void> checkSrvIsValid(Integer logicTemplateId) {\n        IndexTemplateLogicWithClusterAndMasterTemplate template = indexTemplateService\n            .getLogicTemplateWithClusterAndMasterTemplate(logicTemplateId);\n        if (null == template || null == template.getMasterTemplate()) {\n            LOGGER.warn(\n                \"class=ColdManagerImpl||method=isTemplateSrvAvailable||templateId={}||errMsg=masterPhyTemplate is null\",\n                logicTemplateId);\n            return Result.buildFail();\n        }\n\n        String masterCluster = template.getMasterTemplate().getCluster();\n        Result<ClusterPhy> cluster = clusterPhyManager.getClusterByName(masterCluster);\n        if (Objects.isNull(cluster.getData())) {\n            LOGGER.warn(\n                \"class=ColdManagerImpl||method=isTemplateSrvAvailable||templateId={}||errMsg=clusterPhy of template is null\",\n                logicTemplateId);\n            return Result.buildFail();\n        }\n\n        return Result.buildSucc();\n    }\n\n    /******************************************private************************************************/\n    /**\n     * 更新DB服务状态\n     *\n     * @param status,        true:开启, false:关闭\n     * @param templateIdList\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    private Result<Void> updateSrvStatus(List<Integer> templateIdList, Boolean status, String operator,\n                                         Integer projectId) throws AdminOperateException {\n        String srvCode = templateSrv().getCode().toString();\n        List<TupleTwo</*old*/IndexTemplate, /*change*/IndexTemplate>> tupleTwos = Lists.newArrayList();\n        for (Integer templateId : templateIdList) {\n            IndexTemplate indexTemplate = indexTemplateService.getLogicTemplateById(templateId);\n\n            if (null == indexTemplate) {\n                continue;\n            }\n            TupleTwo</*old*/IndexTemplate, /*change*/IndexTemplate> tupleTwo = Tuples.of(indexTemplate, null);\n            if (status) {\n                // 开启该项模版服务\n                addSrvCode(indexTemplate, srvCode);\n                // 如果是Rollover服务，则也要修改index_tmplate_config表中的disable_index_rollover字段\n                if (TemplateServiceEnum.INDEX_PLAN.getCode().toString().equals(srvCode)){\n                    updateTemplateConfigRollover(templateId, false, operator);\n                }\n            } else {\n                // 关闭该项模版服务\n                removeSrvCode(indexTemplate, srvCode);\n                if (TemplateServiceEnum.INDEX_PLAN.getCode().toString().equals(srvCode)){\n                    updateTemplateConfigRollover(templateId, true, operator);\n                }\n            }\n            tupleTwo = tupleTwo.update2(indexTemplate);\n            tupleTwos.add(tupleTwo);\n        }\n        //确认操作项目的合法性\n        if (tupleTwos\n            .stream().map(TupleTwo::v1).map(oldIndexTemplate -> ProjectUtils\n                .checkProjectCorrectly(IndexTemplate::getProjectId, oldIndexTemplate, projectId))\n            .allMatch(BaseResult::failed)) {\n            return Result.buildFail(\"当前项目不属于超级项目或者持有该操作的项目\");\n        }\n        for (TupleTwo<IndexTemplate, IndexTemplate> tupleTwo : tupleTwos) {\n            final Result<Void> result = indexTemplateService\n                .editTemplateInfoTODB(ConvertUtil.obj2Obj(tupleTwo.v2, IndexTemplateDTO.class));\n            if (result.success()) {\n                operateRecordService.saveOperateRecordWithManualTrigger(\n                        String.format(\"%s:【%s】\", Boolean.TRUE.equals(status) ? \"开启模板服务\" : \"关闭模板服务\",\n                                templateSrvName()), operator, projectId, tupleTwo.v2.getId(),\n                        OperateTypeEnum.TEMPLATE_SERVICE);\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 添加开启服务到对应模板实体中\n     * @param indexTemplate\n     * @param addSrvCode\n     * @return true:有修改, false:无修改；根据返回值判断是否需要刷新到DB\n     */\n    private void addSrvCode(IndexTemplate indexTemplate, String addSrvCode) {\n        String srvCodeStr = indexTemplate.getOpenSrv();\n        List<String> srvCodeList = ListUtils.string2StrList(srvCodeStr);\n        if (srvCodeList.isEmpty()) {\n            indexTemplate.setOpenSrv(addSrvCode);\n        } else {\n            if (!srvCodeList.contains(addSrvCode)) {\n                indexTemplate.setOpenSrv(srvCodeStr + \",\" + addSrvCode);\n            }\n        }\n    }\n\n    private void removeSrvCode(IndexTemplate indexTemplate, String removeSrvCode) {\n        String srvCodeStr = indexTemplate.getOpenSrv();\n        List<String> srvCodeList = ListUtils.string2StrList(srvCodeStr);\n        if (srvCodeList.contains(removeSrvCode)) {\n            srvCodeList.remove(removeSrvCode);\n            indexTemplate.setOpenSrv(ListUtils.strList2String(srvCodeList));\n        }\n    }\n\n    /**\n     * 更新index_template_config表中的disable_index_rollover字段\n     * @param templateId\n     * @param state disable_index_rollover是true还是false\n     * @param operator\n     * @return\n     */\n    private Result<Void> updateTemplateConfigRollover(Integer templateId, Boolean state, String operator){\n        IndexTemplateConfigDTO indexTemplateConfigDTO = new IndexTemplateConfigDTO();\n        indexTemplateConfigDTO.setLogicId(templateId);\n        indexTemplateConfigDTO.setDisableIndexRollover(state);\n        Result<Void> result = indexTemplateService.updateTemplateConfig(indexTemplateConfigDTO, operator);\n        if(result.failed()){\n            LOGGER.warn(\"class=BaseTemplateSrvImpl||method=updateTemplateConfigRollover||msg={}\", result.getMessage());\n            return result;\n        }\n        return Result.buildSucc();\n    }\n\n    ///////////////////////////////////srv\n  \n\n    @Override\n    public boolean isTemplateSrvOpen(List<IndexTemplatePhy> indexTemplatePhies) {\n        for (IndexTemplatePhy indexTemplatePhy : indexTemplatePhies) {\n            if (!isTemplateSrvOpen(indexTemplatePhy.getLogicId())) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    \n  \n\n    @Override\n    public String templateServiceName() {\n        return templateSrv().getServiceName();\n    }\n    \n    @Override\n    public SupportSrv getSupportSrvByLogicTemplateAndMasterClusterPhy(IndexTemplate logicIndexTemplate,\n                                                                      TupleThree<Boolean, Boolean, Boolean> existDCDRAndPipelineModule) {\n       \n        List<TemplateServiceEnum> templateServiceEnums = TemplateServiceEnum.str2Srv(logicIndexTemplate.getOpenSrv());\n        SupportSrv supportSrv = new SupportSrv();\n        supportSrv.setPartition(StringUtils.endsWith(logicIndexTemplate.getExpression(), \"*\"));\n        supportSrv.setDcdrModuleExists(\n                templateServiceEnums.contains(TemplateServiceEnum.TEMPLATE_DCDR)||Objects.equals(logicIndexTemplate.getHasDCDR(),\n                        Boolean.TRUE) || Boolean.TRUE.equals(\n                        existDCDRAndPipelineModule.v1));\n        supportSrv.setPipelineModuleExists(\n                templateServiceEnums.contains(TemplateServiceEnum.TEMPLATE_PIPELINE) || Boolean.TRUE.equals(\n                        existDCDRAndPipelineModule.v2));\n        supportSrv.setColdRegionExists(\n                templateServiceEnums.contains(TemplateServiceEnum.TEMPLATE_COLD) || Boolean.TRUE.equals(\n                        existDCDRAndPipelineModule.v3));\n    \n        return supportSrv;\n    }\n    \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/cold/ColdManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.cold;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport java.util.List;\n\n/**\n * @author chengxiang, zqr\n * @date 2022/5/13\n */\npublic interface ColdManager {\n\n    /**\n     * move2ColdNode\n     *\n     * @param logicTemplateId 逻辑模板id\n     * @return\n     */\n    Result<Boolean> move2ColdNode(Integer logicTemplateId) throws ESOperateException;\n\n    /**\n     * fetchClusterDefaultHotDay\n     * @param phyCluster\n     * @return\n     */\n    int fetchClusterDefaultHotDay(String phyCluster);\n\n    ///////////////srv\n    /**\n    * move2ColdNode\n    * @param cluster\n    * @return\n    */\n    @Deprecated\n    Result<Boolean> move2ColdNode(String cluster);\n\n    Result<Integer> batchChangeHotDay(Integer coldSaveDays, String operator, List<Integer> templateIdList,\n                                      Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/cold/impl/ColdManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.cold.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.ARIUS_COMMON_GROUP;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.ARIUS_TEMPLATE_COLD_GROUP;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.INDEX_TEMPLATE_COLD_DAY_DEFAULT;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.INDEX_TEMPLATE_COLD_DAY_DEFAULT_VALUE;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONException;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.impl.BaseTemplateSrvImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.cold.ColdManager;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegionFSInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.function.Function;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author chengxiang, zqr\n * @date 2022/5/13\n */\n@Service\npublic class ColdManagerImpl extends BaseTemplateSrvImpl implements ColdManager {\n\n    @Autowired\n    private ESIndexService       esIndexService;\n\n    @Autowired\n    private ClusterRegionService   clusterRegionService;\n    @Autowired\n    private ClusterRoleHostService clusterRoleHostService;\n\n    public static final int      MAX_HOT_DAY = 3;\n    public static final int      MIN_HOT_DAY = -2;\n\n    private final static Integer RETRY_TIME  = 3;\n\n    @Override\n    public TemplateServiceEnum templateSrv() {\n        return TemplateServiceEnum.TEMPLATE_COLD;\n    }\n\n    @Override\n    public Result<Boolean> move2ColdNode(Integer logicTemplateId) throws ESOperateException {\n        if (Boolean.FALSE.equals(isTemplateSrvOpen(logicTemplateId))) {\n            return Result.buildSucc();\n        }\n\n        IndexTemplateWithPhyTemplates logicTemplateWithPhysicals = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicTemplateId);\n        if (null == logicTemplateWithPhysicals) {\n            LOGGER.info(\n                    \"class=ColdManagerImpl||method=move2ColdNode||logicTemplateId={}||msg=ColdDataMoveTask no template\",\n                    logicTemplateId);\n            return Result.buildSucc();\n        }\n\n        IndexTemplatePhy masterPhyTemplate = logicTemplateWithPhysicals.getMasterPhyTemplate();\n        if (null == masterPhyTemplate) {\n            LOGGER.info(\n                    \"class=ColdManagerImpl||method=move2ColdNode||logicTemplateId={}||msg=ColdDataMoveTask no master template\",\n                    logicTemplateId);\n            return Result.buildSucc();\n        }\n\n        List<ClusterRegion> coldRegionList = clusterRegionService\n            .listColdRegionByCluster(masterPhyTemplate.getCluster());\n        if (CollectionUtils.isEmpty(coldRegionList)) {\n            LOGGER.warn(\"class=ColdManagerImpl||method=move2ColdNode||logicTemplate={}||no cold rack\", logicTemplateId);\n            return Result.buildSucc();\n        }\n        ClusterRegion minUsageColdRegion = getMinUsageColdRegion(masterPhyTemplate.getCluster(), coldRegionList);\n        //minUsageColdRegion可能为空\n        if (Objects.isNull(minUsageColdRegion)){\n            LOGGER.warn(\"class=ColdManagerImpl||method=move2ColdNode||logicTemplate={}||no cold rack\", logicTemplateId);\n            return Result.buildSucc();\n        }\n            Result<Void> moveResult = movePerTemplate(masterPhyTemplate, minUsageColdRegion.getId().intValue());\n            if (moveResult.failed()) {\n                LOGGER.warn(\"class=ColdManagerImpl||method=move2ColdNode||template={}||msg=move2ColdNode fail\",\n                    masterPhyTemplate.getName());\n                return Result.buildFrom(moveResult);\n            }\n       \n\n        return Result.build(Boolean.TRUE);\n    }\n\n    @Override\n    public int fetchClusterDefaultHotDay(String phyCluster) {\n        int hotDay = -1;\n        Set<String> enableClusterSet = ariusConfigInfoService.stringSettingSplit2Set(ARIUS_COMMON_GROUP,\n            \"platform.govern.cold.data.move2ColdNode.enable.clusters\", \"\", \",\");\n        if (enableClusterSet.contains(phyCluster)) {\n            int defaultHotDay = getDefaultHotDay();\n            if (defaultHotDay > 0) {\n                hotDay = defaultHotDay;\n            }\n        }\n\n        LOGGER.info(\n            \"class=TemplateColdManagerImpl||method=fetchClusterDefaultHotDay||msg=no changed||cluster={}||enableClusters={}||version={}\",\n            phyCluster, JSON.toJSONString(enableClusterSet), hotDay);\n\n        return hotDay;\n    }\n\n    ////////////////////////////private method/////////////////////////////////////\n    /**\n    * 获取配置默认hotDay值\n    *\n    * @return\n    */\n    private int getDefaultHotDay() {\n        String defaultDay = ariusConfigInfoService.stringSetting(ARIUS_TEMPLATE_COLD_GROUP,\n            INDEX_TEMPLATE_COLD_DAY_DEFAULT, INDEX_TEMPLATE_COLD_DAY_DEFAULT_VALUE);\n        LOGGER.info(\"class=TemplateColdManagerImpl||method=getDefaultHotDay||msg=defaultDay: {}\", defaultDay);\n        if (StringUtils.isNotBlank(defaultDay)) {\n            try {\n                JSONObject object = JSON.parseObject(defaultDay);\n                return object.getInteger(\"defaultHotDay\");\n            } catch (JSONException e) {\n                LOGGER.warn(\"class=TemplateColdManagerImpl||method=getDefaultHotDay||errMsg={}\", e.getMessage());\n            }\n        }\n        return -1;\n    }\n\n    /**\n     * 移动单个物理模板下的索引到冷节点\n     * @param templatePhysical\n     * @param coldRegionId\n     * @return\n     * @throws ESOperateException\n     */\n    private Result<Void> movePerTemplate(IndexTemplatePhy templatePhysical,\n                                         Integer coldRegionId) throws ESOperateException {\n        Tuple<Set<String>, Set<String>> coldAndHotIndices = getColdAndHotIndex(templatePhysical.getId());\n        Set<String> coldIndex = coldAndHotIndices.getV1();\n        Set<String> hotIndices = coldAndHotIndices.getV2();\n        \n        Boolean moveSuccFlag = Boolean.TRUE;\n        Function</*coldRegionId*/Integer,Result<List<ClusterRoleHost>>> coldRegionIdFunc=\n                coldId-> clusterRoleHostService.listByRegionId(coldId);\n        if (!CollectionUtils.isEmpty(coldIndex)) {\n            moveSuccFlag = esIndexService.syncBatchUpdateRegion(templatePhysical.getCluster(),\n                Lists.newArrayList(coldIndex), coldRegionId, RETRY_TIME,coldRegionIdFunc );\n        }\n\n        if (!moveSuccFlag && !CollectionUtils.isEmpty(hotIndices)) {\n            moveSuccFlag = esIndexService.syncBatchUpdateRegion(templatePhysical.getCluster(),\n                Lists.newArrayList(hotIndices), templatePhysical.getRegionId(), RETRY_TIME, coldRegionIdFunc);\n        }\n\n        return Result.build(moveSuccFlag);\n    }\n\n    /**\n     * 获取指定物理模板下的冷热索引\n     * @param physicalId\n     * @return\n     */\n    private Tuple</*冷节点索引列表*/Set<String>, /*热节点索引列表*/Set<String>> getColdAndHotIndex(Long physicalId) {\n        IndexTemplatePhyWithLogic templatePhysicalWithLogic = indexTemplatePhyService\n            .getTemplateWithLogicById(physicalId);\n        if (templatePhysicalWithLogic == null) {\n            return new Tuple<>();\n        }\n\n        int hotTime = templatePhysicalWithLogic.getLogicTemplate().getHotTime();\n\n        if (hotTime <= 0) {\n            LOGGER.info(\"class=ColdManagerImpl||method=getColdAndHotIndex||template={}||msg=hotTime illegal\",\n                templatePhysicalWithLogic.getName());\n            return new Tuple<>();\n        }\n\n        if (hotTime >= templatePhysicalWithLogic.getLogicTemplate().getExpireTime()) {\n            LOGGER.info(\"class=ColdManagerImpl||method=getColdAndHotIndex||||template={}||msg=all index is hot\",\n                templatePhysicalWithLogic.getName());\n            return new Tuple<>();\n        }\n\n        return templatePhyManager.getHotAndColdIndexByBeforeDay(templatePhysicalWithLogic, hotTime);\n    }\n\n    private ClusterRegion getMinUsageColdRegion(String cluster, List<ClusterRegion> regionList) {\n        if (CollectionUtils.isEmpty(regionList)) {\n            return null;\n        }\n\n        Map<Integer, ClusterRegionFSInfo> regionId2FsInfoMap = clusterRegionService.getClusterRegionFSInfo(cluster);\n        if (MapUtils.isEmpty(regionId2FsInfoMap)) {\n            return null;\n        }\n\n        ClusterRegion minUsageColdRegion = regionList.get(0);\n        Double maxFreeDiskRatio = Double.MIN_VALUE;\n        for (ClusterRegion region : regionList) {\n            ClusterRegionFSInfo fsInfo = regionId2FsInfoMap.get(region.getId().intValue());\n            if (null == fsInfo) {\n                continue;\n            }\n\n            Double freeDiskRatio = fsInfo.getAvailableInBytes().doubleValue() / fsInfo.getTotalInBytes();\n            if (freeDiskRatio > maxFreeDiskRatio) {\n                minUsageColdRegion = region;\n                maxFreeDiskRatio = freeDiskRatio;\n            }\n        }\n\n        return minUsageColdRegion;\n    }\n    \n\n    /////////////////srv\n\n   \n    /**\n     * 确保搬迁配置是打开的\n     *\n     * 修改索引的rack\n     *\n     * 通过tts任务触发，任务需要幂等，需要多次重试，确保成功\n     *\n     * @return result\n     */\n    @Override\n    public Result<Boolean> move2ColdNode(String phyCluster) {\n        final List<ClusterRegion> coldRegionByPhyCluster = clusterRegionManager.getColdRegionByPhyCluster(phyCluster);\n        if (CollectionUtils.isEmpty(coldRegionByPhyCluster)){\n            //没有冷节点\n            return Result.buildFail(String.format(\"【%s】没有冷节点\", phyCluster));\n        }\n        \n    \n        List<IndexTemplatePhy> templatePhysicals = indexTemplatePhyService.getNormalTemplateByCluster(phyCluster);\n    \n        if (CollectionUtils.isEmpty(templatePhysicals)) {\n            return Result.buildSucc(true);\n        }\n        final ClusterRegion region = coldRegionByPhyCluster.get(0);\n    \n        int succ = 0;\n        for (IndexTemplatePhy templatePhysical : templatePhysicals) {\n            try {\n                //该逻辑模版没有开启冷热分离的节点\n                if (Boolean.FALSE.equals(isTemplateSrvOpen(templatePhysical.getLogicId()))) {\n                    continue;\n                }\n                Result<Void> moveResult = movePerTemplate(templatePhysical, region.getId().intValue());\n                if (moveResult.success()) {\n                    succ++;\n                } else {\n                    LOGGER.warn(\n                            \"class=TemplateColdManagerImpl||method=move2ColdNode||template={}||msg=move2ColdNode fail\",\n                            templatePhysical.getName());\n                }\n            } catch (Exception e) {\n                LOGGER.warn(\"class=TemplateColdManagerImpl||method=move2ColdNode||template={}||errMsg={}\",\n                        templatePhysical.getName(), e.getMessage(), e);\n            }\n        }\n    \n        return Result.buildSucc(succ * 1.0 / templatePhysicals.size() > 0.8);\n    }\n\n    /**\n     * 批量修改hotDays\n     *\n     * @param days           变量\n     * @param operator       操作人\n     * @param templateIdList\n     * @param projectId\n     * @return result\n     */\n    @Override\n    public Result<Integer> batchChangeHotDay(Integer days, String operator, List<Integer> templateIdList,\n                                             Integer projectId) {\n        if (days > MAX_HOT_DAY || days < MIN_HOT_DAY) {\n            return Result.buildParamIllegal(\"冷热分离的时间参数非法, 介于[1, 3]\");\n        }\n\n        int count = indexTemplateService.batchChangeHotDay(days, templateIdList);\n\n        LOGGER.info(\"class=TemplateColdManagerImpl||method=batchChangeHotDay||days={}||count={}||operator={}\", days,\n            count, operator);\n        for (Integer id : templateIdList) {\n            operateRecordService.save(\n                new OperateRecord.Builder().userOperation(operator).operationTypeEnum(OperateTypeEnum.TEMPLATE_SERVICE)\n                    .bizId(id).project(projectService.getProjectBriefByProjectId(projectId))\n                    .content(\"deltaHotDays:\" + days).buildDefaultManualTrigger());\n        }\n\n        return Result.buildSucc(count);\n    }\n\n    /**************************************************** private method ****************************************************/\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/dcdr/TemplateDCDRManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.dcdr;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.DCDRMasterSlaveSwitchDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplatePhysicalDCDRDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.WorkTaskVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DCDRSingleTemplateMasterSlaveSwitchDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DCDRTasksDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateDCDRInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport java.util.List;\n\n/**\n * DCDR服务\n * @author didi\n */\npublic interface TemplateDCDRManager {\n    /**\n     * 复制并且创建DCDR链路\n     *\n     * @param templateId    模板ID\n     * @param targetCluster 物理集群名称\n     * @param regionId      regionId信息\n     * @param operator      操作人\n     * @param projectId\n     * @return Result\n     * @throws AdminOperateException 管理操作Exception\n     */\n    Result<Void> copyAndCreateDCDR(Integer templateId, String targetCluster, Integer regionId, String operator,\n                                   Integer projectId) throws AdminOperateException;\n\n    /**\n     * createPhyDCDR\n     * @param param\n     * @param operator\n     * @return\n     * @throws ESOperateException\n     */\n    Result<Void> createPhyDCDR(TemplatePhysicalDCDRDTO param, String operator) throws ESOperateException;\n\n    /**\n     * 删除DCDR\n     *\n     * @param templateId 模板ID\n     * @param operator   操作人\n     * @param projectId\n     * @return result\n     * @throws ESOperateException\n     */\n    Result<Void> deleteDCDR(Integer templateId, String operator, Integer projectId,boolean isDCDRForce) throws ESOperateException;\n\n    /**\n     * deletePhyDCDR\n     *\n     * @param param\n     * @param operator\n     * @param projectId\n     * @return\n     * @throws ESOperateException\n     */\n    Result<Void> deletePhyDCDR(TemplatePhysicalDCDRDTO param, String operator, Integer projectId) throws ESOperateException;\n\n    /**\n     * 批量DCDR主从切换\n     *\n     * @param dcdrMasterSlaveSwitchDTO\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<WorkTaskVO> batchDCDRSwitchMaster2Slave(DCDRMasterSlaveSwitchDTO dcdrMasterSlaveSwitchDTO, String operator,\n                                                   Integer projectId);\n\n    /**\n     * 根据任务id和模板id取消DCDR主从切换\n     *\n     * @param taskId\n     * @param templateIds\n     * @param fullDeleteFlag\n     * @param operator\n     * @param projectId\n     * @return\n     * @throws ESOperateException\n     */\n    Result<Void> cancelDCDRSwitchMasterSlaveByTaskIdAndTemplateIds(Integer taskId, List<Long> templateIds,\n                                                                   boolean fullDeleteFlag, String operator,\n                                                                   Integer projectId) throws ESOperateException;\n\n    /**\n     * 取消dcdr主从切换任务id 根据任务id取消DCDR主从切换\n     *\n     * @param taskId    任务id\n     * @param operator  操作人或角色\n     * @param projectId\n     * @return {@link Result}<{@link Void}>\n     * @throws ESOperateException esoperateException\n     */\n    Result<Void> cancelDCDRSwitchMasterSlaveByTaskId(Integer taskId, String operator,\n                                                     Integer projectId) throws ESOperateException;\n\n    /**\n     * 刷新dcdrChannel状态\n     *\n     * @param taskId     任务id\n     * @param templateId 模板id\n     * @param operator   操作人或角色\n     * @param projectId\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> refreshDCDRChannelState(Integer taskId, Integer templateId, String operator, Integer projectId);\n\n    /**\n     * 异步刷新DCDR任务状态\n     *\n     * @param taskId     业务key\n     * @param templateId 模板id\n     *\n     @param operator 操作人或角色\n      * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> asyncRefreshDCDRChannelState(Integer taskId, Integer templateId, String operator);\n\n    /**\n     * 主从强制切换接口\n     *\n     * @param taskId\n     * @param templateId\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Void> forceSwitchMasterSlave(Integer taskId, Integer templateId, String operator, Integer projectId);\n\n    /**\n     * 获取DCDR主从切换任务详情\n     *\n     * @param taskId\n     * @return\n     */\n    Result<DCDRTasksDetailVO> getDCDRMasterSlaveSwitchDetailVO(Integer taskId);\n\n    /**\n     * 获取单个模板DCDR主从切换详情\n     * @param taskId         任务id\n     * @param templateId     模板id\n     * @return\n     */\n    Result<DCDRSingleTemplateMasterSlaveSwitchDetailVO> getDCDRSingleTemplateMasterSlaveSwitchDetailVO(Integer taskId,\n                                                                                                       Long templateId);\n\n    /**\n     * 创建DCDR模板\n     * @param physicalId 物理模板ID\n     * @param replicaCluster 从集群名称\n     * @return result\n     @param retryCount 重试计数\n     @throws ESOperateException esoperateException\n     */\n    boolean syncCreateTemplateDCDR(Long physicalId, String replicaCluster, int retryCount) throws ESOperateException;\n\n    /**\n     * 删除DCDR模板\n     * @param physicalId 物理模板ID\n     * @param replicaCluster 从集群名称\n     * @return result\n     @param retryCount 重试计数\n     @throws ESOperateException esoperateException\n     */\n    boolean syncDeleteTemplateDCDR(Long physicalId, String replicaCluster, int retryCount) throws ESOperateException;\n\n    /**\n     * 是否存在\n     * @param physicalId 物理模板ID\n     * @param replicaCluster 从集群名称\n     * @return true/false\n     */\n    boolean syncExistTemplateDCDR(Long physicalId, String replicaCluster) throws ESOperateException;\n\n    /**\n     * 删除索引DCDR链路\n     * @param cluster 集群\n     * @param replicaCluster 从集群\n     * @param indices 索引列表\n     * @param retryCount 重试次数\n     * @return result\n     @throws ESOperateException esoperateException\n     */\n    boolean syncDeleteIndexDCDR(String cluster, String replicaCluster, List<String> indices,\n                                int retryCount) throws ESOperateException;\n\n    /**\n     * 修改索引配置\n     * @param cluster 集群\n     * @param indices 索引\n     * @param replicaIndex DCDR配置\n     * @param retryCount 重试次数\n     * @return result\n     @throws ESOperateException esoperateException\n     */\n    boolean syncDCDRSetting(String cluster, List<String> indices, boolean replicaIndex,\n                            int retryCount) throws ESOperateException;\n\n    /**\n     * 判断集群是否支持DCDR\n     * @param cluster 集群名称\n     * @return\n     */\n    boolean clusterSupport(String cluster);\n\n    /**\n     * 根据模板Id获取主从DCDR位点\n     * @param templateId    模板id\n     * @return\n     */\n    Tuple<Long/*主模板位点*/, Long/*从模板位点*/> getMasterAndSlaveTemplateCheckPoint(Integer templateId)\n\t\t    throws ESOperateException;\n\n    /**\n     * 获取模板DCDR信息\n     * @param templateId\n     * @return\n     */\n    Result<TemplateDCDRInfoVO> getTemplateDCDRInfoVO(Integer templateId) throws ESOperateException;\n    \n    /**\n     * 重建DCDR链路异常索引\n     *\n     * @param cluster       源集群的集群名称\n     * @param targetCluster 目标集群名称\n     * @param indices       要重建的索引\n     * @return 操作的结果。\n     */\n    Result<Void> rebuildDCDRLinkAbnormalIndices(String cluster, String targetCluster,\n                                                List<String> indices)throws ESOperateException;\n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/dcdr/TemplateDCDRManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.dcdr;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum.MASTER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum.SLAVE;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.impl.BaseTemplateSrvImpl;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskProcessDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.DCDRMasterSlaveSwitchDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplatePhysicalCopyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplatePhysicalDCDRDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.detail.DCDRSingleTemplateMasterSlaveSwitchDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.detail.DCDRTaskDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.detail.DCDRTasksDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.WorkTaskVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DCDRSingleTemplateMasterSlaveSwitchDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DCDRTasksDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateDCDRInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.dcdr.DCDRStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.dcdr.DCDRSwithTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDCDRStepEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.DCDRLinkAbnormalIndicesRebuildEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.threadpool.AriusTaskThreadPool;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.BatchProcessor;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ESVersionUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.dcdr.ESDCDRService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.stats.IndexNodes;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.jetbrains.annotations.NotNull;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * 索引DCDR服务实现\n * @author zqr\n * @date 2020-09-09\n */\n@Service\npublic class TemplateDCDRManagerImpl extends BaseTemplateSrvImpl implements TemplateDCDRManager {\n\n    private static final ILog     LOGGER                      = LogFactory.getLog(TemplateDCDRManagerImpl.class);\n\n    private static final String   DCDR_TEMPLATE_NAME_FORMAT   = \"%s_to_%s\";\n\n    private static final String   DCDR_INDEX_SETTING          = \"dcdr.replica_index\";\n\n    private static final int      DCDR_SWITCH_STEP_1          = 1;\n    private static final int      DCDR_SWITCH_STEP_2          = 2;\n    private static final int      DCDR_SWITCH_STEP_3          = 3;\n    private static final int      DCDR_SWITCH_STEP_4          = 4;\n    private static final int      DCDR_SWITCH_STEP_5          = 5;\n    private static final int      DCDR_SWITCH_STEP_6          = 6;\n    private static final int      DCDR_SWITCH_STEP_7          = 7;\n    private static final int      DCDR_SWITCH_STEP_8          = 8;\n    private static final int      DCDR_SWITCH_STEP_9          = 9;\n    private static final String   DCDR_SWITCH_TODO            = \"TODO\";\n    private static final String   DCDR_SWITCH_DONE            = \"DONE\";\n    private static final String   DCDR_SWITCH_FAIL            = \"FAIL\";\n    private static final String   SEPARATOR                   = \"@@@\";\n    private static final String   SUCCESS_INFO                = \"Successful Execution\";\n\n    private static final String[] DCDR_SWITCH_STEP_ARR_SMOOTH = new String[] { TemplateDCDRStepEnum.STEP_1.getValue(),\n                                                                               TemplateDCDRStepEnum.STEP_2.getValue(),\n                                                                               TemplateDCDRStepEnum.STEP_3.getValue(),\n                                                                               TemplateDCDRStepEnum.STEP_4.getValue(),\n                                                                               TemplateDCDRStepEnum.STEP_5.getValue(),\n                                                                               TemplateDCDRStepEnum.STEP_6.getValue(),\n                                                                               TemplateDCDRStepEnum.STEP_7.getValue(),\n                                                                               TemplateDCDRStepEnum.STEP_8.getValue(),\n                                                                               TemplateDCDRStepEnum.STEP_9.getValue() };\n\n    private static final String[] DCDR_SWITCH_STEP_ARR_FORCE  = new String[] { TemplateDCDRStepEnum.STEP_5.getValue(),\n                                                                               TemplateDCDRStepEnum.STEP_9.getValue() };\n\n    private static final String   TEMPLATE_NO_EXIST           = \"模板不存在\";\n\n    private static final String   TASK_IS_CANCEL              = \"任务已取消\";\n\n    private static final String   TASK_EMPTY                  = \"根据任务Id[%s]获取任务失败\";\n    private static final String DCDR_CLUSTER_REMOTE_ERROR = \"主从集群无法正常连接，不能进行 DCDR 迁移\";\n    public static final int       MAX_PHY_TEMPLATE_NUM        = 2;\n\n    @Value(\"${dcdr.concurrent:2}\")\n    private Integer               dcdrConcurrent;\n\n    @Value(\"${dcdr.fault.tolerant:5}\")\n    private Integer               dcdrFaultTolerant;\n    \n    @Autowired\n    private ESDCDRService esDCDRService;\n\n    @Autowired\n    private ESIndexService        esIndexService;\n\n    @Autowired\n    private ESTemplateService     esTemplateService;\n\n    @Autowired\n    private OpTaskManager         opTaskManager;\n    @Autowired\n    private IndexTemplateService  indexTemplateService;\n  \n\n    \n    private static final int      TRY_LOCK_TIMEOUT            = 5;\n    private static final int      ONE_STEP                    = 1;\n    private static final int      TRY_TIMES_THREE             = 3;\n\n    /**\n     * @return\n     */\n    @Override\n    public TemplateServiceEnum templateSrv() {\n        return TemplateServiceEnum.TEMPLATE_DCDR;\n    }\n\n    private AriusTaskThreadPool           ariusTaskThreadPool;\n\n    private Cache<Integer, ReentrantLock> taskId2ReentrantLockCache = CacheBuilder.newBuilder()\n        .expireAfterWrite(30, TimeUnit.MINUTES).maximumSize(100).build();\n\n    @PostConstruct\n    public void init() {\n        ariusTaskThreadPool = new AriusTaskThreadPool();\n        ariusTaskThreadPool.init(10, \"TemplateDCDRManagerImpl\", 10000);\n    }\n  \n    \n    private static final FutureUtil<Void> BATCH_DCDR_FUTURE_UTIL = FutureUtil.init(\"BATCH_DCDR_FUTURE_UTIL\", 10, 10,\n        100);\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> copyAndCreateDCDR(Integer templateId, String targetCluster, Integer regionId, String operator,\n                                          Integer projectId) throws AdminOperateException {\n        //1. 判断目标集群是否存在模板, 存在则需要删除, 避免copy失败，确保copy流程的执行来保证主从模板setting mapping等信息的一致性。\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(templateId);\n        if (null == templateLogicWithPhysical) {\n            return Result.buildParamIllegal(TEMPLATE_NO_EXIST);\n        }\n\n        IndexTemplatePhy slavePhyTemplate = templateLogicWithPhysical.getSlavePhyTemplate();\n        if (null != slavePhyTemplate) {\n            //1.1删除DCDR链路\n            Result<Void> deleteDCDRResult = deleteDCDR(templateId, operator, projectId,false);\n            if (deleteDCDRResult.failed()) {\n                return deleteDCDRResult;\n            }\n\n            //1.2清理slave模板\n            Result<Void> delTemplateResult = indexTemplatePhyService.delTemplate(slavePhyTemplate.getId(), operator);\n            if (delTemplateResult.failed()) {\n                return delTemplateResult;\n            }\n        }\n\n        // 2. 校验目标集群合法性\n        Result<ClusterPhy> targetClusterPhyResult = clusterPhyManager.getClusterByName(targetCluster);\n        if (null == targetClusterPhyResult.getData()) {\n            return Result.buildFail(String.format(\"目标集群[%s]不存在\", targetCluster));\n        }\n        //校验target具备dcdr\n        if (Boolean.FALSE.equals(\n                clusterPhyManager.getDCDRAndPipelineAndColdRegionTupleByClusterPhyWithCache(targetCluster).v1)) {\n            return Result.buildFail(String.format(\"目标集群【%s】不支持dcdr\", targetCluster));\n        }\n        IndexTemplatePhy masterPhyTemplate = templateLogicWithPhysical.getMasterPhyTemplate();\n        if (null == masterPhyTemplate) {\n            return Result.buildFail(String.format(\"模板Id[%s]不存在\", templateId));\n        }\n       \n    \n        if (AriusObjUtils.isBlack(masterPhyTemplate.getCluster())) {\n            return Result.buildFail(String.format(\"模板Id[%s]所在集群[%s]不存在\", templateId, masterPhyTemplate.getCluster()));\n        }\n\n        Result<ClusterPhy> sourceClusterPhyResult = clusterPhyManager.getClusterByName(masterPhyTemplate.getCluster());\n        if (null == sourceClusterPhyResult.getData()) {\n            return Result.buildFail(String.format(\"原集群[%s]不存在\", masterPhyTemplate.getCluster()));\n        }\n        //大版本一致就可以，小之间是不应该产生影响的\n        if (Boolean.FALSE.equals(ESVersionUtil.compareBigVersionConsistency(sourceClusterPhyResult.getData().getEsVersion(),\n                targetClusterPhyResult.getData().getEsVersion()))) {\n            return Result.buildFail(\"主从集群版本必须一致\");\n        }\n        /**\n         * 注意：鉴于目前dcdr插件是不支持带有密码的跨集群迁移，后续要需要加入密码验证方可完成迁移，后续支持\n         */\n        final Result<Void> remoteClusterAndCheckConnected = createRemoteClusterAndCheckConnected(\n                masterPhyTemplate.getCluster(), targetCluster);\n        if (remoteClusterAndCheckConnected.failed()) {\n            return remoteClusterAndCheckConnected;\n        }\n\n        // 3. 执行复制流程\n        TemplatePhysicalCopyDTO templatePhysicalCopyDTO = buildTemplatePhysicalCopyDTO(templateId, targetCluster,\n            regionId);\n        if (null == templatePhysicalCopyDTO) {\n            return Result.buildFail(TEMPLATE_NO_EXIST);\n        }\n\n        Result<Void> copyTemplateResult = templatePhyManager.copyTemplate(templatePhysicalCopyDTO, operator);\n        if (copyTemplateResult.failed()) {\n            throw new ESOperateException(copyTemplateResult.getMessage());\n        }\n\n        //3. 创建DCDR链路\n        Result<Void> result = createPhyDCDR(createDCDRMeta(templateId,false), operator);\n\n        //4. 记录操作\n        if (result.success()) {\n            // 如果操作成功，则将 hasDCDR 设置为 true, 防止用户多次点击\n            IndexTemplatePO indexTemplatePO = new IndexTemplatePO();\n            indexTemplatePO.setId(templateId);\n            indexTemplatePO.setHasDCDR(true);\n            indexTemplatePO.setCheckPointDiff(0L);\n            indexTemplateService.update(indexTemplatePO);\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    String.format(\"创建 DCDR 链路，主集群：%s，从集群：%s\", sourceClusterPhyResult.getData().getCluster(),\n                            targetClusterPhyResult.getData().getCluster()), operator, projectId, templateId,\n                    OperateTypeEnum.TEMPLATE_SERVICE_DCDR_SETTING);\n        }\n        return result;\n    }\n\n    /**\n     * 删除DCDR\n     *\n     * @param templateId 模板ID\n     * @param operator   操作人\n     * @param projectId\n     * @return result\n     * @throws ESOperateException\n     */\n    @Override\n    public Result<Void> deleteDCDR(Integer templateId, String operator, Integer projectId,boolean isDCDRForce) throws ESOperateException {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        Result<Void> checkResult = checkDCDRParam(templateId);\n\n        if (checkResult.failed()) {\n            return checkResult;\n        }\n\n        return deletePhyDCDR(createDCDRMeta(templateId,isDCDRForce), operator,\n                projectId);\n    }\n\n    /**\n     * 创建DCDR链路\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @return result\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> createPhyDCDR(TemplatePhysicalDCDRDTO param, String operator) throws ESOperateException {\n        Result<Void> checkDCDRResult = checkDCDRParam(param, OperationEnum.CREATE_DCDR);\n\n        if (checkDCDRResult.failed()) { return Result.buildFrom(checkDCDRResult);}\n\n        for (int i = 0; i < param.getPhysicalIds().size(); ++i) {\n            IndexTemplatePhy templatePhysicalPO = indexTemplatePhyService\n                .getTemplateById(param.getPhysicalIds().get(i));\n\n            // 判断集群与从集群是否配置了\n            if (!clusterPhyManager.ensureDCDRRemoteCluster(templatePhysicalPO.getCluster(),\n                param.getReplicaClusters().get(i))) {\n                return Result.buildFail(\"创建remote-cluster失败, 请检查从集群是否正常\");\n            }\n          \n\n            if (!syncCreateTemplateDCDR(param.getPhysicalIds().get(i), param.getReplicaClusters().get(i), 3)) {\n                return Result.buildFail(\"创建DCDR链路失败, 请检查主从集群是否正常\");\n\n            }\n        }\n\n        return Result.buildSucc();\n    }\n    \n    /**\n     * 创建远程集群和检查连接\n     *\n     * @param cluster       集群\n     * @param targetCluster 目标集群\n     * @return {@link Result}<{@link Void}>\n     * @throws ESOperateException esoperateException\n     */\n    private Result<Void> createRemoteClusterAndCheckConnected(String cluster, String targetCluster)\n            throws ESOperateException {\n        // 判断集群与从集群是否配置了\n        if (!clusterPhyManager.ensureDCDRRemoteCluster(cluster, targetCluster)) {\n            return Result.buildFail(\"创建 remote-cluster 失败, 请检查从集群是否正常\");\n        }\n        // 校验集群的的连通性\n        if (Boolean.FALSE.equals(ESOpTimeoutRetry.esRetryExecute(\"createRemoteClusterAndCheckConnected\", 3,\n                () -> esClusterService.checkTargetClusterConnected(cluster, targetCluster), Boolean.FALSE::equals))) {\n            return Result.buildFail(DCDR_CLUSTER_REMOTE_ERROR);\n        }\n        return Result.buildSucc();\n    }\n    \n    /**\n     * 删除DCDR链路\n     *\n     * @param param     参数\n     * @param operator  操作人\n     * @param projectId\n     * @return result\n     */\n    @Override\n    public Result<Void> deletePhyDCDR(TemplatePhysicalDCDRDTO param, String operator, Integer projectId) throws ESOperateException {\n        Result<Void> checkDCDRResult = checkDCDRParam(param, OperationEnum.DELETE_DCDR);\n\n        if (checkDCDRResult.failed()) {\n            return checkDCDRResult;\n        }\n\n        for (int i = 0; i < param.getPhysicalIds().size(); ++i) {\n            if (syncDeleteTemplateDCDR(param.getPhysicalIds().get(i), param.getReplicaClusters().get(i), 3)) {\n                IndexTemplatePhy templatePhysicalPO = indexTemplatePhyService\n                    .getTemplateById(param.getPhysicalIds().get(i));\n\n                if (param.getDeleteIndexDcdr() == null || param.getDeleteIndexDcdr()) {\n                    if (syncDeleteIndexDCDR(templatePhysicalPO.getCluster(), param.getReplicaClusters().get(i),\n                        indexTemplatePhyService.getMatchIndexNames(templatePhysicalPO.getId()), 3)) {\n                        LOGGER.info(\"method=deletePhyDCDR||physicalId={}||msg=delete index DCDR succ\",\n                            param.getPhysicalIds());\n                    } else {\n                        LOGGER.warn(\"method=deletePhyDCDR||physicalId={}||msg=delete index DCDR fail\",\n                            param.getPhysicalIds());\n                    }\n                }\n                operateRecordService.saveOperateRecordWithManualTrigger(\"replicaCluster:\" + param.getReplicaClusters(),\n                        operator, projectId, templatePhysicalPO.getLogicId(),\n                        OperateTypeEnum.TEMPLATE_SERVICE_DCDR_SETTING);\n                return Result.buildSucc();\n            }\n        }\n\n        return Result.buildFail(\"删除DCDR链路失败\");\n    }\n\n    @Override\n    public Result<WorkTaskVO> batchDCDRSwitchMaster2Slave(DCDRMasterSlaveSwitchDTO dcdrMasterSlaveSwitchDTO,\n                                                          String operator, Integer projectId) {\n        Result<OpTask> workTaskResult = Result.buildSucc();\n        try {\n            //1. 批量校验模板DCDR是否可以切换, 仅有一个模板校验不通过结果为不通过。\n            List<Long> templateIdList = dcdrMasterSlaveSwitchDTO.getTemplateIds();\n            String dcdrType = dcdrMasterSlaveSwitchDTO.getType() == 1 ? \"平滑\" : \"强制\";\n            Result<Void> batchCheckValidForDCDRSwitchResult = batchCheckValidForDCDRSwitch(templateIdList, operator);\n            if (batchCheckValidForDCDRSwitchResult.failed()) {\n                return Result.buildFrom(batchCheckValidForDCDRSwitchResult);\n            }\n            \n            //2.1 设置基础数据\n            OpTaskDTO opTaskDTO = new OpTaskDTO();\n            String businessKey = getBusinessKey(templateIdList);\n            opTaskDTO.setBusinessKey(businessKey);\n            opTaskDTO.setTitle(getDCDRTaskTitle(templateIdList, dcdrType));\n            opTaskDTO.setTaskType(OpTaskTypeEnum.TEMPLATE_DCDR.getType());\n            opTaskDTO.setCreator(operator);\n            opTaskDTO.setDeleteFlag(false);\n            opTaskDTO.setStatus(OpTaskStatusEnum.RUNNING.getStatus());\n\n            //2.2 设置多个模板DCDR任务信息\n            DCDRTasksDetail dcdrTasksDetail = buildDCDRTasksDetail(dcdrMasterSlaveSwitchDTO, templateIdList);\n\n            //2.3 计算状态\n            dcdrTasksDetail.calculateProcess();\n\n            //2.4 保存任务\n            opTaskDTO.setExpandData(ConvertUtil.obj2Json(dcdrTasksDetail));\n            workTaskResult = opTaskManager.addTask(opTaskDTO, projectId);\n            if (workTaskResult.failed()) {\n                return Result.buildFrom(workTaskResult);\n            }\n\n            //2.5 记录操作\n            for (DCDRSingleTemplateMasterSlaveSwitchDetail dcdrTask : dcdrTasksDetail\n                .getDcdrSingleTemplateMasterSlaveSwitchDetailList()) {\n                operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"【%s】%s\",\n                                indexTemplateService.getNameByTemplateLogicId(dcdrTask.getTemplateId().intValue()), dcdrType),\n                        operator, projectId, dcdrTask.getTemplateId(), OperateTypeEnum.TEMPLATE_SERVICE_DCDR_SETTING);\n                \n            }\n\n        } catch (Exception e) {\n            LOGGER.error(\"method=batchDCDRSwitchMaster2Slave||templateIds={}||msg={}\",\n                dcdrMasterSlaveSwitchDTO.getTemplateIds(), e.getMessage(), e);\n            return Result.buildFail(\"工单提交失败\");\n        }\n\n        return Result.buildSucc(ConvertUtil.obj2Obj(workTaskResult.getData(), WorkTaskVO.class));\n    }\n\n    @Override\n    public Result<Void> cancelDCDRSwitchMasterSlaveByTaskId(Integer taskId, String operator,\n                                                            Integer projectId) throws ESOperateException {\n        return cancelDCDRSwitchMasterSlaveByTaskIdAndTemplateIds(taskId, null, true, operator, projectId);\n    }\n\n    @Override\n    public Result<Void> cancelDCDRSwitchMasterSlaveByTaskIdAndTemplateIds(Integer taskId, List<Long> templateIds,\n                                                                          boolean fullDeleteFlag, String operator,\n                                                                          Integer projectId) throws ESOperateException {\n        try {\n            Result<OpTask> taskForDcdrSwitchResult = opTaskManager.getById(taskId);\n            if (taskForDcdrSwitchResult.failed()) {\n                LOGGER.error(\"method=cancelDcdrSwitchMasterSlaveByTaskIdAndTemplateIds||taskId={}||msg=taskId is empty\",\n                    taskId);\n                return Result.buildFail(String.format(TASK_EMPTY, taskId));\n            }\n\n            OpTask taskForDCDRSwitch = taskForDcdrSwitchResult.getData();\n            DCDRTasksDetail dcdrTasksDetail = ConvertUtil.str2ObjByJson(taskForDCDRSwitch.getExpandData(),\n                DCDRTasksDetail.class);\n            List<DCDRSingleTemplateMasterSlaveSwitchDetail> dcdrSingleTemplateMasterSlaveSwitchDetailList = dcdrTasksDetail\n                .getDcdrSingleTemplateMasterSlaveSwitchDetailList();\n            if (CollectionUtils.isEmpty(dcdrSingleTemplateMasterSlaveSwitchDetailList)) {\n                return Result.buildSucc();\n            }\n\n            for (DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail : dcdrSingleTemplateMasterSlaveSwitchDetailList) {\n                if (fullDeleteFlag) {\n                    //取消任务中全部DCDR模板链路\n                    if (DCDRStatusEnum.SUCCESS.getCode().equals(switchDetail.getTaskStatus())) {\n                        continue;\n                    }\n                    switchDetail.setTaskStatus(DCDRStatusEnum.CANCELLED.getCode());\n                } else {\n                    if (!CollectionUtils.isEmpty(templateIds) && templateIds.contains(switchDetail.getTemplateId())) {\n                        //取消任务中指定DCDR模板链路\n                        switchDetail.setTaskStatus(DCDRStatusEnum.CANCELLED.getCode());\n                    }\n                }\n            }\n\n            saveNewestWorkTaskStatusToDB(taskForDCDRSwitch, dcdrTasksDetail, projectId);\n        } catch (Exception e) {\n            LOGGER.error(\n                \"method=cancelDCDRSwitchMasterSlaveByTaskIdAndTemplateIds||taskId={}||templateIds={}||\" + \"msg={}\",\n                taskId, templateIds, e.getMessage(), e);\n            return Result.buildFail(\"取消失败, 请联系管理员\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> refreshDCDRChannelState(Integer taskId, Integer templateId, String operator,\n                                                Integer projectId) {\n        Result<OpTask> taskForDCDRSwitchResult = opTaskManager.getById(taskId);\n        if (taskForDCDRSwitchResult.failed()) {\n            return Result.buildFrom(taskForDCDRSwitchResult);\n        }\n\n        OpTask taskForDCDRSwitch = taskForDCDRSwitchResult.getData();\n        if (null == taskForDCDRSwitch) {\n            return Result.buildFail(\"任务不存在\");\n        }\n\n        DCDRTasksDetail dcdrTasksDetail = ConvertUtil.str2ObjByJson(taskForDCDRSwitch.getExpandData(),\n            DCDRTasksDetail.class);\n\n        // 1. 初始化单个模板DCDR任务状态\n        initSwitchTaskInfo(templateId, dcdrTasksDetail);\n\n        // 2. 保存初始化状态\n        saveNewestWorkTaskStatusToDB(taskForDCDRSwitch, dcdrTasksDetail, projectId);\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> asyncRefreshDCDRChannelState(Integer taskId, Integer templateId, String operator) {\n        ariusTaskThreadPool.run(() -> {\n            // 这里引入锁, 来确保同一时刻只有单个任务在执行。\n            ReentrantLock reentrantLock = null;\n            try {\n                reentrantLock = taskId2ReentrantLockCache.get(taskId, ReentrantLock::new);\n            } catch (ExecutionException e) {\n                e.printStackTrace();\n            }\n\n            if (reentrantLock != null) {\n                try {\n                    if (reentrantLock.tryLock(TRY_LOCK_TIMEOUT, TimeUnit.SECONDS)) {\n                        // 刷新全量状态\n                        doRefreshDCDRChannelsState(taskId, ONE_STEP, operator);\n                    } else {\n                        LOGGER.info(\n                            \"method=asyncRefreshDCDRChannelState||taskId={}||thread={}||errMsg=failed to fetch the lock\",\n                            taskId, Thread.currentThread().getName());\n                    }\n                } catch (Exception e) {\n                    LOGGER.error(\"method=asyncRefreshDCDRChannelState||taskId={}||errMsg={}\", taskId, e);\n                } finally {\n                    reentrantLock.unlock();\n                }\n            }\n        });\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> forceSwitchMasterSlave(Integer taskId, Integer templateId, String operator, Integer projectId) {\n        if (null == templateId) {\n            return Result.buildFail(\"模板Id不存在\");\n        }\n\n        try {\n            Result<OpTask> taskForDcdrSwitchResult = opTaskManager.getById(taskId);\n            if (taskForDcdrSwitchResult.failed()) {\n                LOGGER.error(\"method=forceSwitchMasterSlave||taskId={}||msg=taskId is empty\", taskId);\n                return Result.buildFail(String.format(TASK_EMPTY, taskId));\n            }\n\n            OpTask data = taskForDcdrSwitchResult.getData();\n            if (null == data) {\n                LOGGER.error(\"method=forceSwitchMasterSlave||taskId={}||msg=WorkTask is empty\", taskId);\n                return Result.buildFail(\"获取DCDR任务详情失败, 请检查任务是否存在\");\n            }\n\n            DCDRTasksDetail dcdrTasksDetail = ConvertUtil.str2ObjByJson(data.getExpandData(), DCDRTasksDetail.class);\n            List<DCDRSingleTemplateMasterSlaveSwitchDetail> switchDetailList = dcdrTasksDetail\n                .getDcdrSingleTemplateMasterSlaveSwitchDetailList();\n            if (CollectionUtils.isEmpty(switchDetailList)) {\n                Result.buildFail(\"强切失败, 请确认是否有DCDR任务\");\n            }\n\n            for (DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail : switchDetailList) {\n                if (templateId.equals(switchDetail.getTemplateId().intValue())) {\n                    switchDetail.setSwitchType(DCDRSwithTypeEnum.FORCE.getCode());\n                }\n            }\n\n            //1.初始化单个模板DCDR任务状态\n            initSwitchTaskInfo(templateId, dcdrTasksDetail);\n\n            //2. 更新任务状态\n            saveNewestWorkTaskStatusToDB(data, dcdrTasksDetail, projectId);\n        } catch (Exception e) {\n            LOGGER.error(\"method=forceSwitchMasterSlave||taskId={}||templateId={}||msg=\"\n                         + \"failed to save newest workTask to db\",\n                taskId, templateId, e);\n            return Result.buildFail(\"主从强切失败, 请联系管理员\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<DCDRTasksDetailVO> getDCDRMasterSlaveSwitchDetailVO(Integer taskId) {\n        Result<OpTask> taskForDcdrSwitchResult = opTaskManager.getById(taskId);\n        if (taskForDcdrSwitchResult.failed()) {\n            LOGGER.error(\"method=getDCDRMasterSlaveSwitchDetailVO||taskId={}||msg=taskId is empty\", taskId);\n            return Result.buildFail(String.format(TASK_EMPTY, taskId));\n        }\n\n        OpTask data = taskForDcdrSwitchResult.getData();\n        if (null == data) {\n            LOGGER.error(\"method=getDCDRMasterSlaveSwitchDetailVO||taskId={}||msg=OpTask is empty\", taskId);\n            return Result.buildFail(\"获取DCDR任务详情失败\");\n        }\n        DCDRTasksDetail dcdrTasksDetail = ConvertUtil.str2ObjByJson(data.getExpandData(), DCDRTasksDetail.class);\n        dcdrTasksDetail.calculateProcess();\n\n        //刷新DCDR任务状态\n        if (DCDRStatusEnum.RUNNING.getCode().equals(dcdrTasksDetail.getState())) {\n            asyncRefreshDCDRChannelState(taskId, null, null);\n        }\n        return Result.buildSucc(ConvertUtil.obj2Obj(dcdrTasksDetail, DCDRTasksDetailVO.class));\n    }\n\n    @Override\n    public Result<DCDRSingleTemplateMasterSlaveSwitchDetailVO> getDCDRSingleTemplateMasterSlaveSwitchDetailVO(Integer taskId,\n                                                                                                              Long templateId) {\n        if (null == templateId) {\n            return Result.buildParamIllegal(\"模板为空\");\n        }\n\n        Result<OpTask> taskForDCDRSwitchResult = opTaskManager.getById(taskId);\n        if (taskForDCDRSwitchResult.failed()) {\n            return Result.buildFail(String.format(TASK_EMPTY, taskId));\n        }\n\n        OpTask taskForDcdrSwitch = taskForDCDRSwitchResult.getData();\n        if (null == taskForDcdrSwitch) {\n            return Result.buildFail(\"任务不存在\");\n        }\n\n        DCDRTasksDetail dcdrTasksDetail = ConvertUtil.str2ObjByJson(taskForDcdrSwitch.getExpandData(),\n            DCDRTasksDetail.class);\n\n        List<DCDRSingleTemplateMasterSlaveSwitchDetail> switchDetailList = dcdrTasksDetail\n            .getDcdrSingleTemplateMasterSlaveSwitchDetailList();\n\n        // 检查是否有需要刷新DCDR任务\n        switchDetailList.stream()\n            .filter(switchDetail -> templateId.equals(switchDetail.getTemplateId())\n                                    && DCDRStatusEnum.RUNNING.getCode().equals(switchDetail.getTaskStatus()))\n            .forEach(switchDetail -> asyncRefreshDCDRChannelState(taskId, templateId.intValue(), null));\n\n        // 返回详情\n        for (DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail : switchDetailList) {\n            if (templateId.equals(switchDetail.getTemplateId())) {\n                return Result\n                    .buildSucc(ConvertUtil.obj2Obj(switchDetail, DCDRSingleTemplateMasterSlaveSwitchDetailVO.class));\n            }\n        }\n\n        return Result.buildFail();\n    }\n\n    /**\n     * 创建DCDR模板\n     *\n     * @param physicalId     物理模板ID\n     * @param replicaCluster 从集群名称\n     * @return result\n     */\n    @Override\n    public boolean syncCreateTemplateDCDR(Long physicalId, String replicaCluster,\n                                          int retryCount) throws ESOperateException {\n\n        IndexTemplatePhy templatePhysical = indexTemplatePhyService.getTemplateById(physicalId);\n        if (null == templatePhysical) {\n            LOGGER.error(\"method=syncCreateTemplateDCDR||physicalId={}||replicaCluster={}||errMsg=templatePhysical is null\", physicalId, replicaCluster);\n            return false;\n        }\n\n        LOGGER.info(\"method=syncCreateTemplateDCDR||physicalId={}||replicaCluster={}\", physicalId, replicaCluster);\n        return esDCDRService.put(\"putDCDRForTemplate\",templatePhysical.getCluster(),\n                String.format(DCDR_TEMPLATE_NAME_FORMAT, templatePhysical.getName(), replicaCluster),\n                templatePhysical.getName(), replicaCluster,retryCount );\n     \n    }\n\n    /**\n     * 删除DCDR模板\n     *\n     *\n     * @param physicalId     物理模板ID\n     * @param replicaCluster 从集群名称\n     * @return result\n     */\n    @Override\n    public boolean syncDeleteTemplateDCDR(Long physicalId, String replicaCluster,\n                                          int retryCount) throws ESOperateException {\n        IndexTemplatePhy templatePhysical = indexTemplatePhyService.getTemplateById(physicalId);\n\n        LOGGER.info(\"method=syncDeleteTemplateDCDR||physicalId={}||replicaCluster={}\", physicalId, replicaCluster);\n    \n        return esDCDRService.delete(\"deleteDCDRForTemplate\", templatePhysical.getCluster(),\n                String.format(DCDR_TEMPLATE_NAME_FORMAT, templatePhysical.getName(), replicaCluster), retryCount);\n    }\n\n    /**\n     * 是否存在\n     *\n     * @param physicalId     物理模板ID\n     * @param replicaCluster 从集群名称\n     * @return true/false\n     */\n    @Override\n    public boolean syncExistTemplateDCDR(Long physicalId, String replicaCluster) throws ESOperateException {\n        IndexTemplatePhy templatePhysical = indexTemplatePhyService.getTemplateById(physicalId);\n        if (Objects.isNull(templatePhysical)) {\n            throw new ESOperateException(\"获取不到物理模版:【%s】\");\n        }\n        LOGGER.info(\"method=syncExistTemplateDCDR||physicalId={}||replicaCluster={}\", physicalId, replicaCluster);\n        \n        return esDCDRService.exist(templatePhysical.getCluster(),String.format(DCDR_TEMPLATE_NAME_FORMAT, templatePhysical.getName(), replicaCluster));\n    }\n\n    /**\n     * 删除索引DCDR链路\n     *\n     * @param cluster                  集群\n     * @param replicaCluster           从集群\n     * @param indices 索引列表\n     * @param retryCount               重试次数\n     * @return result\n     */\n    @Override\n    public boolean syncDeleteIndexDCDR(String cluster, String replicaCluster, List<String> indices,\n                                       int retryCount) throws ESOperateException {\n        return esDCDRService.delete(\"syncDeleteIndexDCDR\",cluster,replicaCluster,indices,retryCount);\n    }\n\n    /**\n     * 修改索引配置\n     *\n     * @param cluster      集群\n     * @param indices      索引\n     * @param replicaIndex DCDR配置\n     * @param retryCount   重试次数\n     * @return result\n     */\n    @Override\n    public boolean syncDCDRSetting(String cluster, List<String> indices, boolean replicaIndex,\n                                   int retryCount) throws ESOperateException {\n\n        BatchProcessor.BatchProcessResult<String, Boolean> result = new BatchProcessor<String, Boolean>()\n            .batchList(indices).batchSize(30).processor(items -> {\n                    return esIndexService.syncPutIndexSetting(cluster, items, DCDR_INDEX_SETTING,\n                        String.valueOf(replicaIndex), \"false\", retryCount);\n            }).succChecker(succ -> succ).process();\n        if (!result.isSucc() && CollectionUtils.isNotEmpty(result.getErrorMap().values())) {\n            throw new ESOperateException(result.getErrorMap().values().stream().findFirst().get().getMessage());\n        \n        }\n        return result.isSucc();\n    }\n\n    /**\n     * 判断集群是否支持DCDR\n     *\n     * @param phyCluster 集群名称\n     * @return\n     */\n    @Override\n    public boolean clusterSupport(String phyCluster) {\n        //直接获取插件信息\n        return esClusterNodeService.existDCDRAndPipelineModule(phyCluster).v1;\n    }\n\n    @Override\n    public Tuple<Long, Long> getMasterAndSlaveTemplateCheckPoint(Integer templateId) throws ESOperateException {\n        //1.初始化信息\n        Tuple<Long, Long> masterAndSlaveCheckPointTuple = new Tuple<>();\n        masterAndSlaveCheckPointTuple.setV1(0L);\n        masterAndSlaveCheckPointTuple.setV2(0L);\n\n        IndexTemplateWithPhyTemplates logicTemplateWithPhysicals = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(templateId);\n        IndexTemplatePhy masterPhyTemplate = logicTemplateWithPhysicals.getMasterPhyTemplate();\n        IndexTemplatePhy slavePhyTemplate = logicTemplateWithPhysicals.getSlavePhyTemplate();\n        if (null == masterPhyTemplate) {\n            LOGGER.warn(\n                \"class=TemplateDCDRManagerImpl||method=setCheckPointDiff||templateId={}||msg=masterPhyTemplate is empty\",\n                templateId);\n            return masterAndSlaveCheckPointTuple;\n        }\n\n        if (null == slavePhyTemplate) {\n            LOGGER.warn(\n                \"class=TemplateDCDRManagerImpl||method=setCheckPointDiff||templateId={}||msg=slavePhyTemplate is empty\",\n                templateId);\n            return masterAndSlaveCheckPointTuple;\n        }\n\n        //2. 根据索引主从位点信息构建模板主从位点信息\n        List<String> indexNames = indexTemplatePhyService.getMatchIndexNames(masterPhyTemplate.getId());\n\n        Map<String, IndexNodes> indexStatForMasterMap = esIndexService\n            .syncBatchGetIndices(masterPhyTemplate.getCluster(), indexNames);\n        //获取从集群的真实索引\n        List<String> slaveMasterAllIndexList = esIndexService.syncCatIndex(slavePhyTemplate.getCluster(), 3).stream()\n                .map(CatIndexResult::getIndex).collect(Collectors.toList());\n        \n        // 对索引进行过滤，找到从集群存在的索引，目的是保证从集群获取 count 数据不会报出 no such index not found 问题\n        List<String> relaIndexNames = indexNames.stream().filter(slaveMasterAllIndexList::contains)\n                .collect(Collectors.toList());\n        // 获取从集群中没有创建创建出来的索引，进行二次补偿，目的是：当从机器挂掉了，那么索引没有创建出来，会造成 dcdr 数据无法同步，\n        // 所以这里通过删除从集群未生成的索引的链路，将其创建，从而解决该问题\n        final List<String> targetClusterNotCreateIndices = indexNames.stream()\n                .filter(i -> !slaveMasterAllIndexList.contains(i)).collect(Collectors.toList());\n        // 发布事件进行重建\n        SpringTool.publish(new DCDRLinkAbnormalIndicesRebuildEvent(this, masterPhyTemplate.getCluster(),\n                slavePhyTemplate.getCluster(), targetClusterNotCreateIndices));\n        Map<String, IndexNodes> indexStatForSlaveMap = esIndexService.syncBatchGetIndices(slavePhyTemplate.getCluster(),\n                relaIndexNames);\n\n        long masterCheckPointTotal = 0;\n        long slaveCheckPointTotal = 0;\n        for (String index : indexNames) {\n            IndexNodes statForMaster = indexStatForMasterMap.get(index);\n            IndexNodes statForSlave = indexStatForSlaveMap.get(index);\n            AtomicLong totalCheckpointForMaster = esIndexService.syncGetTotalCheckpoint(index, statForMaster, null);\n            AtomicLong totalCheckpointForSlave = esIndexService.syncGetTotalCheckpoint(index, statForSlave, null);\n            masterCheckPointTotal += totalCheckpointForMaster.get();\n            slaveCheckPointTotal += totalCheckpointForSlave.get();\n        }\n\n        masterAndSlaveCheckPointTuple.setV1(masterCheckPointTotal);\n        masterAndSlaveCheckPointTuple.setV2(slaveCheckPointTotal);\n        return masterAndSlaveCheckPointTuple;\n    }\n\n    @Override\n    public Result<TemplateDCDRInfoVO> getTemplateDCDRInfoVO(Integer templateId) throws ESOperateException {\n        TemplateDCDRInfoVO templateDCDRInfoVO = new TemplateDCDRInfoVO();\n        IndexTemplateWithPhyTemplates logicTemplateWithPhysicals = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(templateId);\n        IndexTemplatePhy slavePhyTemplate = Optional.ofNullable(logicTemplateWithPhysicals)\n                .map(IndexTemplateWithPhyTemplates::getSlavePhyTemplate)\n                .orElse(null);\n        IndexTemplatePhy masterPhyTemplate = Optional.ofNullable(logicTemplateWithPhysicals)\n                .map(IndexTemplateWithPhyTemplates::getMasterPhyTemplate)\n                .orElse(null);\n        Optional.ofNullable(masterPhyTemplate)\n                .map(IndexTemplatePhy::getCluster).ifPresent(templateDCDRInfoVO::setMasterClusterName);\n        Optional.ofNullable(slavePhyTemplate)\n                .map(IndexTemplatePhy::getCluster).ifPresent(templateDCDRInfoVO::setSlaveClusterName);\n        if (null == masterPhyTemplate) {\n            return Result.buildFail(TEMPLATE_NO_EXIST);\n        }\n        // 1. 判断模板是否存在DCDR\n        if (null == slavePhyTemplate) {\n            templateDCDRInfoVO.setDcdrFlag(false);\n            return Result.buildSuccWithTips(templateDCDRInfoVO, \"模板未开启DCDR链路\");\n        } else {\n            try {\n        \n                templateDCDRInfoVO.setDcdrFlag(\n                        syncExistTemplateDCDR(masterPhyTemplate.getId(), slavePhyTemplate.getCluster()));\n               \n            } catch (Exception e) {\n                LOGGER.error(\"method=getTemplateDCDRInfoVO||templateId={}\", templateId,e);\n               return Result.buildFailWithMsg(templateDCDRInfoVO,\"主集群异常，获取主从位点差失败\");\n            }\n        }\n\n        if (Boolean.FALSE.equals(templateDCDRInfoVO.getDcdrFlag())) {\n            return Result.buildSuccWithTips(templateDCDRInfoVO, \"模板未开启DCDR链路\");\n        }\n        // 校验集群的的连通性,如果链接不通，则会导致异常\n        if (!esClusterService.checkTargetClusterConnected(masterPhyTemplate.getCluster(),\n                slavePhyTemplate.getCluster())) {\n            return Result.buildFail(DCDR_CLUSTER_REMOTE_ERROR);\n        }\n        // 2. 获取主从模板checkpoint信息\n        Tuple<Long, Long> masterAndSlaveTemplateCheckPointTuple = new Tuple<>();\n        try {\n            masterAndSlaveTemplateCheckPointTuple = getMasterAndSlaveTemplateCheckPoint(templateId);\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=TemplateDCDRManagerImpl||method=getTemplateDCDRInfoVO||templateId={}||msg=masterAndSlaveTemplateCheckPointTuple is empty\",\n                templateId, e);\n            return Result.buildFailWithMsg(templateDCDRInfoVO,\"从集群异常，获取主从位点差失败\");\n        }\n        \n        templateDCDRInfoVO.setMasterTemplateCheckPoint(masterAndSlaveTemplateCheckPointTuple.getV1());\n\n        templateDCDRInfoVO.setSlaveTemplateCheckPoint(masterAndSlaveTemplateCheckPointTuple.getV2());\n\n        long checkPointDiff =\n                Math\n            .abs(masterAndSlaveTemplateCheckPointTuple.getV1() - masterAndSlaveTemplateCheckPointTuple.getV2());\n        templateDCDRInfoVO.setTemplateCheckPointDiff(checkPointDiff);\n        return Result.buildSucc(templateDCDRInfoVO);\n    }\n    \n    /**\n     * 重建DCDR链路异常索引\n     *\n     * @param cluster       源集群的集群名称\n     * @param targetCluster 目标集群名称\n     * @param indices       要重建的索引\n     * @return 操作的结果。\n     */\n    @Override\n    public Result<Void> rebuildDCDRLinkAbnormalIndices(String cluster, String targetCluster,\n                                                       List<String> indices) throws ESOperateException {\n        if (esClusterService.checkTargetClusterConnected(cluster, targetCluster)) {\n            return Result.buildFail(DCDR_CLUSTER_REMOTE_ERROR);\n        }\n       \n    \n        return Result.build( esDCDRService.delete(\"rebuildDCDRLinkAbnormalIndices\", cluster, targetCluster,\n                indices, 3));\n    \n    }\n    \n    /**************************************** private method ****************************************************/\n    private Result<Void> checkDCDRParam(Integer logicId) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n        if (templateLogicWithPhysical == null) {\n            return Result.buildNotExist(TEMPLATE_NO_EXIST);\n        }\n\n        if (templateLogicWithPhysical.getMasterPhyTemplate() == null) {\n            return Result.buildParamIllegal(\"模板没有部署master\");\n        }\n\n        if (templateLogicWithPhysical.getSlavePhyTemplate() == null) {\n            return Result.buildParamIllegal(\"模板没有部署slave\");\n        }\n\n        if (templateLogicWithPhysical.getPhysicals().size() != MAX_PHY_TEMPLATE_NUM) {\n            return Result.buildParamIllegal(\"DCDR仅支持一主一从部署的模板\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkDCDRParam(TemplatePhysicalDCDRDTO param, OperationEnum operationEnum) {\n        if (param == null) {\n            return Result.buildParamIllegal(\"DCDR参数不存在\");\n        }\n\n        if (CollectionUtils.isEmpty(param.getPhysicalIds())) {\n            return Result.buildParamIllegal(\"模板ID必须存在\");\n        }\n\n        if (CollectionUtils.isEmpty(param.getReplicaClusters())) {\n            return Result.buildParamIllegal(\"从集群必须存在\");\n        }\n\n        for (int i = 0; i < param.getPhysicalIds().size(); ++i) {\n            IndexTemplatePhy templatePhysical = indexTemplatePhyService.getTemplateById(param.getPhysicalIds().get(i));\n            if (templatePhysical == null) {\n                return Result.buildNotExist(\"物理模板不存在\");\n            }\n\n            if (!clusterPhyManager.isClusterExists(param.getReplicaClusters().get(i))) {\n                return Result.buildNotExist(\"从集群不存在\");\n            }\n    \n            // 只有create阶段的dcdr才需要校验\n            if (OperationEnum.CREATE_DCDR.equals(operationEnum)) {\n                if (!clusterSupport(templatePhysical.getCluster())) {\n                    return Result.buildParamIllegal(\"模板所在集群不支持 DCDR\");\n                }\n                if (!clusterSupport(param.getReplicaClusters().get(i))) {\n                    return Result.buildParamIllegal(\"所选的从集群不支持 DCDR\");\n                }\n            }\n\n            if (templatePhysical.getCluster().equals(param.getReplicaClusters().get(i))) {\n                return Result.buildParamIllegal(\"所选的从集群与主集群不能一样\");\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 根据逻辑索引ID创建物理模板DCDR\n     *\n     * @param templateId\n     * @return {@link  TemplatePhysicalDCDRDTO}\n     */\n    private TemplatePhysicalDCDRDTO createDCDRMeta(Integer templateId,boolean isDCDRForce) {\n        TemplatePhysicalDCDRDTO dcdrMeta = new TemplatePhysicalDCDRDTO();\n\n        dcdrMeta.setPhysicalIds(new ArrayList<>());\n        dcdrMeta.setReplicaClusters(new ArrayList<>());\n\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(templateId);\n\n        List<IndexTemplatePhy> masterPhysicals = templateLogicWithPhysical.fetchMasterPhysicalTemplates();\n        for (IndexTemplatePhy indexTemplatePhysicalInfo : masterPhysicals) {\n            IndexTemplatePhy slave = null;\n            if (StringUtils.isNotBlank(indexTemplatePhysicalInfo.getGroupId())) {\n                slave = templateLogicWithPhysical.fetchMasterSlave(indexTemplatePhysicalInfo.getGroupId());\n            }\n\n            if (null == slave) {\n                slave = templateLogicWithPhysical.getSlavePhyTemplate();\n            }\n\n            if (slave != null) {\n                if (isDCDRForce) {\n                    //如果是强切，则新主就是原从，且新从是旧主，然后进行切花\n                    dcdrMeta.getPhysicalIds().add(slave.getId());\n                    dcdrMeta.getReplicaClusters().add(indexTemplatePhysicalInfo.getCluster());\n                } else {\n                    dcdrMeta.getPhysicalIds().add(indexTemplatePhysicalInfo.getId());\n                    dcdrMeta.getReplicaClusters().add(slave.getCluster());\n                }\n            }\n        }\n\n        return dcdrMeta;\n    }\n\n\n    private TemplatePhysicalDCDRDTO buildCreateDCDRParam(IndexTemplatePhy masterTemplate,\n                                                         IndexTemplatePhy slaveTemplate) {\n        TemplatePhysicalDCDRDTO dcdrdto = new TemplatePhysicalDCDRDTO();\n        dcdrdto.setPhysicalIds(Arrays.asList(masterTemplate.getId()));\n        dcdrdto.setReplicaClusters(Arrays.asList(slaveTemplate.getCluster()));\n        return dcdrdto;\n    }\n    \n    private Result<Void> changeDCDRConfig(String cluster, List<String> indices, boolean replicaIndex) {\n        try {\n            // 修改配置\n            if (!syncDCDRSetting(cluster, indices, replicaIndex, TRY_TIMES_THREE)) {\n                return Result.buildFail(\"修改\" + cluster + \"索引 dcdr 配置失败\");\n            }\n        } catch (ESOperateException e) {\n            return Result.buildFail(String.format(\"修改 [%s] 索引 dcdr 配置失败, 原因是：%s\", cluster, e.getMessage()));\n        }\n        try {\n            // reopen 索引\n            if (!esIndexService.reOpenIndex(cluster, indices, TRY_TIMES_THREE)) {\n                return Result.buildFail(\"reOpen\" + cluster + \"索引失败\");\n            }\n        } catch (ESOperateException e) {\n            return Result.buildFail(String.format(\"reOpen[%s] 索引失败, 原因是：%s\", cluster, e.getMessage()));\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> deleteSrcDCDR(IndexTemplatePhy masterTemplate, IndexTemplatePhy slaveTemplate,\n\n                                       List<String> matchNoVersionIndexNames,\n                                       String operator) throws ESOperateException {\n\n        TemplatePhysicalDCDRDTO dcdrDTO = new TemplatePhysicalDCDRDTO();\n\n        dcdrDTO.setPhysicalIds(Arrays.asList(masterTemplate.getId()));\n        dcdrDTO.setReplicaClusters(Arrays.asList(slaveTemplate.getCluster()));\n        dcdrDTO.setDeleteIndexDcdr(false);\n\n        Result<Void> delTemDCDRResult = deletePhyDCDR(dcdrDTO, operator, AuthConstant.SUPER_PROJECT_ID);\n        //删除失败了需要抛出信息\n        if (delTemDCDRResult.failed()) {\n            return Result.buildFrom(delTemDCDRResult);\n        }\n        boolean delIndexDCDRResult = syncDeleteIndexDCDR(masterTemplate.getCluster(), slaveTemplate.getCluster(),\n            matchNoVersionIndexNames, 3);\n\n        return Result.build(delTemDCDRResult.success() && delIndexDCDRResult);\n    }\n\n    /**\n     * 执行\n     *\n     * @param workTaskId                     任务id\n     * @param switchDetail\n     * @param expectMasterPhysicalId         期望的模板Id\n     * @param step                           切换起始步骤\n     * @param masterTemplate                 主模板元数据信息\n     * @param slaveTemplate                  从模板元数据信息\n     * @param operator\n     * @return\n     */\n    private Result<List<String>> executeDCDRForForce(Integer workTaskId,\n                                                     DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail,\n                                                     Long expectMasterPhysicalId, int step,\n                                                     IndexTemplatePhy masterTemplate, IndexTemplatePhy slaveTemplate,\n                                                     String operator) {\n        int templateId = switchDetail.getTemplateId().intValue();\n        final String expression = slaveTemplate.getExpression();\n        try {\n            if (DCDR_SWITCH_STEP_1 == step) {\n                // 不需要校验从集群到主集群是否是通路：这里是由于强切之后不会创建链路\n                // 修改DCDR索引配置 index.dcdr.replica_index = true/false\n                // 然后还需要reopen索引，配置才能生效\n                Result<Void> setSettingResult = Result.buildSucc();\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    setSettingResult = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    //这里采用表达式设置这个会更快，这样会保证任务快速执行\n                    Result<Void> changeSlaveDCDRConfig = changeDCDRConfig(slaveTemplate.getCluster(), Collections.singletonList(expression),\n                            false);\n                    if (changeSlaveDCDRConfig.failed()) {\n                        setSettingResult = Result.buildFail(changeSlaveDCDRConfig.getMessage());\n                    }\n                }\n\n                Result<List<String>> step1Result = buildStepMsg(DCDRSwithTypeEnum.FORCE.getCode(), setSettingResult,\n                    templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_1, operator,\n                    switchDetail.getTaskProgressList());\n                if (step1Result.failed()) {\n                    return step1Result;\n                }\n                step++;\n                sleep(1000L);\n            }\n\n            if (DCDR_SWITCH_STEP_2 == step) {\n                // 主从角色切换\n                Result<Void> switchMasterSlave;\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    switchMasterSlave = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    if (hasFinishSwitchMasterSlave(switchDetail)) {\n                        switchMasterSlave = Result.buildSucc();\n                    } else {\n                        switchMasterSlave = templatePhyManager.switchMasterSlave(masterTemplate.getLogicId(),\n                            slaveTemplate.getId(), AriusUser.SYSTEM.getDesc());\n                    }\n                }\n\n                Result<List<String>> step2Result = buildStepMsg(DCDRSwithTypeEnum.FORCE.getCode(), switchMasterSlave,\n                    templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_2, operator,\n                    switchDetail.getTaskProgressList());\n                if (step2Result.failed()) {\n                    return step2Result;\n                }\n            }\n\n        } catch (Exception e) {\n            LOGGER.warn(\"method=executeDCDRForForce||templateId={}||errMsg={}\", templateId, e.getMessage(), e);\n            return buildStepMsg(DCDRSwithTypeEnum.FORCE.getCode(), Result.buildFail(e.getMessage()), templateId,\n                expectMasterPhysicalId, step, operator, switchDetail.getTaskProgressList());\n        }\n\n        return Result.buildSucc(switchDetail.getTaskProgressList());\n    }\n\n    /**\n     * todo：alibaba规范 方法总行数超过80行\n     * 执行\n     * @param switchDetail\n     * @param expectMasterPhysicalId         期望的模板Id\n     * @param step                           切换起始步骤\n     * @param masterTemplate                 主模板元数据信息\n     * @param slaveTemplate                  从模板元数据信息\n     * @param operator\n     * @return\n     */\n    private Result<List<String>> executeDCDRForSmooth(Integer workTaskId,\n                                                      DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail,\n                                                      Long expectMasterPhysicalId, int step,\n                                                      IndexTemplatePhy masterTemplate, IndexTemplatePhy slaveTemplate,\n                                                      String operator) {\n        List<String> matchIndexNames = indexTemplatePhyService.getMatchIndexNames(masterTemplate.getId());\n        String indexExpression=slaveTemplate.getExpression();\n        \n        int templateId = switchDetail.getTemplateId().intValue();\n        //todo 注意如果主比从多一个索引的状态下，那么平滑切换是有问题\n        try {\n            /**\n             * 注意这里的if不能使用else if代替，这里的代码需要顺序执行下去\n             */\n            if (DCDR_SWITCH_STEP_1 == step) {\n                // 校验从集群到主集群是否是通路：这里是由于平切之后会创建链路，那么就会出现问题，所以这里得严格规定\n                Result<Void> slaveConnectedMaster = createRemoteClusterAndCheckConnected(slaveTemplate.getCluster(),\n                        masterTemplate.getCluster());\n                Result<List<String>> step1ResultForCheck = buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(),\n                        slaveConnectedMaster, templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_1, operator,\n                        switchDetail.getTaskProgressList());\n                if (step1ResultForCheck.failed()) {\n                    return step1ResultForCheck;\n                }\n                \n                Result<Void> stopMasterIndexResult;\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    stopMasterIndexResult = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    // 停止索引写入:使用indexName*的方式进行索引关闭，避免索引数量过多，从而导致了执行时间过长\n                    boolean suc = esIndexService.syncBatchBlockIndexWrite(masterTemplate.getCluster(),\n                            Collections.singletonList(indexExpression),\n                        true, 3);\n                    stopMasterIndexResult = Result.build(suc);\n                }\n\n                Result<List<String>> step1Result = buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(),\n                    stopMasterIndexResult, templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_1, operator,\n                    switchDetail.getTaskProgressList());\n                if (step1Result.failed()) {\n                    return step1Result;\n                }\n                step++;\n                sleep(1000L);\n            }\n\n            if (DCDR_SWITCH_STEP_2 == step) {\n                // 确保主从数据同步完成\n                Result<Void> checkDataResult = Result.buildSucc();\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    checkDataResult = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    if (!esIndexService.ensureDataSame(masterTemplate.getCluster(), slaveTemplate.getCluster(),\n                        matchIndexNames,indexExpression,switchDetail.getTimeout())) {\n                        checkDataResult = Result.buildFail(\"校验索引数据不一致!\");\n                        // 恢复实时数据写入：使用indexName*的方式进行索引关闭，避免索引数量过多，从而导致了执行时间过长\n                        Result<Void> sttartMasterIndexResult = Result.build(esIndexService\n                            .syncBatchBlockIndexWrite(masterTemplate.getCluster(), Collections.singletonList(indexExpression),\n                                    false, 3));\n                        if (sttartMasterIndexResult.failed()) {\n                            checkDataResult\n                                .setMessage(checkDataResult.getMessage() + \"|\" + sttartMasterIndexResult.getMessage());\n                        }\n                    }\n                }\n\n                Result<List<String>> step2Result = buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(), checkDataResult,\n                    templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_2, operator,\n                    switchDetail.getTaskProgressList());\n                if (step2Result.failed()) {\n                    return step2Result;\n                }\n                step++;\n                sleep(1000L);\n            }\n\n            if (DCDR_SWITCH_STEP_3 == step) {\n                Result<Void> deleteSrcDCDRResult;\n                // 删除DCDR链路（模板和索引）\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    deleteSrcDCDRResult = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    deleteSrcDCDRResult = deleteSrcDCDR(masterTemplate, slaveTemplate, matchIndexNames,\n                        AriusUser.SYSTEM.getDesc());\n                }\n\n                Result<List<String>> step3Result = buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(), deleteSrcDCDRResult,\n                    templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_3, operator,\n                    switchDetail.getTaskProgressList());\n                if (step3Result.failed()) {\n                    return step3Result;\n                }\n                step++;\n                sleep(1000L);\n            }\n\n            if (DCDR_SWITCH_STEP_4 == step) {\n                Result<Void> copyResult = Result.buildSucc();\n\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    copyResult = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    // 拷贝主模板到从模板\n                    if (!esTemplateService.syncCopyMappingAndAlias(masterTemplate.getCluster(),\n                        masterTemplate.getName(), slaveTemplate.getCluster(), slaveTemplate.getName(), 3)) {\n                        copyResult = Result.buildFail(\"拷贝模板失败\");\n                    }\n                }\n               \n\n                Result<List<String>> step4Result = buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(), copyResult,\n                    templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_4, operator,\n                    switchDetail.getTaskProgressList());\n                if (step4Result.failed()) {\n                    return step4Result;\n                }\n                step++;\n                sleep(1000L);\n            }\n\n            if (DCDR_SWITCH_STEP_5 == step) {\n                // 修改DCDR索引配置 index.dcdr.replica_index = true/false\n                // 然后还需要reopen索引，配置才能生效\n                Result<Void> setSettingResult = Result.buildSucc();\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    setSettingResult = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    //使用indexName*的方式进行索引关闭，避免索引数量过多，从而导致了执行时间过长\n                    Result<Void> changeMasterDCDRConfig = changeDCDRConfig(masterTemplate.getCluster(),\n                            Collections.singletonList(indexExpression),\n                        true);\n                    //使用indexName*的方式进行索引关闭，避免索引数量过多，从而导致了执行时间过长\n                    Result<Void> changeSlaveDCDRConfig = changeDCDRConfig(slaveTemplate.getCluster(),\n                            Collections.singletonList(indexExpression),\n                        false);\n                   \n\n                    if (changeMasterDCDRConfig.failed() || changeSlaveDCDRConfig.failed()) {\n                        setSettingResult = Result\n                            .buildFail(changeMasterDCDRConfig.getMessage() + \"|\" + changeSlaveDCDRConfig.getMessage());\n                    }\n                }\n\n                Result<List<String>> step5Result = buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(), setSettingResult,\n                    templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_5, operator,\n                    switchDetail.getTaskProgressList());\n                if (step5Result.failed()) {\n                    return step5Result;\n                }\n                step++;\n                sleep(1000L);\n            }\n\n            if (DCDR_SWITCH_STEP_6 == step) {\n                // 停止索引写入\n                Result<Void> stopSlaveIndexResult;\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    stopSlaveIndexResult = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    //使用indexName*的方式进行索引关闭，避免索引数量过多，从而导致了执行时间过长\n                    stopSlaveIndexResult = Result.build(\n                        esIndexService.syncBatchBlockIndexWrite(masterTemplate.getCluster(),\n                                Collections.singletonList(indexExpression), true, 3));\n                }\n                Result<List<String>> step6Result = buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(),\n                    stopSlaveIndexResult, templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_6, operator,\n                    switchDetail.getTaskProgressList());\n                if (step6Result.failed()) {\n                    return step6Result;\n                }\n                step++;\n                sleep(1000L);\n            }\n\n            if (DCDR_SWITCH_STEP_7 == step) {\n                Result<Void> createDCDRResult;\n                // 创建新的主从链路\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    createDCDRResult = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    createDCDRResult = createPhyDCDR(buildCreateDCDRParam(slaveTemplate, masterTemplate),\n                        AriusUser.SYSTEM.getDesc());\n                }\n                Result<List<String>> step7Result = buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(), createDCDRResult,\n                    templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_7, operator,\n                    switchDetail.getTaskProgressList());\n                if (step7Result.failed()) {\n                    return step7Result;\n                }\n                step++;\n                sleep(1000L);\n            }\n\n            if (DCDR_SWITCH_STEP_8 == step) {\n                // 恢复实时写入\n                Result<Void> startIndexResult = Result.buildSucc();\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    startIndexResult = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    //使用indexName*的方式进行索引关闭，避免索引数量过多，从而导致了执行时间过长\n                    Result<Void> startMasterIndexResult = Result.build(esIndexService\n                        .syncBatchBlockIndexWrite(masterTemplate.getCluster(), Collections.singletonList(indexExpression), false,\n                                3));\n\n                    Result<Void> startSlaveIndexResult = Result.build(\n                        esIndexService.syncBatchBlockIndexWrite(slaveTemplate.getCluster(), Collections.singletonList(indexExpression), false, 3));\n\n                    if (startMasterIndexResult.failed() || startSlaveIndexResult.failed()) {\n                        startIndexResult = Result\n                            .buildFail(startMasterIndexResult.getMessage() + \"|\" + startSlaveIndexResult.getMessage());\n                    }\n                }\n\n                Result<List<String>> step8Result = buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(), startIndexResult,\n                    templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_8, operator,\n                    switchDetail.getTaskProgressList());\n                if (step8Result.failed()) {\n                    return step8Result;\n                }\n                step++;\n                sleep(1000L);\n            }\n\n            if (DCDR_SWITCH_STEP_9 == step) {\n                // 主从角色切换\n                Result<Void> switchMasterSlave;\n                if (hasCancelSubTask(workTaskId, switchDetail.getTemplateId())) {\n                    switchMasterSlave = Result.buildFail(TASK_IS_CANCEL);\n                } else {\n                    if (hasFinishSwitchMasterSlave(switchDetail)) {\n                        switchMasterSlave = Result.buildSucc();\n                    } else {\n                        switchMasterSlave = templatePhyManager.switchMasterSlave(masterTemplate.getLogicId(),\n                            slaveTemplate.getId(), AriusUser.SYSTEM.getDesc());\n                    }\n                }\n\n                Result<List<String>> step9Result = buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(), switchMasterSlave,\n                    templateId, expectMasterPhysicalId, DCDR_SWITCH_STEP_9, operator,\n                    switchDetail.getTaskProgressList());\n                if (step9Result.failed()) {\n                    return step9Result;\n                }\n                //打开hasDCDR\n                IndexTemplatePO indexTemplatePO = new IndexTemplatePO();\n                indexTemplatePO.setId(masterTemplate.getLogicId());\n                indexTemplatePO.setHasDCDR(true);\n                indexTemplateService.update(indexTemplatePO);\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\"method=executeDCDRForSmooth||templateId={}||errMsg={}\", templateId, e.getMessage(), e);\n            return buildStepMsg(DCDRSwithTypeEnum.SMOOTH.getCode(), Result.buildFail(e.getMessage()), templateId,\n                expectMasterPhysicalId, step, operator, switchDetail.getTaskProgressList());\n        }\n        return Result.buildSucc(switchDetail.getTaskProgressList());\n    }\n    \n \n    \n    /**\n     * 是否已经成功切换\n     * @param switchDetail\n     * @return\n     */\n    private boolean hasFinishSwitchMasterSlave(DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail) {\n        IndexTemplateWithPhyTemplates logicTemplateWithPhysicals = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(switchDetail.getTemplateId().intValue());\n        IndexTemplatePhy masterTemplate = logicTemplateWithPhysicals.getMasterPhyTemplate();\n        IndexTemplatePhy slaveTemplate = logicTemplateWithPhysicals.getSlavePhyTemplate();\n\n        String masterTemplateClusterFromDB = masterTemplate.getCluster();\n        String slaveTemplateClusterFromDB = slaveTemplate.getCluster();\n\n        String masterCluster = switchDetail.getMasterCluster();\n        String slaveCluster = switchDetail.getSlaveCluster();\n        return masterCluster.equals(masterTemplateClusterFromDB) && slaveCluster.equals(slaveTemplateClusterFromDB);\n    }\n\n    private void sleep(long l) {\n        try {\n            Thread.sleep(l);\n        } catch (InterruptedException ignored) {\n            Thread.currentThread().interrupt();\n        }\n    }\n\n    /**\n     * 单个DCDR子任务是否取消\n     * @param workTaskId\n     * @param templateId\n     * @return\n     */\n    private boolean hasCancelSubTask(Integer workTaskId, Long templateId) {\n        Result<OpTask> workTaskResult = opTaskManager.getById(workTaskId);\n        if (null == workTaskResult || null == workTaskResult.getData()) {\n            LOGGER.error(\"method=submitTask||workTaskId={}||msg= workTaskId is empty\", workTaskId);\n            return false;\n        }\n        OpTask opTask = workTaskResult.getData();\n\n        DCDRTasksDetail dcdrTasksDetail = JSON.parseObject(opTask.getExpandData(), DCDRTasksDetail.class);\n        List<DCDRSingleTemplateMasterSlaveSwitchDetail> switchDetailList = dcdrTasksDetail\n            .getDcdrSingleTemplateMasterSlaveSwitchDetailList();\n        if (CollectionUtils.isEmpty(switchDetailList)) {\n            return false;\n        }\n\n        for (DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail : switchDetailList) {\n            if (templateId.equals(switchDetail.getTemplateId())\n                && DCDRStatusEnum.CANCELLED.getCode().equals(switchDetail.getTaskStatus())) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    @NotNull\n    private List<String> buildInitTaskProgressInfo(String[] dcdrSwitchStepArrSmooth) {\n        List<String> stepMsgList = Lists.newArrayList();\n        for (String stepMsgFormat : dcdrSwitchStepArrSmooth) {\n            stepMsgList.add(String.format(stepMsgFormat, SEPARATOR + DCDR_SWITCH_TODO));\n        }\n        return stepMsgList;\n    }\n\n    private Result<List<String>> buildStepMsg(Integer swithType, Result<Void> result, Integer logicId,\n                                              Long expectMasterPhysicalId, int localStep, String operator,\n                                              List<String> stepMsgList) {\n        if (DCDRSwithTypeEnum.FORCE.getCode().equals(swithType)) {\n            int localStepTemp = DCDR_SWITCH_STEP_5;\n\n            if (localStep == DCDR_SWITCH_STEP_2) {\n                localStepTemp = DCDR_SWITCH_STEP_9;\n            }\n\n            if (result.failed()) {\n                buildSwitchStepMsgForFailedList(stepMsgList, result, localStep, localStepTemp);\n                return Result.buildFail(stepMsgList);\n            }\n            buildSwitchStepMsgForSuccessList(stepMsgList, localStep, localStepTemp);\n        }\n\n        if (DCDRSwithTypeEnum.SMOOTH.getCode().equals(swithType)) {\n            if (result.failed()) {\n                buildSwitchStepMsgForFailedList(stepMsgList, result, localStep, localStep);\n                return Result.buildFail(stepMsgList);\n            }\n            buildSwitchStepMsgForSuccessList(stepMsgList, localStep, localStep);\n        }\n\n        LOGGER.info(\n            \"method=DCDRSwitchMasterSlave||logicId={}||operator={}||expectMasterPhysicalId={}||msg=step {} succ\",\n            logicId, operator, expectMasterPhysicalId, localStep);\n        return Result.buildSucc(stepMsgList);\n    }\n\n    private void buildSwitchStepMsgForFailedList(List<String> stepMsgList, Result<Void> result, int localStep,\n                                                 int localStepTemp) {\n        stepMsgList.set(localStep - 1,\n            String.format(TemplateDCDRStepEnum.valueOfStep(localStepTemp).getValue(), SEPARATOR + DCDR_SWITCH_FAIL)\n                                       + SEPARATOR + result.getMessage());\n    }\n\n    private void buildSwitchStepMsgForSuccessList(List<String> stepMsgList, int localStep, int localStepTemp) {\n        stepMsgList.set(localStep - 1, String.format(TemplateDCDRStepEnum.valueOfStep(localStepTemp).getValue(),\n            SEPARATOR + DCDR_SWITCH_DONE + SEPARATOR + SUCCESS_INFO));\n    }\n\n    private Result<Void> processDcdrTask(Integer logicId, Result<Void> dcdrResult,\n                                         int step) throws NotFindSubclassException {\n        Result<OpTask> result = opTaskManager.getLatestTask(String.valueOf(logicId),\n            OpTaskTypeEnum.TEMPLATE_DCDR.getType());\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n        OpTaskProcessDTO processDTO = new OpTaskProcessDTO();\n        processDTO.setStatus(\n            dcdrResult.success() ? OpTaskStatusEnum.SUCCESS.getStatus() : OpTaskStatusEnum.FAILED.getStatus());\n        processDTO.setTaskId(result.getData().getId());\n        processDTO.setTaskProgress(step);\n\n        if (dcdrResult.failed()) {\n            DCDRTaskDetail detail = new DCDRTaskDetail();\n            detail.setComment(result.getMessage());\n            processDTO.setExpandData(JSON.toJSONString(detail));\n        }\n        return opTaskManager.processTask(processDTO);\n    }\n\n    private TemplatePhysicalCopyDTO buildTemplatePhysicalCopyDTO(Integer templateId, String targetCluster,\n                                                                 Integer regionId) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(templateId);\n\n        TemplatePhysicalCopyDTO templatePhysicalCopyDTO = new TemplatePhysicalCopyDTO();\n        IndexTemplatePhy masterPhyTemplate = templateLogicWithPhysical.getMasterPhyTemplate();\n        if (null == masterPhyTemplate) {\n            return null;\n        }\n\n        templatePhysicalCopyDTO.setCluster(targetCluster);\n        templatePhysicalCopyDTO.setPhysicalId(masterPhyTemplate.getId());\n        templatePhysicalCopyDTO.setShard(masterPhyTemplate.getShard());\n        templatePhysicalCopyDTO.setRegionId(regionId);\n        return templatePhysicalCopyDTO;\n    }\n\n    /**\n     * 构建业务key\n     * @param templateIdList\n     * @return\n     */\n    @NotNull\n    private String getBusinessKey(List<Long> templateIdList) {\n        List<String> templateIdStrList = templateIdList.stream().map(String::valueOf).collect(Collectors.toList());\n        return ListUtils.strList2String(templateIdStrList);\n    }\n\n    private Result<Void> checkValidForDCDRSwitch(Integer logicId, Long expectMasterPhysicalId, int step,\n                                                 String operator) {\n        List<IndexTemplatePhy> templatePhysicals = indexTemplatePhyService.getTemplateByLogicId(logicId);\n        if (CollectionUtils.isEmpty(templatePhysicals)) {\n            return Result.buildNotExist(\"逻辑模板有没有部署物理模板\");\n        }\n\n        if (templatePhysicals.size() > MAX_PHY_TEMPLATE_NUM) {\n            return Result.buildParamIllegal(\"DCDR主从切换只支持2副本部署\");\n        }\n\n        IndexTemplatePhy masterTemplate = null;\n        IndexTemplatePhy slaveTemplate = null;\n        for (IndexTemplatePhy templatePhysical : templatePhysicals) {\n            if (MASTER.getCode().equals(templatePhysical.getRole())) {\n                masterTemplate = templatePhysical;\n            }\n            if (SLAVE.getCode().equals(templatePhysical.getRole())) {\n                slaveTemplate = templatePhysical;\n            }\n        }\n\n        if (masterTemplate == null || slaveTemplate == null) {\n            return Result.buildParamIllegal(\"模板主从部署角色异常\");\n        }\n\n        if (masterTemplate.getId().equals(expectMasterPhysicalId)) {\n            return Result.buildSucc();\n        }\n\n        if (step > TemplateDCDRStepEnum.STEP_9.getStep() || step < TemplateDCDRStepEnum.STEP_1.getStep()) {\n            step = TemplateDCDRStepEnum.STEP_1.getStep();\n        }\n     \n       \n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> batchCheckValidForDCDRSwitch(List<Long> templateIdList, String operator) {\n        if (CollectionUtils.isEmpty(templateIdList)) {\n            return Result.buildParamIllegal(\"模板id为空\");\n        }\n        for (Long templateId : templateIdList) {\n            IndexTemplateWithPhyTemplates logicTemplateWithPhysicals = indexTemplateService\n                .getLogicTemplateWithPhysicalsById(templateId.intValue());\n\n            IndexTemplatePhy slaveTemplate = logicTemplateWithPhysicals.getSlavePhyTemplate();\n            if (null == slaveTemplate) {\n                return Result.buildFail(String.format(\"模板Id[%s]不存在从模板, 无法进行DCDR主从切换\", templateId));\n            }\n\n            Result<Void> checkValidForDCDRSwitchResult = checkValidForDCDRSwitch(templateId.intValue(),\n                slaveTemplate.getId(), 1, operator);\n            if (checkValidForDCDRSwitchResult.failed()) {\n                return checkValidForDCDRSwitchResult;\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    private DCDRTasksDetail buildDCDRTasksDetail(DCDRMasterSlaveSwitchDTO dcdrMasterSlaveSwitchDTO,\n                                                 List<Long> templateIdList) {\n        DCDRTasksDetail dcdrTasksDetail = new DCDRTasksDetail();\n        List<DCDRSingleTemplateMasterSlaveSwitchDetail> dcdrSingleTemplateMasterSlaveSwitchDetailList = new ArrayList<>();\n        //1. 设置DCDR详情信息\n        for (Long templateId : templateIdList) {\n            DCDRSingleTemplateMasterSlaveSwitchDetail singleSwitchDetail = new DCDRSingleTemplateMasterSlaveSwitchDetail();\n\n            IndexTemplate logicTemplate = indexTemplateService.getLogicTemplateById(templateId.intValue());\n            singleSwitchDetail.editTaskTitle(logicTemplate.getName());\n\n            //1.1 设置切换类型 强切、平滑\n            singleSwitchDetail.setSwitchType(dcdrMasterSlaveSwitchDTO.getType());\n\n            //1.2 构建DCDR主从切换基础信息\n            singleSwitchDetail.setTemplateId(templateId);\n\n            IndexTemplateWithPhyTemplates logicTemplateWithPhysicals = indexTemplateService\n                .getLogicTemplateWithPhysicalsById(templateId.intValue());\n            IndexTemplatePhy masterTemplate = logicTemplateWithPhysicals.getMasterPhyTemplate();\n            IndexTemplatePhy slaveTemplate = logicTemplateWithPhysicals.getSlavePhyTemplate();\n            singleSwitchDetail.setMasterCluster(slaveTemplate.getCluster());\n            singleSwitchDetail.setSlaveCluster(masterTemplate.getCluster());\n            singleSwitchDetail.setDeleteDcdrChannelFlag(false);\n            singleSwitchDetail.setCreateTime(new Date());\n\n            //1.3 构建DCDR主从切换初始化任务进度信息\n            List<String> stepMsgList = new ArrayList<>();\n            if (DCDRSwithTypeEnum.SMOOTH.getCode().equals(singleSwitchDetail.getSwitchType())) {\n                stepMsgList = buildInitTaskProgressInfo(DCDR_SWITCH_STEP_ARR_SMOOTH);\n            }\n\n            if (DCDRSwithTypeEnum.FORCE.getCode().equals(singleSwitchDetail.getSwitchType())) {\n                stepMsgList = buildInitTaskProgressInfo(DCDR_SWITCH_STEP_ARR_FORCE);\n            }\n            singleSwitchDetail.setTaskProgressList(stepMsgList);\n\n            dcdrSingleTemplateMasterSlaveSwitchDetailList.add(singleSwitchDetail);\n        }\n\n        //2. 分批次执行\n        int tempDCDRConcurrent = dcdrConcurrent;\n        Collections.shuffle(dcdrSingleTemplateMasterSlaveSwitchDetailList);\n        for (DCDRSingleTemplateMasterSlaveSwitchDetail singleTemplateMasterSlaveSwitchDetail : dcdrSingleTemplateMasterSlaveSwitchDetailList) {\n            if (tempDCDRConcurrent > 0) {\n                singleTemplateMasterSlaveSwitchDetail.setTaskStatus(DCDRStatusEnum.RUNNING.getCode());\n                tempDCDRConcurrent--;\n            } else {\n                singleTemplateMasterSlaveSwitchDetail.setTaskStatus(DCDRStatusEnum.WAIT.getCode());\n            }\n        }\n\n        dcdrTasksDetail.setDcdrSingleTemplateMasterSlaveSwitchDetailList(dcdrSingleTemplateMasterSlaveSwitchDetailList);\n        return dcdrTasksDetail;\n    }\n\n    /**\n     * 刷新DCDR链路状态\n     * @param taskId                 DCDR主从切换任务id\n     * @param step                   是否需要根据起始执行步骤往后执行\n     * @param operator\n     *\n     */\n    private void doRefreshDCDRChannelsState(Integer taskId, Integer step, String operator) {\n        Result<OpTask> taskForDcdrSwitchResult = opTaskManager.getById(taskId);\n        if (taskForDcdrSwitchResult.failed()) {\n            LOGGER.error(\"method=asyncRefreshDCDRChannelState||taskId={}||msg=taskId is empty\", taskId);\n            return;\n        }\n\n        OpTask taskForDCDRSwitch = taskForDcdrSwitchResult.getData();\n\n        DCDRTasksDetail dcdrTasksDetail = ConvertUtil.str2ObjByJson(taskForDCDRSwitch.getExpandData(),\n            DCDRTasksDetail.class);\n        if (null == dcdrTasksDetail) {\n            return;\n        }\n\n        if (hasSkipForTask(taskForDCDRSwitch, dcdrTasksDetail)) {\n            return;\n        }\n\n        List<DCDRSingleTemplateMasterSlaveSwitchDetail> singleSwitchDetailList = dcdrTasksDetail\n            .getDcdrSingleTemplateMasterSlaveSwitchDetailList();\n        if (CollectionUtils.isEmpty(singleSwitchDetailList)) {\n            return;\n        }\n\n        for (DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail : singleSwitchDetailList) {\n            //前置过滤处理\n            if (hasSkipForSingleDCDRRefresh(switchDetail)) {\n                continue;\n            }\n\n            //并发去刷新多个模板状态\n            BATCH_DCDR_FUTURE_UTIL.runnableTask(() -> {\n                try {\n                    IndexTemplateWithPhyTemplates logicTemplateWithPhysicals = indexTemplateService\n                        .getLogicTemplateWithPhysicalsById(switchDetail.getTemplateId().intValue());\n                    IndexTemplatePhy masterTemplate = logicTemplateWithPhysicals.getMasterPhyTemplate();\n                    IndexTemplatePhy slaveTemplate = logicTemplateWithPhysicals.getSlavePhyTemplate();\n\n                    if (null == slaveTemplate) {\n                        return;\n                    }\n\n                    // 防止并发问题带来的逆向主从切换\n                    if (switchDetail.getMasterCluster().equals(masterTemplate.getCluster())\n                        && switchDetail.getSlaveCluster().equals(slaveTemplate.getCluster())) {\n                        return;\n                    }\n\n                    syncRefreshStatus(taskId, step, switchDetail, masterTemplate, slaveTemplate, operator);\n\n                    switchDetail.setUpdateTime(new Date());\n                } catch (Exception e) {\n                    LOGGER.error(\"method=doRefreshDCDRChannelsState||taskId={}||templateId={}||msg={}\",\n                        taskForDCDRSwitch.getId(), switchDetail.getTemplateId(), e.getMessage(), e);\n                }\n\n            });\n        }\n        BATCH_DCDR_FUTURE_UTIL.waitExecute(120);\n\n        try {\n            saveNewestWorkTaskStatusToDB(taskForDCDRSwitch, dcdrTasksDetail, AuthConstant.SUPER_PROJECT_ID);\n        } catch (Exception e) {\n            LOGGER.error(\"method=doRefreshDCDRChannelsState||taskId={}||msg=failed to save newest workTask to db\",\n                taskForDCDRSwitch.getId(), e);\n        }\n    }\n\n    /**\n     * 同步刷新状态\n     *\n     * @param taskId\n     * @param step                步骤\n     * @param switchDetail        元数据\n     * @param masterTemplate      主模板信息\n     * @param slaveTemplate       从模板信息\n     * @param operator            操作人\n     * @return\n     */\n    @NotNull\n    private void syncRefreshStatus(Integer taskId, Integer step, DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail,\n                                   IndexTemplatePhy masterTemplate, IndexTemplatePhy slaveTemplate, String operator) {\n\n        Result<List<String>> executeDCDRResult = Result.buildSucc();\n        // 平滑切换刷新状态\n        if (DCDRSwithTypeEnum.SMOOTH.getCode().equals(switchDetail.getSwitchType())) {\n            executeDCDRResult = executeDCDRForSmooth(taskId, switchDetail, slaveTemplate.getId(), step, masterTemplate,\n                slaveTemplate, operator);\n        }\n\n        // 强制切换刷新状态\n        if (DCDRSwithTypeEnum.FORCE.getCode().equals(switchDetail.getSwitchType())) {\n            executeDCDRResult = executeDCDRForForce(taskId, switchDetail, slaveTemplate.getId(), step, masterTemplate,\n                slaveTemplate, operator);\n        }\n\n        // 最新状态\n        if (executeDCDRResult.failed()) {\n            switchDetail.setTaskStatus(DCDRStatusEnum.FAILED.getCode());\n        }\n        if (executeDCDRResult.success()) {\n            switchDetail.setTaskStatus(DCDRStatusEnum.SUCCESS.getCode());\n        }\n    }\n\n    /**\n     * 更新db中 DCDR任务状态\n     *\n     * @param taskForDCDRSwitch 原任务状态信息\n     * @param dcdrTasksDetail   新具体状态信息\n     * @param projectId\n     */\n    private void saveNewestWorkTaskStatusToDB(OpTask taskForDCDRSwitch, DCDRTasksDetail dcdrTasksDetail,\n                                              Integer projectId) {\n        //根据多个detail task 来计算状态\n        dcdrTasksDetail.calculateProcess();\n\n        //是否需要设置下一批DCDR模板切换任务的状态为running\n        setNextBatchDCDRTaskDetailStateToRunning(dcdrTasksDetail);\n\n        if (DCDRStatusEnum.SUCCESS.getCode().equals(dcdrTasksDetail.getState())) {\n            taskForDCDRSwitch.setStatus(OpTaskStatusEnum.SUCCESS.getStatus());\n            //成功删除DCDR链路\n            deleteDCDRChannelForSuccForceSwitch(taskForDCDRSwitch, dcdrTasksDetail, projectId);\n        }\n\n        if (DCDRStatusEnum.FAILED.getCode().equals(dcdrTasksDetail.getState())) {\n            taskForDCDRSwitch.setStatus(OpTaskStatusEnum.FAILED.getStatus());\n        }\n        if (DCDRStatusEnum.CANCELLED.getCode().equals(dcdrTasksDetail.getState())) {\n            taskForDCDRSwitch.setStatus(OpTaskStatusEnum.CANCEL.getStatus());\n        }\n        if (DCDRStatusEnum.RUNNING.getCode().equals(dcdrTasksDetail.getState())) {\n            taskForDCDRSwitch.setStatus(OpTaskStatusEnum.RUNNING.getStatus());\n        }\n\n        taskForDCDRSwitch.setExpandData(ConvertUtil.obj2Json(dcdrTasksDetail));\n\n        // 解决分布式部署由于时序不一致带来更新不一致的问题\n        Result<OpTask> workTaskResult = opTaskManager.getById(taskForDCDRSwitch.getId());\n        if (null != workTaskResult.getData()\n            && OpTaskStatusEnum.SUCCESS.getStatus().equals(workTaskResult.getData().getStatus())) {\n            return;\n        }\n\n        // 这里由于多线程更新，可能会出现不可重复读的问题，所以这里加上了一个判断\n        // 临时打个补丁，等待下一个版本ecm 重构\n        if (workTaskResult.getData().getUpdateTime().after(taskForDCDRSwitch.getUpdateTime())) {\n            return;\n        }\n        taskForDCDRSwitch.setUpdateTime(new Date());\n\n        opTaskManager.updateTask(taskForDCDRSwitch);\n    }\n\n    /**\n     * 强切成功删除DCDR链路\n     *\n     * @param taskForDCDRSwitch 任务信息\n     * @param dcdrTasksDetail   DCDR任务信息\n     * @param projectId\n     */\n    private void deleteDCDRChannelForSuccForceSwitch(OpTask taskForDCDRSwitch, DCDRTasksDetail dcdrTasksDetail,\n                                                     Integer projectId) {\n        for (DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail : dcdrTasksDetail\n            .getDcdrSingleTemplateMasterSlaveSwitchDetailList()) {\n            if (DCDRSwithTypeEnum.FORCE.getCode().equals(switchDetail.getSwitchType())) {\n                try {\n                    Result<Void> deleteDCDRResult = deleteDCDR(switchDetail.getTemplateId().intValue(),\n                        AriusUser.SYSTEM.getDesc(), projectId,true);\n                    if (deleteDCDRResult.failed()) {\n                        LOGGER.error(\n                            \"method=deleteDCDRChannelForSuccForceSwitch||taskId={}||msg=failed to deleteDCDR for force switch\",\n                            taskForDCDRSwitch.getId());\n                        switchDetail.setDeleteDcdrChannelFlag(false);\n                    } else {\n                        switchDetail.setDeleteDcdrChannelFlag(true);\n                    }\n                } catch (ESOperateException e) {\n                    LOGGER.error(\n                        \"method=deleteDCDRChannelForSuccForceSwitch||taskId={}||msg=failed to deleteDCDR for force switch\",\n                        taskForDCDRSwitch.getId(), e);\n                    switchDetail.setDeleteDcdrChannelFlag(false);\n                }\n            }\n        }\n    }\n\n    /**\n     * 是否需要更新下一批DCDR模板切换任务的状态为running\n     * @param dcdrTasksDetail\n     */\n    private void setNextBatchDCDRTaskDetailStateToRunning(DCDRTasksDetail dcdrTasksDetail) {\n        List<DCDRSingleTemplateMasterSlaveSwitchDetail> slaveSwitchDetailList = dcdrTasksDetail\n            .getDcdrSingleTemplateMasterSlaveSwitchDetailList();\n\n        // 按任务状态分组\n        Map<Integer, List<DCDRSingleTemplateMasterSlaveSwitchDetail>> status2SwitchDetailMap = ConvertUtil\n            .list2MapOfList(slaveSwitchDetailList, DCDRSingleTemplateMasterSlaveSwitchDetail::getTaskStatus,\n                dcdrSingleTemplateMasterSlaveSwitchDetail -> dcdrSingleTemplateMasterSlaveSwitchDetail);\n\n        //获取任务成功数\n        List<DCDRSingleTemplateMasterSlaveSwitchDetail> runningSwitchDetailList = status2SwitchDetailMap\n            .get(DCDRStatusEnum.RUNNING.getCode());\n        int runingTaskSize = CollectionUtils.isNotEmpty(runningSwitchDetailList) ? runningSwitchDetailList.size() : 0;\n\n        //获取任务失败数\n        List<DCDRSingleTemplateMasterSlaveSwitchDetail> failedSwitchDetailList = status2SwitchDetailMap\n            .get(DCDRStatusEnum.FAILED.getCode());\n        int failedTaskSize = CollectionUtils.isNotEmpty(failedSwitchDetailList) ? failedSwitchDetailList.size() : 0;\n\n        // 运行数小于 并发数, 并且在失败数上限\n        if (hasSetNextBatch(runingTaskSize, failedTaskSize)) {\n            List<DCDRSingleTemplateMasterSlaveSwitchDetail> waitingSwitchDetailList = status2SwitchDetailMap\n                .get(DCDRStatusEnum.WAIT.getCode());\n\n            if (CollectionUtils.isEmpty(waitingSwitchDetailList)) {\n                return;\n            }\n\n            int tempDCDRConcurrent = dcdrConcurrent;\n            for (DCDRSingleTemplateMasterSlaveSwitchDetail waitingSwitchDetail : waitingSwitchDetailList) {\n                if (tempDCDRConcurrent > 0) {\n                    waitingSwitchDetail.setTaskStatus(DCDRStatusEnum.RUNNING.getCode());\n                    tempDCDRConcurrent--;\n                }\n            }\n        }\n    }\n\n    /**\n     * 是否需要跳过 DCDRChannel 刷新流程\n     * @param dcdrSingleTemplateMasterSlaveSwitchDetail\n     * @return\n     */\n    private boolean hasSkipForSingleDCDRRefresh(DCDRSingleTemplateMasterSlaveSwitchDetail dcdrSingleTemplateMasterSlaveSwitchDetail) {\n        return DCDRStatusEnum.CANCELLED.getCode().equals(dcdrSingleTemplateMasterSlaveSwitchDetail.getTaskStatus())\n               || DCDRStatusEnum.SUCCESS.getCode().equals(dcdrSingleTemplateMasterSlaveSwitchDetail.getTaskStatus())\n               || DCDRStatusEnum.WAIT.getCode().equals(dcdrSingleTemplateMasterSlaveSwitchDetail.getTaskStatus())\n               || DCDRStatusEnum.FAILED.getCode().equals(dcdrSingleTemplateMasterSlaveSwitchDetail.getTaskStatus());\n    }\n\n    /**\n     * 是否需要跳过 任务刷新\n     * @param taskForDCDRSwitch\n     * @param dcdrTasksDetail\n     * @return\n     */\n    private boolean hasSkipForTask(OpTask taskForDCDRSwitch, DCDRTasksDetail dcdrTasksDetail) {\n        List<DCDRSingleTemplateMasterSlaveSwitchDetail> switchDetailList = dcdrTasksDetail\n            .getDcdrSingleTemplateMasterSlaveSwitchDetailList();\n        List<Integer> runningTaskStatusList = switchDetailList.stream()\n            .filter(switchDetail -> DCDRStatusEnum.RUNNING.getCode().equals(switchDetail.getTaskStatus()))\n            .map(DCDRSingleTemplateMasterSlaveSwitchDetail::getTaskStatus).collect(Collectors.toList());\n\n        return OpTaskStatusEnum.CANCEL.getStatus().equals(taskForDCDRSwitch.getStatus())\n               || OpTaskStatusEnum.SUCCESS.getStatus().equals(taskForDCDRSwitch.getStatus())\n               || runningTaskStatusList.isEmpty();\n    }\n\n    /**\n     * 初始化主从切换任务信息\n     * @param templateId\n     * @param dcdrTasksDetail\n     */\n    private void initSwitchTaskInfo(Integer templateId, DCDRTasksDetail dcdrTasksDetail) {\n        if (null != templateId) {\n            List<DCDRSingleTemplateMasterSlaveSwitchDetail> switchDetailList = dcdrTasksDetail\n                .getDcdrSingleTemplateMasterSlaveSwitchDetailList();\n            for (DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail : switchDetailList) {\n                if (templateId.equals(switchDetail.getTemplateId().intValue())) {\n                    switchDetail.setTaskStatus(DCDRStatusEnum.RUNNING.getCode());\n                    if (DCDRSwithTypeEnum.SMOOTH.getCode().equals(switchDetail.getSwitchType())) {\n                        switchDetail.setTaskProgressList(buildInitTaskProgressInfo(DCDR_SWITCH_STEP_ARR_SMOOTH));\n                    }\n\n                    if (DCDRSwithTypeEnum.FORCE.getCode().equals(switchDetail.getSwitchType())) {\n                        switchDetail.setTaskProgressList(buildInitTaskProgressInfo(DCDR_SWITCH_STEP_ARR_FORCE));\n                    }\n                }\n            }\n        }\n    }\n\n    /**\n     * 判断是否需要切换执行下批任务\n     * @param runingTaskSize  运行任务数\n     * @param failedTaskSize  失败任务数\n     * @return\n     */\n    private boolean hasSetNextBatch(int runingTaskSize, int failedTaskSize) {\n        return dcdrConcurrent > runingTaskSize && (runingTaskSize / dcdrConcurrent) == 0\n               && dcdrFaultTolerant >= failedTaskSize;\n    }\n    \n    /**\n     * 获取dcdr任务的标题\n     *\n     * @param templateIdList 模板id列表\n     * @param dcdrType       dcdr类型\n     * @return {@link String}\n     */\n    private String getDCDRTaskTitle(List<Long> templateIdList, String dcdrType) {\n        final Long templateId = templateIdList.get(0);\n        final String templateName = indexTemplateService.getNameByTemplateLogicId(\n            Math.toIntExact(templateId));\n        return templateIdList.size() == 1 ? String.format(\"%s索引模板主从%s切换\",\n            templateName, dcdrType) : String.format(\"%s等%s个索引模板主从%s切换\",\n            templateName, templateIdList.size(), dcdrType);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/expire/ExpireManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.expire;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\n\n/**\n * @author chengxiang\n * @date 2022/5/12\n */\npublic interface ExpireManager {\n\n    /**\n     * 删除过期索引\n     * @param logicTemplateId 逻辑模板id\n     * @return true/false\n     */\n    Result<Void> deleteExpireIndex(Integer logicTemplateId);\n    /////////////srv\n\n    /**\n     * 删除过期索引\n     *\n     * @param cluster 集群\n     * @return true/false\n     * @throws\n     */\n    @Deprecated\n    boolean deleteExpireIndex(String cluster);\n\n    /**\n     * 删除模板过期索引\n     *  1、可以是当前集群存在的物理模板\n     *  2、可以是已经从当前集群迁移走的模板,但是还有数据在当前集群\n     * @param physicalId 物理模板id\n     * @param retryCount 重试次数\n     * @return true/false\n     */\n    boolean deleteExpireIndices(Long physicalId, int retryCount);\n\n    /**\n     * 删除已经被删除的模板的索引\n     * @param physical 物理模板信息\n     * @param retryCount 重试次数\n     * @throws ESOperateException e\n     * @return true/false\n     */\n    boolean deleteTemplateDeletedIndices(IndexTemplatePhy physical, int retryCount) throws ESOperateException;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/expire/impl/ExpireManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.expire.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.PLATFORM_DELETED_TEMPLATE_EXPIRED_TIME;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.PLATFORM_EXPIRE_TIME_MIN;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.impl.BaseTemplateSrvImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.expire.ExpireManager;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplatePhysicalStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.IndexCatInfoCollector;\nimport com.google.common.collect.ArrayListMultimap;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Sets;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author chengxiang, zqr\n * @date 2022/5/12\n */\n@Service\npublic class ExpireManagerImpl extends BaseTemplateSrvImpl implements ExpireManager {\n\n    private final Integer         RETRY_TIMES = 3;\n\n    @Autowired\n    private ESIndexService        esIndexService;\n\n    @Autowired\n    private IndexCatInfoCollector indexCatInfoCollector;\n    @Autowired\n    private ESIndexCatService     esIndexCatService;\n\n    @Override\n    public TemplateServiceEnum templateSrv() {\n        return TemplateServiceEnum.TEMPLATE_DEL_EXPIRE;\n    }\n\n    @Override\n    public Result<Void> deleteExpireIndex(Integer logicTemplateId) {\n        if (Boolean.FALSE.equals(isTemplateSrvOpen(logicTemplateId))) {\n            return Result.buildSucc();\n        }\n        //开启dcdr后不能进行过期删除\n        if (Boolean.TRUE.equals(indexTemplateService.getLogicTemplatePOById(logicTemplateId).getHasDCDR())) {\n            return Result.buildSucc();\n        }\n\n        Boolean succ = deleteNormalTemplateExpireIndex(logicTemplateId, RETRY_TIMES)\n                       && deleteDeletingTemplateExpireIndex(logicTemplateId);\n        return succ ? Result.buildSucc() : Result.buildFail(\"删除过期索引失败\");\n    }\n\n    /////////////////////////////private method/////////////////////////////////////////////\n\n    private Boolean deleteNormalTemplateExpireIndex(Integer logicTemplateId, int retryCount) {\n        List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.getTemplateByLogicIdAndStatus(logicTemplateId,\n            TemplatePhysicalStatusEnum.NORMAL.getCode());\n        if (CollectionUtils.isEmpty(templatePhyList)) {\n            LOGGER.info(\n                \"class=ExpireManagerImpl||method=deleteNormalTemplateExpireIndex||logicTemplateId={}||msg=no physical template\",\n                logicTemplateId);\n            return Boolean.TRUE;\n        }\n\n        Multimap<String, String> cluster2ShouldDeleteIndex = ArrayListMultimap.create();\n        for (IndexTemplatePhy templatePhy : templatePhyList) {\n            try {\n                Long templatePhyId = templatePhy.getId();\n                Tuple<String, Set<String>> expireIndexTuple = getExpireIndex(templatePhyId);\n                if (null == expireIndexTuple) {\n                    LOGGER.info(\n                        \"class=ExpireManagerImpl||method=deleteNormalTemplateExpireIndex||templatePhyId={}||msg=no expire index\",\n                        templatePhyId);\n                    continue;\n                }\n\n                cluster2ShouldDeleteIndex.putAll(expireIndexTuple.getV1(), expireIndexTuple.getV2());\n            } catch (Exception e) {\n                LOGGER.warn(\n                    \"class=ExpireManagerImpl||method=deleteNormalTemplateExpireIndex||templatePhyId={}||errMsg={}\",\n                    templatePhy.getId(), e.getMessage());\n            }\n        }\n\n        if (cluster2ShouldDeleteIndex.isEmpty()) {\n            LOGGER.info(\n                \"class=ExpireManagerImpl||method=deleteNormalTemplateExpireIndex||logicTemplateId={}||msg=no expire index\",\n                logicTemplateId);\n            return Boolean.TRUE;\n        }\n\n        Boolean succ = Boolean.TRUE;\n        for (String cluster : cluster2ShouldDeleteIndex.keySet()) {\n            List<String> shouldDeleteIndexList = new ArrayList<>(cluster2ShouldDeleteIndex.get(cluster));\n            if (CollectionUtils.isEmpty(shouldDeleteIndexList)) {\n                LOGGER.info(\n                    \"class=ExpireManagerImpl||method=deleteNormalTemplateExpireIndex||cluster={}||msg=no expire index\",\n                    cluster);\n                continue;\n            }\n\n            succ = succ && esIndexService.syncBatchDeleteIndices(cluster, shouldDeleteIndexList,\n                retryCount) == shouldDeleteIndexList.size();\n            succ = succ && updateIndexFlagInvalid(cluster, shouldDeleteIndexList).success();\n        }\n        return succ;\n    }\n\n    private Boolean deleteDeletingTemplateExpireIndex(Integer logicTemplateId) {\n        List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.getTemplateByLogicIdAndStatus(logicTemplateId,\n            TemplatePhysicalStatusEnum.INDEX_DELETING.getCode());\n        if (CollectionUtils.isEmpty(templatePhyList)) {\n            LOGGER.info(\n                \"class=ExpireManagerImpl||method=deleteDeletingTemplateExpireIndex||logicTemplateId={}||msg=no deleting template\",\n                logicTemplateId);\n            return true;\n        }\n\n        Boolean succ = Boolean.TRUE;\n        IndexTemplate template = indexTemplateService.getLogicTemplateById(logicTemplateId);\n        for (IndexTemplatePhy templatePhy : templatePhyList) {\n            try {\n                if (null != template) {\n                    succ = succ && deleteTemplatePhyExpireIndex(templatePhy.getId());\n                } else {\n                    succ = succ && deleteTemplatePhyDeletedIndex(templatePhy);\n                }\n            } catch (Exception e) {\n                succ = Boolean.FALSE;\n                LOGGER.warn(\"class=ExpireManagerImpl||method=deleteDeletingTemplateExpireIndex||cluster={}||msg={}\",\n                    templatePhy.getCluster(), e.getMessage(), e);\n            }\n        }\n        return succ;\n    }\n\n    /**\n     * 获取模板过期的索引\n     * @param physicalId 模板物理ID\n     * @return <cluster, expireIndex>\n     */\n    private Tuple<String, Set<String>> getExpireIndex(Long physicalId) {\n        IndexTemplatePhyWithLogic templatePhysicalWithLogic = getNormalAndDeletingTemplateWithLogicById(physicalId);\n        if (templatePhysicalWithLogic == null) {\n            return null;\n        }\n\n        IndexTemplate logicTemplate = templatePhysicalWithLogic.getLogicTemplate();\n        int expireTime = logicTemplate.getExpireTime();\n        if (expireTime > 0 && expireTime < PLATFORM_EXPIRE_TIME_MIN) {\n            expireTime = PLATFORM_EXPIRE_TIME_MIN;\n            LOGGER.warn(\n                \"class=ExpireManagerImpl||method=getExpireIndex||msg=getExpireIndexByTemplate expire time illegal||template={}\",\n                logicTemplate.getName());\n        }\n\n        if (expireTime <= 0) {\n            if (!TemplatePhysicalStatusEnum.NORMAL\n                .equals(TemplatePhysicalStatusEnum.valueOf(templatePhysicalWithLogic.getStatus()))) {\n                // 对于已经删除的物理索引模板，我们需要重新设置其过期时间\n                expireTime = PLATFORM_DELETED_TEMPLATE_EXPIRED_TIME;\n                LOGGER.info(\n                    \"class=ExpireManagerImpl||method=getExpireIndex||msg=method=getExpireIndex||msg=reset template expire time||template={}\",\n                    logicTemplate.getName());\n            } else {\n                LOGGER.info(\n                    \"class=ExpireManagerImpl||method=getExpireIndex||msg=getExpireIndexByTemplate no expire||template={}\",\n                    logicTemplate.getName());\n                return null;\n            }\n        }\n\n        Set<String> expireIndex = templatePhyManager.getIndexByBeforeDay(templatePhysicalWithLogic, expireTime);\n        return new Tuple<>(templatePhysicalWithLogic.getCluster(), expireIndex);\n    }\n\n    /**\n     * 删除模板过期索引\n     *  1、可以是当前集群存在的物理模板\n     *  2、可以是已经从当前集群迁移走的模板,但是还有数据在当前集群\n     * @param physicalId 物理模板id\n     * @return true/false\n     */\n    private Boolean deleteTemplatePhyExpireIndex(Long physicalId) {\n        IndexTemplatePhy templatePhy = getNormalAndDeletingTemplateWithLogicById(physicalId);\n        if (templatePhy == null) {\n            return Boolean.TRUE;\n        }\n\n        Set<String> expireIndex = Optional.ofNullable(getExpireIndex(physicalId)).map(Tuple::getV2).orElse(null);\n        if (CollectionUtils.isEmpty(expireIndex)) {\n            finishDeleteIndex(physicalId);\n            return Boolean.TRUE;\n        }\n\n        Boolean succ = expireIndex.size() == esIndexService.syncBatchDeleteIndices(templatePhy.getCluster(),\n            expireIndex, RETRY_TIMES);\n        if (succ) {\n            updateIndexFlagInvalid(templatePhy.getCluster(), Lists.newArrayList(expireIndex));\n        }\n        return succ;\n    }\n\n    /**\n     * 删除已经被删除的模板的索引\n     * @param physical 物理模板信息\n     * @return true/false\n     */\n    private Boolean deleteTemplatePhyDeletedIndex(IndexTemplatePhy physical) {\n        if (!isTemplateSrvOpen(physical.getLogicId())) {\n            return Boolean.FALSE;\n        }\n\n        List<IndexTemplatePhyPO> physicalPOs = indexTemplatePhyService.getByClusterAndNameAndStatus(\n            physical.getCluster(), physical.getName(), TemplatePhysicalStatusEnum.NORMAL.getCode());\n\n        //如果还有正常状态的物理模板存在，那就把非正常状态的物理模板给清理掉\n        if (CollectionUtils.isNotEmpty(physicalPOs)) {\n            deleteTemplateNuNormalStatusFromDB(physical);\n            return Boolean.TRUE;\n        }\n        physicalPOs.addAll(indexTemplatePhyService.getByClusterAndStatus(physical.getCluster(),\n            TemplatePhysicalStatusEnum.INDEX_DELETING.getCode()));\n\n        // 0：noConflict\n        // 1：hasConflict\n        // 2：reCreate\n        int deleteCode = 0;\n        for (IndexTemplatePhyPO po : physicalPOs) {\n            if (po.getId().equals(physical.getId())) {\n                continue;\n            }\n\n            if (physical.getExpression().equals(po.getExpression())) {\n                deleteCode = 2;\n                break;\n            }\n\n            String expressionPre = physical.getExpression().replace(\"*\", \"\");\n            if (po.getExpression().startsWith(expressionPre)) {\n                LOGGER.info(\n                    \"class=ExpireManagerImpl||method=deleteTemplateDeletedIndices||msg=processLogicDeleted hasConflict||deletedTemplate={}||conflictTemplate={}\",\n                    physical.getName(), po.getName());\n                deleteCode = 1;\n                break;\n            }\n        }\n\n        if (deleteCode == 1) {\n            LOGGER.warn(\n                \"class=ExpireManagerImpl||method=deleteTemplateDeletedIndices||msg=processLogicDeleted has conflict||deletedTemplate={}||expression={}\",\n                physical.getName(), physical.getExpression());\n            return false;\n        }\n\n        Boolean succ = Boolean.TRUE;\n        if (deleteCode == 0) {\n            LOGGER.info(\n                \"class=ExpireManagerImpl||method=deleteTemplateDeletedIndices||msg=processLogicDeleted no conflict and not reCreate||deletedTemplate={}||expression={}\",\n                physical.getName(), physical.getExpression());\n            Set<String> shouldDelSet = esIndexService.syncGetIndexNameByExpression(physical.getCluster(),\n                physical.getExpression());\n            if (CollectionUtils.isNotEmpty(shouldDelSet)) {\n                try {\n                    succ = esIndexService.syncDeleteIndexByExpression(physical.getCluster(), physical.getExpression(),\n                        RETRY_TIMES);\n                } catch (Exception e) {\n                    LOGGER.error(\n                        \"class=ExpireManagerImpl||method=deleteTemplateDeletedIndices||msg=processLogicDeleted delete index error||deletedTemplate={}||expression={}\",\n                        physical.getName(), physical.getExpression(), e);\n                    succ = Boolean.FALSE;\n                }\n                if (succ) {\n                    //批量设置存储索引cat/index信息的元数据索引中的文档标志位（deleteFlag）为true\n                    updateIndexFlagInvalid(physical.getCluster(), Lists.newArrayList(shouldDelSet));\n                }\n            }\n        }\n\n        if (succ) {\n            //修改模板的状态为已删除\n            finishDeleteIndex(physical.getId());\n        }\n        return succ;\n    }\n\n    private Result<Boolean> updateIndexFlagInvalid(String cluster, List<String> indexNameList) {\n        //不采集已删除索引\n        indexCatInfoCollector.updateNotCollectorIndexNames(cluster, indexNameList);\n        //更新存储cat/index信息的元信息索引中对应文档删除标识位为true\n        boolean succ = indexNameList.size() == esIndexCatService.syncUpdateCatIndexDeleteFlag(cluster, indexNameList,\n            3);\n        if (!succ) {\n            LOGGER.error(\n                \"class=ExpireManagerImpl||method=batchSetIndexFlagInvalid||cluster={}||indexNameList={}||errMsg=failed to batchSetIndexFlagInvalid\",\n                cluster, ListUtils.strList2String(indexNameList));\n        }\n        return Result.build(succ);\n    }\n\n    private boolean deleteTemplateNuNormalStatusFromDB(IndexTemplatePhy physical) {\n        return indexTemplatePhyService.deleteDirtyByClusterAndName(physical.getCluster(), physical.getName());\n    }\n\n    /**\n     * 模板数据删除完成\n     * @param physicalId 物理模板id\n     * @return true、false\n     */\n    private boolean finishDeleteIndex(Long physicalId) {\n        return indexTemplatePhyService.updateStatus(physicalId, TemplatePhysicalStatusEnum.DELETED.getCode());\n    }\n\n    private IndexTemplatePhyWithLogic getNormalAndDeletingTemplateWithLogicById(Long physicalId) {\n        return indexTemplatePhyService.buildIndexTemplatePhysicalWithLogicByPhysicalId(physicalId);\n    }\n    ///////////////////////////////////////////srv\n\n    /**\n     * 删除模板过期索引\n     * 1、可以是当前集群存在的物理模板\n     * 2、可以是已经从当前集群迁移走的模板,但是还有数据在当前集群\n     *\n     * @param physicalId 物理模板id\n     * @param retryCount 重试次数\n     * @return true/false\n     */\n    @Override\n    public boolean deleteExpireIndices(Long physicalId, int retryCount) {\n        IndexTemplatePhy templatePhysical = getNormalAndDeletingTemplateWithLogicById(physicalId);\n        if (templatePhysical == null) {\n            return true;\n        }\n\n        Set<String> shouldDels = Optional.ofNullable(getExpireIndex(physicalId)).map(Tuple::getV2)\n            .orElse(Sets.newHashSet());\n\n        LOGGER.error(\"class=ExpireManagerImpl||method=deleteExpireIndices||physicalId={}||logicId={}||status={}\"\n                     + \"||name={}||shouldDeleteIndices={}\",\n            physicalId, templatePhysical.getLogicId(), templatePhysical.getStatus(), templatePhysical.getName(),\n            JSON.toJSONString(shouldDels));\n\n        if (CollectionUtils.isEmpty(shouldDels)) {\n            if (templatePhysical.getStatus().equals(TemplatePhysicalStatusEnum.INDEX_DELETING.getCode())) {\n                finishDeleteIndex(physicalId);\n            }\n            return true;\n        }\n\n        boolean succ = shouldDels.size() == esIndexService.syncBatchDeleteIndices(templatePhysical.getCluster(),\n            shouldDels, retryCount);\n\n        if (succ) {\n            updateIndexFlagInvalid(templatePhysical.getCluster(), Lists.newArrayList(shouldDels));\n        }\n\n        return succ;\n    }\n\n    /**\n     * 删除已经被删除的模板的索引\n     *\n     * @param physical   物理模板信息\n     * @param retryCount 重试次数\n     * @return true/false\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean deleteTemplateDeletedIndices(IndexTemplatePhy physical, int retryCount) throws ESOperateException {\n        if (!isTemplateSrvOpen(physical.getLogicId())) {\n            return false;\n        }\n\n        List<IndexTemplatePhyPO> physicalPOs =\n\n                indexTemplatePhyService.getByClusterAndNameAndStatus(physical.getCluster(), physical.getName(),\n                    TemplatePhysicalStatusEnum.NORMAL.getCode());\n\n        //如果还有正常状态的物理模板存在，那就把非正常状态的物理模板给清理掉\n        if (CollectionUtils.isNotEmpty(physicalPOs)) {\n            deleteTemplateNuNormalStatusFromDB(physical);\n            return true;\n        }\n\n        physicalPOs.addAll(indexTemplatePhyService.getByClusterAndStatus(physical.getCluster(),\n            TemplatePhysicalStatusEnum.INDEX_DELETING.getCode()));\n\n        // 0：noConflict\n        // 1：hasConflict\n        // 2：reCreate\n        int deleteCode = 0;\n        for (IndexTemplatePhyPO po : physicalPOs) {\n            if (po.getId().equals(physical.getId())) {\n                continue;\n            }\n\n            if (physical.getExpression().equals(po.getExpression())) {\n                deleteCode = 2;\n                break;\n            }\n\n            String expressionPre = physical.getExpression().replace(\"*\", \"\");\n            if (po.getExpression().startsWith(expressionPre)) {\n                LOGGER.info(\n                    \"class=BaseTemplateSrv||method=deleteTemplateDeletedIndices||msg=processLogicDeleted hasConflict||deletedTemplate={}||conflictTemplate={}\",\n                    physical.getName(), po.getName());\n                deleteCode = 1;\n                break;\n            }\n        }\n\n        if (deleteCode == 1) {\n            LOGGER.warn(\n                \"class=BaseTemplateSrv||method=deleteTemplateDeletedIndices||msg=processLogicDeleted has conflict||deletedTemplate={}||expression={}\",\n                physical.getName(), physical.getExpression());\n            return false;\n        }\n\n        boolean succ = true;\n        if (deleteCode == 0) {\n            LOGGER.info(\n                \"class=BaseTemplateSrv||method=deleteTemplateDeletedIndices||msg=processLogicDeleted no conflict and not reCreate||deletedTemplate={}||expression={}\",\n                physical.getName(), physical.getExpression());\n            Set<String> shouldDelSet = esIndexService.syncGetIndexNameByExpression(physical.getCluster(),\n                physical.getExpression());\n            if (CollectionUtils.isNotEmpty(shouldDelSet)) {\n                succ = esIndexService.syncDeleteIndexByExpression(physical.getCluster(), physical.getExpression(),\n                    retryCount);\n                if (succ) {\n                    //批量设置存储索引cat/index信息的元数据索引中的文档标志位（deleteFlag）为true\n                    updateIndexFlagInvalid(physical.getCluster(), Lists.newArrayList(shouldDelSet));\n                }\n            }\n        }\n\n        if (succ) {\n            //修改模板的状态为已删除\n            finishDeleteIndex(physical.getId());\n        }\n\n        return succ;\n    }\n\n    /**\n     * @param cluster 集群\n     * @return\n     */\n    @Override\n    public boolean deleteExpireIndex(String cluster) {\n       \n\n        int retryCount = 5;\n        return deleteNormalTemplateExpireIndexByCluster(cluster, retryCount)\n               && deleteDeletingTemplateExpireIndexByCluster(cluster, retryCount);\n    }\n\n    /**************************************** private method ****************************************************/\n\n    private boolean deleteNormalTemplateExpireIndexByCluster(String cluster, int retryCount) {\n        List<IndexTemplatePhy> templatePhysicals = indexTemplatePhyService.getTemplateByClusterAndStatus(cluster,\n            TemplatePhysicalStatusEnum.NORMAL.getCode());\n        if (CollectionUtils.isEmpty(templatePhysicals)) {\n            LOGGER.info(\n                \"class=ESClusterPhyServiceImpl||method=deleteNormalTemplateExpireIndex||cluster={}||msg=cluster no template\",\n                cluster);\n            return true;\n        }\n\n        Set<String> shouldDels = Sets.newHashSet();\n        for (IndexTemplatePhy templatePhysical : templatePhysicals) {\n            //集群移动到模版侧\n            if (Boolean.FALSE.equals(isTemplateSrvOpen(templatePhysical.getLogicId()))){\n                continue;\n            }\n            try {\n                shouldDels.addAll(getExpireIndexByPhysicalId(templatePhysical.getId()));\n            } catch (Exception e) {\n                LOGGER.warn(\n                    \"class=ESClusterPhyServiceImpl||method=deleteNormalTemplateExpireIndex||cluster={}||errMsg={}\",\n                    cluster, e.getMessage());\n            }\n        }\n\n        if (CollectionUtils.isEmpty(shouldDels)) {\n            LOGGER.info(\n                \"class=ESClusterPhyServiceImpl||method=deleteNormalTemplateExpireIndex||cluster={}||msg=no expire index\",\n                cluster);\n            return true;\n        }\n\n        boolean succ = esIndexService.syncBatchDeleteIndices(cluster, shouldDels, retryCount) == shouldDels.size();\n        if (succ) {\n            List<String> shouldDelList = Lists.newArrayList(shouldDels);\n            Result<Boolean> batchSetIndexFlagInvalidResult = updateIndexFlagInvalid(cluster, shouldDelList);\n            if (batchSetIndexFlagInvalidResult.success()) {\n                operateRecordService.saveOperateRecordWithSchedulingTasks(\n                        String.format(\"根据模板过期时间删除过期索引：集群%s;索引:%s\", cluster, ListUtils.strList2String(shouldDelList)),\n                        AriusUser.SYSTEM.getDesc(),AuthConstant.SUPER_PROJECT_ID,cluster,OperateTypeEnum.INDEX_MANAGEMENT_DELETE);\n\n            }\n        }\n\n        return succ;\n    }\n\n    public Set<String> getExpireIndexByPhysicalId(Long physicalId) {\n\n        IndexTemplatePhyWithLogic templatePhysicalWithLogic = getNormalAndDeletingTemplateWithLogicById(physicalId);\n        if (templatePhysicalWithLogic == null) {\n            return Sets.newHashSet();\n        }\n\n        IndexTemplate logicTemplate = templatePhysicalWithLogic.getLogicTemplate();\n\n        int expireTime = logicTemplate.getExpireTime();\n\n        if (expireTime > 0 && expireTime < PLATFORM_EXPIRE_TIME_MIN) {\n            expireTime = PLATFORM_EXPIRE_TIME_MIN;\n            LOGGER.warn(\n                \"class=BaseTemplateSrv||method= getExpireIndex||msg=getExpireIndexByTemplate expire time illegal||template={}\",\n                logicTemplate.getName());\n        }\n\n        if (expireTime <= 0) {\n            if (!TemplatePhysicalStatusEnum.NORMAL\n                .equals(TemplatePhysicalStatusEnum.valueOf(templatePhysicalWithLogic.getStatus()))) {\n                // 对于已经删除的物理索引模板，我们需要重新设置其过期时间\n                expireTime = PLATFORM_DELETED_TEMPLATE_EXPIRED_TIME;\n\n                LOGGER.info(\n                    \"class=BaseTemplateSrv||method= getExpireIndex||msg=method=getExpireIndex||msg=reset template expire time||template={}\",\n                    logicTemplate.getName());\n            } else {\n                LOGGER.info(\n                    \"class=BaseTemplateSrv||method= getExpireIndex||msg=getExpireIndexByTemplate no expire||template={}\",\n                    logicTemplate.getName());\n                return Sets.newHashSet();\n            }\n\n        }\n\n        return templatePhyManager.getIndexByBeforeDay(templatePhysicalWithLogic, expireTime);\n    }\n\n    private boolean deleteDeletingTemplateExpireIndexByCluster(String cluster, int retryCount) {\n        List<IndexTemplatePhy> templatePhysicals = indexTemplatePhyService.getTemplateByClusterAndStatus(cluster,\n            TemplatePhysicalStatusEnum.INDEX_DELETING.getCode());\n        if (CollectionUtils.isEmpty(templatePhysicals)) {\n            LOGGER.info(\n                \"class=ESClusterPhyServiceImpl||method=deleteDeletingTemplateExpireIndex||cluster={}||msg=cluster no deleting template\",\n                cluster);\n            return true;\n        }\n\n        boolean succ = true;\n        for (IndexTemplatePhy physical : templatePhysicals) {\n            //没有开启就跳过\n            if (Boolean.FALSE.equals(isTemplateSrvOpen(physical.getLogicId()))){\n                continue;\n            }\n            try {\n                IndexTemplate templateLogic = indexTemplateService\n                    .getLogicTemplateWithPhysicalsById(physical.getLogicId());\n                \n                if (templateLogic != null) {\n                    succ = deleteExpireIndices(physical.getId(), retryCount) && succ;\n                } else {\n                    succ = deleteTemplateDeletedIndices(physical, retryCount) && succ;\n                }\n            } catch (Exception e) {\n                succ = false;\n                LOGGER.warn(\n                    \"class=ESClusterPhyServiceImpl||method=deleteDeletingTemplateExpireIndex||template={}||msg={}\",\n                    physical.getName(), e.getMessage(), e);\n            }\n\n        }\n\n        if (succ) {\n            List<String> indexTemplatePhyNameList = templatePhysicals.stream().map(IndexTemplatePhy::getName)\n                .collect(Collectors.toList());\n            operateRecordService.saveOperateRecordWithSchedulingTasks(\n                    String.format(\"删除已删除模板关联的索引：集群 %s; 模板 %s\", cluster,\n                            ListUtils.strList2String(indexTemplatePhyNameList)), AriusUser.SYSTEM.getDesc(),\n                    AuthConstant.SUPER_PROJECT_ID, cluster, OperateTypeEnum.INDEX_MANAGEMENT_DELETE);\n\n        }\n\n        return succ;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/indexplan/IndexPlanManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.indexplan;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplatePhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\n\n/**\n * @author chengxiang, jiamin\n * @date 2022/5/11\n */\npublic interface IndexPlanManager {\n\n    /**\n     * indexRollover能力\n     * 获取当天的索引主分片占用磁盘容量大小\n     * 如果小于主shardCnt*30G，则不进行升级版本\n     * 如果大于主shardCnt*50G，则直接升级版本\n     * 如果超过了过去7天索引大小的最大值，则升级版本\n     * @param logicTemplateId 逻辑模板id\n     * @return Result 是否成功\n     */\n    Result<Void> indexRollover(Integer logicTemplateId);\n\n    /**\n     * 调整索引模版的shard个数配置\n     *\n     * @param logicTemplateId 逻辑模板id\n     * @return Result 是否成功\n     */\n    Result<Boolean> adjustShardNum(Integer logicTemplateId) throws ESOperateException;\n\n    /**\n     * 根据shard设置ShardRouting，再把shard调整到合适大小\n     * @param param IndexTemplatePhyDTO\n     */\n    void initShardRoutingAndAdjustShard(IndexTemplatePhyDTO param);\n\n    /////////////////////////SRV\n\n    /**\n     * indexRollover能力\n     * 根据该物理集群下，获取当天的索引主分片占用磁盘容量大小\n     * 如果小于主shardCnt*30G，则不进行升级版本\n     * 如果大于主shardCnt*50G，则直接升级版本\n     * 如果超过了过去7天索引大小的最大值，则升级版本\n     * @param clusterPhyName 物理集群名\n     * @return boolean\n     */\n    @Deprecated\n    boolean indexRollover(String clusterPhyName);\n\n    /**\n     * 调整物理集群下，索引模版的shard个数配置\n     * @param phyClusterName 物理集群名\n     * @return boolean 是否成功\n     */\n    Result<Void> adjustShardCountByPhyClusterName(String phyClusterName);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/indexplan/impl/IndexPlanManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.indexplan.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.BYTE_TO_G;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.G_PER_SHARD;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.impl.BaseTemplateSrvImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.indexplan.IndexPlanManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplatePhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplatePhysicalUpgradeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.stats.IndexNodes;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Multimap;\n\n/**\n * @author chengxiang, jiamin\n * @date 2022/5/11\n */\n@Service(\"newIndexPlanManagerImpl\")\npublic class IndexPlanManagerImpl extends BaseTemplateSrvImpl implements IndexPlanManager {\n\n    private final static Integer  SINGLE_SHARD_MAX_SIZE       = 50;\n    private final static Integer  SINGLE_SHARD_RECOMMEND_SIZE = 30;\n\n    /**\n     * (key, value) = (模板id, 该模版对应索引近七天某一天占用磁盘容量最大值)\n     */\n    private final Map<Long, Long> indexMaxStoreMap            = Maps.newConcurrentMap();\n\n    @Autowired\n    private AriusConfigInfoService ariusConfigInfoService;\n\n    @Autowired\n    private ESIndexService        esIndexService;\n\n    @Override\n    public TemplateServiceEnum templateSrv() {\n        return TemplateServiceEnum.INDEX_PLAN;\n    }\n\n    @Override\n    public Result<Void> indexRollover(Integer logicTemplateId) {\n        LOGGER.info(\"class=IndexPlanManagerImpl||method=indexRollover||logicTemplateId={}||msg=start indexRollover\",\n            logicTemplateId);\n        if (!isTemplateSrvOpen(logicTemplateId)) {\n            return Result.buildSucc();\n        }\n\n        List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.getTemplateByLogicId(logicTemplateId);\n        if (CollectionUtils.isEmpty(templatePhyList)) {\n            LOGGER.info(\n                \"class=IndexPlanManagerImpl||method=indexRollover||logicTemplateId={}||msg=IndexRolloverTask no physical template\",\n                logicTemplateId);\n            return Result.buildSucc();\n        }\n\n        IndexTemplate template = indexTemplateService.getLogicTemplateById(logicTemplateId);\n        for (IndexTemplatePhy templatePhy : templatePhyList) {\n            String phyClusterName = templatePhy.getCluster();\n            // 根据索引分区规则，获取当天或当月或不分区带有版本信息的索引的名字\n            String indexName = getIndexNameByDateFormat(template, templatePhy);\n\n            // 获取indexNodes信息（该索引对应的元信息）\n            IndexNodes indexNodes = getIndexNodes(indexName, phyClusterName);\n\n            // 获取索引的主shard个数，这里不能直接从数据库获取，因为可能会被改变，所以从ES中获取\n            Integer primaryShardCnt = esIndexService.syncGetIndexPrimaryShardNumber(phyClusterName, indexName);\n            if (primaryShardCnt == null || indexNodes == null) {\n                continue;\n            }\n\n            // 当天最高版本的索引占用磁盘的容量\n            long curSizeInBytes = indexNodes.getPrimaries().getStore().getSizeInBytes();\n            double curSizeInGb = curSizeInBytes * BYTE_TO_G;\n\n            double rolloverThreshold = ariusConfigInfoService.doubleSetting(AriusConfigConstant.ARIUS_COMMON_GROUP,\n                    AriusConfigConstant.INDEX_ROLLOVER_THRESHOLD, 50.0);\n\n            if (curSizeInGb >= primaryShardCnt * rolloverThreshold) {\n                // 如果大于（主shard个数 * 推荐的单个shard大小50G），直接升版本\n                updateTemplateVersion(templatePhy);\n            } else if (curSizeInGb >= primaryShardCnt * SINGLE_SHARD_RECOMMEND_SIZE\n                       && TemplateUtils.isSaveByDay(template.getDateFormat())) {\n                // 如果大于（主shard个数 * 推荐的单个shard大小30G），并且索引模版是按天创建索引\n                // 获取该索引模版对应索引近7天占用磁盘的最大值\n                Long sizeInBytesMax = getMaxStoreInRecentSevenDayByTemplatePhyId(templatePhy.getId());\n                // 比较两者大小，大于则升版本\n                if (curSizeInBytes > sizeInBytesMax) {\n                    updateTemplateVersion(templatePhy);\n                }\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Boolean> adjustShardNum(Integer logicTemplateId) throws ESOperateException {\n        LOGGER.info(\n            \"class=IndexPlanManagerImpl||method=adjustShardCount||logicTemplateId={}||msg=start adjustShardCount\",\n            logicTemplateId);\n        if (!isTemplateSrvOpen(logicTemplateId)) {\n            return Result.buildSucc();\n        }\n\n        List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.getTemplateByLogicId(logicTemplateId);\n        if (CollectionUtils.isEmpty(templatePhyList)) {\n            LOGGER.info(\n                \"class=IndexPlanManagerImpl||method=adjustShardCount||logicTemplateId={}||msg=IndexRolloverTask no physical template\",\n                logicTemplateId);\n            return Result.build(Boolean.TRUE);\n        }\n\n        governPerTemplate(templatePhyList);\n          return Result.build(Boolean.TRUE);\n    }\n\n    @Override\n    public void initShardRoutingAndAdjustShard(IndexTemplatePhyDTO param) {\n        int shard = param.getShard();\n        if (shard >= 320) {\n            param.setShardRouting(32);\n            param.setShard(calculateShardByShardRouting(shard, 32));\n        } else if (shard >= 80) {\n            param.setShardRouting(16);\n            param.setShard(calculateShardByShardRouting(shard, 16));\n        } else if (shard >= 16) {\n            param.setShardRouting(8);\n            param.setShard(calculateShardByShardRouting(shard, 8));\n        } else if (shard >= 4) {\n            param.setShardRouting(4);\n            param.setShard(calculateShardByShardRouting(shard, 4));\n        } else {\n            param.setShardRouting(1);\n        }\n    }\n\n    //////////private method/////////////////////////////////////////////////////////////\n\n    private String getIndexNameByDateFormat(IndexTemplate logiTemplate, IndexTemplatePhy phyTemplate) {\n        if (TemplateUtils.isSaveByDay(logiTemplate.getDateFormat())) {\n            // 按天分区则获取模版对应当天索引拼接版本信息\n            return IndexNameUtils.genDailyIndexNameWithVersion(phyTemplate.getName(), 0, phyTemplate.getVersion());\n        } else if (TemplateUtils.isSaveByMonth(logiTemplate.getDateFormat())) {\n            // 按月分区则获取模版对应当月索引拼接版本信息\n            return IndexNameUtils.genCurrentMonthlyIndexNameWithVersion(phyTemplate.getName(),\n                phyTemplate.getVersion());\n        } else {\n            // 不分区则模版名拼接版本信息\n            return IndexNameUtils.genIndexNameWithVersion(phyTemplate.getName(), phyTemplate.getVersion());\n        }\n    }\n\n    /**\n     * @param indexName 索引名字\n     * @param clusterPhyName 物理集群名\n     * @return IndexNodes 索引的元信息\n     */\n    private IndexNodes getIndexNodes(String indexName, String clusterPhyName) {\n        // 获取该索引模版对应索引当天占用磁盘的大小\n        Map<String, IndexNodes> indexNodeMap = esIndexService.syncGetIndexNodes(clusterPhyName, indexName);\n        if (indexNodeMap == null || indexNodeMap.size() == 0) {\n            LOGGER.warn(\"class=IndexPlanManagerImpl||method=getIndexNodes||index={}||errMsg={}\", indexName,\n                \"获取不到该索引的IndexNodes（元数据）信息，索引也许不存在\");\n            return null;\n        }\n        return indexNodeMap.get(indexName);\n    }\n\n    private void updateTemplateVersion(IndexTemplatePhy templatePhy) {\n        TemplatePhysicalUpgradeDTO param = new TemplatePhysicalUpgradeDTO();\n        param.setVersion(templatePhy.getVersion() + 1);\n        param.setPhysicalId(templatePhy.getId());\n\n        try {\n            Result<Void> result = templatePhyManager.rolloverUpgradeTemplate(param, AriusUser.CAPACITY_PLAN.getDesc());\n            if (result.failed()) {\n                throw new ESOperateException(result.getMessage());\n            }\n            LOGGER.info(\"class=IndexPlanManagerImpl||method=updateTemplateVersion||template={}||upgradeResult={}\",\n                templatePhy.getId(), result);\n        } catch (ESOperateException e) {\n            LOGGER.warn(\"class=IndexPlanManagerImpl||method=updateTemplateVersion||template={}||errMsg={}\",\n                templatePhy.getId(), e);\n        }\n    }\n\n    private Long getMaxStoreInRecentSevenDayByTemplatePhyId(Long templatePhyId) {\n        IndexTemplatePhy templatePhy = indexTemplatePhyService.getTemplateById(templatePhyId);\n        if (templatePhy == null) {\n            // 该模版不存在\n            return 0L;\n        }\n        // 如果templatePhyId不存在map，则调用getSizeInBytesMax，再把结果放入map\n        return indexMaxStoreMap.computeIfAbsent(templatePhyId, x -> getSizeInBytesMax(templatePhy));\n    }\n\n    /**\n     * 获取该索引模版对应索引近七天某一天占用磁盘容量最大值\n     * @param templatePhy 物理模版\n     * @return 该索引模版对应索引近七天某一天占用磁盘容量最大值\n     */\n    private long getSizeInBytesMax(IndexTemplatePhy templatePhy) {\n        // 获取上一天起一周内的索引名称，今天是10-22，则获取10-15~10-21时间\n        long lastWeekDayTimestamp = AriusDateUtils.getBeforeDays(new Date(), 6).getTime();\n        long yesterdayTimestamp = AriusDateUtils.getBeforeDays(new Date(), 1).getTime();\n        String indexNames = IndexNameUtils.genDailyIndexName(templatePhy.getName(), lastWeekDayTimestamp,\n            yesterdayTimestamp);\n        String[] indexNameSplits = indexNames.split(\",\");\n\n        List<String> indexNameList = Lists.newArrayList();\n        Map<String/*不包括版本的索引名字*/, Long/*索引占用磁盘的大小*/> indexStoreSizeInBytesMap = Maps.newHashMap();\n        for (String indexName : indexNameSplits) {\n            // 当天某个索引，可能有多个版本（xxx-2021-10-10、xxx-2021-10-10-v2），所以用*来匹配\n            indexNameList.add(indexName + \"*\");\n            indexStoreSizeInBytesMap.put(indexName, 0L);\n        }\n\n        // 获取索引的stats信息\n        Map<String, IndexNodes> indexNodeMap = esIndexService.syncGetIndexNodes(templatePhy.getCluster(),\n            StringUtils.join(indexNameList, \",\"));\n\n        if (indexNodeMap == null || indexNodeMap.isEmpty()) {\n            return 0;\n        }\n\n        long sizeInBytesMax = 0;\n        for (Map.Entry<String, IndexNodes> entry : indexNodeMap.entrySet()) {\n            // 移除索引的版本信息（如果有版本信息的话）\n            String indexNameNoVersion = IndexNameUtils.removeVersion(entry.getKey());\n            // 获取索引主分片占用磁盘大小\n            long indexSizeInBytes = entry.getValue().getPrimaries().getStore().getSizeInBytes();\n            // 当天某个索引，可能有多个版本（xxx-2021-10-10、xxx-2021-10-10-v2），所以要进行累加\n            long indexSizeInBytesTotalOfDay = indexStoreSizeInBytesMap.get(indexNameNoVersion);\n            indexSizeInBytesTotalOfDay += indexSizeInBytes;\n            indexStoreSizeInBytesMap.put(indexNameNoVersion, indexSizeInBytesTotalOfDay);\n            if (indexSizeInBytesTotalOfDay > sizeInBytesMax) {\n                sizeInBytesMax = indexSizeInBytesTotalOfDay;\n            }\n        }\n        return sizeInBytesMax;\n    }\n\n    private void governPerTemplate(Collection<IndexTemplatePhy> templatePhyList) throws ESOperateException {\n        // 就一个模板 直接改\n        if (templatePhyList.size() == 1) {\n            List<IndexTemplatePhy> list = Lists.newArrayList(templatePhyList);\n            Result<String> result = adjustShardCount(list.get(0));\n            if (result.failed()) {\n                LOGGER.warn(\n                    \"class=IndexPlanManagerImpl||method=governPerTemplate||template={}||msg=adjust shard count fail={}\",\n                    list.get(0).getName(), result.getMessage());\n            }\n            return;\n        }\n\n        // 先改主再改从\n        List<IndexTemplatePhy> masterTemplatePhyList = templatePhyList.stream()\n            // 只保留主角色的物理模版\n            .filter(x -> x.getRole().equals(TemplateDeployRoleEnum.MASTER.getCode())).collect(Collectors.toList());\n\n        if (masterTemplatePhyList.isEmpty()) {\n            return;\n        }\n\n        for (IndexTemplatePhy masterTemplatePhy : masterTemplatePhyList) {\n            // 修改主\n            Result<String> masterResult = adjustShardCount(masterTemplatePhy);\n            if (masterResult.failed()) {\n                LOGGER.warn(\n                    \"class=IndexPlanManagerImpl||method=governPerTemplate||masterTemplate={}||msg=adjust shard count fail={}\",\n                    masterTemplatePhy.getName(), masterResult.getMessage());\n                return;\n            }\n\n            // 获取从物理模版\n            List<IndexTemplatePhy> slaveTemplatePhyList = templatePhyList.stream()\n                // 只保留从角色的物理模版\n                .filter(x -> x.getRole().equals(TemplateDeployRoleEnum.SLAVE.getCode())).collect(Collectors.toList());\n\n            for (IndexTemplatePhy slaveTemplatePhy : slaveTemplatePhyList) {\n                // 修改从\n                Result<String> slaveResult = adjustShardCount(slaveTemplatePhy);\n                if (slaveResult.failed()) {\n                    LOGGER.warn(\n                        \"class=IndexPlanManagerImpl||method=governPerTemplate||slaveTemplate={}||msg=adjust shard count fail={}\",\n                        masterTemplatePhy.getName(), masterResult.getMessage());\n                }\n            }\n        }\n    }\n\n    /**\n     * shard个数调整\n     * 非按天滚动，无需调整主shard个数\n     * @param templatePhy 物理模版\n     * @return result 结果\n     * @throws ESOperateException e\n     */\n    private Result<String> adjustShardCount(IndexTemplatePhy templatePhy) throws ESOperateException {\n        IndexTemplate logicTemplate = indexTemplateService.getLogicTemplateById(templatePhy.getLogicId());\n        if (!TemplateUtils.isSaveByDay(logicTemplate.getDateFormat())) {\n            // 非按天滚动，无需调整主shard个数\n            return Result.buildSucc();\n        }\n        int shardCount = calculateShardCount(templatePhy);\n        if (shardCount < 1) {\n            return Result.buildFail(\"计算shard个数失败\");\n        }\n\n        if (templatePhy.getShard() != shardCount) {\n            // 不等于old的shard，则可能是缩shard、或扩shard\n            Result<Void> result = editTemplateWithoutCheck(templatePhy, shardCount, AriusUser.CAPACITY_PLAN.getDesc());\n            if (result.success()) {\n                LOGGER.info(\"class=IndexPlanManagerImpl||method=adjustShardCount||template={}||shardCount={}->{}\",\n                    templatePhy.getName(), templatePhy.getShard(), shardCount);\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    private int calculateShardCount(IndexTemplatePhy templatePhy) {\n        long sizeInBytesMax = getSizeInBytesMax(templatePhy);\n        // 放进缓存（主要提供给IndexRolloverTask功能作数据参考）\n        indexMaxStoreMap.put(templatePhy.getId(), sizeInBytesMax);\n        return (int) (sizeInBytesMax * BYTE_TO_G / G_PER_SHARD) + 1;\n    }\n\n    private Result<Void> editTemplateWithoutCheck(IndexTemplatePhy templatePhy, Integer shardNum,\n                                                  String operator) throws ESOperateException {\n        // 计算 ShardRouting，并通过 ShardRouting 再计算 shard\n        IndexTemplatePhyDTO param = new IndexTemplatePhyDTO();\n        param.setShard(templatePhy.getShard());\n        param.setShardRouting(templatePhy.getShardRouting());\n        initShardRoutingAndAdjustShard(param);\n        templatePhy.setShard(param.getShard());\n        templatePhy.setShardRouting(param.getShardRouting());\n\n        // 获取明天的索引名\n        String indexName = IndexNameUtils.genDailyIndexNameWithVersion(templatePhy.getName(), -1,\n            templatePhy.getVersion());\n        if (esIndexService.syncIsIndexExist(templatePhy.getCluster(), indexName)) {\n            // 如果明天的索引已经存在，则删除\n            List<String> indexNameList = new ArrayList<>();\n            indexNameList.add(indexName);\n            esIndexService.syncBatchDeleteIndices(templatePhy.getCluster(), indexNameList, 1);\n        }\n\n        // 更新\n        return indexTemplatePhyService.updateTemplateShardNum(templatePhy, shardNum, operator);\n    }\n\n    private Integer calculateShardByShardRouting(int shard, int shardRouting) {\n        if (shard % shardRouting == 0) {\n            return shard;\n        }\n        return (shard / shardRouting + 1) * shardRouting;\n    }\n\n    /////////////////////////SRV\n    @Override\n    public boolean indexRollover(String phyClusterName) {\n        LOGGER.info(\"class=CapacityPlanManagerImpl||method=indexRollover||cluster={}||msg=start indexRollover\",\n            phyClusterName);\n        // 判断指定物理集群是否开启了当前索引服务\n        //if (!isTemplateSrvOpen(phyClusterName)) {\n        //    return false;\n        //}\n\n        // 获取所有的索引物理模版\n        List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.getNormalTemplateByCluster(phyClusterName);\n        if (CollectionUtils.isEmpty(templatePhyList)) {\n            LOGGER.info(\n                \"class=CapacityPlanManagerImpl||method=indexRollover||cluster={}||msg=IndexRolloverTask no template\",\n                phyClusterName);\n            return true;\n        }\n\n        for (IndexTemplatePhy phyTemplate : templatePhyList) {\n            // 判断该索引模版是否开启当前索引服务\n            IndexTemplateConfig config = indexTemplateService.getTemplateConfig(phyTemplate.getLogicId());\n            \n            if (config == null || config.getDisableIndexRollover()) {\n                LOGGER.info(\n                    \"class=CapacityPlanManagerImpl||method=indexRollover||cluster={}||template={}||msg=skip indexRollover\",\n                    phyClusterName, phyTemplate.getName());\n                continue;\n            }\n            //判断集群的模版是否开启了索引规划rollover\n            if (!isTemplateSrvOpen(phyTemplate.getLogicId())){\n                continue;\n            }\n            // 获取逻辑模版信息\n            IndexTemplate logiTemplate = indexTemplateService.getLogicTemplateById(phyTemplate.getLogicId());\n\n            // 根据索引分区规则，获取当天或当月或不分区带有版本信息的索引的名字\n            String indexName = getIndexNameByDateFormat(logiTemplate, phyTemplate);\n\n            // 获取indexNodes信息（该索引对应的元信息）\n            IndexNodes indexNodes = getIndexNodes(indexName, phyClusterName);\n            // 获取索引的主shard个数，这里不能直接从数据库获取，因为可能会被改变，所以从ES中获取\n            Integer primaryShardCnt = esIndexService.syncGetIndexPrimaryShardNumber(phyClusterName, indexName);\n            if (primaryShardCnt == null || indexNodes == null) {\n                continue;\n            }\n\n            // 当天最高版本的索引占用磁盘的容量\n            long curSizeInBytes = indexNodes.getPrimaries().getStore().getSizeInBytes();\n            double curSizeInGb = curSizeInBytes * BYTE_TO_G;\n\n            double rolloverThreshold = ariusConfigInfoService.doubleSetting(AriusConfigConstant.ARIUS_COMMON_GROUP,\n                    AriusConfigConstant.INDEX_ROLLOVER_THRESHOLD, 50.0);\n\n            if (curSizeInGb >= primaryShardCnt * rolloverThreshold) {\n                // 如果大于（主shard个数 * 推荐的单个shard大小50G），直接升版本\n                updateTemplateVersion(phyTemplate);\n            } else if (curSizeInGb >= primaryShardCnt * 30 && TemplateUtils.isSaveByDay(logiTemplate.getDateFormat())) {\n                // 如果大于（主shard个数 * 推荐的单个shard大小30G），并且索引模版是按天创建索引\n                // 获取该索引模版对应索引近7天占用磁盘的最大值\n                Long sizeInBytesMax = getMaxStoreInRecentSevenDayByTemplatePhyId((phyTemplate.getId()));\n                // 比较两者大小，大于则升版本\n                if (curSizeInBytes > sizeInBytesMax) {\n                    updateTemplateVersion(phyTemplate);\n                }\n            }\n        }\n        return true;\n    }\n\n    @Override\n    public Result<Void> adjustShardCountByPhyClusterName(String phyClusterName) {\n        LOGGER.info(\n            \"class=CapacityPlanManagerImpl||method=adjustShardCountByPhyClusterName||cluster={}||msg=start adjustShardCount\",\n            phyClusterName);\n        //物理集群侧不在判读\n        //if (!isTemplateSrvOpen(phyClusterName)) {\n        //    return Result.buildFail(phyClusterName + \"没有开启\" + templateServiceName());\n        //}\n\n        List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.listTemplate();\n       \n        if (AriusObjUtils.isEmptyList(templatePhyList)) {\n            return Result.buildSucc();\n        }\n\n        Multimap<Integer/*逻辑模版id*/, IndexTemplatePhy/*物理模版*/> multimap = ConvertUtil.list2MulMap(templatePhyList,\n            IndexTemplatePhy::getLogicId);\n\n        for (Integer templateLogicId : multimap.keySet()) {\n            try {\n                if (!isTemplateSrvOpen(templateLogicId)){\n                    continue;\n                }\n                governPerTemplate(multimap.get(templateLogicId));\n            } catch (Exception e) {\n                LOGGER.warn(\n                    \"class=CapacityPlanManagerImpl||method=adjustShardCountByPhyClusterName||templateLogicId={}||errMsg={}\",\n                    templateLogicId, e.getMessage(), e);\n            }\n        }\n        return Result.buildSucc();\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/mapping/TemplateLogicMappingManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateSchemaDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateSchemaOptimizeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithMapping;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateMappingVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.Field;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * 逻辑模板的mapping服务；对我暴露的是field对象，并屏蔽底层的mapping信息、部署信息\n * @author zhognhua\n */\npublic interface TemplateLogicMappingManager {\n\n    /**\n     * 查询指定的逻辑模板 带有Mapping信息\n     * @param logicId 模板id\n     * @throws Exception\n     * @return 模板信息  不存在返回null\n     */\n    Result<IndexTemplateWithMapping> getTemplateWithMapping(Integer logicId);\n\n    /**\n     * 更新\n     *\n     * @param logicId   模板id\n     * @param fields    fields\n     * @param projectId\n     * @param operator\n     * @return result\n     */\n    Result<Void> updateFields(Integer logicId, List<Field> fields, Set<String> removeFields, Integer projectId,\n                              String operator);\n\n    /**\n     * 校验模板field\n     *\n     * @param logicId 模板id\n     * @param fields 属性列表\n     * @return Result\n     */\n    Result<Void> checkFields(Integer logicId, List<Field> fields);\n\n    /**\n     * 更新\n     * @param logicId 模板id\n     * @param ariusTypeProperty mapping\n     * @return result\n     */\n    Result<Void> updateMappingForNew(Integer logicId, AriusTypeProperty ariusTypeProperty) throws AdminOperateException;\n\n    /**\n     * updateProperties\n     * @param logicId\n     * @param properties\n     * @param operator\n     * @return\n     */\n    Result<Void> updateProperties(Integer logicId, List<AriusTypeProperty> properties, String operator);\n\n    /**\n     * field装AriusTypeProperty\n     * @param fields fields\n     * @return str\n     */\n    AriusTypeProperty fields2Mapping(List<Field> fields);\n\n\n\n    /**\n     * mapping优化\n     * @param optimizeDTO dto\n     * @param operator 操作人\n     * @return result\n     */\n    Result<Void> modifySchemaOptimize(ConsoleTemplateSchemaOptimizeDTO optimizeDTO, String operator);\n\n    /**\n     * 修改模板schema\n     *\n     * @param schemaDTO       schema\n     * @param operator        操作人\n     * @param projectId\n     * @return result\n     */\n    Result<Void> editMapping(ConsoleTemplateSchemaDTO schemaDTO, String operator,\n                             Integer projectId) throws AdminOperateException;\n\n    /**\n     * 获取模板schema\n     * @param logicId 模板id\n     * @return result\n     */\n    Result<TemplateMappingVO> getSchema(Integer logicId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/mapping/TemplatePhyMappingManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\n\nimport java.util.Set;\n\n/**\n * 物理模板的mapping服务\n * @author zhonghua\n */\npublic interface TemplatePhyMappingManager {\n\n    /**\n     * 更新模板mapping\n     * @param cluster 集群\n     * @param template 模板名字\n     * @param mappings mappings\n     * @return result\n     */\n    Result<Void> updateMapping(String cluster, String template, String mappings);\n\n    Result<Void> updateMappingAndMerge(String cluster, String template, String mappings, Set<String> removeFields);\n\n    /**\n     * 校验模板mapping 模板已经存在\n     * @param cluster 集群\n     * @param template 模板名字\n     * @param mappings mapping\n     * @return result\n     */\n    Result<Void> checkMapping(String cluster, String template, String mappings, boolean doMerge);\n\n    /**\n     * 获取模板mapping\n     * @param cluster 集群\n     * @param template 模板\n     * @return result\n     */\n    Result<MappingConfig> getMapping(String cluster, String template);\n\n    /**\n     * 将模板mapping 更新到非滚动index上\n     * @param cluster\n     * @param index\n     * @param mappingConfig\n     * @return\n     */\n    Result<Void> syncTemplateMapping2Index(String cluster, String index, MappingConfig mappingConfig) throws ESOperateException;\n\n    /**\n     * 将index的mapping同步到template上\n     * @param cluster 集群\n     * @param template 模板\n     * @param expression 模板表达式\n     * @param dataFormat 模板名中的时间格式\n     * @return result\n     */\n    Result<MappingConfig> syncMappingConfig(String cluster, String template, String expression, String dataFormat);\n\n    /**\n     * 更新索引mapping\n     * @param cluster 集群\n     * @param expression 模板表达式\n     * @param dataFormat 模板名中的时间格式\n     * @return result\n     */\n    Result<Void> addIndexMapping(String cluster, String expression, String dataFormat, int updateDays,\n                                 MappingConfig mappingConfig) throws ESOperateException;\n\n    /**\n     * 校验模板mapping 模板还不存在\n     *\n     * @param template 模板名字\n     * @param ariusTypeProperty 属性列表\n     * @return Result\n     */\n    Result<Void> checkMappingForNew(String template, AriusTypeProperty ariusTypeProperty);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/mapping/impl/TemplateLogicMappingManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.DEFAULT_INDEX_MAPPING_TYPE;\nimport static com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty.DYNAMIC_TEMPLATES_STR;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.impl.BaseTemplateSrvImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping.TemplateLogicMappingManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping.TemplatePhyMappingManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.MappingOptimizeItem;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateSchemaDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateSchemaOptimizeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.operaterecord.template.TemplateMappingOperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithMapping;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateTypePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateMappingVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.index.ReBuildTomorrowIndexEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AnalyzerEnum;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.Field;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.IndexEnum;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.SortEnum;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.SpecialField;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.TypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusIndexMappingConfigUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ESVersionUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.impl.IndexTemplateServiceImpl;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.TypeConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.TypeDefine;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.TypeProperties;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Sets;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author zhonghua\n * @date 2019-06-13\n */\n@Service(\"templateLogicMappingManagerImpl\")\npublic class TemplateLogicMappingManagerImpl extends BaseTemplateSrvImpl implements TemplateLogicMappingManager {\n\n    private static final ILog         LOGGER                            = LogFactory\n        .getLog(IndexTemplateServiceImpl.class);\n\n    private static final String       PHYSICAL_TEMPLATE_NOT_EXISTS_TIPS = \"物理模板不存在，ID:%d\";\n    @Autowired\n    private TemplatePhyMappingManager templatePhyMappingManager;\n    \n    @Autowired\n    private IndexTemplateService indexTemplateService;\n    \n \n   \n\n\n    private static final String       TEXT_STR                          = \"text\";\n    private static final String       TYPE_STR                          = \"type\";\n    private static final String       KEYWORD_STR                       = \"keyword\";\n    private static final String       IK_SMART_SRT                      = \"ik_smart\";\n    private static final String       ANALYZER_STR                      = \"analyzer\";\n    private static final String       DOC_VALUES_STR                    = \"doc_values\";\n    private static final String       INDEX_STR                         = \"index\";\n\n    /**\n     * @return\n     */\n    @Override\n    public TemplateServiceEnum templateSrv() {\n        return TemplateServiceEnum.TEMPLATE_MAPPING;\n    }\n\n    /**\n     * 查询指定的逻辑模板的Field信息\n     *\n     * @param logicId 模板id\n     * @return 模板信息  不存在返回null\n     */\n    @Override\n    public Result<IndexTemplateWithMapping> getTemplateWithMapping(Integer logicId) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (templateLogicWithPhysical == null) {\n            LOGGER.warn(\"method=getTemplateWithFieldById||msg=not exit||logicId={}\", logicId);\n            return Result.buildNotExist(\"模板不存在\");\n        }\n\n        IndexTemplateWithMapping templateLogicWithMapping = ConvertUtil.obj2Obj(templateLogicWithPhysical,\n            IndexTemplateWithMapping.class);\n\n        if (templateLogicWithPhysical.hasPhysicals()) {\n            MappingConfig mergeMappingConfig = null;\n            List<IndexTemplatePhy> masterPhysicalTemplates = templateLogicWithPhysical.fetchMasterPhysicalTemplates();\n            for (IndexTemplatePhy templatePhysical : masterPhysicalTemplates) {\n\n                Result<MappingConfig> result = templatePhyMappingManager.getMapping(templatePhysical.getCluster(),\n                    templatePhysical.getName());\n                if (result.failed()) {\n                    return Result.buildFrom(result);\n                }\n                MappingConfig mappingConfig = result.getData();\n                if (mergeMappingConfig == null) {\n                    mergeMappingConfig = mappingConfig;\n                } else {\n                    mergeMappingConfig.merge(mappingConfig);\n                }\n            }\n\n            if (null != mergeMappingConfig) {\n                templateLogicWithMapping.setTypeProperties(\n                    genAriusTypePropertyList(templateLogicWithMapping, mergeMappingConfig.getMapping()));\n\n                List<Field> fields = null;\n                try {\n                    fields = convert2Fields(mergeMappingConfig);\n                } catch (Exception t) {\n                    LOGGER.warn(\"method=getTemplateWithFieldById||msg=mapping to field error||logicId={}\", logicId, t);\n                }\n                if (fields == null) {\n                    fields = new ArrayList<>();\n                }\n                templateLogicWithMapping.setFields(fields);\n            }\n        } else {\n            LOGGER.warn(\"method=getTemplateWithFieldById||msg=not deploy||logicId={}\", logicId);\n        }\n\n        return Result.buildSucc(templateLogicWithMapping);\n    }\n\n    @Override\n    public Result checkFields(Integer logicId, List<Field> fields) {\n        if (CollectionUtils.isEmpty(fields)) {\n            return Result.buildSucc();\n        }\n\n        Result<Void> result = checkFieldInternal(fields);\n        if (result.failed()) {\n            return result;\n        }\n\n        List<IndexTemplatePhy> templatePhysicals = getMasterTemplatePhysicalByLogicId(logicId);\n\n        if (CollectionUtils.isEmpty(templatePhysicals)) {\n            return Result.buildFail(\"can not find template physical, logicId:\" + logicId);\n        }\n\n        for (IndexTemplatePhy templatePhysical : templatePhysicals) {\n            Result<MappingConfig> getDiffMappingResult = getDiffMapping(templatePhysical.getCluster(),\n                templatePhysical.getName(), fields);\n            if (getDiffMappingResult.failed()) {\n                return getDiffMappingResult;\n            }\n\n            MappingConfig mappingConfig = getDiffMappingResult.getData();\n\n            String cluster = templatePhysical.getCluster();\n            String template = templatePhysical.getName();\n            String mapping = mappingConfig.toJson().toJSONString();\n            Result<Void> checkMappingResult = templatePhyMappingManager.checkMapping(cluster, template, mapping, true);\n            if (checkMappingResult.failed()) {\n                return checkMappingResult;\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> updateFields(Integer logicId, List<Field> fields, Set<String> removeFields, Integer projectId,\n                                     String operator) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (templateLogicWithPhysical == null) {\n            return Result.buildNotExist(String.format(PHYSICAL_TEMPLATE_NOT_EXISTS_TIPS, logicId));\n        }\n\n        if (!templateLogicWithPhysical.hasPhysicals()) {\n            return Result.buildNotExist(String.format(PHYSICAL_TEMPLATE_NOT_EXISTS_TIPS, logicId));\n        }\n\n        Result<Void> checkFieldResult = checkFieldInternal(fields);\n        if (checkFieldResult.failed()) {\n            return checkFieldResult;\n        }\n\n        List<IndexTemplatePhy> masterPhysicalTemplates = templateLogicWithPhysical.fetchMasterPhysicalTemplates();\n        for (IndexTemplatePhy masterTemplatePhysical : masterPhysicalTemplates) {\n            if (masterTemplatePhysical == null) {\n                return Result.buildFail(\"can not find template physical, logicId:\" + logicId);\n            }\n            final Result<MappingConfig> beforeResult = templatePhyMappingManager\n                .getMapping(masterTemplatePhysical.getCluster(), masterTemplatePhysical.getName());\n            JSONObject beforeData = beforeResult.getData().toJson();\n            Result<MappingConfig> getDiffResult = getDiffMapping(masterTemplatePhysical.getCluster(),\n                masterTemplatePhysical.getName(), fields);\n            if (getDiffResult.failed()) {\n                return Result.buildFrom(getDiffResult);\n            }\n\n            String diffMapping = getDiffResult.getData().toJson().toJSONString();\n\n            Result<Void> editResult = templatePhyMappingManager.updateMappingAndMerge(\n                masterTemplatePhysical.getCluster(), masterTemplatePhysical.getName(), diffMapping, removeFields);\n            if (editResult.failed()) {\n                return Result.buildFrom(editResult);\n            }\n            final Result<MappingConfig> afterResult = templatePhyMappingManager\n                .getMapping(masterTemplatePhysical.getCluster(), masterTemplatePhysical.getName());\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    new TemplateMappingOperateRecord(beforeData, afterResult.getData()).toString(),\n                    operator, projectId, logicId, OperateTypeEnum.TEMPLATE_MANAGEMENT_EDIT_MAPPING);\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public AriusTypeProperty fields2Mapping(List<Field> fields) {\n        if (fields == null) {\n            fields = Lists.newArrayList();\n        }\n\n        MappingConfig mappingConfig = convert2Mapping(AdminConstant.DEFAULT_INDEX_MAPPING_TYPE, fields);\n        AriusTypeProperty ariusTypeProperty = new AriusTypeProperty();\n        ariusTypeProperty.setTypeName(AdminConstant.DEFAULT_INDEX_MAPPING_TYPE);\n        if (CollectionUtils.isNotEmpty(fields)) {\n            ariusTypeProperty.setProperties(\n                mappingConfig.getMapping().get(AdminConstant.DEFAULT_INDEX_MAPPING_TYPE).getProperties().toJson());\n        } else {\n            ariusTypeProperty.setProperties(new JSONObject());\n        }\n        return ariusTypeProperty;\n    }\n\n\n\n    /**\n     * mapping优化\n     *\n     * @param optimizeDTO dto\n     * @param operator    操作人\n     * @return result\n     */\n    @Override\n    public Result<Void> modifySchemaOptimize(ConsoleTemplateSchemaOptimizeDTO optimizeDTO, String operator) {\n\n        if (CollectionUtils.isEmpty(optimizeDTO.getItems())) {\n            return Result.buildParamIllegal(\"未选择优化字段\");\n        }\n\n        List<AriusTypeProperty> typeProperties = buildAriusTypeProperty(optimizeDTO.getItems());\n\n        return updateProperties(optimizeDTO.getLogicId(), typeProperties, operator);\n    }\n\n    @Override\n    public Result updateMappingForNew(Integer logicId, AriusTypeProperty ariusTypeProperty) throws\n                                                                                            AdminOperateException {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (templateLogicWithPhysical == null) {\n            return Result.buildNotExist(\"逻辑模板不存在, ID:\" + logicId);\n        }\n\n        if (!templateLogicWithPhysical.hasPhysicals()) {\n            return Result.buildNotExist(String.format(PHYSICAL_TEMPLATE_NOT_EXISTS_TIPS, logicId));\n        }\n        TemplateConfigPO config = indexTemplateService.getTemplateConfigByLogicId(logicId);\n\n        List<IndexTemplatePhy> templatePhysicals = templateLogicWithPhysical.fetchMasterPhysicalTemplates();\n        for (IndexTemplatePhy templatePhysical : templatePhysicals) {\n\n            Result<MappingConfig> mappingConfigResult = AriusIndexMappingConfigUtils\n                .parseMappingConfig(ariusTypeProperty.toMappingJSON().toJSONString());\n            if (mappingConfigResult.failed()) {\n                return mappingConfigResult;\n            }\n\n            MappingConfig mappingConfig = mappingConfigResult.getData();\n\n            if (config != null && config.getDisableSourceFlags() != null\n                && config.getDisableSourceFlags().booleanValue()) {\n                LOGGER.info(\"method=updateMappingForNew||msg=disableSource||logicId={}\", logicId);\n                mappingConfig.disableSource();\n            } else {\n                mappingConfig.enableSource();\n            }\n\n            Result<Void> result = templatePhyMappingManager.updateMapping(templatePhysical.getCluster(),\n                templatePhysical.getName(), mappingConfig.toJson().toJSONString());\n\n            if (result.failed()) {\n                return result;\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> updateProperties(Integer logicId, List<AriusTypeProperty> ariusTypePropertyList,\n                                         String operator) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (templateLogicWithPhysical == null) {\n            return Result.buildNotExist(\"逻辑模板不存在, ID:\" + logicId);\n        }\n\n        if (!templateLogicWithPhysical.hasPhysicals()) {\n            return Result.buildNotExist(String.format(PHYSICAL_TEMPLATE_NOT_EXISTS_TIPS, logicId));\n        }\n\n        TemplateConfigPO config = indexTemplateService.getTemplateConfigByLogicId(logicId);\n\n        List<IndexTemplatePhy> templatePhysicals = templateLogicWithPhysical.fetchMasterPhysicalTemplates();\n        boolean isSingleIndex = isSingleIndex(logicId);\n\n        for (IndexTemplatePhy templatePhysical : templatePhysicals) {\n            Result<MappingConfig> result = templatePhyMappingManager.getMapping(templatePhysical.getCluster(),\n                templatePhysical.getName());\n            if (result.failed()) {\n                return Result.buildFrom(result);\n            }\n\n            MappingConfig templateMappingConfig = (result.getData());\n            Map<String, TypeConfig> typeConfigMap = templateMappingConfig.getMapping();\n\n            if (typeConfigMap.size() == 0) {\n                TypeConfig typeConfig = new TypeConfig();\n                typeConfigMap.put(AdminConstant.DEFAULT_INDEX_MAPPING_TYPE, typeConfig);\n            }\n\n            // 将对应的type替换\n            for (AriusTypeProperty ariusTypePropertyTemp : ariusTypePropertyList) {\n                //todo 后续0.3.2下线\n                AriusTypeProperty ariusTypeProperty = AriusTypeProperty.buildPropertiesAndDynamicTemplates(ariusTypePropertyTemp);\n                //高版本es集群只有一个type\n                TypeProperties typeProperties = new TypeProperties(ariusTypeProperty.getProperties());\n\n                for (Map.Entry<String, TypeConfig> entry : typeConfigMap.entrySet()) {\n                    if (isSingleIndex && (entry.getValue().getProperties() == null || (isExistMappingChanged(entry.getValue().getProperties().getJsonMap(),\n                        typeProperties.getJsonMap())))){\n                        return Result.buildFail(\"非分区模板禁止编辑mapping\");\n                    }\n                    entry.getValue().setProperties(typeProperties);\n                    entry.getValue().getNotUsedMap().put(AdminConstant.DEFAULT_DYNAMIC_TEMPLATES_KEY,\n                        ariusTypeProperty.getDynamicTemplates());\n                }\n            }\n\n            if (config != null && config.getDisableSourceFlags()) {\n                templateMappingConfig.disableSource();\n            } else {\n                templateMappingConfig.enableSource();\n            }\n            final Result<MappingConfig> beforeResult = templatePhyMappingManager\n                .getMapping(templatePhysical.getCluster(), templatePhysical.getName());\n            JSONObject beforeData = beforeResult.getData().toJson();\n            Result<Void> updateMappingResult = templatePhyMappingManager.updateMapping(templatePhysical.getCluster(),\n                templatePhysical.getName(), templateMappingConfig.toJson().toJSONString());\n            \n            if (updateMappingResult.failed()) {\n                return Result.buildFrom(updateMappingResult);\n            }\n            final Result<MappingConfig> afterResult = templatePhyMappingManager\n                .getMapping(templatePhysical.getCluster(), templatePhysical.getName());\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    new TemplateMappingOperateRecord(beforeData, afterResult.getData()).toString(),\n                    operator, templateLogicWithPhysical.getProjectId(), logicId,\n                    OperateTypeEnum.TEMPLATE_MANAGEMENT_EDIT_MAPPING);\n        }\n\n        return Result.buildSucc();\n    }\n    \n    /**\n     * 修改模板schema\n     *\n     * @param schemaDTO       schema\n     * @param operator        操作人\n     * @param projectId\n     * @return result\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> editMapping(ConsoleTemplateSchemaDTO schemaDTO, String operator,\n                                    Integer projectId) throws AdminOperateException {\n        if (AriusObjUtils.isNull(operator)) {\n            return Result.buildParamIllegal(\"操作人为空\");\n        }\n\n        if (schemaDTO.getFields() == null && schemaDTO.getTypeProperties() == null) {\n            return Result.buildParamIllegal(\"fields或mapping信息非法\");\n        }\n\n        if (schemaDTO.getFields() != null && schemaDTO.getTypeProperties() != null) {\n            return Result.buildParamIllegal(\"fields或mapping信息非法\");\n        }\n\n        if (schemaDTO.getFields() != null && !clusterIsHighVersion(schemaDTO.getLogicId())) {\n            return Result.buildParamIllegal(\"该功能只支持高版本(6.5.1以上)es， 请使用JSON格式\");\n        }\n\n        Result<Void> saveSpecialFieldResult = saveSpecialField(schemaDTO, operator, projectId);\n        if (saveSpecialFieldResult.failed()) {\n            return saveSpecialFieldResult;\n        }\n\n        // 修改mapping信息.\n        if (schemaDTO.getTypeProperties() != null) {\n            Result<Void> result = updateProperties(schemaDTO.getLogicId(), schemaDTO.getTypeProperties(), operator);\n            if (result.success()) {\n                // 根据是否滚动生成索引 进行index mapping update\n                if (isSingleIndex(schemaDTO.getLogicId())) {\n                    syncTemplateMapping2Index(schemaDTO.getLogicId());\n                } else {\n                    SpringTool.publish(new ReBuildTomorrowIndexEvent(this,schemaDTO.getLogicId()));\n                }\n            }\n            return result;\n        }\n\n        Result<Void> result = updateFields(schemaDTO.getLogicId(), schemaDTO.getFields(),\n            schemaDTO.getRemoveFieldNames(), projectId, operator\n\n        );\n        if (result.success()) {\n            //JSonu\n            // 重建明天索引 通过发布事件提升模板编辑的速度\n            \n             SpringTool.publish(new ReBuildTomorrowIndexEvent(this,schemaDTO.getLogicId()));\n        }\n\n        return result;\n    }\n\n    @Override\n    public Result<TemplateMappingVO> getSchema(Integer logicId) {\n        Result<IndexTemplateWithMapping> result = getTemplateWithMapping(logicId);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n\n        IndexTemplateWithMapping templateLogicWithMapping = result.getData();\n        if (templateLogicWithMapping == null) {\n            return Result.buildParamIllegal(\"索引不存在\");\n        }\n\n        fillSpecialField(templateLogicWithMapping);\n\n        TemplateMappingVO schemaVO = ConvertUtil.obj2Obj(templateLogicWithMapping, TemplateMappingVO.class);\n        return Result.buildSucc(schemaVO);\n    }\n\n    /**************************************** private method ****************************************************/\n    private List<AriusTypeProperty> genAriusTypePropertyList(IndexTemplate templateLogic,\n                                                             Map<String, TypeConfig> typeConfigMap) {\n\n        List<IndexTemplateType> templateTypes = indexTemplateService.listLogicTemplateTypes(templateLogic.getId());\n        Map<String, IndexTemplateType> typeName2IndexTemplateTypeMap = ConvertUtil.list2Map(templateTypes,\n            IndexTemplateType::getName);\n\n        List<AriusTypeProperty> ariusTypePropertyList = Lists.newArrayList();\n\n        if (typeConfigMap == null || typeConfigMap.size() == 0) {\n            ariusTypePropertyList.add(buildDefaultType(templateLogic));\n        } else if (typeConfigMap.size() == 1) {\n            ariusTypePropertyList.add(buildOneType(templateLogic, typeConfigMap, typeName2IndexTemplateTypeMap));\n        } else {\n            List<AriusTypeProperty> typeProperties = buildMultiType(templateLogic, typeConfigMap,\n                typeName2IndexTemplateTypeMap);\n            ariusTypePropertyList.addAll(typeProperties);\n        }\n\n        return ariusTypePropertyList;\n    }\n\n    private List<IndexTemplatePhy> getMasterTemplatePhysicalByLogicId(Integer logicId) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (templateLogicWithPhysical == null) {\n            LOGGER.warn(\"method=getIndexTemplatePhysicalByLogicId||msg=not exit||logicId={}\", logicId);\n            return Collections.emptyList();\n        }\n\n        if (templateLogicWithPhysical.hasPhysicals()) {\n            return templateLogicWithPhysical.fetchMasterPhysicalTemplates();\n        } else {\n            LOGGER.warn(\"method=getIndexTemplatePhysicalByLogicId||msg=not deploy||logicId={}\", logicId);\n            return Collections.emptyList();\n        }\n    }\n\n    private Result<Void> checkFieldInternal(List<Field> fields) {\n        Set<String> existName = Sets.newHashSet();\n        for (Field field : fields) {\n            Result<Void> result = checkField(existName, field);\n            if (result.failed()) {\n                return result;\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkField(Set<String> existName, Field field) {\n        Result<Void> result = checkFieldIsNull(field);\n        if (result.failed()) {\n            return result;\n        }\n\n        if (existName.contains(field.getName())) {\n            return Result.buildParamIllegal(\"字段名称重复\");\n        }\n\n        existName.add(field.getName());\n        TypeEnum typeEnum = TypeEnum.valueFrom(field.getType());\n        if (typeEnum.equals(TypeEnum.UNKNOWN)) {\n            return Result.buildParamIllegal(\"字段类型非法\");\n        }\n\n        IndexEnum indexEnum = IndexEnum.valueFrom(field.getIndexType());\n        if (indexEnum.equals(IndexEnum.UNKNOWN)) {\n            return Result.buildParamIllegal(\"检索类型非法\");\n        }\n\n        if (field.getAnalyzerType() != null) {\n            Result<Void> checkFieldAnalyzerTypeResult = checkFieldAnalyzerType(field);\n            if (checkFieldAnalyzerTypeResult.failed()) {\n                return checkFieldAnalyzerTypeResult;\n            }\n        }\n\n        if (field.getSortType() != null) {\n            Result<Void> checkFieldSortTypeResult = checkFieldSortType(field);\n            if (checkFieldSortTypeResult.failed()) {\n                return checkFieldSortTypeResult;\n            }\n        }\n\n        Result<Void> checkFieldTypeResult = checkfieldType(field);\n        if (checkFieldTypeResult.failed()) {\n            return checkFieldTypeResult;\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkFieldAnalyzerType(Field field) {\n        AnalyzerEnum analyzerEnum = AnalyzerEnum.valueFrom(field.getAnalyzerType());\n        if (analyzerEnum.equals(AnalyzerEnum.UNKNOWN)) {\n            return Result.buildParamIllegal(\"分词器非法\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkFieldSortType(Field field) {\n        SortEnum sortEnum = SortEnum.valueFrom(field.getSortType());\n        if (sortEnum.equals(SortEnum.UNKNOWN)) {\n            return Result.buildParamIllegal(\"是否排序非法非法\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkfieldType(Field field) {\n        if (field.getType().equals(TypeEnum.STRING.getCode())) {\n            Result<Void> checkFieldStringResult = handleCheckFieldString(field);\n            if (checkFieldStringResult.failed()) {\n                return checkFieldStringResult;\n            }\n        } else {\n            if (field.getIndexType().equals(IndexEnum.FUZZY.getCode())) {\n                return Result.buildParamIllegal(\"非string类型的字段不能配置全文检索\");\n            }\n            if (field.getAnalyzerType() != null) {\n                return Result.buildParamIllegal(\"非string类型的字段不能配置分词器\");\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleCheckFieldString(Field field) {\n        if (field.getIndexType().equals(IndexEnum.FUZZY.getCode())) {\n            if (field.getSortType() != null && field.getSortType().equals(SortEnum.YES.getCode())) {\n                return Result.buildParamIllegal(\"全文检索的string类型不能排序\");\n            }\n            if (field.getAnalyzerType() == null) {\n                return Result.buildParamIllegal(\"全文检索的string类型必须选择分词器\");\n            }\n        }\n        if (field.getIndexType().equals(IndexEnum.FORBID.getCode()) && field.getAnalyzerType() != null) {\n            return Result.buildParamIllegal(\"不检索的string类型不能配置分词器\");\n        }\n        if (field.getIndexType().equals(IndexEnum.EXACT.getCode()) && field.getAnalyzerType() != null) {\n            return Result.buildParamIllegal(\"精确检索的string类型不能配置分词器\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkFieldIsNull(Field field) {\n        if (AriusObjUtils.isNull(field)) {\n            return Result.buildParamIllegal(\"字段信息不能为空\");\n        }\n        if (AriusObjUtils.isNull(field.getName())) {\n            return Result.buildParamIllegal(\"字段名称不能为空\");\n        }\n        if (AriusObjUtils.isNull(field.getType())) {\n            return Result.buildParamIllegal(\"字段类型不能为空\");\n        }\n        if (AriusObjUtils.isNull(field.getIndexType())) {\n            return Result.buildParamIllegal(\"检索类型不能为空\");\n        }\n        return Result.buildSucc();\n    }\n\n    /**\n     * 根据现有配置 和 fields对比，得到修改的mapping\n     */\n    private Result<MappingConfig> getDiffMapping(String cluster, String template, List<Field> fields) {\n        try {\n            Result<MappingConfig> result = templatePhyMappingManager.getMapping(cluster, template);\n            if (result.failed()) {\n                return result;\n            }\n\n            MappingConfig mappingConfig = result.getData();\n            Set<String> typeNames = mappingConfig.getMapping().keySet();\n            if (typeNames.size() > 1) {\n                return Result.buildFrom(Result\n                    .buildFail(\"模板中有多个type，请使用mapping json的方式修改, \" + \"cluster:\" + cluster + \", template:\" + template));\n            }\n\n            String type = \"type\";\n            if (typeNames.size() == 1) {\n                for (String typeName : typeNames) {\n                    type = typeName;\n                }\n            }\n\n            List<Field> srcFields = convert2Fields(mappingConfig);\n            List<Field> diffFields = diffField(srcFields, fields);\n\n            mappingConfig = convert2Mapping(type, diffFields);\n\n            return Result.buildSucc(mappingConfig);\n\n        } catch (Exception e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    private List<Field> convert2Fields(MappingConfig mapping) {\n        Map<String/*typeName*/, Map<String/*field*/, TypeDefine>> typeFieldTypeMap = mapping.getTypeDefines();\n        List<Field> ret = new ArrayList<>();\n\n        Set<String> fieldNames = new HashSet<>();\n\n        for (Map.Entry<String/*typeName*/, Map<String/*field*/, TypeDefine>> entry : typeFieldTypeMap.entrySet()) {\n            for (String fieldName : entry.getValue().keySet()) {\n                if (fieldNames.contains(fieldName)) {\n                    continue;\n                } else {\n                    fieldNames.add(fieldName);\n                }\n\n                TypeDefine td = entry.getValue().get(fieldName);\n\n                JSONObject typeObj = td.getDefine();\n                if (typeObj.isEmpty()) {\n                    continue;\n                }\n\n                Field field = getField(fieldName, typeObj);\n\n                ret.add(field);\n            }\n        }\n\n        LOGGER.debug(\"method=convert2Fields||ret={}||mapping={}\", ret, mapping);\n\n\n        return ret;\n    }\n\n    private Field getField(String fieldName, JSONObject typeObj) {\n        Field field = new Field();\n        field.setName(fieldName);\n\n        if (TEXT_STR.equals(typeObj.getString(TYPE_STR))) {\n            handleTypeText(typeObj, field);\n        } else if (KEYWORD_STR.equals(typeObj.get(TYPE_STR))) {\n            handleTypeKeyword(typeObj, field);\n        } else if (TypeEnum.INT.getCode().equalsIgnoreCase(typeObj.getString(TYPE_STR))\n                   || TypeEnum.LONG.getCode().equalsIgnoreCase(typeObj.getString(TYPE_STR))\n                   || TypeEnum.BOOLEAN.getCode().equalsIgnoreCase(typeObj.getString(TYPE_STR))\n                   || TypeEnum.DOUBLE.getCode().equalsIgnoreCase(typeObj.getString(TYPE_STR))\n                   || TypeEnum.DATE.getCode().equalsIgnoreCase(typeObj.getString(TYPE_STR))\n                   || TypeEnum.OBJECT.getCode().equalsIgnoreCase(typeObj.getString(TYPE_STR))\n                   || TypeEnum.FLOAT.getCode().equalsIgnoreCase(typeObj.getString(TYPE_STR))) {\n            handleTypeNonString(typeObj, field);\n        } else {\n            handleTypeUnknown(field);\n        }\n        return field;\n    }\n\n    private void handleTypeUnknown(Field field) {\n        field.setType(TypeEnum.UNKNOWN.getCode());\n        field.setAnalyzerType(AnalyzerEnum.UNKNOWN.getCode());\n        field.setIndexType(IndexEnum.UNKNOWN.getCode());\n        field.setSortType(SortEnum.UNKNOWN.getCode());\n    }\n\n    private void handleTypeNonString(JSONObject typeObj, Field field) {\n        field.setType(typeObj.getString(TYPE_STR));\n\n        if (typeObj.containsKey(INDEX_STR) && !typeObj.getBoolean(INDEX_STR).booleanValue()) {\n            field.setIndexType(IndexEnum.FORBID.getCode());\n        } else {\n            field.setIndexType(IndexEnum.EXACT.getCode());\n        }\n\n        if (typeObj.containsKey(DOC_VALUES_STR)) {\n            if (typeObj.getBoolean(DOC_VALUES_STR).booleanValue()) {\n                field.setSortType(SortEnum.YES.getCode());\n            } else {\n                field.setSortType(SortEnum.NO.getCode());\n            }\n        }\n    }\n\n    private void handleTypeKeyword(JSONObject typeObj, Field field) {\n        field.setType(TypeEnum.STRING.getCode());\n\n        if (typeObj.containsKey(INDEX_STR) && !typeObj.getBoolean(INDEX_STR).booleanValue()) {\n            field.setIndexType(IndexEnum.FORBID.getCode());\n        } else {\n            field.setIndexType(IndexEnum.EXACT.getCode());\n        }\n\n        if (typeObj.containsKey(DOC_VALUES_STR)) {\n            if (typeObj.getBoolean(DOC_VALUES_STR).booleanValue()) {\n                field.setSortType(SortEnum.YES.getCode());\n            } else {\n                field.setSortType(SortEnum.NO.getCode());\n            }\n        }\n    }\n\n    private void handleTypeText(JSONObject typeObj, Field field) {\n        field.setType(TypeEnum.STRING.getCode());\n\n        // 分词配置\n        if (typeObj.containsKey(ANALYZER_STR) && IK_SMART_SRT.equals(typeObj.getString(ANALYZER_STR))) {\n            field.setAnalyzerType(AnalyzerEnum.IK.getCode());\n        } else {\n            field.setAnalyzerType(AnalyzerEnum.DEFAULT.getCode());\n        }\n\n        if (typeObj.containsKey(INDEX_STR) && !typeObj.getBoolean(INDEX_STR).booleanValue()) {\n            field.setIndexType(IndexEnum.FORBID.getCode());\n            field.setAnalyzerType(null);\n        } else {\n            field.setIndexType(IndexEnum.FUZZY.getCode());\n        }\n\n        if (typeObj.containsKey(DOC_VALUES_STR)) {\n            if (typeObj.getBoolean(DOC_VALUES_STR).booleanValue()) {\n                field.setSortType(SortEnum.YES.getCode());\n            } else {\n                field.setSortType(SortEnum.NO.getCode());\n            }\n        }\n    }\n\n    private MappingConfig convert2Mapping(String type, List<Field> fields) {\n        Map<String, TypeDefine> mappingTypes = Maps.newHashMap();\n\n        for (Field field : fields) {\n            // fields -> type\n            TypeEnum typeEnum = TypeEnum.valueFrom(field.getType());\n            IndexEnum indexEnum = IndexEnum.valueFrom(field.getIndexType());\n            SortEnum sortEnum = SortEnum.valueFrom(field.getSortType());\n            AnalyzerEnum analyzerEnum = AnalyzerEnum.valueFrom(field.getAnalyzerType());\n\n            JSONObject typeObj = new JSONObject();\n            if (typeEnum == TypeEnum.STRING) {\n                handleTypeString(indexEnum, sortEnum, analyzerEnum, typeObj);\n            } else {\n                handleTypeNonString(typeEnum, indexEnum, sortEnum, typeObj);\n            }\n\n            mappingTypes.put(field.getName(), new TypeDefine(typeObj));\n        }\n\n        MappingConfig mappingConfig = new MappingConfig();\n\n        for (Map.Entry<String, TypeDefine> entry : mappingTypes.entrySet()) {\n            String field = entry.getKey();\n            List<String> fieldList = new ArrayList<>();\n            fieldList.addAll(Arrays.asList(field.split(\"\\\\.\")));\n            mappingConfig.addFields(type, fieldList, entry.getValue());\n        }\n\n        return mappingConfig;\n    }\n\n    private void handleTypeNonString(TypeEnum typeEnum, IndexEnum indexEnum, SortEnum sortEnum, JSONObject typeObj) {\n        typeObj.put(TYPE_STR, typeEnum.getCode());\n\n        if (typeEnum != TypeEnum.OBJECT && typeEnum != TypeEnum.ARRAY) {\n            if (indexEnum == IndexEnum.FORBID) {\n                typeObj.put(INDEX_STR, false);\n            } else if (indexEnum == IndexEnum.EXACT) {\n                typeObj.put(INDEX_STR, true);\n            }\n\n            if (sortEnum == SortEnum.NO) {\n                typeObj.put(DOC_VALUES_STR, false);\n            } else if (sortEnum == SortEnum.YES) {\n                typeObj.put(DOC_VALUES_STR, true);\n            }\n\n            // 如果新增，或者改为Date类型，则自动增加format\n            if (typeEnum == TypeEnum.DATE) {\n                typeObj.put(\n                    \"format\",\n                    \"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS\"\n                              + \"||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\");\n            }\n        }\n    }\n\n    private void handleTypeString(IndexEnum indexEnum, SortEnum sortEnum, AnalyzerEnum analyzerEnum,\n                                  JSONObject typeObj) {\n        if (indexEnum == IndexEnum.FUZZY) {\n            typeObj.put(TYPE_STR, TEXT_STR);\n        } else {\n            typeObj.put(TYPE_STR, KEYWORD_STR);\n        }\n\n        if (indexEnum == IndexEnum.FORBID) {\n            typeObj.put(INDEX_STR, false);\n        } else if (indexEnum == IndexEnum.EXACT) {\n            typeObj.put(INDEX_STR, true);\n        }\n\n        if (sortEnum == SortEnum.NO) {\n            typeObj.put(DOC_VALUES_STR, false);\n        } else if (sortEnum == SortEnum.YES) {\n            typeObj.put(DOC_VALUES_STR, true);\n        }\n\n        if (analyzerEnum == AnalyzerEnum.IK) {\n            typeObj.put(ANALYZER_STR, IK_SMART_SRT);\n        }\n    }\n\n    /**\n     * 返回dst中和src中不同的field\n     *\n     * @param src\n     * @param dst\n     * @return\n     */\n    private List<Field> diffField(List<Field> src, List<Field> dst) {\n        Map<String, Field> srcMap = Maps.newHashMap();\n\n        for (Field field : src) {\n            srcMap.put(field.getName(), field);\n        }\n\n        List<Field> ret = new ArrayList<>();\n        for (Field field : dst) {\n            if (!srcMap.containsKey(field.getName())) {\n                ret.add(field);\n                continue;\n            }\n\n            if (!field.esTypeEquals(srcMap.get(field.getName()))) {\n                ret.add(field);\n            }\n        }\n\n        return ret;\n    }\n\n    private AriusTypeProperty buildDefaultType(IndexTemplate templateLogic) {\n        // 优先取模板中的id和routing\n        String idField = templateLogic.getIdField();\n        String routingField = templateLogic.getRoutingField();\n\n        AriusTypeProperty ariusTypeProperty = new AriusTypeProperty();\n        ariusTypeProperty.setTypeName(AdminConstant.DEFAULT_INDEX_MAPPING_TYPE);\n\n        ariusTypeProperty.setProperties(new JSONObject());\n\n        ariusTypeProperty.setIdField(idField);\n        ariusTypeProperty.setRoutingField(routingField);\n        ariusTypeProperty.setDateField(templateLogic.getDateField());\n        ariusTypeProperty.setDateFieldFormat(templateLogic.getDateFieldFormat());\n\n        return ariusTypeProperty;\n    }\n\n    private AriusTypeProperty buildOneType(IndexTemplate templateLogic, Map<String, TypeConfig> typeConfigMap,\n                                           Map<String, IndexTemplateType> typeName2IndexTemplateTypeMap) {\n        Map.Entry<String, TypeConfig> entry = typeConfigMap.entrySet().iterator().next();\n        String typeName = entry.getKey();\n\n        // 优先取模板中的id和routing\n        String idField = templateLogic.getIdField();\n        String routingField = templateLogic.getRoutingField();\n\n        if (typeName2IndexTemplateTypeMap.containsKey(typeName)) {\n            IndexTemplateType typeFromMysql = typeName2IndexTemplateTypeMap.get(typeName);\n\n            if (StringUtils.isBlank(idField) && typeFromMysql != null) {\n                idField = typeFromMysql.getIdField();\n            }\n\n            if (StringUtils.isBlank(routingField) && typeFromMysql != null) {\n                routingField = typeFromMysql.getRouting();\n            }\n        }\n\n        TypeConfig typeConfig = entry.getValue();\n\n        AriusTypeProperty ariusTypeProperty = new AriusTypeProperty();\n        ariusTypeProperty.setTypeName(typeName);\n\n        if (typeConfig.getProperties() == null) {\n            ariusTypeProperty.setProperties(new JSONObject());\n        } else {\n            ariusTypeProperty.setProperties(typeConfig.getProperties().toJson());\n        }\n\n        ariusTypeProperty.setIdField(idField);\n        ariusTypeProperty.setRoutingField(routingField);\n        ariusTypeProperty.setDateField(templateLogic.getDateField());\n        ariusTypeProperty.setDateFieldFormat(templateLogic.getDateFieldFormat());\n\n        // 获取并且设置对应的dynamic_templates\n        Map<String, Object> notUsedMap = typeConfig.getNotUsedMap();\n        if (!MapUtils.isEmpty(notUsedMap) && notUsedMap.containsKey(DYNAMIC_TEMPLATES_STR)) {\n            JSONArray dynamicArrays = (JSONArray) notUsedMap.get(DYNAMIC_TEMPLATES_STR);\n            ariusTypeProperty.setDynamicTemplates(dynamicArrays);\n        }\n\n        return ariusTypeProperty;\n    }\n\n    private List<AriusTypeProperty> buildMultiType(IndexTemplate templateLogic, Map<String, TypeConfig> typeConfigMap,\n                                                   Map<String, IndexTemplateType> typeName2IndexTemplateTypeMap) {\n        List<AriusTypeProperty> typeProperties = Lists.newArrayList();\n        for (Map.Entry<String, TypeConfig> entry : typeConfigMap.entrySet()) {\n            String typeName = entry.getKey();\n            TypeConfig typeConfig = entry.getValue();\n\n            AriusTypeProperty ariusTypeProperty = new AriusTypeProperty();\n            ariusTypeProperty.setTypeName(typeName);\n\n            if (typeConfig.getProperties() == null) {\n                ariusTypeProperty.setProperties(new JSONObject());\n            } else {\n                ariusTypeProperty.setProperties(typeConfig.getProperties().toJson());\n            }\n\n            if (typeName2IndexTemplateTypeMap.containsKey(typeName)) {\n                IndexTemplateType typeFromMysql = typeName2IndexTemplateTypeMap.get(typeName);\n                if (typeFromMysql != null) {\n                    ariusTypeProperty.setIdField(typeFromMysql.getIdField());\n                    ariusTypeProperty.setRoutingField(typeFromMysql.getRouting());\n                    ariusTypeProperty.setDateField(templateLogic.getDateField());\n                    ariusTypeProperty.setDateFieldFormat(templateLogic.getDateFieldFormat());\n                }\n            }\n\n            typeProperties.add(ariusTypeProperty);\n        }\n\n        return typeProperties;\n    }\n\n    private List<AriusTypeProperty> buildAriusTypeProperty(List<MappingOptimizeItem> items) {\n        Multimap<String, MappingOptimizeItem> typeName2JSONObjectMultiMap = ConvertUtil.list2MulMap(items,\n            MappingOptimizeItem::getTypeName);\n\n        List<AriusTypeProperty> typeProperties = Lists.newArrayList();\n        for (String typeName : typeName2JSONObjectMultiMap.keySet()) {\n            AriusTypeProperty typeProperty = new AriusTypeProperty();\n            typeProperty.setTypeName(typeName);\n\n            Collection<MappingOptimizeItem> typeOptimizeItems = typeName2JSONObjectMultiMap.get(typeName);\n            JSONObject properties = new JSONObject();\n            for (MappingOptimizeItem item : typeOptimizeItems) {\n                properties.put(item.getFieldName(), item.getOptimize());\n            }\n\n            typeProperty.setProperties(properties);\n\n            typeProperties.add(typeProperty);\n        }\n\n        return typeProperties;\n    }\n\n    private Result<Void> saveSpecialField(ConsoleTemplateSchemaDTO schemaDTO, String operator,\n                                          Integer projectId) throws AdminOperateException {\n        if (CollectionUtils.isNotEmpty(schemaDTO.getFields())) {\n            return saveSpecialFieldByField(schemaDTO, operator, projectId);\n        } else {\n            return saveSpecialFieldByJSON(schemaDTO, operator, projectId);\n        }\n\n    }\n\n    private Result<Void> saveSpecialFieldByJSON(ConsoleTemplateSchemaDTO schemaDTO, String operator,\n                                                Integer projectId) throws AdminOperateException {\n        List<AriusTypeProperty> typeProperties = schemaDTO.getTypeProperties();\n        if (typeProperties.size() == 1 && (StringUtils.isBlank(typeProperties.get(0).getTypeName())\n                                           || typeProperties.get(0).getTypeName().equals(DEFAULT_INDEX_MAPPING_TYPE))) {\n            // 就一个type，修改模板的id和routing字段\n            IndexTemplateDTO templateLogicDTO = new IndexTemplateDTO();\n            templateLogicDTO.setId(schemaDTO.getLogicId());\n\n            templateLogicDTO.setDateField(typeProperties.get(0).getDateField());\n            templateLogicDTO.setDateFieldFormat(typeProperties.get(0).getDateFieldFormat());\n            Result<Void> editDateFieldResult = indexTemplateService.editTemplate(templateLogicDTO, operator, projectId);\n            if (editDateFieldResult.failed()) {\n                return editDateFieldResult;\n            }\n        } else {\n            Result<Void> result = handleUpdateType(schemaDTO, operator, typeProperties, projectId);\n            if (result.failed()) {\n                return result;\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleUpdateType(ConsoleTemplateSchemaDTO schemaDTO, String operator,\n                                          List<AriusTypeProperty> typeProperties,\n                                          Integer projectId) throws AdminOperateException {\n        // 修改type表\n        List<IndexTemplateType> templateTypes = indexTemplateService.listLogicTemplateTypes(schemaDTO.getLogicId());\n        Map<String, IndexTemplateType> typeName2IndexTemplateTypeMap = ConvertUtil.list2Map(templateTypes,\n            IndexTemplateType::getName);\n\n        String dateField = typeProperties.get(0).getDateField();\n        String dateFieldFormat = typeProperties.get(0).getDateFieldFormat();\n\n        Result<Void> result = handleTypeProperties(typeProperties, typeName2IndexTemplateTypeMap, dateField);\n        if (result.failed()) {\n            return result;\n        }\n\n        // 修改模板的时间字段\n        if (dateField != null || dateFieldFormat != null) {\n            IndexTemplateDTO templateLogicDTO = new IndexTemplateDTO();\n            templateLogicDTO.setId(schemaDTO.getLogicId());\n            templateLogicDTO.setDateField(dateField);\n            templateLogicDTO.setDateFieldFormat(dateFieldFormat);\n            Result<Void> editDateFieldResult = indexTemplateService.editTemplate(templateLogicDTO, operator, projectId);\n            if (editDateFieldResult.failed()) {\n                return editDateFieldResult;\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleTypeProperties(List<AriusTypeProperty> typeProperties,\n                                              Map<String, IndexTemplateType> typeName2IndexTemplateTypeMap,\n                                              String dateField) {\n        for (AriusTypeProperty typeProperty : typeProperties) {\n\n            if (!Objects.equals(dateField, typeProperty.getDateField())) {\n                return Result.buildFail(\"多个type的分区字段必须一致\");\n            }\n\n            if (typeName2IndexTemplateTypeMap.containsKey(typeProperty.getTypeName())) {\n                // 更新\n                IndexTemplateType indexTemplateType = typeName2IndexTemplateTypeMap.get(typeProperty.getTypeName());\n                TemplateTypePO param = new TemplateTypePO();\n                param.setId(indexTemplateType.getId());\n                param.setIdField(typeProperty.getIdField());\n                param.setRouting(typeProperty.getRoutingField());\n                if (!indexTemplateService.updateTemplateType(param)) {\n                    return Result.buildFail(\"保存特征字段失败\");\n                } else {\n                    LOGGER.info(\"method=saveSpecialFieldByJSON||msg=update db succ||typeId={}\", param.getId());\n                }\n            } else {\n                if (StringUtils.isNotBlank(typeProperty.getIdField())\n                    || StringUtils.isNotBlank(typeProperty.getRoutingField())) {\n                    return Result.buildFail(\n                        \"平台升级es到高版本(7.6.1)，高版本es索引仅支持单type，不再支持多个type；平台弱化了用户侧索引type的概念，索引多type需求用户可以通过创建多个索引来实现；\\n\"\n                                            + \"如需指定索引type的主键字段或者路由字段，请确认您的索引mapping中只有一个名为\\\"\"\n                                            + DEFAULT_INDEX_MAPPING_TYPE + \"\\\"的type；\");\n                }\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> saveSpecialFieldByField(ConsoleTemplateSchemaDTO schemaDTO, String operator,\n                                                 Integer projectId) throws AdminOperateException {\n        SpecialField specialField = SpecialField.analyzeFromFields(schemaDTO.getFields(),\n            schemaDTO.getRemoveFieldNames());\n        IndexTemplateDTO templateLogicDTO = new IndexTemplateDTO();\n        templateLogicDTO.setId(schemaDTO.getLogicId());\n        templateLogicDTO.setDateField(specialField.getDateField());\n        templateLogicDTO.setDateFieldFormat(specialField.getDateFieldFormat());\n        return indexTemplateService.editTemplate(templateLogicDTO, operator, projectId);\n    }\n\n    private boolean clusterIsHighVersion(Integer logicId) {\n        IndexTemplateWithPhyTemplates logicWithPhysical = this.indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (!logicWithPhysical.hasPhysicals()) {\n            return false;\n        }\n\n        Result<ClusterPhy> clusterPhyResult = clusterPhyManager\n            .getClusterByName(logicWithPhysical.getMasterPhyTemplate().getCluster());\n        if (null == clusterPhyResult.getData()) {\n            return false;\n        }\n\n        return ESVersionUtil.isHigher(clusterPhyResult.getData().getEsVersion(), \"6.5.1\");\n    }\n\n    protected void fillSpecialField(IndexTemplateWithMapping templateLogicWithMapping) {\n        if (CollectionUtils.isEmpty(templateLogicWithMapping.getFields())) {\n            return;\n        }\n\n        Map<String, Field> name2FieldMap = ConvertUtil.list2Map(templateLogicWithMapping.getFields(), Field::getName);\n\n        if (StringUtils.isNotBlank(templateLogicWithMapping.getDateField())) {\n            handleDateField(templateLogicWithMapping, name2FieldMap);\n        }\n\n        if (StringUtils.isNotBlank(templateLogicWithMapping.getIdField())) {\n            handleIdField(templateLogicWithMapping, name2FieldMap);\n        }\n\n        if (StringUtils.isNotBlank(templateLogicWithMapping.getRoutingField())) {\n            handleRoutingField(templateLogicWithMapping, name2FieldMap);\n        }\n    }\n\n    private void handleRoutingField(IndexTemplateWithMapping templateLogicWithMapping,\n                                    Map<String, Field> name2FieldMap) {\n        for (String routingField : templateLogicWithMapping.getRoutingField().split(\",\")) {\n            if (name2FieldMap.containsKey(routingField)) {\n                name2FieldMap.get(routingField).setRoutingField(true);\n            }\n        }\n    }\n\n    private void handleIdField(IndexTemplateWithMapping templateLogicWithMapping, Map<String, Field> name2FieldMap) {\n        for (String idField : templateLogicWithMapping.getIdField().split(\",\")) {\n            if (name2FieldMap.containsKey(idField)) {\n                name2FieldMap.get(idField).setIdField(true);\n            }\n        }\n    }\n\n    private void handleDateField(IndexTemplateWithMapping templateLogicWithMapping, Map<String, Field> name2FieldMap) {\n        if (name2FieldMap.containsKey(templateLogicWithMapping.getDateField())) {\n            name2FieldMap.get(templateLogicWithMapping.getDateField()).setDateField(true);\n            name2FieldMap.get(templateLogicWithMapping.getDateField())\n                .setDateFieldFormat(templateLogicWithMapping.getDateFieldFormat());\n        }\n    }\n\n    /**\n     * 判断模板是否生成滚动索引\n     * @param logicId\n     * @return\n     */\n    private boolean isSingleIndex(Integer logicId) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n        //滚动索引的expression 以* 结尾\n        return !templateLogicWithPhysical.getExpression().endsWith(\"*\");\n    }\n\n    /**\n     * 将模板mapping 更新到非滚动index上\n     * @param logicId\n     * @return\n     */\n    private void syncTemplateMapping2Index(Integer logicId) throws ESOperateException {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        List<IndexTemplatePhy> templatePhysicals = templateLogicWithPhysical.fetchMasterPhysicalTemplates();\n        for (IndexTemplatePhy indexTemplatePhy : templatePhysicals) {\n            Result<MappingConfig> result = templatePhyMappingManager.getMapping(indexTemplatePhy.getCluster(),\n                indexTemplatePhy.getName());\n            if (result.failed()) {\n                LOGGER.warn(\"class=TemplateLogicMappingManagerImpl||method=syncTemplateMapping2Index|||logicId={}\",\n                    logicId);\n            }\n            MappingConfig templateMappingConfig = result.getData();\n            Result<Void> updateResult = templatePhyMappingManager.syncTemplateMapping2Index(\n                indexTemplatePhy.getCluster(), indexTemplatePhy.getExpression(), templateMappingConfig);\n            if (updateResult.failed()) {\n                LOGGER.warn(\"class=TemplateLogicMappingManagerImpl||method=syncTemplateMapping2Index||mapping={}\",\n                    templateMappingConfig);\n            }\n        }\n    }\n\n    /**\n     * 判断修改前后两个mapping 对象是否改变，这里只判断「原mapping」已有字段是否被修改，「新增字段」不在判断范围之内\n     * @param src\n     * @param dest\n     * @return\n     */\n    private boolean isExistMappingChanged(Map<String, TypeDefine> src, Map<String, TypeDefine> dest) {\n        if (src == null || dest == null) {\n            return false;\n        }\n        try {\n            for (Map.Entry<String, TypeDefine> entry : src.entrySet()) {\n                if (!entry.getValue().equals(dest.get(entry.getKey()))) {\n                    return true;\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=TemplateLogicMappingManagerImpl||method=isExistMappingChanged||errMsg={}\",\n                e.getMessage(), e);\n        }\n        return false;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/mapping/impl/TemplatePhyMappingManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping.impl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONException;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping.TemplatePhyMappingManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminESOpRetryConstants;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusIndexMappingConfigUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameFactory;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.impl.IndexTemplateServiceImpl;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.TypeConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.IndexConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.MultiIndexsConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.TemplateConfig;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Maps;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author zhonghua\n */\n@Service\n@NoArgsConstructor\npublic class TemplatePhyMappingManagerImpl implements TemplatePhyMappingManager {\n    private static final ILog    LOGGER                   = LogFactory.getLog(IndexTemplateServiceImpl.class);\n\n    private static final String  MAPPING_STR              = \"mapping\";\n    private static final String  MAPPINGS_STR             = \"mappings\";\n    private static final Integer MAPPING_FIELD_LIMIT_SIZE = 1000;\n\n    private static final String  JSON_PARSE_ERROR_TIPS    = \"json解析失败\";\n\n    @Autowired\n    private ESTemplateService    templateService;\n\n    @Autowired\n    private ESIndexService       indexService;\n\n\n\n    @Override\n    public Result<Void> updateMapping(String cluster, String template, String mappingStr) {\n        return updateMappingCore(cluster, template, mappingStr, null, false);\n    }\n\n    @Override\n    public Result<Void> updateMappingAndMerge(String cluster, String template, String mappingStr,\n                                              Set<String> removeFields) {\n        return updateMappingCore(cluster, template, mappingStr, removeFields, true);\n    }\n\n    @Override\n    public Result<MappingConfig> getMapping(String cluster, String name) {\n        if (!templateService.syncGetEsClusterIsNormal(cluster)) {\n            return Result.buildFail(String.format(\"模版【%s】异常,无法获取mapping信息\", name));\n        }\n        TemplateConfig templateConfig = null;\n        try {\n            templateConfig = templateService.syncGetTemplateConfig(cluster, name);\n        } catch (ESOperateException e) {\n           return Result.buildFail(e.getMessage());\n        }\n        if (templateConfig != null) {\n            MappingConfig mappingConfig = templateConfig.getMappings();\n            if (mappingConfig != null) {\n                mappingConfig.removeDefault();\n                return Result.buildSucc(mappingConfig);\n            }\n        }\n        return Result.buildFail(\"not find template mapping, cluster:\" + cluster + \", template:\" + name);\n    }\n\n    @Override\n    public Result<Void> syncTemplateMapping2Index(String cluster, String index, MappingConfig mappingConfig) throws ESOperateException {\n        if (!indexService.updateIndexMapping(cluster, index, mappingConfig)) {\n            return Result.buildFail(\"update index mapping fail\");\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> checkMapping(String cluster, String template, String mappingsStr, boolean doMerge) {\n        try {\n            MappingConfig mappings = new MappingConfig(getMappingObj(JSON.parseObject(mappingsStr)));\n            if (mappings.haveDefault()) {\n                return Result.build(ResultType.FAIL.getCode(), \"mapping have _default_ type\");\n            }\n\n            return checkMapping(cluster, template, mappings);\n        } catch (JSONException e) {\n            return Result.build(ResultType.FAIL.getCode(), JSON_PARSE_ERROR_TIPS);\n        } catch (Exception t) {\n            return Result.build(ResultType.FAIL.getCode(), t.getMessage());\n        }\n    }\n\n    @Override\n    public Result<MappingConfig> syncMappingConfig(String cluster, String template, String expression,\n                                                   String dataFormat) {\n        try {\n            // 拉取模板mapping\n            Result<MappingConfig> getTemplateMappingResult = getMapping(cluster, template);\n            if (getTemplateMappingResult.failed()) {\n                return getTemplateMappingResult;\n            }\n            // 模板mapping\n            MappingConfig templateMappingConfig = getTemplateMappingResult.getData();\n\n            // 拉取索引mapping, 和模板mapping融合，索引名使用昨天和今天的索引名，逗号分隔\n            String todayIndexName = IndexNameFactory.getNoVersion(expression, dataFormat, 0);\n            String yesterdayIndexName = IndexNameFactory.getNoVersion(expression, dataFormat, -1);\n            String indexName = todayIndexName + \"*,\" + yesterdayIndexName + \"*\";\n\n            Result<List<MappingConfig>> getIndexMappingResult = getIndexMappings(cluster, indexName);\n\n            if (getIndexMappingResult.failed()) {\n                return Result.buildFrom(getIndexMappingResult);\n            }\n\n            List<MappingConfig> indexMappingConfigs = getIndexMappingResult.getData();\n            if (indexMappingConfigs == null || indexMappingConfigs.isEmpty()) {\n                return Result.buildSucc(templateMappingConfig);\n            }\n\n            // 将索引的mapping合并到模板mapping\n            MappingConfig mergeMappingConfig = new MappingConfig(templateMappingConfig.toJson());\n            for (MappingConfig imc : indexMappingConfigs) {\n                mergeMappingConfig.merge(imc);\n            }\n\n            if (checkMappingFieldSize(cluster, template, mergeMappingConfig, MAPPING_FIELD_LIMIT_SIZE)) {\n                return Result.buildFail(\"模版字段个数超过\" + MAPPING_FIELD_LIMIT_SIZE);\n            }\n\n            // index和template定义冲突字段类型，使用template的定义\n            mergeMappingConfig.merge(new MappingConfig(templateMappingConfig.toJson()));\n\n            clearDefaultMapping(templateMappingConfig);\n            clearDefaultMapping(mergeMappingConfig);\n            // mapping有变化，更新\n            if (!mergeMappingConfig.toJson().equals(templateMappingConfig.toJson())) {\n                mergeMultiTypePropertiesToUserDefinedType(indexName, mergeMappingConfig);\n                MappingConfig toUpdateMapping = new MappingConfig(mergeMappingConfig.toJson());\n                Result<Void> result = updateMapping(cluster, template, toUpdateMapping.toJson().toJSONString());\n                if (result.failed()) {\n                    LOGGER.error(\"class=TemplatePhyMappingManagerImpl||method=syncMappingConfig||errMsg={} \"\n                                 + \"{} fail to update mapping, error {}\",\n                        cluster, template, result.getMessage());\n                }\n            }\n\n            return Result.buildSucc(mergeMappingConfig);\n        } catch (Exception t) {\n            return Result.buildFail(t.getMessage());\n        }\n    }\n\n    @Override\n    public Result<Void> addIndexMapping(String cluster, String expression, String dataFormat, int updateDays,\n                                        MappingConfig mappingConfig) throws ESOperateException {\n        for (int i = 1; i <= updateDays; i++) {\n            String indexName = IndexNameFactory.getNoVersion(expression, dataFormat, 2 - i);\n\n            if (!indexService.updateIndexMapping(cluster, indexName, mappingConfig)) {\n                return Result.buildFail(\"update index mapping fail\");\n            }\n        }\n\n        return Result.buildSucc();\n\n    }\n\n    @Override\n    public Result<Void> checkMappingForNew(String name, AriusTypeProperty ariusTypeProperty) {\n        try {\n            MappingConfig mappingConfig = new MappingConfig(ariusTypeProperty.toMappingJSON());\n            Map<String, TypeConfig> typeConfigMap = mappingConfig.getMapping();\n            if (typeConfigMap != null && typeConfigMap.size() > 1) {\n                return Result.build(ResultType.FAIL.getCode(), \"mapping具有多个type, 只能配置一个type\");\n            }\n        } catch (JSONException e) {\n            return Result.build(ResultType.FAIL.getCode(), JSON_PARSE_ERROR_TIPS);\n        } catch (Exception e) {\n            return Result.build(ResultType.FAIL.getCode(), e.getMessage());\n        }\n\n        return checkMapping(null, name, ariusTypeProperty.toMappingJSON().toJSONString(), false);\n\n    }\n\n    /**************************************** private method ****************************************************/\n    private Result<Void> checkMapping(String cluster, String template, MappingConfig mappings) throws ESOperateException {\n        if (isLowVersionCluster(cluster) && !mappings.isEmpty()) {\n            String indexName = String.format(\"indexforcheckmapping_%s_%s\", cluster, template);\n            return preCreateIndexToCheckTemplateConfig(cluster, indexName, mappings,\n                createDefaultSettings(indexName, mappings.getMapping()));\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 低版本ES集群\n     * @param cluster\n     * @return\n     */\n    private boolean isLowVersionCluster(String cluster) {\n        return (StringUtils.isNotBlank(cluster) && AdminConstant.LOW_VERSION_ES_CLUSTER.contains(cluster));\n    }\n\n    /**\n     * 需要通过创建索引的方式来Check模板Mapping的合法性\n     * @param cluster 集群名称\n     * @param template 模板名称\n     * @param mappings 模板Mapping信息\n     * @return\n     */\n    private Result<Void> preCreateIndexToCheckTemplateConfig(String cluster, String template, MappingConfig mappings,\n                                                             Map<String, String> settings) throws ESOperateException {\n\n        IndexConfig indexConfig = new IndexConfig();\n        indexConfig.setMappings(mappings);\n        indexConfig.setSettings(settings);\n\n        return tryCreateIndex(cluster, template, indexConfig);\n    }\n\n    /**\n     * 创建默认模板Setting信息\n     * @param indexName 索引名称\n     * @param typeConfigMap 模板配置\n     * @return\n     */\n    private Map<String, String> createDefaultSettings(String indexName, Map<String, TypeConfig> typeConfigMap) {\n        Map<String, String> settings = Maps.newHashMap();\n        settings.put(\"index.mapping.total_fields.limit\", \"100000\");\n//        if (typeConfigMap != null) {\n//            if (typeConfigMap.containsKey(\"_default_\")) {\n//                if (typeConfigMap.size() == 2) {\n//                    settings.put(AdminConstant.SINGLE_TYPE_KEY, AdminConstant.DEFAULT_SINGLE_TYPE);\n//                }\n//\n//            } else {\n//                if (typeConfigMap.size() == 1) {\n//                    settings.put(AdminConstant.SINGLE_TYPE_KEY, AdminConstant.DEFAULT_SINGLE_TYPE);\n//                }\n//            }\n//\n//            String settingValue = settings.get(AdminConstant.SINGLE_TYPE_KEY);\n//            if (null == settingValue || !AdminConstant.DEFAULT_SINGLE_TYPE.equals(settingValue)) {\n//                LOGGER.warn(\"class=TemplatePhyMappingManagerImpl||method=checkMapping||\"\n//                            + \"singleTypeSettings={}||indexTemplate={}\",\n//                    settings.keySet(), indexName);\n//                settings.put(AdminConstant.SINGLE_TYPE_KEY, AdminConstant.DEFAULT_SINGLE_TYPE);\n//            }\n//        }\n\n        return settings;\n    }\n\n    /**\n     * 获取指定集群指定索引的mapping\n     * @param cluster 集群名\n     * @param indexName 索引名，支持多个，逗号分隔\n     * @return 索引mapping\n     */\n    private Result<List<MappingConfig>> getIndexMappings(String cluster, String indexName) {\n        // 获取索引配置\n        MultiIndexsConfig multiIndexsConfig = indexService.syncGetIndexConfigs(cluster, indexName);\n        if (multiIndexsConfig == null || multiIndexsConfig.getIndexConfigMap() == null) {\n            return Result.buildFail(\"get index config return null\");\n        }\n\n        // 索引配置map，key-索引名，value-索引配置\n        Map<String, IndexConfig> indexConfigMap = multiIndexsConfig.getIndexConfigMap();\n\n        List<MappingConfig> ret = new ArrayList<>();\n        // 遍历索引名，获取索引的mapping配置\n\n        for (Map.Entry<String, IndexConfig> entry : indexConfigMap.entrySet()) {\n            String name = entry.getKey();\n            IndexConfig indexConfig = indexConfigMap.get(name);\n            if (indexConfig == null) {\n                return Result.buildFail(\"get null index config, indexName:\" + name);\n            }\n\n            if (indexConfig.getMappings() == null) {\n                return Result.buildFail(\"get null mapping config, indexName:\" + name);\n            }\n\n            ret.add(indexConfig.getMappings());\n        }\n\n        return Result.buildSucc(ret);\n    }\n\n    /**\n     * 合并多个type属性到默认type\n     * @param indexTemplate 索引名称\n     * @param templateMappingConfig 模板配置\n     */\n    private void mergeMultiTypePropertiesToUserDefinedType(String indexTemplate, MappingConfig templateMappingConfig) {\n        if (templateMappingConfig != null && templateMappingConfig.getMapping() != null) {\n            templateMappingConfig.removeDefault();\n            Map<String, TypeConfig> typeConfigs = templateMappingConfig.getMapping();\n            if (!typeConfigs.isEmpty()) {\n                if (typeConfigs.size() == 1) {\n                    LOGGER.info(\n                        \"class=TemplatePhysicalMappingServiceImpl||method=mergeMultiTypePropertiesToDefaultType||msg=singleType\"\n                                + \"||typeName={}||indexTemplate={}\",\n                        typeConfigs.keySet(), indexTemplate);\n                } else if (typeConfigs.size() == 2\n                           && typeConfigs.containsKey(AdminConstant.DEFAULT_INDEX_MAPPING_TYPE)) {\n                    String userDefinedTypeName = fetchNonDefaultKey(typeConfigs,\n                        AdminConstant.DEFAULT_INDEX_MAPPING_TYPE);\n                    LOGGER\n                        .info(\"class=TemplatePhysicalMappingServiceImpl||method=mergeMultiTypePropertiesToDefaultType||\"\n                              + \"msg=multi type||userDefinedType={}||indexTemplate={}\",\n                            userDefinedTypeName, indexTemplate);\n                    if (StringUtils.isNotBlank(userDefinedTypeName)) {\n                        typeConfigs.get(userDefinedTypeName)\n                            .merge(typeConfigs.get(AdminConstant.DEFAULT_INDEX_MAPPING_TYPE));\n                        typeConfigs.remove(AdminConstant.DEFAULT_INDEX_MAPPING_TYPE);\n                    }\n                } else {\n                    LOGGER.warn(\n                        \"class=TemplatePhysicalMappingServiceImpl||method=mergeMultiTypePropertiesToDefaultTypee||\"\n                                + \"msg=multi user defined types||userDefinedTypes={}||indexTemplate={}\",\n                        typeConfigs.keySet(), indexTemplate);\n                }\n            }\n        }\n    }\n\n    /**\n     * 获取第一个非默认type名称\n     * @param typeConfigs type configs\n     * @param defaultType 默认type名称\n     * @return\n     */\n    private String fetchNonDefaultKey(Map<String, TypeConfig> typeConfigs, String defaultType) {\n        if (typeConfigs == null || StringUtils.isBlank(defaultType)) {\n            return null;\n        }\n\n        for (String typeName : typeConfigs.keySet()) {\n            if (!defaultType.equals(typeName)) {\n                return typeName;\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * 清楚Default Mapping信息\n     *\n     * @param mappingConfig 模板Mapping Config.\n     */\n    private void clearDefaultMapping(MappingConfig mappingConfig) {\n        mappingConfig.removeDefault();\n    }\n\n    private JSONObject getMappingObj(JSONObject obj) {\n        if (obj.containsKey(MAPPING_STR)) {\n            return obj.getJSONObject(MAPPING_STR);\n        }\n\n        if (obj.containsKey(MAPPINGS_STR)) {\n            return obj.getJSONObject(MAPPINGS_STR);\n        }\n\n        return obj;\n    }\n\n    private Result<Void> tryCreateIndex(String clusterName, String indexName, IndexConfig indexConfig) throws ESOperateException {\n        try {\n            indexService.deleteIndex(clusterName, indexName);\n\n            if (!indexService.createIndexWithConfig(clusterName, indexName, indexConfig,3)) {\n                return Result.buildFail(\"create index get false\");\n            }\n\n            return Result.buildSucc();\n        } catch (Exception t) {\n            LOGGER.warn(\n                \"class=TemplatePhyMappingManagerImpl||method=tryCreateIndex||msg=check mapping error, cluster:{}, tmp_index:{}, mapping:{}\",\n                clusterName, indexName, indexConfig.getMappings().toJson(), t);\n\n            StringBuilder sb = new StringBuilder();\n            while (t != null) {\n                sb.append(t.getMessage()).append(\"\\n\");\n                t = (Exception) t.getCause();\n            }\n\n            String message = sb.toString();\n            int i = message.indexOf(\"{\\\"error\\\"\");\n            if (i > 0) {\n                message = message.substring(i);\n            }\n\n            i = message.indexOf(\"400}\");\n            if (i > 0) {\n                message = message.substring(0, i + 4);\n            }\n\n            return Result.buildFail(\"mapping不能创建索引，异常信息:\" + message);\n\n        } finally {\n            if (!indexService.deleteIndex(clusterName, indexName)) {\n                LOGGER.warn(\n                    \"class=TemplatePhyMappingManagerImpl||method=tryCreateIndex||msg=delete index error, indexName:{}\",\n                    indexName);\n            }\n        }\n    }\n\n    private Result<Void> updateMappingCore(String cluster, String template, String mappingStr, Set<String> removeFields,\n                                           boolean doMerge) {\n        try {\n\n            Result<MappingConfig> result = AriusIndexMappingConfigUtils.parseMappingConfig(mappingStr);\n            if (result.failed()) {\n                return Result.buildFrom(result);\n            }\n\n            MappingConfig mappings = result.getData();\n\n            if (mappings.haveDefault()) {\n                return Result.build(ResultType.FAIL.getCode(), \"mapping have _default_ type\");\n            }\n\n            return updateMapping(cluster, template, mappings, removeFields, doMerge);\n        } catch (JSONException e) {\n            return Result.build(ResultType.FAIL.getCode(), JSON_PARSE_ERROR_TIPS);\n        } catch (Exception t) {\n            return Result.build(ResultType.FAIL.getCode(), t.getMessage());\n        }\n    }\n\n    private Result<Void> updateMapping(String cluster, String name, MappingConfig mappings, Set<String> removeFields,\n                                       boolean doMerge) throws ESOperateException {\n        Result<Void> result = checkMapping(cluster, name, mappings);\n        if (result.failed()) {\n            return result;\n        }\n    \n        TemplateConfig templateConfig = null;\n        try {\n            templateConfig = templateService.syncGetTemplateConfig(cluster, name);\n        } catch (ESOperateException e) {\n            return Result.buildFail(e.getMessage());\n        }\n        if (templateConfig == null) {\n            return Result.buildFail(\"模版不存在，tamplate:\" + name);\n        }\n\n        if (doMerge) {\n            templateConfig.getMappings().merge(mappings);\n        } else {\n            mappings.mergeDefault(templateConfig.getMappings());\n            templateConfig.setMappings(mappings);\n        }\n\n        if (CollectionUtils.isNotEmpty(removeFields)) {\n            for (String removeField : removeFields) {\n                templateConfig.getMappings().delFields(Arrays.asList(removeField.split(\"\\\\.\")));\n            }\n        }\n\n        try {\n            if (!templateService.syncUpdateTemplateConfig(cluster, name, templateConfig,\n                AdminESOpRetryConstants.DEFAULT_RETRY_COUNT)) {\n                return Result.buildFail(\"更新模板mapping失败，请稍后重试\");\n            }\n        } catch (ESOperateException e) {\n            return Result.buildFail(\"更新模板mapping失败，errMsg: \" + e.getMessage());\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 检测模版字段数是否超标 超过则记录日志\n     * @param cluster 物理集群名称\n     * @param template 模板名称\n     * @param templateMappingConfig 模板mapping\n     * @param fieldLimitSize 长度限制\n     * @return true/false 是否超标\n     */\n    private boolean checkMappingFieldSize(String cluster, String template, MappingConfig templateMappingConfig,\n                                          Integer fieldLimitSize) {\n        Map<String, TypeConfig> typeConfigMap = templateMappingConfig.getMapping();\n\n        for (TypeConfig typeConfig : typeConfigMap.values()) {\n            if (typeConfig.getProperties() != null && typeConfig.getProperties().getJsonMap().size() > fieldLimitSize) {\n                LOGGER.warn(\n                    \"class=TemplatePhyMappingManagerImpl||method=checkMappingFieldSize||cluster={}||template {} mapping size is {}\",\n                    cluster, template, typeConfig.getProperties().getJsonMap().size());\n                return true;\n            }\n        }\n        return false;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/pipeline/PipelineManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.pipeline;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\n\n/**\n * @author chengxiang, d06679\n * @date 2022/5/13\n */\npublic interface PipelineManager {\n\n    /**\n     * 创建\n     * @param templatePhyId 物理模板id\n     * @return true/false\n     */\n    Result<Void> createPipeline(Integer templatePhyId);\n\n    /**\n     * 修改逻辑字段\n     * @param newTemplate 新逻辑模板\n     * @param oldTemplate 旧逻辑模板\n     * @return true/false\n     */\n    Result<Void> editFromTemplateLogic(IndexTemplate oldTemplate, IndexTemplate newTemplate);\n\n    //////////////////////////SRV\n\n\n\n    /**\n     * 创建\n     * @param indexTemplatePhysicalInfo 物理模板\n     * @param logicWithPhysical 逻辑模板\n     * @return true/false\n     */\n    boolean createPipeline(IndexTemplatePhy indexTemplatePhysicalInfo,\n                           IndexTemplateWithPhyTemplates logicWithPhysical) throws ESOperateException;\n\n\n\n    /**\n     * 修改物理字段\n     * @param oldTemplate 物理模板\n     * @return true/false\n     */\n    boolean editFromTemplatePhysical(IndexTemplatePhy oldTemplate, IndexTemplatePhy newTemplate,\n                                     IndexTemplateWithPhyTemplates logicWithPhysical) throws ESOperateException;\n\n    Integer getRateLimit(IndexTemplatePhy indexTemplatePhysicalMasterInfo);\n\n    /**\n     * 同步pipeline\n     * @param logicTemplateId 物理模板id\n     * @return\n     */\n    Result<Void> syncPipeline(Integer logicTemplateId);\n\n    /**\n     * 删除\n     * @param templatePhyId 物理模板id\n     * @return true/false\n     */\n    Result<Void> deletePipeline(Integer templatePhyId);\n\n    /**\n     * 调整限流值\n     *\n     * @param indexTemplatePhysicalInfo 名字\n     * @param percent 百分比 [-99, 1000]\n     * @return true/false\n     */\n    boolean editRateLimitByPercent(IndexTemplatePhy indexTemplatePhysicalInfo,\n                                   Integer percent) throws ESOperateException;\n\n    /**\n     * 修复模板的pipeline\n     * @param logicId\n     * @return\n     */\n    Result<Void> repairPipeline(Integer logicId) throws ESOperateException;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/pipeline/impl/PipelineManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.pipeline.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.PIPELINE_RATE_LIMIT_MAX_VALUE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser.SYSTEM;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO.DATE_FIELD;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO.DATE_FIELD_FORMAT;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO.EXPIRE_DAY;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO.INDEX_NAME_FORMAT;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO.INDEX_VERSION;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO.MS_TIME_FIELD_ES_FORMAT;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO.MS_TIME_FIELD_PLATFORM_FORMAT;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO.RATE_LIMIT;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO.SECOND_TIME_FIELD_ES_FORMAT;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO.SECOND_TIME_FIELD_PLATFORM_FORMAT;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.impl.BaseTemplateSrvImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.pipeline.PipelineManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ESPipelineProcessor;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.IndexTemplatePhysicalConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.ESPipeline;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.pipeline.ESPipelineService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.List;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author chengxiang, d06679\n * @date 2022/5/13\n */\n@Service\npublic class PipelineManagerImpl extends BaseTemplateSrvImpl implements PipelineManager {\n\n    private static final ILog    LOGGER      = LogFactory.getLog(PipelineManagerImpl.class);\n    private static final Integer RETRY_TIMES = 3;\n\n    @Autowired\n    private ESPipelineService esPipelineService;\n\n    @Override\n    public TemplateServiceEnum templateSrv() {\n        return TemplateServiceEnum.TEMPLATE_PIPELINE;\n    }\n\n    @Override\n    public Result<Void> createPipeline(Integer templatePhyId) {\n        IndexTemplatePhy indexTemplatePhy = indexTemplatePhyService.getTemplateById(templatePhyId.longValue());\n        if (null == indexTemplatePhy) {\n            return Result.buildFail(\"物理模板不存在\");\n        }\n\n        IndexTemplate indexTemplate = indexTemplateService.getLogicTemplateById(indexTemplatePhy.getLogicId());\n        if (null == indexTemplate) {\n            return Result.buildFail(\"逻辑模板不存在\");\n        }\n\n        if (!isTemplateSrvOpen(indexTemplate.getId())) {\n            return Result.buildFail(\"未开启pipeLine服务\");\n        }\n\n        Integer rateLimit = getDynamicRateLimit(indexTemplatePhy);\n        return doCreatePipeline(indexTemplatePhy, indexTemplate, rateLimit);\n    }\n\n    @Override\n    public Result<Void> editFromTemplateLogic(IndexTemplate oldTemplate, IndexTemplate newTemplate) {\n        if (!isTemplateSrvOpen(oldTemplate.getId())) {\n            return Result.buildFail(\"未开启pipeLine服务\");\n        }\n\n        boolean changed = AriusObjUtils.isChanged(newTemplate.getDateField(), oldTemplate.getDateField())\n                          || AriusObjUtils.isChanged(newTemplate.getDateFieldFormat(), oldTemplate.getDateFieldFormat())\n                          || AriusObjUtils.isChanged(newTemplate.getDateFormat(), oldTemplate.getDateFormat())\n                          || AriusObjUtils.isChanged(newTemplate.getExpireTime(), oldTemplate.getExpireTime())\n                          || AriusObjUtils.isChanged(newTemplate.getWriteRateLimit(), oldTemplate.getWriteRateLimit());\n\n        boolean cyclicalRollChanged = oldTemplate.getExpression().endsWith(\"*\")\n                                      && !newTemplate.getExpression().endsWith(\"*\");\n\n        if (!changed && !cyclicalRollChanged) {\n            LOGGER.info(\"class=PipelineManagerImpl||method=editFromTemplateLogic||msg=no changed||pipelineId={}\",\n                oldTemplate.getName());\n            return Result.buildSucc();\n        }\n\n        String dateField = newTemplate.getDateField();\n        String dateFieldFormat = newTemplate.getDateFieldFormat();\n        String dateFormat = newTemplate.getDateFormat();\n\n        Integer expireDay = newTemplate.getExpireTime();\n\n\n        if (cyclicalRollChanged) {\n            dateField = \"\";\n            dateFieldFormat = \"\";\n            dateFormat = \"\";\n            expireDay = -1;\n        }\n\n        List<IndexTemplatePhy> templatePhysicals = indexTemplatePhyService.getTemplateByLogicId(oldTemplate.getId());\n        if (CollectionUtils.isEmpty(templatePhysicals)) {\n            return Result.buildFail(\"物理模板不存在\");\n        }\n\n        for (IndexTemplatePhy physical : templatePhysicals) {\n            Integer rateLimit = getManualRateLimit(physical);\n            try {\n                final ESPipeline esPipeline = new ESPipeline();\n                esPipeline.setCluster(physical.getCluster());\n                esPipeline.setPipelineId(physical.getName());\n                esPipeline.setDateField(dateField);\n                esPipeline.setDateFieldFormat(dateFieldFormat);\n                esPipeline.setDateFormat(dateFormat);\n                esPipeline.setExpireDay(expireDay);\n                esPipeline.setRateLimit(rateLimit);\n                esPipeline.setVersion(physical.getVersion());\n                esPipeline.setIdField(newTemplate.getIdField());\n                esPipeline.setRoutingField(newTemplate.getRoutingField());\n    \n                if (!esPipelineService.save(\"editFromTemplateLogic\", esPipeline, 3)) {\n                    return Result.buildFail(\"edit fail\");\n                }\n            } catch (Exception e) {\n                LOGGER.error(\"class=PipelineManagerImpl||method=editFromTemplateLogic||template={}||errMsg={}\",\n                    physical.getName(), e.getMessage(), e);\n                return Result.buildFail(\"edit fail\");\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    ///////////////////////////private method/////////////////////////////////////////////\n\n    private boolean notConsistent(IndexTemplatePhy indexTemplatePhy, IndexTemplate logicTemplate,\n                                  ESPipelineProcessor esPipelineProcessor) {\n        if (StringUtils.isNotEmpty(logicTemplate.getDateField()) && (!isDateFieldEqual(logicTemplate.getDateField(),\n            esPipelineProcessor.getIndexTemplate().getString(DATE_FIELD)))) {\n            LOGGER.info(\n                \"class=PipelineManagerImpl||method=notConsistent||msg=dateField change||pipelineId={}||templateDateField={}||pipelineDateField={}\",\n                logicTemplate.getName(), logicTemplate.getDateField(),\n                esPipelineProcessor.getIndexTemplate().getString(DATE_FIELD));\n            return true;\n        }\n\n        if (StringUtils.isNotEmpty(logicTemplate.getDateFieldFormat())\n            && (isDateFieldFormatChange(logicTemplate.getDateFieldFormat(),\n                esPipelineProcessor.getIndexTemplate().getString(DATE_FIELD_FORMAT)))) {\n            LOGGER.info(\n                \"class=PipelineManagerImpl||method=notConsistent||msg=dateFieldFormat change||pipelineId={}||dateFieldFormat={}||dateField={}\"\n                        + \"||pipelineDateFieldFormat={}\",\n                logicTemplate.getName(), logicTemplate.getDateFieldFormat(), logicTemplate.getDateField(),\n                esPipelineProcessor.getIndexTemplate().getString(DATE_FIELD_FORMAT));\n            return true;\n        }\n\n        if (StringUtils.isNotEmpty(logicTemplate.getDateFormat()) && (!logicTemplate.getDateFormat()\n            .equals(esPipelineProcessor.getIndexTemplate().getString(INDEX_NAME_FORMAT)))) {\n            LOGGER.info(\n                \"class=PipelineManagerImpl||method=notConsistent||msg=date format change||pipelineId={}||dateFormat={}\"\n                        + \"||pipelineDateFormat={}\",\n                logicTemplate.getName(), logicTemplate.getDateFormat(),\n                esPipelineProcessor.getIndexTemplate().getString(INDEX_NAME_FORMAT));\n            return true;\n        }\n\n        if (isExpireDayChange(logicTemplate.getExpireTime(), logicTemplate.getHotTime(),\n            esPipelineProcessor.getIndexTemplate().getInteger(EXPIRE_DAY))) {\n            LOGGER.info(\n                \"class=PipelineManagerImpl||method=notConsistent||msg=expireDay change||pipelineId={}||expireTime={}\"\n                        + \"||hotTime={}||pipelineExpireDay={}\",\n                logicTemplate.getName(), logicTemplate.getExpireTime(), logicTemplate.getHotTime(),\n                esPipelineProcessor.getIndexTemplate().getInteger(EXPIRE_DAY));\n            return true;\n        }\n\n        if (!indexTemplatePhy.getVersion().equals(esPipelineProcessor.getIndexTemplate().getInteger(INDEX_VERSION))) {\n            LOGGER.info(\"class=PipelineManagerImpl||method=notConsistent||msg=version change||pipelineId={}||version={}\"\n                        + \"||pipelineVersion={}\",\n                logicTemplate.getName(), indexTemplatePhy.getVersion(),\n                esPipelineProcessor.getIndexTemplate().getInteger(INDEX_VERSION));\n            return true;\n        }\n\n        if (isRateLimitNoConsistent(indexTemplatePhy.fetchConfig(), esPipelineProcessor.getThrottle())) {\n            LOGGER.info(\n                \"class=PipelineManagerImpl||method=notConsistent||msg=rateLimit change||pipelineId={}||physicalConfig={}||throttle={}\",\n                logicTemplate.getName(), indexTemplatePhy.getConfig(), esPipelineProcessor.getThrottle());\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * 比较日期字段是否一致\n     *\n     * @param logicWithPhysicalDateField 逻辑模板日期字段\n     * @param pipelineDateField          pipeline日期字段\n     * @return\n     */\n    private boolean isDateFieldEqual(String logicWithPhysicalDateField, String pipelineDateField) {\n        if (StringUtils.isNotBlank(logicWithPhysicalDateField) && StringUtils.isNotBlank(pipelineDateField)) {\n            return logicWithPhysicalDateField.equals(pipelineDateField);\n        }\n        return false;\n    }\n\n    /**\n     * 校验日期字段格式是否改变\n     *\n     * @param dateFieldFormat         日期字段格式\n     * @return\n     */\n    private boolean isDateFieldFormatChange(String dateFieldFormat, String pipelineDateFieldFormat) {\n        if (StringUtils.equals(MS_TIME_FIELD_PLATFORM_FORMAT,dateFieldFormat)) {\n            dateFieldFormat = MS_TIME_FIELD_ES_FORMAT;\n        } else if (StringUtils.equals(SECOND_TIME_FIELD_PLATFORM_FORMAT,dateFieldFormat)) {\n            dateFieldFormat = SECOND_TIME_FIELD_ES_FORMAT;\n        }\n        return !StringUtils.equals(dateFieldFormat,pipelineDateFieldFormat);\n    }\n\n    /**\n     * 校验expire day是否改变\n     *\n     * @param expireTime        过期时间\n     * @param hotTime           热保存天数\n     * @param pipelineExpireDay pipeline过期天数\n     * @return\n     */\n    private boolean isExpireDayChange(Integer expireTime, Integer hotTime, Integer pipelineExpireDay) {\n        return pipelineExpireDay.equals(expireTime);\n    }\n\n    /**\n     * 索引模板流控ES集群和MySQL元数据是否一致\n     * @param config 物理模板配置\n     * @param throttle 流控相关信息\n     * @return\n     */\n    private boolean isRateLimitNoConsistent(IndexTemplatePhysicalConfig config, JSONObject throttle) {\n        if (config == null || throttle == null) {\n            return false;\n        }\n\n        return (config.getPipeLineRateLimit() != null\n                && !config.getPipeLineRateLimit().equals(throttle.getInteger(\"rate_limit\")));\n    }\n\n    /**\n     * 根据逻辑模板更新物理模板的pipeline 配置\n     * @param indexTemplatePhy\n     * @param logicTemplate\n     * @param rateLimit\n     * @return\n     */\n    private Result<Void> doCreatePipeline(IndexTemplatePhy indexTemplatePhy, IndexTemplate logicTemplate,\n                                          Integer rateLimit) {\n        String cluster = indexTemplatePhy.getCluster();\n        String pipelineId = indexTemplatePhy.getName();\n        String dateField = logicTemplate.getDateField();\n        String dateFieldFormat = logicTemplate.getDateFieldFormat();\n        String dateFormat = logicTemplate.getDateFormat();\n\n        Integer version = indexTemplatePhy.getVersion();\n        String idField = logicTemplate.getIdField();\n        String routingField = logicTemplate.getRoutingField();\n        Integer expireDay =  logicTemplate.getExpireTime();\n\n        LOGGER.info(\n            \"class=PipelineManagerImpl||method=doCreatePipeline||cluster={}||pipelineId={}||dateField={}||dateFormat={}||expireDay={}||rateLimit={}||version={}\",\n            cluster, pipelineId, dateField, dateFormat, expireDay, rateLimit, version);\n\n        // 保存限流值到DB\n        saveRateLimitToDB(indexTemplatePhy, rateLimit);\n\n        try {\n            final ESPipeline esPipeline = new ESPipeline();\n            esPipeline.setCluster(cluster);\n            esPipeline.setPipelineId(pipelineId);\n            esPipeline.setDateField(dateField);\n            esPipeline.setDateFieldFormat(dateFieldFormat);\n            esPipeline.setDateFormat(dateFormat);\n            esPipeline.setExpireDay(expireDay);\n            esPipeline.setRateLimit(rateLimit);\n            esPipeline.setVersion(version);\n            esPipeline.setIdField(idField);\n            esPipeline.setRoutingField(routingField);\n            return Result.build(esPipelineService.save(\"doCreatePipeline\",esPipeline,3));\n        } catch (Exception e) {\n            LOGGER.error(\"class=PipelineManagerImpl||method=doCreatePipeline||error\", e);\n            return Result.buildFail();\n        }\n    }\n\n    private void saveRateLimitToDB(IndexTemplatePhy physical, Integer rateLimit) {\n        // 保存数据库\n        IndexTemplatePhysicalConfig physicalConfig = JSON.parseObject(physical.getConfig(),\n            IndexTemplatePhysicalConfig.class);\n        if (null == physicalConfig) {\n            physicalConfig = new IndexTemplatePhysicalConfig();\n        }\n\n        physicalConfig.setPipeLineRateLimit(rateLimit);\n        IndexTemplatePhyPO physicalPO = new IndexTemplatePhyPO();\n        physicalPO.setId(physical.getId());\n        physicalPO.setConfig(JSON.toJSONString(physicalConfig));\n\n        // 避免出现死循环风险，这里直接使用DAO，历史原因\n        indexTemplatePhyService.updateByIndexTemplatePhyPO(physicalPO);\n\n    }\n\n    private Integer getDynamicRateLimit(IndexTemplatePhy indexTemplatePhy) {\n        Integer rateLimit = PIPELINE_RATE_LIMIT_MAX_VALUE;\n\n        if (StringUtils.isNotBlank(indexTemplatePhy.getConfig())) {\n            IndexTemplatePhysicalConfig physicalConfig = JSON.parseObject(indexTemplatePhy.getConfig(),\n                IndexTemplatePhysicalConfig.class);\n            if (null == physicalConfig) {\n                return rateLimit;\n            }\n\n            if (null != physicalConfig.getManualPipeLineRateLimit()\n                && physicalConfig.getManualPipeLineRateLimit() > 0) {\n                rateLimit = physicalConfig.getManualPipeLineRateLimit();\n            }\n\n            if (null != physicalConfig.getPipeLineRateLimit()) {\n                rateLimit = (physicalConfig.getPipeLineRateLimit() < rateLimit) ? physicalConfig.getPipeLineRateLimit()\n                    : rateLimit;\n            }\n        }\n\n        return rateLimit;\n    }\n\n\n\n    /**\n     * 创建\n     *\n     * @param indexTemplatePhysicalInfo 物理模板\n     * @param logicWithPhysical     逻辑模板\n     * @return true/false\n     */\n    @Override\n    public boolean createPipeline(IndexTemplatePhy indexTemplatePhysicalInfo,\n                                  IndexTemplateWithPhyTemplates logicWithPhysical) throws ESOperateException {\n        if (!isTemplateSrvOpen(indexTemplatePhysicalInfo.getLogicId())) {\n            return false;\n        }\n\n        Integer rateLimit = getDynamicQuotaRateLimit(indexTemplatePhysicalInfo);\n\n        return doCreatePipeline(indexTemplatePhysicalInfo, logicWithPhysical, rateLimit);\n    }\n\n\n\n    /**\n     * 修改物理字段\n     *\n     * @param oldTemplate 物理模板\n     * @return true/false\n     */\n    @Override\n    public boolean editFromTemplatePhysical(IndexTemplatePhy oldTemplate, IndexTemplatePhy newTemplate,\n                                            IndexTemplateWithPhyTemplates logicWithPhysical) throws ESOperateException {\n        boolean changed = AriusObjUtils.isChanged(newTemplate.getVersion(), oldTemplate.getVersion());\n\n        if (!changed) {\n            LOGGER.info(\n                \"class=TemplatePipelineManagerImpl||method=editFromTemplatePhysical||msg=no changed||pipelineId={}||version={}\",\n                oldTemplate.getName(), oldTemplate.getVersion());\n            return true;\n        }\n\n        LOGGER.info(\n            \"class=TemplatePipelineManagerImpl||method=editFromTemplatePhysical||cluster={}||pipelineId={}||version={}\",\n            newTemplate.getCluster(), newTemplate.getName(), newTemplate.getVersion());\n    \n        Integer rateLimit = getManualRateLimit(newTemplate);\n        final ESPipeline esPipeline = new ESPipeline();\n        esPipeline.setCluster(newTemplate.getCluster());\n        esPipeline.setPipelineId(newTemplate.getName());\n        esPipeline.setDateField(logicWithPhysical.getDateField());\n        esPipeline.setDateFieldFormat(logicWithPhysical.getDateFieldFormat());\n        esPipeline.setDateFormat(logicWithPhysical.getDateFormat());\n        esPipeline.setExpireDay( logicWithPhysical.getExpireTime());\n        esPipeline.setRateLimit(rateLimit);\n        esPipeline.setVersion(newTemplate.getVersion());\n        esPipeline.setIdField(logicWithPhysical.getIdField());\n        esPipeline.setRoutingField(logicWithPhysical.getRoutingField());\n        return esPipelineService.save(\"editFromTemplatePhysical\", esPipeline, 3);\n       \n    }\n\n    @Override\n    public Integer getRateLimit(IndexTemplatePhy indexTemplatePhysicalMasterInfo) {\n        ESPipelineProcessor esPipelineProcessor = esPipelineService.get(indexTemplatePhysicalMasterInfo.getCluster(),\n            indexTemplatePhysicalMasterInfo.getName());\n        return null != esPipelineProcessor ? esPipelineProcessor.getThrottle().getInteger(RATE_LIMIT) : 0;\n    }\n\n    @Override\n    public Result<Void> syncPipeline(Integer logicTemplateId) {\n    \n      \n        IndexTemplate logicTemplate = indexTemplateService.getLogicTemplateById(logicTemplateId);\n        if (null == logicTemplate) {\n            return Result.buildFail(\"逻辑模板不存在\");\n        }\n          if (!isTemplateSrvOpen(logicTemplateId)) {\n            return Result.buildFail(\"未开启pipeLine服务\");\n        }\n        final List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.getTemplateByLogicId(logicTemplateId);\n        if (CollectionUtils.isEmpty(templatePhyList)) {\n            return Result.buildFail(\"物理模板不存在\");\n        }\n        \n        for (IndexTemplatePhy indexTemplatePhy : templatePhyList) {\n            try {\n                esPipelineService.get(indexTemplatePhy.getCluster(),\n                        indexTemplatePhy.getName());\n                ESPipelineProcessor esPipelineProcessor = esPipelineService.get(indexTemplatePhy.getCluster(),\n                        indexTemplatePhy.getName());\n                if (esPipelineProcessor == null) {\n                    // pipeline processor不存在，创建\n                    LOGGER.info(\n                            \"class=TemplatePipelineManagerImpl||method=syncPipeline||template={}||msg=pipeline not exist, recreate\",\n                            indexTemplatePhy.getName());\n                    final Result<Void> pipeline = createPipeline(indexTemplatePhy.getId().intValue());\n                    if (pipeline.failed()){\n                        LOGGER.warn(\n                                \"class=TemplatePipelineManagerImpl||method=syncPipeline||indexTemplatePhy={}||errMsg={}\",\n                                indexTemplatePhy.getCluster(), indexTemplatePhy.getName(), pipeline.getMessage());\n                        //创建失败了，就不应该走入下面的逻辑了，直接跳过就可以了\n                        continue;\n                    }\n                    //重新获取一遍，否则下层的逻辑是npe的状态；且此刻默认是能够获取到esPipelineProcessor；如果获取不到，那么下面逻辑就应该报错npe的问题\n                    esPipelineProcessor= esPipelineService.get(indexTemplatePhy.getCluster(),\n                        indexTemplatePhy.getName());\n                   \n                }\n                // pipeline processor不一致（有变化），以新元数据创建\n                if (notConsistent(indexTemplatePhy, logicTemplate, esPipelineProcessor)) {\n                    LOGGER.info(\n                            \"class=TemplatePipelineManagerImpl||method=syncPipeline||template={}||msg=doCreatePipeline\",\n                            indexTemplatePhy.getName());\n                    final Result<Void> result = doCreatePipeline(indexTemplatePhy, logicTemplate,\n                            esPipelineProcessor.getThrottle().getInteger(\"rate_limit\"));\n                    if (result.failed()) {\n                        LOGGER.warn(\n                                \"class=TemplatePipelineManagerImpl||method=syncPipeline||indexTemplatePhy={}||errMsg={}\",\n                                indexTemplatePhy.getCluster(), indexTemplatePhy.getName(), result.getMessage());\n                    }\n                }\n            } catch (Exception e) {\n                LOGGER.error(\"class=TemplatePipelineManagerImpl||method=syncPipeline||template={}\",\n                        indexTemplatePhy.getCluster(), e);\n                return Result.buildFail(\"sync fail\");\n            }\n    \n        }\n    \n        return Result.buildSucc();\n       \n\n    }\n\n    @Override\n    public Result<Void> deletePipeline(Integer templatePhyId) {\n        IndexTemplatePhy indexTemplatePhy = indexTemplatePhyService.getTemplateById(templatePhyId.longValue());\n        if (null == indexTemplatePhy) {\n            return Result.buildFail(\"物理模板不存在\");\n        }\n\n        if (!isTemplateSrvOpen(indexTemplatePhy.getLogicId())) {\n            return Result.buildFail(\"未开启pipeLine服务\");\n        }\n\n        try {\n            return Result.build(esPipelineService.delete(indexTemplatePhy.getCluster(), indexTemplatePhy.getName(),\n                    \"deletePipeline\", RETRY_TIMES));\n        } catch (Exception e) {\n            LOGGER.error(\"class=PipelineManagerImpl||method=deletePipeline||template={}||errMsg={}\",\n                indexTemplatePhy.getName(), e.getMessage(), e);\n            return Result.buildFail(\"delete fail\");\n        }\n\n    }\n\n    @Override\n    public boolean editRateLimitByPercent(IndexTemplatePhy templatePhysical,\n                                          Integer percent) throws ESOperateException {\n        if (!isTemplateSrvOpen(templatePhysical.getLogicId())) {\n            return false;\n        }\n\n        if (percent == 0) {\n            return true;\n        }\n\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(templatePhysical.getLogicId());\n\n        Integer manualRateLimit = getManualRateLimit(templatePhysical);\n        Integer rateLimitOld = getDynamicQuotaRateLimit(templatePhysical);\n\n        int rateLimitNew = 1 + (int) (rateLimitOld * ((100.0 + percent) / 100.0));\n\n        rateLimitNew = (rateLimitNew < 1) ? 1 : rateLimitNew;\n        rateLimitNew = (rateLimitNew > manualRateLimit) ? manualRateLimit : rateLimitNew;\n\n        LOGGER.info(\n            \"class=TemplatePipelineManagerImpl||method=editRateLimitByPercent||cluster={}||pipelineId={}||percent={}||rateLimit={}->{}\",\n            templatePhysical.getCluster(), templatePhysical.getName(), percent, rateLimitOld, rateLimitNew);\n\n        int finalRateLimitNew = rateLimitNew;\n\n        if (rateLimitOld != rateLimitNew) {\n            // 保存到DB\n            saveRateLimitToDB(templatePhysical, finalRateLimitNew);\n            final ESPipeline esPipeline = new ESPipeline();\n            esPipeline.setCluster(templatePhysical.getCluster());\n            esPipeline.setPipelineId(templatePhysical.getName());\n            esPipeline.setDateField(templateLogicWithPhysical.getDateField());\n            esPipeline.setDateFieldFormat(templateLogicWithPhysical.getDateFieldFormat());\n            esPipeline.setDateFormat(templateLogicWithPhysical.getDateFormat());\n            esPipeline.setExpireDay(templateLogicWithPhysical.getExpireTime());\n            esPipeline.setRateLimit(finalRateLimitNew);\n            esPipeline.setVersion(templatePhysical.getVersion());\n            esPipeline.setIdField(templateLogicWithPhysical.getIdField());\n            esPipeline.setRoutingField(templateLogicWithPhysical.getRoutingField());\n            boolean esSuccess = esPipelineService.save(\"editFromTemplatePhysical\", esPipeline, 3);\n            \n            if (esSuccess) {\n                operateRecordService.saveOperateRecordWithSchedulingTasks(\n                        String.format(\"rateLimit:%s->%s\", rateLimitOld, rateLimitNew), SYSTEM.getDesc(),\n                        AuthConstant.SUPER_PROJECT_ID, templatePhysical.getId(),\n                        OperateTypeEnum.TEMPLATE_MANAGEMENT_INFO_MODIFY);\n            }\n            return esSuccess;\n        }\n        return true;\n    }\n\n    @Override\n    public Result<Void> repairPipeline(Integer logicId) throws ESOperateException {\n        IndexTemplateWithPhyTemplates logicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (logicWithPhysical == null) {\n            return Result.buildFail(\"索引模板不存在\");\n        }\n\n        if (!isTemplateSrvOpen(logicId)) {\n            return Result.buildFail(String.format(\"%s没有开启%s\", logicWithPhysical.getName(), templateSrv().getServiceName()));\n        }\n\n        for (IndexTemplatePhy templatePhysical : logicWithPhysical.getPhysicals()) {\n            boolean result = createPipeline(templatePhysical, logicWithPhysical);\n            if (!result) {\n                return Result.buildFail(String.format(\"更新pipeline失败，name=%s, cluster=%s\", templatePhysical.getName(),\n                    templatePhysical.getCluster()));\n            }\n        }\n\n        IndexTemplatePO editTemplate = indexTemplateService.getLogicTemplatePOById(logicId);\n\n        editTemplate.setIngestPipeline(logicWithPhysical.getName());\n\n        if (indexTemplateService.update(editTemplate)) {\n            return Result.buildFail(String.format(\"更新模板pipeline字段失败，id=%d\", editTemplate.getId()));\n        }\n        return Result.build(true);\n    }\n\n    /**************************************** private method ****************************************************/\n\n    private Integer getManualRateLimit(IndexTemplatePhysicalConfig physicalConfig) {\n        Integer rateLimit;\n\n        if (null == physicalConfig.getManualPipeLineRateLimit() || physicalConfig.getManualPipeLineRateLimit() < 0) {\n            rateLimit = PIPELINE_RATE_LIMIT_MAX_VALUE;\n        } else {\n            rateLimit = physicalConfig.getManualPipeLineRateLimit();\n        }\n\n        return rateLimit;\n    }\n\n    private Integer getManualRateLimit(IndexTemplatePhy templatePhysical) {\n        Integer rateLimit = PIPELINE_RATE_LIMIT_MAX_VALUE;\n\n        if (StringUtils.isNotBlank(templatePhysical.getConfig())) {\n            IndexTemplatePhysicalConfig physicalConfig = JSON.parseObject(templatePhysical.getConfig(),\n                IndexTemplatePhysicalConfig.class);\n\n            rateLimit = getManualRateLimit(physicalConfig);\n        }\n\n        return rateLimit;\n    }\n\n    private Integer getDynamicQuotaRateLimit(IndexTemplatePhy templatePhysical) {\n        Integer rateLimit = PIPELINE_RATE_LIMIT_MAX_VALUE;\n\n        if (StringUtils.isNotBlank(templatePhysical.getConfig())) {\n            IndexTemplatePhysicalConfig physicalConfig = JSON.parseObject(templatePhysical.getConfig(),\n                IndexTemplatePhysicalConfig.class);\n            rateLimit = getManualRateLimit(templatePhysical);\n\n            if (physicalConfig.getPipeLineRateLimit() != null) {\n                rateLimit = (physicalConfig.getPipeLineRateLimit() < rateLimit) ? physicalConfig.getPipeLineRateLimit()\n                    : rateLimit;\n            }\n        }\n\n        return rateLimit;\n    }\n\n    private boolean doCreatePipeline(IndexTemplatePhy indexTemplatePhysicalInfo,\n                                     IndexTemplateWithPhyTemplates logicWithPhysical,\n                                     Integer rateLimit) throws ESOperateException {\n        String cluster = indexTemplatePhysicalInfo.getCluster();\n        String pipelineId = indexTemplatePhysicalInfo.getName();\n        String dateField = logicWithPhysical.getDateField();\n        String dateFieldFormat = logicWithPhysical.getDateFieldFormat();\n        String dateFormat = logicWithPhysical.getDateFormat();\n\n        Integer version = indexTemplatePhysicalInfo.getVersion();\n        String idField = logicWithPhysical.getIdField();\n        String routingField = logicWithPhysical.getRoutingField();\n        Integer expireDay = logicWithPhysical.getExpireTime();\n\n        LOGGER.info(\n            \"class=TemplatePipelineManagerImpl||method=createPipeline||cluster={}||pipelineId={}||dateField={}||dateFormat={}||expireDay={}||rateLimit={}||version={}\",\n            cluster, pipelineId, dateField, dateFormat, expireDay, rateLimit, version);\n\n        // 保存限流值到DB\n        saveRateLimitToDB(indexTemplatePhysicalInfo, rateLimit);\n        final ESPipeline esPipeline = new ESPipeline();\n        esPipeline.setCluster(cluster);\n        esPipeline.setPipelineId(pipelineId);\n        esPipeline.setDateField(dateField);\n        esPipeline.setDateFieldFormat(dateFieldFormat);\n        esPipeline.setDateFormat(dateFormat);\n        esPipeline.setExpireDay(expireDay);\n        esPipeline.setRateLimit(rateLimit);\n        esPipeline.setVersion(version);\n        esPipeline.setIdField(idField);\n        esPipeline.setRoutingField(routingField);\n    \n        return esPipelineService.save(\"createPipeline\", esPipeline, RETRY_TIMES);\n    }\n\n \n\n\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/precreate/PreCreateManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.precreate;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\n\n/**\n * @author chengxiang\n * @date 2022/5/11\n */\npublic interface PreCreateManager {\n\n    /**\n     * 索引预先创建\n     *\n     * @param logicTemplateId 逻辑模板id\n     * @return Result 创建是否成功\n     */\n    Result<Boolean> preCreateIndex(Integer logicTemplateId) throws ESOperateException;\n\n    /**\n     * 异步创建今明天索引\n     * @param physicalId 物理模板id\n     */\n    void asyncCreateTodayAndTomorrowIndexByPhysicalId(Long physicalId);\n\n    /**\n     * 同步创建今天索引\n     *\n     * @param physicalId 物理模版id\n     * @param version    版本\n     * @return boolean\n     * @throws ESOperateException esoperate例外\n     */\n    boolean syncCreateTodayIndexByPhysicalId(Long physicalId, int version) throws ESOperateException;\n\n        ////////////////////srv\n    /**\n    * 索引预先创建\n    * @param cluster 集群\n    * @param retryCount 重试次数\n    * @return true/false\n    * @throws AdminOperateException\n    */\n    @Deprecated\n    boolean preCreateIndex(String cluster, int retryCount);\n\n    /**\n     * 重建明天索引\n     * @param logicId 逻辑模板id\n     * @param retryCount 重试次数\n     * @return true/false\n     */\n    boolean reBuildTomorrowIndex(Integer logicId, int retryCount) throws ESOperateException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/precreate/impl/PreCreateManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.precreate.impl;\n\nimport java.util.List;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.impl.BaseTemplateSrvImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.dcdr.TemplateDCDRManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.precreate.PreCreateManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.threadpool.AriusOpThreadPool;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameFactory;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.IndexConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.TemplateConfig;\n\n/**\n * @author chengxiang, zqr\n * @date 2022/5/11\n */\n@Service\npublic class PreCreateManagerImpl extends BaseTemplateSrvImpl implements PreCreateManager {\n\n    private final static Integer RETRY_TIMES  = 3;\n    private final static Double  SUCCESS_RATE = 0.7;\n    public static final String   START        = \"*\";\n\n    @Autowired\n    private TemplateDCDRManager  templateDcdrManager;\n\n    @Autowired\n    private ESIndexService       esIndexService;\n    @Autowired\n    private ESTemplateService    esTemplateService;\n\n    @Autowired\n    private AriusOpThreadPool    ariusOpThreadPool;\n\n    @Override\n    public TemplateServiceEnum templateSrv() {\n        return TemplateServiceEnum.TEMPLATE_PRE_CREATE;\n    }\n    \n\n    @Override\n    public Result<Boolean> preCreateIndex(Integer logicTemplateId) throws ESOperateException {\n        if (Boolean.FALSE.equals(isTemplateSrvOpen(logicTemplateId))) {\n            return Result.buildSucc();\n        }\n\n        List<IndexTemplatePhy> templatePhyList = indexTemplatePhyService.getTemplateByLogicId(logicTemplateId);\n        if (CollectionUtils.isEmpty(templatePhyList)) {\n            LOGGER.info(\n                \"class=PreCreateManagerImpl||method=preCreateIndex||logicTemplateId={}||msg=PreCreateIndexTask no template\",\n                logicTemplateId);\n            return Result.buildSucc();\n        }\n\n        Integer succeedCount = 0;\n        for (IndexTemplatePhy templatePhy : templatePhyList) {\n                if (syncCreateTomorrowIndexByPhysicalId(templatePhy.getId())) {\n                    succeedCount++;\n                } else {\n                    LOGGER.warn(\n                        \"class=PreCreateManagerImpl||method=preCreateIndex||logicTemplateId={}||physicalTemplateId={}||msg=preCreateIndex fail\",\n                        logicTemplateId, templatePhy.getId());\n                }\n          \n        }\n\n        return Result.build(( succeedCount * 1.0 / templatePhyList.size() > SUCCESS_RATE));\n    }\n\n    @Override\n    public void asyncCreateTodayAndTomorrowIndexByPhysicalId(Long physicalId) {\n        ariusOpThreadPool.execute(() -> {\n            try {\n                //lbq这里睡眠一秒钟，保证上层方法数据事物已经提交；\n                Thread.sleep(1000L);\n                syncCreateTodayIndexByPhysicalId(physicalId);\n                syncCreateTomorrowIndexByPhysicalId(physicalId);\n            } catch (ESOperateException | InterruptedException e) {\n                LOGGER.error(\n                    \"class=PreCreateManagerImpl||method=asyncCreateTodayIndexAsyncByPhysicalId||errMsg={}||physicalId={}\",\n                    e.getMessage(), physicalId, e);\n            }\n        });\n    }\n\n    ///////////////////////////////private method/////////////////////////////////////////////\n    /**\n     * 同步创建明天索引\n     *\n     * @param physicalId 物理模板id\n     * @return result\n     * @throws ESOperateException\n     */\n    private boolean syncCreateTomorrowIndexByPhysicalId(Long physicalId) throws ESOperateException {\n        IndexTemplatePhyWithLogic physicalWithLogic = indexTemplatePhyService.getTemplateWithLogicById(physicalId);\n        if (physicalWithLogic == null || !physicalWithLogic.hasLogic()) {\n            return false;\n        }\n\n        // 如果是从模板不需要预先创建\n        // 这里耦合了dcdr的逻辑，应该通过接口解耦\n        if (physicalWithLogic.getRole().equals(TemplateDeployRoleEnum.SLAVE.getCode())\n            && templateDcdrManager.clusterSupport(physicalWithLogic.getCluster())) {\n            return true;\n        }\n\n        String tomorrowIndexName = IndexNameFactory.get(physicalWithLogic.getExpression(),\n            physicalWithLogic.getLogicTemplate().getDateFormat(), 1, physicalWithLogic.getVersion());\n        return createIndex(tomorrowIndexName, physicalWithLogic, RETRY_TIMES);\n    }\n    /**\n     * 同步创建今天索引\n     *\n     * @param physicalId 物理模板id\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean syncCreateTodayIndexByPhysicalId(Long physicalId, int version) throws ESOperateException {\n        IndexTemplatePhyWithLogic physicalWithLogic = indexTemplatePhyService.getTemplateWithLogicById(physicalId);\n        if (physicalWithLogic == null || !physicalWithLogic.hasLogic()) {\n            return false;\n        }\n        String todayIndexName = IndexNameFactory.get(physicalWithLogic.getExpression(),\n                physicalWithLogic.getLogicTemplate().getDateFormat(), 0, version);\n        return createIndex(todayIndexName, physicalWithLogic, RETRY_TIMES);\n    }\n\n    /**\n     * 同步创建今天索引\n     * @param physicalId 物理模板id\n     * @throws ESOperateException\n     */\n    private boolean syncCreateTodayIndexByPhysicalId(Long physicalId) throws ESOperateException {\n        IndexTemplatePhyWithLogic physicalWithLogic = indexTemplatePhyService.getTemplateWithLogicById(physicalId);\n        if (physicalWithLogic == null || !physicalWithLogic.hasLogic()) {\n            return false;\n        }\n        String todayIndexName = IndexNameFactory.get(physicalWithLogic.getExpression(),\n            physicalWithLogic.getLogicTemplate().getDateFormat(), 0, physicalWithLogic.getVersion());\n        return createIndex(todayIndexName, physicalWithLogic, RETRY_TIMES);\n    }\n\n    private boolean createIndex(String indexName, IndexTemplatePhyWithLogic physicalWithLogic,\n                                int retryCount) throws ESOperateException {\n        IndexConfig indexConfig = null;\n        if (!StringUtils.endsWith(physicalWithLogic.getExpression(), START) && physicalWithLogic.getVersion() > 0) {\n            indexConfig = generateIndexConfig(physicalWithLogic);\n        }\n        if (null != indexConfig) {\n            return esIndexService.syncCreateIndex(physicalWithLogic.getCluster(), indexName, indexConfig, retryCount);\n        }\n        return esIndexService.syncCreateIndex(physicalWithLogic.getCluster(), indexName, retryCount);\n    }\n\n    private IndexConfig generateIndexConfig(IndexTemplatePhyWithLogic physicalWithLogic) throws ESOperateException {\n        TemplateConfig templateConfig = esTemplateService.syncGetTemplateConfig(physicalWithLogic.getCluster(),\n                physicalWithLogic.getName());\n        if (null == templateConfig) {\n            throw new ESOperateException(\"获取模板配置失败，请稍后重试\");\n        }\n        IndexConfig indexConfig = new IndexConfig();\n        indexConfig.setMappings(templateConfig.getMappings());\n        indexConfig.setSettings(templateConfig.getSetttings());\n        indexConfig.setAliases(templateConfig.getAliases());\n        indexConfig.setVersion(templateConfig.getVersion());\n        return indexConfig;\n    }\n\n    /**\n     * 同步删除明天索引\n     * @param physicalId 物理模板id\n     * @param retryCount 重试次数\n     * @return\n     * @throws ESOperateException\n     */\n    private boolean syncDeleteTomorrowIndexByPhysicalId(Long physicalId, int retryCount) throws ESOperateException {\n        IndexTemplatePhyWithLogic physicalWithLogic = indexTemplatePhyService.getTemplateWithLogicById(physicalId);\n        if (physicalWithLogic == null || !physicalWithLogic.hasLogic()) {\n            return false;\n        }\n\n        String tomorrowIndexName = IndexNameFactory.get(physicalWithLogic.getExpression(),\n            physicalWithLogic.getLogicTemplate().getDateFormat(), 1, physicalWithLogic.getVersion());\n        String todayIndexName = IndexNameFactory.get(physicalWithLogic.getExpression(),\n            physicalWithLogic.getLogicTemplate().getDateFormat(), 0, physicalWithLogic.getVersion());\n\n        if (tomorrowIndexName.equals(todayIndexName)) {\n            return false;\n        }\n\n        return esIndexService.syncDelIndex(physicalWithLogic.getCluster(), tomorrowIndexName, retryCount);\n    }\n\n    /////////////////////////////srv\n    @Override\n    public boolean preCreateIndex(String phyCluster, int retryCount) {\n        \n\n        List<IndexTemplatePhy> physicals = indexTemplatePhyService.getNormalTemplateByCluster(phyCluster);\n        if (CollectionUtils.isEmpty(physicals)) {\n            LOGGER.info(\n                \"class=ESClusterPhyServiceImpl||method=preCreateIndex||cluster={}||msg=PreCreateIndexTask no template\",\n                phyCluster);\n            return true;\n        }\n       \n        int succeedCount = 0;\n        for (IndexTemplatePhy physical : physicals) {\n            if (Boolean.FALSE.equals(isTemplateSrvOpen(physical.getLogicId()))) {\n                continue;\n            }\n            \n            IndexTemplateConfig config = indexTemplateService.getTemplateConfig(physical.getLogicId());\n            if (config == null || !config.getPreCreateFlags()) {\n                LOGGER.warn(\n                    \"class=ESClusterPhyServiceImpl||method=preCreateIndex||cluster={}||template={}||msg=skip preCreateIndex\",\n                    phyCluster, physical.getName());\n                continue;\n            }\n\n            try {\n                if (syncCreateTomorrowIndexByPhysicalId(physical.getId())) {\n                    succeedCount++;\n                } else {\n                    LOGGER.warn(\n                        \"class=ESClusterPhyServiceImpl||method=preCreateIndex||cluster={}||template={}||msg=preCreateIndex fail\",\n                        phyCluster, physical.getName());\n                }\n            } catch (Exception e) {\n                LOGGER.error(\"class=ESClusterPhyServiceImpl||method=preCreateIndex||errMsg={}||cluster={}||template={}\",\n                    e.getMessage(), phyCluster, physical.getName(), e);\n            }\n        }\n\n        return succeedCount * 1.0 / physicals.size() > 0.7;\n    }\n\n    /**\n     * 重建明天索引\n     *\n     * @param logicId    逻辑模板id\n     * @param retryCount 重试次数\n     * @return true/false\n     */\n    @Override\n    public boolean reBuildTomorrowIndex(Integer logicId, int retryCount) throws ESOperateException {\n        List<IndexTemplatePhy> indexTemplatePhies = indexTemplatePhyService.getTemplateByLogicId(logicId);\n        if (CollectionUtils.isEmpty(indexTemplatePhies)) {\n            return true;\n        }\n\n        boolean succ = true;\n        for (IndexTemplatePhy indexTemplatePhy : indexTemplatePhies) {\n            if (syncDeleteTomorrowIndexByPhysicalId(indexTemplatePhy.getId(), retryCount)) {\n                succ = succ && syncCreateTomorrowIndexByPhysicalId(indexTemplatePhy.getId());\n            }\n        }\n\n        return succ;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/setting/TemplateLogicSettingsManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.setting;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhySetting;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateSettingVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusIndexTemplateSetting;\n\n/**\n * 逻辑模板settings service\n * @author wangshu\n * @date 2020/09/02\n */\npublic interface TemplateLogicSettingsManager {\n\n    ///**\n    // * 修改模板Setting\n    // *\n    // * @param settingDTO Setting\n    // * @param operator   操作者\n    // * @param projectId\n    // * @return Result\n    // * @throws AdminOperateException\n    // */\n    //Result<Void> modifySetting(ConsoleTemplateSettingDTO settingDTO, String operator,\n    //                           Integer projectId) throws AdminOperateException;\n\n    /**\n     * 修改模板Setting(仅开放对于副本设置和异步translog落盘方式的设置)\n     * @param settingDTO 模板seting修改类\n     * @param operator 操作者\n     * @throws AdminOperateException\n     */\n    Result<Void> customizeSetting(TemplateSettingDTO settingDTO, String operator) throws AdminOperateException;\n\n    /**\n     * 获取逻辑模板settings\n     * @param logicId 逻辑模板ID\n     * @return\n     * @throws AdminOperateException\n     */\n    Result<IndexTemplatePhySetting> getSettings(Integer logicId) throws AdminOperateException;\n\n    /**\n     * 创建逻辑模板settings视图\n     * @param logicId 逻辑模板ID\n     * @return 索引模板视图信息\n     */\n    Result<TemplateSettingVO> buildTemplateSettingVO(Integer logicId);\n\n    /**\n     * 更新settings信息\n     * @param logicId 逻辑ID\n     * @param settings settings\n     * @return\n     */\n    @Deprecated\n    Result<Void> updateSettings(Integer logicId, String operator, AriusIndexTemplateSetting settings);\n\n    /**\n     * 更新settings信息\n     *\n     * @param logicId   逻辑ID\n     * @param settings  settings\n     * @param operator\n     * @param projectId\n     * @return\n     */\n    Result<Void> updateSettings(Integer logicId, IndexTemplatePhySetting settings, String operator, Integer projectId)\n            throws AdminOperateException;\n\n    /**\n     * 更加逻辑ID获取Settings\n     * @param logicId 逻辑ID\n     * @return\n     */\n    Result<IndexTemplatePhySetting> getTemplateSettings(Integer logicId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/setting/TemplatePhySettingManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.setting;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhySetting;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport java.util.Map;\n\npublic interface TemplatePhySettingManager {\n    /**\n     * 校验当前物理模板settings信息\n     * @param cluster 物理集群名称\n     * @param template 逻辑模板\n     * @param settings settings.\n     * @return\n     */\n    boolean validTemplateSettings(String cluster, String template,\n                                  IndexTemplatePhySetting settings) throws ESOperateException;\n\n    /**\n     * 获取模板settings\n     * @param cluster 集群名称\n     * @param template 模板名称\n     * @return\n     */\n    IndexTemplatePhySetting fetchTemplateSettings(String cluster, String template) throws ESOperateException;\n\n    /**\n     * merge当前settings，并更新到物理模板中\n     * @param cluster 集群名称\n     * @param template 模板名称\n     * @param settings 增量配置\n     * @return\n     */\n    boolean mergeTemplateSettings(Integer logicId, String cluster, String template, String operator,\n                                  Map<String, String> settings) throws AdminOperateException;\n\n    /**\n     * 更新模板settings\n     * @param logicId\n     * @param cluster\n     * @param template\n     * @param settings\n     * @return\n     * @throws AdminOperateException\n     */\n    boolean mergeTemplateSettingsCheckAllocationAndShard(Integer logicId, String cluster, String template,\n                                                         IndexTemplatePhySetting settings) throws AdminOperateException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/setting/impl/TemplateLogicSettingsManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.setting.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.mapping.AriusIndexTemplateSetting.ASYNC;\nimport static com.didichuxing.datachannel.arius.admin.common.mapping.AriusIndexTemplateSetting.NUMBER_OF_REPLICAS_KEY;\nimport static com.didichuxing.datachannel.arius.admin.common.mapping.AriusIndexTemplateSetting.REQUEST;\nimport static com.didichuxing.datachannel.arius.admin.common.mapping.AriusIndexTemplateSetting.TRANSLOG_DURABILITY_KEY;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.base.impl.BaseTemplateSrvImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping.TemplateLogicMappingManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.precreate.PreCreateManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.setting.TemplateLogicSettingsManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.setting.TemplatePhySettingManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.operaterecord.template.TemplateSettingOperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhySetting;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithMapping;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateSettingVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.index.ReBuildTomorrowIndexEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusIndexTemplateSetting;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didiglobal.knowframework.elasticsearch.client.utils.JsonUtils;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * 索引setting服务实现\n * @author zqr\n * @date 2020-09-09\n */\n@Service\npublic class TemplateLogicSettingsManagerImpl extends BaseTemplateSrvImpl implements TemplateLogicSettingsManager {\n\n    @Autowired\n    private TemplatePhySettingManager   templatePhySettingManager;\n\n    @Autowired\n    private TemplateLogicMappingManager templateLogicMappingManager;\n\n    @Autowired\n    private PreCreateManager            templatePreCreateManager;\n    @Autowired\n    private ESTemplateService           esTemplateService;\n    @Autowired\n    private ESIndexService esIndexService;\n\n    /**\n     * @return\n     */\n    @Override\n    public TemplateServiceEnum templateSrv() {\n        return TemplateServiceEnum.TEMPLATE_SETTING;\n    }\n    \n\n    @Override\n    public Result<Void> customizeSetting(TemplateSettingDTO settingDTO, String operator) throws AdminOperateException {\n\n        LOGGER.info(\"class=TemplateLogicServiceImpl||method=modifySetting||operator={}||setting={}\", operator,\n            JSON.toJSONString(settingDTO));\n\n        if (AriusObjUtils.isNull(operator)) {\n            return Result.buildParamIllegal(\"操作人为空\");\n        }\n\n        // 根据传入setting的设置创建修改的模板setting\n        AriusIndexTemplateSetting settings = new AriusIndexTemplateSetting();\n        settings.setReplicasNum(settingDTO.isCancelCopy() ? 0 : 1);\n        settings.setTranslogDurability(settingDTO.isAsyncTranslog() ? ASYNC : REQUEST);\n\n        Result<Void> result = updateSettings(settingDTO.getLogicId(), operator, settings);\n        if (result.success()) {\n            SpringTool.publish(new ReBuildTomorrowIndexEvent(this, settingDTO.getLogicId()));\n        }\n\n        return result;\n    }\n\n    /**\n     * 获取逻辑模板settings\n     *\n     * @param logicId 逻辑模板ID\n     * @return\n     * @throws AdminOperateException\n     */\n    @Override\n    public Result<IndexTemplatePhySetting> getSettings(Integer logicId) {\n        return getTemplateSettings(logicId);\n    }\n\n    @Override\n    public Result<TemplateSettingVO> buildTemplateSettingVO(Integer logicId) {\n        // 从es引擎中获取逻辑模板对应的settings设置\n        Result<IndexTemplatePhySetting> indexTemplateSettingsResult = getSettings(logicId);\n        if (indexTemplateSettingsResult.failed()) {\n            return Result.buildFrom(indexTemplateSettingsResult);\n        }\n\n        IndexTemplatePhySetting indexTemplatePhySetting = indexTemplateSettingsResult.getData();\n\n        //  获取模板setting的扁平化结构\n        Map<String, String> flatIndexTemplateMap = indexTemplatePhySetting.flatSettings();\n\n        //模板索引setting视图构建,当副本为零时,cancelCopy为true,当translog为异步时，asyncTranslog为true\n        TemplateSettingVO templateSettingVO = new TemplateSettingVO();\n\n        // translog异步设置默认是request同步的\n        templateSettingVO.setAsyncTranslog(flatIndexTemplateMap.containsKey(TRANSLOG_DURABILITY_KEY)\n                                           && flatIndexTemplateMap.get(TRANSLOG_DURABILITY_KEY).equals(ASYNC));\n\n        // 获取当前模板的副本数目设置\n        templateSettingVO.setCancelCopy(flatIndexTemplateMap.containsKey(NUMBER_OF_REPLICAS_KEY)\n                                        && Integer.parseInt(flatIndexTemplateMap.get(NUMBER_OF_REPLICAS_KEY)) == 0);\n\n        // 获取当前模板设置的分词器，获取index.analysis下的自定义分词器设置\n        templateSettingVO.setAnalysis(getAnalysisFromTemplateSettings(indexTemplatePhySetting));\n\n        // 获取当前模板的dynamic_templates\n        templateSettingVO.setDynamicTemplates(getDynamicTemplatesByLogicTemplate(logicId));\n\n        return Result.buildSucc(templateSettingVO);\n    }\n\n    /**\n     * 更新settings信息\n     * @param logicId 逻辑ID\n     * @param settings settings\n     * @return\n     */\n    @Override\n    public Result<Void> updateSettings(Integer logicId, String operator, AriusIndexTemplateSetting settings) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (templateLogicWithPhysical == null) {\n            return Result.buildNotExist(\"逻辑模板不存在, ID:\" + logicId);\n        }\n\n        if (!templateLogicWithPhysical.hasPhysicals()) {\n            return Result.buildNotExist(\"物理模板不存在，ID:\" + logicId);\n        }\n\n        List<IndexTemplatePhy> templatePhysicals = templateLogicWithPhysical.fetchMasterPhysicalTemplates();\n\n        \n\n        for (IndexTemplatePhy templatePhysical : templatePhysicals) {\n            try {\n                templatePhySettingManager.mergeTemplateSettings(logicId, templatePhysical.getCluster(),\n                    templatePhysical.getName(), operator, settings.toJSON());\n            } catch (AdminOperateException adminOperateException) {\n                return Result.buildFail(adminOperateException.getMessage());\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> updateSettings(Integer logicId, IndexTemplatePhySetting settings, String operator,\n                                       Integer projectId) throws AdminOperateException {\n\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (templateLogicWithPhysical == null) {\n            return Result.buildNotExist(\"逻辑模板不存在, ID:\" + logicId);\n        }\n\n        if (!templateLogicWithPhysical.hasPhysicals()) {\n            return Result.buildNotExist(\"物理模板不存在，ID:\" + logicId);\n        }\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(IndexTemplateWithPhyTemplates::getProjectId,\n            templateLogicWithPhysical, projectId);\n        if (result.failed()) {\n            return result;\n        }\n        //如果是非分区模版\n        if (!templateLogicWithPhysical.getMasterPhyTemplate().getExpression().endsWith(\"*\")){\n            final Result<Void> voidResult = noPartitioningIndexSettingChanges(settings,\n                templateLogicWithPhysical);\n            if (voidResult.failed()){\n                return Result.buildFrom(voidResult);\n            }\n        }\n        \n        List<IndexTemplatePhy> templatePhysicals = templateLogicWithPhysical.fetchMasterPhysicalTemplates();\n        \n        //获取变更前的setting\n        final Result<IndexTemplatePhySetting> beforeSetting = getSettings(logicId);\n        for (IndexTemplatePhy templatePhysical : templatePhysicals) {\n        \n            templatePhySettingManager.mergeTemplateSettingsCheckAllocationAndShard(logicId,\n                    templatePhysical.getCluster(), templatePhysical.getName(), settings);\n        }\n        //分区索引会自动重建\n        if (templateLogicWithPhysical.getMasterPhyTemplate().getExpression().endsWith(\"*\")) {\n            SpringTool.publish(new ReBuildTomorrowIndexEvent(this, logicId));\n        }\n        final Result<IndexTemplatePhySetting> afterSetting = getSettings(logicId);\n        operateRecordService.save(new OperateRecord.Builder()\n            .project(projectService.getProjectBriefByProjectId(projectId)).triggerWayEnum(TriggerWayEnum.MANUAL_TRIGGER)\n            .userOperation(operator).operationTypeEnum(OperateTypeEnum.TEMPLATE_MANAGEMENT_EDIT_SETTING)\n            .content(new TemplateSettingOperateRecord(beforeSetting.getData(), afterSetting.getData()).toString())\n            .bizId(logicId).build());\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 通过逻辑ID获取Settings\n     * @param logicId 逻辑ID\n     * @return\n     */\n    @Override\n    public Result<IndexTemplatePhySetting> getTemplateSettings(Integer logicId) {\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (templateLogicWithPhysical == null) {\n            return Result.buildNotExist(\"逻辑模板不存在, ID:\" + logicId);\n        }\n\n        if (!templateLogicWithPhysical.hasPhysicals()) {\n            return Result.buildNotExist(\"物理模板不存在，ID:\" + logicId);\n        }\n\n        IndexTemplatePhy indexTemplatePhy = templateLogicWithPhysical.getMasterPhyTemplate();\n        if (indexTemplatePhy != null) {\n            try {\n                return Result.buildSucc(templatePhySettingManager.fetchTemplateSettings(indexTemplatePhy.getCluster(),\n                    indexTemplatePhy.getName()));\n            } catch (ESOperateException e) {\n                return Result.buildFail(e.getMessage());\n            }\n        }\n\n        return Result.buildFail(\"不存在Master角色物理模板，ID：\" + logicId);\n    }\n\n    /**************************************** private method ****************************************************/\n    /**\n     * 根据逻辑模板id获取设置的dynamic_templates设置\n     * @param logicId 逻辑模板id\n     * @return\n     */\n    private JSONArray getDynamicTemplatesByLogicTemplate(Integer logicId) {\n        Result<IndexTemplateWithMapping> templateWithMapping = templateLogicMappingManager\n            .getTemplateWithMapping(logicId);\n        if (templateWithMapping.failed()) {\n            LOGGER.warn(\n                \"class=TemplateLogicServiceImpl||method=getDynamicTemplatesByLogicTemplate||logicTemplateId={}||msg={}\",\n                logicId, templateWithMapping.getMessage());\n            return null;\n        }\n\n        // 获取逻辑模板对应的物理模板的mapping设置\n        List<AriusTypeProperty> typeProperties = templateWithMapping.getData().getTypeProperties();\n        if (CollectionUtils.isEmpty(typeProperties)) {\n            return null;\n        }\n\n        // 获取其中一个物理模板的mapping的中的dynamic_templates设置\n        return typeProperties.get(0).getDynamicTemplates();\n    }\n\n    private JSONObject getAnalysisFromTemplateSettings(IndexTemplatePhySetting indexTemplatePhySetting) {\n        JSONObject indexSettings = indexTemplatePhySetting.getSettings().getJSONObject(\"index\");\n        if (AriusObjUtils.isNull(indexSettings)) {\n            LOGGER.info(\n                \"class=TemplateLogicServiceImpl||method=getAnalysisFromTemplateSettings||settings={}||msg= no index settings\",\n                indexTemplatePhySetting);\n            return null;\n        }\n\n        return indexSettings.getJSONObject(\"analysis\");\n    }\n    \n    /**\n     * 修改不分区索引的setting，尝试性修改，对错误结果不做返回\n     *\n     * @param settings 索引模板设置。\n     * @param templateLogicWithPhysical 带有物理模板的逻辑索引模板\n     */\n    private Result<Void> noPartitioningIndexSettingChanges(IndexTemplatePhySetting settings,\n        IndexTemplateWithPhyTemplates templateLogicWithPhysical) {\n        // 同步修改不分区索引\n        final Map<String, String> settingMap = JsonUtils.flat(settings.getSettings());\n        // 删除 index.routing.allocation.include._name 和 index.number_of_shards 因为会导致更新索引 setting 失效\n        settingMap.remove(\"index.routing.allocation.include._name\");\n        settingMap.remove(\"index.number_of_shards\");\n        // 更新索引 setting\n        for (IndexTemplatePhy physical : templateLogicWithPhysical.getPhysicals()) {\n            try {\n                esIndexService.syncPutIndexSettings(physical.getCluster(),\n                    Collections.singletonList(physical.getName()),\n                    settingMap, 3);\n            } catch (ESOperateException e) {\n                return Result.buildFail(String.format(\"非分区模版setting修改错误，原因：%s\",e.getMessage()));\n            }\n        }\n        return Result.buildSucc();\n    \n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/template/srv/setting/impl/TemplatePhySettingManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.template.srv.setting.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.setting.TemplatePhySettingManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.operaterecord.template.TemplateSettingOperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhySetting;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminESOpRetryConstants;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.impl.IndexTemplateServiceImpl;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.TemplateConfig;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.Map;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author wangshu\n * @date 2020/08/24\n */\n@Service\npublic class TemplatePhySettingManagerImpl implements TemplatePhySettingManager {\n\n    private static final ILog    LOGGER = LogFactory.getLog(IndexTemplateServiceImpl.class);\n\n    @Autowired\n    private ESTemplateService    esTemplateService;\n\n    @Autowired\n    private OperateRecordService operateRecordService;\n\n    @Override\n    public boolean validTemplateSettings(String cluster, String template,\n                                         IndexTemplatePhySetting settings) throws ESOperateException {\n        if (StringUtils.isBlank(cluster) || StringUtils.isBlank(template) || settings == null) {\n            return false;\n        }\n\n        TemplateConfig templateConfig = new TemplateConfig();\n        templateConfig.setMappings(new MappingConfig());\n        templateConfig.setSetttings(settings.flatSettings());\n        templateConfig.setTemplate(template);\n\n        return esTemplateService.syncCheckTemplateConfig(cluster, template, templateConfig,\n            AdminESOpRetryConstants.DEFAULT_RETRY_COUNT);\n    }\n\n    @Override\n    public IndexTemplatePhySetting fetchTemplateSettings(String cluster, String template) throws ESOperateException {\n        if (!esTemplateService.syncGetEsClusterIsNormal(cluster)) {\n            throw new ESOperateException(String.format(\"模版【%s】,无法获取setting信息\", template));\n        }\n        TemplateConfig templateConfig = esTemplateService.syncGetTemplateConfig(cluster, template);\n        if (templateConfig != null) {\n            return new IndexTemplatePhySetting(templateConfig.getSetttings());\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean mergeTemplateSettings(Integer logicId, String cluster, String template, String operator,\n                                         Map<String, String> settings) throws AdminOperateException {\n\n        TemplateConfig templateConfig = esTemplateService.syncGetTemplateConfig(cluster, template);\n        if (templateConfig == null) {\n            LOGGER.info(\"class=TemplatePhySettingsManagerImpl||method=updateSetting||\"\n                        + \"msg=templateNotExists||cluster={}||template={}\",\n                cluster, template);\n            throw new AdminOperateException(\"模版不存在，template:\" + template);\n        }\n\n        IndexTemplatePhySetting oldTemplateSettings = new IndexTemplatePhySetting(templateConfig.getSetttings());\n        IndexTemplatePhySetting newTemplateSettings = new IndexTemplatePhySetting(templateConfig.getSetttings());\n        templateConfig.setSetttings(newTemplateSettings.merge(settings));\n\n        if (!esTemplateService.syncCheckTemplateConfig(cluster, fetchPreCreateTemplateName(template), templateConfig,\n            AdminESOpRetryConstants.DEFAULT_RETRY_COUNT)) {\n            LOGGER.info(\"class=TemplatePhySettingsManagerImpl||method=updateSetting||\"\n                        + \"msg=checkTemplateConfigFail||cluster={}||templateName={}||templateConfig={}\",\n                cluster, fetchPreCreateTemplateName(template), templateConfig);\n            throw new AdminOperateException(\"非法模板settings: \" + settings);\n        }\n\n        boolean result = esTemplateService.syncUpsertSetting(cluster, template, settings,\n            AdminESOpRetryConstants.DEFAULT_RETRY_COUNT);\n        if (result) {\n            // 记录setting 更新记录\n            operateRecordService.save(new OperateRecord.Builder().bizId(logicId)\n                .operationTypeEnum(OperateTypeEnum.TEMPLATE_MANAGEMENT_EDIT_SETTING)\n\n                .content(new TemplateSettingOperateRecord(oldTemplateSettings, newTemplateSettings).toString())\n                .triggerWayEnum(TriggerWayEnum.MANUAL_TRIGGER).build());\n        }\n        return result;\n    }\n\n    @Override\n    public boolean mergeTemplateSettingsCheckAllocationAndShard(Integer logicId, String cluster, String template,\n                                                                IndexTemplatePhySetting settings) throws AdminOperateException {\n        Map<String, String> flatSettings = settings.flatSettings();\n        TemplateConfig templateConfig = esTemplateService.syncGetTemplateConfig(cluster, template);\n        if (templateConfig == null) {\n            throw new AdminOperateException(\"模版不存在，template:\" + template);\n        }\n\n        templateConfig.setSetttings(flatSettings);\n        if (!esTemplateService.syncCheckTemplateConfig(cluster, fetchPreCreateTemplateName(template), templateConfig,\n            AdminESOpRetryConstants.DEFAULT_RETRY_COUNT)) {\n            throw new AdminOperateException(\"非法模板settings: \" + settings);\n        }\n\n        return esTemplateService.syncUpdateSettingCheckAllocationAndShard(cluster, template, flatSettings,\n            AdminESOpRetryConstants.DEFAULT_RETRY_COUNT);\n    }\n\n    /**************************************** private method ****************************************************/\n    /**\n     * 获取预创建模板名称\n     * @param templateName 原始模板名称\n     * @return 预创建模板名称\n     */\n    private String fetchPreCreateTemplateName(String templateName) {\n        return AdminConstant.ES_CHECK_TEMPLATE_INDEX_PREFIX + System.currentTimeMillis() + templateName;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/thardpart/CommonManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.thardpart;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.config.AriusConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ThirdPartClusterVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.config.ThirdpartConfigVO;\nimport java.util.List;\n\npublic interface CommonManager {\n\n    /**\n     * 获取物理集群列表接口\n     * @return\n     */\n    Result<List<ThirdPartClusterVO>> listDataCluster();\n\n    /**\n     * 获取集群接口\n     * @param cluster\n     * @return\n     */\n    Result<ThirdPartClusterVO> getDataCluster(String cluster);\n\n    /**\n    * 获取配置列表接口\n    * @param param\n    * @return\n    */\n    Result<List<ThirdpartConfigVO>> queryConfig(AriusConfigInfoDTO param);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/thardpart/impl/CommonManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.thardpart.impl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.TemplateSrvManager;\nimport com.didichuxing.datachannel.arius.admin.biz.thardpart.CommonManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.config.AriusConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ThirdPartClusterVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.config.ThirdpartConfigVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Sets;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class CommonManagerImpl implements CommonManager {\n\n    private static final ILog      LOGGER = LogFactory.getLog(CommonManagerImpl.class);\n\n    @Autowired\n    private ClusterPhyService      esClusterPhyService;\n\n    @Autowired\n    private TemplateSrvManager     templateSrvManager;\n    @Autowired\n    private AriusConfigInfoService ariusConfigInfoService;\n\n    @Override\n    public Result<List<ThirdPartClusterVO>> listDataCluster() {\n        List<ThirdPartClusterVO> clusterVOS = ConvertUtil.list2List(esClusterPhyService.listAllClusters(),\n            ThirdPartClusterVO.class);\n        List<String> hasSecurityClusters = templateSrvManager\n            .getPhyClusterByOpenTemplateSrv(TemplateServiceEnum.TEMPLATE_SECURITY.getCode());\n\n        clusterVOS.forEach(vo -> {\n            if (hasSecurityClusters.contains(vo.getCluster())) {\n                vo.setPlugins(Sets.newHashSet(\"security\"));\n            }\n        });\n\n        return Result.buildSucc(clusterVOS);\n    }\n\n    @Override\n    public Result<ThirdPartClusterVO> getDataCluster(String cluster) {\n        return Result\n            .buildSucc(ConvertUtil.obj2Obj(esClusterPhyService.getClusterByName(cluster), ThirdPartClusterVO.class));\n    }\n\n    @Override\n    public Result<List<ThirdpartConfigVO>> queryConfig(AriusConfigInfoDTO param) {\n        return Result\n            .buildSucc(ConvertUtil.list2List(ariusConfigInfoService.queryByCondition(param), ThirdpartConfigVO.class));\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/BaseWorkOrderHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder.WorkOrderProcessDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.WorkOrderVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.OrderStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport java.util.List;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\npublic abstract class BaseWorkOrderHandler implements WorkOrderHandler {\n\n    protected static final ILog    LOGGER = LogFactory.getLog(BaseWorkOrderHandler.class);\n\n    @Autowired\n    private WorkOrderManager       workOrderManager;\n\n    @Autowired\n    protected OperateRecordService operateRecordService;\n    @Autowired\n    protected ProjectService projectService;\n    @Autowired\n    private RoleTool               roleTool;\n\n    /**\n     * 创建一个工单\n     * 1、校验用户提供数据是否合法\n     * 2、提交工单\n     */\n    @Override\n    public Result<WorkOrderPO> submit(WorkOrder workOrder) throws AdminOperateException {\n\n        Result<Void> checkAuth = validateConsoleAuth(workOrder);\n        if (checkAuth.failed()) {\n            LOGGER.warn(\"class=BaseWorkOrderHandler||method=submit||msg=checkAuth fail||type={}||content={}\",\n                workOrder.getType(), ConvertUtil.obj2Json(workOrder.getContentObj()));\n\n            return Result.buildFrom(checkAuth);\n        }\n\n        Result<Void> checkDuplicateOrder = validDuplicateOrder(workOrder);\n        if (checkDuplicateOrder.failed()) {\n            LOGGER.warn(\"class=BaseWorkOrderHandler||method=submit||msg=checkDuplicateOrder fail||type={}||content={}\",\n                workOrder.getType(), ConvertUtil.obj2Json(workOrder.getContentObj()));\n            return Result.buildFrom(checkDuplicateOrder);\n        }\n\n        Result<Void> checkParam = validateConsoleParam(workOrder);\n        if (checkParam.failed()) {\n            LOGGER.warn(\"class=BaseWorkOrderHandler||method=submit||msg=checkParam fail||type={}||content={}\",\n                workOrder.getType(), ConvertUtil.obj2Json(workOrder.getContentObj()));\n            return Result.buildFrom(checkParam);\n        }\n\n        workOrder.setTitle(getTitle(workOrder));\n\n        WorkOrderPO workOrderPO = buildOrderPO(workOrder);\n        workOrderManager.insert(workOrderPO);\n\n        return Result.buildSuccWithTips(workOrderPO, \"工单提交成功！\");\n    }\n\n    /**\n     * 处理工单,审核通过或者不需要审核的工单处理逻辑\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> processAgree(WorkOrder workOrder, String approver,\n                                     String opinion) throws AdminOperateException {\n        Result<Void> checkParamResult = validateParam(workOrder);\n\n        if (checkParamResult.failed()) {\n            LOGGER.warn(\"class=BaseWorkOrderHandler||method=processAgree||msg=checkParam fail||type={}||content={}\",\n                workOrder.getType(), ConvertUtil.obj2Json(workOrder.getContentObj()));\n\n            return checkParamResult;\n        }\n\n        return handleProcessAgree(workOrder, approver, opinion);\n    }\n\n    /**\n     * 处理审核不同意的工单，要求配置不同意的工单回调\n     *\n     * @param orderPO 工单内容\n     * @return result\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> processDisagree(WorkOrderPO orderPO, WorkOrderProcessDTO processDTO) {\n        return doProcessDisagree(orderPO, processDTO);\n    }\n\n    /*************************************** protected method ************************************/\n    /**\n     * 审核不通过\n     * @param orderPO WorkOrderPO\n     * @return\n     */\n    protected Result<Void> doProcessDisagree(WorkOrderPO orderPO, WorkOrderProcessDTO processDTO) {\n        orderPO.setApprover(processDTO.getAssignee());\n        orderPO.setApproverProjectId(processDTO.getAssigneeProjectId());\n        orderPO.setOpinion(processDTO.getComment());\n        orderPO.setStatus(OrderStatusEnum.REFUSED.getCode());\n\n        if (workOrderManager.updateOrderById(orderPO) > 0) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(\"审批不通过\");\n    }\n\n    /**\n     * 校验申请人是否重复提交了相同类型,相同内容的工单\n     * @param workOrder workorder工单\n     * @return 重复性校验的结果\n     */\n    protected Result<Void> validDuplicateOrder(WorkOrder workOrder) {\n        // 获取当前提交人已经提交待审批的工单列表\n        Result<List<WorkOrderVO>> orderToApproveResult = workOrderManager.getOrderApplyList(workOrder.getSubmitor(),\n            OrderStatusEnum.WAIT_DEAL.getCode());\n        if (orderToApproveResult.failed()) {\n            return Result.buildFrom(orderToApproveResult);\n        }\n\n        List<WorkOrderVO> applyListResultData = orderToApproveResult.getData();\n        // 当前不存在待审批的工单时，无需做重复性校验\n        if (CollectionUtils.isEmpty(applyListResultData)) {\n            return Result.buildSucc();\n        }\n\n        // 遍历所有的工单，对于待审批的工单的内容和类型进行重复性的条件过滤\n        for (WorkOrderVO param : applyListResultData) {\n            if (workOrder.getType().equals(param.getType())\n                && JSON.toJSONString(workOrder.getContentObj()).equals(param.getExtensions())) {\n                return Result.buildFail(\"存在重复工单，如需重新提交，需前往[工单任务-我的申请]撤回原有工单。\");\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证用户提供的参数\n     * @param workOrder 工单\n     * @return result\n     */\n    protected abstract Result<Void> validateConsoleParam(WorkOrder workOrder) throws NotFindSubclassException;\n\n    /**\n     * 生成标题\n     * @param workOrder 工单\n     * @return result\n     */\n    protected abstract String getTitle(WorkOrder workOrder);\n\n    /**\n     * 验证用户是否有该工单权限\n     * @param workOrder 工单内容\n     * @return result\n     */\n    protected abstract Result<Void> validateConsoleAuth(WorkOrder workOrder);\n\n    /**\n     * 验证平台参数\n     * @param workOrder 工单内容\n     * @return result\n     */\n    protected abstract Result<Void> validateParam(WorkOrder workOrder);\n\n    /**过程是否同意\n     * 处理工单\n     * @param workOrder 工单\n     * @return result\n     @param approver 审批人\n     @throws AdminOperateException 管理操作Exception\n     */\n    protected abstract Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException;\n\n    protected List<UserBriefVO> getOPList() {\n        return roleTool.getAdminList();\n    }\n\n    protected boolean isOP(String userName) {\n        return roleTool.isAdmin(userName);\n    }\n\n    /*************************************** privete method ************************************/\n    /**\n     * 构建订单表单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    private WorkOrderPO buildOrderPO(WorkOrder workOrder) {\n        WorkOrderPO orderPo = new WorkOrderPO();\n        orderPo.setApplicant(workOrder.getSubmitor());\n        orderPo.setDescription(workOrder.getDescription());\n        orderPo.setExtensions(JSON.toJSONString(workOrder.getContentObj()));\n        orderPo.setType(workOrder.getType());\n        orderPo.setTitle(workOrder.getTitle());\n        orderPo.setStatus(OrderStatusEnum.WAIT_DEAL.getCode());\n        orderPo.setApplicantProjectId(workOrder.getSubmitorProjectId());\n        return orderPo;\n    }\n\n    private Result<Void> handleProcessAgree(WorkOrder workOrder, String approver,\n                                            String opinion) throws AdminOperateException {\n        Result<Void> result = doProcessAgree(workOrder, approver);\n\n        if (result.success()) {\n            Result<Void> updateResult = updateWorkOrderStatus(workOrder, approver, opinion);\n            if (updateResult.failed()) {\n                return updateResult;\n            }\n        }\n\n        return result;\n    }\n\n    private Result<Void> updateWorkOrderStatus(WorkOrder workOrder, String approver, String opinion) {\n        WorkOrderPO orderPO = new WorkOrderPO();\n        orderPO.setId(workOrder.getId());\n        orderPO.setApprover(approver);\n        orderPO.setOpinion(opinion);\n        orderPO.setStatus(OrderStatusEnum.PASSED.getCode());\n        Result<Void> processResult = workOrderManager.processOrder(orderPO);\n        if (processResult.failed()) {\n            return processResult;\n        }\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/WorkOrderHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder.WorkOrderProcessDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\n\n/**\n * @author d06679\n * @date 2018/9/18\n */\npublic interface WorkOrderHandler extends BaseHandle {\n\n    /**提交\n     * 创建一个工单\n     *\n     * 1、校验工单内容是否合法\n     * 2、构建工单请求\n     * 3、提交工单\n     *\n     * @param workOrder 工单数据\n     * @return result\n     @throws AdminOperateException 管理操作Exception\n     */\n    Result<WorkOrderPO> submit(WorkOrder workOrder) throws AdminOperateException;\n\n    /**过程一致\n     * 处理工单\n     * @param workOrder 工单内容\n     * @return result\n     @param approver 审批人\n     @param opinion 意见\n     @throws AdminOperateException 管理操作Exception\n     */\n    Result<Void> processAgree(WorkOrder workOrder, String approver, String opinion) throws AdminOperateException;\n\n    /**过程不同意\n     * 处理审核不同意的工单\n     * @param processDTO 工单内容\n     * @return result\n     @param orderPO 订单订单\n     */\n    Result<Void> processDisagree(WorkOrderPO orderPO, WorkOrderProcessDTO processDTO);\n\n    /**\n     * 工单是否自动审批\n     * @param workOrder 工单类型\n     * @return result\n     */\n    boolean canAutoReview(WorkOrder workOrder);\n\n    /**\n     * 获取工单详细信息\n     * @param extensions 扩展信息\n     * @return AbstractOrderDetail\n     */\n    AbstractOrderDetail getOrderDetail(String extensions);\n\n    /**\n     * 获取审批人列表\n     * @param detail 扩展信息\n     * @return List<AriusUserInfo>\n     */\n    List<UserBriefVO> getApproverList(AbstractOrderDetail detail);\n\n    /**检查机关\n     * 是否审批人员\n     * @param orderPO 订单信息, userName 审批人名称\n     * @return Result\n     @param userName 用户名\n     */\n    Result<Void> checkAuthority(WorkOrderPO orderPO, String userName);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/WorkOrderManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder.WorkOrderDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder.WorkOrderProcessDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.OrderInfoDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.AriusWorkOrderInfoSubmittedVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.OrderTypeVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.WorkOrderVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.detail.OrderDetailBaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.OperateForbiddenException;\nimport java.util.List;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\npublic interface WorkOrderManager {\n\n    /**获取订单类型\n     * 获取工代类型\n     * @return {@link Result}<{@link List}<{@link OrderTypeVO}>>\n     */\n    Result<List<OrderTypeVO>> getOrderTypes();\n\n    /**提交\n     * 提交一个工单\n     @param workOrderDTO 工作订单dto\n      * @return {@link Result}<{@link AriusWorkOrderInfoSubmittedVO}>\n     @throws AdminOperateException 管理操作Exception\n     */\n    Result<AriusWorkOrderInfoSubmittedVO> submit(WorkOrderDTO workOrderDTO) throws AdminOperateException;\n\n    /**\n     * 过程 工单处理流程\n     *\n     * @param workOrderProcessDTO 工作订单流程dto\n     * @param projectId\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> process(WorkOrderProcessDTO workOrderProcessDTO, Integer projectId) throws NotFindSubclassException;\n\n    /**新增\n     * 插入一条工单\n     @param orderDO 订单做\n     @return int\n     */\n    int insert(WorkOrderPO orderDO);\n\n    /**更新订单id\n     * 通过id更新工单\n     @param orderDO 订单做\n     @return int\n     */\n    int updateOrderById(WorkOrderPO orderDO);\n\n    /**获取通过id\n     * 通过id获取工单\n     @param id id\n      * @return {@link Result}<{@link OrderDetailBaseVO}>\n     */\n    Result<OrderDetailBaseVO> getById(Long id);\n\n    /**\n     * 获取所有的工单\n     * @return List<OrderPO>\n     */\n    List<WorkOrderPO> list();\n\n    /**取消订单\n     * 撤销工单\n     @param id id\n     @param userName 用户名\n      * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> cancelOrder(Long id, String userName);\n\n    /**过程顺序\n     * 处理工单工单\n     @param orderDO 订单做\n      * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> processOrder(WorkOrderPO orderDO);\n\n    /**\n     * 获取订单应用列表 获取工单申请列表\n     *\n     * @param status    状态\n     * @param projectId\n     * @return {@link Result}<{@link List}<{@link WorkOrderVO}>>\n     */\n    Result<List<WorkOrderVO>> getOrderApplyList(Integer status, Integer projectId);\n\n    Result<List<WorkOrderVO>> getOrderApplyList(String applicant, Integer status);\n\n    /**获取批准列表\n     * 获取全部的工单审核列表\n     @param approver 审批人\n      * @return {@link List}<{@link WorkOrderPO}>\n     */\n    List<WorkOrderPO> getApprovalList(String approver);\n\n    /**获取通过批准列表\n     * 获取通过的工单审核列表\n     @param approver 审批人\n      * @return {@link List}<{@link WorkOrderPO}>\n     */\n    List<WorkOrderPO> getPassApprovalList(String approver);\n\n    /**获取等待批准列表\n     * 获取除指定类型的工单\n     @param userName 用户名\n      * @return {@link List}<{@link WorkOrderPO}>\n     */\n    List<WorkOrderPO> getWaitApprovalList(String userName);\n\n    /**获取抽象类细节\n     * 获取工单详情信息\n     @param orderPO 订单订单\n      * @return {@link OrderInfoDetail}\n     */\n    OrderInfoDetail getBaseDetail(WorkOrderPO orderPO) throws NotFindSubclassException, ESOperateException;\n\n    /**获取订单批准列表通过状态\n     * 根据状态获取工单列表\n     @param status 状态\n      * @return {@link Result}<{@link List}<{@link WorkOrderVO}>>\n     */\n    Result<List<WorkOrderVO>> getOrderApprovalListByStatus(Integer status) throws OperateForbiddenException;\n    \n    Result<AriusWorkOrderInfoSubmittedVO> submitByJoinLogicCluster(WorkOrderDTO workOrderDTO)\n            throws AdminOperateException;\n    \n    Result<Void> processByJoinLogicCluster(WorkOrderProcessDTO processDTO, Integer projectId) throws NotFindSubclassException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/BaseContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\n/**\n * @author d06679\n * @date 2019/5/7\n */\npublic class BaseContent {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/ClusterDeleteContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterBaseContent;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-06-11\n */\n@Data\n@NoArgsConstructor\npublic class ClusterDeleteContent extends ClusterBaseContent {\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/ClusterLogicTransferContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-06-17\n */\n@Data\n@NoArgsConstructor\npublic class ClusterLogicTransferContent extends BaseContent {\n\n    private Integer targetProjectId;\n\n    private Integer sourceProjectId;\n\n    private Long    clusterLogicId;\n\n    private String  clusterLogicName;\n\n\n    private String  memo;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/DslTemplateQueryLimitContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.DslQueryLimitDTO;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\npublic class DslTemplateQueryLimitContent {\n\n    /**\n     * 查询语句限流值相关参数\n     */\n    private List<DslQueryLimitDTO> dslQueryLimitDTOList;\n\n    /**\n     * 项目id\n     */\n    private Integer projectId;\n\n    /**\n     * 操作者\n     */\n    private String operator;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/DslTemplateStatusContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class DslTemplateStatusContent {\n\n    /**\n     * 名字\n     */\n    private String  name;\n\n    /**\n     * 项目id\n     */\n    private Integer projectId;\n\n    /**\n     * 操作者\n     */\n    private String operator;\n\n    /**\n     * dsl模板MD5\n     */\n    private String dslTemplateMd5;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/JoinLogicClusterContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 加入逻辑clueter内容\n *\n * @author shizeying\n * @date 2022/07/28\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class JoinLogicClusterContent extends BaseContent{\n    private Long id;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/LogicClusterAuthContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class LogicClusterAuthContent extends BaseContent {\n    /**\n     * 逻辑模板id\n     */\n    private Long    logicClusterId;\n\n    /**\n     * 逻辑模板名字\n     */\n    private String  logicClusterName;\n\n    /**\n     * 权限类型\n     * @see ProjectClusterLogicAuthEnum\n     */\n    private Integer authCode;\n\n    /**\n     * 申请说明\n     */\n    private String  memo;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/LogicClusterCreateContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class LogicClusterCreateContent extends BaseContent {\n    /**\n     * 集群名称\n     */\n    private String  name;\n\n    /**\n     * 集群类型\n     */\n    private Integer type;\n\n    /**\n     * 服务等级\n     */\n    private Integer level;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n\n    /**\n     * dataNode的规格\n     */\n    private String  dataNodeSpec;\n\n    /**\n     * dataNode的个数\n     */\n    private int     dataNodeNu;\n\n    \n\n    /**\n     * 备注\n     */\n    private String  memo;\n\n    /**\n     * 插件上传\n     */\n    private String  plugins;\n    \n  \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/LogicClusterDeleteContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-06-11\n */\n@Data\n@NoArgsConstructor\npublic class LogicClusterDeleteContent extends BaseContent {\n\n    /**\n     * 主键\n     */\n    private Long    id;\n\n    /**\n     * 集群名称\n     */\n    private String  name;\n\n    /**\n     * 集群类型\n     */\n    private Integer type;\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/LogicClusterIndecreaseContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionWithNodeInfoDTO;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\npublic class LogicClusterIndecreaseContent extends BaseContent {\n    /**\n     * 逻辑集群名称\n     */\n    private String                             logicClusterName;\n\n    /**\n     * 逻辑集群的id\n     */\n    private Long                               logicClusterId;\n\n    /**\n     * dataNode的规格\n     */\n    private String                             dataNodeSpec;\n\n    /**\n     * dataNode的个数\n     */\n    private int                                dataNodeNu;\n    /**\n     * 备注\n     */\n    private String                             memo;\n\n    /**\n     * 扩缩容的region信息\n     */\n    private List<ClusterRegionWithNodeInfoDTO> regionWithNodeInfo;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/LogicClusterPlugOperationContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class LogicClusterPlugOperationContent extends BaseContent {\n    /**\n     * 操作类型 3:安装 4：卸载\n     */\n    private Integer operationType;\n\n    /**\n     * 类型 6 插件安装卸载\n     */\n    private Integer type;\n    /**\n     * 集群id\n     */\n    private Long    logicClusterId;\n\n    /**\n     * 集群名称\n     */\n    private String  logicClusterName;\n\n    /**\n     * 插件ID\n     */\n    private String  plugIds;\n\n    /**\n     * 插件名称\n     */\n    private String  plugName;\n\n    /**\n     * 插件描述\n     */\n    private String  plugDesc;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/LogicClusterPluginContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class LogicClusterPluginContent extends BaseContent {\n\n    /**\n     * 逻辑集群id\n     */\n    private Long   logicClusterId;\n    /**\n     * 逻辑集群名称\n     */\n    private String logicClusterName;\n    /**\n     * 插件地址\n     */\n    private String pluginPathUrl;\n    /**\n     * 插件md5\n     */\n    private String pluginMd5;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/PhyClusterPluginOperationContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class PhyClusterPluginOperationContent extends BaseContent {\n\n    /**\n     * 操作类型 3:安装 4：卸载\n     */\n    private Integer operationType;\n    /**\n     * 插件 id\n     */\n    private Long    pluginId;\n    /**\n     * 插件文件名称\n     */\n    private String  pluginFileName;\n    /**\n     * 插件在文件仓库上的地址\n     */\n    private String  url;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/QueryDslLimitEditContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 模板扩缩容\n * @author d06679\n * @date 2019/5/7\n */\n@Data\n@NoArgsConstructor\npublic class QueryDslLimitEditContent extends BaseContent {\n\n    /**\n     * md5\n     */\n    private String dslTemplateMd5;\n\n    /**\n     * 模板\n     */\n    private String dslTemplate;\n\n    /**\n     * 源限流值\n     */\n    private Double queryLimit;\n\n    /**\n     * 希望限流值\n     */\n    private Double expectQueryLimit;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/TemplateAuthContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 模板扩缩容\n * @author d06679\n * @date 2019/5/7\n */\n@Data\n@NoArgsConstructor\npublic class TemplateAuthContent extends BaseContent {\n\n    /**\n     * 逻辑模板id\n     */\n    private Integer id;\n\n    /**\n     * 逻辑模板名字\n     */\n    private String  name;\n\n    /**\n     * 权限类型\n     * @see ProjectTemplateAuthEnum\n     */\n    private Integer authCode;\n\n    /**\n     * 申请说明\n     */\n    private String  memo;\n\n   \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/TemplateCreateContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-06-04\n */\n@Data\n@NoArgsConstructor\npublic class TemplateCreateContent extends BaseContent {\n\n    /**************************************** 基本信息 ****************************************************/\n\n    /**\n     * 索引模板名称\n     */\n    private String  name;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n\n    /**\n     * 用户数据类型\n     * @see DataTypeEnum\n     */\n    private Integer dataType;\n\n    \n\n    \n\n\n\n    /**\n     * 备注\n     */\n    private String  desc;\n\n    /**\n     * 逻辑集群id\n     */\n    private Long    resourceId;\n\n    /**\n     * 数据保存时长 单位天\n     */\n    private Integer expireTime;\n\n    /**\n     * 热数据保存天数, 单位天\n     */\n    private Integer hotTime;\n\n    /**\n     * 数据总量 单位G\n     */\n    private Double  diskQuota;\n\n    /**\n     * 周期性滚动  1 滚动   0 不滚动\n     */\n    private Boolean cyclicalRoll;\n\n    /**************************************** Schema信息 ****************************************************/\n\n    /**\n     * 时间字段\n     */\n    private String  dateField;\n    /**\n     * 时间字段格式\n     */\n    private String  dateFieldFormat;\n\n    /**\n     * mapping信息 mapping导入的\n     *\n     *      {\n     *       \"key1\": {\n     *         \"type\": \"integer\"\n     *       },\n     *       \"key2\": {\n     *         \"type\": \"long\"\n     *       }\n     *     }\n     *\n     */\n    private String  mapping;\n\n    /**\n     * id字段\n     */\n    private String  idField;\n\n    /**\n     * routing字段\n     */\n    private String  routingField;\n\n    /**\n     * dynamic_templates设置\n     * {\"dynamic_templates\":[{\"key\":{}}]}\n     */\n    private String  dynamicTemplates;\n\n    /**\n     * 是否取消副本\n     */\n    private boolean cancelCopy    = false;\n\n    /**\n     * 是否开启异步translog\n     */\n    private boolean asyncTranslog = false;\n\n    /**\n     * 索引模板自定义分词器\n     * {\"analyzer\":{\"key\":{}},\"tokenizer\":{}...}\n     * 支持 analyzer同级的可选项 analyzer、tokenizer、char_filter、filter\n     */\n    private String  customerAnalysis;\n\n    /**\n     * 模板服务等级\n     */\n    private Integer level;\n\n    /**************************************** 部署信息 ****************************************************/\n    /**\n     * 物理集群信息\n     */\n    private String  cluster;\n\n    /**\n     * rack信息\n     */\n    private String  rack;\n\n    /**\n     * 预创建索引标识\n     */\n    private Boolean preCreateFlags;\n\n    /**\n     * shard数量\n     */\n    private Integer shardNum;\n\n    /**\n     * 禁用索引_source标识\n     */\n    private Boolean disableSourceFlags;\n\n    /**\n     * 禁用rollover标识\n     */\n    private Boolean disableIndexRollover;\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/TemplateIndecreaseContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 模板扩缩容\n * @author d06679\n * @date 2019/5/7\n */\n@Data\n@NoArgsConstructor\npublic class TemplateIndecreaseContent extends BaseContent {\n\n    private Integer id;\n\n    /**\n     * 索引模板名称\n     */\n    private String  name;\n\n    /**\n     * 数据保存时长 单位天\n     */\n    private Integer expireTime;\n\n    /**\n     * 规格 单位台\n     */\n    private Double  quota;\n\n    /**\n     * 热数据保存天数 单位是天\n     */\n    private Integer hotTime;\n\n    /**\n     * 实际的磁盘消耗\n     */\n    private Double  actualDiskG;\n\n    /**\n     * 实际的CPU消耗\n     */\n    private Double  actualCpuCount;\n\n    /**\n     * Quota的磁盘消耗\n     */\n    private Double  quotaDiskG;\n\n    /**\n     * Quota的CPU消耗\n     */\n    private Double  quotaCpuCount;\n\n    /**************************************** 期望容量信息 ****************************************************/\n    /**\n     * 期望数据保存时长 单位天\n     */\n    private Integer expectExpireTime;\n\n    /**\n     * 数据总量 单位台\n     */\n    private Double  expectQuota;\n\n    /**\n     * 期望热数据保存天数 单位天\n     */\n    private Integer expectHotTime;\n\n    /**************************************** 管理员操作 ****************************************************/\n    /**\n     * 是否跳过容量规划，强制扩容 1:强制 0:不强制\n     */\n    private Integer force = 0;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/TemplateLogicStatusContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class TemplateLogicStatusContent {\n    /**\n     * 索引模板名称\n     */\n    private String name;\n    /**\n     * 模板Id\n     */\n    private Integer templateId;\n    /**\n     * 读/写的启用/禁用状态\n     */\n    private Boolean status;\n    /**\n     * 操作者\n     */\n    private String operator;\n    /**\n     * 项目id\n     */\n    private Integer projectId;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/TemplateQueryDslContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 模板扩缩容\n * @author d06679\n * @date 2019/5/7\n */\n@Data\n@NoArgsConstructor\npublic class TemplateQueryDslContent extends BaseContent {\n\n    private Integer id;\n\n    /**\n     * 名字\n     */\n    private String  name;\n\n    private String  dsl;\n\n    private String  memo;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/content/TemplateTransferContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.content;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 模板转让\n * @author d06679\n * @date 2019/5/7\n */\n@Data\n@NoArgsConstructor\npublic class TemplateTransferContent extends BaseContent {\n\n    private Integer id;\n\n    /**\n     * 名字\n     */\n    private String  name;\n\n    /**\n     * 目标ProjectId\n     */\n    private Integer sourceProjectId;\n\n    /**\n     * 目标ProjectId\n     */\n    private Integer tgtProjectId;\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/ClusterDeleteHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterContextManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterLogicManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.ClusterDeleteContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.ClusterDeleteOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author linyunan\n * @date 2021-06-11\n */\n@Service\n@Deprecated\npublic class ClusterDeleteHandler extends BaseWorkOrderHandler {\n    protected static final ILog     LOGGER = LogFactory.getLog(ClusterDeleteHandler.class);\n\n    @Autowired\n    private ClusterContextManager   clusterContextManager;\n\n    @Autowired\n    private ClusterPhyManager       clusterPhyManager;\n    @Autowired\n    private ClusterLogicManager clusterLogicManager;\n\n   \n\n    @Autowired\n    private IndexTemplatePhyService indexTemplatePhyService;\n\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        ClusterDeleteContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterDeleteContent.class);\n        if (!clusterPhyManager.isClusterExists(content.getPhyClusterName())) {\n            return Result.buildFail(String.format(\"物理集群[%s]不存在\", content.getPhyClusterName()));\n        }\n        \n        List<String> clusterLogicIdList = clusterLogicManager.getClusterPhyAssociatedClusterLogicNames(content.getPhyClusterName());\n        \n        if (CollectionUtils.isNotEmpty(clusterLogicIdList)) {\n            return Result.buildFail(String.format(\"物理集群[%s]和逻辑集群[%s]关联\", content.getPhyClusterName(),\n                ListUtils.strList2String(clusterLogicIdList)));\n        }\n\n        List<String> templatePhyNameList = indexTemplatePhyService\n            .getNormalTemplateByCluster(content.getPhyClusterName()).stream().map(IndexTemplatePhy::getName)\n            .collect(Collectors.toList());\n        if (CollectionUtils.isNotEmpty(templatePhyNameList)) {\n            return Result.buildFail(String.format(\"物理集群[%s]中已经存在模板[%s]\", content.getPhyClusterName(),\n                ListUtils.strList2String(templatePhyNameList)));\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        ClusterDeleteContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterDeleteContent.class);\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getPhyClusterName() + workOrderTypeEnum.getMessage();\n    }\n\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        if (!isOP(workOrder.getSubmitor())) {\n            return Result.buildOpForBidden(\"非运维人员不能操作集群扩缩容！\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) {\n        ClusterDeleteContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterDeleteContent.class);\n        final Result<ClusterPhy> clusterPhyResult = clusterPhyManager.getClusterByName(content.getPhyClusterName());\n        if (null == clusterPhyResult.getData()) {\n            return Result.buildFail(String.format(\"物理集群[%s]不存在\", content.getPhyClusterName()));\n        }\n\n        Result<Boolean> deleteClusterResult = clusterPhyManager.deleteCluster(clusterPhyResult.getData().getId(),\n            workOrder.getSubmitor(), AuthConstant.SUPER_PROJECT_ID);\n        if (deleteClusterResult.failed()) {\n            return Result.buildFail(deleteClusterResult.getMessage());\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        return ConvertUtil.obj2Obj(extensions, ClusterDeleteOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/ClusterOpIndecreaseHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_DOCKER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_HOST;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterBaseContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterIndecreaseDockerContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterIndecreaseHostContent;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.utils.OpOrderTaskConverter;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostScaleActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.ClusterOpIndecreaseDockerOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.ClusterOpIndecreaseHostOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.EcmHandleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * 集群op indecrease处理程序\n *\n * @author\n * @date 2022/05/09\n */\n@Service(\"clusterOpIndecreaseHandler\")\n@Deprecated\npublic class ClusterOpIndecreaseHandler extends BaseWorkOrderHandler {\n    protected static final ILog    LOGGER = LogFactory.getLog(ClusterOpIndecreaseHandler.class);\n\n    @Autowired\n    private RoleTool               roleTool;\n\n    @Autowired\n    private ClusterPhyService      esClusterPhyService;\n\n    @Autowired\n    private ESClusterService       esClusterService;\n\n    @Autowired\n    private EcmHandleService       ecmHandleService;\n\n    @Autowired\n    private ClusterRoleHostService clusterRoleHostService;\n\n    @Autowired\n    private OpTaskManager          opTaskManager;\n\n    @Override\n    protected Result validateConsoleParam(WorkOrder workOrder) throws NotFindSubclassException {\n\n        ClusterBaseContent baseContent = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterBaseContent.class);\n\n        if (ES_DOCKER.getCode() == baseContent.getType()) {\n            ClusterIndecreaseDockerContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                ClusterIndecreaseDockerContent.class);\n\n            if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n                return Result.buildParamIllegal(\"物理集群id为空\");\n            }\n\n            ClusterPhy clusterPhy = esClusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n            if (AriusObjUtils.isNull(clusterPhy)) {\n                return Result.buildParamIllegal(\"物理集群不存在\");\n            }\n\n            if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n                OpTaskTypeEnum.CLUSTER_EXPAND.getType())) {\n                return Result.buildParamIllegal(\"该集群上存在未完成的任务\");\n            }\n\n            return Result.buildSucc();\n        } else if (ES_HOST.getCode() == baseContent.getType()) {\n            initParam(workOrder);\n            ClusterIndecreaseHostContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                ClusterIndecreaseHostContent.class);\n\n            if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n                return Result.buildParamIllegal(\"物理集群id为空\");\n            }\n\n            ClusterPhy clusterPhy = esClusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n            if (AriusObjUtils.isNull(clusterPhy)) {\n                return Result.buildParamIllegal(\"物理集群不存在\");\n            }\n\n            if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n                OpTaskTypeEnum.CLUSTER_EXPAND.getType())) {\n                return Result.buildParamIllegal(\"该集群上存在未完成的集群扩缩容任务\");\n            }\n\n            // 对于datanode的缩容，如果该节点上存在数据分片,做出警告\n            if (content.getOperationType() == OpTaskTypeEnum.CLUSTER_SHRINK.getType()) {\n                Map<String, Integer> segmentsOfIpByCluster = null;\n                try {\n                    segmentsOfIpByCluster = esClusterService\n                        .synGetSegmentsOfIpByCluster(content.getPhyClusterName());\n                } catch (ESOperateException e) {\n                    LOGGER.error(\"class=ClusterOpIndecreaseHandler||method=validateConsoleParam||errMsg=fail to get segments of ip by cluster\",\n                            e);\n                    Result.buildFail(\"获取集群ip上的segment数目异常\");\n                }\n\n                for (ESClusterRoleHost esClusterRoleHost : content.getClusterRoleHosts()) {\n                    if (esClusterRoleHost.getRole().equals(ESClusterNodeRoleEnum.DATA_NODE.getDesc())\n                        && segmentsOfIpByCluster.containsKey(esClusterRoleHost.getHostname())\n                        && !segmentsOfIpByCluster.get(esClusterRoleHost.getHostname()).equals(0)) {\n                        return Result.buildFail(\"数据节点上存在分片，请迁移分片之后再进行该节点的缩容\");\n                    }\n                }\n            }\n\n            return Result.buildSucc();\n        } else {\n            return Result.buildFail(\"type 类型不对\");\n        }\n\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        ClusterBaseContent baseContent = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterBaseContent.class);\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n\n        return baseContent.getPhyClusterName() + workOrderTypeEnum.getMessage();\n    }\n\n    @Override\n    protected Result validateConsoleAuth(WorkOrder workOrder) {\n        if (!roleTool.isAdmin(workOrder.getSubmitor())) {\n            return Result.buildOpForBidden(\"非运维人员不能操作集群扩缩容！\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        ClusterBaseContent clusterBaseContent = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterBaseContent.class);\n\n        EcmTaskDTO esEcmTaskDTO = new EcmTaskDTO();\n        esEcmTaskDTO.setWorkOrderId(workOrder.getId());\n        esEcmTaskDTO.setTitle(workOrder.getTitle());\n        esEcmTaskDTO.setCreator(workOrder.getSubmitor());\n        esEcmTaskDTO.setType(clusterBaseContent.getType());\n\n        if (ES_DOCKER.getCode() == clusterBaseContent.getType()) {\n            ClusterIndecreaseDockerContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                ClusterIndecreaseDockerContent.class);\n            esEcmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n            esEcmTaskDTO.setOrderType(content.getOperationType());\n            List<EcmParamBase> ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ES_DOCKER,\n                OpTaskTypeEnum.valueOfType(content.getOperationType()), content);\n            esEcmTaskDTO.setClusterNodeRole(ListUtils\n                .strList2String(ecmParamBaseList.stream().map(EcmParamBase::getRoleName).collect(Collectors.toList())));\n            esEcmTaskDTO.setEcmParamBaseList(ecmParamBaseList);\n        } else if (ES_HOST.getCode() == clusterBaseContent.getType()) {\n            ClusterIndecreaseHostContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                ClusterIndecreaseHostContent.class);\n            esEcmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n            esEcmTaskDTO.setOrderType(content.getOperationType());\n\n            List<EcmParamBase> hostScaleParamBaseList = getHostScaleParamBaseList(content.getPhyClusterId().intValue(),\n                content.getClusterRoleHosts(), content.getPidCount());\n\n            esEcmTaskDTO.setClusterNodeRole(ListUtils.strList2String(\n                hostScaleParamBaseList.stream().map(EcmParamBase::getRoleName).collect(Collectors.toList())));\n            esEcmTaskDTO.setEcmParamBaseList(hostScaleParamBaseList);\n        } else {\n            return Result.buildFail(\"type 类型不对\");\n        }\n\n        OpTaskDTO opTaskDTO = new OpTaskDTO();\n        opTaskDTO.setExpandData(JSON.toJSONString(esEcmTaskDTO));\n        opTaskDTO.setTaskType(esEcmTaskDTO.getOrderType());\n        opTaskDTO.setCreator(workOrder.getSubmitor());\n        Result<OpTask> result = opTaskManager.addTask(opTaskDTO, AuthConstant.SUPER_PROJECT_ID);\n        if (null == result || result.failed()) {\n            return Result.buildFail(\"生成集群新建操作任务失败!\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        ClusterBaseContent baseContent = ConvertUtil.obj2ObjByJSON(JSON.parse(extensions), ClusterBaseContent.class);\n\n        if (ES_DOCKER.getCode() == baseContent.getType()) {\n            ClusterIndecreaseDockerContent content = JSON.parseObject(JSON.parse(extensions).toString(),\n                ClusterIndecreaseDockerContent.class);\n\n            return ConvertUtil.obj2Obj(content, ClusterOpIndecreaseDockerOrderDetail.class);\n        } else if (ES_HOST.getCode() == baseContent.getType()) {\n            ClusterIndecreaseHostContent content = JSON.parseObject(JSON.parse(extensions).toString(),\n                ClusterIndecreaseHostContent.class);\n\n            return ConvertUtil.obj2Obj(content, ClusterOpIndecreaseHostOrderDetail.class);\n        }\n        return null;\n\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc(true);\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    private List<EcmParamBase> getHostScaleParamBaseList(Integer phyClusterId, List<ESClusterRoleHost> roleClusterHosts,\n                                                         Integer pidCount) {\n        List<String> roleNameList = new ArrayList<>();\n        for (ESClusterRoleHost clusterRoleHost : roleClusterHosts) {\n            if (!roleNameList.contains(clusterRoleHost.getRole())) {\n                roleNameList.add(clusterRoleHost.getRole());\n            }\n        }\n\n        List<EcmParamBase> ecmParamBaseList = ecmHandleService.buildEcmParamBaseList(phyClusterId, roleNameList)\n            .getData();\n        return buildHostScaleParamBaseList(roleClusterHosts, pidCount, roleNameList, ecmParamBaseList);\n    }\n\n    private void initParam(WorkOrder workOrder) {\n        ClusterIndecreaseHostContent clusterOpIndecreaseHostContent = ConvertUtil\n            .obj2ObjByJSON(workOrder.getContentObj(), ClusterIndecreaseHostContent.class);\n        if (ES_HOST.getCode() == clusterOpIndecreaseHostContent.getType()) {\n            // 如果当前角色对应pid_count为null，则设置为默认值1\n            if (null == clusterOpIndecreaseHostContent.getPidCount()) {\n                clusterOpIndecreaseHostContent.setPidCount(ClusterConstant.DEFAULT_CLUSTER_PAID_COUNT);\n            }\n\n            // 填充工单中的ip字段,port端口号填充\n            Map<String, String> portOfRoleMapFromHost = getPortOfRoleMapFromHost(\n                clusterOpIndecreaseHostContent.getPhyClusterId());\n            for (ESClusterRoleHost esClusterRoleHost : clusterOpIndecreaseHostContent.getClusterRoleHosts()) {\n                esClusterRoleHost\n                    .setIp(Getter.strWithDefault(esClusterRoleHost.getIp(), esClusterRoleHost.getHostname()));\n                esClusterRoleHost.setPort(portOfRoleMapFromHost.get(esClusterRoleHost.getRole()));\n            }\n\n            workOrder.setContentObj(JSON.toJSON(clusterOpIndecreaseHostContent));\n        }\n    }\n\n    private List<EcmParamBase> buildHostScaleParamBaseList(List<ESClusterRoleHost> roleClusterHosts, Integer pidCount,\n                                                           List<String> roleNameList,\n                                                           List<EcmParamBase> ecmParamBaseList) {\n        List<EcmParamBase> hostScaleParamBaseList = new ArrayList<>();\n        for (String roleName : roleNameList) {\n            List<String> hostnameList = new ArrayList<>();\n            for (ESClusterRoleHost clusterRoleHost : roleClusterHosts) {\n                if (roleName.equals(clusterRoleHost.getRole())) {\n                    if (AriusObjUtils.isBlank(clusterRoleHost.getHostname())) {\n                        continue;\n                    }\n                    hostnameList.add(clusterRoleHost.getHostname());\n                }\n            }\n            for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n                if (roleName.equals(ecmParamBase.getRoleName())) {\n                    HostParamBase hostParamBase = (HostParamBase) ecmParamBase;\n\n                    HostScaleActionParam hostScaleActionParam = ConvertUtil.obj2Obj(hostParamBase,\n                        HostScaleActionParam.class);\n                    hostScaleActionParam.setPidCount(pidCount);\n                    hostScaleActionParam.setHostList(hostnameList);\n                    hostScaleActionParam.setNodeNumber(hostnameList.size());\n\n                    hostScaleParamBaseList.add(hostScaleActionParam);\n                }\n            }\n        }\n        return hostScaleParamBaseList;\n    }\n\n    /**\n     * 从db中获取物理集群角色下的端口号信息\n     * @return 物理集群下的角色端口map\n     */\n    private Map<String/*角色名称*/, String/*端口号*/> getPortOfRoleMapFromHost(Long phyClusterId) {\n        Map<String, String> rolePortMap = new HashMap<>(ESClusterNodeRoleEnum.values().length);\n        for (ESClusterNodeRoleEnum param : ESClusterNodeRoleEnum.values()) {\n            if (param != ESClusterNodeRoleEnum.UNKNOWN) {\n                List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService.getByRoleAndClusterId(phyClusterId,\n                    param.getDesc());\n                // 默认采用8060端口进行es集群的搭建\n                rolePortMap.put(param.getDesc(),\n                    CollectionUtils.isEmpty(clusterRoleHosts) ? ClusterConstant.DEFAULT_PORT\n                        : clusterRoleHosts.get(0).getPort());\n            }\n        }\n\n        return rolePortMap;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/ClusterOpNewHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.CREATE_MASTER_NODE_MIN_NUMBER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.MASTER_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_DOCKER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_HOST;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterBaseContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterNewDockerContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterNewHostContent;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.utils.OpOrderTaskConverter;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleDocker;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.ClusterOpNewDockerOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.ClusterOpNewHostOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPackageService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.google.common.collect.Maps;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * 集群op新处理程序\n *\n * @author\n * @date 2022/05/09\n */\n@Service(\"clusterOpNewHandler\")\n@Deprecated\npublic class ClusterOpNewHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private OpTaskManager       opTaskManager;\n\n    @Autowired\n    private ClusterPhyService   esClusterPhyService;\n\n    @Autowired\n    private ESPackageService    esPackageService;\n\n    private static final String PARAM_ILLEGAL_TIPS = \"集群缺少类型为%s的节点\";\n\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        Result<Void> initResult = initParam(workOrder);\n        if (initResult.failed()) {\n            return Result.buildFrom(initResult);\n        }\n\n        ClusterBaseContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterBaseContent.class);\n        Result<Void> doValidateHostTypeResult = validateClusterMasterNodeNumber(content, workOrder);\n        if (doValidateHostTypeResult.failed()) {\n            return doValidateHostTypeResult;\n        }\n\n        if (AriusObjUtils.isNull(content.getPhyClusterName())) {\n            return Result.buildParamIllegal(\"物理集群名称为空\");\n        }\n\n        if (esClusterPhyService.isClusterExists(content.getPhyClusterName())) {\n            return Result.buildParamIllegal(\"物理集群名称不能重复\");\n        }\n\n        //ES同一个角色的端口号应该相同，拆解ip和port后进行校验\n        Result<Void> doValidRoleClusterPort = validRoleClusterPort(workOrder);\n        if (doValidRoleClusterPort.failed()) {\n            return Result.buildFrom(doValidRoleClusterPort);\n        }\n\n        ClusterNewHostContent clusterOpNewHostContent = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterNewHostContent.class);\n        // es版本的\n        if (null == esPackageService.getByVersionAndType(clusterOpNewHostContent.getEsVersion(), ES_HOST.getCode())) {\n            return Result.buildFail(ES_HOST.getDesc() + \"类型版本为\" + clusterOpNewHostContent.getEsVersion() + \"的程序包不存在\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        ClusterBaseContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterBaseContent.class);\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getPhyClusterName() + workOrderTypeEnum.getMessage();\n    }\n\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        if (!isOP(workOrder.getSubmitor())) {\n            return Result.buildOpForBidden(\"非运维人员不能操作集群扩缩容！\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        ClusterBaseContent clusterBaseContent = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterBaseContent.class);\n\n        EcmTaskDTO ecmTaskDTO = new EcmTaskDTO();\n        ecmTaskDTO.setWorkOrderId(workOrder.getId());\n        ecmTaskDTO.setTitle(workOrder.getTitle());\n        ecmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_NEW.getType());\n        ecmTaskDTO.setType(clusterBaseContent.getType());\n        ecmTaskDTO.setCreator(workOrder.getSubmitor());\n        ecmTaskDTO.setPhysicClusterId(ClusterConstant.INVALID_VALUE);\n\n        // 工单数据 转 handle data\n        List<EcmParamBase> ecmParamBaseList = null;\n        if (ES_DOCKER.getCode() == clusterBaseContent.getType()) {\n            ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ESClusterTypeEnum.ES_DOCKER,\n                OpTaskTypeEnum.CLUSTER_NEW,\n                ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterNewDockerContent.class));\n        } else if (ES_HOST.getCode() == clusterBaseContent.getType()) {\n            // 获取并且设置新建集群工单内容中的集群创建人信息\n            ClusterNewHostContent clusterOpNewHostContent = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                ClusterNewHostContent.class);\n            clusterOpNewHostContent.setCreator(workOrder.getSubmitor());\n\n            ecmParamBaseList = OpOrderTaskConverter.convert2EcmParamBaseList(ESClusterTypeEnum.ES_HOST,\n                OpTaskTypeEnum.CLUSTER_NEW, clusterOpNewHostContent);\n        } else {\n            return Result.buildFail(\"集群类型(Docker|Host)错误\");\n        }\n\n        ecmTaskDTO.setEcmParamBaseList(ecmParamBaseList);\n\n        OpTaskDTO opTaskDTO = new OpTaskDTO();\n        opTaskDTO.setTaskType(OpTaskTypeEnum.CLUSTER_NEW.getType());\n        opTaskDTO.setCreator(workOrder.getSubmitor());\n        opTaskDTO.setExpandData(ConvertUtil.obj2Json(ecmTaskDTO));\n\n        Result<OpTask> result = opTaskManager.addTask(opTaskDTO, AuthConstant.SUPER_PROJECT_ID);\n        if (null == result || result.failed()) {\n            return Result.buildFail(\"生成集群新建操作任务失败!\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        ClusterBaseContent clusterBaseContent = ConvertUtil.obj2ObjByJSON(JSON.parse(extensions),\n            ClusterBaseContent.class);\n\n        if (ES_DOCKER.getCode() == clusterBaseContent.getType()) {\n            ClusterNewDockerContent content = JSON.parseObject(JSON.parse(extensions).toString(),\n                ClusterNewDockerContent.class);\n\n            return ConvertUtil.obj2Obj(content, ClusterOpNewDockerOrderDetail.class);\n        } else if (ES_HOST.getCode() == clusterBaseContent.getType()) {\n            ClusterNewHostContent content = JSON.parseObject(JSON.parse(extensions).toString(),\n                ClusterNewHostContent.class);\n\n            return ConvertUtil.obj2Obj(content, ClusterOpNewHostOrderDetail.class);\n        } else {\n            return null;\n        }\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /*******************************************private************************************************/\n\n    private Result<Void> validateClusterMasterNodeNumber(ClusterBaseContent content, WorkOrder workOrder) {\n        if (ES_HOST.getCode() == content.getType()) {\n            return validateClusterMasterNodeNumberESHost(workOrder);\n        } else if (ES_DOCKER.getCode() == content.getType()) {\n            return validateClusterMasterNodeNumberESDocker(workOrder);\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> initParam(WorkOrder workOrder) {\n        ClusterNewHostContent clusterOpNewHostContent = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterNewHostContent.class);\n\n        // 校验pid_count（单节点实例数字段）,如果为null，则设置默认值1\n        if (null == clusterOpNewHostContent.getPidCount()) {\n            clusterOpNewHostContent.setPidCount(ClusterConstant.DEFAULT_CLUSTER_PAID_COUNT);\n        }\n\n        // 对于address字段进行ip和端口号的拆分\n        List<ESClusterRoleHost> roleClusterHosts = clusterOpNewHostContent.getClusterRoleHosts();\n\n        for (ESClusterRoleHost esClusterRoleHost : roleClusterHosts) {\n            if (null == esClusterRoleHost.getAddress()) {\n                return Result.buildFail(\"传入节点的address不应该为空\");\n            }\n            // 将ip和port中hostname中拆分出来\n            String[] ipAndPort = esClusterRoleHost.getAddress().split(\":\");\n            if (ipAndPort.length < 2) {\n                return Result.buildFail(\"传入节点的address应该满足【ip:port】格式\");\n            }\n            esClusterRoleHost.setHostname(ipAndPort[0]);\n            esClusterRoleHost.setIp(ipAndPort[0]);\n            esClusterRoleHost.setPort(ipAndPort[1]);\n        }\n\n        workOrder.setContentObj(JSON.toJSON(clusterOpNewHostContent));\n        return Result.buildSucc();\n    }\n\n    private Result<Void> validateClusterMasterNodeNumberESDocker(WorkOrder workOrder) {\n        ClusterBaseContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterNewDockerContent.class);\n\n        List<ESClusterRoleDocker> roleClusterDockers = ((ClusterNewDockerContent) content).getRoleClusters();\n        if (CollectionUtils.isEmpty(roleClusterDockers)) {\n            return Result.buildParamIllegal(\"集群角色为空\");\n        }\n\n        Set<String> dockerRoles = roleClusterDockers.stream().map(ESClusterRoleDocker::getRole)\n            .collect(Collectors.toSet());\n        if (!dockerRoles.contains(MASTER_NODE.getDesc())) {\n            return Result.buildParamIllegal(String.format(PARAM_ILLEGAL_TIPS, MASTER_NODE.getDesc()));\n        }\n\n        Integer masterNodesNumber = roleClusterDockers.stream().filter(r -> MASTER_NODE.getDesc().equals(r.getRole()))\n            .map(ESClusterRoleDocker::getPodNumber).collect(Collectors.toList()).get(0);\n\n        if (masterNodesNumber < CREATE_MASTER_NODE_MIN_NUMBER) {\n            return Result.buildParamIllegal(\"masternode角色pod数量要求大于等于1\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> validateClusterMasterNodeNumberESHost(WorkOrder workOrder) {\n        ClusterBaseContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterNewHostContent.class);\n\n        List<ESClusterRoleHost> roleClusterHosts = ((ClusterNewHostContent) content).getClusterRoleHosts();\n        if (CollectionUtils.isEmpty(roleClusterHosts)) {\n            return Result.buildParamIllegal(\"集群角色为空\");\n        }\n\n        Set<String> hostRoles = roleClusterHosts.stream().map(ESClusterRoleHost::getRole).collect(Collectors.toSet());\n        if (!hostRoles.contains(MASTER_NODE.getDesc())) {\n            return Result.buildParamIllegal(String.format(PARAM_ILLEGAL_TIPS, MASTER_NODE.getDesc()));\n        }\n\n        List<ESClusterRoleHost> masterNodes = roleClusterHosts.stream()\n            .filter(r -> MASTER_NODE.getDesc().equals(r.getRole())).collect(Collectors.toList());\n\n        if (masterNodes.size() < CREATE_MASTER_NODE_MIN_NUMBER) {\n            return Result.buildParamIllegal(\"masternode角色ip个数要求大于等于1\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> validRoleClusterPort(WorkOrder workOrder) {\n        ClusterNewHostContent clusterOpNewHostContent = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterNewHostContent.class);\n        List<ESClusterRoleHost> roleClusterHosts = clusterOpNewHostContent.getClusterRoleHosts();\n\n        Map<Object, Object> roleClusterPortMap = Maps.newHashMap();\n        for (ESClusterRoleHost esClusterRoleHost : roleClusterHosts) {\n            // 如果map中不存在角色ip信息，则进行put\n            if (!roleClusterPortMap.containsKey(esClusterRoleHost.getRole())) {\n                roleClusterPortMap.put(esClusterRoleHost.getRole(), esClusterRoleHost.getPort());\n                continue;\n            }\n\n            if (roleClusterPortMap.containsKey(esClusterRoleHost.getRole())\n                && !roleClusterPortMap.get(esClusterRoleHost.getRole()).equals(esClusterRoleHost.getPort())) {\n                return Result.buildFail(\"同一个集群中同一角色的端口号应该相同\");\n            }\n        }\n\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/ClusterOpOfflineHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterOfflineContent;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.ClusterOpOfflineOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-24\n */\n@Service(\"clusterOpOfflineHandler\")\n@Deprecated\npublic class ClusterOpOfflineHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private ClusterPhyService esClusterPhyService;\n\n    @Autowired\n    private OpTaskManager     opTaskManager;\n    @Autowired\n    private RoleTool          roleTool;\n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        ClusterOfflineContent content = JSON.parseObject(extensions, ClusterOfflineContent.class);\n\n        return ConvertUtil.obj2Obj(content, ClusterOpOfflineOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**************************************** protected method ******************************************/\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) throws NotFindSubclassException {\n        ClusterOfflineContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterOfflineContent.class);\n\n        if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n            return Result.buildParamIllegal(\"物理集群id为空\");\n        }\n\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildParamIllegal(\"物理集群不存在\");\n        }\n\n        if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n            OpTaskTypeEnum.CLUSTER_OFFLINE.getType())) {\n            return Result.buildParamIllegal(\"该集群上存在未完成的任务\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        ClusterOfflineContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterOfflineContent.class);\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getPhyClusterName() + workOrderTypeEnum.getMessage();\n    }\n\n    /**\n     * 验证用户是否有该工单权限\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        //管理员能扩缩容\n        if (!roleTool.isAdmin(workOrder.getSubmitor())) {\n            return Result.buildOpForBidden(\"非运维人员不能操作集群扩缩容！\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证平台参数\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        ClusterOfflineContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterOfflineContent.class);\n\n        EcmTaskDTO ecmTaskDTO = new EcmTaskDTO();\n        ecmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n        ecmTaskDTO.setWorkOrderId(workOrder.getId());\n        ecmTaskDTO.setTitle(content.getPhyClusterName() + \"集群下线任务\");\n        ecmTaskDTO.setOrderType(5);\n        ecmTaskDTO.setCreator(workOrder.getSubmitor());\n\n        OpTaskDTO opTaskDTO = new OpTaskDTO();\n        opTaskDTO.setCreator(workOrder.getSubmitor());\n        opTaskDTO.setExpandData(JSON.toJSONString(ecmTaskDTO));\n        opTaskDTO.setTaskType(OpTaskTypeEnum.CLUSTER_OFFLINE.getType());\n        Result<OpTask> result = opTaskManager.addTask(opTaskDTO, AuthConstant.SUPER_PROJECT_ID);\n        if (null == result || result.failed()) {\n            return Result.buildFail(\"生成集群新建操作任务失败!\");\n        }\n\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/ClusterOpUpdateHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_HOST;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterUpdateContent;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord.Builder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud.ElasticCloudCommonActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.espackage.ESPackage;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.ClusterOpUpdateOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPackageService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.EcmHandleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport java.util.List;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * 集群op更新处理程序\n *\n * @author\n * @date 2022/05/09\n */\n@Service(\"clusterOpUpdateHandler\")\n@Deprecated\npublic class ClusterOpUpdateHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private RoleTool          roleTool;\n\n    @Autowired\n    private ClusterPhyService esClusterPhyService;\n\n    @Autowired\n    private ESPackageService  esPackageService;\n\n    @Autowired\n    private EcmHandleService  ecmHandleService;\n\n    @Autowired\n    private OpTaskManager     opTaskManager;\n    @Autowired\n    private ProjectService projectService;\n\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) throws NotFindSubclassException {\n        ClusterUpdateContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterUpdateContent.class);\n\n        if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n            return Result.buildParamIllegal(\"物理集群id为空\");\n        }\n\n        if (StringUtils.isBlank(content.getRoleOrder())) {\n            return Result.buildParamIllegal(\"物理集群升级角色顺序为空\");\n        }\n\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildParamIllegal(\"物理集群不存在\");\n        }\n\n        if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n            OpTaskTypeEnum.CLUSTER_UPGRADE.getType())) {\n            return Result.buildParamIllegal(\"该集群上存在未完成的任务\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        ClusterUpdateContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterUpdateContent.class);\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getPhyClusterName() + workOrderTypeEnum.getMessage();\n    }\n\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        if (!roleTool.isAdmin(workOrder.getSubmitor())) {\n            return Result.buildOpForBidden(\"非运维人员不能操作物理集群升级！\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws NotFindSubclassException {\n        ClusterUpdateContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), ClusterUpdateContent.class);\n        //获取物理集群名称旧版本的版本号\n        final String beforeEsVersion = esClusterPhyService.getClusterByName(content.getPhyClusterName()).getEsVersion();\n        EcmTaskDTO ecmTaskDTO = new EcmTaskDTO();\n        ecmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n        ecmTaskDTO.setWorkOrderId(workOrder.getId());\n        ecmTaskDTO.setTitle(workOrder.getTitle());\n        ecmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_UPGRADE.getType());\n        ecmTaskDTO.setCreator(workOrder.getSubmitor());\n\n        Result<List<EcmParamBase>> ecmParamBaseResult = ecmHandleService.buildEcmParamBaseList(\n            content.getPhyClusterId().intValue(), ConvertUtil.str2ObjArrayByJson(content.getRoleOrder(), String.class));\n\n        if (ecmParamBaseResult.failed()) {\n            return Result.buildFail(ecmParamBaseResult.getMessage());\n        }\n\n        List<EcmParamBase> ecmParamBaseList = ecmParamBaseResult.getData();\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            // 补充version信息\n            ESPackage esPackage = esPackageService.getByVersionAndType(content.getEsVersion(), ecmParamBase.getType());\n\n            if (ecmParamBase.getType().equals(ES_HOST.getCode())) {\n                ((HostParamBase) ecmParamBase).setEsVersion(content.getEsVersion());\n                if (!AriusObjUtils.isNull(esPackage) && !AriusObjUtils.isBlack(esPackage.getUrl())) {\n                    ((HostParamBase) ecmParamBase).setImageName(esPackage.getUrl());\n                }\n            } else {\n                ((ElasticCloudCommonActionParam) ecmParamBase).setEsVersion(content.getEsVersion());\n                if (!AriusObjUtils.isNull(esPackage) && !AriusObjUtils.isBlack(esPackage.getUrl())) {\n                    ((ElasticCloudCommonActionParam) ecmParamBase).setImageName(esPackage.getUrl());\n                }\n            }\n        }\n\n        ecmTaskDTO.setType(ecmParamBaseList.get(0).getType());\n        ecmTaskDTO.setEcmParamBaseList(ecmParamBaseList);\n\n        OpTaskDTO opTaskDTO = new OpTaskDTO();\n        opTaskDTO.setCreator(workOrder.getSubmitor());\n        opTaskDTO.setTaskType(OpTaskTypeEnum.CLUSTER_UPGRADE.getType());\n        opTaskDTO.setExpandData(JSON.toJSONString(ecmTaskDTO));\n        Result<OpTask> result = opTaskManager.addTask(opTaskDTO, AuthConstant.SUPER_PROJECT_ID);\n        if (null == result || result.failed()) {\n            return Result.buildFail(\"生成集群新建操作任务失败!\");\n        }\n        //版本升级的操作记录\n        final OperateRecord operateRecord = new Builder().userOperation(opTaskDTO.getCreator())\n                .project(projectService.getProjectBriefByProjectId(workOrder.getSubmitorProjectId()))\n                .operationTypeEnum(OperateTypeEnum.PHYSICAL_CLUSTER_RESTART)\n                .content(String.format(\"【%s】->【%s】\",beforeEsVersion,\n                        content.getEsVersion()))\n                .bizId(content.getPhyClusterId())\n                .buildDefaultManualTrigger();\n        operateRecordService.save(operateRecord);\n        return Result.buildSucc();\n    }\n\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        ClusterUpdateContent content = JSON.parseObject(extensions, ClusterUpdateContent.class);\n\n        return ConvertUtil.obj2Obj(content, ClusterOpUpdateOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc(true);\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/DslTemplateQueryLimitHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.dsl.DslTemplateManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.DslTemplateQueryLimitContent;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.DslTemplateStatusContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.DslTemplateQueryLimitDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * @author wuxuan\n * @date 2022/11/15\n */\n@Service(\"dslTemplateQueryLimitHandler\")\npublic class DslTemplateQueryLimitHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private DslTemplateManager dslTemplateManager;\n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        DslTemplateQueryLimitContent content = JSON.parseObject(extensions, DslTemplateQueryLimitContent.class);\n        return ConvertUtil.obj2Obj(content, DslTemplateQueryLimitDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        DslTemplateQueryLimitContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),DslTemplateQueryLimitContent.class);\n\n        if (AriusObjUtils.isNull(content.getProjectId())) {\n            return Result.buildParamIllegal(\"项目id为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getDslQueryLimitDTOList())) {\n            return Result.buildParamIllegal(\"查询语句限流值相关参数为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getOperator())) {\n            return Result.buildParamIllegal(\"操作者为空\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        DslTemplateStatusContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                DslTemplateStatusContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return workOrderTypeEnum.getMessage();\n    }\n\n\n    /**************************************** protected method ******************************************/\n\n    /**\n     * 验证用户是否有该工单权限\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证平台参数\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        DslTemplateQueryLimitContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                DslTemplateQueryLimitContent.class);\n\n        Result<Boolean> result = dslTemplateManager.updateDslTemplateQueryLimit(content.getProjectId(),\n                content.getOperator(), content.getDslQueryLimitDTOList());\n\n        return Result.buildFrom(result);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/DslTemplateStatusChangeHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.dsl.DslTemplateManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.DslTemplateStatusContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.DslTemplateStatusDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * @author wuxuan\n * @date 2022/11/14\n */\n@Service(\"dslTemplateStatusChangeHandler\")\npublic class DslTemplateStatusChangeHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private DslTemplateManager dslTemplateManager;\n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        DslTemplateStatusContent content = JSON.parseObject(extensions, DslTemplateStatusContent.class);\n\n        return ConvertUtil.obj2Obj(content, DslTemplateStatusDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        DslTemplateStatusContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),DslTemplateStatusContent.class);\n\n        if (AriusObjUtils.isNull(content.getProjectId())) {\n            return Result.buildParamIllegal(\"项目id为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getDslTemplateMd5())) {\n            return Result.buildParamIllegal(\"dslTemplateMd5为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getOperator())) {\n            return Result.buildParamIllegal(\"操作者为空\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        DslTemplateStatusContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                DslTemplateStatusContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n\n        return content.getDslTemplateMd5() + workOrderTypeEnum.getMessage();\n    }\n\n\n    /**************************************** protected method ******************************************/\n\n    /**\n     * 验证用户是否有该工单权限\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证平台参数\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        DslTemplateStatusContent dslTemplateStatusContent = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                DslTemplateStatusContent.class);\n\n        Result<Boolean> result = dslTemplateManager.changeDslTemplateStatus(dslTemplateStatusContent.getProjectId(),\n                dslTemplateStatusContent.getOperator(), dslTemplateStatusContent.getDslTemplateMd5());\n\n        if (result.success()) {\n            //操作记录\n            //查询模板读写变更记录\n            operateRecordService.save(new OperateRecord.Builder().operationTypeEnum(OperateTypeEnum.QUERY_TEMPLATE_STATUS_CHANGE)\n                    .project(projectService.getProjectBriefByProjectId(workOrder.getSubmitorProjectId()))\n                    .content(String.format(\"项目%d的查询模板%s启用/禁用状态变更\", dslTemplateStatusContent.getProjectId(),dslTemplateStatusContent.getDslTemplateMd5()))\n                    .userOperation(workOrder.getSubmitor())\n                    .buildDefaultManualTrigger());\n        }\n\n        return Result.buildFrom(result);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/LogicClusterAuthHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.LogicClusterAuthContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.LogicClusterAuthOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectClusterLogicAuthService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service(\"logicClusterAuthHandler\")\npublic class LogicClusterAuthHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private ClusterLogicService            clusterLogicService;\n    @Autowired\n    private ProjectService                 projectService;\n\n    @Autowired\n    private ProjectClusterLogicAuthService projectClusterLogicAuthService;\n\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        LogicClusterAuthContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterAuthContent.class);\n\n        if (AriusObjUtils.isNull(content.getLogicClusterId())) {\n            return Result.buildParamIllegal(\"逻辑集群id为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getAuthCode())) {\n            return Result.buildParamIllegal(\"申请的权限为空\");\n        }\n\n        if (!clusterLogicService.existClusterLogicById(content.getLogicClusterId())) {\n            return Result.buildParamIllegal(\"集群不存在\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        LogicClusterAuthContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterAuthContent.class);\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getLogicClusterName() + workOrderTypeEnum.getMessage();\n    }\n\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        LogicClusterAuthContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterAuthContent.class);\n\n        \n        return  projectClusterLogicAuthService.ensureSetLogicClusterAuth(workOrder.getSubmitorProjectId(),\n            content.getLogicClusterId(), ProjectClusterLogicAuthEnum.valueOf(content.getAuthCode()), workOrder.getSubmitor());\n    }\n\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        LogicClusterAuthContent content = JSON.parseObject(extensions, LogicClusterAuthContent.class);\n\n        return ConvertUtil.obj2Obj(content, LogicClusterAuthOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/LogicClusterCreateHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterLogicManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.LogicClusterCreateContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterWithRegionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.LogicClusterCreateOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\n@Service(\"logicClusterCreateHandler\")\npublic class LogicClusterCreateHandler extends BaseWorkOrderHandler {\n\n   \n\n    @Autowired\n    private ClusterLogicManager clusterLogicManager;\n    \n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        LogicClusterCreateContent content = JSON.parseObject(extensions, LogicClusterCreateContent.class);\n\n        return ConvertUtil.obj2Obj(content, LogicClusterCreateOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    /**************************************** protected method ******************************************/\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        LogicClusterCreateContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterCreateContent.class);\n\n        ESLogicClusterDTO resourceLogicDTO = ConvertUtil.obj2Obj(content, ESLogicClusterDTO.class);\n        resourceLogicDTO.setProjectId(workOrder.getSubmitorProjectId());\n        resourceLogicDTO.setType(ClusterResourceTypeEnum.PRIVATE.getCode());\n        return clusterLogicManager.validateClusterLogicParams(resourceLogicDTO,\n                \n                OperationEnum.ADD,\n            resourceLogicDTO.getProjectId());\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        LogicClusterCreateContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterCreateContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getName() + workOrderTypeEnum.getMessage();\n    }\n\n    /**\n     * 验证用户是否有该工单权限\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单 这里分为两种，一种是分配逻辑集群，一种是申请逻辑集群，其中申请逻辑集群不会绑定region，会联系同学在运维侧进行操作\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        ESLogicClusterWithRegionDTO esLogicClusterWithRegionDTO = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ESLogicClusterWithRegionDTO.class);\n        esLogicClusterWithRegionDTO.setProjectId(workOrder.getSubmitorProjectId());\n    \n        if (CollectionUtils.isEmpty(esLogicClusterWithRegionDTO.getClusterRegionDTOS())) {\n            return Result.buildFail(\"集群未绑定region\");\n        }\n        Result<Void> result = clusterLogicManager.addLogicClusterAndClusterRegions(esLogicClusterWithRegionDTO,\n                approver);\n        \n        if (result.success()) {\n            //操作记录\n            //逻辑集群创建添加操作记录\n            operateRecordService.save(new OperateRecord.Builder().operationTypeEnum(OperateTypeEnum.MY_CLUSTER_APPLY)\n                    .bizId(esLogicClusterWithRegionDTO.getName())\n                    .project(projectService.getProjectBriefByProjectId(workOrder.getSubmitorProjectId()))\n                    .content(String.format(\"申请:【%s】\", esLogicClusterWithRegionDTO.getName()))\n                    .userOperation(workOrder.getSubmitor())\n                    .buildDefaultManualTrigger());\n        }\n\n        return Result.buildFrom(result);\n    }\n\n    @Override\n    protected Result validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/LogicClusterIndecreaseHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterNodeManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.LogicClusterIndecreaseContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionWithNodeInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.LogicClusterIndecreaseOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectClusterLogicAuthService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\nimport java.util.Optional;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\n@Service(\"logicClusterIndecreaseHandler\")\npublic class LogicClusterIndecreaseHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private ClusterLogicService            clusterLogicService;\n\n    @Autowired\n    private ProjectClusterLogicAuthService projectClusterLogicAuthService;\n\n    @Autowired\n    private ClusterNodeManager             clusterNodeManager;\n  \n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        LogicClusterIndecreaseContent content = JSON.parseObject(extensions, LogicClusterIndecreaseContent.class);\n        LogicClusterIndecreaseOrderDetail logicClusterIndecreaseOrderDetail = ConvertUtil.obj2Obj(content,\n                LogicClusterIndecreaseOrderDetail.class);\n        //添加原有的节点数目\n        Optional.ofNullable(content.getLogicClusterId())\n                .map(clusterLogicService::getClusterLogicByIdThatNotContainsProjectId)\n                .map(ClusterLogic::getDataNodeNum)\n                .ifPresent(logicClusterIndecreaseOrderDetail::setOldDataNodeNu);\n        return logicClusterIndecreaseOrderDetail;\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**************************************** protected method ******************************************/\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        LogicClusterIndecreaseContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterIndecreaseContent.class);\n\n        if (AriusObjUtils.isNull(content.getLogicClusterId())) {\n            return Result.buildParamIllegal(\"集群id为空\");\n        }\n\n        \n        if (!clusterLogicService.existClusterLogicById(content.getLogicClusterId())) {\n            return Result.buildParamIllegal(\"集群不存在\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        LogicClusterIndecreaseContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterIndecreaseContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getLogicClusterName() + workOrderTypeEnum.getMessage();\n    }\n\n    /**\n     * 验证用户是否有该工单权限\n     * 要求只有集群所属的projectId才能操作\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        LogicClusterIndecreaseContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterIndecreaseContent.class);\n\n        ProjectClusterLogicAuthEnum logicClusterAuthEnum = projectClusterLogicAuthService\n            .getLogicClusterAuthEnum(workOrder.getSubmitorProjectId(), content.getLogicClusterId());\n\n        switch (logicClusterAuthEnum) {\n            case ALL:\n            case OWN:\n                return Result.buildSucc();\n            case ACCESS:\n                return Result.buildParamIllegal(\"您的projectId无该集群的扩缩容权限\");\n            case NO_PERMISSIONS:\n            default:\n                return Result.buildParamIllegal(\"您的projectId无该集群的相关权限\");\n        }\n    }\n\n    /**\n     * 验证平台参数\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        LogicClusterIndecreaseContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterIndecreaseContent.class);\n        //执行前的节点结果\n        final Result<List<ESClusterRoleHostVO>> resultBefore = clusterNodeManager.listClusterLogicNode(\n                content.getLogicClusterId().intValue());\n        Long beforeSize = 0L;\n        if (resultBefore.success() && CollectionUtils.isNotEmpty(resultBefore.getData())) {\n            beforeSize = resultBefore.getData().stream().map(ESClusterRoleHostVO::getId).distinct()\n                   .count();\n        \n        }\n       \n        \n        List<ClusterRegionWithNodeInfoDTO> clusterRegionWithNodeInfoDTOList = content.getRegionWithNodeInfo();\n\n        Result<Boolean> regionEditResult = clusterNodeManager.editMultiNode2Region(clusterRegionWithNodeInfoDTOList,\n            approver, workOrder.getSubmitorProjectId(), OperationEnum.EDIT );\n        if (regionEditResult.failed()) {\n            return Result.buildFrom(regionEditResult);\n        }\n       //执行后的节点结果\n         final Result<List<ESClusterRoleHostVO>> resultAfter = clusterNodeManager.listClusterLogicNode(\n                content.getLogicClusterId().intValue());\n        Long afterSize=0L;\n        if (resultAfter.success() && CollectionUtils.isNotEmpty(resultAfter.getData())) {\n            afterSize = resultAfter.getData().stream().map(ESClusterRoleHostVO::getId).distinct().count();\n            // 更新逻辑集群下的节点数目\n            Long logicClusterId = content.getLogicClusterId();\n            ESLogicClusterDTO esLogicClusterDTO = new ESLogicClusterDTO();\n            esLogicClusterDTO.setId(logicClusterId);\n            esLogicClusterDTO.setDataNodeNum(Math.toIntExact(afterSize));\n            clusterLogicService.editClusterLogicNotCheck(esLogicClusterDTO);\n        \n        }\n        \n        operateRecordService.save(new OperateRecord.Builder().bizId(content.getLogicClusterId())\n            .operationTypeEnum(OperateTypeEnum.MY_CLUSTER_CAPACITY).triggerWayEnum(TriggerWayEnum.MANUAL_TRIGGER)\n            .content(String.format(\"%s：【%d】->【%d】\",afterSize>beforeSize?\"扩容\":\"缩容\",beforeSize,afterSize))\n            .userOperation(workOrder.getSubmitor())\n            .project(projectService.getProjectBriefByProjectId(workOrder.getSubmitorProjectId())).build());\n        return Result.buildFrom(regionEditResult);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/LogicClusterJoinHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterLogicManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.JoinLogicClusterContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.LogicClusterCreateOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterLogicVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service(\"logicClusterJoinHandler\")\npublic class LogicClusterJoinHandler extends BaseWorkOrderHandler {\n    @Autowired\n    private ClusterLogicManager clusterLogicManager;\n    \n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        JoinLogicClusterContent content = JSON.parseObject(extensions, JoinLogicClusterContent.class);\n        return ConvertUtil.obj2Obj(content, LogicClusterCreateOrderDetail.class);\n    }\n    \n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n    \n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n    \n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }    /**************************************** protected method ******************************************/\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        JoinLogicClusterContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                JoinLogicClusterContent.class);\n        ESLogicClusterDTO resourceLogicDTO = ConvertUtil.obj2Obj(content, ESLogicClusterDTO.class);\n        resourceLogicDTO.setProjectId(workOrder.getSubmitorProjectId());\n        resourceLogicDTO.setId(content.getId());\n        return clusterLogicManager.validateClusterLogicParams(resourceLogicDTO, OperationEnum.ADD_BIND_MULTIPLE_PROJECT,\n                resourceLogicDTO.getProjectId());\n    }\n    \n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        JoinLogicClusterContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                JoinLogicClusterContent.class);\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        \n        return content.getId() + workOrderTypeEnum.getMessage();\n    }\n    \n    /**\n     * 验证用户是否有该工单权限\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n    \n    /**\n     * 处理工单 这里分为两种，一种是分配逻辑集群，一种是申请逻辑集群，其中申请逻辑集群不会绑定region，会联系同学在运维侧进行操作\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        ESLogicClusterDTO esLogicClusterDTO = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                ESLogicClusterDTO.class);\n        esLogicClusterDTO.setProjectId(workOrder.getSubmitorProjectId());\n        Result<Void> result = clusterLogicManager.joinClusterLogic(esLogicClusterDTO.getId(),\n                workOrder.getSubmitorProjectId());\n        if (result.success()) {\n            ClusterLogicVO clusterLogic = clusterLogicManager.getClusterLogic(esLogicClusterDTO.getId(),\n                    workOrder.getSubmitorProjectId());\n            //操作记录\n            // 逻辑集群创建添加操作记录\n            operateRecordService.save(new OperateRecord.Builder().operationTypeEnum(OperateTypeEnum.MY_CLUSTER_APPLY)\n                    .bizId(esLogicClusterDTO.getId())\n                    .project(projectService.getProjectBriefByProjectId(workOrder.getSubmitorProjectId()))\n                    .content(String.format(\"申请:【%s】\", clusterLogic.getName())).userOperation(workOrder.getSubmitor())\n                    .buildDefaultManualTrigger());\n        }\n        return Result.buildFrom(result);\n    }\n    \n    @Override\n    protected Result validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/LogicClusterPlugOperationHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.LogicClusterPlugOperationContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.LogicClusterPlugOperationOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.OperationTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.EcmHandleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectClusterLogicAuthService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\n\n@Service(\"logicClusterPlugOperationHandler\")\npublic class LogicClusterPlugOperationHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private ProjectClusterLogicAuthService projectClusterLogicAuthService;\n\n    @Autowired\n    private ClusterRegionService           clusterRegionService;\n\n    @Autowired\n    private ClusterPhyService              esClusterPhyService;\n\n    @Autowired\n    private ClusterLogicService            clusterLogicService;\n\n    @Autowired\n    private EcmTaskManager                 ecmTaskManager;\n\n    @Autowired\n    private ClusterRoleService             clusterRoleService;\n\n    @Autowired\n    private EcmHandleService               ecmHandleService;\n\n    protected static final ILog            LOGGER = LogFactory.getLog(LogicClusterPlugOperationHandler.class);\n\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        LogicClusterPlugOperationContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterPlugOperationContent.class);\n\n        if (AriusObjUtils.isNull(content.getLogicClusterId())) {\n            return Result.buildParamIllegal(\"物理集群id为空！\");\n        }\n\n        if (!clusterLogicService.existClusterLogicById(content.getLogicClusterId())) {\n            return Result.buildParamIllegal(\"集群不存在\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        LogicClusterPlugOperationContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterPlugOperationContent.class);\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        OperationTypeEnum typeEnum = OperationTypeEnum.valueOfCode(content.getOperationType());\n        return content.getLogicClusterName() + \" \" + content.getPlugName() + workOrderTypeEnum.getMessage() + \"-\"\n               + typeEnum.getMessage();\n    }\n\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        LogicClusterPlugOperationContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterPlugOperationContent.class);\n\n        ProjectClusterLogicAuthEnum logicClusterAuthEnum = projectClusterLogicAuthService\n            .getLogicClusterAuthEnum(workOrder.getSubmitorProjectId(), content.getLogicClusterId());\n\n        switch (logicClusterAuthEnum) {\n            case OWN:\n            case ALL:\n                return Result.buildSucc();\n            case ACCESS:\n                return Result.buildParamIllegal(\"您的projectId无该集群的管理权限进行插件安装\");\n            case NO_PERMISSIONS:\n            default:\n                return Result.buildParamIllegal(\"您的projectId无该集群的相关权限\");\n        }\n    }\n\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        LogicClusterPlugOperationContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterPlugOperationContent.class);\n\n        List<Integer> clusterStrIdList = clusterRegionService.listPhysicClusterId(content.getLogicClusterId());\n        for (Integer clusterId : clusterStrIdList) {\n            Result<EcmTaskDTO> result = editClusterAndSave2WorkOrderTask(clusterId, workOrder, content);\n            if (result.failed()) {\n                return Result.buildFrom(result);\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        LogicClusterPlugOperationContent content = JSON.parseObject(extensions, LogicClusterPlugOperationContent.class);\n\n        return ConvertUtil.obj2Obj(content, LogicClusterPlugOperationOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    private Result<EcmTaskDTO> editClusterAndSave2WorkOrderTask(Integer clusterId, WorkOrder workOrder,\n                                                                LogicClusterPlugOperationContent content) {\n        EcmTaskDTO esEcmTaskDTO = new EcmTaskDTO();\n\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(clusterId);\n        esEcmTaskDTO.setPhysicClusterId(clusterPhy.getId().longValue());\n\n        List<ClusterRoleInfo> clusterRoleInfoList = clusterRoleService.getAllRoleClusterByClusterId(clusterPhy.getId());\n        if (CollectionUtils.isEmpty(clusterRoleInfoList)) {\n            return Result.buildFail(\"物理集群角色不存在\");\n        }\n\n        List<String> roleNameList = new ArrayList<>();\n        for (ClusterRoleInfo clusterRoleInfo : clusterRoleInfoList) {\n            roleNameList.add(clusterRoleInfo.getRole());\n        }\n\n        esEcmTaskDTO.setWorkOrderId(workOrder.getId());\n        esEcmTaskDTO.setTitle(workOrder.getTitle());\n        esEcmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_RESTART.getType());\n        esEcmTaskDTO.setEcmParamBaseList(ecmHandleService.buildEcmParamBaseList(clusterId, roleNameList).getData());\n        esEcmTaskDTO.setClusterNodeRole(ListUtils.strList2String(roleNameList));\n        esEcmTaskDTO.setCreator(workOrder.getSubmitor());\n        esEcmTaskDTO.setType(clusterPhy.getType());\n        ecmTaskManager.saveEcmTask(esEcmTaskDTO);\n\n        List<Long> plugIdList = ListUtils.string2LongList(clusterPhy.getPlugIds());\n        if (OperationTypeEnum.INSTALL.getCode().equals(content.getOperationType())) {\n            plugIdList.addAll(ListUtils.string2LongList(content.getPlugIds()));\n        } else {\n            plugIdList.removeAll(ListUtils.string2LongList(content.getPlugIds()));\n        }\n        clusterPhy.setPlugIds(ListUtils.longList2String(plugIdList.stream().distinct().collect(Collectors.toList())));\n        esClusterPhyService.editCluster(ConvertUtil.obj2Obj(clusterPhy, ClusterPhyDTO.class), workOrder.getSubmitor());\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/LogicClusterPluginHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.LogicClusterPluginContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.LogicClusterPluginOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectClusterLogicAuthService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service(\"logicClusterPluginHandler\")\npublic class LogicClusterPluginHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private ClusterLogicService            clusterLogicService;\n\n    @Autowired\n    private ProjectClusterLogicAuthService projectClusterLogicAuthService;\n\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        LogicClusterPluginContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterPluginContent.class);\n\n        if (!clusterLogicService.existClusterLogicById(content.getLogicClusterId())) {\n            return Result.buildParamIllegal(\"集群不存在\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        LogicClusterPluginContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterPluginContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getLogicClusterName() + workOrderTypeEnum.getMessage();\n    }\n\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        LogicClusterPluginContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            LogicClusterPluginContent.class);\n\n        ProjectClusterLogicAuthEnum logicClusterAuthEnum = projectClusterLogicAuthService\n            .getLogicClusterAuthEnum(workOrder.getSubmitorProjectId(), content.getLogicClusterId());\n\n        switch (logicClusterAuthEnum) {\n            case OWN:\n            case ALL:\n                return Result.buildSucc();\n            case ACCESS:\n                return Result.buildParamIllegal(\"您的projectId无该集群的管理权限进行插件安装\");\n            case NO_PERMISSIONS:\n            default:\n                return Result.buildParamIllegal(\"您的projectId无该集群的相关权限\");\n        }\n    }\n\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        LogicClusterPluginContent content = JSON.parseObject(extensions, LogicClusterPluginContent.class);\n\n        return ConvertUtil.obj2Obj(content, LogicClusterPluginOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/LogicClusterTransferHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.ClusterLogicTransferContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.ClusterLogicTransferOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * Created by linyunan on 2021-06-17\n */\n@Service\npublic class LogicClusterTransferHandler extends BaseWorkOrderHandler {\n\n    \n\n    @Autowired\n    private ClusterLogicService clusterLogicService;\n\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        ClusterLogicTransferContent clusterLogicTransferContent = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterLogicTransferContent.class);\n\n        Integer sourceProjectId = clusterLogicTransferContent.getSourceProjectId();\n        Integer targetProjectId = clusterLogicTransferContent.getTargetProjectId();\n        if (AriusObjUtils.isNull(sourceProjectId)) {\n            return Result.buildParamIllegal(\"原项目Id为空\");\n        }\n        if (AriusObjUtils.isNull(targetProjectId)) {\n            return Result.buildParamIllegal(\"目标项目Id为空\");\n        }\n\n        if (!projectService.checkProjectExist(sourceProjectId)) {\n            return Result.buildParamIllegal(\"原项目不存在\");\n        }\n\n        if (!projectService.checkProjectExist(targetProjectId)) {\n            return Result.buildParamIllegal(\"目标项目不存在\");\n        }\n\n        Long clusterLogicId = clusterLogicTransferContent.getClusterLogicId();\n        if (Boolean.FALSE.equals(clusterLogicService.isClusterLogicExists(clusterLogicId))) {\n            return Result.buildParamIllegal(\"逻辑集群不存在\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        ClusterLogicTransferContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterLogicTransferContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getClusterLogicName() + workOrderTypeEnum.getMessage();\n    }\n\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        ClusterLogicTransferContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterLogicTransferContent.class);\n\n        if (AriusObjUtils.isNull(content.getSourceProjectId())) {\n            return Result.buildParamIllegal(\"原projectId为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getTargetProjectId())) {\n            return Result.buildParamIllegal(\"目标projectId为空\");\n        }\n\n        if (content.getTargetProjectId().equals(content.getSourceProjectId())) {\n            return Result.buildFail(\"无效转让, 原始项目Id和目标项目ID相同\");\n        }\n\n        if (projectService.checkProjectExist(workOrder.getSubmitorProjectId())) {\n            return Result.buildSucc();\n        }\n    \n        final boolean noneMatch = clusterLogicService.listClusterLogicByIdThatProjectIdStrConvertProjectIdList(content.getClusterLogicId()).stream()\n                .noneMatch(clusterLogic -> clusterLogic.getProjectId().equals(workOrder.getSubmitorProjectId()));\n        if (noneMatch) {\n            return Result.buildOpForBidden(\"您无权对该集群进行转让操作\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) {\n        ClusterLogicTransferContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterLogicTransferContent.class);\n\n        Result<Void> result = clusterLogicService.transferClusterLogic(content.getClusterLogicId(),\n            content.getTargetProjectId(), workOrder.getSubmitor());\n\n        return Result.buildFrom(result);\n    }\n\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        return ConvertUtil.obj2ObjByJSON(JSON.parse(extensions), ClusterLogicTransferOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/QueryDslLimitEditHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.QueryDslLimitEditOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.QueryDslLimitEditContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslQueryLimit;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.DslStatisticsService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\n@Service(\"queryDslLimitEditHandler\")\npublic class QueryDslLimitEditHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private DslStatisticsService dslStatisticsService;\n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        QueryDslLimitEditContent content = JSON.parseObject(extensions, QueryDslLimitEditContent.class);\n\n        return ConvertUtil.obj2Obj(content, QueryDslLimitEditOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**************************************** protected method ******************************************/\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        QueryDslLimitEditContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            QueryDslLimitEditContent.class);\n\n        if (AriusObjUtils.isNull(content.getDslTemplateMd5())) {\n            return Result.buildParamIllegal(\"查询模板为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getQueryLimit())) {\n            return Result.buildParamIllegal(\"查询模板限流值为空\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        QueryDslLimitEditContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            QueryDslLimitEditContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getDslTemplateMd5() + workOrderTypeEnum.getMessage();\n    }\n\n    /**\n     * 验证用户是否有该工单权限\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证平台参数\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) {\n        QueryDslLimitEditContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            QueryDslLimitEditContent.class);\n\n        DslQueryLimit dslQueryLimit = new DslQueryLimit();\n        dslQueryLimit.setProjectId(workOrder.getSubmitorProjectId());\n        dslQueryLimit.setQueryLimit(content.getQueryLimit());\n        dslQueryLimit.setDslTemplateMd5(content.getDslTemplateMd5());\n\n        List<DslQueryLimit> dslQueryLimitList = new ArrayList<>();\n        dslQueryLimitList.add(dslQueryLimit);\n\n        Result<Boolean> result = dslStatisticsService.batchUpdateQueryLimit(dslQueryLimitList, approver);\n\n        if (result.failed()) {\n            return Result.buildFail(\"模版扩缩容失败！\");\n        }\n\n        return Result.buildFrom(result);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/TemplateAuthHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.TemplateAuthContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.TemplateAuthOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\nimport java.util.Map;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\n@NoArgsConstructor\n@Service(\"templateAuthHandler\")\n@Deprecated\npublic class TemplateAuthHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private ProjectLogicTemplateAuthService projectLogicTemplateAuthService;\n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return true;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        TemplateAuthContent content = JSON.parseObject(extensions, TemplateAuthContent.class);\n        return ConvertUtil.obj2Obj(content, TemplateAuthOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**************************************** protected method ****************************************************/\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        TemplateAuthContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), TemplateAuthContent.class);\n\n        if (AriusObjUtils.isNull(content.getId())) {\n            return Result.buildParamIllegal(\"索引id为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getName())) {\n            return Result.buildParamIllegal(\"索引名字为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getAuthCode())) {\n            return Result.buildParamIllegal(\"权限类型为空\");\n        }\n\n        ProjectTemplateAuthEnum authEnum = ProjectTemplateAuthEnum.valueOf(content.getAuthCode());\n        if (ProjectTemplateAuthEnum.NO_PERMISSION.equals(authEnum)) {\n            return Result.buildParamIllegal(\"权限类型非法\");\n        }\n\n        if (authEnum.equals(ProjectTemplateAuthEnum.OWN) ) {\n            return Result.buildParamIllegal(\"管理责任人为空\");\n        }\n\n        List<ProjectTemplateAuth> auths = projectLogicTemplateAuthService\n            .getTemplateAuthsByProjectId(workOrder.getSubmitorProjectId());\n        Map<Integer, ProjectTemplateAuth> logicId2AppTemplateAuthMap = ConvertUtil.list2Map(auths,\n            ProjectTemplateAuth::getTemplateId);\n        ProjectTemplateAuth templateAuth = logicId2AppTemplateAuthMap.get(content.getId());\n        if (templateAuth != null && templateAuth.getType() <= content.getAuthCode()) {\n            return Result.buildParamIllegal(\"您已经拥有该权限\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        TemplateAuthContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(), TemplateAuthContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getName() + workOrderTypeEnum.getMessage();\n    }\n\n    /**\n     * 验证用户是否有该工单权限\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证平台参数\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/TemplateCreateHandler.java",
    "content": ""
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/TemplateIndecreaseHandler.java",
    "content": ""
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/TemplateLogicBlockReadHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplateLogicManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.TemplateLogicStatusContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.TemplateLogicStatusDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * @author wuxuan\n * @date 2022/11/14\n */\n@Service(\"templateLogicBlockReadHandler\")\npublic class TemplateLogicBlockReadHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private TemplateLogicManager templateLogicManager;\n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        TemplateLogicStatusContent content = JSON.parseObject(extensions, TemplateLogicStatusContent.class);\n\n        return ConvertUtil.obj2Obj(content, TemplateLogicStatusDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        TemplateLogicStatusContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),TemplateLogicStatusContent.class);\n\n        if (AriusObjUtils.isNull(content.getProjectId())) {\n            return Result.buildParamIllegal(\"项目id为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getTemplateId())) {\n            return Result.buildParamIllegal(\"模板Id为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getOperator())) {\n            return Result.buildParamIllegal(\"操作者为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getStatus())) {\n            return Result.buildParamIllegal(\"禁用/启用读的状态为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getName())) {\n            return Result.buildParamIllegal(\"索引模板名称为空\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        TemplateLogicStatusContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                TemplateLogicStatusContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n\n        return content.getName()+ workOrderTypeEnum.getMessage();\n    }\n\n\n    /**************************************** protected method ******************************************/\n\n    /**\n     * 验证用户是否有该工单权限\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证平台参数\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        TemplateLogicStatusContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                TemplateLogicStatusContent.class);\n        Result<Void> result = templateLogicManager.blockRead(content.getTemplateId(),\n                content.getStatus(),content.getOperator(),content.getProjectId());\n\n        if (result.success()) {\n            //操作记录\n            //查询模板读写变更记录\n            operateRecordService.save(new OperateRecord.Builder().operationTypeEnum(OperateTypeEnum.TEMPLATE_MANAGEMENT_BLOCK_READ)\n                    .project(projectService.getProjectBriefByProjectId(workOrder.getSubmitorProjectId()))\n                    .content(String.format(\"项目%d的模板%s启用/禁用读状态变更\", content.getProjectId(),content.getTemplateId()))\n                    .userOperation(workOrder.getSubmitor())\n                    .buildDefaultManualTrigger());\n        }\n\n        return Result.buildFrom(result);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/TemplateLogicBlockWriteHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplateLogicManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.TemplateLogicStatusContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.TemplateLogicStatusDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * @author wuxuan\n * @date 2022/11/14\n */\n@Service(\"templateLogicBlockWriteHandler\")\npublic class TemplateLogicBlockWriteHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private TemplateLogicManager templateLogicManager;\n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        TemplateLogicStatusContent content = JSON.parseObject(extensions, TemplateLogicStatusContent.class);\n\n        return ConvertUtil.obj2Obj(content, TemplateLogicStatusDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        TemplateLogicStatusContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),TemplateLogicStatusContent.class);\n\n        if (AriusObjUtils.isNull(content.getProjectId())) {\n            return Result.buildParamIllegal(\"项目id为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getTemplateId())) {\n            return Result.buildParamIllegal(\"模板Id为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getOperator())) {\n            return Result.buildParamIllegal(\"操作者为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getStatus())) {\n            return Result.buildParamIllegal(\"禁用/启用写的状态为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getName())) {\n            return Result.buildParamIllegal(\"索引模板名称为空\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        TemplateLogicStatusContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                TemplateLogicStatusContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n\n        return content.getName() + workOrderTypeEnum.getMessage();\n    }\n\n\n    /**************************************** protected method ******************************************/\n\n    /**\n     * 验证用户是否有该工单权限\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证平台参数\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        TemplateLogicStatusContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n                TemplateLogicStatusContent.class);\n        Result<Void> result = templateLogicManager.blockWrite(content.getTemplateId(),\n                content.getStatus(),content.getOperator(),content.getProjectId());\n\n        if (result.success()) {\n            //操作记录\n            //查询模板读写变更记录\n            operateRecordService.save(new OperateRecord.Builder().operationTypeEnum(OperateTypeEnum.TEMPLATE_MANAGEMENT_BLOCK_WRITE)\n                    .project(projectService.getProjectBriefByProjectId(workOrder.getSubmitorProjectId()))\n                    .content(String.format(\"项目%d的模板%s启用/禁用写状态变更\", content.getProjectId(),content.getTemplateId()))\n                    .userOperation(workOrder.getSubmitor())\n                    .buildDefaultManualTrigger());\n        }\n\n        return Result.buildFrom(result);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/TemplateQueryDslHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.TemplateQueryDslContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.AuditDsl;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.TemplateQueryDslOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.DslStatisticsService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\n@Service(\"templateQueryDslHandler\")\npublic class TemplateQueryDslHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private ProjectLogicTemplateAuthService projectLogicTemplateAuthService;\n\n    @Autowired\n    private DslStatisticsService            dslStatisticsService;\n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        TemplateQueryDslContent content = JSON.parseObject(extensions, TemplateQueryDslContent.class);\n\n        return ConvertUtil.obj2Obj(content, TemplateQueryDslOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        TemplateQueryDslContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            TemplateQueryDslContent.class);\n\n        if (AriusObjUtils.isNull(content.getId())) {\n            return Result.buildParamIllegal(\"索引id为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getName())) {\n            return Result.buildParamIllegal(\"索引名字为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getDsl())) {\n            return Result.buildParamIllegal(\"DSL语句为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getMemo())) {\n            return Result.buildParamIllegal(\"DSL语句说明为空\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        TemplateQueryDslContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            TemplateQueryDslContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getName() + workOrderTypeEnum.getMessage();\n    }\n\n    /**************************************** protected method ******************************************/\n\n    /**\n     * 验证用户是否有该工单权限\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        TemplateQueryDslContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            TemplateQueryDslContent.class);\n\n        List<ProjectTemplateAuth> projectTemplateAuths = projectLogicTemplateAuthService\n            .getTemplateAuthsByLogicTemplateId(content.getId());\n        Map<Integer, ProjectTemplateAuth> projectId2ProjectTemplateAuthMap = ConvertUtil.list2Map(projectTemplateAuths,\n            ProjectTemplateAuth::getProjectId);\n\n        if (projectId2ProjectTemplateAuthMap.containsKey(workOrder.getSubmitorProjectId())) {\n            return Result.buildSucc();\n        }\n\n        return Result.buildParamIllegal(\"当前project无该索引访问访问权限，请先申请查询权限\");\n    }\n\n    /**\n     * 验证平台参数\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        TemplateQueryDslContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            TemplateQueryDslContent.class);\n\n        DslInfo dslInfo = new DslInfo();\n        dslInfo.setDsl(content.getDsl());\n        dslInfo.setMemo(content.getMemo());\n\n        List<DslInfo> dslInfos = new ArrayList<>();\n        dslInfos.add(dslInfo);\n\n        // 修改模板quota及保存时长信息\n        AuditDsl auditDsl = new AuditDsl(workOrder.getSubmitorProjectId(), workOrder.getSubmitor(), dslInfos);\n\n        return Result.buildFrom(dslStatisticsService.auditDsl(auditDsl));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/TemplateTransferHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.TemplateTransferContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.TemplateTransferOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\n@Service(\"templateTransferHandler\")\npublic class TemplateTransferHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    private IndexTemplateService indexTemplateService;\n\n    @Autowired\n    private ProjectService       projectService;\n    @Autowired\n    private UserService          userService;\n\n    /**\n     * 工单是否自动审批\n     *\n     * @param workOrder 工单类型\n     * @return result\n     */\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        return JSON.parseObject(extensions, TemplateTransferOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n\n    /**************************************** protected method ******************************************/\n\n    /**\n     * 验证用户提供的参数\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) {\n        TemplateTransferContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            TemplateTransferContent.class);\n\n        if (AriusObjUtils.isNull(content.getId())) {\n            return Result.buildParamIllegal(\"索引id为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getName())) {\n            return Result.buildParamIllegal(\"索引名字为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getTgtProjectId())) {\n            return Result.buildParamIllegal(\"应用id为空\");\n        }\n\n        if (AriusObjUtils.isNull(indexTemplateService.getLogicTemplateById(content.getId()))) {\n            return Result.buildNotExist(\"索引不存在\");\n        }\n\n        if (!projectService.checkProjectExist(content.getTgtProjectId())) {\n            return Result.buildNotExist(\"应用不存在\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        TemplateTransferContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            TemplateTransferContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getName() + workOrderTypeEnum.getMessage();\n    }\n\n    /**\n     * 验证用户是否有该工单权限\n     */\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        TemplateTransferContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            TemplateTransferContent.class);\n\n        if (AriusObjUtils.isNull(content.getSourceProjectId())) {\n            return Result.buildParamIllegal(\"原projectId为空\");\n        }\n\n        if (AriusObjUtils.isNull(content.getTgtProjectId())) {\n            return Result.buildParamIllegal(\"目标projectId为空\");\n        }\n\n        if (content.getTgtProjectId().equals(content.getSourceProjectId())) {\n            return Result.buildFail(\"无效转让, 原始项目Id和目标项目ID相同\");\n        }\n\n        if (AuthConstant.SUPER_PROJECT_ID.equals(workOrder.getSubmitorProjectId())) {\n            return Result.buildSucc();\n        }\n\n        IndexTemplate templateLogic = indexTemplateService.getLogicTemplateById(content.getId());\n        if (!templateLogic.getProjectId().equals(workOrder.getSubmitorProjectId())) {\n            return Result.buildOpForBidden(\"您无权对该索引进行转让操作\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证平台参数\n     *\n     * @param workOrder 工单内容\n     * @return result\n     */\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    /**\n     * 处理工单\n     *\n     * @param workOrder 工单\n     * @return result\n     */\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        TemplateTransferContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            TemplateTransferContent.class);\n\n        Result<Void> result = indexTemplateService.turnOverLogicTemplate(content.getId(), content.getSourceProjectId(),\n            content.getTgtProjectId(), workOrder.getSubmitor());\n\n        if (result.success()) {\n            operateRecordService.save(\n                new OperateRecord.Builder().operationTypeEnum(OperateTypeEnum.TEMPLATE_SERVICE).userOperation(approver)\n                    .content(String.format(\"模板从 项目:[%s】->项目:【%s】\",\n                        projectService.getProjectBriefByProjectId(content.getSourceProjectId()).getProjectName(),\n                        projectService.getProjectBriefByProjectId(content.getTgtProjectId()).getProjectName()))\n                    .project(projectService.getProjectBriefByProjectId(workOrder.getSubmitorProjectId())).build());\n\n        }\n\n        return Result.buildFrom(result);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/clusterrestart/BaseClusterOpRestartHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler.clusterrestart;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.BaseWorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterRestartContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.clusteroprestart.ClusterOpRestartOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.EcmHandleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n *\n * @author admin\n * @date 2022/05/09\n */\npublic abstract class BaseClusterOpRestartHandler extends BaseWorkOrderHandler {\n\n    @Autowired\n    protected ClusterPhyService esClusterPhyService;\n\n    @Autowired\n    protected EcmHandleService  ecmHandleService;\n\n    @Autowired\n    protected OpTaskManager     opTaskManager;\n\n    @Override\n    protected Result validateConsoleAuth(WorkOrder workOrder) {\n        if (!isOP(workOrder.getSubmitor())) {\n            return Result.buildOpForBidden(\"非运维人员不能操作集群扩缩容！\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        ClusterRestartContent content = JSON.parseObject(extensions, ClusterRestartContent.class);\n\n        return ConvertUtil.obj2Obj(content, ClusterOpRestartOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc(true);\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/clusterrestart/ClusterOpConfigRestartHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler.clusterrestart;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum.ADD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum.DELETE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum.EDIT;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterConfigRestartContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.esconfig.ESConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.clusteroprestart.ClusterOpConfigRestartOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESClusterConfigService;\nimport com.google.common.collect.ArrayListMultimap;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Multimap;\nimport java.util.List;\nimport java.util.Objects;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author lyn\n * @date 2021-01-21\n */\n@Service(\"clusterOpConfigRestartHandler\")\n@Deprecated\npublic class ClusterOpConfigRestartHandler extends BaseClusterOpRestartHandler {\n\n    @Autowired\n    private ESClusterConfigService esClusterConfigService;\n\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) throws NotFindSubclassException {\n        ClusterConfigRestartContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterConfigRestartContent.class);\n\n        if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n            return Result.buildParamIllegal(\"物理集群id为空\");\n        }\n\n        if (StringUtils.isBlank(content.getRoleOrder())) {\n            return Result.buildParamIllegal(\"物理集群重启角色顺序为空\");\n        }\n\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildParamIllegal(\"物理集群不存在\");\n        }\n\n        if (AriusObjUtils.isNull(content.getActionType())) {\n            return Result.buildParamIllegal(\"配置操作不存在\");\n        }\n\n        if (ADD.getCode() == content.getActionType() && CollectionUtils.isEmpty(content.getNewEsConfigs())) {\n            return Result.buildParamIllegal(\"新增配置为空\");\n        }\n\n        if (EsConfigActionEnum.EDIT.getCode() == content.getActionType()\n            && CollectionUtils.isEmpty(content.getOriginalConfigs())) {\n            return Result.buildParamIllegal(\"原始配置为空\");\n        }\n\n        if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n            OpTaskTypeEnum.CLUSTER_RESTART.getType())) {\n            return Result.buildParamIllegal(\"该集群上存在未完成的集群重启任务\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        ClusterConfigRestartContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterConfigRestartContent.class);\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getPhyClusterName() + EsConfigActionEnum.valueOf(content.getActionType()).getDesc();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        ClusterConfigRestartContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterConfigRestartContent.class);\n\n        EcmTaskDTO ecmTaskDTO = new EcmTaskDTO();\n        ecmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n        ecmTaskDTO.setWorkOrderId(workOrder.getId());\n        ecmTaskDTO.setTitle(workOrder.getTitle());\n\n        ecmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_RESTART.getType());\n        ecmTaskDTO.setCreator(workOrder.getSubmitor());\n\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        ecmTaskDTO.setType(clusterPhy.getType());\n\n        List<String> roleNameList = Lists.newArrayList();\n        for (String roleClusterName : JSON.parseArray(content.getRoleOrder(), String.class)) {\n            String roleName = roleClusterName.replaceFirst(clusterPhy.getCluster() + \"-\", \"\");\n            roleNameList.add(roleName);\n        }\n\n        Multimap<String, Long> role2ConfigIdsMultiMap = saveAndGetEsConfigIds(content, approver);\n        List<EcmParamBase> ecmParamBaseList = ecmHandleService.buildEcmParamBaseListWithConfigAction(clusterPhy.getId(),\n            roleNameList, role2ConfigIdsMultiMap, content.getActionType()).getData();\n\n        ecmTaskDTO.setEcmParamBaseList(ecmParamBaseList);\n\n        OpTaskDTO opTaskDTO = new OpTaskDTO();\n        opTaskDTO.setExpandData(JSON.toJSONString(ecmTaskDTO));\n        opTaskDTO.setTaskType(OpTaskTypeEnum.CLUSTER_RESTART.getType());\n        opTaskDTO.setCreator(workOrder.getSubmitor());\n        Result<OpTask> result = opTaskManager.addTask(opTaskDTO, AuthConstant.SUPER_PROJECT_ID);\n        if (null == result || result.failed()) {\n            return Result.buildFail(\"生成集群新建操作任务失败!\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        ClusterConfigRestartContent content = JSON.parseObject(extensions, ClusterConfigRestartContent.class);\n        if (EDIT.getCode() == content.getActionType()) {\n            buildOriginalConfigsData(content.getNewEsConfigs());\n        }\n\n        return ConvertUtil.obj2Obj(content, ClusterOpConfigRestartOrderDetail.class);\n    }\n\n    private void buildOriginalConfigsData(List<ESConfig> newEsConfigs) {\n        newEsConfigs.stream().filter(Objects::nonNull).forEach(config -> {\n            ESConfig originalConfig = esClusterConfigService.getEsConfigById(config.getId());\n            if (AriusObjUtils.isNull(originalConfig)) {\n                LOGGER.error(\n                    \"class=ClusterOpConfigRestartHandler||method=getOrderDetail||msg=\" + \"original config is empty\");\n                return;\n            }\n\n            config.setOriginalConfigData(originalConfig.getConfigData());\n        });\n    }\n\n    /**落配置信息入DB*/\n    private Multimap</*集群角色*/String, /*改动的配置id*/Long> saveAndGetEsConfigIds(ClusterConfigRestartContent content,\n                                                                            String approver) {\n        Multimap<String, Long> role2ConfigIdsMultiMap = ArrayListMultimap.create();\n        if (ADD.getCode() == content.getActionType()) {\n            List<ESConfigDTO> newEsConfigs = ConvertUtil.list2List(content.getNewEsConfigs(), ESConfigDTO.class);\n            newEsConfigs.stream().filter(Objects::nonNull).forEach(config -> {\n                Result<Long> result = esClusterConfigService.esClusterConfigAction(config, ADD, approver);\n                if (result.failed()) {\n                    LOGGER.error(\"class=ClusterOpConfigRestartHandler||method=saveAndGetEsConfigIds||msg=\"\n                                 + \"failed to add es config\");\n                }\n                config.setId(result.getData());\n            });\n\n            role2ConfigIdsMultiMap = ConvertUtil.list2MulMap(newEsConfigs, ESConfigDTO::getEnginName,\n                ESConfigDTO::getId);\n        }\n\n        if (EDIT.getCode() == content.getActionType()) {\n            List<ESConfigDTO> editConfigs = ConvertUtil.list2List(content.getNewEsConfigs(), ESConfigDTO.class);\n            editConfigs.stream().filter(Objects::nonNull).forEach(config -> {\n                Result<Long> result = esClusterConfigService.esClusterConfigAction(config, EDIT, approver);\n                if (result.failed()) {\n                    LOGGER.error(\"class=ClusterOpConfigRestartHandler||method=saveAndGetEsConfigIds||msg=\"\n                                 + \"failed to edit es config\");\n                    return;\n                }\n                config.setId(result.getData());\n            });\n\n            role2ConfigIdsMultiMap = ConvertUtil.list2MulMap(editConfigs, ESConfigDTO::getEnginName,\n                ESConfigDTO::getId);\n        }\n\n        if (DELETE.getCode() == content.getActionType()) {\n            role2ConfigIdsMultiMap = ConvertUtil.list2MulMap(content.getOriginalConfigs(), ESConfig::getEnginName,\n                ESConfig::getId);\n        }\n\n        return role2ConfigIdsMultiMap;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/clusterrestart/ClusterOpNormalRestartHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler.clusterrestart;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterRestartContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.clusteroprestart.ClusterOpRestartOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author lyn\n * @date 2021-01-21\n */\n@Service(\"clusterOpRestartHandler\")\n@Deprecated\npublic class ClusterOpNormalRestartHandler extends BaseClusterOpRestartHandler {\n\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) throws NotFindSubclassException {\n        ClusterRestartContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterRestartContent.class);\n\n        if (AriusObjUtils.isNull(content.getPhyClusterId())) {\n            return Result.buildParamIllegal(\"物理集群id为空\");\n        }\n\n        if (StringUtils.isBlank(content.getRoleOrder())) {\n            return Result.buildParamIllegal(\"物理集群重启角色顺序为空\");\n        }\n\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildParamIllegal(\"物理集群不存在\");\n        }\n\n        if (opTaskManager.existUnClosedTask(content.getPhyClusterId().intValue(),\n            OpTaskTypeEnum.CLUSTER_RESTART.getType())) {\n            return Result.buildParamIllegal(\"该集群上存在未完成的集群重启任务\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        ClusterRestartContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterRestartContent.class);\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        return content.getPhyClusterName() + workOrderTypeEnum.getMessage();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        ClusterRestartContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            ClusterRestartContent.class);\n\n        EcmTaskDTO ecmTaskDTO = new EcmTaskDTO();\n        ecmTaskDTO.setPhysicClusterId(content.getPhyClusterId());\n        ecmTaskDTO.setWorkOrderId(workOrder.getId());\n        ecmTaskDTO.setTitle(workOrder.getTitle());\n\n        ecmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_RESTART.getType());\n        ecmTaskDTO.setCreator(workOrder.getSubmitor());\n\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(content.getPhyClusterId().intValue());\n        ecmTaskDTO.setType(clusterPhy.getType());\n\n        List<String> roleNameList = new ArrayList<>();\n        for (String roleClusterName : JSON.parseArray(content.getRoleOrder(), String.class)) {\n            String roleName = roleClusterName.replaceFirst(clusterPhy.getCluster() + \"-\", \"\");\n            roleNameList.add(roleName);\n        }\n        List<EcmParamBase> ecmParamBaseList = ecmHandleService.buildEcmParamBaseList(clusterPhy.getId(), roleNameList)\n            .getData();\n\n        ecmTaskDTO.setEcmParamBaseList(ecmParamBaseList);\n\n        OpTaskDTO opTaskDTO = new OpTaskDTO();\n        opTaskDTO.setTaskType(OpTaskTypeEnum.CLUSTER_RESTART.getType());\n        opTaskDTO.setExpandData(JSON.toJSONString(ecmTaskDTO));\n        opTaskDTO.setCreator(workOrder.getSubmitor());\n        Result<OpTask> result = opTaskManager.addTask(opTaskDTO, AuthConstant.SUPER_PROJECT_ID);\n        if (null == result || result.failed()) {\n            return Result.buildFail(\"生成集群新建操作任务失败!\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        ClusterRestartContent content = JSON.parseObject(extensions, ClusterRestartContent.class);\n\n        return ConvertUtil.obj2Obj(content, ClusterOpRestartOrderDetail.class);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/handler/clusterrestart/ClusterOpPluginRestartHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.handler.clusterrestart;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.content.PhyClusterPluginOperationContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm.EcmTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.PhyClusterPluginOperationOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin.PluginPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.OperationTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPluginService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\n\n/**\n * 集群op插件启动处理程序\n *\n * @author admin\n * @date 2022/05/09\n */\n@Service(\"clusterOpPluginRestartHandler\")\npublic class ClusterOpPluginRestartHandler extends BaseClusterOpRestartHandler {\n\n    @Autowired\n    private ESPluginService    esPluginService;\n\n    @Autowired\n    private ClusterRoleService clusterRoleService;\n\n    @Autowired\n    private OpTaskManager      workTaskService;\n\n    @Autowired\n    private EcmTaskManager     ecmTaskManager;\n\n    @Override\n    protected Result<Void> validateConsoleParam(WorkOrder workOrder) throws NotFindSubclassException {\n        PhyClusterPluginOperationContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            PhyClusterPluginOperationContent.class);\n\n        // 校验插件id\n        if (AriusObjUtils.isNull(content.getPluginId())) {\n            return Result.buildParamIllegal(\"插件id为空！\");\n        }\n        PluginPO plugin = esPluginService.getESPluginById(content.getPluginId());\n        if (AriusObjUtils.isNull(plugin)) {\n            return Result.buildParamIllegal(\"插件不存在！\");\n        }\n\n        // 校验操作类型\n        if (AriusObjUtils.isNull(content.getOperationType())) {\n            return Result.buildParamIllegal(\"未定义插件操作类型\");\n        }\n\n        OperationTypeEnum operationType = OperationTypeEnum.valueOfCode(content.getOperationType());\n        if (!operationType.equals(OperationTypeEnum.INSTALL) && !operationType.equals(OperationTypeEnum.UNINSTALL)) {\n            return Result.buildParamIllegal(\"插件操作类型不合法(合法的操作类型包括安装和卸载)\");\n        }\n\n        if (opTaskManager.existUnClosedTask(Integer.parseInt(plugin.getPhysicClusterId()),\n            OpTaskTypeEnum.CLUSTER_RESTART.getType())) {\n            return Result.buildParamIllegal(\"该集群上存在未完成的集群重启任务\");\n        }\n\n        // 集群存在等待执行或正在执行的插件操作任务\n        if (null != ecmTaskManager.getRunningEcmTaskByClusterId(Integer.parseInt(plugin.getPhysicClusterId()))) {\n            return Result.buildFail(\"该集群上仍存在待执行或者正在执行的插件操作任务，请完成该任务后再提交\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected String getTitle(WorkOrder workOrder) {\n        PhyClusterPluginOperationContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            PhyClusterPluginOperationContent.class);\n\n        WorkOrderTypeEnum workOrderTypeEnum = WorkOrderTypeEnum.valueOfName(workOrder.getType());\n        if (workOrderTypeEnum == null) {\n            return \"\";\n        }\n        OperationTypeEnum operationType = OperationTypeEnum.valueOfCode(content.getOperationType());\n        PluginPO pluginPO = esPluginService.getESPluginById(content.getPluginId());\n        ClusterPhy cluster = esClusterPhyService.getClusterById(Integer.parseInt(pluginPO.getPhysicClusterId()));\n        return cluster.getCluster() + \" \" + pluginPO.getName() + pluginPO.getVersion() + \" \"\n               + workOrderTypeEnum.getMessage() + \"-\" + operationType.getMessage();\n    }\n\n    @Override\n    protected Result<Void> validateConsoleAuth(WorkOrder workOrder) {\n        if (!isOP(workOrder.getSubmitor())) {\n            return Result.buildOpForBidden(\"非运维人员不能操作物理集群插件的安装和卸载！\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> validateParam(WorkOrder workOrder) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    protected Result<Void> doProcessAgree(WorkOrder workOrder, String approver) throws AdminOperateException {\n        PhyClusterPluginOperationContent content = ConvertUtil.obj2ObjByJSON(workOrder.getContentObj(),\n            PhyClusterPluginOperationContent.class);\n\n        // 当该物理集群对应的逻辑集群对应多个物理集群时，提示用户应该在逻辑侧进行操作\n        PluginPO pluginPO = esPluginService.getESPluginById(content.getPluginId());\n\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(Integer.parseInt(pluginPO.getPhysicClusterId()));\n        List<ClusterRoleInfo> clusterRoleInfoList = clusterRoleService.getAllRoleClusterByClusterId(clusterPhy.getId());\n        if (CollectionUtils.isEmpty(clusterRoleInfoList)) {\n            return Result.buildFail(\"物理集群角色不存在\");\n        }\n\n        List<String> roleNameList = new ArrayList<>();\n        for (ClusterRoleInfo clusterRoleInfo : clusterRoleInfoList) {\n            roleNameList.add(clusterRoleInfo.getRole());\n        }\n        List<EcmParamBase> ecmParamBaseList = ecmHandleService.buildEcmParamBaseListWithEsPluginAction(\n            clusterPhy.getId(), roleNameList, content.getPluginId(), content.getOperationType()).getData();\n\n        // 生成工单任务\n        EcmTaskDTO ecmTaskDTO = new EcmTaskDTO();\n        ecmTaskDTO.setPhysicClusterId(Long.parseLong(pluginPO.getPhysicClusterId()));\n        ecmTaskDTO.setWorkOrderId(workOrder.getId());\n        ecmTaskDTO.setTitle(workOrder.getTitle());\n        ecmTaskDTO.setOrderType(OpTaskTypeEnum.CLUSTER_RESTART.getType());\n        ecmTaskDTO.setCreator(workOrder.getSubmitor());\n        ecmTaskDTO.setType(clusterPhy.getType());\n        ecmTaskDTO.setEcmParamBaseList(ecmParamBaseList);\n        ecmTaskDTO.setClusterNodeRole(ListUtils.strList2String(roleNameList));\n\n        OpTaskDTO opTaskDTO = new OpTaskDTO();\n        opTaskDTO.setExpandData(JSON.toJSONString(ecmTaskDTO));\n        opTaskDTO.setTaskType(OpTaskTypeEnum.CLUSTER_RESTART.getType());\n        opTaskDTO.setCreator(workOrder.getSubmitor());\n        Result<OpTask> result = workTaskService.addTask(opTaskDTO, AuthConstant.SUPER_PROJECT_ID);\n        if (null == result || result.failed()) {\n            return Result.buildFail(\"生成物理集群插件操作任务失败!\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public boolean canAutoReview(WorkOrder workOrder) {\n        return false;\n    }\n\n    @Override\n    public AbstractOrderDetail getOrderDetail(String extensions) {\n        PhyClusterPluginOperationContent content = JSON.parseObject(extensions, PhyClusterPluginOperationContent.class);\n        return ConvertUtil.obj2Obj(content, PhyClusterPluginOperationOrderDetail.class);\n    }\n\n    @Override\n    public List<UserBriefVO> getApproverList(AbstractOrderDetail detail) {\n        return getOPList();\n    }\n\n    @Override\n    public Result<Void> checkAuthority(WorkOrderPO orderPO, String userName) {\n        if (isOP(userName)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/impl/WorkOrderManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.workorder.BpmAuditTypeEnum.AGREE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.workorder.BpmAuditTypeEnum.DISAGREE;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.WorkOrderHandler;\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.WorkOrderManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder.WorkOrderDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder.WorkOrderProcessDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.WorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.OrderInfoDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.AriusWorkOrderInfoSubmittedVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.OrderTypeVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.WorkOrderVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.detail.OrderDetailBaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.OrderStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.OperateForbiddenException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.workorder.WorkOrderService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.entity.dept.Dept;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.service.DeptService;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\n@Service\npublic class WorkOrderManagerImpl implements WorkOrderManager {\n\n    private static final ILog LOGGER               = LogFactory.getLog(WorkOrderManagerImpl.class);\n\n    private static final int    PROJECT_ID_TO_CREATE = -99;\n\n    @Autowired\n    private HandleFactory       handleFactory;\n\n    @Autowired\n    private ProjectService      projectService;\n    @Autowired\n    private UserService         userService;\n\n    \n    @Autowired\n    private WorkOrderService workOrderService;\n    @Autowired\n    private DeptService         deptService;\n    @Autowired\n    private RoleTool            roleTool;\n  \n\n    @Override\n    public Result<List<OrderTypeVO>> getOrderTypes() {\n        List<OrderTypeVO> orderTypeVOList = new ArrayList<>();\n        orderTypeVOList.add(new OrderTypeVO(WorkOrderTypeEnum.LOGIC_CLUSTER_CREATE.getName(),\n            WorkOrderTypeEnum.LOGIC_CLUSTER_CREATE.getMessage()));\n        orderTypeVOList.add(new OrderTypeVO(WorkOrderTypeEnum.LOGIC_CLUSTER_INDECREASE.getName(),\n            WorkOrderTypeEnum.LOGIC_CLUSTER_INDECREASE.getMessage()));\n        orderTypeVOList.add(new OrderTypeVO(WorkOrderTypeEnum.LOGIC_CLUSTER_JOIN.getName(),\n            WorkOrderTypeEnum.LOGIC_CLUSTER_JOIN.getMessage()));\n        orderTypeVOList.add(new OrderTypeVO(WorkOrderTypeEnum.DSL_TEMPLATE_STATUS_CHANGE.getName(),\n                WorkOrderTypeEnum.DSL_TEMPLATE_STATUS_CHANGE.getMessage()));\n        orderTypeVOList.add(new OrderTypeVO(WorkOrderTypeEnum.DSL_TEMPLATE_QUERY_LIMIT.getName(),\n                WorkOrderTypeEnum.DSL_TEMPLATE_QUERY_LIMIT.getMessage()));\n        orderTypeVOList.add(new OrderTypeVO(WorkOrderTypeEnum.TEMPLATE_LOGIC_BLOCK_READ.getName(),\n                WorkOrderTypeEnum.TEMPLATE_LOGIC_BLOCK_READ.getMessage()));\n        orderTypeVOList.add(new OrderTypeVO(WorkOrderTypeEnum.TEMPLATE_LOGIC_BLOCK_WRITE.getName(),\n                WorkOrderTypeEnum.TEMPLATE_LOGIC_BLOCK_WRITE.getMessage()));\n        return Result.buildSucc(orderTypeVOList);\n    }\n    \n    /**\n     * @param workOrderDTO\n     * @return\n     */\n    @Override\n    public Result<AriusWorkOrderInfoSubmittedVO> submitByJoinLogicCluster(WorkOrderDTO workOrderDTO)\n            throws AdminOperateException {\n    \n        workOrderDTO.setType(WorkOrderTypeEnum.LOGIC_CLUSTER_JOIN.getName());\n    \n        return submit(workOrderDTO);\n    }\n    \n    \n    @Override\n    public Result<AriusWorkOrderInfoSubmittedVO> submit(WorkOrderDTO workOrderDTO) throws AdminOperateException {\n\n        String workOrderJsonString = JSON.toJSONString(workOrderDTO);\n        LOGGER.info(\n            \"class=WorkOrderManagerImpl||method=WorkOrderController.process||workOrderDTO={}||envInfo={}||dataCenter={}\",\n            workOrderJsonString, EnvUtil.getStr(), workOrderDTO.getDataCenter());\n\n        try {\n            initWorkOrderDTO(workOrderDTO);\n        } catch (OperateForbiddenException e) {\n            LOGGER.error(\n                    \"class=WorkOrderManagerImpl||method=submit||workOrderDTO={}||envInfo={}||dataCenter={}||errMsg=fail to init workOrderDTO\",\n                    workOrderJsonString, EnvUtil.getStr(), workOrderDTO.getDataCenter(),e.getMessage(),e);\n            Result.buildFail(\"初始化工单异常\");\n        }\n\n        Result<Void> submitValidResult = checkSubmitValid(workOrderDTO);\n        if (submitValidResult.failed()) {\n            return Result.buildFrom(submitValidResult);\n        }\n\n        WorkOrderHandler handler = null;\n        try {\n            handler = (WorkOrderHandler) handleFactory.getByHandlerNamePer(workOrderDTO.getType());\n        } catch (NotFindSubclassException e) {\n            LOGGER.error(\n                    \"class=WorkOrderManagerImpl||method=submit||workOrderDTO={}||envInfo={}||dataCenter={}||errMsg=fail to get WorkOrderHandler\",\n                    workOrderJsonString, EnvUtil.getStr(), workOrderDTO.getDataCenter(),e.getMessage(),e);\n            Result.buildFail(\"获取WorkOrderHandler异常\");\n        }\n\n        Result<WorkOrderPO> submitResult = null;\n        try {\n            submitResult = handler.submit(ConvertUtil.obj2Obj(workOrderDTO, WorkOrder.class));\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=WorkOrderManagerImpl||method=submit||workOrderDTO={}||envInfo={}||dataCenter={}||errMsg=fail to get WorkOrderHandler\",\n                    workOrderJsonString, EnvUtil.getStr(), workOrderDTO.getDataCenter(),e);\n            Result.buildFail(\"工单提交异常\");\n        }\n        if (submitResult.failed()) {\n            return Result.buildFail(submitResult.getMessage());\n        }\n\n        return Result.buildSucc(convert2WorkOrderSubmittedVO(submitResult.getData()));\n    }\n\n    @Override\n    public Result<Void> process(WorkOrderProcessDTO processDTO, Integer projectId) throws NotFindSubclassException {\n        final Result<Void> voidResult = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (voidResult.failed()){\n            return voidResult;\n        }\n        Result<Void> checkProcessResult = checkProcessValid(processDTO);\n        if (checkProcessResult.failed()) {\n            return checkProcessResult;\n        }\n        WorkOrderPO orderPO = workOrderService.getById(processDTO.getOrderId());\n        if (AriusObjUtils.isNull(orderPO)) {\n            return Result.buildFail(ResultType.NOT_EXIST.getMessage());\n        }\n\n        return doProcessByWorkOrderHandle(orderPO, processDTO);\n    }\n    \n    /**\n     * @param processDTO\n     * @param projectId\n     * @return\n     */\n    @Override\n    public Result<Void> processByJoinLogicCluster(WorkOrderProcessDTO processDTO, Integer projectId) throws NotFindSubclassException {\n        \n        \n        return process(processDTO, projectId);\n    }\n    \n    @Override\n    public int insert(WorkOrderPO orderPO) {\n        try {\n            if (orderPO.getApproverProjectId() == null) {\n                orderPO.setApproverProjectId(AuthConstant.SUPER_PROJECT_ID);\n            }\n            workOrderService.insert(orderPO);\n            return orderPO.getId().intValue();\n        } catch (Exception e) {\n            LOGGER.error(\"class=WorkOrderManagerImpl||method=insert||orderPO={}||msg=add order failed!\", orderPO, e);\n        }\n        return 0;\n    }\n\n    @Override\n    public int updateOrderById(WorkOrderPO orderPO) {\n        try {\n            return workOrderService.update(orderPO);\n        } catch (Exception e) {\n            LOGGER.error(\"class=WorkOrderManagerImpl||method=updateOrderById||orderPO={}||msg=update order failed!\",\n                orderPO, e);\n        }\n        return 0;\n    }\n\n    @Override\n    public Result<OrderDetailBaseVO> getById(Long id) {\n        try {\n            WorkOrderPO orderPO = workOrderService.getById(id);\n            if (AriusObjUtils.isNull(orderPO)) {\n                return Result.buildFail(ResultType.NOT_EXIST.getMessage());\n            }\n\n            return Result.buildSucc(convert2DetailBaseVO(getBaseDetail(orderPO)));\n\n        } catch (Exception e) {\n            LOGGER.error(\"class=WorkOrderManagerImpl||method=getById||id={}||msg=get order failed!\", id, e);\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public List<WorkOrderPO> list() {\n        try {\n            return workOrderService.list();\n            \n        } catch (Exception e) {\n            LOGGER.error(\"class=WorkOrderManagerImpl||method=list||msg=get all order failed!\", e);\n        }\n        return new ArrayList<>();\n    }\n\n    @Override\n    public Result<Void> cancelOrder(Long id, String userName) {\n        try {\n            WorkOrderPO orderPO = workOrderService.getById(id);\n            if (AriusObjUtils.isNull(orderPO)) {\n                return Result.buildFail(ResultType.NOT_EXIST.getMessage());\n            }\n\n            if (!userName.equals(orderPO.getApplicant())) {\n                return Result.buildFail(ResultType.OPERATE_FORBIDDEN_ERROR.getMessage());\n            }\n    \n            if (workOrderService.updateOrderStatusById(id, OrderStatusEnum.CANCELLED.getCode())) {\n                return Result.buildSucc();\n            }\n\n        } catch (Exception e) {\n            LOGGER.error(\"class=WorkOrderManagerImpl||method=cancelOrder||id={}||msg=cancel order failed!\", id, e);\n            return Result.buildFail(ResultType.FAIL.getMessage());\n        }\n        return Result.buildFail(ResultType.FAIL.getMessage());\n    }\n\n    @Override\n    public Result<Void> processOrder(WorkOrderPO order) {\n        try {\n            WorkOrderPO orderPO = workOrderService.getById(order.getId());\n            if (AriusObjUtils.isNull(orderPO)) {\n                return Result.buildFail(ResultType.NOT_EXIST.getMessage());\n            }\n            if (workOrderService.update(order) > 0) {\n                return Result.buildSucc();\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=WorkOrderManagerImpl||method=processOrder||id={}||msg=cancel order failed!\",\n                order.getId(), e);\n            return Result.buildFail(ResultType.FAIL.getMessage());\n        }\n        return Result.buildFail(ResultType.FAIL.getMessage());\n    }\n\n    @Override\n    public Result<List<WorkOrderVO>> getOrderApplyList(Integer status, Integer projectId) {\n        List<WorkOrderVO> orderDOList = Lists.newArrayList();\n        try {\n            orderDOList=workOrderService.listByStatusAndProjectId(status, projectId);\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=WorkOrderManagerImpl||method=getOrderApplyList||status={}||msg=get apply order failed!\",\n                status, e);\n        }\n        return Result.buildSucc(orderDOList);\n    }\n\n    /**\n     * @param applicant\n     * @param status\n     * @return\n     */\n    @Override\n    public Result<List<WorkOrderVO>> getOrderApplyList(String applicant, Integer status) {\n        List<WorkOrderVO> orderDOList = Lists.newArrayList();\n        try {\n            orderDOList = workOrderService.listByApplicantAndStatus(applicant, status);\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=WorkOrderManagerImpl||method=getOrderApplyList||applicant={}||status={}||msg=get apply order failed!\",\n                applicant, status, e);\n        }\n        return Result.buildSucc(orderDOList);\n    }\n\n    @Override\n    public List<WorkOrderPO> getApprovalList(String approver) {\n        try {\n            //是用户 但不是管理员\n            if (!roleTool.isAdmin(approver) && Objects.nonNull(userService.getUserBriefByUserName(approver))) {\n                return workOrderService.listByApproverAndStatus(approver, null);\n            }\n            return workOrderService.list();\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=WorkOrderManagerImpl||method=getApprovalList||approver={}||msg=get approval order failed!\",\n                approver, e);\n        }\n        return Collections.emptyList();\n    }\n\n    @Override\n    public List<WorkOrderPO> getPassApprovalList(String approver) {\n        try {\n            if (!roleTool.isAdmin(approver)) {\n                return workOrderService.listByApproverAndStatus(approver, OrderStatusEnum.PASSED.getCode());\n            }\n            return workOrderService.listByStatus(OrderStatusEnum.PASSED.getCode());\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=WorkOrderManagerImpl||method=getPassApprovalList||approver={}||msg=get approval order list failed!\",\n                approver, e);\n        }\n        return Collections.emptyList();\n    }\n\n    @Override\n    public List<WorkOrderPO> getWaitApprovalList(String userName) {\n        List<WorkOrderPO> orderList = new ArrayList<>();\n        try {\n            orderList = workOrderService.listByStatus(OrderStatusEnum.WAIT_DEAL.getCode());\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=WorkOrderManagerImpl||method=getWaitApprovalList||userName={}||msg=get wait order list failed!\",\n                userName, e);\n        }\n\n        if (roleTool.isAdmin(userName)) {\n            return orderList;\n        } else {\n            orderList = handleOrderList(userName, orderList);\n        }\n        return orderList;\n    }\n\n    @Override\n    public OrderInfoDetail getBaseDetail(WorkOrderPO orderPO) throws NotFindSubclassException, ESOperateException {\n        if (AriusObjUtils.isNull(orderPO)) {\n            return null;\n        }\n\n        OrderInfoDetail detailBaseDTO = new OrderInfoDetail();\n        detailBaseDTO.setDescription(orderPO.getDescription());\n        detailBaseDTO.setCreateTime(orderPO.getCreateTime());\n        detailBaseDTO.setFinishTime(orderPO.getFinishTime());\n        detailBaseDTO.setId(orderPO.getId());\n        detailBaseDTO.setOpinion(orderPO.getOpinion());\n        detailBaseDTO.setStatus(orderPO.getStatus());\n        detailBaseDTO.setType(orderPO.getType());\n        detailBaseDTO.setTitle(orderPO.getTitle());\n        detailBaseDTO.setApplicantProjectId(orderPO.getApplicantProjectId());\n        UserBriefVO userBriefVO = userService.getUserBriefByUserName(orderPO.getApplicant());\n        Map<Integer, Dept> map = deptService.getAllDeptMap();\n        if (Objects.nonNull(userBriefVO) && map.containsKey(userBriefVO.getDeptId())) {\n            detailBaseDTO.setAppDeptName(map.get(userBriefVO.getDeptId()).getDeptName());\n\n        }\n\n        WorkOrderTypeEnum typeEnum = WorkOrderTypeEnum.valueOfName(orderPO.getType());\n        if (WorkOrderTypeEnum.UNKNOWN.equals(typeEnum)) {\n            return null;\n        }\n\n        WorkOrderHandler handler = (WorkOrderHandler) handleFactory.getByHandlerNamePer(orderPO.getType());\n        // 获取具体工单的详情\n        try {\n            detailBaseDTO.setDetail(handler.getOrderDetail(orderPO.getExtensions()));\n            detailBaseDTO.setApproverList(handler.getApproverList(detailBaseDTO.getDetail()));\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=WorkOrderManagerImpl||method=getBaseDetail||extensions={}||msg=get order detail failed!\",\n                orderPO.getExtensions(), e);\n        }\n        UserBriefVO briefVO = userService.getUserBriefByUserName(orderPO.getApplicant());\n        detailBaseDTO.setApplicant(briefVO);\n        return detailBaseDTO;\n    }\n\n    @Override\n    public Result<List<WorkOrderVO>> getOrderApprovalListByStatus(Integer status) throws OperateForbiddenException {\n        List<WorkOrderPO> orderDOList = new ArrayList<>();\n\n        String userName = SpringTool.getUserName();\n\n        if (AriusObjUtils.isNull(status)) {\n            orderDOList = getApprovalList(userName);\n\n        } else if (OrderStatusEnum.WAIT_DEAL.getCode().equals(status)) {\n            orderDOList = getWaitApprovalList(userName);\n\n        } else if (OrderStatusEnum.PASSED.getCode().equals(status)) {\n            orderDOList = getPassApprovalList(userName);\n        }\n\n        return Result.buildSucc(ConvertUtil.list2List(orderDOList, WorkOrderVO.class));\n    }\n\n    /*****************************************private*****************************************************/\n\n    private Result<Void> checkSubmitValid(WorkOrderDTO workOrderDTO) {\n\n        if (AriusObjUtils.isNull(workOrderDTO.getType())) {\n            return Result.buildParamIllegal(\"工单类型为空\");\n        }\n\n        if (AriusObjUtils.isNull(workOrderDTO.getContentObj())) {\n            return Result.buildParamIllegal(\"工单内容为空\");\n        }\n\n        WorkOrderTypeEnum typeEnum = WorkOrderTypeEnum.valueOfName(workOrderDTO.getType());\n        if (WorkOrderTypeEnum.UNKNOWN.equals(typeEnum)) {\n            return Result.buildNotExist(\"工单类型不存在\");\n        }\n\n        if (AriusObjUtils.isNull(userService.getUserBriefByUserName(workOrderDTO.getSubmitor()))) {\n            return Result.buildParamIllegal(\"提交人非法\");\n        }\n\n        if (AriusObjUtils.isNull(workOrderDTO.getSubmitorProjectId())) {\n            return Result.buildParamIllegal(\"提交projectID为空\");\n        }\n        if (PROJECT_ID_TO_CREATE != workOrderDTO.getSubmitorProjectId()\n            && !projectService.checkProjectExist(workOrderDTO.getSubmitorProjectId())) {\n            return Result.buildNotExist(\"提交projectId不存在\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private void initWorkOrderDTO(WorkOrderDTO workOrderDTO) throws OperateForbiddenException {\n        workOrderDTO.setSubmitor(SpringTool.getUserName());\n    }\n\n    private AriusWorkOrderInfoSubmittedVO convert2WorkOrderSubmittedVO(WorkOrderPO workOrderPO) {\n        if (AriusObjUtils.isNull(workOrderPO)) {\n            return null;\n        }\n        AriusWorkOrderInfoSubmittedVO vo = new AriusWorkOrderInfoSubmittedVO();\n        vo.setId(workOrderPO.getId());\n        vo.setTitle(workOrderPO.getTitle());\n        return vo;\n    }\n\n    private Result<Void> checkProcessValid(WorkOrderProcessDTO processDTO) {\n        if (AriusObjUtils.isNull(processDTO)) {\n            return Result.buildParamIllegal(\"处理工单不存在\");\n        }\n\n        if (AriusObjUtils.isNull(processDTO.getOrderId())) {\n            return Result.buildParamIllegal(\"orderId为空\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> doProcessByWorkOrderHandle(WorkOrderPO orderPO,\n                                                    WorkOrderProcessDTO processDTO) throws NotFindSubclassException {\n        WorkOrderHandler handler = (WorkOrderHandler) handleFactory.getByHandlerNamePer(orderPO.getType());\n\n        Result<Void> checkAuthResult = handler.checkAuthority(orderPO, processDTO.getAssignee());\n        if (processDTO.getCheckAuthority().booleanValue() && checkAuthResult.failed()) {\n            return checkAuthResult;\n        }\n\n        try {\n\n            if (AGREE.getValue().equals(processDTO.getOutcome())) {\n                return handler.processAgree(builderWorkOrder(orderPO, processDTO), processDTO.getAssignee(),\n                    processDTO.getComment());\n            }\n\n            if (DISAGREE.getValue().equals(processDTO.getOutcome())) {\n                return handler.processDisagree(orderPO, processDTO);\n            }\n\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=WorkOrderController||method=doProcessByWorkOrderHandle||errMsg={}\", e.getMessage(), e);\n            return Result.buildFail(e.getMessage());\n        }\n\n        return Result.buildFail(\"审批结果非法\");\n    }\n\n    private WorkOrder builderWorkOrder(WorkOrderPO orderPO, WorkOrderProcessDTO processDTO) {\n        WorkOrder workOrder = new WorkOrder();\n        workOrder.setId(orderPO.getId());\n        workOrder.setTitle(orderPO.getTitle());\n        workOrder.setSubmitor(orderPO.getApplicant());\n        workOrder.setSubmitorProjectId(orderPO.getApplicantProjectId());\n        workOrder.setType(orderPO.getType());\n        workOrder.setOpinion(processDTO.getComment());\n        //合并两Json属性\n        JSONObject jsonObject = JSON.parseObject(orderPO.getExtensions());\n        jsonObject.putAll(JSON.parseObject(ConvertUtil.obj2Json(processDTO.getContentObj())));\n        workOrder.setContentObj(jsonObject.toJavaObject(Object.class));\n        return workOrder;\n    }\n\n    private OrderDetailBaseVO convert2DetailBaseVO(OrderInfoDetail orderInfoDetail) {\n        OrderDetailBaseVO baseVO = new OrderDetailBaseVO();\n\n        baseVO.setId(orderInfoDetail.getId());\n        baseVO.setType(orderInfoDetail.getType());\n        baseVO.setStatus(orderInfoDetail.getStatus());\n        baseVO.setAppDeptName(orderInfoDetail.getAppDeptName());\n        baseVO.setApplicant(orderInfoDetail.getApplicant());\n        baseVO.setApplicantProjectId(orderInfoDetail.getApplicantProjectId());\n        baseVO.setApplicantAppName(getApplicantAppName(orderInfoDetail.getApplicantProjectId()));\n        baseVO.setApproverList(orderInfoDetail.getApproverList());\n        baseVO.setFinishTime(orderInfoDetail.getFinishTime());\n        baseVO.setCreateTime(orderInfoDetail.getCreateTime());\n        baseVO.setTitle(orderInfoDetail.getTitle());\n        baseVO.setOpinion(orderInfoDetail.getOpinion());\n        baseVO.setDescription(orderInfoDetail.getDescription());\n        baseVO.setDetail(JSON.toJSONString(orderInfoDetail.getDetail()));\n\n        return baseVO;\n    }\n\n    private List<WorkOrderPO> handleOrderList(String userName, List<WorkOrderPO> orderList) {\n        orderList = orderList.stream().filter(orderDO -> {\n            try {\n                WorkOrderHandler handler = (WorkOrderHandler) handleFactory.getByHandlerNamePer(orderDO.getType());\n\n                AbstractOrderDetail abstractOrderDetail = handler.getOrderDetail(orderDO.getExtensions());\n                if (null == abstractOrderDetail) {\n                    return false;\n                }\n\n                List<UserBriefVO> ariusUserInfos = handler.getApproverList(abstractOrderDetail);\n\n                for (UserBriefVO userBriefVO : ariusUserInfos) {\n                    if (userName.equals(userBriefVO.getUserName())) {\n                        return true;\n                    }\n                }\n            } catch (Exception e) {\n                LOGGER.warn(\"class=WorkOrderManagerImpl||method=getWaitApprovalList||userName={}||msg=exception!\",\n                    userName, e);\n            }\n            return false;\n        }).collect(Collectors.toList());\n        return orderList;\n    }\n\n    private String getApplicantAppName(Integer applicantProjectId) {\n        ProjectBriefVO briefVO = projectService.getProjectBriefByProjectId(applicantProjectId);\n        if (null != briefVO) {\n            return briefVO.getProjectName();\n        }\n\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/workorder/utils/OpOrderTaskConverter.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.workorder.utils;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.CLIENT_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.DATA_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.MASTER_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_DOCKER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_HOST;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterBaseContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterIndecreaseDockerContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterNewDockerContent;\nimport com.didichuxing.datachannel.arius.admin.biz.task.content.ClusterNewHostContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleDocker;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud.ElasticCloudCommonActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud.ElasticCloudCreateActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud.ElasticCloudScaleActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostCreateActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostScaleActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.ecm.EcmTask;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\n\nimport java.util.*;\n\n/**\n * @author zengqiao\n * @date 20/10/24\n */\npublic class OpOrderTaskConverter {\n\n    private OpOrderTaskConverter() {\n    }\n\n    /**\n     * 工单过来的数据转list\n     */\n    public static List<EcmParamBase> convert2EcmParamBaseList(ESClusterTypeEnum clusterTypeEnum,\n                                                              OpTaskTypeEnum opTaskTypeEnum,\n                                                              ClusterBaseContent clusterBaseContent) {\n        List<EcmParamBase> ecmParamBaseList = null;\n        if (ES_DOCKER.equals(clusterTypeEnum)) {\n            ecmParamBaseList = convert2ElasticCloudParamBaseList(clusterTypeEnum, opTaskTypeEnum, clusterBaseContent);\n        } else if (ES_HOST.equals(clusterTypeEnum)) {\n            ecmParamBaseList = convert2HostParamBaseList(opTaskTypeEnum, clusterBaseContent);\n        }\n        return ecmParamBaseList;\n    }\n\n    private static List<EcmParamBase> convert2ElasticCloudParamBaseList(ESClusterTypeEnum clusterTypeEnum,\n                                                                        OpTaskTypeEnum opTaskTypeEnum,\n                                                                        ClusterBaseContent clusterBaseContent) {\n        List<EcmParamBase> ecmParamBaseList = new ArrayList<>();\n        if (OpTaskTypeEnum.CLUSTER_EXPAND.equals(opTaskTypeEnum)\n            || OpTaskTypeEnum.CLUSTER_SHRINK.equals(opTaskTypeEnum)) {\n            ClusterIndecreaseDockerContent clusterOpIndecreaseDockerContent = (ClusterIndecreaseDockerContent) clusterBaseContent;\n            for (ESClusterRoleDocker esClusterRoleDocker : clusterOpIndecreaseDockerContent.getRoleClusters()) {\n                ElasticCloudScaleActionParam elasticCloudScaleActionParam = new ElasticCloudScaleActionParam();\n                elasticCloudScaleActionParam.setType(clusterTypeEnum.getCode());\n                elasticCloudScaleActionParam.setPodNum(esClusterRoleDocker.getPodNumber());\n                elasticCloudScaleActionParam.setNsTree(\"\");\n                elasticCloudScaleActionParam.setMachineRoom(\"\");\n                elasticCloudScaleActionParam.setNodeNumber(esClusterRoleDocker.getPodNumber());\n                elasticCloudScaleActionParam.setRoleName(esClusterRoleDocker.getRole());\n                elasticCloudScaleActionParam.setPhyClusterId(clusterOpIndecreaseDockerContent.getPhyClusterId());\n                elasticCloudScaleActionParam.setPhyClusterName(clusterBaseContent.getPhyClusterName());\n                ecmParamBaseList.add(elasticCloudScaleActionParam);\n            }\n        } else if (OpTaskTypeEnum.CLUSTER_NEW.equals(opTaskTypeEnum)) {\n            ClusterNewDockerContent clusterOpNewDockerContent = (ClusterNewDockerContent) clusterBaseContent;\n            for (String roleName : Arrays.asList(MASTER_NODE.getDesc(), CLIENT_NODE.getDesc(), DATA_NODE.getDesc())) {\n                ElasticCloudCreateActionParam elasticCloudCreateActionParam = ConvertUtil\n                    .obj2Obj(clusterOpNewDockerContent, ElasticCloudCreateActionParam.class);\n                elasticCloudCreateActionParam.setPhyClusterId(ClusterConstant.INVALID_VALUE);\n                elasticCloudCreateActionParam.setRoleName(roleName);\n                elasticCloudCreateActionParam.setImageName(\"\");\n                ecmParamBaseList.add(elasticCloudCreateActionParam);\n            }\n\n            for (ESClusterRoleDocker esClusterRoleDocker : clusterOpNewDockerContent.getRoleClusters()) {\n                ElasticCloudCreateActionParam elasticCloudCreateActionParam = null;\n                if (MASTER_NODE.getDesc().equals(esClusterRoleDocker.getRole())) {\n                    elasticCloudCreateActionParam = (ElasticCloudCreateActionParam) ecmParamBaseList.get(0);\n                } else if (CLIENT_NODE.getDesc().equals(esClusterRoleDocker.getRole())) {\n                    elasticCloudCreateActionParam = (ElasticCloudCreateActionParam) ecmParamBaseList.get(1);\n                } else if (DATA_NODE.getDesc().equals(esClusterRoleDocker.getRole())) {\n                    elasticCloudCreateActionParam = (ElasticCloudCreateActionParam) ecmParamBaseList.get(2);\n                } else {\n                    continue;\n                }\n                elasticCloudCreateActionParam.setMachineSpec(esClusterRoleDocker.getMachineSpec());\n                elasticCloudCreateActionParam.setNodeNumber(esClusterRoleDocker.getPodNumber());\n            }\n        }\n        return ecmParamBaseList;\n    }\n\n    private static List<EcmParamBase> convert2HostParamBaseList(OpTaskTypeEnum opTaskTypeEnum,\n                                                                ClusterBaseContent clusterBaseContent) {\n        List<EcmParamBase> ecmParamBaseList = new ArrayList<>();\n        if (OpTaskTypeEnum.CLUSTER_NEW.equals(opTaskTypeEnum)) {\n            ClusterNewHostContent clusterOpNewHostContent = (ClusterNewHostContent) clusterBaseContent;\n            for (String roleName : Arrays.asList(MASTER_NODE.getDesc(), CLIENT_NODE.getDesc(), DATA_NODE.getDesc())) {\n                HostCreateActionParam hostCreateActionParam = ConvertUtil.obj2Obj(clusterOpNewHostContent,\n                    HostCreateActionParam.class);\n                hostCreateActionParam.setPhyClusterId(ClusterConstant.INVALID_VALUE);\n                hostCreateActionParam.setRoleName(roleName);\n                hostCreateActionParam.setImageName(\"\");\n                hostCreateActionParam.setHostList(new ArrayList<>());\n                hostCreateActionParam.setMasterHostList(new ArrayList<>());\n                ecmParamBaseList.add(hostCreateActionParam);\n            }\n\n            for (ESClusterRoleHost esClusterRoleHost : clusterOpNewHostContent.getClusterRoleHosts()) {\n                // 这三个节点的顺序一定是这个顺序\n                if (AriusObjUtils.isBlank(esClusterRoleHost.getHostname())) {\n                    continue;\n                }\n                if (MASTER_NODE.getDesc().equals(esClusterRoleHost.getRole())) {\n                    HostCreateActionParam masterCreateAction = (HostCreateActionParam) ecmParamBaseList.get(0);\n                    masterCreateAction.getHostList().add(esClusterRoleHost.getHostname());\n                    masterCreateAction.setPort(esClusterRoleHost.getPort());\n\n                } else if (CLIENT_NODE.getDesc().equals(esClusterRoleHost.getRole())) {\n                    HostCreateActionParam clientCreateAction = ((HostCreateActionParam) ecmParamBaseList.get(1));\n                    clientCreateAction.getHostList().add(esClusterRoleHost.getHostname());\n                    clientCreateAction.setPort(esClusterRoleHost.getPort());\n\n                } else if (DATA_NODE.getDesc().equals(esClusterRoleHost.getRole())) {\n                    HostCreateActionParam dataCreateAction = ((HostCreateActionParam) ecmParamBaseList.get(2));\n                    dataCreateAction.getHostList().add(esClusterRoleHost.getHostname());\n                    dataCreateAction.setPort(esClusterRoleHost.getPort());\n                }\n            }\n\n            List<String> masterHostList = ((HostCreateActionParam) ecmParamBaseList.get(0)).getHostList();\n            for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n                HostCreateActionParam hostCreateActionParam = (HostCreateActionParam) ecmParamBase;\n                hostCreateActionParam.setMasterHostList(masterHostList);\n                hostCreateActionParam.setNodeNumber(hostCreateActionParam.getHostList().size());\n            }\n            return ecmParamBaseList;\n        }\n        return new ArrayList<>();\n    }\n\n    /**\n     * DB中的handle data数据转map\n     */\n    public static Map<String, EcmParamBase> convert2EcmParamBaseMap(EcmTask ecmTask) {\n        List<EcmParamBase> ecmParamBaseList = null;\n        if (ES_DOCKER.getCode() == ecmTask.getType()) {\n            ecmParamBaseList = convert2ElasticCloudParamBaseList(ecmTask);\n        } else if (ES_HOST.getCode() == ecmTask.getType()) {\n            ecmParamBaseList = convert2HostParamBaseList(ecmTask);\n        }\n        if (AriusObjUtils.isNull(ecmParamBaseList)) {\n            return new HashMap<>(8);\n        }\n\n        Map<String, EcmParamBase> roleNameEcmParamBaseMap = new HashMap<>(8);\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            roleNameEcmParamBaseMap.put(ecmParamBase.getRoleName(), ecmParamBase);\n        }\n        return roleNameEcmParamBaseMap;\n    }\n\n    public static List<EcmParamBase> convert2EcmParamBaseList(EcmTask ecmTask) {\n        if (ESClusterTypeEnum.ES_DOCKER.getCode() == ecmTask.getType()) {\n            return convert2ElasticCloudParamBaseList(ecmTask);\n        } else if (ESClusterTypeEnum.ES_HOST.getCode() == ecmTask.getType()) {\n            return convert2HostParamBaseList(ecmTask);\n        }\n        return new ArrayList<>();\n    }\n\n    private static List<EcmParamBase> convert2ElasticCloudParamBaseList(EcmTask ecmTask) {\n        List<EcmParamBase> ecmParamBaseList;\n        if (Objects.equals(OpTaskTypeEnum.CLUSTER_EXPAND.getType(), ecmTask.getOrderType())\n            || Objects.equals(OpTaskTypeEnum.CLUSTER_SHRINK.getType(), ecmTask.getOrderType())) {\n            ecmParamBaseList = new ArrayList<>(\n                JSON.parseArray(ecmTask.getHandleData(), ElasticCloudScaleActionParam.class));\n        } else if (Objects.equals(OpTaskTypeEnum.CLUSTER_NEW.getType(), ecmTask.getOrderType())) {\n            ecmParamBaseList = new ArrayList<>(\n                ConvertUtil.str2ObjArrayByJson(ecmTask.getHandleData(), ElasticCloudCreateActionParam.class));\n        } else {\n            ecmParamBaseList = new ArrayList<>(\n                JSON.parseArray(ecmTask.getHandleData(), ElasticCloudCommonActionParam.class));\n        }\n        return ecmParamBaseList;\n    }\n\n    private static List<EcmParamBase> convert2HostParamBaseList(EcmTask ecmTask) {\n        List<EcmParamBase> ecmParamBaseList;\n        if (Objects.equals(OpTaskTypeEnum.CLUSTER_NEW.getType(), ecmTask.getOrderType())) {\n            ecmParamBaseList = new ArrayList<>(\n                ConvertUtil.str2ObjArrayByJson(ecmTask.getHandleData(), HostCreateActionParam.class));\n        } else if (Objects.equals(OpTaskTypeEnum.CLUSTER_EXPAND.getType(), ecmTask.getOrderType())\n                   || Objects.equals(OpTaskTypeEnum.CLUSTER_SHRINK.getType(), ecmTask.getOrderType())) {\n            ecmParamBaseList = new ArrayList<>(JSON.parseArray(ecmTask.getHandleData(), HostScaleActionParam.class));\n        } else {\n            ecmParamBaseList = new ArrayList<>(JSON.parseArray(ecmTask.getHandleData(), HostParamBase.class));\n        }\n        return ecmParamBaseList;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/zeus/ZeusCollectManager.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.zeus;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESZeusHostInfoDTO;\n\n/**\n * Created by linyunan on 2021-09-14\n */\npublic interface ZeusCollectManager {\n    /**\n     * @param esZeusHostInfoDTO      Zeus采集节点信息实体\n     * @return\n     */\n    @Deprecated\n    Result<Boolean> updateHttpAddressFromZeus(ESZeusHostInfoDTO esZeusHostInfoDTO);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-biz/src/main/java/com/didichuxing/datachannel/arius/admin/biz/zeus/ZeusCollectManagerImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.zeus;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.*;\nimport static com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils.isBlank;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESZeusHostInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\n\n/**\n * @author linyunan\n * @date 2021-09-14\n */\n@Component\npublic class ZeusCollectManagerImpl implements ZeusCollectManager {\n\n    @Autowired\n    private ClusterPhyManager          clusterPhyManager;\n\n    @Autowired\n    private ClusterPhyService          clusterPhyService;\n    /**\n     * Map<clusterPhyName, clientCount>\n     */\n    private final Map<String, Integer> clusterPhyName2ClientCountMap = new ConcurrentHashMap<>();\n\n    @Override\n    public synchronized Result<Boolean> updateHttpAddressFromZeus(ESZeusHostInfoDTO esZeusHostInfoDTO) {\n\n        if (null == esZeusHostInfoDTO) {\n            return Result.buildParamIllegal(\"入参为空\");\n        }\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(esZeusHostInfoDTO.getClusterPhyName());\n        if (null == clusterPhy) {\n            return Result.buildFail(\"物理集群不存在\");\n        }\n\n        if (DATA_NODE.getDesc().equals(esZeusHostInfoDTO.getRole())) {\n            return Result.buildSucc();\n        }\n\n        ClusterPhyDTO clusterDTO = new ClusterPhyDTO();\n        clusterDTO.setId(clusterPhy.getId());\n\n        //如果集群存在client, 用client代替master作为集群读写访问入口\n        if (CLIENT_NODE.getDesc().equals(esZeusHostInfoDTO.getRole())) {\n            //清空master httpAddress\n            if (null == clusterPhyName2ClientCountMap.get(esZeusHostInfoDTO.getClusterPhyName())) {\n                clusterDTO.setHttpAddress(\"\");\n                clusterDTO.setHttpWriteAddress(\"\");\n                Result<Boolean> result = clusterPhyService.editCluster(clusterDTO, null);\n                if (result.success()) {\n                    //client标识位 + 1\n                    clusterPhyName2ClientCountMapAddOne(esZeusHostInfoDTO.getClusterPhyName());\n\n                    //刷新最新物理集群配置\n                    clusterPhy = clusterPhyService.getClusterByName(esZeusHostInfoDTO.getClusterPhyName());\n                }\n            }\n\n            if (clusterPhyName2ClientCountMap.get(esZeusHostInfoDTO.getClusterPhyName()) >= 0) {\n                buildESClusterDTOFromZeus(clusterDTO, clusterPhy, esZeusHostInfoDTO);\n                clusterPhyManager.editCluster(clusterDTO, null);\n                clusterPhyName2ClientCountMapAddOne(esZeusHostInfoDTO.getClusterPhyName());\n            }\n        }\n\n        if (MASTER_NODE.getDesc().equals(esZeusHostInfoDTO.getRole())\n            && null == clusterPhyName2ClientCountMap.get(esZeusHostInfoDTO.getClusterPhyName())) {\n            buildESClusterDTOFromZeus(clusterDTO, clusterPhy, esZeusHostInfoDTO);\n            clusterPhyManager.editCluster(clusterDTO, null);\n        }\n        return Result.buildSucc();\n    }\n\n    private void buildESClusterDTOFromZeus(ClusterPhyDTO clusterDTO, ClusterPhy clusterPhy,\n                                           ESZeusHostInfoDTO esZeusHostInfoDTO) {\n        String httpAddress = clusterPhy.getHttpAddress();\n        List<String> httpAddressList = ListUtils.string2StrList(httpAddress);\n        if (httpAddressList.contains(esZeusHostInfoDTO.getHttpAddress())) {\n            return;\n        }\n\n        StringBuilder httpAddressStr = new StringBuilder();\n        if (isBlank(httpAddress) && !isBlank(esZeusHostInfoDTO.getHttpAddress())) {\n            httpAddressStr.append(esZeusHostInfoDTO.getHttpAddress());\n        } else if (!isBlank(httpAddress) && !isBlank(esZeusHostInfoDTO.getHttpAddress())) {\n            httpAddressStr.append(httpAddress).append(\",\").append(esZeusHostInfoDTO.getHttpAddress());\n        }\n\n        clusterDTO.setHttpAddress(httpAddressStr.toString());\n        clusterDTO.setHttpWriteAddress(httpAddressStr.toString());\n    }\n\n    private void clusterPhyName2ClientCountMapAddOne(String clusterPhyName) {\n        if (null == clusterPhyName) {\n            return;\n        }\n        if (clusterPhyName2ClientCountMap.containsKey(clusterPhyName)) {\n            clusterPhyName2ClientCountMap.put(clusterPhyName, clusterPhyName2ClientCountMap.get(clusterPhyName) + 1);\n        } else {\n            clusterPhyName2ClientCountMap.put(clusterPhyName, 0);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <artifactId>arius-admin</artifactId>\n       <version>${revision}${sha1}${changelist}</version>\n    </parent>\n\n    <artifactId>arius-admin-common</artifactId>\n\n    <dependencies>\n         <dependency>\n            <groupId>io.github.java-diff-utils</groupId>\n            <artifactId>java-diff-utils</artifactId>\n        </dependency>\n              <dependency>\n                <groupId>com.github.java-json-tools</groupId>\n                <artifactId>json-patch</artifactId>\n            </dependency>\n\n         <dependency>\n             <groupId>io.github.knowstack</groupId>\n             <artifactId>kf-security-spring-boot-starter</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-collections4</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>joda-time</groupId>\n            <artifactId>joda-time</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.yaml</groupId>\n            <artifactId>snakeyaml</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.tomcat.embed</groupId>\n            <artifactId>tomcat-embed-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.fasterxml.jackson.datatype</groupId>\n            <artifactId>jackson-datatype-jsr310</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-elasticsearch-client</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-log</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-compress</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.baomidou</groupId>\n            <artifactId>mybatis-plus-boot-starter</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.springframework</groupId>\n                    <artifactId>spring-jdbc</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>io.swagger</groupId>\n            <artifactId>swagger-annotations</artifactId>\n        </dependency>\n\n    </dependencies>\n\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/Triple.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common;\n\npublic class Triple<T, V, U> {\n    private T v1;\n    private V v2;\n    private U v3;\n\n    public Triple() {\n    }\n\n    public Triple(T v1, V v2, U v3) {\n        this.v1 = v1;\n        this.v2 = v2;\n        this.v3 = v3;\n    }\n\n    public T v1() {\n        return v1;\n    }\n\n    public Triple<T, V, U> setV1(T v1) {\n        this.v1 = v1;\n        return this;\n    }\n\n    public V v2() {\n        return v2;\n    }\n\n    public Triple<T, V, U> setV2(V v2) {\n        this.v2 = v2;\n        return this;\n    }\n\n    public U v3() {\n        return v3;\n    }\n\n    public Triple<T, V, U> setV3(U v3) {\n        this.v3 = v3;\n        return this;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        Triple<?, ?, ?> triple = (Triple<?, ?, ?>) o;\n\n        if (v1 != null ? !v1.equals(triple.v1) : triple.v1 != null) {\n            return false;\n        }\n        if (v2 != null ? !v2.equals(triple.v2) : triple.v2 != null) {\n            return false;\n        }\n        return v3 != null ? v3.equals(triple.v3) : triple.v3 == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = (v1 != null) ? v1.hashCode() : 0;\n        result = 63 * result + 31 * (v2 != null ? v2.hashCode() : 0) + (v2 != null ? v2.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/Tuple.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\n\nimport lombok.Data;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/5/29 下午4:08\n * @Modified By\n */\n@JsonIgnoreProperties(value = { \"hibernateLazyInitializer\", \"handler\" })\n@Data\npublic class Tuple<T, V> {\n\n    private T v1;\n    private V v2;\n\n    public Tuple() {\n    }\n\n    public Tuple(T v1, V v2) {\n        this.v1 = v1;\n        this.v2 = v2;\n    }\n\n    public T v1() {\n        return v1;\n    }\n\n    public Tuple<T, V> setV1(T v1) {\n        this.v1 = v1;\n        return this;\n    }\n\n    public V v2() {\n        return v2;\n    }\n\n    public Tuple<T, V> setV2(V v2) {\n        this.v2 = v2;\n        return this;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        Tuple<?, ?> tuple = (Tuple<?, ?>) o;\n\n        if (v1 != null ? !v1.equals(tuple.v1) : tuple.v1 != null) {\n            return false;\n        }\n        return v2 != null ? v2.equals(tuple.v2) : tuple.v2 == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = v1 != null ? v1.hashCode() : 0;\n        result = 31 * result + (v2 != null ? v2.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/Alias.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-07-25\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Alias {\n\n    private String name;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/BaseResult.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\nimport java.io.Serializable;\n\n/**\n * fitz\n */\n@ApiModel(description = \"返回结构\")\n@Data\npublic class BaseResult implements Serializable {\n\n    private static final long serialVersionUID = 3472961240718956029L;\n\n    @ApiModelProperty(\"异常信息\")\n    protected String          message;\n\n    @ApiModelProperty(\"提示\")\n    protected String          tips;\n\n    @ApiModelProperty(\"返回码，0表示成功；10000表示参数错误；10004表示重复；10005表示不存在；\")\n    protected Integer         code;\n\n    public boolean success() {\n        return getCode() != null && ResultType.SUCCESS.getCode() == getCode();\n    }\n\n    public boolean duplicate() {\n        return getCode() != null && ResultType.DUPLICATION.getCode() == getCode();\n    }\n\n    public boolean failed() {\n        return !success();\n    }\n\n    public boolean isPagine() {\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ESPipelineProcessor.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-09-03\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESPipelineProcessor {\n\n    @JSONField(name = \"index_template\")\n    private JSONObject indexTemplate;\n\n    @JSONField(name = \"throttle\")\n    private JSONObject throttle;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/GatewayHeartbeat.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-07-26\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class GatewayHeartbeat {\n\n    /**\n     * \"集群名称\"\n     */\n    private String clusterName;\n\n    /**\n     * 主机名\n     */\n    private String hostName;\n\n    /**\n     * 端口\n     */\n    private int    port;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/IndexNameQueryAvgRate.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-06-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexNameQueryAvgRate {\n\n    /**\n     * 索引名称\n     */\n    private String indexName;\n\n    /**\n     * 访问次数\n     */\n    private Double queryTotalRate;\n\n    /**\n     * 统计日期 yyyy-MM-dd\n     */\n    private String date;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/IndexTemplatePhysicalConfig.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport java.util.Map;\nimport java.util.Set;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplatePhysicalConfig {\n\n    /**\n     * 人工设置的pipeline限流值\n     */\n    private Integer                                         manualPipeLineRateLimit;\n\n    /**\n     * 动态pipeline限流值，pipeLineRateLimit 必须小于 manualPipeLineRateLimit\n     */\n    private Integer                                         pipeLineRateLimit;\n\n    /**\n     * kafkatopic\n     */\n    private String                                          kafkaTopic;\n\n    /**\n     * 可以访问的APP\n     */\n    private Set<Integer> accessProjects;\n\n    /**\n     * frozen配置\n     */\n    private Boolean                                         frozen;\n\n    /**\n     * 用于索引多type改造   是否启用索引名称映射 0 禁用 1 启用\n     */\n    private Boolean                                         mappingIndexNameEnable;\n\n    /**\n     * 是否是默认写索引标识\n     */\n    private Boolean                                         defaultWriterFlags;\n\n    /**\n     * 组ID\n     */\n    private String                                          groupId;\n\n    /**\n     * 多type索引type名称到单type索引模板名称的映射\n     */\n    private Map<String/*typeName*/, String/*templateName*/> typeIndexMapping;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/IndexTemplateValue.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n/**\n * 索引模板价值分\n * @author wangshu\n * @date 2020/09/09\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateValue implements Serializable {\n\n    private static final long serialVersionUID = 1905122041950251207L;\n\n    /**\n     * 索引模板id\n     */\n    private Integer           logicTemplateId;\n\n    /**\n     * 价值\n     */\n    private Integer           value;\n\n    /**\n     * 访问量\n     */\n    private Long              accessCount;\n\n    /**\n     * 大小G\n     */\n    private Double            sizeG;\n\n    /**\n     * 逻辑集群\n     */\n    private String            logicCluster;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/Label.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/5/20\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"标签信息\")\npublic class Label {\n\n    @ApiModelProperty(\"标签ID\")\n    private String labelId;\n\n    @ApiModelProperty(\"标签名字\")\n    private String labelName;\n\n    @ApiModelProperty(\"标签等级(green/yellow/red)\")\n    private String level;\n\n    public String getLevel() {\n        String levelCode = labelId.substring(2, 3);\n        if (\"3\".equals(levelCode)) {\n            return \"red\";\n        }\n\n        if (\"2\".equals(levelCode)) {\n            return \"yellow\";\n        }\n\n        return \"green\";\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/LogicResourceConfig.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 资源的配置\n * @author wangshu\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class LogicResourceConfig {\n\n    public static final String  QUOTA_CTL_NONE                     = \"none\";\n    public static final String  QUOTA_CTL_DISK                     = \"disk\";\n    public static final String  QUOTA_CTL_ALL                      = \"all\";\n\n    public static final Integer REPLICA_NUM_DEFAULT                = 1;\n\n    /**\n     * quota管控配置\n     * \n     * normal集群需要配置为ALL\n     * important集群设置为DISK\n     * \n     */\n    private String              quotaCtl                           = QUOTA_CTL_NONE;\n\n    /**\n     * 副本个数 1表示无副本，2表示有一个副本\n     * \n     * 目前平台中使用这个值的地方有：\n     *  1、容量规划计算模板的factor时\n     *  2、容量规划计算模板的CPU消耗时\n     * \n     * important和vip集群设置为2\n     */\n    private Integer             replicaNum                         = REPLICA_NUM_DEFAULT;\n\n    /**\n     * 模板创建工单是否自动处理\n     *\n     * vip集群设置为false\n     */\n    private Boolean             templateCreateWorkOrderAutoProcess = true;\n\n    /**\n     * 模板价值的基准值\n     *\n     * normal集群设置为0\n     * important集群设置为10\n     * vip集群设置为20\n     */\n    private Integer             templateValueBase                  = 0;\n\n    /**\n     * 热数据保存天数\n     */\n    private Integer             hotDataDays                        = -1;\n\n    /**\n     * 是否需要治理废弃的模板\n     * templateGovern\n     */\n    private Boolean             templateGovern                     = true;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/LogicTemplateTpsMetric.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport java.util.Map;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-06-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class LogicTemplateTpsMetric {\n\n    /**\n     * 历史每小时tps峰值 单位 条/s\n     * 是取各个物理模板最大值\n     */\n    private Double                          maxTps;\n\n    /**\n     * 最大值对应的小时时间\n     */\n    private String                          maxTpsTimestamp;\n\n    /**\n     * 最大值对应的索引模板物理ID\n     */\n    private Long                            maxTpsTemplateId;\n\n    /**\n     * 每个物理模板，最近15分钟平均值 单位 条/s\n     *\n     */\n    private Map<Long/*templateId*/, Double> currentTpsMap;\n\n    /**\n     * 每个物理模板，最近一段时间失败次数的平均值 单位 条/s\n     */\n    private Map<Long/*templateId*/, Double> currentFailCountMap;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/MappingOptimize.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport java.util.List;\n\nimport com.google.common.collect.Lists;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class MappingOptimize {\n    private String                    clusterName;\n\n    private String                    templateName;\n\n    private List<MappingOptimizeItem> optimizeItems = Lists.newArrayList();\n\n    public MappingOptimize(String clusterName, String templateName) {\n        this.clusterName = clusterName;\n        this.templateName = templateName;\n    }\n\n    public void addOptimize(MappingOptimizeItem item) {\n        optimizeItems.add(item);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/MappingOptimizeItem.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport com.alibaba.fastjson.JSONObject;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"MappingOptimizeItem\", description = \"优化信息\")\npublic class MappingOptimizeItem {\n\n    @ApiModelProperty(\"type名称\")\n    private String     typeName;\n\n    @ApiModelProperty(\"字段名称\")\n    private String     fieldName;\n\n    @ApiModelProperty(\"源属性\")\n    private JSONObject initial;\n\n    @ApiModelProperty(\"优化后属性\")\n    private JSONObject optimize;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/NodeAllocationInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class NodeAllocationInfo {\n    /**\n     * 节点上的分片数目\n     */\n    @JSONField(name = \"shards\")\n    private String shardsNumber;\n\n    /**\n     * 节点上索引index占用的空间大小\n     */\n    @JSONField(name = \"disk.indices\")\n    private String diskIndicesSize;\n\n    /**\n     * 节点上已用磁盘空间\n     */\n    @JSONField(name = \"disk.used\")\n    private String usedDiskSize;\n\n    /**\n     * 节点上可用磁盘空间\n     */\n    @JSONField(name = \"disk.avail\")\n    private String canUseDiskSize;\n\n    /**\n     * 节点上磁盘空间总量\n     */\n    @JSONField(name = \"disk.total\")\n    private String totalDiskSize;\n\n    /**\n     * 节点上磁盘已使用百分比\n     */\n    @JSONField(name = \"disk.percent\")\n    private String usedDiskPercent;\n\n    /**\n     * 节点主机地址\n     */\n    @JSONField(name = \"host\")\n    private String host;\n\n    /**\n     * 节点ip\n     */\n    @JSONField(name = \"ip\")\n    private String ip;\n\n    /**\n     * 节点名称\n     */\n    @JSONField(name = \"node\")\n    private String node;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/NodeAttrInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class NodeAttrInfo {\n    /**\n     * 物理集群节点名称\n     */\n    @JSONField(name = \"node\")\n    private String node;\n\n    /**\n     * 节点属性\n     */\n    @JSONField(name = \"attr\")\n    private String attribute;\n\n    /**\n     * 节点属性对应值\n     */\n    @JSONField(name = \"value\")\n    private String value;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/OperateRecord.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.ModuleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.Optional;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 操作记录\n *\n * @author shizeying\n * @date 2022/06/17\n */\n@Data\n@NoArgsConstructor\npublic class OperateRecord {\n    /**\n     * @see ModuleEnum\n     */\n    private Integer moduleId;\n\n    /**\n     * @see OperateTypeEnum\n     */\n    private Integer operateId;\n\n    /**\n     * 操作描述\n     */\n    private String  content;\n\n    /**\n     * 操作人\n     */\n    private String  userOperation;\n\n    /**\n     * 操作时间\n     */\n    private Date    operateTime;\n    /**\n     * 触发方式\n     *\n     * @see TriggerWayEnum\n     */\n    private Integer triggerWayId;\n    /**\n     * 应用id\n     */\n    private String  projectName;\n    /**\n     * 业务id\n     */\n    private String  bizId;\n\n    public OperateRecord(String projectName, OperateTypeEnum operateTypeEnum, TriggerWayEnum triggerWayEnum,\n                         String content, String userOperation, Object bizId) {\n        this.moduleId = operateTypeEnum.getModule().getCode();\n        this.operateId = operateTypeEnum.getCode();\n        this.content = content;\n        this.userOperation = userOperation;\n        this.operateTime = Calendar.getInstance().getTime();\n        this.triggerWayId = triggerWayEnum.getCode();\n        this.projectName = projectName;\n        this.bizId = Optional.ofNullable(bizId).map(String::valueOf).orElse(null);\n    }\n\n    public OperateRecord(String projectName, OperateTypeEnum operateTypeEnum, TriggerWayEnum triggerWayEnum,\n                         String content, String userOperation) {\n        this.moduleId = operateTypeEnum.getModule().getCode();\n        this.operateId = operateTypeEnum.getCode();\n        this.content = content;\n        this.userOperation = userOperation;\n        this.operateTime = Calendar.getInstance().getTime();\n        this.triggerWayId = triggerWayEnum.getCode();\n        this.projectName = projectName;\n    }\n\n    public OperateRecord(OperateTypeEnum operateTypeEnum, TriggerWayEnum triggerWayEnum, String content,\n                         String userOperation, Object bizId) {\n        this.moduleId = operateTypeEnum.getModule().getCode();\n        this.operateId = operateTypeEnum.getCode();\n        this.projectName=\"-\";\n        this.content = content;\n        this.userOperation = userOperation;\n        this.operateTime = Calendar.getInstance().getTime();\n        this.triggerWayId = triggerWayEnum.getCode();\n        this.bizId = Optional.ofNullable(bizId).map(String::valueOf).orElse(null);\n    }\n\n    public OperateRecord(OperateTypeEnum operateTypeEnum, TriggerWayEnum triggerWayEnum, String content,\n                         String userOperation) {\n        this.moduleId = operateTypeEnum.getModule().getCode();\n        this.operateId = operateTypeEnum.getCode();\n        this.content = content;\n        this.userOperation = userOperation;\n        this.operateTime = Calendar.getInstance().getTime();\n        this.triggerWayId = triggerWayEnum.getCode();\n    }\n\n    public OperateRecord(OperateTypeEnum operateTypeEnum, String content, String userOperation) {\n        this.moduleId = operateTypeEnum.getModule().getCode();\n        this.operateId = operateTypeEnum.getCode();\n        this.content = content;\n        this.userOperation = userOperation;\n        this.operateTime = Calendar.getInstance().getTime();\n    }\n\n    public OperateRecord(OperateTypeEnum operateTypeEnum, String content, String userOperation, Object bizId) {\n        this.moduleId = operateTypeEnum.getModule().getCode();\n        this.operateId = operateTypeEnum.getCode();\n        this.content = content;\n        this.userOperation = userOperation;\n        this.operateTime = Calendar.getInstance().getTime();\n        this.bizId = Optional.ofNullable(bizId).map(String::valueOf).orElse(null);\n    }\n\n    private OperateRecord(Builder builder) {\n        Optional.ofNullable(builder.operateTypeEnum).map(OperateTypeEnum::getModule).map(ModuleEnum::getCode)\n            .ifPresent(this::setModuleId);\n        Optional.ofNullable(builder.operateTypeEnum).map(OperateTypeEnum::getCode).ifPresent(this::setOperateId);\n        setContent(builder.content);\n        setUserOperation(builder.userOperation);\n        setOperateTime(Calendar.getInstance().getTime());\n        Optional.ofNullable(builder.triggerWayEnum).map(TriggerWayEnum::getCode).ifPresent(this::setTriggerWayId);\n        setProjectName(builder.projectName);\n        setBizId(builder.bizId);\n    }\n\n    public static final class Builder {\n        private OperateTypeEnum operateTypeEnum;\n        private TriggerWayEnum  triggerWayEnum;\n        private String          content;\n        private String          userOperation;\n\n        private String          projectName;\n        private String          bizId;\n\n        public Builder operationTypeEnum(OperateTypeEnum operationType) {\n            this.operateTypeEnum = operationType;\n            return this;\n        }\n\n        public Builder triggerWayEnum(TriggerWayEnum triggerWay) {\n            triggerWayEnum = triggerWay;\n            return this;\n        }\n\n        public Builder content(String content) {\n            this.content = content;\n            return this;\n        }\n\n        public Builder userOperation(String operation) {\n            userOperation = operation;\n            return this;\n        }\n\n        public Builder project(ProjectBriefVO project) {\n            this.projectName = Optional.ofNullable(project).map(ProjectBriefVO::getProjectName).orElse(null);\n            return this;\n        }\n\n        public Builder projectName(String project) {\n            this.projectName = project;\n            return this;\n        }\n\n        public Builder bizId(Object bizId) {\n            this.bizId = Optional.ofNullable(bizId).map(String::valueOf).orElse(null);\n            return this;\n        }\n\n        public OperateRecord build() {\n            return new OperateRecord(this);\n        }\n\n        public OperateRecord buildDefaultManualTrigger() {\n            this.triggerWayEnum = TriggerWayEnum.MANUAL_TRIGGER;\n            return new OperateRecord(this);\n        }\n\n        public OperateRecord buildDefaultSystemTrigger() {\n            this.triggerWayEnum = TriggerWayEnum.SYSTEM_TRIGGER;\n            return new OperateRecord(this);\n        }\n\n        public OperateRecord buildDefaultSchedulingTasks() {\n            this.triggerWayEnum = TriggerWayEnum.SCHEDULING_TASKS;\n            return new OperateRecord(this);\n        }\n\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/PaginationResult.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport io.swagger.annotations.ApiModel;\nimport lombok.Data;\n\nimport java.util.List;\n\n@Data\n@ApiModel(description = \"分页结果\")\npublic class PaginationResult<T> extends BaseResult {\n\n    protected PagingData<T> data;\n\n    @Override\n    public boolean isPagine() {\n        return true;\n    }\n\n    public PaginationResult() {\n    }\n\n    public PaginationResult(PagingData<T> data) {\n        this.data = data;\n    }\n\n    public PaginationResult(List<T> records, long total, long pageNo, long pageSize) {\n        this.data = new PagingData<>(records, total, pageNo, pageSize);\n    }\n\n    public static <T> PaginationResult<T> buildSucc() {\n        PaginationResult<T> result = new PaginationResult<>();\n        result.setCode(ResultType.SUCCESS.getCode());\n        result.setMessage(ResultType.SUCCESS.getMessage());\n        return result;\n    }\n\n    public static <T> PaginationResult<T> buildSucc(List<T> records, long total, long pageNo, long pageSize) {\n        PaginationResult<T> paginationResult = new PaginationResult<>(records, total, pageNo, pageSize);\n        paginationResult.setCode(ResultType.SUCCESS.getCode());\n        paginationResult.setMessage(ResultType.SUCCESS.getMessage());\n        return paginationResult;\n    }\n\n    public static <T> PaginationResult<T> buildFail(String failMsg) {\n        PaginationResult<T> result = new PaginationResult<>();\n        result.setCode(ResultType.FAIL.getCode());\n        result.setMessage(failMsg);\n        return result;\n    }\n\n    public static <T> PaginationResult<T> buildParamIllegal(String msg) {\n        PaginationResult<T> result = new PaginationResult<>();\n        result.setCode(ResultType.ILLEGAL_PARAMS.getCode());\n        result.setMessage(msg);\n        return result;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/PagingData.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n@Data\npublic class PagingData<T> implements Serializable {\n\n    private static final long serialVersionUID = -4498978062649547459L;\n    private List<T>           bizData;\n\n    private Pagination        pagination;\n\n    public PagingData(List<T> bizData, long total, long pageNo, long pageSize) {\n        this.bizData = bizData;\n        this.pagination = new Pagination(total, pageNo, pageSize);\n    }\n\n    @Data\n    public static class Pagination implements Serializable {\n\n        private static final long serialVersionUID = 1037592182089929607L;\n        private long              total;\n        private long              pageNo;\n        private long              pageSize;\n\n        public Pagination(long total, long pageNo, long pageSize) {\n            this.total = total;\n            this.pageNo = pageNo;\n            this.pageSize = pageSize;\n        }\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/PhysicalTemplateTpsMetric.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport javax.annotation.Nullable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-06-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class PhysicalTemplateTpsMetric {\n\n    /**\n     * 历史每小时tps峰值 单位 条/s\n     * 是取各个物理模板最大值\n     */\n    private Double maxTps;\n\n    /**\n     * 每个物理模板，最近15分钟平均值 单位 条/s\n     *\n     */\n    private Double currentTps;\n\n    /**\n     * 当前写入失败的格式\n     * 这个值只针对ingestPipeline写入的有效；当有值的时候，表示模板被限流了\n     */\n    @Nullable\n    private Double currentFailCount;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/Plugin.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.springframework.web.multipart.MultipartFile;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Plugin {\n    /**\n     * ID主键自增\n     */\n    private Long          id;\n\n    /**\n     * 插件名\n     */\n    private String        name;\n\n    /**\n     * 物理集群Id\n     */\n    private String        physicClusterId;\n\n    /**\n     * 插件版本\n     */\n    private String        version;\n\n    /**\n     * 插件存储地址\n     */\n    private String        url;\n\n    /**\n     * 插件文件md5\n     */\n    private String        md5;\n\n    /**\n     * 插件描述\n     */\n    private String        desc;\n\n    /**\n     * 插件创建人\n     */\n    private String        creator;\n\n    /**\n     * 上传的文件名\n     */\n    private String        fileName;\n\n    /**\n     * 上传的文件\n     */\n    private MultipartFile uploadFile;\n\n    /**\n     * 插件文件类型 0 系统默认插件, 1 ES能力插件, 2 平台能力插件\n     */\n    private Integer       pDefault;\n\n    /**\n     * 是否安装\n     */\n    private Boolean       installed;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/Result.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\n\n/**\n * Service服务执行的结果\n @author ohushenglin_v\n @date 2022-05-10\n */\n@ApiModel(description = \"返回结构\")\npublic class Result<T> extends BaseResult {\n\n    @ApiModelProperty(\"内容\")\n    protected T data;\n\n    public T getData() {\n        return data;\n    }\n\n    public void setData(T data) {\n        this.data = data;\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n    public static <T> Result<T> build(ResultType resultType) {\n        Result<T> result = new Result<>();\n        result.setCode(resultType.getCode());\n        result.setMessage(resultType.getMessage());\n        return result;\n    }\n\n    public static <T> Result<T> build(int code, String msg) {\n        Result<T> result = new Result<>();\n        result.setCode(code);\n        result.setMessage(msg);\n        return result;\n    }\n\n    public static <T> Result<T> buildSucc() {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.SUCCESS.getCode());\n        result.setMessage(ResultType.SUCCESS.getMessage());\n        return result;\n    }\n\n    public static <T> Result<T> buildSucWithTips(String tips) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.SUCCESS.getCode());\n        result.setMessage(ResultType.SUCCESS.getMessage());\n        result.setTips(tips);\n        return result;\n    }\n\n    public static <T> Result<T> buildFail(String failMsg) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.FAIL.getCode());\n        result.setMessage(failMsg);\n        return result;\n    }\n\n    public static <T> Result<T> buildFail(T data) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.FAIL.getCode());\n        result.setMessage(ResultType.FAIL.getMessage());\n        result.setData(data);\n        return result;\n    }\n\n    public static <T> Result<T> buildFailWithMsg(T data, String failMsg) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.FAIL.getCode());\n        result.setMessage(failMsg);\n        result.setData(data);\n        return result;\n    }\n\n    public static <T> Result<T> buildFail() {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.FAIL.getCode());\n        result.setMessage(ResultType.FAIL.getMessage());\n        return result;\n    }\n\n    public static Result<Boolean> buildBoolen(boolean succ) {\n        if (succ) {\n            return buildSucc(succ);\n        }\n        return buildFail();\n    }\n\n    public static <T> Result<T> build(boolean succ) {\n        if (succ) {\n            return buildSucc();\n        }\n        return buildFail();\n    }\n\n    public static <T> Result<T> buildWithTips(boolean succ, String tips) {\n        if (succ) {\n            return buildSucWithTips(tips);\n        }\n        return buildFail();\n    }\n\n    public static <T> Result<T> buildParamIllegal(String msg) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.ILLEGAL_PARAMS.getCode());\n        result.setMessage(ResultType.ILLEGAL_PARAMS.getMessage() + \":\" + msg + \"，请检查后再提交！\");\n        return result;\n    }\n\n    public static <T> Result<T> buildDuplicate(String msg) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.DUPLICATION.getCode());\n        result.setMessage(msg);\n        return result;\n    }\n\n    public static <T> Result<T> buildNotExist(String msg) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.NOT_EXIST.getCode());\n        result.setMessage(msg);\n        return result;\n    }\n\n    public static <T> Result<T> buildOpForBidden(String msg) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.OPERATE_FORBIDDEN_ERROR.getCode());\n        result.setMessage(msg);\n        return result;\n    }\n\n    public static <T> Result<T> build(boolean succ, T data) {\n        Result<T> result = new Result<>();\n        if (succ) {\n            result.setCode(ResultType.SUCCESS.getCode());\n            result.setMessage(ResultType.SUCCESS.getMessage());\n            result.setData(data);\n        } else {\n            result.setCode(ResultType.FAIL.getCode());\n            result.setMessage(ResultType.FAIL.getMessage());\n        }\n        return result;\n    }\n\n    public static <T> Result<T> buildWithMsg(boolean succ, String msg) {\n        Result<T> result = new Result<>();\n        if (succ) {\n            result.setCode(ResultType.SUCCESS.getCode());\n            result.setMessage(msg);\n        } else {\n            result.setCode(ResultType.FAIL.getCode());\n            result.setMessage(msg);\n        }\n        return result;\n    }\n\n    public static <T> Result<T> buildSucc(T data) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.SUCCESS.getCode());\n        result.setMessage(ResultType.SUCCESS.getMessage());\n        result.setData(data);\n        return result;\n    }\n\n    public static <T> Result<T> buildSuccWithMsg(String msg) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.SUCCESS.getCode());\n        result.setMessage(msg);\n        return result;\n    }\n\n    public static <T> Result<T> buildSucc(T data, String msg) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.SUCCESS.getCode());\n        result.setData(data);\n        result.setMessage(msg);\n        return result;\n    }\n\n    public static <T> Result<T> buildSuccWithTips(T data, String tips) {\n        Result<T> result = new Result<>();\n        result.setCode(ResultType.SUCCESS.getCode());\n        result.setMessage(ResultType.SUCCESS.getMessage());\n        result.setData(data);\n        result.setTips(tips);\n        return result;\n    }\n\n    public static <T> Result<T> buildFrom(Result<? extends Object> result) {\n        Result<T> resultT = new Result<>();\n        resultT.setCode(result.getCode());\n        resultT.setMessage(result.getMessage());\n        return resultT;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ResultWorkOrder.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport java.io.Serializable;\n\n/**\n * Service服务执行的结果\n * @author d06679\n * @date 2019/3/22\n */\npublic class ResultWorkOrder implements Serializable {\n\n    private static final long serialVersionUID = 3472961240718956029L;\n\n    private String            errorMsg;\n    private Integer           errCode;\n\n    public ResultWorkOrder(String errorMsg, Integer errCode) {\n        this.errorMsg = errorMsg;\n        this.errCode = errCode;\n    }\n\n    public String getErrorMsg() {\n        return errorMsg;\n    }\n\n    public void setErrorMsg(String errorMsg) {\n        this.errorMsg = errorMsg;\n    }\n\n    public Integer getErrCode() {\n        return errCode;\n    }\n\n    public void setErrCode(Integer errCode) {\n        this.errCode = errCode;\n    }\n\n    public static <T> ResultWorkOrder build(Result<T> result) {\n        return new ResultWorkOrder(result.getMessage(), result.getCode());\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/TemplateLabel.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport java.util.List;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/5/20\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateLabel {\n\n    private Integer     indexTemplateId;\n\n    private List<Label> labels;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/TemplateMetaMetric.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport java.util.Date;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-06-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateMetaMetric {\n\n    /***************************************** admin指标 ****************************************************/\n\n    /**\n     * 物理模板id\n     */\n    private Long    physicalId;\n\n    /**\n     * 集群\n     */\n    private String  cluster;\n\n    /**\n     * 模板名字\n     */\n    private String  templateName;\n\n    /**\n     * 模板Quota\n     */\n    private Double  quota;\n\n    /**\n     * 数据保存时长\n     */\n    private Integer expireTime;\n\n    /**\n     * shard个数\n     */\n    private Integer shardNum;\n\n    /**\n     * 模板创建时间\n     */\n    private Date    createTime;\n\n    /**\n     * 时间后缀\n     */\n    private String  dateFormat;\n\n    /**\n     * 表达式\n     */\n    private String  expression;\n\n    /**\n     * 副本个数\n     */\n    private Integer replicaNum;\n\n    /**\n     * 热数据的天数\n     */\n    private Integer hotTime;\n\n    /***************************************** AMS指标 ****************************************************/\n\n    /**\n     * 模板总的磁盘消耗  单位G\n     */\n    private Double  sumIndexSizeG;\n\n    /**\n     * 模板最大的索引磁盘消耗  单位G\n     */\n    private Double  maxIndexSizeG;\n\n    /**\n     * 总条数\n     */\n    private Long    sumDocCount;\n\n    /**\n     * 模板最大的索引的文档个数\n     */\n    private Long    maxIndexDocCount;\n\n    /**\n     * tps峰值 单位 条/s\n     */\n    private Double  maxTps;\n\n    /**\n     * 查询的峰值\n     */\n    private Double  maxQueryTime;\n\n    /**\n     * scroll的峰值\n     */\n    private Double  maxScrollTime;\n\n    /***************************************** 计算指标 ****************************************************/\n\n    /**\n     * 实际的磁盘消耗\n     */\n    private Double  actualDiskG;\n\n    /**\n     * 实际的CPU消耗\n     */\n    private Double  actualCpuCount;\n\n    /**\n     * Quota的磁盘消耗\n     */\n    private Double  quotaDiskG;\n\n    /**\n     * Quota的CPU消耗\n     */\n    private Double  quotaCpuCount;\n\n    /**\n     * 综合的磁盘消耗\n     */\n    private Double  combinedDiskG;\n\n    /**\n     * 综合的CPU消耗\n     */\n    private Double  combinedCpuCount;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/TemplateMetric.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-06-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateMetric {\n\n    /**\n     * 集群\n     */\n    private String cluster;\n\n    /**\n     * 模板名字\n     */\n    private String template;\n\n    /***************************************** AMS指标 ****************************************************/\n\n    /**\n     * 模板总的磁盘消耗  单位G\n     */\n    private Double sumIndexSizeG;\n\n    /**\n     * 模板最大的索引磁盘消耗  单位G\n     */\n    private Double maxIndexSizeG;\n\n    /**\n     * 总条数\n     */\n    private Long   sumDocCount;\n\n    /**\n     * 模板最大的索引的文档个数\n     */\n    private Long   maxIndexDocCount;\n\n    /**\n     * tps峰值 单位 W/s\n     */\n    private Double maxTps;\n\n    /**\n     * 查询的峰值 ms\n     */\n    private Double maxQueryTime;\n\n    /**\n     * scroll的峰值 ms\n     */\n    private Double maxScrollTime;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/TemplateResourceConfig.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common;\n\nimport lombok.Data;\n\n/**\n * @author d06679\n * @date 2019-06-25\n */\n@Data\npublic class TemplateResourceConfig {\n\n    /**\n     * 文档大小的基准 单位：KB\n     */\n    private Double docSizeBaseline = 1.0;\n\n    /**\n     * 每个CPU的tps能力 单位：条/s\n     */\n    private Double tpsPerCpu       = 2300.0;\n\n    /**\n     * 每个CPU的查询能力  单位：ms\n     */\n    private Double queryTimePerCpu = 1000.0;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/ESClusterRoleDocker.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterRoleDocker implements Serializable {\n    /**\n     * 集群角色(masternode/datanode/clientnode)\n     */\n    private String  role;\n\n    /**\n     * pod数量\n     */\n    private Integer podNumber;\n\n    /**\n     * 单机实例数\n     */\n    private Integer pidCount;\n\n    /**\n     * 机器规格\n     */\n    private String  machineSpec;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/ESClusterRoleHost.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm;\n\nimport java.io.Serializable;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ESClusterRoleHost implements Serializable {\n\n    /**\n     * ip:port 主機名:port = hostname:port\n     */\n    private String  address;\n\n    /**\n     * 角色名称\n     */\n    private String  role;\n\n    /**\n     * 主機名\n     */\n    private String  hostname;\n\n    /**\n     * IP\n     */\n    private String  ip;\n\n    /**\n     * 端口号\n     */\n    private String  port;\n\n    /**\n     * 冷热节点标识\n     */\n    private Boolean beCold;\n\n    /**\n     * 机器规格 例如32C-64G-SSD-6T\n     */\n    private String  machineSpec;\n\n    /**\n     * regionId\n     */\n    private Integer regionId;\n\n    /**\n     * attributes, 逗号分隔  key1:value1,key2:value2\n     */\n    private String  attributes;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/ESResponsePluginInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ESResponsePluginInfo {\n    /**\n     * name 物理节点的名称\n     */\n    private String name;\n\n    /**\n     * component 插件组成名称\n     */\n    private String component;\n\n    /**\n     * version 插件的版本\n     */\n    private String version;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/EcmParamBase.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm;\n\nimport com.alibaba.fastjson.annotation.JSONType;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@JSONType(serialzeFeatures = { SerializerFeature.WriteClassName })\npublic class EcmParamBase implements Serializable {\n    /**\n     * 工单Id\n     */\n    protected Long    workOrderId;\n\n    /**\n     * 集群ID\n     */\n    protected Long    phyClusterId;\n\n    /**\n     * 集群名字\n     */\n    protected String  phyClusterName;\n\n    /**\n     * 角色名称\n     */\n    protected String  roleName;\n\n    /**\n     * 集群类型(3：容器云集群；4：物理机集群 ）)\n     * @see ESClusterTypeEnum\n     */\n    protected Integer type;\n\n    /**\n     * 任务ID\n     */\n    protected Integer taskId;\n\n    /**\n     * 节点数(pod数量)\n     */\n    protected Integer nodeNumber;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/EcmTaskBasic.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Date;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class EcmTaskBasic {\n    /**\n     * ID主键自增\n     */\n    private Long    id;\n\n    /**\n     * 标题\n     */\n    private String  title;\n\n    /**\n     * 工单ID\n     */\n    private Long    workOrderId;\n\n    /**\n     * es版本\n     */\n    private String  esVersion;\n\n    /**\n     * 镜像名\n     */\n    private String  imageName;\n\n    /**\n     * 集群名称\n     */\n    private String  clusterName;\n\n    /**\n     * 集群描述\n     */\n    private String  desc;\n\n    /**\n     * 服务节点\n     */\n    private String  nsTree;\n\n    /**\n     * 机房\n     */\n    private String  idc;\n\n    /**\n     * 成本部门\n     */\n    private String  dept;\n\n    /**\n     * 集群节点角色\n     */\n    private String  clusterNodeRole;\n\n    /**\n     * 状态\n     */\n    private String  status;\n\n    /**\n     * 类型  docker容器云/host 物理机\n     */\n    private Integer type;\n\n    /**\n     * 类型  1 集群新增  2 集群扩容 3 集群缩容 4 集群重启 5 集群升级\n     */\n    private Integer orderType;\n\n    /**\n     * 创建人\n     */\n    private String  creator;\n\n    /**\n     * 开始时间\n     */\n    private Date    createTime;\n\n    /**\n     * 结束时间\n     */\n    private Date    updateTime;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/EcmTaskDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmTaskStatusEnum;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Date;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class EcmTaskDetail {\n    /**\n     * ID主键自增\n     */\n    private Long    id;\n\n    /**\n     *  工单任务ID\n     */\n    private Long    workOrderTaskId;\n\n    /**\n     * 角色\n     */\n    private String  role;\n\n    /**\n     * 节点名称/主机名称\n     */\n    private String  hostname;\n\n    /**\n     * 分组\n     */\n    private Integer grp;\n    /**\n     * 顺序\n     */\n    private Integer idx;\n\n    /**\n     * 状态\n     * @see EcmTaskStatusEnum\n     */\n    private String  status;\n\n    /**\n     * 容器云/物理机 接口返回任务ID\n     */\n    @ApiModelProperty(\"容器云/物理机 接口返回任务ID\")\n    private Long    taskId;\n\n    /**\n     * 创建时间\n     */\n    private Date    createTime;\n\n    /**\n     * 更新时间\n     */\n    private Date    updateTime;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/EcmTaskDetailProgress.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm;\n\nimport com.google.common.collect.Maps;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.*;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class EcmTaskDetailProgress {\n    /**\n     * 执行进度\n     */\n    private Long                             percent;\n\n    /**\n     * 成功的节点个数\n     */\n    private Long                             success;\n\n    /**\n     * 失败的节点个数\n     */\n    private Long                             failed;\n\n    /**\n     * 执行中的节点个数\n     */\n    private Long                             creating;\n\n    /**\n     * 等待中的节点个数\n     */\n    private Long                             waiting;\n\n    /**\n     * 忽略的节点个数\n     */\n    private Long                             ignore;\n\n    /**\n     * 取消的节点个数\n     */\n    private Long                             cancel;\n\n    /**\n     * 节点总个数\n     */\n    private Long                             sum;\n\n    /**\n     * 任务状态\n     */\n    @ApiModelProperty(\"任务状态\")\n    private String                           status;\n\n    /**\n     * 工单类型\n     */\n    @ApiModelProperty(\"工单类型  1 集群新增  2 集群扩容 3 集群缩容 4 集群重启 5 集群升级\")\n    private Integer                          orderType;\n\n    /**\n     * 全部节点\n     */\n    private Map<String, List<EcmTaskDetail>> roleNameTaskDetailMap;\n\n    public Long updatePercent() {\n        if (this.sum == null || this.sum.equals(0L)) {\n            this.percent = null;\n            return this.percent;\n        }\n\n        Long finished = 0L;\n        if (this.failed != null) {\n            finished += this.failed;\n        }\n        if (this.success != null) {\n            finished += this.success;\n        }\n        if (this.ignore != null) {\n            finished += this.ignore;\n        }\n\n        this.percent = finished * 10000 / this.sum;\n        return this.percent;\n    }\n\n    public static EcmTaskDetailProgress newFieldInitializedInstance() {\n        EcmTaskDetailProgress ecmTaskDetailProgress = new EcmTaskDetailProgress();\n        ecmTaskDetailProgress.setPercent(0L);\n        ecmTaskDetailProgress.setSuccess(0L);\n        ecmTaskDetailProgress.setFailed(0L);\n        ecmTaskDetailProgress.setCreating(0L);\n        ecmTaskDetailProgress.setWaiting(0L);\n        ecmTaskDetailProgress.setIgnore(0L);\n        ecmTaskDetailProgress.setCancel(0L);\n        ecmTaskDetailProgress.setSum(0L);\n        ecmTaskDetailProgress.setStatus(\"\");\n        ecmTaskDetailProgress.setOrderType(null);\n        ecmTaskDetailProgress.setRoleNameTaskDetailMap(Maps.newHashMap());\n        return ecmTaskDetailProgress;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/EsConfigAction.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * @author lyn\n * @date 2021-01-21\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class EsConfigAction implements Serializable {\n\n    /**\n     * 配置操作类型\n     * @see EsConfigActionEnum\n     */\n    private Integer    actionType;\n\n    /**\n     * actionType = ADD、EDIT 时，表示的是变更之后的配置id, actionType = DELETE 时， 表示的是需要删除的配置id\n     */\n    private List<Long> actionEsConfigIds;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/EsPluginAction.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class EsPluginAction implements Serializable {\n\n    /**\n     * plugin操作类型\n     */\n    private Integer actionType;\n\n    /**\n     * 无效Es集群配置id\n     */\n    private Long    pluginId;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/elasticcloud/ElasticCloudCommonActionParam.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud;\n\nimport com.alibaba.fastjson.annotation.JSONType;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EsConfigAction;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EsPluginAction;\nimport lombok.Data;\n\n@Data\n@JSONType(serialzeFeatures = { SerializerFeature.WriteClassName })\npublic class ElasticCloudCommonActionParam extends EcmParamBase {\n    protected String         nsTree;\n\n    protected String         machineRoom;\n\n    protected String         imageName;\n\n    protected String         esVersion;\n\n    protected EsConfigAction esConfigActions;\n\n    protected EsPluginAction esPluginAction;\n\n    public ElasticCloudCommonActionParam() {\n    }\n\n    public ElasticCloudCommonActionParam(Long clusterId, String roleName) {\n        this.phyClusterId = clusterId;\n        this.roleName = roleName;\n    }\n\n    public String namespace() {\n        return String.format(\"%s.%s.%s\", this.roleName, this.phyClusterName, this.nsTree);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/elasticcloud/ElasticCloudCreateActionParam.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud;\n\nimport com.alibaba.fastjson.annotation.JSONType;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ResourceLogicLevelEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@JSONType(serialzeFeatures = { SerializerFeature.WriteClassName })\npublic class ElasticCloudCreateActionParam extends EcmParamBase {\n    /**\n     * 机器规格\n     */\n    private String   machineSpec;\n\n    /**\n     * role信息\n     */\n    private Long     roleId;\n\n    private String   roleClusterName;\n\n    private Integer  podNum;\n\n    /**\n     * 数据中心\n     */\n    protected String dataCenter;\n\n    /**\n     * 机器节点\n     */\n    protected String nsTree;\n\n    /**\n     * 机房\n     */\n    protected String idc;\n\n    /**\n     * es版本\n     */\n    protected String esVersion;\n\n    /**\n     * 插件包ID列表\n     */\n    protected String plugs;\n\n    /**\n     * 集群创建人\n     */\n    protected String creator;\n\n    /**\n     * 描述\n     */\n    protected String desc;\n\n    /**\n     * 镜像地址\n     */\n    protected String imageName;\n\n    /**\n     * 服务等级\n     * @see ResourceLogicLevelEnum\n     */\n    private Integer  level;\n\n    public Result<Void> validateFiledIllegal() {\n        if (StringUtils.isBlank(this.phyClusterName)) {\n            return Result.buildParamIllegal(\"集群名称为空\");\n        }\n        if (null == this.type) {\n            return Result.buildParamIllegal(\"集群类型为空\");\n        }\n        if (StringUtils.isBlank(this.dataCenter)) {\n            return Result.buildParamIllegal(\"数据中心为空\");\n        }\n        if (StringUtils.isBlank(this.idc)) {\n            return Result.buildParamIllegal(\"机房名称为空\");\n        }\n        if (StringUtils.isBlank(this.esVersion)) {\n            return Result.buildParamIllegal(\"ES版本为空\");\n        }\n        return Result.buildSucc();\n    }\n\n    public String namespace() {\n        return String.format(\"%s.%s.%s\", this.roleName, this.phyClusterName, this.nsTree);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/elasticcloud/ElasticCloudScaleActionParam.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud;\n\nimport com.alibaba.fastjson.annotation.JSONType;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author zengqiao\n * @date 20/10/20\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@JSONType(serialzeFeatures = { SerializerFeature.WriteClassName })\npublic class ElasticCloudScaleActionParam extends ElasticCloudCommonActionParam {\n    private Integer podNum;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/host/HostCreateActionParam.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport com.alibaba.fastjson.annotation.JSONType;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ResourceLogicLevelEnum;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@JSONType(serialzeFeatures = { SerializerFeature.WriteClassName })\npublic class HostCreateActionParam extends HostParamBase {\n\n    /**\n     * 机器规格\n     */\n    private String   machineSpec;\n\n    /**\n     * 数据中心\n     */\n    protected String dataCenter;\n\n    /**\n     * 机器节点\n     */\n    protected String nsTree;\n\n    /**\n     * 机房\n     */\n    protected String idc;\n\n    /**\n     * 插件包ID列表\n     */\n    protected String plugs;\n\n    /**\n     * 集群创建人\n     */\n    protected String creator;\n\n    /**\n     * 描述\n     */\n    protected String desc;\n\n    /**\n     * 服务等级\n     * @see ResourceLogicLevelEnum\n     */\n    private Integer  level;\n\n    private String   platformType;\n\n    /**\n     * @see ClusterResourceTypeEnum\n     */\n    private Integer  resourceType;\n\n    public Result<Void> validateFiledIllegal() {\n        if (StringUtils.isBlank(this.phyClusterName)) {\n            return Result.buildParamIllegal(\"集群名称为空\");\n        }\n        if (null == this.type) {\n            return Result.buildParamIllegal(\"集群类型为空\");\n        }\n        if (StringUtils.isBlank(this.esVersion)) {\n            return Result.buildParamIllegal(\"ES版本为空\");\n        }\n        return Result.buildSucc();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/host/HostParamBase.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host;\n\nimport com.alibaba.fastjson.annotation.JSONType;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EsConfigAction;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EsPluginAction;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@JSONType(serialzeFeatures = { SerializerFeature.WriteClassName })\npublic class HostParamBase extends EcmParamBase {\n    /**\n     * 版本包地址\n     */\n    protected String         imageName;\n\n    /**\n     * 版本\n     */\n    protected String         esVersion;\n\n    /**\n     * 单节点实例数\n     */\n    protected Integer        pidCount;\n\n    /**\n     * Es集群配置相关\n     */\n    protected EsConfigAction esConfigAction;\n\n    /**\n     * Es集群plugin相关\n     */\n    protected EsPluginAction esPluginAction;\n\n    /**\n     * 主机列表\n     */\n    protected List<String>   hostList;\n\n    /**\n     * 端口号, 同一ES实例角色的端口号相同\n     */\n    protected String         port;\n\n    /**\n     * master主机列表\n     */\n    protected List<String>   masterHostList;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/host/HostScaleActionParam.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host;\n\nimport com.alibaba.fastjson.annotation.JSONType;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author zengqiao\n * @date 20/10/20\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@JSONType(serialzeFeatures = { SerializerFeature.WriteClassName })\npublic class HostScaleActionParam extends HostParamBase {\n    private String action;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/response/EcmCreateApp.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response;\n\nimport lombok.Data;\n\nimport java.util.List;\n\n@Data\npublic class EcmCreateApp extends EcmOperateAppBase {\n    private List<String> hostList;\n\n    public EcmCreateApp(Integer taskId, List<String> hostList) {\n        this.taskId = taskId;\n        this.hostList = hostList;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/response/EcmOperateAppBase.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport lombok.Data;\n\n/**\n * @author zengqiao\n * @date 20/10/29\n */\n@Data\npublic class EcmOperateAppBase extends BaseDTO {\n    protected Integer taskId;\n\n    public EcmOperateAppBase() {\n    }\n\n    public EcmOperateAppBase(Integer taskId) {\n        this.taskId = taskId;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/response/EcmSubTaskLog.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author zengqiao\n * @date 20/10/19\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class EcmSubTaskLog {\n    private String agent;\n\n    private String user;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/common/ecm/response/EcmTaskStatus.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmHostStatusEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * ES集群状态信息\n * @author didi\n * @date 2020/10/17\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class EcmTaskStatus implements Serializable {\n    /**\n     * 主机名或IP\n     */\n    private String            hostname;\n\n    /**\n     * 容器云/物理机 接口返回任务ID\n     */\n    private Integer           taskId;\n\n    /**\n     * pod分组\n     */\n    private Integer           group;\n\n    /**\n     * pod index\n     */\n    private Integer           podIndex;\n\n    /**\n     * pod IP\n     */\n    private String            podIp;\n\n    /**\n     * 主机状态\n     */\n    private EcmHostStatusEnum statusEnum;\n\n    /**\n     * 创建时间\n     */\n    private Date              createTime;\n\n    /**\n     * 修改时间\n     */\n    private Date              updateTime;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/BaseDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto;\n\nimport java.io.Serializable;\n\n/**\n * @author didi\n * @date 2019/3/13\n */\npublic class BaseDTO implements Serializable {\n    private static final long serialVersionUID = 7861489615519826338L;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/PageDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/29\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"分页实体\")\npublic class PageDTO extends BaseDTO {\n    @ApiModelProperty(\"起始页码 前端需求默认第一页的页码是1而不是0\")\n    private Long page;\n\n    @ApiModelProperty(\"当前页数量\")\n    private Long size;\n\n    @ApiModelProperty(\"查询数据开始下标，自动计算\")\n    private Long from;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/README.md",
    "content": "dto包中的bean是用来接收rest请求(新建、编辑等)参数使用;\n命名规则: xxxDTO\n必须继承基类:BaseDTO"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/app/ConsoleESUserDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.app;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n *\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"es user 信息\")\npublic class ConsoleESUserDTO extends BaseDTO {\n\n    @ApiModelProperty(\"es user\")\n    private Integer id;\n\n    @ApiModelProperty(\"备注\")\n    private String  memo;\n\n    @ApiModelProperty(\"数据中心\")\n    private String  dataCenter;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/app/ESUserDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.app;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n *\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"es user 信息\")\npublic class ESUserDTO extends BaseDTO {\n\n    @ApiModelProperty(\"es user name\")\n    private Integer id;\n\n    @ApiModelProperty(\"root用户\")\n    private Integer isRoot = 0;\n\n    @ApiModelProperty(\"验证码\")\n    private String  verifyCode;\n\n    @ApiModelProperty(\"备注\")\n    private String  memo;\n\n    @ApiModelProperty(\"删除标记（1:正常；0：删除）\")\n    private Integer isActive;\n\n    @ApiModelProperty(\"限流值\")\n    private Integer queryThreshold;\n\n    @ApiModelProperty(\"查询集群\")\n    private String  cluster;\n\n    @ApiModelProperty(\"查询模式（0:集群模式；1:索引模式）\")\n    private Integer searchType;\n\n    @ApiModelProperty(\"数据中心\")\n    private String  dataCenter;\n\n    @ApiModelProperty(\"项目id\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"项目默认使用的es user\")\n    private Boolean defaultDisplay;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/app/ProjectConfigDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.app;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"应用配置信息\")\npublic class ProjectConfigDTO extends BaseDTO {\n\n    @ApiModelProperty(value = \"项目id(更新操作必填)\", dataType = \"projectId\", hidden = true, required = false)\n    private Integer projectId;\n\n    @ApiModelProperty(\"gateway返回结果解析开关\")\n    private Integer analyzeResponseEnable;\n\n    @ApiModelProperty(\"是否生效DSL分析查询限流值 1为生效DSL分析查询限流值，0不生效DSL分析查询限流值\")\n    private Integer dslAnalyzeEnable;\n\n    @ApiModelProperty(\"是否开启聚合分析  1 开启  0 不开启  默认为 1\")\n    private Integer aggrAnalyzeEnable;\n\n    @ApiModelProperty(\"是否索引存储分离，1为分离，0为不分离，默认为0\")\n    private Integer isSourceSeparated;\n    /**\n     * 慢查询时间\n     */\n    @ApiModelProperty(\"慢查询耗时：ms\")\n\n    private Integer slowQueryTimes;\n    @ApiModelProperty(\"备注\")\n    private String  memo;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/app/ProjectExtendSaveDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.app;\n\nimport com.didiglobal.knowframework.security.common.dto.project.ProjectSaveDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 项目扩展dto：包含Logi中projectSaveDto和knowsearch中的projectConfigDto\n *\n * @author shizeying\n * @date 2022/06/10\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"项目保存dto\")\npublic class ProjectExtendSaveDTO {\n    @ApiModelProperty(value = \"项目\", dataType = \"ProjectSaveDTO\", required = false)\n    private ProjectSaveDTO   project;\n    @ApiModelProperty(value = \"项目配置\", dataType = \"ProjectSaveDTO\", required = false)\n    private ProjectConfigDTO config;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/app/ProjectLogicClusterAuthDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.app;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/4/16\n */\n@Data\n@ApiModel(description = \"应用逻辑集群权限信息\")\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ProjectLogicClusterAuthDTO extends BaseDTO {\n\n    @ApiModelProperty(\"ID\")\n    private Long    id;\n\n    @ApiModelProperty(\"应用ID\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"逻辑集群ID\")\n    private Long    logicClusterId;\n\n    /**\n     * @see ProjectClusterLogicAuthEnum\n     */\n    @ApiModelProperty(\"权限类型，0：超管权限，1：配置管理权限，2：访问权限\")\n    private Integer type;\n\n    \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/app/ProjectQueryExtendDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.app;\n\nimport com.didiglobal.knowframework.security.common.dto.project.ProjectQueryDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n\n/**\n * 项目查询扩展dto\n *\n * @author shizeying\n * @date 2022/06/13\n */\n@EqualsAndHashCode(callSuper = true)\n@Data\n@ApiModel(description = \"项目查找条件扩展信息\")\npublic class ProjectQueryExtendDTO extends ProjectQueryDTO {\n    @ApiModelProperty(value = \"查询模式（0:集群模式；1:索引模式）\", dataType = \"Integer\", required = false)\n    private Integer searchType;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/app/ProjectTemplateAuthDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.app;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/4/16\n */\n@Data\n@ApiModel(description = \"应用权限信息\")\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ProjectTemplateAuthDTO extends BaseDTO {\n\n    @ApiModelProperty(\"ID\")\n    private Long    id;\n\n    @ApiModelProperty(\"应用ID\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"模板ID\")\n    private Integer templateId;\n\n    /**\n     * @see ProjectTemplateAuthEnum\n     */\n    @ApiModelProperty(\"权限类型（1:管理；2:读写；3:读）\")\n    private Integer type;\n\n    \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/app/UserExtendDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.app;\n\nimport com.didiglobal.knowframework.security.common.dto.user.UserDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n\n@EqualsAndHashCode(callSuper = false)\n@Data\n@ApiModel(description = \"用户信息\")\npublic class UserExtendDTO extends UserDTO {\n\t@ApiModelProperty(value = \"用户旧密码\", dataType = \"Integer\", required = false)\n    private String  oldPw;\n\t@ApiModelProperty(value = \"忽略密码比对\", dataType = \"boolean\", hidden = true)\n\tprivate boolean ignorePasswordMatching = false;\n\t\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/app/UserQueryExtendDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.app;\n\nimport com.didiglobal.knowframework.security.common.dto.user.UserQueryDTO;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class UserQueryExtendDTO extends UserQueryDTO {\n    @ApiModelProperty(value = \"是否包含管理员角色的用户\", dataType = \"Integer\", required = false)\n    private Boolean containsAdminRole = true;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterJoinDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author linyunan\n * @date 2021-03-18\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterJoinDTO extends BaseDTO {\n\n    /**\n     * @see ESClusterTypeEnum\n     */\n    @ApiModelProperty(\"集群类型(-1 未知 3 docker集群 4 host集群 5 VM集群)\")\n    private Integer                    type;\n\n    @ApiModelProperty(\"所属项目id\")\n    private Integer                    projectId;\n\n    @ApiModelProperty(\"集群名字\")\n    private String                     cluster;\n\n    \n\n    @ApiModelProperty(\"es版本\")\n    private String                     esVersion;\n\n    @ApiModelProperty(\"集群角色 对应主机列表\")\n    private List<ESClusterRoleHostDTO> roleClusterHosts;\n\n    @ApiModelProperty(\"描述\")\n    private String                     phyClusterDesc;\n\n    @ApiModelProperty(\"集群认证信息：'user:password'\")\n    private String                     password;\n\n    @ApiModelProperty(\"录入规则 0 自动获取 1 全量录入\")\n    private Integer                    importRule;\n\n    @ApiModelProperty(\"集群展示用属性标签，如「集群所属资源类型」等等\")\n    private String                     tags;\n\n    @ApiModelProperty(\"数据中心\")\n    private String                     dataCenter;\n\n    @ApiModelProperty(\"IaaS平台类型\")\n    private String                     platformType;\n\n    @ApiModelProperty(\"集群资源类型(-1 未知 1 共享 2 独立 3 独享)\")\n    private Integer                    resourceType;\n\n    @ApiModelProperty(\"kibana外链地址\")\n    private String                    kibanaAddress;\n\n    @ApiModelProperty(\"cerebro外链地址\")\n    private String                    cerebroAddress;\n\n    @ApiModelProperty(\"http地址-读\")\n    private String                     httpAddress;\n\n    @ApiModelProperty(\"http地址-写\")\n    private String                     httpWriteAddress;\n\n    @ApiModelProperty(\"代理地址\")\n    private String                     proxyAddress;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterLogicConditionDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 2021-10-14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"逻辑集群条件查询信息\")\npublic class ClusterLogicConditionDTO extends ESLogicClusterDTO {\n    /**\n     * @see ProjectClusterLogicAuthEnum\n     */\n    @ApiModelProperty(\"权限类型 1:配置管理, 2:访问, -1:无权限\")\n    private Integer      authType;\n\n    @ApiModelProperty(\"排序字段，type，disk_usage_percent,es_cluster_version,data_node_num\")\n    private String       sortTerm;\n\n    @ApiModelProperty(\"DESC,ASC\")\n    private String       sortType;\n\n    @ApiModelProperty(value = \"是否降序排序（默认降序）\", dataType = \"Boolean\", required = false)\n    private Boolean      orderByDesc = true;\n\n    @ApiModelProperty(\"集群名称，用于后端根据项目筛选\")\n    private List<String> clusterNames;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterLogicNodeConditionDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 2021-10-14\n * @author gyp\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"逻辑集群节点详情条件查询信息\")\npublic class ClusterLogicNodeConditionDTO extends PageDTO {\n\n    @ApiModelProperty(\"关键字\")\n    private String  keyword;\n\n    @ApiModelProperty(\"暂无\")\n    private String  sortTerm;\n\n    private String  sortType;\n\n    @ApiModelProperty(value = \"是否降序排序（默认降序）\", dataType = \"Boolean\")\n    private Boolean orderByDesc = true;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterLogicSpecCondition.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @Authoer: zyl\n * @Date: 2022/11/15\n * @Version: 1.0\n */\n@Data\n@Builder()\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"逻辑集群规格信息\")\npublic class ClusterLogicSpecCondition {\n\n    /**\n     * 节点数\n     */\n    private Integer hostNum;\n\n    /**\n     * 机器规格\n     */\n    private String machineSpec;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterPhyConditionDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport java.util.List;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author linyunan\n * @date 2021-10-14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"物理集群条件查询信息\")\npublic class ClusterPhyConditionDTO extends ClusterPhyDTO {\n\n    @ApiModelProperty(\"排序字段 diskUsagePercent\")\n    private String       sortTerm;\n\n    private String       sortType;\n\n    @ApiModelProperty(value = \"是否降序排序（默认降序）\", dataType = \"Boolean\", required = false)\n    private Boolean      orderByDesc = true;\n\n    @ApiModelProperty(\"逻辑集群\")\n    private String       logicClusterName;\n\n    @ApiModelProperty(\"集群名称，用于后端根据项目筛选\")\n    private List<String> clusterNames;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterPhyDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n *\n * @author ohushenglin_v\n * @date 2022-05-10\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"集群信息\")\npublic class ClusterPhyDTO extends PageDTO {\n\n    @ApiModelProperty(\"集群ID\")\n    private Integer                    id;\n\n    @ApiModelProperty(\"集群名字\")\n    private String                     cluster;\n\n    @ApiModelProperty(\"描述\")\n    private String                     desc;\n\n    @ApiModelProperty(\"tcp地址-读\")\n    private String                     readAddress;\n\n    @ApiModelProperty(\"tcp地址-写\")\n    private String                     writeAddress;\n\n    @ApiModelProperty(\"http地址-读\")\n    private String                     httpAddress;\n\n    @ApiModelProperty(\"http地址-写\")\n    private String                     httpWriteAddress;\n\n    /**\n     * @see ESClusterTypeEnum\n     */\n    @ApiModelProperty(\"集群类型(-1 未知 3 docker集群 4 host集群 5 vm集群)\")\n    private Integer                    type;\n\n    @ApiModelProperty(\"集群展示用属性标签，如「集群所属资源类型」等等\")\n    private String                     tags;\n\n    @ApiModelProperty(\"数据中心\")\n    private String                     dataCenter;\n\n    @ApiModelProperty(\"机房\")\n    private String                     idc;\n\n    @ApiModelProperty(\"服务等级\")\n    private Integer                    level;\n\n    @ApiModelProperty(\"es版本\")\n    private String                     esVersion;\n\n    @ApiModelProperty(\"镜像名称\")\n    private String                     imageName;\n\n    @ApiModelProperty(\"机器节点\")\n    private String                     nsTree;\n\n    @ApiModelProperty(\"插件ID\")\n    private String                     plugIds;\n\n    @ApiModelProperty(\"程序包Id\")\n    private Long                       packageId;\n\n    @ApiModelProperty(\"配置包\")\n    private ESConfigDTO                eSConfigDTO;\n\n    @ApiModelProperty(\"插件包列表\")\n    private List<PluginDTO>            plugs;\n\n    @ApiModelProperty(\"集群角色列表\")\n    private List<ESClusterRoleDTO>     roleClusters;\n\n    @ApiModelProperty(\"集群角色 对应主机列表\")\n    private List<ESClusterRoleHostDTO> roleClusterHosts;\n\n    @ApiModelProperty(\"单节点实例数\")\n    private Integer                    pidCount;\n\n    @ApiModelProperty(\"机器规格  host物理集群必填\")\n    private String                     machineSpec;\n\n    @ApiModelProperty(\"集群创建人\")\n    private String                     creator;\n\n    @ApiModelProperty(\"集群密码\")\n    private String                     password;\n\n    @ApiModelProperty(\"client运行模式（0：读写共享 1：读写分离）\")\n    private Integer                    runMode;\n\n    @ApiModelProperty(\"指定用写client的action\")\n    private String                     writeAction;\n\n    @ApiModelProperty(\"集群状态 0 green 1 yellow 2 red -1 未知\")\n    private Integer                    health;\n\n    @ApiModelProperty(\"活跃分片数目\")\n    private Long                       activeShardNum;\n\n    @ApiModelProperty(\"磁盘总量(byte)\")\n    private Long                       diskTotal;\n\n    @ApiModelProperty(\"磁盘使用大小(byte)\")\n    private Long                       diskUsage;\n\n    @ApiModelProperty(\"磁盘使用率(byte)\")\n    private Double                     diskUsagePercent;\n\n    @ApiModelProperty(\"IaaS平台类型\")\n    private String                     platformType;\n\n    /**\n     * @see ClusterResourceTypeEnum\n     */\n    @ApiModelProperty(\"集群资源类型(-1 未知 1 共享 2 独立 3 独享)\")\n    private Integer                    resourceType;\n\n    @ApiModelProperty(\"gateway地址\")\n    private String                     gatewayUrl;\n\n    @ApiModelProperty(\"kibana外链地址\")\n    private String                    kibanaAddress;\n\n    @ApiModelProperty(\"cerebro外链地址\")\n    private String                    cerebroAddress;\n\n    @ApiModelProperty(\"代理地址\")\n    private String                    proxyAddress;\n\n    /**\n     * 是否接入 ecm\n     */\n    @ApiModelProperty(\"是否接入 ecm\")\n    private Boolean                   ecmAccess;\n\n    /**\n     * ecm 关联组建 id\n     */\n    @ApiModelProperty(\"ecm 关联组建 id\")\n    private Integer                   componentId;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterPhyQuickCommandIndicesQueryDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/29\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"快捷命令索引条件查询实体\")\npublic class ClusterPhyQuickCommandIndicesQueryDTO extends PageDTO {\n\n    @ApiModelProperty(\"集群\")\n    private String cluster;\n\n    @ApiModelProperty(\"关键字\")\n    private String keyword;\n\n    @ApiModelProperty(\"索引名称\")\n    private String index;\n\n    @ApiModelProperty(\"状态 green yellow red\")\n    private String health;\n\n    @ApiModelProperty(\"状态 open close\")\n    private String status;\n\n    @ApiModelProperty(\"排序字段(priStoreSize)、主分配个数(pri)、副本个数(rep)、存储大小(storeSize)、文档数量(docsCount)、删除文档数量(docsDeleted)、索引名称（index）\")\n    private String sortTerm;\n\n    @ApiModelProperty(value = \"是否降序排序（默认降序）\", dataType = \"Boolean\", required = false)\n    private Boolean orderByDesc = true;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterPhyQuickCommandShardsQueryDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/29\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"快捷命令索引条件查询实体\")\npublic class ClusterPhyQuickCommandShardsQueryDTO extends PageDTO {\n\n    @ApiModelProperty(\"集群\")\n    private String cluster;\n\n    @ApiModelProperty(\"关键字\")\n    private String keyword;\n\n    @ApiModelProperty(\"索引名称\")\n    private String index;\n\n    @ApiModelProperty(\"状态 green yellow red\")\n    private String health;\n\n    @ApiModelProperty(\"状态 open close\")\n    private String status;\n\n    @ApiModelProperty(\"排序字段(docs)\")\n    private String sortTerm;\n\n    @ApiModelProperty(value = \"是否降序排序（默认降序）\", dataType = \"Boolean\", required = false)\n    private Boolean orderByDesc = true;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterRegionDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-06-04\n */\n@Data\n@Builder()\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"集群Region\")\npublic class ClusterRegionDTO {\n    @ApiModelProperty(\"主键\")\n    private Long   id;\n\n    @ApiModelProperty(\"region 名称\")\n    private String name;\n\n    @ApiModelProperty(\"逻辑集群ID\")\n    private String logicClusterIds;\n\n    @ApiModelProperty(\"物理集群名称\")\n    private String phyClusterName;\n\n    @ApiModelProperty(\"配置项\")\n    private String config;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterRegionWithNodeInfoDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by lyn on 2022/5/17\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"集群带节点信息的Region实体\")\npublic class ClusterRegionWithNodeInfoDTO extends ClusterRegionDTO {\n    @ApiModelProperty(\"绑定节点id列表\")\n    private List<Integer> bindingNodeIds;\n\n    @ApiModelProperty(\"解绑节点id列表\")\n    private List<Integer> unBindingNodeIds;\n    \n    private ClusterRegionWithNodeInfoDTO(ClusterRegionWithNodeInfoDTOBuilder clusterRegionWithNodeInfoDTOBuilder) {\n        setId(clusterRegionWithNodeInfoDTOBuilder.id);\n        setName(clusterRegionWithNodeInfoDTOBuilder.name);\n        setLogicClusterIds(clusterRegionWithNodeInfoDTOBuilder.logicClusterIds);\n        setPhyClusterName(clusterRegionWithNodeInfoDTOBuilder.phyClusterName);\n        setConfig(clusterRegionWithNodeInfoDTOBuilder.config);\n        setBindingNodeIds(clusterRegionWithNodeInfoDTOBuilder.bindingNodeIds);\n        setUnBindingNodeIds(clusterRegionWithNodeInfoDTOBuilder.unBindingNodeIds);\n    }\n    \n    public static final class ClusterRegionWithNodeInfoDTOBuilder {\n        private Long          id;\n        private String        name;\n        private String        logicClusterIds;\n        private String        phyClusterName;\n        private String        config;\n        private List<Integer> bindingNodeIds;\n        private List<Integer> unBindingNodeIds;\n        \n        public ClusterRegionWithNodeInfoDTOBuilder() {\n        }\n        \n        public ClusterRegionWithNodeInfoDTOBuilder(ClusterRegionWithNodeInfoDTO copy) {\n            this.id = copy.getId();\n            this.name = copy.getName();\n            this.logicClusterIds = copy.getLogicClusterIds();\n            this.phyClusterName = copy.getPhyClusterName();\n            this.config = copy.getConfig();\n            this.bindingNodeIds = copy.getBindingNodeIds();\n            this.unBindingNodeIds = copy.getUnBindingNodeIds();\n        }\n        \n        public ClusterRegionWithNodeInfoDTOBuilder withId(Long val) {\n            id = val;\n            return this;\n        }\n        \n        public ClusterRegionWithNodeInfoDTOBuilder withName(String val) {\n            name = val;\n            return this;\n        }\n        \n        public ClusterRegionWithNodeInfoDTOBuilder withLogicClusterIds(String val) {\n            logicClusterIds = val;\n            return this;\n        }\n        \n        public ClusterRegionWithNodeInfoDTOBuilder withPhyClusterName(String val) {\n            phyClusterName = val;\n            return this;\n        }\n        \n        public ClusterRegionWithNodeInfoDTOBuilder withConfig(String val) {\n            config = val;\n            return this;\n        }\n        \n        public ClusterRegionWithNodeInfoDTOBuilder withBindingNodeIds(List<Integer> val) {\n            bindingNodeIds = val;\n            return this;\n        }\n        \n        public ClusterRegionWithNodeInfoDTOBuilder withUnBindingNodeIds(List<Integer> val) {\n            unBindingNodeIds = val;\n            return this;\n        }\n        \n        public ClusterRegionWithNodeInfoDTO build() {\n            return new ClusterRegionWithNodeInfoDTO(this);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ClusterSettingDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModelProperty;\nimport io.swagger.annotations.ApiOperation;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiOperation(\"动态配置项信息\")\npublic class ClusterSettingDTO extends BaseDTO {\n\n    @ApiModelProperty(\"集群名称\")\n    private String clusterName;\n\n    @ApiModelProperty(\"动态配置项修改的字段名称\")\n    private String key;\n\n    @ApiModelProperty(\"动态修改配置项字段对应的值\")\n    private Object value;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ConsoleLogicClusterDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Console 逻辑集群信息\n * @author d06679\n * @date 2019/3/22\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"集群信息\")\npublic class ConsoleLogicClusterDTO extends BaseDTO {\n\n    @ApiModelProperty(\"逻辑集群ID\")\n    private Long   id;\n\n \n\n    \n\n \n\n    @ApiModelProperty(\"备注\")\n    private String memo;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ESClusterRoleDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterRoleDTO extends BaseDTO {\n    private static final long serialVersionUID = 1L;\n\n    private Long              id;\n\n    /**\n     * elastic_cluster外键ID\n     */\n    private Long              elasticClusterId;\n\n    /**\n     * role集群名称\n     */\n    private String            roleClusterName;\n\n    /**\n     * 集群角色(masternode/datanode/clientnode)\n     */\n    private String            role;\n\n    /**\n     * pod数量\n     */\n    private Integer           podNumber;\n\n    /**\n     * 单机实例数\n     */\n    private Integer           pidCount;\n\n    /**\n     * 机器规格\n     */\n    private String            machineSpec;\n\n    /**\n     * ES版本\n     */\n    private String            esVersion;\n\n    /**\n     * 配置包ID\n     */\n    private Integer           cfgId;\n\n    /**\n     * 插件包ID列表\n     *\n     */\n    private String            plugIds;\n\n    /**\n     * 标记删除\n     */\n    private Boolean           deleteFlag;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ESClusterRoleHostDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeStatusEnum;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterRoleHostDTO extends BaseDTO {\n\n    private static final long serialVersionUID = 1L;\n\n    @ApiModelProperty(\"主键\")\n    private Long              id;\n\n    @ApiModelProperty(\"集群角色Id\")\n    private Long              roleClusterId;\n\n    @ApiModelProperty(\"主机名称\")\n    private String            hostname;\n\n    @ApiModelProperty(\"主机ip\")\n    private String            ip;\n\n    @ApiModelProperty(\"集群名称\")\n    private String            cluster;\n\n    @ApiModelProperty(\"端口\")\n    private String            port;\n\n    @ApiModelProperty(\"冷热节点标识,是热节点则设置为false\")\n    private Boolean           beCold;\n\n    /**\n     * @see ESClusterNodeRoleEnum\n     */\n    @ApiModelProperty(\"角色(1data   2client    3master)\")\n    private Integer           role;\n\n    /**\n     * @see ESClusterNodeStatusEnum\n     */\n    @ApiModelProperty(\"状态（1 在线    2 离线   3 故障）\")\n    private Integer           status;\n\n    @ApiModelProperty(\"节点set信息\")\n    private String            nodeSet;\n\n    @ApiModelProperty(\"regionId\")\n    private Integer           regionId;\n\n    @ApiModelProperty(\"attributes, 逗号分隔 key1:value1,key2:value2\")\n    private String            attributes;\n\n    @ApiModelProperty(\"机器规格\")\n    private String            machineSpec;\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        ESClusterRoleHostDTO nodeDTO = (ESClusterRoleHostDTO) o;\n\n        if (!hostname.equals(nodeDTO.hostname)) {\n            return false;\n        }\n        return cluster.equals(nodeDTO.cluster);\n\n    }\n\n    @Override\n    public int hashCode() {\n        int result = hostname.hashCode();\n        result = 31 * result + cluster.hashCode();\n        return result;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ESConfigDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"配置包DTO\")\npublic class ESConfigDTO extends BaseDTO {\n\n    @ApiModelProperty(\"主键\")\n    private Long    id;\n\n    @ApiModelProperty(\"集群id\")\n    private Long    clusterId;\n\n    @ApiModelProperty(\"配置文件名称\")\n    private String  typeName;\n\n    @ApiModelProperty(\"组件名称\")\n    private String  enginName;\n\n    @ApiModelProperty(\"配置内容\")\n    private String  configData;\n\n    @ApiModelProperty(\"配置描述\")\n    private String  desc;\n\n    @ApiModelProperty(\"配置tag\")\n    private String  versionTag;\n\n    @ApiModelProperty(\"配置版本\")\n    private Integer versionConfig;\n\n    @ApiModelProperty(\"是否在使用\")\n    private Integer selected;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ESLogicClusterDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/22\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"逻辑集群信息\")\npublic class ESLogicClusterDTO extends PageDTO {\n\n    @ApiModelProperty(\"逻辑集群ID\")\n    private Long    id;\n\n    @ApiModelProperty(\"逻辑集群名字\")\n    private String  name;\n\n    /**\n     * @see ClusterResourceTypeEnum\n     */\n    @ApiModelProperty(\"类型(1:公共：2:独立, 3:独占)\")\n    private Integer type;\n\n    @ApiModelProperty(\"所属应用ID\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"数据中心\")\n    private String  dataCenter;\n\n    @ApiModelProperty(\"数据节点个数\")\n    private Integer dataNodeNum;\n\n    @ApiModelProperty(\"备注\")\n    private String  memo;\n\n    @ApiModelProperty(\"服务等级\")\n    private Integer level;\n\n    @ApiModelProperty(\"配额\")\n    private Double  quota;\n\n    @ApiModelProperty(\"配置\")\n    private String  configJson;\n\n    @ApiModelProperty(\"健康状态 0 green 1 yellow 2 red -1 未知\")\n    private Integer health;\n\n    @ApiModelProperty(\"规格\")\n    private String  dataNodeSpec;\n\n    @ApiModelProperty(\"磁盘使用率\")\n    private Double diskUsagePercent;\n\n    @ApiModelProperty(\"磁盘总量\")\n    private Long diskTotal;\n\n    @ApiModelProperty(\"磁盘使用量\")\n    private Long diskUsage;\n\n    @ApiModelProperty(\"集群版本\")\n    private String esClusterVersion;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ESLogicClusterWithRegionDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author linyunan\n * @date 2021-03-15\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"带有region信息的逻辑集群\")\npublic class ESLogicClusterWithRegionDTO extends ESLogicClusterDTO {\n\n    @ApiModelProperty(\"集群Region\")\n    private List<ClusterRegionDTO> clusterRegionDTOS;\n    \n    private ESLogicClusterWithRegionDTO(ESLogicClusterWithRegionDTOBuilder ESLogicClusterWithRegionDTOBuilder) {\n        setId(ESLogicClusterWithRegionDTOBuilder.id);\n        setName(ESLogicClusterWithRegionDTOBuilder.name);\n        setType(ESLogicClusterWithRegionDTOBuilder.type);\n        setProjectId(ESLogicClusterWithRegionDTOBuilder.projectId);\n        setDataCenter(ESLogicClusterWithRegionDTOBuilder.dataCenter);\n        setDataNodeNum(ESLogicClusterWithRegionDTOBuilder.dataNodeNum);\n        setMemo(ESLogicClusterWithRegionDTOBuilder.memo);\n        setLevel(ESLogicClusterWithRegionDTOBuilder.level);\n        setQuota(ESLogicClusterWithRegionDTOBuilder.quota);\n        setConfigJson(ESLogicClusterWithRegionDTOBuilder.configJson);\n        setHealth(ESLogicClusterWithRegionDTOBuilder.health);\n        setDataNodeSpec(ESLogicClusterWithRegionDTOBuilder.dataNodeSpec);\n        setDiskUsagePercent(ESLogicClusterWithRegionDTOBuilder.diskUsagePercent);\n        setDiskTotal(ESLogicClusterWithRegionDTOBuilder.diskTotal);\n        setDiskUsage(ESLogicClusterWithRegionDTOBuilder.diskUsage);\n        setEsClusterVersion(ESLogicClusterWithRegionDTOBuilder.esClusterVersion);\n        setClusterRegionDTOS(ESLogicClusterWithRegionDTOBuilder.clusterRegionDTOS);\n    }\n    \n    public static final class ESLogicClusterWithRegionDTOBuilder {\n        private Long                   id;\n        private String                 name;\n        private Integer                type;\n        private Integer                projectId;\n        private String                 dataCenter;\n        private Integer                dataNodeNum;\n        private String                 memo;\n        private Integer                level;\n        private Double                 quota;\n        private String                 configJson;\n        private Integer                health;\n        private String                 dataNodeSpec;\n        private Double                 diskUsagePercent;\n        private Long                   diskTotal;\n        private Long                   diskUsage;\n        private String                 esClusterVersion;\n        private List<ClusterRegionDTO> clusterRegionDTOS;\n        \n        public ESLogicClusterWithRegionDTOBuilder() {\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder(ESLogicClusterWithRegionDTO copy) {\n            this.id = copy.getId();\n            this.name = copy.getName();\n            this.type = copy.getType();\n            this.projectId = copy.getProjectId();\n            this.dataCenter = copy.getDataCenter();\n            this.dataNodeNum = copy.getDataNodeNum();\n            this.memo = copy.getMemo();\n            this.level = copy.getLevel();\n            this.quota = copy.getQuota();\n            this.configJson = copy.getConfigJson();\n            this.health = copy.getHealth();\n            this.dataNodeSpec = copy.getDataNodeSpec();\n            this.diskUsagePercent = copy.getDiskUsagePercent();\n            this.diskTotal = copy.getDiskTotal();\n            this.diskUsage = copy.getDiskUsage();\n            this.esClusterVersion = copy.getEsClusterVersion();\n            this.clusterRegionDTOS = copy.getClusterRegionDTOS();\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withId(Long val) {\n            id = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withName(String val) {\n            name = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withType(Integer val) {\n            type = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withProjectId(Integer val) {\n            projectId = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withDataCenter(String val) {\n            dataCenter = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withDataNodeNum(Integer val) {\n            dataNodeNum = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withMemo(String val) {\n            memo = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withLevel(Integer val) {\n            level = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withQuota(Double val) {\n            quota = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withConfigJson(String val) {\n            configJson = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withHealth(Integer val) {\n            health = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withDataNodeSpec(String val) {\n            dataNodeSpec = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withDiskUsagePercent(Double val) {\n            diskUsagePercent = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withDiskTotal(Long val) {\n            diskTotal = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withDiskUsage(Long val) {\n            diskUsage = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withEsClusterVersion(String val) {\n            esClusterVersion = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTOBuilder withClusterRegionDTOS(List<ClusterRegionDTO> val) {\n            clusterRegionDTOS = val;\n            return this;\n        }\n        \n        public ESLogicClusterWithRegionDTO build() {\n            return new ESLogicClusterWithRegionDTO(this);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ESPackageDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.springframework.web.multipart.MultipartFile;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESPackageDTO extends BaseDTO {\n\n    private Long          id;\n    /**\n     * 镜像地址或包地址\n     */\n    private String        url;\n\n    /**\n     * 程序包文件名\n     */\n    private String        fileName;\n\n    /**\n     * 文件md5\n     */\n    private String        md5;\n\n    /**\n     * 版本标识\n     */\n    private String        esVersion;\n\n    /**\n     * 类型( 3 docker/ 4 host)\n     */\n    private Integer       manifest;\n\n    /**\n     * 包创建人\n     */\n    private String        creator;\n    /**\n     *备注\n     */\n    private String        desc;\n\n    /**\n     * 上传配置包实体\n     */\n    private MultipartFile uploadFile;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ESZeusConfigDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"配置包查询DTO\")\npublic class ESZeusConfigDTO extends BaseDTO {\n\n    @ApiModelProperty(\"集群Id\")\n    private Long   clusterId;\n\n    @ApiModelProperty(\"集群名称\")\n    private String clusterName;\n\n    @ApiModelProperty(\"组件名称\")\n    private String enginName;\n\n    @ApiModelProperty(\"配置文件名称\")\n    private String typeName;\n\n    @ApiModelProperty(\"配置文件内容\")\n    private String content;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/ESZeusHostInfoDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n/**\n * Created by linyunan on 2021-09-14\n */\n@Data\n@ApiModel(description = \"用户zeus回写ES集群读写地址\")\npublic class ESZeusHostInfoDTO {\n\n    @ApiModelProperty(\"集群名称\")\n    private String clusterPhyName;\n\n    @ApiModelProperty(\"角色\")\n    private String role;\n\n    @ApiModelProperty(\"Http读写地址\")\n    private String httpAddress;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/cluster/PluginDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.springframework.web.multipart.MultipartFile;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"ESPluginDTO\", description = \"插件包DTO\")\npublic class PluginDTO extends BaseDTO {\n\n    @ApiModelProperty(\"ID主键自增\")\n    private Long          id;\n\n    @ApiModelProperty(\"插件名\")\n    private String        name;\n\n    @ApiModelProperty(\"物理集群Id\")\n    private String        physicClusterId;\n\n    @ApiModelProperty(\"插件版本\")\n    private String        version;\n\n    @ApiModelProperty(\"插件存储地址\")\n    private String        url;\n\n    @ApiModelProperty(\"插件文件md5\")\n    private String        md5;\n\n    @ApiModelProperty(\"插件描述\")\n    private String        desc;\n\n    @ApiModelProperty(\"插件创建人\")\n    private String        creator;\n\n    @ApiModelProperty(\"集群插件类型\")\n    private Integer       pDefault;\n\n    @ApiModelProperty(\"上传的文件名\")\n    private String        fileName;\n\n    @ApiModelProperty(\"上传的文件\")\n    private MultipartFile uploadFile;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/config/AriusConfigInfoDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.config;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"配置信息\")\npublic class AriusConfigInfoDTO extends BaseDTO {\n\n    @ApiModelProperty(\"配置ID\")\n    private Integer id;\n\n    @ApiModelProperty(\"配置组\")\n    private String  valueGroup;\n\n    @ApiModelProperty(\"配置名称\")\n    private String  valueName;\n\n    @ApiModelProperty(\"值\")\n    private String  value;\n\n    @ApiModelProperty(\"配置项维度  1 集群   2 模板\")\n    private Integer dimension;\n\n    @ApiModelProperty(\"状态(1 正常；2 禁用；-1 删除)\")\n    private Integer status;\n\n    @ApiModelProperty(\"备注\")\n    private String  memo;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/dsl/DslBaseDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/6/21 下午2:47\n * @Modified By\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslBaseDTO {\n\n    /**\n     * 应用id\n     */\n    @ApiModelProperty(value = \"应用账号\", example = \"1\")\n    private Integer projectId;\n\n    /**\n     * 查询模板的md5值\n     */\n    @ApiModelProperty(value = \"查询模板MD5\", example = \"V2_EA317B2029682DB83A191CBD797A66FE\")\n    private String  dslTemplateMd5;\n\n    /**\n     * 获取索引主键\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    public String getProjectIdDslTemplateMd5() {\n        return String.format(\"%d_%s\", this.projectId, this.dslTemplateMd5);\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/dsl/DslQueryLimitDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/6/20 下午4:48\n * @Modified By\n * 查询模板限流值\n */\n@ApiModel(value = \"DslQueryLimit\", description = \"查询语句限流值参数\")\npublic class DslQueryLimitDTO extends DslBaseDTO {\n\n    @ApiModelProperty(value = \"查询语句当前限流值\", example = \"50\")\n    private Double queryLimit;\n\n    @ApiModelProperty(value = \"查询语句上一次更改的限流值\", example = \"50\")\n    private Double queryLimitBefore;\n\n    public DslQueryLimitDTO() {\n    }\n\n    public DslQueryLimitDTO(Integer projectId, String dslTemplateMd5, Double queryLimit) {\n        super(projectId, dslTemplateMd5);\n        this.queryLimit = queryLimit;\n    }\n\n    public DslQueryLimitDTO(Integer projectId, String dslTemplateMd5, Double queryLimit, Double queryLimitBefore) {\n        super(projectId, dslTemplateMd5);\n        this.queryLimit = queryLimit;\n        this.queryLimitBefore = queryLimitBefore;\n    }\n\n    public Double getQueryLimit() {\n        return queryLimit;\n    }\n\n    public DslQueryLimitDTO setQueryLimit(Double queryLimit) {\n        this.queryLimit = queryLimit;\n        return this;\n    }\n\n    public Double getQueryLimitBefore() {\n        return queryLimitBefore;\n    }\n\n    public DslQueryLimitDTO setQueryLimitBefore(Double queryLimitBefore) {\n        this.queryLimitBefore = queryLimitBefore;\n        return this;\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/dsl/template/DslTemplateConditionDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author cjm\n */\n@NoArgsConstructor\n@EqualsAndHashCode(callSuper = true)\n@Data\n@ApiModel(description = \"DSL模版分页列表查询条件\")\npublic class DslTemplateConditionDTO extends PageDTO {\n\n    @ApiModelProperty(value = \"应用ID\", dataType = \"Integer\", required = false)\n    private Integer  projectId;\n\n    @ApiModelProperty(value = \"排序信息（精确）\", dataType = \"String\", required = false)\n    private String  sortInfo;\n\n    @ApiModelProperty(value = \"是否逆序排序（默认逆序）\", dataType = \"Boolean\", required = false)\n    private Boolean orderByDesc = true;\n\n    @ApiModelProperty(value = \"DSL模版MD5（精确）\", dataType = \"String\", required = false)\n    private String  dslTemplateMd5;\n\n    @ApiModelProperty(value = \"查询索引（模糊）\", dataType = \"String\", required = false)\n    private String  queryIndex;\n\n    @ApiModelProperty(value = \"DSL模版最近使用时间start（时间戳ms）\", dataType = \"Long\", required = true)\n    private Long    startTime;\n\n    @ApiModelProperty(value = \"DSL模版最近使用时间end（时间戳ms）\", dataType = \"Long\", required = true)\n    private Long    endTime;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/indices/IndexCatCellDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.indices;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引详情\")\npublic class IndexCatCellDTO {\n\n    @ApiModelProperty(\"主键\")\n    private String  key;\n\n    @ApiModelProperty(\"物理集群名称\")\n    private String  cluster;\n\n    @ApiModelProperty(\"逻辑集群名称\")\n    private String  clusterLogic;\n\n    @ApiModelProperty(\"逻辑集群Id\")\n    private Long    resourceId;\n\n    @ApiModelProperty(\"项目Id\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"分区健康\")\n    private String  health;\n\n    @ApiModelProperty(\"分区状态\")\n    private String  status;\n\n    @ApiModelProperty(\"分区名字\")\n    private String  index;\n\n    @ApiModelProperty(\"分区shard个数\")\n    private Long    pri;\n\n    @ApiModelProperty(\"分区副本个数\")\n    private Long    rep;\n\n    @ApiModelProperty(\"分区文档个数\")\n    private Long    docsCount;\n\n    @ApiModelProperty(\"分区文档删除个数\")\n    private Long    docsDeleted;\n\n    @ApiModelProperty(\"分区主分片存储大小\")\n    private String  storeSize;\n\n    @ApiModelProperty(\"分区存储大小\")\n    private String  priStoreSize;\n\n    @ApiModelProperty(\"可读标志位\")\n    private Boolean readFlag;\n\n    @ApiModelProperty(\"可写标志位\")\n    private Boolean writeFlag;\n\n    @ApiModelProperty(\"删除标识\")\n    private Boolean deleteFlag;\n\n    @ApiModelProperty(\"时间戳\")\n    private Long    timestamp;\n\n    @ApiModelProperty(\"primaries segment count\")\n    private Long    primariesSegmentCount;\n\n    @ApiModelProperty(\"total segment count\")\n    private Long    totalSegmentCount;\n\n    @ApiModelProperty(\"平台模板Id\")\n    private Integer templateId;\n\n    @ApiModelProperty(\"通过平台索引创建标识 true 通过平台创建，false不是通过平台创建\")\n    private Boolean platformCreateFlag;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/indices/IndexQueryDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.indices;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/29\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引条件查询实体\")\npublic class IndexQueryDTO extends PageDTO {\n\n    @ApiModelProperty(\"集群\")\n    private String  cluster;\n\n    @ApiModelProperty(\"索引名称\")\n    private String  index;\n\n    @ApiModelProperty(\"状态 green yellow red\")\n    private String  health;\n\n    @ApiModelProperty(\"状态 open close\")\n    private String  status;\n\n    @ApiModelProperty(\"排序字段(priStoreSize)、shard数(pri)、副本个数(rep)、存储大小(storeSize)、文档数量(docsCount)、删除文档数量(docsDeleted、索引名称（index）、segment数（totalSegmentCount）\")\n    private String  sortTerm;\n\n    @ApiModelProperty(value = \"是否降序排序（默认降序）\", dataType = \"Boolean\", required = false)\n    private Boolean orderByDesc = true;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/indices/IndicesBlockSettingDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.indices;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/29\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引阻塞实体\")\npublic class IndicesBlockSettingDTO {\n    @ApiModelProperty(\"集群名称\")\n    private String  cluster;\n\n    @ApiModelProperty(\"索引名称\")\n    private String  index;\n\n    @ApiModelProperty(\"阻塞类型 1 read 读 2 write 写\")\n    private String  type;\n\n    @ApiModelProperty(\"阻塞值 true false\")\n    private Boolean value;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/indices/IndicesClearDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.indices;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/29\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Deprecated\n@ApiModel(description = \"索引清理实体\")\npublic class IndicesClearDTO extends BaseDTO {\n    @ApiModelProperty(\"集群名称\")\n    private String clusterPhyName;\n\n    @ApiModelProperty(\"索引名称\")\n    private String index;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/indices/manage/IndexCatCellWithConfigDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.manage;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"索引带有配置信息\")\npublic class IndexCatCellWithConfigDTO extends IndexCatCellDTO {\n\n    @ApiModelProperty(\"mapping\")\n    private String       mapping;\n\n    @ApiModelProperty(\"setting\")\n    private String       setting;\n\n    @ApiModelProperty(\"target index\")\n    private String       targetIndex;\n\n    @ApiModelProperty(\"extra\")\n    private String       extra;\n\n    @ApiModelProperty(\"别名\")\n    private List<String> aliases;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/indices/srv/IndexForceMergeDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.srv;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author chengxiang\n * @date 2022/6/2\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引force merge\")\npublic class IndexForceMergeDTO extends BaseDTO {\n\n    @ApiModelProperty(\"max_num_segments\")\n    private Integer               maxNumSegments;\n\n    @ApiModelProperty(\"only_expunge_deletes\")\n    private Boolean               onlyExpungeDeletes;\n\n    @ApiModelProperty(\"index 列表\")\n    private List<IndexCatCellDTO> indices;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/indices/srv/IndexRolloverDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.srv;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/6/2\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引rollover\")\npublic class IndexRolloverDTO extends BaseDTO {\n\n    @ApiModelProperty(\"rollover的参数\")\n    private String                content;\n\n    @ApiModelProperty(\"index 列表\")\n    private List<IndexCatCellDTO> indices;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/ClientNodeDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author cjm\n */\n@EqualsAndHashCode(callSuper = true)\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"esClientNode节点查询\")\npublic class ClientNodeDTO extends GatewayNodeDTO {\n\n    @ApiModelProperty(\"clientNodeIp\")\n    private String clientNodeIp;\n\n    @Override\n    public String getGroup() {\n        return \"clientNode\";\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/DashBoardMetricThresholdDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricListTypeEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 阈值详细信息.\n *\n * @ClassName DashBoardMetricThresholdDTO\n * @Author gyp\n * @Date 2022/7/26\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Builder\npublic class DashBoardMetricThresholdDTO {\n    /**\n     * 配置名称\n     */\n    private String configName;\n    /**\n     *\n     */\n    private DashBoardMetricListTypeEnum typeEnum;\n    /**\n     * 名称\n     */\n    private String name;\n    /**\n     * 指标项名称\n     */\n    private String metrics;\n    /**\n     * 单位\n     */\n    private String unit;\n    /**\n     * 比较符号\n     */\n    private String compare;\n    /**\n     * 阈值\n     */\n    private Double value;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/GatewayDslDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by fitz on 2021-08-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"gateway DSL模版查询\")\npublic class GatewayDslDTO extends GatewayMetricsDTO {\n\n    @ApiModelProperty(\"dslMd5\")\n    private String  dslMd5;\n\n    @ApiModelProperty(\"top数字\")\n    private Integer topNu;\n\n    @Override\n    public String getGroup() {\n        return \"dsl\";\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/GatewayIndexDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by fitz on 2021-08-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"gateway索引查询\")\npublic class GatewayIndexDTO extends GatewayMetricsDTO {\n\n    @ApiModelProperty(\"索引名称\")\n    private String  indexName;\n\n    @ApiModelProperty(\"top数字\")\n    private Integer topNu;\n\n    @Override\n    public String getGroup() {\n        return \"index\";\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/GatewayJoinQueryDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n/**\n * @author cjm\n */\n@Data\n@ApiModel(description = \"GatewayJoin异常查询分页列表查询条件\")\npublic class GatewayJoinQueryDTO extends PageDTO {\n\n    @ApiModelProperty(value = \"查询索引（模糊）\", dataType = \"String\", required = false)\n    private String queryIndex;\n\n    @ApiModelProperty(value = \"DSL模版最近使用时间start（时间戳ms）\", dataType = \"Long\", required = true)\n    private Long   startTime;\n\n    @ApiModelProperty(value = \"DSL模版最近使用时间end（时间戳ms）\", dataType = \"Long\", required = true)\n    private Long   endTime;\n\n    @ApiModelProperty(value = \"查询总耗时（时间戳ms）\", dataType = \"Long\", required = true)\n    private Long   totalCost;\n\n    @ApiModelProperty(value = \"应用Id\", dataType = \"Integer\", required = false)\n    private Integer   projectId;\n\n    @ApiModelProperty(value = \"物理集群名称（仅限超管侧使用）\", dataType = \"String\", required = false)\n    private String clusterName;\n\n    @ApiModelProperty(value = \"排序信息（精确）,排序字段 响应时间（ms）esCost、总耗时（ms）totalCost、单次命中数totalHits、单次响应长度responseLen\", dataType = \"String\", required = false)\n    private String  sortTerm;\n\n    @ApiModelProperty(value = \"是否逆序排序（默认逆序）\", dataType = \"Boolean\", required = false)\n    private Boolean orderByDesc = true;\n\n    @ApiModelProperty(value = \"tab页面名称\", dataType = \"String\", required = false)\n    private String tabName;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/GatewayMetricsDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\n\n/**\n * Created by fitz on 2021-08-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"gateway指标公共参数\")\npublic abstract class GatewayMetricsDTO extends BaseDTO {\n    private static final Long ONE_HOUR = 60 * 60 * 1000L;\n\n    @ApiModelProperty(\"开始时间\")\n    private Long              startTime;\n\n    @ApiModelProperty(\"结束时间\")\n    private Long              endTime;\n\n    @ApiModelProperty(\"指标类型\")\n    private List<String>      metricsTypes;\n\n    public void validParam() {\n        if (endTime == null) {\n            endTime = System.currentTimeMillis();\n        }\n        if (startTime == null) {\n            startTime = endTime - ONE_HOUR;\n        }\n        //超过一周时间容易引起熔断，不允许\n        if ((endTime - startTime) > ONE_HOUR * 24 * 7) {\n            throw new RuntimeException(\"时间跨度不要超过一周\");\n        }\n\n        if (CollectionUtils.isEmpty(metricsTypes)) {\n            throw new RuntimeException(\"指标类型为空\");\n        }\n\n    }\n\n    public abstract String getGroup();\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/GatewayNodeDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by fitz on 2021-08-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"gateway节点查询\")\npublic class GatewayNodeDTO extends GatewayMetricsDTO {\n\n    @ApiModelProperty(\"节点Ip\")\n    private String  nodeIp;\n\n    @ApiModelProperty(\"top数字\")\n    private Integer topNu;\n\n    @Override\n    public String getGroup() {\n        return \"node\";\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/GatewayOverviewDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport lombok.Data;\n\n/**\n * Created by fitz on 2021-08-11\n */\n@Data\n@ApiModel(description = \"gateway总览查询\")\npublic class GatewayOverviewDTO extends GatewayMetricsDTO {\n    @Override\n    public String getGroup() {\n        return \"overview\";\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/GatewayProjectDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by fitz on 2021-08-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"gateway项目查询\")\npublic class GatewayProjectDTO extends GatewayMetricsDTO {\n\n    @ApiModelProperty(\"项目Id\")\n    private String  projectId;\n\n    @ApiModelProperty(\"top数字\")\n    private Integer topNu;\n\n    @Override\n    public String getGroup() {\n        return \"app\";\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MetricDictionaryDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 指标字典查询.\n *\n * @ClassName MetricDictionaryDTO\n * @Author gyp\n * @Date 2022/9/29\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"指标字典信息\")\npublic class MetricDictionaryDTO {\n    @ApiModelProperty(\"指标分类\")\n    private String type;\n\n    @ApiModelProperty(\"指标分类\")\n    private String metricType;\n\n    @ApiModelProperty(\"指标分类\")\n    private String name;\n\n    @ApiModelProperty(\"是否黄金指标\")\n    private Integer isGold;\n\n    @ApiModelProperty(\"告警指标\")\n    private Integer isWarning;\n\n    @ApiModelProperty(\"阈值配置\")\n    private Integer isThreshold;\n\n    @ApiModelProperty(\"指标来源\")\n    private String source;\n\n    @ApiModelProperty(\"指标标签\")\n    private String tags;\n\n    @ApiModelProperty(\"模块\")\n    private String model;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MetricsClusterPhyDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-30\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"指标信息\")\npublic class MetricsClusterPhyDTO extends BaseDTO {\n\n    @ApiModelProperty(\"物理集群名称\")\n    private String       clusterPhyName;\n\n    @ApiModelProperty(\"逻辑集群名称\")\n    private String       clusterLogicName;\n\n    @ApiModelProperty(\"开始时间\")\n    private Long         startTime;\n\n    @ApiModelProperty(\"结束时间\")\n    private Long         endTime;\n\n    @ApiModelProperty(\"聚合类型\")\n    private String       aggType;\n\n    @ApiModelProperty(\"指标类型\")\n    private List<String> metricsTypes;\n\n    @ApiModelProperty(\"Top-Level:5,10,15,20\")\n    private Integer      topNu;\n\n    @ApiModelProperty(\"Top计算时间步长:1,5,10,15\")\n    private Integer      topTimeStep;\n\n    @ApiModelProperty(\"Top计算方式:max,avg\")\n    private String       topMethod;\n\n    /**\n     * 逻辑集群下的节点名，索引名，索引模板名\n     */\n    private List<String> itemNamesUnderClusterLogic;\n    @ApiModelProperty(value = \"内置，不需要前端传入，项目id\",hidden = true)\n    private Integer       projectId;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MetricsClusterPhyIndicesDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-30\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"指标信息\")\npublic class MetricsClusterPhyIndicesDTO extends MetricsClusterPhyDTO {\n\n    @ApiModelProperty(\"索引名称\")\n    private String indexName;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MetricsClusterPhyNodeDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-30\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"指标信息\")\npublic class MetricsClusterPhyNodeDTO extends MetricsClusterPhyDTO {\n\n    @ApiModelProperty(\"集群节点ip\")\n    private String nodeName;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MetricsClusterPhyNodeTaskDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author didi\n * @date 2022-01-15 4:20 下午\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"节点task指标信息\")\npublic class MetricsClusterPhyNodeTaskDTO extends MetricsClusterPhyNodeDTO {\n\n    @ApiModelProperty(\"集群节点ip\")\n    private List<String> aggTypes;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MetricsClusterPhyTemplateDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"物理集群模板维度指标信息\")\npublic class MetricsClusterPhyTemplateDTO extends MetricsClusterPhyIndicesDTO {\n    @ApiModelProperty(\"逻辑模板Id\")\n    private Integer logicTemplateId;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MetricsDashboardListDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-30\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"Dashboard大盘列表类型的指标信息, 默认时间为当前时间\")\npublic class MetricsDashboardListDTO extends BaseDTO {\n    @ApiModelProperty(\"聚合类型\")\n    private String       aggType;\n\n    @ApiModelProperty(value = \"是否降序排序（默认降序）\", dataType = \"Boolean\", required = false)\n    private Boolean      orderByDesc = true;\n\n    @ApiModelProperty(\"指标类型\")\n    private List<String> metricsTypes;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MetricsDashboardTopNDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-30\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"Dashboard大盘Top类型类型的指标信息\")\npublic class MetricsDashboardTopNDTO extends BaseDTO {\n    @ApiModelProperty(\"开始时间\")\n    private Long         startTime;\n\n    @ApiModelProperty(\"结束时间\")\n    private Long         endTime;\n\n    @ApiModelProperty(\"聚合类型\")\n    private String       aggType;\n\n    @ApiModelProperty(\"指标类型\")\n    private List<String> metricsTypes;\n\n    @ApiModelProperty(\"Top-Level:5,10,15,20\")\n    private Integer      topNu;\n\n    public void init() {\n        // 这里后端暂时写定max, 防止前端乱传聚合类型导致返回数据失真\n        // aggType   = null == aggType ? \"max\" : aggType;\n        aggType = \"max\";\n        topNu = null == topNu ? 5 : topNu;\n        long currentTimeMillis = System.currentTimeMillis();\n        // 默认为最新一小时的时间区间\n        startTime = null == startTime ? (currentTimeMillis - 60 * 60 * 1000) : startTime;\n        endTime = null == endTime ? currentTimeMillis : endTime;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MultiGatewayNodesDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * Created by chengxiang\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"gateway节点查询\")\npublic class MultiGatewayNodesDTO extends GatewayMetricsDTO {\n\n    @ApiModelProperty(\"节点Ip\")\n    private List<String> nodeIps;\n\n    @ApiModelProperty(\"top数字\")\n    private Integer      topNu;\n\n    @Override\n    public String getGroup() {\n        return \"node\";\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MultiMetricsClusterPhyIndicesDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @Authoer: zyl\n * @Date: 2022/11/23\n * @Version: 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"指标信息\")\npublic class MultiMetricsClusterPhyIndicesDTO extends MetricsClusterPhyDTO {\n\n    @ApiModelProperty(\"集群多个索引名称\")\n    private List<String> indexNames;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MultiMetricsClusterPhyNodeDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * Created by liuchengxiang\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"指标信息\")\npublic class MultiMetricsClusterPhyNodeDTO extends MetricsClusterPhyDTO {\n\n    @ApiModelProperty(\"集群多个节点ip\")\n    private List<String> nodeNames;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MultiMetricsClusterPhyNodeTaskDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author didi\n * @date 2022-01-15 4:20 下午\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"多节点task指标信息\")\npublic class MultiMetricsClusterPhyNodeTaskDTO extends MultiMetricsClusterPhyNodeDTO {\n\n    @ApiModelProperty(\"集群节点ip\")\n    private List<String> aggTypes;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/MultiMetricsClusterPhyTemplateDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @Authoer: zyl\n * @Date: 2022/11/23\n * @Version: 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"指标信息\")\npublic class MultiMetricsClusterPhyTemplateDTO extends MetricsClusterPhyDTO{\n\n    @ApiModelProperty(\"集群多个逻辑模板Id\")\n    private List<Integer> templateIdList;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/ThresholdDto.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\n\n/**\n * dashboard阈值的信息.\n *\n * @ClassName ThresholdDto\n * @Author gyp\n * @Date 2022/7/26\n * @Version 1.0\n */\n@Data\n@AllArgsConstructor\n@Builder\npublic class ThresholdDto {\n    /**\n     * 名称\n     */\n    private String name;\n    /**\n     * 指标项名称\n     */\n    private String metrics;\n    /**\n     * 描述\n     */\n    private String desc;\n    /**\n     * 单位\n     */\n    private String unit;\n    /**\n     * 比较符号\n     */\n    private String compare;\n    /**\n     * 阈值\n     */\n    private Double value;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/metrics/UserConfigInfoDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class UserConfigInfoDTO extends BaseDTO {\n\n    @ApiModelProperty(\"用户名\")\n    private String       userName;\n\n    @ApiModelProperty(\"一级目录下的配置类型,如集群看板，网关看板\")\n    private String       firstUserConfigType;\n\n    @ApiModelProperty(\"二级目录下的配置类型,如集群看板下的总览指标类型\")\n    private String       secondUserConfigType;\n\n    @ApiModelProperty(\"二级目录配置下具体的配置列表,如cpu利用率\")\n    private List<String> userConfigTypes;\n\n    @ApiModelProperty(\"应用ID\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"配置类型\")\n    private Integer configType;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/oprecord/OperateRecordDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.OperateRecordSortEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.ModuleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.Date;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/3/14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"操作记录信息\")\npublic class OperateRecordDTO extends PageDTO {\n\n    /**\n     * 主键\n     */\n    @ApiModelProperty(\"记录ID\")\n    private Integer id;\n\n    /**\n     * @see ModuleEnum\n     */\n    @ApiModelProperty(\"模块ID\")\n    private Integer moduleId;\n\n    /**\n     * @see OperateTypeEnum\n     */\n    @ApiModelProperty(value = \"操作ID\")\n    private Integer operateId;\n\n    /**\n     * 操作描述\n     */\n    @ApiModelProperty(\"操作内容\")\n    private String  content;\n\n    /**\n     * 操作人  邮箱前缀\n     */\n    @ApiModelProperty(\"操作人\")\n    private String  userOperation;\n\n    /**\n     * 操作起始时间 查询使用\n     */\n    @ApiModelProperty(value = \"开始时间\", dataType = \"Date\")\n    private Date    beginTime;\n\n    /**\n     * 操作截止时间 查询使用\n     */\n    @ApiModelProperty(value = \"结束时间\", dataType = \"Date\")\n    private Date    endTime;\n\n    /**\n     * 触发方式\n     * @see com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum\n     */\n    @ApiModelProperty(\"触发方式\")\n    private Integer triggerWayId;\n    /**\n     * 应用id\n     */\n    @ApiModelProperty(\"项目\")\n    private String  projectName;\n    @ApiModelProperty(\"bizId\")\n    private String  bizId;\n    /**\n     * @see OperateRecordSortEnum\n     */\n    @ApiModelProperty(value = \"排序字段\", example = \"id或者operateTime\")\n    private String  sortTerm;\n\n    @ApiModelProperty(value = \"是否降序排序（默认降序）\", dataType = \"Boolean\", required = false)\n    private Boolean orderByDesc = true;\n    @ApiModelProperty(hidden = true)\n    private String  sortType;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/stats/ClusterLogicStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.stats;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@NoArgsConstructor\n@AllArgsConstructor\n@Data\npublic class ClusterLogicStats {\n    //文档数量\n    private Long docCount;\n    //已使用存储大小\n    private Long usageFsBytes;\n    //剩余存储大小\n    private Long freeInBytes;\n    //总存储大小\n    private Long totalFsBytes;\n    // cpu使用率\n    private Double cpuUsedPresent;\n    //节点主机地址\n    private String host;\n    //节点名称\n    private String nodeName;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/task/OpTaskDTO.java",
    "content": "/*\n * Copyright (c) 2015, WINIT and/or its affiliates. All rights reserved. Use, Copy is subject to authorized license.\n */\npackage com.didichuxing.datachannel.arius.admin.common.bean.dto.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.Date;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * OpTask Vo 对象\n * \n * @author fengqiongfeng\n * @date 2020-12-21\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class OpTaskDTO extends BaseDTO {\n\n    private static final long serialVersionUID = 1L;\n\n    private Integer           id;\n\n    @ApiModelProperty(\"标题\")\n    private String            title;\n\n    @ApiModelProperty(\"任务类型\")\n    private Integer           taskType;\n\n    @ApiModelProperty(\"业务数据主键\")\n    private String            businessKey;\n\n    /**\n     * 任务状态\n     * success:成功 failed:失败\n     * running:执行中 waiting:等待\n     * cancel:取消 pause:暂停\n     */\n    @ApiModelProperty(\"任务状态\")\n    private String            status;\n\n    @ApiModelProperty(\"创建人\")\n    private String            creator;\n\n    @ApiModelProperty(\"创建时间\")\n    private Date              createTime;\n\n    @ApiModelProperty(\"更新时间\")\n    private Date              updateTime;\n\n    @ApiModelProperty(\"标记删除 \")\n    private Boolean           deleteFlag;\n\n    @ApiModelProperty(\"expandData\")\n    private String            expandData;\n\n    @ApiModelProperty(\"数据中心\")\n    private String            dataCenter;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/task/OpTaskProcessDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n *\n * @author d06679\n * @date 2018/10/25\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"任务处理信息\")\npublic class OpTaskProcessDTO extends BaseDTO {\n\n    @ApiModelProperty(\"任务id\")\n    private Integer taskId;\n\n    /**\n     * 执行状态\n     *   success     成功\n     *   failed      失败\n     *   running    执行中\n     *   waiting     等待\n     *   cancel      取消\n     *   pause      暂停\n     */\n    @ApiModelProperty(\"执行状态\")\n    private String  status;\n\n    @ApiModelProperty(\"任务步骤\")\n    private Integer taskProgress;\n\n    @ApiModelProperty(\"扩展信息\")\n    private String  expandData;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/task/OpTaskQueryDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\nimport java.util.Date;\n\n@Data\n@ApiModel(description = \"任务中心查询分页列表查询条件\")\npublic class OpTaskQueryDTO extends PageDTO {\n    @ApiModelProperty(value = \"标题（模糊）\", dataType = \"String\")\n    private String title;\n    @ApiModelProperty(value = \"最近创建时间start（时间戳ms）\", dataType = \"Date\")\n    private Date startTime;\n\n    @ApiModelProperty(value = \"最近创建时间end（时间戳ms）\", dataType = \"Date\")\n    private Date   endTime;\n\n    @ApiModelProperty(value = \"排序信息（精确）,排序字段 创建时间create_time,更新时间update_time\", dataType = \"String\")\n    private String  sortTerm;\n\n    @ApiModelProperty(value = \"是否逆序排序（默认逆序）\", dataType = \"Boolean\")\n    private Boolean orderByDesc = true;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/task/ecm/EcmTaskDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.task.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"ECM任务信息\")\npublic class EcmTaskDTO extends BaseDTO {\n\n    private static final long  serialVersionUID = 1L;\n\n    @ApiModelProperty(\"ID主键自增\")\n    private Long               id;\n\n    @ApiModelProperty(\"标题\")\n    private String             title;\n\n    @ApiModelProperty(\"工单ID\")\n    private Long               workOrderId;\n\n    @ApiModelProperty(\"物理集群ID\")\n    private Long               physicClusterId;\n\n    @ApiModelProperty(\"集群节点角色\")\n    private String             clusterNodeRole;\n\n    @ApiModelProperty(\"状态\")\n    private String             status;\n\n    @ApiModelProperty(\"工单数据\")\n    private List<EcmParamBase> ecmParamBaseList;\n\n    @ApiModelProperty(\"docker容器云/host 物理机\")\n    private Integer            type;\n\n    /**\n     * @see EcmTaskTypeEnum\n     */\n    @ApiModelProperty(\"任务类型\")\n    private Integer            orderType;\n\n    @ApiModelProperty(\"插件创建人\")\n    private String             creator;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/ConsoleTemplateRateLimitDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@NoArgsConstructor\n@Data\n@ApiModel(\"索引模板限流调整\")\npublic class ConsoleTemplateRateLimitDTO {\n    @ApiModelProperty(\"索引模板ID\")\n    private Integer logicId;\n    @ApiModelProperty(\"索引模板当前限流值\")\n    private Integer curRateLimit;\n    @ApiModelProperty(\"索引模板调整后限流值\")\n    private Integer adjustRateLimit;\n    @ApiModelProperty(\"限流变更人\")\n    private String  submitor;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/ConsoleTemplateSchemaDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport java.util.List;\nimport java.util.Set;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.Field;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-06-13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引schema信息\")\npublic class ConsoleTemplateSchemaDTO extends BaseDTO {\n\n    @ApiModelProperty(\"索引ID\")\n    private Integer                 logicId;\n\n    /**\n     * mapping信息 手动设置的\n     */\n    @ApiModelProperty(\"索引schema列表信息\")\n    private List<Field>             fields;\n\n    @ApiModelProperty(\"索引mapping删除字段列表\")\n    private Set<String>             removeFieldNames;\n\n    @ApiModelProperty(\"索引schemajson信息\")\n    private List<AriusTypeProperty> typeProperties;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/ConsoleTemplateSchemaOptimizeDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.MappingOptimizeItem;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-06-13\n */\n@Data\n\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引schema信息\")\npublic class ConsoleTemplateSchemaOptimizeDTO extends BaseDTO {\n\n    @ApiModelProperty(\"索引ID\")\n    private Integer                   logicId;\n\n    @ApiModelProperty(\"索引mapping优化信息\")\n    private List<MappingOptimizeItem> items;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/ConsoleTemplateSettingDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusIndexTemplateSetting;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引模板setting信息\")\npublic class ConsoleTemplateSettingDTO extends BaseDTO {\n\n    @ApiModelProperty(\"索引ID\")\n    private Integer                   logicId;\n\n    @ApiModelProperty(\"索引分词器\")\n    private AriusIndexTemplateSetting setting;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/ConsoleTemplateUpdateDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679, chengxiang\n * @date 2019/3/29\n * @update 2022/5/26\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板修改信息\")\npublic class ConsoleTemplateUpdateDTO extends BaseDTO {\n\n    @ApiModelProperty(\"模板ID\")\n    private Integer id;\n\n    @ApiModelProperty(\"数据类型（0:系统 1:日志；2:用户上报；3:RDS；6：离线导入）\")\n    private Integer dataType;\n\n  \n\n    @ApiModelProperty(\"备注\")\n    private String  desc;\n    @ApiModelProperty(\"保存天数, 单位天\")\n    private Integer expireTime;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/DCDRMasterSlaveSwitchDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 12/14/21\n */\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(value = \"DCDRMasterSlaveSwitchDTO\", description = \"DCDR主从切换\")\npublic class DCDRMasterSlaveSwitchDTO extends BaseDTO {\n    @ApiModelProperty(\"切换类型 1 平滑 2 强制\")\n    private Integer    type;\n\n    @ApiModelProperty(\"主模板Id列表\")\n    private List<Long> templateIds;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/IndexTemplateConfigDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板配置信息\")\npublic class IndexTemplateConfigDTO extends BaseDTO {\n\n    @ApiModelProperty(\"模板ID\")\n    private Long    id;\n\n    @ApiModelProperty(\"模板ID\")\n    private Integer logicId;\n\n    @ApiModelProperty(\"索引存储分离开关\")\n    private Integer isSourceSeparated;\n\n    @ApiModelProperty(\"tps因子\")\n    private Double  adjustTpsFactor;\n\n    @ApiModelProperty(\"shard资源因子\")\n    private Double  adjustShardFactor;\n\n    @ApiModelProperty(\"动态限流开关\")\n    private Integer dynamicLimitEnable;\n\n    @ApiModelProperty(\"mapping优化开关\")\n    private Integer mappingImproveEnable;\n\n    @ApiModelProperty(\"indexRollover功能\")\n    private Boolean disableIndexRollover;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/IndexTemplateDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.PageDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/10\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"逻辑模板信息\")\npublic class IndexTemplateDTO extends PageDTO {\n\n    @ApiModelProperty(\"模板ID\")\n    private Integer                   id;\n\n    @ApiModelProperty(\"模板名字\")\n    private String                    name;\n\n    @ApiModelProperty(\"索引应用ID\")\n    private Integer                   projectId;\n\n    @ApiModelProperty(\"数据类型（0:系统 1:日志；2:上报；3:rds数据；4:离线导入数据\")\n    private Integer                   dataType;\n\n    @ApiModelProperty(\"时间后缀,索引滚动格式\")\n    private String                    dateFormat;\n\n    @ApiModelProperty(\"数据中心\")\n    private String                    dataCenter;\n\n    @ApiModelProperty(\"保存天数, 单位天\")\n    private Integer                   expireTime;\n\n    @ApiModelProperty(\"热数据保存天数, 单位天\")\n    private Integer                   hotTime;\n\n   \n\n    @ApiModelProperty(\"时间分区字段\")\n    private String                    dateField;\n\n    @ApiModelProperty(\"时间字段格式\")\n    private String                    dateFieldFormat;\n\n    @Deprecated\n    @ApiModelProperty(\"主键字段：后续下线，无需使用\")\n    private String                    idField;\n\n    @Deprecated\n    @ApiModelProperty(\"routing字段：后续下线，无需使用\")\n    private String                    routingField;\n\n    @ApiModelProperty(\"表达式\")\n    private String                    expression;\n\n    @ApiModelProperty(\"描述\")\n    private String                    desc;\n\n    @ApiModelProperty(\"配额\")\n    private Double                    quota;\n\n    @ApiModelProperty(\"ingestPipeline\")\n    private String                    ingestPipeline;\n\n    @ApiModelProperty(\"preCreateFlags\")\n    private Boolean                   preCreateFlags;\n\n    @ApiModelProperty(\"shardNum\")\n    private Integer                   shardNum;\n\n    @ApiModelProperty(\"disableSourceFlags，禁用索引_source标识\")\n    private Boolean                   disableSourceFlags;\n\n    @ApiModelProperty(\"disableIndexRollover，禁用indexRollover\")\n    private Boolean                   disableIndexRollover;\n\n    /**\n     * 写入限流值，\n     * writeRateLimit = 0 禁止写入，\n     * writeRateLimit = -1 不限流，\n     * writeRateLimit = 123 具体的写入tps限流值，即单台client每秒写入123条文档\n     */\n    @ApiModelProperty(\"writeRateLimit\")\n    private Integer                   writeRateLimit;\n\n    /**\n     * 是否禁读\n     */\n    @ApiModelProperty(\"是否禁读\")\n    private Boolean                   blockRead;\n\n    /**\n     * 是否禁写\n     */\n    @ApiModelProperty(\"是否禁写\")\n    private Boolean                   blockWrite;\n\n    @ApiModelProperty(\"逻辑集群id\")\n    private Long                      resourceId;\n\n    @ApiModelProperty(\"位点差\")\n    private Long                      checkPointDiff;\n\n    @ApiModelProperty(\"是否已创建dcdr\")\n    private Boolean                   hasDCDR;\n\n    @ApiModelProperty(\"服务等级\")\n    private Integer                   level;\n\n    @ApiModelProperty(\"物理模板信息\")\n    private List<IndexTemplatePhyDTO> physicalInfos;\n\n    @ApiModelProperty(\"开启服务\")\n    private String                    openSrv;\n\n    @ApiModelProperty(\"可用磁盘容量\")\n    private Double                    diskSize;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/IndexTemplatePhyDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/10\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"物理模板信息\")\npublic class IndexTemplatePhyDTO extends BaseDTO {\n\n    @ApiModelProperty(\"模板ID\")\n    private Long                      id;\n\n    @ApiModelProperty(\"逻辑模板id\")\n    private Integer                   logicId;\n\n    @ApiModelProperty(\"模板名称\")\n    private String                    name;\n\n    @ApiModelProperty(\"表达式\")\n    private String                    expression;\n\n    @ApiModelProperty(\"物理集群名字\")\n    private String                    cluster;\n\n    @ApiModelProperty(\"资源是否是默认物理索引\")\n    private Boolean                   defaultWriterFlags;\n\n    @ApiModelProperty(\"组ID\")\n    private String                    groupId;\n\n    @ApiModelProperty(\"rack\")\n    private String                    rack;\n\n    @ApiModelProperty(\"shard\")\n    private Integer                   shard;\n\n    @ApiModelProperty(\"shardRouting\")\n    private Integer                   shardRouting;\n\n    @ApiModelProperty(\"版本\")\n    private Integer                   version;\n\n    @ApiModelProperty(\"角色(1:主；2:从)\")\n    private Integer                   role;\n\n    @ApiModelProperty(\"状态(1:常规；-1:索引删除中；-2:删除)\")\n    private Integer                   status;\n\n    @ApiModelProperty(\"配置信息\")\n    private String                    config;\n\n    /**\n     * {\n     *     \"type\": {\n     *         \"dynamic_templates\": [\n     *             {\n     *                 \"key1\": {}\n     *             }\n     *         ],\n     *         \"properties\": {\n     *             \"key3\": {\n     *                 \"type\": \"key4\"\n     *             }\n     *         }\n     *     }\n     * }\n     */\n    @ApiModelProperty(\"mapping信息\")\n    private String                    mappings;\n    /**\n     *\n     * {\n     *     \"index.number_of_replicas\": 0,\n     *     \"index.translog.durability\": \"request\",\n     *     \"analysis\": {\n     *         \"analyzer\": {\n     *             \"my_custom_analyzer\": {\n     *                  ...\n     *             }\n     *         },\n     *         \"tokenizer\": {\n     *         }...\n     *     }\n     * }\n     */\n    @ApiModelProperty(\"索引模板自定义settings\")\n    private String                    settings;\n\n    @ApiModelProperty(\"逻辑集群ID\")\n    private Long                      resourceId;\n\n    /**\n     * 写入限流值，\n     * writeRateLimit = 0 禁止写入，\n     * writeRateLimit = -1 不限流，\n     * writeRateLimit = 123 具体的写入tps限流值，即单台client每秒写入123条文档\n     */\n    @ApiModelProperty(\"写入限流值\")\n    private Integer                   writeRateLimit;\n\n    //todo: delete this annoying field\n    @ApiModelProperty(\"物理模板列表\")\n    private List<IndexTemplatePhyDTO> physicalInfos;\n\n    @ApiModelProperty(\"regionId\")\n    private Integer                   regionId;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/IndexTemplateWithCreateInfoDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/26\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"创建逻辑模板DTO\")\npublic class IndexTemplateWithCreateInfoDTO extends IndexTemplateDTO {\n\n    @ApiModelProperty(\"是否分区\")\n    private Boolean cyclicalRoll;\n\n    @ApiModelProperty(\"mapping\")\n    private String  mapping;\n\n    @ApiModelProperty(\"setting信息\")\n    private String  setting;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/TemplateClearDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-06-13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引清理信息\")\npublic class TemplateClearDTO extends BaseDTO {\n\n    @ApiModelProperty(\"索引ID\")\n    private Integer      logicId;\n\n    @ApiModelProperty(\"需要清理的索引列表\")\n    private List<String> delIndices;\n\n    @ApiModelProperty(\"删除条件\")\n    private String       delQueryDsl;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/TemplateConditionDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-10-12\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"条件查询索引模板信息\")\npublic class TemplateConditionDTO extends IndexTemplateDTO {\n    /**\n     * @see ProjectTemplateAuthEnum\n     */\n    @ApiModelProperty(\"当前项目拥有的权限（1:管理；2:读写；3:读; -1无权限）\")\n    private Integer      authType;\n\n    @ApiModelProperty(\"所属集群\")\n    private List<String> clusterPhies;\n\n    @ApiModelProperty(\"排序字段 block_read(禁读)、block_write(禁写)\")\n    private String       sortTerm;\n    @ApiModelProperty(\"模板健康度\")\n    private Integer health;\n\n    @ApiModelProperty(value = \"是否降序排序（默认降序）\", dataType = \"Boolean\", required = false)\n    private Boolean      orderByDesc = true;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/TemplatePhysicalCopyDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/4/3\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板复制信息\")\npublic class TemplatePhysicalCopyDTO extends BaseDTO {\n\n    @ApiModelProperty(\"物理模板id\")\n    private Long    physicalId;\n\n    @ApiModelProperty(\"目标集群\")\n    private String  cluster;\n\n    @ApiModelProperty(\"shard个数\")\n    private Integer shard;\n\n    @ApiModelProperty(\"regionId\")\n    private Integer regionId;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/TemplatePhysicalDCDRDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.ToString;\n\nimport java.util.List;\n\n/**\n * @author d06679\n * @date 2019/4/3\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ToString\n@ApiModel(description = \"模板dcdr链路信息\")\npublic class TemplatePhysicalDCDRDTO extends BaseDTO {\n\n    @ApiModelProperty(\"物理模板ID\")\n    private Long         physicalId;\n\n    @ApiModelProperty(\"目标集群\")\n    private String       replicaCluster;\n\n    @ApiModelProperty(\"物理模板ID列表\")\n    private List<Long>   physicalIds;\n\n    @ApiModelProperty(\"目标集群列表\")\n    private List<String> replicaClusters;\n\n    @ApiModelProperty(\"模板对应的索引上的dcdr链路是否需要删除\")\n    private Boolean      deleteIndexDcdr;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/TemplatePhysicalUpgradeDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/4/3\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板升级信息\")\npublic class TemplatePhysicalUpgradeDTO extends BaseDTO {\n\n    @ApiModelProperty(\"物理模板id\")\n    private Long    physicalId;\n\n    @ApiModelProperty(\"模板当前的shard个数\")\n    private Integer shard;\n\n    @ApiModelProperty(\"模板的rack\")\n    private String  rack;\n\n    @ApiModelProperty(\"版本\")\n    private Integer version;\n\n    @ApiModelProperty(\"逻辑模板id\")\n    private Long    logicId;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/TemplateSettingDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateSettingDTO extends BaseDTO {\n\n    @ApiModelProperty(\"索引ID\")\n    private Integer logicId;\n\n    @ApiModelProperty(\"是否开启副本\")\n    private boolean cancelCopy;\n\n    @ApiModelProperty(\"是否开启异步translog\")\n    private boolean asyncTranslog;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/alias/ConsoleAliasDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板别名\")\npublic class ConsoleAliasDTO extends BaseDTO {\n\n    @ApiModelProperty(\"模板别名名称\")\n    private String     alias;\n\n    @ApiModelProperty(\"别名过滤器\")\n    private JSONObject filter;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/alias/ConsoleLogicTemplateAliasesDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引模板别名创建信息\")\npublic class ConsoleLogicTemplateAliasesDTO extends BaseDTO {\n    @ApiModelProperty(\"索引ID\")\n    private Integer               logicId;\n\n    @ApiModelProperty(\"索引别名列表信息\")\n    private List<ConsoleAliasDTO> aliases;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/alias/ConsoleLogicTemplateDeleteAliasesDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"删除逻辑模板别名列表DTO\")\npublic class ConsoleLogicTemplateDeleteAliasesDTO implements Serializable {\n    @ApiModelProperty(\"索引ID\")\n    private Integer      logicId;\n\n    @ApiModelProperty(\"索引别名列表信息\")\n    private List<String> aliases;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/alias/ConsoleTemplateAliasSwitchDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias;\n\nimport java.util.List;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n@Data\n@ApiModel(value = \"索引别名切换\")\npublic class ConsoleTemplateAliasSwitchDTO {\n    @ApiModelProperty(\"索引应用ID\")\n    private Integer      projectId;\n    @ApiModelProperty(\"别名名称\")\n    private String       aliasName;\n    @ApiModelProperty(\"需要添加别名的索引\")\n    private List<String> addAliasIndices;\n    @ApiModelProperty(\"需要删除别名的索引\")\n    private List<String> delAliasIndices;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/alias/IndexTemplateAliasDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@ApiModel(description = \"模板别名信息\")\npublic class IndexTemplateAliasDTO extends BaseDTO {\n\n    @ApiModelProperty(\"逻辑模板ID\")\n    private Integer logicId;\n\n    @ApiModelProperty(\"别名名称\")\n    private String  name;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/srv/BaseTemplateSrvOpenDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\n\n/**\n * @author chengxiang\n * @date 2022/5/19\n */\npublic class BaseTemplateSrvOpenDTO extends BaseDTO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/srv/ColdSrvOpenDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/19\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ColdSrvOpenDTO extends BaseTemplateSrvOpenDTO {\n\n    /**\n     * 冷节点保存天数\n     */\n    private Integer coldSaveDays;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/template/srv/TemplateQueryDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/18\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板分页查询条件\")\npublic class TemplateQueryDTO extends IndexTemplateDTO {\n\n    @ApiModelProperty(\"所属物理集群\")\n    private String cluster;\n    @ApiModelProperty(\"模板健康度\")\n    private Integer health;\n    @ApiModelProperty(\"是否具备 dcdr\")\n    private Boolean hasDCDR;\n    @ApiModelProperty(\"排序字段 id、（主从位点差）check_point_diff、（模板健康度）health\")\n    private String  sortTerm;\n    \n    @ApiModelProperty(value = \"是否降序排序（默认降序）\", dataType = \"Boolean\", required = false)\n    private Boolean orderByDesc = true;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/workorder/WorkOrderDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"工单内容\")\npublic class WorkOrderDTO extends BaseDTO {\n\n    private static final long serialVersionUID = -4536847390271645624L;\n\n    @ApiModelProperty(\"工单类型（路径参数）\")\n    private String            type;\n\n    @ApiModelProperty(\"工单内容\")\n    private Object            contentObj;\n\n    @ApiModelProperty(\"提交人\")\n    private String            submitor;\n\n    @ApiModelProperty(\"提交projectID\")\n    private Integer           submitorProjectId;\n\n    @ApiModelProperty(\"数据中心\")\n    private String            dataCenter;\n\n    @ApiModelProperty(\"描述\")\n    private String            description;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/workorder/WorkOrderProcessDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n *\n * @author d06679\n * @date 2018/10/25\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"工单处理信息\")\npublic class WorkOrderProcessDTO {\n\n    @ApiModelProperty(\"工单id\")\n    private Long    orderId;\n\n    @ApiModelProperty(\"审批结果，agree/disagree/submit\")\n    private String  outcome;\n\n    @ApiModelProperty(\"审批意见\")\n    private String  comment;\n\n    @ApiModelProperty(\"审批人\")\n    private String  assignee;\n\n    @ApiModelProperty(\"审批人projectId\")\n    private Integer assigneeProjectId;\n\n    @ApiModelProperty(\"是否自动审批\")\n    private Boolean checkAuthority;\n\n    @ApiModelProperty(\"业务参数\")\n    private Object  contentObj;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/dto/workorder/WorkOrderTaskDetailDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"工单任务详细\")\n@Deprecated\npublic class WorkOrderTaskDetailDTO extends BaseDTO {\n\n    @ApiModelProperty(\"ID\")\n    private Long    id;\n\n    @ApiModelProperty(\"工单任务ID\")\n    private Long    workOrderTaskId;\n\n    @ApiModelProperty(\"所属角色\")\n    private String  role;\n\n    @ApiModelProperty(\"节点名称/主机名称\")\n    private String  hostname;\n\n    @ApiModelProperty(\"分组\")\n    private Integer grp;\n\n    @ApiModelProperty(\"顺序\")\n    private Integer idx;\n\n    @ApiModelProperty(\"状态\")\n    private String  status;\n\n    @ApiModelProperty(\"容器云/物理机 接口返回任务ID\")\n    private Long    taskId;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/BaseEntity.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * @author d06679\n * @date 2019/3/22\n */\n@Data\npublic class BaseEntity implements Serializable {\n    protected Date createTime;\n\n    protected Date updateTime;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/GlobalParam.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity;\n\npublic class GlobalParam {\n\n    private GlobalParam() {\n    }\n\n    public static ThreadLocal<String>  CURRENT_USER       = new InheritableThreadLocal<>();\n    public static ThreadLocal<Integer> CURRENT_PROJECT_ID = new InheritableThreadLocal<>();\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/MulityTypeTemplatesInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity;\n\nimport com.google.common.collect.Maps;\nimport lombok.Data;\n\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * 多type索引信息\n */\n@Data\npublic class MulityTypeTemplatesInfo {\n\n    /**\n     * 多type索引映射,目标索引到源索引映射\n     */\n    private Map<String/*destTemplateName*/, String/*sourceTemplateName*/>      dest2SourceTemplateMap = Maps\n        .newHashMap();\n\n    /**\n     * 多type索引映射,源索引映射到目标索引\n     */\n    private Map<String/*sourceTemplateName*/, Set<String/*destTemplateName*/>> source2DestTemplateMap = Maps\n        .newHashMap();\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/access/TemplateAccessDateRange.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.access;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/3/4 下午4:29\n * @modified By D10865\n *\n * 索引模板维度查询次数统计请求参数\n *\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@Deprecated\npublic class TemplateAccessDateRange {\n\n    /**\n     * 统计起始时间\n     */\n    private String startDate;\n    /**\n     * 统计结束时间\n     */\n    private String endDate;\n\n    /**\n     * 是否有效\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    public boolean isValid() {\n        return !(StringUtils.isBlank(startDate) || StringUtils.isBlank(endDate));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/access/TemplateAccessDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.access;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/3/4 下午5:34\n * @modified By D10865\n *\n * 某个索引模板具体索引查询次数统计请求参数\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateAccessDetail {\n    /**\n     * 集群名称\n     */\n    private String clusterName;\n    /**\n     * 索引模板名称\n     */\n    private String templateName;\n    /**\n     * 统计日期\n     */\n    private String countDate;\n\n    /**\n     * 是否有效\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    public boolean isValid() {\n        return !(StringUtils.isBlank(templateName) || StringUtils.isBlank(countDate)\n                 || StringUtils.isBlank(clusterName));\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/access/TemplateAccessHistory.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.access;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/3/4 下午8:07\n * @modified By D10865\n *\n * 某个索引模板历史查询次数统计请求参数\n *\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateAccessHistory {\n    /**\n     * 集群名称\n     */\n    private String clusterName;\n    /**\n     * 索引模板名称\n     */\n    private String templateName;\n\n    /**\n     * 是否有效\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    public boolean isValid() {\n        return !(StringUtils.isBlank(templateName) || StringUtils.isBlank(clusterName));\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/access/UserAccessTemplateDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.access;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/3/4 下午5:34\n * @modified By D10865\n *\n * 某个索引模板具体索引查询次数统计请求参数\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class UserAccessTemplateDetail {\n\n    /**\n     * 索引模板主键\n     */\n    private Integer templateId;\n    /**\n     * 统计日期\n     */\n    private String  countDate;\n\n    /**\n     * 是否有效\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    public boolean isValid() {\n        return !(templateId == null || StringUtils.isBlank(countDate));\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/AriusMetaJobClusterDistribute.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster;\n\nimport java.util.Date;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author ohushenglin_v\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class AriusMetaJobClusterDistribute {\n    /**\n     * 主键id\n     */\n    private Long    id;\n    /**\n     * 集群id\n     */\n    private Integer clusterId;\n    /**\n     * 集群名称\n     */\n    private String  cluster;\n    /**\n     * 集群数据中心：us01/cn\n     */\n    private String  dataCentre;\n    /**\n     * motitor集群host\n     */\n    private String  monitorHost;\n    /**\n     * motitor监控时间\n     */\n    private Date    monitorTime;\n    /**\n     * 创建时间\n     */\n    private Date    gmtCreate;\n    /**\n     * 更新时间\n     */\n    private Date    gmtModify;\n    /**\n     * 修改记录使用,monitorHost字段用于校验是否被修改过\n     */\n    private String  destMonitorHost;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/ClusterLogic.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterLogic extends BaseEntity implements Comparable<ClusterLogic> {\n\n    /**\n     * 主键\n     */\n    private Long    id;\n\n    /**\n     * 名字\n     */\n    private String  name;\n\n    /**\n     * 类型\n     * @see ClusterResourceTypeEnum\n     */\n    private Integer type;\n\n    /**\n     * 所属project ID\n     */\n    private Integer projectId;\n\n    /**\n     * 所属projectName\n     */\n    private String projectName;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n\n    /**\n     * dataNode的规格\n     */\n    private String  dataNodeSpec;\n\n    /**\n     * dataNode的个数\n     */\n    private Integer dataNodeNum;\n\n    /**\n     * 备注\n     */\n    private String  memo;\n\n    /**\n     * 独立资源的大小\n     */\n    private Double  quota;\n\n    /**\n     * 服务等级\n     */\n    private Integer level;\n\n    /**\n     * 配置\n     */\n    private String  configJson;\n\n    /**\n     * 健康状态 1 green 2 yellow 3 red -1 未知\n     */\n    private Integer health;\n\n    /**\n     * 磁盘使用率\n     */\n    private Double diskUsagePercent;\n\n    /**\n     * 磁盘总量\n     */\n    private Long diskTotal;\n\n    /**\n     * 磁盘使用量\n     */\n    private Long diskUsage;\n\n    /**\n     * 集群版本\n     */\n    private String esClusterVersion;\n\n    /**\n     * 数据节点数\n     */\n    private Integer nodeNum;\n\n    @Override\n    public int compareTo(ClusterLogic o) {\n        if (null == o) {\n            return 0;\n        }\n\n        return o.getId().intValue() - this.getId().intValue();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/ClusterLogicContext.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster;\n\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-06-08\n */\n@Data\n@Builder\n@NoArgsConstructor\n@AllArgsConstructor\n@Deprecated\npublic class ClusterLogicContext {\n\n    /*****************************************clusterLogicInfo*************************************/\n\n    private Long         clusterLogicId;\n\n    private String       clusterLogicName;\n\n    private Integer      logicClusterType;\n\n    /*****************************************clusterPhyInfo***************************************/\n\n    private Integer      associatedPhyNumMax;\n\n    private Integer      associatedPhyNum;\n\n    private List<String> associatedClusterPhyNames;\n\n    /*****************************************clusterPhyNodeInfo***********************************/\n\n    private Integer      associatedDataNodeNum;\n\n    private List<String> associatedDataNodeIps;\n\n    /*****************************************regionInfo********************************************/\n\n    private List<Long>   associatedRegionIds;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/ClusterLogicStatis.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 基本集群状态信息\n * @author wangshu\n * @date 2020/10/04\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterLogicStatis extends BaseEntity {\n    /**\n     * 物理集群状态\n     */\n    private String status;\n\n    /**\n     * docNu\n     */\n    private double docNu;\n\n    /**\n     * 总的磁盘容量\n     */\n    private double totalDisk;\n\n    /**\n     * 已使用的磁盘容量\n     */\n    private double usedDisk;\n\n    /**\n     * 索引数量\n     */\n    private long   indexNu;\n\n    /**\n     * 集群名称\n     */\n    private String name;\n\n    /**\n     * 集群id\n     */\n    private long   id;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/ClusterNodeInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/06/08\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterNodeInfo {\n\n    private String nodeSet;\n\n    private String nodeName;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/ClusterPhy.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport java.util.List;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 物理集群\n * @author ohushenglin_v\n * @date 2022-05-10\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterPhy extends BaseEntity implements Comparable<ClusterPhy> {\n\n    /**\n     * 集群id\n     */\n    private Integer               id;\n\n    /**\n     * 集群名字\n     */\n    private String                cluster;\n\n    /**\n     * 描述\n     */\n    private String                desc;\n\n    /**\n     * TCP读地址\n     */\n    private String                readAddress;\n\n    /**\n     * TCP写地址\n     */\n    private String                writeAddress;\n\n    /**\n     * http读地址\n     */\n    private String                httpAddress;\n\n    /**\n     * http写地址\n     */\n    private String                httpWriteAddress;\n\n    /**\n     * 集群类型\n     * @see ESClusterTypeEnum\n     */\n    private Integer               type;\n\n    /**\n     * 集群展示用属性标签，如「集群所属资源类型」等等\n     */\n    private String                tags;\n\n    /**\n     * 数据中心\n     */\n    private String                dataCenter;\n\n    /**\n     * 机房\n     */\n    private String                idc;\n\n    /**\n     * 服务等级\n     */\n    private Integer               level;\n\n    /**\n     * es版本\n     */\n    private String                esVersion;\n\n    /**\n     * 配置包Id\n     */\n    private Long                  cfgId;\n\n    /**\n     * 插件Id列表\n     */\n    private String                plugIds;\n\n    /**\n     * 程序包Id\n     */\n    private Long                  packageId;\n\n    /**\n     * 镜像名称\n     */\n    private String                imageName;\n\n    /**\n     * odin 节点\n     */\n    private String                nsTree;\n\n    /**\n     *节点数量\n     */\n    private Integer               pidCount;\n    /**\n     * 机器规格\n     */\n    private String                machineSpec;\n\n\n    /**\n     * 集群密码\n     */\n    private String                password;\n\n    /**\n     * 集群创建人\n     */\n    private String                creator;\n\n    /**\n     * ES的角色\n     */\n    private List<ClusterRoleInfo> clusterRoleInfos;\n\n    /**\n     * ES的角色的机器节点\n     */\n    private List<ClusterRoleHost> clusterRoleHosts;\n\n    /**\n     * client运行模式，读写共享还是读写分离\n     */\n    private Integer               runMode;\n\n    /**\n     * 读写分离时候，指定action（获取写client）\n     */\n    private String                writeAction;\n\n    /**\n     * 集群状态\n     */\n    private Integer               health;\n\n    /**\n     * 活跃的分片数目\n     */\n    private Long                  activeShardNum;\n\n    private Long                  diskTotal;\n    private Long                  diskUsage;\n    private Double                diskUsagePercent;\n\n    /**\n     * IaaS平台类型\n     */\n    private String                platformType;\n\n    /**\n     * 集群资源类型(-1 未知 1 共享 2 独立 3 独享)\n     * @see ClusterResourceTypeEnum\n     */\n    private Integer               resourceType;\n\n    /**\n     * 网关地址\n     */\n    private String                gatewayUrl;\n\n    /**\n     * kibana外链地址\n     */\n    private String                    kibanaAddress;\n\n    /**\n     * cerebro外链地址\n     */\n    private String                    cerebroAddress;\n\n    /**\n     * 代理地址\n     */\n    private String                    proxyAddress;\n\n    @Override\n    public int compareTo(ClusterPhy o) {\n        if (null == o) {\n            return 0;\n        }\n\n        return o.getId().intValue() - this.getId().intValue();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/ClusterPhyContext.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster;\n\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-06-08\n */\n@Data\n@Builder\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterPhyContext {\n\n    private Long          clusterPhyId;\n\n    private String        clusterName;\n\n    /*****************************************projectid***********************************/\n    private List<String>  associatedProjectNames;\n\n    private List<Integer> associatedProjectIds;\n\n    /*****************************************clusterLogicInfo***********************************/\n\n    private Integer       associatedLogicNum;\n\n    private Integer       associatedLogicNumMax;\n\n    private List<Long>    associatedClusterLogicIds;\n\n    /*****************************************clusterPhyNodeInfo***********************************/\n\n    private Integer       associatedDataNodeNum;\n\n    private List<String>  associatedDataNodeIps;\n\n    private List<String>  associatedNodeIps;\n\n    /*****************************************regionInfo********************************************/\n\n    private List<Long>    associatedRegionIds;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/ecm/ClusterRoleHost.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterRoleHost extends BaseEntity {\n\n    private Long    id;\n\n    /**\n    * elastic_cluster外键ID\n    */\n    private Long    roleClusterId;\n\n    /**\n    * 主机名\n    */\n    private String  hostname;\n\n    /**\n     * IP\n     */\n    private String  ip;\n\n    /**\n     * 集群名称\n     */\n    private String  cluster;\n\n    /**\n     * es进程端口\n     */\n    private String  port;\n\n    /**\n     * 1data   2client    3master   4tribe\n     * @see ESClusterNodeRoleEnum\n     */\n    private Integer role;\n\n    /**\n     * 1 在线    2 离线   3 故障\n     * @see ESClusterNodeStatusEnum\n     */\n    private Integer status;\n\n    /**\n     * rack\n     */\n    private String  rack;\n\n    /**\n     * 节点名称\n     */\n    private String  nodeSet;\n\n    /**\n     * 机器规格 例如32C-64G-SSD-6T\n     */\n    private String  machineSpec;\n\n    /**\n     * regionId\n     */\n    private Integer regionId;\n\n    /**\n     * attributes, 逗号分隔  key1:value1,key2:value2\n     */\n    private String  attributes;\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        ClusterRoleHost node = (ClusterRoleHost) o;\n\n        if (!hostname.equals(node.hostname)) {\n            return false;\n        }\n        return cluster.equals(node.cluster);\n\n    }\n\n    @Override\n    public int hashCode() {\n        int result = hostname.hashCode();\n        result = 31 * result + cluster.hashCode();\n        return result;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/ecm/ClusterRoleInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterRoleInfo extends BaseEntity {\n\n    private static final long     serialVersionUID = 1L;\n\n    private Long                  id;\n\n    /**\n     * elastic_cluster外键ID\n     */\n    private Long                  elasticClusterId;\n\n    /**\n     * role集群名称\n     */\n    private String                roleClusterName;\n\n    /**\n     * 集群角色(master-node/data-node/client-node)\n     */\n    private String                role;\n\n    /**\n     * pod数量\n     */\n    private Integer               podNumber;\n\n    /**\n     * 单机实例数\n     */\n    private Integer               pidCount;\n\n    /**\n     * 机器规格\n     */\n    private String                machineSpec;\n\n    /**\n     * ES版本\n     */\n    private String                esVersion;\n\n    /**\n     * 配置包ID\n     */\n    private Integer               cfgId;\n\n    /**\n     * 插件包ID列表\n     */\n    private String                plugIds;\n\n    /**\n     * 标记删除\n     */\n    private Boolean               deleteFlag;\n\n    /**\n     * role所拥有的节点\n     */\n    private List<ClusterRoleHost> clusterRoleHosts;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/ecm/ClusterTag.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterTag {\n\n    /**\n     * 物理集群是「接入」还是「新建」0 接入 1 新建\n     */\n    private Integer createSource;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/ecm/RoleClusterNodeSepc.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@EqualsAndHashCode(of = { \"role\", \"spec\" }, callSuper = false)\npublic class RoleClusterNodeSepc extends BaseEntity {\n\n    /**\n     * 节点角色\n     */\n    private String role;\n\n    /**\n     * 节点规格\n     */\n    private String spec;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/setting/ESClusterGetSettingsAllAction.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESClusterGetSettingsAllAction extends\n                                           Action<ESClusterGetSettingsAllRequest, ESClusterGetSettingsAllResponse, ESClusterGetSettingsAllRequestBuilder> {\n\n    public static final ESClusterGetSettingsAllAction INSTANCE = new ESClusterGetSettingsAllAction();\n    public static final String                        NAME     = \"cluster:settings/get\";\n\n    private ESClusterGetSettingsAllAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESClusterGetSettingsAllResponse newResponse() {\n        return new ESClusterGetSettingsAllResponse();\n    }\n\n    @Override\n    public ESClusterGetSettingsAllRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESClusterGetSettingsAllRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/setting/ESClusterGetSettingsAllRequest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\npublic class ESClusterGetSettingsAllRequest extends ESActionRequest<ESClusterGetSettingsAllRequest> {\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        return new RestRequest(\"GET\", \"/_cluster/settings?include_defaults=true&pretty\", null);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESClusterGetSettingsAllResponse.class);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/setting/ESClusterGetSettingsAllRequestBuilder.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting;\n\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESClusterGetSettingsAllRequestBuilder extends\n                                                   ActionRequestBuilder<ESClusterGetSettingsAllRequest, ESClusterGetSettingsAllResponse, ESClusterGetSettingsAllRequestBuilder> {\n\n    public ESClusterGetSettingsAllRequestBuilder(ElasticsearchClient client, ESClusterGetSettingsAllAction action) {\n        super(client, action, new ESClusterGetSettingsAllRequest());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/cluster/setting/ESClusterGetSettingsAllResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.getsetting.ESClusterGetSettingsResponse;\nimport lombok.AllArgsConstructor;\nimport lombok.NoArgsConstructor;\n\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterGetSettingsAllResponse extends ESClusterGetSettingsResponse {\n\n    @JSONField(name = \"defaults\")\n    private JSONObject defaults;\n\n    public JSONObject getDefaults() {\n        return defaults;\n    }\n\n    public void setDefaults(JSONObject defaults) {\n        this.defaults = defaults;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/config/AriusConfigInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.config;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class AriusConfigInfo extends BaseEntity {\n\n    /**\n     * 主键\n     */\n    private Integer id;\n\n    /**\n     * 配置组\n     */\n    private String  valueGroup;\n\n    /**\n     * 配置项的名称\n     */\n    private String  valueName;\n\n    /**\n     * 配置项的值\n     */\n    private String  value;\n\n    /**\n     * 配置项维度  1 集群   2 模板\n     */\n    private Integer dimension;\n\n    /**\n     * 1 正常  2 禁用  -1 删除\n     */\n    private Integer status;\n\n    /**\n     * 备注\n     */\n    private String  memo;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/AuditDsl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.List;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class AuditDsl {\n    private Integer       projectId;\n\n    private String        userName;\n\n    private List<DslInfo> dslInfos;\n\n    /**\n     * 是否有效\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    public boolean isVaild() {\n        if (projectId == null) {\n            return false;\n        }\n\n        if (StringUtils.isBlank(userName)) {\n            return false;\n        }\n\n        if (CollectionUtils.isEmpty(dslInfos)) {\n            return false;\n        }\n\n        return true;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/DslBase.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/6/21 下午2:47\n * @Modified By\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslBase {\n\n    /**\n     * 应用id\n     */\n    @ApiModelProperty(value = \"应用账号\", example = \"1\")\n    private Integer projectId;\n\n    /**\n     * 查询模板的md5值\n     */\n    @ApiModelProperty(value = \"查询模板MD5\", example = \"V2_EA317B2029682DB83A191CBD797A66FE\")\n    private String  dslTemplateMd5;\n\n    /**\n     * 获取索引主键\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    public String getProjectIdDslTemplateMd5() {\n        return String.format(\"%d_%s\", this.projectId, this.dslTemplateMd5);\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/DslCheckMode.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/6/20 下午5:30\n * @Modified By\n *\n * 修改查询模板黑白名单\n *\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslCheckMode extends DslBase {\n\n    /**\n     * 黑白名单：black、write\n     */\n    private String checkMode;\n\n    public DslCheckMode(Integer projectId, String dslTemplateMd5, String checkMode) {\n        super(projectId, dslTemplateMd5);\n        this.checkMode = checkMode;\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/DslInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport io.swagger.annotations.ApiModel;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/14 下午5:21\n * @modified By D10865\n *\n * dsl查询语句\n *\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(value = \"DslInfo\", description = \"查询语句\")\npublic class DslInfo {\n    /**\n     * 查询语句，如：select * from A\n     */\n    private String dsl;\n    /**\n     * 查询语句描述\n     */\n    private String memo;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/DslQueryLimit.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/6/20 下午4:48\n * @Modified By\n * 查询模板限流值\n */\n@ApiModel(value = \"DslQueryLimit\", description = \"查询语句限流值参数\")\npublic class DslQueryLimit extends DslBase {\n\n    @ApiModelProperty(value = \"查询语句限流值\", example = \"50\")\n    private Double queryLimit;\n\n    public DslQueryLimit() {\n    }\n\n    public DslQueryLimit(Integer projectId, String dslTemplateMd5, Double queryLimit) {\n        super(projectId, dslTemplateMd5);\n        this.queryLimit = queryLimit;\n    }\n\n    public Double getQueryLimit() {\n        return queryLimit;\n    }\n\n    public DslQueryLimit setQueryLimit(Double queryLimit) {\n        this.queryLimit = queryLimit;\n        return this;\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/DslSearchFieldNameMetric.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayJoinPO;\nimport com.google.common.collect.Maps;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.LinkedHashSet;\nimport java.util.Map;\nimport java.util.Set;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslSearchFieldNameMetric {\n\n    /**\n     * 索引名称\n     */\n    private String            indexName;\n    /**\n     * 查询字段统计\n     */\n    private Map<String, Long> selectFieldsCounter  = Maps.newHashMap();\n    /**\n     * 过滤字段统计\n     */\n    private Map<String, Long> whereFieldsCounter   = Maps.newHashMap();\n    /**\n     * 聚合字段统计\n     */\n    private Map<String, Long> groupByFieldsCounter = Maps.newHashMap();\n    /**\n     * 排序字段统计\n     */\n    private Map<String, Long> sortByFieldsCounter  = Maps.newHashMap();\n    /**\n     * 使用的字段集合\n     */\n    private Set<String>       useFieldSet;\n\n    public DslSearchFieldNameMetric(String indexName) {\n        this.indexName = indexName;\n    }\n\n    /**\n     * 获取使用的字段\n     *\n     * @return\n     */\n    public Set<String> getUseFieldSet() {\n        if (useFieldSet == null) {\n            useFieldSet = new LinkedHashSet<>();\n\n            if (selectFieldsCounter != null) {\n                useFieldSet.addAll(selectFieldsCounter.keySet());\n            }\n            if (whereFieldsCounter != null) {\n                useFieldSet.addAll(whereFieldsCounter.keySet());\n            }\n            if (groupByFieldsCounter != null) {\n                useFieldSet.addAll(groupByFieldsCounter.keySet());\n            }\n            if (sortByFieldsCounter != null) {\n                useFieldSet.addAll(sortByFieldsCounter.keySet());\n            }\n        }\n        return useFieldSet;\n    }\n\n    public void mergeSearchFieldNameMetric(DslSearchFieldNameMetric that) {\n        if (that == null) {\n            return;\n        }\n\n        for (Map.Entry<String, Long> entry : that.getSelectFieldsCounter().entrySet()) {\n            if (selectFieldsCounter.containsKey(entry.getKey())) {\n                Long counter = selectFieldsCounter.get(entry.getKey()) + entry.getValue();\n                selectFieldsCounter.put(entry.getKey(), counter);\n            } else {\n                selectFieldsCounter.put(entry.getKey(), entry.getValue());\n            }\n        }\n\n        for (Map.Entry<String, Long> entry : that.getWhereFieldsCounter().entrySet()) {\n            if (whereFieldsCounter.containsKey(entry.getKey())) {\n                Long counter = whereFieldsCounter.get(entry.getKey()) + entry.getValue();\n                whereFieldsCounter.put(entry.getKey(), counter);\n            } else {\n                whereFieldsCounter.put(entry.getKey(), entry.getValue());\n            }\n        }\n\n        for (Map.Entry<String, Long> entry : that.getGroupByFieldsCounter().entrySet()) {\n            if (groupByFieldsCounter.containsKey(entry.getKey())) {\n                Long counter = groupByFieldsCounter.get(entry.getKey()) + entry.getValue();\n                groupByFieldsCounter.put(entry.getKey(), counter);\n            } else {\n                groupByFieldsCounter.put(entry.getKey(), entry.getValue());\n            }\n        }\n\n        for (Map.Entry<String, Long> entry : that.getSortByFieldsCounter().entrySet()) {\n            if (sortByFieldsCounter.containsKey(entry.getKey())) {\n                Long counter = sortByFieldsCounter.get(entry.getKey()) + entry.getValue();\n                sortByFieldsCounter.put(entry.getKey(), counter);\n            } else {\n                sortByFieldsCounter.put(entry.getKey(), entry.getValue());\n            }\n        }\n    }\n\n    public void mergeSearchFieldNameMetric(GatewayJoinPO that) {\n\n        if (that == null) {\n            return;\n        }\n\n        if (that.getSelectFields() != null) {\n            for (Map.Entry<String, Long> entry : that.getSelectFields().entrySet()) {\n                if (selectFieldsCounter.containsKey(entry.getKey())) {\n                    Long counter = selectFieldsCounter.get(entry.getKey()) + entry.getValue();\n                    selectFieldsCounter.put(entry.getKey(), counter);\n                } else {\n                    selectFieldsCounter.put(entry.getKey(), entry.getValue());\n                }\n            }\n        }\n\n        if (that.getWhereFields() != null) {\n            for (Map.Entry<String, Long> entry : that.getWhereFields().entrySet()) {\n                if (whereFieldsCounter.containsKey(entry.getKey())) {\n                    Long counter = whereFieldsCounter.get(entry.getKey()) + entry.getValue();\n                    whereFieldsCounter.put(entry.getKey(), counter);\n                } else {\n                    whereFieldsCounter.put(entry.getKey(), entry.getValue());\n                }\n            }\n        }\n\n        if (that.getGroupByFields() != null) {\n            for (Map.Entry<String, Long> entry : that.getGroupByFields().entrySet()) {\n                if (groupByFieldsCounter.containsKey(entry.getKey())) {\n                    Long counter = groupByFieldsCounter.get(entry.getKey()) + entry.getValue();\n                    groupByFieldsCounter.put(entry.getKey(), counter);\n                } else {\n                    groupByFieldsCounter.put(entry.getKey(), entry.getValue());\n                }\n            }\n        }\n\n        if (that.getOrderByFields() != null) {\n            for (Map.Entry<String, Long> entry : that.getOrderByFields().entrySet()) {\n                if (sortByFieldsCounter.containsKey(entry.getKey())) {\n                    Long counter = sortByFieldsCounter.get(entry.getKey()) + entry.getValue();\n                    sortByFieldsCounter.put(entry.getKey(), counter);\n                } else {\n                    sortByFieldsCounter.put(entry.getKey(), entry.getValue());\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/DslTemplate.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description: Dsl模板\n * @date: Create on 2019/1/15 下午8:19\n * @modified By D10865\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslTemplate {\n    /**\n     * 查询模板增加个数\n     */\n    private Long dslIncCnt;\n    /**\n     * 查询模板个数\n     */\n    private Long dslTotalCnt;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/ErrorDsl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/15 下午8:23\n * @modified By D10865\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ErrorDsl {\n\n    /**\n     * 异常查询总次数\n     */\n    private Long               count;\n    /**\n     * 异常查询\n     */\n    private List<ErrorDslInfo> details;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/ErrorDslDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description: 错误dsl模板详情\n * @date: Create on 2019/1/15 下午8:24\n * @modified By D10865\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ErrorDslDetail {\n    /**\n     * dsl查询模板MD5\n     */\n    private String dslTemplateMd5;\n    /**\n     * DSL查询模板\n     */\n    private String dslTemplate;\n    /**\n     * 异常索引名称\n     */\n    private String indices;\n    /**\n     * 异常dsl语句\n     */\n    private String dsl;\n    /**\n     * 次数\n     */\n    private Long   count;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/ErrorDslEmailLine.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/10/24 下午3:46\n * @Modified By\n *\n * 异常查询一行记录\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ErrorDslEmailLine {\n    /**\n     * 日期\n     */\n    private String date;\n    /**\n     * 异常名称\n     */\n    private String exceptionName;\n    /**\n     * 次数\n     */\n    private Long   count;\n    /**\n     * 索引名称\n     */\n    private String indices;\n    /**\n     * 查询语句\n     */\n    private String dsl;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/ErrorDslInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author: D10865\n * @description: 错误dsl模板\n * @date: Create on 2019/1/15 下午8:23\n * @modified By D10865\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ErrorDslInfo {\n    /**\n     * 异常名称\n     */\n    private String               name;\n    /**\n     * 异常次数\n     */\n    private Long                 count;\n    /**\n     * 异常详情\n     */\n    private List<ErrorDslDetail> details = null;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/ExceptionDslRequest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport com.alibaba.fastjson.JSONObject;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * 异常分析请求类\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ExceptionDslRequest {\n\n    private static final String TIME_FORMAT       = \"yyyy-MM-dd-HH:mm:ss\";\n\n    /**\n     * 查询异常检测时间段结束时刻, 单位毫秒\n     */\n    private Long                end;\n\n    @ApiModelProperty(value = \"查询异常检测时间段长度, 单位毫秒\", example = \"10\")\n    private Long                gap;\n\n    @ApiModelProperty(value = \"查询异常检测时间段中，总请求数据小于minCheckQps的查询MD5，不做分析\", example = \"10\")\n    private Long                minCheckQps;\n\n    @ApiModelProperty(value = \"QPS小于minQps的请求，不用于检测异常\", example = \"10\")\n    private Long                minQps;\n\n    @ApiModelProperty(value = \"如果是60*1000,则统计每分钟的请求数目，如果是1000则统计每条的请求数目，结果用于异常分析\", example = \"10\")\n    private String              interval;\n\n    @ApiModelProperty(value = \"请求的查询耗时超过该值，才对查询进行分析\", example = \"5000\")\n    private Long                esCost;\n\n    @ApiModelProperty(value = \"如果历史qps*factor < 当前qps，则说明查询请求涨幅过大，判断为异常信息\", example = \"5000\")\n    private Float               factor;\n\n    @ApiModelProperty(value = \"对查询请求数据增加过滤条件，DSL语句的形式，如term,range\", example = \"term,range\")\n    private JSONObject          filterDsl;\n\n    @ApiModelProperty(value = \"检测类型\", example = \"esCost只分析耗时超过阈值的查询, qps分析索引查询请求, timedOut只分析超时的查询请求\")\n    private String              type;\n\n    @ApiModelProperty(value = \"只分析indices指定的索引相关的查询查询请求\", example = \"dos_order_201909\")\n    private String              indices;\n\n    @ApiModelProperty(value = \"查询异常开始时刻\", example = \"1550160000000\")\n    private String              gte;\n\n    @ApiModelProperty(value = \"查询异常结束时刻\", example = \"1550246399999\")\n    private String              lte;\n\n    private static final Long   ONE_HOUR          = 60 * 60 * 1000L;\n    private static final String TYPE_ESCOST_STR   = \"esCost\";\n    private static final String TYPE_QPS_STR      = \"qps\";\n    private static final String TYPE_TIMEDOUT_STR = \"timedOut\";\n\n    public void check() {\n\n        // 如果大于 小于值存在\n        if (StringUtils.isNotBlank(lte) && StringUtils.isNotBlank(gte)) {\n            end = Long.valueOf(lte);\n            gap = end - Long.valueOf(gte);\n        } else {\n            if (end == null) {\n                end = System.currentTimeMillis();\n            }\n\n            if (gap == null) {\n                gap = ONE_HOUR;\n            }\n        }\n\n        if (minQps == null) {\n            minQps = 60L;\n        }\n\n        if (interval == null) {\n            interval = \"1m\";\n        }\n\n        if (factor == null) {\n            factor = 1.2f;\n        }\n\n        if (type == null) {\n            type = TYPE_ESCOST_STR;\n        }\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/ExceptionDslResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.text.SimpleDateFormat;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ExceptionDslResponse {\n\n    public static final String  TIME_FORMAT     = \"yyyy-MM-dd-HH:mm:ss\";\n    private static final String NEW_FORMAT_STR  = \"new dsl, time:%s, count:%d\";\n    private static final String GROW_FORMAT_STR = \"grow dsl, before:%d, after:%d, time:%s\";\n\n    private int                 projectId;\n\n    private String              templateMD5;\n\n    private String              reason;\n\n    public static ExceptionDslResponse buildForNew(long timeStamp, long count) {\n        SimpleDateFormat format = new SimpleDateFormat(TIME_FORMAT);\n\n        ExceptionDslResponse ret = new ExceptionDslResponse();\n        ret.reason = String.format(NEW_FORMAT_STR, format.format(timeStamp), count);\n        return ret;\n    }\n\n    public static ExceptionDslResponse buildForGrow(long timeStamp, long before, long after) {\n        SimpleDateFormat format = new SimpleDateFormat(TIME_FORMAT);\n\n        ExceptionDslResponse ret = new ExceptionDslResponse();\n        ret.reason = String.format(GROW_FORMAT_STR, before, after, format.format(timeStamp));\n        return ret;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/ExtractDslContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"提取查询模板\")\n@Deprecated\npublic class ExtractDslContent {\n\n    @ApiModelProperty(value = \"查询语句\")\n    private String dslContent;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/QueryQpsMetric.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/15 下午8:16\n * @modified By D10865\n *\n * 查询qps统计信息\n */\n@Data\n@AllArgsConstructor\npublic class QueryQpsMetric {\n\n    /**\n     * 最大qps\n     */\n    private Long   maxQps;\n    /**\n     * 最大qps发生时刻\n     */\n    private String maxQpsTime;\n    /**\n     * 平均qps\n     */\n    private Long   avgQps;\n    /**\n     * 最小qps\n     */\n    private Long   minQps;\n    /**\n     * 最小qps发生时刻\n     */\n    private String minQpsTime;\n\n    public QueryQpsMetric() {\n        maxQps = avgQps = minQps = 0L;\n        maxQpsTime = minQpsTime = \"\";\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/ScrollDslTemplateRequest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/22 下午4:31\n * @modified By D10865\n *\n * 滚动获取查询模板接口\n *\n */\n@Data\n@NoArgsConstructor\npublic class ScrollDslTemplateRequest {\n\n    /**\n     * 滚动查询大小\n     */\n    private Long   scrollSize;\n    /**\n     * 查询模板版本号\n     */\n    private String dslTemplateVersion;\n    /**\n     * 上次修改时间\n     */\n    private Long   lastModifyTime;\n    /**\n     * 滚动游标\n     */\n    private String scrollId;\n\n    /**\n     * 请求参数是否有效\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    public boolean isValid() {\n\n        if (StringUtils.isBlank(this.dslTemplateVersion)) {\n            return false;\n        }\n\n        if (this.lastModifyTime == null) {\n            return false;\n        }\n\n        if (this.scrollSize == null) {\n            return false;\n        }\n\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/ScrollDslTemplateResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/22 下午4:45\n * @modified By D10865\n *\n * 滚动查询查询模板响应\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Builder\npublic class ScrollDslTemplateResponse {\n\n    /**\n     * 查询模板集合\n     */\n    private List<DslTemplatePO> dslTemplatePoList;\n    /**\n     * 滚动查询游标\n     */\n    private String              scrollId;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/SearchDslTemplateResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/22 下午4:45\n * @modified By D10865\n *\n * 查询查询模板响应\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Builder\npublic class SearchDslTemplateResponse {\n\n    /**\n     * 查询模板集合\n     */\n    private List<DslTemplatePO> records;\n\n    /**\n     * 查询命中记录数\n     */\n    private Long                totalHits;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/SearchOverview.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/15 下午8:20\n * @modified By D10865\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class SearchOverview {\n    /**\n     * 查询总次数\n     */\n    private Long                count;\n    /**\n     * 查询qps信息\n     */\n    private QueryQpsMetric      qpsMetric;\n    /**\n     * 查询耗时分位图\n     */\n    private Map<String, Object> costQuantile;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/SlowDsl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/15 下午8:21\n * @modified By D10865\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"dsl慢查语句\")\npublic class SlowDsl {\n    /**\n     * 慢查次数\n     */\n    @ApiModelProperty(value = \"慢查次数\")\n    private Long                count;\n    /**\n     * 慢查详情\n     */\n    @ApiModelProperty(value = \"慢查详情\")\n    private List<SlowQueryInfo> details;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/SlowDslEmailLine.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/10/24 下午3:48\n * @Modified By\n *\n * 慢查一行\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Deprecated\npublic class SlowDslEmailLine {\n    /**\n     * 日期\n     */\n    private String date;\n    /**\n     * 次数\n     */\n    private Long   count;\n    /**\n     * 索引名称\n     */\n    private String indices;\n    /**\n     * 耗时\n     */\n    private Double cost;\n    /**\n     * 查询语句\n     */\n    private String dsl;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/SlowDslReasonType.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/10/24 下午5:30\n * @Modified By\n *\n * 慢查原因枚举\n */\npublic enum SlowDslReasonType {\n\n                               /**\n                                * 用户查询引起\n                                */\n                               USER_DSL(\"user dsl\"),\n                               /**\n                                * ES查询引起\n                                */\n                               ES(\"es\");\n\n    private final String type;\n\n    public String getType() {\n        return type;\n    }\n\n    SlowDslReasonType(String type) {\n        this.type = type;\n    }\n\n    private static final Map<String, SlowDslReasonType> TYPE_MAP;\n\n    static {\n        Map<String, SlowDslReasonType> typeMap = new HashMap<>();\n        for (SlowDslReasonType slowDslReasonType : SlowDslReasonType.values()) {\n            typeMap.put(slowDslReasonType.getType(), slowDslReasonType);\n        }\n        TYPE_MAP = Collections.unmodifiableMap(typeMap);\n    }\n\n    public static SlowDslReasonType fromType(String type) {\n        SlowDslReasonType slowDslReasonType = TYPE_MAP.get(type);\n        if (slowDslReasonType == null) {\n            throw new IllegalArgumentException(\"no SlowDslReasonType for \" + type);\n        }\n        return slowDslReasonType;\n    }\n\n    @Override\n    public String toString() {\n        return getType();\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/dsl/SlowQueryInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/10/17 下午9:51\n * @Modified By\n *\n * 慢查语句信息\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"dsl慢查详情\")\npublic class SlowQueryInfo {\n    /**\n     * dsl查询模板MD5\n     */\n    @ApiModelProperty(value = \"dsl查询模板MD5\")\n    private String            dslTemplateMd5;\n    /**\n     * DSL查询模板\n     */\n    @ApiModelProperty(value = \"DSL查询模板\")\n    private String            dslTemplate;\n    /**\n     * dsl查询语句\n     */\n    @ApiModelProperty(value = \"dsl查询语句\")\n    private String            dsl;\n    /**\n     * 查询索引\n     */\n    @ApiModelProperty(value = \"查询索引\")\n    private String            indices;\n    /**\n     * 查询次数\n     */\n    @ApiModelProperty(value = \"查询次数\")\n    private Long              count;\n    /**\n     * 查询耗时\n     */\n    @ApiModelProperty(value = \"查询耗时\")\n    private Double            cost;\n    /**\n     * 慢查阈值\n     */\n    @ApiModelProperty(value = \"慢查阈值\")\n    private Long              slowDslThreshold;\n    /**\n     * 查询原因\n     */\n    @ApiModelProperty(value = \"查询原因\")\n    private String            cause;\n    /**\n     * 慢查原因类型\n     */\n    @ApiModelProperty(value = \"慢查原因类型：USER_DSL/ES\")\n    private SlowDslReasonType slowReasonType;\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/esconfig/ESConfig.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.esconfig;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2020-12-29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESConfig extends BaseEntity {\n    /**\n     * ID主键自增\n     */\n    private Long    id;\n\n    /**\n     * 集群id\n     */\n    private Long    clusterId;\n\n    /**\n     * 配置文件名称 ：elasticsearch.yml\n     */\n    private String  typeName;\n\n    /**\n     * 角色名称\n     */\n    private String  enginName;\n\n    /**\n     * 配置内容\n     */\n    private String  configData;\n\n    /**\n     *  原始配置内容(工单特有，其他实体P DTO无此字段)\n     */\n    private String  originalConfigData;\n\n    /**\n     * 配置描述\n     */\n    private String  desc;\n\n    /**\n     * 配置tag\n     */\n    private String  versionTag;\n\n    /**\n     * 配置版本\n     */\n    private Integer versionConfig;\n\n    /**\n     *  是否在使用 0：不使用 1：部分生效中 2：已生效\n     */\n    private Integer selected;\n\n    /**\n     * 标记删除\n     */\n    private Boolean deleteFlag;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/espackage/ESPackage.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.espackage;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021-01-12\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESPackage extends BaseEntity {\n\n    private Long    id;\n\n    /**\n     * 镜像地址或包地址\n     */\n    private String  url;\n\n    /**\n     * 版本标识\n     */\n    private String  esVersion;\n\n    /**\n     * 包创建人\n     */\n    private String  creator;\n\n    /**\n     * 是否为发布版本\n     */\n    private Boolean release;\n\n    /**\n     * 类型(3 docker/4 host)\n     */\n    private Integer manifest;\n    /**\n     * 备注\n     */\n    private String  desc;\n\n    /**\n     * 标记删除\n     */\n    private Boolean deleteFlag;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/gateway/GatewayClusterNode.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.gateway;\n\nimport java.util.Date;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class GatewayClusterNode extends BaseEntity {\n\n    private Integer id;\n\n    private String  clusterName;\n\n    private String  hostName;\n\n    private Integer port;\n\n    private Date    heartbeatTime;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/BaseDegree.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.IndicatorsType;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class BaseDegree {\n\n    @ApiModelProperty(value = \"健康分计算类型：健康分基数、实时写入量、实时查询量、实时JVM内存使用、实时查询时间耗时、实时磁盘利用率、实时CPU利用率\")\n    private IndicatorsType indicatorsType;\n\n    @ApiModelProperty(value = \"得分\")\n    private double         score;\n\n    /**\n     * 乘以权重的最终得分，weightScore=score*weightRate\n     */\n    @ApiModelProperty(value = \"乘以权重的最终得分，weightScore=score*weightRate\")\n    private double         weightScore;\n\n    /**\n     * 权重\n     */\n    @ApiModelProperty(value = \"权重\")\n    private int            weight;\n\n    /**\n     * 权重比例\n     */\n    @ApiModelProperty(value = \"权重比例\")\n    private double         weightRate;\n\n    /**\n     * 计算处理过程\n     */\n    @ApiModelProperty(value = \"计算处理过程\")\n    private String         process;\n\n    /**\n     * 惩罚机制计算\n     */\n    @ApiModelProperty(value = \"惩罚机制计算\")\n    private String         punishment;\n\n    @ApiModelProperty(value = \"得分描述\")\n    private String         desc;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/IndexCatCell.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport java.util.List;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/30\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexCatCell {\n    private String       cluster;\n    private String       clusterLogic;\n    private Long         resourceId;\n    private Integer      projectId;\n    private String       health;\n    private String       status;\n    private String       index;\n    private Long         pri;\n    private Long         rep;\n    private Long         docsCount;\n    private Long         docsDeleted;\n    private String       storeSize;\n    private String       priStoreSize;\n    private Boolean      readFlag;\n    private Boolean      writeFlag;\n    private Boolean      deleteFlag;\n    private Long         timestamp;\n\n    private Long         primariesSegmentCount;\n    private Long         totalSegmentCount;\n    private Integer      templateId;\n    private Boolean      platformCreateFlag;\n    private List<String> aliases;\n\n    public String getKey() {\n        return cluster + \"@\" + index;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/IndexRealTimeInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Date;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class IndexRealTimeInfo {\n\n    /**\n     * 模板名称\n     */\n    private String template;\n\n    /**\n     * 集群名称\n     */\n    private String cluster;\n\n    /**\n     * 开始时间\n     */\n    private Date   start;\n\n    /**\n     * 结束时间\n     */\n    private Date   end;\n\n    /**\n     * 平均查询率\n     */\n    private double avgSearchQueryTotalRate;\n\n    /**\n     * 平均写入率\n     */\n    private double avgIndexingIndexTotalRate;\n\n    /**\n     * 平均查询时长\n     */\n    private double avgIndicesSearchQueryTime;\n\n    @Override\n    public String toString() {\n        return \"IndexInfo\" + \": template=\" + template + \": cluster=\" + cluster + \": start=\" + start.toString()\n               + \": end=\" + end.toString() + \": avgSearchQueryTotalRate=\" + avgSearchQueryTotalRate\n               + \", avgIndexingIndexTotalRate=\" + avgIndexingIndexTotalRate + \", avgIndicesSearchQueryTime=\"\n               + avgIndicesSearchQueryTime;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/IndicatorChild.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class IndicatorChild {\n    /**\n     * 主键\n     */\n    private int    id;\n    /**\n     * 指标编码\n     */\n    private int    code;\n    /**\n     * 指标区间上值\n     */\n    private int    upper;\n    /**\n     * 指标区间下值\n     */\n    private int    lower;\n    /**\n     * 指标得分\n     */\n    private String scoreExpr = \"\";\n    /**\n     * 是否有效\n     */\n    private int    isActive;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/OffLine.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(description = \"索引健康分离线统计信息\")\npublic class OffLine extends BaseDegree {\n    /**\n     * 模板id\n     */\n    @ApiModelProperty(value = \"模板id\")\n    private Integer templateId;\n    /**\n     * 模板名称\n     */\n    @ApiModelProperty(value = \"模板名称\")\n    private String  template;\n    /**\n     * 成本(单位GB)\n     */\n    @ApiModelProperty(value = \"每GB成本\")\n    private double  costByGb;\n    /**\n     * 模板天访问量(前一天)\n     */\n    @ApiModelProperty(value = \"模板天访问量(前一天)\")\n    private long    yesterdayAccessNum;\n    /**\n     * 单成本访问量(accessNum/costGb)\n     */\n    @ApiModelProperty(value = \"单成本访问量(accessNum/costGb)\")\n    private double  singleGbAccess;\n    /**\n     * 集群\n     */\n    @ApiModelProperty(value = \"集群\")\n    private String  cluster;\n    /**\n     * 是否文档数为0\n     */\n    @ApiModelProperty(value = \"是否文档数为0\")\n    private boolean isZeroCount;\n    /**\n     * 时间字段(毫秒时间戳)\n     */\n    @ApiModelProperty(value = \"时间字段(毫秒时间戳)\")\n    private long    timestamp;\n    /**\n     * 部门\n     */\n    @ApiModelProperty(value = \"部门\")\n    private String  department;\n\n    public double getOffLineSocre() {\n        return super.getScore();\n    }\n\n    public double getOffLineWeighScore() {\n        return super.getWeightScore();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/RealTimeCpuUse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(description = \"索引健康分实时cpu统计信息\")\npublic class RealTimeCpuUse extends BaseDegree {\n    /**\n     * 近十分钟索引所在节点平均cpu使用率\n     */\n    @ApiModelProperty(value = \"近十分钟索引所在节点平均cpu使用率分\")\n    private Double avgCpuAvgUse;\n\n    public String getCpuUseScoreDesc() {\n        return super.getDesc();\n    }\n\n    /**\n     * 实时cpu使用率得分\n     */\n    public double getCpuUseScore() {\n        return super.getScore();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/RealTimeDiskUse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(description = \"索引健康分实时磁盘统计信息\")\npublic class RealTimeDiskUse extends BaseDegree {\n    /**\n     * 近十分钟,平均磁盘使用率\n     */\n    @ApiModelProperty(value = \"近十分钟,平均磁盘使用率\")\n    private Double avgDiskUse;\n\n    public String getDiskUseScoreDesc() {\n        return super.getDesc();\n    }\n\n    /**\n     * 实时磁盘使用率得分\n     */\n    public double getDiskUseScore() {\n        return super.getScore();\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/RealTimeOldGC.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(description = \"索引健康分实时jvm统计信息\")\npublic class RealTimeOldGC extends BaseDegree {\n    /**\n     * 近十分钟内,总的old gc次数\n     */\n    @ApiModelProperty(value = \"近十分钟内,总的old gc次数\")\n    private Double avgJvmOldGc;\n\n    public String getJvmOldGcDesc() {\n        return super.getDesc();\n    }\n\n    /**\n     * 实时jvm使用率(用fullgc次数作为指标)得分\n     */\n    public double getJvmOldGcScore() {\n        return super.getScore();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/RealTimeSearch.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(description = \"索引健康分实时查询统计信息\")\npublic class RealTimeSearch extends BaseDegree {\n    /**\n     * 近十分钟平均查询率\n     */\n    @ApiModelProperty(value = \"近十分钟平均查询率\")\n    private Double avgSearchRate;\n\n    /**\n     * 昨天近十分钟平均查询率\n     */\n    @ApiModelProperty(value = \"昨天近十分钟平均查询率\")\n    private Double yesterdayAvgSearchRate;\n\n    public String getRealTimeSearchDesc() {\n        return super.getDesc();\n    }\n\n    /**\n     * 实时查询得分\n     */\n    public double getSearchScore() {\n        return super.getScore();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/RealTimeSearchCost.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(description = \"索引健康分实时查询耗时统计信息\")\npublic class RealTimeSearchCost extends BaseDegree {\n    /**\n     * 近十分钟平均查询时长\n     */\n    @ApiModelProperty(value = \"近十分钟平均查询时长\")\n    private Double avgSearchCostTime;\n\n    /**\n     * 查询耗时得分\n     */\n    public double getSearchCostTimeScore() {\n        return super.getScore();\n    }\n\n    public String getSearchCostTimeDesc() {\n        return super.getDesc();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/RealTimeWrite.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(description = \"索引健康分实时写入统计信息\")\npublic class RealTimeWrite extends BaseDegree {\n    /**\n     * 10分钟内平均写入率\n     */\n    @ApiModelProperty(value = \"10分钟内平均写入率\")\n    private Double avgIndexingRate;\n\n    /**\n     * 前一天近10分钟内平均写入率\n     */\n    @ApiModelProperty(value = \"前一天近10分钟内平均写入率\")\n    private Double yesterdayAvgIndexingRate;\n\n    public String getRealTimeWriteDesc() {\n        return super.getDesc();\n    }\n\n    /**\n     * 实时写入得分\n     */\n    public double getRealTimeWriteScore() {\n        return super.getScore();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/index/setting/ESIndicesGetAllSettingRequest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.index.setting;\n\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.getindex.ESIndicesGetIndexRequest;\n\n/**\n * @author lyn\n * @date 2021/10/03\n **/\npublic class ESIndicesGetAllSettingRequest extends ESIndicesGetIndexRequest {\n    private boolean defaultSettingFlag = false;\n\n    public void setDefaultSettingFlag(boolean defaultSettingFlag) {\n        this.defaultSettingFlag = defaultSettingFlag;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        RestRequest restRequest = super.toRequest();\n        String endPoint = \"\";\n        if (defaultSettingFlag) {\n            endPoint = restRequest.getEndpoint() + \"?include_defaults=true&pretty\";\n        }\n        return new RestRequest(\"GET\", endPoint, null);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/config/UserConfigInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.config;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.UserConfigTypeEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * 标准配置信息\n *\n * @author shizeying\n * @date 2022/05/24\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class UserConfigInfo extends BaseEntity {\n\n    /**\n     * 用户名\n     */\n    private String       userName;\n\n    /**\n     * 一级目录下的指标配置类型,如集群看板，网关看板\n     * @see UserConfigTypeEnum\n     */\n    private String       firstUserConfigType;\n\n    /**\n     * 二级目录下的指标配置类型,如集群看板下的总览指标类型\n     * @see UserConfigTypeEnum\n     */\n    private String       secondUserConfigType;\n\n    /**\n     * 二级目录指标配置下具体的配置列表,如cpu利用率\n     */\n    private List<String> userConfigTypes;\n\n    /**\n     * 应用ID\n     */\n    private Integer       projectId;\n\n    /**\n     * 配置类型\n     */\n    private Integer       configType;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/DashboardTopMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DashboardTopMetrics extends TopMetrics {\n    private List<Tuple<String/*集群名称*/, String/*索引名称/节点名称/集群名称/模板名称*/>> dashboardTopInfo;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/DiskInfoMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DiskInfoMetrics implements Serializable {\n    private long   timeStamp;\n    private double totalStoreSize;\n    private double storeSize;\n    private double freeStoreSize;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/GatewayOverviewMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport com.google.common.collect.Lists;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * Created by fitz on 2021-08-23\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class GatewayOverviewMetrics implements Serializable {\n\n    private String                   type;\n\n    private List<MetricsContentCell> metrics;\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        GatewayOverviewMetrics that = (GatewayOverviewMetrics) o;\n        return type.equals(that.type);\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(type);\n    }\n\n    public void addMetrics(MetricsContentCell contentCell) {\n        if (this.metrics == null) {\n            this.metrics = Lists.newArrayList();\n        }\n        this.metrics.add(contentCell);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/MetricsContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class MetricsContent implements Serializable {\n    /**\n     * 集群名称，仅在节点维度指标、索引维度指标、模板维度指标设置该值，用于前端dashboard跳转至指标看板\n     */\n    private String                   cluster;\n\n    /**\n     * 节点名称、模板名称、索引名称、网关相关信息\n     */\n    private String                   name;\n\n    /**\n     * 多个时间片指标数据\n     */\n    private List<MetricsContentCell> metricsContentCells;\n\n    /**\n     * 时间段内的最大值或平均值\n     */\n    private Double                   valueInTimePeriod;\n\n    /**\n     * 集群索引数量\n     */\n    private Long                   indexCount;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/MetricsContentCell.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n/**\n * Created by linyunan on 2021-08-12\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class MetricsContentCell implements Serializable {\n    /**\n     * 指标值\n     */\n    private double value;\n\n    /**\n     * 时间戳\n     */\n    private long   timeStamp;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/ReadQPSMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ReadQPSMetrics implements Serializable {\n    private long   timeStamp;\n    private double readTps;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/RecvTransMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class RecvTransMetrics implements Serializable {\n    private long   timeStamp;\n    private double recvTransSize;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/SendTransMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class SendTransMetrics implements Serializable {\n    private long   timeStamp;\n    private double sendTransSize;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/ShardInfoMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ShardInfoMetrics implements Serializable {\n    private long timeStamp;\n    private long shardNu;\n    private long unAssignedShards;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/TaskCountMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n/**\n * @author didi\n * @date 2022-01-13 6:01 下午\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TaskCountMetrics implements Serializable {\n    private long timeStamp;\n    private long taskCount;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/TopMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport java.util.List;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/26\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TopMetrics {\n    /**\n     * 指标类型、节点维度指标、索引维度指标\n     * see ClusterPhyNodeMetricsEnum\n     * see ClusterPhyIndicesMetricsEnum\n     */\n    private String       type;\n\n    /**\n     * 指标看板top信息 集群名称/节点名称/模板名称/索引名称等列表\n     */\n    private List<String> topNames;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/VariousLineChartMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport java.io.Serializable;\nimport java.util.List;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class VariousLineChartMetrics implements Serializable {\n\n    /**\n     * 指标类型\n     */\n    private String               type;\n\n    /**\n     * 集群节点指标类型\n     */\n    private List<MetricsContent> metricsContents;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/linechart/WriteTPSMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class WriteTPSMetrics implements Serializable {\n    private long   timeStamp;\n    private double writeTps;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/list/MetricList.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.list;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n * \n * 列表类型的指标类\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class MetricList extends BaseEntity {\n    /**\n     * 当前时间\n     */\n    private Long                    currentTime;\n\n    /**\n     * 指标类型\n     */\n    private String                  type;\n\n    /**\n     * 具体指标信息\n     */\n    private List<MetricListContent> metricListContents;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/list/MetricListContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.list;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class MetricListContent {\n    /**\n     * 物理集群名称\n     */\n    private String clusterPhyName;\n\n    /**\n     * 名称: node Name / index name /template name\n     */\n    private String name;\n\n    /**\n     * 指标值, 某些指标项需要展示指标值, 可能为百分比, 考虑客户端做适配\n     */\n    private Double value;\n\n    /**\n     * 指标值, 某些指标项需要展示指标值, 可能为百分比, 考虑客户端做适配\n     */\n    private Long indexCount;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/ordinary/BigIndexMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class BigIndexMetrics implements Serializable {\n\n    /**\n     * 索引名称\n     */\n    private String               indexName;\n\n    /**\n     * 归属节点node名称\n     */\n    private List<IndexShardInfo> belongNodeInfo;\n\n    /**\n     * 文档数\n     */\n    private Long                 docsCount;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/ordinary/ClusterMemInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@Builder\npublic class ClusterMemInfo implements Serializable {\n    @ApiModelProperty(\"已用内存大小\")\n    private Long   memUsed;\n\n    @ApiModelProperty(\"剩余空闲内存大小\")\n    private Long   memFree;\n\n    @ApiModelProperty(\"总内存大小\")\n    private Long   memTotal;\n\n    @ApiModelProperty(\"已用内存百分比\")\n    private Double memUsedPercent;\n\n    @ApiModelProperty(\"剩余空闲内存百分比\")\n    private Double memFreePercent;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/ordinary/ESClusterTaskDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n/**\n * @author didi\n * @date 2022-01-14 1:42 下午\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterTaskDetail implements Serializable {\n\n    private String taskId;\n\n    private String node;\n\n    private String action;\n\n    private long   startTime;\n\n    private long   runningTime;\n\n    private String runningTimeString;\n\n    private String description;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/ordinary/IndexResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexResponse implements Serializable {\n\n    /**\n     * 索引名称\n     */\n    private String index;\n\n    /**\n     * 文档数\n     */\n    private long   dc;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/ordinary/IndexShardInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexShardInfo implements Serializable {\n\n    private String index;\n    private int    shard;\n    private String prirep;\n    private String state;\n    private long   docs;\n    private String store;\n    private String ip;\n    private String node;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/ordinary/MovingShardMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-29\n */\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class MovingShardMetrics implements Serializable {\n\n    /**\n     * 归属索引\n     */\n    private String i;\n\n    /**\n     * 源节点ip\n     */\n    private String shost;\n\n    /**\n     * 目标节点ip\n     */\n    private String thost;\n\n    /**\n     * 覆盖的字节数\n     */\n    private String br;\n\n    /**\n     * 字节占比\n     */\n    private String bp;\n\n    /**\n     * 转换日志操作占比\n     */\n    private String top;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/ordinary/PendingTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-30\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class PendingTask implements Serializable {\n\n    /**\n     * 序号\n     */\n    private long   insertOrder;\n\n    /**\n     * 在队列里等待时间\n     */\n    private String timeInQueue;\n\n    /**\n     * 优先级, HIGH\n     */\n    private String priority;\n\n    /**\n     * 任务来源说明\n     */\n    private String source;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/ordinary/ShardMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ShardMetrics implements Serializable {\n    /**\n     * shard标识\n     */\n    private long   shard;\n\n    /**\n     * 归属索引\n     */\n    private String index;\n\n    /**\n     * 主/备\n     */\n    private String prirep;\n\n    /**\n     * 所属节点Ip\n     */\n    private String ip;\n\n    /**\n     * 所属节点Ip\n     */\n    private String node;\n\n    /**\n     * 容量\n     */\n    private String store;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/ordinary/UnAssignShardMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class UnAssignShardMetrics implements Serializable {\n    /**\n     * 归属索引\n     */\n    private String index;\n\n    /**\n     * shard标识\n     */\n    private long   shard;\n\n    /**\n     * 主/备\n     */\n    private String prirep;\n\n    /**\n     * 状态\n     */\n    private String state;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/metrics/percentiles/BasePercentileMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.percentiles;\n\nimport java.io.Serializable;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class BasePercentileMetrics implements Serializable, Comparable<BasePercentileMetrics> {\n\n    private double aggType;\n    private double st99;\n    private double st95;\n    private double st75;\n    private double st55;\n    private long   timeStamp;\n\n    @Override\n    public int compareTo(BasePercentileMetrics o) {\n        if (null == o) {\n            return 0;\n        }\n\n        return (int) (this.getTimeStamp() - o.getTimeStamp());\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/operaterecord/template/ESConfigOperateRecode.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.operaterecord.template;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum.valueOf;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord.Builder;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.esconfig.ESConfig;\nimport com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.DiffUtil;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.github.difflib.text.DiffRow;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.function.BiFunction;\nimport java.util.function.Function;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\n@Data\n@AllArgsConstructor\npublic class ESConfigOperateRecode {\n    public static final String DELIMITER = \"\\n\";\n    public static final String STR_EMPTY = \"\";\n    /**\n     * {@linkplain EsConfigActionEnum#getDesc()}\n     */\n    private String             operationType;\n    /**\n     * {@linkplain  ESConfig#getConfigData()} ()}\n     */\n    private String             source;\n    /**\n     * {@linkplain  ESConfig#getConfigData()} ()}\n     */\n    private String             target;\n\n    /**\n     * {@linkplain  ESConfig#getTypeName()}\n     */\n    private String             typeName;\n    /**\n     * {@linkplain  ESConfig#getEnginName()} ()}\n     */\n    private String             enginName;\n    /**\n     * {@linkplain  ESConfig#getVersionConfig()} ()}\n     */\n    private Integer            versionConfig;\n    /**\n     * 对比结果列表\n     */\n    private List<DiffRow>      diffResultList;\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n    public static final BiFunction<ESConfig, Function<Long, ESConfig>, TupleTwo</*source*/ESConfig, /*target*/ESConfig>> sourceAndTargetConfigFunc = (esConfig,\n                                                                                                                                                      getEsConfigByIdFunc) -> {\n        final Long id = esConfig.getId();\n        //新增\n        if (Objects.isNull(id)) {\n            return Tuples.of(null, esConfig);\n        }\n        final ESConfig oldEsConfig = getEsConfigByIdFunc.apply(id);\n        return Tuples.of(esConfig, oldEsConfig);\n\n    };\n\n    public static ESConfigOperateRecode sourceTargetDiff(TupleTwo</*source*/ESConfig, /*target*/ESConfig> sourceTargetTuple,\n                                                         Integer actionType) {\n        final EsConfigActionEnum esConfigActionEnum = valueOf(actionType);\n        String source = Optional.ofNullable(sourceTargetTuple.v1).map(ESConfig::getConfigData).orElse(STR_EMPTY);\n        String target = Optional.ofNullable(sourceTargetTuple.v2).map(ESConfig::getConfigData).orElse(STR_EMPTY);\n        final List<DiffRow> diffResultList = DiffUtil.diffRowsByString(source, target, DELIMITER);\n        final String typeName = Optional.ofNullable(sourceTargetTuple.v1).map(ESConfig::getTypeName).orElse(STR_EMPTY);\n        final String enginName = Optional.ofNullable(sourceTargetTuple.v1).map(ESConfig::getEnginName)\n            .orElse(STR_EMPTY);\n        final Integer versionConfig = Optional.ofNullable(sourceTargetTuple.v1).map(ESConfig::getVersionConfig)\n            .orElse(0);\n\n        return new ESConfigOperateRecode(esConfigActionEnum.getDesc(), source, target, typeName, enginName,\n            versionConfig, diffResultList);\n\n    }\n\n    public static OperateRecord buildESConfigOperateRecode(String operationUser,\n                                                           Function<Integer, ProjectBriefVO> getProjectByIdFunc,\n                                                           Integer projectId,\n                                                           ESConfigOperateRecode esConfigOperateRecode, Object bizId\n\n    ) {\n\n        return new Builder().userOperation(operationUser).project(getProjectByIdFunc.apply(projectId))\n            .operationTypeEnum(OperateTypeEnum.PHYSICAL_CLUSTER_CONF_FILE_CHANGE)\n\n            .content(esConfigOperateRecode.toString()).bizId(bizId).buildDefaultManualTrigger();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/operaterecord/template/TemplateMappingOperateRecord.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.operaterecord.template;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexMappingVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TemplateOperateRecordEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.DiffUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.DiffUtil.DiffJson;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport java.util.List;\nimport lombok.Data;\nimport org.apache.commons.collections4.CollectionUtils;\n\n/**\n * @author liuchengxiang\n * @date 2022/2/17\n */\n@Data\npublic class TemplateMappingOperateRecord extends TemplateOperateRecord {\n\n    public TemplateMappingOperateRecord(IndexMappingVO oldIndexMappingVO, IndexMappingVO newIndexMappingVO) {\n        final String oldMappings = oldIndexMappingVO.getMappings();\n        final String newMappings = newIndexMappingVO.getMappings();\n        source = JSON.parseObject(oldMappings);\n        target = JSON.parseObject(newMappings);\n        final List<DiffJson> diffs = DiffUtil.diffJsonByString(oldMappings, newMappings);\n        diffResult.addAll(diffs);\n        operateType = TemplateOperateRecordEnum.MAPPING.getCode();\n        change = CollectionUtils.isNotEmpty(diffs);\n        this.behavior = \"编辑MAPPING\";\n    }\n\n    public TemplateMappingOperateRecord(MappingConfig before, MappingConfig after) {\n        source = before.toJson();\n        target = after.toJson();\n        final List<DiffJson> diffs = DiffUtil.diffJsonByString(before.toJson().toJSONString(),\n            after.toJson().toJSONString());\n\n        diffResult.addAll(diffs);\n        operateType = TemplateOperateRecordEnum.MAPPING.getCode();\n        change = CollectionUtils.isNotEmpty(diffs);\n        this.behavior = \"编辑MAPPING\";\n    }\n    public TemplateMappingOperateRecord(JSONObject before, MappingConfig after) {\n        source = before;\n        target = after.toJson();\n        final List<DiffJson> diffs = DiffUtil.diffJsonByString(before.toJSONString(),\n            after.toJson().toJSONString());\n\n        diffResult.addAll(diffs);\n        operateType = TemplateOperateRecordEnum.MAPPING.getCode();\n        change = CollectionUtils.isNotEmpty(diffs);\n        this.behavior = \"编辑MAPPING\";\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/operaterecord/template/TemplateOperateRecord.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.operaterecord.template;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.util.DiffUtil.DiffJson;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateOperateRecord {\n\n    /**\n     * 模板操作类型，如mapping, setting, etc\n     */\n    protected Integer        operateType;\n    /**\n     * 旧的schema 设置\n     */\n    protected JSONObject     source;\n\n    /**\n     * 新的schema 设置\n     */\n    protected JSONObject     target;\n    protected List<DiffJson> diffResult = Lists.newArrayList();\n\n    protected Boolean        change;\n    protected String         behavior;\n    \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/operaterecord/template/TemplateSettingOperateRecord.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.operaterecord.template;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONAware;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhySetting;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexSettingVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TemplateOperateRecordEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.DiffUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.DiffUtil.DiffJson;\nimport java.util.List;\nimport java.util.Optional;\nimport lombok.Data;\nimport org.apache.commons.collections4.CollectionUtils;\n\n/**\n * @author liuchengxiang\n * @date 2022/2/17\n */\n@Data\npublic class TemplateSettingOperateRecord extends TemplateOperateRecord {\n\n    public TemplateSettingOperateRecord(IndexTemplatePhySetting oldConfig, IndexTemplatePhySetting newConfig) {\n        this.operateType = TemplateOperateRecordEnum.SETTING.getCode();\n        source = oldConfig.getSettings();\n        target = newConfig.getSettings();\n        final List<DiffJson> diffs = DiffUtil.diffJsonByString(\n            Optional.ofNullable(oldConfig).map(IndexTemplatePhySetting::getSettings).map(JSONAware::toJSONString)\n\n                .orElse(\"\"),\n            Optional.ofNullable(newConfig).map(IndexTemplatePhySetting::getSettings).map(JSONAware::toJSONString)\n\n                .orElse(\"\")\n\n        );\n\n        diffResult.addAll(diffs);\n        change = CollectionUtils.isNotEmpty(diffs);\n        this.behavior=\"编辑SETTING\";\n        \n\n    }\n\n    public TemplateSettingOperateRecord(IndexSettingVO oldSetting, IndexSettingVO newSettingVo) {\n        source = oldSetting.getProperties();\n        target = newSettingVo.getProperties();\n        final List<DiffJson> diffs = DiffUtil.diffJsonByString(source.toJSONString(), target.toJSONString());\n\n        diffResult.addAll(diffs);\n        operateType = TemplateOperateRecordEnum.SETTING.getCode();\n        change = CollectionUtils.isNotEmpty(diffs);\n        this.behavior=\"编辑SETTING\";\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/project/ESUser.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n *\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESUser extends BaseEntity {\n\n    private Integer id;\n\n    private String  name;\n\n    private Integer isRoot;\n\n    private String  verifyCode;\n\n \n\n    private String  memo;\n\n    private Integer isActive;\n\n    private Integer queryThreshold;\n\n    private String  cluster;\n\n    private Integer searchType;\n\n    private String  dataCenter;\n    private Integer projectId;\n    private Boolean defaultDisplay;\n\n    /******************** 即将废弃字段 ***********************/\n\n    private String  ip;\n\n    private String  indexExp;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/project/ProjectClusterLogicAuth.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ProjectClusterLogicAuth extends BaseEntity {\n    /**\n     * ID\n     */\n    private Long    id;\n\n    /**\n     * 应用ID\n     */\n    private Integer projectId;\n\n    /**\n     * 逻辑集群ID\n     */\n    private Long    logicClusterId;\n\n    /**\n     * 权限类型  管理、访问、无权限\n     * @see ProjectClusterLogicAuthEnum\n     */\n    private Integer type;\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/project/ProjectClusterPhyAuth.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ProjectClusterPhyAuth extends BaseEntity {\n    /**\n     * ID\n     */\n    private Long    id;\n\n    /**\n     * 应用ID\n     */\n    private Integer projectId;\n\n    /**\n     * 物理集群名称\n     */\n    private String  clusterPhyName;\n\n    /**\n     * 权限类型  读写  读\n     * @see ProjectClusterLogicAuthEnum\n     */\n    private Integer type;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/project/ProjectConfig.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ProjectConfig extends BaseEntity {\n\n    /**\n     * projectId\n     */\n    private Integer projectId;\n\n    /**\n     * gateway返回结果解析开关\n     */\n    private Integer analyzeResponseEnable;\n\n    /**\n     * 是否生效DSL分析查询限流值 1为生效DSL分析查询限流值，0不生效DSL分析查询限流值\n     */\n    private Integer dslAnalyzeEnable;\n\n    /**\n     * 是否开启聚合分析  1 开启  0 不开启  默认为 1\n     */\n    private Integer aggrAnalyzeEnable;\n\n    /**\n     * 是否索引存储分离，1为分离，0为不分离，默认为0\n     */\n    private Integer isSourceSeparated;\n    /**\n     * 慢查询时间\n     */\n    private Integer slowQueryTimes;\n    /**\n     * 备注\n     */\n    private String  memo;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/project/ProjectTemplateAuth.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/4/16\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ProjectTemplateAuth extends BaseEntity {\n\n    /**\n     * 主键\n     */\n    private Long    id;\n\n    /**\n     * project ID\n     */\n    private Integer projectId;\n\n    /**\n     * 模板ID\n     */\n    private Integer templateId;\n\n    /**\n     * 权限类型  读写  读\n     * @see ProjectTemplateAuthEnum\n     */\n    private Integer type;\n\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/quota/ClusterPhyResourceUsage.java",
    "content": ""
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/region/ClusterRegion.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.region;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.ToString;\n\n/**\n * @Author: lanxinzheng\n * @Date: 2021/1/13\n * @Comment:\n */\n@Data\n@ToString\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterRegion extends BaseEntity {\n    /**\n     * region ID\n     */\n    private Long   id;\n\n    /**\n     * region 名称\n     */\n    private String name;\n\n    /**\n     * 绑定到的逻辑集群ID列表, 为-1则没有被绑定\n     */\n    private String logicClusterIds;\n\n    /**\n     * 物理集群名称\n     */\n    private String phyClusterName;\n\n    /**\n     * 配置\n     */\n    private String config;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/region/ClusterRegionConfig.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.region;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/06/06\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterRegionConfig {\n\n    /**\n     * 冷节点标志\n     */\n    private Boolean cold = Boolean.FALSE;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/region/ClusterRegionFSInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.region;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/06/08\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterRegionFSInfo extends BaseEntity {\n\n    private Integer regionId;\n\n    private Long    totalInBytes     = 0L;\n\n    private Long    freeInBytes      = 0L;\n\n    private Long    availableInBytes = 0L;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/shard/Segment.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.shard;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Segment extends BaseEntity {\n\n    private String index;\n\n    private String shard;\n\n    private String ip;\n\n    private String segment;\n\n    private Double memoSize;\n\n    private String primaryFlag;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/CollectBean.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\npublic interface CollectBean {\n    /**\n     * 获取采集时间戳，毫秒\n     * @return\n     */\n    long getTimestamp();\n\n    /**\n     * 获取采集的值\n     * @return\n     */\n    Double getValue();\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ECSegmentOnIp.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ECSegmentOnIp {\n\n    /**\n     * segment数目\n     */\n    @JSONField(name = \"sc\")\n    String segment;\n\n    /**\n     * es集群上实例的ip\n     */\n    @JSONField(name = \"ip\")\n    String ip;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESClusterStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport static com.didichuxing.datachannel.arius.admin.common.util.CommonUtils.monitorTimestamp2min;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PercentilesEnum;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterStats extends BaseESPO {\n    /**\n     * 集群名称，all则表示全集群信息\n     */\n    private String              cluster;\n\n    /**\n     * 统计的时间戳，单位：毫秒\n     */\n    private long                timestamp;\n\n    /**\n     * 是否是物理集群 1：是；0：不是\n     */\n    private long                physicCluster;\n\n    /**\n     * 分位类型\n     * @see PercentilesEnum\n     */\n    private String              percentilesType;\n\n    /**\n     * 统计信息\n     */\n    private ESClusterStatsCells statis;\n\n    /**\n     * 数据中心\n     */\n    private String              dataCenter;\n\n    @Override\n    public String getKey() {\n        return String.format(\"%s@%s@%s@%d@%d\", dataCenter, cluster, percentilesType, monitorTimestamp2min(timestamp),physicCluster);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return cluster;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESClusterStatsCells.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterStatsCells {\n    /**\n     * 集群名称，all则表示全集群信息\n     */\n    private String clusterName;\n\n    /**\n     * 集群状态\n     */\n    private String status;\n\n    /**\n     * 集群状态\n     */\n    private int    statusType;\n\n    /**\n     * 未分配shard\n     */\n    private long   unAssignedShards;\n\n    /**\n     * pengdingtask梳理\n     */\n    private long   numberPendingTasks;\n\n    /**\n     * dataNode数量\n     */\n    private long   numberDataNodes;\n\n    private long   numberMasterNodes;\n    private long   numberClientNodes;\n    private long   numberIngestNodes;\n\n    /**\n     * 集群节点数量\n     */\n    private long   numberNodes;\n\n    /**\n     * 节点存活率\n     */\n    private int    alivePercent;\n\n    /**\n     * 集群重要等级\n     */\n    private int    level;\n\n    /**\n     * 集群已使用容量，单位\n     */\n    private Long storeSize;\n\n    /**\n     * 集群总容量，单位\n     */\n    private Long totalStoreSize;\n\n    /**\n     * 集群空余容量，单位\n     */\n    private Long freeStoreSize;\n\n    /**\n     * 索引容量，单位\n     */\n    private double indexStoreSize;\n\n    /**\n     * 集群索引数\n     */\n    private double totalIndicesNu;\n\n    /**\n     * 集群模板数\n     */\n    private int    totalTemplateNu;\n\n    /**\n     * 集群文档数\n     */\n    private long   totalDocNu;\n\n    /**\n     * 集群shard数量\n     */\n    private long   shardNu;\n\n    /**\n     * 每秒接受流量\n     */\n    private double recvTransSize;\n\n    /**\n     * 每秒发送流量\n     */\n    private double sendTransSize;\n\n    /**\n     * 集群写入tps\n     */\n    private double writeTps;\n\n    /**\n     * 集群读取tps\n     */\n    private double readTps;\n\n    /**\n     * cpu相关\n     */\n    private double cpuUsage;\n    private double cpuLoad1M;\n    private double cpuLoad5M;\n    private double cpuLoad15M;\n\n    /**\n     * 磁盘使用率\n     */\n    private double diskUsage;\n\n    /**\n     * 集群总数\n     */\n    private int    clusterNu;\n\n    /**\n     * es节点数\n     */\n    private double esNodeNu;\n\n    /**\n     * 应用数量\n     */\n    private int    appNu;\n\n    /**\n     * 每日查询总量\n     */\n    private long   queryTimesPreDay;\n    /**\n     * 集群稳定性\n     */\n    private double sla;\n\n    private long   memUsed;\n    private long   memFree;\n    private long   memTotal;\n    private double memUsedPercent;\n    private double memFreePercent;\n\n    /**\n     * 查询耗时\n     */\n    private double searchLatency;\n\n    /**\n     * 写入耗时\n     */\n    private double indexingLatency;\n\n    /**\n     * 任务耗时\n     */\n    private double taskCost;\n\n    /**\n     * 任务数量\n     */\n    private long   taskCount;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESClusterStatsResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.elasticsearch.common.unit.ByteSizeValue;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ESClusterStatsResponse {\n\n    /**\n     * 状态\n     */\n    private String        status;\n\n    /**\n     * 索引个数\n     */\n    private long          indexCount;\n    /**\n     * shard总个数\n     */\n    private long          totalShard;\n    /**\n     * 文档个数\n     */\n    private long          docsCount;\n    /**\n     * 集群索引总存储量\n     */\n    private ByteSizeValue indicesStoreSize;\n\n    /**\n     * 集群未分配shard数\n     */\n    private long          unassignedShardNum;\n    /**\n     * 集群Pending task数\n     */\n    private long          pendingTasks;\n    /**\n     * 总节点个数\n     */\n    private long          totalNodes;\n    private long          numberDataNodes;\n    private long          numberMasterNodes;\n    private long          numberClientNodes;\n    private long          numberCoordinatingOnly;\n    private long          numberIngestNodes;\n\n    /**********************内存********************/\n    private ByteSizeValue memUsed;\n    private ByteSizeValue memFree;\n    private ByteSizeValue memTotal;\n    private long          memUsedPercent;\n    private long          memFreePercent;\n\n    /**\n     * 磁盘总大小\n     */\n    private ByteSizeValue totalFs;\n    /**\n     * 剩余磁盘大小\n     */\n    private ByteSizeValue freeFs;\n\n    /**\n     * 最大堆内存空间\n     */\n    private ByteSizeValue totalHeapMem;\n\n    /**\n     * 已使用的堆内存空间\n     */\n    private ByteSizeValue usedHeapMem;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESClusterTaskStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author didi\n * @date 2022-01-13 11:45 上午\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterTaskStats extends BaseESPO {\n    /**\n     * 集群名称，all则表示全集群信息\n     */\n    private String                     cluster;\n\n    /**\n     * 统计的时间戳，单位：毫秒\n     */\n    private long                       timestamp;\n\n    /**\n     * 是否是物理集群 1：是；0：不是\n     */\n    private long                       physicCluster;\n\n    /**\n     * 统计信息\n     */\n    private ESClusterTaskStatsResponse metrics;\n\n    /**\n     * 数据中心\n     */\n    private String                     dataCenter;\n\n    @Override\n    public String getKey() {\n        return String.format(\"%s@%s@%d\", metrics.getTaskId(), cluster, timestamp);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return cluster;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESClusterTaskStatsResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author didi\n * @date 2022-01-13 11:55 上午\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ESClusterTaskStatsResponse {\n    private String action;\n    private String taskId;\n    private String parentTaskId;\n    private String type;\n    private long   startTime;\n    private long   runningTime;\n    private String runningTimeString;\n    private String ip;\n    private String node;\n    private String description;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESClusterThreadStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterThreadStats extends BaseEntity {\n\n    private String cluster;\n    private Long   management;\n    private Long   refresh;\n    private Long   flush;\n    private Long   merge;\n    private Long   search;\n    private Long   write;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESDataTempBean.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport com.didiglobal.knowframework.log.util.HostUtil;\nimport com.google.common.collect.Maps;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\nimport java.util.Objects;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESDataTempBean extends BaseESPO implements CollectBean {\n    public static final Integer INDEX_TYPE = 1;\n    public static final Integer NODE_TYPE  = 2;\n\n    public static final String  DIVIDEND   = \"Dividend\";\n    public static final String  DIVISOR    = \"Divisor\";\n\n    public ESDataTempBean(Double value) {\n        this.value = value;\n    }\n\n    /**\n     * 维度 1 是索引  2 是节点\n     */\n    private Integer             dimension;\n    /**\n     * 时间戳 单位是毫秒\n     */\n    private long                timestamp;\n    /**\n     * 模板所在集群\n     */\n    private String              cluster;\n    /**\n     * 模板名称\n     */\n    private String              template;\n    /**\n     * 物理模板id\n     */\n    private long                templateId;\n    /**\n     * 逻辑模板id\n     */\n    private long                logicTemplateId;\n    /**\n     * 索引名称\n     */\n    private String              index;\n\n    private String              type;\n    /**\n     * ams host\n     */\n    private String              host        = HostUtil.getHostName();\n    /**\n     * es节点名称\n     */\n    private String              node;\n    /**\n     * es节点ip\n     */\n    private String              ip;\n    /**\n     * es节点port\n     */\n    private String              port;\n    /**\n     * rack\n     */\n    private String              rack;\n    /**\n     * 模板shardNu\n     */\n    private long                shardNu;\n    /**\n     * 采集出来的原始值\n     */\n    private Double              value;\n    /**\n     * 指标名称,上报Odin用的\n     */\n    private String              valueName;\n    /**\n     * 衍生计算需要的参数\n     */\n    private Map<String, String> deriveParam = Maps.newHashMap();\n    /**\n     * 计算后的值\n     */\n    private String              computeValue;\n    /**\n     * 是否需要发送odin\n     */\n    private boolean             sendToN9e   = false;\n\n    @Override\n    public String getKey() {\n        return getKeyPre() + valueName;\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return cluster;\n    }\n\n    /**\n     * 此处不能带上monitorTimestamp2min(timestamp)\n     * @return\n     */\n    public String getKeyPre() {\n        if (Objects.equals(dimension, INDEX_TYPE)) {\n            return cluster + \"@\" + index + \"@\";\n        }\n\n        if (Objects.equals(dimension, NODE_TYPE)) {\n            return cluster + \"@\" + node + \"@\" + port + \"@\";\n        }\n\n        throw new IllegalArgumentException(\"dimension not know.\");\n    }\n\n    public String getDeriverParamByKey(String key) {\n        return deriveParam.get(key);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESIndexDCDRStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport io.swagger.annotations.ApiModel;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.didichuxing.datachannel.arius.admin.common.util.CommonUtils.monitorTimestamp2min;\n\n/**\n * author weizijun\n * date：2020-01-20\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"集群索引的DCDR统计信息\")\npublic class ESIndexDCDRStats extends BaseESPO {\n    /**\n     * 统计的时间戳，单位：毫秒\n     */\n    private long                timestamp;\n\n    /**\n     * 统计的集群名称\n     */\n    private String              cluster;\n\n    /**\n     * 统计的从集群名称\n     */\n    private String              replicaCluster;\n\n    /**\n     * 统计的集群中的索引模板名称\n     */\n    private String              template;\n\n    /**\n     * 统计的集群中的索引模板的id\n     */\n    private long                templateId;\n\n    /**\n     * 统计的集群中的索引模板的逻辑id\n     */\n    private long                logicTemplateId;\n\n    /**\n     * 统计的集群中的索引的名称\n     */\n    private String              index;\n\n    /**\n     * 统计的集群中的索引的shard个数\n     */\n    private long                shardNu;\n\n    /**\n     * 统计的集群中的索引的具体指标\n     */\n    private Map<String, String> metrics;\n\n    public void putMetrics(String key, String value) {\n        if (null == metrics) {\n            metrics = new HashMap<>();\n        }\n\n        metrics.put(key, value);\n    }\n\n    @Override\n    public String getKey() {\n        return cluster + \"@\" + index + \"@\" + replicaCluster + \"@\" + monitorTimestamp2min(timestamp);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return cluster;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESIndexStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport static com.didichuxing.datachannel.arius.admin.common.util.CommonUtils.monitorTimestamp2min;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\n\nimport io.swagger.annotations.ApiModel;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"集群索引中的统计信息\")\npublic class ESIndexStats extends BaseESPO {\n    /**\n     * 统计的时间戳，单位：毫秒\n     */\n    private long                timestamp;\n\n    /**\n     * 统计的集群名称\n     */\n    private String              cluster;\n\n    /**\n     * 统计的集群中的索引模板名称\n     */\n    private String              template;\n\n    /**\n     * 统计的集群中的索引模板的id\n     */\n    private long                templateId;\n\n    /**\n     * 统计的集群中的索引模板的逻辑id\n     */\n    private long                logicTemplateId;\n\n    /**\n     * 统计的集群中的索引的名称\n     */\n    private String              index;\n\n    /**\n     * 统计的集群中的索引的shard个数\n     */\n    private long                shardNu;\n\n    /**\n     * 统计的集群中的索引的具体指标\n     */\n    private Map<String, String> metrics;\n\n    public void putMetrics(String key, String value) {\n        if (null == metrics) {\n            metrics = new HashMap<>();\n        }\n\n        metrics.put(key, value);\n    }\n\n    @Override\n    public String getKey() {\n        return cluster + \"@\" + index + \"@\" + monitorTimestamp2min(timestamp);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return index;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESIndexToNodeStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\n\nimport static com.didichuxing.datachannel.arius.admin.common.util.CommonUtils.monitorTimestamp2min;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESIndexToNodeStats extends BaseESPO {\n    /**\n     * 时间戳，单位，毫秒\n     */\n    private long                timestamp;\n\n    /**\n     * 索引所属集群\n     */\n    private String              cluster;\n\n    /**\n     * 索引模板名称\n     */\n    private String              template;\n\n    /**\n     * 物理索引模板id\n     */\n    private long                templateId;\n\n    /**\n     * 逻辑模板id\n     */\n    private long                logicTemplateId;\n\n    /**\n     * 索引名称\n     */\n    private String              index;\n\n    /**\n     * 节点ip\n     */\n    private String              node;\n\n    /**\n     * 端口\n     */\n    private String              port;\n\n    /**\n     * rack信息\n     */\n    private String              rack;\n\n    /**\n     * index_node的统计信息\n     */\n    private Map<String, String> metrics;\n\n    @Override\n    public String getKey() {\n        return cluster + \"@\" + node + \"@\" + index + \"@\" + monitorTimestamp2min(timestamp);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESIndexToNodeTempBean.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Set;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESIndexToNodeTempBean {\n    /**\n     * 单位：毫秒\n     */\n    private long        timestamp;\n\n    /**\n     * 集群名称\n     */\n    private String      cluster;\n\n    /**\n     * 模板名称\n     */\n    private String      template;\n\n    /**\n     * 物理模板id\n     */\n    private long        templateId;\n\n    /**\n     * 逻辑模板id\n     */\n    private long        logicTemplateId;\n\n    /**\n     * 索引名称\n     */\n    private String      index;\n\n    /**\n     * 索引所在节点\n     */\n    private Set<String> nodes;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESIngestStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.didichuxing.datachannel.arius.admin.common.util.CommonUtils.monitorTimestamp2min;\n\n/**\n * author weizijun\n * date：2019-11-04\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESIngestStats extends BaseESPO {\n    /**\n     * 单位：毫秒\n     */\n    private long                timestamp;\n\n    /**\n     * 集群名称\n     */\n    private String              cluster;\n\n    /**\n     * 模板名称\n     */\n    private String              template;\n\n    /**\n     * 模板id\n     */\n    private long                templateId;\n\n    /**\n     * 逻辑模板id\n     */\n    private long                logicTemplateId;\n\n    /**\n     * 节点\n     */\n    private String              node;\n\n    /**\n     * 端口\n     */\n    private String              port;\n\n    /**\n     * 指标\n     */\n    private Map<String, String> metrics;\n\n    public void putMetrics(String key, String value) {\n        if (null == metrics) {\n            metrics = new HashMap<>();\n        }\n\n        metrics.put(key, value);\n    }\n\n    @Override\n    public String getKey() {\n        return cluster + \"@\" + node + \"@\" + template + \"@\" + monitorTimestamp2min(timestamp);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESNodeStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.didichuxing.datachannel.arius.admin.common.util.CommonUtils.monitorTimestamp2min;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESNodeStats extends BaseESPO {\n    /**\n     * 单位：毫秒\n     */\n    private long                timestamp;\n\n    private String              cluster;\n\n    private String              ip;\n\n    private String              node;\n\n    private String              port;\n\n    private String              rack;\n\n    private Map<String, String> metrics;\n\n    public void putMetrics(String key, String value) {\n        if (null == metrics) {\n            metrics = new HashMap<>();\n        }\n\n        metrics.put(key, value);\n    }\n\n    @Override\n    public String getKey() {\n        return cluster + \"@\" + ip + \"@\" + port + \"@\" + monitorTimestamp2min(timestamp);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return node;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESNodeToIndexStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.didichuxing.datachannel.arius.admin.common.util.CommonUtils.monitorTimestamp2min;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESNodeToIndexStats extends BaseESPO {\n    /**\n     * 单位：毫秒\n     */\n    private long                timestamp;\n\n    private String              cluster;\n\n    private String              template;\n\n    private long                templateId;\n\n    private long                logicTemplateId;\n\n    private String              index;\n\n    private String              node;\n\n    private String              port;\n\n    private Map<String, String> metrics;\n\n    public void putMetrics(String key, String value) {\n        if (null == metrics) {\n            metrics = new HashMap<>();\n        }\n\n        metrics.put(key, value);\n    }\n\n    @Override\n    public String getKey() {\n        return cluster + \"@\" + node + \"@\" + port + \"@\" + index + \"@\" + monitorTimestamp2min(timestamp);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/ESNodeToIndexTempBean.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport com.google.common.collect.Maps;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\nimport java.util.Map;\n\n@Data\n@AllArgsConstructor\npublic class ESNodeToIndexTempBean implements CollectBean {\n    /**\n     * 单位：毫秒\n     */\n    private long                timestamp;\n\n    private String              cluster;\n\n    private String              node;\n\n    private String              port;\n\n    private String              template;\n\n    /**\n     * 物理模板id\n     */\n    private long                templateId;\n\n    /**\n     * 逻辑模板id\n     */\n    private long                logicTemplateId;\n\n    private String              index;\n\n    /**\n     * 采集出来的原始值\n     */\n    private Double              value;\n\n    private String              valueName;\n\n    /**\n     * 计算后的值\n     */\n    private String              computeValue;\n\n    /**\n     * 衍生计算需要的参数\n     */\n    private Map<String, String> deriveParam = Maps.newHashMap();\n\n    public ESNodeToIndexTempBean() {\n    }\n\n    public ESNodeToIndexTempBean(Double value) {\n        this.value = value;\n    }\n\n    public String getKey() {\n        return getKeyPre() + valueName;\n    }\n\n    //此处不能带上monitorTimestamp2min(timestamp)\n    public String getKeyPre() {\n        return cluster + \"@\" + node + \"@\" + port + \"@\" + index + \"@\";\n    }\n\n    public String getDeriveParam(String name) {\n        return deriveParam.get(name);\n    }\n\n    public Map<String, String> getDeriveParam() {\n        return deriveParam;\n    }\n\n    public void setDeriveParam(Map<String, String> deriveParam) {\n        this.deriveParam = deriveParam;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/MonitorTaskInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * monitor 采集任务信息\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class MonitorTaskInfo {\n\n    /**\n     * 集群名称\n     */\n    private String  clusterName;\n    /**\n     * 任务开始时刻\n     */\n    private Long    startTick;\n    /**\n     * 任务执行耗时\n     */\n    private Long    totalCost;\n    /**\n     * 是否在运行\n     */\n    private Boolean running;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/dashboard/ClusterMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 3/11/22\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ClusterMetrics {\n    /**\n     * 统计的时间戳，单位：毫秒\n     */\n    private Long    timestamp;\n\n    /**\n     * 集群名称\n     */\n    private String  cluster;\n\n    /**\n     * 集群总shard数\n     */\n    private Long    shardNum;\n\n    /**\n     * 单集群写入耗时\n     */\n    private Double  indexingLatency;\n\n    /**\n     * 单集群查询耗时\n     */\n    private Double  searchLatency;\n\n    /**\n     * 单集群写入请求数\n     */\n    private Long    indexReqNum;\n\n    /**\n     * 单集群网关成功率\n     */\n    private Double  gatewaySucPer;\n    /**\n     * 单集群失败率\n     */\n    private Double  gatewayFailedPer;\n\n    /**\n     * 单集群Pending task数\n     */\n    private Long    pendingTaskNum;\n\n    /**\n     * 集群http连接数\n     */\n    private Long    httpNum;\n\n    /**\n     * 写入文档数突增量（上个时间间隔的写文档数的两倍）\n     */\n    private Long    docUprushNum;\n\n    /**\n     * 查询请求数突增量 （上个时间间隔请求数的两倍）\n     */\n    private Long    reqUprushNum;\n\n    /**\n     * _cluster/stats消耗时间 （开始采集到结束采集的时间）\n     */\n    private Long    clusterElapsedTime;\n\n    /**\n     * _node/stats消耗时间 （开始采集到结束采集的时间）\n     */\n    private Long    nodeElapsedTime;\n\n    /**\n     * 指标采集延时\n     */\n    private Long    collectorDelayed;\n\n\n    /**\n     * 消耗时间是否大于5分钟（开始采集到结束采集的时间）\n     */\n    private Boolean clusterElapsedTimeGte5Min;\n\n    /**\n     * 索引数量\n     */\n    private Long indexCount;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/dashboard/ClusterPhyHealthMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 3/14/22\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterPhyHealthMetrics {\n    /**\n     * 当前时间\n     */\n    private Long    timestamp;\n\n    /**\n     * 总物理集群个数\n     */\n    private Integer totalNum;\n\n    /**\n     * green状态集群数\n     */\n    private Integer greenNum;\n\n    /**\n     * yellow状态集群数\n     */\n    private Integer yellowNum;\n\n    /**\n     * red状态集群数\n     */\n    private Integer redNum;\n\n    /**\n     * 未知状态集群数\n     */\n    private Integer unknownNum;\n    \n     /**\n     * green状态集群名称列表\n     */\n    private String  greenClusterListStr;\n\n    /**\n     * yellow状态集群名称列表\n     */\n    private String  yellowClusterListStr;\n\n    /**\n     * red状态集群名称列表\n     */\n    private String  redClusterListStr;\n\n    /**\n     * 未知状态集群名称列表\n     */\n    private String  unknownClusterListStr;\n\n    /**\n     * green状态集群百分比\n     */\n    private Double  greenPercent;\n\n    /**\n     * yellow状态集群百分比\n     */\n    private Double  yellowPercent;\n\n    /**\n     * red状态集群百分比\n     */\n    private Double  redPercent;\n\n    /**\n     * 未知状态集群百分比\n     */\n    private Double  unknownPercent;\n\n    public void computePercent() {\n        if (null == totalNum) {\n            return;\n        }\n\n        this.greenPercent = CommonUtils.divideIntAndFormatDouble(greenNum, totalNum, 5, 100);\n        this.yellowPercent = CommonUtils.divideIntAndFormatDouble(yellowNum, totalNum, 5, 100);\n        this.redPercent = CommonUtils.divideIntAndFormatDouble(redNum, totalNum, 5, 100);\n        this.unknownPercent = CommonUtils.divideIntAndFormatDouble(unknownNum, totalNum, 5, 100);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/dashboard/ClusterThreadPoolQueueMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 3/11/22\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ClusterThreadPoolQueueMetrics {\n    /**\n     * 集群名称\n     */\n    private String cluster;\n    private Long   timestamp;\n    private Long   management;\n    private Long   refresh;\n    private Long   flush;\n    private Long   merge;\n    private Long   search;\n    private Long   write;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/dashboard/DashBoardStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.routing.ESRoutingConstant.*;\n\n/**\n * Created by linyunan on 3/11/22\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DashBoardStats extends BaseESPO {\n    /**\n     * 统计的时间戳，单位：毫秒\n     */\n    private Long                          timestamp;\n    /**\n     * 是否物理集群 0 物理集群 1 逻辑集群\n     */\n    private Integer                       physicCluster;\n\n    /**\n     * dashboard集群信息\n     */\n    private ClusterMetrics                cluster;\n\n    /**\n     * dashboard节点信息\n     */\n    private NodeMetrics                   node;\n\n    /**\n     * dashboard模板信息\n     */\n    private TemplateMetrics               template;\n\n    /**\n     * dashboard索引信息\n     */\n    private IndexMetrics                  index;\n\n    /**\n     * dashboard节点线程queue信息\n     */\n    private ClusterThreadPoolQueueMetrics clusterThreadPoolQueue;\n\n    /**\n     * dashboard状态信息\n     */\n    private ClusterPhyHealthMetrics       clusterPhyHealth;\n\n    @Override\n    public String getKey() {\n        if (null != cluster) {\n            return String.format(\"cluster:%s@%d\", cluster.getCluster(), cluster.getTimestamp());\n        }\n\n        if (null != node) {\n            return String.format(\"%s@node:%s@%d\", node.getCluster(), node.getNode(), node.getTimestamp());\n        }\n\n        if (null != template) {\n            return String.format(\"%s@template:%s@%d\", template.getCluster(), template.getTemplate(),\n                template.getTimestamp());\n        }\n\n        if (null != index) {\n            return String.format(\"%s@index:%s@%d\", index.getCluster(), index.getIndex(), index.getTimestamp());\n        }\n\n        if (null != clusterThreadPoolQueue) {\n            return String.format(\"%s@%s@%d\", clusterThreadPoolQueue.getCluster(), THREAD_POOL_ROUTING,\n                clusterThreadPoolQueue.getTimestamp());\n        }\n\n        if (null != clusterPhyHealth) {\n            return String.format(\"%s@%d\", CLUSTER_PHY_HEALTH_ROUTING, timestamp);\n        }\n\n        return String.format(\"%s@%d\", CLUSTER_PHY_ROUTING, timestamp);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        if (null != cluster) {\n            return String.format(\"cluster:%s\", cluster.getCluster());\n        }\n\n        if (null != node) {\n            return String.format(\"%s@node:%s\", node.getCluster(), node.getNode());\n        }\n\n        if (null != template) {\n            return String.format(\"%s@template:%s\", template.getCluster(), template.getTemplate());\n        }\n\n        if (null != index) {\n            return String.format(\"%s@index:%s\", index.getCluster(), index.getIndex());\n        }\n\n        if (null != clusterThreadPoolQueue) {\n            return String.format(\"%s@%s\", clusterThreadPoolQueue.getCluster(), THREAD_POOL_ROUTING);\n        }\n\n        if (null != clusterPhyHealth) {\n            return CLUSTER_PHY_HEALTH_ROUTING;\n        }\n\n        return CLUSTER_PHY_ROUTING;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/dashboard/IndexMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 3/11/22\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class IndexMetrics {\n    private Long    timestamp;\n    /**\n     * 集群名称\n     */\n    private String  cluster;\n    /**\n     * 索引名称\n     */\n    private String  index;\n    /**\n     * 是否为RED索引\n     */\n    private Boolean red;\n    /**\n     * 是否为单副本索引\n     */\n    private Boolean singReplicate;\n    /**\n     * 是否存在未分配shard\n     */\n    private Boolean unassignedShard;\n    /**\n     * 是否存在大shard\n     */\n    private Boolean bigShard;\n    /**\n     * 是否存在小shard\n     */\n    private Boolean smallShard;\n        /**\n     * shard大小\n     */\n    private Long    shardSize;\n    /**\n     * shard数量\n     */\n    private Long    shardNum;\n    /**\n     * mapping字段个数\n     */\n    private Long    mappingNum;\n    /**\n     * segment个数\n     */\n    private Long    segmentNum;\n    /**\n     * 占用segment内存大小\n     */\n    private Double  segmentMemSize;\n\n    /**\n     * 写入文档数突增量（上个时间间隔的两倍）\n     */\n    private Long    docUprushNum;\n\n    /**\n     * 查询请求数突增量 （上个时间间隔的两倍）\n     */\n    private Long    reqUprushNum;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/dashboard/NodeMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 3/11/22\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class NodeMetrics {\n    /**\n     * 统计的时间戳，单位：毫秒\n     */\n    private Long    timestamp;\n\n    /**\n     * 集群名称\n     */\n    private String  cluster;\n\n    /**\n     * 节点名称\n     */\n    private String  node;\n\n    /**\n     * 是否死亡\n     */\n    private Boolean dead;\n\n    /**\n     * 磁盘利用率超红线节点（阈值85%）\n     */\n    private Double  largeDiskUsage;\n\n    /**\n     * 堆内存利用率超红线（阈值80% 且持续5分钟）\n     */\n    private Double  largeHead;\n\n    /**\n     * CPU利用率超红线节点（80%  持续30分钟）\n     */\n    private Double  largeCpuUsage;\n\n    /**\n     * WriteRejected数\n     */\n    private Long    writeRejectedNum;\n\n    /**\n     * SearchRejected数\n     */\n    private Long    SearchRejectedNum;\n\n    /**\n     * 节点分片个数\n     */\n    private Long    shardNum;\n\n    /**\n     * 节点任务耗时(单位 ms)\n     */\n    private Long    taskConsuming;\n\n    /**\n     * 消耗时间 （开始采集到结束采集的时间）\n     */\n    private Long    nodeElapsedTime;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/stats/dashboard/TemplateMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 3/11/22\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateMetrics {\n    /**\n     * 统计的时间戳，单位：毫秒\n     */\n    private Long   timestamp;\n\n    /**\n     * 集群名称\n     */\n    private String cluster;\n\n    /**\n     * arius-admin模板名称\n     */\n    private String template;\n\n    /**\n     * arius-admin模板id\n     */\n    private Long   templateId;\n\n    /**\n     * 分段(倒排table)数量\n     */\n    private Long   segmentNum;\n\n    /**\n     * Segements内存大小（MB）\n     */\n    private Double segmentMemSize;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/task/OpTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/12/21\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class OpTask extends BaseEntity {\n    /**\n     * 序列化版本号\n     */\n    private static final long serialVersionUID = 1L;\n\n    /**\n     * id\n     */\n    private Integer           id;\n\n    /**\n     * 标题\n     */\n    private String            title;\n\n    /**\n     * 任务类型\n     */\n    private Integer           taskType;\n\n    /**\n     * 业务数据主键\n     */\n    private String            businessKey;\n\n    /**\n     * 任务状态\n     * success:成功 failed:失败\n     * running:执行中 waiting:等待\n     * cancel:取消 pause:暂停\n     */\n    private String            status;\n\n    /**\n     * 创建人\n     */\n    private String            creator;\n\n    /**\n     * 标记删除\n     */\n    private Boolean           deleteFlag;\n\n    /**\n     * expandData\n     */\n    private String            expandData;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/task/detail/AbstractTaskDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.task.detail;\n\n/**\n * @author fengqiongfeng\n * @date 2020/12/21\n */\npublic abstract class AbstractTaskDetail {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/task/detail/DCDRSingleTemplateMasterSlaveSwitchDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.task.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.dcdr.DCDRStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.dcdr.DCDRSwithTypeEnum;\nimport java.util.Date;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DCDRSingleTemplateMasterSlaveSwitchDetail extends AbstractTaskDetail {\n    /**\n     * 任务标题\n     */\n    private String       taskTitle;\n\n    /**\n     * dcdr主从切换类型 1 平滑 2 强切\n     * @see DCDRSwithTypeEnum\n     */\n    private Integer      switchType;\n\n    /**\n     * 模板Id\n     */\n    private Long         templateId;\n\n    /**\n     * 主集群\n     */\n    private String       masterCluster;\n\n    /**\n     * 从集群\n     */\n    private String       slaveCluster;\n\n    /**\n     * dcdr链路删除标识位\n     */\n    private Boolean      deleteDcdrChannelFlag;\n\n    /**\n     * 任务执行进度\n     * 0.创建dcdr\n     * 1.停止向主索引写入数据\n     * 2.确保主从索引数据同步\n     * 3.删除源dcdr模板和索引链路\n     * 4.拷贝主模板的mapping信息到从模板\n     * 5.关闭从索引dcdr索引开关，并打开主索引dcdr索引开关\n     * 6.停止从索引写入\n     * 7.创建新的dcdr链路\n     * 8.恢复主从索引实时写入\n     * 9.主从模板角色切换\n     */\n    private List<String> taskProgressList;\n\n    /**\n     * 任务状态: 0 取消 1 成功 2 执行中 3 失败 4 等待\n     * @see DCDRStatusEnum\n     */\n    private Integer      taskStatus;\n\n    private Date         createTime;\n    private Date         updateTime;\n    /**\n     * 位点差超时时间\n     */\n    private Integer      timeout;\n\n    public void editTaskTitle(String templateName) {\n        this.taskTitle = templateName + \"索引模板主从切换\";\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/task/detail/DCDRTaskDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.task.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Date;\n\n/**\n * @author fengqiongfeng\n * @date 2020/12/21\n */\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DCDRTaskDetail extends AbstractTaskDetail {\n    /**\n     * 开始时间\n     */\n    private Date    createTime;\n\n    /**\n     * 逻辑索引模版Id\n     */\n    private Integer logicTemplateId;\n\n    /**\n     * 逻辑索引模版名称\n     */\n    private String  logicTemplateName;\n\n    /**\n     * 所属逻辑集群名称\n     */\n    private String  logicClusterName;\n\n    /**\n     * 主物理索引模版\n     */\n    private String  masterPhysicalTemplateName;\n\n    /**\n     * 所属主物理集群名称\n     */\n    private String  masterPhysicalClusterName;\n\n    /**\n     * 副物理索引模版\n     */\n    private String  slavePhysicalTemplateName;\n\n    /**\n     * 所属副物理集群名称\n     */\n    private String  slavePhysicalClusterName;\n\n    /**\n     * 任务状态\n     * success:成功 failed:失败\n     * running:执行中\n     */\n    private String  status;\n\n    /**\n     * 任务执行进度\n     * 0.创建dcdr\n     * 1.停止向主索引写入数据\n     * 2.确保主从索引数据同步\n     * 3.删除源dcdr模板和索引链路\n     * 4.拷贝主模板的mapping信息到从模板\n     * 5.关闭从索引dcdr索引开关，并打开主索引dcdr索引开关\n     * 6.停止从索引写入\n     * 7.创建新的dcdr链路\n     * 8.恢复主从索引实时写入\n     * 9.主从模板角色切换\n     */\n    private Integer taskProgress;\n\n    /**\n     * 备注\n     */\n    private String  comment;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/task/detail/DCDRTasksDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.task.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.dcdr.DCDRStatusEnum;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * dcdr tasks Detail\n *\n * @author\n * @date 2022/05/09\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DCDRTasksDetail extends AbstractTaskDetail {\n    private List<DCDRSingleTemplateMasterSlaveSwitchDetail> dcdrSingleTemplateMasterSlaveSwitchDetailList;\n\n    private int                                             total;\n    private int                                             successNum;\n    private int                                             failedNum;\n    private int                                             runningNum;\n    private int                                             cancelNum;\n    private int                                             waitNum;\n\n    /**\n     * 0 取消 1 成功 2 运行中 3 失败 4 待运行\n     */\n    private int                                             state;\n\n    private int                                             percent;\n\n    public void calculateProcess() {\n        int successNum = 0;\n        int failedNum = 0;\n        int runningNum = 0;\n        int cancelNum = 0;\n        int waitNum = 0;\n\n        for (DCDRSingleTemplateMasterSlaveSwitchDetail dcdrSingleTemplateMasterSlaveSwitchDetail : this.dcdrSingleTemplateMasterSlaveSwitchDetailList) {\n            if (DCDRStatusEnum.SUCCESS.getCode().equals(dcdrSingleTemplateMasterSlaveSwitchDetail.getTaskStatus())) {\n                successNum++;\n            }\n            if (DCDRStatusEnum.CANCELLED.getCode().equals(dcdrSingleTemplateMasterSlaveSwitchDetail.getTaskStatus())) {\n                cancelNum++;\n            }\n            if (DCDRStatusEnum.RUNNING.getCode().equals(dcdrSingleTemplateMasterSlaveSwitchDetail.getTaskStatus())) {\n                runningNum++;\n            }\n            if (DCDRStatusEnum.FAILED.getCode().equals(dcdrSingleTemplateMasterSlaveSwitchDetail.getTaskStatus())) {\n                failedNum++;\n            }\n            if (DCDRStatusEnum.WAIT.getCode().equals(dcdrSingleTemplateMasterSlaveSwitchDetail.getTaskStatus())) {\n                waitNum++;\n            }\n        }\n\n        this.total = this.dcdrSingleTemplateMasterSlaveSwitchDetailList.size();\n        this.successNum = successNum;\n        this.failedNum = failedNum;\n        this.runningNum = runningNum;\n        this.cancelNum = cancelNum;\n        this.waitNum = waitNum;\n        this.percent = successNum * 100 / this.total;\n\n        if (runningNum > 0) {\n            this.state = DCDRStatusEnum.RUNNING.getCode();\n            return;\n        }\n        if (failedNum > 0) {\n            this.state = DCDRStatusEnum.FAILED.getCode();\n            return;\n        }\n        if (cancelNum == this.dcdrSingleTemplateMasterSlaveSwitchDetailList.size()) {\n            this.state = DCDRStatusEnum.CANCELLED.getCode();\n            return;\n        }\n        if (cancelNum > 0 && (cancelNum + successNum) == this.dcdrSingleTemplateMasterSlaveSwitchDetailList.size()) {\n            this.state = DCDRStatusEnum.CANCELLED.getCode();\n            return;\n        }\n        if (successNum > 0 && successNum == this.dcdrSingleTemplateMasterSlaveSwitchDetailList.size()) {\n            this.state = DCDRStatusEnum.SUCCESS.getCode();\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/DslMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2018/9/18 下午5:24\n * @modified By\n *\n * 查询模板一分钟聚合指标统计信息\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslMetrics {\n    /**\n     * 创建时间\n     */\n    private String  ariusCreateTime;\n    /**\n     * 日期时间\n     */\n    private String  logTime;\n    /**\n     * sink写入时间\n     */\n    private Long    sinkTime;\n    /**\n     * flink写入时间\n     */\n    private String  flinkTime;\n    /**\n     * 响应平均长度\n     */\n    private Double  responseLenAvg;\n    /**\n     * 请求类型 http/tcp\n     */\n    private String  requestType;\n    /**\n     * 查询类型 dsl/sql\n     */\n    private String  searchType;\n    /**\n     * 查询次数\n     */\n    private Long    searchCount;\n    /**\n     * 查询es平均耗时\n     */\n    private Double  esCostAvg;\n    /**\n     * 查询语句平均长度\n     */\n    private Double  dslLenAvg;\n    /**\n     * 查询平均命中记录数\n     */\n    private Double  totalHitsAvg;\n    /**\n     * 查询成功平均shard数\n     */\n    private Double  successfulShardsAvg;\n    /**\n     * 查询平均总shard数\n     */\n    private Double  totalShardsAvg;\n    /**\n     * 查询索引示例\n     */\n    private String  indiceSample;\n    /**\n     * 查询模板\n     */\n    private String  dslTemplate;\n    /**\n     * 记录生成时间戳\n     */\n    private Long    timeStamp;\n    /**\n     * dsl语句类型 normal/agg等\n     */\n    private String  dslType;\n    /**\n     * 查询索引名称，去重后的\n     */\n    private String  indices;\n    /**\n     * 查询模板\n     */\n    private String  dslTemplateMd5;\n    /**\n     * 查询平均总耗时\n     */\n    private Double  totalCostAvg;\n    /**\n     * 查询平均失败shard数\n     */\n    private Double  failedShardsAvg;\n    /**\n     * projectId\n     */\n    private Integer projectId;\n    /**\n     * 查询语句\n     */\n    private String  dsl;\n    /**\n     * gateway处理平均耗时\n     */\n    private Double  beforeCostAvg;\n    /**\n     * dsl查询限流值\n     */\n    private Double  queryLimit;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/DslTemplate.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/15 下午6:39\n * @modified By D10865\n *\n * dsl模板信息\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslTemplate {\n    /**\n     * 查询模板创建时间\n     */\n    private String  ariusCreateTime;\n    /**\n     * 查询模板修改时间\n     */\n    private String  ariusModifyTime;\n    /**\n     * 平均响应长度\n     */\n    private Double  responseLenAvg;\n    /**\n     * 请求类型\n     */\n    private String  requestType;\n    /**\n     * 查询类型\n     */\n    private String  searchType;\n    /**\n     * 查询次数(分钟级别)\n     */\n    private Long    searchCount;\n    /**\n     * es查询耗时\n     */\n    private Double  esCostAvg;\n    /**\n     * 平均查询语句长度\n     */\n    private Double  dslLenAvg;\n    /**\n     * 平均命中记录数\n     */\n    private Double  totalHitsAvg;\n    /**\n     * 平均查询shard成功个数\n     */\n    private Double  successfulShardsAvg;\n    /**\n     * 平均shard成功个数\n     */\n    private Double  totalShardsAvg;\n    /**\n     * 查询请求时刻\n     */\n    private String  logTime;\n    /**\n     * 查询索引示例\n     */\n    private String  indiceSample;\n    /**\n     * 查询模板\n     */\n    private String  dslTemplet;\n    /**\n     * 查询请求时刻\n     */\n    private Long    timeStamp;\n    /**\n     * 查询语句类型\n     */\n    private String  dslType;\n    /**\n     * 查询索引名称\n     */\n    private String  indices;\n    /**\n     * 查询模板MD5\n     */\n    private String  dslTemplateMd5;\n    /**\n     * 平均查询总耗时\n     */\n    private Double  totalCostAvg;\n    /**\n     * 查询shard失败个数\n     */\n    private Double  failedShardsAvg;\n    /**\n     * dsink写入时间\n     */\n    private Long    sinkTime;\n    /**\n     * projectId\n     */\n    private Integer projectId;\n    /**\n     * 查询语句\n     */\n    private String  dsl;\n    /**\n     * 平均gateway处理耗时\n     */\n    private Double  beforeCostAvg;\n    /**\n     * flin\n     */\n    private String  flinkTime;\n    /**\n     * 查询限流\n     */\n    private Double  queryLimit;\n    /**\n     * 是否来自用户控制台\n     */\n    private Boolean isFromUserConsole;\n    /**\n     * 是否强制设置查询限流值\n     */\n    private Boolean forceSetQueryLimit;\n    /**\n     * 是否可用 null/true表示可用，false表示不可用\n     */\n    private Boolean enable;\n    /**\n     * 黑白名单 null/white表示白名单，black表示黑名单\n     */\n    private String  checkMode;\n    /**\n     * 慢查dsl阈值，单位为ms\n     */\n    private Long    slowDslThreshold;\n    /**\n     * 查询模板版本号\n     */\n    private String  version;\n    /**\n     * 查询模板危害标签\n     */\n    private String  dslTag;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/ESPipeline.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * es pipeline\n *\n * @author shizeying\n * @date 2022/08/12\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ESPipeline {\n    private String  cluster;\n    private String  pipelineId;\n    private String  dateField;\n    private String  dateFieldFormat;\n    private String  dateFormat;\n    private Integer expireDay;\n    private Integer rateLimit;\n    private Integer version;\n    private String  idField;\n    private String  routingField;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/GatewayJoin.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport java.util.Map;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2018/9/19 下午5:36\n * @modified By\n *\n * join 后的gateway日志\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class GatewayJoin {\n\n    /**\n     * 请求path\n     */\n    private String            uri;\n    /**\n     * 请求id\n     */\n    private String            requestId;\n    /**\n     * projectid\n     */\n    private Integer           projectId;\n    /**\n     * 索引名称\n     */\n    private String            indices;\n    /**\n     * type名称\n     */\n    private String            typeName;\n    /**\n     * 查询命中索引信息json\n     */\n    private String            index;\n    /**\n     * 查询语句\n     */\n    private String            dsl;\n    /**\n     * 查询模板\n     */\n    private String            dslTemplate;\n    /**\n     * 查询模板MD5\n     */\n    private String            dslTemplateMd5;\n    /**\n     * 是否超时，\"true\"/\"false\"\n     */\n    private String            isTimedOut;\n    /**\n     * 查询语句类型\n     */\n    private String            dslType;\n    /**\n     * 查询方式,dsl/sql\n     */\n    private String            searchType;\n    /**\n     * 查询es耗时\n     */\n    private Long              esCost;\n    /**\n     * 查询总耗时\n     */\n    private Long              totalCost;\n    /**\n     * 查询shard个数\n     */\n    private Long              totalShards;\n    /**\n     * 查询总命中数\n     */\n    private Long              totalHits;\n    /**\n     * 查询响应长度\n     */\n    private Long              responseLen;\n    /**\n     * 错误名称\n     */\n    private String            exceptionName;\n    /**\n     * 创建时间\n     */\n    private String            ariusCreateTime;\n    /**\n     * timeStamp\n     */\n    private long              timeStamp;\n    /**\n     * indiceSample\n     */\n    private String            indiceSample;\n    /**\n     * 查询字段\n     */\n    private Map<String, Long> selectFields;\n    /**\n     * 过滤字段\n     */\n    private Map<String, Long> whereFields;\n    /**\n     * 聚合字段\n     */\n    private Map<String, Long> groupByFields;\n    /**\n     *排序字段\n     */\n    private Map<String, Long> orderByFields;\n    /**\n     * 多type索引查询映射后的索引名称\n     */\n    private String            destIndexName;\n    /**\n     * 请求源ip\n     */\n    private String            remoteAddr;\n\n    private String            clusterName;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplate.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplate extends BaseEntity implements Comparable<IndexTemplate> {\n\n    private Integer id;\n\n    /**\n     * 索引模板名称\n     */\n    private String  name;\n\n    /**\n     * projectId\n     */\n    private Integer projectId;\n\n    /**\n     * 用户数据类型\n     * @see DataTypeEnum\n     */\n    private Integer dataType;\n\n    /**\n     * 索引滚动格式\n     */\n    private String  dateFormat;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n\n    /**\n     * 数据保存时长 单位天\n     */\n    private Integer expireTime;\n\n    /**\n     * 热数据保存时长 单位天\n     */\n    private Integer hotTime;\n\n    /**\n     * 副本保存时长 单位天\n     */\n    private Integer replicaTime;\n\n\n\n\n\n    /**\n     * 时间字段\n     */\n    private String  dateField;\n\n    /**\n     * 时间字段的格式\n     */\n    private String  dateFieldFormat;\n\n    /**\n     * id字段\n     */\n    private String  idField;\n\n    /**\n     * routing字段\n     */\n    private String  routingField;\n\n    /**\n     * 表达式\n     */\n    private String  expression;\n\n    /**\n     * 逻辑集群id\n     */\n    private Long    resourceId;\n\n    /**\n     * 备注\n     */\n    private String  desc;\n\n    /**\n     * 规格 单位台 每台的资源量就是DOCKER类型的规格的资源；与物理部署的模板无关\n     */\n    private Double  quota;\n\n    /**\n     * 写入限流值，\n     * writeRateLimit = 0 禁止写入，\n     * writeRateLimit = -1 不限流，\n     * writeRateLimit = 123 具体的写入tps限流值，即单台client每秒写入123条文档\n     */\n    private Integer writeRateLimit;\n\n    /**\n     * pipeline\n     */\n    private String  ingestPipeline;\n\n    /**\n     * 是否禁止读\n     */\n    private Boolean blockRead;\n\n    /**\n     * 是否禁止写\n     */\n    private Boolean blockWrite;\n\n    /**\n     * 服务等级\n     */\n    private Integer level;\n\n    /**\n     * 是否开启dcdr\n     */\n    private Boolean hasDCDR;\n\n    /**\n     * 数据位点差\n     */\n    private Long    checkPointDiff;\n\n    /**\n     * 已开启的模板服务\n     */\n    private String  openSrv;\n    /**\n     * regionId\n     */\n    private Integer regionId;\n\n    /**\n     * 可用磁盘容量\n     */\n    private Double diskSize;\n    /**\n     * 模版健康度\n     */\n    private Integer health;\n\n    @Override\n    public int compareTo(IndexTemplate o) {\n        if (null == o) {\n            return 0;\n        }\n\n        return o.getId().intValue() - this.getId().intValue();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplateAlias.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-07-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateAlias extends BaseEntity {\n\n    private int     id;\n\n    private Integer logicId;\n\n    private String  name;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplateConfig.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateConfig extends BaseEntity {\n\n    /**\n     * 主键\n     */\n    private Long    id;\n\n    /**\n     * 逻辑模板id\n     */\n    private Integer logicId;\n\n    /**\n     * 索引存储分离开关 默认关闭\n     */\n    private Integer isSourceSeparated;\n\n    /**\n     * 资源调整tps系数  默认1.0\n     */\n    private Double  adjustTpsFactor;\n\n    /**\n     * 资源调整  默认1.0\n     */\n    private Double  adjustShardFactor;\n\n    /**\n     * 写入动态限流开关  默认打开\n     */\n    private Integer dynamicLimitEnable;\n\n    /**\n     * mapping优化开关  默认关闭\n     */\n    private Integer mappingImproveEnable;\n\n    /**\n     * 预创建分区索引标识，0：不预先创建；1：预先创建\n     */\n    private Boolean preCreateFlags;\n\n    /**\n     * 禁用报错_source标识，0：不禁用；1：禁用\n     */\n    private Boolean disableSourceFlags;\n\n    /**\n     * 限定逻辑模板下所有物理模板shardNum\n     */\n    private Integer shardNum;\n\n    /**\n     * indexRollover功能，0：不禁用；1：禁用\n     */\n    private Boolean disableIndexRollover;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplateLogicAggregate.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.IndexTemplateValue;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport java.io.Serializable;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 逻辑模板聚合类\n * @author wangshu\n * @date 2020/09/11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateLogicAggregate implements Serializable {\n\n    /**\n     * 具备逻辑集群信息的逻辑模板详情信息\n     */\n    private IndexTemplateWithCluster indexTemplateLogicWithCluster;\n\n    /**\n     * APP对当前模板的权限\n     */\n    private ProjectTemplateAuth      projectTemplateAuth;\n\n    /**\n     * 模板健康分\n     */\n    private IndexTemplateValue       indexTemplateValue;\n\n    /**\n     * 是否具有DCDR\n     */\n    private Boolean                  hasDCDR;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplateLogicWithClusterAndMasterTemplate.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateLogicWithClusterAndMasterTemplate extends IndexTemplate {\n\n    /**\n     * Master物理模板\n     */\n    private IndexTemplatePhy masterTemplate;\n\n    /**\n     * 逻辑集群\n     */\n    private ClusterLogic     logicCluster;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplatePhy.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.IndexTemplatePhysicalConfig;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplatePhysicalStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author chengxiang\n * @date 2022/5/10\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplatePhy extends BaseEntity {\n\n    /**\n     * 主键\n     */\n    private Long    id;\n\n    /**\n     * 逻辑模板id\n     */\n    private Integer logicId;\n\n    /**\n     * 模板名称\n     */\n    private String  name;\n\n    /**\n     * 表达式\n     */\n    private String  expression;\n\n    /**\n     * 集群\n     */\n    private String  cluster;\n\n    /**\n     * rack\n     */\n    private String  rack;\n\n    /**\n     * shard个数\n     */\n    private Integer shard;\n\n    /**\n     * shardRouting个数\n     */\n    private Integer shardRouting;\n\n    /**\n     * 版本\n     */\n    private Integer version;\n\n    /**\n     * 角色\n     * @see TemplateDeployRoleEnum\n     */\n    private Integer role;\n\n    /**\n     * 状态\n     * @see TemplatePhysicalStatusEnum\n     */\n    private Integer status;\n\n    /**\n     * 配置 json格式\n     */\n    private String  config;\n\n    /**\n     * regionId\n     */\n    private Integer regionId;\n\n    /**\n     * 获取并且解析config\n     * @return\n     */\n    public IndexTemplatePhysicalConfig fetchConfig() {\n        IndexTemplatePhysicalConfig physicalConfig = null;\n        if (StringUtils.isNotBlank(config)) {\n            try {\n                physicalConfig = JSON.parseObject(config, IndexTemplatePhysicalConfig.class);\n            } catch (Exception e) {\n                return null;\n            }\n        }\n        return physicalConfig;\n    }\n\n    /**\n     * 获取默认写标识\n     * @return\n     */\n    public Boolean fetchDefaultWriterFlags() {\n        IndexTemplatePhysicalConfig physicalConfig = fetchConfig();\n        if (physicalConfig != null && physicalConfig.getDefaultWriterFlags() != null) {\n            return physicalConfig.getDefaultWriterFlags();\n        }\n        return AdminConstant.DEFAULT_WRITER_FLAGS;\n    }\n\n    /**\n     * 获取组ID信息\n     * @return\n     */\n    public String getGroupId() {\n        IndexTemplatePhysicalConfig physicalConfig = fetchConfig();\n        if (physicalConfig != null && StringUtils.isNotBlank(physicalConfig.getGroupId())) {\n            return physicalConfig.getGroupId();\n        }\n        return AdminConstant.DEFAULT_GROUP_ID;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplatePhyAlias.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.alibaba.fastjson.JSONObject;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n/**\n * 物理模板别名\n * @author wangshu\n * @date 2020/08/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplatePhyAlias implements Serializable {\n\n    /**\n     * 模板别名名称\n     */\n    private String     alias;\n\n    /**\n     * 别名过滤器\n     */\n    private JSONObject filter;\n\n    /**\n     * 转换成别名JSON\n     * @return\n     */\n    public JSONObject toAliasesJSON() {\n        JSONObject aliases = new JSONObject();\n        aliases.put(alias, filter);\n        return aliases;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplatePhyAliases.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.alibaba.fastjson.JSONObject;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\n@Data\n@NoArgsConstructor\npublic class IndexTemplatePhyAliases implements Serializable {\n    private JSONObject aliases;\n\n    public IndexTemplatePhyAliases(JSONObject aliases) {\n        this.aliases = aliases;\n    }\n\n    /**\n     * Check别名是否存在\n     * @param aliasName 别名名称\n     * @return\n     */\n    public boolean isAliasExists(String aliasName) {\n        if (StringUtils.isNotBlank(aliasName) && aliases != null) {\n            return aliases.containsKey(aliasName);\n        }\n\n        return false;\n    }\n\n    /**\n     * 删除别名\n     * @param aliasName 别名名称\n     */\n    public void removeAlias(String aliasName) {\n        if (StringUtils.isNotBlank(aliasName)) {\n            this.aliases.remove(aliasName);\n        }\n    }\n\n    /**\n     * 增加别名\n     * @param aliasName 别名名称\n     * @param filter Filter\n     * @return\n     */\n    public boolean putAlias(String aliasName, JSONObject filter) {\n        if (StringUtils.isNotBlank(aliasName) && filter != null) {\n            this.aliases.put(aliasName, filter);\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * 获取别名列表信息\n     * @return\n     */\n    public List<IndexTemplatePhyAlias> parseTemplateAliases() {\n        List<IndexTemplatePhyAlias> parsedAliases = new ArrayList<>();\n        if (aliases != null) {\n            for (Map.Entry<String, Object> alias : aliases.entrySet()) {\n                IndexTemplatePhyAlias templateAlias = new IndexTemplatePhyAlias();\n                templateAlias.setAlias(alias.getKey());\n                parsedAliases.add(templateAlias);\n            }\n        }\n\n        return parsedAliases;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplatePhySetting.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didiglobal.knowframework.elasticsearch.client.utils.JsonUtils;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\nimport java.util.Map;\n\n/**\n * 物理模板Settings Entity.\n * @author wangshu\n * @date 2020/08/24\n */\n@Data\n@NoArgsConstructor\npublic class IndexTemplatePhySetting implements Serializable {\n    private JSONObject settings;\n\n    /**\n     * 构造函数\n     * @param settings JSON settings\n     */\n    public IndexTemplatePhySetting(JSONObject settings) {\n        this.settings = settings;\n    }\n\n    public IndexTemplatePhySetting(Map<String, String> settings) {\n        reset(settings);\n    }\n\n    /**\n     * 重置settings信息\n     * @param currentSettings 最新settings信息\n     */\n    public void reset(Map<String, String> currentSettings) {\n        if (currentSettings != null) {\n            settings = JsonUtils.reFlat(currentSettings);\n        } else {\n            settings = null;\n        }\n    }\n\n    /**\n     * 扁平化settings.\n     * @return\n     */\n    public Map<String, String> flatSettings() {\n        return JsonUtils.flat(settings);\n    }\n\n    /**\n     * merge增量settings信息\n     * @param incrementalSettings 增量settings.\n     */\n    public Map<String, String> merge(Map<String, String> incrementalSettings) {\n        Map<String, String> finalSettings = flatSettings();\n        if (incrementalSettings != null) {\n            finalSettings.putAll(incrementalSettings);\n            reset(finalSettings);\n        }\n        return finalSettings;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplatePhyWithLogic.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplatePhyWithLogic extends IndexTemplatePhy {\n\n    /**\n     * 逻辑模板信息\n     */\n    private IndexTemplate logicTemplate;\n\n    public boolean hasLogic() {\n        return getLogicTemplate() != null;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplateType.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019-07-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateType extends BaseEntity {\n\n    private Integer id;\n\n    private String  name;\n\n    private String  idField;\n\n    private Boolean source;\n\n    private String  routing;\n\n    private String  indexTemplateName;\n\n    private Integer indexTemplateId;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplateWithCluster.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateWithCluster extends IndexTemplate {\n    /**\n     * 逻辑集群信息\n     */\n    private List<ClusterLogic> logicClusters;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplateWithLabels.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Label;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateWithLabels extends IndexTemplate {\n\n    private List<Label> labels;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplateWithMapping.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.mapping.Field;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateWithMapping extends IndexTemplate {\n\n    private List<Field>             fields;\n\n    private List<AriusTypeProperty> typeProperties;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplateWithPhyTemplates.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.apache.commons.collections4.CollectionUtils;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateWithPhyTemplates extends IndexTemplate {\n\n    /**\n     * 物理模板信息\n     */\n    private List<IndexTemplatePhy> physicals;\n\n    public boolean hasPhysicals() {\n        return CollectionUtils.isNotEmpty(physicals);\n    }\n\n    public IndexTemplatePhy getMasterPhyTemplate() {\n        if (CollectionUtils.isNotEmpty(physicals)) {\n            for (IndexTemplatePhy physical : physicals) {\n                if (physical.getRole().equals(TemplateDeployRoleEnum.MASTER.getCode())) {\n                    return physical;\n                }\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 获取逻辑索引模板所有的master物理所有模板列表\n     * @return\n     */\n    public List<IndexTemplatePhy> fetchMasterPhysicalTemplates() {\n        List<IndexTemplatePhy> masterTemplates = new ArrayList<>();\n        if (CollectionUtils.isNotEmpty(physicals)) {\n            for (IndexTemplatePhy physical : physicals) {\n                if (TemplateDeployRoleEnum.MASTER.getCode().equals(physical.getRole())) {\n                    masterTemplates.add(physical);\n                }\n            }\n        }\n        return masterTemplates;\n    }\n\n    /**\n     * 获取master对应的slave物理模板\n     * @param groupId 组ID\n     * @return\n     */\n    public IndexTemplatePhy fetchMasterSlave(String groupId) {\n        List<IndexTemplatePhy> physicalsTemp = fetchMasterSlaves(groupId);\n        if (!physicalsTemp.isEmpty()) {\n            return physicalsTemp.get(0);\n        }\n        return null;\n    }\n\n    /**\n     * 获取逻辑模板下GroupId相同的所有的物理模板列表\n     * @param groupId 组ID\n     * @return\n     */\n    public List<IndexTemplatePhy> fetchMasterSlaves(String groupId) {\n        List<IndexTemplatePhy> templatePhysicals = new ArrayList<>();\n        if (CollectionUtils.isNotEmpty(physicals)) {\n            for (IndexTemplatePhy physical : physicals) {\n                if (TemplateDeployRoleEnum.SLAVE.getCode().equals(physical.getRole())\n                    && physical.getGroupId().equals(groupId)) {\n                    templatePhysicals.add(physical);\n                }\n            }\n        }\n        return templatePhysicals;\n    }\n\n    public IndexTemplatePhy getSlavePhyTemplate() {\n        if (CollectionUtils.isNotEmpty(physicals)) {\n            for (IndexTemplatePhy physical : physicals) {\n                if (physical.getRole().equals(TemplateDeployRoleEnum.SLAVE.getCode())) {\n                    return physical;\n                }\n            }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/IndexTemplateWithStats.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Set;\n\n/**\n *\n * @author apsarazhouyunfan\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplateWithStats extends IndexTemplate {\n\n    /**\n     * 平均tps\n     */\n    private Double      avgTps;\n\n    /**\n     * 平均qps\n     */\n    private Double      avgQps;\n\n    /**\n     * 实际的磁盘消耗\n     */\n    private Double      actualDiskG;\n\n    /**\n     * 索引成本\n     */\n    private Double      cost;\n\n    /**\n     * 索引存储容量\n     */\n    private double      store;\n\n    /**\n     * 索引健康分\n     */\n    private Double      indexHealthDegree;\n\n    /**\n     * 索引价值分\n     */\n    private Double      indexValueDegree;\n\n    /**\n     * 不健康标签\n     */\n    private Set<String> unhealthyLabels;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/ProjectTemplateAccessCount.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\nimport java.util.Map;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/27 下午2:19\n * @modified By D10865\n *\n * projectid访问索引模板级别次数\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@Accessors(chain = true)\npublic class ProjectTemplateAccessCount {\n    /**\n     * 索引模板主键\n     */\n    private Integer                                                  templateId;\n    /**\n     * 索引逻辑id\n     */\n    private Integer                                                  logicTemplateId;\n    /**\n     * 索引模板名称\n     */\n    private String                                                   templateName;\n    /**\n     * 集群名称\n     */\n    private String                                                   clusterName;\n    /**\n     * 应用账号\n     */\n    private Integer                                                  projectId;\n    /**\n     * 访问索引模板次数，为@accessDetailInfo 访问索引明细的总次数\n     */\n    private Long                                                     count;\n    /**\n     *访问索引名称明细数据,key不能是.开头，否则写入es失败\n     */\n    private Map<String/*indexName*/, Long/*access indexName count*/> accessDetailInfo;\n    /**\n     * 统计日期\n     */\n    private String                                                   date;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/TemplateHealthDegreeRecord.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateLabelPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateHealthDegreeRecord {\n\n    /**\n     * 统计时间\n     */\n    private Long          timestamp;\n\n    /**\n     * 索引模板id\n     */\n    private Integer       logicTemplateId;\n\n    /**\n     * 健康分\n     */\n    private Integer       healthDegree;\n\n    /**\n     * 标签\n     */\n    List<TemplateLabelPO> labelPOS;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/TemplateStatsInfo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 索引的基本统计信息\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateStatsInfo {\n    /**\n     * 模板id\n     */\n    private Long         templateId;\n    /**\n     * 模板名称\n     */\n    private String       templateName;\n    /**\n     * 索引健康分\n     */\n    private double       indexHealthDegree;\n    /**\n     * 索引存储容量\n     */\n    private double       store;\n    /**\n     * 索引qutoa\n     */\n    private double       qutoa;\n    /**\n     * 索引成本\n     */\n    private double       cost;\n    /**\n     * 索引昨日访问均量\n     */\n    private double       accessCountPreDay;\n    /**\n     * 索引文档数\n     */\n    private long         docNu;\n    /**\n     * 索引昨日峰值写入tps\n     */\n    private double       writeTps;\n    /**\n     * 索引对应的topic\n     */\n    private List<String> topics = new ArrayList<>();\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/TemplateValueRecord.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateValueRecord {\n    /**\n     * 统计时间\n     */\n    private Long    timestamp;\n    /**\n     * 索引模板id\n     */\n    private Integer logicTemplateId;\n    /**\n     * 价值\n     */\n    private Integer value;\n    /**\n     * 访问量\n     */\n    private Long    accessCount;\n    /**\n     * 大小G\n     */\n    private Double  sizeG;\n    /**\n     * 逻辑集群\n     */\n    private String  logicCluster;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/srv/TemplateSrv.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateServiceEnum;\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author chengxiang\n * @date 2022/5/11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateSrv extends BaseEntity {\n\n    /**\n     * 模板服务code\n     */\n    protected Integer srvCode;\n\n    /**\n     * 模板服务名称\n     */\n    protected String  srvName;\n\n\n\n    public static List<TemplateSrv> codeStr2SrvList(String codeStr) {\n        if (StringUtils.isBlank(codeStr)) {\n            return new ArrayList<>();\n        }\n\n        List<TemplateSrv> srvList = new ArrayList<>();\n        for (String srvId : StringUtils.split(codeStr, \",\")) {\n            TemplateSrv templateSrv = getSrv(Integer.parseInt(srvId));\n            if (null != templateSrv) {\n                srvList.add(templateSrv);\n            }\n        }\n\n        return srvList;\n    }\n\n    public static TemplateSrv getSrv(Integer templateSrvCode) {\n        TemplateServiceEnum srvEnum = TemplateServiceEnum.getById(templateSrvCode);\n        return new TemplateSrv(srvEnum.getCode(), srvEnum.getServiceName());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/template/srv/UnavailableTemplateSrv.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.template.srv;\n\nimport lombok.Data;\n\n/**\n * @author chengxiang\n * @date 2022/5/20\n */\n@Data\npublic class UnavailableTemplateSrv extends TemplateSrv {\n\n    /**\n     * 不可用原因\n     */\n    private String unavailableReason;\n\n    public UnavailableTemplateSrv(Integer srvCode, String srvName, String esVersion, String unavailableReason) {\n        super(srvCode, srvName);\n        this.unavailableReason = unavailableReason;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/weekly/AppQuery.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.weekly;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author: CT17534\n * @date: 2020-03-15 19:56\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class AppQuery extends BaseEntity {\n    /**\n     * 模板名称\n     */\n    private String       indiceSample;\n\n    /**\n     * dsl查询模版\n     */\n    private String       dslTemplate;\n\n    /**\n     * dsl查询时间\n     */\n    private String       timeStamp;\n\n    /**\n     * 模版MD5\n     */\n    private List<String> dslTemplateMd5;\n\n    /**\n     * 查询耗时\n     */\n    private Integer      totalCost;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/WorkOrder.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/4/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class WorkOrder extends BaseEntity {\n    /**\n     * id\n     */\n    private Long    id;\n\n    /**\n     * 工单类型\n     */\n    private String  type;\n\n    /**\n     * 工单标题\n     */\n    private String  title;\n\n    /**\n     * 结构化的工单内容 json\n     */\n    private Object  contentObj;\n\n    /**\n     * 提交人\n     */\n    private String  submitor;\n\n    /**\n     * 提交人projectid\n     */\n    private Integer submitorProjectId;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n\n    /**\n     * 审批信息\n     */\n    private String  opinion;\n\n    /**\n     * 申请原因\n     */\n    private String  description;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/AbstractOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\npublic abstract class AbstractOrderDetail extends BaseEntity {\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/BaseClusterHostOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport java.io.Serializable;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class BaseClusterHostOrderDetail extends AbstractOrderDetail implements Serializable {\n\n    /**\n     * 物理集群名称\n     */\n    private String                  phyClusterName;\n\n    /**\n     * type 3:docker 4:host\n     */\n    private int                     type;\n\n    /**\n     * 单机实例数\n     */\n    private Integer                 pidCount;\n\n    /**\n     * 集群角色 对应的变动的主机列表\n     */\n    private List<ESClusterRoleHost> roleClusterHosts;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/ClusterDeleteOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-06-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterDeleteOrderDetail extends AbstractOrderDetail {\n    /**\n     * type 3:docker 4:host\n     */\n    private Integer type;\n\n    /**\n     * 物理集群名称\n     */\n    private String  phyClusterName;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/ClusterLogicTransferOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-06-17\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterLogicTransferOrderDetail extends AbstractOrderDetail {\n\n    private Integer targetProjectId;\n\n    private Integer sourceProjectId;\n\n    private Long    clusterLogicId;\n\n    private String  clusterLogicName;\n\n\n    private String  memo;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/ClusterOpIndecreaseDockerOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleDocker;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterOpIndecreaseDockerOrderDetail extends AbstractOrderDetail {\n\n    /**\n     * type 3:docker 4:host\n     */\n    private Integer                   type;\n\n    /**\n     * 物理集群id\n     */\n    private Long                      phyClusterId;\n    /**\n     * 物理集群名称\n     */\n    private String                    phyClusterName;\n\n    /**\n     * 2:扩容 3：缩容\n     */\n    private Integer                   operationType;\n\n    /**\n     * 集群角色列表\n     */\n    private List<ESClusterRoleDocker> roleClusters;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/ClusterOpIndecreaseHostOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport java.io.Serializable;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterOpIndecreaseHostOrderDetail extends BaseClusterHostOrderDetail implements Serializable {\n\n    /**\n     * 物理集群id\n     */\n    private Long                    phyClusterId;\n    /**\n     * 2:扩容 3：缩容\n     */\n    private Integer                 operationType;\n    /**\n     * 集群角色 对应的原始的主机列表\n     */\n    private List<ESClusterRoleHost> originRoleClusterHosts;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/ClusterOpNewDockerOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleDocker;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterOpNewDockerOrderDetail extends AbstractOrderDetail {\n\n    /**\n     * type 3:docker 4:host\n     */\n    private int                       type;\n\n    /**\n     * 数据中心\n     */\n    private String                    dataCenter;\n    /**\n     * 机器节点\n     */\n    private String                    nsTree;\n\n    /**\n     * 机房\n     */\n    private String                    idc;\n\n    /**\n     * es版本\n     */\n    private String                    esVersion;\n\n    /**\n     * 插件包ID列表\n     */\n    private String                    plugs;\n\n    /**\n     * 集群创建人\n     */\n    private String                    creator;\n\n    /**\n     * 描述\n     */\n    private String                    desc;\n\n    /**\n     * 集群角色列表\n     */\n    private List<ESClusterRoleDocker> roleClusters;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/ClusterOpNewHostOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterOpNewHostOrderDetail extends BaseClusterHostOrderDetail {\n\n    /**\n     * 数据中心\n     */\n    private String dataCenter;\n\n    /**\n     * 机器节点\n     */\n    private String nsTree;\n\n    /**\n     * 机房\n     */\n    private String idc;\n\n    /**\n     * es版本\n     */\n    private String esVersion;\n\n    /**\n     * 插件包ID列表\n     */\n    private String plugs;\n\n    /**\n     * 集群创建人\n     */\n    private String creator;\n\n    /**\n     * 描述\n     */\n    private String desc;\n\n    /**\n     * 机器规格\n     */\n    private String machineSpec;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/ClusterOpOfflineOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterOpOfflineOrderDetail extends AbstractOrderDetail {\n    /**\n     * 物理集群id\n     */\n    private Long   phyClusterId;\n    /**\n     * 物理集群名称\n     */\n    private String phyClusterName;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/ClusterOpUpdateOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterOpUpdateOrderDetail extends AbstractOrderDetail {\n    /**\n     * 物理集群id\n     */\n    private Long                    phyClusterId;\n    /**\n     * 物理集群名称\n     */\n    private String                  phyClusterName;\n    /**\n     * 角色顺序，如：airepo-masternode,airepo-clientnode,airepo-datanode\n     */\n    private String                  roleOrder;\n    /**\n     * 集群角色 对应主机列表\n     */\n    private List<ESClusterRoleHost> roleClusterHosts;\n    /**\n     * 集群版本\n     */\n    private String                  esVersion;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/DslTemplateQueryLimitDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.DslQueryLimitDTO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author wuxuan\n * @date 2022/11/15\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslTemplateQueryLimitDetail extends AbstractOrderDetail{\n    /**\n     * 查询语句限流值相关参数\n     */\n    private List<DslQueryLimitDTO> dslQueryLimitDTOList;\n\n    /**\n     * 项目id\n     */\n    private Integer projectId;\n\n    /**\n     * 操作者\n     */\n    private String operator;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/DslTemplateStatusDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author wuxuan\n * @date 2022/11/14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslTemplateStatusDetail  extends AbstractOrderDetail {\n\n    /**\n     * 名字\n     */\n    private String  name;\n\n    /**\n     * 项目id\n     */\n    Integer projectId;\n\n    /**\n     * 操作者\n     */\n    String operator;\n\n    /**\n     * dsl模板MD5\n     */\n    String dslTemplateMd5;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/LogicClusterAuthOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class LogicClusterAuthOrderDetail extends AbstractOrderDetail {\n    /**\n     * 逻辑模板id\n     */\n    private Long    logicClusterId;\n\n    /**\n     * 逻辑模板名字\n     */\n    private String  logicClusterName;\n\n    /**\n     * 权限类型\n     * @see ProjectClusterLogicAuthEnum\n     */\n    private Integer authCode;\n\n    /**\n     * 申请说明\n     */\n    private String  memo;\n\n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/LogicClusterCreateOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class LogicClusterCreateOrderDetail extends AbstractOrderDetail {\n    /**\n     * 集群名称\n     */\n    private String  name;\n\n    /**\n     * 集群类型\n     */\n    private Integer type;\n\n    /**\n     * 服务等级\n     */\n    private Integer level;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n\n    /**\n     * dataNode的规格\n     */\n    private String  dataNodeSpec;\n\n    /**\n     * dataNode的个数\n     */\n    private Integer dataNodeNu;\n\n \n\n    /**\n     * 备注\n     */\n    private String  memo;\n\n    /**\n     * 插件上传\n     */\n    private String  plugins;\n\n    /**\n     * 配置文件上传\n     */\n    private String  config;\n\n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/LogicClusterDeleteOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-06-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class LogicClusterDeleteOrderDetail extends AbstractOrderDetail {\n    /**\n     * 集群名称\n     */\n    private String  name;\n\n    /**\n     * 集群类型\n     */\n    private Integer type;\n\n    /**\n     * 服务等级\n     */\n    private Integer level;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/LogicClusterIndecreaseOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class LogicClusterIndecreaseOrderDetail extends AbstractOrderDetail {\n    /**\n     * 集群名称\n     */\n    private String  logicClusterName;\n\n    /**\n     * 逻辑集群的id\n     */\n    private Long    logicClusterId;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n\n    /**\n     * dataNode的规格\n     */\n    private String  dataNodeSpec;\n\n    /**\n     * dataNode的个数\n     */\n    private Integer dataNodeNu;\n    \n    /**\n     * 原有 dataNode 的个数\n     */\n    private int oldDataNodeNu;\n   \n\n    /**\n     * 备注\n     */\n    private String  memo;\n\n    /**\n     * 插件上传\n     */\n    private String  plugins;\n\n    /**\n     * 配置文件上传\n     */\n    private String  config;\n\n  \n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/LogicClusterPlugOperationOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class LogicClusterPlugOperationOrderDetail extends AbstractOrderDetail {\n    /**\n     * 操作类型 3:安装 4：卸载\n     */\n    private String operationType;\n    /**\n     * 集群id\n     */\n    private Long   logicClusterId;\n\n    /**\n     * 集群名称\n     */\n    private String logicClusterName;\n\n    /**\n     * 插件ID\n     */\n    private Long   plugId;\n\n    /**\n     * 插件名称\n     */\n    private String plugName;\n\n    /**\n     * 插件描述\n     */\n    private String plugDesc;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/LogicClusterPluginOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class LogicClusterPluginOrderDetail extends AbstractOrderDetail {\n    /**\n     * 逻辑集群id\n     */\n    private Long   logicClusterId;\n    /**\n     * 逻辑集群名称\n     */\n    private String logicClusterName;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/OrderInfoDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.Date;\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class OrderInfoDetail {\n\n    /**\n     * 订单id\n     */\n    private Long                id;\n\n    /**\n     * @see WorkOrderTypeEnum\n     */\n    private String              type;\n\n    /**\n     * 标题\n     */\n    private String              title;\n\n    /**\n     * 申请人部门名称\n     */\n    private String              appDeptName;\n\n    /**\n     * 申请人\n     */\n    private UserBriefVO         applicant;\n\n    /**\n     * 申请人ProjectId\n     */\n    private Integer             applicantProjectId;\n\n    /**\n     * 审批人信息\n     */\n    private List<UserBriefVO>   approverList;\n\n    /**\n     * 任务完成时间\n     */\n    private Date                finishTime;\n\n    /**\n     * 审批信息\n     */\n    private String              opinion;\n\n    /**\n     * 工单状态, 0:待审批, 1:通过, 2:拒绝, 3:取消\n     */\n    private Integer             status;\n\n    /**\n     * 备注\n     */\n    private String              description;\n\n    /**\n     * 申请时间\n     */\n    protected Date              createTime;\n\n    /**\n     * 订单详细信息\n     */\n    private AbstractOrderDetail detail;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/PhyClusterPluginOperationOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class PhyClusterPluginOperationOrderDetail extends AbstractOrderDetail {\n    /**\n     * 操作类型 3:安装 4：卸载\n     */\n    private Integer operationType;\n    /**\n     * 插件 id\n     */\n    private Long    pluginId;\n    /**\n     * 插件文件名称\n     */\n    private String  pluginFileName;\n    /**\n     * 插件在url上的地址\n     */\n    private String  url;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/QueryDslLimitEditOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author zhongyuankai\n * @date 2020/5/18\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class QueryDslLimitEditOrderDetail extends AbstractOrderDetail {\n    /**\n     * md5\n     */\n    private String dslTemplateMd5;\n\n    /**\n     * 模板\n     */\n    private String dslTemplate;\n\n    /**\n     * 源限流值\n     */\n    private Double queryLimit;\n\n    /**\n     * 希望限流值\n     */\n    private Double expectQueryLimit;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/TemplateAuthOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateAuthOrderDetail extends AbstractOrderDetail {\n    /**\n     * 逻辑模板id\n     */\n    private Integer id;\n\n    /**\n     * 逻辑模板名字\n     */\n    private String  name;\n\n    /**\n     * 权限类型\n     * @see ProjectTemplateAuthEnum\n     */\n    private Integer authCode;\n\n    /**\n     * 申请说明\n     */\n    private String  memo;\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/TemplateCreateOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateCreateOrderDetail extends AbstractOrderDetail {\n    /**************************************** 基本信息 ****************************************************/\n\n    /**\n     * 索引模板名称\n     */\n    private String       name;\n\n    /**\n     * 数据中心\n     */\n    private String       dataCenter;\n\n    /**\n     * 用户数据类型\n     * @see DataTypeEnum\n     */\n    private Integer      dataType;\n\n   \n\n  \n\n    /**\n     * 备注\n     */\n    private String       desc;\n\n    /**\n     * 数据保存时长 单位天\n     */\n    private Integer      expireTime;\n\n    /**\n     * 热数据保存天数, 单位天\n     */\n    private Integer      hotTime;\n\n    /**\n     * 数据总量 单位G\n     */\n    private Double       diskQuota;\n\n    /**\n     * 周期性滚动  1 滚动   0 不滚动\n     */\n    private Boolean      cyclicalRoll;\n\n    /**************************************** Schema信息 ****************************************************/\n\n    /**\n     * 时间字段\n     */\n    private String       dateField;\n    /**\n     * 时间字段格式\n     */\n    private String       dateFieldFormat;\n    /**\n     * 索引mapping信息\n     */\n    private String       mapping;\n    /**\n     * id字段\n     */\n    private String       idField;\n\n    /**\n     * routing字段\n     */\n    private String       routingField;\n\n    /**************************************** 部署信息 ****************************************************/\n\n    /**\n     * 物理集群名称\n     */\n    private List<String> clusterPhyNameList;\n\n    /**\n     * 逻辑集群名称\n     */\n    private String       clusterLogicName;\n\n    /**\n     * 预创建索引标识\n     */\n    private Boolean      preCreateFlags;\n\n    /**\n     * shard数量\n     */\n    private Integer      shardNum;\n\n    /**\n     * 禁用索引_source标识\n     */\n    private Boolean      disableSourceFlags;\n\n    /**\n     * 禁用rollover标识\n     */\n    private Boolean      disableIndexRollover;\n\n    /**\n     * 服务等级\n     */\n    private Integer      level;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/TemplateIndecreaseOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateIndecreaseOrderDetail extends AbstractOrderDetail {\n    private Integer id;\n\n    /**\n     * 索引模板名称\n     */\n    private String  name;\n\n    /**\n     * 数据保存时长 单位天\n     */\n    private Integer expireTime;\n\n    /**\n     * 规格 单位台\n     */\n    private Double  quota;\n\n    /**\n     * 实际的磁盘消耗\n     */\n    private Double  actualDiskG;\n\n    /**\n     * 实际的CPU消耗\n     */\n    private Double  actualCpuCount;\n\n    /**\n     * Quota的磁盘消耗\n     */\n    private Double  quotaDiskG;\n\n    /**\n     * Quota的CPU消耗\n     */\n    private Double  quotaCpuCount;\n\n    /**************************************** 期望容量信息 ****************************************************/\n    /**\n     * 期望数据保存时长 单位天\n     */\n    private Integer expectExpireTime;\n\n    /**\n     * 数据总量 单位台\n     */\n    private Double  expectQuota;\n\n    /**************************************** 管理员操作 ****************************************************/\n    /**\n     * 是否跳过容量规划，强制扩容 1:强制 0:不强制\n     */\n    private Integer force = 0;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/TemplateLogicStatusDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author wuxuan\n * @date 2022/11/14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateLogicStatusDetail extends AbstractOrderDetail {\n    /**\n     * 索引模板名称\n     */\n    private String name;\n    /**\n     * 模板Id\n     */\n    private Integer templateId;\n    /**\n     * 读/写的启用/禁用状态\n     */\n    private Boolean status;\n    /**\n     * 操作者\n     */\n    private String operator;\n    /**\n     * 项目id\n     */\n    private Integer projectId;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/TemplateQueryDslOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateQueryDslOrderDetail extends AbstractOrderDetail {\n    private Integer id;\n\n    /**\n     * 名字\n     */\n    private String  name;\n    /**\n     * dsl语句\n     */\n    private String  dsl;\n    /**\n     * 备注\n     */\n    private String  memo;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/TemplateTransferOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateTransferOrderDetail extends AbstractOrderDetail {\n    private Integer id;\n\n    /**\n     * 目标ProjectId\n     */\n    private Integer sourceProjectId;\n\n    /**\n     * 目标ProjectId\n     */\n    private Integer tgtProjectId;\n\n    /**\n     * 名字\n     */\n    private String  name;\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/clusteroprestart/ClusterOpConfigRestartOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.clusteroprestart;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.esconfig.ESConfig;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author lyn\n * @date 2021-01-21\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterOpConfigRestartOrderDetail extends ClusterOpRestartOrderDetail {\n    /**\n     * Es配置操作: 1.新增 2.编辑 3.删除\n     * @see EsConfigActionEnum\n     */\n    private Integer        actionType;\n\n    /**\n     * 新增Es配置\n     */\n    private List<ESConfig> newEsConfigs;\n\n    /**\n     * 原始Es配置\n     */\n    private List<ESConfig> originalConfigs;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/detail/clusteroprestart/ClusterOpRestartOrderDetail.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.clusteroprestart;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.detail.AbstractOrderDetail;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterOpRestartOrderDetail extends AbstractOrderDetail {\n    /**\n     * 物理集群id\n     */\n    private Long   phyClusterId;\n    /**\n     * 物理集群名称\n     */\n    private String phyClusterName;\n    /**\n     * 角色顺序，如：airepo-masternode,airepo-clientnode,airepo-datanode\n     */\n    private String roleOrder;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/entity/workorder/ecm/EcmTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmTaskStatusEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author linyunan\n * @date 2020-12-23\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class EcmTask {\n    /**\n     * ID主键自增\n     */\n    private Long    id;\n\n    /**\n     * 标题\n     */\n    private String  title;\n\n    /**\n     * 工单ID\n     */\n    private Long    workOrderId;\n\n    /**\n     * 物理集群ID\n     */\n    private Long    physicClusterId;\n\n    /**\n     * 集群节点角色 执行顺序\n     */\n    private String  clusterNodeRole;\n\n    /**\n     * 状态\n     * @see EcmTaskStatusEnum\n     */\n    private String  status;\n\n    /**\n     * 类型  docker容器云/host 物理机\n     */\n    private Integer type;\n\n    /**\n     * 类型  1 集群新增  2 集群扩容 3 集群缩容 4 集群重启 5 集群升级\n     */\n    private Integer orderType;\n\n    /**\n     *  zeus任务角色数据\n     */\n    private String  handleData;\n\n    /**\n     * 创建人\n     */\n    private String  creator;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/BaseESPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po;\n\npublic abstract class BaseESPO {\n    /**\n     * 获取主键key\n     *\n     * @return\n     */\n    public abstract String getKey();\n\n    /**\n     * 获取routing值\n     * @return\n     */\n    public abstract String getRoutingValue();\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/BasePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/3/13\n */\npublic class BasePO implements Serializable {\n\n    protected Date createTime;\n\n    protected Date updateTime;\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public Date getUpdateTime() {\n        return updateTime;\n    }\n\n    public void setUpdateTime(Date updateTime) {\n        this.updateTime = updateTime;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/cluster/ClusterLogicDiskUsedInfoPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.cluster;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName ClusterLogicDiskUsedInfo\n * @Author gyp\n * @Date 2022/5/30\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterLogicDiskUsedInfoPO {\n    @ApiModelProperty(\"磁盘使用率\")\n    private Double diskUsagePercent;\n\n    @ApiModelProperty(\"磁盘总量\")\n    private Long   diskTotal;\n\n    @ApiModelProperty(\"磁盘使用量\")\n    private Long   diskUsage;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/cluster/ClusterLogicPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterLogicPO extends BasePO {\n\n    /**\n     * 主键\n     */\n    private Long    id;\n\n    /**\n     * 名字\n     */\n    private String  name;\n\n    /**\n     * 类型\n     * @see ClusterResourceTypeEnum\n     */\n    private Integer type;\n\n    /**\n     * 所属projectID\n     */\n    private String projectId;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n\n    /**\n     * dataNode的规格\n     */\n    private String  dataNodeSpec;\n\n    /**\n     * dataNode的个数\n     */\n    private Integer dataNodeNum;\n\n    /**\n     * 备注\n     */\n    private String  memo;\n\n    /**\n     * 独立资源的大小\n     */\n    private Double  quota;\n\n    /**\n     * 服务等级\n     */\n    private Integer level;\n\n    /**\n     * 配置\n     */\n    private String  configJson;\n\n    /**\n     * 健康状态 1 green 2 yellow 3 red -1 未知\n     */\n    private Integer health;\n\n    /**\n     * 磁盘使用率\n     */\n    private Double diskUsagePercent;\n\n    /**\n     * 磁盘总量\n     */\n    private Long diskTotal;\n\n    /**\n     * 磁盘使用量\n     */\n    private Long diskUsage;\n\n    /**\n     * 集群版本\n     */\n    private String esClusterVersion;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/cluster/ClusterPhyPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author d06679\n * @date 2019/3/19\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterPhyPO extends BasePO {\n\n    /**\n     * 集群id\n     */\n    private Integer id;\n\n    /**\n     * 集群名字\n     */\n    private String  cluster;\n\n    /**\n     * 描述\n     */\n    private String  desc;\n\n    /**\n     * 读地址\n     */\n    private String  readAddress;\n\n    /**\n     * 写地址\n     */\n    private String  writeAddress;\n\n    /**\n     * http地址\n     */\n    private String  httpAddress;\n\n    /**\n     * http写地址\n     */\n    private String  httpWriteAddress;\n\n    /**\n     * 集群类型\n     * @see ESClusterTypeEnum\n     */\n    private Integer type;\n\n    /**\n     * 拓展字段,这里用于存放集群展示用属性标签，如「集群所属资源类型」等等\n     */\n    private String  tags;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n\n    /**\n     * 机房\n     */\n    private String  idc;\n\n    /**\n     * 服务等级\n     */\n    private Integer level;\n\n    /**\n     * es版本\n     */\n    private String  esVersion;\n\n    /**\n     * 配置包Id\n     */\n    private Long    cfgId;\n\n    /**\n     * 插件Id列表\n     */\n    private String  plugIds;\n\n    /**\n     * 程序包Id\n     */\n    private Long    packageId;\n\n    /**\n     * 集群创建人\n     */\n    private String  creator;\n\n\n\n    /**\n     * 镜像名\n     */\n    private String  imageName;\n    /**\n     * odin 树节点\n     */\n    private String  nsTree;\n\n    /**\n     * 集群密码\n     */\n    private String  password;\n\n    /**\n     * client运行模式，读写共享还是读写分离\n     */\n    private Integer runMode;\n\n    /**\n     * 读写分离时候，指定action（获取写client）\n     */\n    private String  writeAction;\n\n    /**\n     * 健康状态 0 green 1 yellow 2 red -1 未知\n     */\n    private Integer health;\n\n    /**\n     * 活跃的分片数目\n     */\n    private Long    activeShardNum;\n\n    private Long    diskTotal;\n    private Long    diskUsage;\n    private Double  diskUsagePercent;\n\n    /**\n     * IaaS平台类型\n     */\n    private String  platformType;\n\n    /**\n     * 集群资源类型(-1 未知 1 共享 2 独立 3 独享)\n     * @see ClusterResourceTypeEnum\n     */\n\n    private Integer resourceType;\n\n    /**\n     * gateway地址\n     */\n    private String  gatewayUrl;\n\n    /**\n     * kibana外链地址\n     */\n    private String                    kibanaAddress;\n\n    /**\n     * cerebro外链地址\n     */\n    private String                    cerebroAddress;\n\n    /**\n     * 代理地址\n     */\n    private String                    proxyAddress;\n\n    @Override\n    public boolean equals(Object obj) {\n        if (obj == null || obj.getClass() != this.getClass()) {\n            return false;\n        }\n\n        ClusterPhyPO other = (ClusterPhyPO) obj;\n\n        if (StringUtils.isNotBlank(httpAddress) && !httpAddress.equals(other.getHttpAddress())) {\n            return false;\n        } else if (StringUtils.isNotBlank(other.getHttpAddress()) && !other.getHttpAddress().equals(httpAddress)) {\n            return false;\n        } else if (StringUtils.isNotBlank(password) && !password.equals(other.getPassword())) {\n            return false;\n        } else if (StringUtils.isNotBlank(other.getPassword()) && !other.getPassword().equals(password)) {\n            return false;\n        } else if (StringUtils.isNotBlank(other.getEsVersion()) && !other.getEsVersion().equals(esVersion)) {\n            return false;\n        } else if (StringUtils.isNotBlank(esVersion) && !esVersion.equals(other.getEsVersion())) {\n            return false;\n        }\n\n        return true;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/cluster/ClusterRegionPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.ToString;\n\n/**\n * 物理集群Region PO\n * 对应表名es_cluster_region\n * @author wangshu\n * @date 2020/09/15\n */\n@Data\n@ToString\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterRegionPO extends BasePO {\n    /**\n     * region ID\n     */\n    private Long   id;\n\n    /**\n     * region 名称\n     */\n    private String name;\n\n    /**\n     * 绑定到的逻辑集群ID列表，用逗号隔开, 为空则没有被绑定\n     */\n    private String logicClusterIds;\n\n    /**\n     * 物理集群名称\n     */\n    private String phyClusterName;\n\n    /**\n     * 配置项\n     */\n    private String config;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/config/AriusConfigInfoPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.config;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class AriusConfigInfoPO extends BasePO {\n\n    /**\n     * 主键\n     */\n    private Integer id;\n\n    /**\n     * 配置组\n     */\n    private String  valueGroup;\n\n    /**\n     * 配置项的名称\n     */\n    private String  valueName;\n\n    /**\n     * 配置项的值\n     */\n    private String  value;\n\n    /**\n     * 配置项维度  1 集群   2 模板\n     */\n    private Integer dimension;\n\n    /**\n     * 1 正常  2 禁用  -1 删除\n     */\n    private Integer status;\n\n    /**\n     * 备注\n     */\n    private String  memo;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/dsl/DslAnalyzeResultQpsPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/9/11 下午2:51\n * @Modified By\n *\n * 查询模板qps信息\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslAnalyzeResultQpsPO extends BaseESPO {\n\n    /**\n     * projectid\n     */\n    private Integer projectId;\n\n    /**\n     * 查询模板的md5值\n     */\n    private String  dslTemplateMd5;\n\n    /**\n     * 查询次数\n     */\n    private Long    searchCount;\n    /**\n     * 日期\n     */\n    private String  date;\n    /**\n     * 时间\n     */\n    private Long    timeStamp;\n    /**\n     * 数据类型\n     */\n    private String  ariusType;\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n    /**\n     * 获取主键id\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.format(\"%d_%s_%s\", this.projectId, this.dslTemplateMd5, date);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n\n    /**\n     * 构建ProjectIdTemplateQpsInfo\n     *\n     * @param maxQpsTimeTuple\n     * @param projectId\n     * @param dslTemplateMd5\n     * @param date\n     * @return\n     */\n    public static DslAnalyzeResultQpsPO buildProjectIdTemplateQpsInfo(Tuple<Long, Long> maxQpsTimeTuple,\n                                                                      Integer projectId, String dslTemplateMd5,\n                                                                      String date) {\n        DslAnalyzeResultQpsPO dslAnalyzeResultQps = new DslAnalyzeResultQpsPO();\n        dslAnalyzeResultQps.setProjectId(projectId);\n        dslAnalyzeResultQps.setDslTemplateMd5(dslTemplateMd5);\n        dslAnalyzeResultQps.setSearchCount(maxQpsTimeTuple.v2());\n        dslAnalyzeResultQps.setDate(date);\n        dslAnalyzeResultQps.setTimeStamp(maxQpsTimeTuple.v1());\n        dslAnalyzeResultQps.setAriusType(\"qps\");\n\n        return dslAnalyzeResultQps;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/dsl/DslAnalyzeResultTypePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ErrorDsl;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.SearchOverview;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.SlowDsl;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslAnalyzeResultTypePO extends BaseESPO {\n\n    /**\n     * projectId\n     */\n    private Integer        projectId;\n    /**\n     * 分析所在日期\n     */\n    private String         date;\n    /**\n     * 访问gateway信息\n     */\n    private String         accessGatewayInfo;\n    /**\n     * 查询模板信息\n     */\n    private DslTemplate    dslTemplate;\n    /**\n     *  查询概述\n     */\n    private SearchOverview overview;\n    /**\n     * 慢查信息\n     */\n    private SlowDsl        slowDsl;\n    /**\n     * 异常查询\n     */\n    private ErrorDsl       errorDsl;\n    /**\n     * 数据类型\n     */\n    private String         ariusType;\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.format(\"%d_%s\", projectId, date);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/dsl/DslFieldUsePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.dsl;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslSearchFieldNameMetric;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslFieldUsePO extends BaseESPO {\n\n    private Long              id;\n\n    private String            clusterName;\n\n    private String            name;\n\n    private String            date;\n\n    private Long              fieldCount;\n    /**\n     * 数据中心\n     */\n    private String            dataCenter;\n\n    private List<String>      notUseFields;\n\n    /**\n     * 最近创建的字段名称\n     */\n    private List<String>      recentCreateFields;\n\n    private Map<String, Long> selectFieldsCounter;\n\n    private Map<String, Long> whereFieldsCounter;\n\n    private Map<String, Long> groupByFieldsCounter;\n\n    private Map<String, Long> sortByFieldsCounter;\n\n    /**\n     * 更新统计字段值\n     *\n     * @param searchFieldNameMetric\n     */\n    public void updateFromSearchFieldMetric(DslSearchFieldNameMetric searchFieldNameMetric) {\n        this.setSelectFieldsCounter(searchFieldNameMetric.getSelectFieldsCounter());\n        this.setSortByFieldsCounter(searchFieldNameMetric.getSortByFieldsCounter());\n        this.setGroupByFieldsCounter(searchFieldNameMetric.getGroupByFieldsCounter());\n        this.setWhereFieldsCounter(searchFieldNameMetric.getWhereFieldsCounter());\n    }\n\n    /**\n     * 使用空map\n     */\n    public void fillEmptyMap() {\n        this.selectFieldsCounter = Maps.newHashMap();\n        this.whereFieldsCounter = Maps.newHashMap();\n        this.groupByFieldsCounter = Maps.newHashMap();\n        this.sortByFieldsCounter = Maps.newHashMap();\n    }\n\n    /**\n     * 合并notUseFields,recentCreateFields,selectFieldsCounter,sortByFieldsCounter,whereFieldsCounter,groupByFieldsCounter\n     */\n    public void combineDataWithPo(DslFieldUsePO other) {\n        // 没有使用的字段，国内统计结果和国外统计结果求交集\n        Set<String> notUseFieldSetsCenter1 = Sets.newHashSet();\n        if (CollectionUtils.isNotEmpty(notUseFields)) {\n            notUseFieldSetsCenter1.addAll(notUseFields);\n        }\n        Set<String> notUseFieldSetsCenter2 = Sets.newHashSet();\n        if (CollectionUtils.isNotEmpty(other.getNotUseFields())) {\n            notUseFieldSetsCenter2.addAll(other.getNotUseFields());\n        }\n        notUseFields = Lists.newArrayList(Sets.intersection(notUseFieldSetsCenter1, notUseFieldSetsCenter2));\n\n        Set<String> recentCreateFieldsSets = Sets.newHashSet();\n        if (CollectionUtils.isNotEmpty(recentCreateFields)) {\n            recentCreateFieldsSets.addAll(recentCreateFields);\n        }\n        if (CollectionUtils.isNotEmpty(other.getRecentCreateFields())) {\n            recentCreateFieldsSets.addAll(other.getRecentCreateFields());\n        }\n        recentCreateFields = Lists.newArrayList(recentCreateFieldsSets);\n\n        // 合并字段使用次数\n        combineFieldUseCount(other);\n    }\n\n    /**\n     * 合并字段使用次数\n     *\n     * @param other\n     */\n    public void combineFieldUseCount(DslFieldUsePO other) {\n        countFieldUse(other.getSelectFieldsCounter(), selectFieldsCounter);\n        countFieldUse(other.getWhereFieldsCounter(), whereFieldsCounter);\n        countFieldUse(other.getGroupByFieldsCounter(), groupByFieldsCounter);\n        countFieldUse(other.getSortByFieldsCounter(), sortByFieldsCounter);\n    }\n\n    private void countFieldUse(Map<String, Long> otherFieldsCounter, Map<String, Long> fieldsCounter) {\n        if (otherFieldsCounter != null) {\n            for (Map.Entry<String, Long> entry : otherFieldsCounter.entrySet()) {\n                if (fieldsCounter == null) {\n                    fieldsCounter = new HashMap<>();\n                }\n\n                if (fieldsCounter.containsKey(entry.getKey())) {\n                    Long counter = fieldsCounter.get(entry.getKey()) + entry.getValue();\n                    fieldsCounter.put(entry.getKey(), counter);\n                } else {\n                    fieldsCounter.put(entry.getKey(), entry.getValue());\n                }\n            }\n        }\n    }\n\n    public void removeBlankField() {\n        selectFieldsCounter.remove(\"\");\n        whereFieldsCounter.remove(\"\");\n        groupByFieldsCounter.remove(\"\");\n        sortByFieldsCounter.remove(\"\");\n    }\n\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.format(\"%d_%s_%s\", id, date, dataCenter);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/dsl/DslMetricsPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2018/9/18 下午5:24\n * @modified By\n *\n * 查询模板一分钟聚合指标统计信息\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslMetricsPO extends BaseESPO {\n    /**\n     * 创建时间\n     */\n    private String  ariusCreateTime;\n    /**\n     * 日期时间\n     */\n    private String  logTime;\n    /**\n     * sink写入时间\n     */\n    private Long    sinkTime;\n    /**\n     * flink写入时间\n     */\n    private String  flinkTime;\n    /**\n     * 响应平均长度\n     */\n    private Double  responseLenAvg;\n    /**\n     * 请求类型 http/tcp\n     */\n    private String  requestType;\n    /**\n     * 查询类型 dsl/sql\n     */\n    private String  searchType;\n    /**\n     * 查询次数\n     */\n    private Long    searchCount;\n    /**\n     * 查询es平均耗时\n     */\n    private Double  esCostAvg;\n    /**\n     * 查询语句平均长度\n     */\n    private Double  dslLenAvg;\n    /**\n     * 查询平均命中记录数\n     */\n    private Double  totalHitsAvg;\n    /**\n     * 查询成功平均shard数\n     */\n    private Double  successfulShardsAvg;\n    /**\n     * 查询平均总shard数\n     */\n    private Double  totalShardsAvg;\n    /**\n     * 查询索引示例\n     */\n    private String  indiceSample;\n    /**\n     * 查询模板\n     */\n    private String  dslTemplate;\n    /**\n     * 记录生成时间戳\n     */\n    private Long    timeStamp;\n    /**\n     * dsl语句类型 normal/agg等\n     */\n    private String  dslType;\n    /**\n     * 查询索引名称，去重后的\n     */\n    private String  indices;\n    /**\n     * 查询模板\n     */\n    private String  dslTemplateMd5;\n    /**\n     * 查询平均总耗时\n     */\n    private Double  totalCostAvg;\n    /**\n     * 查询平均失败shard数\n     */\n    private Double  failedShardsAvg;\n    /**\n     * projectId\n     */\n    private Integer projectId;\n    /**\n     * 查询语句\n     */\n    private String  dsl;\n    /**\n     * gateway处理平均耗时\n     */\n    private Double  beforeCostAvg;\n    /**\n     * dsl查询限流值\n     */\n    private Double  queryLimit;\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return null;\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/dsl/DslTemplatePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/15 下午6:39\n * @modified By D10865\n *\n * dsl模板信息\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DslTemplatePO extends BaseESPO {\n\n    /**\n     * 查询模板创建时间\n     */\n    private String  ariusCreateTime;\n    /**\n     * 查询模板修改时间\n     */\n    private String  ariusModifyTime;\n    /**\n     * 平均响应长度\n     */\n    private Double  responseLenAvg;\n    /**\n     * 请求类型\n     */\n    private String  requestType;\n    /**\n     * 查询类型\n     */\n    private String  searchType;\n    /**\n     * 查询次数(分钟级别)\n     */\n    private Long    searchCount;\n    /**\n     * es查询耗时\n     */\n    private Double  esCostAvg;\n    /**\n     * 平均查询语句长度\n     */\n    private Double  dslLenAvg;\n    /**\n     * 平均命中记录数\n     */\n    private Double  totalHitsAvg;\n    /**\n     * 平均查询shard成功个数\n     */\n    private Double  successfulShardsAvg;\n    /**\n     * 平均shard成功个数\n     */\n    private Double  totalShardsAvg;\n    /**\n     * 查询请求时刻\n     */\n    private String  logTime;\n    /**\n     * 查询索引示例\n     */\n    private String  indiceSample;\n    /**\n     * 查询模板\n     */\n    private String  dslTemplate;\n    /**\n     * 查询请求时刻\n     */\n    private Long    timeStamp;\n    /**\n     * 查询语句类型\n     */\n    private String  dslType;\n    /**\n     * 查询索引名称\n     */\n    private String  indices;\n    /**\n     * 查询模板MD5\n     */\n    private String  dslTemplateMd5;\n    /**\n     * 平均查询总耗时\n     */\n    private Double  totalCostAvg;\n    /**\n     * 查询shard失败个数\n     */\n    private Double  failedShardsAvg;\n    /**\n     * sink写入时间\n     */\n    private Long    sinkTime;\n    /**\n     * projectId\n     */\n    private Integer projectId;\n    /**\n     * 查询语句\n     */\n    private String  dsl;\n    /**\n     * 平均gateway处理耗时\n     */\n    private Double  beforeCostAvg;\n    /**\n     * flin\n     */\n    private String  flinkTime;\n    /**\n     * 查询限流\n     */\n    private Double  queryLimit;\n    /**\n     * 是否来自用户控制台\n     */\n    private Boolean isFromUserConsole;\n    /**\n     * 是否强制设置查询限流值\n     * 如果设置为 true，则DSL模版查询限流值更新定时任务就不会修改该模版的查询限流值\n     */\n    private Boolean forceSetQueryLimit;\n    /**\n     * 是否可用 null/true表示可用，false表示不可用\n     */\n    private Boolean enable;\n    /**\n     * 黑白名单 null/white表示白名单，black表示黑名单\n     */\n    private String  checkMode;\n    /**\n     * 慢查dsl阈值，单位为ms\n     */\n    private Long    slowDslThreshold;\n    /**\n     * 查询模板版本号\n     */\n    private String  version;\n    /**\n     * 查询模板危害标签\n     */\n    private String  dslTag;\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.format(\"%d_%s\", this.projectId, this.dslTemplateMd5);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/ecm/ESClusterRoleHostPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * ES集群表对应各角色主机列表\n * @author chengxiang\n * @date 2022/4/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterRoleHostPO extends BasePO {\n\n    private Long    id;\n\n    /**\n     * elastic_cluster外键ID\n     */\n    private Long    roleClusterId;\n\n    /**\n     * 主机名或IP\n     */\n    private String  hostname;\n\n    /**\n     * IP\n     */\n    private String  ip;\n\n    /**\n     * 集群名称\n     */\n    private String  cluster;\n\n    /**\n     * es进程端口\n     */\n    private String  port;\n\n    /**\n     * 1data   2client    3master   4tribe\n     * @see ESClusterNodeRoleEnum\n     */\n    private Integer role;\n\n    /**\n     * 1 在线    2 离线   3 故障\n     * @see ESClusterNodeStatusEnum\n     */\n    private Integer status;\n\n    /**\n     * rack\n     */\n    private String  rack;\n\n    /**\n     * 节点名称\n     */\n    private String  nodeSet;\n\n    /**\n     * 机器规格 例如32C-64G-SSD-6T\n     */\n    private String  machineSpec;\n\n    /**\n     * regionId\n     */\n    private Integer regionId;\n\n    /**\n     * attributes, 逗号分隔  key1:value1,key2:value2\n     */\n    private String  attributes;\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        ESClusterRoleHostPO nodePO = (ESClusterRoleHostPO) o;\n\n        if (!hostname.equals(nodePO.hostname)) {\n            return false;\n        }\n        return cluster.equals(nodePO.cluster);\n\n    }\n\n    @Override\n    public int hashCode() {\n        int result = hostname.hashCode();\n        result = 31 * result + cluster.hashCode();\n        return result;\n    }\n\n    public String getKey() {\n        return roleClusterId + \"@\" + ip + \"@\" + port;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/ecm/ESClusterRolePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * ES集群对应角色集群\n * @author chengxiang\n * @date 2022/5/9\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterRolePO extends BasePO {\n    private static final long serialVersionUID = 1L;\n\n    private Long              id;\n\n    /**\n     * elastic_cluster外键ID\n     */\n    private Long              elasticClusterId;\n\n    /**\n     * role集群名称\n     */\n    private String            roleClusterName;\n\n    /**\n     * 集群角色(master-node/data-node/client-node)\n     */\n    private String            role;\n\n    /**\n     * pod(节点)数量\n     */\n    private Integer           podNumber;\n\n    /**\n     * 节点版本\n     */\n    private String            esVersion;\n\n    /**\n     * 单机实例数\n     */\n    private Integer           pidCount;\n\n    /**\n     * 机器规格\n     */\n    private String            machineSpec;\n\n    /**\n     * 配置包ID\n     */\n    private Integer           cfgId;\n\n    /**\n     * 标记删除\n     */\n    private Boolean           deleteFlag;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/ecm/ESMachineNormsPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 容器规格列表\n * @author didi\n * @since 2020-08-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESMachineNormsPO extends BasePO {\n\n    private static final long serialVersionUID = 1L;\n\n    private Long              id;\n\n    /**\n     * 角色(masternode/datanode/clientnode/datanode-ceph)\n     */\n    private String            role;\n\n    /**\n     * 规格(16-48Gi-100g)\n     */\n    private String            spec;\n\n    /**\n     * 标记删除\n     */\n    private Boolean           deleteFlag;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/esconfig/ESConfigPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.esconfig;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * ES配置包列表\n * @author didi\n * @since 2020-08-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESConfigPO extends BasePO {\n    /**\n     * ID主键自增\n     */\n    private Long    id;\n\n    /**\n     * 集群id\n     */\n    private Long    clusterId;\n\n    /**\n    * 配置文件名称\n    */\n    private String  typeName;\n\n    /**\n     * 角色名称\n     */\n    private String  enginName;\n\n    /**\n    * 配置内容\n    */\n    private String  configData;\n\n    /**\n     * 配置描述\n     */\n    private String  desc;\n\n    /**\n     * 配置tag\n     */\n    private String  versionTag;\n\n    /**\n     * 配置版本\n     */\n    private Integer versionConfig;\n\n    /**\n     * 是否在使用\n     */\n    private Integer selected;\n\n    /**\n     * 标记删除\n     */\n    private Boolean deleteFlag;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/espackage/ESPackagePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.espackage;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 程序包版本管理\n * @author didi\n * @since 2020-08-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESPackagePO extends BasePO {\n\n    private static final long serialVersionUID = 1L;\n\n    private Long              id;\n\n    /**\n     * 镜像地址或包地址\n     */\n    private String            url;\n\n    /**\n     * 版本标识\n     */\n    private String            esVersion;\n\n    /**\n     * 包创建人\n     */\n    private String            creator;\n\n    /**\n     * 是否为发布版本\n     */\n    private Boolean           release;\n\n    /**\n     * 类型(3 docker/4 host)\n     */\n    private Integer           manifest;\n    /**\n     *备注\n     */\n    private String            desc;\n\n    /**\n     * 标记删除\n     */\n    private Boolean           deleteFlag;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/esplugin/PluginPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PluginTypeEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * ES插件包管理\n * @author didi\n * @since 2020-08-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class PluginPO extends BasePO {\n\n    private static final long serialVersionUID = 1L;\n\n    /**\n     * ID主键自增\n     */\n    private Long              id;\n\n    /**\n     * 插件名\n     */\n    private String            name;\n\n    /**\n     * 物理集群Id\n     */\n    private String            physicClusterId;\n\n    /**\n     * 插件版本\n     */\n    private String            version;\n\n    /**\n     * 插件存储地址\n     */\n    private String            url;\n\n    /**\n     * 插件文件md5\n     */\n    private String            md5;\n\n    /**\n     * 插件描述\n     */\n    private String            desc;\n\n    /**\n     * 插件创建人\n     */\n    private String            creator;\n\n    /**\n     * @see PluginTypeEnum\n     */\n    private Integer           pDefault;\n\n    /**\n     * 标记删除\n     */\n    private Boolean           deleteFlag;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/gateway/GatewayClusterNodePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.gateway;\n\nimport java.util.Date;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class GatewayClusterNodePO extends BasePO {\n\n    private Integer id;\n\n    private String  clusterName;\n\n    private String  hostName;\n\n    private Integer port;\n\n    private Date    heartbeatTime;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/gateway/GatewayClusterPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.gateway;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class GatewayClusterPO extends BasePO {\n\n    private Integer id;\n\n    private String  clusterName;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/gateway/GatewayJoinPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.gateway;\n\nimport java.util.Map;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport com.google.common.collect.Maps;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2018/9/19 下午5:36\n * @modified By\n *\n * join 后的gateway日志\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class GatewayJoinPO extends BaseESPO {\n\n    /**\n     * 请求path\n     */\n    private String            uri;\n    /**\n     * 请求id\n     */\n    private String            requestId;\n    /**\n     * projectId\n     */\n    private Integer           projectId;\n    /**\n     * 索引名称\n     */\n    private String            indices;\n    /**\n     * type名称\n     */\n    private String            typeName;\n    /**\n     * 查询命中索引信息json\n     */\n    private String            index;\n    /**\n     * 查询语句\n     */\n    private String            dsl;\n    /**\n     * 查询模板\n     */\n    private String            dslTemplate;\n    /**\n     * 查询模板MD5\n     */\n    private String            dslTemplateMd5;\n    /**\n     * 是否超时，\"true\"/\"false\"\n     */\n    private String            isTimedOut;\n    /**\n     * 查询语句类型\n     */\n    private String            dslType;\n    /**\n     * 查询方式,dsl/sql\n     */\n    private String            searchType;\n    /**\n     * 查询es耗时\n     */\n    private Long              esCost;\n    /**\n     * 查询总耗时\n     */\n    private Long              totalCost;\n    /**\n     * 查询shard个数\n     */\n    private Long              totalShards;\n    /**\n     * 查询总命中数\n     */\n    private Long              totalHits;\n    /**\n     * 查询响应长度\n     */\n    private Long              responseLen;\n    /**\n     * 错误名称\n     */\n    private String            exceptionName;\n    /**\n     * 创建时间\n     */\n    private String            ariusCreateTime;\n    /**\n     * timeStamp\n     */\n    private long              timeStamp;\n    /**\n     * indiceSample\n     */\n    private String            indiceSample;\n    /**\n     * 查询字段\n     */\n    private Map<String, Long> selectFields;\n    /**\n     * 过滤字段\n     */\n    private Map<String, Long> whereFields;\n    /**\n     * 聚合字段\n     */\n    private Map<String, Long> groupByFields;\n    /**\n     *排序字段\n     */\n    private Map<String, Long> orderByFields;\n    /**\n     * 多type索引查询映射后的索引名称\n     */\n    private String            destIndexName;\n    /**\n     * 请求源ip\n     */\n    private String            remoteAddr;\n\n    /**\n     * 所属集群\n     */\n    private String            clusterName;\n\n    @JSONField(name = \"selectFields\")\n    public void setSelectFields(String selectFields) {\n        this.selectFields = Maps.newHashMap();\n        splitFieldsThenAddMetric(selectFields, this.selectFields);\n    }\n\n    @JSONField(name = \"whereFields\")\n    public void setWhereFields(String whereFields) {\n        this.whereFields = Maps.newHashMap();\n        splitFieldsThenAddMetric(whereFields, this.whereFields);\n    }\n\n    @JSONField(name = \"groupByFields\")\n    public void setGroupByFields(String groupByFields) {\n        this.groupByFields = Maps.newHashMap();\n        splitFieldsThenAddMetric(groupByFields, this.groupByFields);\n    }\n\n    @JSONField(name = \"orderByFields\")\n    public void setOrderByFields(String orderByFields) {\n        this.orderByFields = Maps.newHashMap();\n        splitFieldsThenAddMetric(orderByFields, this.orderByFields);\n    }\n\n    public Map<String, Long> getGroupByFields() {\n        return groupByFields;\n    }\n\n    public Map<String, Long> getOrderByFields() {\n        return orderByFields;\n    }\n\n    public Map<String, Long> getWhereFields() {\n        return whereFields;\n    }\n\n    public Map<String, Long> getSelectFields() {\n        return selectFields;\n    }\n\n    /**\n     * 重置字段使用次数\n     * @param count\n     */\n    public void resetFieldUseCount(Long count) {\n        setMapValue(this.selectFields, count);\n        setMapValue(this.whereFields, count);\n        setMapValue(this.groupByFields, count);\n        setMapValue(this.orderByFields, count);\n    }\n\n    /**\n     * 切分字符串，然后累加计数器\n     *\n     * @param selectField\n     * @param fieldMap\n     */\n    private void splitFieldsThenAddMetric(String selectField, Map<String, Long> fieldMap) {\n        String[] selectFieldArray = StringUtils.splitByWholeSeparatorPreserveAllTokens(selectField, \",\");\n        for (String fieldName : selectFieldArray) {\n            Long count = fieldMap.computeIfAbsent(fieldName, k -> 0L);\n            ++count;\n            fieldMap.put(fieldName, count);\n        }\n    }\n\n    /**\n     * 设置map中的value\n     * @param fieldMap\n     * @param value\n     */\n    private void setMapValue(Map<String, Long> fieldMap, Long value) {\n        if (fieldMap == null) {\n            return;\n        }\n        for (Map.Entry<String, Long> entry : fieldMap.entrySet()) {\n            entry.setValue(value);\n        }\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n    // 没有更新场景，id可以为null\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return null;\n    }\n\n    @JSONField(serialize = false)\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/index/IndexCatCellPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.index;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/30\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexCatCellPO extends BaseESPO {\n    private String  cluster;\n    private String  clusterLogic;\n    private Long    resourceId;\n    private Integer projectId;\n    private String  health;\n    private String  status;\n    private String  index;\n    private Long    pri;\n    private Long    rep;\n    private Long    docsCount;\n    private Long    docsDeleted;\n    private String  storeSize;\n    private String  priStoreSize;\n    private Boolean readFlag;\n    private Boolean writeFlag;\n    private Boolean deleteFlag;\n    private Boolean platformCreateFlag;\n    private Long    timestamp;\n\n    private Long    primariesSegmentCount;\n    private Long    totalSegmentCount;\n    private Integer templateId;\n\n    @Override\n    @JSONField(serialize = false)\n    public String getKey() {\n        return cluster + \"@\" + index;\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/index/IndexSizePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.index;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author: D10865\n * @description: 索引历史大小，用于mapping优化计算得到优化成果\n * @date: Create on 2019/1/15 下午7:44\n * @modified By D10865\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Accessors(chain = true)\npublic class IndexSizePO extends BaseESPO {\n    /**\n     * 索引名称，会去除末尾版本号\n     */\n    private String indexName;\n    /**\n     * 索引模板名称\n     */\n    private String templateName;\n    /**\n     * 集群名称\n     */\n    private String clusterName;\n    /**\n     * 索引日期\n     */\n    private String date;\n    /**\n     * 主shard大小，单位字节\n     */\n    private Long   primaryStoreSize;\n    /**\n     * 单位化主shard磁盘大小\n     */\n    private String unitStoreSize;\n    /**\n     * 文档个数\n     */\n    private Long   docsCount;\n    /**\n     * 流入流量\n     */\n    private String sourceUnitSize;\n    /**\n     * 流入流量 字节\n     */\n    private Long   sourceSize;\n    /**\n     * 压缩比 primaryStoreSize/sourceSize\n     */\n    private Double compressionRatio;\n    /**\n     * 写入日期\n     */\n    private String sinkDate;\n    /**\n     * 索引大小，包括副本(如果有的话)，单位是字节\n     */\n    private Long   totalStoreSize;\n    /**\n     * 单位化索引大小，包括副本(如果有的话)\n     */\n    private String unitTotalStoreSize;\n\n    public boolean existCR() {\n        if (compressionRatio == null) {\n            return false;\n        }\n\n        if (compressionRatio <= 0) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * 是否为有效的日期\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    public boolean isVaildDate() {\n        if (StringUtils.isBlank(date)) {\n            return true;\n        }\n        char[] chars = date.toCharArray();\n        for (int i = 0; i < chars.length; ++i) {\n            if (!Character.isDigit(chars[i]) && chars[i] != '-') {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        // 以索引名称命名会出现双写的索引覆盖问题\n        return String.format(\"%s_%s\", clusterName, indexName);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/index/healthdegree/HealthDegreesPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.index.healthdegree;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(value = \"HealthDegreesPO\", description = \"模板的健康分\")\npublic class HealthDegreesPO extends BaseESPO {\n    /**\n     * 模块id\n     */\n    @ApiModelProperty(value = \"物理模板id\")\n    private Integer            templateId;\n    /**\n     * 逻辑模块id\n     */\n    @ApiModelProperty(value = \"逻辑模板id\")\n    private Integer            logicTemplateId;\n    /**\n     * 模板\n     */\n    @ApiModelProperty(value = \"模板名称\")\n    private String             template;\n    /**\n     * 集群\n     */\n    @ApiModelProperty(value = \"集群名称\")\n    private String             cluster;\n    /**\n     * 部门\n     */\n    @ApiModelProperty(value = \"部门名称\")\n    private String             department;\n    /**\n     * 离线模块得分\n     */\n    @ApiModelProperty(value = \"索引离线指标得分\")\n    private Double             offLineScore;\n    /**\n     * 实时模块得分\n     */\n    @ApiModelProperty(value = \"索引实时指标得分\")\n    private Double             onLineScore;\n    /**\n     * 健康总分\n     */\n    @ApiModelProperty(value = \"索引总的指标得分\")\n    private Double             totalScore;\n    /**\n     * 核算时间\n     */\n    @ApiModelProperty(value = \"索引健康分计算时间\")\n    private Long               timestamp;\n    /**\n     * 健康分详情\n     */\n    @ApiModelProperty(value = \"索引健康分说明\")\n    private String             desc;\n    /**\n     * 实时写入指标\n     */\n    @JSONField(name = \"realTimeWrite\")\n    @ApiModelProperty(value = \"索引实时写入详细指标\")\n    private RealTimeWrite      realTimeWrite;\n\n    /**\n     * 实时查询指标\n     */\n    @JSONField(name = \"realTimeSearch\")\n    @ApiModelProperty(value = \"索引实时查询详细指标\")\n    private RealTimeSearch     realTimeSearch;\n\n    /**\n     * 查询时长指标\n     */\n    @JSONField(name = \"searchCostTime\")\n    @ApiModelProperty(value = \"索引实时查询耗时详细指标\")\n    private RealTimeSearchCost realTimeSearchCost;\n\n    /**\n     * 实时jvm使用率\n     */\n    @JSONField(name = \"jvmOldGcCollection\")\n    @ApiModelProperty(value = \"索引实时GC详细指标\")\n    private RealTimeOldGC      realTimeOldGC;\n\n    /**\n     * 实时磁盘使用率\n     */\n    @JSONField(name = \"diskUseRate\")\n    @ApiModelProperty(value = \"索引实时磁盘详细指标\")\n    private RealTimeDiskUse    realTimeDiskUse;\n\n    /**\n     * 实时cpu使用率\n     */\n    @JSONField(name = \"osCpuUseRate\")\n    @ApiModelProperty(value = \"索引实时CPU详细指标\")\n    private RealTimeCpuUse     realTimeCpuUse;\n\n    /**\n     * 离线模块\n     */\n    @JSONField(name = \"offLine\")\n    @ApiModelProperty(value = \"索引离线详细指标\")\n    private OffLine            offLine;\n\n    @Override\n    public String getKey() {\n        return cluster + \"_\" + template + \"_\" + timestamp;\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/metrics/MetricsDictionaryPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.metrics;\n\nimport com.baomidou.mybatisplus.annotation.TableName;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 指标字典配置po\n *\n * @author shizeying\n * @date 2022/09/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@TableName(\"metric_dictionary_info\")\npublic class MetricsDictionaryPO extends BasePO {\n    /**\n     * id自增\n     */\n    private Integer id;\n\n    /**\n     * 指标分类\n     */\n    private String type;\n\n    /**\n     * metric\n     */\n    private String metricType;\n\n    /**\n     * 指标名称\n     */\n    private String  name;\n\n    /**\n     * 指标价值\n     */\n    private String  price;\n\n    /**\n     * 计算间隔\n     */\n    private String interval;\n\n    /**\n     * 当前计算逻辑\n     */\n    private String currentCalLogic;\n    /**\n     * 是否黄金指标\n     */\n    private Integer isGold;\n    /**\n     * 单位\n     */\n    private String unit;\n    /**\n     * 交互形式\n     */\n    private String interactiveForm;\n    /**\n     * 告警指标\n     */\n    private Integer isWarning;\n    /**\n     * 指标来源\n     */\n    private String source;\n    /**\n     * 指标标签\n     */\n    private String tags;\n    /**\n     * 模块\n     */\n    private String model;\n    /**\n     * 阈值配置\n     */\n    private Integer isThreshold;\n    /**\n     * 阈值详情\n     */\n    private String threshold;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/metrics/UserConfigPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.metrics;\n\nimport com.baomidou.mybatisplus.annotation.TableName;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 用户指标配置po\n *\n * @author shizeying\n * @date 2022/05/24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@TableName(\"user_config_info\")\npublic class UserConfigPO extends BasePO {\n    /**\n     * id自增\n     */\n    private Integer id;\n\n    /**\n     * 用户名\n     */\n    private String  userName;\n\n    /**\n     * 指标看板的配置\n     */\n    private String  configInfo;\n\n    /**\n     * 应用ID\n     */\n    private Integer projectId;\n\n    /**\n     * 配置类型\n     */\n    private Integer configType;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/monitor/AriusMetaJobClusterDistributePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.monitor;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Date;\n\n/**\n * @author ohushenglin_v\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class AriusMetaJobClusterDistributePO {\n    /**\n     * 主键id\n     */\n    private Long    id;\n    /**\n     * 集群id\n     */\n    private Integer clusterId;\n    /**\n     * 集群名称\n     */\n    private String  cluster;\n    /**\n     * 集群数据中心：us01/cn\n     */\n    private String  dataCentre;\n    /**\n     * monitor集群host\n     */\n    private String  monitorHost;\n    /**\n     * monitor监控时间\n     */\n    private Date    monitorTime;\n    /**\n     * 创建时间\n     */\n    private Date    gmtCreate;\n    /**\n     * 更新时间\n     */\n    private Date    gmtModify;\n    /**\n     * 修改记录使用,monitorHost字段用于校验是否被修改过\n     */\n    private String  destMonitorHost;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/operaterecord/OperateRecordInfoPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.operaterecord;\n\nimport com.baomidou.mybatisplus.annotation.TableName;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.ModuleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport java.util.Date;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class OperateRecordInfoPO extends BasePO {\n\n    /**\n     * 主键\n     */\n    private Integer id;\n\n    /**\n     * @see ModuleEnum\n     */\n    private Integer moduleId;\n\n    /**\n     * @see OperateTypeEnum\n     */\n    private Integer operateId;\n\n    /**\n     * 操作描述\n     */\n    private String  content;\n\n    /**\n     * 操作人\n     */\n    private String  userOperation;\n\n    /**\n     * 操作时间\n     */\n    private Date    operateTime;\n    /**\n    * 触发方式\n     * @see com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum\n    */\n    private Integer triggerWayId;\n    /**\n    * 应用id\n    */\n    private String  projectName;\n    /**\n     * 业务id\n     */\n    private String  bizId;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/order/WorkOrderPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.order;\n\nimport java.util.Date;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.workorder.WorkOrderTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @since 2020-08-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class WorkOrderPO extends BasePO {\n\n    /**\n     * ID\n     */\n    private Long    id;\n\n    /**\n     * @see WorkOrderTypeEnum\n     */\n    private String  type;\n\n    /**\n     * 标题\n     */\n    private String  title;\n\n    /**\n     * 扩展字段\n     */\n    private String  extensions;\n\n    /**\n     * 申请人\n     */\n    private String  applicant;\n\n    /**\n     * 申请人projectid\n     */\n    private Integer applicantProjectId;\n\n    /**\n     * 备注信息\n     */\n    private String  description;\n\n    /**\n     * 审批人\n     */\n    private String  approver;\n\n    /**\n     * 结束时间\n     */\n    private Date    finishTime;\n\n    /**\n     * 审批信息\n     */\n    private String  opinion;\n\n    /**\n     * 工单状态, 0:待审批, 1:通过, 2:拒绝, 3:取消\n     */\n    private Integer status;\n\n    /**\n     * 审批人projectId\n     */\n    private Integer approverProjectId;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/project/ESUserPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESUserPO extends BasePO {\n\n    /**\n     * 主键\n     */\n    private Integer id;\n\n    /**\n     * 是否是超管\n     */\n    private Integer isRoot;\n\n    /**\n     * 验证码\n     */\n    private String  verifyCode;\n\n    /**\n     * 备注\n     */\n    private String  memo;\n\n    /**\n     * 删除标志\n     */\n    private Integer isActive;\n\n    /**\n     * 查询限流值\n     */\n    private Integer queryThreshold;\n\n    /**\n     * 租户查询集群\n     */\n    private String  cluster;\n\n    /**\n     * 查询模式\n     */\n    private Integer searchType;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n    private Integer projectId;\n    /**\n     * 默认显示\n     */\n    private Boolean defaultDisplay;\n\n    /******************** 即将废弃字段 ***********************/\n\n    private String  ip;\n\n    private String  indexExp;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/project/ProjectClusterLogicAuthPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 逻辑集群权限PO\n * @author wangshu\n * @date 2020/09/17\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ProjectClusterLogicAuthPO extends BasePO {\n    /**\n     * 主键\n     */\n    private Long    id;\n\n    /**\n     * project id\n     */\n    private Integer projectId;\n\n    /**\n     * 逻辑集群ID\n     */\n    private Long    logicClusterId;\n\n    /**\n     * 权限类型\n     * @see ProjectClusterLogicAuthEnum\n     */\n    private Integer type;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/project/ProjectConfigPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ProjectConfigPO extends BasePO {\n\n    /**\n     * projectId\n     */\n    private Integer projectId;\n\n    /**\n     * gateway返回结果解析开关\n     */\n    private Integer analyzeResponseEnable;\n\n    /**\n     * 是否生效DSL分析查询限流值 1为生效DSL分析查询限流值，0不生效DSL分析查询限流值\n     */\n    private Integer dslAnalyzeEnable;\n\n    /**\n     * 是否开启聚合分析  1 开启  0 不开启  默认为 1\n     */\n    private Integer aggrAnalyzeEnable;\n\n    /**\n     * 是否索引存储分离，1为分离，0为不分离，默认为0\n     */\n    private Integer isSourceSeparated;\n    /**\n     * 慢查询\n     */\n    private Integer slowQueryTimes;\n    private String  memo;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/project/ProjectTemplateAuthPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/4/16\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ProjectTemplateAuthPO extends BasePO {\n\n    /**\n     * 主键\n     */\n    private Long    id;\n\n    /**\n     * project id\n     */\n    private Integer projectId;\n\n    /**\n     * 模板ID\n     */\n    private Integer templateId;\n\n    /**\n     * 权限类型  读写  读\n     * @see ProjectTemplateAuthEnum\n     */\n    private Integer type;\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/query/IndexNameAccessCountPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.query;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/27 下午2:14\n * @modified By D10865\n *\n * 索引维度访问次数\n *\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@Accessors(chain = true)\n@ApiModel(value = \"IndexNameAccessCountPO\", description = \"索引访问统计结果\")\npublic class IndexNameAccessCountPO extends BaseESPO {\n\n    /**\n     * 索引模板主键\n     */\n    @ApiModelProperty(\"索引模板主键\")\n    private Integer templateId;\n    /**\n     * 逻辑模板id\n     */\n    @ApiModelProperty(\"逻辑模板id\")\n    private Integer logicTemplteId;\n    /**\n     * 索引模板名称\n     */\n    @ApiModelProperty(\"索引模板名称\")\n    private String  templateName;\n    /**\n     * 集群名称\n     */\n    @ApiModelProperty(\"集群名称\")\n    private String  clusterName;\n    /**\n     * 索引名称\n     */\n    @ApiModelProperty(\"索引名称\")\n    private String  indexName;\n    /**\n     * 访问次数\n     */\n    @ApiModelProperty(\"访问次数\")\n    private Long    count;\n    /**\n     * 统计日期\n     */\n    @ApiModelProperty(\"统计日期\")\n    private String  date;\n\n    /**\n     * 累加访问次数\n     */\n    @JSONField(serialize = false)\n    public void increase(Long value) {\n        if (count == null) {\n            count = 0L;\n        }\n        count += value;\n    }\n\n    /**\n     * 获取主键key\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        // 由于存在索引双写的情况，需要加上索引模板主键作为联合id\n        return String.format(\"%d_%s_%s\", templateId, indexName, date);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/query/IndexNameQueryAvgRatePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.query;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/27 下午2:14\n * @modified By D10865\n *\n * 索引维度访问次数\n *\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@Accessors(chain = true)\n@ApiModel(value = \"IndexNameQueryAvgRatePO\", description = \"索引访问统计结果\")\npublic class IndexNameQueryAvgRatePO {\n\n    /**\n     * 索引名称\n     */\n    @ApiModelProperty(\"索引名称\")\n    private String indexName;\n    /**\n     * 访问次数\n     */\n    @ApiModelProperty(\"访问频率\")\n    private Double queryTotalRate;\n    /**\n     * 统计日期\n     */\n    @ApiModelProperty(\"统计日期\")\n    private String date;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/query/ProjectQueryPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.query;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * 获取ProjectId查询信息\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ProjectQueryPO {\n\n    /**\n     * 模板名称\n     */\n    private String       indiceSample;\n    /**\n     * dsl查询模版\n     */\n    private String       dslTemplate;\n    /**\n     * dsl查询时间 yyyy-MM-dd HH:mm:ss\n     */\n    private String       timeStamp;\n    /**\n     * 模版MD5\n     */\n    private List<String> dslTemplateMd5;\n    /**\n     * 查询耗时\n     */\n    private Integer      totalCost;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/query/ProjectTemplateAccessCountPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.query;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport io.swagger.annotations.ApiModel;\nimport java.util.Map;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/27 下午2:19\n * @modified By D10865\n *\n * project访问索引模板级别次数\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@Accessors(chain = true)\n@ApiModel(value = \"ProjectTemplateAccessCountPO\", description = \"Project访问索引模板级别次数\")\npublic class ProjectTemplateAccessCountPO extends BaseESPO {\n\n    /**\n     * 索引模板主键\n     */\n    private Integer                                                  templateId;\n    /**\n     * 索引逻辑id\n     */\n    private Integer                                                  logicTemplateId;\n    /**\n     * 索引模板名称\n     */\n    private String                                                   templateName;\n    /**\n     * 集群名称\n     */\n    private String                                                   clusterName;\n    /**\n     * 应用账号\n     */\n\n    private Integer                                                  projectId;\n    /**\n     * 访问索引模板次数，为@accessDetailInfo 访问索引明细的总次数\n     */\n    private Long                                                     count;\n    /**\n     *访问索引名称明细数据,key不能是.开头，否则写入es失败\n     */\n    private Map<String/*indexName*/, Long/*access indexName count*/> accessDetailInfo;\n    /**\n     * 统计日期\n     */\n    private String                                                   date;\n\n    /**\n     * 累加访问次数\n     */\n    @JSONField(serialize = false)\n    public void increase(Long value) {\n        if (count == null) {\n            count = 0L;\n        }\n        count += value;\n    }\n\n    /**\n     * 获取主键key\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        // 由于存在索引双写的情况，需要加上索引模板主键作为联合id\n        return String.format(\"%d_%d_%s\", templateId, projectId, date);\n    }\n\n    @JSONField(serialize = false)\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/query/TemplateAccessCountPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.query;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/27 下午2:09\n * @modified By D10865\n *\n * 索引模板维度访问次数\n *\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@Accessors(chain = true)\n@ApiModel(value = \"TemplateAccessCountPO\", description = \"索引模板访问次数统计\")\npublic class TemplateAccessCountPO extends BaseESPO {\n    /**\n     * 索引模板主键\n     */\n    @ApiModelProperty(value = \"物理索引模板ID\")\n    private Integer templateId;\n    /**\n     * 逻辑模板id\n     */\n    @ApiModelProperty(value = \"逻辑模板id\")\n    private Integer logicTemplateId;\n    /**\n     * 索引模板名称\n     */\n    @ApiModelProperty(value = \"索引模板名称\")\n    private String  templateName;\n    /**\n     * 集群名称\n     */\n    @ApiModelProperty(value = \"集群名称\")\n    private String  clusterName;\n    /**\n     * 访问次数\n     */\n    @ApiModelProperty(value = \"访问次数\")\n    private Long    count;\n    /**\n     * 统计日期\n     */\n    @ApiModelProperty(value = \"统计日期\")\n    private String  date;\n\n    /**\n     * 累加访问次数\n     */\n    @JSONField(serialize = false)\n    public void increase(Long value) {\n        if (count == null) {\n            count = 0L;\n        }\n        count += value;\n    }\n\n    /**\n     * 获取主键key\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.format(\"%d_%s\", templateId, date);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/quota/ESTemplateQuotaUsagePO.java",
    "content": ""
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/shard/SegmentPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.shard;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class SegmentPO extends BasePO {\n\n    private String index;\n\n    private String shard;\n\n    private String ip;\n\n    private String segment;\n\n    @JSONField(name = \"size.memory\")\n    private Double memoSize;\n\n    /**\n     * 主副标识 p 或 r\n     */\n    @JSONField(name = \"prirep\")\n    private String primaryFlag;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/shard/ShardCatCellPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.shard;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Shard分布.\n *\n * @ClassName ShardDistributionVO\n * @Author gyp\n * @Date 2022/6/7\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ShardCatCellPO extends BaseESPO {\n    @ApiModelProperty(\"主副\")\n    private String prirep;\n    @ApiModelProperty(\"节点名称\")\n    private String node;\n    @ApiModelProperty(\"文档\")\n    private String docs;\n    @ApiModelProperty(\"ip\")\n    private String ip;\n    @ApiModelProperty(\"索引\")\n    private String index;\n    @ApiModelProperty(\"分片\")\n    private String shard;\n    @ApiModelProperty(\"state\")\n    private String state;\n    @ApiModelProperty(\"store大小\")\n    private String store;\n    @ApiModelProperty(\"物理集群名称\")\n    private String clusterPhy;\n\n    private long    timestamp;\n\n    @Override\n    @JSONField(serialize = false)\n    public String getKey() {\n        return index+\"@\"+clusterPhy+\"@\"+prirep+\"@\"+ip+\"@\"+shard;\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/stats/ClusterLogicStatsPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.stats;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterLogicStatsPO {\n    /**\n     * 逻辑集群名称\n     */\n    private String name;\n\n    /**\n     * 逻辑集群id\n     */\n    private long   id;\n\n    /**\n     * 逻辑集群状态\n     */\n    private String status;\n\n    /**\n     * 逻辑集群状态\n     */\n    private int    statusType;\n\n    /**\n     * docNu\n     */\n    private Long docNu;\n\n    /**\n     * 总的磁盘容量\n     */\n    private double totalDisk;\n\n    /**\n     * 已使用的磁盘容量\n     */\n    private double usedDisk;\n\n    /**\n     * 空闲的磁盘容量\n     */\n    private double freeDisk;\n\n    /**\n     * 索引数量\n     */\n    private long   indexNu;\n\n    /**\n     * dataNode个数\n     */\n    private long   numberDataNodes;\n\n    /**\n     * masterNode个数\n     */\n    private long   masterNodeNu;\n\n    /**\n     * 未分配shard\n     */\n    private long   unAssignedShards;\n\n    /**\n     * pengdingtask梳理\n     */\n    private long   numberPendingTasks;\n\n    /**\n     * 节点存活率\n     */\n    private int    alivePercent;\n    /**\n     * cpu相关\n     */\n    private double cpuUsedPercent;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/stats/ESClusterThreadPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.stats;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ESClusterThreadPO extends BasePO {\n\n    @JSONField(name = \"node_name\")\n    private String nodeName;\n\n    @JSONField(name = \"name\")\n    private String threadName;\n\n    @JSONField(name = \"active\")\n    private Long   activeNum;\n\n    @JSONField(name = \"rejected\")\n    private Long   rejectedNum;\n\n    @JSONField(name = \"queue\")\n    private Long   queueNum;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/stats/TemplateTpsMetricPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.stats;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateTpsMetricPO {\n\n    /**\n     * 历史每小时tps峰值 单位 条/s\n     * 是取各个物理模板最大值\n     */\n    private Double                          maxTps;\n\n    /**\n     * 最大值对应的小时时间\n     */\n    private String                          maxTpsTimestamp;\n\n    /**\n     * 最大值对应的索引模板物理ID\n     */\n    private Long                            maxTpsTemplateId;\n\n    /**\n     * 每个物理模板，最近15分钟平均值 单位 条/s\n     *\n     */\n    private Map<Long/*templateId*/, Double> currentTpsMap;\n\n    /**\n     * 每个物理模板，最近一段时间失败次数的平均值 单位 条/s\n     */\n    private Map<Long/*templateId*/, Double> currentFailCountMap;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/task/OpTaskPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * AriusWorkTask PO 对象\n * \n * @author fengqiongfeng\n * @date 2020-12-21\n */\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class OpTaskPO extends BasePO {\n\n    /**\n     * 序列化版本号\n     */\n    private static final long serialVersionUID = 1L;\n\n    /**\n     * id\n     */\n    private Integer           id;\n\n    /**\n     * 标题 \n     */\n    private String            title;\n\n    /**\n     * 任务类型\n     */\n    private Integer           taskType;\n\n    /**\n     * 业务数据主键 \n     */\n    private String            businessKey;\n\n    /**\n     * 任务状态：\n     * success:成功 failed:失败\n     * running:执行中 waiting:等待\n     * cancel:取消 pause:暂停\n     */\n    private String            status;\n\n    /**\n     * 创建人 \n     */\n    private String            creator;\n\n    /**\n     * 标记删除 \n     */\n    private Boolean           deleteFlag;\n\n    /**\n     * expandData \n     */\n    private String            expandData;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/task/ecm/EcmTaskDetailPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class EcmTaskDetailPO extends BasePO {\n\n    private static final long serialVersionUID = 1L;\n\n    /**\n     * ID主键自增\n     */\n    private Long              id;\n\n    /**\n     *  工单任务ID\n     */\n    private Long              workOrderTaskId;\n\n    /**\n     *  所属角色\n     */\n    private String            role;\n\n    /**\n     * 节点名称/主机名成\n     */\n    private String            hostname;\n\n    /**\n     * 分组\n     */\n    private Integer           grp;\n    /**\n     * 顺序\n     */\n    private Integer           idx;\n\n    /**\n     * 状态\n     */\n    private String            status;\n\n    /**\n     * 容器云 /物理机 接口返回任务ID\n     */\n    private Long              taskId;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/task/ecm/EcmTaskPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmTaskStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class EcmTaskPO extends BasePO {\n\n    /**\n     * ID主键自增\n     */\n    private Long    id;\n\n    /**\n     * 标题\n     */\n    private String  title;\n\n    /**\n     * 工单ID\n     */\n    private Long    workOrderId;\n\n    /**\n     * 物理集群ID\n     */\n    private Long    physicClusterId;\n\n    /**\n     * 集群节点角色 执行顺序\n     */\n    private String  clusterNodeRole;\n\n    /**\n     * 状态\n     * @see EcmTaskStatusEnum\n     */\n    private String  status;\n\n    /**\n     * 类型  docker容器云/host 物理机\n     */\n    private Integer type;\n\n    /**\n     * 类型  1 集群新增  2 集群扩容 3 集群缩容 4 集群重启 5 集群升级\n     */\n    private Integer orderType;\n\n    /**\n     *  工单数据\n     */\n    private String  handleData;\n\n    /**\n     * 创建人\n     */\n    private String  creator;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/IndexTemplatePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/9\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplatePO extends BasePO {\n\n    private Integer id;\n\n    /**\n     * 索引模板名称\n     */\n    private String  name;\n\n    /**\n     * projectId\n     */\n    private Integer projectId;\n\n    /**\n     * 用户数据类型\n     * @see DataTypeEnum\n     */\n    private Integer dataType;\n\n    /**\n     * 索引滚动格式\n     */\n    private String  dateFormat;\n\n    /**\n     * 数据中心\n     */\n    private String  dataCenter;\n\n    /**\n     * 数据保存时长 单位天\n     */\n    private Integer expireTime;\n\n    /**\n     * 热数据保存时长 单位天\n     */\n    private Integer hotTime;\n\n   \n\n    /**\n     * 时间字段\n     */\n    private String  dateField;\n\n    /**\n     * 时间字段的格式\n     */\n    private String  dateFieldFormat;\n\n    /**\n     * id地钻\n     */\n    private String  idField;\n\n    /**\n     * routing字段\n     */\n    private String  routingField;\n\n    /**\n     * 表达式\n     */\n    private String  expression;\n\n    /**\n     * 备注\n     */\n    private String  desc;\n\n    /**\n     * 规格 单位台\n     */\n    private Double  quota;\n\n    /**\n     * 写入限流值，\n     * writeRateLimit = 0 禁止写入，\n     * writeRateLimit = -1 不限流，\n     * writeRateLimit = 123 具体的写入tps限流值，即单台client每秒写入123条文档\n     */\n    private Integer writeRateLimit;\n\n    /**\n     * 是否禁止读\n     */\n    private Boolean blockRead;\n\n    /**\n     * 是否禁止写\n     */\n    private Boolean blockWrite;\n\n    /**\n     * pipeline\n     */\n    private String  ingestPipeline;\n\n    /**\n     * 逻辑集群id\n     */\n    private Long    resourceId;\n\n    /**\n     * 服务等级\n     */\n    private Integer level;\n\n    /*\n     * dcdr位点差\n     */\n    private Long    checkPointDiff;\n\n    /**\n     * 是否有创建dcdr链路\n     */\n    private Boolean hasDCDR;\n\n    /**\n     * 已开启的模板服务\n     */\n    private String  openSrv;\n\n    /**\n     * 可用磁盘容量\n     */\n    private Double  diskSize;\n    /**\n     * 模版健康率 -1 是unknown\n     *\n     */\n    private Integer health;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/IndexTemplatePhyPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/9\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndexTemplatePhyPO extends BasePO {\n\n    private Long    id;\n\n    private Integer logicId;\n\n    private String  name;\n\n    private String  expression;\n\n    private String  cluster;\n\n    private String  rack;\n\n    private Integer shard;\n\n    private Integer shardRouting;\n\n    private Integer version;\n\n    private Integer role;\n\n    private Integer status;\n\n    private String  config;\n\n    private Integer regionId;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateAliasPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * \n * @author d06679\n * @date 2019-07-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateAliasPO extends BasePO {\n\n    private Integer id;\n\n    private Integer logicId;\n\n    private String  name;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateConfigPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateConfigPO extends BasePO {\n\n    private Long    id;\n\n    private Integer logicId;\n\n    private Integer isSourceSeparated;\n\n    private Double  adjustTpsFactor;\n\n    private Double  adjustShardFactor;\n\n    private Integer dynamicLimitEnable;\n\n    private Integer mappingImproveEnable;\n\n    /**\n     * 预创建分区索引标识，0：不预先创建；1：预先创建\n     */\n    private Boolean preCreateFlags;\n\n    /**\n     * 禁用报错_source标识，0：不禁用；1：禁用\n     */\n    private Boolean disableSourceFlags;\n\n    /**\n     * 限定逻辑模板下所有物理模板shardNum\n     */\n    private Integer shardNum;\n\n    /**\n     * indexRollover功能，0：不禁用；1：禁用\n     */\n    private Boolean disableIndexRollover;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateFieldPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.*;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/15 下午7:40\n * @modified By D10865\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateFieldPO extends BaseESPO {\n\n    private Integer             id;\n\n    private String              name;\n\n    private String              clusterName;\n\n    private Map<String, String> templateFieldMap;\n\n    private Integer             fieldCount;\n\n    @JSONField(serialize = false)\n    private Set<String>         keySet;\n    /**\n     * 更新状态，1为启用mapping优化 @UpdateMappingState\n     */\n    private Integer             state;\n    /**\n     * 是否索引存储分离，1为分离，0不分离\n     */\n    private Integer             sourceSeparated;\n    /**\n     * 可忽略mapping优化字段集合\n     */\n    private Set<String>         ignoreFields;\n\n    public TemplateFieldPO(int id, String name, String clusterName) {\n        this.id = id;\n        this.name = name;\n        this.clusterName = clusterName;\n    }\n\n    public TemplateFieldPO(int id, String name, String clusterName, Map<String, String> templateFieldMap) {\n        this.id = id;\n        this.name = name;\n        this.clusterName = clusterName;\n        this.templateFieldMap = templateFieldMap;\n    }\n\n    public TemplateFieldPO(Integer id, String name, String clusterName, Map<String, String> templateFieldMap,\n                           Integer state) {\n        this.id = id;\n        this.name = name;\n        this.clusterName = clusterName;\n        this.templateFieldMap = templateFieldMap;\n        this.state = state;\n    }\n\n    public void setTemplateFieldMap(Map<String, String> templateFieldMap) {\n        this.templateFieldMap = templateFieldMap;\n        if (templateFieldMap != null) {\n            this.fieldCount = templateFieldMap.size();\n        } else {\n            this.fieldCount = 0;\n        }\n    }\n\n    @JSONField(serialize = false)\n    public Set<String> getKeySet() {\n        if (null == keySet) {\n            keySet = new HashSet<>();\n            if (templateFieldMap != null) {\n                keySet.addAll(templateFieldMap.keySet());\n            }\n        }\n        return keySet;\n    }\n\n    @JSONField(serialize = false)\n    public void setKeySet(Set<String> keySet) {\n        this.keySet = keySet;\n    }\n\n    /**\n     * 从其他map进行更新\n     * that为从ES中获取到的对象(原来的值)，this目前收集到的字段信息(现有的值)\n     *\n     * @param that\n     */\n    @JSONField(serialize = false)\n    public void updateFromTemplateFieldPO(TemplateFieldPO that) {\n        Map<String, String> thatTemplateFieldMap = that.getTemplateFieldMap();\n        state = that.state;\n\n        if (templateFieldMap != null) {\n            Iterator<Map.Entry<String, String>> entryIterator = templateFieldMap.entrySet().iterator();\n\n            while (entryIterator.hasNext()) {\n                Map.Entry<String, String> updateEntry = entryIterator.next();\n\n                // 字段名为空则移除\n                if (StringUtils.isBlank(updateEntry.getKey())) {\n                    entryIterator.remove();\n                    continue;\n                }\n\n                // 如果原来就有，则使用原来的值\n                if (thatTemplateFieldMap != null && thatTemplateFieldMap.containsKey(updateEntry.getKey())) {\n                    updateEntry.setValue(thatTemplateFieldMap.get(updateEntry.getKey()));\n                }\n            }\n            fieldCount = templateFieldMap.size();\n        } else {\n            fieldCount = 0;\n        }\n\n        // 可忽略字段信息以ES中的为准\n        ignoreFields = that.ignoreFields;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        TemplateFieldPO that = (TemplateFieldPO) o;\n\n        if (!id.equals(that.id)) {\n            return false;\n        }\n        if (name != null ? !name.equals(that.name) : that.name != null) {\n            return false;\n        }\n        if (clusterName != null ? !clusterName.equals(that.clusterName) : that.clusterName != null) {\n            return false;\n        }\n\n        if (fieldCount != null ? !fieldCount.equals(that.fieldCount) : that.fieldCount != null) {\n            return false;\n        }\n\n        if (state != null ? !state.equals(that.state) : that.state != null) {\n            return false;\n        }\n\n        if (sourceSeparated != null ? !sourceSeparated.equals(that.sourceSeparated) : that.sourceSeparated != null) {\n            return false;\n        }\n\n        if (!Objects.equals(ignoreFields, that.ignoreFields)) {\n            return false;\n        }\n\n        if (templateFieldMap == null && that.templateFieldMap == null) {\n            return true;\n        }\n        if (templateFieldMap != null || that.templateFieldMap != null) {\n            return false;\n        }\n\n        // 仅比较map的个数和key与key之间比较\n        if (templateFieldMap.size() != that.templateFieldMap.size()) {\n            return false;\n        }\n\n        Set<String> key1 = new TreeSet<>();\n        key1.addAll(templateFieldMap.keySet());\n\n        Set<String> key2 = new TreeSet<>();\n        key2.addAll(that.templateFieldMap.keySet());\n\n        if (!StringUtils.join(key1, AdminConstant.COMMA).equals(StringUtils.join(key2, AdminConstant.COMMA))) {\n            return false;\n        }\n\n        return true;\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return \"\" + id;\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateHealthDegreePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateHealthDegreePO extends BaseESPO {\n\n    /**\n     * 索引模板id\n     */\n    private Integer       logicTemplateId;\n\n    /**\n     * 健康分\n     */\n    private Integer       healthDegree;\n\n    /**\n     * 标签\n     */\n    List<TemplateLabelPO> labelPOS;\n\n    /**\n     * 获取主键key\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.valueOf(logicTemplateId);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateHealthDegreeRecordPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.util.DateTimeUtil;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateHealthDegreeRecordPO extends TemplateHealthDegreePO {\n    /**\n     * 统计时间\n     */\n    private Long timestamp;\n\n    /**\n     * 获取主键key\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.format(\"%d_%s\", getLogicTemplateId(), DateTimeUtil.formatTimestamp(timestamp));\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateHitPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.BaseException;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Maps;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Map;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateHitPO extends BaseESPO {\n\n    private static final ILog LOGGER      = LogFactory.getLog(TemplateHitPO.class);\n\n    /**\n     * 模版主键id\n     */\n    private Integer           id;\n    /**\n     * 索引模板名称\n     */\n    private String            name;\n    /**\n     * 集群名称\n     */\n    private String            clusterName;\n    /**\n     * 日期\n     */\n    private String            date;\n\n    /**\n     * 实际使用周期\n     */\n    private long              useTime;\n\n    private long              day1Count   = 0;\n\n    private long              day3Count   = 0;\n\n    private long              day7Count   = 0;\n\n    private long              day30Count  = 0;\n\n    private long              dayAllCount = 0;\n\n    /**\n     * 索引名称命中次数统计\n     */\n    private Map<String, Long> hitIndexMap = Maps.newHashMap();\n\n    public TemplateHitPO(Integer id, String name, String clusterName, String date) {\n        this.id = id;\n        this.name = name;\n        this.clusterName = clusterName;\n        this.date = date;\n    }\n\n    public TemplateHitPO(TemplateHitPO templateHitPO) {\n        this.id = templateHitPO.id;\n        this.name = templateHitPO.name;\n        this.clusterName = templateHitPO.clusterName;\n        this.date = templateHitPO.date;\n    }\n\n    public void addCount(String indexName, long count) {\n        hitIndexMap.putIfAbsent(indexName, 0L);\n\n        Long value = hitIndexMap.get(indexName);\n        hitIndexMap.put(indexName, value + count);\n    }\n\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.format(\"%s_%d_%s\", EnvUtil.getStr(), id, date.replace(\" \", \"_\"));\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n\n    @JSONField(serialize = false)\n    public void merge(TemplateHitPO templateHitPO) {\n        if (templateHitPO == null) {\n            return;\n        }\n\n        Map<String, Long> m = templateHitPO.hitIndexMap;\n        for (Map.Entry<String, Long> entry : m.entrySet()) {\n            String index = entry.getKey();\n            Long count = entry.getValue();\n\n            hitIndexMap.putIfAbsent(index, 0L);\n\n            this.hitIndexMap.put(index, this.hitIndexMap.get(index) + count);\n        }\n    }\n\n    // 统计当天，3天，7天，30天，全部的查询次数\n    private static final Long ONE_DAY = 24 * 60 * 60 * 1000L;\n\n    public void setSumHits(String express, String timeFormat) {\n        try {\n            if (!express.endsWith(\"*\") || timeFormat == null || timeFormat.trim().length() == 0) {\n                return;\n            }\n            timeFormat = timeFormat.replace(\"YYYY\", \"yyyy\");\n\n            SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd\");\n            Long dateTime = sdf.parse(date).getTime();\n\n            SimpleDateFormat extraSdf = null;\n            if (!timeFormat.contains(\"dd\")) {\n                extraSdf = new SimpleDateFormat(\"_yyyy-MM-dd\");\n            }\n\n            int length = express.length();\n            if (express.endsWith(\"*\")) {\n                length--;\n            }\n\n            sdf = new SimpleDateFormat(timeFormat);\n            handleHitIndexMap(express, sdf, dateTime, extraSdf, length);\n\n        } catch (Exception t) {\n            LOGGER.error(\n                \"class=TemplateHitPO||method=setSumHits||errMsg=get used day num error, express:{}, format:{}, hitPO:{}\",\n                express, timeFormat, JSON.toJSONString(this), t);\n        }\n    }\n\n    private void handleHitIndexMap(String express, SimpleDateFormat sdf, Long dateTime, SimpleDateFormat extraSdf,\n                                   int length) throws ParseException {\n        for (Map.Entry<String, Long> entry : hitIndexMap.entrySet()) {\n            String index = entry.getKey();\n            String dataStr = index.substring(length);\n            Long count = entry.getValue();\n            if (count == null) {\n                continue;\n            }\n\n            Long time = getTime(sdf, extraSdf, dataStr);\n\n            if (time == null) {\n                LOGGER.error(\"class=TemplateHitPO||method=handleHitIndexMap||errMsg=parser time error, indexName:\"\n                             + index + \", express:\" + express);\n                continue;\n            }\n\n            Long gap = dateTime - time;\n            int day = (int) (gap / ONE_DAY);\n            dayAllCount += count;\n\n            if (day < 30) {\n                day30Count += count;\n            }\n\n            if (day < 7) {\n                day7Count += count;\n            }\n\n            if (day < 3) {\n                day3Count += count;\n            }\n\n            if (day < 1) {\n                day1Count += count;\n            }\n        }\n    }\n\n    // 返回-1表示不处理\n    @JSONField(serialize = false)\n    public long getUsedDayNum(String express, String timeFormat, long maxQpsPerDay) {\n        try {\n            if (!express.endsWith(\"*\") || timeFormat == null || timeFormat.trim().length() == 0) {\n                return -1;\n            }\n            timeFormat = timeFormat.replace(\"YYYY\", \"yyyy\");\n\n            SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd\");\n            Long dateTime = sdf.parse(date).getTime();\n\n            SimpleDateFormat extraSdf = null;\n            if (!timeFormat.contains(\"dd\")) {\n                extraSdf = new SimpleDateFormat(\"_yyyy-MM-dd\");\n            }\n\n            int length = express.length();\n            if (express.endsWith(\"*\")) {\n                length--;\n            }\n\n            sdf = new SimpleDateFormat(timeFormat);\n            Long maxGap = 0L;\n            for (Map.Entry<String, Long> entry : hitIndexMap.entrySet()) {\n                String index = entry.getKey();\n                String dataStr = index.substring(length);\n                Long count = entry.getValue();\n                if (count != null && count < maxQpsPerDay) {\n                    continue;\n                }\n\n                Long time = getTime(sdf, extraSdf, dataStr);\n\n                if (time == null) {\n                    throw new BaseException(\"parse time error\", ResultType.FAIL);\n                }\n\n                Long gap = dateTime - time;\n                if (gap > maxGap) {\n                    maxGap = gap;\n                }\n            }\n            return maxGap;\n        } catch (Exception t) {\n            LOGGER.error(\n                \"class=TemplateHitPO||method=getUsedDayNum||errMsg=get used day num error express:{}, format:{}, hitPO:{}\",\n                express, timeFormat, JSON.toJSONString(this), t);\n            return -1;\n        }\n    }\n\n    private Long getTime(SimpleDateFormat sdf, SimpleDateFormat extraSdf, String dataStr) throws ParseException {\n        Long time = null;\n        try {\n            time = sdf.parse(dataStr).getTime();\n        } catch (Exception t) {\n            if (extraSdf != null) {\n                time = extraSdf.parse(dataStr).getTime();\n            }\n        }\n        return time;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateLabelPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Date;\n\n/**\n * 索引标签\n *\n * @author d06679\n * @date 2017/10/9\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateLabelPO extends BaseESPO {\n\n    /**\n     * 索引模板id\n     */\n    private Integer indexTemplateId;\n    /**\n     * 标签id，有一定的规则\n     */\n    private String  labelId;\n    /**\n     * 标签名称\n     */\n    private String  labelName;\n    /**\n     * 标记时间\n     */\n    private Date    markTime;\n\n    /**\n     * 获取主键key\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.format(\"%d_%s\", indexTemplateId, labelId);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n\n    /**\n     * 获取主键key\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    public String getId() {\n        return getKey();\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateNotifyESPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateNotifyESPO extends BaseESPO {\n    int    logicTemplateId;\n\n    int    projectId;\n\n    String templateName;\n\n    String zeroDate;\n\n    int    rate;\n\n    int    notifyNu;\n\n    @Override\n    public String getKey() {\n        return logicTemplateId + \"#\" + zeroDate + \"#\" + rate;\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateStatsInfoPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 索引的基本统计信息\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateStatsInfoPO {\n    /**\n     * 模板id\n     */\n    private Long         templateId;\n    /**\n     * 模板名称\n     */\n    private String       templateName;\n    /**\n     * 索引健康分\n     */\n    private double       indexHealthDegree;\n    /**\n     * 索引存储容量\n     */\n    private double       store;\n    /**\n     * 索引qutoa\n     */\n    private double       qutoa;\n    /**\n     * 索引成本\n     */\n    private double       cost;\n    /**\n     * 索引昨日访问均量\n     */\n    private double       accessCountPreDay;\n    /**\n     * 索引文档数\n     */\n    private long         docNu;\n    /**\n     * 索引昨日峰值写入tps\n     */\n    private double       writeTps;\n    /**\n     * 索引对应的topic\n     */\n    private List<String> topics = new ArrayList<>();\n    /**\n     * 索引存储容量\n     */\n    private double       storeBytes;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateTypePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BasePO;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * \n * @author d06679\n * @date 2019-07-24\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateTypePO extends BasePO {\n\n    private Integer id;\n\n    private String  name;\n\n    private String  idField;\n\n    private Boolean source;\n\n    private String  routing;\n\n    private String  indexTemplateName;\n\n    private Integer indexTemplateId;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateValuePO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 索引标签bean\n *\n * @author d06679\n * @date 2017/10/9\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateValuePO extends BaseESPO {\n\n    /**\n     * 索引模板id\n     */\n    private Integer logicTemplateId;\n    /**\n     * 价值\n     */\n    private Integer value;\n    /**\n     * 访问量\n     */\n    private Long    accessCount;\n    /**\n     * 大小G\n     */\n    private Double  sizeG;\n    /**\n     * 逻辑集群\n     */\n    private String  logicCluster;\n\n    /**\n     * 获取主键key\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.valueOf(logicTemplateId);\n    }\n\n    @Override\n    public String getRoutingValue() {\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/po/template/TemplateValueRecordPO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.po.template;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.util.DateTimeUtil;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 索引标签bean\n *\n * @author d06679\n * @date 2017/10/9\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class TemplateValueRecordPO extends TemplateValuePO {\n\n    /**\n     * 统计时间\n     */\n    private Long timestamp;\n\n    /**\n     * 获取主键key\n     *\n     * @return\n     */\n    @JSONField(serialize = false)\n    @Override\n    public String getKey() {\n        return String.format(\"%d_%s\", getLogicTemplateId(), DateTimeUtil.formatTimestamp(timestamp));\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/BaseVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\nimport lombok.Data;\nimport lombok.ToString;\n\n/**\n * @author d06679\n * @date 2019/3/13\n */\n@ToString\n@Data\npublic class BaseVO implements Serializable {\n    private Date createTime;\n    private Date updateTime;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/README.md",
    "content": "vo中的bean是用于响应rest请求数据的bean\n命名规则: xxxVO\n必须继承基类:BaseVO\n\n\n同一个业务实体区分不用的使用场景:\nAppVO               用于运维控制台获取数据,包含全部字段属性\nAppGatewayVO        用于gateway获取app信息,包含基本信息和授权模板\nAppConsoleSampleVO  用于用户控制台获取app列表,只包含基础信息,且不包含密码\nAppConsoleVO        用于用户控制台app责任人获取app列表,只包含基础信息\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ClusterConnectionStatusWithTemplateVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterConnectionStatusWithTemplateEnum;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 该类用于表示集群连接的状态\n *\n * @author shizeying\n * @date 2022/08/12\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ClusterConnectionStatusWithTemplateVO {\n    private String cluster;\n    private String status;\n    private String desc;\n    \n    public ClusterConnectionStatusWithTemplateVO(String clusterPhy,\n            ClusterConnectionStatusWithTemplateEnum clusterConnectionStatusWithTemplateEnum) {\n        this.cluster=clusterPhy;\n        this.status = clusterConnectionStatusWithTemplateEnum.toString();\n        this.desc = clusterConnectionStatusWithTemplateEnum.getDesc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ClusterLogicTemplateIndexCountVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndicesClearDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateLogicAggregate;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName ClusterLogicTemplateIndexVO\n * @Author gyp\n * @Date 2022/5/31\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterLogicTemplateIndexCountVO {\n    @ApiModelProperty(\"模板列表数量\")\n    private Integer templateLogicAggregates;\n\n    @ApiModelProperty(\"索引列表\")\n    private Integer catIndexResults;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ClusterLogicTemplateIndexDetailDTO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * 模板和索引的详细信息\n * @author gyp\n * @Date 2022/5/31\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ClusterLogicTemplateIndexDetailDTO {\n    @ApiModelProperty(\"模板列表\")\n    private List<IndexTemplate>    templates;\n\n    @ApiModelProperty(\"索引列表\")\n    private List<IndexCatCellDTO>  catIndexResults;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ClusterLogicVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * 集群基本类\n *\n * @author wangshu\n * @date 2020/09/23\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"逻辑集群\")\npublic class ClusterLogicVO extends BaseVO implements Comparable<ClusterLogicVO> {\n\n    @ApiModelProperty(\"集群ID\")\n    private Long                         id;\n\n    @ApiModelProperty(\"集群名字\")\n    private String                       name;\n\n    @ApiModelProperty(\"数据中心\")\n    private String                       dataCenter;\n\n    /** @see ClusterResourceTypeEnum */\n    @ApiModelProperty(\"集群类型（1：公共；2：独立）\")\n    private Integer                      type;\n\n    @ApiModelProperty(\"所属应用ID\")\n    private Integer                      projectId;\n\n    @ApiModelProperty(\"所属应用名\")\n    private String                       projectName;\n\n    @ApiModelProperty(\"是否关联物理集群\")\n    private Boolean                      phyClusterAssociated;\n\n    @ApiModelProperty(\"关联物理集群列表\")\n    private List<String>                 associatedPhyClusterName;\n\n    @ApiModelProperty(\"数据节点数\")\n    private Integer                      dataNodeNum;\n\n    @ApiModelProperty(\"gateway地址\")\n    private String                       gatewayAddress;\n\n    \n\n    @ApiModelProperty(\"备注\")\n    private String                       memo;\n\n\n    @ApiModelProperty(\"服务等级\")\n    private Integer                      level;\n\n    @ApiModelProperty(\"配额\")\n    private Double                       quota;\n\n    @ApiModelProperty(\"权限记录ID\")\n    private Long                         authId;\n\n    /** @see ProjectClusterLogicAuthEnum */\n    @ApiModelProperty(\"权限,1:配置管理,2:访问,-1:无权限\")\n    private Integer                      authType;\n\n    @ApiModelProperty(\"权限,1:配置管理,2:访问,-1:无权限\")\n    private String                       permissions;\n\n    @ApiModelProperty(\"ES集群版本\")\n    private String                       esClusterVersion;\n\n    @ApiModelProperty(\"集群状态信息\")\n    private ConsoleClusterStatusVO       clusterStatus;\n\n    @ApiModelProperty(\"配置\")\n    private String                       configJson;\n\n    @ApiModelProperty(\"集群所开放的索引服务\")\n    private List<ESClusterTemplateSrvVO> esClusterTemplateSrvVOS;\n\n    @ApiModelProperty(\"集群角色信息\")\n    private List<ESClusterRoleVO>        esClusterRoleVOS;\n\n    @ApiModelProperty(\"集群健康状态\")\n    private Integer                      health;\n\n    @ApiModelProperty(\"磁盘使用率\")\n    private Double                       diskUsagePercent;\n\n    @ApiModelProperty(\"磁盘总量\")\n    private Long                         diskTotal;\n\n    @ApiModelProperty(\"磁盘使用量\")\n    private Long                         diskUsage;\n\n    @ApiModelProperty(\"分片数\")\n    private Long                         activeShardNum;\n\n    @Override\n    public int compareTo(ClusterLogicVO o) {\n        if (null == o) {\n            return -1;\n        }\n\n        return o.getId().intValue() - this.getId().intValue();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ClusterLogicVOWithProjects.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"逻辑集群关联的项目集合\")\npublic class ClusterLogicVOWithProjects extends BaseVO implements Comparable<ClusterLogicVOWithProjects>{\n\t@ApiModelProperty(\"集群ID\")\n    private Long                         id;\n\n    @ApiModelProperty(\"集群名字\")\n    private String                       name;\n\n    @ApiModelProperty(\"数据中心\")\n    private String                       dataCenter;\n\n    /** @see ClusterResourceTypeEnum */\n    @ApiModelProperty(\"集群类型（1：公共；2：独立）\")\n    private Integer                      type;\n\n  \n\n    @ApiModelProperty(\"是否关联物理集群\")\n    private Boolean                      phyClusterAssociated;\n\n    @ApiModelProperty(\"关联物理集群列表\")\n    private List<String> associatedPhyClusterName;\n\n    @ApiModelProperty(\"数据节点数\")\n    private Integer                      dataNodeNum;\n\n    @ApiModelProperty(\"gateway地址\")\n    private String                       gatewayAddress;\n\n    \n\n    @ApiModelProperty(\"备注\")\n    private String                       memo;\n\n\n    @ApiModelProperty(\"服务等级\")\n    private Integer                      level;\n\n    @ApiModelProperty(\"配额\")\n    private Double                       quota;\n\n    @ApiModelProperty(\"权限记录ID\")\n    private Long                         authId;\n\n    /** @see ProjectClusterLogicAuthEnum */\n    @ApiModelProperty(\"权限,1:配置管理,2:访问,-1:无权限\")\n    private Integer                      authType;\n\n    @ApiModelProperty(\"权限,1:配置管理,2:访问,-1:无权限\")\n    private String                       permissions;\n\n    @ApiModelProperty(\"ES集群版本\")\n    private String                       esClusterVersion;\n\n    @ApiModelProperty(\"集群状态信息\")\n    private ConsoleClusterStatusVO       clusterStatus;\n\n    @ApiModelProperty(\"配置\")\n    private String                       configJson;\n\n    @ApiModelProperty(\"集群所开放的索引服务\")\n    private List<ESClusterTemplateSrvVO> esClusterTemplateSrvVOS;\n\n    @ApiModelProperty(\"集群角色信息\")\n    private List<ESClusterRoleVO>        esClusterRoleVOS;\n\n    @ApiModelProperty(\"集群健康状态\")\n    private Integer                      health;\n\n    @ApiModelProperty(\"磁盘使用率\")\n    private Double                       diskUsagePercent;\n\n    @ApiModelProperty(\"磁盘总量\")\n    private Long                         diskTotal;\n\n    @ApiModelProperty(\"磁盘使用量\")\n    private Long                         diskUsage;\n\t@ApiModelProperty(\"项目名称列表\")\n\tprivate List<String> projectNameList;\n\n    @Override\n    public int compareTo(ClusterLogicVOWithProjects o) {\n        if (null == o) {\n            return -1;\n        }\n\n        return o.getId().intValue() - this.getId().intValue();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ClusterNodeInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 节点信息.\n *\n * @ClassName ClusterNodeInfoVO\n * @Author gyp\n * @Date 2022/10/21\n * @Version 1.0\n */\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"节点信息\")\npublic class ClusterNodeInfoVO {\n\n    @ApiModelProperty(\"节点名称\")\n    private String                                       nodeName;\n\n    @ApiModelProperty(\"节点类型,角色信息， 1data 2client 3master 4tribe\")\n    private Integer                                       nodeType;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ClusterPhyVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.google.common.collect.Lists;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/19\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"集群信息\")\npublic class ClusterPhyVO extends BaseVO implements Comparable<ClusterPhyVO> {\n\n    @ApiModelProperty(\"集群ID\")\n    private Integer                                      id;\n\n    @ApiModelProperty(\"集群名字\")\n    private String                                       cluster;\n\n    @ApiModelProperty(\"描述\")\n    private String                                       desc;\n\n    @ApiModelProperty(\"tcp地址-读\")\n    private String                                       readAddress;\n\n    @ApiModelProperty(\"tcp地址-写\")\n    private String                                       writeAddress;\n\n    @ApiModelProperty(\"http地址-读\")\n    private String                                       httpAddress;\n\n    @ApiModelProperty(\"http地址-写\")\n    private String                                       httpWriteAddress;\n\n    /** @see ESClusterTypeEnum */\n    @ApiModelProperty(\"集群类型(3 docker, 4 host)\")\n    private Integer                                      type;\n\n    @ApiModelProperty(\"集群展示用属性标签，如「集群所属资源类型」等等\")\n    private String                                       tags;\n\n    @ApiModelProperty(\"数据中心\")\n    private String                                       dataCenter;\n\n    @ApiModelProperty(\"单节点实例数 host物理集群必填\")\n    private Integer                                      pidCount;\n\n    @ApiModelProperty(\"机器规格  host物理集群必填\")\n    private String                                       machineSpec;\n\n    @ApiModelProperty(\"服务等级\")\n    private Integer                                      level;\n\n    @ApiModelProperty(\"es版本\")\n    private String                                       esVersion;\n\n    @ApiModelProperty(\"镜像地址\")\n    private String                                       imageName;\n\n    @ApiModelProperty(\"集群所开放的索引服务\")\n    private List<ESClusterTemplateSrvVO>                 esClusterTemplateSrvVOS;\n\n    @ApiModelProperty(\"集群角色信息\")\n    private List<ESClusterRoleVO>                        esClusterRoleVOS;\n\n    @ApiModelProperty(\"磁盘使用率\")\n    private Double                                       diskUsagePercent;\n\n    @ApiModelProperty(\"磁盘总量\")\n    private Long                                         diskTotal;\n\n    @ApiModelProperty(\"磁盘使用量\")\n    private Long                                         diskUsage;\n\n    @ApiModelProperty(\"集群密码\")\n    private String                                       password;\n\n    @ApiModelProperty(\"机房\")\n    private String                                       idc;\n\n    @ApiModelProperty(\"client运行模式（0：读写共享 1：读写分离）\")\n    private Integer                                      runMode;\n\n    @ApiModelProperty(\"指定用写client的action\")\n    private String                                       writeAction;\n\n    @ApiModelProperty(\"集群状态\")\n    private Integer                                      health;\n\n    @ApiModelProperty(\"活跃的分片数目\")\n    private Long                                         activeShardNum;\n\n    @ApiModelProperty(\"IaaS平台类型\")\n    private String                                       platformType;\n\n    /**\n     * @see ClusterResourceTypeEnum\n     */\n    @ApiModelProperty(\"集群资源类型(-1 未知 1 共享 2 独立 3 独享)\")\n    private Integer                                      resourceType;\n\n    @ApiModelProperty(\"gateway地址\")\n    private String                                       gatewayUrl;\n    @ApiModelProperty(\"是否支持 zeus:（扩缩容、升级、重启、配置变更）\")\n    private Boolean supportZeus = true;\n    @ApiModelProperty(\"逻辑集群与对应region的列表\")\n    private List<Tuple<ClusterLogicVOWithProjects, ClusterRegionVO>> logicClusterAndRegionList;\n    @ApiModelProperty(\"物理集群绑定的逻辑集群\")\n    private List<String> bindLogicCluster;\n\n    @ApiModelProperty(\"kibana外链地址\")\n    private String                    kibanaAddress;\n\n    @ApiModelProperty(\"cerebro外链地址\")\n    private String                    cerebroAddress;\n\n    @ApiModelProperty(\"代理地址\")\n    private String                    proxyAddress;\n\n    /**\n     * 添加逻辑集群\n     *\n     * @param clusterLogicVO 逻辑集群\n     * @param regionVO    region\n     */\n    public void addLogicCluster(ClusterLogicVOWithProjects clusterLogicVO, ClusterRegionVO regionVO) {\n        if (null == logicClusterAndRegionList) {\n            logicClusterAndRegionList = Lists.newArrayList();\n        }\n        if (clusterLogicVO != null || regionVO != null) {\n            Tuple<ClusterLogicVOWithProjects, ClusterRegionVO> tuple = new Tuple<>(clusterLogicVO, regionVO);\n            logicClusterAndRegionList.add(tuple);\n        }\n    }\n\n    @Override\n    public int compareTo(ClusterPhyVO o) {\n        if (null == o) {\n            return 0;\n        }\n\n        return o.getId().intValue() - this.getId().intValue();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ClusterPhyWithLogicClusterVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport lombok.Builder;\nimport lombok.Data;\n\n/**\n * 物理集群和逻辑集群对应关系\n *\n * @author shizeying\n * @date 2022/09/15\n */\n@Data\n@Builder\npublic class ClusterPhyWithLogicClusterVO {\n\tprivate String clusterPhy;\n\tprivate String clusterLogic;\n\tprivate Long   clusterLogicId;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ClusterRegionVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"集群Region信息\")\npublic class ClusterRegionVO extends BaseVO {\n\n    @ApiModelProperty(\"主键\")\n    private Long   id;\n\n    @ApiModelProperty(\"region 名称\")\n    private String name;\n\n    @ApiModelProperty(\"逻辑集群ID\")\n    private String logicClusterIds;\n\n    @ApiModelProperty(\"物理集群名称\")\n    private String clusterName;\n\n    @ApiModelProperty(\"配置项\")\n    private String config;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ClusterRegionWithNodeInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2022/5/26\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"带节点信息的集群Region实体\")\npublic class ClusterRegionWithNodeInfoVO extends ClusterRegionVO {\n    @ApiModelProperty(\"划分到region的节点名称, 用逗号分隔\")\n    private String nodeNames;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ConsoleClusterStatusVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"逻辑集群状态信息\")\npublic class ConsoleClusterStatusVO extends BaseVO {\n\n    @ApiModelProperty(\"逻辑集群名称\")\n    private String  name;\n\n    @ApiModelProperty(\"逻辑集群id\")\n    private Long    id;\n\n    @ApiModelProperty(\"逻辑集群状态(green/yellow/red)\")\n    private String  status;\n\n    @ApiModelProperty(\"集群docNu个数\")\n    private Integer docNu;\n\n    @ApiModelProperty(\"总的磁盘容量\")\n    private Double  totalDisk;\n\n    @ApiModelProperty(\"已使用的磁盘容量\")\n    private Double  usedDisk;\n\n    @ApiModelProperty(\"索引数量\")\n    private Long    indexNu;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ESClusterRoleHostVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * es集群节点信息,信息是同步自es集群\n * @author chengxiang\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"节点信息\")\npublic class ESClusterRoleHostVO extends BaseVO {\n\n    @ApiModelProperty(\"主键\")\n    private Long    id;\n\n    @ApiModelProperty(\"集群角色Id\")\n    private Long    roleClusterId;\n\n    @ApiModelProperty(\"主机名称\")\n    private String  hostname;\n\n    @ApiModelProperty(\"主机ip\")\n    private String  ip;\n\n    @ApiModelProperty(\"物理集群名称\")\n    private String  cluster;\n\n    @ApiModelProperty(\"逻辑集群名称\")\n    private String  clusterLogicNames;\n\n    @ApiModelProperty(\"端口\")\n    private String  port;\n\n    /**\n     * 1data   2client    3master   4tribe\n     * @see ESClusterNodeRoleEnum\n     */\n    @ApiModelProperty(\"角色(1data   2client    3master   4tribe)\")\n    private Integer role;\n\n    @ApiModelProperty(\"状态（1 在线    2 离线   3 故障）\")\n    private Integer status;\n\n    @ApiModelProperty(\"rack\")\n    @Deprecated\n    private String  rack;\n\n    @ApiModelProperty(\"实例规格\")\n    private String  machineSpec;\n\n    @ApiModelProperty(\"实例名称\")\n    private String  nodeSet;\n\n    @ApiModelProperty(\"RegionId\")\n    private Integer regionId;\n\n    @ApiModelProperty(\"逻辑划分\")\n    private String  logicDepart;\n\n    @ApiModelProperty(\"attributes, 逗号分隔 key1:value1,key2:value2\")\n    private String  attributes;\n\n    @ApiModelProperty(\"regionName\")\n    private String  regionName;\n\n    @ApiModelProperty(\"磁盘使用率\")\n    private Double  diskUsagePercent;\n\n    @ApiModelProperty(\"磁盘总量(byte)\")\n    private Long    diskTotal;\n\n    @ApiModelProperty(\"磁盘使用大小(byte)\")\n    private Long    diskUsage;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ESClusterRoleHostWithRegionInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2022/5/25\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"带region信息的节点实体\")\npublic class ESClusterRoleHostWithRegionInfoVO extends ESClusterRoleHostVO {\n    @ApiModelProperty(\"Region名称\")\n    private String regionName;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ESClusterRoleVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * ES集群表对应各角色主机列表\n * @author chengxiang\n * @date 2022/5/9\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"ES角色集群信息\")\npublic class ESClusterRoleVO extends BaseVO {\n    private static final long         serialVersionUID = 1L;\n\n    private Long                      id;\n\n    @ApiModelProperty(\"集群ID\")\n    private Long                      elasticClusterId;\n\n    @ApiModelProperty(\"role集群名称\")\n    private String                    roleClusterName;\n\n    /**\n     *  集群角色(masternode/datanode/clientnode)\n     * @see ESClusterNodeRoleEnum\n     */\n    @ApiModelProperty(\"集群角色(masternode/datanode/clientnode)\")\n    private String                    role;\n\n    @ApiModelProperty(\"pod数量\")\n    private Integer                   podNumber;\n\n    @ApiModelProperty(\"单机实例数\")\n    private Integer                   pidCount;\n\n    @ApiModelProperty(\"机器规格\")\n    private String                    machineSpec;\n\n    @ApiModelProperty(\"角色名下角色列表\")\n    private List<ESClusterRoleHostVO> esClusterRoleHostVO;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ESClusterTemplateSrvVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * es集群索引服务信息\n * @author zhaoqingrong\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"es集群索引服务信息\")\npublic class ESClusterTemplateSrvVO extends BaseVO {\n    private static final long serialVersionUID = 1905122041950251207L;\n\n    @ApiModelProperty(\"索引服务id\")\n    private Integer           serviceId;\n\n    @ApiModelProperty(\"索引服务名称\")\n    private String            serviceName;\n\n    @ApiModelProperty(\"索引服务所需的最低es版本号\")\n    private String            esVersion;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/PluginVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"插件信息\")\npublic class PluginVO extends BaseVO {\n    @ApiModelProperty(\"ID主键自增\")\n    private Long    id;\n\n    @ApiModelProperty(\"插件名\")\n    private String  name;\n\n    @ApiModelProperty(\"插件版本\")\n    private String  version;\n\n    @ApiModelProperty(\"插件存储地址\")\n    private String  url;\n\n    @ApiModelProperty(\"插件文件md5\")\n    private String  md5;\n\n    @ApiModelProperty(\"插件描述\")\n    private String  desc;\n\n    @ApiModelProperty(\"插件创建人\")\n    private String  creator;\n\n    @ApiModelProperty(\"上传插件类型: 0 系统默认插件, 1 ES能力插件, 2 平台能力插件\")\n    private Integer pDefault;\n\n    @ApiModelProperty(\"是否安装: true 是, false 否\")\n    private Boolean installed;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/ThirdPartClusterVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\nimport lombok.AllArgsConstructor;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n/**\n * @author d06679\n * @date 2019/3/19\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"物理集群信息\")\npublic class ThirdPartClusterVO extends BaseVO {\n\n    @ApiModelProperty(\"集群ID\")\n    private Integer              id;\n\n    @ApiModelProperty(\"集群名字\")\n    private String               cluster;\n\n    @ApiModelProperty(\"描述\")\n    private String               desc;\n\n    @ApiModelProperty(\"tcp地址-读\")\n    private String               readAddress;\n\n    @ApiModelProperty(\"tcp地址-写\")\n    private String               writeAddress;\n\n    @ApiModelProperty(\"http地址-读\")\n    private String               httpAddress;\n\n    @ApiModelProperty(\"http地址-写\")\n    private String               httpWriteAddress;\n\n    /**\n     * 集群类型\n     * @see ESClusterTypeEnum\n     */\n    @ApiModelProperty(\"集群类型（0:数据集群；1:trib集群）\")\n    private Integer              type;\n\n    @ApiModelProperty(\"数据中心\")\n    private String               dataCenter;\n\n    @ApiModelProperty(\"机房\")\n    private String               idc;\n\n    @ApiModelProperty(\"服务等级\")\n    private Integer              level;\n\n    @ApiModelProperty(\"es版本\")\n    private String               esVersion;\n\n    @ApiModelProperty(\"集群密码\")\n    private String               password;\n\n    @ApiModelProperty(\"集群插件\")\n    private Set<String>          plugins;\n\n    @ApiModelProperty(\"tcp地址-读-map\")\n    private Map<String, Integer> readAddressMap;\n\n    @ApiModelProperty(\"tcp地址-写-map\")\n    private Map<String, Integer> writeAddressMap;\n\n    @ApiModelProperty(\"http地址-读-map\")\n    private Map<String, Integer> httpAddressMap;\n\n    @ApiModelProperty(\"client运行模式（0：读写共享 1：读写分离）\")\n    private Integer              runMode;\n\n    @ApiModelProperty(\"指定用写client的action\")\n    private String               writeAction;\n\n    public void setReadAddress(String readAddress) {\n        this.readAddress = readAddress;\n        readAddressMap = toAddressMap(readAddress);\n    }\n\n    public void setWriteAddress(String writeAddress) {\n        this.writeAddress = writeAddress;\n        writeAddressMap = toAddressMap(writeAddress);\n    }\n\n    public void setHttpAddress(String httpAddress) {\n        this.httpAddress = httpAddress;\n        httpAddressMap = toAddressMap(httpAddress);\n    }\n\n    private Map<String, Integer> toAddressMap(String addresses) {\n        if (StringUtils.isBlank(addresses)) {\n            return null;\n        }\n        String[] addressList = addresses.split(\",\");\n        Map<String, Integer> addressMap = new HashMap<>(16);\n        for (String address : addressList) {\n            try {\n                String[] hostAndPort = address.trim().split(\":\");\n                addressMap.put(hostAndPort[0], Integer.valueOf(hostAndPort[1]));\n            } catch (Exception e) {\n                return addressMap;\n            }\n        }\n        return addressMap;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/quickcommand/IndicesDistributionVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * indices分布.\n *\n * @ClassName indicesVO\n * @Author gyp\n * @Date 2022/6/1\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class IndicesDistributionVO {\n    @ApiModelProperty(\"健康检查\")\n    private String health;\n    @ApiModelProperty(\"状态\")\n    private String status;\n    @ApiModelProperty(\"索引名\")\n    private String index;\n    @ApiModelProperty(\"主分片数量\")\n    private String pri;\n    @ApiModelProperty(\"副分片数量\")\n    private String rep;\n    @ApiModelProperty(\"文档数量\")\n    private String docsCount;\n    @ApiModelProperty(\"文档删数量\")\n    private String docsDeleted;\n    @ApiModelProperty(\"存储主副本和副本的大小\")\n    private Long storeSize;\n    @ApiModelProperty(\"主分片大小\")\n    private Long priStoreSize;\n    @ApiModelProperty(\"uuid\")\n    private String uuid;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/quickcommand/NodeStateVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.math.BigDecimal;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName indicesVO\n * @Author gyp\n * @Date 2022/6/1\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class NodeStateVO {\n    @ApiModelProperty(\"节点名称\")\n    private String  nodeName;\n    @ApiModelProperty(\"segments大小\")\n    private Long    segmentsMemory;\n    @ApiModelProperty(\"cpu占用\")\n    private Integer osCpu;\n    @ApiModelProperty(\"load_average_1m\")\n    private double  loadAverage1m;\n    @ApiModelProperty(\"load_average_5m\")\n    private double  loadAverage5m;\n    @ApiModelProperty(\"load_average_15m\")\n    private double  loadAverage15m;\n    @ApiModelProperty(\"jvm堆内存使用率\")\n    private long    jvmHeapUsedPercent;\n    @ApiModelProperty(\"线程数量\")\n    private long    threadsCount;\n    @ApiModelProperty(\"currentOpen\")\n    private long    currentOpen;\n    @ApiModelProperty(\"线程池写活跃数\")\n    private long    threadPoolWriteActive;\n    @ApiModelProperty(\"线程池写队列数\")\n    private long    threadPoolWriteQueue;\n    @ApiModelProperty(\"线程池写拒绝数\")\n    private long    threadPoolWriteReject;\n    @ApiModelProperty(\"线程池搜索活跃数\")\n    private long    threadPoolSearchActive;\n    @ApiModelProperty(\"线程池搜索队列数\")\n    private long    threadPoolSearchQueue;\n    @ApiModelProperty(\"线程池搜索拒绝数\")\n    private long    threadPoolSearchReject;\n    @ApiModelProperty(\"线程池管理活跃数\")\n    private long    threadPoolManagementActive;\n    @ApiModelProperty(\"线程池管理队列数\")\n    private long    threadPoolManagementQueue;\n    @ApiModelProperty(\"线程池管理拒绝数\")\n    private long    threadPoolManagementReject;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/quickcommand/PendingTaskAnalysisVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.PendingTaskVO;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * pending task分析.\n *\n * @ClassName PendingTask\n * @Author gyp\n * @Date 2022/6/7\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class PendingTaskAnalysisVO extends PendingTaskVO {\n    @ApiModelProperty(\"节点名称\")\n    private String timeInQueueMillis;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/quickcommand/ShardAssignmenNodeVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName ShardAssignmenNodeVO\n * @Author gyp\n * @Date 2022/6/7\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ShardAssignmenNodeVO {\n    @ApiModelProperty(\"节点决策\")\n    private String nodeDecide;\n    @ApiModelProperty(\"节点名称\")\n    private String nodeName;\n    @ApiModelProperty(\"解释\")\n    private String explanation;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/quickcommand/ShardAssignmentDescriptionVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName ShardAssignmentDescriptionVO\n * @Author gyp\n * @Date 2022/6/7\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ShardAssignmentDescriptionVO {\n    @ApiModelProperty(\"是否为主\")\n    private boolean                    primary;\n    @ApiModelProperty(\"索引\")\n    private String                     index;\n    @ApiModelProperty(\"分片\")\n    private Integer                    shard;\n    @ApiModelProperty(\"当前状态\")\n    private String                     currentState;\n\n    @ApiModelProperty(\"节点信息\")\n    private List<ShardAssignmenNodeVO> decisions;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/quickcommand/ShardDistributionVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName ShardDistributionVO\n * @Author gyp\n * @Date 2022/6/7\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ShardDistributionVO {\n    @ApiModelProperty(\"主副\")\n    private String prirep;\n    @ApiModelProperty(\"节点名称\")\n    private String node;\n    @ApiModelProperty(\"文档\")\n    private String docs;\n    @ApiModelProperty(\"ip\")\n    private String ip;\n    @ApiModelProperty(\"索引\")\n    private String index;\n    @ApiModelProperty(\"分片\")\n    private String shard;\n    @ApiModelProperty(\"state\")\n    private String state;\n    @ApiModelProperty(\"store大小\")\n    private Long store;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/cluster/quickcommand/TaskMissionAnalysisVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * task任务分析.\n *\n * @ClassName TaskMissionAnalysisVO\n * @Author gyp\n * @Date 2022/6/7\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TaskMissionAnalysisVO {\n    @ApiModelProperty(\"节点名称\")\n    private String  node;\n    @ApiModelProperty(\"活动\")\n    private String  action;\n    @ApiModelProperty(\"描述\")\n    private String  description;\n    @ApiModelProperty(\"开始时间\")\n    private Long    startTimeInMillis;\n    @ApiModelProperty(\"运行时间\")\n    private Integer runningTimeInNanos;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/config/AriusConfigInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.config;\n\nimport java.util.Date;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"配置信息\")\npublic class AriusConfigInfoVO extends BaseVO {\n\n    @ApiModelProperty(\"配置ID\")\n    private Integer id;\n\n    @ApiModelProperty(\"配置组\")\n    private String  valueGroup;\n\n    @ApiModelProperty(\"配置名称\")\n    private String  valueName;\n\n    @ApiModelProperty(\"值\")\n    private String  value;\n\n    /**\n     * 配置项维度  1 集群   2 模板\n     */\n    @ApiModelProperty(\"维度\")\n    private Integer dimension;\n\n    @ApiModelProperty(\"状态(1 正常；2 禁用；-1 删除)\")\n    private Integer status;\n\n    @ApiModelProperty(\"备注\")\n    private String  memo;\n\n    @ApiModelProperty(\"创建时间\")\n    private Date    createTime;\n\n    @ApiModelProperty(\"修改时间\")\n    private Date    updateTime;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/config/ThirdpartConfigVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.config;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"配置信息\")\npublic class ThirdpartConfigVO extends BaseVO {\n\n    @ApiModelProperty(\"配置ID\")\n    private Integer id;\n\n    @ApiModelProperty(\"配置组\")\n    private String  valueGroup;\n\n    @ApiModelProperty(\"配置名称\")\n    private String  valueName;\n\n    @ApiModelProperty(\"值\")\n    private String  value;\n\n    @ApiModelProperty(\"状态(1 正常；2 禁用；-1 删除)\")\n    private Integer status;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/ecm/ESClusterNodeSepcVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * es集群节点的套餐\n * @author d06679\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"集群节点规格信息\")\npublic class ESClusterNodeSepcVO extends BaseDTO {\n\n    @ApiModelProperty(\"主键\")\n    private int    id;\n\n    @ApiModelProperty(\"角色\")\n    private String role;\n\n    @ApiModelProperty(\"规格\")\n    private String spec;\n\n    @ApiModelProperty(\"生效标识\")\n    private int    delete_flag;\n\n    @ApiModelProperty(\"创建时间\")\n    private String Create_time;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/ecm/ESConfigVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2020-12-30\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"ES集群配置VO\")\npublic class ESConfigVO extends BaseVO {\n\n    @ApiModelProperty(\"主键\")\n    private Long   id;\n\n    @ApiModelProperty(\"集群id\")\n    private Long   clusterId;\n\n    @ApiModelProperty(\"配置文件名称\")\n    private String typeName;\n\n    @ApiModelProperty(\"组件名称\")\n    private String enginName;\n\n    @ApiModelProperty(\"配置内容\")\n    private String configData;\n\n    @ApiModelProperty(\"配置描述\")\n    private String desc;\n\n    @ApiModelProperty(\"配置tag\")\n    private String versionTag;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/ecm/EcmTaskBasicVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"工单任务基本情况\")\npublic class EcmTaskBasicVO extends BaseVO {\n    private static final long serialVersionUID = 1L;\n\n    @ApiModelProperty(\"ID\")\n    private Long              id;\n\n    @ApiModelProperty(\"标题\")\n    private String            title;\n\n    @ApiModelProperty(\"工单ID\")\n    private Long              workOrderId;\n\n    @ApiModelProperty(\"es版本\")\n    private String            esVersion;\n\n    @ApiModelProperty(\"镜像名\")\n    private String            imageName;\n\n    @ApiModelProperty(\"集群名称\")\n    private String            clusterName;\n\n    @ApiModelProperty(\"集群描述\")\n    private String            desc;\n\n    @ApiModelProperty(\"服务节点\")\n    private String            nsTree;\n\n    /**\n     * @deprecated\n     */\n    @Deprecated\n    @ApiModelProperty(\"机房\")\n    private String            idc;\n\n    @ApiModelProperty(\"成本部门\")\n    private String            dept;\n\n    @ApiModelProperty(\"集群节点角色\")\n    private String            clusterNodeRole;\n\n    @ApiModelProperty(\"状态\")\n    private String            status;\n\n    @ApiModelProperty(\"类型  docker容器云 3 /host 物理机 4\")\n    private Integer           type;\n\n    @ApiModelProperty(\"类型 1 集群新增  2 集群扩容 3 集群缩容 4 集群重启 5 集群升级\")\n    private Integer           orderType;\n\n    @ApiModelProperty(\"创建人\")\n    private String            creator;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/ecm/EcmTaskDetailVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm;\n\nimport io.swagger.annotations.ApiModel;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmTaskDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(description = \"ECM任务执行详情\")\npublic class EcmTaskDetailVO extends BaseVO {\n\n    @ApiModelProperty(\"执行进度\")\n    private Long                             percent;\n\n    @ApiModelProperty(\"成功的节点个数\")\n    private Long                             success;\n\n    @ApiModelProperty(\"失败的节点个数\")\n    private Long                             failed;\n\n    @ApiModelProperty(\"执行中的节点个数\")\n    private Long                             creating;\n\n    @ApiModelProperty(\"等待中的节点个数\")\n    private Long                             waiting;\n\n    @ApiModelProperty(\"忽略的节点个数\")\n    private Long                             ignore;\n\n    @ApiModelProperty(\"取消的节点个数\")\n    private Long                             cancel;\n\n    @ApiModelProperty(\"节点总个数\")\n    private Long                             sum;\n\n    @ApiModelProperty(\"任务状态\")\n    private String                           status;\n\n    @ApiModelProperty(\"工单类型  1 集群新增  2 集群扩容 3 集群缩容 4 集群重启 5 集群升级\")\n    private Integer                          orderType;\n\n    @ApiModelProperty(\"各角色任务详情<角色名称, 详情>\")\n    private Map<String, List<EcmTaskDetail>> roleNameTaskDetailMap;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/ecm/EcmTaskVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"ECM任务详情\")\npublic class EcmTaskVO extends BaseVO {\n\n    private static final long serialVersionUID = 1L;\n\n    @ApiModelProperty(\"ID\")\n    private Long              id;\n\n    @ApiModelProperty(\"标题\")\n    private String            title;\n\n    @ApiModelProperty(\"工单ID\")\n    private Long              workOrderId;\n\n    @ApiModelProperty(\"es版本\")\n    private String            esVersion;\n\n    @ApiModelProperty(\"镜像名\")\n    private String            imageName;\n\n    @ApiModelProperty(\"物理集群ID\")\n    private Long              physicClusterId;\n\n    @ApiModelProperty(\"集群节点角色 执行顺序\")\n    private String            clusterNodeRole;\n\n    @ApiModelProperty(\"状态\")\n    private String            status;\n\n    @ApiModelProperty(\"类型  docker容器云 3 /host 物理机 4\")\n    private Integer           type;\n\n    @ApiModelProperty(\"类型 1 集群新增  2 集群扩容 3 集群缩容 4 集群重启 5 集群升级\")\n    private Integer           orderType;\n\n    @ApiModelProperty(\"创建人\")\n    private String            creator;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/espackage/ESPackageVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.espackage;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Date;\n\n/**\n * @author lyn\n * @date 2021-01-12\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"ES集群安装包VO\")\npublic class ESPackageVO extends BaseVO {\n\n    @ApiModelProperty(\"主键\")\n    private Long    id;\n\n    @ApiModelProperty(\"镜像地址或包地址\")\n    private String  url;\n\n    @ApiModelProperty(\"版本标识\")\n    private String  esVersion;\n\n    @ApiModelProperty(\"包创建人\")\n    private String  creator;\n\n    @ApiModelProperty(\"是否为发布版本\")\n    private Boolean release;\n\n    @ApiModelProperty(\"类型(3 docker/4 host)\")\n    private Integer manifest;\n\n    @ApiModelProperty(\"备注\")\n    private String  desc;\n\n    @ApiModelProperty(\"标记删除\")\n    private Boolean deleteFlag;\n\n    @ApiModelProperty(\"创建时间\")\n    private Date    createTime;\n\n    @ApiModelProperty(\"类型(1 滴滴内部版本/2 开源版本)\")\n    private Integer packageType;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/gateway/GatewayClusterNodeVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.gateway;\n\nimport java.util.Date;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"节点信息\")\npublic class GatewayClusterNodeVO extends BaseVO {\n\n    @ApiModelProperty(\"节点ID\")\n    private Integer id;\n\n    @ApiModelProperty(\"集群名称\")\n    private String  clusterName;\n\n    @ApiModelProperty(\"主机名\")\n    private String  hostName;\n\n    @ApiModelProperty(\"端口\")\n    private Integer port;\n\n    @ApiModelProperty(\"上报时间\")\n    private Date    heartbeatTime;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/indices/IndexCatCellVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.indices;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/30\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"IndexCatCellVO\", description = \"索引详情\")\npublic class IndexCatCellVO extends BaseVO {\n    @ApiModelProperty(\"主键\")\n    private String       key;\n\n    @ApiModelProperty(\"物理集群名称\")\n    private String       cluster;\n\n    @ApiModelProperty(\"逻辑集群名称\")\n    private String       clusterLogic;\n\n    @ApiModelProperty(\"逻辑集群ID\")\n    private Long         resourceId;\n\n    @ApiModelProperty(\"projectId\")\n    private Integer      projectId;\n\n    @ApiModelProperty(\"分区健康\")\n    private String       health;\n\n    @ApiModelProperty(\"分区状态\")\n    private String       status;\n\n    @ApiModelProperty(\"索引名字\")\n    private String       index;\n\n    @ApiModelProperty(\"分区shard个数\")\n    private Long         pri;\n\n    @ApiModelProperty(\"分区副本个数\")\n    private Long         rep;\n\n    @ApiModelProperty(\"分区文档个数\")\n    private Long         docsCount;\n\n    @ApiModelProperty(\"分区文档删除个数\")\n    private Long         docsDeleted;\n\n    @ApiModelProperty(\"分区主分片存储大小\")\n    private String       storeSize;\n\n    @ApiModelProperty(\"分区存储大小\")\n    private String       priStoreSize;\n\n    @ApiModelProperty(\"可读标志位\")\n    private Boolean      readFlag;\n\n    @ApiModelProperty(\"可写标志位\")\n    private Boolean      writeFlag;\n\n    @ApiModelProperty(\"segment数\")\n    private Long         totalSegmentCount;\n\n    @ApiModelProperty(\"模板ID\")\n    private Integer      templateId;\n\n    @ApiModelProperty(\"通过平台索引创建标识 true 通过平台创建，false不是通过平台创建\")\n    private Boolean      platformCreateFlag;\n\n    @ApiModelProperty(\"别名\")\n    private List<String> aliases;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/indices/IndexCatCellWithTemplateVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.indices;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 关联模板的索引信息\n *\n * @author shizeying\n * @date 2022/08/10\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"IndexCatCellWithTemplateVO\", description = \"关联模板的索引信息\")\npublic class IndexCatCellWithTemplateVO extends BaseVO {\n    \n\n    @ApiModelProperty(\"索引名字\")\n    private String       index;\n\n\n    @ApiModelProperty(\"分区存储大小\")\n    private String       priStoreSize;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/indices/IndexMappingVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.indices;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.Field;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/28\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"IndexMappingVO\", description = \"索引mapping信息\")\npublic class IndexMappingVO extends BaseVO {\n\n    @ApiModelProperty(\"索引名称\")\n    private String      indexName;\n\n    @ApiModelProperty(\"索引mapping列表信息\")\n    private List<Field> fields;\n\n    @ApiModelProperty(\"索引mapping信息\")\n    private String      mappings;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/indices/IndexSettingVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.indices;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/28\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"IndexSettingVO\", description = \"索引setting信息\")\npublic class IndexSettingVO extends BaseVO {\n    @ApiModelProperty(\"索引名称\")\n    private String     indexName;\n\n    @ApiModelProperty(\"配置信息（json格式）\")\n    private JSONObject properties;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/indices/IndexShardInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.indices;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021/09/29\n **/\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引shard分配信息\")\npublic class IndexShardInfoVO extends BaseVO {\n    @ApiModelProperty(\"索引名称\")\n    private String  index;\n\n    @ApiModelProperty(\"shard序号\")\n    private Integer shard;\n\n    @ApiModelProperty(\"shard状态\")\n    private String  state;\n\n    @ApiModelProperty(\"shard文档数\")\n    private Long    docs;\n\n    @ApiModelProperty(\"shard存储空间 单位: kb,gb,mb\")\n    private String  store;\n\n    @ApiModelProperty(\"shard存储空间 单位byte\")\n    private Long    storeInByte;\n\n    @ApiModelProperty(\"shard所在节点ip\")\n    private String  ip;\n\n    @ApiModelProperty(\"shard所在节点实例名称\")\n    private String  node;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/MetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics;\n\nimport java.io.Serializable;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@ApiModel(\"指标信息\")\npublic abstract class MetricsVO implements Serializable {\n\n    @ApiModelProperty(\"当前时刻\")\n    private String currentTime;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/dictionary/MetricsDictionaryVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.dictionary;\n\nimport io.swagger.annotations.ApiModel;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName MetricsDictionaryVO\n * @Author gyp\n * @Date 2022/9/28\n * @Version 1.0\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"指标字典信息\")\npublic class MetricsDictionaryVO {\n    /**\n     * id自增\n     */\n    private Integer id;\n\n    /**\n     * 指标分类\n     */\n    private String type;\n    /**\n     * metric\n     */\n    private String metricType;\n\n    /**\n     * 指标名称\n     */\n    private String  name;\n\n    /**\n     * 指标价值\n     */\n    private String  price;\n\n    /**\n     * 计算间隔\n     */\n    private String interval;\n\n    /**\n     * 当前计算逻辑\n     */\n    private String currentCalLogic;\n    /**\n     * 是否黄金指标\n     */\n    private Integer isGold;\n    /**\n     * 单位\n     */\n    private String unit;\n    /**\n     * 交互形式\n     */\n    private String interactiveForm;\n    /**\n     * 告警指标\n     */\n    private Integer isWarning;\n    /**\n     * 指标来源\n     */\n    private String source;\n    /**\n     * 指标标签\n     */\n    private String tags;\n    /**\n     * 模块\n     */\n    private String model;\n    /**\n     * 阈值配置\n     */\n    private Integer isThreshold;\n    /**\n     * 阈值详情\n     */\n    private String threshold;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/list/MetricListContentVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.list;\n\nimport java.io.Serializable;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"列表类型的指标类\")\npublic class MetricListContentVO implements Serializable {\n    @ApiModelProperty(\"物理集群名称\")\n    private String clusterPhyName;\n\n    @ApiModelProperty(\"名称: node Name / index name /template name\")\n    private String name;\n\n    @ApiModelProperty(\"指标值, 某些指标项需要展示指标值, 可能为百分比, 考虑客户端做适配\")\n    private Double value;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/list/MetricListVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.list;\n\nimport java.io.Serializable;\nimport java.util.List;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"列表类型的指标类\")\npublic class MetricListVO implements Serializable {\n    @ApiModelProperty(\"当前时间\")\n    private Long                      currentTime;\n\n    @ApiModelProperty(\"指标类型\")\n    private String                    type;\n\n    @ApiModelProperty(\"具体指标信息\")\n    private List<MetricListContentVO> metricListContents;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/BigIndexMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"大索引, 大于10亿文档数的索引\")\npublic class BigIndexMetricsVO implements Serializable {\n\n    @ApiModelProperty(\"索引名称\")\n    private String                  indexName;\n\n    @ApiModelProperty(\"归属节点信息\")\n    private List<IndexBelongNodeVO> belongNodeInfo;\n\n    @ApiModelProperty(\"文档数\")\n    private Long                 docsCount;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/BigShardMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport java.io.Serializable;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"大shard\")\npublic class BigShardMetricsVO implements Serializable {\n\n    @ApiModelProperty(\"shard标识\")\n    private Long   shard;\n\n    @ApiModelProperty(\"归属索引\")\n    private String index;\n\n    @ApiModelProperty(\"主/备\")\n    private String prirep;\n\n    @ApiModelProperty(\"所属节点Ip\")\n    private String ip;\n\n    @ApiModelProperty(\"所属节点名称\")\n    private String node;\n\n    @ApiModelProperty(\"容量\")\n    private String store;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/CpuLoadFor15MinMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.percentiles.ESPercentileMetricsVO;\nimport io.swagger.annotations.ApiModel;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@ApiModel(\"CPU15分钟负载指标信息\")\npublic class CpuLoadFor15MinMetricsVO extends ESPercentileMetricsVO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/CpuLoadFor1MinMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.percentiles.ESPercentileMetricsVO;\nimport io.swagger.annotations.ApiModel;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@ApiModel(\"CPU1分钟负载指标信息\")\npublic class CpuLoadFor1MinMetricsVO extends ESPercentileMetricsVO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/CpuLoadFor5MinMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.percentiles.ESPercentileMetricsVO;\nimport io.swagger.annotations.ApiModel;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@ApiModel(\"CPU5分钟负载指标信息\")\npublic class CpuLoadFor5MinMetricsVO extends ESPercentileMetricsVO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/CpuUsageMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.percentiles.ESPercentileMetricsVO;\nimport io.swagger.annotations.ApiModel;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@ApiModel(\"CPU使用率指标信息\")\npublic class CpuUsageMetricsVO extends ESPercentileMetricsVO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/DiskInfoMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"磁盘使用指标信息\")\npublic class DiskInfoMetricsVO extends ESAggMetricsVO {\n\n    @ApiModelProperty(\"集群总容量, 单位G\")\n    private Double totalStoreSize;\n\n    @ApiModelProperty(\"集群已使用容量, 单位G\")\n    private Double storeSize;\n\n    @ApiModelProperty(\"集群空余容量, 单位G\")\n    private Double freeStoreSize;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/DiskUsageMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.percentiles.ESPercentileMetricsVO;\nimport io.swagger.annotations.ApiModel;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@ApiModel(\"集群磁盘使用率指标信息\")\npublic class DiskUsageMetricsVO extends ESPercentileMetricsVO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/ESAggMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport java.io.Serializable;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-05\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"ES聚合指标\")\npublic class ESAggMetricsVO implements Serializable, Comparable<ESAggMetricsVO> {\n    @ApiModelProperty(\"时间戳\")\n    private Long timeStamp;\n\n    @Override\n    public int compareTo(ESAggMetricsVO o) {\n        if (null == o) {\n            return 0;\n        }\n\n        return this.getTimeStamp().intValue() - o.getTimeStamp().intValue();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/ESClusterOverviewMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.MetricsVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 2021-07-30\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"物理集群指标总览信息\")\npublic class ESClusterOverviewMetricsVO extends MetricsVO {\n\n    @ApiModelProperty(\"集群名称，all则表示全集群信息\")\n    private String                                   clusterName;\n\n    @ApiModelProperty(\"是否是物理集群 1：是；0：不是\")\n    private Integer                                  physicCluster;\n\n    @ApiModelProperty(\"数据中心\")\n    private String                                   dataCenter;\n\n    /*****************************************1.基础信息********************************************/\n\n    @ApiModelProperty(\"物理集群基础指标信息\")\n    private ESClusterPhyBasicMetricsVO               basic;\n\n    /*****************************************2.cpu 相关********************************************/\n\n    @ApiModelProperty(\"CPU使用率指标信息\")\n    private List<CpuUsageMetricsVO>                  cpuUsage;\n\n    @ApiModelProperty(\"CPU1分钟负载指标信息\")\n    private List<CpuLoadFor1MinMetricsVO>            cpuLoad1M;\n\n    @ApiModelProperty(\"CPU5分钟负载指标信息\")\n    private List<CpuLoadFor5MinMetricsVO>            cpuLoad5M;\n\n    @ApiModelProperty(\"CPU15分钟负载指标信息\")\n    private List<CpuLoadFor15MinMetricsVO>           cpuLoad15M;\n\n    /******************************************3.磁盘信息********************************************/\n\n    @ApiModelProperty(\"集群磁盘使用率指标信息\")\n    private List<DiskUsageMetricsVO>                 diskUsage;\n\n    @ApiModelProperty(\"磁盘使用指标信息\")\n    private List<DiskInfoMetricsVO>                  diskInfo;\n\n    /*************************************4.网络流量信息(单位 MB)***************************************/\n\n    @ApiModelProperty(\"每秒接受流量\")\n    private List<RecvTransMetricsVO>                 recvTransSize;\n\n    @ApiModelProperty(\"每秒发送流量\")\n    private List<SendTransMetricsVO>                 sendTransSize;\n\n    /****************************************5.shard对比信息******************************************/\n\n    @ApiModelProperty(\"shard数量(总数, 未分配Shard)\")\n    private List<ShardInfoMetricsVO>                 shardNu;\n\n    @ApiModelProperty(\"正在迁移shard列表\")\n    private List<MovingShardMetricsVO>               movingShards;\n\n    @ApiModelProperty(\"未分配的shard列表\")\n    private List<UnAssignShardMetricsVO>               unAssignShards;\n\n    @ApiModelProperty(\"大shard列表\")\n    private List<BigShardMetricsVO>                  bigShards;\n\n    @ApiModelProperty(\"大shard阈值，单位g\")\n    private Double                                   bigShardThreshold;\n\n    /******************************************6.节点信息******************************************/\n\n    @ApiModelProperty(\"大于75%磁盘利用率节点列表\")\n    private List<NodeInfoForDiskUsageGte75PercentVO> nodesForDiskUsageGte75Percent;\n\n    @ApiModelProperty(\"无效节点的Ip列表\")\n    private List<ClusterRoleHost>                             invalidNodes;\n\n    /****************************************7.进程任务信息******************************************/\n\n    @ApiModelProperty(\"Pending任务列表\")\n    private List<PendingTaskVO>                      pendingTasks;\n\n    /*****************************************8.read/write 单位:/s******************************************/\n\n    @ApiModelProperty(\"查询QPS\")\n    private List<ReadQPSMetricsVO>                   readTps;\n\n    @ApiModelProperty(\"写入TPS\")\n    private List<WriteTPSMetricsVO>                  writeTps;\n\n    @ApiModelProperty(\"查询延时\")\n    private List<SearchLatencyMetricsVO>             searchLatency;\n\n    @ApiModelProperty(\"写入延时\")\n    private List<IndexingLatencyMetricsVO>           indexingLatency;\n\n    @ApiModelProperty(\"当前执行的task耗时\")\n    private List<TaskCostMetricVO>                   taskCost;\n\n    @ApiModelProperty(\"当前执行的task数量\")\n    private List<TaskCountMetricVO>                  taskCount;\n\n    /******************************************6.索引信息******************************************/\n\n    @ApiModelProperty(\"大索引列表,大于10亿文档的索引列表\")\n    private List<BigIndexMetricsVO>                  bigIndices;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/ESClusterPhyBasicMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport java.io.Serializable;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"物理集群基础指标信息\")\npublic class ESClusterPhyBasicMetricsVO implements Serializable {\n    /******************************************1.状态栏信息*****************************************/\n\n    @ApiModelProperty(\"集群状态, green yellow red\")\n    private String  status;\n\n    @ApiModelProperty(\"集群节点数量\")\n    private Long    numberNodes;\n\n    @ApiModelProperty(\"活跃节点数量\")\n    private Long    activeNodeNu;\n\n    @ApiModelProperty(\"无效节点数量\")\n    private Long    invalidNodeNu;\n\n    @ApiModelProperty(\"无效节点数量\")\n    private Integer totalNodeNu;\n\n    @ApiModelProperty(\"活跃节点百分比\")\n    private Double  activeNodeNuPercent;\n\n    @ApiModelProperty(\"无效节点百分比\")\n    private Double  invalidNodeNuPercent;\n\n    @ApiModelProperty(\"集群模板数\")\n    private Long    totalTemplateNu;\n\n    @ApiModelProperty(\"集群索引数\")\n    private Long    totalIndicesNu;\n\n    @ApiModelProperty(\"集群shard数量\")\n    private Long    shardNu;\n\n    @ApiModelProperty(\"集群文档数\")\n    private Long    totalDocNu;\n\n    @ApiModelProperty(\"已用内存大小\")\n    private Long    memUsed;\n\n    @ApiModelProperty(\"剩余空闲内存大小\")\n    private Long    memFree;\n\n    @ApiModelProperty(\"总内存大小\")\n    private Long    memTotal;\n\n    @ApiModelProperty(\"已用堆内存大小\")\n    private Long    heapMemUsed;\n\n    @ApiModelProperty(\"剩余堆内存大小\")\n    private Long    heapMemFree;\n\n    @ApiModelProperty(\"总堆内存大小\")\n    private Long    heapMemTotal;\n\n    @ApiModelProperty(\"堆内存使用率\")\n    private Double  heapUsage;\n\n    @ApiModelProperty(\"堆内存空闲率\")\n    private Double  heapFreeUsage;\n\n    @ApiModelProperty(\"已用内存百分比\")\n    private Double  memUsedPercent;\n\n    @ApiModelProperty(\"剩余空闲内存百分比\")\n    private Double  memFreePercent;\n\n    @ApiModelProperty(\"集群已使用容量，bytes 单位\")\n    private Long    storeSize;\n\n    @ApiModelProperty(\"集群总容量，bytes 单位\")\n    private Long    totalStoreSize;\n\n    @ApiModelProperty(\"集群空余容量，bytes 单位\")\n    private Long    freeStoreSize;\n\n    @ApiModelProperty(\"磁盘使用率\")\n    private Double  storeUsage;\n\n    @ApiModelProperty(\"磁盘空闲率\")\n    private Double  storeFreeUsage;\n\n    @ApiModelProperty(\"master节点数量\")\n    private Long    numberMasterNodes;\n\n    @ApiModelProperty(\"dataNode数量\")\n    private Long    numberDataNodes;\n\n    @ApiModelProperty(\"client节点数量\")\n    private Long    numberClientNodes;\n\n    @ApiModelProperty(\"Ingest节点数量\")\n    private Long    numberIngestNodes;\n\n    @ApiModelProperty(\"CoordinatingOnly节点数量\")\n    private Long    numberCoordinatingOnlyNodes;\n\n    @ApiModelProperty(\"集群索引总存储量\")\n    private Long    indicesStoreSize;\n\n    @ApiModelProperty(\"未分配shard数\")\n    private Long    unassignedShardNum;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/ESClusterTaskDetailVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n/**\n * @author didi\n * @date 2022-01-14 10:36 上午\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"task任务详情\")\npublic class ESClusterTaskDetailVO implements Serializable {\n\n    @ApiModelProperty(\"任务id\")\n    private String taskId;\n\n    @ApiModelProperty(\"节点名称\")\n    private String node;\n\n    @ApiModelProperty(\"操作类型\")\n    private String action;\n\n    @ApiModelProperty(\"开始时间\")\n    private long   startTime;\n\n    @ApiModelProperty(\"运行时间ms\")\n    private long   runningTime;\n\n    @ApiModelProperty(\"运行时间string\")\n    private String runningTimeString;\n\n    @ApiModelProperty(\"描述\")\n    private String description;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/IndexBelongNodeVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"索引归属节点信息\")\npublic class IndexBelongNodeVO extends BaseVO {\n\n    @ApiModelProperty(\"节点名称\")\n    private String node;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/IndexingLatencyMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.percentiles.ESPercentileMetricsVO;\nimport io.swagger.annotations.ApiModel;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@ApiModel(\"写入延时\")\npublic class IndexingLatencyMetricsVO extends ESPercentileMetricsVO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/MovingShardMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport java.io.Serializable;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-29\n */\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"正在迁移shard信息\")\npublic class MovingShardMetricsVO implements Serializable {\n\n    @ApiModelProperty(\"承载索引\")\n    private String i;\n\n    @ApiModelProperty(\"源节点Ip\")\n    private String shost;\n\n    @ApiModelProperty(\"目标节点ip\")\n    private String thost;\n\n    @ApiModelProperty(\"恢复的字节数\")\n    private String br;\n\n    @ApiModelProperty(\"字节数占比\")\n    private String bp;\n\n    @ApiModelProperty(\"转换日志操作占比\")\n    private String top;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/NodeInfoForDiskUsageGte75PercentVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n/**\n * Created by linyunan on 2021-08-09\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"大于75%磁盘利用率节点列表\")\npublic class NodeInfoForDiskUsageGte75PercentVO implements Serializable {\n\n    @ApiModelProperty(\"大于75%磁盘利用率节点Ip列表\")\n    private String nodeIp;\n\n    @ApiModelProperty(\"大于75%磁盘利用率节点名称列表\")\n    private String nodeName;\n\n    @ApiModelProperty(\"利用率\")\n    private Double value;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/PendingTaskVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport java.io.Serializable;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-30\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"Pending任务\")\npublic class PendingTaskVO implements Serializable {\n\n    @ApiModelProperty(\"顺序\")\n    private Long   insertOrder;\n\n    @ApiModelProperty(\"队列耗时\")\n    private String timeInQueue;\n\n    @ApiModelProperty(\"优先级, HIGH\")\n    private String priority;\n\n    @ApiModelProperty(\"原因\")\n    private String source;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/ReadQPSMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"查询QPS\")\npublic class ReadQPSMetricsVO extends ESAggMetricsVO {\n\n    @ApiModelProperty(\"集群读取tps\")\n    private Double readTps;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/RecvTransMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"每秒接受总流量\")\npublic class RecvTransMetricsVO extends ESAggMetricsVO {\n\n    @ApiModelProperty(\"集群每秒接受总流量\")\n    private Double recvTransSize;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/SearchLatencyMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.percentiles.ESPercentileMetricsVO;\nimport io.swagger.annotations.ApiModel;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@ApiModel(\"查询延时\")\npublic class SearchLatencyMetricsVO extends ESPercentileMetricsVO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/SendTransMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"每秒发送总流量\")\npublic class SendTransMetricsVO extends ESAggMetricsVO {\n\n    @ApiModelProperty(\"集群每秒发送总流量\")\n    private Double sendTransSize;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/ShardInfoMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-07-31\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"shard数量(总数, 未分配Shard)\")\npublic class ShardInfoMetricsVO extends ESAggMetricsVO {\n\n    @ApiModelProperty(\"集群shard数量\")\n    private Long shardNu;\n\n    @ApiModelProperty(\"未分配shard\")\n    private Long unAssignedShards;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/TaskCostMetricVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.percentiles.ESPercentileMetricsVO;\nimport io.swagger.annotations.ApiModel;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author didi\n * @date 2022-01-13 5:43 下午\n */\n@Data\n@NoArgsConstructor\n@ApiModel(\"task耗时指标信息\")\npublic class TaskCostMetricVO extends ESPercentileMetricsVO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/TaskCountMetricVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author didi\n * @date 2022-01-13 5:44 下午\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"task数量\")\npublic class TaskCountMetricVO extends ESAggMetricsVO {\n\n    @ApiModelProperty(\"集群task数量\")\n    private long taskCount;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/UnAssignShardMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.Serializable;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"未分配的shard信息\")\npublic class UnAssignShardMetricsVO implements Serializable {\n\n    @ApiModelProperty(\"归属索引\")\n    private String index;\n\n    @ApiModelProperty(\"shard标识\")\n    private long   shard;\n\n    @ApiModelProperty(\"主/备\")\n    private String prirep;\n\n    @ApiModelProperty(\"状态\")\n    private String state;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/cluster/WriteTPSMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"写入TPS\")\npublic class WriteTPSMetricsVO extends ESAggMetricsVO {\n\n    @ApiModelProperty(\"集群写入tps\")\n    private Double writeTps;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/dashboard/ClusterPhyHealthMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.dashboard;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 3/14/22\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"dashboard物理集群健康指标信息\")\npublic class ClusterPhyHealthMetricsVO {\n    @ApiModelProperty(\"当前时间\")\n    private Long         timestamp;\n\n    @ApiModelProperty(\"总物理集群数量\")\n    private Integer      totalNum;\n\n    @ApiModelProperty(\"green状态集群数\")\n    private Integer      greenNum;\n\n    @ApiModelProperty(\"yellow状态集群数\")\n    private Integer      yellowNum;\n\n    @ApiModelProperty(\"red状态集群数\")\n    private Integer      redNum;\n\n    @ApiModelProperty(\"未知状态集群数\")\n    private Integer      unknownNum;\n\n    @ApiModelProperty(\"green状态集群名称列表\")\n    private List<String> greenClusterList;\n\n    @ApiModelProperty(\"yellow状态集群名称列表\")\n    private List<String> yellowClusterList;\n\n    @ApiModelProperty(\"red状态集群名称列表\")\n    private List<String> redClusterList;\n\n    @ApiModelProperty(\"未知状态集群名称列表\")\n    private List<String> unknownClusterList;\n\n    @ApiModelProperty(\"未知状态集群百分比\")\n    private Double       unknownPercent;\n\n    @ApiModelProperty(\"green状态集群百分比\")\n    private Double       greenPercent;\n\n    @ApiModelProperty(\"yellow状态集群百分比\")\n    private Double       yellowPercent;\n\n    @ApiModelProperty(\"red状态集群百分比\")\n    private Double       redPercent;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/other/gateway/GatewayOverviewMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.gateway;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.MetricsContentCellVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * Created by fitz on 2021-08-11\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"gateway总览折线图指标信息\")\npublic class GatewayOverviewMetricsVO {\n\n    @ApiModelProperty(\"指标类型\")\n    private String                     type;\n\n    @ApiModelProperty(\"指标值\")\n    private List<MetricsContentCellVO> metrics;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/percentiles/ESPercentileMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.percentiles;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.ESAggMetricsVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author lyn\n * @date 2021-11-18\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"ES分位图指标\")\npublic class ESPercentileMetricsVO extends ESAggMetricsVO {\n    @ApiModelProperty(\"均值\")\n    private Double aggType;\n\n    @ApiModelProperty(\"99分位值\")\n    private Double st99;\n\n    @ApiModelProperty(\"95分位值\")\n    private Double st95;\n\n    @ApiModelProperty(\"75分位值\")\n    private Double st75;\n\n    @ApiModelProperty(\"55分位值\")\n    private Double st55;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/top/MetricsContentCellVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-04\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"某个时刻指标项详情\")\npublic class MetricsContentCellVO extends BaseVO implements Comparable<MetricsContentCellVO> {\n\n    @ApiModelProperty(\"指标值\")\n    private Double value;\n\n    @ApiModelProperty(\"时间戳\")\n    private Long   timeStamp;\n\n    @Override\n    public int compareTo(MetricsContentCellVO o) {\n        if (null == o) {\n            return 0;\n        }\n\n        return this.getTimeStamp().intValue() - o.getTimeStamp().intValue();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/top/MetricsContentVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top;\n\nimport java.io.Serializable;\nimport java.util.List;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"集群索引指标详情\")\npublic class MetricsContentVO implements Serializable {\n\n    @ApiModelProperty(\"集群名称，仅在节点维度指标、索引维度指标、模板维度指标设置该值，用于前端dashboard跳转至指标看板\")\n    private String                     cluster;\n\n    @ApiModelProperty(\"名称： 集群名称/节点名称/模板名称/索引名称\")\n    private String                     name;\n\n    @ApiModelProperty(\"指标列表\")\n    private List<MetricsContentCellVO> metricsContentCells;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/metrics/top/VariousLineChartMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top;\n\nimport java.io.Serializable;\nimport java.util.List;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 2021-08-01\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"折线图(TopN类型)指标信息\")\npublic class VariousLineChartMetricsVO implements Serializable {\n\n    @ApiModelProperty(\"指标类型\")\n    private String                 type;\n\n    @ApiModelProperty(\"指标数据信息\")\n    private List<MetricsContentVO> metricsContents;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/operaterecord/OperateRecordVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.operaterecord;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.ModuleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.Date;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/14\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class OperateRecordVO extends BaseVO {\n\n    /**\n    * 主键\n    */\n    @ApiModelProperty(\"记录ID\")\n    private Integer id;\n\n    /**\n     * @see ModuleEnum\n     */\n    @ApiModelProperty(\"模块\")\n    private String  module;\n\n    /**\n     * @see OperateTypeEnum\n     */\n    @ApiModelProperty(\"操作ID\")\n    private String  operate;\n\n    /**\n     * 操作描述\n     */\n    @ApiModelProperty(\"操作内容\")\n    private String  content;\n\n    /**\n     * 操作人\n     */\n    @ApiModelProperty(\"操作人\")\n    private String  userOperation;\n\n    /**\n     * 操作时间\n     */\n    @ApiModelProperty(\"操作时间\")\n    private Date    operateTime;\n\n    /**\n     * 触发方式\n     * @see com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum\n     */\n    @ApiModelProperty(\"操作方式\")\n    private String  triggerWay;\n    /**\n     * 应用id\n     */\n    @ApiModelProperty(\"项目\")\n    private String  projectName;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/order/AriusWorkOrderInfoSubmittedVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.order;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author zengqiao\n * @date 20/10/20\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"工单创建完成\")\npublic class AriusWorkOrderInfoSubmittedVO extends BaseVO {\n    @ApiModelProperty(value = \"工单ID\")\n    private Long   id;\n\n    @ApiModelProperty(value = \"工单标题\")\n    private String title;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/order/OrderTypeVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.order;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/25\n */\n@Data\n@NoArgsConstructor\npublic class OrderTypeVO extends BaseVO {\n    @ApiModelProperty(value = \"工单类型\")\n    private String type;\n\n    @ApiModelProperty(value = \"描述信息\")\n    private String message;\n\n    public OrderTypeVO(String type, String message) {\n        this.type = type;\n        this.message = message;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/order/WorkOrderVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.order;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Date;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/25\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class WorkOrderVO extends BaseVO {\n    @ApiModelProperty(value = \"工单ID\")\n    private Long    id;\n\n    @ApiModelProperty(value = \"工单标题\")\n    private String  title;\n\n    @ApiModelProperty(value = \"工单类型\")\n    private String  type;\n\n    @ApiModelProperty(value = \"申请人\")\n    private String  applicant;\n\n    @ApiModelProperty(value = \"描述信息\")\n    private String  description;\n\n    @ApiModelProperty(value = \"工单状态, 0:待审批, 1:通过, 2:拒绝, 3:取消\")\n    private Integer status;\n\n    @ApiModelProperty(value = \"申请/审核时间\")\n    private Date    createTime;\n\n    @ApiModelProperty(value = \"审批人ProjectId\")\n    private Integer approverProjectId;\n\n    @ApiModelProperty(value = \"扩展字段\")\n    private String  extensions;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/order/detail/OrderDetailBaseVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.order.detail;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.Date;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/25\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"工单详情类\")\npublic class OrderDetailBaseVO extends BaseVO {\n    @ApiModelProperty(value = \"工单ID\")\n    private Long              id;\n\n    @ApiModelProperty(value = \"工单类型\")\n    private String            type;\n\n    @ApiModelProperty(value = \"申请人\")\n    private UserBriefVO       applicant;\n\n    @ApiModelProperty(value = \"申请人部门\")\n    private String            appDeptName;\n\n    @ApiModelProperty(value = \"申请人使用的ProjectId\")\n    private Integer           applicantProjectId;\n\n    @ApiModelProperty(value = \"申请人使用的项目名称\")\n    private String            applicantAppName;\n\n    @ApiModelProperty(value = \"审批人列表, 状态为未处理时返回的是审批人, 状态为处理完成时返回的是审批的人\")\n    private List<UserBriefVO> approverList;\n\n    @ApiModelProperty(value = \"审批时间\")\n    private Date              finishTime;\n\n    @ApiModelProperty(value = \"审批审批意见\")\n    private String            opinion;\n\n    @ApiModelProperty(value = \"工单状态, 0:待审批, 1:通过, 2:拒绝, 3:取消\")\n    private Integer           status;\n\n    @ApiModelProperty(value = \"备注\")\n    private String            description;\n\n    @ApiModelProperty(value = \"工单title\")\n    private String            title;\n\n    @ApiModelProperty(value = \"工单明细, json字符串\")\n    private String            detail;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/ConsoleESUserVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 用户控制台使用\n *\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"es user 信息\")\npublic class ConsoleESUserVO extends BaseVO {\n\n    @ApiModelProperty(\"es user\")\n    private Integer id;\n\n    @ApiModelProperty(\"备注\")\n    private String  memo;\n\n    @ApiModelProperty(\"查询限流值\")\n    private Integer queryThreshold;\n\n    @ApiModelProperty(\"数据中心\")\n    private String  dataCenter;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/ConsoleESUserWithVerifyCodeVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 用户控制台使用\n *\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"es user 信息（包含验证码）\")\npublic class ConsoleESUserWithVerifyCodeVO extends BaseVO {\n\n    @ApiModelProperty(\"es user \")\n    private Integer id;\n\n    @ApiModelProperty(\"应用名称\")\n    private String  name;\n\n    @ApiModelProperty(\"验证码\")\n    private String  verifyCode;\n\n    @ApiModelProperty(\"部门ID\")\n    @Deprecated\n    private String  departmentId;\n\n    @ApiModelProperty(\"部门名称\")\n    @Deprecated\n    private String  department;\n\n  \n\n    @ApiModelProperty(\"备注\")\n    private String  memo;\n\n    @ApiModelProperty(\"查询限流值\")\n    private Integer queryThreshold;\n\n    @ApiModelProperty(\"数据中心\")\n    private String  dataCenter;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/ESUserVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 运维控制台使用\n *\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"es user信息\")\npublic class ESUserVO extends BaseVO {\n\n    @ApiModelProperty(\"es user\")\n    private Integer id;\n\n    @ApiModelProperty(\"root用户\")\n    private Integer isRoot;\n\n    @ApiModelProperty(\"验证码\")\n    private String  verifyCode;\n\n    @ApiModelProperty(\"备注\")\n    private String  memo;\n\n    @ApiModelProperty(\"限流值\")\n    private Integer queryThreshold;\n\n    @ApiModelProperty(\"查询集群\")\n    private String  cluster;\n\n    @ApiModelProperty(\"查询模式（0:集群模式；1:索引模式, 3:原生模式）\")\n    private Integer searchType;\n    @ApiModelProperty(\"项目默认使用的es user\")\n    private Boolean defaultDisplay;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/GatewayESUserVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 运维控制台使用\n *\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"应用信息（包含权限）\")\npublic class GatewayESUserVO extends BaseVO {\n\n    @ApiModelProperty(\"es user\")\n    private Integer      id;\n    @ApiModelProperty(\"project id\")\n    private Integer      projectId;\n\n    @ApiModelProperty(\"应用名称\")\n    private String       name;\n\n    @ApiModelProperty(\"验证码\")\n    private String       verifyCode;\n\n    @ApiModelProperty(\"限流值\")\n    private Integer      queryThreshold;\n\n    @ApiModelProperty(\"查询集群\")\n    private String       cluster;\n\n    @ApiModelProperty(\"查询模式\")\n    private Integer      searchType;\n\n    /**\n     * 有读权限的索引列表\n     */\n    @ApiModelProperty(\"读权限列表\")\n    private List<String> indexExp;\n\n    /**\n     * 有写权限的索引列表\n     */\n    @ApiModelProperty(\"读写权限列表\")\n    private List<String> wIndexExp;\n\n    /**\n     * 白名单\n     */\n    @ApiModelProperty(\"IP白名单\")\n    private List<String> ip;\n\n    /**\n     *\n     */\n    @ApiModelProperty(\"数据中心\")\n    private String       dataCenter;\n\n    @ApiModelProperty(\"dsl解析开关\")\n    private Integer      dslAnalyzeEnable;\n\n    @ApiModelProperty(\"聚合解析开关\")\n    private Integer      aggrAnalyzeEnable;\n\n    @ApiModelProperty(\"查询结果解析开关\")\n    private Integer      analyzeResponseEnable;\n\n    @ApiModelProperty(\"超级租户开关\")\n    private Integer      isRoot;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/ProjectBriefExtendVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 项目简要扩展签证官:加入项目配置相关信息\n *\n * @author shizeying\n * @date 2022/06/10\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"项目简要信息（包含项目配置）\")\npublic class ProjectBriefExtendVO extends ProjectBriefVO {\n    @ApiModelProperty(value = \"项目配置\", dataType = \"ProjectSaveDTO\", required = false)\n    private ProjectConfigVO config;\n    @ApiModelProperty(value = \"是否为超级项目\", dataType = \"boolean\", required = false)\n    private Boolean         isAdmin;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/ProjectConfigVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"应用信息\")\npublic class ProjectConfigVO extends BaseEntity {\n\n    /**\n     * projectId\n     */\n    @ApiModelProperty(value = \"项目\", required = true)\n    private Integer projectId;\n\n    /**\n     * gateway返回结果解析开关\n     */\n    @ApiModelProperty(value = \"gateway返回结果解析开关\", required = false)\n    private Integer analyzeResponseEnable;\n\n    /**\n     * 是否生效DSL分析查询限流值 1为生效DSL分析查询限流值，0不生效DSL分析查询限流值\n     */\n    @ApiModelProperty(value = \"是否生效DSL分析查询限流值: 1为生效DSL分析查询限流值，0不生效DSL分析查询限流值\", required = false)\n    private Integer dslAnalyzeEnable;\n\n    /**\n     * 是否开启聚合分析  1 开启  0 不开启  默认为 1\n     */\n    @ApiModelProperty(value = \"是否开启聚合分析:  1 开启  0 不开启  默认为 1\", required = false)\n    private Integer aggrAnalyzeEnable;\n\n    /**\n     * 是否索引存储分离，1为分离，0为不分离，默认为0\n     */\n    @ApiModelProperty(value = \"是否索引存储分离:1为分离，0为不分离，默认为0\", required = false)\n    private Integer isSourceSeparated;\n    /**\n     * 慢查询时间\n     */\n    @ApiModelProperty(value = \"慢查询时间\", required = true)\n    private Integer slowQueryTimes;\n    /**\n     * 备注\n     */\n    @ApiModelProperty(value = \"备注\", required = false)\n    private String  memo;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/ProjectExtendVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * projectvo 的扩展类：扩展logi侧projectvo\n *\n * @author shizeying\n * @date 2022/06/10\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"项目信息（包含项目配置）和是否为超级项目\")\npublic class ProjectExtendVO extends ProjectVO {\n    @ApiModelProperty(value = \"项目配置\", dataType = \"ProjectSaveDTO\", required = false)\n    private ProjectConfigVO config;\n    @ApiModelProperty(value = \"是否为超级项目\", dataType = \"boolean\", required = false)\n    private Boolean           isAdmin = false;\n    @ApiModelProperty(value = \"持有管理员角色的项目成员\", dataType = \"List<UserBriefVO>\", required = false)\n    private List<UserBriefVO> userListWithAdminRole;\n    \n    @ApiModelProperty(value = \"具有管理员角色和持有项目用户的项目成员\", dataType = \"List<UserBriefVO>\", required = false)\n    private List<UserBriefVO> userListWithBelongProjectAndAdminRole;\n    \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/ProjectLogicClusterAuthVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.BaseDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/4/16\n */\n@Data\n@ApiModel(description = \"应用逻辑集群权限信息\")\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ProjectLogicClusterAuthVO extends BaseDTO {\n\n    @ApiModelProperty(\"ID\")\n    private Long    id;\n\n    @ApiModelProperty(\"应用ID\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"逻辑集群ID\")\n    private Long    logicClusterId;\n\n    /**\n     * @see ProjectClusterLogicAuthEnum\n     */\n    @ApiModelProperty(\"权限类型:0：超管权限，1：配置管理权限，2：访问权限\")\n    private Integer type;\n\n   \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/ProjectTemplateAuthVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/4/16\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"应用权限信息\")\npublic class ProjectTemplateAuthVO extends BaseVO {\n    @ApiModelProperty(\"ID\")\n    private Long    id;\n\n    @ApiModelProperty(\"应用ID\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"模板ID\")\n    private Integer templateId;\n\n    @ApiModelProperty(\"模板名称\")\n    private String  templateName;\n\n    /**\n     * 权限类型  读写  读\n     * @see ProjectTemplateAuthEnum\n     */\n    @ApiModelProperty(\"权限类型（-1 无权限 ;1:管理；2:读写；3:读）\")\n    private Integer type;\n\n    @ApiModelProperty(\"所属逻辑集群ID\")\n    private Long    logicClusterId;\n\n    @ApiModelProperty(\"所属逻辑集群名称\")\n    private String  logicClusterName;\n\n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/RoleExtendVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didiglobal.knowframework.security.common.vo.role.RoleVO;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n/**\n * 角色扩展\n *\n * @author shizeying\n * @date 2022/06/17\n */\n@Data\npublic class RoleExtendVO extends RoleVO {\n    /**\n     * 是默认角色:\n     *\n     */\n    @ApiModelProperty(value = \"是否为默认角色\", dataType = \"Boolean\", required = false)\n    private Boolean isDefaultRole = false;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/SinkSdkESUserVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 运维控制台使用\n *\n * @author d06679\n * @date 2019/3/13\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"应用信息（包含权限）\")\n@Deprecated\npublic class SinkSdkESUserVO extends BaseVO {\n\n    @ApiModelProperty(\"应用ID\")\n    private Integer      id;\n\n    @ApiModelProperty(\"应用名称\")\n    private String       name;\n\n    @ApiModelProperty(\"验证码\")\n    private String       verifyCode;\n\n    /**\n     * 有读权限的索引列表\n     */\n    @ApiModelProperty(\"读权限列表\")\n    private List<String> indexExp;\n\n    /**\n     * 有写权限的索引列表\n     */\n    @ApiModelProperty(\"读写权限列表\")\n    private List<String> wIndexExp;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/UserExtendVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"用户信息\")\npublic class UserExtendVO extends UserVO {\n    @ApiModelProperty(value = \"持有管理员角色的项目成员\", dataType = \"List<UserBriefVO>\", required = false)\n    private List<UserBriefVO> userListWithAdminRole;\n\n    @ApiModelProperty(value = \"作为责任人的应用列表\", dataType = \"List<String>\", required = false)\n    private List<String> ownProjects;\n\n    @ApiModelProperty(value = \"作为唯一责任人的应用列表\", dataType = \"List<String>\", required = false)\n    private List<String> singleOwnerOfProjects;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/project/UserWithPwVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.project;\n\nimport com.didiglobal.knowframework.security.common.vo.user.UserVO;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n/**\n * @Authoer: zyl\n * @Date: 2022/11/17\n * @Version: 1.0\n */\n@Data\npublic class UserWithPwVO extends UserVO {\n    @ApiModelProperty(value = \"用户密码\", dataType = \"String\", required = false)\n    private String password;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/task/OpTaskVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(\"任务中心信息\")\npublic class OpTaskVO  extends BaseVO {\n    @ApiModelProperty(\"id\")\n    private Integer           id;\n\n    @ApiModelProperty(\"标题\")\n    private String            title;\n\n    @ApiModelProperty(\"任务类型\")\n    private Integer           taskType;\n\n    @ApiModelProperty(\"业务数据主键\")\n    private String            businessKey;\n\n    @ApiModelProperty(\"任务状态，success:成功 failed:失败 running:执行中 waiting:等待 cancel:取消 pause:暂停\")\n    private String            status;\n\n    @ApiModelProperty(\"创建人\")\n    private String            creator;\n\n    @ApiModelProperty(\"标记删除\")\n    private Boolean           deleteFlag;\n\n    @ApiModelProperty(\"expandData\")\n    private String            expandData;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/task/TaskTypeVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n/**\n * @author fengqiongfeng\n * @date 2020/12/21\n */\n@Data\npublic class TaskTypeVO extends BaseVO {\n    @ApiModelProperty(value = \"任务类型\")\n    private Integer type;\n\n    @ApiModelProperty(value = \"描述信息\")\n    private String  message;\n\n    public TaskTypeVO(Integer type, String message) {\n        this.type = type;\n        this.message = message;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/task/WorkTaskVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport java.util.Date;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * OpTask PO 对象\n * \n * @author fengqiongfeng\n * @date 2020-12-21\n */\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class WorkTaskVO extends BaseVO {\n\n    /**\n     * 序列化版本号\n     */\n    private static final long serialVersionUID = 1L;\n\n    /**\n     * id\n     */\n    private Integer           id;\n\n    /**\n     * 标题 \n     */\n    private String            title;\n\n    /**\n     * 任务类型\n     */\n    private Integer           taskType;\n\n    /**\n     * 业务数据主键 \n     */\n    private String            businessKey;\n\n    /**\n     * 任务状态\n     * success:成功 failed:失败\n     * running:执行中 waiting:等待\n     * cancel:取消 pause:暂停\n     */\n    private String            status;\n\n    /**\n     * 创建人 \n     */\n    private String            creator;\n\n    /**\n     * 创建时间 \n     */\n    private Date              createTime;\n\n    /**\n     * 更新时间 \n     */\n    private Date              updateTime;\n\n    /**\n     * 标记删除 \n     */\n    private Boolean           deleteFlag;\n\n    /**\n     * expandData \n     */\n    private String            expandData;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/AmsTemplatePhysicalConfVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"多type索引模板映射信息\")\npublic class AmsTemplatePhysicalConfVO extends BaseVO {\n\n    @ApiModelProperty(\"逻辑模板ID\")\n    private Integer                                         logicId;\n\n    @ApiModelProperty(\"模板名字\")\n    private String                                          name;\n\n    /**\n     * 用于索引多type改造   是否启用索引名称映射 0 禁用 1 启用\n     */\n    @ApiModelProperty(\"是否启用\")\n    private Boolean                                         mappingIndexNameEnable;\n\n    /**\n     * 多type索引type名称到单type索引模板名称的映射\n     */\n    @ApiModelProperty(\"映射关系\")\n    private Map<String/*typeName*/, String/*templateName*/> typeIndexMapping;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/BaseTemplateVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.BaseEntity;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 索引模板签证官\n *\n * @author shizeying\n * @date 2022/08/23\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class BaseTemplateVO extends BaseEntity implements Comparable<BaseTemplateVO> {\n    \n    @ApiModelProperty(\"索引 ID\")\n    private Integer id;\n    \n    @ApiModelProperty(\"索引名称\")\n    private String name;\n    \n    /**\n     * 用户数据类型\n     *\n     * @see DataTypeEnum\n     */\n    @ApiModelProperty(\"数据类型（0: 系统 1: 日志；2: 用户上报；3:RDS 数据；4：离线导入数据）\")\n    private Integer dataType;\n    \n    /**\n     * 索引滚动格式\n     */\n    @ApiModelProperty(\"时间后缀\")\n    private String dateFormat;\n    \n    @ApiModelProperty(\"数据中心\")\n    private String dataCenter;\n    \n    /**\n     * 数据保存时长 单位天\n     */\n    @ApiModelProperty(\"保存天数\")\n    private Integer expireTime;\n    \n    /**\n     * 热数据保存时长 单位天\n     */\n    @ApiModelProperty(\"热数据保存天数\")\n    private Integer hotTime;\n    \n    @ApiModelProperty(\"索引应用 ID\")\n    private Integer projectId;\n    \n    @ApiModelProperty(\"时间字段\")\n    private String dateField;\n    \n    @ApiModelProperty(\"时间字段格式\")\n    private String dateFieldFormat;\n    \n    /**\n     * id 地钻\n     */\n    @ApiModelProperty(\"主键字段\")\n    private String idField;\n    \n    @ApiModelProperty(\"routing 字段\")\n    private String routingField;\n    \n    @ApiModelProperty(\"表达式\")\n    private String expression;\n    \n    @ApiModelProperty(\"描述\")\n    private String desc;\n    \n    /**\n     * 规格 单位台\n     */\n    @ApiModelProperty(\"配额\")\n    private Double quota;\n    \n    @ApiModelProperty(\"写入限流值，\" + \"writeRateLimit = 0 禁止写入；\" + \"writeRateLimit = -1 不限流；\"\n                      + \"writeRateLimit = 123 具体的写入 tps 限流值，即单台 client 每秒写入 123 条文档\")\n    private Integer writeRateLimit;\n    \n    /**\n     * 是否禁读\n     */\n    @ApiModelProperty(\"是否禁读\")\n    private Boolean blockRead;\n    \n    /**\n     * 是否禁写\n     */\n    @ApiModelProperty(\"是否禁写\")\n    private Boolean blockWrite;\n    \n    /**\n     * 副本保存时长 单位天\n     */\n    @ApiModelProperty(\"副本保存时长 单位天\")\n    private Integer replicaTime;\n    \n    /**\n     * 逻辑集群 id\n     */\n    @ApiModelProperty(\"逻辑集群 id\")\n    private Long resourceId;\n    \n    /**\n     * pipeline\n     */\n    @ApiModelProperty(\"pipeline\")\n    private String ingestPipeline;\n    \n    /**\n     * 服务等级\n     */\n    @ApiModelProperty(\"服务等级\")\n    private Integer level;\n    \n    /**\n     * 是否开启 dcdr\n     */\n    @ApiModelProperty(\"是否开启 dcdr\")\n    private Boolean hasDCDR;\n    \n    /**\n     * 数据位点差\n     */\n    @ApiModelProperty(\"是否禁写\")\n    private Long checkPointDiff;\n    \n    /**\n     * 已开启的模板服务\n     */\n    @ApiModelProperty(\"是否禁写\")\n    private String  openSrv;\n    /**\n     * regionId\n     */\n    @ApiModelProperty(\"regionId\")\n    private Integer regionId;\n    \n    /**\n     * 可用磁盘容量\n     */\n    @ApiModelProperty(\"可用磁盘容量\")\n    private Double  diskSize;\n    /**\n     * 模版健康度\n     */\n    @ApiModelProperty(\"模版健康度\")\n    private Integer health;\n    \n    @Override\n    public int compareTo(BaseTemplateVO o) {\n        if (null == o) {\n            return 0;\n        }\n        \n        return o.getId().intValue() - this.getId().intValue();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ConsoleTemplateClearVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexCatCellWithTemplateVO;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引清理信息\")\npublic class ConsoleTemplateClearVO extends BaseVO {\n\n    @ApiModelProperty(\"索引ID\")\n    private Integer              logicId;\n\n    @ApiModelProperty(\"索引名字\")\n    private String               name;\n\n    @ApiModelProperty(\"清理索引列表\")\n    private List<IndexCatCellWithTemplateVO> indices;\n\n    /**\n     * 最近一段时间有访问的app\n     */\n    @ApiModelProperty(\"访问应用列表\")\n    private List<ProjectBriefVO> accessApps;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ConsoleTemplateDeleteVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引下线信息\")\npublic class ConsoleTemplateDeleteVO extends BaseVO {\n\n    @ApiModelProperty(\"索引ID\")\n    private Integer              logicId;\n\n    @ApiModelProperty(\"索引名字\")\n    private String               name;\n\n    /**\n     * 最近一段时间有访问的app\n     */\n    @ApiModelProperty(\"访问应用列表\")\n    private List<ProjectBriefVO> accessApps;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ConsoleTemplateDetailVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ResourceLogicLevelEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引详细信息\")\npublic class ConsoleTemplateDetailVO extends BaseTemplateVO {\n\n    @ApiModelProperty(\"所属应用名称\")\n    private String       appName;\n\n    @ApiModelProperty(\"集群名称\")\n    private String       cluster;\n\n    /**\n     * @see ClusterResourceTypeEnum\n     */\n    @ApiModelProperty(\"集群类型\")\n    private Integer      clusterType;\n\n    /**\n     * @see ResourceLogicLevelEnum\n     */\n    @ApiModelProperty(\"集群服务等级\")\n    private Integer      clusterLevel;\n\n    @ApiModelProperty(\"索引分区列表，按着先后顺序排列\")\n    private List<String> indices;\n\n    @ApiModelProperty(\"是否分区\")\n    private Boolean      cyclicalRoll;\n\n    @ApiModelProperty(\"模板价值\")\n    private Integer      value;\n\n    @ApiModelProperty(\"能够编辑\")\n    private Boolean      editable;\n\n    @ApiModelProperty(\"服务等级\")\n    private Integer      level;\n\n    @ApiModelProperty(\"是否开启indexRollover能力\")\n    private Boolean      disableIndexRollover;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ConsoleTemplateFieldConvertVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引mapping转换信息\")\npublic class ConsoleTemplateFieldConvertVO extends BaseVO {\n\n    @ApiModelProperty(\"时间字段\")\n    private String dateField;\n\n    @ApiModelProperty(\"时间字段格式\")\n    private String dateFieldFormat;\n\n    /**\n     * mapping信息 mapping导入的\n     *\n     *      {\n     *       \"key1\": {\n     *         \"type\": \"integer\"\n     *       },\n     *       \"key2\": {\n     *         \"type\": \"long\"\n     *       }\n     *     }\n     *\n     */\n    @ApiModelProperty(\"mapping信息\")\n    private String mapping;\n\n    /**\n     * id地钻\n     */\n    @ApiModelProperty(\"主键子弹\")\n    private String idField;\n\n    @ApiModelProperty(\"routing字段\")\n    private String routingField;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ConsoleTemplatePhyVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author linyunan\n * @date 2021-03-16\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"携带App权限信息的物理模板信息\")\npublic class ConsoleTemplatePhyVO extends IndexTemplatePhysicalVO {\n\n    @ApiModelProperty(\"归属项目ID\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"归属项目名称\")\n    private String  projectName;\n\n    /**\n     * @see ProjectTemplateAuthEnum\n     */\n    @ApiModelProperty(\"当前App拥有的权限类型（-1 无权限 ;1:管理；2:读写；3:读）\")\n    private Integer authType;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ConsoleTemplateRateLimitVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@NoArgsConstructor\n@Data\n@ApiModel(\"索引限流信息\")\npublic class ConsoleTemplateRateLimitVO extends BaseVO {\n    @ApiModelProperty(\"限流大小\")\n    private Integer rateLimit;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ConsoleTemplateVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板信息\")\npublic class ConsoleTemplateVO extends BaseTemplateVO  {\n    /**\n     * @see ProjectTemplateAuthEnum\n     */\n    @ApiModelProperty(\"权限（1:管理；2:读写；3:读）\")\n    private Integer      authType;\n\n    @ApiModelProperty(\"所属集群\")\n    private List<String> clusterPhies;\n\n    @ApiModelProperty(\"模板价值\")\n    private Integer      value;\n\n    @ApiModelProperty(\"是否具备DCDR\")\n    private Boolean      hasDCDR;\n\n    @ApiModelProperty(\"DCDR主从位点差\")\n    private Long         checkPointDiff;\n\n    @ApiModelProperty(\"项目名称\")\n    private String       projectName;\n\n    @ApiModelProperty(\"是否开启indexRollover能力\")\n    private Boolean      disableIndexRollover;\n\n    @ApiModelProperty(\"逻辑集群id\")\n    private Long         resourceId;\n\n    @ApiModelProperty(\"服务等级,为1，2，3\")\n    private Integer      level;\n\n    @ApiModelProperty(\"逻辑集群\")\n    private String       cluster;\n    @ApiModelProperty(\"是否为分区模板\")\n    private Boolean isPartition;\n    @ApiModelProperty(\"模板健康度\")\n    private Integer health;\n  \n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/DCDRSingleTemplateMasterSlaveSwitchDetailVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(value = \"DCDRSingleTemplateMasterSlaveSwitchDetailVO\", description = \"模板DCDR详情\")\npublic class DCDRSingleTemplateMasterSlaveSwitchDetailVO extends BaseVO {\n    @ApiModelProperty(\"任务标题\")\n    private String       taskTitle;\n\n    @ApiModelProperty(\"dcdr主从切换类型 1 平滑 2 强切\")\n    private Integer      switchType;\n\n    @ApiModelProperty(\"模板Id\")\n    private Long         templateId;\n\n    @ApiModelProperty(\"主集群\")\n    private String       masterCluster;\n\n    @ApiModelProperty(\"从集群\")\n    private String       slaveCluster;\n\n    @ApiModelProperty(\"任务执行详情\\n\" + \"     * 0.创建dcdr\\n\" + \"     * 1.停止向主索引写入数据\\n\" + \"     * 2.确保主从索引数据同步\\n\"\n                      + \"     * 3.删除源dcdr模板和索引链路\\n\" + \"     * 4.拷贝主模板的mapping信息到从模板\\n\"\n                      + \"     * 5.关闭从索引dcdr索引开关，并打开主索引dcdr索引开关\\n\" + \"     * 6.停止从索引写入\\n\" + \"     * 7.创建新的dcdr链路\\n\"\n                      + \"     * 8.恢复主从索引实时写入\\n\" + \"     * 9.主从模板角色切换\")\n    private List<String> taskProgressList;\n\n    @ApiModelProperty(\"任务状态: 0 取消 1 成功 2 执行中 3 失败 4待执行\")\n    private Integer      taskStatus;\n\n    private Date         createTime;\n    private Date         finishTime;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/DCDRTasksDetailVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"dcdr主从切换任务详情\")\npublic class DCDRTasksDetailVO extends BaseVO {\n    @ApiModelProperty(\"多个模板dcdr主从切换任务详情\")\n    private List<DCDRSingleTemplateMasterSlaveSwitchDetailVO> dcdrSingleTemplateMasterSlaveSwitchDetailList;\n\n    @ApiModelProperty(\"任务总数\")\n    private Integer                                           total;\n    @ApiModelProperty(\"成功数\")\n    private Integer                                           successNum;\n    @ApiModelProperty(\"失败数\")\n    private Integer                                           failedNum;\n    @ApiModelProperty(\"正在运行数\")\n    private Integer                                           runningNum;\n    @ApiModelProperty(\"取消数\")\n    private Integer                                           cancelNum;\n    @ApiModelProperty(\"等待运行数\")\n    private Integer                                           waitNum;\n    @ApiModelProperty(\"总状态 0 取消 1 成功 2 运行中 3 失败 4 待运行\")\n    private Integer                                           state;\n    @ApiModelProperty(\"运行进度\")\n    private int                                               percent;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/DslMetricsVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2018/9/18 下午5:24\n * @modified By\n *\n * 查询模板一分钟聚合指标统计信息\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"DslMetricsVO\", description = \"查询模板一分钟聚合指标统计信息\")\npublic class DslMetricsVO {\n\n    @ApiModelProperty(\"创建时间\")\n    private String  ariusCreateTime;\n\n    @ApiModelProperty(\"日期时间\")\n    private String  logTime;\n\n    @ApiModelProperty(\"sink写入时间\")\n    private Long    sinkTime;\n\n    @ApiModelProperty(\"flink写入时间\")\n    private String  flinkTime;\n\n    @ApiModelProperty(\"响应平均长度\")\n    private Double  responseLenAvg;\n\n    @ApiModelProperty(\"请求类型 http/tcp\")\n    private String  requestType;\n\n    @ApiModelProperty(\"查询类型 dsl/sql\")\n    private String  searchType;\n\n    @ApiModelProperty(\"查询次数\")\n    private Long    searchCount;\n\n    @ApiModelProperty(\"查询es平均耗时\")\n    private Double  esCostAvg;\n\n    @ApiModelProperty(\"查询语句平均长度\")\n    private Double  dslLenAvg;\n\n    @ApiModelProperty(\"查询平均命中记录数\")\n    private Double  totalHitsAvg;\n\n    @ApiModelProperty(\"查询成功平均shard数\")\n    private Double  successfulShardsAvg;\n\n    @ApiModelProperty(\"查询平均总shard数\")\n    private Double  totalShardsAvg;\n\n    @ApiModelProperty(\"查询索引示例\")\n    private String  indiceSample;\n\n    @ApiModelProperty(\"查询模板\")\n    private String  dslTemplate;\n\n    @ApiModelProperty(\"记录生成时间戳\")\n    private Long    timeStamp;\n\n    @ApiModelProperty(\"dsl语句类型 normal/agg等\")\n    private String  dslType;\n\n    @ApiModelProperty(\"查询索引名称，去重后的\")\n    private String  indices;\n\n    @ApiModelProperty(\"查询模板\")\n    private String  dslTemplateMd5;\n\n    @ApiModelProperty(\"查询平均总耗时\")\n    private Double  totalCostAvg;\n\n    @ApiModelProperty(\"查询平均失败shard数\")\n    private Double  failedShardsAvg;\n\n    @ApiModelProperty(\"projectId\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"查询语句\")\n    private String  dsl;\n\n    @ApiModelProperty(\"gateway处理平均耗时\")\n    private Double  beforeCostAvg;\n\n    @ApiModelProperty(\"dsl查询限流值\")\n    private Double  queryLimit;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/DslTemplateVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/15 下午6:39\n * @modified By D10865\n *\n * dsl模板信息\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"DslTemplateVO\", description = \"dsl模板信息\")\npublic class DslTemplateVO {\n\n    @ApiModelProperty(\"查询模板创建时间\")\n    private String  ariusCreateTime;\n\n    @ApiModelProperty(\"查询模板修改时间\")\n    private String  ariusModifyTime;\n\n    @ApiModelProperty(\"平均响应长度\")\n    private Double  responseLenAvg;\n\n    @ApiModelProperty(\"请求类型\")\n    private String  requestType;\n\n    @ApiModelProperty(\"查询类型\")\n    private String  searchType;\n\n    @ApiModelProperty(\"查询次数(分钟级别)\")\n    private Long    searchCount;\n\n    @ApiModelProperty(\"es查询耗时\")\n    private Double  esCostAvg;\n\n    @ApiModelProperty(\"平均查询语句长度\")\n    private Double  dslLenAvg;\n\n    @ApiModelProperty(\"平均命中记录数\")\n    private Double  totalHitsAvg;\n\n    @ApiModelProperty(\"平均查询shard成功个数\")\n    private Double  successfulShardsAvg;\n\n    @ApiModelProperty(\"平均shard成功个数\")\n    private Double  totalShardsAvg;\n\n    @ApiModelProperty(\"查询请求时刻\")\n    private String  logTime;\n\n    @ApiModelProperty(\"查询索引示例\")\n    private String  indiceSample;\n\n    @ApiModelProperty(\"查询模板\")\n    private String  dslTemplate;\n\n    @ApiModelProperty(\"查询请求时刻\")\n    private Long    timeStamp;\n\n    @ApiModelProperty(\"查询语句类型\")\n    private String  dslType;\n\n    @ApiModelProperty(\"查询索引名称\")\n    private String  indices;\n\n    @ApiModelProperty(\"查询模板MD5\")\n    private String  dslTemplateMd5;\n\n    @ApiModelProperty(\"平均查询总耗时\")\n    private Double  totalCostAvg;\n\n    @ApiModelProperty(\"查询shard失败个数\")\n    private Double  failedShardsAvg;\n\n    @ApiModelProperty(\"dsink写入时间\")\n    private Long    sinkTime;\n\n    @ApiModelProperty(\"projectId\")\n    private Integer projectId;\n\n    @ApiModelProperty(\"查询语句\")\n    private String  dsl;\n\n    @ApiModelProperty(\"平均gateway处理耗时\")\n    private Double  beforeCostAvg;\n\n    @ApiModelProperty(\"flin\")\n    private String  flinkTime;\n\n    @ApiModelProperty(\"查询限流\")\n    private Double  queryLimit;\n\n    @ApiModelProperty(\"是否来自用户控制台\")\n    private Boolean isFromUserConsole;\n\n    @ApiModelProperty(\"是否强制设置查询限流值\")\n    private Boolean forceSetQueryLimit;\n\n    @ApiModelProperty(\"是否可用 null/true表示可用，false表示不可用\")\n    private Boolean enable;\n\n    @ApiModelProperty(\"黑白名单 null/white表示白名单，black表示黑名单\")\n    private String  checkMode;\n\n    @ApiModelProperty(\"慢查dsl阈值，单位为ms\")\n    private Long    slowDslThreshold;\n\n    @ApiModelProperty(\"查询模板版本号\")\n    private String  version;\n\n    @ApiModelProperty(\"查询模板危害标签\")\n    private String  dslTag;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/GatewayJoinVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport java.util.Map;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2018/9/19 下午5:36\n * @modified By\n *\n * join 后的gateway日志\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"GatewayJoinVO\", description = \"join 后的gateway日志\")\npublic class GatewayJoinVO {\n\n    @ApiModelProperty(\"请求path\")\n    private String            uri;\n\n    @ApiModelProperty(\"请求id\")\n    private String            requestId;\n\n    @ApiModelProperty(\"projectId\")\n    private Integer           projectId;\n\n    @ApiModelProperty(\"索引名称\")\n    private String            indices;\n\n    @ApiModelProperty(\"type名称\")\n    private String            typeName;\n\n    @ApiModelProperty(\"查询命中索引信息json\")\n    private String            index;\n\n    @ApiModelProperty(\"查询语句\")\n    private String            dsl;\n\n    @ApiModelProperty(\"查询模板\")\n    private String            dslTemplate;\n\n    @ApiModelProperty(\"查询模板MD5\")\n    private String            dslTemplateMd5;\n\n    @ApiModelProperty(\"是否超时，\\\"true\\\"/\\\"false\\\"\")\n    private String            isTimedOut;\n\n    @ApiModelProperty(\"查询语句类型\")\n    private String            dslType;\n\n    @ApiModelProperty(\"查询方式,dsl/sql\")\n    private String            searchType;\n\n    @ApiModelProperty(\"查询es耗时\")\n    private Long              esCost;\n\n    @ApiModelProperty(\"查询总耗时\")\n    private Long              totalCost;\n\n    @ApiModelProperty(\"查询shard个数\")\n    private Long              totalShards;\n\n    @ApiModelProperty(\"查询总命中数\")\n    private Long              totalHits;\n\n    @ApiModelProperty(\"查询响应长度\")\n    private Long              responseLen;\n\n    @ApiModelProperty(\"错误名称\")\n    private String            exceptionName;\n\n    @ApiModelProperty(\"创建时间\")\n    private String            ariusCreateTime;\n\n    @ApiModelProperty(\"timeStamp\")\n    private long              timeStamp;\n\n    @ApiModelProperty(\"indiceSample\")\n    private String            indiceSample;\n\n    @ApiModelProperty(\"查询字段\")\n    private Map<String, Long> selectFields;\n\n    @ApiModelProperty(\"过滤字段\")\n    private Map<String, Long> whereFields;\n\n    @ApiModelProperty(\"聚合字段\")\n    private Map<String, Long> groupByFields;\n\n    @ApiModelProperty(\"排序字段\")\n    private Map<String, Long> orderByFields;\n\n    @ApiModelProperty(\"多type索引查询映射后的索引名称\")\n    private String            destIndexName;\n\n    @ApiModelProperty(\"请求源ip\")\n    private String            remoteAddr;\n\n    @ApiModelProperty(\"所属集群\")\n    private String            clusterName;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/GatewayTemplateDeployInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * \n *\n * @author d06679\n * @date 2019/1/15\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板信息\")\npublic class GatewayTemplateDeployInfoVO extends BaseVO {\n\n    /**\n     * 模板基础信息\n     */\n    @ApiModelProperty(\"基本信息\")\n    private GatewayTemplateVO                     baseInfo;\n\n    /**\n     * 主模板独有的信息\n     */\n    @ApiModelProperty(\"master信息\")\n    private GatewayTemplatePhysicalDeployVO       masterInfo;\n\n    /**\n     * 从模板独有的信息\n     */\n    @ApiModelProperty(\"slave信息\")\n    private List<GatewayTemplatePhysicalDeployVO> slaveInfos;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/GatewayTemplatePhysicalDeployVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.Map;\nimport java.util.Set;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板信息\")\npublic class GatewayTemplatePhysicalDeployVO {\n\n    /**\n     * 模板名字\n     */\n    @ApiModelProperty(\"模板名字\")\n    private String                                          templateName;\n\n    /**\n     * 所在集群\n     */\n    @ApiModelProperty(\"所在集群\")\n    private String                                          cluster;\n\n    /**\n     * 是否是默认写索引标识\n     */\n    @ApiModelProperty(\"defaultWriterFlags\")\n    private Boolean                                         defaultWriterFlags;\n\n    /**\n     * 组ID\n     */\n    @ApiModelProperty(\"groupId\")\n    private String                                          groupId;\n\n    /**\n     * rack\n     */\n    @ApiModelProperty(\"rack\")\n    private String                                          rack;\n\n    /**\n     * shard个数\n     */\n    @ApiModelProperty(\"shard个数\")\n    private Integer                                         shardNum;\n\n    /**\n     * kafka topic\n     */\n    @ApiModelProperty(\"kafka-topic\")\n    private String                                          topic;\n\n    /**\n     * 能够查询的应用列表\n     */\n    @ApiModelProperty(\"能够查询的应用列表\")\n    private Set<Integer> accessProjects;\n\n    /**\n     * 用于索引多type改造   是否启用索引名称映射 0 禁用 1 启用\n     */\n    @ApiModelProperty(\"能够查询的app列表\")\n    private Boolean                                         mappingIndexNameEnable;\n\n    /**\n     * 多type索引type名称到单type索引模板名称的映射\n     */\n    @ApiModelProperty(\"type名称到索引的映射\")\n    private Map<String/*typeName*/, String/*templateName*/> typeIndexMapping;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/GatewayTemplatePhysicalVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Alias;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"物理模板信息\")\npublic class GatewayTemplatePhysicalVO extends BaseVO {\n\n    @ApiModelProperty(\"模板ID\")\n    private Long        id;\n\n    /**\n     * 索引模板名称\n     */\n    @ApiModelProperty(\"模板名称\")\n    private String      name;\n\n    /**\n     * 数据中心\n     */\n    @ApiModelProperty(\"数据中心\")\n    private String      dataCenter;\n\n    /**\n     * 表达式\n     */\n    @ApiModelProperty(\"表达式\")\n    private String      expression;\n\n    /**\n     * 版本号\n     */\n    @ApiModelProperty(\"版本\")\n    private Integer     version;\n\n    /**\n     * 别名\n     */\n    @ApiModelProperty(\"别名列表\")\n    private List<Alias> aliases;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/GatewayTemplateVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"基本信息\")\npublic class GatewayTemplateVO extends BaseVO {\n\n    /******************************* 逻辑信息 ********************************/\n    @ApiModelProperty(\"逻辑ID\")\n    private Integer      id;\n\n    /**\n     * 索引模板名称\n     */\n    @ApiModelProperty(\"索引模板名称\")\n    private String       name;\n\n    /**\n     * 数据中心\n     */\n    @ApiModelProperty(\"数据中心\")\n    private String       dataCenter;\n\n    /**\n     * 表达式\n     */\n    @ApiModelProperty(\"表达式\")\n    private String       expression;\n\n    /**\n     * 时间字段\n     */\n    @ApiModelProperty(\"时间字段\")\n    private String       dateField;\n\n    /**\n     * 时间字段的格式\n     */\n    @ApiModelProperty(\"时间字段的格式\")\n    private String       dateFieldFormat;\n\n    /**\n     * id字段\n     */\n    @ApiModelProperty(\"id字段\")\n    private String       idField;\n\n    /**\n     * routing字段\n     */\n    @ApiModelProperty(\"routing字段\")\n    private String       routingField;\n\n    /**\n     * 索引滚动格式\n     */\n    @ApiModelProperty(\"索引滚动格式\")\n    private String       dateFormat;\n\n    /**\n     * 数据保存时长 单位天\n     */\n    @ApiModelProperty(\"数据保存时长\")\n    private Integer      expireTime;\n\n    /**\n     * pipeline\n     */\n    @ApiModelProperty(\"pipeline\")\n    private String       ingestPipeline;\n\n    /******************************* 物理信息 ********************************/\n\n    /**\n     * 部署\n     */\n    @ApiModelProperty(\"部署状态\")\n    private Integer      deployStatus;\n\n    /**\n     * 版本号\n     */\n    @ApiModelProperty(\"版本号\")\n    private Integer      version;\n\n    /******************************* 别名 ********************************/\n\n    /**\n     * 别名\n     */\n    @ApiModelProperty(\"别名列表\")\n    private List<String> aliases;\n\n    /**\n     * 是否禁止读\n     */\n    private Boolean      blockRead;\n\n    /**\n     * 是否禁止写\n     */\n    private Boolean      blockWrite;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/IndexTemplatePhysicalVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"物理模板信息\")\npublic class IndexTemplatePhysicalVO extends BaseVO {\n\n    @ApiModelProperty(\"模板ID\")\n    private Long    id;\n\n    @ApiModelProperty(\"逻辑模板id\")\n    private Integer logicId;\n\n    @ApiModelProperty(\"逻辑模板id\")\n    private String  logicName;\n\n    @ApiModelProperty(\"模板名称\")\n    private String  name;\n\n    @ApiModelProperty(\"表达式\")\n    private String  expression;\n\n    @ApiModelProperty(\"物理集群名字\")\n    private String  cluster;\n\n    @ApiModelProperty(\"rack\")\n    private String  rack;\n\n    @ApiModelProperty(\"shard\")\n    private Integer shard;\n\n    @ApiModelProperty(\"shardRouting\")\n    private Integer shardRouting;\n\n    @ApiModelProperty(\"版本\")\n    private Integer version;\n\n    @ApiModelProperty(\"角色(1:主；2:从)\")\n    private Integer role;\n\n    @ApiModelProperty(\"状态(1:常规；-1:索引删除中；-2:删除)\")\n    private Integer status;\n\n    @ApiModelProperty(\"配置信息\")\n    private String  config;\n\n    @ApiModelProperty(\"描述信息\")\n    private String  memo;\n\n    @ApiModelProperty(\"regionId\")\n    private Integer regionId;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ProjectIdTemplateAccessCountVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.Map;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.experimental.Accessors;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/27 下午2:19\n * @modified By D10865\n *\n * projectid访问索引模板级别次数\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@Accessors(chain = true)\n@ApiModel(value = \"ProjectIdTemplateAccessCountVO\", description = \"projectId访问索引模板级别次数\")\npublic class ProjectIdTemplateAccessCountVO {\n\n    @ApiModelProperty(\"索引模板主键\")\n    private Integer                                                  templateId;\n\n    @ApiModelProperty(\"索引逻辑id\")\n    private Integer                                                  logicTemplateId;\n\n    @ApiModelProperty(\"索引模板名称\")\n    private String                                                   templateName;\n\n    @ApiModelProperty(\"集群名称\")\n    private String                                                   clusterName;\n\n    @ApiModelProperty(\"应用账号\")\n    private Integer                                                  projectId;\n    /**\n     * 访问索引模板次数，为@accessDetailInfo 访问索引明细的总次数\n     */\n    @ApiModelProperty(\"访问索引模板次数\")\n    private Long                                                     count;\n    /**\n     *访问索引名称明细数据,key不能是.开头，否则写入es失败\n     */\n    @ApiModelProperty(\"访问索引名称明细数据\")\n    private Map<String/*indexName*/, Long/*access indexName count*/> accessDetailInfo;\n\n    @ApiModelProperty(\"统计日期\")\n    private String                                                   date;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/SearchDslTemplateResponseVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/22 下午4:45\n * @modified By D10865\n *\n * 查询查询模板响应\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"SearchDslTemplateResponseVO\", description = \"查询查询模板响应\")\npublic class SearchDslTemplateResponseVO {\n\n    /**\n     * 查询模板集合\n     */\n    @ApiModelProperty(\"查询模板集合\")\n    private List<DslTemplateVO> records;\n\n    /**\n     * 查询命中记录数\n     */\n    @ApiModelProperty(\"查询命中记录数\")\n    private Long                totalHits;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/SinkSdkIDCTemplateDeployInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 多机房模板信息\n * @author wangshu\n * @date 2020/06/11\n */\n@Data\n@ApiModel(description = \"多机房模板信息\")\npublic class SinkSdkIDCTemplateDeployInfoVO extends BaseVO {\n    /**\n     * 模板基础信息\n     */\n    @ApiModelProperty(\"基本信息\")\n    private SinkSdkTemplateVO                              baseInfo;\n\n    @ApiModelProperty(\"多机房模板主从元数据信息\")\n    private Map<String, SinkSdkIDCTemplateMasterSlaveMeta> templateMasterSlaveMetas;\n\n    @Data\n    public static class SinkSdkIDCTemplateMasterSlaveMeta extends BaseVO {\n        /**\n         * 主模板独有的信息\n         */\n        @ApiModelProperty(\"master信息\")\n        private SinkSdkTemplatePhysicalDeployVO       masterInfo;\n\n        /**\n         * 从模板独有的信息\n         */\n        @ApiModelProperty(\"slave信息\")\n        private List<SinkSdkTemplatePhysicalDeployVO> slaveInfos;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/SinkSdkTemplateDeployInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * \n *\n * @author d06679\n * @date 2019/1/15\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板信息\")\npublic class SinkSdkTemplateDeployInfoVO extends BaseVO {\n\n    /**\n     * 模板基础信息\n     */\n    @ApiModelProperty(\"基本信息\")\n    private SinkSdkTemplateVO                     baseInfo;\n\n    /**\n     * 主模板独有的信息\n     */\n    @ApiModelProperty(\"master信息\")\n    private SinkSdkTemplatePhysicalDeployVO       masterInfo;\n\n    /**\n     * 从模板独有的信息\n     */\n    @ApiModelProperty(\"slave信息\")\n    private List<SinkSdkTemplatePhysicalDeployVO> slaveInfos;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/SinkSdkTemplatePhysicalDeployVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板信息\")\npublic class SinkSdkTemplatePhysicalDeployVO {\n\n    @ApiModelProperty(\"模板ID\")\n    private Long    physicalId;\n\n    @ApiModelProperty(\"模板名字\")\n    private String  templateName;\n\n    @ApiModelProperty(\"shardRouting\")\n    private Integer shardRouting;\n\n    @ApiModelProperty(\"所在集群\")\n    private String  cluster;\n\n    @ApiModelProperty(\"是否是默认写\")\n    private Boolean defaultWriterFlags;\n\n    @ApiModelProperty(\"组ID\")\n    private String  groupId;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/SinkSdkTemplateVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"基本信息\")\npublic class SinkSdkTemplateVO extends BaseVO {\n\n    /******************************* 逻辑信息 ********************************/\n    @ApiModelProperty(\"逻辑ID\")\n    private Integer id;\n\n    @ApiModelProperty(\"索引模板名称\")\n    private String  name;\n\n    @ApiModelProperty(\"数据中心\")\n    private String  dataCenter;\n\n    @ApiModelProperty(\"表达式\")\n    private String  expression;\n\n    @ApiModelProperty(\"时间字段\")\n    private String  dateField;\n\n    @ApiModelProperty(\"索引滚动格式\")\n    private String  dateFormat;\n\n    @ApiModelProperty(\"数据保存时长\")\n    private Integer expireTime;\n\n    @ApiModelProperty(\"pipeline\")\n    private String  ingestPipeline;\n\n    /******************************* 物理信息 ********************************/\n\n    @ApiModelProperty(\"部署状态\")\n    private Integer deployStatus;\n\n    @ApiModelProperty(\"版本号\")\n    private Integer version;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/TemplateCyclicalRollInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(value = \"TemplateCyclicalRollInfoVO\", description = \"索引分区信息\")\npublic class TemplateCyclicalRollInfoVO {\n\n    @ApiModelProperty(\"分区健康\")\n    private String health;\n\n    @ApiModelProperty(\"分区状态\")\n    private String status;\n\n    @ApiModelProperty(\"分区名字\")\n    private String index;\n\n    @ApiModelProperty(\"分区shard个数\")\n    private String pri;\n\n    @ApiModelProperty(\"分区副本个数\")\n    private String rep;\n\n    @ApiModelProperty(\"分区文档个数\")\n    private String docsCount;\n\n    @ApiModelProperty(\"分区文档删除个数\")\n    private String docsDeleted;\n\n    @ApiModelProperty(\"分区主分片存储大小\")\n    private String storeSize;\n\n    @ApiModelProperty(\"分区存储大小\")\n    private String priStoreSize;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/TemplateDCDRInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * Created by linyunan on 12/14/21\n */\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(value = \"TemplateDCDRInfoVO\", description = \"模板DCDR信息\")\npublic class TemplateDCDRInfoVO extends BaseVO {\n    @ApiModelProperty(\"是否开启dcdr链路\")\n    private Boolean dcdrFlag;\n\n    @ApiModelProperty(\"主集群名称\")\n    private String  masterClusterName;\n\n    @ApiModelProperty(\"从集群名称\")\n    private String  slaveClusterName;\n\n    @ApiModelProperty(\"主模板checkPoint\")\n    private Long    masterTemplateCheckPoint;\n\n    @ApiModelProperty(\"从模板checkPoint\")\n    private Long    slaveTemplateCheckPoint;\n\n    @ApiModelProperty(\"位点差\")\n    private Long    templateCheckPointDiff;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/TemplateHealthDegreeRecordVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(value = \"TemplateHealthDegreeRecordVO\", description = \"索引健康分\")\npublic class TemplateHealthDegreeRecordVO {\n\n    @ApiModelProperty(\"统计时间\")\n    private Long          timestamp;\n\n    @ApiModelProperty(\"逻辑模板Id\")\n    private Integer       logicTemplateId;\n\n    @ApiModelProperty(\"健康分\")\n    private Integer       healthDegree;\n\n    @ApiModelProperty(\"标签\")\n    List<TemplateLabelVO> labelPOS;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/TemplateLabelVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Date;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(value = \"TemplateLabelVO\", description = \"索引标签\")\npublic class TemplateLabelVO {\n\n    @ApiModelProperty(value = \"索引模板id\")\n    private Integer indexTemplateId;\n\n    @ApiModelProperty(value = \"标签id，有一定的规则\")\n    private String  labelId;\n\n    @ApiModelProperty(value = \"标签名称\")\n    private String  labelName;\n\n    @ApiModelProperty(value = \"标记时间\")\n    private Date    markTime;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/TemplateMappingVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.Field;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引schema信息\")\npublic class TemplateMappingVO extends BaseVO {\n\n    @ApiModelProperty(\"索引ID\")\n    private Integer                 id;\n\n    @ApiModelProperty(\"索引名字\")\n    private String                  name;\n\n    /**\n     * mapping信息 手动设置的\n     */\n    @ApiModelProperty(\"索引mapping列表信息\")\n    private List<Field>             fields;\n\n    @ApiModelProperty(\"索引mappingjson信息\")\n    private List<AriusTypeProperty> typeProperties;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/TemplateSettingVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author didi\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"索引模板Setting视图信息\")\npublic class TemplateSettingVO extends BaseVO {\n\n    @ApiModelProperty(\"索引ID\")\n    private Integer    logicId;\n\n    @ApiModelProperty(\"是否开启副本\")\n    private boolean    cancelCopy;\n\n    @ApiModelProperty(\"是否开启异步translog\")\n    private boolean    asyncTranslog;\n\n    @ApiModelProperty(\"分词器\")\n    private JSONObject analysis;\n\n    @ApiModelProperty(\"dynamic_templates设置\")\n    private JSONArray  dynamicTemplates;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/TemplateStatsInfoVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 索引的基本统计信息\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(value = \"TemplateStatsInfoVO\", description = \"模板的基本统计信息\")\npublic class TemplateStatsInfoVO {\n\n    @ApiModelProperty(value = \"模板id\")\n    private Long         templateId;\n\n    @ApiModelProperty(value = \"模板名称\")\n    private String       templateName;\n\n    @ApiModelProperty(value = \"索引模板健康分\")\n    private double       indexHealthDegree;\n\n    @ApiModelProperty(value = \"索引模板总存储容量\")\n    private double       store;\n\n    @ApiModelProperty(value = \"索引模板的Quota\")\n    private double       qutoa;\n\n    @ApiModelProperty(value = \"索引模板的成本\")\n    private double       cost;\n\n    @ApiModelProperty(value = \"索引模板的每日访问均值\")\n    private double       accessCountPreDay;\n\n    @ApiModelProperty(value = \"索引模板的文档总数\")\n    private long         docNu;\n\n    @ApiModelProperty(value = \"索引模板的昨日写入tps峰值\")\n    private double       writeTps;\n\n    /**\n     * 索引对应的topic\n     */\n    private List<String> topics = new ArrayList<>();\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/TemplateValueRecordVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(value = \"TemplateValueRecordVO\", description = \"索引的价值分\")\npublic class TemplateValueRecordVO {\n\n    @ApiModelProperty(value = \"统计时间\")\n    private Long    timestamp;\n\n    @ApiModelProperty(value = \"索引模板id\")\n    private Integer logicTemplateId;\n\n    @ApiModelProperty(value = \"价值\")\n    private Integer value;\n\n    @ApiModelProperty(value = \"访问量\")\n    private Long    accessCount;\n\n    @ApiModelProperty(value = \"大小G\")\n    private Double  sizeG;\n\n    @ApiModelProperty(value = \"逻辑集群\")\n    private String  logicCluster;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ThirdPartTemplateLogicWithMasterTemplateResourceVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterLogicVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"逻辑模板信息，携带master所在的逻辑集群信息\")\npublic class ThirdPartTemplateLogicWithMasterTemplateResourceVO extends ThirdpartTemplateLogicVO {\n\n    @ApiModelProperty(\"master模板\")\n    private IndexTemplatePhysicalVO masterTemplate;\n\n    @ApiModelProperty(\"master所在的逻辑集群信息\")\n    private ClusterLogicVO          masterResource;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ThirdpartTemplateLogicVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.Date;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"逻辑模板信息\")\npublic class ThirdpartTemplateLogicVO extends BaseVO {\n\n    @ApiModelProperty(\"模板ID\")\n    private Integer id;\n\n    @ApiModelProperty(\"模板名字\")\n    private String  name;\n\n    @ApiModelProperty(\"所属应用ID\")\n    private Integer projectId;\n\n    /**\n     * 用户数据类型\n     * @see DataTypeEnum\n     */\n    @ApiModelProperty(\"数据类型（0:系统 1:日志；2:上报；3:rds；6:离线）\")\n    private Integer dataType;\n\n    /**\n     * 索引滚动格式\n     */\n    @ApiModelProperty(\"分区周期\")\n    private String  dateFormat;\n\n    @ApiModelProperty(\"数据中心\")\n    private String  dataCenter;\n\n    /**\n     * 数据保存时长 单位天\n     */\n    @ApiModelProperty(\"保存天数\")\n    private Integer expireTime;\n\n    /**\n     * 热数据保存时长 单位天\n     */\n    @ApiModelProperty(\"热数据保存天数\")\n    private Integer hotTime;\n\n    \n\n   \n\n    @ApiModelProperty(\"时间字段\")\n    private String  dateField;\n\n    /**\n     * id地钻\n     */\n    @ApiModelProperty(\"主键字段：后续要下线无需使用\")\n    @Deprecated\n    private String  idField;\n\n    @ApiModelProperty(\"routing字段：后续下线，无需使用\")\n    @Deprecated\n    private String  routingField;\n\n    @ApiModelProperty(\"表达式\")\n    private String  expression;\n\n    @ApiModelProperty(\"描述\")\n    private String  desc;\n\n    /**\n     * 规格 单位台\n     */\n    @ApiModelProperty(\"配额\")\n    private Double  quota;\n\n    /**\n     * 创建时间\n     */\n    private Date    createTime;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ThirdpartTemplatePhysicalVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.IndexTemplatePhysicalConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author d06679\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"物理模板信息\")\npublic class ThirdpartTemplatePhysicalVO extends BaseVO {\n\n    @ApiModelProperty(\"模板ID\")\n    private Long                        id;\n\n    @ApiModelProperty(\"逻辑模板ID\")\n    private Integer                     logicId;\n\n    @ApiModelProperty(\"模板名字\")\n    private String                      name;\n\n    @ApiModelProperty(\"表达式\")\n    private String                      expression;\n\n    @ApiModelProperty(\"所属物理集群\")\n    private String                      cluster;\n\n    @ApiModelProperty(\"rack\")\n    private String                      rack;\n\n    @ApiModelProperty(\"shard\")\n    private Integer                     shard;\n\n    @ApiModelProperty(\"版本\")\n    private Integer                     version;\n\n    @ApiModelProperty(\"角色(1:主；2:从)\")\n    private Integer                     role;\n\n    @ApiModelProperty(\"状态(1:常规；-1:索引删除中；-2:删除)\")\n    private Integer                     status;\n\n    @ApiModelProperty(\"配置\")\n    private IndexTemplatePhysicalConfig configObj;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/ThirdpartTemplateVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.Date;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 包含物理和逻辑信息\n * @author d06679\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"模板信息\")\npublic class ThirdpartTemplateVO extends BaseVO {\n\n    /******************************* 物理信息 ********************************/\n\n    @ApiModelProperty(\"模板ID\")\n    private Long    id;\n\n    @ApiModelProperty(\"逻辑模板ID\")\n    private Integer logicId;\n\n    @ApiModelProperty(\"模板名字\")\n    private String  name;\n\n    @ApiModelProperty(\"所属物理集群\")\n    private String  cluster;\n\n    @ApiModelProperty(\"rack\")\n    private String  rack;\n\n    @ApiModelProperty(\"shard\")\n    private Integer shard;\n\n    @ApiModelProperty(\"版本\")\n    private Integer version;\n\n    @ApiModelProperty(\"角色(1:主；2:从)\")\n    private Integer role;\n\n    @ApiModelProperty(\"状态(1:常规；-1:索引删除中；-2:删除)\")\n    private Integer status;\n\n    @ApiModelProperty(\"配置\")\n    private String  config;\n\n    /******************************* 逻辑信息 ********************************/\n\n    @ApiModelProperty(\"所属应用ID\")\n    private Integer projectId;\n\n    /**\n     * 用户数据类型\n     * @see DataTypeEnum\n     */\n    @ApiModelProperty(\"数据类型（0:系统 1:日志；2:上报；3:rds；4:离线）\")\n    private Integer dataType;\n\n    /**\n     * 索引滚动格式\n     */\n    @ApiModelProperty(\"分区周期\")\n    private String  dateFormat;\n\n    @ApiModelProperty(\"数据中心\")\n    private String  dataCenter;\n\n    /**\n     * 数据保存时长 单位天\n     */\n    @ApiModelProperty(\"保存天数\")\n    private Integer expireTime;\n\n \n\n   \n\n    @ApiModelProperty(\"时间字段\")\n    private String  dateField;\n\n    /**\n     * id地钻\n     */\n    @ApiModelProperty(\"主键字段\")\n    private String  idField;\n\n    @ApiModelProperty(\"routing字段\")\n    private String  routingField;\n\n    @ApiModelProperty(\"表达式\")\n    private String  expression;\n\n    @ApiModelProperty(\"描述\")\n    private String  desc;\n\n    /**\n     * 规格 单位台\n     */\n    @ApiModelProperty(\"配额\")\n    private Double  quota;\n\n    @ApiModelProperty(\"创建时间\")\n    private Date    createTime;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/srv/TemplateSrvVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template.srv;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/19\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class TemplateSrvVO {\n\n    /**\n     * 模板服务code\n     */\n    private Integer srvCode;\n\n    /**\n     * 模板服务名称\n     */\n    private String  srvName;\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/srv/TemplateWithSrvVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.BaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterConnectionStatusWithTemplateVO;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/18\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@ApiModel(description = \"「模板服务」信息\")\npublic class TemplateWithSrvVO extends BaseVO {\n\n    @ApiModelProperty(\"模板ID\")\n    private Integer                        id;\n\n    @ApiModelProperty(\"模板名称\")\n    private String                         name;\n\n    @ApiModelProperty(\"所属集群\")\n    private List<String>                   cluster;\n\n    @ApiModelProperty(\"开启的服务\")\n    private List<TemplateSrvVO>            openSrv;\n\n    @ApiModelProperty(\"不可用的服务\")\n    private List<UnavailableTemplateSrvVO> unavailableSrv;\n\n    @ApiModelProperty(\"DCDR主从位点差\")\n    private Long                           checkPointDiff;\n\n    @ApiModelProperty(\"数据保存时长 单位天\")\n    private Integer                        expireTime;\n\n    @ApiModelProperty(\"热数据保存时长 单位天\")\n    private Integer                        hotTime;\n\n    @ApiModelProperty(\"项目名称 \")\n    private String                         projectName;\n\n    @ApiModelProperty(\"是否具有dcdr\")\n    private Boolean hasDCDR;\n\n    @ApiModelProperty(\"是否分区\")\n    private Boolean partition;\n    @ApiModelProperty(\"模版健康:-1：未知\")\n    private Integer health;\n\n    /**\n     * 是否禁读\n     */\n    @ApiModelProperty(\"是否禁读\")\n    private Boolean blockRead;\n\n    /**\n     * 是否禁写\n     */\n    @ApiModelProperty(\"是否禁写\")\n    private Boolean blockWrite;\n\n    /**\n     * 指示主集群的联通状态\n     */\n    @ApiModelProperty(value = \"主集群是否能够连通的标志的标志\",notes = \"清理，升版本，扩缩容接口使用\")\n    private List<ClusterConnectionStatusWithTemplateVO> clusterConnectionStatus;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/bean/vo/template/srv/UnavailableTemplateSrvVO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.bean.vo.template.srv;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author chengxiang\n * @date 2022/5/19\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class UnavailableTemplateSrvVO extends TemplateSrvVO {\n\n    /**\n     * 不可用原因\n     */\n    private String unavailableReason;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/component/BaseHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.component;\n\n/**\n * 基础handle标识, 搭配 BaseExtendFactory 使用\n *\n * @author linyunan\n * @date 2021-04-25\n */\npublic interface BaseHandle {\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/component/RestTool.java",
    "content": "\npackage com.didichuxing.datachannel.arius.admin.common.component;\n\nimport java.lang.reflect.Type;\nimport java.util.Map;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.client.RestTemplate;\nimport org.springframework.web.util.UriComponentsBuilder;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusJSON;\n\n/**\n *\n * @author jinbinbin\n * @version $Id: RestHelper.java, v 0.1 2018年09月19日 17:31 jinbinbin Exp $\n */\n@Component\n@Deprecated\npublic class RestTool {\n\n    private static final ILog LOGGER = LogFactory.getLog(RestTool.class);\n\n    @Autowired\n    private RestTemplate      restTemplate;\n\n    /**\n     * POST请求\n     * @param url 请求地址\n     * @param postBody 请求内容\n     * @param headers header\n     * @param resultType 返回类型\n     * @param <T> 泛型T\n     * @return\n     */\n    public <T> T postObjectWithRawContent(String url, Object postBody, HttpHeaders headers, Class<T> resultType) {\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(postBody, headers),\n            String.class);\n        return AriusJSON.toObject(result.getBody(), resultType);\n    }\n\n    /**\n     * POST请求\n     * @param url 请求地址\n     * @param request 请求内容\n     * @param responseType 期望返回的类型\n     * @param <T> 泛型T\n     * @return T \n     */\n    public <T> T postObjectWithJsonContent(String url, Object request, Type responseType) {\n        HttpHeaders jsonHead = getJsonContentHeaders();\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST,\n            new HttpEntity<Object>(AriusJSON.toString(request), jsonHead), String.class);\n        return AriusJSON.toObject(result.getBody(), responseType);\n    }\n\n    /**\n     * POST请求\n     * @param url 请求地址\n     * @param request 请求内容\n     * @param responseType 期望返回的类型\n     * @param <T> 泛型T\n     * @return T\n     */\n    public <T> T postObjectWithJsonContentAndHeader(String url, Map<String, String> headers, Object request,\n                                                    Type responseType) {\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST,\n            new HttpEntity<Object>(AriusJSON.toString(request), getJsonContentHeaders(headers)), String.class);\n        return AriusJSON.toObject(result.getBody(), responseType);\n    }\n\n    /**\n     * GET请求\n     * @param url 请求地址\n     * @param params 请求参数\n     * @param resultType 返回类型\n     * @param <T> 泛型T\n     * @return T\n     */\n    public <T> T getObjectWithJsonContent(String url, Map<String, ?> params, Type resultType) {\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET, null, String.class, params);\n        return AriusJSON.toObject(result.getBody(), resultType);\n    }\n\n    /**\n     * GET请求\n     * @param url 请求地址\n     * @param headers 请求头\n     * @param resultType 返回类型\n     * @param <T> 泛型T\n     * @return T\n     */\n    public <T> T getForObject(String url, HttpHeaders headers, Type resultType) {\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers),\n            String.class);\n        return AriusJSON.toObject(result.getBody(), resultType);\n    }\n\n    /**\n     * GET请求\n     * @param url 请求地址\n     * @param headers 请求头\n     * @param params 请求参数\n     * @param resultType 返回类型\n     * @param <T> 泛型T\n     * @return T\n     */\n    public <T> T getObjectWithParamsAndHeader(String url, Map<String, String> headers, Map<String, ?> params,\n                                              Type resultType) {\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET,\n            new HttpEntity<>(null, getJsonContentHeaders(headers)), String.class, params);\n        return AriusJSON.toObject(result.getBody(), resultType);\n    }\n\n    /**\n     * GET请求\n     * @param url 请求地址\n     * @param headers 请求头\n     * @param resultType 返回类型\n     * @param <T> 泛型T\n     * @return T\n     */\n    public <T> T getForObject(String url, Map<String, String> headers, Type resultType) {\n        try {\n            ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET,\n                new HttpEntity<>(null, getJsonContentHeaders(headers)), String.class);\n            return JSON.parseObject(result.getBody(), resultType);\n        } catch (Exception e) {\n            LOGGER.error(\"class=RestTool||method=getForObject||url={}||msg=exception!\", url, e);\n        }\n\n        return null;\n    }\n\n    /**\n     * GET请求\n     * @param url 请求地址\n     * @param headers 请求头\n     * @return T\n     */\n    public String getForString(String url, Map<String, String> headers) {\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET,\n            new HttpEntity<>(null, getJsonContentHeaders(headers)), String.class);\n        return result.getBody();\n    }\n\n    /**\n     * 根据map中的参数构建url+queryString\n     * @param url 请求地址\n     * @param params 请求参数\n     * @return  请求url\n     */\n    public static String getQueryString(String url, Map<String, ?> params) {\n        if (params == null) {\n            return url;\n        }\n        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);\n\n        return builder.toUriString();\n    }\n\n    /**\n     * DEL请求\n     * @param url 请求地址\n     */\n    public void deleteObject(String url) {\n        restTemplate.delete(url);\n    }\n\n    /**\n     * GET请求\n     * @param url 请求地址\n     * @param headers 请求头\n     * @param params 请求参数\n     * @param resultType 返回类型\n     * @param <T> 泛型T\n     * @return T\n     */\n    public <T> T deleteWithParamsAndHeader(String url, Map<String, String> headers, Map<String, ?> params,\n                                           Type resultType) {\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.DELETE,\n            new HttpEntity<>(params, getJsonContentHeaders(headers)), String.class);\n        return AriusJSON.toObject(result.getBody(), resultType);\n    }\n\n    /**\n     * GET请求  header中有application/json\n     * @param url 请求地址\n     * @param resultType 期望返回的类型\n     * @param <T> 泛型T\n     * @return T\n     */\n    public <T> T getObjectWithJsonContent(String url, Type resultType) {\n        HttpHeaders headers = getJsonContentHeaders();\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(null, headers),\n            String.class);\n        return AriusJSON.toObject(result.getBody(), resultType);\n    }\n\n    /**\n     * 构建 application/json header\n     * @return HttpHeaders\n     */\n    private HttpHeaders getJsonContentHeaders() {\n        HttpHeaders headers = new HttpHeaders();\n        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);\n        return headers;\n    }\n\n    /**\n     * 构建 application/json header\n     * @return HttpHeaders\n     */\n    private HttpHeaders getJsonContentHeaders(Map<String, String> headMap) {\n        HttpHeaders headers = new HttpHeaders();\n        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);\n        for (Map.Entry<String, String> entry : headMap.entrySet()) {\n            headers.add(entry.getKey(), entry.getValue());\n        }\n        return headers;\n    }\n\n    /**\n     * PUT请求 header中有application/json\n     * @param url 请求地址\n     * @param request 请求内容\n     * @param responseType 期望返回的类型\n     * @param <T> 泛型T\n     * @return T\n     */\n    public <T> T putJsonForObject(String url, Object request, Class<T> responseType) {\n        HttpHeaders jsonHead = getJsonContentHeaders();\n        ResponseEntity<T> responseEntity = restTemplate.exchange(url, HttpMethod.PUT,\n            new HttpEntity<Object>(AriusJSON.toString(request), jsonHead), responseType);\n        return responseEntity.getBody();\n    }\n\n    /**\n     * PUT请求\n     * @param url 请求地址\n     * @param request 请求内容\n     * @param responseType 期望返回的类型\n     * @param <T> 泛型T\n     * @return T\n     */\n    public <T> T putForObject(String url, Object request, Type responseType) {\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.PUT,\n            new HttpEntity<>(AriusJSON.toString(request)), String.class);\n        return AriusJSON.toObject(result.getBody(), responseType);\n    }\n\n    /**\n     * POST请求\n     * @param url 请求地址\n     * @param request 请求内容\n     * @param responseType 期望返回的类型\n     * @param <T> 泛型T\n     * @return T\n     */\n    public <T> T putObjectWithJsonContentAndHeader(String url, Map<String, String> headers, Object request,\n                                                   Type responseType) {\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.PUT,\n            new HttpEntity<Object>(AriusJSON.toString(request), getJsonContentHeaders(headers)), String.class);\n        return AriusJSON.toObject(result.getBody(), responseType);\n    }\n\n    /**\n     * GET请求\n     * @param url 请求地址\n     * @param headers 请求头\n     * @param resultType 返回类型\n     * @param <T> 泛型T\n     * @return T\n     * */\n    public <T> T deleteForObject(String url, Map<String, String> headers, Type resultType) {\n        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET,\n            new HttpEntity<>(null, getJsonContentHeaders(headers)), String.class);\n        return AriusJSON.toObject(result.getBody(), resultType);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/AdminConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\nimport com.didiglobal.knowframework.log.util.HostUtil;\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n *\n * 工程常量\n *\n * 如果配置的量过多,需要拆解\n *\n */\npublic class AdminConstant {\n\n    private AdminConstant() {\n    }\n\n//    public static final String       DEFAULT_TYPE                            = \"type\";\n\n    public static final String       DEFAULT_INDEX_MAPPING_TYPE              = \"_doc\";\n    public static final String INDEX_NUMBER_OF_SHARDS = \"index.number_of_shards\";\n    public static final String       DEFAULT_DYNAMIC_TEMPLATES_KEY           = \"dynamic_templates\";\n//    public static final String       SINGLE_TYPE_KEY                         = \"index.mapping.single_type\";\n//    public static final String       DEFAULT_SINGLE_TYPE                     = \"true\";\n\n    public static final String       HOST_NAME                               = HostUtil.getHostName();\n\n    public static final Integer      YES                                     = 1;\n\n    public static final Integer      NO                                      = 0;\n\n    public static final Integer      NOT_EXPIRE                              = -1;\n\n    public static final Double       BYTE_TO_G                               = 1.0 / (1024 * 1024 * 1024);\n\n    public static final Double       BYTE_TO_MB                              = 1.0 / (1024 * 1024);\n\n    public static final Double       TO_W                                    = 1.0 / 10000;\n\n    public static final Double       G_PER_SHARD                             = 50.0;\n\n    public static final String       COMMA                                   = \",\";\n\n    /**\n     * 默认的插件版本\n     */\n    public static final String       DEFAULT_PLUGIN_VERSION                  = \"0.0.0.1\";\n\n    public static final Long         MILLIS_PER_DAY                          = 24 * 60 * 60 * 1000L;\n\n    public static final String       MM_DD_DATE_FORMAT                       = \"MMdd\";\n    public static final String       YY_MM_DD_DATE_FORMAT                    = \"_yyyy-MM-dd\";\n    public static final String       YY_MM_DATE_FORMAT                       = \"_yyyy-MM\";\n\n    public static final Integer      PIPELINE_RATE_LIMIT_MAX_VALUE           = 1000000;\n    public static final Integer      PIPELINE_RATE_LIMIT_MIN_VALUE           = 1000;\n\n    /**\n     * 默认写标识\n     */\n    public static final Boolean      DEFAULT_WRITER_FLAGS                    = true;\n\n    /**\n     * 默认组ID\n     */\n    public static final String       DEFAULT_GROUP_ID                        = \"DEFAULT_GROUP_ID\";\n\n    /**\n     * 校验模板mappings or settings信息前缀\n     */\n    public static final String       ES_CHECK_TEMPLATE_INDEX_PREFIX          = \"check_template_\";\n\n    /**\n     * 版本为2.3.3版本的ES物理集群列表\n     */\n    public static final List<String> LOW_VERSION_ES_CLUSTER                  = Arrays.asList(\"bigdata-arius-olap\",\n        \"bigdata-arius-arcs\", \"mtn-to-es\", \"kefu-es\", \"DSearch_cluster_py\");\n\n    /**\n     * 数据最短保存时长\n     */\n    public static final int          PLATFORM_EXPIRE_TIME_MIN                = 2;\n    public static final int          PLATFORM_HOT_TIME_MIN                   = 1;\n    public static final int          PLATFORM_DELETED_TEMPLATE_EXPIRED_TIME  = 7;\n\n    /**\n     * 默认物理Client集群Http服务端口号\n     */\n    public static final Integer      DEFAULT_PHYSIC_CLUSTER_HTTP_SERVER_PORT = 8060;\n\n    public static final String       CLIENT_CLUSTER_HEALTH_CHECK_SUFFIX      = DEFAULT_PHYSIC_CLUSTER_HTTP_SERVER_PORT\n                                                                               + \"/_cluster/health?pretty\";\n\n    public static boolean yesOrNo(int config) {\n        return config == YES || config == NO;\n    }\n\n    /**\n     * region没有被绑定到逻辑集群时的逻辑集群ID字段值\n     */\n    public static final String  REGION_NOT_BOUND_LOGIC_CLUSTER_ID = \"-1\";\n\n    public static final String  JOB_SUCCESS                       = \"success\";\n    public static final String  JOB_FAILED                        = \"failed\";\n\n    /**\n     * 端口号绑定的上限和下限数值\n     */\n    public static final Integer MAX_BIND_PORT_VALUE               = 65535;\n    public static final Integer MIN_BIND_PORT_VALUE               = 1;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/AdminESOpRetryConstants.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * Admin操作ES底层引擎重试常量\n * @author wangshu\n * @date 2020/08/24\n */\npublic class AdminESOpRetryConstants {\n\n    private AdminESOpRetryConstants() {\n    }\n\n    /**\n     * 默认重试次数\n     */\n    public static final int DEFAULT_RETRY_COUNT = 3;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ApiVersion.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * @author d06679\n * @date 2019/4/24\n */\npublic class ApiVersion {\n\n    private ApiVersion() {\n    }\n\n    public static final String V1            = \"/v1\";\n\n    public static final String V2            = \"/v2\";\n\n    public static final String V3            = \"/v3\";\n    public static final String V3_SECURITY   = \"/v3/security\";\n\n    public static final String V2_OP         = \"/v2/op\";\n\n    public static final String V3_OP         = \"/v3/op\";\n\n    public static final String V2_CONSOLE    = \"/v2/console\";\n\n    public static final String V3_NORMAL     = \"/v3/normal\";\n\n    public static final String V2_THIRD_PART = \"/v2/thirdpart\";\n\n    public static final String V3_THIRD_PART = \"/v3/thirdpart\";\n\n    public static final String V3_WHITE_PART = \"/v3/white\";\n\n    public static final String HEALTH        = \"/health\";\n    public static final String V3_PROJECT    = \"/v3/project\";\n\n    public static final String SWAGGER       = \"swagger\";\n    public static final String SWAGGER_UI    = \"swagger-ui.html\";\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/AriusConfigConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * 工程常量\n * <p>\n * 如果配置的量过多,需要拆解\n *\n * @author d06679\n * @date 2018/5/24\n */\npublic class AriusConfigConstant {\n\n    private AriusConfigConstant() {\n    }\n\n    /**\n     * arius的common配置组\n     */\n    public static final String ARIUS_COMMON_GROUP                                      = \"arius.common.group\";\n\n    /**\n     * 操作记录保存时间\n     */\n    public static final String  OPERATE_RECORD_SAVE_TIME                           = \"operate.record.save_time\";\n\n    /**\n     * DSL和kibana操作记录保存条数\n     */\n    public static final String OPERATE_RECORD_SAVE_NUM                         = \"operate.record.save.num\";\n\n    /**\n     * 超级应用默认就有的命令\n     */\n    public static final String SUPER_APP_DEFALT_DSL_COMMAND                         = \"super_app.default.dsl.command\";\n\n    /**\n     * 集群版本列表\n     */\n    public static final String CLUSTER_PACKAGE_VERSION_LIST                            = \"cluster.package.version_list\";\n\n    /**\n     * 数据中心列表\n     */\n    public static final String CLUSTER_DATA_CENTER_LIST                                = \"cluster.data.center_list\";\n\n    /**\n     * 集群资源列表\n     */\n    public static final String CLUSTER_RESOURCE_TYPE_LIST                              = \"cluster.resource.type_list\";\n\n    /**\n     * 节点数量列表\n     */\n    public static final String CLUSTER_NODE_COUNT_LIST                                 = \"cluster.node.count_list\";\n\n    /**\n     * 节点规格列表\n     */\n    public static final String CLUSTER_NODE_SPECIFICATION_LIST                         = \"cluster.node.specification_list\";\n\n\n    /**\n     * 请求是否拦截鉴权\n     */\n    public static final String REQUEST_INTERCEPTOR_SWITCH_OPEN                         = \"request.interceptor.is_switch_open\";\n\n    /**\n     * meta监控配置组\n     */\n    public static final String ARIUS_META_MONITOR_GROUP                                = \"arius.meta.monitor.group\";\n\n    /**\n     * 节点是否并行获取\n     */\n    public static final String NODE_STAT_COLLECT_CONCURRENT                            = \"node.stat.is_collect_concurrent\";\n\n    /**\n     * 索引是否并行获取\n     */\n    public static final String INDEX_STAT_COLLECT_CONCURRENT                           = \"index.stat.is_collect_concurrent\";\n\n\n    /**\n     * arius的template配置组\n     */\n    public static final String  ARIUS_TEMPLATE_GROUP                                      = \"arius.template.group\";\n\n    /**\n     * 模板业务类型\n     */\n    public static final String LOGIC_TEMPLATE_BUSINESS_TYPE_LIST                       = \"logic.template.business_type\";\n\n    /**\n     * 模板时间格式列表\n     */\n    public static final String LOGIC_TEMPLATE_TIME_FORMAT_LIST                         = \"logic.template.time_format_list\";\n\n    /**\n     * 历史索引模板shard分配是否自动调整\n     */\n    public static final String HISTORY_TEMPLATE_PHYSIC_INDICES_ALLOCATION_IS_EFFECTIVE = \"history.template.physic.indices.allocation.is_effective\";\n\n\n    /**\n     * dashboard阈值配置组\n     */\n    public static final String ARIUS_DASHBOARD_THRESHOLD_GROUP                         = \"arius.dashboard.threshold.group\";\n\n\n    /**\n     * 小Shard列表阈值定义(小Shard索引列表)\n     */\n    public static final String INDEX_SHARD_SMALL_THRESHOLD                             = \"index.shard.small_threshold\";\n\n    /**\n     * 节点分片个数(节点分片个数大于>500)\n     */\n    public static final String NODE_SHARD_NUM_THRESHOLD = \"node.shard.num_threshold\";\n\n    /**\n     * 索引模板Segment内存大小列表阈值定义\n     */\n    public static final String INDEX_TEMPLATE_SEGMENT_MEMORY_SIZE_THRESHOLD            = \"index.template.segment_memory_size_threshold\";\n\n    /**\n     * 索引Segment内存大小列表阈值定义\n     */\n    public static final String INDEX_SEGMENT_MEMORY_SIZE_THRESHOLD                     = \"index.segment.memory_size_threshold\";\n\n    /**\n     * 索引模板Segment个数阈值定义(索引模板Segments个数超过1000)\n     */\n    public static final String INDEX_TEMPLATE_SEGMENT_COUNT_THRESHOLD                  = \"index.template.segment_num_threshold\";\n\n    /**\n     * 索引Segment个数阈值定义(索引Segments个数超过阀值100)\n     */\n    public static final String INDEX_SEGMENT_NUM_THRESHOLD                             = \"index.segment.num_threshold\";\n\n    /**\n     * 索引Mapping个数阈值定义\n     */\n    public static final String INDEX_MAPPING_NUM_THRESHOLD                             = \"index.mapping.num_threshold\";\n\n    /**\n     * 采集延时阈值定义\n     */\n    public static final String DASHBOARD_CLUSTER_METRIC_COLLECTOR_DELAYED_THRESHOLD = \"cluster.metric.collector.delayed_threshold \";\n    /**\n     * 磁盘利用率超红线阈值\n     */\n    public static final String NODE_DISK_USED_PERCENT_THRESHOLD = \"node.disk.used_percent_threshold\";\n    /**\n     * 堆内存利用率超红线阈值\n     */\n    public static final String NODE_LARGE_HEAD_USAGE_PERCENT_THRESHOLD                 = \"node.jvm.heap.used_percent_threshold\";\n    /**\n     * 堆内存利用率持续时间红线\n     */\n    public static final String NODE_LARGE_HEAD_USED_PERCENT_TIME_USAGE_THRESHOLD      = \"node.jvm.heap.used_percent_time_duration_threshold\";\n    /**\n     * CPU利用率超红线\n     */\n    public static final String NODE_LARGE_CPU_USAGE_PERCENT_THRESHOLD                  = \"node.cpu.used_percent_threshold\";\n    /**\n     * cpu利用率持续时间超红线阈值\n     */\n    public static final String NODE_CPU_USED_PERCENT_THRESHOLD_TIME_DURATION_THRESHOLD = \"node.cpu.used_percent_threshold_time_duration_threshold\";\n    /**\n     * 大Shard列表阈值定义(大Shard索引列表)\n     */\n    public static final String INDEX_SHARD_BIG_THRESHOLD                              = \"index.shard.big_threshold\";\n\n\n    /**\n     * rollover阈值，当索引大小超过该值自动rollover\n     */\n    public static final String INDEX_ROLLOVER_THRESHOLD                                = \"index.rollover.threshold\";\n\n    /**\n     * 大shard阈值，用于集群指标看板，超过该值被认为是大shard\n     */\n    public static final String BIG_SHARD_THRESHOLD                                     = \"cluster.shard.big_threshold\";\n\n    /**\n     * 集群shard数阈值\n     */\n    public static final String CLUSTER_SHARD_NUM_THRESHOLD                             = \"cluster.shard.num_threshold\";\n\n\n    /**\n     * 模板冷热配置组\n     */\n    public static final String ARIUS_TEMPLATE_COLD_GROUP                               = \"arius.template.cold.group\";\n\n    /**\n     * 索引模板默认冷存天数\n     */\n    public static final String INDEX_TEMPLATE_COLD_DAY_DEFAULT                         = \"index.template.default_cold_day\";\n\n    /**\n     * default value\n     */\n    /**\n     * 请求是否拦截鉴权\n     */\n    public static final Boolean REQUEST_INTERCEPTOR_SWITCH_OPEN_DEFAULT_VALUE         = Boolean.TRUE;\n    /**\n     * 操作记录的保存时间\n     */\n    public static final Integer OPERATE_RECORD_SAVE_TIME_DEFAULT_VALUE                = 30;\n    /**\n     * DSL和kibana操作记录保存条数\n     */\n    public static final Integer OPERATE_RECORD_SAVE_NUM_DEFAULT_VALUE                = 30;\n    /**\n     * 索引模板默认冷存天数默认值\n     */\n    public static final String INDEX_TEMPLATE_COLD_DAY_DEFAULT_VALUE                   = \"-1\";\n    /**\n     * 历史索引模板shard分配是否自动调整\n     */\n    public static final boolean HISTORY_TEMPLATE_PHYSIC_INDICES_ALLOCATION_IS_EFFECTIVE_DEFAULT_VALUE = true;\n    public static final String CLUSTER_PACKAGE_VERSION_LIST_DEFAULT_VALUE              = \"7.6.2,7.6.0,7.6.0.1400,6.6.1.900\";\n\n    public static final String CLUSTER_DATA_CENTER_LIST_DEFAULT_VALUE                  = \"cn,en\";\n\n    public static final String CLUSTER_RESOURCE_TYPE_LIST_DEFAULT_VALUE                = \"信创,ACS,VMWARE\";\n\n    public static final String CLUSTER_NODE_COUNT_LIST_DEFAULT_VALUE                   = \"2,4,6,8,10,20\";\n\n    public static final String LOGIC_TEMPLATE_TIME_FORMAT_LIST_DEFAULT_VALUE           = \"yyyy-MM-dd HH:mm:ss,yyyy-MM-dd HH:mm:ss.SSS,yyyy-MM-dd HH:mm:ss.SSS Z,\" +\n            \"                                                                               yyyy-MM-dd'T'HH:mm:ss,yyyy-MM-dd'T'HH:mm:ss.SSS,yyyy-MM-dd'T'HH:mm:ssZ,yyyy-MM-dd'T'HH:mm:ss.SSSZ,yyyy/MM/dd HH:mm:ss,epoch_second,epoch_millis,yyyy-MM-dd\";\n\n    public static final String LOGIC_TEMPLATE_BUSINESS_TYPE_LIST_DEFAULT_VALUE         = \"系统数据,日志数据,业务上报数据,RDS数据,离线导入数据\";\n\n    public static final String CLUSTER_NODE_SPECIFICATION_LIST_DEFAULT_VALUE           = \"16c-64g-3072g,16c-48g-3072g\";\n\n    public static final String SUPER_APP_DEFALT_DSL_COMMAND_VALUE           = \"#获取节点状态\\nGET /_nodes/stats,\\n\" +\n                \"#获取集群信息\\nGET _cluster/stats,\\n\" +\n                \"#获取集群健康信息\\nGET _cluster/health?v,\\n\" +\n                \"#查看当前集群的热点线程\\nGET _nodes/hot_threads,\\n\" +\n                \"#查看当前集群运行中的任务信息\\nGET _tasks?actions=*&detailed,\\n\" +\n                \"#shard分配说明，会在分片未分配的事后去通过这个命令查看下具体原因\\nGET /_cluster/allocation/explain,\\n\" +\n                \"#异常shard分配重试，当集群red有shard未分配的情况下会通过这个命令来重试分配\\nPOST /_cluster/reroute?retry_failed=true,\\n\" +\n                \"#清除fielddata内存，当集群因为fileddata太大导致熔断或占用很多内存，可以通过此命令释放内存\\nPOST _cache/clear?fielddata=true\";\n\n    /**\n     * 节点状态并发采集\n     */\n    public static final boolean NODE_STAT_COLLECT_CONCURRENT_DEFAULT_VALUE              = false;\n\n    /**\n     * 索引状态并发采集\n     */\n    public static final boolean INDEX_STAT_COLLECT_CONCURRENT_DEFAULT_VALUE             = false;\n\n    /**\n     * 采集延时阈值定义\n     */\n    public static final String DASHBOARD_CLUSTER_METRIC_COLLECTOR_DELAYED_DEFAULT_VALUE                         = \"{\\\"name\\\":\\\"cluster.metric.collector.delayed_threshold\\\",\\\"metrics\\\":\\\"clusterMetricCollectorTimeDelayMin\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":5}\";\n\n    /**\n     * dashboard节点CPU利用率超阈值的[持续时间]默认值\n     */\n    public static final String DASHBOARD_NODE_CPU_USED_PERCENT_THRESHOLD_TIME_DURATION_THRESHOLD_DEFAULT_VALUE = \"{\\\"name\\\":\\\"node.cpu.used_percent_threshold_time_duration\\\",\\\"metrics\\\":\\\"cpuUsedPercentThresholdTimeDuration\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":5}\";\n    /**\n     * dashboardCPU利用率红线默认值\n     */\n    public static final String DASHBOARD_CPU_PERCENT_THRESHOLD_DEFAULT_VALUE                                   = \"{\\\"name\\\":\\\"node.cpu.used_percent_threshold\\\",\\\"metrics\\\":\\\"cpuUsedPercentThreshold\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":60}\";\n\n    /**\n     * dashboard内存利用率持续时间红线默认值\n     */\n    public static final String DASHBOARD_LARGE_HEAD_USED_PERCENT_TIME_DEFAULT_VALUE                            = \"{\\\"name\\\":\\\"node.jvm.heap.used_percent_threshold_time_duration_threshold\\\",\\\"metrics\\\":\\\"jvmHeapUsedPercentThresholdTimeDuration\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":10}\";\n    /**\n     * dashboard堆内存利用率超红线阈值默认值\n     */\n    public static final String DASHBOARD_HEAD_USED_PERCENT_THRESHOLD_DEFAULT_VALUE                             = \"{\\\"name\\\":\\\"node.jvm.heap.used_percent_threshold\\\",\\\"metrics\\\":\\\"jvmHeapUsedPercentThreshold\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":75}\";\n\n    /**\n     * 磁盘利用率超红线阈值默认值\n     */\n    public static final String DASHBOARD_NODE_DISK_USED_PERCENT_THRESHOLD_DEFAULT_VALUE                        = \"{\\\"name\\\":\\\"node.disk.used_percent_threshold\\\",\\\"metrics\\\":\\\"diskUsedPercentThreshold\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":80}\";\n\n    /**\n     * 索引Segment个数阈值默认值\n     */\n    public static final String DASHBOARD_INDEX_SEGMENT_NUM_THRESHOLD_DEFAULT_VALUE                             = \"{\\\"name\\\":\\\"index.segment.num_threshold\\\",\\\"metrics\\\":\\\"segmentNum\\\",\\\"unit\\\":\\\"个\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":100}\";\n    /**\n     * 索引模板Segment个数阈值定义默认值\n     */\n    public static final String DASHBOARD_INDEX_TEMPLATE_SEGMENT_COUNT_THRESHOLD_DEFAULT_VALUE                  = \"{\\\"name\\\":\\\"index.template.segment_num_threshold\\\",\\\"metrics\\\":\\\"segmentNum\\\",\\\"unit\\\":\\\"个\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":700}\";\n    /**\n     * 索引Segment内存大小列表阈值定义默认值\n     */\n    public static final String DASHBOARD_INDEX_SEGMENT_MEMORY_SIZE_THRESHOLD_DEFAULT_VALUE                     = \"{\\\"name\\\":\\\"index.segment.memory_size_threshold\\\",\\\"metrics\\\":\\\"segmentMemSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":500}\";\n    /**\n     * 索引模板Segment内存大小列表阈值定义默认值\n     */\n    public static final String DASHBOARD_INDEX_TEMPLATE_SEGMENT_MEMORY_SIZE_THRESHOLD_DEFAULT_VALUE            = \"{\\\"name\\\":\\\"index.template.segment.memory_size_threshold\\\",\\\"metrics\\\":\\\"segmentMemSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":3000}\";\n    /**\n     * 大Shard列表阈值定义(大Shard索引列表)默认值\n     */\n    public static final String DASHBOARD_INDEX_SHARD_BIG_THRESHOLD_DEFAULT_VALUE                               = \"{\\\"name\\\":\\\"index.shard.big_threshold\\\",\\\"metrics\\\":\\\"shardSize\\\",\\\"unit\\\":\\\"GB\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":20}\";\n    /**\n     * 小Shard列表阈值定义(小Shard索引列表)默认值\n     */\n    public static final String DASHBOARD_INDEX_SHARD_SMALL_THRESHOLD_DEFAULT_VALUE                             = \"{\\\"name\\\":\\\"index.shard.small_threshold\\\",\\\"metrics\\\":\\\"shardSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\"<\\\",\\\"value\\\":1000}\";\n    /**\n     * 索引Mapping个数阈值定义默认值\n     */\n    public static final String DASHBOARD_INDEX_MAPPING_NUM_THRESHOLD_DEFAULT_VALUE                             = \"{\\\"name\\\":\\\"index.mapping.num_threshold\\\",\\\"metrics\\\":\\\"mappingNum\\\",\\\"unit\\\":\\\"个\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":100}\";\n    /**\n     * 集群shard数阈值默认值\n     */\n    public static final String DASHBOARD_CLUSTER_SHARD_NUM_THRESHOLD_DEFAULT_VALUE                            = \"{\\\"name\\\":\\\"cluster.shard.num_threshold\\\",\\\"metrics\\\":\\\"shardNum\\\",\\\"unit\\\":\\\"个\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":2000}\";\n    /**\n     * 节点分片个数(节点分片个数大于>500)\n     */\n    public static final String DASHBOARD_NODE_SHARD_NUM_THRESHOLD_DEFAULT_VALUE                               = \"{\\\"name\\\":\\\"node.shard.num_threshold\\\",\\\"metrics\\\":\\\"shardNum\\\",\\\"unit\\\":\\\"个\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":1000}\";\n    /**\n     * 集群大shard阈值定义\n     */\n    public static final double BIG_SHARD                                                                      = 10d;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/AriusStatsEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/3/11 下午2:19\n * @modified By D10865\n *\n * 不同维度的es监控数据\n */\npublic enum AriusStatsEnum {\n\n                            /**\n                             * 索引维度\n                             */\n                            INDEX_INFO(\"index_info\"),\n\n                            /**\n                             * 节点到索引维度\n                             */\n                            NODE_INDEX_INFO(\"node_index_info\"),\n\n                            /**\n                             * 索引到节点维度\n                             */\n                            INDEX_NODE_INFO(\"index_node_info\"),\n\n                            /**\n                             * 节点维度\n                             */\n                            NODE_INFO(\"node_info\"),\n\n                            /**\n                             * ingest写入维度\n                             */\n                            INGEST_INFO(\"ingest_info\"),\n\n                            /**\n                             * 集群维度\n                             */\n                            CLUSTER_INFO(\"cluster_info\"),\n\n                            /**\n                             * task维度\n                             */\n                            TASK_INFO(\"task_info\"),\n\n                            /**\n                             * dcdr维度\n                             */\n                            DCDR_INFO(\"dcdr_info\"),\n\n                            /**\n                             * dashboard\n                             */\n                            DASHBOARD_INFO(\"dashboard_info\");\n\n    private String type;\n\n    AriusStatsEnum(String type) {\n        this.type = type;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public static AriusStatsEnum valueOfType(String type) {\n        if (type == null) {\n            return null;\n        }\n        for (AriusStatsEnum infoType : AriusStatsEnum.values()) {\n            if (infoType.getType().equals(type)) {\n                return infoType;\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/AuthConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\nimport lombok.NoArgsConstructor;\n\n/**\n * 权限相关\n *\n * @author shizeying\n * @date 2022/05/27\n * @since 0.3.0\n */\n@NoArgsConstructor\npublic final class AuthConstant {\n    /**\n     * 超级项目\n     */\n    public static final Integer SUPER_PROJECT_ID                     = 1;\n\n    /**\n     * 管理角色id\n     */\n    public static final Integer ADMIN_ROLE_ID                        = 1;\n    /**\n     * 资源own role 角色id\n     */\n    public static final Integer RESOURCE_OWN_ROLE_ID                 = 2;\n    public static final String  GATEWAY_GET_PROJECT_TICKET           = \"xTc59aY72\";\n    public static final String  GATEWAY_GET_PROJECT_TICKET_NAME      = \"X-ARIUS-GATEWAY-TICKET\";\n    public static final String  GET_USER_PROJECT_ID_LIST_TICKET      = \"xTc59aY72\";\n    public static final String  GET_USER_PROJECT_ID_LIST_TICKET_NAME = \"X-ARIUS-APP-TICKET\";\n    /**\n     * 默认元数据项目id\n     */\n    public static final Integer DEFAULT_METADATA_PROJECT_ID          = 2;\n    /**\n     * 非超级项目无权限\n     */\n    public static final String PROJECT_WITHOUT_PERMISSION = \"非超级项目无权限\";\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ClusterConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * @author zengqiao\n * @date 20/10/26\n */\npublic class ClusterConstant {\n\n    private ClusterConstant() {\n    }\n\n    /**\n     * 初始化id\n     */\n    public static final Long    INVALID_VALUE                   = -1L;\n\n    /**\n     * 集群默认HttpAddress\n     */\n    public static final String  DEFAULT_HTTP_ADDRESS            = \"127.0.0.1:9200\";\n\n    /**\n     * 集群完成状态\n     */\n    public static final String  CLOUD_DONE_STATUS               = \"done\";\n\n    /**\n     * 集群失败状态\n     */\n    public static final String  CLOUD_FAILED_STATUS             = \"failed\";\n\n    /**\n     * odin集群状态同步最大重试次数\n     */\n    public static final Integer SYN_ODIN_STATUS_MAX_RETRY_TIMES = 1 << 7;\n\n    /**\n     * 集群默认服务\n     */\n    public static final String  DEFAULT_CLUSTER_TEMPLATE_SRVS   = \"\";\n\n    /**\n     * 集群默认机房\n     */\n    public static final String  DEFAULT_CLUSTER_IDC             = \"ys02\";\n\n    public static final Integer DEFAULT_CLUSTER_HEALTH          = 2;\n\n    /**\n     * 集群默认实例数\n     */\n    public static final Integer DEFAULT_CLUSTER_PAID_COUNT      = 1;\n\n    /**\n     * 集群默认规格\n     */\n    public static final String  DEFAULT_CLUSTER_NODE_SPEC       = \"\";\n\n    /**\n     * 接入集群master角色节点最小数量\n     */\n    public static final Integer JOIN_MASTER_NODE_MIN_NUMBER     = 1;\n\n    /**\n     * 创建集群master角色节点最小数量\n     */\n    public static final Integer CREATE_MASTER_NODE_MIN_NUMBER   = 1;\n\n    /**\n     * 物理集群标识\n     */\n    public static final Integer PHY_CLUSTER                     = 1;\n\n    /**\n     * 逻辑集群标识\n     */\n    public static final Integer LOGIC_CLUSTER                   = 0;\n\n    /**\n     * 所有集群Str\n     */\n    public static final String  ALL_CLUSTER                     = \"allCluster\";\n\n    /**\n     * client运行模式（0：读写共享 1：读写分离）\n     */\n    public static final Integer DEFAULT_RUN_MODEL               = 0;\n\n    /**\n     * 默认可用端口号\n     */\n    public static final String  DEFAULT_PORT                    = \"8060\";\n\n    /**\n     * 间隔时间, 一小时内\n     */\n    public static final long    DEFAULT_TIME_INTERVAL           = 24 * 60 * 60 * 1000L;\n\n    public static final long    MAX_TIME_INTERVAL               = 7 * 24 * 60 * 60 * 1000L;\n\n    /**\n     * 集群读写地址连接重试次数和重试间隔睡眠时间\n     */\n    public static final int     DEFAULT_RETRY_TIME_INTERVAL     = 5000;\n\n    public static Integer defaultRetryTime(int retryTimes) {\n        return DEFAULT_RETRY_TIME_INTERVAL;\n    }\n\n    public static final int DEFAULT_RETRY_TIMES = 24;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ClusterPhyMetricsConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * Created by linyunan on 2021-08-10\n */\npublic class ClusterPhyMetricsConstant {\n\n    private ClusterPhyMetricsConstant() {\n    }\n\n    /*****************************************构建dsl相关常量***************************************/\n\n    public static final String VALUE         = \"value\";\n\n    public static final String VALUES        = \"values\";\n\n    public static final String DOUBLE        = \"double\";\n\n    public static final String LONG          = \"long\";\n\n    public static final String INT           = \"int\";\n\n    public static final String TIME_STAMP    = \"timeStamp\";\n\n    public static final String PERCENTILES   = \"percentiles\";\n\n    public static final String AVG           = \"avg\";\n\n    public static final String HIST          = \"hist\";\n\n    public static final String KEY           = \"key\";\n    public static final String SUM           = \"sum\";\n\n    public static final String STATIS        = \"statis.\";\n\n    public static final String METRICS       = \"metrics.\";\n\n    public static final String FIELD         = \"field\";\n    public static final String MISSING       = \"missing\";\n    public static final String MISSING_VALUE = \"-1.0\";\n\n    public static final String TOTAL         = \"total\";\n    public static final String INDICES       = \"indices\";\n    public static final String SHARDS        = \"shards\";\n    public static final String TIMESTAMP     = \"timestamp\";\n    /*********************************************分位值*******************************************/\n\n    public static final String ST90          = \"90.0\";\n    public static final String ST70          = \"70.0\";\n    public static final String ST50          = \"50.0\";\n    public static final String ST99          = \"99.0\";\n    public static final String ST95          = \"95.0\";\n    public static final String ST75          = \"75.0\";\n    public static final String ST55          = \"55.0\";\n\n    /*********************************************pendingTask*******************************************/\n\n    public static final String TASKS         = \"tasks\";\n    public static final String NODES         = \"nodes\";\n\n    public static final String TIME_IN_QUEUE = \"time_in_queue\";\n\n    public static final String SOURCE        = \"source\";\n\n    public static final String PRIORITY      = \"priority\";\n\n    public static final String INSERT_PRDER  = \"insert_order\";\n\n//    10 * 10000 * 10000L;\n    public static final Long   ONE_BILLION   = 10 * 10000 * 10000L;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/DataCenterEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\npublic enum DataCenterEnum {\n                            US01(\"us01\", \"美东机房\"), CN(\"cn\", \"国内\"), UNKNOWN(\"unknown\", \"未知\");\n\n    DataCenterEnum(String code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private String code;\n\n    private String desc;\n\n    public String getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static DataCenterEnum valueOfCode(String code) {\n        if (code == null) {\n            return DataCenterEnum.UNKNOWN;\n        }\n        for (DataCenterEnum state : DataCenterEnum.values()) {\n            if (state.getCode().equals(code)) {\n                return state;\n            }\n        }\n\n        return DataCenterEnum.UNKNOWN;\n    }\n\n    /**\n     * 校验数据中心是否合法\n     * @param dataCenter 数据中心str\n     * @return 合法 true  不合法 false\n     */\n    public static boolean validate(String dataCenter) {\n        return DataCenterEnum.UNKNOWN != DataCenterEnum.valueOfCode(dataCenter);\n    }\n\n    public boolean sameDC(DataCenterEnum dc) {\n        return this.code.equals(dc.getCode());\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ESClusterMethodNameEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport java.util.Arrays;\nimport java.util.Optional;\n\npublic enum ESClusterMethodNameEnum {\n                                     /**\n                                      * ES集群状态\n                                      */\n                                     ES_CLUSTER_STATUS(\"集群状态\", null),\n                                     /**\n                                      * ES集群开始\n                                      */\n                                     /**\n                                      * ES集群能力\n                                      */\n                                     ES_CLUSTER_CAPACITY(\"集群扩缩容\", OperateTypeEnum.PHYSICAL_CLUSTER_CAPACITY),\n                                     /**\n                                      * ES集群升级\n                                      */\n                                     ES_CLUSTER_UPGRADE(\"集群升级\", OperateTypeEnum.PHYSICAL_CLUSTER_UPGRADE),\n                                     /**\n                                      * ES集群重新启动\n                                      */\n                                     ES_CLUSTER_RESTART(\"集群重启\", OperateTypeEnum.PHYSICAL_CLUSTER_RESTART),\n\n                                     /**\n                                      * ES集群\n                                      */\n                                     ES_CLUSTER_OFFLINE(\"集群移除\", OperateTypeEnum.PHYSICAL_CLUSTER_OFFLINE);\n\n    private String          MethodName;\n    private OperateTypeEnum operateTypeEnum;\n\n    ESClusterMethodNameEnum(String methodName, OperateTypeEnum operateTypeEnum) {\n        MethodName = methodName;\n        this.operateTypeEnum = operateTypeEnum;\n    }\n\n    public String getMethodName() {\n        return MethodName;\n    }\n\n    public OperateTypeEnum getOperateTypeEnum() {\n        return operateTypeEnum;\n    }\n\n    public static Optional<OperateTypeEnum> getOperateTypeEnum(String methodName) {\n        return Arrays.stream(ESClusterMethodNameEnum.values())\n            .filter(esClusterMethodNameEnum -> esClusterMethodNameEnum.getMethodName().equals(methodName)).findFirst()\n            .map(ESClusterMethodNameEnum::getOperateTypeEnum);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ESClusterVersionEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\npublic enum ESClusterVersionEnum {\n\n                                  /**\n                                   * 6.6.1.1001版本\n                                   */\n                                  ES_2_3_3_100(\"2.3.3.100\"),\n\n                                  ES_6_5_1_100(\"6.5.1.500\"),\n\n                                  ES_6_6_1_700(\"6.6.1.700\"),\n\n                                  ES_6_6_1_704(\"6.6.1.704\"),\n\n                                  ES_6_6_1_800(\"6.6.1.800\"),\n\n                                  ES_6_6_1_902(\"6.6.1.902\"),\n\n                                  ES_6_6_6_800(\"6.6.6.800\"),\n\n                                  ES_6_6_6_900(\"6.6.6.900\"),\n\n                                  ES_6_7_0_1002(\"6.7.0.1002\"),\n\n                                  ES_6_7_0_1003(\"6.7.0.1003\"),\n\n                                  ES_6_7_0_1004(\"6.7.0.1004\"),\n\n                                  ES_6_7_0_1005(\"6.7.0.1005\"),\n\n                                  ES_7_6_0_1100(\"7.6.0.1100\"),\n\n                                  ES_7_6_0_1108(\"7.6.0.1108\"),\n\n                                  ES_7_6_0_1201(\"7.6.0.1201\"),\n\n                                  ES_7_6_0_1202(\"7.6.0.1202\");\n\n    private String version;\n\n    public String getVersion() {\n        return version;\n    }\n\n    ESClusterVersionEnum(String version) {\n        this.version = version;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ESConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/23 上午11:28\n * @modified By D10865\n */\npublic class ESConstant {\n\n    private ESConstant() {\n    }\n\n    public static final String AGG_KEY           = \"key\";\n\n    public static final String AGG_KEY_AS_STRING = \"key_as_string\";\n\n    public static final String AGG_DOC_COUNT     = \"doc_count\";\n\n    public static final String SUM_VALUE         = \"value\";\n\n    public static final String CARDINALITY_VALUE = \"value\";\n\n    public static final String HITS_TOTAL        = \"total\";\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ESSettingConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n *\n * 工程常量\n *\n * 如果配置的量过多,需要拆解\n *\n */\npublic class ESSettingConstant {\n\n    private ESSettingConstant() {\n    }\n\n\n    public static final String       DEFAULT_INDEX_MAPPING_TYPE              = \"_doc\";\n    public static final String INDEX_NUMBER_OF_SHARDS = \"index.number_of_shards\";\n    public static final String INDEX_REFRESH_INTERVAL = \"index.refresh_interval\";\n    public static final String INDEX_TRANSLOG_DURABILITY = \"index.translog.durability\";\n    public static final String INDEX_ROUTING_ALLOCATION_INCLUDE_NAME = \"index.routing.allocation.include._name\";\n    public static final String INDEX_TRANSLOG_SYNC_INTERVAL    = \"index.translog.sync_interval\";\n    public static final String DEFAULT_DYNAMIC_TEMPLATES_KEY   = \"dynamic_templates\";\n    public static final String INDEX_CREATION_DATE             = \"index.creation_date\";\n    public static final String INDEX_VERIFIED_BEFORE_CLOSE     = \"index.verified_before_close\";\n    public static final String INDEX_VERSION_CREATED           = \"index.version.created\";\n    public static final String INDEX_VERSION                   = \"index.version\";\n    public static final String INDEX_UUID                      = \"index.uuid\";\n    public static final String INDEX_PROVIDED_NAME             = \"index.provided_name\";\n    public static final String INDEX_ROUTING_ALLOCATION_PREFIX = \"index.routing.allocation\";\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/FileCompressionType.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\npublic class FileCompressionType {\n\n    private FileCompressionType() {\n    }\n\n    /**\n     * 文件压缩类型，比如.zip等\n     */\n    public static String ZIP    = \".zip\";\n\n    public static String TAR_GZ = \".tar.gz\";\n\n    public static String TAR    = \".tar\";\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/GatewaySqlConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\npublic class GatewaySqlConstant {\n\n    /**\n     * 根据sql语句进行相关数据的查询\n     */\n    public static String SQL_SEARCH           = \"/_sql\";\n\n    /**\n     * 将sql语句转化为dsl语句\n     */\n    public static String SQL_EXPLAIN          = \"/_sql/explain\";\n\n    /**\n     * 默认的gateway的http请求头\n     */\n    public static String DEFAULT_HTTP_PRE_FIX = \"http://\";\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/IndicatorsType.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * @author qiuziyang @date：2017年11月23日\n */\npublic enum IndicatorsType {\n                            /**\n                             * 健康分基数\n                             */\n                            BASE_OF_HEALTH_DEGREES(1, 50, \"健康分基数\", \"健康分基数是历史成本和天访问量综合得分\"),\n                            /**\n                             * 实时写入量\n                             */\n                            REAL_TIME_WRITE(2, 5, \"实时写入量\", \"写入量与历史同一时间(前后10分钟)写入率比值k作为评分标准\"),\n                            /**\n                             * 实时查询量\n                             */\n                            REAL_TIME_SEARCH(3, 10, \"实时查询量\", \"一段时间查询数量(历史一个小时为单位同期对比)\"),\n                            /**\n                             * 实时JVM内存使用\n                             */\n                            REAL_TIME_JVM(4, 5, \"实时JVM内存使用\", \"10分钟内full gc次数\"),\n                            /**\n                             * 实时查询时间耗时\n                             */\n                            REAL_TIME_SEARCH_COST(5, 10, \"实时查询时间耗时\", \"查询语句索引模板级别的\"),\n                            /**\n                             * 实时磁盘利用率\n                             **/\n                            REAL_TIME_DISK_RATE(6, 10, \"实时磁盘利用率\", \"索引所在节点实时平均磁盘利用率\"),\n                            /**\n                             * 实时CPU利用率\n                             **/\n                            REAL_TIME_CPU_USE(7, 10, \"实时CPU利用率\", \"平均节点cpu利用率\"),\n                            /**\n                             * 未知指标\n                             **/\n                            UNKNOWN(-1, 0, \"\", \"\");\n\n    private int    code;\n    private int    weight;\n    private String name;\n    private String desc;\n\n    IndicatorsType(int code, int weight, String name, String desc) {\n        this.code = code;\n        this.weight = weight;\n        this.name = name;\n        this.desc = desc;\n    }\n\n    public static double getWeightRate(IndicatorsType indicatorsType) {\n        double totalWeight = BASE_OF_HEALTH_DEGREES.getWeight() + REAL_TIME_WRITE.getWeight()\n                             + REAL_TIME_SEARCH.getWeight() + REAL_TIME_JVM.getWeight()\n                             + REAL_TIME_SEARCH_COST.getWeight() + REAL_TIME_DISK_RATE.getWeight()\n                             + REAL_TIME_CPU_USE.getWeight();\n\n        return Double.valueOf(indicatorsType.getWeight()) / totalWeight;\n    }\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public int getWeight() {\n        return weight;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/LevelEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\npublic enum LevelEnum {\n                       /**\n                        * 服务等级未知\n                        */\n                       UNKNOWN(-1, \"未知等级类型\"),\n                       /**\n                        * 服务等级为1，核心\n                        */\n                       CORE(1, \"核心\"),\n                       /**\n                        * 服务等级为2，表示为重要\n                        */\n                       IMPORTANT(2, \"重要\"),\n                       /**\n                        * 服务等级为3，表示为一般\n                        */\n                       ORDINARY(3, \"一般\");\n\n    LevelEnum(Integer code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private Integer code;\n    private String  desc;\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static LevelEnum valueOfCode(Integer code) {\n        if (code == null) {\n            return LevelEnum.UNKNOWN;\n        }\n\n        for (LevelEnum param : LevelEnum.values()) {\n            if (code.equals(param.getCode())) {\n                return param;\n            }\n        }\n\n        return LevelEnum.UNKNOWN;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/OperateRecordSortEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\nimport java.util.Arrays;\nimport java.util.Objects;\n\n/**\n * 操作记录分类枚举\n *\n * @author shizeying\n * @date 2022/06/28\n */\npublic enum OperateRecordSortEnum {\n                                   /**\n                                    * 操作时间\n                                    */\n                                   OPERATE_TIME(\"operate_time\", \"operateTime\"),\n                                   /**\n                                    * 操作记录id\n                                    */\n                                   OPERATE_RECORD_ID(\"id\", \"id\");\n\n    private String sortField;\n    private String sortTerm;\n\n    OperateRecordSortEnum(String sortField, String sortTerm) {\n        this.sortField = sortField;\n        this.sortTerm = sortTerm;\n    }\n\n    public String getSortField() {\n        return sortField;\n    }\n\n    public String getSortTerm() {\n        return sortTerm;\n    }\n\n    public static String getSortField(String sortTerm) {\n        if (Objects.isNull(sortTerm)) {\n            return OPERATE_RECORD_ID.getSortField();\n        }\n        return Arrays.stream(OperateRecordSortEnum.values())\n            .filter(operateRecordSortEnum -> operateRecordSortEnum.getSortTerm().equals(sortTerm)).findFirst()\n            .map(OperateRecordSortEnum::getSortField).orElse(OPERATE_RECORD_ID.getSortField());\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/PageSearchHandleTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\npublic enum PageSearchHandleTypeEnum {\n        UNKNOWN(\"unknown\"),\n        TEMPLATE_LOGIC(\"templateLogicPageSearch\"),\n        CLUSTER_LOGIC(\"clusterLogicPageSearch\"),\n        DSL_TEMPLATE(\"dslTemplatePageSearch\"),\n        CLUSTER_PHY(\"clusterPhyPageSearch\"),\n        INDEX(\"indexPageSearch\"),\n        TEMPLATE_SRV(\"templateSrvPageSearch\"),\n\n        QUICK_COMMAND_INDEX(\"quickCommandIndicesDistributionPageSearch\"),\n        QUICK_COMMAND_SHARD(\"quickCommandShardsDistributionPageSearch\"),\n        OPERATE_RECORD(\"operateRecordPageSearch\"),\n        GATEWAY_JOIN(\"gatewayJoinPageSearch\"),\n        TASK(\"taskPageSearch\");\n       private String pageSearchType;\n\n        public String getPageSearchType(){\n            return pageSearchType;\n        }\n\n        PageSearchHandleTypeEnum(String pageSearchType) {\n            this.pageSearchType   = pageSearchType;\n        }\n    }"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/PercentilesEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\nimport com.google.common.collect.Lists;\n\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n * Created by linyunan on 11/17/21\n */\npublic enum PercentilesEnum {\n                             ST99(\"99.0\"), ST95(\"95.0\"), ST75(\"75.0\"), ST55(\"55.0\"), ST45(\"45.0\"), ST25(\"25.0\"), ST5(\"5.0\"), ST1(\"1.0\"), AVG(\"avg\");\n\n    PercentilesEnum(String type) {\n        this.type = type;\n    }\n\n    private String type;\n\n    public String getType() {\n        return type;\n    }\n\n    public static List<PercentilesEnum> list() {\n        List<PercentilesEnum> percentilesEnumList = Lists.newArrayList();\n        percentilesEnumList.addAll(Arrays.asList(PercentilesEnum.values()));\n        return percentilesEnumList;\n    }\n\n    public static List<String> listAllType() {\n        List<String> percentilesTypeList = Lists.newArrayList();\n        for (PercentilesEnum value : PercentilesEnum.values()) {\n            percentilesTypeList.add(value.getType());\n        }\n        return percentilesTypeList;\n    }\n\n    public static List<String> listSpecialType() {\n        return Lists.newArrayList(ST1.getType(), ST5.getType(), ST25.getType(), ST45.getType());\n    }\n\n    public static List<String> listUsefulType() {\n        List<String> specialTypeList = listSpecialType();\n        List<String> percentilesTypeList = Lists.newArrayList();\n        for (PercentilesEnum value : PercentilesEnum.values()) {\n            if (specialTypeList.contains(value.getType())) {\n                continue;\n            }\n            percentilesTypeList.add(value.getType());\n        }\n        return percentilesTypeList;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/PluginTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * 插件类型集合\n * @author didi\n */\npublic enum PluginTypeEnum {\n                            /**\n                             * 系统默认安装，在集群部署的时候已经在插件包内\n                             */\n                            DEFAULT_PLUGIN(0, \"系统默认\"),\n                            /**\n                             * 用户自定义上传插件中的ES能力插件，被ES引擎所使用\n                             */\n                            ES_PLUGIN(1, \"ES能力\"),\n                            /**\n                             * 用户自定插件中的平台能力插件，用于平台对集群的其他能力，如心跳插件\n                             */\n                            ADMIN_PLUGIN(2, \"平台能力\"),\n                            /**\n                             * 未知类型\n                             */\n                            UNKNOWN(-1, \"未知类型\");\n\n    int    code;\n    String desc;\n\n    PluginTypeEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static PluginTypeEnum valueOf(Integer code) {\n        if (null == code) {\n            return UNKNOWN;\n        }\n\n        for (PluginTypeEnum param : PluginTypeEnum.values()) {\n            if (param.getCode() == code) {\n                return param;\n            }\n        }\n\n        return UNKNOWN;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ProjectResourceEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * 项目资源枚举\n *\n * @author shizeying\n * @date 2022/05/26\n */\npublic enum ProjectResourceEnum {\n                                 /**\n                                  * 项目绑定的逻辑集群\n                                  */\n                                 PROJECT_CLUSTER_LOGIC(0, \"逻辑集群\"),\n                                 /**\n                                  * 项目绑定的es user\n                                  */\n                                 PROJECT_ES_USER(1, \"es user\"),\n                                 /**\n                                  * 项目绑定的索引模板\n                                  */\n                                 PROJECT_INDEX_TEMPLATE(2, \"索引模板\");\n\n    int    code;\n    String desc;\n\n    ProjectResourceEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/QueryDiagnosisTabNameEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\npublic enum QueryDiagnosisTabNameEnum {\n    /**慢查询列表*/\n    SLOW_QUERY(\"slowQuery\"),\n    /**异常查询列表*/\n    ERROR_QUERY(\"errorQuery\");\n    private String tabName;\n\n    QueryDiagnosisTabNameEnum(String tabName) {\n        this.tabName = tabName;\n    }\n\n    public String getTabName() {\n        return tabName;\n    }\n\n\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ResultLevel.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\npublic enum ResultLevel {\n                         ERROR(1,\n                               \"Error\"), CRITICAL(2,\n                                                  \"Critical\"), MAJOR(3,\n                                                                     \"Major\"), NORMAL(4,\n                                                                                      \"Normal\"), MINOR(5,\n                                                                                                       \"Minor\"), FINE(6,\n                                                                                                                      \"Fine\");\n\n    private int    code;\n    private String name;\n\n    private ResultLevel(int code, String name) {\n        this.code = code;\n        this.name = name;\n    }\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public static ResultLevel getResultlevel(String[] levelConfig, double badPercent) {\n        ResultLevel result = null;\n\n        if (null == levelConfig || levelConfig.length < 5) {\n            levelConfig = new String[] { \"5\", \"10\", \"15\", \"20\", \"25\" };\n        }\n\n        if (Double.parseDouble(levelConfig[0]) / 100 >= badPercent) {\n            result = FINE;\n        } else if (Double.parseDouble(levelConfig[0]) / 100 < badPercent\n                   && badPercent <= Double.parseDouble(levelConfig[1]) / 100) {\n            result = MINOR;\n        } else if (Double.parseDouble(levelConfig[1]) / 100 < badPercent\n                   && badPercent <= Double.parseDouble(levelConfig[2]) / 100) {\n            result = NORMAL;\n        } else if (Double.parseDouble(levelConfig[2]) / 100 < badPercent\n                   && badPercent <= Double.parseDouble(levelConfig[3]) / 100) {\n            result = MAJOR;\n        } else if (Double.parseDouble(levelConfig[3]) / 100 < badPercent\n                   && badPercent <= Double.parseDouble(levelConfig[4]) / 100) {\n            result = CRITICAL;\n        } else if (badPercent > Double.parseDouble(levelConfig[4]) / 100) {\n            result = ERROR;\n        }\n\n        return result;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/RunModeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\npublic enum RunModeEnum {\n                         READ_WRITE_SHARE(0), READ_WRITE_SPLIT(1), UNKNOWN(-1);\n\n    int runMode;\n\n    RunModeEnum(int runMode) {\n        this.runMode = runMode;\n    }\n\n    public int getRunMode() {\n        return runMode;\n    }\n\n    public static RunModeEnum valueOfMode(Integer runMode) {\n        if (runMode == null) {\n            return UNKNOWN;\n        }\n        for (RunModeEnum mode : RunModeEnum.values()) {\n            if (mode.getRunMode() == runMode.intValue()) {\n                return mode;\n            }\n        }\n        return UNKNOWN;\n    }\n\n    public static boolean validate(Integer runMode) {\n        return UNKNOWN != valueOfMode(runMode);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/SortConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * Created by linyunan on 2/16/22\n */\npublic class SortConstant {\n    public static final String ID   = \"id\";\n\n    public static final String DESC = \"DESC\";\n    public static final String ASC  = \"ASC\";\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/SortTermEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\n/**\n * Created by linyunan on 2/16/22\n *\n * 支持排序的字段枚举\n */\npublic enum SortTermEnum {\n                          /*********************************物理集群相关*****************************************/\n                          DISK_FREE_PERCENT(\"disk_usage_percent\"),\n\n                          /*********************************模板相关*****************************************/\n                          CHECK_POINT_DIFF(\"check_point_diff\"), HAS_DCDR(\"has_dcdr\"), LEVEL(\"level\"), ACTIVE_SHARD_NUM(\"active_shard_num\"), BLOCK_WRITE(\"block_write\"), BLOCK_READ(\"block_read\");\n\n    SortTermEnum(String type) {\n        this.type = type;\n    }\n\n    private String type;\n\n    public String getType() {\n        return type;\n    }\n\n    public static Boolean isExit(String type) {\n        for (SortTermEnum sortTermEnum : SortTermEnum.values()) {\n            if (sortTermEnum.getType().equals(type)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/TemplateConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\nimport com.google.common.collect.Sets;\n\nimport java.util.Set;\n\n/**\n * Created by linyunan on 2021-10-18\n */\n\npublic class TemplateConstant {\n\n    public static final Set<Character> TEMPLATE_NAME_CHAR_SET            = Sets.newHashSet('a', 'b', 'c', 'd', 'e', 'f',\n        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',\n        '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', '.');\n\n    public static final Integer        TEMPLATE_NAME_SIZE_MIN            = 4;\n    public static final Integer        TEMPLATE_NAME_SIZE_MAX            = 128;\n    public static final Integer        TEMPLATE_SAVE_BY_DAY_EXPIRE_MAX   = 180;\n    public static final Integer        TEMPLATE_SAVE_BY_MONTH_EXPIRE_MIN = 30;\n\n    public static final String         TEMPLATE_NOT_EXIST                = \"模板不存在\";\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/UpdateIndexTemplateLabelParam.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Label;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * Created by d06679 on 2018/1/17.\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(value = \"UpdateIndexTemplateLabelParam\", description = \"更新索引标签参数\")\npublic class UpdateIndexTemplateLabelParam {\n\n    @ApiModelProperty(\"索引标签列表\")\n    private List<Label> indexTemplateLabels;\n\n    @ApiModelProperty(\"索引模板ID\")\n    private Integer     templateId;\n\n    @ApiModelProperty(\"操作人\")\n    private String      operator;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/arius/AriusUser.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.arius;\n\n/**\n *\n * Created by d06679 on 2017/7/14.\n */\npublic enum AriusUser {\n                       /**\n                        * Arius服务号\n                        */\n                       ARIUS(\"Arius服务号\"),\n\n                       AUTO_EXER(\"zhaoqingrong\"),\n\n                       SYSTEM(\"系统\"),\n\n                       CAPACITY_PLAN(\"容量规划\"),\n\n                       UNKNOWN(\"unknown\");\n\n    AriusUser(String desc) {\n        this.desc = desc;\n    }\n\n    private String desc;\n\n    public String getDesc() {\n        return desc;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/cluster/ClusterConnectionStatus.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.cluster;\n\n/**\n * Cluster 连通状态标示\n */\npublic enum ClusterConnectionStatus {\n                                     /**\n                                      * 正常\n                                      */\n                                     NORMAL(0, \"正常连通\"),\n                                     /**\n                                      * 未认证\n                                      */\n                                     UNAUTHORIZED(1, \"密码错误无法连通\"),\n                                     /**\n                                      * 未连接\n                                      */\n                                     DISCONNECTED(2, \"集群离线未连接\"),\n                                     /**\n                                      * 未知\n                                      */\n                                     UNKNOWN(3, \"未知\");\n\n    ClusterConnectionStatus(Integer code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private Integer code;\n    private String  desc;\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/cluster/ClusterConnectionStatusWithTemplateEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.cluster;\n\n/**\n * 集群与模板连接状态\n *\n * @author shizeying\n * @date 2022/08/12\n */\npublic enum ClusterConnectionStatusWithTemplateEnum {\n    /**\n     * 正常\n     */\n    NORMAL(0, \"正常连通\"),\n    /**\n     * 断开连接\n     */\n    DISCONNECTED(1, \"集群故障，请检查集群状态后重试\");\n    \n    ClusterConnectionStatusWithTemplateEnum(Integer code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n    \n    private final Integer code;\n    private final String  desc;\n    \n    public Integer getCode() {\n        return code;\n    }\n    \n    public String getDesc() {\n        return desc;\n    }\n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/cluster/ClusterDynamicConfigsEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ClusterDynamicConfigTypeCheckFunUtil;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic enum ClusterDynamicConfigsEnum {\n                                       /**\n                                        * 未知动态配置项\n                                        */\n                                       UNKNOWN(\"unknown\", ClusterDynamicConfigsTypeEnum.UNKNOWN,\n                                               ClusterDynamicConfigTypeCheckFunUtil::defaultTypeCheck),\n\n                                       /**\n                                        * 动态配置项中集群下breaker类型\n                                        */\n                                       INDICES_BREAKER_TOTAL_LIMIT(\"indices.breaker.total.limit\",\n                                                                   ClusterDynamicConfigsTypeEnum.BREAKER,\n                                                                   ClusterDynamicConfigTypeCheckFunUtil::percentCheck), INDICES_BREAKER_FIELDDATA_LIMIT(\"indices.breaker.fielddata.limit\",\n                                                                                                                                                        ClusterDynamicConfigsTypeEnum.BREAKER,\n                                                                                                                                                        ClusterDynamicConfigTypeCheckFunUtil::percentCheck), INDICES_BREAKER_FIELDDATA_OVERHEAD(\"indices.breaker.fielddata.overhead\",\n                                                                                                                                                                                                                                                ClusterDynamicConfigsTypeEnum.BREAKER,\n                                                                                                                                                                                                                                                ClusterDynamicConfigTypeCheckFunUtil::floatValueCheck1to100), INDICES_BREAKER_REQUEST_LIMIT(\"indices.breaker.request.limit\",\n                                                                                                                                                                                                                                                                                                                                            ClusterDynamicConfigsTypeEnum.BREAKER,\n                                                                                                                                                                                                                                                                                                                                            ClusterDynamicConfigTypeCheckFunUtil::percentCheck), INDICES_BREAKER_REQUEST_OVERHEAD(\"indices.breaker.request.overhead\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                  ClusterDynamicConfigsTypeEnum.BREAKER,\n                                                                                                                                                                                                                                                                                                                                                                                                                                  ClusterDynamicConfigTypeCheckFunUtil::floatValueCheck1to100), NETWORK_BREAKER_INFLIGHT_REQUESTS_LIMIT(\"network.breaker.inflight_requests.limit\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ClusterDynamicConfigsTypeEnum.BREAKER,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ClusterDynamicConfigTypeCheckFunUtil::percentCheck), NETWORK_BREAKER_INFLIGHT_REQUESTS_OVERHEAD(\"network.breaker.inflight_requests.overhead\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ClusterDynamicConfigsTypeEnum.BREAKER,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ClusterDynamicConfigTypeCheckFunUtil::floatValueCheck1to100),\n\n                                       /**\n                                        * 动态配置项中集群下routing类型\n                                        */\n                                       CLUSTER_ROUTING_ALLOCATION_NODE_CONCURRENT_INCOMING_RECOVERIES(\"cluster.routing.allocation.node_concurrent_incoming_recoveries\",\n                                                                                                      ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                      ClusterDynamicConfigTypeCheckFunUtil::intCheck), CLUSTER_ROUTING_ALLOCATION_NODE_CONCURRENT_OUTGOING_RECOVERIES(\"cluster.routing.allocation.node_concurrent_outgoing_recoveries\",\n                                                                                                                                                                                                                      ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                      ClusterDynamicConfigTypeCheckFunUtil::intCheck), CLUSTER_ROUTING_ALLOCATION_NODE_CONCURRENT_RECOVERIES(\"cluster.routing.allocation.node_concurrent_recoveries\",\n                                                                                                                                                                                                                                                                                                                             ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                             ClusterDynamicConfigTypeCheckFunUtil::intCheck), CLUSTER_ROUTING_ALLOCATION_NODE_INITIAL_PRIMARIES_RECOVERIES(\"cluster.routing.allocation.node_initial_primaries_recoveries\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                           ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                           ClusterDynamicConfigTypeCheckFunUtil::intCheck), CLUSTER_ROUTING_ALLOCATION_SAME_SHARD_HOST(\"cluster.routing.allocation.same_shard.host\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ClusterDynamicConfigTypeCheckFunUtil::booleanCheck), CLUSTER_ROUTING_REBALANCE_ENABLE(\"cluster.routing.rebalance.enable\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ClusterDynamicConfigTypeCheckFunUtil::reBalanceEnableTypeCheck), CLUSTER_ROUTING_ALLOCATION_ALLOW_REBALANCE(\"cluster.routing.allocation.allow_rebalance\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         ClusterDynamicConfigTypeCheckFunUtil::allowReBalanceTypeCheck), CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_REBALANCE(\"cluster.routing.allocation.cluster_concurrent_rebalance\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ClusterDynamicConfigTypeCheckFunUtil::intCheck), CLUSTER_ROUTING_ALLOCATION_BALANCE_SHARD(\"cluster.routing.allocation.balance.shard\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ClusterDynamicConfigTypeCheckFunUtil::floatValueCheckPositive), CLUSTER_ROUTING_ALLOCATION_BALANCE_INDEX(\"cluster.routing.allocation.balance.index\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ClusterDynamicConfigTypeCheckFunUtil::floatValueCheckPositive), CLUSTER_ROUTING_ALLOCATION_BALANCE_THRESHOLD(\"cluster.routing.allocation.balance.threshold\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ClusterDynamicConfigTypeCheckFunUtil::floatValueCheckPositive), CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED(\"cluster.routing.allocation.disk.threshold_enabled\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ClusterDynamicConfigTypeCheckFunUtil::booleanCheck), CLUSTER_ROUTING_ALLOCATION_DISK_WATERMARK_LOW(\"cluster.routing.allocation.disk.watermark.low\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ClusterDynamicConfigTypeCheckFunUtil::percentCheck), CLUSTER_ROUTING_ALLOCATION_DISK_WATERMARK_HIGH(\"cluster.routing.allocation.disk.watermark.high\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ClusterDynamicConfigTypeCheckFunUtil::percentCheck), CLUSTER_ROUTING_ALLOCATION_DISK_WATERMARK_FLOOD_STAGE(\"cluster.routing.allocation.disk.watermark.flood_stage\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ClusterDynamicConfigTypeCheckFunUtil::percentCheck), CLUSTER_ROUTING_ALLOCATION_TOTAL_SHARDS_PER_NODE(\"cluster.routing.allocation.total_shards_per_node\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ClusterDynamicConfigTypeCheckFunUtil::intCheck1000), CLUSTER_ROUTING_ALLOCATION_AWARENESS_ATTRIBUTES(\"cluster.routing.allocation.awareness.attributes\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ClusterDynamicConfigTypeCheckFunUtil::attributesTypeCheck), CLUSTER_ROUTING_ALLOCATION_ENABLE(\"cluster.routing.allocation.enable\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ClusterDynamicConfigTypeCheckFunUtil::allocationEnableTypeCheck), INDICES_RECOVERY_MAX_BYTES_PER_SEC(\"indices.recovery.max_bytes_per_sec\",\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ClusterDynamicConfigsTypeEnum.ROUTING,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ClusterDynamicConfigTypeCheckFunUtil::bandwidthCheck),\n                                       /**\n                                        * 动态配置项中集群下zen类型\n                                        */\n                                       DISCOVERY_ZEN_COMMIT_TIMEOUT(\"discovery.zen.commit_timeout\",\n                                                                    ClusterDynamicConfigsTypeEnum.ZEN,\n                                                                    ClusterDynamicConfigTypeCheckFunUtil::timeCheck), DISCOVERY_ZEN_MINIMUM_MASTER_NODES(\"discovery.zen.minimum_master_nodes\",\n                                                                                                                                                         ClusterDynamicConfigsTypeEnum.ZEN,\n                                                                                                                                                         ClusterDynamicConfigTypeCheckFunUtil::intCheck), DISCOVERY_ZEN_NO_MASTER_BLOCK(\"discovery.zen.no_master_block\",\n                                                                                                                                                                                                                                        ClusterDynamicConfigsTypeEnum.ZEN,\n                                                                                                                                                                                                                                        ClusterDynamicConfigTypeCheckFunUtil::masterBlockTypeCheck), DISCOVERY_ZEN_PUBLISH_DIFF_ENABLE(\"discovery.zen.publish_diff.enable\",\n                                                                                                                                                                                                                                                                                                                                       ClusterDynamicConfigsTypeEnum.ZEN,\n                                                                                                                                                                                                                                                                                                                                       ClusterDynamicConfigTypeCheckFunUtil::booleanCheck), DISCOVERY_ZEN_PUBLISH_TIMEOUT(\"discovery.zen.publish_timeout\",\n                                                                                                                                                                                                                                                                                                                                                                                                                          ClusterDynamicConfigsTypeEnum.ZEN,\n                                                                                                                                                                                                                                                                                                                                                                                                                          ClusterDynamicConfigTypeCheckFunUtil::timeCheck);\n\n    private String                        name;\n    private ClusterDynamicConfigsTypeEnum clusterDynamicConfigsType;\n    private Function<String, Boolean>     checkFun;\n\n    ClusterDynamicConfigsEnum(String name, ClusterDynamicConfigsTypeEnum clusterDynamicConfigsType,\n                              Function<String, Boolean> checkFun) {\n        this.name = name;\n        this.clusterDynamicConfigsType = clusterDynamicConfigsType;\n        this.checkFun = checkFun;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public ClusterDynamicConfigsTypeEnum getClusterDynamicConfigsType() {\n        return clusterDynamicConfigsType;\n    }\n\n    public Function<String, Boolean> getCheckFun() {\n        return checkFun;\n    }\n\n    public static ClusterDynamicConfigsEnum valueCodeOfName(String name) {\n        if (AriusObjUtils.isNull(name)) {\n            return ClusterDynamicConfigsEnum.UNKNOWN;\n        }\n\n        for (ClusterDynamicConfigsEnum param : ClusterDynamicConfigsEnum.values()) {\n            if (param.getName().equals(name)) {\n                return param;\n            }\n        }\n        return ClusterDynamicConfigsEnum.UNKNOWN;\n    }\n\n    public static List<ClusterDynamicConfigsEnum> valuesWithoutUnknown() {\n        return Arrays.stream(values())\n            .filter(clusterDynamicConfigsEnum -> clusterDynamicConfigsEnum != ClusterDynamicConfigsEnum.UNKNOWN)\n            .collect(Collectors.toList());\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/cluster/ClusterDynamicConfigsTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.cluster;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\npublic enum ClusterDynamicConfigsTypeEnum {\n\n                                           /**\n                                            * 未知项\n                                            */\n                                           UNKNOWN(-1, \"unknown\"),\n\n                                           /**\n                                            * 物理集群下的breaker配置项\n                                            */\n                                           BREAKER(1, \"breaker\"),\n\n                                           /**\n                                            * 物理集群下的routing配置项\n                                            */\n                                           ROUTING(2, \"routing\"),\n\n                                           /**\n                                            * 物理集群下的zen配置项\n                                            */\n                                           ZEN(3, \"zen\");\n\n    ClusterDynamicConfigsTypeEnum(int code, String type) {\n        this.code = code;\n        this.type = type;\n    }\n\n    public static List<ClusterDynamicConfigsTypeEnum> valuesWithoutUnknown() {\n        return Arrays.stream(values())\n            .filter(\n                clusterDynamicConfigsTypeEnum -> clusterDynamicConfigsTypeEnum != ClusterDynamicConfigsTypeEnum.UNKNOWN)\n            .collect(Collectors.toList());\n    }\n\n    private int    code;\n    private String type;\n\n    public String getType() {\n        return type;\n    }\n\n    public int getCode() {\n        return code;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/cluster/ClusterHealthEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\n\n/**\n * @author wangshu\n * @date 2020/09/22\n */\npublic enum ClusterHealthEnum {\n\n                               /**\n                                * green\n                                */\n                               GREEN(0, \"green\"),\n\n                               /**\n                                * yellow\n                                */\n                               YELLOW(1, \"yellow\"),\n\n                               /**\n                                * red\n                                */\n                               RED(2, \"red\"),\n\n                               /**\n                                * 未知\n                                */\n                               UNKNOWN(-1, \"unknown\");\n\n    ClusterHealthEnum(Integer code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    public static ClusterHealthEnum valueOf(Integer code) {\n        if (YELLOW.getCode().equals(code)) {\n            return YELLOW;\n        } else if (RED.getCode().equals(code)) {\n            return RED;\n        } else if (GREEN.getCode().equals(code)) {\n            return GREEN;\n        }\n        return UNKNOWN;\n    }\n\n    public static ClusterHealthEnum valuesOf(String desc) {\n        if (AriusObjUtils.isBlack(desc) || UNKNOWN.getDesc().equals(desc)) {\n            return UNKNOWN;\n        }\n\n        if (YELLOW.getDesc().equals(desc)) {\n            return YELLOW;\n        } else if (RED.getDesc().equals(desc)) {\n            return RED;\n        } else if (GREEN.getDesc().equals(desc)) {\n            return GREEN;\n        }\n        return UNKNOWN;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    private Integer code;\n    private String  desc;\n\n    public static boolean isExitByCode(Integer code) {\n        if (null == code) {\n            return false;\n        }\n\n        for (ClusterHealthEnum value : ClusterHealthEnum.values()) {\n            if (code.equals(value.getCode())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/cluster/ClusterQuickCommandMethodsEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.cluster;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName ClusterQuickCommandEnum\n * @Author gyp\n * @Date 2022/6/1\n * @Version 1.0\n */\npublic enum ClusterQuickCommandMethodsEnum {\n                                            /**\n                                             * shard分布\n                                             */\n                                            SHARD(\"GET\", \"_cat/shards\"),\n                                            /**\n                                             * pending task分析\n                                             */\n                                            PENDING_TASK(\"GET\", \"/_cluster/pending_tasks\"),\n                                            /**\n                                             * task任务分析 MissionAnalysis\n                                             */\n                                            TASK_MISSION_ANALYSIS(\"GET\", \"_tasks?detailed\"),\n                                            /**\n                                             * 热点线程分析\n                                             */\n                                            HOT_THREAD(\"GET\", \"_nodes/hot_threads\"),\n                                            /**\n                                             * shard分配说明\n                                             */\n                                            SHARD_ASSIGNMENT(\"GET\", \"_cluster/allocation/explain\"),\n                                            /**\n                                             * 异常shard分配重试 abnormal-shard-allocation-retry\n                                             */\n                                            ABNORMAL_SHARD_RETRY(\"POST\", \"/_cluster/reroute?retry_failed=true\"),\n                                            /**\n                                             * 清除fielddata内存 clear-fielddata-memory\n                                             */\n                                            CLEAR_FIELDDATA_MEMORY(\"POST\", \"_cache/clear?fielddata=true\");\n\n    private String method;\n    private String uri;\n\n    ClusterQuickCommandMethodsEnum(String method, String uri) {\n        this.method = method;\n        this.uri = uri;\n    }\n\n    public String getMethod() {\n        return method;\n    }\n\n    public void setMethod(String method) {\n        this.method = method;\n    }\n\n    public String getUri() {\n        return uri;\n    }\n\n    public void setUri(String uri) {\n        this.uri = uri;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/cluster/ClusterRegionStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.cluster;\n\n/**\n * Region是否在容量规划标示\n * @author wangshu\n * @date 2020/09/14\n */\n@Deprecated\npublic enum ClusterRegionStatusEnum {\n                                     /**\n                                      * Region未加入容量规划\n                                      */\n                                     NOT_IN_CAPACITY_PLAN(0, \"未加入容量规划\"),\n\n                                     /**\n                                      * Region已经在容量规划中\n                                      */\n                                     IN_CAPACITY_PLAN(1, \"容量规划中\");\n\n    ClusterRegionStatusEnum(Integer code, String message) {\n        this.code = code;\n        this.message = message;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    private Integer code;\n    private String  message;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/cluster/ClusterResourceTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.cluster;\n\n/**\n * 集群资源类型\n * @author ohushenglin_v\n * @date 2022-05-25\n */\npublic enum ClusterResourceTypeEnum {\n                                     PUBLIC(1, \"共享集群\"),\n\n                                     PRIVATE(2, \"独立集群\"),\n\n                                     EXCLUSIVE(3, \"独享集群\"),\n\n                                     UNKNOWN(-1, \"未知\");\n\n    ClusterResourceTypeEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static ClusterResourceTypeEnum valueOf(Integer code) {\n        if (code == null) {\n            return ClusterResourceTypeEnum.UNKNOWN;\n        }\n        for (ClusterResourceTypeEnum state : ClusterResourceTypeEnum.values()) {\n            if (state.getCode() == code) {\n                return state;\n            }\n        }\n\n        return ClusterResourceTypeEnum.UNKNOWN;\n    }\n\n    public static boolean isExist(Integer code) {\n        return UNKNOWN.getCode() != ClusterResourceTypeEnum.valueOf(code).getCode();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/cluster/PluginConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.cluster;\n\n/**\n * 插件常数\n *\n * @author shizeying\n * @date 2022/07/15\n */\npublic final class PluginConstant {\n    \n    /**\n     *pipeline\n     */\n    public static final String INGEST_INDEX_TEMPLATE=\"ingest-index-template\";\n    /**\n     * dcdr\n     */\n    public static final String DIDI_CROSS_DATACENTER_REPLICATION=\"didi-cross-datacenter-replication\";\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/config/AriusConfigDimensionEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.config;\n\n/**\n * 操作记录模块枚举\n *\n * Created by d06679 on 2017/7/14.\n */\npublic enum AriusConfigDimensionEnum {\n                                      /**集群*/\n                                      CLUSTER(1, \"集群\"),\n\n                                      TEMPLATE(2, \"模板\"),\n\n                                      RESOURCE(3, \"资源\"),\n\n                                      UNKNOWN(-1, \"未知\");\n\n    AriusConfigDimensionEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static AriusConfigDimensionEnum valueOf(Integer code) {\n        if (code == null) {\n            return AriusConfigDimensionEnum.UNKNOWN;\n        }\n        for (AriusConfigDimensionEnum state : AriusConfigDimensionEnum.values()) {\n            if (state.getCode() == code) {\n                return state;\n            }\n        }\n\n        return AriusConfigDimensionEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/config/AriusConfigItemEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.config;\n\npublic enum AriusConfigItemEnum {\n                                 /**正常*/\n                                 DASHBOARD_THRESHOLD(\"dashboard.threshold\", \"dashboard限制阈值\");\n\n    AriusConfigItemEnum(String name, String desc) {\n        this.name = name;\n        this.desc = desc;\n    }\n\n    private String name;\n\n    private String desc;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public void setDesc(String desc) {\n        this.desc = desc;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/config/AriusConfigStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.config;\n\n/**\n * 操作记录模块枚举\n *\n * Created by d06679 on 2017/7/14.\n */\npublic enum AriusConfigStatusEnum {\n                                   /**正常*/\n                                   NORMAL(1, \"正常\"),\n\n                                   DISABLE(2, \"禁用\"),\n\n                                   DELETED(-1, \"删除\");\n\n    AriusConfigStatusEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static AriusConfigStatusEnum valueOf(Integer code) {\n        if (code == null) {\n            return null;\n        }\n        for (AriusConfigStatusEnum state : AriusConfigStatusEnum.values()) {\n            if (state.getCode() == code) {\n                return state;\n            }\n        }\n\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/dcdr/DCDRStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.dcdr;\n\n/**\n * Created by linyunan on 12/14/21\n */\npublic enum DCDRStatusEnum {\n                            CANCELLED(\"cancelled\", 0),\n\n                            SUCCESS(\"success\", 1),\n\n                            RUNNING(\"running\", 2),\n\n                            FAILED(\"failed\", 3),\n\n                            WAIT(\"wait\", 4),\n\n                            UNKNOWN(\"unknown\", -1);\n\n    DCDRStatusEnum(String value, Integer code) {\n        this.value = value;\n        this.code = code;\n    }\n\n    private String  value;\n\n    private Integer code;\n\n    public String getValue() {\n        return value;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public void setCode(Integer code) {\n        this.code = code;\n    }\n\n    public static DCDRStatusEnum valueFromCode(Integer code) {\n        if (code == null) {\n            return null;\n        }\n\n        for (DCDRStatusEnum state : DCDRStatusEnum.values()) {\n            if (UNKNOWN.getCode().equals(code)) {\n                continue;\n            }\n\n            if (state.getCode().equals(code)) {\n                return state;\n            }\n        }\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/dcdr/DCDRSwithTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.dcdr;\n\n/**\n * Created by linyunan on 12/14/21\n */\npublic enum DCDRSwithTypeEnum {\n                               SMOOTH(\"smooth\", 1),\n\n                               FORCE(\"force\", 2),\n\n                               UNKNOWN(\"unknown\", -1);\n\n    DCDRSwithTypeEnum(String value, Integer code) {\n        this.value = value;\n        this.code = code;\n    }\n\n    private String  value;\n\n    private Integer code;\n\n    public String getValue() {\n        return value;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public void setCode(Integer code) {\n        this.code = code;\n    }\n\n    public static DCDRSwithTypeEnum valueFromCode(Integer code) {\n        if (code == null) {\n            return null;\n        }\n        for (DCDRSwithTypeEnum state : DCDRSwithTypeEnum.values()) {\n            if (UNKNOWN.getCode().equals(code)) {\n                continue;\n            }\n\n            if (state.getCode().equals(code)) {\n                return state;\n            }\n        }\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ecm/EcmHostStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.ecm;\n\nimport java.util.Set;\n\n/**\n * 宙斯物理集群操作动作枚举类型\n * running   运行中\n * creating  创建中\n * failed    失败\n * skip      跳过\n * rodo      重做\n * ready     准备\n * updated   待更新\n * unknown   未知\n * @author   didi\n * @date 2020/9/25\n */\npublic enum EcmHostStatusEnum {\n                               /**killing*/\n                               KILLING(\"killing\"),\n\n                               KILL_FAILED(\"kill_failed\"),\n\n                               CANCELLED(\"cancelled\"),\n\n                               IGNORE(\"ignored\"),\n\n                               TIMEOUT(\"timeout\"),\n\n                               WAITING(\"waiting\"),\n\n                               RUNNING(\"running\"),\n\n                               FAILED(\"failed\"),\n\n                               READY(\"ready\"),\n\n                               UPDATED(\"updated\"),\n\n                               UPDATING(\"updating\"),\n\n                               SUCCESS(\"success\"),\n\n                               UNKNOWN(\"unknown\");\n\n    private String value;\n\n    EcmHostStatusEnum(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public static EcmHostStatusEnum valueFrom(String value) {\n        if (value == null) {\n            return null;\n        }\n        for (EcmHostStatusEnum state : EcmHostStatusEnum.values()) {\n            if (state.getValue().equals(value)) {\n                return state;\n            }\n        }\n        return null;\n    }\n\n    public static boolean isSuccessFinished(Set<EcmHostStatusEnum> statusEnumSet) {\n        if (statusEnumSet == null || statusEnumSet.isEmpty()) {\n            return false;\n        }\n        if ((statusEnumSet.contains(SUCCESS) && statusEnumSet.size() == 1)\n            || (statusEnumSet.contains(IGNORE) && statusEnumSet.size() == 1)\n            || (statusEnumSet.contains(IGNORE) && statusEnumSet.contains(SUCCESS) && statusEnumSet.size() == 2)) {\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/ecm/EcmTaskStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.ecm;\n\nimport java.util.Set;\n\n/**\n * 宙斯物理集群操作动作枚举类型\n * success     成功\n * failed      失败\n * running    执行中\n * waiting     等待\n * cancel      取消\n * unknown     未知\n * @author     didi\n * @date 2020/10/10\n */\npublic enum EcmTaskStatusEnum {\n                               /**success*/\n                               SUCCESS(\"success\"),\n\n                               FAILED(\"failed\"),\n\n                               RUNNING(\"running\"),\n\n                               WAITING(\"waiting\"),\n\n                               PAUSE(\"pause\"),\n\n                               IGNORE(\"ignore\"),\n\n                               CANCEL(\"cancel\"),\n\n                               UNKNOWN(\"unknown\");\n\n    private String value;\n\n    EcmTaskStatusEnum(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public static EcmTaskStatusEnum valueFrom(String value) {\n        if (value == null) {\n            return EcmTaskStatusEnum.UNKNOWN;\n        }\n        for (EcmTaskStatusEnum state : EcmTaskStatusEnum.values()) {\n            if (state.getValue().equals(value)) {\n                return state;\n            }\n        }\n        return EcmTaskStatusEnum.UNKNOWN;\n    }\n\n    /**\n     * 计算工单状态\n     * @param subStatusSet\n     * @return\n     */\n    public static EcmTaskStatusEnum calTaskStatus(Set<EcmTaskStatusEnum> subStatusSet) {\n        if (subStatusSet == null) {\n            return EcmTaskStatusEnum.UNKNOWN;\n        }\n\n        if (subStatusSet.isEmpty()) {\n            return EcmTaskStatusEnum.SUCCESS;\n        }\n\n        if (subStatusSet.contains(EcmTaskStatusEnum.WAITING) && subStatusSet.size() == 1) {\n            return EcmTaskStatusEnum.PAUSE;\n        }\n        if (subStatusSet.contains(EcmTaskStatusEnum.CANCEL) && subStatusSet.size() == 1) {\n            return EcmTaskStatusEnum.CANCEL;\n        }\n\n        if (subStatusSet.contains(EcmTaskStatusEnum.FAILED)) {\n            return EcmTaskStatusEnum.FAILED;\n        }\n\n        if (subStatusSet.contains(EcmTaskStatusEnum.RUNNING)) {\n            return EcmTaskStatusEnum.RUNNING;\n        }\n\n        if ((subStatusSet.contains(EcmTaskStatusEnum.SUCCESS) && subStatusSet.size() == 1)\n            || (subStatusSet.contains(EcmTaskStatusEnum.IGNORE) && subStatusSet.size() == 1)\n            || (subStatusSet.contains(EcmTaskStatusEnum.SUCCESS) && subStatusSet.contains(EcmTaskStatusEnum.IGNORE)\n                && subStatusSet.size() == 2)) {\n            //1 只有SUCCESS；2 只有IGNORE；3 只有SUCCESS和IGNORE  --> SUCCESS\n            return EcmTaskStatusEnum.SUCCESS;\n        }\n\n        if (subStatusSet.contains(EcmTaskStatusEnum.PAUSE)\n            || (subStatusSet.contains(EcmTaskStatusEnum.WAITING) && subStatusSet.contains(EcmTaskStatusEnum.SUCCESS)\n                && subStatusSet.size() == 2)) {\n            //1 只有PAUSE；2 走到暂停点，只有WAITING 和 SUCCESS\n            return EcmTaskStatusEnum.PAUSE;\n        }\n\n        if (subStatusSet.contains(EcmTaskStatusEnum.UNKNOWN)) {\n            return EcmTaskStatusEnum.UNKNOWN;\n        }\n\n        return EcmTaskStatusEnum.UNKNOWN;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/esconfig/EsConfigActionEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.esconfig;\n\n/**\n * @author lyn\n * @date 2021-01-21\n */\npublic enum EsConfigActionEnum {\n                                /**新增*/\n                                ADD(1, \"集群配置新增\"),\n\n                                EDIT(2, \"集群配置编辑\"),\n\n                                DELETE(3, \"集群配置删除\"),\n\n                                UNKNOWN(-1, \"未知\");\n\n    EsConfigActionEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static EsConfigActionEnum valueOf(Integer code) {\n        if (code == null) {\n            return EsConfigActionEnum.UNKNOWN;\n        }\n        for (EsConfigActionEnum typeEnum : EsConfigActionEnum.values()) {\n            if (typeEnum.getCode() == code) {\n                return typeEnum;\n            }\n        }\n\n        return EsConfigActionEnum.UNKNOWN;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/espackage/AriusESPackageEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.espackage;\n\npublic enum AriusESPackageEnum {\n                                /**\n                                 * 滴滴内部的es程序包，对于es内核进行了一定的改造,版本为4位\n                                 */\n                                DI_DI_INTERNAL(1, 4, \"滴滴内部\"),\n                                /**\n                                 * 外部开源的es程序包，版本为3位\n                                 */\n                                OPEN_SOURCE(2, 2, \"外部通用\"),\n                                /**\n                                 * 未知\n                                 */\n                                UNKNOWN(-1, 0, \"未知\");\n\n    AriusESPackageEnum(Integer code, Integer versionLength, String desc) {\n        this.code = code;\n        this.versionLength = versionLength;\n        this.desc = desc;\n    }\n\n    private int    code;\n    private int    versionLength;\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public int getVersionLength() {\n        return versionLength;\n    }\n\n    public static AriusESPackageEnum valueOfCode(Integer code) {\n        if (code == null) {\n            return UNKNOWN;\n        }\n\n        for (AriusESPackageEnum param : AriusESPackageEnum.values()) {\n            if (param.getCode() == code) {\n                return param;\n            }\n        }\n\n        return UNKNOWN;\n    }\n\n    public static AriusESPackageEnum valueOfLength(Integer versionLength) {\n        if (versionLength == null) {\n            return UNKNOWN;\n        }\n\n        for (AriusESPackageEnum param : AriusESPackageEnum.values()) {\n            if (param.getVersionLength() == versionLength) {\n                return param;\n            }\n        }\n\n        return UNKNOWN;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/index/IndexBlockEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.index;\n\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author lyn\n * @date 2021/09/30\n **/\npublic enum IndexBlockEnum {\n\n                            UNKNOWN(\"unknown\"),\n\n                            READ(\"read\"),\n\n                            WRITE(\"write\");\n\n    private String type;\n\n    IndexBlockEnum(String type) {\n        this.type = type;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public static boolean isIndexBlockExit(String type) {\n        if (StringUtils.isBlank(type)) {\n            return false;\n        }\n\n        for (IndexBlockEnum value : IndexBlockEnum.values()) {\n            if (UNKNOWN.getType().equals(type)) {\n                continue;\n            }\n\n            if (type.equals(value.getType())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/index/IndexStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.index;\n\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author lyn\n * @date 2021/09/30\n **/\npublic enum IndexStatusEnum {\n\n                             UNKNOWN(\"unknown\"), GREEN(\"green\"),\n\n                             YELLOW(\"yellow\"),\n\n                             RED(\"red\");\n\n    private String status;\n\n    IndexStatusEnum(String status) {\n        this.status = status;\n    }\n\n    public String getStatus() {\n        return status;\n    }\n\n    public void setStatus(String status) {\n        this.status = status;\n    }\n\n    public static boolean isStatusExit(String status) {\n        if (StringUtils.isBlank(status)) {\n            return false;\n        }\n\n        for (IndexStatusEnum value : IndexStatusEnum.values()) {\n            if (UNKNOWN.getStatus().equals(status)) {\n                continue;\n            }\n\n            if (status.equals(value.getStatus())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/AggMetricsTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\n/**\n * Created by linyunan on 2021-08-04\n */\npublic enum AggMetricsTypeEnum {\n                                /*** 未知*/\n                                UNKNOWN(-1, \"\"), MAX(1, \"max\"), MIN(2, \"min\"), AVG(3, \"avg\"), SUM(4, \"sum\");\n\n    AggMetricsTypeEnum(int code, String type) {\n        this.code = code;\n        this.type = type;\n    }\n\n    private int    code;\n\n    private String type;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    /**\n     * 默认code == null 选max\n     */\n    public static String valueTypeOfCode(Integer code) {\n        if (null == code) {\n            return AggMetricsTypeEnum.MAX.getType();\n        }\n        for (AggMetricsTypeEnum typeEnum : AggMetricsTypeEnum.values()) {\n            if (code.equals(typeEnum.getCode())) {\n                return typeEnum.getType();\n            }\n        }\n\n        return null;\n    }\n\n    public static String valueCodeOfType(String type) {\n        if (null == type) {\n            return AggMetricsTypeEnum.MAX.getType();\n        }\n        for (AggMetricsTypeEnum typeEnum : AggMetricsTypeEnum.values()) {\n            if (type.equals(typeEnum.getType())) {\n                return typeEnum.getType();\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/ClusterPhyClusterMetricsEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\nimport com.google.common.collect.Lists;\n\nimport java.util.List;\n\n/**\n * @author gyp\n * @date 2022/5/9\n * @version 1.0\n */\npublic enum ClusterPhyClusterMetricsEnum {\n                                          /*** 未知 */\n                                          UNKNOWN(\"\", \"未知\"),\n\n                                          BASIC(\"basic\", \"基本指标\"),\n\n                                          ELAPSEDTIME(\"elapsedTime\", \"采集用时\"),\n\n                                          /*************************************1.CPU**************************************/\n                                          /**\n                                           * 单位：%\n                                           */\n                                          CPU_USAGE(\"cpuUsage\", \"cpu使用率\"),\n                                          /**\n                                           * 单位：无\n                                           */\n                                          CPU_LOAD_1M(\"cpuLoad1M\", \"cpu 1分钟负载\"),\n                                          /**\n                                           * 单位：无\n                                           */\n                                          CPU_LOAD_5M(\"cpuLoad5M\", \"cpu 5分钟负载\"),\n                                          /**\n                                           * 单位：无\n                                           */\n                                          CPU_LOAD_15M(\"cpuLoad15M\", \"cpu 15分钟负载\"),\n                                          /*************************************2.磁盘******************************************/\n                                          /**\n                                           * 单位：%\n                                           */\n                                          DISK_USAGE(\"diskUsage\", \"磁盘使用率\"),\n                                          /**\n                                           * 单位：GB\n                                           */\n                                          DISK_INFO(\"diskInfo\", \"磁盘使用情况\"),\n                                          /**\n                                           * 单位：%\n                                           */\n                                          NODES_FOR_DISK_USAGE_GTE_75PERCENT(\"nodesForDiskUsageGte75Percent\",\n                                                                             \"磁盘使用率（大于75%）\"),\n\n                                          /*************************************3.网络流量**************************************/\n                                          /**\n                                           * 单位：MB/S\n                                           */\n                                          RECV_TRANS_SIZE(\"recvTransSize\", \"网络入口流量\"),\n                                          /**\n                                           * 单位：MB/S\n                                           */\n                                          SEND_TRANS_SIZE(\"sendTransSize\", \"网络出口流量\"),\n\n                                          /*************************************4.shard******************************************/\n                                          /**\n                                           * 单位：个\n                                           */\n                                          SHARD_NUM(\"shardNu\", \"shard总数\"),\n                                          /**\n                                           * 单位：个\n                                           */\n                                          MOVING_SHARDS(\"movingShards\", \"正在搬迁shard\"),\n                                          /**\n                                           * 单位：个\n                                           */\n                                          UNASSIGN_SHARDS(\"unAssignShards\", \"未分配的shard\"),\n                                          /**\n                                           * 单位：个\n                                           */\n                                          BIG_SHARDS(\"bigShards\", \"大shard（大于50G）\"),\n\n                                          /*************************************5.index******************************************/\n                                          /**\n                                           * 单位：个\n                                           */\n                                          BIG_INDICES(\"bigIndices\", \"大索引（大于10亿）\"),\n\n                                          /*************************************6.node******************************************/\n                                          /**\n                                           * 单位：个\n                                           */\n                                          INVALID_NODES(\"invalidNodes\", \"无效节点\"),\n\n                                          /*************************************7.任务进程******************************************/\n                                          /**\n                                           * 单位：个\n                                           */\n                                          PENDING_TASKS(\"pendingTasks\", \"集群元数据变更堆积任务\"),\n\n                                          /*************************************8.read/write******************************************/\n                                          /**\n                                           * 单位：个/S\n                                           */\n                                          READ_QPS(\"readTps\", \"查询QPS\"),\n                                          /**\n                                           * 单位：个/S\n                                           */\n                                          WRITE_TPS(\"writeTps\", \"写入TPS\"),\n                                          /**\n                                           * 单位：ms\n                                           */\n                                          SEARCH_LATENCY(\"searchLatency\", \"查询耗时\"),\n                                          /**\n                                           * 单位：ms\n                                           */\n                                          INDEXING_LATENCY(\"indexingLatency\", \"写入耗时\"),\n                                          /**\n                                           * 单位：ms\n                                           */\n                                          TASK_COST(\"taskCost\", \"任务耗时\"),\n                                          /**\n                                           * 单位：个\n                                           */\n                                          TASK_NUM(\"taskCount\", \"任务数量\");\n\n    ClusterPhyClusterMetricsEnum(String type, String desc) {\n        this.type = type;\n        this.desc = desc;\n    }\n\n    private String type;\n\n    private String desc;\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public static ClusterPhyClusterMetricsEnum valueOfType(String type) {\n        if (null == type) {\n            return ClusterPhyClusterMetricsEnum.UNKNOWN;\n        }\n        for (ClusterPhyClusterMetricsEnum typeEnum : ClusterPhyClusterMetricsEnum.values()) {\n            if (type.equals(typeEnum.getType())) {\n                return typeEnum;\n            }\n        }\n\n        return ClusterPhyClusterMetricsEnum.UNKNOWN;\n    }\n\n    public static boolean hasExist(String metricsType) {\n        if (null == metricsType) {\n            return false;\n        }\n        for (ClusterPhyClusterMetricsEnum typeEnum : ClusterPhyClusterMetricsEnum.values()) {\n            if (metricsType.equals(typeEnum.getType())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public static List<String> getClusterPhyMetricsType() {\n        List<String> clusterPhyMetricsTypes = Lists.newArrayList();\n        for (ClusterPhyClusterMetricsEnum value : ClusterPhyClusterMetricsEnum.values()) {\n            if (UNKNOWN.getType().equals(value.getType())) {\n                continue;\n            }\n\n            clusterPhyMetricsTypes.add(value.type);\n        }\n\n        return clusterPhyMetricsTypes;\n    }\n\n    public static List<String> getDefaultClusterPhyMetricsCode() {\n        return getClusterPhyMetricsType();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/ClusterPhyIndicesMetricsEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\nimport com.google.common.collect.Lists;\n\nimport java.util.List;\n\n/**\n * @author gyp\n * @version 1.0\n * @date 2022/5/9\n */\npublic enum ClusterPhyIndicesMetricsEnum {\n    /*** 未知*/\n    UNKNOWN(\"\", \"未知\"),\n\n    /*************************************1.索引性能指标**************************************/\n    /**\n     * 单位：个\n     */\n    SHARDS_NUM(\"shardNu\", \"Shard数\"),\n    /**\n     * 单位：GB\n     */\n    INDEX_STORE_SIZE(\"store-size_in_bytes\", \"索引大小\"),\n    /**\n     * 单位：个\n     */\n    DOCS_NUM(\"docs-count\", \"文档总数\"),\n    /**\n     * 单位：次/S\n     */\n    INDEXING_RATE(\"indexing-index_total_rate\", \"写入速率\"),\n    /**\n     * 单位：MS\n     */\n    INDEXING_LATENCY(\"indexing-index_time_in_millis\", \"写入耗时\"),\n    /**\n     * 单位：MS\n     */\n    INDEXING_INDEX_TIME_PER_DOC(\"indexing-index_time_per_doc\", \"单个文档写入耗时\"),\n    /**\n     * 单位：个/S\n     */\n    QUERY_RATE(\"search-query_total_rate\", \"查询Query速率\"),\n    /**\n     * 单位：个/S\n     */\n    FETCH_RATE(\"search-fetch_total_rate\", \"查询Fetch速率\"),\n    /**\n     * 单位：MS\n     */\n    QUERY_LATENCY(\"cost-query_time_in_millis\", \"查询Query耗时\"),\n    /**\n     * 单位：MS\n     */\n    INDEX_LATENCY(\"cost-index_time_in_millis\", \"写入耗时\"),\n    /**\n     * 单位：MS\n     */\n    FETCH_LATENCY(\"cost-fetch_time_in_millis\", \"查询Fetch耗时\"),\n    /**\n     * 单位：次/MIN\n     */\n    SCROLL_RATE(\"search-scroll_total_rate\", \"查询Scroll次数/分钟\"),\n    /**\n     * 单位：MS\n     */\n    SCROLL_LATENCY(\"cost-scroll_time_in_millis\", \"查询Scroll耗时\"),\n    /**\n     * 单位：MS\n     */\n    MERGE_LATENCY(\"cost-merges-total_time_in_millis\", \"Merge耗时\"),\n    /**\n     * 单位：MS\n     */\n    REFRESH_LATENCY(\"cost-refresh-total_time_in_millis\", \"Refresh耗时\"),\n    /**\n     * 单位：MS\n     */\n    FLUSH_LATENCY(\"cost-flush-total_time_in_millis\", \"Flush耗时\"),\n    /**\n     * 单位：MB\n     */\n    QUERY_CACHE_SIZE(\"query_cache-memory_size_in_bytes\", \"query_cache大小\"),\n    /**\n     * 单位：次/S\n     */\n    MERGE_RATE(\"merges-total_rate\", \"Merge次/S\"),\n    /**\n     * 单位：次/S\n     */\n    REFRESH_RATE(\"refresh-total_rate\", \"Refresh次/S\"),\n    /**\n     * 单位：次/S\n     */\n    FLUSH_RATE(\"flush-total_rate\", \"Flush次数/S\"),\n    /**\n     * 单位：MB\n     */\n    SEGMENT_MEM_SIZE(\"segments-memory_in_bytes\", \"Segments大小\"),\n    /**\n     * 单位：MB\n     */\n    TERMS_MEM_SIZE(\"segments-term_vectors_memory_in_bytes\", \"terms_memory大小\"),\n    /**\n     * 单位：MB\n     */\n    POINT_MEM_SIZE(\"segments-points_memory_in_bytes\", \"points_memory大小\"),\n    /**\n     * 单位：MB\n     */\n    DOC_VALUE_MEM_SIZE(\"segments-doc_values_memory_in_bytes\",\"doc_values_memory大小\"),\n    /**\n     * 单位：MB\n     */\n    INDEX_WRITE_MEM_SIZE(\"segments-index_writer_memory_in_bytes\",\"index_writer_memory大小\"),\n    /**\n     * 单位：MB\n     */\n    TRANSLOG_SIZE(\"translog-size_in_bytes\", \"translog大小\"),\n    /**\n     * 单位：MS\n     */\n    INDEXING_TIME_PER_DOC(\"indices-indexing-index_time_per_doc\", \"索引单次操作文档耗时\"),\n    /**\n     * 单位：MS\n     */\n    MERGES_AVG_TIME(\"merges_avg_time\", \"单次merges操作耗时\"),\n    /**\n     * 单位：MS\n     */\n    REFRESH_AVG_TIME(\"refresh_avg_time\", \"单次refresh操作耗时\"),\n    /**\n     * 单位：MS\n     */\n    FLUSH_AVG_TIME(\"flush_avg_time\", \"单次flush操作耗时\"),\n    /**\n     * 单位：MB\n     */\n    SEGMENTS_STORED_FIELDS_MEM_SIZE(\"segments-stored_fields_memory_in_bytes\",\"segments-stored_fields内存大小\"),\n    /**\n     * 单位：MB\n     */\n    SEGMENTS_NORMS_MEM_SIZE(\"segments-norms_memory_in_bytes\",\"Norms内存大小\"),\n    /**\n     * 单位：MB\n     */\n    SEGMENTS_VERSION_MAP_MEM_SIZE(\"segments-version_map_memory_in_bytes\",\"Version Map内存大小\"),\n    /**\n     * 单位：MB\n     */\n    SEGMENTS_FIXED_BIT_SET_MEM_SIZE(\"segments-fixed_bit_set_memory_in_bytes\",\"Fixed Bitsets内存大小\"),\n    /**\n     * 单位：MB\n     */\n    FIELDDATA_MEM_SIZE(\"fielddata-memory_size_in_bytes\",\"Fielddata内存大小\"),\n    /**\n     * 单位：MB\n     */\n    SEGMENTS_REQUEST_CACHE_MEM_SIZE(\"request_cache-memory_size_in_bytes\",\"Request Cache内存大小\");\n\n    ClusterPhyIndicesMetricsEnum(String type, String desc) {\n        this.type = type;\n        this.desc = desc;\n    }\n\n    private String type;\n\n    private String desc;\n\n    public static boolean hasExist(String metricsType) {\n        if (null == metricsType) {\n            return false;\n        }\n        for (ClusterPhyIndicesMetricsEnum typeEnum : ClusterPhyIndicesMetricsEnum.values()) {\n            if (metricsType.equals(typeEnum.getType())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public static List<String> getClusterPhyIndicesMetricsType() {\n        List<String> clusterPhyIndicesMetricsTypes = Lists.newArrayList();\n        for (ClusterPhyIndicesMetricsEnum value : ClusterPhyIndicesMetricsEnum.values()) {\n            if (UNKNOWN.getType().equals(value.getType())) {\n                continue;\n            }\n\n            clusterPhyIndicesMetricsTypes.add(value.getType());\n        }\n\n        return clusterPhyIndicesMetricsTypes;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/ClusterPhyNodeMetricsEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\nimport com.google.common.collect.Lists;\n\nimport java.util.List;\n\n/**\n * @author gyp\n * @version 1.0\n * @date 2022/5/9\n */\npublic enum ClusterPhyNodeMetricsEnum {\n    /*** 未知*/\n    UNKNOWN(\"\", \"未知\"),\n\n    /*************************************1.系统指标**************************************/\n    /**\n     * 单位：%\n     */\n    CPU_USAGE_PERCENT(\"os-cpu-percent\", \"CPU利用率\"),\n    /**\n     * 单位：无\n     */\n    CPU_LOAD_AVERAGE_1M(\"os-cpu-load_average-1m\", \"cpu近1分钟内负载\"),\n    /**\n     * 单位：无\n     */\n    CPU_LOAD_AVERAGE_5M(\"os-cpu-load_average-5m\", \"cpu近5分钟内负载\"),\n    /**\n     * 单位：无\n     */\n    CPU_LOAD_AVERAGE_15M(\"os-cpu-load_average-15m\", \"cpu近15分钟内负载\"),\n    /**\n     * 单位：%\n     */\n\n    DISK_FREE_PERCENT(\"fs-total-disk_free_percent\", \"磁盘空闲率\"),\n    /**\n     * 单位：MB/S\n     */\n\n    TRANS_TX_RATE(\"transport-tx_count_rate\", \"网络发送速率\"),\n    /**\n     * 单位：MB/S\n     */\n\n    TRANS_RX_RATE(\"transport-rx_count_rate\", \"网络接收速率\"),\n    /**\n     * 单位：MB/S\n     */\n\n    TRANS_TX_SIZE(\"transport-tx_size_in_bytes_rate\", \"网络发送流量\"),\n    /**\n     * 单位：MB/S\n     */\n\n    TRANS_RX_SIZE(\"transport-rx_size_in_bytes_rate\", \"网络接收流量\"),\n\n    /*************************************2.节点-索引基本信息******************************************/\n    /**\n     * 单位：个/S\n     */\n\n    INDICES_INDEXING_RATE(\"indices-indexing-index_total_rate\", \"索引写入TPS\"),\n    /**\n     * 单位：次/S\n     */\n    INDICES_QUERY_CACHE_EVICTIONS(\"indices-query_cache-evictions\", \"query Cache evictions\"),\n    /**\n     * 单位：次/S\n     */\n    INDICES_REQUEST_CACHE_EVICTIONS(\"indices-request_cache-evictions\", \"request Cache eviction\"),\n    /**\n     * 单位：MS\n     */\n\n    INDICES_INDEXING_LATENCY(\"indices-indexing-index_time_in_millis\", \"索引写入耗时\"),\n    /**\n     * 单位：MS\n     */\n    INDICES_INDEXING_INDEX_TIME_PER_DOC(\"indices-indexing-index_time_per_doc\", \"单个文档写入耗时\"),\n    /**\n     * 单位：个/S\n     */\n\n    INDICES_QUERY_RATE(\"indices-search-query_total_rate\", \"Query QPS\"),\n    /**\n     * 单位：个/S\n     */\n    INDICES_FETCH_RATE(\"indices-search-fetch_total_rate\", \"Fetch QPS\"),\n    /**\n     * 单位：MS\n     */\n    INDICES_QUERY_LATENCY(\"indices-search-query_time_per_query\", \"索引Query耗时\"),\n\n    /**\n     * 单位：MS\n     */\n    INDICES_QUERY_TIME_IN_MILLIS(\"indices-search-query_time_in_millis\", \"索引Query耗时\"),\n    /**\n     * 单位：个\n     */\n    INDICES_QUERY_TOTAL(\"indices-search-query_total\", \"索引Query总数\"),\n    /**\n     * 单位：MS\n     */\n    INDICES_FETCH_LATENCY(\"indices-search-fetch_time_per_fetch\", \"索引Fetch耗时\"),\n    /**\n     * 单位：个\n     */\n    INDICES_CUREENT_SCROLL_NUM(\"indices-search-scroll_current\", \"Scroll当下请求量\"),\n    /**\n     * 单位：MS\n     */\n    INDICES_SCROLL_LATENCY(\"indices-search-scroll_avg_time\", \"Scroll请求耗时\"),\n    /**\n     * 单位：MS\n     */\n    INDICES_MERGE_LATENCY(\"indices-merges_avg_time\", \"Merge操作耗时\"),\n    /**\n     * 单位：次/MIN\n     */\n    INDICES_MERGES_NUM_PER_MIN(\"indices-merges-total\", \"每分钟merges操作次数\"),\n    /**\n     * 单位：次/MIN\n     */\n\n    INDICES_FLUSH_NUM_PER_MIN(\"indices-flush-total\", \"每分钟indices操作次数\"),\n    /**\n     * 单位：次/MIN\n     */\n    INDICES_REFRESH_NUM_PER_MIN(\"indices-refresh-total\", \"每分钟refresh操作次数\"),\n    /**\n     * 单位：MS\n     */\n    INDICES_REFRESH_LATENCY(\"indices-refresh_avg_time\", \"Refresh操作耗时\"),\n    /**\n     * 单位：MS\n     */\n    INDICES_FLUSH_LATENCY(\"indices-flush_avg_time\", \"Flush操作耗时\"),\n    /**\n     * 单位：MB\n     */\n    INDICES_UNCOMMITTED_TRANSLOG_SIZE(\"indices-translog-uncommitted_size_in_bytes\",\n            \"未提交Translog大小\"),\n    /**\n     * 单位：MB\n     */\n    INDICES_QUERY_CACHE_MEM_SIZE(\"indices-query_cache-memory_size_in_bytes\",\n            \"QueryCache内存占用大小\"),\n    /**\n     * 单位：MB\n     */\n    INDICES_REQUEST_CACHE_MEM_SIZE(\"indices-request_cache-memory_size_in_bytes\",\n            \"RequestCache内存占用大小\"),\n    /**\n     * 单位：次/MIN\n     */\n    INDICES_QUERY_CACHE_HIT_NUM(\"indices-query_cache-hit_count\", \"QueryCache内存命中次数\"),\n    /**\n     * 单位：次/MIN\n     */\n\n    INDICES_REQUEST_CACHE_HIT_NUM(\"indices-request_cache-hit_count\",\n            \"RequestCache内存命中次数\"),\n    /**\n     * 单位：次/MIN\n     */\n\n    INDICES_QUERY_CACHE_MISS_NUM(\"indices-query_cache-miss_count\",\n            \"QueryCache内存未命中次数\"),\n    /**\n     * 单位：次/MIN\n     */\n\n    INDICES_REQUEST_CACHE_MISS_NUM(\"indices-request_cache-miss_count\",\n            \"RequestCache内存未命中次数\"),\n\n    /**\n     * 单位：%\n     */\n\n    INDICES_QUERY_CACHE_HIT_RATE(\"indices-query_cache-hit_rate\",\n            \"Query Cache内存命中率\"),\n\n    /**\n     * 单位：%\n     */\n\n    INDICES_REQUEST_CACHE_HIT_RATE(\"indices-request_cache-hit_rate\",\n            \"Request Cache内存未命率\"),\n\n    /*************************************3.节点-索引高级指标**************************************/\n    /**\n     * 单位：个\n     */\n    HTTP_OPEN_NUM(\"http-current_open\", \"Http活跃连接数\"),\n    /**\n     * 单位：个\n     */\n    BUIK_QUEUE_SIZE(\"thread_pool-bulk-queue\", \"BulkQueue大小\"),\n    /**\n     * 单位：个\n     */\n    BUIK_REJECTED_NUM(\"thread_pool-bulk-rejected\", \"BulkRejected个数\"),\n    /**\n     * 单位：个\n     */\n    SEARCH_QUEUE_NUM(\"thread_pool-search-queue\", \"查询线程池queue数\"),\n    /**\n     * 单位：个\n     */\n    REFRESH_QUEUE_NUM(\"thread_pool-refresh-queue\", \"刷新线程池queue数\"),\n    /**\n     * 单位：个\n     */\n    ROLLUP_INDEXING_QUEUE_NUM(\"thread_pool-rollup_indexing-queue\", \"落盘线程池queue数\"),\n    /**\n     * 单位：个\n     */\n    MANAGEMENT_QUEUE_NUM(\"thread_pool-management-queue\", \"管理线程池queue数\"),\n    /**\n     * 单位：个\n     */\n    FORCE_MERGE_QUEUE_NUM(\"thread_pool-force_merge-queue\", \"合并线程池queue数\"),\n    /**\n     * 单位：个\n     */\n    SEARCH_REJECTED_NUM(\"thread_pool-search-rejected\", \"SearchRejected个数\"),\n    /**\n     * 单位：个\n     */\n    WRITE_REJECTED_NUM(\"thread_pool-write-rejected\", \"WriteRejected个数\"),\n    /**\n     * 单位：个\n     */\n    WRITE_QUEUE_SIZE(\"thread_pool-write-queue\", \"WriteQueue大小\"),\n    /**\n     * 单位：个\n     */\n    INDICES_SEGMENT_NUM(\"indices-segments-count\", \"索引Segement数 \"),\n    /**\n     * 单位：MB\n     */\n    INDICES_SEGMENT_MEM_SIZE(\"indices-segments-memory_in_bytes\", \"索引Segement内存大小\"),\n    /**\n     * 单位：MB\n     */\n    INDICES_TERM_VECTORS_MEM_SIZE(\"indices-segments-term_vectors_memory_in_bytes\",\n            \"索引term_vectors内存大小\"),\n    /**\n     * 单位：MB\n     */\n    INDICES_POINT_MEM_SIZE(\"indices-segments-points_memory_in_bytes\",\n            \"索引points内存大小\"),\n    /**\n     * 单位：MB\n     */\n    INDICES_DOC_VALUES_MEM_SIZE(\"indices-segments-doc_values_memory_in_bytes\",\n            \"索引doc_values内存大小\"),\n    /**\n     * 单位：MB\n     */\n    INDICES_NORMS_MEMORY_IN_BYTES(\"indices-segments-norms_memory_in_bytes\",\n            \"索引norMS内存大小\"),\n\n    /**\n     * 单位：MB\n     */\n    INDICES_FIXED_BIT_SET_MEMORY_IN_BYTES(\"indices-segments-fixed_bit_set_memory_in_bytes\",\n            \"索引Fixed Bitsets内存大小\"),\n\n    /**\n     * 单位：MB\n     */\n    INDICES_VERSION_MAP_MEMORY_IN_BYTES(\"indices-segments-version_map_memory_in_bytes\",\n            \"索引Version Map内存大小\"),\n    /**\n     * 单位：MB\n     */\n    INDICES_BREAKERS_FIELDDATA_LIMIT_SIZE_IN_BYTES(\"breakers-fielddata-estimated_size_in_bytes\",\n            \"索引Fielddata内存大小\"),\n\n    /**\n     * 单位：MB\n     */\n    INDICES_WRITE_MEM_SIZE(\"indices-segments-index_writer_memory_in_bytes\",\n            \"索引index_writer内存大小\"),\n    /**\n     * 单位：个\n     */\n    INDICES_NUM(\"indices-docs-count\", \"索引文档总数\"),\n\n    /**\n     * 单位：个\n     */\n    INDICES_NUM_DIFF(\"indices-docs-count_diff\", \"间隔时间索引文档差值\"),\n\n    /**\n     * 单位：MB\n     */\n    INDICES_SIZE(\"indices-store-size_in_bytes\", \"索引总存储大小\"),\n\n    /*************************************4.JVM指标******************************************/\n    /**\n     * 单位：次/S\n     */\n    YOUNG_GC_NUM(\"jvm-gc-young-collection_count_rate\", \"young-gc次数/S\"),\n    /**\n     * 单位：次/S\n     */\n    OLD_GC_NUM(\"jvm-gc-old-collection_count_rate\", \"old-gc次数/S\"),\n    /**\n     * 单位：MS\n     */\n    YOUNG_GC_LATENCY(\"jvm-gc-young-collection_avg_time\", \"young-gc耗时\"),\n    /**\n     * 单位：MS\n     */\n    OLD_GC_LATENCY(\"jvm-gc-old-collection_avg_time\", \"old-gc耗时\"),\n    /**\n     * 单位：MB\n     */\n    JVM_MEM_HEAP_USED(\"jvm-mem-heap_used_in_bytes\", \"JVM堆内存使用量\"),\n    /**\n     * 单位：MB\n     */\n    JVM_MEM_NON_HEAP_USED(\"jvm-mem-non_heap_used_in_bytes\", \"JVM堆外存使用量\"),\n    /**\n     * 单位：%\n     */\n    JVM_MEM_HEAP_PERCENT(\"jvm-mem-heap_used_percent\", \"JVM堆使用率\"),\n    /**\n     * 单位：MB\n     */\n    JVM_MEM_POOLS_YOUNG_USED_IN_BYTES(\"jvm-mem-pools-young-used_in_bytes\",\n            \"jvm堆内存young区使用空间\"),\n    /**\n     * 单位：MB\n     */\n    JVM_MEM_POOLS_OLD_USED_IN_BYTES(\"jvm-mem-pools-old-used_in_bytes\",\n            \"jvm堆内存old区使用空间\"),\n    /**\n     * 单位：MB\n     */\n    STORED_FIELDS_MEMORY_IN_BYTES(\"indices-segments-stored_fields_memory_in_bytes\",\n            \"indices-segments-stored_fields内存大小\"),\n\n    /*************************************5.BREAKERS指标******************************************/\n\n    /**\n     * 单位：MB\n     */\n    BREAKERS_FIELDDATA_LIMIT_SIZE_IN_BYTES(\"breakers-fielddata-limit_size_in_bytes\",\n            \"Field data circuit breaker 内存占用\"),\n    /**\n     * 单位：MB\n     */\n    BREAKERS_REQUEST_LIMIT_SIZE_IN_BYTES(\"breakers-request-limit_size_in_bytes\",\n            \"Request circuit breaker 内存占用\"),\n\n    /**\n     * 单位：MB\n     */\n    BREAKERS_IN_FLIGHT_REQUESTS_LIMIT_SIZE_IN_BYTES(\"breakers-in_flight_requests-limit_size_in_bytes\",\n            \"inflight requests circuit breaker 内存占用\"),\n\n    /**\n     * 单位：MB\n     */\n    BREAKERS_IN_FLIGHT_HTTP_REQUESTS_LIMIT_SIZE_IN_BYTES(\"breakers-in_flight_http_requests-limit_size_in_bytes\",\n            \"inflight requests http circuit breaker 内存占用\"),\n\n    /**\n     * 单位：MB\n     */\n    BREAKERS_ACCOUNTING_LIMIT_SIZE_IN_BYTES(\"breakers-accounting-limit_size_in_bytes\",\n            \"Accounting requests circuit breaker 内存占用\"),\n\n    /**\n     * 单位：次/MIN\n     */\n    SCRIPT_COMPILATIONS(\"script-compilations\",\n            \"Script compilation circuit breaker 编译次数\"),\n\n    /**\n     * 单位：MB\n     */\n    BREAKERS_PARENT_LIMIT_SIZE_IN_BYTES(\"breakers-parent-limit_size_in_bytes\",\n            \"Parent circuit breaker JVM真实内存占用\"),\n\n    /*************************************6.TASK指标******************************************/\n    TASK_COUNT(\"taskId\", \"task id\"), TASK_COST(\"runningTime\", \"task耗时\");\n\n    ClusterPhyNodeMetricsEnum(String type, String desc) {\n        this.type = type;\n        this.desc = desc;\n\n    }\n\n    private String type;\n\n    private String desc;\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public static boolean hasExist(String metricsType) {\n        if (null == metricsType) {\n            return false;\n        }\n        for (ClusterPhyNodeMetricsEnum typeEnum : ClusterPhyNodeMetricsEnum.values()) {\n            if (metricsType.equals(typeEnum.getType())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public static List<String> getClusterPhyNodeMetricsType() {\n        List<String> clusterPhyNodeMetricsTypes = Lists.newArrayList();\n        for (ClusterPhyNodeMetricsEnum value : ClusterPhyNodeMetricsEnum.values()) {\n            if (UNKNOWN.getType().equals(value.getType())) {\n                continue;\n            }\n\n            clusterPhyNodeMetricsTypes.add(value.getType());\n        }\n\n        return clusterPhyNodeMetricsTypes;\n    }\n\n    public static List<String> getPercentMetricsType() {\n        return Lists.newArrayList(DISK_FREE_PERCENT.getType());\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/ClusterPhyTypeMetricsEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\n/**\n * Created by linyunan on 2021-08-01\n */\npublic enum ClusterPhyTypeMetricsEnum {\n    /*** 未知*/\n    UNKNOWN(-1, \"未知\",false),\n    CLUSTER(1, \"clusterPhyOverviewMetrics\",false),\n    NODE(2, \"clusterPhyNodeMetrics\", true),\n    INDICES(3, \"clusterPhyIndicesMetrics\", true),\n    TEMPLATES(4, \"clusterPhyTemplateMetrics\", true),\n    NODE_TASKS(5, \"clusterPhyNodesTaskMetricsHandler\", true);\n\n    ClusterPhyTypeMetricsEnum(int code, String type, boolean collectCurveMetricsList) {\n        this.code = code;\n        this.type = type;\n        this.collectCurveMetricsList = collectCurveMetricsList;\n    }\n\n    private int code;\n\n    private String type;\n\n    private boolean collectCurveMetricsList;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public boolean isCollectCurveMetricsList() {\n        return collectCurveMetricsList;\n    }\n\n    public static ClusterPhyTypeMetricsEnum valueOfCode(Integer code) {\n        if (null == code) {\n            return ClusterPhyTypeMetricsEnum.UNKNOWN;\n        }\n        for (ClusterPhyTypeMetricsEnum typeEnum : ClusterPhyTypeMetricsEnum.values()) {\n            if (code.equals(typeEnum.getCode())) {\n                return typeEnum;\n            }\n        }\n\n        return ClusterPhyTypeMetricsEnum.UNKNOWN;\n    }\n\n    public static ClusterPhyTypeMetricsEnum valueOfType(String type) {\n        if (null == type) {\n            return ClusterPhyTypeMetricsEnum.UNKNOWN;\n        }\n        for (ClusterPhyTypeMetricsEnum typeEnum : ClusterPhyTypeMetricsEnum.values()) {\n            if (type.equals(typeEnum.getType())) {\n                return typeEnum;\n            }\n        }\n\n        return ClusterPhyTypeMetricsEnum.UNKNOWN;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/ConfigTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\npublic enum ConfigTypeEnum {\n    /**\n     * code表示编号\n     * config_type表示是哪个功能的个性化配置\n     */\n    /**\n     * dashboard和指标看板\n     */\n    DASHBOARD_AND_METRICS_BOARD(\"dashboard_and_metrics_board\",1),\n    /**\n     * 检索查询大菜单下的查询模板\n     */\n    RETRIEVE_TEMPLATE(\"retrieve_template\",2);\n\n    private String configType;\n    private int code;\n    ConfigTypeEnum(String configType,int code){\n        this.configType=configType;\n        this.code=code;\n    }\n\n    public String getConfigType() {\n        return configType;\n    }\n\n    public int getCode() {\n        return code;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/DashBoardMetricListTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\nimport com.google.common.collect.Lists;\nimport org.apache.commons.collections4.CollectionUtils;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 3/11/22\n */\npublic enum DashBoardMetricListTypeEnum {\n    UNKNOWN(OneLevelTypeEnum.UNKNOWN, \"\", \"未知\"),\n    CLUSTER_ELAPSED_TIME_GTE_5MIN(OneLevelTypeEnum.CLUSTER, \"clusterElapsedTimeGte5Min\", \"采集超过5分钟\"),\n    NODE_DEAD(OneLevelTypeEnum.NODE, \"dead\", \"节点是否死亡\"),\n    NODE_LARGE_DISK_USAGE(OneLevelTypeEnum.NODE, \"largeDiskUsage\", \"磁盘利用率是否超红线\"),\n    NODE_LARGE_HEAD(OneLevelTypeEnum.NODE, \"largeHead\", \"堆内存利用率是否超红线\"),\n    NODE_LARGE_CPU_USAGE(OneLevelTypeEnum.NODE, \"largeCpuUsage\", \"CPU利用率是否超红线\"),\n    NODE_WRITE_REJECTED_NUM(OneLevelTypeEnum.NODE, \"writeRejectedNum\", \"WriteRejected节点\"),\n    NODE_SEARCH_REJECTED_NUM(OneLevelTypeEnum.NODE, \"searchRejectedNum\", \"SearchRejected节点\"),\n    NODE_SHARD_NUM(OneLevelTypeEnum.NODE, \"shardNum\", \"shardNum节点\"),\n    CLUSTER_SHARD_NUM(OneLevelTypeEnum.CLUSTER, \"shardNum\", \"shardNum节点\"),\n    \n    TEMPLATE_SEGMENT_MEM_NUM(OneLevelTypeEnum.TEMPLATE, \"segmentMemSize\", \"模板Segments内存大小（MB）\"),\n    TEMPLATE_SEGMENT_NUM(OneLevelTypeEnum.TEMPLATE, \"segmentNum\", \"模板Segments个数\"),\n    \n    INDEX_RED(OneLevelTypeEnum.INDEX, \"red\", \"是否RED索引\"),\n    INDEX_SINGLE_REP(OneLevelTypeEnum.INDEX, \"singReplicate\", \"是否单副本索引\"),\n    INDEX_UNASSIGNED_SHARD(OneLevelTypeEnum.INDEX, \"unassignedShard\", \"是否是未分配shard索引\"),\n    INDEX_BIG_SHARD(OneLevelTypeEnum.INDEX, \"bigShard\", \"大shard索引列表\"),\n    INDEX_SMALL_SHARD(OneLevelTypeEnum.INDEX, \"smallShard\", \"小shard索引列表\"),\n    INDEX_MAPPING_NUM(OneLevelTypeEnum.INDEX, \"mappingNum\", \"索引Mapping字段个数\"),\n    INDEX_SEGMENT_NUM(OneLevelTypeEnum.INDEX, \"segmentNum\", \"索引Segments个数\"),\n    INDEX_SEGMENT_MEM_SIZE(OneLevelTypeEnum.INDEX, \"segmentMemSize\", \"索引Segments内存大小（MB）\");\n    \n    DashBoardMetricListTypeEnum(OneLevelTypeEnum oneLevelTypeEnum, String type, String desc) {\n        this.oneLevelTypeEnum = oneLevelTypeEnum;\n        this.type = type;\n        this.desc = desc;\n    }\n    \n    private OneLevelTypeEnum oneLevelTypeEnum;\n    private String           type;\n    private String           desc;\n    \n    public String getType() {\n        return type;\n    }\n    \n    public String getDesc() {\n        return desc;\n    }\n    \n    public OneLevelTypeEnum getOneLevelTypeEnum() {\n        return oneLevelTypeEnum;\n    }\n    \n    public static boolean hasExist(String oneLevelType, String metricsType) {\n        if (null == metricsType) {\n            return false;\n        }\n        for (DashBoardMetricListTypeEnum typeEnum : DashBoardMetricListTypeEnum.values()) {\n            OneLevelTypeEnum oneLevelTypeEnum = typeEnum.getOneLevelTypeEnum();\n            if (oneLevelTypeEnum.getType().equals(oneLevelType) && metricsType.equals(typeEnum.getType())) {\n                return true;\n            }\n        }\n        \n        return false;\n    }\n    \n    public static DashBoardMetricListTypeEnum valueOfType(String type) {\n        if (null == type) {\n            return DashBoardMetricListTypeEnum.UNKNOWN;\n        }\n        \n        for (DashBoardMetricListTypeEnum typeEnum : DashBoardMetricListTypeEnum.values()) {\n            if (type.equals(typeEnum.getType())) {\n                return typeEnum;\n            }\n        }\n        \n        return DashBoardMetricListTypeEnum.UNKNOWN;\n    }\n\n    public static DashBoardMetricListTypeEnum valueOfTypeAndOneLevelType(String type,String oneLevelType) {\n        if (null == type) {\n            return DashBoardMetricListTypeEnum.UNKNOWN;\n        }\n\n        for (DashBoardMetricListTypeEnum typeEnum : DashBoardMetricListTypeEnum.values()) {\n            if (type.equals(typeEnum.getType())&&oneLevelType.equals(typeEnum.getOneLevelTypeEnum().getType())) {\n                return typeEnum;\n            }\n        }\n\n        return DashBoardMetricListTypeEnum.UNKNOWN;\n    }\n    \n    public static List<DashBoardMetricListTypeEnum> valueOfTypes(List<String> types) {\n        List<DashBoardMetricListTypeEnum> resList = Lists.newArrayList();\n        if (CollectionUtils.isEmpty(types)) {\n            return resList;\n        }\n        \n        for (String s : types) {\n            if (null == s) {\n                continue;\n            }\n            \n            for (DashBoardMetricListTypeEnum typeEnum : DashBoardMetricListTypeEnum.values()) {\n                if (s.equals(typeEnum.getType())) {\n                    resList.add(typeEnum);\n                }\n            }\n        }\n        \n        return resList;\n    }\n    \n    public static List<String> getFaultTypeList() {\n        return Lists.newArrayList(NODE_DEAD.getType(), INDEX_RED.getType(), INDEX_SINGLE_REP.getType(),\n                INDEX_BIG_SHARD.getType(), INDEX_SMALL_SHARD.getType(), CLUSTER_ELAPSED_TIME_GTE_5MIN.getType(),\n                INDEX_UNASSIGNED_SHARD.getType());\n    }\n    \n    public static List<String> getValueTypeList() {\n        return Lists.newArrayList(NODE_WRITE_REJECTED_NUM.getType(), NODE_SEARCH_REJECTED_NUM.getType(),\n                NODE_SHARD_NUM.getType(),CLUSTER_SHARD_NUM.getType(), NODE_LARGE_DISK_USAGE.getType(), NODE_LARGE_HEAD.getType(),\n                NODE_LARGE_CPU_USAGE.getType(), TEMPLATE_SEGMENT_MEM_NUM.getType(), TEMPLATE_SEGMENT_NUM.getType(),\n                INDEX_MAPPING_NUM.getType(), INDEX_SEGMENT_MEM_SIZE.getType(), INDEX_SEGMENT_NUM.getType());\n    }\n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/DashBoardMetricListTypeWithExtendValueFieldEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\n/**\n * @author gyp\n * @version 1.0\n * @description: 需要获取额外的值进行展示的指标项，因为有的指标项之前没有设计展示值，比如bigshard，\n *               采集的时候是true和false，现在需要展示大小，就需要添加额外的采集字段进行获取\n * @date 2022/6/22 19:44\n */\npublic enum DashBoardMetricListTypeWithExtendValueFieldEnum {\n    SMALL_SHARD(DashBoardMetricListTypeEnum.INDEX_SMALL_SHARD.getType(),\"shardSize\"),\n    BIG_SHARD(DashBoardMetricListTypeEnum.INDEX_BIG_SHARD.getType(),\"shardSize\"),\n    CLUSTER_ELAPSED_TIME_GTE_5_MIN(DashBoardMetricListTypeEnum.CLUSTER_ELAPSED_TIME_GTE_5MIN.getType(),\"collectorDelayed\");\n\n    /**\n     * 统计指标项，eg。smallShard，bigShard\n     */\n    private String metricType;\n\n    /**\n     * 新增额外的展示需要的字段 eg,小shard列表中的shard大小\n     */\n    private String extendValueField;\n\n    DashBoardMetricListTypeWithExtendValueFieldEnum(String metricType, String valueType) {\n        this.metricType = metricType;\n        this.extendValueField = valueType;\n    }\n\n    public String getMetricType() {\n        return metricType;\n    }\n\n    public void setMetricType(String metricType) {\n        this.metricType = metricType;\n    }\n\n    public String getExtendValueField() {\n        return extendValueField;\n    }\n\n    public void setExtendValueField(String extendValueField) {\n        this.extendValueField = extendValueField;\n    }\n\n    public static DashBoardMetricListTypeWithExtendValueFieldEnum valueOfMetricType(String metricType) {\n        if (null == metricType) {\n            return null;\n        }\n\n        for (DashBoardMetricListTypeWithExtendValueFieldEnum typeEnum : DashBoardMetricListTypeWithExtendValueFieldEnum.values()) {\n            if (metricType.equals(typeEnum.getMetricType())) {\n                return typeEnum;\n            }\n        }\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/DashBoardMetricOtherTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\nimport com.google.common.collect.Lists;\nimport org.apache.commons.collections4.CollectionUtils;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 3/11/22\n */\npublic enum DashBoardMetricOtherTypeEnum {\n                                          UNKNOWN(\"\", \"未知\"), CLUSTER_HEALTH(\"clusterPhyHealth\", \"健康度\");\n\n    DashBoardMetricOtherTypeEnum(String type, String desc) {\n        this.type = type;\n        this.desc = desc;\n    }\n\n    private String type;\n    private String desc;\n\n    public String getType() {\n        return type;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static boolean hasExist(String metricsType) {\n        if (null == metricsType) {\n            return false;\n        }\n        for (DashBoardMetricOtherTypeEnum typeEnum : DashBoardMetricOtherTypeEnum.values()) {\n            if (metricsType.equals(typeEnum.getType())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public static DashBoardMetricOtherTypeEnum valueOfType(String type) {\n        if (null == type) {\n            return DashBoardMetricOtherTypeEnum.UNKNOWN;\n        }\n\n        for (DashBoardMetricOtherTypeEnum typeEnum : DashBoardMetricOtherTypeEnum.values()) {\n            if (type.equals(typeEnum.getType())) {\n                return typeEnum;\n            }\n        }\n\n        return DashBoardMetricOtherTypeEnum.UNKNOWN;\n    }\n\n    public static List<DashBoardMetricOtherTypeEnum> valueOfTypes(List<String> types) {\n        List<DashBoardMetricOtherTypeEnum> resList = Lists.newArrayList();\n        if (CollectionUtils.isEmpty(types)) {\n            return resList;\n        }\n\n        for (String s : types) {\n            if (null == s) {\n                continue;\n            }\n\n            for (DashBoardMetricOtherTypeEnum typeEnum : DashBoardMetricOtherTypeEnum.values()) {\n                if (s.equals(typeEnum.getType())) {\n                    resList.add(typeEnum);\n                }\n            }\n        }\n\n        return resList;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/DashBoardMetricThresholdValueNameEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\nimport com.google.common.collect.Lists;\n\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.*;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricListTypeEnum.*;\n\n/**\n * dashboard默认的配置\n */\npublic enum DashBoardMetricThresholdValueNameEnum {\n    /**\n     * {\"name\":\"索引Segments个数\",\"metrics\":\"segmentNum\",\"unit\":\"个\",\"compare\":\">\",\"value\":1}\n     * {\"name\":\"模板Segments个数\",\"metrics\":\"segmentNum\"\"unit\":\"个\",\"compare\":\">\",\"value\":1}\n     * {\"name\":\"索引Segments内存大小\",\"metrics\":\"segmentMemSize\"\"unit\":\"kb\",\"compare\":\">\",\"value\":1}\n     * {\"name\":\"模板Segments内存大小\",\"metrics\":\"segmentMemSize\",\"unit\":\"kb\",\"compare\":\">\",\"value\":50}\n     * {\"name\":\"节点分片个数\",\"metrics\":\"shardNum\"\"unit\":\"个\",\"compare\":\">\",\"value\":500}\n     * {\"name\":\"小shard索引列表\",\"metrics\":\"shardSize\",\"unit\":\"个\",\"compare\":\">\",\"value\":100}\n     * {\"name\":\"索引Mapping个数\",\"metrics\":\"mappingNum\",\"unit\":\"个\",\"compare\":\">\",\"value\":100}\n     * {\"name\":\"集群shard个数\",\"metrics\":\"shardNum\",\"unit\":\"个\",\"compare\":\">\",\"value\":10000}\n     */\n\n    INDEX_SEGMENTS_NUM_THRESHOLD(INDEX_SEGMENT_NUM_THRESHOLD,INDEX_SEGMENT_NUM,DASHBOARD_INDEX_SEGMENT_NUM_THRESHOLD_DEFAULT_VALUE),\n    TEMPLATE_SEGMENTS_NUM_THRESHOLD(INDEX_TEMPLATE_SEGMENT_COUNT_THRESHOLD,TEMPLATE_SEGMENT_NUM,DASHBOARD_INDEX_TEMPLATE_SEGMENT_COUNT_THRESHOLD_DEFAULT_VALUE),\n    INDEX_SEGMENTS_MEN_SIZE_THRESHOLD(INDEX_SEGMENT_MEMORY_SIZE_THRESHOLD,INDEX_SEGMENT_MEM_SIZE,DASHBOARD_INDEX_SEGMENT_MEMORY_SIZE_THRESHOLD_DEFAULT_VALUE),\n    TEMPLATE_SEGMENTS_MEN_SIZE_THRESHOLD(INDEX_TEMPLATE_SEGMENT_MEMORY_SIZE_THRESHOLD,TEMPLATE_SEGMENT_MEM_NUM,DASHBOARD_INDEX_TEMPLATE_SEGMENT_MEMORY_SIZE_THRESHOLD_DEFAULT_VALUE),\n    NODE_SHARD_SIZE_THRESHOLD(NODE_SHARD_NUM_THRESHOLD,NODE_SHARD_NUM,DASHBOARD_NODE_SHARD_NUM_THRESHOLD_DEFAULT_VALUE),\n    MAPPING_NUM_THRESHOLD(INDEX_MAPPING_NUM_THRESHOLD,INDEX_MAPPING_NUM,DASHBOARD_INDEX_MAPPING_NUM_THRESHOLD_DEFAULT_VALUE),\n    INDEX_SMALL_SHARD_THRESHOLD(INDEX_SHARD_SMALL_THRESHOLD,INDEX_SMALL_SHARD,DASHBOARD_INDEX_SHARD_SMALL_THRESHOLD_DEFAULT_VALUE),\n    COLLECTOR_DELAYED_THRESHOLD(DASHBOARD_CLUSTER_METRIC_COLLECTOR_DELAYED_THRESHOLD,CLUSTER_ELAPSED_TIME_GTE_5MIN,DASHBOARD_CLUSTER_METRIC_COLLECTOR_DELAYED_DEFAULT_VALUE),\n    SHARD_NUM_THRESHOLD(CLUSTER_SHARD_NUM_THRESHOLD,CLUSTER_SHARD_NUM, DASHBOARD_CLUSTER_SHARD_NUM_THRESHOLD_DEFAULT_VALUE);\n    /**\n     * 配置名称\n     */\n    private String configName;\n\n    /**\n     *\n     */\n    private DashBoardMetricListTypeEnum typeEnum;\n    /**\n     * 名称\n     */\n    private String defaultValue;\n\n    DashBoardMetricThresholdValueNameEnum(String configName, DashBoardMetricListTypeEnum typeEnum, String defaultValue) {\n        this.configName = configName;\n        this.typeEnum = typeEnum;\n        this.defaultValue = defaultValue;\n    }\n\n    public String getConfigName() {\n        return configName;\n    }\n\n    public void setConfigName(String configName) {\n        this.configName = configName;\n    }\n\n    public DashBoardMetricListTypeEnum getTypeEnum() {\n        return typeEnum;\n    }\n\n    public void setTypeEnum(DashBoardMetricListTypeEnum typeEnum) {\n        this.typeEnum = typeEnum;\n    }\n\n    public String getDefaultValue() {\n        return defaultValue;\n    }\n\n    public void setDefaultValue(String defaultValue) {\n        this.defaultValue = defaultValue;\n    }\n\n    public static List<DashBoardMetricThresholdValueNameEnum> getAllDefaultThresholdValue(){\n        List<DashBoardMetricThresholdValueNameEnum> list = Lists.newArrayList();\n        for (DashBoardMetricThresholdValueNameEnum typeEnum : DashBoardMetricThresholdValueNameEnum.values()) {\n            list.add(typeEnum);\n        }\n        return list;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/DashBoardMetricTopTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\nimport com.google.common.collect.Lists;\nimport org.apache.commons.collections4.CollectionUtils;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 3/11/22\n */\npublic enum DashBoardMetricTopTypeEnum {\n\n    UNKNOWN(OneLevelTypeEnum.UNKNOWN, \"\", \"未知\"),\n    CLUSTER_ELAPSED_TIME(OneLevelTypeEnum.CLUSTER, \"clusterElapsedTime\", \"cluster_stats 接口平均采集耗时(s)\"),\n    NODE_ELAPSED_TIME(OneLevelTypeEnum.CLUSTER, \"nodeElapsedTime\", \"nodes_stats 接口平均采集耗时(s)\"),\n\n    CLUSTER_ELAPSED_TIME_GTE_5MIN(OneLevelTypeEnum.CLUSTER, \"elapsedTimeGte5Min\", \"采集耗时大于5分钟\"),\n    CLUSTER_INDEXING_LATENCY(OneLevelTypeEnum.CLUSTER, \"indexingLatency\", \"写入耗时\"),\n    CLUSTER_SEARCH_LATENCY(OneLevelTypeEnum.CLUSTER, \"searchLatency\", \"查询耗时\"),\n    CLUSTER_INDEX_REQ_NUM(OneLevelTypeEnum.CLUSTER, \"indexReqNum\", \"写入文档数\"),\n    CLUSTER_GATEWAY_SUC_PER(OneLevelTypeEnum.CLUSTER, \"gatewaySucPer\", \"网关成功率\"),\n    CLUSTER_GATEWAY_FAILED_PER(OneLevelTypeEnum.CLUSTER, \"gatewayFailedPer\", \"网关失败率\"),\n    CLUSTER_PENDING_TASK_NUM(OneLevelTypeEnum.CLUSTER, \"pendingTaskNum\", \"集群pending-task数\"),\n    CLUSTER_HTTP_NUM(OneLevelTypeEnum.CLUSTER, \"httpNum\", \"集群http连接数\"),\n    CLUSTER_DOC_UPRUSH_NUM(OneLevelTypeEnum.CLUSTER, \"docUprushNum\", \"查询请求数突增集群\"),\n    CLUSTER_REQ_UPRUSH_NUM(OneLevelTypeEnum.CLUSTER, \"reqUprushNum\", \"写入文档数突增集群\"),\n    CLUSTER_SHARD_NUM(OneLevelTypeEnum.CLUSTER, \"shardNum\", \"集群shard个数\"),\n    NODE_TASK_CONSUMING(OneLevelTypeEnum.NODE, \"taskConsuming\", \"节点分片耗时\"),\n    INDEX_REQ_UPRUSH_NUM(OneLevelTypeEnum.INDEX, \"reqUprushNum\", \"查询请求数突增索引\"),\n    NODE_DOC_UPRUSH_NUM(OneLevelTypeEnum.INDEX, \"docUprushNum\", \"写入文档数突增索引\"),\n\n    MANAGEMENT_QUEUE(OneLevelTypeEnum.CLUSTER_THREAD_POOL_QUEUE, \"management\", \"集群管理queue数\"),\n    REFRESH_QUEUE(OneLevelTypeEnum.CLUSTER_THREAD_POOL_QUEUE, \"refresh\", \"集群刷新线程池queue数\"),\n    FLUSH_QUEUE(OneLevelTypeEnum.CLUSTER_THREAD_POOL_QUEUE, \"flush\", \"集群落盘刷新线程池queue数\"),\n    MERGE_QUEUE(OneLevelTypeEnum.CLUSTER_THREAD_POOL_QUEUE, \"merge\", \"集群合并线程池queue数\"),\n    SEARCH_QUEUE(OneLevelTypeEnum.CLUSTER_THREAD_POOL_QUEUE, \"search\", \"集群查询理线程池queue数\"),\n    WRITE_QUEUE(OneLevelTypeEnum.CLUSTER_THREAD_POOL_QUEUE, \"write\", \"集群写入线程池queue数\");\n\n    DashBoardMetricTopTypeEnum(OneLevelTypeEnum oneLevelTypeEnum, String type, String desc) {\n        this.oneLevelTypeEnum = oneLevelTypeEnum;\n        this.type = type;\n        this.desc = desc;\n    }\n\n    private OneLevelTypeEnum oneLevelTypeEnum;\n    private String desc;\n    private String type;\n\n    public String getType() {\n        return type;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public OneLevelTypeEnum getOneLevelTypeEnum() {\n        return oneLevelTypeEnum;\n    }\n\n    public static boolean hasExist(String oneLevelType, String metricsType) {\n        if (null == metricsType) {\n            return false;\n        }\n        for (DashBoardMetricTopTypeEnum typeEnum : DashBoardMetricTopTypeEnum.values()) {\n            OneLevelTypeEnum oneLevelTypeEnum = typeEnum.getOneLevelTypeEnum();\n            if (oneLevelTypeEnum.getType().equals(oneLevelType) && metricsType.equals(typeEnum.getType())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public static DashBoardMetricTopTypeEnum valueOfType(String type) {\n        if (null == type) {\n            return DashBoardMetricTopTypeEnum.UNKNOWN;\n        }\n\n        for (DashBoardMetricTopTypeEnum typeEnum : DashBoardMetricTopTypeEnum.values()) {\n            if (type.equals(typeEnum.getType())) {\n                return typeEnum;\n            }\n        }\n\n        return DashBoardMetricTopTypeEnum.UNKNOWN;\n    }\n\n    public static List<DashBoardMetricTopTypeEnum> valueOfTypes(List<String> types) {\n        List<DashBoardMetricTopTypeEnum> resList = Lists.newArrayList();\n        if (CollectionUtils.isEmpty(types)) {\n            return resList;\n        }\n\n        for (String s : types) {\n            if (null == s) {\n                continue;\n            }\n\n            for (DashBoardMetricTopTypeEnum typeEnum : DashBoardMetricTopTypeEnum.values()) {\n                if (s.equals(typeEnum.getType())) {\n                    resList.add(typeEnum);\n                }\n            }\n        }\n\n        return resList;\n    }\n\n    /**\n     * 需要特殊处理的指标项，这里需要过滤去除指标值为-1\n     *\n     * @return List<String>\n     */\n    public static List<String> listNoNegativeMetricTypes() {\n        return Lists.newArrayList(CLUSTER_GATEWAY_SUC_PER.getType(),\n                /**\n                 * 未知\n                 */CLUSTER_GATEWAY_FAILED_PER.getType());\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/ESHttpRequestContent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\n\n/**\n * Created by linyunan on 2021-08-11\n */\npublic class ESHttpRequestContent {\n\n    private ESHttpRequestContent() {\n    }\n\n    /**\n     * 获取集群搬迁shard\n     */\n    public static final String GET_MOVING_SHARD            = \"_cat/recovery?v&h=i,shost,thost,br,bp,top&active_only=true\";\n\n    /**\n     * 获取集群pendingTask\n     */\n    public static final String GET_PENDING_TASKS           = \"/_cluster/pending_tasks\";\n    /**\n     * 获取集群http信息\n     */\n    public static final String GET_STATS_HTTP              = \"/_nodes/stats/http?level=cluster\";\n    public static final String GET_STATS_FS                = \"/_nodes/stats/fs?level=cluster\";\n\n    /**\n     * 获取集群索引信息\n     */\n    public static final String GET_INDICES                 = \"/_cat/indices?v&h=index,dc\";\n\n    /**\n     * 获取集群shard\n     */\n    public static final String GET_SHARDS                  = \"/_cat/shards/\";\n\n    /**\n     * 获取json格式的集群shard\n     */\n    public static final String GET_SHARDS_JSON                  = \"_cat/shards?format=json\";\n\n    /**\n     * 获取集群shard\n     */\n    public static final String GET_CLUSTER_STATS           = \"/_cluster/stats/\";\n\n    public static final String GET_SHARDS_ALL              = \"_cat/shards?v&h=index,prirep,shard,store,ip,node\";\n    public static final String GET_SHARDS_NODE             = \"_cat/shards?v&h=node\";\n\n    public static final String GET_TEMPLATE_NAME           = \"/_cat/templates?v&h=name\";\n\n    public static final String MASTER_TIMEOUT              = \"&master_timeout=\";\n\n    /**\n     * 获取集群模板segments 信息\n     */\n    public static final String GET_PATH_SEGMENTS           = \"/_cat/segments/\";\n\n    public static final String GET_PATH_SEGMENTS_PART_INFO = GET_PATH_SEGMENTS + \"?v&h=size,size.memory,index\";\n\n    public static final String GET_PATH_SEGMENTS_COUNT_INFO = GET_PATH_SEGMENTS + \"?v&h=index,prirep\";\n\n    /**\n     * 获取大索引请求内容\n     */\n    public static String getBigIndicesRequestContent(String masterTimeout) {\n        if (AriusObjUtils.isBlack(masterTimeout)) {\n            return GET_INDICES;\n        }\n        return GET_INDICES + MASTER_TIMEOUT + masterTimeout;\n    }\n\n    public static String getShardsAllInfoRequestContent(String masterTimeout) {\n        if (AriusObjUtils.isBlack(masterTimeout)) {\n            return GET_SHARDS_ALL;\n        }\n        return GET_SHARDS_ALL + MASTER_TIMEOUT + masterTimeout;\n    }\n\n    public static String getShards2NodeRequestContent(String masterTimeout) {\n        if (AriusObjUtils.isBlack(masterTimeout)) {\n            return GET_SHARDS_NODE;\n        }\n        return GET_SHARDS_NODE + MASTER_TIMEOUT + masterTimeout;\n    }\n\n    public static String getShardToNodeRequestContentByIndexName(String indexName, String masterTimeout) {\n        if (AriusObjUtils.isBlack(masterTimeout)) {\n            return GET_SHARDS + indexName + \"?v&h=node\";\n        }\n\n        return GET_SHARDS + indexName + \"?v&h=node\" + MASTER_TIMEOUT + masterTimeout;\n    }\n\n    public static String getShards2NodeInfoRequestContent(String indexName, String masterTimeout) {\n        if (AriusObjUtils.isBlack(masterTimeout)) {\n            return GET_SHARDS + indexName + \"?v\";\n        }\n\n        return GET_SHARDS + indexName + \"?v\" + MASTER_TIMEOUT + masterTimeout;\n    }\n\n    public static String getTemplateNameRequestContent() {\n        return GET_TEMPLATE_NAME;\n    }\n\n    public static String getSegmentsPartInfoRequestContent() { return GET_PATH_SEGMENTS_PART_INFO;}\n\n    public static String getSegmentsCountContent() { return GET_PATH_SEGMENTS_COUNT_INFO;}\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/GatewayMetricsTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\nimport com.google.common.collect.Lists;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * Created by fitz on 2021-08-12\n */\npublic enum GatewayMetricsTypeEnum {\n    /**\n     * overview metrics\n     */\n    QUERY_TOTAL_HITS_AVG_COUNT(MetricsConstant.OVERVIEW, \"queryTotalHitsAvgCount\",\"total_hits_avg\",\"平均查询命中数量\"),\n    QUERY_COST_AVG(MetricsConstant.OVERVIEW, \"queryCostAvg\", MetricsConstant.TOTAL_COST_AVG, \"查询平均响应时间\"),\n    QUERY_TOTAL_SHARDS_AVG(MetricsConstant.OVERVIEW, \"queryTotalShardsAvg\", \"total_shards_avg\", \"查询平均shard数量\"),\n    QUERY_FAILED_SHARDS_AVG(MetricsConstant.OVERVIEW, \"queryFailedShardsAvg\", \"failed_shards_avg\", \"查询失败平均shard数量\"),\n    READ_DOC_COUNT(MetricsConstant.OVERVIEW, \"readDocCount\", MetricsConstant.DOC_COUNT, \"查询量\"),\n    QUERY_SEARCH_TYPE(MetricsConstant.OVERVIEW, \"querySearchType\", MetricsConstant.DOC_COUNT, \"dsl/sql分布\"),\n    WRITE_DOC_COUNT(MetricsConstant.OVERVIEW, \"writeDocCount\", MetricsConstant.DOC_COUNT, \"写入量\"),\n    WRITE_TOTAL_COST(MetricsConstant.OVERVIEW, \"writeTotalCost\", MetricsConstant.TOTAL_COST_AVG, \"写入平均耗时\"),\n    DSL_LEN(MetricsConstant.OVERVIEW, \"dslLen\", \"dsl_len\", \"写入的dsl 长度\"),\n    WRITE_RESPONSE_LEN(MetricsConstant.OVERVIEW, \"writeResponseLen\", \"response_len_avg\", \"写入请求响应长度\"),\n\n    /**\n     * index metrics\n     */\n    WRITE_INDEX_COUNT(MetricsConstant.INDEX, \"writeIndexCount\", MetricsConstant.DOC_COUNT, \"索引写入量分布\"),\n    WRITE_INDEX_TOTAL_COST(MetricsConstant.INDEX, \"writeIndexTotalCost\", MetricsConstant.TOTAL_COST_AVG, \"索引平均写入耗时\"),\n    SEARCH_INDEX_COUNT(MetricsConstant.INDEX, \"searchIndexCount\", MetricsConstant.DOC_COUNT, \"索引查询量分布\"),\n    SEARCH_INDEX_TOTAL_COST(MetricsConstant.INDEX, \"searchIndexTotalCost\", MetricsConstant.TOTAL_COST_AVG, \"索引平均查询耗时\"),\n\n    /**\n     * gateway node metrics\n     */\n    WRITE_GATEWAY_NODE(MetricsConstant.NODE, \"writeGatewayNode\", MetricsConstant.DOC_COUNT, \"gateway节点写入量分布\"),\n    QUERY_GATEWAY_NODE(MetricsConstant.NODE, \"queryGatewayNode\", MetricsConstant.DOC_COUNT, \"gateway节点查询分布\"),\n    DSLLEN_GATEWAY_NODE(MetricsConstant.NODE, \"dslLen\", \"dsl_len\", \"gateway 节点写入dsl 长度\"),\n\n    /**\n     * es client node metrics\n     */\n    WRITE_CLIENT_NODE(MetricsConstant.CLIENT_NODE, \"writeClientNode\", MetricsConstant.DOC_COUNT, \"clientNode节点写入量分布\"),\n    QUERY_CLIENT_NODE(MetricsConstant.CLIENT_NODE, \"queryClientNode\", MetricsConstant.DOC_COUNT, \"clientNode节点查询分布\"),\n    DSLLEN_CLIENT_NODE(MetricsConstant.CLIENT_NODE, \"dslLen\", \"dsl_len\", \"client 节点写入dsl 长度\"),\n\n    /**\n     * 项目 metrics\n     */\n    QUERY_APP_SEARCH_COST(MetricsConstant.APP, \"queryAppSearchCost\", \"search_cost_avg\", \"projectId查询时间分布\"),\n    QUERY_APP_COUNT(MetricsConstant.APP, \"queryAppCount\", MetricsConstant.DOC_COUNT, \"projectId查询量\"),\n    QUERY_APP_TOTAL_COST(MetricsConstant.APP, \"queryAppTotalCost\", MetricsConstant.TOTAL_COST_AVG, \"projectId查询平均响应时间\"),\n\n    /**\n     * 查询模版 metrics\n     */\n    QUERY_DSL_COUNT(MetricsConstant.DSL, \"queryDslCount\", MetricsConstant.DOC_COUNT, \"查询模板访问量\"),\n    QUERY_DSL_TOTAL_COST(MetricsConstant.DSL, \"queryDslTotalCost\", MetricsConstant.TOTAL_COST_AVG, \"询模板访问耗时\");\n\n    /**\n     * @param group  分组，对应网管看板上面每一个tab\n     * @param type   指标名字\n     * @param aggKey dsl查询结果中聚合字段的key\n     * @param desc   指标描述\n     */\n    GatewayMetricsTypeEnum(String group, String type, String aggKey, String desc) {\n        this.group = group;\n        this.type = type;\n        this.aggKey = aggKey;\n        this.desc = desc;\n    }\n\n    public static final List<String> commonOverviewMetrics = Lists.newArrayList(QUERY_TOTAL_HITS_AVG_COUNT.getType(),\n            QUERY_COST_AVG.getType(), QUERY_TOTAL_SHARDS_AVG.getType(), QUERY_FAILED_SHARDS_AVG.getType());\n\n    public static final List<String> writeOverviewMetrics = Lists.newArrayList(WRITE_DOC_COUNT.getType(),\n            WRITE_TOTAL_COST.getType(), WRITE_RESPONSE_LEN.getType(), DSL_LEN.getType());\n\n    public static final List<String> writeIndexMetrics = Lists.newArrayList(WRITE_INDEX_COUNT.getType(),\n            WRITE_INDEX_TOTAL_COST.getType());\n    public static final List<String> searchIndexMetrics = Lists.newArrayList(SEARCH_INDEX_COUNT.getType(),\n            SEARCH_INDEX_TOTAL_COST.getType());\n\n    public static final List<String> commonAppMetrics = Lists.newArrayList(QUERY_APP_SEARCH_COST.getType(),\n            QUERY_APP_TOTAL_COST.getType());\n\n    /**\n     * 分组名称\n     */\n    private String group;\n\n    /**\n     * 指标名\n     */\n    private String type;\n\n    /**\n     * dsl聚合自定义key\n     */\n    private String aggKey;\n\n    /**\n     * 描述信息\n     */\n    private String desc;\n\n    public String getType() {\n        return type;\n    }\n\n    public String getGroup() {\n        return group;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public String getAggKey() {\n        return aggKey;\n    }\n\n    public static List<String> getMetricsByGroup(String group) {\n        return Arrays.stream(GatewayMetricsTypeEnum.values()).filter(x -> x.getGroup().equals(group))\n                .map(GatewayMetricsTypeEnum::getType).collect(Collectors.toList());\n\n    }\n\n    public static String type2AggKey(String type) {\n        for (GatewayMetricsTypeEnum gatewayMetricsTypeEnum : GatewayMetricsTypeEnum.values()) {\n            if (gatewayMetricsTypeEnum.getType().equals(type)) {\n                return gatewayMetricsTypeEnum.getAggKey();\n            }\n        }\n        return \"\";\n    }\n\n    public static GatewayMetricsTypeEnum type2Value(String type) {\n        for (GatewayMetricsTypeEnum gatewayMetricsTypeEnum : GatewayMetricsTypeEnum.values()) {\n            if (gatewayMetricsTypeEnum.getType().equals(type)) {\n                return gatewayMetricsTypeEnum;\n            }\n        }\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/MetricsConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\npublic class MetricsConstant {\n    private MetricsConstant() {\n    }\n\n    public static final String OVERVIEW       = \"overview\";\n    public static final String INDEX          = \"index\";\n    public static final String NODE           = \"node\";\n    public static final String CLIENT_NODE    = \"clientNode\";\n    public static final String APP            = \"app\";\n    public static final String DSL            = \"dsl\";\n    public static final String TOTAL_COST_AVG = \"total_cost_avg\";\n    public static final String DOC_COUNT      = \"doc_count\";\n    public static final String CLUSTER        = \"cluster\";\n    public static final String TEMPLATE       = \"template\";\n    public static final String GATEWAY        = \"gateway\";\n    public static final String USER_SHOW      = \"user_show\";\n    public static final String DASHBOARD      = \"dashboard\";\n\n    /**\n     * 作用于dashBoard list类型的指标项，判断是否异常 ，如：Dead节点列表 true是，false为否\n     */\n    public static final String FAULT_FLAG     = \"true\";\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/OneLevelTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\nimport java.util.List;\n\nimport com.google.common.collect.Lists;\n\npublic enum OneLevelTypeEnum {\n                              UNKNOWN(\"\"), CLUSTER(\"cluster\"), NODE(\"node\"), TEMPLATE(\"template\"), INDEX(\"index\"), CLUSTER_THREAD_POOL_QUEUE(\"clusterThreadPoolQueue\");\n\n    OneLevelTypeEnum(String type) {\n        this.type = type;\n    }\n\n    private String type;\n\n    public String getType() {\n        return type;\n    }\n\n    public static OneLevelTypeEnum valueOfType(String type) {\n        if (null == type) {\n            return OneLevelTypeEnum.UNKNOWN;\n        }\n\n        for (OneLevelTypeEnum typeEnum : OneLevelTypeEnum.values()) {\n            if (type.equals(typeEnum.getType())) {\n                return typeEnum;\n            }\n        }\n\n        return null;\n    }\n\n    public static List<String> listNoClusterOneLevelType() {\n        return Lists.newArrayList(NODE.getType(), TEMPLATE.getType(), INDEX.getType());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/metrics/UserConfigTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.metrics;\n\n/**\n * @author wangpengkai\n */\n\npublic enum UserConfigTypeEnum {\n\n                             /**\n                              * code表示编号\n                              * firstUserConfigType表示一级目录下指标配置信息，如集群看板和网关看板\n                              * secondUserConfigType表示二级目录下指标配置信息，如集群看板下的总览指标类型\n                              */\n                             /**\n                              * 未知的分类\n                              */\n                             UNKNOWN(-1, \"unknown\", \"unknown\"),\n                             /**\n                              * 集群看板下的总览指标\n                              */\n                             CLUSTER_OVERVIEW(11, MetricsConstant.CLUSTER, \"overview\"),\n                             /**\n                              * 集群看板下的节点指标\n                              */\n                             CLUSTER_NODE(12, MetricsConstant.CLUSTER, \"node\"),\n                             /**\n                              * 集群看板下的索引指标\n                              */\n                             CLUSTER_INDEX(13, MetricsConstant.CLUSTER, \"index\"),\n                             /**\n                              * 集群看板下的索引模板指标\n                              */\n                             CLUSTER_INDEX_TEMPLATE(14, MetricsConstant.CLUSTER, \"template\"),\n                             /**\n                              * 网关看板下的总览指标\n                              */\n                             GATEWAY_OVERVIEW(21, MetricsConstant.GATEWAY, \"overview\"),\n                             /**\n                              * 网关看板下的节点指标\n                              */\n                             GATEWAY_NODE(22, MetricsConstant.GATEWAY, \"node\"),\n                             /**\n                              * 网关看板下的索引指标\n                              */\n                             GATEWAY_INDEX(23, MetricsConstant.GATEWAY, \"index\"),\n                             /**\n                              * 网关看板下的项目指标\n                              */\n                             GATEWAY_APP(24, MetricsConstant.GATEWAY, \"app\"),\n                             /**\n                              * 网关看板下的DSL指标\n                              */\n                             GATEWAY_DSL(25, MetricsConstant.GATEWAY, \"dsl\"),\n                             /**\n                              * 字段页展示中的DSL模板配置\n                              */\n                             USER_CONFIG_SHOW_DSL_TEMPLATE(31, MetricsConstant.USER_SHOW, \"dslTemplate\"),\n                             /**\n                              * 字段页展示中的索引查询配置\n                              */\n                             USER_CONFIG_SHOW_INDEX_SEARCH(32, MetricsConstant.USER_SHOW, \"indexSearch\"),\n                             /**\n                              * 网关看板下的clientNode指标\n                              */\n                             GATEWAY_CLIENT_NODE(33, MetricsConstant.GATEWAY, \"clientNode\"),\n\n                             /**\n                              * dashboard 集群指标配置\n                              */\n                             DASHBOARD_CLUSTER(41, MetricsConstant.DASHBOARD, \"cluster\"),\n\n                             /**\n                              * dashboard 节点指标配置\n                              */\n                             DASHBOARD_NODE(42, MetricsConstant.DASHBOARD, \"node\"),\n\n                             /**\n                              * dashboard 索引指标配置\n                              */\n                             DASHBOARD_INDEX(43, MetricsConstant.DASHBOARD, \"index\"),\n\n                            /**\n                             * 检索查询 查询模板指标配置\n                             */\n                            QUERY_TEMPLATE(44, \"searchQuery\", \"searchTemplate\");\n\n    UserConfigTypeEnum(int code, String firstUserConfigType, String secondUserConfigType) {\n        this.code = code;\n        this.firstUserConfigType = firstUserConfigType;\n        this.secondUserConfigType = secondUserConfigType;\n    }\n\n    private int    code;\n    private String firstUserConfigType;\n    private String secondUserConfigType;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getFirstUserConfigType() {\n        return firstUserConfigType;\n    }\n\n    public String getSecondUserConfigType() {\n        return secondUserConfigType;\n    }\n\n    public static UserConfigTypeEnum valueOfCode(Integer code) {\n        if (null == code) {\n            return UserConfigTypeEnum.UNKNOWN;\n        }\n        for (UserConfigTypeEnum typeEnum : UserConfigTypeEnum.values()) {\n            if (code.equals(typeEnum.getCode())) {\n                return typeEnum;\n            }\n        }\n        return UserConfigTypeEnum.UNKNOWN;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/operaterecord/ModuleEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.operaterecord;\n\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\n/**\n * 操作记录模块枚举\n *\n * @author shizeying\n * @date 2022/06/13\n */\npublic enum ModuleEnum {\n                           /**\n                            * 物理集群：\n                            */\n                           PHYSICAL_CLUSTER(\"物理集群\", 0),\n\n                           /**\n                            * 我的集群：\n                            */\n                           MY_CLUSTER(\"我的集群\", 1),\n\n                           /**\n                            * 应用：\n                            */\n                           APPLICATION(\"应用\", 2),\n\n                           /**\n                            * 租户\n                            */\n                           TENANT(\"租户\", 3),\n\nTEMPLATE_MANAGEMENT(\"模板管理\", 4),\n\n                           /**\n                            * 模板服务:DCDR设置\n                            */\n                           TEMPLATE_SERVICE(\"模板服务\", 5),\n\n                           /**\n                            * 索引管理:创建\n                            */\n                           INDEX_MANAGEMENT(\"索引管理\", 6),\n\n                           /**\n                            * 索引服务:\n                            */\n                           INDEX_SERVICE(\"索引服务\", 7),\n    /**\n     * 查询模板\n     */\n    QUERY_TEMPLATE(\"查询模板\", 8),\n\n    /**\n     * DSL查询\n     */\n    DSL_QUERY(\"DSL查询\",15),\n    /**\n     * 配置\n     */\n    SETTING(\"配置\", 9),\n    //SENSE_OP(\"sense操作\", 10),\n    SCHEDULE(\"定时任务\", 11),\n    ES_CLUSTER_PLUGINS(\"ES集群插件\", 12),\n    ES_CLUSTER_CONFIG(\"ES集群配置\", 13),\n    ROLE_MANAGER(\"角色管理\", 14);\n\n    /**\n     * 模块\n     */\n    private final String  module;\n    /**\n     * code\n     */\n    private final Integer code;\n\n    ModuleEnum(String module, Integer code) {\n        this.module = module;\n        this.code = code;\n    }\n\n    public String getModule() {\n        return module;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public static Map<String, Integer> toMap() {\n        return Arrays.stream(ModuleEnum.values())\n            .collect(Collectors.toMap(ModuleEnum::getModule, ModuleEnum::getCode));\n    }\n\n    public static ModuleEnum getModuleEnum(Integer code) {\n        return Arrays.stream(ModuleEnum.values()).filter(moduleEnum -> moduleEnum.getCode().equals(code)).findFirst()\n            .orElse(null);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/operaterecord/OperateTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.operaterecord;\n\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\n/**\n * 操作类型枚举\n *\n * @author shizeying\n * @date 2022/06/16\n */\npublic enum OperateTypeEnum {\n    /**\n     * 物理集群：集群接入\n     */\n    PHYSICAL_CLUSTER_JOIN(ModuleEnum.PHYSICAL_CLUSTER, \"集群接入\", 0),\n    /**\n     * 物理集群：新建\n     */\n    PHYSICAL_CLUSTER_NEW(ModuleEnum.PHYSICAL_CLUSTER, \"集群新建\", 1),\n    /**\n     * 物理集群: 下线\n     */\n    PHYSICAL_CLUSTER_OFFLINE(ModuleEnum.PHYSICAL_CLUSTER, \"集群下线\", 2),\n    /**\n     * 物理集群:扩容\n     */\n    PHYSICAL_CLUSTER_CAPACITY(ModuleEnum.PHYSICAL_CLUSTER, \"集群扩缩容\", 3),\n    \n    /**\n     * 物理集群：重启\n     */\n    PHYSICAL_CLUSTER_RESTART(ModuleEnum.PHYSICAL_CLUSTER, \"重启\", 5),\n    \n    /**\n     * 物理集群： 信息修改\n     */\n    PHYSICAL_CLUSTER_INFO_MODIFY(ModuleEnum.PHYSICAL_CLUSTER, \"物理集群信息修改\", 6),\n    //PHYSICAL_CLUSTER_START(NewModuleEnum.PHYSICAL_CLUSTER, \"启动\",57),\n    /**\n     * 物理集群:升级\n     */\n    PHYSICAL_CLUSTER_UPGRADE(ModuleEnum.PHYSICAL_CLUSTER, \"集群升级\", 7),\n    /**\n     * 物理集群:REGION变更\n     */\n    PHYSICAL_CLUSTER_REGION_CHANGE(ModuleEnum.PHYSICAL_CLUSTER, \"REGION变更\", 8),\n    /**\n     * 物理集群：GATEWAY变更\n     */\n    PHYSICAL_CLUSTER_GATEWAY_CHANGE(ModuleEnum.PHYSICAL_CLUSTER, \"GATEWAY变更\", 9),\n    /**\n     * 物理集群：配置文件变更 todo op-task/cluster-config-add\n     */\n    PHYSICAL_CLUSTER_CONF_FILE_CHANGE(ModuleEnum.PHYSICAL_CLUSTER, \"配置文件变更\", 10),\n    /**\n     * 物理集群动：动态配置变更\n     */\n    PHYSICAL_CLUSTER_DYNAMIC_CONF_CHANGE(ModuleEnum.PHYSICAL_CLUSTER, \"动态配置变更\", 11),\n    /**\n     * 我的集群：信息修改\n     */\n    MY_CLUSTER_INFO_MODIFY(ModuleEnum.MY_CLUSTER, \"我的集群信息修改\", 12),\n    /**\n     * 我的集群：申请集群\n     */\n    MY_CLUSTER_APPLY(ModuleEnum.MY_CLUSTER, \"申请集群\", 13),\n    /**\n     * 我的集群：集群扩容\n     */\n    MY_CLUSTER_CAPACITY(ModuleEnum.MY_CLUSTER, \"集群扩缩容\", 3),\n    \n    /**\n     * 我的集群：集群下线\n     */\n    MY_CLUSTER_OFFLINE(ModuleEnum.MY_CLUSTER, \"集群下线\", 2),\n    /**\n     * 应用：新建应用\n     */\n    APPLICATION_CREATE(ModuleEnum.APPLICATION, \"新建应用\", 17),\n    /**\n     * 应用：删除应用\n     */\n    APPLICATION_DELETE(ModuleEnum.APPLICATION, \"删除应用\", 18),\n    \n    /**\n     * 应用：访问模式\n     */\n    APPLICATION_ACCESS_MODE(ModuleEnum.APPLICATION, \"访问模式\", 19),\n\n    /**\n     * 应用：访问设置\n     */\n    APPLICATION_ACCESS_CHANGE(ModuleEnum.APPLICATION,\"访问设置变更\",69),\n\n    /**\n     * 应用：负责人变更\n     */\n    APPLICATION_OWNER_CHANGE(ModuleEnum.APPLICATION, \"负责人变更\", 20),\n    /**\n     * 应用程序：用户\n     */\n    APPLICATION_USER_CHANGE(ModuleEnum.APPLICATION, \"成员变更\", 45),\n    /**\n     * 租户：新增租户\n     */\n    TENANT_ADD(ModuleEnum.TENANT, \"新增租户\", 21),\n    /**\n     * 租户信息修改\n     */\n    TENANT_INFO_MODIFY(ModuleEnum.TENANT, \"租户信息修改\", 22),\n    /**\n     * 索引模板管理：模板创建 todo 新建模版\n     */\n    TEMPLATE_MANAGEMENT_CREATE(ModuleEnum.TEMPLATE_MANAGEMENT, \"模板创建\", 23),\n\n    /**\n     * 模板管理:模板下线\n     */\n    TEMPLATE_MANAGEMENT_OFFLINE(ModuleEnum.TEMPLATE_MANAGEMENT, \"模板下线\", 26),\n     TEMPLATE_MANAGEMENT_EDIT_MAPPING(ModuleEnum.TEMPLATE_MANAGEMENT, \"编辑MAPPING\", 60),\n    TEMPLATE_MANAGEMENT_EDIT_SETTING(ModuleEnum.TEMPLATE_MANAGEMENT, \"编辑SETTING\", 59),\n    /**\n     * 模板管理:读/写状态变更\n     */\n    TEMPLATE_MANAGEMENT_BLOCK_WRITE(ModuleEnum.TEMPLATE_MANAGEMENT, \"模板管理写状态变更\", 68),\n    TEMPLATE_MANAGEMENT_BLOCK_READ(ModuleEnum.TEMPLATE_MANAGEMENT, \"模板管理读状态变更\", 70),\n    /**\n     * 索引模板管理:索引模板信息修改\n     */\n    TEMPLATE_MANAGEMENT_INFO_MODIFY(ModuleEnum.TEMPLATE_MANAGEMENT, \"索引模板信息修改\", 27),\n    /**\n     * 索引模板管理:升级版本\n     */\n    TEMPLATE_SERVICE_UPGRADED_VERSION(ModuleEnum.TEMPLATE_SERVICE, \"升版本\", 28),\n    /**\n     * 模板服务:DCDR设置\n     */\n    TEMPLATE_SERVICE_DCDR_SETTING(ModuleEnum.TEMPLATE_SERVICE, \"DCDR设置\", 29),\n    /**\n     * 模板服务:索引清理\n     */\n    TEMPLATE_SERVICE_CLEAN(ModuleEnum.TEMPLATE_SERVICE, \"索引清理\", 30),\n    /**\n     * 模板服务:模板扩缩容\n     */\n    TEMPLATE_SERVICE_CAPACITY(ModuleEnum.TEMPLATE_SERVICE, \"模板扩缩容\", 31),\n   \n    \n    /**\n     * 模板服务\n     */\n    TEMPLATE_SERVICE(ModuleEnum.TEMPLATE_SERVICE, \"模板服务\", 33),\n    /**\n     * 索引管理:创建\n     */\n    INDEX_MANAGEMENT_CREATE(ModuleEnum.INDEX_MANAGEMENT, \"索引创建\", 34),\n    /**\n     * 索引管理:删除索引\n     */\n    INDEX_MANAGEMENT_DELETE(ModuleEnum.INDEX_MANAGEMENT, \"删除索引\", 35),\n    /**\n     * 索引管理:别名调整\n     */\n    INDEX_MANAGEMENT_ALIAS_MODIFY(ModuleEnum.INDEX_MANAGEMENT, \"别名调整\", 36),\n    INDEX_MANAGEMENT_LABEL_MODIFY(ModuleEnum.INDEX_MANAGEMENT, \"标签调整\", 56),\n        /**\n     * 索引模板管理:编辑MAPPING\n     */\n    INDEX_TEMPLATE_MANAGEMENT_EDIT_MAPPING(ModuleEnum.INDEX_MANAGEMENT, \"编辑MAPPING\", 24),\n    /**\n     * 索引模板管理:编辑SETTING\n     */\n    INDEX_TEMPLATE_MANAGEMENT_EDIT_SETTING(ModuleEnum.INDEX_MANAGEMENT, \"编辑SETTING\", 25),\n\n    /**\n     * 索引管理:操作索引\n     */\n    INDEX_SERVICE_OP_INDEX(ModuleEnum.INDEX_SERVICE, \"操作索引\", 38),\n    /**\n     * 索引服务:执行索引服务\n     */\n    INDEXING_SERVICE_RUN(ModuleEnum.INDEX_SERVICE, \"执行索引服务\", 39),\n        /**\n     * 索引管理:索引读写变更\n     */\n    INDEX_SERVICE_READ_WRITE_CHANGE(ModuleEnum.INDEX_SERVICE, \"索引读写变更\", 37),\n    /**\n     * 查询模板:DSL限流调整\n     */\n    QUERY_TEMPLATE_DSL_CURRENT_LIMIT_ADJUSTMENT(ModuleEnum.QUERY_TEMPLATE, \"DSL限流调整\", 40),\n    /**\n     * 查询模板:DSL查询模板禁用\n     */\n    QUERY_TEMPLATE_DISABLE(ModuleEnum.QUERY_TEMPLATE, \"DSL查询模板禁用\", 41),\n    /**\n     * 查询模板:查询模板状态变更\n     */\n    QUERY_TEMPLATE_STATUS_CHANGE(ModuleEnum.QUERY_TEMPLATE, \"查询模板状态变更\", 67),\n    /**\n     * DSL查询:查询记录\n     */\n    DSL_QUERY_RECORD(ModuleEnum.DSL_QUERY, \"DSL查询记录\", 66),\n    /**\n     * 配置修改\n     */\n    SETTING_MODIFY(ModuleEnum.SETTING, \"配置修改\", 42),\n    /**\n     * 配置添加\n     */\n    SETTING_ADD(ModuleEnum.SETTING, \"新增配置\", 43),\n    /**\n     * 配置删除\n     */\n    SETTING_DELETE(ModuleEnum.SETTING, \"删除配置\", 44),\n    \n    ES_CLUSTER_PLUGINS_ADD(ModuleEnum.ES_CLUSTER_PLUGINS, \"新增插件\", 47),\n    ES_CLUSTER_PLUGINS_EDIT(ModuleEnum.ES_CLUSTER_PLUGINS, \"编辑插件\", 48),\n    ES_CLUSTER_PLUGINS_DELETE(ModuleEnum.ES_CLUSTER_PLUGINS, \"删除配置\", 49),\n    ES_CLUSTER_CONFIG_DELETE(ModuleEnum.ES_CLUSTER_CONFIG, \"删除集群配置\", 50),\n    \n    ES_CLUSTER_CONFIG_ADD(ModuleEnum.ES_CLUSTER_CONFIG, \"新增集群配置\", 51),\n    \n    ROLE_MANAGER_DELETE(ModuleEnum.ROLE_MANAGER, \"删除角色\", 58),\n    ROLE_MANAGER_CREATE(ModuleEnum.ROLE_MANAGER, \"创建角色\", 53),\n    ROLE_MANAGER_UNBIND_USER(ModuleEnum.ROLE_MANAGER, \"角色解绑用户\", 54),\n    ROLE_MANAGER_BIND_USER(ModuleEnum.ROLE_MANAGER, \"角色绑定用户\", 55),\n    PHYSICAL_CLUSTER_NODE_CHANGE(ModuleEnum.PHYSICAL_CLUSTER, \"节点变更\", 62),\n    /**\n     * 租户：删除租户\n     */\n    TENANT_DELETE(ModuleEnum.TENANT, \"删除租户\", 63);\n\n    /**\n     * 模块\n     */\n    private final ModuleEnum module;\n    /**\n     * 操作类型\n     */\n    private final String     operationType;\n    private final Integer    code;\n\n    OperateTypeEnum(ModuleEnum module, String operationType, Integer code) {\n        this.module = module;\n        this.operationType = operationType;\n        this.code = code;\n    }\n\n    public ModuleEnum getModule() {\n        return module;\n    }\n\n    public String getOperationType() {\n        return operationType;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public static Map<Integer, String> getOperationTypeByModule(Integer module) {\n        final ModuleEnum moduleEnum = ModuleEnum.getModuleEnum(module);\n        if (Objects.isNull(moduleEnum)) {\n            return Arrays.stream(OperateTypeEnum.values())\n                .map(operateTypeEnum -> Tuples.of(operateTypeEnum.getOperationType(), operateTypeEnum.getCode()))\n                .distinct().collect(Collectors.toMap(TupleTwo::v2, TupleTwo::v1));\n        }\n        return Arrays.stream(OperateTypeEnum.values())\n            .filter(operationTypeEnum -> operationTypeEnum.getModule().equals(moduleEnum))\n            .map(operateTypeEnum -> Tuples.of(operateTypeEnum.getOperationType(), operateTypeEnum.getCode())).distinct()\n            .collect(Collectors.toMap(TupleTwo::v2, TupleTwo::v1));\n    }\n\n    public static OperateTypeEnum getOperationTypeEnum(Integer code) {\n        return Arrays.stream(OperateTypeEnum.values())\n            .filter(operationTypeEnum -> operationTypeEnum.getCode().equals(code)).findFirst().orElse(null);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/operaterecord/OperationEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.operaterecord;\n\n/**\n * 操作枚举\n * <p>\n *\n * @author d06679\n * @date 2017/7/14\n */\npublic enum OperationEnum {\n                           /**\n                            * 新增\n                            */\n                           ADD(1, \"新增\"),\n\n                           DELETE(2, \"删除\"),\n\n                           EDIT(3, \"修改\"),\n\n                           ENABLE(4, \"启用\"),\n\n                           DISABLE(5, \"禁用\"),\n\n                           EXE(6, \"执行\"),\n\n                           EDIT_LABELS(7, \"修改标签\"),\n\n                           PRE_CREATE_INDEX(8, \"预创建索引\"),\n\n                           WO_SUBMIT(9, \"提交\"),\n\n                           WO_ARIUS_REVIEW(10, \"Arius审核\"),\n\n                           WO_DATA_OWNER_REVIEW(11, \"第三方审核\"),\n\n                           WO_ARIUS_REJECT(12, \"Arius驳回\"),\n\n                           WO_DATA_OWNER_REJECT(13, \"第三方驳回\"),\n\n                           WO_CANCEL(14, \"撤销\"),\n\n                           WO_EXECUTE(15, \"执行\"),\n\n                           WO_EDIT(16, \"提交\"),\n\n                           SWITCH(17, \"使能\"),\n\n                           UPGRADE(18, \"升版本\"),\n\n                           COPY(19, \"复制\"),\n\n                           SWITCH_MASTER_SLAVE(20, \"主从切换\"),\n\n                           CREATE_DCDR(21, \"创建dcdr链路\"),\n\n                           DELETE_DCDR(22, \"删除dcdr链路\"),\n\n                           SENSE_GET(30, \"sense查询\"),\n\n                           SENSE_DEL(31, \"sense删除\"),\n\n                           SENSE_PUT(32, \"sense更新\"),\n\n                           SENSE_OTHER(39, \"sense其他\"),\n\n                           DELETE_INDEX(40, \"删除索引\"),\n\n                           CAPACITY_PAN_INIT_REGION(41, \"region初始化\"),\n\n                           BATCH_CHANGE_TEMPLATE_HOT_DAYS(42, \"批量修改模板hotDay\"),\n\n                           EDIT_TEMPLATE_MAPPING(43, \"修改模板mapping\"),\n\n                           EDIT_TEMPLATE_ALIASES(44, \"修改模板aliases\"),\n\n                           CONFIG_ROLL_BACK(45, \"回滚\"),\n\n                           REGION_BIND(46, \"region绑定\"),\n\n                           REGION_UNBIND(47, \"region解绑\"),\n\n                           CLUSTER_CONFIG(48, \"修复/新增配置\"),\n\n                           CHECK(49, \"校验\"), BLOCK_READ(50, \"禁读\"),\n\n                           BLOCK_WRITE(51, \"禁写\"),\n\n                           CLOSE_INDEX(52, \"关闭索引\"),\n\n                           OPEN_INDEX(53, \"开启索引\"),\n    ADD_BIND_MULTIPLE_PROJECT(54, \"绑定逻辑集群\"),\n\n\n                           UNKNOWN(-1, \"unknown\");\n\n    OperationEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static OperationEnum valueOf(Integer code) {\n        if (code == null) {\n            return OperationEnum.UNKNOWN;\n        }\n        for (OperationEnum state : OperationEnum.values()) {\n            if (state.getCode() == code) {\n                return state;\n            }\n        }\n\n        return OperationEnum.UNKNOWN;\n    }\n\n    public static boolean validate(Integer code) {\n        if (code == null) {\n            return false;\n        }\n        for (OperationEnum state : OperationEnum.values()) {\n            if (state.getCode() == code) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/operaterecord/TemplateOperateRecordEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.operaterecord;\n\npublic enum TemplateOperateRecordEnum {\n\n                                       /**\n                                        * 模板操作类型\n                                        */\n                                       NEW(\"new\",\n                                           0), ROLLOVER(\"rollover\",\n                                                        1), MAPPING(\"mapping\",\n                                                                    2), SETTING(\"setting\",\n                                                                                3), WRITE(\"write\",\n                                                                                          4), READ(\"read\",\n                                                                                                   5), CONFIG(\"config\",\n                                                                                                              6), TRANSFER(\"transfer\",\n                                                                                                                           7), UPGRADE(\"upgrade\",\n                                                                                                                                       8);\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public int getCode() {\n        return code;\n    }\n\n    TemplateOperateRecordEnum(String desc, int code) {\n        this.desc = desc;\n        this.code = code;\n    }\n\n    private int    code;\n\n    private String desc;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/operaterecord/TriggerWayEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.operaterecord;\n\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\n/**\n * 触发方式枚举\n *\n * @author shizeying\n * @date 2022/06/14\n */\npublic enum TriggerWayEnum {\n                            /**\n                             * 手动触发\n                             */\n                            MANUAL_TRIGGER(\"手动触发\", 0),\n                            /**\n                             * 系统触发\n                             */\n                            SYSTEM_TRIGGER(\"系统触发\", 1),\n                            /**\n                             * 调度任务scheduling_tasks\n                             */\n                            SCHEDULING_TASKS(\"调度任务\", 2);\n\n    /**\n     * 触发方式\n     */\n    private final String  triggerWay;\n    private final Integer code;\n\n    TriggerWayEnum(String triggerWay, int code) {\n        this.triggerWay = triggerWay;\n        this.code = code;\n    }\n\n    public String getTriggerWay() {\n        return triggerWay;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public static Map<String, Integer> getOperationList() {\n        return Arrays.stream(TriggerWayEnum.values())\n            .collect(Collectors.toMap(TriggerWayEnum::getTriggerWay, TriggerWayEnum::getCode));\n\n    }\n\n    public static TriggerWayEnum getTriggerWayEnum(Integer code) {\n        return Arrays.stream(TriggerWayEnum.values()).filter(triggerWayEnum -> triggerWayEnum.getCode().equals(code))\n            .findFirst().orElse(null);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/project/ProjectClusterLogicAuthEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.project;\n\nimport java.util.Arrays;\nimport java.util.Objects;\n\npublic enum ProjectClusterLogicAuthEnum {\n                                         /**\n                                          * 超级权限\n                                          */\n                                         ALL(0, \"manager\", \"超管\"),\n\n                                         /**\n                                          * Owner权限\n                                          */\n                                         OWN(1, \"own\", \"配置管理\"),\n\n                                         /**\n                                          * 访问权限\n                                          */\n                                         ACCESS(2, \"r\", \"访问\"),\n\n                                         /**\n                                          * 没有权限\n                                          */\n                                         NO_PERMISSIONS(-1, \"\", \"无权限\");\n\n    private final Integer code;\n    private final String  name;\n    private final String  desc;\n\n    ProjectClusterLogicAuthEnum(int code, String name, String desc) {\n        this.code = code;\n        this.name = name;\n        this.desc = desc;\n    }\n\n    public static ProjectClusterLogicAuthEnum valueOf(Integer code) {\n        if (code != null) {\n            for (ProjectClusterLogicAuthEnum state : ProjectClusterLogicAuthEnum.values()) {\n                if (state.getCode().equals(code)) {\n                    return state;\n                }\n            }\n        }\n\n        return ProjectClusterLogicAuthEnum.NO_PERMISSIONS;\n    }\n\n    public static ProjectClusterLogicAuthEnum highestAuth(ProjectClusterLogicAuthEnum... authEnums) {\n        if (authEnums == null) {\n            return NO_PERMISSIONS;\n        }\n\n        // ordinal越小权限越大\n        return Arrays.stream(authEnums).filter(Objects::nonNull).min(ProjectClusterLogicAuthEnum::compareTo)\n            .orElse(NO_PERMISSIONS);\n\n    }\n\n    public boolean higherOrEqual(ProjectClusterLogicAuthEnum anotherEnums) {\n        if (anotherEnums == null) {\n            return true;\n        }\n\n        return this.ordinal() <= anotherEnums.ordinal();\n    }\n\n    public boolean higher(ProjectClusterLogicAuthEnum anotherEnums) {\n        if (anotherEnums == null) {\n            return true;\n        }\n\n        return this.ordinal() < anotherEnums.ordinal();\n    }\n\n    public static boolean isExitByCode(Integer code) {\n        if (code == null) {\n            return false;\n        }\n\n        for (ProjectClusterLogicAuthEnum state : ProjectClusterLogicAuthEnum.values()) {\n            if (state.getCode().equals(code)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/project/ProjectSearchTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.project;\n\n/**\n * 用户状态枚举\n *\n *\n * @author d06679\n * @date 2017/7/14\n */\npublic enum ProjectSearchTypeEnum {\n    /**\n     * 集群模式\n     */\n    CLUSTER(0, \"集群模式\"),\n    /**\n     * 索引模式\n     */\n    TEMPLATE(1, \"索引模式\"),\n    \n    /**\n     * 原生模式\n     */\n    PRIMITIVE(2, \"原生模式\"),\n    \n    UNKNOWN(-1, \"未知\");\n\n    ProjectSearchTypeEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static ProjectSearchTypeEnum valueOf(Integer code) {\n        if (code == null) {\n            return ProjectSearchTypeEnum.UNKNOWN;\n        }\n        for (ProjectSearchTypeEnum state : ProjectSearchTypeEnum.values()) {\n            if (state.getCode() == code) {\n                return state;\n            }\n        }\n\n        return ProjectSearchTypeEnum.UNKNOWN;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/project/ProjectTemplateAuthEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.project;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * 操作枚举\n *\n * @author d06679\n * @date 2017/7/14\n */\npublic enum ProjectTemplateAuthEnum {\n\n                                     /**\n                                      * Owner权限\n                                      */\n                                     OWN(1, \"own\", \"管理\"),\n\n                                     /**\n                                      * 读写权限\n                                      */\n                                     RW(2, \"rw\", \"读写\"),\n\n                                     /**\n                                      * 读权限\n                                      */\n                                     R(3, \"r\", \"读\"),\n\n                                     /**\n                                      * 没有权限\n                                      */\n                                     NO_PERMISSION(-1, \"\", \"unknown\");\n\n    ProjectTemplateAuthEnum(int code, String name, String desc) {\n        this.code = code;\n        this.name = name;\n        this.desc = desc;\n    }\n\n    private final Integer code;\n    private final String  name;\n    private final String  desc;\n\n    public String getName() {\n        return name;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static ProjectTemplateAuthEnum valueOf(Integer code) {\n        if (code == null) {\n            return ProjectTemplateAuthEnum.NO_PERMISSION;\n        }\n        for (ProjectTemplateAuthEnum state : ProjectTemplateAuthEnum.values()) {\n            if (state.getCode().equals(code)) {\n                return state;\n            }\n        }\n\n        return ProjectTemplateAuthEnum.NO_PERMISSION;\n    }\n\n    public static ProjectTemplateAuthEnum valueOfName(String name) {\n        if (name == null) {\n            return ProjectTemplateAuthEnum.NO_PERMISSION;\n        }\n\n        name = name.toLowerCase();\n\n        if (\"w\".equals(name)) {\n            name = RW.getName();\n        }\n\n        for (ProjectTemplateAuthEnum state : ProjectTemplateAuthEnum.values()) {\n            if (state.getName().equals(name)) {\n                return state;\n            }\n        }\n\n        return ProjectTemplateAuthEnum.NO_PERMISSION;\n    }\n\n    public static boolean isTemplateAuthExitByCode(Integer code) {\n        if (code == null) {\n            return false;\n        }\n        for (ProjectTemplateAuthEnum state : ProjectTemplateAuthEnum.values()) {\n            if (state.getCode().equals(code)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public static List<Integer> listAppTemplateAuthCodes() {\n        return Arrays.stream(ProjectTemplateAuthEnum.values()).map(ProjectTemplateAuthEnum::getCode).distinct()\n            .collect(Collectors.toList());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/resource/ESClusterCreateSourceEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.resource;\n\n/**\n * 集群创建来源枚举 接入 or 新建集群\n * @author chengxiang\n */\npublic enum ESClusterCreateSourceEnum {\n                                       /**\n                                        *\n                                        */\n                                       ES_IMPORT(0, \"接入集群\"),\n\n                                       /**\n                                        * vmware集群\n                                        */\n                                       ES_NEW(1, \"新建集群\"),\n\n                                       /**\n                                        * 未知\n                                        */\n                                       UNKNOWN(-1, \"unknown\");\n\n    ESClusterCreateSourceEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static ESClusterCreateSourceEnum valueOf(Integer code) {\n        if (code == null) {\n            return ESClusterCreateSourceEnum.UNKNOWN;\n        }\n\n        for (ESClusterCreateSourceEnum typeEnum : ESClusterCreateSourceEnum.values()) {\n            if (typeEnum.getCode() == code) {\n                return typeEnum;\n            }\n        }\n        return ESClusterCreateSourceEnum.UNKNOWN;\n    }\n\n    public static boolean validCode(Integer code) {\n        if (code == null) {\n            return false;\n        }\n        for (ESClusterCreateSourceEnum typeEnum : ESClusterCreateSourceEnum.values()) {\n            if (typeEnum.getCode() == code) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/resource/ESClusterImportRuleEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.resource;\n\n/**\n * 节点接入规则枚举\n * @author chengxiang\n */\npublic enum ESClusterImportRuleEnum {\n                                     AUTO_IMPORT(0, \"自动接入\"),\n\n                                     FULL_IMPORT(1, \"全量接入\"),\n\n                                     UNKNOWN(-1, \"unknown\");\n\n    ESClusterImportRuleEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static ESClusterImportRuleEnum valueOf(Integer code) {\n        if (code == null) {\n            return ESClusterImportRuleEnum.UNKNOWN;\n        }\n        for (ESClusterImportRuleEnum importRuleEnum : ESClusterImportRuleEnum.values()) {\n            if (importRuleEnum.getCode() == code) {\n                return importRuleEnum;\n            }\n        }\n        return ESClusterImportRuleEnum.UNKNOWN;\n    }\n\n    public static boolean validCode(Integer code) {\n        if (code == null) {\n            return false;\n        }\n        for (ESClusterImportRuleEnum importRuleEnum : ESClusterImportRuleEnum.values()) {\n            if (importRuleEnum.getCode() == code) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/resource/ESClusterNodeRoleEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.resource;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * 节点角色类型枚举\n *\n * Created by d06679 on 2017/7/14.\n */\npublic enum ESClusterNodeRoleEnum {\n                                   /**datanode*/\n                                   DATA_NODE(1, \"datanode\"),\n\n                                   CLIENT_NODE(2, \"clientnode\"),\n\n                                   MASTER_NODE(3, \"masternode\"),\n\n                                   UNKNOWN(-1, \"unknown\");\n\n    ESClusterNodeRoleEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static ESClusterNodeRoleEnum valueOf(Integer code) {\n        if (code == null) {\n            return ESClusterNodeRoleEnum.UNKNOWN;\n        }\n        for (ESClusterNodeRoleEnum typeEnum : ESClusterNodeRoleEnum.values()) {\n            if (typeEnum.getCode() == code) {\n                return typeEnum;\n            }\n        }\n\n        return ESClusterNodeRoleEnum.UNKNOWN;\n    }\n\n    public static ESClusterNodeRoleEnum getByDesc(String desc) {\n        if (desc == null) {\n            return ESClusterNodeRoleEnum.UNKNOWN;\n        }\n        for (ESClusterNodeRoleEnum typeEnum : ESClusterNodeRoleEnum.values()) {\n            if (typeEnum.getDesc().equals(desc)) {\n                return typeEnum;\n            }\n        }\n\n        return ESClusterNodeRoleEnum.UNKNOWN;\n    }\n\n    /**\n     * 获取去除node部分的role列表，例如data,master等\n     */\n    public static List<String> nodeRoleList() {\n        return Arrays.stream(values()).filter(param -> param != UNKNOWN).map(ESClusterNodeRoleEnum::getDesc)\n            .map(roleNode -> roleNode.substring(0, roleNode.lastIndexOf(\"n\"))).collect(Collectors.toList());\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/resource/ESClusterNodeStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.resource;\n\n/**\n * 节点角色类型枚举\n *\n * Created by d06679 on 2017/7/14.\n */\npublic enum ESClusterNodeStatusEnum {\n                                     /**在线*/\n                                     ONLINE(1, \"在线\"),\n\n                                     OFFLINE(2, \"离线\"),\n\n                                     FAULT(3, \"故障\"),\n\n                                     UNKNOWN(-1, \"unknown\");\n\n    ESClusterNodeStatusEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static ESClusterNodeStatusEnum valueOf(Integer code) {\n        if (code == null) {\n            return ESClusterNodeStatusEnum.UNKNOWN;\n        }\n        for (ESClusterNodeStatusEnum typeEnum : ESClusterNodeStatusEnum.values()) {\n            if (typeEnum.getCode() == code) {\n                return typeEnum;\n            }\n        }\n\n        return ESClusterNodeStatusEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/resource/ESClusterTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.resource;\n\n/**\n * 集群类型枚举\n * @author  d06679\n * @date 2017/7/14.\n */\npublic enum ESClusterTypeEnum {\n                               /**\n                                * 弹性云集群\n                                */\n                               ES_DOCKER(3, \"docker集群\"),\n\n                               /**\n                                * 物理机集群\n                                */\n                               ES_HOST(4, \"host集群\"),\n\n                               /**\n                               * 虚拟机集群\n                               */\n                               ES_VM(5, \"virtual machine集群\"),\n\n                               /**\n                                * 未知\n                                */\n                               UNKNOWN(-1, \"unknown\");\n\n    ESClusterTypeEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static ESClusterTypeEnum valueOf(Integer code) {\n        if (code == null) {\n            return ESClusterTypeEnum.UNKNOWN;\n        }\n\n        for (ESClusterTypeEnum typeEnum : ESClusterTypeEnum.values()) {\n            if (typeEnum.getCode() == code) {\n                return typeEnum;\n            }\n        }\n        return ESClusterTypeEnum.UNKNOWN;\n    }\n\n    public static boolean validCode(Integer code) {\n        if (code == null) {\n            return false;\n        }\n        for (ESClusterTypeEnum typeEnum : ESClusterTypeEnum.values()) {\n            if (typeEnum.getCode() == code) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/resource/ResourceLogicLevelEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.resource;\n\n/**\n * 集群业务分组\n * Created by d06679 on 2017/7/14.\n */\npublic enum ResourceLogicLevelEnum {\n                                    /**normal*/\n                                    NORMAL(1, \"normal\"),\n\n                                    IMPORTANT(2, \"important\"),\n\n                                    VIP(3, \"vip\");\n\n    ResourceLogicLevelEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static ResourceLogicLevelEnum valueOf(Integer code) {\n        if (code == null) {\n            return ResourceLogicLevelEnum.NORMAL;\n        }\n        for (ResourceLogicLevelEnum state : ResourceLogicLevelEnum.values()) {\n            if (state.getCode() == code) {\n                return state;\n            }\n        }\n\n        return ResourceLogicLevelEnum.NORMAL;\n    }\n\n    public static ResourceLogicLevelEnum valueFromDesc(String desc) {\n        if (desc == null) {\n            return ResourceLogicLevelEnum.NORMAL;\n        }\n        for (ResourceLogicLevelEnum state : ResourceLogicLevelEnum.values()) {\n            if (state.getDesc().equals(desc)) {\n                return state;\n            }\n        }\n\n        return ResourceLogicLevelEnum.NORMAL;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/result/ResultType.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.result;\n\n/**\n * rest请求返回类型\n *\n * @author d06679\n */\npublic enum ResultType {\n                        /**操作成功*/\n                        SUCCESS(0, \"操作成功\"),\n\n                        FAIL(19999, \"操作失败\"),\n\n                        ILLEGAL_PARAMS(10000, \"参数错误\"),\n\n                        RESOURCE_NOT_READY(10001, \"资源未就绪\"),\n\n                        RESOURCE_PROCESSING(10002, \"资源审批中\"),\n\n                        ES_OPERATE_ERROR(10003, \"es操作失败\"),\n\n                        DUPLICATION(10004, \"数据已存在\"),\n\n                        NOT_EXIST(10005, \"数据不存在\"),\n\n                        APP_VERIFY_SUCCESS(10006, \"APP校验通过\"),\n\n                        APP_VERIFY_FAIL_APP_NOT_EXIST(10007, \"APP校验失败:PROJECTID不存在\"),\n\n                        APP_VERIFY_FAIL_VERIFY_ERROR(10008, \"APP校验失败:appsecret不正确\"),\n\n                        HTTP_REQ_ERROR(10009, \"第三方http请求异常\"),\n\n                        OPERATE_FORBIDDEN_ERROR(10010, \"无权限\"),\n\n                        ADMIN_OPERATE_ERROR(10011, \"Admin操作失败\"),\n\n                        IN_USE_ERROR(10012, \"使用中\"),\n\n                        WORK_ORDER_NOT_SUPPORT_ERROR(10013, \"工单类型不支持\"),\n\n                        AMS_SERVER_ERROR(10015, \"ams服务异常\"),\n\n                        ODIN_SERVER_ERROR(10016, \"odin服务异常\"),\n\n                        ECM_SERVER_ERROR(10017, \"ecm服务异常\"),\n\n                        ADMIN_META_ERROR(10018, \"admin元数据异常\"),\n\n                        RESOURCE_NOT_ENOUGH(10019, \"集群资源不足\"),\n\n                        EXTEND_SERVICE_ERROR(10020, \"扩展服务异常\"),\n\n                        NO_CAPACITY_PLAN(10021, \"集群没有容量规划\"),\n\n                        ADMIN_TASK_ERROR(10022, \"admin任务异常\"),\n\n                        ORDER_ALREADY_HANDLED(10023, \"工单已审批\"),\n\n                        STORAGE_DOWNLOAD_FILE_FAILED(10024, \"download file failed\"),\n\n                        NO_FIND_SUB_CLASS(10025, \"找不到实现类\"),\n\n                        CLUSTER_LOGIC_TYPE_ERROR(10026, \"逻辑集群类型不存在\"),\n\n                        N9E_SERVER_ERROR(10027, \"夜莺服务异常\"),\n\n                        ARIUS_GATEWAY_ERROR(10028, \"arius gateway 异常\"),\n\n                        FILE_UPLOAD_ERROR(10029, \"upload file failed\"),\n\n                        NOT_SUPPORT_ERROR(10030, \"接口不再支持\"),\n    ES_CLIENT_NUL_ERROR(10031, \"es client [%s] 集群异常\"),\n\n    EVENT_ERROR(10032,\"事件处理异常\"),\n\n    ;\n\n    private Integer code;\n    private String  message;\n\n    ResultType(int code, String message) {\n        this.code = code;\n        this.message = message;\n    }\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/routing/ESRoutingConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.routing;\n\n/**\n * Created by linyunan on 3/15/22\n */\n\npublic class ESRoutingConstant {\n    public static final String CLUSTER_PHY_HEALTH_ROUTING = \"allClusterPhyHealth\";\n\n    public static final String CLUSTER_PHY_ROUTING        = \"allCluster\";\n\n    public static final String THREAD_POOL_ROUTING        = \"threadPoolQueue\";\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/task/OpTaskDCDRProgressEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.task;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic enum OpTaskDCDRProgressEnum {\n                                    /**创建DCDR链路*/\n                                    STEP_0(0, \"创建DCDR链路\"),\n\n                                    STEP_1(1, \"停止主索引写入\"),\n\n                                    STEP_2(2, \"确保主从索引数据同步\"),\n\n                                    STEP_3(3, \"删除源dcdr模板和索引链路\"),\n\n                                    STEP_4(4, \"拷贝主模板的mapping信息到从模板\"),\n\n                                    STEP_5(5, \"关闭从索引dcdr索引开关并打开主索引dcdr索引开关\"),\n\n                                    STEP_6(6, \"停止从索引写入\"),\n\n                                    STEP_7(7, \"创建新的dcdr链路\"),\n\n                                    STEP_8(8, \"恢复主从索引实时写入\"),\n\n                                    STEP_9(9, \"主从模板角色切换\"),\n\n                                    UNKNOWN(-1, \"unknown\");\n\n    OpTaskDCDRProgressEnum(Integer progress, String value) {\n        this.progress = progress;\n        this.value = value;\n    }\n\n    private Integer progress;\n\n    private String  value;\n\n    public Integer getProgress() {\n        return progress;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public static List<OpTaskDCDRProgressEnum> listAll() {\n        return new ArrayList<>(Arrays.asList(OpTaskDCDRProgressEnum.values()));\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/task/OpTaskHandleEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.task;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-24\n */\npublic enum OpTaskHandleEnum {\n                              /**新增*/\n                              CLUSTER_NEW(OpTaskTypeEnum.CLUSTER_NEW.getType(), OpTaskConstant.CLUSTER_CREATE_TASK),\n\n                              CLUSTER_EXPAND(OpTaskTypeEnum.CLUSTER_EXPAND.getType(),\n                                             OpTaskConstant.CLUSTER_SCALE_TASK),\n\n                              CLUSTER_SHRINK(OpTaskTypeEnum.CLUSTER_SHRINK.getType(),\n                                             OpTaskConstant.CLUSTER_SCALE_TASK),\n\n                              CLUSTER_RESTART(OpTaskTypeEnum.CLUSTER_RESTART.getType(),\n                                              OpTaskConstant.CLUSTER_RESTART_TASK),\n\n                              CLUSTER_UPGRADE(OpTaskTypeEnum.CLUSTER_UPGRADE.getType(),\n                                              OpTaskConstant.CLUSTER_UPGRADE_TASK),\n\n                              CLUSTER_PLUG_OPERATION(OpTaskTypeEnum.CLUSTER_PLUG_OPERATION.getType(),\n                                                     OpTaskConstant.ECM_WORK_TASK),\n\n                              CLUSTER_OFFLINE(OpTaskTypeEnum.CLUSTER_OFFLINE.getType(),\n                                              OpTaskConstant.CLUSTER_OFFLINE_TASK),\n\n                              TEMPLATE_DCDR(OpTaskTypeEnum.TEMPLATE_DCDR.getType(), OpTaskConstant.DCDR_WORK_TASK),\n\n                              CLUSTER_CONFIG_ADD(OpTaskTypeEnum.CLUSTER_CONFIG_ADD.getType(),\n                                                 OpTaskConstant.CLUSTER_CONFIG_RESTART_TASK),\n\n                              CLUSTER_CONFIG_EDIT(OpTaskTypeEnum.CLUSTER_CONFIG_EDIT.getType(),\n                                                  OpTaskConstant.ECM_WORK_TASK),\n\n                              CLUSTER_CONFIG_DELETE(OpTaskTypeEnum.CLUSTER_CONFIG_DELETE.getType(),\n                                                    OpTaskConstant.ECM_WORK_TASK),\n\n                              UNKNOWN(OpTaskTypeEnum.UNKNOWN.getType(), OpTaskConstant.UNKNOWN);\n\n    OpTaskHandleEnum(Integer type, String message) {\n        this.type = type;\n        this.message = message;\n    }\n\n    private Integer type;\n\n    private String  message;\n\n    public Integer getType() {\n        return type;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public static OpTaskHandleEnum valueOfType(Integer type) {\n        if (type == null) {\n            return OpTaskHandleEnum.UNKNOWN;\n        }\n        for (OpTaskHandleEnum typeEnum : OpTaskHandleEnum.values()) {\n            if (type.equals(typeEnum.getType())) {\n                return typeEnum;\n            }\n        }\n\n        return OpTaskHandleEnum.UNKNOWN;\n    }\n\n}\n\nclass OpTaskConstant {\n\n    private OpTaskConstant() {\n    }\n\n    public static final String ECM_WORK_TASK               = \"ecmOpTask\";\n\n    public static final String CLUSTER_CREATE_TASK         = \"clusterCreateTask\";\n\n    public static final String CLUSTER_SCALE_TASK          = \"clusterScaleTask\";\n\n    public static final String CLUSTER_RESTART_TASK        = \"clusterRestartTask\";\n\n    public static final String CLUSTER_UPGRADE_TASK        = \"clusterUpgradeTask\";\n\n    public static final String CLUSTER_OFFLINE_TASK        = \"clusterOfflineTask\";\n    public static final String CLUSTER_CONFIG_RESTART_TASK = \"clusterConfigRestartTask\";\n\n    public static final String DCDR_WORK_TASK              = \"dcdrOpTask\";\n    public static final String UNKNOWN                     = \"unknown\";\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/task/OpTaskStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.task;\n\npublic enum OpTaskStatusEnum {\n                              /**执行成功*/\n                              SUCCESS(\"success\", \"执行成功\"),\n\n                              FAILED(\"failed\", \"执行失败\"),\n\n                              RUNNING(\"running\", \"执行中\"),\n\n                              WAITING(\"waiting\", \"等待\"),\n\n                              PAUSE(\"pause\", \"暂停\"),\n\n                              CANCEL(\"cancel\", \"取消\"),\n\n                              UNKNOWN(\"unknown\", \"unknown\");\n\n    OpTaskStatusEnum(String status, String value) {\n        this.status = status;\n        this.value = value;\n    }\n\n    private String status;\n\n    private String value;\n\n    public String getStatus() {\n        return status;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public static OpTaskStatusEnum valueOfStatus(String status) {\n        if (status == null) {\n            return OpTaskStatusEnum.UNKNOWN;\n        }\n        for (OpTaskStatusEnum statusEnum : OpTaskStatusEnum.values()) {\n            if (status.equals(statusEnum.getStatus())) {\n                return statusEnum;\n            }\n        }\n\n        return OpTaskStatusEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/task/OpTaskTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.task;\n\nimport java.util.Arrays;\n\n/**\n * 任务枚举类型\n *\n * @author ohushenglin_v\n * @date 2022-05-20\n */\npublic enum OpTaskTypeEnum {\n                            /**新增*/\n                            CLUSTER_NEW(1, \"集群新建\", \"cluster-create\"),\n\n                            CLUSTER_EXPAND(2, \"集群扩容\", \"cluster-expand\"),\n\n                            CLUSTER_SHRINK(3, \"集群缩容\", \"cluster-shrink\"),\n\n                            CLUSTER_RESTART(4, \"集群重启\", \"cluster-restart\"),\n\n                            CLUSTER_UPGRADE(5, \"集群升级\", \"cluster-upgrade\"),\n\n                            CLUSTER_PLUG_OPERATION(6, \"集群插件操作\", \"cluster-plug-operation\"),\n\n                            CLUSTER_OFFLINE(7, \"集群下线操作\", \"cluster-offline\"),\n\n                            TEMPLATE_DCDR(10, \"索引模板主从切换\", \"template-dcdr\"),\n\n                            CLUSTER_CONFIG_ADD(11, \"集群配置新增\", \"cluster-config-add\"),\n\n                            CLUSTER_CONFIG_EDIT(12, \"集群配置编辑\", \"cluster-config-edit\"),\n\n                            CLUSTER_CONFIG_DELETE(13, \"集群配置删除\", \"cluster-config-delete\"),\n\n                            UNKNOWN(-1, \"unknown\");\n\n    OpTaskTypeEnum(Integer type, String message) {\n        this.type = type;\n        this.message = message;\n    }\n\n    OpTaskTypeEnum(Integer type, String message, String apiPath) {\n        this.type = type;\n        this.message = message;\n        this.apiPath = apiPath;\n    }\n\n    private Integer type;\n\n    private String  message;\n    private String  apiPath;\n\n    public Integer getType() {\n        return type;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public String getApiPath() {\n        return apiPath;\n    }\n\n    public static OpTaskTypeEnum valueOfType(Integer type) {\n        if (type == null) {\n            return OpTaskTypeEnum.UNKNOWN;\n        }\n        for (OpTaskTypeEnum typeEnum : OpTaskTypeEnum.values()) {\n            if (type.equals(typeEnum.getType())) {\n                return typeEnum;\n            }\n        }\n\n        return OpTaskTypeEnum.UNKNOWN;\n    }\n\n    public static OpTaskTypeEnum valueOfPath(String apiPath) {\n        if (apiPath == null || \"\".equals(apiPath.trim())) {\n            return OpTaskTypeEnum.UNKNOWN;\n        }\n\n        return Arrays.stream(OpTaskTypeEnum.values()).filter(typeEnum -> apiPath.equals(typeEnum.getApiPath()))\n            .findAny().orElse(OpTaskTypeEnum.UNKNOWN);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/DataTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\npublic enum DataTypeEnum {\n                          /**\n                           * 日志数据\n                           */\n                          SYSTEM(0, \"系统数据\", \"system\"),\n\n                          LOG(1, \"日志数据\", \"log\"),\n\n                          OLAP(2, \"用户上报数据\", \"olap\"),\n\n                          BINLOG(3, \"RDS数据\", \"binlog\"),\n\n                          OFFLINE(4, \"离线导入数据\", \"offline\"),\n\n                          UNKNOWN(-1, \"未知\", \"\");\n\n    DataTypeEnum(int code, String desc, String label) {\n        this.code = code;\n        this.desc = desc;\n        this.label = label;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    private String label;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public String getLabel() {\n        return label;\n    }\n\n    public static DataTypeEnum valueOf(Integer code) {\n        if (code == null) {\n            return DataTypeEnum.UNKNOWN;\n        }\n        for (DataTypeEnum state : DataTypeEnum.values()) {\n            if (state.getCode() == code) {\n                return state;\n            }\n        }\n\n        return DataTypeEnum.UNKNOWN;\n    }\n\n    public static boolean isExit(Integer code) {\n        if (code == null) {\n            return false;\n        }\n        for (DataTypeEnum state : DataTypeEnum.values()) {\n            if (state.getCode() == code) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public static final Map<Integer, String> code2DescMap() {\n        return Arrays.stream(DataTypeEnum.values()).filter(dataTypeEnum -> !UNKNOWN.equals(dataTypeEnum))\n            .collect(Collectors.toMap(DataTypeEnum::getCode, DataTypeEnum::getDesc));\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/SupportSrv.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * 支持srv\n *\n * @author shizeying\n * @date 2022/07/20\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic   class SupportSrv {\n    private boolean dcdrModuleExists     = false;\n    private boolean coldRegionExists     = false;\n    private boolean pipelineModuleExists = false;\n    private boolean enableWriteRateLimit = false;\n    private boolean isPartition          = false;\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplateDCDRStepEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\npublic enum TemplateDCDRStepEnum {\n                                  /**第一步：停止主索引写入*/\n                                  STEP_1(1, \"停止主索引写入%s\"),\n\n                                  STEP_2(2, \"确保主从索引数据同步%s\"),\n\n                                  STEP_3(3, \"删除源dcdr模板和索引链路%s\"),\n\n                                  STEP_4(4, \"拷贝主模板的mapping信息到从模板%s\"),\n\n                                  STEP_5(5, \"关闭从索引dcdr索引开关并打开主索引dcdr索引开关%s\"),\n\n                                  STEP_6(6, \"停止从索引写入%s\"),\n\n                                  STEP_7(7, \"创建新的dcdr链路%s\"),\n\n                                  STEP_8(8, \"恢复主从索引实时写入%s\"),\n\n                                  STEP_9(9, \"主从模板角色切换%s\"),\n\n                                  UNKNOWN(-1, \"unknown\");\n\n    TemplateDCDRStepEnum(int step, String value) {\n        this.step = step;\n        this.value = value;\n    }\n\n    private int    step;\n\n    private String value;\n\n    public int getStep() {\n        return step;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public static TemplateDCDRStepEnum valueOfStep(int step) {\n\n        for (TemplateDCDRStepEnum stepEnum : TemplateDCDRStepEnum.values()) {\n            if (step == stepEnum.getStep()) {\n                return stepEnum;\n            }\n        }\n        return TemplateDCDRStepEnum.UNKNOWN;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplateDeployRoleEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\npublic enum TemplateDeployRoleEnum {\n                                    /**主*/\n                                    MASTER(1, \"主\"),\n\n                                    SLAVE(2, \"从\"),\n\n                                    UNKNOWN(-1, \"未知\");\n\n    TemplateDeployRoleEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private Integer code;\n\n    private String  desc;\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static TemplateDeployRoleEnum valueOf(Integer code) {\n        if (code == null) {\n            return TemplateDeployRoleEnum.UNKNOWN;\n        }\n        for (TemplateDeployRoleEnum state : TemplateDeployRoleEnum.values()) {\n            if (state.getCode().equals(code)) {\n                return state;\n            }\n        }\n\n        return TemplateDeployRoleEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplateDeployStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\npublic enum TemplateDeployStatusEnum {\n                                      /**主从都在线*/\n                                      MASTER_SLAVE_ONLINE(1, \"主从都在线\"),\n\n                                      MASTER_SLAVE_OFFLINE(2, \"主从都不在线\"),\n\n                                      ONLY_MASTER_ONLINE(3, \"只有主在线\"),\n\n                                      NO_MASTER_ONLINE(4, \"主不在线从在线\"),\n\n                                      UNKNOWN(-2, \"被删除\");\n\n    TemplateDeployStatusEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    private String label;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public String getLabel() {\n        return label;\n    }\n\n    public static TemplateDeployStatusEnum valueOf(Integer code) {\n        if (code == null) {\n            return TemplateDeployStatusEnum.UNKNOWN;\n        }\n        for (TemplateDeployStatusEnum state : TemplateDeployStatusEnum.values()) {\n            if (state.getCode() == code) {\n                return state;\n            }\n        }\n\n        return TemplateDeployStatusEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplateHealthEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\n\n/**\n * @author wangshu\n * @date 2020/09/22\n */\npublic enum TemplateHealthEnum {\n\n                               /**\n                                * green\n                                */\n                               GREEN(0, \"green\"),\n\n                               /**\n                                * yellow\n                                */\n                               YELLOW(1, \"yellow\"),\n\n                               /**\n                                * red\n                                */\n                               RED(2, \"red\"),\n\n                               /**\n                                * 未知\n                                */\n                               UNKNOWN(-1, \"unknown\");\n\n    TemplateHealthEnum(Integer code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    public static TemplateHealthEnum valueOf(Integer code) {\n        if (YELLOW.getCode().equals(code)) {\n            return YELLOW;\n        } else if (RED.getCode().equals(code)) {\n            return RED;\n        } else if (GREEN.getCode().equals(code)) {\n            return GREEN;\n        }\n        return UNKNOWN;\n    }\n\n    public static TemplateHealthEnum valuesOf(String desc) {\n        if (AriusObjUtils.isBlack(desc) || UNKNOWN.getDesc().equals(desc)) {\n            return UNKNOWN;\n        }\n\n        if (YELLOW.getDesc().equals(desc)) {\n            return YELLOW;\n        } else if (RED.getDesc().equals(desc)) {\n            return RED;\n        } else if (GREEN.getDesc().equals(desc)) {\n            return GREEN;\n        }\n        return UNKNOWN;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    private Integer code;\n    private String  desc;\n\n    public static boolean isExitByCode(Integer code) {\n        if (null == code) {\n            return false;\n        }\n\n        for (TemplateHealthEnum value : TemplateHealthEnum.values()) {\n            if (code.equals(value.getCode())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplateLabelAttributeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\n/**\n * @author didi\n */\npublic enum TemplateLabelAttributeEnum {\n                                        SYS(\"1\", \"平台侧\"),\n\n                                        USER(\"2\", \"用户侧\");\n\n    private String id;\n\n    private String attribute;\n\n    TemplateLabelAttributeEnum(String id, String attribute) {\n        this.id = id;\n        this.attribute = attribute;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public String getAttribute() {\n        return attribute;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplateLabelEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateLabelAttributeEnum.SYS;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateLabelAttributeEnum.USER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateLabelLevelEnum.*;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateLabelSourceEnum.*;\n\n/**\n * @author didi\n */\npublic enum TemplateLabelEnum {\n\n                               /**\n                                *\n                                */\n                               DSL_NEED_REVIEW(\"01\", \"DSL查询需要审核\", ADMIN, SYS, GREEN, TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               IMPORTANT(\"02\", \"重要索引\", ADMIN, SYS, GREEN, TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               FULL_LINK_SUPPORT(\"03\", \"全链路保证\", ADMIN, USER, GREEN, TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               SUSPEND_GOVERN(\"04\", \"暂停治理\", ADMIN, USER, GREEN, TemplateLabelPeriodEnum.THREE_MONTH),\n\n                               /**\n                                *\n                                */\n                               QUOTA_USAGE_LOW(\"20\", \"Quota利用率过低\", PLATFORM_GOVERN, USER, YELLOW,\n                                               TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               QUOTA_USAGE_HIGH(\"21\", \"Quota利用率过高\", PLATFORM_GOVERN, USER, RED,\n                                                TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               EXPIRE_DAYS_LONG(\"22\", \"保存周期过长\", PLATFORM_GOVERN, USER, YELLOW,\n                                                TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               HAS_DELETED_DOC(\"40\", \"有删除操作\", AMS, SYS, GREEN, TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               VALUE_LOW(\"41\", \"低价值\", AMS, USER, YELLOW, TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               MAPPING_NEED_IMPROVE(\"42\", \"mapping待优化\", AMS, USER, YELLOW,\n                                                    TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               QUERY_ERROR(\"43\", \"异常查询\", AMS, USER, YELLOW, TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               QUERY_SLOW(\"44\", \"慢查询\", AMS, USER, YELLOW, TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               NO_DATA(\"45\", \"无数据\", AMS, USER, RED, TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               NO_WRITE(\"46\", \"无写入\", AMS, USER, YELLOW, TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               NO_QUERY(\"47\", \"无查询\", AMS, USER, RED, TemplateLabelPeriodEnum.FOREVER),\n\n                               /**\n                                *\n                                */\n                               INVALID(\"48\", \"废弃索引\", AMS, USER, RED, TemplateLabelPeriodEnum.FOREVER);\n\n    public static final String         LABEL_ID   = \"labelId\";\n\n    public static final String         LABEL_NAME = \"labelName\";\n\n    private String                     id;\n\n    private String                     name;\n\n    private TemplateLabelSourceEnum    source;\n\n    private TemplateLabelAttributeEnum attribute;\n\n    private TemplateLabelLevelEnum     level;\n\n    private TemplateLabelPeriodEnum    period;\n\n    TemplateLabelEnum(String id, String name, TemplateLabelSourceEnum source, TemplateLabelAttributeEnum attribute,\n                      TemplateLabelLevelEnum level, TemplateLabelPeriodEnum period) {\n        this.id = id;\n        this.name = name;\n        this.source = source;\n        this.attribute = attribute;\n        this.level = level;\n        this.period = period;\n    }\n\n    public static TemplateLabelEnum valueBy(String labelId) {\n        for (TemplateLabelEnum labelEnum : TemplateLabelEnum.values()) {\n            if (labelEnum.getId().equals(labelId)) {\n                return labelEnum;\n            }\n        }\n        return null;\n    }\n\n    public String getId() {\n        return source.getId() + attribute.getId() + level.getId() + id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public TemplateLabelSourceEnum getSource() {\n        return source;\n    }\n\n    public TemplateLabelAttributeEnum getAttribute() {\n        return attribute;\n    }\n\n    public TemplateLabelLevelEnum getLevel() {\n        return level;\n    }\n\n    public TemplateLabelPeriodEnum getPeriod() {\n        return period;\n    }\n\n    public static List<Map<String, Object>> getLabelList() {\n        List<Map<String, Object>> list = Lists.newArrayList();\n        for (TemplateLabelEnum labelEnum : TemplateLabelEnum.values()) {\n            Map<String, Object> map = Maps.newHashMap();\n            map.put(LABEL_ID, labelEnum.getId());\n            map.put(LABEL_NAME, labelEnum.getName());\n            list.add(map);\n        }\n        return list;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplateLabelLevelEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\n/**\n * @author didi\n */\npublic enum TemplateLabelLevelEnum {\n                                    GREEN(\"1\", \"green\"),\n\n                                    YELLOW(\"2\", \"yellow\"),\n\n                                    RED(\"3\", \"red\");\n\n    private String id;\n\n    private String level;\n\n    TemplateLabelLevelEnum(String id, String level) {\n        this.id = id;\n        this.level = level;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public String getLevel() {\n        return level;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplateLabelPeriodEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\nimport static javax.management.timer.Timer.ONE_DAY;\n\n/**\n * @author didi\n */\npublic enum TemplateLabelPeriodEnum {\n\n                                     FOREVER(\"1\", \"永久\", -1L),\n\n                                     ONE_MONTH(\"2\", \"一个月\", ONE_DAY * 30),\n\n                                     THREE_MONTH(\"3\", \"三个月\", ONE_DAY * 90);\n\n    private String id;\n\n    private String period;\n\n    private Long   intervalMillis;\n\n    TemplateLabelPeriodEnum(String id, String period, Long intervalMillis) {\n        this.id = id;\n        this.period = period;\n        this.intervalMillis = intervalMillis;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public String getPeriod() {\n        return period;\n    }\n\n    public Long getIntervalMillis() {\n        return intervalMillis;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplateLabelSourceEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\n/**\n * @author didi\n */\npublic enum TemplateLabelSourceEnum {\n\n                                     ADMIN(\"1\", \"admin\"),\n\n                                     AMS(\"2\", \"ams\"),\n\n                                     PLATFORM_GOVERN(\"3\", \"平台治理\");\n\n    private String id;\n\n    private String source;\n\n    TemplateLabelSourceEnum(String id, String source) {\n        this.id = id;\n        this.source = source;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public String getSource() {\n        return source;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplatePhysicalStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\npublic enum TemplatePhysicalStatusEnum {\n                                        /**常规*/\n                                        NORMAL(1, \"常规\"),\n\n                                        INDEX_DELETING(-1, \"索引删除中\"),\n\n                                        DELETED(-2, \"删除\"),\n\n                                        UNKNOWN(-3, \"unknown\");\n\n    TemplatePhysicalStatusEnum(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private int    code;\n\n    private String desc;\n\n    private String label;\n\n    public int getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public String getLabel() {\n        return label;\n    }\n\n    public static TemplatePhysicalStatusEnum valueOf(Integer code) {\n        if (code == null) {\n            return TemplatePhysicalStatusEnum.UNKNOWN;\n        }\n        for (TemplatePhysicalStatusEnum state : TemplatePhysicalStatusEnum.values()) {\n            if (state.getCode() == code) {\n                return state;\n            }\n        }\n\n        return TemplatePhysicalStatusEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/template/TemplateServiceEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.template;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ESClusterVersionEnum.ES_2_3_3_100;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ESClusterVersionEnum.ES_6_6_1_700;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ESClusterVersionEnum.ES_6_6_1_902;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ESClusterVersionEnum.ES_6_6_6_800;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ESClusterVersionEnum.ES_7_6_0_1100;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESClusterVersionEnum;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author zqr\n * @date 2020-09-09\n */\npublic enum TemplateServiceEnum {\n\n                                 /**\n                                  * 预创建：对于分区创建的索引，支持预创建，减轻集群负担，提高稳定性.\n                                  */\n                                 TEMPLATE_PRE_CREATE(1, \"预创建\", ES_2_3_3_100, 1),\n                                     /**\n                                  * Pipeline：提供索引分区规则（索引模版到具体的物理索引的映射）和写入限流能力.\n                                  */\n                                 TEMPLATE_PIPELINE(2, \"Pipeline\", ES_6_6_6_800, 1),\n       /**\n                                  * 索引规划：索引shard动态调整+indexRollover能力\n                                  */\n                                 INDEX_PLAN(3, \"索引规划\", ES_6_6_1_700, 1),\n\n                                 /**\n                                  * 过期删除：支持索引根据保存周期自动清理，避免磁盘过满.\n                                  */\n                                 TEMPLATE_DEL_EXPIRE(4, \"过期删除\", ES_2_3_3_100, 1),\n                                 /**\n                                  * 冷热分离：提供SSD和HDD两种类型的磁盘来保存索引，从而降低成本.\n                                  */\n                                 TEMPLATE_COLD(5, \"冷热分离\", ES_6_6_1_700, 1),\n                                     /**\n                                  * 索引别名：支持通过接口来设置和修改索引别名.\n                                  */\n                                 TEMPLATE_ALIASES(6, \"索引别名\", ES_6_6_1_700, 1),\n    \n    /**\n     * Mapping 设置 ：提供修改索引的 mapping 的信息的功能.\n     * 4-》7\n     */\n    TEMPLATE_MAPPING(7, \"Mapping设置\", ES_6_6_1_700, 1),\n\n\n                                 /**\n                                  * Setting 设置 ：提供修改索引 Setting 的信息的功能.\n                                  * 5-》8\n                                  */\n                                 TEMPLATE_SETTING(8, \"Setting设置\", ES_6_6_1_700, 1),\n                                     /**\n                                  * 写入限流：对索引写入量进行限制，避免过大影响集群稳定性.\n                                  */\n                                 TEMPLATE_LIMIT_W(9, \"写入限流\", ES_6_6_6_800, 1),\n\n    \n                               \n\n                                 /**\n                                  * 跨集群同步（DCDR）：跨集群数据复制功能，用于集群间的数据复制，类似ES官方的CCR能力.\n                                  */\n                                 TEMPLATE_DCDR(10, \"跨集群同步(DCDR)\", ES_6_6_1_902, 1),\n\n\n\n                              \n\n                                 /**\n                                  * 安全管控:对于索引的安全服务进行权限控制.\n                                  */\n                                 TEMPLATE_SECURITY(13, \"安全管控\", ES_7_6_0_1100, 0),\n\n                                 /**\n                                  * 清理\n                                  */\n                                  @Deprecated\n                                 TEMPLATE_CLEAR(14, \"清理\", ES_2_3_3_100, 0),\n\n                                 /**\n                                  * 升级版本\n                                  */\n                                  @Deprecated\n                                 TEMPLATE_UPGRADE(15, \"升级版本\", ES_2_3_3_100, 0),\n\n                                 /**\n                                  * 扩缩容（调整shard）\n                                  */\n                                 @Deprecated\n                                 TEMPLATE_ADJUST_SHARD(16, \"扩缩容\", ES_2_3_3_100, 0);\n\n    private Integer              code;\n\n    private String               serviceName;\n\n    private Integer              defaultSrv;\n\n    private ESClusterVersionEnum esClusterVersion;\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getServiceName() {\n        return serviceName;\n    }\n\n    public Integer getDefaultSrv() {\n        return defaultSrv;\n    }\n\n    public ESClusterVersionEnum getEsClusterVersion() {\n        return esClusterVersion;\n    }\n\n    TemplateServiceEnum(Integer code, String serviceName, ESClusterVersionEnum esClusterVersion, Integer defaultSrv) {\n        this.code = code;\n        this.serviceName = serviceName;\n        this.esClusterVersion = esClusterVersion;\n        this.defaultSrv = defaultSrv;\n    }\n\n    public static TemplateServiceEnum getById(int code) {\n        for (TemplateServiceEnum templateServiceEnum : TemplateServiceEnum.values()) {\n            if (templateServiceEnum.getCode().intValue() == code) {\n                return templateServiceEnum;\n            }\n        }\n        return null;\n    }\n\n    public static List<TemplateServiceEnum> allTemplateSrv() {\n        return Arrays.asList(TemplateServiceEnum.values());\n    }\n\n    public boolean isDefaultSrv() {\n        return 1 == getDefaultSrv();\n    }\n\n    public static String getDefaultSrvs() {\n        List<TemplateServiceEnum> serviceEnumList = new ArrayList<>();\n        for (TemplateServiceEnum templateServiceEnum : TemplateServiceEnum.values()) {\n            if (templateServiceEnum.isDefaultSrv()) {\n                serviceEnumList.add(templateServiceEnum);\n            }\n        }\n\n        if (CollectionUtils.isEmpty(serviceEnumList)) {\n            return \"\";\n        }\n\n        return serviceEnumList.stream().map(t -> String.valueOf(t.getCode())).collect(Collectors.joining(\",\"));\n    }\n\n    \n    \n    public static List<TemplateServiceEnum> usePartitionService(){\n        \n        \n        return Lists.newArrayList(TemplateServiceEnum.TEMPLATE_PRE_CREATE,TemplateServiceEnum.TEMPLATE_DEL_EXPIRE,\n                TemplateServiceEnum.TEMPLATE_COLD);\n    }\n    \n   \n    \n    /**\n     * str是否保存传入的枚举类\n     *\n     * @param openSrvStr  打开电脑,str\n     * @param serviceEnum\n     * @return boolean\n     */\n    public static boolean strContainsSrv(String openSrvStr, TemplateServiceEnum serviceEnum) {\n        if (StringUtils.isBlank(openSrvStr)) {\n            return Boolean.FALSE;\n        }\n        return Arrays.stream(StringUtils.split(openSrvStr, \",\")).filter(StringUtils::isNumeric).map(Integer::parseInt)\n                .map(TemplateServiceEnum::getById).filter(Objects::nonNull).anyMatch(srv -> srv.equals(serviceEnum));\n    }\n    \n    public static List<TemplateServiceEnum> str2Srv(String openSrvStr) {\n        if (StringUtils.isBlank(openSrvStr)){\n            return Collections.emptyList();\n        }\n        \n        return Arrays.stream(StringUtils.split(openSrvStr, \",\")).filter(StringUtils::isNumeric).map(Integer::parseInt)\n                .map(TemplateServiceEnum::getById).filter(Objects::nonNull).distinct().collect(Collectors.toList());\n    }\n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/workorder/BpmAuditTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.workorder;\n\n/**\n * 工单节点动作\n * 不能修改，必须这3个\n *\n * @author d06679\n * @date 2018/10/25\n */\npublic enum BpmAuditTypeEnum {\n                              /**agree*/\n                              AGREE(\"agree\"),\n\n                              DISAGREE(\"disagree\"),\n\n                              SUBMIT(\"submit\");\n\n    private String value;\n\n    BpmAuditTypeEnum(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public static BpmAuditTypeEnum valueFrom(String value) {\n        if (value == null) {\n            return null;\n        }\n        for (BpmAuditTypeEnum state : BpmAuditTypeEnum.values()) {\n            if (state.getValue().equals(value)) {\n                return state;\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/workorder/OperationTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.workorder;\n\n/**\n * 操作类型\n * @author fengqiongfeng\n * @date 2020/08/24\n */\npublic enum OperationTypeEnum {\n                               CREATE(0,\n                                      \"创建\"), UPDATE(1,\n                                                    \"更新\"), DELETE(2,\n                                                                  \"删除\"), INSTALL(3,\n                                                                                 \"安装\"), UNINSTALL(4,\n                                                                                                  \"卸载\"), UNKNOWN(-1,\n                                                                                                                 \"UNKNOWN\");\n\n    private Integer code;\n\n    private String  message;\n\n    OperationTypeEnum(Integer code, String message) {\n        this.code = code;\n        this.message = message;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public static OperationTypeEnum valueOfCode(Integer code) {\n        if (null == code) {\n            return OperationTypeEnum.UNKNOWN;\n        }\n        for (OperationTypeEnum typeEnum : OperationTypeEnum.values()) {\n            if (code.equals(typeEnum.getCode())) {\n                return typeEnum;\n            }\n        }\n\n        return OperationTypeEnum.UNKNOWN;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/workorder/OrderStatusEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.workorder;\n\n/**\n * 工单状态\n * @author fengqiongfeng\n * @date 2020/8/24\n */\npublic enum OrderStatusEnum {\n                             WAIT_DEAL(0, \"待处理\"),\n\n                             PASSED(1, \"通过\"),\n\n                             REFUSED(2, \"拒绝\"),\n\n                             CANCELLED(3, \"取消\");\n\n    private Integer code;\n\n    private String  message;\n\n    OrderStatusEnum(Integer code, String message) {\n        this.code = code;\n        this.message = message;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/workorder/OrderTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.workorder;\n\n/**\n * 工单类型\n * @author fengqiongfeng\n * @date 20/8/24\n */\npublic enum OrderTypeEnum {\n                           APPLY_INDEX(00, \"索引申请\",\n                                       \"applyIndexOrder\"), DELETE_INDEX(10, \"索引下线\",\n                                                                        \"deleteIndexOrder\"), APPLY_EXPAND_INDEX(20,\n                                                                                                                \"索引扩容\",\n                                                                                                                \"modifyIndexOrder\"), APPLY_REDUCE_INDEX(21,\n                                                                                                                                                        \"索引缩容\",\n                                                                                                                                                        \"modifyIndexOrder\"), APPLY_ROLE_INDEX(30,\n                                                                                                                                                                                              \"索引权限申请\",\n                                                                                                                                                                                              \"deleteIndexOrder\"), TRANSFER_INDEX(40,\n                                                                                                                                                                                                                                  \"索引转让\",\n                                                                                                                                                                                                                                  \"transferIndexOrder\"),\n\n                           APPLY_APP(01, \"应用申请\", \"applyAppOrder\"),\n\n                           APPLY_CLUSTER(04, \"集群申请\", \"applyClusterOrder\"), DELETE_CLUSTER(13, \"集群下线\",\n                                                                                          \"deleteClusterOrder\"),\n\n                           APPLY_EXPAND_CLUSTER(22, \"集群扩容\",\n                                                \"modifyClusterOrder\"), APPLY_REDUCE_CLUSTER(23, \"集群缩容\",\n                                                                                            \"modifyClusterOrder\"),\n\n                           APPLY_QUERY_SENTENCE(05, \"查询语句申请\",\n                                                \"applyQuerySentenceOrder\"), APPLY_QUERY_LIMITING(23, \"查询语句限流\",\n                                                                                                 \"limittingQueryOrder\"),\n\n                           APPLY_CLUSTER_PLUG_INSTALL(30, \"集群插件安装\",\n                                                      \"logicClusterPlugOperation\"), APPLY_CLUSTER_PLUG_UNINSTALL(40,\n                                                                                                                 \"集群插件卸载\",\n                                                                                                                 \"logicClusterPlugOperation\"),\n\n    ;\n\n    private Integer code;\n\n    private String  message;\n\n    private String  orderName;\n\n    OrderTypeEnum(Integer code, String message, String orderName) {\n        this.code = code;\n        this.message = message;\n        this.orderName = orderName;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public String getOrderName() {\n        return orderName;\n    }\n\n    public static String getOrderNameByType(Integer code) {\n        for (OrderTypeEnum orderTypeEnum : values()) {\n            if (orderTypeEnum.getCode().equals(code)) {\n                return orderTypeEnum.getOrderName();\n            }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/constant/workorder/WorkOrderTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.constant.workorder;\n\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * arius工单状态枚举\n * name要求是对应的handler的bean的名字的前缀;框架会根据前缀去找handler\n *\n * @author d06679\n * @date 2018/9/18\n */\npublic enum WorkOrderTypeEnum {\n\n                               /**\n                                * 逻辑集群创建\n                                */\n                               LOGIC_CLUSTER_CREATE(\"logicClusterCreate\", \"集群创建\"),\n\n                               /**\n                                * 逻辑集群indecrease\n                                */\n                               LOGIC_CLUSTER_INDECREASE(\"logicClusterIndecrease\", \"集群扩(缩)容\"),\n\n                               LOGIC_CLUSTER_OP_DELETE(\"logicClusterDelete\", \"逻辑集群删除\"),\n\n                               LOGIC_CLUSTER_AUTH(\"logicClusterAuth\", \"集群权限\"),\n\n                               LOGIC_CLUSTER_TRANSFER(\"logicClusterTransfer\", \"逻辑集群转让\"),\n\n                               LOGIC_CLUSTER_PLUGIN(\"logicClusterPlugin\", \"集群插件\"),\n\n                               TEMPLATE_AUTH(\"templateAuth\", \"索引权限\"),\n\n                               TEMPLATE_CREATE(\"templateCreate\", \"模版创建\"),\n\n                               TEMPLATE_INDECREASE(\"templateIndecrease\", \"模版扩缩\"),\n\n                               TEMPLATE_QUERY_DSL(\"templateQueryDsl\", \"查询语句\"),\n\n                               TEMPLATE_TRANSFER(\"templateTransfer\", \"模版转移\"),\n\n                               TEMPLATE_LOGIC_BLOCK_WRITE(\"templateLogicBlockWrite\", \"索引模板写状态变更\"),\n\n                               TEMPLATE_LOGIC_BLOCK_READ(\"templateLogicBlockRead\", \"索引模板读状态变更\"),\n\n                               DSL_TEMPLATE_STATUS_CHANGE(\"dslTemplateStatusChange\", \"查询模板状态变更\"),\n\n                               DSL_TEMPLATE_QUERY_LIMIT(\"dslTemplateQueryLimit\", \"查询模板限流值变更\"),\n\n                               QUERY_DSL_LIMIT_EDIT(\"queryDslLimitEdit\", \"查询语句编辑\"),\n\n                               CLUSTER_OP_INDECREASE(\"clusterOpIndecrease\", \"集群扩缩(OP)\"),\n\n                               CLUSTER_OP_NEW(\"clusterOpNew\", \"集群创建(OP)\"),\n\n                               CLUSTER_OP_PLUG_OPERATION(\"logicClusterPlugOperation\", \"集群插件操作\"),\n\n                               CLUSTER_OP_OFFLINE(\"clusterOpOffline\", \"集群下线(OP)\"),\n\n                               CLUSTER_OP_RESTART(\"clusterOpRestart\", \"集群重启(OP)\"),\n\n                               CLUSTER_OP_CONFIG_RESTART(\"clusterOpConfigRestart\", \"集群配置重启(OP)\"),\n\n                               CLUSTER_OP_UPDATE(\"clusterOpUpdate\", \"集群升级(OP)\"),\n\n                               CLUSTER_DELETE(\"clusterDelete\", \"物理集群删除\"),\n\n                               PHY_CLUSTER_PLUGIN_OPERATION(\"clusterOpPluginRestart\", \"物理集群插件操作\"),\n    LOGIC_CLUSTER_JOIN(\"logicClusterJoin\", \"集群加入\"),\n\n                               UNKNOWN(\"unknown\", \"未知\");\n\n    WorkOrderTypeEnum(String name, String message) {\n        this.name = name;\n        this.message = message;\n    }\n\n    private String name;\n\n    private String message;\n\n    public String getName() {\n        return name;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public static WorkOrderTypeEnum valueOfName(String name) {\n        if (StringUtils.isBlank(name)) {\n            return WorkOrderTypeEnum.UNKNOWN;\n        }\n        for (WorkOrderTypeEnum typeEnum : WorkOrderTypeEnum.values()) {\n            if (name.equals(typeEnum.getName())) {\n                return typeEnum;\n            }\n        }\n\n        return WorkOrderTypeEnum.UNKNOWN;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/auth/ProjectAuthEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.auth;\n\nimport org.springframework.context.ApplicationEvent;\n\npublic abstract class ProjectAuthEvent extends ApplicationEvent {\n\n    protected ProjectAuthEvent(Object source) {\n        super(source);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/auth/ProjectLogicClusterAuthAddEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.auth;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\n\n/**\n * App逻辑集群权限增加事件\n * @author wangshu\n * @date 2020/09/19\n */\npublic class ProjectLogicClusterAuthAddEvent extends ProjectAuthEvent {\n    private ProjectClusterLogicAuth clusterAuth;\n\n    public ProjectLogicClusterAuthAddEvent(Object source, ProjectClusterLogicAuth logicClusterAuth) {\n        super(source);\n        this.clusterAuth = logicClusterAuth;\n    }\n\n    /**\n     * 获取App逻辑权限\n     * @return\n     */\n    public ProjectClusterLogicAuth getClusterAuth() {\n        return this.clusterAuth;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/auth/ProjectLogicClusterAuthDeleteEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.auth;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\n\n/**\n * App逻辑集群删除事件\n * @author wangshu\n * @date 2020/09/19\n */\npublic class ProjectLogicClusterAuthDeleteEvent extends ProjectAuthEvent {\n    private ProjectClusterLogicAuth logicClusterAuth;\n\n    public ProjectLogicClusterAuthDeleteEvent(Object source, ProjectClusterLogicAuth projectClusterLogicAuth) {\n        super(source);\n        this.logicClusterAuth = projectClusterLogicAuth;\n    }\n\n    public ProjectClusterLogicAuth getLogicClusterAuth() {\n        return logicClusterAuth;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/auth/ProjectLogicClusterAuthEditEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.auth;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\n\n/**\n * App逻辑集群权限编辑事件\n * @author wangshu\n * @date 2020/09/19\n */\npublic class ProjectLogicClusterAuthEditEvent extends ProjectAuthEvent {\n    private ProjectClusterLogicAuth srcAuth;\n    private ProjectClusterLogicAuth tgtAuth;\n\n    public ProjectLogicClusterAuthEditEvent(Object source, ProjectClusterLogicAuth srcAuth,\n                                            ProjectClusterLogicAuth tgtAuth) {\n        super(source);\n        this.srcAuth = srcAuth;\n        this.tgtAuth = tgtAuth;\n    }\n\n    public ProjectClusterLogicAuth getSrcAuth() {\n        return srcAuth;\n    }\n\n    public ProjectClusterLogicAuth getTgtAuth() {\n        return tgtAuth;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/auth/ProjectTemplateAuthAddEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.auth;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\n\n/**\n * @author d06679\n * @date 2019/4/18\n */\npublic class ProjectTemplateAuthAddEvent extends ProjectAuthEvent {\n\n    private ProjectTemplateAuth projectTemplateAuth;\n\n    public ProjectTemplateAuthAddEvent(Object source, ProjectTemplateAuth projectTemplateAuth) {\n        super(source);\n        this.projectTemplateAuth = projectTemplateAuth;\n    }\n\n    public ProjectTemplateAuth getAppTemplateAuth() {\n        return projectTemplateAuth;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/auth/ProjectTemplateAuthDeleteEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.auth;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\n\n/**\n * @author d06679\n * @date 2019/4/18\n */\npublic class ProjectTemplateAuthDeleteEvent extends ProjectAuthEvent {\n\n    private ProjectTemplateAuth projectTemplateAuth;\n\n    public ProjectTemplateAuthDeleteEvent(Object source, ProjectTemplateAuth projectTemplateAuth) {\n        super(source);\n        this.projectTemplateAuth = projectTemplateAuth;\n    }\n\n    public ProjectTemplateAuth getAppTemplateAuth() {\n        return projectTemplateAuth;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/auth/ProjectTemplateAuthEditEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.auth;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\n\n/**\n * @author d06679\n * @date 2019/4/18\n */\npublic class ProjectTemplateAuthEditEvent extends ProjectAuthEvent {\n\n    private ProjectTemplateAuth srcAuth;\n\n    private ProjectTemplateAuth tgtAuth;\n\n    public ProjectTemplateAuthEditEvent(Object source, ProjectTemplateAuth srcAuth, ProjectTemplateAuth tgtAuth) {\n        super(source);\n        this.srcAuth = srcAuth;\n        this.tgtAuth = tgtAuth;\n    }\n\n    public ProjectTemplateAuth getSrcAuth() {\n        return srcAuth;\n    }\n\n    public ProjectTemplateAuth getTgtAuth() {\n        return tgtAuth;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/ecm/EcmTaskEditEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.ecm.EcmTask;\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @author lyn\n * @date 2021-01-26\n */\npublic class EcmTaskEditEvent extends ApplicationEvent {\n\n    private EcmTask editTask;\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public EcmTaskEditEvent(Object source, EcmTask editTask) {\n        super(source);\n        this.editTask = editTask;\n    }\n\n    public EcmTask getEditTask() {\n        return editTask;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/index/IndexDeleteEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.index;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport java.util.List;\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @author shizeying\n * @date 2022/07/18\n */\n\npublic class IndexDeleteEvent extends ApplicationEvent {\n\tprivate Integer projectId;\n\tprivate String operator;\n\tprivate List<IndexCatCellDTO> catCellList;\n\t\n\t/**\n\t * @param source\n\t */\n\tpublic IndexDeleteEvent(Object source, List<IndexCatCellDTO> catCellList,Integer projectId,String operator) {\n\t\tsuper(source);\n\t\tthis.catCellList = catCellList;\n\t\tthis.projectId=projectId;\n\t\tthis.operator=operator;\n\t}\n\t\n\tpublic Integer getProjectId() {\n\t\treturn projectId;\n\t}\n\t\n\tpublic String getOperator() {\n\t\treturn operator;\n\t}\n\t\n\tpublic List<IndexCatCellDTO> getCatCellList() {\n\t\treturn catCellList;\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/index/ReBuildTomorrowIndexEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.index;\n\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @author shizeying\n * @date 2022/07/18\n */\npublic class ReBuildTomorrowIndexEvent extends ApplicationEvent {\n\t private Integer                 logicId;\n\t\n\t/**\n\t * @param source\n\t */\n\tpublic ReBuildTomorrowIndexEvent(Object source,Integer logicId) {\n\t\tsuper(source);\n\t\tthis.logicId=logicId;\n\t}\n\t\n\tpublic Integer getLogicId() {\n\t\treturn logicId;\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/index/RefreshCatIndexInfoEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.index;\n\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport java.util.List;\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @author shizeying\n * @date 2022/07/30\n */\npublic class RefreshCatIndexInfoEvent extends ApplicationEvent {\n\t\n\t\n\t private  final List<TupleTwo</*clusterPhy*/String,/*index*/String>> clusterIndexTupleList;\n\t\n\tpublic RefreshCatIndexInfoEvent(Object source, List<TupleTwo<String, String>> clusterIndexTupleList) {\n\t\tsuper(source);\n\t\tthis.clusterIndexTupleList = clusterIndexTupleList;\n\t}\n\t\n\tpublic List<TupleTwo<String, String>> getClusterIndexTupleList() {\n\t\treturn clusterIndexTupleList;\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/metrics/MetaDataMetricsEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.metrics;\n\nimport org.springframework.context.ApplicationEvent;\n\npublic abstract class MetaDataMetricsEvent extends ApplicationEvent {\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public MetaDataMetricsEvent(Object source) {\n        super(source);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/metrics/MetricsMonitorClusterEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStats;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport java.util.List;\nimport java.util.Map;\n\npublic class MetricsMonitorClusterEvent extends MetaDataMetricsEvent {\n\n    private List<ESClusterStats>                     esClusterStatsList;\n\n    private Map<ClusterPhy, ESClusterHealthResponse> clusterHealthResponseMap;\n\n    private String                                   hostName;\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public MetricsMonitorClusterEvent(Object source, List<ESClusterStats> esClusterStatsList,\n                                      Map<ClusterPhy, ESClusterHealthResponse> clusterHealthResponseMap,\n                                      String hostName) {\n        super(source);\n        this.esClusterStatsList = esClusterStatsList;\n        this.clusterHealthResponseMap = clusterHealthResponseMap;\n        this.hostName = hostName;\n    }\n\n    public List<ESClusterStats> getEsClusterStatsList() {\n        return esClusterStatsList;\n    }\n\n    public Map<ClusterPhy, ESClusterHealthResponse> getClusterHealthResponseMap() {\n        return clusterHealthResponseMap;\n    }\n\n    public String getHostName() {\n        return hostName;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/metrics/MetricsMonitorCollectTimeEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.metrics;\n\npublic class MetricsMonitorCollectTimeEvent extends MetaDataMetricsEvent {\n\n    private String  cluster;\n\n    private Integer clusterLevel;\n\n    private String  type;\n\n    private double  time;\n\n    private String  hostName;\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public MetricsMonitorCollectTimeEvent(Object source, String type, double time, String cluster, Integer clusterLevel,\n                                          String hostName) {\n        super(source);\n        this.type = type;\n        this.time = time;\n        this.cluster = cluster;\n        this.clusterLevel = clusterLevel;\n        this.hostName = hostName;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public double getTime() {\n        return time;\n    }\n\n    public String getCluster() {\n        return cluster;\n    }\n\n    public Integer getClusterLevel() {\n        return clusterLevel;\n    }\n\n    public String getHostName() {\n        return hostName;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/metrics/MetricsMonitorIndexEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESDataTempBean;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexStats;\n\nimport java.util.List;\n\npublic class MetricsMonitorIndexEvent extends MetaDataMetricsEvent {\n\n    private List<ESDataTempBean> esDataTempBeans;\n\n    private List<ESIndexStats>   esIndexStatsList;\n\n    private Integer              clusterLevel;\n\n    private String               hostName;\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public MetricsMonitorIndexEvent(Object source, List<ESDataTempBean> esDataTempBeans,\n                                    List<ESIndexStats> esIndexStatsList, Integer clusterLevel, String hostName) {\n        super(source);\n        this.esDataTempBeans = esDataTempBeans;\n        this.esIndexStatsList = esIndexStatsList;\n        this.clusterLevel = clusterLevel;\n        this.hostName = hostName;\n    }\n\n    public List<ESDataTempBean> getEsDataTempBeans() {\n        return esDataTempBeans;\n    }\n\n    public Integer getClusterLevel() {\n        return clusterLevel;\n    }\n\n    public String getHostName() {\n        return hostName;\n    }\n\n    public List<ESIndexStats> getEsIndexStatsList() {\n        return esIndexStatsList;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/metrics/MetricsMonitorLogicClusterEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.metrics;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStats;\n\npublic class MetricsMonitorLogicClusterEvent extends MetaDataMetricsEvent {\n    private List<ESClusterStats> esClusterStatsList;\n    private String               hostName;\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public MetricsMonitorLogicClusterEvent(Object source, List<ESClusterStats> esClusterStatsList, String hostName) {\n        super(source);\n        this.esClusterStatsList = esClusterStatsList;\n        this.hostName = hostName;\n    }\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public MetricsMonitorLogicClusterEvent(Object source) {\n        super(source);\n    }\n\n    public List<ESClusterStats> getEsClusterStatsList() {\n        return esClusterStatsList;\n    }\n\n    public String getHostName() {\n        return hostName;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/metrics/MetricsMonitorNodeEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESDataTempBean;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESNodeStats;\n\nimport java.util.List;\n\npublic class MetricsMonitorNodeEvent extends MetaDataMetricsEvent {\n\n    private List<ESDataTempBean> esDataTempBeans;\n\n    private List<ESNodeStats>    esNodeStatsList;\n\n    private Integer              clusterLevel;\n\n    private String               hostName;\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public MetricsMonitorNodeEvent(Object source, List<ESDataTempBean> esDataTempBeans,\n                                   List<ESNodeStats> esNodeStatsList, Integer clusterLevel, String hostName) {\n        super(source);\n        this.esDataTempBeans = esDataTempBeans;\n        this.clusterLevel = clusterLevel;\n        this.esNodeStatsList = esNodeStatsList;\n        this.hostName = hostName;\n    }\n\n    public List<ESDataTempBean> getEsDataTempBeans() {\n        return esDataTempBeans;\n    }\n\n    public Integer getClusterLevel() {\n        return clusterLevel;\n    }\n\n    public String getHostName() {\n        return hostName;\n    }\n\n    public List<ESNodeStats> getEsNodeStats() {\n        return esNodeStatsList;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/region/RegionBindEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.region;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @Author: lanxinzheng\n * @Date: 2021/1/7\n * @Comment: region绑定事件\n */\npublic class RegionBindEvent extends ApplicationEvent {\n\n    private ClusterRegion clusterRegion;\n\n    private Integer       share;\n\n    private String        operator;\n\n    public RegionBindEvent(Object source, ClusterRegion clusterRegion, Integer share, String operator) {\n        super(source);\n        this.clusterRegion = clusterRegion;\n        this.share = share;\n        this.operator = operator;\n    }\n\n    public ClusterRegion getClusterRegion() {\n        return clusterRegion;\n    }\n\n    public Integer getShare() {\n        return share;\n    }\n\n    public String getOperator() {\n        return operator;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/region/RegionCreateEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.region;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @Author: lanxinzheng\n * @Date: 2021/1/7\n * @Comment: region创建事件\n */\npublic class RegionCreateEvent extends ApplicationEvent {\n\n    private ClusterRegion clusterRegion;\n\n    private Integer       share;\n\n    private String        operator;\n\n    public RegionCreateEvent(Object source, ClusterRegion clusterRegion, Integer share, String operator) {\n        super(source);\n        this.clusterRegion = clusterRegion;\n        this.operator = operator;\n        this.share = share;\n    }\n\n    public ClusterRegion getClusterRegion() {\n        return clusterRegion;\n    }\n\n    public Integer getShare() {\n        return share;\n    }\n\n    public String getOperator() {\n        return operator;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/region/RegionDeleteEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.region;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @Author: lanxinzheng\n * @Date: 2021/1/7\n * @Comment: region删除事件\n */\npublic class RegionDeleteEvent extends ApplicationEvent {\n\n    private ClusterRegion clusterRegion;\n\n    private String        operator;\n\n    public RegionDeleteEvent(Object source, ClusterRegion clusterRegion, String operator) {\n        super(source);\n        this.clusterRegion = clusterRegion;\n        this.operator = operator;\n    }\n\n    public ClusterRegion getClusterRegion() {\n        return clusterRegion;\n    }\n\n    public String getOperator() {\n        return operator;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/region/RegionEditEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.region;\n\nimport org.springframework.context.ApplicationEvent;\n\nimport java.util.List;\n\n/**\n * @author didi\n * @date 2022-05-23 2:36 下午\n */\npublic class RegionEditEvent extends ApplicationEvent {\n\n    private List<Long> regionIdList;\n\n    public RegionEditEvent(Object source, List<Long> regionIdList) {\n        super(source);\n        this.regionIdList = regionIdList;\n    }\n\n    public List<Long> getRegionIdList() {\n        return regionIdList;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/region/RegionUnbindEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.region;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @Author: lanxinzheng\n * @Date: 2021/1/7\n * @Comment: region解除绑定事件\n */\npublic class RegionUnbindEvent extends ApplicationEvent {\n\n    private ClusterRegion clusterRegion;\n\n    private String        operator;\n\n    public RegionUnbindEvent(Object source, ClusterRegion clusterRegion, String operator) {\n        super(source);\n        this.clusterRegion = clusterRegion;\n        this.operator = operator;\n    }\n\n    public ClusterRegion getClusterRegion() {\n        return clusterRegion;\n    }\n\n    public String getOperator() {\n        return operator;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/resource/ClusterEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.resource;\n\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * Created by linyunan on 2021-06-03\n */\npublic abstract class ClusterEvent extends ApplicationEvent {\n\n    protected ClusterEvent(Object source) {\n        super(source);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/resource/ClusterLogicEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.resource;\n\n/**\n * Created by linyunan on 2021-06-03\n */\npublic class ClusterLogicEvent extends ClusterEvent {\n\n    private Long    clusterLogicId;\n\n    private Integer projectId;\n\n    public ClusterLogicEvent(Long clusterLogicId, Integer projectId) {\n        super(clusterLogicId);\n        this.clusterLogicId = clusterLogicId;\n        this.projectId = projectId;\n    }\n\n    public Long getClusterLogicId() {\n        return clusterLogicId;\n    }\n\n    public void setClusterLogicId(Long clusterLogicId) {\n        this.clusterLogicId = clusterLogicId;\n    }\n\n    public Integer getProjectId() {\n        return projectId;\n    }\n\n    public void setProjectId(Integer projectId) {\n        this.projectId = projectId;\n    }\n\n    public ClusterLogicEvent(Object source) {\n        super(source);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/resource/ClusterPhyEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.resource;\n\n/**\n * @author linyunan\n * @date 2021-06-03\n */\npublic class ClusterPhyEvent extends ClusterEvent {\n\n    private String clusterPhyName;\n\n    private String operator;\n\n    public ClusterPhyEvent(String clusterPhyName, String operator) {\n        super(clusterPhyName);\n        this.clusterPhyName = clusterPhyName;\n        this.operator = operator;\n    }\n\n    public String getClusterPhyName() {\n        return clusterPhyName;\n    }\n\n    public void setClusterPhyName(String clusterPhyName) {\n        this.clusterPhyName = clusterPhyName;\n    }\n\n    public String getOperator() {\n        return operator;\n    }\n\n    public void setOperator(String operator) {\n        this.operator = operator;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/resource/ClusterPhyHealthEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.resource;\n\nimport org.springframework.context.ApplicationEvent;\n\npublic class ClusterPhyHealthEvent extends ApplicationEvent {\n\n    private String clusterPhyName;\n\n    public ClusterPhyHealthEvent(Object source, String clusterPhyName) {\n        super(source);\n        this.clusterPhyName = clusterPhyName;\n    }\n\n    public String getClusterPhyName() {\n        return clusterPhyName;\n    }\n\n    public void setClusterPhyName(String clusterPhyName) {\n        this.clusterPhyName = clusterPhyName;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/DCDRLinkAbnormalIndicesRebuildEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template;\n\nimport java.util.List;\nimport lombok.Getter;\nimport org.springframework.context.ApplicationEvent;\n\n/**\n *  该类用于集群与目标集群之间的DCDR链路的索引异常，需要重建\n *\n * @author shizeying\n * @date 2022/09/26\n */\n@Getter\npublic class DCDRLinkAbnormalIndicesRebuildEvent extends ApplicationEvent {\n    private final String cluster;\n    private final String targetCluster;\n    private final List<String> indices;\n    \n   \n    \n    public DCDRLinkAbnormalIndicesRebuildEvent(Object source, String cluster, String targetCluster,\n                                              List<String> indices) {\n        super(source);\n        this.cluster = cluster;\n        this.targetCluster = targetCluster;\n        this.indices = indices;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/LogicTemplateCreatePipelineEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template;\n\n/**\n * 逻辑模板创建pipeline\n *\n * @author shizeying\n * @date 2022/07/22\n */\npublic class LogicTemplateCreatePipelineEvent extends LogicTemplateEvent{\n    private final Integer logicTemplateId;\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public LogicTemplateCreatePipelineEvent(Object source,Integer logicTemplateId) {\n        super(source);\n        this.logicTemplateId=logicTemplateId;\n    }\n    \n    public Integer getLogicTemplateId() {\n        return logicTemplateId;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/LogicTemplateEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template;\n\n/**\n * @author d06679\n * @date 2019/4/18\n */\npublic abstract class LogicTemplateEvent extends TemplateEvent {\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    protected LogicTemplateEvent(Object source) {\n        super(source);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/LogicTemplateModifyEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\n\n/**\n *\n * @author d06679\n * @date 2019/4/18\n */\npublic class LogicTemplateModifyEvent extends LogicTemplateEvent {\n\n    private IndexTemplate oldTemplate;\n\n    private IndexTemplate newTemplate;\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public LogicTemplateModifyEvent(Object source, IndexTemplate oldTemplate, IndexTemplate newTemplate) {\n        super(source);\n        this.oldTemplate = oldTemplate;\n        this.newTemplate = newTemplate;\n    }\n\n    public IndexTemplate getOldTemplate() {\n        return oldTemplate;\n    }\n\n    public IndexTemplate getNewTemplate() {\n        return newTemplate;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/PhysicalTemplateAddEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\n\n/**\n * @author d06679\n * @date 2019/4/18\n */\npublic class PhysicalTemplateAddEvent extends PhysicalTemplateEvent {\n\n    private IndexTemplatePhy newTemplate;\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public PhysicalTemplateAddEvent(Object source, IndexTemplatePhy newTemplate,\n                                    IndexTemplateWithPhyTemplates logicWithPhysical) {\n        super(source, logicWithPhysical);\n        this.newTemplate = newTemplate;\n    }\n\n    public IndexTemplatePhy getNewTemplate() {\n        return newTemplate;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/PhysicalTemplateDeleteEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\n\n/**\n * @author d06679\n * @date 2019/4/18\n */\npublic class PhysicalTemplateDeleteEvent extends PhysicalTemplateEvent {\n\n    private IndexTemplatePhy delTemplate;\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public PhysicalTemplateDeleteEvent(Object source, IndexTemplatePhy delTemplate,\n                                       IndexTemplateWithPhyTemplates logicWithPhysical) {\n        super(source, logicWithPhysical);\n        this.delTemplate = delTemplate;\n    }\n\n    public IndexTemplatePhy getDelTemplate() {\n        return delTemplate;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/PhysicalTemplateEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\n\n/**\n * @author d06679\n * @date 2019/4/18\n */\npublic abstract class PhysicalTemplateEvent extends TemplateEvent {\n\n    private IndexTemplateWithPhyTemplates logicWithPhysical;\n\n    protected PhysicalTemplateEvent(Object source, IndexTemplateWithPhyTemplates logicWithPhysical) {\n        super(source);\n        this.logicWithPhysical = logicWithPhysical;\n    }\n\n    public IndexTemplateWithPhyTemplates getLogicWithPhysical() {\n        return logicWithPhysical;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/PhysicalTemplateModifyEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\n\n/**\n * @author d06679\n * @date 2019/4/18\n */\npublic class PhysicalTemplateModifyEvent extends PhysicalTemplateEvent {\n\n    private IndexTemplatePhy oldTemplate;\n\n    private IndexTemplatePhy newTemplate;\n\n    /**\n     * Create a new ApplicationEvent.\n     *\n     * @param source the object on which the event initially occurred (never {@code null})\n     */\n    public PhysicalTemplateModifyEvent(Object source, IndexTemplatePhy oldTemplate, IndexTemplatePhy newTemplate,\n                                       IndexTemplateWithPhyTemplates logicWithPhysical) {\n        super(source, logicWithPhysical);\n        this.oldTemplate = oldTemplate;\n        this.newTemplate = newTemplate;\n    }\n\n    public IndexTemplatePhy getOldTemplate() {\n        return oldTemplate;\n    }\n\n    public IndexTemplatePhy getNewTemplate() {\n        return newTemplate;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/TemplateCreateEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @author chengxiang\n * @date 2022/5/27\n */\npublic class TemplateCreateEvent extends ApplicationEvent {\n\n    private IndexTemplateDTO indexTemplateDTO;\n\n    public TemplateCreateEvent(Object source, IndexTemplateDTO indexTemplateDTO) {\n        super(source);\n        this.indexTemplateDTO = indexTemplateDTO;\n    }\n\n    public IndexTemplateDTO getIndexTemplateDTO() {\n        return indexTemplateDTO;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/TemplateEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template;\n\nimport org.springframework.context.ApplicationEvent;\n\n/**\n * @author d06679\n * @date 2019/4/18\n */\npublic abstract class TemplateEvent extends ApplicationEvent {\n\n    protected TemplateEvent(Object source) {\n        super(source);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/physical/metadata/PhysicalMetaDataModifyEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template.physical.metadata;\n\nimport com.didichuxing.datachannel.arius.admin.common.event.template.TemplateEvent;\n\n/**\n * 物理模板元数据变更事件基本类\n * @author wangshu\n * @date 2020/09/02\n */\npublic abstract class PhysicalMetaDataModifyEvent extends TemplateEvent {\n    protected PhysicalMetaDataModifyEvent(Object source) {\n        super(source);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/physical/metadata/PhysicalTemplateAliasModifyEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template.physical.metadata;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyAlias;\n\nimport java.util.List;\n\n/**\n * 物理模板别名更新事件\n * @author wangshu\n * @date 2020/09/02\n */\npublic class PhysicalTemplateAliasModifyEvent extends PhysicalMetaDataModifyEvent {\n\n    /**\n     * project ID\n     */\n    private final Integer               projectId;\n\n    /**\n     * 模板名称\n     */\n    private final String                templateName;\n\n    /**\n     * 集群名称\n     */\n    private final String                cluster;\n\n    /**\n     * 接受者列表\n     */\n    private final List<String>          receivers;\n\n    /**\n     * 更新之前索引模板别名信息\n     */\n    private final IndexTemplatePhyAlias beforeUpdateAlias;\n\n    /**\n     * 更新之后索引模板别名信息\n     */\n    private final IndexTemplatePhyAlias afterUpdateAlias;\n\n    public PhysicalTemplateAliasModifyEvent(Object source, Integer projectId, String cluster, String templateName,\n                                            List<String> receivers, IndexTemplatePhyAlias beforeUpdateAlias,\n                                            IndexTemplatePhyAlias afterUpdateAlias) {\n        super(source);\n        this.projectId = projectId;\n        this.templateName = templateName;\n        this.cluster = cluster;\n        this.receivers = receivers;\n        this.beforeUpdateAlias = beforeUpdateAlias;\n        this.afterUpdateAlias = afterUpdateAlias;\n    }\n\n    public Integer getProjectId() {\n        return projectId;\n    }\n\n    public String getTemplateName() {\n        return templateName;\n    }\n\n    public String getCluster() {\n        return this.cluster;\n    }\n\n    public List<String> getReceivers() {\n        return this.receivers;\n    }\n\n    public IndexTemplatePhyAlias getBeforeUpdateAlias() {\n        return this.beforeUpdateAlias;\n    }\n\n    public IndexTemplatePhyAlias getAfterUpdateAlias() {\n        return this.afterUpdateAlias;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/physical/metadata/PhysicalTemplatePropertiesTypesModifyEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template.physical.metadata;\n\nimport java.util.List;\n\n/**\n * 物理模板type变更事件\n * @author wangshu\n * @date 2020/09/02\n */\npublic class PhysicalTemplatePropertiesTypesModifyEvent extends PhysicalMetaDataModifyEvent {\n\n    /**\n     * project ID\n     */\n    private final Integer      projectId;\n\n    /**\n     * 集群\n     */\n    private final String       cluster;\n\n    /**\n     * 模板名称\n     */\n    private final String       templateName;\n\n    /**\n     * 接受者列表\n     */\n    private final List<String> receivers;\n\n    /**\n     * 更新前物理模板properties types\n     */\n    private final List<String> beforeUpdateTypes;\n\n    /**\n     * 更新后物理模板properties types\n     */\n    private final List<String> afterUpdateTypes;\n\n    public PhysicalTemplatePropertiesTypesModifyEvent(Object source, Integer projectId, String cluster,\n                                                      String templateName, List<String> receivers,\n                                                      List<String> beforeUpdateTypes, List<String> afterUpdateTypes) {\n        super(source);\n        this.projectId = projectId;\n        this.cluster = cluster;\n        this.templateName = templateName;\n        this.receivers = receivers;\n        this.beforeUpdateTypes = beforeUpdateTypes;\n        this.afterUpdateTypes = afterUpdateTypes;\n    }\n\n    public Integer getProjectId() {\n        return this.projectId;\n    }\n\n    public String getCluster() {\n        return this.cluster;\n    }\n\n    public String getTemplateName() {\n        return this.templateName;\n    }\n\n    public List<String> getReceivers() {\n        return this.receivers;\n    }\n\n    public List<String> getBeforeUpdateTypes() {\n        return this.beforeUpdateTypes;\n    }\n\n    public List<String> getAfterUpdateTypes() {\n        return this.afterUpdateTypes;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/event/template/physical/metadata/PhysicalTemplateSettingsModifyEvent.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.event.template.physical.metadata;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhySetting;\n\nimport java.util.List;\n\n/**\n * 物理模板settings更新事件\n * @author wangshu\n * @date 2020/09/02\n */\npublic class PhysicalTemplateSettingsModifyEvent extends PhysicalMetaDataModifyEvent {\n    private final Integer                 projectId;\n    private final String                  cluster;\n    private final String                  templateName;\n    private final List<String>            receivers;\n    private final IndexTemplatePhySetting beforeUpdateSettings;\n    private final IndexTemplatePhySetting afterUpdateSettings;\n\n    public PhysicalTemplateSettingsModifyEvent(Object source, Integer projectId, String cluster, String templateName,\n                                               List<String> receivers, IndexTemplatePhySetting beforeUpdateSettings,\n                                               IndexTemplatePhySetting afterUpdateSettings) {\n        super(source);\n        this.projectId = projectId;\n        this.cluster = cluster;\n        this.templateName = templateName;\n        this.receivers = receivers;\n        this.beforeUpdateSettings = beforeUpdateSettings;\n        this.afterUpdateSettings = afterUpdateSettings;\n    }\n\n    public Integer getProjectId() {\n        return this.projectId;\n    }\n\n    public String getCluster() {\n        return this.cluster;\n    }\n\n    public String getTemplateName() {\n        return this.templateName;\n    }\n\n    public List<String> getReceivers() {\n        return this.receivers;\n    }\n\n    public IndexTemplatePhySetting getBeforeUpdateSettings() {\n        return this.beforeUpdateSettings;\n    }\n\n    public IndexTemplatePhySetting getAfterUpdateSettings() {\n        return this.afterUpdateSettings;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/AdminOperateException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/2/21\n */\npublic class AdminOperateException extends BaseException {\n\n    public AdminOperateException(String message) {\n        super(message, ResultType.ADMIN_OPERATE_ERROR);\n    }\n\n    public AdminOperateException(String message, Throwable cause) {\n        super(message, cause, ResultType.ADMIN_OPERATE_ERROR);\n    }\n\n    public AdminOperateException(String message, ResultType resultType) {\n        super(message, resultType);\n    }\n\n    public AdminOperateException(String message, Throwable cause, ResultType resultType) {\n        super(message, cause, resultType);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/AdminTaskException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/2/21\n */\npublic class AdminTaskException extends AdminOperateException {\n\n    public AdminTaskException(String message) {\n        super(message, ResultType.ADMIN_TASK_ERROR);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/AmsRemoteException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n * @author d06679\n * @date 2019/3/18\n */\npublic class AmsRemoteException extends ThirdPartRemoteException {\n\n    public AmsRemoteException(String message) {\n        super(message, ResultType.AMS_SERVER_ERROR);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/AriusGatewayException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n * Arius gateway 异常\n *\n * @author d06679\n * @date 2019/3/13\n */\npublic class AriusGatewayException extends AdminOperateException {\n\n    public AriusGatewayException(String message) {\n        super(message, ResultType.ARIUS_GATEWAY_ERROR);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/BaseException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n * 平台错误基类\n *\n * @author d06679\n * @date 2019/3/13\n */\npublic class BaseException extends Exception {\n\n    private ResultType resultType;\n\n    public BaseException(String message, Throwable cause, ResultType resultType) {\n        super(message, cause);\n        this.resultType = resultType;\n    }\n\n    public BaseException(String message, ResultType resultType) {\n        super(message);\n        this.resultType = resultType;\n    }\n\n    public ResultType getResultType() {\n        return resultType;\n    }\n\n    public void setResultType(ResultType resultType) {\n        this.resultType = resultType;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/ESOperateException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/2/21\n */\npublic class ESOperateException extends AdminOperateException {\n\n    public ESOperateException(String message, Throwable cause) {\n        super(message, cause, ResultType.ES_OPERATE_ERROR);\n    }\n\n    public ESOperateException(String message) {\n        super(message, ResultType.ES_OPERATE_ERROR);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/EcmRemoteException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n * @author d06679\n * @date 2019/3/18\n */\npublic class EcmRemoteException extends ThirdPartRemoteException {\n\n    public EcmRemoteException(String message) {\n        super(message, ResultType.ECM_SERVER_ERROR);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/EventException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\npublic class EventException extends BaseException{\n\n    public EventException(String message) {\n        super(message, ResultType.EVENT_ERROR);\n    }\n\n    public EventException(String message, Throwable cause) {\n        super(message, cause, ResultType.EVENT_ERROR);\n    }\n\n    public EventException(String message, ResultType resultType) {\n        super(message, resultType);\n    }\n\n    public EventException(String message, Throwable cause, ResultType resultType) {\n        super(message, cause, resultType);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/ExtendServiceNotSupportException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/2/21\n */\npublic class ExtendServiceNotSupportException extends AdminOperateException {\n\n    public ExtendServiceNotSupportException(String message) {\n        super(message, ResultType.EXTEND_SERVICE_ERROR);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/NotFindSubclassException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n * @author linyunan\n * @date 2021-04-25\n */\npublic class NotFindSubclassException extends AdminOperateException {\n\n    public NotFindSubclassException(String message) {\n        super(message, ResultType.NO_FIND_SUB_CLASS);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/NullESClientException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n * > 该类用于在 Elasticsearch 客户端为空时抛出异常\n *\n * @author shizeying\n * @date 2022/08/26\n */\npublic class NullESClientException extends ESOperateException {\n    private final ResultType resultType;\n    \n    \n    public NullESClientException(String cluster) {\n        super( ResultType.ES_CLIENT_NUL_ERROR.getCode()+\"-\"+String.format(ResultType.ES_CLIENT_NUL_ERROR.getMessage(),cluster));\n        this.resultType = ResultType.ES_CLIENT_NUL_ERROR;\n        \n    }\n    \n    public NullESClientException(String message,ResultType resultType) {\n        super(message);\n        this.resultType = resultType;\n        \n    }\n    @Override\n    public ResultType getResultType() {\n        return resultType;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/OperateForbiddenException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/2/21\n */\npublic class OperateForbiddenException extends AdminOperateException {\n\n    public OperateForbiddenException(String message) {\n        super(message, ResultType.OPERATE_FORBIDDEN_ERROR);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/ThirdPartRemoteException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n * @author d06679\n * @date 2019/3/18\n */\npublic class ThirdPartRemoteException extends AdminOperateException {\n\n    public ThirdPartRemoteException(String message, Throwable cause, ResultType resultType) {\n        super(message, cause, resultType);\n    }\n\n    public ThirdPartRemoteException(String message, ResultType resultType) {\n        super(message, resultType);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/WorkOrderNotSupportException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/2/21\n */\npublic class WorkOrderNotSupportException extends AdminOperateException {\n\n    public WorkOrderNotSupportException(String message) {\n        super(message, ResultType.WORK_ORDER_NOT_SUPPORT_ERROR);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/exception/WorkOrderOperateException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.exception;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/2/21\n */\npublic class WorkOrderOperateException extends AdminOperateException {\n\n    /**\n     * Constructs a new exception with the specified detail message.  The\n     * cause is not initialized, and may subsequently be initialized by\n     * a call to {@link #initCause}.\n     *\n     * @param message the detail message. The detail message is saved for\n     *                later retrieval by the {@link #getMessage()} method.\n     */\n    public WorkOrderOperateException(String message) {\n        super(message);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/function/BiFunctionWithESOperateException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.function;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport java.util.Objects;\nimport java.util.function.Function;\n\n/**\n * 可丢弃双函数\n *\n * @author shizeying\n * @date 2022/08/17\n */\n@FunctionalInterface\npublic interface BiFunctionWithESOperateException<T, U, R> {\n\t\n\t/**\n\t * 它接受两个参数并返回一个值。\n\t *\n\t * @param t 函数的第一个参数。\n\t * @param u 函数的第一个参数。\n\t * @return 一个接受两个参数并返回一个值的函数。\n\t */\n\tR apply(T t, U u) throws ESOperateException;\n\t\n\n\t/**\n\t * > 返回一个组合函数，该函数首先将此函数应用于其输入，然后将 after 函数应用于结果\n\t *\n\t * @param after 应用此功能后要应用的功能\n\t * @return 一个接受两个参数并返回结果的函数。\n\t */\n\tdefault <V> BiFunctionWithESOperateException<T, U, V> andThen(Function<? super R, ? extends V> after) throws ESOperateException {\n\t\tObjects.requireNonNull(after);\n\t\treturn (T t, U u) -> after.apply(apply(t, u));\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/function/FunctionWithESOperateException.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.function;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport java.util.Objects;\n\n/**\n * 带有esoperate异常函数\n *\n * @author shizeying\n * @date 2022/09/08\n */\n@FunctionalInterface\npublic interface FunctionWithESOperateException<T, R> {\n\tR apply(T t) throws ESOperateException;\n\t\n\tdefault <V> FunctionWithESOperateException<V, R> compose(\n\t\t\tFunctionWithESOperateException<? super V, ? extends T> before) throws ESOperateException {\n\t\tObjects.requireNonNull(before);\n\t\treturn (V v) -> apply(before.apply(v));\n\t}\n\t\n\tdefault <V> FunctionWithESOperateException<T, V> andThen(\n\t\t\tFunctionWithESOperateException<? super R, ? extends V> after) throws ESOperateException {\n\t\tObjects.requireNonNull(after);\n\t\treturn (T t) -> after.apply(apply(t));\n\t}\n\t\n\tstatic <T> FunctionWithESOperateException<T, T> identity() throws ESOperateException {\n\t\treturn t -> t;\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/mapping/AnalyzerEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.mapping;\n\n/**\n * 搜索类型枚举\n *\n * @author d06679\n * @date 2017/7/14\n */\npublic enum AnalyzerEnum {\n                          /**标准分词器*/\n                          DEFAULT(1, \"标准分词器\"),\n\n                          IK(2, \"ik分词器\"),\n\n                          UNKNOWN(-1, \"unknown\");\n\n    AnalyzerEnum(Integer code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private Integer code;\n\n    private String  desc;\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static AnalyzerEnum valueFrom(Integer code) {\n        if (code == null) {\n            return AnalyzerEnum.UNKNOWN;\n        }\n        for (AnalyzerEnum state : AnalyzerEnum.values()) {\n            if (state.getCode().equals(code)) {\n                return state;\n            }\n        }\n\n        return AnalyzerEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/mapping/AriusIndexTemplateSetting.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.mapping;\n\nimport java.io.Serializable;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONException;\nimport com.alibaba.fastjson.JSONObject;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\nimport org.apache.commons.lang3.StringUtils;\n\n@Data\n@ApiModel(description = \"索引模板分词器setting信息\")\n//todo: 重构\npublic class AriusIndexTemplateSetting implements Serializable {\n\n    @ApiModelProperty(\"分词器\")\n    private JSONObject                analysis;\n    /**\n     * 副本数量\n     * index.number_of_replicas:0\n     * {\"index\": {\"number_of_replicas\": 0}\n     */\n    private Integer                   replicasNum;\n    /**\n     * 变更translog设置\n     * index.translog.durability:\"request\"\n     * \"async\"|\"request\"\n     */\n    private String                    translogDurability;\n\n    public static String              NUMBER_OF_REPLICAS_KEY  = \"index.number_of_replicas\";\n    public static String              TRANSLOG_DURABILITY_KEY = \"index.translog.durability\";\n\n    public final static String        REQUEST                 = \"request\";\n    public final static String        ASYNC                   = \"async\";\n\n    private static final String       ANALYSIS_KEY_PREFIX     = \"index.analysis.\";\n\n    private static final String       ANALYZER_KEY            = \"analyzer\";\n    private static final String       TOKENIZER_KEY           = \"tokenizer\";\n    private static final String       CHAR_FILTER_KEY         = \"char_filter\";\n    private static final String       FILTER_KEY              = \"filter\";\n\n    private static final List<String> ANALYSIS_SUPPORTED_KEYS = Arrays.asList(ANALYZER_KEY, TOKENIZER_KEY,\n        CHAR_FILTER_KEY, FILTER_KEY);\n\n    /**\n     * to formatted json.\n     * @return\n     */\n    public Map<String, String> toJSON() {\n        Map<String, String> ret = new HashMap<>();\n        if (analysis != null) {\n            Map<String, String> analysisDict = flat(analysis);\n\n            for (Map.Entry<String, String> entry : analysisDict.entrySet()) {\n                String analysisKey = entry.getKey();\n                ret.put(ANALYSIS_KEY_PREFIX + analysisKey, entry.getValue());\n            }\n        }\n        if (replicasNum != null && replicasNum >= 0) {\n            ret.put(NUMBER_OF_REPLICAS_KEY, String.valueOf(replicasNum));\n        }\n        if (StringUtils.isNotBlank(translogDurability)\n            && (REQUEST.equals(translogDurability) || ASYNC.equals(translogDurability))) {\n            ret.put(TRANSLOG_DURABILITY_KEY, translogDurability);\n        }\n        return ret;\n    }\n\n    public static Map<String, String> flat(JSONObject obj) {\n        Map<String, String> ret = new HashMap<>();\n\n        if (obj == null) {\n            return ret;\n        }\n\n        for (Map.Entry<String, Object> entry : obj.entrySet()) {\n            String key = entry.getKey();\n            Object o = obj.get(key);\n\n            JSONObject json = parseJsonObject(o);\n            if (json != null) {\n                Map<String, String> m = flat(json);\n\n                for (Map.Entry<String, String> fEntry : m.entrySet()) {\n                    String k = fEntry.getKey();\n                    ret.put(key.replace(\".\", \"#\") + \".\" + k, m.get(k));\n                }\n            } else {\n                ret.put(key.replace(\".\", \"#\"), o.toString());\n            }\n        }\n\n        return ret;\n    }\n\n    /**\n     * 尝试获取JSON Object\n     * @param o 对象\n     * @return\n     */\n    private static JSONObject parseJsonObject(Object o) {\n        if (o instanceof JSONObject) {\n            return (JSONObject) o;\n        } else {\n            try {\n                return JSON.parseObject(JSON.toJSONString(o));\n            } catch (JSONException e) {\n                return null;\n            }\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/mapping/AriusTypeProperty.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.mapping;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.DEFAULT_INDEX_MAPPING_TYPE;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.util.Objects;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n *\n *\n * {\n *   \"type_name\": {\n *     \"properties\": {\n *       \"key1\": {\n *         \"type\": \"integer\"\n *       },\n *       \"key2\": {\n *         \"type\": \"long\"\n *       }\n *     }\n *   }\n * }\n *\n * @author d06679\n * @date 2019-08-27\n * @see 0.3.2下线\n */\n@Data\n@ApiModel(description = \"索引type信息\")\n@NoArgsConstructor\n@Deprecated()\npublic class AriusTypeProperty {\n\n    /**\n     * type_name\n     */\n    @ApiModelProperty(\"名称\")\n    private String             typeName              = DEFAULT_INDEX_MAPPING_TYPE;\n\n    /**\n     * id字段\n     */\n    @ApiModelProperty(\"主键字段\")\n    private String             idField;\n\n    /**\n     * routing字段\n     */\n    @ApiModelProperty(\"routing字段\")\n    private String             routingField;\n\n    /**\n     * 时间字段\n     */\n    @ApiModelProperty(\"时间字段\")\n    private String             dateField;\n\n    /**\n     * 时间字段的格式\n     */\n    @ApiModelProperty(\"时间字段格式\")\n    private String             dateFieldFormat;\n\n    /**\n     *      {\n     *       \"key1\": {\n     *         \"type\": \"integer\"\n     *       },\n     *       \"key2\": {\n     *         \"type\": \"long\"\n     *       }\n     *     }\n     */\n    @ApiModelProperty(\"属性（json格式）\")\n    @JSONField(name = \"properties\")\n    private JSONObject         properties;\n\n    /**\n     * [{\"key1\":{}},{\"key2\":{}}]\n     */\n    @ApiModelProperty(\"dynamic_templates（jsonArray格式）\")\n    @JsonProperty(\"dynamic_templates\")\n    private JSONArray          dynamicTemplates;\n\n    public static final String PROPERTIES_STR        = \"properties\";\n    public static final String DYNAMIC_TEMPLATES_STR = \"dynamic_templates\";\n\n    public JSONObject toMappingJSON() {\n        JSONObject obj = new JSONObject();\n        obj.put(PROPERTIES_STR, properties);\n\n        if (null != dynamicTemplates && !dynamicTemplates.isEmpty()) {\n            obj.put(DYNAMIC_TEMPLATES_STR, dynamicTemplates);\n        }\n\n        JSONObject root = new JSONObject();\n        root.put(typeName, obj);\n\n        return root;\n    }\n    /**\n     * 它接受一个 AriusTypeProperty 对象，检查它是否有 properties 字段，如果有，它检查该 properties 字段是否有 properties 字段和 dynamicTemplates 字段。如果是，则将\n     * AriusTypeProperty 对象的 properties 字段设置为 properties 字段的 properties 字段，并将 AriusTypeProperty 对象的 dynamicTemplates 字段设置为\n     * properties 字段的 dynamicTemplates 字段\n     *\n     * @param ariusTypeProperty 包含属性和动态模板的对象。\n     */\n    public static AriusTypeProperty buildPropertiesAndDynamicTemplates(AriusTypeProperty ariusTypeProperty) {\n        final JSONObject properties = ariusTypeProperty.getProperties();\n    \n        if (Objects.nonNull(properties) && properties.containsKey(PROPERTIES_STR)) {\n            if (properties.containsKey(PROPERTIES_STR)) {\n                ariusTypeProperty.setProperties(properties.getJSONObject(PROPERTIES_STR));\n            }\n            if (properties.containsKey(DYNAMIC_TEMPLATES_STR)) {\n                ariusTypeProperty.setDynamicTemplates(properties.getJSONArray(DYNAMIC_TEMPLATES_STR));\n            }\n            \n        }\n        return ariusTypeProperty;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/mapping/Field.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.mapping;\n\nimport io.swagger.annotations.ApiModel;\nimport io.swagger.annotations.ApiModelProperty;\nimport lombok.Data;\n\n/**\n * @author d06679\n * @date 2019-06-04\n */\n@Data\n@ApiModel(description = \"索引mapping字段信息\")\npublic class Field {\n\n    @ApiModelProperty(\"字段名称\")\n    private String  name;\n\n    @ApiModelProperty(\"字段类型\")\n    private String  type;\n\n    @ApiModelProperty(\"索引类型（1:关闭分词，关闭倒排索引；2:关闭分词，开启倒排索引；3:开启分词，开启倒排索引）\")\n    private Integer indexType;\n\n    @ApiModelProperty(\"分词类型（1:标准分词；2:ik分词）\")\n    private Integer analyzerType;\n\n    @ApiModelProperty(\"排序类型（0:不排序；1:排序）\")\n    private Integer sortType;\n\n    @ApiModelProperty(\"是否是分区字段\")\n    private Boolean dateField;\n\n    @ApiModelProperty(\"分区字段格式\")\n    private String  dateFieldFormat;\n\n    @ApiModelProperty(\"是否是主键子弹\")\n    private Boolean idField;\n\n    @ApiModelProperty(\"是否是routing字段\")\n    private Boolean routingField;\n\n    public boolean esTypeEquals(Object o) {\n        if (o == null || !(o instanceof Field)) {\n            return false;\n        }\n\n        Field field = (Field) o;\n\n        if (!isEqual(type, field.type)) {\n            return false;\n        }\n\n        if (!isEqual(indexType, field.indexType)) {\n            return false;\n        }\n\n        if (!isEqual(analyzerType, field.analyzerType)) {\n            return false;\n        }\n\n        if (!isEqual(sortType, field.sortType)) {\n            return false;\n        }\n\n        return true;\n    }\n\n    private boolean isEqual(Object o1, Object o2) {\n        if (o1 == null) {\n            if (o2 == null) {\n                return true;\n            } else {\n                return false;\n            }\n        }\n\n        return o1.equals(o2);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/mapping/IndexEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.mapping;\n\n/**\n * 搜索类型枚举\n *\n * @author d06679\n * @date 2017/7/14\n */\npublic enum IndexEnum {\n                       /**关闭分词，关闭倒排索引*/\n                       FORBID(1, \"forbid\"),\n\n                       /**关闭分词，开启倒排索引*/\n                       EXACT(2, \"exact\"),\n\n                       /**开启分词，开启倒排索引*/\n                       FUZZY(3, \"fuzzy\"),\n\n                       UNKNOWN(-1, \"unknown\");\n\n    IndexEnum(Integer code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private Integer code;\n\n    private String  desc;\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static IndexEnum valueFrom(Integer code) {\n        if (code == null) {\n            return IndexEnum.UNKNOWN;\n        }\n        for (IndexEnum state : IndexEnum.values()) {\n            if (state.getCode().equals(code)) {\n                return state;\n            }\n        }\n\n        return IndexEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/mapping/SortEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.mapping;\n\n/**\n * 排序类型枚举\n *\n * @author d06679\n * @date 2017/7/14\n */\npublic enum SortEnum {\n                      /**开始doc value*/\n                      YES(1, \"是\"),\n\n                      NO(0, \"否\"),\n\n                      UNKNOWN(-1, \"unknown\");\n\n    SortEnum(Integer code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private Integer code;\n\n    private String  desc;\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static SortEnum valueFrom(Integer code) {\n        if (code == null) {\n            return SortEnum.UNKNOWN;\n        }\n        for (SortEnum state : SortEnum.values()) {\n            if (state.getCode().equals(code)) {\n                return state;\n            }\n        }\n\n        return SortEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/mapping/SpecialField.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.mapping;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport lombok.Data;\n\n/**\n * @author d06679\n * @date 2019-06-04\n */\n@Data\npublic class SpecialField {\n\n    private String dateField;\n\n    /**\n     * 时间字段的格式\n     */\n    private String dateFieldFormat;\n\n    private String idField;\n\n    private String routingField;\n\n    public static SpecialField analyzeFromFields(Collection<Field> fields) {\n        SpecialField specialField = new SpecialField();\n        for (Field field : fields) {\n            if (field.getDateField() != null && field.getDateField()) {\n                specialField.setDateField(field.getName());\n                specialField.setDateFieldFormat(field.getDateFieldFormat());\n                break;\n            }\n        }\n\n        List<String> idFields = fields.stream().filter(field -> field.getIdField() != null && field.getIdField())\n            .map(Field::getName).collect(Collectors.toList());\n        specialField.setIdField(String.join(\",\", idFields));\n\n        List<String> routingFields = fields.stream()\n            .filter(field -> field.getRoutingField() != null && field.getRoutingField()).map(Field::getName)\n            .collect(Collectors.toList());\n        specialField.setRoutingField(String.join(\",\", routingFields));\n\n        return specialField;\n    }\n\n    public static SpecialField analyzeFromFields(Collection<Field> fields, Set<String> removeFieldNameSet) {\n\n        if (removeFieldNameSet == null) {\n            return analyzeFromFields(fields);\n        }\n\n        SpecialField specialField = new SpecialField();\n        for (Field field : fields) {\n            if (field.getDateField() != null && field.getDateField() && !removeFieldNameSet.contains(field.getName())) {\n                specialField.setDateField(field.getName());\n                specialField.setDateFieldFormat(field.getDateFieldFormat());\n                break;\n            }\n        }\n\n        List<String> idFields = fields.stream().filter(\n            field -> field.getIdField() != null && field.getIdField() && !removeFieldNameSet.contains(field.getName()))\n            .map(Field::getName).collect(Collectors.toList());\n        specialField.setIdField(String.join(\",\", idFields));\n\n        List<String> routingFields = fields.stream()\n            .filter(field -> field.getRoutingField() != null && field.getRoutingField()\n                             && !removeFieldNameSet.contains(field.getName()))\n            .map(Field::getName).collect(Collectors.toList());\n        specialField.setRoutingField(String.join(\",\", routingFields));\n\n        return specialField;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/mapping/TypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.mapping;\n\n/**\n * 字段类型枚举\n *\n * @author d06679\n * @date 2017/7/14\n */\npublic enum TypeEnum {\n                      // 数字类型\n                      INT(\"integer\",\n                          \"integer\"), LONG(\"long\",\n                                           \"long\"), DOUBLE(\"double\",\n                                                           \"double\"), SHORT(\"short\",\n                                                                            \"short\"), BYTE(\"byte\",\n                                                                                           \"byte\"), FLOAT(\"float\",\n                                                                                                          \"float\"), HALF_FLOAT(\"half_float\",\n                                                                                                                               \"half_float\"), SCALED_FLOAT(\"scaled_float\",\n                                                                                                                                                           \"scaled_float\"), NUMERIC(\"numeric\",\n                                                                                                                                                                                    \"numeric\"),\n\n                      // 布尔类型\n                      BOOLEAN(\"boolean\", \"boolean\"),\n\n                      KEYWORD(\"keyword\", \"keyword\"),\n\n                      STRING(\"string\", \"string\"),\n\n                      // 日期类型\n                      DATE(\"date\", \"date\"), DATE_NANOS(\"date_nanos\", \"date_nanos\"),\n\n                      ARRAY(\"array\", \"array\"),\n\n                      // Object类型\n                      OBJECT(\"object\", \"object\"), FLATTENED(\"flattened\", \"flattened\"), NESTED(\"nested\", \"nested\"),\n\n                      BINARY(\"binary\", \"binary\"),\n\n                      // 空间数据类型\n                      GEO_POINT(\"geo-point\", \"geo-point\"), GEO_SHAPE(\"geo-shape\", \"geo-shape\"), SHARPE(\"sharpe\",\n                                                                                                       \"sharpe\"),\n\n                      // 结构化数据类型\n                      IP(\"ip\", \"ip\"), RANGE(\"range\", \"range\"),\n\n                      // Text检索类型\n                      TEXT(\"text\", \"text\"),\n\n                      UNKNOWN(\"unknown\", \"unknown\");\n\n    TypeEnum(String code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n\n    private String code;\n\n    private String desc;\n\n    public String getCode() {\n        return code;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public static TypeEnum valueFrom(String code) {\n        if (code == null) {\n            return TypeEnum.UNKNOWN;\n        }\n        for (TypeEnum state : TypeEnum.values()) {\n            if (state.getCode().equals(code)) {\n                return state;\n            }\n        }\n\n        return TypeEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/threadpool/AriusOpThreadPool.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.threadpool;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.observability.Observability;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.scheduling.concurrent.CustomizableThreadFactory;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.List;\nimport java.util.concurrent.*;\n\n/**\n * 异步操作线程池\n */\n@Component\n@NoArgsConstructor\npublic class AriusOpThreadPool implements Executor {\n\n    private static final String THREAD_FACTORY_NAME = \"OP-POOL\";\n\n    private static final ILog   LOG                 = LogFactory.getLog(AriusOpThreadPool.class);\n\n    @Value(\"${admin.thread.size.op:20}\")\n    public int                  poolSize;\n\n    private ExecutorService     pool;\n\n    private ThreadFactory       springThreadFactory = new CustomizableThreadFactory(\"AriusOpThreadPool\");\n\n    @PostConstruct\n    public void init() {\n        LOG.info(\"class=AriusOpThreadPool||method=init||AriusOpThreadPool init start..\");\n        pool = Observability.wrap(new ThreadPoolExecutor(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS,\n                new LinkedBlockingQueue<Runnable>(), springThreadFactory));\n        Runtime.getRuntime().addShutdownHook(new Thread() {\n\n            @Override\n            public void run() {\n                pool.shutdown();\n                try {\n                    if (!pool.awaitTermination(20, TimeUnit.SECONDS)) {\n                        LOG.warn(\n                            \"class=AriusOpThreadPool||method=init||errMsg=still some task running, force to shutdown!\");\n                        List<Runnable> shutDownList = pool.shutdownNow();\n                        shutDownList.forEach(\n                            e -> LOG.info(\"class=AriusOpThreadPool||method=init||msg=Runnable forced shutdown\"));\n                    }\n                } catch (InterruptedException e) {\n                    pool.shutdownNow();\n                    Thread.currentThread().interrupt();\n                }\n                LOG.info(\"class=AriusOpThreadPool||method=init||{}shutdown finished\", THREAD_FACTORY_NAME);\n            }\n        });\n        LOG.info(\"class=AriusOpThreadPool||method=init||AriusOpThreadPool init finished.\");\n    }\n\n    public <T> T submit(Callable<T> caller) throws InterruptedException, ExecutionException {\n        Future<T> future = pool.submit(caller);\n        return future.get();\n    }\n\n    public int getPoolSize() {\n        return poolSize;\n    }\n\n    public void run(Runnable runner) {\n        pool.execute(runner);\n    }\n\n    @Override\n    public void execute(Runnable command) {\n        pool.execute(command);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/threadpool/AriusScheduleThreadPool.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.threadpool;\n\nimport com.didiglobal.knowframework.observability.Observability;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n@Component\npublic class AriusScheduleThreadPool {\n\n    private ScheduledExecutorService scheduleThreadPool;\n    private int                      scheduleThreadNum = 1 << 5;\n\n    @PostConstruct\n    public void init() {\n        scheduleThreadPool = Observability.wrap(new ScheduledThreadPoolExecutor(scheduleThreadNum,\n                new DesmondThreadFactory(\"scheduleThreadPool\")));\n    }\n\n    public void submitScheduleAtFixedRateTask(Runnable runnable, long initialDelay, long period) {\n        scheduleThreadPool.scheduleAtFixedRate(runnable, initialDelay, period, TimeUnit.SECONDS);\n    }\n\n    public void submitScheduleAtFixedDelayTask(Runnable runnable, long initialDelay, long delay) {\n        scheduleThreadPool.scheduleWithFixedDelay(runnable, initialDelay, delay, TimeUnit.SECONDS);\n    }\n\n    static class DesmondThreadFactory implements ThreadFactory {\n        static final AtomicInteger poolNumber   = new AtomicInteger(1);\n        final AtomicInteger        threadNumber = new AtomicInteger(1);\n        final String               namePrefix;\n\n        DesmondThreadFactory(String prefix) {\n            namePrefix = prefix + \"-pool-\" + poolNumber.getAndIncrement() + \"-\";\n        }\n\n        @Override\n        public Thread newThread(Runnable r) {\n            Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());\n            if (!t.isDaemon()) {\n                t.setDaemon(true);\n            }\n\n            if (t.getPriority() != Thread.NORM_PRIORITY) {\n                t.setPriority(Thread.NORM_PRIORITY);\n            }\n            return t;\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/threadpool/AriusTaskThreadPool.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.threadpool;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.observability.Observability;\nimport com.didiglobal.knowframework.observability.conponent.thread.ContextExecutorService;\nimport lombok.NoArgsConstructor;\nimport org.springframework.scheduling.concurrent.CustomizableThreadFactory;\nimport org.springframework.util.ReflectionUtils;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.concurrent.*;\n\n/**\n * admin执行任务的线程池\n */\n@NoArgsConstructor\npublic class AriusTaskThreadPool {\n\n    private static final String THREAD_FACTORY_NAME = \"TASK-POOL\";\n\n    private static final ILog   LOGGER              = LogFactory.getLog(AriusTaskThreadPool.class);\n\n    private int                 poolSize;\n\n    private ExecutorService     pool;\n\n    private ThreadFactory       springThreadFactory = new CustomizableThreadFactory(\"AriusTaskThreadPool\");\n\n    public void init(int poolSize, String taskName, int queueLen) {\n        this.poolSize = poolSize;\n\n        LOGGER.warn(\"class=AriusTaskThreadPool||method=init||poolSize={}||taskName={}\", poolSize, taskName);\n\n        // 这里注意需要 LinkedBlockingQueue 的容量大小设置，默认为接近无限大,\n        // 随着worker数量积增，会导致内存压力持续上升，若部署在容器中, 服务会被容器主动kill掉\n        pool = Observability.wrap(new ThreadPoolExecutor(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS,\n                new LinkedBlockingQueue<>(queueLen), springThreadFactory));\n\n        Runtime.getRuntime().addShutdownHook(new Thread(() -> {\n            pool.shutdown();\n            try {\n                if (!pool.awaitTermination(20, TimeUnit.SECONDS)) {\n                    LOGGER.warn(\n                        \"class=AriusTaskThreadPool||method=init||msg=still some task running, force to shutdown!\");\n                    List<Runnable> shutDownList = pool.shutdownNow();\n                    shutDownList.forEach(e -> LOGGER\n                        .info(\"class=AriusTaskThreadPool||method=init||msg=Runnable forced shutdown||class={}\"));\n                }\n            } catch (InterruptedException e) {\n                pool.shutdownNow();\n                Thread.currentThread().interrupt();\n            }\n            LOGGER.info(\"class=AriusTaskThreadPool||method=init||msg={} shutdown finished\", THREAD_FACTORY_NAME);\n        }));\n\n        LOGGER.info(\"class=AriusTaskThreadPool||method=init||AriusTaskThreadPool init finished.\");\n    }\n\n    public void run(Runnable runner) {\n        pool.execute(runner);\n    }\n\n    public <T> T submit(Callable<T> caller) throws InterruptedException, ExecutionException {\n        Future<T> future = pool.submit(caller);\n        return future.get();\n    }\n\n    public int getPoolSize() {\n        return poolSize;\n    }\n\n    public int getCurrentQueueWorkerSize() {\n        return Optional.ofNullable(ReflectionUtils.findField(ContextExecutorService.class, \"delegate\")).map(field -> {\n            field.setAccessible(true);\n            return (ThreadPoolExecutor) ReflectionUtils.getField(field, pool);\n        }).map(ThreadPoolExecutor::getQueue).map(Collection::size).orElse(0);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/tuple/TupleOne.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.tuple;\n\nimport java.io.Serializable;\nimport java.util.Comparator;\nimport java.util.Objects;\nimport java.util.function.Function;\nimport lombok.AllArgsConstructor;\nimport lombok.ToString;\n\n/**\n * tuple1\n *\n * @author shizeying\n * @date 2022/06/20\n */\n@ToString\n@AllArgsConstructor\npublic class TupleOne<T1> implements Tuples, Comparable<TupleOne<T1>>, Serializable {\n    public final T1 V1;\n\n    /**\n     * 元组大小\n     *\n     * @return int\n     */\n    @Override\n    public int tupleSize() {\n        return 1;\n    }\n\n    public static <T1> Comparator<TupleOne<T1>> comparator(Comparator<? super T1> t1Comp) {\n        return (Comparator<TupleOne<T1>> & Serializable) (t1, t2) -> {\n            final int check1 = t1Comp.compare(t1.V1, t2.V1);\n            if (check1 != 0) {\n                return check1;\n            }\n            return 0;\n        };\n    }\n\n    private static <U1 extends Comparable<? super U1>> int compareTo(TupleOne<?> o1, TupleOne<?> o2) {\n\n        final TupleOne<U1> t1 = (TupleOne<U1>) o1;\n        final TupleOne<U1> t2 = (TupleOne<U1>) o2;\n\n        final int check1 = t1.V1.compareTo(t2.V1);\n        if (check1 != 0) {\n            return check1;\n        }\n\n        return 0;\n    }\n\n    @Override\n    public int compareTo(TupleOne<T1> that) {\n        return TupleOne.compareTo(this, that);\n    }\n\n    public T1 _1() {\n        return V1;\n    }\n\n    public TupleOne<T1> update1(T1 value) {\n        return new TupleOne<>(value);\n    }\n\n    public <U1> TupleOne<U1> map(Function<? super T1, ? extends U1> mapper) {\n        Objects.requireNonNull(mapper, \"mapper is null\");\n        return Tuples.of(mapper.apply(V1));\n    }\n\n    public <U> U apply(Function<? super T1, ? extends U> f) {\n        Objects.requireNonNull(f, \"function is null\");\n        return f.apply(V1);\n    }\n\n    public <T2> TupleTwo<T1, T2> append(T2 t2) {\n        return Tuples.of(V1, t2);\n    }\n\n    public <T2> TupleTwo<T1, T2> concat(TupleOne<T2> tuple) {\n        Objects.requireNonNull(tuple, \"tuple1 is null\");\n        return Tuples.of(V1, tuple.V1);\n    }\n\n    public <T2, T3> TupleThree<T1, T2, T3> concat(TupleTwo<T2, T3> tuple) {\n        Objects.requireNonNull(tuple, \"tuple2 is null\");\n        return Tuples.of(V1, tuple.v1, tuple.v2);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (o == this) {\n            return true;\n        } else if (o instanceof TupleOne) {\n            final TupleOne<?> that = (TupleOne<?>) o;\n            return Objects.equals(this.V1, that.V1);\n        }\n        return false;\n    }\n\n    /**\n     * @return\n     */\n    @Override\n    public int hashCode() {\n        return Tuples.hash(V1);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/tuple/TupleThree.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.tuple;\n\nimport java.io.Serializable;\nimport java.util.Comparator;\nimport java.util.Objects;\nimport java.util.function.Function;\nimport lombok.AllArgsConstructor;\nimport lombok.ToString;\n\n@AllArgsConstructor\n@ToString\npublic class TupleThree<T1, T2, T3> implements Tuples, Comparable<TupleThree<T1, T2, T3>>, Serializable {\n    private static final long serialVersionUID = 1L;\n\n    /**\n     * 第一个元素\n     */\n    public final T1           v1;\n\n    /**\n     * 第二个元素\n     */\n    public final T2           v2;\n\n    /**\n     * 第三个元素\n     */\n    public final T3           v3;\n\n    /**\n     * 比较器\n     *\n     * @param t1Comp t1 比较器\n     * @param t2Comp t2 比较器\n     * @param t3Comp t3 比较器\n     * @return {@code Comparator<Tuple3<T1, T2, T3>>}\n     */\n    public static <T1, T2, T3> Comparator<TupleThree<T1, T2, T3>> comparator(Comparator<? super T1> t1Comp,\n                                                                             Comparator<? super T2> t2Comp,\n                                                                             Comparator<? super T3> t3Comp) {\n        return (Comparator<TupleThree<T1, T2, T3>> & Serializable) (t1, t2) -> {\n            final int check1 = t1Comp.compare(t1.v1, t2.v1);\n            if (check1 != 0) {\n                return check1;\n            }\n\n            final int check2 = t2Comp.compare(t1.v2, t2.v2);\n            if (check2 != 0) {\n                return check2;\n            }\n\n            final int check3 = t3Comp.compare(t1.v3, t2.v3);\n            if (check3 != 0) {\n                return check3;\n            }\n\n            return 0;\n        };\n    }\n\n    /**\n     * 比较具体实现\n     *\n     * @param o1 tuple 3\n     * @param o2 o2\n     * @return int\n     */\n    private static <U1 extends Comparable<? super U1>, U2 extends Comparable<? super U2>, U3 extends Comparable<? super U3>> int compareTo(TupleThree<?, ?, ?> o1,\n                                                                                                                                           TupleThree<?, ?, ?> o2) {\n        final TupleThree<U1, U2, U3> t1 = (TupleThree<U1, U2, U3>) o1;\n        final TupleThree<U1, U2, U3> t2 = (TupleThree<U1, U2, U3>) o2;\n\n        final int check1 = t1.v1.compareTo(t2.v1);\n        if (check1 != 0) {\n            return check1;\n        }\n\n        final int check2 = t1.v2.compareTo(t2.v2);\n        if (check2 != 0) {\n            return check2;\n        }\n\n        final int check3 = t1.v3.compareTo(t2.v3);\n        if (check3 != 0) {\n            return check3;\n        }\n\n        return 0;\n    }\n\n    @Override\n    public int compareTo(TupleThree<T1, T2, T3> that) {\n        return TupleThree.compareTo(this, that);\n    }\n\n    public T1 _1() {\n        return v1;\n    }\n\n    public TupleThree<T1, T2, T3> update1(T1 value) {\n        return new TupleThree<>(value, v2, v3);\n    }\n\n    public T2 _2() {\n        return v2;\n    }\n\n    /**\n     * 更新第二个元素\n     *\n     * @param value value\n     * @return {@code Tuple3<T1, T2, T3>}\n     */\n    public TupleThree<T1, T2, T3> update2(T2 value) {\n        return new TupleThree<>(v1, value, v3);\n    }\n\n    public T3 _3() {\n        return v3;\n    }\n\n    /**\n     * 更人第三个元素\n     *\n     * @param value value\n     * @return {@code Tuple3<T1, T2, T3>}\n     */\n    public TupleThree<T1, T2, T3> update3(T3 value) {\n        return new TupleThree<>(v1, v2, value);\n    }\n\n    /**\n     * 地图\n     *\n     * @param f1 f1 _1 mapper 生成\n     * @param f2 f2 _2 mapper 生成\n     * @param f3 f3 _3 mapper 生成\n     * @return {@code Tuple3<U1, U2, U3>}\n     */\n    public <U1, U2, U3> TupleThree<U1, U2, U3> map(Function<? super T1, ? extends U1> f1,\n                                                   Function<? super T2, ? extends U2> f2,\n                                                   Function<? super T3, ? extends U3> f3) {\n        Objects.requireNonNull(f1, \"f1 is null\");\n        Objects.requireNonNull(f2, \"f2 is null\");\n        Objects.requireNonNull(f3, \"f3 is null\");\n        return Tuples.of(f1.apply(v1), f2.apply(v2), f3.apply(v3));\n    }\n\n    public <U> TupleThree<U, T2, T3> map1(Function<? super T1, ? extends U> mapper) {\n        Objects.requireNonNull(mapper, \"mapper is null\");\n        final U u = mapper.apply(v1);\n        return Tuples.of(u, v2, v3);\n    }\n\n    public <U> TupleThree<T1, U, T3> map2(Function<? super T2, ? extends U> mapper) {\n        Objects.requireNonNull(mapper, \"mapper is null\");\n        final U u = mapper.apply(v2);\n        return Tuples.of(v1, u, v3);\n    }\n\n    public <U> TupleThree<T1, T2, U> map3(Function<? super T3, ? extends U> mapper) {\n        Objects.requireNonNull(mapper, \"mapper is null\");\n        final U u = mapper.apply(v3);\n        return Tuples.of(v1, v2, u);\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (obj == this) {\n            return true;\n        } else if (obj instanceof TupleThree) {\n            final TupleThree<?, ?, ?> that = (TupleThree<?, ?, ?>) obj;\n            return Objects.equals(this.v1, that.v1) && Objects.equals(this.v2, that.v2)\n                   && Objects.equals(this.v3, that.v3);\n        }\n        return false;\n    }\n\n    /**\n     * @return\n     */\n    @Override\n    public int tupleSize() {\n        return 3;\n    }\n\n    @Override\n    public int hashCode() {\n        return Tuples.hash(v1, v2, v3);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/tuple/TupleTwo.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.tuple;\n\nimport java.io.Serializable;\nimport java.util.AbstractMap;\nimport java.util.Comparator;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.function.BiFunction;\nimport lombok.AllArgsConstructor;\nimport lombok.ToString;\n\n/**\n * tuple2 实现\n *\n * @author shizeying\n * @date 2022/06/20\n */\n@AllArgsConstructor\n@ToString\npublic class TupleTwo<T1, T2> implements Tuples, Comparable<TupleTwo<T1, T2>>, Serializable {\n    private static final long serialVersionUID = 1L;\n    public final T1           v1;\n    public final T2           v2;\n\n    public static <T1, T2> Comparator<TupleTwo<T1, T2>> comparator(Comparator<? super T1> t1Comp,\n                                                                   Comparator<? super T2> t2Comp) {\n        return (Comparator<TupleTwo<T1, T2>> & Serializable) (t1, t2) -> {\n            final int check1 = t1Comp.compare(t1.v1, t2.v1);\n            if (check1 != 0) {\n                return check1;\n            }\n\n            final int check2 = t2Comp.compare(t1.v2, t2.v2);\n            if (check2 != 0) {\n                return check2;\n            }\n\n            return 0;\n        };\n    }\n\n    private static <U1 extends Comparable<? super U1>, U2 extends Comparable<? super U2>> int compareTo(TupleTwo<?, ?> o1,\n                                                                                                        TupleTwo<?, ?> o2) {\n        final TupleTwo<U1, U2> t1 = (TupleTwo<U1, U2>) o1;\n        final TupleTwo<U1, U2> t2 = (TupleTwo<U1, U2>) o2;\n\n        final int check1 = t1.v1.compareTo(t2.v1);\n        if (check1 != 0) {\n            return check1;\n        }\n\n        final int check2 = t1.v2.compareTo(t2.v2);\n        if (check2 != 0) {\n            return check2;\n        }\n\n        return 0;\n    }\n\n    public T1 v1() {\n        return v1;\n    }\n\n    public T2 v2() {\n        return v2;\n    }\n\n    public TupleTwo<T1, T2> update2(T2 value) {\n        return new TupleTwo<>(v1, value);\n    }\n\n    public TupleTwo<T2, T1> swap() {\n        return Tuples.of(v2, v1);\n    }\n\n    public Map.Entry<T1, T2> toEntry() {\n        return new AbstractMap.SimpleEntry<>(v1, v2);\n    }\n\n    /**\n     * 传入bi func 转换为tuple\n     * <blockquote><pre>\n     *   final Tuple2<Integer, Integer> tuple2 = Tuple.of(1, 2);\n     *         BiFunction<Integer,Integer,Tuple2<Integer,Integer>> biFunction=(a,b)->Tuple.of(a+1,b+1 );\n     *         result : tuple_2=3\n     * </pre></blockquote>\n     *\n     * @param mapper 映射器\n     * @return {@code Tuple2<U1, U2>}\n     */\n    public <U1, U2> TupleTwo<U1, U2> map(BiFunction<? super T1, ? super T2, TupleTwo<U1, U2>> mapper) {\n        Objects.requireNonNull(mapper, \"mapper is null\");\n        return mapper.apply(v1, v2);\n    }\n\n    /**\n     * @param obj\n     * @return\n     */\n    @Override\n    public boolean equals(Object obj) {\n        if (obj == this) {\n            return true;\n        } else if (obj instanceof TupleTwo) {\n            final TupleTwo<?, ?> that = (TupleTwo<?, ?>) obj;\n            return Objects.equals(this.v1, that.v1) && Objects.equals(this.v2, that.v2);\n        }\n        return false;\n    }\n\n    @Override\n    public int hashCode() {\n        return Tuples.hash(v1, v2);\n    }\n\n    /**\n     * @return\n     */\n    @Override\n    public int tupleSize() {\n        return 2;\n    }\n\n    /**\n     * @param that the object to be compared.\n     * @return\n     */\n    @Override\n    public int compareTo(TupleTwo<T1, T2> that) {\n        Objects.requireNonNull(that, \"that is not  null\");\n        return TupleTwo.compareTo(this, that);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/tuple/Tuples.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.tuple;\n\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * 元组\n *\n * @author shizeying\n * @date 2022/06/20\n */\npublic interface Tuples {\n    /**\n     * max 最大设置\n     */\n    int MAX_ARITY = 3;\n\n    /**\n     * 元组大小\n     *\n     * @return int\n     */\n    int tupleSize();\n\n    static <T1, T2> TupleTwo<T1, T2> fromEntry(Map.Entry<? extends T1, ? extends T2> entry) {\n        Objects.requireNonNull(entry, \"entry is null\");\n        return new TupleTwo<>(entry.getKey(), entry.getValue());\n    }\n\n    /**\n     * @param t1 t1\n     * @return {@code Tuple1<T1>}\n     */\n    static <T1> TupleOne<T1> of(T1 t1) {\n        return new TupleOne<>(t1);\n    }\n\n    /**\n     * @param t1 t1\n     * @param t2 t2\n     * @return {@code Tuple2<T1, T2>}\n     */\n    static <T1, T2> TupleTwo<T1, T2> of(T1 t1, T2 t2) {\n        return new TupleTwo<>(t1, t2);\n    }\n\n    /**\n     * @param t1 t1\n     * @param t2 t2\n     * @param t3 t3\n     * @return {@code Tuple3<T1, T2, T3>}\n     */\n    static <T1, T2, T3> TupleThree<T1, T2, T3> of(T1 t1, T2 t2, T3 t3) {\n        return new TupleThree<>(t1, t2, t3);\n    }\n\n    static int hash(Object o1) {\n        return Objects.hashCode(o1);\n    }\n\n    static int hash(Object o1, Object o2) {\n        int result = 1;\n        result = 31 * result + hash(o1);\n        result = 31 * result + hash(o2);\n        return result;\n    }\n\n    static int hash(Object o1, Object o2, Object o3) {\n        int result = 1;\n        result = 31 * result + hash(o1);\n        result = 31 * result + hash(o2);\n        result = 31 * result + hash(o3);\n        return result;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/AriusDateUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.commons.lang3.time.DateUtils;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Calendar;\nimport java.util.Date;\n\n/**\n * @author d06679\n * @date 2017/7/26\n */\npublic class AriusDateUtils {\n\n    private static final String FORMAT = \"yyyy-MM-dd HH:mm:ss\";\n\n    private AriusDateUtils() {\n    }\n\n    public static Long date2Long(Date time, String formatStr) {\n\n        if (time == null) {\n            return null;\n        }\n\n        String format;\n        if (formatStr == null) {\n            format = \"yyyyMMddHHmmss\";\n        } else {\n            format = formatStr;\n        }\n\n        String timeStr = new SimpleDateFormat(format).format(time);\n\n        return Long.valueOf(timeStr);\n    }\n\n    public static Date getYesterday(Date time) {\n        return getBeforeDays(time, 1);\n    }\n\n    public static Date getYesterday() {\n        return getBeforeDays(new Date(), 1);\n    }\n\n    public static Date getTodayBegin() {\n        Calendar c = Calendar.getInstance();\n        c.set(Calendar.HOUR_OF_DAY, 0);\n        c.set(Calendar.MINUTE, 0);\n        c.set(Calendar.SECOND, 0);\n        c.set(Calendar.MILLISECOND, 0);\n        return c.getTime();\n    }\n\n    public static Date getBeforeDays(Date time, int before) {\n\n        if (time == null) {\n            return null;\n        }\n\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        c.set(Calendar.DATE, c.get(Calendar.DATE) - before);\n\n        return c.getTime();\n    }\n\n    public static Date getBeforeSeconds(Date time, int before) {\n\n        if (time == null) {\n            return null;\n        }\n\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        c.set(Calendar.SECOND, c.get(Calendar.SECOND) - before);\n\n        return c.getTime();\n    }\n\n    public static Date getBeforeMonths(Date time, int before) {\n        if (time == null) {\n            return null;\n        }\n\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        c.set(Calendar.MONTH, c.get(Calendar.MONTH) - before);\n\n        return c.getTime();\n    }\n\n    /**\n     * 获取当前月的最后一天的\n     *\n     * @param time 时间\n     * @return\n     */\n    public static Date getLastDayOfTheMonth(Date time) {\n        if (time == null) {\n            return null;\n        }\n\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        c.set(Calendar.MONTH, c.get(Calendar.MONTH) + 1);\n        c.set(Calendar.DATE, 0);\n\n        return c.getTime();\n    }\n\n    public static Date getAfterDays(Date time, int after) {\n\n        if (time == null) {\n            return null;\n        }\n\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        c.set(Calendar.DATE, c.get(Calendar.DATE) + after);\n\n        return c.getTime();\n    }\n\n    public static int getWeekInfo(Date time) {\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        return c.get(Calendar.DAY_OF_WEEK);\n    }\n\n    public static int getDayInfo(Date time) {\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        return c.get(Calendar.DAY_OF_MONTH);\n    }\n\n    public static int getMonthInfo(Date time) {\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        return c.get(Calendar.MONTH);\n    }\n\n    public static int getHourInfo(Date time) {\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        return c.get(Calendar.HOUR_OF_DAY);\n    }\n\n    public static int getYearInfo(Date time) {\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        return c.get(Calendar.YEAR);\n    }\n\n    public static Integer date2int(Date time) {\n\n        if (time == null) {\n            return null;\n        }\n\n        String timeStr = new SimpleDateFormat(\"yyyyMMddHH\").format(time);\n\n        return Integer.valueOf(timeStr);\n    }\n\n    public static Integer date2int(Date time, String format) {\n\n        if (time == null) {\n            return null;\n        }\n\n        if (StringUtils.isBlank(format)) {\n            format = \"yyyyMMddHH\";\n        }\n\n        String timeStr = new SimpleDateFormat(format).format(time);\n\n        return Integer.valueOf(timeStr);\n    }\n\n    public static Date int2date(int time, String format) {\n\n        if (format == null) {\n            return null;\n        }\n\n        String timeStr = String.valueOf(time);\n        Date result = null;\n        try {\n            result = new SimpleDateFormat(format).parse(timeStr);\n        } catch (ParseException e) {\n            return null;\n        }\n\n        return result;\n    }\n\n    public static String date2Str(Date date, String newFormatStr) {\n\n        if (date == null) {\n            return null;\n        } else {\n            String newformat;\n            if (StringUtils.isBlank(newFormatStr)) {\n                newformat = FORMAT;\n            } else {\n                newformat = newFormatStr;\n            }\n\n            SimpleDateFormat format = new SimpleDateFormat(newformat);\n            return format.format(date);\n        }\n    }\n\n    public static String getDateTimeStr(long time) {\n        SimpleDateFormat sdf = new SimpleDateFormat(FORMAT);\n        return sdf.format(new Date(time));\n    }\n\n    public static Date str2Date(String str, String newFormatStr) {\n        if (str == null) {\n            return null;\n        } else {\n            String newformat;\n            if (StringUtils.isBlank(newFormatStr)) {\n                newformat = FORMAT;\n            } else {\n                newformat = newFormatStr;\n            }\n\n            SimpleDateFormat format = new SimpleDateFormat(newformat);\n            try {\n                return format.parse(str);\n            } catch (ParseException e) {\n                return null;\n            }\n        }\n    }\n\n    public static Date getZeroDate() {\n        return getZeroDate(new Date());\n    }\n\n    public static Date getZeroDate(Date time) {\n        if (time == null) {\n            return null;\n        }\n\n        time = DateUtils.setHours(time, 0);\n        time = DateUtils.setMinutes(time, 0);\n        time = DateUtils.setSeconds(time, 0);\n        time = DateUtils.setMilliseconds(time, 0);\n        return time;\n    }\n\n    public static int getBeforeDayCount(Date before) {\n        Date todayZero = getZeroDate();\n        long timestamp = todayZero.getTime() - before.getTime();\n        if (timestamp < 0) {\n            return 0;\n        }\n\n        Double result = Math.ceil(timestamp * 1.0 / 1000 / 60 / 60 / 24);\n        return result.intValue();\n    }\n\n    public static boolean isLastOfMonth(Date date) {\n\n        Date tomorrow = AriusDateUtils.getAfterDays(date, 1);\n        int tomorrowMonth = getMonthInfo(tomorrow);\n        int todayMonth = getMonthInfo(date);\n\n        return todayMonth != tomorrowMonth;\n    }\n\n    public static int getThisMonthRemainDay() {\n        Date today = new Date();\n        int todayMonth = getMonthInfo(today);\n        int i = 1;\n        while (getMonthInfo(getAfterDays(today, i)) == todayMonth) {\n            i++;\n        }\n        return i;\n    }\n\n    /**\n     * 将时间的其他单位（s,m,h,d）转化为ms\n     *\n     * @param value\n     * @param unit\n     * @return\n     */\n    public static long getUnitTime(long value, String unit) {\n        long ms = 0L;\n        switch (unit) {\n            case \"s\":\n                ms = value * 1000;\n                break;\n            case \"min\":\n                ms = value * 1000 * 60;\n                break;\n            case \"h\":\n                ms = value * 1000 * 60 * 60;\n                break;\n            case \"d\":\n                ms = value * 1000 * 60 * 60 * 24;\n                break;\n            default:\n                ms = value;\n        }\n        return ms;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/AriusIndexMappingConfigUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONException;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * @author wangshu\n * @date 2020/06/14\n */\npublic class AriusIndexMappingConfigUtils {\n\n    private AriusIndexMappingConfigUtils() {\n    }\n\n    private static final ILog   LOGGER       = LogFactory.getLog(AriusIndexMappingConfigUtils.class);\n\n    private static final String MAPPING_STR  = \"mapping\";\n    private static final String MAPPINGS_STR = \"mappings\";\n\n    /**\n     * 解析索引mapping config.\n     * @param mappingConfig mapping config JSON序列化内容\n     * @return\n     */\n    public static Result<MappingConfig> parseMappingConfig(String mappingConfig) throws AdminOperateException {\n        try {\n            return Result.buildSucc(new MappingConfig(getMappingObj(JSON.parseObject(mappingConfig))));\n        } catch (Exception t) {\n            LOGGER.warn(\n                \"class=AriusIndexMappingConfigUtils||method=parseMappingConfig||\" + \"mappingConfig={}||exception={}\",\n                mappingConfig, t);\n            if (t instanceof JSONException) {\n                throw new AdminOperateException(\"mapping解析失败\");\n            }\n            return Result.build(ResultType.FAIL.getCode(), t.getMessage());\n        }\n    }\n\n    private static JSONObject getMappingObj(JSONObject obj) {\n        if (obj.containsKey(MAPPING_STR)) {\n            return obj.getJSONObject(MAPPING_STR);\n        }\n\n        if (obj.containsKey(MAPPINGS_STR)) {\n            return obj.getJSONObject(MAPPINGS_STR);\n        }\n\n        return obj;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/AriusJSON.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.lang.reflect.Type;\n\nimport com.alibaba.fastjson.JSON;\n\n/**\n * @author d06679\n * @date 2019/3/18\n */\npublic class AriusJSON {\n\n    private AriusJSON() {\n    }\n\n    public static String toString(Object obj) {\n        if (obj == null) {\n            return null;\n        }\n        if (obj instanceof String) {\n            return (String) obj;\n        } else {\n            return JSON.toJSONString(obj);\n        }\n    }\n\n    public static <T> T toObject(String json, Type resultType) {\n        if (resultType instanceof Class) {\n            Class<T> clazz = (Class<T>) resultType;\n            return toObject(json, clazz);\n        }\n        return JSON.parseObject(json, resultType);\n    }\n\n    public static <T> T toObject(String json, Class<T> resultType) {\n        if (resultType.isAssignableFrom(String.class)) {\n            return resultType.cast(json);\n        }\n        return JSON.parseObject(json, resultType);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/AriusObjUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Maps;\nimport io.swagger.annotations.ApiModelProperty;\nimport java.beans.PropertyDescriptor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Modifier;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.StringJoiner;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.util.ObjectUtils;\n\n/**\n * Bean操作工具\n *\n * @author d06679\n * @date 2019/2/26\n */\npublic class AriusObjUtils {\n\n    private AriusObjUtils() {\n    }\n\n    private static final ILog LOGGER = LogFactory.getLog(AriusObjUtils.class);\n\n    /**\n     * 比较两个对象是否相等\n     * @param dest 目标对象  如果是null  则认为没有变\n     * @param src 源对象\n     * @return 变了 true  没变 false\n     */\n    public static boolean isChanged(Object dest, Object src) {\n        return dest != null && !ObjectUtils.nullSafeEquals(src, dest);\n    }\n\n    /**\n     * 找到两个对象不一样的地方\n     * 这个方法要求参数bean中必须都是基本类型,且是封装类;如过不是封装类,例如boolean,getter方法不是get开头,而是is开头\n     * @param src 源\n     * @param dest 目标\n     * @return 不一样的字段\n     */\n    public static String findChanged(Object src, Object dest) {\n        if (src == null || dest == null) {\n            return \"\";\n        }\n        StringBuilder content = new StringBuilder(\"\");\n        try {\n            Map<String, Method> destMethodMap = Maps.newHashMap();\n            for (Method destMethod : dest.getClass().getMethods()) {\n                if (isGetter(destMethod)) {\n                    destMethodMap.put(destMethod.getName(), destMethod);\n                }\n            }\n\n            for (Method srcMethod : src.getClass().getMethods()) {\n                if (isGetter(srcMethod)) {\n                    Method destMethod = destMethodMap.get(srcMethod.getName());\n                    if (destMethod != null) {\n                        Object srcV = srcMethod.invoke(src);\n                        Object destV = destMethod.invoke(dest);\n\n                        if (isChanged(destV, srcV)) {\n                            content.append(getPropertyName(srcMethod.getName())).append(\":\").append(srcV).append(\"->\")\n                                .append(destV).append(\"; \");\n                        }\n                    }\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=AriusObjUtils||method=findChanged||errMsg={}\", e.getMessage(), e);\n        }\n\n        return content.toString();\n    }\n\n    /**\n     * 找到两个对象不一样的地方\n     * 这个方法要求参数bean中必须都是基本类型,且是封装类;如过不是封装类,例如boolean,getter方法不是get开头,而是is开头\n     * @param src 源\n     * @param dest 目标\n     * @return 不一样的字段，格式更加清晰\n     */\n    public static String findChangedWithClear(Object src, Object dest) {\n        if (src == null || dest == null) {\n            return \"\";\n        }\n        StringBuilder content = new StringBuilder(\"\");\n        try {\n            Map<String, Method> destMethodMap = Maps.newHashMap();\n            for (Method destMethod : dest.getClass().getMethods()) {\n                if (isGetter(destMethod)) {\n                    destMethodMap.put(destMethod.getName(), destMethod);\n                }\n            }\n\n            for (Method srcMethod : src.getClass().getMethods()) {\n                if (isGetter(srcMethod)) {\n                    Method destMethod = destMethodMap.get(srcMethod.getName());\n                    if (destMethod != null) {\n                        Object srcV = srcMethod.invoke(src);\n                        Object destV = destMethod.invoke(dest);\n\n                        if (isChanged(destV, srcV)) {\n                            content.append(\"字段\").append(getPropertyName(srcMethod.getName())).append(\"的原值\").append(\"【\")\n                                .append(srcV).append(\"】\").append(\"修改为\").append(\"【\").append(destV).append(\"】\")\n                                .append(\"\\r\\n\");\n                        }\n                    }\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=AriusObjUtils||method=findChanged||errMsg={}\", e.getMessage(), e);\n        }\n\n        return content.toString();\n    }\n\n    /**\n     * 找出两个vo中不同的值\n     *\n     * @param srcVo                       srcVo\n     * @param destVo                      destVo\n     * @param apiModelPropertyValueModify apiModelPropertyValueModify\n     * @return {@code String}\n     */\n    public static String findChangedWithClearByBeanVo(Object srcVo, Object destVo,\n                                                      Map</*apiModelPropertyValue*/String, /*修改后的apiModelPropertyValue*/String> apiModelPropertyValueModify) {\n        if (srcVo == null || destVo == null) {\n            return null;\n        }\n        StringJoiner content = new StringJoiner(\"\");\n        try {\n            Map<String, String> destMethodMap = Maps.newHashMap();\n            for (Field destField : destVo.getClass().getDeclaredFields()) {\n                if (destField.isAnnotationPresent(ApiModelProperty.class)) {\n                    String apiModelPropertyValue = destField.getAnnotation(ApiModelProperty.class).value();\n                    String getValue = getInvokeValue(destField.getName(), destVo);\n                    if (StringUtils.isNotBlank(getValue)) {\n                        destMethodMap.put(apiModelPropertyValue, getValue);\n                    }\n                }\n            }\n\n            for (Field srcField : srcVo.getClass().getDeclaredFields()) {\n                if (srcField.isAnnotationPresent(ApiModelProperty.class)) {\n                    String apiModelPropertyValue = srcField.getAnnotation(ApiModelProperty.class).value();\n                    String destValue = destMethodMap.get(apiModelPropertyValue);\n                    if (destValue != null) {\n                        String srcGetValue = getInvokeValue(srcField.getName(), srcVo);\n                        String finalApiModelPropertyValue = apiModelPropertyValue;\n                        final Optional<String> apiModelPropertyValueModifyOptional = Optional\n                            .ofNullable(apiModelPropertyValueModify).map(m -> m.get(finalApiModelPropertyValue));\n                        if (apiModelPropertyValueModifyOptional.isPresent()) {\n                            apiModelPropertyValue = apiModelPropertyValueModifyOptional.get();\n                        }\n                        if (isChanged(destValue, srcGetValue)) {\n                            content.add(\"字段\").add(\"【\").add(apiModelPropertyValue).add(\"】\").add(\"的原值\").add(\"【\")\n                                .add(srcGetValue).add(\"】\").add(\"修改为\").add(\"【\").add(destValue).add(\"】\").add(\"\\r\\n\");\n                        }\n                    }\n\n                }\n\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=AriusObjUtils||method=findChangedWithClearByBeanVo||errMsg={}\", e.getMessage(), e);\n        }\n\n        return content.toString();\n    }\n\n    /**\n     * 是否是空\n     * @param object\n     * @return\n     */\n    public static boolean isNull(Object object) {\n        return object == null;\n    }\n\n    public static boolean isNull(String str) {\n        return isBlack(str);\n    }\n\n    /**\n     * 是否是空\n     * @param str\n     * @return\n     */\n    public static boolean isNullStr(String str) {\n        return str == null;\n    }\n\n    /**\n     * 是否是空字符串\n     * @param str\n     * @return\n     */\n    public static boolean isBlack(String str) {\n        return StringUtils.isBlank(str);\n    }\n\n    private static String getInvokeValue(String propertyName, Object bean) {\n        try {\n            PropertyDescriptor pd = new PropertyDescriptor(propertyName, bean.getClass());\n            Object invoke = pd.getReadMethod().invoke(bean);\n            return String.valueOf(invoke);\n        } catch (Exception e) {\n            return null;\n        }\n\n    }\n\n    private static boolean isGetter(Method method) {\n        String methodName = method.getName();\n        return (methodName.startsWith(\"get\")) && !\"getClass\".equals(methodName)\n               && Modifier.isPublic(method.getModifiers()) && method.getParameterTypes().length == 0\n               && isPrimitive(method.getReturnType());\n    }\n\n    private static boolean isPrimitive(Class<?> type) {\n        return type.isPrimitive() || type == String.class || type == Character.class || type == Boolean.class\n               || type == Byte.class || type == Short.class || type == Integer.class || type == Long.class\n               || type == Float.class || type == Double.class || type == Object.class;\n    }\n\n    private static String getPropertyName(String name) {\n        return name.length() > 3 ? name.substring(3, 4).toLowerCase() + name.substring(4) : \"\";\n    }\n\n    /**\n     * 是空字符串或者空\n     */\n    public static boolean isBlank(String str) {\n        return StringUtils.isBlank(str);\n    }\n\n    /**\n     * 是空字符串或者空\n     */\n    public static boolean anyBlank(String... strings) {\n        return Arrays.stream(strings).anyMatch(StringUtils::isBlank);\n    }\n\n    /**\n     * 存在空\n     */\n    public static boolean isExistBlank(String str) {\n        int strLen;\n        if (str == null || (strLen = str.length()) == 0) {\n            return true;\n        }\n        for (int i = 0; i < strLen; i++) {\n            if ((Character.isWhitespace(str.charAt(i)))) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * 是空字符串\n     */\n    public static boolean equalList(List<Object> seq1, List<Object> seq2) {\n        if (isNull(seq1) && isNull(seq2)) {\n            return true;\n        } else if (isNull(seq1) || isNull(seq2) || seq1.size() != seq2.size()) {\n            return false;\n        }\n        for (Object elem : seq1) {\n            if (!seq2.contains(elem)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    public static boolean isEmptyList(List<?> seq) {\n        return isNull(seq) || seq.isEmpty();\n    }\n\n    public static boolean isEmptySet(Set<?> seq) {\n        return isNull(seq) || seq.isEmpty();\n    }\n\n    public static boolean isNullOrLessThanZero(Long value) {\n        return value == null || value < 0;\n    }\n\n    public static boolean isNullOrLessThanZero(Integer value) {\n        return value == null || value < 0;\n    }\n\n    public static boolean isNullOrLessThanZero(Double value) {\n        return value == null || value < 0;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/AriusOptional.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.util.Collection;\nimport java.util.NoSuchElementException;\nimport java.util.Objects;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\nimport java.util.function.Supplier;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport org.apache.commons.collections4.CollectionUtils;\n\n/**\n * 模仿Java8 Optional, 兼容服务Result响应体\n * @author linyunan\n * @date 2021-05-21\n */\npublic class AriusOptional<T> {\n\n    private static final AriusOptional<?> EMPTY = new AriusOptional<>();\n\n    private final T                       value;\n\n    private AriusOptional() {\n        this.value = null;\n    }\n\n    public static <T> AriusOptional<T> empty() {\n        @SuppressWarnings(\"unchecked\")\n        AriusOptional<T> t = (AriusOptional<T>) EMPTY;\n        return t;\n    }\n\n    private AriusOptional(T value) {\n        this.value = Objects.requireNonNull(value);\n    }\n\n    public static <T> AriusOptional<T> of(T value) {\n        return new AriusOptional<>(value);\n    }\n\n    public static <T> AriusOptional<T> ofListNullable(T value) {\n        if (value instanceof Collection) {\n            return CollectionUtils.isEmpty((Collection<?>) value) ? empty() : of(value);\n        }\n\n        return ofObjNullable(value);\n    }\n\n    public static <T> AriusOptional<T> ofObjNullable(T value) {\n        return value == null ? empty() : of(value);\n    }\n\n    public T get() {\n        if (value == null) {\n            throw new NoSuchElementException(\"No value present\");\n        }\n        return value;\n    }\n\n    public boolean isPresent() {\n        return value != null;\n    }\n\n    public void ifPresent(Consumer<? super T> consumer) {\n        if (value != null) {\n            consumer.accept(value);\n\n        }\n    }\n\n    public AriusOptional<T> filter(Predicate<? super T> predicate) {\n        Objects.requireNonNull(predicate);\n        if (!isPresent()) {\n            return this;\n\n        } else {\n            return predicate.test(value) ? this : empty();\n        }\n    }\n\n    public <U> AriusOptional<U> map(Function<? super T, ? extends U> mapper) {\n        Objects.requireNonNull(mapper);\n        if (!isPresent()) {\n            return empty();\n\n        } else {\n            return AriusOptional.ofObjNullable(mapper.apply(value));\n        }\n    }\n\n    public <U> AriusOptional<U> flatMap(Function<? super T, AriusOptional<U>> mapper) {\n        Objects.requireNonNull(mapper);\n        if (!isPresent()) {\n            return empty();\n\n        } else {\n            return Objects.requireNonNull(mapper.apply(value));\n        }\n    }\n\n    public T orElse(T other) {\n        return value != null ? value : other;\n    }\n\n    public Result<T> orGetResult(Supplier<? extends Result<T>> other) {\n        return value != null ? Result.buildSucc(value) : other.get();\n    }\n\n    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {\n        if (value != null) {\n            return value;\n        } else {\n            throw exceptionSupplier.get();\n        }\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n\n        if (!(obj instanceof AriusOptional)) {\n            return false;\n        }\n\n        AriusOptional<?> other = (AriusOptional<?>) obj;\n        return Objects.equals(value, other.value);\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hashCode(value);\n    }\n\n    @Override\n    public String toString() {\n        return value != null ? String.format(\"AriusOptional[%s]\", value) : \"AriusOptional.empty\";\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/AriusUnitUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\n/**\n * 单位转换工具类.\n *\n * @ClassName AriusUnitUtil\n * @Author gyp\n * @Date 2022/8/27\n * @Version 1.0\n */\npublic class AriusUnitUtil {\n\n    public static String TIME = \"time\";\n    public static String SIZE = \"size\";\n    public static String COMMON = \"common\";\n\n    /**\n     *  将其他单位转换为基础单位\n     * @param value\n     * @param unit\n     * @return\n     */\n    public static long unitChange(long value, String unit, String unitStyle) {\n        switch (unitStyle) {\n            case \"time\":\n                value = AriusDateUtils.getUnitTime(value, unit.toLowerCase());\n                break;\n            case \"size\":\n                value = SizeUtil.getUnitSize(value + unit.toLowerCase());\n                break;\n            case \"common\":\n            default:\n                break;\n        }\n        return value;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/AriusUserUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.collections4.CollectionUtils;\n\nimport com.google.common.collect.Sets;\n\n/**\n * 是一些arius用户id的工具类\n * Created by d06679 on 2018/9/8.\n */\npublic class AriusUserUtil {\n\n    private AriusUserUtil() {\n    }\n\n    public static String userIds2Str(Collection<Long> userIds) {\n\n        if (CollectionUtils.isEmpty(userIds)) {\n            return null;\n        }\n\n        List<String> userIdStrs = userIds.stream().map(String::valueOf).collect(Collectors.toList());\n\n        return String.join(\",\", userIdStrs);\n    }\n\n    public static Set<Long> getUserIdsByStr(String userIdStr) {\n        Set<Long> userIds = Sets.newHashSet();\n        for (String userId : userIdStr.split(\",\")) {\n            userIds.add(Long.valueOf(userId));\n        }\n        return userIds;\n    }\n\n    public static boolean userIdsIsSame(Set<Long> newUserIds, Set<Long> oldUserIds) {\n\n        if (CollectionUtils.isEmpty(newUserIds) && CollectionUtils.isEmpty(oldUserIds)) {\n            return true;\n        }\n\n        if (CollectionUtils.isEmpty(newUserIds) || CollectionUtils.isEmpty(oldUserIds)) {\n            return false;\n        }\n\n        for (Long userId : newUserIds) {\n            if (!oldUserIds.contains(userId)) {\n                return false;\n            }\n        }\n\n        for (Long userId : oldUserIds) {\n            if (!newUserIds.contains(userId)) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/BaseHttpUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.http.Header;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.entity.UrlEncodedFormEntity;\nimport org.apache.http.client.methods.HttpDelete;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.client.methods.HttpPut;\nimport org.apache.http.entity.BasicHttpEntity;\nimport org.apache.http.impl.client.DefaultHttpClient;\nimport org.apache.http.impl.conn.PoolingClientConnectionManager;\nimport org.apache.http.message.BasicHeader;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.UnsupportedEncodingException;\nimport java.lang.reflect.Array;\nimport java.util.*;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/25 下午4:04\n * @modified By D10865\n */\npublic class BaseHttpUtil {\n    private static final ILog       LOGGER        = LogFactory.getLog(BaseHttpUtil.class);\n    public static final String      UTF8          = \"UTF-8\";\n    public static final String      GBK           = \"GBK\";\n    public static final String      GB2312        = \"GB2312\";\n\n    private static final String     COOKIE_POLICY = \"http.protocol.cookie-policy\";\n    private static final String     COMPATIBILITY = \"compatibility\";\n    private static final String     EXCEPTION_1   = \"UTF-8 is not surportted\";\n    private static final String     EXCEPTION_2   = \"error post data to \";\n    private static final String     RESPONSE      = \"response=\";\n\n    private static final HttpClient HTTP_CLIENT;\n\n    private BaseHttpUtil() {\n    }\n\n    public static String post(String url, Map<String, Object> params) throws AdminOperateException {\n        return post(url, params, (Map) null, (String) null, (String) null);\n    }\n\n    public static String postEncode(String url, Map<String, Object> params, String reqEncode,\n                                    String resEncode) throws AdminOperateException {\n        return post(url, params, (Map) null, reqEncode, resEncode);\n    }\n\n    public static String post(String url, Map<String, Object> params, Map<String, String> headers, String reqEncode,\n                              String resEncode) throws AdminOperateException {\n        HttpPost post = new HttpPost(url);\n        if (StringUtils.isBlank(reqEncode)) {\n            reqEncode = UTF8;\n        }\n\n        if (StringUtils.isBlank(resEncode)) {\n            resEncode = UTF8;\n        }\n\n        List<BasicNameValuePair> httpParams;\n        Iterator var7;\n        if (params != null && !params.isEmpty()) {\n            httpParams = new ArrayList<>(params.size());\n            var7 = params.entrySet().iterator();\n\n            while (true) {\n                Map.Entry e;\n                while (var7.hasNext()) {\n                    e = (Map.Entry) var7.next();\n                    String k = (String) e.getKey();\n                    Object v = e.getValue();\n                    if (v == null) {\n                        httpParams.add(new BasicNameValuePair(k, (String) null));\n                    } else if (!v.getClass().isArray()) {\n                        httpParams.add(new BasicNameValuePair(k, v.toString()));\n                    } else {\n                        int len = Array.getLength(v);\n\n                        for (int i = 0; i < len; ++i) {\n                            Object element = Array.get(v, i);\n                            if (element != null) {\n                                httpParams.add(new BasicNameValuePair(k, element.toString()));\n                            } else {\n                                httpParams.add(new BasicNameValuePair(k, (String) null));\n                            }\n                        }\n                    }\n                }\n\n                if (headers != null) {\n                    var7 = headers.entrySet().iterator();\n\n                    while (var7.hasNext()) {\n                        e = (Map.Entry) var7.next();\n                        post.addHeader((String) e.getKey(), (String) e.getValue());\n                    }\n                }\n\n                try {\n                    post.setEntity(new UrlEncodedFormEntity(httpParams, reqEncode));\n                    post.getParams().setParameter(COOKIE_POLICY, COMPATIBILITY);\n                    break;\n                } catch (UnsupportedEncodingException var20) {\n                    throw new AdminOperateException(EXCEPTION_1, var20, ResultType.FAIL);\n                }\n            }\n        }\n\n        var7 = null;\n\n        String response;\n        try {\n            HttpEntity entity = HTTP_CLIENT.execute(post).getEntity();\n            response = EntityUtils.toString(entity, resEncode);\n        } catch (Exception var18) {\n            throw new AdminOperateException(EXCEPTION_2 + url, var18, ResultType.FAIL);\n        } finally {\n            post.releaseConnection();\n        }\n\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"class=BaseHttpUtil||method=post||mesg={}\", RESPONSE + response);\n        }\n\n        return response;\n    }\n\n    public static String postForString(String url, String content,\n                                       Map<String, String> headers) throws AdminOperateException {\n        HttpPost post = new HttpPost(url);\n\n        Iterator<Map.Entry<String, String>> var4;\n        if (StringUtils.isNotBlank(content)) {\n            if (headers != null) {\n                var4 = headers.entrySet().iterator();\n\n                while (var4.hasNext()) {\n                    Map.Entry<String, String> e = var4.next();\n                    post.addHeader(e.getKey(), e.getValue());\n                }\n            }\n\n            try {\n                BasicHttpEntity requestBody = new BasicHttpEntity();\n                requestBody.setContent(new ByteArrayInputStream(content.getBytes(UTF8)));\n                requestBody.setContentLength((long) content.getBytes(UTF8).length);\n                post.setEntity(requestBody);\n                post.getParams().setParameter(COOKIE_POLICY, COMPATIBILITY);\n            } catch (UnsupportedEncodingException var12) {\n                throw new AdminOperateException(EXCEPTION_1, var12, ResultType.FAIL);\n            }\n        }\n\n        var4 = null;\n\n        String response;\n        try {\n            HttpEntity entity = HTTP_CLIENT.execute(post).getEntity();\n            response = EntityUtils.toString(entity, UTF8);\n            EntityUtils.consume(entity);\n        } catch (Exception var10) {\n            throw new AdminOperateException(EXCEPTION_2 + url, var10, ResultType.FAIL);\n        } finally {\n            post.releaseConnection();\n        }\n\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"class=BaseHttpUtil||method=postForString||msg={}\", RESPONSE + response);\n        }\n\n        return response;\n    }\n\n    public static String deleteForString(String url, String content,\n                                         Map<String, String> headers) throws AdminOperateException {\n        HttpDelete post = new HttpDelete(url);\n\n        Iterator<Map.Entry<String, String>> var4;\n        if (StringUtils.isNotBlank(content)) {\n            if (headers != null) {\n                var4 = headers.entrySet().iterator();\n\n                while (var4.hasNext()) {\n                    Map.Entry<String, String> e = var4.next();\n                    post.addHeader(e.getKey(), e.getValue());\n                }\n            }\n\n            try {\n                BasicHttpEntity requestBody = new BasicHttpEntity();\n                requestBody.setContent(new ByteArrayInputStream(content.getBytes(UTF8)));\n                requestBody.setContentLength((long) content.getBytes(UTF8).length);\n                post.getParams().setParameter(COOKIE_POLICY, COMPATIBILITY);\n            } catch (UnsupportedEncodingException var12) {\n                throw new AdminOperateException(EXCEPTION_1, var12, ResultType.FAIL);\n            }\n        }\n\n        var4 = null;\n\n        String response;\n        try {\n            HttpEntity entity = HTTP_CLIENT.execute(post).getEntity();\n            response = EntityUtils.toString(entity, UTF8);\n            EntityUtils.consume(entity);\n        } catch (Exception var10) {\n            throw new AdminOperateException(EXCEPTION_2 + url, var10, ResultType.FAIL);\n        } finally {\n            post.releaseConnection();\n        }\n\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"class=BaseHttpUtil||method=deleteForString||msg={}\", RESPONSE + response);\n        }\n\n        return response;\n    }\n\n    public static String putForString(String url, String content,\n                                      Map<String, String> headers) throws AdminOperateException {\n        HttpPut post = new HttpPut(url);\n\n        Iterator<Map.Entry<String, String>> var4;\n        if (StringUtils.isNotBlank(content)) {\n            if (headers != null) {\n                var4 = headers.entrySet().iterator();\n\n                while (var4.hasNext()) {\n                    Map.Entry<String, String> e = var4.next();\n                    post.addHeader(e.getKey(), e.getValue());\n                }\n            }\n\n            try {\n                BasicHttpEntity requestBody = new BasicHttpEntity();\n                requestBody.setContent(new ByteArrayInputStream(content.getBytes(UTF8)));\n                requestBody.setContentLength((long) content.getBytes(UTF8).length);\n                post.setEntity(requestBody);\n                post.getParams().setParameter(COOKIE_POLICY, COMPATIBILITY);\n            } catch (UnsupportedEncodingException var12) {\n                throw new AdminOperateException(EXCEPTION_1, var12, ResultType.FAIL);\n            }\n        }\n\n        var4 = null;\n\n        String response;\n        try {\n            HttpEntity entity = HTTP_CLIENT.execute(post).getEntity();\n            response = EntityUtils.toString(entity, UTF8);\n            EntityUtils.consume(entity);\n        } catch (Exception var10) {\n            throw new AdminOperateException(EXCEPTION_2 + url, var10, ResultType.FAIL);\n        } finally {\n            post.releaseConnection();\n        }\n\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"class=BaseHttpUtil||method=putForString||msg={}\", RESPONSE + response);\n        }\n\n        return response;\n    }\n\n    public static String get(String url, Map<String, String> params) throws AdminOperateException {\n        Iterator<Map.Entry<String, String>> var3;\n        if (params != null) {\n            StringBuilder builder = (new StringBuilder(url)).append('?');\n            var3 = params.entrySet().iterator();\n\n            while (var3.hasNext()) {\n                Map.Entry<String, String> e = (Map.Entry) var3.next();\n                builder.append((String) e.getKey()).append('=').append((String) e.getValue()).append('&');\n            }\n\n            url = builder.toString();\n        }\n\n        HttpGet get = new HttpGet(url);\n        var3 = null;\n\n        String response;\n        try {\n            HttpEntity entity = HTTP_CLIENT.execute(get).getEntity();\n            response = EntityUtils.toString(entity, UTF8);\n        } catch (Exception var8) {\n            throw new AdminOperateException(EXCEPTION_2 + url, var8, ResultType.FAIL);\n        } finally {\n            get.releaseConnection();\n        }\n\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"class=BaseHttpUtil||method=get||msg={}\", RESPONSE + response);\n        }\n\n        return response;\n    }\n\n    public static String get(String url, Map<String, String> params,\n                             Map<String, String> headers) throws AdminOperateException {\n        if (params != null) {\n            StringBuilder builder = new StringBuilder(url).append('?');\n            for (Map.Entry<String, String> e : params.entrySet()) {\n                builder.append(e.getKey()).append('=').append(e.getValue()).append('&');\n            }\n            url = builder.toString();\n        }\n\n        HttpGet get = new HttpGet(url);\n        if (headers != null) {\n            for (Map.Entry<String, String> e : headers.entrySet()) {\n                get.addHeader(e.getKey(), e.getValue());\n            }\n        }\n\n        String response = null;\n        try {\n            HttpEntity entity = HTTP_CLIENT.execute(get).getEntity();\n            response = EntityUtils.toString(entity, UTF8);\n        } catch (Exception e) {\n            throw new AdminOperateException(EXCEPTION_2 + url, e, ResultType.FAIL);\n        } finally {\n            get.releaseConnection();\n        }\n\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"class=BaseHttpUtil||method=get||msg={}\", RESPONSE + response);\n        }\n        return response;\n    }\n\n    public static Header buildHttpHeader(String esUser, String passWord) {\n        // 构建认证信息的header\n        Header header = null;\n        try {\n            header = new BasicHeader(\"Authorization\",\n                \"Basic \" + Base64.getEncoder().encodeToString(String.format(\"%s:%s\", esUser, passWord).getBytes(UTF8)));\n        } catch (UnsupportedEncodingException e) {\n            LOGGER.error(\"class=BaseHttpUtil||method=buildHttpHeader||esUser={}||passWord={}||errMsg=encoding error\",\n                esUser, passWord, e);\n        }\n\n        return header;\n    }\n\n    static {\n        PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();\n        connectionManager.setMaxTotal(200);\n        connectionManager.setDefaultMaxPerRoute(50);\n        HTTP_CLIENT = new DefaultHttpClient(connectionManager);\n        HTTP_CLIENT.getParams().setParameter(\"http.connection.timeout\", Integer.valueOf(20000));\n        HTTP_CLIENT.getParams().setParameter(\"http.socket.timeout\", Integer.valueOf(20000));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/BatchConvert.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.function.Function;\n\nimport org.apache.commons.collections4.CollectionUtils;\n\nimport com.google.common.collect.Lists;\n\n/**\n * 分配次执行\n * batchList 需要处理的对象List\n * function 处理函数\n * batchSize 批次大小\n * @author d06679\n */\npublic class BatchConvert<S, T> {\n\n    private Collection<S>                    batchList;\n\n    private Function<Collection<S>, List<T>> function;\n\n    private Integer                          batchSize = 100;\n\n    public Collection<S> getBatchList() {\n        return batchList;\n    }\n\n    public BatchConvert<S, T> batchList(Collection<S> batchList) {\n        this.batchList = batchList;\n        return this;\n    }\n\n    public Function<Collection<S>, List<T>> getFunction() {\n        return function;\n    }\n\n    public BatchConvert<S, T> function(Function<Collection<S>, List<T>> function) {\n        this.function = function;\n        return this;\n    }\n\n    public Integer getBatchSize() {\n        return batchSize;\n    }\n\n    public BatchConvert<S, T> batchSize(Integer batchSize) {\n        this.batchSize = batchSize;\n        return this;\n    }\n\n    public List<T> execute() {\n        if (CollectionUtils.isEmpty(batchList) || function == null) {\n            return Lists.newArrayList();\n        }\n\n        List<T> result = Lists.newArrayList();\n\n        List<S> tempList = new ArrayList<>(batchSize);\n        for (S t : batchList) {\n            tempList.add(t);\n            if (tempList.size() >= batchSize) {\n                List<T> list = function.apply(tempList);\n                if (list != null) {\n                    result.addAll(list);\n                }\n                tempList.clear();\n            }\n        }\n\n        if (tempList.size() > 0) {\n            List<T> list = function.apply(tempList);\n            if (list != null) {\n                result.addAll(list);\n            }\n        }\n\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/BatchProcessor.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didichuxing.datachannel.arius.admin.common.function.FunctionWithESOperateException;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.Predicate;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nullable;\nimport org.apache.commons.collections4.CollectionUtils;\n\n/**\n * 分配次执行\n * batchList 需要处理的对象List\n * function 处理函数\n * batchSize 批次大小\n * @author d06679\n */\npublic class BatchProcessor<S, R> {\n\n    private Collection<S>        batchList;\n\n    private FunctionWithESOperateException<List<S>, R> processor;\n\n    @Nullable\n    private Predicate<R>         succChecker;\n\n    private Integer              batchSize = 100;\n\n    public BatchProcessor<S, R> batchList(Collection<S> batchList) {\n        this.batchList = batchList;\n        return this;\n    }\n\n    public BatchProcessor<S, R> processor(FunctionWithESOperateException<List<S>, R> processor) {\n        this.processor = processor;\n        return this;\n    }\n\n    public BatchProcessor<S, R> succChecker(Predicate<R> succChecker) {\n        this.succChecker = succChecker;\n        return this;\n    }\n\n    public BatchProcessor<S, R> batchSize(Integer batchSize) {\n        this.batchSize = batchSize;\n        return this;\n    }\n\n    public BatchProcessResult<S, R> process() {\n\n        BatchProcessResult<S, R> result = new BatchProcessResult<>();\n\n        if (CollectionUtils.isEmpty(batchList) || processor == null) {\n            return result;\n        }\n\n        List<S> tempList = new ArrayList<>(batchSize);\n        for (S t : batchList) {\n            if (tempList.size() >= batchSize) {\n                innerProcess(tempList, result);\n                tempList.clear();\n            }\n            tempList.add(t);\n        }\n\n        if (CollectionUtils.isNotEmpty(tempList)) {\n            innerProcess(tempList, result);\n        }\n\n        return result;\n    }\n\n    private void innerProcess(List<S> tempList, BatchProcessResult<S, R> result) {\n        try {\n            R r = processor.apply(tempList);\n\n            if (succChecker != null) {\n                boolean succ = succChecker.test(r);\n                if (!succ) {\n                    result.addFail(tempList);\n                } else {\n                    result.addResult(r);\n                }\n            } else {\n                result.addResult(r);\n            }\n\n        } catch (Exception e) {\n            result.addError(tempList, e);\n        }\n    }\n\n    public static class BatchProcessResult<S, R> {\n\n        private List<R>                 resultList = Lists.newArrayList();\n\n        private List<S>                 failList   = Lists.newArrayList();\n\n        private Map<List<S>, Exception> errorMap   = Maps.newHashMap();\n\n        void addFail(List<S> fails) {\n            this.failList.addAll(fails);\n        }\n\n        void addError(List<S> errors, Exception e) {\n            this.errorMap.put(errors, e);\n        }\n\n        void addResult(R result) {\n            this.resultList.add(result);\n        }\n\n        public List<R> getResultList() {\n            return resultList;\n        }\n\n        public List<S> getFailList() {\n            return failList;\n        }\n\n        public Map<List<S>, Exception> getErrorMap() {\n            return errorMap;\n        }\n\n        public boolean isSucc() {\n            return failList.isEmpty() && errorMap.size() == 0;\n        }\n\n        public int getFailAndErrorCount() {\n            return failList.size() + errorMap.size();\n        }\n\n        @Override\n        public String toString() {\n            if (isSucc()) {\n                return \"BatchProcessResult{process succ}\";\n            }\n\n            return \"BatchProcessResult{\" + \"failSize=\" + failList.size() + \", errorSize=\" + errorMap.size()\n                   + \", errorList=\" + getErrorDesc(errorMap) + '}';\n        }\n\n        private String getErrorDesc(Map<List<S>, Exception> errorMap) {\n            return String.join(\",\", Lists.newArrayList(errorMap.values().stream()\n                .map(e -> e.getClass().getSimpleName() + \"_\" + e.getMessage()).collect(Collectors.toList())));\n        }\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/ClusterDynamicConfigTypeCheckFunUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.math.BigDecimal;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport org.apache.commons.lang3.StringUtils;\n\npublic class ClusterDynamicConfigTypeCheckFunUtil {\n\n    private ClusterDynamicConfigTypeCheckFunUtil() {\n    }\n\n    public static final Set<String> reBalanceEnableTypes  = new HashSet<>();\n\n    public static final Set<String> allowReBalanceTypes   = new HashSet<>();\n\n    public static final Set<String> allocationEnableTypes = new HashSet<>();\n\n    public static final Set<String> masterBlockTypes      = new HashSet<>();\n    public static final Set<String> bandwidthUnits        = new HashSet<>();\n    static {\n        reBalanceEnableTypes.add(\"all\");\n        reBalanceEnableTypes.add(\"primaries\");\n        reBalanceEnableTypes.add(\"replicas\");\n        reBalanceEnableTypes.add(\"none\");\n\n        allowReBalanceTypes.add(\"always\");\n        allowReBalanceTypes.add(\"indices_primaries_active\");\n        allowReBalanceTypes.add(\"indices_all_active\");\n\n        allocationEnableTypes.add(\"all\");\n        allocationEnableTypes.add(\"primaries\");\n        allocationEnableTypes.add(\"new_primaries\");\n        allocationEnableTypes.add(\"none\");\n\n        masterBlockTypes.add(\"all\");\n        masterBlockTypes.add(\"write\");\n\n        bandwidthUnits.addAll(Arrays.asList(\"k\", \"kb\", \"m\", \"mb\", \"g\", \"gb\", \"t\", \"tb\", \"p\", \"pb\", \"b\"));\n    }\n\n    public static boolean percentCheck(String value) {\n        String reg = \"^(100|[1-9]?\\\\d(\\\\.\\\\d\\\\d?)?)%$\";\n        return value.matches(reg);\n    }\n\n    public static boolean floatCheck(String value) {\n        try {\n            Float.valueOf(value);\n        } catch (NumberFormatException e) {\n            return false;\n        }\n        return true;\n    }\n\n    public static boolean floatValueCheck1to100(String value) {\n        if (floatCheck(value)) {\n            float number = Float.valueOf(value);\n            if (number < 100 && number > 1) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public static boolean floatValueCheckPositive(String value) {\n        if (floatCheck(value)) {\n            float number = Float.valueOf(value);\n            if (number >= 0) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public static boolean timeCheck(String value) {\n        if (value == null || value.isEmpty()) {\n            return false;\n        }\n        int length = value.length();\n\n        if (value.charAt(length - 1) != 's') {\n            return false;\n        }\n\n        int number = 0;\n        try {\n            number = Integer.valueOf(value.substring(0, length - 1));\n        } catch (NumberFormatException e) {\n            return false;\n        }\n\n        if (number < 0 || number > 120) {\n            return false;\n        }\n\n        return true;\n    }\n\n    public static boolean intCheck(String value) {\n        String point = \".\";\n        int number = 0;\n        if (!value.contains(point)) {\n            try {\n                number = Integer.valueOf(value);\n                if (number > 0) {\n                    return true;\n                }\n            } catch (NumberFormatException e) {\n                return false;\n            }\n        }\n        return false;\n    }\n\n    public static boolean intCheck1000(String value) {\n        if (intCheck(value)) {\n            int number = Integer.valueOf(value);\n            return number > 1000;\n        }\n        return false;\n    }\n\n    public static boolean booleanCheck(String value) {\n        if (value.equals(\"true\") || value.equals(\"false\")) {\n            return true;\n        }\n        return false;\n    }\n\n    public static boolean reBalanceEnableTypeCheck(String value) {\n        return reBalanceEnableTypes.contains(value);\n    }\n\n    public static boolean allowReBalanceTypeCheck(String value) {\n        return allowReBalanceTypes.contains(value);\n    }\n\n    public static boolean attributesTypeCheck(String value) {\n        return true;\n    }\n\n    public static boolean allocationEnableTypeCheck(String value) {\n        return allocationEnableTypes.contains(value);\n    }\n\n    public static boolean masterBlockTypeCheck(String value) {\n        return masterBlockTypes.contains(value);\n    }\n\n    public static boolean defaultTypeCheck(String value) {\n        return false;\n    }\n\n    public static boolean bandwidthCheck(String proStoreSize) {\n        BigDecimal bandwidth = null;\n        try {\n            String lowerSValue = proStoreSize.toLowerCase().trim();\n            String bandwidthUnit = StringUtils.right(lowerSValue, 2);\n            if (ClusterDynamicConfigTypeCheckFunUtil.bandwidthUnits.contains(bandwidthUnit)) {\n                bandwidth = new BigDecimal(StringUtils.left(lowerSValue, lowerSValue.length() - 2).trim());\n            } else {\n                bandwidthUnit = StringUtils.right(lowerSValue, 1);\n                if (ClusterDynamicConfigTypeCheckFunUtil.bandwidthUnits.contains(bandwidthUnit)) {\n                    bandwidth = new BigDecimal(StringUtils.left(lowerSValue, lowerSValue.length() - 1).trim());\n                }\n            }\n        } catch (Exception e) {\n            //pass\n        }\n        return bandwidth != null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/ClusterUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.google.common.collect.Sets;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.List;\nimport java.util.Set;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum.*;\n\n/**\n * Created by linyunan on 2021-06-29\n */\npublic class ClusterUtils {\n\n    private ClusterUtils() {\n    }\n\n    public static String getDuplicateIp(List<String> ips) {\n        if (CollectionUtils.isEmpty(ips)) {\n            return null;\n        }\n\n        Set<String> tempSet = Sets.newHashSet();\n        for (String ip : ips) {\n            if (tempSet.contains(ip)) {\n                return ip;\n            }\n\n            tempSet.add(ip);\n        }\n\n        return null;\n    }\n\n    public static Integer getClusterLogicHealthByClusterHealth(Set<Integer> clusterHealthSet) {\n        if (CollectionUtils.isEmpty(clusterHealthSet) || clusterHealthSet.contains(UNKNOWN.getCode())) {\n            return UNKNOWN.getCode();\n        }\n\n        if (clusterHealthSet.contains(RED.getCode())) {\n            return RED.getCode();\n        }\n\n        if (clusterHealthSet.contains(YELLOW.getCode())) {\n            return YELLOW.getCode();\n        }\n\n        return GREEN.getCode();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/CommonUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.InputStream;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.nio.charset.StandardCharsets;\nimport java.security.MessageDigest;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\nimport org.apache.commons.compress.archivers.tar.TarArchiveEntry;\nimport org.apache.commons.compress.archivers.tar.TarArchiveInputStream;\nimport org.apache.commons.compress.archivers.zip.ZipArchiveEntry;\nimport org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;\nimport org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.multipart.MultipartFile;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/18 上午11:48\n * @modified By D10865\n */\npublic class CommonUtils {\n\n    private static final ILog   LOGGER = LogFactory.getLog(CommonUtils.class);\n\n    private static final String REGEX  = \",\";\n\n    private CommonUtils() {\n    }\n\n    /**\n     * 获取MD5值\n     *\n     * @param str\n     * @return\n     */\n    public static String getMD5(String str) {\n        try {\n            MessageDigest md = MessageDigest.getInstance(\"MD5\");\n            byte[] bytes = md.digest(str.getBytes(StandardCharsets.UTF_8));\n            return toHex(bytes);\n        } catch (Exception e) {\n            return \"\";\n        }\n    }\n\n    /**\n     * 获取文件的md5\n     * @param file\n     * @return\n     */\n    public static String getMD5(MultipartFile file) {\n        try {\n            //获取文件的byte信息\n            byte[] uploadBytes = file.getBytes();\n            // 拿到一个MD5转换器\n            MessageDigest md5 = MessageDigest.getInstance(\"MD5\");\n            byte[] digest = md5.digest(uploadBytes);\n            //转换为16进制\n            return new BigInteger(1, digest).toString(16);\n        } catch (Exception e) {\n            LOGGER.error(\"class=CommonUtils||method=getMD5||msg=获取文件的md5失败:{}\", e.getMessage());\n        }\n        return null;\n    }\n\n    /**\n     * 保留指定的小数位 四舍五入\n     * @param data    需要转换的数据\n     * @param decimal 保留小数的位数 默认是2\n     * @return\n     */\n    public static double formatDouble(double data, int decimal) {\n        if (decimal < 0) {\n            decimal = 2;\n        }\n\n        BigDecimal b = BigDecimal.valueOf(data);\n        return b.setScale(decimal, BigDecimal.ROUND_HALF_UP).doubleValue();\n    }\n\n    public static double divideIntAndFormatDouble(int v1, int v2, int scale, int multiply) {\n        BigDecimal v1Decimal = new BigDecimal(v1);\n        BigDecimal v2Decimal = new BigDecimal(v2);\n        BigDecimal bigDecimal = new BigDecimal(multiply);\n\n        BigDecimal greenDivide = v1Decimal.divide(v2Decimal, scale, 1);\n        return greenDivide.multiply(bigDecimal).doubleValue();\n    }\n\n    public static double divideDoubleAndFormatDouble(double v1, double v2, int scale, int multiply) {\n        BigDecimal v1Decimal = new BigDecimal(v1);\n        BigDecimal v2Decimal = new BigDecimal(v2);\n        BigDecimal bigDecimal = new BigDecimal(multiply);\n  \n        BigDecimal greenDivide = v2==0?new BigDecimal(0):v1Decimal.divide(v2Decimal, scale, 1);\n        return greenDivide.multiply(bigDecimal).doubleValue();\n    }\n\n    public static String toHex(byte[] bytes) {\n\n        final char[] hexDigits = \"0123456789ABCDEF\".toCharArray();\n        StringBuilder ret = new StringBuilder(bytes.length * 2);\n        for (int i = 0; i < bytes.length; i++) {\n            ret.append(hexDigits[(bytes[i] >> 4) & 0x0f]);\n            ret.append(hexDigits[bytes[i] & 0x0f]);\n        }\n        return ret.toString();\n    }\n\n    public static String strList2String(List<String> strList) {\n        if (strList == null || strList.isEmpty()) {\n            return \"\";\n        }\n\n        StringBuilder sb = new StringBuilder();\n        for (String elem : strList) {\n            if (!StringUtils.hasText(elem)) {\n                continue;\n            }\n            sb.append(elem).append(REGEX);\n        }\n        return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : sb.toString();\n    }\n\n    public static List<String> string2StrList(String str) {\n        if (!StringUtils.hasText(str)) {\n            return new ArrayList<>();\n        }\n        List<String> strList = new ArrayList<>();\n        for (String elem : str.split(REGEX)) {\n            if (!StringUtils.hasText(elem)) {\n                continue;\n            }\n            strList.add(elem);\n        }\n        return strList;\n    }\n\n    /**\n     * 将 .zip 压缩文件中的目标文件转化为输入流\n     * @param in zip 压缩文件的输入流\n     * @param targetFileName 目标文件名\n     * @return 该目标文件的输入流\n     */\n    public static InputStream unZip(InputStream in, String targetFileName) {\n        if (in == null || targetFileName == null) {\n            return null;\n        }\n        byte[] bytes = new byte[1024];\n        ZipArchiveEntry zipEntry;\n        try (ZipArchiveInputStream zip = new ZipArchiveInputStream(in);\n                ByteArrayOutputStream bos = new ByteArrayOutputStream()) {\n            while ((zipEntry = zip.getNextZipEntry()) != null) {\n                // 该 entry 在压缩包中的 完整路径 + 文件名\n                String entryName = zipEntry.getName();\n                // 该 entry 的文件名\n                String fileName = entryName.substring(entryName.lastIndexOf(\"/\") + 1);\n\n                if (targetFileName.equals(fileName)) {\n                    // 找到了目标文件\n                    while (true) {\n                        int len = zip.read(bytes);\n                        if (len <= 0) {\n                            break;\n                        }\n                        bos.write(bytes, 0, len);\n                    }\n                    return new ByteArrayInputStream(bos.toByteArray());\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=CommonUtils||method=unZip||msg=fail to unZip:\", e);\n        }\n        return null;\n    }\n\n    /**\n     * 将 .tar 压缩文件中的目标文件转化为输入流\n     * @param in .tar 压缩文件的输入流\n     * @param targetFileName 目标文件名\n     * @return 该目标文件的输入流\n     */\n    public static InputStream unTar(InputStream in, String targetFileName) {\n        if (in == null || targetFileName == null) {\n            return null;\n        }\n        byte[] bytes = new byte[1024];\n        TarArchiveEntry tarEntry;\n        try (TarArchiveInputStream tar = new TarArchiveInputStream(new GzipCompressorInputStream(in));\n                ByteArrayOutputStream bos = new ByteArrayOutputStream()) {\n            while ((tarEntry = tar.getNextTarEntry()) != null) {\n                // 该 entry 在压缩包中的 完整路径 + 文件名\n                String entryName = tarEntry.getName();\n                // 该 entry 的文件名\n                String fileName = entryName.substring(entryName.lastIndexOf(\"/\") + 1);\n\n                if (targetFileName.equals(fileName)) {\n                    // 找到了目标文件\n                    while (true) {\n                        int len = tar.read(bytes);\n                        if (len <= 0) {\n                            break;\n                        }\n                        bos.write(bytes, 0, len);\n                    }\n                    return new ByteArrayInputStream(bos.toByteArray());\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=CommonUtils||method=unTar||msg=fail to unTar:\", e);\n        }\n        return null;\n    }\n\n    public static Long monitorTimestamp2min(Long timestamp) {\n        return timestamp - timestamp % 60000;\n    }\n\n    /**\n     * 字符串追加\n     *\n     * @param items\n     * @return\n     */\n    public static String strConcat(List<String> items) {\n        StringBuilder stringBuilder = new StringBuilder(128);\n        boolean isFirstItem = true;\n\n        for (String item : items) {\n            if (isFirstItem) {\n                stringBuilder.append(String.format(\"\\\"%s\\\"\", item));\n                isFirstItem = false;\n            } else {\n                stringBuilder.append(\",\").append(String.format(\"\\\"%s\\\"\", item));\n            }\n        }\n\n        return stringBuilder.toString();\n    }\n\n    /**\n     * 判断是否为合法IP\n     * @return the ip\n     */\n    public static boolean checkIp(String addr) {\n        if (addr.length() < 7 || addr.length() > 15 || \"\".equals(addr)) {\n            return false;\n        }\n\n        String rexp1 = \"^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])\\\\.\";\n        String rexp2 = \"(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])\\\\.\";\n        String rexp3 = \"(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$\";\n\n        Pattern pat = Pattern.compile(rexp1 + rexp2 + rexp2 + rexp3);\n        Matcher mat = pat.matcher(addr);\n\n        return mat.find();\n\n    }\n\n    /**\n     * 生成固定长度的随机字符串\n     */\n    public static String randomString(int length) {\n        char[] value = new char[length];\n        for (int i = 0; i < length; i++) {\n            value[i] = randomWritableChar();\n        }\n        return new String(value);\n    }\n\n    /**\n     * 随机生成单个随机字符\n     */\n    public static char randomWritableChar() {\n        Random random = new Random();\n        return (char) (33 + random.nextInt(94));\n    }\n\n    public static String getUniqueKey(String... arg) {\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < arg.length; i++) {\n            if (i == (arg.length - 1)) {\n                sb.append(arg[i]);\n            } else {\n                sb.append(arg[i]).append(\"@\");\n            }\n        }\n        return sb.toString();\n    }\n     public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {\n        Map<Object, Boolean> seen = new ConcurrentHashMap<>();\n        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;\n    }\n\n    /**\n     * 避免模糊查询把查询条件中的\"% _\"当作通配符处理（造成结果是全量查询）\n     */\n    public static String sqlFuzzyQueryTransfer(String str){\n        if(str.contains(\"%\")){\n            str = str.replaceAll(\"%\", \"\\\\\\\\%\");\n        }\n        if(str.contains(\"_\")){\n            str = str.replaceAll(\"_\",\"\\\\\\\\_\");\n        }\n        return str;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/ConvertUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Modifier;\nimport java.util.*;\nimport java.util.Map.Entry;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.BeanUtils;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.*;\n\npublic class ConvertUtil {\n\n    private ConvertUtil() {\n    }\n\n    private static final ILog LOGGER = LogFactory.getLog(ConvertUtil.class);\n\n    public static <T> T str2ObjByJson(String srcStr, Class<T> tgtClass) {\n        return JSON.parseObject(srcStr, tgtClass);\n    }\n\n    public static String obj2Json(Object srcObj) {\n        return JSON.toJSONString(srcObj);\n    }\n\n    public static <T> List<T> str2ObjArrayByJson(String srcStr, Class<T> tgtClass) {\n        return JSON.parseArray(srcStr, tgtClass);\n    }\n\n    public static <T> T obj2ObjByJSON(Object srcObj, Class<T> tgtClass) {\n        return JSON.parseObject(JSON.toJSONString(srcObj), tgtClass);\n    }\n\n    public static String list2String(List<?> list, String separator) {\n        if (list == null || list.isEmpty()) {\n            return \"\";\n        }\n\n        StringBuilder sb = new StringBuilder();\n        for (Object item : list) {\n            sb.append(item).append(separator);\n        }\n        return sb.deleteCharAt(sb.length() - 1).toString();\n    }\n\n    public static <K, V> String list2String(List<V> list, String separator, Function<? super V, ? extends K> mapper) {\n        if (list == null || list.isEmpty()) {\n            return \"\";\n        }\n\n        StringBuilder sb = new StringBuilder();\n        for (V item : list) {\n            sb.append(mapper.apply(item)).append(separator);\n        }\n        return sb.deleteCharAt(sb.length() - 1).toString();\n    }\n\n    public static <K, V> Map<K, V> list2Map(List<V> list, Function<? super V, ? extends K> mapper) {\n        Map<K, V> map = Maps.newHashMap();\n        if (CollectionUtils.isNotEmpty(list)) {\n            for (V v : list) {\n                map.put(mapper.apply(v), v);\n            }\n        }\n        return map;\n    }\n\n    public static <K, V> Map<K, V> list2MapParallel(List<V> list, Function<? super V, ? extends K> mapper) {\n        Map<K, V> map = new ConcurrentHashMap<>();\n        if (CollectionUtils.isNotEmpty(list)) {\n            list.parallelStream().forEach(v -> map.put(mapper.apply(v), v));\n        }\n        return map;\n    }\n\n    public static <K, V, O> Map<K, V> list2Map(List<O> list, Function<? super O, ? extends K> keyMapper,\n                                               Function<? super O, ? extends V> valueMapper) {\n        Map<K, V> map = Maps.newHashMap();\n        if (CollectionUtils.isNotEmpty(list)) {\n            for (O o : list) {\n                map.put(keyMapper.apply(o), valueMapper.apply(o));\n            }\n        }\n        return map;\n    }\n\n    public static <K, V> Multimap<K, V> list2MulMap(List<V> list, Function<? super V, ? extends K> mapper) {\n        Multimap<K, V> multimap = ArrayListMultimap.create();\n        if (CollectionUtils.isNotEmpty(list)) {\n            for (V v : list) {\n                multimap.put(mapper.apply(v), v);\n            }\n        }\n        return multimap;\n    }\n\n    public static <K, V, O> Multimap<K, V> list2MulMap(List<O> list, Function<? super O, ? extends K> keyMapper,\n                                                       Function<? super O, ? extends V> valueMapper) {\n        Multimap<K, V> multimap = ArrayListMultimap.create();\n        if (CollectionUtils.isNotEmpty(list)) {\n            for (O o : list) {\n                multimap.put(keyMapper.apply(o), valueMapper.apply(o));\n            }\n        }\n        return multimap;\n    }\n\n    public static <K, V, O> Map<K, List<V>> list2MapOfList(List<O> list, Function<? super O, ? extends K> keyMapper,\n                                                           Function<? super O, ? extends V> valueMapper) {\n        ArrayListMultimap<K, V> multimap = ArrayListMultimap.create();\n        if (CollectionUtils.isNotEmpty(list)) {\n            for (O o : list) {\n                multimap.put(keyMapper.apply(o), valueMapper.apply(o));\n            }\n        }\n\n        return Multimaps.asMap(multimap);\n    }\n\n    public static <K, V> Set<K> list2Set(List<V> list, Function<? super V, ? extends K> mapper) {\n        Set<K> set = Sets.newHashSet();\n        if (CollectionUtils.isNotEmpty(list)) {\n            for (V v : list) {\n                set.add(mapper.apply(v));\n            }\n        }\n        return set;\n    }\n\n    public static <T> Set<T> set2Set(Set<? extends Object> set, Class<T> tClass) {\n        if (CollectionUtils.isEmpty(set)) {\n            return new HashSet<>();\n        }\n\n        Set<T> result = new HashSet<>();\n\n        for (Object o : set) {\n            T t = obj2Obj(o, tClass);\n            if (t != null) {\n                result.add(t);\n            }\n        }\n\n        return result;\n    }\n\n    public static <T> List<T> list2List(List<? extends Object> list, Class<T> tClass) {\n        return list2List(list, tClass, (t) -> {\n        });\n    }\n\n    public static <T> List<T> list2List(List<? extends Object> list, Class<T> tClass, Consumer<T> consumer) {\n        if (CollectionUtils.isEmpty(list)) {\n            return Lists.newArrayList();\n        }\n\n        List<T> result = Lists.newArrayList();\n\n        for (Object object : list) {\n            T t = obj2Obj(object, tClass, consumer);\n            if (t != null) {\n                result.add(t);\n            }\n        }\n\n        return result;\n    }\n\n    /**\n     * 对象转换工具\n     * @param srcObj 元对象\n     * @param tgtClass 目标对象类\n     * @param <T> 泛型\n     * @return 目标对象\n     */\n    public static <T> T obj2Obj(final Object srcObj, Class<T> tgtClass) {\n        return obj2Obj(srcObj, tgtClass, (t) -> {\n        });\n    }\n\n    public static <T> T obj2Obj(final Object srcObj, Class<T> tgtClass, Consumer<T> consumer) {\n        if (srcObj == null) {\n            return null;\n        }\n\n        T tgt = null;\n        try {\n            tgt = tgtClass.newInstance();\n            BeanUtils.copyProperties(srcObj, tgt);\n            consumer.accept(tgt);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ConvertUtil||method=obj2Obj||msg={}\", e.getMessage());\n        }\n\n        return tgt;\n    }\n\n    public static <K, V> Map<K, V> mergeMapList(List<Map<K, V>> mapList) {\n        Map<K, V> result = Maps.newHashMap();\n        for (Map<K, V> map : mapList) {\n            result.putAll(map);\n        }\n        return result;\n    }\n\n    public static Map<String, Object> obj2Map(Object obj) {\n        if (null == obj) {\n            return null;\n        }\n\n        Map<String, Object> map = new HashMap<>();\n        Field[] fields = obj.getClass().getDeclaredFields();\n        for (Field field : fields) {\n            field.setAccessible(true);\n            try {\n                map.put(field.getName(), field.get(obj));\n            } catch (IllegalAccessException e) {\n                LOGGER.warn(\"class=ConvertUtil||method=obj2Map||msg={}\", e.getMessage(), e);\n            }\n        }\n        return map;\n    }\n\n    public static Object map2Obj(Map<String, Object> map, Class<?> clz) {\n        Object obj = null;\n        try {\n            obj = clz.newInstance();\n            Field[] declaredFields = obj.getClass().getDeclaredFields();\n            for (Field field : declaredFields) {\n                int mod = field.getModifiers();\n                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {\n                    continue;\n                }\n                field.setAccessible(true);\n                field.set(obj, map.get(field.getName()));\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ConvertUtil||method=map2Obj||msg={}\", e.getMessage(), e);\n        }\n\n        return obj;\n    }\n\n    /**\n     * string 用逗号分隔\n     * @param map  map\n     * @return     key1:value1, key2:value2\n     */\n    public static String map2String(Map<String, String> map) {\n        Set<String> keySet = map.keySet();\n        String[] keyArray = keySet.toArray(new String[0]);\n        Arrays.sort(keyArray);\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < keyArray.length; i++) {\n            if ((String.valueOf(map.get(keyArray[i]))).trim().length() > 0) {\n                sb.append(keyArray[i]).append(\":\").append(String.valueOf(map.get(keyArray[i])).trim());\n            }\n            if (i != keyArray.length - 1) {\n                sb.append(\",\");\n            }\n        }\n\n        return sb.toString();\n    }\n\n    public static Map<String, Double> sortMapByValue(Map<String, Double> map) {\n        List<Map.Entry<String, Double>> data = new ArrayList<>(map.entrySet());\n        data.sort((o1, o2) -> {\n            if ((o2.getValue() - o1.getValue()) > 0) {\n                return 1;\n            } else if ((o2.getValue() - o1.getValue()) == 0) {\n                return 0;\n            } else {\n                return -1;\n            }\n        });\n\n        Map<String, Double> result = Maps.newLinkedHashMap();\n\n        for (Entry<String, Double> next : data) {\n            result.put(next.getKey(), next.getValue());\n        }\n        return result;\n    }\n\n    public static Map<String, Object> directFlatObject(JSONObject obj) {\n        Map<String, Object> ret = new HashMap<>();\n\n        if (obj == null) {\n            return ret;\n        }\n\n        for (Map.Entry<String, Object> entry : obj.entrySet()) {\n            String key = entry.getKey();\n            Object o = entry.getValue();\n\n            if (o instanceof JSONObject) {\n                Map<String, Object> m = directFlatObject((JSONObject) o);\n                for (Map.Entry<String, Object> e : m.entrySet()) {\n                    ret.put(key + \".\" + e.getKey(), e.getValue());\n                }\n            } else {\n                ret.put(key, o);\n            }\n        }\n\n        return ret;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/DSLSearchUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.alibaba.fastjson.JSONObject;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 2021-10-28\n */\npublic class DSLSearchUtils {\n\n    private static final String QUERY_BOOL_MUST_TERM       = \"\\\"term\\\":\";\n    private static final String QUERY_BOOL_MUST_TERMS      = \"\\\"terms\\\":\";\n    private static final String QUERY_BOOL_MUST_TERM_VALUE = \"\\\"value\\\":\";\n    private static final String QUERY_BOOL_MUST_PREFIX     = \"\\\"prefix\\\":\";\n    private static final String QUERY_BOOL_MUST_RANGE      = \"\\\"range\\\":\";\n    private static final String QUERY_BOOL_MUST_WILDCARD   = \"\\\"wildcard\\\":\";\n    private static final String PLACE_HOLDER               = \"\\\"%s\\\":\";\n\n    private static final String QUERY_BOOL_MUST_RANGE_GTE  = \"\\\"gte\\\":\";\n    private static final String QUERY_BOOL_MUST_RANGE_LTE  = \"\\\"lte\\\":\";\n\n    /**\n     * 工具类不支持使用构造方法\n     */\n    private DSLSearchUtils() {\n        throw new IllegalStateException(\"Utility class\");\n    }\n\n    /**\n     * 构建范围查询子条件\n     * @param gteValue 大于\n     * @param lteValue 小于\n     * @param termKey 字段\n     * @return dsl\n     */\n    public static String getTermCellForRangeSearch(Object gteValue, Object lteValue, String termKey) {\n        if ((gteValue == null && lteValue == null) || AriusObjUtils.isBlack(termKey)) {\n            return null;\n        }\n\n        StringBuilder rangeSb = new StringBuilder();\n        rangeSb.append(\"{\").append(QUERY_BOOL_MUST_RANGE).append(\"{\").append(String.format(PLACE_HOLDER, termKey))\n            .append(\"{\");\n        if (gteValue != null) {\n            rangeSb.append(QUERY_BOOL_MUST_RANGE_GTE).append(gteValue);\n        }\n        if (lteValue != null) {\n            if (gteValue != null) {\n                rangeSb.append(\",\");\n            }\n            rangeSb.append(QUERY_BOOL_MUST_RANGE_LTE).append(lteValue);\n        }\n        rangeSb.append(\"}\").append(\"}\").append(\"}\");\n        return rangeSb.toString();\n    }\n\n    /**\n     * 构建精确查询子条件\n     *\n     * 返回样例：\n     * {\n     *           \"term\": {\n     *             \"health\": {\n     *               \"value\": \"green\"\n     *             }\n     *           }\n     *         }\n     * @param term     值（String）\n     * @param termKey  键\n     * @return\n     */\n    public static String getTermCellForExactSearch(String term, String termKey) {\n        if (AriusObjUtils.isBlack(term) || AriusObjUtils.isBlack(termKey)) {\n            return null;\n        }\n\n        StringBuilder termSb = new StringBuilder();\n        termSb.append(\"{\").append(QUERY_BOOL_MUST_TERM).append(\"{\").append(String.format(PLACE_HOLDER, termKey))\n            .append(\"{\").append(QUERY_BOOL_MUST_TERM_VALUE).append(\"\\\"\").append(term).append(\"\\\"\").append(\"}\")\n            .append(\"}\").append(\"}\");\n        return termSb.toString();\n    }\n\n    /**\n     * 构建精确查询子条件\n     * 返回样例：\n     *\n     * {\n     *   \"term\": {\n     *       \"projectId\": {\n     *            \"value\": 123\n     *           }\n     *     }\n     *  }\n     * @param term     值（Integer）\n     * @param termKey  键\n     * @return\n     */\n    public static String getTermCellForExactSearch(Integer term, String termKey) {\n        if (term == null || AriusObjUtils.isBlack(termKey)) {\n            return null;\n        }\n\n        StringBuilder termSb = new StringBuilder();\n        termSb.append(\"{\").append(QUERY_BOOL_MUST_TERM).append(\"{\").append(String.format(PLACE_HOLDER, termKey))\n            .append(\"{\").append(QUERY_BOOL_MUST_TERM_VALUE).append(\"\\\"\").append(term).append(\"\\\"\").append(\"}\")\n            .append(\"}\").append(\"}\");\n        return termSb.toString();\n    }\n\n    /**\n     * 构建精确查询子条件\n     * 返回样例：\n     * {\n     *   \"term\": {\n     *       \"projectId\": {\n     *            \"value\": true\n     *           }\n     *     }\n     *  }\n     * @param term       值（Boolean）\n     * @param termKey    键\n     * @return\n     */\n    public static String getTermCellForExactSearch(Boolean term, String termKey) {\n        if (term == null || AriusObjUtils.isBlack(termKey)) {\n            return null;\n        }\n\n        StringBuilder termSb = new StringBuilder();\n        termSb.append(\"{\").append(QUERY_BOOL_MUST_TERM).append(\"{\").append(String.format(PLACE_HOLDER, termKey))\n            .append(\"{\").append(QUERY_BOOL_MUST_TERM_VALUE).append(term).append(\"}\").append(\"}\").append(\"}\");\n\n        return termSb.toString();\n    }\n\n    /**\n     * 批量构建精确查询子条件\n     * 返回样例：\n     * {\n     *   \"terms\": {\n     *     \"cluster\": [\n     *       \"logi-elasticsearch-7.6.0\",\n     *       \"dc-cluster\",\n     *       \"dc-es02\"\n     *     ]\n     *   }\n     * }\n     * @param termList  值\n     * @param termsKey  键\n     * @return\n     */\n    public static String getTermCellsForExactSearch(List<String> termList, String termsKey) {\n        if (CollectionUtils.isEmpty(termList) || AriusObjUtils.isBlack(termsKey)) {\n            return null;\n        }\n\n        StringBuilder termSb = new StringBuilder();\n        termSb.append(\"{\").append(QUERY_BOOL_MUST_TERMS).append(\"{\").append(String.format(PLACE_HOLDER, termsKey))\n            .append(\"[\");\n        for (int i = 0; i < termList.size(); i++) {\n            termSb.append(\"\\\"\").append(termList.get(i)).append(\"\\\"\");\n            if (i != termList.size() - 1) {\n                termSb.append(\",\");\n            }\n        }\n        termSb.append(\"]\").append(\"}\").append(\"}\");\n\n        return termSb.toString();\n    }\n\n    /**\n     * 构建最右匹配查询子条件\n     * 返回样例：\n     *  {\n     *    \"wildcard\": {\n     *      \"index\": {\n     *        \"value\": \"test*\"\n     *      }\n     *    }\n     *  }\n     *\n     * @param term    值\n     * @param termKey 键\n     * @return\n     */\n    public static String getTermCellForPrefixSearch(String term, String termKey) {\n        if (AriusObjUtils.isBlack(term) || AriusObjUtils.isBlack(termKey)) {\n            return null;\n        }\n\n        StringBuilder termSb = new StringBuilder();\n        if (StringUtils.isNotBlank(term)) {\n            termSb.append(\"{\").append(QUERY_BOOL_MUST_PREFIX).append(\"{\").append(String.format(PLACE_HOLDER, termKey))\n                .append(\"{\").append(QUERY_BOOL_MUST_TERM_VALUE).append(\"\\\"\").append(term).append(\"\\\"\").append(\"}\")\n                .append(\"}\").append(\"}\");\n        }\n\n        return termSb.toString();\n    }\n\n    /**\n     * 构建term的模糊查询条件\n     * {\n     *   \"wildcard\": {\n     *     \"index\": {\n     *       \"value\": \"*my_index*\"\n     *     }\n     *   }\n     * }\n     * @param term 值\n     * @param termKey 键\n     * @return\n     */\n    public static String getTermCellForWildcardSearch(String term, String termKey) {\n        if (AriusObjUtils.isBlack(term) || AriusObjUtils.isBlack(termKey)) {\n            return null;\n        }\n        StringBuilder termSb = new StringBuilder();\n        if (StringUtils.isNotBlank(term)) {\n            termSb.append(\"{\").append(QUERY_BOOL_MUST_WILDCARD).append(\"{\").append(String.format(PLACE_HOLDER, termKey))\n                .append(\"{\").append(QUERY_BOOL_MUST_TERM_VALUE).append(\"\\\"\").append(\"*\").append(term).append(\"*\")\n                .append(\"\\\"\").append(\"}\").append(\"}\").append(\"}\");\n        }\n        return termSb.toString();\n    }\n\n    /**\n     *\n     * @param aggType  聚合算子类型：avg, count, sum, min, max 等\n     * @param field    字段名称\n     * @return         返回的聚合项\n     * eg:\n     * {\n     *     \"avg\":{\n     *         \"field\":\"totalCost\"\n     *     }\n     * }\n     */\n    public static JSONObject buildAggItem(String aggType, String field) {\n        JSONObject aggTypeJson = new JSONObject();\n        JSONObject fieldJson = new JSONObject();\n        fieldJson.put(\"field\", field);\n        aggTypeJson.put(aggType, fieldJson);\n        return aggTypeJson;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/DateTimeUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/1/21 下午5:09\n * @modified By D10865\n */\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.time.*;\nimport java.time.format.DateTimeFormatter;\nimport java.time.temporal.ChronoUnit;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.commons.lang3.time.DateUtils;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Maps;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/8/29 上午10:37\n * @Modified By\n */\npublic class DateTimeUtil {\n\n    private static final ILog           LOGGER            = LogFactory.getLog(DateTimeUtil.class);\n\n    private static final String         REGEX             = \"\\\\d{4}-\\\\d{2}-\\\\d{2}\";\n    private static final String         PATTERN_1         = \"yyyy-MM-dd\";\n    private static final String         PATTERN_2         = \"yyyy-MM-dd HH:mm:ss.SSS Z\";\n    private static final String         PATTERN_3         = \"yyyy-MM-dd HH:mm:ss\";\n\n    // 不同日期格式的正则匹配\n    private static Map<String, Pattern> dateFormatPattern = Maps.newHashMap();\n\n    private DateTimeUtil() {\n    }\n\n    static {\n        dateFormatPattern.put(\"_YYYY-MM\", Pattern.compile(\"\\\\d{4}-\\\\d{2}\"));\n        dateFormatPattern.put(\"_YYYYMM\", Pattern.compile(\"\\\\d{6}\"));\n        dateFormatPattern.put(\"_yyyyMM\", Pattern.compile(\"\\\\d{6}\"));\n\n        dateFormatPattern.put(\"YYYYMMdd\", Pattern.compile(\"\\\\d{8}\"));\n        dateFormatPattern.put(\"_YYYYMMdd\", Pattern.compile(\"\\\\d{8}\"));\n        dateFormatPattern.put(\"_YYYY-MM-dd\", Pattern.compile(REGEX));\n        dateFormatPattern.put(\"__YYYY-MM-dd\", Pattern.compile(REGEX));\n        dateFormatPattern.put(\"_yyyyMMdd\", Pattern.compile(REGEX));\n        dateFormatPattern.put(\"_yyyy-MM-dd\", Pattern.compile(REGEX));\n\n        // 除了定义的可以还有\n        dateFormatPattern.put(\"YYYY_MM_dd\", Pattern.compile(\"\\\\d{4}_\\\\d{2}_\\\\d{2}\"));\n    }\n\n    public static String getDateStr(long time) {\n        SimpleDateFormat sdf = new SimpleDateFormat(PATTERN_1);\n        return sdf.format(new Date(time));\n    }\n\n    public static String getDateStr(Date date) {\n        SimpleDateFormat sdf = new SimpleDateFormat(PATTERN_1);\n        return sdf.format(date);\n    }\n\n    public static Long getTime(String date) {\n        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(PATTERN_1);\n        if (StringUtils.isBlank(date)) {\n            date = dateTimeFormatter.format(ZonedDateTime.now().minus(1, ChronoUnit.DAYS));\n        }\n        LocalDate localDate = LocalDate.parse(date, dateTimeFormatter);\n        ZoneId zone = ZoneId.systemDefault();\n        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();\n        return instant.toEpochMilli();\n    }\n\n    public static Long getTimeEpochMilli(String date) {\n        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(PATTERN_3);\n        try {\n            return simpleDateFormat.parse(date).getTime();\n        } catch (ParseException e) {\n            LOGGER.error(\"class=DateTimeUtil||method=getTimeEpochMilli||date={}||errMsg={}\", date, e.getMessage());\n        }\n        return 0L;\n    }\n\n    public static Date getBeforeDays(Date time, int before) {\n        if (time == null) {\n            return null;\n        }\n        if (before < 1) {\n            return null;\n        }\n\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        c.set(Calendar.DATE, c.get(Calendar.DATE) - before);\n\n        return c.getTime();\n    }\n\n    /**\n     * 获取索引日期\n     *\n     * @param date\n     * @return\n     */\n    public static String getIndexDate(String indexName, String date, String dateFormat) {\n        if (StringUtils.isBlank(date)) {\n            return null;\n        }\n        if (StringUtils.isBlank(dateFormat)) {\n            return null;\n        }\n\n        String indexDate = date;\n        // 月日方式, 添加年份\n        if (\"MMdd\".equals(dateFormat)) {\n            indexDate = String.valueOf(LocalDate.now().getYear()).concat(date);\n            dateFormat = \"YYYYMMdd\";\n        }\n        // 去掉下划线\n        if (dateFormat.contains(\"_\")) {\n            indexDate = date.substring(1);\n        }\n\n        // 使用正则提取时间\n        Pattern pattern = dateFormatPattern.get(dateFormat);\n        if (pattern == null) {\n            LOGGER.error(\"class=DateTimeUtil||method=getIndexDate||msg={} can't find pattern dateFormat {}, date {}\",\n                indexName, dateFormat, date);\n            return indexDate;\n        }\n\n        try {\n            Matcher matcher = pattern.matcher(indexDate);\n            if (matcher.find()) {\n                return matcher.group();\n            }\n\n            // 这里可能由于之前时间格式做过修改，历史索引名称和目前时间格式不匹配\n            for (Pattern p : dateFormatPattern.values()) {\n                matcher = p.matcher(indexDate);\n\n                if (matcher.find()) {\n                    return matcher.group();\n                }\n            }\n            LOGGER.error(\"class=DateTimeUtil||method=getIndexDate||msg={} dateFormat {} not match date {}\", indexName,\n                dateFormat, date);\n\n        } catch (Exception e) {\n            LOGGER.error(\"class=DateTimeUtil||method=getIndexDate||msg=fail to getIndexDate {}, {}, {}\", indexName,\n                dateFormat, date, e);\n        }\n\n        return indexDate;\n    }\n\n    /**\n     * 是否在指定时间之前\n     *\n     * @param formatDateTime\n     * @param dayOffset\n     * @return\n     */\n    public static boolean isBeforeDateTime(String formatDateTime, int dayOffset) {\n        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(PATTERN_2);\n        ZonedDateTime markDateTime = ZonedDateTime.parse(formatDateTime, dateTimeFormatter);\n        ZonedDateTime expectDateTime = ZonedDateTime.now().minus(dayOffset, ChronoUnit.DAYS);\n\n        return markDateTime.isBefore(expectDateTime);\n    }\n\n    public static String getDateTimeStr(long time) {\n        SimpleDateFormat sdf = new SimpleDateFormat(PATTERN_3);\n        return sdf.format(new Date(time));\n    }\n\n    /**\n     * 是否在指定时间之前\n     *\n     * @param date\n     * @param dayOffset\n     * @return\n     */\n    public static boolean isBeforeDateTime(Date date, int dayOffset) {\n        ZonedDateTime markDateTime = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());\n        ZonedDateTime expectDateTime = ZonedDateTime.now().minus(dayOffset, ChronoUnit.DAYS);\n\n        return markDateTime.isBefore(expectDateTime);\n    }\n\n    /**\n     * 是否在指定时间之后\n     *\n     * @param date\n     * @param dayOffset\n     * @return\n     */\n    public static boolean isAfterDateTime(Date date, int dayOffset) {\n        ZonedDateTime markDateTime = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());\n        ZonedDateTime expectDateTime = ZonedDateTime.now().minus(dayOffset, ChronoUnit.DAYS);\n\n        return markDateTime.isAfter(expectDateTime);\n    }\n\n    /**\n     * 获取当前格式化时间\n     *\n     * @return\n     */\n    public static String getCurrentFormatDateTime() {\n        String formatDateTime = DateTimeFormatter.ofPattern(PATTERN_2)\n            .format(ZonedDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.systemDefault()));\n\n        return formatDateTime;\n    }\n\n    /**\n     * 格式化时间\n     *\n     * @param timestamp\n     * @return\n     */\n    public static String formatTimestamp(long timestamp) {\n        Instant instant = Instant.ofEpochMilli(timestamp);\n        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());\n        return DateTimeFormatter.ofPattern(PATTERN_2).format(zonedDateTime);\n    }\n\n    /**\n     * 格式化时间\n     *\n     * @param timestamp\n     * @return\n     */\n    public static String formatTimestamp2(long timestamp) {\n        Instant instant = Instant.ofEpochMilli(timestamp);\n        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());\n        return DateTimeFormatter.ofPattern(\"yyyy-MM-dd'T'HH:mm:ssZ\").format(zonedDateTime);\n    }\n\n    /**\n     * 获取指定偏移日期的格式化结果\n     *\n     * @param offset\n     * @return\n     */\n    public static String getFormatDayByOffset(int offset) {\n        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(PATTERN_1);\n        return dateTimeFormatter.format(ZonedDateTime.now().minus(offset, ChronoUnit.DAYS));\n    }\n\n    public static String getFormatMonthByOffset(int offset) {\n        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(\"yyyy-MM\");\n        return dateTimeFormatter.format(ZonedDateTime.now().minus(offset, ChronoUnit.DAYS));\n    }\n\n    /**\n     * 获取格式化的昨天\n     *\n     * @param dateFormat\n     * @return\n     */\n    public static String getYesterdayDayByFormat(String dateFormat) {\n        try {\n            LocalDateTime dateTime = LocalDateTime.now().minusDays(1);\n            // 根据时间格式转换为格式化后的时间字符串\n            return DateTimeFormatter.ofPattern(dateFormat.replace(\"Y\", \"y\")).format(dateTime);\n        } catch (Exception e) {\n            LOGGER.error(\"class=DateTimeUtil||method=getYesterdayDayByFormat||errMsg=format date error {}. \",\n                dateFormat, e);\n            return null;\n        }\n    }\n\n    /**\n     * 获取格式化的上个月\n     *\n     * @param dateFormat\n     * @return\n     */\n    public static String getLastMonthDayByFormat(String dateFormat) {\n        try {\n            LocalDateTime dateTime = LocalDateTime.now().minusMonths(1);\n            // 根据时间格式转换为格式化后的时间字符串\n            return DateTimeFormatter.ofPattern(dateFormat.replace(\"Y\", \"y\")).format(dateTime);\n        } catch (Exception e) {\n            LOGGER.error(\"class=DateTimeUtil||method=getLastMonthDayByFormat||errMsg=format date error {}. \",\n                dateFormat, e);\n            return null;\n        }\n    }\n\n    /**\n     * 获取格式化的去年\n     *\n     * @param dateFormat\n     * @return\n     */\n    public static String getLastYearDayByFormat(String dateFormat) {\n        try {\n            LocalDateTime dateTime = LocalDateTime.now().minusYears(1);\n            // 根据时间格式转换为格式化后的时间字符串\n            return DateTimeFormatter.ofPattern(dateFormat.replace(\"Y\", \"y\")).format(dateTime);\n        } catch (Exception e) {\n            LOGGER.error(\"class=DateTimeUtil||method=getLastMonthDayByFormat||errMsg=format date error {}. \",\n                dateFormat, e);\n            return null;\n        }\n    }\n\n    /**\n     * 获取周几\n     *\n     * @param dateTime\n     * @return\n     */\n    public static Integer getDayOfWeek(LocalDateTime dateTime) {\n        return dateTime.getDayOfWeek().getValue();\n    }\n\n    public static Integer getDayOfCurrentMonth() {\n        Calendar now = Calendar.getInstance();\n\n        return now.get(Calendar.DAY_OF_MONTH);\n    }\n\n    /**\n     * 根据时间获取起始结束时间\n     *\n     * @param date\n     * @return\n     */\n    public static Tuple<String, String> getStartEndTimeByDate(String date) {\n        //计算时间范围\n        String startDate = \"\", endDate = \"\";\n        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(PATTERN_1);\n        if (StringUtils.isBlank(date)) {\n            date = dateTimeFormatter.format(ZonedDateTime.now().minus(1, ChronoUnit.DAYS));\n        }\n        LocalDate localDate = LocalDate.parse(date, dateTimeFormatter);\n        ZonedDateTime dateTime = ZonedDateTime.of(localDate, LocalDateTime.now().toLocalTime(), ZoneId.systemDefault());\n        endDate = dateTimeFormatter.format(dateTime.plus(1, ChronoUnit.DAYS));\n        startDate = dateTimeFormatter.format(dateTime);\n\n        return new Tuple<>(startDate, endDate);\n    }\n\n    /**\n     * 根据时间获取起始结束时间\n     *\n     * @param date\n     * @return\n     */\n    public static Tuple<String, String> getStartEndWeekTimeByDate(String date) {\n        String startDate = \"\", endDate = \"\";\n        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(PATTERN_1);\n        if (StringUtils.isBlank(date)) {\n            date = dateTimeFormatter.format(ZonedDateTime.now());\n        }\n        LocalDate localDate = LocalDate.parse(date, dateTimeFormatter);\n        ZonedDateTime dateTime = ZonedDateTime.of(localDate, LocalDateTime.now().toLocalTime(), ZoneId.systemDefault());\n        endDate = dateTimeFormatter.format(dateTime.plus(1, ChronoUnit.DAYS));\n        startDate = dateTimeFormatter.format(dateTime.minus(7, ChronoUnit.DAYS));\n\n        return new Tuple<>(startDate, endDate);\n    }\n\n    /**\n     * 获取时间范围\n     *\n     * @param ariusCreateTime\n     * @return\n     */\n    public static Tuple<Long, Long> getAriusCreateTimeRange(String ariusCreateTime) {\n        long startTimeMilli = System.currentTimeMillis() - 43200000;\n        long endTimeMilli = System.currentTimeMillis() + 43200000;\n        try {\n            ZonedDateTime dateTime = ZonedDateTime.parse(ariusCreateTime, DateTimeFormatter.ofPattern(PATTERN_2));\n            ZonedDateTime startDate = dateTime.minus(12, ChronoUnit.HOURS);\n            ZonedDateTime endDate = dateTime.plus(12, ChronoUnit.HOURS);\n            startTimeMilli = startDate.toInstant().toEpochMilli();\n            endTimeMilli = endDate.toInstant().toEpochMilli();\n        } catch (Exception e) {\n            LOGGER.error(\"class=DateTimeUtil||method=getAriusCreateTimeRange||msg=fail to parse data {}\",\n                ariusCreateTime, e);\n        }\n\n        return new Tuple<>(startTimeMilli, endTimeMilli);\n    }\n\n    /**\n     * 得到简化的时间格式\n     *\n     * @param date 例如2018-10-08 16:00:00.330 +0800\n     * @return\n     */\n    public static String getShortDay(String date) {\n        int index = date.indexOf(\" \");\n        if (index > 0) {\n            return date.substring(0, index);\n        }\n        return date;\n    }\n\n    /**\n     * 获取某天凌晨的时间\n     * @param time\n     * @return\n     */\n    public static Date getZeroDate(Date time, int offset) {\n        if (time == null) {\n            time = new Date();\n        }\n\n        Calendar c = Calendar.getInstance();\n        c.setTime(time);\n        c.set(Calendar.DATE, c.get(Calendar.DATE) - offset);\n\n        Date offsetDate = c.getTime();\n\n        offsetDate = DateUtils.setHours(offsetDate, 0);\n        offsetDate = DateUtils.setMinutes(offsetDate, 0);\n        offsetDate = DateUtils.setSeconds(offsetDate, 0);\n        offsetDate = DateUtils.setMilliseconds(offsetDate, 0);\n        return offsetDate;\n    }\n\n    public static long getCurrentMonthEnd() {\n        Calendar c = Calendar.getInstance();\n        c.add(Calendar.MONTH, 0);\n\n        int currentMonthMaxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);\n\n        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), currentMonthMaxDay, 23, 59, 59);\n        return c.getTimeInMillis();\n    }\n\n    public static long getCurrentMonthStart() {\n        Calendar c = Calendar.getInstance();\n        c.add(Calendar.MONTH, 0);\n        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), 1, 00, 00, 00);\n        return c.getTimeInMillis();\n    }\n\n    public static long getLastMonthEnd() {\n        Calendar c = Calendar.getInstance();\n        c.add(Calendar.MONTH, -1);\n\n        int lastMonthMaxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);\n\n        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), lastMonthMaxDay, 23, 59, 59);\n        return c.getTimeInMillis();\n    }\n\n    public static long getLastMonthStart() {\n        Calendar c = Calendar.getInstance();\n        c.add(Calendar.MONTH, -1);\n        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), 1, 00, 00, 00);\n        return c.getTimeInMillis();\n    }\n\n    /**\n     * 获取到当前时间戳，按分钟对齐\n     * @return\n     */\n    public static long getCurrentTimestampMinute() {\n        long timeStamp = System.currentTimeMillis() / 1000;\n        long seconds = timeStamp % 60;\n        if (seconds >= 30) {\n            timeStamp = timeStamp - seconds + 60;\n        } else {\n            timeStamp = timeStamp - seconds;\n        }\n\n        return timeStamp;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/DiffUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.JSONPath;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.github.difflib.text.DiffRow;\nimport com.github.difflib.text.DiffRowGenerator;\nimport com.github.fge.jsonpatch.diff.JsonDiff;\nimport com.google.common.collect.Lists;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport java.util.stream.StreamSupport;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * json 对象或者文本的diff工具类\n *\n * @author shizeying\n * @date 2022/07/09\n */\npublic final class DiffUtil {\n    private static ObjectMapper mapper = new ObjectMapper();\n\n    public static List<Diff> diffJson(String expectedJsonStr, String actualJsonStr) throws Exception {\n        return diffJson(expectedJsonStr, actualJsonStr, null, null, null);\n    }\n\n    public static List<Diff> diffJson(String expectedJsonStr, String actualJsonStr,\n                                      String extractJsonPath) throws Exception {\n        return diffJson(expectedJsonStr, actualJsonStr, extractJsonPath, null, null);\n    }\n\n    public static List<Diff> diffJson(String expectedJsonStr, String actualJsonStr,\n                                      List<String> excludeJsonPaths) throws Exception {\n        return diffJson(expectedJsonStr, actualJsonStr, null, null, excludeJsonPaths);\n    }\n\n    public static List<Diff> diffJson(String expectedJsonStr, String actualJsonStr, String extractJsonPath,\n                                      List<String> excludeFields, List<String> excludeJsonPaths) throws Exception {\n        if (expectedJsonStr == null) {\n            throw new Exception(\"Expected string is null\");\n        } else if (actualJsonStr == null) {\n            throw new Exception(\"Actual string is null\");\n        } else if (expectedJsonStr.equals(actualJsonStr)) {\n            return Collections.emptyList();\n        }\n        Object expected = JSON.parse(expectedJsonStr);\n        Object actual = JSON.parse(actualJsonStr);\n\n        //  根据JsonPath提取指定的对比内容\n        if (extractJsonPath != null && !extractJsonPath.isEmpty()) {\n            //  根据JsonPath获取的内容进行对比\n            if (!JSONPath.contains(expected, extractJsonPath)) {\n                throw new Exception(String.format(\"Expected string not found jsonPath: %s\", extractJsonPath));\n            } else if (!JSONPath.contains(actual, extractJsonPath)) {\n                throw new Exception(String.format(\"Actual string not found jsonPath: %s\", extractJsonPath));\n            }\n            expected = JSONPath.eval(expected, extractJsonPath);\n            actual = JSONPath.eval(actual, extractJsonPath);\n        }\n\n        //  移除符合JsonPath的属性\n        if (excludeJsonPaths != null && !excludeJsonPaths.isEmpty()) {\n            for (String path : excludeJsonPaths) {\n                JSONPath.remove(expected, path);\n                JSONPath.remove(actual, path);\n            }\n        }\n        //  移除符合的字段属性\n        if (excludeFields != null && !excludeFields.isEmpty()) {\n            removeField(expected, excludeFields);\n            removeField(actual, excludeFields);\n        }\n\n        List<Diff> result = new ArrayList<>();\n        compareJSON(\"\", expected, actual, result);\n        return result;\n    }\n\n    public static List<Diff> diffJson(JSONObject expected, JSONObject actual) {\n        List<Diff> result = new ArrayList<>();\n        compareJSON(\"\", expected, actual, result);\n        return result;\n    }\n\n    public static List<Diff> diffJson(JSONArray expected, JSONArray actual) {\n        List<Diff> result = Lists.newArrayList();\n        compareJSON(\"\", expected, actual, result);\n        return result;\n    }\n\n    private static void compareJSON(String prefix, Object expected, Object actual, List<Diff> result) {\n        if ((expected instanceof JSONObject) && (actual instanceof JSONObject)) {\n            compareJSONObject(prefix, (JSONObject) expected, (JSONObject) actual, result);\n        } else if ((expected instanceof JSONArray) && (actual instanceof JSONArray)) {\n            compareJSONArray(prefix, (JSONArray) expected, (JSONArray) actual, result);\n        } else {\n            compareValue(prefix, expected, actual, result);\n        }\n    }\n\n    private static void compareValue(String prefix, Object expectedValue, Object actualValue, List<Diff> result) {\n        if (expectedValue == null && actualValue == null) {\n            return;\n        } else if (expectedValue != null && expectedValue.equals(actualValue)) {\n            return;\n        }\n        addError(result, prefix, DiffEnum.CHANGE, expectedValue, actualValue);\n    }\n\n    private static void compareJSONArray(String prefix, JSONArray expected, JSONArray actual, List<Diff> result) {\n        // 预期或实际值某个为空时，结果则为错误\n        if ((expected.size() < 1 || actual.size() < 1) && expected.size() != actual.size()) {\n            addError(result, prefix, DiffEnum.CHANGE, expected, actual);\n            return;\n        }\n        for (int i = 0; i < expected.size(); i++) {\n            String arrayPrefix = String.format(\"[%d]\", i);\n            compareJSON(qualify(prefix, arrayPrefix), expected.get(i), actual.get(i), result);\n        }\n    }\n\n    private static void compareJSONObject(String prefix, JSONObject expected, JSONObject actual, List<Diff> result) {\n        Set<String> expectedKeys = expected.keySet();\n        for (String key : expectedKeys) {\n            //  预期的key在实际对象中不存在\n            if (!actual.containsKey(key)) {\n                addError(result, qualify(prefix, key), DiffEnum.MISSING, expected.get(key), actual.get(key));\n                continue;\n            }\n            compareJSON(qualify(prefix, key), expected.get(key), actual.get(key), result);\n        }\n    }\n\n    private static String qualify(String prefix, String key) {\n        return \"\".equals(prefix) ? key : prefix + \".\" + key;\n    }\n\n    private static void addError(List<Diff> result, String field, DiffEnum type, Object expected, Object actual) {\n        if (result == null) {\n            return;\n        }\n        Diff diff = new Diff.DiffBuilder().source(expected).target(actual).field(field)\n            .type(type.name().toLowerCase(Locale.ROOT)).build();\n        result.add(diff);\n    }\n\n    private static void removeField(Object json, List<String> fields) {\n        if (json instanceof JSONArray) {\n            JSONArray jsonArray = (JSONArray) json;\n            for (int i = 0; i < jsonArray.size(); i++) {\n                removeField(jsonArray.get(i), fields);\n            }\n        } else if (json instanceof JSONObject) {\n            JSONObject jsonObject = (JSONObject) json;\n            //  先移除符合的字段\n            for (String field : fields) {\n                jsonObject.remove(field);\n            }\n            //  再遍历剩下字段，继续下一层级的移除\n            Set<String> keys = jsonObject.keySet();\n            for (String key : keys) {\n                removeField(jsonObject.get(key), fields);\n            }\n        }\n    }\n\n    public static List<Diff> diffDBData(String expectJsonStr, Map<String, Object> actualDbData) throws Exception {\n        String actualDbJson = JSON.toJSONString(actualDbData, SerializerFeature.WriteMapNullValue);\n        return diffJson(expectJsonStr, actualDbJson);\n    }\n\n    public static List<Diff> diffDBData(String expectJsonStr, List<Map<String, Object>> actualDbList) throws Exception {\n        String actualDbJson = JSON.toJSONString(actualDbList, SerializerFeature.WriteMapNullValue);\n        return diffJson(expectJsonStr, actualDbJson);\n    }\n\n    public static List<Diff> diffDBData(String expectJsonStr, Map<String, Object> expectMap,\n                                        Map<String, Object> actualMap) throws Exception {\n        //  先移除值含有sql函数的对象\n        for (Map.Entry<String, Object> entry : expectMap.entrySet()) {\n            String field = entry.getKey();\n            if (String.valueOf(entry.getValue()).indexOf(\"()\") > 0) {\n                expectMap.remove(field, entry.getValue());\n            }\n        }\n        //  合并\n        Map map = JSON.parseObject(expectJsonStr, Map.class);\n        if (map != null && !map.isEmpty()) {\n            expectMap.putAll(map);\n        }\n        String expectJson = JSON.toJSONString(expectMap);\n        String actualJson = JSON.toJSONString(actualMap);\n        return diffJson(expectJson, actualJson);\n    }\n\n    public static List<DiffRow> diffRowsByString(String original, String revised, String separatorChars) {\n        List<String> originalList = Lists.newArrayList(StringUtils.split(original, separatorChars));\n        List<String> revisedList = Lists.newArrayList(StringUtils.split(revised, separatorChars));\n        //行比较器，原文件删除的内容用\"~\"包裹，对比文件新增的内容用\"**\"包裹\n        DiffRowGenerator generator = DiffRowGenerator.create().showInlineDiffs(true).inlineDiffByWord(true)\n            .reportLinesUnchanged(true).replaceOriginalLinefeedInChangesWithSpaces(true).ignoreWhiteSpaces(true)\n            .mergeOriginalRevised(true).build();\n\n        return generator.generateDiffRows(originalList, revisedList);\n    }\n\n    public static List<DiffJson> diffJsonByString(String original, String revised) {\n        JsonNode source = readJson(original);\n        JsonNode target = readJson(revised);\n        JsonNode jsonNode = JsonDiff.asJson(source, target);\n        return StreamSupport.stream(jsonNode.spliterator(), false)\n            .map(node -> new DiffJson.DiffJsonBuilder().path(node.get(\"path\").asText()).op(node.get(\"op\").asText())\n                .value(Objects.nonNull(node.get(\"value\")) ? getNode(node.get(\"value\")) : null).build())\n            .collect(Collectors.toList());\n    }\n\n    private static JsonNode readJson(String content) {\n        try {\n            return mapper.readTree(content);\n        } catch (IOException ignore) {\n            return mapper.createObjectNode();\n        }\n    }\n\n    private static Object getNode(JsonNode jsonNode) {\n        return jsonNode.isBoolean() ? jsonNode.booleanValue()\n            : jsonNode.isNumber() ? jsonNode.numberValue() : jsonNode.asText();\n    }\n\n    public enum DiffEnum {\n                          MISSING, CHANGE;\n    }\n\n    @Data\n    @Builder\n    @NoArgsConstructor\n    @AllArgsConstructor\n    public static class Diff {\n\n        /**\n         * 变化的字段\n         */\n        private Object field;\n        /**\n         * 类型\n         */\n        private Object type;\n        /**\n         * 原始\n         */\n        private Object source;\n        /**\n         * 实际\n         */\n        private Object target;\n    }\n\n    @Data\n    @Builder\n    @NoArgsConstructor\n    @AllArgsConstructor\n    public static class DiffJson {\n\n        private String op;\n\n        private String path;\n\n        private Object value;\n\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/DslTermUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 3/23/22\n */\n\npublic class DslTermUtil {\n    private DslTermUtil() {\n    }\n\n    public static String buildTermsDslByIndexList(List<String> indexList) {\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < indexList.size(); i++) {\n            if (i == 0) {\n                sb.append(\"[\");\n            }\n            sb.append(\"\\\"\").append(indexList.get(i)).append(\"\\\"\");\n            if (i != indexList.size() - 1) {\n                sb.append(\",\");\n            }\n            if (i == indexList.size() - 1) {\n                sb.append(\"]\");\n            }\n        }\n        return sb.toString();\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/ESVersionUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport static java.util.regex.Pattern.compile;\n\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\nimport org.apache.commons.lang3.StringUtils;\n\npublic class ESVersionUtil {\n    public static final String                                   VERSION_PREFIX_PATTERN                      = \"^\\\\d*.\\\\d*\";\n    private ESVersionUtil() {\n    }\n\n    /**\n     * 判断是不是标准的es版本号，如：6.6.1.1000 或者 6.6.1\n     * @param version\n     * @return\n     */\n    public static boolean isValid(String version) {\n        if (StringUtils.isBlank(version)) {\n            return false;\n        }\n\n        String[] vers = version.split(\"\\\\.\");\n        if (null == vers) {\n            return false;\n        }\n\n        for (String ver : vers) {\n            if (!ver.chars().allMatch(Character::isDigit)) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * 获取当前版本的es版本号\n     * @param version 版本名称\n     * @return 版本长度\n     */\n    public static int getVersionLength(String version) {\n        if (StringUtils.isBlank(version)) {\n            return 0;\n        }\n\n        return version.split(\"\\\\.\").length;\n    }\n\n    /**\n     * 判断下version1是不是比version2的版本高\n     * @param version1\n     * @param version2\n     * @return\n     */\n    public static boolean isHigher(String version1, String version2) {\n        if (!isValid(version1) || !isValid(version2)) {\n            return false;\n        }\n\n        String[] vers1 = version1.split(\"\\\\.\");\n        String[] vers2 = version2.split(\"\\\\.\");\n\n        //小版本兼容\n        List<String> vers1List = Lists.newArrayList(vers1);\n        List<String> vers2List = Lists.newArrayList(vers2);\n\n        int vers1Size = vers1List.size();\n        int vers2Size = vers2List.size();\n\n        if (vers1Size > vers2Size) {\n            for (int i = 0; i < vers1Size - vers2Size; i++) {\n                vers2List.add(\"0\");\n            }\n        }\n\n        if (vers2Size > vers1Size) {\n            for (int i = 0; i < vers2Size - vers1Size; i++) {\n                vers1List.add(\"0\");\n            }\n        }\n        int ver1Count = 0, ver2Count = 0;\n        for (int i = 0; i < vers1List.size(); i++) {\n            int number = i == (vers1List.size() - 1) ? 1 : (100000000 / (int) Math.pow(100, i));\n            ver1Count = ver1Count + Integer.parseInt(vers1List.get(i)) * number;\n            ver2Count = ver2Count + Integer.parseInt(vers2List.get(i)) * number;\n        }\n        return ver1Count >= ver2Count;\n    }\n    \n    /**\n     * 比较大版本一致性 小版本之间是属于相同的版本：7.6.0==7.6.1 大版本之前的版本是不同的：7.6.0！=7.5.0\n     *\n     * @param esVersion1 7.6.x\n     * @param esVersion2 7.6.x\n     * @return boolean    true\n     */\n    public static Boolean compareBigVersionConsistency(String esVersion1, String esVersion2) {\n        if (StringUtils.isBlank(esVersion1) || StringUtils.isBlank(esVersion2)) {\n            return Boolean.FALSE;\n        }\n        if (StringUtils.equals(esVersion1, esVersion2)) {\n            return Boolean.TRUE;\n        }\n        return StringUtils.equals(getESBigVersion(esVersion1), getESBigVersion(esVersion2));\n    }\n    \n    /**\n     * 获取es的大版本前缀\n     *\n     * @param esVersion\n     * @return {@link String}\n     */\n    private static String getESBigVersion(String esVersion) {\n        Pattern pattern = compile(VERSION_PREFIX_PATTERN);\n        final Matcher matcher = pattern.matcher(esVersion);\n        if (matcher.find()) {\n            return matcher.group(0);\n        }\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/EnvUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.DataCenterEnum;\n\npublic class EnvUtil {\n\n    private static EnvType        type = EnvType.TEST;\n\n    private static DataCenterEnum dc   = DataCenterEnum.CN;\n\n    public static boolean isOnline() {\n        return type == EnvType.ONLINECN;\n    }\n\n    public static boolean isPre() {\n        return type == EnvType.PRECN;\n    }\n\n    public static boolean isDev() {\n        return type == EnvType.DEV;\n    }\n\n    public static boolean isPressure() {\n        return type == EnvType.PRESSURE;\n    }\n\n    public static boolean isTest() {\n        return type == EnvType.TEST;\n    }\n\n    public static boolean isStable() {\n        return type == EnvType.STABLE;\n    }\n\n    public static boolean isCN() {\n        return dc == DataCenterEnum.CN;\n    }\n\n    public static DataCenterEnum getDC() {\n        return dc;\n    }\n\n    public static String getStr() {\n        return type.getStr() + \"-\" + dc.getCode();\n    }\n\n    /**\n     * 设置加载的活跃的profile文件\n     */\n    public static void setLoadActiveProfiles(String[] activeProfiles) {\n        if (activeProfiles == null || activeProfiles.length == 0) {\n            return;\n        }\n\n        for (String profile : activeProfiles) {\n            if (profile.contains(\"dev\") || profile.contains(\"integration\")) {\n                type = EnvType.DEV;\n            } else if (profile.contains(\"test\")) {\n                type = EnvType.TEST;\n            } else if (profile.contains(\"stable\")) {\n                type = EnvType.STABLE;\n            } else if (profile.contains(\"pressure\")) {\n                type = EnvType.PRESSURE;\n            } else if (profile.contains(\"pre\")) {\n                type = EnvType.PRECN;\n            } else if (profile.contains(\"online\")) {\n                type = EnvType.ONLINECN;\n            }\n\n            if (profile.contains(\"us01\")) {\n                dc = DataCenterEnum.US01;\n            }\n        }\n    }\n\n    /**\n     * 根据环境信息获取写入索引名称\n     *\n     * @param indexName\n     * @return\n     */\n    public static String getWriteIndexNameByEnv(String indexName) {\n        if (isPre()) {\n            return \"pre_\".concat(indexName);\n        }\n\n        return indexName;\n    }\n\n    public enum EnvType {\n                         DEV(\"dev\"), TEST(\"test\"), STABLE(\"stable\"), PRECN(\"pre\"), PRESSURE(\"pressure\"), ONLINECN(\"online\");\n\n        private String str;\n\n        private EnvType(String str) {\n            this.str = str;\n        }\n\n        public String getStr() {\n            return str;\n        }\n\n        public static EnvType getByStr(String str) {\n            for (EnvType type : EnvType.values()) {\n                if (type.str.equalsIgnoreCase(str)) {\n                    return type;\n                }\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/EventRetryExecutor.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.BaseException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.EventException;\n\nimport java.util.function.Predicate;\n\n/**\n * 事件重试器\n *  1、重试的睡眠时间为10ms\n *  2、操作返回false,这里直接返回false，表示操作没有成功\n *  3、若事件没有操作成功则会重试，重试次数为3次，超过3次不再重试\n *  4、事件重试器会对所有异常进行判断，若为异常则重试，超过重试次数仍然出现异常则抛出\n *  5、操作返回true,这里直接返回true，不再重试\n *\n * @author wx\n * @date 2022/10/13\n */\npublic class EventRetryExecutor {\n    private static final int SEC_1 = 1000;\n\n    private EventRetryExecutor() {\n    }\n\n    /**\n     * 定制事件重试方法，不对返回判断重试\n     */\n    public static <T> T eventRetryExecute(String methodName, RetryExecutor.Handler<T> handler, int retryTimes) throws EventException {\n        return eventRetryExecuteInner(methodName, handler, retryTimes);\n    }\n\n    /**************************************** private method ***************************************************/\n    private static <T> T eventRetryExecuteInner(String methodName, RetryExecutor.Handler<T> handler,\n                                                int retryTimes) throws EventException {\n        try {\n            final RetryExecutor<T> retryExecutor = RetryExecutor.builder().name(methodName).retryCount(retryTimes)\n                    .handler(new RetryExecutor.Handler() {\n                        @Override\n                        public T process() throws BaseException {\n                            return handler.process();\n                        }\n\n                        @Override\n                        public boolean needExceptionRetry(Exception e) {\n                            return e instanceof EventException;\n                        }\n\n                        @Override\n                        public int retrySleepTime(int retryTimes) {\n                            return SEC_1;\n                        }\n                    });\n            return retryExecutor.execute();\n        } catch (Exception e){\n            throw new EventException(e.getMessage(), e);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/FutureUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.*;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.observability.Observability;\nimport com.google.common.collect.Lists;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.lucene.util.NamedThreadFactory;\n\n@NoArgsConstructor\npublic class FutureUtil<T> {\n    private static final ILog                             LOGGER        = LogFactory.getLog(FutureUtil.class);\n\n    private ExecutorService                            executor;\n    private String                                        name;\n\n    private Map<Long/*currentThreadId*/, List<Future<T>>> futuresMap;\n\n    public final static FutureUtil<Void>                  DEAULT_FUTURE = FutureUtil.init(\"default\");\n\n    public void setExecutor(ExecutorService executor) {\n        this.executor = executor;\n    }\n\n    public ExecutorService getExecutor() {\n        return executor;\n    }\n\n    public void setFuturesMap(Map<Long, List<Future<T>>> futuresMap) {\n        this.futuresMap = futuresMap;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public static <T> FutureUtil<T> init(String name, int corePoolSize, int maxPoolSize, int queueSize) {\n        FutureUtil<T> futureUtil = new FutureUtil<>();\n\n        ExecutorService exe = Observability.wrap(new ThreadPoolExecutor(corePoolSize, maxPoolSize, 3000, TimeUnit.MILLISECONDS,\n                new LinkedBlockingDeque<>(queueSize), new NamedThreadFactory(\"Arius-admin-FutureUtil-\" + name),\n                new ThreadPoolExecutor.DiscardOldestPolicy()));//对拒绝任务不抛弃，而是抛弃队列里面等待最久的一个线程，然后把拒绝任务加到队列。\n\n        futureUtil.setExecutor(exe);\n        futureUtil.setName(name);\n        futureUtil.setFuturesMap(new ConcurrentHashMap<>());\n        return futureUtil;\n    }\n\n    /**\n     * 根据系统处理器的数目创建线程池\n     *\n     * @param name\n     * @param queueSize\n     * @param <T>\n     * @return\n     */\n    public static <T> FutureUtil<T> initBySystemAvailableProcessors(String name, int queueSize) {\n        int processorsNum = Runtime.getRuntime().availableProcessors();\n        if (processorsNum >= 3) {\n            return init(name, processorsNum, processorsNum, queueSize);\n        }\n        return init(name, 3, 3, queueSize);\n    }\n\n    /**\n     * 不能在其他方法中调用此方法, 会导致不停创建线程池\n     */\n    public static <T> FutureUtil<T> init(String name) {\n        return FutureUtil.init(name, 5, 5, 100);\n    }\n\n    /**\n     * 必须配合 waitResult使用 否则容易会撑爆内存\n     * @param callable\n     * @return\n     */\n    public FutureUtil<T> callableTask(Callable<T> callable) {\n        Long currentThreadId = Thread.currentThread().getId();\n\n        List<Future<T>> futures = futuresMap.get(currentThreadId);\n        if (CollectionUtils.isEmpty(futures)) {\n            futures = Lists.newCopyOnWriteArrayList();\n        }\n\n        futures.add(executor.submit(callable));\n        futuresMap.put(currentThreadId, futures);\n        return this;\n    }\n\n    /**\n     * 必须配合 waitExecute使用 否则容易会撑爆内存\n     * @param runnable\n     * @return\n     */\n    public FutureUtil<T> runnableTask(Runnable runnable) {\n        Long currentThreadId = Thread.currentThread().getId();\n\n        List<Future<T>> futures = futuresMap.get(currentThreadId);\n        if (CollectionUtils.isEmpty(futures)) {\n            futures = Lists.newCopyOnWriteArrayList();\n        }\n\n        futures.add((Future<T>) executor.submit(runnable));\n        futuresMap.put(currentThreadId, futures);\n        return this;\n    }\n\n    public void waitExecute(long timeOutSeconds) {\n        Long currentThreadId = Thread.currentThread().getId();\n\n        List<Future<T>> currentFutures = futuresMap.get(currentThreadId);\n\n        if (CollectionUtils.isEmpty(currentFutures)) {\n            return;\n        }\n\n        //CopyOnWriteArrayList 不支持迭代器进行remove 会抛出java.lang.UnsupportedOperationException\n        for (Future<T> f : currentFutures) {\n            try {\n                f.get(timeOutSeconds, TimeUnit.SECONDS);\n            } catch (Exception e) {\n                f.cancel(true);\n                LOGGER.error(\"class=FutureUtil||method=waitExecute||msg=exception\", e);\n            } finally {\n                currentFutures.remove(f);\n            }\n        }\n\n        if (CollectionUtils.isEmpty(currentFutures)) {\n            futuresMap.remove(currentThreadId);\n        }\n\n        LOGGER.debug(\"class=FutureUtil||method={}||futuresSize={}||msg=all future excu done!\", name, currentFutures.size());\n\n    }\n\n    /**\n     * 带有错误容忍的waitExecute，当连续有超过continuousFailThres 个任务失败时\n     * 则认为这一堆任务不稳定，终止并清空\n     * @param timeOutSeconds 单个任务超时上限\n     * @param continuousFailThres 连续失败任务数量上限\n     */\n    public void waitExecuteWithErrorTolerance(long timeOutSeconds, int continuousFailThres) {\n        Long currentThreadId = Thread.currentThread().getId();\n        List<Future<T>> currentFutures = futuresMap.get(currentThreadId);\n        boolean lastFail = false;\n        int failCnt = 0;\n        if (CollectionUtils.isEmpty(currentFutures)) {\n            return;\n        }\n        for (Future<T> f : currentFutures) {\n            try {\n                if (lastFail && failCnt >= continuousFailThres) {\n                    throw new Exception(\"exceed error tolerance upper bound\");\n                }\n                f.get(timeOutSeconds, TimeUnit.SECONDS);\n                lastFail = false;\n                failCnt = 0;\n            } catch (Exception e) {\n                lastFail = true;\n                failCnt += 1;\n                f.cancel(true);\n                LOGGER.error(\"class=FutureUtil||method=waitExecute||msg=exception\", e);\n            } finally {\n                currentFutures.remove(f);\n            }\n        }\n\n        if (CollectionUtils.isEmpty(currentFutures)) {\n            futuresMap.remove(currentThreadId);\n        }\n\n        LOGGER.debug(\"class=FutureUtil||method={}||futuresSize={}||msg=all future excu done!\", name,currentFutures.size());\n\n    }\n\n    public void waitExecute() {\n        waitExecute(30);\n    }\n\n    public List<T> waitResult(long timeOutSeconds) {\n        Long currentThreadId = Thread.currentThread().getId();\n\n        List<Future<T>> currentFutures = futuresMap.get(currentThreadId);\n\n        List<T> list = Lists.newCopyOnWriteArrayList();\n\n        if (CollectionUtils.isEmpty(currentFutures)) {\n            return list;\n        }\n\n        for (Future<T> f : currentFutures) {\n            try {\n                T t = f.get(timeOutSeconds, TimeUnit.SECONDS);\n                if (t != null) {\n                    list.add(t);\n                }\n            } catch (Exception e) {\n                f.cancel(true);\n                LOGGER.error(\"class=FutureUtil||method=waitResult||msg=exception\", e);\n            } finally {\n                currentFutures.remove(f);\n            }\n        }\n\n        if (CollectionUtils.isEmpty(currentFutures)) {\n            futuresMap.remove(currentThreadId);\n        }\n\n        LOGGER.debug(\"class=FutureUtil||method={}||futuresSize={}||msg=all future excu done!\", name,currentFutures.size());\n        return list;\n    }\n\n    public List<T> waitResult() {\n        return waitResult(30);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/Getter.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n *\n * @author d06679\n * @date 2019/3/21\n */\npublic class Getter {\n\n    private Getter() {\n    }\n\n    private static final ILog LOGGER = LogFactory.getLog(Getter.class);\n\n    public static <T> T withDefault(T value, T defaultValue) {\n        if (value != null) {\n            return value;\n        }\n        return defaultValue;\n    }\n\n    public static String strWithDefault(Object value, String defaultValue) {\n        if (value != null) {\n            return String.valueOf(value);\n        }\n        return defaultValue;\n    }\n\n    /**\n     *\n     * @param fileName\n     * @return\n     */\n    public static String getHtmlFileInJarFile(String fileName) {\n        InputStream inputStream = Getter.class.getClassLoader().getResourceAsStream(fileName);\n        if (inputStream != null) {\n            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));\n            String line = null;\n            StringBuilder stringBuilder = new StringBuilder(\"\");\n            try {\n                while ((line = bufferedReader.readLine()) != null) {\n                    stringBuilder.append(line);\n                }\n                return stringBuilder.toString();\n            } catch (IOException e) {\n                LOGGER.error(\"class=Getter||method=readMailHtmlFileInJarFile||errMsg=read file {} error. \", fileName,\n                    e);\n                return \"\";\n            } finally {\n                try {\n                    inputStream.close();\n                } catch (IOException e) {\n                    LOGGER.error(\"class=Getter||method=readMailHtmlFileInJarFile||errMsg=fail to close file {} error. \",\n                        fileName, e);\n                }\n            }\n        } else {\n            LOGGER.error(\n                \"class=Getter||class=MailTool||method=readMailHtmlFileInJarFile||errMsg=fail to read file {} content\",\n                fileName);\n            return \"\";\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/HttpHostUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didiglobal.knowframework.log.util.HostUtil;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.http.HttpHost;\n\nimport java.util.ArrayList;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.COMMA;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/8/30 上午10:56\n * @Modified By\n */\npublic class HttpHostUtil {\n\n    private HttpHostUtil() {\n    }\n\n    public static final String HOST_NAME = HostUtil.getHostName();\n\n    /**\n     * 根据ip地址和端口获取HttpHost\n     *\n     * @param address\n     * @param port\n     * @return\n     */\n    public static HttpHost[] getHttpHostArray(String address, int port) {\n        ArrayList<HttpHost> hosts = Lists.newArrayList();\n        for (String host : StringUtils.splitByWholeSeparatorPreserveAllTokens(address, COMMA)) {\n            hosts.add(new HttpHost(host, port));\n        }\n        HttpHost[] hostArr = new HttpHost[hosts.size()];\n        hostArr = hosts.toArray(hostArr);\n        return hostArr;\n    }\n\n    /**\n     * 根据ip地址和端口获取HttpHost\n     *\n     * @param address\n     * @return\n     */\n    public static HttpHost[] getHttpHostArray(String address) {\n        ArrayList<HttpHost> hosts = Lists.newArrayList();\n\n        if (StringUtils.isBlank(address)) {\n            return new HttpHost[] {};\n        }\n\n        String[] httpAddressArray = StringUtils.splitByWholeSeparatorPreserveAllTokens(address, COMMA);\n        for (String hostAndPort : httpAddressArray) {\n            String[] httpAddressAndPortArray = StringUtils.splitByWholeSeparatorPreserveAllTokens(hostAndPort, \":\");\n            if (httpAddressAndPortArray != null && httpAddressAndPortArray.length == 2) {\n                hosts.add(new HttpHost(httpAddressAndPortArray[0], Integer.valueOf(httpAddressAndPortArray[1])));\n            }\n        }\n        HttpHost[] hostArr = new HttpHost[hosts.size()];\n        hostArr = hosts.toArray(hostArr);\n        return hostArr;\n    }\n\n    /**\n     * 获取HttpHost和url base\n     *\n     * @param url  http://100.69.238.11:8000/arius-admin/admin\n     * @return\n     */\n    public static Tuple<HttpHost, String> getHttpHostAndBaseUrl(String url) {\n        int port = 8080;\n        String httpHost = \"\";\n        String baseUrl = \"\";\n        // 构建查询客户端\n        int portStartIndex = url.lastIndexOf(\":\");\n        if (portStartIndex > 0) {\n            httpHost = url.substring(0, portStartIndex).replace(\"http://\", \"\");\n            int portEndIndex = url.substring(portStartIndex).indexOf(\"/\", 0);\n            if (portEndIndex > 0) {\n                baseUrl = url.substring(portStartIndex + portEndIndex);\n                port = Integer.valueOf(url.substring(portStartIndex + 1, portStartIndex + portEndIndex));\n            }\n        }\n\n        return new Tuple<>(new HttpHost(httpHost, port), baseUrl);\n    }\n\n    //从类似10.179.100.148:9300的地址中获取端口\n    public static String getPortFromTransportAddress(String transportAddress) {\n        if (StringUtils.isBlank(transportAddress)) {\n            return \"\";\n        }\n\n        String[] strTemp = transportAddress.split(\":\");\n        if (null == strTemp || 2 != strTemp.length) {\n            return \"\";\n        }\n\n        return strTemp[1];\n    }\n\n    //从类似10.179.100.148:9300的地址中获取ip\n    public static String getIpFromTransportAddress(String transportAddress) {\n        if (StringUtils.isBlank(transportAddress)) {\n            return \"\";\n        }\n\n        String[] strTemp = transportAddress.split(\":\");\n        if (null == strTemp || 2 != strTemp.length) {\n            return \"\";\n        }\n\n        return strTemp[0];\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/IndexNameFactory.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * @author d06679\n * @date 2019/4/3\n */\npublic class IndexNameFactory {\n\n    private IndexNameFactory() {\n    }\n\n    private static final ILog    LOGGER             = LogFactory.getLog(IndexNameFactory.class);\n\n    private static final Pattern INDEX_NAME_PATTERN = Pattern.compile(\"(.*)(_v[1-9]\\\\d*)(.*)\");\n\n    public static List<String> appendSuffix(List<String> indices, String suffix) {\n        if (indices == null) {\n            return new ArrayList<>();\n        }\n\n        return indices.stream().map(index -> index + suffix).collect(Collectors.toList());\n\n    }\n\n    /**\n     * 生成带版本号的索引名字\n     * @param expression 表达式\n     * @param dateFormat 时间格式\n     * @param days 天数\n     * @param version  版本号\n     * @return\n     */\n    public static String get(String expression, String dateFormat, Integer days, Integer version) {\n        String indexName = getNoVersion(expression, dateFormat, days);\n        if (version > 0) {\n            indexName = indexName + \"_v\" + version;\n        }\n        return indexName;\n    }\n\n    /**\n     * 生成某一天的索引\n     * @param expression 表达式\n     * @param dateFormat 时间格式\n     * @param days 天数, 负数表示是之前某一天的索引,正数表示是之后某一天的索引\n     * @return 索引名字\n     */\n    public static String getNoVersion(String expression, String dateFormat, Integer days) {\n\n        String result = \"\";\n\n        if (!expression.endsWith(\"*\")) {\n            result = expression;\n        } else {\n\n            if (StringUtils.isBlank(dateFormat)) {\n                LOGGER.warn(\"class=IndexNameFactory||method=getNoVersion||expression={}||msg=illegal date format\",\n                    expression);\n                dateFormat = \"_yyyy-MM-dd\";\n            }\n\n            Date now = new Date();\n            String indexDate = \"\";\n            if (days >= 0) {\n                indexDate = AriusDateUtils.date2Str(AriusDateUtils.getAfterDays(now, days), dateFormat);\n            } else {\n                indexDate = AriusDateUtils.date2Str(AriusDateUtils.getBeforeDays(now, -1 * days), dateFormat);\n            }\n            result = expression.replace(\"*\", \"\") + indexDate;\n        }\n\n        return result;\n    }\n\n    /**\n     * 滚动索引去除版本号\n     * @param indexName 索引名字\n     * @return 无版本号的索引名字  如果不匹配 返回空字符串\n     */\n    public static String genIndexNameClear(String indexName, String expression) {\n        if (indexName.equals(expression)) {\n            return indexName;\n        }\n\n        if (expression.endsWith(\"*\")) {\n            expression = expression.replace(\"*\", \"\");\n        }\n\n        if (indexName.equals(expression)) {\n            return indexName;\n        }\n\n        Matcher m = INDEX_NAME_PATTERN.matcher(indexName);\n        if (!m.find() || StringUtils.isNotBlank(m.group(3))) {\n            return indexName;\n        }\n        return m.group(1);\n    }\n\n    /**\n     * 校验是否与当前表示是匹配\n     * @param noVersionIndexName 索引名字\n     * @param expression 表达式\n     * @param dateFormat 时间格式\n     * @return 无版本号的索引名字  如果不匹配 返回空字符串\n     */\n    public static boolean noVersionIndexMatchExpression(String noVersionIndexName, String expression,\n                                                        String dateFormat) {\n        if (expression.endsWith(\"*\")) {\n            return noVersionIndexName.length() == (expression.length() - 1 + dateFormat.length());\n        }\n        return expression.equals(noVersionIndexName);\n    }\n\n    /**\n     * 校验是否与当前表示是匹配\n     * @param indexName 索引名字\n     * @param expression 表达式\n     * @param dateFormat 时间格式\n     * @return 无版本号的索引名字  如果不匹配 返回空字符串\n     */\n    public static boolean indexMatchExpression(String indexName, String expression, String dateFormat) {\n        return noVersionIndexMatchExpression(genIndexNameClear(indexName, expression), expression, dateFormat);\n    }\n\n    /**\n     * 获取索引所在的时间\n     * @param indexNameNoVersion 没有版本号的索引名字\n     * @param expression expression\n     * @param dateFormat dateFormat\n     * @return 时间\n     */\n    public static Date genIndexTimeByIndexName(String indexNameNoVersion, String expression, String dateFormat) {\n        String dateFormatyyyy = dateFormat.replace(\"Y\", \"y\");\n\n        if (dateFormatyyyy.contains(\"y\")) {\n            try {\n                SimpleDateFormat format = new SimpleDateFormat(dateFormatyyyy);\n                return format.parse(indexNameNoVersion.substring(expression.length() - 1));\n            } catch (Exception e) {\n                LOGGER.warn(\n                    \"class=IndexNameFactory||method=genIndexTimeByIndexName||expression={}||dateFormat{}||indexNameNoVersion={}\",\n                    expression, dateFormatyyyy, indexNameNoVersion);\n            }\n        } else {\n\n            Date now = new Date();\n\n            //单独处理没有年份的场景\n            //按着同一年计算  如果索引时间晚于当前时间5天则是去年的索引\n            String indexTimeStr = indexNameNoVersion.substring(expression.length() - 1);\n\n            //大部分场景都是在同一年的\n            dateFormatyyyy = \"yyyy\" + dateFormatyyyy;\n            indexTimeStr = AriusDateUtils.date2Str(now, \"yyyy\") + indexTimeStr;\n\n            try {\n                SimpleDateFormat format = new SimpleDateFormat(dateFormatyyyy);\n                Date indexTime = format.parse(indexTimeStr);\n\n                //如果索引时间不会晚于未来5天,则认为是与当前时间同一年的索引\n                if (indexTime.before(AriusDateUtils.getAfterDays(now, 4))) {\n                    return indexTime;\n                } else {\n                    return AriusDateUtils.getBeforeMonths(indexTime, 12);\n                }\n\n            } catch (Exception e) {\n                LOGGER.warn(\n                    \"class=IndexNameFactory||method=genIndexTimeByIndexName||expression={}||dateFormat{}||indexNameNoVersion={}\",\n                    expression, dateFormatyyyy, indexNameNoVersion);\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/IndexNameUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Set;\n\npublic class IndexNameUtils {\n\n    private IndexNameUtils() {\n    }\n\n    private static final String VERSION_TAG = \"_v\";\n\n    private static final Long   ONE_DAY     = 24 * 60 * 60 * 1000L;\n\n    public static String removeVersion(String indexName) {\n        if (indexName == null || indexName.length() < VERSION_TAG.length()) {\n            return indexName;\n        }\n\n        int i = indexName.lastIndexOf(VERSION_TAG);\n        if (i < 0) {\n            return indexName;\n        }\n\n        String numStr = indexName.substring(i + VERSION_TAG.length());\n        try {\n            if (numStr.startsWith(\"+\") || numStr.startsWith(\"-\")) {\n                return indexName;\n            }\n\n            Long.valueOf(numStr);\n        } catch (Exception t) {\n            return indexName;\n        }\n\n        return indexName.substring(0, i);\n    }\n\n    public static String genCurrentDailyIndexName(String templateName) {\n        return templateName + \"_\" + DateTimeUtil.getFormatDayByOffset(0);\n    }\n\n    public static String genCurrentMonthlyIndexName(String templateName) {\n        return templateName + \"_\" + DateTimeUtil.getFormatMonthByOffset(0);\n    }\n\n    public static String genIndexNameWithVersion(String indexName, Integer version) {\n        if (version == null || version <= 0) {\n            return indexName;\n        }\n        return indexName + \"_v\" + version;\n    }\n\n    public static String genDailyIndexNameWithVersion(String templateName, int offsetDay, Integer version) {\n        return genIndexNameWithVersion(genDailyIndexName(templateName, offsetDay), version);\n    }\n\n    public static String genCurrentMonthlyIndexNameWithVersion(String templateName, Integer version) {\n        return genIndexNameWithVersion(genCurrentMonthlyIndexName(templateName), version);\n    }\n\n    public static String genDailyIndexName(String templateName, int offsetDay) {\n        return templateName + \"_\" + DateTimeUtil.getFormatDayByOffset(offsetDay);\n    }\n\n    //startDate、endDate 毫秒\n    public static String genDailyIndexName(String templateName, Long startDate, Long endDate) {\n        if (startDate > endDate) {\n            return templateName + \"_\" + DateTimeUtil.getFormatDayByOffset(0);\n        }\n\n        long currentDate = System.currentTimeMillis();\n        long offsetFromStart = (currentDate - startDate) / ONE_DAY + 1;\n        long offsetFromEnd = (currentDate - endDate) / ONE_DAY;\n\n        List<String> indexList = new ArrayList<>();\n        for (; offsetFromStart >= offsetFromEnd; offsetFromStart--) {\n            indexList.add(templateName + \"_\" + DateTimeUtil.getFormatDayByOffset((int) offsetFromStart));\n        }\n\n        return StringUtils.join(indexList, \",\");\n    }\n\n    public static boolean indexExpMatch(String index, String exp) {\n\n        if (StringUtils.isBlank(index)) {\n            return false;\n        }\n\n        if (StringUtils.isBlank(exp)) {\n            return false;\n        }\n\n        int indexPointer = 0;\n        int expPointer = 0;\n\n        while (expPointer < exp.length()) {\n            char expC = exp.charAt(expPointer);\n\n            if (expC == '*') {\n                expPointer++;\n                boolean expPointerEnd = true;\n                while (expPointer < exp.length()) {\n                    expC = exp.charAt(expPointer);\n                    if (expC != '*') {\n                        expPointerEnd = false;\n                        break;\n                    }\n\n                    expPointer++;\n                }\n\n                // * is the last char in exp\n                if (expPointerEnd) {\n                    return true;\n                }\n\n                int nextStar = exp.indexOf('*', expPointer);\n                String expInter = null;\n                if (nextStar < 0) {\n                    expInter = exp.substring(expPointer);\n                } else {\n                    expInter = exp.substring(expPointer, nextStar);\n                }\n\n                int indexPos = index.indexOf(expInter, indexPointer);\n                if (indexPos <= 0) {\n                    return false;\n                }\n\n                expPointer = expPointer + expInter.length();\n                indexPointer = indexPos + expInter.length();\n\n            } else if (indexPointer < index.length()) {\n                char indexC = index.charAt(indexPointer);\n                if (indexC != expC) {\n                    // not the same, failed\n                    return false;\n                }\n\n                indexPointer++;\n                expPointer++;\n            } else {\n                return false;\n            }\n        }\n\n        if (indexPointer < index.length()) {\n            // index has chars left\n            return false;\n        } else {\n            // index also to end\n            return true;\n        }\n    }\n\n    /**\n     * 查询的索引名称是否匹配到索引模板\n     *\n     * @param searchIndexName\n     * @param templateExp\n     * @return\n     */\n    public static boolean isIndexNameMatchTemplateExp(final String searchIndexName, final String templateExp) {\n\n        if (StringUtils.isBlank(searchIndexName) || StringUtils.isBlank(templateExp)) {\n            return false;\n        }\n\n        String tmpTemplateExp = templateExp;\n\n        // 索引表达式不是以*结尾，单个索引没有分区\n        if (!tmpTemplateExp.endsWith(\"*\")) {\n            return isSearchIndexNameMatchNoExpTemplate(searchIndexName, tmpTemplateExp);\n        }\n\n        // 1. 去除索引模板表达式中的结尾*\n        tmpTemplateExp = StringUtils.removeEnd(tmpTemplateExp, \"*\");\n        // 2. 用*来切分查询使用的索引名称\n        String[] indexSplits = StringUtils.split(searchIndexName, \"*\");\n\n        if (indexSplits == null || indexSplits.length == 0) {\n            return false;\n        }\n\n        // 查询使用的索引名称不包含*\n        if (!searchIndexName.endsWith(\"*\") && indexSplits.length <= 1) {\n\n            String trimSearchIndexName = StringUtils.removeEnd(searchIndexName, \"*\");\n            // 去掉_vx版本号信息\n            String lastStr = removeIndexNameVersionIfHas(trimSearchIndexName);\n\n            // 去掉查询索引中的索引表达式部分\n            String leftStr = lastStr.replace(tmpTemplateExp, \"\");\n            if (StringUtils.isBlank(leftStr)) {\n                return true;\n            }\n\n            // 剩余的为时间\n            if (isNumbericOrSpecialChar(leftStr)) {\n                return true;\n            }\n\n            // 去掉_vx版本号信息\n            tmpTemplateExp = removeIndexNameVersionIfHas(tmpTemplateExp);\n            if (lastStr.equals(tmpTemplateExp)) {\n                return true;\n            }\n\n            return false;\n\n            // 查询使用的索引名称含有*，例如btb_b2b.crius*hna*_2019-03-07\n        } else {\n            String lastStr = indexSplits[indexSplits.length - 1];\n            // 去掉_vx版本号信息\n            lastStr = removeIndexNameVersionIfHas(lastStr);\n            indexSplits[indexSplits.length - 1] = lastStr;\n\n            // lastStr是日期,除掉最后一个进行匹配\n            if (isNumbericOrSpecialChar(lastStr)\n                && isMatchIndexPartPositiveSequence(tmpTemplateExp, indexSplits, indexSplits.length - 1)) {\n                return true;\n            }\n\n            // 去掉lastStr日期部分\n            lastStr = removeIndexNameDateIfHas(lastStr);\n            if (StringUtils.isBlank(lastStr)) {\n                if (isMatchIndexPartPositiveSequence(tmpTemplateExp, indexSplits, indexSplits.length - 1)) {\n                    return true;\n                } else {\n                    return false;\n                }\n\n            } else {\n                indexSplits[indexSplits.length - 1] = lastStr;\n                if (isMatchIndexPartPositiveSequence(tmpTemplateExp, indexSplits, indexSplits.length)) {\n                    return true;\n                } else {\n                    return false;\n                }\n            }\n        }\n    }\n\n    /**\n     * 部分索引切片匹配索引模板是否为正序\n     *\n     * 例如templateExp为ABCDEFG,partIndexName为AB,DE,FG。则匹配\n     *\n     * @param templateExp\n     * @param partIndexName\n     * @return\n     */\n    public static boolean isMatchIndexPartPositiveSequence(String templateExp, String[] partIndexName,\n                                                           int compareCount) {\n        // 存在子字符串序号\n        List<Integer> indexList = Lists.newArrayList();\n\n        for (int i = 0; i < partIndexName.length && i < compareCount; ++i) {\n            indexList.add(templateExp.indexOf(partIndexName[i]));\n        }\n\n        Integer lastIndex = null;\n        for (int i = 0; i < indexList.size(); ++i) {\n            // 不包含其中一个子串，则整体不匹配\n            if (indexList.get(i) < 0) {\n                return false;\n            }\n            if (lastIndex == null) {\n                lastIndex = indexList.get(i);\n            } else {\n                if (indexList.get(i) >= lastIndex) {\n                    lastIndex = indexList.get(i);\n                } else {\n                    // 后一个的序号小于前一个，则整体不匹配\n                    return false;\n                }\n            }\n        }\n\n        // 如果只有一个序号, 匹配部分为索引表达式中间\n        if (indexList.size() == 1 && indexList.get(0) > 0) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * 如果有版本号信息，则移除版本号字符串\n     *\n     * @param lastIndexNamePart\n     * @return\n     */\n    public static String removeIndexNameVersionIfHas(String lastIndexNamePart) {\n        // 是否含有_vx版本号数据\n        int index = lastIndexNamePart.lastIndexOf(\"_v\");\n        if (index > 0) {\n            // 去掉_v\n            String endStr = lastIndexNamePart.substring(index + 2);\n            // _v之后是不是数字\n            if (StringUtils.isNumeric(endStr)) {\n                // 是数字,去掉版本号\n                return lastIndexNamePart.substring(0, index);\n            }\n        }\n\n        return lastIndexNamePart;\n    }\n\n    /**\n     * 是否是数字或者特殊字符\n     *\n     * @param lastIndexNamePart\n     * @return\n     */\n    public static boolean isNumbericOrSpecialChar(String lastIndexNamePart) {\n        for (int i = 0; i < lastIndexNamePart.length(); ++i) {\n            char c = lastIndexNamePart.charAt(i);\n            // 是数字或者-,_\n            if (Character.isDigit(c) || c == '-' || c == '_') {\n                continue;\n            } else {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * 如果有日期信息，则移除日期\n     *\n     * @param lastIndexNamePart\n     * @return\n     */\n    public static String removeIndexNameDateIfHas(String lastIndexNamePart) {\n\n        int index = lastIndexNamePart.lastIndexOf(\"_\");\n        if (index >= 0) {\n            String endStr = lastIndexNamePart.substring(index + 1);\n            // 剩余部分是日期，则移除\n            if (isNumbericOrSpecialChar(endStr)) {\n                return lastIndexNamePart.substring(0, index);\n            }\n        } else {\n            if (isNumbericOrSpecialChar(lastIndexNamePart)) {\n                return \"\";\n            }\n        }\n\n        return lastIndexNamePart;\n    }\n\n    /**\n     * 查询索引是否匹配没有时间分区的索引模板表达式\n     *\n     * @param searchIndexName\n     * @param templateExp  索引表达式不带*\n     * @return\n     */\n    public static boolean isSearchIndexNameMatchNoExpTemplate(final String searchIndexName, final String templateExp) {\n\n        if (StringUtils.isBlank(searchIndexName) || StringUtils.isBlank(templateExp)) {\n            return false;\n        }\n\n        // 1. 用*来切分查询使用的索引名称\n        String[] indexSplits = StringUtils.split(searchIndexName, \"*\");\n\n        if (indexSplits == null || indexSplits.length == 0) {\n            return false;\n        }\n\n        // 查询使用的索引名称不包含*\n        if (!searchIndexName.endsWith(\"*\") && indexSplits.length <= 1) {\n            String trimSearchIndexName = StringUtils.removeEnd(searchIndexName, \"*\");\n            // 如果查询索引名称和索引表达式相同，例如arius.dsl.template -> arius.dsl.template\n            if (trimSearchIndexName.equals(templateExp)) {\n                return true;\n            } else {\n                return false;\n            }\n\n        } else {\n            // 查看*分隔之后最后一个分段\n\n            // 去掉_vx版本号信息\n            String lastStr = removeIndexNameVersionIfHas(indexSplits[indexSplits.length - 1]);\n            indexSplits[indexSplits.length - 1] = lastStr;\n\n            // *之后为空串\n            if (StringUtils.isBlank(lastStr)) {\n                // 各个分段进行匹配\n                if (isMatchIndexPartPositiveSequence(templateExp, indexSplits, indexSplits.length - 1)) {\n                    return true;\n                } else {\n                    return false;\n                }\n            }\n\n            // 如果lastStr包含_，而索引表达式不包含_\n            if (lastStr.contains(\"_\") && !templateExp.contains(\"_\")) {\n                return false;\n            }\n\n            // lastStr是日期\n            if (isNumbericOrSpecialChar(lastStr)) {\n                return false;\n            }\n\n            // 各个分段进行匹配\n            if (isMatchIndexPartPositiveSequence(templateExp, indexSplits, indexSplits.length)) {\n                return true;\n            } else {\n                return false;\n            }\n\n        }\n    }\n\n    /**\n     * 根据查询使用的索引模板匹配更多的索引模板\n     *\n     * @param indexName\n     * @param indexTemplateList\n     * @return\n     */\n    public static Set<String> matchIndexTemplateBySearchIndexName(String indexName,\n                                                                  List<IndexTemplatePhyWithLogic> indexTemplateList) {\n        Set<String> matchIndexTemplateNameSet = Sets.newTreeSet();\n        String tmpIndexName = indexName;\n        if (tmpIndexName != null && tmpIndexName.endsWith(\"*\")) {\n            tmpIndexName = StringUtils.removeEnd(tmpIndexName, \"*\");\n        }\n\n        for (IndexTemplatePhyWithLogic indexTemplate : indexTemplateList) {\n\n            // 匹配索引表达式\n            if (IndexNameUtils.isIndexNameMatchTemplateExp(indexName, indexTemplate.getExpression())) {\n                matchIndexTemplateNameSet.add(indexTemplate.getName());\n            }\n        }\n\n        return matchIndexTemplateNameSet;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/IndexSettingsUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONValidator;\nimport com.alibaba.fastjson.JSONValidator.Type;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexSettingVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESSettingConstant;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.elasticsearch.client.utils.JsonUtils;\nimport org.apache.commons.compress.utils.Sets;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class IndexSettingsUtil {\n    final static Set<String> ignoreSettings = Sets.newHashSet(\n            ESSettingConstant.INDEX_VERIFIED_BEFORE_CLOSE,\n            ESSettingConstant.INDEX_VERSION_CREATED,\n            ESSettingConstant.INDEX_VERSION,\n            ESSettingConstant.INDEX_UUID,\n            ESSettingConstant.INDEX_CREATION_DATE,\n            ESSettingConstant.INDEX_PROVIDED_NAME);\n\n    /**\n     * 排除忽视设置\n     *\n     * @param settings 设置\n     * @return {@link Map}<{@link String}, {@link String}>\n     */\n    public static Map<String, String> excludeIgnoreSettings(Map<String, String> settings) {\n        Map<String, String> result = new HashMap<>();\n        if (null != settings && !settings.isEmpty()) {\n            settings.forEach((key, val) -> {\n                if (!ignoreSettings.contains(key)) {\n                    result.put(key, val);\n                }\n            });\n        }\n        return result;\n    }\n\n    public static Map<String, String> getChangedSettings(Map<String, String> sourceSettings,\n                                                         Map<String, String> changedSettings) {\n        Map<String, String> result = new HashMap<>();\n        if (null != changedSettings && !changedSettings.isEmpty()) {\n            Map<String, String> finalSourceSettings = sourceSettings != null ? sourceSettings : new HashMap<>();\n            changedSettings.forEach((key, val) -> {\n                if (!StringUtils.equals(val, finalSourceSettings.get(key))) {\n                    result.put(key, val);\n                }\n            });\n        }\n        return excludeIgnoreSettings(result);\n    }\n    \n    /**\n     * > 检查设置是否不可变且正确\n     *\n     * @param setting 指标设置\n     * @param projectId 项目编号\n     */\n    public static void checkImmutableSettingAndCorrectSetting(String setting, IndexSettingVO indexSettingVO, Integer projectId) throws ESOperateException {\n        final JSONValidator from = JSONValidator.from(setting);\n        if (!(from.validate() && from.getType().equals(Type.Object))) {\n            throw new ESOperateException(\"不是正确的 setting\");\n        }\n        final Map<String, String> stringMap = JsonUtils.flat(JSON.parseObject(setting));\n        for (String key : stringMap.keySet()) {\n            if (StringUtils.startsWith(key, ESSettingConstant.INDEX_ROUTING_ALLOCATION_PREFIX) &&\n                    !AuthConstant.SUPER_PROJECT_ID.equals(projectId) &&\n                    !stringMap.get(key).equals(JsonUtils.flat(JSON.parseObject(indexSettingVO.getProperties().toJSONString())).get(key))\n            ) {\n                throw new ESOperateException(String.format(\"{%s}不允许修改\", key));\n            }\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/ListUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * @author arthur\n * @date 2019/7/30.\n */\npublic class ListUtils {\n\n    private ListUtils() {\n    }\n\n    // 分隔符\n    private static final String SEPARATOR = \",\";\n\n    public static List<Integer> string2IntList(String str) {\n\n        List<Integer> intList = new ArrayList<>();\n        if (StringUtils.isBlank(str)) {\n            return intList;\n        }\n\n        for (String elem : str.split(SEPARATOR)) {\n            if (StringUtils.isBlank(elem)) {\n                continue;\n            }\n            intList.add(Integer.valueOf(elem.trim()));\n        }\n        return intList;\n    }\n\n    public static List<Long> string2LongList(String str) {\n        List<Long> longList = new ArrayList<>();\n        if (StringUtils.isBlank(str)) {\n            return longList;\n        }\n\n        for (String elem : str.split(SEPARATOR)) {\n            if (StringUtils.isBlank(elem)) {\n                continue;\n            }\n            longList.add(Long.valueOf(elem.trim()));\n        }\n        return longList;\n    }\n\n    public static Set<String> string2StrSet(String str) {\n        List<String> strList = string2StrList(str);\n        return new HashSet<>(strList);\n    }\n\n    public static List<String> string2StrList(String str) {\n        List<String> strList = new ArrayList<>();\n        if (StringUtils.isBlank(str)) {\n            return strList;\n        }\n\n        for (String elem : str.split(SEPARATOR)) {\n            if (StringUtils.isBlank(elem)) {\n                continue;\n            }\n            strList.add(elem.trim());\n        }\n        return strList;\n    }\n\n    public static String longList2String(List<Long> longList) {\n        if (longList == null || longList.isEmpty()) {\n            return \"\";\n        }\n\n        longList = longList.stream().filter(Objects::nonNull).collect(Collectors.toList());\n\n        return StringUtils.join(longList, SEPARATOR);\n    }\n\n    public static String intList2String(List<Integer> intList) {\n        if (intList == null || intList.isEmpty()) {\n            return \"\";\n        }\n\n        intList = intList.stream().filter(Objects::nonNull).collect(Collectors.toList());\n\n        return StringUtils.join(intList, SEPARATOR);\n    }\n\n    public static String strList2String(List<String> strList) {\n        if (strList == null || strList.isEmpty()) {\n            return \"\";\n        }\n\n        strList = strList.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());\n\n        return StringUtils.join(strList, SEPARATOR);\n    }\n\n    public static String strSet2String(Set<String> strSet) {\n        if (strSet == null || strSet.isEmpty()) {\n            return \"\";\n        }\n\n        strSet = strSet.stream().filter(StringUtils::isNotBlank).collect(Collectors.toSet());\n\n        return StringUtils.join(strSet, SEPARATOR);\n    }\n\n    public static String[] strList2StringArray(List<String> strList) {\n        String[] stringArr = new String[strList.size()];\n        for (int i = 0; i < strList.size(); i++) {\n            stringArr[i] = strList.get(i);\n        }\n\n        return stringArr;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/MapUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class MapUtils {\n\n    private static final ILog LOGGER = LogFactory.getLog(MapUtils.class);\n\n    public static String findChanged(Map<String, String> src, Map<String, String> dest) {\n        if (src == null || dest == null) {\n            return \"\";\n        }\n\n        StringBuilder content = new StringBuilder(\"\");\n        try {\n            for (String key : src.keySet()) {\n                String destValue = dest.get(key);\n                String srcValue = src.get(key);\n                if (null != destValue) {\n                    if (!destValue.equals(srcValue)) {\n                        content.append(\"字段\").append(key).append(\"的原值\").append(\"【\").append(srcValue).append(\"】\")\n                            .append(\"修改为\").append(\"【\").append(destValue).append(\"】\").append(\"\\r\\n\");\n                    }\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=MapUtils||method=findChanged||errMsg={}\", e.getMessage(), e);\n        }\n        return content.toString();\n    }\n\n    public static Map<String, String> findChangedWithDestV(Map<String, String> src, Map<String, String> dest) {\n        Map<String, String> result = new HashMap<>();\n        if (src == null || dest == null) {\n            return result;\n        }\n        try {\n            for (String key : src.keySet()) {\n                String destValue = dest.get(key);\n                String srcValue = src.get(key);\n                if (null != destValue) {\n                    if (!destValue.equals(srcValue)) {\n                        result.put(key, destValue);\n                    }\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=MapUtils||method=findChanged||errMsg={}\", e.getMessage(), e);\n        }\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/MappingConfigUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.util.Map;\n\nimport org.apache.commons.collections4.MapUtils;\n\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.TypeDefine;\n\n/**\n * Created by linyunan on 3/22/22\n */\n\npublic class MappingConfigUtil {\n    private MappingConfigUtil() {\n    }\n\n    public static Integer countMappingFieldNum(MappingConfig mapping) {\n        if (null == mapping) {\n            return 0;\n        }\n\n        Map<String/*typeName*/, Map<String/*field*/, TypeDefine>> typeFieldTypeMap = mapping.getTypeDefines();\n        if (MapUtils.isEmpty(typeFieldTypeMap)) {\n            return 0;\n        }\n\n        int count = 0;\n        for (Map.Entry<String/*typeName*/, Map<String/*field*/, TypeDefine>> entry : typeFieldTypeMap.entrySet()) {\n            count += entry.getValue().keySet().size();\n        }\n        return count;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/MetricsUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.MetricsContentVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.Calendar;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.TimeZone;\n\n/**\n * Created by linyunan on 2021-08-05\n */\npublic class MetricsUtils {\n    /**\n     * 突增定义倍数 上个时间间隔请求数的两倍，\n     * 例子: 上一个时间间隔是 1000r/s  当前时间间隔是 2500 r/s 超过2000, 则定义为突增\n     */\n    private static final double UPRUSH_THRESHOLD = 2.0;\n\n    private static final long   ONE_HOUR         = 60 * 60 * 1000L;\n    private static final long   ONE_DAY          = 24 * 60 * 60 * 1000L;\n    private static final long   SEVEN_DAY        = 7 * 24 * 60 * 60 * 1000L;\n    private static final char   COLON            = ':';\n    private static final char   SPACE            = ' ';\n\n    /**\n     *   指标看板返回值中的时间间隔:\n     *   1小时            1min为一时间分片\n     *   1小时 ~ 24小时   20min为一时间分片\n     *   1天到7天         1h为一时间分片\n     *   7天以后          1h为一时间分片\n     * @param intervalTime     起始结束时间差值\n     * @return  返回dsl时间分隔值\n     */\n    public static String getInterval(Long intervalTime) {\n        if (intervalTime > 0 && intervalTime <= ONE_HOUR) {\n            return Interval.ONE_MIN.getStr();\n        } else if (intervalTime > ONE_HOUR && intervalTime <= ONE_DAY) {\n            return Interval.TWENTY_MIN.getStr();\n        } else if (intervalTime > ONE_DAY && intervalTime <= SEVEN_DAY) {\n            return Interval.ONE_HOUR.getStr();\n        } else if (intervalTime > SEVEN_DAY) {\n            return Interval.ONE_HOUR.getStr();\n        } else {\n            return Interval.ONE_HOUR.getStr();\n        }\n    }\n\n    /**\n     *   dashboard返回值中的时间间隔:\n     *   1小时            5min为一时间分片\n     *   1小时 ~ 24小时   20min为一时间分片\n     *   1天到7天         1h为一时间分片\n     *   7天以后          1h为一时间分片\n     * @param intervalTime     起始结束时间差值\n     * @return  返回dsl时间分隔值\n     */\n    public static String getIntervalForDashBoard(Long intervalTime) {\n        if (intervalTime > 0 && intervalTime <= ONE_HOUR) {\n            return Interval.FIVE_MIN.getStr();\n        } else if (intervalTime > ONE_HOUR && intervalTime <= ONE_DAY) {\n            return Interval.TWENTY_MIN.getStr();\n        } else if (intervalTime > ONE_DAY && intervalTime <= SEVEN_DAY) {\n            return Interval.ONE_HOUR.getStr();\n        } else if (intervalTime > SEVEN_DAY) {\n            return Interval.ONE_HOUR.getStr();\n        } else {\n            return Interval.ONE_HOUR.getStr();\n        }\n    }\n\n    /**\n     * 获取时间点对应聚合时间段\n     * @param intervalTime\n     * @param timePoint\n     * @return\n     */\n    public static Tuple<Long, Long> getSortInterval(Long intervalTime, long timePoint) {\n        Calendar cal = Calendar.getInstance();\n        cal.setTimeInMillis(timePoint);\n        cal.set(Calendar.SECOND, 0);\n        cal.set(Calendar.MILLISECOND, 0);\n        if (intervalTime > 0 && intervalTime <= ONE_HOUR) {\n            long tuple1 = cal.getTimeInMillis();\n            return new Tuple<>(tuple1 - 60 * 1000, tuple1);\n        } else if (intervalTime > ONE_HOUR && intervalTime <= ONE_DAY) {\n            int minute = cal.get(Calendar.MINUTE);\n            int start = 0;\n            int end = 20;\n            if (minute > 20 && minute <= 40) {\n                start = 20;\n                end = 40;\n            } else if (minute > 40 && minute <= 60) {\n                start = 40;\n                end = 60;\n            }\n            cal.set(Calendar.MINUTE, start);\n            long tuple1 = cal.getTimeInMillis();\n            cal.set(Calendar.MINUTE, end);\n            long tuple2 = cal.getTimeInMillis();\n            return new Tuple<>(tuple1, tuple2);\n        } else {\n            cal.set(Calendar.MINUTE, 0);\n            long tuple1 = cal.getTimeInMillis();\n            return new Tuple<>(tuple1, tuple1 + 60 * 60 * 1000);\n        }\n    }\n\n    public static Double getDoubleValuePerMin(String interval, String value) {\n        if (Interval.ONE_MIN.getStr().equals(interval)) {\n            return Double.valueOf(value);\n        } else if (Interval.TWENTY_MIN.getStr().equals(interval)) {\n            return Double.valueOf(value) / 20.00;\n        } else if (Interval.ONE_HOUR.getStr().equals(interval)) {\n            return Double.valueOf(value) / 60.00;\n        }\n        return Double.valueOf(value);\n    }\n\n    /**\n     * 判断是否需要单位转化，一般以_count结尾的指标都是累加的结果，需要单位转化。\n     * eg: 20分钟聚合的指标数据/20 = 个/min\n     * @return\n     */\n    public static boolean needConvertUnit(String aggKey) {\n        return aggKey.endsWith(\"_count\");\n    }\n\n    /**\n     * 计算一段时间内，时间分片\n     * @param startTime\n     * @param endTime\n     * @param interval\n     * @param dateUnit   Calendar.MINUTE||Calendar.SECOND||Calendar.HOUR\n     * @return\n     */\n    public static List<Long> timeRange(long startTime, long endTime, long interval, int dateUnit) {\n        long step = interval * 1000 * 60;\n        if (dateUnit == Calendar.HOUR) {\n            step = interval * 1000 * 60 * 60;\n        } else if (dateUnit == Calendar.SECOND) {\n            step = interval * 1000;\n        }\n        startTime = startTime / 1000 * 1000;\n        endTime = endTime / 1000 * 1000;\n        if (endTime < startTime) {\n            return new ArrayList<>(0);\n        }\n\n        List<Long> list = Lists.newArrayList();\n        while (endTime >= startTime) {\n            list.add(endTime);\n            endTime -= step;\n        }\n\n        return list;\n    }\n\n    public static double getAggMapDoubleValue(ESBucket esBucket, String key) {\n        return Optional.ofNullable(esBucket.getAggrMap().get(key)).map(x -> x.getUnusedMap().get(\"value\"))\n            .map(d -> Double.valueOf(d.toString())).orElse(0.0);\n    }\n\n    public static List<VariousLineChartMetricsVO> joinDuplicateTypeVOs(List<VariousLineChartMetricsVO> duplicatedVOs) {\n        List<VariousLineChartMetricsVO> result = new ArrayList<>();\n        Map<String, List<MetricsContentVO>> chartMetricsMap = new HashMap<>();\n        for (VariousLineChartMetricsVO vo : duplicatedVOs) {\n            if (!chartMetricsMap.containsKey(vo.getType())) {\n                chartMetricsMap.put(vo.getType(), vo.getMetricsContents());\n            } else {\n                chartMetricsMap.get(vo.getType()).addAll(vo.getMetricsContents());\n            }\n        }\n        for (Map.Entry<String, List<MetricsContentVO>> entry : chartMetricsMap.entrySet()) {\n            VariousLineChartMetricsVO variousLineChartMetricsVO = new VariousLineChartMetricsVO();\n            variousLineChartMetricsVO.setType(entry.getKey());\n            variousLineChartMetricsVO.setMetricsContents(entry.getValue());\n            result.add(variousLineChartMetricsVO);\n        }\n        return result;\n    }\n    \n    /**\n     * 获取每天下一个一个一分钟\n     *\n     * @param timeStamp 时间戳\n     * @return {@code Long}\n     */\n    public static Long getDailyNextOneMinute(Long timeStamp) {\n        Calendar calendar = Calendar.getInstance();\n        calendar.setTimeInMillis(timeStamp);\n        calendar.setTimeZone(TimeZone.getDefault());\n        calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) + 1);\n        return calendar.getTimeInMillis();\n    }\n\n    public enum Interval {\n                          ONE_MIN(\"1m\"), FIVE_MIN(\"5m\"), TWENTY_MIN(\"20m\"), ONE_HOUR(\"1h\");\n\n        private String str;\n\n        private Interval(String str) {\n            this.str = str;\n        }\n\n        public String getStr() {\n            return str;\n        }\n\n        public static MetricsUtils.Interval getByStr(String str) {\n            for (MetricsUtils.Interval type : MetricsUtils.Interval.values()) {\n                if (type.str.equalsIgnoreCase(str)) {\n                    return type;\n                }\n            }\n\n            return null;\n        }\n    }\n\n    /**\n     * 具体计算突增逻辑处\n     * @param currentTimeValue      当前采集值\n     * @param lastTimeValue         上次采集值\n     * @return\n     */\n    public static Double computerUprushNum(Double currentTimeValue, Double lastTimeValue) {\n        if (null == lastTimeValue || null == currentTimeValue) {\n            return 0d;\n        }\n\n        if (0 == lastTimeValue && 0 > currentTimeValue) {\n            return currentTimeValue;\n        }\n        if (0 == lastTimeValue && 0 < currentTimeValue) {\n            return 0d;\n        }\n\n        return (currentTimeValue / lastTimeValue) >= UPRUSH_THRESHOLD ? currentTimeValue : 0d;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/ParsingExceptionUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NullESClientException;\nimport com.didiglobal.knowframework.elasticsearch.client.model.exception.ESAlreadyExistsException;\nimport com.didiglobal.knowframework.elasticsearch.client.model.exception.ESIndexNotFoundException;\nimport com.didiglobal.knowframework.elasticsearch.client.model.exception.ESIndexTemplateMissingException;\nimport java.io.IOException;\nimport java.net.ConnectException;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.concurrent.ExecutionException;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.util.EntityUtils;\nimport org.elasticsearch.client.ResponseException;\nimport org.elasticsearch.common.util.concurrent.UncategorizedExecutionException;\n\n/**\n *  `ParsingExceptionUtils` 是一个实用程序类，提供解析异常的方法\n *\n * @author shizeying\n * @date 2022/08/17\n */\npublic final class ParsingExceptionUtils {\n    private static final String CONNECTION_REFUSED=\"Connection refused\";\n    private static final String CONNECTION_CLOSE=\"远程主机强迫关闭了一个现有的连接。\";\n    public static final String CLUSTER_ERROR = \"当前操作集群异常\";\n    public static final String CONNECT_EXCEPTION = \"connect_exception\";\n    private ParsingExceptionUtils(){}\n    \n /**\n     * > 如果异常是 `ResponseException`，则获取响应实体并将其解析为 JSON 对象\n     *\n     * @param e 请求抛出的异常\n     * @return 一个 JSON 对象\n     */\n    public static JSONObject getResponseExceptionJsonMessageByException(Exception e) {\n        final Throwable cause = e.getCause();\n        if (cause instanceof ExecutionException) {\n            final Throwable throwable =  cause.getCause();\n            if (throwable instanceof ResponseException) {\n                final HttpEntity entity = ((ResponseException) throwable).getResponse().getEntity();\n                try {\n                    return JSON.parseObject(EntityUtils.toString(entity));\n                } catch (IOException ignore) {\n                    return null;\n                }\n                \n            }\n            \n        }\n        return null;\n    }\n    \n    /**\n     * 如果异常不是解析异常，则抛出新异常\n     *\n     * @param e ES 客户端抛出的异常对象。\n     */\n    public static void abnormalTermination(Exception e) throws ESOperateException {\n        String exception = ParsingExceptionUtils.getESErrorMessageByException(e);\n        if (StringUtils.equals(exception, CLUSTER_ERROR)) {\n            throw new NullESClientException(exception, ResultType.ES_CLIENT_NUL_ERROR);\n        }\n        if (StringUtils.isNotBlank(exception) && !StringUtils.equals(exception, CLUSTER_ERROR)) {\n            throw new ESOperateException(exception);\n        }\n\n    }\n    \n    \n    /**\n     * > 它返回一个字符串，该字符串是异常的错误消息\n     *\n     * @param e 抛出的异常。\n     * @return 错误信息\n     */\n    public static String getESErrorMessageByException(Exception e) {\n        if (e instanceof ESIndexNotFoundException) {\n            return getESIndexNotFoundErrorMessageByException((ESIndexNotFoundException) e);\n        } else if (e instanceof ESIndexTemplateMissingException) {\n            return getESIndexTemplateMissingExceptionErrorMessageByException((ESIndexTemplateMissingException) e);\n        } else if (e instanceof ESAlreadyExistsException) {\n            return getESAlreadyExistsExceptionErrorMessageByException((ESAlreadyExistsException) e);\n        }else if (e instanceof  UncategorizedExecutionException){\n             return getErrorMessagePassUncategorizedExecutionFindResponseExceptionByException((UncategorizedExecutionException) e);\n        }else if (e instanceof ExecutionException){\n             return getExecutionExceptionErrorMessageByException((ExecutionException) e);\n        }\n        return null;\n        \n    }\n    \n    \n    /**\n     * > 该函数返回Elasticsearch在找不到索引时抛出的异常的错误信息\n     *\n     * @param indexNotFoundException Elasticsearch 客户端抛出的异常。\n     * @return 来自 ResponseException 的错误消息。\n     */\n    private static String getESIndexNotFoundErrorMessageByException(ESIndexNotFoundException indexNotFoundException) {\n        Throwable throwable = indexNotFoundException.getT();\n        if (Objects.nonNull(throwable) && throwable instanceof ResponseException) {\n            return getErrorMessageByResponseException((ResponseException) throwable).orElse(null);\n            \n        }\n        return null;\n    }\n    \n    /**\n     * > 该函数返回索引模板缺失时Elasticsearch抛出的异常的错误信息\n     *\n     * @param esIndexTemplateMissingException 抛出的异常对象。\n     * @return 来自 ResponseException 的错误消息。\n     */\n    private static String getESIndexTemplateMissingExceptionErrorMessageByException(ESIndexTemplateMissingException esIndexTemplateMissingException) {\n        Throwable throwable = esIndexTemplateMissingException.getT();\n        if (Objects.nonNull(throwable) && throwable instanceof ResponseException) {\n            return getErrorMessageByResponseException((ResponseException) throwable).orElse(null);\n            \n        }\n        return null;\n    }\n    \n    /**\n     * > 该函数用于从 ESAlreadyExistsException 中获取错误信息\n     *\n     * @param esAlreadyExistsException 抛出的异常对象。\n     * @return 来自 ResponseException 的错误消息。\n     */\n    private static String getESAlreadyExistsExceptionErrorMessageByException(ESAlreadyExistsException esAlreadyExistsException) {\n        Throwable throwable = esAlreadyExistsException.getT();\n        if (Objects.nonNull(throwable) && throwable instanceof ResponseException) {\n            return getErrorMessageByResponseException((ResponseException) throwable).orElse(null);\n            \n        }\n        return null;\n    }\n    \n    /**\n     * > 如果未分类的执行异常的原因是执行异常，则返回执行异常的错误信息\n     *\n     * @param uncategorizedExecutionException 抛出的异常。\n     * @return 异常的错误信息。\n     */\n    private static String getErrorMessagePassUncategorizedExecutionFindResponseExceptionByException(\n            UncategorizedExecutionException uncategorizedExecutionException) {\n        Throwable throwable = uncategorizedExecutionException.getCause();\n        if (Objects.nonNull(throwable) && throwable instanceof ExecutionException) {\n            return getExecutionExceptionErrorMessageByException((ExecutionException) throwable);\n            \n        }\n        return null;\n    }\n    \n    /**\n     * > 如果`ExecutionException`的原因是`ResponseException`，则返回`ResponseException`的错误信息；否则，返回 `null`\n     *\n     * @param executionException 执行任务时抛出的异常。\n     * @return 响应异常的错误信息。\n     */\n    private static String getExecutionExceptionErrorMessageByException(ExecutionException executionException) {\n        Throwable cause = executionException.getCause();\n        if (Objects.nonNull(cause) && cause instanceof ResponseException) {\n            \n            return getErrorMessageByResponseException((ResponseException) cause).orElse(null);\n        }\n        if (Objects.nonNull(cause) && cause instanceof IOException) {\n            return StringUtils.equals(cause.getMessage(), CONNECTION_REFUSED) || StringUtils.equals(cause.getMessage(), CONNECTION_CLOSE)? CLUSTER_ERROR : cause.getMessage();\n        }\n        return null;\n    }\n    \n    \n    /**\n     * 它尝试从响应正文中获取错误消息，如果失败，则返回一个空的 Optional\n     *\n     * @param e 请求抛出的异常\n     * @return 可选<字符串>\n     */\n    private static Optional<String> getErrorMessageByResponseException(ResponseException e) {\n        HttpEntity entity = e.getResponse().getEntity();\n        try {\n            String error = EntityUtils.toString(entity, \"UTF-8\");\n            if (StringUtils.equals(error,\"{}\")){\n                \n                return Optional.of(String.format(\"%s is not found\",e.getResponse().getRequestLine().getUri()));\n            }\n            \n            return Optional.ofNullable(EntityUtils.toString(entity, \"UTF-8\")).map(JSONObject::parseObject)\n                    .map(json -> json.getJSONObject(\"error\")).map(json -> json.getString(\"reason\"));\n        } catch (IOException ignore) {\n            return Optional.empty();\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/PercentUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\n/**\n * @author d06679\n * @date 2019-07-26\n */\npublic class PercentUtils {\n\n    private PercentUtils() {\n    }\n\n    public static int getWithLimit(Double value) {\n        if (value == null) {\n            return 0;\n        }\n\n        if (value > 1.0) {\n            return 100;\n        }\n\n        if (value < 0.0) {\n            return 0;\n        }\n\n        return (int) (value * 100);\n\n    }\n\n    public static String getStrWithLimit(Double value) {\n        return getWithLimit(value) + \"%\";\n    }\n\n    public static int get(Double value) {\n        if (value == null) {\n            return 0;\n        }\n\n        return (int) (value * 100);\n\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/ProjectUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.Collections;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport org.springframework.util.StringUtils;\n\npublic final class ProjectUtils {\n    private static final ILog LOGGER = LogFactory.getLog(CommonUtils.class);\n\n    private ProjectUtils() {\n    }\n\n    /**\n    * 检查项目是否匹配当前业务的操作\n    *\n    * @param func                     函数\n    * @param r                         操作点业务标识 各个业务的点\n    * @param projectId                项目id 接口传入的项目id\n    * @return {@code Boolean}\n    */\n    public static <R> Result<Void> checkProjectCorrectly(Function<R, Integer> func, R r, Integer projectId) {\n        final int currentProjectId = func.apply(r);\n        if (AuthConstant.SUPER_PROJECT_ID.equals(currentProjectId)) {\n            return Result.buildSucc();\n        }\n        if (Objects.equals(currentProjectId, projectId)) {\n            return Result.buildSucc();\n        }\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail(\"当前项目不属于超级项目或者持有该操作的项目\");\n    }\n\n    /**\n    * 用户名是属于项目成员\n    * @see ProjectVO#getUserList()\n    * @param userName 用户名\n    * @param projectVO\n    * @return boolean\n    */\n    public static boolean isUserNameBelongProjectMember(String userName, ProjectVO projectVO) {\n        return StringUtils.hasText(userName)\n               && Optional.ofNullable(projectVO).map(ProjectVO::getUserList).orElse(Collections.emptyList()).stream()\n                   .map(UserBriefVO::getUserName).anyMatch(username -> username.equals(userName));\n    }\n\n    /**\n     * 判断用户名属于项目拥有者\n     * @see  ProjectVO#getOwnerList()\n     * @param userName 用户名\n     * @param projectVO\n     * @return boolean\n     */\n    public static boolean isUserNameBelongProjectResponsible(String userName, ProjectVO projectVO) {\n        return StringUtils.hasText(userName)\n               && Optional.ofNullable(projectVO).map(ProjectVO::getOwnerList).orElse(Collections.emptyList()).stream()\n                   .map(UserBriefVO::getUserName).anyMatch(username -> username.equals(userName));\n    }\n\n    /**\n     * 获取变更之前和变更之后的json\n     *\n     * @param afterObj  obj后\n     * @param beforeObj obj之前\n     * @return {@code String}\n     */\n    public static String getChangeByAfterAndBeforeJson(Object afterObj, Object beforeObj) {\n        return new JSONObject().fluentPut(\"beforeChange\", beforeObj).fluentPut(\"afterChange\", afterObj).toJSONString();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/RegexUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport static java.util.regex.Pattern.compile;\n\nimport java.util.regex.Pattern;\n\n/**\n * regex utils 此类包含用于处理正则表达式的静态方法。\n *\n * @author shizeying\n * @date 2022/08/17\n */\npublic final class RegexUtils {\n    private RegexUtils() {\n    }\n    \n    \n    /**\n     * 它检查索引名称是否以连字符结尾，后跟一个或多个数字\n     *\n     * @param indexName 要检查的索引的名称。\n     * @return 一个布尔值。\n     */\n    public static boolean checkEndWithHyphenNumbers(String indexName) {\n        Pattern regex = compile(\"-\\\\d+$\");\n        return regex.matcher(indexName).find();\n    }\n    \n    \n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/RetryExecutor.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.BaseException;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Predicate;\n\npublic class RetryExecutor<T> {\n    private static final ILog LOGGER     = LogFactory.getLog(RetryExecutor.class);\n\n    /**\n     * 最多的重试次数\n     */\n    private static final int  RETRY_MAX  = 10;\n    /**\n     * 操作名字\n     */\n    private String            name       = \"\";\n    /**\n     * es操作内容\n     */\n    private Handler<T>        handler;\n    /**\n     * 重试次数\n     */\n    private Integer           retryCount = 0;\n\n    /**\n     * es操作\n     * Created by d06679 on 2017/8/24.\n     */\n\n    public interface Handler<T> {\n        /**\n         * 处理方法\n         * @return\n         * @throws Throwable\n         */\n        T process() throws BaseException;\n\n        /***\n         * 异常是否需要重试\n         * @param e 异常\n         * @return\n         */\n        default boolean needExceptionRetry(Exception e) {\n            return false;\n        }\n\n        /**\n         * 返回值是否需要重试\n         * @param t\n         * @return\n         */\n        default boolean needReturnObjRetry(Object t) {\n            return false;\n        }\n\n        /**\n         * 重试Sleep时间间隔\n         * @param retryTimes 重试次数\n         * @return\n         */\n        default int retrySleepTime(int retryTimes) {\n            return 0;\n        }\n    }\n\n    public static <T> RetryExecutor<T> builder() {\n        return new RetryExecutor();\n    }\n\n    public RetryExecutor<T> name(String name) {\n        this.name = name;\n        return this;\n    }\n\n    public RetryExecutor<T> handler(Handler<T> handler) {\n        this.handler = handler;\n        return this;\n    }\n\n    public RetryExecutor<T> retryCount(Integer retryCount) {\n        this.retryCount = (retryCount > RETRY_MAX) ? RETRY_MAX : retryCount;\n        return this;\n    }\n\n    /**\n     * 重试操作，要么handler执行成功有返回值,要么报异常\n     * @throws Exception 操作的异常\n     */\n    public T execute() throws Exception {\n        T t = null;\n        int tryCount = 0;\n        do {\n            try {\n                int retrySleepTime = handler.retrySleepTime(tryCount);\n                if (tryCount > 0 && retrySleepTime > 0) {\n                    TimeUnit.MILLISECONDS.sleep(retrySleepTime);\n                }\n\n                t = handler.process();\n\n                if(!handler.needReturnObjRetry(t)){\n                    return t;\n                }\n            } catch (Exception e) {\n                if (!handler.needExceptionRetry(e) || tryCount == retryCount) {\n                    LOGGER.warn(\"class=RetryExecutor||method=execute||errMsg={}||handlerName={}||tryCount={}\",\n                            e.getMessage(), name, tryCount, e);\n                    throw e;\n                }\n               \n                LOGGER.warn(\n                        \"class=RetryExecutor||method=execute||errMsg={}||handlerName={}||tryCount={}||maxTryCount={}\",\n                        e.getMessage(), name, tryCount, retryCount);\n            }\n        } while (tryCount++ < retryCount);\n\n        return t;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/SizeUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport com.alibaba.druid.util.StringUtils;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/9/28 下午5:16\n * @Modified By\n * <p>\n * 索引大小转换工具类\n */\npublic class SizeUtil {\n\n    private SizeUtil() {\n    }\n\n    private static final ILog LOGGER = LogFactory.getLog(SizeUtil.class);\n\n\n    public static Long getDasboardUnitSize(String proStoreSize) {\n        if (StringUtils.isEmpty(proStoreSize)){\n            return 0L;\n        }\n        if (proStoreSize.contains(\"个\")){\n            return (long) (Double.parseDouble(proStoreSize.replaceAll(\"个\",\"\")));\n        }else {\n            return getUnitSize(proStoreSize);\n        }\n    }\n    /**\n     * 得到字节数\n     *\n     * @param proStoreSize\n     * @return\n     */\n    public static Long getUnitSize(String proStoreSize) {\n        final long C0 = 1L;\n        final long C1 = C0 * 1024L;\n        final long C2 = C1 * 1024L;\n        final long C3 = C2 * 1024L;\n        final long C4 = C3 * 1024L;\n        final long C5 = C4 * 1024L;\n        long bytes = 0L;\n        //TODO:JIANG\n        try {\n            String trimValue = proStoreSize.trim();\n            if (trimValue.endsWith(\"k\")) {\n                bytes = (long) (Double.parseDouble(trimValue.substring(0, trimValue.length() - 1)) * C1);\n            } else if (trimValue.endsWith(\"kb\")) {\n                bytes = (long) (Double.parseDouble(trimValue.substring(0, trimValue.length() - 2)) * C1);\n            } else if (trimValue.endsWith(\"m\")) {\n                bytes = (long) (Double.parseDouble(trimValue.substring(0, trimValue.length() - 1)) * C2);\n            } else if (trimValue.endsWith(\"mb\")) {\n                bytes = (long) (Double.parseDouble(trimValue.substring(0, trimValue.length() - 2)) * C2);\n            } else if (trimValue.endsWith(\"g\")) {\n                bytes = (long) (Double.parseDouble(trimValue.substring(0, trimValue.length() - 1)) * C3);\n            } else if (trimValue.endsWith(\"gb\")) {\n                bytes = (long) (Double.parseDouble(trimValue.substring(0, trimValue.length() - 2)) * C3);\n            } else if (trimValue.endsWith(\"t\")) {\n                bytes = (long) (Double.parseDouble(trimValue.substring(0, trimValue.length() - 1)) * C4);\n            } else if (trimValue.endsWith(\"tb\")) {\n                bytes = (long) (Double.parseDouble(trimValue.substring(0, trimValue.length() - 2)) * C4);\n            } else if (trimValue.endsWith(\"p\")) {\n                bytes = (long) (Double.parseDouble(trimValue.substring(0, trimValue.length() - 1)) * C5);\n            } else if (trimValue.endsWith(\"pb\")) {\n                bytes = (long) (Double.parseDouble(trimValue.substring(0, trimValue.length() - 2)) * C5);\n            } else if (trimValue.endsWith(\"b\")) {\n                bytes = Long.parseLong(trimValue.substring(0, trimValue.length() - 1).trim());\n            } else if (trimValue.equals(\"-1\")) {\n                // Allow this special value to be unit-less:\n                bytes = -1;\n            } else if (trimValue.equals(\"0\")) {\n                // Allow this special value to be unit-less:\n                bytes = 0;\n            } else {\n                LOGGER.error(\"class=SizeUtil||method=getUnitSize||msg={}\", proStoreSize);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=SizeUtil||method=getUnitSize||msg={}\", proStoreSize, e);\n        }\n        return bytes;\n    }\n\n    /**\n     * 得到单位化的大小, 四舍五入保留小数点\n     * @param decimal  保留小数点\n     * @param bytes\n     * @return\n     */\n    public static String getUnitSizeAndFormat(long bytes, int decimal) {\n        final long C0 = 1L;\n        final long C1 = C0 * 1024L;\n        final long C2 = C1 * 1024L;\n        final long C3 = C2 * 1024L;\n        final long C4 = C3 * 1024L;\n        final long C5 = C4 * 1024L;\n        double value = bytes;\n        String suffix = \"b\";\n        if (bytes >= C5) {\n            value = CommonUtils.formatDouble(((double) bytes) / C5, decimal);\n            suffix = \"pb\";\n        } else if (bytes >= C4) {\n            value = CommonUtils.formatDouble(((double) bytes) / C4, decimal);\n            suffix = \"tb\";\n        } else if (bytes >= C3) {\n            value = CommonUtils.formatDouble(((double) bytes) / C3, decimal);\n            suffix = \"gb\";\n        } else if (bytes >= C2) {\n            value = CommonUtils.formatDouble(((double) bytes) / C2, decimal);\n            suffix = \"mb\";\n        } else if (bytes >= C1) {\n            value = CommonUtils.formatDouble(((double) bytes) / C1, decimal);\n            suffix = \"kb\";\n        }\n\n        return String.format(\"%s%s\", value, suffix);\n    }\n\n    /**\n     * 得到单位化的大小\n     *\n     * @param bytes\n     * @return\n     */\n    public static String getUnitSize(long bytes) {\n        final long C0 = 1L;\n        final long C1 = C0 * 1024L;\n        final long C2 = C1 * 1024L;\n        final long C3 = C2 * 1024L;\n        final long C4 = C3 * 1024L;\n        final long C5 = C4 * 1024L;\n        double value = bytes;\n        String suffix = \"b\";\n        if (bytes >= C5) {\n            value = ((double) bytes) / C5;\n            suffix = \"pb\";\n        } else if (bytes >= C4) {\n            value = ((double) bytes) / C4;\n            suffix = \"tb\";\n        } else if (bytes >= C3) {\n            value = ((double) bytes) / C3;\n            suffix = \"gb\";\n        } else if (bytes >= C2) {\n            value = ((double) bytes) / C2;\n            suffix = \"mb\";\n        } else if (bytes >= C1) {\n            value = ((double) bytes) / C1;\n            suffix = \"kb\";\n        }\n\n        return String.format(\"%f%s\", value, suffix);\n    }\n\n    public static String getShortUnitSize(long bytes) {\n        final long c1 = 1024L;\n        final long c2 = c1 * 1024L;\n        final long c3 = c2 * 1024L;\n        final long c4 = c3 * 1024L;\n        final long c5 = c4 * 1024L;\n        long value = bytes;\n        String suffix = \"b\";\n        if (bytes >= c5) {\n            value /= c5;\n            suffix = \"p\";\n        } else if (bytes >= c4) {\n            value /= c4;\n            suffix = \"t\";\n        } else if (bytes >= c3) {\n            value /= c3;\n            suffix = \"g\";\n        } else if (bytes >= c2) {\n            value /= c2;\n            suffix = \"m\";\n        } else if (bytes >= c1) {\n            value /= c1;\n            suffix = \"k\";\n        }\n        return String.format(\"%d%s\", value, suffix);\n    }\n\n    public static String getMachineSpec(int cpuNum, long memoryBytes, long diskBytes) {\n        return String.format(\"%sc-%s-%s\", cpuNum, getShortUnitSize(memoryBytes), getShortUnitSize(diskBytes));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/TemplateUtils.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployStatusEnum;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * @author d06679\n * @date 2019/4/3\n */\npublic class TemplateUtils {\n\n    private static final ILog LOGGER        = LogFactory.getLog(TemplateUtils.class);\n    private static final String REGEX_PATTERN_DAY   = \"[0-9]{4}[-][0-9]{1,2}[-][0-9]{1,2}\";\n    private static final String REGEX_PATTERN_MONTH = \"[0-9]{4}[-][0-9]{1,2}\";\n    private static final String REGEX_PATTERN_YEAR = \"[0-9]{4}\";\n\n    /**\n     * 兼容匹配平台升级版本后的索引\n     * template6_v1, template6_v2\n     */\n    private static final String REGEX_PATTERN_NO_PARTITION  = \"[v][0-9]{1,3}\";\n\n    private TemplateUtils() {\n    }\n\n    /**\n     * 模板是否是按天创建\n     * @param dateFormat 时间格式\n     * @return true/false\n     */\n    public static boolean isSaveByDay(String dateFormat) {\n        if (StringUtils.isBlank(dateFormat)) {\n            return false;\n        }\n\n        return dateFormat.toLowerCase().contains(\"dd\");\n    }\n\n    /**\n     * 模板是否是按天创建\n     * @param dateFormat 时间格式\n     * @return true/false\n     */\n    public static boolean isSaveByMonth(String dateFormat) {\n        if (StringUtils.isBlank(dateFormat)) {\n            return false;\n        }\n\n        if (isSaveByDay(dateFormat)) {\n            return false;\n        }\n\n        return dateFormat.toLowerCase().contains(\"mm\");\n    }\n\n    /**\n     * 无滚动  就一个索引判断\n     * @param expression 表达式\n     * @return true/false\n     */\n    public static boolean isOnly1Index(String expression) {\n        return !expression.endsWith(\"*\");\n    }\n\n    /**\n     * 生成部署信息\n     * @param logicWithPhysical\n     * @return\n     */\n    public static Integer genDeployStatus(IndexTemplateWithPhyTemplates logicWithPhysical) {\n        if (!logicWithPhysical.hasPhysicals()) {\n            return TemplateDeployStatusEnum.MASTER_SLAVE_OFFLINE.getCode();\n        }\n\n        if (logicWithPhysical.getMasterPhyTemplate() != null && logicWithPhysical.getSlavePhyTemplate() != null) {\n            return TemplateDeployStatusEnum.MASTER_SLAVE_ONLINE.getCode();\n        }\n\n        if (logicWithPhysical.getMasterPhyTemplate() != null) {\n            return TemplateDeployStatusEnum.ONLY_MASTER_ONLINE.getCode();\n        }\n\n        return TemplateDeployStatusEnum.NO_MASTER_ONLINE.getCode();\n    }\n\n    /**\n     * 根据索引名称匹配平台模板名称\n     * 目前平台仅支持2020-10-22、2020-10、2020 等三种时间后缀分区索引\n     * @param indexName     索引名称\n     * @return              模板名称,  null 代表不匹配平台模板\n     */\n    public  static String getMatchTemplateNameByIndexName(String indexName) {\n        if (AriusObjUtils.isBlank(indexName)) { return null;}\n        String[] temp;\n\n        try {\n            // 尝试匹配2020-10-22\n            Pattern patternOfDay = Pattern.compile(REGEX_PATTERN_DAY);\n            Matcher matcherOfDay = patternOfDay.matcher(indexName);\n            if (matcherOfDay.find()) {\n                temp = indexName.split(matcherOfDay.group(0));\n                if (temp.length == 0) { return null;}\n    \n                // 获取索引前缀\n                String template = temp[0];\n                if (AriusObjUtils.isBlank(template)) { return null;}\n                return template.substring(0, template.length() - 1);\n            }\n\n            // 尝试匹配2020-10\n            Pattern patternOfMonth = Pattern.compile(REGEX_PATTERN_MONTH);\n            Matcher matcherOfMonth = patternOfMonth.matcher(indexName);\n            if (matcherOfMonth.find()) {\n                temp = indexName.split(matcherOfMonth.group(0));\n                if (temp.length == 0) { return null;}\n    \n                // 获取索引前缀\n                String template = temp[0];\n                if (AriusObjUtils.isBlank(template)) { return null;}\n                return template.substring(0, template.length() - 1);\n            }\n\n            // 尝试匹配2020\n            Pattern patternOfYear = Pattern.compile(REGEX_PATTERN_YEAR);\n            Matcher matcherOfYear = patternOfYear.matcher(indexName);\n            if (matcherOfYear.find()) {\n                temp = indexName.split(matcherOfYear.group(0));\n                if (temp.length == 0) { return null;}\n\n                // 获取索引前缀\n                String template = temp[0];\n                if (AriusObjUtils.isBlank(template)) { return null;}\n                return template.substring(0, template.length() - 1);\n            }\n\n            Pattern patternOfNoPartition = Pattern.compile(REGEX_PATTERN_NO_PARTITION);\n            Matcher matcherOfNoPartition = patternOfNoPartition.matcher(indexName);\n            if (matcherOfNoPartition.find()) {\n                temp = indexName.split(matcherOfNoPartition.group(0));\n                if (temp.length == 0) { return null;}\n\n                // 获取索引前缀\n                String template = temp[0];\n                if (AriusObjUtils.isBlank(template)) { return null;}\n                return template.substring(0, template.length() - 1);\n            }\n\n        } catch (Exception e) {\n            LOGGER.error(\"class=TemplateUtils||method=getMatchTemplateNameByIndexName||errMsg={}\", e.getMessage(), e);\n        }\n\n        return indexName;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/TimeValue.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.util.Locale;\nimport java.util.concurrent.TimeUnit;\n\nimport org.joda.time.Period;\nimport org.joda.time.PeriodType;\nimport org.joda.time.format.PeriodFormat;\nimport org.joda.time.format.PeriodFormatter;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n *\n *\n * @author d06679\n * @date 2018/9/6\n */\npublic class TimeValue {\n\n    private static final ILog LOGGER        = LogFactory.getLog(TimeValue.class);\n\n    /** How many nano-seconds in one milli-second */\n    public static final long  NSEC_PER_MSEC = 1000000;\n\n    public static TimeValue timeValueNanos(long nanos) {\n        return new TimeValue(nanos, TimeUnit.NANOSECONDS);\n    }\n\n    public static TimeValue timeValueMillis(long millis) {\n        return new TimeValue(millis, TimeUnit.MILLISECONDS);\n    }\n\n    public static TimeValue timeValueSeconds(long seconds) {\n        return new TimeValue(seconds, TimeUnit.SECONDS);\n    }\n\n    public static TimeValue timeValueMinutes(long minutes) {\n        return new TimeValue(minutes, TimeUnit.MINUTES);\n    }\n\n    public static TimeValue timeValueHours(long hours) {\n        return new TimeValue(hours, TimeUnit.HOURS);\n    }\n\n    private long     duration;\n\n    private TimeUnit timeUnit;\n\n    private TimeValue() {\n\n    }\n\n    public TimeValue(long millis) {\n        this(millis, TimeUnit.MILLISECONDS);\n    }\n\n    public TimeValue(long duration, TimeUnit timeUnit) {\n        this.duration = duration;\n        this.timeUnit = timeUnit;\n    }\n\n    public long nanos() {\n        return timeUnit.toNanos(duration);\n    }\n\n    public long getNanos() {\n        return nanos();\n    }\n\n    public long micros() {\n        return timeUnit.toMicros(duration);\n    }\n\n    public long getMicros() {\n        return micros();\n    }\n\n    public long millis() {\n        return timeUnit.toMillis(duration);\n    }\n\n    public long getMillis() {\n        return millis();\n    }\n\n    public long seconds() {\n        return timeUnit.toSeconds(duration);\n    }\n\n    public long getSeconds() {\n        return seconds();\n    }\n\n    public long minutes() {\n        return timeUnit.toMinutes(duration);\n    }\n\n    public long getMinutes() {\n        return minutes();\n    }\n\n    public long hours() {\n        return timeUnit.toHours(duration);\n    }\n\n    public long getHours() {\n        return hours();\n    }\n\n    public long days() {\n        return timeUnit.toDays(duration);\n    }\n\n    public long getDays() {\n        return days();\n    }\n\n    public double microsFrac() {\n        return ((double) nanos()) / C1;\n    }\n\n    public double getMicrosFrac() {\n        return microsFrac();\n    }\n\n    public double millisFrac() {\n        return ((double) nanos()) / C2;\n    }\n\n    public double getMillisFrac() {\n        return millisFrac();\n    }\n\n    public double secondsFrac() {\n        return ((double) nanos()) / C3;\n    }\n\n    public double getSecondsFrac() {\n        return secondsFrac();\n    }\n\n    public double minutesFrac() {\n        return ((double) nanos()) / C4;\n    }\n\n    public double getMinutesFrac() {\n        return minutesFrac();\n    }\n\n    public double hoursFrac() {\n        return ((double) nanos()) / C5;\n    }\n\n    public double getHoursFrac() {\n        return hoursFrac();\n    }\n\n    public double daysFrac() {\n        return ((double) nanos()) / C6;\n    }\n\n    public double getDaysFrac() {\n        return daysFrac();\n    }\n\n    private final PeriodFormatter defaultFormatter = PeriodFormat.getDefault().withParseType(PeriodType.standard());\n\n    public String format() {\n        Period period = new Period(millis());\n        return defaultFormatter.print(period);\n    }\n\n    public String format(PeriodType type) {\n        Period period = new Period(millis());\n        return PeriodFormat.getDefault().withParseType(type).print(period);\n    }\n\n    @Override\n    public String toString() {\n        if (duration < 0) {\n            return Long.toString(duration);\n        }\n        long nanos = nanos();\n        if (nanos == 0) {\n            return \"0s\";\n        }\n        double value = nanos;\n        String suffix = \"nanos\";\n        if (nanos >= C6) {\n            value = daysFrac();\n            suffix = \"d\";\n        } else if (nanos >= C5) {\n            value = hoursFrac();\n            suffix = \"h\";\n        } else if (nanos >= C4) {\n            value = minutesFrac();\n            suffix = \"m\";\n        } else if (nanos >= C3) {\n            value = secondsFrac();\n            suffix = \"s\";\n        } else if (nanos >= C2) {\n            value = millisFrac();\n            suffix = \"ms\";\n        } else if (nanos >= C1) {\n            value = microsFrac();\n            suffix = \"micros\";\n        }\n        return format1Decimals(value, suffix);\n    }\n\n    private String format1Decimals(double value, String suffix) {\n        String p = String.valueOf(value);\n        int ix = p.indexOf('.') + 1;\n        int ex = p.indexOf('E');\n        char fraction = p.charAt(ix);\n        if (fraction == '0') {\n            if (ex != -1) {\n                return p.substring(0, ix - 1) + p.substring(ex) + suffix;\n            } else {\n                return p.substring(0, ix - 1) + suffix;\n            }\n        } else {\n            if (ex != -1) {\n                return p.substring(0, ix) + fraction + p.substring(ex) + suffix;\n            } else {\n                return p.substring(0, ix) + fraction + suffix;\n            }\n        }\n    }\n\n    public static TimeValue parseTimeValue(String sValue, TimeValue defaultValue) {\n        if (sValue == null) {\n            return defaultValue;\n        }\n        try {\n            long millis;\n            String lowerSValue = sValue.toLowerCase(Locale.ROOT).trim();\n            if (lowerSValue.endsWith(\"ms\")) {\n                millis = (long) (Double.parseDouble(lowerSValue.substring(0, lowerSValue.length() - 2)));\n            } else if (lowerSValue.endsWith(\"s\")) {\n                millis = (long) Double.parseDouble(lowerSValue.substring(0, lowerSValue.length() - 1)) * 1000;\n            } else if (lowerSValue.endsWith(\"m\")) {\n                millis = (long) (Double.parseDouble(lowerSValue.substring(0, lowerSValue.length() - 1)) * 60 * 1000);\n            } else if (lowerSValue.endsWith(\"h\")) {\n                millis = (long) (Double.parseDouble(lowerSValue.substring(0, lowerSValue.length() - 1)) * 60 * 60\n                                 * 1000);\n            } else if (lowerSValue.endsWith(\"d\")) {\n                millis = (long) (Double.parseDouble(lowerSValue.substring(0, lowerSValue.length() - 1)) * 24 * 60 * 60\n                                 * 1000);\n            } else if (lowerSValue.endsWith(\"w\")) {\n                millis = (long) (Double.parseDouble(lowerSValue.substring(0, lowerSValue.length() - 1)) * 7 * 24 * 60\n                                 * 60 * 1000);\n            } else if (\"-1\".equals(lowerSValue)) {\n                // Allow this special value to be unit-less:\n                millis = -1;\n            } else if (\"0\".equals(lowerSValue)) {\n                // Allow this special value to be unit-less:\n                millis = 0;\n            } else {\n                millis = Long.parseLong(sValue);\n            }\n            return new TimeValue(millis, TimeUnit.MILLISECONDS);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=TimeValue||method=parseTimeValue||msg=parseTimeValue error:{}\", e);\n            return defaultValue;\n        }\n    }\n\n    static final long C0 = 1L;\n    static final long C1 = C0 * 1000L;\n    static final long C2 = C1 * 1000L;\n    static final long C3 = C2 * 1000L;\n    static final long C4 = C3 * 60L;\n    static final long C5 = C4 * 60L;\n    static final long C6 = C5 * 24L;\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        TimeValue timeValue = (TimeValue) o;\n        return timeUnit.toNanos(duration) == timeValue.timeUnit.toNanos(timeValue.duration);\n    }\n\n    @Override\n    public int hashCode() {\n        long normalized = timeUnit.toNanos(duration);\n        return (int) (normalized ^ (normalized >>> 32));\n    }\n\n    public static long nsecToMSec(long ns) {\n        return ns / NSEC_PER_MSEC;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/TimeValueUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport org.elasticsearch.common.unit.TimeValue;\n\nimport java.util.Locale;\nimport java.util.Objects;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * @author didi\n * @date 2022-01-13 3:00 下午\n */\npublic class TimeValueUtil {\n\n    private static final long     C0        = 1L;\n    private static final long     C1        = C0 * 1000L;\n    private static final long     C2        = C1 * 1000L;\n    private static final long     C3        = C2 * 1000L;\n    private static final long     C4        = C3 * 60L;\n    private static final long     C5        = C4 * 60L;\n    private static final long     C6        = C5 * 24L;\n\n    public static final TimeValue MINUS_ONE = timeValueMillis(-1);\n    public static final TimeValue ZERO      = timeValueMillis(0);\n\n    public static TimeValue parseTimeValue(String sValue, String settingName) {\n        settingName = Objects.requireNonNull(settingName);\n        if (sValue == null) {\n            return ZERO;\n        }\n        final String normalized = sValue.toLowerCase(Locale.ROOT).trim();\n        if (normalized.endsWith(\"nanos\")) {\n            return new org.elasticsearch.common.unit.TimeValue((long) parse(sValue, normalized, \"nanos\"),\n                TimeUnit.NANOSECONDS);\n        } else if (normalized.endsWith(\"micros\")) {\n            return new org.elasticsearch.common.unit.TimeValue((long) (parse(sValue, normalized, \"micros\") * C1),\n                TimeUnit.NANOSECONDS);\n        } else if (normalized.endsWith(\"ms\")) {\n            return new org.elasticsearch.common.unit.TimeValue((long) (parse(sValue, normalized, \"ms\") * C2),\n                TimeUnit.NANOSECONDS);\n        } else if (normalized.endsWith(\"s\")) {\n            return new org.elasticsearch.common.unit.TimeValue((long) (parse(sValue, normalized, \"s\") * C3),\n                TimeUnit.NANOSECONDS);\n        } else if (sValue.endsWith(\"m\")) {\n            // parsing minutes should be case-sensitive as 'M' means \"months\", not \"minutes\"; this is the only special case.\n            return new org.elasticsearch.common.unit.TimeValue((long) (parse(sValue, normalized, \"m\") * C4),\n                TimeUnit.NANOSECONDS);\n        } else if (normalized.endsWith(\"h\")) {\n            return new org.elasticsearch.common.unit.TimeValue((long) (parse(sValue, normalized, \"h\") * C5),\n                TimeUnit.NANOSECONDS);\n        } else if (normalized.endsWith(\"d\")) {\n            return new org.elasticsearch.common.unit.TimeValue((long) (parse(sValue, normalized, \"d\") * C6),\n                TimeUnit.NANOSECONDS);\n        } else if (normalized.matches(\"-0*1\")) {\n            return MINUS_ONE;\n        } else if (normalized.matches(\"0+\")) {\n            return ZERO;\n        } else {\n            // Missing units:\n            throw new IllegalArgumentException(\"failed to parse setting [\" + settingName + \"] with value [\" + sValue\n                                               + \"] as a time value: unit is missing or unrecognized\");\n        }\n    }\n\n    private static double parse(final String initialInput, final String normalized, final String suffix) {\n        final String s = normalized.substring(0, normalized.length() - suffix.length()).trim();\n        try {\n            return Double.parseDouble(s);\n        } catch (final NumberFormatException e) {\n            try {\n                @SuppressWarnings(\"unused\")\n                final double ignored = Double.parseDouble(s);\n                throw new IllegalArgumentException(\n                    \"failed to parse [\" + initialInput + \"], fractional time values are not supported\", e);\n            } catch (final NumberFormatException ignored) {\n                throw new IllegalArgumentException(\"failed to parse [\" + initialInput + \"]\", e);\n            }\n        }\n    }\n\n    public static TimeValue timeValueMillis(long millis) {\n        return new TimeValue(millis, TimeUnit.MILLISECONDS);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/VerifyCodeFactory.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Random;\n\nimport com.google.common.collect.Lists;\n\n/**\n * @author d06679\n * @date 2019/4/18\n */\npublic class VerifyCodeFactory {\n\n    private VerifyCodeFactory() {\n    }\n\n    private static final String CHAR_SET = \"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\n    private static List<String> charList;\n\n    private static final Random random   = new Random();\n\n    static {\n        charList = Lists.newArrayList();\n        for (char c : CHAR_SET.toCharArray()) {\n            charList.add(String.valueOf(c));\n        }\n    }\n\n    public static String get(int length) {\n        Collections.shuffle(charList);\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < length; i++) {\n            int number = random.nextInt(charList.size());\n            sb.append(charList.get(number));\n        }\n        return sb.toString();\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-common/src/main/java/com/didichuxing/datachannel/arius/admin/common/util/YamlUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.common.util;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.util.ResourceUtils;\nimport org.yaml.snakeyaml.Yaml;\n\nimport java.io.*;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 读取 .yml 配置文件\n *\n * @author cjm\n */\npublic class YamlUtil {\n\n    private static final Map<String/* ymlName */, Map<String, String>/* properties */> YML_NAME_TO_PROPERTIES = new HashMap<>();\n\n    /**\n     * 根据文件名获取yml的文件内容\n     *\n     * @param ymlPath .yml 配置文件路径\n     * @param keys     第一个参数对应第一个key，第二个参数对应第二个key 比如spring.name下的所有 就是两个参数、\n     *                 getYmlByFileName(bootstrap_file,\"spring\", \"name\");\n     * @return Map<String, String>\n     */\n    public static Map<String, String> getYmlByFileName(String ymlPath, String... keys) throws IOException {\n        if (ymlPath == null) {\n            return null;\n        }\n        if (YML_NAME_TO_PROPERTIES.containsKey(ymlPath)) {\n            return YML_NAME_TO_PROPERTIES.get(ymlPath);\n        }\n        Map<String, String> properties = new HashMap<>();\n        InputStream in = null;\n        try {\n            File file = ResourceUtils.getFile(ymlPath);\n            in = new BufferedInputStream(new FileInputStream(file));\n            Yaml props = new Yaml();\n            Object obj = props.loadAs(in, Map.class);\n            Map<String, Object> param = (Map<String, Object>) obj;\n\n            for (Map.Entry<String, Object> entry : param.entrySet()) {\n                String key = entry.getKey();\n                Object val = entry.getValue();\n                if (keys.length != 0 && !keys[0].equals(key)) {\n                    continue;\n                }\n                if (val instanceof Map) {\n                    forEachYaml(properties, key, (Map<String, Object>) val, 1, keys);\n                } else {\n                    properties.put(key, val != null ? val.toString() : null);\n                }\n            }\n            YML_NAME_TO_PROPERTIES.put(ymlPath, properties);\n            return properties;\n        } finally {\n            if (in != null) {\n                in.close();\n            }\n        }\n    }\n\n    /**\n     * 根据 key 获取值\n     */\n    public static String getValue(String ymlPath, String key) throws IOException {\n        if (YML_NAME_TO_PROPERTIES.containsKey(ymlPath)) {\n            return YML_NAME_TO_PROPERTIES.get(ymlPath).get(key);\n        }\n        Map<String, String> properties = getYmlByFileName(ymlPath);\n\n        if (properties == null) {\n            return null;\n        }\n\n        return properties.get(key);\n    }\n\n    /**\n     * 遍历 yml 文件，获取 map 集合\n     */\n    private static void forEachYaml(Map<String, String> properties, String key_str, Map<String, Object> obj, int i,\n                                    String... keys) {\n        for (Map.Entry<String, Object> entry : obj.entrySet()) {\n            String key = entry.getKey();\n            Object val = entry.getValue();\n            if (keys.length > i && !keys[i].equals(key)) {\n                continue;\n            }\n            String str_new = \"\";\n            if (StringUtils.isNotEmpty(key_str)) {\n                str_new = key_str + \".\" + key;\n            } else {\n                str_new = key;\n            }\n            if (val instanceof Map) {\n                forEachYaml(properties, str_new, (Map<String, Object>) val, ++i, keys);\n                i--;\n            } else {\n                properties.put(str_new, val != null ? val.toString() : null);\n            }\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <artifactId>arius-admin</artifactId>\n        <version>${revision}${sha1}${changelist}</version>\n    </parent>\n\n    <artifactId>arius-admin-core</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.github.java-json-tools</groupId>\n            <artifactId>json-patch</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-security-spring-boot-starter</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-common</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-remote</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-persistence</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-lang3</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.guava</groupId>\n            <artifactId>guava</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-collections4</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-elasticsearch-client</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-email</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.sun.mail</groupId>\n                    <artifactId>javax.mail</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-tx</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-log4j2</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.apache.logging.log4j</groupId>\n                    <artifactId>log4j-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n    </dependencies>\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/component/BaseExtendFactory.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.component;\n\nimport java.util.Map;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.BeansException;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * 从SpringContent中获取指定接口的类的实例\n * 使用例子参考 HandleFactory\n *\n * @author linyunan\n * @date 2021-04-25\n */\npublic abstract class BaseExtendFactory {\n\n    private static final ILog LOGGER = LogFactory.getLog(BaseExtendFactory.class);\n\n    public <T> T getByClassNamePer(String classNamePre, Class<T> clazz) throws NotFindSubclassException {\n        T handler = null;\n        handler = doGet(classNamePre, clazz);\n\n        return handler;\n    }\n\n    private <T> T doGet(String classNamePre, Class<T> clazz) throws NotFindSubclassException {\n        Map<String, T> beans = null;\n        try {\n            beans = SpringTool.getBeansOfType(clazz);\n        } catch (BeansException e) {\n            LOGGER.error(\"class=BaseExtendFactory||method=findFromSpringContext||handleNamePre={}||msg={}\",\n                classNamePre, e.getMessage());\n        }\n\n        if (beans == null || beans.isEmpty()) {\n            throw new NotFindSubclassException(String.format(\"找不到【%s】的具体处理器【%s】\", clazz.getSimpleName(), classNamePre));\n        }\n\n        for (Map.Entry<String, T> bean : beans.entrySet()) {\n            if (StringUtils.startsWith(bean.getKey(), classNamePre)) {\n                return bean.getValue();\n            }\n        }\n\n        throw new NotFindSubclassException(String.format(\"找不到【%s】的具体处理器【%s】\", clazz.getSimpleName(), classNamePre));\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/component/CacheSwitch.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.component;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\n\n/**\n * @author didi\n */\n\n@Component\npublic class CacheSwitch {\n\n    private static final String    CONFIG_GROUP = \"arius.cache.switch\";\n\n    @Autowired\n    private AriusConfigInfoService ariusConfigInfoService;\n\n    public boolean logicTemplateCacheEnable() {\n        return ariusConfigInfoService.booleanSetting(CONFIG_GROUP, \"logic.template.cache.enable\", true);\n    }\n\n    public boolean logicTemplateQuotaUsageCacheEnable() {\n        return ariusConfigInfoService.booleanSetting(CONFIG_GROUP, \"logic.template.quota.usage.cache.enable\", true);\n    }\n\n    public boolean physicalTemplateCacheEnable() {\n        return ariusConfigInfoService.booleanSetting(CONFIG_GROUP, \"physical.template.cache.enable\", true);\n    }\n\n    public boolean clusterPhyCacheEnable() {\n        return ariusConfigInfoService.booleanSetting(CONFIG_GROUP, \"cluster.phy.cache.enable\", true);\n    }\n\n    public boolean clusterLogicCacheEnable() {\n        return ariusConfigInfoService.booleanSetting(CONFIG_GROUP, \"cluster.logic.cache.enable\", true);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/component/HandleFactory.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.component;\n\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.google.common.collect.Maps;\nimport java.util.Map;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author linyunan\n * @date 2021-04-26\n */\n@Component\npublic class HandleFactory extends BaseExtendFactory {\n\n    private Map<String, BaseHandle> baseHandleMap = Maps.newConcurrentMap();\n\n    /**\n     * 根据类名前缀获取接口BaseHandle的实现类实例\n     * 注意： handleNamePre 需要保证全局唯一\n     */\n    public BaseHandle getByHandlerNamePer(String handleNamePre) throws NotFindSubclassException {\n        if (baseHandleMap.containsKey(handleNamePre)) {\n            return baseHandleMap.get(handleNamePre);\n        } else {\n            BaseHandle baseHandle = getByClassNamePer(handleNamePre, BaseHandle.class);\n            baseHandleMap.put(handleNamePre, baseHandle);\n            return baseHandle;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/component/RoleTool.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.component;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didiglobal.knowframework.security.common.vo.role.RoleVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserVO;\nimport com.didiglobal.knowframework.security.service.RoleService;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.stream.Collectors;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * 角色工具\n *\n * @author shizeying\n * @date 2022/06/01\n * @see com.didiglobal.knowframework.security.service.RoleService 实现admin册指定角色任务的判断\n */\n@Component\npublic class RoleTool {\n    @Autowired\n    private RoleService roleService;\n    @Autowired\n    private UserService userService;\n\n    /**\n     * 校验用户是否为管理员\n     *\n     * @param userName 用户名\n     * @return boolean\n     */\n    public boolean isAdmin(String userName) {\n        final RoleVO roleVO = roleService.getRoleDetailByRoleId(AuthConstant.ADMIN_ROLE_ID);\n        return Optional.ofNullable(roleVO).map(RoleVO::getAuthedUsers).orElse(Collections.emptyList()).stream()\n            .anyMatch(user -> StringUtils.equals(user, userName));\n    }\n\n    /**\n     * 管理员用户列表\n     *\n     * @return {@code List<UserBriefVO>}\n     */\n    public List<UserBriefVO> getAdminList() {\n        final RoleVO roleVO = roleService.getRoleDetailByRoleId(AuthConstant.ADMIN_ROLE_ID);\n        return Optional.ofNullable(roleVO).map(RoleVO::getAuthedUsers)\n\n            .orElse(Collections.emptyList()).stream().map(userService::getUserBriefByUserName)\n            .collect(Collectors.toList());\n    }\n\n    public boolean isAdmin(Integer userId) {\n        final RoleVO roleVO = roleService.getRoleDetailByRoleId(AuthConstant.ADMIN_ROLE_ID);\n        final UserVO userVO = userService.getUserDetailByUserId(userId);\n        return Optional.ofNullable(roleVO).map(RoleVO::getAuthedUsers).orElse(Collections.emptyList()).stream()\n            .anyMatch(user -> StringUtils.equals(user, userVO.getUserName()));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/component/SpringTool.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.component;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.OperateForbiddenException;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport java.util.Map;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.DisposableBean;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.ApplicationEvent;\nimport org.springframework.context.annotation.Lazy;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.context.request.RequestContextHolder;\nimport org.springframework.web.context.request.ServletRequestAttributes;\n\n/**\n * @author huangyiminghappy@163.com\n * @date 2019-05-08\n */\n@Service(\"springTool\")\n@Lazy(false)\n@Order(value = 1)\npublic class SpringTool implements ApplicationContextAware, DisposableBean {\n    private static ApplicationContext applicationContext = null;\n\n    private static ILog logger             = LogFactory.getLog(SpringTool.class);\n\n    /**\n     * 去的存储在静态变量中的ApplicationContext\n     */\n    private static ApplicationContext getApplicationContext() {\n        return applicationContext;\n    }\n\n    /**\n     * 从静态变量applicationContext中去的Bean，自动转型为所复制对象的类型\n     */\n    public static <T> T getBean(String name) {\n        return (T) applicationContext.getBean(name);\n    }\n\n    public static <T> T getBean(String name, Class<T> clazz) {\n        return applicationContext.getBean(name, clazz);\n    }\n\n    public static <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {\n        return getApplicationContext().getBeansOfType(type);\n    }\n\n    /**\n     * 清除SpringContextHolder中的ApplicationContext为Null\n     */\n    public static void clearHolder() {\n        if (logger.isDebugEnabled()) {\n            logger.debug(\"class=SpringTool||method=learHolder||msg=清除SpringContextHolder中的ApplicationContext:{}\",\n                applicationContext);\n        }\n        applicationContext = null;\n    }\n\n    /**\n     * 实现ApplicationContextAware接口，注入Context到静态变量\n     */\n    @Override\n    public void setApplicationContext(ApplicationContext context) throws BeansException {\n        SpringTool.applicationContext = context;\n    }\n\n    /**\n     * 实现DisposableBean接口，在Context关闭时清理静态变量\n     */\n    @Override\n    public void destroy() throws Exception {\n        SpringTool.clearHolder();\n    }\n\n    public static String getUserName() throws OperateForbiddenException {\n        ServletRequestAttributes servletRequestAttributes = ((ServletRequestAttributes) RequestContextHolder\n            .getRequestAttributes());\n        if (null == servletRequestAttributes) {\n            throw new OperateForbiddenException(String.format(\"请携带操作人信息,HTTP_HEADER_KEY:%s\", HttpRequestUtil.USER));\n        }\n        HttpServletRequest request = servletRequestAttributes.getRequest();\n        Object value = request.getHeader(HttpRequestUtil.USER);\n        if (value == null) {\n            throw new OperateForbiddenException(String.format(\"请携带操作人信息,HTTP_HEADER_KEY:%s\", HttpRequestUtil.USER));\n        }\n        return String.valueOf(value);\n    }\n\n    /**\n     * 发布一个事件\n     */\n    public static void publish(ApplicationEvent event) {\n        getApplicationContext().publishEvent(event);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/config/ProjectEventMultiConfig.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.config;\n\nimport com.didichuxing.datachannel.arius.admin.common.threadpool.AriusOpThreadPool;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.event.ApplicationEventMulticaster;\nimport org.springframework.context.event.SimpleApplicationEventMulticaster;\n\n/**\n * 设置时间广播执行的线程池,所有的事件都会异步执行\n * 所以事件的监听者在处理消息时,如果处理失败,需要打error日志,通过监控感知;\n * 事件的发布线程不会感知,保证核心流程不受事件发布影响\n * @author d06679\n * @date 2019/5/24\n */\n@Configuration\npublic class ProjectEventMultiConfig {\n\n    @Bean\n    public ApplicationEventMulticaster applicationEventMulticaster(AriusOpThreadPool ariusOpThreadPool) {\n        SimpleApplicationEventMulticaster applicationEventMulticaster = new SimpleApplicationEventMulticaster();\n        applicationEventMulticaster.setTaskExecutor(ariusOpThreadPool);\n        return applicationEventMulticaster;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/config/RestTemplateConfig.java",
    "content": "/**\n * @Author yunan\n * @Date 2017/9/27 18:24\n */\npackage com.didichuxing.datachannel.arius.admin.core.config;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.nio.charset.StandardCharsets;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport lombok.SneakyThrows;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpRequest;\nimport org.springframework.http.client.*;\nimport org.springframework.http.converter.HttpMessageConverter;\nimport org.springframework.http.converter.StringHttpMessageConverter;\nimport org.springframework.web.client.RestTemplate;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ThirdPartRemoteException;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.log.common.Constants;\n\n/**\n * @author jinbinbin\n * @version $Id: RestTemplateConfig.java, v 0.1 2018年09月27日 17:45 jinbinbin Exp $\n */\n@Configuration\npublic class RestTemplateConfig {\n\n    private static final ILog REQ_LOGGER    = LogFactory.getLog(\"thirdReqLogger\");\n    private static final ILog RESP_LOGGER   = LogFactory.getLog(\"thirdRespLogger\");\n    private static final ILog SYSTEM_LOGGER = LogFactory.getLog(RestTemplateConfig.class);\n\n    @Bean\n    public RestTemplate restTemplate() {\n        SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();\n        // 2分钟超时\n        simpleClientHttpRequestFactory.setConnectTimeout(2 * 60 * 1000);\n        simpleClientHttpRequestFactory.setReadTimeout(60 * 1000);\n\n        RestTemplate restTemplate = new RestTemplate(\n            new BufferingClientHttpRequestFactory(simpleClientHttpRequestFactory));\n\n        // 增加自定义的拦截器\n        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();\n        interceptors.add(new LogHttpRequestInterceptor());\n        restTemplate.setInterceptors(interceptors);\n\n        // 设置字符编码\n        List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();\n        for (HttpMessageConverter<?> converter : converters) {\n            if (converter instanceof StringHttpMessageConverter) {\n                StringHttpMessageConverter stringConverter = (StringHttpMessageConverter) converter;\n                stringConverter.setWriteAcceptCharset(false);\n                stringConverter.setDefaultCharset(StandardCharsets.UTF_8);\n            }\n        }\n\n        return restTemplate;\n    }\n\n    private class LogHttpRequestInterceptor implements ClientHttpRequestInterceptor {\n\n        @SneakyThrows\n        @Override\n        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {\n            ClientHttpResponse response = null;\n            String subFlag = LogFactory.getUniqueFlag();\n            Long beginNano = System.nanoTime();\n            try {\n\n                //打印请求出口日志\n                traceRequest(request, subFlag, body);\n\n                request.getHeaders().add(Constants.FLAG, LogFactory.getFlag());\n                request.getHeaders().add(Constants.TRACE_ID, LogFactory.getFlag());\n                request.getHeaders().add(Constants.SPAN_ID, subFlag);\n\n                response = execution.execute(request, body);\n\n                // 打印请求响应日志\n                traceResponse(request, response, null, subFlag, beginNano);\n\n                return response;\n            } catch (IOException exe) {\n                try {\n                    traceResponse(request, response, exe, subFlag, beginNano);\n                } catch (Exception e) {\n                    SYSTEM_LOGGER.warn(\"class=LogHttpRequestInterceptor||method=intercept||msg={}\", e.getMessage());\n                }\n                throw new ThirdPartRemoteException(\"rest-template: \" + exe.getMessage(), exe,\n                    ResultType.HTTP_REQ_ERROR);\n            }\n        }\n\n        private void traceRequest(HttpRequest request, String subFlag, byte[] body) throws IOException {\n            REQ_LOGGER.info(\n                \"class=LogHttpRequestInterceptor||method=traceRequest||remoteRequest||url={}||method={}||headers={}||body={}||subFlag={}\",\n                request.getURI(), request.getMethod(), JSON.toJSONString(request.getHeaders()),\n                new String(body, StandardCharsets.UTF_8), subFlag);\n        }\n\n        private void traceResponse(HttpRequest request, ClientHttpResponse response, IOException exception,\n                                   String subFlag, long nanoTime) throws IOException, ThirdPartRemoteException {\n            String url = simpleUrl(request);\n            StringBuilder inputStringBuilder = new StringBuilder();\n            if (response == null) {\n                RESP_LOGGER.warn(\n                    \"class=LogHttpRequestInterceptor||method=traceResponse||remoteResponse||code=-1||url={}||text={}||headers={}||body={}||timeCost={}||subFlag={}\",\n                    url, null, null, null, (System.nanoTime() - nanoTime) / 1000 / 1000, subFlag);\n                return;\n            }\n\n            try {\n                try (BufferedReader bufferedReader = new BufferedReader(\n                    new InputStreamReader(response.getBody(), StandardCharsets.UTF_8))) {\n\n                    boolean first = true;\n                    String line = bufferedReader.readLine();\n                    while (line != null) {\n                        if (!first) {\n                            inputStringBuilder.append('\\n');\n                        } else {\n                            first = false;\n                        }\n                        inputStringBuilder.append(line);\n                        line = bufferedReader.readLine();\n                    }\n                }\n            } catch (Exception e) {\n                RESP_LOGGER.warn(\n                    \"class=remoteResponse||code={}||url={}||text={}||headers={}||body={}||error={}||timeCost={}||subFlag={}\",\n                    response.getStatusCode(), url, response.getStatusText(), response.getHeaders(),\n                    inputStringBuilder.toString(), e, (System.nanoTime() - nanoTime) / 1000 / 1000, subFlag);\n                if (!response.getStatusCode().is2xxSuccessful()) {\n                    throw new ThirdPartRemoteException(e.getMessage(), e, ResultType.HTTP_REQ_ERROR);\n                }\n            }\n            String responseString = inputStringBuilder.toString().replace(\"\\n\", \"\");\n            responseString = responseString.substring(0, Math.min(responseString.length(), 5000));\n\n            if (!response.getStatusCode().is2xxSuccessful()) {\n                if (exception == null) {\n                    RESP_LOGGER.warn(\n                        \"class=LogHttpRequestInterceptor||method=traceResponse||remoteResponse||code={}||url={}||text={}||headers={}||body={}||timeCost={}||subFlag={}\",\n                        response.getStatusCode(), url, response.getStatusText(), response.getHeaders(), responseString,\n                        (System.nanoTime() - nanoTime) / 1000 / 1000, subFlag);\n                } else {\n                    RESP_LOGGER.warn(\n                        \"remoteResponse||code={}||url={}||text={}||headers={}||body={}||error={}||timeCost={}||subFlag={}\",\n                        response.getStatusCode(), url, response.getStatusText(), response.getHeaders(), responseString,\n                        exception, (System.nanoTime() - nanoTime) / 1000 / 1000, subFlag);\n                }\n                throw new ThirdPartRemoteException(responseString, ResultType.HTTP_REQ_ERROR);\n            }\n\n            if (exception == null) {\n                RESP_LOGGER.info(\n                    \"class=LogHttpRequestInterceptor||method=traceResponse||remoteResponse||code={}||url={}||text={}||headers={}||responseBody={}||timeCost={}||subFlag={}\",\n                    response.getStatusCode(), url, response.getStatusText(), response.getHeaders(), responseString,\n                    (System.nanoTime() - nanoTime) / 1000 / 1000, subFlag);\n            } else {\n                RESP_LOGGER.warn(\n                    \"class=LogHttpRequestInterceptor||method=traceResponse||remoteResponse||code={}||url={}||text={}||headers={}||responseBody={}||error={}||timeCost={}||subFlag={}\",\n                    response.getStatusCode(), url, response.getStatusText(), response.getHeaders(), responseString,\n                    exception, (System.nanoTime() - nanoTime) / 1000 / 1000, subFlag);\n            }\n\n        }\n\n    }\n\n    private static String simpleUrl(HttpRequest request) {\n        String url = request.getURI().toString();\n        int index = url.indexOf(\"?\");\n        if (index > 0) {\n            return url.substring(0, index);\n        } else {\n            return url;\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/ESClusterConfigService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESZeusConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.esconfig.ESConfig;\nimport com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum;\nimport java.util.List;\n\n/**\n * @author lyn\n * @date 2020-12-30\n */\npublic interface ESClusterConfigService {\n    /**\n     * 获取宙斯ES执行脚本配置内容\n     * @param esZeusConfigDTO\n     * @param configAction 配置项动作\n     * @return\n     */\n    Result<String> getZeusConfigContent(ESZeusConfigDTO esZeusConfigDTO, Integer configAction);\n\n    /**\n     * 根据集群id获取配置\n     * @param clusterId\n     * @return\n     */\n    Result<List<ESConfig>> listEsClusterConfigByClusterId(Long clusterId);\n\n    /**\n     * 获取集群默认配置Client\\master\\data节点都一致\n     * @param type\n     * @return\n     */\n    ESConfig getEsClusterTemplateConfig(String type);\n\n    /**\n     * 获取ES集群配置信息\n     * @param clusterId\n     * @param type\n     * @param engin\n     * @return\n     */\n    ESConfig getByClusterIdAndTypeAndEngin(Long clusterId, String type, String engin);\n\n    /**\n     * 根据主键获取ES集群有效配置信息\n     * @param id\n     * @return\n     */\n    ESConfig getEsClusterConfigById(Long id);\n\n    /**\n     * 根据id获取配置信息(不区分是否有效无效)\n     * @param id\n     * @return\n     */\n    ESConfig getEsConfigById(Long id);\n\n    /**\n     * 新增/编辑ES集群配置\n     * @param param\n     * @param actionEnum ADD EDIT\n     * @return\n     */\n    Result<Long> esClusterConfigAction(ESConfigDTO param, EsConfigActionEnum actionEnum, String operator);\n\n    /**\n     * 删除ES集群配置\n     * @param configId\n     * @param operator\n     * @return\n     */\n    Result<Void> deleteEsClusterConfig(Long configId, String operator);\n\n    /**\n     * 设置配置为无效\n     * @param id\n     * @return\n     */\n    Result<Void> setConfigValid(Long id);\n\n    /**\n     * 设置原始配置为无效\n     * @param esConfig\n     * @return\n     */\n    Result<Void> setOldConfigInvalid(ESConfig esConfig);\n\n    /**\n     * 修改配置详情\n     *\n     * @param param\n     * @return\n     */\n    Result<Void> editConfigDesc(ESConfigDTO param);\n\n    /**\n     * 删除固定集群角色配置类型下的配置信息\n     * @param clusterId 物理集群id\n     * @param typeName 配置类型\n     * @param enginName 角色名称\n     * @return\n     */\n    Result<Void> deleteByClusterIdAndTypeAndEngin(Long clusterId, String typeName, String enginName);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/ESMachineNormsService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESMachineNormsPO;\n\n/**\n * 容器规格列表 服务类\n * @author didi\n * @since 2020-08-24\n */\npublic interface ESMachineNormsService {\n\n    /**\n     * 获取所有的机器规格列表\n     * @param\n     * @return List<ESMachineNormsPO>\n     */\n    List<ESMachineNormsPO> listMachineNorms();\n\n    ESMachineNormsPO getById(Long id);\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/ESPackageService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESPackageDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.espackage.ESPackage;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\n\nimport java.util.List;\n\n/**\n * 程序包版本管理 服务类\n * @author didi\n * @since 2020-08-24\n */\npublic interface ESPackageService {\n    /**\n     * 获取所有的package列表\n     * @return package列表\n     */\n    List<ESPackage> listESPackage();\n\n    /**\n     * 创建一个Package\n     * @param esPackageDTO dto\n     * @param operator 操作者\n     * @return 创建数量\n     */\n    Result<Long> addESPackage(ESPackageDTO esPackageDTO, String operator);\n\n    /**\n     * 修改ES package\n     *\n     * @param esPackageDTO dto\n     * @param operator     操作者\n     * @param projectId\n     * @return 更新的es package\n     */\n    Result<ESPackage> updateESPackage(ESPackageDTO esPackageDTO, String operator, Integer projectId);\n\n    /**\n     * 根据id获取es package\n     * @param id 安装包id\n     * @return 安装包\n     */\n    ESPackage getESPackagePOById(Long id);\n\n    /**\n     * 根据id删除ES安装包\n     * @param id es安装包id\n     * @param operator 操作者\n     * @return 删除es安装包数量\n     */\n    Result<Long> deleteESPackage(Long id, String operator) throws NotFindSubclassException;\n\n    /**\n     * 根据根据版本和类型查询一个程序包\n     * @param esVersion es版本\n     * @param manifest 类型host或者docker\n     * @return es安装包\n     */\n    ESPackage getByVersionAndType(String esVersion, Integer manifest);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/ESPluginService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Plugin;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.PluginDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin.PluginPO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\n\nimport java.util.List;\n\npublic interface ESPluginService {\n\n    /**\n     * 获取所有的plugin列表\n     *\n     * @param\n     * @return list\n     */\n    List<PluginPO> listESPlugin();\n\n    /**\n     * 获取默认 & 集群相关联的的plugin列表\n     *\n     * @param\n     * @return list\n     */\n    List<PluginPO> listClusterAndDefaultESPlugin(String phyClusterId);\n\n    /**\n     * 创建一个plugin\n     *\n     * @param pluginDTO ES插件\n     * @return result\n     */\n    Result<Long> addESPlugin(PluginDTO pluginDTO) throws NotFindSubclassException;\n\n    /**\n     * 修改 plugin （只允许修改描述信息）\n     *\n     * @param pluginDTO ES插件\n     * @return ESPluginPO\n     */\n    Result<Void> updateESPluginDesc(PluginDTO pluginDTO, String operator);\n\n    /**\n     * 获取指定id的plugin\n     *\n     * @param id 插件ID\n     * @return ESPluginPO\n     */\n    PluginPO getESPluginById(Long id);\n\n    /**\n     * 根据id删除一个plugin\n     *\n     * @param id 插件ID\n     * @return result\n     */\n    Result<Long> deletePluginById(Long id, String operator) throws NotFindSubclassException;\n\n    /**\n     * 获取全部系统默认插件\n     *\n     * @return result\n     */\n    String getAllSysDefaultPluginIds();\n\n    /**\n     * 根据集群名称获取关联插件\n     *\n     * @return result\n     */\n    List<Plugin> getPluginsByClusterName(String clusterName);\n\n    /**\n     * 上传多个 plugin\n     * @param  param ES插件的集合\n     * @return result\n     */\n    Result<String> addESPlugins(List<PluginDTO> param) throws NotFindSubclassException;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/EcmHandleService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmOperateAppBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmSubTaskLog;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmTaskStatus;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.EcmActionEnum;\nimport com.google.common.collect.Multimap;\n\n/**\n * ES集群表 服务类\n * @author didi\n * @since 2020-08-24\n */\npublic interface EcmHandleService {\n    /**\n     * 新建一个集群\n     * @param ecmParamBaseList\n     * @return Result\n     */\n    Result<Long> saveESCluster(List<EcmParamBase> ecmParamBaseList);\n\n    /**\n     * 启动集群\n     * @param ecmParamBase  集群ID\n     * @param operator      操作人\n     * @return\n     */\n    Result<EcmOperateAppBase> startESCluster(EcmParamBase ecmParamBase, String operator);\n\n    /**\n     * 集群扩缩容\n     * @param ecmParamBase  集群角色\n     * @param operator      操作人\n     * @return Result\n     */\n    Result<EcmOperateAppBase> scaleESCluster(EcmParamBase ecmParamBase, String operator);\n\n    /**\n     * 集群升级\n     * @param   ecmParamBase  集群角色\n     * @param   operator      操作人\n     * @return Result\n     */\n    Result<EcmOperateAppBase> upgradeESCluster(EcmParamBase ecmParamBase, String operator);\n\n    /**\n     * 重启集群\n     * @param ecmParamBase  集群角色\n     * @param operator      操作人\n     * @return Result\n     */\n    Result<EcmOperateAppBase> restartESCluster(EcmParamBase ecmParamBase, String operator);\n\n    /**\n     * 根据物理集群Id删除集群\n     * @param clusterId     集群Id\n     * @param operator      操作人\n     * @return\n     */\n    Result<Void> deleteESCluster(Long clusterId, String operator);\n\n    /**\n     * 继续启动角色集群中未完成的节点任务\n     * @param operator  操作人\n     * @return Result\n     */\n    Result<EcmOperateAppBase> actionUnfinishedESCluster(EcmActionEnum ecmActionEnum, EcmParamBase actionParamBase,\n                                                        String hostname, String operator);\n\n    /**\n     * 获取集群节点信息\n     * @param clusterId\n     * @param operator  操作人\n     * @return Result\n     */\n    Result<String> infoESCluster(Long clusterId, String operator);\n\n    /**\n     * 获取容器云节点日志信息\n     * @param ecmParamBase   容器云任务Id\n     * @param hostname       容器云主机IP\n     * @return Result\n     */\n    Result<EcmSubTaskLog> getSubTaskLog(EcmParamBase ecmParamBase, String hostname, String operator);\n\n    /**\n     * 获取本次操作所有机器的状态\n     * @param actionParamBase\n     * @param operator\n     * @return\n     */\n    Result<List<EcmTaskStatus>> getESClusterStatus(EcmParamBase actionParamBase, Integer orderType, String operator);\n\n    /**\n     * 依据集群ID & 角色列表构造EcmParamBase\n     * @param  phyClusterId  物理集群ID\n     * @param  roleNameList  角色列表\n     * @return Result\n     */\n    Result<List<EcmParamBase>> buildEcmParamBaseList(Integer phyClusterId, List<String> roleNameList);\n\n    /**\n     * 获取带集群配置的Ecm参数列表\n     * @param phyClusterId\n     * @param roleNameList\n     * @param role2ConfigIdsMultiMap\n     * @param actionType\n     * @return\n     */\n    Result<List<EcmParamBase>> buildEcmParamBaseListWithConfigAction(Integer phyClusterId, List<String> roleNameList,\n                                                                     Multimap<String, Long> role2ConfigIdsMultiMap,\n                                                                     Integer actionType);\n\n    /**\n     * 获取带集群Plugin的Ecm参数列表\n     */\n    Result<List<EcmParamBase>> buildEcmParamBaseListWithEsPluginAction(Integer phyClusterId, List<String> roleNameList,\n                                                                       Long EsPluginId, Integer actionType);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/impl/ESClusterConfigServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum.ADD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum.EDIT;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESZeusConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.esconfig.ESConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.esconfig.ESConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESClusterConfigService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESClusterConfigDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author lyn\n * @date 2020-12-30\n */\n@Service\npublic class ESClusterConfigServiceImpl implements ESClusterConfigService {\n\n    private static final ILog    LOGGER                  = LogFactory.getLog(ESClusterConfigServiceImpl.class);\n\n    @Autowired\n    private ClusterPhyService    esClusterPhyService;\n\n    @Autowired\n    private ESClusterConfigDAO   esClusterConfigDAO;\n\n    private static final String  DEFAULT_CONFIG_TEMPLATE = \"template\";\n\n    private static final Long    SYSTEM_CLUSTER_ID       = 1L;\n\n    private static final Integer DEFAULT_CONFIG_VERSION  = 1;\n\n    @Override\n    public Result<String> getZeusConfigContent(ESZeusConfigDTO esZeusConfigDTO, Integer configAction) {\n        Result<Void> r = preCheck(esZeusConfigDTO);\n        if (r.failed()) {\n            return Result.buildFrom(r);\n        }\n\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterByName(esZeusConfigDTO.getClusterName());\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildFail(\"es clusterPhy is empty\");\n        }\n\n        if (configAction.equals(EsConfigActionEnum.DELETE.getCode())) {\n            return Result.buildSucc();\n        }\n\n        if (configAction.equals(EDIT.getCode())) {\n            ESConfigPO oldESConfigPO = esClusterConfigDAO.getByClusterIdAndTypeAndEngin(clusterPhy.getId().longValue(),\n                esZeusConfigDTO.getTypeName(), esZeusConfigDTO.getEnginName());\n            if (AriusObjUtils.isNull(oldESConfigPO) || AriusObjUtils.isNull(oldESConfigPO.getVersionConfig())) {\n                return Result.buildFail(\"old es config is empty\");\n            }\n            ESConfigPO newESConfigPO = esClusterConfigDAO.getByClusterIdAndTypeAndEnginAndVersion(\n                clusterPhy.getId().longValue(), esZeusConfigDTO.getTypeName(), esZeusConfigDTO.getEnginName(),\n                oldESConfigPO.getVersionConfig() + 1);\n            if (AriusObjUtils.isNull(newESConfigPO) || AriusObjUtils.isBlack(newESConfigPO.getConfigData())) {\n                return Result.buildFail(\"es config is empty\");\n            }\n            return Result.build(Boolean.TRUE, newESConfigPO.getConfigData());\n        }\n\n        if (configAction.equals(ADD.getCode())) {\n            ESConfigPO esConfigPO = esClusterConfigDAO.getByClusterIdAndTypeAndEnginAndVersion(\n                clusterPhy.getId().longValue(), esZeusConfigDTO.getTypeName(), esZeusConfigDTO.getEnginName(),\n                DEFAULT_CONFIG_VERSION);\n            if (AriusObjUtils.isNull(esConfigPO) || AriusObjUtils.isBlack(esConfigPO.getConfigData())) {\n                return Result.buildFail(\"es config is empty\");\n            }\n            return Result.build(Boolean.TRUE, esConfigPO.getConfigData());\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public Result<List<ESConfig>> listEsClusterConfigByClusterId(Long clusterId) {\n        List<ESConfigPO> esConfigs = esClusterConfigDAO.listByClusterId(clusterId);\n        List<ESConfigPO> respEsConfigs = Lists.newArrayList();\n\n        List<ESConfigPO> defaultConfigs = esClusterConfigDAO.listByClusterId(1L);\n        if (CollectionUtils.isEmpty(defaultConfigs)) {\n            return Result.buildFail(\"default configs template is empty\");\n        }\n\n        if (CollectionUtils.isEmpty(esConfigs)) {\n            return Result.buildSucc(ConvertUtil.list2List(respEsConfigs, ESConfig.class));\n        } else {\n            respEsConfigs.addAll(esConfigs);\n        }\n\n        return Result.buildSucc(ConvertUtil.list2List(respEsConfigs, ESConfig.class));\n    }\n\n    @Override\n    public ESConfig getEsClusterTemplateConfig(String type) {\n        return ConvertUtil.obj2Obj(\n            esClusterConfigDAO.getByClusterIdAndTypeAndEngin(SYSTEM_CLUSTER_ID, type, DEFAULT_CONFIG_TEMPLATE),\n            ESConfig.class);\n    }\n\n    @Override\n    public ESConfig getByClusterIdAndTypeAndEngin(Long clusterId, String type, String engin) {\n        return ConvertUtil.obj2Obj(esClusterConfigDAO.getByClusterIdAndTypeAndEngin(clusterId, type, engin),\n            ESConfig.class);\n    }\n\n    @Override\n    public ESConfig getEsClusterConfigById(Long id) {\n        return ConvertUtil.obj2Obj(esClusterConfigDAO.getValidEsConfigById(id), ESConfig.class);\n    }\n\n    @Override\n    public ESConfig getEsConfigById(Long id) {\n        return ConvertUtil.obj2Obj(esClusterConfigDAO.getById(id), ESConfig.class);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Long> esClusterConfigAction(ESConfigDTO param, EsConfigActionEnum actionEnum, String operator) {\n        Result<Void> r = checkParam(param, operator, actionEnum);\n        if (r.failed()) {\n            return Result.buildFrom(r);\n        }\n        param.setVersionConfig(DEFAULT_CONFIG_VERSION);\n        if (EDIT.getCode() == actionEnum.getCode()) {\n            ESConfig esConfig = getEsClusterConfigById(param.getId());\n            param.setVersionConfig(esConfig.getVersionConfig() + 1);\n        }\n        ESConfigPO esConfigPo = ConvertUtil.obj2Obj(param, ESConfigPO.class);\n\n        return Result.build(1 == esClusterConfigDAO.insertSelective(esConfigPo));\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> deleteEsClusterConfig(Long configId, String operator) {\n\n        return Result.build(1 == esClusterConfigDAO.delete(configId));\n    }\n\n    @Override\n    public Result<Void> setConfigValid(Long id) {\n        boolean success = 1 == esClusterConfigDAO.updateConfigValidById(id);\n        if (success) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> editConfigDesc(ESConfigDTO param) {\n        Result<Void> result = checkEditConfigValid(param);\n        if (result.failed()) {\n            return result;\n        }\n\n        try {\n            return Result.build(1 == esClusterConfigDAO.update(ConvertUtil.obj2Obj(param, ESConfigPO.class)));\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterConfigServiceImpl||method=editConfigDesc||\" + \"configId={}||msg={}\",\n                param.getId(), e);\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public Result<Void> deleteByClusterIdAndTypeAndEngin(Long clusterId, String typeName, String enginName) {\n        try {\n            esClusterConfigDAO.deleteByClusterIdAndTypeAndEngin(clusterId, typeName, enginName);\n            return Result.buildSuccWithMsg(\"集群角色下对应类型的配置已删除\");\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterConfigServiceImpl||method=deleteByClusterIdAndTypeAndEngin||msg={}\",\n                e.getStackTrace());\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public Result<Void> setOldConfigInvalid(ESConfig esConfig) {\n        int oldVersion = esConfig.getVersionConfig() - 1;\n        ESConfigPO esConfigPo = esClusterConfigDAO.getByClusterIdAndTypeAndEnginAndVersion(esConfig.getClusterId(),\n            esConfig.getTypeName(), esConfig.getEnginName(), oldVersion);\n        if (AriusObjUtils.isNull(esConfigPo)) {\n            return Result.buildFail(\"the old config is empty\");\n        }\n\n        esConfigPo.setSelected(0);\n        boolean success = 1 == esClusterConfigDAO.update(esConfigPo);\n        if (success) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail();\n    }\n\n    /*************************************************private**********************************************************/\n    private Result<Void> preCheck(ESZeusConfigDTO esZeusConfigDTO) {\n        if (AriusObjUtils.isBlack(esZeusConfigDTO.getClusterName())) {\n            return Result.buildFail(\"cluster name is empty\");\n        }\n\n        if (AriusObjUtils.isBlack(esZeusConfigDTO.getEnginName())) {\n            return Result.buildFail(\"engin name is empty\");\n        }\n\n        if (AriusObjUtils.isBlack(esZeusConfigDTO.getTypeName())) {\n            return Result.buildFail(\"type name is empty\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkParam(ESConfigDTO param, String operator, EsConfigActionEnum actionEnum) {\n        if (ADD.getCode() == actionEnum.getCode()) {\n            Result<Void> esConfigDTOIsEmpty = isEmpty(param, operator);\n            if (esConfigDTOIsEmpty.failed()) {\n                return esConfigDTOIsEmpty;\n            }\n\n            if (!AriusObjUtils.isNull(esClusterConfigDAO.getByClusterIdAndTypeAndEngin(param.getClusterId(),\n                param.getTypeName(), param.getEnginName()))) {\n                return Result.buildFail(\"config is exist, forbid repeat create config\");\n            }\n\n        } else if (EDIT.getCode() == actionEnum.getCode()) {\n            if (AriusObjUtils.isNull(param.getId())) {\n                return Result.buildParamIllegal(\"id is empty\");\n            }\n\n            if (AriusObjUtils.isNull(esClusterConfigDAO.getValidEsConfigById(param.getId()))) {\n                return Result.buildParamIllegal(\"config is not exist, please create first\");\n            }\n\n            if (AriusObjUtils.isNull(getEsClusterConfigById(param.getId()))) {\n                return Result.buildFail(\"es cluster config is empty\");\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> isEmpty(ESConfigDTO param, String operator) {\n        if (AriusObjUtils.isNull(param)) {\n            return Result.buildParamIllegal(\"esConfigDTO is empty\");\n        }\n\n        if (AriusObjUtils.isBlack(operator)) {\n            return Result.buildParamIllegal(\"operator is empty\");\n        }\n\n        if (AriusObjUtils.isBlack(param.getConfigData())) {\n            return Result.buildParamIllegal(\"config data is empty\");\n        }\n\n        if (AriusObjUtils.isBlack(param.getEnginName())) {\n            return Result.buildParamIllegal(\"engin name is empty\");\n        }\n\n        if (AriusObjUtils.isBlack(param.getTypeName())) {\n            return Result.buildParamIllegal(\"type name is empty\");\n        }\n\n        if (AriusObjUtils.isNull(param.getClusterId())) {\n            return Result.buildParamIllegal(\"clusterId name is empty\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> checkEditConfigValid(ESConfigDTO param) {\n        if (AriusObjUtils.isNull(param.getId())) {\n            return Result.buildParamIllegal(\"集群配置Id为空\");\n        }\n\n        ESConfigPO esConfig = esClusterConfigDAO.getById(param.getId());\n        if (AriusObjUtils.isNull(esConfig)) {\n            return Result.buildParamIllegal(\"集群配置不存在\");\n        }\n\n        if (AriusObjUtils.isBlack(esConfig.getConfigData())) {\n            return Result.buildParamIllegal(\"集群配置内容为空\");\n        }\n\n        if (esConfig.getConfigData().equals(param.getConfigData())) {\n            return Result.buildParamIllegal(\"不允许修改集群配置数据信息\");\n        }\n\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/impl/ESMachineNormsServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESMachineNormsPO;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESMachineNormsService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESMachineNormsDAO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * 容器规格列表 服务实现类\n * @author didi\n * @since 2020-08-24\n */\n@Service\npublic class ESMachineNormsServiceImpl implements ESMachineNormsService {\n\n    @Autowired\n    private ESMachineNormsDAO machineNormsDAO;\n\n    @Override\n    public List<ESMachineNormsPO> listMachineNorms() {\n        return machineNormsDAO.listMachineNorms();\n    }\n\n    @Override\n    public ESMachineNormsPO getById(Long id) {\n        return machineNormsDAO.getById(id);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/impl/ESPackageServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.ADD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.DELETE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.EDIT;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.UNKNOWN;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESPackageDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.espackage.ESPackage;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.espackage.ESPackagePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.FileCompressionType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ESVersionUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPackageService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.extend.storage.FileStorageService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESPackageDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author linyunan\n * @date 2021-05-19\n */\n@Service\npublic class ESPackageServiceImpl implements ESPackageService {\n    private static final ILog  LOGGER                   = LogFactory.getLog(ESPackageServiceImpl.class);\n\n    @Autowired\n    private ESPackageDAO       esPackageDAO;\n\n    @Autowired\n    private UserService        userService;\n    @Autowired\n    private RoleTool           roleTool;\n\n    @Autowired\n    private FileStorageService fileStorageService;\n\n    @Autowired\n    private ClusterPhyService  clusterPhyService;\n\n    private static final Long  MULTI_PART_FILE_SIZE_MAX = 1024 * 1024 * 500L;\n\n    @Override\n    public List<ESPackage> listESPackage() {\n        return ConvertUtil.list2List(esPackageDAO.listAll(), ESPackage.class);\n    }\n\n    @Override\n    public Result<Long> addESPackage(ESPackageDTO esPackageDTO, String operator) {\n        Result<Void> checkResult = checkValid(esPackageDTO, operator, ADD);\n        if (checkResult.failed()) {\n            return Result.buildFrom(checkResult);\n        }\n\n        if (isHostType(esPackageDTO)) {\n            Result<Void> uploadResult = upload(esPackageDTO);\n            if (uploadResult.failed()) {\n                return Result.buildFrom(uploadResult);\n            }\n        }\n\n        return saveESPackageToDB(esPackageDTO);\n    }\n\n    @Override\n    public Result<ESPackage> updateESPackage(ESPackageDTO esPackageDTO, String operator, Integer projectId) {\n        Result<Void> checkResult = checkValid(esPackageDTO, operator, EDIT);\n        if (checkResult.failed()) {\n            return Result.buildFrom(checkResult);\n        }\n\n        if (isHostType(esPackageDTO)) {\n            Result<Void> uploadResult = upload(esPackageDTO);\n            if (uploadResult.failed()) {\n                return Result.buildFrom(uploadResult);\n            }\n        }\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(id -> id, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n\n        return updatePackageToDB(esPackageDTO);\n    }\n\n    @Override\n    public ESPackage getESPackagePOById(Long id) {\n        return ConvertUtil.obj2Obj(esPackageDAO.getById(id), ESPackage.class);\n    }\n\n    @Override\n    public Result<Long> deleteESPackage(Long id, String operator) throws NotFindSubclassException {\n        // 集群版本删除操作时进行的参数校验\n        ESPackageDTO esPackageDTO = new ESPackageDTO();\n        esPackageDTO.setId(id);\n        Result<Void> checkResult = checkValid(esPackageDTO, operator, DELETE);\n        if (checkResult.failed()) {\n            return Result.buildFrom(checkResult);\n        }\n\n        // 在文件系统中删除对应的集群版本文件\n        ESPackagePO esPackagePO = esPackageDAO.getById(id);\n        Result<Void> response = fileStorageService\n            .remove(getUniqueFileName(ConvertUtil.obj2Obj(esPackagePO, ESPackage.class)));\n        if (response.failed()) {\n            return Result.buildFail(\"删除文件失败\");\n        }\n\n        // 删除数据库中id对应的集群版本的信息\n        boolean succ = (1 == esPackageDAO.delete(id));\n        return Result.build(succ, id);\n    }\n\n    @Override\n    public ESPackage getByVersionAndType(String esVersion, Integer manifest) {\n        return ConvertUtil.obj2Obj(esPackageDAO.getByVersionAndType(esVersion, manifest), ESPackage.class);\n    }\n\n    /*************************************************private**********************************************************/\n    private Result<Void> upload(ESPackageDTO esPackageDTO) {\n        Result<String> response = Result.buildFail();\n        try {\n            if (esPackageDTO.getUploadFile() != null) {\n                response = fileStorageService.upload(\n                    getUniqueFileName(ConvertUtil.obj2Obj(esPackageDTO, ESPackage.class)), esPackageDTO.getMd5(),\n                    esPackageDTO.getUploadFile());\n                if (response.success()) {\n                    esPackageDTO.setUrl(response.getData());\n                } else {\n                    return Result.buildFail(\"上传文件失败\");\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.info(\n                \"class=ESPackageServiceImpl||method=addESPlugin||uploadResponse={}||pluginName={}||exception={}\",\n                response.getMessage(), esPackageDTO.getFileName(), e);\n        }\n\n        return Result.buildSucc();\n    }\n\n    private boolean isHostType(ESPackageDTO esPackageDTO) {\n        return null == esPackageDTO.getManifest() || esPackageDTO.getManifest() == ESClusterTypeEnum.ES_HOST.getCode();\n    }\n\n    private Result<Void> checkValid(ESPackageDTO esPackageDTO, String operator, OperationEnum operation) {\n        if (AriusObjUtils.isNull(esPackageDTO)) {\n            return Result.buildParamIllegal(\"安装包为空\");\n        }\n\n        if (!roleTool.isAdmin(operator)) {\n            return Result.buildFail(\"非运维人员不能更新ES安装包!\");\n        }\n\n        if (operation.equals(UNKNOWN)) {\n            return Result.buildFail(\"操作类型未知\");\n        }\n\n        if (!ESVersionUtil.isValid(esPackageDTO.getEsVersion()) && !operation.equals(DELETE)) {\n            return Result.buildParamIllegal(\"版本号格式不正确, 必须是'1.1.1.1000'类似的格式\");\n        }\n\n        ESPackagePO packageByVersion = null;\n        if (operation.getCode() == ADD.getCode()) {\n            packageByVersion = esPackageDAO.getByVersionAndType(esPackageDTO.getEsVersion(),\n                esPackageDTO.getManifest());\n            if (esPackageDTO.getUploadFile().getSize() > MULTI_PART_FILE_SIZE_MAX) {\n                return Result.buildFail(\"es程序包[\" + esPackageDTO.getFileName() + \"]文件的大小超过限制，不能超过\"\n                                        + MULTI_PART_FILE_SIZE_MAX / 1024 / 1024 + \"M\");\n            }\n        } else if (operation.getCode() == EDIT.getCode()) {\n            packageByVersion = esPackageDAO.getByVersionAndManifestNotSelf(esPackageDTO.getEsVersion(),\n                esPackageDTO.getManifest(), esPackageDTO.getId());\n        } else if (operation.getCode() == DELETE.getCode()) {\n            if (null == esPackageDTO.getId()) {\n                return Result.buildFail(\"所要删除的集群版本字段为空\");\n            }\n\n            ESPackagePO esPackagePO = esPackageDAO.getById(esPackageDTO.getId());\n            if (esPackagePO == null) {\n                return Result.buildFail(\"对应id的集群版本不存在\");\n            }\n\n            if (clusterPhyService.isClusterExistsByPackageId(esPackageDTO.getId())) {\n                return Result.buildFail(\"版本已绑定集群无法删除\");\n            }\n\n        }\n\n        if (!AriusObjUtils.isNull(packageByVersion)) {\n            return Result.buildParamIllegal(\"版本号重复\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Long> saveESPackageToDB(ESPackageDTO esPackageDTO) {\n        ESPackagePO esPackagePO = ConvertUtil.obj2Obj(esPackageDTO, ESPackagePO.class);\n\n        boolean succ = Boolean.FALSE;\n        try {\n            succ = (1 == esPackageDAO.insert(esPackagePO));\n        } catch (Exception e) {\n            LOGGER.info(\"class=ESPackageServiceImpl||method=saveESPackageToDB||msg={}\", e.getMessage());\n        }\n\n        return Result.build(succ, esPackagePO.getId());\n    }\n\n    private Result<ESPackage> updatePackageToDB(ESPackageDTO esPackageDTO) {\n        ESPackagePO esPackagePO = ConvertUtil.obj2Obj(esPackageDTO, ESPackagePO.class);\n        boolean succ = Boolean.FALSE;\n        try {\n            succ = (1 == esPackageDAO.update(esPackagePO));\n        } catch (Exception e) {\n            LOGGER.info(\"class=ESPackageServiceImpl||method=updatePackageToDB||msg={}\", e.getMessage());\n        }\n\n        return Result.build(succ, ConvertUtil.obj2Obj(esPackagePO, ESPackage.class));\n    }\n\n    private String getUniqueFileName(ESPackage esPackage) {\n        return esPackage.getEsVersion() + \"-\" + esPackage.getManifest() + FileCompressionType.TAR_GZ;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/impl/ESPluginServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.ADD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.DELETE;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Plugin;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.PluginDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin.PluginPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.PluginVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.FileCompressionType;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PluginTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ESVersionUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPluginService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.core.service.extend.storage.FileStorageService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESPluginDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport com.google.common.collect.Maps;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.compress.utils.Lists;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.multipart.MultipartFile;\n\n/**\n * ES插件包管理 服务实现类\n *\n * @since 2020-08-24\n */\n@Service\npublic class ESPluginServiceImpl implements ESPluginService {\n\n    private static final ILog    LOGGER                   = LogFactory.getLog(ESPluginServiceImpl.class);\n\n    @Autowired\n    private ESPluginDAO          esPluginDAO;\n\n    private static final Long    MULTI_PART_FILE_SIZE_MAX = 1024 * 1024 * 100L;\n\n    @Autowired\n    private UserService          userService;\n\n    @Autowired\n    private ClusterPhyService    esClusterPhyService;\n\n    @Autowired\n    private OperateRecordService operateRecordService;\n\n    @Autowired\n    private ESClusterService     esClusterService;\n\n    @Autowired\n    private FileStorageService   fileStorageService;\n\n    private static final String  SEPARATOR                = \"-\";\n    @Autowired\n    private RoleTool             roleTool;\n\n    /**\n     * 相同名字的ES插件会有不同的版本，始终是显示最新的版本\n     * @return 插件类型列表\n     */\n    @Override\n    public List<PluginPO> listESPlugin() {\n        // 获取全部的插件列表\n        List<PluginPO> allESPlugins = esPluginDAO.listAll();\n\n        if (CollectionUtils.isEmpty(allESPlugins)) {\n            return Collections.emptyList();\n        }\n\n        // 展示更高版本的插件列表\n        Map<String, PluginPO> esPluginPOMap = new HashMap<>();\n        for (PluginPO pluginPO : allESPlugins) {\n            String pluginName = pluginPO.getName();\n            String pluginVersion = pluginPO.getVersion();\n\n            PluginPO esPluginTemp = esPluginPOMap.get(pluginName);\n            if (null == esPluginTemp) {\n                esPluginPOMap.put(pluginName, pluginPO);\n            } else {\n                String versionTemp = esPluginTemp.getVersion();\n                if (ESVersionUtil.isHigher(pluginVersion, versionTemp)) {\n                    esPluginPOMap.put(pluginName, pluginPO);\n                }\n            }\n        }\n\n        return new ArrayList<>(esPluginPOMap.values());\n    }\n\n    @Override\n    public List<PluginPO> listClusterAndDefaultESPlugin(String phyClusterId) {\n        List<PluginPO> pluginPOS = esPluginDAO.listByPhyClusterId(phyClusterId);\n        if (CollectionUtils.isEmpty(pluginPOS)) {\n            return new ArrayList<>();\n        }\n        return pluginPOS;\n    }\n\n    @Override\n    public Result<Long> addESPlugin(PluginDTO pluginDTO) throws NotFindSubclassException {\n        // 1.对插件信息的参数进行校验\n        Result<Void> resultCheck = paramCheck(pluginDTO, ADD, null);\n        if (resultCheck.failed()) {\n            return Result.buildFrom(resultCheck);\n        }\n\n        // 2.将对应的插件上传至配置的文件仓库\n        Result<String> response = Result.buildFail();\n        try {\n            response = fileStorageService.upload(getGiftName(ConvertUtil.obj2Obj(pluginDTO, Plugin.class)),\n                pluginDTO.getMd5(), pluginDTO.getUploadFile());\n        } catch (Exception e) {\n            LOGGER.info(\"class=ESPluginServiceImpl||method=addESPlugin||pluginName={}||msg=fail to upload the file\",\n                pluginDTO.getName());\n        }\n\n        // 3.上传成功后返回url，回写到插件信息对象中\n        if (response.success()) {\n            pluginDTO.setUrl(response.getData());\n        } else {\n            return Result.buildFail(\"上传文件失败\");\n        }\n\n        // 4.插件信息入DB\n        boolean succ = false;\n        PluginPO pluginPO = ConvertUtil.obj2Obj(pluginDTO, PluginPO.class);\n        try {\n            succ = (1 == esPluginDAO.insert(pluginPO));\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESPluginServiceImpl||method=addESPlugin||pluginName={}||msg=exception\",\n                pluginDTO.getName(), e);\n        }\n\n        // 5.插件信息入库失败，删除已经上传至文件仓库的文件\n        if (!succ) {\n            fileStorageService.remove(getGiftName(ConvertUtil.obj2Obj(pluginPO, Plugin.class)));\n            LOGGER.info(\"class=ESPluginServiceImpl||method=addESPlugin||pluginName={}||msg=fail to upload the file\",\n                pluginDTO.getName());\n        }\n\n        return Result.build(succ, pluginPO.getId());\n    }\n\n    /**\n     * 校验唯一性的过程就和名称的唯一性结合\n     * @param pluginDTO ES插件\n     * @param operator  操作人\n     * @return\n     */\n    @Override\n    public Result<Void> updateESPluginDesc(PluginDTO pluginDTO, String operator) {\n        PluginPO oldPlugin = esPluginDAO.getById(pluginDTO.getId());\n\n        // 检验插件信息\n        if (oldPlugin == null) {\n            return Result.buildFail(\"当前插件不存在\");\n        }\n        boolean succ = (1 == esPluginDAO.updateDesc(oldPlugin.getId(), pluginDTO.getDesc()));\n\n        if (succ) {\n            PluginPO newPluginPo = esPluginDAO.getById(oldPlugin.getId());\n            PluginVO oldPluginVO = ConvertUtil.obj2Obj(oldPlugin, PluginVO.class);\n            PluginVO newPluginVO = ConvertUtil.obj2Obj(newPluginPo, PluginVO.class);\n            Map</*apiModelPropertyValue*/String, /*修改后的apiModelPropertyValue*/String> apiModelPropertyValueModify = Maps\n                .newHashMap();\n            apiModelPropertyValueModify.put(\"上传插件类型: 0 系统默认插件, 1 ES能力插件, 2 平台能力插件\", \"上传插件类型\");\n            operateRecordService.saveOperateRecordWithManualTrigger(\n                    AriusObjUtils.findChangedWithClearByBeanVo(oldPluginVO, newPluginVO, apiModelPropertyValueModify),\n                    operator, AuthConstant.SUPER_PROJECT_ID, pluginDTO.getId(), OperateTypeEnum.ES_CLUSTER_PLUGINS_EDIT\n            );\n        }\n        return Result.build(succ);\n    }\n\n    @Override\n    public PluginPO getESPluginById(Long id) {\n        return esPluginDAO.getById(id);\n    }\n\n    @Override\n    public Result<Long> deletePluginById(Long id, String operator) throws NotFindSubclassException {\n        PluginDTO pluginDTO = new PluginDTO();\n        pluginDTO.setId(id);\n\n        // 插件删除操作的参数校验\n        Result<Void> result = paramCheck(pluginDTO, DELETE, operator);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n\n        // 文件系统删除插件\n        PluginPO pluginPO = esPluginDAO.getById(id);\n        Result<Void> response = fileStorageService.remove(getGiftName(ConvertUtil.obj2Obj(pluginPO, Plugin.class)));\n        if (response.failed()) {\n            return Result.buildFail(\"删除文件失败\");\n        }\n\n        // 删除DB插件信息\n        boolean succ = (1 == esPluginDAO.delete(id));\n        if (succ) {\n            operateRecordService.save(new OperateRecord.Builder().bizId(pluginDTO.getId()).userOperation(operator)\n                .operationTypeEnum(OperateTypeEnum.ES_CLUSTER_PLUGINS_DELETE)\n                .triggerWayEnum(TriggerWayEnum.MANUAL_TRIGGER).build());\n        }\n\n        return Result.build(succ, id);\n    }\n\n    @Override\n    public String getAllSysDefaultPluginIds() {\n        List<PluginPO> list = esPluginDAO.getAllSysDefaultPlugins();\n        List<Long> idList = list.stream().map(PluginPO::getId).collect(Collectors.toList());\n        return ListUtils.longList2String(idList);\n    }\n\n    @Override\n    public List<Plugin> getPluginsByClusterName(String clusterName) {\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterByName(clusterName);\n        if (clusterPhy == null) {\n            return Collections.emptyList();\n        }\n\n        String plugIds = clusterPhy.getPlugIds();\n\n        List<Long> longIds = ListUtils.string2LongList(plugIds);\n        List<PluginPO> plugsList = esPluginDAO.listByPlugIds(longIds);\n\n        return ConvertUtil.list2List(plugsList, Plugin.class);\n    }\n\n    @Override\n    public Result<String> addESPlugins(List<PluginDTO> pluginDTOS) throws NotFindSubclassException {\n        List<String> addFail = Lists.newArrayList();\n\n        // 分批次上传插件，并记录上传失败的插件名称\n        for (PluginDTO pluginDTO : pluginDTOS) {\n            Result<Long> result = addESPlugin(pluginDTO);\n            if (result.failed()) {\n                addFail.add(pluginDTO.getFileName());\n            }\n        }\n\n        return Result.build(addFail.isEmpty(), \"上传插件失败,失败的插件名有：\" + addFail);\n    }\n\n    /**\n     * 检验需要进行 delete add updateDsc 传递的插件的参数的基本信息\n     * @param pluginDTO 上传的插件\n     * @return 校验结果\n     */\n    private Result<Void> paramCheck(PluginDTO pluginDTO, OperationEnum operationEnum, String operator) {\n        if (ADD.equals(operationEnum)) {\n            Result<Void> result = handleAdd(pluginDTO);\n            if (result.failed()) {\n                return result;\n            }\n        } else if (DELETE.equals(operationEnum)) {\n            Result<Void> result = handleDelete(pluginDTO, operator);\n            if (result.failed()) {\n                return result;\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleDelete(PluginDTO pluginDTO, String operator) {\n        if (!roleTool.isAdmin(operator)) {\n            return Result.buildFail(\"非运维人员不能删除插件\");\n        }\n\n        Long id = pluginDTO.getId();\n        if (null == id) {\n            return Result.buildFail(\"插件id为空\");\n        }\n\n        PluginPO pluginPO = getESPluginById(id);\n        if (null == pluginPO) {\n            return Result.buildFail(\"对应的插件不存在\");\n        }\n\n        // 校验集群是否已经安装了指定的插件，如已安装，则首先需要卸载插件\n        List<Long> pluginIds = ListUtils.string2LongList(\n            esClusterPhyService.getClusterById(Integer.valueOf(pluginPO.getPhysicClusterId())).getPlugIds());\n        if (pluginIds.contains(id)) {\n            return Result.buildFail(\"该插件已安装，请先卸载\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleAdd(PluginDTO pluginDTO) {\n        if (AriusObjUtils.isNull(pluginDTO)) {\n            return Result.buildFail(\"插件为空\");\n        }\n\n        if (pluginDTO.getPhysicClusterId() == null) {\n            return Result.buildFail(\"物理集群id为空\");\n        }\n\n        if (null == esClusterPhyService.getClusterById(Integer.valueOf(pluginDTO.getPhysicClusterId()))) {\n            return Result.buildFail(\"物理集群id不存在\");\n        }\n\n        if (pluginDTO.getUploadFile() == null) {\n            return Result.buildFail(\"文件不存在\");\n        }\n\n        // 根据插件的类型进行对应的插件文件校验\n        switch (PluginTypeEnum.valueOf(pluginDTO.getPDefault())) {\n            case ES_PLUGIN:\n                return verifyESPluginFileAndModifyPluginName(pluginDTO);\n            case ADMIN_PLUGIN:\n                return verifyAdminPluginFileAndModifyPluginVersion(pluginDTO);\n            case DEFAULT_PLUGIN:\n                return Result.buildFail(\"不允许上传系统默认插件\");\n            default:\n                return Result.buildFail(\"上传插件类型未知\");\n        }\n    }\n\n    /**\n     * 对于平台能力的插件进行内容的校验\n     * @param pluginDTO 插件\n     * @return 校验结果\n     */\n    private Result<Void> verifyAdminPluginFileAndModifyPluginVersion(PluginDTO pluginDTO) {\n        if (null == pluginDTO.getVersion()) {\n            pluginDTO.setVersion(AdminConstant.DEFAULT_PLUGIN_VERSION);\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 校验某个ES能力插件文件的合法性\n     * @param pluginDTO 插件\n     * @return 校验结果\n     */\n    private Result<Void> verifyESPluginFileAndModifyPluginName(PluginDTO pluginDTO) {\n        MultipartFile pluginFile = pluginDTO.getUploadFile();\n        if (pluginDTO.getUploadFile().getSize() > MULTI_PART_FILE_SIZE_MAX) {\n            return Result.buildFail(\n                \"插件[\" + pluginDTO.getName() + \"]文件的大小超过限制，不能超过\" + MULTI_PART_FILE_SIZE_MAX / 1024 / 1024 + \"M\");\n        }\n        // 读取插件配置信息\n        Map<String, String> propsMap = readFromProperties(pluginFile);\n\n        // 校验 plugin-descriptor.properties 文件是否存在\n        if (MapUtils.isEmpty(propsMap)) {\n            return Result.buildFail(\"插件压缩包中没有 plugin-descriptor.properties 文件！\");\n        }\n\n        // 校验 name\n        final String name = propsMap.remove(\"name\");\n        if (name == null || name.isEmpty()) {\n            return Result.buildFail(\"property [name] is missing in [\" + pluginFile.getName() + \"]\");\n        }\n        pluginDTO.setName(name);\n\n        // 校验 description\n        final String description = propsMap.remove(\"description\");\n        if (description == null) {\n            return Result.buildFail(\"property [description] is missing for plugin [\" + name + \"]\");\n        }\n\n        // 校验 version\n        final String version = propsMap.remove(\"version\");\n        if (version == null) {\n            return Result.buildFail(\"property [version] is missing for plugin [\" + name + \"]\");\n        }\n        if (!ESVersionUtil.isValid(version)) {\n            return Result.buildFail(\"插件[\" + pluginDTO.getName() + \"]的版本号不符合规则，必须是'1.1.1.1'类似的格式\");\n        }\n        // 插件的版本格式是什么样的\n        pluginDTO.setVersion(version);\n\n        // 校验 elasticsearch.version\n        final String esVersion = propsMap.get(\"elasticsearch.version\");\n        if (esVersion == null) {\n            return Result.buildFail(\"property [version] is missing for plugin [\" + name + \"]\");\n        }\n\n        // 获取当前部署集群的es版本\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(Integer.valueOf(pluginDTO.getPhysicClusterId()));\n        if (AriusObjUtils.isNull(clusterPhy) || AriusObjUtils.isNull(clusterPhy.getCluster())) {\n            return Result.buildFail(\"插件上传的物理集群不存在\");\n        }\n\n        // 从es集群获取实时生效的版本号\n        String esVersionFromESClient = null;\n        try {\n            esVersionFromESClient = esClusterService.synGetESVersionByCluster(clusterPhy.getCluster());\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=ESClusterServiceImpl||method=verifyESPluginFileAndModifyPluginName||clusterName={}||errMsg=fail to get esversion\",\n                    clusterPhy.getCluster(),e);\n            return Result.buildFail(\"获取物理集群版本出现异常\");\n        }\n        if (esVersionFromESClient == null) {\n            return Result.buildFail(\"无法从物理集群获取版本\");\n        }\n\n        // 这里兼容内部4位版本\n        if (!esVersion.startsWith(esVersionFromESClient)) {\n            return Result.buildFail(\"插件适配的es版本和当前运行的es集群版本号不匹配\");\n        }\n\n        // 校验 classname\n        final String classname = propsMap.remove(\"classname\");\n        if (classname == null) {\n            return Result.buildFail(\"property [classname] is missing for plugin [\" + name + \"]\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 从插件中的 plugin-descriptor.properties 文件中读取插件配置信息\n     * @param pluginFile 插件压缩包\n     * @return 插件配置信息\n     */\n    private Map<String, String> readFromProperties(MultipartFile pluginFile) {\n        InputStream bis = null;\n        String fileName = pluginFile.getOriginalFilename();\n        if (null == fileName) {\n            LOGGER.warn(\n                \"class=ESPluginServiceImpl||method=readFromProperties||errmsg = MultipartFile.getOriginalFilename() is null \");\n            return null;\n        }\n        Properties props = new Properties();\n\n        try {\n            if (fileName.endsWith(FileCompressionType.TAR) || fileName.endsWith(FileCompressionType.TAR_GZ)) {\n                bis = CommonUtils.unTar(pluginFile.getInputStream(), \"plugin-descriptor.properties\");\n            } else if (fileName.endsWith(FileCompressionType.ZIP)) {\n                bis = CommonUtils.unZip(pluginFile.getInputStream(), \"plugin-descriptor.properties\");\n            } else {\n                throw new IllegalStateException(\"插件文件类型不合法！\");\n            }\n\n            // 说明压缩包中不存在 plugin-descriptor.properties 文件\n            if (bis == null) {\n                return null;\n            }\n\n            // 将插件的 plugin-descriptor.properties 文件加载到 Properties 对象中\n            props.load(bis);\n        } catch (Exception e) {\n            LOGGER.info(\"class=ESPluginServiceImpl||method=readFromProperties||exception={}\"\n                        + \"msg = 读取 plugin-descriptor.properties 文件失败\",\n                e);\n            return null;\n        } finally {\n            if (bis != null) {\n                try {\n                    bis.close();\n                } catch (IOException e) {\n                    LOGGER.info(\"class=ESPluginServiceImpl||method=readFromProperties||exception={}\"\n                                + \"msg = 读取 plugin-descriptor.properties 文件失败\",\n                        e);\n                }\n            }\n        }\n\n        return props.stringPropertyNames().stream().collect(Collectors.toMap(Function.identity(), props::getProperty));\n    }\n\n    /**\n     * 重构上传至文件仓库系统的名称，作为文件存储的唯一键\n     * @param plugin 插件信息\n     * @return 唯一区别的名称\n     */\n    private String getGiftName(Plugin plugin) {\n        return plugin.getName() + SEPARATOR + plugin.getVersion() + SEPARATOR + plugin.getPhysicClusterId() + SEPARATOR\n               + plugin.getPDefault() + FileCompressionType.TAR_GZ;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/impl/EcmHandleServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.MASTER_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_DOCKER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum.ES_HOST;\nimport static java.util.Objects.nonNull;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EsConfigAction;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EsPluginAction;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.elasticcloud.ElasticCloudCommonActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmOperateAppBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmSubTaskLog;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmTaskStatus;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.espackage.ESPackage;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESClusterMethodNameEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.threadpool.AriusTaskThreadPool;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPackageService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.EcmHandleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl.handler.AbstractEcmBaseHandle;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl.handler.EcmDockerHandler;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl.handler.EcmHostHandler;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.EcmActionEnum;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.service.UserService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Multimap;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.BiFunction;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * ES集群表 服务实现类\n * @author didi\n * @since 2020-08-24\n */\n@Service\n@NoArgsConstructor\npublic class EcmHandleServiceImpl implements EcmHandleService {\n\n    private static final ILog LOGGER                           = LogFactory\n        .getLog(EcmHandleServiceImpl.class);\n\n    @Autowired\n    private ClusterPhyService                   esClusterPhyService;\n\n    @Autowired\n    private ClusterRoleService                  clusterRoleService;\n\n    @Autowired\n    private ClusterRoleHostService              clusterRoleHostService;\n\n    @Autowired\n    private EcmDockerHandler                    ecmDockerHandler;\n\n    @Autowired\n    private EcmHostHandler                      ecmHostHandler;\n\n    @Autowired\n    private OperateRecordService                operateRecordService;\n\n    @Autowired\n    private ESPackageService                    esPackageService;\n\n    @Autowired\n    private UserService                         userService;\n    @Autowired\n    private ProjectService                      projectService;\n\n    private AriusTaskThreadPool                 ariusTaskThreadPool;\n\n    private Map<Integer, AbstractEcmBaseHandle> ecmBaseHandleMap                 = new HashMap<>();\n\n    private static final int                    DELETE_ODIN_TREE_MAX_RETRY_TIMES = 1 << 6;\n\n    private static final String                 CLUSTER_NOT_EXIST                = \"%d对应的物理集群不存在\";\n\n    private static final String                 UNKNOWN_TYPE                     = \"未知类型，请确认类型为(docker/host)\";\n\n    @PostConstruct\n    public void init() {\n        ariusTaskThreadPool = new AriusTaskThreadPool();\n        ariusTaskThreadPool.init(10, \"EcmHandleServiceImpl\", 100);\n        ecmBaseHandleMap.put(ecmHostHandler.getEsClusterTypeEnum().getCode(), ecmHostHandler);\n        ecmBaseHandleMap.put(ecmDockerHandler.getEsClusterTypeEnum().getCode(), ecmDockerHandler);\n    }\n\n    @Override\n    public Result<Long> saveESCluster(List<EcmParamBase> ecmParamBaseList) {\n        Result<Void> checkResult = checkValidForEsCluster(ecmParamBaseList);\n        if (checkResult.failed()) {\n            return Result.buildFrom(checkResult);\n        }\n\n        AbstractEcmBaseHandle ecmBaseHandle = getByClusterType(ecmParamBaseList.get(0).getType());\n        if (null == ecmBaseHandle) {\n            return Result.buildNotExist(UNKNOWN_TYPE);\n        }\n\n        Result<Long> saveResult = ecmBaseHandle.saveESCluster(ecmParamBaseList);\n        if (saveResult.failed()) {\n            return Result.buildFrom(saveResult);\n        }\n        return Result.buildSucc(saveResult.getData());\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> startESCluster(EcmParamBase ecmParamBase, String operator) {\n        // 接口调用\n        return callESClusterBaseHandle(\"集群启动\", ecmParamBase.getPhyClusterId(), operator, ecmParamBase,\n            (withoutUsed, esClusterBaseHandle) -> esClusterBaseHandle.startESCluster(ecmParamBase));\n    }\n\n    @Override\n    public Result<Void> deleteESCluster(Long clusterId, String operator) {\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> scaleESCluster(EcmParamBase actionParamBase, String operator) {\n        // 补充参数\n        Result<EcmParamBase> actionParamBaseResult = supplyCommonActionParamBase(actionParamBase.getPhyClusterId(),\n            actionParamBase.getRoleName(), actionParamBase);\n        if (actionParamBaseResult.failed()) {\n            return Result.buildFrom(actionParamBaseResult);\n        }\n\n        // 调用接口\n        return callESClusterBaseHandle(\"集群扩缩容\", actionParamBase.getPhyClusterId(), operator,\n            actionParamBaseResult.getData(),\n            (withoutUsed, esClusterBaseHandle) -> esClusterBaseHandle.scaleESCluster(actionParamBaseResult.getData()));\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> upgradeESCluster(EcmParamBase ecmParamBase, String operator) {\n        // 构造请求参数\n        Result<EcmParamBase> actionParamBaseResult = supplyCommonActionParamBase(ecmParamBase.getPhyClusterId(),\n            ecmParamBase.getRoleName(), ecmParamBase);\n\n        if (actionParamBaseResult.failed()) {\n            return Result.buildFrom(actionParamBaseResult);\n        }\n\n        // 接口调用\n        return callESClusterBaseHandle(\"集群升级\", ecmParamBase.getPhyClusterId(), operator,\n            actionParamBaseResult.getData(), (withoutUsed, esClusterBaseHandle) -> esClusterBaseHandle\n                .upgradeESCluster(actionParamBaseResult.getData()));\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> restartESCluster(EcmParamBase ecmParamBase, String operator) {\n        // 构造请求参数\n        Result<EcmParamBase> actionParamBaseResult = supplyCommonActionParamBase(ecmParamBase.getPhyClusterId(),\n            ecmParamBase.getRoleName(), ecmParamBase);\n        if (actionParamBaseResult.failed()) {\n            return Result.buildFrom(actionParamBaseResult);\n        }\n\n        // 接口调用\n        return callESClusterBaseHandle(\"集群重启\", ecmParamBase.getPhyClusterId(), operator,\n            actionParamBaseResult.getData(), (withoutUsed, esClusterBaseHandle) -> esClusterBaseHandle\n                .restartESCluster(actionParamBaseResult.getData()));\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> actionUnfinishedESCluster(EcmActionEnum ecmActionEnum, EcmParamBase ecmParamBase,\n                                                               String hostname, String operator) {\n        // 构造请求参数\n        Result<EcmParamBase> actionParamBaseResult = supplyCommonActionParamBase(ecmParamBase.getPhyClusterId(),\n            ecmParamBase.getRoleName(), ecmParamBase);\n        if (actionParamBaseResult.failed()) {\n            return Result.buildFrom(actionParamBaseResult);\n        }\n\n        // 接口调用\n        return callESClusterBaseHandle(\"集群\" + ecmActionEnum.getAction(), ecmParamBase.getPhyClusterId(), operator,\n            actionParamBaseResult.getData(), (withoutUsed, esClusterBaseHandle) -> esClusterBaseHandle\n                .actionNotFinishedTask(actionParamBaseResult.getData(), ecmActionEnum, hostname));\n    }\n\n    @Override\n    public Result<String> infoESCluster(Long clusterId, String operator) {\n        // 构造请求参数\n        Result<EcmParamBase> actionParamBaseResult = buildActionParamBase(clusterId, null);\n        if (actionParamBaseResult.failed()) {\n            return Result.buildFrom(actionParamBaseResult);\n        }\n\n        return callESClusterBaseHandle(\"集群信息获取\", clusterId, operator, actionParamBaseResult.getData(),\n            (actionParamBase, esClusterBaseHandle) -> esClusterBaseHandle.infoESCluster(actionParamBase));\n    }\n\n    @Override\n    public Result<EcmSubTaskLog> getSubTaskLog(EcmParamBase ecmParamBase, String hostname, String operator) {\n        return callESClusterBaseHandle(\"集群日志收集\", ecmParamBase.getPhyClusterId(), operator, ecmParamBase,\n            (withoutUsed, esClusterBaseHandle) -> esClusterBaseHandle\n                .getSubTaskLog(ecmParamBase.getTaskId().longValue(), hostname, ecmParamBase));\n    }\n\n    @Override\n    public Result<List<EcmTaskStatus>> getESClusterStatus(EcmParamBase ecmParamBase, Integer orderType,\n                                                          String operator) {\n        return callESClusterBaseHandle(\"集群状态\", ecmParamBase.getPhyClusterId(), operator, ecmParamBase,\n            (withoutUsed, esClusterBaseHandle) -> esClusterBaseHandle.getTaskStatus(ecmParamBase, orderType), false);\n    }\n\n    @Override\n    public Result<List<EcmParamBase>> buildEcmParamBaseListWithConfigAction(Integer phyClusterId,\n                                                                            List<String> roleNameList,\n                                                                            Multimap<String, Long> role2ConfigIdsMultiMap,\n                                                                            Integer actionType) {\n        return buildEcmParamBaseListInner(phyClusterId, roleNameList, role2ConfigIdsMultiMap, actionType, null);\n    }\n\n    @Override\n    public Result<List<EcmParamBase>> buildEcmParamBaseListWithEsPluginAction(Integer phyClusterId,\n                                                                              List<String> roleNameList,\n                                                                              Long esPluginId, Integer actionType) {\n        return buildEcmParamBaseListInner(phyClusterId, roleNameList, null, actionType, esPluginId);\n    }\n\n    @Override\n    public Result<List<EcmParamBase>> buildEcmParamBaseList(Integer phyClusterId, List<String> roleNameList) {\n        return buildEcmParamBaseListInner(phyClusterId, roleNameList, null, null, null);\n    }\n\n    private Result<List<EcmParamBase>> buildEcmParamBaseListInner(Integer phyClusterId, List<String> roleNameList,\n                                                                  Multimap<String, Long> role2ConfigIdsMultiMap,\n                                                                  Integer actionType, Long pluginId) {\n        if (AriusObjUtils.isEmptyList(roleNameList)) {\n            return Result.buildSucc(new ArrayList<>());\n        }\n\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(phyClusterId);\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return Result.buildFail(String.format(CLUSTER_NOT_EXIST, phyClusterId));\n        }\n\n        List<String> masterHostList = clusterRoleHostService\n            .getHostNamesByRoleAndClusterId(clusterPhy.getId().longValue(), MASTER_NODE.getDesc());\n\n        List<EcmParamBase> ecmParamBaseList = new ArrayList<>();\n        for (String roleName : roleNameList) {\n            String newRoleName = roleName;\n            if (newRoleName.startsWith(clusterPhy.getCluster())) {\n                newRoleName = newRoleName.replaceFirst(clusterPhy.getCluster() + \"-\", \"\");\n            }\n\n            if (ES_DOCKER.getCode() == clusterPhy.getType()) {\n                Result<EcmParamBase> buildElasticCloudParamBase = buildElasticCloudParamBase(clusterPhy, newRoleName,\n                    role2ConfigIdsMultiMap, actionType);\n                if (buildElasticCloudParamBase.failed()) {\n                    return Result.buildFrom(buildElasticCloudParamBase);\n                }\n                ecmParamBaseList.add(buildElasticCloudParamBase.getData());\n            } else if (ES_HOST.getCode() == clusterPhy.getType()) {\n                Result<EcmParamBase> buildHostParamBase = buildHostParamBase(clusterPhy, newRoleName, masterHostList,\n                    role2ConfigIdsMultiMap, pluginId, actionType);\n                if (buildHostParamBase.failed()) {\n                    return Result.buildFrom(buildHostParamBase);\n                }\n                ecmParamBaseList.add(buildHostParamBase.getData());\n            }\n        }\n        return Result.buildSucc(ecmParamBaseList);\n    }\n\n    /**************************************** private method ****************************************************/\n\n    private Result<EcmParamBase> buildHostParamBase(ClusterPhy clusterPhy, String roleName, List<String> masterHostList,\n                                                    Multimap<String, Long> role2ConfigIdsMultiMap, Long pluginId,\n                                                    Integer actionType) {\n        HostParamBase hostParamBase = new HostParamBase();\n        hostParamBase.setPhyClusterId(clusterPhy.getId().longValue());\n        hostParamBase.setPhyClusterName(clusterPhy.getCluster());\n        hostParamBase.setRoleName(roleName);\n        hostParamBase.setType(clusterPhy.getType());\n        hostParamBase.setMasterHostList(masterHostList);\n\n        // ES集群配置回调设置, 在事件回调处调用\n        if (!AriusObjUtils.isNull(role2ConfigIdsMultiMap) && !AriusObjUtils.isNull(actionType)) {\n            List<Long> configs = (List<Long>) role2ConfigIdsMultiMap.get(roleName);\n            hostParamBase.setEsConfigAction(new EsConfigAction(actionType, configs));\n        }\n\n        // ES集群插件回调设置, 在事件回调处调用\n        if (!AriusObjUtils.isNull(pluginId)) {\n            hostParamBase.setEsPluginAction(new EsPluginAction(actionType, pluginId));\n        }\n\n        ClusterRoleInfo clusterRoleInfo = clusterRoleService.getByClusterIdAndRole(clusterPhy.getId().longValue(),\n            roleName);\n        if (null == clusterRoleInfo) {\n            hostParamBase.setEsVersion(clusterPhy.getEsVersion());\n            // 根据物理集群的版本号获取对应的镜像地址\n            ESPackage esPackage = esPackageService.getByVersionAndType(clusterPhy.getEsVersion(), clusterPhy.getType());\n            if (AriusObjUtils.isNull(esPackage)) {\n                return Result.buildParamIllegal(String.format(\"传入的版本号: %s 有误\", clusterPhy.getEsVersion()));\n            }\n            hostParamBase.setImageName(esPackage.getUrl());\n            return Result.buildSucc(hostParamBase);\n        }\n\n        // 根绝role_cluster获取对应ecm操作的es集群版本号\n        ESPackage esPackage = esPackageService.getByVersionAndType(clusterRoleInfo.getEsVersion(), ES_HOST.getCode());\n        if (AriusObjUtils.isNull(esPackage)) {\n            return Result.buildParamIllegal(String.format(\"传入的版本号: %s 有误\", clusterRoleInfo.getEsVersion()));\n        }\n\n        hostParamBase.setPidCount(clusterRoleInfo.getPidCount());\n        hostParamBase.setEsVersion(clusterRoleInfo.getEsVersion());\n        hostParamBase.setImageName(esPackage.getUrl());\n\n        List<String> hostList = clusterRoleHostService.getHostNamesByRoleAndClusterId(clusterPhy.getId().longValue(),\n            roleName);\n        hostParamBase.setHostList(hostList);\n        if (!CollectionUtils.isEmpty(hostList)) {\n            hostParamBase.setNodeNumber(hostList.size());\n        } else {\n            hostParamBase.setNodeNumber(0);\n        }\n\n        return Result.buildSucc(hostParamBase);\n    }\n\n    private Result<EcmParamBase> buildElasticCloudParamBase(ClusterPhy clusterPhy, String roleName,\n                                                            Multimap<String, Long> role2ConfigIdsMultiMap,\n                                                            Integer actionType) {\n        ElasticCloudCommonActionParam elasticCloudCommonActionParam = ConvertUtil.obj2Obj(clusterPhy,\n            ElasticCloudCommonActionParam.class);\n\n        if (!AriusObjUtils.isNull(role2ConfigIdsMultiMap) && !AriusObjUtils.isNull(actionType)) {\n            List<Long> configs = (List<Long>) role2ConfigIdsMultiMap.get(roleName);\n            elasticCloudCommonActionParam.setEsConfigActions(new EsConfigAction(actionType, configs));\n        }\n\n        elasticCloudCommonActionParam.setPhyClusterId(clusterPhy.getId().longValue());\n        elasticCloudCommonActionParam.setPhyClusterName(clusterPhy.getCluster());\n\n        elasticCloudCommonActionParam.setRoleName(roleName);\n        elasticCloudCommonActionParam.setMachineRoom(clusterPhy.getIdc());\n\n        ClusterRoleInfo clusterRoleInfo = clusterRoleService.getByClusterIdAndRole(clusterPhy.getId().longValue(),\n            roleName);\n        ESPackage esPackage = esPackageService.getByVersionAndType(clusterRoleInfo.getEsVersion(), ES_DOCKER.getCode());\n        if (AriusObjUtils.isNull(esPackage)) {\n            return Result.buildParamIllegal(String.format(\"传入的版本号: %s 有误\", clusterRoleInfo.getEsVersion()));\n        }\n\n        elasticCloudCommonActionParam.setNodeNumber(clusterRoleInfo.getPidCount());\n        elasticCloudCommonActionParam.setEsVersion(clusterRoleInfo.getEsVersion());\n        elasticCloudCommonActionParam.setImageName(esPackage.getUrl());\n\n        return Result.buildSucc(elasticCloudCommonActionParam);\n    }\n\n    private Result<EcmParamBase> supplyCommonActionParamBase(Long clusterId, String roleName,\n                                                             EcmParamBase actionParamBase) {\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(clusterId.intValue());\n        if (null == clusterPhy) {\n            return Result.buildNotExist(String.format(CLUSTER_NOT_EXIST, clusterId.intValue()));\n        }\n\n        AbstractEcmBaseHandle esClusterBaseHandle = getByClusterType(clusterPhy.getType());\n        if (null == esClusterBaseHandle) {\n            return Result.buildNotExist(UNKNOWN_TYPE);\n        }\n\n        if (actionParamBase instanceof HostParamBase) {\n            // 增加对应角色的端口号注入\n            HostParamBase hostParamBase = (HostParamBase) actionParamBase;\n            Result<String> result = getPortFromHost(clusterId, hostParamBase.getRoleName());\n            if (result.failed()) {\n                return Result.buildFrom(result);\n            }\n            hostParamBase.setPort(result.getData());\n        }\n\n        actionParamBase.setPhyClusterId(clusterId);\n        actionParamBase.setPhyClusterName(clusterPhy.getCluster());\n        if (AriusObjUtils.isBlank(roleName) || ESClusterTypeEnum.ES_HOST.getCode() == clusterPhy.getType()) {\n            return Result.buildSucc(actionParamBase);\n        }\n\n        // 弹性云集群 补充角色信息\n        String newRoleName = roleName.startsWith(clusterPhy.getCluster()) ? roleName\n            : clusterPhy.getCluster() + \"-\" + roleName;\n        ElasticCloudCommonActionParam elasticCloudCommonActionParam = (ElasticCloudCommonActionParam) actionParamBase;\n        ClusterRoleInfo clusterRoleInfo = clusterRoleService.getByClusterIdAndClusterRole(clusterId, newRoleName);\n        if (null == clusterRoleInfo) {\n            return Result.buildNotExist(String.format(\"%d对应的物理集群%s角色不存在\", clusterId, roleName));\n        }\n        elasticCloudCommonActionParam.setMachineRoom(clusterPhy.getIdc());\n        elasticCloudCommonActionParam.setNsTree(clusterPhy.getNsTree());\n        elasticCloudCommonActionParam.setRoleName(clusterRoleInfo.getRole());\n\n        return Result.buildSucc(elasticCloudCommonActionParam);\n    }\n\n    private Result<String> getPortFromHost(Long clusterId, String roleName) {\n        List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService.getByRoleAndClusterId(clusterId, roleName);\n        if (CollectionUtils.isEmpty(clusterRoleHosts)) {\n            return Result.buildSucc(ClusterConstant.DEFAULT_PORT, \"获取默认配置端口\");\n        }\n        return Result.buildSucc(clusterRoleHosts.get(0).getPort(), \"角色端口获取成功\");\n    }\n\n    private Result<EcmParamBase> buildActionParamBase(Long clusterId, String roleName) {\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(clusterId.intValue());\n        if (null == clusterPhy) {\n            return Result.buildNotExist(String.format(CLUSTER_NOT_EXIST, clusterId));\n        }\n\n        ClusterRoleInfo clusterRoleInfo = clusterRoleService.getByClusterIdAndClusterRole(clusterId, roleName);\n        if (null == clusterRoleInfo) {\n            return Result.buildNotExist(String.format(\"%d对应的物理集群%s角色不存在\", clusterId, roleName));\n        }\n\n        AbstractEcmBaseHandle esClusterBaseHandle = getByClusterType(clusterPhy.getType());\n        if (null == esClusterBaseHandle) {\n            return Result.buildNotExist(UNKNOWN_TYPE);\n        }\n        ElasticCloudCommonActionParam elasticCloudCommonActionParam = new ElasticCloudCommonActionParam(clusterId,\n            roleName);\n\n        elasticCloudCommonActionParam.setPhyClusterId(clusterId);\n        elasticCloudCommonActionParam.setPhyClusterName(clusterPhy.getCluster());\n        elasticCloudCommonActionParam.setType(clusterPhy.getType());\n\n        elasticCloudCommonActionParam.setRoleName(clusterRoleInfo.getRole());\n        elasticCloudCommonActionParam.setNsTree(clusterPhy.getNsTree());\n        elasticCloudCommonActionParam.setMachineRoom(clusterPhy.getIdc());\n\n        return Result.buildSucc(elasticCloudCommonActionParam);\n    }\n\n    private <T> Result<T> callESClusterBaseHandle(String methodName, Long clusterId, String operator,\n                                                  EcmParamBase ecmParamBase,\n                                                  BiFunction<EcmParamBase, AbstractEcmBaseHandle, Result<T>> function) {\n        return callESClusterBaseHandle(methodName, clusterId, operator, ecmParamBase, function, true);\n    }\n\n    private <T> Result<T> callESClusterBaseHandle(String methodName, Long clusterId, String operator,\n                                                  EcmParamBase ecmParamBase,\n                                                  BiFunction<EcmParamBase, AbstractEcmBaseHandle, Result<T>> function,\n                                                  boolean recordOperate) {\n        // 获取对应的handler\n        AbstractEcmBaseHandle abstractEcmBaseHandle = getByClusterType(ecmParamBase.getType());\n        if (null == abstractEcmBaseHandle) {\n            return Result.buildNotExist(UNKNOWN_TYPE);\n        }\n\n        // 执行方法进行处理\n        Result<T> result = function.apply(ecmParamBase, abstractEcmBaseHandle);\n\n        String infoLog = String.format(\n            \"class=ESClusterHandleServiceImpl||method=callESClusterBaseHandle||methodName={%s}||clusterId={%d}||result={%s}\",\n            methodName, clusterId, JSON.toJSONString(result));\n        LOGGER.info(infoLog);\n\n        // 操作记录\n        if (recordOperate) {\n            ESClusterMethodNameEnum.getOperateTypeEnum(methodName)\n                .ifPresent(operateTypeEnum -> operateRecordService\n                    .save(new OperateRecord.Builder().operationTypeEnum(operateTypeEnum)\n                        .content(String.format(\"物理集群 %s 开始进行 %s 操作\", clusterId, methodName))\n                        .project(projectService.getProjectBriefByProjectId(AuthConstant.SUPER_PROJECT_ID))\n                        .triggerWayEnum(TriggerWayEnum.SCHEDULING_TASKS).bizId(clusterId).userOperation(operator).build()));\n\n          \n        }\n\n        return result;\n    }\n\n    private AbstractEcmBaseHandle getByClusterType(Integer clusterType) {\n        return ecmBaseHandleMap.get(clusterType);\n    }\n\n    private void deleteLocalClusterInfo(ClusterPhy clusterPhy, String operator, Integer projectId) {\n        Result<Boolean> deleteClusterResult = esClusterPhyService.deleteClusterById(clusterPhy.getId(), projectId);\n        if (deleteClusterResult.failed()) {\n            LOGGER\n                .error(\"class=ElasticClusterServiceImpl||method=deleteLocalClusterInfo||clusterId={}||clusterName={}||\"\n                       + \"msg=failed to delete local db cluster info\",\n                    clusterPhy.getId(), clusterPhy.getCluster());\n        }\n\n        //逻辑删除\n        Result<Void> deleteRoleClusterResult = clusterRoleService.deleteRoleClusterByClusterId(clusterPhy.getId(),\n            projectId);\n        if (deleteRoleClusterResult.failed()) {\n            LOGGER.error(\"class=ElasticClusterServiceImpl||method=deleteLocalClusterInfo||clusterName={}||\"\n                         + \"msg=failed to delete local db role cluster info\",\n                clusterPhy.getCluster());\n        }\n\n        //逻辑删除\n        Result<Void> deleteRoleClusterHostResult = clusterRoleHostService.deleteByCluster(clusterPhy.getCluster(),\n            projectId);\n        if (deleteRoleClusterHostResult.failed()) {\n            LOGGER.error(\n                \"class=ElasticClusterServiceImpl||method=deleteLocalClusterInfo||roleClusterName=={}||roleClusterName={}||\"\n                         + \"msg=failed to delete role host cluster info\",\n                clusterPhy.getCluster(), clusterPhy.getCluster());\n        }\n    }\n\n    private Result<Void> validityCheck(Integer clusterId, String operator) {\n        if (userService.getUserBriefByUserName(operator) == null) {\n            return Result.buildFail(\"User has no permissions\");\n        }\n\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(String.format(\n                \"class=EcmHandleServiceImpl||method=validityCheck||debugMsg={clusterId={%d}, operator={%s}},\",\n                clusterId, operator));\n        }\n\n        Result<Boolean> checkClusterPhyExitTemplateResult = checkClusterPhyExitTemplate(clusterId);\n        if (checkClusterPhyExitTemplateResult.failed()) {\n            return Result.buildFrom(checkClusterPhyExitTemplateResult);\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Boolean> checkClusterPhyExitTemplate(Integer clusterId) {\n        //检查集群上是否关联模板资源\n        return Result.buildSucc();\n    }\n\n    private Result<List<ElasticCloudCommonActionParam>> deleteOdinMachine(ClusterPhy clusterPhy,\n                                                                          List<ClusterRoleInfo> allRoles,\n                                                                          String operator) {\n        List<ElasticCloudCommonActionParam> elasticCloudActionParams = Lists.newArrayList();\n        allRoles.stream().filter(role -> nonNull(role) && role.getRole() != null).forEach(role -> {\n            // 构造请求参数\n            Result<EcmParamBase> actionParamBaseResult = buildActionParamBase(clusterPhy.getId().longValue(),\n                clusterPhy.getCluster() + \"-\" + role.getRole());\n            if (actionParamBaseResult.failed()) {\n                LOGGER.error(\n                    \"class=EcmHandleServiceImpl||method=deleteESCluster||msg=failed to build the actionParamBaseResult\");\n            }\n\n            elasticCloudActionParams.add((ElasticCloudCommonActionParam) actionParamBaseResult.getData());\n            // 调用接口，删除单个odin节点上的机器\n            Result<EcmOperateAppBase> r = callESClusterBaseHandle(\"集群移除\", clusterPhy.getId().longValue(), operator,\n                actionParamBaseResult.getData(), (withoutUsed, esClusterBaseHandle) -> esClusterBaseHandle\n                    .removeESCluster(actionParamBaseResult.getData()));\n\n            if (r.failed()) {\n                LOGGER.error(\"class=EcmHandleServiceImpl||method=deleteESCluster||clusterName={}||\" + \"msg={}\",\n                    actionParamBaseResult.getData().getPhyClusterName(), r.getMessage());\n            }\n        });\n\n        return Result.buildSucc(elasticCloudActionParams);\n    }\n\n    private Result<Void> checkValidForEsCluster(List<EcmParamBase> ecmParamBaseList) {\n        if (CollectionUtils.isEmpty(ecmParamBaseList)) {\n            return Result.buildFail(\"ecm参数为空\");\n        }\n\n        ClusterPhy clusterByName = esClusterPhyService.getClusterByName(ecmParamBaseList.get(0).getPhyClusterName());\n        if (!AriusObjUtils.isNull(clusterByName)) {\n            return Result.buildDuplicate(\"集群信息已存在\");\n        }\n\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/impl/handler/AbstractEcmBaseHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl.handler;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmOperateAppBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmSubTaskLog;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmTaskStatus;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.EcmActionEnum;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport java.util.List;\n\npublic abstract class AbstractEcmBaseHandle {\n    protected final static ILog LOGGER = LogFactory.getLog(AbstractEcmBaseHandle.class);\n\n    protected ESClusterTypeEnum   esClusterTypeEnum;\n\n    public ESClusterTypeEnum getEsClusterTypeEnum() {\n        return esClusterTypeEnum;\n    }\n\n    /**\n     * 保留集群信息、集群角色信息, 不保留集群节点信息, 集群节点信息由定时任务同步\n     */\n    public abstract Result<Long> saveESCluster(List<EcmParamBase> ecmParamBaseList);\n\n    public abstract Result<EcmOperateAppBase> startESCluster(EcmParamBase actionParamBase);\n\n    public abstract Result<EcmOperateAppBase> scaleESCluster(EcmParamBase actionParamBase);\n\n    public abstract Result<EcmOperateAppBase> upgradeESCluster(EcmParamBase actionParamBase);\n\n    public abstract Result<EcmOperateAppBase> restartESCluster(EcmParamBase actionParamBase);\n\n    public abstract Result<EcmOperateAppBase> removeESCluster(EcmParamBase actionParamBase);\n\n    public abstract Result<EcmOperateAppBase> actionNotFinishedTask(EcmParamBase actionParamBase,\n                                                                    EcmActionEnum ecmActionEnum, String hostname);\n\n    public abstract Result<String> infoESCluster(EcmParamBase actionParamBase);\n\n    public abstract Result<EcmSubTaskLog> getSubTaskLog(Long taskId, String hostname, EcmParamBase actionParamBase);\n\n    public abstract Result<List<EcmTaskStatus>> getTaskStatus(EcmParamBase ecmParamBase, Integer orderType);\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/impl/handler/EcmDockerHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl.handler;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmOperateAppBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmSubTaskLog;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmTaskStatus;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport lombok.NoArgsConstructor;\nimport org.springframework.stereotype.Service;\nimport javax.annotation.PostConstruct;\nimport java.util.List;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.EcmActionEnum;\n\n@NoArgsConstructor\n@Service(\"ecmDockerHandler\")\npublic class EcmDockerHandler extends AbstractEcmBaseHandle {\n\n    @PostConstruct\n    public void init() {\n        esClusterTypeEnum = ESClusterTypeEnum.ES_DOCKER;\n    }\n\n    @Override\n    public Result<Long> saveESCluster(List<EcmParamBase> ecmParamBaseList) {\n        return Result.buildFail(\"暂不支持\");\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> startESCluster(EcmParamBase actionParamBase) {\n        return Result.buildFail(\"暂不支持\");\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> scaleESCluster(EcmParamBase actionParamBase) {\n        return Result.buildFail(\"暂不支持\");\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> upgradeESCluster(EcmParamBase actionParamBase) {\n        return Result.buildFail(\"暂不支持\");\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> restartESCluster(EcmParamBase actionParamBase) {\n        return Result.buildFail(\"暂不支持\");\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> removeESCluster(EcmParamBase actionParamBase) {\n        return Result.buildFail(\"暂不支持\");\n    }\n\n    @Override\n    public Result actionNotFinishedTask(EcmParamBase actionParamBase, EcmActionEnum ecmActionEnum, String hostname) {\n        return Result.buildFail(\"暂不支持\");\n    }\n\n    @Override\n    public Result<String> infoESCluster(EcmParamBase actionParamBase) {\n        return Result.buildFail(\"暂不支持\");\n    }\n\n    @Override\n    public Result<EcmSubTaskLog> getSubTaskLog(Long taskId, String hostname, EcmParamBase actionParamBase) {\n        return Result.buildFail(\"暂不支持\");\n    }\n\n    @Override\n    public Result<List<EcmTaskStatus>> getTaskStatus(EcmParamBase actionParamBase, Integer orderType) {\n        return Result.buildFail(\"暂不支持\");\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/ecm/impl/handler/EcmHostHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.impl.handler;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.INVALID_VALUE;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EsConfigAction;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostCreateActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostParamBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.host.HostScaleActionParam;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmOperateAppBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmSubTaskLog;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmTaskStatus;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.espackage.ESPackage;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.esconfig.EsConfigActionEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPackageService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPluginService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.ZeusClusterRemoteService;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.EcmActionEnum;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.ZeusClusterActionEnum;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.regex.Pattern;\nimport javax.annotation.PostConstruct;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service(\"ecmHostHandler\")\npublic class EcmHostHandler extends AbstractEcmBaseHandle {\n    @Autowired\n    private ClusterRoleService       clusterRoleService;\n\n    @Autowired\n    private ESPluginService          esPluginService;\n\n    @Autowired\n    private ESPackageService         esPackageService;\n\n    @Autowired\n    private ClusterRoleHostService   clusterRoleHostService;\n\n    @Autowired\n    private ClusterPhyService        esClusterPhyService;\n\n    @Autowired\n    private ZeusClusterRemoteService zeusClusterRemoteService;\n\n    @PostConstruct\n    public void init() {\n        esClusterTypeEnum = ESClusterTypeEnum.ES_HOST;\n    }\n\n    @Override\n    public Result<Long> saveESCluster(List<EcmParamBase> ecmParamBaseList) {\n        List<HostCreateActionParam> hostCreateActionParamList = new ArrayList<>();\n        for (EcmParamBase ecmParamBase : ecmParamBaseList) {\n            HostCreateActionParam hostCreateActionParam = (HostCreateActionParam) ecmParamBase;\n            // 检查参数是否合理\n            Result<Void> fieldCheckResult = hostCreateActionParam.validateFiledIllegal();\n            if (fieldCheckResult.failed()) {\n                return Result.buildFrom(fieldCheckResult);\n            }\n            hostCreateActionParamList.add(hostCreateActionParam);\n        }\n\n        //保存物理集群信息 es_cluster_phy_info\n        Result<HostCreateActionParam> hostCreateActionParamResult = persistClusterPOAndSupplyField(\n            hostCreateActionParamList.get(0));\n        if (hostCreateActionParamResult.failed()) {\n            return Result.buildFrom(hostCreateActionParamResult);\n        }\n\n        for (HostCreateActionParam hostCreateActionParam : hostCreateActionParamList) {\n            hostCreateActionParam.setPhyClusterId(hostCreateActionParamResult.getData().getPhyClusterId());\n            hostCreateActionParam.setPlugs(hostCreateActionParamResult.getData().getPlugs());\n            hostCreateActionParam.setImageName(hostCreateActionParamResult.getData().getImageName());\n        }\n\n        // 保存集群角色信息 es_cluster_role_info\n        for (HostCreateActionParam hostCreateActionParam : hostCreateActionParamList) {\n            // 角色集群 信息入库\n            ESClusterRoleDTO esClusterRoleDTO = new ESClusterRoleDTO();\n            esClusterRoleDTO.setElasticClusterId(hostCreateActionParam.getPhyClusterId());\n            if (hostCreateActionParam.getRoleName().startsWith(hostCreateActionParam.getPhyClusterName())) {\n                esClusterRoleDTO.setRoleClusterName(hostCreateActionParam.getRoleName());\n            } else {\n                esClusterRoleDTO.setRoleClusterName(\n                    hostCreateActionParam.getPhyClusterName() + \"-\" + hostCreateActionParam.getRoleName());\n            }\n            esClusterRoleDTO.setRole(hostCreateActionParam.getRoleName());\n            esClusterRoleDTO.setPodNumber(0);\n            esClusterRoleDTO.setPidCount(hostCreateActionParam.getPidCount());\n            esClusterRoleDTO.setMachineSpec(hostCreateActionParam.getMachineSpec());\n            esClusterRoleDTO.setCfgId(INVALID_VALUE.intValue());\n            esClusterRoleDTO.setEsVersion(hostCreateActionParam.getEsVersion());\n\n            clusterRoleService.save(esClusterRoleDTO);\n        }\n        return Result.buildSucc(hostCreateActionParamResult.getData().getPhyClusterId());\n    }\n\n    /**\n     * 集群基础数据入库：集群  角色 角色对应主机\n     * @param  param\n     * @return esClusterDTO\n     */\n    private Result<HostCreateActionParam> persistClusterPOAndSupplyField(HostCreateActionParam param) {\n        ClusterPhyDTO esClusterDTO = ConvertUtil.obj2Obj(param, ClusterPhyDTO.class);\n        esClusterDTO.setCluster(param.getPhyClusterName());\n        ESPackage esPackage = esPackageService.getByVersionAndType(param.getEsVersion(), param.getType());\n        esClusterDTO.setImageName(esPackage.getUrl());\n\n        esClusterDTO.setPlugIds(buildEsClusterPlugins(esClusterDTO));\n        esClusterDTO.setPackageId(esPackage.getId());\n        esClusterDTO.setHttpAddress(ClusterConstant.DEFAULT_HTTP_ADDRESS);\n        if (StringUtils.isBlank(esClusterDTO.getDataCenter())) {\n            esClusterDTO.setDataCenter(EnvUtil.getDC().getCode());\n        }\n        if (StringUtils.isBlank(esClusterDTO.getIdc())) {\n            esClusterDTO.setIdc(ClusterConstant.DEFAULT_CLUSTER_IDC);\n        }\n        esClusterDTO.setRunMode(ClusterConstant.DEFAULT_RUN_MODEL);\n\n        Result<Boolean> clusterResult = esClusterPhyService.createCluster(esClusterDTO, param.getCreator());\n        if (clusterResult.failed()) {\n            return Result.buildFrom(clusterResult);\n        }\n        param.setPhyClusterId(esClusterDTO.getId().longValue());\n        param.setImageName(esPackage.getUrl());\n        param.setPlugs(esClusterDTO.getPlugIds());\n        return Result.buildSucc(param);\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> startESCluster(EcmParamBase ecmParamBase) {\n        HostCreateActionParam hostCreateActionParam = (HostCreateActionParam) ecmParamBase;\n        return zeusClusterRemoteService.createTask(hostCreateActionParam.getHostList(),\n            buildArgs(hostCreateActionParam, ZeusClusterActionEnum.NEW.getValue(), hostCreateActionParam.getHostList(),\n                getInitialRackValue(ecmParamBase, ZeusClusterActionEnum.NEW)));\n    }\n\n    @Override\n    public Result scaleESCluster(EcmParamBase actionParamBase) {\n        HostScaleActionParam hostScaleActionParam = (HostScaleActionParam) actionParamBase;\n        return zeusClusterRemoteService.createTask(hostScaleActionParam.getHostList(), buildArgs(hostScaleActionParam,\n            hostScaleActionParam.getAction(), hostScaleActionParam.getHostList(),\n            getInitialRackValue(actionParamBase, ZeusClusterActionEnum.valueFrom(hostScaleActionParam.getAction()))));\n    }\n\n    @Override\n    public Result upgradeESCluster(EcmParamBase actionParamBase) {\n        HostParamBase hostUpgradeActionParam = (HostParamBase) actionParamBase;\n        return zeusClusterRemoteService.createTask(hostUpgradeActionParam.getHostList(),\n            buildArgs(hostUpgradeActionParam.getMasterHostList(), hostUpgradeActionParam,\n                ZeusClusterActionEnum.UPDATE.getValue(), null));\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> restartESCluster(EcmParamBase actionParamBase) {\n        HostParamBase hostParamBase = (HostParamBase) actionParamBase;\n        return zeusClusterRemoteService.createTask(hostParamBase.getHostList(),\n            buildArgs(hostParamBase.getMasterHostList(), hostParamBase, ZeusClusterActionEnum.RESTART.getValue(),\n                getConfigActionType(hostParamBase.getEsConfigAction())));\n    }\n\n    @Override\n    public Result<EcmOperateAppBase> removeESCluster(EcmParamBase actionParamBase) {\n        HostScaleActionParam hostScaleActionParam = (HostScaleActionParam) actionParamBase;\n        return zeusClusterRemoteService.createTask(hostScaleActionParam.getHostList(),\n            buildArgs(hostScaleActionParam.getMasterHostList(), hostScaleActionParam,\n                ZeusClusterActionEnum.SHRINK.getValue(), null));\n    }\n\n    @Override\n    public Result actionNotFinishedTask(EcmParamBase actionParamBase, EcmActionEnum ecmActionEnum, String hostname) {\n        if (AriusObjUtils.isBlank(hostname)) {\n            return zeusClusterRemoteService.actionTask(actionParamBase.getTaskId(), ecmActionEnum.getAction());\n        }\n        return zeusClusterRemoteService.actionHostTask(actionParamBase.getTaskId(), hostname,\n            ecmActionEnum.getAction());\n    }\n\n    @Override\n    public Result<String> infoESCluster(EcmParamBase actionParamBase) {\n        return Result.buildSuccWithMsg(\"\");\n    }\n\n    @Override\n    public Result<EcmSubTaskLog> getSubTaskLog(Long taskId, String hostname, EcmParamBase actionParamBase) {\n        return zeusClusterRemoteService.getTaskLog(taskId.intValue(), hostname);\n    }\n\n    @Override\n    public Result<List<EcmTaskStatus>> getTaskStatus(EcmParamBase ecmParamBase, Integer orderType) {\n        return zeusClusterRemoteService.getZeusTaskStatus(ecmParamBase.getTaskId());\n    }\n\n    /*********************** private method ***********************************/\n\n    private String buildArgs(List<String> masterHostList, HostParamBase hostActionParam, String action,\n                             Integer configActionType) {\n        return String.format(\n            \"--cluster_name=%s,,--port=%s,,--masters=%s,,--package_url=%s,,--es_version=%s,,--role=%s,,--pid_count=%d,,--action=%s,,--config_action=%s\",\n            hostActionParam.getPhyClusterName(), hostActionParam.getPort(), ListUtils.strList2String(masterHostList),\n            hostActionParam.getImageName(), hostActionParam.getEsVersion(), hostActionParam.getRoleName(),\n            hostActionParam.getPidCount(), action, configActionType);\n    }\n\n    private String buildArgs(HostParamBase hostParamBase, String action, List<String> hostLists, String initialRack) {\n        return String.format(\n            \"--cluster_name=%s,,--port=%s,,--masters=%s,,--package_url=%s,,--es_version=%s,,--role=%s,,--pid_count=%d,,--action=%s,,--hosts=%s,,--initial_rack=%s\",\n            hostParamBase.getPhyClusterName(), hostParamBase.getPort(),\n            ListUtils.strList2String(hostParamBase.getMasterHostList()), hostParamBase.getImageName(),\n            hostParamBase.getEsVersion(), hostParamBase.getRoleName(), hostParamBase.getPidCount(), action,\n            ListUtils.strList2String(hostLists), initialRack);\n    }\n\n    private String buildEsClusterPlugins(ClusterPhyDTO esClusterDTO) {\n        String defaultPlugins = StringUtils.defaultString(esPluginService.getAllSysDefaultPluginIds(), \"\");\n\n        if (StringUtils.isNotEmpty(esClusterDTO.getPlugIds())) {\n            defaultPlugins = defaultPlugins + \",\" + esClusterDTO.getPlugIds();\n        }\n        return defaultPlugins;\n    }\n\n    private Integer getConfigActionType(EsConfigAction esConfigAction) {\n        if (null == esConfigAction || esConfigAction.getActionType().equals(EsConfigActionEnum.UNKNOWN.getCode())) {\n            return null;\n        }\n        return esConfigAction.getActionType();\n    }\n\n    private String getInitialRackValue(EcmParamBase actionParamBase, ZeusClusterActionEnum zeusClusterActionEnum) {\n        HostParamBase hostParamBase = (HostParamBase) actionParamBase;\n        if (!actionParamBase.getRoleName().equals(ESClusterNodeRoleEnum.DATA_NODE.getDesc())\n            || CollectionUtils.isEmpty(hostParamBase.getHostList())) {\n            return null;\n        }\n\n        String initialRack = null;\n        if (zeusClusterActionEnum.equals(ZeusClusterActionEnum.EXPAND)\n            || zeusClusterActionEnum.equals(ZeusClusterActionEnum.NEW)) {\n            // 根据物理集群id和数据节点的角色名称获取所有的当前集群绑定的主机列表\n            List<ClusterRoleHost> clusterRoleHosts = clusterRoleHostService\n                .getByRoleAndClusterId(hostParamBase.getPhyClusterId(), ESClusterNodeRoleEnum.DATA_NODE.getDesc());\n\n            float initialRackValue = 0;\n            if (CollectionUtils.isEmpty(clusterRoleHosts)) {\n                // 当新建或者扩容前data角色列表为空时，设置基准值\n                initialRackValue += 0.5;\n            } else {\n                // 根据rack的大小进行排序并且获取新的data节点类型的rack起始值\n                for (ClusterRoleHost clusterRoleHost : clusterRoleHosts) {\n                    if (!Pattern.matches(\"r.*\", clusterRoleHost.getRack())) {\n                        // 如果rack 不是r* 形式，则跳过不进行计算, 这里为了与前人逻辑保持一致，hold住特殊case 如cold rack\n                        continue;\n                    }\n                    int roleHostRackValue = Integer.parseInt(clusterRoleHost.getRack().replaceFirst(\"r\", \"\"));\n                    if (roleHostRackValue > initialRackValue) {\n                        initialRackValue = roleHostRackValue;\n                    } else if (roleHostRackValue == initialRackValue) {\n                        initialRackValue += 0.5;\n                    }\n                }\n            }\n\n            initialRack = String.valueOf(initialRackValue);\n        }\n        return initialRack;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/logic/ClusterLogicService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.logic;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.LogicResourceConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Plugin;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.PluginDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.RoleClusterNodeSepc;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * 逻辑集群service\n * @author d06679\n * @date  2019/3/25\n */\npublic interface ClusterLogicService {\n\n    /**\n     * 条件查询逻辑集群\n     * @param param 条件\n     * @return 逻辑集群列表\n     */\n    List<ClusterLogic> listClusterLogics(ESLogicClusterDTO param);\n\n    /**\n     * 获取所有逻辑集群\n     * @return 逻辑集群列表\n     */\n    List<ClusterLogic> listAllClusterLogics();\n\n    /**\n     * 根据逻辑集群ID删除逻辑集群\n     *\n     * @param logicClusterId 逻辑集群ID\n     * @param operator       操作人\n     * @param projectId     项目id\n     * @return result\n     * @throws AdminOperateException admin操作异常\n     */\n    Result<Void> deleteClusterLogicById(Long logicClusterId, String operator,\n                                        Integer projectId) throws AdminOperateException;\n\n    /**\n     * > 判断索引模板的项目id与待删除项目的项目id是否可以匹配\n     *\n     * @param logicClusterId 逻辑集群的id\n     * @param deleteProjectId 要删除的项目\n     * @return boolean\n     */\n    boolean hasLogicClusterWithTemplates(Long logicClusterId, Integer deleteProjectId);\n\n    /**\n     * 新建逻辑集群\n     * @param param 参数\n     * @return result\n     */\n    Result<Long> createClusterLogic(ESLogicClusterDTO param);\n\n    /**\n     * 验证逻辑集群创建、更新参数是否合法\n     *\n     * @param param     参数\n     * @param operation 操作\n     * @param projectId 项目id\n     * @return result\n     */\n    Result<Void> validateClusterLogicParams(ESLogicClusterDTO param, OperationEnum operation, Integer projectId);\n\n    /**\n     * 编辑逻辑集群信息\n     *\n     * @param param     参数\n     * @param operator  操作人\n     * @param projectId 项目id\n     * @return result\n     */\n    Result<Void> editClusterLogic(ESLogicClusterDTO param, String operator, Integer projectId);\n\n    Result<Void> editClusterLogicNotCheck(ESLogicClusterDTO param);\n\n    /**\n     * 查询指定逻辑集群\n     *\n     * @param logicClusterId 逻辑集群id\n     * @param projectId\n     * @return 逻辑集群 不存在返回null\n     */\n    ClusterLogic getClusterLogicByIdAndProjectId(Long logicClusterId, Integer projectId);\n    \n    /**\n     * 获取集群逻辑通过id那不包含项目id\n     *\n     * @param logicClusterId 逻辑集群id\n     * @return {@code ClusterLogic}\n     */\n    ClusterLogic getClusterLogicByIdThatNotContainsProjectId(Long logicClusterId);\n    \n    boolean  existClusterLogicById(Long logicClusterId);\n    \n    \n    /**\n     *通过逻辑集群id获取逻辑集群而且将projectIdStr转换为ProjectIdList\n     *\n     * @param logicClusterId 逻辑集群id\n     * @return {@code List<ClusterLogic>}\n     */\n    List<ClusterLogic> listClusterLogicByIdThatProjectIdStrConvertProjectIdList(Long logicClusterId);\n    \n    /**\n     * 获取逻辑集群通过名字和项目id\n     *\n     * @param logicClusterName 逻辑集群名称\n     * @param projectId        项目id\n     * @return {@code ClusterLogic}\n     */\n    ClusterLogic getClusterLogicByNameAndProjectId(String logicClusterName, Integer projectId);\n    \n    /**\n     * 获取集群逻辑通过名字然后不包含项目id\n     *\n     * @param logicClusterName 逻辑集群名称\n     * @return {@code ClusterLogic}\n     */\n    ClusterLogic getClusterLogicByNameThatNotContainsProjectId(String logicClusterName);\n    \n    /**\n     * 通过逻辑集群名称获取逻辑集群而且将projectIdStr转换为ProjectIdList\n     *\n     * @param logicClusterName 逻辑集群名称\n     * @return {@code List<ClusterLogic>}\n     */\n    List<ClusterLogic> listClusterLogicByNameThatProjectIdStrConvertProjectIdList(String logicClusterName);\n\n    /**\n     * 获取逻辑集群配置\n     * @param logicClusterId 逻辑集群id\n     * @return 逻辑集群配置 不存在返回null\n     */\n    LogicResourceConfig getClusterLogicConfigById(Long logicClusterId);\n\n    /**\n     * 查询指定app所创建（作为owner）的逻辑集群\n     * @param projectId project ID\n     * @return 逻辑集群列表\n     */\n    List<ClusterLogic> getOwnedClusterLogicListByProjectId(Integer projectId);\n\n    /**\n     * 查询指定app有权限的逻辑集群（包括ALL、OWN、ACCESS）\n     * @param projectId project ID\n     * @return 逻辑集群列表\n     */\n    List<ClusterLogic> getHasAuthClusterLogicsByProjectId(Integer projectId);\n\n    /**\n     * 根据项目和集群名称获取逻辑集群\n     *\n     * @param projectId   项目id\n     * @param clusterName 集群名称\n     * @return {@link List}<{@link ClusterLogic}>\n     */\n    List<ClusterLogic> listClusterLogicByProjectIdAndName(Integer projectId, String clusterName);\n\n     /**\n     * 获取对应项目下有权限的逻辑集群\n     *\n     * @param projectId   项目id\n     * @return List<Long> 有权限的逻辑集群id列表\n     */\n    List<Long> getHasAuthClusterLogicIdsByProjectId(Integer projectId);\n\n    /**\n     * 判断逻辑集群是否存在\n     * @param resourceId 逻辑集群id\n     * @return result\n     */\n    Boolean isClusterLogicExists(Long resourceId);\n\n    /**\n     * 根据配置字符创生成配置，填充默认值\n     * @param configJson JSON\n     * @return LogicResourceConfig\n     */\n    LogicResourceConfig genClusterLogicConfig(String configJson);\n\n    /**\n     * 获取逻辑集群的所有role\n     * @param logicClusterId 逻辑集群ID\n     * @return ClusterRoleInfo\n     */\n    List<ClusterRoleInfo> getClusterLogicRole(Long logicClusterId);\n\n    /**\n     * 获取逻辑集群datanode的规格信息\n     * @param logicClusterId 逻辑集群ID\n     * @return 规格信息\n     */\n    Set<RoleClusterNodeSepc> getLogicDataNodeSepc(Long logicClusterId);\n\n    /**\n     * 根据逻辑集群ID获取插件信息\n     * @param  logicClusterId 逻辑集群ID\n     * @return List<Plugin> 插件信息\n     */\n    List<Plugin> getClusterLogicPlugins(Long logicClusterId);\n\n    /**\n     * 根据逻辑集群Id添加插件信息\n     * @param  logicClusterId        逻辑集群ID\n     * @param  pluginDTO           插件信息\n     * @param  operator              操作人\n     * @return ESPlugin             成功\n     */\n    Result<Long> addPlugin(Long logicClusterId, PluginDTO pluginDTO, String operator) throws NotFindSubclassException;\n\n    /**\n     * 转移逻辑集群\n     *\n     * @param clusterLogicId  逻辑集群Id\n     * @param targetProjectId 项目Id\n     * @param submitor        提交人\n     * @return 成功/失败\n     */\n    Result<Void> transferClusterLogic(Long clusterLogicId, Integer targetProjectId,\n                                      String submitor);\n\n    /**\n     * 模糊分页查询物理集群列表信息，仅获取部分属性\n     */\n    List<ClusterLogic> pagingGetClusterLogicByCondition(ClusterLogicConditionDTO condition);\n\n    /**\n     * 模糊查询统计总命中数\n     * @param param 模糊查询条件\n     * @return 命中数\n     */\n    Long fuzzyClusterLogicHitByCondition(ClusterLogicConditionDTO param);\n\n    /**\n     * 根据逻辑集群id列表获取逻辑集群列表信息\n     * @param clusterLogicIdList  逻辑集群id列表\n     * @return                    List<ClusterLogic>\n     */\n    List<ClusterLogic> getClusterLogicListByIds(List<Long> clusterLogicIdList);\n    \n    /**\n     *\n     * 通过level获取逻辑集群并且将projectIdStr convert projectId list\n     * @param level 水平\n     * @return {@code List<ClusterLogic>}\n     */\n    List<ClusterLogic> listLogicClustersByLevelThatProjectIdStrConvertProjectIdList(Integer level);\n    \n    /**\n     * > 加入集群\n     *\n     * @param param 加入集群逻辑的参数对象。\n     * @return 加入集群逻辑的结果。\n     */\n    Result<Long> joinClusterLogic(ESLogicClusterDTO param);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/logic/impl/ClusterLogicServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.DEFAULT_CLUSTER_HEALTH;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.ADD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.ADD_BIND_MULTIPLE_PROJECT;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.EDIT;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.DATA_NODE;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.LogicResourceConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Plugin;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.PluginDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.RoleClusterNodeSepc;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterLogicPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESMachineNormsPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin.PluginPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESMachineNormsService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPluginService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectClusterLogicAuthService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.resource.LogicClusterDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author d06679\n * @date 2019/3/25\n */\n@Service\npublic class ClusterLogicServiceImpl implements ClusterLogicService {\n\n    private static final ILog              LOGGER = LogFactory.getLog(ClusterLogicServiceImpl.class);\n\n    @Autowired\n    private LogicClusterDAO                logicClusterDAO;\n    @Autowired\n    private IndexTemplateDAO indexTemplateDAO;\n\n    @Autowired\n    private ProjectClusterLogicAuthService logicClusterAuthService;\n\n    @Autowired\n    private ProjectService                 projectService;\n\n\n    @Autowired\n    private ESPluginService                esPluginService;\n\n    @Autowired\n    private ClusterPhyService              clusterPhyService;\n\n    @Autowired\n    private ESMachineNormsService          esMachineNormsService;\n\n    @Autowired\n    private ClusterRegionService           clusterRegionService;\n\n    @Autowired\n    private ClusterRoleHostService         clusterRoleHostService;\n\n    /**\n     * 条件查询逻辑集群\n     *\n     * @param param 条件\n     * @return List<ClusterLogic> 逻辑集群列表\n     */\n    @Override\n    public List<ClusterLogic> listClusterLogics(ESLogicClusterDTO param) {\n        return logicClusterDAO.listByCondition(ConvertUtil.obj2Obj(param, ClusterLogicPO.class)).stream()\n                .map(this::clusterLogicPoProjectIdStrConvertClusterLogic).flatMap(Collection::stream)\n                .filter(clusterLogic -> filterClusterLogicByProjectId(clusterLogic, param.getProjectId()))\n                .collect(Collectors.toList());\n        \n    }\n\n    /**\n     * 获取所有逻辑集群\n     *\n     * @return List<ClusterLogic> 逻辑集群列表\n     */\n    @Override\n    public List<ClusterLogic> listAllClusterLogics() {\n        return logicClusterDAO.listAll()\n                .stream()\n                .map(this::clusterLogicPoProjectIdStrConvertClusterLogic)\n                .flatMap(Collection::stream)\n                .collect(Collectors.toList());\n    }\n\n    /**\n     * 删除逻辑集群\n     *\n     * @param logicClusterId 逻辑集群ID\n     * @param operator       操作人\n     * @param deleteProjectId     项目id\n     * @return result\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> deleteClusterLogicById(Long logicClusterId, String operator,\n                                               Integer deleteProjectId) throws AdminOperateException {\n        ClusterLogicPO logicCluster = logicClusterDAO.getById(logicClusterId);\n        if (logicCluster == null) {\n            return Result.buildNotExist(\"逻辑集群不存在\");\n        }\n        if (hasLogicClusterWithTemplates(logicClusterId, deleteProjectId)) {\n            return Result.build(ResultType.IN_USE_ERROR.getCode(), \"逻辑集群使用中\");\n        }\n        boolean succeed = false;\n        //如果项目id中含有,默认为需要更新的状态\n        if (StringUtils.contains(logicCluster.getProjectId(), \",\")) {\n            final ClusterLogicPO clusterLogicPO = new ClusterLogicPO();\n            clusterLogicPO.setId(logicClusterId);\n            final List<Integer> projectIds = str2ListProjectIds(logicCluster);\n            projectIds.remove(deleteProjectId);\n            clusterLogicPO.setProjectId(ConvertUtil.list2String(projectIds, \",\"));\n            succeed = (logicClusterDAO.update(clusterLogicPO) == 1);\n        } else {\n            succeed = (logicClusterDAO.delete(logicClusterId) == 1);\n        }\n        if (!succeed) {\n            throw new AdminOperateException(\"删除逻辑集群失败\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * > 索引模板的项目id与待删除项目的项目id是否可以匹配\n     *\n     * @param logicClusterId 逻辑集群的id\n     * @param deleteProjectId 要删除的项目\n     * @return boolean\n     */\n    @Override\n    public boolean hasLogicClusterWithTemplates(Long logicClusterId, Integer deleteProjectId) {\n       \n        return indexTemplateDAO.listByResourceIds(Collections.singletonList(logicClusterId))\n                .stream().anyMatch(indexTemplatePO -> indexTemplatePO.getProjectId().equals(deleteProjectId));\n    }\n    \n    /**\n     * > 加入集群\n     *\n     * @param param 加入集群逻辑的参数对象。\n     * @return 加入集群逻辑的结果。\n     */\n    @Override\n    public Result<Long> joinClusterLogic(ESLogicClusterDTO param) {\n        Result<Void> checkResult = validateClusterLogicParams(param, ADD_BIND_MULTIPLE_PROJECT, param.getProjectId());\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=ClusterLogicServiceImpl||method=joinClusterLogic||msg={}\", checkResult.getMessage());\n            return Result.buildFrom(checkResult);\n        }\n        ClusterLogicPO clusterLogicPO = logicClusterDAO.getById(param.getId());\n        final List<Integer> projectIds = str2ListProjectIds(clusterLogicPO);\n        projectIds.add(param.getProjectId());\n        final String projectIdStr = ConvertUtil.list2String(projectIds.stream().distinct().collect(Collectors.toList()),\n                \",\");\n        clusterLogicPO.setProjectId(projectIdStr);\n        return Result.build(logicClusterDAO.update(clusterLogicPO) == 1, clusterLogicPO.getId());\n    }\n    \n    /**\n     * 新建逻辑集群\n     *\n     * @param param    参数\n     * @return result\n     */\n    @Override\n    public Result<Long> createClusterLogic(ESLogicClusterDTO param) {\n        Result<Void>  checkResult = validateClusterLogicParams(param, ADD, param.getProjectId());\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=ClusterLogicServiceImpl||method=createClusterLogic||msg={}\", checkResult.getMessage());\n            return Result.buildFrom(checkResult);\n        }\n    \n        initLogicCluster(param);\n    \n        ClusterLogicPO logicPO = ConvertUtil.obj2Obj(param, ClusterLogicPO.class,\n                po -> po.setProjectId(param.getProjectId().toString()));\n        boolean succeed = logicClusterDAO.insert(logicPO) == 1;\n        return Result.build(succeed, logicPO.getId());\n    \n    }\n\n    /**\n     * 验证逻辑集群是否合法\n     *\n     * @param param     参数\n     * @param operation 操作\n     * @param projectId 项目id\n     * @return result\n     */\n    @Override\n    public Result<Void> validateClusterLogicParams(ESLogicClusterDTO param, OperationEnum operation,\n                                                   Integer projectId) {\n        return checkLogicClusterParams(param, operation, projectId);\n    }\n\n     /**\n     * 编辑逻辑集群信息\n     *\n     * @param param     参数\n     * @param operator  操作人\n     * @param projectId 项目id\n     * @return result\n     */\n    @Override\n    public Result<Void> editClusterLogic(ESLogicClusterDTO param, String operator, Integer projectId) {\n        Result<Void> checkResult = validateClusterLogicParams(param, EDIT, projectId);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=ClusterLogicServiceImpl||method=editResource||msg={}\", checkResult.getMessage());\n            return checkResult;\n        }\n\n        return editClusterLogicNotCheck(param);\n    }\n\n    @Override\n    public Result<Void> editClusterLogicNotCheck(ESLogicClusterDTO param) {\n        ClusterLogicPO paramPO = ConvertUtil.obj2Obj(param, ClusterLogicPO.class);\n        if (Objects.nonNull(paramPO.getProjectId())) {\n            final ClusterLogicPO clusterLogicPO = logicClusterDAO.getById(param.getId());\n            final List<Integer> listProjectIds = str2ListProjectIds(clusterLogicPO);\n            listProjectIds.add(param.getProjectId());\n            final String projectIdStr = ConvertUtil.list2String(\n                    listProjectIds.stream().distinct().collect(Collectors.toList()), \",\");\n            paramPO.setProjectId(projectIdStr);\n        }\n        \n    \n        boolean succ = (1 == logicClusterDAO.update(paramPO));\n\n        return Result.build(succ);\n    }\n    \n    /**\n     * 获取集群逻辑通过id那不包含项目id\n     *\n     * @param logicClusterId 逻辑集群id\n     * @return {@code ClusterLogic}\n     */\n    @Override\n    public ClusterLogic getClusterLogicByIdThatNotContainsProjectId(Long logicClusterId) {\n        return ConvertUtil.obj2Obj(logicClusterDAO.getById(logicClusterId),ClusterLogic.class);\n    }\n    \n    /**\n     * 根据逻辑集群Id判断逻辑集群是否存在\n     * @param logicClusterId 逻辑集群Id\n     * @return boolean 存在与否\n     */\n    @Override\n    public boolean existClusterLogicById(Long logicClusterId) {\n        return Objects.nonNull(logicClusterDAO.getById(logicClusterId));\n    }\n    \n     /**\n     * 查询指定逻辑集群\n     *\n     * @param logicClusterId 逻辑集群id\n     * @param projectId 项目id\n     * @return ClusterLogic 逻辑集群 不存在返回null\n     */\n    @Override\n    public ClusterLogic getClusterLogicByIdAndProjectId(Long logicClusterId, Integer projectId) {\n        return clusterLogicPoProjectIdStrConvertClusterLogic(logicClusterDAO.getById(logicClusterId)).stream()\n                .filter(clusterLogic -> filterClusterLogicByProjectId(clusterLogic, projectId)).findFirst()\n                .orElse(null);\n       \n    }\n    \n    /**\n     *通过逻辑集群id获取逻辑集群而且将projectIdStr转换为ProjectIdList\n     *\n     * @param logicClusterId 逻辑集群id\n     * @return {@code List<ClusterLogic>}\n     */\n    @Override\n    public List<ClusterLogic> listClusterLogicByIdThatProjectIdStrConvertProjectIdList(Long logicClusterId) {\n        return clusterLogicPoProjectIdStrConvertClusterLogic(logicClusterDAO.getById(logicClusterId));\n    }\n    \n     /**\n     * 获取逻辑集群通过名字和项目id\n     *\n     * @param logicClusterName 逻辑集群名称\n     * @param projectId        项目id\n     * @return {@code ClusterLogic}\n     */\n    @Override\n    public ClusterLogic getClusterLogicByNameAndProjectId(String logicClusterName, Integer projectId) {\n        return clusterLogicPoProjectIdStrConvertClusterLogic(logicClusterDAO.getByName(logicClusterName)).stream()\n                .filter(clusterLogic -> filterClusterLogicByProjectId(clusterLogic, projectId)).findFirst()\n                .orElse(null);\n    }\n    \n    /**\n     * 获取集群逻辑通过名字但不包含项目id\n     *\n     * @param logicClusterName 逻辑集群名称\n     * @return {@code ClusterLogic}\n     */\n    @Override\n    public ClusterLogic getClusterLogicByNameThatNotContainsProjectId(String logicClusterName) {\n        return ConvertUtil.obj2Obj(logicClusterDAO.getByName(logicClusterName), ClusterLogic.class);\n    }\n    \n    /**\n     * 通过逻辑集群名称获取逻辑集群而且将projectIdStr转换为ProjectIdList\n     *\n     * @param logicClusterName 逻辑集群名称\n     * @return {@code List<ClusterLogic>}\n     */\n    @Override\n    public List<ClusterLogic> listClusterLogicByNameThatProjectIdStrConvertProjectIdList(String logicClusterName) {\n         return clusterLogicPoProjectIdStrConvertClusterLogic(logicClusterDAO.getByName(logicClusterName));\n    }\n    \n    /**\n     * 查询指定逻辑集群的配置\n     *\n     * @param logicClusterId 逻辑集群id\n     * @return 逻辑集群 不存在返回null\n     */\n    @Override\n    public LogicResourceConfig getClusterLogicConfigById(Long logicClusterId) {\n        ClusterLogic clusterLogic =ConvertUtil.obj2Obj(logicClusterDAO.getById(logicClusterId), ClusterLogic.class);\n        if (clusterLogic == null) {\n            return null;\n        }\n        return genClusterLogicConfig(clusterLogic.getConfigJson());\n    }\n\n    /**\n     * 查询指定project所创建的逻辑集群\n     *\n     * @param projectId project\n     * @return list\n     */\n    @Override\n    public List<ClusterLogic> getOwnedClusterLogicListByProjectId(Integer projectId) {\n        return logicClusterDAO.listByProjectId(projectId).stream()\n                .map(this::clusterLogicPoProjectIdStrConvertClusterLogic).flatMap(Collection::stream)\n                .filter(clusterLogic -> filterClusterLogicByProjectId(clusterLogic,projectId))\n                .collect(Collectors.toList());\n    }\n\n     /**\n     * 通过项目id获取对应项目下有权限的逻辑集群id列表\n     *\n     * @param projectId 项目id\n     * @return List<Long> 逻辑集群id列表\n     */\n    @Override\n    public List<Long> getHasAuthClusterLogicIdsByProjectId(Integer projectId) {\n        if (projectId == null) {\n            LOGGER.error(\n                \"class=ClusterLogicServiceImpl||method=getHasAuthClusterLogicsByProjectId||errMsg=获取有权限逻辑集群时projectId为null\");\n            return new ArrayList<>();\n        }\n\n        // 获取有权限的逻辑集群id\n        return logicClusterAuthService.getAllLogicClusterAuths(projectId).stream()\n            .map(ProjectClusterLogicAuth::getLogicClusterId).distinct().collect(Collectors.toList());\n    }\n\n    /**\n     * 查询指定app有权限的逻辑集群（包括申请权限）\n     *\n     * @param projectId 项目ID\n     * @return List<ClusterLogic> 逻辑集群列表\n     */\n    @Override\n    public List<ClusterLogic> getHasAuthClusterLogicsByProjectId(Integer projectId) {\n        if (projectId == null) {\n            LOGGER.error(\n                \"class=ClusterLogicServiceImpl||method=getHasAuthClusterLogicsByProjectId||errMsg=获取有权限逻辑集群时projectId为null\");\n            return new ArrayList<>();\n        }\n\n        // 获取有权限的逻辑集群id\n        Set<Long> hasAuthLogicClusterIds = logicClusterAuthService.getAllLogicClusterAuths(projectId).stream()\n            .map(ProjectClusterLogicAuth::getLogicClusterId).collect(Collectors.toSet());\n\n        // 批量获取有权限的集群\n        List<ClusterLogicPO> hasAuthLogicClusters = !hasAuthLogicClusterIds.isEmpty()\n            ? logicClusterDAO.listByIds(hasAuthLogicClusterIds)\n            : new ArrayList<>();\n\n        // 获取作为owner的集群, 这里权限管控逻辑参看 getClusterLogicByProjectIdAndAuthType\n        List<ClusterLogicPO> ownedLogicClusters;\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            ownedLogicClusters = logicClusterDAO.listAll();\n        } else {\n            ownedLogicClusters = logicClusterDAO.listByProjectId(projectId);\n        }\n\n        // 综合\n        for (ClusterLogicPO ownedLogicCluster : ownedLogicClusters) {\n            if (!hasAuthLogicClusterIds.contains(ownedLogicCluster.getId())) {\n                hasAuthLogicClusters.add(ownedLogicCluster);\n            }\n        }\n        return hasAuthLogicClusters.stream().map(this::clusterLogicPoProjectIdStrConvertClusterLogic)\n                .flatMap(Collection::stream)\n                .filter(clusterLogic -> filterClusterLogicByProjectId(clusterLogic,projectId))\n                \n                .collect(Collectors.toList());\n    }\n\n     /**\n     * 判断逻辑集群是否存在\n     * @param resourceId 逻辑集群id\n     * @return result\n     */\n    @Override\n    public Boolean isClusterLogicExists(Long resourceId) {\n        return null != logicClusterDAO.getById(resourceId);\n    }\n\n    /**\n     * 根据配置字符创获取配置，填充默认值\n     *\n     * @param configJson json\n     * @return config\n     */\n    @Override\n    public LogicResourceConfig genClusterLogicConfig(String configJson) {\n        if (StringUtils.isBlank(configJson)) {\n            return new LogicResourceConfig();\n        }\n        return JSON.parseObject(configJson, LogicResourceConfig.class);\n    }\n\n     /**\n     * 获取逻辑集群datanode的规格信息\n     * @param logicClusterId 逻辑集群ID\n     * @return 规格信息\n     */\n    @Override\n    public Set<RoleClusterNodeSepc> getLogicDataNodeSepc(Long logicClusterId) {\n        List<ClusterRoleInfo> clusterRoleInfos = getClusterLogicRole(logicClusterId);\n\n        Set<RoleClusterNodeSepc> esRoleClusterDataNodeSepcs = new HashSet<>();\n\n        if (CollectionUtils.isNotEmpty(clusterRoleInfos)) {\n            for (ClusterRoleInfo clusterRoleInfo : clusterRoleInfos) {\n                if (DATA_NODE.getDesc().equals(clusterRoleInfo.getRole())) {\n                    RoleClusterNodeSepc roleClusterNodeSepc = new RoleClusterNodeSepc();\n                    roleClusterNodeSepc.setRole(DATA_NODE.getDesc());\n                    roleClusterNodeSepc.setSpec(clusterRoleInfo.getMachineSpec());\n\n                    esRoleClusterDataNodeSepcs.add(roleClusterNodeSepc);\n                }\n            }\n        }\n\n        if (CollectionUtils.isNotEmpty(esRoleClusterDataNodeSepcs)) {\n            return esRoleClusterDataNodeSepcs;\n        }\n\n        List<ESMachineNormsPO> esMachineNormsPOS = esMachineNormsService.listMachineNorms();\n        for (ESMachineNormsPO esMachineNormsPO : esMachineNormsPOS) {\n            esRoleClusterDataNodeSepcs.add(ConvertUtil.obj2Obj(esMachineNormsPO, RoleClusterNodeSepc.class));\n        }\n\n        return esRoleClusterDataNodeSepcs;\n    }\n\n    /**\n     * 获取逻辑集群的所有role\n     * @param logicClusterId 逻辑集群ID\n     * @return ClusterRoleInfo 逻辑集群role信息\n     */\n    @Override\n    public List<ClusterRoleInfo> getClusterLogicRole(Long logicClusterId) {\n        List<ClusterRoleInfo> clusterRoleInfos = new ArrayList<>();\n\n        try {\n            ClusterLogicPO clusterLogicPO = logicClusterDAO.getById(logicClusterId);\n\n            List<String> phyClusterNames = clusterRegionService.listPhysicClusterNames(logicClusterId);\n            if (CollectionUtils.isEmpty(phyClusterNames)) {\n                return new ArrayList<>();\n            }\n\n            //拿第一个物理集群的client、master信息，因为只有Arius维护的大公共共享集群才会有一个逻辑集群映射成多个物理集群\n            ClusterPhy clusterPhy = clusterPhyService.getClusterByName(phyClusterNames.get(0));\n            if (null == clusterPhy) {\n                return new ArrayList<>();\n            }\n\n            List<ClusterRoleInfo> esRolePhyClusters = clusterPhy.getClusterRoleInfos();\n            List<ClusterRoleHost> esRolePhyClusterHosts = clusterPhy.getClusterRoleHosts();\n\n            for (ClusterRoleInfo clusterRoleInfo : esRolePhyClusters) {\n\n                List<ClusterRoleHost> clusterRoleHosts = new ArrayList<>();\n\n                //如果是datanode节点，那么使用逻辑集群申请的节点个数和阶段规格配置\n                if (DATA_NODE.getDesc().equals(clusterRoleInfo.getRoleClusterName())) {\n                    setLogicClusterInfo(logicClusterId, clusterLogicPO, clusterRoleInfo, clusterRoleHosts);\n                } else {\n                    setPhyClusterInfo(esRolePhyClusterHosts, clusterRoleInfo, clusterRoleHosts);\n                }\n\n                clusterRoleInfo.setClusterRoleHosts(clusterRoleHosts);\n                clusterRoleInfo.setPodNumber(clusterRoleHosts.size());\n                clusterRoleInfos.add(clusterRoleInfo);\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ClusterLogicServiceImpl||method=acquireLogicClusterRole||logicClusterId={}\",\n                logicClusterId, e);\n        }\n\n        return clusterRoleInfos;\n    }\n\n     /**\n     * 根据逻辑集群ID获取插件信息\n     * @param  logicClusterId 逻辑集群ID\n     * @return List<Plugin> 插件列表\n     */\n    @Override\n    public List<Plugin> getClusterLogicPlugins(Long logicClusterId) {\n        List<String> clusterNameList = clusterRegionService.listPhysicClusterNames(logicClusterId);\n        if (AriusObjUtils.isEmptyList(clusterNameList)) {\n            return new ArrayList<>();\n        }\n\n        //逻辑集群对应的物理集群插件一致 取其中一个物理集群\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterNameList.get(0));\n        List<PluginPO> pluginPOList = esPluginService.listClusterAndDefaultESPlugin(clusterPhy.getId().toString());\n\n        if (AriusObjUtils.isEmptyList(pluginPOList)) {\n            return new ArrayList<>();\n        }\n\n        List<ClusterPhy> clusterPhyList = clusterPhyService.listAllClusters();\n        Map<String, ClusterPhy> name2ClusterPhyMap = ConvertUtil.list2Map(clusterPhyList, ClusterPhy::getCluster);\n\n        Map<Long, Plugin> pluginMap = new HashMap<>(0);\n        for (PluginPO pluginPO : pluginPOList) {\n            Plugin logicalPlugin = ConvertUtil.obj2Obj(pluginPO, Plugin.class);\n            logicalPlugin.setInstalled(Boolean.FALSE);\n            pluginMap.put(pluginPO.getId(), logicalPlugin);\n        }\n\n        for (String clusterName : clusterNameList) {\n            ClusterPhy cluster = name2ClusterPhyMap.get(clusterName);\n            if (AriusObjUtils.isNull(cluster)) {\n                continue;\n            }\n            List<Long> pluginIds = parsePluginIds(cluster.getPlugIds());\n            for (Long pluginId : pluginIds) {\n                Plugin logicalPlugin = pluginMap.get(pluginId);\n                if (AriusObjUtils.isNull(logicalPlugin)) {\n                    continue;\n                }\n                logicalPlugin.setInstalled(true);\n            }\n        }\n\n        return new ArrayList<>(pluginMap.values());\n    }\n\n    /**\n     * 根据逻辑集群Id添加插件信息\n     * @param  logicClusterId        逻辑集群ID\n     * @param  pluginDTO           插件信息\n     * @param  operator              操作人\n     * @return Result<Long> \n     */\n    @Override\n    public Result<Long> addPlugin(Long logicClusterId, PluginDTO pluginDTO,\n                                  String operator) throws NotFindSubclassException {\n\n        if (null != logicClusterId) {\n            List<Integer> clusterIdList = clusterRegionService.listPhysicClusterId(logicClusterId);\n            if (AriusObjUtils.isEmptyList(clusterIdList)) {\n                return Result.buildFail(\"对应物理集群不存在\");\n            }\n\n            String clusterIds = ListUtils.intList2String(clusterIdList);\n            pluginDTO.setPhysicClusterId(clusterIds);\n        }\n        return esPluginService.addESPlugin(pluginDTO);\n    }\n\n     /**\n     * 转移逻辑集群\n     *\n     * @param clusterLogicId  逻辑集群Id\n     * @param targetProjectId 项目Id\n     * @param submitor        提交人\n     * @return 成功/失败\n     */\n    @Override\n    public Result<Void> transferClusterLogic(Long clusterLogicId, Integer targetProjectId, String submitor) {\n\n        ESLogicClusterDTO esLogicClusterDTO = new ESLogicClusterDTO();\n        esLogicClusterDTO.setId(clusterLogicId);\n        esLogicClusterDTO.setProjectId(targetProjectId);\n        return editClusterLogicNotCheck(esLogicClusterDTO);\n    }\n\n     /**\n     * 模糊分页查询物理集群列表信息，仅获取部分属性\n     * @param param 模糊查询条件\n     * @return List<ClusterLogic> 逻辑集群列表\n     */\n    @Override\n    public List<ClusterLogic> pagingGetClusterLogicByCondition(ClusterLogicConditionDTO param) {\n        List<ClusterLogicPO> clusters = Lists.newArrayList();\n        try {\n            clusters = logicClusterDAO.pagingByCondition(param);\n        } catch (Exception e) {\n            e.printStackTrace();\n            LOGGER.error(\"class=ClusterPhyServiceImpl||method=pagingGetClusterPhyByCondition||msg={}\", e.getMessage(),\n                e);\n        }\n      return clusters.stream().map(this::clusterLogicPoProjectIdStrConvertClusterLogic).flatMap(Collection::stream)\n              .filter(clusterLogic -> filterClusterLogicByProjectId(clusterLogic,param.getProjectId()))\n              .collect(Collectors.toList());\n    }\n\n     /**\n     * 模糊查询统计总命中数\n     * @param param 模糊查询条件\n     * @return 命中数\n     */\n    @Override\n    public Long fuzzyClusterLogicHitByCondition(ClusterLogicConditionDTO param) {\n        return logicClusterDAO.getTotalHitByCondition(param);\n    }\n\n     /**\n     * 根据逻辑集群id列表获取逻辑集群列表信息\n     * @param clusterLogicIdList  逻辑集群id列表\n     * @return List<ClusterLogic> 逻辑集群列表\n     */\n    @Override\n    public List<ClusterLogic> getClusterLogicListByIds(List<Long> clusterLogicIdList) {\n        return logicClusterDAO.listByIds(new HashSet<>(clusterLogicIdList)).stream()\n                .map(this::clusterLogicPoProjectIdStrConvertClusterLogic).flatMap(Collection::stream)\n                .collect(Collectors.toList());\n    }\n\n     /**\n     *\n     * 通过项目Id和集群名获取逻辑集群列表\n     * @param clusterName\n     * @param projectId     \n     * @return {@code List<ClusterLogic>} 逻辑集群列表\n     */\n    @Override\n    public List<ClusterLogic> listClusterLogicByProjectIdAndName(Integer projectId, String clusterName) {\n        return logicClusterDAO.listByNameAndProjectId(clusterName, projectId).stream()\n                .map(this::clusterLogicPoProjectIdStrConvertClusterLogic)\n                .flatMap(Collection::stream)\n                .filter(clusterLogic -> filterClusterLogicByProjectId(clusterLogic,projectId))\n                .collect(Collectors.toList());\n    }\n    \n    /**\n     *\n     * 通过level获取逻辑集群并且将projectIdStr convert projectId list\n     * @param level 水平\n     * @return {@code List<ClusterLogic>}\n     */\n    @Override\n    public List<ClusterLogic> listLogicClustersByLevelThatProjectIdStrConvertProjectIdList(Integer level) {\n         return logicClusterDAO.listByLevel(level)\n                 .stream()\n                 .map(this::clusterLogicPoProjectIdStrConvertClusterLogic)\n                .flatMap(Collection::stream)\n                 .collect(Collectors.toList());\n    }\n    /***************************************** private method ****************************************************/\n    /**\n     * Check逻辑集群参数\n     *\n     * @param param     逻辑集群\n     * @param operation 操作类型\n     * @param projectId 项目id\n     * @return  Result\n     */\n    private Result<Void> checkLogicClusterParams(ESLogicClusterDTO param, OperationEnum operation, Integer projectId) {\n        if (AriusObjUtils.isNull(param)) {\n            return Result.buildParamIllegal(\"逻辑集群信息为空\");\n        }\n        if (ADD_BIND_MULTIPLE_PROJECT.equals(operation)) {\n            if (!existClusterLogicById(param.getId())) {\n                return Result.buildFail(\"逻辑集群不存在\");\n            }\n            return Result.buildSucc();\n        }\n        Result<Void> isIllegalResult = isIllegal(param);\n        if (isIllegalResult.failed()) {\n            return isIllegalResult;\n        }\n\n        if (ADD.equals(operation)) {\n            Result<Void> isFieldNullResult = addVoidResult(param);\n            if (isFieldNullResult != null) {\n                return isFieldNullResult;\n            }\n        } else if (EDIT.equals(operation)) {\n            Result<Void> editVoidResult = editVoidResult(param, projectId);\n            if (editVoidResult != null) {\n                return editVoidResult;\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Nullable\n    private Result<Void> addVoidResult(ESLogicClusterDTO param) {\n        Result<Void> isFieldNullResult = isFieldNull(param);\n        if (isFieldNullResult.failed()) {\n            return isFieldNullResult;\n        }\n        //逻辑集群绑定多个项目\n        ClusterLogicPO logicPO = logicClusterDAO.getByName(param.getName());\n        if (!AriusObjUtils.isNull(logicPO)) {\n            return Result.buildDuplicate(\"逻辑集群重复\");\n        }\n        return null;\n    }\n\n    @Nullable\n    private Result<Void> editVoidResult(ESLogicClusterDTO param, Integer projectId) {\n        if (AriusObjUtils.isNull(param.getId())) {\n            return Result.buildParamIllegal(\"逻辑集群ID为空\");\n        }\n\n        ClusterLogicPO oldPO = logicClusterDAO.getById(param.getId());\n        if (oldPO == null) {\n            return Result.buildNotExist(\"逻辑集群不存在\");\n        }\n        //当param中projectid存在\n        if (Objects.nonNull(param.getProjectId())) {\n            final boolean failed = str2ListProjectIds(oldPO).stream()\n                    .map(pid -> ProjectUtils.checkProjectCorrectly(a -> a, pid, param.getProjectId()))\n                \n                    .allMatch(Result::failed);\n            if (failed) {\n                return Result.buildFail(\"当前项目不属于超级项目或者持有该操作的项目\");\n            }\n        \n        } else {\n            //校验路径\n            final boolean failed = str2ListProjectIds(oldPO).stream()\n                    .map(pid -> ProjectUtils.checkProjectCorrectly(a -> a, pid, projectId))\n                \n                    .allMatch(Result::failed);\n        \n            if (failed) {\n                return Result.buildFail(\"当前项目不属于超级项目或者持有该操作的项目\");\n            }\n        }\n        return null;\n    }\n    \n    @NotNull\n    private static List<Integer> str2ListProjectIds(ClusterLogicPO oldPO) {\n        return Arrays.stream(StringUtils.split(oldPO.getProjectId(), \",\"))\n                .map(Integer::parseInt)\n                .collect(Collectors.toList());\n    }\n    \n    private Result<Void> isFieldNull(ESLogicClusterDTO param) {\n        if (AriusObjUtils.isNull(param.getName())) {\n            return Result.buildParamIllegal(\"集群名字为空\");\n        }\n        if (AriusObjUtils.isNull(param.getType())) {\n            return Result.buildParamIllegal(\"类型为空\");\n        }\n        if (AriusObjUtils.isNull(param.getProjectId())) {\n            return Result.buildParamIllegal(\"应用ID为空\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> isIllegal(ESLogicClusterDTO param) {\n        ClusterResourceTypeEnum typeEnum = ClusterResourceTypeEnum.valueOf(param.getType());\n        if (ClusterResourceTypeEnum.UNKNOWN.equals(typeEnum)) {\n            return Result.buildParamIllegal(\"新建逻辑集群提交内容中集群类型非法\");\n        }\n\n        if (param.getProjectId() != null && !projectService.checkProjectExist(param.getProjectId())) {\n            return Result.buildParamIllegal(\"应用ID非法\");\n        }\n        return Result.buildSucc();\n    }\n\n    /**\n     * 解析插件ID列表\n     *\n     * @param pluginIdsStr 插件ID格式化字符串\n     * @return List<Long>\n     */\n    private List<Long> parsePluginIds(String pluginIdsStr) {\n        List<Long> pluginIds = new ArrayList<>();\n        if (StringUtils.isNotBlank(pluginIdsStr)) {\n            String[] arr = StringUtils.split(pluginIdsStr, \",\");\n            for (String s : arr) {\n                pluginIds.add(Long.parseLong(s));\n            }\n        }\n        return pluginIds;\n    }\n\n    private void initLogicCluster(ESLogicClusterDTO param) {\n\n        if (AriusObjUtils.isNull(param.getConfigJson())) {\n            param.setConfigJson(\"\");\n        }\n\n        if (!AriusObjUtils.isNull(param.getDataNodeNum())) {\n            param.setQuota((double) param.getDataNodeNum());\n        }\n\n        if (AriusObjUtils.isNull(param.getDataCenter())) {\n            param.setDataCenter(EnvUtil.getDC().getCode());\n        }\n\n        if (AriusObjUtils.isNull(param.getLevel())) {\n            param.setLevel(1);\n        }\n\n        if (AriusObjUtils.isNull(param.getMemo())) {\n            param.setMemo(\"\");\n        }\n\n        if (AriusObjUtils.isNull(param.getQuota())) {\n            param.setQuota(0.00);\n        }\n\n        if (null == param.getHealth()) {\n            param.setHealth(DEFAULT_CLUSTER_HEALTH);\n        }\n    }\n\n    private void setPhyClusterInfo(List<ClusterRoleHost> esRolePhyClusterHosts, ClusterRoleInfo clusterRoleInfo,\n                                   List<ClusterRoleHost> clusterRoleHosts) {\n        for (ClusterRoleHost clusterRoleHost : esRolePhyClusterHosts) {\n            if (clusterRoleHost.getRoleClusterId().longValue() == clusterRoleInfo.getId().longValue()) {\n                clusterRoleHosts.add(ConvertUtil.obj2Obj(clusterRoleHost, ClusterRoleHost.class));\n            }\n        }\n    }\n\n   /**\n     * 设置逻辑集群信息\n     *\n     * @param logicClusterId\n     * @param clusterLogicPO\n     * @param clusterRoleInfo\n     * @param clusterRoleHosts    \n     */\n    private void setLogicClusterInfo(Long logicClusterId, ClusterLogicPO clusterLogicPO,\n                                     ClusterRoleInfo clusterRoleInfo, List<ClusterRoleHost> clusterRoleHosts) {\n        clusterRoleInfo.setPodNumber(clusterLogicPO.getDataNodeNum());\n        clusterRoleInfo.setMachineSpec(clusterLogicPO.getDataNodeSpec());\n\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(logicClusterId);\n        if (null == clusterRegion) {\n            return;\n        }\n\n        Result<List<ClusterRoleHost>> ret = clusterRoleHostService.listByRegionId(clusterRegion.getId().intValue());\n        if (ret.failed() || CollectionUtils.isEmpty(ret.getData())) {\n            LOGGER.error(\"class=ClusterLogicServiceImpl||method=setLogicClusterInfo||errMsg={}\", ret.getMessage());\n            return;\n        }\n\n        for (ClusterRoleHost clusterHost : ret.getData()) {\n            ClusterRoleHost clusterRoleHost = new ClusterRoleHost();\n            clusterRoleHost.setHostname(clusterHost.getHostname());\n            clusterRoleHost.setRole(DATA_NODE.getCode());\n\n            clusterRoleHosts.add(clusterRoleHost);\n        }\n    }\n    \n    /**\n     * 逻辑集群po中的projectId转换为int类型的ClusterLogic\n     *\n     * @param clusterLogicPO 集群逻辑po\n     * @return {@code List<ClusterLogic>}\n     */\n    public List<ClusterLogic> clusterLogicPoProjectIdStrConvertClusterLogic(ClusterLogicPO clusterLogicPO) {\n        if (clusterLogicPO==null){\n            return Collections.emptyList();\n        }\n        if (!StringUtils.contains(clusterLogicPO.getProjectId(), \",\")) {\n            return Collections.singletonList(ConvertUtil.obj2Obj(clusterLogicPO, ClusterLogic.class,\n                    clusterLogic -> clusterLogic.setProjectId(Integer.parseInt(clusterLogicPO.getProjectId()))\n            \n            ));\n        } else {\n            return str2ListProjectIds(clusterLogicPO).stream()\n                    .map(projectId -> ConvertUtil.obj2Obj(clusterLogicPO, ClusterLogic.class,\n                            clusterLogic -> clusterLogic.setProjectId(projectId))).distinct()\n                    .collect(Collectors.toList());\n        }\n    }\n    private boolean filterClusterLogicByProjectId(ClusterLogic clusterLogic, Integer projectId){\n        return Objects.isNull(projectId) || Objects.equals(clusterLogic.getProjectId(), projectId);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/monitortask/AriusMetaJobClusterDistributeService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.monitortask;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.AriusMetaJobClusterDistribute;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\n\n/**\n * Created by linyunan on 3/21/22\n * modify by ohushenglin_v 2022/5/9\n * @author ohushenglin_v\n */\npublic interface AriusMetaJobClusterDistributeService {\n\n    /**\n     * 根据host获取监控采集的集群名称列表\n     * @param monitorHost monitorHost\n     * @param size  size\n     * @return 监控的集群信息\n     */\n    List<AriusMetaJobClusterDistribute> getTaskByHost(String monitorHost, int size);\n\n    /**\n     * 获取单台机器监控采集的集群名称列表, 当分布式部署分组采集，可分摊采集压力\n     * @param monitorHost            采集机器名称\n     * @return                       采集集群列表\n     */\n    List<ClusterPhy> getSingleMachineMonitorCluster(String monitorHost);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/monitortask/impl/AriusMetaJobClusterDistributeServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.monitortask.impl;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.collections.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.AriusMetaJobClusterDistribute;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.monitortask.AriusMetaJobClusterDistributeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.monitor.AriusMetaJobClusterDistributeDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\n\n/**\n * @date    3/21/22\n * @author linyunan\n */\n@Service\npublic class AriusMetaJobClusterDistributeServiceImpl implements AriusMetaJobClusterDistributeService {\n    private static final ILog                LOGGER = LogFactory.getLog(AriusMetaJobClusterDistributeServiceImpl.class);\n\n    /**\n     * maxPoolSize，当前monitor-job能支持的最大集群采集个数，\n     * 超过maxPoolSize的集群不会被采集，保证maxPoolSize个集群采集的稳定性\n     */\n    @Value(\"${monitorJob.threadPool.maxsize:30}\")\n    private int                              maxPoolSize;\n\n    @Autowired\n    private ClusterPhyService                clusterPhyService;\n\n    @Autowired\n    private AriusMetaJobClusterDistributeDAO ariusMetaJobClusterDistributeDAO;\n\n    @Override\n    public List<ClusterPhy> getSingleMachineMonitorCluster(String monitorHost) {\n        List<ClusterPhy> monitorCluster = Lists.newArrayList();\n        List<ClusterPhy> clusterPhyList = clusterPhyService.listAllClusters();\n        if (CollectionUtils.isEmpty(clusterPhyList)) {\n            LOGGER.warn(\"class=AriusMetaJobClusterDistributeServiceImpl||method=getSingleMachineMonitorCluster||\"\n                        + \"msg=clusterPhyList is empty\");\n            return monitorCluster;\n        }\n\n        List<AriusMetaJobClusterDistribute> ariusMetaJobClusterDistributes = getTaskByHost(monitorHost, maxPoolSize);\n        if (CollectionUtils.isEmpty(ariusMetaJobClusterDistributes)) {\n            LOGGER.warn(\"class=AriusMetaJobClusterDistributeServiceImpl||method=getSingleMachineMonitorCluster||\"\n                        + \"msg=clusterMonitorTaskPOS is empty\");\n        } else {\n            Map<String, AriusMetaJobClusterDistribute> taskMap = ariusMetaJobClusterDistributes.stream()\n                .collect(Collectors.toMap(AriusMetaJobClusterDistribute::getCluster, c -> c));\n\n            for (ClusterPhy clusterPhy : clusterPhyList) {\n                if (null != taskMap.get(clusterPhy.getCluster())) {\n                    monitorCluster.add(clusterPhy);\n                }\n            }\n        }\n\n        LOGGER.info(\n            \"class=AriusMetaJobClusterDistributeServiceImpl||method=getSingleMachineMonitorCluster||monitorCluster={}\",\n            JSON.toJSONString(monitorCluster));\n        return monitorCluster;\n    }\n\n    @Override\n    public List<AriusMetaJobClusterDistribute> getTaskByHost(String monitorHost, int size) {\n        return ConvertUtil.list2List(ariusMetaJobClusterDistributeDAO.getTaskByHost(monitorHost, size),\n            AriusMetaJobClusterDistribute.class);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/physic/ClusterPhyService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.physic;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Plugin;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-30\n */\npublic interface ClusterPhyService {\n\n    /**\n     * 条件查询物理集群\n     * @param params 条件\n     * @return 集群列表\n     *\n     */\n    List<ClusterPhy> listClustersByCondt(ClusterPhyDTO params);\n\n    /**\n     * 删除物理集群\n     *\n     * @param clusterId 集群id\n     * @param projectId\n     * @return 成功 true 失败 false\n     */\n    Result<Boolean> deleteClusterById(Integer clusterId, Integer projectId);\n\n    /**\n     * 新建物理集群\n     * @param param 集群信息\n     * @param operator 操作人\n     * @return 成功 true 失败 false\n     */\n    Result<Boolean> createCluster(ClusterPhyDTO param, String operator);\n\n    /**\n     * 编辑物理集群信息\n     * @param param 物理集群信息\n     * @param operator 操作人\n     * @return 成功 true 失败 false\n     *\n     */\n    Result<Boolean> editCluster(ClusterPhyDTO param, String operator);\n\n    /**\n     * 根据集群名字查询集群\n     * @param clusterName 集群名字\n     * @return 集群\n     */\n    ClusterPhy getClusterByName(String clusterName);\n\n    /**\n     * 更新物理集群插件列表\n     * @param pluginIds    插件id列表\n     * @param phyClusterId 物理集群id\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> updatePluginIdsById(String pluginIds, Integer phyClusterId);\n\n    /**\n     * 列出所有集群\n     * @return 集群列表,如果没有返回空列表\n     */\n    List<ClusterPhy> listAllClusters();\n\n    /**\n     * 获取所有集群名称列表\n     *\n     * @return {@link List}<{@link String}>\n     */\n    List<String> listClusterNames();\n\n    /**\n     * 根据names列出所有集群\n     * @param names\n     * @return 集群列表,如果没有返回空列表\n     */\n    List<ClusterPhy> listClustersByNames(List<String> names);\n\n    /**\n     * 集群是否存在\n     *\n     * @param clusterName 集群名字\n     * @return true 存在\n     */\n    boolean isClusterExists(String clusterName);\n\n    /**\n     * 获取集群插件列表\n     * @param cluster 集群名称\n     * @return\n     */\n    List<Plugin> listClusterPlugins(String cluster);\n\n    /**\n     * 查询指定集群\n     * @param phyClusterId 集群id\n     * @return 集群  不存在返回null\n     */\n    ClusterPhy getClusterById(Integer phyClusterId);\n\n    /**\n     * 确保集群配置了DCDR的远端集群地址，如果没有配置尝试配置\n     * @param cluster 集群\n     * @param remoteCluster 远端集群\n     * @throws ESOperateException\n     * @return\n     */\n    boolean ensureDCDRRemoteCluster(String cluster, String remoteCluster) throws ESOperateException;\n\n    /**\n     * 更新集群的动态配置信息\n     * @param param 更新集群下动态配置项的信息\n     * @return result\n     */\n    Result<Boolean> updatePhyClusterDynamicConfig(ClusterSettingDTO param);\n\n    /**\n     * 获取集群路由的属性，例如rack1\n     * @param cluster 集群名称\n     * @return 属性的列表\n     */\n    Set<String> getRoutingAllocationAwarenessAttributes(String cluster);\n\n    /**\n     * 模糊分页查询物理集群列表信息，仅获取部分属性\n     * @param param 参数\n     * @return {@link List}<{@link ClusterPhy}>\n     */\n    List<ClusterPhy> pagingGetClusterPhyByCondition(ClusterPhyConditionDTO param);\n\n    /**\n     * 模糊查询统计总命中数\n     * @param param 模糊查询条件\n     * @return\n     */\n    Long fuzzyClusterPhyHitByCondition(ClusterPhyConditionDTO param);\n\n    /**\n     * 是否存在绑定指定安装包的集群\n     *\n     * @param packageId 安装包名\n     * @return true or false\n     */\n    boolean isClusterExistsByPackageId(Long packageId);\n\n\n\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/physic/ClusterRoleHostService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.physic;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterJoinDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleHostDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * ES集群节点 服务类\n *\n * @author chengxiang\n * @date 2022/5/9\n */\npublic interface ClusterRoleHostService {\n\n    /**\n     * 条件查询\n     * @param condt 条件\n     * @return 节点列表\n     */\n    List<ClusterRoleHost> queryNodeByCondt(ESClusterRoleHostDTO condt);\n\n    /**\n     * 查询集群节点列表\n     * @param cluster 集群\n     * @return 节点列表 集群不存在返回空列表\n     */\n    List<ClusterRoleHost> getNodesByCluster(String cluster);\n\n    /**\n     * 查询集群节点列表\n     * @param cluster 集群\n     * @return 节点列表 集群不存在返回空列表\n     */\n    List<ClusterRoleHost> getOnlineNodesByCluster(String cluster);\n\n    /**\n     * 修改节点状态\n     * @param param 参数\n     * @param operator 操作人\n     * @return 成功 true  失败  false\n     */\n    Result<Void> editNodeStatus(ESClusterRoleHostDTO param, String operator);\n\n    /**\n     * 修改节点参数\n     * @param param 参数\n     * @return 成功 true  失败  false\n     */\n    Result<Void> editNode(ESClusterRoleHostDTO param);\n\n    /**\n     * 编辑节点列表regionId\n     * @param nodeIds  节点主键列表\n     * @param regionId regionId\n     * @return      false or true\n     */\n    boolean editNodeRegionId(List<Integer> nodeIds, Integer regionId) throws AdminOperateException;\n\n    /**\n     * 采集集群节点配置信息到MySQL, 包括节点状态\n     * @param cluster 集群名字\n     * @return true/false\n     * @throws AdminTaskException\n     */\n    boolean collectClusterNodeSettings(String cluster) throws AdminTaskException;\n\n    /**\n     * 全量录入根据配置的节点信息持久化到MySQL, 包括节点状态\n     * @param param 参数\n     * @return true/false\n     */\n    boolean saveClusterNodeSettings(ClusterJoinDTO param) throws AdminTaskException;\n\n    /**\n     * 创建或扩容集群节点时录入节点数据到MySQL, 包括节点规格\n     * @param param               节点角色列表\n     * @param phyClusterName      物理集群名称\n     * @throws AdminTaskException 事务异常\n     * @return                    操作结果\n     */\n    boolean createClusterNodeSettings(List<ESClusterRoleHost> param, String phyClusterName) throws AdminTaskException;\n\n    /**\n     * 获取所有在线的节点\n     * @return list\n     */\n    List<ClusterRoleHost> listOnlineNode();\n\n    /**\n     * 保存节点信息\n     * @param clusterRoleHost\n     * @return\n     */\n    Result<Long> save(ClusterRoleHost clusterRoleHost);\n\n    /**\n     * 获取节点信息\n     * @param id 主键\n     * @return 节点对象\n     */\n    ClusterRoleHost getById(Long id);\n\n    /**\n     * 获取节点信息\n     * @param roleClusterId 角色集群id\n     * @return 节点对象\n     */\n    List<ClusterRoleHost> getByRoleClusterId(Long roleClusterId);\n\n    /**\n     * 根据集群和nodeSet 获取节点信息\n     * @param cluster\n     * @param nodeSets\n     * @return\n     */\n    List<ClusterRoleHost> getByClusterAndNodeSets(String cluster, List<String> nodeSets);\n\n    /**\n     * 获取节点信息\n     * @param roleClusterIds 多个角色集群id\n     * @return  Map<角色集群id,List<节点对象>>\n     */\n    Map<Long, List<ClusterRoleHost>> getByRoleClusterIds(List<Long> roleClusterIds);\n\n    /**\n     * 获取节点名\n     * @param clusterId 集群id\n     * @param role      角色\n     * @return\n     */\n    List<String> getHostNamesByRoleAndClusterId(Long clusterId, String role);\n\n    /**\n     * 获取节点信息\n     * @param clusterId 集群id\n     * @param role      角色\n     * @return\n     */\n    List<ClusterRoleHost> getByRoleAndClusterId(Long clusterId, String role);\n\n    /**\n     * 逻辑删除节点\n     *\n     * @param cluster   集群名称\n     * @param projectId\n     * @return\n     */\n    Result<Void> deleteByCluster(String cluster, Integer projectId);\n\n    /**\n     * 获取所有节点(包括不在线)\n     * @return\n     */\n    List<ClusterRoleHost> listAllNode();\n\n    /**\n     * 获取平台指定角色(masternode/datanode/clientnode)节点列表\n     * @param roleCode    节点角色 {@link ESClusterNodeRoleEnum}\n     * @return            List<ClusterRoleHost>\n     */\n    List<ClusterRoleHost> listAllNodeByRole(Integer roleCode);\n\n    /**\n     * 删除\n     * @param id\n     * @return\n     */\n    Result<Void> deleteById(Long id);\n\n    /**\n     * 根据主机名称和节点的角色id删除对应的节点\n     *\n     * @param hostname 主机名称列表\n     * @param roleId   角色id\n     * @return\n     */\n    Result deleteByHostNameAndRoleId(List<String> hostname, Long roleId);\n\n    /**\n     * 获取ClusterHost节点信息\n     * @param hostName\n     * @return\n     */\n    ClusterRoleHost getByHostName(String hostName);\n\n    /**\n     * 获取已删除节点\n     * @param hostname\n     */\n    ClusterRoleHost getDeleteHostByHostNameAnRoleId(String hostname, Long roleId);\n\n    /**恢复节点状态\n     * @param deleteHost\n     * @return\n     */\n    Result<Void> setHostValid(ClusterRoleHost deleteHost);\n\n    /**\n     * 构建集群client角色的HttpAddresses地址\n     * @return ip:port,ip:port\n     */\n    String buildESClientHttpAddressesStr(List<ESClusterRoleHostDTO> roleClusterHosts);\n\n    /**\n     * 构建集群client, master角色的HttpAddresses地址\n     * @return List<ip:port>\n     */\n    List<String> buildESClientMasterHttpAddressesList(List<ESClusterRoleHostDTO> roleClusterHosts);\n\n    /**\n     * 构建集群master,client,data角色的HttpAddresses地址\n     * @return List<ip:port>\n     */\n    List<String> buildESAllRoleHttpAddressesList(List<ESClusterRoleHostDTO> roleClusterHosts);\n\n    /**\n     * 获取角色id对应的机器数（ip数目）\n     */\n    int getPodNumberByRoleId(Long roleId);\n\n    /**\n     * 根据regionId获取节点信息\n     * @param regionId      regionId\n     * @return              Result<List<ClusterRoleHost>>\n     */\n    Result<List<ClusterRoleHost>> listByRegionId(Integer regionId);\n    \n   \n    /**\n     * 它返回 ClusterRoleHost 对象的列表。\n     *\n     * @param ids 要查询的 id 列表。\n     * @return 列表<ClusterRoleHost>\n     */\n    List<ClusterRoleHost> listById(List<Integer> ids);\n\n    List<ClusterRoleHost> listNodesByClusters(List<String> phyClusterNames);\n    boolean deleteByIds(List<Integer> ids);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/physic/ClusterRoleService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.physic;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * ES集群角色 服务类\n * @author chengxiang\n * @date 2022/5/9\n */\npublic interface ClusterRoleService {\n\n    /**\n     * 保存集群角色\n     * @param esClusterRoleDTO\n     * @return id\n     */\n    Result<Void> save(ESClusterRoleDTO esClusterRoleDTO);\n\n    /**\n     * 角色不存在则创建，存在则返回已存在的角色\n     * @param clusterName 集群名\n     * @param role        角色, ESClusterNodeRoleEnum的desc\n     * @return\n     */\n    ClusterRoleInfo createRoleClusterIfNotExist(String clusterName, String role);\n\n    /**\n     * 根据集群Id查询名下全部角色\n     * @param clusterId\n     * @return List<RoleCluster>\n     */\n    List<ClusterRoleInfo> getAllRoleClusterByClusterId(Integer clusterId);\n\n    Map<Long, List<ClusterRoleInfo>> getAllRoleClusterByClusterIds(List<Integer> clusterIds);\n\n    /**\n     * 根据集群Id和roleClusterRole查询角色\n     * @param clusterId\n     * @return ESRoleClusterPO\n     */\n    ClusterRoleInfo getByClusterIdAndClusterRole(Long clusterId, String roleClusterName);\n\n    /**\n     * 根据集群Id和role查询角色\n     * @param clusterId\n     * @return RoleCluster\n     */\n    ClusterRoleInfo getByClusterIdAndRole(Long clusterId, String role);\n\n    /**\n     * 根据集群Id和role查询角色\n     * @param clusterName 集群名\n     * @return RoleCluster\n     */\n    ClusterRoleInfo getByClusterNameAndRole(String clusterName, String role);\n\n    /**\n     * 修改集群角色的pod数量\n     * @param clusterRoleInfo\n     * @return Result\n     */\n    Result<Void> updatePodByClusterIdAndRole(ClusterRoleInfo clusterRoleInfo);\n\n    /**\n     * 修改集群角色的es版本\n     * @param clusterId\n     * @param role\n     * @param version\n     * @return\n     */\n    Result<Void> updateVersionByClusterIdAndRole(Long clusterId, String role, String version);\n\n    /**\n     * 删除集群角色\n     *\n     * @param clusterId\n     * @param projectId\n     * @return\n     */\n    Result<Void> deleteRoleClusterByClusterId(Integer clusterId, Integer projectId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/physic/impl/ClusterPhyServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.DEFAULT_CLUSTER_HEALTH;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Plugin;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterPhyPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.SortConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterDynamicConfigsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPluginService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.resource.PhyClusterDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.model.type.ESVersion;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author didi\n */\n@Service\n@NoArgsConstructor\npublic class ClusterPhyServiceImpl implements ClusterPhyService {\n\n    private static final ILog      LOGGER                      = LogFactory.getLog(ClusterPhyServiceImpl.class);\n\n    private static final String    CLUSTER_NOT_EXIST           = \"集群不存在\";\n\n    @Autowired\n    private PhyClusterDAO          clusterDAO;\n\n    @Autowired\n    private ESClusterService       esClusterService;\n\n    @Autowired\n    private ESPluginService        esPluginService;\n\n    @Autowired\n    private ClusterRoleService     clusterRoleService;\n\n    @Autowired\n    private ClusterRoleHostService clusterRoleHostService;\n\n    private static final String    DEFAULT_WRITE_ACTION        = \"RestBulkAction,RestDeleteAction,RestIndexAction,RestUpdateAction\";\n    private static final String    PHYSICAL_CLUSTER_NOT_EXISTS = \"物理集群不存在\";\n\n    private static final String    COMMA_SYMBOL                = \",\";\n\n    /**\n     * 条件查询\n     * @param params 条件\n     * @return 集群列表\n     */\n    @Override\n    public List<ClusterPhy> listClustersByCondt(ClusterPhyDTO params) {\n        List<ClusterPhyPO> clusterPOs = clusterDAO.listByCondition(ConvertUtil.obj2Obj(params, ClusterPhyPO.class));\n\n        if (CollectionUtils.isEmpty(clusterPOs)) {\n            return Lists.newArrayList();\n        }\n\n        return ConvertUtil.list2List(clusterPOs, ClusterPhy.class);\n    }\n\n    /**\n     * 删除集群\n     *\n     * @param clusterId 集群id\n     * @param projectId\n     * @return 成功 true 失败 false\n     * <p>\n     * 集群不存在\n     */\n    @Override\n    public Result<Boolean> deleteClusterById(Integer clusterId, Integer projectId) {\n        ClusterPhyPO clusterPO = clusterDAO.getById(clusterId);\n        if (clusterPO == null) {\n            return Result.buildNotExist(CLUSTER_NOT_EXIST);\n        }\n        //校验操作项目的合法性\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n\n        return Result.buildBoolen(clusterDAO.delete(clusterId) == 1);\n    }\n\n    /**\n     * 新建集群\n     * @param param    集群信息\n     * @param operator 操作人\n     * @return 成功 true 失败 false\n     * <p>\n     * 参数不合理\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Boolean> createCluster(ClusterPhyDTO param, String operator) {\n        Result<Boolean> checkResult = checkClusterParam(param, OperationEnum.ADD);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=ESClusterPhyServiceImpl||method=addCluster||msg={}\", checkResult.getMessage());\n            return checkResult;\n        }\n\n        initClusterParam(param);\n\n        ClusterPhyPO clusterPO = ConvertUtil.obj2Obj(param, ClusterPhyPO.class);\n        boolean succ = (1 == clusterDAO.insert(clusterPO));\n        if (succ) {\n            param.setId(clusterPO.getId());\n        }\n        return Result.buildBoolen(succ);\n    }\n\n    /**\n     * 编辑集群\n     * @param param    集群信息\n     * @param operator 操作人\n     * @return 成功 true 失败 false\n     * <p>\n     * IllegalArgumentException\n     * 参数不合理\n     * 集群不存在\n     */\n    @Override\n    public Result<Boolean> editCluster(ClusterPhyDTO param, String operator) {\n        Result<Boolean> checkResult = checkClusterParam(param, OperationEnum.EDIT);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=ESClusterPhyServiceImpl||method=editCluster||msg={}\", checkResult.getMessage());\n            return checkResult;\n        }\n\n        boolean succ = (1 == clusterDAO.update(ConvertUtil.obj2Obj(param, ClusterPhyPO.class)));\n        return Result.buildBoolen(succ);\n    }\n\n    /**\n     * 根据集群名字查询集群\n     * @param clusterName 集群名字\n     * @return 集群\n     */\n    @Override\n    public ClusterPhy getClusterByName(String clusterName) {\n        // 获取物理集群\n        ClusterPhyPO clusterPO = clusterDAO.getByName(clusterName);\n        if (null == clusterPO) {\n            return null;\n        }\n\n        // 转换物理集群对象\n        ClusterPhy clusterPhy = ConvertUtil.obj2Obj(clusterPO, ClusterPhy.class);\n\n        // 添加角色、机器信息\n        List<ClusterRoleInfo> clusterRoleInfos = clusterRoleService.getAllRoleClusterByClusterId(clusterPhy.getId());\n        if (CollectionUtils.isNotEmpty(clusterRoleInfos)) {\n            // 角色信息\n            clusterPhy.setClusterRoleInfos(clusterRoleInfos);\n\n            // 机器信息\n            List<ClusterRoleHost> clusterRoleHosts = new ArrayList<>();\n            Map<Long, List<ClusterRoleHost>> map = clusterRoleHostService.getByRoleClusterIds(\n                clusterRoleInfos.stream().map(ClusterRoleInfo::getId).collect(Collectors.toList()));\n            for (ClusterRoleInfo clusterRoleInfo : clusterRoleInfos) {\n                List<ClusterRoleHost> esClusterRoleHosts = map.getOrDefault(clusterRoleInfo.getId(), new ArrayList<>());\n                clusterRoleHosts.addAll(esClusterRoleHosts);\n            }\n            clusterPhy.setClusterRoleHosts(clusterRoleHosts);\n        }\n\n        return clusterPhy;\n    }\n\n    @Override\n    public Result<Void> updatePluginIdsById(String pluginIds, Integer phyClusterId) {\n        boolean succ = (1 == clusterDAO.updatePluginIdsById(pluginIds, phyClusterId));\n        return Result.build(succ);\n    }\n\n    @Override\n    public List<ClusterPhy> listAllClusters() {\n        return ConvertUtil.list2List(clusterDAO.listAll(), ClusterPhy.class);\n    }\n\n    @Override\n    public List<String> listClusterNames() {\n        List<String> clusterNameList = Lists.newArrayList();\n        try {\n            clusterNameList.addAll(clusterDAO.listAllName());\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterPhyServiceImpl||method=listAllClusterNameList||errMsg={}\", e.getMessage(), e);\n        }\n        return clusterNameList;\n    }\n\n    @Override\n    public List<ClusterPhy> listClustersByNames(List<String> names) {\n        if (CollectionUtils.isEmpty(names)) {\n            return new ArrayList<>();\n        }\n        return ConvertUtil.list2List(clusterDAO.listByNames(names), ClusterPhy.class);\n    }\n\n    /**\n     * 集群是否存在\n     * @param clusterName 集群名字\n     * @return true 存在\n     */\n    @Override\n    public boolean isClusterExists(String clusterName) {\n        return StringUtils.isNotBlank(clusterName)&&clusterDAO.getByName(clusterName) != null;\n    }\n\n    /**\n     * 根据集群名称解析获取对应的插件列表\n     * @param cluster 集群名称\n     * @return\n     */\n    @Override\n    public List<Plugin> listClusterPlugins(String cluster) {\n        ClusterPhyPO clusterPhy = clusterDAO.getByName(cluster);\n        if (AriusObjUtils.isNull(clusterPhy)) {\n            return new ArrayList<>();\n        }\n\n        List<Plugin> pluginList = ConvertUtil\n            .list2List(esPluginService.listClusterAndDefaultESPlugin(clusterPhy.getId().toString()), Plugin.class);\n\n        // 将从插件列表获得的所有的插件(系统默认以及自定义)安装状态设置为FALSE\n        Map<Long, Plugin> pluginMap = new HashMap<>(0);\n        for (Plugin esPlugin : pluginList) {\n            esPlugin.setInstalled(Boolean.FALSE);\n            pluginMap.put(esPlugin.getId(), esPlugin);\n        }\n\n        // 获取集群对应的已安装的插件列表，将对应的已安装的插件的安装状态设置为TRUE\n        List<Long> pluginIds = parsePluginIds(clusterPhy.getPlugIds());\n        for (Long pluginId : pluginIds) {\n            Plugin phyPlugin = pluginMap.get(pluginId);\n            if (AriusObjUtils.isNull(phyPlugin)) {\n                continue;\n            }\n            phyPlugin.setInstalled(true);\n        }\n\n        return new ArrayList<>(pluginMap.values());\n    }\n\n    /**\n     * 查询指定集群\n     * @param phyClusterId 集群id\n     * @return 集群  不存在返回null\n     */\n    @Override\n    public ClusterPhy getClusterById(Integer phyClusterId) {\n        ClusterPhyPO clusterPO = clusterDAO.getById(phyClusterId);\n        return ConvertUtil.obj2Obj(clusterPO, ClusterPhy.class);\n    }\n\n    /**\n     * 确保集群配置了DCDR的远端集群地址，如果没有配置尝试配置\n     * @param cluster       集群\n     * @param remoteCluster 远端集群\n     * @return\n     */\n    @Override\n    public boolean ensureDCDRRemoteCluster(String cluster, String remoteCluster) throws ESOperateException {\n\n        ClusterPhy clusterPhy = getClusterByName(cluster);\n        if (clusterPhy == null) {\n            return false;\n        }\n\n        ClusterPhy remoteClusterPhy = getClusterByName(remoteCluster);\n        if (remoteClusterPhy == null) {\n            return false;\n        }\n\n        return esClusterService.syncPutRemoteCluster(cluster, remoteCluster,\n            buildTcpAddress(remoteCluster), 3);\n    }\n\n    @Override\n    public Result<Boolean> updatePhyClusterDynamicConfig(ClusterSettingDTO param) {\n        Result<ClusterDynamicConfigsEnum> result = checkClusterDynamicType(param);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n\n        Map<String, Object> persistentConfig = Maps.newHashMap();\n        persistentConfig.put(param.getKey(), param.getValue());\n        return Result.buildBoolen(esClusterService.syncPutPersistentConfig(param.getClusterName(), persistentConfig));\n    }\n\n    @Override\n    public Set<String> getRoutingAllocationAwarenessAttributes(String cluster) {\n        if (!isClusterExists(cluster)) {\n            return Sets.newHashSet();\n        }\n\n        return esClusterService.syncGetAllNodesAttributes(cluster);\n    }\n\n    @Override\n    public List<ClusterPhy> pagingGetClusterPhyByCondition(ClusterPhyConditionDTO param) {\n        String sortTerm = null == param.getSortTerm() ? SortConstant.ID : param.getSortTerm();\n        String sortType = param.getOrderByDesc() ? SortConstant.DESC : SortConstant.ASC;\n        param.setSortTerm(sortTerm);\n        param.setSortType(sortType);\n        param.setFrom((param.getPage() - 1) * param.getSize());\n        if(StringUtils.isNotEmpty(param.getDesc())){\n            param.setDesc(CommonUtils.sqlFuzzyQueryTransfer(param.getDesc()));\n        }\n        List<ClusterPhyPO> clusters = Lists.newArrayList();\n        try {\n            clusters = clusterDAO.pagingByCondition(param);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ClusterPhyServiceImpl||method=pagingGetClusterPhyByCondition||msg={}\", e.getMessage(),\n                e);\n        }\n        return ConvertUtil.list2List(clusters, ClusterPhy.class);\n    }\n\n    @Override\n    public Long fuzzyClusterPhyHitByCondition(ClusterPhyConditionDTO param) {\n        return clusterDAO.getTotalHitByCondition(param);\n    }\n\n    /**\n     * 安装包是否绑定集群\n     * @param packageId 安装包名\n     * @return true or false\n     */\n    @Override\n    public boolean isClusterExistsByPackageId(Long packageId) {\n        return clusterDAO.getTotalHitByPackageId(packageId) > 0;\n    }\n\n\n    /**************************************** private method ***************************************************/\n    private List<String> buildTcpAddress(String cluster) {\n        try {\n            return esClusterService.syncGetTcpAddress(cluster);\n        } catch (Exception e) {\n            LOGGER.error(\"method=genTcpAddr||cluster={}||errMsg={}\", cluster, e.getMessage(), e);\n        }\n\n        return Lists.newArrayList();\n    }\n\n    private Result<ClusterDynamicConfigsEnum> checkClusterDynamicType(ClusterSettingDTO param) {\n        if (!isClusterExists(param.getClusterName())) {\n            return Result.buildFail(CLUSTER_NOT_EXIST);\n        }\n\n        ClusterDynamicConfigsEnum clusterSettingEnum = ClusterDynamicConfigsEnum.valueCodeOfName(param.getKey());\n        if (clusterSettingEnum.equals(ClusterDynamicConfigsEnum.UNKNOWN)) {\n            return Result.buildFail(\"传入的字段类型未知\");\n        }\n\n        if (!clusterSettingEnum.getCheckFun().apply(String.valueOf(param.getValue())).booleanValue()) {\n            return Result.buildFail(\"传入的字段参数格式有误\");\n        }\n\n        if (clusterSettingEnum == ClusterDynamicConfigsEnum.CLUSTER_ROUTING_ALLOCATION_AWARENESS_ATTRIBUTES\n            && !getRoutingAllocationAwarenessAttributes(param.getClusterName())\n                .containsAll((JSONArray) JSON.toJSON(param.getValue()))) {\n            return Result.buildFail(\"传入的attributes字段参数有误\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Boolean> checkClusterParam(ClusterPhyDTO param, OperationEnum operation) {\n        if (AriusObjUtils.isNull(param)) {\n            return Result.buildParamIllegal(\"集群信息为空\");\n        }\n\n        if (OperationEnum.ADD.equals(operation)) {\n            Result<Boolean> result = handleAdd(param);\n            if (result.failed()) {\n                return result;\n            }\n        } else if (OperationEnum.EDIT.equals(operation)) {\n            Result<Boolean> result = handleEdit(param);\n            if (result.failed()) {\n                return result;\n            }\n        }\n\n        Result<Boolean> isIllegalResult = isIllegal(param);\n        if (isIllegalResult.failed()) {\n            return isIllegalResult;\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Boolean> handleEdit(ClusterPhyDTO param) {\n        if (AriusObjUtils.isNull(param.getId())) {\n            return Result.buildParamIllegal(\"集群ID为空\");\n        }\n\n        ClusterPhyPO oldClusterPO = clusterDAO.getById(param.getId());\n        if (oldClusterPO == null) {\n            return Result.buildNotExist(CLUSTER_NOT_EXIST);\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Boolean> handleAdd(ClusterPhyDTO param) {\n        Result<Boolean> isFieldNullResult = isFieldNull(param);\n        if (isFieldNullResult.failed()) {\n            return isFieldNullResult;\n        }\n\n        if (param.getCluster() != null) {\n            ClusterPhyPO clusterPO = clusterDAO.getByName(param.getCluster());\n            if (clusterPO != null && clusterPO.getId().equals(param.getId())) {\n                return Result.buildDuplicate(\"集群重复\");\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Boolean> isIllegal(ClusterPhyDTO param) {\n\n        if (param.getEsVersion() != null && ESVersion.valueBy(param.getEsVersion()) == null) {\n            return Result.buildParamIllegal(\"es版本号非法\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Boolean> isFieldNull(ClusterPhyDTO param) {\n        if (AriusObjUtils.isNull(param.getCluster())) {\n            return Result.buildParamIllegal(\"集群名称为空\");\n        }\n        if (AriusObjUtils.isNull(param.getHttpAddress())) {\n            return Result.buildParamIllegal(\"集群HTTP地址为空\");\n        }\n        if (AriusObjUtils.isNull(param.getType())) {\n            return Result.buildParamIllegal(\"集群类型为空\");\n        }\n        if (AriusObjUtils.isNull(param.getDataCenter())) {\n            return Result.buildParamIllegal(\"数据中心为空\");\n        }\n        if (AriusObjUtils.isNull(param.getIdc())) {\n            return Result.buildParamIllegal(\"机房信息为空\");\n        }\n        if (AriusObjUtils.isNull(param.getEsVersion())) {\n            return Result.buildParamIllegal(\"es版本为空\");\n        }\n        return Result.buildSucc();\n    }\n\n    private void initClusterParam(ClusterPhyDTO param) {\n        if (param.getWriteAddress() == null) {\n            param.setWriteAddress(\"\");\n        }\n\n        if (param.getReadAddress() == null) {\n            param.setReadAddress(\"\");\n        }\n\n        if (param.getHttpWriteAddress() == null) {\n            param.setHttpWriteAddress(\"\");\n        }\n\n        if (param.getHttpAddress() == null) {\n            param.setHttpAddress(\"\");\n        }\n\n        if (param.getPassword() == null) {\n            param.setPassword(\"\");\n        }\n\n        if (param.getImageName() == null) {\n            param.setImageName(\"\");\n        }\n\n        if (param.getLevel() == null) {\n            param.setLevel(1);\n        }\n\n        if (param.getCreator() == null) {\n            param.setCreator(\"\");\n        }\n\n        if (param.getNsTree() == null) {\n            param.setNsTree(\"\");\n        }\n\n        if (param.getDesc() == null) {\n            param.setDesc(\"\");\n        }\n\n        if (param.getWriteAction() == null) {\n            param.setWriteAction(DEFAULT_WRITE_ACTION);\n        }\n\n        \n\n        if (null == param.getHealth()) {\n            param.setHealth(DEFAULT_CLUSTER_HEALTH);\n        }\n\n        if (null == param.getActiveShardNum()) {\n            param.setActiveShardNum(0L);\n        }\n\n        if (null == param.getDiskTotal()) {\n            param.setDiskTotal(0L);\n        }\n\n        if (null == param.getDiskUsage()) {\n            param.setDiskUsage(0L);\n        }\n\n        if (null == param.getDiskUsagePercent()) {\n            param.setDiskUsagePercent(0D);\n        }\n\n        if (null == param.getPlatformType()) {\n            param.setPlatformType(\"\");\n        }\n        if (null == param.getResourceType()) {\n            param.setResourceType(ClusterResourceTypeEnum.UNKNOWN.getCode());\n        }\n        if (null == param.getGatewayUrl()) {\n            param.setGatewayUrl(\"\");\n        }\n        if (null == param.getKibanaAddress()) {\n            param.setKibanaAddress(\"\");\n        }\n        if (null == param.getCerebroAddress()) {\n            param.setCerebroAddress(\"\");\n        }\n        if (null == param.getProxyAddress()) {\n            param.setProxyAddress(\"\");\n        }\n    }\n\n    /**\n     * 解析插件ID列表\n     *\n     * @param pluginIdsStr 插件ID格式化字符串\n     * @return\n     */\n    private List<Long> parsePluginIds(String pluginIdsStr) {\n        List<Long> pluginIds = new ArrayList<>();\n        if (StringUtils.isNotBlank(pluginIdsStr)) {\n            String[] arr = StringUtils.split(pluginIdsStr, \",\");\n            for (int i = 0; i < arr.length; ++i) {\n                pluginIds.add(Long.parseLong(arr[i]));\n            }\n        }\n        return pluginIds;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/physic/impl/ClusterRoleHostServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.CLIENT_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.DATA_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.MASTER_NODE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.UNKNOWN;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum.valueOf;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeStatusEnum.OFFLINE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeStatusEnum.ONLINE;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_ROLE_CLIENT;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_ROLE_DATA;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_ROLE_MASTER;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterJoinDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleHostDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRoleHostPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.Getter;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.SizeUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESClusterRoleHostDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodes.ClusterNodeInfo;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodessetting.ClusterNodeSettings;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.http.HttpInfo;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * ES集群表对应各角色主机列表 服务实现类\n * @author chengxiang\n * @date 2022/5/9\n */\n@Service\npublic class ClusterRoleHostServiceImpl implements ClusterRoleHostService {\n\n    private static final ILog    LOGGER = LogFactory.getLog(ClusterRoleHostServiceImpl.class);\n\n    @Autowired\n    private ESClusterRoleHostDAO clusterRoleHostDAO;\n\n    @Autowired\n    private ClusterRoleService   clusterRoleService;\n\n    @Autowired\n    private ESClusterNodeService esClusterNodeService;\n\n    @Autowired\n    private ESClusterService     esClusterService;\n\n    @Override\n    public List<ClusterRoleHost> queryNodeByCondt(ESClusterRoleHostDTO condt) {\n        List<ESClusterRoleHostPO> pos = clusterRoleHostDAO\n            .listByCondition(ConvertUtil.obj2Obj(condt, ESClusterRoleHostPO.class));\n        return ConvertUtil.list2List(pos, ClusterRoleHost.class);\n    }\n\n    @Override\n    public List<ClusterRoleHost> getNodesByCluster(String cluster) {\n        List<ESClusterRoleHostPO> pos = clusterRoleHostDAO.listByCluster(cluster);\n        return ConvertUtil.list2List(pos, ClusterRoleHost.class);\n    }\n\n    @Override\n    public List<ClusterRoleHost> getOnlineNodesByCluster(String cluster) {\n        List<ClusterRoleHost> clusterRoleHosts = getNodesByCluster(cluster);\n        if (CollectionUtils.isEmpty(clusterRoleHosts)) {\n            return Lists.newArrayList();\n        }\n        return clusterRoleHosts.stream().filter(esClusterNode -> ONLINE.getCode() == esClusterNode.getStatus())\n            .collect(Collectors.toList());\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> editNodeStatus(ESClusterRoleHostDTO param, String operator) {\n        if (AriusObjUtils.isNull(param)) {\n            return Result.buildParamIllegal(\"节点信息为空\");\n        }\n        if (AriusObjUtils.isNull(param.getId())) {\n            return Result.buildParamIllegal(\"节点ID为空\");\n        }\n        if (AriusObjUtils.isNull(param.getStatus())) {\n            return Result.buildParamIllegal(\"节点状态为空\");\n        }\n        if (ESClusterNodeStatusEnum.UNKNOWN != ESClusterNodeStatusEnum.valueOf(param.getStatus())) {\n            return Result.buildParamIllegal(\"节点状态非法\");\n        }\n\n        ESClusterRoleHostPO hostPo = clusterRoleHostDAO.getById(param.getId());\n        if (hostPo == null) {\n            return Result.buildNotExist(\"节点不存在\");\n        }\n\n        ESClusterRoleHostPO clusterHostPO = new ESClusterRoleHostPO();\n        clusterHostPO.setId(param.getId());\n        clusterHostPO.setStatus(param.getStatus());\n\n        return Result.build(1 == (clusterRoleHostDAO.update(clusterHostPO)));\n    }\n\n    @Override\n    public Result<Void> editNode(ESClusterRoleHostDTO param) {\n        Result<Void> checkResult = checkNodeParam(param, OperationEnum.EDIT);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=ClusterRoleHostServiceImpl||method=editNode|msg={}\", checkResult.getMessage());\n            return checkResult;\n        }\n        return Result.build(1 == clusterRoleHostDAO.update(ConvertUtil.obj2Obj(param, ESClusterRoleHostPO.class)));\n    }\n\n    @Override\n    public boolean editNodeRegionId(List<Integer> nodeIds, Integer regionId) throws AdminOperateException {\n        if (CollectionUtils.isEmpty(nodeIds)) {\n            throw new AdminOperateException(\"节点不存在\", ResultType.ILLEGAL_PARAMS);\n        }\n        if (null == regionId) {\n            throw new AdminOperateException(\"regionId为空\", ResultType.ILLEGAL_PARAMS);\n        }\n\n        return clusterRoleHostDAO.updateRegionId(nodeIds, regionId) >= 1;\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public boolean collectClusterNodeSettings(String cluster) throws AdminTaskException {\n        // get node information from ES engine\n        List<ESClusterRoleHostPO> nodesFromEs = null;\n\n        try {\n            nodesFromEs = getClusterHostFromEsAndCreateRoleClusterIfNotExist(cluster);\n        } catch (ESOperateException e) {\n            LOGGER.warn(\n                    \"class=RoleClusterHostServiceImpl||method=collectClusterNodeSettings||clusterPhyName={}||errMag=fail to get cluster host\",\n                    cluster);\n            return false;\n        }\n        if (CollectionUtils.isEmpty(nodesFromEs)) {\n            clusterRoleHostDAO.offlineByCluster(cluster);\n            LOGGER.warn(\n                \"class=RoleClusterHostServiceImpl||method=collectClusterNodeSettings||clusterPhyName={}||errMag=fail to collect cluster node settings\",\n                cluster);\n            return false;\n        }\n\n        // get node info from db\n        Map<String/*roleClusterId@esNodeName*/, ESClusterRoleHostPO> nodePOFromDbMap = getNodeInfoFromDbMap(cluster);\n        List<ESClusterRoleHostPO> shouldAdd = Lists.newArrayList();\n        List<ESClusterRoleHostPO> shouldEdit = Lists.newArrayList();\n\n        for (ESClusterRoleHostPO nodePO : nodesFromEs) {\n            if (nodePOFromDbMap.containsKey(nodePO.getKey())) {\n                nodePO.setId(nodePOFromDbMap.get(nodePO.getKey()).getId());\n                nodePO.setRegionId(nodePOFromDbMap.get(nodePO.getKey()).getRegionId());\n                String machineSpec = nodePOFromDbMap.get(nodePO.getKey()).getMachineSpec();\n                if (StringUtils.isNotBlank(machineSpec)) {\n                    nodePO.setMachineSpec(machineSpec);\n                }\n                LOGGER.debug(\n                    \"class=RoleClusterHostServiceImpl||method=collectClusterNodeSettings||nodeName={}||id={}||msg=node has exist!\",\n                    nodePO.getNodeSet(), nodePO.getId());\n                shouldEdit.add(nodePO);\n            } else {\n                LOGGER.debug(\n                    \"class=RoleClusterHostServiceImpl||method=collectClusterNodeSettings||ip={}||msg=node is new!\",\n                    nodePO.getIp());\n                shouldAdd.add(nodePO);\n            }\n        }\n\n        return addAndEditNodes(cluster, shouldAdd, shouldEdit);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public boolean saveClusterNodeSettings(ClusterJoinDTO param) throws AdminTaskException {\n        if (null == param.getRoleClusterHosts()) {\n            return false;\n        }\n        List<ESClusterRoleHostPO> nodePOList = new ArrayList<>();\n        for (ESClusterRoleHostDTO node : param.getRoleClusterHosts()) {\n            ESClusterRoleHostPO roleClusterHostPO = buildEsClusterHostPO(node);\n            setRoleClusterId(roleClusterHostPO, param.getCluster());\n            roleClusterHostPO.setStatus(OFFLINE.getCode());\n            nodePOList.add(roleClusterHostPO);\n        }\n        return addAndEditNodes(param.getCluster(), nodePOList, null);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public boolean createClusterNodeSettings(List<ESClusterRoleHost> param,\n                                             String phyClusterName) throws AdminTaskException {\n        if (CollectionUtils.isEmpty(param) || StringUtils.isBlank(phyClusterName)) {\n            return false;\n        }\n\n        List<ESClusterRoleHostPO> nodePOList = new ArrayList<>();\n        param.stream().filter(esClusterRoleHost -> !AriusObjUtils.isNull(esClusterRoleHost.getHostname()))\n            .forEach(esClusterRoleHost -> nodePOList\n                .add(buildEsClusterHostPOFromEcmTaskOrder(esClusterRoleHost, phyClusterName)));\n\n        return addAndEditNodes(phyClusterName, nodePOList, null);\n    }\n\n    private ESClusterRoleHostPO buildEsClusterHostPOFromEcmTaskOrder(ESClusterRoleHost esClusterRoleHost,\n                                                                     String phyClusterName) {\n        ESClusterRoleHostPO roleClusterHostPO = ConvertUtil.obj2Obj(esClusterRoleHost, ESClusterRoleHostPO.class);\n        roleClusterHostPO.setHostname(roleClusterHostPO.getIp());\n        roleClusterHostPO.setCluster(phyClusterName);\n        roleClusterHostPO.setRole(ESClusterNodeRoleEnum.getByDesc(esClusterRoleHost.getRole()).getCode());\n        roleClusterHostPO.setStatus(2);\n        roleClusterHostPO.setNodeSet(\"\");\n        setRoleClusterId(roleClusterHostPO, phyClusterName);\n        return roleClusterHostPO;\n    }\n\n    @Override\n    public List<ClusterRoleHost> listOnlineNode() {\n        List<ESClusterRoleHostPO> pos = clusterRoleHostDAO.listOnlineNode();\n        return ConvertUtil.list2List(pos, ClusterRoleHost.class);\n    }\n\n    @Override\n    public Result<Long> save(ClusterRoleHost clusterRoleHost) {\n        ESClusterRoleHostPO esClusterRoleHostPO = ConvertUtil.obj2Obj(clusterRoleHost, ESClusterRoleHostPO.class);\n        boolean succ = (1 == clusterRoleHostDAO.insert(esClusterRoleHostPO));\n        return Result.build(succ, esClusterRoleHostPO.getId());\n    }\n\n    @Override\n    public ClusterRoleHost getById(Long id) {\n        return ConvertUtil.obj2Obj(clusterRoleHostDAO.getById(id), ClusterRoleHost.class);\n    }\n\n    @Override\n    public List<ClusterRoleHost> getByRoleClusterId(Long roleClusterId) {\n        List<ESClusterRoleHostPO> roleClusterPOS = clusterRoleHostDAO.listByRoleClusterId(roleClusterId);\n\n        if (null == roleClusterPOS) {\n            return Lists.newArrayList();\n        }\n        return ConvertUtil.list2List(roleClusterPOS, ClusterRoleHost.class);\n    }\n\n    @Override\n    public List<ClusterRoleHost> getByClusterAndNodeSets(String cluster, List<String> nodeSets) {\n        List<ESClusterRoleHostPO> roleHostPOS = clusterRoleHostDAO.listByClusterAndNodeSets(cluster, nodeSets);\n\n        if (null == roleHostPOS) {\n            return Lists.newArrayList();\n        }\n\n        return ConvertUtil.list2List(roleHostPOS, ClusterRoleHost.class);\n    }\n\n    @Override\n    public Map<Long, List<ClusterRoleHost>> getByRoleClusterIds(List<Long> roleClusterIds) {\n        if (CollectionUtils.isEmpty(roleClusterIds)) {\n            return new HashMap<>();\n        }\n        List<ESClusterRoleHostPO> roleClusterPOS = clusterRoleHostDAO.listByRoleClusterIds(roleClusterIds);\n        Map<Long, List<ClusterRoleHost>> ret = new HashMap<>();\n        if (CollectionUtils.isNotEmpty(roleClusterPOS)) {\n            List<ClusterRoleHost> list = ConvertUtil.list2List(roleClusterPOS, ClusterRoleHost.class);\n            ret = list.stream().collect(Collectors.groupingBy(ClusterRoleHost::getRoleClusterId));\n        }\n        return ret;\n    }\n\n    @Override\n    public List<String> getHostNamesByRoleAndClusterId(Long clusterId, String role) {\n        List<ClusterRoleHost> clusterRoleHosts = getByRoleAndClusterId(clusterId, role);\n        return clusterRoleHosts.stream().map(ClusterRoleHost::getHostname).collect(Collectors.toList());\n    }\n\n    @Override\n    public List<ClusterRoleHost> getByRoleAndClusterId(Long clusterId, String role) {\n        ClusterRoleInfo clusterRoleInfo = clusterRoleService.getByClusterIdAndRole(clusterId, role);\n        if (null == clusterRoleInfo) {\n            return Arrays.asList();\n        }\n        return ConvertUtil.list2List(clusterRoleHostDAO.listByRoleClusterId(clusterRoleInfo.getId()),\n            ClusterRoleHost.class);\n    }\n\n    @Override\n    public Result<Void> deleteByCluster(String cluster, Integer projectId) {\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return result;\n        }\n        boolean success = (clusterRoleHostDAO.deleteByCluster(cluster) > 0);\n        if (!success) {\n            return Result.buildFail(\"failed to delete the clusterHost\");\n        }\n        return Result.buildSuccWithMsg(\"success to delete the clusterHost\");\n    }\n\n    @Override\n    public List<ClusterRoleHost> listAllNode() {\n        List<ESClusterRoleHostPO> pos = clusterRoleHostDAO.listAll();\n        return ConvertUtil.list2List(pos, ClusterRoleHost.class);\n    }\n\n    @Override\n    public List<ClusterRoleHost> listAllNodeByRole(Integer roleCode) {\n        return ConvertUtil.list2List(clusterRoleHostDAO.listAllByRoleCode(roleCode), ClusterRoleHost.class);\n    }\n\n    @Override\n    public Result<Void> setHostValid(ClusterRoleHost deleteHost) {\n        boolean success = 1 == clusterRoleHostDAO.updateHostValid(deleteHost);\n        if (success) {\n            return Result.buildSucc();\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public ClusterRoleHost getDeleteHostByHostNameAnRoleId(String hostname, Long roleId) {\n        return ConvertUtil.obj2Obj(clusterRoleHostDAO.getDeleteHostByHostNameAnRoleId(hostname, roleId),\n            ClusterRoleHost.class);\n    }\n\n    @Override\n    public ClusterRoleHost getByHostName(String hostName) {\n        return ConvertUtil.obj2Obj(clusterRoleHostDAO.getByHostName(hostName), ClusterRoleHost.class);\n    }\n\n    @Override\n    public Result<Void> deleteById(Long id) {\n        boolean success = (1 == clusterRoleHostDAO.delete(id));\n        if (!success) {\n            return Result.buildFail(\"failed to delete the clusterHost\");\n        }\n        return Result.buildSuccWithMsg(\"success to delete the clusterHost\");\n    }\n\n    @Override\n    public Result deleteByHostNameAndRoleId(List<String> hostnames, Long roleId) {\n        boolean success = (hostnames.size() == clusterRoleHostDAO.deleteByHostNameAndRoleId(hostnames, roleId));\n        if (!success) {\n            LOGGER.error(\"class=RoleClusterHostServiceImpl||method=deleteByHostNameAndRoleId||hostname={}||roleId={}\"\n                         + \"msg=failed to delete roleClusterHost\",\n                hostnames, roleId);\n            return Result.buildFail(\"failed to delete the clusterHost\");\n        }\n        return Result.buildSuccWithMsg(\"success to delete the clusterHost\");\n    }\n\n    @Override\n    public String buildESClientHttpAddressesStr(List<ESClusterRoleHostDTO> roleClusterHosts) {\n        return ListUtils.strList2String(buildESClientMasterHttpAddressesList(roleClusterHosts));\n    }\n\n    @Override\n    public List<String> buildESClientMasterHttpAddressesList(List<ESClusterRoleHostDTO> roleClusterHosts) {\n        List<String> clientAddressesList = buildESRoleNodeHttpAddressesList(roleClusterHosts, CLIENT_NODE.getCode());\n        List<String> masterAddressesList = buildESRoleNodeHttpAddressesList(roleClusterHosts, MASTER_NODE.getCode());\n        return Stream.of(clientAddressesList, masterAddressesList).flatMap(Collection::stream)\n            .collect(Collectors.toList());\n    }\n\n    @Override\n    public List<String> buildESAllRoleHttpAddressesList(List<ESClusterRoleHostDTO> roleClusterHosts) {\n        List<String> dataAddressesList = buildESRoleNodeHttpAddressesList(roleClusterHosts, DATA_NODE.getCode());\n        return Stream.of(dataAddressesList, buildESClientMasterHttpAddressesList(roleClusterHosts))\n            .flatMap(Collection::stream).collect(Collectors.toList());\n    }\n\n    @Override\n    public int getPodNumberByRoleId(Long roleId) {\n        return clusterRoleHostDAO.getPodNumberByRoleId(roleId);\n    }\n\n    @Override\n    public Result<List<ClusterRoleHost>> listByRegionId(Integer regionId) {\n        List<ESClusterRoleHostPO> esClusterRoleHostPOS;\n        try {\n            esClusterRoleHostPOS = clusterRoleHostDAO.listByRegionId(regionId);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ClusterRoleHostServiceImpl||method=listByRegionId||errMsg={}\", e.getMessage(), e);\n            return Result.buildFail(String.format(\"根据regionId[%d]获取节点信息失败\", regionId));\n        }\n        return Result.buildSucc(ConvertUtil.list2List(esClusterRoleHostPOS, ClusterRoleHost.class));\n    }\n    \n    /**\n     * 它返回 ClusterRoleHost 对象的列表。\n     *\n     * @param ids 要查询的 id 列表。\n     * @return 列表<ClusterRoleHost>\n     */\n    @Override\n    public List<ClusterRoleHost> listById(List<Integer> ids) {\n        return ConvertUtil.list2List(clusterRoleHostDAO.listByIds(ids),ClusterRoleHost.class);\n    }\n\n    @Override\n    public List<ClusterRoleHost> listNodesByClusters(List<String> phyClusterNames) {\n        List<ESClusterRoleHostPO> pos = clusterRoleHostDAO.listByClusters(phyClusterNames);\n        return ConvertUtil.list2List(pos,ClusterRoleHost.class);\n    }\n\n    /**\n     * @param ids\n     * @return\n     */\n    @Override\n    public boolean deleteByIds(List<Integer> ids) {\n        \n        return clusterRoleHostDAO.deleteByIds(ids)==ids.size();\n    }\n    \n    /***************************************** private method ****************************************************/\n    private Result<Void> checkNodeParam(ESClusterRoleHostDTO param, OperationEnum operation) {\n        if (AriusObjUtils.isNull(param)) {\n            return Result.buildParamIllegal(\"节点信息为空\");\n        }\n\n        if (OperationEnum.ADD.equals(operation)) {\n            Result<Void> isNullResult = isNull(param);\n            if (isNullResult.failed()) {\n                return isNullResult;\n            }\n        } else if (OperationEnum.EDIT.equals(operation)) {\n            ESClusterRoleHostPO oldClusterHostPo = clusterRoleHostDAO.getById(param.getId());\n            if (oldClusterHostPo == null) {\n                return Result.buildNotExist(\"节点不存在\");\n            }\n        }\n\n        Result<Void> isIllegalResult = isIllegal(param);\n        if (isIllegalResult.failed()) {\n            return isIllegalResult;\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> isIllegal(ESClusterRoleHostDTO param) {\n        if (param.getRole() != null\n            && ESClusterNodeRoleEnum.UNKNOWN == ESClusterNodeRoleEnum.valueOf(param.getRole())) {\n            return Result.buildParamIllegal(\"节点角色非法\");\n        }\n\n        if (param.getStatus() != null\n            && ESClusterNodeStatusEnum.UNKNOWN == ESClusterNodeStatusEnum.valueOf(param.getStatus())) {\n            return Result.buildParamIllegal(\"节点状态非法\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> isNull(ESClusterRoleHostDTO param) {\n        if (AriusObjUtils.isNull(param.getHostname())) {\n            return Result.buildParamIllegal(\"节点名字为空\");\n        }\n        if (AriusObjUtils.isNull(param.getCluster())) {\n            return Result.buildParamIllegal(\"集群为空\");\n        }\n        if (AriusObjUtils.isNull(param.getIp())) {\n            return Result.buildParamIllegal(\"IP地址为空\");\n        }\n        if (AriusObjUtils.isNullStr(param.getPort())) {\n            return Result.buildParamIllegal(\"节点端口为空\");\n        }\n        if (AriusObjUtils.isNull(param.getRole())) {\n            return Result.buildParamIllegal(\"节点角色为空\");\n        }\n        if (AriusObjUtils.isNull(param.getStatus())) {\n            return Result.buildParamIllegal(\"节点状态为空\");\n        }\n        if (AriusObjUtils.isNullStr(param.getNodeSet())) {\n            return Result.buildParamIllegal(\"节点set为空\");\n        }\n        return Result.buildSucc();\n    }\n\n    private boolean addNodeBatch(List<ESClusterRoleHostPO> nodePOs) {\n        // 数据修改的行数成功数\n        int count = 0;\n        for (ESClusterRoleHostPO param : nodePOs) {\n            if (null != clusterRoleHostDAO.getDeleteHostByHostNameAnRoleId(param.getHostname(),\n                param.getRoleClusterId())) {\n                count += clusterRoleHostDAO.restoreByHostNameAndRoleId(param.getHostname(), param.getRoleClusterId());\n                continue;\n            }\n            count += clusterRoleHostDAO.insert(param);\n        }\n        return CollectionUtils.isEmpty(nodePOs) || nodePOs.size() == count;\n    }\n\n    private boolean editNodeBatch(List<ESClusterRoleHostPO> nodePOs) {\n        if (CollectionUtils.isEmpty(nodePOs)) {\n            return true;\n        }\n\n        boolean succ = true;\n        for (ESClusterRoleHostPO nodePO : nodePOs) {\n            succ &= editNode(ConvertUtil.obj2Obj(nodePO, ESClusterRoleHostDTO.class)).success();\n        }\n\n        return succ;\n    }\n\n    /**\n     * 获取集群内节点配置\n     * @param cluster 集群名称\n     * @return EsClusterNodePO列表\n     */\n    private List<ESClusterRoleHostPO> getClusterHostFromEsAndCreateRoleClusterIfNotExist(String cluster) throws ESOperateException {\n        List<ESClusterRoleHostPO> nodePOList = Lists.newArrayList();\n\n        // 从ES集群中获取初始的节点信息列表\n        List<ClusterNodeInfo> clusterNodeInfos = buildAllClusterNodeInfoFromES(cluster);\n        Map<String, String> node2machineSpecMap = buildESClusterNodeMachineSpecMap(cluster);\n\n        // 根据集群节点角色信息构建入DB的host列表信息\n        for (ClusterNodeInfo nodeInfoListFromArius : clusterNodeInfos) {\n            // 构造节点记录数据\n            ESClusterRoleHostPO roleClusterHostPO = buildEsClusterHostPO(nodeInfoListFromArius, node2machineSpecMap,\n                cluster);\n            // 节点所属的角色记录如果不存在，则去设置\n            setRoleClusterId(roleClusterHostPO, cluster);\n\n            nodePOList.add(roleClusterHostPO);\n        }\n\n        return nodePOList;\n    }\n\n    private Map<String, String> buildESClusterNodeMachineSpecMap(String cluster) throws ESOperateException {\n        Map<String, String> node2machineSpecMap = Maps.newHashMap();\n        Map<String, Integer> node2CpuNum = esClusterNodeService.syncGetNodesCpuNum(cluster);\n        Map<String, Tuple<Long, Long>> node2MemAndDisk = esClusterNodeService.syncGetNodesMemoryAndDisk(cluster);\n        Set<String> nodes = Sets.intersection(node2CpuNum.keySet(), node2MemAndDisk.keySet());\n        if (CollectionUtils.isNotEmpty(nodes)) {\n            nodes.forEach(node -> {\n                Integer cpuNum = node2CpuNum.get(node);\n                Tuple<Long, Long> memAndDisk = node2MemAndDisk.get(node);\n                Long memoryBytes = memAndDisk.getV1();\n                Long diskBytes = memAndDisk.getV2();\n                if (null != cpuNum && null != memoryBytes && null != diskBytes) {\n                    node2machineSpecMap.put(node, SizeUtil.getMachineSpec(cpuNum, memoryBytes, diskBytes));\n                }\n            });\n        }\n\n        return node2machineSpecMap;\n    }\n\n    /**\n     * 从es中获取全部的集群节点信息，尤其包括节点角色的初始化操作\n     * @param cluster 集群名称\n     * @return\n     */\n    private List<ClusterNodeInfo> buildAllClusterNodeInfoFromES(String cluster) throws ESOperateException {\n        List<ClusterNodeInfo> clusterNodeInfoListFromES = Lists.newArrayList();\n\n        // 从ES集群获取节点全量的信息\n        Map<String, ClusterNodeInfo> clusterNodeInfoMap = esClusterService.syncGetAllSettingsByCluster(cluster);\n        if (MapUtils.isEmpty(clusterNodeInfoMap)) {\n            return Collections.emptyList();\n        }\n        // 获取高低版本通用的节点角色信息\n        Map<String, ClusterNodeSettings> clusterNodeSettingsMap = esClusterService\n            .syncGetPartOfSettingsByCluster(cluster);\n        if (MapUtils.isEmpty(clusterNodeSettingsMap)) {\n            return Collections.emptyList();\n        }\n\n        if (MapUtils.isEmpty(clusterNodeSettingsMap) || MapUtils.isEmpty(clusterNodeInfoMap)) {\n            return clusterNodeInfoListFromES;\n        }\n\n        // 构建原生集群节点信息列表\n        for (Map.Entry</*UUID*/String, ClusterNodeInfo> entry : clusterNodeInfoMap.entrySet()) {\n            if (!clusterNodeSettingsMap.containsKey(entry.getKey())) {\n                continue;\n            }\n            // 为纳管2.3.3版本的角色信息，需要从_nodes/settings中获取\n            ClusterNodeInfo clusterNodeInfo = entry.getValue();\n            // 根据节点的UUID获取对应的全量的角色信息\n\n            ClusterNodeSettings clusterNodeSettings = clusterNodeSettingsMap.get(entry.getKey());\n            // 重新设置clusterNodeInfo的roles列表\n            clusterNodeInfo.setRoles(buildRolesInfoFromSettings(clusterNodeSettings));\n            // 构建节点角色的多角色信息\n            buildMultiRoleListForESNode(clusterNodeInfoListFromES, clusterNodeInfo);\n        }\n\n        return CollectionUtils.isEmpty(clusterNodeInfoListFromES) ? Lists.newArrayList(clusterNodeInfoMap.values())\n            : clusterNodeInfoListFromES;\n    }\n\n    /**\n     * 构建节点的多角色信息列表\n     * @param clusterNodeInfoListFromES 节点信息列表\n     * @param clusterNodeInfo 节点信息对象\n     */\n    private void buildMultiRoleListForESNode(List<ClusterNodeInfo> clusterNodeInfoListFromES,\n                                             ClusterNodeInfo clusterNodeInfo) {\n        // 根据当前角色列表添加节点角色信息\n        List<String> roles = clusterNodeInfo.getRoles();\n        if (notHasRoleOfMasterAndData(roles)) {\n            //该节点既不含有data角色也不含有master角色，则添加client角色\n            roles.add(ES_ROLE_CLIENT);\n        }\n\n        //根据es获取的节点信息构建节点角色信息\n        addNodeRoleInfoFromES(clusterNodeInfoListFromES, clusterNodeInfo, roles);\n    }\n\n    private List<String> buildRolesInfoFromSettings(ClusterNodeSettings clusterNodeSetting) {\n        List<String> roles = JSONArray.parseArray(JSON.toJSONString(clusterNodeSetting.getRoles()), String.class);\n        if (CollectionUtils.isEmpty(roles)) {\n            JSONObject roleNode = clusterNodeSetting.getSettings().getJSONObject(\"node\");\n            List<String> roleInfo = Lists.newArrayList();\n            if (AriusObjUtils.isNull(roleNode)) {\n                roleInfo.add(ES_ROLE_DATA);\n                roleInfo.add(ES_ROLE_MASTER);\n            } else {\n                for (String role : ESClusterNodeRoleEnum.nodeRoleList()) {\n                    if (role.equalsIgnoreCase(ES_ROLE_CLIENT)) {\n                        continue;\n                    }\n                    if (!roleNode.containsKey(role) || roleNode.getBoolean(role)) {\n                        roleInfo.add(role);\n                    }\n                }\n            }\n\n            return roleInfo;\n        }\n\n        return roles;\n    }\n\n    private void addNodeRoleInfoFromES(List<ClusterNodeInfo> clusterNodeInfoListFromArius,\n                                       ClusterNodeInfo clusterNodeInfo, List<String> roles) {\n        for (String role : roles) {\n            //对于节点的角色进行过滤，平台只兼容data,master和client三种角色类型\n            if (!ESClusterNodeRoleEnum.getByDesc(role + \"node\").equals(UNKNOWN)) {\n                ClusterNodeInfo nodeInfo = ConvertUtil.obj2Obj(clusterNodeInfo, ClusterNodeInfo.class);\n                nodeInfo.setRoles(Lists.newArrayList(role));\n                clusterNodeInfoListFromArius.add(nodeInfo);\n            }\n        }\n    }\n\n    private boolean notHasRoleOfMasterAndData(List<String> roles) {\n        return !roles.contains(ES_ROLE_DATA) && !roles.contains(ES_ROLE_MASTER);\n    }\n\n    private ESClusterRoleHostPO buildEsClusterHostPO(ClusterNodeInfo clusterNodeInfo,\n                                                     Map<String, String> node2machineSpecMap, String cluster) {\n        ESClusterRoleHostPO nodePO = new ESClusterRoleHostPO();\n        nodePO.setCluster(cluster);\n\n        nodePO.setIp(Getter.withDefault(clusterNodeInfo.getIp(), \"\"));\n        nodePO.setHostname(Getter.withDefault(clusterNodeInfo.getHost(), \"\"));\n        nodePO.setNodeSet(Getter.withDefault(clusterNodeInfo.getName(), \"\"));\n        Optional.ofNullable(clusterNodeInfo.getAttributes()).map(ConvertUtil::map2String)\n            .ifPresent(nodePO::setAttributes);\n\n        HttpInfo httpInfo = clusterNodeInfo.getHttpInfo();\n        if (null != httpInfo && null != httpInfo.getPublishAddress()) {\n            String[] split = httpInfo.getPublishAddress().split(\":\");\n            nodePO.setPort(split[split.length - 1]);\n        } else {\n            nodePO.setPort(\"\");\n        }\n        nodePO.setMachineSpec(node2machineSpecMap.get(nodePO.getNodeSet()));\n\n        nodePO.setStatus(ONLINE.getCode());\n        nodePO.setRegionId(-1);\n        nodePO.setRole(getRoleFromNodeSettings(clusterNodeInfo));\n\n        return nodePO;\n    }\n\n    private ESClusterRoleHostPO buildEsClusterHostPO(ESClusterRoleHostDTO nodeDTO) {\n        ESClusterRoleHostPO nodePO = ConvertUtil.obj2Obj(nodeDTO, ESClusterRoleHostPO.class);\n        nodePO.setHostname(Getter.withDefault(nodeDTO.getIp(), \"\"));\n        return nodePO;\n    }\n\n    /**\n     * 设置节点所属的角色记录ID\n     * @param roleClusterHostPO  节点记录\n     * @param cluster            物理集群名\n     * @return\n     */\n    private void setRoleClusterId(ESClusterRoleHostPO roleClusterHostPO, String cluster) {\n        ESClusterNodeRoleEnum role = ESClusterNodeRoleEnum.valueOf(roleClusterHostPO.getRole());\n        ClusterRoleInfo clusterRoleInfo = clusterRoleService.createRoleClusterIfNotExist(cluster, role.getDesc());\n        roleClusterHostPO.setRoleClusterId(clusterRoleInfo.getId());\n    }\n\n    private Map<String/*roleClusterId@esNodeName*/ , ESClusterRoleHostPO> getNodeInfoFromDbMap(String cluster) {\n        List<ESClusterRoleHostPO> nodesFromDB = clusterRoleHostDAO.listByCluster(cluster);\n\n        LOGGER.info(\"class=RoleClusterHostServiceImpl||method=getNodeInfoFromDbMap||cluster={}||dbSize={}\", cluster,\n            nodesFromDB.size());\n\n        return ConvertUtil.list2Map(nodesFromDB, ESClusterRoleHostPO::getKey);\n    }\n\n    /**\n     * 从节点设置获取节点角色，注意一个节点可能会有多种角色，取角色的优先级为：data->master->client\n     * @param clusterNodeInfo 节点设置\n     * @return\n     */\n    private Integer getRoleFromNodeSettings(ClusterNodeInfo clusterNodeInfo) {\n        // 高版本\n        List<String> roles = clusterNodeInfo.getRoles();\n        if (roles != null && !roles.isEmpty()) {\n            if (roles.contains(ES_ROLE_DATA)) {\n                return DATA_NODE.getCode();\n            }\n            if (roles.contains(ES_ROLE_MASTER)) {\n                return MASTER_NODE.getCode();\n            }\n        }\n\n        return CLIENT_NODE.getCode();\n    }\n\n    private boolean updateRolePod(List<ESClusterRoleHostPO> shouldAdd, String cluster) {\n        if (CollectionUtils.isEmpty(shouldAdd)) {\n            return true;\n        }\n\n        Map<Integer, List<ESClusterRoleHostPO>> role2ESRoleClusterHostPOListMap = ConvertUtil.list2MapOfList(shouldAdd,\n            ESClusterRoleHostPO::getRole, esClusterRoleHostPO -> esClusterRoleHostPO);\n\n        AtomicBoolean flag = new AtomicBoolean(true);\n        role2ESRoleClusterHostPOListMap.forEach((role, roleClusterHostPOList) -> {\n            ClusterRoleInfo clusterRoleInfo = clusterRoleService.getByClusterNameAndRole(cluster,\n                valueOf(role).getDesc());\n            clusterRoleInfo.setPodNumber(clusterRoleHostDAO.getPodNumberByRoleId(clusterRoleInfo.getId()));\n            Result<Void> result = clusterRoleService.updatePodByClusterIdAndRole(clusterRoleInfo);\n            if (result.failed()) {\n                flag.set(false);\n            }\n        });\n\n        return flag.get();\n    }\n\n    private boolean addAndEditNodes(String cluster, List<ESClusterRoleHostPO> shouldAdd,\n                                    List<ESClusterRoleHostPO> shouldEdit) throws AdminTaskException {\n        clusterRoleHostDAO.offlineByCluster(cluster);\n        boolean flag = addNodeBatch(shouldAdd);\n        if (flag) {\n            if (!updateRolePod(shouldAdd, cluster)) {\n                throw new AdminTaskException(\"更新新增节点数量失败\");\n            }\n        } else {\n            LOGGER.error(\n                \"class=RoleClusterHostServiceImpl||method=collectClusterNodeSettings||clusterPhyName={}||addNode={}\"\n                         + \"||errMag=fail to add cluster node to arius\",\n                cluster, shouldAdd);\n        }\n        if (!editNodeBatch(shouldEdit)) {\n            LOGGER.error(\n                \"class=RoleClusterHostServiceImpl||method=collectClusterNodeSettings||clusterPhyName={}||addNode={}\"\n                         + \"||errMag=fail to edit cluster node to arius\",\n                cluster, shouldEdit);\n        }\n        return true;\n    }\n\n    private List<String> buildESRoleNodeHttpAddressesList(List<ESClusterRoleHostDTO> roleClusterHosts,\n                                                          Integer roleCode) {\n        Map<Integer, List<ESClusterRoleHostDTO>> role2ESRoleClusterHostDTOMap = ConvertUtil.list2MapOfList(\n            roleClusterHosts, ESClusterRoleHostDTO::getRole, esRoleClusterHostDTO -> esRoleClusterHostDTO);\n\n        List<String> httpAddressesList = Lists.newArrayList();\n        List<ESClusterRoleHostDTO> esClusterRoleHostDTOS = role2ESRoleClusterHostDTOMap.get(roleCode);\n        if (null != esClusterRoleHostDTOS) {\n            esClusterRoleHostDTOS.forEach(host -> httpAddressesList.add(host.getIp() + \":\" + host.getPort()));\n        }\n        return httpAddressesList;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/physic/impl/ClusterRoleServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.impl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRolePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESClusterRoleDAO;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * ES集群对应角色集群 服务实现类\n *\n * @author didi\n * @since 2020-08-24\n */\n@Service\npublic class ClusterRoleServiceImpl implements ClusterRoleService {\n\n    @Autowired\n    private ESClusterRoleDAO  roleClusterDAO;\n\n    @Autowired\n    private ClusterPhyService clusterPhyService;\n\n    @Override\n    public Result<Void> save(ESClusterRoleDTO esClusterRoleDTO) {\n        ESClusterRolePO esClusterRolePO = ConvertUtil.obj2Obj(esClusterRoleDTO, ESClusterRolePO.class);\n        boolean succ = (1 == roleClusterDAO.insert(esClusterRolePO));\n        if (succ) {\n            esClusterRoleDTO.setId(esClusterRolePO.getId());\n        }\n\n        return Result.build(succ);\n    }\n\n    @Override\n    public ClusterRoleInfo createRoleClusterIfNotExist(String clusterName, String role) {\n\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterName);\n\n        ESClusterRolePO roleClusterPO = roleClusterDAO.getByClusterIdAndRole(clusterPhy.getId().longValue(), role);\n        if (roleClusterPO == null) {\n            roleClusterPO = new ESClusterRolePO();\n            roleClusterPO.setElasticClusterId(clusterPhy.getId().longValue());\n            roleClusterPO.setRoleClusterName(clusterName + \"-\" + role);\n            roleClusterPO.setRole(role);\n            roleClusterPO.setPodNumber(0);\n            roleClusterPO.setPidCount(1);\n            roleClusterPO.setMachineSpec(\"\");\n            roleClusterPO.setEsVersion(clusterPhy.getEsVersion());\n            roleClusterPO.setCfgId(ClusterConstant.INVALID_VALUE.intValue());\n            roleClusterDAO.insert(roleClusterPO);\n        }\n\n        return ConvertUtil.obj2Obj(roleClusterPO, ClusterRoleInfo.class);\n    }\n\n    @Override\n    public List<ClusterRoleInfo> getAllRoleClusterByClusterId(Integer clusterId) {\n        List<ESClusterRolePO> roleClusterPos = roleClusterDAO.listByClusterId(clusterId.toString());\n        return ConvertUtil.list2List(roleClusterPos, ClusterRoleInfo.class);\n    }\n\n    @Override\n    public Map<Long, List<ClusterRoleInfo>> getAllRoleClusterByClusterIds(List<Integer> clusterIds) {\n        List<String> clusterStrIds = clusterIds.stream().map(i -> String.valueOf(i)).collect(Collectors.toList());\n        List<ESClusterRolePO> roleClusterPos = roleClusterDAO.listByClusterIds(clusterStrIds);\n\n        Map<Long, List<ClusterRoleInfo>> ret = new HashMap<>();\n\n        if (CollectionUtils.isNotEmpty(roleClusterPos)) {\n            List<ClusterRoleInfo> list = ConvertUtil.list2List(roleClusterPos, ClusterRoleInfo.class);\n            ret = list.stream().collect(Collectors.groupingBy(ClusterRoleInfo::getElasticClusterId));\n        }\n\n        return ret;\n    }\n\n    @Override\n    public ClusterRoleInfo getByClusterIdAndClusterRole(Long clusterId, String roleClusterName) {\n        return ConvertUtil.obj2Obj(roleClusterDAO.getByClusterIdAndClusterRole(clusterId, roleClusterName),\n            ClusterRoleInfo.class);\n    }\n\n    @Override\n    public ClusterRoleInfo getByClusterIdAndRole(Long clusterId, String role) {\n        return ConvertUtil.obj2Obj(roleClusterDAO.getByClusterIdAndRole(clusterId, role), ClusterRoleInfo.class);\n    }\n\n    @Override\n    public ClusterRoleInfo getByClusterNameAndRole(String clusterName, String role) {\n        ClusterPhy clusterPhy = clusterPhyService.getClusterByName(clusterName);\n\n        return clusterPhy == null ? null : getByClusterIdAndRole(clusterPhy.getId().longValue(), role);\n    }\n\n    @Override\n    public Result<Void> updatePodByClusterIdAndRole(ClusterRoleInfo clusterRoleInfo) {\n        ESClusterRolePO esClusterRolePo = ConvertUtil.obj2Obj(clusterRoleInfo, ESClusterRolePO.class);\n        boolean succ = (roleClusterDAO.update(esClusterRolePo) != 0);\n\n        return Result.build(succ);\n    }\n\n    @Override\n    public Result<Void> updateVersionByClusterIdAndRole(Long clusterId, String role, String version) {\n        boolean succ = (1 == roleClusterDAO.updateVersionByClusterIdAndRole(clusterId, role, version));\n\n        return Result.build(succ);\n    }\n\n    @Override\n    public Result<Void> deleteRoleClusterByClusterId(Integer clusterId, Integer projectId) {\n        //校验操作项目的合法性\n        final Result<Void> result = ProjectUtils.checkProjectCorrectly(i -> i, projectId, projectId);\n        if (result.failed()) {\n            return result;\n        }\n        //在接入集群阶段可能会存在角色表未插入的脏数据，直接用>0判断可能导致结果不准确\n        final int countByClusterId = roleClusterDAO.countByClusterId(clusterId);\n        if (countByClusterId>0){\n            return Result.build(roleClusterDAO.delete(clusterId) >0);\n        }\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/region/ClusterRegionService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.region;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegionConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegionFSInfo;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-30\n */\npublic interface ClusterRegionService {\n    /**\n     * 获取region\n     * @param regionId regionId\n     */\n    ClusterRegion getRegionById(Long regionId);\n\n\n\n    ClusterRegion getRegionByLogicClusterId(Long logicClusterId);\n\n    /**\n     * 获取物理集群下的region\n     * @param phyClusterName 物理集群名\n     * @return 物理集群下的region\n     */\n    List<ClusterRegion> listRegionsByClusterName(String phyClusterName);\n\n    /**\n     * 根据逻辑集群ID获取物理集群名称列表（获取逻辑集群拥有资源的物理集群）\n     * @param logicClusterId 逻辑集群ID\n     * @return 逻辑集群被分配到的物理集群的集群名list\n     */\n    List<String> listPhysicClusterNames(Long logicClusterId);\n\n    /**\n     * 根据逻辑集群ID获取物理集群Id列表\n     * @param logicClusterId 逻辑集群ID\n     * @return 逻辑集群被分配到的物理集群的集群ID list\n     */\n    List<Integer> listPhysicClusterId(Long logicClusterId);\n\n    /**\n     * 获取指定物理集群下的region\n     * @param clusterName 物理集群名\n     * @return 物理集群clusterName下的region\n     */\n    List<ClusterRegion> listPhyClusterRegions(String clusterName);\n\n    /**\n     * 获取所有已经被绑定到逻辑集群的region\n     * @return 所有已经被绑定到逻辑集群的region\n     */\n    List<ClusterRegion> listAllBoundRegions();\n\n    /**\n     * 创建物理集群region\n     * @param clusterRegionDTO  region信息\n     * @param operator          操作人\n     * @return                  regionId\n     */\n    Result<Long> createPhyClusterRegion(ClusterRegionDTO clusterRegionDTO, String operator);\n\n    /**\n     * 删除物理集群region\n     *\n     * @param regionId regionId\n     * @param operator 操作人\n     * @return\n     */\n    Result<Void> deletePhyClusterRegion(Long regionId, String operator);\n\n    /**\n     * 批量删除物理集群中region\n     * @param clusterPhyName 物理集群名称\n     * @return\n     */\n    Result<Void> deleteByClusterPhy(String clusterPhyName);\n\n    /**\n     * 解绑region\n     *\n     * @param regionId       regionId\n     * @param logicClusterId 逻辑集群id\n     * @param operator       operator\n     * @return\n     */\n    Result<Void> unbindRegion(Long regionId, Long logicClusterId, String operator);\n\n    /**\n     * 绑定region到逻辑集群\n     * @param regionId       regionId\n     * @param logicClusterId 逻辑集群ID\n     * @param share          share\n     * @param operator       操作人\n     * @return\n     */\n    Result<Void> bindRegion(Long regionId, Long logicClusterId, Integer share, String operator);\n\n    /**\n     * 判断region是否已经被绑定给逻辑集群\n     * @param region region\n     * @return true-已经被绑定，false-没有被绑定\n     */\n    boolean isRegionBound(ClusterRegion region);\n\n    /**\n     * 判断region是否还可以被某个逻辑集群绑定\n     * @param region  ClusterRegion\n     * @param clusterLogicType 逻辑集群类型\n     * @return true-可以被绑定，false-不能被绑定\n     */\n    boolean isRegionCanBeBound(ClusterRegion region,Integer clusterLogicType);\n\n    /**\n     * 根据物理集群id，获取该物理集群对应的逻辑集群的id列表\n     * @param phyClusterId 物理集群id\n     * @return 逻辑集群id列表\n     */\n    Set<Long> getLogicClusterIdByPhyClusterId(Integer phyClusterId);\n\n    /**\n     * 根据名称判断region是否存在\n     * @param regionName region名称\n     * @return   false or true\n     */\n    boolean isExistByRegionName(String regionName);\n\n    /**\n     * 根据regionId判断region是否存在\n     * @param regionId  regionId\n     * @return          false or true\n     */\n    boolean isExistByRegionId(Integer regionId);\n\n    /**\n     * 获取指定物理集群下的冷节点\n     * @param cluster\n     * @return\n     */\n    List<ClusterRegion> listColdRegionByCluster(String cluster);\n\n    /**\n     * 获取region 配置项\n     * @param config\n     * @return\n     */\n    ClusterRegionConfig genClusterRegionConfig(String config);\n\n    /**\n     * 获取region 磁盘使用情况\n     * @param cluster\n     * @return (key, value) = (regionId, diskUsage)\n     */\n    Map<Integer, ClusterRegionFSInfo> getClusterRegionFSInfo(String cluster);\n\n    /**\n     * 根据逻辑集群Id列表获取region列表, 注意这里入参列表元素不能太大，否则有性能影响\n     * @param clusterLogicIdList  逻辑集群id列表\n     * @return\n     */\n    List<ClusterRegion> getClusterRegionsByLogicIds(List<Long> clusterLogicIdList);\n\n    /**\n     * 根据物理集群名称批量查询region\n     *\n     * @param phyClusterNames 物理集群名称\n     * @return {@link List}<{@link ClusterRegion}>\n     */\n    List<ClusterRegion> listRegionByPhyClusterNames(List<String> phyClusterNames);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/region/impl/ClusterRegionServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.region.impl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegionConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegionFSInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterRegionPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.region.RegionUnbindEvent;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.region.ClusterRegionDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.fs.FSTotal;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Multimap;\nimport com.google.common.collect.Sets;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-30\n */\n@Service\npublic class ClusterRegionServiceImpl implements ClusterRegionService {\n    private static final ILog       LOGGER           = LogFactory.getLog(ClusterRegionServiceImpl.class);\n\n    private static final String     REGION_NOT_EXIST = \"region %d 不存在\";\n\n    @Autowired\n    private ClusterRegionDAO        clusterRegionDAO;\n\n    @Autowired\n    private ClusterLogicService     clusterLogicService;\n\n    @Autowired\n    private ClusterPhyService       esClusterPhyService;\n\n    @Autowired\n    private OperateRecordService    operateRecordService;\n\n    @Autowired\n    private IndexTemplatePhyService indexTemplatePhyService;\n\n    @Autowired\n    private ClusterRoleHostService  clusterRoleHostService;\n\n    @Autowired\n    private ESClusterNodeService    esClusterNodeService;\n    @Autowired\n    private ProjectService          projectService;\n\n    @Override\n    public ClusterRegion getRegionById(Long regionId) {\n        if (regionId == null) {\n            return null;\n        }\n        return ConvertUtil.obj2Obj(clusterRegionDAO.getById(regionId), ClusterRegion.class);\n    }\n\n    @Override\n    public List<String> listPhysicClusterNames(Long logicClusterId) {\n        // 获取逻辑集群有的region\n        List<ClusterRegion> regions = getClusterRegionsByLogicIds(Collections.singletonList(logicClusterId));\n        // 从region获取物理集群名\n        return regions.stream().map(ClusterRegion::getPhyClusterName).distinct().collect(Collectors.toList());\n    }\n\n    @Override\n    public List<Integer> listPhysicClusterId(Long logicClusterId) {\n        List<String> clusterNames = listPhysicClusterNames(logicClusterId);\n        // 从物理集群名获取物理集群ID\n        return clusterNames.stream().map(clusterName -> esClusterPhyService.getClusterByName(clusterName).getId())\n            .collect(Collectors.toList());\n    }\n\n    @Override\n    public List<ClusterRegion> listPhyClusterRegions(String phyClusterName) {\n        return ConvertUtil.list2List(clusterRegionDAO.getByPhyClusterName(phyClusterName), ClusterRegion.class);\n    }\n\n    @Override\n    public List<ClusterRegion> listRegionByPhyClusterNames(List<String> phyClusterNames) {\n        if (CollectionUtils.isNotEmpty(phyClusterNames)) {\n            return ConvertUtil.list2List(clusterRegionDAO.listByPhyClusterNames(phyClusterNames), ClusterRegion.class);\n        }\n        return Lists.newArrayList();\n    }\n\n    @Override\n    public List<ClusterRegion> listAllBoundRegions() {\n        return ConvertUtil.list2List(clusterRegionDAO.listBoundRegions(), ClusterRegion.class);\n    }\n\n    @Override\n    public Result<Long> createPhyClusterRegion(ClusterRegionDTO clusterRegionDTO, String operator) {\n        ClusterRegionPO clusterRegionPO = ConvertUtil.obj2Obj(clusterRegionDTO, ClusterRegionPO.class);\n        clusterRegionPO.setLogicClusterIds(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID);\n        return Result.build(1 == clusterRegionDAO.insert(clusterRegionPO), clusterRegionPO.getId());\n    }\n\n    @Override\n    public Result<Void> deletePhyClusterRegion(Long regionId, String operator) {\n        if (regionId == null) {\n            return Result.buildFail(\"regionId不能为null\");\n        }\n\n        ClusterRegion region = getRegionById(regionId);\n        if (region == null) {\n            return Result.buildFail(String.format(REGION_NOT_EXIST, regionId));\n        }\n        // 已经绑定过的region不能删除\n        if (isRegionBound(region)) {\n            // 获取逻辑集群的信息,一个region可能被多个逻辑集群绑定\n            List<Long> logicClusterIds = ListUtils.string2LongList(region.getLogicClusterIds());\n            List<String> logicClusterNames = Lists.newArrayList();\n            for (Long logicClusterId : logicClusterIds) {\n                ClusterLogic clusterLogic =\n                        clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(logicClusterId );\n                if (AriusObjUtils.isNull(clusterLogic)) {\n                    continue;\n                }\n                // 获取被绑定的全部逻辑集群的名称\n                logicClusterNames.add(clusterLogic.getName());\n            }\n            return Result.buildFail(\n                String.format(\"region [%d] 已经被绑定到逻辑集群 [%s]\", regionId, ListUtils.strList2String(logicClusterNames)));\n        }\n\n        return Result.build(clusterRegionDAO.delete(regionId) == 1);\n    }\n\n    @Override\n    public Result<Void> deleteByClusterPhy(String clusterPhyName) {\n        return Result.build(0 < clusterRegionDAO.deleteByClusterPhyName(clusterPhyName));\n    }\n\n    @Override\n    public Result<Void> bindRegion(Long regionId, Long logicClusterId, Integer share, String operator) {\n\n        try {\n            // 判断region存在\n            ClusterRegion region = getRegionById(regionId);\n            if (region == null) {\n                return Result.buildFail(String.format(REGION_NOT_EXIST, regionId));\n            }\n\n            // 检查逻辑集群存在\n            ClusterLogic clusterLogic =\n                    clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(logicClusterId );\n            if (AriusObjUtils.isNull(clusterLogic)) {\n                return Result.buildFail(String.format(\"逻辑集群 %S 不存在\", logicClusterId));\n            }\n\n            // 判断在未绑定状态,获取region被绑定的逻辑集群的类型，只有被共享逻辑集群绑定的region才能被另一个共享逻辑集群重复绑定\n            if (isRegionBound(region)) {\n                if (!isRegionBindByPublicLogicCluster(region)) {\n                    return Result.buildFail(\n                            String.format(\"regionId %d,regionName %s 已经被非共享逻辑集群绑定\", regionId,\n                                    region.getName()));\n                }\n\n                if (!clusterLogic.getType().equals(ClusterResourceTypeEnum.PUBLIC.getCode())) {\n                    return Result\n                        .buildFail(String.format(\"region %d 已经被绑定,并且逻辑集群 %s 不是共享集群\", regionId, clusterLogic.getName()));\n                }\n            }\n\n            if (share == null) {\n                share = AdminConstant.YES;\n            }\n\n            if (!share.equals(AdminConstant.YES) && !share.equals(AdminConstant.NO)) {\n                return Result.buildParamIllegal(\"指定的share非法\");\n            }\n\n            // 绑定\n            updateRegion(regionId, constructNewLogicIds(logicClusterId, region.getLogicClusterIds()));\n\n            return Result.buildSucc();\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=RegionRackServiceImpl||method=bindRegion||regionId={}||logicClusterId={}||share={}||operator={}\"\n                         + \"msg=bind region failed||e->\",\n                regionId, logicClusterId, share, operator, e);\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    private String constructNewLogicIds(Long newLogicClusterId, String oldLogicClusterIds) {\n        // region未被绑定，做覆盖操作\n        if (oldLogicClusterIds.equals(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID)) {\n            return newLogicClusterId.toString();\n        }\n\n        // region被绑定,逗号隔开连接\n        return oldLogicClusterIds + \",\" + newLogicClusterId.toString();\n    }\n\n    @Override\n    public Result<Void> unbindRegion(Long regionId, Long logicClusterId, String operator) {\n        try {\n            if (regionId == null) {\n                return Result.buildFail(\"未指定regionId\");\n            }\n            // 判断region存在\n            ClusterRegion region = getRegionById(regionId);\n            if (region == null) {\n                return Result.buildFail(String.format(REGION_NOT_EXIST, regionId));\n            }\n\n            // 判断在绑定状态\n            if (!isRegionBound(region)) {\n                return Result.buildFail(String.format(\"region %d 未被绑定\", regionId));\n            }\n\n            // 判断region上没有模板\n            Result<List<IndexTemplatePhy>> ret = indexTemplatePhyService.listByRegionId(regionId.intValue());\n            if (ret.failed()) {\n                return Result.buildFail(ret.getMessage());\n            }\n\n            List<IndexTemplatePhy> clusterTemplates = ret.getData();\n            if (CollectionUtils.isNotEmpty(clusterTemplates)) {\n                return Result.buildFail(String.format(\"region %d 上已经分配模板\", regionId));\n            }\n\n            // 删除绑定\n            updateRegion(regionId, getNewBoundLogicIds(region, logicClusterId));\n\n            // 发送消息，删除容量规划容量信息\n            SpringTool.publish(new RegionUnbindEvent(this, region, operator));\n\n            return Result.buildSucc();\n        } catch (Exception e) {\n            LOGGER.error(\"class=RegionRackServiceImpl||method=unbindRegion||regionId={}||operator={}\"\n                         + \"msg=unbind region failed||e->\",\n                regionId, operator, e);\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    /**\n     * 获取region解绑指定逻辑集群之后剩余的逻辑集群id列表\n     * @param region region\n     * @param logicClusterId 逻辑集群id\n     * @return region新的逻辑集群id列表\n     */\n    private String getNewBoundLogicIds(ClusterRegion region, Long logicClusterId) {\n        // 获取region已经关联到的逻辑集群id列表\n        List<Long> boundLogicClusterIds = ListUtils.string2LongList(region.getLogicClusterIds());\n\n        // 当没有指定解绑的逻辑集群id或者region没有被逻辑集群绑定或者region仅被指定解绑的逻辑集群绑定，则回滚至默认值-1\n        if (AriusObjUtils.isNull(logicClusterId) || CollectionUtils.isEmpty(boundLogicClusterIds)\n            || (boundLogicClusterIds.size() == 1 && boundLogicClusterIds.contains(logicClusterId))) {\n            return AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID;\n        }\n\n        // 解绑指定逻辑集群\n        boundLogicClusterIds.remove(logicClusterId);\n        return ListUtils.longList2String(boundLogicClusterIds);\n    }\n\n\n    @Override\n    public ClusterRegion getRegionByLogicClusterId(Long logicClusterId) {\n        if (logicClusterId == null) {\n            return null;\n        }\n\n        ClusterRegionPO clusterRegionPO = clusterRegionDAO.getByLogicClusterId(logicClusterId);\n        return ConvertUtil.obj2Obj(clusterRegionPO, ClusterRegion.class);\n    }\n\n    /**\n     * 判断region是否可以被某个逻辑集群绑定\n     * @param region  ClusterRegion\n     * @param clusterLogicType 逻辑集群类型\n     * @return true-可以被绑定，false-不能被绑定\n     */\n    @Override\n    public boolean isRegionCanBeBound(ClusterRegion region,Integer clusterLogicType) {\n        //判断region是否已经被绑定，以及绑定的region是否还能被逻辑集群绑定\n        if (isRegionBound(region) && (!isRegionBindByPublicLogicCluster(region)||!clusterLogicType.equals(ClusterResourceTypeEnum.PUBLIC.getCode()))) {\n            return false;\n        }\n        return true ;\n    }\n\n    /**\n     * 获取物理下的region\n     * @param phyClusterName 物理集群名\n     * @return 物理集群下的region\n     */\n    @Override\n    public List<ClusterRegion> listRegionsByClusterName(String phyClusterName) {\n        if (StringUtils.isBlank(phyClusterName)) {\n            return new ArrayList<>();\n        }\n        return ConvertUtil.list2List(clusterRegionDAO.getByPhyClusterName(phyClusterName), ClusterRegion.class);\n    }\n\n    /**\n     * 判断region是否已经被绑定给逻辑集群\n     * @param region region\n     * @return true-已经被绑定，false-没有被绑定\n     */\n    @Override\n    public boolean isRegionBound(ClusterRegion region) {\n        if (region == null) {\n            return false;\n        }\n\n        return !region.getLogicClusterIds().equals(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID);\n    }\n\n    /**\n     * 判断region是否被共享类型的逻辑集群绑定\n     * @param region region信息\n     * @return true or false\n     */\n    private boolean isRegionBindByPublicLogicCluster(ClusterRegion region) {\n        if (!isRegionBound(region)) {\n            return false;\n        }\n\n        // 只有共享逻辑集群下的region能够被重复绑定\n        Long logicClusterId = ListUtils.string2LongList(region.getLogicClusterIds()).get(0);\n        ClusterLogic clusterLogic =\n                clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(logicClusterId);\n\n        return !AriusObjUtils.isNull(clusterLogic)\n               && clusterLogic.getType().equals(ClusterResourceTypeEnum.PUBLIC.getCode());\n    }\n\n    @Override\n    public Set<Long> getLogicClusterIdByPhyClusterId(Integer phyClusterId) {\n        ClusterPhy clusterPhy = esClusterPhyService.getClusterById(phyClusterId);\n        if (clusterPhy == null) {\n            return null;\n        }\n        List<ClusterRegion> clusterRegions = listRegionsByClusterName(clusterPhy.getCluster());\n        if (CollectionUtils.isEmpty(clusterRegions)) {\n            return null;\n        }\n\n        // 获取物理集群对应的逻辑集群，进行去重的操作\n        Set<Long> logicClusterIds = Sets.newHashSet();\n        clusterRegions.forEach(clusterRegion -> logicClusterIds\n            .addAll(new HashSet<>(ListUtils.string2LongList(clusterRegion.getLogicClusterIds()))));\n        return logicClusterIds.stream().filter(logicClusterId -> logicClusterId > 0).collect(Collectors.toSet());\n    }\n\n    @Override\n    public boolean isExistByRegionName(String regionName) {\n        return null != clusterRegionDAO.getByName(regionName);\n    }\n\n    @Override\n    public boolean isExistByRegionId(Integer regionId) {\n        return null != clusterRegionDAO.getById(regionId.longValue());\n    }\n\n    @Override\n    public List<ClusterRegion> getClusterRegionsByLogicIds(List<Long> clusterLogicIds) {\n        if (CollectionUtils.isEmpty(clusterLogicIds)) {\n            return Lists.newArrayList();\n        }\n        List<Long> uniqueClusterLogicIds = clusterLogicIds.stream().distinct().collect(Collectors.toList());\n        List<ClusterRegion> clusterRegionList = Lists.newArrayList();\n        // 这里不应该一次性把clusterLogic_id列表放置在 sql in中, 使用范围来查询，是为了模糊匹配单列中的clusterLogicId;\n        for (Long clusterLogicId : uniqueClusterLogicIds) {\n            ClusterRegionPO logicCluster = clusterRegionDAO.getByLogicClusterId(clusterLogicId);\n            clusterRegionList.add(ConvertUtil.obj2Obj(logicCluster, ClusterRegion.class));\n        }\n\n        return clusterRegionList;\n    }\n\n    @Override\n    public List<ClusterRegion> listColdRegionByCluster(String cluster) {\n        List<ClusterRegionPO> clusterRegions = clusterRegionDAO.getByPhyClusterName(cluster);\n        if (CollectionUtils.isEmpty(clusterRegions)) {\n            return new ArrayList<>();\n        }\n\n        List<ClusterRegion> coldRegionList = new ArrayList<>();\n        for (ClusterRegionPO region : clusterRegions) {\n            ClusterRegionConfig config = genClusterRegionConfig(region.getConfig());\n            if (Boolean.TRUE.equals(config.getCold())) {\n                coldRegionList.add(ConvertUtil.obj2Obj(region, ClusterRegion.class));\n            }\n        }\n\n        return coldRegionList;\n    }\n\n    @Override\n    public ClusterRegionConfig genClusterRegionConfig(String config) {\n        if (StringUtils.isBlank(config)) {\n            return new ClusterRegionConfig();\n        }\n        return JSON.parseObject(config, ClusterRegionConfig.class);\n    }\n\n    @Override\n    public Map<Integer, ClusterRegionFSInfo> getClusterRegionFSInfo(String cluster) {\n        Map<Integer, ClusterRegionFSInfo> clusterRegionFSInfoMap = new HashMap<>();\n\n        List<ClusterRegion> clusterRegionList = listRegionsByClusterName(cluster);\n        if (CollectionUtils.isEmpty(clusterRegionList)) {\n            return clusterRegionFSInfoMap;\n        }\n\n        Map<String, ClusterNodeStats> nodeId2NodeStatsMap = esClusterNodeService.syncGetNodeFsStatsMap(cluster);\n        if (MapUtils.isEmpty(nodeId2NodeStatsMap)) {\n            return clusterRegionFSInfoMap;\n        }\n        Map<String, ClusterNodeStats> nodeName2NodeStatsMap = new HashMap<>();\n        for (Map.Entry<String, ClusterNodeStats> entry : nodeId2NodeStatsMap.entrySet()) {\n            ClusterNodeStats nodeStats = entry.getValue();\n            if (nodeStats == null) {\n                continue;\n            }\n\n            nodeName2NodeStatsMap.put(nodeStats.getName(), nodeStats);\n        }\n\n        List<ClusterRoleHost> clusterRoleHostList = clusterRoleHostService.getNodesByCluster(cluster);\n        if (CollectionUtils.isEmpty(clusterRoleHostList)) {\n            return clusterRegionFSInfoMap;\n        }\n\n        Multimap<Integer, ClusterRoleHost> regionId2NodeMap = ConvertUtil.list2MulMap(clusterRoleHostList,\n            ClusterRoleHost::getRegionId);\n        for (Integer regionId : regionId2NodeMap.keySet()) {\n            List<ClusterRoleHost> nodeList = Lists.newArrayList(regionId2NodeMap.get(regionId));\n            ClusterRegionFSInfo clusterRegionFSInfo = new ClusterRegionFSInfo();\n            clusterRegionFSInfo.setRegionId(regionId);\n            for (ClusterRoleHost node : nodeList) {\n                if (ESClusterNodeRoleEnum.DATA_NODE.getCode() != node.getRole()) {\n                    continue;\n                }\n\n                ClusterNodeStats nodeStats = nodeName2NodeStatsMap.get(node.getNodeSet());\n                if (null == nodeStats) {\n                    continue;\n                }\n\n                FSTotal fsTotal = nodeStats.getFs().getTotal();\n                clusterRegionFSInfo\n                    .setAvailableInBytes(fsTotal.getAvailableInBytes() + clusterRegionFSInfo.getAvailableInBytes());\n                clusterRegionFSInfo.setFreeInBytes(fsTotal.getFreeInBytes() + clusterRegionFSInfo.getFreeInBytes());\n                clusterRegionFSInfo.setTotalInBytes(fsTotal.getTotalInBytes() + clusterRegionFSInfo.getTotalInBytes());\n            }\n            clusterRegionFSInfoMap.put(regionId, clusterRegionFSInfo);\n        }\n\n        return clusterRegionFSInfoMap;\n    }\n\n    /***************************************** private method ****************************************************/\n    /**\n     * 根据regionId更新region的logicClusterId或racks\n     * @param regionId       要更新的region的ID\n     * @param logicClusterIds 逻辑集群ID列表，为null则不更新\n     */\n    private void updateRegion(Long regionId, String logicClusterIds) {\n        if (regionId == null) {\n            return;\n        }\n\n        ClusterRegionPO updateParam = new ClusterRegionPO();\n        updateParam.setId(regionId);\n        updateParam.setLogicClusterIds(logicClusterIds);\n\n        clusterRegionDAO.update(updateParam);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/common/AriusConfigInfoService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.common;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.config.AriusConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.config.AriusConfigInfo;\n\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * @author d06679\n * @date 2019/3/14\n */\npublic interface AriusConfigInfoService {\n\n    /**\n     * 新增配置\n     * @param configInfoDTO 配置信息\n     * @param operator 操作人\n     * @return 成功 true\n     */\n    Result<Integer> addConfig(AriusConfigInfoDTO configInfoDTO, String operator);\n\n    /**\n     * 删除配置\n     * @param configId 配置id\n     * @param operator 操作人\n     * @return 成功 true  失败 false\n     */\n    Result<Void> delConfig(Integer configId, String operator);\n\n    /**\n     * 编辑配置\n     * @param configInfoDTO 配置内容\n     * @param operator 操作人\n     * @return 成功 true  失败 false\n     *\n     */\n    Result<Void> editConfig(AriusConfigInfoDTO configInfoDTO, String operator);\n\n    /**\n     * 使能配置\n     * @param configId 配置id\n     * @param status 状态\n     * @param operator 操作人\n     * @return 成功 true  失败 false\n     *\n     */\n    Result<Void> switchConfig(Integer configId, Integer status, String operator);\n\n    /**\n     * 根据配置组获取配置项\n     * @param group 配置组\n     * @return 配置AriusConfigInfoPO列表  项目内部使用\n     *\n     * 如果配置组不存在 返回空列表\n     *\n     */\n    List<AriusConfigInfo> getConfigByGroup(String group);\n\n    /**\n     * 根据查询条件返回AriusConfigInfoVO列表\n     * @param param 查询条件\n     * @return 配置列表\n     *\n     * 如果不存在,返回空列表\n     */\n    List<AriusConfigInfo> queryByCondition(AriusConfigInfoDTO param);\n\n    /**\n     * 查询指定配置\n     * @param configId 配置id\n     * @return 配置信息  不存在返回null\n     */\n    AriusConfigInfo getConfigById(Integer configId);\n\n    /**\n     * 获取int类型配置\n     * @param group 配置组\n     * @param name 配置项\n     * @param defaultValue 默认值\n     * @return 如果查到转换后返回,转换报错或者没有查到则返回默认值\n     */\n    Integer intSetting(String group, String name, Integer defaultValue);\n\n    /**\n     * 获取long类型配置\n     * @param group 配置组\n     * @param name 配置项\n     * @param defaultValue 默认值\n     * @return 如果查到转换后返回,转换报错或者没有查到则返回默认值\n     */\n    Long longSetting(String group, String name, Long defaultValue);\n\n    /**\n     * 获取double类型配置\n     * @param group 配置组\n     * @param name 配置项\n     * @param defaultValue 默认值\n     * @return 如果查到转换后返回,转换报错或者没有查到则返回默认值\n     */\n    Double doubleSetting(String group, String name, Double defaultValue);\n\n    /**\n     * 获取String类型配置\n     * @param group 配置组\n     * @param name 配置项\n     * @param defaultValue 默认值\n     * @return 如果查到转换后返回,转换报错或者没有查到则返回默认值\n     */\n    String stringSetting(String group, String name, String defaultValue);\n\n    /**\n     * 获取String类型配置 用字符分割\n     * @param group 配置组\n     * @param name 配置项\n     * @param defaultValue 默认值\n     * @param split 分隔符\n     * @return 分隔符\n     */\n    Set<String> stringSettingSplit2Set(String group, String name, String defaultValue, String split);\n\n    /**\n     * 获取bool类型配置\n     * @param group 配置组\n     * @param name 配置项\n     * @param defaultValue 默认值\n     * @return 如果查到转换后返回,转换报错或者没有查到则返回默认值\n     */\n    Boolean booleanSetting(String group, String name, Boolean defaultValue);\n\n    /**\n     * 获取Object类型配置\n     * @param group 配置组\n     * @param name 配置项\n     * @param defaultValue 默认值\n     * @param clazz 返回类型\n     * @return 如果查到转换后返回,转换报错或者没有查到则返回默认值\n     */\n    <T> T objectSetting(String group, String name, T defaultValue, Class<T> clazz);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/common/OperateRecordService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.common;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.operaterecord.OperateRecordVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * 操作记录\n *\n * @author gyp\n * @version 1.0\n * @date 2022/5/10\n */\npublic interface OperateRecordService {\n    /**\n     * 删除早于指定时间的数据\n     *\n     * @param saveTime 删除数据的时间。\n     */\n   void deleteExprieData( Date saveTime);\n    Result<Void> save(OperateRecord operateRecord);\n    /**\n     * 手动触发保存操作记录\n     *\n     * @param content         操作记录的内容\n     * @param operator        操作员是触发操作的用户。\n     * @param projectId       项目编号\n     * @param bizId           业务id，即业务表的id\n     * @param operateTypeEnum 操作的类型，为枚举类，枚举类如下：\n     */\n    void saveOperateRecordWithManualTrigger(String content, String operator, Integer projectId, Object bizId,\n                                            OperateTypeEnum operateTypeEnum) ;\n    /**\n     * 保存项目的运行记录\n     *\n     * @param content 操作记录的内容\n     * @param operator 运营商名称\n     * @param projectId 项目编号\n     * @param bizId 操作记录的业务ID，即任务的ID。\n     * @param operateTypeEnum 操作的类型，为枚举类型，枚举类型如下：\n     */\n    void saveOperateRecordWithSchedulingTasks(String content, String operator, Integer projectId, Object bizId,\n                                            OperateTypeEnum operateTypeEnum) ;\n\n    /**\n     * 动态分页查询\n     *\n     * @param pageDTO 页面dto\n     * @return {@code Object}\n     */\n    Tuple<Long, List<OperateRecordVO>> pagingGetOperateRecordByCondition(OperateRecordDTO pageDTO);\n\n    OperateRecordVO getById(Integer id);\n\n /**\n  * 获取操作记录list\n  * @param queryDTO\n  * @return\n  */\n List<OperateRecordVO> queryCondition(OperateRecordDTO queryDTO);\n\n    /**\n     * 更新操作记录\n     * @param operateRecordDTO\n     * @return\n     */\n    Result<Integer> updateOperateRecord(OperateRecordDTO operateRecordDTO);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/common/impl/AriusConfigInfoServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.common.impl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.config.AriusConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.config.AriusConfigInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.config.AriusConfigInfoPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.config.AriusConfigDimensionEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.config.AriusConfigStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.config.AriusConfigInfoDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\n\n/**\n *\n *\n * @author d06679\n * @date 2019/3/14\n */\n@Service\npublic class AriusConfigInfoServiceImpl implements AriusConfigInfoService {\n\n    private static final ILog                LOGGER      = LogFactory.getLog(AriusConfigInfoServiceImpl.class);\n\n    private static final String              NOT_EXIST   = \"配置不存在\";\n\n    @Autowired\n    private AriusConfigInfoDAO               configInfoDAO;\n\n    @Autowired\n    private OperateRecordService             operateRecordService;\n    @Autowired\n    private ProjectService projectService;\n\n    private Cache<String, AriusConfigInfoPO> configCache = CacheBuilder.newBuilder()\n        .expireAfterWrite(1, TimeUnit.MINUTES).maximumSize(100).build();\n\n    /**\n     * 新增配置\n     * @param configInfoDTO 配置信息\n     * @param operator      操作人\n     * @return 成功 true\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Integer> addConfig(AriusConfigInfoDTO configInfoDTO, String operator) {\n        Result<Void> checkResult = checkParam(configInfoDTO);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=AriusConfigInfoServiceImpl||method=addConfig||msg={}||msg=check fail!\",\n                checkResult.getMessage());\n            return Result.buildFrom(checkResult);\n        }\n\n        initConfig(configInfoDTO);\n\n        AriusConfigInfoPO oldConfig = getByGroupAndNameFromDB(configInfoDTO.getValueGroup(),\n            configInfoDTO.getValueName());\n        if (oldConfig != null) {\n            return Result.buildDuplicate(\"配置重复\");\n        }\n        //TODO:对于新增的dashboard配置，需要验证格式是否正确\n        AriusConfigInfoPO param = ConvertUtil.obj2Obj(configInfoDTO, AriusConfigInfoPO.class);\n        boolean succ = (1 == configInfoDAO.insert(param));\n        if (succ) {\n            operateRecordService.save(buildOperateRecord(configInfoDTO.getId(),operator,OperateTypeEnum.SETTING_ADD,\n                    String.format(\"新增平台配置, 配置组:%s, 配置名称%s\",\n                    configInfoDTO.getValueGroup(), configInfoDTO.getValueName())));\n        }\n        return Result.build(succ, param.getId());\n    }\n\n    /**\n     * 删除配置\n     * @param configId 配置id\n     * @param operator 操作人\n     * @return 成功 true  失败 false\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> delConfig(Integer configId, String operator) {\n        AriusConfigInfoPO configInfoPO = configInfoDAO.getById(configId);\n        if (configInfoPO == null) {\n            return Result.buildNotExist(NOT_EXIST);\n        }\n\n        boolean succ = (1 == configInfoDAO.updateByIdAndStatus(configId, AriusConfigStatusEnum.DELETED.getCode()));\n        if (succ) {\n            operateRecordService.save(buildOperateRecord(configId,operator,OperateTypeEnum.SETTING_DELETE,\n                    String.format(\"删除平台配置, 配置组:%s, 配置名称%s\", configInfoPO.getValueGroup(), configInfoPO.getValueName())));\n        }\n\n        return Result.build(succ);\n    }\n\n    /**\n     * 编辑配置 只能编辑值  组和名称不能修改\n     * @param configInfoDTO 配置内容\n     * @param operator      操作人\n     * @return 成功 true  失败 false\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> editConfig(AriusConfigInfoDTO configInfoDTO, String operator) {\n        if (AriusObjUtils.isNull(configInfoDTO.getId())) {\n            return Result.buildParamIllegal(\"配置ID为空\");\n        }\n\n        AriusConfigInfoPO configInfoPO = configInfoDAO.getById(configInfoDTO.getId());\n        if (configInfoPO == null) {\n            return Result.buildNotExist(NOT_EXIST);\n        }\n\n        boolean succ = (1 == configInfoDAO.update(ConvertUtil.obj2Obj(configInfoDTO, AriusConfigInfoPO.class)));\n\n        if (succ) {\n            operateRecordService.save(buildOperateRecord(configInfoPO.getId(),operator,OperateTypeEnum.SETTING_MODIFY\n                    ,String.format(\"编辑平台配置，配置组：%s，配置名称%s，配置值：【%s】->【%s】\", configInfoPO.getValueGroup(),\n                            configInfoPO.getValueName(),configInfoPO.getValue(),configInfoDTO.getValue())));\n\n        }\n\n        return Result.build(succ);\n    }\n\n    /**\n     * 使能配置\n     * @param configId 配置id\n     * @param status   状态\n     * @param operator 操作人\n     * @return 成功 true  失败 false\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> switchConfig(Integer configId, Integer status, String operator) {\n        AriusConfigInfoPO configInfoPO = configInfoDAO.getById(configId);\n        if (configInfoPO == null) {\n            return Result.buildNotExist(NOT_EXIST);\n        }\n\n        AriusConfigStatusEnum statusEnum = AriusConfigStatusEnum.valueOf(status);\n        if (statusEnum == null) {\n            return Result.buildParamIllegal(\"状态非法\");\n        }\n\n        boolean succ = (1 == configInfoDAO.updateByIdAndStatus(configId, status));\n        if (succ) {\n            operateRecordService.save(buildOperateRecord(configInfoPO.getId(),operator,OperateTypeEnum.SETTING_MODIFY,String.format(\"平台配置%s, 配置组:%s, 配置名称%s\",\n                    statusEnum.getDesc(), configInfoPO.getValueGroup(), configInfoPO.getValueName())));\n\n        }\n\n        return Result.build(succ);\n    }\n\n    /**\n     * 根据配置组获取配置项\n     * @param group 配置组\n     * @return 配置AriusConfigInfoPO列表  项目内部使用\n     * <p>\n     * 如果配置组不存在 返回空列表\n     */\n    @Override\n    public List<AriusConfigInfo> getConfigByGroup(String group) {\n        List<AriusConfigInfo> configInfos = Lists.newArrayList();\n\n        List<AriusConfigInfoPO> configInfoPOList = configInfoDAO.listByGroup(group);\n        if (CollectionUtils.isEmpty(configInfoPOList)) {\n            return configInfos;\n        }\n\n        return ConvertUtil.list2List(configInfoPOList, AriusConfigInfo.class);\n    }\n\n    /**\n     * 根据查询条件返回AriusConfigInfoVO列表\n     * @param param 查询条件\n     * @return 配置列表\n     *\n     * 如果不存在,返回空列表\n     */\n    @Override\n    public List<AriusConfigInfo> queryByCondition(AriusConfigInfoDTO param) {\n        List<AriusConfigInfoPO> configInfoPOList = configInfoDAO\n            .listByCondition(ConvertUtil.obj2Obj(param, AriusConfigInfoPO.class));\n        return ConvertUtil.list2List(configInfoPOList, AriusConfigInfo.class);\n    }\n\n    /**\n     * 查询指定配置\n     * @param configId 配置id\n     * @return 配置信息  不存在返回null\n     */\n    @Override\n    public AriusConfigInfo getConfigById(Integer configId) {\n        return ConvertUtil.obj2Obj(configInfoDAO.getById(configId), AriusConfigInfo.class);\n    }\n\n    /**\n     * 获取int类型配置\n     * @param group        配置组\n     * @param name         配置项\n     * @param defaultValue 默认值\n     * @return 如果查到转换后返回, 转换报错或者没有查到则返回默认值\n     */\n    @Override\n    public Integer intSetting(String group, String name, Integer defaultValue) {\n        try {\n            AriusConfigInfoPO configInfoPO = getByGroupAndName(group, name);\n            if (configInfoPO == null || StringUtils.isBlank(configInfoPO.getValue())) {\n                return defaultValue;\n            }\n            return Integer.valueOf(configInfoPO.getValue());\n        } catch (NumberFormatException e) {\n\n            LOGGER.debug(\"class=AriusConfigInfoServiceImpl||method=intSetting||group={}||name={}||msg=get config error!\",\n                    group, name);\n\n        }\n        return defaultValue;\n    }\n\n    /**\n     * 获取long类型配置\n     * @param group        配置组\n     * @param name         配置项\n     * @param defaultValue 默认值\n     * @return 如果查到转换后返回, 转换报错或者没有查到则返回默认值\n     */\n    @Override\n    public Long longSetting(String group, String name, Long defaultValue) {\n        try {\n            AriusConfigInfoPO configInfoPO = getByGroupAndName(group, name);\n            if (configInfoPO == null || StringUtils.isBlank(configInfoPO.getValue())) {\n                return defaultValue;\n            }\n            return Long.valueOf(configInfoPO.getValue());\n        } catch (Exception e) {\n            LOGGER.debug(\"class=AriusConfigInfoServiceImpl||method=longSetting||group={}||name={}||msg=get config error!\",\n                    group, name);\n\n        }\n        return defaultValue;\n    }\n\n    /**\n     * 获取double类型配置\n     * @param group        配置组\n     * @param name         配置项\n     * @param defaultValue 默认值\n     * @return 如果查到转换后返回, 转换报错或者没有查到则返回默认值\n     */\n    @Override\n    public Double doubleSetting(String group, String name, Double defaultValue) {\n        try {\n            AriusConfigInfoPO configInfoPO = getByGroupAndName(group, name);\n            if (configInfoPO == null || StringUtils.isBlank(configInfoPO.getValue())) {\n                return defaultValue;\n            }\n            return Double.valueOf(configInfoPO.getValue());\n        } catch (Exception e) {\n            LOGGER.debug(\"class=AriusConfigInfoServiceImpl||method=doubleSetting||group={}||name={}||msg=get config error!\",group, name, e);\n        }\n        return defaultValue;\n    }\n\n    /**\n     * 获取String类型配置\n     * @param group        配置组\n     * @param name         配置项\n     * @param defaultValue 默认值\n     * @return 如果查到转换后返回, 转换报错或者没有查到则返回默认值\n     */\n    @Override\n    public String stringSetting(String group, String name, String defaultValue) {\n        try {\n            AriusConfigInfoPO configInfoPO = getByGroupAndName(group, name);\n            if (configInfoPO == null || StringUtils.isBlank(configInfoPO.getValue())) {\n                return defaultValue;\n            }\n            return configInfoPO.getValue();\n        } catch (Exception e) {\n            LOGGER.debug(\"class=AriusConfigInfoServiceImpl||method=stringSetting||group={}||name={}||msg=get config error!\",group, name, e);\n        }\n        return defaultValue;\n    }\n\n    /**\n     * 获取String类型配置 用字符分割\n     *\n     * @param group        配置组\n     * @param name         配置项\n     * @param defaultValue 默认值\n     * @param split        分隔符\n     * @return 分隔符\n     */\n    @Override\n    public Set<String> stringSettingSplit2Set(String group, String name, String defaultValue, String split) {\n        String string = stringSetting(group, name, defaultValue);\n        return Sets.newHashSet(string.split(split));\n    }\n\n    /**\n     * 获取bool类型配置\n     * @param group        配置组\n     * @param name         配置项\n     * @param defaultValue 默认值\n     * @return 如果查到转换后返回, 转换报错或者没有查到则返回默认值\n     */\n    @Override\n    public Boolean booleanSetting(String group, String name, Boolean defaultValue) {\n        AriusConfigInfoPO configInfoPO = getByGroupAndName(group, name);\n        if (configInfoPO == null || StringUtils.isBlank(configInfoPO.getValue())) {\n            return defaultValue;\n        }\n        return Boolean.valueOf(configInfoPO.getValue());\n    }\n\n    /**\n     * 获取Object类型配置\n     * @param group        配置组\n     * @param name         配置项\n     * @param defaultValue 默认值\n     * @param clazz        返回类型\n     * @return 如果查到转换后返回, 转换报错或者没有查到则返回默认值\n     */\n    @Override\n    public <T> T objectSetting(String group, String name, T defaultValue, Class<T> clazz) {\n        try {\n            AriusConfigInfoPO configInfoPO = getByGroupAndName(group, name);\n            if (configInfoPO == null || StringUtils.isBlank(configInfoPO.getValue())) {\n                return defaultValue;\n            }\n            return JSON.parseObject(configInfoPO.getValue(), clazz);\n        } catch (Exception e) {\n            LOGGER.debug(\"class=AriusConfigInfoServiceImpl||method=objectSetting||group={}||name={}||msg=get config error!\", group, name, e);\n        }\n        return defaultValue;\n    }\n\n    /******************************************* private method **************************************************/\n    private Result<Void> checkParam(AriusConfigInfoDTO configInfoDTO) {\n        if (AriusObjUtils.isNull(configInfoDTO)) {\n            return Result.buildParamIllegal(\"配置信息为空\");\n        }\n        if (AriusObjUtils.isNull(configInfoDTO.getValueGroup())) {\n            return Result.buildParamIllegal(\"组为空\");\n        }\n        if (AriusObjUtils.isNull(configInfoDTO.getValueName())) {\n            return Result.buildParamIllegal(\"名字为空\");\n        }\n        return Result.buildSucc();\n    }\n\n    private void initConfig(AriusConfigInfoDTO configInfoDTO) {\n\n        if (configInfoDTO.getDimension() == null) {\n            configInfoDTO.setDimension(AriusConfigDimensionEnum.UNKNOWN.getCode());\n        }\n\n        if (configInfoDTO.getStatus() == null) {\n            configInfoDTO.setStatus(AriusConfigStatusEnum.NORMAL.getCode());\n        }\n\n        if (configInfoDTO.getValue() == null) {\n            configInfoDTO.setValue(\"\");\n        }\n\n        if (configInfoDTO.getMemo() == null) {\n            configInfoDTO.setMemo(\"\");\n        }\n    }\n\n    private AriusConfigInfoPO getByGroupAndName(String group, String valueName) {\n        try {\n            return configCache.get(group + \"@\" + valueName, () -> getByGroupAndNameFromDB(group, valueName));\n        } catch (Exception e) {\n            return getByGroupAndNameFromDB(group, valueName);\n        }\n    }\n\n    private AriusConfigInfoPO getByGroupAndNameFromDB(String group, String valueName) {\n        return configInfoDAO.getByGroupAndName(group, valueName);\n    }\n    \n    private OperateRecord buildOperateRecord(Object bizId, String operator, OperateTypeEnum operationTypeEnum, String content) {\n        return new OperateRecord.Builder().content(content).bizId(bizId).operationTypeEnum(operationTypeEnum)\n                .project(projectService.getProjectBriefByProjectId(AuthConstant.SUPER_PROJECT_ID))\n                .userOperation(operator)\n                .buildDefaultManualTrigger();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/common/impl/OperateRecordServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.common.impl;\n\nimport com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.operaterecord.OperateRecordInfoPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.operaterecord.OperateRecordVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.OperateRecordSortEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.SortConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.ModuleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.threadpool.AriusTaskThreadPool;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.optrecord.OperateRecordDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.dao.ProjectDao;\n\nimport java.util.*;\nimport java.util.function.Consumer;\n\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\n\n/**\n *\n * @author d06679\n * @date 2019/3/14\n */\n@Service\npublic class OperateRecordServiceImpl implements OperateRecordService {\n\n    private static final ILog LOGGER          = LogFactory.getLog(OperateRecordServiceImpl.class);\n\n    private static final String  PROJECT_NAME = \"project_name\";\n    private static final String  MODULE_ID = \"module_id\";\n    private static final String  OPERATE_ID = \"operate_id\";\n    private static final String  TRIGGER_WAY_ID = \"trigger_way_id\";\n    private static final String  USER_OPERATION = \"user_operation\";\n    private static final String  ID = \"id\";\n\n    private AriusTaskThreadPool ariusTaskThreadPool;\n\n    @Autowired\n    private OperateRecordDAO  operateRecordDAO;\n    @Autowired\n    private ProjectDao projectDao;\n\n    @PostConstruct\n    public void init() {\n        ariusTaskThreadPool = new AriusTaskThreadPool();\n        ariusTaskThreadPool.init(3, \"OperateRecordServiceImpl\", 100);\n    }\n    \n    @Override\n    public void deleteExprieData(Date saveTime) {\n    \n        operateRecordDAO.deleteExprieData(saveTime);\n    \n    }\n    \n    \n    @Override\n    public Result<Void> save(OperateRecord operateRecord) {\n        ariusTaskThreadPool.run(() -> {\n            try {\n                OperateRecordInfoPO operateRecordInfoPO = ConvertUtil.obj2Obj(operateRecord, OperateRecordInfoPO.class);\n                operateRecordDAO.insert(operateRecordInfoPO);\n            } catch (Exception e) {\n                LOGGER.error(\n                        \"class=OperateRecordServiceImply||method=save||errMsg={}||operateId={}\",\n                        e.getMessage(), operateRecord.getOperateId(), e);\n            }\n        });\n        return Result.buildSucc();\n\n    }\n    \n    @Override\n    public void saveOperateRecordWithManualTrigger(String content, String operator, Integer projectId,\n                                                   Object bizId, OperateTypeEnum operateTypeEnum) {\n        save(new OperateRecord.Builder().project(ConvertUtil.obj2Obj(projectDao.selectByProjectId(projectId),\n                        ProjectBriefVO.class)).operationTypeEnum(operateTypeEnum)\n                .triggerWayEnum(TriggerWayEnum.MANUAL_TRIGGER).userOperation(operator).content(content).bizId(bizId)\n                .build());\n    }\n    \n    @Override\n    public void saveOperateRecordWithSchedulingTasks(String content, String operator, Integer projectId, Object bizId,\n                                                     OperateTypeEnum operateTypeEnum) {\n       save(new OperateRecord.Builder().project(ConvertUtil.obj2Obj(projectDao.selectByProjectId(projectId),\n                        ProjectBriefVO.class)).operationTypeEnum(operateTypeEnum)\n                .triggerWayEnum(TriggerWayEnum.SCHEDULING_TASKS).userOperation(operator).content(content).bizId(bizId)\n                .build());\n    }\n    \n    /**\n     * 动态分页查询\n     *\n     * @param pageDTO 页面dto\n     * @return {@code Object}\n     */\n    @Override\n    public Tuple<Long, List<OperateRecordVO>> pagingGetOperateRecordByCondition(OperateRecordDTO pageDTO) {\n        String sortTerm = OperateRecordSortEnum.getSortField(pageDTO.getSortTerm());\n        String sortType = pageDTO.getOrderByDesc() ? SortConstant.DESC : SortConstant.ASC;\n        pageDTO.setSortTerm(sortTerm);\n        pageDTO.setSortType(sortType);\n        if(StringUtils.isNotBlank(pageDTO.getProjectName())){\n            pageDTO.setProjectName(CommonUtils.sqlFuzzyQueryTransfer(pageDTO.getProjectName()));\n        }\n        if(StringUtils.isNotBlank(pageDTO.getContent())){\n            pageDTO.setContent(CommonUtils.sqlFuzzyQueryTransfer(pageDTO.getContent()));\n        }\n        final List<OperateRecordInfoPO> recordInfoPOList = operateRecordDAO.listByCondition(pageDTO);\n\n        final Map</*id*/Integer, OperateRecordInfoPO> operateRecordInfoMap = ConvertUtil.list2Map(recordInfoPOList,\n            OperateRecordInfoPO::getId);\n        final List<OperateRecordVO> operateRecordVOList = ConvertUtil.list2List(recordInfoPOList,\n            OperateRecordVO.class);\n        //对vo中的数据进行转换\n        Consumer<OperateRecordVO> poIncludeEnumIdConvertEnumStrFunc = operateRecordVO -> this\n            .poIncludeEnumIdConvertEnumStr(operateRecordInfoMap.get(operateRecordVO.getId()), operateRecordVO);\n        operateRecordVOList.forEach(poIncludeEnumIdConvertEnumStrFunc);\n\n        final Long count = operateRecordDAO.countByCondition(pageDTO);\n\n        return new Tuple<>(count, operateRecordVOList);\n    }\n\n    /**\n     * po包括枚举id转换枚举str\n     *\n     * @param recordInfo 操作记录信息pomap\n     * @param operateRecordVO        操作记录签证官\n     */\n    private void poIncludeEnumIdConvertEnumStr(OperateRecordInfoPO recordInfo, OperateRecordVO operateRecordVO) {\n        //设置操作的模块\n        Optional.ofNullable(recordInfo).map(OperateRecordInfoPO::getModuleId).map(ModuleEnum::getModuleEnum)\n            .map(ModuleEnum::getModule).ifPresent(operateRecordVO::setModule);\n        //设置触发方式\n        Optional.ofNullable(recordInfo).map(OperateRecordInfoPO::getTriggerWayId).map(TriggerWayEnum::getTriggerWayEnum)\n            .map(TriggerWayEnum::getTriggerWay).ifPresent(operateRecordVO::setTriggerWay);\n        //设置操作类型\n        Optional.ofNullable(recordInfo).map(OperateRecordInfoPO::getOperateId)\n            .map(OperateTypeEnum::getOperationTypeEnum).map(OperateTypeEnum::getOperationType)\n            .ifPresent(operateRecordVO::setOperate);\n    }\n\n    /**\n     * @param id\n     * @return\n     */\n    @Override\n    public OperateRecordVO getById(Integer id) {\n        final OperateRecordInfoPO recordInfo = operateRecordDAO.getById(id);\n        final OperateRecordVO operateRecordVO = ConvertUtil.obj2Obj(recordInfo, OperateRecordVO.class);\n        poIncludeEnumIdConvertEnumStr(recordInfo, operateRecordVO);\n        return operateRecordVO;\n    }\n\n    /**\n     * 查询操作记录list\n     * @param queryDTO\n     * @return\n     */\n    @Override\n    public List<OperateRecordVO> queryCondition(OperateRecordDTO queryDTO) {\n        Result<Void> result = paramCheck(queryDTO.getUserOperation(), queryDTO.getProjectName());\n        if (result.failed()) {\n            return new ArrayList<>();\n        }\n        List<OperateRecordInfoPO> recordInfoPOList = operateRecordDAO.listByCondition(queryDTO);\n        List<OperateRecordVO> operateRecordVOList = ConvertUtil.list2List(recordInfoPOList,\n                OperateRecordVO.class);\n        return operateRecordVOList;\n    }\n\n    @Override\n    public Result<Integer> updateOperateRecord(OperateRecordDTO operateRecordDTO) {\n        Result<Void> result = paramCheck(operateRecordDTO.getUserOperation(), operateRecordDTO.getProjectName());\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n        OperateRecordInfoPO selectOneOperateRecordInfoPO = operateRecordDAO.selectOneOperateRecord(operateRecordDTO);\n        if (null == selectOneOperateRecordInfoPO) {\n            return insertOperateRecordInfoWithoutCheck(operateRecordDTO);\n        }\n        OperateRecordInfoPO convertOperateRecordInfoPO = ConvertUtil.obj2Obj(operateRecordDTO, OperateRecordInfoPO.class);\n        convertOperateRecordInfoPO.setUpdateTime(new Date());\n        convertOperateRecordInfoPO.setOperateTime(new Date());\n        convertOperateRecordInfoPO.setId(selectOneOperateRecordInfoPO.getId());\n        boolean succ = (1 == operateRecordDAO.updateById(convertOperateRecordInfoPO));\n        return Result.build(succ, convertOperateRecordInfoPO.getId());\n    }\n\n    /**\n     * 组装查询参数\n     * @param operateRecordDTO\n     * @return\n     */\n    private QueryWrapper<OperateRecordInfoPO> buildOperateRecordInfoPOQueryWrapper(OperateRecordDTO operateRecordDTO) {\n        QueryWrapper<OperateRecordInfoPO> operateRecordInfoPOQueryWrapper = new QueryWrapper<>();\n        operateRecordInfoPOQueryWrapper.eq(PROJECT_NAME, operateRecordDTO.getProjectName());\n        operateRecordInfoPOQueryWrapper.eq(MODULE_ID, operateRecordDTO.getModuleId());\n        operateRecordInfoPOQueryWrapper.eq(OPERATE_ID, operateRecordDTO.getOperateId());\n        operateRecordInfoPOQueryWrapper.eq(TRIGGER_WAY_ID, operateRecordDTO.getTriggerWayId());\n        operateRecordInfoPOQueryWrapper.eq(USER_OPERATION, operateRecordDTO.getUserOperation());\n        return operateRecordInfoPOQueryWrapper;\n    }\n\n    /**\n     * 新增操作记录\n     * @param operateRecordDTO\n     */\n    private Result<Integer> insertOperateRecordInfoWithoutCheck(OperateRecordDTO operateRecordDTO) {\n        OperateRecord operateRecord = ConvertUtil.obj2Obj(operateRecordDTO,OperateRecord.class);\n        return Result.build(save(operateRecord).success(),operateRecordDTO.getId());\n    }\n\n    /**\n     * 校验应用和用户\n     * @param userOperation\n     * @param projectName\n     * @return\n     */\n    private Result<Void> paramCheck(String userOperation, String projectName) {\n        if (AriusObjUtils.isNull(userOperation)) {\n            return Result.buildFail(\"用户账号为空\");\n        }\n        if (AriusObjUtils.isNull(projectName)) {\n            return Result.buildFail(\"应用为空\");\n        }\n        return Result.buildSucc();\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/ESClusterNodeService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es;\n\nimport com.didichuxing.datachannel.arius.admin.common.Triple;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.BigIndexMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ClusterMemInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.PendingTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.NodeStateVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodes.ClusterNodeInfo;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by linyunan on 2021-08-09\n */\npublic interface ESClusterNodeService {\n\n    /**\n     * 一次获取ES集群的所有节点Fs信息\n     * @param clusterName 集群名称\n     * @return 集群节点stats，key-节点ID，value-节点stats\n     */\n    Map<String, ClusterNodeStats> syncGetNodeFsStatsMap(String clusterName);\n\n    Map<String, ClusterNodeStats> syncGetNodePartStatsMap(String clusterName);\n\n    /**\n     * 获取ES集群节点ip列表\n     */\n    List<String> syncGetNodeHosts(String clusterName);\n\n    List<String> syncGetNodeIp(String clusterName);\n\n    /**\n     * 获取ES集群节点\n     */\n    Map<String, ClusterNodeInfo> syncGetNodeInfo(String clusterName);\n\n    /**\n     * 获取ES集群节点名称列表\n     */\n    List<String> syncGetNodeNames(String clusterName);\n\n    /**\n     * 获取ES集群PendingTask\n     */\n    List<PendingTask> syncGetPendingTask(String clusterName) throws ESOperateException;\n\n    Map<String/*node*/, Long /*shardNum*/> syncGetNode2ShardNumMap(String clusterName);\n\n    /**\n     * 获取ES集群大索引(大于10亿文档数)信息\n     */\n    List<BigIndexMetrics> syncGetBigIndices(String clusterName) throws ESOperateException;\n\n    /**\n     * 获取ES集群某个节点上的索引个数\n     * @param nodes 主机名或IP集合字符串 , 用逗号分隔  \n     */\n    int syncGetIndicesCount(String cluster, String nodes) throws ESOperateException;\n\n    /**\n     * 获取ES集群的内存使用统计信息\n     * @param cluster 物理集群名称\n     * @return 集群的内存使用信息统计\n     */\n    ClusterMemInfo synGetClusterMem(String cluster);\n\n    /**\n     * 同步节点磁盘使用情况\n     * 同步获取节点磁盘使用情况\n     *\n     * @param cluster 集群\n     * @return {@link Map}<{@link String}, {@link Triple}<{@link Long}, {@link Long}, {@link Double}>>\n     */\n    Map<String, Triple<Long, Long, Double>> syncGetNodesDiskUsage(String cluster);\n\n    /**\n     * node_state分析\n     * @param cluster\n     * @return\n     */\n    List<NodeStateVO> syncNodeStateAnalysis(String cluster);\n\n    /**\n     * 同步获取节点内存和磁盘\n     *\n     * @param cluster 集群\n     * @return {@link Map}<{@link String}, {@link Tuple}<{@link Long}, {@link Long}>>\n     */\n    Map<String, Tuple<Long, Long>> syncGetNodesMemoryAndDisk(String cluster);\n\n    /**\n     * 同步获取节点的cpu数量\n     *\n     * @param cluster 集群\n     * @return {@link Map}<{@link String}, {@link Integer}>\n     */\n    Map<String, Integer> syncGetNodesCpuNum(String cluster) throws ESOperateException;\n    \n    /**\n     * 同步获取节点插件元组列表\n     *\n     * @param phyCluster phy集群\n     * @return {@code List<TupleTwo<String, List<String>>>}\n     */\n    public List<TupleTwo</*node name*/String,/*plugin names*/List<String>>> syncGetNodePluginTupleList(String phyCluster) throws ESOperateException;\n    \n    /**\n     * 确定dcdr 和pipeline存在于集群中\n     *\n     * @param phyClusterName phy集群名称\n     * @return {@code TupleTwo<Boolean, Boolean>}\n     */\n    public TupleTwo</*dcdrExist*/Boolean,/*pipelineExist*/ Boolean> existDCDRAndPipelineModule(String phyClusterName);\n\n    /**\n     * WriteRejected数\n     *\n     * @param cluster 集群 WriteRejectedNum\n     * @return {@code Long}\n     */\n    public Long getWriteRejectedNum(String cluster,String node);\n\n    /**\n     * SearchRejected数\n     *\n     * @param cluster 集群 WriteRejectedNum\n     * @param node\n     * @return {@code Long}\n     */\n    public Long getSearchRejectedNum(String cluster,String node);\n\n    /**\n     * 获取nodeStats信息\n     * @param cluster\n     * @return\n     */\n    List<ClusterNodeStats> syncGetNodeStats(String cluster);}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/ESClusterService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting.ESClusterGetSettingsAllResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterTaskStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterThreadStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.PendingTaskAnalysisVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.TaskMissionAnalysisVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterConnectionStatus;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodes.ClusterNodeInfo;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodessetting.ClusterNodeSettings;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * @author d06679\n * @date 2019/5/8\n */\npublic interface ESClusterService {\n\n    /**\n     * 关闭集群re balance\n     * @param cluster 集群\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    boolean syncCloseReBalance(String cluster, Integer retryCount) throws ESOperateException;\n\n    /**\n     * 打开集群re balance\n     * @param cluster 集群\n     * @param esVersion 版本\n     * @return result\n     * @throws ESOperateException\n     */\n    boolean syncOpenReBalance(String cluster, String esVersion) throws ESOperateException;\n\n    /**\n     * 配置远端集群\n     * @param cluster 集群\n     * @param remoteCluster 远端集群\n     * @param tcpAddresses tcp地址\n     * @param retryCount 重试次数\n     * @return true/false\n     * @throws ESOperateException\n     */\n    boolean syncPutRemoteCluster(String cluster, String remoteCluster, List<String> tcpAddresses,\n                                 Integer retryCount) throws ESOperateException;\n\n    /**\n     * 判断配置否存在\n     * @param cluster 集群\n     * @param settingFlatName  setting名字\n     * @return true/false\n     */\n    boolean hasSettingExist(String cluster, String settingFlatName) throws ESOperateException;\n\n    /**\n     * 获取物理集群下各个节点的插件名称列表\n     * @param cluster\n     * @return map\n     */\n    Map<String, List<String>> syncGetNode2PluginsMap(String cluster) throws ESOperateException;\n\n    /**\n     * 获取某个集群内索引别名到索引名称的映射\n     * @param cluster\n     * @return\n     */\n    Map<String/*alias*/, Set<String>> syncGetAliasMap(String cluster);\n\n    /**\n     * 获取 某个es 集群client存活率 0 ~ 100\n     *\n     * @param cluster\n     * @param password\n     * @param clientAddresses 地址用逗号分隔: ip:port,ip:port\n     * @return\n     */\n    int syncGetClientAlivePercent(String cluster, String password, String clientAddresses);\n\n    /**\n     * 判断es client是否存活\n     *\n     * @param cluster\n     * @param password 认证信息\n     * @param clientAddress 单个地址\n     * @return\n     */\n    boolean judgeClientAlive(String cluster, String password, String clientAddress);\n\n    /**\n     * 获取集群状态信息\n     *\n     * @param clusterName\n     * @return\n     */\n    ESClusterHealthResponse syncGetClusterHealth(String clusterName) throws ESOperateException;\n\n    /**\n     * 获取集群task信息\n     *\n     * @param clusterName\n     * @return\n     */\n    List<ESClusterTaskStatsResponse> syncGetClusterTaskStats(String clusterName) throws ESOperateException;\n\n    /**\n     * 获取集群健康度\n     *\n     * @param clusterName\n     * @return\n     */\n    ClusterHealthEnum syncGetClusterHealthEnum(String clusterName) throws ESOperateException;\n\n    /**\n     * 获取集群状态信息\n     */\n    ESClusterStatsResponse syncGetClusterStats(String clusterName);\n\n    /**\n     * 获取集群配置\n     * @param cluster 集群名称\n     * @return response\n     */\n    ESClusterGetSettingsAllResponse syncGetClusterSetting(String cluster) throws ESOperateException;\n\n    /**\n     * 获取集群ip上的segment数目\n     * @param clusterName 物理集群名称\n     * @return Map<String, Integer> String表示的是实例所在的ip值，Integer表示该ip上的总的segment数目\n     */\n    Map<String, Integer> synGetSegmentsOfIpByCluster(String clusterName) throws ESOperateException;\n\n    /**\n     * 集群的持久化操作\n     * @param cluster 集群\n     * @param configMap 配置\n     * @return true/false\n     */\n    boolean syncPutPersistentConfig(String cluster, Map<String, Object> configMap);\n\n    /**\n     * 获取集群节点中的attributes可配置的信息\n     * @param cluster 物理集群名称\n     * @return 集群下所有节点的attribute的并集信息列表\n     */\n    Set<String> syncGetAllNodesAttributes(String cluster);\n\n    /**\n     * 获取全量集群节点Setting配置; key ——> 节点uuid ,value ——> ClusterNodeInfo\n     */\n    Map<String, ClusterNodeInfo> syncGetAllSettingsByCluster(String cluster) throws ESOperateException;\n\n    /**\n     * 获取部分集群节点Setting配置; key ——> 节点uuid ,value ——> ClusterNodeSettings\n     */\n    Map<String, ClusterNodeSettings> syncGetPartOfSettingsByCluster(String cluster) throws ESOperateException;\n\n    /**\n     * 获取运行集群的es版本号\n     * @param cluster 物理集群名称\n     * @return 物理集群es版本号\n     */\n    String synGetESVersionByCluster(String cluster) throws ESOperateException;\n\n    /**\n     * 检测是否为同一个集群\n     * @param password\n     * @param addresses\n     * @return\n     */\n    Result<Void> checkSameCluster(String password, List<String> addresses);\n\n    /**\n     * 获取运行的es版本号\n     * @param addresses 地址\n     * @param password 集群认证信息\n     * @return\n     */\n    String synGetESVersionByHttpAddress(String addresses, String password);\n\n    /**\n     * 检测集群账户信息\n     * @param addresses\n     * @param password\n     * @return True 正确连接集群， False 无法连接集群\n     */\n    ClusterConnectionStatus checkClusterPassword(String addresses, String password);\n\n    /**\n     * 获取集群线程池相关信息\n     * @param cluster\n     */\n    ESClusterThreadStats syncGetThreadStatsByCluster(String cluster);\n\n    @Deprecated\n    ESClusterHealthResponse syncGetClusterHealthAtIndicesLevel(String phyClusterName);\n\n    /**\n     * pending task分析\n     * @param cluster\n     * @return\n     */\n    List<PendingTaskAnalysisVO> syncPendingTaskAnalysis(String cluster);\n\n    /**\n     * task任务分析\n     * @param cluster\n     * @return\n     */\n    List<TaskMissionAnalysisVO> syncTaskMissionAnalysis(String cluster);\n\n    /**\n     * 热点线程分析\n     * @param cluster\n     * @return\n     */\n    String syncHotThreadAnalysis(String cluster);\n\n    /**\n     * 异常shard分配重试\n     * @param cluster\n     * @return\n     */\n    boolean syncAbnormalShardAllocationRetry(String cluster);\n\n    /**\n     * 清除fielddata内存\n     * @param cluster\n     * @return\n     */\n    boolean syncClearFieldDataMemory(String cluster);\n\n    /**\n     * 获取集群所有节点的tcp连接地址\n     * @param cluster\n     * @return\n     */\n    List<String> syncGetTcpAddress(String cluster);\n    \n    /**\n     * 获取连接状态\n     *\n     * @param cluster 集群phy\n     * @return boolean\n     */\n    boolean isConnectionStatus(String cluster);\n\t\n\t/**\n\t * 检查目标集群是否连接到集群\n\t *\n\t * @param cluster 当前集群的集群名称\n\t * @param targetCluster 目标集群名称\n\t * @return boolean\n\t */\n\tboolean checkTargetClusterConnected(String cluster, String targetCluster) throws ESOperateException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/ESIndexCatService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexCatCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.IndexShardInfo;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\n\npublic interface ESIndexCatService {\n\n    /**\n     * 分页获取CatIndex信息\n     *\n     * @param cluster     cluster\n     * @param index       索引名称\n     * @param health      索引健康状态\n     * @param projectId   应用id\n     * @param from        起始点\n     * @param size        当前页数量\n     * @param sortTerm    排序字段\n     * @param orderByDesc 降序标识\n     * @return Tuple<Long, List < IndexCatCell>>   key1 -> 命中总数, key2 索引列表\n     */\n    Tuple<Long, List<IndexCatCell>> syncGetCatIndexInfo(String cluster, String index, String health, String status,\n                                                        Integer projectId, Long from, Long size, String sortTerm,\n                                                        Boolean orderByDesc);\n\n    /**\n     * 更新索引删除标识\n     * @param cluster           集群名称\n     * @param indexNameList     索引名称\n     * @param retryCount        重试次数\n     * @return\n     */\n    int syncUpdateCatIndexDeleteFlag(String cluster, List<String> indexNameList, int retryCount);\n\n    /**\n     * 更新索引关闭标识\n     * @param cluster           集群名称\n     * @param indexNameList     索引名称\n     * @param status    \"open\" 开启索引标识，\"close\" 关闭索引标识\n     * @param retryCount        重试次数\n     * @return\n     */\n    int syncUpdateCatIndexStatus(String cluster, List<String> indexNameList, String status, int retryCount);\n\n    /**\n     * 获取索引shard(主)在节点中的分布详情\n     * @param cluster   集群名称\n     * @param indexName 索引名称\n     * @return\n     */\n    List<IndexShardInfo> syncGetIndexShardInfo(String cluster, String indexName) throws ESOperateException;\n\n\n    /**\n     * 同步插入文档至cat_index元数据索引\n     * @param params         入参\n     * @param retryCount     重试次数\n     * @return               Boolean\n     */\n    Boolean syncInsertCatIndex(List<IndexCatCellDTO> params, int retryCount);\n    Boolean syncUpsertCatIndex(List<IndexCatCellDTO> params, int retryCount);\n\n    /**\n     * 获取通过平台创建的索引(不经过模板)IndexCatCellDTO信息，作用于平台索引管理新建索引侧\n     */\n     List<IndexCatCell> syncGetPlatformCreateCatIndexList( Integer searchSize);\n\n    /**\n     * 根据逻辑集群获取索引\n     * @param name\n     * @return\n     */\n    List<IndexCatCellDTO> syncGetIndexByCluster(String name, Integer projectId);\n    \n    Result<List<IndexCatCellDTO>> syncGetSegmentsIndexList(String cluster, Collection<String> indexList);\n    \n    List<String> syncGetIndexListByProjectId(Integer projectId,\n                                             String clusterLogic);\n    \n    Map</*clusterPhy*/String,/*docCount*/Integer> syncGetByClusterPhyList(List<String> clusterPhyList);\n    \n    IndexCatCell syncGetCatIndexInfoById(/* clusterPhy*/String clusterPhy,/*IndexName*/ String index);\n    \n   \n    /**\n     * 通过projectId和模糊索引获取索引列表\n     *\n     * @param projectId 项目编号\n     * @param clusterLogicName 集群名称，即配置文件中的集群名称。\n     * @param index 索引名称\n     * @return List<String>\n     */\n    List<String> syncGetIndexListByProjectIdAndFuzzyIndexAndClusterLogic(Integer projectId, String clusterLogicName, String index);\n\n    List<IndexCatCell> syncGetAllCatIndexNameListByClusters(Integer searchSize,List<String> phyClusterNames);\n    /**\n     * 通过项目id、集群物理名、模糊索引获取索引列表\n     *\n     * @param clusterPhyName 集群的物理名称，例如“es-cluster-01”\n     * @param index          索引名称\n     * @return List<String>\n     */\n    List<String> syncGetIndexListByProjectIdAndFuzzyIndexAndClusterPhy( String clusterPhyName,\n                                                                       String index);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/ESIndexService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexCatCell;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.stats.IndexNodes;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.IndexConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.MultiIndexsConfig;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.function.Function;\n\n/**\n * @author d06679\n * @date 2019/4/2\n */\npublic interface ESIndexService {\n\n    /**\n     * 同步创建索引\n     * @param cluster 集群名称\n     * @param indexName 索引名称\n     * @param retryCount 重试次数\n     * @return\n     * @throws ESOperateException\n     */\n    boolean syncCreateIndex(String cluster, String indexName, int retryCount) throws ESOperateException;\n\n    /**\n     * 同步创建索引\n     * @param cluster 集群名称\n     * @param indexName 索引名称\n     * @param retryCount 重试次数\n     * @param indexConfig 索引配置\n     * @return\n     * @throws ESOperateException\n     */\n    boolean syncCreateIndex(String cluster, String indexName, IndexConfig indexConfig,\n                            int retryCount) throws ESOperateException;\n\n    /**\n     * 同步删除索引\n     * @param cluster\n     * @param indexName\n     * @param retryCount\n     * @return\n     * @throws ESOperateException\n     */\n    boolean syncDelIndex(String cluster, String indexName, int retryCount) throws ESOperateException;\n    /**\n     * 删除索引中的所有文档\n     *\n     * @param cluster ES集群的集群名称。\n     * @param expression 要删除的索引的名称。\n     * @param retryCount 重试次数，默认3次\n     */\n    boolean syncDeleteByExpression(String cluster, String expression, int retryCount) throws ESOperateException;\n\n    /**\n     * 根据表达式删除索引\n     * @param cluster    集群\n     * @param expression 表达式\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    boolean syncDeleteIndexByExpression(String cluster, String expression, int retryCount) throws ESOperateException;\n\n    /**\n     * 根据索引名称获取索引的mapping\n     * @param cluster    集群\n     * @param index      索引名称\n     * @return result\n     */\n    String syncGetIndexMapping(String cluster, String index);\n\n    /**\n     * 更新索引mapping\n     * @param cluster\n     * @param index\n     * @param mappingConfig\n     * @return\n     */\n    boolean syncUpdateIndexMapping(String cluster, String index, MappingConfig mappingConfig) throws ESOperateException;\n\n    Map<String, IndexConfig> syncBatchGetIndexConfig(String cluster, List<String> indexList);\n\n    /**\n     * 查询集群中的索引\n     * @param cluster    集群\n     * @param expression 表达式\n     * @return 索引集合\n     */\n    Set<String> syncGetIndexNameByExpression(String cluster, String expression);\n\n    /**\n     * 同步\n     * @param cluster 集群\n     * @param indices 索引列表\n     * @param settingName setting名称\n     * @param settingValue setting值\n     * @param defaultValue 默认值\n     * @return\n     */\n    boolean syncPutIndexSetting(String cluster, List<String> indices, String settingName, String settingValue,\n                                String defaultValue, int retryCount) throws ESOperateException;\n\n    /**\n     * 更新setting\n     * @param cluster\n     * @param indices\n     * @param settingMap\n     * @param retryCount\n     * @return\n     */\n    boolean syncPutIndexSetting(String cluster, List<String> indices, Map<String, String> settingMap,\n                                Integer retryCount) throws ESOperateException;\n\n    /**\n     * 批量修改多个索引的相同的多个setting\n     * @param cluster 物理集群名称\n     * @param indices 索引列表\n     * @param settings key：setting名称 value：setting数值\n     * @param retryCount 重试次数\n     */\n    boolean syncPutIndexSettings(String cluster, List<String> indices,\n                                 Map</*setting名称*/String, /*setting数值*/String> settings,\n                                 int retryCount) throws ESOperateException;\n\n    /**\n     * 获取索引信息\n     * @param cluster 集群\n     * @param expression 表达式\n     * @return result\n     */\n    Map<String, IndexNodes> syncGetIndexByExpression(String cluster, String expression);\n\n    /**\n     * 获取索引信息\n     * @param cluster 集群\n     * @param indexNames 索引列表\n     * @return result\n     */\n    Map<String, IndexNodes> syncBatchGetIndices(String cluster, Collection<String> indexNames)\n\t\t    throws ESOperateException;\n\n    /**\n     * 查询集群中的别名\n     * @param cluster    集群\n     * @param expression 表达式\n     * @return 索引集合\n     */\n    List<Tuple<String, String>> syncGetIndexAliasesByExpression(String cluster, String expression);\n\n    /**\n     * 查询集群中的别名\n     *\n     * @param cluster 集群\n     * @param indices 索引列表\n     * @return {@link Map}<{@link String}, {@link List}<{@link String}>>\n     */\n    Map<String, List<String>> syncGetIndexAliasesByIndices(String cluster, String... indices);\n\n    /**\n     * 批量删除索引\n     * @param cluster 集群\n     * @param shouldDels 索引集合\n     * @param retryCount\n     * @return int  成功的个数\n     */\n    int syncBatchDeleteIndices(String cluster, Collection<String> shouldDels, int retryCount);\n\n    /**\n     * 批量关闭索引\n     * @param cluster 集群\n     * @param shouldCloses 索引集合\n     * @param retryCount 重试次数\n     * @return boolean\n     */\n    boolean syncBatchCloseIndices(String cluster, List<String> shouldCloses, int retryCount) throws ESOperateException;\n\n    /**\n     * 批量开启索引\n     * @param cluster 集群\n     * @param shouldOpens 索引集合\n     * @param retryCount 重试次数\n     * @return boolean\n     */\n    boolean syncBatchOpenIndices(String cluster, List<String> shouldOpens, int retryCount) throws ESOperateException;\n\n    /**\n     * 删除文档\n     * @param cluster 集群\n     * @param delIndices 索引\n     * @param delQueryDsl 删除语句\n     * @return boolean\n     */\n    boolean syncDeleteByQuery(String cluster, List<String> delIndices, String delQueryDsl) throws ESOperateException;\n\n    /**\n     * 修改索引的region\n     *\n     * @param cluster\n     * @param indices\n     * @param tgtRegionId\n     * @param retryCount\n     * @param coldRegionIdFunc\n     * @return\n     * @throws ESOperateException\n     */\n    boolean syncBatchUpdateRegion(String cluster, List<String> indices, Integer tgtRegionId,\n                                  int retryCount, Function</*coldRegionId*/Integer,Result<List<ClusterRoleHost>>> coldRegionIdFunc) throws ESOperateException;\n\n    /**\n     * 修改索引只读配置\n     * @param cluster 集群\n     * @param indices 索引\n     * @param block 配置\n     * @param retryCount 重试次数\n     * @return succCount\n     */\n    boolean syncBatchBlockIndexWrite(String cluster, List<String> indices, boolean block,\n                                     int retryCount) throws ESOperateException;\n\n    /**\n     * 修改索引只写配置\n     * @param cluster 集群\n     * @param indices 索引\n     * @param block 配置\n     * @param retryCount 重试次数\n     * @return succCount\n     */\n    boolean syncBatchBlockIndexRead(String cluster, List<String> indices, boolean block,\n                                    int retryCount) throws ESOperateException;\n\n    /**\n     * 校验索引数据是否一致\n     *\n     * @param cluster1        集群1\n     * @param cluster2        集群2\n     * @param indexNames      索引名字\n     * @param indexExpression\n     * @param timeout\n     * @return true/false\n     */\n    boolean ensureDataSame(String cluster1, String cluster2, List<String> indexNames,\n        String indexExpression,Integer timeout) throws ESOperateException;\n\n    /**\n     * close and open index\n     * @param cluster 集群\n     * @param indices 索引\n     * @return result\n     */\n    boolean reOpenIndex(String cluster, List<String> indices, int retryCount) throws ESOperateException;\n\n    /**\n     * 获取索引配置\n     * @param cluster 集群名称\n     * @param name    索引名称\n     * @return\n     */\n    MultiIndexsConfig syncGetIndexConfigs(String cluster, String name);\n\n    /**\n     * 根据集群名称和索引名称获取索引setting信息\n     * @param cluster           集群名称\n     * @param indexNames        索引列表\n     * @param tryTimes          重试次数\n     * @return\n     */\n    Map<String, IndexConfig> syncGetIndexSetting(String cluster, List<String> indexNames, int tryTimes);\n\n    /**\n     * cat index\n     * @param cluster 集群\n     * @param expression 表达式\n     * @return list\n     */\n    List<CatIndexResult> syncCatIndexByExpression(String cluster, String expression);\n\n    /**\n     * 获取指定集群全量索引列表信息\n     * @param cluster  集群名称\n     * @param tryTimes          重试次数\n     * @return List<CatIndexResult>\n     */\n    List<CatIndexResult> syncCatIndex(String cluster, int tryTimes);\n\n    /**\n     * 获取索引主shard个数\n     * @param cluster\n     * @param indexName\n     * @return\n     */\n    Integer syncGetIndexPrimaryShardNumber(String cluster, String indexName);\n\n    /**\n     * 获取索引的IndexNodes信息\n     * @param cluster\n     * @param templateExp\n     * @return\n     */\n    Map<String, IndexNodes> syncGetIndexNodes(String cluster, String templateExp);\n\n    /**\n     * 获取原生集群索引名称列表,不包含特殊索引（带.开头）\n     */\n    List<String> syncGetIndexName(String clusterName) throws ESOperateException;\n\n    /**\n     * 索引是否存在\n     * @param cluster   集群名称\n     * @param indexName 索引名称\n     * @return\n     */\n    boolean syncIsIndexExist(String cluster, String indexName);\n\n    /**\n     * 获取索引checkpoint\n     * @param index                  索引名称\n     * @param stat                   索引节点信息\n     * @param checkpointEqualSeqNo   位点是否相同标识\n     * @return\n     */\n    AtomicLong syncGetTotalCheckpoint(String index, IndexNodes stat, AtomicBoolean checkpointEqualSeqNo);\n\n    /**\n     * 新增别名\n     *\n     * @param cluster       集群\n     * @param index         索引\n     * @param aliases    要添加别名\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> addAliases(String cluster, String index, List<String> aliases);\n\n    /**\n     * 删除别名\n     *\n     * @param cluster       集群\n     * @param index         索引\n     * @param aliases 要删除别名\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> deleteAliases(String cluster, String index, List<String> aliases);\n\n    /**\n     * rollover\n     *\n     * @param cluster    集群\n     * @param alias      别名\n     * @param conditions 条件\n     * @return {@link Result}<{@link Void}>\n     */\n    Result<Void> rollover(String cluster, String alias, String conditions);\n\n    /**\n     * forceMerge\n     * @param cluster\n     * @param index\n     * @param maxNumSegments\n     * @param onlyExpungeDeletes\n     * @return\n     */\n    Result<Void> forceMerge(String cluster, String index, Integer maxNumSegments, Boolean onlyExpungeDeletes);\n\n    /**\n     * shrink\n     * @param cluster\n     * @param index\n     * @param targetIndex\n     * @param config\n     * @return\n     */\n    Result<Void> shrink(String cluster, String index, String targetIndex, String config);\n\n    /**\n     * split\n     * @param cluster\n     * @param index\n     * @param targetIndex\n     * @param config\n     * @return\n     */\n    Result<Void> split(String cluster, String index, String targetIndex, String config);\n\n    /**\n     * indices分布\n     * @param cluster\n     * @return\n     */\n    List<CatIndexResult> syncIndicesDistribution(String cluster);\n\n    /**\n     * 构建索引实时数据(包含block和aliases)\n     * @param cluster          集群\n     * @param indexCatCellList 索引cat/index基本信息\n     */\n    List<IndexCatCell> buildIndexAliasesAndBlockInfo(String cluster, List<IndexCatCell> indexCatCellList);\n\n    /**\n     * 更新索引映射\n     *\n     * @param cluster       集群\n     * @param index\n     * @param mappingConfig\n     * @return boolean\n     * @throws ESOperateException\n     */\n    boolean updateIndexMapping(String cluster, String index, MappingConfig mappingConfig) throws ESOperateException;\n    \n    /**\n     * @param clusterName 集群名称\n     * @param indexName\n     * @param indexConfig\n     * @param tryTimes    试次\n     * @return boolean\n     */\n    boolean createIndexWithConfig(String clusterName, String indexName, IndexConfig indexConfig, int tryTimes)\n            throws ESOperateException;\n    \n    /**\n     * @param clusterName 集群名称\n     * @param indexName\n     * @return boolean\n     */\n    boolean deleteIndex(String clusterName, String indexName) throws ESOperateException;\n    \n    /**\n     * 返回与指定别名匹配的索引数\n     *\n     * @param cluster 集群的名称。\n     * @param alias   索引的别名\n     * @return 与别名匹配的索引数。\n     */\n    Result<Integer> countIndexByAlias(String cluster, String alias);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/ESShardCatService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.shard.ShardCatCellPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.ShardDistributionVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\n\nimport java.util.List;\n\npublic interface ESShardCatService {\n    /**\n     * shard分布\n     * @param cluster\n     * @return\n     */\n    List<ShardCatCellPO> syncShardDistribution(String cluster,long currentTimeMillis) throws ESOperateException;\n\n    /**\n     * 分页获取shard信息\n     * @param queryCluster\n     * @param queryProjectId\n     * @param keyword\n     * @param from\n     * @param size\n     * @param sortTerm\n     * @param orderByDesc\n     * @return\n     */\n    Tuple<Long, List<ShardDistributionVO>> syncGetCatShardInfo(String queryCluster, Integer queryProjectId,String keyword, long from, Long size, String sortTerm, Boolean orderByDesc);\n\n    /**\n     * 修改\n     * @param params\n     * @param retryCount\n     * @return\n     */\n    Boolean syncInsertCatShard(List<ShardCatCellPO> params, int retryCount);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/ESShardService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.MovingShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.UnAssignShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.shard.Segment;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.ShardAssignmentDescriptionVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 3/22/22\n */\npublic interface ESShardService {\n\n    /**\n     * 获取ES集群movingShard信息\n     */\n    List<MovingShardMetrics> syncGetMovingShards(String clusterName) throws ESOperateException;\n\n    /**\n     * 获取ES集群unassignShard信息\n     */\n    List<UnAssignShardMetrics> syncGetUnAssignShards(String clusterName) throws ESOperateException;\n\n    /**\n     * 获取ES集群大Shard(平台可配置，默认50G)信息\n     */\n    List<ShardMetrics> syncGetBigShards(String clusterName) throws ESOperateException;\n\n    /**\n     * 获取ES集群大Shard(50G)信息 和 小Shard(1G以内)信息\n     */\n    Tuple</*大shard列表*/List<ShardMetrics>, /*小shard列表*/List<ShardMetrics>> syncGetBigAndSmallShards(String clusterName,long configBigShard,long configSmallShard);\n\n    /**\n     * 获取集群segments信息, 不包含全量segment属性\n     * @param clusterName\n     * @return\n     */\n    List<Segment> syncGetSegments(String clusterName);\n\n    /**\n     * 获取集群segments数量统计信息\n     * @param clusterName\n     * @return\n     */\n    List<Segment> syncGetSegmentsCountInfo(String clusterName) throws ESOperateException;\n\n\n    /**\n     *  shard分配说明\n     * @param cluster\n     * @return\n     */\n    ShardAssignmentDescriptionVO syncShardAssignmentDescription(String cluster) throws ESOperateException;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/ESTemplateService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.MultiTemplatesConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.TemplateConfig;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author d06679\n * @date 2019/4/2\n */\npublic interface ESTemplateService {\n\n    /**\n     * 删除模板\n     * @param cluster 集群名字\n     * @param name 模板名字\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    boolean syncDelete(String cluster, String name, int retryCount) throws ESOperateException;\n\n    /**\n     * 修改模板rack和shard\n     * @param cluster 集群\n     * @param name 模板明细\n     * @param shard shard\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    boolean syncUpdateShard(String cluster, String name, Integer shard, Integer shardRouting,\n                            int retryCount) throws ESOperateException;\n\n    /**\n     * 创建模板, 会覆盖之前的存在的\n     * @param cluster 集群\n     * @param name 模板名字\n     * @param expression 表达式\n     * @param shard shard\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    boolean syncCreate(String cluster, String name, String expression, Integer shard, Integer shardRouting,\n                       int retryCount) throws ESOperateException;\n\n    /**\n     * 创建模板, 会覆盖之前的存在的\n     * @param settings 模板settings\n     * @param cluster 集群\n     * @param name 模板名字\n     * @param expression 表达式\n     * @param mappings 模板mappings\n     * @param retryCount 重试次数\n     * @return\n     * @throws ESOperateException\n     */\n    boolean syncCreate(Map<String, String> settings, String cluster, String name, String expression,\n                       MappingConfig mappings, int retryCount) throws ESOperateException;\n\n    /**\n     * 修改模板\n     * @param cluster 集群\n     * @param name 模板名字\n     * @param expression 表达式\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    boolean syncUpdateExpression(String cluster, String name, String expression,\n                                 int retryCount) throws ESOperateException;\n\n    /**\n     * 修改模板分片数量\n     * @param cluster 集群\n     * @param name 模板姓名\n     * @param shardNum 分片数目\n     * @param retryCount 重试次数\n     * @return\n     * @throws ESOperateException\n     */\n    boolean syncUpdateShardNum(String cluster, String name, Integer shardNum, int retryCount) throws ESOperateException;\n\n    /**\n     * 修改模板setting\n     * @param cluster 集群\n     * @param name 模板明细\n     * @param setting 配置\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    boolean syncUpsertSetting(String cluster, String name, Map<String, String> setting,\n                              int retryCount) throws ESOperateException;\n\n    /**\n     * 更新集群的设置，检查分配和分片是否正确\n     *\n     * @param cluster 集群名称\n     * @param name 索引的名称\n     * @param setting 要更新的设置\n     * @param retryCount 重试次数。\n     */\n    boolean syncUpdateSettingCheckAllocationAndShard(String cluster, String name, Map<String, String> setting,\n                                                     int retryCount) throws ESOperateException;\n    /**\n     * 跨集群拷贝模板mapping和索引\n     * @param srcCluster 源集群\n     * @param srcTemplateName 原模板\n     * @param tgtCluster 目标集群\n     * @param tgtTemplateName 目标模板\n     * @param retryCount 重试次数\n     * @return result\n     */\n    boolean syncCopyMappingAndAlias(String srcCluster, String srcTemplateName, String tgtCluster,\n                                    String tgtTemplateName, int retryCount) throws ESOperateException;\n\n    /**\n     * 同步更新物理模板配置\n     * @param cluster 集群名称\n     * @param templateName 物理模板名称\n     * @param templateConfig 模板配置\n     * @param retryCount 重试次数\n     * @return\n     * @throws ESOperateException\n     */\n    boolean syncUpdateTemplateConfig(String cluster, String templateName, TemplateConfig templateConfig,\n                                     int retryCount) throws ESOperateException;\n\n    /**\n     * 获取模板信息\n     * @param cluster 集群\n     * @param name    名字\n     * @return Config\n     */\n    TemplateConfig syncGetTemplateConfig(String cluster, String name) throws ESOperateException;\n\n    /**\n     * 获取模板的mapping配置\n     *\n     * @param clusterName\n     * @param templateName\n     * @return\n     */\n    MappingConfig syncGetMappingsByClusterName(String clusterName, String templateName) throws ESOperateException;\n\n    /**\n     * 获取模板配置\n     * @param clusterName 集群名称\n     * @param templateName 模板名称\n     * @return\n     */\n    MultiTemplatesConfig syncGetTemplates(String clusterName, String templateName) throws ESOperateException;\n\n    /**\n     * 获取所有引擎模板\n     * @param clusters 集群名\n     * @return\n     */\n    Map<String, TemplateConfig> syncGetAllTemplates(List<String> clusters) throws ESOperateException;\n\n    /**\n     * 修改模板名称\n     * @param cluster 集群\n     * @param srcName 源名称\n     * @param tgtName 现名称\n     * @return\n     */\n    boolean syncUpdateName(String cluster, String srcName, String tgtName, int retryCount) throws ESOperateException;\n\n    /**\n     * 验证模板配置是否正常\n     * @param cluster 物理集群名称\n     * @param name 模板名称\n     * @param templateConfig 模板配置\n     * @return\n     * @throws ESOperateException\n     */\n    boolean syncCheckTemplateConfig(String cluster, String name, TemplateConfig templateConfig,\n                                    int retryCount) throws ESOperateException;\n\n    /**\n     * 获取集群模板个数, 不包涵原生自带模板\n     */\n    long syncGetTemplateNum(String cluster);\n\n    /**\n     * 获取集群模板个数，兼容2.3.3低版本的集群\n     * @param cluster 物理集群名称\n     * @return 集群模板个数\n     */\n    long synGetTemplateNumForAllVersion(String cluster) throws ESOperateException;\n    \n    boolean syncGetEsClusterIsNormal(String cluster);\n    \n    /**\n     * > 检查指定集群的索引是否匹配指定的表达式和模板健康状态\n     *\n     * @param cluster 集群名称\n     * @param expression 索引的表达式，如“log-*”\n     * @param templateHealthEnum 模板的健康状态，为枚举类型，枚举值如下：\n     * @return 布尔值\n     */\n    boolean hasMatchHealthIndexByExpressionTemplateHealthEnum(String cluster, String expression,\n                                                                     TemplateHealthEnum templateHealthEnum) ;\n\n    /**\n     * 从元数据索引 arius_cat_index_info 中获取模版每个索引的health状态，从而确定模版health\n     * @param cluster 集群名称\n     * @param wildcard 通配符，如“log-*”\n     * @return  模版健康状态\n     */\n    Integer getTemplateHealthCode(String cluster, String wildcard);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/impl/ESClusterNodeServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.INSERT_PRDER;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.ONE_BILLION;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.PRIORITY;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.SOURCE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.TASKS;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.TIME_IN_QUEUE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ESHttpRequestContent.GET_PENDING_TASKS;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ESHttpRequestContent.getBigIndicesRequestContent;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ESHttpRequestContent.getShards2NodeRequestContent;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_OPERATE_TIMEOUT;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Triple;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESResponsePluginInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.BigIndexMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ClusterMemInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.IndexResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.PendingTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.NodeStateVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.PluginConstant;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpClient;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESClusterNodeDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsNodeInfoESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodes.ClusterNodeInfo;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodes.ESClusterNodesResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ESClusterNodesStatsResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.fs.FSNode;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.http.HttpNode;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.indices.CommonStat;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.indices.Segments;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.jvm.JvmMem;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.jvm.JvmNode;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.jvm.JvmThreads;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.os.LoadAverage;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.os.OsCpu;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.os.OsNode;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.threadpool.ThreadPoolNode;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.threadpool.ThreadPoolNodes;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport java.math.BigDecimal;\nimport java.math.RoundingMode;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.jetbrains.annotations.NotNull;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * Created by linyunan on 2021-08-09\n */\n@Service\npublic class ESClusterNodeServiceImpl implements ESClusterNodeService {\n    private static final ILog LOGGER = LogFactory.getLog(ESClusterNodeServiceImpl.class);\n\n    @Autowired\n    private ESOpClient        esOpClient;\n\n    @Autowired\n    private ESClusterNodeDAO  esClusterNodeDAO;\n\n    @Autowired\n    private AriusStatsNodeInfoESDAO ariusStatsNodeInfoESDAO;\n\n    @Override\n    public Map<String, ClusterNodeStats> syncGetNodeFsStatsMap(String clusterName) {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        if (esClient == null) {\n            LOGGER.error(\n                \"class=ESClusterNodeServiceImpl||method=syncGetNodeFsStatsMap||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            return Maps.newHashMap();\n        }\n\n        ESClusterNodesStatsResponse response = esClient.admin().cluster().prepareNodeStats().setFs(true).execute()\n            .actionGet(30, TimeUnit.SECONDS);\n\n        return response.getNodes();\n    }\n\n    @Override\n    public Map<String, ClusterNodeStats> syncGetNodePartStatsMap(String clusterName) {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        if (esClient == null) {\n            LOGGER.error(\n                \"class=ESClusterNodeServiceImpl||method=syncGetNodeFsStatsMap||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            return Maps.newHashMap();\n        }\n\n        ESClusterNodesStatsResponse response = esClient.admin().cluster().prepareNodeStats().setFs(true).setOs(true)\n            .setJvm(true).setThreadPool(true).level(\"node\").execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n        return response.getNodes();\n    }\n\n    @Override\n    public List<String> syncGetNodeHosts(String clusterName) {\n        return syncGetNodeInfo(clusterName).values().stream().map(ClusterNodeInfo::getHost)\n            .collect(Collectors.toList());\n    }\n\n    @Override\n    public List<String> syncGetNodeIp(String clusterName) {\n        return syncGetNodeInfo(clusterName).values().stream().map(ClusterNodeInfo::getIp).collect(Collectors.toList());\n    }\n\n    @Override\n    public Map<String, ClusterNodeInfo> syncGetNodeInfo(String clusterName) {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        if (esClient == null) {\n            LOGGER.error(\n                \"class=ESClusterNodeServiceImpl||method=syncGetNodeHosts||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            return Maps.newHashMap();\n        }\n\n        ESClusterNodesResponse esClusterNodesResponse = esClient.admin().cluster().prepareNodes().addFlag(\"http\").get();\n        if (null == esClusterNodesResponse || null == esClusterNodesResponse.getNodes()) {\n            return Maps.newHashMap();\n        }\n\n        return esClusterNodesResponse.getNodes();\n    }\n\n    @Override\n    public List<String> syncGetNodeNames(String clusterName) {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        if (esClient == null) {\n            LOGGER.error(\n                \"class=ESClusterNodeServiceImpl||method=syncGetNodeNames||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            return Lists.newArrayList();\n        }\n\n        ESClusterNodesResponse esClusterNodesResponse = esClient.admin().cluster().prepareNodes().get();\n        if (null == esClusterNodesResponse || null == esClusterNodesResponse.getNodes()) {\n            return Lists.newArrayList();\n        }\n\n        return esClusterNodesResponse.getNodes().values().stream().map(ClusterNodeInfo::getName)\n            .collect(Collectors.toList());\n    }\n\n    @Override\n    public List<PendingTask> syncGetPendingTask(String clusterName) throws ESOperateException {\n        DirectResponse directResponse = esClusterNodeDAO.getDirectResponse(clusterName, \"Get\", GET_PENDING_TASKS);\n        List<PendingTask> pendingTasks = Lists.newArrayList();\n        if (directResponse.getRestStatus() == RestStatus.OK\n            && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n\n            JSONObject jsonObject = JSON.parseObject(directResponse.getResponseContent());\n            if (null != jsonObject && null != jsonObject.getJSONArray(TASKS)) {\n                JSONArray pendingTasksObj = jsonObject.getJSONArray(TASKS);\n                for (int i = 0; i < pendingTasksObj.size(); i++) {\n                    PendingTask pendingTask = new PendingTask();\n                    setPendingTaskField(pendingTasksObj, i, pendingTask);\n                    pendingTasks.add(pendingTask);\n                }\n            }\n        }\n\n        return pendingTasks;\n    }\n\n    private void setPendingTaskField(JSONArray pendingTasksObj, int i, PendingTask pendingTask) {\n        if (null != pendingTasksObj.getJSONObject(i).get(TIME_IN_QUEUE)) {\n            pendingTask.setTimeInQueue(pendingTasksObj.getJSONObject(i).get(TIME_IN_QUEUE).toString());\n        }\n\n        if (null != pendingTasksObj.getJSONObject(i).get(SOURCE)) {\n            pendingTask.setSource(pendingTasksObj.getJSONObject(i).get(SOURCE).toString());\n        }\n\n        if (null != pendingTasksObj.getJSONObject(i).get(PRIORITY)) {\n            pendingTask.setPriority(pendingTasksObj.getJSONObject(i).get(PRIORITY).toString());\n        }\n\n        if (null != pendingTasksObj.getJSONObject(i).get(INSERT_PRDER)) {\n            pendingTask.setInsertOrder(Long.valueOf(pendingTasksObj.getJSONObject(i).get(INSERT_PRDER).toString()));\n        }\n    }\n\n    @Override\n    public Map<String/*node*/, Long /*shardNum*/> syncGetNode2ShardNumMap(String clusterName) {\n        String bigShardsRequestContent = getShards2NodeRequestContent(\"20s\");\n        DirectResponse directResponse = null;\n        try {\n            directResponse = esClusterNodeDAO.getDirectResponse(clusterName, \"Get\", bigShardsRequestContent);\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=ESClusterNodeServiceImpl||method=syncGetNode2ShardNumMap||clusterName={}||errMsg=fail to get directresponse\",\n                    clusterName);\n            return Maps.newHashMap();\n        }\n\n        Map<String/*node*/, Long /*shardNum*/> node2ShardNumMap = Maps.newHashMap();\n        if (directResponse.getRestStatus() == RestStatus.OK\n            && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n            List<ShardMetrics> bigShardsMetricsFromES = ConvertUtil\n                .str2ObjArrayByJson(directResponse.getResponseContent(), ShardMetrics.class);\n\n            Map<String, List<ShardMetrics>> node2ShardMetricsListMap = ConvertUtil\n                .list2MapOfList(bigShardsMetricsFromES, ShardMetrics::getNode, ShardMetrics -> ShardMetrics);\n\n            node2ShardMetricsListMap.forEach((key, value) -> {\n                node2ShardNumMap.put(key, (long) value.size());\n            });\n            return node2ShardNumMap;\n        }\n\n        return node2ShardNumMap;\n    }\n\n    @Override\n    public List<BigIndexMetrics> syncGetBigIndices(String clusterName) throws ESOperateException {\n\n        String indicesRequestContent = getBigIndicesRequestContent(\"20s\");\n\n        DirectResponse directResponse = esClusterNodeDAO.getDirectResponse(clusterName, \"Get\", indicesRequestContent);\n\n        List<BigIndexMetrics> bigIndicesMetrics = Lists.newArrayList();\n\n        List<IndexResponse> indexResponses;\n\n        if (directResponse.getRestStatus() == RestStatus.OK\n            && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n\n            indexResponses = ConvertUtil.str2ObjArrayByJson(directResponse.getResponseContent(), IndexResponse.class);\n\n            indexResponses.stream().filter(index -> index.getDc() > ONE_BILLION).forEach(r -> {\n                BigIndexMetrics bigIndexMetrics = new BigIndexMetrics();\n                bigIndexMetrics.setIndexName(r.getIndex());\n                bigIndexMetrics.setDocsCount(r.getDc());\n                bigIndicesMetrics.add(bigIndexMetrics);\n            });\n        }\n        return bigIndicesMetrics;\n    }\n\n    @Override\n    public int syncGetIndicesCount(String cluster, String nodes) throws ESOperateException {\n        return esClusterNodeDAO.getIndicesCount(cluster, nodes);\n    }\n\n    @Override\n    public ClusterMemInfo synGetClusterMem(String cluster) {\n        ESClient esClient = esOpClient.getESClient(cluster);\n        if (esClient == null) {\n            LOGGER.error(\n                \"class=ESClusterNodeServiceImpl||method=synGetClusterMem||clusterName={}||errMsg=esClient is null\",\n                cluster);\n            return null;\n        }\n\n        // 获取nodes中的os信息\n        ESClusterNodesStatsResponse response = esClient.admin().cluster().prepareNodeStats().setOs(true).execute()\n            .actionGet(30, TimeUnit.SECONDS);\n\n        // 构建集群的内存使用信息对象\n        ClusterMemInfo clusterMemInfo = ClusterMemInfo.builder().memFree(0L).memUsed(0L).memTotal(0L).build();\n        Map<String, ClusterNodeStats> clusterNodeStatsMap = response.getNodes();\n        if (MapUtils.isEmpty(clusterNodeStatsMap)) {\n            return clusterMemInfo;\n        }\n\n        // 统计所有的节点的内存信息合成为集群的内存使用信息\n        clusterNodeStatsMap.values().stream().map(ClusterNodeStats::getOs).map(OsNode::getMem).forEach(osMem -> {\n            clusterMemInfo.setMemFree(clusterMemInfo.getMemFree() + osMem.getFreeInBytes());\n            clusterMemInfo.setMemTotal(clusterMemInfo.getMemTotal() + osMem.getTotalInBytes());\n            clusterMemInfo.setMemUsed(clusterMemInfo.getMemUsed() + osMem.getUsedInBytes());\n        });\n\n        // 计算集群总的内存使用和空闲的百分比信息，保留小数点后3位\n        BigDecimal memFreeDec = new BigDecimal(clusterMemInfo.getMemFree());\n        BigDecimal totalSizeDec = new BigDecimal(clusterMemInfo.getMemTotal());\n        clusterMemInfo.setMemFreePercent(memFreeDec.divide(totalSizeDec, 5, RoundingMode.HALF_UP).doubleValue() * 100);\n        clusterMemInfo.setMemUsedPercent(100 - clusterMemInfo.getMemFreePercent());\n\n        return clusterMemInfo;\n    }\n\n    @Override\n    public Map<String, Triple<Long, Long, Double>> syncGetNodesDiskUsage(String cluster) {\n        Map<String, Triple<Long, Long, Double>> diskUsageMap = new HashMap<>();\n        List<ClusterNodeStats> nodeStatsList = null;\n        try {\n            nodeStatsList = esClusterNodeDAO.syncGetNodesStats(cluster);\n        } catch (ESOperateException e) {\n            LOGGER.error(\n                \"class=ESClusterNodeServiceImpl||method=syncGetNodesDiskUsage||clusterName={}\",\n                cluster,e);\n            return diskUsageMap;\n        }\n    \n        if (CollectionUtils.isNotEmpty(nodeStatsList)) {\n            // 遍历节点，获得节点和对应的磁盘使用率\n            nodeStatsList.forEach(nodeStats -> {\n\n                FSNode fsNode = nodeStats.getFs();\n                String nodeName = nodeStats.getName();\n                long totalFsBytes = fsNode.getTotal().getTotalInBytes();\n                long usageFsBytes = totalFsBytes - fsNode.getTotal().getFreeInBytes();\n                //Triple<diskTotal, diskUsage, diskUsagePercent>\n                Triple<Long, Long, Double> triple = new Triple<>();\n                if (totalFsBytes > 0) {\n                    triple.setV1(totalFsBytes);\n                }\n                if (usageFsBytes >= 0 && usageFsBytes <= totalFsBytes) {\n                    triple.setV2(usageFsBytes);\n                }\n\n                if (StringUtils.isNotBlank(nodeName) && totalFsBytes > 0 && usageFsBytes >= 0\n                    && usageFsBytes <= totalFsBytes) {\n                    triple.setV3(BigDecimal.valueOf(usageFsBytes)\n                        .divide(BigDecimal.valueOf(totalFsBytes), 5, RoundingMode.HALF_UP).doubleValue());\n                }\n                diskUsageMap.put(nodeName, triple);\n            });\n        }\n        return diskUsageMap;\n    }\n\n    @Override\n    public Map<String, Tuple<Long, Long>> syncGetNodesMemoryAndDisk(String cluster) {\n        Map<String, Tuple<Long, Long>> node2MemAndDiskMap = Maps.newHashMap();\n        List<ClusterNodeStats> nodeStatsList;\n        try {\n            nodeStatsList = esClusterNodeDAO.syncGetNodesStats(cluster);\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class={}||method=syncGetNodesDiskUsage||clusterName={}\", getClass().getSimpleName(), cluster,\n                    e);\n            return node2MemAndDiskMap;\n        }\n    \n        if (CollectionUtils.isNotEmpty(nodeStatsList)) {\n            // 遍历节点，获得节点和对应的磁盘使用率\n            nodeStatsList.forEach(nodeStats -> {\n                String nodeName = nodeStats.getName();\n\n                FSNode fsNode = nodeStats.getFs();\n                long totalFsBytes = fsNode.getTotal().getTotalInBytes();\n                long totalOsMemBytes = nodeStats.getOs().getMem().getTotalInBytes();\n                if (totalFsBytes <= 0 || totalOsMemBytes <= 0) {\n                    return;\n                }\n                //Tuple<memoryBytes, diskBytes>\n                Tuple<Long, Long> tuple = new Tuple<>();\n                tuple.setV1(totalOsMemBytes);\n                tuple.setV2(totalFsBytes);\n\n                node2MemAndDiskMap.put(nodeName, tuple);\n            });\n        }\n        return node2MemAndDiskMap;\n    }\n\n    @Override\n    public Map<String, Integer> syncGetNodesCpuNum(String cluster) throws ESOperateException {\n        Map<String, Integer> node2CpuNumMap = Maps.newHashMap();\n        //这里直接使用 esClient.admin().cluster().nodes(new ESClusterNodesRequest().flag(\"os\")).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);无法正确获取到数据，所以使用\n        DirectResponse directResponse = esClusterNodeDAO.getDirectResponse(cluster, \"GET\", \"/_nodes/os\");\n\n        if (directResponse.getRestStatus() == RestStatus.OK\n            && StringUtils.isNotBlank(directResponse.getResponseContent())) {\n            JSONObject nodes = null;\n            try {\n                JSONObject jsonObject = JSONObject.parseObject(directResponse.getResponseContent());\n                nodes = jsonObject.getJSONObject(\"nodes\");\n            } catch (Exception e) {\n                // pass \n            }\n            Optional.ofNullable(nodes).ifPresent(nodesMap -> {\n                nodesMap.values().forEach(obj -> {\n                    Integer cpuNum = null;\n                    String nodeName = null;\n                    try {\n                        JSONObject nodeInfo = JSONObject.parseObject(JSONObject.toJSONString(obj));\n                        nodeName = nodeInfo.getString(\"name\");\n                        cpuNum = nodeInfo.getJSONObject(\"os\").getInteger(\"available_processors\");\n                    } catch (Exception e) {\n                        // pass\n                    }\n                    if (StringUtils.isNotBlank(nodeName) && null != cpuNum && cpuNum > 0) {\n                        node2CpuNumMap.put(nodeName, cpuNum);\n                    }\n\n                });\n            });\n        }\n\n        return node2CpuNumMap;\n    }\n    \n    /**\n     * 同步获取节点插件元组列表\n     *\n     * @param phyCluster phy集群\n     * @return {@code List<TupleTwo<String, List<String>>>}\n     */\n    @Override\n    public List<TupleTwo<String, List<String>>> syncGetNodePluginTupleList(String phyCluster) throws ESOperateException {\n        return esClusterNodeDAO.syncGetNodesPlugins(phyCluster);\n    }\n    \n    /**\n     * @param phyClusterName\n     * @return\n     */\n    @Override\n    public TupleTwo<Boolean, Boolean> existDCDRAndPipelineModule(String phyClusterName) {\n        //获取物理集群侧的插件列表\n        final List<TupleTwo<String, List<String>>> syncGetNodePluginTupleList;\n        try {\n            syncGetNodePluginTupleList = syncGetNodePluginTupleList(\n                    phyClusterName);\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=ESClusterNodeServiceImpl||method=existDCDRAndPipelineModule||clusterName={}||errMsg=fail to syncGetNodePluginTupleList\",\n                    phyClusterName,e);\n            return Tuples.of(Boolean.FALSE, Boolean.FALSE);\n        }\n        if (CollectionUtils.isEmpty(syncGetNodePluginTupleList)) {\n            return Tuples.of(Boolean.FALSE, Boolean.FALSE);\n        }\n        //这里对于一个集群来说，不需要校验全部节点是否是存在dcdr和pipeline的;这里属于内置的module，默认拿一个验证即可\n        final TupleTwo<String, List<String>> nodeNamePlugins = syncGetNodePluginTupleList.get(0);\n        if (CollectionUtils.isEmpty(nodeNamePlugins.v2())) {\n            return Tuples.of(Boolean.FALSE, Boolean.FALSE);\n        }\n        return Tuples.of(nodeNamePlugins.v2().contains(PluginConstant.DIDI_CROSS_DATACENTER_REPLICATION),\n                nodeNamePlugins.v2().contains(PluginConstant.INGEST_INDEX_TEMPLATE));\n    }\n\n    @Override\n    public Long getWriteRejectedNum(String cluster, String node) {\n        return ariusStatsNodeInfoESDAO.getWriteRejectedNum(cluster, node);\n    }\n\n    @Override\n    public Long getSearchRejectedNum(String cluster, String node) {\n        return ariusStatsNodeInfoESDAO.getSearchRejectedNum(cluster, node);\n    }\n\n    @Override\n    public List<ClusterNodeStats> syncGetNodeStats(String cluster) {\n        return esClusterNodeDAO.getNodeState(cluster);\n    }\n\n\n    /*********************************************private******************************************/\n\n    @Override\n    public List<NodeStateVO> syncNodeStateAnalysis(String cluster) {\n        List<ClusterNodeStats> nodeStats = esClusterNodeDAO.getNodeState(cluster);\n        return nodeStats.stream().map(this::buildNodeStateVO).collect(Collectors.toList());\n    }\n\n    @NotNull\n    private NodeStateVO buildNodeStateVO(ClusterNodeStats nodeStat) {\n        NodeStateVO vo = new NodeStateVO();\n        vo.setNodeName(nodeStat.getName());\n        Optional.of(nodeStat).map(ClusterNodeStats::getIndices).map(CommonStat::getSegments).map(Segments::getMemoryInBytes).ifPresent(vo::setSegmentsMemory);\n        Optional.of(nodeStat).map(ClusterNodeStats::getOs).map(OsNode::getCpu).map(OsCpu::getPercent).ifPresent(vo::setOsCpu);\n        Optional.of(nodeStat).map(ClusterNodeStats::getOs).map(OsNode::getCpu).map(OsCpu::getLoadAverage).map(LoadAverage::getOneM).ifPresent(vo::setLoadAverage1m);\n        Optional.of(nodeStat).map(ClusterNodeStats::getOs).map(OsNode::getCpu).map(OsCpu::getLoadAverage).map(LoadAverage::getFiveM).ifPresent(vo::setLoadAverage5m);\n        Optional.of(nodeStat).map(ClusterNodeStats::getOs).map(OsNode::getCpu).map(OsCpu::getLoadAverage).map(LoadAverage::getFifteenM).ifPresent(vo::setLoadAverage15m);\n        Optional.of(nodeStat).map(ClusterNodeStats::getJvm).map(JvmNode::getMem).map(JvmMem::getHeapUsedPercent).ifPresent(vo::setJvmHeapUsedPercent);\n        Optional.of(nodeStat).map(ClusterNodeStats::getJvm).map(JvmNode::getThreads).map(JvmThreads::getCount).ifPresent(vo::setThreadsCount);\n        Optional.of(nodeStat).map(ClusterNodeStats::getHttp).map(HttpNode::getCurrentOpen).ifPresent(vo::setCurrentOpen);\n        Optional.of(nodeStat).map(ClusterNodeStats::getThreadPool).map(ThreadPoolNodes::getWrite).map(ThreadPoolNode::getActive).ifPresent(vo::setThreadPoolWriteActive);\n        Optional.of(nodeStat).map(ClusterNodeStats::getThreadPool).map(ThreadPoolNodes::getWrite).map(ThreadPoolNode::getQueue).ifPresent(vo::setThreadPoolWriteQueue);\n        Optional.of(nodeStat).map(ClusterNodeStats::getThreadPool).map(ThreadPoolNodes::getWrite).map(ThreadPoolNode::getRejected).ifPresent(vo::setThreadPoolWriteReject);\n        Optional.of(nodeStat).map(ClusterNodeStats::getThreadPool).map(ThreadPoolNodes::getSearch).map(ThreadPoolNode::getActive).ifPresent(vo::setThreadPoolSearchActive);\n        Optional.of(nodeStat).map(ClusterNodeStats::getThreadPool).map(ThreadPoolNodes::getSearch).map(ThreadPoolNode::getRejected).ifPresent(vo::setThreadPoolSearchReject);\n        Optional.of(nodeStat).map(ClusterNodeStats::getThreadPool).map(ThreadPoolNodes::getSearch).map(ThreadPoolNode::getQueue).ifPresent(vo::setThreadPoolSearchQueue);\n        Optional.of(nodeStat).map(ClusterNodeStats::getThreadPool).map(ThreadPoolNodes::getManagement).map(ThreadPoolNode::getActive).ifPresent(vo::setThreadPoolManagementActive);\n        Optional.of(nodeStat).map(ClusterNodeStats::getThreadPool).map(ThreadPoolNodes::getManagement).map(ThreadPoolNode::getRejected).ifPresent(vo::setThreadPoolManagementReject);\n        Optional.of(nodeStat).map(ClusterNodeStats::getThreadPool).map(ThreadPoolNodes::getManagement).map(ThreadPoolNode::getQueue).ifPresent(vo::setThreadPoolManagementQueue);\n        return vo;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/impl/ESClusterServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_OPERATE_TIMEOUT;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.VERSION;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.VERSION_INNER_NUMBER;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.VERSION_NUMBER;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.NodeAttrInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting.ESClusterGetSettingsAllResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ECSegmentOnIp;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterTaskStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterThreadStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.stats.ESClusterThreadPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.PendingTaskAnalysisVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.TaskMissionAnalysisVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterConnectionStatus;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESClusterDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodes.ClusterNodeInfo;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodessetting.ClusterNodeSettings;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodessetting.ESClusterNodesSettingResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.getalias.ESIndicesGetAliasResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport java.net.InetAddress;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.compress.utils.Sets;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.common.transport.InetSocketTransportAddress;\nimport org.elasticsearch.common.transport.TransportAddress;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class ESClusterServiceImpl implements ESClusterService {\n\n    private static final ILog LOGGER                = LogFactory.getLog(ESClusterServiceImpl.class);\n\n    @Autowired\n    private ESClusterDAO      esClusterDAO;\n\n    private final String      ACKNOWLEDGED          = \"acknowledged\";\n    private final String      SHARDS                = \"_shards\";\n    private final String      FAILED                = \"failed\";\n    private final String      DESCRIPTION           = \"description\";\n    private final String      START_TIME_IN_MILLIS  = \"start_time_in_millis\";\n    private final String      RUNNING_TIME_IN_NANOS = \"running_time_in_nanos\";\n    private final String      ACTION                = \"action\";\n    private final String      NAME                  = \"name\";\n    private final String      NODES                 = \"nodes\";\n    private final String      TASKS                 = \"tasks\";\n\n    /**\n     * 关闭集群re balance\n     * @param cluster    集群\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean syncCloseReBalance(String cluster, Integer retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"syncCloseReBalance\", retryCount,\n            () -> esClusterDAO.configReBalanceOperate(cluster, \"none\"));\n    }\n\n    /**\n     * 打开集群rebalance\n     *\n     * @param cluster   集群\n     * @param esVersion 版本\n     * @return result\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean syncOpenReBalance(String cluster, String esVersion) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"syncOpenReBalance\", 3,\n            () -> esClusterDAO.configReBalanceOperate(cluster, \"all\"));\n    }\n\n    /**\n     * 配置远端集群\n     *\n     * @param cluster       集群\n     * @param remoteCluster 远端集群\n     * @param tcpAddresses  tcp地址\n     * @param retryCount    重试次数\n     * @return true/false\n     */\n    @Override\n    public boolean syncPutRemoteCluster(String cluster, String remoteCluster, List<String> tcpAddresses,\n                                        Integer retryCount) throws ESOperateException {\n        if (CollectionUtils.isEmpty(tcpAddresses)) { return false;}\n\n        return ESOpTimeoutRetry.esRetryExecute(\"syncPutRemoteCluster\", retryCount,\n            () -> esClusterDAO.putPersistentRemoteClusters(cluster,\n                String.format(ESOperateConstant.REMOTE_CLUSTER_FORMAT, remoteCluster), tcpAddresses));\n    }\n\n    /**\n     * 判断配置否存在\n     *\n     * @param cluster         集群\n     * @param settingFlatName setting名字\n     * @return true/false\n     */\n    @Override\n    public boolean hasSettingExist(String cluster, String settingFlatName) throws ESOperateException {\n        Map<String, Object> clusterSettingMap = esClusterDAO.getPersistentClusterSettings(cluster);\n        if (null == clusterSettingMap) {\n            return false;\n        }\n        return clusterSettingMap.containsKey(settingFlatName);\n    }\n\n    @Override\n    public Map<String, List<String>> syncGetNode2PluginsMap(String cluster) throws ESOperateException {\n        return esClusterDAO.getNode2PluginsMap(cluster, 3);\n    }\n\n    /**\n     * 获取某个集群内索引别名到索引名称的映射\n     *\n     * @param cluster\n     * @return\n     */\n    @Override\n    public Map<String/*alias*/, Set<String>> syncGetAliasMap(String cluster) {\n        Map<String, Set<String>> ret = new HashMap<>();\n\n        try {\n            ESIndicesGetAliasResponse response = esClusterDAO.getClusterAlias(cluster, 3);\n            if (response == null || response.getM() == null) {\n                return ret;\n            }\n            for (String index : response.getM().keySet()) {\n                for (String alias : response.getM().get(index).getAliases().keySet()) {\n                    if (!ret.containsKey(alias)) {\n                        ret.put(alias, new HashSet<>());\n                    }\n                    ret.get(alias).add(index);\n                }\n            }\n            return ret;\n        } catch (Exception t) {\n            LOGGER.error(\"class=ClusterClientPool||method=syncGetAliasMap||clusterName={}||errMsg=fail to get alias\",\n                cluster, t);\n            return ret;\n        }\n    }\n\n    @Override\n    public int syncGetClientAlivePercent(String cluster, String password, String clientAddresses) {\n        if (null == cluster || StringUtils.isBlank(clientAddresses)) {\n            return 0;\n        }\n\n        List<String> addresses = ListUtils.string2StrList(clientAddresses);\n\n        int alive = 0;\n        for (String address : addresses) {\n            boolean isAlive = judgeClientAlive(cluster, password, address);\n            if (isAlive) {\n                alive++;\n            }\n        }\n\n        return alive * 100 / addresses.size();\n    }\n\n    /**\n     * 判断es client是否存活\n     *\n     * @param cluster\n     * @param address\n     * @return\n     */\n    @Override\n    public boolean judgeClientAlive(String cluster, String password, String address) {\n\n        String[] hostAndPortStr = StringUtils.split(address, \":\");\n        if (null == hostAndPortStr || hostAndPortStr.length <= 1) {\n            LOGGER.info(\"class=ClusterClientPool||method=getNotSniffESClient||addresses={}||msg=clusterClientError\",\n                address);\n            return false;\n        }\n\n        String host = hostAndPortStr[0];\n        String port = hostAndPortStr[1];\n        List<InetSocketTransportAddress> transportAddresses = Lists.newArrayList();\n        ESClient esClient = new ESClient();\n        try {\n            transportAddresses.add(new InetSocketTransportAddress(InetAddress.getByName(host), Integer.parseInt(port)));\n            esClient.addTransportAddresses(transportAddresses.toArray(new TransportAddress[0]));\n            esClient.setClusterName(cluster);\n            if (StringUtils.isNotBlank(password)) {\n                esClient.setPassword(password);\n            }\n            esClient.start();\n\n            ESClusterHealthResponse response = esClient.admin().cluster().prepareHealth().execute().actionGet(30,\n                TimeUnit.SECONDS);\n            return !response.isTimedOut();\n        } catch (Exception e) {\n            esClient.close();\n            LOGGER.error(\n                \"class=ESClusterServiceImpl||method=judgeClientAlive||cluster={}||client={}||msg=judgeAlive is excepjudgeClientAlivetion!\",\n                cluster, address, e);\n            return false;\n        } finally {\n            esClient.close();\n        }\n    }\n\n    @Override\n    public ESClusterHealthResponse syncGetClusterHealth(String clusterName) throws ESOperateException {\n        return esClusterDAO.getClusterHealth(clusterName, 3);\n    }\n\n    @Override\n    public List<ESClusterTaskStatsResponse> syncGetClusterTaskStats(String clusterName) throws ESOperateException {\n        return esClusterDAO.getClusterTaskStats(clusterName);\n    }\n\n    @Override\n    public ClusterHealthEnum syncGetClusterHealthEnum(String clusterName) throws ESOperateException {\n        ESClusterHealthResponse clusterHealthResponse = esClusterDAO.getClusterHealth(clusterName, 3);\n\n        ClusterHealthEnum clusterHealthEnum = ClusterHealthEnum.UNKNOWN;\n        if (clusterHealthResponse != null) {\n            clusterHealthEnum = ClusterHealthEnum.valuesOf(clusterHealthResponse.getStatus());\n        }\n        return clusterHealthEnum;\n    }\n\n    @Override\n    public ESClusterStatsResponse syncGetClusterStats(String clusterName) {\n        try {\n            return esClusterDAO.getClusterStats(clusterName);\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=ESClusterServiceImpl||method=syncGetClusterStats||clusterName={}||errMsg=fail to get cluster stats\",\n                    clusterName);\n            return null;\n        }\n    }\n\n    @Override\n    public ESClusterGetSettingsAllResponse syncGetClusterSetting(String cluster) throws ESOperateException {\n        return esClusterDAO.getClusterSetting(cluster);\n    }\n\n    @Override\n    public Map<String, Integer> synGetSegmentsOfIpByCluster(String clusterName) throws ESOperateException {\n        Map<String, Integer> segmentsOnIpMap = Maps.newHashMap();\n        for (ECSegmentOnIp ecSegmentsOnIp : esClusterDAO.getSegmentsOfIpByCluster(clusterName)) {\n            if (segmentsOnIpMap.containsKey(ecSegmentsOnIp.getIp())) {\n                Integer newSegments = segmentsOnIpMap.get(ecSegmentsOnIp.getIp())\n                                      + Integer.parseInt(ecSegmentsOnIp.getSegment());\n                segmentsOnIpMap.put(ecSegmentsOnIp.getIp(), newSegments);\n            } else {\n                segmentsOnIpMap.put(ecSegmentsOnIp.getIp(), Integer.valueOf(ecSegmentsOnIp.getSegment()));\n            }\n        }\n        return segmentsOnIpMap;\n    }\n\n    @Override\n    public boolean syncPutPersistentConfig(String cluster, Map<String, Object> configMap) {\n        try {\n            return esClusterDAO.putPersistentConfig(cluster, configMap);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterServiceImpl||method=syncPutPersistentConfig||clusterName={}\", cluster,e);\n            return false;\n        }\n    }\n\n    @Override\n    public String synGetESVersionByCluster(String cluster) throws ESOperateException {\n        return esClusterDAO.getESVersionByCluster(cluster, 3);\n    }\n\n    @Override\n    public Map<String, ClusterNodeInfo> syncGetAllSettingsByCluster(String cluster) throws ESOperateException {\n        return esClusterDAO.getAllSettingsByCluster(cluster, 3);\n    }\n\n    @Override\n    public Map<String, ClusterNodeSettings> syncGetPartOfSettingsByCluster(String cluster) throws ESOperateException {\n        return esClusterDAO.getPartOfSettingsByCluster(cluster, 3);\n    }\n\n    @Override\n    public Set<String> syncGetAllNodesAttributes(String cluster) {\n        Set<String> nodeAttributes = Sets.newHashSet();\n        List<NodeAttrInfo> nodeAttrInfos = esClusterDAO.syncGetAllNodesAttributes(cluster);\n        if (CollectionUtils.isEmpty(nodeAttrInfos)) {\n            return nodeAttributes;\n        }\n\n        //对于所有的节点属性进行去重的操作\n        nodeAttrInfos.forEach(nodeAttrInfo -> nodeAttributes.add(nodeAttrInfo.getAttribute()));\n\n        return nodeAttributes;\n    }\n\n    @Override\n    public Result<Void> checkSameCluster(String password, List<String> addresses) {\n        Set<String> clusters = new HashSet<>();\n        for (String address : addresses) {\n            ESClient client = new ESClient();\n            try {\n                if (StringUtils.isNotBlank(password)) {\n                    client.setPassword(password);\n                }\n                client.addTransportAddresses(address);\n                client.start();\n                ESClusterNodesSettingResponse response = client.admin().cluster().prepareNodesSetting().execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n                if (RestStatus.OK.getStatus() == response.getRestStatus().getStatus()) {\n                    clusters.add(response.getClusterName());\n                }\n            } catch (Exception e) {\n                LOGGER.error(\n                    \"class=ESClusterServiceImpl||method=getClusterRackByHttpAddress||msg=get rack error||httpAddress={}||msg=client start error\",\n                    addresses);\n            } finally {\n                client.close();\n            }\n        }\n        return clusters.size() > 1 ? Result.buildFail() : Result.buildSucc();\n    }\n\n    @Override\n    public String synGetESVersionByHttpAddress(String addresses, String password) {\n        ESClient client = new ESClient();\n        client.addTransportAddresses(addresses);\n\n        if (StringUtils.isNotBlank(password)) {\n            client.setPassword(password);\n        }\n        String esVersion = null;\n        try {\n            client.start();\n            DirectRequest directRequest = new DirectRequest(\"GET\", \"\");\n            DirectResponse directResponse = client.direct(directRequest).actionGet(30, TimeUnit.SECONDS);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                JSONObject version = JSONObject.parseObject(directResponse.getResponseContent()).getJSONObject(VERSION);\n                esVersion = version.getString(VERSION_NUMBER);\n                if (version.containsKey(VERSION_INNER_NUMBER)) {\n                    String innerVersion = version.getString(VERSION_INNER_NUMBER).split(\"\\\\.\")[0].trim();\n                    esVersion = Strings.isNullOrEmpty(innerVersion) ? esVersion : esVersion + \".\" + innerVersion;\n                }\n            }\n            return esVersion;\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=ESClusterServiceImpl||method=synGetESVersionByHttpAddress||address={}||mg=get es segments fail\",\n                addresses, e);\n            return null;\n        } finally {\n            client.close();\n        }\n    }\n\n    @Override\n    public ClusterConnectionStatus checkClusterPassword(String addresses, String password) {\n        ESClient client = new ESClient();\n        client.addTransportAddresses(addresses);\n        if (StringUtils.isNotBlank(password)) {\n            client.setPassword(password);\n        }\n\n        try {\n            client.start();\n            DirectRequest directRequest = new DirectRequest(\"GET\", \"\");\n            client.direct(directRequest).actionGet(30, TimeUnit.SECONDS);\n            return ClusterConnectionStatus.NORMAL;\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=ESClusterServiceImpl||method=checkClusterWithoutPassword||address={}||mg=get es segments fail\",\n                addresses, e);\n            if (e.getCause().getMessage().contains(\"Unauthorized\")) {\n                return ClusterConnectionStatus.UNAUTHORIZED;\n            } else {\n                return ClusterConnectionStatus.DISCONNECTED;\n            }\n        } finally {\n            client.close();\n        }\n    }\n\n    @Override\n    public ESClusterThreadStats syncGetThreadStatsByCluster(String cluster) {\n        List<ESClusterThreadPO> threadStats = esClusterDAO.syncGetThreadStatsByCluster(cluster);\n        ESClusterThreadStats esClusterThreadStats = new ESClusterThreadStats(cluster, 0L, 0L, 0L, 0L, 0L, 0L);\n        if (threadStats != null) {\n            esClusterThreadStats\n                .setManagement(threadStats.stream().filter(thread -> \"management\".equals(thread.getThreadName()))\n                    .mapToLong(ESClusterThreadPO::getQueueNum).sum());\n            esClusterThreadStats\n                .setRefresh(threadStats.stream().filter(thread -> \"refresh\".equals(thread.getThreadName()))\n                    .mapToLong(ESClusterThreadPO::getQueueNum).sum());\n            esClusterThreadStats.setFlush(threadStats.stream().filter(thread -> \"flush\".equals(thread.getThreadName()))\n                .mapToLong(ESClusterThreadPO::getQueueNum).sum());\n            esClusterThreadStats\n                .setMerge(threadStats.stream().filter(thread -> \"force_merge\".equals(thread.getThreadName()))\n                    .mapToLong(ESClusterThreadPO::getQueueNum).sum());\n            esClusterThreadStats\n                .setSearch(threadStats.stream().filter(thread -> \"search\".equals(thread.getThreadName()))\n                    .mapToLong(ESClusterThreadPO::getQueueNum).sum());\n            esClusterThreadStats.setWrite(threadStats.stream().filter(thread -> \"write\".equals(thread.getThreadName()))\n                .mapToLong(ESClusterThreadPO::getQueueNum).sum());\n        }\n        return esClusterThreadStats;\n    }\n\n    @Override\n    public ESClusterHealthResponse syncGetClusterHealthAtIndicesLevel(String phyClusterName) {\n        return esClusterDAO.getClusterHealthAtIndicesLevel(phyClusterName);\n    }\n\n    @Override\n    public List<PendingTaskAnalysisVO> syncPendingTaskAnalysis(String cluster) {\n        String response = esClusterDAO.pendingTask(cluster);\n        return Optional.ofNullable(response).map(JSONObject::parseObject)\n            .map(jsonObject -> jsonObject.getJSONArray(TASKS))\n            .map(tasks -> JSONObject.parseArray(tasks.toJSONString(), PendingTaskAnalysisVO.class))\n            .orElse(new ArrayList<>());\n    }\n\n    @Override\n    public List<TaskMissionAnalysisVO> syncTaskMissionAnalysis(String cluster) {\n        String response = esClusterDAO.taskMission(cluster);\n        return Optional.ofNullable(response).map(JSONObject::parseObject)\n            .map(jsonObject -> buildTaskMission(jsonObject)).orElse(new ArrayList<>());\n    }\n\n    @Override\n    public String syncHotThreadAnalysis(String cluster) {\n        String response = esClusterDAO.hotThread(cluster);\n        return response;\n    }\n\n    @Override\n    public boolean syncAbnormalShardAllocationRetry(String cluster) {\n        String response = esClusterDAO.abnormalShardAllocationRetry(cluster);\n        return Optional.ofNullable(response).map(JSONObject::parseObject)\n            .map(jsonObject -> jsonObject.getBoolean(ACKNOWLEDGED)).orElse(false);\n    }\n\n    @Override\n    public boolean syncClearFieldDataMemory(String cluster) {\n        String response = esClusterDAO.clearFieldDataMemory(cluster);\n        return Optional.ofNullable(response).map(JSONObject::parseObject)\n            .map(jsonObject -> jsonObject.getJSONObject(SHARDS)).map(shards -> shards.getInteger(FAILED))\n            .map(failed -> failed.equals(0)).orElse(false);\n    }\n\n    @Override\n    public List<String> syncGetTcpAddress(String cluster) {\n        return esClusterDAO.getNodeTcpAddress(cluster);\n    }\n    \n    /**\n     * 获取连接状态\n     *\n     * @param cluster 集群phy\n     * @return boolean\n     */\n    @Override\n    public boolean isConnectionStatus(String cluster) {\n    \n        try {\n            return ESOpTimeoutRetry.esRetryExecute(\"isConnectionStatus\", 3,\n                    () -> esClusterDAO.isConnectionStatus(cluster));\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class={}||method=isConnectionStatus\", getClass().getSimpleName(), e);\n            return false;\n        }\n    }\n    \n    @Override\n    public boolean checkTargetClusterConnected(String cluster, String targetCluster) throws ESOperateException {\n        return esClusterDAO.checkTargetClusterConnected(cluster,targetCluster);\n    }\n    \n    private List<TaskMissionAnalysisVO> buildTaskMission(JSONObject responseJson) {\n        List<TaskMissionAnalysisVO> vos = new ArrayList<>();\n        JSONObject nodes = responseJson.getJSONObject(NODES);\n        nodes.keySet().forEach(key -> {\n            Optional.ofNullable((JSONObject) nodes.get(key)).map(o -> o.getJSONObject(TASKS)).ifPresent(nodeTasks -> {\n                nodeTasks.forEach((key1, val) -> {\n                    JSONObject nodeInfo = (JSONObject) val;\n                    String nodeName = nodes.getJSONObject(key).getString(NAME);\n                    TaskMissionAnalysisVO taskMissionAnalysisVO = new TaskMissionAnalysisVO();\n                    Optional.ofNullable(nodeInfo).ifPresent(o -> {\n                        taskMissionAnalysisVO.setAction(o.getString(ACTION));\n                        taskMissionAnalysisVO.setNode(nodeName);\n                        taskMissionAnalysisVO.setDescription(o.getString(DESCRIPTION));\n                        taskMissionAnalysisVO.setStartTimeInMillis(o.getLong(START_TIME_IN_MILLIS));\n                        taskMissionAnalysisVO.setRunningTimeInNanos(o.getInteger(RUNNING_TIME_IN_NANOS));\n                        vos.add(taskMissionAnalysisVO);\n                    });\n                });\n            });\n        });\n        return vos;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/impl/ESIndexCatServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ESHttpRequestContent.getShards2NodeInfoRequestContent;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexCatCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.IndexShardInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.index.IndexCatCellPO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.BatchProcessor;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.index.IndexCatESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\n\n/**\n * Created by linyunan on 2021-10-14\n */\n@Service\npublic class ESIndexCatServiceImpl implements ESIndexCatService {\n\n    private static final ILog LOGGER = LogFactory.getLog(ESIndexCatService.class);\n    @Autowired\n    private IndexCatESDAO indexCatESDAO;\n   \n\n    @Override\n    public Tuple<Long, List<IndexCatCell>> syncGetCatIndexInfo(String cluster, String index, String health,\n                                                               String status, Integer projectId, Long from, Long size,\n                                                               String sortTerm, Boolean orderByDesc) {\n        Tuple<Long, List<IndexCatCellPO>> hitTotal2catIndexInfoTuplePO = indexCatESDAO.getCatIndexInfo(cluster, index,\n            health, status, projectId, from, size, sortTerm, orderByDesc);\n        if (null == hitTotal2catIndexInfoTuplePO) {\n            return null;\n        }\n\n        Tuple<Long, List<IndexCatCell>> hitTotal2catIndexInfoTuple = new Tuple<>();\n        hitTotal2catIndexInfoTuple.setV1(hitTotal2catIndexInfoTuplePO.getV1());\n        hitTotal2catIndexInfoTuple.setV2(ConvertUtil.list2List(hitTotal2catIndexInfoTuplePO.getV2(), IndexCatCell.class));\n        return hitTotal2catIndexInfoTuple;\n    }\n\n    @Override\n    public int syncUpdateCatIndexDeleteFlag(String cluster, List<String> indexNameList, int retryCount) {\n        if (CollectionUtils.isEmpty(indexNameList)) {\n            return 0;\n        }\n\n        BatchProcessor.BatchProcessResult<String, Boolean> result = new BatchProcessor<String, Boolean>()\n            .batchList(indexNameList).batchSize(10)\n            .processor(items -> indexCatESDAO.batchUpdateCatIndexDeleteFlag(cluster, items, retryCount))\n            .succChecker(succ -> succ).process();\n\n        if (!result.isSucc()) {\n            LOGGER.warn(\n                \"class=ESIndexCatServiceImpl||method=syncUpdateCatIndexDeleteFlag||cluster={}||indexNameList={}||result={}\",\n                cluster, indexNameList, result);\n        }\n\n        return indexNameList.size() - result.getFailAndErrorCount();\n    }\n\n    @Override\n    public int syncUpdateCatIndexStatus(String cluster, List<String> indexNameList, String status, int retryCount) {\n        if (CollectionUtils.isEmpty(indexNameList)) {\n            return 0;\n        }\n\n        BatchProcessor.BatchProcessResult<String, Boolean> result = new BatchProcessor<String, Boolean>()\n            .batchList(indexNameList).batchSize(10)\n            .processor(items -> indexCatESDAO.batchUpdateCatIndexStatus(cluster, items, status, retryCount))\n            .succChecker(succ -> succ).process();\n\n        if (!result.isSucc()) {\n            LOGGER.warn(\n                \"class=ESIndexCatServiceImpl||method=syncUpdateCatIndexStatus||cluster={}||indexNameList={}||result={}\",\n                cluster, indexNameList, result);\n        }\n\n        return indexNameList.size() - result.getFailAndErrorCount();\n    }\n\n    @Override\n    public List<IndexShardInfo> syncGetIndexShardInfo(String clusterPhyName, String indexName) throws ESOperateException {\n        String shards2NodeInfoRequestContent = getShards2NodeInfoRequestContent(indexName, \"20s\");\n        DirectResponse shardNodeResponse = indexCatESDAO.getDirectResponse(clusterPhyName, \"Get\",\n            shards2NodeInfoRequestContent);\n\n        if (shardNodeResponse.getRestStatus() == RestStatus.OK\n            && StringUtils.isNoneBlank(shardNodeResponse.getResponseContent())) {\n            return ConvertUtil.str2ObjArrayByJson(shardNodeResponse.getResponseContent(), IndexShardInfo.class);\n        }\n\n        return Lists.newArrayList();\n    }\n\n    @Override\n    public Boolean syncInsertCatIndex(List<IndexCatCellDTO> params, int retryCount) {\n        BatchProcessor.BatchProcessResult<IndexCatCellDTO, Boolean> result = new BatchProcessor<IndexCatCellDTO, Boolean>()\n                .batchList(params).batchSize(5000)\n                .processor(items -> indexCatESDAO.batchInsert(ConvertUtil.list2List(params, IndexCatCellPO.class), retryCount))\n                .succChecker(succ -> succ).process();\n\n        if (!result.isSucc()) {\n            List<String> clusterList = params.stream().map(IndexCatCellDTO::getCluster).distinct().collect(Collectors.toList());\n            List<String> indexList   = params.stream().map(IndexCatCellDTO::getIndex).distinct().collect(Collectors.toList());\n            LOGGER.error(\"class=ESIndexCatServiceImpl||method=syncInsertCatIndex||cluster={}||indexNameList={}||errMsg=failed to batchInsert, batch total count = {}, batch failed count={}\",\n                    ListUtils.strList2String(clusterList), ListUtils.strList2String(indexList),\n                    params.size(), result.getFailAndErrorCount());\n        }\n\n        return result.isSucc();\n    }\n    \n    @Override\n    public Boolean syncUpsertCatIndex(List<IndexCatCellDTO> params, int retryCount) {\n        BatchProcessor.BatchProcessResult<IndexCatCellDTO, Boolean> result = new BatchProcessor<IndexCatCellDTO, Boolean>().batchList(\n                        params).batchSize(5000).processor(\n                        items -> indexCatESDAO.batchUpsert(ConvertUtil.list2List(params, IndexCatCellPO.class), retryCount))\n                .succChecker(succ -> succ).process();\n        \n        if (!result.isSucc()) {\n            List<String> clusterList = params.stream().map(IndexCatCellDTO::getCluster).distinct()\n                    .collect(Collectors.toList());\n            List<String> indexList = params.stream().map(IndexCatCellDTO::getIndex).distinct()\n                    .collect(Collectors.toList());\n            LOGGER.error(\n                    \"class=ESIndexCatServiceImpl||method=syncUpsertCatIndex||cluster={}||indexNameList={}||errMsg=failed to batchInsert, batch total count = {}, batch failed count={}\",\n                    ListUtils.strList2String(clusterList), ListUtils.strList2String(indexList), params.size(),\n                    result.getFailAndErrorCount());\n        }\n        \n        return result.isSucc();\n    }\n\n    @Override\n    public List<IndexCatCell> syncGetPlatformCreateCatIndexList(Integer searchSize) {\n        try {\n            return indexCatESDAO.getPlatformCreateCatIndexList(searchSize);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESIndexCatServiceImpl||method=syncGetHasProjectIdButNotTemplateIdCatIndexList||\" +\n                    \"errMsg=failed to get syncGetHasProjectIdButNotTemplateIdCatIndexList\", e);\n        }\n        return Collections.emptyList();\n    }\n\n    @Override\n    public List<IndexCatCellDTO> syncGetIndexByCluster(String clusterLogicName, Integer projectId) {\n        Tuple<Long, List<IndexCatCellPO>> totalHitAndIndexCatCellListTuple = indexCatESDAO.getIndexListByTerms(clusterLogicName,projectId);\n        if (totalHitAndIndexCatCellListTuple == null){\n            return new ArrayList<>();\n        }\n        return ConvertUtil.list2List(totalHitAndIndexCatCellListTuple.v2(),IndexCatCellDTO.class);\n    }\n\n    /**\n     * @param cluster\n     * @param indexList\n     * @return\n     */\n    @Override\n    public Result<List<IndexCatCellDTO>> syncGetSegmentsIndexList(String cluster, Collection<String> indexList) {\n        BatchProcessor.BatchProcessResult<String, List<IndexCatCellDTO>> result = new BatchProcessor<String, List<IndexCatCellDTO>>().batchList(\n                        indexList)\n            \n                .batchSize(50).processor(items -> indexCatESDAO.syncGetSegmentsIndexList(cluster, items))\n                .succChecker(CollectionUtils::isNotEmpty).process();\n        if (!result.isSucc() && MapUtils.isNotEmpty(result.getErrorMap()) && CollectionUtils.isNotEmpty(\n                result.getErrorMap().values())) {\n            LOGGER.error(\"class={}||method=syncGetSegmentsIndexList||errMsg=failed to get syncGetSegmentsIndexList\",\n                    result.getErrorMap().values().stream().findFirst().get());\n        }\n        \n        \n        List<IndexCatCellDTO> indexCatCellDTOList = result.getResultList().stream().filter(CollectionUtils::isNotEmpty)\n                .flatMap(Collection::stream).collect(Collectors.toList());\n        return Result.buildSucc(indexCatCellDTOList);\n    }\n    \n    /**\n     * @param projectId\n     * @return\n     */\n    @Override\n    public List<String> syncGetIndexListByProjectId(Integer projectId, String clusterLogic) {\n        return indexCatESDAO.syncGetIndexListByProjectIdAndClusterLogic(projectId,\n                clusterLogic);\n    }\n    \n    @Override\n    public List<String> syncGetIndexListByProjectIdAndFuzzyIndexAndClusterLogic(Integer projectId, String clusterLogicName,\n                                                                                String index) {\n       return indexCatESDAO.syncGetIndexListByProjectIdAndFuzzyIndexAndClusterLogic(projectId,\n                clusterLogicName,index);\n    }\n\n    @Override\n    public List<IndexCatCell> syncGetAllCatIndexNameListByClusters(Integer searchSize,List<String> phyClusterNames) {\n        try {\n            return indexCatESDAO.getAllCatIndexNameListByClusters(searchSize,phyClusterNames);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESIndexCatServiceImpl||method=syncGetAllCatIndexNameList||\" + \"errMsg=failed to get syncGetAllCatIndexNameList\", e);\n        }\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<String> syncGetIndexListByProjectIdAndFuzzyIndexAndClusterPhy(String clusterPhyName,\n                                                                              String index) {\n         return indexCatESDAO.syncGetIndexListByProjectIdAndFuzzyIndexAndClusterPhy( clusterPhyName,index);\n    }\n\n    /**\n     * @param clusterPhyList\n     * @return\n     */\n    @Override\n    public Map<String, Integer> syncGetByClusterPhyList(List<String> clusterPhyList) {\n        return indexCatESDAO.syncGetByClusterPhyList(clusterPhyList);\n    }\n    \n    /**\n     * @param clusterPhy\n     * @param index\n     */\n    @Override\n    public IndexCatCell syncGetCatIndexInfoById(String clusterPhy, String index) {\n        return indexCatESDAO.syncGetCatIndexInfoById(clusterPhy,index);\n    }\n    /*************************************************private*******************************************************/\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/impl/ESIndexServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ESHttpRequestContent.getBigIndicesRequestContent;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.*;\n\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexCatCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.IndexResponse;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESSettingConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.index.IndexBlockEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.BatchProcessor;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESIndexDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.putalias.PutAliasNode;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.putalias.PutAliasType;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.getalias.AliasIndexNode;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.stats.IndexNodes;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.IndexConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.MultiIndexsConfig;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\n\n/**\n * @author d06679\n * @date 2019/4/2\n */\n@Service\npublic class ESIndexServiceImpl implements ESIndexService {\n\n    private static final ILog      LOGGER = LogFactory.getLog(ESIndexServiceImpl.class);\n\n    @Autowired\n    private ESIndexDAO             esIndexDAO;\n\n   \n\n    @Override\n    public boolean syncCreateIndex(String cluster, String indexName, int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"createIndex\", retryCount,\n            () -> esIndexDAO.createIndex(cluster, indexName));\n    }\n\n    @Override\n    public boolean syncCreateIndex(String cluster, String indexName, IndexConfig indexConfig,\n                                   int retryCount) throws ESOperateException {\n       \n        return esIndexDAO.createIndexWithConfig(cluster, indexName, indexConfig,retryCount);\n    }\n\n    @Override\n    public boolean syncDelIndex(String cluster, String indexName, int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"deleteIndex\", retryCount,\n            () -> esIndexDAO.deleteIndex(cluster, indexName));\n    }\n    \n    @Override\n    public boolean syncDeleteByExpression(String cluster, String expression, int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"syncDeleteByExpression\", retryCount,\n                () -> esIndexDAO.deleteByExpression(cluster, expression));\n    }\n    \n    /**\n     * 根据表达式删除索引\n     * @param cluster    集群\n     * @param expression 表达式\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean syncDeleteIndexByExpression(String cluster, String expression,\n                                               int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"deleteIndexByExpression\", retryCount,\n            () -> esIndexDAO.deleteIndex(cluster, expression));\n    }\n\n    /**\n     * 跟进索引名称获取索引的mapping\n     * @param cluster    集群\n     * @param index      索引名称\n     * @return result\n     * @throws ESOperateException\n     */\n    @Override\n    public String syncGetIndexMapping(String cluster, String index) {\n        MappingConfig mappingConfig = esIndexDAO.getIndexMapping(cluster, index);\n\n        if (null == mappingConfig) {\n            LOGGER.warn(\n                \"class=ESIndexServiceImpl||method=syncGetIndexMapping||errMsg=index mapping is null||cluster={}||index={}\",\n                cluster, index);\n            return \"\";\n        }\n        return mappingConfig.toJson().toString();\n    }\n\n    @Override\n    public boolean syncUpdateIndexMapping(String cluster, String index, MappingConfig mappingConfig) throws ESOperateException {\n        return esIndexDAO.updateIndexMapping(cluster, index, mappingConfig);\n    }\n\n    @Override\n    public Map<String, IndexConfig> syncBatchGetIndexConfig(String cluster, List<String> indexList) {\n        try {\n            MultiIndexsConfig multiIndexsConfig = esIndexDAO.batchGetIndexConfig(cluster, indexList);\n            return Optional.ofNullable(multiIndexsConfig).map(MultiIndexsConfig::getIndexConfigMap)\n                    .orElse(Maps.newConcurrentMap());\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=ESIndexServiceImpl||method=syncBatchGetIndexConfig||index={}\", cluster,\n                    String.join(\",\", indexList), e);\n        }\n        return Maps.newConcurrentMap();\n    }\n\n    /**\n     * 查询集群中的索引\n     * @param cluster    集群\n     * @param expression 表达式\n     * @return 索引集合\n     */\n    @Override\n    public Set<String> syncGetIndexNameByExpression(String cluster, String expression) {\n        LOGGER.info(\"class=ESIndexServiceImpl||method=syncGetIndexNameByExpression||cluster={}||expression={}\", cluster,\n            expression);\n\n        Map<String, IndexNodes> indexNodesMap = esIndexDAO.getIndexByExpression(cluster, expression);\n        if (indexNodesMap == null || indexNodesMap.isEmpty()) {\n            LOGGER.warn(\n                \"class=ESIndexServiceImpl||method=syncGetIndexNameByExpression||errMsg=no index||cluster={}||expression={}\",\n                cluster, expression);\n            return Sets.newHashSet();\n        }\n\n        LOGGER.info(\n            \"class=ESIndexServiceImpl||method=syncGetIndexNameByExpression||cluster={}||expression={}||indices={}\",\n            cluster, expression, JSON.toJSONString(indexNodesMap));\n\n        return indexNodesMap.keySet();\n    }\n\n    /**\n     * 更新索引列表对应settings中值\n     * @param cluster 集群名称\n     * @param indices 索引列表\n     * @param settingName setting名称\n     * @param settingValue setting值\n     * @param defaultValue 默认值\n     * @param retryCount 重试次数\n     * @return\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean syncPutIndexSetting(String cluster, List<String> indices, String settingName, String settingValue,\n                                       String defaultValue, int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"putIndexSetting\", retryCount,\n            () -> esIndexDAO.putIndexSetting(cluster, indices, settingName, settingValue, defaultValue));\n    }\n\n    @Override\n    public boolean syncPutIndexSetting(String cluster, List<String> indices, Map<String, String> settingMap,\n                                       Integer retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"putIndexSettingBatch\", retryCount,\n            () -> esIndexDAO.putIndexSetting(cluster, indices, settingMap));\n    }\n\n    @Override\n    public boolean syncPutIndexSettings(String cluster, List<String> indices, Map<String, String> settings,\n                                        int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"putIndexSettings\", retryCount,\n            () -> esIndexDAO.putIndexSettings(cluster, indices, settings));\n    }\n\n    /**\n     * 获取索引信息\n     *\n     * @param cluster    集群\n     * @param expression 表达式\n     * @return result\n     */\n    @Override\n    public Map<String, IndexNodes> syncGetIndexByExpression(String cluster, String expression) {\n        return esIndexDAO.getIndexByExpression(cluster, expression);\n    }\n\n    /**\n     * 获取索引信息\n     *\n     * @param cluster 集群\n     * @param indexNames 索引列表\n     * @return result\n     */\n    @Override\n    public Map<String, IndexNodes> syncBatchGetIndices(String cluster, Collection<String> indexNames)\n            throws ESOperateException {\n        BatchProcessor.BatchProcessResult<String, Map<String, IndexNodes>> result = new BatchProcessor<String, Map<String, IndexNodes>>()\n            .batchList(indexNames).batchSize(30)\n            .processor(items -> esIndexDAO.getIndexStatsWithShards(cluster, String.join(\",\", items))).process();\n        if (!result.isSucc() && CollectionUtils.isNotEmpty(result.getErrorMap().values())) {\n            throw new ESOperateException(String.format(\"cluster : %s get failed ; reason : %s\", cluster,\n                    result.getErrorMap().values().stream().findFirst().get().getMessage()));\n        }\n        return ConvertUtil.mergeMapList(result.getResultList());\n    }\n\n    /**\n     * 查询集群中的别名\n     * @param cluster    集群\n     * @param expression 表达式\n     * @return 索引集合\n     */\n    @Override\n    public List<Tuple<String, String>> syncGetIndexAliasesByExpression(String cluster, String expression) {\n        Map<String/*index*/, AliasIndexNode> aliasIndexNodeMap = esIndexDAO.getAliasesByExpression(cluster, expression);\n        if (aliasIndexNodeMap == null) {\n            LOGGER.warn(\n                \"class=ESIndexServiceImpl||method=syncGetIndexNameByExpression||msg=no alias||cluster={}||expression={}\",\n                cluster, expression);\n            return new ArrayList<>();\n        }\n\n        List<Tuple<String, String>> ret = new ArrayList<>();\n\n        for (Map.Entry<String, AliasIndexNode> entry : aliasIndexNodeMap.entrySet()) {\n            String index = entry.getKey();\n            AliasIndexNode aliasIndexNode = aliasIndexNodeMap.get(index);\n            Map<String, JSONObject> aliases = aliasIndexNode.getAliases();\n\n            if (null != aliases) {\n                aliases.keySet().forEach(a -> ret.add(new Tuple<>(index, a)));\n            }\n        }\n\n        return ret;\n    }\n\n    @Override\n    public Map<String, List<String>> syncGetIndexAliasesByIndices(String cluster, String... indices) {\n        Map<String/*index*/, AliasIndexNode> aliasIndexNodeMap = esIndexDAO.getAliasesByIndices(cluster, indices);\n        if (aliasIndexNodeMap == null) {\n            LOGGER.warn(\n                \"class=ESIndexServiceImpl||method=syncGetIndexNameByExpression||msg=no alias||cluster={}||expression={}\",\n                cluster, indices);\n            return new HashMap<>();\n        }\n\n        Map<String, List<String>> ret = new HashMap<>();\n        aliasIndexNodeMap.forEach((index, aliasIndexNode) -> {\n            Optional.ofNullable(aliasIndexNode.getAliases()).map(Map::keySet).ifPresent(set -> {\n                List<String> aliases = ret.getOrDefault(index, Lists.newArrayList());\n                aliases.addAll(set);\n                ret.put(index, aliases);\n            });\n        });\n\n        return ret;\n    }\n\n    /**\n     * 批量删除索引\n     * @param cluster    集群\n     * @param shouldDels 索引集合\n     * @param retryCount 重试次数\n     * @return result\n     */\n    @Override\n    public int syncBatchDeleteIndices(String cluster, Collection<String> shouldDels, int retryCount) {\n        if (CollectionUtils.isEmpty(shouldDels)) {\n            return 0;\n        }\n\n        BatchProcessor.BatchProcessResult<String, Boolean> result = new BatchProcessor<String, Boolean>()\n            .batchList(shouldDels).batchSize(10)\n            .processor(items -> batchDeleteIndicesInner(cluster, String.join(\",\", items), retryCount))\n            .succChecker(succ -> succ).process();\n\n        if (!result.isSucc()) {\n            LOGGER.warn(\"class=ESIndexServiceImpl||method=syncBatchDeleteIndices||cluster={}||shouldDels={}||result={}\",\n                cluster, shouldDels, result);\n        }\n\n        return shouldDels.size() - result.getFailAndErrorCount();\n    }\n\n    @Override\n    public boolean syncBatchCloseIndices(String cluster, List<String> shouldCloses,\n                                         int retryCount) throws ESOperateException {\n        if (CollectionUtils.isEmpty(shouldCloses)) {\n            return true;\n        }\n\n        return ESOpTimeoutRetry.esRetryExecute(\"closeIndex\", retryCount,\n            () -> esIndexDAO.closeIndex(cluster, shouldCloses));\n    }\n\n    @Override\n    public boolean syncBatchOpenIndices(String cluster, List<String> shouldOpens,\n                                        int retryCount) throws ESOperateException {\n        if (CollectionUtils.isEmpty(shouldOpens)) {\n            return true;\n        }\n\n        return ESOpTimeoutRetry.esRetryExecute(\"openIndex\", retryCount,\n            () -> esIndexDAO.openIndex(cluster, shouldOpens));\n    }\n\n    /**\n     * 删除文档\n     *\n     * @param cluster     集群\n     * @param delIndices  索引\n     * @param delQueryDsl 删除语句\n     * @return\n     */\n    @Override\n    public boolean syncDeleteByQuery(String cluster, List<String> delIndices,\n                                     String delQueryDsl) throws ESOperateException {\n        return esIndexDAO.deleteByQuery(cluster, String.join(\",\", delIndices), delQueryDsl);\n    }\n\n    @Override\n    public boolean syncBatchUpdateRegion(String cluster, List<String> indices, Integer tgtRegionId,\n                                         int retryCount,\n                                         Function</*coldRegionId*/Integer, Result<List<ClusterRoleHost>>> coldRegionIdFunc) throws ESOperateException {\n        Set<String> nodeNames = new HashSet<>();\n        final Result<List<ClusterRoleHost>> clusterRoleHostResult = coldRegionIdFunc.apply(tgtRegionId);\n        if (clusterRoleHostResult.failed() || CollectionUtils.isEmpty(clusterRoleHostResult.getData())) {\n            return false;\n        }\n        clusterRoleHostResult.getData()\n            .forEach(clusterRoleHost -> nodeNames.add(clusterRoleHost.getNodeSet()));\n\n        return ESOpTimeoutRetry.esRetryExecute(\"syncBatchUpdateRegion\", retryCount,\n            () -> esIndexDAO.batchUpdateIndexRegion(cluster, indices, nodeNames));\n    }\n\n    /**\n     * 修改索引只读配置\n     *\n     * @param cluster    集群\n     * @param indices    索引\n     * @param block   配置\n     * @param retryCount 重试次数\n     * @return true/false\n     */\n    @Override\n    public boolean syncBatchBlockIndexWrite(String cluster, List<String> indices, boolean block,\n                                            int retryCount) throws ESOperateException {\n        BatchProcessor.BatchProcessResult<String, Boolean> result = new BatchProcessor<String, Boolean>()\n            .batchList(indices).batchSize(30).processor(items -> {\n                    return ESOpTimeoutRetry.esRetryExecute(\"syncBatchBlockIndexWrite\", retryCount,\n                        () -> esIndexDAO.blockIndexWrite(cluster, items, block));\n            }).succChecker(succ -> succ).process();\n        if (!result.isSucc() && CollectionUtils.isNotEmpty(result.getErrorMap().values())) {\n            throw new ESOperateException(result.getErrorMap().values().stream().findFirst().get().getMessage());\n        }\n        return result.isSucc();\n    }\n\n    @Override\n    public boolean syncBatchBlockIndexRead(String cluster, List<String> indices, boolean block,\n                                           int retryCount) throws ESOperateException {\n        BatchProcessor.BatchProcessResult<String, Boolean> result = new BatchProcessor<String, Boolean>()\n            .batchList(indices).batchSize(30).processor(items -> {\n                        return ESOpTimeoutRetry.esRetryExecute(\"syncBatchBlockIndexRead\", retryCount,\n                                    () -> esIndexDAO.blockIndexRead(cluster, items, block));\n                }).succChecker(succ -> succ).process();\n        if (!result.isSucc() && CollectionUtils.isNotEmpty(result.getErrorMap().values())) {\n            throw new ESOperateException(result.getErrorMap().values().stream().findFirst().get().getMessage());\n        \n        }\n        return result.isSucc();\n    }\n\n    /**\n     * 校验索引数据是否一致\n     *\n     * @param cluster1        集群1\n     * @param cluster2        集群2\n     * @param indexNames      索引名字\n     * @param indexExpression\n     * @param timeout\n     * @return true/false\n     */\n    @Override\n    public boolean ensureDataSame(String cluster1, String cluster2, List<String> indexNames, String indexExpression,\n        Integer timeout) throws ESOperateException {\n        int retryCount = getRetryCountByTimeout(timeout);\n        \n        while (retryCount-- > 0) {\n            try {\n                Thread.sleep(5000);\n            } catch (InterruptedException e) {\n                Thread.currentThread().interrupt();\n                LOGGER.warn(\"class=ESIndexServiceImpl||method=ensureDateSame||msg=sleep interrupted\", e);\n            }\n\n            if (checkDateSame(cluster1, cluster2, indexNames,indexExpression)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * close and open index\n     *\n     * @param cluster 集群\n     * @param indices 索引\n     * @return result\n     */\n    @Override\n    public boolean reOpenIndex(String cluster, List<String> indices, int retryCount) throws ESOperateException {\n        BatchProcessor.BatchProcessResult<String, Boolean> result = new BatchProcessor<String, Boolean>().batchList(\n                indices).batchSize(30).processor(items -> {\n            if (ESOpTimeoutRetry.esRetryExecute(\"reOpenIndex-close\", retryCount,\n                    () -> esIndexDAO.closeIndex(cluster, items))) {\n                return ESOpTimeoutRetry.esRetryExecute(\"reOpenIndex-open\", retryCount,\n                        () -> esIndexDAO.openIndex(cluster, items));\n            } else {\n                return false;\n            }\n        }).succChecker(succ -> succ).process();\n        if (!result.isSucc() && CollectionUtils.isNotEmpty(result.getErrorMap().values())) {\n            throw new ESOperateException(result.getErrorMap().values().stream().findFirst().get().getMessage());\n        \n        }\n        return result.isSucc();\n    }\n\n    /**\n     * cat index\n     *\n     * @param cluster    集群\n     * @param expression 表达式\n     * @return list\n     */\n    @Override\n    public List<CatIndexResult> syncCatIndexByExpression(String cluster, String expression) {\n        List<CatIndexResult> catIndexResults = esIndexDAO.catIndexByExpression(cluster, expression);\n\n        LOGGER.info(\"class=ESIndexServiceImpl||method=syncCatIndexByExpression||cluster={}||expression={}||indices={}\",\n            cluster, expression, JSON.toJSONString(catIndexResults));\n\n        return catIndexResults;\n    }\n\n    @Override\n    public List<CatIndexResult> syncCatIndex(String clusterPhyName, int tryTimes) {\n        int retryCount = tryTimes < 0 ? 1 : tryTimes;\n        List<CatIndexResult> catIndexResultList = Lists.newArrayList();\n        while (retryCount-- > 0) {\n            try {\n                Thread.sleep(1000);\n            } catch (InterruptedException e) {\n                Thread.currentThread().interrupt();\n                LOGGER.warn(\"class=ESIndexServiceImpl||method=ensureDateSame||msg=sleep interrupted\", e);\n            }\n            catIndexResultList.addAll(esIndexDAO.catIndices(clusterPhyName));\n            if (CollectionUtils.isNotEmpty(catIndexResultList)) {\n                break;\n            }\n        }\n\n        return catIndexResultList.stream().filter(this::filterOriginalIndices).collect(Collectors.toList());\n    }\n\n    /**\n     * 过滤原始索引\n     */\n    private boolean filterOriginalIndices(CatIndexResult catIndexResult) {\n        if (null == catIndexResult) {\n            return false;\n        }\n\n        return StringUtils.isNotBlank(catIndexResult.getIndex()) && !catIndexResult.getIndex().startsWith(\".\");\n    }\n\n    /**\n     * 获取索引配置\n     * @param cluster 集群名称\n     * @param name 索引名称\n     * @return\n     */\n    @Override\n    public MultiIndexsConfig syncGetIndexConfigs(String cluster, String name) {\n        return esIndexDAO.getIndexConfigs(cluster, name);\n    }\n\n    @Override\n    public Map<String, IndexConfig> syncGetIndexSetting(String cluster, List<String> indexNames, int tryTimes) {\n        return esIndexDAO.getIndicesSetting(cluster, indexNames, tryTimes);\n    }\n\n    /**\n     * 获取索引主shard个数\n     * @param clusterName\n     * @param indexName\n     * @return\n     */\n    @Override\n    public Integer syncGetIndexPrimaryShardNumber(String clusterName, String indexName) {\n        Integer primaryShardNumber = null;\n\n        MultiIndexsConfig multiIndexsConfig = syncGetIndexConfigs(clusterName, indexName);\n        if (multiIndexsConfig != null && multiIndexsConfig.getIndexConfigMap() != null) {\n            for (Map.Entry<String, IndexConfig> entry : multiIndexsConfig.getIndexConfigMap().entrySet()) {\n                Map<String, String> settings = entry.getValue().getSettings();\n                if (settings != null) {\n                    try {\n                        primaryShardNumber = getPrimaryShardNumber(primaryShardNumber, settings);\n                    } catch (NumberFormatException e) {\n                        LOGGER.error(\n                            \"class=ESIndexServiceImpl||method=getIndexPrimaryShardNumberByCLusterName||clusterName={}||indexName={}||errMsg=fail to parse {}. \",\n                            clusterName, indexName, settings.get(\"index.number_of_shards\"), e);\n                    }\n                }\n            }\n        }\n\n        return primaryShardNumber;\n    }\n\n    @Override\n    public Map<String, IndexNodes> syncGetIndexNodes(String clusterName, String templateExp) {\n        return esIndexDAO.getIndexNodes(clusterName, templateExp);\n    }\n\n    @Override\n    public List<String> syncGetIndexName(String clusterName) throws ESOperateException {\n        String indicesRequestContent = getBigIndicesRequestContent(\"20s\");\n\n        DirectResponse directResponse = esIndexDAO.getDirectResponse(clusterName, \"Get\", indicesRequestContent);\n\n        List<IndexResponse> indexResponses = Lists.newArrayList();\n\n        if (directResponse.getRestStatus() == RestStatus.OK\n            && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n\n            indexResponses = ConvertUtil.str2ObjArrayByJson(directResponse.getResponseContent(), IndexResponse.class);\n        }\n        return indexResponses.stream().map(IndexResponse::getIndex).collect(Collectors.toList());\n    }\n\n    @Override\n    public boolean syncIsIndexExist(String cluster, String indexName) {\n        try {\n            return ESOpTimeoutRetry.esRetryExecute(\"syncIsIndexExist\", 3,\n                    () -> esIndexDAO.existByClusterAndIndexName(cluster, indexName));\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class={}||method=syncIsIndexExist||indexName={}||cluster={}\", getClass().getSimpleName(),\n                    indexName, cluster, e);\n            return false;\n        }\n    }\n\n    @Override\n    public AtomicLong syncGetTotalCheckpoint(String index, IndexNodes stat, AtomicBoolean checkpointEqualSeqNo) {\n        AtomicLong totalCheckpoint = new AtomicLong(0);\n        if (stat == null) {\n            return totalCheckpoint;\n        }\n\n        stat.getShards().forEach((shard, v) -> v.forEach(commonStat -> {\n            if (!commonStat.getRouting().isPrimary()) {\n                return;\n            }\n\n            if (null == commonStat.getSeqNo()) {\n                LOGGER.warn(\n                    \"class=ESIndexServiceImpl||method=syncGetTotalCheckpoint||indexName={}||shard={}||msg=commonStat seqNo is empty\",\n                    index, shard);\n                return;\n            }\n\n            if (commonStat.getSeqNo().getMaxSeqNo() != commonStat.getSeqNo().getGlobalCheckpoint()) {\n                LOGGER.warn(\n                    \"class=ESIndexServiceImpl||method=syncGetTotalCheckpoint||indexName={}||shard={}||msg=primary maxSeqNo({})!=globalCheckpoint({})\",\n                    index, shard, commonStat.getSeqNo().getMaxSeqNo(), commonStat.getSeqNo().getGlobalCheckpoint());\n                if (null != checkpointEqualSeqNo) {\n                    checkpointEqualSeqNo.set(false);\n                }\n            }\n\n            totalCheckpoint.addAndGet(commonStat.getSeqNo().getGlobalCheckpoint());\n        }));\n        return totalCheckpoint;\n    }\n\n    @Override\n    public Result<Void> addAliases(String cluster, String index, List<String> aliases) {\n        if (!esIndexDAO.exist(cluster, index)) {\n            return Result.buildParamIllegal(String.format(\"索引【%s】不存在\", index));\n        }\n        if (CollectionUtils.isEmpty(aliases)) {\n            return Result.buildParamIllegal(\"要操作的别名不存在\");\n        }\n        List<PutAliasNode> putAliasNodeList = new ArrayList<>();\n        Map<String, List<String>> aliasIndexNodeMap = syncGetIndexAliasesByIndices(cluster, index);\n        Set<String> aliasSet = new HashSet<>();\n        Optional.ofNullable(aliasIndexNodeMap.get(index)).ifPresent(aliasSet::addAll);\n\n        aliases.stream().filter(StringUtils::isNotBlank).forEach(aliasName -> {\n            PutAliasNode putAliasNode = new PutAliasNode();\n            putAliasNode.setIndex(index);\n            putAliasNode.setAlias(aliasName);\n            putAliasNode.setType(PutAliasType.ADD);\n            if (!aliasSet.contains(aliasName)) {\n                putAliasNodeList.add(putAliasNode);\n            }\n        });\n\n        if (CollectionUtils.isNotEmpty(putAliasNodeList)) {\n            try {\n                return Result.build(esIndexDAO.editAlias(cluster, putAliasNodeList));\n            } catch (ESOperateException e) {\n                return Result.buildFail(e.getMessage());\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> deleteAliases(String cluster, String index, List<String> aliases) {\n        if (!esIndexDAO.exist(cluster, index)) {\n            return Result.buildParamIllegal(String.format(\"索引【%s】不存在\", index));\n        }\n        if (CollectionUtils.isEmpty(aliases)) {\n            return Result.buildParamIllegal(\"要操作的别名不存在\");\n        }\n        List<PutAliasNode> putAliasNodeList = new ArrayList<>();\n        Map<String, List<String>> aliasIndexNodeMap = syncGetIndexAliasesByIndices(cluster, index);\n        Set<String> aliasSet = new HashSet<>();\n        Optional.ofNullable(aliasIndexNodeMap.get(index)).map(aliasSet::addAll);\n        Set<String> notExistsAlias = new HashSet<>();\n\n        aliases.stream().filter(StringUtils::isNotBlank).forEach(aliasName -> {\n            PutAliasNode putAliasNode = new PutAliasNode();\n            putAliasNode.setIndex(index);\n            putAliasNode.setAlias(aliasName);\n            putAliasNode.setType(PutAliasType.REMOVE);\n            if (!aliasSet.contains(aliasName)) {\n                notExistsAlias.add(aliasName);\n            }\n            putAliasNodeList.add(putAliasNode);\n        });\n        if (!notExistsAlias.isEmpty()) {\n            return Result.buildParamIllegal(String.format(\"要删除的别名【%s】不存在\", StringUtils.join(notExistsAlias, \",\")));\n        }\n        try {\n            return Result.build(esIndexDAO.editAlias(cluster, putAliasNodeList));\n        } catch (ESOperateException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n\n    @Override\n    public Result<Void> rollover(String cluster, String alias, String conditions) {\n        return esIndexDAO.rollover(cluster, alias, conditions);\n    }\n\n    @Override\n    public Result<Void> forceMerge(String cluster, String index, Integer maxNumSegments, Boolean onlyExpungeDeletes) {\n        return esIndexDAO.forceMerge(cluster, index, maxNumSegments, onlyExpungeDeletes);\n    }\n\n    @Override\n    public Result<Void> shrink(String cluster, String index, String targetIndex, String config) {\n        return esIndexDAO.shrink(cluster, index, targetIndex, config);\n    }\n\n    @Override\n    public Result<Void> split(String cluster, String index, String targetIndex, String config) {\n        return esIndexDAO.split(cluster, index, targetIndex, config);\n    }\n\n    @Override\n    public List<CatIndexResult> syncIndicesDistribution(String cluster) {\n        List<CatIndexResult> catIndexResultList = esIndexDAO.catIndices(cluster);\n        return catIndexResultList;\n    }\n\n    @Override\n    public List<IndexCatCell> buildIndexAliasesAndBlockInfo(String cluster, List<IndexCatCell> indexCatCellList) {\n        if (CollectionUtils.isNotEmpty(indexCatCellList)) {\n            List<String> indexNameList = indexCatCellList.stream().map(IndexCatCell::getIndex)\n                .collect(Collectors.toList());\n            Map<String, IndexConfig> name2IndexConfigMap = this.syncGetIndexSetting(cluster, indexNameList, 3);\n\n            Map<String, List<String>> aliasMap = this.syncGetIndexAliasesByIndices(cluster,\n                indexNameList.toArray(new String[0]));\n            indexCatCellList.forEach(indexCatCell -> {\n                indexCatCell.setAliases(aliasMap.getOrDefault(indexCatCell.getIndex(), Lists.newArrayList()));\n\n                IndexConfig indexConfig = name2IndexConfigMap.get(indexCatCell.getIndex());\n                Tuple<Boolean, Boolean> writeAndReadBlockFromMerge = getWriteAndReadBlock(indexConfig);\n\n                indexCatCell\n                    .setReadFlag(writeAndReadBlockFromMerge.getV1() != null && writeAndReadBlockFromMerge.getV1());\n                indexCatCell\n                    .setWriteFlag(writeAndReadBlockFromMerge.getV2() != null && writeAndReadBlockFromMerge.getV2());\n            });\n        } else {\n            LOGGER.warn(\n                \"class=IndicesPageSearchHandle||method=buildBlockInfo||cluster={}||index={}||errMsg=index is empty\",\n                cluster);\n        }\n        return indexCatCellList;\n    }\n    \n    /**\n     * @param cluster\n     * @param index\n     * @param mappingConfig\n     * @return\n     */\n    @Override\n    public boolean updateIndexMapping(String cluster, String index, MappingConfig mappingConfig)\n            throws ESOperateException {\n        return esIndexDAO.updateIndexMapping(cluster,index,mappingConfig);\n    }\n    \n    /**\n     * @param clusterName\n     * @param indexName\n     * @param indexConfig\n     * @param tryTimes\n     * @return\n     */\n    @Override\n    public boolean createIndexWithConfig(String clusterName, String indexName, IndexConfig indexConfig, int tryTimes)\n            throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"createIndexWithConfig\", 3,\n                () -> esIndexDAO.createIndexWithConfig(clusterName, indexName, indexConfig, tryTimes), Objects::isNull);\n    }\n    \n    /**\n     * @param clusterName\n     * @param indexName\n     * @return\n     */\n    @Override\n    public boolean deleteIndex(String clusterName, String indexName) throws ESOperateException {\n        return esIndexDAO.deleteIndex(clusterName,indexName);\n    }\n    \n    /**\n     * 返回与指定别名匹配的索引数\n     *\n     * @param cluster 集群的名称。\n     * @param alias   索引的别名\n     * @return 与别名匹配的索引数。\n     */\n    @Override\n    public Result<Integer> countIndexByAlias(String cluster, String alias) {\n        try {\n            return Result.buildSucc(esIndexDAO.countIndexByAlias(cluster, alias));\n        } catch (ESOperateException e) {\n            return Result.buildFail(e.getMessage());\n        }\n    }\n    \n    /***************************************** private method ****************************************************/\n\n    private Tuple<Boolean, Boolean> getWriteAndReadBlock(IndexConfig indexConfig) {\n        Tuple<Boolean, Boolean> writeAndReadBlockFromMerge = new Tuple<>();\n        //build from es setUp settings\n        Tuple<Boolean, Boolean> writeAndReadBlockFromSetUpSettingTuple = new Tuple<>();\n        Optional.ofNullable(indexConfig).map(IndexConfig::getSettings).filter(MapUtils::isNotEmpty)\n            .map(JSON::toJSONString).map(JSON::parseObject).ifPresent(settingsObj -> {\n                writeAndReadBlockFromSetUpSettingTuple.setV1(settingsObj.getBoolean(READ));\n                writeAndReadBlockFromSetUpSettingTuple.setV2(settingsObj.getBoolean(WRITE));\n            });\n        //build from es default settings\n        Tuple<Boolean, Boolean> writeAndReadBlockFromDefaultSettingTuple = new Tuple<>();\n        Optional.ofNullable(indexConfig).map(config -> config.getOther(DEFAULTS)).map(Object::toString)\n            .map(JSON::parseObject).map(defaultObj -> defaultObj.getJSONObject(INDEX))\n            .map(indexSettings -> indexSettings.getJSONObject(BLOCKS)).ifPresent(blocksObj -> {\n                if (null != blocksObj.get(IndexBlockEnum.READ.getType())) {\n                    writeAndReadBlockFromDefaultSettingTuple.setV1(blocksObj.getBoolean(IndexBlockEnum.READ.getType()));\n                }\n                if (null != blocksObj.get(IndexBlockEnum.WRITE.getType())) {\n                    writeAndReadBlockFromDefaultSettingTuple\n                        .setV2(blocksObj.getBoolean(IndexBlockEnum.WRITE.getType()));\n                }\n            });\n\n        //set read block info\n        if (null != writeAndReadBlockFromSetUpSettingTuple.getV1()) {\n            writeAndReadBlockFromMerge.setV1(writeAndReadBlockFromSetUpSettingTuple.getV1());\n        } else if (null != writeAndReadBlockFromDefaultSettingTuple.getV1()) {\n            writeAndReadBlockFromMerge.setV1(writeAndReadBlockFromDefaultSettingTuple.getV1());\n        }\n\n        //set write block info\n        if (null != writeAndReadBlockFromSetUpSettingTuple.getV2()) {\n            writeAndReadBlockFromMerge.setV2(writeAndReadBlockFromSetUpSettingTuple.getV2());\n        } else if (null != writeAndReadBlockFromDefaultSettingTuple.getV2()) {\n            writeAndReadBlockFromMerge.setV2(writeAndReadBlockFromDefaultSettingTuple.getV2());\n        }\n\n        return writeAndReadBlockFromMerge;\n    }\n\n    private Result<Void> refreshIndex(String cluster, List<String> indexNames) throws ESOperateException {\n        BatchProcessor.BatchProcessResult<String, Boolean> result = new BatchProcessor<String, Boolean>()\n            .batchList(indexNames).batchSize(30).processor(items -> esIndexDAO.refreshIndex(cluster, items))\n            .succChecker(succ -> succ).process();\n        if (!result.isSucc() && CollectionUtils.isNotEmpty(result.getErrorMap().values())) {\n            throw new ESOperateException(String.format(\"cluster : %s get failed ; reason : %s\", cluster,\n                    result.getErrorMap().values().stream().findFirst().get().getMessage()));\n        \n        }\n        return Result.build(result.isSucc());\n    }\n\n    private boolean checkDateSame(String cluster1, String cluster2, List<String> indexNames, String indexExpression) throws ESOperateException {\n        //使用indexName*的方式进行索引关闭，避免索引数量过多，从而导致了执行时间过长\n        Result<Void> refreshIndexResult1 = refreshIndex(cluster1, Collections.singletonList(indexExpression));\n        if (refreshIndexResult1.failed()) {\n            LOGGER.warn(\"class=ESIndexServiceImpl||method=ensureDateSame||cluster={}||indexNames={}||msg=refresh fail\",\n                cluster1, indexNames);\n            return false;\n        }\n        //使用indexName*的方式进行索引关闭，避免索引数量过多，从而导致了执行时间过长\n        Result<Void> refreshIndexResult2 = refreshIndex(cluster2, Collections.singletonList(indexExpression));\n        if (refreshIndexResult2.failed()) {\n            LOGGER.warn(\"class=ESIndexServiceImpl||method=ensureDateSame||cluster={}||indexNames={}||msg=refresh fail\",\n                cluster2, indexNames);\n            return false;\n        }\n    \n        Map<String, IndexNodes> indexStat1 = syncBatchGetIndices(cluster1, Collections.singletonList(indexExpression));\n        Map<String, IndexNodes> indexStat2 = syncBatchGetIndices(cluster2, Collections.singletonList(indexExpression));\n\n        for (String index : indexNames) {\n            IndexNodes stat1 = indexStat1.get(index);\n            IndexNodes stat2 = indexStat2.get(index);\n\n            if (stat1 == null || stat2 == null) {\n                LOGGER.warn(\"class=ESIndexServiceImpl||method=ensureDateSame||indexName={}||msg=index miss\", index);\n                return false;\n            }\n\n            if (stat1.getPrimaries().getDocs().getCount() != stat2.getPrimaries().getDocs().getCount()) {\n                LOGGER.warn(\n                    \"class=ESIndexServiceImpl||method=ensureDateSame||indexName={}||msg=doc count not match, primary={}, replica={}\",\n                    index, stat1.getPrimaries().getDocs().getCount(), stat2.getPrimaries().getDocs().getCount());\n                return false;\n            }\n\n            // 校验checkpoint\n            AtomicBoolean checkpointEqualSeqNo = new AtomicBoolean(true);\n            AtomicLong totalCheckpoint1 = syncGetTotalCheckpoint(index, stat1, checkpointEqualSeqNo);\n            AtomicLong totalCheckpoint2 = syncGetTotalCheckpoint(index, stat2, checkpointEqualSeqNo);\n\n            if (!checkpointEqualSeqNo.get()) {\n                return false;\n            }\n\n            if (totalCheckpoint1.get() != totalCheckpoint2.get()) {\n                LOGGER.warn(\n                    \"class=ESIndexServiceImpl||method=ensureDateSame||indexName={}|||msg=checkpoint not match, primary={}, replica={}\",\n                    index, totalCheckpoint1.get(), totalCheckpoint2.get());\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    private boolean batchDeleteIndicesInner(String cluster, String indices, int retryCount) {\n        try {\n            syncDeleteIndexByExpression(cluster, indices, retryCount);\n            return true;\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=ESIndexServiceImpl||method=batchDeleteIndicesInner||cluster\" + \"={}||indices={}\",\n                cluster, indices, e);\n        }\n        return false;\n    }\n\n    private Integer getPrimaryShardNumber(Integer primaryShardNumber, Map<String, String> settings) {\n        Integer shardNo = Integer.parseInt(settings.get(\"index.number_of_shards\"));\n        if (primaryShardNumber == null) {\n            primaryShardNumber = shardNo;\n        } else {\n            // 得到多个索引时获取到最大的主shard个数\n            primaryShardNumber = Math.max(primaryShardNumber, shardNo);\n        }\n        return primaryShardNumber;\n    }\n    \n    /**\n     * > 此函数返回给定超时的重试次数\n     *\n     * @param timeout 请求的超时。\n     * @return 放弃前应尝试的重试次数。\n     */\n    private int getRetryCountByTimeout(Integer timeout) {\n        if (timeout == null) {\n            return 20;\n        }\n        int retryCount = (int) Math.ceil(timeout.doubleValue() / 5);\n        return retryCount == 0 ? 1 : retryCount;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/impl/ESShardCatServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es.impl;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.shard.ShardCatCellPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.ShardDistributionVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.BatchProcessor;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.SizeUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESShardCatService;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESShardDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName ESShardCatServiceImpl\n * @Author gyp\n * @Date 2022/7/11\n * @Version 1.0\n */\n@Service\npublic class ESShardCatServiceImpl implements ESShardCatService {\n    private static final ILog LOGGER = LogFactory.getLog(ESIndexCatService.class);\n    @Autowired\n    private ESShardDAO esShardDAO;\n\n    @Override\n    public List<ShardCatCellPO> syncShardDistribution(String cluster,long currentTimeMillis) throws ESOperateException {\n        List<ShardCatCellPO> shardCatCellPOS = esShardDAO.catShard(cluster);\n        shardCatCellPOS.forEach(shardCatCellPO -> {\n            shardCatCellPO.setClusterPhy(cluster);\n            shardCatCellPO.setTimestamp(currentTimeMillis);\n        });\n        return shardCatCellPOS;\n    }\n\n    @Override\n    public Tuple<Long, List<ShardDistributionVO>> syncGetCatShardInfo(String queryCluster, Integer queryProjectId, String keyword, long from, Long size, String sortTerm, Boolean orderByDesc) {\n        Tuple<Long, List<ShardCatCellPO>> hitTotal2catIndexInfoTuplePO = esShardDAO.getCatShardInfo(queryCluster,\n                queryProjectId, keyword, from, size, sortTerm, orderByDesc);\n        if (null == hitTotal2catIndexInfoTuplePO) {\n            return null;\n        }\n\n        Tuple<Long, List<ShardDistributionVO>> hitTotal2catIndexInfoTuple = new Tuple<>();\n        hitTotal2catIndexInfoTuple.setV1(hitTotal2catIndexInfoTuplePO.getV1());\n        hitTotal2catIndexInfoTuple.setV2(buildShardCatCell(hitTotal2catIndexInfoTuplePO.getV2()));\n        return hitTotal2catIndexInfoTuple;\n    }\n\n    @Override\n    public Boolean syncInsertCatShard(List<ShardCatCellPO> params, int retryCount) {\n        BatchProcessor.BatchProcessResult<ShardCatCellPO, Boolean> result = new BatchProcessor<ShardCatCellPO, Boolean>().batchList(\n                        params).batchSize(5000).processor(\n                        items -> esShardDAO.batchInsert(ConvertUtil.list2List(params, ShardCatCellPO.class)))\n                .succChecker(succ -> succ).process();\n\n        if (!result.isSucc()) {\n            List<String> clusterList = params.stream().map(ShardCatCellPO::getClusterPhy).distinct()\n                    .collect(Collectors.toList());\n            LOGGER.error(\n                    \"class=ESShardCatServiceImpl||method=syncInsertCatShard||cluster={}||errMsg=failed to batchInsert, batch total count = {}, batch failed count={}\",\n                    ListUtils.strList2String(clusterList),  params.size(),\n                    result.getFailAndErrorCount());\n        }\n\n        return result.isSucc();\n    }\n\n    private List<ShardDistributionVO> buildShardCatCell(List<ShardCatCellPO> v2) {\n        List<ShardDistributionVO> shardDistributionVOList = new ArrayList<>();\n        v2.forEach(cell->{\n            ShardDistributionVO shardDistributionVO = new ShardDistributionVO();\n            shardDistributionVO.setDocs(cell.getDocs());\n            shardDistributionVO.setIndex(cell.getIndex());\n            shardDistributionVO.setIp(cell.getIp());\n            shardDistributionVO.setNode(cell.getNode());\n            shardDistributionVO.setPrirep(cell.getPrirep());\n            shardDistributionVO.setShard(String.valueOf(cell.getShard()));\n            shardDistributionVO.setState(cell.getState());\n            shardDistributionVO.setStore(SizeUtil.getUnitSize(cell.getStore()));\n            shardDistributionVOList.add(shardDistributionVO);\n        });\n        return shardDistributionVOList;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/impl/ESShardServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es.impl;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.MovingShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.UnAssignShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.shard.Segment;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.shard.SegmentPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.ShardAssignmenNodeVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.ShardAssignmentDescriptionVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.SizeUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESShardService;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESShardDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.jetbrains.annotations.NotNull;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.*;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ESHttpRequestContent.*;\n\n/**\n * Created by linyunan on 3/22/22\n */\n@Service\npublic class ESShardServiceImpl implements ESShardService {\n\n    private static final ILog LOGGER = LogFactory.getLog(ESShardServiceImpl.class);\n    \n    private String              shard                        = \"shard\";\n    private String              index                        = \"index\";\n    private String              primary                      = \"primary\";\n    private String              current_state                = \"current_state\";\n    private String              node_allocation_decisions    = \"node_allocation_decisions\";\n    private String              node_name                    = \"node_name\";\n    private String              decider                      = \"decider\";\n    private String              deciders                     = \"deciders\";\n    private String              explanation                  = \"explanation\";\n    private String              unassign                     = \"UNASSIGNED\";\n    private int                 ONE                          = 1;\n    \n    \n    @Autowired\n    private ESShardDAO esShardDAO;\n\n    @Autowired\n    private AriusConfigInfoService ariusConfigInfoService;\n\n    @Override\n    public List<MovingShardMetrics> syncGetMovingShards(String clusterName) throws ESOperateException {\n        DirectResponse directResponse = esShardDAO.getDirectResponse(clusterName, \"Get\", GET_MOVING_SHARD);\n\n        List<MovingShardMetrics> movingShardsMetrics = Lists.newArrayList();\n        if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n\n            movingShardsMetrics = ConvertUtil.str2ObjArrayByJson(directResponse.getResponseContent(),\n                    MovingShardMetrics.class);\n\n        }\n        return movingShardsMetrics;\n    }\n\n    @Override\n    public List<UnAssignShardMetrics> syncGetUnAssignShards(String clusterName) throws ESOperateException {\n        DirectResponse directResponse = esShardDAO.getDirectResponse(clusterName, \"Get\", GET_SHARDS_JSON);\n\n        if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n\n            return ConvertUtil.str2ObjArrayByJson(directResponse.getResponseContent(),\n                    UnAssignShardMetrics.class).stream().filter(r->r.getState().equals(unassign)).collect(Collectors.toList());\n        }\n        return Lists.newArrayList();\n    }\n    @Override\n    public List<ShardMetrics> syncGetBigShards(String clusterName) throws ESOperateException {\n        List<ShardMetrics> shardsMetrics = getShardMetrics(clusterName);\n        long configBigShard = SizeUtil.getUnitSize(ariusConfigInfoService.doubleSetting(ARIUS_COMMON_GROUP,BIG_SHARD_THRESHOLD,BIG_SHARD)+\"g\");\n        return shardsMetrics.stream().filter(s->filterBigShard(configBigShard,s)).sorted(Comparator.comparing(s->SizeUtil.getUnitSize(s.getStore())))\n                .collect(Collectors.toList());\n    }\n\n    @Override\n    public Tuple</*大shard列表*/List<ShardMetrics>, /*小shard列表*/List<ShardMetrics>> syncGetBigAndSmallShards(String clusterName,long configBigShard,long configSmallShard) {\n        List<ShardMetrics> shardsMetrics = null;\n        Tuple<List<ShardMetrics>, List<ShardMetrics>> tuple = new Tuple<>();\n        try {\n            shardsMetrics = getShardMetrics(clusterName);\n            Map<String, List<ShardMetrics>> indexAndShardMetricsMap =  ConvertUtil.list2MapOfList(\n                    shardsMetrics, ShardMetrics::getIndex, shardMetrics -> shardMetrics);\n            tuple.setV1(shardsMetrics.stream().filter(s->filterBigShard(configBigShard,s)).collect(Collectors.toList()));\n            tuple.setV2(shardsMetrics.stream().filter(s->filterSmallShard(configSmallShard,s,indexAndShardMetricsMap)).collect(Collectors.toList()));\n            return tuple;\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=ESShardServiceImpl||method=syncGetBigAndSmallShards||cluster={}||errMsg=fail to get ShardMetrics\",\n                    clusterName, e);\n           return tuple;\n        }\n    }\n\n    @Override\n    public List<Segment> syncGetSegments(String clusterName) {\n        String segmentsPartInfoRequestContent = getSegmentsPartInfoRequestContent();\n        List<SegmentPO> segmentPOS = null;\n        try {\n            segmentPOS = esShardDAO.commonGet(clusterName, segmentsPartInfoRequestContent, SegmentPO.class);\n            return ConvertUtil.list2List(segmentPOS, Segment.class);\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=ESShardServiceImpl||method=syncGetSegments||cluster={}||errMsg=fail to commonGet\",clusterName,e);\n        }\n        return new ArrayList<>();\n    }\n\n    @Override\n    public List<Segment> syncGetSegmentsCountInfo(String clusterName) throws ESOperateException {\n        String segmentsCountContent = getSegmentsCountContent();\n        List<SegmentPO> segmentPOS = esShardDAO.commonGet(clusterName, segmentsCountContent, SegmentPO.class);\n        return ConvertUtil.list2List(segmentPOS, Segment.class);\n    }\n\n\n    @Override\n    public ShardAssignmentDescriptionVO syncShardAssignmentDescription(String cluster) throws ESOperateException {\n        String response = esShardDAO.shardAssignment(cluster);\n        if (null!=response){\n            return buildShardAssignment(JSONObject.parseObject(response));\n        }else {\n            return null;\n        }\n    }\n\n\n    /*********************************************private******************************************/\n\n\n    @NotNull\n    private List<ShardMetrics> getShardMetrics(String clusterName) throws ESOperateException {\n        String shardsRequestContent = getShardsAllInfoRequestContent(\"20s\");\n        return esShardDAO.commonGet(clusterName, shardsRequestContent, ShardMetrics.class);\n    }\n\n    private boolean filterBigShard( long configBigShard,ShardMetrics shardMetrics) {\n        if (null == shardMetrics) { return false;}\n\n        String store = shardMetrics.getStore();\n        if (null == store) { return false;}\n        return  configBigShard<=SizeUtil.getUnitSize(store);\n    }\n\n    private boolean filterSmallShard(long configSmallValue,ShardMetrics shardMetrics,Map<String, List<ShardMetrics>> indexAndShardMetricsMap) {\n        if (null == shardMetrics) {\n            return false;\n        }\n        String store = shardMetrics.getStore();\n        if (null == store) {\n            return false;\n        }\n        int shardNum = indexAndShardMetricsMap.get(shardMetrics.getIndex()).size();\n        return  shardNum>ONE&&SizeUtil.getUnitSize(store)<=configSmallValue;\n    }\n\n    private ShardAssignmentDescriptionVO buildShardAssignment(JSONObject responseJson) {\n        ShardAssignmentDescriptionVO descriptionVO = new ShardAssignmentDescriptionVO();\n        descriptionVO.setShard((Integer) responseJson.get(shard));\n        descriptionVO.setIndex((String) responseJson.get(index));\n        descriptionVO.setPrimary((Boolean) responseJson.get(primary));\n        descriptionVO.setCurrentState((String) responseJson.get(current_state));\n        JSONArray decisionsArray = responseJson.getJSONArray(node_allocation_decisions);\n        List<ShardAssignmenNodeVO> decisions = new ArrayList<>();\n        for (int i = 0; i < decisionsArray.size(); i++) {\n            ShardAssignmenNodeVO decisionMap = new ShardAssignmenNodeVO();\n            JSONObject decisionObject = decisionsArray.getJSONObject(i);\n            decisionMap.setNodeName((String) decisionObject.get(node_name));\n            JSONArray decidersJson = decisionObject.getJSONArray(deciders);\n            JSONObject deciderJson = (JSONObject) decidersJson.get(0);\n            decisionMap.setNodeDecide((String) deciderJson.get(decider));\n            decisionMap.setExplanation((String) deciderJson.get(explanation));\n            decisions.add(decisionMap);\n        }\n        descriptionVO.setDecisions(decisions);\n        return descriptionVO;\n    }\n\n    private String buildSortType(Boolean orderByDesc) {\n        String sortType = \"desc\";\n        if (orderByDesc == null) {\n            return sortType;\n        }\n\n        if (orderByDesc) {\n            return sortType;\n        }\n\n        return \"asc\";\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/es/impl/ESTemplateServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.es.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ESHttpRequestContent.getTemplateNameRequestContent;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.TEMPLATE_DEFAULT_ORDER;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESGatewayClient;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESTemplateDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslLoaderUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.MultiTemplatesConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.TemplateConfig;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author d06679\n * @date 2019/4/2\n */\n@Service\npublic class ESTemplateServiceImpl implements ESTemplateService {\n    private static final ILog LOGGER = LogFactory.getLog(ESTemplateServiceImpl.class);\n\n    @Value(\"${es.update.cluster.name}\")\n    private String                                                      metadataClusterName;\n\n    @Autowired\n    private ESTemplateDAO     esTemplateDAO;\n\n    /**\n     * 加载查询语句工具类\n     */\n    @Autowired\n    private DslLoaderUtil dslLoaderUtil;\n    /**\n     * 查询es客户端\n     */\n    @Autowired\n    private ESGatewayClient gatewayClient;\n\n    /**\n     * 索引type名称为type\n     */\n    private static final String TYPE = \"type\";\n\n    private static final String HEALTH = \"health\";\n\n    /**\n     * 删除模板\n     * @param cluster    集群名字\n     * @param name       模板名字\n     * @param retryCount 重试次数\n     * @return result\n     */\n    @Override\n    public boolean syncDelete(String cluster, String name, int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"deleteTemplate\", retryCount, () -> esTemplateDAO.delete(cluster, name));\n    }\n\n    /**\n     * 修改模板rack和shard\n     *\n     * @param cluster    集群\n     * @param name       模板明细\n     * @param shard      shard\n     * @param retryCount 重试次数\n     * @return result\n     */\n    @Override\n    public boolean syncUpdateShard(String cluster, String name, Integer shard, Integer shardRouting,\n                                   int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"updateTemplateRackAndShard\", retryCount,\n            () -> esTemplateDAO.updateShard(cluster, name, shard, shardRouting));\n    }\n\n    /**\n     * 创建模板, 会覆盖之前的存在的\n     * @param cluster    集群\n     * @param name       模板名字\n     * @param expression 表达式\n     * @param shard      shard\n     * @param retryCount 重试次数\n     * @return result\n     */\n    @Override\n    public boolean syncCreate(String cluster, String name, String expression, Integer shard, Integer shardRouting,\n                              int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"createTemplate\", retryCount,\n            () -> esTemplateDAO.create(cluster, name, expression, shard, shardRouting));\n    }\n\n    @Override\n    public boolean syncCreate(Map<String, String> settings, String cluster, String name, String expression,\n                              MappingConfig mappings, int retryCount) throws ESOperateException {\n        // 获取es中原来index template的配置\n        TemplateConfig templateConfig = esTemplateDAO.getTemplate(cluster, name);\n        if (templateConfig == null) {\n            templateConfig = new TemplateConfig();\n        }\n        if (StringUtils.isNotBlank(expression)) {\n            templateConfig.setTemplate(expression);\n        }\n        if (templateConfig.getOrder() == null) {\n            templateConfig.setOrder(TEMPLATE_DEFAULT_ORDER);\n        }\n        if (MapUtils.isNotEmpty(settings)) {\n            templateConfig.setSetttings(settings);\n        }\n        if (null != mappings) {\n            templateConfig.setMappings(mappings);\n        }\n        TemplateConfig finalTemplateConfig = templateConfig;\n        return ESOpTimeoutRetry.esRetryExecute(\"createTemplate\", retryCount,\n            () -> esTemplateDAO.create(cluster, name, finalTemplateConfig));\n    }\n\n    /**\n     * 修改模板\n     * @param cluster    集群\n     * @param name       模板名字\n     * @param expression 表达式\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean syncUpdateExpression(String cluster, String name, String expression,\n                                        int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"updateExpression\", retryCount,\n            () -> esTemplateDAO.updateExpression(cluster, name, expression));\n    }\n\n    @Override\n    public boolean syncUpdateShardNum(String cluster, String name, Integer shardNum,\n                                      int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"updateShardNum\", retryCount,\n            () -> esTemplateDAO.updateShardNum(cluster, name, shardNum));\n    }\n\n    /**\n     * 修改模板setting\n     *\n     * @param cluster    集群\n     * @param name       模板明细\n     * @param setting    配置\n     * @param retryCount 重试次数\n     * @return result\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean syncUpsertSetting(String cluster, String name, Map<String, String> setting,\n                                     int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"upsertSetting\", retryCount,\n            () -> esTemplateDAO.upsertSetting(cluster, name, setting));\n    }\n    \n    \n    @Override\n    public boolean syncUpdateSettingCheckAllocationAndShard(String cluster, String name, Map<String, String> setting, int retryCount)\n            throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"updateSettingCheckAllocationAndShard\", retryCount,\n            () -> esTemplateDAO.updateSettingCheckAllocationAndShard(cluster, name, setting));\n    }\n    \n    /**\n     * 同步更新物理模板配置\n     * @param cluster 集群名称\n     * @param templateName 物理模板名称\n     * @param templateConfig 模板配置\n     * @param retryCount 重试次数\n     * @return\n     * @throws ESOperateException\n     */\n    @Override\n    public boolean syncUpdateTemplateConfig(String cluster, String templateName, TemplateConfig templateConfig,\n                                            int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"updateTemplateConfig\", retryCount,\n            () -> esTemplateDAO.updateTemplate(cluster, templateName, templateConfig));\n    }\n\n    /**\n     * 跨集群拷贝模板mapping和索引\n     *\n     * @param srcCluster      源集群\n     * @param srcTemplateName 原模板\n     * @param tgtCluster      目标集群\n     * @param tgtTemplateName 目标模板\n     * @param retryCount      重试次数\n     * @return result\n     */\n    @Override\n    public boolean syncCopyMappingAndAlias(String srcCluster, String srcTemplateName, String tgtCluster,\n                                           String tgtTemplateName, int retryCount) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"syncCopyMappingAndAlias\", retryCount,\n            () -> esTemplateDAO.copyMappingAndAlias(srcCluster, srcTemplateName, tgtCluster, tgtTemplateName));\n    }\n\n    /**\n     * 获取模板信息\n     *\n     * @param cluster 集群\n     * @param name    名字\n     * @return Config\n     */\n    @Override\n    public TemplateConfig syncGetTemplateConfig(String cluster, String name) throws ESOperateException {\n        if (StringUtils.isBlank(cluster) || StringUtils.isBlank(name)) {\n            return null;\n        }\n\n        return esTemplateDAO.getTemplate(cluster, name);\n    }\n\n    /**\n     * 获取mapping配置\n     *\n     * @param clusterName\n     * @param templateName\n     * @return\n     */\n    @Override\n    public MappingConfig syncGetMappingsByClusterName(String clusterName, String templateName)\n            throws ESOperateException {\n        MultiTemplatesConfig templatesConfig = syncGetTemplates(clusterName, templateName);\n\n        if (templatesConfig == null || templatesConfig.getSingleConfig() == null) {\n            return null;\n        }\n\n        return templatesConfig.getSingleConfig().getMappings();\n    }\n\n    /**\n     * 获取集群模板配置\n     * @param clusterName 集群名称\n     * @param templateName 模板名称\n     * @return\n     */\n    @Override\n    public MultiTemplatesConfig syncGetTemplates(String clusterName, String templateName) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(\"syncGetTemplates\", 3,\n                () -> esTemplateDAO.getTemplates(clusterName, templateName), Objects::isNull);\n    }\n\n    /**\n     * 获取所有引擎模板\n     * @param clusters 集群名\n     * @return\n     */\n    @Override\n    public Map<String, TemplateConfig> syncGetAllTemplates(List<String> clusters) throws ESOperateException {\n        return esTemplateDAO.getAllTemplate(clusters);\n    }\n\n    /**\n     * 修改模板名称\n     *\n     * @param cluster    集群\n     * @param srcName    源名称\n     * @param tgtName    现名称\n     * @param retryCount\n     * @return\n     */\n    @Override\n    public boolean syncUpdateName(String cluster, String srcName, String tgtName,\n                                  int retryCount) throws ESOperateException {\n        TemplateConfig templateConfig = esTemplateDAO.getTemplate(cluster, srcName);\n        if (templateConfig == null) {\n            return false;\n        }\n\n        if (syncDelete(cluster, srcName, retryCount)) {\n            try {\n                return ESOpTimeoutRetry.esRetryExecute(\"createTemplate\", retryCount,\n                    () -> esTemplateDAO.create(cluster, tgtName, templateConfig));\n            } catch (Exception e) {\n                LOGGER.error(\n                    \"class=ESTemplateServiceImpl||method=syncUpdateName||clusterName={}||srcName={}||tgtName={}||errMsg=exception\",\n                    cluster, srcName, tgtName);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean syncCheckTemplateConfig(String cluster, String name, TemplateConfig templateConfig,\n                                           int retryCount) throws ESOperateException {\n        try {\n            return ESOpTimeoutRetry.esRetryExecute(\"preCreateTemplate\", retryCount,\n                () -> esTemplateDAO.create(cluster, name, templateConfig));\n        } finally {\n            try {\n                ESOpTimeoutRetry.esRetryExecute(\"deleteTemplate\", retryCount,\n                    () -> esTemplateDAO.delete(cluster, name));\n            } catch (Exception e) {\n                LOGGER.error(\n                    \"class=ESTemplateServiceImpl||method=syncCheckTemplateConfig||clusterName={}||name={}||errMsg=exception\",\n                    cluster, name);\n            }\n        }\n    }\n\n    @Override\n    public long syncGetTemplateNum(String cluster) {\n        String templateNameRequestContent = getTemplateNameRequestContent();\n        try {\n            DirectResponse directResponse = esTemplateDAO.getDirectResponse(cluster, \"Get\", templateNameRequestContent);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                List<IndexTemplatePhyPO> indexBelongNodes = ConvertUtil\n                    .str2ObjArrayByJson(directResponse.getResponseContent(), IndexTemplatePhyPO.class);\n\n                return indexBelongNodes.stream().map(IndexTemplatePhyPO::getName).filter(r -> !r.startsWith(\".\"))\n                    .count();\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESTemplateServiceImpl||method=syncGetTemplateNum||clusterName={}||errMsg=exception\",\n                cluster, e.getMessage());\n            return 0;\n        }\n\n        return 0;\n    }\n\n    @Override\n    public long synGetTemplateNumForAllVersion(String cluster) throws ESOperateException {\n        Map<String, TemplateConfig> allTemplate = esTemplateDAO.getAllTemplate(Collections.singletonList(cluster));\n        return MapUtils.isEmpty(allTemplate) ? 0 : allTemplate.size();\n    }\n    \n    /**\n     * @param cluster\n     * @return\n     */\n    @Override\n    public boolean syncGetEsClusterIsNormal(String cluster) {\n        return esTemplateDAO.syncGetClusterIsNormal(cluster);\n    }\n    \n    /**\n     * > 检查指定集群的索引是否匹配指定的表达式和模板健康状态\n     *\n     * @param cluster            集群名称\n     * @param expression         索引的表达式，如“log-*”\n     * @param templateHealthEnum 模板的健康状态，为枚举类型，枚举值如下：\n     * @return 布尔值\n     */\n    @Override\n    public boolean hasMatchHealthIndexByExpressionTemplateHealthEnum(String cluster, String expression,\n                                                                     TemplateHealthEnum templateHealthEnum) {\n        try {\n            //无需关心底层的异常原因，这里在于，我们获取的的分区和非分区，一般来说，分区索引会自动+*，所以不会有错误的异常抛出\n            //那么非分区的话，就会精确到每一个索引名称，此时有可能出现index_not_found_exception，所以这里默认返回false即可\n            return esTemplateDAO.hasMatchHealthIndexByExpressionTemplateHealthEnum(cluster, expression,\n                    templateHealthEnum);\n        } catch (ESOperateException e) {\n            //pass\n        }\n        return false;\n\n    }\n\n    /**\n     * 从元数据索引 arius_cat_index_info 中获取模版每个索引的health状态，从而确定模版health\n     * @param cluster 集群名称\n     * @param wildcard 通配符，如“log-*”\n     * @return  模版健康状态\n     */\n    @Override\n    public Integer getTemplateHealthCode(String cluster, String wildcard) {\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TEMPLATE_INDICES_HEALTH, wildcard);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(\"arius_cat_index_info\");\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, cluster, realIndex, TYPE, dsl,\n                s -> getTemplateHealthESQueryResponse(s), 3);\n    }\n\n    /**************************************** private method ***************************************************/\n\n    private Integer getTemplateHealthESQueryResponse(ESQueryResponse response) {\n        if (response == null || response.getAggs() == null) {\n            LOGGER.warn(\"class=ESTemplateServiceImpl||method=getTemplateHealthESQueryResponse||msg=response is null\");\n            return TemplateHealthEnum.GREEN.getCode();\n        }\n\n        ESAggr esAggr = response.getAggs().getEsAggrMap().get(HEALTH);\n        if(esAggr == null) {\n            return TemplateHealthEnum.GREEN.getCode();\n        }\n        List<ESBucket> bucketList = esAggr.getBucketList();\n        boolean yellowFlag = false;\n        if(!bucketList.isEmpty()) {\n            for (ESBucket esBucket : bucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n\n                String health = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n                if(TemplateHealthEnum.RED.getDesc().equals(health)){\n                    return TemplateHealthEnum.RED.getCode();\n                }else if(TemplateHealthEnum.YELLOW.getDesc().equals(health)) {\n                    yellowFlag = true;\n                }\n            }\n        }\n\n        if(yellowFlag)  {\n            return TemplateHealthEnum.YELLOW.getCode();\n        }\n        return TemplateHealthEnum.GREEN.getCode();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/extend/storage/FileStorageService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.extend.storage;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.remote.storage.content.FileStorageTypeEnum;\nimport org.springframework.web.multipart.MultipartFile;\n\n/**\n * @author linyunan\n * @date 2021-05-19\n */\npublic interface FileStorageService {\n    /**\n     * 根据 FileStorageTypeEnum 获取接口实现类 ,实现上传\n     *\n     * @param fileName   文件名\n     * @param fileMd5    文件md5\n     * @param uploadFile 文件\n     * @return 上传结果\n     * @see FileStorageTypeEnum\n     */\n    Result<String> upload(String fileName, String fileMd5, MultipartFile uploadFile) throws NotFindSubclassException;\n\n    Result<Void> remove(String fileName) throws NotFindSubclassException;\n\n    /**\n     * 根据 FileStorageTypeEnum 获取接口实现类, 实现下载文件\n     *\n     * @param fileName 文件名\n     * @see  FileStorageTypeEnum\n     * @return 文件\n     */\n    Result<MultipartFile> download(String fileName) throws NotFindSubclassException;\n\n    /**\n     * 下载base地址\n     *\n     * @see FileStorageTypeEnum\n     */\n    Result<String> getDownloadBaseUrl() throws NotFindSubclassException;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/extend/storage/impl/FileStorageServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.extend.storage.impl;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.service.extend.storage.FileStorageService;\nimport com.didichuxing.datachannel.arius.admin.remote.storage.FileStorageHandle;\nimport com.didichuxing.datachannel.arius.admin.remote.storage.content.FileStorageTypeEnum;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport javax.annotation.PostConstruct;\n\n/**\n * @author linyunan\n * @date 2021-05-19\n */\n@Service\n@NoArgsConstructor\npublic class FileStorageServiceImpl implements FileStorageService {\n\n    private static final ILog LOGGER = LogFactory.getLog(FileStorageServiceImpl.class);\n\n    @Autowired\n    private HandleFactory     handleFactory;\n\n    @Value(\"${extend.fileStorage}\")\n    private String            fileStorageType;\n\n    @PostConstruct\n    public void fileStorageTypeCheck() {\n        FileStorageTypeEnum fileStorageTypeEnum = FileStorageTypeEnum.valueOfType(fileStorageType);\n        if (fileStorageTypeEnum.getCode().equals(FileStorageTypeEnum.UNKNOWN.getCode())) {\n            LOGGER.error(\"class=FileStorageServiceImpl||method=fileStorageTypeCheck||fileStorageType={}\",\n                fileStorageTypeEnum);\n        }\n    }\n\n    @Override\n    public Result<String> upload(String fileName, String fileMd5,\n                                 MultipartFile uploadFile) throws NotFindSubclassException {\n        Result<FileStorageHandle> result = getFileStorageHandleByType(fileStorageType);\n        if (result.failed()) {\n            LOGGER.info(\"class=FileStorageServiceImpl||method=upload||fileStorageType={}\", fileStorageType);\n            return Result.buildFrom(result);\n        }\n        return result.getData().upload(fileName, fileMd5, uploadFile);\n    }\n\n    @Override\n    public Result<Void> remove(String fileName) throws NotFindSubclassException {\n        Result<FileStorageHandle> result = getFileStorageHandleByType(fileStorageType);\n        if (result.failed()) {\n            LOGGER.info(\"class=FileStorageServiceImpl||method=remove||fileStorageType={}\", fileStorageType);\n            return Result.buildFrom(result);\n        }\n        return result.getData().remove(fileName);\n    }\n\n    @Override\n    public Result<MultipartFile> download(String fileName) throws NotFindSubclassException {\n        Result<FileStorageHandle> result = getFileStorageHandleByType(fileStorageType);\n        if (result.failed()) {\n            LOGGER.info(\"class=FileStorageServiceImpl||method=download||fileStorageType={}\", fileStorageType);\n            return Result.buildFrom(result);\n        }\n        return result.getData().download(fileName);\n    }\n\n    @Override\n    public Result<String> getDownloadBaseUrl() throws NotFindSubclassException {\n        Result<FileStorageHandle> result = getFileStorageHandleByType(fileStorageType);\n        if (result.failed()) {\n            LOGGER.info(\"class=FileStorageServiceImpl||method=getDownloadBaseUrl||fileStorageType={}\", fileStorageType);\n            return Result.buildFrom(result);\n        }\n        return Result.build(Boolean.TRUE, result.getData().getDownloadBaseUrl());\n    }\n\n    /*****************************************private*************************************************************/\n\n    private Result<FileStorageHandle> getFileStorageHandleByType(String fileStorageType) throws NotFindSubclassException {\n        if (FileStorageTypeEnum.valueOfType(fileStorageType).getCode() == -1) {\n            return Result.buildFail(String.format(\"获取 %s 类型出错\", fileStorageType));\n        }\n        LOGGER.info(\"class=FileStorageServiceImpl||method=getDownloadBaseUrl||fileStorageType={}\", fileStorageType);\n        FileStorageHandle fileStorageHandle = (FileStorageHandle) handleFactory.getByHandlerNamePer(fileStorageType);\n        return Result.buildSucc(fileStorageHandle);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/gateway/GatewayService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.gateway;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.GatewayHeartbeat;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.gateway.GatewayClusterNode;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\n\n/**\n * @author didi\n */\npublic interface GatewayService {\n\n    /**\n     * gateway节点提交心跳\n     * @param heartbeat 心跳\n     * @return result\n     */\n    Result<Void> heartbeat(GatewayHeartbeat heartbeat);\n\n    /**\n     * 计算当前存活的节点数目\n     * @param clusterName 集群\n     * @param gapTime  时间\n     * @return count\n     */\n    Result<Integer> aliveCount(String clusterName, long gapTime);\n\n    /**\n     * 重新加载集群\n     */\n    void reloadClusterName();\n\n    /**\n     * 获取集群存活的节点列表\n     * @param clusterName 集群名字\n     * @param timeout  存活超时时间\n     * @return list\n     */\n    List<GatewayClusterNode> getAliveNode(String clusterName, long timeout);\n\n    /**\n     * sql语句直接操作,可以进行sql语句的直接查询,也可以进行sql到dsl语句的转换\n     *\n     * @param sql            sql查询语句\n     * @param phyClusterName 指定查询物理集群名\n     * @param esUser         项目id\n     * @param postFix        sql语句操作后缀\n     * @return 数据查询结果\n     */\n    Result<String> sqlOperate(String sql, String phyClusterName, ESUser esUser, String postFix);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/gateway/impl/GatewayServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.gateway.impl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.GatewayHeartbeat;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.gateway.GatewayClusterNode;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayClusterNodePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayClusterPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.GatewaySqlConstant;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.BaseHttpUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.gateway.GatewayService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESGatewayClient;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.gateway.GatewayClusterDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.gateway.GatewayClusterNodeDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.http.Header;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author didi\n */\n@Service\n@NoArgsConstructor\npublic class GatewayServiceImpl implements GatewayService {\n\n    private static final ILog     LOGGER = LogFactory.getLog(GatewayServiceImpl.class);\n\n    @Autowired\n    private GatewayClusterDAO     gatewayClusterDAO;\n\n    @Autowired\n    private ESGatewayClient       esGatewayClient;\n\n    @Autowired\n    private GatewayClusterNodeDAO gatewayClusterNodeDAO;\n\n    private Set<String>           clusterNames;\n\n    @PostConstruct\n    public void init() {\n        LOGGER.info(\"class=GatewayManageServiceImpl||method=init||GatewayManageServiceImpl init start.\");\n        reloadClusterName();\n        LOGGER.info(\"class=GatewayManageServiceImpl||method=init||GatewayManageServiceImpl init finished.\");\n    }\n\n    /**\n     * gateway节点提交心跳\n     *\n     * @param heartbeat 心跳\n     */\n    @Override\n    public Result<Void> heartbeat(GatewayHeartbeat heartbeat) {\n        Result<Void> checkResult = checkHeartbeat(heartbeat);\n        if (checkResult.failed()) {\n            return checkResult;\n        }\n\n        if (!recordHeartbeat(heartbeat)) {\n            return Result.buildFail(\"save db fail\");\n        }\n\n        if (!clusterNames.contains(heartbeat.getClusterName())) {\n            saveGatewayCluster(heartbeat.getClusterName());\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 计算当前存活的节点数目\n     *\n     * @param clusterName 集群\n     * @param gapTime     时间\n     * @return count\n     */\n    @Override\n    public Result<Integer> aliveCount(String clusterName, long gapTime) {\n        if (AriusObjUtils.isNull(clusterName)) {\n            return Result.buildParamIllegal(\"cluster name is null\");\n        }\n\n        if (gapTime < 0) {\n            return Result.buildParamIllegal(\"gapTime name illegal\");\n        }\n\n        long time = System.currentTimeMillis() - gapTime;\n        return Result.buildSucc(gatewayClusterNodeDAO.aliveCountByClusterNameAndTime(clusterName, new Date(time)));\n    }\n\n    /**\n     * 重新加载集群\n     */\n    @Override\n    public void reloadClusterName() {\n        clusterNames = Sets.newConcurrentHashSet();\n        clusterNames.addAll(\n            gatewayClusterDAO.listAll().stream().map(GatewayClusterPO::getClusterName).collect(Collectors.toSet()));\n    }\n\n    @Override\n    public List<GatewayClusterNode> getAliveNode(String clusterName, long timeout) {\n        Date time = new Date(System.currentTimeMillis() - timeout);\n        return ConvertUtil.list2List(gatewayClusterNodeDAO.listAliveNodeByClusterNameAndTime(clusterName, time),\n            GatewayClusterNode.class);\n    }\n\n    @Override\n    public Result<String> sqlOperate(String sql, String phyClusterName, ESUser esUser, String postFix) {\n        Result<String> result = preSqlParamCheck(sql, postFix);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n\n        String url = GatewaySqlConstant.DEFAULT_HTTP_PRE_FIX + esGatewayClient.getSingleGatewayAddress() + postFix;\n\n        try {\n            // gateway的sql语句操作接口直接以字符串的形式返还结果\n            String sqlResponse = BaseHttpUtil.postForString(url, sql, buildGatewayHeader(phyClusterName, esUser));\n            return Result.buildSucc(sqlResponse, \"\");\n        } catch (Exception e) {\n            LOGGER.error(\"class=GatewayManageServiceImpl||method=directSqlSearch||postFix={}||errMsg={}\", postFix, e);\n        }\n        return Result.buildFail();\n    }\n\n    private Result<String> preSqlParamCheck(String sql, String postFix) {\n        if (StringUtils.isBlank(sql)) {\n            return Result.buildParamIllegal(\"查询的sql语句为空\");\n        }\n        if (StringUtils.isBlank(postFix)) {\n            return Result.buildParamIllegal(\"查询gateway的路径后缀为空\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Map<String, String> buildGatewayHeader(String phyClusterName, ESUser esUser) {\n        Map<String, String> headers = Maps.newHashMap();\n\n        Header header = BaseHttpUtil.buildHttpHeader(String.valueOf(esUser.getId()), esUser.getVerifyCode());\n        headers.put(\"Content-Type\", \"application/json;charset=utf-8\");\n        headers.put(header.getName(), header.getValue());\n        if (!AriusObjUtils.isBlack(phyClusterName)) {\n            headers.put(\"CLUSTER-ID\", phyClusterName);\n        }\n        return headers;\n    }\n\n    private Result<Void> checkHeartbeat(GatewayHeartbeat heartbeat) {\n        if (AriusObjUtils.isNull(heartbeat.getClusterName())) {\n            return Result.buildParamIllegal(\"cluster name is null\");\n        }\n\n        if (AriusObjUtils.isNull(heartbeat.getHostName())) {\n            return Result.buildParamIllegal(\"host name is null\");\n        }\n\n        if (AriusObjUtils.isNull(heartbeat.getPort())) {\n            return Result.buildParamIllegal(\"port is null\");\n        }\n\n        if (heartbeat.getPort() < 1) {\n            return Result.buildParamIllegal(\"port illegal\");\n        }\n        return Result.buildSucc();\n    }\n\n    private boolean recordHeartbeat(GatewayHeartbeat heartbeat) {\n        GatewayClusterNodePO gatewayClusterNodePO = new GatewayClusterNodePO();\n        gatewayClusterNodePO.setClusterName(heartbeat.getClusterName().trim());\n        gatewayClusterNodePO.setHeartbeatTime(new Date());\n        gatewayClusterNodePO.setHostName(heartbeat.getHostName().trim());\n        gatewayClusterNodePO.setPort(heartbeat.getPort());\n        return gatewayClusterNodeDAO.recordGatewayNode(gatewayClusterNodePO) > 0;\n    }\n\n    private void saveGatewayCluster(String clusterName) {\n        GatewayClusterPO gatewayClusterPO = new GatewayClusterPO();\n        gatewayClusterPO.setClusterName(clusterName);\n        if (1 == gatewayClusterDAO.insert(gatewayClusterPO)) {\n            clusterNames.add(clusterName);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/metrics/MetricsDictionaryService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricDictionaryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.metrics.MetricsDictionaryPO;\n\nimport java.util.List;\n\n/**\n * @author gyp\n */\npublic interface MetricsDictionaryService {\n    /**\n     * 获取物理集群指标看板下的配置\n     * @return 二级目录下的指标名称列表\n     */\n    List<MetricsDictionaryPO> list(String model);\n\n    List<MetricsDictionaryPO> listByCondition(MetricDictionaryDTO param);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/metrics/UserConfigService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.UserConfigInfoDTO;\n\nimport java.util.List;\n\n/**\n * @author wangpengkai\n */\npublic interface UserConfigService {\n    /**\n     * 获取物理集群指标看板下的配置\n     * @param param 指标的信息说明DTO\n     * @return 二级目录下的指标名称列表\n     */\n    List<String> getUserConfigByConfigTypeAndUserNameAndProjectId(UserConfigInfoDTO param);\n\n    /**\n     * 更新物理集群看板下的配置\n     * @param param 指标的信息说明DTO\n     * @return result\n     */\n    Result<Integer> updateUserConfigByConfigTypeAndUserNameAndProjectId(UserConfigInfoDTO param);\n\n    /**\n     * 删除用户账号下的指标配置信息\n     * @param userName 账号\n     */\n    void deleteByUserName(String userName,Integer projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/metrics/impl/MetricsDictionaryServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.metrics.impl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricDictionaryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.metrics.MetricsDictionaryPO;\nimport com.didichuxing.datachannel.arius.admin.core.service.metrics.MetricsDictionaryService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.metrics.MetricsDictionaryDAO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName MetricsDictionaryServiceImpl\n * @Author gyp\n * @Date 2022/9/28\n * @Version 1.0\n */\n@Service\npublic class MetricsDictionaryServiceImpl implements MetricsDictionaryService {\n    @Autowired\n    private MetricsDictionaryDAO metricsDictionaryDAO;\n    @Override\n    public List<MetricsDictionaryPO> list(String model) {\n        return metricsDictionaryDAO.listByModel(model);\n    }\n\n    @Override\n    public List<MetricsDictionaryPO> listByCondition(MetricDictionaryDTO param) {\n        return metricsDictionaryDAO.listByCondition(param);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/metrics/impl/UserConfigServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.metrics.impl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.UserConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.config.UserConfigInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.metrics.UserConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.UserConfigTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.metrics.UserConfigService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.metrics.UserConfigDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport org.apache.commons.lang3.BooleanUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author wangpengkai\n * @date 2021/08/10\n */\n@Service\npublic class UserConfigServiceImpl implements UserConfigService {\n\n    private static final ILog    LOGGER    = LogFactory.getLog(UserConfigServiceImpl.class);\n\n    private static final String  USER_NAME = \"user_name\";\n\n    private static final String  PROJECT_ID = \"project_id\";\n\n    private static final String CONFIG_TYPE = \"config_type\";\n\n    @Autowired\n    private UserConfigDAO userConfigDAO;\n\n    @Override\n    public List<String> getUserConfigByConfigTypeAndUserNameAndProjectId(UserConfigInfoDTO param) {\n        UserConfigTypeEnum userConfigTypeEnum = userConfigDTO2Type(param);\n\n        Result<Void> result = paramCheck(param.getUserName(),param.getProjectId(), userConfigTypeEnum);\n        if (result.failed()) {\n            return new ArrayList<>();\n        }\n        UserConfigPO userConfigPO = getUserConfigByUserNameAndProjectIdAndConfigType(param);\n        if (null == userConfigPO || AriusObjUtils.isNull(userConfigPO.getConfigInfo())) {\n            return new ArrayList<>();\n        }\n\n        List<UserConfigInfo> userConfigInfos = JSON.parseArray(userConfigPO.getConfigInfo(),\n            UserConfigInfo.class);\n\n        // 获取对应属性下的配置列表\n        List<List<String>> metricsList = userConfigInfos.stream()\n            .filter(userConfigInfoPO -> userConfigTypeMatch(userConfigInfoPO, userConfigTypeEnum))\n            .map(UserConfigInfo::getUserConfigTypes).collect(Collectors.toList());\n\n        if (metricsList.isEmpty()) {\n            LOGGER.info(\"对应属性的配置内容尚未入库\");\n            return new ArrayList<>();\n        }\n        return metricsList.get(0);\n    }\n\n    @Override\n    public Result<Integer> updateUserConfigByConfigTypeAndUserNameAndProjectId(UserConfigInfoDTO param) {\n        UserConfigTypeEnum userConfigTypeEnum = userConfigDTO2Type(param);\n\n        Result<Void> result = paramCheck(param.getUserName(), param.getProjectId(), userConfigTypeEnum);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n\n        UserConfigPO userConfigPO = getUserConfigByUserNameAndProjectIdAndConfigType(param);\n        if (null == userConfigPO) {\n            return insertUserConfigInfoWithoutCheck(param);\n        }\n\n        List<UserConfigInfo> userConfigInfos = JSON.parseArray(userConfigPO.getConfigInfo(),\n            UserConfigInfo.class);\n\n        boolean ifPresent = false;\n        for (UserConfigInfo userConfigInfoPO : userConfigInfos) {\n            if (userConfigTypeMatch(userConfigInfoPO, userConfigTypeEnum)) {\n                userConfigInfoPO.setUserConfigTypes(param.getUserConfigTypes());\n                ifPresent = true;\n                break;\n            }\n        }\n\n        if (BooleanUtils.isFalse(ifPresent)) {\n            userConfigInfos.add(createUserConfigInfoWithoutCheck(param));\n        }\n\n        userConfigPO.setConfigInfo(JSON.toJSONString(userConfigInfos));\n        boolean succ = (1 == userConfigDAO.update(userConfigPO,buildUserConfigQueryWrapper(param)));\n        return Result.build(succ, userConfigPO.getId());\n    }\n\n    @Override\n    public void deleteByUserName(String userName,Integer projectId) {\n        userConfigDAO.delete(new QueryWrapper<UserConfigPO>().eq(USER_NAME, userName).eq(PROJECT_ID,projectId));\n    }\n\n    /**************************************************** private methods ****************************************************/\n\n    private UserConfigTypeEnum userConfigDTO2Type(UserConfigInfoDTO param) {\n        if (null == param) {\n            return UserConfigTypeEnum.UNKNOWN;\n        }\n        for (UserConfigTypeEnum typeEnum : UserConfigTypeEnum.values()) {\n            if (typeEnum.getFirstUserConfigType().equals(param.getFirstUserConfigType())\n                && typeEnum.getSecondUserConfigType().equals(param.getSecondUserConfigType())) {\n                return typeEnum;\n            }\n        }\n        return UserConfigTypeEnum.UNKNOWN;\n    }\n\n    private Result<Void> paramCheck(String userName, Integer projectId, UserConfigTypeEnum userConfigTypeEnum) {\n        if (AriusObjUtils.isNull(userName)) {\n            return Result.buildFail(\"用户账号为空\");\n        }\n        if(AriusObjUtils.isNull(projectId)){\n            return Result.buildFail(\"应用ID为空\");\n        }\n        if (userConfigTypeEnum.getCode() == UserConfigTypeEnum.UNKNOWN.getCode()) {\n            return Result.buildFail(\"配置类型未知\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private UserConfigPO getUserConfigByUserNameAndProjectIdAndConfigType(UserConfigInfoDTO userConfigInfoDTO) {\n        QueryWrapper<UserConfigPO> queryWrapper = buildUserConfigQueryWrapper(userConfigInfoDTO);\n        return userConfigDAO.selectOne(queryWrapper);\n    }\n\n    private boolean userConfigTypeMatch(UserConfigInfo userConfigInfoPO, UserConfigTypeEnum userConfigTypeEnum) {\n        return userConfigInfoPO.getFirstUserConfigType().equals(userConfigTypeEnum.getFirstUserConfigType())\n               && userConfigInfoPO.getSecondUserConfigType().equals(userConfigTypeEnum.getSecondUserConfigType());\n    }\n\n    private Result<Integer> insertUserConfigInfoWithoutCheck(UserConfigInfoDTO param) {\n        UserConfigPO userConfigPO = new UserConfigPO();\n        userConfigPO.setUserName(param.getUserName());\n        userConfigPO.setProjectId(param.getProjectId());\n        userConfigPO.setConfigType(param.getConfigType());\n        userConfigPO.setConfigInfo(JSON.toJSONString(Arrays.asList(createUserConfigInfoWithoutCheck(param))));\n        boolean succ = (1 == userConfigDAO.insert(userConfigPO));\n        return Result.build(succ, userConfigPO.getId());\n    }\n\n    private UserConfigInfo createUserConfigInfoWithoutCheck(UserConfigInfoDTO param) {\n        UserConfigInfo userConfigInfo = new UserConfigInfo();\n        userConfigInfo.setUserConfigTypes(param.getUserConfigTypes());\n        userConfigInfo.setFirstUserConfigType(param.getFirstUserConfigType());\n        userConfigInfo.setSecondUserConfigType(param.getSecondUserConfigType());\n        userConfigInfo.setUserName(param.getUserName());\n        userConfigInfo.setProjectId(param.getProjectId());\n        return userConfigInfo;\n    }\n    /**\n     * 构建querywrapper\n     * @param param\n     * @return\n     */\n    private QueryWrapper<UserConfigPO> buildUserConfigQueryWrapper(UserConfigInfoDTO param) {\n        QueryWrapper<UserConfigPO> userConfigPOQueryWrapper = new QueryWrapper<>();\n        userConfigPOQueryWrapper.eq(USER_NAME, param.getUserName());\n        userConfigPOQueryWrapper.eq(PROJECT_ID,param.getProjectId());\n        userConfigPOQueryWrapper.eq(CONFIG_TYPE, param.getConfigType());\n        return userConfigPOQueryWrapper;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/project/ESUserService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ESUserDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport java.util.List;\n\n/**\n *es 用户操作\n *\n * @author shizeying\n * @date 2022/05/25\n */\npublic interface ESUserService {\n\n    /**\n     * 指定id查询\n     *\n     * @param esUser\n     * @return app  如果不存在返回null\n     */\n    ESUser getEsUserById(Integer esUser);\n\n    /**\n     * 查询app详细信息\n     *\n     * @return 返回app列表\n     */\n    List<ESUser> listESUsers(List<Integer> projectIds);\n\n    /**\n     * 新建APP\n     *\n     * @param esUserDTO dto\n     * @param operator  操作人 邮箱前缀\n     * @return 成功 true  失败 false\n     */\n    TupleTwo</*创建的es user*/Result, /*创建的es user po*/ ESUserPO> registerESUser(ESUserDTO esUserDTO, String operator);\n\n    /**编辑用户\n     * 编辑APP\n     *\n     * @param esUserDTO dto\n     * @return Tuple<Result < Void>, ESUserPO>\n     */\n    TupleTwo<Result<Void>/*更新的状态*/, ESUserPO/*更新之后的的ESUserPO*/> editUser(ESUserDTO esUserDTO);\n\n    /**\n     * 删除APP\n     *\n     * @param esUser esuser\n     * @return 成功 true  失败 false\n     */\n    TupleTwo<Result<Void>, ESUserPO> deleteESUserById(int esUser);\n\n    TupleTwo<Result<Void>, List<ESUserPO>> deleteByESUsers(int projectId);\n\n    /**\n     * 获取项目下es user 个数\n     *\n     * @param projectId 项目id\n     * @return int\n     */\n    int countByProjectId(int projectId);\n\n    /**\n     * 校验验证码\n     * @param esUserName app\n     * @param verifyCode 验证码\n     * @return result\n     */\n    Result<Void> verifyAppCode(Integer esUserName, String verifyCode);\n\n    /**\n     * 验证APP参数是否合法\n     *\n     * @param appDTO    dto\n     * @param operation 是否校验null参数;  新建的时候需要校验,编辑的时候不需要校验\n     * @return 参数合法返回\n     */\n    Result<Void> validateESUser(ESUserDTO appDTO, OperationEnum operation);\n\n    /**\n     * 查询项目下可以免密登录的es user\n     * @param projectId projectId\n     * @return appList\n     */\n    List<ESUser> getProjectWithoutCodeApps(Integer projectId);\n\n    /**\n     * 通过project 获取默认的es user\n     *\n     * @param projectId 项目id\n     * @return {@code ESUser}\n     */\n    ESUser getDefaultESUserByProject(Integer projectId);\n\n    boolean checkDefaultESUserByProject(Integer projectId);\n\n    /**\n     * 获取项目id通过搜索类型\n     *\n     * @param searchType 搜索类型\n     * @return {@code List<Integer>}\n     */\n    List<Integer> getProjectIdBySearchType(Integer searchType);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/project/ProjectClusterLogicAuthService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectLogicClusterAuthDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport java.util.List;\n\n/**\n * project逻辑集群权限管理服务\n * @author wangshu\n * @date 2020/09/17\n */\npublic interface ProjectClusterLogicAuthService {\n\n    /**\n     * 设置 项目对某逻辑集群的权限. 封装了新增、更新、删除操作，调用接口时只需描述期望的权限状态\n     *\n     * @param projectId      项目\n     * @param logicClusterId 逻辑集群ID\n     * @param auth           要设置的权限\n     * @return 设置结果\n     */\n    Result<Void> ensureSetLogicClusterAuth(Integer projectId, Long logicClusterId, ProjectClusterLogicAuthEnum auth,\n                                           String operator);\n\n    /**\n     * 新增 项目逻辑集群权限\n     * @param logicClusterAuth APP逻辑集群权限\n     * @param operator 操作者\n     * @return\n     */\n    Result<Void> addLogicClusterAuth(ProjectLogicClusterAuthDTO logicClusterAuth, String operator);\n\n    /**\n     * 新增 项目逻辑集群权限\n     * @param logicClusterAuth APP逻辑集群权限\n     * @param operator 操作者\n     * @return\n     */\n    Result<Void> updateLogicClusterAuth(ProjectLogicClusterAuthDTO logicClusterAuth, String operator);\n\n    /**\n     * 删除 项目逻辑集群权限\n     * @param authId 权限点ID\n     * @param operator 操作者\n     * @return\n     */\n    Result<Void> deleteLogicClusterAuthById(Long authId, String operator);\n\n    Result<Boolean> deleteLogicClusterAuthByLogicClusterId(Long logicClusterId);\n\n    /**\n     * 根据权限记录ID获取逻辑集群权限点\n     * @param authId 权限点ID\n     * @return\n     */\n    ProjectClusterLogicAuth getLogicClusterAuthById(Long authId);\n\n    /**\n     * 获取指定 项目对指定逻辑集群的权限.\n     * @param projectId           项目\n     * @param logicClusterId 逻辑集群ID\n     */\n    ProjectClusterLogicAuthEnum getLogicClusterAuthEnum(Integer projectId, Long logicClusterId);\n\n    /**\n     * 获取指定 项目对指定逻辑集群的权限，若没有权限则返回null.\n     * 有权限时，返回结果中id不为null则为来自于权限表的数据，否则为来自于创建表的数据\n     * @param projectId           项目\n     * @param logicClusterId 逻辑集群ID\n     */\n    ProjectClusterLogicAuth getLogicClusterAuth(Integer projectId, Long logicClusterId);\n\n    /**\n     * 获取指定 项目所有权限点\n     * @param projectId  项目\n     * @return\n     */\n    List<ProjectClusterLogicAuth> getAllLogicClusterAuths(Integer projectId);\n\n    /**\n     * 访问权限\n     * @param projectId  项目\n     * @return\n     */\n    List<ProjectClusterLogicAuth> getLogicClusterAccessAuths(Integer projectId);\n\n    /**\n     * 获取指定逻辑集群指定类型的权限点\n     * @param logicClusterId 逻辑集群ID\n     * @param clusterAuthType 逻辑集群权限类型，为null则不筛选权限类型，返回改逻辑集群的全部权限点\n     * @return\n     */\n    List<ProjectClusterLogicAuth> getLogicClusterAuths(Long logicClusterId,\n                                                       ProjectClusterLogicAuthEnum clusterAuthType);\n\n    /**\n     * 判断 项目是否有在指定逻辑集群下创建索引的权限\n     * @param projectId  项目\n     * @param logicClusterId 逻辑集群ID\n     * @return\n     */\n    boolean canCreateLogicTemplate(Integer projectId, Long logicClusterId);\n\n    /**\n     * 增加权限  不做参数校验\n     * @param authDTO  权限信息\n     * @param operator 操作人\n     * @return result\n     */\n    Result<Void> addLogicClusterAuthWithoutCheck(ProjectLogicClusterAuthDTO authDTO, String operator);\n\n    /**\n     * 构建项目对物理集群的权限信息\n     * @param projectId                   项目\n     * @param clusterLogicId          逻辑集群Id\n     * @param projectClusterLogicAuthEnum 权限点\n     * @return\n     */\n    ProjectClusterLogicAuth buildClusterLogicAuth(Integer projectId, Long clusterLogicId,\n                                                  ProjectClusterLogicAuthEnum projectClusterLogicAuthEnum);\n\n    /**\n     * 获取全量权限信息\n     * @return\n     */\n    List<ProjectClusterLogicAuth> list();\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/project/ProjectConfigService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport java.util.Map;\n\n/**\n * 项目config服务 project config 每个项目都会初始化一个项目配置\n *\n * @author shizeying\n * @date 2022/06/01\n * @see com.didiglobal.knowframework.security.common.vo.project.ProjectVO\n */\npublic interface ProjectConfigService {\n    /**\n     * 获取项目config 获取project id配置信息\n     *\n     * @param projectId projectId\n     * @return 配置信息\n     */\n    ProjectConfig getProjectConfig(int projectId);\n\n    /**\n     * 项目id2下项目config地图\n     * <p>\n     * 项目id\n     *\n     * @return {@code Map<Integer, ProjectConfig>}\n     */\n    Map<Integer/*项目id*/, ProjectConfig> projectId2ProjectConfigMap();\n\n    /**\n     * 更新或初始化项目config 更新或初始化projectConfig\n     *\n     * @param configDTO configdto\n     * @param operator  操作人\n     * @return {@code Tuple<Result<Void>, ProjectConfigPO>}\n     */\n    TupleTwo<Result<Void>, ProjectConfigPO> updateOrInitProjectConfig(ProjectConfigDTO configDTO, String operator);\n\n    /**\n     * 按项目id删除 通过项目id逻辑删除项目配置\n     *\n     * @param projectId 项目id\n     */\n    void deleteByProjectId(int projectId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/project/ProjectLogicTemplateAuthService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectTemplateAuthDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * APP逻辑模板权限控制服务\n * @author d06679\n * @date 2019/3/13\n */\npublic interface ProjectLogicTemplateAuthService {\n\n    /**\n     * 元数据校验\n     * @param delete 是否执行删除操作\n     * @return\n     */\n    boolean deleteRedundancyTemplateAuths(boolean delete);\n\n    /**\n     * 在逻辑模板权限表中设置项目对某逻辑模板的权限 封装了新增、更新、删除操作，调用接口时只需描述期望的权限状态\n     *\n     * @param projectId       project的ID\n     * @param logicTemplateId 逻辑模板ID\n     * @param auth            要设置的权限\n     * @return 设置结果\n     */\n    Result<Void> ensureSetLogicTemplateAuth(Integer projectId, Integer logicTemplateId, ProjectTemplateAuthEnum auth,\n                                            String operator);\n\n    /**\n     * 获取project有权限的逻辑模板权限点\n     * @param projectId APP ID\n     * @return 模板权限\n     */\n    List<ProjectTemplateAuth> getTemplateAuthsByProjectId(Integer projectId);\n\n    /**\n     * 从权限表获取prject对active逻辑模板的读写权限点\n     * @param projectId project ID\n     * @return\n     */\n    List<ProjectTemplateAuth> getProjectActiveTemplateRWAndRAuths(Integer projectId);\n\n    List<ProjectTemplateAuth> getProjectTemplateRWAndRAuthsWithoutCodec(Integer projectId);\n\n    List<ProjectTemplateAuth> getProjectActiveTemplateRWAuths(Integer projectId);\n\n    List<ProjectTemplateAuth> getProjectActiveTemplateRAuths(Integer projectId);\n\n    /**\n     * 获取指定逻辑模板的模板权限点列表\n     * @param logicTemplateId 逻辑模板id\n     * @return 模板权限 WR R\n     */\n    List<ProjectTemplateAuth> getTemplateAuthsByLogicTemplateId(Integer logicTemplateId);\n\n    /**\n     * 获取指定逻辑模板的模板权读、读写限点列表\n     */\n    ProjectTemplateAuth getTemplateRWAuthByLogicTemplateIdAndProjectId(Integer logicTemplateId, Integer projectId);\n\n    /**\n     * 增加逻辑模板权限\n     *\n     * @param authDTO 权限信息\n     * @return result\n     */\n    Result<Void> addTemplateAuth(ProjectTemplateAuthDTO authDTO);\n\n    /**\n     * 修改逻辑模板权限，仅可以修改权限类型和责任人\n     *\n     * @param authDTO 参数\n     * @return result\n     */\n    Result<Void> updateTemplateAuth(ProjectTemplateAuthDTO authDTO);\n\n    /**\n     * 删除逻辑模板权限\n     *\n     * @param authId 主键\n     * @return result\n     */\n    Result<Void> deleteTemplateAuth(Long authId);\n\n    /**\n     * 根据逻辑模板id删除权限信息\n     *\n     * @param templateId 模板Id\n     * @return\n     */\n    Result<Void> deleteTemplateAuthByTemplateId(Integer templateId);\n\n    /**\n     * 获取所有project 的权限\n     * @return map, key为APP ID, value为权限点信息\n     */\n    Map<Integer/*projectId*/, Collection<ProjectTemplateAuth>> getAllProjectTemplateAuths();\n\n    /**\n     * 获取当前projectId对逻辑索引的权限\n     * projectId为超级项目, 有所有资源的管理权限\n     */\n    ProjectTemplateAuthEnum getAuthEnumByProjectIdAndLogicId(Integer projectId, Integer logicId);\n\n    /**\n     * 构建具备O指定权限点的模板\n     * @param logicTemplate 逻辑模板\n     * @return\n     */\n    ProjectTemplateAuth buildTemplateAuth(IndexTemplate logicTemplate, ProjectTemplateAuthEnum projectTemplateAuthEnum);\n\n    Integer getProjectIdById(Long authId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/project/impl/ESUserServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.project.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.ADD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.EDIT;\nimport static com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil.obj2Obj;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ESUserDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectSearchTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.VerifyCodeFactory;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ESUserService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.project.ESUserDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author linyunan\n * @date 2021-04-28\n */\n@Service\n@Transactional\npublic class ESUserServiceImpl implements ESUserService {\n\n    private static final ILog    LOGGER                      = LogFactory.getLog(ESUserServiceImpl.class);\n\n    public static final Integer  VERIFY_CODE_LENGTH          = 15;\n\n    private static final Integer APP_QUERY_THRESHOLD_DEFAULT = 100;\n\n    private static final String  ES_USER_NOT_EXIST           = \"es user 不存在\";\n\n    @Autowired\n    private ESUserDAO            esUserDAO;\n\n    /**\n     * 查询app详细信息\n     *\n     * @return 返回app列表\n     */\n    @Override\n    public List<ESUser> listESUsers(List<Integer> projectIds) {\n        return ConvertUtil.list2List(esUserDAO.listByProjectIds(projectIds), ESUser.class);\n    }\n\n    /**\n     * 新建APP\n     *\n     * @param esUserDTO dto\n     * @param operator  操作人 邮箱前缀\n     * @return 成功 true  失败 false\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public TupleTwo<Result, ESUserPO> registerESUser(ESUserDTO esUserDTO, String operator) {\n\n        Result<Void> checkResult = validateESUser(esUserDTO, ADD);\n\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=ESUserManagerImpl||method=addApp||fail msg={}\", checkResult.getMessage());\n            return Tuples.of(checkResult, null);\n        }\n        initParam(esUserDTO);\n        ESUserPO param = obj2Obj(esUserDTO, ESUserPO.class);\n        final int countByProjectId = esUserDAO.countByProjectId(esUserDTO.getProjectId());\n        //如果项目中已经存在es user，那么setDefaultDisplay为false\n        if (countByProjectId == 0) {\n            //新创建的项目会默认创建一个es user ，作为当前项目的默认es user\n            param.setDefaultDisplay(true);\n        } else {\n            param.setDefaultDisplay(false);\n        }\n\n        boolean succ = (esUserDAO.insert(param) == 1);\n\n        return Tuples.of(Result.build(succ, param.getId()), param);\n    }\n\n    /**\n     * 编辑APP\n     *\n     * @param esUserDTO dto\n     * @return 成功 true  失败 false\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public TupleTwo<Result<Void>/*更新的状态*/, ESUserPO/*更新之后的的ESUserPO*/> editUser(ESUserDTO esUserDTO) {\n\n        final ESUserPO param = obj2Obj(esUserDTO, ESUserPO.class);\n\n        return Tuples.of(Result.build((esUserDAO.update(param) == 1)), param);\n\n    }\n\n    /**\n     * 删除APP\n     *\n     * @param esUser\n     * @return 成功 true  失败 false\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public TupleTwo<Result<Void>, ESUserPO> deleteESUserById(int esUser) {\n\n        ESUserPO oldPO = esUserDAO.getByESUser(esUser);\n        boolean succ = esUserDAO.delete(esUser) == 1;\n\n        return Tuples.of(Result.build(succ), oldPO);\n    }\n\n    /**\n     * @param projectId\n     * @return\n     */\n    @Transactional(rollbackFor = Exception.class)\n    @Override\n    public TupleTwo<Result<Void>, List<ESUserPO>> deleteByESUsers(int projectId) {\n        final List<ESUserPO> esUserPOS = esUserDAO.listByProjectId(projectId);\n        final int deleteByProjectId = esUserDAO.deleteByProjectId(projectId);\n        return Tuples.of(Result.build(deleteByProjectId == esUserPOS.size()), esUserPOS);\n    }\n\n    /**\n     * 获取项目下es user 个数\n     *\n     * @param projectId 项目id\n     * @return int\n     */\n    @Override\n    public int countByProjectId(int projectId) {\n        return esUserDAO.countByProjectId(projectId);\n    }\n\n    /**\n     * 指定id查询\n     *\n     * @param esUser esuer\n     * @return app  如果不存在返回null\n     */\n    @Override\n    public ESUser getEsUserById(Integer esUser) {\n        return obj2Obj(esUserDAO.getByESUser(esUser), ESUser.class);\n    }\n\n    /**\n     * 校验验证码\n     *\n     * @param esUserName     esuser\n     * @param verifyCode 验证码\n     * @return result\n     */\n    @Override\n    public Result<Void> verifyAppCode(Integer esUserName, String verifyCode) {\n        final ESUserPO esUser = esUserDAO.getByESUser(esUserName);\n\n        if (esUser == null) {\n            return Result.buildNotExist(ES_USER_NOT_EXIST);\n        }\n\n        if (StringUtils.isBlank(verifyCode) || !esUser.getVerifyCode().equals(verifyCode)) {\n            return Result.buildParamIllegal(\"校验码错误\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 验证APP参数是否合法\n     *\n     * @param appDTO    dto\n     * @param operation 是否校验null参数;  新建的时候需要校验,编辑的时候不需要校验\n     * @return 参数合法返回\n     */\n    @Override\n    public Result<Void> validateESUser(ESUserDTO appDTO, OperationEnum operation) {\n        if (AriusObjUtils.isNull(appDTO)) {\n            return Result.buildParamIllegal(\"应用信息为空\");\n        }\n\n        if (Objects.isNull(appDTO.getProjectId())) {\n            return Result.buildParamIllegal(\"项目id为空\");\n        }\n\n        ESUserPO oldESUser = null;\n        if (Objects.nonNull(appDTO.getId())) {\n            oldESUser = esUserDAO.getByESUser(appDTO.getId());\n        }\n\n        if (ADD.equals(operation)) {\n            if (Objects.nonNull(oldESUser) && !appDTO.getProjectId().equals(oldESUser.getProjectId())) {\n                return Result.buildParamIllegal(String.format(\"es user [%s] 已存在\", appDTO.getId()));\n            }\n            if (StringUtils.isBlank(appDTO.getVerifyCode())) {\n                return Result.buildParamIllegal(\"校验码不能为空\");\n            }\n            \n        } else if (EDIT.equals(operation)) {\n            if (AriusObjUtils.isNull(appDTO.getId()) || AriusObjUtils.isNull(oldESUser)) {\n                return Result.buildNotExist(ES_USER_NOT_EXIST);\n            }\n\n            //判断当前es user 在同一个项目中\n            if (Objects.nonNull(oldESUser) && !Objects.equals(oldESUser.getProjectId(), appDTO.getProjectId())) {\n                return Result.buildParamIllegal(String.format(\"es user 已经存在在项目[%s],不能为项目[%s]创建,请重新提交es user\",\n                    oldESUser.getProjectId(), appDTO.getProjectId()));\n            }\n        }\n\n        if (appDTO.getIsRoot() == null || !AdminConstant.yesOrNo(appDTO.getIsRoot())) {\n            return Result.buildParamIllegal(\"超管标记非法\");\n        }\n        ProjectSearchTypeEnum searchTypeEnum = ProjectSearchTypeEnum.valueOf(appDTO.getSearchType());\n        if (searchTypeEnum.equals(ProjectSearchTypeEnum.UNKNOWN)) {\n            return Result.buildParamIllegal(\"查询模式非法\");\n        }\n       \n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 查询项目下可以免密登录的es user\n     *\n     * @param projectId projectId\n     * @return appList\n     */\n    @Override\n    public List<ESUser> getProjectWithoutCodeApps(Integer projectId) {\n\n        return listESUsers(Collections.singletonList(projectId));\n\n    }\n\n    /**\n     * 获取项目id通过搜索类型\n     *\n     * @param searchType 搜索类型\n     * @return {@code List<Integer>}\n     */\n    @Override\n    public List<Integer> getProjectIdBySearchType(Integer searchType) {\n        return esUserDAO.getProjectIdBySearchType(searchType);\n    }\n\n    /**\n     *\n     * @param projectId\n     * @return\n     */\n    @Override\n    public boolean checkDefaultESUserByProject(Integer projectId) {\n        return esUserDAO.countDefaultESUserByProject(projectId) == 1;\n    }\n\n    /**\n     *\n     * @param projectId\n     * @return\n     */\n    @Override\n    public ESUser getDefaultESUserByProject(Integer projectId) {\n        return esUserDAO.getDefaultESUserByProject(projectId);\n    }\n\n    /**************************************** private method ****************************************************/\n\n    private void initParam(ESUserDTO esUser) {\n        // 默认不是root用户\n        if (esUser.getIsRoot() == null) {\n            esUser.setIsRoot(AdminConstant.NO);\n        }\n\n        if (StringUtils.isBlank(esUser.getDataCenter())) {\n            esUser.setDataCenter(EnvUtil.getDC().getCode());\n        }\n\n        // 默认cluster=\"\"\n        if (esUser.getCluster() == null) {\n            esUser.setCluster(\"\");\n        }\n\n        // 默认索引模式\n        if (esUser.getSearchType() == null) {\n            esUser.setSearchType(ProjectSearchTypeEnum.TEMPLATE.getCode());\n        }\n\n        // 生成默认的校验码\n        if (StringUtils.isBlank(esUser.getVerifyCode())) {\n            esUser.setVerifyCode(VerifyCodeFactory.get(VERIFY_CODE_LENGTH));\n        }\n\n        // 设置默认查询限流值\n        if (esUser.getQueryThreshold() == null) {\n            esUser.setQueryThreshold(APP_QUERY_THRESHOLD_DEFAULT);\n        }\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/project/impl/ProjectClusterLogicAuthServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.project.impl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.OperateRecord;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectLogicClusterAuthDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectClusterLogicAuthPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.auth.ProjectLogicClusterAuthAddEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.auth.ProjectLogicClusterAuthDeleteEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.auth.ProjectLogicClusterAuthEditEvent;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectClusterLogicAuthService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.project.ProjectLogicClusterAuthDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * APP 逻辑集群权限服务\n * @author wangshu\n * @date 2020/09/19\n */\n@Service\npublic class ProjectClusterLogicAuthServiceImpl implements ProjectClusterLogicAuthService {\n\n    private static final ILog          LOGGER = LogFactory.getLog(ProjectLogicTemplateAuthServiceImpl.class);\n\n    @Autowired\n    private ProjectLogicClusterAuthDAO logicClusterAuthDAO;\n\n    @Autowired\n    private ClusterLogicService        clusterLogicService;\n\n    @Autowired\n    private OperateRecordService       operateRecordService;\n    @Autowired\n    private ProjectService             projectService;\n    @Autowired\n    private RoleTool                   roleTool;\n\n    /**\n     * 设置APP对某逻辑集群的权限. 封装了新增、更新、删除操作，调用接口时只需描述期望的权限状态\n     *\n     * @param projectId      APP的ID\n     * @param logicClusterId 逻辑集群ID\n     * @param auth           要设置的权限\n     * @param operator       操作人\n     * @return 设置结果\n     */\n    @Override\n    public Result<Void> ensureSetLogicClusterAuth(Integer projectId, Long logicClusterId,\n                                                  ProjectClusterLogicAuthEnum auth, String operator) {\n        // 参数检查\n        if (projectId == null) {\n            return Result.buildParamIllegal(\"未指定projectId\");\n        }\n\n        if (logicClusterId == null) {\n            return Result.buildParamIllegal(\"未指定逻辑集群ID\");\n        }\n\n        if (StringUtils.isBlank(operator)) {\n            return Result.buildParamIllegal(\"未指定操作人\");\n        }\n\n        // 获取已经存在的权限，可能来自于权限表（id不为null）和创建信息表（id为null）\n        ProjectClusterLogicAuth oldAuth = getLogicClusterAuth(projectId, logicClusterId);\n\n        if (oldAuth == null || oldAuth.getType().equals(ProjectClusterLogicAuthEnum.NO_PERMISSIONS.getCode())) {\n            // 之前无权限\n            return handleNoAuth(projectId, logicClusterId, auth, operator);\n        } else {\n            // 之前有权限\n            if (oldAuth.getId() != null) {\n                // 期望删除权限\n                return deleteAuth(auth,  operator, oldAuth);\n            } else {\n                //权限来自于创建信息表（权限肯定为OWN）,对于集群owner的app权限信息不能修改，只能增加大于OWN的权限\n                return addAuth(projectId, logicClusterId, auth,  operator);\n            }\n        }\n    }\n\n    private Result<Void> addAuth(Integer projectId, Long logicClusterId, ProjectClusterLogicAuthEnum auth,\n                                 String operator) {\n        if (auth != null\n            && ProjectClusterLogicAuthEnum.valueOf(auth.getCode()).higher(ProjectClusterLogicAuthEnum.OWN)) {\n            return addLogicClusterAuth(\n                new ProjectLogicClusterAuthDTO(null, projectId, logicClusterId, auth.getCode()), operator);\n        } else {\n            return Result.buildFail(\"不支持对集群owner的权限进行修改\");\n        }\n    }\n\n    private Result<Void> deleteAuth(ProjectClusterLogicAuthEnum auth,String operator,\n                                    ProjectClusterLogicAuth oldAuth) {\n        if (auth == ProjectClusterLogicAuthEnum.NO_PERMISSIONS) {\n            return deleteLogicClusterAuthById(oldAuth.getId(), operator);\n        }\n\n        // 期望更新权限信息\n        ProjectLogicClusterAuthDTO newAuthDTO = new ProjectLogicClusterAuthDTO(oldAuth.getId(), null, null,\n            auth == null ? null : auth.getCode() );\n        return updateLogicClusterAuth(newAuthDTO, operator);\n    }\n\n    private Result<Void> handleNoAuth(Integer projectId, Long logicClusterId, ProjectClusterLogicAuthEnum auth,\n                                       String operator) {\n        // NO_PERMISSIONS不需添加\n        if (auth == null || auth == ProjectClusterLogicAuthEnum.NO_PERMISSIONS) {\n            return Result.buildSucc();\n        }\n\n        // 新增\n        return addLogicClusterAuth(\n            new ProjectLogicClusterAuthDTO(null, projectId, logicClusterId, auth.getCode()), operator);\n    }\n\n    /**\n     * 插入逻辑集群权限点\n     * @param logicClusterAuth 逻辑集群权限点\n     * @return\n     */\n    @Override\n    public Result<Void> addLogicClusterAuth(ProjectLogicClusterAuthDTO logicClusterAuth, String operator) {\n\n        Result<Void> checkResult = validateLogicClusterAuth(logicClusterAuth, OperationEnum.ADD);\n        if (checkResult.failed()) {\n            LOGGER.warn(\n                \"class=ProjectClusterLogicAuthServiceImpl||method=createLogicClusterAuth||msg={}||msg=check fail!\",\n                checkResult.getMessage());\n            return checkResult;\n        }\n\n        return addLogicClusterAuthWithoutCheck(logicClusterAuth, operator);\n    }\n\n    /**\n     * 更新逻辑集群权限点\n     * @param logicClusterAuth 逻辑集群权限点\n     * @return\n     */\n    @Override\n    public Result<Void> updateLogicClusterAuth(ProjectLogicClusterAuthDTO logicClusterAuth, String operator) {\n        // 只支持修改权限类型和责任人\n        logicClusterAuth.setProjectId(null);\n        logicClusterAuth.setLogicClusterId(null);\n\n        Result<Void> checkResult = validateLogicClusterAuth(logicClusterAuth, OperationEnum.EDIT);\n        if (checkResult.failed()) {\n            LOGGER.warn(\n                \"class=ProjectClusterLogicAuthServiceImpl||method=createLogicClusterAuth||msg={}||msg=check fail!\",\n                checkResult.getMessage());\n            return checkResult;\n        }\n\n        return updateLogicClusterAuthWithoutCheck(logicClusterAuth, operator);\n    }\n\n    /**\n     * 删除权限点\n     * @param authId 权限点ID\n     * @return\n     */\n    @Override\n    public Result<Void> deleteLogicClusterAuthById(Long authId, String operator) {\n\n        ProjectClusterLogicAuthPO oldAuthPO = logicClusterAuthDAO.getById(authId);\n        if (oldAuthPO == null) {\n            return Result.buildNotExist(\"权限不存在\");\n        }\n\n        boolean succeed = 1 == logicClusterAuthDAO.delete(authId);\n        if (succeed) {\n            SpringTool.publish(new ProjectLogicClusterAuthDeleteEvent(this,\n                ConvertUtil.obj2Obj(oldAuthPO, ProjectClusterLogicAuth.class)));\n            operateRecordService.save(new OperateRecord.Builder().bizId(oldAuthPO.getId())\n                .operationTypeEnum(OperateTypeEnum.MY_CLUSTER_OFFLINE).userOperation(operator).build());\n        }\n\n        return Result.build(succeed);\n    }\n\n    @Override\n    public Result<Boolean> deleteLogicClusterAuthByLogicClusterId(Long logicClusterId) {\n        boolean succ = logicClusterAuthDAO.deleteByLogicClusterId(logicClusterId) >= 0;\n        return Result.buildBoolen(succ);\n    }\n\n    /**\n     * 获取APP所有权限点\n     * @param projectId 逻辑ID\n     * @return\n     */\n    @Override\n    public List<ProjectClusterLogicAuth> getAllLogicClusterAuths(Integer projectId) {\n\n        if (projectId == null) {\n            return new ArrayList<>();\n        }\n\n        // 权限表\n        List<ProjectClusterLogicAuthPO> authPOs = logicClusterAuthDAO.listByProjectId(projectId);\n        List<ProjectClusterLogicAuth> authDTOs = ConvertUtil.list2List(authPOs, ProjectClusterLogicAuth.class);\n\n        // 从逻辑集群表获取APP作为owner的集群\n        List<ClusterLogic> clusterLogicList = clusterLogicService.getOwnedClusterLogicListByProjectId(projectId);\n        authDTOs.addAll(clusterLogicList.stream()\n            .map(clusterLogic -> buildLogicClusterAuth(clusterLogic, ProjectClusterLogicAuthEnum.OWN))\n            .collect(Collectors.toList()));\n\n        return authDTOs;\n    }\n\n    @Override\n    public List<ProjectClusterLogicAuth> getLogicClusterAccessAuths(Integer projectId) {\n        return ConvertUtil.list2List(logicClusterAuthDAO.listWithAccessByProjectId(projectId),\n            ProjectClusterLogicAuth.class);\n    }\n\n    /**\n     * 根据ID获取逻辑集群权限点\n     * @param authId 权限点ID\n     * @return\n     */\n    @Override\n    public ProjectClusterLogicAuth getLogicClusterAuthById(Long authId) {\n        return ConvertUtil.obj2Obj(logicClusterAuthDAO.getById(authId), ProjectClusterLogicAuth.class);\n    }\n\n    /**\n     * 获取指定app对指定逻辑集群的权限.\n     * @param projectId          APP ID\n     * @param logicClusterId 逻辑集群ID\n     */\n    @Override\n    public ProjectClusterLogicAuthEnum getLogicClusterAuthEnum(Integer projectId, Long logicClusterId) {\n        if (projectId == null || logicClusterId == null) {\n            return ProjectClusterLogicAuthEnum.NO_PERMISSIONS;\n        }\n\n        ProjectClusterLogicAuth auth = getLogicClusterAuth(projectId, logicClusterId);\n        return auth == null ? ProjectClusterLogicAuthEnum.NO_PERMISSIONS\n            : ProjectClusterLogicAuthEnum.valueOf(auth.getType());\n    }\n\n    /**\n     * 获取指定app对指定逻辑集群的权限，若没有权限则返回null.\n     * 有权限时，返回结果中id不为null则为来自于权限表的数据，否则为来自于创建表的数据\n     * @param projectId          APP ID\n     * @param logicClusterId 逻辑集群ID\n     */\n    @Override\n    public ProjectClusterLogicAuth getLogicClusterAuth(Integer projectId, Long logicClusterId) {\n        if (projectId == null || logicClusterId == null) {\n            return null;\n        }\n\n        // 从逻辑集群表获取创建信息\n        ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdAndProjectId(logicClusterId, projectId);\n        ProjectClusterLogicAuthEnum authFromCreateRecord = (clusterLogic != null\n                                                            && projectId.equals(clusterLogic.getProjectId()))\n                                                                ? ProjectClusterLogicAuthEnum.OWN\n                                                                : ProjectClusterLogicAuthEnum.NO_PERMISSIONS;\n\n        // 从权限表获取权限信息\n        ProjectClusterLogicAuthPO authPO = logicClusterAuthDAO.getByProjectIdAndLogicClusterId(projectId,\n            logicClusterId);\n        ProjectClusterLogicAuthEnum authFromAuthRecord = authPO != null\n            ? ProjectClusterLogicAuthEnum.valueOf(authPO.getType())\n            : ProjectClusterLogicAuthEnum.NO_PERMISSIONS;\n\n        // 都没有权限\n        if (authFromCreateRecord == ProjectClusterLogicAuthEnum.NO_PERMISSIONS\n            && authFromAuthRecord == ProjectClusterLogicAuthEnum.NO_PERMISSIONS) {\n            return buildLogicClusterAuth(clusterLogic, ProjectClusterLogicAuthEnum.NO_PERMISSIONS);\n        }\n\n        // 选择权限高的构建AppLogicClusterAuthDTO，优先取权限表中的记录\n        return authFromAuthRecord.higherOrEqual(authFromCreateRecord)\n            ? ConvertUtil.obj2Obj(authPO, ProjectClusterLogicAuth.class)\n            : buildLogicClusterAuth(clusterLogic, ProjectClusterLogicAuthEnum.OWN);\n\n    }\n\n    /**\n     * 获取逻辑集群权限点列表\n     * @param logicClusterId  逻辑集群ID\n     * @param clusterAuthType 集群权限类型\n     * @return\n     */\n    @Override\n    public List<ProjectClusterLogicAuth> getLogicClusterAuths(Long logicClusterId,\n                                                              ProjectClusterLogicAuthEnum clusterAuthType) {\n\n        ProjectClusterLogicAuthPO queryParams = new ProjectClusterLogicAuthPO();\n        if (logicClusterId != null) {\n            queryParams.setLogicClusterId(logicClusterId);\n        }\n\n        if (clusterAuthType != null) {\n            queryParams.setType(clusterAuthType.getCode());\n        }\n\n        // 权限表\n        List<ProjectClusterLogicAuthPO> authPOs = logicClusterAuthDAO.listByCondition(queryParams);\n        List<ProjectClusterLogicAuth> authDTOS = ConvertUtil.list2List(authPOs, ProjectClusterLogicAuth.class);\n\n        // 从逻辑集群表获取APP作为owner的集群\n        if (logicClusterId != null && clusterAuthType == ProjectClusterLogicAuthEnum.OWN) {\n    \n            clusterLogicService.listClusterLogicByIdThatProjectIdStrConvertProjectIdList(logicClusterId).stream()\n                    .filter(Objects::nonNull)\n                    //需要绑定项目\n                    .map(clusterLogic -> buildLogicClusterAuth(clusterLogic, ProjectClusterLogicAuthEnum.OWN))\n                    .filter(Objects::nonNull).forEach(authDTOS::add);\n        }\n\n        return authDTOS;\n    }\n\n    @Override\n    public boolean canCreateLogicTemplate(Integer projectId, Long logicClusterId) {\n        if (projectId == null || logicClusterId == null) {\n            return false;\n        }\n\n        ProjectClusterLogicAuthEnum authEnum = getLogicClusterAuthEnum(projectId, logicClusterId);\n        return authEnum.higherOrEqual(ProjectClusterLogicAuthEnum.ACCESS);\n    }\n\n    /**\n     * 增加权限  不做参数校验\n     * @param authDTO  权限信息\n     * @param operator 操作人\n     * @return result\n     */\n    @Override\n    public Result<Void> addLogicClusterAuthWithoutCheck(ProjectLogicClusterAuthDTO authDTO, String operator) {\n        ProjectClusterLogicAuthPO authPO = ConvertUtil.obj2Obj(authDTO, ProjectClusterLogicAuthPO.class);\n\n        boolean succeed = 1 == logicClusterAuthDAO.insert(authPO);\n        if (succeed) {\n            // 发送消息\n            SpringTool.publish(\n                new ProjectLogicClusterAuthAddEvent(this, ConvertUtil.obj2Obj(authPO, ProjectClusterLogicAuth.class)));\n\n            // 记录操作\n            operateRecordService.save(new OperateRecord.Builder().content(JSON.toJSONString(authPO))\n                .userOperation(operator).operationTypeEnum(OperateTypeEnum.MY_CLUSTER_INFO_MODIFY)\n                .project(projectService.getProjectBriefByProjectId(authDTO.getProjectId())).bizId(authPO.getId())\n                .build());\n        }\n\n        return Result.build(succeed);\n    }\n\n    @Override\n    public ProjectClusterLogicAuth buildClusterLogicAuth(Integer projectId, Long clusterLogicId,\n                                                         ProjectClusterLogicAuthEnum projectClusterLogicAuthEnum) {\n        if (null == projectClusterLogicAuthEnum || null == projectId || null == clusterLogicId) {\n            return null;\n        }\n\n        if (!ProjectClusterLogicAuthEnum.isExitByCode(projectClusterLogicAuthEnum.getCode())) {\n            return null;\n        }\n\n        ProjectClusterLogicAuth projectClusterLogicAuth = new ProjectClusterLogicAuth();\n        projectClusterLogicAuth.setProjectId(projectId);\n        projectClusterLogicAuth.setLogicClusterId(clusterLogicId);\n        projectClusterLogicAuth.setType(projectClusterLogicAuthEnum.getCode());\n        return projectClusterLogicAuth;\n    }\n\n    @Override\n    public List<ProjectClusterLogicAuth> list() {\n        return ConvertUtil.list2List(logicClusterAuthDAO.listByCondition(null), ProjectClusterLogicAuth.class);\n    }\n\n    /**************************************** private method ****************************************************/\n    /**\n     * 验证权限参数\n     * @param authDTO   参数信息\n     * @param operation 操作\n     * @return result\n     */\n    private Result<Void> validateLogicClusterAuth(ProjectLogicClusterAuthDTO authDTO, OperationEnum operation) {\n\n        LOGGER.debug(\"class=AppAuthServiceImpl||method=validateTemplateAuth||authDTO={}||operator={}\",\n                JSON.toJSONString(authDTO), operation);\n\n        if (authDTO == null) {\n            return Result.buildParamIllegal(\"权限信息为空\");\n        }\n\n        Integer projectId = authDTO.getProjectId();\n        Long logicClusterId = authDTO.getLogicClusterId();\n        ProjectClusterLogicAuthEnum authEnum = ProjectClusterLogicAuthEnum.valueOf(authDTO.getType());\n\n        if (OperationEnum.ADD.equals(operation)) {\n            Result<Void> result = handleAdd(authDTO, projectId, logicClusterId, authEnum);\n            if (result.failed()) {\n                return result;\n            }\n\n        } else if (OperationEnum.EDIT.equals(operation)) {\n            Result<Void> result = handleEdit(authDTO);\n            if (result.failed()) {\n                return result;\n            }\n        }\n\n        Result<Void> isIllegalResult = isIllegal(authDTO, authEnum);\n        if (isIllegalResult.failed()) {\n            return isIllegalResult;\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleEdit(ProjectLogicClusterAuthDTO authDTO) {\n        // 更新权限检查\n        if (AriusObjUtils.isNull(authDTO.getId())) {\n            return Result.buildParamIllegal(\"权限ID为空\");\n        }\n\n        if (null == logicClusterAuthDAO.getById(authDTO.getId())) {\n            return Result.buildNotExist(\"权限不存在\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleAdd(ProjectLogicClusterAuthDTO authDTO, Integer projectId, Long logicClusterId,\n                                   ProjectClusterLogicAuthEnum authEnum) {\n        // 新增权限检查\n        Result<Void> judgeResult = validateProjectIdIsNull(projectId, logicClusterId);\n        if (judgeResult.failed()) {\n            return judgeResult;\n        }\n\n        ClusterLogic clusterLogic = clusterLogicService.getClusterLogicByIdAndProjectId(logicClusterId, projectId);\n        if (AriusObjUtils.isNull(clusterLogic)) {\n            return Result.buildParamIllegal(String.format(\"逻辑集群[%d]不存在\", logicClusterId));\n        }\n\n        if (AriusObjUtils.isNull(authDTO.getType())) {\n            return Result.buildParamIllegal(\"权限类型为空\");\n        }\n\n        // 重复添加不做幂等，抛出错误\n        if (null != logicClusterAuthDAO.getByProjectIdAndLogicClusterId(projectId, logicClusterId)) {\n            return Result.buildDuplicate(\"权限已存在\");\n        }\n\n        // APP是逻辑集群的owner，无需添加\n        if (clusterLogic.getProjectId().equals(projectId) && authEnum == ProjectClusterLogicAuthEnum.OWN) {\n            return Result.buildDuplicate(String.format(\"APP[%d]已有管理权限\", projectId));\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> isIllegal(ProjectLogicClusterAuthDTO authDTO, ProjectClusterLogicAuthEnum authEnum) {\n        if (ProjectClusterLogicAuthEnum.NO_PERMISSIONS == authEnum) {\n            // 不应该走到这一步，防御编码\n            return Result.buildParamIllegal(\"无权限无需添加\");\n        }\n\n        // 不能添加管理权限\n        if (ProjectClusterLogicAuthEnum.ALL == authEnum) {\n            return Result.buildParamIllegal(\"不支持添加超管权限\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> validateProjectIdIsNull(Integer projectId, Long logicClusterId) {\n        if (AriusObjUtils.isNull(projectId)) {\n            return Result.buildParamIllegal(\"projectId为空\");\n        }\n\n        if (!projectService.checkProjectExist(projectId)) {\n            return Result.buildParamIllegal(String.format(\"project [%d]不存在\", projectId));\n        }\n\n        if (AriusObjUtils.isNull(logicClusterId)) {\n            return Result.buildParamIllegal(\"逻辑集群ID为空\");\n        }\n        return Result.buildSucc();\n    }\n\n    /**\n     * 由逻辑集群记录构建owner APP的权限数据\n     * @param clusterLogic 逻辑集群记录\n     */\n    private ProjectClusterLogicAuth buildLogicClusterAuth(ClusterLogic clusterLogic,\n                                                          ProjectClusterLogicAuthEnum projectClusterLogicAuthEnum) {\n        if (clusterLogic == null) {\n            return null;\n        }\n        ProjectClusterLogicAuth appLogicClusterAuth = new ProjectClusterLogicAuth();\n        appLogicClusterAuth.setId(null);\n        appLogicClusterAuth.setProjectId(clusterLogic.getProjectId());\n        appLogicClusterAuth.setLogicClusterId(clusterLogic.getId());\n        appLogicClusterAuth.setType(projectClusterLogicAuthEnum.getCode());\n        return appLogicClusterAuth;\n    }\n\n    /**\n     * 修改权限 可以修改权限类型和责任人 不校验参数\n     * @param authDTO  参数\n     * @param operator 操作人\n     * @return result\n     */\n    private Result<Void> updateLogicClusterAuthWithoutCheck(ProjectLogicClusterAuthDTO authDTO, String operator) {\n\n        ProjectClusterLogicAuthPO oldAuthPO = logicClusterAuthDAO.getById(authDTO.getId());\n        ProjectClusterLogicAuthPO newAuthPO = ConvertUtil.obj2Obj(authDTO, ProjectClusterLogicAuthPO.class);\n        boolean succeed = 1 == logicClusterAuthDAO.update(newAuthPO);\n        if (succeed) {\n            SpringTool.publish(new ProjectLogicClusterAuthEditEvent(this,\n                ConvertUtil.obj2Obj(oldAuthPO, ProjectClusterLogicAuth.class),\n                ConvertUtil.obj2Obj(logicClusterAuthDAO.getById(authDTO.getId()), ProjectClusterLogicAuth.class)));\n            operateRecordService.saveOperateRecordWithManualTrigger(JSON.toJSONString(newAuthPO), operator,\n                    authDTO.getProjectId(), oldAuthPO.getId(), OperateTypeEnum.MY_CLUSTER_INFO_MODIFY);\n        }\n\n        return Result.build(succeed);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/project/impl/ProjectConfigServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.project.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.yesOrNo;\nimport static com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil.obj2Obj;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectConfigService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.project.ProjectConfigDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.Map;\nimport java.util.stream.Collectors;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n *\n *\n * @author shizeying\n * @date 2022/06/01\n */\n@Service\npublic class ProjectConfigServiceImpl implements ProjectConfigService {\n    private static final ILog LOGGER = LogFactory.getLog(ESUserServiceImpl.class);\n    @Autowired\n    private ProjectConfigDAO  projectConfigDAO;\n\n    /**\n     * 获取porject id配置信息\n     *\n     * @param projectId APP ID\n     * @return 配置信息\n     */\n    @Override\n    public ProjectConfig getProjectConfig(int projectId) {\n        return obj2Obj(projectConfigDAO.getByProjectId(projectId), ProjectConfig.class);\n    }\n\n    /**\n     * @return\n     */\n    @Override\n    public Map<Integer, ProjectConfig> projectId2ProjectConfigMap() {\n        return projectConfigDAO.listAll().stream().collect(Collectors.toMap(ProjectConfigPO::getProjectId,\n            projectConfigPO -> ConvertUtil.obj2Obj(projectConfigPO, ProjectConfig.class)));\n    }\n\n    /**\n     * 修改APP配置\n     *\n     * @param configDTO 配置信息\n     * @param operator  操作人\n     * @return 成功 true  失败  false\n     * <p>\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public TupleTwo<Result<Void>, ProjectConfigPO> updateOrInitProjectConfig(ProjectConfigDTO configDTO,\n                                                                             String operator) {\n        Result<Void> checkResult = checkConfigParam(configDTO);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=ProjectConfigServiceImpl||method=updateProjectConfig||msg={}||msg=check fail!\",\n                checkResult.getMessage());\n            return Tuples.of(checkResult, null);\n        }\n        //当项目存在的时候\n        if (projectConfigDAO.checkProjectConfigByProjectId(configDTO.getProjectId())) {\n            ProjectConfigPO oldConfigPO = projectConfigDAO.getByProjectId(configDTO.getProjectId());\n            boolean succ = (1 == projectConfigDAO.update(obj2Obj(configDTO, ProjectConfigPO.class)));\n            return Tuples.of(Result.build(succ), oldConfigPO);\n\n        }\n        //\n        else {\n            ProjectConfigPO param = obj2Obj(configDTO, ProjectConfigPO.class);\n            if (param.getDslAnalyzeEnable() == null) {\n                param.setDslAnalyzeEnable(AdminConstant.YES);\n\n            }\n            if (param.getIsSourceSeparated() == null) {\n                param.setIsSourceSeparated(AdminConstant.NO);\n\n            }\n            if (param.getAggrAnalyzeEnable() == null) {\n                param.setAggrAnalyzeEnable(AdminConstant.YES);\n\n            }\n            if (param.getAnalyzeResponseEnable() == null) {\n                param.setAnalyzeResponseEnable(AdminConstant.YES);\n\n            }\n            boolean succ = (1 == projectConfigDAO.insert(param));\n            final ProjectConfigPO newProjectConfigPO = projectConfigDAO.getByProjectId(configDTO.getProjectId());\n\n            return Tuples.of(Result.build(succ), newProjectConfigPO);\n        }\n\n    }\n\n    /**\n     * @param projectId\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public void deleteByProjectId(int projectId) {\n        if (projectConfigDAO.checkProjectConfigByProjectId(projectId)) {\n            projectConfigDAO.deleteByProjectId(projectId);\n        }\n    }\n\n    private Result<Void> checkConfigParam(ProjectConfigDTO configDTO) {\n        if (configDTO == null) {\n            return Result.buildParamIllegal(\"配置信息为空\");\n        }\n        if (configDTO.getProjectId() == null) {\n            return Result.buildParamIllegal(\"应用ID为空\");\n        }\n        if (configDTO.getAnalyzeResponseEnable() != null && !yesOrNo(configDTO.getAnalyzeResponseEnable())) {\n            return Result.buildParamIllegal(\"解析响应结果开关非法\");\n        }\n        if (configDTO.getDslAnalyzeEnable() != null && !yesOrNo(configDTO.getDslAnalyzeEnable())) {\n            return Result.buildParamIllegal(\"DSL分析开关非法\");\n        }\n        if (configDTO.getAggrAnalyzeEnable() != null && !yesOrNo(configDTO.getAggrAnalyzeEnable())) {\n            return Result.buildParamIllegal(\"聚合分析开关非法\");\n        }\n        if (configDTO.getIsSourceSeparated() != null && !yesOrNo(configDTO.getIsSourceSeparated())) {\n            return Result.buildParamIllegal(\"索引存储分离开关非法\");\n        }\n\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/project/impl/ProjectLogicTemplateAuthServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.project.impl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectTemplateAuthDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectTemplateAuthPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.auth.ProjectTemplateAuthAddEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.auth.ProjectTemplateAuthDeleteEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.auth.ProjectTemplateAuthEditEvent;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectClusterLogicAuthService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.project.ProjectTemplateAuthDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Multimap;\nimport java.util.Collection;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author d06679\n * @date 2019/4/16\n */\n@Service\npublic class ProjectLogicTemplateAuthServiceImpl implements ProjectLogicTemplateAuthService {\n\n    private static final ILog              LOGGER = LogFactory.getLog(ProjectLogicTemplateAuthServiceImpl.class);\n\n    @Autowired\n    private ProjectTemplateAuthDAO         templateAuthDAO;\n\n    @Autowired\n    private ProjectService                 projectService;\n\n    @Autowired\n    private IndexTemplateService           indexTemplateService;\n\n    @Autowired\n    private ProjectClusterLogicAuthService logicClusterAuthService;\n\n    @Autowired\n    private OperateRecordService           operateRecordService;\n\n    @Override\n    public boolean deleteRedundancyTemplateAuths(boolean shouldDeleteFlags) {\n        Map<Integer, IndexTemplate> logicTemplateId2LogicTemplateMappings = ConvertUtil\n            .list2Map(indexTemplateService.listAllLogicTemplates(), IndexTemplate::getId);\n\n        Multimap<Integer, ProjectTemplateAuthPO> projectId2TemplateAuthsMappings = ConvertUtil\n            .list2MulMap(templateAuthDAO.listWithRwAuths(), ProjectTemplateAuthPO::getProjectId);\n\n        Map<Long, ProjectTemplateAuthPO> needDeleteTemplateAuths = Maps.newHashMap();\n\n        for (Integer projectId : projectId2TemplateAuthsMappings.keySet()) {\n            List<ProjectTemplateAuthPO> appTemplateAuths = Lists\n                .newArrayList(projectId2TemplateAuthsMappings.get(projectId));\n\n            Multimap<Integer, ProjectTemplateAuthPO> currentProjectLogicId2TemplateAuthsMappings = ConvertUtil\n                .list2MulMap(appTemplateAuths, ProjectTemplateAuthPO::getTemplateId);\n\n            for (Integer logicTemplateId : currentProjectLogicId2TemplateAuthsMappings.keySet()) {\n                List<ProjectTemplateAuthPO> currentLogicTemplateAuths = Lists\n                    .newArrayList(currentProjectLogicId2TemplateAuthsMappings.get(logicTemplateId));\n\n                if (!logicTemplateId2LogicTemplateMappings.containsKey(logicTemplateId)) {\n                    needDeleteTemplateAuths\n                        .putAll(ConvertUtil.list2Map(currentLogicTemplateAuths, ProjectTemplateAuthPO::getId));\n\n                    LOGGER.info(\n                        \"class=AppLogicTemplateAuthServiceImpl||method=checkMeta||msg=templateDeleted||projectId=={}||logicId={}\",\n                        projectId, logicTemplateId);\n\n                } else if (projectId\n                    .equals(logicTemplateId2LogicTemplateMappings.get(logicTemplateId).getProjectId())) {\n                    needDeleteTemplateAuths\n                        .putAll(ConvertUtil.list2Map(currentLogicTemplateAuths, ProjectTemplateAuthPO::getId));\n\n                    LOGGER.info(\n                        \"class=AppLogicTemplateAuthServiceImpl||method=checkMeta||msg=appOwnTemplate||projectId=={}||logicId={}\",\n                        projectId, logicTemplateId);\n                } else {\n\n                    if (currentLogicTemplateAuths.size() == 1) {\n                        continue;\n                    }\n\n                    currentLogicTemplateAuths.sort(Comparator.comparing(ProjectTemplateAuthPO::getType));\n\n                    needDeleteTemplateAuths.putAll(\n                        ConvertUtil.list2Map(currentLogicTemplateAuths.subList(1, currentLogicTemplateAuths.size()),\n                            ProjectTemplateAuthPO::getId));\n\n                    LOGGER.info(\n                        \"class=AppLogicTemplateAuthServiceImpl||method=checkMeta||msg=appHasMultiTemplateAuth||projectId=={}||logicId={}\",\n                        projectId, logicTemplateId);\n                }\n            }\n        }\n\n        doDeleteOperationForNeed(needDeleteTemplateAuths.values(), shouldDeleteFlags);\n\n        return true;\n    }\n\n    @Override\n    public Result<Void> ensureSetLogicTemplateAuth(Integer projectId, Integer logicTemplateId,\n                                                   ProjectTemplateAuthEnum auth, String operator) {\n        // 参数检查\n        if (projectId == null) {\n            return Result.buildParamIllegal(\"未指定projectId\");\n        }\n\n        if (logicTemplateId == null) {\n            return Result.buildParamIllegal(\"未指定逻辑模板ID\");\n        }\n\n        if (StringUtils.isBlank(operator)) {\n            return Result.buildParamIllegal(\"未指定操作人\");\n        }\n\n        // 获取权限表中已经存在的权限¬记录\n        ProjectTemplateAuthPO oldAuthPO = templateAuthDAO.getByProjectIdAndTemplateId(projectId,\n            String.valueOf(logicTemplateId));\n\n        if (oldAuthPO == null) {\n            // 之前无权限\n            // NO_PERMISSIONS不需添加\n            if (auth == null || auth == ProjectTemplateAuthEnum.NO_PERMISSION) {\n                return Result.buildSucc();\n            }\n\n            // 新增\n            return addTemplateAuth(\n                new ProjectTemplateAuthDTO(null, projectId, logicTemplateId, auth.getCode()));\n        } else {\n            // 有权限记录\n            // 期望删除权限\n            if (auth == ProjectTemplateAuthEnum.NO_PERMISSION) {\n                return deleteTemplateAuth(oldAuthPO.getId());\n            }\n\n            // 期望更新权限信息\n            ProjectTemplateAuthDTO newAuthDTO = new ProjectTemplateAuthDTO(oldAuthPO.getId(), null, null,\n                auth == null ? null : auth.getCode());\n            return updateTemplateAuth(newAuthDTO);\n        }\n    }\n\n    /**\n     * 获取APP有权限的逻辑模板权限点（包括模板所属APP的OWN权限以及添加的R/RW权限）\n     * @param projectId APP ID\n     * @return 模板权限\n     */\n    @Override\n    public List<ProjectTemplateAuth> getTemplateAuthsByProjectId(Integer projectId) {\n        if (!projectService.checkProjectExist(projectId)) {\n            return Lists.newArrayList();\n        }\n\n        //超级项目拥有所有模板own权限\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            List<IndexTemplate> allLogicTemplates = indexTemplateService.listAllLogicTemplates();\n            return allLogicTemplates.stream().map(r -> buildTemplateAuth(r, ProjectTemplateAuthEnum.OWN))\n                .collect(Collectors.toList());\n        }\n\n        // 从权限表获取的权限\n        List<ProjectTemplateAuth> projectTemplateRWAndRAuths = getProjectActiveTemplateRWAndRAuths(projectId);\n\n        // 从逻辑模板表创建信息获取的own权限\n        List<ProjectTemplateAuth> projectTemplateOwnerAuths = getAppTemplateOwnerAuths(projectId);\n        return mergeAppTemplateAuths(projectTemplateRWAndRAuths, projectTemplateOwnerAuths);\n    }\n\n    @Override\n    public ProjectTemplateAuth getTemplateRWAuthByLogicTemplateIdAndProjectId(Integer logicTemplateId,\n                                                                              Integer projectId) {\n        return ConvertUtil.obj2Obj(\n            templateAuthDAO.getByProjectIdAndTemplateId(projectId, String.valueOf(logicTemplateId)),\n            ProjectTemplateAuth.class);\n    }\n\n    /**\n     * 获取逻辑模板权限列表\n     * @param logicTemplateId 逻辑模板ID\n     * @return 模板权限\n     */\n    @Override\n    public List<ProjectTemplateAuth> getTemplateAuthsByLogicTemplateId(Integer logicTemplateId) {\n        return ConvertUtil.list2List(templateAuthDAO.listByLogicTemplateId(String.valueOf(logicTemplateId)),\n            ProjectTemplateAuth.class);\n    }\n\n    /**\n     * 增加权限\n     *\n     * @param authDTO 权限信息\n     * @return result\n     */\n    @Override\n    public Result<Void> addTemplateAuth(ProjectTemplateAuthDTO authDTO) {\n\n        Result<Void> checkResult = validateTemplateAuth(authDTO, OperationEnum.ADD);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=AppAuthServiceImpl||method=addTemplateAuth||msg={}||msg=check fail!\",\n                checkResult.getMessage());\n            return checkResult;\n        }\n\n        return addTemplateAuthWithoutCheck(authDTO);\n    }\n\n    /**\n     * 修改权限 可以修改权限类型和责任人\n     *\n     * @param authDTO 参数\n     * @return result\n     */\n    @Override\n    public Result<Void> updateTemplateAuth(ProjectTemplateAuthDTO authDTO) {\n        Result<Void> checkResult = validateTemplateAuth(authDTO, OperationEnum.EDIT);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=AppAuthServiceImpl||method=updateTemplateAuth||msg={}||msg=check fail!\",\n                checkResult.getMessage());\n            return checkResult;\n        }\n        return updateTemplateAuthWithoutCheck(authDTO);\n    }\n\n    /**\n     * 删除模板权限\n     *\n     * @param authId 主键\n     * @return result\n     */\n    @Override\n    public Result<Void> deleteTemplateAuth(Long authId) {\n\n        ProjectTemplateAuthPO oldAuthPO = templateAuthDAO.getById(authId);\n        if (oldAuthPO == null) {\n            return Result.buildNotExist(\"权限不存在\");\n        }\n\n        boolean succeed = 1 == templateAuthDAO.delete(authId);\n\n        if (succeed) {\n            SpringTool.publish(\n                new ProjectTemplateAuthDeleteEvent(this, ConvertUtil.obj2Obj(oldAuthPO, ProjectTemplateAuth.class)));\n\n        }\n\n        return Result.build(succeed);\n    }\n\n    @Override\n    public Result<Void> deleteTemplateAuthByTemplateId(Integer templateId) {\n        boolean succeed = false;\n        try {\n            List<ProjectTemplateAuthPO> oldAppTemplateAuthPO = templateAuthDAO.getByTemplateId(templateId);\n            if (CollectionUtils.isEmpty(oldAppTemplateAuthPO)) {\n                return Result.buildSucc();\n            }\n\n            List<Integer> oldTemplateIds = oldAppTemplateAuthPO.stream().map(ProjectTemplateAuthPO::getTemplateId)\n                .collect(Collectors.toList());\n            succeed = oldTemplateIds.size() == templateAuthDAO.batchDeleteByTemplateIds(oldTemplateIds);\n            if (Boolean.FALSE.equals(succeed)) {\n                LOGGER.error(\n                    \"class=AppLogicTemplateAuthServiceImpl||method=deleteTemplateAuthByTemplateId||delete infos failed\");\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=AppLogicTemplateAuthServiceImpl||method=deleteTemplateAuthByTemplateId||errMsg={}\",\n                e.getMessage(), e);\n        }\n\n        return Result.build(succeed);\n    }\n\n    /**\n     * @param authId\n     * @return\n     */\n    @Override\n    public Integer getProjectIdById(Long authId) {\n        return templateAuthDAO.getProjectIdById(authId);\n    }\n\n    /**\n     * 获取所有APP的权限\n     * @return map, key为projectId，value为app拥有的权限点集合\n     */\n    @Override\n    public Map<Integer, Collection<ProjectTemplateAuth>> getAllProjectTemplateAuths() {\n\n        List<ProjectTemplateAuth> authTemplates = getAllAppsActiveTemplateRWAuths();\n        authTemplates.addAll(getAllAppsActiveTemplateOwnerAuths());\n\n        return ConvertUtil.list2MulMap(authTemplates, ProjectTemplateAuth::getProjectId).asMap();\n    }\n\n    @Override\n    public ProjectTemplateAuthEnum getAuthEnumByProjectIdAndLogicId(Integer projectId, Integer logicId) {\n        if (AuthConstant.SUPER_PROJECT_ID.equals(projectId)) {\n            return ProjectTemplateAuthEnum.OWN;\n        }\n\n        for (ProjectTemplateAuth appTemplateAuth : getTemplateAuthsByLogicTemplateId(logicId)) {\n            if (projectId.equals(appTemplateAuth.getProjectId())) {\n                return ProjectTemplateAuthEnum.valueOf(appTemplateAuth.getType());\n            }\n        }\n\n        return ProjectTemplateAuthEnum.NO_PERMISSION;\n    }\n\n    @Override\n    public ProjectTemplateAuth buildTemplateAuth(IndexTemplate logicTemplate,\n                                                 ProjectTemplateAuthEnum projectTemplateAuthEnum) {\n        ProjectTemplateAuth auth = new ProjectTemplateAuth();\n        auth.setProjectId(logicTemplate.getProjectId());\n        auth.setTemplateId(logicTemplate.getId());\n        auth.setType(projectTemplateAuthEnum.getCode());\n        return auth;\n    }\n\n    /**************************************** private method ****************************************************/\n    /**\n     * 修改权限 可以修改权限类型和责任人 不校验参数\n     * @param authDTO  参数\n     * @param operator 操作人\n     * @return result\n     */\n    private Result<Void> updateTemplateAuthWithoutCheck(ProjectTemplateAuthDTO authDTO) {\n\n        ProjectTemplateAuthPO oldAuthPO = templateAuthDAO.getById(authDTO.getId());\n        ProjectTemplateAuthPO newAuthPO = ConvertUtil.obj2Obj(authDTO, ProjectTemplateAuthPO.class);\n\n        boolean succeed = 1 == templateAuthDAO.update(newAuthPO);\n\n        if (succeed) {\n            SpringTool.publish(\n                new ProjectTemplateAuthEditEvent(this, ConvertUtil.obj2Obj(oldAuthPO, ProjectTemplateAuth.class),\n                    ConvertUtil.obj2Obj(templateAuthDAO.getById(authDTO.getId()), ProjectTemplateAuth.class)));\n\n        }\n\n        return Result.build(succeed);\n    }\n\n    /**\n     * 增加权限  不做参数校验\n     * @param authDTO  权限信息\n     * @return result\n     */\n    private Result<Void> addTemplateAuthWithoutCheck(ProjectTemplateAuthDTO authDTO) {\n        ProjectTemplateAuthPO authPO = ConvertUtil.obj2Obj(authDTO, ProjectTemplateAuthPO.class);\n        boolean succeed = 1 == templateAuthDAO.insert(authPO);\n        if (succeed) {\n            // 发送消息\n            SpringTool\n                .publish(new ProjectTemplateAuthAddEvent(this, ConvertUtil.obj2Obj(authPO, ProjectTemplateAuth.class)));\n        }\n\n        return Result.build(succeed);\n    }\n\n    /**\n     * 验证权限参数\n     * @param authDTO   参数信息\n     * @param operation 操作\n     * @return result\n     */\n    private Result<Void> validateTemplateAuth(ProjectTemplateAuthDTO authDTO, OperationEnum operation) {\n\n        LOGGER.debug(\"class=AppAuthServiceImpl||method=validateTemplateAuth||authDTO={}\",JSON.toJSONString(authDTO));\n\n\n        if (authDTO == null) {\n            return Result.buildParamIllegal(\"权限信息为空\");\n        }\n\n        Integer projectId = authDTO.getProjectId();\n        Integer logicTemplateId = authDTO.getTemplateId();\n        ProjectTemplateAuthEnum authEnum = ProjectTemplateAuthEnum.valueOf(authDTO.getType());\n\n        if (OperationEnum.ADD.equals(operation)) {\n            Result<Void> result = handleAdd(authDTO, projectId, logicTemplateId, authEnum);\n            if (result.failed()) {\n                return result;\n            }\n        } else if (OperationEnum.EDIT.equals(operation)) {\n            Result<Void> result = handleEdit(authDTO);\n            if (result.failed()) {\n                return result;\n            }\n        }\n\n        // 不能添加管理权限\n        if (ProjectTemplateAuthEnum.OWN == authEnum) {\n            return Result.buildParamIllegal(\"不支持添加管理权限\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleEdit(ProjectTemplateAuthDTO authDTO) {\n        // 更新权限检查\n        if (AriusObjUtils.isNull(authDTO.getId())) {\n            return Result.buildParamIllegal(\"权限ID为空\");\n        }\n\n        if (null == templateAuthDAO.getById(authDTO.getId())) {\n            return Result.buildNotExist(\"权限不存在\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleAdd(ProjectTemplateAuthDTO authDTO, Integer projectId, Integer logicTemplateId,\n                                   ProjectTemplateAuthEnum authEnum) {\n        // 新增权限检查\n        if (AriusObjUtils.isNull(projectId)) {\n            return Result.buildParamIllegal(\"projectId为空\");\n        }\n\n        if (projectService.checkProjectExist(projectId)) {\n            return Result.buildParamIllegal(String.format(\"project[%d]不存在\", projectId));\n        }\n\n        if (AriusObjUtils.isNull(logicTemplateId)) {\n            return Result.buildParamIllegal(\"模板ID为空\");\n        }\n\n        IndexTemplate logicTemplate = indexTemplateService.getLogicTemplateById(logicTemplateId);\n        if (AriusObjUtils.isNull(logicTemplate)) {\n            return Result.buildParamIllegal(String.format(\"逻辑模板[%d]不存在\", logicTemplateId));\n        }\n\n        if (AriusObjUtils.isNull(authDTO.getType())) {\n            return Result.buildParamIllegal(\"权限类型为空\");\n        }\n\n        // 重复添加不做幂等，抛出错误\n        if (null != templateAuthDAO.getByProjectIdAndTemplateId(projectId, String.valueOf(logicTemplateId))) {\n            return Result.buildNotExist(\"权限已存在\");\n        }\n\n        // APP是逻辑模板的owner，无需添加\n        if (logicTemplate.getProjectId().equals(projectId) && authEnum == ProjectTemplateAuthEnum.OWN) {\n            return Result.buildDuplicate(String.format(\"APP[%d]已有管理权限\", projectId));\n        }\n\n        // 有集群权限才能新增索引权限\n        ClusterLogic clusterLogic = indexTemplateService.getLogicTemplateWithClusterAndMasterTemplate(logicTemplateId)\n            .getLogicCluster();\n        if (AriusObjUtils.isNull(clusterLogic) || logicClusterAuthService.getLogicClusterAuthEnum(projectId,\n            clusterLogic.getId()) == ProjectClusterLogicAuthEnum.NO_PERMISSIONS) {\n            return Result.buildOpForBidden(\"没有索引所在集群的权限\");\n        }\n        return Result.buildSucc();\n    }\n\n    /**\n     * 获取所有APP具备OWNER权限模板权限点列表\n     * @return\n     */\n    private List<ProjectTemplateAuth> getAllAppsActiveTemplateOwnerAuths() {\n        List<IndexTemplate> logicTemplates = indexTemplateService.listAllLogicTemplates();\n        List<Integer> projectIds = projectService.getProjectBriefList().stream().map(ProjectBriefVO::getId)\n            .collect(Collectors.toList());\n\n        return logicTemplates.stream()\n            .filter(indexTemplateLogic -> projectIds.contains(indexTemplateLogic.getProjectId()))\n            .map(r -> buildTemplateAuth(r, ProjectTemplateAuthEnum.OWN)).collect(Collectors.toList());\n    }\n\n    /**\n     * 获取所有应用具备RW权限点的模板权限列表\n     * @return\n     */\n    private List<ProjectTemplateAuth> getAllAppsActiveTemplateRWAuths() {\n        List<ProjectTemplateAuth> rwTemplateAuths = ConvertUtil.list2List(templateAuthDAO.listWithRwAuths(),\n            ProjectTemplateAuth.class);\n\n        // 过滤出active的逻辑模板的权限点\n        Set<Integer> logicTemplateIds = indexTemplateService.listAllLogicTemplates().stream().map(IndexTemplate::getId)\n            .collect(Collectors.toSet());\n        return rwTemplateAuths.stream().filter(authTemplate -> logicTemplateIds.contains(authTemplate.getTemplateId()))\n            .collect(Collectors.toList());\n    }\n\n    private List<ProjectTemplateAuth> getAppTemplateOwnerAuths(Integer projectId) {\n        List<IndexTemplate> ownAuthTemplates = indexTemplateService.listProjectLogicTemplatesByProjectId(projectId);\n        return ownAuthTemplates.stream().map(r -> buildTemplateAuth(r, ProjectTemplateAuthEnum.OWN))\n            .collect(Collectors.toList());\n    }\n\n    @Override\n    public List<ProjectTemplateAuth> getProjectActiveTemplateRWAndRAuths(Integer projectId) {\n        return ConvertUtil.list2List(templateAuthDAO.listWithRwAuthsByProjectId(projectId), ProjectTemplateAuth.class);\n    }\n\n    @Override\n    public List<ProjectTemplateAuth> getProjectTemplateRWAndRAuthsWithoutCodec(Integer projectId) {\n        return ConvertUtil.list2List(templateAuthDAO.listWithRwAuthsByProjectId(projectId), ProjectTemplateAuth.class);\n    }\n\n    @Override\n    public List<ProjectTemplateAuth> getProjectActiveTemplateRWAuths(Integer projectId) {\n        ProjectTemplateAuthPO projectTemplateAuthPO = new ProjectTemplateAuthPO();\n        projectTemplateAuthPO.setProjectId(projectId);\n        projectTemplateAuthPO.setType(ProjectTemplateAuthEnum.RW.getCode());\n        return ConvertUtil.list2List(templateAuthDAO.listByCondition(projectTemplateAuthPO), ProjectTemplateAuth.class);\n    }\n\n    @Override\n    public List<ProjectTemplateAuth> getProjectActiveTemplateRAuths(Integer projectId) {\n        ProjectTemplateAuthPO projectTemplateAuthPO = new ProjectTemplateAuthPO();\n        projectTemplateAuthPO.setProjectId(projectId);\n        projectTemplateAuthPO.setType(ProjectTemplateAuthEnum.R.getCode());\n        return ConvertUtil.list2List(templateAuthDAO.listByCondition(projectTemplateAuthPO), ProjectTemplateAuth.class);\n    }\n\n    /**\n     * 模板权限列表\n     * @param templateAuths 模板权限列表\n     * @param deleteFlags   删除标示\n     */\n    private void doDeleteOperationForNeed(Collection<ProjectTemplateAuthPO> templateAuths, boolean deleteFlags) {\n        if (CollectionUtils.isNotEmpty(templateAuths)) {\n            for (ProjectTemplateAuthPO templateAuth : templateAuths) {\n                if (deleteFlags) {\n                    if (1 == templateAuthDAO.delete(templateAuth.getId())) {\n                        LOGGER.info(\n                            \"class=AppLogicTemplateAuthServiceImpl||method=checkMeta||msg=deleteTemplateAuthSucceed||authId={}\",\n                            templateAuth.getId());\n                    }\n                } else {\n                    LOGGER.info(\"class=AppLogicTemplateAuthServiceImpl||method=checkMeta||msg=deleteCheck||authId={}\",\n                        templateAuth.getId());\n                }\n            }\n        }\n    }\n\n    /**\n     * 合并读写、读、管理权限\n     * @param projectTemplateRWAuths       项目对模板有读写、读的权限信息列表\n     * @param projectTemplateOwnerAuths    项目对模板有管理的权限信息列表\n     * @return\n     */\n    private List<ProjectTemplateAuth> mergeAppTemplateAuths(List<ProjectTemplateAuth> projectTemplateRWAuths,\n                                                            List<ProjectTemplateAuth> projectTemplateOwnerAuths) {\n        List<ProjectTemplateAuth> mergeAppTemplateAuthList = Lists.newArrayList();\n        List<Integer> appOwnTemplateId = projectTemplateOwnerAuths.stream().map(ProjectTemplateAuth::getTemplateId)\n            .collect(Collectors.toList());\n\n        //合并读写、读、管理权限\n        for (ProjectTemplateAuth appTemplateRWAuth : projectTemplateRWAuths) {\n            if (appOwnTemplateId.contains(appTemplateRWAuth.getTemplateId())) {\n                continue;\n            }\n            mergeAppTemplateAuthList.add(appTemplateRWAuth);\n        }\n\n        mergeAppTemplateAuthList.addAll(projectTemplateOwnerAuths);\n        return mergeAppTemplateAuthList;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/task/OpTaskService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.OpTaskVO;\n\nimport java.util.List;\n\n/**\n * op任务service\n *\n * @author shizeying\n * @date 2022/08/12\n */\npublic interface OpTaskService {\n    /**\n     * 更新\n     *\n     * @param task 任务\n     * @return boolean\n     */\n    boolean update(OpTask task);\n    \n    /**\n     * 获取通过id\n     *\n     * @param id id\n     * @return {@link OpTask}\n     */\n    OpTask getById(Integer id);\n    \n    /**\n     * 获取所有集合\n     *\n     * @return {@link List}<{@link OpTask}>\n     */\n    List<OpTask> listAll();\n    \n    /**\n     * 获取成功任务通过类型\n     *\n     * @param taskType 任务类型\n     * @return {@link List}<{@link OpTask}>\n     */\n    List<OpTask> getSuccessTaskByType(Integer taskType);\n    \n    /**\n     * 获取pending任务通过类型\n     *\n     * @param taskType 任务类型\n     * @return {@link List}<{@link OpTask}>\n     */\n    List<OpTask> getPendingTaskByType(Integer taskType);\n    \n    /**\n     * 获取最新任务\n     *\n     * @param businessKey 业务key\n     * @param taskType    任务类型\n     * @return {@link OpTask}\n     */\n    OpTask getLatestTask(String businessKey, Integer taskType);\n    \n    /**\n     * 新增\n     *\n     * @param task 任务\n     * @return boolean\n     */\n    boolean insert(OpTask task);\n\n    /**\n     * 任务中心分页查询\n     * @param queryDTO\n     * @return\n     */\n    Tuple<Long, List<OpTaskVO>> pagingGetTasksByCondition(OpTaskQueryDTO queryDTO);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/task/OpTaskServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.task.OpTaskPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.OpTaskVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.SortConstant;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.task.OpTaskDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\n\nimport com.google.common.collect.Lists;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * op任务服务impl\n *\n * @author shizeying\n * @date 2022/08/12\n */\n@Service\n@NoArgsConstructor\npublic class OpTaskServiceImpl implements OpTaskService {\n    private static final ILog      LOGGER = LogFactory.getLog(OpTaskServiceImpl.class);\n    @Autowired\n    private              OpTaskDAO opTaskDao;\n    \n    /**\n     * 更新\n     *\n     * @param task 任务\n     * @return boolean\n     */\n    @Override\n    public boolean update(OpTask task) {\n        return opTaskDao.update(ConvertUtil.obj2Obj(task, OpTaskPO.class)) > 0;\n    }\n    \n    /**\n     * 获取通过id\n     *\n     * @param id id\n     * @return {@link OpTask}\n     */\n    @Override\n    public OpTask getById(Integer id) {\n        return ConvertUtil.obj2Obj(opTaskDao.getById(id), OpTask.class);\n    }\n    \n    /**\n     * 获取所有集合\n     *\n     * @return {@link List}<{@link OpTask}>\n     */\n    @Override\n    public List<OpTask> listAll() {\n        return Optional.ofNullable(opTaskDao.listAll()).map(opTasks -> ConvertUtil.list2List(opTasks, OpTask.class))\n                .orElse(Collections.emptyList());\n    }\n    \n    /**\n     * 获取成功任务通过类型\n     *\n     * @param taskType 任务类型\n     * @return {@link List}<{@link OpTask}>\n     */\n    @Override\n    public List<OpTask> getSuccessTaskByType(Integer taskType) {\n        return ConvertUtil.list2List(opTaskDao.getSuccessTaskByType(taskType), OpTask.class);\n    }\n    \n    /**\n     * 获取pending任务通过类型\n     *\n     * @param taskType 任务类型\n     * @return {@link List}<{@link OpTask}>\n     */\n    @Override\n    public List<OpTask> getPendingTaskByType(Integer taskType) {\n        return ConvertUtil.list2List(opTaskDao.getPendingTaskByType(taskType), OpTask.class);\n    }\n    \n    /**\n     * 获取最新任务\n     *\n     * @param businessKey 业务key\n     * @param taskType    任务类型\n     * @return {@link OpTask}\n     */\n    @Override\n    public OpTask getLatestTask(String businessKey, Integer taskType) {\n        return ConvertUtil.obj2Obj(opTaskDao.getLatestTask(businessKey, taskType), OpTask.class);\n    }\n    \n    /**\n     * 新增\n     *\n     * @param task 任务\n     * @return boolean\n     */\n    @Override\n    public boolean insert(OpTask task) {\n        OpTaskPO opTaskPO = ConvertUtil.obj2Obj(task, OpTaskPO.class);\n        boolean success = opTaskDao.insert(opTaskPO) > 0;\n        task.setId(opTaskPO.getId());\n        return success;\n    }\n\n    @Override\n    public Tuple<Long, List<OpTaskVO>> pagingGetTasksByCondition(OpTaskQueryDTO queryDTO) {\n        String sortTerm = null == queryDTO.getSortTerm() ? SortConstant.ID : queryDTO.getSortTerm();\n        String sortType = queryDTO.getOrderByDesc() ? SortConstant.DESC : SortConstant.ASC;\n        List<OpTaskPO> opTaskPOList = Lists.newArrayList();\n        Long count = 0L;\n        try {\n            opTaskPOList = opTaskDao.pagingByCondition(queryDTO, (queryDTO.getPage() - 1) * queryDTO.getSize(),\n                    queryDTO.getSize(), sortTerm, sortType);\n            count = opTaskDao.countByCondition(queryDTO);\n        } catch (Exception e) {\n            LOGGER.error(\"class=OpTaskServiceImpl||method=pagingGetTasksByCondition||err={}\",\n                    e.getMessage(), e);\n        }\n        return new Tuple<>(count, ConvertUtil.list2List(opTaskPOList,OpTaskVO.class));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/template/dcdr/ESDCDRService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.template.dcdr;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.elasticsearch.client.request.dcdr.DCDRTemplate;\nimport java.util.List;\n\n/**\n * esdcdrservice\n *\n * @author shizeying\n * @date 2022/08/12\n */\npublic interface ESDCDRService {\n    /**\n     * 将自动复制 put自动复制\n     *\n     * @param methodName     方法名称\n     * @param cluster        集群\n     * @param name           名字\n     * @param template       template\n     * @param replicaCluster 集群复制\n     * @param tryTimes       重试次数\n     * @return boolean\n     */\n    boolean put(String methodName, String cluster, String name, String template, String replicaCluster,\n                int tryTimes) throws ESOperateException;\n    \n    /**\n     * 删除自动复制\n     *\n     * @param cluster    集群\n     * @param name       名字\n     * @param methodName 方法名称\n     * @param tryTimes   试次\n     * @return boolean\n     */\n    boolean delete(String methodName, String cluster, String name, int tryTimes) throws ESOperateException;\n    \n    /**\n     * 删除\n     *\n     * @param cluster        集群\n     * @param replicaCluster 集群复制\n     * @param indices        索引集合\n     * @param methodName     方法名称\n     * @param tryTimes       重试次数\n     * @return boolean\n     */\n    boolean delete(String methodName, String cluster, String replicaCluster, List<String> indices, int tryTimes)\n            throws ESOperateException;\n    \n    /**\n     * 获取\n     *\n     * @param cluster 集群\n     * @param name    名字\n     * @return {@link DCDRTemplate}\n     * @throws ESOperateException esoperateException\n     */\n    DCDRTemplate get(String cluster, String name) throws ESOperateException;\n    \n    /**\n     * 存在\n     *\n     * @param cluster 集群\n     * @param name    名字\n     * @return boolean\n     * @throws ESOperateException esoperateException\n     */\n    boolean exist(String cluster, String name) throws ESOperateException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/template/dcdr/ESDCDRServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.template.dcdr;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESDCDRDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.request.dcdr.DCDRTemplate;\nimport com.google.common.collect.Sets;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * esdcdrservice实现\n *\n * @author shizeying\n * @date 2022/08/12\n */\n@Service\npublic class ESDCDRServiceImpl implements ESDCDRService {\n    @Autowired\n    private ESDCDRDAO esDCDRDAO;\n    \n    /**\n     * 将自动复制 put自动复制\n     *\n     * @param methodName     方法名称\n     * @param cluster        集群\n     * @param name           名字\n     * @param template       template\n     * @param replicaCluster 集群复制\n     * @param tryTimes       重试次数\n     * @return boolean\n     */\n    @Override\n    public boolean put(String methodName, String cluster, String name, String template,\n                       String replicaCluster, int tryTimes) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(methodName, tryTimes,\n                () -> esDCDRDAO.putAutoReplication(cluster, name, template, replicaCluster));\n    }\n    \n    @Override\n    public boolean delete(String methodName, String cluster, String name, int tryTimes) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(methodName, tryTimes,\n                () -> esDCDRDAO.deleteAutoReplication(cluster, name));\n    }\n    \n    /**\n     * 删除\n     *\n     * @param methodName     方法名称\n     * @param cluster        集群\n     * @param replicaCluster 集群复制\n     * @param indices        索引集合\n     * @param tryTimes       重试次数\n     * @return boolean\n     */\n    @Override\n    public boolean delete(String methodName, String cluster, String replicaCluster, List<String> indices, int tryTimes)\n            throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(methodName, tryTimes,\n                () -> esDCDRDAO.deleteReplication(cluster, replicaCluster, Sets.newHashSet(indices)));\n    }\n    \n    /**\n     * 获取\n     *\n     * @param cluster 集群\n     * @param name    名字\n     * @return {@link DCDRTemplate}\n     * @throws ESOperateException esoperateException\n     */\n    @Override\n    public DCDRTemplate get(String cluster, String name) throws ESOperateException {\n        return esDCDRDAO.getAutoReplication(cluster, name);\n    }\n    \n    /**\n     * 存在\n     *\n     * @param cluster 集群\n     * @param name    名字\n     * @return boolean\n     * @throws ESOperateException esoperateException\n     */\n    @Override\n    public boolean exist(String cluster, String name) throws ESOperateException {\n        return get(cluster, name) != null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/template/logic/IndexTemplateService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.template.logic;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateRateLimitDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv.TemplateQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateLogicWithClusterAndMasterTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithCluster;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateTypePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\npublic interface IndexTemplateService {\n    /**\n     * 条件查询\n     * @param param 条件\n     * @return 逻辑模板列表\n     */\n    List<IndexTemplate> listLogicTemplates(IndexTemplateDTO param);\n\n    /**\n     * 模糊查询\n     * @param param 模糊查询条件\n     * @return      List<IndexTemplateLogic>\n     */\n    List<IndexTemplate> fuzzyLogicTemplatesByCondition(IndexTemplateDTO param);\n    \n    /**\n     *\n     *\n     * @param param 查询条件对象，与上一方法中的查询条件对象相同。\n     * @param logicClusterIds 逻辑集群 ID 列表。\n     * @return 列表<索引模板>\n     */\n    List<IndexTemplate> pagingGetTemplateSrvByConditionAndLogicClusterIdList(TemplateQueryDTO param, List<Integer> logicClusterIds);\n\n    /**\n     * 模糊分页查询模板列表信息\n     */\n    List<IndexTemplate> pagingGetLogicTemplatesByCondition(TemplateConditionDTO param);\n\n    /**\n     * 模糊分页查询「模板服务」列表信息\n     * @param param 模糊查询条件\n     * @return\n     */\n    List<IndexTemplate> pagingGetTemplateSrvByCondition(TemplateQueryDTO param);\n\n    /**\n     * 模糊查询统计总命中数, 用于前端分页\n     * @param param 模糊查询条件\n     * @return      查询总命中数\n     */\n    Long fuzzyLogicTemplatesHitByCondition(IndexTemplateDTO param);\n   \n    /**\n     * 它返回与给定条件和逻辑集群 ID 匹配的模板数量。\n     *\n     * @param param 将用于构造查询的参数对象。\n     * @param logicClusterIds 逻辑集群 ID 列表。\n     * @return 长\n     */\n    Long fuzzyLogicTemplatesHitByConditionAndLogicClusterIdList(IndexTemplateDTO param,List<Integer> logicClusterIds);\n\n    /**\n     * 根据名字查询\n     * @param templateName 模板名字\n     * @return list\n     */\n    List<IndexTemplate> listLogicTemplateByName(String templateName);\n\n    /**\n     * 查询指定的逻辑模板\n     * @param logicTemplateId 模板id\n     * @return 模板信息  不存在返回null\n     */\n    IndexTemplate getLogicTemplateById(Integer logicTemplateId);\n\n    /**\n     * 删除逻辑模板\n     *\n     * @param logicTemplateId 模板id\n     * @param operator        操作人\n     * @return result\n     * @throws AdminOperateException\n     */\n    Result<Void> delTemplate(Integer logicTemplateId, String operator) throws AdminOperateException;\n\n    /**\n     * 校验模板参数是否合法\n     * @param param 参数\n     * @param operation 操作\n     * @return result\n     */\n    Result<Void> validateTemplate(IndexTemplateDTO param, OperationEnum operation, Integer projectId);\n\n    /**\n     * 编辑逻辑模板\n     * @param param 参数\n     * @param operator 操作人\n     * @return result\n     * @throws AdminOperateException 操作es失败\n     */\n    Result<Void> editTemplate(IndexTemplateDTO param, String operator, Integer projectId) throws AdminOperateException;\n\n    /**\n     * 添加逻辑模板而不需要参数校验\n     * @param param 索引逻辑模板参数\n     * @return result\n     */\n    Result<Void> addTemplateWithoutCheck(IndexTemplateDTO param) throws AdminOperateException;\n\n    /**\n     * 获取模板配置信息\n     * @param logicTemplateId 逻辑模板id\n     * @return 配置信息  不存在返回null\n     */\n    IndexTemplateConfig getTemplateConfig(Integer logicTemplateId);\n\n    /**\n     * 更新模板配置\n     * @param configDTO  配置参数\n     * @param operator 操作人\n     * @return result\n     */\n    Result<Void> updateTemplateConfig(IndexTemplateConfigDTO configDTO, String operator);\n\n    /**\n     * 记录模板配置\n     *\n     * @param indexTemplateConfig 索引模板配置\n     * @return result\n     */\n    Result<Void> insertTemplateConfig(IndexTemplateConfig indexTemplateConfig);\n\n    /**\n     * 更新模板配置\n     * @param logicTemplateId  逻辑模板id\n     * @param factor  factor\n     * @param operator 操作人\n     */\n    void upsertTemplateShardFactor(Integer logicTemplateId, Double factor, String operator);\n\n    /**\n     * 更新模板配置\n     * @param logicTemplateId  逻辑模板id\n     * @param factor  factor\n     * @param operator 操作人\n     */\n    void updateTemplateShardFactorIfGreater(Integer logicTemplateId, Double factor, String operator);\n\n    /**\n     * 判断模板是否存在\n     * @param logicTemplateId 逻辑模板id\n     * @return true/false\n     */\n    boolean exist(Integer logicTemplateId);\n\n    /**\n     * 获取全部逻辑模板\n     * @return list\n     */\n    List<IndexTemplate> listAllLogicTemplates();\n\n    List<IndexTemplate> listAllLogicTemplatesWithCache();\n\n    /**\n     * 获取全部逻辑模板\n     * @return map，key-逻辑模板ID，value-逻辑模板\n     */\n    Map<Integer, IndexTemplate> getAllLogicTemplatesMap();\n\n    /**\n     * 根据列表获取逻辑模板\n     * @return list\n     */\n    List<IndexTemplate> listLogicTemplatesByIds(List<Integer> logicTemplateIds);\n\n    /**\n     * 根据列表获取逻辑模板\n     * @return map，key-逻辑模板ID，value-逻辑模板\n     */\n    Map<Integer, IndexTemplate> getLogicTemplatesMapByIds(List<Integer> logicTemplateIds);\n\n    /**\n     * 根据projectId查询模板\n     * @param projectId projectId\n     * @return list\n     */\n    List<IndexTemplate> listProjectLogicTemplatesByProjectId(Integer projectId);\n\n    /**\n     * 获取所有逻辑集群对应逻辑模板\n     * @param logicClusterId 逻辑集群ID\n     * @return\n     */\n    List<IndexTemplate> listLogicClusterTemplates(Long logicClusterId);\n\n    /**\n     * 获取模板具体的物理索引\n     * @param projectId projectId\n     * @return result\n     */\n    Result<List<Tuple<String, String>>> listLogicTemplatesByProjectId(Integer projectId);\n\n    /**\n     * 模板移交\n     *\n     * @param logicId         模板id\n     * @param sourceProjectId 原项目\n     * @param tgtProjectId    projectId\n     * @param operator        操作人\n     * @return Result\n     * @throws AdminOperateException\n     */\n    Result<Void> turnOverLogicTemplate(Integer logicId, Integer sourceProjectId, Integer tgtProjectId,\n                                        String operator) throws AdminOperateException;\n\n    /**\n     * 获取每个模板的部署个数\n     * @return map\n     */\n    Map<Integer, Integer> getAllLogicTemplatesPhysicalCount();\n\n    /**\n     * 获取type\n     * @param logicId 模板id\n     * @return list\n     */\n    List<IndexTemplateType> listLogicTemplateTypes(Integer logicId);\n\n    /**\n     * 修改模板名称\n     * @param param 参数\n     * @param operator 操作人\n     * @return result\n     * @throws AdminOperateException\n     */\n    Result<Void> editTemplateName(IndexTemplateDTO param, String operator) throws AdminOperateException;\n\n    /**\n     * 只更新本地db 不同步更新es\n     * @param param\n     * @return\n     * @throws AdminOperateException\n     */\n    Result<Void> editTemplateInfoTODB(IndexTemplateDTO param) throws AdminOperateException;\n\n    /**\n     * 获取APP有权限的集群下的所有逻辑模板.\n     * @param projectId APP的id\n     * @return list\n     */\n    List<IndexTemplate> listTemplatesByHasAuthCluster(Integer projectId);\n\n    /**\n     * 获取APP在指定逻辑集群下有权限的逻辑模板.\n     * @param projectId project的id\n     * @param logicClusterId 逻辑集群ID\n     * @return list\n     */\n    List<IndexTemplate> listHasAuthTemplatesInLogicCluster(Integer projectId, Long logicClusterId);\n\n    /**\n     * 获取所有的逻辑模板列表信息（带有逻辑集群和物理模板）\n     * @return\n     */\n    List<IndexTemplateLogicWithClusterAndMasterTemplate> listLogicTemplatesWithClusterAndMasterTemplate();\n\n    /**\n     * 获取指定逻辑模板（带有逻辑集群和物理模板）\n     * @param logicTemplateId 逻辑模板id\n     */\n    IndexTemplateLogicWithClusterAndMasterTemplate getLogicTemplateWithClusterAndMasterTemplate(Integer logicTemplateId);\n    String getMaterClusterPhyByLogicTemplateId(Integer logicTemplateId);\n\n    /**\n     * 获取指定逻辑模板列表信息（带有逻辑集群和物理模板）\n     * @param logicTemplateIds 逻辑模板列表\n     * @return\n     */\n    List<IndexTemplateLogicWithClusterAndMasterTemplate> listLogicTemplatesWithClusterAndMasterTemplate(Set<Integer> logicTemplateIds);\n\n    /**\n     * 获取指定逻辑模板列表信息（带有逻辑集群和物理模板）\n     * @param logicTemplateIds 逻辑模板列表\n     * @return map, key-逻辑模板ID, value-带有逻辑集群和物理模板信息的逻辑模板对象\n     */\n    Map<Integer, IndexTemplateLogicWithClusterAndMasterTemplate> getLogicTemplatesWithClusterAndMasterTemplateMap(Set<Integer> logicTemplateIds);\n\n    /**\n     * 获取指定集群下的逻辑模板（带有逻辑集群和物理模板）\n     * @param logicClusterIds 逻辑集群id列表\n     */\n    List<IndexTemplateLogicWithClusterAndMasterTemplate> listLogicTemplateWithClusterAndMasterTemplateByClusters(Set<Long> logicClusterIds);\n\n    /**\n     * 获取指定集群下的逻辑模板（带有逻辑集群和物理模板）\n     * @param logicClusterId 逻辑集群id\n     */\n    List<IndexTemplateLogicWithClusterAndMasterTemplate> listLogicTemplateWithClusterAndMasterTemplateByCluster(Long logicClusterId);\n\n    /**\n     * 获取单个逻辑模板逻辑集群相关信息\n     * @param logicTemplateId 逻辑模板ID\n     * @return\n     */\n    IndexTemplateWithCluster getLogicTemplateWithCluster(Integer logicTemplateId);\n\n    /**\n     * 查询模板资源信息\n     * @param logicTemplateIds 逻辑模板ID列表\n     * @return\n     */\n    List<IndexTemplateWithCluster> listLogicTemplateWithClusters(Set<Integer> logicTemplateIds);\n\n    /**\n     * 查询模板资源信息\n     * @return 带有逻辑集群的所有逻辑模板列表\n     */\n    List<IndexTemplateWithCluster> listAllLogicTemplateWithClusters();\n\n    /**\n     * 查询模板资源信息\n     * @param logicClusterId 逻辑集群ID\n     * @return List<IndexTegetAllLogicClustersmplateLogicClusterMeta> 逻辑模板列表\n     */\n    List<IndexTemplateWithCluster> listLogicTemplateWithClustersByClusterId(Long logicClusterId);\n\n    /**\n     * 获取所有带有物理模板详情的逻辑模板列表\n     * @return\n     */\n    List<IndexTemplateWithPhyTemplates> listAllLogicTemplateWithPhysicals();\n\n    /**\n     * 获取指定的带有物理模板详情的逻辑模板列表\n     * @return\n     */\n    List<IndexTemplateWithPhyTemplates> listLogicTemplateWithPhysicalsByIds(Set<Integer> logicTemplateIds);\n\n    /**\n     * 根据逻辑模板ID获取对应的物理模板详情\n     * @param logicTemplateId 逻辑模板ID\n     * @return\n     */\n    IndexTemplateWithPhyTemplates getLogicTemplateWithPhysicalsById(Integer logicTemplateId);\n\n    /**\n     * 获取指定数据中的模板信息\n     *\n     * @return list\n     */\n    List<IndexTemplateWithPhyTemplates> listTemplateWithPhysical();\n\n    /**\n     * 修改禁读状态\n     *\n     * @param logicId   逻辑模板\n     * @param blockRead 是否禁读\n     * @return\n     */\n    Result<Void> updateBlockReadState(Integer logicId, Boolean blockRead);\n\n    /**\n     * 修改禁写状态\n     *\n     * @param logicId    逻辑模板\n     * @param blockWrite 是否禁读\n     * @return\n     */\n    Result<Void> updateBlockWriteState(Integer logicId, Boolean blockWrite);\n\n    Result updateTemplateWriteRateLimit(ConsoleTemplateRateLimitDTO consoleTemplateRateLimitDTO) throws ESOperateException;\n\n    Result<Void> preCheckTemplateName(String templateName);\n\n    /**\n     * 获取指定regionId下的所有模板列表\n     * @param regionId  regionId\n     * @return    Result<List<IndexTemplate>>\n     */\n    Result<List<IndexTemplate>> listByRegionId(Integer regionId);\n\n    List<IndexTemplateWithCluster> convert2WithCluster(List<IndexTemplateWithPhyTemplates> indexTemplateWithPhyTemplates);\n\n    /**\n     * 根据逻辑集群id 列表获取逻辑模板列表\n     * @param resourceIds\n     * @return\n     */\n    List<IndexTemplate> listByResourceIds(List<Long> resourceIds);\n\n    /**\n     * 获取项目id通过模板逻辑id\n     *\n     * @param templateLogicId 模板逻辑id\n     * @return {@code Integer}\n     */\n    Integer getProjectIdByTemplateLogicId(Integer templateLogicId);\n\n    IndexTemplatePO getLogicTemplatePOById(Integer logicId);\n\n    boolean update(IndexTemplatePO editTemplate);\n\n    int batchChangeHotDay(Integer days, List<Integer> templateIdList);\n\n    String getNameByTemplateLogicId(Integer logicTemplateId);\n    \n    List<Integer> getLogicTemplateIdListByProjectId(Integer projectId);\n    \n     /**\n     * 获取通过逻辑id\n     *\n     * @param logicId 逻辑标识\n     * @return {@link TemplateConfigPO}\n     */\n    TemplateConfigPO getTemplateConfigByLogicId(Integer logicId);\n    \n    /**\n     * 更新\n     *\n     * @param param 入参\n     * @return boolean\n     */\n    boolean updateTemplateType(TemplateTypePO param);\n\t\n\t\n\t/**\n\t * 通过逻辑模板ID获取主模板的物理模板ID\n\t *\n\t * @param logicTemplateId 逻辑模板 ID。\n\t * @return 长\n\t */\n\tLong getMasterTemplatePhyIdByLogicTemplateId(Integer logicTemplateId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/template/logic/TemplateLogicAliasService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.template.logic;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.IndexTemplateAliasDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateAlias;\nimport java.util.List;\nimport java.util.Map;\n\npublic interface TemplateLogicAliasService {\n\n    /**\n     * 获取所有的别名\n     *\n     * @param logicId logicId\n     * @return list\n     */\n    List<String> getAliasesById(Integer logicId);\n\n    /**\n     * 从缓存中获取模板所有的别名\n     * @param logicId\n     * @return\n     */\n    List<String> getAliasesByIdFromCache(Integer logicId);\n\n    /**\n     * 获取别名\n     *\n     * @return list\n     */\n    List<IndexTemplateAlias> listAlias();\n\n    /**\n     * 增加一个索引的别名\n     *\n     * @param indexTemplateAlias\n     * @return\n     */\n    Result<Boolean> addAlias(IndexTemplateAliasDTO indexTemplateAlias);\n\n    /**\n     * 删除一个索引的别名\n     *\n     * @param indexTemplateAlias\n     * @return\n     */\n    Result<Boolean> delAlias(IndexTemplateAliasDTO indexTemplateAlias);\n\n    /**\n     * 获取平台所有索引别名\n     *\n     * @return\n     */\n    Map<Integer/*logicId*/, List<String>/*aliasNames*/> listAliasMap();\n\n    /**\n     * 从缓存中获取平台所有索引别名\n     * @return\n     */\n    Map<Integer, List<String>> listAliasMapWithCache();\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/template/logic/impl/IndexTemplateServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.template.logic.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.yesOrNo;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_NAME_CHAR_SET;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_NAME_SIZE_MAX;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_NAME_SIZE_MIN;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_NOT_EXIST;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_SAVE_BY_DAY_EXPIRE_MAX;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_SAVE_BY_MONTH_EXPIRE_MIN;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.ADD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.EDIT;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateRateLimitDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv.TemplateQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateLogicWithClusterAndMasterTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithCluster;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateTypePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.DataCenterEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.LevelEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.SortConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.LogicTemplateModifyEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ProjectUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.TemplateUtils;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectClusterLogicAuthService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateConfigDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateTypeDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.TemplateConfig;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Multimap;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Supplier;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.dao.DuplicateKeyException;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Service\npublic class IndexTemplateServiceImpl implements IndexTemplateService {\n\n    private static final ILog                  LOGGER            = LogFactory.getLog(IndexTemplateServiceImpl.class);\n\n    @Autowired\n    private IndexTemplateDAO                   indexTemplateDAO;\n\n    @Autowired\n    private IndexTemplateConfigDAO             indexTemplateConfigDAO;\n\n    @Autowired\n    private IndexTemplateTypeDAO               indexTemplateTypeDAO;\n\n    @Autowired\n    private IndexTemplatePhyService            indexTemplatePhyService;\n\n    @Autowired\n    private ProjectService                     projectService;\n\n    @Autowired\n    private ESIndexService                     esIndexService;\n\n    @Autowired\n    private ProjectLogicTemplateAuthService    logicTemplateAuthService;\n\n    @Autowired\n    private ProjectClusterLogicAuthService     logicClusterAuthService;\n\n    @Autowired\n    private ClusterLogicService                clusterLogicService;\n\n  \n\n    @Autowired\n    private ClusterRegionService               clusterRegionService;\n\n    private Cache<String, List<IndexTemplate>> templateListCache = CacheBuilder.newBuilder()\n        .expireAfterWrite(1, TimeUnit.MINUTES).maximumSize(10).build();\n\n    /**\n     * 条件查询\n     *\n     * @param param 条件\n     * @return 逻辑模板列表\n     */\n    @Override\n    public List<IndexTemplate> listLogicTemplates(IndexTemplateDTO param) {\n        return ConvertUtil.list2List(\n            indexTemplateDAO.listByCondition(ConvertUtil.obj2Obj(param, IndexTemplatePO.class)), IndexTemplate.class);\n    }\n\n    /**\n     * 根据逻辑模板名称模糊查询\n     *\n     * @param param 模糊查询条件\n     * @return\n     */\n    @Override\n    public List<IndexTemplate> fuzzyLogicTemplatesByCondition(IndexTemplateDTO param) {\n        return ConvertUtil.list2List(\n            indexTemplateDAO.likeByCondition(ConvertUtil.obj2Obj(param, IndexTemplatePO.class)), IndexTemplate.class);\n    }\n    \n    /**\n     * @param param           查询条件对象，与上一方法中的查询条件对象相同。\n     * @param logicClusterIds 逻辑集群 ID 列表。\n     * @return 列表 < 索引模板 >\n     */\n    @Override\n    public List<IndexTemplate> pagingGetTemplateSrvByConditionAndLogicClusterIdList(TemplateQueryDTO param,\n                                                                                    List<Integer> logicClusterIds) {\n        List<IndexTemplatePO> indexTemplatePOS = Lists.newArrayList();\n        String sortTerm = null == param.getSortTerm() ? SortConstant.ID : param.getSortTerm();\n        \n        String sortType = param.getOrderByDesc() ? SortConstant.DESC : SortConstant.ASC;\n        try {\n            indexTemplatePOS = indexTemplateDAO.pagingByConditionAndLogicClusterIdList(\n                    ConvertUtil.obj2Obj(param, IndexTemplatePO.class), (param.getPage() - 1) * param.getSize(),\n                    param.getSize(), sortTerm, sortType, logicClusterIds);\n        } catch (Exception e) {\n            LOGGER.error(\"class=IndexTemplateServiceImpl||method=pagingGetTemplateSrvByCondition||err={}\",\n                    e.getMessage(), e);\n        }\n        return ConvertUtil.list2List(indexTemplatePOS, IndexTemplate.class);\n    }\n    \n    @Override\n    public List<IndexTemplate> pagingGetLogicTemplatesByCondition(TemplateConditionDTO param) {\n        String sortTerm = null == param.getSortTerm() ? SortConstant.ID : param.getSortTerm();\n        String sortType = param.getOrderByDesc() ? SortConstant.DESC : SortConstant.ASC;\n       \n        List<IndexTemplatePO> indexTemplatePOS = Lists.newArrayList();\n        try {\n            indexTemplatePOS = indexTemplateDAO.pagingByCondition(ConvertUtil.obj2Obj(param, IndexTemplatePO.class),\n                (param.getPage() - 1) * param.getSize(), param.getSize(), sortTerm, sortType);\n        } catch (Exception e) {\n            LOGGER.error(\"class=TemplateLogicServiceImpl||method=pagingGetLogicTemplatesByCondition||err={}\",\n                e.getMessage(), e);\n        }\n\n        return ConvertUtil.list2List(indexTemplatePOS, IndexTemplate.class);\n    }\n\n    @Override\n    public List<IndexTemplate> pagingGetTemplateSrvByCondition(TemplateQueryDTO param) {\n        List<IndexTemplatePO> indexTemplatePOS = Lists.newArrayList();\n        String sortTerm = null == param.getSortTerm() ? SortConstant.ID : param.getSortTerm();\n        if(StringUtils.isNotBlank(sortTerm)){\n            sortTerm = sortTerm==\"blockRead\"?\"block_read\":\"block_write\";\n        }\n        \n        String sortType = param.getOrderByDesc() ? SortConstant.DESC : SortConstant.ASC;\n        try {\n            indexTemplatePOS = indexTemplateDAO.pagingByCondition(ConvertUtil.obj2Obj(param, IndexTemplatePO.class),\n                (param.getPage() - 1) * param.getSize(), param.getSize(), sortTerm, sortType);\n        } catch (Exception e) {\n            LOGGER.error(\"class=IndexTemplateServiceImpl||method=pagingGetTemplateSrvByCondition||err={}\",\n                e.getMessage(), e);\n        }\n        return ConvertUtil.list2List(indexTemplatePOS, IndexTemplate.class);\n    }\n\n    @Override\n    public Long fuzzyLogicTemplatesHitByCondition(IndexTemplateDTO param) {\n      \n        return indexTemplateDAO.getTotalHitByCondition(ConvertUtil.obj2Obj(param, IndexTemplatePO.class));\n    }\n    \n    /**\n     * 它返回与给定条件和逻辑集群 ID 匹配的模板数量。\n     *\n     * @param param           将用于构造查询的参数对象。\n     * @param logicClusterIds 逻辑集群 ID 列表。\n     * @return 长\n     */\n    @Override\n    public Long fuzzyLogicTemplatesHitByConditionAndLogicClusterIdList(IndexTemplateDTO param,\n                                                                       List<Integer> logicClusterIds) {\n      \n        return indexTemplateDAO.getTotalHitByConditionAndLogicClusterIdList(ConvertUtil.obj2Obj(param,\n                IndexTemplatePO.class),logicClusterIds);\n    }\n    \n    /**\n     * 根据名字查询\n     *\n     * @param templateName 模板名字\n     * @return list\n     */\n    @Override\n    public List<IndexTemplate> listLogicTemplateByName(String templateName) {\n        return ConvertUtil.list2List(indexTemplateDAO.listByName(templateName), IndexTemplate.class);\n    }\n\n    /**\n     * 查询指定的逻辑模板\n     *\n     * @param logicTemplateId 模板id\n     * @return 模板信息  不存在返回null\n     */\n    @Override\n    public IndexTemplate getLogicTemplateById(Integer logicTemplateId) {\n        return ConvertUtil.obj2Obj(indexTemplateDAO.getById(logicTemplateId), IndexTemplate.class);\n    }\n\n    /**\n     * 删除逻辑模板\n     *\n     * @param logicTemplateId 模板id\n     * @param operator        操作人\n     * @return result\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> delTemplate(Integer logicTemplateId, String operator) throws AdminOperateException {\n        IndexTemplatePO oldPO = indexTemplateDAO.getById(logicTemplateId);\n        if (oldPO == null) {\n            return Result.buildNotExist(TEMPLATE_NOT_EXIST);\n        }\n\n        boolean succeed = (1 == indexTemplateDAO.delete(logicTemplateId));\n        if (succeed) {\n            Result<Void> deleteTemplateAuthResult = logicTemplateAuthService\n                .deleteTemplateAuthByTemplateId(oldPO.getId());\n            if (deleteTemplateAuthResult.failed()) {\n                throw new AdminOperateException(\"删除模板失败\");\n            } else {\n                LOGGER.info(\n                    \"class=TemplateLogicServiceImpl||method=delTemplate||logicId={}||msg=deleteTemplateAuthByTemplateId succ\",\n                    logicTemplateId);\n            }\n            //一并下线索引模版配置\n            indexTemplateConfigDAO.deleteByLogicId(logicTemplateId);\n\n            Result<Void> result = indexTemplatePhyService.delTemplateByLogicId(logicTemplateId, operator);\n            if (result.failed()) {\n                throw new AdminOperateException(\"删除模板失败\");\n            } else {\n\n                LOGGER.info(\n                    \"class=TemplateLogicServiceImpl||method=delTemplate||logicId={}||msg=delTemplateByLogicId succ\",\n                    logicTemplateId);\n            }\n\n        } else {\n            throw new AdminOperateException(\"删除模板失败\");\n        }\n        return Result.buildSucc();\n    }\n\n    /**\n     * 校验模板参数是否合法\n     *\n     * @param param     参数\n     * @param operation 操作\n     * @return result\n     */\n    @Override\n    public Result<Void> validateTemplate(IndexTemplateDTO param, OperationEnum operation, Integer projectId) {\n        if (param == null) {\n            return Result.buildParamIllegal(\"模板信息为空\");\n        }\n\n        String dateFormatFinal = null;\n        String expressionFinal = null;\n        String nameFinal = null;\n        String dateFieldFinal = null;\n\n        if (ADD.equals(operation)) {\n            Result<Void> result = validateAdd(param);\n            if (result.failed()) {\n                return result;\n            }\n\n            dateFormatFinal = StringUtils.isBlank(param.getDateFormat()) ? null : param.getDateFormat();\n            expressionFinal = param.getExpression();\n            nameFinal = param.getName();\n            dateFieldFinal = param.getDateField();\n        } else if (EDIT.equals(operation)) {\n            if (AriusObjUtils.isNull(param.getId())) {\n                return Result.buildParamIllegal(\"模板id为空\");\n            }\n\n            IndexTemplatePO oldPO = indexTemplateDAO.getById(param.getId());\n            final Result<Void> checkProjectCorrectly = ProjectUtils.checkProjectCorrectly(IndexTemplatePO::getProjectId,\n                oldPO, projectId);\n            if (checkProjectCorrectly.failed()) {\n                return checkProjectCorrectly;\n            }\n            if (oldPO == null) {\n                return Result.buildNotExist(TEMPLATE_NOT_EXIST);\n            }\n            dateFormatFinal = getDateFormat(param, oldPO);\n            expressionFinal = getExpression(param, oldPO);\n            dateFieldFinal = getDateField(param, oldPO);\n            nameFinal = oldPO.getName();\n            param.setName(nameFinal);\n        }\n\n        List<IndexTemplate> indexTemplateList = listAllLogicTemplates();\n        Result<Void> result = validateIndexTemplateLogicStep1(param, indexTemplateList);\n        if (result.failed()) {\n            return result;\n        }\n\n        result = validateIndexTemplateLogicStep2(param, dateFormatFinal, expressionFinal, nameFinal, dateFieldFinal);\n        if (result.failed()) {\n            return result;\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 编辑逻辑模板\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @return result\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> editTemplate(IndexTemplateDTO param, String operator,\n                                     Integer projectId) throws AdminOperateException {\n        Result<Void> checkResult = validateTemplate(param, EDIT, projectId);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=TemplateLogicServiceImpl||method=editTemplate||msg={}\", checkResult.getMessage());\n            return checkResult;\n        }\n\n        return editTemplateWithoutCheck(param, operator);\n    }\n\n    @Override\n    public Result<Void> addTemplateWithoutCheck(IndexTemplateDTO param) throws AdminOperateException {\n        IndexTemplatePO templatePO = ConvertUtil.obj2Obj(param, IndexTemplatePO.class);\n        boolean succ;\n        try {\n            succ = (1 == indexTemplateDAO.insert(templatePO));\n        } catch (DuplicateKeyException e) {\n            LOGGER.warn(\"class=TemplateLogicServiceImpl||method=addTemplateWithoutCheck||errMsg={}\", e.getMessage());\n            throw new AdminOperateException(String.format(\"保存逻辑模板【%s】失败！\", templatePO.getName()));\n        }\n\n        param.setId(templatePO.getId());\n        return Result.build(succ);\n    }\n\n    /**\n     * 获取模板配置信息\n     *\n     * @param logicTemplateId 模板id\n     * @return 配置信息  不存在返回null\n     */\n    @Override\n    public IndexTemplateConfig getTemplateConfig(Integer logicTemplateId) {\n        return ConvertUtil.obj2Obj(indexTemplateConfigDAO.getByLogicId(logicTemplateId), IndexTemplateConfig.class);\n    }\n\n    /**\n     * 更新模板配置\n     *\n     * @param configDTO 配置参数\n     * @param operator  操作人\n     * @return result\n     */\n    @Override\n    public Result<Void> updateTemplateConfig(IndexTemplateConfigDTO configDTO, String operator) {\n        Result<Void> checkResult = checkConfigParam(configDTO);\n        if (checkResult.failed()) {\n            LOGGER.warn(\"class=TemplateLogicServiceImpl||method=updateTemplateConfig||msg={}\",\n                checkResult.getMessage());\n            return checkResult;\n        }\n\n        IndexTemplatePO oldPO = indexTemplateDAO.getById(configDTO.getLogicId());\n        if (oldPO == null) {\n            return Result.buildNotExist(TEMPLATE_NOT_EXIST);\n        }\n\n        boolean succ = 1 == indexTemplateConfigDAO.update(ConvertUtil.obj2Obj(configDTO, TemplateConfigPO.class));\n\n        return Result.build(succ);\n    }\n\n    @Override\n    public Result<Void> insertTemplateConfig(IndexTemplateConfig indexTemplateConfig) {\n        return Result.build(\n            1 == indexTemplateConfigDAO.insert(ConvertUtil.obj2Obj(indexTemplateConfig, TemplateConfigPO.class)));\n    }\n    \n     /**\n     * 获取通过逻辑id\n     *\n     * @param logicId 逻辑标识\n     * @return {@link TemplateConfig}\n     */\n    @Override\n    public TemplateConfigPO getTemplateConfigByLogicId(Integer logicId) {\n        return indexTemplateConfigDAO.getByLogicId(logicId);\n    }\n    \n    /**\n     * 更新模板配置\n     *\n     * @param logicTemplateId  logicId\n     * @param factor   factor\n     * @param operator 操作人\n     */\n    @Override\n    public void upsertTemplateShardFactor(Integer logicTemplateId, Double factor, String operator) {\n        IndexTemplateConfig templateConfig = getTemplateConfig(logicTemplateId);\n        if (templateConfig == null) {\n            TemplateConfigPO configPO = getDefaultTemplateConfig(logicTemplateId);\n            configPO.setAdjustShardFactor(factor);\n            Result.build(1 == indexTemplateConfigDAO.insert(configPO));\n        } else {\n            IndexTemplateConfigDTO param = new IndexTemplateConfigDTO();\n            param.setLogicId(logicTemplateId);\n            param.setAdjustShardFactor(factor);\n            updateTemplateConfig(param, operator);\n        }\n    }\n\n    /**\n     * 更新模板配置\n     *\n     * @param logicTemplateId  logicId\n     * @param factor   factor\n     * @param operator 操作人\n     */\n    @Override\n    public void updateTemplateShardFactorIfGreater(Integer logicTemplateId, Double factor, String operator) {\n        IndexTemplateConfig templateConfig = getTemplateConfig(logicTemplateId);\n        if (templateConfig == null) {\n            TemplateConfigPO configPO = getDefaultTemplateConfig(logicTemplateId);\n            configPO.setAdjustShardFactor(factor);\n            Result.build(1 == indexTemplateConfigDAO.insert(configPO));\n            return;\n        } else if (templateConfig.getAdjustShardFactor() < factor) {\n            IndexTemplateConfigDTO param = new IndexTemplateConfigDTO();\n            param.setLogicId(logicTemplateId);\n            param.setAdjustShardFactor(factor);\n            updateTemplateConfig(param, operator);\n            return;\n        }\n        Result.buildSucc();\n    }\n\n    /**\n     * 判断模板是否存在\n     *\n     * @param logicTemplateId 模板id\n     * @return true/false\n     */\n    @Override\n    public boolean exist(Integer logicTemplateId) {\n        return indexTemplateDAO.getById(logicTemplateId) != null;\n    }\n\n    /**\n     * 获取平台所有的模板\n     *\n     * @return map\n     */\n    @Override\n    public Map<Integer, IndexTemplate> getAllLogicTemplatesMap() {\n        return listAllLogicTemplates().stream()\n            .collect(Collectors.toMap(IndexTemplate::getId, indexTemplateLogic -> indexTemplateLogic));\n    }\n\n    @Override\n    public List<IndexTemplate> listLogicTemplatesByIds(List<Integer> logicTemplateIds) {\n        if (CollectionUtils.isEmpty(logicTemplateIds)) {\n            return new ArrayList<>();\n        }\n\n        return ConvertUtil.list2List(indexTemplateDAO.listByIds(logicTemplateIds), IndexTemplate.class);\n    }\n\n    @Override\n    public Map<Integer, IndexTemplate> getLogicTemplatesMapByIds(List<Integer> logicTemplateIds) {\n        return listLogicTemplatesByIds(logicTemplateIds).stream()\n            .collect(Collectors.toMap(IndexTemplate::getId, indexTemplateLogic -> indexTemplateLogic));\n    }\n\n    /**\n     * 根据APP ID查询模板\n     *\n     * @param projectId APP ID\n     * @return list\n     */\n    @Override\n    public List<IndexTemplate> listProjectLogicTemplatesByProjectId(Integer projectId) {\n        return ConvertUtil.list2List(indexTemplateDAO.listByProjectId(projectId), IndexTemplate.class);\n    }\n\n    /**\n     * 根据逻辑集群获取所有的逻辑模板\n     * @param logicClusterId 逻辑集群ID\n     * @return\n     */\n    @Override\n    public List<IndexTemplate> listLogicClusterTemplates(Long logicClusterId) {\n        List<IndexTemplate> logicTemplates = Lists.newArrayList();\n\n        if (logicClusterId != null) {\n            List<IndexTemplateWithCluster> indexTemplateLogicWithClusters = listLogicTemplateWithClustersByClusterId(\n                logicClusterId);\n            logicTemplates = ConvertUtil.list2List(indexTemplateLogicWithClusters, IndexTemplate.class);\n        }\n\n        return logicTemplates;\n    }\n\n    /**\n     * 获取模板具体的物理索引\n     *\n     * @param projectId projectId\n     */\n    @Override\n    public Result<List<Tuple<String, String>>> listLogicTemplatesByProjectId(Integer projectId) {\n        List<ProjectTemplateAuth> projectTemplateAuths = logicTemplateAuthService\n            .getTemplateAuthsByProjectId(projectId);\n        if (CollectionUtils.isEmpty(projectTemplateAuths)) {\n            return Result.buildSucc();\n        }\n\n        List<Tuple<String, String>> indicesClusterTupleList = new ArrayList<>();\n\n        projectTemplateAuths.parallelStream().forEach(appTemplateAuth -> {\n            IndexTemplateWithPhyTemplates logicWithPhysical = getLogicTemplateWithPhysicalsById(\n                appTemplateAuth.getTemplateId());\n\n            if (null != logicWithPhysical && logicWithPhysical.hasPhysicals()) {\n                IndexTemplatePhy indexTemplatePhysicalInfo = logicWithPhysical.getPhysicals().get(0);\n\n                String cluster = indexTemplatePhysicalInfo.getCluster();\n                Set<String> indices = esIndexService.syncGetIndexNameByExpression(cluster,\n                    indexTemplatePhysicalInfo.getExpression());\n                if (CollectionUtils.isNotEmpty(indices) && StringUtils.isNotBlank(cluster)) {\n                    indices.forEach(i -> indicesClusterTupleList.add(new Tuple<>(i, cluster)));\n                }\n            }\n        });\n\n        LOGGER.info(\n            \"class=TemplateLogicServiceImpl||method=getAllTemplateIndicesByProjectId||projectId={}||indicesList={}\",\n            projectId, JSON.toJSONString(indicesClusterTupleList));\n\n        return Result.buildSucc(indicesClusterTupleList);\n    }\n\n    /**\n     * 模板移交\n     *\n     * @param logicId         模板id\n     * @param sourceProjectId\n     * @param tgtProjectId    projectId\n     * @param operator        操作人\n     * @return Result\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> turnOverLogicTemplate(Integer logicId, Integer sourceProjectId, Integer tgtProjectId, String operator) throws AdminOperateException {\n\n        IndexTemplate templateLogic = getLogicTemplateById(logicId);\n        if (templateLogic == null) {\n            return Result.buildParamIllegal(TEMPLATE_NOT_EXIST);\n        }\n\n        IndexTemplateDTO logicDTO = new IndexTemplateDTO();\n        logicDTO.setId(logicId);\n        logicDTO.setProjectId(tgtProjectId);\n\n        return editTemplate(logicDTO, operator, sourceProjectId);\n\n    }\n\n    /**\n     * 获取所有逻辑模板物理模板数量\n     *\n     * @return 逻辑模板和对应物理模板数量的映射\n     */\n    @Override\n    public Map<Integer, Integer> getAllLogicTemplatesPhysicalCount() {\n        return indexTemplatePhyService.getAllLogicTemplatesPhysicalCount();\n    }\n\n    /**\n     * 查询全部的模板\n     *\n     * @return\n     */\n    @Override\n    public List<IndexTemplate> listAllLogicTemplates() {\n        return ConvertUtil.list2List(indexTemplateDAO.listAll(), IndexTemplate.class);\n    }\n\n    @Override\n    public List<IndexTemplate> listAllLogicTemplatesWithCache() {\n        try {\n            return templateListCache.get(\"listAllLogicTemplates\", this::listAllLogicTemplates);\n        } catch (Exception e) {\n            return listAllLogicTemplates();\n        }\n    }\n\n    /**\n     * 获取type\n     *\n     * @param logicId 模板id\n     * @return list\n     */\n    @Override\n    public List<IndexTemplateType> listLogicTemplateTypes(Integer logicId) {\n        return ConvertUtil.list2List(indexTemplateTypeDAO.listByIndexTemplateId(logicId), IndexTemplateType.class);\n    }\n    \n    /**\n     * 更新\n     *\n     * @param param 入参\n     * @return boolean\n     */\n    @Override\n    public boolean updateTemplateType(TemplateTypePO param) {\n        return indexTemplateTypeDAO.update(param) == 1;\n    }\n\n    /**\n     * 需要修改逻辑表和物理表的name\n     * 需要修改集群中的name\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @return\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> editTemplateName(IndexTemplateDTO param, String operator) throws AdminOperateException {\n        if (AriusObjUtils.isNull(param.getId())) {\n            return Result.buildParamIllegal(\"索引ID必填\");\n        }\n\n        if (AriusObjUtils.isNull(param.getName())) {\n            return Result.buildParamIllegal(\"索引名称必填\");\n        }\n\n        IndexTemplatePO logicParam = new IndexTemplatePO();\n        logicParam.setId(param.getId());\n        logicParam.setName(param.getName());\n\n        boolean succ = 1 == indexTemplateDAO.update(logicParam);\n        if (!succ) {\n            return Result.buildFail(\"修改逻辑模板名称失败\");\n        }\n\n        List<IndexTemplatePhy> physicals = indexTemplatePhyService.getTemplateByLogicId(param.getId());\n        if (CollectionUtils.isNotEmpty(physicals)) {\n            for (IndexTemplatePhy physical : physicals) {\n                physical.setName(param.getName());\n                Result<Void> result = indexTemplatePhyService.updateTemplateName(physical, operator);\n                if (result.failed()) {\n                    throw new AdminOperateException(\"修改物理模板[\" + physical.getId() + \"]失败：\" + result.getMessage());\n                }\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> editTemplateInfoTODB(IndexTemplateDTO param) {\n        boolean succ = false;\n        try {\n            succ = 1 == indexTemplateDAO.update(ConvertUtil.obj2Obj(param, IndexTemplatePO.class));\n        } catch (Exception e) {\n            LOGGER.error(\"class=TemplateLogicServiceImpl||method=editTemplateInfoTODB||||msg={}\", e.getMessage(), e);\n        }\n        return Result.build(succ);\n    }\n\n    @Override\n    public List<IndexTemplate> listTemplatesByHasAuthCluster(Integer projectId) {\n        if (projectId == null) {\n            return new ArrayList<>();\n        }\n\n        // 获取有权限的集群id\n        Set<Long> hasAuthLogicClusterIds = logicClusterAuthService.getAllLogicClusterAuths(projectId).stream()\n            .map(ProjectClusterLogicAuth::getLogicClusterId).collect(Collectors.toSet());\n\n        // 获取集群下的模板\n        return listLogicTemplateWithClusterAndMasterTemplateByClusters(hasAuthLogicClusterIds).stream()\n            .map(IndexTemplate.class::cast).collect(Collectors.toList());\n    }\n\n    @Override\n    public List<IndexTemplate> listHasAuthTemplatesInLogicCluster(Integer projectId, Long logicClusterId) {\n        if (projectId == null || logicClusterId == null) {\n            return new ArrayList<>();\n        }\n\n        // 获取逻辑集群下的逻辑模板列表\n        List<IndexTemplateLogicWithClusterAndMasterTemplate> templatesInLogicCluster = listLogicTemplateWithClusterAndMasterTemplateByCluster(\n            logicClusterId);\n\n        // 获取app的模板权限记录\n        List<ProjectTemplateAuth> projectTemplateAuths = logicTemplateAuthService\n            .getTemplateAuthsByProjectId(projectId);\n        Set<Integer> hasAuthTemplateIds = projectTemplateAuths.stream().map(ProjectTemplateAuth::getTemplateId)\n            .collect(Collectors.toSet());\n\n        // 筛选app有权限的逻辑模板\n        return templatesInLogicCluster.stream()\n            .filter(templateInLogicCluster -> hasAuthTemplateIds.contains(templateInLogicCluster.getId()))\n            .map(IndexTemplate.class::cast).collect(Collectors.toList());\n    }\n\n    @Override\n    public List<IndexTemplateLogicWithClusterAndMasterTemplate> listLogicTemplatesWithClusterAndMasterTemplate() {\n\n        List<IndexTemplateWithCluster> logicClusters = listAllLogicTemplateWithClusters();\n        if (CollectionUtils.isEmpty(logicClusters)) {\n            return new ArrayList<>();\n        }\n\n        return logicClusters.parallelStream().filter(Objects::nonNull).map(this::convert).collect(Collectors.toList());\n    }\n\n    @Override\n    public IndexTemplateLogicWithClusterAndMasterTemplate getLogicTemplateWithClusterAndMasterTemplate(Integer logicTemplateId) {\n        return convert(getLogicTemplateWithCluster(logicTemplateId));\n    }\n    \n    /**\n     * @param logicTemplateId\n     * @return\n     */\n    @Override\n    public String getMaterClusterPhyByLogicTemplateId(Integer logicTemplateId) {\n        IndexTemplatePhy IndexTemplatePhy = indexTemplatePhyService.getTemplateByLogicIdAndRole(logicTemplateId,\n                TemplateDeployRoleEnum.MASTER.getCode());\n        if (IndexTemplatePhy==null){\n            return null;\n        }\n     \n        return IndexTemplatePhy.getCluster();\n    }\n    \n    /**\n     * 通过逻辑模板ID获取主模板的物理模板ID\n     *\n     * @param logicTemplateId 逻辑模板 ID。\n     * @return 长\n     */\n    @Override\n    public Long getMasterTemplatePhyIdByLogicTemplateId(Integer logicTemplateId) {\n        IndexTemplatePhy IndexTemplatePhy = indexTemplatePhyService.getTemplateByLogicIdAndRole(logicTemplateId,\n                TemplateDeployRoleEnum.MASTER.getCode());\n        if (IndexTemplatePhy==null){\n            return null;\n        }\n     \n        return IndexTemplatePhy.getId();\n    }\n    \n    @Override\n    public List<IndexTemplateLogicWithClusterAndMasterTemplate> listLogicTemplatesWithClusterAndMasterTemplate(Set<Integer> logicTemplateIds) {\n\n        List<IndexTemplateWithCluster> logicClusters = listLogicTemplateWithClusters(logicTemplateIds);\n        if (CollectionUtils.isEmpty(logicClusters)) {\n            return new ArrayList<>();\n        }\n\n        return logicClusters.stream().filter(Objects::nonNull).map(this::convert).collect(Collectors.toList());\n    }\n\n    @Override\n    public Map<Integer, IndexTemplateLogicWithClusterAndMasterTemplate> getLogicTemplatesWithClusterAndMasterTemplateMap(Set<Integer> logicTemplateIds) {\n        return listLogicTemplatesWithClusterAndMasterTemplate(logicTemplateIds).stream()\n            .collect(Collectors.toMap(IndexTemplateLogicWithClusterAndMasterTemplate::getId, template -> template));\n    }\n\n    @Override\n    public List<IndexTemplateLogicWithClusterAndMasterTemplate> listLogicTemplateWithClusterAndMasterTemplateByClusters(Set<Long> logicClusterIds) {\n\n        if (CollectionUtils.isEmpty(logicClusterIds)) {\n            return new ArrayList<>();\n        }\n\n        // 过滤出指定集群的数据\n        return listLogicTemplatesWithClusterAndMasterTemplate().parallelStream()\n            .filter(logicTemplateWithLogicCluster -> logicTemplateWithLogicCluster != null\n                                                     && logicTemplateWithLogicCluster.getLogicCluster() != null\n                                                     && logicClusterIds.contains(\n                                                         logicTemplateWithLogicCluster.getLogicCluster().getId()))\n            .collect(Collectors.toList());\n    }\n\n    @Override\n    public List<IndexTemplateLogicWithClusterAndMasterTemplate> listLogicTemplateWithClusterAndMasterTemplateByCluster(Long logicClusterId) {\n        if (logicClusterId == null) {\n            return new ArrayList<>();\n        }\n\n        // 过滤出指定集群的数据\n        return listLogicTemplatesWithClusterAndMasterTemplate().parallelStream()\n            .filter(logicTemplateWithLogicCluster -> logicTemplateWithLogicCluster != null\n                                                     && logicTemplateWithLogicCluster.getLogicCluster() != null\n                                                     && logicClusterId.equals(\n                                                         logicTemplateWithLogicCluster.getLogicCluster().getId()))\n            .collect(Collectors.toList());\n    }\n\n    /**\n     * 获取单个逻辑模板逻辑集群相关信息\n     * @param logicTemplateId 逻辑模板ID\n     * @return\n     */\n    @Override\n    public IndexTemplateWithCluster getLogicTemplateWithCluster(Integer logicTemplateId) {\n        IndexTemplateWithPhyTemplates physicalTemplates = getLogicTemplateWithPhysicalsById(logicTemplateId);\n\n        if (physicalTemplates == null) {\n            return null;\n        }\n        return convert2WithCluster(Arrays.asList(physicalTemplates)).stream().distinct().filter(Objects::nonNull).findFirst()\n            .orElse(null);\n    }\n\n    @Override\n    public List<IndexTemplateWithCluster> listLogicTemplateWithClusters(Set<Integer> logicTemplateIds) {\n        List<IndexTemplateWithPhyTemplates> physicalTemplates = listLogicTemplateWithPhysicalsByIds(logicTemplateIds);\n\n        return convert2WithCluster(physicalTemplates).stream().filter(Objects::nonNull).collect(Collectors.toList());\n    }\n\n    /**\n     * 查询模板资源信息\n     *\n     * @return 带有逻辑集群的所有逻辑模板列表\n     */\n    @Override\n    public List<IndexTemplateWithCluster> listAllLogicTemplateWithClusters() {\n        List<IndexTemplateWithPhyTemplates> logicTemplatesCombinePhysicals = listAllLogicTemplateWithPhysicals();\n\n        return convert2WithCluster(logicTemplatesCombinePhysicals).stream().filter(Objects::nonNull)\n            .collect(Collectors.toList());\n    }\n\n    /**\n     * 查询模板资源信息\n     *\n     * @param logicClusterId 逻辑集群ID\n     * @return List<IndexTemplateLogicClusterMeta> 逻辑模板列表\n     */\n    @Override\n    public List<IndexTemplateWithCluster> listLogicTemplateWithClustersByClusterId(Long logicClusterId) {\n        List<IndexTemplateWithCluster> allClusterMetas = listAllLogicTemplateWithClusters();\n\n        List<IndexTemplateWithCluster> currentClusterMetas = new ArrayList<>();\n        for (IndexTemplateWithCluster clusterMeta : allClusterMetas) {\n            if (isLogicClusterIdWithin(clusterMeta.getLogicClusters(), logicClusterId)) {\n                currentClusterMetas.add(clusterMeta);\n            }\n        }\n\n        return currentClusterMetas;\n    }\n\n    /**\n     * 获取所有带有物理模板详情的逻辑模板列表\n     * @return\n     */\n    @Override\n    public List<IndexTemplateWithPhyTemplates> listAllLogicTemplateWithPhysicals() {\n        return batchConvertLogicTemplateCombinePhysicalWithCache(indexTemplateDAO.listAll());\n    }\n\n    @Override\n    public List<IndexTemplateWithPhyTemplates> listLogicTemplateWithPhysicalsByIds(Set<Integer> logicTemplateIds) {\n        if (CollectionUtils.isEmpty(logicTemplateIds)) {\n            return new ArrayList<>();\n        }\n        return batchConvertLogicTemplateCombinePhysical(indexTemplateDAO.listByIds(new ArrayList<>(logicTemplateIds)));\n    }\n\n    /**\n     * 根据当前逻辑模板获取对应带有物理模板列表的逻辑模板详情\n     * @param logicTemplateId 逻辑模板ID\n     * @return\n     */\n    @Override\n    public IndexTemplateWithPhyTemplates getLogicTemplateWithPhysicalsById(Integer logicTemplateId) {\n        IndexTemplatePO templateLogic = indexTemplateDAO.getById(logicTemplateId);\n        if (templateLogic == null) {\n            return null;\n        }\n\n        List<IndexTemplateWithPhyTemplates> physicalTemplates = batchConvertLogicTemplateCombinePhysical(\n            Arrays.asList(templateLogic));\n        return physicalTemplates.stream().findFirst().orElse(null);\n    }\n\n    /**\n     * 获取指定数据中的模板信息\n     *\n     * @return list\n     */\n    @Override\n    public List<IndexTemplateWithPhyTemplates> listTemplateWithPhysical() {\n        return batchConvertLogicTemplateCombinePhysical(indexTemplateDAO.listAll());\n    }\n\n    /**\n     * 更新读状态\n     *\n     * @param logicId   逻辑模板\n     * @param blockRead 是否禁读\n     * @return\n     * @throws AdminOperateException\n     */\n    @Override\n    public Result<Void> updateBlockReadState(Integer logicId, Boolean blockRead) {\n        if (null == logicId || null == blockRead) {\n            return Result.buildFail(\"logicId or blockRead is null\");\n        }\n\n        return Result.build(1 == indexTemplateDAO.updateBlockReadState(logicId, blockRead));\n    }\n\n    /**\n     * 更新写状态\n     *\n     * @param logicId    逻辑模板\n     * @param blockWrite 是否禁写\n     * @return\n     */\n    @Override\n    public Result<Void> updateBlockWriteState(Integer logicId, Boolean blockWrite) {\n        if (null == logicId || null == blockWrite) {\n            return Result.buildFail(\"logicId or blockWrite is null\");\n        }\n\n        return Result.build(indexTemplateDAO.updateBlockWriteState(logicId, blockWrite) == 1);\n    }\n\n    @Override\n    public Result updateTemplateWriteRateLimit(ConsoleTemplateRateLimitDTO dto) throws ESOperateException {\n     \n        IndexTemplatePO oldPO = indexTemplateDAO.getById(dto.getLogicId());\n        IndexTemplatePO editTemplate = ConvertUtil.obj2Obj(dto, IndexTemplatePO.class);\n        editTemplate.setId(dto.getLogicId());\n        editTemplate.setWriteRateLimit(dto.getAdjustRateLimit());\n        int update = indexTemplateDAO.update(editTemplate);\n        if (update > 0) {\n            IndexTemplateDTO param = ConvertUtil.obj2Obj(editTemplate, IndexTemplateDTO.class);\n            param.setId(dto.getLogicId());\n            // 将修改同步到物理模板\n            Result editPhyResult = indexTemplatePhyService.editTemplateFromLogic(param, AriusUser.SYSTEM.getDesc());\n            if (editPhyResult.failed()) {\n                return Result.buildFail(\"修改限流，修改物理模板失败\");\n            }\n\n            SpringTool.publish(new LogicTemplateModifyEvent(this, ConvertUtil.obj2Obj(oldPO, IndexTemplate.class),\n                getLogicTemplateById(oldPO.getId())));\n            return Result.buildSucc();\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public Result<Void> preCheckTemplateName(String name) {\n        if (name == null) {\n            return Result.buildParamIllegal(\"模板名称为空\");\n        }\n        List<String> pos = indexTemplateDAO.listAllNames();\n        for (String po : pos) {\n            if (name.equals(po)) {\n                return Result.buildDuplicate(\"模板名称已经存在\");\n            }\n            if (name.startsWith(po) || po.startsWith(name)) {\n                return Result.buildParamIllegal(\"索引模板\" + name + \"与【\" + po + \"】冲突,不能互为前缀,模板表达式匹配时会重叠\");\n            }\n        }\n        return Result.buildSuccWithMsg(\"索引模板可以使用\");\n    }\n\n    @Override\n    public Result<List<IndexTemplate>> listByRegionId(Integer regionId) {\n        Result<List<IndexTemplatePhy>> phyListResult = indexTemplatePhyService.listByRegionId(regionId);\n        if (phyListResult.failed() && CollectionUtils.isEmpty(phyListResult.getData())) {\n            return Result.buildFail(phyListResult.getMessage());\n        }\n\n        List<Integer> logicTemplateIdList = phyListResult.getData().stream().map(IndexTemplatePhy::getLogicId)\n            .distinct().collect(Collectors.toList());\n        List<IndexTemplate> logicTemplateList = listLogicTemplatesByIds(logicTemplateIdList);\n        return Result.buildSucc(logicTemplateList);\n    }\n\n    @Override\n    public List<IndexTemplateWithCluster> convert2WithCluster(List<IndexTemplateWithPhyTemplates> indexTemplateWithPhyTemplates) {\n        if (CollectionUtils.isEmpty(indexTemplateWithPhyTemplates)) {\n            return new ArrayList<>();\n        }\n\n        List<IndexTemplateWithCluster> res = Lists.newArrayList();\n        for (IndexTemplateWithPhyTemplates indexTemplateWithPhyTemplate : indexTemplateWithPhyTemplates) {\n            IndexTemplateWithCluster indexTemplateWithCluster = ConvertUtil.obj2Obj(indexTemplateWithPhyTemplate,\n                IndexTemplateWithCluster.class);\n            IndexTemplatePhy masterPhyTemplate = indexTemplateWithPhyTemplate.getMasterPhyTemplate();\n             if (null == masterPhyTemplate) {\n                continue;\n            }\n            res.add(indexTemplateWithCluster);\n\n            ClusterRegion region = clusterRegionService.getRegionById(masterPhyTemplate.getRegionId().longValue());\n            if (null == region) {\n                continue;\n            }\n\n            String logicClusterIds = region.getLogicClusterIds();\n            if (REGION_NOT_BOUND_LOGIC_CLUSTER_ID.equals(logicClusterIds)) {\n                continue;\n            }\n    \n            List<String> logicClusterIdStrList = ListUtils.string2StrList(logicClusterIds);\n            List<Long> logicClusterIdList = logicClusterIdStrList.stream().map(Long::parseLong).distinct()\n                    .collect(Collectors.toList());\n            //这里存在逻辑集群创建项目被超级项目拿来使用了，且创建了模版，但是集群个数1的情况\n            final List<ClusterLogic> clusterLogicListByIds = clusterLogicService.getClusterLogicListByIds(\n                    logicClusterIdList);\n            if (clusterLogicListByIds.size() == 1) {\n                indexTemplateWithCluster.setLogicClusters(\n                      clusterLogicListByIds  );\n            } else {\n                List<ClusterLogic> clusterLogicList = clusterLogicListByIds\n                        .stream().filter(clusterLogic -> Objects.equals(clusterLogic.getProjectId(),\n                                indexTemplateWithPhyTemplate.getProjectId())).collect(Collectors.toList());\n                indexTemplateWithCluster.setLogicClusters(clusterLogicList);\n            }\n            \n                    \n\n        }\n        return res;\n    }\n\n    @Override\n    public List<IndexTemplate> listByResourceIds(List<Long> resourceIds) {\n        if (CollectionUtils.isEmpty(resourceIds)) {\n            return new ArrayList<>();\n        }\n\n        return ConvertUtil.list2List(indexTemplateDAO.listByResourceIds(resourceIds), IndexTemplate.class);\n    }\n\n    /**\n     * @param templateLogicId 模板逻辑id\n     * @return\n     */\n    @Override\n    public Integer getProjectIdByTemplateLogicId(Integer templateLogicId) {\n        return indexTemplateDAO.getProjectIdByTemplateLogicId(templateLogicId);\n    }\n\n    /**\n     * @param logicId\n     * @return\n     */\n    @Override\n    public IndexTemplatePO getLogicTemplatePOById(Integer logicId) {\n        return indexTemplateDAO.getById(logicId);\n    }\n\n    /**\n     * @param editTemplate\n     * @return\n     */\n    @Override\n    public boolean update(IndexTemplatePO editTemplate) {\n        return indexTemplateDAO.update(editTemplate) == 1;\n    }\n\n    /**\n     * @param days\n     * @param templateIdList\n     * @return\n     */\n    @Override\n    public int batchChangeHotDay(Integer days, List<Integer> templateIdList) {\n\n        return indexTemplateDAO.batchChangeHotDay(days, templateIdList);\n    }\n\n    /**\n     * @param logicTemplateId\n     * @return\n     */\n    @Override\n    public String getNameByTemplateLogicId(Integer logicTemplateId) {\n        return indexTemplateDAO.getNameByTemplateLogicId(logicTemplateId);\n    }\n    \n    /**\n     * @param projectId\n     * @return\n     */\n    @Override\n    public List<Integer> getLogicTemplateIdListByProjectId(Integer projectId) {\n        return indexTemplateDAO.getLogicTemplateIdListByProjectId(projectId);\n    }\n    \n    /**************************************** private method ****************************************************/\n    private List<IndexTemplateWithPhyTemplates> batchConvertLogicTemplateCombinePhysicalWithFunction(List<IndexTemplatePO> logicTemplates,\n                                                                                         Supplier<List<IndexTemplatePhy>> supplier){\n        if (CollectionUtils.isEmpty(logicTemplates)) {\n            return Lists.newArrayList();\n        }\n\n        // 逻辑模板对应1到多个物理模板\n        Multimap<Integer, IndexTemplatePhy> logicId2PhysicalTemplatesMapping = ConvertUtil\n            .list2MulMap(supplier.get(), IndexTemplatePhy::getLogicId);\n\n        List<IndexTemplateWithPhyTemplates> indexTemplateCombinePhysicalTemplates = Lists\n            .newArrayListWithCapacity(logicTemplates.size());\n\n        for (IndexTemplatePO logicTemplate : logicTemplates) {\n            IndexTemplateWithPhyTemplates logicWithPhysical = ConvertUtil.obj2Obj(logicTemplate,\n                IndexTemplateWithPhyTemplates.class);\n            logicWithPhysical\n                .setPhysicals(Lists.newArrayList(logicId2PhysicalTemplatesMapping.get(logicTemplate.getId())));\n\n            indexTemplateCombinePhysicalTemplates.add(logicWithPhysical);\n        }\n\n        return indexTemplateCombinePhysicalTemplates;\n        \n    }\n    \n    private List<IndexTemplateWithPhyTemplates> batchConvertLogicTemplateCombinePhysicalWithCache(\n            List<IndexTemplatePO> logicTemplates) {\n        return batchConvertLogicTemplateCombinePhysicalWithFunction(logicTemplates,\n                () -> indexTemplatePhyService.listTemplateWithCache());\n    }\n    /**\n     * 转换逻辑模板，获取并组合对应的物理模板信息\n     * @param logicTemplates 逻辑模板列表\n     * @return\n     */\n    private List<IndexTemplateWithPhyTemplates> batchConvertLogicTemplateCombinePhysical(List<IndexTemplatePO> logicTemplates) {\n\n       \n\n        return batchConvertLogicTemplateCombinePhysicalWithFunction(logicTemplates, ()->indexTemplatePhyService.listTemplate());\n    }\n\n    /**\n     *\n     * @param esLogicClusters 逻辑集群列表\n     * @param logicClusterId 逻辑ID\n     * @return\n     */\n    private boolean isLogicClusterIdWithin(List<ClusterLogic> esLogicClusters, Long logicClusterId) {\n        if (CollectionUtils.isNotEmpty(esLogicClusters) && logicClusterId != null) {\n            for (ClusterLogic logic : esLogicClusters) {\n                if (logic.getId().equals(logicClusterId)) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    private Result<Void> checkConfigParam(IndexTemplateConfigDTO configDTO) {\n        if (configDTO == null) {\n            return Result.buildParamIllegal(\"配置信息为空\");\n        }\n        if (configDTO.getLogicId() == null) {\n            return Result.buildParamIllegal(\"模板ID为空\");\n        }\n        if (configDTO.getIsSourceSeparated() != null && !yesOrNo(configDTO.getIsSourceSeparated())) {\n            return Result.buildParamIllegal(\"索引存储分离开关非法\");\n        }\n        if (configDTO.getDynamicLimitEnable() != null && !yesOrNo(configDTO.getDynamicLimitEnable())) {\n            return Result.buildParamIllegal(\"写入动态限流开关非法\");\n        }\n        if (configDTO.getMappingImproveEnable() != null && !yesOrNo(configDTO.getMappingImproveEnable())) {\n            return Result.buildParamIllegal(\"mapping优化开关非法\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private TemplateConfigPO getDefaultTemplateConfig(Integer logicId) {\n        TemplateConfigPO configPO = new TemplateConfigPO();\n        configPO.setLogicId(logicId);\n        configPO.setAdjustTpsFactor(1.0);\n        configPO.setAdjustShardFactor(1.0);\n        configPO.setDynamicLimitEnable(AdminConstant.YES);\n        configPO.setMappingImproveEnable(AdminConstant.NO);\n        configPO.setIsSourceSeparated(AdminConstant.NO);\n        configPO.setDisableSourceFlags(false);\n        configPO.setPreCreateFlags(true);\n        configPO.setShardNum(1);\n        return configPO;\n    }\n\n    /**\n     * 编辑逻辑模板   无参数校验\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @return result\n     */\n    private Result<Void> editTemplateWithoutCheck(IndexTemplateDTO param,\n                                                  String operator) throws AdminOperateException {\n\n        if (param.getDateFormat() != null) {\n            param.setDateFormat(param.getDateFormat().replace(\"Y\", \"y\"));\n        }\n\n        IndexTemplatePO oldPO = indexTemplateDAO.getById(param.getId());\n        IndexTemplatePO editTemplate = ConvertUtil.obj2Obj(param, IndexTemplatePO.class);\n\n        boolean succeed = (1 == indexTemplateDAO.update(editTemplate));\n\n        if (succeed) {\n            param.setId(editTemplate.getId());\n            // 将修改同步到物理模板\n            Result<Void> editPhyResult = indexTemplatePhyService.editTemplateFromLogic(param, operator);\n            if (editPhyResult.failed()) {\n                throw new AdminOperateException(\"修改物理模板失败\");\n            }\n\n            SpringTool.publish(new LogicTemplateModifyEvent(this, ConvertUtil.obj2Obj(oldPO, IndexTemplate.class),\n                getLogicTemplateById(oldPO.getId())));\n        }\n\n        return Result.build(succeed);\n    }\n\n    /**\n     * 转换具体格式\n     * @param combineLogicCluster 逻辑模板\n     * @return\n     */\n    private IndexTemplateLogicWithClusterAndMasterTemplate convert(IndexTemplateWithCluster combineLogicCluster) {\n        if (combineLogicCluster == null) {\n            return null;\n        }\n\n        IndexTemplateLogicWithClusterAndMasterTemplate combineLogicClusterAndMasterTemplate = ConvertUtil\n            .obj2Obj(combineLogicCluster, IndexTemplateLogicWithClusterAndMasterTemplate.class);\n\n        combineLogicClusterAndMasterTemplate.setLogicCluster(fetchOne(combineLogicCluster.getLogicClusters()));\n\n        combineLogicClusterAndMasterTemplate.setMasterTemplate(\n            fetchMasterTemplate(indexTemplatePhyService.getValidTemplatesByLogicId(combineLogicCluster.getId())));\n\n        return combineLogicClusterAndMasterTemplate;\n    }\n\n    /**\n     * 获取Master物理模板\n     * @param physicalTemplates 物理模板列表\n     * @return\n     */\n    private IndexTemplatePhy fetchMasterTemplate(List<IndexTemplatePhy> physicalTemplates) {\n        if (CollectionUtils.isEmpty(physicalTemplates)) {\n            return null;\n        }\n\n        for (IndexTemplatePhy physicalTemplate : physicalTemplates) {\n            if (TemplateDeployRoleEnum.MASTER.getCode().equals(physicalTemplate.getRole())) {\n                return physicalTemplate;\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * 获取第一条记录\n     * @param logicClusters 逻辑集群列表\n     * @return\n     */\n    private ClusterLogic fetchOne(List<ClusterLogic> logicClusters) {\n        if (CollectionUtils.isNotEmpty(logicClusters)) {\n            return logicClusters.get(0);\n        }\n\n        return null;\n    }\n\n    private Result<Void> validateIndexTemplateLogicStep2(IndexTemplateDTO param, String dateFormatFinal,\n                                                         String expressionFinal, String nameFinal,\n                                                         String dateFieldFinal) {\n        if (expressionFinal != null && expressionFinal.endsWith(\"*\") && AriusObjUtils.isNull(dateFormatFinal)) {\n            return Result.buildParamIllegal(\"表达式*结尾,后缀格式必填\");\n        }\n        if (dateFormatFinal != null && param.getExpireTime() != null && TemplateUtils.isSaveByDay(dateFormatFinal)\n            && param.getExpireTime() > TEMPLATE_SAVE_BY_DAY_EXPIRE_MAX) {\n            return Result.buildParamIllegal(\"按天创建的索引数据保存时长不能超过180天\");\n        }\n        if (dateFormatFinal != null && param.getExpireTime() != null && TemplateUtils.isSaveByMonth(dateFormatFinal)\n            && (param.getExpireTime() < TEMPLATE_SAVE_BY_MONTH_EXPIRE_MIN && param.getExpireTime() > 0)) {\n            return Result.buildParamIllegal(\"按月创建的索引数据保存时长不能小于30天\");\n        }\n        if (param.getExpireTime() != null && param.getExpireTime() > 0\n            && param.getExpireTime() < AdminConstant.PLATFORM_EXPIRE_TIME_MIN) {\n            return Result\n                .buildParamIllegal(String.format(\"分区索引模板数据保存天数不能小于%d天\", AdminConstant.PLATFORM_EXPIRE_TIME_MIN));\n        }\n        if (nameFinal != null) {\n            boolean expressionMatch = nameFinal.equals(expressionFinal) || (nameFinal + \"*\").equals(expressionFinal);\n            if (!expressionMatch) {\n                return Result.buildParamIllegal(\"表达式与模板名字不匹配\");\n            }\n        }\n        if (StringUtils.isNotBlank(dateFormatFinal) && StringUtils.isBlank(dateFieldFinal)) {\n            return Result.buildParamIllegal(\"索引分区创建，分区字段必填\");\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> validateIndexTemplateLogicStep1(IndexTemplateDTO param,\n                                                         List<IndexTemplate> indexTemplateList) {\n        // 校验索引名字\n        if (param.getName() != null) {\n            Result<Void> result = validateIndexName(param, indexTemplateList);\n            if (result.failed()) {\n                return result;\n            }\n        }\n        if (param.getExpression() != null) {\n            Result<Void> result = validateExpression(param, indexTemplateList);\n            if (result.failed()) {\n                return result;\n            }\n        }\n        if (param.getDataCenter() != null && !DataCenterEnum.validate(param.getDataCenter())) {\n            return Result.buildParamIllegal(\"数据中心非法\");\n        }\n        if (param.getProjectId() != null && !projectService.checkProjectExist(param.getProjectId())) {\n            return Result.buildParamIllegal(\"所属应用不存在\");\n        }\n        if (param.getDataType() != null && DataTypeEnum.UNKNOWN.equals(DataTypeEnum.valueOf(param.getDataType()))) {\n            return Result.buildParamIllegal(\"数据类型非法\");\n        }\n        if (param.getShardNum() != null && param.getShardNum() <= 0) {\n            return Result.buildNotExist(\"shard数量必须大于0\");\n        }\n        return Result.buildSucc();\n    }\n\n    private String getDateField(IndexTemplateDTO param, IndexTemplatePO oldPO) {\n        String dateFieldFinal;\n        if (param.getDateField() != null) {\n            dateFieldFinal = param.getDateField();\n        } else {\n            dateFieldFinal = oldPO.getDateField();\n        }\n        return dateFieldFinal;\n    }\n\n    private String getExpression(IndexTemplateDTO param, IndexTemplatePO oldPO) {\n        String expressionFinal;\n        if (param.getExpression() != null) {\n            expressionFinal = param.getExpression();\n        } else {\n            expressionFinal = oldPO.getExpression();\n        }\n        return expressionFinal;\n    }\n\n    private String getDateFormat(IndexTemplateDTO param, IndexTemplatePO oldPO) {\n        String dateFormatFinal;\n        if (param.getDateFormat() != null) {\n            dateFormatFinal = param.getDateFormat();\n        } else {\n            dateFormatFinal = oldPO.getDateFormat();\n        }\n        return dateFormatFinal;\n    }\n\n    private Result<Void> validateAdd(IndexTemplateDTO param) {\n        if (AriusObjUtils.isNull(param.getName())) {\n            return Result.buildParamIllegal(\"名字为空\");\n        }\n        if (AriusObjUtils.isNull(param.getProjectId())) {\n            return Result.buildParamIllegal(\"所属应用为空\");\n        }\n        if (AriusObjUtils.isNull(param.getDataType())) {\n            return Result.buildParamIllegal(\"数据类型为空\");\n        }\n        if (AriusObjUtils.isNull(param.getExpireTime())) {\n            return Result.buildParamIllegal(\"保存时长为空\");\n        }\n\n        if (AriusObjUtils.isNull(param.getExpression())) {\n            return Result.buildParamIllegal(\"表达式为空\");\n        }\n        if (AriusObjUtils.isNull(param.getDataCenter())) {\n            return Result.buildParamIllegal(\"数据中心为空\");\n        }\n        if (AriusObjUtils.isNull(param.getDiskSize())) {\n            return Result.buildParamIllegal(\"DiskSize为空\");\n        }\n        if (AriusObjUtils.isNull(param.getWriteRateLimit())) {\n            param.setWriteRateLimit(-1);\n        }\n        if (LevelEnum.valueOfCode(param.getLevel()).equals(LevelEnum.UNKNOWN)) {\n            return Result.buildParamIllegal(\"模板设置的服务等级为未知类型\");\n        }\n        if (levelOfTemplateLower(param)) {\n            return Result.buildParamIllegal(\"模板设置的服务等级低于所属逻辑集群的服务等级\");\n        }\n        if (!clusterLogicService.existClusterLogicById(param.getResourceId() )) {\n            return Result.buildNotExist(\"逻辑集群不存在\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private boolean levelOfTemplateLower(IndexTemplateDTO param) {\n        ClusterLogic clusterLogic =\n                clusterLogicService.getClusterLogicByIdThatNotContainsProjectId(param.getResourceId());\n        return !AriusObjUtils.isNull(clusterLogic) && clusterLogic.getLevel() < param.getLevel();\n    }\n\n    private Result<Void> validateExpression(IndexTemplateDTO param, List<IndexTemplate> indexTemplateList) {\n        String expression = param.getExpression();\n        for (IndexTemplate templateLogic : indexTemplateList) {\n            if (StringUtils.isBlank(templateLogic.getExpression()) || StringUtils.isBlank(expression)) {\n                continue;\n            }\n\n            if (templateLogic.getId().equals(param.getId())) {\n                continue;\n            }\n\n            if (templateLogic.getExpression().equals(expression)) {\n                return Result.buildParamIllegal(\"模板表达式已经存在\");\n            }\n\n            String otherExpressionPre = templateLogic.getExpression();\n            if (otherExpressionPre.endsWith(\"*\")) {\n                otherExpressionPre = otherExpressionPre.substring(0, otherExpressionPre.length() - 1);\n            }\n\n            String expressionPre = expression;\n            if (expressionPre.contains(\"*\")) {\n                expressionPre = expressionPre.substring(0, expressionPre.length() - 1);\n            }\n\n            if (expressionPre.startsWith(otherExpressionPre) || otherExpressionPre.startsWith(expressionPre)) {\n                return Result.buildParamIllegal(\"表达式与【\" + templateLogic.getName() + \"】冲突,不能互为前缀,模板表达式匹配时会重叠\");\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> validateIndexName(IndexTemplateDTO param, List<IndexTemplate> indexTemplateList) {\n        String name = param.getName();\n        if (name.length() < TEMPLATE_NAME_SIZE_MIN || name.length() > TEMPLATE_NAME_SIZE_MAX) {\n            return Result\n                .buildParamIllegal(String.format(\"名称长度非法, %s-%s\", TEMPLATE_NAME_SIZE_MIN, TEMPLATE_NAME_SIZE_MAX));\n        }\n\n        for (Character c : name.toCharArray()) {\n            if (!TEMPLATE_NAME_CHAR_SET.contains(c)) {\n                return Result.buildParamIllegal(\"名称包含非法字符, 只能包含小写字母、数字、-、_和.\");\n            }\n        }\n\n        for (IndexTemplate templateLogic : indexTemplateList) {\n            if (templateLogic.getName().equals(name) && !templateLogic.getId().equals(param.getId())) {\n                return Result.buildDuplicate(\"模板名称已经存在\");\n            }\n        }\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/template/logic/impl/TemplateLogicAliasServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.template.logic.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_NAME_CHAR_SET;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_NAME_SIZE_MAX;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.TemplateConstant.TEMPLATE_NAME_SIZE_MIN;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.ConsoleTemplateAliasSwitchDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.IndexTemplateAliasDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateAlias;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateAliasPO;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.CacheSwitch;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.TemplateLogicAliasService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateAliasDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplatePhyDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.putalias.PutAliasNode;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.putalias.PutAliasType;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Maps;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class TemplateLogicAliasServiceImpl implements TemplateLogicAliasService {\n\n    @Autowired\n    private IndexTemplateAliasDAO                     indexTemplateAliasDAO;\n    @Autowired\n    private IndexTemplateDAO                          indexTemplateDAO;\n    @Autowired\n    private IndexTemplatePhyDAO                       indexTemplatePhyDAO;\n \n    @Autowired\n    private CacheSwitch                               cacheSwitch;\n\n    private Cache<Integer, List<String>>              templateLogicAliasCache = CacheBuilder.newBuilder()\n        .expireAfterWrite(60, TimeUnit.MINUTES).maximumSize(1000).build();\n    private Cache<String, Map<Integer, List<String>>> templateAliasMapCache   = CacheBuilder.newBuilder()\n        .expireAfterWrite(1, TimeUnit.MINUTES).maximumSize(100).build();\n\n    /**\n     * 获取别名\n     *\n     * @param logicId logicId\n     * @return list\n     */\n    @Override\n    public List<String> getAliasesById(Integer logicId) {\n        List<TemplateAliasPO> indexTemplateAliasPOS = indexTemplateAliasDAO.listByTemplateId(logicId);\n        if (CollectionUtils.isEmpty(indexTemplateAliasPOS)) {\n            return new ArrayList<>();\n        }\n\n        return indexTemplateAliasPOS.stream().map(i -> i.getName()).collect(Collectors.toList());\n    }\n\n    /**\n     * 从缓存中获取模板所有的别名\n     * @param logicId\n     * @return\n     */\n    @Override\n    public List<String> getAliasesByIdFromCache(Integer logicId) {\n        try {\n            return templateLogicAliasCache.get(logicId, () -> getAliasesById(logicId));\n        } catch (ExecutionException e) {\n            return getAliasesById(logicId);\n        }\n    }\n\n    /**\n     * 获取别名\n     *\n     * @return list\n     */\n    @Override\n    public List<IndexTemplateAlias> listAlias() {\n        return ConvertUtil.list2List(indexTemplateAliasDAO.listAll(), IndexTemplateAlias.class);\n    }\n\n    /**\n     * 获取平台所有索引别名\n     * @return\n     */\n    @Override\n    public Map<Integer, List<String>> listAliasMap() {\n        Map<Integer, List<String>> templateAliasMap = Maps.newHashMap();\n\n        List<IndexTemplateAlias> aliasList = ConvertUtil.list2List(indexTemplateAliasDAO.listAll(),\n            IndexTemplateAlias.class);\n\n        if (CollectionUtils.isNotEmpty(aliasList)) {\n            for (IndexTemplateAlias alias : aliasList) {\n                Integer key = alias.getLogicId();\n                List<String> aliasNames = templateAliasMap.getOrDefault(key, new ArrayList<>());\n                aliasNames.add(alias.getName());\n                templateAliasMap.putIfAbsent(key, aliasNames);\n            }\n        }\n        return templateAliasMap;\n    }\n\n    @Override\n    public Map<Integer, List<String>> listAliasMapWithCache() {\n        if (cacheSwitch.logicTemplateCacheEnable()) {\n            try {\n                return templateAliasMapCache.get(\"listAliasMap\", this::listAliasMap);\n            } catch (ExecutionException e) {\n                return listAliasMap();\n            }\n        }\n        return listAliasMap();\n    }\n\n    /**\n     * 增加一个索引的别名\n     *\n     * @param indexTemplateAlias\n     * @return\n     */\n    @Override\n    public Result<Boolean> addAlias(IndexTemplateAliasDTO indexTemplateAlias) {\n        //这里进行别名检查\n        Result result = aliasChecked(indexTemplateAlias.getName(), null, indexTemplateAlias.getLogicId());\n        if (null != result) {\n            return Result.buildSucc(result.success(), result.getMessage());\n        }\n        int ret = indexTemplateAliasDAO.insert(ConvertUtil.obj2Obj(indexTemplateAlias, TemplateAliasPO.class));\n\n        return Result.buildSucc(ret > 0);\n    }\n\n    /**\n     * 删除一个索引的别名\n     *\n     * @param indexTemplateAlias\n     * @return\n     */\n    @Override\n    public Result<Boolean> delAlias(IndexTemplateAliasDTO indexTemplateAlias) {\n        int ret = indexTemplateAliasDAO.delete(indexTemplateAlias.getLogicId(), indexTemplateAlias.getName());\n\n        return Result.buildSucc(ret > 0);\n    }\n\n   \n\n    private Result<List<PutAliasNode>> buildAliasNodes(ConsoleTemplateAliasSwitchDTO aliasSwitchDTO,\n                                                       List<IndexTemplatePO> indexIndexTemplatePOS,\n                                                       List<TemplateAliasPO> insertAliasList,\n                                                       List<Integer> deleteAliasList, Set<Integer> logicIdList) {\n        List<PutAliasNode> nodes = new ArrayList<>();\n        List<PutAliasNode> addNodes = buildAliasNodes(aliasSwitchDTO, PutAliasType.ADD, indexIndexTemplatePOS,\n            insertAliasList, deleteAliasList, logicIdList);\n        if (null == addNodes) {\n            Result.buildFail(\"索引模板不存在！\");\n        } else if (CollectionUtils.isNotEmpty(addNodes)) {\n            nodes.addAll(addNodes);\n        }\n        List<PutAliasNode> removeNodes = buildAliasNodes(aliasSwitchDTO, PutAliasType.REMOVE, indexIndexTemplatePOS,\n            insertAliasList, deleteAliasList, logicIdList);\n        if (removeNodes == null) {\n            Result.buildFail(\"索引模板不存在！\");\n        } else if (CollectionUtils.isNotEmpty(removeNodes)) {\n            nodes.addAll(removeNodes);\n        }\n        return Result.buildSucc(nodes);\n    }\n\n    private List<PutAliasNode> buildAliasNodes(ConsoleTemplateAliasSwitchDTO aliasSwitchDTO, PutAliasType aliasType,\n                                               List<IndexTemplatePO> indexIndexTemplatePOS,\n                                               List<TemplateAliasPO> insertAliasList, List<Integer> deleteAliasList,\n                                               Set<Integer> logicIdList) {\n        List<PutAliasNode> nodes = new ArrayList<>();\n        List<String> indexList = null;\n        String aliasName = aliasSwitchDTO.getAliasName();\n        if (PutAliasType.ADD == aliasType) {\n            indexList = aliasSwitchDTO.getAddAliasIndices();\n        } else if (PutAliasType.REMOVE == aliasType) {\n            indexList = aliasSwitchDTO.getDelAliasIndices();\n        }\n\n        if (CollectionUtils.isEmpty(indexList)) {\n            return nodes;\n        }\n        for (String indexName : indexList) {\n            Integer logicId = getLogicIdByIndexName(indexIndexTemplatePOS, indexName);\n            if (null == logicId) {\n                return null;\n            }\n            PutAliasNode node = new PutAliasNode();\n            node.setType(aliasType);\n            node.setAlias(aliasName);\n            node.setIndex(indexName);\n            nodes.add(node);\n            TemplateAliasPO aliasPO = new TemplateAliasPO();\n            if (!logicIdList.contains(logicId)) {\n                //针对逻辑ID去重，避免一个逻辑模板存在多条相同的别名记录\n                if (PutAliasType.ADD == aliasType) {\n                    aliasPO.setName(aliasName);\n                    aliasPO.setLogicId(logicId);\n                    insertAliasList.add(aliasPO);\n                }\n                deleteAliasList.add(logicId);\n                logicIdList.add(aliasPO.getLogicId());\n            }\n        }\n        return nodes;\n    }\n\n    /**\n     * 检查别名是否基于projectId唯一，检查模板是否已经拥有该别名，检查别名是否和索引模板互为前缀\n     *\n     * @param name\n     * @param projectId\n     * @param logicId\n     * @return\n     */\n    private Result aliasChecked(String name, Integer projectId, Integer logicId) {\n        if (StringUtils.isBlank(name)) {\n            return Result.buildFail(\"别名名称不能为空\");\n        }\n        if (name.length() < TEMPLATE_NAME_SIZE_MIN || name.length() > TEMPLATE_NAME_SIZE_MAX) {\n            return Result\n                .buildParamIllegal(String.format(\"名称长度非法, %s-%s\", TEMPLATE_NAME_SIZE_MIN, TEMPLATE_NAME_SIZE_MAX));\n        }\n        for (Character c : name.toCharArray()) {\n            if (!TEMPLATE_NAME_CHAR_SET.contains(c)) {\n                return Result.buildParamIllegal(\"名称包含非法字符, 只能包含小写字母、数字、-、_和.\");\n            }\n        }\n\n        String prefix = name.substring(0, 1);\n        if (StringUtils.containsAny(prefix, \"_\", \"-\", \"+\")) {\n            return Result.buildParamIllegal(\"Invalid alias name must not start with '_', '-', or '+'\");\n        }\n\n        // 这里进行别名检查\n        List<IndexTemplateAlias> aliasList = ConvertUtil.list2List(indexTemplateAliasDAO.listAll(),\n            IndexTemplateAlias.class);\n        List<IndexTemplatePO> poList = indexTemplateDAO.listAll();\n        Set<Integer> logicIds = new HashSet<>();\n        if (null != logicId) {\n            logicIds.add(logicId);\n        }\n        if (CollectionUtils.isNotEmpty(aliasList)) {\n            for (IndexTemplateAlias alias : aliasList) {\n                if (alias.getName().equals(name)) {\n                    logicIds.add(alias.getLogicId());\n                }\n                if (alias.getName().equals(name) && alias.getLogicId().equals(logicId)) {\n                    // 模板已经拥有该别名，返回true，不需要重复写入\n                    return Result.buildSucc(true);\n                }\n            }\n        }\n        //判断别名不能和索引互为前缀\n        if (CollectionUtils.isNotEmpty(poList)) {\n            if (poList.stream().anyMatch(IndexTemplateLogic -> IndexTemplateLogic.getName().startsWith(name)\n                                                               || name.startsWith(IndexTemplateLogic.getName()))) {\n                return Result.buildFail(\"别名不能和索引模板互为前缀！\");\n            }\n            List<IndexTemplatePO> indexTemplatePOS = poList.stream().filter(po -> logicIds.contains(po.getId()))\n                .collect(Collectors.toList());\n            Set<Integer> projectIds = new HashSet<>();\n            if (null != projectId) {\n                projectIds.add(projectId);\n            }\n            if (CollectionUtils.isNotEmpty(indexTemplatePOS)) {\n                projectIds\n                    .addAll(indexTemplatePOS.stream().map(IndexTemplatePO::getProjectId).collect(Collectors.toSet()));\n            } else if (CollectionUtils.isEmpty(indexTemplatePOS) && CollectionUtils.isNotEmpty(logicIds)) {\n                return Result.buildFail(\"索引模板不存在！\");\n            }\n            if (projectIds.size() > 1) {\n                //别名已经被其他projectId占用了\n                return Result.buildFail(\"别名已被占用！\");\n            }\n        }\n        return null;\n    }\n\n    private Integer getLogicIdByIndexName(List<IndexTemplatePO> indexIndexTemplatePOS, String indexName) {\n        for (IndexTemplatePO template : indexIndexTemplatePOS) {\n            String expression = template.getExpression();\n            //判断索引名称是否满足索引模板\n            if ((!expression.endsWith(\"*\") && template.getName().equals(indexName))\n                || (expression.endsWith(\"*\")\n                    && indexName.startsWith(expression.substring(0, expression.length() - 1)))) {\n                return template.getId();\n            }\n        }\n        return null;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/template/physic/IndexTemplatePhyService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.template.physic;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplatePhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\npublic interface IndexTemplatePhyService {\n    /**\n     * 条件查询\n     * @param param 参数\n     * @return 物理模板列表\n     */\n    List<IndexTemplatePhy> getByCondt(IndexTemplatePhyDTO param);\n\n    /**\n     * 查询指定逻辑模板对应的物理模板\n     * @param logicId 逻辑模板\n     * @return list\n     */\n    List<IndexTemplatePhy> getTemplateByLogicId(Integer logicId);\n    IndexTemplatePhy getTemplateByLogicIdAndRole(Integer logicId,Integer role);\n\n    /**\n     * 从缓存中查询指定逻辑模板对应的物理模板\n     * @param logicId 逻辑模板\n     * @return list\n     */\n    List<IndexTemplatePhy> getValidTemplatesByLogicId(Integer logicId);\n\n    /**\n     * 查询指定id的模板\n     * @param templatePhyId 物理模板id\n     * @return result\n     */\n    IndexTemplatePhy getTemplateById(Long templatePhyId);\n\n    /**\n     * 查询指定id的模板 包含逻辑模板信息\n     * @param physicalId 物理模板id\n     * @return result\n     */\n    IndexTemplatePhyWithLogic getTemplateWithLogicById(Long physicalId);\n\n    /**\n     * 插入\n     * @param param 物理索引模板\n     * @return result\n     */\n    Result<Long> insert(IndexTemplatePhyDTO param) throws AdminOperateException;\n\n    /**\n     * 删除\n     *\n     * @param cluster 物理集群名称\n     * @param name    模板名称\n     * @return\n     */\n    Boolean deleteDirtyByClusterAndName(String cluster, String name);\n\n    /**\n     * 删除\n     * @param physicalId 物理模板id\n     * @param operator 操作人\n     * @return result\n     * @throws ESOperateException e\n     */\n    Result<Void> delTemplate(Long physicalId, String operator) throws ESOperateException;\n\n    /**\n     * 删除\n     * @param logicId id\n     * @param operator 操作人\n     * @return result\n     * @throws ESOperateException e\n     */\n    Result<Void> delTemplateByLogicId(Integer logicId, String operator) throws ESOperateException;\n\n    /**\n     * 修改由于逻辑模板修改而物理模板需要同步修改的属性\n     * @param param 参数\n     * @param operator 操作人\n     * @return result\n     */\n    Result<Void> editTemplateFromLogic(IndexTemplateDTO param, String operator) throws ESOperateException;\n\n    /**\n     * 通过集群和名字查询\n     * @param cluster 集群\n     * @param templateName 名字\n     * @return result 不存在返回null\n     */\n    IndexTemplatePhy getTemplateByClusterAndName(String cluster, String templateName);\n\n    /**\n     * 通过集群和名字查询\n     * @param cluster 集群\n     * @param templateName 名字\n     * @return result 不存在返回null\n     */\n    IndexTemplatePhyWithLogic getTemplateWithLogicByClusterAndName(String cluster, String templateName);\n\n    /**\n     * 根据物理模板状态获取模板列表\n     * @param cluster 集群\n     * @param status 状态 1 常规    -1 删除中     -2 已删除\n     * @return list\n     */\n    List<IndexTemplatePhy> getTemplateByClusterAndStatus(String cluster, int status);\n\n    /**\n     * 根据物理模板状态获取模板列表\n     * @param logicId 逻辑模板id\n     * @param status 状态 1 常规    -1 删除中     -2 已删除\n     * @return list\n     */\n    List<IndexTemplatePhy> getTemplateByLogicIdAndStatus(Integer logicId, Integer status);\n\n    /**\n     * 根据物理模板状态获取模板列表\n     * @param cluster 集群\n     * @return list\n     */\n    List<IndexTemplatePhy> getNormalTemplateByCluster(String cluster);\n\n    /**\n     * 获取模板匹配的索引列表，按着时间排序\n     * @param physicalId 物理模板id\n     * @return list\n     */\n    List<String> getMatchNoVersionIndexNames(Long physicalId);\n\n    /**\n     * 获取模板匹配的索引列表，按着时间排序\n     * @param physicalId 物理模板id\n     * @return list\n     */\n    List<String> getMatchIndexNames(Long physicalId);\n\n    /**\n     * 批量获取模板信息\n     * @param physicalIds 物理模板id\n     * @return list\n     */\n    List<IndexTemplatePhyWithLogic> getTemplateWithLogicByIds(List<Long> physicalIds);\n\n    /**\n     * 全量获取指定物理集群所关联的逻辑模板信息列表\n     * @param phyCluster 物理集群名称\n     * @return 物理集群下的全量模板信息列表\n     */\n    List<IndexTemplatePhyWithLogic> getTemplateByPhyCluster(String phyCluster);\n\n    /**\n     * 根据名字查询\n     * @param template 名字\n     * @return list\n     */\n    List<IndexTemplatePhyWithLogic> getTemplateWithLogicByName(String template);\n\n    /**\n     * 获取全量\n     * @return list\n     */\n    List<IndexTemplatePhy> listTemplate();\n\n    List<IndexTemplatePhy> listTemplateWithCache();\n\n    /**\n     * 获取IndexTemplatePhysicalWithLogic\n     * @return list\n     */\n    List<IndexTemplatePhyWithLogic> listTemplateWithLogic();\n\n    List<IndexTemplatePhyWithLogic> listTemplateWithLogicWithCache();\n\n    /**\n     * 获取集群模板量统计映射\n     */\n    Map<String, Integer> getClusterTemplateCountMap();\n\n    /**\n     * 根绝逻辑模板id列表查询\n     * @param logicIds 列表\n     * @return list\n     */\n    List<IndexTemplatePhy> getTemplateByLogicIds(List<Integer> logicIds);\n\n    /**\n     * 修改物理模板，名称\n     * @param physical 模板\n     * @param operator 操作人\n     * @return\n     */\n    Result<Void> updateTemplateName(IndexTemplatePhy physical, String operator) throws ESOperateException;\n\n    /**\n     * 修改物理模板，表达\n     * @param indexTemplatePhy 模板\n     * @param expression 新的表达\n     * @param operator 操作人\n     * @throws ESOperateException\n     * @return result\n     */\n    Result<Void> updateTemplateExpression(IndexTemplatePhy indexTemplatePhy, String expression,\n                                          String operator) throws ESOperateException;\n\n    /**\n     * 修改物理模板，表达\n     * @param indexTemplatePhy 模板\n     * @param shardNum 分片数量\n     * @param operator 操作人\n     * @throws ESOperateException\n     * @return result\n     */\n    Result<Void> updateTemplateShardNum(IndexTemplatePhy indexTemplatePhy, Integer shardNum,\n                                        String operator) throws ESOperateException;\n\n    /**\n     * 修改物理模板，角色\n     * @param indexTemplatePhy 模板\n     * @param templateDeployRoleEnum 角色\n     * @param operator 操作人\n     * @return\n     */\n    Result<Void> updateTemplateRole(IndexTemplatePhy indexTemplatePhy, TemplateDeployRoleEnum templateDeployRoleEnum,\n                                    String operator);\n\n    /**\n     * 更新物理模板\n     *\n     */\n    Result<Void> update(IndexTemplatePhyDTO indexTemplatePhyDTO);\n\n    /**\n     *\n     * @param physicalPO\n     * @return\n     */\n    IndexTemplatePhyWithLogic buildIndexTemplatePhysicalWithLogic(IndexTemplatePhyPO physicalPO);\n\n    Map<Integer, Integer> getAllLogicTemplatesPhysicalCount();\n\n    /**\n     * 校验物理模板信息\n     *\n     * @param param     参数\n     * @param operation 操作\n     * @return result\n     */\n    Result<Void> validateTemplate(IndexTemplatePhyDTO param, OperationEnum operation);\n\n    /**\n     * 批量校验物理模板信息\n     *\n     * @param params    参数\n     * @param operation 操作\n     * @return result\n     */\n    Result<Void> validateTemplates(List<IndexTemplatePhyDTO> params, OperationEnum operation);\n\n    /**\n     * 获取指定regionId下的所有物理模板列表\n     * @param regionId  regionId\n     * @return    Result<List<IndexTemplatePhy>>\n     */\n    Result<List<IndexTemplatePhy>> listByRegionId(Integer regionId);\n\n    IndexTemplatePhyWithLogic buildIndexTemplatePhysicalWithLogicByPhysicalId(Long physicalId);\n\n    List<IndexTemplatePhyPO> getByClusterAndNameAndStatus(String cluster, String name, int code);\n\n    Collection<IndexTemplatePhyPO> getByClusterAndStatus(String cluster, int code);\n\n    boolean updateStatus(Long physicalId, int code);\n\n    boolean updateByIndexTemplatePhyPO(IndexTemplatePhyPO physicalPO);\n    \n    List<String> getPhyClusterByLogicTemplateId(Integer logicTemplateId);\n    \n    /**\n     * 通过逻辑 id 更新索引模板的分片号\n     *\n     * @param logicId  逻辑索引 ID，即 index_template_logic 表中索引的 ID。\n     * @param shardNum 要更新的分片数\n     */\n    boolean updateShardNumByLogicId(Integer logicId, Integer shardNum);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/template/physic/impl/IndexTemplatePhyServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.template.physic.impl;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum.EDIT;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.IndexTemplatePhysicalConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplatePhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateDeployRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplatePhysicalStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.template.PhysicalTemplateDeleteEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameFactory;\nimport com.didichuxing.datachannel.arius.admin.core.component.CacheSwitch;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplatePhyDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Service\npublic class IndexTemplatePhyServiceImpl implements IndexTemplatePhyService {\n\n    private static final ILog      LOGGER                       = LogFactory.getLog(IndexTemplatePhyServiceImpl.class);\n\n    public static final Integer    NOT_CHECK                    = -100;\n\n    private static final String    MSG                          = \"editTemplateFromLogic fail||physicalId={}||expression={}\";\n    private static final String    TEMPLATE_PHYSICAL_ID_IS_NULL = \"物理模板id为空\";\n\n    private static final String    TEMPLATE_PHYSICAL_NOT_EXISTS = \"物理模板不存在\";\n\n    private static final String    CHECK_FAIL_MSG               = \"check fail||msg={}\";\n\n    @Autowired\n    private IndexTemplatePhyDAO    indexTemplatePhyDAO;\n\n    @Autowired\n    private IndexTemplateDAO       indexTemplateDAO;\n\n    \n\n    @Autowired\n    private ESIndexService         esIndexService;\n\n    @Autowired\n    private ESTemplateService      esTemplateService;\n\n    @Autowired\n    private ClusterPhyService      clusterPhyService;\n\n    @Autowired\n    private IndexTemplateService   indexTemplateService;\n\n    @Autowired\n    private ClusterRegionService   clusterRegionService;\n\n    @Autowired\n    private CacheSwitch            cacheSwitch;\n    \n    private Cache<String, List<?>> templatePhyListCache         = CacheBuilder.newBuilder()\n        .expireAfterWrite(1, TimeUnit.MINUTES).maximumSize(10).build();\n\n    /**\n     * 条件查询\n     *\n     * @param param 参数\n     * @return 物理模板列表\n     */\n    @Override\n    public List<IndexTemplatePhy> getByCondt(IndexTemplatePhyDTO param) {\n        return ConvertUtil.list2List(\n            indexTemplatePhyDAO.listByCondition(ConvertUtil.obj2Obj(param, IndexTemplatePhyPO.class)),\n            IndexTemplatePhy.class);\n    }\n\n    /**\n     * 查询指定逻辑模板对应的物理模板\n     *\n     * @param logicId 逻辑模板\n     * @return result\n     */\n    @Override\n    public List<IndexTemplatePhy> getTemplateByLogicId(Integer logicId) {\n        return ConvertUtil.list2List(indexTemplatePhyDAO.listByLogicId(logicId), IndexTemplatePhy.class);\n    }\n    \n    /**\n     * @param logicId\n     * @param role\n     * @return\n     */\n    @Override\n    public IndexTemplatePhy getTemplateByLogicIdAndRole(Integer logicId, Integer role) {\n        return ConvertUtil.obj2Obj(indexTemplatePhyDAO.getTemplateByLogicIdAndRole(logicId,role),IndexTemplatePhy.class);\n    }\n    \n    /**\n     * 从缓存中查询指定逻辑模板对应的物理模板\n     * @param logicId 逻辑模板\n     * @return list\n     */\n    @Override\n    public List<IndexTemplatePhy> getValidTemplatesByLogicId(Integer logicId) {\n        if (logicId == null) {\n            return Lists.newArrayList();\n        }\n\n        List<IndexTemplatePhy> indexTemplatePhies = listTemplate();\n        if (CollectionUtils.isEmpty(indexTemplatePhies)) {\n            return Lists.newArrayList();\n        }\n\n        return indexTemplatePhies.parallelStream()\n            .filter(i -> i.getLogicId() != null && logicId.intValue() == i.getLogicId().intValue())\n            .collect(Collectors.toList());\n    }\n\n    @Override\n    public IndexTemplatePhy getTemplateById(Long templatePhyId) {\n        return ConvertUtil.obj2Obj(indexTemplatePhyDAO.getById(templatePhyId), IndexTemplatePhy.class);\n    }\n\n    /**\n     * 查询指定id的模板 包含逻辑模板信息\n     *\n     * @param physicalId 物理模板id\n     * @return result\n     */\n    @Override\n    public IndexTemplatePhyWithLogic getTemplateWithLogicById(Long physicalId) {\n        IndexTemplatePhyPO physicalPO = indexTemplatePhyDAO.getById(physicalId);\n        return buildIndexTemplatePhysicalWithLogic(physicalPO);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Long> insert(IndexTemplatePhyDTO param) throws AdminOperateException {\n        IndexTemplatePhyPO newTemplate = ConvertUtil.obj2Obj(param, IndexTemplatePhyPO.class);\n        boolean succ = (1 == indexTemplatePhyDAO.insert(newTemplate));\n    \n        return Result.build(succ, newTemplate.getId());\n    }\n\n    @Override\n    public Boolean deleteDirtyByClusterAndName(String cluster, String name) {\n        return indexTemplatePhyDAO.deleteDirtyByClusterAndName(cluster, name) > 0;\n    }\n\n    /**\n     * 删除\n     *\n     * @param physicalId 物理模板id\n     * @param operator   操作人\n     * @return result\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> delTemplate(Long physicalId, String operator) throws ESOperateException {\n        IndexTemplatePhyPO oldPO = indexTemplatePhyDAO.getById(physicalId);\n        if (oldPO == null) {\n            return Result.buildNotExist(\"template not exist\");\n        }\n\n        boolean succ = 1 == indexTemplatePhyDAO.updateStatus(physicalId,\n            TemplatePhysicalStatusEnum.INDEX_DELETING.getCode());\n        if (succ) {\n            // 删除集群中的模板\n            try {\n                if (!(esIndexService.syncDeleteByExpression(oldPO.getCluster(), oldPO.getExpression(), 3)\n                    && esTemplateService.syncDelete(oldPO.getCluster(), oldPO.getName(), 1))) {\n                    throw new ESOperateException(\n                            String.format(\"删除集群【%s】中物理模板【%s】失败！\", oldPO.getCluster(), oldPO.getName()));\n                }\n            } catch (ESOperateException e) {\n                String msg = e.getMessage();\n                if (StringUtils.indexOf(msg, \"index_template_missing_exception\") != -1) {\n                    LOGGER.warn(\n                        \"class=TemplatePhyServiceImpl||method=delTemplate||physicalId={}||operator={}||msg= index template not found!\",\n                        physicalId, operator);\n                } else {\n                    LOGGER.error(\n                        \"class=TemplatePhyServiceImpl||method=delTemplate||physicalId={}||operator={}||msg=delete physical template failed! {}\",\n                        physicalId, operator, msg);\n                    throw new ESOperateException(\n                        String.format(\"删除集群【%s】中物理模板【%s】失败！\", oldPO.getCluster(), oldPO.getName()));\n                }\n            }\n         \n\n            SpringTool.publish(new PhysicalTemplateDeleteEvent(this, ConvertUtil.obj2Obj(oldPO, IndexTemplatePhy.class),\n                indexTemplateService.getLogicTemplateWithPhysicalsById(oldPO.getLogicId())));\n        }\n\n        return Result.build(succ);\n    }\n\n    /**\n     * 删除\n     *\n     * @param logicId  id\n     * @param operator 操作人\n     * @return result\n     * @throws ESOperateException e\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> delTemplateByLogicId(Integer logicId, String operator) throws ESOperateException {\n        List<IndexTemplatePhyPO> physicalPOs = indexTemplatePhyDAO.listByLogicId(logicId);\n\n        boolean succ = true;\n        if (CollectionUtils.isEmpty(physicalPOs)) {\n            LOGGER.info(\n                \"class=TemplatePhyServiceImpl||method=delTemplateByLogicId||logicId={}||msg=template no physical info!\",\n                logicId);\n        } else {\n            LOGGER.info(\n                \"class=TemplatePhyServiceImpl||method=delTemplateByLogicId||logicId={}||physicalSize={}||msg=template has physical info!\",\n                logicId, physicalPOs.size());\n            for (IndexTemplatePhyPO physicalPO : physicalPOs) {\n                if (delTemplate(physicalPO.getId(), operator).failed()) {\n                    succ = false;\n                }\n\n            }\n        }\n\n        return Result.build(succ);\n    }\n\n    /**\n     * 修改由于逻辑模板修改而物理模板需要同步修改的属性\n     * 目前有:\n     * expression\n     *\n     * @param param    参数\n     * @param operator 操作人\n     * @return result\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public Result<Void> editTemplateFromLogic(IndexTemplateDTO param, String operator) throws ESOperateException {\n        if (param == null) {\n            return Result.buildFail(\"参数为空！\");\n        }\n        List<IndexTemplatePhyPO> physicalPOs = indexTemplatePhyDAO.listByLogicId(param.getId());\n        if (CollectionUtils.isEmpty(physicalPOs)) {\n            return Result.buildSucc();\n        }\n\n        for (IndexTemplatePhyPO physicalPO : physicalPOs) {\n            IndexTemplatePhyPO updateParam = new IndexTemplatePhyPO();\n            updateParam.setId(physicalPO.getId());\n\n            if (null != param.getWriteRateLimit() && StringUtils.isNotBlank(physicalPO.getConfig())) {\n                IndexTemplatePhysicalConfig indexTemplatePhysicalConfig = JSON.parseObject(physicalPO.getConfig(),\n                    IndexTemplatePhysicalConfig.class);\n\n                indexTemplatePhysicalConfig.setManualPipeLineRateLimit(param.getWriteRateLimit());\n                updateParam.setConfig(JSON.toJSONString(indexTemplatePhysicalConfig));\n                boolean succeed = (1 == indexTemplatePhyDAO.update(updateParam));\n                if (!succeed) {\n                    LOGGER.warn(\n                        \"class=TemplatePhyServiceImpl||method=editTemplateFromLogic||msg=editTemplateFromLogic fail||physicalId={}||expression={}||writeRateLimit={}\",\n                        physicalPO.getId(), param.getExpression(), param.getWriteRateLimit());\n                    return Result.build(false);\n                }\n            }\n\n            Result<Void> buildExpression = updateExpressionTemplatePhysical(param, updateParam, physicalPO);\n            if (buildExpression.failed()) {\n                return buildExpression;\n            }\n\n            Result<Void> buildShardNum = updateShardNumTemplatePhy(param, updateParam, physicalPO);\n            if (buildShardNum.failed()) {\n                return buildShardNum;\n            }\n        }\n\n        return Result.buildSucc();\n    }\n\n    /**\n     * 通过集群和名字查询\n     *\n     * @param cluster      集群\n     * @param templateName 名字\n     * @return result 不存在返回null\n     */\n    @Override\n    public IndexTemplatePhy getTemplateByClusterAndName(String cluster, String templateName) {\n        return ConvertUtil.obj2Obj(indexTemplatePhyDAO.getByClusterAndName(cluster, templateName),\n            IndexTemplatePhy.class);\n    }\n\n    /**\n     * 通过集群和名字查询\n     *\n     * @param cluster      集群\n     * @param templateName 名字\n     * @return result 不存在返回null\n     */\n    @Override\n    public IndexTemplatePhyWithLogic getTemplateWithLogicByClusterAndName(String cluster, String templateName) {\n        return buildIndexTemplatePhysicalWithLogic(indexTemplatePhyDAO.getByClusterAndName(cluster, templateName));\n    }\n\n    /**\n     * 根据物理模板状态获取模板列表\n     *\n     * @param cluster 集群\n     * @param status  状态\n     * @return list\n     */\n    @Override\n    public List<IndexTemplatePhy> getTemplateByClusterAndStatus(String cluster, int status) {\n        return ConvertUtil.list2List(indexTemplatePhyDAO.listByClusterAndStatus(cluster, status),\n            IndexTemplatePhy.class);\n    }\n\n    /**\n     * 根据物理模板状态获取模板列表\n     * @param logicId 逻辑模板id\n     * @param status 状态 1 常规    -1 删除中     -2 已删除\n     * @return list\n     */\n    @Override\n    public List<IndexTemplatePhy> getTemplateByLogicIdAndStatus(Integer logicId, Integer status) {\n        return ConvertUtil.list2List(indexTemplatePhyDAO.getByLogicIdAndStatus(logicId, status),\n            IndexTemplatePhy.class);\n    }\n\n    /**\n     * 获取状态正常的模板列表\n     *\n     * @param cluster 集群\n     * @return list\n     */\n    @Override\n    public List<IndexTemplatePhy> getNormalTemplateByCluster(String cluster) {\n        return ConvertUtil.list2List(\n            indexTemplatePhyDAO.listByClusterAndStatus(cluster, TemplatePhysicalStatusEnum.NORMAL.getCode()),\n            IndexTemplatePhy.class);\n    }\n\n    /**\n     * 获取模板匹配的索引列表，按着时间排序\n     * 注意：\n     * 该方法只能识别出那些时间后缀是一样的情况；\n     * 如果模板中途修改过时间后缀，则无法识别之前时间后缀的索引\n     *\n     * @param physicalId 物理模板id\n     * @return list\n     */\n    @Override\n    public List<String> getMatchNoVersionIndexNames(Long physicalId) {\n        IndexTemplatePhyWithLogic templatePhysicalWithLogic = getTemplateWithLogicById(physicalId);\n        if (templatePhysicalWithLogic == null) {\n            return Lists.newArrayList();\n        }\n        Set<String> indices = esIndexService.syncGetIndexNameByExpression(templatePhysicalWithLogic.getCluster(),\n            templatePhysicalWithLogic.getExpression());\n        if (CollectionUtils.isEmpty(indices)) {\n            return Lists.newArrayList();\n        }\n\n        Set<String> noVersionIndices = indices.stream()\n            .map(indexName -> IndexNameFactory.genIndexNameClear(indexName, templatePhysicalWithLogic.getExpression()))\n            .collect(Collectors.toSet());\n\n        List<String> matchIndices = Lists.newArrayList();\n        for (String noVersionIndex : noVersionIndices) {\n            if (IndexNameFactory.noVersionIndexMatchExpression(noVersionIndex,\n                templatePhysicalWithLogic.getExpression(),\n                templatePhysicalWithLogic.getLogicTemplate().getDateFormat())) {\n                matchIndices.add(noVersionIndex);\n            }\n        }\n\n        Collections.sort(matchIndices);\n\n        return matchIndices;\n    }\n\n    /**\n     * 获取模板匹配的索引列表，按着时间排序\n     *\n     * @param physicalId 物理模板id\n     * @return list\n     */\n    @Override\n    public List<String> getMatchIndexNames(Long physicalId) {\n        IndexTemplatePhyWithLogic templatePhysicalWithLogic = getNormalAndDeletingTemplateWithLogicById(physicalId);\n        if (templatePhysicalWithLogic == null) {\n            return Lists.newArrayList();\n        }\n\n        List<CatIndexResult> indices = esIndexService.syncCatIndexByExpression(templatePhysicalWithLogic.getCluster(),\n            templatePhysicalWithLogic.getExpression());\n        if (CollectionUtils.isEmpty(indices)) {\n            return Lists.newArrayList();\n        }\n\n        List<String> matchIndices = Lists.newArrayList();\n        for (CatIndexResult indexResult : indices) {\n            LOGGER.info(\n                \"class=TemplatePhyServiceImpl||method=getMatchIndexNames||msg=fetch should be deleted indices||template={}||status={}||\"\n                        + \"cluster={}||docCount={}||docSize={}\",\n                templatePhysicalWithLogic.getName(), templatePhysicalWithLogic.getStatus(),\n                templatePhysicalWithLogic.getCluster(), indexResult.getDocsCount(), indexResult.getStoreSize());\n\n            if (IndexNameFactory.indexMatchExpression(indexResult.getIndex(), templatePhysicalWithLogic.getExpression(),\n                templatePhysicalWithLogic.getLogicTemplate().getDateFormat())) {\n                matchIndices.add(indexResult.getIndex());\n            }\n        }\n\n        Collections.sort(matchIndices);\n\n        return matchIndices;\n    }\n\n    /**\n     * 批量获取模板信息\n     *\n     * @param physicalIds 物理模板id\n     * @return list\n     */\n    @Override\n    public List<IndexTemplatePhyWithLogic> getTemplateWithLogicByIds(List<Long> physicalIds) {\n        if (CollectionUtils.isEmpty(physicalIds)) {\n            return Lists.newArrayList();\n        }\n        List<IndexTemplatePhyPO> indexTemplatePhyPOS = indexTemplatePhyDAO.listByIds(physicalIds);\n        return batchBuildTemplatePhysicalWithLogic(indexTemplatePhyPOS);\n    }\n\n    @Override\n    public List<IndexTemplatePhyWithLogic> getTemplateByPhyCluster(String phyCluster) {\n        if (phyCluster == null) {\n            return new ArrayList<>();\n        }\n\n        return batchBuildTemplatePhysicalWithLogic(\n            indexTemplatePhyDAO.listByClusterAndStatus(phyCluster, TemplatePhysicalStatusEnum.NORMAL.getCode()));\n    }\n\n    /**\n     * 根据名字查询\n     *\n     * @param template 名字\n     * @return list\n     */\n    @Override\n    public List<IndexTemplatePhyWithLogic> getTemplateWithLogicByName(String template) {\n        List<IndexTemplatePhyPO> indexTemplatePhyPOS = indexTemplatePhyDAO.listByName(template);\n        return batchBuildTemplatePhysicalWithLogic(indexTemplatePhyPOS);\n    }\n\n    /**\n     * 获取全量\n     *\n     * @return list\n     */\n    @Override\n    public List<IndexTemplatePhy> listTemplate() {\n        return ConvertUtil.list2List(indexTemplatePhyDAO.listAll(), IndexTemplatePhy.class);\n    }\n\n    @Override\n    public List<IndexTemplatePhy> listTemplateWithCache() {\n        try {\n            return (List<IndexTemplatePhy>) templatePhyListCache.get(\"listTemplate\", this::listTemplate);\n        } catch (Exception e) {\n            return listTemplate();\n        }\n    }\n\n    /**\n     * 获取IndexTemplatePhysicalWithLogic\n     *\n     * @return list\n     */\n    @Override\n    public List<IndexTemplatePhyWithLogic> listTemplateWithLogic() {\n        List<IndexTemplatePhyPO> indexTemplatePhyPOS = indexTemplatePhyDAO.listAll();\n        return batchBuildTemplatePhysicalWithLogic(indexTemplatePhyPOS);\n    }\n\n    @Override\n    public List<IndexTemplatePhyWithLogic> listTemplateWithLogicWithCache() {\n        try {\n            return (List<IndexTemplatePhyWithLogic>) templatePhyListCache.get(\"listTemplateWithLogic\",\n                this::listTemplateWithLogic);\n        } catch (Exception e) {\n            return listTemplateWithLogic();\n        }\n    }\n\n    @Override\n    public Map<String, Integer> getClusterTemplateCountMap() {\n        Map<String, Integer> templateCountMap = Maps.newHashMap();\n        List<IndexTemplatePhyWithLogic> indexTemplateList = listTemplateWithLogic();\n        if (CollectionUtils.isNotEmpty(indexTemplateList)) {\n            for (IndexTemplatePhyWithLogic indexTemplate : indexTemplateList) {\n                Integer templateCount = templateCountMap.get(indexTemplate.getCluster());\n                templateCount = templateCount == null ? 1 : templateCount + 1;\n                templateCountMap.put(indexTemplate.getCluster(), templateCount);\n            }\n        }\n        return templateCountMap;\n    }\n\n    /**\n     * 根绝逻辑模板id列表查询\n     *\n     * @param logicIds 列表\n     * @return list\n     */\n    @Override\n    public List<IndexTemplatePhy> getTemplateByLogicIds(List<Integer> logicIds) {\n        return ConvertUtil.list2List(indexTemplatePhyDAO.listByLogicIds(logicIds), IndexTemplatePhy.class);\n    }\n\n    @Override\n    public Result<Void> updateTemplateName(IndexTemplatePhy physical, String operator) throws ESOperateException {\n        Result<Void> validResult = validParamUpdateTemplateName(physical);\n        if (validResult.failed()) {\n            return Result.buildFrom(validResult);\n        }\n\n        IndexTemplatePhyPO editParam = new IndexTemplatePhyPO();\n        editParam.setId(physical.getId());\n        editParam.setName(physical.getName());\n\n        //更新数据库中物理模板的名称\n        boolean succ = 1 == indexTemplatePhyDAO.update(editParam);\n        if (!succ) {\n            return Result.buildFail(\"修改物理模板失败\");\n        }\n\n        //更新ES当中存储的物理模板的名称\n        IndexTemplatePhyPO oldPhysicalPO = indexTemplatePhyDAO.getById(physical.getId());\n        return Result.build(\n            esTemplateService.syncUpdateName(physical.getCluster(), oldPhysicalPO.getName(), physical.getName(), 0));\n    }\n\n    @Override\n    public Result<Void> updateTemplateExpression(IndexTemplatePhy indexTemplatePhy, String expression,\n                                                 String operator) throws ESOperateException {\n        IndexTemplatePhyPO updateParam = new IndexTemplatePhyPO();\n        updateParam.setId(indexTemplatePhy.getId());\n        updateParam.setExpression(expression);\n        boolean succeed = (1 == indexTemplatePhyDAO.update(updateParam));\n\n        if (succeed) {\n            esTemplateService.syncUpdateExpression(indexTemplatePhy.getCluster(), indexTemplatePhy.getName(),\n                expression, 0);\n        } else {\n            LOGGER.warn(\"class=TemplatePhyServiceImpl||method=updateTemplateExpression||msg=\", MSG,\n                indexTemplatePhy.getId(), expression);\n            return Result.buildFail(\"数据库更新失败\");\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> updateTemplateShardNum(IndexTemplatePhy indexTemplatePhy, Integer shardNum,\n                                               String operator) throws ESOperateException {\n        IndexTemplatePhyPO updateParam = new IndexTemplatePhyPO();\n        updateParam.setId(indexTemplatePhy.getId());\n        updateParam.setShard(shardNum);\n        boolean succeed = 1 == indexTemplatePhyDAO.update(updateParam);\n        if (succeed) {\n            LOGGER.info(\n                \"class=TemplatePhyServiceImpl||method=editTemplateFromLogic succeed||physicalId={}||preShardNum={}||currentShardNum={}\",\n                indexTemplatePhy.getId(), indexTemplatePhy.getShard(), shardNum);\n\n            esTemplateService.syncUpdateShardNum(indexTemplatePhy.getCluster(), indexTemplatePhy.getName(), shardNum,\n                0);\n        } else {\n            LOGGER.warn(\n                \"class=TemplatePhyServiceImpl||method=updateTemplateShardNum||editTemplateFromLogic fail||physicalId={}||shardNum={}\",\n                indexTemplatePhy.getId(), shardNum);\n            return Result.buildFail(\"数据库更新失败\");\n        }\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> updateTemplateRole(IndexTemplatePhy indexTemplatePhy,\n                                           TemplateDeployRoleEnum templateDeployRoleEnum, String operator) {\n        IndexTemplatePhyPO updateParam = new IndexTemplatePhyPO();\n        updateParam.setId(indexTemplatePhy.getId());\n        updateParam.setRole(templateDeployRoleEnum.getCode());\n        return Result.build(1 == indexTemplatePhyDAO.update(updateParam));\n    }\n\n    @Override\n    public Result<Void> update(IndexTemplatePhyDTO indexTemplatePhyDTO) {\n        IndexTemplatePhyPO updateParam = ConvertUtil.obj2Obj(indexTemplatePhyDTO, IndexTemplatePhyPO.class);\n        return Result.build(1 == indexTemplatePhyDAO.update(updateParam));\n    }\n\n    @Override\n    public IndexTemplatePhyWithLogic buildIndexTemplatePhysicalWithLogic(IndexTemplatePhyPO physicalPO) {\n        if (physicalPO == null) {\n            return null;\n        }\n\n        IndexTemplatePhyWithLogic indexTemplatePhyWithLogic = ConvertUtil.obj2Obj(physicalPO,\n            IndexTemplatePhyWithLogic.class);\n\n        IndexTemplatePO logicPO = indexTemplateDAO.getById(physicalPO.getLogicId());\n        if (logicPO == null) {\n            LOGGER.warn(\n                \"class=TemplatePhyServiceImpl||method=buildIndexTemplatePhysicalWithLogic||logic template not exist||logicId={}\",\n                physicalPO.getLogicId());\n            return indexTemplatePhyWithLogic;\n        }\n        indexTemplatePhyWithLogic.setLogicTemplate(ConvertUtil.obj2Obj(logicPO, IndexTemplate.class));\n        return indexTemplatePhyWithLogic;\n    }\n\n    @Override\n    public Map<Integer, Integer> getAllLogicTemplatesPhysicalCount() {\n        Map<Integer, Integer> map = new HashMap<>();\n        List<IndexTemplatePhyPO> list = indexTemplatePhyDAO.countListByLogicId();\n        if (CollectionUtils.isNotEmpty(list)) {\n            map = list.stream().collect(Collectors.toMap(IndexTemplatePhyPO::getLogicId, o -> 1, Integer::sum));\n        }\n        return map;\n    }\n\n    @Override\n    public Result<Void> validateTemplates(List<IndexTemplatePhyDTO> params, OperationEnum operation) {\n        if (AriusObjUtils.isNull(params)) {\n            return Result.buildParamIllegal(\"物理模板信息为空\");\n        }\n\n        Set<String> deployClusterSet = Sets.newTreeSet();\n        for (IndexTemplatePhyDTO param : params) {\n            Result<Void> checkResult = validateTemplate(param, operation);\n            if (checkResult.failed()) {\n                LOGGER.warn(\"class=TemplatePhyManagerImpl||method=validateTemplates||msg={}\",\n                    CHECK_FAIL_MSG + checkResult.getMessage());\n                checkResult\n                    .setMessage(checkResult.getMessage() + \"; 集群:\" + param.getCluster() + \",模板:\" + param.getName());\n                return checkResult;\n            }\n\n            if (deployClusterSet.contains(param.getCluster())) {\n                return Result.buildParamIllegal(\"部署集群重复\");\n            } else {\n                deployClusterSet.add(param.getCluster());\n            }\n\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<Void> validateTemplate(IndexTemplatePhyDTO param, OperationEnum operation) {\n        if (AriusObjUtils.isNull(param)) {\n            return Result.buildParamIllegal(\"物理模板参数为空\");\n        }\n        if (operation == OperationEnum.ADD) {\n            Result<Void> result = handleValidateTemplateAdd(param);\n            if (result.failed()) {\n                return result;\n            }\n        } else if (operation == EDIT) {\n            Result<Void> result = handleValidateTemplateEdit(param);\n            if (result.failed()) {\n                return result;\n            }\n        }\n\n        Result<Void> result = handleValidateTemplate(param);\n        if (result.failed()) {\n            return result;\n        }\n\n        return Result.buildSucc();\n    }\n\n    @Override\n    public Result<List<IndexTemplatePhy>> listByRegionId(Integer regionId) {\n        List<IndexTemplatePhyPO> indexTemplatePhyPOS;\n        try {\n            indexTemplatePhyPOS = indexTemplatePhyDAO.listByRegionId(regionId);\n        } catch (Exception e) {\n            LOGGER.error(\"class=IndexTemplatePhyServiceImpl||method=listAllByRegionId||errMsg={}\", e);\n            return Result.buildFail(String.format(\"根据regionId获取模板列表失败, msg:%s\", e.getMessage()));\n        }\n        return Result.buildSucc(ConvertUtil.list2List(indexTemplatePhyPOS, IndexTemplatePhy.class));\n    }\n\n    /**\n     * @param physicalId\n     * @return\n     */\n    @Override\n    public IndexTemplatePhyWithLogic buildIndexTemplatePhysicalWithLogicByPhysicalId(Long physicalId) {\n        IndexTemplatePhyPO physicalPO = indexTemplatePhyDAO.getNormalAndDeletingById(physicalId);\n        return buildIndexTemplatePhysicalWithLogic(physicalPO);\n    }\n\n    /**\n     * @param cluster\n     * @param name\n     * @param code\n     * @return\n     */\n    @Override\n    public List<IndexTemplatePhyPO> getByClusterAndNameAndStatus(String cluster, String name, int code) {\n        return indexTemplatePhyDAO.getByClusterAndNameAndStatus(cluster, name, code);\n    }\n\n    /**\n     * @param cluster\n     * @param code\n     * @return\n     */\n    @Override\n    public Collection<IndexTemplatePhyPO> getByClusterAndStatus(String cluster, int code) {\n        return indexTemplatePhyDAO.getByClusterAndStatus(cluster, code);\n    }\n\n    /**\n     * @param physicalId\n     * @param code\n     * @return\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public boolean updateStatus(Long physicalId, int code) {\n        return 1 == indexTemplatePhyDAO.updateStatus(physicalId, code);\n\n    }\n\n    /**\n     * @param physicalPO\n     * @return\n     */\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public boolean updateByIndexTemplatePhyPO(IndexTemplatePhyPO physicalPO) {\n        return indexTemplatePhyDAO.update(physicalPO) == 1;\n    }\n    \n    /**\n     * @param logicTemplateId\n     * @return\n     */\n    @Override\n    public List<String> getPhyClusterByLogicTemplateId(Integer logicTemplateId) {\n        return  getTemplateByLogicId(logicTemplateId).stream().map(IndexTemplatePhy::getCluster).distinct().collect(\n                Collectors.toList());\n    }\n    \n    \n    /**\n     * 通过逻辑id更新索引模板的分片号\n     *\n     * @param logicId 逻辑索引ID，即index_template_logic表中索引的ID。\n     * @param shardNum 要更新的分片数\n     */\n    @Override\n    public boolean updateShardNumByLogicId(Integer logicId, Integer shardNum) {\n        return indexTemplatePhyDAO.updateShardNumByLogicId(logicId,shardNum)>0;\n    }\n    \n    /**************************************************** private method ****************************************************/\n    private List<IndexTemplatePhyWithLogic> batchBuildTemplatePhysicalWithLogic(List<IndexTemplatePhyPO> indexTemplatePhyPOS) {\n        if (CollectionUtils.isEmpty(indexTemplatePhyPOS)) {\n            return Lists.newArrayList();\n        }\n\n        List<Integer> logicIds = indexTemplatePhyPOS.stream().map(IndexTemplatePhyPO::getLogicId)\n            .collect(Collectors.toList());\n        List<IndexTemplatePO> indexTemplatePOS = indexTemplateDAO.listByIds(logicIds);\n        Map<Integer, IndexTemplatePO> id2IndexTemplateLogicPOMap = ConvertUtil.list2Map(indexTemplatePOS,\n            IndexTemplatePO::getId);\n\n        List<IndexTemplatePhyWithLogic> physicalWithLogics = Lists.newArrayList();\n        for (IndexTemplatePhyPO indexTemplatePhyPO : indexTemplatePhyPOS) {\n            IndexTemplatePhyWithLogic physicalWithLogic = ConvertUtil.obj2Obj(indexTemplatePhyPO,\n                IndexTemplatePhyWithLogic.class);\n            physicalWithLogic.setLogicTemplate(ConvertUtil\n                .obj2Obj(id2IndexTemplateLogicPOMap.get(indexTemplatePhyPO.getLogicId()), IndexTemplate.class));\n\n            physicalWithLogics.add(physicalWithLogic);\n        }\n\n        return physicalWithLogics;\n    }\n\n    private IndexTemplatePhyWithLogic getNormalAndDeletingTemplateWithLogicById(Long physicalId) {\n        IndexTemplatePhyPO physicalPO = indexTemplatePhyDAO.getNormalAndDeletingById(physicalId);\n        return buildIndexTemplatePhysicalWithLogic(physicalPO);\n    }\n\n    /**\n     * 判定是否是合法的shard number.\n     *\n     * @param shardNum shard 数量\n     * @return boolean\n     */\n    private boolean isValidShardNum(Integer shardNum) {\n        return shardNum != null && shardNum > 0;\n    }\n\n    /**\n     * 更新物理模板名称时，做参数的校验\n     * @param physical 索引物理模板\n     * @return 校验结果\n     */\n    private Result<Void> validParamUpdateTemplateName(IndexTemplatePhy physical) {\n        if (AriusObjUtils.isNull(physical)) {\n            return Result.buildParamIllegal(\"输入的物理模板为空\");\n        }\n        if (AriusObjUtils.isNull(physical.getId())) {\n            return Result.buildParamIllegal(\"需要修改的物理模板的Id为空\");\n        }\n        if (AriusObjUtils.isNull(physical.getName())) {\n            return Result.buildParamIllegal(\"需要修改的物理模板的名称为空\");\n        }\n\n        IndexTemplatePhyPO oldIndexTemplatePhy = indexTemplatePhyDAO.getById(physical.getId());\n        if (AriusObjUtils.isNull(oldIndexTemplatePhy)) {\n            return Result.buildParamIllegal(\"需要修改的物理模板的id对应的原数据不存在\");\n        }\n\n        return Result.buildSucc();\n    }\n\n    private Result<Void> updateShardNumTemplatePhy(IndexTemplateDTO param, IndexTemplatePhyPO updateParam,\n                                                   IndexTemplatePhyPO physicalPO) throws ESOperateException {\n        if (isValidShardNum(param.getShardNum())\n            && AriusObjUtils.isChanged(param.getShardNum(), physicalPO.getShard())) {\n            updateParam.setId(physicalPO.getId());\n            updateParam.setShard(param.getShardNum());\n            boolean succeed = 1 == indexTemplatePhyDAO.update(updateParam);\n            if (succeed) {\n                LOGGER.info(\n                    \"class=TemplatePhyServiceImpl||method=updateShardNumTemplatePhy||editTemplateFromLogic succeed||physicalId={}||preShardNum={}||currentShardNum={}\",\n                    physicalPO.getId(), physicalPO.getShard(), param.getShardNum());\n\n                esTemplateService.syncUpdateShard(physicalPO.getCluster(), physicalPO.getName(), param.getShardNum(),\n                    physicalPO.getShardRouting(), 0);\n            } else {\n                LOGGER.warn(\"class=TemplatePhyServiceImpl||method=updateShardNumTemplatePhy||msg=\", MSG,\n                    physicalPO.getId(), param.getExpression());\n                return Result.build(false);\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> updateExpressionTemplatePhysical(IndexTemplateDTO param, IndexTemplatePhyPO updateParam,\n                                                          IndexTemplatePhyPO physicalPO) throws ESOperateException {\n        if (AriusObjUtils.isChanged(param.getExpression(), physicalPO.getExpression())) {\n            updateParam.setId(physicalPO.getId());\n            updateParam.setExpression(param.getExpression());\n            boolean succeed = (1 == indexTemplatePhyDAO.update(updateParam));\n            if (succeed) {\n                esTemplateService.syncUpdateExpression(physicalPO.getCluster(), physicalPO.getName(),\n                    param.getExpression(), 0);\n            } else {\n                LOGGER.warn(\"class=TemplatePhyServiceImpl||method=updateExpressionTemplatePhysical||msg=\", MSG,\n                    physicalPO.getId(), param.getExpression());\n                return Result.build(false);\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleValidateTemplate(IndexTemplatePhyDTO param) {\n        if (param.getCluster() != null && !clusterPhyService.isClusterExists(param.getCluster())) {\n            return Result.buildParamIllegal(\"集群不存在\");\n        }\n        if (param.getShard() != null && param.getShard() < 1) {\n            return Result.buildParamIllegal(\"shard个数非法\");\n        }\n        if (param.getRole() != null\n            && TemplateDeployRoleEnum.UNKNOWN.equals(TemplateDeployRoleEnum.valueOf(param.getRole()))) {\n            return Result.buildParamIllegal(\"模板角色非法\");\n        }\n        if (param.getLogicId() != null && !Objects.equals(param.getLogicId(), NOT_CHECK)) {\n            IndexTemplate logic = indexTemplateService.getLogicTemplateById(param.getLogicId());\n            if (logic == null) {\n                return Result.buildNotExist(\"逻辑模板不存在\");\n            }\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleValidateTemplateEdit(IndexTemplatePhyDTO param) {\n        if (AriusObjUtils.isNull(param.getId())) {\n            return Result.buildParamIllegal(TEMPLATE_PHYSICAL_ID_IS_NULL);\n        }\n        IndexTemplatePhy indexTemplatePhy = getTemplateById(param.getId());\n        if (indexTemplatePhy == null) {\n            return Result.buildNotExist(TEMPLATE_PHYSICAL_NOT_EXISTS);\n        }\n        return Result.buildSucc();\n    }\n\n    private Result<Void> handleValidateTemplateAdd(IndexTemplatePhyDTO param) {\n        if (AriusObjUtils.isNull(param.getLogicId())) {\n            return Result.buildParamIllegal(\"逻辑模板id为空\");\n        }\n        if (AriusObjUtils.isNull(param.getCluster())) {\n            return Result.buildParamIllegal(\"集群为空\");\n        }\n\n        if (AriusObjUtils.isNull(param.getShard())) {\n            return Result.buildParamIllegal(\"shard为空\");\n        }\n        if (AriusObjUtils.isNull(param.getRole())) {\n            return Result.buildParamIllegal(\"模板角色为空\");\n        }\n\n        IndexTemplatePhy indexTemplatePhy = getTemplateByClusterAndName(param.getCluster(), param.getName());\n        if (indexTemplatePhy != null) {\n            return Result.buildDuplicate(\"物理模板已经存在\");\n        }\n        return Result.buildSucc();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/template/pipeline/ESPipelineService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.template.pipeline;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ESPipelineProcessor;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.ESPipeline;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\n\n/**\n * espipelineservice\n *\n * @author shizeying\n * @date 2022/08/12\n */\npublic interface ESPipelineService {\n    /**\n     * 保存\n     *\n     * @param esPipeline ES管道\n     * @param methodName 方法名称\n     * @param tryTimes   试次\n     * @return boolean\n     * @throws ESOperateException esoperateException\n     */\n    boolean save(String methodName,ESPipeline esPipeline,int tryTimes) throws ESOperateException;\n    \n    /**\n     * 获取\n     *\n     * @param cluster 集群\n     * @param name    名字\n     * @return {@link ESPipelineProcessor}\n     */\n    ESPipelineProcessor get(String cluster, String name);\n    \n    /**\n     * 删除\n     *\n     * @param cluster    集群\n     * @param name       名字\n     * @param methodName 方法名称\n     * @param tryTimes   试次\n     * @return boolean\n     * @throws ESOperateException esoperateException\n     */\n    boolean delete(String cluster, String name,String methodName,int tryTimes) throws ESOperateException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/template/pipeline/ESPipelineServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.template.pipeline;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ESPipelineProcessor;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.ESPipeline;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESPipelineDAO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * espipelineservice实现\n *\n * @author shizeying\n * @date 2022/08/12\n */\n@Service\npublic class ESPipelineServiceImpl implements ESPipelineService {\n    @Autowired\n    private ESPipelineDAO esPipelineDAO;\n    \n  \n    @Override\n    public boolean save(String methodName, ESPipeline esPipeline, int tryTimes) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(methodName, tryTimes,\n                () -> esPipelineDAO.save(esPipeline.getCluster(), esPipeline.getPipelineId(), esPipeline.getDateField(),\n                        esPipeline.getDateFieldFormat(), esPipeline.getDateFormat(), esPipeline.getExpireDay(),\n                        esPipeline.getRateLimit(), esPipeline.getVersion(), esPipeline.getIdField(),\n                        esPipeline.getRoutingField()));\n    }\n    \n    /**\n     * 获取\n     *\n     * @param cluster 集群\n     * @param name    名字\n     * @return {@link ESPipelineProcessor}\n     */\n    @Override\n    public ESPipelineProcessor get(String cluster, String name) {\n        return esPipelineDAO.get(cluster,name);\n    }\n    \n    /**\n     * 删除\n     *\n     * @param cluster    集群\n     * @param name       名字\n     * @param methodName 方法名称\n     * @param tryTimes   试次\n     * @return boolean\n     * @throws ESOperateException esoperateException\n     */\n    @Override\n    public boolean delete(String cluster, String name, String methodName, int tryTimes) throws ESOperateException {\n        return ESOpTimeoutRetry.esRetryExecute(methodName, tryTimes,\n                () -> esPipelineDAO.delete(cluster, name));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/workorder/WorkOrderService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.workorder;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.WorkOrderVO;\nimport java.util.List;\n\n/**\n * 工作订单service\n *\n * @author shizeying\n * @date 2022/08/12\n */\npublic interface WorkOrderService {\n    /**\n     * 获取通过id\n     *\n     * @param orderId 订单id\n     * @return {@link WorkOrderPO}\n     */\n    WorkOrderPO getById(Long orderId);\n    \n    /**\n     * 新增\n     *\n     * @param orderPO 订单po\n     * @return int\n     */\n    int insert(WorkOrderPO orderPO);\n    \n    /**\n     * 更新\n     *\n     * @param orderPO 订单po\n     * @return int\n     */\n    int update(WorkOrderPO orderPO);\n    \n    /**\n     * 列表\n     *\n     * @return {@link List}<{@link WorkOrderPO}>\n     */\n    List<WorkOrderPO> list();\n    \n    /**\n     * 更新订单状态通过id\n     *\n     * @param id   id\n     * @param code code\n     * @return boolean\n     */\n    boolean updateOrderStatusById(Long id, Integer code);\n    \n    /**\n     * 由申请人和状态列表\n     *\n     * @param applicant 申请人\n     * @param status    状态\n     * @return {@link List}<{@link WorkOrderVO}>\n     */\n    List<WorkOrderVO> listByApplicantAndStatus(String applicant, Integer status);\n    \n    /**\n     * 通过状态和项目id列表\n     *\n     * @param status    状态\n     * @param projectId 项目id\n     * @return {@link List}<{@link WorkOrderVO}>\n     */\n    List<WorkOrderVO> listByStatusAndProjectId(Integer status, Integer projectId);\n    \n    /**\n     * 由审批人列表和地位\n     *\n     * @param approver 审批人\n     * @param status   status\n     * @return {@link List}<{@link WorkOrderPO}>\n     */\n    List<WorkOrderPO> listByApproverAndStatus(String approver, Integer status);\n    \n    /**\n     * 列表状态\n     *\n     * @param status 代码\n     * @return {@link List}<{@link WorkOrderPO}>\n     */\n    List<WorkOrderPO> listByStatus(Integer status);\n}"
  },
  {
    "path": "arius-admin/arius-admin-core/src/main/java/com/didichuxing/datachannel/arius/admin/core/service/workorder/WorkOrderServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.workorder;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.WorkOrderVO;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.workorder.WorkOrderDAO;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * 工作订单service实现\n *\n * @author shizeying\n * @date 2022/08/12\n */\n@Service\npublic class WorkOrderServiceImpl implements WorkOrderService {\n    @Autowired\n    private WorkOrderDAO orderDao;\n    \n    /**\n     * 获取通过id\n     *\n     * @param orderId 订单id\n     * @return {@link WorkOrderPO}\n     */\n    @Override\n    public WorkOrderPO getById(Long orderId) {\n        return orderDao.getById(orderId);\n    }\n    \n    /**\n     * 新增\n     *\n     * @param orderPO 订单po\n     * @return int\n     */\n    @Override\n    public int insert(WorkOrderPO orderPO) {\n        return orderDao.insert(orderPO);\n    }\n    \n    /**\n     * 更新\n     *\n     * @param orderPO 订单po\n     * @return int\n     */\n    @Override\n    public int update(WorkOrderPO orderPO) {\n        return orderDao.update(orderPO);\n    }\n    \n    /**\n     * 列表\n     *\n     * @return {@link List}<{@link WorkOrderPO}>\n     */\n    @Override\n    public List<WorkOrderPO> list() {\n       return orderDao.list();\n    }\n    \n    /**\n     * 更新订单状态通过id\n     *\n     * @param id   id\n     * @param code code\n     * @return boolean\n     */\n    @Override\n    public boolean updateOrderStatusById(Long id, Integer code) {\n        return orderDao.updateOrderStatusById(id, code)>0;\n    }\n    \n    /**\n     * 由申请人和状态列表\n     *\n     * @param applicant 申请人\n     * @param status    状态\n     * @return {@link List}<{@link WorkOrderVO}>\n     */\n    @Override\n    public List<WorkOrderVO> listByApplicantAndStatus(String applicant, Integer status) {\n        return ConvertUtil.list2List(orderDao.listByApplicantAndStatus(applicant, status),\n                WorkOrderVO.class);\n    }\n    \n    /**\n     * 通过状态和项目id列表\n     *\n     * @param status    状态\n     * @param projectId 项目id\n     * @return {@link List}<{@link WorkOrderVO}>\n     */\n    @Override\n    public List<WorkOrderVO> listByStatusAndProjectId(Integer status, Integer projectId) {\n        return ConvertUtil.list2List(\n                orderDao.listByStatusAndProjectId(status, projectId), WorkOrderVO.class);\n    }\n    \n    \n    @Override\n    public List<WorkOrderPO> listByApproverAndStatus(String approver, Integer status) {\n        return orderDao.listByApproverAndStatus(approver,status);\n    }\n    \n    /**\n     * 列表状态\n     *\n     * @param status 代码\n     * @return {@link List}<{@link WorkOrderPO}>\n     */\n    @Override\n    public List<WorkOrderPO> listByStatus(Integer status) {\n       return orderDao.listByStatus(status);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-extend/arius-admin-rest-v2/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <artifactId>arius-admin</artifactId>\n         <version>${revision}${sha1}${changelist}</version>\n        <relativePath>../../pom.xml</relativePath>\n    </parent>\n\n    <artifactId>arius-admin-rest-v2</artifactId>\n    <dependencies>\n\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-core</artifactId>\n            <exclusions>\n                <exclusion>\n                    <artifactId>mybatis</artifactId>\n                    <groupId>org.mybatis</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-common</artifactId>\n            <exclusions>\n                <exclusion>\n                    <artifactId>mybatis</artifactId>\n                    <groupId>org.mybatis</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-task</artifactId>\n            <exclusions>\n                <exclusion>\n                    <artifactId>mybatis-spring</artifactId>\n                    <groupId>org.mybatis</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-biz</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-remote</artifactId>\n        </dependency>\n\n\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-log</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>commons-io</groupId>\n            <artifactId>commons-io</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.annotation</groupId>\n                    <artifactId>javax.annotation-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <artifactId>log4j-to-slf4j</artifactId>\n                    <groupId>org.apache.logging.log4j</groupId>\n                </exclusion>\n                <exclusion>\n                    <groupId>>ch.qos.logback</groupId>\n                    <artifactId>ch.qos.logback:logback-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.yaml</groupId>\n            <artifactId>snakeyaml</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-webmvc</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>javax.servlet-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-web</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.hibernate.validator</groupId>\n            <artifactId>hibernate-validator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.tomcat.embed</groupId>\n            <artifactId>tomcat-embed-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.fasterxml.jackson.datatype</groupId>\n            <artifactId>jackson-datatype-jsr310</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-autoconfigure</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>net.minidev</groupId>\n            <artifactId>json-smart</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-aop</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger2</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>net.bytebuddy</groupId>\n                    <artifactId>byte-buddy</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger-ui</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>druid-spring-boot-starter</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.faces</groupId>\n                    <artifactId>jsf-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.resource</groupId>\n                    <artifactId>connector-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>servlet-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.mail</groupId>\n                    <artifactId>mail</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>javax.servlet-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.persistence</groupId>\n                    <artifactId>persistence-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>mysql</groupId>\n                    <artifactId>mysql-connector-java</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>jsp-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>jstl</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.apache.logging.log4j</groupId>\n                    <artifactId>log4j-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.h2database</groupId>\n                    <artifactId>h2</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.mchange</groupId>\n                    <artifactId>c3p0</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mortbay.jetty</groupId>\n            <artifactId>jetty</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>fastjson</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-utils</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>osgi-resource-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.openjdk.jol</groupId>\n                    <artifactId>jol-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-utils</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jersey.bundles.repackaged</groupId>\n                    <artifactId>jersey-guava</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jersey.core</groupId>\n                    <artifactId>jersey-common</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.postgresql</groupId>\n            <artifactId>postgresql</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>javax.servlet-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.hibernate</groupId>\n            <artifactId>hibernate-validator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.hibernate</groupId>\n            <artifactId>hibernate-core</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.el</groupId>\n                    <artifactId>javax.el-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.interceptor</groupId>\n                    <artifactId>javax.interceptor-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.activation</groupId>\n                    <artifactId>javax.activation-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.jboss.spec.javax.transaction</groupId>\n                    <artifactId>jboss-transaction-api_1.2_spec</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jaxb</groupId>\n                    <artifactId>jaxb-runtime</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jaxb</groupId>\n                    <artifactId>txw2</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>net.bytebuddy</groupId>\n                    <artifactId>byte-buddy</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.zookeeper</groupId>\n            <artifactId>zookeeper</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>io.netty</groupId>\n            <artifactId>netty-all</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.eclipse.jetty</groupId>\n            <artifactId>jetty-server</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.eclipse.jetty</groupId>\n            <artifactId>jetty-io</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.thrift</groupId>\n            <artifactId>libthrift</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.annotation</groupId>\n                    <artifactId>javax.annotation-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.mina</groupId>\n            <artifactId>mina-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.httpcomponents</groupId>\n            <artifactId>httpclient</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.cxf</groupId>\n            <artifactId>cxf-rt-bindings-soap</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.sun.xml.bind</groupId>\n                    <artifactId>jaxb-impl</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.sun.xml.bind</groupId>\n                    <artifactId>jaxb-xjc</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.cxf</groupId>\n            <artifactId>cxf-rt-transports-http</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.glassfish.jaxb</groupId>\n                    <artifactId>jaxb-runtime</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jaxb</groupId>\n                    <artifactId>txw2</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.cxf</groupId>\n            <artifactId>cxf-api</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.sun.xml.bind</groupId>\n                    <artifactId>jaxb-impl</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.xml.stream</groupId>\n                    <artifactId>stax-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.calcite</groupId>\n            <artifactId>calcite-core</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.guava</groupId>\n            <artifactId>guava</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.ant</groupId>\n            <artifactId>ant</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-dbcp2</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>commons-codec</groupId>\n            <artifactId>commons-codec</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.thoughtworks.xstream</groupId>\n            <artifactId>xstream</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>xmlpull</groupId>\n                    <artifactId>xmlpull</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.protobuf</groupId>\n            <artifactId>protobuf-java</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-params</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-api</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-log4j2</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.apache.logging.log4j</groupId>\n                    <artifactId>log4j-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.lmax</groupId>\n            <artifactId>disruptor</artifactId>\n        </dependency>\n    </dependencies>\n\n\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <artifactId>arius-admin</artifactId>\n        <version>1.0.1-SNAPSHOT</version>\n        <relativePath>../..</relativePath>\n    </parent>\n\n    <artifactId>fast-index</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-lang3</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-collections4</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.guava</groupId>\n            <artifactId>guava</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.annotation</groupId>\n                    <artifactId>javax.annotation-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-aop</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.annotation</groupId>\n                    <artifactId>javax.annotation-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.apache.tomcat.embed</groupId>\n                    <artifactId>tomcat-embed-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish</groupId>\n                    <artifactId>javax.el</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>javax.servlet-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n      \n\n        <dependency>\n            <groupId>org.yaml</groupId>\n            <artifactId>snakeyaml</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-webmvc</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>javax.servlet-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.fasterxml.jackson.datatype</groupId>\n            <artifactId>jackson-datatype-jsr310</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>commons-codec</groupId>\n            <artifactId>commons-codec</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-web</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n\n        </dependency>\n\n        <dependency>\n            <groupId>net.minidev</groupId>\n            <artifactId>json-smart</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-core</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.apache.logging.log4j</groupId>\n                    <artifactId>log4j-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-common</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-persistence</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.apache.logging.log4j</groupId>\n                    <artifactId>log4j-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n    </dependencies>\n\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/FastIndexLoadDataParam.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class FastIndexLoadDataParam {\n    private int maxCocurrent = 20 ;\n\n    private int nodeMaxCocurrent = 10;\n\n    private int waitTimeout = 20*60*1000;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/entity/IndexFastIndexInfo.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.entity;\n\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.elasticsearch.client.response.setting.index.IndexConfig;\nimport lombok.Data;\n\n@Data\npublic class IndexFastIndexInfo {\n    private IndexConfig indexConfig;\n    private long shardNum;\n    private String transformType;\n    private long expanfactor;\n    private boolean smallData;\n    private String intFilterKeys;\n\n    private boolean longToStr = false;\n    private boolean longNullToZero = false;\n    private boolean removeBracket = false;\n    private boolean isPassengerPre = false;\n    private boolean null2Null = false;\n    private String shardField = null;\n    private String strToArray = null;\n\n    private SpatialInfo spatialInfo = null;\n    private boolean haveSpatialSetting = false;\n    private String esVersion = null;\n    private boolean printWriteLog = true;\n\n    public JSONObject toJson() {\n        JSONObject obj = new JSONObject();\n        obj.put(\"shardNum\", shardNum);\n        if(indexConfig!=null) {\n            obj.put(\"indexConfig\", indexConfig.toJson());\n        }\n        obj.put(\"transformType\", transformType);\n        obj.put(\"expanfactor\", expanfactor);\n        obj.put(\"smallData\", smallData);\n        obj.put(\"intFilterKeys\", intFilterKeys);\n        obj.put(\"longToStr\", longToStr);\n        obj.put(\"longNullToZero\", longNullToZero);\n        obj.put(\"removeBracket\", removeBracket);\n        obj.put(\"isPassengerPre\", isPassengerPre);\n        obj.put(\"null2Null\", null2Null);\n        obj.put(\"shardField\", shardField);\n        obj.put(\"strToArray\", strToArray);\n        obj.put(\"spatialInfo\", JSON.toJSON(spatialInfo));\n        obj.put(\"haveSpatialSetting\", haveSpatialSetting);\n        obj.put(\"esVersion\", esVersion);\n        obj.put(\"printWriteLog\", printWriteLog);\n        return obj;\n    }\n\n    @Override\n    public String toString( ){\n        return toJson().toJSONString();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/entity/IndexShardsVersion.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.entity;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport lombok.Data;\n\nimport java.util.List;\n\n@Data\npublic class IndexShardsVersion {\n    private static final String INDEX_SHARDS_VERSION = \"shardVersions\";\n    private List<ShardVersion> shardVersions;\n\n    public IndexShardsVersion(List<ShardVersion> shardVersions) {\n        this.shardVersions = shardVersions;\n    }\n\n    public JSONObject toJson() {\n        JSONObject jsonObject = new JSONObject();\n        JSONArray jsonArray = new JSONArray();\n        jsonArray.addAll(shardVersions);\n\n        jsonObject.put(INDEX_SHARDS_VERSION, jsonArray);\n        return jsonObject;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/entity/NodeVersion.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.entity;\n\nimport lombok.Data;\n\n@Data\npublic class NodeVersion {\n    private String name;\n    private String version;\n}"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/entity/ShardDisk.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.entity;\n\nimport lombok.Data;\n\n@Data\npublic class ShardDisk {\n    private Integer shard;\n    private String prirep;\n    private String state;\n    private String pd;\n}"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/entity/ShardNode.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.entity;\n\nimport lombok.Data;\n\n@Data\npublic class ShardNode {\n    private Integer shard;\n    private String prirep;\n    private String state;\n    private String node;\n}"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/entity/ShardVersion.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.entity;\n\nimport lombok.Data;\n\nimport java.util.Objects;\n\n@Data\npublic class ShardVersion {\n    private Integer shard;\n    private String version;\n\n    public ShardVersion(Integer shard, String version) {\n        this.shard = shard;\n        this.version = version;\n    }\n\n    public ShardVersion smaller(ShardVersion shardVersion) {\n        Integer v1 = Integer.parseInt(version.replace(\".\", \"\"));\n        Integer v2 = Integer.parseInt(shardVersion.version.replace(\".\", \"\"));\n        return v1 > v2 ? shardVersion : this;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        ShardVersion that = (ShardVersion) o;\n        return Objects.equals(shard, that.shard) && Objects.equals(version, that.version);\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(shard, version);\n    }\n\n    @Override\n    public String toString() {\n        return \"[\" + shard + \":\" + version + \"]\";\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/entity/SpatialInfo.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.entity;\n\nimport lombok.Data;\n\n@Data\npublic class SpatialInfo {\n    private String s2Data;\n    private String geoName;\n    private String cityIdName;\n    private Integer maxCell = 10;\n    private Integer maxLevel = 12;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/po/FastIndexLoadDataPO.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.po;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class FastIndexLoadDataPO extends BaseESPO {\n    private String clusterName;\n    private String templateName;\n    private String indexName;\n    private String indexUUID;\n    private long shardNum;\n    private String hostName;\n    private int port;\n\n    private String srcTag;\n    private String hdfsShards;\n    private String hdfsSrcDir;\n    private String workDir;\n    private String hdfsUser;\n    private String hdfsPassword;\n\n    private String esDstDir;\n    private String esInnerPrimerKey = \"_uid\";\n\n    private long zeusTaskId;\n    private boolean start;\n    private long startTime;\n\n\n    private boolean isFinish;\n    private long finishTime;\n\n    private boolean highES = false;\n\n    // 重试次数\n    private long runCount = 0;\n\n\n    @JSONField(serialize = false)\n    public String getOpKey() {\n        if (srcTag == null || srcTag.trim().length() == 0) {\n            return clusterName + \"_\" + indexName;\n        } else {\n            return srcTag.trim() + \"_\" + clusterName + \"_\" + indexName;\n        }\n    }\n\n    @Override\n    public String getKey() {\n        if (srcTag == null || srcTag.trim().length() == 0) {\n            return clusterName + \"_\" + indexName + \"_\" + shardNum;\n        } else {\n            return srcTag.trim() + \"_\" + clusterName + \"_\" + indexName + \"_\" + shardNum;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/po/FastIndexMappingPO.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.po;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.io.UnsupportedEncodingException;\nimport java.util.Base64;\n\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class FastIndexMappingPO extends BaseESPO {\n\n    private String srcTag;\n\n    private String clusterName;\n\n    private String indexName;\n\n    private long shardNum;\n\n    private String mappingMd5;\n\n    private long addTime;\n\n\n    @JSONField(serialize = false)\n    public void setMapping(String mapping) throws UnsupportedEncodingException {\n        this.mappingMd5 = Base64.getEncoder().encodeToString(mapping.toString().getBytes(\"UTF-8\"));;\n    }\n\n    @JSONField(serialize = false)\n    public String getMapping() throws UnsupportedEncodingException {\n        return new String(Base64.getDecoder().decode(mappingMd5), \"UTF-8\");\n    }\n\n    @Override\n    public String getKey() {\n        if(srcTag==null || srcTag.trim().length()==0) {\n            return clusterName + \"_\" + indexName + \"_\" + shardNum;\n        } else {\n            return srcTag.trim() + \"_\" + clusterName + \"_\" + indexName + \"_\" + shardNum;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/po/FastIndexOpIndexPO.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.po;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class FastIndexOpIndexPO extends BaseESPO {\n    private String srcTag;\n\n    private String clusterName;\n    private String templateName;\n    private String indexName;\n\n    private boolean isOpen;\n    protected long openTime;\n\n    private boolean isFinish;\n    private long finishTime;\n\n    private String exceptionStr;\n\n    @Override\n    public String getKey() {\n        if(srcTag==null || srcTag.trim().length()==0) {\n            return clusterName + \"_\" + indexName;\n        } else {\n            return srcTag.trim() + \"_\" + clusterName + \"_\" + indexName;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/po/FastIndexTaskMetricPO.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.po;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class FastIndexTaskMetricPO extends BaseESPO {\n\n    private String srcTag;\n\n    private String clusterName;\n\n    private String indexName;\n\n    private long shardNum;\n\n    private long addTime;\n\n    private JSONObject metrics;\n\n    @Override\n    public String getKey() {\n        if(srcTag==null || srcTag.trim().length()==0) {\n            return clusterName + \"_\" + indexName + \"_\" + shardNum;\n        } else {\n            return srcTag.trim() + \"_\" + clusterName + \"_\" + indexName + \"_\" + shardNum;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/bean/po/FastIndexTemplateConfigPO.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.bean.po;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class FastIndexTemplateConfigPO extends BaseESPO {\n    private String name;\n\n    /**\n     * reducer数目系数， reducerNum=shardNum*expandfactor\n     */\n    private int expanfactor = -1;\n\n    /**\n     * 最近replicaDay天索引，配置多副本，标签业务\n     */\n    private int replicaDay = -1;\n\n    /**\n     * 数据转化配置\n     */\n    private String transformType = \"normal\";\n\n    /**\n     * 废弃\n     */\n    private boolean smallData = false;\n\n    /**\n     * 主键中类型是int的字段名\n     */\n    private String intFilterKeys = null;\n\n    /**\n     * 数字类型转化成string写入ES\n     */\n    private boolean longToStr = false;\n\n    /**\n     * 数据类型，如果hive数据为null，则写入数字0\n     */\n    private boolean longNullToZero = false;\n\n    /**\n     * 去除字符串2遍的中括号\n     */\n    private boolean removeBracket = false;\n\n    /**\n     * 是否调用标签系统的预发环境\n     */\n    private boolean isPassengerPre = false;\n\n    /**\n     * hive为null的之后，写入es的数据也是null\n     */\n    private boolean null2Null = false;\n\n    /**\n     * hive中该字段的内容指定当前数据属于哪个es的shard\n     */\n    private String shardField = null;\n\n    /**\n     * 将string解析成json的array写入es\n     */\n    private String strToArray = null;\n\n    /**\n     * 是否需要写入source，如果为false，则会再导入过程中修改索引的mapping配置\n     */\n    private boolean needSource = true;\n\n    /**\n     * 空间索引的geo字段名，配置则开始空间索引功能\n     */\n    private String spatialGeo = null;\n\n    /**\n     * 空间索引的cityId字段名\n     */\n    private String spatialCityId = null;\n\n    /**\n     * 数据加载过程中，是否停止索引写入\n     */\n    private boolean blockWriter = false;\n\n    /**\n     * 当前索引需要使用哪个版本的ES安装包导入数据\n     */\n    private String esVersion = null;\n\n    /**\n     * 写入过程中是否需要答应日志\n     */\n    private boolean printWriteLog = true;\n\n    /**\n     * 是否开始DCDR功能\n     */\n    private boolean enableDCDR = false;\n\n    /**\n     * 写es批次\n     */\n    private Integer batchSize = -1;\n\n    @Override\n    public String getKey() {\n        return name;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/controller/FastIndexController.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.controller;\n\nimport io.swagger.annotations.Api;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController()\n@RequestMapping({\"/ams/api/v3/fastindex\"})\n@Api(description = \"FastIndex接口(REST)\")\npublic class FastIndexController {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/dao/FastIndexLoadDataESDAO.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.dao;\n\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class FastIndexLoadDataESDAO extends BaseESDAO {\n\n    /**\n     * 查询模板聚合数据的索引名称\n     */\n    private String indexName;\n\n    /**\n     * type名称，主键id是topic_partition_offset\n     */\n    private String typeName = \"type\";\n\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/dao/FastIndexMappingESDAO.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.dao;\n\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class FastIndexMappingESDAO extends BaseESDAO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/dao/FastIndexOpIndexESDAO.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.dao;\n\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class FastIndexOpIndexESDAO extends BaseESDAO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/dao/FastIndexTaskMetricESDAO.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.dao;\n\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class FastIndexTaskMetricESDAO extends BaseESDAO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/dao/FastIndexTemplateConfigESDAO.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.dao;\n\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class FastIndexTemplateConfigESDAO extends BaseESDAO {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/job/FastIndexCleanMetaDataTask.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.job;\n\npublic class FastIndexCleanMetaDataTask {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/job/FastIndexLoadDataTask.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.job;\n\npublic class FastIndexLoadDataTask {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/job/FastIndexOpIndexTask.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.job;\n\npublic class FastIndexOpIndexTask {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/limit/CocurrentLimiter.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.limit;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class CocurrentLimiter {\n    private int allCocurrent = 0;\n    private Map<String, Integer> nodeCocurrent = new HashMap<>();\n\n    private int maxCocurrent;\n    private int nodeMaxCocurrent;\n\n\n    public CocurrentLimiter(int maxCocurrent, int nodeMaxCocurrent) {\n        this.maxCocurrent = maxCocurrent;\n        this.nodeMaxCocurrent = nodeMaxCocurrent;\n    }\n\n\n    public void add(String hostName) {\n        allCocurrent++;\n        if(!nodeCocurrent.containsKey(hostName)) {\n            nodeCocurrent.put(hostName, 0);\n        }\n\n        int old = nodeCocurrent.get(hostName);\n        nodeCocurrent.put(hostName, old+1);\n    }\n\n\n    public boolean tryOne(String hostName) {\n        if(allCocurrent>=maxCocurrent) {\n            return false;\n        }\n\n        if(nodeCocurrent.containsKey(hostName) &&\n                nodeCocurrent.get(hostName)>=nodeMaxCocurrent) {\n            return false;\n        }\n\n        return true;\n    }\n\n    public void clear() {\n        allCocurrent=0;\n        nodeCocurrent.clear();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/limit/ShardLimiter.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.limit;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class ShardLimiter {\n    private Map<String, Set<Long>> currShards = new HashMap<>();\n\n\n    public void add(String index, Long shard) {\n        if(!currShards.containsKey(index)) {\n            currShards.put(index, new HashSet<>());\n        }\n\n        currShards.get(index).add(shard);\n    }\n\n    public boolean tryOne(String index, Long shard) {\n        if(currShards.containsKey(index) && currShards.get(index).contains(shard)) {\n            return false;\n        }\n        return true;\n    }\n\n    public void clear() {\n        currShards.clear();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-extend/fast-index/src/main/java/com/didichuxing/arius/admin/extend/fastindex/service/FastIndexService.java",
    "content": "package com.didichuxing.arius.admin.extend.fastindex.service;\n\nimport com.didichuxing.arius.admin.extend.fastindex.dao.*;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpClient;\nimport com.didichuxing.tunnel.util.log.ILog;\nimport com.didichuxing.tunnel.util.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class FastIndexService {\n    private static final ILog LOGGER = LogFactory.getLog(FastIndexService.class);\n\n    public static final String LUCENE_VERSION_840 = \"8.4.0\";\n    public static final String LUCENE_VERSION_760 = \"7.6.0\";\n    public static final String ES_VERSION_760 = \"7.6.0\";\n    public static final String ES_VERSION_670 = \"6.7.0\";\n    public static final String ES_VERSION_661 = \"6.6.1\";\n\n    @Autowired\n    private FastIndexLoadDataESDAO fastIndexLoadDataESDao;\n\n    @Autowired\n    private FastIndexMappingESDAO fastIndexMappingESDao;\n\n    @Autowired\n    private FastIndexOpIndexESDAO fastIndexOpIndexESDao;\n\n    @Autowired\n    private FastIndexTaskMetricESDAO fastIndexTaskMetricESDao;\n\n    @Autowired\n    private FastIndexTemplateConfigESDAO fastIndexTemplateConfigESDao;\n\n    @Autowired\n    private ESOpClient                 esOpClient;\n\n    private static final Long DAY_TIME = 24 * 60 * 60 * 1000L;\n\n    private static final int EXPANFACTOR = 20;\n\n    private static final String ES_PATH_FORMAT      = \"/data1/es/%s/nodes/0/indices/%s/%d\";\n    private static final String ES_PATH_FORMAT_661  = \"/data1/es/nodes/0/indices/%s/%d\";\n\n    private static final String WORK_DIR_FORMAT = \"/data1/es/fastIndex/%s_shard%d\";\n\n    private static final String SOURCE_STR  = \"_source\";\n\n    private static final String MSG         = \"msg\";\n    private static final String SUCCESS     = \"success\";\n    private static final String SELF_IP     = \"selfIp\";\n    private static final String DEVICE_NAME = \"deviceName\";\n\n    private static final long   MAX_COUNT   = 90; // 90分钟\n\n    private static final String CMDB_URL = \"http://cmdb.sys.xiaojukeji.com:8000/cmdb/cmdb/devices/getMachinesByIps\";\n    private static final String STAR_URL = \"http://cmdb.intra.xiaojukeji.com/cmdbRead/cmdb/devices/getDevicesByUsername?username=isThread&searchType=IP&searchValue=\";\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/README.md",
    "content": "集成测试说明：\n1. 到 arius-admin-rest 下的 application.yml 确保以下配置信息正确：\n   1. integrate.test.admin.ip\n   2. integrate.test.admin.port\n   3. integrate.test.es.ip\n   4. integrate.test.es.port\n   5. integrate.test.appid\n   6. integrate.test.operator\n2. 找到需要测试的接口类 xxxController，到 com.didichuxing.datachannel.arius.admin.method 下创建接口对应的 xxxMethod；\n3. 创建 xxxTest 类，如果该接口测试需要用到物理集群，则该 xxxTest 继承 BasePhyClusterInfoTest，需要用到逻辑集群，则该 xxxTest 继承 BaseLogicClusterInfoTest，其他的参考现有的实现；\n4. 一些 Dto 相关的类信息，初始化的时候可以选择在 CustomDataSource 类中进行初始化；\n5. 可以参考已经编写好的用例，再进行编写集成测试代码。"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>arius-admin</artifactId>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <version>${revision}${sha1}${changelist}</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>arius-admin-integration-test</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-api</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-params</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>fastjson</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.annotation</groupId>\n                    <artifactId>javax.annotation-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2.external</groupId>\n                    <artifactId>javax.inject</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-utils</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>osgi-resource-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.openjdk.jol</groupId>\n                    <artifactId>jol-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-utils</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>osgi-resource-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jersey.bundles.repackaged</groupId>\n                    <artifactId>jersey-guava</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jersey.core</groupId>\n                    <artifactId>jersey-common</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.httpcomponents</groupId>\n            <artifactId>httpclient</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-simple</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.squareup.okhttp3</groupId>\n            <artifactId>okhttp</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>commons-codec</groupId>\n            <artifactId>commons-codec</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-common</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.springframework.boot</groupId>\n                    <artifactId>spring-boot-starter-web</artifactId>\n                </exclusion>\n                <exclusion>\n                    <artifactId>log4j-to-slf4j</artifactId>\n                    <groupId>org.apache.logging.log4j</groupId>\n                </exclusion>\n                <exclusion>\n                    <groupId>ch.qos.logback</groupId>\n                    <artifactId>logback-classic</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>ch.qos.logback</groupId>\n                    <artifactId>logback-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-surefire-plugin</artifactId>\n                <version>2.22.2</version>\n                <configuration>\n                    <!--表示执行任何子目录下所有命名以Test结尾的java类-->\n                    <includes>\n                        <include>**/*Test.java</include>\n                    </includes>\n                    <!--表示不执行任何子目录下所有命名以Test开头的java类-->\n                    <excludes>\n                        <exclude>**/Test*.java</exclude>\n                    </excludes>\n                    <reportsDirectory>${basedir}/test_output</reportsDirectory>\n                    <!-- 忽略测试套件执行过程中失败的测试方法，继续执行剩余的测试类和测试方法 -->\n                    <testFailureIgnore>true</testFailureIgnore>\n                    <!-- 并行执行最大线程数 -->\n                    <forkCount>2</forkCount>\n                    <!-- 是否可以重用 -->\n                    <reuseForks>true</reuseForks>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/java/com/didichuxing/datachannel/arius/admin/method/v3/op/metrics/GatewayMetricsControllerMethod.java",
    "content": ""
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/java/com/didichuxing/datachannel/arius/admin/request/outer/ThirdpartGatewayControllerMethod.java",
    "content": "package com.didichuxing.datachannel.arius.admin.request.outer;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V2_THIRD_PART;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.TypeReference;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.GatewayHeartbeat;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateRequest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.GatewayESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplateDeployInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplatePhysicalVO;\nimport com.didichuxing.datachannel.arius.admin.util.AriusClient;\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author wuxuan\n * @Date 2022/6/16\n */\npublic class ThirdpartGatewayControllerMethod {\n    public static final String THIRDPART_GATEWAY = V2_THIRD_PART + \"/gateway\";\n\n    public static Result<Void> heartbeat(GatewayHeartbeat heartbeat) throws IOException {\n        String path = String.format(\"%s/heartbeat\", THIRDPART_GATEWAY);\n        return JSON.parseObject(AriusClient.put(path, heartbeat), new TypeReference<Result<Void>>() {\n        });\n    }\n\n    public static Result<Integer> heartbeat(String clusterName) throws IOException {\n        String path = String.format(\"%s/alivecount\", THIRDPART_GATEWAY);\n        Map<String, Object> params = new HashMap<>(1);\n        params.put(\"clusterName\", clusterName);\n        return JSON.parseObject(AriusClient.get(path, params), new TypeReference<Result<Integer>>() {\n        });\n    }\n\n    public static Result<List<String>> getGatewayAliveNodeNames() throws IOException {\n        String path = String.format(\"%s/aliveNodeName\", THIRDPART_GATEWAY);\n        return JSON.parseObject(AriusClient.get(path), new TypeReference<Result<List<String>>>() {\n        });\n    }\n\n    public static Result<List<GatewayESUserVO>> listApp() throws IOException {\n        String path = String.format(\"%s/listApp\", THIRDPART_GATEWAY);\n        return JSON.parseObject(AriusClient.get(path), new TypeReference<Result<List<GatewayESUserVO>>>() {\n        });\n    }\n\n    public static Result<Map<String, GatewayTemplatePhysicalVO>> getTemplateMap(String cluster) throws IOException {\n        String path = String.format(\"%s/getTemplateMap\", THIRDPART_GATEWAY);\n        Map<String, Object> params = new HashMap<>(1);\n        params.put(\"cluster\", cluster);\n        return JSON.parseObject(AriusClient.get(path, params),\n            new TypeReference<Result<Map<String, GatewayTemplatePhysicalVO>>>() {\n            });\n    }\n\n    public static Result<Map<String, GatewayTemplateDeployInfoVO>> listDeployInfo(String dataCenter) throws IOException {\n        String path = String.format(\"%s/listDeployInfo\", THIRDPART_GATEWAY);\n        Map<String, Object> params = new HashMap<>(1);\n        params.put(\"dataCenter\", dataCenter);\n        return JSON.parseObject(AriusClient.get(path, params),\n            new TypeReference<Result<Map<String, GatewayTemplateDeployInfoVO>>>() {\n            });\n    }\n\n    public static Result<ScrollDslTemplateResponse> scrollSearchDslTemplate(ScrollDslTemplateRequest request) throws IOException {\n        String path = String.format(\"%s/dsl/scrollDslTemplates\", THIRDPART_GATEWAY);\n        return JSON.parseObject(AriusClient.post(path, request),\n            new TypeReference<Result<ScrollDslTemplateResponse>>() {\n            });\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/java/com/didichuxing/datachannel/arius/admin/resource/CustomDataSource.java",
    "content": "package com.didichuxing.datachannel.arius.admin.resource;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterJoinDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleHostDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.template.DslTemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.GatewayJoinQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.GatewayMetricsDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardListDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardTopNDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder.WorkOrderDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder.WorkOrderProcessDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterImportRuleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Random;\n\npublic class CustomDataSource {\n\n    public static final int SIZE = 10;\n\n    public static String    testAdminIp;\n    public static String    testAdminPort;\n    public static String    testPhyClusterIp;\n    public static Integer   testPhyClusterPort;\n    public static String    operator;\n    public static Integer   projectId;\n\n    private static String generateString(Random random, int length) {\n        String sources = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n        char[] text = new char[length];\n        for (int i = 0; i < length; i++) {\n            text[i] = sources.charAt(random.nextInt(sources.length()));\n        }\n        return new String(text);\n    }\n\n    private static String getRandomClusterName() {\n        return generateString(new Random(), 5) + \"_\" + generateString(new Random(), 5);\n    }\n\n    public static String getRandomString(int length) {\n        return generateString(new Random(), length);\n    }\n\n    public static ClusterJoinDTO getClusterJoinDTO() {\n        String clusterName = getRandomClusterName();\n        ClusterJoinDTO param = new ClusterJoinDTO();\n        param.setType(4);\n        param.setProjectId(projectId);\n        param.setCluster(clusterName);\n        param.setEsVersion(\"7.6.2\");\n        param.setPhyClusterDesc(\"\");\n        param.setPassword(\"\");\n        param.setImportRule(ESClusterImportRuleEnum.AUTO_IMPORT.getCode());\n        param.setTags(\"\\\"createSource\\\":0}\");\n        List<ESClusterRoleHostDTO> list = new ArrayList<>();\n        for (int i = 1; i <= 3; i++) {\n            ESClusterRoleHostDTO esClusterRoleHostDTO = getESRoleClusterHostDTO();\n            esClusterRoleHostDTO.setCluster(clusterName);\n            esClusterRoleHostDTO.setRole(i);\n            list.add(esClusterRoleHostDTO);\n        }\n        param.setRoleClusterHosts(list);\n        return param;\n    }\n\n    public static ESClusterRoleHostDTO getESRoleClusterHostDTO() {\n        ESClusterRoleHostDTO hostDTO = new ESClusterRoleHostDTO();\n        hostDTO.setCluster(getRandomClusterName());\n        hostDTO.setIp(testPhyClusterIp);\n        hostDTO.setNodeSet(\"\");\n        hostDTO.setPort(String.valueOf(testPhyClusterPort));\n        hostDTO.setRole(ESClusterNodeRoleEnum.MASTER_NODE.getCode());\n        hostDTO.setRoleClusterId(0L);\n        hostDTO.setStatus(0);\n        hostDTO.setBeCold(false);\n        return hostDTO;\n    }\n\n    public static WorkOrderDTO getWorkOrderDTO(String type) {\n        WorkOrderDTO workOrderDTO = new WorkOrderDTO();\n        Map<String, Object> contentObj = new HashMap<>();\n        workOrderDTO.setContentObj(contentObj);\n        workOrderDTO.setSubmitor(operator);\n        workOrderDTO.setSubmitorProjectId(projectId);\n        workOrderDTO.setDescription(\"testtest\");\n        workOrderDTO.setType(type);\n        return workOrderDTO;\n    }\n\n    public static ClusterPhyConditionDTO getClusterPhyConditionDTO(String clusterName) {\n        ClusterPhyConditionDTO clusterPhyConditionDTO = new ClusterPhyConditionDTO();\n        clusterPhyConditionDTO.setCluster(clusterName);\n        clusterPhyConditionDTO.setPage(1L);\n        clusterPhyConditionDTO.setSize(10L);\n        return clusterPhyConditionDTO;\n    }\n\n    public static ClusterLogicConditionDTO getClusterLogicConditionDTO(String clusterName) {\n        ClusterLogicConditionDTO clusterLogicConditionDTO = new ClusterLogicConditionDTO();\n        clusterLogicConditionDTO.setName(clusterName);\n        clusterLogicConditionDTO.setPage(1L);\n        clusterLogicConditionDTO.setSize(10L);\n        return clusterLogicConditionDTO;\n    }\n\n    public static WorkOrderProcessDTO getWorkOrderProcessDTO(Long orderId) {\n        WorkOrderProcessDTO workOrderProcessDTO = new WorkOrderProcessDTO();\n        workOrderProcessDTO.setAssignee(operator);\n        workOrderProcessDTO.setAssigneeProjectId(projectId);\n        workOrderProcessDTO.setComment(\"testtest\");\n        workOrderProcessDTO.setOrderId(orderId);\n        workOrderProcessDTO.setCheckAuthority(false);\n        workOrderProcessDTO.setOutcome(\"agree\");\n        workOrderProcessDTO.setContentObj(new HashMap<>());\n        return workOrderProcessDTO;\n    }\n\n    public static DslTemplateConditionDTO getDslTemplateConditionDTO() {\n        DslTemplateConditionDTO dto = new DslTemplateConditionDTO();\n        long endTime = System.currentTimeMillis();\n        dto.setEndTime(endTime);\n        dto.setStartTime(endTime - 1000 * 60 * 60 * 24);\n        dto.setPage(1L);\n        dto.setSize(10L);\n        return dto;\n    }\n\n    public static GatewayJoinQueryDTO getGatewayJoinQueryDTO() {\n        GatewayJoinQueryDTO dto = new GatewayJoinQueryDTO();\n        long endTime = System.currentTimeMillis();\n        dto.setEndTime(endTime);\n        dto.setStartTime(endTime - 1000 * 60 * 60 * 24);\n        return dto;\n    }\n\n    public static TemplateConditionDTO getTemplateConditionDTO() {\n        TemplateConditionDTO dto = new TemplateConditionDTO();\n        dto.setPage(1L);\n        dto.setSize(10L);\n        return dto;\n    }\n\n    public static OpTaskDTO getworkTaskDTO() {\n        OpTaskDTO opTaskDTO = new OpTaskDTO();\n        opTaskDTO.setTaskType(1);\n        opTaskDTO.setBusinessKey(\"1\");\n        opTaskDTO.setDataCenter(\"1\");\n        opTaskDTO.setCreator(operator);\n        opTaskDTO.setExpandData(\"1\");\n        opTaskDTO.setStatus(\"success\");\n        opTaskDTO.setCreateTime(new Date(System.currentTimeMillis()));\n        opTaskDTO.setDeleteFlag(Boolean.FALSE);\n        opTaskDTO.setId(2);\n        opTaskDTO.setTitle(\"1\");\n        opTaskDTO.setUpdateTime(new Date(System.currentTimeMillis()));\n        return opTaskDTO;\n    }\n\n    public static void setMetricsClusterPhyDTO(MetricsClusterPhyDTO param) {\n        param.setClusterPhyName(\"logi-elasticsearch-7.6.0\");\n        param.setAggType(\"max\");\n        Long nowTime = System.currentTimeMillis();\n        param.setStartTime(nowTime - 10 * 60 * 1000);\n        param.setEndTime(nowTime);\n    }\n\n    public static void setGatewayMetricsDTO(GatewayMetricsDTO param) {\n        Long nowTime = System.currentTimeMillis();\n        param.setStartTime(nowTime - 10 * 60 * 1000);\n        param.setEndTime(nowTime);\n    }\n\n    public static MetricsDashboardTopNDTO getMetricsDashboardTopNDTO() {\n        MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO();\n        Long nowTime = System.currentTimeMillis();\n        param.setStartTime(nowTime - 10 * 60 * 1000);\n        param.setEndTime(nowTime);\n        param.setAggType(\"max\");\n        return param;\n    }\n\n    public static MetricsDashboardListDTO getMetricsDashboardListDTO() {\n        MetricsDashboardListDTO param = new MetricsDashboardListDTO();\n        param.setAggType(\"max\");\n        param.setOrderByDesc(true);\n        return param;\n    }\n\n    public static <T> List<T> getRandomItemsFromList(List<T> sourceList) {\n        Random random = new Random();\n        int randomIndex = random.nextInt(sourceList.size()) + 1;\n        Collections.shuffle(sourceList);\n        return sourceList.subList(0, randomIndex);\n    }\n\n    public static List<String> getRandomTopClusterMetrics() {\n        List<String> clusterMetrics = Lists.newArrayList(\"indexingLatency\", \"indexReqNum\", \"searchLatency\",\n            \"gatewaySucPer\", \"gatewayFailedPer\", \"pendingTaskNum\", \"docUprushNum\", \"reqUprushNum\", \"shardNum\");\n        return getRandomItemsFromList(clusterMetrics);\n    }\n\n    public static List<String> getRandomTopNodeMetrics() {\n        List<String> nodeMetrics = Lists.newArrayList(\"taskConsuming\");\n        return getRandomItemsFromList(nodeMetrics);\n    }\n\n    public static List<String> getRandomTopIndexMetrics() {\n        List<String> indexMetrics = Lists.newArrayList(\"reqUprushNum\", \"docUprushNum\");\n        return getRandomItemsFromList(indexMetrics);\n    }\n\n    public static List<String> getRandomTopClusterThreadPoolQueueMetrics() {\n        List<String> clusterThreadPoolQueueMetrics = Lists.newArrayList(\"refresh\", \"flush\", \"merge\", \"search\", \"write\",\n            \"management\");\n        return getRandomItemsFromList(clusterThreadPoolQueueMetrics);\n    }\n\n    public static List<String> getRandomListTemplateMetrics() {\n        List<String> templateMetrics = Lists.newArrayList(\"segmentMemSize\", \"segmentNum\");\n        return getRandomItemsFromList(templateMetrics);\n    }\n\n    public static List<String> getRandomListNodeMetrics() {\n        List<String> nodeMetrics = Lists.newArrayList(\"dead\", \"largeDiskUsage\", \"largeHead\", \"largeCpuUsage\",\n            \"writeRejectedNum\", \"searchRejectedNum\", \"shardNum\");\n        return getRandomItemsFromList(nodeMetrics);\n    }\n\n    public static List<String> getRandomListIndexMetrics() {\n        List<String> indexMetrics = Lists.newArrayList(\"red\", \"singReplicate\", \"unassignedShard\", \"bigShard\",\n            \"smallShard\", \"mappingNum\", \"segmentNum\", \"segmentMemSize\");\n        return getRandomItemsFromList(indexMetrics);\n    }\n\n    public static List<String> getRandomOverviewMetrics() {\n        List<String> overviewMetrics = Lists.newArrayList(\"writeDocCount\", \"writeTotalCost\", \"writeResponseLen\",\n            \"queryTotalHitsAvgCount\", \"readDocCount\", \"querySearchType\", \"queryCostAvg\", \"queryTotalShardsAvg\",\n            \"queryFailedShardsAvg\", \"dslLen\");\n        return getRandomItemsFromList(overviewMetrics);\n    }\n\n    public static List<String> getRandomGatewayNodeMetrics() {\n        List<String> gatewayNodeMetrics = Lists.newArrayList(\"queryGatewayNode\", \"writeGatewayNode\", \"dslLen\");\n        return getRandomItemsFromList(gatewayNodeMetrics);\n    }\n\n    public static List<String> getRandomClientNodeMetrics() {\n        List<String> clientNodeMetrics = Lists.newArrayList(\"queryClientNode\", \"writeClientNode\", \"dslLen\");\n        return getRandomItemsFromList(clientNodeMetrics);\n    }\n\n    public static List<String> getRandomGatewayIndexMetrics() {\n        List<String> gatewayIndexMetrics = Lists.newArrayList(\"searchIndexCount\", \"searchIndexTotalCost\",\n            \"writeIndexCount\", \"writeIndexTotalCost\");\n        return getRandomItemsFromList(gatewayIndexMetrics);\n    }\n\n    public static List<String> getRandomGatewayAppMetrics() {\n        List<String> gatewayAppMetrics = Lists.newArrayList(\"queryAppSearchCost\", \"queryAppTotalCost\", \"queryAppCount\");\n        return getRandomItemsFromList(gatewayAppMetrics);\n    }\n\n    public static List<String> getRandomGatewayDslMetrics() {\n        List<String> gatewayDslMetrics = Lists.newArrayList(\"queryDslTotalCost\", \"queryDslCount\");\n        return getRandomItemsFromList(gatewayDslMetrics);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/java/com/didichuxing/datachannel/arius/admin/util/AriusClient.java",
    "content": "package com.didichuxing.datachannel.arius.admin.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport okhttp3.*;\nimport org.apache.commons.lang3.StringUtils;\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.*;\nimport java.util.concurrent.TimeUnit;\n\npublic class AriusClient {\n    private static final ILog LOGGER                      = LogFactory.getLog(AriusClient.class);\n    private static final MediaType JSON_TYPE                   = MediaType.get(\"application/json; charset=utf-8\");\n    private static String          prefix;\n    private static String          user                        = \"admin\";\n    private static String          app                         = \"\";\n    private static final String    GATEWAY_GET_APP_TICKET      = \"xTc59aY72\";\n    private static final String    GATEWAY_GET_APP_TICKET_NAME = \"X-ARIUS-GATEWAY-TICKET\";\n\n    public static String postForFileForm(String path, String fileFormKey, File fileFormValue,\n                                         Map<String, Object> params) throws IOException {\n        RequestBody fileBody = RequestBody.create(MediaType.parse(\"multipart/form-data\"), fileFormValue);\n        MultipartBody.Builder builder = new MultipartBody.Builder();\n        builder.addFormDataPart(fileFormKey, fileFormValue.getName(), fileBody);\n        builder.setType(MultipartBody.FORM);\n        for (String key : params.keySet()) {\n            builder.addFormDataPart(key, String.valueOf(params.get(key)));\n        }\n\n        Request request = new Request.Builder().url(prefix + path).post(builder.build()).addHeader(\"X-SSO-USER\", user)\n            .addHeader(\"X-ARIUS-APP-ID\", app).addHeader(GATEWAY_GET_APP_TICKET_NAME, GATEWAY_GET_APP_TICKET).build();\n\n        OkHttpClient client = new OkHttpClient.Builder().readTimeout(1200000, TimeUnit.MILLISECONDS).build();\n\n        long start = System.currentTimeMillis();\n        try (Response response = client.newCall(request).execute()) {\n            String responseBody = Objects.requireNonNull(response.body()).string();\n            long end = System.currentTimeMillis();\n            LOGGER.info(\"class=AriusClient||method=postForFileForm||msg=used time {}ms\", end - start);\n            LOGGER.info(\"class=AriusClient||method=postForFileForm||msg={}\", responseBody);\n            return responseBody;\n        }\n    }\n\n    private static Request buildRequest(String path, String method, String requestBody) {\n        if (requestBody != null) {\n            LOGGER.info(\"class=AriusClient||method=run||msg={}\", requestBody);\n        }\n\n        RequestBody body = requestBody != null ? RequestBody.create(requestBody, JSON_TYPE) : null;\n        Request.Builder builder = new Request.Builder();\n        builder.url(prefix + path).method(method, body);\n        if (!StringUtils.isBlank(user)) {\n            builder.addHeader(\"X-SSO-USER\", user);\n        }\n        if (!StringUtils.isBlank(app)) {\n            builder.addHeader(\"X-ARIUS-APP-ID\", app);\n        }\n        builder.addHeader(GATEWAY_GET_APP_TICKET_NAME, GATEWAY_GET_APP_TICKET);\n        return builder.build();\n    }\n\n    public static String run(String path, String method, String requestBody) throws IOException {\n        long start = System.currentTimeMillis();\n        OkHttpClient client = new OkHttpClient.Builder().readTimeout(1200000, TimeUnit.MILLISECONDS).build();\n        Request request = buildRequest(path, method, requestBody);\n        try (Response response = client.newCall(request).execute()) {\n            String responseBody = Objects.requireNonNull(response.body()).string();\n            long end = System.currentTimeMillis();\n            LOGGER.info(\"class=AriusClient||method={}||path={}||requestBody={}||msg={}||used time {}ms\", method, path,\n                requestBody, responseBody, end - start);\n            return responseBody;\n        }\n    }\n\n    public static String runPage(String path, String method, String requestBody) throws IOException {\n        long start = System.currentTimeMillis();\n        OkHttpClient client = new OkHttpClient.Builder().readTimeout(1200000, TimeUnit.MILLISECONDS).build();\n        Request request = buildRequest(path, method, requestBody);\n        try (Response response = client.newCall(request).execute()) {\n            String responseBody = Objects.requireNonNull(response.body()).string();\n            long end = System.currentTimeMillis();\n            LOGGER.info(\"class=AriusClient||method=runPage||msg=used time {}ms\", end - start);\n            LOGGER.info(\"class=AriusClient||method=runPage||msg={}\", responseBody);\n            return responseBody;\n        }\n    }\n\n    public static String get(String path) throws IOException {\n        return run(path, \"GET\", null);\n    }\n\n    private static String buildPathWithParams(String path, Map<String, Object> params) {\n        Iterator<Map.Entry<String, Object>> var3;\n        if (params != null) {\n            StringBuilder builder = (new StringBuilder(path)).append('?');\n            var3 = params.entrySet().iterator();\n\n            while (var3.hasNext()) {\n                Map.Entry<String, Object> e = var3.next();\n                builder.append(e.getKey()).append('=').append(e.getValue()).append('&');\n            }\n\n            path = builder.toString();\n        }\n        return path;\n    }\n\n    public static String get(String path, Map<String, Object> params) throws IOException {\n        path = buildPathWithParams(path, params);\n        return get(path);\n    }\n\n    public static String post(String path, Object requestBody) throws IOException {\n        if (requestBody == null) {\n            return run(path, \"POST\", null);\n        }\n        return run(path, \"POST\", JSON.toJSONString(requestBody));\n    }\n\n    public static String postPage(String path, Object requestBody) throws IOException {\n        if (requestBody == null) {\n            return runPage(path, \"POST\", null);\n        }\n        return runPage(path, \"POST\", JSON.toJSONString(requestBody));\n    }\n\n    public static String put(String path, Object requestBody) throws IOException {\n        if (requestBody == null) {\n            return run(path, \"PUT\", JSON.toJSONString(new HashMap<>()));\n        }\n        return run(path, \"PUT\", JSON.toJSONString(requestBody));\n    }\n\n    public static String put(String path, Map<String, Object> params, Object requestBody) throws IOException {\n        if (params == null) {\n            return delete(path, JSON.toJSONString(requestBody));\n        }\n        path = buildPathWithParams(path, params);\n        return put(path, JSON.toJSONString(requestBody));\n    }\n\n    public static String put(String path) throws IOException {\n        return put(path, new HashMap<>());\n    }\n\n    public static String delete(String path) throws IOException {\n        return delete(path, null);\n    }\n\n    private static String delete(String path, Object requestBody) throws IOException {\n        if (requestBody == null) {\n            return run(path, \"DELETE\", null);\n        }\n        return run(path, \"DELETE\", JSON.toJSONString(requestBody));\n    }\n\n    public static String delete(String path, Map<String, Object> params, Object requestBody) throws IOException {\n        if (params == null) {\n            return delete(path, JSON.toJSONString(requestBody));\n        }\n        path = buildPathWithParams(path, params);\n        return delete(path, JSON.toJSONString(requestBody));\n    }\n\n    public static String getPrefix() {\n        return prefix;\n    }\n\n    public static void setPrefix(String prefix) {\n        AriusClient.prefix = prefix;\n    }\n\n    public static String getUser() {\n        return user;\n    }\n\n    public static void setUser(String user) {\n        AriusClient.user = user;\n    }\n\n    public static String getApp() {\n        return app;\n    }\n\n    public static void setApp(String app) {\n        AriusClient.app = app;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/java/com/didichuxing/datachannel/arius/admin/util/CompareUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.io.FileUtils;\nimport org.springframework.util.ResourceUtils;\nimport java.io.File;\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.nio.charset.StandardCharsets;\nimport java.util.*;\n\npublic class CompareUtil {\n    private static final ILog LOGGER = LogFactory.getLog(CompareUtil.class);\n\n    private CompareUtil() {\n    }\n\n    /**\n     * src为用户传入的参数，dst为系统返回，src和dst类型不需要相同，dst中可能包含src中没有的属性\n     * 如果设置ignore对象的子对象属性，可以用'.'分隔，ignore属性只针对src\n     *\n     * @param src\n     * @param dst\n     * @param ignoreFields\n     * @return\n     */\n    public static boolean objectEquals(Object src, Object dst, String... ignoreFields) throws AdminOperateException {\n        if (src == null) {\n            LOGGER.warn(\"class=CompareUtils||method=objectEquals||msg=src and dst is null\");\n            return dst == null;\n        } else if (dst == null) {\n            return false;\n        }\n        Class<?> c = src.getClass();\n        Field[] fields = c.getDeclaredFields();\n        for (Field field : fields) {\n            String name = field.getName();\n            if (\"id\".equals(name)) {\n                continue;\n            }\n            if (search(ignoreFields, name) >= 0) {\n                continue;\n            }\n            field.setAccessible(true);\n            try {\n                Object srcValue = field.get(src);\n                Object dstValue = field.get(dst);\n                if (srcValue == null) {\n                    return dstValue == null;\n                }\n                if (srcValue.getClass() != dstValue.getClass()) {\n                    LOGGER.error(\n                        \"class=CompareUtils||method=objectEquals||msg=type not match, field name: {}, src type: {}, dst type: {}\",\n                        name, srcValue.getClass(), dstValue.getClass());\n                    return false;\n                }\n                if (isJsonTypeOrObject(srcValue)) {\n                    if (!srcValue.equals(dstValue)) {\n                        LOGGER.error(\n                            \"class=CompareUtils||method=objectEquals||errMsg=field not equals, name: {}, src: {}, dst: {}\",\n                            name, srcValue, dstValue);\n                        return false;\n                    }\n                } else {\n                    String[] nextFields = multiSlice(ignoreFields, '.');\n                    if (List.class.isAssignableFrom(srcValue.getClass())) {\n                        if (!listEqualsIgnoreOrder((List) srcValue, (List) dstValue, nextFields)) {\n                            return false;\n                        }\n                    } else {\n                        if (!objectEquals(srcValue, dstValue, nextFields)) {\n                            return false;\n                        }\n                    }\n                }\n            } catch (IllegalAccessException e) {\n                LOGGER.error(\"\", e);\n                throw new AdminOperateException(\"\", ResultType.FAIL);\n            }\n        }\n        return true;\n    }\n\n    public static String[] multiSlice(String[] s, char c) {\n        List<String> result = new ArrayList<>();\n        for (String s1 : s) {\n            int index = s1.indexOf(c);\n            if (index >= 0) {\n                result.add(s1.substring(index + 1));\n            }\n        }\n        return result.toArray(new String[0]);\n    }\n\n    /**\n     * dst为系统返回列表，不可少于src\n     *\n     * @param src\n     * @param dst\n     * @param ignoreFields\n     * @return\n     */\n    public static boolean listEqualsIgnoreOrder(List<?> src, List<?> dst,\n                                                String... ignoreFields) throws AdminOperateException {\n        if (src == null) {\n            LOGGER.warn(\"class=CompareUtils||method=listEqualsIgnoreOrder||msg=src and dst is null\");\n            return dst == null;\n        } else if (dst == null) {\n            return false;\n        }\n        if (src.size() != dst.size()) {\n            LOGGER.error(\"class=CompareUtils||method=listEqualsIgnoreOrder||errMsg=size not equal, src: {}, dst: {}\",\n                src.size(), dst.size());\n            return false;\n        }\n        for (int i = 0; i < src.size(); i++) {\n            boolean found = false;\n            for (int j = 0; j < dst.size(); j++) {\n                if (objectEquals(src.get(i), dst.get(j), ignoreFields)) {\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                LOGGER.error(\n                    \"class=CompareUtils||method=listEqualsIgnoreOrder||errMsg=no equal element found in dst, index: {}, element: {}\",\n                    i, JSON.toJSONString(src.get(i)));\n                return false;\n            }\n        }\n        return true;\n    }\n\n    public static int search(String[] array, String s) {\n        if (s == null) {\n            for (int i = 0; i < array.length; i++) {\n                if (array[i] == null) {\n                    return i;\n                }\n            }\n        } else {\n            for (int i = 0; i < array.length; i++) {\n                if (s.equals(array[i])) {\n                    return i;\n                }\n            }\n        }\n        return -1;\n    }\n\n    /**\n     * 判断json对象属性的类型，包括bool, number, string, date\n     *\n     * @return true属性为基础类型 false属性为其他对象\n     */\n    public static boolean isJsonTypeOrObject(Object o) {\n        Class<?> c = o.getClass();\n        return String.class.isAssignableFrom(c) || Number.class.isAssignableFrom(c) || Boolean.class == c\n               || Date.class == c;\n    }\n\n    /**\n     * 把类反序列化为json\n     */\n    public static String serialize(Object object) {\n        // JSON对象序列化\n        String objectJson = JSON.toJSONString(object, SerializerFeature.WRITE_MAP_NULL_FEATURES);\n        return objectJson;\n    }\n\n    public static boolean compareJson(String templateJsonFile, String responseJsonString) throws IOException {\n        //根据文件路径读取模版json\n        File file = ResourceUtils.getFile(templateJsonFile);\n        if (file == null) {\n            LOGGER.error(\"class=CompareUtils||method=compareJson||errMsg=templateJsonFile is not found\");\n            return false;\n        }\n        String templateJsonString = FileUtils.readFileToString(file, StandardCharsets.UTF_8);\n        //将返回体与json转换为Map形式方便比较对比\n        JSON templateJson = JSON.parseObject(templateJsonString);\n        JSON responseJson = JSON.parseObject(responseJsonString);\n        Map<String, Object> templateMap = new LinkedHashMap<>();\n        Map<String, Object> responseMap = new LinkedHashMap<>();\n        convertJsonToMap(templateJson, \"\", templateMap);\n        convertJsonToMap(responseJson, \"\", responseMap);\n        //调用CompareUtil中用于对比的compareMap函数\n        return compareMap(responseMap, templateMap);\n    }\n\n    public static void convertJsonToMap(Object json, String root, Map<String, Object> resultMap) {\n        if (json instanceof JSONObject) {\n            JSONObject jsonObject = ((JSONObject) json);\n            Iterator iterator = jsonObject.keySet().iterator();\n            while (iterator.hasNext()) {\n                Object key = iterator.next();\n                Object value = jsonObject.get(key);\n                String newRoot = \"\".equals(root) ? key + \"\" : root + \".\" + key;\n                if (value instanceof JSONObject || value instanceof JSONArray) {\n                    convertJsonToMap(value, newRoot, resultMap);\n                } else {\n                    resultMap.put(newRoot, value);\n                }\n            }\n        } else if (json instanceof JSONArray) {\n            JSONArray jsonArray = (JSONArray) json;\n            for (int i = 0; i < jsonArray.size(); i++) {\n                Object vaule = jsonArray.get(i);\n                String newRoot = \"\".equals(root) ? \"[\" + i + \"]\" : root + \".[\" + i + \"]\";\n                if (vaule instanceof JSONObject || vaule instanceof JSONArray) {\n                    convertJsonToMap(vaule, newRoot, resultMap);\n                } else {\n                    resultMap.put(newRoot, vaule);\n                }\n            }\n        }\n    }\n\n    public static boolean compareMap(Map<String, Object> responseMap, Map<String, Object> templateMap) {\n        for (String templateKey : templateMap.keySet()) {\n            boolean flag = false;\n            for (String responseKey : responseMap.keySet()) {\n                if (isMatch(responseKey, templateKey)) {\n                    if (responseMap.get(responseKey) == null && templateMap.get(templateKey) != null) {\n                        return false;\n                    } else if (responseMap.get(responseKey) == \"\" && templateMap.get(templateKey) != \"\") {\n                        return false;\n                    } else {\n                        flag = true;\n                    }\n                }\n            }\n            if (flag == false) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    public static boolean isMatch(String s, String p) {\n        boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];\n        dp[0][0] = true;\n        for (int j = 0; j < p.length(); j++) {\n            if (dp[0][j] && p.charAt(j) == '*') {\n                dp[0][j + 1] = true;\n            }\n        }\n        for (int i = 0; i < s.length(); i++) {\n            for (int j = 0; j < p.length(); j++) {\n                if (p.charAt(j) == '*') {\n                    dp[i + 1][j + 1] = dp[i][j + 1] || dp[i + 1][j];\n                } else if (p.charAt(j) == '.' || p.charAt(j) == s.charAt(i)) {\n                    dp[i + 1][j + 1] = dp[i][j];\n                }\n            }\n        }\n        return dp[s.length()][p.length()];\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/java/com/didichuxing/datachannel/arius/admin/util/RandomConfig.java",
    "content": "package com.didichuxing.datachannel.arius.admin.util;\n\npublic class RandomConfig {\n    private RandomConfig() {\n    }\n\n    public static final int    INT_LOW       = 0;\n    public static final int    INT_HIGH      = 1;\n    public static final int    LONG_LOW      = 0;\n    public static final int    LONG_HIGH     = 100000;\n    public static final double DOUBLE_LOW    = 0;\n    public static final double DOUBLE_HIGH   = 100000;\n    public static final int    STRING_LENGTH = 10;\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/java/com/didichuxing/datachannel/arius/admin/util/RandomFilledBean.java",
    "content": "package com.didichuxing.datachannel.arius.admin.util;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.math.BigDecimal;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.Map;\n\npublic class RandomFilledBean {\n\n    private RandomFilledBean() {\n    }\n\n    private static final ILog LOGGER = LogFactory.getLog(RandomFilledBean.class);\n\n    public static <T> T construct(Class<T> cls) throws NoSuchMethodException, IllegalAccessException,\n                                                InvocationTargetException, InstantiationException {\n        Constructor<T> constructor = cls.getConstructor();\n        return constructor.newInstance();\n    }\n\n    public static <T> void fill(T bean) {\n        Field[] fields = bean.getClass().getDeclaredFields();\n        for (Field field : fields) {\n            if (\"createTime\".equals(field.getName()) || \"updateTime\".equals(field.getName())\n                || \"id\".equals(field.getName())) {\n                continue;\n            }\n            field.setAccessible(true);\n            Class<?> cls = field.getType();\n            try {\n                setBean(bean, field, cls);\n            } catch (IllegalAccessException e) {\n                LOGGER.error(\"class=RandomFilledBean||method=fill||errMsg=field generate failed\");\n            }\n        }\n    }\n\n    private static <T> void setBean(T bean, Field field, Class cls) throws IllegalAccessException {\n        if (String.class.isAssignableFrom(cls)) {\n            field.set(bean, RandomGenerator.randomString(RandomConfig.STRING_LENGTH));\n        } else if (Number.class.isAssignableFrom(cls)) {\n            setBeanRandom(bean, field, cls);\n        } else if (cls == Boolean.class) {\n            field.set(bean, RandomGenerator.randomBoolean());\n        } else if (cls == Date.class) {\n            field.set(bean, new Date());\n        } else if (Collection.class.isAssignableFrom(cls) || Map.class.isAssignableFrom(cls)) {\n            field.set(bean, null);\n        } else if (Enum.class.isAssignableFrom(cls)) {\n            field.set(bean, RandomGenerator.randomFromEnum(cls));\n        } else {\n            field.set(bean, null);\n        }\n    }\n\n    private static <T> void setBeanRandom(T bean, Field field, Class cls) throws IllegalAccessException {\n        if (cls == Integer.class) {\n            field.set(bean, RandomGenerator.randomInt(RandomConfig.INT_LOW, RandomConfig.INT_HIGH));\n        } else if (cls == Long.class) {\n            field.set(bean, Long.valueOf(RandomGenerator.randomInt(RandomConfig.LONG_LOW, RandomConfig.LONG_HIGH)));\n        } else if (cls == Double.class) {\n            field.set(bean, RandomGenerator.randomDouble(RandomConfig.DOUBLE_LOW, RandomConfig.DOUBLE_HIGH));\n        } else if (cls == BigDecimal.class) {\n            field.set(bean,\n                BigDecimal.valueOf(RandomGenerator.randomDouble(RandomConfig.DOUBLE_LOW, RandomConfig.DOUBLE_HIGH)));\n        }\n    }\n\n    public static <T> T getRandomBeanOfType(Class<T> cls) {\n        T t = null;\n        try {\n            t = construct(cls);\n            fill(t);\n        } catch (NoSuchMethodException e) {\n            LOGGER.error(\"class=RandomFilledBean||method=fill||errMsg=field generate failed\");\n            return null;\n        } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {\n            LOGGER.error(\"class=RandomFilledBean||method=fill||errMsg=field generate failed\");\n        }\n        return t;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/java/com/didichuxing/datachannel/arius/admin/util/RandomGenerator.java",
    "content": "package com.didichuxing.datachannel.arius.admin.util;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.Random;\n\npublic class RandomGenerator {\n\n    private RandomGenerator() {\n    }\n\n    private static final Random random = new Random();\n\n    private static final ILog LOGGER = LogFactory.getLog(RandomGenerator.class);\n\n    public static Integer randomInt(int low, int high) {\n        if (high <= low) {\n            throw new IllegalArgumentException(\"bound should be higher\");\n        }\n        return low + random.nextInt(high - low);\n    }\n\n    public static Double randomDouble(double low, double high) {\n        if (high <= low) {\n            throw new IllegalArgumentException(\"bound should be higher\");\n        }\n        return random.nextDouble() * (high - low) + low;\n    }\n\n    public static String randomString(int length) {\n        char[] value = new char[length];\n        for (int i = 0; i < length; i++) {\n            value[i] = randomWritableChar();\n        }\n        return new String(value);\n    }\n\n    public static char randomWritableChar() {\n        return (char) (33 + random.nextInt(94));\n    }\n\n    public static <T> T randomFromEnum(Class<? extends Enum> c) {\n        try {\n            Method method = c.getMethod(\"values\");\n            T[] ts = (T[]) method.invoke(c);\n            int index = new Random().nextInt(ts.length);\n            return ts[index];\n        } catch (NoSuchMethodException e) {\n            LOGGER.error(\"class=RandomGenerator||method=randomFromEnum||errMsg=get enum failed\", e);\n        } catch (IllegalAccessException | InvocationTargetException e) {\n            LOGGER.error(\"class=RandomGenerator||method=randomFromEnum||errMsg=\", e);\n        }\n        return null;\n    }\n\n    public static boolean randomBoolean() {\n        return new Random().nextInt() % 2 == 0;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/resources/template.thirdpart.gateway/gatewayappvo.json",
    "content": "{\n  \"createTime\":\"2022-03-08T08:19:11.000+0000\",\n  \"updateTime\":\"2022-04-13T06:49:42.000+0000\",\n  \"id\":4437,\n  \"name\":\"2-hf-test\",\n  \"verifyCode\":\"123456\",\n  \"queryThreshold\":11,\n  \"cluster\":\"lcx-0401\",\n  \"searchType\":2,\n  \"indexExp\":[\n    \"\\\"\\\"\"\n  ],\n  \"ip\":[\n\n  ],\n  \"dataCenter\":\"cn\",\n  \"dslAnalyzeEnable\":1,\n  \"aggrAnalyzeEnable\":1,\n  \"analyzeResponseEnable\":1,\n  \"isRoot\":0,\n  \"windexExp\":[\n\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/resources/template.thirdpart.gateway/gatewaytemplatedeployinfovo.json",
    "content": "{\n  \"*\":{\n    \"createTime\":null,\n    \"updateTime\":null,\n    \"baseInfo\":{\n      \"createTime\":\"2022-03-08T06:48:08.000+0000\",\n      \"updateTime\":\"2022-03-22T14:57:48.000+0000\",\n      \"id\":33425,\n      \"name\":\"4144-didi-cloud\",\n      \"dataCenter\":\"cn\",\n      \"expression\":\"4144-didi-cloud*\",\n      \"dateField\":\"timeStamp\",\n      \"dateFieldFormat\":\"\",\n      \"idField\":\"\",\n      \"routingField\":\"\",\n      \"dateFormat\":\"_yyyy-MM-dd\",\n      \"expireTime\":2,\n      \"ingestPipeline\":\"4144-didi-cloud\",\n      \"deployStatus\":3,\n      \"version\":0,\n      \"aliases\":[\n\n      ],\n      \"blockRead\":false,\n      \"blockWrite\":false\n    },\n    \"masterInfo\":{\n      \"templateName\":\"4144-didi-cloud\",\n      \"cluster\":\"dcdr-master\",\n      \"defaultWriterFlags\":true,\n      \"groupId\":\"42a9aeef-bab7-4b35-bf8e-b33bd3245496\",\n      \"rack\":\"r0,r3\",\n      \"shardNum\":1,\n      \"topic\":null,\n      \"accessApps\":null,\n      \"mappingIndexNameEnable\":null,\n      \"typeIndexMapping\":null\n    },\n    \"slaveInfos\":[\n\n    ]\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/resources/template.thirdpart.gateway/gatewaytemplatephysicalvo.json",
    "content": "{\n  \"*\":{\n    \"createTime\":\"2022-04-11T06:21:04.000+0000\",\n    \"updateTime\":\"2022-04-15T19:00:12.000+0000\",\n    \"id\":46799,\n    \"name\":\"yyftest-mb-0411-01\",\n    \"dataCenter\":\"cn\",\n    \"expression\":\"yyftest-mb-0411-01*\",\n    \"version\":1,\n    \"aliases\":[\n\n    ]\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/main/resources/template.thirdpart.gateway/scrollDslTemplateResponse.json",
    "content": "{\n\"dslTemplatePoList\":[\n\n],\n\"scrollId\":\"2022-04-13T06:49:42.000+0000\"\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/base/BaseContextTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.base;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.YamlUtil;\nimport com.didichuxing.datachannel.arius.admin.resource.CustomDataSource;\nimport com.didichuxing.datachannel.arius.admin.util.AriusClient;\nimport org.apache.commons.lang3.StringUtils;\nimport org.junit.jupiter.api.BeforeAll;\n\nimport java.io.*;\n\npublic class BaseContextTest {\n\n    protected static String prefix;\n\n    @BeforeAll\n    public static void init() throws IOException {\n        initProperties();\n        String address = CustomDataSource.testAdminIp + \":\" + CustomDataSource.testAdminPort;\n        prefix = \"http://\" + address + \"/admin/api\";\n        AriusClient.setPrefix(prefix);\n    }\n\n    public static void initProperties() throws IOException {\n        String[] ymlPaths = { \"arius-admin-rest\", \"target\", \"classes\", \"application.yml\" };\n        String path = System.getProperty(\"user.dir\");\n        // D:\\software\\project\\IdeaProjects\\arius-admin-v2\\arius-admin-rest\\target\\classes\\application.yml\n        path = path.substring(0, path.lastIndexOf(File.separator) + 1) + StringUtils.join(ymlPaths, File.separator);\n        String testPhyClusterIp = YamlUtil.getValue(path, \"integrate.test.es.ip\");\n        if (StringUtils.isEmpty(testPhyClusterIp)) {\n            throw new RuntimeException(\"集成测试需要可用的ES服务ip，请配置文件application.yml中设置：integrate.test.es.ip\");\n        }\n        String testPhyClusterPort = YamlUtil.getValue(path, \"integrate.test.es.port\");\n        if (StringUtils.isEmpty(testPhyClusterPort)) {\n            throw new RuntimeException(\"集成测试需要可用的ES服务port，请配置文件application.yml中设置：integrate.test.es.port\");\n        }\n        String appid = YamlUtil.getValue(path, \"integrate.test.appid\");\n        if (StringUtils.isEmpty(appid)) {\n            throw new RuntimeException(\"集成测试需要appid，请配置文件application.yml中设置：integrate.test.appid\");\n        }\n        String operator = YamlUtil.getValue(path, \"integrate.test.operator\");\n        if (StringUtils.isEmpty(operator)) {\n            throw new RuntimeException(\"集成测试需要operator，请配置文件application.yml中设置：integrate.test.operator\");\n        }\n        String testAdminIp = YamlUtil.getValue(path, \"integrate.test.admin.ip\");\n        if (StringUtils.isEmpty(testAdminIp)) {\n            throw new RuntimeException(\"集成测试需要可用的Admin服务ip，请配置文件application.yml中设置：integrate.test.admin.ip\");\n        }\n        String testAdminPort = YamlUtil.getValue(path, \"integrate.test.admin.port\");\n        if (StringUtils.isEmpty(testAdminPort)) {\n            throw new RuntimeException(\"集成测试需要可用的Admin服务port，请配置文件application.yml中设置：integrate.test.admin.port\");\n        }\n        CustomDataSource.testAdminIp = testAdminIp;\n        CustomDataSource.testAdminPort = testAdminPort;\n        CustomDataSource.testPhyClusterIp = testPhyClusterIp;\n        CustomDataSource.testPhyClusterPort = Integer.valueOf(testPhyClusterPort);\n        CustomDataSource.projectId = Integer.valueOf(appid);\n        CustomDataSource.operator = operator;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/base/BaseLogicClusterInfoTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.base;\n\n/**\n * @author cjm\n */\npublic class BaseLogicClusterInfoTest extends BasePhyClusterInfoTest {\n    //\n    //    protected static LogicClusterInfoSource.LogicClusterInfo logicClusterInfo;\n    //\n    //    /**\n    //     * 在当前类的所有测试方法之前执行\n    //     * 由于本类中的方法都依赖物理集群和逻辑集群，所以需要接入一个物理集群，和创建一个逻辑集群\n    //     */\n    //    @BeforeAll\n    //    public static void preHandle() throws IOException {\n    //        BasePhyClusterInfoTest.preHandle();\n    //        // 创建逻辑集群（关联了前面创建的物理集群的 region）\n    //        logicClusterInfo = LogicClusterInfoSource.applyLogicCluster(phyClusterInfo.getPhyClusterName(), phyClusterInfo.getPhyClusterName());\n    //    }\n    //\n    //    /**\n    //     * 在当前类中的所有测试方法之后执行\n    //     * 本类所有方法测试完毕后，删除物理集群，删除逻辑集群\n    //     */\n    //    @AfterAll\n    //    public static void afterCompletion() throws IOException {\n    //        BasePhyClusterInfoTest.afterCompletion();\n    //    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/base/BasePhyClusterInfoTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.base;\n\n/**\n * @author cjm\n */\npublic class BasePhyClusterInfoTest extends BaseContextTest {\n    //\n    //    protected static PhyClusterInfoSource.PhyClusterInfo phyClusterInfo;\n    //\n    //    /**\n    //     * 在当前类的所有测试方法之前执行\n    //     */\n    //    @BeforeAll\n    //    public static void preHandle() throws IOException {\n    //        BaseContextTest.init();\n    //        phyClusterInfo = PhyClusterInfoSource.phyClusterJoin();\n    //    }\n    //\n    //    /**\n    //     * 在当前类中的所有测试方法之后执行\n    //     */\n    //    @AfterAll\n    //    public static void afterCompletion() throws IOException {\n    //        PhyClusterInfoSource.phyClusterRemove(phyClusterInfo.getPhyClusterName(), phyClusterInfo.getPhyClusterId());\n    //    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/base/BasePhyClusterRegionInfoTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.base;\n\n/**\n * @author cjm\n */\npublic class BasePhyClusterRegionInfoTest extends BasePhyClusterInfoTest {\n    //\n    //    protected static PhyClusterRegionInfoSource.PhyClusterRegionInfo phyClusterRegionInfo;\n    //\n    //    /**\n    //     * 在当前类的所有测试方法之前执行\n    //     * @throws IOException e\n    //     */\n    //    @BeforeAll\n    //    public static void preHandle() throws IOException {\n    //        BasePhyClusterInfoTest.preHandle();\n    //        // create region\n    //        /*phyClusterRegionInfo = PhyClusterRegionInfoSource.createRegion(phyClusterInfo.getPhyClusterName());*/\n    //    }\n    //\n    //    /**\n    //     * 在当前类中的所有测试方法之后执行\n    //     * @throws IOException e\n    //     */\n    //    @AfterAll\n    //    public static void afterCompletion() throws IOException {\n    //        // delete region\n    //        PhyClusterRegionInfoSource.deleteRegion(phyClusterRegionInfo.getRegionId());\n    //        BasePhyClusterInfoTest.afterCompletion();\n    //    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/base/BaseTemplateInfoTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.base;\n\n/**\n * @author cjm\n */\npublic class BaseTemplateInfoTest extends BaseLogicClusterInfoTest {\n    //\n    //    protected static TemplateInfoSource.TemplateInfo templateInfo;\n    //\n    //    /**\n    //     * 在当前类的所有测试方法之前执行\n    //     */\n    //    @BeforeAll\n    //    public static void preHandle() throws IOException {\n    //        BaseLogicClusterInfoTest.preHandle();\n    //        // 创建模版\n    //        templateInfo = TemplateInfoSource.createTemplate(phyClusterInfo.getPhyClusterName(), logicClusterInfo.getLogicClusterName(), logicClusterInfo.getLogicClusterId());\n    //    }\n    //\n    //    /**\n    //     * 在当前类中的所有测试方法之后执行\n    //     */\n    //    @AfterAll\n    //    public static void afterCompletion() throws IOException {\n    //        // 删除模版\n    //        TemplateInfoSource.deleteTemplate(templateInfo.getLogicTemplateId());\n    //        BaseLogicClusterInfoTest.afterCompletion();\n    //    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/request/outer/ThirdpartGatewayTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.request.outer;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport com.didichuxing.datachannel.arius.admin.base.BaseContextTest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.GatewayHeartbeat;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateRequest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.GatewayESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplateDeployInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplatePhysicalVO;\nimport com.didichuxing.datachannel.arius.admin.util.CompareUtil;\nimport java.io.IOException;\nimport java.util.List;\nimport java.util.Map;\nimport org.junit.Assert;\nimport org.junit.jupiter.api.Test;\n\n/**\n * @author wuxuan\n * @Date 2022/6/16\n */\npublic class ThirdpartGatewayTest extends BaseContextTest {\n\n    @Test\n    public void testHeartbeat() throws IOException {\n        GatewayHeartbeat heartbeat = new GatewayHeartbeat();\n        heartbeat.setClusterName(\"admin\");\n        heartbeat.setPort(8080);\n        heartbeat.setHostName(\"admin\");\n\n        Result<Void> result = ThirdpartGatewayControllerMethod.heartbeat(heartbeat);\n        Assert.assertTrue(result.success());\n    }\n\n    @Test\n    public void testHeartbeatByClusterName() throws IOException {\n        Result<Integer> result = ThirdpartGatewayControllerMethod.heartbeat(\"normal\");\n\n        Assert.assertTrue(result.getData() >= 0);\n        Assert.assertTrue(result.success());\n    }\n\n    @Test\n    public void testGetGatewayAliveNodeNames() throws IOException {\n        Result<List<String>> result = ThirdpartGatewayControllerMethod.getGatewayAliveNodeNames();\n        Assert.assertTrue(result.getData() != null);\n        Assert.assertTrue(result.success());\n    }\n\n    @Test\n    public void testListApp() throws IOException {\n        //调用main中的request方法去访问接口\n        Result<List<GatewayESUserVO>> result = ThirdpartGatewayControllerMethod.listApp();\n        Assert.assertTrue(result.success());\n        String templateJsonFile = \"src/main/resources/template.thirdpart.gateway/gatewayappvo.json\";\n        for (GatewayESUserVO gatewayAppVO : result.getData()) {\n            String responseJsonString = CompareUtil.serialize(gatewayAppVO);\n            Assert.assertTrue(CompareUtil.compareJson(templateJsonFile, responseJsonString));\n        }\n    }\n\n    @Test\n    public void testGetTemplateMap() throws IOException {\n        Result<Map<String, GatewayTemplatePhysicalVO>> result = ThirdpartGatewayControllerMethod\n            .getTemplateMap(\"lcx-0401\");\n        Assert.assertTrue(result.success());\n        String templateJsonFile = \"src/main/resources/template.thirdpart.gateway/gatewaytemplatephysicalvo.json\";\n        String responseJsonString = JSONObject.toJSONString(result.getData());\n        Assert.assertTrue(CompareUtil.compareJson(templateJsonFile, responseJsonString));\n    }\n\n    @Test\n    public void testListDeployInfo() throws IOException {\n        Result<Map<String, GatewayTemplateDeployInfoVO>> result = ThirdpartGatewayControllerMethod.listDeployInfo(\"cn\");\n        Assert.assertTrue(result.success());\n        String templateJsonFile = \"src/main/resources/template.thirdpart.gateway/gatewaytemplatedeployinfovo.json\";\n        String responseJsonString = JSONObject.toJSONString(result.getData(), SerializerFeature.PrettyFormat,\n            SerializerFeature.WriteMapNullValue);\n        Assert.assertTrue(CompareUtil.compareJson(templateJsonFile, responseJsonString));\n    }\n\n    @Test\n    public void testScrollSearchDslTemplate() throws IOException {\n        ScrollDslTemplateRequest scrollDslTemplateRequest = new ScrollDslTemplateRequest();\n        scrollDslTemplateRequest.setDslTemplateVersion(\"7.6.1\");\n        scrollDslTemplateRequest.setScrollSize(23L);\n        scrollDslTemplateRequest.setLastModifyTime(System.currentTimeMillis());\n        Result<ScrollDslTemplateResponse> result = ThirdpartGatewayControllerMethod\n            .scrollSearchDslTemplate(scrollDslTemplateRequest);\n        Assert.assertTrue(result.success());\n\n        String templateJsonFile = \"src/main/resources/template.thirdpart.gateway/scrollDslTemplateResponse.json\";\n        String responseJsonString = CompareUtil.serialize(result.getData());\n        Assert.assertTrue(CompareUtil.compareJson(templateJsonFile, responseJsonString));\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/resource/LogicClusterInfoSource.java",
    "content": "package com.didichuxing.datachannel.arius.admin.resource;\n\n/**\n * @author cjm\n */\npublic class LogicClusterInfoSource {\n    //\n    //    @Data\n    //    public static class LogicClusterInfo {\n    //        private String logicClusterName;\n    //        private Long logicClusterId;\n    //        private Integer type = ClusterResourceTypeEnum.PRIVATE.getCode();\n    //    }\n    //\n    //    /**\n    //     * 申请逻辑集群\n    //     */\n    //    public static LogicClusterInfo applyLogicCluster(String phyClusterName, String logicClusterName) throws IOException {\n    //        LogicClusterInfo logicClusterInfo = new LogicClusterInfo();\n    //        logicClusterInfo.logicClusterName = logicClusterName;\n    //        // 用户点击申请逻辑集群，发起工单申请\n    //        String type = \"logicClusterCreate\";\n    //        WorkOrderDTO workOrderDTO = CustomDataSource.getWorkOrderDTO(type);\n    //        Map<String, Object> contentObj = new HashMap<>();\n    //        contentObj.put(\"name\", logicClusterName);\n    //        contentObj.put(\"dataNodeSpec\", \"16-64Gi-3072g\");\n    //        contentObj.put(\"dataNodeNu\", 3);\n    //        contentObj.put(\"type\", ClusterResourceTypeEnum.PRIVATE.getCode());\n    //        workOrderDTO.setContentObj(contentObj);\n    //        Result<AriusWorkOrderInfoSubmittedVO> result = NormalOrderControllerMethod.submit(type, workOrderDTO);\n    //        Assertions.assertTrue(result.success());\n    //\n    //        // 通过工单\n    //        Long orderId = result.getData().getId();\n    //        WorkOrderProcessDTO processDTO = CustomDataSource.getWorkOrderProcessDTO(orderId);\n    //        Result<Void> result2 = NormalOrderControllerMethod.process(orderId, processDTO);\n    //        Assertions.assertTrue(result2.success());\n    //\n    //        // 运维人员点击分配集群\n    //        PhyClusterInfoSource.distributeCluster(phyClusterName, logicClusterName);\n    //\n    //        // 获取刚申请的逻辑集群 id\n    //        ClusterLogicConditionDTO condition = CustomDataSource.getClusterLogicConditionDTO(logicClusterName);\n    //        PaginationResult<ClusterLogicVO> result3 = ESLogicClusterOpV3ControllerMethod.pageGetConsoleClusterVOS(condition);\n    //        Assertions.assertTrue(result3.success());\n    //        Assertions.assertFalse(result3.getData().getBizData().isEmpty());\n    //        logicClusterInfo.logicClusterId = result3.getData().getBizData().get(0).getId();\n    //        return logicClusterInfo;\n    //    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/resource/PhyClusterInfoSource.java",
    "content": "package com.didichuxing.datachannel.arius.admin.resource;\n\n/**\n * @author cjm\n */\npublic class PhyClusterInfoSource {\n    //\n    //    @Data\n    //    public static class PhyClusterInfo {\n    //        private String phyClusterName;\n    //        private Long phyClusterId;\n    //\n    //        private ConsoleClusterPhyVO consoleClusterPhyVO;\n    //        // 接入物理集群时的请求体\n    //        private ClusterJoinDTO clusterJoinDTO;\n    //    }\n    //\n    //    /**\n    //     * 接入物理集群\n    //     */\n    //    public static PhyClusterInfo phyClusterJoin() throws IOException {\n    //        PhyClusterInfo phyClusterInfo = new PhyClusterInfo();\n    //        // 增加物理集群，不带有逻辑集群\n    //        phyClusterInfo.clusterJoinDTO = CustomDataSource.getClusterJoinDTO();\n    //        // Tuple<Long, String> 逻辑集群Id, 物理集群名称\n    //        Result<Tuple<Long, String>> result = ESPhyClusterControllerMethod.clusterJoin(phyClusterInfo.clusterJoinDTO);\n    //        Assertions.assertTrue(result.success());\n    //\n    //        phyClusterInfo.phyClusterName = phyClusterInfo.clusterJoinDTO.getCluster();\n    //\n    //        // 获取刚创建的物理集群id，先分页获取物理集群，根据名字查询\n    //        ClusterPhyConditionDTO dto = CustomDataSource.getClusterPhyConditionDTO(phyClusterInfo.clusterJoinDTO.getCluster());\n    //        PaginationResult<ConsoleClusterPhyVO> result2 = ESPhyClusterControllerMethod.pageGetConsoleClusterPhyVOS(dto);\n    //        List<ConsoleClusterPhyVO> data = result2.getData().getBizData();\n    //        for(ConsoleClusterPhyVO clusterPhyVO : data) {\n    //            if(clusterPhyVO.getCluster().equals(phyClusterInfo.clusterJoinDTO.getCluster())) {\n    //                phyClusterInfo.phyClusterId = Long.valueOf(clusterPhyVO.getId());\n    //                phyClusterInfo.consoleClusterPhyVO = clusterPhyVO;\n    //                break;\n    //            }\n    //        }\n    //        return phyClusterInfo;\n    //    }\n    //\n    //    /**\n    //     * 删除物理集群\n    //     */\n    //    public static void phyClusterRemove(String phyClusterName, Long phyClusterId) throws IOException {\n    //        // 删除物理集群\n    //        // 提交工单\n    //        WorkOrderDTO workOrderDTO = CustomDataSource.getWorkOrderDTO(\"clusterDelete\");\n    //        Map<String, Object> contentObj = new HashMap<>();\n    //        contentObj.put(\"phyClusterName\", phyClusterName);\n    //        contentObj.put(\"id\", phyClusterId);\n    //        workOrderDTO.setContentObj(contentObj);\n    //        Result<AriusWorkOrderInfoSubmittedVO> result = NormalOrderControllerMethod.submit(\"clusterDelete\", workOrderDTO);\n    //\n    //        Assertions.assertTrue(result.success());\n    //\n    //        // 通过工单，删除物理集群\n    //        Long orderId = result.getData().getId();\n    //        WorkOrderProcessDTO workOrderProcessDTO = CustomDataSource.getWorkOrderProcessDTO(orderId);\n    //        Result<Void> result2 = NormalOrderControllerMethod.process(orderId, workOrderProcessDTO);\n    //        Assertions.assertTrue(result2.success());\n    //    }\n    //\n    //    /**\n    //     * 分配集群，给用户申请的逻辑集群，分配当前物理集群\n    //     */\n    //    public static void distributeCluster(String phyClusterName, String logicClusterName) throws IOException {\n    //        // 物理集群新增 region\n    //\n    //        // 获取物理集群的空闲 region\n    //        Result<List<ClusterRegionVO>> result =\n    //                ESPhyClusterRegionControllerMethod.listPhyClusterRegions(phyClusterName, ClusterResourceTypeEnum.PRIVATE.getCode());\n    //        Assertions.assertTrue(result.success());\n    //        Long regionId = null;\n    //        for(ClusterRegionVO clusterRegionVO : result.getData()) {\n    //            if(AriusObjUtils.isBlack(clusterRegionVO.getLogicClusterIds()) || \"-1\".equals(clusterRegionVO.getLogicClusterIds())) {\n    //                // 如果该 region 没有绑定逻辑集群\n    //                regionId = clusterRegionVO.getId();\n    //                break;\n    //            }\n    //        }\n    //        if(regionId == null) {\n    //            // 如果没有 region，则新增\n    //            PhyClusterRegionInfoSource.PhyClusterRegionInfo phyClusterRegionInfo = new PhyClusterRegionInfoSource.PhyClusterRegionInfo();\n    //            regionId = phyClusterRegionInfo.getRegionId();\n    //        }\n    //        Assertions.assertNotNull(regionId);\n    //\n    //        String operateType = \"logicClusterCreate\";\n    //        WorkOrderDTO workOrderDTO = CustomDataSource.getWorkOrderDTO(operateType);\n    //        List<ClusterRegionDTO> clusterRegionDTOs = new ArrayList<>();\n    //        ClusterRegionDTO clusterRegionDTO = new ClusterRegionDTO();\n    //        clusterRegionDTO.setPhyClusterName(phyClusterName);\n    //        clusterRegionDTO.setId(regionId);\n    //        clusterRegionDTOs.add(clusterRegionDTO);\n    //\n    //        Map<String, Object> contentObj = new HashMap<>();\n    //        contentObj.put(\"clusterRegionDTOS\", clusterRegionDTOs);\n    //        contentObj.put(\"dataCenter\", \"cn\");\n    //        contentObj.put(\"dataNodeSpec\", \"\");\n    //        contentObj.put(\"dataNodeNu\", 0);\n    //        contentObj.put(\"configJson\", \"\");\n    //        contentObj.put(\"id\", 0);\n    //        contentObj.put(\"libraDepartment\", \"\");\n    //        contentObj.put(\"quota\", 0);\n    //        contentObj.put(\"name\", logicClusterName);\n    //        contentObj.put(\"type\", ClusterResourceTypeEnum.PRIVATE.getCode());\n    //        workOrderDTO.setContentObj(contentObj);\n    //\n    //        // 提交工单\n    //        Result<AriusWorkOrderInfoSubmittedVO> result2 = NormalOrderControllerMethod.submit(operateType, workOrderDTO);\n    //        Assertions.assertTrue(result2.success());\n    //\n    //        // 审批通过工单\n    //        Long orderId = result2.getData().getId();\n    //        WorkOrderProcessDTO processDTO = CustomDataSource.getWorkOrderProcessDTO(orderId);\n    //        Result<Void> result3 = NormalOrderControllerMethod.process(orderId, processDTO);\n    //        Assertions.assertTrue(result3.success());\n    //    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/resource/PhyClusterRegionInfoSource.java",
    "content": "package com.didichuxing.datachannel.arius.admin.resource;\n\n/**\n * @author cjm\n */\npublic class PhyClusterRegionInfoSource {\n    //\n    //    @Data\n    //    public static class PhyClusterRegionInfo {\n    //        private Long regionId;\n    //    }\n    //\n    //    public static void deleteRegion(Long regionId) throws IOException {\n    //        ESPhyClusterRegionControllerMethod.removeRegion(regionId);\n    //    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/resource/TemplateInfoSource.java",
    "content": "package com.didichuxing.datachannel.arius.admin.resource;\n\n/**\n * @author cjm\n */\npublic class TemplateInfoSource {\n    //\n    //    @Data\n    //    public static class TemplateInfo {\n    //        private Integer logicTemplateId;\n    //        private String templateName;\n    //        private ConsoleTemplateVO consoleTemplateVO;\n    //    }\n    //\n    //    public static TemplateInfo createTemplate(String phyClusterName, String logicClusterName, Long logicClusterId) throws IOException {\n    //        TemplateInfo templateInfo = new TemplateInfo();\n    //        return templateInfo;\n    //    }\n    //\n    //    public static void deleteTemplate(Integer logicTemplateId) throws IOException {\n    //        Result<Void> result = TemplateLogicV3ControllerMethod.deleteTemplate(logicTemplateId);\n    //        Assertions.assertTrue(result.success());\n    //    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-integration-test/src/test/java/com/didichuxing/datachannel/arius/admin/v3/op/cluster/logic/ESLogicClusterRegionTest.java",
    "content": ""
  },
  {
    "path": "arius-admin/arius-admin-metadata/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <artifactId>arius-admin</artifactId>\n       <version>${revision}${sha1}${changelist}</version>\n    </parent>\n\n    <artifactId>arius-admin-metadata</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-lang3</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-collections4</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.guava</groupId>\n            <artifactId>guava</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.annotation</groupId>\n                    <artifactId>javax.annotation-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <artifactId>log4j-to-slf4j</artifactId>\n                    <groupId>org.apache.logging.log4j</groupId>\n                </exclusion>\n                <exclusion>\n                    <groupId>ch.qos.logback</groupId>\n                    <artifactId>logback-classic</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>ch.qos.logback</groupId>\n                    <artifactId>logback-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.yaml</groupId>\n            <artifactId>snakeyaml</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>net.minidev</groupId>\n            <artifactId>json-smart</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-aop</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.annotation</groupId>\n                    <artifactId>javax.annotation-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.hibernate</groupId>\n                    <artifactId>hibernate-validator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>ch.qos.logback</groupId>\n                    <artifactId>logback-classic</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>ch.qos.logback</groupId>\n                    <artifactId>logback-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-webmvc</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>javax.servlet-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-web</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.hibernate.validator</groupId>\n            <artifactId>hibernate-validator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.tomcat.embed</groupId>\n            <artifactId>tomcat-embed-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.fasterxml.jackson.datatype</groupId>\n            <artifactId>jackson-datatype-jsr310</artifactId>\n        </dependency>\n\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-common</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-log</artifactId>\n        </dependency>\n    </dependencies>\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/AbstractMetaDataJob.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport java.util.List;\n\npublic abstract class AbstractMetaDataJob {\n    protected static final ILog LOGGER           = LogFactory.getLog(AbstractMetaDataJob.class);\n    public static final int     WARN_BLOCK_SIZE  = 10;\n    public static final int     ERROR_BLOCK_SIZE = 30;\n\n    public abstract Object handleJobTask(String params);\n\n    public Object handleBrocastJobTask(String params, String curretnWorker, List<String> allWorders) {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/ClusterMonitorJobHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.JOB_SUCCESS;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.PHY_CLUSTER;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsCells;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterTaskStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterTaskStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PercentilesEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.metrics.MetricsMonitorClusterEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.HttpHostUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.monitortask.AriusMetaJobClusterDistributeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.AbstractMetaDataJob;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.MonitorMetricsSender;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsClusterTaskInfoESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsIndexInfoESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsNodeInfoESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.template.TemplateAccessESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport com.didiglobal.knowframework.observability.Observability;\nimport com.didiglobal.knowframework.observability.conponent.thread.ContextExecutorService;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\n\nimport java.util.*;\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.concurrent.BasicThreadFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.ReflectionUtils;\n\n/**\n * 集群维度采集监控数据，包含 es节点存活检查；es集群tps/qps掉底报警\n * @author ohushenglin_v\n */\n@Component\npublic class ClusterMonitorJobHandler extends AbstractMetaDataJob {\n\n    private static final double                  SLA       = 0.9999;\n\n    @Autowired\n    private ClusterPhyService                    clusterPhyService;\n\n    @Autowired\n    private IndexTemplatePhyService              indexTemplatePhyService;\n\n    @Autowired\n    private ProjectService                       projectService;\n\n    @Autowired\n    private ESClusterService                     esClusterService;\n\n    @Autowired\n    private MonitorMetricsSender                 monitorMetricsSender;\n\n    @Autowired\n    private AriusStatsIndexInfoESDAO             ariusStatsIndexInfoEsDao;\n\n    @Autowired\n    private AriusStatsNodeInfoESDAO              ariusStatsNodeInfoEsDao;\n\n    @Autowired\n    private AriusStatsClusterTaskInfoESDAO       ariusStatsClusterTaskInfoESDAO;\n\n    @Autowired\n    private AriusMetaJobClusterDistributeService ariusMetaJobClusterDistributeService;\n\n    @Autowired\n    private TemplateAccessESDAO                  templateAccessESDAO;\n\n    private final static String                  hostName  = HttpHostUtil.HOST_NAME;\n\n    @Value(\"${monitorJob.threadPool.initsize:20}\")\n    private int                                  poolSize;\n\n    /**\n     * maxPoolSize，当前monitorjob能支持的最大集群采集个数，\n     * 超过maxPoolSize的集群不会被采集，保证maxPoolSize个集群采集的稳定性\n     */\n    @Value(\"${monitorJob.threadPool.maxsize:30}\")\n    private int                                  maxPoolSize;\n\n    private ExecutorService threadPool;\n\n    private FutureUtil<Void>                     futureUtil;\n\n    private long                                 timestamp = CommonUtils\n        .monitorTimestamp2min(System.currentTimeMillis());\n\n    @PostConstruct\n    public void init() {\n        futureUtil = FutureUtil.init(\"ClusterMonitorJobHandler\", 3 * maxPoolSize, 3 * maxPoolSize, 100);\n    }\n\n    @Override\n    public Object handleJobTask(String params) {\n        LOGGER.info(\"class=ClusterMonitorJobHandler||method=handleJobTask||params={}\", params);\n        // 处理逻辑集群的统计数据\n        List<ESClusterStats> esClusterStatsList = Lists.newCopyOnWriteArrayList();\n\n        // 处理集群的统计数据,处理保留集群状态至DB, 后端分页条件中需要使用状态字段\n        Map<ClusterPhy, ESClusterHealthResponse> clusterHealthResponseMap = handlePhysicalClusterStats(\n            esClusterStatsList);\n\n        SpringTool\n            .publish(new MetricsMonitorClusterEvent(this, esClusterStatsList, clusterHealthResponseMap, hostName));\n\n        return JOB_SUCCESS;\n    }\n\n    /**************************************** private methods ****************************************/\n    private Map<ClusterPhy, ESClusterHealthResponse> handlePhysicalClusterStats(List<ESClusterStats> esClusterStatsList) {\n        this.timestamp = CommonUtils.monitorTimestamp2min(System.currentTimeMillis());\n\n        // 获取单台机器监控采集的集群名称列表, 当分布式部署分组采集，可分摊采集压力\n        List<ClusterPhy> monitorCluster = ariusMetaJobClusterDistributeService.getSingleMachineMonitorCluster(hostName);\n\n        final Map<String, Integer> clusterPhyName2TemplateCountMap = indexTemplatePhyService\n            .getClusterTemplateCountMap();\n\n        int projectIdCount = calcAppNu();\n\n        Map<ClusterPhy, ESClusterHealthResponse> clusterHealthResponseMap = Maps.newConcurrentMap();\n        int clusterSize = monitorCluster.size();\n        Map<String, Future> futureMap = new HashMap<>(monitorCluster.size());\n        // 1. build multiple clusters status\n        monitorCluster.forEach(dataSource -> {\n            if (checkThreadPool()) {\n                futureMap.put(dataSource.getCluster(), threadPool.submit(() -> {\n                    try {\n                        ESClusterHealthResponse clusterHealthResponse = esClusterService\n                            .syncGetClusterHealth(dataSource.getCluster());\n                        List<ESClusterStats> esClusterStatusList = buildEsClusterStatusWithPercentiles(clusterSize,\n                            dataSource, clusterPhyName2TemplateCountMap, projectIdCount, clusterHealthResponse);\n\n                        monitorMetricsSender.sendClusterStats(esClusterStatusList);\n                        buildAndSendTaskStats(timestamp, dataSource);\n\n                        if (clusterHealthResponse == null) {\n                            clusterHealthResponse = new ESClusterHealthResponse();\n                            clusterHealthResponse.setClusterName(dataSource.getCluster());\n                            clusterHealthResponse.setStatus(ClusterHealthEnum.UNKNOWN.getDesc());\n                            clusterHealthResponse.setActiveShards(0);\n                        }\n                        clusterHealthResponseMap.put(dataSource, clusterHealthResponse);\n\n                        esClusterStatsList.addAll(esClusterStatusList);\n\n                        // 更新物理集群的健康度信息和活跃的分片数目信息\n                        handleSaveClusterHealthToDB(dataSource, clusterHealthResponse);\n\n                    } catch (Exception e) {\n                        LOGGER.error(\n                            \"class=ClusterMonitorJobHandler||method=handlePhysicalClusterStats||clusterPhyName={}||clusterPhyDataCenter={}\"\n                                     + \"||errMsg= dataSource mismatch\",\n                            dataSource.getCluster(), dataSource.getDataCenter(), e);\n                    }\n                }));\n            }\n        });\n\n        if (MapUtils.isNotEmpty(futureMap)) {\n            futureMap.forEach((key, val) -> {\n                try {\n                    val.get(50, TimeUnit.SECONDS);\n                } catch (Exception e) {\n                    val.cancel(true);\n                    LOGGER.error(\n                        \"class=ClusterMonitorJobHandler||method=handlePhysicalClusterStats||clusterPhyName={}||errMsg= dataSource mismatch\",\n                        key);\n                }\n            });\n        }\n\n        return clusterHealthResponseMap;\n    }\n\n    private void buildAndSendTaskStats(long timestamp, ClusterPhy dataSource) throws ESOperateException {\n        List<ESClusterTaskStatsResponse> taskStatsResponses = esClusterService\n            .syncGetClusterTaskStats(dataSource.getCluster());\n\n        taskStatsResponses.sort((stats1, stats2) -> (int) (stats1.getRunningTime() - stats2.getRunningTime()));\n\n        List<ESClusterTaskStats> esClusterTaskStatsList = taskStatsResponses.stream().map(x -> {\n            ESClusterTaskStats esClusterTaskStats = new ESClusterTaskStats();\n            esClusterTaskStats.setCluster(dataSource.getCluster());\n            esClusterTaskStats.setDataCenter(dataSource.getDataCenter());\n            esClusterTaskStats.setPhysicCluster(PHY_CLUSTER);\n            esClusterTaskStats.setTimestamp(timestamp);\n            esClusterTaskStats.setMetrics(x);\n            return esClusterTaskStats;\n        }).collect(Collectors.toList());\n\n        monitorMetricsSender.sendClusterTaskStats(esClusterTaskStatsList);\n    }\n\n    /**\n     * 获取 提交到ES数据格式 集群状态\n     * @param clusterNum 集群数量\n     * @param dataSource 集群信息\n     * @param clusterPhyName2TemplateCountMap  集群中的模板数量\n     * @param projectIdCount  应用数量\n     * @return 集群状态\n     */\n    private List<ESClusterStats> buildEsClusterStatusWithPercentiles(Integer clusterNum, ClusterPhy dataSource,\n                                                                     Map<String, Integer> clusterPhyName2TemplateCountMap,\n                                                                     Integer projectIdCount,\n                                                                     ESClusterHealthResponse healthResponse) {\n\n        List<ESClusterStats> esClusterStatsList = Lists.newArrayList();\n\n        //获取不同分位值的指标\n        Map<String, ESClusterStatsCells> percentilesType2ESClusterStatsCellsMap = getPhysicalClusterStatsPercentiles(\n            dataSource, healthResponse, clusterPhyName2TemplateCountMap, projectIdCount, clusterNum);\n\n        percentilesType2ESClusterStatsCellsMap.forEach((percentilesType, esClusterStatsCells) -> {\n            ESClusterStats esClusterStats = new ESClusterStats();\n            esClusterStats.setStatis(esClusterStatsCells);\n            esClusterStats.setCluster(dataSource.getCluster());\n            esClusterStats.setPercentilesType(percentilesType);\n            esClusterStats.setPhysicCluster(PHY_CLUSTER);\n            esClusterStats.setTimestamp(this.timestamp);\n            esClusterStats.setDataCenter(dataSource.getDataCenter());\n\n            esClusterStatsList.add(esClusterStats);\n        });\n\n        return esClusterStatsList;\n    }\n\n    /**\n     * 采集不同分位图的指标数据\n     * @param dataSource 集群信息\n     * @param healthResponse    健康信息\n     * @param clusterPhyName2TemplateCountMap   集群中模板数量\n     * @param projectIdCount    应用数量\n     * @param clusterNum    集群数量\n     * @return  Map<String, ESClusterStatsCells>\n     */\n    private Map<String, ESClusterStatsCells> getPhysicalClusterStatsPercentiles(ClusterPhy dataSource,\n                                                                                ESClusterHealthResponse healthResponse,\n                                                                                Map<String, Integer> clusterPhyName2TemplateCountMap,\n                                                                                Integer projectIdCount,\n                                                                                Integer clusterNum) {\n        Map<String, ESClusterStatsCells> percentilesType2ESClusterStatsCellsMap = Maps.newHashMap();\n        String clusterName = dataSource.getCluster();\n        if (AriusObjUtils.isNull(clusterName)) {\n            LOGGER.warn(\n                \"class=ClusterMonitorJobHandler||method=getPhysicalClusterStatsPercentiles||errMsg=clusterName is empty\");\n            return percentilesType2ESClusterStatsCellsMap;\n        }\n\n        ESClusterStatsCells esClusterStatsCells = buildForBasicInfo(dataSource, healthResponse,\n            clusterPhyName2TemplateCountMap, projectIdCount, clusterNum);\n\n        AtomicReference<Map<String, Double>> clusterCpuAvgAndPercentilesAtomic = new AtomicReference<>();\n        AtomicReference<Map<String, Double>> clusterDiskFreeUsagePercentAvgAndPercentilesAtomic = new AtomicReference<>();\n        AtomicReference<Map<String, Double>> clusterCpuLoad1MinAvgAndPercentilesAtomic = new AtomicReference<>();\n        AtomicReference<Map<String, Double>> clusterCpuLoad5MinAvgAndPercentilesAtomic = new AtomicReference<>();\n        AtomicReference<Map<String, Double>> clusterCpuLoad15MinAvgAndPercentilesAtomic = new AtomicReference<>();\n        AtomicReference<Map<String, Double>> clusterTaskCostMinAvgAndPercentilesAtomic = new AtomicReference<>();\n\n        futureUtil\n            .runnableTask(() -> clusterCpuAvgAndPercentilesAtomic\n                .set(ariusStatsNodeInfoEsDao.getClusterCpuAvgAndPercentiles(clusterName)))\n            .runnableTask(() -> clusterDiskFreeUsagePercentAvgAndPercentilesAtomic\n                .set(ariusStatsNodeInfoEsDao.getClusterDiskFreeUsagePercentAvgAndPercentiles(clusterName)))\n            .runnableTask(() -> clusterCpuLoad1MinAvgAndPercentilesAtomic\n                .set(ariusStatsNodeInfoEsDao.getClusterCpuLoad1MinAvgAndPercentiles(clusterName)))\n            .runnableTask(() -> clusterCpuLoad5MinAvgAndPercentilesAtomic\n                .set(ariusStatsNodeInfoEsDao.getClusterCpuLoad5MinAvgAndPercentiles(clusterName)))\n            .runnableTask(() -> clusterCpuLoad15MinAvgAndPercentilesAtomic\n                .set(ariusStatsNodeInfoEsDao.getClusterCpuLoad15MinAvgAndPercentiles(clusterName)))\n            .runnableTask(() -> clusterTaskCostMinAvgAndPercentilesAtomic\n                .set(ariusStatsClusterTaskInfoESDAO.getTaskCostMinAvgAndPercentiles(clusterName)))\n            .waitExecute();\n\n        for (String type : PercentilesEnum.listUsefulType()) {\n            ESClusterStatsCells esClusterStatsCellDeepCopy = ConvertUtil.obj2Obj(esClusterStatsCells,\n                ESClusterStatsCells.class);\n\n            buildForPercentiles(esClusterStatsCellDeepCopy, type, clusterCpuAvgAndPercentilesAtomic.get(),\n                clusterCpuLoad1MinAvgAndPercentilesAtomic.get(), clusterCpuLoad5MinAvgAndPercentilesAtomic.get(),\n                clusterCpuLoad15MinAvgAndPercentilesAtomic.get(),\n                clusterDiskFreeUsagePercentAvgAndPercentilesAtomic.get(),\n                clusterTaskCostMinAvgAndPercentilesAtomic.get());\n\n            percentilesType2ESClusterStatsCellsMap.put(type, esClusterStatsCellDeepCopy);\n\n        }\n\n        return percentilesType2ESClusterStatsCellsMap;\n    }\n\n    /**\n     * @param esClusterStatsCellDeepCopy                       集群维度统计信息\n     * @param type                                             avg、分位类型(99、95、75、55)\n     * @param clusterCpuAvgAndPercentiles                      集群cpu平均值和分位值(key:99, value:值)\n     * @param clusterDiskFreeUsagePercentAvgAndPercentiles     集群节点磁盘空闲率平均值和分位值(key:99, value:值)\n     * @param clusterCpuLoad1MinAvgAndPercentiles              集群cpu load1平均值和分位值(key:99, value:值)\n     * @param clusterCpuLoad5MinAvgAndPercentiles              集群cpu load5平均值和分位值(key:99, value:值)\n     * @param clusterCpuLoad15MinAvgAndPercentiles             集群cpu load15平均值和分位值(key:99, value:值)\n     * @param clusterTaskCostMinAvgAndPercentiles              集群task cost平均值和分位值(key:99, value:值)\n     */\n    private void buildForPercentiles(ESClusterStatsCells esClusterStatsCellDeepCopy, String type,\n                                     Map<String, Double> clusterCpuAvgAndPercentiles,\n                                     Map<String, Double> clusterCpuLoad1MinAvgAndPercentiles,\n                                     Map<String, Double> clusterCpuLoad5MinAvgAndPercentiles,\n                                     Map<String, Double> clusterCpuLoad15MinAvgAndPercentiles,\n                                     Map<String, Double> clusterDiskFreeUsagePercentAvgAndPercentiles,\n                                     Map<String, Double> clusterTaskCostMinAvgAndPercentiles) {\n        if (null != clusterCpuAvgAndPercentiles && null != clusterCpuAvgAndPercentiles.get(type)) {\n            esClusterStatsCellDeepCopy.setCpuUsage(clusterCpuAvgAndPercentiles.get(type));\n        }\n\n        if (null != clusterCpuLoad1MinAvgAndPercentiles && null != clusterCpuLoad1MinAvgAndPercentiles.get(type)) {\n            esClusterStatsCellDeepCopy.setCpuLoad1M(clusterCpuLoad1MinAvgAndPercentiles.get(type));\n        }\n\n        if (null != clusterCpuLoad5MinAvgAndPercentiles && null != clusterCpuLoad5MinAvgAndPercentiles.get(type)) {\n            esClusterStatsCellDeepCopy.setCpuLoad5M(clusterCpuLoad5MinAvgAndPercentiles.get(type));\n        }\n\n        if (null != clusterCpuLoad15MinAvgAndPercentiles && null != clusterCpuLoad15MinAvgAndPercentiles.get(type)) {\n            esClusterStatsCellDeepCopy.setCpuLoad15M(clusterCpuLoad15MinAvgAndPercentiles.get(type));\n        }\n\n        String realType = convertSpecialTypeForDiskFreeUsage(type);\n        if (null != clusterDiskFreeUsagePercentAvgAndPercentiles\n            && null != clusterDiskFreeUsagePercentAvgAndPercentiles.get(realType)) {\n            esClusterStatsCellDeepCopy.setDiskUsage(1 - clusterDiskFreeUsagePercentAvgAndPercentiles.get(realType));\n        }\n\n        if (null != clusterTaskCostMinAvgAndPercentiles && null != clusterTaskCostMinAvgAndPercentiles.get(type)) {\n            esClusterStatsCellDeepCopy.setTaskCost(clusterTaskCostMinAvgAndPercentiles.get(type));\n        }\n    }\n\n    private String convertSpecialTypeForDiskFreeUsage(String type) {\n        if (PercentilesEnum.ST99.getType().equals(type)) {\n            return PercentilesEnum.ST1.getType();\n        }\n\n        if (PercentilesEnum.ST95.getType().equals(type)) {\n            return PercentilesEnum.ST5.getType();\n        }\n\n        if (PercentilesEnum.ST75.getType().equals(type)) {\n            return PercentilesEnum.ST25.getType();\n        }\n\n        if (PercentilesEnum.ST55.getType().equals(type)) {\n            return PercentilesEnum.ST45.getType();\n        }\n\n        return PercentilesEnum.AVG.getType();\n    }\n\n    /**\n     * 构建集群相关统计信息\n     * @param dataSource 集群信息\n     * @param healthResponse    健康信息\n     * @param clusterPhyName2TemplateCountMap   集群中模板数量\n     * @param projectId    应用数量\n     * @param clusterNum    集群数量\n     * @return  ESClusterStatsCells\n    */\n    private ESClusterStatsCells buildForBasicInfo(ClusterPhy dataSource, ESClusterHealthResponse healthResponse,\n                                                  Map<String, Integer> clusterPhyName2TemplateCountMap,\n                                                  Integer projectId, Integer clusterNum) {\n        ESClusterStatsCells esClusterStatsBean = new ESClusterStatsCells();\n        if (null != healthResponse) {\n            esClusterStatsBean.setStatus(healthResponse.getStatus());\n            esClusterStatsBean.setStatusType(ClusterHealthEnum.valuesOf(healthResponse.getStatus()).getCode());\n        } else {\n            esClusterStatsBean.setStatus(ClusterHealthEnum.UNKNOWN.getDesc());\n            esClusterStatsBean.setStatusType(ClusterHealthEnum.UNKNOWN.getCode());\n        }\n\n        if (null != dataSource) {\n            esClusterStatsBean.setClusterName(dataSource.getCluster());\n            esClusterStatsBean.setLevel(dataSource.getLevel());\n            esClusterStatsBean.setClusterNu(clusterNum);\n            esClusterStatsBean.setAppNu(projectId);\n            esClusterStatsBean.setSla(SLA);\n\n            int totalTemplateNu = clusterPhyName2TemplateCountMap.getOrDefault(dataSource.getCluster(), 0);\n            esClusterStatsBean.setTotalTemplateNu(totalTemplateNu);\n\n            handlePhysicalClusterStatsForSum(dataSource.getCluster(), esClusterStatsBean);\n        }\n        return esClusterStatsBean;\n    }\n\n    private void handlePhysicalClusterStatsForSum(String clusterName, ESClusterStatsCells esClusterStats) {\n        // 这里会有多次es查询，做成并发的以免http接口超时\n        futureUtil.runnableTask(() -> esClusterStats.setReadTps(ariusStatsIndexInfoEsDao.getClusterQps(clusterName)))\n            .runnableTask(() -> esClusterStats.setWriteTps(ariusStatsNodeInfoEsDao.getClusterTps(clusterName)))\n            .runnableTask(() -> esClusterStats.setRecvTransSize(ariusStatsNodeInfoEsDao.getClusterRx(clusterName)))\n            .runnableTask(() -> esClusterStats.setSendTransSize(ariusStatsNodeInfoEsDao.getClusterTx(clusterName)))\n            .runnableTask(() -> setClusterOtherStats(clusterName, esClusterStats))\n            .runnableTask(() -> esClusterStats.setQueryTimesPreDay(templateAccessESDAO.getYesterDayAllTemplateAccess(clusterName)))\n            .runnableTask(() -> esClusterStats.setSearchLatency(calcSearchLatencyAvg(clusterName)))\n            .runnableTask(() -> esClusterStats.setIndexingLatency(calcIndexingLatencyAvg(clusterName)))\n            .waitExecute();\n    }\n\n    /**\n     * 计算SearchLatency\n     *    计算逻辑：\n     *    （集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis差值累加值）\n     *        除以\n     *    （节点间隔时间nodes.{nodeName}.indices.search.query_total差值累加值）\n     *\n     * @param clusterName   集群名称\n     * @return\n     */\n    private double calcSearchLatencyAvg(String clusterName){\n        // 获取分子：所有节点的indices.search.query_time_in_millis差值累加值\n        double searchLatencySum = ariusStatsNodeInfoEsDao.getClusterSearchLatencySum(clusterName);\n        // 获取分母：所有节点indices.search.query_total差值累加值\n        double searchQueryTotal = ariusStatsNodeInfoEsDao.getClusterSearchQueryTotal(clusterName);\n        return searchQueryTotal == 0 ? 0 : (searchLatencySum / searchQueryTotal);\n    }\n\n    /**\n     * 计算IndexingLatency\n     *    计算逻辑：\n     *    （集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis差值累加值）\n     *         除以\n     *    （节点间隔时间nodes.{nodeName}.indices.docs.count差值累加值）\n     *\n     * @param clusterName\n     * @return\n     */\n    private double calcIndexingLatencyAvg(String clusterName){\n        // 获取分子：所有节点的indices.indexing.index_time_in_millis差值累加值\n        double indexingLatencySum = ariusStatsNodeInfoEsDao.getClusterIndexingLatencySum(clusterName);\n        // 获取分母：所有节点的indices.docs.count差值累加值\n        double indexingDocSum = ariusStatsNodeInfoEsDao.getClusterIndexingDocSum(clusterName);\n        return indexingDocSum == 0 ? 0 : (indexingLatencySum / indexingDocSum);\n    }\n\n    /**\n     * 设置集群其他状态值\n     *\n     * @param clusterName   集群名称\n     * @param esClusterStats    集群状态\n     */\n    private void setClusterOtherStats(String clusterName, ESClusterStatsCells esClusterStats) {\n        ESClusterStatsResponse clusterStats = null;\n        try {\n\n            clusterStats = esClusterService.syncGetClusterStats(clusterName);\n            if (Objects.isNull(clusterStats)) {\n                return;\n            }\n\n            //索引相关\n            esClusterStats.setTotalIndicesNu(clusterStats.getIndexCount());\n            esClusterStats.setShardNu(clusterStats.getTotalShard());\n            esClusterStats.setTotalDocNu(clusterStats.getDocsCount());\n            esClusterStats.setEsNodeNu(clusterStats.getTotalNodes());\n\n            //节点相关\n            esClusterStats.setNumberNodes(clusterStats.getTotalNodes());\n            esClusterStats.setNumberMasterNodes(clusterStats.getNumberMasterNodes());\n            esClusterStats.setNumberClientNodes(clusterStats.getNumberClientNodes());\n            esClusterStats.setNumberDataNodes(clusterStats.getNumberDataNodes());\n            esClusterStats.setNumberIngestNodes(clusterStats.getNumberIngestNodes());\n\n            //节点使用情况\n            esClusterStats.setTotalStoreSize(clusterStats.getTotalFs().getBytes());\n            esClusterStats.setFreeStoreSize(clusterStats.getFreeFs().getBytes());\n\n            esClusterStats.setStoreSize(esClusterStats.getTotalStoreSize() - esClusterStats.getFreeStoreSize());\n            esClusterStats.setIndexStoreSize(esClusterStats.getTotalStoreSize() - esClusterStats.getFreeStoreSize());\n\n            //集群内存相关\n            esClusterStats.setMemUsed(clusterStats.getMemUsed().getGb());\n            esClusterStats.setMemFree(clusterStats.getMemFree().getGb());\n            esClusterStats.setMemTotal(clusterStats.getMemTotal().getGb());\n            esClusterStats.setMemFreePercent(clusterStats.getMemFreePercent());\n            esClusterStats.setMemUsedPercent(clusterStats.getMemUsedPercent());\n\n            //集群shard相关\n            ESClusterHealthResponse clusterHealthResponse = esClusterService.syncGetClusterHealth(clusterName);\n            if (null == clusterHealthResponse) {\n                return;\n            }\n            esClusterStats.setUnAssignedShards(clusterHealthResponse.getUnassignedShards());\n            esClusterStats.setNumberPendingTasks(clusterHealthResponse.getNumberOfPendingTasks());\n\n            //集群task相关\n            esClusterStats.setTaskCount(ariusStatsClusterTaskInfoESDAO.getTaskCount(clusterName));\n\n        } catch (Exception e) {\n            LOGGER.error(\"class=ClusterMonitorJobHandler||method=setClusterOtherStats||clusterName={}, clusterStats={}\",\n                clusterName, clusterStats, e);\n        }\n    }\n\n    /**\n     * 获取应用数量\n     */\n    private int calcAppNu() {\n        return projectService.getProjectBriefList().size();\n    }\n\n    private void handleSaveClusterHealthToDB(ClusterPhy clusterPhy, ESClusterHealthResponse esClusterHealthResponse) {\n        ClusterPhyDTO esClusterDTO = new ClusterPhyDTO();\n        try {\n            esClusterDTO.setId(clusterPhy.getId());\n\n            if (null == esClusterHealthResponse) {\n                esClusterDTO.setHealth(ClusterHealthEnum.UNKNOWN.getCode());\n                esClusterDTO.setActiveShardNum(0L);\n            } else {\n                ClusterHealthEnum clusterHealthEnum = ClusterHealthEnum.valuesOf(esClusterHealthResponse.getStatus());\n                esClusterDTO.setHealth(clusterHealthEnum.getCode());\n                esClusterDTO.setActiveShardNum(esClusterHealthResponse.getActiveShards());\n            }\n            clusterPhyService.editCluster(esClusterDTO, AriusUser.SYSTEM.getDesc());\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=ClusterMonitorJobHandler||method=handleSaveClusterHealthToDB||clusterName={}, clusterStats={}\",\n                clusterPhy.getCluster(),\n                null != esClusterHealthResponse && null != esClusterHealthResponse.getStatus()\n                    ? esClusterHealthResponse.getStatus()\n                    : null,\n                e);\n        }\n    }\n\n    /**\n     * 校验线程资源是否合理\n     * @return boolean\n     */\n    private boolean checkThreadPool() {\n        if (threadPool == null || threadPool.isShutdown()) {\n            threadPool = Observability.wrap(new ThreadPoolExecutor(poolSize, maxPoolSize + 10, 0L, TimeUnit.MILLISECONDS,\n                    new LinkedBlockingQueue<>(100),\n                    new BasicThreadFactory.Builder().namingPattern(\"cluster-monitor-cluster-data-collect-%d\").build()));\n        }\n\n        long blockSize = Optional.ofNullable(ReflectionUtils.findField(ContextExecutorService.class, \"delegate\")).map(field -> {\n            field.setAccessible(true);\n            return (ThreadPoolExecutor) ReflectionUtils.getField(field, threadPool);\n        }).map(ThreadPoolExecutor::getQueue).map(Collection::size).orElse(0);\n\n        if (blockSize > WARN_BLOCK_SIZE) {\n            LOGGER.warn(\n                \"class=ClusterMonitorJobHandler||method=checkThreadPool||blockSize={}||msg=collect thread pool has block task\",\n                blockSize);\n        }\n\n        if (blockSize > ERROR_BLOCK_SIZE) {\n            LOGGER.error(\n                \"class=ClusterMonitorJobHandler||method=checkThreadPool||blockSize={}||msg=collect thread pool is too busy. thread pool recreate\",\n                blockSize);\n            threadPool.shutdownNow();\n            threadPool = null;\n            return false;\n        }\n\n        return true;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/LogicClusterMonitorJobHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.JOB_SUCCESS;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.LOGIC_CLUSTER;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.stats.ClusterLogicStats;\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexCatCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsCells;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.stats.ClusterLogicStatsPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PercentilesEnum;\nimport com.didichuxing.datachannel.arius.admin.common.event.metrics.MetricsMonitorLogicClusterEvent;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.monitortask.AriusMetaJobClusterDistributeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.AbstractMetaDataJob;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.MonitorMetricsSender;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.ESClusterLogicStatsService;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsClusterTaskInfoESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsIndexInfoESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsNodeInfoESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.clusterindex.IndexStatusResult;\nimport com.google.common.collect.Lists;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.*;\nimport com.google.common.collect.Maps;\n\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\n\n/**\n * 集群维度采集监控数据，包含 es节点存活检查；es集群tps/qps掉底报警\n * @author ohushenglin_v\n */\n@Component\npublic class LogicClusterMonitorJobHandler extends AbstractMetaDataJob {\n\n    @Value(\"${monitorJob.threadPool.maxsize:30}\")\n    private int                                  maxPoolSize;\n    @Autowired\n    private ClusterLogicService                  clusterLogicService;\n    @Autowired\n    private AriusMetaJobClusterDistributeService ariusMetaJobClusterDistributeService;\n    @Autowired\n    private MonitorMetricsSender                 monitorMetricsSender;\n    @Autowired\n    private ESClusterLogicStatsService           clusterLogicStaticsService;\n    @Autowired\n    private ClusterRegionService                 clusterRegionService;\n    @Autowired\n    private ClusterPhyService                    clusterPhyService;\n    @Autowired\n    private ClusterRoleHostService               clusterRoleHostService;\n    @Autowired\n    private ESIndexCatService                    esIndexCatService;\n    @Autowired\n    private AriusStatsNodeInfoESDAO              ariusStatsNodeInfoEsDao;\n    @Autowired\n    private AriusStatsClusterTaskInfoESDAO       ariusStatsClusterTaskInfoESDAO;\n\n    private FutureUtil<ESClusterStats>           clusterLogicFutureUtil;\n    private final String hostName                = HttpHostUtil.HOST_NAME;\n\n\n\n    private static final Integer SEARCH_SIZE     = 5000;\n\n\n    private long                                 timestamp = CommonUtils\n            .monitorTimestamp2min(System.currentTimeMillis());\n\n    @Override\n    public Object handleJobTask(String params) {\n        handleLogicClusterStats();\n        return JOB_SUCCESS;\n    }\n\n    @PostConstruct\n    public void init() {\n        clusterLogicFutureUtil = FutureUtil.init(\"ClusterLogicMonitorJobHandler\", 3 * maxPoolSize, 3 * maxPoolSize,\n            100);\n    }\n\n    private void handleLogicClusterStats() {\n        // 获取单台机器监控采集的集群名称列表, 当分布式部署分组采集，可分摊采集压力\n        List<ClusterPhy> monitorCluster = ariusMetaJobClusterDistributeService.getSingleMachineMonitorCluster(hostName);\n        // 2. do handle\n        if (CollectionUtils.isNotEmpty(monitorCluster)) {\n            Set<String> monitorClusterSet = monitorCluster.stream().map(ClusterPhy::getCluster)\n                .collect(Collectors.toSet());\n            doHandleLogicClusterStats(monitorClusterSet);\n        }\n    }\n\n    private void doHandleLogicClusterStats(Set<String> monitorClusterSet) {\n        List<ClusterRegion> regionList = clusterRegionService.listRegionByPhyClusterNames(Lists.newArrayList(monitorClusterSet)).stream()\n                .filter(clusterRegion -> StringUtils.isNotBlank(clusterRegion.getLogicClusterIds())\n                        && !AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID.equals(clusterRegion.getLogicClusterIds()))\n                .collect(Collectors.toList());\n        List<Long> logicClusterIds = regionList.stream().map(clusterRegion -> ListUtils.string2StrList(clusterRegion.getLogicClusterIds()))\n                .flatMap(Collection::stream).distinct().map(Long::parseLong).collect(Collectors.toList());\n        List<ClusterLogic> clusterLogicList = clusterLogicService.getClusterLogicListByIds(logicClusterIds);\n        List<ClusterRoleHost> clusterRoleHostsList = clusterRoleHostService.listNodesByClusters(Lists.newArrayList(monitorClusterSet)).stream()\n                .filter(i -> Objects.nonNull(i.getRegionId()) && !Objects.equals(-1, i.getRegionId())).collect(Collectors.toList());\n        List<ClusterPhy> phyClusterList = clusterPhyService.listClustersByNames(Lists.newArrayList(monitorClusterSet));\n        List<IndexCatCell> allCatIndexNameList = esIndexCatService.syncGetAllCatIndexNameListByClusters(SEARCH_SIZE,Lists.newArrayList(monitorClusterSet))\n                .stream().distinct().collect(Collectors.toList());\n        if (CollectionUtils.isEmpty(clusterLogicList) || CollectionUtils.isEmpty(regionList)\n                || CollectionUtils.isEmpty(clusterRoleHostsList) || CollectionUtils.isEmpty(phyClusterList)) {\n            LOGGER.info(\"class=LogicClusterMonitorJobHandler||method=doHandleLogicClusterStats||msg=logicClusters is empty\");\n            return;\n        }\n        if (CollectionUtils.isEmpty(allCatIndexNameList)) {\n            LOGGER.info(\"class=LogicClusterMonitorJobHandler||method=doHandleLogicClusterStats||msg=indices is empty\");\n            return;\n        }\n        //物理集群和region\n        Map<String, List<ClusterRegion>> phyClusterRegionMap = ConvertUtil.list2MapOfList(regionList,\n                clusterRegion -> clusterRegion.getPhyClusterName(), clusterRegionList -> clusterRegionList);\n        //regionId和nodeName\n        Map<Integer, List<String>> regionNodeMap = ConvertUtil.list2MapOfList(clusterRoleHostsList, ClusterRoleHost::getRegionId,\n                ClusterRoleHost::getNodeSet);\n        //物理集群和物理信息的关系\n        Map<String, ClusterPhy> ClusterPhyMap = ConvertUtil.list2Map(phyClusterList, clusterPhy -> clusterPhy.getCluster(),\n                clusterPhy -> clusterPhy);\n        //逻辑集群和索引的关系\n        Map<Long, List<String>> logicClusterIndicesNameMap = ConvertUtil.list2MapOfList(allCatIndexNameList,\n                IndexCatCell::getResourceId, IndexCatCell::getIndex);\n        //逻辑集群对象\n        Map<Long, ClusterLogic> longClusterLogicMap = ConvertUtil.list2Map(clusterLogicList,\n                ClusterLogic::getId, clusterLogic -> clusterLogic);\n        //物理集群和逻辑集群\n        Map<String, List<ClusterLogic>> phyClusterNameLogicCluster = Maps.newHashMap();\n        Map<String, List<String>> phyClusterNameLogicCLusterIds = regionList.stream()\n                .collect(Collectors.toMap(ClusterRegion::getPhyClusterName, clusterRegion ->\n                                Lists.newArrayList(StringUtils.split(clusterRegion.getLogicClusterIds(), \",\"))\n                        , (oldList, newList) -> {\n                            oldList.addAll(newList);\n                            return oldList;\n                        }));\n        for (Map.Entry<String, List<String>> entry : phyClusterNameLogicCLusterIds.entrySet()) {\n            List<ClusterLogic> logicList = entry.getValue().stream().\n                    map(logicId -> longClusterLogicMap.get(Long.parseLong(logicId))).filter(Objects::nonNull).collect(Collectors.toList());\n            if (CollectionUtils.isNotEmpty(logicList)) {\n                phyClusterNameLogicCluster.put(entry.getKey(), logicList);\n            }\n        }\n        //维护逻辑集群和节点名称之间的关系，物理机群节点统计信息的关系，逻辑集群和索引统计信息的关系，方便后面计算\n        Map<Integer, List<String>> logicClusterNodesNameMap = Maps.newConcurrentMap();\n        Map<String, List<ClusterLogicStats>> nodeStatsMap = Maps.newConcurrentMap();\n        Map<Long, List<IndexStatusResult>> logicClusterIndicesStatsMap = Maps.newConcurrentMap();\n        for (String phyClusterName : monitorClusterSet) {\n            clusterLogicFutureUtil.runnableTask(() -> {\n                clusterLogicStaticsService.buildLogicClusterStats(phyClusterRegionMap, regionNodeMap,\n                        logicClusterIndicesNameMap, phyClusterName, logicClusterNodesNameMap,\n                        nodeStatsMap, logicClusterIndicesStatsMap);\n                //指标采集\n                List<ESClusterStats> esLogicClusterStatsList = Lists.newArrayList();\n                long collectTime = CommonUtils.monitorTimestamp2min(System.currentTimeMillis());\n                List<ClusterLogic> logicClusterListByPhyClusterName = phyClusterNameLogicCluster.get(phyClusterName);\n                if (CollectionUtils.isNotEmpty(logicClusterListByPhyClusterName)) {\n                    logicClusterListByPhyClusterName.stream()\n                            .filter(logicCluster -> logicClusterNodesNameMap.containsKey(logicCluster.getId().intValue()))\n                            .forEach(logicCluster -> {\n                                ClusterLogicStatsPO clusterLogicStatisPO = clusterLogicStaticsService.getLogicClusterStats(logicCluster.getId(),\n                                        ClusterPhyMap.get(phyClusterName), logicClusterNodesNameMap,\n                                        nodeStatsMap, logicClusterIndicesStatsMap, true);\n                                ESClusterStatsCells esClusterStatsBean = new ESClusterStatsCells();\n                                esClusterStatsBean.setStatus(clusterLogicStatisPO.getStatus());\n                                esClusterStatsBean.setStatusType(clusterLogicStatisPO.getStatusType());\n                                esClusterStatsBean.setClusterName(logicCluster.getName());\n                                esClusterStatsBean.setLevel(logicCluster.getLevel());\n                                esClusterStatsBean.setClusterNu(1);\n                                esClusterStatsBean.setTotalIndicesNu(clusterLogicStatisPO.getIndexNu());\n                                esClusterStatsBean.setTotalDocNu(clusterLogicStatisPO.getDocNu());\n                                Optional.ofNullable(clusterLogicStatisPO.getUsedDisk())\n                                        .ifPresent(usedDisk->esClusterStatsBean.setIndexStoreSize(usedDisk.longValue()));\n                                Optional.ofNullable(clusterLogicStatisPO.getUsedDisk())\n                                        .ifPresent(usedDisk->esClusterStatsBean.setStoreSize(usedDisk.longValue()));\n                                Optional.ofNullable(clusterLogicStatisPO.getFreeDisk())\n                                        .ifPresent(freeDisk->esClusterStatsBean.setFreeStoreSize(freeDisk.longValue()));\n                                Optional.ofNullable(clusterLogicStatisPO.getTotalDisk())\n                                        .ifPresent(totalDisk->esClusterStatsBean.setTotalStoreSize(totalDisk.longValue()));\n                                esClusterStatsBean.setNumberDataNodes(clusterLogicStatisPO.getNumberDataNodes());\n                                esClusterStatsBean.setNumberPendingTasks(clusterLogicStatisPO.getNumberPendingTasks());\n                                esClusterStatsBean.setUnAssignedShards(clusterLogicStatisPO.getUnAssignedShards());\n                                esClusterStatsBean.setCpuUsage(clusterLogicStatisPO.getCpuUsedPercent());\n                                esClusterStatsBean.setAlivePercent(clusterLogicStatisPO.getAlivePercent());\n                                if (Objects.nonNull(esClusterStatsBean.getStoreSize()) && Objects.nonNull(esClusterStatsBean.getTotalStoreSize())\n                                        && 0.0 < esClusterStatsBean.getTotalStoreSize()) {\n                                    esClusterStatsBean.setDiskUsage(esClusterStatsBean.getStoreSize().doubleValue() / esClusterStatsBean.getTotalStoreSize());\n                                }\n                                List<String> nodes = getNodesWithClusterLogic(logicCluster.getId());\n                                handlePhysicalClusterStatsForSum(phyClusterName,nodes, esClusterStatsBean);\n\n\n                                //获取不同分位值的指标\n                                Map<String, ESClusterStatsCells> percentilesType2ESClusterStatsCellsMap = getPhysicalClusterStatsPercentiles(logicCluster.getName(), nodes, esClusterStatsBean,phyClusterName);\n\n                                percentilesType2ESClusterStatsCellsMap.forEach((percentilesType, esClusterStatsCells) -> {\n                                    ESClusterStats esClusterStats = new ESClusterStats();\n                                    esClusterStats.setStatis(esClusterStatsCells);\n                                    esClusterStats.setCluster(logicCluster.getName());\n                                    esClusterStats.setPercentilesType(percentilesType);\n                                    esClusterStats.setPhysicCluster(LOGIC_CLUSTER);\n                                    esClusterStats.setTimestamp(collectTime);\n                                    esClusterStats.setDataCenter(logicCluster.getDataCenter());\n\n                                    esLogicClusterStatsList.add(esClusterStats);\n                                });\n                            });\n                }\n                // send cluster status to es and kafka\n                if (CollectionUtils.isNotEmpty(esLogicClusterStatsList)) {\n                    monitorMetricsSender.sendClusterStats(esLogicClusterStatsList);\n                    SpringTool.publish(new MetricsMonitorLogicClusterEvent(this, esLogicClusterStatsList, hostName));\n                }\n            });\n        }\n        clusterLogicFutureUtil.waitExecute();\n    }\n\n    /**\n     * 采集系统指标\n     * @param nodes\n     * @param esClusterStats\n     */\n    private void handlePhysicalClusterStatsForSum(String phyClusterName,List<String> nodes, ESClusterStatsCells esClusterStats) {\n        // 这里会有多次es查询，做成并发的以免http接口超时\n        clusterLogicFutureUtil.runnableTask(() -> esClusterStats.setReadTps(ariusStatsNodeInfoEsDao.getClusterLogicQps(phyClusterName,nodes)))\n                .runnableTask(() -> esClusterStats.setWriteTps(ariusStatsNodeInfoEsDao.getClusterLogicTps(phyClusterName,nodes)))\n                .runnableTask(() -> esClusterStats.setRecvTransSize(ariusStatsNodeInfoEsDao.getClusterLogicRx(phyClusterName,nodes)))\n                .runnableTask(() -> esClusterStats.setSendTransSize(ariusStatsNodeInfoEsDao.getClusterLogicTx(phyClusterName,nodes)))\n                .runnableTask(() -> esClusterStats.setSearchLatency(calcSearchLatencyAvg(phyClusterName,nodes)))\n                .runnableTask(() -> esClusterStats.setIndexingLatency(calcIndexingLatencyAvg(phyClusterName,nodes)))\n                .waitExecute();\n    }\n\n    /**\n     * 计算SearchLatency\n     *    计算逻辑：\n     *    （集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis差值累加值）\n     *        除以\n     *    （节点间隔时间nodes.{nodeName}.indices.search.query_total差值累加值）\n     *\n     * @param nodes   集群下的节点\n     * @return\n     */\n    private double calcSearchLatencyAvg(String phyClusterName,List<String> nodes){\n        // 获取分子：所有节点的indices.search.query_time_in_millis差值累加值\n        double searchLatencySum = ariusStatsNodeInfoEsDao.getClusterLogicSearchLatencySum(phyClusterName,nodes);\n        // 获取分母：所有节点indices.search.query_total差值累加值\n        double searchQueryTotal = ariusStatsNodeInfoEsDao.getClusterLogicSearchQueryTotal(phyClusterName,nodes);\n        return searchQueryTotal == 0 ? 0 : (searchLatencySum / searchQueryTotal);\n    }\n\n    /**\n     * 计算IndexingLatency\n     *    计算逻辑：\n     *    （集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis差值累加值）\n     *         除以\n     *    （节点间隔时间nodes.{nodeName}.indices.docs.count差值累加值）\n     *\n     * @param phyClusterName\n     * @return\n     */\n    private double calcIndexingLatencyAvg(String phyClusterName,List<String> nodes){\n        // 获取分子：所有节点的indices.indexing.index_time_in_millis差值累加值\n        double indexingLatencySum = ariusStatsNodeInfoEsDao.getClusterLogicIndexingLatencySum(phyClusterName,nodes);\n        // 获取分母：所有节点的indices.docs.count差值累加值\n        double indexingDocSum = ariusStatsNodeInfoEsDao.getClusterLogicIndexingDocSum(phyClusterName,nodes);\n        return indexingDocSum == 0 ? 0 : (indexingLatencySum / indexingDocSum);\n    }\n\n\n    /**\n     * 获取逻辑集群下的nodes\n     * @param clusterLogicId\n     * @return\n     */\n    private List<String> getNodesWithClusterLogic(Long  clusterLogicId) {\n        ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(clusterLogicId);\n        Result<List<ClusterRoleHost>> result = clusterRoleHostService\n                .listByRegionId(Math.toIntExact(clusterRegion.getId()));\n        List<String> nodes = result.getData().stream().map(ClusterRoleHost::getNodeSet).collect(Collectors.toList());\n        return nodes;\n    }\n\n    /**\n     * 采集不同分位图的指标数据\n     * @return  Map<String, ESClusterStatsCells>\n     */\n    private Map<String, ESClusterStatsCells> getPhysicalClusterStatsPercentiles(String clusterLogicName,List<String> nodes,ESClusterStatsCells esClusterStatsCells,String phyClusterName) {\n        Map<String, ESClusterStatsCells> percentilesType2ESClusterStatsCellsMap = Maps.newHashMap();\n        if (AriusObjUtils.isNull(clusterLogicName)) {\n            LOGGER.warn(\n                    \"class=ClusterMonitorJobHandler||method=getPhysicalClusterStatsPercentiles||errMsg=clusterName is empty\");\n            return percentilesType2ESClusterStatsCellsMap;\n        }\n        AtomicReference<Map<String, Double>> clusterCpuAvgAndPercentilesAtomic = new AtomicReference<>();\n        AtomicReference<Map<String, Double>> clusterDiskFreeUsagePercentAvgAndPercentilesAtomic = new AtomicReference<>();\n        AtomicReference<Map<String, Double>> clusterCpuLoad1MinAvgAndPercentilesAtomic = new AtomicReference<>();\n        AtomicReference<Map<String, Double>> clusterCpuLoad5MinAvgAndPercentilesAtomic = new AtomicReference<>();\n        AtomicReference<Map<String, Double>> clusterCpuLoad15MinAvgAndPercentilesAtomic = new AtomicReference<>();\n        AtomicReference<Map<String, Double>> clusterTaskCostMinAvgAndPercentilesAtomic = new AtomicReference<>();\n\n        clusterLogicFutureUtil\n                .runnableTask(() -> clusterCpuAvgAndPercentilesAtomic\n                        .set(ariusStatsNodeInfoEsDao.getClusterLogicCpuAvgAndPercentiles(nodes,phyClusterName)))\n                .runnableTask(() -> clusterDiskFreeUsagePercentAvgAndPercentilesAtomic\n                        .set(ariusStatsNodeInfoEsDao.getClusterLogicDiskFreeUsagePercentAvgAndPercentiles(nodes,phyClusterName)))\n                .runnableTask(() -> clusterCpuLoad1MinAvgAndPercentilesAtomic\n                        .set(ariusStatsNodeInfoEsDao.getClusterLogicCpuLoad1MinAvgAndPercentiles(nodes,phyClusterName)))\n                .runnableTask(() -> clusterCpuLoad5MinAvgAndPercentilesAtomic\n                        .set(ariusStatsNodeInfoEsDao.getClusterLogicCpuLoad5MinAvgAndPercentiles(nodes,phyClusterName)))\n                .runnableTask(() -> clusterCpuLoad15MinAvgAndPercentilesAtomic\n                        .set(ariusStatsNodeInfoEsDao.getClusterLogicCpuLoad15MinAvgAndPercentiles(nodes,phyClusterName)))\n                .runnableTask(() -> clusterTaskCostMinAvgAndPercentilesAtomic\n                        .set(ariusStatsClusterTaskInfoESDAO.getTaskCostMinAvgAndPercentilesWithNodes(nodes,phyClusterName)))\n                .waitExecute();\n\n        for (String type : PercentilesEnum.listUsefulType()) {\n            ESClusterStatsCells esClusterStatsCellDeepCopy = ConvertUtil.obj2Obj(esClusterStatsCells,\n                    ESClusterStatsCells.class);\n\n            buildForPercentiles(esClusterStatsCellDeepCopy, type, clusterCpuAvgAndPercentilesAtomic.get(),\n                    clusterCpuLoad1MinAvgAndPercentilesAtomic.get(), clusterCpuLoad5MinAvgAndPercentilesAtomic.get(),\n                    clusterCpuLoad15MinAvgAndPercentilesAtomic.get(),\n                    clusterDiskFreeUsagePercentAvgAndPercentilesAtomic.get(),\n                    clusterTaskCostMinAvgAndPercentilesAtomic.get());\n\n            percentilesType2ESClusterStatsCellsMap.put(type, esClusterStatsCellDeepCopy);\n\n        }\n\n        return percentilesType2ESClusterStatsCellsMap;\n    }\n\n    /**\n     * @param esClusterStatsCellDeepCopy                       集群维度统计信息\n     * @param type                                             avg、分位类型(99、95、75、55)\n     * @param clusterCpuAvgAndPercentiles                      集群cpu平均值和分位值(key:99, value:值)\n     * @param clusterDiskFreeUsagePercentAvgAndPercentiles     集群节点磁盘空闲率平均值和分位值(key:99, value:值)\n     * @param clusterCpuLoad1MinAvgAndPercentiles              集群cpu load1平均值和分位值(key:99, value:值)\n     * @param clusterCpuLoad5MinAvgAndPercentiles              集群cpu load5平均值和分位值(key:99, value:值)\n     * @param clusterCpuLoad15MinAvgAndPercentiles             集群cpu load15平均值和分位值(key:99, value:值)\n     * @param clusterTaskCostMinAvgAndPercentiles              集群task cost平均值和分位值(key:99, value:值)\n     */\n    private void buildForPercentiles(ESClusterStatsCells esClusterStatsCellDeepCopy, String type,\n                                     Map<String, Double> clusterCpuAvgAndPercentiles,\n                                     Map<String, Double> clusterCpuLoad1MinAvgAndPercentiles,\n                                     Map<String, Double> clusterCpuLoad5MinAvgAndPercentiles,\n                                     Map<String, Double> clusterCpuLoad15MinAvgAndPercentiles,\n                                     Map<String, Double> clusterDiskFreeUsagePercentAvgAndPercentiles,\n                                     Map<String, Double> clusterTaskCostMinAvgAndPercentiles) {\n        if (null != clusterCpuAvgAndPercentiles && null != clusterCpuAvgAndPercentiles.get(type)) {\n            esClusterStatsCellDeepCopy.setCpuUsage(clusterCpuAvgAndPercentiles.get(type));\n        }\n\n        if (null != clusterCpuLoad1MinAvgAndPercentiles && null != clusterCpuLoad1MinAvgAndPercentiles.get(type)) {\n            esClusterStatsCellDeepCopy.setCpuLoad1M(clusterCpuLoad1MinAvgAndPercentiles.get(type));\n        }\n\n        if (null != clusterCpuLoad5MinAvgAndPercentiles && null != clusterCpuLoad5MinAvgAndPercentiles.get(type)) {\n            esClusterStatsCellDeepCopy.setCpuLoad5M(clusterCpuLoad5MinAvgAndPercentiles.get(type));\n        }\n\n        if (null != clusterCpuLoad15MinAvgAndPercentiles && null != clusterCpuLoad15MinAvgAndPercentiles.get(type)) {\n            esClusterStatsCellDeepCopy.setCpuLoad15M(clusterCpuLoad15MinAvgAndPercentiles.get(type));\n        }\n\n        String realType = convertSpecialTypeForDiskFreeUsage(type);\n        if (null != clusterDiskFreeUsagePercentAvgAndPercentiles\n                && null != clusterDiskFreeUsagePercentAvgAndPercentiles.get(realType)) {\n            esClusterStatsCellDeepCopy.setDiskUsage(1 - clusterDiskFreeUsagePercentAvgAndPercentiles.get(realType));\n        }\n\n        if (null != clusterTaskCostMinAvgAndPercentiles && null != clusterTaskCostMinAvgAndPercentiles.get(type)) {\n            esClusterStatsCellDeepCopy.setTaskCost(clusterTaskCostMinAvgAndPercentiles.get(type));\n        }\n    }\n\n    private String convertSpecialTypeForDiskFreeUsage(String type) {\n        if (PercentilesEnum.ST99.getType().equals(type)) {\n            return PercentilesEnum.ST1.getType();\n        }\n\n        if (PercentilesEnum.ST95.getType().equals(type)) {\n            return PercentilesEnum.ST5.getType();\n        }\n\n        if (PercentilesEnum.ST75.getType().equals(type)) {\n            return PercentilesEnum.ST25.getType();\n        }\n\n        if (PercentilesEnum.ST55.getType().equals(type)) {\n            return PercentilesEnum.ST45.getType();\n        }\n\n        return PercentilesEnum.AVG.getType();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/MonitorClusterJob.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.MulityTypeTemplatesInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.event.metrics.MetricsMonitorCollectTimeEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.metrics.MetricsMonitorIndexEvent;\nimport com.didichuxing.datachannel.arius.admin.common.event.metrics.MetricsMonitorNodeEvent;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.HttpHostUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.index.ESIndexStatsAction;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.index.ESIndexStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics.CollectMetrics;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics.DCDRMetrics;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics.ESNodeToIndexComputer;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics.MetricsRegister;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node.ESNodeAction;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node.ESNodeResponse;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node.ESNodeStatsAction;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node.ESNodeStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.metadata.utils.MonitorUtil;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.request.dcdr.DCDRIndexStats;\nimport com.didiglobal.knowframework.elasticsearch.client.request.dcdr.DCDRStats;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.stats.IndicesStatsLevel;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ESClusterNodesStatsResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.dcdr.ESGetDCDRStatsResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.ESIndicesCatIndicesResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.stats.IndexNodes;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.indices.CommonStat;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.indices.Docs;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.node.NodeAttributes;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.common.StopWatch;\nimport org.springframework.beans.BeanUtils;\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.*;\nimport static com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node.ESNodeStatsRequest.HTTP;\n\n/**\n * 每个集群的采集任务\n */\npublic class MonitorClusterJob {\n\n    protected static final ILog                           LOGGER                     = LogFactory\n        .getLog(MonitorClusterJob.class);\n\n    private static final String                           HOST_NAME                  = HttpHostUtil.HOST_NAME;\n    private static final long                             CLIENT_TO_WITH_MILLS       = 50 * 1000L;\n\n    private static final String[]                         DATA_FORMATS               = new String[] { \"_YYYYMM\",\n                                                                                                      \"YYYYMM\",\n                                                                                                      \"YYYYMMdd\",\n                                                                                                      \"_YYYYMMdd\",\n                                                                                                      \"YYYY-MM-dd\",\n                                                                                                      \"_YYYY-MM-dd\",\n                                                                                                      \"MMdd\", \"YYMM\",\n                                                                                                      \"_YYMM\", \"YY-MM\",\n                                                                                                      \"_YYYY-MM\",\n                                                                                                      \"YYYY\",\n                                                                                                      \"_YYYY.MM.dd\",\n                                                                                                      \"YYYY.MM.dd\" };\n    public static final int                               GROUP                      = 3;\n\n    private Pattern                                       pattern                    = Pattern\n        .compile(\"(.*)(_v[1-9]\\\\d*)(.*)\");\n\n    private static final String                           COMPUTE                    = \"compute\";\n    private static final String                           ES_NODE                    = \"es.node.\";\n    private static final String                           TIME_OUT                   = \"collect task already timeout\";\n    private static final String                           ES_INDICES                 = \"es.indices.\";\n\n    private static final int                              NODE_COLLECT_BATCH_SIZE    = 5;\n    private static final int                              INDICES_COLLECT_BATCH_SIZE = 30;\n\n    //key: cluster@templateName\n    private Cache<String, IndexTemplatePhyWithLogic>      indexTemplateCache         = CacheBuilder.newBuilder()\n        .expireAfterWrite(60, TimeUnit.MINUTES).maximumSize(10000).build();\n\n    //采集指标\n    private List<CollectMetrics>                          indexWorkOrders;\n    private List<CollectMetrics>                          indexToNodeWorkOrders;\n    private List<CollectMetrics>                          nodeWorkOrders;\n    private List<CollectMetrics>                          nodeToIndexWorkOrders;\n    private List<CollectMetrics>                          ingestWorkOrders;\n    private List<CollectMetrics>                          dcdrWorkOrders;\n\n    //缓存索引和节点的对应关系\n    private List<ESIndexToNodeTempBean>                   indexToNodeTemps           = new CopyOnWriteArrayList<>();\n\n    //缓存nodeid 与 发送给es的指标数据映射关系\n    private Map<String, ESNodeStats>                      nodeIdEsNodeStatsMap       = new ConcurrentHashMap<>();\n\n    private List<IndexTemplatePhyWithLogic>               indexTemplates             = new CopyOnWriteArrayList<>();\n\n    private ESClient                                      esClient;\n\n    private MonitorMetricsSender                          monitorMetricsSender;\n\n    private MetricsRegister                               metricsRegister;\n\n    private Set<String>                                   clusterNodeIps             = Collections\n        .synchronizedSet(new HashSet<>());\n\n    private ClusterPhy                                    clusterPhy;\n\n    // 多type索引 启用查询映射的信息\n    private MulityTypeTemplatesInfo                       mulityTypeTemplatesInfo;\n\n    private AriusConfigInfoService                        ariusConfigInfoService;\n\n    private String                                        clusterName;\n\n    private static final FutureUtil<ESNodeStatsResponse>  NODE_STATS_FUTURE          = FutureUtil\n        .init(\"MonitorClusterJob-nodeStats\", 10, 10, 20);\n    private static final FutureUtil<ESIndexStatsResponse> INDEX_STATS_FUTURE         = FutureUtil\n        .init(\"MonitorClusterJob-indexStats\", 10, 10, 20);\n\n    private StopWatch                                     indexStopWatch             = new StopWatch();\n    private StopWatch                                     nodeStopWatch              = new StopWatch();\n    private StopWatch                                     dcdrStopWatch              = new StopWatch();\n    private StopWatch                                     index2NodeStopWatch        = new StopWatch();\n\n    public MonitorClusterJob(ESClient esClient, String ariusClusterName, ClusterPhy clusterPhy,\n                             List<IndexTemplatePhyWithLogic> indexTemplates, MetricsRegister metricsRegister,\n                             MonitorMetricsSender monitorMetricsSender, List<CollectMetrics> indexWorkOrders,\n                             List<CollectMetrics> nodeWorkOrders, List<CollectMetrics> indexToNodeWorkOrders,\n                             List<CollectMetrics> nodeToIndexWorkOrders, List<CollectMetrics> ingestWorkOrders,\n                             List<CollectMetrics> dcdrWorkOrders, MulityTypeTemplatesInfo mulityTypeTemplatesInfo,\n                             AriusConfigInfoService ariusConfigInfoService) {\n        this.esClient = esClient;\n        this.clusterPhy = clusterPhy;\n        this.metricsRegister = metricsRegister;\n        this.monitorMetricsSender = monitorMetricsSender;\n        this.indexWorkOrders = indexWorkOrders;\n        this.nodeWorkOrders = nodeWorkOrders;\n        this.indexToNodeWorkOrders = indexToNodeWorkOrders;\n        this.nodeToIndexWorkOrders = nodeToIndexWorkOrders;\n        this.ingestWorkOrders = ingestWorkOrders;\n        this.dcdrWorkOrders = dcdrWorkOrders;\n        this.mulityTypeTemplatesInfo = mulityTypeTemplatesInfo;\n        this.clusterName = ariusClusterName;\n        this.ariusConfigInfoService = ariusConfigInfoService;\n        this.indexTemplates.addAll(indexTemplates);\n    }\n\n    public void collectData(String ariusClusterName) {\n        collectNodeData(ariusClusterName, esClient, metricsRegister);\n        collectIndexData(ariusClusterName, esClient, metricsRegister);\n        //collectIndexToNodeData();\n\n        LOGGER.info(\n            \"class=MonitorClusterJob||method=collectData||clusterName={}||indexStopWatch={}||nodeStopWatch={}||dcdrStopWatch={}||index2NodeStopWatch={}\",\n            ariusClusterName, indexStopWatch.toString(), nodeStopWatch.toString(), dcdrStopWatch.toString(),\n            index2NodeStopWatch.toString());\n    }\n\n    /**************************************** private methods ****************************************/\n    /**\n     * 通过clientNode一次获取集群的所有节点stats\n     * @param esClient esClient\n     * @return 集群节点stats，key-节点ID，value-节点stats\n     */\n    private Map<String, ClusterNodeStats> getNodeStatsByOnce(ESClient esClient) {\n        ESClusterNodesStatsResponse response = esClient.admin().cluster().prepareNodeStats()\n            .level(IndicesStatsLevel.INDICES.getStr()).execute().actionGet(CLIENT_TO_WITH_MILLS);\n        return response.getNodes();\n    }\n\n    /**\n     * 获取集群下的所有节点ID\n     * @param esClient esClient\n     */\n    private List<String> getClusterNodeIds(ESClient esClient, long timeLimitMillis) {\n        ESNodeResponse nodesResponse = esClient.admin().cluster().prepareExecute(ESNodeAction.INSTANCE).addFlag(HTTP)\n            .execute().actionGet(timeLimitMillis);\n        if (nodesResponse.getFailedNodes() > 0) {\n            LOGGER.warn(\n                \"class=MonitorClusterJob||method=getClusterNodeIds||collect node id has part of the failure, failed nodes:[{}]\",\n                nodesResponse.getFailedNodes());\n        }\n        return new ArrayList<>(nodesResponse.getNodes().keySet());\n    }\n\n    /**\n     * 通过datanode并发去获取节点stats\n     * @param esClient\n     * @return\n     * @throws AdminOperateException\n     */\n    private Map<String, ClusterNodeStats> getClusterNodeStatsConcurrently(ESClient esClient) throws AdminOperateException {\n        try {\n            long startTime = System.currentTimeMillis();\n            long expectEndTime = startTime + CLIENT_TO_WITH_MILLS;\n\n            // 1.获取集群下的所有节点ID\n            List<String> clusterNodeIds = getClusterNodeIds(esClient, CLIENT_TO_WITH_MILLS);\n\n            // 2.划分批次\n            List<List<String>> nodeIdBatches = Lists.partition(clusterNodeIds, NODE_COLLECT_BATCH_SIZE);\n\n            // 3.分批次并行获取节点指标\n            for (List<String> nodeIdBatch : nodeIdBatches) {\n                // 总任务超时时间也作为子任务超时时间\n                NODE_STATS_FUTURE.callableTask(() -> {\n                    ESNodeStatsResponse response = new ESNodeStatsResponse();\n                    response.setNodes(new HashMap<>());\n                    try {\n                        if (System.currentTimeMillis() > expectEndTime) {\n                            // 总任务已经超时，不再执行\n                            throw new AdminOperateException(TIME_OUT);\n                        }\n                        response = esClient.admin().cluster().prepareExecute(ESNodeStatsAction.INSTANCE)\n                            .setNodesIds(nodeIdBatch.toArray(new String[0])).level(IndicesStatsLevel.INDICES.getStr())\n                            .execute().actionGet(CLIENT_TO_WITH_MILLS);\n                    } catch (Exception e) {\n                        LOGGER.error(\n                            \"class=MonitorClusterJob||method=getClusterNodeStatsConcurrently||batch get node stats execute error\",\n                            e);\n                    }\n\n                    return response;\n                });\n            }\n\n            // 4.获取所有批次结果\n            List<ESNodeStatsResponse> nodeStatsResponseList = NODE_STATS_FUTURE.waitResult();\n\n            // 5.合并批次结果\n            Map<String, ClusterNodeStats> clusterNodeStatsMap = new HashMap<>();\n            for (ESNodeStatsResponse nodesStatsResponse : nodeStatsResponseList) {\n                clusterNodeStatsMap.putAll(nodesStatsResponse.getNodes());\n            }\n\n            // 6.有部分节点失败,打印告警日志\n            int failedNode = clusterNodeIds.size() - clusterNodeStatsMap.size();\n            if (failedNode != 0) {\n                LOGGER.warn(\n                    \"class=MonitorClusterJob||method=getClusterNodeStatsConcurrently||batch get node stats has part of the failure, failed nodes:[{}]\",\n                    failedNode);\n            }\n\n            return clusterNodeStatsMap;\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=MonitorClusterJob||method=getClusterNodeStatsConcurrently||getClusterNodeStats for cluster {} error, e->\",\n                esClient.getClusterName(), e);\n            throw new AdminOperateException(TIME_OUT, e.getCause());\n        }\n    }\n\n    private Map<String, ClusterNodeStats> getClusterNodeStats(ESClient esClient) throws AdminOperateException {\n        boolean isConcurrentCollect = ariusConfigInfoService.booleanSetting(ARIUS_META_MONITOR_GROUP,\n            NODE_STAT_COLLECT_CONCURRENT, NODE_STAT_COLLECT_CONCURRENT_DEFAULT_VALUE);\n\n        Map<String, ClusterNodeStats> clusterNodeStatsMap;\n        if (!isConcurrentCollect) {\n            // 方式1：原获取方式，一次获取全部\n            nodeStopWatch.stop().start(\"stats_node_once\");\n            clusterNodeStatsMap = getNodeStatsByOnce(esClient);\n        } else {\n            // 方式2：并行获取节点stats数据，key-节点ID，value-节点stats\n            nodeStopWatch.stop().start(\"stats_node_concurrent\");\n            clusterNodeStatsMap = getClusterNodeStatsConcurrently(esClient);\n        }\n\n        LOGGER.debug(\"class=MonitorClusterJob||method=getClusterNodeStats||clusterName={}||clusterNodeStatsMapSize={}\",\n            clusterName, clusterNodeStatsMap.size());\n\n        return clusterNodeStatsMap;\n    }\n\n    /**\n     * 采集节点信息\n     * @param esClient\n     * @param metricsRegister\n     * @param ariusClusterName 平台设置的物理名称\n     */\n    private void collectNodeData(String ariusClusterName, ESClient esClient, MetricsRegister metricsRegister) {\n        long timestamp = CommonUtils.monitorTimestamp2min(System.currentTimeMillis());\n\n        try {\n            nodeStopWatch.start(\"stats_node_begin\");\n            Map<String, ClusterNodeStats> clusterNodeStatsMap = getClusterNodeStats(esClient);\n\n            List<ESNodeStats> esNodeStatsList = new CopyOnWriteArrayList<>();\n\n            nodeStopWatch.stop().start(COMPUTE);\n            clusterNodeStatsMap.entrySet().parallelStream().forEach(entry -> {\n                String nodeId = entry.getKey();\n                try {\n                    ClusterNodeStats clusterNodeStats = entry.getValue();\n                    NodeAttributes attributes = clusterNodeStats.getAttributes();\n\n                    ESDataTempBean base = new ESDataTempBean();\n                    base.setDimension(ESDataTempBean.NODE_TYPE);\n                    base.setCluster(ariusClusterName);\n                    base.setTimestamp(timestamp);\n                    base.setNode(clusterNodeStats.getName());\n                    base.setIp(HttpHostUtil.getIpFromTransportAddress(clusterNodeStats.getTransportAddress()));\n                    base.setPort(HttpHostUtil.getPortFromTransportAddress(clusterNodeStats.getTransportAddress()));\n                    base.setRack(null == attributes ? \"\" : attributes.getRack());\n\n                    clusterNodeIps.add(base.getIp());\n\n                    Map map = JSON.parseObject(JSON.toJSONString(clusterNodeStats), Map.class);\n                    // 根据nodeWorkOrders的指定获取指标，生成对应的ESDataTempBean，返回esDataTempBeans的size等于nodeWorkOrders的size（一一对应）\n                    List<ESDataTempBean> esDataTempBeans = aggrAndComputeData(map, nodeWorkOrders, base,\n                        metricsRegister);\n\n                    // 节点数据\n                    ESNodeStats esNodeStats = buildESNodeStats(base, esDataTempBeans);\n\n                    esNodeStatsList.add(esNodeStats);\n                    // 节点id到节点数据的map\n                    nodeIdEsNodeStatsMap.put(nodeId, esNodeStats);\n\n                    //发送到指标到监控系统\n                    SpringTool.publish(new MetricsMonitorNodeEvent(this, esDataTempBeans, esNodeStatsList,\n                        clusterPhy.getLevel(), HOST_NAME));\n                } catch (Exception e) {\n                    LOGGER.error(\n                        \"class=MonitorClusterJob||method=collectNodeData||nodeId={}||clusterName={}||msg=exception\",\n                        nodeId, clusterName, e);\n                }\n            });\n\n            monitorMetricsSender.sendNodeInfo(esNodeStatsList);\n        } catch (Exception e) {\n            LOGGER.error(\"class=MonitorClusterJob||method=collectNodeData||clusterName={}||msg=exception\", clusterName,\n                e);\n        }\n\n        //必须要放到cache外层，在获取es数据超时时也要进行上报\n        SpringTool.publish(new MetricsMonitorCollectTimeEvent(this, \"node\",\n            (double) System.currentTimeMillis() - timestamp, clusterName, clusterPhy.getLevel(), HOST_NAME));\n\n        if (nodeStopWatch.isRunning()) {\n            nodeStopWatch.stop();\n        }\n    }\n\n    // 一次获取所有索引stat-减少反序列化字段\n    private Map<String, IndexNodes> getIndexStatsByOnce(ESClient esClient) {\n        ESIndexStatsResponse response = esClient.admin().indices().prepareExecute(ESIndexStatsAction.INSTANCE)\n            .setLevel(IndicesStatsLevel.SHARDS).execute().actionGet(CLIENT_TO_WITH_MILLS);\n        return response.getIndicesMap();\n    }\n\n    /**\n     * 获取集群下的所有索引名\n     * @param esClient esClient\n     */\n    private List<String> getClusterOpenIndexNames(ESClient esClient) {\n        ESIndicesCatIndicesResponse esIndicesCatIndicesResponse = esClient.admin().indices().prepareCatIndices()\n            .execute().actionGet(CLIENT_TO_WITH_MILLS);\n        return esIndicesCatIndicesResponse.getCatIndexResults().stream()\n            .filter(catIndexResult -> \"open\".equalsIgnoreCase(catIndexResult.getStatus())).map(CatIndexResult::getIndex)\n            .collect(Collectors.toList());\n    }\n\n    /**\n     * 并发去获取索引的指标\n     * @param esClient\n     * @return\n     */\n    private Map<String, IndexNodes> getIndexStatsConcurrently(ESClient esClient) {\n        try {\n            long startTime = System.currentTimeMillis();\n            long expectEndTime = startTime + CLIENT_TO_WITH_MILLS;\n\n            // 获取集群下的所有索引名称\n            List<String> indexNames = getClusterOpenIndexNames(esClient);\n            // 划分批次\n            List<List<String>> indexNameBatches = Lists.partition(indexNames, INDICES_COLLECT_BATCH_SIZE);\n\n            // 分批次并行获取节点指标\n            for (List<String> indexNameBatch : indexNameBatches) {\n                // 总任务超时时间也作为子任务超时时间\n                INDEX_STATS_FUTURE.callableTask(() -> {\n                    ESIndexStatsResponse response = new ESIndexStatsResponse();\n                    response.setIndicesMap(new HashMap<>());\n                    try {\n                        if (System.currentTimeMillis() > expectEndTime) {\n                            // 总任务已经超时，不再执行\n                            throw new AdminOperateException(TIME_OUT);\n                        }\n\n                        response = esClient.admin().indices().prepareExecute(ESIndexStatsAction.INSTANCE)\n                            .setIndices(indexNameBatch.toArray(new String[0])).setLevel(IndicesStatsLevel.SHARDS)\n                            .execute().actionGet(CLIENT_TO_WITH_MILLS);\n                    } catch (Exception e) {\n                        LOGGER.error(\n                            \"class=MonitorClusterJob||method=getIndexStatsConcurrently||batch get index stats execute error\",\n                            e);\n                    }\n\n                    return response;\n                });\n            }\n\n            // 获取所有批次结果\n            List<ESIndexStatsResponse> indicesStatsResponseList = INDEX_STATS_FUTURE.waitResult();\n\n            // 合并批次结果\n            int shardFailedNum = 0;\n            Map<String, IndexNodes> indexStatsMap = new HashMap<>();\n            for (ESIndexStatsResponse indexStatsResponse : indicesStatsResponseList) {\n                if (null != indexStatsResponse.getShards()) {\n                    shardFailedNum += indexStatsResponse.getShards().getFailedShard();\n                }\n                indexStatsMap.putAll(indexStatsResponse.getIndicesMap());\n            }\n\n            //部分shard失败告警\n            if (shardFailedNum > 0) {\n                LOGGER.warn(\n                    \"class=MonitorClusterJob||method=getIndexStatsConcurrently||batch get index stats has part of the failure, failed shards:[{}]\",\n                    shardFailedNum);\n            }\n\n            return indexStatsMap;\n\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=MonitorClusterJob||method=getIndexStatsConcurrently||getClusterNodeStats for cluster {} error, e->\",\n                esClient.getClusterName(), e);\n            throw e;\n        }\n    }\n\n    private Map<String, IndexNodes> getIndexStats(ESClient esClient) {\n        boolean isConcurrentCollect = ariusConfigInfoService.booleanSetting(ARIUS_META_MONITOR_GROUP,\n            INDEX_STAT_COLLECT_CONCURRENT, INDEX_STAT_COLLECT_CONCURRENT_DEFAULT_VALUE);\n\n        // key-索引名，value-索引stats\n        Map<String, IndexNodes> indexStatsMap;\n        if (isConcurrentCollect) {\n            indexStopWatch.stop().start(\"stats_index_concurrent\");\n            indexStatsMap = getIndexStatsConcurrently(esClient);\n        } else {\n            indexStopWatch.stop().start(\"stats_index_once\");\n            indexStatsMap = getIndexStatsByOnce(esClient);\n        }\n\n        LOGGER.debug(\"class=MonitorClusterJob||method=getIndexStats||clusterName={}||clusterNodeStatsMapSize={}\",\n            clusterName, indexStatsMap.size());\n\n        return indexStatsMap;\n    }\n\n    /**\n     * todo：alibaba规范 方法总行数超过80行\n     * 采集索引信息\n     * @param esClient\n     * @param metricsRegister\n     */\n    private void collectIndexData(String ariusClusterName, ESClient esClient, MetricsRegister metricsRegister) {\n        long timestamp = CommonUtils.monitorTimestamp2min(System.currentTimeMillis());\n\n        try {\n            indexStopWatch.start(\"stats_index_begin\");\n            Map<String, IndexNodes> indexStatsMap = getIndexStats(esClient);\n\n            // 存储多type改造 查询原索引的统计信息，需要将查询映射后的单type索引的统计信息进行汇聚\n            Map<String/*source templateName*/, List<ESIndexStats>/*dest index stats*/> destTemplateIndexStatsMap = Maps\n                .newHashMap();\n\n            // 存储多type改造 查询原索引的统计信息\n            Map<String/*source templateName*/, ESIndexStats/*source index stats*/> sourceTemplateSampleIndexStatsMap = Maps\n                .newHashMap();\n\n            List<ESIndexStats> esIndexStatsList = new CopyOnWriteArrayList<>();\n\n            indexStopWatch.stop().start(COMPUTE);\n            indexStatsMap.entrySet().parallelStream().forEach(entry -> {\n                String index = entry.getKey();\n                try {\n\n                    IndexTemplatePhyWithLogic indexTemplate = getTemplateNameForCache(ariusClusterName, index);\n                    IndexNodes indexStats = entry.getValue();\n\n                    ESDataTempBean base = new ESDataTempBean();\n                    base.setDimension(ESDataTempBean.INDEX_TYPE);\n                    base.setCluster(ariusClusterName);\n                    base.setTimestamp(timestamp);\n                    base.setIndex(index);\n\n                    //兼容原生集群索引采集, 不需要先获取Arius平台索引模板\n                    buildForOriginalESIndicesInfo(base, indexTemplate);\n\n                    base.setShardNu(null == indexStats.getShards() ? 0 : indexStats.getShards().size());\n\n                    Map map = JSON.parseObject(JSON.toJSONString(indexStats.getTotal()), Map.class);\n                    List<ESDataTempBean> esDataTempBeans = aggrAndComputeData(map, indexWorkOrders, base,\n                        metricsRegister);\n\n                    esDataTempBeans\n                        .addAll(genIndexTotalCommonStatsMetric(\n                            indexStats.getTotal().getStore().getSizeInBytes(), Optional.ofNullable(indexStats)\n                                .map(IndexNodes::getTotal).map(CommonStat::getDocs).map(Docs::getCount).orElse(0L),\n                            base));\n\n                    ESIndexStats esIndexStats = buildESIndexStats(base, esDataTempBeans);\n\n                    // 判断是否为多type索引映射后的单type索引\n                    if (Objects.nonNull(mulityTypeTemplatesInfo) && null != indexTemplate) {\n\n                        // 该索引统计信息是映射后的单type信息，需要临时保存\n                        if (MapUtils.isNotEmpty(mulityTypeTemplatesInfo.getDest2SourceTemplateMap())\n                            && mulityTypeTemplatesInfo.getDest2SourceTemplateMap()\n                                .containsKey(indexTemplate.getName())) {\n                            String sourceTemplateName = mulityTypeTemplatesInfo.getDest2SourceTemplateMap()\n                                .get(indexTemplate.getName());\n\n                            ESIndexStats esIndexStatsCopy = new ESIndexStats();\n                            BeanUtils.copyProperties(esIndexStats, esIndexStatsCopy);\n                            Map<String, String> metricsCopy = Maps.newHashMap();\n                            metricsCopy.putAll(esIndexStats.getMetrics());\n                            esIndexStatsCopy.setMetrics(metricsCopy);\n\n                            destTemplateIndexStatsMap.computeIfAbsent(sourceTemplateName, key -> Lists.newArrayList())\n                                .add(esIndexStatsCopy);\n                        }\n\n                        // 该索引统计信息是源索引信息\n                        if (MapUtils.isNotEmpty(mulityTypeTemplatesInfo.getSource2DestTemplateMap())\n                            && mulityTypeTemplatesInfo.getSource2DestTemplateMap()\n                                .containsKey(indexTemplate.getName())) {\n                            // 丢弃原索引指标值，不加入待发送索引指标集合中\n                            sourceTemplateSampleIndexStatsMap.put(indexTemplate.getName(), esIndexStats);\n                            return;\n                        }\n                    }\n\n                    esIndexStatsList.add(esIndexStats);\n\n                    // 索引的集群节点分布信息\n                    //achieveIndexToNodeInfo(base, indexStats);\n\n                    // 指标发送给监控系统\n                    SpringTool.publish(new MetricsMonitorIndexEvent(this, esDataTempBeans, esIndexStatsList,\n                        clusterPhy.getLevel(), HOST_NAME));\n                } catch (Exception e) {\n                    LOGGER.error(\n                        \"class=MonitorClusterJob||method=collectIndexData||index={}||clusterName={}||msg=exception\",\n                        index, clusterName, e);\n                }\n            });\n\n            addSourceTemplateIndexStats(destTemplateIndexStatsMap, sourceTemplateSampleIndexStatsMap, esIndexStatsList);\n\n            // 指标持久化（写到ES）\n            monitorMetricsSender.sendIndexInfo(esIndexStatsList);\n        } catch (Exception e) {\n            LOGGER.error(\"class=MonitorClusterJob||method=collectIndexData||clusterName={}||msg=exception\", clusterName,\n                e);\n        }\n\n        //必须要放到cache外层，在获取es数据超时时也要进行上报\n        SpringTool.publish(new MetricsMonitorCollectTimeEvent(this, \"index\",\n            (double) System.currentTimeMillis() - timestamp, clusterName, clusterPhy.getLevel(), HOST_NAME));\n\n        if (indexStopWatch.isRunning()) {\n            indexStopWatch.stop();\n        }\n    }\n\n    private void buildForOriginalESIndicesInfo(ESDataTempBean base, IndexTemplatePhyWithLogic indexTemplate) {\n        if (null != indexTemplate && null != indexTemplate.getName()) {\n            base.setTemplate(indexTemplate.getName());\n        }\n\n        if (null != indexTemplate && null != indexTemplate.getId()) {\n            base.setTemplateId(indexTemplate.getId());\n        }\n\n        if (null != indexTemplate && null != indexTemplate.getLogicId()) {\n            base.setLogicTemplateId(indexTemplate.getLogicId());\n        }\n    }\n\n    /**\n     * 计算索引到节点的信息\n     */\n    private void collectIndexToNodeData() {\n        try {\n            index2NodeStopWatch.start(\"index_node\");\n            List<ESIndexToNodeStats> esIndexToNodeStatsList = new ArrayList<>();\n            for (ESIndexToNodeTempBean temp : indexToNodeTemps) {\n\n                for (String nodeId : temp.getNodes()) {\n                    ESNodeStats esNodeStats = nodeIdEsNodeStatsMap.get(nodeId);\n                    esIndexToNodeStatsList.add(build(temp, esNodeStats, indexToNodeWorkOrders));\n                }\n            }\n\n            monitorMetricsSender.sendIndexToNodeStats(esIndexToNodeStatsList);\n        } catch (Exception e) {\n            LOGGER.error(\"class=MonitorClusterJob||method=collectIndexToNodeData||clusterName={}||msg=exception\",\n                clusterName, e);\n        }\n        if (index2NodeStopWatch.isRunning()) {\n            index2NodeStopWatch.stop();\n        }\n    }\n\n    /**\n     * 采集DCDR监控信息\n     * @param esClient\n     * @param metricsRegister\n     */\n    private void collectDCDRData(ESClient esClient, MetricsRegister metricsRegister) {\n        try {\n            dcdrStopWatch.start(\"dcdr_begin\");\n\n            ESGetDCDRStatsResponse response = esClient.admin().indices().prepareGetDCDRStats().execute()\n                .actionGet(CLIENT_TO_WITH_MILLS);\n            long timestamp = System.currentTimeMillis();\n            String cluster = esClient.getClusterName();\n\n            dcdrStopWatch.stop().start(COMPUTE);\n            List<ESIndexDCDRStats> esIndexDCDRStatsList = new ArrayList<>();\n            response.getIndicesStats().forEach((index, indexStats) -> {\n                try {\n\n                    IndexTemplatePhyWithLogic indexTemplate = getTemplateNameForCache(cluster, index);\n                    if (null == indexTemplate) {\n                        return;\n                    }\n\n                    ESDataTempBean base = new ESDataTempBean();\n                    base.setDimension(ESDataTempBean.INDEX_TYPE);\n                    base.setCluster(cluster);\n                    base.setTimestamp(timestamp);\n                    base.setIndex(index);\n                    base.setTemplate(indexTemplate.getName());\n                    base.setTemplateId(indexTemplate.getId());\n                    base.setLogicTemplateId(indexTemplate.getLogicId());\n                    base.setShardNu(indexStats.getDcdrStats().size());\n\n                    Map<String, DCDRMetrics> indexStatsByCluster = aggrAndComputeDCDRIndexData(indexStats);\n                    indexStatsByCluster.forEach((replicaCluster, dcdrMetrics) -> {\n                        Map map = (Map) JSON.toJSON(dcdrMetrics);\n                        List<ESDataTempBean> esDataTempBeans = aggrAndComputeData(map, dcdrWorkOrders, base,\n                            metricsRegister);\n                        ESIndexDCDRStats esIndexDCDRStats = buildESIndexDCDRStats(base, replicaCluster,\n                            esDataTempBeans);\n                        esIndexDCDRStatsList.add(esIndexDCDRStats);\n\n                        //发送dcdr指标值监控系统\n                    });\n                } catch (Exception e) {\n                    LOGGER.error(\n                        \"class=MonitorClusterJob||method=collectDcdrData||index={}||clusterName={}||msg=exception\",\n                        index, clusterName, e);\n                }\n            });\n\n            monitorMetricsSender.sendDCDRStats(esIndexDCDRStatsList);\n        } catch (Exception e) {\n            LOGGER.error(\"class=MonitorClusterJob||method=collectDcdrData||clusterName={}||msg=dcdr_exception\",\n                clusterName, e);\n        }\n\n        if (dcdrStopWatch.isRunning()) {\n            dcdrStopWatch.stop();\n        }\n    }\n\n    private Map<String, DCDRMetrics> aggrAndComputeDCDRIndexData(DCDRIndexStats indexStats) {\n        Map<String, DCDRMetrics> indexStatsByCluster = new HashMap<>();\n        indexStats.getDcdrStats().forEach((shardId, statsList) -> statsList\n            .forEach(dcdrStats -> setIndexDCDRMetrics(indexStatsByCluster, dcdrStats)));\n\n        return indexStatsByCluster;\n    }\n\n    private void setIndexDCDRMetrics(Map<String, DCDRMetrics> indexStatsByCluster, DCDRStats dcdrStats) {\n        DCDRMetrics indexDCDRMetrics;\n        if (indexStatsByCluster.containsKey(dcdrStats.getReplicaCluster())) {\n            indexDCDRMetrics = indexStatsByCluster.get(dcdrStats.getReplicaCluster());\n        } else {\n            indexDCDRMetrics = new DCDRMetrics();\n            indexStatsByCluster.put(dcdrStats.getReplicaCluster(), indexDCDRMetrics);\n        }\n\n        if (dcdrStats.getReplicaGlobalCheckpoint() >= 0) {\n            indexDCDRMetrics.setGlobalCheckpointDelay(\n                indexDCDRMetrics.getGlobalCheckpointDelay() + dcdrStats.getPrimaryGlobalCheckpoint()\n                                                      - dcdrStats.getReplicaGlobalCheckpoint());\n        }\n        if (dcdrStats.getReplicaMaxSeqNo() >= 0) {\n            indexDCDRMetrics.setMaxSeqNoDelay(\n                indexDCDRMetrics.getMaxSeqNoDelay() + dcdrStats.getPrimaryMaxSeqNo() - dcdrStats.getReplicaMaxSeqNo());\n        }\n        if (dcdrStats.getAvailableSendBulkNumber() < indexDCDRMetrics.getMinAvailableSendBulkNumber()) {\n            indexDCDRMetrics.setMinAvailableSendBulkNumber(dcdrStats.getAvailableSendBulkNumber());\n        }\n        indexDCDRMetrics\n            .setTotalSendTimeMillis(indexDCDRMetrics.getTotalSendTimeMillis() + dcdrStats.getTotalSendTimeMillis());\n        indexDCDRMetrics\n            .setTotalSendRequests(indexDCDRMetrics.getTotalSendRequests() + dcdrStats.getSuccessfulSendRequests()\n                                  + dcdrStats.getFailedSendRequests());\n        indexDCDRMetrics\n            .setFailedSendRequests(indexDCDRMetrics.getFailedRecoverCount() + dcdrStats.getFailedSendRequests());\n        indexDCDRMetrics.setOperationsSend(indexDCDRMetrics.getOperationsSend() + dcdrStats.getOperationsSends());\n        indexDCDRMetrics.setBytesSend(indexDCDRMetrics.getBytesSend() + dcdrStats.getBytesSend());\n        if (dcdrStats.getTimeSinceLastSendMillis() < indexDCDRMetrics.getMinTimeSinceLastSendMillis()) {\n            indexDCDRMetrics.setMinTimeSinceLastSendMillis(dcdrStats.getTimeSinceLastSendMillis());\n        }\n        if (dcdrStats.getTimeSinceLastSendMillis() > indexDCDRMetrics.getMaxTimeSinceLastSendMillis()\n            && dcdrStats.getReplicaGlobalCheckpoint() >= 0\n            && dcdrStats.getPrimaryGlobalCheckpoint() != dcdrStats.getReplicaGlobalCheckpoint()) {\n            indexDCDRMetrics.setMaxTimeSinceLastSendMillis(dcdrStats.getTimeSinceLastSendMillis());\n        }\n        if (dcdrStats.getTimeSinceUpdateReplicaCheckPoint() > indexDCDRMetrics.getMaxTimeSinceLastSendMillis()\n            && dcdrStats.getReplicaGlobalCheckpoint() >= 0\n            && dcdrStats.getPrimaryGlobalCheckpoint() != dcdrStats.getReplicaGlobalCheckpoint()) {\n            indexDCDRMetrics.setMaxTimeSinceUpdateReplicaCheckPoint(dcdrStats.getTimeSinceUpdateReplicaCheckPoint());\n        }\n\n        indexDCDRMetrics\n            .setSuccessRecoverCount(indexDCDRMetrics.getSuccessRecoverCount() + dcdrStats.getSuccessRecoverCount());\n        indexDCDRMetrics\n            .setFailedRecoverCount(indexDCDRMetrics.getFailedRecoverCount() + dcdrStats.getFailedRecoverCount());\n\n        int inSyncSize;\n        if (dcdrStats.getInSyncOffset().size() == 1 && dcdrStats.getInSyncOffset().get(0) != null) {\n            inSyncSize = dcdrStats.getInSyncOffset().get(0).size();\n        } else {\n            inSyncSize = dcdrStats.getInSyncOffset().size();\n        }\n        indexDCDRMetrics.setInSyncTranslogOffsetSize(indexDCDRMetrics.getInSyncTranslogOffsetSize() + inSyncSize);\n        indexDCDRMetrics.setRecoverTotalTimeMillis(\n            indexDCDRMetrics.getRecoverTotalTimeMillis() + dcdrStats.getRecoverTotalTimeMillis());\n    }\n\n    private ESIndexDCDRStats buildESIndexDCDRStats(ESDataTempBean bean, String replicaCluster,\n                                                   List<ESDataTempBean> metricsList) {\n        ESIndexDCDRStats esIndexDCDRStats = new ESIndexDCDRStats();\n        esIndexDCDRStats.setTimestamp(bean.getTimestamp());\n        esIndexDCDRStats.setCluster(bean.getCluster());\n        esIndexDCDRStats.setReplicaCluster(replicaCluster);\n        esIndexDCDRStats.setTemplate(bean.getTemplate());\n        esIndexDCDRStats.setTemplateId(bean.getTemplateId());\n        esIndexDCDRStats.setLogicTemplateId(bean.getLogicTemplateId());\n        esIndexDCDRStats.setIndex(bean.getIndex());\n        esIndexDCDRStats.setShardNu(bean.getShardNu());\n        esIndexDCDRStats.setMetrics(Maps.newHashMap());\n\n        for (ESDataTempBean esDataTempBean : metricsList) {\n            if (StringUtils.isEmpty(esDataTempBean.getComputeValue()) || \"null\".equals(esDataTempBean.getComputeValue())\n                || \"Infinity\".equals(esDataTempBean.getComputeValue())\n                || \"NaN\".equals(esDataTempBean.getComputeValue())) {\n                continue;\n            }\n            esIndexDCDRStats.putMetrics(esDataTempBean.getValueName().substring(ES_INDICES.length()).replace(\".\", \"-\"),\n                esDataTempBean.getComputeValue());\n        }\n\n        return esIndexDCDRStats;\n    }\n\n    private void achieveIndexToNodeInfo(ESDataTempBean base, IndexNodes indexStats) {\n        try {\n            ESIndexToNodeTempBean temp = new ESIndexToNodeTempBean();\n            temp.setTimestamp(base.getTimestamp());\n            temp.setCluster(base.getCluster());\n            temp.setTemplate(base.getTemplate());\n            temp.setTemplateId(base.getTemplateId());\n            temp.setLogicTemplateId(base.getLogicTemplateId());\n            temp.setIndex(base.getIndex());\n\n            Map<String, List<CommonStat>> shards = indexStats.getShards();\n\n            Set<String> nodeIds = Sets.newHashSet();\n            for (Map.Entry<String, List<CommonStat>> entry : shards.entrySet()) {\n                for (CommonStat stat : entry.getValue()) {\n                    nodeIds.add(stat.getRouting().getNode());\n                }\n            }\n\n            temp.setNodes(nodeIds);\n            indexToNodeTemps.add(temp);\n        } catch (Exception e) {\n            LOGGER.error(\"class=MonitorClusterJob||method=achieveIndexToNodeInfo||clusterName={}||msg=exception\",\n                clusterName, e);\n        }\n    }\n\n    private void achieveAndSendNodeToIndexInfo(ESDataTempBean node, Map map, MetricsRegister metricsRegister) {\n        try {\n            Map indicesTotalMap = (Map) map.get(\"indices\");\n            Map indicesMap = (Map) indicesTotalMap.get(\"indices\");\n\n            List<ESNodeToIndexStats> esNodeToIndexStatsList = new ArrayList<>();\n            Map<String, List<ESNodeToIndexTempBean>> dataBeanMap = collectNodeToIndexData(node, indicesMap,\n                metricsRegister);\n            for (List<ESNodeToIndexTempBean> beanList : dataBeanMap.values()) {\n                esNodeToIndexStatsList.add(buildEsNodeToIndexStats(beanList.get(0), beanList, node.getTimestamp()));\n            }\n\n            monitorMetricsSender.sendESNodeToIndexStats(esNodeToIndexStatsList);\n        } catch (Exception e) {\n            LOGGER.error(\"class=MonitorClusterJob||method=achieveAndSendNodeToIndexInfo||clusterName={}||msg=exception\",\n                clusterName, e);\n        }\n    }\n\n    private void achieveAndSendIngestInfo(ESDataTempBean node, Map map, MetricsRegister metricsRegister) {\n        try {\n            Map ingest = (Map) map.get(\"ingest\");\n            if (ingest == null) {\n                return;\n            }\n\n            Map pipelines = (Map) ingest.get(\"pipelines\");\n            if (pipelines == null) {\n                return;\n            }\n\n            List<ESIngestStats> esIngestStatsList = new ArrayList<>();\n            Map<String, List<ESNodeToIndexTempBean>> dataBeanMap = collectIngestData(node, pipelines, metricsRegister);\n            for (List<ESNodeToIndexTempBean> beanList : dataBeanMap.values()) {\n                esIngestStatsList.add(buildESIngestStats(beanList.get(0), beanList, node.getTimestamp()));\n            }\n\n            monitorMetricsSender.sendIngestStats(esIngestStatsList);\n        } catch (Exception e) {\n            LOGGER.error(\"class=MonitorClusterJob||method=achieveAndSendIngestInfo||clusterName={}||msg=exception\",\n                clusterName, e);\n        }\n    }\n\n    /**\n     * 收集ingest指标\n     * @param node 节点\n     * @param pipelines ingest pipelines指标\n     * @param metricsRegister\n     * @return\n     */\n    private Map<String, List<ESNodeToIndexTempBean>> collectIngestData(ESDataTempBean node, Map pipelines,\n                                                                       MetricsRegister metricsRegister) {\n        Map<String, List<ESNodeToIndexTempBean>> pipelinesStats = Maps.newHashMap();\n        for (Object entry : pipelines.entrySet()) {\n            Map.Entry ingestEntry = (Map.Entry) entry;\n            String template = (String) ingestEntry.getKey();\n\n            if (template.startsWith(\".\")) {\n                continue;\n            }\n\n            IndexTemplatePhyWithLogic indexTemplate = getIndexTemplateByTemplateName(node.getCluster(), template);\n            if (null == indexTemplate) {\n                continue;\n            }\n\n            Map pipelineStats = (Map) ingestEntry.getValue();\n\n            ESNodeToIndexTempBean base = new ESNodeToIndexTempBean();\n            base.setTimestamp(node.getTimestamp());\n            base.setCluster(node.getCluster());\n            base.setNode(node.getNode());\n            base.setPort(node.getPort());\n            base.setIndex(template);\n            base.setTemplate(indexTemplate.getName());\n            base.setTemplateId(indexTemplate.getId());\n            base.setLogicTemplateId(indexTemplate.getLogicId());\n\n            List<ESNodeToIndexTempBean> dataBeans = aggrAndComputeNodeToIndexData(pipelineStats, ingestWorkOrders, base,\n                metricsRegister);\n            pipelinesStats.put(template, dataBeans);\n        }\n\n        return pipelinesStats;\n    }\n\n    /**\n     * 采集节点上的索引维度的数据\n     */\n    private Map<String, List<ESNodeToIndexTempBean>> collectNodeToIndexData(ESDataTempBean node, Map indexStatMap,\n                                                                            MetricsRegister metricsRegister) {\n        Map<String, List<ESNodeToIndexTempBean>> indexStats = Maps.newHashMap();\n        for (Object entry : indexStatMap.entrySet()) {\n            Map.Entry indexStatEntry = (Map.Entry) entry;\n            String indexName = (String) indexStatEntry.getKey();\n\n            IndexTemplatePhyWithLogic indexTemplate = getTemplateNameForCache(node.getCluster(), indexName);\n            if (null == indexTemplate) {\n                continue;\n            }\n\n            Map indexStat = (Map) indexStatEntry.getValue();\n\n            ESNodeToIndexTempBean base = new ESNodeToIndexTempBean();\n            base.setTimestamp(node.getTimestamp());\n            base.setCluster(node.getCluster());\n            base.setNode(node.getNode());\n            base.setPort(node.getPort());\n            base.setIndex(indexName);\n            base.setTemplate(indexTemplate.getName());\n            base.setTemplateId(indexTemplate.getId());\n            base.setLogicTemplateId(indexTemplate.getLogicId());\n\n            List<ESNodeToIndexTempBean> dataBeans = aggrAndComputeNodeToIndexData(indexStat, nodeToIndexWorkOrders,\n                base, metricsRegister);\n            indexStats.put(indexName, dataBeans);\n        }\n        return indexStats;\n    }\n\n    private List<ESNodeToIndexTempBean> aggrAndComputeNodeToIndexData(Map indexStat, List<CollectMetrics> workOrders,\n                                                                      ESNodeToIndexTempBean base,\n                                                                      MetricsRegister metricsRegister) {\n        List<ESNodeToIndexTempBean> result = Lists.newArrayList();\n        for (CollectMetrics workOrder : workOrders) {\n            try {\n                String valueName = workOrder.getValueName();\n                String valueRoute = workOrder.getValueRoute();\n                Double value = MonitorUtil.obj2Double(MonitorUtil.getValueByRoute(indexStat, valueRoute));\n\n                ESNodeToIndexTempBean dataBean = new ESNodeToIndexTempBean();\n                BeanUtils.copyProperties(base, dataBean);\n                dataBean.setValueName(valueName);\n                dataBean.setValue(value);\n                dataBean.setDeriveParam(workOrder.getDeriveParam());\n                dataBean.setTimestamp(base.getTimestamp());\n\n                ESNodeToIndexComputer computer = new ESNodeToIndexComputer(workOrder.getComputeType(), metricsRegister);\n                String computerValue = computer.compute(dataBean);\n\n                dataBean.setComputeValue(computerValue);\n\n                result.add(dataBean);\n            } catch (Exception e) {\n                LOGGER.error(\n                    \"class=MonitorClusterJob||method=aggrAndComputeNodeToIndexData||clusterName={}||msg=exception\",\n                    clusterName, e);\n            }\n        }\n        return result;\n    }\n\n    /**\n     * 将map中的数据交给计算模块去处理\n     * workOrders之间不能并发处理，workOrders之间会有相互依赖\n     * @param base\n     */\n    private List<ESDataTempBean> aggrAndComputeData(Map map, List<CollectMetrics> workOrders, ESDataTempBean base,\n                                                    MetricsRegister metricsRegister) {\n        List<ESDataTempBean> result = Lists.newArrayList();\n        for (CollectMetrics workOrder : workOrders) {\n            try {\n                String valueName = workOrder.getValueName();\n                String valueRoute = workOrder.getValueRoute();\n                Double value = MonitorUtil.obj2Double(MonitorUtil.getValueByRoute(map, valueRoute));\n\n                ESDataTempBean esDataTempBean = new ESDataTempBean();\n                BeanUtils.copyProperties(base, esDataTempBean);\n                esDataTempBean.setValueName(valueName);\n                esDataTempBean.setValue(value);\n                esDataTempBean.setDeriveParam(workOrder.getDeriveParam());\n                esDataTempBean.setSendToN9e(workOrder.isSendToN9e());\n                esDataTempBean\n                    .setComputeValue(workOrder.getComputeType().getComputer(metricsRegister).compute(esDataTempBean));\n\n                result.add(esDataTempBean);\n            } catch (Exception e) {\n                LOGGER.error(\"class=MonitorClusterJob||method=aggrAndComputeData||clusterName={}||msg=exception\",\n                    clusterName, e);\n            }\n        }\n        return result;\n    }\n\n    private ESIndexToNodeStats build(ESIndexToNodeTempBean temp, ESNodeStats esNodeStats,\n                                     List<CollectMetrics> indexToNodeWorkOrders) {\n        Set<String> metricsNameSet = Sets.newHashSet();\n        for (CollectMetrics workOrder : indexToNodeWorkOrders) {\n            metricsNameSet.add(workOrder.getValueName().substring(ES_NODE.length()).replace(\".\", \"-\"));\n        }\n\n        ESIndexToNodeStats indexToNodeStats = new ESIndexToNodeStats();\n        BeanUtils.copyProperties(temp, indexToNodeStats);\n        Map<String, String> metrics = Maps.newHashMap();\n\n        if (esNodeStats != null) {\n            indexToNodeStats.setNode(esNodeStats.getNode());\n            indexToNodeStats.setPort(esNodeStats.getPort());\n            indexToNodeStats.setRack(esNodeStats.getRack());\n\n            Map<String, String> metricsAll = esNodeStats.getMetrics();\n\n            for (Map.Entry<String, String> entry : metricsAll.entrySet()) {\n                if (StringUtils.isEmpty(entry.getValue()) || \"null\".equals(entry.getValue())\n                    || \"Infinity\".equals(entry.getValue()) || \"NaN\".equals(entry.getValue())) {\n                    continue;\n                }\n                String key = entry.getKey();\n                if (metricsNameSet.contains(key)) {\n                    metrics.put(key, entry.getValue());\n                }\n            }\n        }\n        indexToNodeStats.setMetrics(metrics);\n\n        return indexToNodeStats;\n    }\n\n    private ESNodeStats buildESNodeStats(ESDataTempBean bean, List<ESDataTempBean> metricsList) {\n        ESNodeStats esNodeStats = new ESNodeStats();\n        esNodeStats.setTimestamp(bean.getTimestamp());\n        esNodeStats.setCluster(bean.getCluster());\n        esNodeStats.setNode(bean.getNode());\n        esNodeStats.setIp(bean.getIp());\n        esNodeStats.setPort(bean.getPort());\n        esNodeStats.setMetrics(Maps.newHashMap());\n        esNodeStats.setRack(bean.getRack());\n\n        for (ESDataTempBean esDataTempBean : metricsList) {\n            if (StringUtils.isEmpty(esDataTempBean.getComputeValue()) || \"null\".equals(esDataTempBean.getComputeValue())\n                || \"Infinity\".equals(esDataTempBean.getComputeValue())\n                || \"NaN\".equals(esDataTempBean.getComputeValue())) {\n                continue;\n            }\n\n            esNodeStats.putMetrics(esDataTempBean.getValueName().substring(ES_NODE.length()).replace(\".\", \"-\"),\n                esDataTempBean.getComputeValue());\n        }\n\n        return esNodeStats;\n    }\n\n    private ESIndexStats buildESIndexStats(ESDataTempBean bean, List<ESDataTempBean> metricsList) {\n        ESIndexStats esIndexStats = new ESIndexStats();\n        esIndexStats.setTimestamp(bean.getTimestamp());\n        esIndexStats.setCluster(bean.getCluster());\n        esIndexStats.setTemplate(bean.getTemplate());\n        esIndexStats.setTemplateId(bean.getTemplateId());\n        esIndexStats.setLogicTemplateId(bean.getLogicTemplateId());\n        esIndexStats.setIndex(bean.getIndex());\n        esIndexStats.setShardNu(bean.getShardNu());\n        esIndexStats.setMetrics(Maps.newHashMap());\n\n        for (ESDataTempBean esDataTempBean : metricsList) {\n            if (StringUtils.isEmpty(esDataTempBean.getComputeValue()) || \"null\".equals(esDataTempBean.getComputeValue())\n                || \"Infinity\".equals(esDataTempBean.getComputeValue())\n                || \"NaN\".equals(esDataTempBean.getComputeValue())) {\n                continue;\n            }\n\n            esIndexStats.putMetrics(esDataTempBean.getValueName().substring(ES_INDICES.length()).replace(\".\", \"-\"),\n                esDataTempBean.getComputeValue());\n        }\n\n        esIndexStats.putMetrics(\"shardNu\", String.valueOf(bean.getShardNu()));\n\n        return esIndexStats;\n    }\n\n    private ESNodeToIndexStats buildEsNodeToIndexStats(ESNodeToIndexTempBean base,\n                                                       List<ESNodeToIndexTempBean> metricsList, long timestamp) {\n        ESNodeToIndexStats esNodeToIndexStats = new ESNodeToIndexStats();\n        esNodeToIndexStats.setCluster(base.getCluster());\n        esNodeToIndexStats.setIndex(base.getIndex());\n        esNodeToIndexStats.setNode(base.getNode());\n        esNodeToIndexStats.setPort(base.getPort());\n        esNodeToIndexStats.setTemplate(base.getTemplate());\n        esNodeToIndexStats.setTemplateId(base.getTemplateId());\n        esNodeToIndexStats.setLogicTemplateId(base.getLogicTemplateId());\n        esNodeToIndexStats.setTimestamp(timestamp);\n        for (ESNodeToIndexTempBean bean : metricsList) {\n            if (StringUtils.isEmpty(bean.getComputeValue()) || \"null\".equals(bean.getComputeValue())\n                || \"Infinity\".equals(bean.getComputeValue()) || \"NaN\".equals(bean.getComputeValue())) {\n                continue;\n            }\n\n            esNodeToIndexStats.putMetrics(bean.getValueName().substring(\"es.node.index.\".length()).replace(\".\", \"-\"),\n                bean.getComputeValue());\n        }\n\n        return esNodeToIndexStats;\n    }\n\n    /**\n     * 构建ingest的指标\n     * @param base base指标\n     * @param metricsList 指标列表\n     * @param timestamp 时间戳\n     * @return ESIngestStats对象\n     */\n    private ESIngestStats buildESIngestStats(ESNodeToIndexTempBean base, List<ESNodeToIndexTempBean> metricsList,\n                                             long timestamp) {\n        ESIngestStats ingestStats = new ESIngestStats();\n        ingestStats.setCluster(base.getCluster());\n        ingestStats.setNode(base.getNode());\n        ingestStats.setPort(base.getPort());\n        ingestStats.setTemplate(base.getTemplate());\n        ingestStats.setTemplateId(base.getTemplateId());\n        ingestStats.setLogicTemplateId(base.getLogicTemplateId());\n        ingestStats.setTimestamp(timestamp);\n        for (ESNodeToIndexTempBean bean : metricsList) {\n            if (StringUtils.isEmpty(bean.getComputeValue()) || \"null\".equals(bean.getComputeValue())\n                || \"Infinity\".equals(bean.getComputeValue()) || \"NaN\".equals(bean.getComputeValue())) {\n                continue;\n            }\n\n            ingestStats.putMetrics(bean.getValueName().substring(ES_NODE.length()).replace(\".\", \"-\"),\n                bean.getComputeValue());\n        }\n\n        return ingestStats;\n    }\n\n    /**\n     * 根据索引获取模板名称\n     * @param cluster\n     * @param indexName\n     * @return\n     */\n    private IndexTemplatePhyWithLogic getTemplateNameForCache(String cluster, String indexName) {\n        try {\n            return indexTemplateCache.get(cluster + \"@\" + indexName, () -> getTemplateName(cluster, indexName));\n        } catch (Exception e) {\n            //pass\n        }\n        return null;\n    }\n\n    /**\n     * 根据集群和模板名称获取IndexTemplate对象\n     * @param cluster 集群名称\n     * @param templateName 模板名称\n     * @return IndexTemplate对象\n     */\n    private IndexTemplatePhyWithLogic getIndexTemplateByTemplateName(String cluster, String templateName) {\n        for (IndexTemplatePhyWithLogic indexTemplate : indexTemplates) {\n            String indexTemplateCluster = indexTemplate.getCluster();\n            String name = indexTemplate.getName();\n\n            if (indexTemplateCluster.equals(cluster) && name.equals(templateName)) {\n                return indexTemplate;\n            }\n        }\n\n        return null;\n    }\n\n    private IndexTemplatePhyWithLogic getTemplateName(String cluster, String indexName) {\n        for (IndexTemplatePhyWithLogic indexTemplate : indexTemplates) {\n            String indexTemplateCluster = indexTemplate.getCluster();\n            String expression = indexTemplate.getExpression();\n            String expressionWhoutAsterisk = \"\";\n\n            if (expression.endsWith(\"*\")) {\n                expressionWhoutAsterisk = expression.substring(0, expression.length() - 1);\n            } else {\n                expressionWhoutAsterisk = expression;\n            }\n\n            if (indexName.startsWith(expressionWhoutAsterisk)) {\n                IndexTemplatePhyWithLogic indexTemplate1 = getIndexTemplatePhyWithLogic(cluster, indexName,\n                    indexTemplate, indexTemplateCluster, expression);\n                if (indexTemplate1 != null) {\n                    return indexTemplate1;\n                }\n            }\n        }\n\n        return null;\n    }\n\n    private IndexTemplatePhyWithLogic getIndexTemplatePhyWithLogic(String cluster, String indexName,\n                                                                   IndexTemplatePhyWithLogic indexTemplate,\n                                                                   String clusterName, String expression) {\n        String dataFormat = indexTemplate.getLogicTemplate().getDateFormat();\n\n        if (!expression.endsWith(\"*\") || StringUtils.isEmpty(dataFormat)\n            || \"null\".equals(dataFormat) && (indexName.equals(expression) && cluster.equals(clusterName))) {\n            return indexTemplate;\n        }\n\n        if (isMatch(indexName, expression, dataFormat) && cluster.equals(clusterName)) {\n            return indexTemplate;\n        }\n\n        //时间后缀变更\n        for (String otherFormat : DATA_FORMATS) {\n            if (otherFormat.equals(dataFormat)) {\n                continue;\n            }\n            if (isMatch(indexName, expression, otherFormat) && cluster.equals(clusterName)) {\n                return indexTemplate;\n            }\n        }\n        return null;\n    }\n\n    private String genIndexNameClear(String indexName, String expression, String dateFormat) {\n        Matcher m = pattern.matcher(indexName);\n\n        if (!m.find() || StringUtils.isNotBlank(m.group(GROUP))) {\n            //校验是否是当前模板的\n            if (indexName.length() != (expression.length() - 1 + dateFormat.length())) {\n                return \"\";\n            }\n            return indexName;\n        }\n\n        String indexNameClear = m.group(1);\n        if (indexNameClear.length() != (expression.length() - 1 + dateFormat.length())) {\n            return \"\";\n        }\n\n        return indexNameClear;\n    }\n\n    private boolean isMatch(String indexName, String expression, String dataFormat) {\n        String indexNameNoVersion = genIndexNameClear(indexName, expression, dataFormat);\n\n        if (StringUtils.isNotBlank(indexNameNoVersion)) {\n            String indexNameForTemplate = expression.replace(\"*\", \"\") + dataFormat;\n            if (indexNameNoVersion.length() == indexNameForTemplate.length()) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    private List<ESDataTempBean> genIndexTotalCommonStatsMetric(long totalSize, long totalDocCount,\n                                                                ESDataTempBean base) {\n        ESDataTempBean totalSizeBean = new ESDataTempBean();\n        BeanUtils.copyProperties(base, totalSizeBean);\n        totalSizeBean.setValueName(\"es.indices.store.size_in_bytes.total\");\n        totalSizeBean.setValue((double) totalSize);\n        totalSizeBean.setComputeValue(String.valueOf(totalSizeBean.getValue()));\n\n        ESDataTempBean totalDocsBean = new ESDataTempBean();\n        BeanUtils.copyProperties(base, totalDocsBean);\n        totalDocsBean.setValueName(\"es.indices.docs.count.total\");\n        totalDocsBean.setValue((double) totalDocCount);\n        totalDocsBean.setComputeValue(String.valueOf(totalDocsBean.getValue()));\n\n        return Lists.newArrayList(totalSizeBean, totalDocsBean);\n    }\n\n    private boolean indexSkip(String indexName) {\n        return (indexName.startsWith(\".monitoring\") || indexName.startsWith(\".marvel\")\n                || indexName.startsWith(\".kibana\"));\n    }\n\n    /**\n     * 转换并加入原索引统计信息\n     *\n     * @param destTemplateIndexStatsMap\n     * @param sourceTemplateSampleIndexStatsMap\n     * @param esIndexStatsList\n     */\n    private void addSourceTemplateIndexStats(Map<String, List<ESIndexStats>> destTemplateIndexStatsMap,\n                                             Map<String, ESIndexStats> sourceTemplateSampleIndexStatsMap,\n                                             List<ESIndexStats> esIndexStatsList) {\n        try {\n            // 存储多type改造 查询原索引的统计信息，需要将查询映射后的单type索引的统计信息进行汇聚\n            for (Map.Entry<String/*source templateName*/, List<ESIndexStats>/*dest index stats*/> entry : destTemplateIndexStatsMap\n                .entrySet()) {\n                // 目标索引统计信息集合，进行指标汇聚\n                Map<String/*source index name*/, ESIndexStats/*dest index merge stats*/> sourceIndexNameIndexStatsMap = Maps\n                    .newHashMap();\n                // 某个索引个数统计用于求均值\n                Map<String/*source index name*/, AtomicInteger> sourceIndexNameCountMap = Maps.newHashMap();\n\n                ESIndexStats destMergeIndexStats = null;\n                ESIndexStats sourceIndexStats = null;\n                for (ESIndexStats destIndexStats : entry.getValue()) {\n                    // 将索引名称替换为原索引名称，包含时间分区\n                    String sourceIndexName = destIndexStats.getIndex().replaceFirst(destIndexStats.getTemplate(),\n                        entry.getKey());\n                    destMergeIndexStats = sourceIndexNameIndexStatsMap.get(sourceIndexName);\n                    if (Objects.isNull(destMergeIndexStats)) {\n                        sourceIndexStats = sourceTemplateSampleIndexStatsMap.get(entry.getKey());\n                        if (Objects.nonNull(sourceIndexStats)) {\n                            destIndexStats.setLogicTemplateId(sourceIndexStats.getLogicTemplateId());\n                            destIndexStats.setTemplate(sourceIndexStats.getTemplate());\n                            destIndexStats.setTemplateId(sourceIndexStats.getTemplateId());\n                            destIndexStats.setShardNu(sourceIndexStats.getShardNu());\n                        }\n                        destIndexStats.setIndex(sourceIndexName);\n                        sourceIndexNameIndexStatsMap.put(sourceIndexName, destIndexStats);\n                        sourceIndexNameCountMap.put(sourceIndexName, new AtomicInteger(1));\n                        continue;\n                    }\n                    // 指标数据合并\n                    destMergeIndexStats = mergeIndexStats(destMergeIndexStats, destIndexStats);\n                    sourceIndexNameIndexStatsMap.put(sourceIndexName, destMergeIndexStats);\n                    sourceIndexNameCountMap.get(sourceIndexName).incrementAndGet();\n                }\n\n                // 将指标数据合并后的统计值加入到待发送索引指标集合中\n                // 处理求平均的指标项\n                handleAvgIndexStats(esIndexStatsList, sourceIndexNameIndexStatsMap, sourceIndexNameCountMap);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=MonitorClusterJob||method=addSourceTemplateIndexStats||clusterName={}||msg=exception\",\n                clusterName, e);\n        }\n    }\n\n    private void handleAvgIndexStats(List<ESIndexStats> esIndexStatsList,\n                                     Map<String, ESIndexStats> sourceIndexNameIndexStatsMap,\n                                     Map<String, AtomicInteger> sourceIndexNameCountMap) {\n        for (Map.Entry<String/*source index name*/, ESIndexStats/*dest index merge stats*/> indexNameEntry : sourceIndexNameIndexStatsMap\n            .entrySet()) {\n            Iterator<Map.Entry<String/*metrics name*/, String/*metrics vale*/>> iterator = indexNameEntry.getValue()\n                .getMetrics().entrySet().iterator();\n            Map.Entry<String/*metrics name*/, String/*metrics vale*/> metricsEntry = null;\n            Integer count = sourceIndexNameCountMap.get(indexNameEntry.getKey()).get();\n\n            while (iterator.hasNext()) {\n                metricsEntry = iterator.next();\n                if (metricsEntry.getKey().contains(\"avg\")) {\n                    Double sum = Double.valueOf(metricsEntry.getValue());\n                    metricsEntry.setValue(String.valueOf(sum / count));\n                }\n            }\n            esIndexStatsList.add(indexNameEntry.getValue());\n        }\n    }\n\n    /**\n     * 索引指标数据合并\n     *\n     * @param mergeIndexStats\n     * @param indexStats\n     * @return\n     */\n    private ESIndexStats mergeIndexStats(ESIndexStats mergeIndexStats, ESIndexStats indexStats) {\n        String num1 = \"\";\n        String num2 = \"\";\n        String key = \"\";\n        try {\n            Iterator<Map.Entry<String/*metrics name*/, String/*metrics vale*/>> iterator = mergeIndexStats.getMetrics()\n                .entrySet().iterator();\n            Map.Entry<String/*metrics name*/, String/*metrics vale*/> entry = null;\n            while (iterator.hasNext()) {\n                entry = iterator.next();\n                key = entry.getKey();\n                num1 = entry.getValue();\n                num2 = indexStats.getMetrics().get(key);\n                if (StringUtils.isBlank(num1)) {\n                    num1 = \"0\";\n                }\n                if (StringUtils.isBlank(num2)) {\n                    num2 = \"0\";\n                }\n                Double sum = Double.valueOf(num1) + Double.valueOf(num2);\n                entry.setValue(String.valueOf(sum));\n            }\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=MonitorClusterJob||method=mergeIndexStats||clusterName={}||key={}||num1={}||num2={}||msg=exception\",\n                clusterName, key, num1, num2, e);\n        }\n\n        return mergeIndexStats;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/MonitorCollectMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESDataTempBean;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics.CollectMetrics;\nimport com.google.common.collect.Lists;\n\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\nimport static com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics.MetricsComputeType.*;\n\npublic class MonitorCollectMetrics {\n\n    private MonitorCollectMetrics() {\n    }\n\n    private static final String INDEXING_INDEX_TOTAL          = \"indexing.index_total\";\n    private static final String INDEXING_INDEX_TIME_IN_MILLIS = \"indexing.index_time_in_millis\";\n    private static final String MERGES_TOTAL                  = \"merges.total\";\n    private static final String SEARCH_QUERY_TIME_IN_MILLIS   = \"search.query_time_in_millis\";\n    private static final String SEARCH_FETCH_TIME_IN_MILLIS   = \"search.fetch_time_in_millis\";\n    private static final String SEARCH_SCROLL_TIME_IN_MILLIS  = \"search.scroll_time_in_millis\";\n    private static final String STORE_SIZE_IN_BYTES           = \"store.size_in_bytes\";\n\n    /**\n     * 采集线程会顺序执行以下指标采集,所有复合计算的最好放最后,这样不会导致因为复合计算需要的参数没有算出来导致失败\n     */\n    public static List<CollectMetrics> initIndexDataRegisterMap() {\n        CopyOnWriteArrayList<CollectMetrics> indexWorkOrders = Lists.newCopyOnWriteArrayList();\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indexing.index_total\")\n            .valueRoute(INDEXING_INDEX_TOTAL).computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indexing.index_total_times\")\n            .valueRoute(INDEXING_INDEX_TOTAL).computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indexing.index_time_in_millis_rate\")\n            .valueRoute(INDEXING_INDEX_TIME_IN_MILLIS).computeType(AVG).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.merges.current\")\n            .valueRoute(\"merges.current\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.merges.total\")\n            .valueRoute(MERGES_TOTAL).computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.merges.total_rate\")\n            .valueRoute(MERGES_TOTAL).computeType(AVG_MIN).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.merges.total_time_in_millis\")\n            .valueRoute(\"merges.total_time_in_millis\").computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.query_cache.memory_size_in_bytes\")\n            .valueRoute(\"query_cache.memory_size_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.count\")\n            .valueRoute(\"segments.count\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.stored_fields_memory_in_bytes\")\n            .valueRoute(\"segments.stored_fields_memory_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.term_vectors_memory_in_bytes\")\n            .valueRoute(\"segments.terms_memory_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.points_memory_in_bytes\")\n            .valueRoute(\"segments.points_memory_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.doc_values_memory_in_bytes\")\n            .valueRoute(\"segments.doc_values_memory_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.index_writer_memory_in_bytes\")\n            .valueRoute(\"segments.index_writer_memory_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.translog.size_in_bytes\")\n            .valueRoute(\"translog.size_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.query_total_rate\")\n            .valueRoute(\"search.query_total\").computeType(AVG).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.query_total\")\n            .valueRoute(\"search.query_total\").computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.fetch_total_rate\")\n            .valueRoute(\"search.fetch_total\").computeType(AVG).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.scroll_total_rate\")\n            .valueRoute(\"search.scroll_total\").computeType(AVG).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.scroll_total\")\n                .valueRoute(\"search.scroll_total\").computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.query_time_in_millis\")\n            .valueRoute(SEARCH_QUERY_TIME_IN_MILLIS).computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.query_time_in_millis_rate\")\n            .valueRoute(SEARCH_QUERY_TIME_IN_MILLIS).computeType(AVG).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.fetch_time_in_millis\")\n            .valueRoute(SEARCH_FETCH_TIME_IN_MILLIS).computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.fetch_time_in_millis_rate\")\n            .valueRoute(SEARCH_FETCH_TIME_IN_MILLIS).computeType(AVG).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.scroll_time_in_millis\")\n            .valueRoute(SEARCH_SCROLL_TIME_IN_MILLIS).computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.scroll_time_in_millis_rate\")\n            .valueRoute(SEARCH_SCROLL_TIME_IN_MILLIS).computeType(AVG).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.refresh.total\")\n            .valueRoute(\"refresh.total\").computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.refresh.total_rate\")\n            .valueRoute(\"refresh.total\").computeType(AVG_MIN).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.refresh.total_time_in_millis\")\n            .valueRoute(\"refresh.total_time_in_millis\").computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.flush.total\")\n                .valueRoute(\"flush.total\").computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.flush.total_rate\")\n            .valueRoute(\"flush.total\").computeType(AVG_MIN).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.flush.total_time_in_millis\")\n            .valueRoute(\"flush.total_time_in_millis\").computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indexing.index_failed_rate\")\n            .valueRoute(\"indexing.index_failed\").computeType(AVG).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.store.size_in_bytes\")\n            .valueRoute(STORE_SIZE_IN_BYTES).computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.store.size_in_bytes_rate\")\n            .valueRoute(STORE_SIZE_IN_BYTES).computeType(AVG).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.docs.count\")\n            .valueRoute(\"docs.count\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.memory_in_bytes\")\n            .valueRoute(\"segments.memory_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.norms_memory_in_bytes\")\n                .valueRoute(\"segments.norms_memory_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.version_map_memory_in_bytes\")\n                .valueRoute(\"segments.version_map_memory_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.fixed_bit_set_memory_in_bytes\")\n                .valueRoute(\"segments.fixed_bit_set_memory_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.fielddata.memory_size_in_bytes\")\n                .valueRoute(\"fielddata.memory_size_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.segments.breakers.fieldd.limit_size_in_bytes\")\n                .valueRoute(\"segments.breakers.fielddata.limit_size_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.search.fetch_total\")\n                .valueRoute(\"search.fetch_total\").computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.request_cache.memory_size_in_bytes\")\n                .valueRoute(\"request_cache.memory_size_in_bytes\").computeType(NONE).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indexing.index_time_in_millis\")\n                .valueRoute(INDEXING_INDEX_TIME_IN_MILLIS).computeType(MINUS).sendToN9e().build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indexing.index_total_rate\")\n                .valueRoute(\"docs.count\").computeType(AVG).sendToN9e().build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indexing.docs.count_diff\")\n                .valueRoute(INDEXING_INDEX_TOTAL).computeType(MINUS).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indices.indexing.index_time_per_doc\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.indexing.index_time_in_millis\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.indexing.docs.count_diff\").computeType(DERIVE_DIVISION)\n            .build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indices.indexing.index_latency\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.indexing.index_time_in_millis_rate\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.indexing.index_total_rate\").computeType(DERIVE_DIVISION)\n            .build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indices.search.query_avg_time\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.search.query_time_in_millis_rate\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.search.query_total_rate\").computeType(DERIVE_DIVISION)\n            .build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indices.search.fetch_avg_time\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.search.fetch_time_in_millis_rate\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.search.fetch_total_rate\").computeType(DERIVE_DIVISION)\n            .build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indices.search.scroll_avg_time\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.search.scroll_time_in_millis_rate\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.search.scroll_total_rate\").computeType(DERIVE_DIVISION)\n            .build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indices.refresh_avg_time\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.refresh.total_time_in_millis\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.refresh.total\").computeType(DERIVE_DIVISION).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.indices.flush_avg_time\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.flush.total_time_in_millis\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.flush.total\").computeType(DERIVE_DIVISION).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.cost.merges.total_time_in_millis\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.merges.total_time_in_millis\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.merges.total\").computeType(DERIVE_DIVISION).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.cost.index_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.indexing.total_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.indexing.docs.count_diff\").computeType(DERIVE_DIVISION).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.cost.query_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.search.query_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.search.query_total\").computeType(DERIVE_DIVISION).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.cost.fetch_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.search.fetch_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.search.fetch_total\").computeType(DERIVE_DIVISION).build());\n        \n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.cost.scroll_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.search.scroll_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.search.scroll_total\").computeType(DERIVE_DIVISION).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.cost.refresh.total_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.refresh.total_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.refresh.total\").computeType(DERIVE_DIVISION).build());\n\n        indexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.cost.flush.total_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.flush.total_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.flush.total\").computeType(DERIVE_DIVISION).build());\n\n        return indexWorkOrders;\n    }\n\n    /**\n     * 采集线程会顺序执行以下指标采集,所有复合计算的最好放最后,这样不会导致因为复合计算需要的参数没有算出来导致失败\n     */\n    public static List<CollectMetrics> initNodeDataRegisterMap() {\n        CopyOnWriteArrayList<CollectMetrics> nodeWorkOrders = Lists.newCopyOnWriteArrayList();\n\n        /**********************************node -> indices*******************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.indexing.index_total\")\n            .valueRoute(\"indices.indexing.index_total\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.indexing.index_time_in_millis\")\n            .valueRoute(\"indices.indexing.index_time_in_millis\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.query_total\")\n            .valueRoute(\"indices.search.query_total\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.fetch_total\")\n                .valueRoute(\"indices.search.fetch_total\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.scroll_current\")\n            .valueRoute(\"indices.search.scroll_current\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.translog.uncommitted_size_in_bytes\")\n            .valueRoute(\"indices.translog.uncommitted_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.stored_fields_memory_in_bytes\")\n            .valueRoute(\"indices.segments.stored_fields_memory_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.norms_memory_in_bytes\")\n            .valueRoute(\"indices.segments.norms_memory_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.version_map_memory_in_bytes\")\n            .valueRoute(\"indices.segments.version_map_memory_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.version_map_memory_in_bytes\")\n            .valueRoute(\"indices.segments.version_map_memory_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.fixed_bit_set_memory_in_bytes\")\n            .valueRoute(\"indices.segments.fixed_bit_set_memory_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.breakers.fielddata.limit_size_in_bytes\")\n            .valueRoute(\"indices.segments.breakers.fielddata.limit_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.query_cache.memory_size_in_bytes\")\n            .valueRoute(\"indices.query_cache.memory_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.request_cache.memory_size_in_bytes\")\n            .valueRoute(\"indices.request_cache.memory_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.request_cache.hit_count\")\n            .valueRoute(\"indices.request_cache.hit_count\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.query_cache.hit_count\")\n            .valueRoute(\"indices.query_cache.hit_count\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.request_cache.miss_count\")\n            .valueRoute(\"indices.request_cache.miss_count\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.query_cache.miss_count\")\n            .valueRoute(\"indices.query_cache.miss_count\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.request_cache.total_count\")\n            .valueRoute(\"indices.request_cache.hit_count+indices.request_cache.miss_count\").computeType(MINUS)\n                .bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.query_cache.total_count\")\n            .valueRoute(\"indices.query_cache.total_count\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.query_time_in_millis\")\n            .valueRoute(\"indices.search.query_time_in_millis\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.fetch_time_in_millis\")\n            .valueRoute(\"indices.search.fetch_time_in_millis\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.scroll_time_in_millis\")\n            .valueRoute(\"indices.search.scroll_time_in_millis\").computeType(MINUS).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.merges.current\")\n            .valueRoute(\"indices.merges.current\").computeType(NONE).sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.merges.total\")\n            .valueRoute(\"indices.merges.total\").computeType(AVG_MIN).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.merges.total_time_in_millis\")\n            .valueRoute(\"indices.merges.total_time_in_millis\").computeType(MINUS).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.refresh.total\")\n            .valueRoute(\"indices.refresh.total\").computeType(AVG_MIN).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.refresh.total_time_in_millis\")\n            .valueRoute(\"indices.refresh.total_time_in_millis\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.flush.total\")\n            .valueRoute(\"indices.flush.total\").computeType(AVG_MIN).sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.flush.total_time_in_millis\")\n            .valueRoute(\"indices.flush.total_time_in_millis\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.count\")\n            .valueRoute(\"indices.segments.count\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.memory_in_bytes\")\n            .valueRoute(\"indices.segments.memory_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.term_vectors_memory_in_bytes\")\n            .valueRoute(\"indices.segments.terms_memory_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.points_memory_in_bytes\")\n            .valueRoute(\"indices.segments.points_memory_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.doc_values_memory_in_bytes\")\n            .valueRoute(\"indices.segments.doc_values_memory_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.segments.index_writer_memory_in_bytes\")\n            .valueRoute(\"indices.segments.index_writer_memory_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.docs.count\")\n            .valueRoute(\"indices.docs.count\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.docs.count_diff\")\n            .valueRoute(\"indices.indexing.index_total\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.translog.operations_rate\")\n            .valueRoute(\"indices.translog.operations\").computeType(AVG).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.store.size_in_bytes\")\n            .valueRoute(\"indices.store.size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.indexing.index_total_rate\")\n            .valueRoute(\"indices.indexing.index_total\").computeType(AVG).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.indexing.index_time_in_millis_rate\")\n            .valueRoute(\"indices.indexing.index_time_in_millis\").computeType(AVG).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.indexing.delete_total_rate\")\n            .valueRoute(\"indices.indexing.delete_total\").computeType(AVG).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.query_total_rate\")\n            .valueRoute(\"indices.search.query_total\").computeType(AVG).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.query_time_in_millis_rate\")\n            .valueRoute(\"indices.search.query_time_in_millis\").computeType(AVG).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.fetch_total_rate\")\n            .valueRoute(\"indices.search.fetch_total\").computeType(AVG).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.scroll_total\")\n                .valueRoute(\"indices.search.scroll_total\").computeType(MINUS).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.query_cache.evictions\")\n            .valueRoute(\"indices.query_cache.evictions\").computeType(AVG).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.request_cache.evictions\")\n                .valueRoute(\"indices.request_cache.evictions\").computeType(AVG).bIndexToNodeMetrics().build());\n\n        /**********************************node -> http*****************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.http.current_open\")\n            .valueRoute(\"http.current_open\").computeType(NONE).build());\n\n        /**********************************node -> jvm*****************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.mem.heap_used_percent\")\n            .valueRoute(\"jvm.mem.heap_used_percent\").computeType(NONE).bIndexToNodeMetrics().sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.mem.heap_used_in_bytes\")\n            .valueRoute(\"jvm.mem.heap_used_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.mem.non_heap_used_in_bytes\")\n            .valueRoute(\"jvm.mem.non_heap_used_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.mem.pools.young.used_in_bytes\")\n            .valueRoute(\"jvm.mem.pools.young.used_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.mem.pools.old.used_in_bytes\")\n            .valueRoute(\"jvm.mem.pools.old.used_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.threads.count\")\n            .valueRoute(\"jvm.threads.count\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.gc.young.collection_time_in_millis\")\n            .valueRoute(\"jvm.gc.collectors.young.collection_time_in_millis\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.gc.old.collection_time_in_millis\")\n            .valueRoute(\"jvm.gc.collectors.old.collection_time_in_millis\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.gc.young.collection_count\")\n                .valueRoute(\"jvm.gc.collectors.young.collection_count\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.gc.old.collection_count\")\n                .valueRoute(\"jvm.gc.collectors.old.collection_count\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.gc.young.collection_count_rate\")\n            .valueRoute(\"jvm.gc.collectors.young.collection_count\").computeType(AVG).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.gc.old.collection_count_rate\")\n            .valueRoute(\"jvm.gc.collectors.old.collection_count\").computeType(AVG).bIndexToNodeMetrics().build());\n        /**********************************node -> os*****************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.os.cpu.percent\").valueRoute(\"os.cpu.percent\")\n            .computeType(NONE).bIndexToNodeMetrics().sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.os.cpu.load_average.1m\")\n            .valueRoute(\"os.cpu.load_average.1m\").computeType(NONE).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.os.cpu.load_average.5m\")\n            .valueRoute(\"os.cpu.load_average.5m\").computeType(NONE).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.os.cpu.load_average.15m\")\n            .valueRoute(\"os.cpu.load_average.15m\").computeType(NONE).bIndexToNodeMetrics().build());\n\n        /**********************************node -> thread_pool************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.bulk.rejected\")\n            .valueRoute(\"thread_pool.bulk.rejected\").computeType(AVG_MIN).bIndexToNodeMetrics().sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.bulk.completed\")\n            .valueRoute(\"thread_pool.bulk.completed\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.bulk.queue\")\n            .valueRoute(\"thread_pool.bulk.queue\").computeType(NONE).bIndexToNodeMetrics().sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.write.rejected\")\n            .valueRoute(\"thread_pool.write.rejected\").computeType(MINUS).bIndexToNodeMetrics().sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.write.completed\")\n            .valueRoute(\"thread_pool.write.completed\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.write.queue\")\n            .valueRoute(\"thread_pool.write.queue\").computeType(NONE).bIndexToNodeMetrics().sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.search.rejected\")\n            .valueRoute(\"thread_pool.search.rejected\").computeType(AVG_MIN).sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.search.completed\")\n            .valueRoute(\"thread_pool.search.completed\").computeType(MINUS).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.refresh.queue\")\n                .valueRoute(\"thread_pool.refresh.queue\").computeType(NONE).sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.rollup_indexing.queue\")\n                .valueRoute(\"thread_pool.rollup_indexing.queue\").computeType(NONE).sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.management.queue\")\n                .valueRoute(\"thread_pool.management.queue\").computeType(NONE).sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.force_merge.queue\")\n                .valueRoute(\"thread_pool.force_merge.queue\").computeType(NONE).sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.thread_pool.search.queue\")\n            .valueRoute(\"thread_pool.search.queue\").computeType(NONE).sendToN9e().build());\n\n        /**********************************node -> transport************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.transport.server_open\")\n            .valueRoute(\"transport.server_open\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.transport.rx_count_rate\")\n            .valueRoute(\"transport.rx_count\").computeType(AVG).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.transport.rx_size_in_bytes_rate\")\n            .valueRoute(\"transport.rx_size_in_bytes\").computeType(AVG).sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.transport.tx_count_rate\")\n            .valueRoute(\"transport.tx_count\").computeType(AVG).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.transport.tx_size_in_bytes_rate\")\n            .valueRoute(\"transport.tx_size_in_bytes\").computeType(AVG).sendToN9e().build());\n\n        /**********************************node -> fs************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.fs.total.disk_free_percent\")\n            .valueRoute(\"fs.total.free_in_bytes/fs.total.total_in_bytes\").computeType(NONE).bIndexToNodeMetrics()\n            .sendToN9e().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.fs.total.total_in_bytes\")\n            .valueRoute(\"fs.total.total_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.fs.total.free_in_bytes\")\n            .valueRoute(\"fs.total.free_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.fs.total.available_in_bytes\")\n            .valueRoute(\"fs.total.available_in_bytes\").computeType(NONE).build());\n\n        /**********************************node -> process************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.process.cpu.percent\")\n            .valueRoute(\"process.cpu.percent\").computeType(NONE).bIndexToNodeMetrics().build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.process.process.open_file_descriptors\")\n            .valueRoute(\"process.open_file_descriptors\").computeType(NONE).build());\n\n        /**********************************node -> ingest************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.ingest.total.count\")\n            .valueRoute(\"ingest.total.count\").computeType(AVG).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.ingest.total.time_in_millis\")\n            .valueRoute(\"ingest.total.time_in_millis\").computeType(AVG).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.ingest.total.failed\")\n            .valueRoute(\"ingest.total.failed\").computeType(AVG).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.ingest.total.current\")\n            .valueRoute(\"ingest.total.current\").computeType(NONE).build());\n\n        /**********************************node -> breakers************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.breakers.fielddata.limit_size_in_bytes\")\n                .valueRoute(\"breakers.fielddata.limit_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.breakers.fielddata.estimated_size_in_bytes\")\n                .valueRoute(\"breakers.fielddata.estimated_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.breakers.request.limit_size_in_bytes\")\n                .valueRoute(\"breakers.request.limit_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.breakers.request.estimated_size_in_bytes\")\n                .valueRoute(\"breakers.request.estimated_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.breakers.in_flight_requests.limit_size_in_bytes\")\n                .valueRoute(\"breakers.in_flight_requests.limit_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.breakers.in_flight_requests.estimated_size_in_bytes\")\n                .valueRoute(\"breakers.in_flight_requests.estimated_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.breakers.accounting.limit_size_in_bytes\")\n                .valueRoute(\"breakers.accounting.limit_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.breakers.accounting.estimated_size_in_bytes\")\n                .valueRoute(\"breakers.accounting.estimated_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.breakers.parent.limit_size_in_bytes\")\n                .valueRoute(\"breakers.parent.limit_size_in_bytes\").computeType(NONE).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.breakers.parent.estimated_size_in_bytes\")\n                .valueRoute(\"breakers.parent.estimated_size_in_bytes\").computeType(NONE).build());\n\n        /**********************************node -> script************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.script.compilations\")\n                .valueRoute(\"script.compilations\").computeType(AVG_MIN).build());\n\n        /**********************************node -> 复合指标************************************/\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.query_cache.hit_rate\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.indices.query_cache.hit_count\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.node.indices.query_cache.total_count\").computeType(DERIVE_DIVISION)\n                .build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.request_cache.hit_rate\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.indices.request_cache.hit_count\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.node.indices.request_cache.total_count\").computeType(DERIVE_DIVISION)\n                .build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.indexing.index_time_per_doc\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.indices.indexing.index_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.node.indices.docs.count_diff\").computeType(DERIVE_DIVISION)\n                .build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.query_time_per_query\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.indices.search.query_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.node.indices.search.query_total\").computeType(DERIVE_DIVISION)\n                .build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.fetch_time_per_fetch\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.indices.search.fetch_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.node.indices.search.fetch_total\").computeType(DERIVE_DIVISION)\n                .build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.search.scroll_avg_time\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.indices.search.scroll_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.node.indices.search.scroll_total\").computeType(DERIVE_DIVISION)\n                .build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.merges_avg_time\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.indices.merges.total_time_in_millis\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.node.indices.merges.total\").computeType(DERIVE_DIVISION).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.refresh_avg_time\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.indices.refresh.total_time_in_millis\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.node.indices.refresh.total\").computeType(DERIVE_DIVISION).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.indices.flush_avg_time\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.indices.flush.total_time_in_millis\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.node.indices.flush.total\").computeType(DERIVE_DIVISION).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.gc.young.collection_avg_time\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.jvm.gc.young.collection_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.node.jvm.gc.young.collection_count\")\n                .computeType(DERIVE_DIVISION).build());\n\n        nodeWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.jvm.gc.old.collection_avg_time\")\n                .deriveParam(ESDataTempBean.DIVIDEND, \"es.node.jvm.gc.old.collection_time_in_millis\")\n                .deriveParam(ESDataTempBean.DIVISOR, \"es.node.jvm.gc.old.collection_count\")\n                .computeType(DERIVE_DIVISION).build());\n\n        return nodeWorkOrders;\n    }\n\n    public static List<CollectMetrics> initNodeToIndexDataRegisterMap() {\n        CopyOnWriteArrayList<CollectMetrics> nodeToIndexWorkOrders = Lists.newCopyOnWriteArrayList();\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.merges.current\")\n            .valueRoute(\"merges.current\").computeType(NONE).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.merges.total\")\n            .valueRoute(MERGES_TOTAL).computeType(MINUS).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.merges.total_time_in_millis\")\n            .valueRoute(\"merges.total_time_in_millis\").computeType(MINUS).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.refresh.total\")\n            .valueRoute(\"refresh.total\").computeType(MINUS).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.refresh.total_time_in_millis\")\n            .valueRoute(\"refresh.total_time_in_millis\").computeType(MINUS).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.flush.total\")\n            .valueRoute(\"flush.total\").computeType(MINUS).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.flush.total_time_in_millis\")\n            .valueRoute(\"flush.total_time_in_millis\").computeType(MINUS).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.segments.count\")\n            .valueRoute(\"segments.count\").computeType(NONE).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.segments.memory_in_bytes\")\n            .valueRoute(\"segments.memory_in_bytes\").computeType(NONE).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.segments.norms_memory_in_bytes\")\n             .valueRoute(\"segments.norms_memory_in_bytes\").computeType(NONE).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.segments.version_map_memory_in_bytes\")\n                .valueRoute(\"segments.version_map_memory_in_bytes\").computeType(NONE).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.segments.fixed_bit_set_memory_in_bytes\")\n                .valueRoute(\"segments.fixed_bit_set_memory_in_bytes\").computeType(NONE).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.segments.breakers.fielddata.limit_size_in_bytes\")\n                .valueRoute(\"segments.breakers.fielddata.limit_size_in_bytes\").computeType(NONE).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.docs.count\")\n            .valueRoute(\"docs.count\").computeType(NONE).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.store.size_in_bytes\")\n            .valueRoute(STORE_SIZE_IN_BYTES).computeType(NONE).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.indexing.index_total_rate\")\n            .valueRoute(INDEXING_INDEX_TOTAL).computeType(AVG).build());\n\n        nodeToIndexWorkOrders\n            .add(new CollectMetrics.Builder().valueName(\"es.node.index.indexing.index_time_in_millis_rate\")\n                .valueRoute(INDEXING_INDEX_TIME_IN_MILLIS).computeType(AVG).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.search.query_total_rate\")\n            .valueRoute(\"search.query_total\").computeType(AVG).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.search.fetch_total_rate\")\n            .valueRoute(\"search.fetch_total\").computeType(AVG).build());\n\n        nodeToIndexWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.index.search.scroll_total_rate\")\n            .valueRoute(\"search.scroll_total\").computeType(AVG).build());\n\n        nodeToIndexWorkOrders\n            .add(new CollectMetrics.Builder().valueName(\"es.node.index.search.query_time_in_millis_rate\")\n                .valueRoute(SEARCH_QUERY_TIME_IN_MILLIS).computeType(AVG).build());\n\n        nodeToIndexWorkOrders\n            .add(new CollectMetrics.Builder().valueName(\"es.node.index.search.fetch_time_in_millis_rate\")\n                .valueRoute(SEARCH_FETCH_TIME_IN_MILLIS).computeType(AVG).build());\n\n        nodeToIndexWorkOrders\n            .add(new CollectMetrics.Builder().valueName(\"es.node.index.search.scroll_time_in_millis_rate\")\n                .valueRoute(SEARCH_SCROLL_TIME_IN_MILLIS).computeType(AVG).build());\n\n        return nodeToIndexWorkOrders;\n    }\n\n    public static List<CollectMetrics> initIndexToNodeDataRegisterMap(List<CollectMetrics> nodeWorkOrders) {\n        CopyOnWriteArrayList<CollectMetrics> indexToNodeWorkOrders = Lists.newCopyOnWriteArrayList();\n\n        for (CollectMetrics workOrder : nodeWorkOrders) {\n            if (workOrder.isIndexToNodeMetrics()) {\n                indexToNodeWorkOrders.add(workOrder);\n            }\n        }\n\n        return indexToNodeWorkOrders;\n    }\n\n    public static List<CollectMetrics> initIngestDataRegisterMap() {\n        CopyOnWriteArrayList<CollectMetrics> ingestWorkOrders = Lists.newCopyOnWriteArrayList();\n\n        ingestWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.ingest.count\").valueRoute(\"count\")\n            .computeType(AVG).bIndexToNodeMetrics().build());\n\n        ingestWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.ingest.time_in_millis\")\n            .valueRoute(\"time_in_millis\").computeType(AVG).bIndexToNodeMetrics().build());\n\n        ingestWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.ingest.current\").valueRoute(\"current\")\n            .computeType(NONE).bIndexToNodeMetrics().build());\n\n        ingestWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.node.ingest.failed\").valueRoute(\"failed\")\n            .computeType(AVG).bIndexToNodeMetrics().build());\n\n        return ingestWorkOrders;\n    }\n\n    public static List<CollectMetrics> initDCDRDataRegisterMap() {\n        CopyOnWriteArrayList<CollectMetrics> dcdrWorkOrders = Lists.newCopyOnWriteArrayList();\n\n        // max_seq_no延迟量\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.max_seq_no_delay\")\n            .valueRoute(\"max_seq_no_delay\").computeType(NONE).build());\n\n        // global_checkpoint延迟量\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.global_checkpoint_delay\")\n            .valueRoute(\"global_checkpoint_delay\").computeType(NONE).sendToN9e().build());\n\n        // shard中最少的可用的bulk队列\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.min_available_send_bulk_number\")\n            .valueRoute(\"min_available_send_bulk_number\").computeType(NONE).sendToN9e().build());\n\n        // 总的发送时间\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.total_send_time_millis\")\n            .valueRoute(\"total_send_time_millis\").computeType(AVG).build());\n\n        // 总的发送请求数\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.total_send_request\")\n            .valueRoute(\"total_send_request\").computeType(AVG).build());\n\n        // 发送失败数\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.failed_send_requests\")\n            .valueRoute(\"failed_send_requests\").computeType(AVG).sendToN9e().build());\n\n        // 发送的bulk请求数\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.operations_send\")\n            .valueRoute(\"operations_send\").computeType(AVG).sendToN9e().build());\n\n        // 发送的总字节数\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.bytes_send\").valueRoute(\"bytes_send\")\n            .computeType(AVG).build());\n\n        // 上次发送请求时间间隔最小的shard时间\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.min_time_since_last_send_millis\")\n            .valueRoute(\"min_time_since_last_send_millis\").computeType(NONE).build());\n\n        // 上次发送请求时间间隔最大的shard时间\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.max_time_since_last_send_millis\")\n            .valueRoute(\"max_time_since_last_send_millis\").computeType(NONE).sendToN9e().build());\n\n        // 上次更新checkpoint时间间隔最大的shard时间\n        dcdrWorkOrders\n            .add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.max_time_since_update_replica_checkpoint\")\n                .valueRoute(\"max_time_since_update_replica_checkpoint\").computeType(NONE).sendToN9e().build());\n\n        // 成功的恢复数量\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.success_recover_count\")\n            .valueRoute(\"success_recover_count\").computeType(AVG).build());\n\n        // 失败的恢复数量\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.failed_recover_count\")\n            .valueRoute(\"failed_recover_count\").computeType(AVG).build());\n\n        // 总的恢复时间\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.recover_total_time_millis\")\n            .valueRoute(\"recover_total_time_millis\").computeType(AVG).build());\n\n        // 在同步的translog数量\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.in_sync_translog_offset_size\")\n            .valueRoute(\"in_sync_translog_offset_size\").computeType(NONE).build());\n\n        // 请求平均耗时\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.send_request_avg_time\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.dcdr.total_send_time_millis\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.dcdr.total_send_request\").computeType(DERIVE_DIVISION)\n            .build());\n\n        // 平均延迟时间\n        dcdrWorkOrders.add(new CollectMetrics.Builder().valueName(\"es.indices.dcdr.global_checkpoint_delay_seconds\")\n            .deriveParam(ESDataTempBean.DIVIDEND, \"es.indices.dcdr.global_checkpoint_delay\")\n            .deriveParam(ESDataTempBean.DIVISOR, \"es.indices.dcdr.operations_send\").computeType(DERIVE_DIVISION)\n            .sendToN9e().build());\n\n        return dcdrWorkOrders;\n    }\n\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/MonitorJobHandler.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.Triple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.IndexTemplatePhysicalConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.MulityTypeTemplatesInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.MonitorTaskInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.monitor.AriusMetaJobClusterDistributePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.AmsTemplatePhysicalConfVO;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.HttpHostUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.AbstractMetaDataJob;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics.CollectMetrics;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics.MetricsRegister;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpClient;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.monitor.AriusMetaJobClusterDistributeDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.observability.Observability;\nimport com.didiglobal.knowframework.observability.conponent.thread.ContextExecutorService;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.commons.lang3.concurrent.BasicThreadFactory;\nimport org.elasticsearch.common.StopWatch;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.cglib.core.ReflectUtils;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.ReflectionUtils;\n\nimport javax.annotation.PostConstruct;\nimport java.lang.reflect.Field;\nimport java.util.*;\nimport java.util.concurrent.*;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.JOB_FAILED;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.JOB_SUCCESS;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.*;\n\n/**\n * 通过查数据库观察每个节点采集es集群名称\n *\n * select * from cluster_monitor_task_v2 where monitor_time > '2020-07-10 15:01:10' and datacentre='cn' order by monitor_host desc  limit 20\n * @author didi\n */\n@Component\n@NoArgsConstructor\npublic class MonitorJobHandler extends AbstractMetaDataJob {\n\n    public static final long                                                           TASK_TIMEOUT_TIME                     = 220\n                                                                                                                               * 1000L;\n    @Autowired\n    private AriusMetaJobClusterDistributeDAO                                           ariusMetaJobClusterDistributeDAO;\n\n    @Autowired\n    private ClusterPhyService                                                          phyClusterService;\n\n    @Autowired\n    private IndexTemplatePhyService                                                    indexTemplatePhyService;\n\n    @Autowired\n    private IndexTemplateService                                                       indexTemplateService;\n\n    @Autowired\n    private ESOpClient                                                                 esOpClient;\n\n    @Autowired\n    private MonitorMetricsSender                                                       monitorMetricsSender;\n\n    @Autowired\n    private AriusConfigInfoService                                                     ariusConfigInfoService;\n\n    private MetricsRegister                                                            metricsRegister                       = new MetricsRegister();\n\n    private String                                                                     hostName                              = HttpHostUtil.HOST_NAME;\n    private Integer                                                                    clusterTotal                          = -1;\n\n    private String                                                                     dataCentre                            = EnvUtil\n        .getDC().getCode();\n\n    private static final Long                                                          MONITOR_TASK_CHECK_MINUTES_WITH_MILLS = EnvUtil\n        .isOnline() ? (long) (1000 * 60 * 30) : (long) (1000 * 60 * 5);\n\n    /**\n     * 采集指标\n     */\n    private List<CollectMetrics>                                                       indexWorkOrders                       = Lists\n        .newCopyOnWriteArrayList();\n    private List<CollectMetrics>                                                       indexToNodeWorkOrders                 = Lists\n        .newCopyOnWriteArrayList();\n    private List<CollectMetrics>                                                       nodeWorkOrders                        = Lists\n        .newCopyOnWriteArrayList();\n    private List<CollectMetrics>                                                       nodeToIndexWorkOrders                 = Lists\n        .newCopyOnWriteArrayList();\n    private List<CollectMetrics>                                                       ingestWorkOrders                      = Lists\n        .newCopyOnWriteArrayList();\n    private List<CollectMetrics>                                                       dcdrWorkOrders                        = Lists\n        .newCopyOnWriteArrayList();\n\n    /**\n     * key：clusterName\n     */\n    private Map<String, Triple<ESClient, AriusMetaJobClusterDistributePO, ClusterPhy>> localTask                             = new HashMap<>();\n\n    private final Set<String>                                                          notMonitorCluster                     = Sets\n        .newHashSet();\n\n    @Value(\"${monitorJob.threadPool.initsize:20}\")\n    private int                                                                        poolSize;\n\n    /**\n     * maxPoolSize，当前monitorjob能支持的最大集群采集个数，\n     * 超过maxPoolSize的集群不会被采集，保证maxPoolSize个集群采集的稳定性\n     */\n    @Value(\"${monitorJob.threadPool.maxsize:30}\")\n    private int                                                                        maxPoolSize;\n\n    private ExecutorService threadPool;\n\n    /**\n     * 监控采集任务执行情况\n     * key：clusterName\n     */\n    private Map<String, MonitorTaskInfo>                                               monitorTaskInfoMap                    = Maps\n        .newConcurrentMap();\n\n    @PostConstruct\n    public void init() {\n        indexWorkOrders = MonitorCollectMetrics.initIndexDataRegisterMap();\n        nodeWorkOrders = MonitorCollectMetrics.initNodeDataRegisterMap();\n        nodeToIndexWorkOrders = MonitorCollectMetrics.initNodeToIndexDataRegisterMap();\n        indexToNodeWorkOrders = MonitorCollectMetrics.initIndexToNodeDataRegisterMap(nodeWorkOrders);\n        ingestWorkOrders = MonitorCollectMetrics.initIngestDataRegisterMap();\n        dcdrWorkOrders = MonitorCollectMetrics.initDCDRDataRegisterMap();\n    }\n\n    @Override\n    public Object handleBrocastJobTask(String params, String curretnWorker, List<String> allWorkers) {\n        if (StringUtils.isEmpty(hostName)) {\n            LOGGER.error(\"class=MonitorJobHandler||method=handleJobTask||hostName is empty!\");\n            return JOB_FAILED;\n        }\n\n        if (CollectionUtils.isEmpty(allWorkers)) {\n            LOGGER.error(\"class=MonitorJobHandler||method=handleJobTask||allWorders is empty!\");\n            return JOB_FAILED;\n        }\n\n        List<ClusterPhy> clusterPhyList = dataSourceFilter(phyClusterService.listAllClusters());\n        List<AriusMetaJobClusterDistributePO> allTaskPOList = ariusMetaJobClusterDistributeDAO.getAllTask();\n\n        int jobTotalNu = allWorkers.size();\n\n        //计算本机需要采集的具体es集群\n        if (needReAcquireCluster(jobTotalNu, clusterPhyList, allTaskPOList)) {\n            List<AriusMetaJobClusterDistributePO> lockedTasks = acquireOwnCluster(jobTotalNu, allTaskPOList);\n\n            localTask.clear();\n            localTask = getLocalTaskInfo(lockedTasks, clusterPhyList);\n            clusterTotal = jobTotalNu;\n        }\n\n        // AMS节点开始采集具体负责的es集群的信息\n        if (!localTask.isEmpty()) {\n            collectData(localTask);\n        }\n\n        return JOB_SUCCESS;\n    }\n\n    @Override\n    public Object handleJobTask(String params) {\n        return JOB_SUCCESS;\n    }\n\n    /**************************************** private methods ****************************************/\n    private List<ClusterPhy> dataSourceFilter(List<ClusterPhy> allDataSource) {\n        List<ClusterPhy> dataSources = new ArrayList<>();\n\n        for (ClusterPhy dataSource : allDataSource) {\n            if (notMonitorCluster.contains(dataSource.getCluster())) {\n                LOGGER.info(\"class=MonitorJobHandler||method=dataSourceFilter||cluster={}||msg=not monitor!\",\n                    dataSource.getCluster());\n            } else {\n                dataSources.add(dataSource);\n            }\n        }\n\n        return dataSources;\n    }\n\n    /**\n     * 是否需要重新把es集群分配到具体的ams节点上\n     * @param jobTotalNu\n     * @param clusterPhies\n     * @param allTaskPOs\n     * @return\n     */\n    private boolean needReAcquireCluster(int jobTotalNu, List<ClusterPhy> clusterPhies,\n                                         List<AriusMetaJobClusterDistributePO> allTaskPOs) {\n        //allTaskPOs是空，重新分配\n        //allTaskPOs发生了变动，重新分配\n        if (CollectionUtils.isEmpty(allTaskPOs) || clusterPhies.size() != allTaskPOs.size()) {\n            updateMonitorTaskByDataSource(clusterPhies, allTaskPOs);\n            return true;\n        }\n\n        //localESClient是空，重新分配\n        if (localTask.isEmpty()) {\n            return true;\n        }\n\n        //ams集群数量发生了变更，重新分配\n        if (clusterTotal.intValue() != jobTotalNu) {\n            return true;\n        }\n\n        //30分钟之内没有执行任务，重新分配\n        Long now = System.currentTimeMillis();\n        for (AriusMetaJobClusterDistributePO taskPO : allTaskPOs) {\n            if (now - taskPO.getMonitorTime().getTime() > MONITOR_TASK_CHECK_MINUTES_WITH_MILLS) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * 在es集群信息发送变动时，根据es集群更新ClusterMonitorTaskEntity\n     * @param clusterPhies\n     * @param allTaskPOs\n     */\n    private void updateMonitorTaskByDataSource(List<ClusterPhy> clusterPhies,\n                                               List<AriusMetaJobClusterDistributePO> allTaskPOs) {\n        Map<Integer, AriusMetaJobClusterDistributePO> deletedCluster = Maps.newHashMap();\n        if (CollectionUtils.isNotEmpty(allTaskPOs)) {\n            for (AriusMetaJobClusterDistributePO taskPO : allTaskPOs) {\n                deletedCluster.put(taskPO.getClusterId(), taskPO);\n            }\n        }\n\n        Map<Integer, ClusterPhy> newCluster = Maps.newHashMap();\n        for (ClusterPhy dataSource : clusterPhies) {\n            if (deletedCluster.containsKey(dataSource.getId())) {\n                deletedCluster.remove(dataSource.getId());\n            } else {\n                newCluster.put(dataSource.getId(), dataSource);\n            }\n        }\n\n        List<AriusMetaJobClusterDistributePO> newTasks = Lists.newArrayList();\n\n        for (ClusterPhy dataSource : newCluster.values()) {\n            AriusMetaJobClusterDistributePO newTask = new AriusMetaJobClusterDistributePO();\n            newTask.setClusterId(dataSource.getId());\n            newTask.setCluster(dataSource.getCluster());\n            newTask.setDataCentre(dataSource.getDataCenter());\n            newTasks.add(newTask);\n        }\n\n        LOGGER.info(\"class=MonitorJobHandler||method=updateMonitorTaskByDataSource||newCluster={}||deletedCluster={}\",\n            newCluster.keySet(), deletedCluster.keySet());\n\n        if (CollectionUtils.isNotEmpty(newTasks)) {\n            for (AriusMetaJobClusterDistributePO taskEntity : newTasks) {\n                try {\n                    ariusMetaJobClusterDistributeDAO.insert(taskEntity);\n                } catch (Exception e) {\n                    LOGGER.error(\n                        \"class=MonitorJobHandler||method=updateMonitorTaskByDataSource||cluster={}||msg=insert taskEntity failed!\",\n                        taskEntity.getClusterId(), e);\n                }\n            }\n        }\n\n        List<Long> deleteIds = Lists.newArrayList();\n        for (AriusMetaJobClusterDistributePO oldTask : deletedCluster.values()) {\n            deleteIds.add(oldTask.getId());\n        }\n        if (CollectionUtils.isNotEmpty(deleteIds)) {\n            ariusMetaJobClusterDistributeDAO.deleteBatch(deleteIds);\n        }\n    }\n\n    /**\n     * 开始计算AMS节点具体负责的ClusterMonitorTaskEntity任务，每个节点最多负责maxPoolSize个采集任务\n     * @param jobTotalNu\n     * @param taskPOs\n     * @return\n     */\n    private List<AriusMetaJobClusterDistributePO> acquireOwnCluster(int jobTotalNu,\n                                                                    List<AriusMetaJobClusterDistributePO> taskPOs) {\n        Collections.sort(taskPOs, (o1, o2) -> {\n            Long o1Time = o1.getMonitorTime().getTime();\n            Long o2Time = o2.getMonitorTime().getTime();\n\n            //都没有被monitor\n            if (StringUtils.isEmpty(o1.getMonitorHost()) && StringUtils.isEmpty(o2.getMonitorHost())) {\n                return o1Time.compareTo(o2Time);\n            }\n\n            //都被monitor\n            if (!StringUtils.isEmpty(o1.getMonitorHost()) && !StringUtils.isEmpty(o2.getMonitorHost())) {\n                if (o1.getMonitorHost().equals(o2.getMonitorHost())) {\n                    //优先获取持续被monitor的，保证monitor的稳定性和持续性\n                    return o2Time.compareTo(o1Time);\n                } else {\n                    //都不是本机,不优先\n                    if (!o1.getMonitorHost().equals(hostName) && !o2.getMonitorHost().equals(hostName)) {\n                        return o1Time.compareTo(o2Time);\n                    }\n\n                    //优先本机\n                    if (o1.getMonitorHost().equals(hostName)) {\n                        return -1;\n                    }\n\n                    //优先本机\n                    if (o2.getMonitorHost().equals(hostName)) {\n                        return 1;\n                    }\n                }\n            }\n\n            //o1是本机monitor\n            if (!StringUtils.isEmpty(o1.getMonitorHost()) && o1.getMonitorHost().equals(hostName)) {\n                return -1;\n            }\n\n            //o2是本机monitor\n            if (!StringUtils.isEmpty(o2.getMonitorHost()) && o2.getMonitorHost().equals(hostName)) {\n                return 1;\n            }\n\n            if (StringUtils.isEmpty(o1.getMonitorHost())) {\n                return -1;\n            }\n            if (StringUtils.isEmpty(o2.getMonitorHost())) {\n                return 1;\n            }\n\n            return o1Time.compareTo(o2Time);\n        });\n\n        Double taskCountCeil = Math.ceil(taskPOs.size() * 1.0 / jobTotalNu);\n        int taskCount = taskCountCeil.intValue() > maxPoolSize ? maxPoolSize : taskCountCeil.intValue();\n\n        LOGGER.info(\"class=MonitorJobHandler||method=acquireOwnCluster||hostName={}||count={}||taskPOs={}||env={}\",\n            hostName, taskCount, JSON.toJSON(taskPOs), EnvUtil.getStr());\n\n        //顺序遍历列表,尝试抢占任务,每台AMS节点只能抢占taskCount个任务\n        List<AriusMetaJobClusterDistributePO> lockedTasks = Lists.newArrayList();\n        for (int i = 0; i < taskPOs.size() && taskCount > 0; i++) {\n            if (tryLockTask(taskPOs.get(i), hostName)) {\n                taskCount--;\n                LOGGER.info(\"class=MonitorJobHandler||method=acquireOwnCluster||hostName={}||task={}\", hostName,\n                    JSON.toJSONString(taskPOs.get(i)));\n\n                lockedTasks.add(taskPOs.get(i));\n            }\n        }\n\n        return lockedTasks;\n    }\n\n    /**\n     * 任务抢占的逻辑\n     * @param ariusMetaJobClusterDistributePO\n     * @param hostName\n     * @return\n     */\n    private boolean tryLockTask(AriusMetaJobClusterDistributePO ariusMetaJobClusterDistributePO, String hostName) {\n        // 某个集群不是本节点负责采集并且据上次monitor时间大于配置的30分钟，则尝试更新数据库\n        if (!hostName.equals(ariusMetaJobClusterDistributePO.getMonitorHost())\n            && ariusMetaJobClusterDistributePO.getMonitorTime().getTime()\n               + MONITOR_TASK_CHECK_MINUTES_WITH_MILLS > System.currentTimeMillis()) {\n            LOGGER.info(\"class=MonitorJobHandler||method=tryLockTask||cluster={}||monitorHostName={}||monitorTime={}\",\n                ariusMetaJobClusterDistributePO.getCluster(), ariusMetaJobClusterDistributePO.getMonitorHost(),\n                ariusMetaJobClusterDistributePO.getMonitorTime().toString());\n            return false;\n        }\n\n        ariusMetaJobClusterDistributePO.setDestMonitorHost(hostName);\n        ariusMetaJobClusterDistributePO.setMonitorTime(new Date());\n        ariusMetaJobClusterDistributePO.setGmtModify(new Date());\n\n        //updateMonitorHost不能设置monitorHost\n        return ariusMetaJobClusterDistributeDAO.updateMonitorHost(ariusMetaJobClusterDistributePO) == 1;\n    }\n\n    private Map<String/*clusterName*/, Triple<ESClient, AriusMetaJobClusterDistributePO, ClusterPhy>> getLocalTaskInfo(List<AriusMetaJobClusterDistributePO> localTasks,\n                                                                                                                       List<ClusterPhy> clusterPhies) {\n        Map<Integer/*clusterId*/, AriusMetaJobClusterDistributePO> localTaskMap = new HashMap<>(localTasks.size());\n        for (AriusMetaJobClusterDistributePO taskPO : localTasks) {\n            localTaskMap.put(taskPO.getClusterId(), taskPO);\n        }\n\n        List<ClusterPhy> dataSources = clusterPhies.stream()\n            .filter(cluster -> localTaskMap.containsKey(cluster.getId())).collect(Collectors.toList());\n\n        Map<String/*clusterName*/, Triple<ESClient, AriusMetaJobClusterDistributePO, ClusterPhy>> stringTripleMap = new HashMap<>(\n            dataSources.size());\n        for (ClusterPhy esDataSource : dataSources) {\n            String cluster = esDataSource.getCluster();\n            ESClient esClient = esOpClient.getESClient(cluster);\n            if (null != esClient) {\n                Integer clusterId = esDataSource.getId();\n\n                stringTripleMap.put(cluster, new Triple<>(esClient, localTaskMap.get(clusterId), esDataSource));\n            } else {\n                LOGGER.warn(\"class=MonitorJobHandler||method=getLocalTaskInfo||hostName={}||cluster={}||msg=fail\",\n                    hostName, cluster);\n            }\n        }\n\n        LOGGER.info(\n            \"class=MonitorJobHandler||method=getLocalTaskInfo||hostName={}||taskSize={}||dataSources={}||localTasks={}||env={}\",\n            hostName, localTasks.size(), dataSources2Str(dataSources), JSON.toJSONString(localTasks), EnvUtil.getStr());\n\n        return stringTripleMap;\n    }\n\n    private String dataSources2Str(List<ClusterPhy> dataSources) {\n        if (CollectionUtils.isEmpty(dataSources)) {\n            return \"\";\n        }\n\n        StringBuilder cluster = new StringBuilder();\n        for (ClusterPhy dataSource : dataSources) {\n            cluster.append(dataSource.getCluster());\n            cluster.append(\",\");\n        }\n\n        return cluster.toString();\n    }\n\n    private Map<String/*templateName*/, AmsTemplatePhysicalConfVO> listTypeMappingIndex(String dataCenter) {\n        Map<String/*templateName*/, AmsTemplatePhysicalConfVO> resultMap = Maps.newHashMap();\n        List<IndexTemplateWithPhyTemplates> logicWithPhysicals = indexTemplateService\n            .listTemplateWithPhysical();\n\n        String templateConfig = null;\n        AmsTemplatePhysicalConfVO item = null;\n        for (IndexTemplateWithPhyTemplates logicWithPhysical : logicWithPhysicals) {\n            if (logicWithPhysical.hasPhysicals()) {\n                try {\n                    templateConfig = logicWithPhysical.getMasterPhyTemplate().getConfig();\n                    if (StringUtils.isNotBlank(templateConfig)) {\n                        IndexTemplatePhysicalConfig config = JSON.parseObject(templateConfig,\n                            IndexTemplatePhysicalConfig.class);\n\n                        if (MapUtils.isNotEmpty(config.getTypeIndexMapping())) {\n                            item = new AmsTemplatePhysicalConfVO();\n                            item.setLogicId(logicWithPhysical.getId());\n                            item.setName(logicWithPhysical.getName());\n                            item.setMappingIndexNameEnable(config.getMappingIndexNameEnable());\n                            item.setTypeIndexMapping(config.getTypeIndexMapping());\n\n                            resultMap.put(logicWithPhysical.getName(), item);\n                        }\n                    }\n                } catch (Exception e) {\n                    LOGGER.warn(\"method=listTypeMappingIndex||dataCenter={}||errMsg={}\", dataCenter, e.getMessage(), e);\n                }\n            }\n        }\n\n        return resultMap;\n    }\n\n    /**\n     * 获取到已启用索引映射的多type索引信息\n     *\n     * @param dataCenter\n     * @return\n     */\n    private MulityTypeTemplatesInfo getAllEnabledMulityTypeTemplates(String dataCenter) {\n        MulityTypeTemplatesInfo mulityTypeTemplatesInfo = new MulityTypeTemplatesInfo();\n        Map<String/*templateName*/, AmsTemplatePhysicalConfVO> result = listTypeMappingIndex(dataCenter);\n\n        if (MapUtils.isEmpty(result)) {\n            return mulityTypeTemplatesInfo;\n        }\n\n        Map<String/*destTemplateName*/, String/*sourceTemplateName*/> dest2SourceTemplateMap = Maps.newHashMap();\n        Map<String/*sourceTemplateName*/, Set<String/*destTemplateName*/>> source2DestTemplateMap = Maps.newHashMap();\n        Map<String/*typeName*/, String/*destTemplateName*/> typeIndexMapping = null;\n\n        for (Map.Entry<String/*templateName*/, AmsTemplatePhysicalConfVO> entry : result.entrySet()) {\n            if (entry.getValue().getMappingIndexNameEnable().booleanValue()) {\n                typeIndexMapping = entry.getValue().getTypeIndexMapping();\n                if (MapUtils.isNotEmpty(typeIndexMapping)) {\n                    for (Map.Entry<String/*typeName*/, String/*destTemplateName*/> item : typeIndexMapping.entrySet()) {\n                        dest2SourceTemplateMap.put(item.getValue(), entry.getKey());\n                    }\n                    source2DestTemplateMap.put(entry.getKey(), Sets.newHashSet(typeIndexMapping.values()));\n                }\n            }\n        }\n\n        mulityTypeTemplatesInfo.setDest2SourceTemplateMap(dest2SourceTemplateMap);\n        mulityTypeTemplatesInfo.setSource2DestTemplateMap(source2DestTemplateMap);\n\n        return mulityTypeTemplatesInfo;\n    }\n\n    /**\n     * 校验线程资源是否合理\n     * @return\n     */\n    private boolean checkThreadPool() {\n        if (threadPool == null || threadPool.isShutdown()) {\n            threadPool = Observability.wrap(new ThreadPoolExecutor(poolSize, maxPoolSize + 10, 0L, TimeUnit.MILLISECONDS,\n                    new LinkedBlockingQueue<>(100),\n                    new BasicThreadFactory.Builder().namingPattern(\"monitor-cluster-data-collect-%d\").build()));\n        }\n        long blockSize = Optional.ofNullable(ReflectionUtils.findField(ContextExecutorService.class, \"delegate\")).map(field -> {\n            field.setAccessible(true);\n            return (ThreadPoolExecutor) ReflectionUtils.getField(field, threadPool);\n        }).map(ThreadPoolExecutor::getQueue).map(Collection::size).orElse(0);\n\n        if (blockSize > WARN_BLOCK_SIZE) {\n            LOGGER.warn(\n                \"class=MonitorJobHandler||method=checkThreadPool||blockSize={}||msg=collect thread pool has block task\",\n                blockSize);\n        }\n\n        if (blockSize > ERROR_BLOCK_SIZE) {\n            LOGGER.error(\n                \"class=MonitorJobHandler||method=checkThreadPool||blockSize={}||msg=collect thread pool is too busy. thread pool recreate\",\n                blockSize);\n            threadPool.shutdownNow();\n            threadPool = null;\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * 采集本机负责的es集群信息\n     * @param localTask\n     */\n    private void collectData(Map<String/*clusterName*/, Triple<ESClient, AriusMetaJobClusterDistributePO, ClusterPhy>> localTask) {\n        //清空上个周期的集群缓存, 防止撑爆内存\n        metricsRegister.clearComputeValueRegister();\n\n        // 从admin获取所有模板信息\n        List<IndexTemplatePhyWithLogic> indexTemplates = indexTemplatePhyService.listTemplateWithLogic();\n\n        Map<String, List<IndexTemplatePhyWithLogic>> indexTemplatesMap = new ConcurrentHashMap<>(16);\n        if (CollectionUtils.isNotEmpty(indexTemplates)) {\n            indexTemplatesMap\n                .putAll(indexTemplates.stream().collect(Collectors.groupingBy(IndexTemplatePhy::getCluster)));\n        }\n\n        // 从admin获取所多type的模板信息，包括源模板名和映射到的模板名之间的map\n        MulityTypeTemplatesInfo mulityTypeTemplatesInfo = getAllEnabledMulityTypeTemplates(\"\");\n\n        // 遍历集群，进行采集\n        localTask.forEach((clusterName, taskEntityTuple) -> {\n            try {\n                MonitorTaskInfo monitorTaskInfo = monitorTaskInfoMap.computeIfAbsent(clusterName,\n                    key -> new MonitorTaskInfo(clusterName, 0L, 0L, false));\n                // 如果该集群上一个任务还在运行 并且上个任务开始时间据现在220s(请求超时为50s*4+20s处理时间)内，则返回\n                if (monitorTaskInfo.getRunning()\n                    && ((System.currentTimeMillis() - monitorTaskInfo.getStartTick()) < TASK_TIMEOUT_TIME)) {\n                    LOGGER.warn(\n                        \"class=MonitorJobHandler||method=collectData||clusterName={}||msg=task is running, monitorTaskInfo {}\",\n                        clusterName, JSON.toJSONString(monitorTaskInfo));\n                    //TODO 未超时的任务先不停掉避免数据时间点缺失\n                    //return;\n                }\n\n                if (checkThreadPool()) {\n                    threadPool.execute(() -> {\n                        StopWatch stopWatch = new StopWatch();\n                        stopWatch.start(\"start collect\");\n\n                        Long startTime = System.currentTimeMillis();\n                        monitorTaskInfo.setRunning(true);\n                        monitorTaskInfo.setStartTick(startTime);\n                        AriusMetaJobClusterDistributePO taskEntity = taskEntityTuple.v2();\n\n                        Thread.currentThread().setName(\"monitor-cluster-data-collect-\" + clusterName);\n                        ESClient esClient = esOpClient.getESClient(clusterName);\n                        if (esClient == null) {\n                            LOGGER.error(\n                                \"class=MonitorJobHandler||method=collectData||clusterName={}||errMsg=fail to get esClient\",\n                                clusterName);\n                            monitorTaskInfo.setRunning(false);\n                            return;\n                        }\n\n                        stopWatch.stop().start(\"collect\");\n                        MonitorClusterJob monitorClusterJob = new MonitorClusterJob(esClient, clusterName,\n                            taskEntityTuple.v3(),\n                            indexTemplatesMap.getOrDefault(clusterName, Lists.newCopyOnWriteArrayList()),\n                            metricsRegister, monitorMetricsSender, indexWorkOrders, nodeWorkOrders,\n                            indexToNodeWorkOrders, nodeToIndexWorkOrders, ingestWorkOrders, dcdrWorkOrders,\n                            mulityTypeTemplatesInfo, ariusConfigInfoService);\n\n                        monitorClusterJob.collectData(clusterName);\n\n                        stopWatch.stop().start(\"update db\");\n                        // 更新数据库 任务采集信息\n                        taskEntity.setMonitorTime(new Date());\n                        taskEntity.setGmtModify(new Date());\n                        taskEntity.setMonitorHost(hostName);\n\n                        boolean taskUpdateSuc = ariusMetaJobClusterDistributeDAO.updateMonitorTime(taskEntity) == 1;\n                        long totalCost = System.currentTimeMillis() - startTime;\n\n                        monitorTaskInfo.setTotalCost(totalCost);\n                        monitorTaskInfo.setRunning(false);\n\n                        LOGGER.info(\n                            \"class=MonitorJobHandler||method=collectData||clusterName={}||cost={}||taskUpdateSuc={}||host={}||taskEntity={}||env={}\",\n                            clusterName, stopWatch.toString(), taskUpdateSuc, hostName, JSON.toJSONString(taskEntity),\n                            EnvUtil.getStr());\n                    });\n                }\n            } catch (Exception e) {\n                LOGGER.error(\n                    \"class=MonitorJobHandler||method=collectData||clusterName={}||host={}||env={}||msg=excepiton\",\n                    clusterName, hostName, EnvUtil.getStr(), e);\n            }\n        });\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/MonitorMetricsSender.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob;\n\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.LinkedBlockingDeque;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.DashBoardStats;\nimport com.didiglobal.knowframework.observability.Observability;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.lucene.util.NamedThreadFactory;\nimport org.springframework.stereotype.Component;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterTaskStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexDCDRStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexToNodeStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIngestStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESNodeStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESNodeToIndexStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusStatsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.BaseAriusStatsESDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * 发送monitor指标数据\n */\n@Component(\"monitorMetricsSender\")\npublic class MonitorMetricsSender {\n\n    protected static final ILog LOGGER     = LogFactory.getLog(MonitorMetricsSender.class);\n\n    private static final int    THRESHOLD  = 1000;\n\n    private ExecutorService esExecutor = Observability.wrap(new ThreadPoolExecutor(100, 100, 6000,TimeUnit.MILLISECONDS,\n            new LinkedBlockingDeque<>(4000), new NamedThreadFactory(\"Arius-Meta-MonitorMetricsSender-ES\"),\n            (r, e) -> LOGGER\n                    .warn(\"class=MonitorMetricsSender||msg=Arius-Meta-MonitorMetricsSender-ES Deque is blocked, taskCount:{}\"\n                            + e.getTaskCount())));\n\n    public void sendNodeInfo(List<ESNodeStats> esNodeStatsList) {\n        send2es(AriusStatsEnum.NODE_INFO, esNodeStatsList);\n    }\n\n    public void sendIndexInfo(List<ESIndexStats> esIndexStats) {\n        send2es(AriusStatsEnum.INDEX_INFO, esIndexStats);\n    }\n\n    public void sendIndexToNodeStats(List<ESIndexToNodeStats> esIndexToNodeStats) {\n        send2es(AriusStatsEnum.INDEX_NODE_INFO, esIndexToNodeStats);\n    }\n\n    public void sendESNodeToIndexStats(List<ESNodeToIndexStats> esNodeToIndexStats) {\n        send2es(AriusStatsEnum.NODE_INDEX_INFO, esNodeToIndexStats);\n    }\n\n    public void sendIngestStats(List<ESIngestStats> esIngestStats) {\n        send2es(AriusStatsEnum.INGEST_INFO, esIngestStats);\n    }\n\n    public void sendDCDRStats(List<ESIndexDCDRStats> esIndexDCDRStats) {\n        send2es(AriusStatsEnum.DCDR_INFO, esIndexDCDRStats);\n    }\n\n    public void sendClusterStats(List<ESClusterStats> esClusterStats) {\n        send2es(AriusStatsEnum.CLUSTER_INFO, esClusterStats);\n    }\n\n    public void sendClusterTaskStats(List<ESClusterTaskStats> esClusterTaskStats) {\n        send2es(AriusStatsEnum.TASK_INFO, esClusterTaskStats);\n    }\n\n    public void sendDashboardStats(List<DashBoardStats> dashBoardStats) {\n        send2es(AriusStatsEnum.DASHBOARD_INFO, dashBoardStats);\n    }\n\n    /**\n     * 根据不同监控维度来发送\n     *\n     * @param ariusStats\n     * @param statsList\n     * @return\n     */\n    private boolean send2es(AriusStatsEnum ariusStats, List<? extends BaseESPO> statsList) {\n        if (CollectionUtils.isEmpty(statsList)) {\n            return true;\n        }\n\n        LOGGER.debug(\"class=MonitorMetricsSender||method=send2es||ariusStats={}||size={}\", ariusStats.getType(),\n                statsList.size());\n\n\n        BaseAriusStatsESDAO baseAriusStatsEsDao = BaseAriusStatsESDAO.getByStatsType(ariusStats);\n        if (Objects.isNull(baseAriusStatsEsDao)) {\n            LOGGER.error(\"class=MonitorMetricsSender||method=send2es||errMsg=fail to find {}\", ariusStats.getType());\n            return false;\n        }\n\n        int size = statsList.size();\n        int num = (size) % THRESHOLD == 0 ? (size / THRESHOLD) : (size / THRESHOLD + 1);\n\n        if (size < THRESHOLD) {\n            esExecutor.execute(() -> baseAriusStatsEsDao.batchInsertStats(statsList));\n            return true;\n        }\n\n        for (int i = 1; i < num + 1; i++) {\n            int end = (i * THRESHOLD) > size ? size : (i * THRESHOLD);\n            int start = (i - 1) * THRESHOLD;\n\n            esExecutor.execute(() -> baseAriusStatsEsDao.batchInsertStats(statsList.subList(start, end)));\n        }\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/action/ESIndicesSimpleStatsAction.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.action;\n\n/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESIndicesSimpleStatsAction extends\n                                        Action<ESIndicesSimpleStatsRequest, ESIndicesSimpleStatsResponse, ESIndicesSimpleStatsRequestBuilder> {\n\n    public static final ESIndicesSimpleStatsAction INSTANCE = new ESIndicesSimpleStatsAction();\n    public static final String                     NAME     = \"indices:simplestats\";\n\n    public ESIndicesSimpleStatsAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesSimpleStatsResponse newResponse() {\n        return new ESIndicesSimpleStatsResponse();\n    }\n\n    @Override\n    public ESIndicesSimpleStatsRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesSimpleStatsRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/action/ESIndicesSimpleStatsRequest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.action;\n\n/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport com.alibaba.fastjson.JSON;\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.request.broadcast.ESBroadcastRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.stats.IndicesStatsLevel;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * A request to get indices level nodestats. Allow to enable different nodestats to be returned.\n * <p>\n * By default, all statistics are enabled.\n * <p>\n * All the nodestats to be returned can be cleared using {@link #clear()}, at which point, specific\n * nodestats can be enabled.\n */\npublic class ESIndicesSimpleStatsRequest extends ESBroadcastRequest<ESIndicesSimpleStatsRequest> {\n    public static String      COMPLETION    = \"completion\";\n    public static String      STORE         = \"store\";\n    public static String      INDEXING      = \"indexing\";\n    public static String      TRANSLOG      = \"translog\";\n    public static String      REFRESH       = \"refresh\";\n    public static String      SUGGEST       = \"suggest\";\n    public static String      RECOVERY      = \"recovery\";\n    public static String      WARMER        = \"warmer\";\n    public static String      SEGMENTS      = \"segments\";\n    public static String      SEARCH        = \"search\";\n    public static String      QUERY_CACHE   = \"query_cache\";\n    public static String      DOCS          = \"docs\";\n    public static String      FLUSH         = \"flush\";\n    public static String      FIELDDATA     = \"fielddata\";\n    public static String      GET           = \"get\";\n    public static String      MERGE         = \"merge\";\n    public static String      REQUEST_CACHE = \"request_cache\";\n\n    private Set<String>       flags         = new HashSet<>();\n    private IndicesStatsLevel level         = null;\n\n    /**\n     * Sets all flags to return all nodestats.\n     */\n    public ESIndicesSimpleStatsRequest all() {\n        flags.add(COMPLETION);\n        flags.add(INDEXING);\n        flags.add(TRANSLOG);\n        flags.add(REFRESH);\n        flags.add(SUGGEST);\n        flags.add(RECOVERY);\n        flags.add(WARMER);\n        flags.add(SEGMENTS);\n        flags.add(SEARCH);\n        flags.add(QUERY_CACHE);\n        flags.add(DOCS);\n        flags.add(FLUSH);\n        flags.add(FIELDDATA);\n        flags.add(GET);\n        flags.add(MERGE);\n        flags.add(REQUEST_CACHE);\n\n        return this;\n    }\n\n    /**\n     * Clears all nodestats.\n     */\n    public ESIndicesSimpleStatsRequest clear() {\n        flags.clear();\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequest types(String... types) {\n        for (String type : types) {\n            flags.add(type);\n        }\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequest flag(String type, boolean isSet) {\n        if (isSet) {\n            flags.add(type);\n        } else {\n            flags.remove(type);\n        }\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequest setLevel(IndicesStatsLevel level) {\n        this.level = level;\n\n        return this;\n    }\n\n    public boolean isSet(String type) {\n        return flags.contains(type);\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = buildEndPoint();\n        RestRequest rr = new RestRequest(\"GET\", endpoint, null);\n\n        if (level != null) {\n            rr.addParam(\"level\", level.getStr());\n        }\n\n        return rr;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n\n        String respStr = response.getResponseContent();\n        ESActionResponse esActionResponse = JSON.parseObject(respStr, ESIndicesSimpleStatsResponse.class);\n        return esActionResponse;\n    }\n\n    private String buildEndPoint() {\n        String type = null;\n        if (flags != null && flags.size() > 0) {\n            type = StringUtils.join(flags, \",\");\n        }\n        if (type != null && type.trim().length() == 0) {\n            type = null;\n        }\n\n        String index = null;\n        if (indices != null && indices.length > 0) {\n            index = StringUtils.join(indices, \",\");\n        }\n\n        if (index == null) {\n            if (type == null) {\n                return \"/_stats\";\n            } else {\n                return \"/_stats/\" + type.trim();\n            }\n        } else {\n            if (type == null) {\n                return \"/\" + index.trim() + \"/_stats\";\n            } else {\n                return \"/\" + index.trim() + \"/_stats/\" + type.trim();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/action/ESIndicesSimpleStatsRequestBuilder.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.action;\n\n/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport com.didiglobal.knowframework.elasticsearch.client.request.broadcast.ESBroadcastOperationRequestBuilder;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.stats.IndicesStatsLevel;\nimport org.elasticsearch.client.ElasticsearchClient;\n\nimport static com.didiglobal.knowframework.elasticsearch.client.request.index.stats.ESIndicesStatsRequest.*;\n\n/**\n * A request to get indices level nodestats. Allow to enable different nodestats to be returned.\n * <p>\n * By default, the {@link #setDocs(boolean)}, {@link #setStore(boolean)}, {@link #setIndexing(boolean)}\n * are enabled. Other nodestats can be enabled as well.zx\n * <p>\n * All the nodestats to be returned can be cleared using {@link #clear()}, at which point, specific\n * nodestats can be enabled.\n */\npublic class ESIndicesSimpleStatsRequestBuilder extends\n                                                ESBroadcastOperationRequestBuilder<ESIndicesSimpleStatsRequest, ESIndicesSimpleStatsResponse, ESIndicesSimpleStatsRequestBuilder> {\n\n    public ESIndicesSimpleStatsRequestBuilder(ElasticsearchClient client, ESIndicesSimpleStatsAction action) {\n        super(client, action, new ESIndicesSimpleStatsRequest());\n    }\n\n    /**\n     * Sets all flags to return all nodestats.\n     */\n    public ESIndicesSimpleStatsRequestBuilder all() {\n        request.all();\n        return this;\n    }\n\n    /**\n     * Clears all nodestats.\n     */\n    public ESIndicesSimpleStatsRequestBuilder clear() {\n        request.clear();\n        return this;\n    }\n\n    /**\n     * Document types to return nodestats for. Mainly affects {@link #setIndexing(boolean)} when\n     * enabled, returning specific indexing nodestats for those types.\n     */\n    public ESIndicesSimpleStatsRequestBuilder setTypes(String... types) {\n        request.types(types);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setDocs(boolean docs) {\n        request.flag(DOCS, docs);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setStore(boolean store) {\n        request.flag(STORE, store);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setIndexing(boolean indexing) {\n        request.flag(INDEXING, indexing);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setGet(boolean get) {\n        request.flag(GET, get);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setSearch(boolean search) {\n        request.flag(SEARCH, search);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setMerge(boolean merge) {\n        request.flag(MERGE, merge);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setRefresh(boolean refresh) {\n        request.flag(REFRESH, refresh);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setFlush(boolean flush) {\n        request.flag(FLUSH, flush);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setWarmer(boolean warmer) {\n        request.flag(WARMER, warmer);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setQueryCache(boolean queryCache) {\n        request.flag(QUERY_CACHE, queryCache);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setFieldData(boolean fieldData) {\n        request.flag(FIELDDATA, fieldData);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setSegments(boolean segments) {\n        request.flag(SEGMENTS, segments);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setCompletion(boolean completion) {\n        request.flag(COMPLETION, completion);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setTranslog(boolean translog) {\n        request.flag(TRANSLOG, translog);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setSuggest(boolean suggest) {\n        request.flag(SUGGEST, suggest);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setRequestCache(boolean requestCache) {\n        request.flag(REQUEST_CACHE, requestCache);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setRecovery(boolean recovery) {\n        request.flag(RECOVERY, recovery);\n        return this;\n    }\n\n    public ESIndicesSimpleStatsRequestBuilder setLevel(IndicesStatsLevel level) {\n        request.setLevel(level);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/action/ESIndicesSimpleStatsResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.action;\n\n/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.search.response.Shards;\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionResponse;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n */\npublic class ESIndicesSimpleStatsResponse extends ESActionResponse {\n\n    @JSONField(name = \"_shards\")\n    private Shards                       shards;\n\n    @JSONField(name = \"_all\")\n    private SimpleIndexNode              all;\n\n    @JSONField(name = \"indices\")\n    private Map<String, SimpleIndexNode> indices = new HashMap<>();\n\n    public Shards getShards() {\n        return shards;\n    }\n\n    public void setShards(Shards shards) {\n        this.shards = shards;\n    }\n\n    public SimpleIndexNode getAll() {\n        return all;\n    }\n\n    public void setAll(SimpleIndexNode all) {\n        this.all = all;\n    }\n\n    public JSONObject getIndices() {\n        if (indices == null || indices.size() == 0) {\n            return null;\n        }\n\n        JSONObject ret = new JSONObject();\n\n        for (Map.Entry<String, SimpleIndexNode> entry : indices.entrySet()) {\n            String index = entry.getKey();\n            ret.put(index, JSON.toJSON(indices.get(index)));\n        }\n        return ret;\n    }\n\n    public void setIndices(JSONObject root) {\n        if (root == null) {\n            return;\n        }\n\n        for (String index : root.keySet()) {\n            String str = root.getString(index);\n            indices.put(index, JSON.parseObject(str, SimpleIndexNode.class));\n        }\n    }\n\n    @JSONField(serialize = false)\n    public Map<String, SimpleIndexNode> getIndicesMap() {\n        return indices;\n    }\n\n    @JSONField(serialize = false)\n    public void setIndicesMap(Map<String, SimpleIndexNode> indicesMap) {\n        this.indices = indicesMap;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        return (JSONObject) JSON.toJSON(this);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/action/SimpleCommonStat.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.action;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.indices.Routing;\n\npublic class SimpleCommonStat {\n    @JSONField(name = \"routing\")\n    private Routing routing;\n\n    public Routing getRouting() {\n        return routing;\n    }\n\n    public void setRouting(Routing routing) {\n        this.routing = routing;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/action/SimpleIndexNode.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.action;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.indices.CommonStat;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic class SimpleIndexNode {\n    @JSONField(name = \"primaries\")\n    private CommonStat                          primaries;\n\n    @JSONField(name = \"total\")\n    private CommonStat                          total;\n\n    @JSONField(name = \"shards\")\n    private Map<String, List<SimpleCommonStat>> shards;\n\n    public CommonStat getPrimaries() {\n        return primaries;\n    }\n\n    public void setPrimaries(CommonStat primaries) {\n        this.primaries = primaries;\n    }\n\n    public CommonStat getTotal() {\n        return total;\n    }\n\n    public void setTotal(CommonStat total) {\n        this.total = total;\n    }\n\n    public Map<String, List<SimpleCommonStat>> getShards() {\n        return shards;\n    }\n\n    public void setShards(Map<String, List<SimpleCommonStat>> shards) {\n        this.shards = shards;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/index/ESIndexStatsAction.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.index;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndexStatsAction extends Action<ESIndexStatsRequest, ESIndexStatsResponse, ESIndexStatsRequestBuilder> {\n\n    public static final ESIndexStatsAction INSTANCE = new ESIndexStatsAction();\n    public static final String             NAME     = \"indices:stats/tolerance\";\n\n    private ESIndexStatsAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndexStatsResponse newResponse() {\n        return new ESIndexStatsResponse();\n    }\n\n    @Override\n    public ESIndexStatsRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndexStatsRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/index/ESIndexStatsRequest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.index;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node.ESBroadcastTimeoutRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.stats.IndicesStatsLevel;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class ESIndexStatsRequest extends ESBroadcastTimeoutRequest<ESIndexStatsRequest> {\n    public static String      COMPLETION    = \"completion\";\n    public static String      STORE         = \"store\";\n    public static String      INDEXING      = \"indexing\";\n    public static String      TRANSLOG      = \"translog\";\n    public static String      REFRESH       = \"refresh\";\n    public static String      SUGGEST       = \"suggest\";\n    public static String      RECOVERY      = \"recovery\";\n    public static String      WARMER        = \"warmer\";\n    public static String      SEGMENTS      = \"segments\";\n    public static String      SEARCH        = \"search\";\n    public static String      QUERY_CACHE   = \"query_cache\";\n    public static String      DOCS          = \"docs\";\n    public static String      FLUSH         = \"flush\";\n    public static String      FIELDDATA     = \"fielddata\";\n    public static String      GET           = \"get\";\n    public static String      MERGE         = \"merge\";\n    public static String      REQUEST_CACHE = \"request_cache\";\n\n    private Set<String>       flags         = new HashSet<>();\n    private IndicesStatsLevel level         = null;\n\n    /**\n     * Sets all flags to return all nodestats.\n     */\n    public ESIndexStatsRequest all() {\n        flags.add(COMPLETION);\n        flags.add(INDEXING);\n        flags.add(TRANSLOG);\n        flags.add(REFRESH);\n        flags.add(SUGGEST);\n        flags.add(RECOVERY);\n        flags.add(WARMER);\n        flags.add(SEGMENTS);\n        flags.add(SEARCH);\n        flags.add(QUERY_CACHE);\n        flags.add(DOCS);\n        flags.add(FLUSH);\n        flags.add(FIELDDATA);\n        flags.add(GET);\n        flags.add(MERGE);\n        flags.add(REQUEST_CACHE);\n\n        return this;\n    }\n\n    /**\n     * Clears all nodestats.\n     */\n    public ESIndexStatsRequest clear() {\n        flags.clear();\n        return this;\n    }\n\n    public ESIndexStatsRequest types(String... types) {\n        for (String type : types) {\n            flags.add(type);\n        }\n        return this;\n    }\n\n    public ESIndexStatsRequest flag(String type, boolean isSet) {\n        if (isSet) {\n            flags.add(type);\n        } else {\n            flags.remove(type);\n        }\n        return this;\n    }\n\n    public ESIndexStatsRequest setLevel(IndicesStatsLevel level) {\n        this.level = level;\n\n        return this;\n    }\n\n    public boolean isSet(String type) {\n        return flags.contains(type);\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = buildEndPoint();\n        RestRequest rr = new RestRequest(\"GET\", endpoint, null);\n        if (level != null) {\n            rr.addParam(\"level\", level.getStr());\n        }\n        return rr;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESIndexStatsResponse.class);\n    }\n\n    @SuppressWarnings(\"all\")\n    private String buildEndPoint() {\n        String index = indices != null && indices.length > 0 ? StringUtils.join(indices, \",\").trim() : null;\n        String type = flags.size() > 0 ? StringUtils.join(flags, \",\").trim() : null;\n        String indexUrl = null == index ? \"/_stats\" : String.format(\"/%s/_stats\", index);\n        String finalUrl = null == type ? indexUrl : indexUrl + \"/\" + type;\n        return finalUrl;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/index/ESIndexStatsRequestBuilder.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.index;\n\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node.ESBroadcastTimeoutRequestBuilder;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.stats.IndicesStatsLevel;\nimport org.elasticsearch.client.ElasticsearchClient;\n\nimport static com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.index.ESIndexStatsRequest.*;\n\npublic class ESIndexStatsRequestBuilder extends\n                                        ESBroadcastTimeoutRequestBuilder<ESIndexStatsRequest, ESIndexStatsResponse, ESIndexStatsRequestBuilder> {\n\n    public ESIndexStatsRequestBuilder(ElasticsearchClient client, ESIndexStatsAction action) {\n        super(client, action, new ESIndexStatsRequest());\n    }\n\n    /**\n     * Sets all flags to return all nodestats.\n     */\n    public ESIndexStatsRequestBuilder all() {\n        request.all();\n        return this;\n    }\n\n    /**\n     * Clears all nodestats.\n     */\n    public ESIndexStatsRequestBuilder clear() {\n        request.clear();\n        return this;\n    }\n\n    /**\n     * Document types to return nodestats for. Mainly affects {@link #setIndexing(boolean)} when\n     * enabled, returning specific indexing nodestats for those types.\n     */\n    public ESIndexStatsRequestBuilder setTypes(String... types) {\n        request.types(types);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setDocs(boolean docs) {\n        request.flag(DOCS, docs);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setStore(boolean store) {\n        request.flag(STORE, store);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setIndexing(boolean indexing) {\n        request.flag(INDEXING, indexing);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setGet(boolean get) {\n        request.flag(GET, get);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setSearch(boolean search) {\n        request.flag(SEARCH, search);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setMerge(boolean merge) {\n        request.flag(MERGE, merge);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setRefresh(boolean refresh) {\n        request.flag(REFRESH, refresh);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setFlush(boolean flush) {\n        request.flag(FLUSH, flush);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setWarmer(boolean warmer) {\n        request.flag(WARMER, warmer);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setQueryCache(boolean queryCache) {\n        request.flag(QUERY_CACHE, queryCache);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setFieldData(boolean fieldData) {\n        request.flag(FIELDDATA, fieldData);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setSegments(boolean segments) {\n        request.flag(SEGMENTS, segments);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setCompletion(boolean completion) {\n        request.flag(COMPLETION, completion);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setTranslog(boolean translog) {\n        request.flag(TRANSLOG, translog);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setSuggest(boolean suggest) {\n        request.flag(SUGGEST, suggest);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setRequestCache(boolean requestCache) {\n        request.flag(REQUEST_CACHE, requestCache);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setRecovery(boolean recovery) {\n        request.flag(RECOVERY, recovery);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setLevel(IndicesStatsLevel level) {\n        request.setLevel(level);\n        return this;\n    }\n\n    public ESIndexStatsRequestBuilder setTimeout(String timeout) {\n        request.timeout(timeout);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/index/ESIndexStatsResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.index;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.search.response.Shards;\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.stats.IndexNodes;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ESIndexStatsResponse extends ESActionResponse {\n\n    @JSONField(name = \"_shards\")\n    private Shards                  shards;\n\n    @JSONField(name = \"_all\")\n    private IndexNodes              all;\n\n    @JSONField(name = \"indices\")\n    private Map<String, IndexNodes> indices = new HashMap<>();\n\n    public Shards getShards() {\n        return shards;\n    }\n\n    public void setShards(Shards shards) {\n        this.shards = shards;\n    }\n\n    public IndexNodes getAll() {\n        return all;\n    }\n\n    public void setAll(IndexNodes all) {\n        this.all = all;\n    }\n\n    public JSONObject getIndices() {\n        if (indices == null || indices.size() == 0) {\n            return null;\n        }\n\n        JSONObject ret = new JSONObject();\n        for (Map.Entry<String, IndexNodes> entry : indices.entrySet()) {\n            ret.put(entry.getKey(), JSON.toJSON(entry.getValue()));\n        }\n        return ret;\n    }\n\n    public void setIndices(JSONObject root) {\n        if (root == null) {\n            return;\n        }\n\n        for (String index : root.keySet()) {\n            String str = root.getString(index);\n            indices.put(index, JSON.parseObject(str, IndexNodes.class));\n        }\n    }\n\n    @JSONField(serialize = false)\n    public Map<String, IndexNodes> getIndicesMap() {\n        return indices;\n    }\n\n    @JSONField(serialize = false)\n    public void setIndicesMap(Map<String, IndexNodes> indicesMap) {\n        this.indices = indicesMap;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        return (JSONObject) JSON.toJSON(this);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/metrics/CollectMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics;\n\nimport com.google.common.collect.Maps;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class CollectMetrics {\n\n    public static final String  ES_2                 = \"2\";\n    public static final String  ES_6                 = \"6\";\n\n    /**\n     * 指标名字\n     */\n    private String              valueName;\n\n    /**\n     * 指标采集路径\n     */\n    private String              valueRoute;\n\n    /**\n     * 衍生计算需要的参数\n     */\n    private Map<String, String> deriveParam;\n\n    /**\n     * 指标计算方式\n     */\n    private MetricsComputeType  computeType;\n\n    /**\n     * 索引节点指标中是否包含,默认不包含\n     */\n    private boolean             isIndexToNodeMetrics = false;\n\n    /**\n     * 是否需要从Odin修正数据\n     */\n    private boolean             needCorrectFromOdin  = false;\n\n    /**\n     * 是否需要发送夜莺\n     */\n    private boolean             sendToN9e            = false;\n\n    @Data\n    public static class Builder {\n        private String              valueName;\n\n        private String              valueRoute;\n\n        private MetricsComputeType  computeType;\n\n        private boolean             isIndexToNodeMetrics = false;\n\n        private boolean             needCorrectFromOdin  = false;\n\n        private boolean             sendToN9e            = false;\n\n        private String              esVersion            = \"\";\n\n        private Map<String, String> deriveParam          = Maps.newHashMap();\n\n        public Builder valueName(String valueName) {\n            this.valueName = valueName.trim();\n            return this;\n        }\n\n        public Builder valueRoute(String valueRoute) {\n            this.valueRoute = valueRoute.trim();\n            return this;\n        }\n\n        public Builder computeType(MetricsComputeType computeType) {\n            this.computeType = computeType;\n            return this;\n        }\n\n        public Builder deriveParam(String name, String value) {\n            deriveParam.put(name, value);\n            return this;\n        }\n\n        public Builder bIndexToNodeMetrics() {\n            this.isIndexToNodeMetrics = true;\n            return this;\n        }\n\n        public Builder needCorrectFromOdin() {\n            this.needCorrectFromOdin = true;\n            return this;\n        }\n\n        public Builder sendToN9e() {\n            this.sendToN9e = true;\n            return this;\n        }\n\n        public CollectMetrics build() {\n            return new CollectMetrics(this);\n        }\n    }\n\n    public CollectMetrics(Builder builder) {\n        this.valueName = builder.getValueName();\n        this.valueRoute = builder.getValueRoute();\n        this.computeType = builder.getComputeType();\n        this.deriveParam = builder.getDeriveParam();\n        this.isIndexToNodeMetrics = builder.isIndexToNodeMetrics();\n        this.needCorrectFromOdin = builder.isNeedCorrectFromOdin();\n        this.sendToN9e = builder.isSendToN9e();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/metrics/DCDRMetrics.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * author weizijun\n * date：2020-01-20\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class DCDRMetrics {\n    /**\n     * max_seq_no延迟量\n     */\n    @JSONField(name = \"max_seq_no_delay\")\n    private long maxSeqNoDelay;\n\n    /**\n     * global_checkpoint延迟量\n     */\n    @JSONField(name = \"global_checkpoint_delay\")\n    private long globalCheckpointDelay;\n\n    /**\n     * shard中最少的可用的bulk队列\n     */\n    @JSONField(name = \"min_available_send_bulk_number\")\n    private long minAvailableSendBulkNumber = Long.MAX_VALUE;\n\n    /**\n     * 总的发送时间\n     */\n    @JSONField(name = \"total_send_time_millis\")\n    private long totalSendTimeMillis;\n\n    /**\n     * 总的发送请求数\n     */\n    @JSONField(name = \"total_send_request\")\n    private long totalSendRequests;\n\n    /**\n     * 发送失败数\n     */\n    @JSONField(name = \"failed_send_requests\")\n    private long failedSendRequests;\n\n    /**\n     * 发送的bulk请求数\n     */\n    @JSONField(name = \"operations_send\")\n    private long operationsSend;\n\n    /**\n     * 发送的总字节数\n     */\n    @JSONField(name = \"bytes_send\")\n    private long bytesSend;\n\n    /**\n     * 上次发送请求时间间隔最小的shard时间\n     */\n    @JSONField(name = \"min_time_since_last_send_millis\")\n    private long minTimeSinceLastSendMillis = Long.MAX_VALUE;\n\n    /**\n     * 上次发送请求时间间隔最大的shard时间\n     */\n    @JSONField(name = \"max_time_since_last_send_millis\")\n    private long maxTimeSinceLastSendMillis = -1;\n\n    /**\n     * 成功的恢复数量\n     */\n    @JSONField(name = \"success_recover_count\")\n    private long successRecoverCount;\n\n    /**\n     * 失败的恢复数量\n     */\n    @JSONField(name = \"failed_recover_count\")\n    private long failedRecoverCount;\n\n    /**\n     * 总的恢复时间\n     */\n    @JSONField(name = \"recover_total_time_millis\")\n    private long recoverTotalTimeMillis;\n\n    /**\n     * 在同步的translog数量\n     */\n    @JSONField(name = \"in_sync_translog_offset_size\")\n    private long inSyncTranslogOffsetSize;\n\n    /**\n     * 上次更新checkpoint时间间隔最大的shard时间\n     */\n    @JSONField(name = \"max_time_since_update_replica_checkpoint\")\n    private long maxTimeSinceUpdateReplicaCheckPoint;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/metrics/DeriveComputer.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESDataTempBean;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\npublic class DeriveComputer implements MetricsComputer {\n    private static final ILog  LOGGER = LogFactory.getLog(DeriveComputer.class);\n\n    private MetricsRegister    metricsRegister;\n\n    private MetricsComputeType computeType;\n\n    public DeriveComputer(MetricsComputeType computeType, MetricsRegister metricsRegister) {\n        this.computeType = computeType;\n        this.metricsRegister = metricsRegister;\n    }\n\n    @Override\n    public String compute(ESDataTempBean esDataTempBean) {\n        try {\n            String keyPre = esDataTempBean.getKeyPre();\n            String dividendKey = keyPre + esDataTempBean.getDeriverParamByKey(ESDataTempBean.DIVIDEND);\n            String divisorKey = keyPre + esDataTempBean.getDeriverParamByKey(ESDataTempBean.DIVISOR);\n\n            Double first = metricsRegister.getBeforeComputeData(dividendKey);\n            Double second = metricsRegister.getBeforeComputeData(divisorKey);\n\n            if (first == null || second == null) {\n                //防止AMS启动时误报\n                esDataTempBean.setSendToN9e(false);\n\n                return null;\n            }\n\n            Object value = computeType.compute(new ESDataTempBean(first), new ESDataTempBean(second));\n            return String.valueOf(value);\n        } catch (Exception e) {\n            LOGGER.error(\"class=DeriveComputer||method=compute||msg=exception\", e);\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/metrics/ESNodeToIndexComputer.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESDataTempBean;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESNodeToIndexTempBean;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\npublic class ESNodeToIndexComputer {\n    private static final ILog  LOGGER = LogFactory.getLog(ESNodeToIndexComputer.class);\n\n    private MetricsRegister    metricsRegister;\n\n    private MetricsComputeType computeType;\n\n    public ESNodeToIndexComputer(MetricsComputeType computeType, MetricsRegister metricsRegister) {\n        this.computeType = computeType;\n        this.metricsRegister = metricsRegister;\n    }\n\n    public String compute(ESNodeToIndexTempBean dataBean) {\n        try {\n            //无需计算\n            if (computeType == MetricsComputeType.NONE) {\n\n                LOGGER.debug(\"class=ESNodeToIndexComputer||method=compute||valueName={}\", dataBean.getValueName());\n\n\n                return String.valueOf(dataBean.getValue());\n            }\n\n            if (computeType == MetricsComputeType.DERIVE_DIVISION) {\n                return devireCompute(dataBean);\n            }\n\n            return simpleCompute(dataBean);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESNodeToIndexComputer||method=compute||msg=exception\", e);\n        }\n        return null;\n    }\n\n    private String devireCompute(ESNodeToIndexTempBean dataBean) {\n        String keyPre = dataBean.getKeyPre();\n\n        String dividendKey = keyPre + dataBean.getDeriveParam(ESDataTempBean.DIVIDEND);\n        String divisorKey = keyPre + dataBean.getDeriveParam(ESDataTempBean.DIVISOR);\n\n        Double first = metricsRegister.getBeforeComputeData(dividendKey);\n        Double second = metricsRegister.getBeforeComputeData(divisorKey);\n\n        if (first == null || second == null) {\n\n            LOGGER.debug(\"class=ESNodeToIndexComputer||method=devireCompute||keyPre={}||value={}\", keyPre, dataBean.getValueName());\n\n            return null;\n        }\n\n        Object value = computeType.compute(new ESNodeToIndexTempBean(first), new ESNodeToIndexTempBean(second));\n        if (value == null) {\n            LOGGER.debug(\"class=ESNodeToIndexComputer||method=devireCompute||dataBean={}\", dataBean);\n\n            return null;\n        }\n\n        return String.valueOf(value);\n    }\n\n    private String simpleCompute(ESNodeToIndexTempBean dataBean) {\n        String key = dataBean.getKey();\n        ESNodeToIndexTempBean beforeData = metricsRegister.getBeforeNodeToIndexData(key);\n        metricsRegister.putBeforeNodeToIndexData(key, dataBean);\n        if (beforeData == null) {\n\n            LOGGER.debug(\"class=ESNodeToIndexComputer||method=simpleCompute||key={}\", key);\n\n            return null;\n        } else {\n\n            if (dataBean.getValue() == null) {\n\n                LOGGER.debug(\"class=ESNodeToIndexComputer||method=simpleCompute||dataBean={}||msg=dataValue is null!\", dataBean);\n\n                return null;\n            }\n\n            Double value = computeType.compute(beforeData, dataBean);\n            if (value == null) {\n\n                LOGGER.debug(\"class=ESNodeToIndexComputer||method=simpleCompute||dataBean={}||msg=computer value is null!\", dataBean);\n\n                return null;\n            }\n\n            metricsRegister.putBeforeComputeData(key, value);\n            return String.valueOf(value);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/metrics/MetricsComputeType.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.CollectBean;\n\npublic enum MetricsComputeType {\n    /**\n     * MINUS\n     */\n    MINUS,\n    /**\n     * AVG\n     */\n    AVG,\n    /**\n     * AVG_MIN\n     */\n    AVG_MIN,\n    /**\n     * DERIVE_DIVISION\n     */\n    DERIVE_DIVISION,\n    /**\n     * NONE\n     */\n    NONE;\n\n    public Double compute(CollectBean before, CollectBean now) {\n        Double beforeD = before.getValue();\n        Double nowD = now.getValue();\n\n        switch (this) {\n            case MINUS:\n                return minusByDouble(beforeD, nowD);\n            case AVG:\n                return avg(before, now, minusByDouble(beforeD, nowD));\n            case AVG_MIN:\n                return avgMin(before, now, minusByDouble(beforeD, nowD));\n            case DERIVE_DIVISION:\n                return divide(beforeD, nowD);\n            case NONE:\n                return nowD;\n            default:\n                return null;\n        }\n    }\n\n    public MetricsComputer getComputer(MetricsRegister metricsRegister) {\n        if (this == DERIVE_DIVISION) {\n            return new DeriveComputer(this, metricsRegister);\n        }\n\n        return new SimpleComputer(this, metricsRegister);\n    }\n\n    private Double avg(CollectBean before, CollectBean now, Double result) {\n        if (result == null) {\n            return null;\n        }\n        if (result == 0.0) {\n            return 0.0;\n        }\n\n        //now.getTimestamp()时间戳单位是毫秒\n        Double value = 1000 * result / (now.getTimestamp() - before.getTimestamp());\n        if (value < 0.0) {\n            value = 0.0;\n        }\n\n        return value;\n    }\n\n    private Double avgMin(CollectBean before, CollectBean now, Double result) {\n        if (result == null) {\n            return null;\n        }\n        if (result == 0.0) {\n            return 0.0;\n        }\n\n        //now.getTimestamp()时间戳单位是毫秒\n        Double value = 1000 * 60 * result / (now.getTimestamp() - before.getTimestamp());\n        if (value < 0.0) {\n            value = 0.0;\n        }\n\n        return value;\n    }\n\n    private Double divide(Double first, Double second) {\n        if (first == 0.0 || second == 0.0) {\n            return 0.0;\n        }\n\n        return first / second;\n    }\n\n    private Double minusByDouble(Double before, Double now) {\n        // 类似Get {index}/_stat等RPC请求，存在超时的场景，此时获取的now为空, 特殊处理\n        if (null == now || null == before) {\n            return 0.0;\n        }\n        if (0 == now || 0 == before) {\n            return 0.0;\n        }\n\n        double res = now - before;\n        return res < 0 ? 0 : res;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/metrics/MetricsComputer.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESDataTempBean;\n\npublic interface MetricsComputer {\n    String compute(ESDataTempBean esDataTempBean);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/metrics/MetricsRegister.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics;\n\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESDataTempBean;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESNodeToIndexTempBean;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Maps;\n\n/**\n * @author didi\n * @date 2022/09/13\n */\npublic class MetricsRegister {\n    /**\n     * 缓存普通的采集自es 发送给odin的数据\n     */\n    private final Cache<String, ESDataTempBean>        dataBeanRegisterCache  = CacheBuilder.newBuilder()\n        .expireAfterWrite(10, TimeUnit.MINUTES).initialCapacity(10000).build();\n\n    /**\n     * 缓存采集自一个node上的索引的指标数据\n     */\n    private final Cache<String, ESNodeToIndexTempBean> nodeIndexRegisterCache = CacheBuilder.newBuilder()\n        .expireAfterWrite(10, TimeUnit.MINUTES).initialCapacity(10000).build();\n\n    /**\n     * 缓存需要复合计算的值\n     */\n    private Map<String, Double>                computeValueRegister;\n\n    private Map<String, Tuple<Long, Double>>   clusterNodeCpu;\n\n    public MetricsRegister() {\n        computeValueRegister = Maps.newConcurrentMap();\n        clusterNodeCpu = Maps.newConcurrentMap();\n    }\n\n    public void putBeforeNodeToIndexData(String key, ESNodeToIndexTempBean data) {\n        nodeIndexRegisterCache.put(key, data);\n    }\n\n    public ESNodeToIndexTempBean getBeforeNodeToIndexData(String key) {\n        return nodeIndexRegisterCache.getIfPresent(key);\n    }\n\n    public void putBeforeEsData(String key, ESDataTempBean data) {\n        dataBeanRegisterCache.put(key, data);\n    }\n\n    public ESDataTempBean getBeforeEsData(String key) {\n        return dataBeanRegisterCache.getIfPresent(key);\n    }\n\n    public void putBeforeComputeData(String key, Double data) {\n        computeValueRegister.put(key, data);\n    }\n\n    public Double getBeforeComputeData(String key) {\n        return computeValueRegister.get(key);\n    }\n\n    public void clearComputeValueRegister() {\n        computeValueRegister.clear();\n    }\n\n    public void putNodeCpu(String ip, Tuple<Long, Double> cpu) {\n        clusterNodeCpu.put(ip, cpu);\n    }\n\n    public Tuple<Long, Double> getNodeCpu(String ip) {\n        return clusterNodeCpu.get(ip);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/metrics/SimpleComputer.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESDataTempBean;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\npublic class SimpleComputer implements MetricsComputer {\n    private static final ILog  LOGGER = LogFactory.getLog(SimpleComputer.class);\n\n    private MetricsRegister    metricsRegister;\n\n    private MetricsComputeType computeType;\n\n    public SimpleComputer(MetricsComputeType computeType, MetricsRegister metricsRegister) {\n        this.computeType = computeType;\n        this.metricsRegister = metricsRegister;\n    }\n\n    @Override\n    public String compute(ESDataTempBean esDataTempBean) {\n        try {\n            String key = esDataTempBean.getKey();\n            ESDataTempBean beforeData = metricsRegister.getBeforeEsData(key);\n            metricsRegister.putBeforeEsData(key, esDataTempBean);\n            if (beforeData == null) {\n                LOGGER.debug(\"class=SimpleComputer||method=compute||key={}||msg=beforeData is null!\", key);\n\n                //防止启动AMS时误报\n                esDataTempBean.setSendToN9e(false);\n                return null;\n            } else {\n                if (esDataTempBean.getValue() == null) {\n                    LOGGER.debug(\"class=SimpleComputer||method=compute||msg=collect data value is null. {}\", esDataTempBean);\n\n                    return null;\n                }\n\n                Double value = computeType.compute(beforeData, esDataTempBean);\n\n                //为了衍生计算,缓存计算结果;每次周期开始之前会清空上个周期的缓存\n                metricsRegister.putBeforeComputeData(key, value);\n                return String.valueOf(value);\n            }\n        } catch (Exception e) {\n            LOGGER.info(\"class=SimpleComputer||method=compute||msg=exception\", e);\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/BaseTimeoutRequest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionRequest;\n\npublic abstract class BaseTimeoutRequest<T extends ESActionRequest> extends ESActionRequest<T> {\n\n    //默认超时时间\n    protected String timeout = \"30s\";\n\n    public T timeout(String timeout) {\n        this.timeout = timeout;\n        return (T) this;\n    }\n\n    protected BaseTimeoutRequest() {\n    }\n\n    protected BaseTimeoutRequest(ESActionRequest request) {\n        super(request);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/ESBroadcastTimeoutRequest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionRequest;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.action.IndicesRequest;\nimport org.elasticsearch.action.support.IndicesOptions;\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.common.io.stream.StreamOutput;\n\nimport java.io.IOException;\n\npublic abstract class ESBroadcastTimeoutRequest<T extends ESBroadcastTimeoutRequest> extends BaseTimeoutRequest<T>\n                                               implements IndicesRequest.Replaceable {\n    protected String[]     indices;\n    private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpenAndForbidClosed();\n\n    protected ESBroadcastTimeoutRequest() {\n\n    }\n\n    protected ESBroadcastTimeoutRequest(ESActionRequest originalRequest) {\n        super(originalRequest);\n    }\n\n    protected ESBroadcastTimeoutRequest(String[] indices) {\n        this.indices = indices;\n    }\n\n    @Override\n    public String[] indices() {\n        return indices;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public final T indices(String... indices) {\n        this.indices = indices;\n        return (T) this;\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    @Override\n    public IndicesOptions indicesOptions() {\n        return indicesOptions;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public final T indicesOptions(IndicesOptions indicesOptions) {\n        this.indicesOptions = indicesOptions;\n        return (T) this;\n    }\n\n    @Override\n    public void writeTo(StreamOutput out) throws IOException {\n        super.writeTo(out);\n        out.writeStringArrayNullable(indices);\n        indicesOptions.writeIndicesOptions(out);\n    }\n\n    @Override\n    public void readFrom(StreamInput in) throws IOException {\n        super.readFrom(in);\n        indices = in.readStringArray();\n        indicesOptions = IndicesOptions.readIndicesOptions(in);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/ESBroadcastTimeoutRequestBuilder.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.action.ActionResponse;\nimport org.elasticsearch.action.support.IndicesOptions;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic abstract class ESBroadcastTimeoutRequestBuilder<Request extends ESBroadcastTimeoutRequest<Request>, Response extends ActionResponse, RequestBuilder extends ESBroadcastTimeoutRequestBuilder<Request, Response, RequestBuilder>>\n                                                      extends ActionRequestBuilder<Request, Response, RequestBuilder> {\n\n    protected ESBroadcastTimeoutRequestBuilder(ElasticsearchClient client,\n                                               Action<Request, Response, RequestBuilder> action, Request request) {\n        super(client, action, request);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public final RequestBuilder setIndices(String... indices) {\n        request.indices(indices);\n        return (RequestBuilder) this;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public final RequestBuilder setIndicesOptions(IndicesOptions indicesOptions) {\n        request.indicesOptions(indicesOptions);\n        return (RequestBuilder) this;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/ESNodeAction.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESNodeAction extends Action<ESNodeRequest, ESNodeResponse, ESNodeRequestBuilder> {\n\n    public static final ESNodeAction INSTANCE = new ESNodeAction();\n    public static final String       NAME     = \"cluster:nodes/tolerance\";\n\n    private ESNodeAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESNodeResponse newResponse() {\n        return new ESNodeResponse();\n    }\n\n    @Override\n    public ESNodeRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESNodeRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/ESNodeRequest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestResponse;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class ESNodeRequest extends BaseTimeoutRequest<ESNodeRequest> {\n    private String      nodeIds;\n    private Set<String> flags = new HashSet<>();\n\n    public ESNodeRequest clear() {\n        flags.clear();\n        return this;\n    }\n\n    public ESNodeRequest flag(String name) {\n        flags.add(name);\n        return this;\n    }\n\n    public ESNodeRequest nodeIds(String nodeIds) {\n        this.nodeIds = nodeIds;\n        return this;\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = buildEndPoint();\n        RestRequest restRequest = new RestRequest(\"GET\", endpoint, null);\n        //加上超时时间\n        restRequest.getParams().put(\"timeout\", timeout);\n        return restRequest;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        JSONObject obj = JSON.parseObject(respStr);\n        Object nodes = obj.remove(\"_nodes\");\n        ESNodeResponse esNodeResponse = JSON.parseObject(obj.toJSONString(), ESNodeResponse.class);\n        if (null != nodes) {\n            esNodeResponse.setFailedNodes(((JSONObject) nodes).getInteger(\"failed\"));\n        }\n        return JSON.parseObject(obj.toJSONString(), ESNodeResponse.class);\n    }\n\n    private String buildEndPoint() {\n        String flagStr = flags.size() < 10 ? StringUtils.join(flags, \",\").trim() : null;\n        String nodeUrl = null == nodeIds ? \"_nodes\" : String.format(\"_nodes/%s\", nodeIds);\n        String finalUrl = null == flagStr ? nodeUrl : nodeUrl + \"/\" + flagStr;\n        return finalUrl;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/ESNodeRequestBuilder.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESNodeRequestBuilder extends ActionRequestBuilder<ESNodeRequest, ESNodeResponse, ESNodeRequestBuilder> {\n\n    public ESNodeRequestBuilder(ElasticsearchClient client, ESNodeAction action) {\n        super(client, action, new ESNodeRequest());\n    }\n\n    public ESNodeRequestBuilder clearFlag() {\n        request.clear();\n        return this;\n    }\n\n    public ESNodeRequestBuilder nodeIds(String nodeIds) {\n        request.nodeIds(nodeIds);\n        return this;\n    }\n\n    public ESNodeRequestBuilder addFlag(String flagName) {\n        request.flag(flagName);\n        return this;\n    }\n\n    public ESNodeRequestBuilder timeout(String timeout) {\n        request.timeout(timeout);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/ESNodeResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodes.ClusterNodeInfo;\n\nimport java.util.Map;\n\npublic class ESNodeResponse extends ESActionResponse {\n    @JSONField(name = \"cluster_name\")\n    private String                       clusterName;\n\n    @JSONField(name = \"nodes\")\n    private Map<String, ClusterNodeInfo> nodes;\n\n    private int                          failedNodes;\n\n    public int getFailedNodes() {\n        return failedNodes;\n    }\n\n    public void setFailedNodes(int failedNodes) {\n        this.failedNodes = failedNodes;\n    }\n\n    public String getClusterName() {\n        return clusterName;\n    }\n\n    public void setClusterName(String clusterName) {\n        this.clusterName = clusterName;\n    }\n\n    public Map<String, ClusterNodeInfo> getNodes() {\n        return nodes;\n    }\n\n    public void setNodes(Map<String, ClusterNodeInfo> nodes) {\n        this.nodes = nodes;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        return (JSONObject) JSON.toJSON(this);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/ESNodeStatsAction.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESNodeStatsAction extends Action<ESNodeStatsRequest, ESNodeStatsResponse, ESNodeStatsRequestBuilder> {\n\n    public static final ESNodeStatsAction INSTANCE = new ESNodeStatsAction();\n    public static final String            NAME     = \"cluster:nodes/tolerance/stats\";\n\n    private ESNodeStatsAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESNodeStatsResponse newResponse() {\n        return new ESNodeStatsResponse();\n    }\n\n    @Override\n    public ESNodeStatsRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESNodeStatsRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/ESNodeStatsRequest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.model.RestResponse;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\nimport java.util.HashSet;\nimport java.util.Optional;\nimport java.util.Set;\n\npublic class ESNodeStatsRequest extends BaseTimeoutRequest<ESNodeStatsRequest> {\n\n    public static final String INDICES     = \"indices\";\n    public static final String OS          = \"os\";\n    public static final String PROCESS     = \"process\";\n    public static final String JVM         = \"jvm\";\n    public static final String THREAD_POOL = \"thread_pool\";\n    public static final String FS          = \"fs\";\n    public static final String TRANSPORT   = \"transport\";\n    public static final String HTTP        = \"http\";\n    public static final String BREAKERS    = \"breakers\";\n    public static final String SCRIPT      = \"script\";\n\n    private Set<String>        flags       = new HashSet<>();\n    private String[]           nodesIds    = null;\n    private String             level       = null;\n\n    public final ESNodeStatsRequest nodesIds(String... nodesIds) {\n        this.nodesIds = nodesIds;\n        return this;\n    }\n\n    public ESNodeStatsRequest level(String level) {\n        this.level = level;\n        return this;\n    }\n\n    @SuppressWarnings(\"all\")\n    public ESNodeStatsRequest all() {\n        flags.add(INDICES);\n        flags.add(OS);\n        flags.add(PROCESS);\n        flags.add(JVM);\n        flags.add(THREAD_POOL);\n        flags.add(FS);\n        flags.add(TRANSPORT);\n        flags.add(HTTP);\n        flags.add(BREAKERS);\n        flags.add(SCRIPT);\n        return this;\n    }\n\n    public ESNodeStatsRequest clear() {\n        flags.clear();\n        return this;\n    }\n\n    public ESNodeStatsRequest flag(String name, boolean isSet) {\n        Optional.ofNullable(isSet ? flags.add(name) : flags.remove(name));\n        return this;\n    }\n\n    public boolean isSet(String name) {\n        return flags.contains(name);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = buildEndPoint();\n        RestRequest restRequest = new RestRequest(\"GET\", endpoint, null);\n        //加上超时时间\n        restRequest.getParams().put(\"timeout\", timeout);\n        if (null != level) {\n            restRequest.getParams().put(\"level\", level);\n        }\n        return restRequest;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        JSONObject obj = JSON.parseObject(respStr);\n        Object nodes = obj.remove(\"_nodes\");\n        ESNodeStatsResponse nodesStatsResponse = JSON.parseObject(obj.toJSONString(), ESNodeStatsResponse.class);\n        if (null != nodes) {\n            nodesStatsResponse.setFailedNodes(((JSONObject) nodes).getInteger(\"failed\"));\n        }\n        return nodesStatsResponse;\n    }\n\n    private String buildEndPoint() {\n        String nodes = nodesIds != null ? StringUtils.join(nodesIds, \",\").trim() : null;\n        String flagStr = flags.size() < 10 ? StringUtils.join(flags, \",\").trim() : null;\n        String nodeStatUrl = null == nodes ? \"_nodes/stats\" : String.format(\"_nodes/%s/stats\", nodes);\n        String finalUrl = null == flagStr ? nodeStatUrl : nodeStatUrl + \"/\" + flagStr;\n        return finalUrl;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/ESNodeStatsRequestBuilder.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\nimport static com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node.ESNodeStatsRequest.*;\n\npublic class ESNodeStatsRequestBuilder extends\n                                       ActionRequestBuilder<ESNodeStatsRequest, ESNodeStatsResponse, ESNodeStatsRequestBuilder> {\n\n    public ESNodeStatsRequestBuilder(ElasticsearchClient client, ESNodeStatsAction action) {\n        super(client, action, new ESNodeStatsRequest());\n    }\n\n    public final ESNodeStatsRequestBuilder setNodesIds(String... nodesIds) {\n        request.nodesIds(nodesIds);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder all() {\n        request.all();\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder clear() {\n        request.clear();\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder level(String level) {\n        request.level(level);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder timeout(String timeout) {\n        request.timeout(timeout);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder setIndices(boolean indices) {\n        request.flag(INDICES, indices);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder setBreaker(boolean breaker) {\n        request.flag(BREAKERS, breaker);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder setScript(boolean script) {\n        request.flag(SCRIPT, script);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder setOs(boolean os) {\n        request.flag(OS, os);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder setProcess(boolean process) {\n        request.flag(PROCESS, process);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder setJvm(boolean jvm) {\n        request.flag(JVM, jvm);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder setThreadPool(boolean threadPool) {\n        request.flag(THREAD_POOL, threadPool);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder setFs(boolean fs) {\n        request.flag(FS, fs);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder setTransport(boolean transport) {\n        request.flag(TRANSPORT, transport);\n        return this;\n    }\n\n    public ESNodeStatsRequestBuilder setHttp(boolean http) {\n        request.flag(HTTP, http);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/cluster/monitor/esmonitorjob/node/ESNodeStatsResponse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.node;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didiglobal.knowframework.elasticsearch.client.model.ESActionResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\n\nimport java.util.Map;\n\npublic class ESNodeStatsResponse extends ESActionResponse {\n\n    @JSONField(name = \"cluster_name\")\n    private String                        clusterName;\n\n    @JSONField(name = \"nodes\")\n    private Map<String, ClusterNodeStats> nodes;\n\n    private int                           failedNodes;\n\n    public int getFailedNodes() {\n        return failedNodes;\n    }\n\n    public void setFailedNodes(int failedNodes) {\n        this.failedNodes = failedNodes;\n    }\n\n    public String getClusterName() {\n        return clusterName;\n    }\n\n    public void setClusterName(String clusterName) {\n        this.clusterName = clusterName;\n    }\n\n    public Map<String, ClusterNodeStats> getNodes() {\n        return nodes;\n    }\n\n    public void setNodes(Map<String, ClusterNodeStats> nodes) {\n        this.nodes = nodes;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        return (JSONObject) JSON.toJSON(this);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/dsl/DslTemplateDelExpiredJob.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.dsl.DslTemplateESDAO;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.AbstractMetaDataJob;\nimport org.elasticsearch.common.StopWatch;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.JOB_SUCCESS;\n\n/**\n * @Author: D10865\n * @Description: 删除过期查询模板数据的handler\n * @Date: Create on 2018/6/15 下午12:43\n * @Modified By\n * <p>\n */\n@Component\npublic class DslTemplateDelExpiredJob extends AbstractMetaDataJob {\n\n    /**\n     * 操作dsl template 索引\n     */\n    @Autowired\n    private DslTemplateESDAO dslTemplateEsDao;\n\n    /**\n     * 处理任务\n     *\n     * @param params\n     * @return\n     */\n    @Override\n    public Object handleJobTask(String params) {\n        LOGGER.info(\"class=DslTemplateDelExpiredJob||method=handleJobTask||params={}\", params);\n\n        StopWatch stopWatch = new StopWatch();\n        stopWatch.start(\"get not use dsl\");\n\n        List<DslTemplatePO> deleteDslTemplatePOList = dslTemplateEsDao.getExpiredAndWillDeleteDslTemplate();\n        boolean operatorDeleteResult = dslTemplateEsDao.deleteExpiredDslTemplate();\n\n        String cost = stopWatch.stop().toString();\n\n        LOGGER.info(\"class=DslTemplateDelExpiredJob||method=handleJobTask||size={}||result={}||cost={}\",\n            deleteDslTemplatePOList.size(), operatorDeleteResult, cost);\n\n        return JOB_SUCCESS;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/dsl/DslTemplateUpdateNearestQueryLimitJob.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.util.DateTimeUtil;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.AbstractMetaDataJob;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.dsl.DslTemplateESDAO;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.elasticsearch.common.StopWatch;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Objects;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.JOB_SUCCESS;\n\n/**\n * @author cjm\n * 计算最近一天生成的的DSL模版限流值大小\n * 根据：totalCostAvg（查询耗时）、totalShardsAvg（查询总shard个数）、totalHitsAvg（查询命中记录数）、responseLenAvg（查询响应长度）\n * 这四个指标的大小，获取权重信息，然后取权重信息平均值，再用默认查询限流值 * 该平均值\n */\n@Component\n@NoArgsConstructor\npublic class DslTemplateUpdateNearestQueryLimitJob extends AbstractMetaDataJob {\n\n    @Autowired\n    private DslTemplateESDAO dslTemplateESDAO;\n\n    /**\n     * 默认的查询限流值\n     */\n    @Value(\"${default.query.limit}\")\n    private Integer          defaultQueryLimit;\n\n    @Override\n    public Object handleJobTask(String params) {\n        LOGGER.info(\"class=DslTemplateUpdateNearestQueryLimitJob||method=handleJobTask||params={}\", params);\n\n        StopWatch stopWatch = new StopWatch();\n        stopWatch.start(\"set arius create time\");\n\n        // 获取到缺少ariusCreateTime字段的文档，手动设置该字段\n        List<DslTemplatePO> dslTemplates = dslTemplateESDAO.getMissingAriusCreateTme();\n\n        String ariusCreateTime = DateTimeUtil.getCurrentFormatDateTime();\n        for (DslTemplatePO dslTemplatePO : dslTemplates) {\n            dslTemplatePO.setAriusCreateTime(ariusCreateTime);\n            if (Objects.isNull(dslTemplatePO.getEnable())){\n                dslTemplatePO.setEnable(true);\n            }\n        }\n        boolean updateResult = dslTemplateESDAO.updateTemplates(dslTemplates);\n\n        stopWatch.stop().start(\"get near dsl template\");\n        // 获取一天内的查询模板信息\n        List<DslTemplatePO> dslTemplatePOList = dslTemplateESDAO.getNearestDslTemplate();\n\n        if (CollectionUtils.isEmpty(dslTemplatePOList)) {\n            LOGGER.info(\n                \"class=DslTemplateUpdateNearestQueryLimitJob||method=handleJobTask||msg=nearest dsl template is empty, cost {}\",\n                dslTemplatePOList.size(), stopWatch.stop().toString());\n            return JOB_SUCCESS;\n        }\n\n        stopWatch.stop().start(\"cal query limit and save\");\n        String ariusModifyTime = DateTimeUtil.getCurrentFormatDateTime();\n\n        Iterator<DslTemplatePO> iterator = dslTemplatePOList.iterator();\n        while (iterator.hasNext()) {\n            DslTemplatePO dslTemplatePO = iterator.next();\n            if (null == dslTemplatePO || null == dslTemplatePO.getTotalCostAvg()\n                || null == dslTemplatePO.getTotalShardsAvg() || null == dslTemplatePO.getTotalHitsAvg()\n                || null == dslTemplatePO.getResponseLenAvg()) {\n                continue;\n            }\n            //计算其限流值\n            double queryLimitValue = calQueryLimit(dslTemplatePO.getTotalCostAvg(), dslTemplatePO.getTotalShardsAvg(),\n                dslTemplatePO.getTotalHitsAvg(), dslTemplatePO.getResponseLenAvg());\n\n            if (dslTemplatePO.getQueryLimit() != null\n                && 0 == Double.compare(dslTemplatePO.getQueryLimit(), queryLimitValue)) {\n                // 如果查询限流值没发生变化，就不需要更新es\n                iterator.remove();\n            } else {\n                // 保留两位小数\n                queryLimitValue = (double) Math.round(queryLimitValue * 100) / 100;\n                dslTemplatePO.setQueryLimit(queryLimitValue);\n                dslTemplatePO.setAriusModifyTime(ariusModifyTime);\n            }\n        }\n\n        boolean operatorResult = dslTemplateESDAO.updateTemplates(dslTemplatePOList);\n\n        LOGGER.info(\n            \"class=DslTemplateUpdateNearestQueryLimitJob||method=handleJobTask||msg=set arius create time {}, result {}, update nearest dsl template {}, result {}, cost {}\",\n            dslTemplates.size(), updateResult, dslTemplatePOList.size(), operatorResult, stopWatch.stop().toString());\n        return JOB_SUCCESS;\n    }\n\n    /**\n     * 根据查询响应信息计算限流值\n     *\n     * @param totalCostAvg   查询耗时\n     * @param totalShardsAvg 查询总shard个数\n     * @param totalHitsAvg   查询命中记录数\n     * @param responseLenAvg 查询响应长度\n     * @return\n     */\n    private double calQueryLimit(double totalCostAvg, double totalShardsAvg, double totalHitsAvg,\n                                 double responseLenAvg) {\n        //计算查询耗时比重\n        double queryWeight = getQueryWeight(totalCostAvg);\n\n        //计算查询总shard数比重\n        double shardWeight;\n        if (totalShardsAvg < 10) {\n            shardWeight = 1.0;\n        } else if (totalShardsAvg < 50) {\n            shardWeight = 0.6;\n        } else if (totalShardsAvg < 100) {\n            shardWeight = 0.2;\n        } else {\n            shardWeight = 0.1;\n        }\n\n        //计算查询命令记录数比重\n        double hitsWeight;\n        if (totalHitsAvg < 100) {\n            hitsWeight = 1.0;\n        } else if (totalHitsAvg < 5000) {\n            hitsWeight = 0.6;\n        } else if (totalHitsAvg < 10000) {\n            hitsWeight = 0.2;\n        } else {\n            hitsWeight = 0.1;\n        }\n\n        //计算查询响应长度比重\n        double lengthWeight;\n        if (responseLenAvg < 1000) {\n            lengthWeight = 1.0;\n        } else if (responseLenAvg < 10000) {\n            lengthWeight = 0.6;\n        } else if (responseLenAvg < 50000) {\n            lengthWeight = 0.2;\n        } else {\n            lengthWeight = 0.1;\n        }\n\n        double avgWeight = (queryWeight + shardWeight + hitsWeight + lengthWeight) / 4.0;\n\n        return defaultQueryLimit * avgWeight;\n    }\n\n    private double getQueryWeight(double totalCostAvg) {\n        double queryWeight;\n        if (totalCostAvg < 100) {\n            queryWeight = 1.0;\n        } else if (totalCostAvg < 500) {\n            queryWeight = 0.6;\n        } else if (totalCostAvg < 1000) {\n            queryWeight = 0.2;\n        } else {\n            queryWeight = 0.1;\n        }\n        return queryWeight;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/IndexCatInfoCollector.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.JOB_SUCCESS;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexCatCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.shard.Segment;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.index.IndexCatCellPO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.TemplateUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexCatService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESShardService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.AbstractMetaDataJob;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Multimap;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author lyn\n * @date 2021/09/30\n **/\n@Component\npublic class IndexCatInfoCollector extends AbstractMetaDataJob {\n\n    private static final Integer        RETRY_TIMES                = 3;\n    private static final Integer         SEARCH_SIZE=5000;\n    @Autowired\n    private ClusterPhyService           clusterPhyService;\n\n    @Autowired\n    private ESShardService              esShardService;\n\n    @Autowired\n    private ESIndexService              esIndexService;\n\n    @Autowired\n    private ESIndexCatService           esIndexCatService;\n\n    @Autowired\n    private IndexTemplatePhyService     indexTemplatePhyService;\n\n    @Autowired\n    private ClusterLogicService         clusterLogicService;\n\n    //key: cluster@indexName  value: indexName\n    private final Cache<String, Object> notCollectorIndexNameCache = CacheBuilder.newBuilder()\n        .expireAfterWrite(60, TimeUnit.MINUTES).maximumSize(10000).build();\n\n    private static final FutureUtil<List<IndexCatCellPO>>    INDEX_CAT_INFO_COLLECTOR_FUTURE_UTIL  = FutureUtil\n            .init(\"IndexCatInfoCollectorFutureUtil\", 5, 5, 1000);\n\n    @Override\n    public Object handleJobTask(String params) {\n        long currentTimeMillis = System.currentTimeMillis();\n\n        List<ClusterPhy> clusterPhyList = clusterPhyService.listAllClusters();\n        if (CollectionUtils.isEmpty(clusterPhyList)) { return JOB_SUCCESS;}\n\n        List<String> clusterPhyNameList = clusterPhyList.stream().map(ClusterPhy::getCluster)\n            .collect(Collectors.toList());\n\n        // 1. 构建逻辑集群基础信息映射关系, 用于后面做基础数据构建\n        final Map<Long, String> logicClusterId2NameMap = Maps.newHashMap();\n        List<ClusterLogic> logicClusterList = clusterLogicService.listAllClusterLogics();\n        if (CollectionUtils.isNotEmpty(logicClusterList)) {\n            logicClusterId2NameMap.putAll(ConvertUtil.list2Map(logicClusterList, ClusterLogic::getId, ClusterLogic::getName));\n        }\n\n        // 2. 获取通过平台索引管理 创建的索引cat_index信息且没有生成索引健康的数据\n        List<IndexCatCell> platformCreateCatIndexList = esIndexCatService.syncGetPlatformCreateCatIndexList(SEARCH_SIZE);\n        //获取不到索引了就直接返回\n        if (CollectionUtils.isEmpty(platformCreateCatIndexList)) {\n            LOGGER.warn(\"class=IndexCatInfoCollector||method=getIndexInfoFromEs||platformCreateCatIndexList is empty\");\n        \n        }\n        // 这里的cluster 用户侧创建为逻辑集群名称，运维侧创建为物理集群名称\n        Map<String/*cluster@index*/, IndexCatCell> index2IndexCatCellFromPlatformCreateMap = ConvertUtil.list2Map(\n                platformCreateCatIndexList, IndexCatCell::getKey, r -> r);\n        Map<String, List<IndexCatCell>> clusterPhy2IndexCatCellListMap = ConvertUtil.list2MapOfList(platformCreateCatIndexList,\n                IndexCatCell::getCluster, i -> i);\n        // 3. 并发采集\n        for (String clusterName : clusterPhyNameList) {\n                INDEX_CAT_INFO_COLLECTOR_FUTURE_UTIL.callableTask(()-> {\n                    List<IndexCatCellPO> indexCatCells = Lists.newArrayList();\n                    try {\n                        // 0. 从es中获取数据\n                        List<CatIndexResult> catIndexResults = esIndexService.syncCatIndex(clusterName, RETRY_TIMES);\n                        if (CollectionUtils.isEmpty(catIndexResults)) {\n                            LOGGER.warn(\"class=IndexCatInfoCollector||method=getIndexInfoFromEs||clusterName={}||index empty\", clusterName);\n                            return indexCatCells;\n                        }\n\n                        long timeMillis = System.currentTimeMillis();\n\n                        // 1. 构建segment count 信息\n                        // 对于高版本集群（7以上），直接通过_cat/segments命令获取集群segments数据(默认跳过关闭索引)\n                        Map<String, Tuple<Long /*totalSegmentCount*/, Long /*primarySegmentCount*/>> indices2SegmentCountMap =\n                                getIndex2SegmentCountMap(clusterName);\n                        // 对于低版本集群（7以下），如果有索引关闭，则上面方法获取不到集群segment数据，要通过下面方法获取（相比来说较为麻烦，所以优先使用上面方法）\n                        if(indices2SegmentCountMap.isEmpty()){\n                            indices2SegmentCountMap = getLowVersionIndex2SegmentCountMap(clusterName);\n                        }\n\n                        // 2. 获取物理集群下所有逻辑模板\n                        List<IndexTemplatePhyWithLogic> indexTemplatePhyWithLogicList = indexTemplatePhyService.getTemplateByPhyCluster(clusterName);\n\n                        if (CollectionUtils.isEmpty(indexTemplatePhyWithLogicList)) {\n                            LOGGER.warn(\"class=IndexCatInfoCollector||method=getIndexCatInfo||clusterName={}||index template empty\",\n                                    clusterName);\n                        }\n\n                        Map<String/*templateName*/, IndexTemplatePhyWithLogic> templateName2IndexTemplatePhyWithLogicMap =\n                                ConvertUtil.list2Map(indexTemplatePhyWithLogicList, IndexTemplatePhyWithLogic::getName, r -> r);\n\n                        // 3.1 获取匹配平台模板的cat_index信息\n                        List<CatIndexResult> catIndexMatchAriusTemplateList = catIndexResults.stream()\n                                .filter(Objects::nonNull)\n                                .filter(r -> templateName2IndexTemplatePhyWithLogicMap.containsKey(r.getIndex())\n                                             || templateName2IndexTemplatePhyWithLogicMap.containsKey(\n                                        TemplateUtils.getMatchTemplateNameByIndexName(r.getIndex()))\n                                )\n                                .collect(Collectors.toList());\n\n                        // 3.2 根据模板信息构建Arius平台索引cat_index元数据信息\n                        List<IndexCatCellPO> ariusIndexCatCells = buildAriusIndexCatCells(catIndexMatchAriusTemplateList,\n                                logicClusterId2NameMap,\n                                indices2SegmentCountMap,\n                                templateName2IndexTemplatePhyWithLogicMap,\n                                clusterName,\n                                timeMillis);\n                        indexCatCells.addAll(ariusIndexCatCells);\n                        //3.3 获取平台侧中属于模板的索引，并进行过滤，找出已经删除的索引,然后并打标设置为已删除，否则会导致模板的索引删出不干净\n                        List<String> indexNameList = catIndexResults.stream().map(CatIndexResult::getIndex)\n                                .collect(Collectors.toList());\n                        \n                        List<IndexCatCell> ariusIndexDeleteCatCells = Optional.ofNullable(\n                                        clusterPhy2IndexCatCellListMap.get(clusterName)).orElse(Collections.emptyList())\n                                .stream()\n                                //匹配模板测的索引\n                                .filter(r -> templateName2IndexTemplatePhyWithLogicMap.containsKey(r.getIndex())\n                                             || templateName2IndexTemplatePhyWithLogicMap.containsKey(\n                                        TemplateUtils.getMatchTemplateNameByIndexName(r.getIndex())))\n                                //过滤出从catIndexResults中获取到索引，这里是真实索引，然后进行过滤，找出已经删除，但是平台侧没有及时更新的索引\n                                .filter(r -> !indexNameList.contains(r.getIndex()))\n                                //打标\n                                .peek(r -> r.setDeleteFlag(true))\n                                .collect(Collectors.toList());\n                        indexCatCells.addAll(ConvertUtil.list2List(ariusIndexDeleteCatCells, IndexCatCellPO.class));\n                        // 4.1 获取不匹配平台模板cat_index列表（通过索引管理创建，或者其他第三方客户端创建）\n                        List<CatIndexResult> catIndexMatchNativeTemplateList = catIndexResults.stream()\n                                .filter(r -> !catIndexMatchAriusTemplateList.contains(r))\n                                .collect(Collectors.toList());\n\n                        // 4.3 无需模板信息构建原生索引cat_index元数据信息\n                        List<IndexCatCellPO> nativeIndexCatCells = buildNativeIndexCatCells(catIndexMatchNativeTemplateList,\n                                indices2SegmentCountMap,\n                                index2IndexCatCellFromPlatformCreateMap,\n                                clusterName,\n                                timeMillis);\n                        indexCatCells.addAll(nativeIndexCatCells);\n                        // 4.4 从 indexCatCells 和索引管理下的索引集合进行比对，找到索引管理中不存在的索引，进行打标\n                        List<String> indexLists = indexCatCells.stream().map(IndexCatCellPO::getIndex).distinct()\n                                .collect(Collectors.toList());\n                        List<IndexCatCell> ariusNativeIndexDeleteCatCells = Optional.ofNullable(\n                                        clusterPhy2IndexCatCellListMap.get(clusterName)).orElse(Collections.emptyList())\n                                .stream()\n                                // 如果 index 不在 indexLists 中，则认为此索引是被第三方删除的，这个时候可以进行打标\n                                .filter(catIndexResult -> !indexLists.contains(catIndexResult.getIndex()))\n                                .peek(r -> r.setDeleteFlag(true)).collect(Collectors.toList());\n                        indexCatCells.addAll(\n                                ConvertUtil.list2List(ariusNativeIndexDeleteCatCells, IndexCatCellPO.class));\n                    } catch (Exception e) {\n                        Thread.currentThread().interrupt();\n                        LOGGER.error(\"class=IndexCatInfoCollector||method=handleJobTask||errMsg={}\", e.getMessage(), e);\n                    }\n\n                    return indexCatCells;\n                });\n        }\n\n        List<List<IndexCatCellPO>> lists = INDEX_CAT_INFO_COLLECTOR_FUTURE_UTIL.waitResult();\n        List<IndexCatCellDTO> res =  Lists.newArrayList();\n        for (List<IndexCatCellPO> list : lists) { res.addAll(ConvertUtil.list2List(list, IndexCatCellDTO.class));}\n\n        LOGGER.info(\"class=IndexCatInfoCollector||method=handleJobTask||timeOut={}\", System.currentTimeMillis() - currentTimeMillis);\n\n        //TODO: 部署多台admin，这里会出现过滤失败的问题\n        //移除已删除索引, 不采集\n        Function<Entry<String, List<IndexCatCellDTO>>, IndexCatCellDTO> filterOneIndexCatCellDTOFunc = key2indexCatCellDTOListEntry -> {\n            List<IndexCatCellDTO> indexCatCellDTOList = key2indexCatCellDTOListEntry.getValue();\n            // 如果是只有 1 个或者都是 deleteFlag=true 的时候，默认取第一个即可\n            if (indexCatCellDTOList.size() == 1 || indexCatCellDTOList.stream()\n                    .allMatch(IndexCatCellDTO::getDeleteFlag)) {\n                return indexCatCellDTOList.get(0);\n            }\n            // 否则找到为 false 的即可\n            return indexCatCellDTOList.stream().filter(i -> Boolean.FALSE.equals(i.getDeleteFlag())).findFirst().get();\n        \n        };\n    \n        List<IndexCatCellDTO> finalSaveIndexCatList = res.stream().filter(this::filterNotCollectorIndexCat)\n                // 过滤出重复的索引\n                // 根据 key group by 一次 目的为了找到重复的数据\n                .collect(Collectors.groupingBy(IndexCatCellDTO::getKey)).entrySet().stream()\n                .map(filterOneIndexCatCellDTOFunc).collect(Collectors.toList());\n                \n       \n        \n        \n        esIndexCatService.syncUpsertCatIndex(finalSaveIndexCatList, RETRY_TIMES);\n        return JOB_SUCCESS;\n    }\n\n    public void updateNotCollectorIndexNames(String cluster, List<String> notCollectorIndexNameList) {\n        for (String indexName : notCollectorIndexNameList) {\n            notCollectorIndexNameCache.put(cluster + \"@\" + indexName, indexName);\n        }\n    }\n\n    /**\n     * 构建与平台匹配的索引Cat_index信息\n     * @param catIndexMatchAriusTemplateList                匹配模板的CatIndex列表\n     * @param logicClusterId2NameMap                        logicClusterId2NameMap\n     * @param indices2SegmentCountMap                       indices2SegmentCountMap\n     * @param templateName2IndexTemplatePhyWithLogicMap     templateName2IndexTemplatePhyWithLogicMap\n     * @param clusterName\n     * @param timeMillis\n     * @return\n     */\n    private List<IndexCatCellPO> buildAriusIndexCatCells(List<CatIndexResult> catIndexMatchAriusTemplateList,\n                                                         Map<Long, String> logicClusterId2NameMap,\n                                                         Map<String, Tuple<Long /*totalSegmentCount*/, Long /*primarySegmentCount*/>> indices2SegmentCountMap,\n                                                         Map<String/*templateName*/, IndexTemplatePhyWithLogic> templateName2IndexTemplatePhyWithLogicMap,\n                                                         String clusterName,\n                                                         long timeMillis) {\n        List<IndexCatCellPO> res = Lists.newArrayList();\n        for (CatIndexResult catIndexResult : catIndexMatchAriusTemplateList) {\n            // 构建基础数据\n            IndexCatCellPO indexCatCellPO = buildBasicIndexCatCell(indices2SegmentCountMap, clusterName, timeMillis, catIndexResult);\n\n            // 根据索引名称获取平台模板名称, 匹配为null，则不去设置设置模板相关的属性\n            IndexTemplatePhyWithLogic indexTemplatePhyWithLogic = templateName2IndexTemplatePhyWithLogicMap.get(\n                    indexCatCellPO.getIndex());\n\n            if (Objects.isNull(indexTemplatePhyWithLogic)) {\n                String templateName = TemplateUtils.getMatchTemplateNameByIndexName(indexCatCellPO.getIndex());\n                if (StringUtils.isNotBlank(templateName)) {\n                    indexTemplatePhyWithLogic = templateName2IndexTemplatePhyWithLogicMap.get(templateName);\n                }\n\n            }\n            if (Objects.nonNull(indexTemplatePhyWithLogic)) {\n\n                IndexTemplate logicTemplate = indexTemplatePhyWithLogic.getLogicTemplate();\n                if (null != logicTemplate) {\n                    String clusterLogic = logicClusterId2NameMap.get(logicTemplate.getResourceId());\n                    indexCatCellPO.setClusterLogic(clusterLogic);\n                    indexCatCellPO.setResourceId(logicTemplate.getResourceId());\n                    indexCatCellPO.setTemplateId(logicTemplate.getId());\n                    indexCatCellPO.setProjectId(logicTemplate.getProjectId());\n                }\n            }\n            indexCatCellPO.setPlatformCreateFlag(false);\n            res.add(indexCatCellPO);\n\n        }\n        return res;\n    }\n\n    /**\n     * 构建原生索引Cat_index信息\n     * @param catIndexMatchNativeTemplateList\n     * @param indices2SegmentCountMap\n     * @param index2IndexCatCellFromPlatformCreateMap  平台创建索引Cat_index信息\n     * @param clusterName\n     * @param timeMillis\n     * @return                                    List<IndexCatCellPO>\n     */\n    private List<IndexCatCellPO> buildNativeIndexCatCells(List<CatIndexResult> catIndexMatchNativeTemplateList,\n                                                          Map<String, Tuple<Long /*totalSegmentCount*/, Long /*primarySegmentCount*/>>\n                                                                  indices2SegmentCountMap,\n                                                          Map<String/*cluster@index*/, IndexCatCell> index2IndexCatCellFromPlatformCreateMap,\n                                                          String clusterName,\n                                                          long timeMillis) {\n        List<IndexCatCellPO> res = Lists.newArrayList();\n\n        for (CatIndexResult catIndexResult : catIndexMatchNativeTemplateList) {\n            // 构建基础数据\n            IndexCatCellPO indexCatCellPO = buildBasicIndexCatCell(indices2SegmentCountMap, clusterName, timeMillis, catIndexResult);\n            // 索引管理所创建的索引需要构建以下平台相关信息（项目、物理集群、逻辑集群等）\n            if (index2IndexCatCellFromPlatformCreateMap.containsKey(indexCatCellPO.getKey())) {\n                IndexCatCell indexCatCell = index2IndexCatCellFromPlatformCreateMap.get(indexCatCellPO.getKey());\n                indexCatCellPO.setProjectId(indexCatCell.getProjectId());\n                indexCatCellPO.setCluster(indexCatCell.getCluster());\n                indexCatCellPO.setClusterLogic(indexCatCell.getClusterLogic());\n                indexCatCellPO.setResourceId(indexCatCell.getResourceId());\n                indexCatCellPO.setPlatformCreateFlag(true);\n            }\n\n            res.add(indexCatCellPO);\n        }\n        return res;\n    }\n\n    private Map<String, Tuple<Long /*totalSegmentCount*/, Long /*primarySegmentCount*/>> getIndex2SegmentCountMap(String clusterName) throws ESOperateException {\n        Map<String, Tuple<Long/*totalSegmentCount*/, Long/*primarySegmentCount*/>> index2SegmentCountMap = Maps.newHashMap();\n\n        List<Segment> segments = esShardService.syncGetSegmentsCountInfo(clusterName);\n        if (CollectionUtils.isEmpty(segments)) { return index2SegmentCountMap;}\n\n        // 1. 分组统计 key: indexName@p or indexName@r, value: list\n        Multimap<String, Segment> index2SegmentMultimap = ConvertUtil.list2MulMap(segments,\n                r -> r.getIndex() + \"@\" + r.getPrimaryFlag(), Segment -> Segment);\n\n        // 2.构建各个Index 的segment tuple\n        List<String> indexNamesFromSegments = segments.stream().map(Segment::getIndex).distinct().collect(Collectors.toList());\n        for (String indexNameFromSegment : indexNamesFromSegments) {\n            Tuple<Long, Long> totalSegmentCount2PrimarySegmentCountTuple = new Tuple<>();\n            int primarySegmentCount = index2SegmentMultimap.get(indexNameFromSegment + \"@\" + \"p\").size();\n            int replicaSegmentCount = index2SegmentMultimap.get(indexNameFromSegment + \"@\" + \"r\").size();\n            totalSegmentCount2PrimarySegmentCountTuple.setV1((long) (replicaSegmentCount + primarySegmentCount));\n            totalSegmentCount2PrimarySegmentCountTuple.setV2((long)primarySegmentCount);\n\n            index2SegmentCountMap.put(indexNameFromSegment, totalSegmentCount2PrimarySegmentCountTuple);\n        }\n\n        return index2SegmentCountMap;\n    }\n\n    /**\n     * 对于低版本集群（7以下），如果有索引关闭，则不能直接通过_cat/segments命令获取集群的segment数据，\n     * 要先把close的索引过滤掉，再对其他索引逐一获取segment信息\n     * @param clusterName\n     * @return\n     */\n    private  Map<String, Tuple<Long /*totalSegmentCount*/, Long /*primarySegmentCount*/>> getLowVersionIndex2SegmentCountMap(String clusterName){\n        Map<String, Tuple<Long/*totalSegmentCount*/, Long/*primarySegmentCount*/>> lowVersionIndex2SegmentCountMap = Maps.newHashMap();\n\n        // 获取集群的索引列表\n        List<CatIndexResult> catIndices = esIndexService.syncCatIndex(clusterName, 3);\n        // 过滤掉close状态的索引\n        List<String> openIndexNameList = catIndices.stream().filter(index -> index.getStatus().equals(\"open\"))\n                .map(CatIndexResult::getIndex).collect(Collectors.toList());\n        // 获取含segments信息的索引\n        Result<List<IndexCatCellDTO>> result = esIndexCatService.syncGetSegmentsIndexList(clusterName, openIndexNameList);\n        if (result.failed()) {\n            LOGGER.warn(\"class=IndexCatInfoCollector||method=getLowVersionIndex2SegmentCountMap||cluster={}||msg={}\",\n                    clusterName, result.getMessage());\n            return lowVersionIndex2SegmentCountMap;\n        }\n        List<IndexCatCellDTO> indexCatCellList = result.getData();\n        for (IndexCatCellDTO index : indexCatCellList) {\n            Tuple<Long, Long> totalSegmentCount2PrimarySegmentCountTuple = new Tuple<>();\n            totalSegmentCount2PrimarySegmentCountTuple.setV1(index.getTotalSegmentCount());\n            totalSegmentCount2PrimarySegmentCountTuple.setV2(index.getPrimariesSegmentCount());\n\n            lowVersionIndex2SegmentCountMap.put(index.getIndex(), totalSegmentCount2PrimarySegmentCountTuple);\n        }\n\n        return lowVersionIndex2SegmentCountMap;\n    }\n\n    /**\n     * 构建基础数据\n     * @param indices2SegmentCountMap\n     * @param clusterName\n     * @param timeMillis\n     * @param catIndexResult\n     */\n    private IndexCatCellPO buildBasicIndexCatCell(\n                                        Map<String, Tuple<Long, Long>> indices2SegmentCountMap,\n                                        String clusterName,\n                                        long timeMillis,\n                                        CatIndexResult catIndexResult) {\n        IndexCatCellPO builder = ConvertUtil.obj2Obj(catIndexResult, IndexCatCellPO.class);\n        builder.setPri(Long.valueOf(null != catIndexResult.getPri() ? catIndexResult.getPri() : \"0\"));\n        builder.setRep(Long.valueOf(null != catIndexResult.getRep() ? catIndexResult.getRep() : \"0\"));\n        builder.setDocsCount(Long.valueOf(null != catIndexResult.getDocsCount() ? catIndexResult.getDocsCount() : \"0\"));\n        builder.setDocsDeleted(Long.valueOf(null != catIndexResult.getDocsDeleted() ? catIndexResult.getDocsDeleted() : \"0\"));\n\n        Optional.ofNullable(indices2SegmentCountMap).map(map -> map.get(catIndexResult.getIndex())).ifPresent(tuple -> {\n            builder.setTotalSegmentCount(tuple.v1());\n            builder.setPrimariesSegmentCount(tuple.v2());\n        });\n        builder.setCluster(clusterName);\n        builder.setDeleteFlag(false);\n        builder.setTimestamp(timeMillis);\n\n        return builder;\n    }\n\n    private boolean filterNotCollectorIndexCat(IndexCatCellDTO indexCatCellDTO) {\n        return indexCatCellDTO.getDeleteFlag().equals(Boolean.FALSE) || notCollectorIndexNameCache.getIfPresent(indexCatCellDTO.getKey()) == null;\n    }\n\n    private void sleep(Long millis) {\n        try {\n            Thread.sleep(millis);\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/healthdegree/AbstractDegreeIndicator.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.IndicatorsType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.BaseDegree;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndicatorChild;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.degreeindicator.DegreeParam;\nimport com.didichuxing.datachannel.arius.admin.metadata.utils.ReadExprValueUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\npublic abstract class AbstractDegreeIndicator implements IDegreeIndicator {\n    protected static final ILog LOGGER = LogFactory.getLog(AbstractDegreeIndicator.class);\n\n    private DegreeParam         degreeParam;\n\n    protected AbstractDegreeIndicator() {\n    }\n\n    @Override\n    public <T extends BaseDegree> T exec(DegreeParam degreeParam) {\n        this.degreeParam = degreeParam;\n\n        T baseRealTimePO = getRealTimePO();\n        baseRealTimePO.setIndicatorsType(getType());\n        baseRealTimePO.setWeight(getType().getWeight());\n        baseRealTimePO.setWeightRate(IndicatorsType.getWeightRate(getType()));\n\n        if (isZero()) {\n            baseRealTimePO.setPunishment(\"*0%\");\n            baseRealTimePO.setWeightScore(0d);\n            baseRealTimePO.setScore(0d);\n            baseRealTimePO.setDesc(\"索引文档数为0, \" + getType().getName() + \"得分为0!\");\n        } else {\n            try {\n                baseRealTimePO = execInner(degreeParam, baseRealTimePO);\n                baseRealTimePO.setWeightScore(baseRealTimePO.getScore() * baseRealTimePO.getWeightRate());\n            } catch (Exception e) {\n                LOGGER.info(\"class=AbstractDegreeIndicator||method=exec||index={}||type={}\",\n                    degreeParam.getIndexTemplate().getName(), getType().getName(), e);\n            }\n        }\n\n        LOGGER.debug(\"class=AbstractDegreeIndicator||method=exec||index={}||type={}||score={}||weightScore=={}\",\n                degreeParam.getIndexTemplate().getName(), getType().getName(), baseRealTimePO.getScore(),\n                baseRealTimePO.getWeightScore());\n\n\n        return baseRealTimePO;\n    }\n\n    public abstract <T extends BaseDegree> T execInner(DegreeParam degreeParam, T t);\n\n    protected boolean isZero() {\n        return degreeParam.getTemplateDocNu() == 0;\n    }\n\n    protected double calc(double ratio) {\n        double score = 0.0;\n\n        for (IndicatorChild indicatorChildPO : degreeParam.getIndicatorChilds()) {\n            if (getType().getCode() != indicatorChildPO.getCode()) {\n                continue;\n            }\n\n            if (indicatorChildPO.getUpper() <= Math.floor(ratio)\n                && (indicatorChildPO.getLower() == -1 || indicatorChildPO.getLower() >= Math.floor(ratio))) {\n                String expr = indicatorChildPO.getScoreExpr().replace(\"k\", \"\" + ratio);\n                double value = ReadExprValueUtil.readExprValue(expr);\n\n                if (value > 100) {\n                    value = 100;\n                }\n\n                score = Math.floor(value * 100) / 100;\n                break;\n            }\n        }\n\n        return score;\n    }\n\n    protected double calc1(double ratio) {\n        double score = 0.0;\n\n        for (IndicatorChild indicatorChildPO : degreeParam.getIndicatorChilds()) {\n            if (getType().getCode() != indicatorChildPO.getCode()) {\n                continue;\n            }\n\n            if (indicatorChildPO.getUpper() <= Math.floor(ratio)\n                && (indicatorChildPO.getLower() == -1 || indicatorChildPO.getLower() >= Math.floor(ratio))) {\n                String expr = indicatorChildPO.getScoreExpr();\n                score = ReadExprValueUtil.readExprValue(expr);\n\n                if (score > 100) {\n                    score = 100;\n                }\n\n                break;\n            }\n        }\n\n        return score;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/healthdegree/IDegreeIndicator.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.IndicatorsType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.BaseDegree;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.degreeindicator.DegreeParam;\n\npublic interface IDegreeIndicator {\n    public IndicatorsType getType();\n\n    public <T extends BaseDegree> T getRealTimePO();\n\n    public <T extends BaseDegree> T exec(DegreeParam degreeParam);\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/healthdegree/degreeindicator/DegreeOffline.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.degreeindicator;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.BaseDegree;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.OffLine;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateLogicWithClusterAndMasterTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.constant.IndicatorsType;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.AbstractDegreeIndicator;\nimport com.didichuxing.datachannel.arius.admin.metadata.utils.ReadExprValueUtil;\n\n@Deprecated\npublic class DegreeOffline extends AbstractDegreeIndicator {\n    private static final Long GB_IN_BYTE = 1024 * 1024 * 1024L;\n\n    @Override\n    public <T extends BaseDegree> T execInner(DegreeParam degreeParam, T t) {\n        OffLine offLinePO = (OffLine) t;\n\n        IndexTemplateLogicWithClusterAndMasterTemplate indexTemplate = degreeParam.getIndexTemplate();\n        long templateAccessCount = degreeParam.getTemplateAccessCount();\n\n        offLinePO.setCluster(indexTemplate.getMasterTemplate().getCluster());\n        offLinePO.setTemplate(indexTemplate.getName());\n        offLinePO.setTemplateId(indexTemplate.getId());\n        offLinePO.setZeroCount(0 == degreeParam.getTemplateDocNu());\n        offLinePO.setCostByGb(degreeParam.getTemplateSizeInBytes() / GB_IN_BYTE);\n        offLinePO.setYesterdayAccessNum(templateAccessCount);\n\n        if (offLinePO.getCostByGb() > 0) {\n            offLinePO.setSingleGbAccess(ReadExprValueUtil.getDouble2(templateAccessCount / offLinePO.getCostByGb()));\n        }\n\n        //开始计算离线健康分\n        computeOfflineScore(offLinePO, templateAccessCount);\n\n        return (T) offLinePO;\n    }\n\n    private void computeOfflineScore(OffLine offLinePO, long templateAccessCount) {\n        StringBuilder offlineDesc = new StringBuilder();\n        double offLineScore = 0.0;\n        double singleGbAccess = offLinePO.getSingleGbAccess();\n\n        if (!offLinePO.isZeroCount()) {\n            if (singleGbAccess > 1) {\n                offLineScore = Math.log(singleGbAccess) / Math.log(2.0) * 10;\n                offlineDesc.append(\"Math.log(\").append(singleGbAccess).append(\")/Math.log(2.0)*10\");\n            } else {\n                offLineScore = singleGbAccess * 10;\n                offlineDesc.append(singleGbAccess).append(\"*10\");\n            }\n\n            // 按访问次数调整(仅对分数低于60分的)\n            offLineScore = adjustByAccessCount(templateAccessCount, offlineDesc, offLineScore);\n\n            // 最高分为100分\n            if (offLineScore > 100) {\n                offLineScore = 100;\n                String temp = offlineDesc.toString();\n                offlineDesc.delete(0, offlineDesc.length());\n                offlineDesc.append(\"Math.min(\").append(temp).append(\"),100)\");\n            }\n        }\n\n        offLinePO.setProcess(offlineDesc.toString());\n        offLinePO.setScore(Math.floor(offLineScore));\n        offLinePO.setPunishment(null);\n    }\n\n    private double adjustByAccessCount(long templateAccessCount, StringBuilder offlineDesc, double offLineScore) {\n        if (offLineScore < 60) {\n            int addScore = 0;\n\n            if (templateAccessCount >= 1000000) {\n                addScore = 30;\n            } else if (1000000 > templateAccessCount && templateAccessCount >= 100000) {\n                addScore = 20;\n            } else if (100000 > templateAccessCount && templateAccessCount >= 10000) {\n                addScore = 10;\n            }\n\n            if (addScore > 0) {\n                offLineScore += addScore;\n                offlineDesc.append(\" (+\").append(addScore).append(\")\");\n            }\n        }\n        return offLineScore;\n    }\n\n    @Override\n    public IndicatorsType getType() {\n        return IndicatorsType.BASE_OF_HEALTH_DEGREES;\n    }\n\n    @Override\n    public OffLine getRealTimePO() {\n        return new OffLine();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/healthdegree/degreeindicator/DegreeParam.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.degreeindicator;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexRealTimeInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndicatorChild;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexToNodeStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateLogicWithClusterAndMasterTemplate;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class DegreeParam {\n    IndexTemplateLogicWithClusterAndMasterTemplate indexTemplate;\n\n    long                                           templateDocNu;\n\n    double                                         templateSizeInBytes;\n\n    long                                           templateAccessCount;\n\n    IndexRealTimeInfo                              todayReaTimelInfo;\n\n    IndexRealTimeInfo                              yesdayReaTimelInfo;\n\n    List<ESIndexToNodeStats>                       esIndexToNodeStats;\n\n    List<IndicatorChild>                           indicatorChilds;\n\n    @Override\n    public String toString() {\n        return \"DegreeParam\" + \": template=\" + indexTemplate.getName() + \": templateDocNu=\" + templateDocNu\n               + \": templateSizeInBytes=\" + templateSizeInBytes + \": templateAccessCount=\" + templateAccessCount\n               + \": todayReaTimelInfo=\" + todayReaTimelInfo.toString() + \", yesdayReaTimelInfo=\"\n               + yesdayReaTimelInfo.toString() + \", esIndexToNodeStats=\" + JSON.toJSONString(esIndexToNodeStats);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/healthdegree/degreeindicator/DegreeRealTimeCpuUse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.degreeindicator;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.IndicatorsType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.BaseDegree;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.RealTimeCpuUse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexToNodeStats;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.AbstractDegreeIndicator;\nimport org.apache.commons.lang3.StringUtils;\n\n@Deprecated\npublic class DegreeRealTimeCpuUse extends AbstractDegreeIndicator {\n    @Override\n    public <T extends BaseDegree> T execInner(DegreeParam degreeParam, T t) {\n        double avgCpuUse;\n        double totalCpuUse = 0.0;\n        for (ESIndexToNodeStats esESIndexToNodeStats : degreeParam.getEsIndexToNodeStats()) {\n            if (StringUtils.isNotBlank(esESIndexToNodeStats.getMetrics().get(\"os-cpu-percent\"))) {\n                totalCpuUse += Double.parseDouble(esESIndexToNodeStats.getMetrics().get(\"os-cpu-percent\"));\n            }\n        }\n\n        RealTimeCpuUse realTimeCpuUsePO = (RealTimeCpuUse) t;\n\n        if (degreeParam.getEsIndexToNodeStats().size() == 0) {\n            realTimeCpuUsePO.setScore(100.0);\n            realTimeCpuUsePO.setDesc(\"暂无实时cpu使用率信息.\");\n        } else {\n            avgCpuUse = Math.floor(totalCpuUse / degreeParam.getEsIndexToNodeStats().size() * 100) / 100;\n            realTimeCpuUsePO.setAvgCpuAvgUse(avgCpuUse);\n            realTimeCpuUsePO.setScore(calc1(avgCpuUse));\n        }\n\n        return (T) realTimeCpuUsePO;\n    }\n\n    @Override\n    public IndicatorsType getType() {\n        return IndicatorsType.REAL_TIME_CPU_USE;\n    }\n\n    @Override\n    public RealTimeCpuUse getRealTimePO() {\n        return new RealTimeCpuUse();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/healthdegree/degreeindicator/DegreeRealTimeDiskUse.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.degreeindicator;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.IndicatorsType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.BaseDegree;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.RealTimeDiskUse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexToNodeStats;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.AbstractDegreeIndicator;\nimport org.apache.commons.lang3.StringUtils;\n\n@Deprecated\npublic class DegreeRealTimeDiskUse extends AbstractDegreeIndicator {\n    @Override\n    public <T extends BaseDegree> T execInner(DegreeParam degreeParam, T t) {\n        double avgDiskUse;\n        double totalDiskUse = 0.0;\n\n        for (ESIndexToNodeStats esESIndexToNodeStats : degreeParam.getEsIndexToNodeStats()) {\n            if (StringUtils.isNotBlank(esESIndexToNodeStats.getMetrics().get(\"fs-total-disk_free_percent\"))) {\n                totalDiskUse += (1 - Double\n                    .parseDouble(esESIndexToNodeStats.getMetrics().get(\"fs-total-disk_free_percent\")));\n            }\n        }\n\n        RealTimeDiskUse realTimeDiskUsePO = (RealTimeDiskUse) t;\n\n        if (degreeParam.getEsIndexToNodeStats().size() == 0) {\n            realTimeDiskUsePO.setScore(100.0);\n            realTimeDiskUsePO.setProcess(\"100*\" + realTimeDiskUsePO.getWeight() + \"%\");\n            realTimeDiskUsePO.setDesc(\"暂无实时磁使用率信息.\");\n        } else {\n            // 保留两位小数\n            avgDiskUse = Math.floor(totalDiskUse * 10000 / degreeParam.getEsIndexToNodeStats().size()) / 100;\n            realTimeDiskUsePO.setAvgDiskUse(avgDiskUse);\n            realTimeDiskUsePO.setScore(calc1(avgDiskUse));\n        }\n\n        return (T) realTimeDiskUsePO;\n    }\n\n    @Override\n    public IndicatorsType getType() {\n        return IndicatorsType.REAL_TIME_DISK_RATE;\n    }\n\n    @Override\n    public RealTimeDiskUse getRealTimePO() {\n        return new RealTimeDiskUse();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/healthdegree/degreeindicator/DegreeRealTimeOldGC.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.degreeindicator;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.IndicatorsType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.BaseDegree;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.RealTimeOldGC;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexToNodeStats;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.AbstractDegreeIndicator;\nimport org.apache.commons.lang3.StringUtils;\n\n@Deprecated\npublic class DegreeRealTimeOldGC extends AbstractDegreeIndicator {\n    @Override\n    public <T extends BaseDegree> T execInner(DegreeParam degreeParam, T t) {\n        double gcCount = 0;\n        for (ESIndexToNodeStats esESIndexToNodeStats : degreeParam.getEsIndexToNodeStats()) {\n            if (StringUtils.isNotBlank(esESIndexToNodeStats.getMetrics().get(\"jvm-gc-old-collection_count\"))) {\n                gcCount += Math.floor(\n                    Double.parseDouble(esESIndexToNodeStats.getMetrics().get(\"jvm-gc-old-collection_count\")) * 100)\n                           / 100;\n            }\n        }\n\n        RealTimeOldGC realTimeOldGCPO = (RealTimeOldGC) t;\n\n        realTimeOldGCPO.setAvgJvmOldGc(gcCount);\n        realTimeOldGCPO.setScore(calc1(gcCount));\n        return (T) realTimeOldGCPO;\n    }\n\n    @Override\n    public IndicatorsType getType() {\n        return IndicatorsType.REAL_TIME_JVM;\n    }\n\n    @Override\n    public RealTimeOldGC getRealTimePO() {\n        return new RealTimeOldGC();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/healthdegree/degreeindicator/DegreeRealTimeSearch.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.degreeindicator;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.IndicatorsType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.BaseDegree;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.RealTimeSearch;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.AbstractDegreeIndicator;\n\n@Deprecated\npublic class DegreeRealTimeSearch extends AbstractDegreeIndicator {\n    @Override\n    public IndicatorsType getType() {\n        return IndicatorsType.REAL_TIME_SEARCH;\n    }\n\n    @Override\n    public RealTimeSearch getRealTimePO() {\n        return new RealTimeSearch();\n    }\n\n    @Override\n    public <T extends BaseDegree> T execInner(DegreeParam degreeParam, T t) {\n        double todaySearchRate = Math.floor(degreeParam.getTodayReaTimelInfo().getAvgSearchQueryTotalRate() * 10000)\n                                 / 10000;\n        double yesdaySearchRate = Math.floor(degreeParam.getYesdayReaTimelInfo().getAvgSearchQueryTotalRate() * 10000)\n                                  / 10000;\n\n        RealTimeSearch realTimeSearchPO = (RealTimeSearch) t;\n\n        realTimeSearchPO.setAvgSearchRate(todaySearchRate);\n        realTimeSearchPO.setYesterdayAvgSearchRate(yesdaySearchRate);\n\n        StringBuilder descBuild = new StringBuilder();\n        descBuild.append(\"当前实时查询率为:\").append(todaySearchRate).append(\"次/s\");\n        descBuild.append(\" ,历史查询率为:\").append(yesdaySearchRate).append(\"次/s\");\n        realTimeSearchPO.setDesc(descBuild.toString());\n\n        double score = (yesdaySearchRate <= 0) ? 100 : calc(todaySearchRate / yesdaySearchRate);\n\n        realTimeSearchPO.setScore(score);\n\n        StringBuilder processBuild = new StringBuilder();\n        processBuild.append(score).append(\"*\").append(realTimeSearchPO.getWeightRate()).append(\"%\");\n        realTimeSearchPO.setProcess(processBuild.toString());\n\n        return (T) realTimeSearchPO;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/healthdegree/degreeindicator/DegreeRealTimeWriter.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.degreeindicator;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.IndicatorsType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.BaseDegree;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.RealTimeWrite;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.AbstractDegreeIndicator;\n\n@Deprecated\npublic class DegreeRealTimeWriter extends AbstractDegreeIndicator {\n    @Override\n    public IndicatorsType getType() {\n        return IndicatorsType.REAL_TIME_WRITE;\n    }\n\n    @Override\n    public RealTimeWrite getRealTimePO() {\n        return new RealTimeWrite();\n    }\n\n    @Override\n    public <T extends BaseDegree> T execInner(DegreeParam degreeParam, T t) {\n        double todayIndexRate = Math.floor(degreeParam.getTodayReaTimelInfo().getAvgIndexingIndexTotalRate() * 10000)\n                                / 10000;\n        double yesdayIndexRate = Math.floor(degreeParam.getYesdayReaTimelInfo().getAvgIndexingIndexTotalRate() * 10000)\n                                 / 10000;\n\n        RealTimeWrite realTimeWritePO = (RealTimeWrite) t;\n\n        realTimeWritePO.setAvgIndexingRate(todayIndexRate);\n        realTimeWritePO.setYesterdayAvgIndexingRate(yesdayIndexRate);\n\n        StringBuilder descBuild = new StringBuilder();\n        descBuild.append(\"实时写入率为:\").append(todayIndexRate).append(\"条/s\");\n        descBuild.append(\" ,历史写入率为:\").append(yesdayIndexRate).append(\"条/s\");\n        realTimeWritePO.setDesc(descBuild.toString());\n\n        double score;\n\n        if (todayIndexRate <= 0) {\n            score = 0.0;\n        } else if (yesdayIndexRate <= 0) {\n            score = 100.0;\n        } else {\n            score = calc(todayIndexRate / yesdayIndexRate);\n        }\n\n        realTimeWritePO.setScore(score);\n\n        StringBuilder processBuild = new StringBuilder();\n        processBuild.append(score).append(\"*\").append(realTimeWritePO.getWeightRate()).append(\"%\");\n        realTimeWritePO.setProcess(processBuild.toString());\n\n        return (T) realTimeWritePO;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/index/healthdegree/degreeindicator/DegreeSearchCost.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.degreeindicator;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.IndicatorsType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.BaseDegree;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.RealTimeSearchCost;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.healthdegree.AbstractDegreeIndicator;\n\n@Deprecated\npublic class DegreeSearchCost extends AbstractDegreeIndicator {\n    @Override\n    public <T extends BaseDegree> T execInner(DegreeParam degreeParam, T t) {\n        double searchCostTime = Math.floor(degreeParam.getTodayReaTimelInfo().getAvgIndicesSearchQueryTime() * 10000)\n                                / 10000;\n\n        RealTimeSearchCost realTimeSearchCostPO = (RealTimeSearchCost) t;\n\n        realTimeSearchCostPO.setAvgSearchCostTime(searchCostTime);\n\n        double score;\n\n        if (searchCostTime <= 0) {\n            score = 100.0;\n            realTimeSearchCostPO.setDesc(\"近期无查询,无查询时长信息.\");\n        } else {\n            score = calc(searchCostTime);\n        }\n\n        realTimeSearchCostPO.setScore(score);\n        return (T) realTimeSearchCostPO;\n    }\n\n    @Override\n    public IndicatorsType getType() {\n        return IndicatorsType.REAL_TIME_SEARCH_COST;\n    }\n\n    @Override\n    public RealTimeSearchCost getRealTimePO() {\n        return new RealTimeSearchCost();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/job/shard/ShardCatInfoCollector.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.job.shard;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.shard.ShardCatCellPO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.BatchProcessor;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESShardCatService;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.AbstractMetaDataJob;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESShardDAO;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.JOB_SUCCESS;\n\n/**\n * @author lyn\n * @date 2021/09/30\n **/\n@Component\npublic class ShardCatInfoCollector extends AbstractMetaDataJob {\n\n    private static final Integer RETRY_TIMES = 3;\n    @Autowired\n    private ClusterPhyService clusterPhyService;\n\n    @Autowired\n    private ESShardCatService esShardCatService;\n\n\n    @Autowired\n    private ClusterLogicService clusterLogicService;\n\n    @Autowired\n    private ESShardDAO esShardDAO;\n\n    //key: cluster@indexName  value: indexName\n    private final Cache<String, Object> notCollectorIndexNameCache = CacheBuilder.newBuilder()\n            .expireAfterWrite(60, TimeUnit.MINUTES).maximumSize(10000).build();\n    private Map<Long, String>     logicClusterId2NameMap     = Maps.newConcurrentMap();\n\n    private void initLogicClusterId2NameMap() {\n        List<ClusterLogic> logicClusterList = clusterLogicService.listAllClusterLogics();\n        if (CollectionUtils.isNotEmpty(logicClusterList)) {\n            logicClusterId2NameMap = logicClusterList.stream()\n                    .collect(Collectors.toConcurrentMap(ClusterLogic::getId, ClusterLogic::getName, (o1, o2) -> o1));\n        }\n    }\n\n    @Override\n    public Object handleJobTask(String params) {\n\n        List<ShardCatCellPO> shardCatCellList     =   Lists.newArrayList();\n        List<ClusterPhy>     clusterPhyList       =   clusterPhyService.listAllClusters();\n        List<String>         clusterPhyNameList   =   clusterPhyList.stream().map(ClusterPhy::getCluster).collect(Collectors.toList());\n\n        if (CollectionUtils.isEmpty(clusterPhyNameList)) {\n            return JOB_SUCCESS;\n        }\n        initLogicClusterId2NameMap();\n\n        long currentTimeMillis = System.currentTimeMillis();\n        BatchProcessor.BatchProcessResult<String, List<ShardCatCellPO>> batchResult\n                = new BatchProcessor<String, List<ShardCatCellPO>>()\n                .batchList(clusterPhyNameList)\n                .processor(this::getShardInfoFromEs)\n                .process();\n        LOGGER.info(\"class=IndexCatInfoCollector||method=handleJobTask||timeOut={}\", System.currentTimeMillis() - currentTimeMillis);\n\n        if (!batchResult.isSucc() && (batchResult.getErrorMap().size() > 0)) {\n            LOGGER.warn(\n                    \"class=IndexCatInfoCollector||method=handleJobTask||clusterList={}||errMsg=batch result error:{}\",\n                    ListUtils.strList2String(clusterPhyNameList), batchResult.getErrorMap());\n        }\n        List<List<ShardCatCellPO>> resultList = batchResult.getResultList();\n        for (List<ShardCatCellPO> shardCatCellPOS : resultList) {\n            shardCatCellList.addAll(shardCatCellPOS);\n        }\n        esShardCatService.syncInsertCatShard(shardCatCellList,RETRY_TIMES);\n        return JOB_SUCCESS;\n    }\n\n    public List<ShardCatCellPO> getShardInfoFromEs(List<String> clusterNameList){\n        List<ShardCatCellPO> catShardCellList = Lists.newArrayList();\n        for (String clusterName : clusterNameList) {\n            List<ShardCatCellPO> shardCatCells = null;\n            try {\n                shardCatCells = getShardCatCells(clusterName);\n            } catch (ESOperateException e) {\n                LOGGER.error(\n                        \"class=IndexCatInfoCollector||method=getShardInfoFromEs||clusterList={}||errMsg=batch result error:{}\",\n                        ListUtils.strList2String(clusterNameList), e.getMessage());\n                throw new RuntimeException(e);\n            }\n            if (null != shardCatCells && !shardCatCells.isEmpty()) {\n                catShardCellList.addAll(shardCatCells);\n            }\n        }\n        return catShardCellList;\n    }\n\n    private List<ShardCatCellPO> getShardCatCells(String clusterName) throws ESOperateException {\n        long currentTimeMillis = System.currentTimeMillis();\n        List<ShardCatCellPO> shardDistributionVOS = esShardCatService.syncShardDistribution(clusterName,currentTimeMillis);\n        return shardDistributionVOS;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/listen/MetaDataMonitorMetrics2PrometheusListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.listen;\n\nimport com.didichuxing.datachannel.arius.admin.common.event.metrics.*;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Service;\n\n/**\n * to Prometheus\n */\n@Service\npublic class MetaDataMonitorMetrics2PrometheusListener implements ApplicationListener<MetaDataMetricsEvent> {\n\n    @Override\n    public void onApplicationEvent(MetaDataMetricsEvent event) {\n        if (event instanceof MetricsMonitorClusterEvent) {\n            MetricsMonitorClusterEvent monitorClusterEvent = (MetricsMonitorClusterEvent) event;\n            sendMetrics(monitorClusterEvent);\n        }\n\n        if (event instanceof MetricsMonitorCollectTimeEvent) {\n            MetricsMonitorCollectTimeEvent collectTimeEvent = (MetricsMonitorCollectTimeEvent) event;\n            sendMetrics(collectTimeEvent);\n        }\n\n        if (event instanceof MetricsMonitorIndexEvent) {\n            MetricsMonitorIndexEvent monitorIndexEvent = (MetricsMonitorIndexEvent) event;\n            sendMetrics(monitorIndexEvent);\n        }\n\n        if (event instanceof MetricsMonitorNodeEvent) {\n            MetricsMonitorNodeEvent monitorNodeEvent = (MetricsMonitorNodeEvent) event;\n            sendMetrics(monitorNodeEvent);\n        }\n    }\n\n    private void sendMetrics(MetricsMonitorClusterEvent event) {\n        //todo：实现指标吐到Prometheus的逻辑\n    }\n\n    private void sendMetrics(MetricsMonitorCollectTimeEvent event) {\n        //todo：实现指标吐到Prometheus的逻辑\n    }\n\n    private void sendMetrics(MetricsMonitorIndexEvent event) {\n        //todo：实现指标吐到Prometheus的逻辑\n    }\n\n    private void sendMetrics(MetricsMonitorNodeEvent event) {\n        //todo：实现指标吐到Prometheus的逻辑\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/listen/MetaDataMonitorMetrics2ZHListener.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.listen;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESNodeStats;\nimport com.didichuxing.datachannel.arius.admin.common.event.metrics.*;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.observability.Observability;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.lucene.util.NamedThreadFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.LinkedBlockingDeque;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * 招行内部，把这个实现移动zh-extend中去\n * 这里注释的代码是之前指标对接到行内kafka的实现方式\n * 如果行内有新的指标系统对接，那需要行内同学自己在这个类中实现\n */\n@Service\npublic class MetaDataMonitorMetrics2ZHListener implements ApplicationListener<MetaDataMetricsEvent> {\n    protected static final ILog LOGGER     = LogFactory.getLog(MetaDataMonitorMetrics2ZHListener.class);\n\n    //@Autowired\n    //    private ZHKafkaWriterService ZHKafkaWriterService;\n\n    //@Value(\"${zh.metrics.kafka.topic}\")\n    private String              zhMetricsKafkaTopic;\n\n    private ExecutorService esExecutor = Observability.wrap(new ThreadPoolExecutor(10, 20, 1000,TimeUnit.MILLISECONDS,\n            new LinkedBlockingDeque<>(4000), new NamedThreadFactory(\"Arius-Meta-MonitorMetricsSender-ZH\"),\n            (r, e) -> LOGGER.warn(\n                    \"class=MetaDataMonitorMetrics2ZHListener||msg=Arius-Meta-MonitorMetricsSender-ZH Deque is blocked, taskCount:{}\"\n                            + e.getTaskCount())));\n\n    @Override\n    public void onApplicationEvent(MetaDataMetricsEvent event) {\n        esExecutor.execute(() -> {\n            if (event instanceof MetricsMonitorClusterEvent) {\n                MetricsMonitorClusterEvent monitorClusterEvent = (MetricsMonitorClusterEvent) event;\n                sendMetrics(monitorClusterEvent);\n            }\n\n            if (event instanceof MetricsMonitorCollectTimeEvent) {\n                MetricsMonitorCollectTimeEvent collectTimeEvent = (MetricsMonitorCollectTimeEvent) event;\n                sendMetrics(collectTimeEvent);\n            }\n\n            if (event instanceof MetricsMonitorIndexEvent) {\n                MetricsMonitorIndexEvent monitorIndexEvent = (MetricsMonitorIndexEvent) event;\n                sendMetrics(monitorIndexEvent);\n            }\n\n            if (event instanceof MetricsMonitorNodeEvent) {\n                MetricsMonitorNodeEvent monitorNodeEvent = (MetricsMonitorNodeEvent) event;\n                sendMetrics(monitorNodeEvent);\n            }\n        });\n    }\n\n    private void sendMetrics(MetricsMonitorClusterEvent event) {\n        List<ESClusterStats> esIndexStatsList = event.getEsClusterStatsList();\n\n        //        for(ESClusterStats esClusterStats : esIndexStatsList){\n        //            Map<String, String> metrics = CommonUtils.objectToMap(esClusterStats.getStatis());\n        //            if(MapUtils.isEmpty(metrics)){return;}\n        //\n        //            ZHMetricsData zhMetricsData = new ZHMetricsData();\n        //            zhMetricsData.setName(\"elasticsearch_cluster\");\n        //            zhMetricsData.setTimestamp(System.currentTimeMillis() / 1000);\n        //            zhMetricsData.putTag(\"host\",                event.getHostName());\n        //            zhMetricsData.putTag(\"cluster_name\",        esClusterStats.getCluster());\n        //            zhMetricsData.putTag(\"service_instance\",    esClusterStats.getCluster());\n        //            zhMetricsData.putTag(\"service_type\",        \"elasticsearch\");\n        //            zhMetricsData.setFields(metrics);\n        //\n        //            sendData(Arrays.asList(zhMetricsData));\n        //        }\n    }\n\n    private void sendMetrics(MetricsMonitorCollectTimeEvent event) {\n        //        ZHMetricsData zhMetricsData = new ZHMetricsData();\n        //        zhMetricsData.setName(\"elasticsearch_node_collect_time\");\n        //        zhMetricsData.setTimestamp(System.currentTimeMillis() / 1000);\n        //        zhMetricsData.putTag(\"host\",                event.getHostName());\n        //        zhMetricsData.putTag(\"cluster_name\",        event.getCluster());\n        //        zhMetricsData.putTag(\"type\",                event.getType());\n        //        zhMetricsData.putTag(\"level\",               String.valueOf(event.getClusterLevel()));\n        //        zhMetricsData.putTag(\"service_instance\",    event.getCluster());\n        //        zhMetricsData.putTag(\"service_type\",        \"elasticsearch\");\n        //        zhMetricsData.putField(\"value\", String.valueOf(event.getTime()));\n        //\n        //        sendData(Arrays.asList(zhMetricsData));\n    }\n\n    private void sendMetrics(MetricsMonitorIndexEvent event) {\n        List<ESIndexStats> esIndexStatsList = event.getEsIndexStatsList();\n        if (CollectionUtils.isEmpty(esIndexStatsList)) {\n            return;\n        }\n\n        String hostName = event.getHostName();\n\n        for (ESIndexStats esIndexStats : esIndexStatsList) {\n            //            if(MapUtils.isEmpty(esIndexStats.getMetrics())){continue;}\n            //\n            //            ZHMetricsData zhMetricsData = new ZHMetricsData();\n            //            zhMetricsData.setName(\"elasticsearch_index\");\n            //            zhMetricsData.setTimestamp(System.currentTimeMillis() / 1000);\n            //            zhMetricsData.putTag(\"host\",                hostName);\n            //            zhMetricsData.putTag(\"cluster_name\",        esIndexStats.getCluster());\n            //            zhMetricsData.putTag(\"index\",               esIndexStats.getIndex());\n            //            zhMetricsData.putTag(\"service_instance\",    esIndexStats.getTemplate());\n            //            zhMetricsData.putTag(\"service_type\",        \"es_index\");\n            //\n            //            for(String key : esIndexStats.getMetrics().keySet()){\n            //                zhMetricsData.putField(key, esIndexStats.getMetrics().get(key));\n            //            }\n            //            sendData(Arrays.asList(zhMetricsData));\n        }\n    }\n\n    private void sendMetrics(MetricsMonitorNodeEvent event) {\n        List<ESNodeStats> esNodeStatsList = event.getEsNodeStats();\n        if (CollectionUtils.isEmpty(esNodeStatsList)) {\n            return;\n        }\n\n        String hostName = event.getHostName();\n\n        for (ESNodeStats esNodeStats : esNodeStatsList) {\n            if (MapUtils.isEmpty(esNodeStats.getMetrics())) {\n                continue;\n            }\n\n            //            ZHMetricsData zhMetricsData = new ZHMetricsData();\n            //            zhMetricsData.setName(\"elasticsearch_node\");\n            //            zhMetricsData.setTimestamp(System.currentTimeMillis() / 1000);\n            //            zhMetricsData.putTag(\"host\",                hostName);\n            //            zhMetricsData.putTag(\"node_host\",           esNodeStats.getIp());\n            //            zhMetricsData.putTag(\"node_port\",           esNodeStats.getPort());\n            //            zhMetricsData.putTag(\"node_id\",             esNodeStats.getNode());\n            //            zhMetricsData.putTag(\"cluster_name\",        esNodeStats.getCluster());\n            //            zhMetricsData.putTag(\"service_instance\",    esNodeStats.getCluster());\n            //            zhMetricsData.putTag(\"service_type\",        \"elasticsearch\");\n            //\n            //            for(String key : esNodeStats.getMetrics().keySet()){\n            //                zhMetricsData.putField(key, esNodeStats.getMetrics().get(key));\n            //            }\n            //            sendData(Arrays.asList(zhMetricsData));\n        }\n    }\n\n    //    public void sendData(List<ZHMetricsData> datas){\n    //        if(CollectionUtils.isEmpty(datas)){return;}\n    //\n    //        for(ZHMetricsData zhMetricsData : datas){\n    //            if(null == zhMetricsData){continue;}\n    //\n    //                LOGGER.debug(\"class=ZHMetricsSenderService||method=sendData||datas={}\", JSON.toJSONString(zhMetricsData));\n    //\n    //            ZHKafkaWriterService.sendMessage(zhMetricsKafkaTopic, JSON.toJSONString(zhMetricsData), (recordMetadata, e) -> {\n    //                if(null != e){\n    //                    LOGGER.warn(\"class=ZHMetricsSenderService||method=sendData||datas={}||msg=kafka sendMessage failed!\",\n    //                            JSON.toJSONString(zhMetricsData), e);\n    //                    return;\n    //                }\n    //            });\n    //        }\n    //\n    //        return;\n    //    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/DashBoardMetricsService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardTopNDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.list.MetricList;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.ClusterPhyHealthMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.SortConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricListTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricListTypeWithExtendValueFieldEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricOtherTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricTopTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsDashBoardInfoESDAO;\nimport com.google.common.collect.Lists;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Objects;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.MetricsConstant.FAULT_FLAG;\n\n/**\n * Created by linyunan on 3/14/22\n */\n@Service\npublic class DashBoardMetricsService {\n    //默认排序字段\n    private static final String                                 TIMESTAMP                     = \"timestamp\";\n\n    @Autowired\n    private AriusStatsDashBoardInfoESDAO ariusStatsDashBoardInfoESDAO;\n\n    /**\n     * 获取dashboard大盘TopN指标信息\n     *\n     * @param   param dashboard类型\n     * @param   oneLevelType 目前仅支持 cluster node template index\n     * @see     DashBoardMetricTopTypeEnum\n     * @return  List<VariousLineChartMetrics>\n     */\n    public List<VariousLineChartMetrics> getToNMetrics(MetricsDashboardTopNDTO param, String oneLevelType) {\n        List<String> metricsTypes = param.getMetricsTypes();\n        Long startTime = param.getStartTime();\n        Long endTime = param.getEndTime();\n        Integer topNu = param.getTopNu();\n        String aggType = param.getAggType();\n\n        return ariusStatsDashBoardInfoESDAO.fetchTopMetric(oneLevelType, metricsTypes, topNu, aggType, startTime,\n            endTime);\n    }\n\n    /**\n     * 获取dashboard大盘list列表类异常指标信息 针对dashboard_status 中 的flag字段\n     * @param oneLevelType 一级指标类型 cluster node index template\n     * @param metricsType  二级指标类型 DashBoardMetricListTypeEnum\n     * @param aggType      聚合类型\n     * @see DashBoardMetricListTypeEnum\n     *\n     * @return MetricList\n     */\n    public MetricList getListFaultMetrics(String oneLevelType, String metricsType, String aggType,\n                                          Boolean orderByDesc) {\n        String extendValueField = \"\";\n        String sortItem = TIMESTAMP;\n        String sortType = orderByDesc ? SortConstant.DESC : SortConstant.ASC;\n        List<String> sources = Lists.newArrayList();\n        sources.add(oneLevelType+\".cluster\");\n        sources.add(oneLevelType+\".\"+oneLevelType);\n        if (Objects.nonNull(DashBoardMetricListTypeWithExtendValueFieldEnum.valueOfMetricType(metricsType))){\n            extendValueField = DashBoardMetricListTypeWithExtendValueFieldEnum.valueOfMetricType(metricsType).getExtendValueField();\n            sources.add(oneLevelType+\".\"+extendValueField);\n            sortItem = extendValueField;\n        }\n\n        return ariusStatsDashBoardInfoESDAO.fetchListFlagMetric(oneLevelType, metricsType,sortItem, extendValueField, sources, FAULT_FLAG,\n            sortType);\n    }\n\n    /**\n     * 获取dashboard大盘list列表类指标信息(带额外值)\n     * @param oneLevelType 一级指标类型 cluster node index template\n     * @param metricsType  二级指标类型 DashBoardMetricListTypeEnum\n     * @param aggType      聚合类型\n     * @param orderByDesc  排序类型\n     * @see DashBoardMetricListTypeEnum\n     * @return\n     */\n    public MetricList getListValueMetrics(String oneLevelType, String metricsType, String aggType,\n                                          Boolean orderByDesc) {\n        String sortType = orderByDesc ? SortConstant.DESC : SortConstant.ASC;\n        return ariusStatsDashBoardInfoESDAO.fetchListValueMetrics(oneLevelType, metricsType, aggType, sortType);\n    }\n\n    /**\n     * 获取dashboard大盘健康状态信息\n     *\n     * @see    DashBoardMetricOtherTypeEnum\n     * @return ClusterPhyHealthMetrics\n     */\n    public ClusterPhyHealthMetrics getClusterHealthInfo() {\n        return ariusStatsDashBoardInfoESDAO.fetchClusterHealthInfo();\n    }\n    \n    public MetricList getListThresholdsMetrics(String oneLevelType, String metricsType, String valueName,\n                                               String aggType,\n                                               Boolean orderByDesc) {\n        String sortType = orderByDesc ? SortConstant.DESC : SortConstant.ASC;\n        \n        return ariusStatsDashBoardInfoESDAO.fetchListThresholdsMetric(oneLevelType, metricsType,valueName, aggType,\n                FAULT_FLAG,\n            sortType);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/DslMetricsService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.SearchDslTemplateResponse;\nimport com.google.common.collect.Lists;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.DslMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.DslTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.dsl.DslMetricsESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.dsl.DslTemplateESDAO;\n\n@Service\npublic class DslMetricsService {\n    @Autowired\n    private DslTemplateESDAO dslTemplateESDAO;\n\n    @Autowired\n    private DslMetricsESDAO  dslMetricsESDAO;\n\n    public Result<List<DslTemplate>> getDSLMetricsInfoByProjectId(Integer projectId, Long startDate, Long endDate) {\n        List<DslTemplatePO> dslTemplatePos = dslTemplateESDAO.getDslMetricsByProjectId(projectId, startDate, endDate);\n\n        if (CollectionUtils.isEmpty(dslTemplatePos)) {\n            return Result.buildSucc(new ArrayList<>());\n        }\n\n        dslTemplatePos = dslTemplatePos.stream().filter(d -> !StringUtils.isBlank(d.getIndiceSample()))\n            .collect(Collectors.toList());\n\n        for (DslTemplatePO dslTemplatePo : dslTemplatePos) {\n            if (dslTemplatePo.getQueryLimit() == null) {\n                dslTemplatePo.setQueryLimit(50.0);\n            }\n        }\n\n        return Result.buildSucc(ConvertUtil.list2List(dslTemplatePos, DslTemplate.class));\n    }\n\n    public Result<List<DslMetrics>> getDetailMetrics(int projectId, String dslTemplateMd5, Long startDate,\n                                                     Long endDate) {\n        return Result\n            .buildSucc(ConvertUtil.list2List(dslMetricsESDAO.getDslDetailMetricByProjectIdAndDslTemplateMd5(projectId,\n                dslTemplateMd5, startDate, endDate), DslMetrics.class));\n    }\n\n    public Result<SearchDslTemplateResponse> getDslTemplateByCondition(Integer projectId, String searchKeyword,\n                                                                       String dslTag, String sortInfo, Long from,\n                                                                       Long size, Long startDate, Long endDate) {\n        SearchDslTemplateResponse response = new SearchDslTemplateResponse();\n\n        Tuple<Long, List<DslTemplatePO>> dslTemplatePos = dslTemplateESDAO.getDslTemplateByCondition(projectId,\n            searchKeyword, dslTag, sortInfo, from, size, startDate, endDate);\n\n        if (null == dslTemplatePos) {\n            response.setTotalHits(0L);\n            response.setRecords(Lists.newArrayList());\n            return Result.buildSucc(response);\n        }\n\n        response.setTotalHits(dslTemplatePos.v1());\n        response.setRecords(dslTemplatePos.v2());\n        return Result.buildSucc(response);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/DslStatisticsService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.AuditDsl;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslQueryLimit;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateRequest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.util.DateTimeUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.dsl.DslTemplateESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.parser.DslExtractionUtilV2;\nimport com.didiglobal.knowframework.elasticsearch.client.parser.bean.ExtractResult;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class DslStatisticsService {\n\n    protected static final ILog  LOGGER = LogFactory.getLog(DslStatisticsService.class);\n\n    @Autowired\n    private DslTemplateESDAO     dslTemplateEsDao;\n\n    @Autowired\n    private OperateRecordService operateRecordService;\n    @Autowired\n    private ProjectService       projectService;\n\n    public Result<String> auditDsl(AuditDsl auditDsl) {\n        // 入参判断\n        if (null == auditDsl || !auditDsl.isVaild()) {\n            return Result.build(ResultType.ILLEGAL_PARAMS);\n        }\n\n        Integer projectId = auditDsl.getProjectId();\n\n        List<DslTemplatePO> dslTemplatePOList = Lists.newArrayList();\n        boolean auditResult = auditDsl(projectId, auditDsl.getDslInfos(), dslTemplatePOList);\n        if (!auditResult) {\n            return Result.build(ResultType.FAIL);\n        }\n\n        boolean operatorResult = dslTemplateEsDao.updateTemplates(dslTemplatePOList);\n\n        // 添加操作记录\n        if (operatorResult) {\n            for (DslTemplatePO dslTemplatePo : dslTemplatePOList) {\n                operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"checkMode->%s\",\n                        dslTemplatePo.getCheckMode()),\n                        auditDsl.getUserName(),auditDsl.getProjectId(),String.format(\"%d_%s\", projectId,\n                                dslTemplatePo.getDslTemplateMd5()),OperateTypeEnum.QUERY_TEMPLATE_DSL_CURRENT_LIMIT_ADJUSTMENT);\n            }\n        }\n\n        return Result.build(operatorResult);\n    }\n\n    public Result<Boolean> batchUpdateQueryLimit(List<DslQueryLimit> dslQueryLimitList, String operator) {\n        if (CollectionUtils.isEmpty(dslQueryLimitList)) {\n            return Result.build(ResultType.ILLEGAL_PARAMS);\n        }\n\n        // 获取到原来地查询模板信息\n        Map<String, DslTemplatePO> originalMap = dslTemplateEsDao.getDslTemplateByKeys(dslQueryLimitList);\n\n        // 更新查询限流值\n        boolean operatorResult = dslTemplateEsDao.updateQueryLimitByProjectIdDslTemplate(dslQueryLimitList);\n        if (!operatorResult) {\n            return Result.build(ResultType.FAIL.getCode(), \"document missing fail to update query limit\");\n        }\n\n        DslTemplatePO defaultDsl = new DslTemplatePO();\n        defaultDsl.setQueryLimit(0D);\n\n        // 添加操作记录\n        for (DslQueryLimit dslQueryLimit : dslQueryLimitList) {\n            operateRecordService.saveOperateRecordWithManualTrigger(String.format(\"queryLimit %f->%f\",\n                            originalMap.getOrDefault(dslQueryLimit.getProjectIdDslTemplateMd5(), defaultDsl).getQueryLimit(),\n                            dslQueryLimit.getQueryLimit()), operator, null, dslQueryLimit.getProjectIdDslTemplateMd5(),\n                    OperateTypeEnum.QUERY_TEMPLATE_DSL_CURRENT_LIMIT_ADJUSTMENT);\n        }\n\n        return Result.buildSucc(true);\n    }\n\n    /**\n     * 滚动获取查询模板数据\n     * @param request\n     * @return\n     */\n    public Result<ScrollDslTemplateResponse> scrollSearchDslTemplate(ScrollDslTemplateRequest request) {\n        if (request == null || !request.isValid()) {\n            return Result.buildParamIllegal(\"参数非法\");\n        }\n\n        try {\n            ScrollDslTemplateResponse response = ESOpTimeoutRetry.esRetryExecute(\"scrollSearchDslTemplate\",3,\n                    ()->dslTemplateEsDao.handleScrollDslTemplates(request), Objects::isNull);\n            if (response == null) {\n                return Result.buildFail(\"查询es失败\");\n            }\n\n            return Result.buildSucc(response);\n\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=DslAnalyzerController||method=scrollSearchDslTemplate||errMsg=request {}, search es error||stack={}\",\n                request, e);\n            return Result.buildFail();\n        }\n    }\n\n    /********************************************* private methods *********************************************/\n    /**\n     * DSL审核查询语句\n     *\n     * @param projectId\n     * @param dslInfos\n     * @param dslTemplatePOList\n     * @return\n     */\n    private boolean auditDsl(Integer projectId, List<DslInfo> dslInfos, List<DslTemplatePO> dslTemplatePOList) {\n\n        String dsl;\n        ExtractResult extractResult;\n        String dslTemplateMd5;\n        DslTemplatePO dslTemplatePO;\n        String timeValue = DateTimeUtil.getCurrentFormatDateTime();\n\n        for (DslInfo dslInfo : dslInfos) {\n\n            if (StringUtils.isBlank(dslInfo.getDsl())) {\n                continue;\n            }\n\n            dsl = dslInfo.getDsl();\n            // 对查询语句进行提取成模板\n            extractResult = DslExtractionUtilV2.extractDsl(dsl);\n            if (null == extractResult) {\n                LOGGER.error(\"class=DslStatisService||method=auditDsl||msg=auditDsl extractDsl {} FAIL\", dsl);\n                continue;\n            }\n\n            // 对新版本进行审核\n            dslTemplateMd5 = extractResult.getDslTemplateMd5();\n\n            dslTemplatePO = dslTemplateEsDao.getDslTemplateByKey(projectId, dslTemplateMd5);\n\n            // 如果为空，则新建索引模板\n            if (null == dslTemplatePO) {\n                dslTemplatePO = createDslTemplate(projectId, dsl, extractResult, dslTemplateMd5, timeValue);\n\n                // 如果存在，就修改黑白名单和修改时间\n            } else {\n                dslTemplatePO.setCheckMode(\"white\");\n                dslTemplatePO.setAriusModifyTime(timeValue);\n            }\n\n            dslTemplatePOList.add(dslTemplatePO);\n        }\n\n        // 数据量不等，则失败\n        return dslInfos.size() == dslTemplatePOList.size();\n    }\n\n    private DslTemplatePO createDslTemplate(Integer projectId, String dsl, ExtractResult extractResult,\n                                            String dslTemplateMd5, String timeValue) {\n        DslTemplatePO dslTemplatePO;\n        dslTemplatePO = new DslTemplatePO();\n        dslTemplatePO.setVersion(\"V2\");\n        dslTemplatePO.setAriusCreateTime(timeValue);\n        dslTemplatePO.setAriusModifyTime(timeValue);\n        dslTemplatePO.setFlinkTime(timeValue);\n        dslTemplatePO.setProjectId(projectId);\n        dslTemplatePO.setDslTemplate(extractResult.getDslTemplate());\n        dslTemplatePO.setDslTemplateMd5(dslTemplateMd5);\n        dslTemplatePO.setDslType(extractResult.getDslType());\n        dslTemplatePO.setSearchType(extractResult.getSearchType());\n        dslTemplatePO.setDsl(dsl);\n\n        // 如果查询语句中有聚合查询，或者没有过滤条件，则加入到黑名单\n        if (\"aggs\".equals(extractResult.getDslType()) || StringUtils.isBlank(extractResult.getWhereFields())) {\n            dslTemplatePO.setCheckMode(\"black\");\n            LOGGER.error(\"class=DslAnalyzerController||method=auditDsl||errMsg={} {} has aggs or no where\", projectId,\n                dsl);\n            // 通过sql查询语句中有订单号order_id 但没有routing值，则加入到黑名单\n        } else if (\"sql\".equals(extractResult.getSearchType()) && extractResult.getWhereFields().contains(\"order_id\")\n                   && !extractResult.getDslTemplate().contains(\"ROUTINGS\")) {\n            dslTemplatePO.setCheckMode(\"black\");\n            LOGGER.error(\"class=DslAnalyzerController||method=auditDsl||errMsg={} {} search with order_id no routing\",\n                projectId, dsl);\n        } else {\n            dslTemplatePO.setCheckMode(\"white\");\n        }\n\n        dslTemplatePO.setQueryLimit(10.0);\n        return dslTemplatePO;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/DslTemplateService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.DslQueryLimitDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.template.DslTemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslQueryLimit;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.DateTimeUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.dsl.DslTemplateESDAO;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author cjm\n */\n@Service\npublic class DslTemplateService {\n\n    @Autowired\n    private DslTemplateESDAO dslTemplateESDAO;\n\n    public Boolean updateDslTemplateQueryLimit(List<DslQueryLimitDTO> dslQueryLimitDTOList) {\n\n        List<DslQueryLimit> dslQueryLimitList = new ArrayList<>();\n        for (DslQueryLimitDTO dslQueryLimitDTO : dslQueryLimitDTOList) {\n            // 排除无效的 dslTemplateMd5\n            if (dslTemplateESDAO.getDslTemplateByKey(dslQueryLimitDTO.getProjectIdDslTemplateMd5()) != null) {\n                dslQueryLimitList.add(ConvertUtil.obj2Obj(dslQueryLimitDTO, DslQueryLimit.class));\n            }\n        }\n        return dslTemplateESDAO.updateQueryLimitByProjectIdDslTemplate(dslQueryLimitList);\n    }\n\n    public Boolean updateDslTemplateStatus(Integer projectId,String dslTemplateMd5) {\n        DslTemplatePO dslTemplatePO = dslTemplateESDAO.getDslTemplateByKey(projectId, dslTemplateMd5);\n        if (dslTemplatePO == null) {\n            // 如果没有该 dslTemplateMd5\n            return false;\n        }\n        // getEnable() 如果为 null，表示当前是启用状态，反转模版启用状态\n        if (dslTemplatePO.getEnable() == null) {\n            dslTemplatePO.setEnable(false);\n        } else {\n            dslTemplatePO.setEnable(!dslTemplatePO.getEnable());\n        }\n        String ariusModifyTime =DateTimeUtil.getCurrentFormatDateTime();\n        dslTemplatePO.setAriusModifyTime(ariusModifyTime);\n        List<DslTemplatePO> dslTemplatePOList = new ArrayList<>();\n        dslTemplatePOList.add(dslTemplatePO);\n        return dslTemplateESDAO.updateTemplates(dslTemplatePOList);\n    }\n\n    public DslTemplatePO getDslTemplateDetail(Integer projectId, String dslTemplateMd5) {\n        return dslTemplateESDAO.getDslTemplateByKey(projectId, dslTemplateMd5);\n    }\n\n    public Tuple<Long, List<DslTemplatePO>> getDslTemplatePage(Integer projectId, DslTemplateConditionDTO queryDTO)\n            throws ESOperateException {\n        return dslTemplateESDAO.getDslTemplatePage(projectId, queryDTO);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/ESClusterLogicStatsService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.stats.ClusterLogicStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.stats.ClusterLogicStatsPO;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESClusterNodeDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.clusterindex.IndexStatusResult;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.fs.FSNode;\nimport com.google.common.collect.Lists;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.cluster.health.ClusterHealthStatus;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\n@NoArgsConstructor\n@Service\npublic class ESClusterLogicStatsService {\n    protected static final Logger LOGGER = LoggerFactory.getLogger(ESClusterLogicStatsService.class);\n    private static final String STR_GREEN = \"green\";\n    @Autowired\n    private ESClusterService esClusterService;\n    @Autowired\n    private ESClusterNodeDAO esClusterNodeDAO;\n\n    public ClusterLogicStatsPO getLogicClusterStats(Long logicClusterId, ClusterPhy clusterPhy,\n                                                    Map<Integer, List<String>> logicClusterNodesNameMap,\n                                                    Map<String, List<ClusterLogicStats>> phyClusterNodeStatsMap,\n                                                    Map<Long, List<IndexStatusResult>> logicClusterIndicesMap, boolean isJob) {\n        //初始化返回对象\n        ClusterLogicStatsPO statsPO = new ClusterLogicStatsPO();\n        //通过逻辑集群id获取节点统计信息\n        long timeMillis = System.currentTimeMillis();\n        List<String> logicCLusterNodesList = logicClusterNodesNameMap.get(logicClusterId.intValue());\n        List<ClusterLogicStats> phyCLusterNodeStatsList = phyClusterNodeStatsMap.get(clusterPhy.getCluster());\n        if (CollectionUtils.isNotEmpty(phyCLusterNodeStatsList) && CollectionUtils.isNotEmpty(logicCLusterNodesList)) {\n            List<ClusterLogicStats> logicNodeStats = phyCLusterNodeStatsList.stream()\n                    .filter(clusterLogicStats -> logicCLusterNodesList.contains(clusterLogicStats.getNodeName())).collect(Collectors.toList());\n            Long docNu = logicNodeStats.stream().filter(Objects::nonNull).map(ClusterLogicStats::getDocCount)\n                    .filter(Objects::nonNull).mapToLong(Long::longValue).sum();\n            Double diskFree = logicNodeStats.stream().filter(Objects::nonNull).map(ClusterLogicStats::getFreeInBytes)\n                    .filter(Objects::nonNull).mapToDouble(Long::doubleValue).sum();\n            Double diskUsage = logicNodeStats.stream().filter(Objects::nonNull).map(ClusterLogicStats::getUsageFsBytes)\n                    .filter(Objects::nonNull).mapToDouble(Long::doubleValue).sum();\n            Double diskTotal = logicNodeStats.stream().filter(Objects::nonNull).map(ClusterLogicStats::getTotalFsBytes)\n                    .filter(Objects::nonNull).mapToDouble(Long::doubleValue).sum();\n            //设置节点数\n            statsPO.setNumberDataNodes((long) logicNodeStats.size());\n            //总文档数量\n            statsPO.setDocNu(docNu);\n            //被使用的存储大小\n            statsPO.setUsedDisk(diskUsage);\n            //没有被使用的存储大小\n            statsPO.setFreeDisk(diskFree);\n            //总存储大小\n            statsPO.setTotalDisk(diskTotal);\n            //cpu使用率\n            logicNodeStats.stream().filter(Objects::nonNull).map(ClusterLogicStats::getCpuUsedPresent)\n                    .filter(nodeStats -> Objects.nonNull(nodeStats) && !nodeStats.isNaN())\n                    .mapToDouble(Double::doubleValue).max().ifPresent(statsPO::setCpuUsedPercent);\n            //调用方是定时任务，则采集下面的指标\n            if (isJob) {\n                // 节点存活率\n                Integer clientAlivePrecent = getClientAlivePrecent(logicNodeStats, clusterPhy);\n                statsPO.setAlivePercent(clientAlivePrecent);\n                //通过逻辑集群id获取索引级别统计信息\n                timeMillis = System.currentTimeMillis();\n                handleIndicesStats(statsPO, String.valueOf(logicClusterId), logicClusterIndicesMap);\n            }\n        }\n        return statsPO;\n    }\n\n    /**\n     * @param phyClusterRegionMap         物理集群和单个物理机群下的region的关系\n     * @param regionNodeMap               region和region下的node节点的关系\n     * @param logicClusterIndicesNameMap  逻辑集群和逻辑集群下的索引名称的关系\n     * @param phyClusterName              物理集群名称\n     * @param logicClusterNodesNameMap    返回--逻辑集群和节点名称的关系\n     * @param phyClusterNodeStatsMap      返回--物理集群和节点统计指标的关系\n     * @param logicClusterIndicesStatsMap 返回--逻辑集群和索引统计信息的关系\n     */\n    public void buildLogicClusterStats(Map<String, List<ClusterRegion>> phyClusterRegionMap, Map<Integer,\n            List<String>> regionNodeMap, Map<Long, List<String>> logicClusterIndicesNameMap,\n                                       String phyClusterName, Map<Integer, List<String>> logicClusterNodesNameMap,\n                                       Map<String, List<ClusterLogicStats>> phyClusterNodeStatsMap,\n                                       Map<Long, List<IndexStatusResult>> logicClusterIndicesStatsMap) {\n        //逻辑集群和节点的关系\n        getLogicClusterNodeMap(phyClusterRegionMap, regionNodeMap, phyClusterName, logicClusterNodesNameMap);\n        //物理集群节点信息\n        List<ClusterLogicStats> phyClusterNodesStatsList = syncGetPhyNodesStats(phyClusterName);\n        if (CollectionUtils.isNotEmpty(phyClusterNodesStatsList)) {\n            phyClusterNodeStatsMap.put(phyClusterName, phyClusterNodesStatsList);\n        }    //获取逻辑集群和索引统计信息之间的关系\n        setLogicClusterIndiesStats(phyClusterName, logicClusterIndicesNameMap, logicClusterIndicesStatsMap);\n    }\n\n    private void getLogicClusterNodeMap(Map<String, List<ClusterRegion>> phyClusterRegionMap, Map<Integer, List<String>> regionNodeMap,\n                                        String phyClusterName, Map<Integer, List<String>> logicClusterNodesNameMap) {\n        List<ClusterRegion> clusterRegionList = phyClusterRegionMap.getOrDefault(phyClusterName, Lists.newArrayList());\n        for (ClusterRegion clusterRegion : clusterRegionList) {\n            List<String> nodeNameList = regionNodeMap.get(Math.toIntExact(clusterRegion.getId()));\n            if (CollectionUtils.isNotEmpty(nodeNameList)) {\n                //key是逻辑集群id\n                Map<Integer, List<String>> logicId2ClusterLogicStats = Arrays.stream(StringUtils.split(clusterRegion.getLogicClusterIds(), \",\"))\n                        .filter(StringUtils::isNumeric).map(i -> Tuples.of(Integer.parseInt(i), nodeNameList))\n                        .collect(Collectors.toMap(TupleTwo::v1, TupleTwo::v2));\n                logicClusterNodesNameMap.putAll(logicId2ClusterLogicStats);\n            }\n        }\n    }\n\n    /**\n     * 设置逻辑集群和索引统计信息之间的关系\n     *\n     * @param phyClusterName\n     * @param logicClusterIndicesNameMap\n     * @param logicClusterIndicesStatsMap\n     */\n    private void setLogicClusterIndiesStats(String phyClusterName, Map<Long, List<String>> logicClusterIndicesNameMap,\n                                            Map<Long, List<IndexStatusResult>> logicClusterIndicesStatsMap) {\n        //获取物理集群按节点分组的索引统计信息\n        Map<String, IndexStatusResult> phyClusterIndicesMap = getIndicesStats(phyClusterName);\n        if (MapUtils.isNotEmpty(phyClusterIndicesMap)) {\n            //配置逻辑集群和索引级别统计信息的关系\n\n            for (Map.Entry<Long, List<String>> indexNameListEntry : logicClusterIndicesNameMap.entrySet()) {\n                List<String> indexNameList = indexNameListEntry.getValue();\n                List<IndexStatusResult> indiesStatsList = indexNameList.stream()\n                        .map(indexName -> phyClusterIndicesMap.get(indexName))\n                        .filter(indexStatusResult -> Objects.nonNull(indexStatusResult)).collect(Collectors.toList());\n                if (CollectionUtils.isNotEmpty(indiesStatsList)) {\n                    logicClusterIndicesStatsMap.put(indexNameListEntry.getKey(), indiesStatsList);\n                }\n            }\n        }\n    }\n\n    /**\n     * 节点指标信息采集\n     *\n     * @param phyClusterName\n     * @return\n     */\n    public List<ClusterLogicStats> syncGetPhyNodesStats(String phyClusterName) {\n        List<ClusterLogicStats> phyNodeStatsList = Lists.newArrayList();\n        List<ClusterNodeStats> nodeStatsList = getNodeStats(phyClusterName);\n        if (CollectionUtils.isNotEmpty(nodeStatsList)) {\n            // 遍历节点，获得节点统计指标\n            phyNodeStatsList = nodeStatsList.stream().map(nodeStats -> {\n                try{\n                    //doc文档数量\n                    long docCount = nodeStats.getIndices().getDocs().getCount();\n                    //总存储大小，已使用存储大小，未使用存储大小\n                    FSNode fsNode = nodeStats.getFs();\n                    long totalFsBytes = fsNode.getTotal().getTotalInBytes();\n                    long freeInBytes = fsNode.getTotal().getFreeInBytes();\n                    long usageFsBytes = totalFsBytes - freeInBytes;\n                    int percent = nodeStats.getOs().getCpu().getPercent();\n                    String host = nodeStats.getHost();\n                    String nodeName = nodeStats.getName();\n                    return new ClusterLogicStats(docCount, usageFsBytes, freeInBytes, totalFsBytes, (double) percent, host, nodeName);\n                }catch (Exception e){\n                    LOGGER.error(\"class=ESClusterLogicStatsService||method=syncGetPhyNodeStats||nodeStats={}||errMsg\",nodeStats,e.getMessage(),e);\n                    return new ClusterLogicStats();\n                }\n            }).collect(Collectors.toList());\n        }\n        return phyNodeStatsList;\n    }\n\n    /**\n     * 获取未分配shard数量，集群状态\n     *\n     * @param statsPO\n     * @param logicClusterId\n     * @param logicClusterIndicesMap\n     */\n    private void handleIndicesStats(ClusterLogicStatsPO statsPO, String logicClusterId,\n                                    Map<Long, List<IndexStatusResult>> logicClusterIndicesMap) {\n        byte clusterStatus = ClusterHealthStatus.fromString(STR_GREEN).value();\n        //获取逻辑集群索引列表\n        List<IndexStatusResult> logicClusterIndicesList = logicClusterIndicesMap.get(Long.parseLong(logicClusterId));\n        //获取未分配索引列表\n        statsPO.setUnAssignedShards(0L);\n        statsPO.setStatus(STR_GREEN);\n        statsPO.setStatusType((int) clusterStatus);\n        statsPO.setIndexNu(0L);\n        if (CollectionUtils.isNotEmpty(logicClusterIndicesList)) {\n            statsPO.setIndexNu((long)logicClusterIndicesList.size());\n            logicClusterIndicesList.stream().forEach(indexStatusResult -> {\n                statsPO.setUnAssignedShards(indexStatusResult.getUnassignedShards() + statsPO.getUnAssignedShards());\n                if (indexStatusResult.getStatusType() > statsPO.getStatusType()) {\n                    statsPO.setStatusType(indexStatusResult.getStatusType());\n                    statsPO.setStatus(indexStatusResult.getStatus());\n                }\n            });\n        }\n    }\n\n    /**\n     * 获取逻辑集群节点存活率\n     *\n     * @param clusterLogicStatsList\n     * @param clusterPhy\n     * @return\n     */\n    private Integer getClientAlivePrecent(List<ClusterLogicStats> clusterLogicStatsList, ClusterPhy clusterPhy) {\n        if (CollectionUtils.isNotEmpty(clusterLogicStatsList)) {\n            //查询物理集群的信息\n            if (StringUtils.isBlank(clusterPhy.getHttpAddress())) {\n                return 100;\n            } else {\n                int val = esClusterService.syncGetClientAlivePercent(clusterPhy.getCluster(),\n                        clusterPhy.getPassword(), clusterPhy.getHttpAddress());\n                return val;\n            }\n        }\n        return 0;\n    }\n\n    /**\n     * 获取节点统计信息\n     *\n     * @param phyClusterName\n     * @return\n     */\n\n    private List<ClusterNodeStats> getNodeStats(String phyClusterName) {\n        List<ClusterNodeStats> nodeStatsList = esClusterNodeDAO.syncGetNodesStatsWithIndices(phyClusterName);\n        return nodeStatsList;\n    }\n\n    /**\n     * 获取shard统计信息,粒度为索引级别\n     *\n     * @param phyClusterName\n     * @return\n     */\n    private Map<String, IndexStatusResult> getIndicesStats(String phyClusterName) {\n        Map<String, IndexStatusResult> indexListGroupByNode = new HashMap<>();\n        ESClusterHealthResponse esClusterHealthResponse = esClusterService.syncGetClusterHealthAtIndicesLevel(phyClusterName);\n        if (null == esClusterHealthResponse) {\n            return indexListGroupByNode;\n        }\n        indexListGroupByNode = esClusterHealthResponse.getIndices();\n        return indexListGroupByNode;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/ESClusterPhyStatsService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.percentiles.BasePercentileMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.index.IndexCatCellPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PercentilesEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESClusterDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.cluster.ESClusterNodeDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.gateway.GatewayNodeMetricsDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.index.IndexCatESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsClusterInfoESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsNodeInfoESDAO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.concurrent.atomic.AtomicReference;\n\n/**\n * Created by linyunan on 2021-08-05\n */\n@Service\npublic class ESClusterPhyStatsService {\n\n    @Autowired\n    private AriusStatsClusterInfoESDAO    ariusStatsClusterInfoEsDao;\n\n    @Autowired\n    private AriusStatsNodeInfoESDAO       ariusStatsNodeInfoESDAO;\n\n    @Autowired\n    private ESClusterDAO                  esClusterDAO;\n    @Autowired\n    private ESClusterNodeDAO              esClusterNodeDAO;\n    @Autowired\n    private GatewayNodeMetricsDAO         gatewayNodeMetricsDAO;\n    @Autowired\n    private IndexCatESDAO                 indexCatESDAO;\n\n    private static final FutureUtil<Void> futureUtil = FutureUtil.init(\"ESClusterPhyStaticsService\", 10, 10, 200);\n\n    /**\n     * 获取集群维度分位统计信息\n     * @param clusterName            集群名称\n     * @param clusterMetricsType     根据指标名称去ES索引中匹配指标，匹配则返回，否则为空\n     * @param aggType                聚合类型\n     * @param startTime              开始时间\n     * @param endTime                结束时间\n     * @return                       分位图实体\n     */\n    public List<BasePercentileMetrics> getAggPercentilesMetrics(String clusterName,long clusterType, String clusterMetricsType,\n                                                                String aggType, Long startTime, Long endTime) {\n        AtomicReference<Map<Long, Double>> avgAtomic = new AtomicReference<>();\n        AtomicReference<Map<Long, Double>> st99Atomic = new AtomicReference<>();\n        AtomicReference<Map<Long, Double>> st95Atomic = new AtomicReference<>();\n        AtomicReference<Map<Long, Double>> st75Atomic = new AtomicReference<>();\n        AtomicReference<Map<Long, Double>> st55Atomic = new AtomicReference<>();\n\n        futureUtil\n            .runnableTask(() -> avgAtomic.set(ariusStatsClusterInfoEsDao.getAggSinglePercentilesMetrics(clusterName,clusterType,\n                clusterMetricsType, aggType, PercentilesEnum.AVG.getType(), startTime, endTime)))\n\n            .runnableTask(() -> st99Atomic.set(ariusStatsClusterInfoEsDao.getAggSinglePercentilesMetrics(clusterName,clusterType,\n                clusterMetricsType, aggType, PercentilesEnum.ST99.getType(), startTime, endTime)))\n\n            .runnableTask(() -> st95Atomic.set(ariusStatsClusterInfoEsDao.getAggSinglePercentilesMetrics(clusterName,clusterType,\n                clusterMetricsType, aggType, PercentilesEnum.ST95.getType(), startTime, endTime)))\n\n            .runnableTask(() -> st75Atomic.set(ariusStatsClusterInfoEsDao.getAggSinglePercentilesMetrics(clusterName,clusterType,\n                clusterMetricsType, aggType, PercentilesEnum.ST75.getType(), startTime, endTime)))\n\n            .runnableTask(() -> st55Atomic.set(ariusStatsClusterInfoEsDao.getAggSinglePercentilesMetrics(clusterName,clusterType,\n                clusterMetricsType, aggType, PercentilesEnum.ST55.getType(), startTime, endTime)))\n            .waitExecute();\n\n        Map<Long, Double> timeSlip2AvgValueMap = avgAtomic.get();\n        Map<Long, Double> timeSlip2St99ValueMap = st99Atomic.get();\n        Map<Long, Double> timeSlip2St95ValueMap = st95Atomic.get();\n        Map<Long, Double> timeSlip2St75ValueMap = st75Atomic.get();\n        Map<Long, Double> timeSlip2St55ValueMap = st55Atomic.get();\n\n        List<BasePercentileMetrics> basePercentilesMetricList = new ArrayList<>(timeSlip2AvgValueMap.keySet().size());\n        timeSlip2AvgValueMap.forEach((timeSlip, value) -> {\n            BasePercentileMetrics basePercentileMetrics = new BasePercentileMetrics();\n            basePercentileMetrics.setTimeStamp(timeSlip);\n            basePercentileMetrics.setAggType(value);\n            basePercentilesMetricList.add(basePercentileMetrics);\n        });\n\n        for (BasePercentileMetrics basePercentileMetrics : basePercentilesMetricList) {\n            Double value99 = timeSlip2St99ValueMap.get(basePercentileMetrics.getTimeStamp());\n            Double value95 = timeSlip2St95ValueMap.get(basePercentileMetrics.getTimeStamp());\n            Double value75 = timeSlip2St75ValueMap.get(basePercentileMetrics.getTimeStamp());\n            Double value55 = timeSlip2St55ValueMap.get(basePercentileMetrics.getTimeStamp());\n            basePercentileMetrics.setSt99(null == value99 ? 0 : value99);\n            basePercentileMetrics.setSt95(null == value95 ? 0 : value95);\n            basePercentileMetrics.setSt75(null == value75 ? 0 : value75);\n            basePercentileMetrics.setSt55(null == value55 ? 0 : value55);\n        }\n\n        return basePercentilesMetricList;\n    }\n\n    /**\n     * 获取集群统计信息\n     * @param clusterName 集群名称\n     * @param aggType     聚合类型\n     * @param startTime   开始时间\n     * @param endTime     结束时间\n     * @param clazz       根据类中属性名称去ES索引中匹配指标，匹配到则返回，否则为空\n     * @return            clazz\n     */\n    public <T> List<T> getAggClusterPhyMetrics(String clusterName,long clusterType, String aggType, Long startTime, Long endTime,\n                                               Class<T> clazz) {\n        return ariusStatsClusterInfoEsDao.getAggClusterPhyMetrics(clusterName,clusterType, aggType, startTime, endTime, clazz);\n    }\n\n    /**\n     * 获取集群写入总耗时\n     * @param  cluster 集群名称\n     * @return double\n     */\n    public double getClusterIndexingLatency(String cluster) {\n        return ariusStatsNodeInfoESDAO.getClusterIndexingLatency(cluster);\n    }\n\n    /**\n     * 获取集群查询总耗时\n     * @param  cluster  集群名称\n     * @return double\n     */\n    public double getClusterSearchLatency(String cluster) {\n        return ariusStatsNodeInfoESDAO.getClusterSearchLatency(cluster);\n    }\n\n    /**\n     * 获取集群shard总数\n     *\n     * @param cluster 集群\n     * @return {@code Long}\n     */\n    public Long getClustersShardTotal(String cluster) throws ESOperateException {\n        return  ariusStatsClusterInfoEsDao.getClustersShardTotal(cluster);\n    }\n\n    /**\n     * 获取pending task数量\n     *\n     * @param cluster 集群\n     * @return {@code Long}\n     */\n    public Long getPendingTaskTotal(String cluster) throws ESOperateException {\n        return ariusStatsClusterInfoEsDao.getPendingTaskTotal(cluster);\n    }\n\n    /**\n     * 获取网关成功率和失败率\n     *\n     * @param cluster 集群\n     * @return {@code Tuple<Double, Double>} tuple.1:成功率；tuple.2:失败率\n     */\n    public Tuple<Double/*成功率*/, Double/*失败率*/> getGatewaySuccessRateAndFailureRate(String cluster) {\n        return gatewayNodeMetricsDAO.getGatewaySuccessRateAndFailureRate(cluster);\n    }\n\n    /**\n     * 写入请求数\n     *\n     * @param cluster 集群\n     * @return {@link Long}\n     */\n    public Long getCurrentIndexTotal(String cluster) {\n        return ariusStatsNodeInfoESDAO.getCurrentIndexTotal(cluster);\n    }\n\n    /**\n     * 查询请求数突增量\n     *\n     * @param cluster 集群\n     * @return {@link Long}\n     */\n    public Long getCurrentQueryTotal(String cluster) {\n        return ariusStatsNodeInfoESDAO.getCurrentQueryTotal(cluster);\n    }\n\n    /**\n     * 集群http连接数\n     *\n     * @param cluster 集群\n     * @return {@link Long}\n     */\n    public Long getHttpConnectionTotal(String cluster) {\n        return ariusStatsNodeInfoESDAO.getHttpConnectionTotal(cluster);\n    }\n\n    /**\n     * _cluster/stats 耗时\n     */\n    public Long getClusterStatusElapsedTime(String cluster) throws ESOperateException {\n        long startTime = System.currentTimeMillis();\n        esClusterDAO.getClusterStats(cluster);\n        long endTime = System.currentTimeMillis();\n        return endTime-startTime;\n    }\n\n    /**\n     * _cluster/stats 耗时\n     */\n    public Long getNodeStatusElapsedTime(String cluster) {\n        long startTime = System.currentTimeMillis();\n        esClusterNodeDAO.getNodeState(cluster);\n        long endTime = System.currentTimeMillis();\n        return endTime-startTime;\n    }\n\n    /**\n     * 获取集群采集的最近一个节点和当前时间的时间差\n     * @return\n     */\n    public Long getTimeDifferenceBetweenNearestPointAndNow(String cluster){\n        return ariusStatsClusterInfoEsDao.getTimeDifferenceBetweenNearestPointAndNow(cluster);\n    }\n\n    /**\n     * 获取集群下的索引数量\n     * @param cluster\n     * @return\n     */\n    public Long getIndexCountByCluster(String cluster){\n        Tuple<Long, List<IndexCatCellPO>> index = indexCatESDAO.getIndexListByTerms(cluster,null);\n        return Objects.nonNull(index)?index.v1():0L;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/ESIndicesStatsService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyIndicesDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsIndexInfoESDAO;\nimport com.google.common.collect.Maps;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by linyunan on 2021-08-16\n */\n@Service\npublic class ESIndicesStatsService {\n    @Autowired\n    private   AriusStatsIndexInfoESDAO ariusStatsIndexInfoESDAO;\n    @Value(\"${es.metrics.indices.buckets.max.num}\")\n    protected int                      indicesBucketsMaxNum;\n\n    public List<VariousLineChartMetrics> getAggClusterPhyIndicesMetrics(MetricsClusterPhyIndicesDTO param) {\n        Integer topNu = param.getTopNu();\n        String topMethod = param.getTopMethod();\n        Integer topTimeStep = param.getTopTimeStep();\n        String searchIndexName = param.getIndexName();\n        String clusterPhyName = param.getClusterPhyName();\n        String aggType = param.getAggType();\n        Long endTime = param.getEndTime();\n        Long startTime = param.getStartTime();\n        List<String> metricsTypes = param.getMetricsTypes();\n\n        if (!AriusObjUtils.isBlack(param.getIndexName())) {\n            return ariusStatsIndexInfoESDAO.getAggSingleIndexMetrics(clusterPhyName, metricsTypes, searchIndexName,\n                aggType, startTime, endTime);\n        }\n\n        return ariusStatsIndexInfoESDAO.getTopNIndicesAggMetricsWithStep(clusterPhyName, metricsTypes, topNu, topMethod,\n            topTimeStep, aggType, startTime, endTime);\n    }\n    \n    public List<VariousLineChartMetrics> getAggClusterPhyIndicesMetrics(MetricsClusterPhyIndicesDTO param,\n                                                                        List<String> belongToProjectIndexName) {\n        Integer topNu = param.getTopNu();\n        String topMethod = param.getTopMethod();\n        Integer topTimeStep = param.getTopTimeStep();\n        \n        String clusterPhyName = param.getClusterPhyName();\n        String aggType = param.getAggType();\n        Long endTime = param.getEndTime();\n        Long startTime = param.getStartTime();\n        List<String> metricsTypes = param.getMetricsTypes();\n        \n      \n        return ariusStatsIndexInfoESDAO.getTopNIndicesAggMetricsWithStep(clusterPhyName, metricsTypes, topNu, topMethod,\n                topTimeStep, aggType, startTime, endTime,belongToProjectIndexName);\n    }\n   \n\n    /**\n     * 获取并且聚合对应的物理集群的模板指标类型\n     * @param param 模板指标类型\n     * @return 聚合完成的指标类型列表\n     */\n    public List<VariousLineChartMetrics> getAggClusterPhyTemplateMetrics(MetricsClusterPhyTemplateDTO param) {\n        Integer topNu = param.getTopNu();\n        String topMethod = param.getTopMethod();\n        Integer topTimeStep = param.getTopTimeStep();\n        Integer logicTemplateId = param.getLogicTemplateId();\n        String clusterPhyName = param.getClusterPhyName();\n        String aggType = param.getAggType();\n        Long endTime = param.getEndTime();\n        Long startTime = param.getStartTime();\n        List<String> metricsTypes = param.getMetricsTypes();\n\n        if (!AriusObjUtils.isNull(param.getLogicTemplateId())) {\n            return ariusStatsIndexInfoESDAO.getAggSingleTemplateMetrics(clusterPhyName, metricsTypes, logicTemplateId,\n                aggType, startTime, endTime);\n        }\n        return ariusStatsIndexInfoESDAO.getTopNTemplateAggMetricsWithStep(clusterPhyName, metricsTypes, topNu,\n            topMethod, topTimeStep, aggType, startTime, endTime);\n    }\n    \n      public List<VariousLineChartMetrics> getAggClusterPhyTemplateMetrics(MetricsClusterPhyTemplateDTO param,List<Integer> belongToProjectIdLogicTemplateIdList) {\n        Integer topNu = param.getTopNu();\n        String topMethod = param.getTopMethod();\n        Integer topTimeStep = param.getTopTimeStep();\n        String clusterPhyName = param.getClusterPhyName();\n        String aggType = param.getAggType();\n        Long endTime = param.getEndTime();\n        Long startTime = param.getStartTime();\n        List<String> metricsTypes = param.getMetricsTypes();\n\n       \n        return ariusStatsIndexInfoESDAO.getTopNTemplateAggMetricsWithStep(clusterPhyName, metricsTypes, topNu,\n            topMethod, topTimeStep, aggType, startTime, endTime,belongToProjectIdLogicTemplateIdList);\n    }\n\n    /**\n     * 获取索引search-query数突增量\n     * 上个时间值(now-3,now-2)/(now-5,now-4)上个时间间隔值的两倍 >=2.0\n     *\n     * @param cluster      集群\n     * @param indexList   索引列表\n     * @return {@code Map<String, Double>}\n     */\n    public Map<String, Double> getIndex2CurrentSearchQueryMap(String cluster, List<String> indexList) {\n        if (AriusObjUtils.isBlack(cluster) || CollectionUtils.isEmpty(indexList)) {\n            return Maps.newHashMap();\n        }\n        return ariusStatsIndexInfoESDAO.getIndex2CurrentSearchQueryMap(cluster, indexList);\n    }\n\n    /**\n     * 获取索引indexing-index数突增量\n     * 上个时间值(now-3,now-2)/(now-5,now-4)上个时间间隔值的两倍 >=2.0\n     *\n     * @param cluster     集群\n     * @param indexList   索引列表\n     * @return {@code Map<String, Double>}\n     */\n    public Map<String, Double> getIndex2CurrentIndexingIndexMap(String cluster, List<String> indexList) {\n        if (AriusObjUtils.isBlack(cluster) || CollectionUtils.isEmpty(indexList)) {\n            return Maps.newHashMap();\n        }\n        return ariusStatsIndexInfoESDAO.getIndex2CurrentIndexingIndexMap(cluster, indexList);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/GatewayJoinLogService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.GatewayJoinQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.GatewayJoin;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayJoinPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.gateway.GatewayJoinESDAO;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class GatewayJoinLogService {\n\n    @Autowired\n    private GatewayJoinESDAO gatewayJoinESDAO;\n\n    \n\n    public Result<Long> getSearchCountByProjectId(Long projectId, Long startDate, Long endDate) {\n        return Result.buildSucc(gatewayJoinESDAO.getSearchCountByProjectId(projectId, startDate, endDate));\n    }\n\n    public Result<List<GatewayJoin>> getGatewayErrorList(Long projectId, Long startDate, Long endDate) {\n        return Result.buildSucc(ConvertUtil\n            .list2List(gatewayJoinESDAO.getGatewayErrorList(projectId, startDate, endDate), GatewayJoin.class));\n    }\n\n    public Result<List<GatewayJoin>> getGatewaySlowList(Long projectId, Long startDate, Long endDate) {\n        return Result.buildSucc(ConvertUtil\n            .list2List(gatewayJoinESDAO.getGatewaySlowList(projectId, startDate, endDate), GatewayJoin.class));\n    }\n\n    private void initGatewaySlowQueryCondition(GatewayJoinQueryDTO queryDTO, int defaultSlowTime) {\n        initQueryTimeRange(queryDTO);\n        if (queryDTO.getTotalCost() == null) {\n            queryDTO.setTotalCost((long) defaultSlowTime);\n        }\n    }\n\n    private void initQueryTimeRange(GatewayJoinQueryDTO queryDTO) {\n        if (queryDTO.getStartTime() == null) {\n            long curTimestamp = System.currentTimeMillis();\n            queryDTO.setStartTime(curTimestamp - AdminConstant.MILLIS_PER_DAY);\n            queryDTO.setEndTime(curTimestamp);\n        }\n        if (queryDTO.getEndTime() == null) {\n            queryDTO.setEndTime(System.currentTimeMillis());\n        }\n    }\n    \n    /**\n     *  通过项目 id 和索引名称获取一个 DSL\n     *\n     * @param projectId 您要查询的项目的项目ID。\n     * @param indexName 索引的名称\n     * @return String\n     */\n    public String getOneDSLByProjectIdAndIndexName(Integer projectId, String indexName) {\n        return gatewayJoinESDAO.getOneDSLByProjectIdAndIndexName(projectId, indexName);\n    }\n\n    /**\n     * 分页查询gatewayJoin慢查询日志\n     * @param projectId\n     * @param queryDTO\n     * @param slowQueryTime\n     * @return\n     */\n    public Tuple<Long, List<GatewayJoinPO>> getGatewayJoinSlowQueryLogPage(Integer projectId, GatewayJoinQueryDTO queryDTO, Integer slowQueryTime) throws ESOperateException {\n        initGatewaySlowQueryCondition(queryDTO, slowQueryTime);\n        return gatewayJoinESDAO.getGatewayJoinSlowQueryPage(projectId, queryDTO);\n    }\n\n    /**\n     * 分页查询gatewayJoin异常日志\n     * @param projectId\n     * @param queryDTO\n     * @return\n     */\n    public Tuple<Long, List<GatewayJoinPO>> getGatewayJoinErrorLogPage(Integer projectId, GatewayJoinQueryDTO queryDTO) throws ESOperateException {\n        initQueryTimeRange(queryDTO);\n        return gatewayJoinESDAO.getGatewayJoinErrorPage(projectId, queryDTO);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/GatewayMetricsService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.stream.Collectors;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.GatewayOverviewMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.GatewayMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.MetricsConstant;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.gateway.*;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\n\n/**\n * Created by fitz on 2021-08-16\n */\n@Service\npublic class GatewayMetricsService {\n    private static final ILog LOGGER = LogFactory.getLog(GatewayMetricsService.class);\n    @Autowired\n    private           GatewayOverviewMetricsDAO gatewayOverviewMetricsDAO;\n\n    @Autowired\n    private GatewayIndexMetricsDAO    gatewayIndexMetricsDAO;\n\n    @Autowired\n    private GatewayNodeMetricsDAO     gatewayNodeMetricsDAO;\n\n    @Autowired\n    private GatewayAppMetricsDAO      gatewayAppMetricsDAO;\n\n    @Autowired\n    private GatewayDslMetricsDAO      gatewayDslMetricsDAO;\n\n    public List<GatewayOverviewMetrics> getOverviewCommonMetrics(List<String> metricsTypes, Long startTime,\n                                                                 Long endTime) {\n        return gatewayOverviewMetricsDAO.getAggCommonMetricsByRange(metricsTypes, startTime, endTime);\n    }\n\n    public GatewayOverviewMetrics getOverviewReadCountMetrics(Long startTime, Long endTime) {\n        return gatewayOverviewMetricsDAO.getAggSingleMetricsByRange(DslsConstant.GET_GATEWAY_READ_COUNT,\n            GatewayMetricsTypeEnum.READ_DOC_COUNT, startTime, endTime);\n    }\n\n    public GatewayOverviewMetrics getOverviewSearchTypeMetrics(Long startTime, Long endTime) {\n        return gatewayOverviewMetricsDAO.getAggSingleMetricsByRange(DslsConstant.GET_GATEWAY_SEARCH_TYPE,\n            GatewayMetricsTypeEnum.QUERY_SEARCH_TYPE, startTime, endTime);\n    }\n\n    public List<GatewayOverviewMetrics> getOverviewWriteMetrics(List<String> metricsTypes, Long startTime,\n                                                                Long endTime) {\n        return gatewayOverviewMetricsDAO.getAggWriteMetricsByRange(metricsTypes, startTime, endTime);\n    }\n\n    public List<VariousLineChartMetrics> getGatewayIndexWriteMetrics(List<String> metricsTypes, Long startTime,\n                                                                     Long endTime, Integer projectId, Integer topNu) {\n        return gatewayIndexMetricsDAO.getWriteIndex(metricsTypes, startTime, endTime, projectId, topNu);\n    }\n\n    public List<VariousLineChartMetrics> getGatewayIndexSearchMetrics(List<String> metricsTypes, Long startTime,\n                                                                      Long endTime, Integer projectId, Integer topNu) {\n        return gatewayIndexMetricsDAO.getSearchIndex(metricsTypes, startTime, endTime, projectId, topNu);\n    }\n\n    public List<VariousLineChartMetrics> getGatewayIndexWriteMetrics(List<String> metricsTypes, Long startTime,\n                                                                     Long endTime, Integer projectId,\n                                                                     String templateName) {\n        return gatewayIndexMetricsDAO.getWriteIndexByTemplateName(metricsTypes, startTime, endTime, projectId,\n            templateName);\n    }\n\n    public List<VariousLineChartMetrics> getGatewayIndexSearchMetrics(List<String> metricsTypes, Long startTime,\n                                                                      Long endTime, Integer projectId,\n                                                                      String templateName) {\n        return gatewayIndexMetricsDAO.getSearchIndexByTemplateName(metricsTypes, startTime, endTime, projectId,\n            templateName);\n    }\n\n    public VariousLineChartMetrics getGatewayNodeWriteMetrics(Long startTime, Long endTime, Integer projectId,\n                                                              Integer topNu) {\n        return gatewayNodeMetricsDAO.getWriteGatewayNode(startTime, endTime, projectId, topNu);\n    }\n\n    public VariousLineChartMetrics getGatewayNodeWriteMetrics(Long startTime, Long endTime, Integer projectId,\n                                                              String nodeIp) {\n        return gatewayNodeMetricsDAO.getWriteGatewayNodeByIp(startTime, endTime, projectId, nodeIp);\n    }\n\n    public VariousLineChartMetrics getGatewayNodeDSLLenMetrics(Long startTime, Long endTime, Integer projectId,\n                                                               String nodeIp) {\n        return gatewayNodeMetricsDAO.getWriteGatewayDSLLenByIp(startTime, endTime, projectId, nodeIp);\n    }\n\n    public VariousLineChartMetrics getGatewayNodeDSLLenMetrics(Long startTime, Long endTime, Integer projectId,\n                                                               Integer topNu) {\n        return gatewayNodeMetricsDAO.getWriteGatewayDSLLen(startTime, endTime, projectId, topNu);\n    }\n\n    public VariousLineChartMetrics getGatewayNodeMetrics(Long startTime, Long endTime, Integer projectId,\n                                                         Integer topNu) {\n        return gatewayNodeMetricsDAO.getAggFieldByRange(GatewayMetricsTypeEnum.QUERY_GATEWAY_NODE, startTime, endTime,\n            projectId, topNu);\n    }\n\n    public VariousLineChartMetrics getGatewayNodeMetrics(Long startTime, Long endTime, Integer projectId,\n                                                         String nodeIp) {\n        return gatewayNodeMetricsDAO.getAggFieldByRange(GatewayMetricsTypeEnum.QUERY_GATEWAY_NODE, startTime, endTime,\n            projectId, nodeIp);\n    }\n\n    public VariousLineChartMetrics getClientNodeWriteMetrics(Long startTime, Long endTime, Integer projectId,\n                                                             String gatewayNodeIp, String clientNodeIp) {\n        return gatewayNodeMetricsDAO.getClientNodeWriteByIp(startTime, endTime, projectId, gatewayNodeIp, clientNodeIp);\n    }\n\n    public VariousLineChartMetrics getClientNodeWriteMetrics(Long startTime, Long endTime, Integer projectId,\n                                                             Integer topNu, String gatewayNodeIp) {\n        return gatewayNodeMetricsDAO.getClientNodeWrite(startTime, endTime, projectId, topNu, gatewayNodeIp);\n    }\n\n    public VariousLineChartMetrics getClientNodeDSLLENMetrics(Long startTime, Long endTime, Integer projectId,\n                                                              Integer topNu, String gatewayNodeIp) {\n        return gatewayNodeMetricsDAO.getClientNodeDSLLENByIp(startTime, endTime, projectId, topNu, gatewayNodeIp);\n    }\n\n    public VariousLineChartMetrics getClientNodeDSLLENMetrics(Long startTime, Long endTime, Integer projectId,\n                                                              String gatewayNodeIp, String clientNodeIp) {\n        return gatewayNodeMetricsDAO.getClientNodeDSLLENByIp(startTime, endTime, projectId, gatewayNodeIp,\n            clientNodeIp);\n    }\n\n    public VariousLineChartMetrics getClientNodeMetrics(Long startTime, Long endTime, Integer projectId, Integer topNu,\n                                                        String gatewayNodeIp) {\n        return gatewayNodeMetricsDAO.getClientNodeAggFieldByRange(GatewayMetricsTypeEnum.QUERY_CLIENT_NODE, startTime,\n            endTime, projectId, topNu, gatewayNodeIp);\n    }\n\n    public VariousLineChartMetrics getClientNodeMetrics(Long startTime, Long endTime, Integer projectId,\n                                                        String gatewayNodeIp, String clientNodeIp) {\n        return gatewayNodeMetricsDAO.getClientNodeAggFieldByRange(GatewayMetricsTypeEnum.QUERY_CLIENT_NODE, startTime,\n            endTime, projectId, gatewayNodeIp, clientNodeIp);\n    }\n\n    public List<VariousLineChartMetrics> getAppCommonMetrics(Long startTime, Long endTime, List<String> metricsTypes,\n                                                             Integer topNu) {\n        return gatewayAppMetricsDAO.getAggFieldByRange(startTime, endTime, metricsTypes, topNu);\n    }\n\n    public List<VariousLineChartMetrics> getAppCommonMetricsByProjectId(Long startTime, Long endTime,\n                                                                        List<String> metricsTypes, String projectId) {\n        return gatewayAppMetricsDAO.getAggFieldByRange(startTime, endTime, metricsTypes, projectId);\n    }\n\n    public VariousLineChartMetrics getAppCountMetrics(Long startTime, Long endTime, Integer topNu) {\n        return gatewayAppMetricsDAO.getProjectCountByRange(startTime, endTime, topNu);\n    }\n\n    public VariousLineChartMetrics getAppCountMetricsByProjectId(Long startTime, Long endTime, String projectId) {\n        return gatewayAppMetricsDAO.getProjectCountByRange(startTime, endTime, projectId);\n    }\n\n    public VariousLineChartMetrics getDslCountMetrics(Long startTime, Long endTime, Integer topNu, Integer projectId) {\n        return gatewayDslMetricsDAO.getDslCountByRange(startTime, endTime, topNu, projectId);\n    }\n\n    public VariousLineChartMetrics getDslCountMetricsByMd5(Long startTime, Long endTime, String dslMd5,\n                                                           Integer projectId) {\n        return gatewayDslMetricsDAO.getDslCountByRangeAndMd5(startTime, endTime, dslMd5, projectId);\n    }\n\n    public VariousLineChartMetrics getDslTotalCostMetrics(Long startTime, Long endTime, Integer topNu,\n                                                          Integer projectId) {\n        return gatewayDslMetricsDAO.getDslTotalCostByRange(startTime, endTime, topNu, projectId);\n    }\n\n    public VariousLineChartMetrics getDslTotalCostMetricsByMd5(Long startTime, Long endTime, String dslMd5,\n                                                               Integer projectId) {\n        return gatewayDslMetricsDAO.getDslTotalCostByRangeAndMd5(startTime, endTime, dslMd5, projectId);\n    }\n\n    public List<String> getDslMd5List(Long startTime, Long endTime, Integer projectId) {\n        return gatewayDslMetricsDAO.getDslMd5List(startTime, endTime, projectId);\n    }\n\n    public List<Tuple<String, String>> getEsClientNodeIpListByGatewayNode(String gatewayNode, Long startTime, Long endTime,\n                                                                          Integer projectId) {\n        return gatewayNodeMetricsDAO.getEsClientNodeIpListByGatewayNode(gatewayNode, startTime, endTime, projectId);\n    }\n    \n    /**\n     * 构建topnsingle指标\n     *\n     * @param buildMetrics           构建指标\n     * @param startTime              开始时间\n     * @param endTime                结束时间\n     * @param variousLineChartMetric 各种各样折线图度量\n     * @param projectId              projectId\n     * @param gatewayMetricsTypeEnum {@link GatewayMetricsTypeEnum#getGroup()}\n     * @param nodeIp                 节点ip {@linkplain  GatewayMetricsTypeEnum CLIENT_NODE} 需要设置该参数\n     */\n    private void buildTopNSingleMetrics(List<VariousLineChartMetrics> buildMetrics, Long startTime, Long endTime,\n                                        VariousLineChartMetrics variousLineChartMetric, Integer projectId,\n                                        GatewayMetricsTypeEnum gatewayMetricsTypeEnum, String nodeIp) {\n        List<String> values = variousLineChartMetric.getMetricsContents().stream().map(MetricsContent::getName)\n                .collect(Collectors.toList());\n        String type = variousLineChartMetric.getType();\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(type);\n        variousLineChartMetrics.setMetricsContents(Lists.newArrayList());\n        List<MetricsContent> contents = null;\n        try {\n            switch (gatewayMetricsTypeEnum.getGroup()) {\n                case MetricsConstant.NODE:\n                    contents = gatewayNodeMetricsDAO.getByRangeTopN(values, gatewayMetricsTypeEnum, startTime, endTime,\n                            projectId);\n                    break;\n                case MetricsConstant.CLIENT_NODE:\n                    contents = gatewayNodeMetricsDAO.getByRangeTopN(values, gatewayMetricsTypeEnum, startTime, endTime,\n                        projectId, nodeIp);\n                    List<Tuple<String, String>> tuples = gatewayNodeMetricsDAO\n                        .getEsClientNodeIpListByClientNodes(values, startTime, endTime, projectId);\n                    Map<String, String> clientNode2ClusterName = ConvertUtil.list2Map(tuples, Tuple::getV2,\n                        Tuple::getV1);\n                    if (null != contents) {\n                        contents.forEach(content -> content.setCluster(clientNode2ClusterName.get(content.getName())));\n                    }\n                    break;\n                case MetricsConstant.INDEX:\n                    contents = gatewayIndexMetricsDAO.getByRangeTopN(values, gatewayMetricsTypeEnum, startTime, endTime,\n                            projectId);\n                    break;\n                case MetricsConstant.DSL:\n                    contents = gatewayDslMetricsDAO.getByRangeTopN(values, gatewayMetricsTypeEnum, startTime, endTime,\n                            projectId);\n                    break;\n                case MetricsConstant.APP:\n                    contents = gatewayAppMetricsDAO.getByRangeTopN(values, gatewayMetricsTypeEnum, startTime, endTime);\n                    break;\n                default:\n                    return;\n            }\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=GatewayMetricsService||method=buildTopNSingleMetrics||msg={}||msg=check fail!\",\n                    e.getMessage());\n        }\n    \n        if (CollectionUtils.isNotEmpty(contents)) {\n            variousLineChartMetrics.getMetricsContents().addAll(contents);\n        }\n        buildMetrics.add(variousLineChartMetrics);\n    }\n    \n    public <T extends GatewayMetricsDTO> Optional<List<VariousLineChartMetrics>> getTopNMetrics(Integer projectId,\n                                                                                                T dto,\n                                                                                                GatewayMetricsTypeEnum gatewayMetricsTypeEnum) {\n        Long startTime = dto.getStartTime();\n        Long endTime = dto.getEndTime();\n        List<VariousLineChartMetrics> variousLineChartMetrics = Lists.newArrayList();\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n        int topNu;    //第一阶段结果召回\n        try {\n            switch (gatewayMetricsTypeEnum.getGroup()) {\n                case MetricsConstant.NODE:\n                    topNu = ((GatewayNodeDTO) dto).getTopNu() == 0 ? 1 : ((GatewayNodeDTO) dto).getTopNu();\n                    String nodeIp = ((GatewayNodeDTO) dto).getNodeIp();\n                    variousLineChartMetrics.addAll(\n                            gatewayNodeMetricsDAO.fetchTopMetric(gatewayMetricsTypeEnum, startTime, endTime, topNu,\n                                    projectId, nodeIp));\n                    break;\n                case MetricsConstant.CLIENT_NODE:\n                    topNu = ((ClientNodeDTO) dto).getTopNu() == 0 ? 1 : ((ClientNodeDTO) dto).getTopNu();\n                    String clientNodeIp = ((ClientNodeDTO) dto).getClientNodeIp();\n                    String nodeIpByClientNodeIp = ((ClientNodeDTO) dto).getNodeIp();\n                    variousLineChartMetrics.addAll(\n                            gatewayNodeMetricsDAO.fetchTopMetric(gatewayMetricsTypeEnum, startTime, endTime, topNu,\n                                    projectId, clientNodeIp, nodeIpByClientNodeIp));\n                    break;\n                case MetricsConstant.INDEX:\n                    topNu = ((GatewayIndexDTO) dto).getTopNu() == 0 ? 1 : ((GatewayIndexDTO) dto).getTopNu();\n                    String indexName = ((GatewayIndexDTO) dto).getIndexName();\n                    variousLineChartMetrics.addAll(\n                            gatewayIndexMetricsDAO.fetchTopMetric(gatewayMetricsTypeEnum, startTime, endTime, topNu,\n                                    projectId, indexName));\n                    break;\n                case MetricsConstant.DSL:\n                    topNu = ((GatewayDslDTO) dto).getTopNu() == 0 ? 1 : ((GatewayDslDTO) dto).getTopNu();\n                    String dslMd5 = ((GatewayDslDTO) dto).getDslMd5();\n                    variousLineChartMetrics.addAll(\n                            gatewayDslMetricsDAO.fetchTopMetric(gatewayMetricsTypeEnum, startTime, endTime, topNu,\n                                    projectId, dslMd5));\n                    break;\n                default:\n                    return Optional.empty();\n            }\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=GatewayMetricsService||method=getTopNMetrics||msg={}||msg=check fail!\", e.getMessage());\n        }\n        \n        //第二阶段结果召回\n        for (VariousLineChartMetrics variousLineChartMetric : variousLineChartMetrics) {\n            String nodeIpByClientNodeIp = null;\n            if (gatewayMetricsTypeEnum.getGroup().equals(MetricsConstant.CLIENT_NODE) && dto instanceof ClientNodeDTO) {\n                nodeIpByClientNodeIp = ((ClientNodeDTO) dto).getNodeIp();\n            }\n            String finalNodeIpByClientNodeIp = nodeIpByClientNodeIp;\n            Integer finalProjectId = projectId;\n            buildTopNSingleMetrics(buildMetrics, startTime, endTime, variousLineChartMetric, finalProjectId,\n                    gatewayMetricsTypeEnum, finalNodeIpByClientNodeIp);\n        }\n        return Optional.of(buildMetrics);\n    }\n    \n    public <T extends GatewayMetricsDTO> Optional<List<VariousLineChartMetrics>> getTopNMetrics(T dto,\n                                                                                                GatewayMetricsTypeEnum gatewayMetricsTypeEnum) {\n        final Long endTime = dto.getEndTime();\n        final Long startTime = dto.getStartTime();\n        final String group = dto.getGroup();\n        List<VariousLineChartMetrics> variousLineChartMetrics = Lists.newArrayList();\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n        try {\n            switch (group) {\n                case MetricsConstant.APP:\n                    final String projectId = ((GatewayProjectDTO) dto).getProjectId();\n                    final Integer topNu =\n                            ((GatewayProjectDTO) dto).getTopNu() == 0 ? 1 : ((GatewayProjectDTO) dto).getTopNu();\n                    variousLineChartMetrics.addAll(\n                            gatewayAppMetricsDAO.fetchTopMetric(gatewayMetricsTypeEnum, startTime, endTime, topNu,\n                                    projectId));\n                    break;\n                default:\n                    return Optional.empty();\n            }\n        } catch (AdminOperateException e) {\n            LOGGER.error(\"class=GatewayMetricsService||method=getTopNMetrics||msg={}||msg=check fail!\", e.getMessage());\n        }\n        \n        //第二阶段结果召回\n        for (VariousLineChartMetrics variousLineChartMetric : variousLineChartMetrics) {\n            buildTopNSingleMetrics(buildMetrics, startTime, endTime, variousLineChartMetric, null,\n                    gatewayMetricsTypeEnum, null);\n        }\n        return Optional.of(buildMetrics);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/NodeStatsService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyNodeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyNodeTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ESClusterTaskDetail;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsClusterTaskInfoESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsNodeInfoESDAO;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n@Service\npublic class NodeStatsService {\n    @Autowired\n    private AriusStatsNodeInfoESDAO        ariusStatsNodeInfoEsDao;\n\n    @Autowired\n    private AriusStatsClusterTaskInfoESDAO ariusStatsClusterTaskInfoESDAO;\n\n    public List<VariousLineChartMetrics> getAggClusterPhyNodeMetrics(MetricsClusterPhyNodeDTO param) {\n        Integer topNu = param.getTopNu();\n        String topMethod = param.getTopMethod();\n        Integer topTimeStep = param.getTopTimeStep();\n        String nodeName = param.getNodeName();\n        String clusterPhyName = param.getClusterPhyName();\n        String aggType = param.getAggType();\n        Long endTime = param.getEndTime();\n        Long startTime = param.getStartTime();\n        List<String> metricsTypes = param.getMetricsTypes();\n        List<String> nodeNamesUnderClusterLogic = param.getItemNamesUnderClusterLogic();\n        if (!AriusObjUtils.isBlack(param.getNodeName())) {\n            return ariusStatsNodeInfoEsDao.getAggClusterPhySingleNodeMetrics(clusterPhyName, metricsTypes, nodeName,\n                aggType, startTime, endTime);\n        }\n\n        return ariusStatsNodeInfoEsDao.getTopNNodeAggMetricsWithStep(clusterPhyName, nodeNamesUnderClusterLogic,\n            metricsTypes, topNu, topMethod, topTimeStep, aggType, startTime, endTime);\n    }\n\n    public List<ESClusterTaskDetail> getClusterTaskDetail(String cluster, String node, long startTime, long endTime) {\n        return ariusStatsClusterTaskInfoESDAO.getTaskDetailByNode(cluster, node, startTime, endTime);\n    }\n\n    public List<VariousLineChartMetrics> getAggClusterPhyNodeTaskMetrics(MetricsClusterPhyNodeTaskDTO param) {\n        Integer topNu = param.getTopNu();\n        String nodeName = param.getNodeName();\n        String clusterPhyName = param.getClusterPhyName();\n        Long endTime = param.getEndTime();\n        Long startTime = param.getStartTime();\n        List<String> metricsTypes = param.getMetricsTypes();\n        List<String> aggTypes = param.getAggTypes();\n\n        if (!AriusObjUtils.isBlack(param.getNodeName())) {\n            return ariusStatsClusterTaskInfoESDAO.getAggClusterPhySingleNodeMetrics(clusterPhyName, metricsTypes,\n                nodeName, aggTypes, startTime, endTime);\n        }\n\n        return ariusStatsClusterTaskInfoESDAO.getTopNNodeAggMetrics(clusterPhyName, metricsTypes, topNu, aggTypes,\n            startTime, endTime);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/service/TemplateStatsService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.service;\n\nimport static com.didichuxing.datachannel.arius.admin.common.util.CommonUtils.formatDouble;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.TemplateMetric;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.ProjectTemplateAccessCount;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.TemplateStatsInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.query.ProjectTemplateAccessCountPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.query.TemplateAccessCountPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateStatsInfoPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.app.ProjectTemplateAccessESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsIndexInfoESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.template.TemplateAccessESDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class TemplateStatsService {\n\n    protected static final ILog          LOGGER         = LogFactory.getLog(TemplateStatsService.class);\n\n    @Autowired\n    private AriusStatsIndexInfoESDAO     ariusStatsIndexInfoESDAO;\n\n   \n\n    @Autowired\n    private TemplateAccessESDAO          templateAccessESDAO;\n\n    @Autowired\n    private ProjectTemplateAccessESDAO   projectTemplateAccessESDAO;\n\n \n\n    \n\n    @Autowired\n    private IndexTemplateService         indexTemplateService;\n\n\n    private static final Long            ONE_DAY        = 24 * 60 * 60 * 1000L;\n    private static final Long            MINS_OF_15     = 15 * 60 * 1000L;\n    private static final Long            ONE_GB         = 1024 * 1024 * 1024L;\n\n   \n\n\n\n    /**\n     * 获取模板最近一段时间在访问的app列表\n     *\n     * @param logicTemplateId 模板id\n     * @param days 结束日期\n     * @return projectid列表\n     */\n\n    public Result<Map<Integer, Long>> getTemplateAccessProjectIds(Integer logicTemplateId, int days) {\n        List<ProjectTemplateAccessCountPO> accessCountPos = projectTemplateAccessESDAO\n            .getAccessProjectIdsInfoByTemplateId(logicTemplateId, days);\n        if (CollectionUtils.isEmpty(accessCountPos)) {\n            return Result.buildSucc();\n        }\n\n        Map<Integer, Long> ret = new HashMap<>();\n        for (ProjectTemplateAccessCountPO accessCountPo : accessCountPos) {\n            Integer projectId = accessCountPo.getProjectId();\n            Long count = accessCountPo.getCount();\n\n            if (null != ret.get(projectId)) {\n                count += ret.get(projectId);\n            }\n            ret.put(projectId, count);\n        }\n\n        return Result.buildSucc(ret);\n    }\n\n\n    private void setMaxField(TemplateMetric templateMetric, Map<String, String> maxInfo) {\n        if (StringUtils.isNotBlank(maxInfo.get(\"max_tps\"))) {\n            templateMetric.setMaxTps(Double.valueOf(maxInfo.get(\"max_tps\")));\n        } else {\n            templateMetric.setMaxTps(0d);\n        }\n        if (StringUtils.isNotBlank(maxInfo.get(\"max_query_time\"))) {\n            templateMetric.setMaxQueryTime(Double.valueOf(maxInfo.get(\"max_query_time\")));\n        } else {\n            templateMetric.setMaxQueryTime(0d);\n        }\n        if (StringUtils.isNotBlank(maxInfo.get(\"max_scroll_time\"))) {\n            templateMetric.setMaxScrollTime(Double.valueOf(maxInfo.get(\"max_scroll_time\")));\n        } else {\n            templateMetric.setMaxScrollTime(0d);\n        }\n    }\n\n\n\n\n\n\n\n\n\n\n\n    public Result<Map<Integer, Long>> getAccessStatsInfoByTemplateIdAndDays(int logicTemplateId, int days) {\n        List<ProjectTemplateAccessCountPO> accessCountPos = projectTemplateAccessESDAO\n            .getAccessProjectIdsInfoByTemplateId(logicTemplateId, days);\n        if (CollectionUtils.isEmpty(accessCountPos)) {\n            Result.build(ResultType.SUCCESS);\n        }\n\n        Map<Integer, Long> ret = Maps.newHashMap();\n        for (ProjectTemplateAccessCountPO accessCountPo : accessCountPos) {\n            Integer projectId = accessCountPo.getProjectId();\n            Long count = accessCountPo.getCount();\n\n            if (null != ret.get(projectId)) {\n                count += ret.get(projectId);\n            }\n            ret.put(projectId, count);\n        }\n\n        return Result.buildSucc(ret);\n    }\n\n    public Result<TemplateStatsInfo> getTemplateBaseStatisticalInfoByLogicTemplateId(Long logicTemplateId) {\n        long current = System.currentTimeMillis();\n\n        IndexTemplate indexTemplate = indexTemplateService.getLogicTemplateById(logicTemplateId.intValue());\n\n        if (null == indexTemplate) {\n            return Result.buildFail(\"无法找到对应的模板\");\n        }\n\n        TemplateStatsInfoPO templateStatsInfoPO = new TemplateStatsInfoPO();\n        templateStatsInfoPO.setTemplateId(logicTemplateId);\n        templateStatsInfoPO.setQutoa(indexTemplate.getQuota());\n\n        FutureUtil.DEAULT_FUTURE.runnableTask(() -> {\n            double totalSizeInBytes = ariusStatsIndexInfoESDAO.getLogicTemplateTotalSize(logicTemplateId);\n            templateStatsInfoPO.setStoreBytes(totalSizeInBytes);\n            templateStatsInfoPO.setStore(formatDouble(totalSizeInBytes / ONE_GB, 2));\n        }).runnableTask(() -> {\n            double maxTps = ariusStatsIndexInfoESDAO.getTemplateMaxTpsByTimeRange(logicTemplateId, current - ONE_DAY,\n                current);\n            templateStatsInfoPO.setWriteTps(formatDouble(maxTps, 2));\n        }).runnableTask(() -> {\n            long docNu = ariusStatsIndexInfoESDAO.getTemplateTotalDocNuByTimeRange(logicTemplateId, current - ONE_DAY,\n                current);\n            templateStatsInfoPO.setDocNu(docNu);\n        }).runnableTask(() -> {\n            String indexName = indexTemplate.getName();\n            List<String> topics = Lists.newArrayList();\n            templateStatsInfoPO.setTopics(topics);\n            templateStatsInfoPO.setTemplateName(indexName);\n        }).runnableTask(() -> {\n            List<TemplateAccessCountPO> templateAccessCountPos = templateAccessESDAO\n                .getTemplateAccessLastNDayByLogicTemplateId(logicTemplateId.intValue(), 7);\n            if (CollectionUtils.isNotEmpty(templateAccessCountPos)) {\n                Long count = 0L;\n                for (TemplateAccessCountPO po : templateAccessCountPos) {\n                    count += po.getCount();\n                }\n\n                templateStatsInfoPO.setAccessCountPreDay((double) count / templateAccessCountPos.size());\n            }\n        }).waitExecute();\n\n        return Result.buildSucc(ConvertUtil.obj2Obj(templateStatsInfoPO, TemplateStatsInfo.class));\n    }\n\n    public Result<List<ProjectTemplateAccessCount>> getAccessAppInfos(int logicTemplateId, Long startDate,\n                                                                      Long endDate) {\n        return Result.buildSucc(ConvertUtil.list2List(\n            projectTemplateAccessESDAO.getAccessProjectIdsInfoByTemplateId(logicTemplateId, startDate, endDate),\n            ProjectTemplateAccessCount.class));\n    }\n\n    public Result<List<ESIndexStats>> getIndexStatis(Long logicTemplateId, Long startDate, Long endDate) {\n        return Result.buildSucc(\n            ariusStatsIndexInfoESDAO.getTemplateRealStatis(logicTemplateId, startDate - 1 * 60 * 1000L, endDate));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/utils/MonitorUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.utils;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.Map;\n\npublic class MonitorUtil {\n\n    private MonitorUtil() {\n    }\n\n    public static final String COLLECTION_ROUTE_SPLIT            = \".\";\n\n    public static final String COLLECTION_ROUTE_COMPUTE_DIVISION = \"/\";\n    public static final String COLLECTION_ROUTE_COMPUTE_PLUS     = \"+\";\n\n    public static Object getValueByRoute(Map map, String route) {\n        if (StringUtils.isEmpty(route)) {\n            return null;\n        }\n\n        if (map == null || map.size() == 0) {\n            return null;\n        }\n\n        //这个逻辑是实现两个指标相除加的;后面如果还有其他的算法,可以独立出去;根据符号来运算\n        if (route.contains(COLLECTION_ROUTE_COMPUTE_DIVISION)) {\n            String[] routers = route.split(COLLECTION_ROUTE_COMPUTE_DIVISION);\n            Double dividend = obj2Double(getValueByRoute(map, routers[0]));\n            Double divisor = obj2Double(getValueByRoute(map, routers[1]));\n\n            if (dividend == null || divisor == null || divisor == 0 || dividend + divisor == 0) {\n                return 0d;\n            } else {\n                return dividend / (divisor * 1.0);\n            }\n        }\n\n        if (route.contains(COLLECTION_ROUTE_COMPUTE_PLUS)) {\n            String[] routers = StringUtils.split(route,COLLECTION_ROUTE_COMPUTE_PLUS);\n            Double paramOne = obj2Double(getValueByRoute(map, routers[0]));\n            Double paramTwo = obj2Double(getValueByRoute(map, routers[1]));\n\n            if (paramOne == null) {\n                 paramOne = 0D;\n            }\n            if (paramTwo == null) {\n                paramTwo = 0D;\n            }\n            return paramOne + paramTwo;\n        }\n\n\n        if (route.contains(COLLECTION_ROUTE_SPLIT)) {\n            int offset = route.indexOf(COLLECTION_ROUTE_SPLIT);\n            Object object = map.get(route.substring(0, offset));\n            if (object instanceof Map) {\n                return getValueByRoute((Map) object, route.substring(offset + COLLECTION_ROUTE_SPLIT.length()));\n            } else {\n                return null;\n            }\n        } else {\n            Object object = map.get(route);\n            if (object instanceof Map) {\n                return null;\n            } else {\n                return object;\n            }\n        }\n    }\n\n    public static Double obj2Double(Object obj) {\n        if (null == obj) {\n            return 0d;\n        }\n\n        if (obj instanceof Number) {\n            return Double.valueOf(obj.toString());\n        } else {\n            return 0d;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-metadata/src/main/java/com/didichuxing/datachannel/arius/admin/metadata/utils/ReadExprValueUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.metadata.utils;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport java.math.BigDecimal;\nimport java.util.*;\n\npublic class ReadExprValueUtil {\n    protected static final ILog LOGGER = LogFactory.getLog(ReadExprValueUtil.class);\n\n    private ReadExprValueUtil() {\n    }\n\n    /**\n     * 返回 表达式的值(double)\n     *\n     * @param expr\n     * @return\n     */\n    public static double readExprValue(String expr) {\n        try {\n            if (!isExpression(expr)) {\n                LOGGER.error(\"class=ReadExprValueUtil||method=readExprValue||expr={}\", expr);\n                return -1;\n            }\n            List<String> list = resolveString(expr);\n            list = nifixToPost(list);\n            return getPostfisResult(list);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ReadExprValueUtil||method=readExprValue||expr={}\", expr, e);\n            return 0.0d;\n        }\n    }\n\n    /**\n     * 计算后缀表达式\n     *\n     * @param list\n     * @return\n     */\n    private static double getPostfisResult(List<String> list) {\n        Deque<String> stack = new ArrayDeque<>();\n        for (String str : list) {\n            if (isDouble(str)) {\n                stack.push(str);\n            } else if (isStrOperator(str)) {\n                double n2 = Double.parseDouble(stack.pop());\n                double n1 = Double.parseDouble(stack.pop());\n                stack.push(\"\" + getCountResult(str, n1, n2));\n            }\n        }\n        return Double.valueOf(stack.pop());\n    }\n\n    /**\n     * 字符是否为数字\n     *\n     * @param ch\n     * @return\n     */\n    private static boolean isNum(char ch) {\n        return (ch <= '9' && ch >= '0');\n    }\n\n    /**\n     * 字符串是否为Double类型\n     *\n     * @param s\n     * @return\n     */\n    private static boolean isDouble(String s) {\n        try {\n            Double.valueOf(s);\n            return true;\n        } catch (NumberFormatException e) {\n            return false;\n        }\n    }\n\n    /**\n     * 字符是否为运输符\n     *\n     * @param ch\n     * @return\n     */\n    private static boolean isOperator(char ch) {\n        return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=');\n    }\n\n    /**\n     * 字符串是否为运算符\n     *\n     * @param s\n     * @return\n     */\n    private static boolean isStrOperator(String s) {\n        return (s.equals(\"+\") || s.equals(\"-\") || s.equals(\"*\") || s.equals(\"/\") || s.equals(\"(\") || s.equals(\")\"));\n    }\n\n    /**\n     * 比较运算符优先级\n     *\n     * @param o1\n     * @param o2\n     * @return\n     */\n    private static boolean heightOperator(String o1, String o2) {\n        if ((o1.equals(\"*\") || o1.equals(\"/\")) && (o2.equals(\"+\") || o2.equals(\"-\")) || o2.equals(\"(\")) {\n            return true;\n        } else if ((o1.equals(\"+\") || o1.equals(\"-\")) && (o2.equals(\"*\") || o2.equals(\"/\"))) {\n            return false;\n        } else if ((o1.equals(\"*\") || o1.equals(\"/\")) && (o2.equals(\"*\") || o2.equals(\"/\"))) {\n            return true;\n        } else if ((o1.equals(\"+\") || o1.equals(\"-\")) && (o2.equals(\"+\") || o2.equals(\"-\"))) {\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * 中缀表达式转换后缀\n     *\n     * @param list\n     * @return\n     */\n    private static List<String> nifixToPost(List<String> list) {\n        Deque<String> stack = new ArrayDeque<>();\n        List<String> plist = new ArrayList<>();\n        for (String str : list) {\n            if (isDouble(str)) {\n                plist.add(str);\n            }\n            if (isStrOperator(str) && stack.isEmpty()) {\n                stack.push(str);\n            } else if (isStrOperator(str) && !stack.isEmpty()) {\n                change(stack, plist, str);\n            }\n\n        }\n        while (!stack.isEmpty()) {\n            plist.add(stack.pop());\n        }\n\n        return plist;\n    }\n\n    private static void change(Deque<String> stack, List<String> plist, String str) {\n        String last = stack.getLast();\n        if (heightOperator(str, last) || str.equals(\"(\")) {\n            stack.push(str);\n        } else if (!heightOperator(str, last) && !str.equals(\")\")) {\n            while (!stack.isEmpty() && !stack.getLast().equals(\"(\")) {\n                plist.add(stack.pop());\n            }\n            stack.push(str);\n        } else if (str.equals(\")\")) {\n            while (!stack.isEmpty()) {\n                String pop = stack.pop();\n                if (!pop.equals(\"(\")) {\n                    plist.add(pop);\n                }\n                if (pop.equals(\"(\")) {\n                    break;\n                }\n            }\n        }\n    }\n\n    /**\n     * 分解表达式\n     *\n     * @param str\n     * @return\n     */\n    private static List<String> resolveString(String str) {\n        List<String> list = new ArrayList<>();\n        String temp = \"\";\n        for (int i = 0; i < str.length(); i++) {\n            final char ch = str.charAt(i);\n            if (isNum(ch) || ch == '.') {\n                temp += ch;\n            } else if (isOperator(ch) || ch == ')') {\n                if (!temp.equals(\"\")) {\n                    list.add(temp);\n                }\n                list.add(\"\" + ch);\n                temp = \"\";\n            } else if (ch == '(') {\n                list.add(\"\" + ch);\n                // 科学计数法E\n            } else if (ch == 'E') {\n                list.add(\"(\");\n                list.add(temp);\n                temp = \"\";\n                i++;\n\n                // 科学计数法E换算为10*x方式\n                // E后面的+-符号\n                char symbol = str.charAt(i);\n                if (symbol == '+') {\n                    list.add(\"*\");\n                } else {\n                    list.add(\"/\");\n                }\n\n                i++;\n                String numStr = \"\";\n                for (; i < str.length(); i++) {\n                    char a = str.charAt(i);\n                    if (isOperator(a)) {\n                        i--;\n                        break;\n                    }\n                    numStr += a;\n                }\n                double num = Math.pow(10.0d, Double.parseDouble(numStr));\n                list.add(String.valueOf(num));\n                list.add(\")\");\n            }\n            if (i == str.length() - 1) {\n                list.add(temp);\n            }\n        }\n        return list;\n    }\n\n    /**\n     * 是否为算术表达式\n     *\n     * @param str\n     * @return\n     */\n    private static boolean isExpression(String str) {\n        int flag = 0;\n        for (int i = 0; i < str.length() - 1; i++) {\n            char ch = str.charAt(i);\n            char chb = str.charAt(i + 1);\n            if ((!isNum(ch) && i == 0) && ch != '(' || !isNum(chb) && (i == str.length() - 2) && chb != ')') {\n                LOGGER.error(\"class=ReadExprValueUtil||method=isExpression||errMsg=首尾不是数字---->{}\", ch + chb);\n                return false;\n            }\n            if ((ch == '.' && !isNum(chb)) || (!isNum(ch) && chb == '.')) {\n                LOGGER.error(\"class=ReadExprValueUtil||method=isExpression||errMsg=小数点前后不是数字--->{}\", ch + chb);\n                return false;\n            }\n            if (isOperator(ch) && !isNum(chb) && chb != '(') {\n                LOGGER.error(\"class=ReadExprValueUtil||method=isExpression||errMsg=运算符不是数字--->{}\", ch + chb);\n                return false;\n            }\n            if (isNum(ch) && !isOperator(chb) && chb != '.' && chb != ')' && chb != 'E' && !isNum(chb)) {\n                LOGGER.error(\"class=ReadExprValueUtil||method=isExpression||errMsg=数字后不是运算符--->{}\", ch + chb);\n                return false;\n            }\n            if (ch == '(') {\n                flag++;\n            }\n            if (chb == ')') {\n                flag--;\n            }\n        }\n        if (flag != 0) {\n            LOGGER.error(\"class=ReadExprValueUtil||method=isExpression||errMsg=括号不匹配--->\");\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * 数字的量级\n     */\n    public static int numberOfDigits(int accessNum) {\n        int i = 0;\n        while (accessNum > 0) {\n            accessNum = accessNum / 10;\n            i++;\n        }\n        return i;\n    }\n\n    /**\n     * 两数算术运算\n     */\n    static double getCountResult(String oper, double num1, double num2) {\n        if (oper.equals(\"+\")) {\n            return num1 + num2;\n        } else if (oper.equals(\"-\")) {\n            return num1 - num2;\n        } else if (oper.equals(\"*\")) {\n            return num1 * num2;\n        } else if (oper.equals(\"/\")) {\n            return num1 / num2;\n        } else {\n            return 0;\n        }\n    }\n\n    /**\n     * 将double数值保留2位小数\n     *\n     * @param value double数值\n     * @return 返回2位小数数值\n     */\n    public static double getDouble2(Double value) {\n        BigDecimal bg = BigDecimal.valueOf(value);\n        return bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();\n    }\n\n    public static double getDouble3(Double value) {\n        BigDecimal bg = BigDecimal.valueOf(value);\n        return bg.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <artifactId>arius-admin</artifactId>\n        <version>${revision}${sha1}${changelist}</version>\n    </parent>\n\n    <artifactId>arius-admin-persistence</artifactId>\n\n    <dependencies>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-common</artifactId>\n            <exclusions>\n                <exclusion>\n                    <artifactId>log4j-to-slf4j</artifactId>\n                    <groupId>org.apache.logging.log4j</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>druid</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>mysql</groupId>\n                    <artifactId>mysql-connector-java</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.apache.logging.log4j</groupId>\n                    <artifactId>log4j-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.h2database</groupId>\n                    <artifactId>h2</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.mchange</groupId>\n                    <artifactId>c3p0</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.guava</groupId>\n            <artifactId>guava</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-elasticsearch-client</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mybatis</groupId>\n            <artifactId>mybatis</artifactId>\n        </dependency>\n\n    </dependencies>\n\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/component/ESGatewayClient.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.component;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONException;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESConstant;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AriusGatewayException;\nimport com.didichuxing.datachannel.arius.admin.common.util.BaseHttpUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.document.ESGetRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.document.ESGetResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.document.ESIndexRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.query.query.ESQueryRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.query.query.ESQueryRequestBuilder;\nimport com.didiglobal.knowframework.elasticsearch.client.request.query.scroll.ESQueryScrollRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport java.io.IOException;\nimport java.net.InetSocketAddress;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Function;\nimport javax.annotation.Nullable;\nimport javax.annotation.PostConstruct;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.http.Header;\nimport org.apache.http.message.BasicHeader;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.transport.InetSocketTransportAddress;\nimport org.elasticsearch.common.transport.TransportAddress;\nimport org.elasticsearch.common.unit.TimeValue;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n/**\n * @Author: zqr\n * es的查询类操作需要通过ESGatewayClient, 访问gateway的客户端，\n */\n@Component\n@NoArgsConstructor\n@Data\npublic class ESGatewayClient {\n\n    private static final ILog                                      LOGGER                = LogFactory\n        .getLog(ESGatewayClient.class);\n\n    /**\n     * 请求gateway地址\n     */\n    @Value(\"${es.gateway.url}\")\n    private String                                                 gatewayUrl;\n    /**\n     * 请求gateway 端口号\n     */\n    @Value(\"${es.gateway.port}\")\n    private Integer                                                gatewayPort;\n\n    @Value(\"${es.client.io.thread.count:0}\")\n    private Integer                                                ioThreadCount;\n\n    /**\n     * 访问索引的es user\n     */\n    @Value(\"${es.user}\")\n    private String                                                 esUser;\n    /**\n     * 访问索引的密钥\n     */\n    @Value(\"${es.password}\")\n    private String                                                 password;\n\n    @Value(\"${scroll.timeout}\")\n    private String                                                 scrollTimeOut;\n\n    private static final String                                    COMMA                 = \",\";\n\n    /**\n     * 查询es的客户端\n     */\n    private Map<String/*esUser*/, ESClient>                        queryClientMap        = Maps.newLinkedHashMap();\n    /**\n     * 访问国内索引模板和es user的映射\n     */\n    private Map<String/*access template name*/, String/*es user*/> accessTemplateNameMap = Maps.newHashMap();\n    /**\n     * 认证header\n     */\n    private Map<String/*esUser*/, Header>                          esUserHeaderMap       = Maps.newTreeMap();\n\n    /**\n     * 初始化访问es客户端\n     *\n     */\n    @PostConstruct\n    public void init() throws AriusGatewayException {\n        LOGGER.info(\"class=ESGatewayClient||method=init||ESGatewayClient init start.\");\n        // 多个es user\n        String[] esUsers = StringUtils.splitByWholeSeparatorPreserveAllTokens(esUser, COMMA);\n        String[] passwords = StringUtils.splitByWholeSeparatorPreserveAllTokens(password, COMMA);\n\n        if (esUsers == null || passwords == null || esUsers.length != passwords.length) {\n            throw new AriusGatewayException(\"please check cn gateway es user,password\");\n        }\n\n        // 构建认证信息的header\n        Header accessHeader = null;\n        ESClient esClient = null;\n\n        for (int i = 0; i < esUsers.length; ++i) {\n            accessHeader = BaseHttpUtil.buildHttpHeader(esUsers[i], passwords[i]);\n            esClient = buildGateWayClient(this.gatewayUrl, this.gatewayPort, accessHeader, \"gateway\");\n\n            queryClientMap.put(esUsers[i], esClient);\n            esUserHeaderMap.put(esUsers[i], accessHeader);\n        }\n        LOGGER.info(\"class=ESGatewayClient||method=init||ESGatewayClient init finished.\");\n    }\n\n    /**\n     * 获取gateway读写地址\n     */\n    public String getGatewayAddress() {\n        List<String> urls = ListUtils.string2StrList(gatewayUrl);\n        List<String> gateWayList = Lists.newArrayList();\n        urls.forEach(url -> gateWayList.add(url + \":\" + gatewayPort));\n        return ListUtils.strList2String(gateWayList);\n    }\n\n    /**\n     * 获取一个gateway读写地址\n     */\n    public String getSingleGatewayAddress() {\n        List<String> urls = ListUtils.string2StrList(gatewayUrl);\n        Random random = new Random();\n        int n = random.nextInt(urls.size());\n        return urls.get(n) + \":\" + gatewayPort;\n    }\n\n    /**\n     * 执行sql查询\n     * @param sql\n     * @return\n     */\n    @Nullable\n    public ESQueryResponse performSQLRequest(String indexName, String sql, String orginalQuery) {\n        return performSQLRequest(null, indexName, sql, orginalQuery);\n    }\n\n    /**\n     * 执行sql查询\n     * @param sql\n     * @return\n     */\n    @Nullable\n    public ESQueryResponse performSQLRequest(String clusterName, String indexName, String sql, String orginalQuery) {\n        Tuple<String, ESClient> gatewayClientTuple = null;\n        try {\n            gatewayClientTuple = getGatewayClientByDataCenterAndIndexName(clusterName, indexName);\n\n            return gatewayClientTuple.v2().prepareSQL(sql).get(new TimeValue(120, TimeUnit.SECONDS));\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=GatewayClient||method=performSQLRequest||dataCenter={}||gatewayClientTuple={}||clusterName={}||sql={}||md5={}||errMsg=query error. \",\n                EnvUtil.getDC(), JSON.toJSONString(gatewayClientTuple), clusterName, sql,\n                CommonUtils.getMD5(orginalQuery), e);\n            return null;\n        }\n    }\n\n    /**\n     * 根据查询语句获取数据\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     */\n    public String performRequestAndGetResponse(String indexName, String typeName, String queryDsl) {\n\n        return performRequestAndGetResponse(null, indexName, typeName, queryDsl);\n    }\n\n    /**\n     * 根据查询语句获取数据\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     */\n    public String performRequestAndGetResponse(String clusterName, String indexName, String typeName, String queryDsl) {\n\n        ESQueryResponse esQueryResponse = doQuery(clusterName, indexName,\n            new ESQueryRequest().indices(indexName).types(typeName).source(queryDsl));\n        if (esQueryResponse == null) {\n            return null;\n        }\n\n        return esQueryResponse.toJson().toJSONString();\n    }\n\n    /**\n     * 执行查询\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     * @throws IOException\n     */\n    public ESQueryResponse performRequest(String indexName, String typeName, String queryDsl) {\n\n        return performRequest(null, indexName, typeName, queryDsl);\n    }\n\n    /**\n     * 执行查询\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     * @throws IOException\n     */\n    public ESQueryResponse performRequest(String clusterName, String indexName, String typeName, String queryDsl) {\n        return doQuery(clusterName, indexName,\n            new ESQueryRequest().indices(indexName).types(typeName).source(queryDsl));\n    }\n\n    public ESQueryResponse performRequestWithRouting(String clusterName, String routing, String indexName,\n                                                     String typeName, String queryDsl) {\n        return doQuery(clusterName, indexName,\n            new ESQueryRequest().indices(indexName).routing(routing).types(typeName).source(queryDsl));\n    }\n\n    /**\n     * 获取命中总数\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     */\n    public Long performRequestAndGetTotalCount(String indexName, String typeName, String queryDsl) {\n        return performRequestAndGetTotalCount(null, indexName, typeName, queryDsl);\n    }\n\n    /**\n     * 获取命中总数\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     */\n    public Long performRequestAndGetTotalCount(String clusterName, String indexName, String typeName, String queryDsl,\n                                               int tryTimes) {\n        return performRequest(clusterName, indexName, typeName, queryDsl, esQueryResponse -> {\n            if (null == esQueryResponse || esQueryResponse.getHits() == null) {\n                return 0L;\n            }\n            return Long\n                .valueOf(esQueryResponse.getHits().getUnusedMap().getOrDefault(ESConstant.HITS_TOTAL, \"0\").toString());\n        }, tryTimes);\n    }\n\n    /**\n     * 获取命中总数\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     */\n    public Long performRequestAndGetTotalCount(String clusterName, String indexName, String typeName, String queryDsl) {\n        ESQueryResponse esQueryResponse = performRequest(clusterName, indexName, typeName, queryDsl);\n        if (null == esQueryResponse || esQueryResponse.getHits() == null) {\n            return 0L;\n        }\n\n        return Long\n            .valueOf(esQueryResponse.getHits().getUnusedMap().getOrDefault(ESConstant.HITS_TOTAL, \"0\").toString());\n    }\n\n    /**\n     * 根据查询语句获取数据\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param clzz\n     * @param <T>\n     * @return\n     */\n    public <T> List<T> performRequest(String indexName, String typeName, String queryDsl, Class<T> clzz) {\n        return performRequest(null, indexName, typeName, queryDsl, clzz);\n    }\n\n    /**\n     * 根据dsl语句写数据\n     *\n     * @param templateName 模版名称\n     * @param typeName 类型\n     * @param dsl 数据\n     */\n    public void performWriteRequest(String templateName, String typeName, String dsl) {\n        performWriteRequest(null, templateName, typeName, dsl);\n    }\n\n    /**\n     * 根据dsl语句写数据\n     *\n     * @param clusterName 集群名字\n     * @param templateName 模版名称（目前通过gateway写入只支持传模版，不能具体某一个日期的索引）\n     * @param typeName 类型\n     * @param dsl 数据\n     */\n    public void performWriteRequest(String clusterName, String templateName, String typeName, String dsl) {\n        doWrite(clusterName, templateName, new ESIndexRequest().index(templateName).type(typeName).source(dsl));\n    }\n\n    /**\n     * 根据查询语句获取数据\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param clzz\n     * @param <T>\n     * @return\n     */\n    public <T> List<T> performRequest(String clusterName, String indexName, String typeName, String queryDsl,\n                                      Class<T> clzz) {\n        ESQueryResponse esQueryResponse = doQuery(clusterName, indexName,\n            new ESQueryRequest().indices(indexName).types(typeName).source(queryDsl).clazz(clzz));\n        if (esQueryResponse == null) {\n            return new ArrayList<>();\n        }\n\n        List<Object> objectList = esQueryResponse.getSourceList();\n        if (CollectionUtils.isEmpty(objectList)) {\n            return new ArrayList<>();\n        }\n\n        List<T> hits = Lists.newLinkedList();\n        for (Object obj : objectList) {\n            hits.add((T) obj);\n        }\n\n        return hits;\n    }\n\n    public <R> R performRequest(String indexName, String typeName, String queryDsl, Function<ESQueryResponse, R> func,\n                                int tryTimes) {\n        return performRequest(null, indexName, typeName, queryDsl, func, tryTimes);\n    }\n\n    public <R> R performRequest(String clusterName, String indexName, String typeName, String queryDsl,\n                                Function<ESQueryResponse, R> func, int tryTimes) {\n        ESQueryResponse esQueryResponse;\n        do {\n            esQueryResponse = doQuery(clusterName, indexName,\n                new ESQueryRequest().indices(indexName).types(typeName).source(queryDsl));\n        } while (tryTimes-- > 0 && null == esQueryResponse);\n\n        LOGGER.debug(\"class=GatewayClient||method=performRequest||dataCenter={}||indexName={}||queryDsl={}||ret={}\",\n                EnvUtil.getDC(), indexName, queryDsl, JSON.toJSONString(esQueryResponse));\n\n        return func.apply(esQueryResponse);\n    }\n\n    public <R> R performRequestWithRouting(String clusterName, String routingValue, String indexName, String typeName,\n                                           String queryDsl, Function<ESQueryResponse, R> func, int tryTimes) {\n        ESQueryResponse esQueryResponse;\n        do {\n            esQueryResponse = doQuery(clusterName, indexName,\n                new ESQueryRequest().routing(routingValue).indices(indexName).types(typeName).source(queryDsl));\n        } while (tryTimes-- > 0 && null == esQueryResponse);\n\n        LOGGER.debug(\"class=GatewayClient||method=performRequestWithRouting||dataCenter={}||indexName={}||queryDsl={}||ret={}\",\n                EnvUtil.getDC(), indexName, queryDsl, JSON.toJSONString(esQueryResponse));\n\n        return func.apply(esQueryResponse);\n    }\n\n    /**\n     * 查询并获取第一个元素\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param clzz\n     * @param <T>\n     * @return\n     */\n    public <T> T performRequestAndTakeFirst(String indexName, String typeName, String queryDsl, Class<T> clzz) {\n        return performRequestAndTakeFirst(null, indexName, typeName, queryDsl, clzz);\n    }\n\n    /**\n     * 查询并获取第一个元素\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param clzz\n     * @param <T>\n     * @return\n     */\n    public <T> T performRequestAndTakeFirst(String clusterName, String indexName, String typeName, String queryDsl,\n                                            Class<T> clzz) {\n        List<T> hits = performRequest(clusterName, indexName, typeName, queryDsl, clzz);\n\n        if (CollectionUtils.isEmpty(hits)) {\n            return null;\n        }\n\n        return hits.get(0);\n    }\n\n    /**\n     * 获取命中总数和第一条记录\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param clzz\n     * @param <T>\n     * @return\n     */\n    public <T> Tuple<Long, T> performRequestAndGetTotalCount(String indexName, String typeName, String queryDsl,\n                                                             Class<T> clzz) {\n        return performRequestAndGetTotalCount(null, indexName, typeName, queryDsl, clzz);\n    }\n\n    /**\n     * 获取命中总数和第一条记录\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param clzz\n     * @param <T>\n     * @return\n     */\n    public <T> Tuple<Long, T> performRequestAndGetTotalCount(String clusterName, String indexName, String typeName,\n                                                             String queryDsl, Class<T> clzz) {\n        ESQueryResponse esQueryResponse = doQuery(clusterName, indexName,\n            new ESQueryRequest().indices(indexName).types(typeName).source(queryDsl).clazz(clzz));\n        if (esQueryResponse == null) {\n            return null;\n        }\n\n        List<Object> objectList = esQueryResponse.getSourceList();\n        if (CollectionUtils.isEmpty(objectList)) {\n            return null;\n        }\n\n        return new Tuple<>(\n            Long.valueOf(esQueryResponse.getHits().getUnusedMap().getOrDefault(ESConstant.HITS_TOTAL, \"0\").toString()),\n            (T) objectList.get(0));\n    }\n\n    /**\n     * 执行查询\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     * @throws IOException\n     */\n    @Nullable\n    public ESAggrMap performAggRequest(String indexName, String typeName, String queryDsl) {\n        return performAggRequest(null, indexName, typeName, queryDsl);\n    }\n\n    /**\n     * 执行查询\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     * @throws IOException\n     */\n    @Nullable\n    public ESAggrMap performAggRequest(String clusterName, String indexName, String typeName, String queryDsl) {\n        ESQueryResponse esQueryResponse = doQuery(clusterName, indexName,\n            new ESQueryRequest().indices(indexName).types(typeName).source(queryDsl));\n        if (esQueryResponse == null || esQueryResponse.getAggs() == null) {\n            return null;\n        }\n\n        return esQueryResponse.getAggs();\n    }\n\n    /**\n     * 执行查询\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     * @throws IOException\n     */\n    @Nullable\n    public ESAggrMap performAggRequestWithPreference(String indexName, String typeName, String queryDsl,\n                                                     String preference) {\n        return performAggRequest(null, indexName, typeName, queryDsl, preference);\n    }\n\n    /**\n     * 获取命中总数和返回查询记录\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param clzz\n     * @param <T>\n     * @return\n     */\n    public <T> Tuple<Long, List<T>> performRequestListAndGetTotalCount(String clusterName, String indexName,\n                                                                       String typeName, String queryDsl,\n                                                                       Class<T> clzz) {\n        ESQueryResponse esQueryResponse = doQuery(clusterName, indexName,\n            new ESQueryRequest().indices(indexName).types(typeName).source(queryDsl).clazz(clzz));\n        if (esQueryResponse == null) {\n            return null;\n        }\n\n        List<Object> objectList = esQueryResponse.getSourceList();\n        if (CollectionUtils.isEmpty(objectList)) {\n            return new Tuple<>(0L, Collections.emptyList());\n        }\n\n        List<T> hits = Lists.newLinkedList();\n        for (Object obj : objectList) {\n            hits.add((T) obj);\n        }\n\n        return new Tuple<>(\n            Long.valueOf(esQueryResponse.getHits().getUnusedMap().getOrDefault(ESConstant.HITS_TOTAL, \"0\").toString()),\n            hits);\n    }\n\n    /**\n     * 执行查询\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @return\n     * @throws IOException\n     */\n    @Nullable\n    public ESAggrMap performAggRequest(String clusterName, String indexName, String typeName, String queryDsl,\n                                       String preference) {\n        ESQueryResponse esQueryResponse = doQuery(clusterName, indexName,\n            new ESQueryRequest().indices(indexName).types(typeName).source(queryDsl).preference(preference));\n        if (esQueryResponse == null || esQueryResponse.getAggs() == null) {\n            return null;\n        }\n\n        return esQueryResponse.getAggs();\n    }\n\n    /**\n     * 准备滚动查询\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param clzz\n     * @param scrollResultVisitor\n     * @param <T>\n     * @return\n     */\n    public <T> ESQueryResponse prepareScrollQuery(String indexName, String typeName, String queryDsl, String preference,\n                                                  Class<T> clzz, ScrollResultVisitor<T> scrollResultVisitor) {\n\n        return prepareScrollQuery(null, indexName, typeName, queryDsl, preference, clzz, scrollResultVisitor);\n    }\n\n    /**\n     * 准备滚动查询\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param clzz\n     * @param scrollResultVisitor\n     * @param <T>\n     * @return\n     */\n    public <T> ESQueryResponse prepareScrollQuery(String clusterName, String indexName, String typeName,\n                                                  String queryDsl, String preference, Class<T> clzz,\n                                                  ScrollResultVisitor<T> scrollResultVisitor) {\n        ESQueryResponse esQueryResponse = null;\n        ESQueryRequestBuilder builder = null;\n\n        Tuple<String, ESClient> gatewayClientTuple = null;\n        gatewayClientTuple = getGatewayClientByDataCenterAndIndexName(clusterName, indexName);\n        builder = gatewayClientTuple.v2().prepareQuery(indexName).setTypes(typeName).setClazz(clzz).setSource(queryDsl)\n            .setScroll(new TimeValue(60000));\n\n        // 如果指定了preference\n        if (StringUtils.isNotBlank(preference)) {\n            builder = builder.preference(preference);\n        }\n        esQueryResponse = builder.execute().actionGet(120, TimeUnit.SECONDS);\n\n        if (esQueryResponse == null) {\n            return null;\n        }\n\n        List<Object> objectList = esQueryResponse.getSourceList();\n        if (objectList == null) {\n            return esQueryResponse;\n        }\n\n        List<T> hits = Lists.newLinkedList();\n        for (Object obj : objectList) {\n            hits.add((T) obj);\n        }\n\n        scrollResultVisitor.handleScrollResult(hits);\n\n        return esQueryResponse;\n    }\n\n    /**\n     * 再次滚动查询\n     *\n     * @param scrollId\n     * @param clzz\n     * @param scrollResultVisitor\n     * @param <T>\n     * @return\n     */\n    public <T> ESQueryResponse queryScrollQuery(String indexName, String scrollId, Class<T> clzz,\n                                                ScrollResultVisitor<T> scrollResultVisitor) {\n        return queryScrollQuery(null, indexName, scrollId, clzz, scrollResultVisitor);\n    }\n\n    /**\n     * 再次滚动查询\n     *\n     * @param scrollId\n     * @param clzz\n     * @param scrollResultVisitor\n     * @param <T>\n     * @return\n     */\n    public <T> ESQueryResponse queryScrollQuery(String clusterName, String indexName, String scrollId, Class<T> clzz,\n                                                ScrollResultVisitor<T> scrollResultVisitor) {\n        ESQueryResponse esQueryResponse = null;\n        ESQueryScrollRequest queryScrollRequest = new ESQueryScrollRequest();\n        queryScrollRequest.setScrollId(scrollId).scroll(new TimeValue(60000));\n        queryScrollRequest.clazz(clzz);\n\n        Tuple<String, ESClient> gatewayClientTuple = null;\n        gatewayClientTuple = getGatewayClientByDataCenterAndIndexName(clusterName, indexName);\n        esQueryResponse = gatewayClientTuple.v2().queryScroll(queryScrollRequest).actionGet(120, TimeUnit.SECONDS);\n\n        if (esQueryResponse == null) {\n            return null;\n        }\n\n        List<Object> objectList = esQueryResponse.getSourceList();\n        if (objectList == null) {\n            return esQueryResponse;\n        }\n\n        List<T> hits = Lists.newLinkedList();\n        for (Object obj : objectList) {\n            hits.add((T) obj);\n        }\n\n        scrollResultVisitor.handleScrollResult(hits);\n\n        return esQueryResponse;\n    }\n\n    /**\n     * 使用滚动查询方式\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param scrollSize\n     * @param clzz\n     * @return\n     */\n    public <T> void queryWithScroll(String indexName, String typeName, String queryDsl, int scrollSize,\n                                    String preference, Class<T> clzz, ScrollResultVisitor<T> scrollResultVisitor) {\n        queryWithScroll(null, indexName, typeName, queryDsl, scrollSize, preference, clzz, scrollResultVisitor);\n    }\n\n    /**\n     * 使用滚动查询方式\n     *\n     * @param indexName\n     * @param typeName\n     * @param queryDsl\n     * @param scrollSize\n     * @param clzz\n     * @return\n     */\n    public <T> void queryWithScroll(String clusterName, String indexName, String typeName, String queryDsl,\n                                    int scrollSize, String preference, Class<T> clzz,\n                                    ScrollResultVisitor<T> scrollResultVisitor) {\n        ESQueryResponse esQueryResponse = null;\n        try {\n            esQueryResponse = prepareScrollQuery(clusterName, indexName, typeName, queryDsl, preference, clzz,\n                scrollResultVisitor);\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=GatewayClient||method=queryWithScroll||dataCenter={}||indexName={}||queryDsl={}||errMsg=query error. \",\n                EnvUtil.getDC(), indexName, queryDsl, e);\n        }\n\n        if (esQueryResponse == null) {\n            return;\n        }\n\n        long totalCount = Long\n            .parseLong(esQueryResponse.getHits().getUnusedMap().getOrDefault(ESConstant.HITS_TOTAL, \"0\").toString());\n        int scrollCnt = (int) Math.ceil((double) totalCount / scrollSize);\n\n        for (int scrollIndex = 0; scrollIndex < scrollCnt - 1; ++scrollIndex) {\n            if (esQueryResponse == null) {\n                continue;\n            }\n\n            String scrollId = esQueryResponse.getUnusedMap().get(\"_scroll_id\").toString();\n\n            try {\n                esQueryResponse = queryScrollQuery(clusterName, indexName, scrollId, clzz, scrollResultVisitor);\n            } catch (Exception e) {\n                LOGGER.warn(\n                    \"class=GatewayClient||method=queryWithScroll||dataCenter={}||scrollId={}||errMsg=query error. \",\n                    EnvUtil.getDC(), scrollId, e);\n            }\n        }\n\n    }\n\n    /**\n     * 根据主键获取\n     *\n     * @param indexName\n     * @param typeName\n     * @param id\n     * @param clzz\n     * @param <T>\n     * @return\n     */\n    public <T> T doGet(String indexName, String typeName, String id, Class<T> clzz) {\n        return doGet(null, indexName, typeName, id, clzz);\n    }\n\n    /**\n     * 根据主键获取\n     *\n     * @param indexName\n     * @param typeName\n     * @param id\n     * @param clzz\n     * @param <T>\n     * @return\n     */\n    public <T> T doGet(String clusterName, String indexName, String typeName, String id, Class<T> clzz) {\n        ESGetRequest request = new ESGetRequest();\n        request.index(indexName).type(typeName).id(id);\n\n        ESGetResponse response = null;\n        Tuple<String, ESClient> gatewayClientTuple = null;\n        try {\n            gatewayClientTuple = getGatewayClientByDataCenterAndIndexName(clusterName, indexName);\n            response = gatewayClientTuple.v2().get(request).actionGet(30, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=GatewayClient||method=doGet||dataCenter={}||gatewayClientTuple={}||indexName={}||typeName={}||id={}||errMsg=get error. \",\n                EnvUtil.getDC(), JSON.toJSONString(gatewayClientTuple), indexName, typeName, id, e);\n        }\n\n        if (response == null) {\n            return null;\n        }\n\n        T obj = null;\n        try {\n            obj = JSON.parseObject(JSON.toJSONString(response.getSource()), clzz);\n        } catch (JSONException e) {\n            LOGGER.warn(\n                \"class=GatewayClient||method=doGet||dataCenter={}||indexName={}||typeName={}||id={}||clzz={}||errMsg=fail to parse json. \",\n                EnvUtil.getDC(), indexName, typeName, id, clzz, e);\n        }\n\n        return obj;\n    }\n\n    /**\n     * 执行查询\n     * @param queryRequest\n     * @return\n     */\n    @Nullable\n    private ESQueryResponse doQuery(String clusterName, String indexName, ESQueryRequest queryRequest) {\n        Tuple<String, ESClient> gatewayClientTuple = null;\n        try {\n            gatewayClientTuple = getGatewayClientByDataCenterAndIndexName(clusterName, indexName);\n\n            return gatewayClientTuple.v2().query(queryRequest).actionGet(120, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            String queryDsl = bytesReferenceConvertDsl(queryRequest.source());\n            LOGGER.warn(\n                \"class=GatewayClient||method=doQuery||dataCenter={}||gatewayClientTuple={}||clusterName={}||indexName={}||queryDsl={}||md5={}||errMsg=query error. \",\n                EnvUtil.getDC(), JSON.toJSONString(gatewayClientTuple), clusterName, queryRequest.indices(), queryDsl,\n                CommonUtils.getMD5(queryDsl), e);\n            return null;\n        }\n    }\n\n    /**\n     * @param clusterName 集群名字\n     * @param templateName 模版名称（目前通过gateway写入只支持传模版，不能具体某一个日期的索引）\n     * @param indexRequest indexRequest\n     */\n    private void doWrite(String clusterName, String templateName, ESIndexRequest indexRequest) {\n        Tuple<String, ESClient> gatewayClientTuple = null;\n        try {\n            gatewayClientTuple = getGatewayClientByDataCenterAndIndexName(clusterName, templateName);\n            gatewayClientTuple.v2().index(indexRequest);\n        } catch (Exception e) {\n            String dsl = bytesReferenceConvertDsl(indexRequest.source());\n            LOGGER.warn(\n                \"class=GatewayClient||method=doWrite||dataCenter={}||gatewayClientTuple={}||clusterName={}||indexName={}||queryDsl={}||md5={}||errMsg=query error. \",\n                EnvUtil.getDC(), JSON.toJSONString(gatewayClientTuple), clusterName, indexRequest.index(), dsl,\n                CommonUtils.getMD5(dsl), e);\n        }\n    }\n\n    /**\n     * 根据机房和索引名称获取访问gateway客户端\n     *\n     * @param indexName\n     * @return\n     */\n    private Tuple<String, ESClient> getGatewayClientByDataCenterAndIndexName(String clusterName, String indexName) {\n        // 默认第一个esUser\n        String esUser = queryClientMap.keySet().iterator().next();\n\n        // 只有一个es user时或者没传索引名称时，直接返回第一个；配置多个es user时，根据访问索引名称进行选择\n        if (queryClientMap.size() > 1 && StringUtils.isNotBlank(indexName)) {\n            for (Map.Entry<String/*access template name*/, String/*esUser*/> entry : accessTemplateNameMap.entrySet()) {\n                // 去掉索引表达式最后的*，如果访问的索引名称以表达式开头，则返回该es user\n                String accessTemplateName = StringUtils.removeEnd(entry.getKey(), \"*\");\n                if (StringUtils.isNotBlank(accessTemplateName) && indexName.startsWith(accessTemplateName)) {\n                    esUser = entry.getValue();\n                    break;\n                }\n            }\n        }\n\n        ESClient esClient = queryClientMap.get(esUser);\n\n        LOGGER.debug(\"class=GatewayClient||method=getGatewayClientByDataCenterAndIndexName||esUser={}||indexName={}\",\n                esUser, indexName);\n\n        Header esUserHeader = esUserHeaderMap.get(esUser);\n        if (esClient != null) {\n            List<Header> headers = Lists.newArrayList();\n            if (esUserHeader != null) {\n                // 添加认证头\n                headers.add(esUserHeader);\n\n                // 添加指定集群访问头\n                if (StringUtils.isNotBlank(clusterName)) {\n                    Header clusterNameHeader = new BasicHeader(\"CLUSTER_ID\", clusterName);\n                    headers.add(clusterNameHeader);\n                }\n\n                esClient.setHeaders(headers);\n            }\n        }\n\n        return new Tuple<>(esUser, esClient);\n    }\n\n    private ESClient buildGateWayClient(String url, Integer port, Header header, String clusterName) {\n        String[] ipArray = null;\n        TransportAddress[] transportAddresses = null;\n        ESClient esClient = null;\n        // 构建查询客户端\n        ipArray = StringUtils.splitByWholeSeparatorPreserveAllTokens(url, COMMA);\n        if (ipArray != null && ipArray.length > 0) {\n            try {\n                esClient = new ESClient();\n                transportAddresses = new TransportAddress[ipArray.length];\n                for (int j = 0; j < ipArray.length; ++j) {\n                    transportAddresses[j] = new InetSocketTransportAddress(new InetSocketAddress(ipArray[j], port));\n                }\n                esClient.addTransportAddresses(transportAddresses);\n                if (header != null) {\n                    esClient.setHeader(header);\n                }\n                if (StringUtils.isNotBlank(clusterName)) {\n                    esClient.setClusterName(clusterName);\n                }\n\n                if (ioThreadCount > 0) {\n                    esClient.setIoThreadCount(ioThreadCount);\n                }\n\n                // 配置http超时\n                esClient.setRequestConfigCallback(builder -> builder.setConnectTimeout(10000).setSocketTimeout(120000)\n                    .setConnectionRequestTimeout(120000));\n                esClient.start();\n            } catch (Exception e) {\n                if (null != esClient) {\n                    esClient.close();\n                }\n\n                LOGGER.error(\"class=ESGatewayClient||method=buildGateWayClient||errMsg={}||url={}||port={}\",\n                    e.getMessage(), url, port, e);\n                return null;\n            }\n        }\n\n        return esClient;\n    }\n\n    /**\n     * 转换dsl语句\n     *\n     * @param bytes\n     * @return\n     */\n    private String bytesReferenceConvertDsl(BytesReference bytes) {\n        try {\n            return XContentHelper.convertToJson(bytes, false);\n        } catch (IOException e) {\n            LOGGER.warn(\"class=CommonUtils||method=bytesReferenceConvertDsl||errMsg=fail to covert\", e);\n        }\n\n        return \"\";\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/component/ESOpClient.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.component;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterPhyPO;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.resource.PhyClusterDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Sets;\nimport java.lang.reflect.Field;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\nimport javax.annotation.PostConstruct;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.http.impl.nio.client.CloseableHttpAsyncClient;\nimport org.elasticsearch.client.RestClient;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Component;\n\n/**\n * es的操作需要通过ESOpClient，维护admin与各个集群的链接\n * @author d06679\n * @date 2019/3/20\n */\n@Component\npublic class ESOpClient {\n\n    private static final ILog               LOGGER       = LogFactory.getLog(ESOpClient.class);\n\n    private final Map<String, ESClient>     esClientMap  = new ConcurrentHashMap<>();\n    private final Map<String, ClusterPhyPO> esClusterMap = new ConcurrentHashMap<>();\n\n    @Autowired\n    private PhyClusterDAO                   clusterDAO;\n\n    @Value(\"${es.client.io.thread.count:0}\")\n    private Integer                         ioThreadCount;\n\n    /**\n     * 启动就链接所有集群\n     * 每10min就检查一遍自己的链接\n     *\n     * Client信息最近10分钟有更新的会更新对应的Client信息，\n     * Client的信息会8个小时重新连接一遍，做为兜底方案\n     */\n    @PostConstruct\n    @Scheduled(cron = \"0 3/5 * * * ?\")\n    public synchronized void refreshConnect() {\n\n        LOGGER.info(\"class=ESOpClient||method=init||ESOpClient refreshConnect start.\");\n        List<ClusterPhyPO> dataCluster = clusterDAO.listAll();\n        Set<String> currentESClientClusters = Sets.newConcurrentHashSet(esClientMap.keySet());\n        dataCluster.parallelStream().forEach(clusterPO -> {\n\n            if (!esClientMap.containsKey(clusterPO.getCluster())) {\n                try {\n                    connect(clusterPO);\n                } catch (Exception e) {\n                    LOGGER.error(\"class=ESOpClient||method=refreshConnect||errMsg={}||cluster={}\", e.getMessage(),\n                        clusterPO.getCluster(), e);\n                }\n            } else {\n                ClusterPhyPO cachedCluster = esClusterMap.get(clusterPO.getCluster());\n                if ((cachedCluster != null && !cachedCluster.equals(clusterPO))\n                    || !isActualRunning(clusterPO.getCluster())) {\n                    LOGGER.info(\"class=ESOpClient||method=refreshConnect||msg=clusterMetaUpdate||\"\n                                + \"cluster={}||cachedClusterMeta={}||currentClusterMeta={}\",\n                        clusterPO.getCluster(), JSON.toJSONString(cachedCluster), JSON.toJSONString(clusterPO));\n                    reConnect(clusterPO.getCluster());\n                } else if (cachedCluster == null) {\n                    LOGGER.error(\"class=ESOpClient||method=refreshConnect||msg=clusterCachedMiss||\"\n                                 + \"cluster={}||currentClusterMeta={}\",\n                        clusterPO.getCluster(), JSON.toJSONString(clusterPO));\n                }\n            }\n            currentESClientClusters.remove(clusterPO.getCluster());\n        });\n\n        if (CollectionUtils.isNotEmpty(currentESClientClusters)) {\n            for (String cluster : currentESClientClusters) {\n                removeAndCloseESClient(cluster);\n            }\n        }\n        LOGGER.info(\"class=ESOpClient||method=init||ESOpClient refreshConnect finished.\");\n    }\n\n    /**\n     * 链接\n     * @param cluster 集群名字\n     */\n    public synchronized void connect(String cluster) {\n        if (esClientMap.containsKey(cluster)) {\n            return;\n        }\n\n        connect(clusterDAO.getByName(cluster));\n    }\n\n    /**\n     * 移除某个集群的链接\n     * @param cluster 集群名称\n     */\n    public void removeAndCloseESClient(String cluster) {\n        LOGGER.info(\"class=ESOpClient||method=removeAndCloseESClient||msg=remove es client||cluster={}\", cluster);\n\n        ESClient client = esClientMap.remove(cluster);\n        if (client != null) {\n            client.close();\n        }\n\n        esClusterMap.remove(cluster);\n    }\n\n    /**\n     * 获取某个集群的链接\n     * @param cluster 集群名称\n     * @return 链接\n     */\n    public ESClient getESClient(String cluster) {\n        if (!esClientMap.containsKey(cluster)) {\n            LOGGER.warn(\"class=ESOpClient||method=getESClient||msg=cluster connect not exist, reconnect||cluster={}\",\n                cluster);\n        }\n\n        return esClientMap.get(cluster);\n    }\n\n    /**\n     * 重新链接\n     * @param cluster 集群名字\n     */\n    public void reConnect(String cluster) {\n        removeAndCloseESClient(cluster);\n        //connect(cluster);\n        connect(clusterDAO.getByName(cluster));\n    }\n\n    /**************************************** private method ****************************************************/\n    private void connect(ClusterPhyPO clusterPO) {\n        LOGGER.info(\"class=ESOpClient||method=connect||msg=connect es start||cluster={}\", clusterPO.getCluster());\n\n        if (StringUtils.isBlank(clusterPO.getHttpAddress())) {\n            LOGGER.warn(\"class=ESOpClient||method=connect||msg=connect es fail, httpAddress is null||cluster={}\",\n                clusterPO.getCluster());\n            return;\n        }\n\n        ESClient client = new ESClient();\n        client.addTransportAddresses(clusterPO.getHttpAddress());\n        if (StringUtils.isNotEmpty(clusterPO.getPassword())) {\n            client.setPassword(clusterPO.getPassword());\n        }\n\n        try {\n            if (ESClient.DEFAULT_ES_VERSION.equals(client.getEsVersion())\n                && !ESClient.DEFAULT_ES_VERSION.equals(clusterPO.getEsVersion())) {\n                client.setEsVersion(clusterPO.getEsVersion());\n                client.setClusterName(clusterPO.getCluster());\n            }\n\n            if (ioThreadCount > 0) {\n                client.setIoThreadCount(ioThreadCount);\n            }\n\n            client.start();\n\n            ESClusterHealthResponse response = client.admin().cluster().prepareHealth().execute().actionGet(10,\n                TimeUnit.SECONDS);\n\n            if (RestStatus.OK.getStatus() == response.getRestStatus().getStatus()) {\n                LOGGER.info(\"class=ESOpClient||method=connect||msg=connect es by http succ||cluster={}||hosts={}\",\n                    clusterPO.getCluster(), clusterPO.getHttpAddress());\n\n                esClientMap.put(clusterPO.getCluster(), client);\n                esClusterMap.put(clusterPO.getCluster(), clusterPO);\n            } else {\n                client.close();\n            }\n        } catch (Exception e) {\n            client.close();\n            LOGGER.error(\n                \"class=ESOpClient||method=connect||msg=connect es by http error||cluster={}||hosts={}||msg=client start error\",\n                clusterPO.getCluster(), clusterPO.getHttpAddress());\n        }\n    }\n\n    public boolean isActualRunning(String cluster) {\n        ESClient esClient = esClientMap.get(cluster);\n        if (esClient != null) {\n            return isActualRunning(esClient);\n        }\n        return false;\n    }\n\n    public boolean isActualRunning(ESClient esClient) {\n        try {\n            Field field = esClient.getClass().getDeclaredField(\"restClient\");\n            field.setAccessible(true);\n            RestClient restClient = (RestClient) field.get(esClient);\n            field = restClient.getClass().getDeclaredField(\"client\");\n            field.setAccessible(true);\n            CloseableHttpAsyncClient httpAsyncClient = (CloseableHttpAsyncClient) field.get(restClient);\n            return httpAsyncClient.isRunning();\n        } catch (Exception e) {\n            LOGGER.warn(\"get running status error.\", e);\n            return true;\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/component/ESOpTimeoutRetry.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.component;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.BaseException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NullESClientException;\nimport com.didichuxing.datachannel.arius.admin.common.util.RetryExecutor;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\nimport org.apache.commons.lang3.RandomUtils;\nimport org.elasticsearch.ElasticsearchTimeoutException;\nimport org.elasticsearch.cluster.metadata.ProcessClusterEventTimeoutException;\n\n/**\n * es操作器\n *  1、操作返回false,这里直接返回false\n *  2、超时重试对应的次数后,返回false\n *  3、操作抛出异常(非超时异常), 抛异常\n *  4、操作返回true,这里直接返回true\n *\n * @author d06679\n * @date 2017/8/24\n */\npublic class ESOpTimeoutRetry {\n    private static final int SEC_1 = 1000;\n    private static final int SEC_5 = 5000;\n\n    private ESOpTimeoutRetry() {\n    }\n\n    /**\n     * 定制重试方法，不对返回判断重试\n     */\n    public static <T> T esRetryExecute(String methodName, int tryCount,\n                                       RetryExecutor.Handler<T> handler) throws ESOperateException {\n        return esRetryExecute(methodName, tryCount, handler, t -> false);\n    }\n\n    /**\n     * 定制重试方法，根据返回值来判断是否需要重试\n     */\n    public static <T> T esRetryExecute(String methodName, int tryCount,\n                                       RetryExecutor.Handler<T> handler,\n                                       Predicate<T> retNeedRetry) throws ESOperateException {\n        return esRetryExecuteInner(methodName, tryCount, handler, retNeedRetry, retryTimes -> {\n            int time = retryTimes * SEC_1 + RandomUtils.nextInt(0, 100);\n            return Math.min(time, SEC_5);\n        } );\n    }\n\n    /**\n     * 定制重试方法等待的时间\n     */\n    public static <T> T esRetryExecuteWithGivenTime(String methodName, int tryCount,\n                                                    RetryExecutor.Handler<T> handler,\n                                                    Function<Integer, Integer> retrySleepTime) throws ESOperateException {\n        return esRetryExecuteInner(methodName, tryCount, handler, t -> false, retrySleepTime);\n    }\n\n    /**************************************** private method ***************************************************/\n    private static <T> T esRetryExecuteInner(String methodName, int tryCount,\n                                       RetryExecutor.Handler<T> handler,\n                                       Predicate<T> retNeedRetry,\n                                       Function<Integer, Integer> retrySleepTime) throws ESOperateException {\n        try {\n            final RetryExecutor<T> retryExecutor = RetryExecutor.builder().name(methodName).retryCount(tryCount)\n                    .handler(new RetryExecutor.Handler() {\n                        @Override\n                        public T process() throws BaseException {\n                            return handler.process();\n                        }\n\n                        @Override\n                        public boolean needExceptionRetry(Exception e) {\n                            return e instanceof ProcessClusterEventTimeoutException\n                                    || e instanceof ElasticsearchTimeoutException\n                                    || e instanceof NullESClientException;\n                        }\n\n                        @Override\n                        public boolean needReturnObjRetry(Object t) {\n                            return retNeedRetry.test((T)t);\n                        }\n\n                        @Override\n                        public int retrySleepTime(int retryTimes) {\n                            return retrySleepTime.apply(retryTimes);\n                        }\n                    });\n            return retryExecutor.execute();\n        } catch (ESOperateException e) {\n            throw new ESOperateException(e.getMessage(),e.getCause());\n        }catch (Exception e){\n            throw new ESOperateException(e.getMessage(), e);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/component/ESUpdateClient.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.component;\n\nimport java.net.InetSocketAddress;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport javax.annotation.PostConstruct;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.http.HttpStatus;\nimport org.elasticsearch.common.transport.InetSocketTransportAddress;\nimport org.elasticsearch.common.transport.TransportAddress;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterPhyPO;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.resource.PhyClusterDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.document.ESIndexRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.document.ESIndexResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.model.type.ESVersion;\nimport com.didiglobal.knowframework.elasticsearch.client.request.batch.BatchNode;\nimport com.didiglobal.knowframework.elasticsearch.client.request.batch.BatchType;\nimport com.didiglobal.knowframework.elasticsearch.client.request.batch.ESBatchRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.refreshindex.ESIndicesRefreshIndexRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.response.batch.ESBatchResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.batch.IndexResultItemNode;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.deletebyquery.ESIndicesDeleteByQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.refreshindex.ESIndicesRefreshIndexResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\n\nimport lombok.NoArgsConstructor;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/9/14 下午1:22\n * @Modified By\n *\n * 更新es数据的客户端，数据只会写入arius-meta集群\n */\n@Component\n@NoArgsConstructor\npublic class ESUpdateClient {\n\n    private static final ILog             LOGGER            = LogFactory.getLog(ESUpdateClient.class);\n    public static final int               MAX_RETRY_CONT    = 5;\n\n    /**\n     * 集群名称\n     */\n    @Value(\"${es.update.cluster.name}\")\n    private String                        metadataClusterName;\n\n    @Value(\"${es.client.io.thread.count:0}\")\n    private Integer                       ioThreadCount;\n\n    /**\n     * 客户端个数\n     */\n    private int                           clientCount       = 3;\n    /**\n     *  更新es数据的客户端连接队列\n     */\n    private final List<ESClient> updateClientPool  = Lists.newCopyOnWriteArrayList();\n\n    /**\n     * 轮询获取esClient 时使用的下标\n     */\n    private final AtomicInteger  esClientCounter   = new AtomicInteger(0);\n    /**\n     * 之前的http连接地址\n     */\n    private String                        beforeHttpAddress = null;\n\n    @Autowired\n    private PhyClusterDAO                 clusterDAO;\n\n    public static final int               MAX_RETRY_CNT     = 5;\n\n    private static final String           COMMA             = \",\";\n    private static final String           ES_VERSION_PREFIX = \"es-version\";\n\n    @PostConstruct\n    public void init() {\n        LOGGER.info(\"class=ESUpdateClient||method=init||ESUpdateClient init start.\");\n        List<ClusterPhyPO> clusterPOS = clusterDAO.listAll();\n        setDataSourceList(clusterPOS);\n        LOGGER.info(\"class=ESUpdateClient||method=init||ESUpdateClient init finished.\");\n    }\n\n    // delete by query\n    public ESIndicesDeleteByQueryResponse deleteByQuery(String index, String type, String query) {\n        ESClient esClient = getUpdateEsClientFromPool();\n        if (esClient == null) {\n            LOGGER.warn(\"class=ESUpdateClient||method=deleteByQuery||errMsg=esClient is null\");\n            return null;\n        }\n\n        ESIndicesDeleteByQueryResponse resp = esClient.admin().indices().prepareDeleteByQuery().setIndex(index)\n            .setType(type).setQuery(query).execute().actionGet(5, TimeUnit.MINUTES);\n        if (resp == null) {\n            LOGGER.warn(\"class=UpdateClient||method=deleteByQuery||errMsg=resp is null\");\n            return null;\n        }\n\n        return resp;\n    }\n\n    /**\n     * 写入单条\n     *\n     * @param source\n     * @return\n     */\n    public boolean index(String indexName, String typeName, String id, String source) {\n        ESClient esClient = null;\n        ESIndexResponse response = null;\n\n        try {\n            esClient = getUpdateEsClientFromPool();\n            if (esClient == null) {\n                return false;\n            }\n\n            ESIndexRequest esIndexRequest = new ESIndexRequest();\n            esIndexRequest.setIndex(indexName);\n            esIndexRequest.type(typeName);\n            esIndexRequest.source(source);\n            esIndexRequest.id(id);\n\n            for (int i = 0; i < MAX_RETRY_CNT; ++i) {\n                response = esClient.index(esIndexRequest).actionGet(10, TimeUnit.SECONDS);\n                if (response == null) {\n                    continue;\n                }\n\n                return response.getRestStatus().getStatus() == HttpStatus.SC_OK\n                       || response.getRestStatus().getStatus() == HttpStatus.SC_CREATED;\n            }\n\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=UpdateClient||method=index||indexName={}||typeName={}||id={}||source={}||errMsg=index doc error. \",\n                indexName, typeName, id, source, e);\n            if (response != null) {\n                LOGGER.warn(\n                    \"class=UpdateClient||method=index||indexName={}||typeName={}||id={}||source={}||errMsg=response {}\",\n                    indexName, typeName, id, source, JSON.toJSONString(response));\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * 批量写入\n     *\n     * @param indexName\n     * @param typeName\n     * @return\n     */\n    public boolean batchInsert(String indexName, String typeName, List<? extends BaseESPO> pos) {\n        if (CollectionUtils.isEmpty(pos)) {\n            return true;\n        }\n\n        ESClient esClient = null;\n        ESBatchResponse response = null;\n        try {\n            esClient = getUpdateEsClientFromPool();\n            if (esClient == null) {\n                return false;\n            }\n\n            ESBatchRequest batchRequest = new ESBatchRequest();\n            for (BaseESPO po : pos) {\n                //write with routing\n                if (null != po.getRoutingValue()) {\n                    BatchNode batchNode = new BatchNode(BatchType.INDEX, indexName, typeName, po.getKey(),\n                        JSON.toJSONString(po));\n                    batchNode.setRouting(po.getRoutingValue());\n                    batchNode.setEsVersion(getUpdateEsVersion(esClient));\n                    batchRequest.addNode(batchNode);\n                    continue;\n                }\n\n                //write without routing\n                batchRequest.addNode(BatchType.INDEX, indexName, typeName, po.getKey(), JSON.toJSONString(po));\n            }\n\n            for (int i = 0; i < MAX_RETRY_CNT; ++i) {\n                response = esClient.batch(batchRequest).actionGet(2, TimeUnit.MINUTES);\n                if (response == null) {\n                    continue;\n                }\n\n                if (handleErrorResponse(indexName, typeName, pos, response)) {\n                    return false;\n                }\n\n                return response.getRestStatus().getStatus() == HttpStatus.SC_OK && !response.getErrors();\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=UpdateClient||method=batchInsert||indexName={}||typeName={}||errMsg=batch insert error. \",\n                indexName, typeName, e);\n            if (response != null) {\n                LOGGER.warn(\"class=UpdateClient||method=batchInsert||indexName={}||typeName={}||errMsg=response {}\",\n                    indexName, typeName, JSON.toJSONString(response));\n            }\n\n        }\n\n        return false;\n    }\n\n    private ESVersion getUpdateEsVersion(ESClient esClient) {\n        return null != esClient ? ESVersion.valueBy(ES_VERSION_PREFIX + esClient.getEsVersion()) : null;\n    }\n\n    /**\n     * 批量删除\n     *\n     * @param indexName\n     * @param typeName\n     * @param ids\n     * @return\n     */\n    public boolean batchDelete(String indexName, String typeName, List<String> ids) {\n        if (CollectionUtils.isEmpty(ids)) {\n            return true;\n        }\n\n        ESClient esClient = null;\n        ESBatchResponse response = null;\n        try {\n            esClient = getUpdateEsClientFromPool();\n            if (esClient == null) {\n                return false;\n            }\n\n            ESBatchRequest batchRequest = new ESBatchRequest();\n            for (String id : ids) {\n                batchRequest.addNode(BatchType.DELETE, indexName, typeName, id, \"\");\n            }\n\n            for (int i = 0; i < MAX_RETRY_CNT; ++i) {\n                response = esClient.batch(batchRequest).actionGet(2, TimeUnit.MINUTES);\n                if (response == null) {\n                    continue;\n                }\n\n                return response.getRestStatus().getStatus() == HttpStatus.SC_OK && !response.getErrors();\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=UpdateClient||method=batchDelete||indexName={}||typeName={}||errMsg=batch delete error. \",\n                indexName, typeName, e);\n            if (response != null) {\n                LOGGER.warn(\"class=UpdateClient||method=batchDelete||indexName={}||typeName={}||errMsg=response {}\",\n                    indexName, typeName, JSON.toJSONString(response));\n            }\n\n        }\n\n        return false;\n    }\n\n    /**\n     * 批量更新\n     *\n     * @param indexName\n     * @param typeName\n     * @param pos\n     * @return\n     */\n    public boolean batchUpdate(String indexName, String typeName, List<? extends BaseESPO> pos) {\n        if (CollectionUtils.isEmpty(pos)) {\n            return true;\n        }\n\n        ESClient esClient = null;\n        ESBatchResponse response = null;\n        try {\n            esClient = getUpdateEsClientFromPool();\n            if (esClient == null) {\n                return false;\n            }\n\n            ESBatchRequest batchRequest = new ESBatchRequest();\n            for (BaseESPO po : pos) {\n                batchRequest.addNode(BatchType.UPDATE, indexName, typeName, po.getKey(), JSON.toJSONString(po));\n            }\n\n            for (int i = 0; i < MAX_RETRY_CNT; ++i) {\n                response = esClient.batch(batchRequest).actionGet(2, TimeUnit.MINUTES);\n                if (response == null) {\n                    continue;\n                }\n                //todo 存在失败的情况需要解析 缺陷\n                return response.getRestStatus().getStatus() == HttpStatus.SC_OK && !response.getErrors();\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=UpdateClient||method=batchUpdate||indexName={}||typeName={}||errMsg=batch update error. \",\n                indexName, typeName, e);\n            if (response != null) {\n                LOGGER.warn(\"class=UpdateClient||method=batchUpdate||indexName={}||typeName={}||errMsg=response {}\",\n                    indexName, typeName, JSON.toJSONString(response));\n            }\n\n        }\n\n        return false;\n    }\n\n    /**\n     * 刷新索引\n     *\n     * @param indexName\n     * @return\n     */\n    public boolean refreshIndex(String indexName) {\n        if (StringUtils.isBlank(indexName)) {\n            return false;\n        }\n\n        ESClient esClient = null;\n        try {\n            esClient = getUpdateEsClientFromPool();\n            if (esClient == null) {\n                return false;\n            }\n\n            ESIndicesRefreshIndexRequest request = new ESIndicesRefreshIndexRequest();\n            request.setIndex(indexName);\n\n            ESIndicesRefreshIndexResponse response = null;\n            response = esClient.admin().indices().refreshIndex(request).actionGet(10, TimeUnit.SECONDS);\n\n            return response.getRestStatus().getStatus() == HttpStatus.SC_OK;\n        } catch (Exception e) {\n            LOGGER.warn(\"class=UpdateClient||method=refreshIndex||indexName={}||errMsg=refresh index error. \",\n                indexName, e);\n        }\n\n        return false;\n    }\n\n    /**************************************** private method ****************************************************/\n    /**\n     * 从更新es http 客户端连接池找那个获取\n     *\n     * @return\n     */\n    private ESClient getUpdateEsClientFromPool() {\n        ESClient esClient = null;\n        try {\n            //这里获取当前轮询的次数，如果次数超过一定阈值则置为 0 （暂定阈值为client数量的10倍）\n            int flag = esClientCounter.getAndIncrement();\n            if (flag > clientCount * 5) {\n                esClientCounter.lazySet(0);\n            }\n            //获取真正的esClient下标\n            int currentIndex = flag % clientCount;\n            esClient = updateClientPool.get(currentIndex);\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=ESUpdateClient||method=getUpdateEsClientFromPool||errMsg=fail to get es client from pool：\", e);\n        }\n        if (esClient == null) {\n            LOGGER.error(\n                \"class=ESUpdateClient||method=getUpdateEsClientFromPool||errMsg=fail to get es client from pool\");\n        }\n\n        return esClient;\n    }\n\n    private ESClient buildEsClient(String address, String password, String clusterName) {\n        if (StringUtils.isBlank(address)) {\n            return null;\n        }\n\n        ESClient esClient = new ESClient();\n        try {\n            String[] httpAddressArray = StringUtils.splitByWholeSeparatorPreserveAllTokens(address, COMMA);\n            TransportAddress[] transportAddresses = new TransportAddress[httpAddressArray.length];\n\n            for (int i = 0; i < httpAddressArray.length; ++i) {\n                String[] httpAddressAndPortArray = StringUtils\n                    .splitByWholeSeparatorPreserveAllTokens(httpAddressArray[i], \":\");\n                if (httpAddressAndPortArray != null && httpAddressAndPortArray.length == 2) {\n                    transportAddresses[i] = new InetSocketTransportAddress(\n                        new InetSocketAddress(httpAddressAndPortArray[0], Integer.valueOf(httpAddressAndPortArray[1])));\n                }\n            }\n            esClient.addTransportAddresses(transportAddresses);\n            if (StringUtils.isNotBlank(clusterName)) {\n                esClient.setClusterName(clusterName);\n            }\n\n            if (ioThreadCount > 0) {\n                esClient.setIoThreadCount(ioThreadCount);\n            }\n            if (StringUtils.isNotBlank(password)) {\n                esClient.setPassword(password);\n            }\n\n            // 配置http超时\n            esClient.setRequestConfigCallback(builder -> builder.setConnectTimeout(10000).setSocketTimeout(120000)\n                .setConnectionRequestTimeout(120000));\n            esClient.start();\n\n            return esClient;\n        } catch (Exception e) {\n            esClient.close();\n\n            LOGGER.error(\"class=ESUpdateClient||method=buildEsClient||errMsg={}||address={}\", e.getMessage(), address,\n                e);\n            return null;\n        }\n    }\n\n    /**\n     * 初始化访问es集群的客户端\n     *\n     */\n    private void setDataSourceList(List<ClusterPhyPO> dataSourceList) {\n        if (dataSourceList == null) {\n            LOGGER.error(\"class=ESUpdateClient||method=setDataSourceList||errMsg=fail to get es clusters\");\n            return;\n        }\n\n        ClusterPhyPO updateClusterDataSource = getUpdateClusterDataSource(dataSourceList);\n\n        if (updateClusterDataSource == null) {\n            LOGGER.error(\"class=UpdateClient||method=setDataSourceList||errMsg=fail to get es cluster info {}\",\n                metadataClusterName);\n            return;\n        }\n\n        // 判断地址是否发生变化\n        if (beforeHttpAddress != null && updateClusterDataSource.getHttpAddress().equals(beforeHttpAddress)) {\n            return;\n        }\n\n        // 移除以存在的客户端\n        try {\n            ESClient beforeEsClient = null;\n            Iterator<ESClient> iterator = this.updateClientPool.iterator();\n            if (iterator != null) {\n                while (iterator.hasNext()) {\n                    beforeEsClient = iterator.next();\n                    if (beforeEsClient != null) {\n                        beforeEsClient.close();\n                    }\n                    iterator.remove();\n                    LOGGER.info(\"class=UpdateClient||method=setDataSourceList||msg=remove old es client {}, {}\",\n                        metadataClusterName, beforeHttpAddress);\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=UpdateClient||method=setDataSourceList||errMsg=fail to remove old es client {}\",\n                metadataClusterName, e);\n        }\n\n        this.updateClientPool.clear();\n        beforeHttpAddress = updateClusterDataSource.getHttpAddress();\n        String pw = updateClusterDataSource.getPassword();\n\n        // 添加新的客户端\n        ESClient esClient = null;\n        for (int i = 0; i < clientCount; ++i) {\n            esClient = buildEsClient(beforeHttpAddress, pw, metadataClusterName);\n            if (esClient != null) {\n                this.updateClientPool.add(esClient);\n                LOGGER.info(\"class=UpdateClient||method=setDataSourceList||msg=add new es client {}, {}\",\n                    metadataClusterName, beforeHttpAddress);\n            }\n        }\n    }\n\n    private ClusterPhyPO getUpdateClusterDataSource(List<ClusterPhyPO> dataSourceList) {\n        ClusterPhyPO updateClusterDataSource = null;\n        for (ClusterPhyPO dataSource : dataSourceList) {\n            if (metadataClusterName.equals(dataSource.getCluster())) {\n                updateClusterDataSource = dataSource;\n                break;\n            }\n        }\n        return updateClusterDataSource;\n    }\n\n    private boolean handleErrorResponse(String indexName, String typeName, List<? extends BaseESPO> pos,\n                                        ESBatchResponse response) {\n        if (response.getErrors().booleanValue()) {\n            int errorItemIndex = 0;\n\n            if (CollectionUtils.isNotEmpty(response.getItems())) {\n                for (IndexResultItemNode item : response.getItems()) {\n                    recordErrorResponseItem(indexName, typeName, pos, errorItemIndex++, item);\n                }\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    private void recordErrorResponseItem(String indexName, String typeName, List<? extends BaseESPO> pos,\n                                         int errorItemIndex, IndexResultItemNode item) {\n        if (item.getIndex() != null && item.getIndex().getShards() != null\n            && CollectionUtils.isNotEmpty(item.getIndex().getShards().getFailures())) {\n            LOGGER.warn(\n                \"class=UpdateClient||method=batchInsert||indexName={}||typeName={}||errMsg=Failures: {}, content: {}\",\n                indexName, typeName, item.getIndex().getShards().getFailures().toString(),\n                JSON.toJSONString(pos.get(errorItemIndex)));\n        }\n\n        if (item.getIndex() != null && item.getIndex().getError() != null) {\n            LOGGER.warn(\n                \"class=UpdateClient||method=batchInsert||indexName={}||typeName={}||errMsg=Error: {}, content: {}\",\n                indexName, typeName, item.getIndex().getError().getReason(),\n                JSON.toJSONString(pos.get(errorItemIndex)));\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/component/ScrollResultVisitor.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.component;\n\nimport java.util.List;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/9/30 下午5:59\n * @Modified By\n *\n * 遍历scroll结果\n */\npublic interface ScrollResultVisitor<T> {\n\n    /**\n     * 处理scroll结果\n     *\n     * @return\n     */\n    void handleScrollResult(List<T> resultList);\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/config/DruidDbConfig.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.config;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.baomidou.mybatisplus.annotation.DbType;\nimport com.baomidou.mybatisplus.annotation.IdType;\nimport com.baomidou.mybatisplus.core.MybatisConfiguration;\nimport com.baomidou.mybatisplus.core.config.GlobalConfig;\nimport com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;\nimport com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;\nimport com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;\nimport javax.sql.DataSource;\nimport org.apache.ibatis.session.SqlSessionFactory;\nimport org.mybatis.spring.SqlSessionTemplate;\nimport org.mybatis.spring.annotation.MapperScan;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.core.io.support.PathMatchingResourcePatternResolver;\n\n/**\n *\n * @author d06679\n */\n@Configuration\n@MapperScan(value = \"com.didichuxing.datachannel.arius.admin.persistence.mysql\", sqlSessionFactoryRef = \"adminSqlSessionFactory\")\npublic class DruidDbConfig {\n\n    @Bean(\"adminDataSource\")\n    @Primary\n    @ConfigurationProperties(prefix = \"spring.datasource.druid\")\n    public DataSource dataSource() {\n        return new DruidDataSource();\n    }\n\n    @Bean\n    public GlobalConfig globalConfigByArius() {\n        GlobalConfig globalConfig = new GlobalConfig();\n        globalConfig.setBanner(false);\n        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();\n        dbConfig.setIdType(IdType.AUTO);\n        globalConfig.setDbConfig(dbConfig);\n        return globalConfig;\n    }\n\n    /**\n     * 分页插件\n     */\n    @Bean\n    public MybatisPlusInterceptor paginationInterceptor() {\n        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();\n        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MARIADB));\n        return interceptor;\n    }\n\n    /**\n     * 配置SqlSessionFactory.\n     *\n     * @param dataSource dataSource\n     * @return SqlSessionFactory\n     * @throws Exception Exception\n     */\n    @Bean(\"adminSqlSessionFactory\")\n    @Primary\n    public SqlSessionFactory sqlSessionFactory(@Qualifier(\"adminDataSource\") DataSource dataSource) throws Exception {\n        //将SqlSessionFactoryBean 替换为 MybatisSqlSessionFactoryBean， 否则mybatis-plus 提示 Invalid bound statement (not found)\n        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();\n        bean.setDataSource(dataSource);\n        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(\"classpath:mybatis/*.xml\"));\n        bean.setGlobalConfig(globalConfigByArius());\n        MybatisConfiguration mc = new MybatisConfiguration();\n        //查看打印sql日志\n        //org.apache.ibatis.logging.stdout.StdOutImpl.class 只能打印到控制台\n        //org.apache.ibatis.logging.slf4j.Slf4jImpl.class 打印到具体的文件中\n        mc.setLogImpl(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);\n        bean.setConfiguration(mc);\n        //添加分页插件，不加这个，分页不生效\n        bean.setPlugins(paginationInterceptor());\n        // 设置mybatis的xml所在位置\n        return bean.getObject();\n    }\n\n    @Bean({ \"adminSqlSessionTemplate\" })\n    @Primary\n    public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier(\"adminSqlSessionFactory\") SqlSessionFactory sessionFactory) {\n        return new SqlSessionTemplate(sessionFactory);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/constant/ESOperateConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.constant;\n\npublic class ESOperateConstant {\n\n    private ESOperateConstant() {\n    }\n\n    /**\n     * rebalance配置名字\n     */\n    public static final String  REBALANCE                        = \"cluster.routing.rebalance.enable\";\n\n    /**\n     * remote-cluster\n     */\n    public static final String  REMOTE_CLUSTER_FORMAT            = \"cluster.remote.%s.seeds\";\n\n    /**\n     * 操作es超时时间 单位s\n     */\n    public static final Integer ES_OPERATE_TIMEOUT               = 30;\n    public static final Integer ES_OPERATE_MIN_TIMEOUT           = 10;\n\n    /**\n     * region 配置\n     */\n    public static final String  TEMPLATE_INDEX_INCLUDE_NODE_NAME = \"index.routing.allocation.include._name\";\n\n    /**\n     * read-only\n     */\n    public static final String  INDEX_BLOCKS_WRITE               = \"blocks.write\";\n\n    /**\n     * write-only\n     */\n    public static final String  INDEX_BLOCKS_READ                = \"blocks.read\";\n\n    /**\n     * shard配置名字\n     */\n    public static final String  INDEX_SHARD_NUM                  = \"index.number_of_shards\";\n    public static final String  INDEX_SHARD_ROUTING_NUM          = \"index.number_of_routing_size\";\n\n    /**\n     * 副本分片个数\n     */\n    public static final String  INDEX_REPLICAS_NUM               = \"number_of_replicas\";\n\n    /**\n     * 模板默认order\n     */\n    public static final Long    TEMPLATE_DEFAULT_ORDER           = 10L;\n\n    /**\n     * 通用版本role--client\n     */\n    public static final String  ES_ROLE_CLIENT                   = \"client\";\n\n    /**\n     * 高版本role——data\\client\\master\\ingest\n     */\n    public static final String  ES_ROLE_DATA                     = \"data\";\n    public static final String  ES_ROLE_COORDINATING_ONLY        = \"coordinating_only\";\n    public static final String  ES_ROLE_MASTER                   = \"master\";\n    public static final String  ES_ROLE_INGEST                   = \"ingest\";\n    public static final String  ES_ROLE_ML                       = \"ml\";\n\n    /**\n     * 低版本role--data\\master\n     */\n    public static final String  ES_ROLE_MASTER_ONLY              = \"master_only\";\n    public static final String  ES_ROLE_DATA_ONLY                = \"data_only\";\n    public static final String  ES_ROLE_MASTER_DATA              = \"master_data\";\n\n    /**\n     * 指标看板相关\n     */\n    public static final String  STATUS                           = \"status\";\n    public static final String  INDICES                          = \"indices\";\n    public static final String  COUNT                            = \"count\";\n    public static final String  SHARDS                           = \"shards\";\n    public static final String  TOTAL                            = \"total\";\n    public static final String  DOCS                             = \"docs\";\n    public static final String  STORE                            = \"store\";\n    public static final String  NODES                            = \"nodes\";\n    public static final String  OS                               = \"os\";\n    public static final String  MEM                              = \"mem\";\n    public static final String  FS                               = \"fs\";\n    public static final String  JVM                              = \"jvm\";\n    public static final String  TOTAL_IN_BYTES                   = \"total_in_bytes\";\n    public static final String  FREE_IN_BYTES                    = \"free_in_bytes\";\n    public static final String  SIZE_IN_BYTES                    = \"size_in_bytes\";\n    public static final String  USED_IN_BYTES                    = \"used_in_bytes\";\n    public static final String  FREE_PERCENT                     = \"free_percent\";\n    public static final String  USED_PERCENT                     = \"used_percent\";\n    public static final String  HEAP_USED_IN_BYTES               = \"heap_used_in_bytes\";\n    public static final String  HEAP_MAX_IN_BYTES                = \"heap_max_in_bytes\";\n    public static final String  PENDING_TASKS                    = \"pending_tasks\";\n\n    /**\n     * 索引管理\n     */\n    public static final String  READ                             = \"index.blocks.read\";\n    public static final String  WRITE                            = \"index.blocks.write\";\n    public static final String  BLOCKS                           = \"blocks\";\n    public static final String  INDEX                            = \"index\";\n    public static final String  DEFAULTS                         = \"defaults\";\n    public static final String  PRIMARY                          = \"p\";\n    public static final String  INDEX_SETTING_PRE                = \"index.\";\n\n    /**\n     * task管理\n     */\n    public static final String  ACTION                           = \"action\";\n    public static final String  TASK_ID                          = \"task_id\";\n    public static final String  PARENT_TASK_ID                   = \"parent_task_id\";\n    public static final String  TYPE                             = \"type\";\n    public static final String  START_TIME                       = \"start_time\";\n    public static final String  RUNNING_TIME                     = \"running_time\";\n    public static final String  IP                               = \"ip\";\n    public static final String  NODE                             = \"node\";\n    public static final String  DESCRIPTION                      = \"description\";\n    public static final String  UNASSIGN                         = \"unassign\";\n\n    /**\n     * version\n     */\n    public static final String  VERSION_NUMBER                   = \"number\";\n    public static final String  VERSION_INNER_NUMBER             = \"inner_version\";\n    public static final String  VERSION                          = \"version\";\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/BaseESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NullESClientException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ParsingExceptionUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESGatewayClient;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpClient;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESUpdateClient;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.datacentre.DataCentreUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslLoaderUtil;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * 直接操作es集群的dao\n */\npublic class BaseESDAO {\n    protected static final ILog LOGGER = LogFactory.getLog(BaseESDAO.class);\n    public static final String REASON    = \"reason\";\n    public static final String ERROR     = \"error\";\n    public static final String TYPE      = \"type\";\n    public static final String CAUSED_BY = \"caused_by\";\n\n    /**\n     * 索引名数据中心加载工具类\n     */\n    @Autowired\n    protected DataCentreUtil    dataCentreUtil;\n    /**\n     * 加载查询语句工具类\n     */\n    @Autowired\n    protected DslLoaderUtil     dslLoaderUtil;\n    /**\n     * 查询es客户端\n     */\n    @Autowired\n    protected ESGatewayClient   gatewayClient;\n    /**\n     * 更新es客户端\n     */\n    @Autowired\n    protected ESUpdateClient    updateClient;\n\n    /**\n     * Arius操作es集群的client\n     */\n    @Autowired\n    protected ESOpClient        esOpClient;\n\n    public DirectResponse getDirectResponse(String clusterName, String methodType, String url) throws ESOperateException {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        DirectResponse directResponse = new DirectResponse();\n        if (esClient == null) {\n            LOGGER.error(\"class=BaseESDAO||method=getDirectResponse||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            throw new NullESClientException(clusterName);\n        }\n\n        DirectRequest directRequest = new DirectRequest(methodType, url);\n        try {\n            return esClient.direct(directRequest).actionGet(30, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.error(\"class=BaseESDAO||method=getDirectResponse||clusterName={}||errMsg=fail to direct\",\n                clusterName, e.getMessage(), e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        directResponse.setRestStatus(RestStatus.SERVICE_UNAVAILABLE);\n        return directResponse;\n    }\n\n    public <T> List<T> commonGet(String clusterName, String directRequestContent, Class<T> clazz) throws ESOperateException {\n        DirectResponse directResponse = getDirectResponse(clusterName, \"Get\", directRequestContent);\n        List<T> list = Lists.newArrayList();\n        if (directResponse.getRestStatus() == RestStatus.OK\n            && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n            try {\n                List<T> resList = ConvertUtil.str2ObjArrayByJson(directResponse.getResponseContent(), clazz);\n                list.addAll(resList);\n            } catch (Exception e) {\n                LOGGER.error(\"class=BaseESDAO||method=commonGet||cluster={}||directRequestContent={}||\"\n                             + \"clazzName={}||errMsg=str convert obj error:{}\",\n                    clusterName, directRequestContent, clazz.getName(), e.getMessage(), e);\n                ParsingExceptionUtils.abnormalTermination(e);\n            }\n        }\n        return list;\n    }\n    \n\n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/cluster/ESClusterDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterQuickCommandMethodsEnum.ABNORMAL_SHARD_RETRY;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterQuickCommandMethodsEnum.CLEAR_FIELDDATA_MEMORY;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterQuickCommandMethodsEnum.HOT_THREAD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterQuickCommandMethodsEnum.PENDING_TASK;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterQuickCommandMethodsEnum.TASK_MISSION_ANALYSIS;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.*;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.NodeAllocationInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.NodeAttrInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESResponsePluginInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting.ESClusterGetSettingsAllAction;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting.ESClusterGetSettingsAllRequest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting.ESClusterGetSettingsAllResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ECSegmentOnIp;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterTaskStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.stats.ESClusterThreadPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NullESClientException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ParsingExceptionUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.TimeValueUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.request.cat.ESCatAction;\nimport com.didiglobal.knowframework.elasticsearch.client.request.cat.ESCatRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.cluster.getsetting.ESClusterGetSettingsRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.cluster.health.ESClusterHealthRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.cluster.updatesetting.ESClusterUpdateSettingsRequestBuilder;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.stats.IndicesStatsLevel;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cat.ESCatResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.getsetting.ESClusterGetSettingsResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodes.ClusterNodeInfo;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodes.ESClusterNodesResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodessetting.ClusterNodeSettings;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodessetting.ESClusterNodesSettingResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ESClusterNodesStatsResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.updatesetting.ESClusterUpdateSettingsResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.getalias.ESIndicesGetAliasResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.utils.JsonUtils;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.ElasticsearchTimeoutException;\nimport org.elasticsearch.common.unit.ByteSizeValue;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author d06679\n */\n@Repository\npublic class ESClusterDAO extends BaseESDAO {\n    private final static String REMOTE_TARGET_CLUSTER=\"_remote/info?filter_path=%s.%s\";\n    private final static String REMOTE_TARGET_CLUSTER_COUNT=\"%s:*/_count?ignore_unavailable=true\";\n    private final static String CONNECTED=\"connected\";\n\n    /**\n     * 配置集群re balance开关\n     * @param cluster 集群名称\n     * @param value  all /  none\n     * @return 成功 true   失败 false\n     */\n    public boolean configReBalanceOperate(String cluster, String value) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (null == client) {\n            LOGGER.warn(\n                    \"class={}||method=configReBalanceOperate||clusterName={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster);\n            throw new NullESClientException(cluster);\n        }\n        try {\n            ESClusterUpdateSettingsResponse response = client.admin().cluster().prepareUpdateSettings()\n                    .addPersistent(REBALANCE, value).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\"class={}||method=configReBalanceOperate||clusterName={}||value={}\",\n                    getClass().getSimpleName(), cluster, value,e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 获取集群 persistent 配置\n     * @param cluster 集群名称\n     * @return map<flat_setting_name, setting_value>\n     */\n    public Map<String, Object> getPersistentClusterSettings(String cluster) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (null == client) {\n            LOGGER.warn(\n                    \"class={}||method=getPersistentClusterSettings||clusterName={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster);\n            throw new NullESClientException(cluster);\n        }\n\n        try {\n            ESClusterGetSettingsRequest request = new ESClusterGetSettingsRequest();\n            ESClusterGetSettingsResponse response = client.admin().cluster().getSetting(request)\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n            return JsonUtils.flatObject(response.getPersistentObj());\n        } catch (Exception e) {\n            LOGGER.error(\"class={}||method=getPersistentClusterSettings||clusterName={}\",\n                    getClass().getSimpleName(), cluster,e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return null;\n    }\n\n    /**\n     * 获取集群配置\n     * @param cluster 集群名称\n     * @return response\n     */\n    public ESClusterGetSettingsAllResponse getClusterSetting(String cluster) throws ESOperateException {\n        ESClusterGetSettingsAllResponse response = null;\n        ESClient client = esOpClient.getESClient(cluster);\n        if (null == client) {\n            throw new NullESClientException(cluster);\n        }\n        try {\n        \n            response = client.admin().cluster()\n                    .execute(ESClusterGetSettingsAllAction.INSTANCE, new ESClusterGetSettingsAllRequest())\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterDAO||method=getClusterSetting||clusterName={}\", cluster, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return response;\n    }\n\n    /**\n     * put-setting\n     * @param cluster 集群\n     * @param remoteCluster 集群名字\n     * @param tcpAddresses 地址\n     * @return true/false\n     */\n    public boolean putPersistentRemoteClusters(String cluster, String remoteCluster, List<String> tcpAddresses)\n            throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (null == client) {\n          throw new NullESClientException(cluster);\n        }\n\n        JSONArray addresses = new JSONArray();\n        addresses.addAll(tcpAddresses);\n        try {\n        \n            ESClusterUpdateSettingsResponse response = client.admin().cluster().prepareUpdateSettings()\n                    .addPersistent(remoteCluster, addresses).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        \n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterDAO||method=putPersistentRemoteClusters||clusterName={}\", cluster, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * put-setting\n     * @param cluster 集群\n     * @param configMap 配置\n     * @return true/false\n     */\n    public boolean putPersistentConfig(String cluster, Map<String, Object> configMap) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (null == client) {\n            LOGGER.warn(\"class={}||method=putPersistentConfig||clusterName={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster);\n            throw new NullESClientException(cluster);\n        }\n\n        try {\n            ESClusterUpdateSettingsRequestBuilder updateSettingsRequestBuilder = client.admin().cluster()\n                    .prepareUpdateSettings();\n\n            for (Map.Entry<String, Object> entry : configMap.entrySet()) {\n                String configName = entry.getKey();\n                updateSettingsRequestBuilder.addPersistent(configName, configMap.get(configName));\n            }\n\n            ESClusterUpdateSettingsResponse response = client.admin().cluster()\n                    .updateSetting(updateSettingsRequestBuilder.request()).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterDAO||method=putPersistentConfig||clusterName={}\", cluster,e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 获取物理集群下各个节点的插件名称列表\n     *\n     * @param cluster\n     * @return map\n     */\n    public Map<String/*nodeName*/, List<String>/*pluginName*/> getNode2PluginsMap(String cluster, Integer tryTimes) throws ESOperateException{\n        ESClient client = esOpClient.getESClient(cluster);\n        if (null == client) {\n            LOGGER.warn(\n                    \"class=ESClusterDAO||method=getNode2PluginsMap||clusterName={}||errMsg=esClient is null\",\n                    cluster);\n            throw new NullESClientException(cluster);\n        }\n\n        ESCatRequest esCatRequest = new ESCatRequest();\n        esCatRequest.setUri(\"plugins\");\n        ESCatResponse esCatResponse = null;\n        try {\n            do {\n                esCatResponse = client.admin().cluster().execute(ESCatAction.INSTANCE, esCatRequest)\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            } while (tryTimes-- > 0 && null == esCatResponse);\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=ESClusterDAO||method=getNode2PluginsMap||clusterName={}\" + \"||errMsg=can't get node  plugin\",\n                cluster);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n\n        return Optional.ofNullable(esCatResponse).map(ESCatResponse::getResponse).map(Object::toString)\n            .map(esCatResponseString2ESResponsePluginInfoListFunc).map(eSResponsePluginInfoList2MapFunc).orElse(null);\n\n    }\n    \n    /**\n     * 它获取集群的插件。\n     *\n     * @param cluster 要查询的集群名称\n     * @return 插件列表。\n     */\n    public List<ESResponsePluginInfo> getPlugins(String cluster) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (null == client) {\n            LOGGER.warn(\n                \"class=ESClusterDAO||method=getNode2PluginsMap||clusterName={}||errMsg=esClient is null\",\n                cluster);\n            throw new NullESClientException(cluster);\n        }\n        \n        ESCatRequest esCatRequest = new ESCatRequest();\n        esCatRequest.setUri(\"plugins\");\n        ESCatResponse esCatResponse = null;\n        try {\n            esCatResponse = client.admin().cluster().execute(ESCatAction.INSTANCE, esCatRequest)\n                .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=ESClusterDAO||method=getNode2PluginsMap||clusterName={}\"\n                    + \"||errMsg=can't get node  plugin\",\n                cluster);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return Optional.ofNullable(esCatResponse).map(ESCatResponse::getResponse)\n            .map(Object::toString)\n            .map(esCatResponseString2ESResponsePluginInfoListFunc).orElse(Collections.emptyList());\n    }\n\n    \n\n    /**\n     * 获取物理集群下各个节点的资源设置信息\n     * @param cluster 物理集群名称\n     * @return 集群下的节点资源使用信息列表\n     */\n    public List<NodeAllocationInfo> getNodeAllocationInfoByCluster(String cluster, Integer tryTimes) throws ESOperateException {\n        ESClient esClient = esOpClient.getESClient(cluster);\n        if (esClient == null) {\n            LOGGER.warn(\n                \"class=ESClusterDAO||method=getNodeAllocationInfoByCluster||clusterName={}\" + \"||errMsg=client is null\",\n                cluster);\n            throw new NullESClientException(cluster);\n        }\n\n        ESCatRequest esCatRequest = new ESCatRequest();\n        esCatRequest.setUri(\"allocation\");\n        ESCatResponse esCatResponse = null;\n        try {\n            do {\n                esCatResponse = esClient.admin().cluster().execute(ESCatAction.INSTANCE, esCatRequest)\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            } while (tryTimes-- > 0 && null == esCatResponse);\n\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESClusterDAO||method=getNodeAllocationInfoByCluster||clusterName={}\"\n                        + \"||errMsg=can't get allocation info\",\n                cluster);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return Optional.ofNullable(esCatResponse).map(ESCatResponse::getResponse).map(Object::toString)\n            .map(esCatResponseString2NodeAllocationInfoListFunc).orElse(null);\n    }\n\n    private final Function<String, List<NodeAllocationInfo>> esCatResponseString2NodeAllocationInfoListFunc = esCatResponse -> JSON\n        .parseArray(esCatResponse, NodeAllocationInfo.class);\n\n    /**\n     * 获取集群中索引的别名信息\n     *\n     * @param cluster\n     * @param tryTimes\n     * @return\n     */\n    public ESIndicesGetAliasResponse getClusterAlias(String cluster, Integer tryTimes) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\n                    \"class=ESClusterDAO||method=getClusterAlias||clusterName={}\" + \"||errMsg=client is null\",\n                    cluster);\n            throw new NullESClientException(cluster);\n        }\n        ESIndicesGetAliasResponse esIndicesGetAliasResponse = null;\n        try {\n            do {\n                esIndicesGetAliasResponse = client.admin().indices().prepareAlias().execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.MINUTES);\n            } while (tryTimes-- > 0 && null == esIndicesGetAliasResponse);\n            return esIndicesGetAliasResponse;\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterDAO||method=getClusterAlias||clusterName={}||errMsg=query error. \", cluster,\n                e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return null;\n    }\n\n    /**\n    * 获取集群状态信息\n    *\n    * @param cluster\n    * @return\n    */\n    public ESClusterHealthResponse getClusterHealth(String cluster, Integer tryTimes) throws ESOperateException {\n        ESClient esClient = esOpClient.getESClient(cluster);\n        if (esClient == null) {\n            LOGGER.error(\"class=ESClusterDAO||method=getClusterHealth||clusterName={}||errMsg=esClient is null\",\n                cluster);\n            throw new NullESClientException(cluster);\n        }\n        ESClusterHealthResponse esClusterHealthResponse = null;\n        Long minTimeoutNum = 1L;\n        Long maxTimeoutNum = tryTimes.longValue();\n        try {\n            ESClusterHealthRequest request = new ESClusterHealthRequest();\n            do {\n                esClusterHealthResponse = esClient.admin().cluster().health(request)\n                    .actionGet(/*降低因为抖动导致的等待时常,等待时常从低到高进行重试*/minTimeoutNum * ES_OPERATE_MIN_TIMEOUT, TimeUnit.SECONDS);\n                minTimeoutNum++;\n                if (minTimeoutNum > maxTimeoutNum) {\n                    minTimeoutNum = maxTimeoutNum;\n                }\n            } while (tryTimes-- > 0 && null == esClusterHealthResponse);\n            return esClusterHealthResponse;\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterDAO||method=getClusterHealth||clusterName={}||errMsg=query error. \", cluster,\n                e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return null;\n    }\n\n    public Map<String, ClusterNodeSettings> getPartOfSettingsByCluster(String cluster, Integer tryTimes) throws ESOperateException {\n        ESClusterNodesSettingResponse response = null;\n\n        ESClient client = esOpClient.getESClient(cluster);\n        if (null == client) {\n            LOGGER.error(\"class=ESClusterDAO||method=getPartOfSettingsByCluster||clusterName={}||errMsg=esClient is null\",\n                    cluster);\n            throw new NullESClientException(cluster);\n        }\n\n        try {\n\n            do {\n                response = client.admin().cluster().prepareNodesSetting().execute().actionGet(ES_OPERATE_TIMEOUT,\n                    TimeUnit.SECONDS);\n            } while (tryTimes-- > 0 && null == response);\n\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESClusterDAO||method=getPartOfSettingsByCluster||cluster={}||mg=get es setting fail\",\n                cluster, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return Optional.ofNullable(response).map(ESClusterNodesSettingResponse::getNodes).orElse(null);\n    }\n\n    /**\n    * 获取全量ES集群nodeSetting\n    * @param cluster\n    * @return\n    */\n    public Map<String, ClusterNodeInfo> getAllSettingsByCluster(String cluster, Integer tryTimes) throws ESOperateException {\n        ESClusterNodesResponse response = null;\n\n        ESClient client = esOpClient.getESClient(cluster);\n        if (null == client) {\n            LOGGER.warn(\"class=ESClusterDAO||method=getAllSettingsByCluster||cluster={}||mg=ESClient is empty\",\n                    cluster);\n            throw new NullESClientException(cluster);\n        }\n\n        try {\n            do {\n                response = client.admin().cluster().prepareNodes().execute().actionGet(ES_OPERATE_TIMEOUT,\n                    TimeUnit.SECONDS);\n            } while (tryTimes-- > 0 && null == response);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESClusterDAO||method=getAllSettingsByCluster||cluster={}||mg=get es setting fail\",\n                cluster, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return Optional.ofNullable(response).map(ESClusterNodesResponse::getNodes).orElse(null);\n    }\n\n    public String getESVersionByCluster(String cluster, Integer tryTimes) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        String esVersion = null;\n        if (Objects.isNull(client)) {\n            LOGGER.error(\"class=ESClusterDAO||method=getESVersionByCluster||clusterName={}||errMsg=esClient is null\",\n                cluster);\n            throw new NullESClientException(cluster);\n        }\n        DirectResponse directResponse = null;\n        try {\n            DirectRequest directRequest = new DirectRequest(\"GET\", \"\");\n\n            do {\n                directResponse = client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            } while (tryTimes-- > 0 && null == directResponse);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESClusterDAO||method=getESVersionByCluster||cluster={}||mg=get es segments fail\",\n                cluster, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        if (directResponse.getRestStatus() == RestStatus.OK\n            && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n            esVersion = (String) JSONObject.parseObject(directResponse.getResponseContent()).getJSONObject(\"version\")\n                .get(\"number\");\n        }\n        return esVersion;\n    }\n\n    /**\n     * 获取集群节点ip下的segment数目\n     *\n     * @param clusterName 集群名称\n     * @return\n     */\n    public List<ECSegmentOnIp> getSegmentsOfIpByCluster(String clusterName) throws ESOperateException{\n        ESClient client = esOpClient.getESClient(clusterName);\n        List<ECSegmentOnIp> ecSegmentOnIps = null;\n        if (Objects.isNull(client)) {\n            LOGGER.error(\"class=ESClusterDAO||method=getClusterStats||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            throw new NullESClientException(clusterName);\n        }\n        try {\n            DirectRequest directRequest = new DirectRequest(\"GET\", \"_cat/nodes?v&h=sc,ip&format=json\");\n            DirectResponse directResponse = client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                ecSegmentOnIps = JSONArray.parseArray(directResponse.getResponseContent(), ECSegmentOnIp.class);\n            }\n            return ecSegmentOnIps;\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESClusterDAO||method=getSegmentsOfIpByCluster||cluster={}||mg=get es segments fail\",\n                clusterName, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return new ArrayList<>();\n    }\n\n    public ESClusterStatsResponse getClusterStats(String clusterName) throws ESOperateException {\n        ESClusterStatsResponse responses = initESClusterStatsResponse();\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        if (Objects.isNull(esClient)) {\n            LOGGER.error(\"class=ESClusterDAO||method=getClusterStats||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            throw new NullESClientException(clusterName);\n        }\n\n        try {\n            DirectRequest directRequest = new DirectRequest(\"GET\", \"_cluster/stats\");\n            DirectResponse directResponse = esClient.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n            //获取\n            DirectRequest directHealthRequest = new DirectRequest(\"GET\", \"_cat/health?format=json\");\n            DirectResponse directHealthResponse = esClient.direct(directHealthRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n            if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n\n                if (directHealthResponse.getRestStatus() == RestStatus.OK\n                        && StringUtils.isNoneBlank(directHealthResponse.getResponseContent())) {\n\n                    JSONArray jsonArray = JSON.parseArray(directHealthResponse.getResponseContent());\n                    jsonArray.stream()\n                            .filter(Objects::nonNull)\n                            .filter(j -> j instanceof JSONObject)\n                            .map(j -> (JSONObject) j)\n                            .map(jsonObject -> Long.parseLong(jsonObject.getString(SHARDS)) +\n                                    Long.parseLong(jsonObject.getString(UNASSIGN)))\n                            .findFirst()\n                            .ifPresent(responses::setTotalShard);\n                    jsonArray.stream()\n                            .filter(Objects::nonNull)\n                            .filter(j -> j instanceof JSONObject)\n                            .map(j -> (JSONObject) j)\n                            .map(jsonObject -> Long.parseLong(jsonObject.getString(PENDING_TASKS)))\n                            .findFirst()\n                            .ifPresent(responses::setPendingTasks);\n                    jsonArray.stream()\n                            .filter(Objects::nonNull)\n                            .filter(j -> j instanceof JSONObject)\n                            .map(j -> (JSONObject) j)\n                            .map(jsonObject -> Long.parseLong(jsonObject.getString(UNASSIGN)))\n                            .findFirst()\n                            .ifPresent(responses::setUnassignedShardNum);\n                }\n\n                JSONObject jsonObject = JSON.parseObject(directResponse.getResponseContent());\n                responses.setStatus(jsonObject.getObject(STATUS, String.class));\n\n                JSONObject indicesObj = jsonObject.getJSONObject(INDICES);\n                responses.setIndexCount(indicesObj.getLongValue(COUNT));\n\n\n                JSONObject docsObj = indicesObj.getJSONObject(DOCS);\n                responses.setDocsCount(docsObj.getLongValue(COUNT));\n\n                JSONObject storeObj = indicesObj.getJSONObject(STORE);\n                responses.setIndicesStoreSize(new ByteSizeValue(storeObj.getLongValue(SIZE_IN_BYTES)));\n\n                JSONObject nodesObj = jsonObject.getJSONObject(NODES);\n                JSONObject nodesCountObj = nodesObj.getJSONObject(COUNT);\n                responses.setTotalNodes(nodesCountObj.getLongValue(TOTAL));\n\n                setRoleNumberToResponses(responses, nodesCountObj);\n\n                JSONObject osObj = nodesObj.getJSONObject(OS);\n                JSONObject memObj = osObj.getJSONObject(MEM);\n                responses.setMemTotal(new ByteSizeValue(memObj.getLongValue(TOTAL_IN_BYTES)));\n                responses.setMemFree(new ByteSizeValue(memObj.getLongValue(FREE_IN_BYTES)));\n                responses.setMemUsed(new ByteSizeValue(memObj.getLongValue(USED_IN_BYTES)));\n                responses.setMemFreePercent(memObj.getIntValue(FREE_PERCENT));\n                responses.setMemUsedPercent(memObj.getIntValue(USED_PERCENT));\n\n                JSONObject fsObj = nodesObj.getJSONObject(FS);\n                responses.setTotalFs(new ByteSizeValue(fsObj.getLongValue(TOTAL_IN_BYTES)));\n                responses.setFreeFs(new ByteSizeValue(fsObj.getLongValue(FREE_IN_BYTES)));\n\n                JSONObject jvmObj = nodesObj.getJSONObject(JVM);\n                JSONObject jvmHeapObj = jvmObj.getJSONObject(MEM);\n                responses.setTotalHeapMem(new ByteSizeValue(jvmHeapObj.getLongValue(HEAP_MAX_IN_BYTES)));\n                responses.setUsedHeapMem(new ByteSizeValue(jvmHeapObj.getLongValue(HEAP_USED_IN_BYTES)));\n            }\n\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterDAO||method=getClusterStats||clusterName={}||errMsg=fail to get\", clusterName,\n                e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n\n        return responses;\n    }\n\n    public List<ESClusterTaskStatsResponse> getClusterTaskStats(String clusterName) throws ESOperateException {\n        List<ESClusterTaskStatsResponse> responses = Lists.newArrayList();\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        if (null == esClient) {\n            LOGGER.error(\"class=ESClusterDAO||method=getClusterTaskStats||clusterName={}||errMsg=esClient is null\", clusterName);\n            throw new NullESClientException(clusterName);\n        }\n\n        try {\n            DirectRequest taskStatsRequest = new DirectRequest(\"GET\", \"_cat/tasks?v&detailed&format=json\");\n            DirectResponse directResponse = esClient.direct(taskStatsRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                JSONArray jsonArray = JSON.parseArray(directResponse.getResponseContent());\n                for (int i = 0; i < jsonArray.size(); i++) {\n                    ESClusterTaskStatsResponse response = new ESClusterTaskStatsResponse();\n                    JSONObject js = jsonArray.getJSONObject(i);\n                    response.setAction(js.getString(ACTION));\n                    response.setDescription(js.getString(DESCRIPTION));\n                    response.setIp(js.getString(IP));\n                    response.setNode(js.getString(NODE));\n                    response.setTaskId(js.getString(TASK_ID));\n                    response.setStartTime(Long.parseLong(js.getString(START_TIME)));\n                    response.setType(js.getString(TYPE));\n                    response.setParentTaskId(js.getString(PARENT_TASK_ID));\n                    response\n                        .setRunningTime(TimeValueUtil.parseTimeValue(js.getString(RUNNING_TIME), \"task\").getMillis());\n                    response.setRunningTimeString(js.getString(RUNNING_TIME));\n                    responses.add(response);\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterDAO||method=getClusterTaskStats||clusterName={}||errMsg=fail to get\",\n                clusterName, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n\n        return responses;\n    }\n\n    private void setRoleNumberToResponses(ESClusterStatsResponse responses, JSONObject nodesCountObj) {\n        // role--client/data/master的数目初始化\n        long clientNum, dataNum, masterNum;\n\n        // 设置dataNumber和masterNumber，兼容2.3.3低版本的es集群\n        if (nodesCountObj.get(ES_ROLE_MASTER_ONLY) != null) {\n            // 低版本中存在master_only的key\n            dataNum = nodesCountObj.getLongValue(ES_ROLE_DATA_ONLY) + nodesCountObj.getLongValue(ES_ROLE_MASTER_DATA);\n            masterNum = nodesCountObj.getLongValue(ES_ROLE_MASTER_ONLY)\n                        + nodesCountObj.getLongValue(ES_ROLE_MASTER_DATA);\n            clientNum = nodesCountObj.getLongValue(ES_ROLE_CLIENT);\n        } else {\n            // 高版本的角色节点数目设置\n            dataNum = nodesCountObj.getLongValue(ES_ROLE_DATA);\n            masterNum = nodesCountObj.getLongValue(ES_ROLE_MASTER);\n            clientNum = nodesCountObj.getLongValue(TOTAL) - dataNum - masterNum;\n        }\n\n        // 对于clientNumber的极端值处理，处理特殊情况, 单实例全部角色\n        if (clientNum < 0) {\n            clientNum = 0;\n        }\n\n        responses.setNumberClientNodes(clientNum);\n        responses.setNumberDataNodes(dataNum);\n        responses.setNumberMasterNodes(masterNum);\n        responses.setNumberIngestNodes(nodesCountObj.getLongValue(ES_ROLE_INGEST));\n        responses.setNumberCoordinatingOnly(nodesCountObj.getLongValue(ES_ROLE_COORDINATING_ONLY));\n    }\n\n    private ESClusterStatsResponse initESClusterStatsResponse() {\n        ESClusterStatsResponse responses = new ESClusterStatsResponse();\n        responses.setStatus(ClusterHealthEnum.UNKNOWN.getDesc());\n        responses.setMemUsed(new ByteSizeValue(0));\n        responses.setMemFree(new ByteSizeValue(0));\n        responses.setMemTotal(new ByteSizeValue(0));\n        responses.setTotalFs(new ByteSizeValue(0));\n        responses.setFreeFs(new ByteSizeValue(0));\n\n        return responses;\n    }\n\n    /**\n     * 获取物理集群动态配置中的attr属性\n     * @param clusterName 物理集群名称\n     * @return 集群配置下的attributesInfo属性集合\n     */\n    public List<NodeAttrInfo> syncGetAllNodesAttributes(String clusterName) {\n        ESClient client = esOpClient.getESClient(clusterName);\n        if (Objects.isNull(client)) {\n            LOGGER.error(\"class=ESClusterDAO||method=getClusterStats||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            return null;\n        }\n\n        try {\n            ESCatRequest esCatRequest = new ESCatRequest();\n            esCatRequest.setUri(\"nodeattrs?h=node,attr,value&s=attr:desc\");\n\n            ESCatResponse esCatResponse = client.admin().cluster().execute(ESCatAction.INSTANCE, esCatRequest)\n                .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return JSON.parseArray(esCatResponse.getResponse().toString(), NodeAttrInfo.class);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterDAO||method=syncGetAllNodesAttributes||cluster={}||errMsg=attributes is null\",\n                clusterName, e);\n        }\n\n        return null;\n    }\n\n    /**\n     * 获取物理集群线程池相关统计信息\n     * @param cluster 物理集群的名称\n     * @return 集群线程池ESClusterThreadStats 属性\n     */\n    public List<ESClusterThreadPO> syncGetThreadStatsByCluster(String cluster) {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (Objects.isNull(client)) {\n            LOGGER.error(\n                \"class=ESClusterDAO||method=syncGetThreadStatsByCluster||clusterName={}||errMsg=esClient is null\",\n                cluster);\n            return null;\n        }\n\n        try {\n            ESCatRequest esCatRequest = new ESCatRequest();\n            esCatRequest.setUri(\"thread_pool\");\n\n            ESCatResponse esCatResponse = client.admin().cluster().execute(ESCatAction.INSTANCE, esCatRequest)\n                .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            if (esCatResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(esCatResponse.getResponse().toString())) {\n                return ConvertUtil.str2ObjArrayByJson(esCatResponse.getResponse().toString(), ESClusterThreadPO.class);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=ESClusterDAO||method=syncGetThreadStatsByCluster||cluster={}||errMsg=attributes is null\",\n                cluster, e);\n        }\n        return null;\n    }\n\n    public ESClusterHealthResponse getClusterHealthAtIndicesLevel(String physicalClusterName) {\n        try {\n            ESClient esClient = esOpClient.getESClient(physicalClusterName);\n            ESClusterHealthRequest request = new ESClusterHealthRequest();\n            return esClient.admin().cluster().health(request.setLevel(IndicesStatsLevel.INDICES))\n                .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=ClusterClientPool||method=getClusterHealthAtIndicesLevel||clusterName={}||errMsg=query error. \",\n                physicalClusterName, e);\n        }\n        return null;\n    }\n\n    public String pendingTask(String clusterName) {\n        ESClient client = esOpClient.getESClient(clusterName);\n        String ecSegmentsOnIps = null;\n        if (Objects.isNull(client)) {\n            LOGGER.error(\"class=ESClusterDAO||method=pendingTask||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            return null;\n        }\n        try {\n            DirectRequest directRequest = new DirectRequest(PENDING_TASK.getMethod(), PENDING_TASK.getUri());\n            DirectResponse directResponse = client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                ecSegmentsOnIps = directResponse.getResponseContent();\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESClusterDAO||method=pendingTask||cluster={}||mg=get es segments fail\", clusterName, e);\n            return null;\n        }\n        return ecSegmentsOnIps;\n    }\n\n    public String taskMission(String clusterName) {\n        ESClient client = esOpClient.getESClient(clusterName);\n        String result = null;\n        if (Objects.isNull(client)) {\n            LOGGER.error(\"class=ESClusterDAO||method=taskMission||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            return null;\n        }\n        try {\n            DirectRequest directRequest = new DirectRequest(TASK_MISSION_ANALYSIS.getMethod(),\n                TASK_MISSION_ANALYSIS.getUri());\n            DirectResponse directResponse = client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                result = directResponse.getResponseContent();\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESClusterDAO||method=taskMission||cluster={}||mg=get es segments fail\", clusterName, e);\n            return null;\n        }\n        return result;\n    }\n\n    public String hotThread(String clusterName) {\n        ESClient client = esOpClient.getESClient(clusterName);\n        String result = null;\n        if (Objects.isNull(client)) {\n            LOGGER.error(\"class=ESClusterDAO||method=hotThread||clusterName={}||errMsg=esClient is null\", clusterName);\n            return null;\n        }\n        try {\n            DirectRequest directRequest = new DirectRequest(HOT_THREAD.getMethod(), HOT_THREAD.getUri());\n            DirectResponse directResponse = client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                result = directResponse.getResponseContent();\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESClusterDAO||method=hotThread||cluster={}||mg=get es segments fail\", clusterName, e);\n            return null;\n        }\n        return result;\n    }\n\n    public String clearFieldDataMemory(String clusterName) {\n        ESClient client = esOpClient.getESClient(clusterName);\n        String result = null;\n        if (Objects.isNull(client)) {\n            LOGGER.error(\"class=ESClusterDAO||method=shardAssignment||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            return null;\n        }\n        try {\n            DirectRequest directRequest = new DirectRequest(CLEAR_FIELDDATA_MEMORY.getMethod(),\n                CLEAR_FIELDDATA_MEMORY.getUri());\n            DirectResponse directResponse = client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                result = directResponse.getResponseContent();\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESClusterDAO||method=shardAssignment||cluster={}||mg=get es segments fail\", clusterName,\n                e);\n            return null;\n        }\n        return result;\n    }\n\n    public String abnormalShardAllocationRetry(String clusterName) {\n        ESClient client = esOpClient.getESClient(clusterName);\n        String result = null;\n        if (Objects.isNull(client)) {\n            LOGGER.error(\n                \"class=ESClusterDAO||method=abnormalShardAllocationRetry||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            return null;\n        }\n        try {\n            DirectRequest directRequest = new DirectRequest(ABNORMAL_SHARD_RETRY.getMethod(),\n                ABNORMAL_SHARD_RETRY.getUri());\n            DirectResponse directResponse = client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                result = directResponse.getResponseContent();\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESClusterDAO||method=abnormalShardAllocationRetry||cluster={}||mg=get es segments fail\",\n                clusterName, e);\n            return null;\n        }\n        return result;\n    }\n\n    /**\n     * 这里获取所有节点的tcp地址，暂时不做角色区分\n     * @param cluster\n     * @return\n     */\n    public List<String> getNodeTcpAddress(String cluster) {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (Objects.isNull(client)) {\n            LOGGER.error(\n                    \"class=ESClusterDAO||method=abnormalShardAllocationRetry||clusterName={}||errMsg=esClient is null\",\n                    cluster);\n            return new ArrayList<>();\n        }\n        ESClusterNodesStatsResponse nodesStatsResponse = client.admin().cluster().prepareNodeStats().execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        Map<String, ClusterNodeStats> nodes = nodesStatsResponse.getNodes();\n        return nodes.values().stream().map(ClusterNodeStats::getTransportAddress).distinct().collect(Collectors.toList());\n    }\n    \n    public boolean isConnectionStatus(String cluster) throws ESOperateException {\n        final boolean actualRunning = esOpClient.isActualRunning(cluster);\n        if (!actualRunning){\n            throw new ESOperateException(String.format(\"无法连接到es client %s\",cluster));\n        }\n    \n        return  actualRunning;\n    }\n    \n    /**\n     *  检查目标集群是否连接到当前集群\n     *\n     * @param cluster 要操作的集群名称\n     * @param targetCluster 目标集群的名称\n     * @return boolean\n     */\n    public boolean checkTargetClusterConnected(String cluster, String targetCluster) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        DirectResponse directResponse = null;\n        try {\n            directResponse = getDirectResponse(cluster, \"GET\",\n                    String.format(REMOTE_TARGET_CLUSTER, targetCluster, CONNECTED));\n        } catch (Exception e) {\n            LOGGER.error(\n                    \"class=ESClusterDAO||method=checkTargetClusterConnected||clusterName={}||errMsg=esClient is null\",\n                    cluster);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        Function<JSONObject,Boolean> jsonObjectFunc=jsonObject -> {\n            //如果是空的，则直接为false\n            if (jsonObject.isEmpty()){\n                return false;\n            }\n            \n           return jsonObject.getJSONObject(targetCluster).getBoolean(CONNECTED) || tryRemoteClusterCountIndicesAndIgnoreException(cluster\n                   , targetCluster);\n        };\n        \n        return Optional.ofNullable(directResponse).filter(d -> d.getRestStatus() == RestStatus.OK)\n                .map(DirectResponse::getResponseContent)\n                .map(JSON::parseObject)\n                .map(jsonObjectFunc)\n                \n                .orElse(false);\n    }\n    \n    /**\n     * > 它尝试获取目标集群中的索引计数，只是为了进行主集群到从集群正常的健康性校验:\n     * <pre>\n     *     1. 无需关注底层异常，这是由于如果集群不通，那么会触发Gateway Time-out，\n     *      那么也可以证明集群是不通的，所以无需关注\n     *     2.如果远程集群_count报错后，我们无需理会它，它会自动为remote信息刷新，\n     *     从而使得remote信息是刷新的，且由此可以证明集群是联通的\n     *     3.如果远程集群报了connect_exception信息，则证明集群配置是错误的或者不是联通的，那么可以证明集群是不联通的\n     * </pre>\n     *\n     * @param cluster 索引所属的集群的名称。\n     * @param targetCluster 目标集群的名称。\n     */\n    private boolean tryRemoteClusterCountIndicesAndIgnoreException(String cluster, String targetCluster)  {\n        DirectResponse directResponse;\n        try {\n            DirectRequest directRequest = new DirectRequest(\"GET\",\n                    String.format(REMOTE_TARGET_CLUSTER_COUNT, targetCluster));\n            directResponse = esOpClient.getESClient(cluster).direct(directRequest).actionGet(3, TimeUnit.SECONDS);\n        } catch (Exception exception) {\n            final String messageByException = ParsingExceptionUtils.getESErrorMessageByException(\n                    exception);\n            if (StringUtils.equals(messageByException,ParsingExceptionUtils.CLUSTER_ERROR)){\n                return false;\n            }\n            if (StringUtils.endsWith(messageByException, ParsingExceptionUtils.CONNECT_EXCEPTION)) {\n                return false;\n            }\n            if (exception instanceof ElasticsearchTimeoutException) {\n                return false;\n            }\n            return true;\n        }\n        return Optional.ofNullable(directResponse).map(d -> d.getRestStatus() == RestStatus.OK)\n                .orElse(false);\n        \n    }\n    \n    private final Function<List<ESResponsePluginInfo>, Map<String/*nodeName*/, List<String>/*pluginName*/>> eSResponsePluginInfoList2MapFunc                 = eSResponsePluginInfos -> ConvertUtil\n        .list2MapOfList(eSResponsePluginInfos, ESResponsePluginInfo::getName, ESResponsePluginInfo::getComponent);\n\n    private final Function<String, List<ESResponsePluginInfo>>                                              esCatResponseString2ESResponsePluginInfoListFunc = esCatResponse -> JSON\n        .parseArray(esCatResponse, ESResponsePluginInfo.class);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/cluster/ESClusterNodeDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_OPERATE_TIMEOUT;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.ESResponsePluginInfo;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NullESClientException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.ParsingExceptionUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.request.cluster.nodestats.ESClusterNodesStatsRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ESClusterNodesStatsResponse;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections4.MapUtils;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author d06679\n */\n@Repository\npublic class ESClusterNodeDAO extends BaseESDAO {\n    private static final String GET_NODE_PLUGINS = \"/_nodes/plugins\";\n    private static final String NODES            = \"nodes\";\n    private static final String NAME    = \"name\";\n    private static final String MODULES = \"modules\";\n    /**\n     * 获取节点上的索引个数\n     * @param cluster 集群\n     * @param nodes 节点\n     * @return 个数\n     */\n    public int getIndicesCount(String cluster, String nodes) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\n                    \"class={}||method=getIndicesCount||clusterName={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster);\n            throw new NullESClientException(cluster);\n        }\n        try {\n            ESClusterNodesStatsResponse response = client.admin().cluster().prepareNodeStats().setNodesIds(nodes)\n                    .setIndices(true).level(\"indices\").execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n            int count = 0;\n            Map<String, ClusterNodeStats> nodeStatsMap = response.getNodes();\n            for (ClusterNodeStats nodeStats : nodeStatsMap.values()) {\n                count += nodeStats.getIndices().getIndices().size();\n            }\n\n            return count;\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterNodeDao||method=getIndicesCount||clusterName={}\",\n                    cluster);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return 0;\n    }\n\n    public List<ClusterNodeStats> syncGetNodesStats(String clusterName) throws ESOperateException {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        if (esClient == null) {\n            LOGGER.error(\n                \"class=ESClusterNodeServiceImpl||method=syncGetNodeFsStatsMap||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            throw new NullESClientException(clusterName);\n        }\n        ESClusterNodesStatsResponse response=null;\n        try {\n        \n            response = esClient.admin().cluster().prepareNodeStats().setFs(true).setOs(true).setJvm(true)\n                    .setThreadPool(true).level(\"node\").execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterNodeServiceImpl||method=syncGetNodeFsStatsMap||clusterName={}\", clusterName,\n                    e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return Optional.ofNullable(response).map(ESClusterNodesStatsResponse::getNodes).filter(MapUtils::isNotEmpty)\n                .map(m->Lists.<ClusterNodeStats>newArrayList(m.values())).orElse(Lists.newArrayList());\n    }\n\n    /**\n     * 获取nodes信息\n     * @param cluster\n     * @return\n     */\n    public List<ClusterNodeStats> getNodeState(String cluster) {\n        ESClient esClient = esOpClient.getESClient(cluster);\n        if (esClient == null) {\n            LOGGER.error(\"class=ESClusterNodeServiceImpl||method=getNodeState||clusterName={}||errMsg=esClient is null\",\n                cluster);\n            return Lists.newArrayList();\n        }\n        ESClusterNodesStatsResponse response = esClient.admin().cluster().nodeStats(new ESClusterNodesStatsRequest())\n            .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        if (response.getNodes() != null) {\n            return new ArrayList<>(response.getNodes().values());\n\n        }\n        return Lists.newArrayList();\n    }\n    \n    public List<TupleTwo</*node name*/String,/*plugin names*/List<String>>> syncGetNodesPlugins(String clusterName) throws ESOperateException {\n        final DirectResponse directResponse = getDirectResponse(clusterName, \"GET\", GET_NODE_PLUGINS);\n        if (directResponse == null) {\n            return Lists.newArrayList();\n        }\n        JSONObject jsonObject = JSON.parseObject(directResponse.getResponseContent());\n        if (jsonObject == null || !jsonObject.containsKey(NODES)) {\n            return Lists.newArrayList();\n        }\n       return jsonObject.getJSONObject(NODES)\n                .values()\n                .stream()\n                .filter(Objects::nonNull)\n                .map(JSONObject.class::cast)\n                .map(this::buildNodeNamePlugins)\n                .collect(Collectors.toList());\n\n    }\n    private  TupleTwo<String,List<String>> buildNodeNamePlugins(JSONObject jsonObject){\n        final String nodeName = jsonObject.getString(NAME);\n        final List<String> pluginNames = jsonObject.getJSONArray(MODULES).stream().filter(Objects::nonNull)\n                .map(plugin -> ((JSONObject) plugin).getString(NAME)).collect(Collectors.toList());\n        return Tuples.of(nodeName,pluginNames);\n    \n    }\n\n    public List<ClusterNodeStats> syncGetNodesStatsWithIndices(String clusterName) {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        if (esClient == null) {\n            LOGGER.error(\"class=ESClusterNodeServiceImpl||method=syncGetNodeFsStatsMap||clusterName={}||errMsg=esClient is null\", clusterName);\n            return Lists.newArrayList();\n        }\n        ESClusterNodesStatsResponse response = esClient.admin().cluster().prepareNodeStats().setFs(true).setOs(true).setIndices(true).setJvm(true).setThreadPool(true).level(\"node\").execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        if (response.getNodes() != null) {\n            return new ArrayList<>(response.getNodes().values());\n        }\n        return Lists.newArrayList();\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/cluster/ESDCDRDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_OPERATE_TIMEOUT;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NullESClientException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ParsingExceptionUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.request.dcdr.DCDRIndex;\nimport com.didiglobal.knowframework.elasticsearch.client.request.dcdr.DCDRTemplate;\nimport com.didiglobal.knowframework.elasticsearch.client.request.dcdr.ESDeleteDCDRTemplateRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.dcdr.ESGetDCDRIndexRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.dcdr.ESGetDCDRTemplateRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.response.dcdr.ESDeleteDCDRTemplateResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.dcdr.ESGetDCDRIndexResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.dcdr.ESGetDCDRTemplateResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.dcdr.ESPutDCDRTemplateResponse;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Repository\npublic class ESDCDRDAO extends BaseESDAO {\n    public static final String SECURITY_EXCEPTION=\"security_exception\";\n    /**\n     * 保存dcdr模板配置 支持幂等\n     * @param cluster 集群\n     * @param name 名字\n     * @param template 模板\n     * @param replicaCluster 从集群\n     * @return true/false\n     */\n    public boolean putAutoReplication(String cluster, String name, String template, String replicaCluster) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\n                    \"class={}||method=putAutoReplication||clusterName={}||replicaCluster={}||template={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster, replicaCluster, template);\n            throw new NullESClientException(cluster);\n        }\n        try {\n            ESPutDCDRTemplateResponse response = client.admin().indices().preparePutDCDRTemplate().setName(name)\n                    .setTemplate(template).setReplicaCluster(replicaCluster).execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return response.getAcknowledged();\n        \n        }catch (Exception e){\n            final JSONObject exception = ParsingExceptionUtils.getResponseExceptionJsonMessageByException(e);\n            final Optional<Boolean> securityExceptionOptional = Optional.ofNullable(exception)\n                    .map(json -> json.getJSONObject(ERROR)).map(json -> json.getString(TYPE))\n                    .map(type -> type.equalsIgnoreCase(SECURITY_EXCEPTION));\n            if (securityExceptionOptional.isPresent() && Boolean.TRUE.equals(securityExceptionOptional.get())) {\n                throw new ESOperateException(String.format(\"集群 %s 含账户名密码，创建 DCDR 链路失败\", cluster));\n            }\n            LOGGER.error(\"class={}||method=putAutoReplication||clusterName={}||name={}\", getClass().getSimpleName(),\n                    cluster, name, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n\n        }\n        return false;\n    }\n\n    /**\n     * 删除dcdr模板链路\n     * @param cluster 集群\n     * @param name 名字\n     * @return true/false\n     */\n    public boolean deleteAutoReplication(String cluster, String name) throws ESOperateException {\n        DCDRTemplate dcdrTemplate = getAutoReplication(cluster, name);\n        if (dcdrTemplate == null) {\n            return true;\n        }\n       \n\n        ESClient client = esOpClient.getESClient(cluster);\n        ESDeleteDCDRTemplateRequest request = new ESDeleteDCDRTemplateRequest();\n        request.setName(name);\n        ESDeleteDCDRTemplateResponse response =null;\n    \n        try {\n        \n            response = client.admin().indices().deleteDCDRTemplate(request)\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.warn(\"class={}||method=deleteReplication||clusterName={}||name={}\", getClass().getSimpleName(),\n                    cluster, name, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return Optional.ofNullable(response).map(ESDeleteDCDRTemplateResponse::getAcknowledged).orElse(false);\n    }\n\n    /**\n     * 获取dcdr模板\n     * @param cluster 集群\n     * @param name 名字\n     * @return dcdr模板\n     */\n    public DCDRTemplate getAutoReplication(String cluster, String name) throws ESOperateException {\n        //如果集群挂掉，就是可以抛出NPE\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client==null){\n            throw new NullESClientException(cluster);\n        }\n        \n        ESGetDCDRTemplateRequest request = new ESGetDCDRTemplateRequest();\n        request.setName(name);\n        ESGetDCDRTemplateResponse response = null;\n        try {\n            response = client.admin().indices().getDCDRTemplate(request)\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.warn(\"class={}||method=deleteReplication||clusterName={}||name={}\", getClass().getSimpleName(),\n                    cluster, name, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return Optional.ofNullable(response).map(ESGetDCDRTemplateResponse::getDcdrs)\n                .filter(CollectionUtils::isNotEmpty).map(dcdrTemplates -> dcdrTemplates.get(0)).orElse(null);\n\n    }\n\n    /**\n     * 删除索引dcdr链路\n     * @param cluster 集群\n     * @param replicaCluster 从集群\n     * @param indices 索引列表\n     * @return result\n     */\n    public boolean deleteReplication(String cluster, String replicaCluster, Set<String> indices)\n            throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\n                    \"class={}||method=deleteReplication||clusterName={}||replicaCluster={}||indices={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster, replicaCluster, indices);\n            throw new NullESClientException(cluster);\n        }\n        try {\n            ESGetDCDRIndexResponse getDCDRIndexResponse = client.admin().indices()\n                    .getDCDRIndex(new ESGetDCDRIndexRequest()).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            List<DCDRIndex> allIndexDCDRs = getDCDRIndexResponse.getDcdrs();\n    \n            List<String> shouldDels = Lists.newArrayList();\n            if (CollectionUtils.isNotEmpty(allIndexDCDRs)) {\n                for (DCDRIndex index : allIndexDCDRs) {\n                    if (index.getReplicaCluster().equals(replicaCluster) && indices.contains(index.getPrimaryIndex())) {\n                        shouldDels.add(index.getPrimaryIndex());\n                    }\n                }\n            }\n    \n            if (CollectionUtils.isEmpty(shouldDels)) {\n                return true;\n            }\n    \n            boolean succ = true;\n            for (String delIndex : shouldDels) {\n                succ = succ && client.admin().indices().prepareDeleteDCDRIndex().setPrimaryIndex(delIndex)\n                        .setReplicaIndex(delIndex).setReplicaCluster(replicaCluster).execute()\n                        .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS).getAcknowledged();\n            }\n    \n            return succ;\n        } catch (Exception e) {\n            LOGGER.warn(\n                    \"class={}||method=deleteReplication||clusterName={}||replicaCluster={}||indices={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster, replicaCluster, indices);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/cluster/ESIndexDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.COMMA;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.*;\n\nimport java.util.*;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.BiFunction;\nimport java.util.stream.Collectors;\n\nimport javax.annotation.Nullable;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.stereotype.Repository;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.setting.ESIndicesGetAllSettingRequest;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NullESClientException;\nimport com.didichuxing.datachannel.arius.admin.common.function.BiFunctionWithESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.function.FunctionWithESOperateException;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.model.Client;\nimport com.didiglobal.knowframework.elasticsearch.client.model.exception.ESAlreadyExistsException;\nimport com.didiglobal.knowframework.elasticsearch.client.model.exception.ESIndexNotFoundException;\nimport com.didiglobal.knowframework.elasticsearch.client.model.type.ESVersion;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.exists.ESIndicesExistsRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.getindex.ESIndicesGetIndexRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.putalias.PutAliasNode;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.stats.ESIndicesStatsRequestBuilder;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.stats.IndicesStatsLevel;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.updatemapping.ESIndicesUpdateMappingRequestBuilder;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.updatesettings.ESIndicesUpdateSettingsRequestBuilder;\nimport com.didiglobal.knowframework.elasticsearch.client.response.ESAcknowledgedResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.ESIndicesCatIndicesResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.closeindex.ESIndicesCloseIndexResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.deletebyquery.ESIndicesDeleteByQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.deleteindex.ESIndicesDeleteIndexResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.exists.ESIndicesExistsResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.getalias.AliasIndexNode;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.getalias.ESIndicesGetAliasResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.getindex.ESIndicesGetIndexResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.openindex.ESIndicesOpenIndexResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.putalias.ESIndicesPutAliasResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.putindex.ESIndicesPutIndexResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.refreshindex.ESIndicesRefreshIndexResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.stats.ESIndicesStatsResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.stats.IndexNodes;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.updatemapping.ESIndicesUpdateMappingResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.updatesettings.ESIndicesUpdateSettingsResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.TypeConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.IndexConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.MultiIndexsConfig;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Repository\npublic class ESIndexDAO extends BaseESDAO {\n    \n    public static final String FAILED_MSG = \"%s 执行失败, 请检查参数与索引配置\";\n    public static final String MAX_NUM_SEGMENTS = \"max_num_segments\";\n    public static final String ONLY_EXPUNGE_DELETES = \"only_expunge_deletes\";\n    public static final String ROLLOVER_API         = \"/_rollover\";\n    public static final  String ALIAS_API              = \"/%s/_alias\";\n    public static final String CAT_INDIES = \"/_cat/indices/%s?v=true&format=json&filter_path=index\";\n    public static final String INDEX = \"index\";\n    public static final String DELETE_INDEX = \"%s?ignore_unavailable=true\";\n    public static final String ACKNOWLEDGED = \"acknowledged\";\n    /**\n     * 创建索引\n     * @param cluster 集群\n     * @param indexName 索引名字\n     * @return result\n     */\n    public boolean createIndex(String cluster, String indexName) throws ESOperateException {\n        if (exist(cluster, indexName)) {\n            LOGGER.warn(\"class=ESIndexDAO||method=createIndex||index already exist||cluster={}||indexName={}\", cluster,\n                    indexName);\n            return true;\n        }\n    \n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        try {\n        \n            ESIndicesPutIndexResponse response = client.admin().indices().preparePutIndex(indexName).execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESIndexDAO||method=createIndex||cluster={}||indexName={}\", cluster);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 通过集群名称获取对应的ES Client\n     * @param clusterName 集群名称\n     * @return\n     */\n    private ESClient fetchESClientByCluster(String clusterName) {\n        ESClient client = esOpClient.getESClient(clusterName);\n        if (client == null) {\n            LOGGER.warn(\"class=ESIndexDAO||method=fetchESClientByCluster||cannot get es client,cluster={}\",\n                clusterName);\n        }\n        return client;\n    }\n\n    /**\n     * 按着指定的配置创建索引\n     * @param cluster 集群\n     * @param indexName 索引\n     * @param indexConfig 索引配置\n     * @return\n     */\n    public boolean createIndexWithConfig(String cluster, String indexName, IndexConfig indexConfig,Integer tryTimes)\n            throws ESOperateException {\n        \n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            return Boolean.FALSE;\n        }\n        indexConfig.setVersion(ESVersion.valueBy(client.getEsVersion()));\n        BiFunctionWithESOperateException<Long, TimeUnit, ESIndicesPutIndexResponse> esIndicesExistsResponseBiFunction = (timeout, unit) -> {\n            try {\n                return client.admin().indices().preparePutIndex(indexName).setIndexConfig(indexConfig).execute()\n                        .actionGet(timeout, unit);\n            } catch (Exception e) {\n                LOGGER.error(\"class=ESIndexDAO||method=createIndexWithConfig||cluster={}||indexName={}\", cluster);\n                ParsingExceptionUtils.abnormalTermination(e);\n            }\n            return null;\n        };\n        \n        ESIndicesPutIndexResponse response = esIndicesExistsResponseBiFunction.apply(Long.valueOf(ES_OPERATE_TIMEOUT), TimeUnit.SECONDS );\n        \n        return Optional.ofNullable(response).map(ESAcknowledgedResponse::getAcknowledged).orElse(Boolean.FALSE);\n    }\n\n    /**\n     * 根据表达式判断索引是否已存在\n     * @param cluster\n     * @return\n     */\n    public boolean exist(String cluster, String expression) {\n        Client client = fetchESClientByCluster(cluster);\n        if (client != null) {\n            return client.admin().indices().prepareExists(expression).execute()\n                .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS).isExists();\n        }\n        return false;\n    }\n\n    /**\n     * 根据索引名称判断索引是否已存在\n     * @param cluster    集群名称\n     * @param indexName  索引名称\n     * @return\n     */\n    public boolean existByClusterAndIndexName(String cluster, String indexName) throws NullESClientException {\n        Client client = fetchESClientByCluster(cluster);\n         if ( client==null) {\n             throw new NullESClientException(cluster);\n        }\n        ESIndicesExistsRequest esIndicesExistsRequest = new ESIndicesExistsRequest();\n        esIndicesExistsRequest.setIndex(indexName);\n        BiFunction<Long,TimeUnit,ESIndicesExistsResponse> esIndicesExistsResponseBiFunction=(timeout,unit)->{\n            try {\n              return   client.admin().indices().exists(esIndicesExistsRequest).actionGet(timeout,unit);\n            }catch (Exception e){\n                 LOGGER.error(\"class=ESIndexDAO||method=existByClusterAndIndexName||cluster={}||indexName={}\",\n                cluster);\n                 return null;\n            }\n        };\n        ESIndicesExistsResponse response = esIndicesExistsResponseBiFunction.apply(Long.valueOf(ES_OPERATE_TIMEOUT),\n                TimeUnit.SECONDS);\n                \n        \n        return Optional.ofNullable(response).map(ESIndicesExistsResponse::isExists).orElse(Boolean.FALSE);\n    }\n\n    /**\n     * 批量获取索引配置\n     * @param cluster 集群\n     * @param indexNames 索引名字\n     * @return 配置\n     */\n    public MultiIndexsConfig batchGetIndexConfig(String cluster, List<String> indexNames) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        try {\n            String indexExpression = String.join(\",\", indexNames);\n            ESIndicesGetIndexResponse getIndexResponse = client.admin().indices().prepareGetIndex(indexExpression)\n                    .execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return getIndexResponse.getIndexsMapping();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESIndexDAO||method=batchGetIndexConfig||cluster={}||indexName={}||msg=index not exist\",\n                    cluster, String.join(\",\", indexNames),e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return null;\n    }\n\n    /**\n     * 获取索引的mapping信息\n     * @param cluster 集群\n     * @param indexName 索引名字\n     * @return\n     */\n    public MappingConfig getIndexMapping(String cluster, String indexName) {\n        if (!exist(cluster, indexName)) {\n            LOGGER.warn(\"class=ESIndexDAO||method=getIndexMapping||cluster={}||indexName={}||msg=index not exist\",\n                cluster, indexName);\n            return null;\n        }\n\n        ESClient client = esOpClient.getESClient(cluster);\n        if (null == client) {\n            return null;\n        }\n        ESIndicesGetIndexResponse response = client.admin().indices().prepareGetIndex(indexName).execute()\n            .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n        return response.getIndexsMapping().getIndexConfig(indexName).getMappings();\n    }\n\n    /**\n     * 更新索引的mapping信息\n     * @param cluster 集群\n     * @param indexName 索引名字\n     * @return\n     */\n    public boolean updateIndexMapping(String cluster, String indexName, MappingConfig mappingConfig) throws ESOperateException {\n        if (!exist(cluster, indexName)) {\n            LOGGER.warn(\"class=ESIndexDAO||method=updateIndexMapping||cluster={}||indexName={}||msg=index not exist\",\n                cluster, indexName);\n            return true;\n        }\n\n        ESClient client = esOpClient.getESClient(cluster);\n        Map<String, TypeConfig> typeConfigMap = mappingConfig.getMapping();\n        if (typeConfigMap == null) {\n            return false;\n        }\n\n        for (Map.Entry<String, TypeConfig> entry : typeConfigMap.entrySet()) {\n            String typeName = entry.getKey();\n            ESIndicesUpdateMappingRequestBuilder builder = client.admin().indices().prepareUpdateMapping();\n            builder.setIndex(indexName).setType(typeName).setTypeConfig(typeConfigMap.get(typeName));\n            // es 集群版本7 需要带includeTypeName 参数，方可以更新index mapping\n            if (Integer.parseInt(client.getEsVersion().split(\"\\\\.\")[0]) == 7) {\n                builder.setIncludeTypeName(true);\n            }\n            //es集群版本8 不需要type参数\n            if (Integer.parseInt(client.getEsVersion().split(\"\\\\.\")[0]) == 8) {\n                builder.setIsNeedType(false);\n            }\n            try {\n                ESIndicesUpdateMappingResponse response = builder.execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n                if (!response.getAcknowledged().booleanValue()) {\n                    return false;\n                }\n            } catch (Exception e) {\n                LOGGER.error(\"class=ESIndexDAO||method=updateIndexMapping||msg=update index mapping fail||cluster={}||indexName={}\", cluster\n                        ,indexName,e);\n                ParsingExceptionUtils.abnormalTermination(e);\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * 删除索引\n     * @param cluster 集群\n     * @param indexName 索引名字\n     * @return\n     */\n    public boolean deleteIndex(String cluster, String indexName) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null){\n            LOGGER.warn(\n                    \"class={}||method=deleteIndex||clusterName={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster);\n            throw new NullESClientException(cluster);\n        }\n        if (!exist(cluster, indexName)) {\n            LOGGER.warn(\"class=ESIndexDAO||method=deleteIndex||cluster={}||indexName={}||msg=index not exist\", cluster,\n                indexName);\n            return true;\n        }\n        try{\n            ESIndicesDeleteIndexResponse response = client.admin().indices().prepareDeleteIndex(indexName).execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESIndexDAO||method=deleteIndex||cluster={}||indexName={}\", cluster,\n                    indexName,e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n    \n    /**\n     * > 按表达式删除索引\n     *\n     * @param cluster 集群名称，与配置文件中的集群名称一致。\n     * @param expression 索引名称或索引名称表达式。\n     * @return boolean\n     */\n    public boolean deleteByExpression(String cluster, String expression) throws ESOperateException {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        try {\n            DirectRequest directRequest = new DirectRequest(\"GET\", String.format(CAT_INDIES, expression));\n            DirectResponse directResponse = client.direct(directRequest).actionGet(30, TimeUnit.SECONDS);\n            List<String> indexNameList = Optional.ofNullable(directResponse)\n                    .filter(response -> response.getRestStatus() == RestStatus.OK)\n                    .map(DirectResponse::getResponseContent).filter(StringUtils::isNotBlank).map(JSON::parseArray)\n                    .filter(json -> !json.isEmpty()).orElse(new JSONArray()).stream().filter(Objects::nonNull)\n                    .map(json -> ((JSONObject) json).getString(INDEX)).distinct().collect(Collectors.toList());\n\n            if (CollectionUtils.isEmpty(indexNameList)) {\n                return true;\n            }\n            FunctionWithESOperateException<List<String>, Boolean> deleteFunc = indexList -> {\n                try {\n                    DirectRequest directRequestDelete = new DirectRequest(\"DELETE\",\n                            String.format(DELETE_INDEX, String.join(\",\", indexList)));\n                    DirectResponse directResponseDelete = client.direct(directRequestDelete)\n                            .actionGet(30, TimeUnit.SECONDS);\n                    return Optional.ofNullable(directResponseDelete)\n                            .filter(response -> response.getRestStatus() == RestStatus.OK)\n                            .map(DirectResponse::getResponseContent).map(JSON::parseObject)\n                            .map(json -> json.getBoolean(ACKNOWLEDGED)).orElse(false);\n                } catch (Exception e) {\n                    LOGGER.warn(\"class={}||method=deleteByExpression||cluster={}||expression={}\",\n                            getClass().getSimpleName(), cluster, String.join(\",\", indexList), e);\n\n                    ParsingExceptionUtils.abnormalTermination(e);\n\n                }\n                return false;\n            };\n    \n            BatchProcessor.BatchProcessResult<String, Boolean> result = new BatchProcessor<String, Boolean>().batchList(\n                    indexNameList).batchSize(30).processor(deleteFunc).succChecker(succ -> succ).process();\n    \n            Optional<Exception> first = result.getErrorMap().values().stream().findFirst();\n            if (first.isPresent()) {\n                throw new ESOperateException(first.get().getMessage());\n            }\n    \n            return result.getResultList().stream().allMatch(Boolean.TRUE::equals);\n        \n        } catch (Exception e) {\n            if (e instanceof ESIndexNotFoundException) {\n                return true;\n            }\n            LOGGER.warn(\"class={}||method=deleteByExpression||cluster={}||expression={}\", getClass().getSimpleName(),\n                    cluster, expression, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n\n        }\n        return false;\n        \n    }\n\n    /**\n     * 根据索引模板名称获取物理集群所有分区索引\n     * @param cluster 集群名称\n     * @param expression 索引模板表达式\n     * @return\n     */\n    public List<CatIndexResult> catIndexByExpression(String cluster, String expression) {\n        List<CatIndexResult> indices = Lists.newArrayList();\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client != null) {\n            BiFunction<Long, TimeUnit, ESIndicesCatIndicesResponse> catIndicesResponseBiFunction = (timeout, unit) -> {\n                try {\n                    return client.admin().indices().prepareCatIndices(expression).execute()\n                            .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n                } catch (Exception e) {\n                    LOGGER.warn(\"class=ESIndexDAO||method=catIndexByExpression||errMsg={}||cluster={}||expression={}\",\n                            e.getMessage(), cluster, expression, e);\n                    return null;\n                }\n            };\n            ESIndicesCatIndicesResponse esIndicesCatIndicesResponse =\n                    catIndicesResponseBiFunction.apply(Long.valueOf(ES_OPERATE_TIMEOUT), TimeUnit.SECONDS);\n            Optional.ofNullable(esIndicesCatIndicesResponse).map(ESIndicesCatIndicesResponse::getCatIndexResults).ifPresent(indices::addAll);\n        }\n         return indices;\n    }\n\n    /**\n     * 获取集群中全量索引\n     * @param cluster\n     * @return\n     */\n    public List<CatIndexResult> catIndices(String cluster) {\n        List<CatIndexResult> indices = Lists.newArrayList();\n\n        try {\n            ESClient client = fetchESClientByCluster(cluster);\n            if (client != null) {\n                ESIndicesCatIndicesResponse response = client.admin().indices().prepareCatIndices().execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n                indices.addAll(response.getCatIndexResults());\n            }\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESIndexDAO||method=catIndexByExpression||errMsg={}||cluster={}\", e.getMessage(), cluster,\n                e);\n        }\n\n        return indices;\n    }\n\n    /**\n     * 获取指定集群,指定表达式的索引\n     * @param cluster\n     * @param expression\n     * @return\n     */\n    public Map<String, IndexNodes> getIndexByExpression(String cluster, String expression) {\n        try {\n            ESClient client = fetchESClientByCluster(cluster);\n            if (client == null) {\n                return null;\n            }\n\n            ESIndicesStatsResponse response = client.admin().indices().prepareStats(expression).execute()\n                .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return response.getIndicesMap();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESIndexDAO||method=getIndexByExpression||cluster={}||expression={}\",\n                 cluster, expression, e);\n            return null;\n        }\n    }\n\n    /**\n     * 获取指定集群,指定表达式的索引指标，附带全部shard的信息\n     * @param cluster\n     * @param expression\n     * @return\n     */\n    public Map<String, IndexNodes> getIndexStatsWithShards(String cluster, String expression)throws ESOperateException {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        ESIndicesStatsResponse response = null;\n        try {\n        \n            response = client.admin().indices().prepareStats(expression).setLevel(IndicesStatsLevel.SHARDS).execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESIndexDAO||method=getIndexByExpression||errMsg={}||cluster={}||expression={}\",\n                    e.getMessage(), cluster, expression, e);\n\n            ParsingExceptionUtils.abnormalTermination(e);\n\n        }\n        return Optional.ofNullable(response).map(ESIndicesStatsResponse::getIndicesMap).orElse(Maps.newHashMap());\n    \n    }\n\n    public Map<String, IndexNodes> getIndexStats(String cluster, String expression) {\n        try {\n            ESClient client = fetchESClientByCluster(cluster);\n            if (client == null) {\n                return Maps.newHashMap();\n            }\n            ESIndicesStatsResponse response;\n            if (StringUtils.isNotBlank(expression)) {\n                response = client.admin().indices().prepareStats(expression).setLevel(IndicesStatsLevel.INDICES)\n                    .execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            } else {\n                response = client.admin().indices().prepareStats().setLevel(IndicesStatsLevel.INDICES).execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            }\n            return response.getIndicesMap();\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESIndexDAO||method=getIndexByExpression||errMsg={}||cluster={}||expression={}\",\n                e.getMessage(), cluster, expression, e);\n            return Maps.newHashMap();\n        }\n    }\n\n    /**\n     * 获取指定集群,指定表达式的别名\n     * @param cluster\n     * @param expression\n     * @return\n     */\n    public Map<String/*index*/, AliasIndexNode> getAliasesByExpression(String cluster, String expression) {\n        try {\n            ESClient client = esOpClient.getESClient(cluster);\n            ESIndicesGetAliasResponse response = client.admin().indices().prepareAlias(expression).execute()\n                .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return response.getM();\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESIndexDAO||method=getAliasesByExpression||errMsg={}||cluster={}||expression={}\",\n                cluster, e.getMessage(), expression, e);\n            return null;\n        }\n    }\n\n    /**\n     * 获取指定集群,指定多个索引\n     * @param cluster\n     * @param indices\n     * @return\n     */\n    public Map<String/*index*/, AliasIndexNode> getAliasesByIndices(String cluster, String... indices) {\n         ESClient client = esOpClient.getESClient(cluster);\n         if (client==null){\n             return null;\n         }\n        BiFunction<Long, TimeUnit, ESIndicesGetAliasResponse> responseBiFunction = (time, unit) -> {\n            try {\n                return client.admin().indices().prepareAlias(indices).execute().actionGet(time, unit);\n            } catch (Exception e) {\n                LOGGER.warn(\"class=ESIndexDAO||method=getAliasesByExpression||cluster={}||indices={}\",\n                        cluster, indices, e);\n                return null;\n            }\n        };\n        ESIndicesGetAliasResponse response =responseBiFunction.apply(Long.valueOf(ES_OPERATE_TIMEOUT),TimeUnit.SECONDS);\n        \n        \n        \n        return Optional.ofNullable(response).map(ESIndicesGetAliasResponse::getM).orElse(null);\n    }\n\n    /**\n     * 删除文档\n     * @param cluster 集群\n     * @param delIndices 索引\n     * @param delQueryDsl 语句\n     * @return true/false\n     */\n    public boolean deleteByQuery(String cluster, String delIndices, String delQueryDsl) throws ESOperateException {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            throw new NullESClientException( cluster);\n        }\n\n        ESIndicesDeleteByQueryResponse response = client.admin().indices().prepareDeleteByQuery().setIndex(delIndices)\n            .setQuery(delQueryDsl).setHighES(true).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n        if (response.getRoot().containsKey(\"error\")) {\n            throw new ESOperateException(response.getRoot().get(\"error\").toString());\n        }\n\n        return true;\n    }\n\n    public boolean batchUpdateIndexRegion(String cluster, List<String> indices, Set<String> nodeNames)  throws ESOperateException{\n        return putIndexSetting(cluster, indices, TEMPLATE_INDEX_INCLUDE_NODE_NAME, String.join(COMMA, nodeNames), \"\");\n    }\n\n    /**\n     * 设置索引只读属性\n     * @param cluster 集群\n     * @param indexNames 索引列表\n     * @param block 配置\n     * @return result\n     */\n    public boolean blockIndexWrite(String cluster, List<String> indexNames, boolean block)  throws ESOperateException{\n        return putIndexSetting(cluster, indexNames, INDEX_BLOCKS_WRITE, String.valueOf(block), \"false\");\n    }\n\n    /**\n     * 设置索引只写属性\n     * @param cluster 集群\n     * @param indexNames 索引列表\n     * @param block 配置\n     * @return result\n     */\n    public boolean blockIndexRead(String cluster, List<String> indexNames, boolean block)  throws ESOperateException{\n        return putIndexSetting(cluster, indexNames, INDEX_BLOCKS_READ, String.valueOf(block), \"false\");\n    }\n\n    /**\n     * refresh索引\n     * @param cluster 集群\n     * @param indexNames 索引列表\n     * @return result\n     */\n    public boolean refreshIndex(String cluster, List<String> indexNames) throws ESOperateException{\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n    \n        ESIndicesRefreshIndexResponse response = null;\n        try {\n            response = client.admin().indices().prepareRefreshIndex(String.join(\",\", indexNames)).execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.error(\"class={}||method=refreshIndex||clusterName={}||indexName={}\", getClass().getSimpleName(),\n                    cluster, String.join(\",\", indexNames), e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n    \n        return Optional.ofNullable(response).map(r -> r.getFaild() == 0).orElse(false);\n    }\n\n    /**\n     * 修改索引配置，多个setting数值的设置\n     * @param cluster 物理集群名称\n     * @param settings key：setting名称 value：setting数值\n     */\n    public boolean putIndexSettings(String cluster, List<String> indices,\n                                    Map</*setting名称*/String, /*setting数值*/String> settings)\n            throws ESOperateException {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null || MapUtils.isEmpty(settings)) {\n            LOGGER.warn(\n                    \"class=ESTemplateDAO||method=putIndexSettings||get settings fail||clusterName={}||indexNames={}\",\n                    cluster, indices);\n            throw new NullESClientException(cluster);\n        }\n    \n        ESIndicesUpdateSettingsResponse esIndicesUpdateSettingsResponse = null;\n        try {\n            ESIndicesUpdateSettingsRequestBuilder updateSettingsRequestBuilder = client.admin().indices()\n                    .prepareUpdateSettings(String.join(\",\", indices));\n            // 依次添加需要设置的 setting 的字段的名称和数值\n            settings.forEach(updateSettingsRequestBuilder::addSettings);\n            esIndicesUpdateSettingsResponse = updateSettingsRequestBuilder.execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESTemplateDAO||method=putIndexSettings||get index fail||clusterName={}||indexName={}\",\n                    cluster, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        \n        }\n        \n\n        return Optional.ofNullable(esIndicesUpdateSettingsResponse).map(ESIndicesUpdateSettingsResponse::getAcknowledged\n        ).orElse(false);\n    }\n\n    /**\n     * 修改索引配置\n     * @param cluster 集群\n     * @param indices 索引\n     * @param settingName 配置名称\n     * @param setting 配置\n     * @param defaultValue 配置默认值\n     * @return true/false\n     */\n    public boolean putIndexSetting(String cluster, List<String> indices, String settingName, String setting,\n                                   String defaultValue) throws ESOperateException{\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n\n        MultiIndexsConfig multiIndexsConfig = batchGetIndexConfig(cluster, indices);\n\n        List<String> needOps = Lists.newArrayList();\n        for (Map.Entry<String, IndexConfig> indexConfigEntry : multiIndexsConfig.getIndexConfigMap().entrySet()) {\n            IndexConfig indexConfig = indexConfigEntry.getValue();\n\n            //由于客户端在put-setting的时候会默认加上\"index.\"的前缀 所以这里需要这样搞\n            Map<String, String> config = indexConfig.getSettings();\n            String src = config.get(INDEX_SETTING_PRE + settingName);\n            if (settingName.startsWith(INDEX_SETTING_PRE)) {\n                src = config.get(settingName);\n            }\n\n            if (src == null) {\n                src = defaultValue;\n            }\n            if (src.equals(String.valueOf(setting))) {\n                continue;\n            }\n            needOps.add(indexConfigEntry.getKey());\n        }\n\n        if (CollectionUtils.isEmpty(needOps)) {\n            return true;\n        }\n    \n        ESIndicesUpdateSettingsResponse updateSettingsResponse = null;\n        try {\n        \n            updateSettingsResponse = client.admin().indices().prepareUpdateSettings(String.join(\",\", needOps))\n                    .addSettings(settingName, String.valueOf(setting)).execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.error(\"class={}||method=putIndexSetting||clusterName={}||indexName={}\", getClass().getSimpleName(),\n                    cluster, String.join(\",\", indices), e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        \n        }\n        return Optional.ofNullable(updateSettingsResponse).map(ESIndicesUpdateSettingsResponse::getAcknowledged)\n                .orElse(false);\n        \n    }\n\n    public boolean putIndexSetting(String cluster, List<String> indices, Map<String, String> settingMap)\n            throws ESOperateException {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (null == client) {\n            return false;\n        }\n\n        MultiIndexsConfig multiIndexsConfig = batchGetIndexConfig(cluster, indices);\n        List<String> needOps = Lists.newArrayList();\n        for (Map.Entry<String, IndexConfig> indexConfigEntry : multiIndexsConfig.getIndexConfigMap().entrySet()) {\n            IndexConfig indexConfig = indexConfigEntry.getValue();\n\n            Map<String, String> config = indexConfig.getSettings();\n            Boolean modifyFlag = Boolean.FALSE;\n            for (Map.Entry<String, String> settingEntry : settingMap.entrySet()) {\n                String settingName = settingEntry.getKey();\n                String settingValue = settingEntry.getValue();\n                String src = config.get(INDEX_SETTING_PRE + settingName);\n                if (settingName.startsWith(INDEX_SETTING_PRE)) {\n                    src = config.get(settingName);\n                }\n\n                if (!settingValue.equals(src)) {\n                    modifyFlag = Boolean.TRUE;\n                }\n            }\n            if (modifyFlag) {\n                needOps.add(indexConfigEntry.getKey());\n            }\n        }\n\n        if (CollectionUtils.isEmpty(needOps)) {\n            return true;\n        }\n        try {\n        \n            ESIndicesUpdateSettingsRequestBuilder updateSettingsRequestBuilder = client.admin().indices()\n                    .prepareUpdateSettings(String.join(\",\", needOps));\n            for (Map.Entry<String, String> settingEntry : settingMap.entrySet()) {\n                updateSettingsRequestBuilder.addSettings(settingEntry.getKey(), settingEntry.getValue());\n            }\n            return updateSettingsRequestBuilder.execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS)\n                    .getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESIndexDAO||method=putIndexSetting||cluster={}||indexName={}\",\n                    cluster, String.join(\",\", indices));\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 关闭索引\n     * @param cluster 集群\n     * @param indices 索引\n     * @return result\n     */\n    public boolean closeIndex(String cluster, List<String> indices) throws ESOperateException {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        try {\n        \n            ESIndicesCloseIndexResponse response = client.admin().indices().prepareCloseIndex(String.join(\",\", indices))\n                    .execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.warn(\"class={}||method=closeIndex||clusterName={}||indexName={}||msg={}\", getClass().getSimpleName(),\n                    cluster, String.join(\",\", indices), e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 打开索引\n     * @param cluster 集群\n     * @param indices 索引\n     * @return result\n     */\n    public boolean openIndex(String cluster, List<String> indices) throws ESOperateException{\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        try {\n        \n            ESIndicesOpenIndexResponse response = client.admin().indices().prepareOpenIndex(String.join(\",\", indices))\n                    .execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.warn(\"class={}||method=closeIndex||clusterName={}||indexName={}||msg={}\", getClass().getSimpleName(),\n                    cluster, String.join(\",\", indices), e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 获取模板信息\n     * @param clusterName       集群名\n     * @param indexName         索引名\n     * @return result\n     */\n    public MultiIndexsConfig getIndexConfigs(String clusterName, String indexName) {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n\n        if (null == esClient) {\n            return null;\n        }\n\n        ESIndicesGetIndexRequest request = new ESIndicesGetIndexRequest();\n        request.setIndices(indexName);\n\n        ESIndicesGetIndexResponse response = null;\n        try {\n            response = esClient.admin().indices().getIndex(request).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=ESTemplateDAO||method=getIndexConfigs||get index fail||clusterName={}||indexName={}||msg={}\",\n                clusterName, indexName, e.getMessage(), e);\n        }\n\n        if (response == null) {\n            return null;\n        }\n\n        LOGGER.debug(\"class=ESTemplateDAO||method=getIndexConfigs||response={}\", JSON.toJSONString(response));\n\n\n        return response.getIndexsMapping();\n    }\n\n    /**\n     * 根据集群名称和索引名称获取索引setting信息\n     * @param clusterName       集群名称\n     * @param indexNames        索引列表\n     * @param tryTimes\n     * @return\n     */\n    public Map<String, IndexConfig> getIndicesSetting(String clusterName, List<String> indexNames, int tryTimes) {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        if (null == esClient) {\n            return Maps.newHashMap();\n        }\n\n        ESIndicesGetAllSettingRequest request = new ESIndicesGetAllSettingRequest();\n        request.setDefaultSettingFlag(true);\n        request.mapping(false);\n        request.alias(false);\n        request.setIndices(ListUtils.strList2StringArray(indexNames));\n\n        ESIndicesGetIndexResponse response = null;\n        try {\n            do {\n                response = esClient.admin().indices().getIndex(request).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            } while (tryTimes-- > 0 && null == response);\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=ESTemplateDAO||method=getIndexConfigs||get index fail||clusterName={}||indexName={}||msg={}\",\n                clusterName, e.getMessage(), e);\n        }\n\n        if (response == null) {\n            return Maps.newHashMap();\n        }\n\n\n\n        return response.getIndexsMapping().getIndexConfigMap();\n    }\n\n    /**\n     * 获取索引IndexNodes信息\n     *\n     * @param clusterName\n     * @return\n     */\n    @Nullable\n    public Map<String, IndexNodes> getIndexNodes(String clusterName, String templateExp) {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n\n        if (esClient == null) {\n            LOGGER.error(\"class=ClusterClientPool||method=getIndexNodes||clusterName={}||errMsg=esClient is null\",\n                clusterName);\n            return null;\n        }\n\n        ESIndicesStatsResponse response = null;\n        ESIndicesStatsRequestBuilder builder = null;\n        try {\n            if (StringUtils.isBlank(templateExp)) {\n                builder = esClient.admin().indices().prepareStats();\n            } else {\n                builder = esClient.admin().indices().prepareStats(templateExp);\n            }\n            response = builder.setStore(true).setDocs(true).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=ClusterClientPool||method=getIndexNodes||clusterName={}||errMsg=get {} index stats error. \",\n                clusterName, templateExp, e);\n        }\n\n        if (response == null) {\n            return null;\n        }\n\n        return response.getIndicesMap();\n    }\n\n    /**\n     * 编辑索引别名\n     * @param aliases\n     * @return result\n     */\n    public boolean editAlias(String cluster, List<PutAliasNode> aliases) throws ESOperateException {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        if (CollectionUtils.isEmpty(aliases)) {\n            return true;\n        }\n        String[] indeies = aliases.stream().map(PutAliasNode::getIndex).distinct().toArray(String[]::new);\n        final List<String> aliasLit = aliases.stream().map(PutAliasNode::getAlias).distinct()\n                .collect(Collectors.toList());\n        // 这里有两种情况，第一种：直接删除成功，但是因为集群不稳定导致了返回异常；第二种：删除失败；\n        BiFunctionWithESOperateException<Long, TimeUnit, ESIndicesPutAliasResponse> esIndicesPutAliasResponseBiFunction = (time, unit) -> {\n            try {\n                return client.admin().indices().preparePutAlias().addPutAliasNodes(aliases).execute()\n                        .actionGet(time, unit);\n            } catch (Exception e) {\n                LOGGER.error(\"class=ESIndexDAO||method=editAlias||clusterName={}\", cluster, e);\n                ParsingExceptionUtils.abnormalTermination(e);\n\n            }\n            return null;\n        };\n        ESIndicesPutAliasResponse response = esIndicesPutAliasResponseBiFunction.apply(Long.valueOf(ES_OPERATE_TIMEOUT),\n                TimeUnit.SECONDS);\n    \n        final Boolean acknowledged = Optional.ofNullable(response).map(ESIndicesPutAliasResponse::getAcknowledged)\n                .orElse(Boolean.FALSE);\n        if (Boolean.FALSE.equals(acknowledged)) {\n            // 针对第一种情况进行别名存在的情况判断，不存在则认为删除成功\n            final Map<String, AliasIndexNode> aliasesByIndices = getAliasesByIndices(cluster, indeies);\n            if (Objects.isNull(aliasesByIndices)) {\n                return false;\n            }\n            // 如果不包含，则都删除成功了\n            return aliasesByIndices.values().stream().map(AliasIndexNode::getAliases).map(Map::keySet)\n                    .flatMap(Collection::stream).noneMatch(aliasLit::contains);\n        \n        }\n    \n        return acknowledged;\n    }\n\n    public Result<Void> rollover(String cluster, String alias, String conditions) {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class=ESIndexDAO||method=rollover||errMsg=es client not found\");\n            return Result.buildFail(\"所属集群异常，请检查集群是否正常\");\n        }\n        \n\n        try {\n            DirectRequest directRequest = new DirectRequest(HttpMethod.POST.name(), alias + ROLLOVER_API);\n            if (StringUtils.isNotBlank(conditions)) {\n                directRequest.setPostContent(conditions);\n            }\n            DirectResponse directResponse = client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT,\n                TimeUnit.SECONDS);\n            return Result.buildWithMsg(RestStatus.OK == directResponse.getRestStatus(),\n                    RestStatus.OK == directResponse.getRestStatus() ? String.format(\"别名 %s 执行 rollover 成功\", alias)\n                            : directResponse.getResponseContent());\n        }catch (ESAlreadyExistsException e){\n            return Result.buildFail(String.format(\"%s 需要先删除此索引\",\n                    ParsingExceptionUtils.getESErrorMessageByException(e)));\n        }\n        catch (Exception e) {\n            final String exception = ParsingExceptionUtils.getESErrorMessageByException(e);\n            if (Objects.nonNull(exception)) {\n                return Result.buildFail(exception);\n            }\n            \n            \n            LOGGER.warn(\"class=ESIndexDAO||method=rollover||errMsg=index rollover fail\");\n            return Result.buildFail(String.format(FAILED_MSG, \"rollover\"));\n        }\n    }\n    \n    \n    public int countIndexByAlias(String cluster, String alias) throws ESOperateException {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class=ESIndexDAO||method=rollover||errMsg=es client not found\");\n            throw new ESOperateException(String.format(\"所属集群 %s 异常，请检查集群是否正常\", cluster));\n        }\n        DirectRequest directRequest = new DirectRequest(HttpMethod.GET.name(), String.format(ALIAS_API, alias));\n        try {\n            DirectResponse directResponse = client.direct(directRequest)\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            if (RestStatus.OK != directResponse.getRestStatus()) {\n                throw new ESOperateException(directResponse.getResponseContent());\n            }\n            return JSONObject.parseObject(directResponse.getResponseContent()).values().size();\n            \n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESIndexDAO||method=countIndexByAlias||errMsg=index countIndexByAlias fail\");\n            ParsingExceptionUtils.abnormalTermination(e);\n\n        }\n        return 0;\n    }\n    \n\n    public Result<Void> forceMerge(String cluster, String index, Integer maxNumSegments, Boolean onlyExpungeDeletes) {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class={}||method=forceMerge||cluster={}||index={}||errMsg=es client not found\",\n                    getClass().getSimpleName(), client, index);\n            return Result.buildFail();\n        }\n\n        try {\n            Map<String, String> params = new HashMap<>();\n            if (Boolean.TRUE.equals(onlyExpungeDeletes)) {\n                params.put(ONLY_EXPUNGE_DELETES, Boolean.TRUE.toString());\n            } else if (null != maxNumSegments) {\n                params.put(MAX_NUM_SEGMENTS, maxNumSegments.toString());\n            }\n\n            DirectRequest directRequest = new DirectRequest(HttpMethod.POST.name(), index + \"/_forcemerge\");\n            directRequest.setParams(params);\n            DirectResponse directResponse = client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT,\n                TimeUnit.SECONDS);\n            return Result.buildWithMsg(RestStatus.OK == directResponse.getRestStatus(),\n                directResponse.getResponseContent());\n        } catch (Exception e) {\n            final String exception = ParsingExceptionUtils.getESErrorMessageByException(e);\n            if (Objects.nonNull(exception)) {\n                return Result.buildFail(exception);\n            }\n            LOGGER.warn(\"class=ESIndexDAO||method=forceMerge||errMsg=index forceMerge fail\");\n            return Result.buildFail(String.format(FAILED_MSG, \"forceMerge\"));\n        }\n    }\n\n    public Result<Void> shrink(String cluster, String index, String targetIndex, String config) {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class=ESIndexDAO||method=forceMerge||errMsg=es client not found\");\n            return Result.buildFail();\n        }\n    \n        try {\n            DirectRequest directRequest = new DirectRequest(HttpMethod.POST.name(), index + \"/_shrink/\" + targetIndex);\n            directRequest.setPostContent(config);\n            DirectResponse directResponse = client.direct(directRequest)\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return Result.buildWithMsg(RestStatus.OK == directResponse.getRestStatus(),\n                    directResponse.getResponseContent());\n        } catch (ESAlreadyExistsException e) {\n            return Result.buildFail(String.format(\"%s 需要先删除此索引\",\n                    ParsingExceptionUtils.getESErrorMessageByException(e)));\n        } catch (Exception e) {\n            final String exception = ParsingExceptionUtils.getESErrorMessageByException(\n                    e);\n        \n            if (Objects.nonNull(exception)) {\n                return Result.buildFail(exception);\n            }\n            LOGGER.warn(\"class=ESIndexDAO||method=shrink||errMsg=index shrink fail\");\n            return Result.buildFail(String.format(FAILED_MSG, \"shrink\"));\n        }\n    }\n\n    public Result<Void> split(String cluster, String index, String targetIndex, String config) {\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class=ESIndexDAO||method=forceMerge||errMsg=es client not found\");\n            return Result.buildFail();\n        }\n        if (Double.parseDouble(client.getEsVersion().substring(0, 2))<=6.0) {\n            return Result.buildFail(String.format(\"es %s 不支持 split 功能\", client.getEsVersion()));\n        }\n        try {\n            DirectRequest directRequest = new DirectRequest(HttpMethod.POST.name(), index + \"/_split/\" + targetIndex);\n            directRequest.setPostContent(config);\n            DirectResponse directResponse = client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT,\n                TimeUnit.SECONDS);\n            return Result.buildWithMsg(RestStatus.OK == directResponse.getRestStatus(),\n                directResponse.getResponseContent());\n        } catch (ESAlreadyExistsException e) {\n            return Result.buildFail(String.format(\"%s 需要先删除此索引\",\n                    ParsingExceptionUtils.getESErrorMessageByException(e)));\n        } catch (Exception e) {\n            final String exception = ParsingExceptionUtils.getESErrorMessageByException(e);\n            if (Objects.nonNull(exception)) {\n                return Result.buildFail(exception);\n            }\n            LOGGER.warn(\"class=ESIndexDAO||method=split||errMsg=index split fail\");\n            return Result.buildFail(String.format(FAILED_MSG, \"split\"));\n        }\n    }\n \n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/cluster/ESPipelineDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_OPERATE_TIMEOUT;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ESPipelineProcessor;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NullESClientException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ParsingExceptionUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.request.ingest.Pipeline;\nimport com.didiglobal.knowframework.elasticsearch.client.response.ingest.ESDeletePipelineResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.ingest.ESGetPipelineResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.ingest.ESPutPipelineResponse;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Repository\npublic class ESPipelineDAO extends BaseESDAO {\n\n    public static final String           INDEX_TEMPLATE_PROCESSOR          = \"index_template\";\n    public static final String           THROTTLE_PROCESSOR                = \"throttle\";\n    public static final String           DATE_FIELD                        = \"field\";\n    public static final String           DATE_FIELD_FORMAT                 = \"field_format\";\n    public static final String           INDEX_NAME_FORMAT                 = \"index_name_format\";\n    public static final String           EXPIRE_DAY                        = \"expire_day\";\n    public static final String           INDEX_VERSION                     = \"index_version\";\n    public static final String           ID_FIELD                          = \"id_field\";\n    public static final String           ROUTING_FIELD                     = \"routing_field\";\n    public static final String           RATE_LIMIT                        = \"rate_limit\";\n    public static final String           MS_TIME_FIELD_ES_FORMAT           = \"UNIX_MS\";\n    public static final String           SECOND_TIME_FIELD_ES_FORMAT       = \"UNIX\";\n    public static final String           MS_TIME_FIELD_PLATFORM_FORMAT     = \"epoch_millis\";\n    public static final String           SECOND_TIME_FIELD_PLATFORM_FORMAT = \"epoch_second\";\n    public static final int              FILE_BEATS_PROCESSOR_INDEX        = 0;\n    public static final Set<String>      FILE_BEATS_PIPELINE_ID_SET        = new HashSet<>();\n    public static final List<JSONObject> FILE_BEATS_PROCESSOR              = new ArrayList<>();\n\n    static {\n        FILE_BEATS_PROCESSOR.add(JSON.parseObject(\n            \"{\\\"grok\\\":{\\\"field\\\":\\\"message\\\",\\\"patterns\\\":[\\\"%{GREEDYDATA}] {%{GREEDYDATA:message}\\\"]}}\"));\n        FILE_BEATS_PROCESSOR.add(JSON.parseObject(\"{\\\"set\\\":{\\\"field\\\":\\\"message\\\",\\\"value\\\":\\\"{ {{{message}}}\\\"}}\"));\n        FILE_BEATS_PROCESSOR.add(JSON.parseObject(\"{\\\"json\\\":{\\\"field\\\":\\\"message\\\",\\\"add_to_root\\\":true}}\"));\n        FILE_BEATS_PROCESSOR.add(\n            JSON.parseObject(\"{\\\"remove\\\":{\\\"field\\\":[\\\"message\\\",\\\"@timestamp\\\",\\\"flag\\\"],\\\"ignore_missing\\\":true}}\"));\n\n        FILE_BEATS_PIPELINE_ID_SET.add(\"arius.gateway.join\");\n        FILE_BEATS_PIPELINE_ID_SET.add(\"cn_arius_gateway_metrics\");\n    }\n\n    /**\n     * 创建\n     * @param cluster 集群\n     * @param pipelineId id\n     * @param dateField 时间字段\n     * @param dateFieldFormat 时间字段格式\n     * @param dateFormat 时间后缀\n     * @param expireDay 过期时间\n     * @param rateLimit 限流\n     * @return true/false\n     */\n    public boolean save(String cluster, String pipelineId, String dateField, String dateFieldFormat, String dateFormat,\n                        Integer expireDay, Integer rateLimit, Integer version, String idField, String routingField) {\n        LOGGER.info(\"class=ESPipelineDAO||method=save||cluster={}||pipelineId={}||dateField={}||\"\n                    + \"dateFieldFormat={}||dateFormat={}||expireDay={}||rateLimit={}||version={}||idField={}||\"\n                    + \"routingField={}\",\n            cluster, pipelineId, dateField, dateFieldFormat, dateFormat, expireDay, rateLimit, version, idField,\n            routingField);\n\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.error(\"class={}||method=save||clusterName={}||pipelineId={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster, pipelineId);\n            return false;\n        }\n        \n        Pipeline pipeline = null;\n\n        try {\n            pipeline = getPipeLine(cluster, pipelineId);\n        } catch (Exception e) {\n            LOGGER.warn(\n                \"class=ESPipelineDAO||method=save||cluster={}||pipelineId={}||msg=failed to get pipeline||exception={}\",\n                cluster, pipelineId, e);\n        }\n\n        if (pipeline == null) {\n            pipeline = new Pipeline();\n        }\n\n        pipeline.setDescription(pipelineId);\n        pipeline.setProcessors(buildProcessors(dateField, dateFieldFormat, dateFormat, expireDay, version, rateLimit,\n            pipeline.getProcessors()));\n\n        if (FILE_BEATS_PIPELINE_ID_SET.contains(pipelineId)) {\n            pipeline.getProcessors().addAll(FILE_BEATS_PROCESSOR_INDEX, FILE_BEATS_PROCESSOR);\n        }\n\n        ESPutPipelineResponse response = client.admin().indices().preparePutPipeline().setPipelineId(pipelineId)\n            .setPipeline(pipeline).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n        return response.getAcknowledged();\n\n    }\n\n    /**\n     * 删除pipeline\n     * @param cluster 集群\n     * @param pipelineId pipelineId\n     * @return true/false\n     */\n    public boolean delete(String cluster, String pipelineId) {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class={}||method=delete||clusterName={}||pipelineId={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster, pipelineId);\n            return false;\n        }\n\n        ESDeletePipelineResponse response = client.admin().indices().prepareDeletePipeline().setPipelineId(pipelineId)\n            .execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n        return response.getAcknowledged();\n    }\n\n    /**\n     * 获取pipeline\n     * @param cluster 集群\n     * @param pipelineId pipeline\n     * @return processor\n     */\n    public ESPipelineProcessor get(String cluster, String pipelineId) {\n        try {\n            Pipeline pipeline = getPipeLine(cluster, pipelineId);\n            if (pipeline == null) {\n                return null;\n            }\n            JSONObject process = pipeline.getProcessors().get(0);\n            if (FILE_BEATS_PIPELINE_ID_SET.contains(pipelineId)) {\n                process = pipeline.getProcessors().get(4);\n            }\n            return JSON.parseObject(JSON.toJSONString(process), ESPipelineProcessor.class);\n        } catch (Exception e) {\n            return null;\n        }\n    }\n\n    /**************************************** private method ****************************************************/\n\n    private Pipeline getPipeLine(String cluster, String pipelineId) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class={}||method=getPipeLine||clusterName={}||pipelineId={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster, pipelineId);\n            throw new NullESClientException(cluster);\n        }\n        try{\n            ESGetPipelineResponse response = client.admin().indices().prepareGetPipeline().setPipelineId(pipelineId)\n                    .execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n            Map<String, Pipeline> pipelineMap = response.getPipelineMap();\n            if (pipelineMap == null || !pipelineMap.containsKey(pipelineId)) {\n                return null;\n            }\n            return pipelineMap.get(pipelineId);\n        } catch (Exception e) {\n            LOGGER.error(\"class={}||method=getPipeLine||clusterName={}||pipelineId={}\",\n                    getClass().getSimpleName(), cluster, pipelineId,e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return null;\n    }\n\n    private List<JSONObject> buildProcessors(String dateField, String dateFieldFormat, String indexNameFormat,\n                                             Integer expireDay, Integer indexVersion, Integer rateLimit,\n                                             List<JSONObject> oldProcessors) {\n\n        if (MS_TIME_FIELD_PLATFORM_FORMAT.equals(dateFieldFormat)) {\n            dateFieldFormat = MS_TIME_FIELD_ES_FORMAT;\n        } else if (SECOND_TIME_FIELD_PLATFORM_FORMAT.equals(dateFieldFormat)) {\n            dateFieldFormat = SECOND_TIME_FIELD_ES_FORMAT;\n        }\n\n        if (indexNameFormat == null) {\n            indexNameFormat = \"\";\n        }\n\n        JSONObject pipelineProcessors = new JSONObject();\n\n        pipelineProcessors.put(INDEX_TEMPLATE_PROCESSOR, new JSONObject());\n        pipelineProcessors.put(THROTTLE_PROCESSOR, new JSONObject());\n\n        JSONObject indexTemplateProcessor = pipelineProcessors.getJSONObject(INDEX_TEMPLATE_PROCESSOR);\n        // 分区创建的\n        if (StringUtils.isNoneBlank(indexNameFormat)) {\n            indexTemplateProcessor.put(DATE_FIELD, dateField);\n            if (StringUtils.isNotBlank(dateFieldFormat)) {\n                indexTemplateProcessor.put(DATE_FIELD_FORMAT, dateFieldFormat);\n            }\n        }\n        indexTemplateProcessor.put(INDEX_NAME_FORMAT, indexNameFormat);\n        indexTemplateProcessor.put(EXPIRE_DAY, expireDay);\n        indexTemplateProcessor.put(INDEX_VERSION, indexVersion);\n\n        JSONObject throttle = pipelineProcessors.getJSONObject(THROTTLE_PROCESSOR);\n        throttle.put(RATE_LIMIT, rateLimit);\n\n        return Lists.newArrayList(pipelineProcessors);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/cluster/ESSecurityRoleDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.request.security.SecurityRole;\nimport com.didiglobal.knowframework.elasticsearch.client.request.security.SecurityRoleIndex;\nimport com.didiglobal.knowframework.elasticsearch.client.response.security.ESGetSecurityRoleResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.security.ESPutSecurityRoleResponse;\nimport com.google.common.collect.Lists;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_OPERATE_TIMEOUT;\n\n/**\n * @author didi\n */\n@Repository\npublic class ESSecurityRoleDAO extends BaseESDAO {\n\n    /**\n     * 获取角色\n     * @param cluster 集群\n     * @param roleName 角色名字\n     * @return result\n     */\n    public SecurityRole getNyName(String cluster, String roleName) {\n        ESClient client = esOpClient.getESClient(cluster);\n        ESGetSecurityRoleResponse response = client.admin().indices().prepareGetSecurityRole().setRoleName(roleName)\n            .execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        Map<String, SecurityRole> roleMap = response.getRoleMap();\n        return roleMap == null ? null : roleMap.get(roleName);\n    }\n\n    /**\n     * put角色\n     * @param cluster 集群\n     * @param roleName 角色名字\n     * @param expression 索引\n     * @param privilegeSet 权限点\n     * @return result\n     */\n    public boolean putRole(String cluster, String roleName, String expression, Set<String> privilegeSet) {\n        ESClient client = esOpClient.getESClient(cluster);\n        ESPutSecurityRoleResponse response = client.admin().indices().preparePutSecurityRole().setName(roleName)\n            .setRole(buildRole(expression, privilegeSet)).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        LOGGER.info(\"class=ESSecurityRoleDAO||method=putRole||cluster={}||roleName={}||response={}\", cluster, roleName,\n            response.getRole().toJSONString());\n        return true;\n    }\n\n    /**************************************** private method ****************************************************/\n\n    private SecurityRole buildRole(String expression, Set<String> privilegeSet) {\n        SecurityRoleIndex securityRoleIndex = new SecurityRoleIndex();\n        securityRoleIndex.setNames(Lists.newArrayList(expression));\n        securityRoleIndex.setPrivileges(Lists.newArrayList(privilegeSet));\n        SecurityRole securityRole = new SecurityRole();\n        securityRole.setIndices(Lists.newArrayList(securityRoleIndex));\n        return securityRole;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/cluster/ESSecurityUserDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.cluster;\n\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.request.security.SecurityUser;\nimport com.didiglobal.knowframework.elasticsearch.client.response.security.ESGetSecurityUserResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.security.ESPutSecurityUserResponse;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_OPERATE_TIMEOUT;\n\n/**\n * @author didi\n */\n@Repository\npublic class ESSecurityUserDAO extends BaseESDAO {\n\n    /**\n     * 获取用户\n     * @param cluster 集群\n     * @param userName 用户\n     * @return result\n     */\n    public SecurityUser getByName(String cluster, String userName) {\n        ESClient client = esOpClient.getESClient(cluster);\n        ESGetSecurityUserResponse response = client.admin().indices().prepareGetSecurityUser().setUserName(userName)\n            .execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        Map<String, SecurityUser> userMap = response.getUserMap();\n        return userMap == null ? null : userMap.get(userName);\n    }\n\n    /**\n     * put用户\n     * @param cluster 集群\n     * @param userName 用户\n     * @param securityUser 信息\n     * @return result\n     */\n    public boolean putUser(String cluster, String userName, SecurityUser securityUser) {\n        ESClient client = esOpClient.getESClient(cluster);\n        ESPutSecurityUserResponse response = client.admin().indices().preparePutSecurityUser().setName(userName)\n            .setUser(securityUser).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        LOGGER.info(\"class=ESSecurityUserDAO||method=putUser||cluster={}||roleName={}||response={}\", cluster, userName,\n            response.getCreated());\n        return true;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/cluster/ESShardDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.cluster;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.shard.ShardCatCellPO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NullESClientException;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Repository;\n\nimport javax.annotation.PostConstruct;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterQuickCommandMethodsEnum.SHARD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterQuickCommandMethodsEnum.SHARD_ASSIGNMENT;\n\n/**\n * Created by linyunan on 3/22/22\n */\n@Repository\npublic class ESShardDAO extends BaseESDAO {\n\n    @Value(\"${es.update.cluster.name}\")\n    private String              metadataClusterName;\n\n    @Autowired\n    private ESIndexDAO indexDAO;\n\n    /**\n     * 索引名称\n     */\n    private String              indexName;\n    /**\n     * type名称\n     */\n    private String              typeName                   = \"type\";\n    private String              shard                      = \"shard\";\n    private String              store                      = \"store\";\n    private String              docs                       = \"docs\";\n    private String              index                      = \"index\";\n    private String              ip                         = \"ip\";\n    private String              node                       = \"node\";\n    private String              prirep                     = \"prirep\";\n    private String              state                      = \"state\";\n    private String              CLOSED                     = \"closed\";\n    private String              OPEN                       = \"open\";\n\n    private static final FutureUtil<List<ShardCatCellPO>> CAT_SHARD_FUTURE = FutureUtil.init(\"CAT_SHARD_FUTURE\", 10, 10, 100);\n\n\n    @PostConstruct\n    public void init() {\n        this.indexName = dataCentreUtil.getAriusCatShardInfo();\n    }\n\n    public List<ShardCatCellPO> catShard(String clusterName) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(clusterName);\n        if (Objects.isNull(client)) {\n            LOGGER.error(\"class=ESClusterDAO||method=catShard||clusterName={}||errMsg=esClient is null\", clusterName);\n            throw new NullESClientException(clusterName);\n        }\n        try {\n            return getShardCatCellPOS(clusterName, client, SHARD.getUri());\n        } catch (Exception e) {\n            final String exception = ParsingExceptionUtils.getESErrorMessageByException(\n                    e);\n            if (StringUtils.equals(exception,CLOSED)){\n                return getLowerVersionShardCatCellPOList(clusterName);\n            }\n            LOGGER.warn(\"class=ESClusterDAO||method=catShard||cluster={}||mg=get es segments fail\", clusterName, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return new ArrayList<>();\n    }\n\n    /**\n     *  获取低版本的shard分布数据\n     * @param cluster 物理集群\n     * @return\n     */\n    private List<ShardCatCellPO> getLowerVersionShardCatCellPOList(String cluster) throws ESOperateException {\n\n        List<ShardCatCellPO> shardCatCellPOS = Lists.newArrayList();\n        ESClient client = fetchESClientByCluster(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        try {\n            List<CatIndexResult> catIndexResults = indexDAO.catIndices(cluster);\n            List<String> openIndexNames = catIndexResults.stream().filter(index->StringUtils.equals(OPEN,index.getStatus()))\n                    .map(CatIndexResult::getIndex).collect(Collectors.toList());\n            //如果索引特别多，需要分批构造uri进行处理\n            List<List<String>> openIndexNamesList = org.apache.commons.collections4.ListUtils.partition(openIndexNames, 50);\n            for(List<String> openIndexNamePartition:openIndexNamesList){\n                String uri = SHARD.getUri() + \"/\" + String.join(\",\", openIndexNamePartition);\n                CAT_SHARD_FUTURE.callableTask(()->getShardCatCellPOS(cluster, client, uri));\n            }\n            CAT_SHARD_FUTURE.waitResult().forEach(catCellList->shardCatCellPOS.addAll(catCellList));\n            return shardCatCellPOS;\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESShardDao||method=getLowerVersionShardCatCellPOList||clusterName={}\", cluster,\n                    e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return Lists.newArrayList();\n    }\n\n    /**\n     * 获取集群下的shard分布信息\n     * @param cluster 物理集群\n     * @param client client\n     * @param uri uri\n     * @return\n     */\n    private List<ShardCatCellPO> getShardCatCellPOS(String cluster, ESClient client, String uri) throws ESOperateException {\n        try{\n            DirectRequest directRequest = new DirectRequest(SHARD.getMethod(), uri);\n            DirectResponse directResponse = client.direct(directRequest).actionGet(30, TimeUnit.SECONDS);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                    && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                return buildShardCatCellPOs(directResponse.getResponseContent(), cluster);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESShardDAO||method=getShardCatCellPOS||clusterName={}||uri={}\", cluster,uri,\n                    e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return Collections.emptyList();\n    }\n\n    /**\n     * 通过集群名称获取对应的ES Client\n     * @param clusterName 集群名称\n     * @return\n     */\n    private ESClient fetchESClientByCluster(String clusterName) {\n        ESClient client = esOpClient.getESClient(clusterName);\n        if (client == null) {\n            LOGGER.warn(\"class=ESIndexDAO||method=fetchESClientByCluster||cannot get es client,cluster={}\",\n                    clusterName);\n        }\n        return client;\n    }\n\n    private List<ShardCatCellPO> buildShardCatCellPOs(String responseContent, String clusterName) {\n        List<ShardCatCellPO> shardCatCellPOList = new ArrayList<>();\n        JSONArray jsonArray = JSONArray.parseArray(responseContent);\n        for (int i = 0; i < jsonArray.size(); i++) {\n            JSONObject shardInfo = jsonArray.getJSONObject(i);\n            String shardStr = shardInfo.getString(shard);\n            String storeStr = shardInfo.getString(store);\n            String docsStr = shardInfo.getString(docs);\n\n            ShardCatCellPO shardCatCellPO = new ShardCatCellPO();\n            shardCatCellPO.setClusterPhy(clusterName);\n            shardCatCellPO.setShard(shardStr);\n            shardCatCellPO.setStore(storeStr);\n            shardCatCellPO.setDocs(docsStr);\n            shardCatCellPO.setIndex(shardInfo.getString(index));\n            shardCatCellPO.setIp(shardInfo.getString(ip));\n            shardCatCellPO.setNode(shardInfo.getString(node));\n            shardCatCellPO.setPrirep(shardInfo.getString(prirep));\n            shardCatCellPO.setState(shardInfo.getString(state));\n            shardCatCellPOList.add(shardCatCellPO);\n        }\n        return shardCatCellPOList;\n    }\n    \n    /**\n     * shard分配说明\n     * @param clusterPhyName 物理集群名称\n     * @return\n     */\n    public String shardAssignment(String clusterPhyName) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(clusterPhyName);\n        String result = null;\n        if (Objects.isNull(client)) {\n            LOGGER.error(\"class=ESClusterDAO||method=shardAssignment||clusterName={}||errMsg=esClient is null\", clusterPhyName);\n            throw new NullESClientException(clusterPhyName);\n        }\n        try {\n            DirectRequest directRequest = new DirectRequest(SHARD_ASSIGNMENT.getMethod(), SHARD_ASSIGNMENT.getUri());\n            DirectResponse directResponse = client.direct(directRequest).actionGet(30, TimeUnit.SECONDS);\n            if (directResponse.getRestStatus() == RestStatus.OK\n                    && StringUtils.isNoneBlank(directResponse.getResponseContent())) {\n                result = directResponse.getResponseContent();\n            }\n            return result;\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESClusterDAO||method=shardAssignment||msg=get es segments faill||cluster={}\", clusterPhyName,e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return null;\n    }\n\n    /**\n     * 根据条件获取Catshard信息\n     *\n     * @param from         起始值\n     * @param size         每页大小\n     * @param sortTerm     排序字段\n     * @param orderByDesc  是否降序\n     * @return             Tuple<Long, List<IndexCatCellPO>> 命中数 具体数据\n     */\n    public Tuple<Long, List<ShardCatCellPO>> getCatShardInfo(String cluster, Integer projectId,String keyword,\n                                                             Long from,\n                                                             Long size, String sortTerm, Boolean orderByDesc) {\n        Tuple<Long, List<ShardCatCellPO>> totalHitAndIndexCatCellListTuple;\n        String queryTermDsl =  buildQueryTermDsl(cluster,projectId,keyword);\n        String sortType     =  buildSortType(orderByDesc);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CAT_SHARD_INFO_BY_CONDITION,\n                queryTermDsl, sortTerm, sortType, from, size);\n        int retryTime = 3;\n        do {\n            totalHitAndIndexCatCellListTuple = gatewayClient.performRequestListAndGetTotalCount(metadataClusterName,\n                    IndexNameUtils.genCurrentDailyIndexName(indexName), typeName, dsl, ShardCatCellPO.class);\n        } while (retryTime-- > 0 && null == totalHitAndIndexCatCellListTuple);\n\n        return totalHitAndIndexCatCellListTuple;\n    }\n\n    /**\n     * 批量保存索引大小结果\n     *\n     * @param list\n     * @return\n     */\n    public boolean batchInsert(List<ShardCatCellPO> list) {\n        return updateClient.batchInsert(IndexNameUtils.genCurrentDailyIndexName(indexName), typeName, list);\n    }\n\n    /**************************************************private******************************************************/\n    /**\n     * 构建模糊查询dsl语法, 如下\n     * {\n     * \t\"term\": {\n     * \t\t\"index\": {\n     * \t\t\t\"value\": \"cn_arius.template.label\"\n     *                } \t}\n     * }\n     * @param cluster\n     * @return\n     */\n    private String buildQueryTermDsl(String cluster,  Integer projectId,String keyword) {\n        return \"[\" + buildTermCell(cluster, projectId,keyword) +\"]\";\n    }\n    private String buildTermCell(String cluster, Integer projectId, String keyword) {\n        List<String> termCellList = Lists.newArrayList();\n        //projectId == null 时，属于超级项目访问；\n        if (null == projectId) {\n            //get cluster dsl term\n            termCellList.add(DSLSearchUtils.getTermCellForExactSearch(cluster, \"clusterPhy\"));\n        } else {\n            //get projectId dsl term\n            termCellList.add(DSLSearchUtils.getTermCellForExactSearch(projectId, \"projectId\"));\n\n            //get resourceId dsl term\n            termCellList.add(DSLSearchUtils.getTermCellForExactSearch(cluster, \"clusterLogic\"));\n        }\n        termCellList.add(buildShouldTermCell(keyword));\n        return ListUtils.strList2String(termCellList);\n    }\n\n    /**\n     * 构造多字段模糊查询\n     * {\n     *           \"bool\": {\n     *             \"should\": [\n     *               {\n     *                 \"wildcard\": {\n     *                   \"ip\": {\n     *                     \"value\": \"*lyn-ks*\"\n     *                   }\n     *                 }\n     *               },{\n     *                 \"wildcard\": {\n     *                   \"index\": {\n     *                     \"value\": \"*lyn-ks*\"\n     *                   }\n     *                 }\n     *               }\n     *             ]\n     *           }\n     *         }\n     * @param keyword 关键字\n     * @return\n     */\n    private String buildShouldTermCell(String keyword){\n        //构造should的条件\n        List<String> shouldCellList = Lists.newArrayList();\n        if (StringUtils.isNotBlank(keyword)){\n            shouldCellList.add(DSLSearchUtils.getTermCellForWildcardSearch(keyword, \"index\"));\n            shouldCellList.add(DSLSearchUtils.getTermCellForWildcardSearch(keyword, \"node\"));\n            shouldCellList.add(DSLSearchUtils.getTermCellForWildcardSearch(keyword, \"ip\"));\n            shouldCellList.add(DSLSearchUtils.getTermCellForWildcardSearch(keyword, \"state\"));\n        }\n\n        return dslLoaderUtil.getFormatDslByFileName(DslsConstant.SHOULD_TERM_CELL,\n                ListUtils.strList2String(shouldCellList));\n    }\n\n\n    private String buildSortType(Boolean orderByDesc) {\n        String sortType = \"desc\";\n        if (orderByDesc == null) {\n            return sortType;\n        }\n\n        if (orderByDesc) {\n            return sortType;\n        }\n\n        return \"asc\";\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/cluster/ESTemplateDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_OPERATE_TIMEOUT;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.INDEX_SHARD_NUM;\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.TEMPLATE_DEFAULT_ORDER;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESSettingConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.TemplateHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NullESClientException;\nimport com.didichuxing.datachannel.arius.admin.common.function.BiFunctionWithESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ParsingExceptionUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.model.type.ESVersion;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.gettemplate.ESIndicesGetTemplateRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.request.index.puttemplate.ESIndicesPutTemplateRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.deletetemplate.ESIndicesDeleteTemplateResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.gettemplate.ESIndicesGetTemplateResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.puttemplate.ESIndicesPutTemplateResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.MultiTemplatesConfig;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.template.TemplateConfig;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.concurrent.TimeUnit;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Repository;\nimport org.springframework.web.bind.annotation.RequestMethod;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Repository\npublic class ESTemplateDAO extends BaseESDAO {\n    public static final String CAT_INDIES_HEALTH = \"/_cat/indices/%s?v=true&format=json&health=%s&filter_path=index\";\n    public static final String CAT_INDIES = \"/_cat/indices/%s?v=true&format=json&filter_path=index\";\n\n    /**\n     * 修改模板表达式\n     * @param cluster 集群\n     * @param name 模板名字\n     * @param expression 表达式\n     * @return result\n     */\n    public boolean updateExpression(String cluster, String name, String expression) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class={}||method=updateExpression||clusterName={}||expression={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster, expression);\n            throw new NullESClientException(cluster);\n        }\n        try {\n            // 获取es中原来index template的配置\n            ESIndicesGetTemplateResponse getTemplateResponse = client.admin().indices().prepareGetTemplate(name).execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            TemplateConfig templateConfig = getTemplateResponse.getMultiTemplatesConfig().getSingleConfig();\n\n            // 修改表达式\n            if (StringUtils.isNotBlank(expression)) {\n                templateConfig.setTemplate(expression);\n            }\n\n            // 设置ES版本\n            templateConfig.setVersion(client.getEsVersion());\n\n            ESIndicesPutTemplateResponse response = client.admin().indices().preparePutTemplate(name)\n                    .setTemplateConfig(templateConfig).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESTemplateDAO||method=updateExpression||clusterName={}||templateName=={}||expression={}\", cluster, name, expression, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 修改模板分片\n     * @param cluster 集群\n     * @param name 模板名字\n     * @param shardNum 表达式\n     * @return\n     */\n    public boolean updateShardNum(String cluster, String name, Integer shardNum) throws ESOperateException{\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class={}||method=updateShardNum||clusterName={}||shardNum={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster, shardNum);\n            throw new NullESClientException(cluster);\n        }\n\n        // 获取es中原来index template的配置\n         ESIndicesGetTemplateResponse getTemplateResponse = getESIndicesGetTemplateResponse(cluster,\n                name);\n        TemplateConfig templateConfig = getTemplateResponse.getMultiTemplatesConfig().getSingleConfig();\n       \n        // 修改分片数目\n        if (shardNum != null && shardNum > 0) {\n            templateConfig.setSettings(INDEX_SHARD_NUM, String.valueOf(shardNum));\n        }\n        \n\n        // 设置ES版本\n        templateConfig.setVersion(client.getEsVersion());\n        try {\n            ESIndicesPutTemplateResponse response = client.admin().indices().preparePutTemplate(name)\n                    .setTemplateConfig(templateConfig).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESTemplateDAO||method=updateShardNum||clusterName={}||templateName={}||shardNum={}\", cluster, name, shardNum, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 修改模板rack和shard\n     * @param cluster 集群\n     * @param name 模板名字\n     * @param shard shard\n     * @return result\n     */\n    public boolean updateShard(String cluster, String name, Integer shard, Integer shardRouting) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        try {\n            // 获取es中原来index template的配置\n            ESIndicesGetTemplateResponse getTemplateResponse = client.admin().indices().prepareGetTemplate(name).execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            TemplateConfig templateConfig = getTemplateResponse.getMultiTemplatesConfig().getSingleConfig();\n\n            if (shard != null && shard > 0) {\n                templateConfig.setSettings(INDEX_SHARD_NUM, String.valueOf(shard));\n            }\n\n            // 设置ES版本\n            templateConfig.setVersion(client.getEsVersion());\n\n            ESIndicesPutTemplateResponse response = client.admin().indices().preparePutTemplate(name)\n                    .setTemplateConfig(templateConfig).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESTemplateDAO||method=updateShard||clusterName={}||templateName={}\", cluster, name, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 删除模板\n     * @param cluster 集群\n     * @param templateName 模板名字\n     * @return result\n     */\n    public boolean delete(String cluster, String templateName) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class={}||method=delete||clusterName={}||templateName={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster, templateName);\n            throw new NullESClientException(cluster);\n        }\n        \n        \n        ESIndicesDeleteTemplateResponse response=null;\n        try {\n            if (!exist(cluster, templateName)) {\n                return true;\n            }\n    \n            response = client.admin().indices().prepareDeleteTemplate(templateName).execute()\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESTemplateDAO||method=delete||cluster={}||name={}\", cluster, templateName, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return Optional.ofNullable(response).map(ESIndicesDeleteTemplateResponse::getAcknowledged).orElse(false);\n    }\n    \n    public boolean exist(String cluster, String templateName) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\"class={}||method=delete||clusterName={}||templateName={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster, templateName);\n            throw new NullESClientException(cluster);\n        }\n        try {\n            \n            ESIndicesGetTemplateRequest request = new ESIndicesGetTemplateRequest();\n            Map<String, TemplateConfig> templateConfigMap = client.admin().indices().getTemplate(request)\n                    .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS).getMultiTemplatesConfig().getTemplateConfigMap();\n            return templateConfigMap.containsKey(templateName);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=ESTemplateDAO||method=delete||cluster={}||name={}\", cluster, templateName, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 保存模板\n     * @param cluster 集群\n     * @param name 名字\n     * @param expression 表达式\n     * @param shard shard\n     * @param shardRouting shardRouting\n     * @return result\n     */\n    public boolean create(String cluster, String name, String expression, Integer shard, Integer shardRouting) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            LOGGER.warn(\n                    \"class=ESTemplateDAO||method=create||msg=es client is null||cluster={}||name={}||expression={}||shard={}||shardRouting={}\",\n                    cluster, name, expression, shard, shardRouting);\n            throw new NullESClientException(cluster);\n        }\n    \n        // 获取es中原来index template的配置\n        BiFunctionWithESOperateException<Long, TimeUnit, ESIndicesGetTemplateResponse> getTemplateResponseBiFunction = (time, unit) -> {\n            try {\n                return client.admin().indices().prepareGetTemplate(name + \"*\").execute()\n                        .actionGet(time,unit);\n            } catch (Exception e) {\n                \n                LOGGER.warn(\"class=ESTemplateDAO||method=create||msg=get src template fail||cluster={}||name={}\",\n                        cluster, name);\n                return null;\n            }\n        };\n        ESIndicesGetTemplateResponse esIndicesGetTemplateResponse =  getTemplateResponseBiFunction.apply(Long.valueOf(ES_OPERATE_TIMEOUT), TimeUnit.SECONDS);\n    \n        TemplateConfig templateConfig = Optional.ofNullable(esIndicesGetTemplateResponse)\n                .map(ESIndicesGetTemplateResponse::getMultiTemplatesConfig).map(MultiTemplatesConfig::getSingleConfig)\n                .orElse(new TemplateConfig());\n       \n\n       \n        if (StringUtils.isNotBlank(expression)) {\n            templateConfig.setTemplate(expression);\n        }\n\n        if (shard != null && shard > 0) {\n            templateConfig.setSettings(INDEX_SHARD_NUM, String.valueOf(shard));\n        }\n\n        //开源版本不支持这个参数，先注释\n        /*if (shardRouting != null) {\n            templateConfig.setSettings(INDEX_SHARD_ROUTING_NUM, String.valueOf(shardRouting));\n        }*/\n\n        if (templateConfig.getOrder() == null) {\n            templateConfig.setOrder(TEMPLATE_DEFAULT_ORDER);\n        }\n\n        // 设置ES版本\n        templateConfig.setVersion(client.getEsVersion());\n        \n        BiFunctionWithESOperateException<Long, TimeUnit, ESIndicesPutTemplateResponse> getESIndicesPutTemplateResponseBiFunction = (time, unit) -> {\n            try {\n                return client.admin().indices().preparePutTemplate(name).setTemplateConfig(templateConfig)\n                        .execute().actionGet(time, unit);\n            } catch (Exception e) {\n                LOGGER.error(\"class=ESTemplateDAO||method=create||msg=put template fail||cluster={}||name={}\", cluster,\n                        name, e);\n                ParsingExceptionUtils.abnormalTermination(e);\n            }\n            return null;\n        };\n        ESIndicesPutTemplateResponse esIndicesPutTemplateResponse =getESIndicesPutTemplateResponseBiFunction.apply(Long.valueOf(ES_OPERATE_TIMEOUT),\n                            TimeUnit.SECONDS);\n    \n        return Optional.ofNullable(\n                        esIndicesPutTemplateResponse)\n                .map(ESIndicesPutTemplateResponse::getAcknowledged).orElse(false);\n                \n    }\n\n    public boolean create(String cluster, String name, TemplateConfig templateConfig) throws ESOperateException{\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client==null){\n            LOGGER.warn(\"class=ESTemplateDAO||method=create||msg=es client is null ||cluster={}||name={}||templateConfig={}\", cluster,\n                name,templateConfig.toString());\n            throw new NullESClientException(cluster);\n        }\n\n        // 设置ES版本\n        templateConfig.setVersion(client.getEsVersion());\n        // 向ES中创建模板流程\n        BiFunctionWithESOperateException<Long, TimeUnit, ESIndicesPutTemplateResponse> responseBiFunction = (time, unit) -> {\n            try {\n                return client.admin().indices().preparePutTemplate(name).setTemplateConfig(templateConfig).execute()\n                        .actionGet(time, unit);\n            \n            } catch (Exception e) {\n                LOGGER.error(\"class=ESTemplateDAO||method=create||put templates fail||clusterName={}||templateName={}\",\n                        cluster, name, e);\n                ParsingExceptionUtils.abnormalTermination(e);\n            }\n            return null;\n        };\n        ESIndicesPutTemplateResponse esIndicesPutTemplateResponse = responseBiFunction.apply(\n                Long.valueOf(ES_OPERATE_TIMEOUT), TimeUnit.SECONDS);\n    \n        return Optional.ofNullable(esIndicesPutTemplateResponse)\n                .map(ESIndicesPutTemplateResponse::getAcknowledged).orElse(false);\n    }\n\n    /**\n     * 更新模板配置\n     * @param clusterName       集群名\n     * @param templateName      模版名\n     * @param templateConfig    模版配置\n     * @return result\n     */\n    public boolean updateTemplate(String clusterName, String templateName, TemplateConfig templateConfig)\n            throws ESOperateException {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n        if (esClient == null) {\n            LOGGER.warn(\n                    \"class=ESTemplateDAO||method=updateTemplate||update template  fail||clusterName={}||templateName={}||esVersion={}||templateConfig={}||msg=es client is null\",\n                    clusterName, templateName, templateConfig.toString());\n            throw new NullESClientException(clusterName);\n        }\n\n        // 设置ES版本\n        templateConfig.setVersion(esClient.getEsVersion());\n\n        ESIndicesPutTemplateRequest request = new ESIndicesPutTemplateRequest();\n        request.setTemplate(templateName);\n        request.setTemplateConfig(templateConfig);\n\n        ESIndicesPutTemplateResponse response = null;\n        try {\n            response = esClient.admin().indices().putTemplate(request).actionGet(120, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.warn(\n                    \"class=ESTemplateDAO||method=updateTemplate||update template fail||clusterName={}||templateName={}||esVersion={}||templateConfig={}||msg={}\",\n                    clusterName, templateName, esClient.getEsVersion(),\n                    templateConfig.toJson(ESVersion.valueBy(esClient.getEsVersion())), e.getMessage(), e);\n            ParsingExceptionUtils.abnormalTermination(e);\n           \n        }\n\n        return response.getAcknowledged();\n    }\n    \n    /**\n     * 同步获取集群是正常\n     *\n     * @param clusterName 集群名称\n     * @return boolean\n     */\n    public boolean syncGetClusterIsNormal(String clusterName) {\n        return esOpClient.getESClient(clusterName) != null;\n    }\n    /**\n     * 获取模板信息\n     * @param clusterName       集群名\n     * @param templateName      模版名\n     * @return result\n     */\n    public TemplateConfig getTemplate(String clusterName, String templateName) throws ESOperateException {\n        MultiTemplatesConfig templatesConfig = getTemplates(clusterName, templateName);\n\n        if (templatesConfig == null) {\n            return null;\n        }\n\n        return templatesConfig.getSingleConfig();\n    }\n\n    /**\n     * 获取所有引擎模板\n     * @param clusters 集群列表\n     * @return\n     */\n    public Map<String, TemplateConfig> getAllTemplate(List<String> clusters) throws ESOperateException {\n        Map<String, TemplateConfig> map = new HashMap<>();\n        for (String clusterName : clusters) {\n            \n            MultiTemplatesConfig templatesConfig = getTemplates(clusterName, null);\n\n            if (null == templatesConfig) {\n                return null;\n            }\n            map.putAll(templatesConfig.getTemplateConfigMap());\n        }\n        return map;\n    }\n\n    /**\n     * 获取mapping配置\n     * @param clusterName       集群名\n     * @param templateName      模版名\n     * @return result\n     */\n    public MappingConfig getTemplateMapping(String clusterName, String templateName) throws ESOperateException {\n        MultiTemplatesConfig templatesConfig = getTemplates(clusterName, templateName);\n\n        if (templatesConfig == null || templatesConfig.getSingleConfig() == null) {\n            return null;\n        }\n\n        return templatesConfig.getSingleConfig().getMappings();\n    }\n\n    /**\n     * 获取模板信息\n     * @param clusterName       集群名\n     * @param templateName      模版名\n     * @return result\n     */\n    public MultiTemplatesConfig getTemplates(String clusterName, String templateName)\n            throws ESOperateException {\n\n      \n\n        ESClient esClient = esOpClient.getESClient(clusterName);\n\n        if (null == esClient) {\n            LOGGER.warn(\"class=ESTemplateDAO||method=getTemplates||clusterName={}||templateName={}||msg= es client is null\",\n                    clusterName,\n            templateName);\n            return null;\n        }\n    \n        ESIndicesGetTemplateResponse response = getESIndicesGetTemplateResponse(clusterName,\n                templateName);\n    \n        if (response == null) {\n            return null;\n        }\n\n        LOGGER.debug(\"class=ESTemplateDAO||method=getTemplates||clusterName={}||templateName={}\", clusterName, templateName);\n\n        return response.getMultiTemplatesConfig();\n    }\n    \n    protected ESIndicesGetTemplateResponse getESIndicesGetTemplateResponse(String clusterName, String templateName)\n            throws ESOperateException {\n        ESClient esClient = esOpClient.getESClient(clusterName);\n    \n        if (esClient == null) {\n            LOGGER.error(\"class={}||method=delete||clusterName={}||templateName={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), clusterName, templateName);\n            throw new NullESClientException(clusterName);\n        }\n        if (templateName != null && !exist(clusterName, templateName)) {\n            return null;\n        }\n        ESIndicesGetTemplateRequest request = new ESIndicesGetTemplateRequest();\n        request.setTemplates(templateName);\n    \n        BiFunctionWithESOperateException<Long, TimeUnit, ESIndicesGetTemplateResponse> responseBiFunction = (time, unit) -> {\n            try {\n                return esClient.admin().indices().getTemplate(request).actionGet(time, unit);\n            \n            } catch (Exception e) {\n                LOGGER.warn(\n                        \"class=ESTemplateDAO||method=getTemplates||get templates fail||clusterName={}||templateName={}||msg={}\",\n                        clusterName, templateName, e.getMessage(), e);\n                ParsingExceptionUtils.abnormalTermination(e);\n            }\n            return null;\n        };\n        \n        return responseBiFunction.apply(Long.valueOf(ES_OPERATE_TIMEOUT),\n                            TimeUnit.SECONDS);\n            \n    }\n\n    /**\n     * 更新配置\n     * @param cluster 集群\n     * @param name    模板\n     * @param setting setting\n     * @return result\n     */\n    public boolean upsertSetting(String cluster, String name, Map<String, String> setting) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n          if (client == null ) {\n           \n            LOGGER.warn(\"class={}||method=upsertSetting||cluster={}||name={}||errMsg=client is null \",\n                    getClass().getSimpleName(), cluster, name);\n            return false;\n        }\n\n        // 获取es中原来index template的配置\n        ESIndicesGetTemplateResponse getTemplateResponse = client.admin().indices().prepareGetTemplate(name).execute()\n            .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        TemplateConfig templateConfig = getTemplateResponse.getMultiTemplatesConfig().getSingleConfig();\n\n        for (Map.Entry<String, String> entry : setting.entrySet()) {\n            templateConfig.setSettings(entry.getKey(), entry.getValue());\n        }\n\n        try {\n            ESIndicesPutTemplateResponse response = client.admin().indices().preparePutTemplate(name)\n                    .setTemplateConfig(templateConfig).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ESTemplateDAO||method=upsertSetting||clusterName={}\", cluster,\n                    e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n    \n    \n    /**\n     * 它更新索引模板设置并检查分配包含名称。\n     *\n     * @param cluster 集群名称\n     * @param name 索引模板名称\n     * @param setting 索引模板的配置\n     */\n    public boolean updateSettingCheckAllocationAndShard(String cluster, String name,\n                                                        Map<String, String> setting) throws ESOperateException {\n        ESClient client = esOpClient.getESClient(cluster);\n          if (client == null ) {\n           \n            LOGGER.warn(\"class={}||method=upsertSetting||cluster={}||name={}||errMsg=client is null \",\n                    getClass().getSimpleName(), cluster, name);\n            throw new NullESClientException(cluster);\n        }\n\n        // 获取es中原来index template的配置\n        ESIndicesGetTemplateResponse getTemplateResponse = client.admin().indices().prepareGetTemplate(name).execute()\n            .actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        TemplateConfig templateConfig = getTemplateResponse.getMultiTemplatesConfig().getSingleConfig();\n        final String indexRoutingAllocationIncludeName =\n                templateConfig.getSetttings().get(ESSettingConstant.INDEX_ROUTING_ALLOCATION_INCLUDE_NAME);\n        //index.routing.allocation.include._name\n        if (!StringUtils.equals(setting.get(ESSettingConstant.INDEX_ROUTING_ALLOCATION_INCLUDE_NAME),\n                indexRoutingAllocationIncludeName)) {\n            throw new ESOperateException(\n                    \"模版分片分配节点配置属于系统权限，不允许变更 index.routing.allocation.include._name\");\n        }\n        final String indexNumberOfShards = templateConfig.getSetttings().get(ESSettingConstant.INDEX_NUMBER_OF_SHARDS);\n        //shard\n        if (!StringUtils.equals(setting.get(ESSettingConstant.INDEX_NUMBER_OF_SHARDS),\n                indexNumberOfShards)) {\n            throw new ESOperateException(\n                    \"模版设置 shard 大小设置属于系统权限, 非运维人员不允许变更 index.number_of_shards\");\n        \n        }\n        templateConfig.setSetttings(setting);\n        \n\n        try {\n            ESIndicesPutTemplateResponse response = client.admin().indices().preparePutTemplate(name)\n                    .setTemplateConfig(templateConfig).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            return response.getAcknowledged();\n        } catch (Exception e) {\n            LOGGER.error(\n                    \"class=ESTemplateDAO||method=updateSettingCheckAllocationAndShard||cluster={}||name={}\",\n                    cluster, name,  e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        return false;\n    }\n\n    /**\n     * 拷贝模板\n     * @param srcCluster 源集群\n     * @param srcTemplateName 原模板\n     * @param tgtCluster 目标集群\n     * @param tgtTemplateName 目标模板\n     * @return result\n     */\n    public boolean copyMappingAndAlias(String srcCluster, String srcTemplateName, String tgtCluster,\n                                       String tgtTemplateName) throws ESOperateException {\n\n        ESClient srcClient = esOpClient.getESClient(srcCluster);\n        ESClient tgtClient = esOpClient.getESClient(tgtCluster);\n        if (srcClient == null) {\n            throw new NullESClientException(srcCluster);\n        }\n        if (tgtClient == null) {\n            throw new NullESClientException(tgtCluster);\n        }\n        ESIndicesPutTemplateResponse response = new ESIndicesPutTemplateResponse();\n        response.setAcknowledged(false);\n\n        try {\n            // 获取es中原来index template的配置\n            ESIndicesGetTemplateResponse getSrcTemplateResponse = srcClient.admin().indices()\n                .prepareGetTemplate(srcTemplateName).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            TemplateConfig srcTemplateConfig = getSrcTemplateResponse.getMultiTemplatesConfig().getSingleConfig();\n\n            // 获取es中目标index template的配置\n            ESIndicesGetTemplateResponse getTgtTemplateResponse = tgtClient.admin().indices()\n                .prepareGetTemplate(tgtTemplateName).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n            TemplateConfig tgtTemplateConfig = getTgtTemplateResponse.getMultiTemplatesConfig().getSingleConfig();\n\n            if (srcTemplateConfig == null || tgtTemplateConfig == null) {\n                return false;\n            }\n\n            tgtTemplateConfig.setMappings(srcTemplateConfig.getMappings());\n            tgtTemplateConfig.setAliases(srcTemplateConfig.getAliases());\n            tgtTemplateConfig.setVersion(tgtClient.getEsVersion());\n\n            response = tgtClient.admin().indices().preparePutTemplate(tgtTemplateName)\n                .setTemplateConfig(tgtTemplateConfig).execute().actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.error(\n                    \"class=ESTemplateDAO||method=copyMappingAndAlias||srcCluster={}||srcTemplateName={}||tgtCluster={}||tgtTemplateName={}\",\n                    srcCluster, srcTemplateName, tgtCluster, tgtTemplateName, e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n\n        return response.getAcknowledged();\n    }\n    \n    \n  \n    /**\n     * > 通过表达式模板健康枚举判断是否有匹配索引\n     *\n     * @param cluster 集群名称\n     * @param expression 索引名称表达式，可以是通配符表达式，如“logstash-*”\n     * @param templateHealthEnum 索引的状态，为枚举类，枚举类如下：\n     */\n    public boolean hasMatchHealthIndexByExpressionTemplateHealthEnum(String cluster, String expression,\n                                                                     TemplateHealthEnum templateHealthEnum) throws ESOperateException{\n        ESClient client = esOpClient.getESClient(cluster);\n        if (client == null) {\n            throw new NullESClientException(cluster);\n        }\n        try {\n            DirectResponse response = getDirectResponseByClusterAndUrl(client,\n                    String.format(CAT_INDIES_HEALTH, expression, templateHealthEnum.getDesc()));\n        \n            if (templateHealthEnum.equals(TemplateHealthEnum.GREEN)) {\n                DirectResponse directResponse = getDirectResponseByClusterAndUrl(client,\n                        String.format(CAT_INDIES, expression));\n                return (response.getRestStatus() == RestStatus.OK && StringUtils.isNotBlank(\n                        response.getResponseContent())) || (directResponse.getRestStatus() == RestStatus.OK\n                                                            && StringUtils.isEmpty(\n                        directResponse.getResponseContent()));\n            }\n            return (response.getRestStatus() == RestStatus.OK && StringUtils.isNotBlank(response.getResponseContent()));\n        } catch (ESOperateException e) {\n            //由于模板没有新建索引，所以会有这种问题出来，注意这是不分区模板产生的问题\n            if (e.getMessage().startsWith(\"no such index\") && templateHealthEnum.equals(TemplateHealthEnum.GREEN)) {\n                return true;\n            }\n            throw e;\n        }\n        \n    }\n  \n    /**\n     * > 通过集群和url获取模板的健康度\n     *\n     * @param client 用于连接 ES 集群的客户端对象。\n     * @param uri    请求地址，即模板的地址。\n     */\n    private DirectResponse getDirectResponseByClusterAndUrl(ESClient client, String uri) throws ESOperateException {\n        DirectRequest directRequest = new DirectRequest(RequestMethod.GET.name(), uri);\n        try {\n            return client.direct(directRequest).actionGet(ES_OPERATE_TIMEOUT, TimeUnit.SECONDS);\n        } catch (Exception e) {\n            LOGGER.error(\"class=BaseESDAO||method=getDirectResponseByClusterAndUrl||uri={}\",\n                    client.getClusterName(), e.getMessage(), e);\n            ParsingExceptionUtils.abnormalTermination(e);\n        }\n        final DirectResponse directResponse = new DirectResponse();\n        directResponse.setRestStatus(RestStatus.SERVICE_UNAVAILABLE);\n        return directResponse;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/app/ProjectTemplateAccessESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.app;\n\nimport static com.didichuxing.datachannel.arius.admin.common.util.DateTimeUtil.getDateStr;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.query.ProjectTemplateAccessCountPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESConstant;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\nimport java.util.List;\nimport java.util.Set;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.springframework.stereotype.Component;\n\n@Component\n@NoArgsConstructor\npublic class ProjectTemplateAccessESDAO extends BaseESDAO {\n\n    /**\n     * 索引名称\n     */\n    private String indexName;\n    /**\n     * type名称\n     */\n    private String typeName = \"type\";\n\n    @PostConstruct\n    public void init() {\n        this.indexName = dataCentreUtil.getAriusProjectIdTemplateAccess();\n    }\n\n    /**\n     * 批量保存结果\n     *\n     * @return\n     */\n    public boolean batchInsert(List<ProjectTemplateAccessCountPO> list) {\n        return updateClient.batchInsert(EnvUtil.getWriteIndexNameByEnv(this.indexName), typeName, list);\n    }\n\n    /**\n     * 根据索引模板获取最近7天访问projectId列表\n     *\n     * @param templateName\n     * @return\n     */\n    public List<Integer> getAccessProjectIdsByTemplateName(String templateName) {\n        List<Integer> projectIds = Lists.newArrayList();\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_ACCESS_PROJECT_ID_BY_TEMPLATE_NAME,\n            templateName);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(this.indexName, typeName, dsl);\n        if (esAggrMap == null) {\n            return projectIds;\n        }\n\n        Set<Integer> projectIdSets = Sets.newTreeSet();\n        String key = null;\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"projectId\");\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n\n                key = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n                projectIdSets.add(Integer.valueOf(key));\n            }\n        }\n\n        projectIds.addAll(projectIdSets);\n\n        return projectIds;\n    }\n\n    /**\n     * 根据索引Id获取最近days天访问project id详细信息\n     *\n     * @param logicTemplateId\n     * @return\n     */\n    public List<ProjectTemplateAccessCountPO> getAccessProjectIdsInfoByTemplateId(int logicTemplateId, int days) {\n        final int scrollSize = 5000;\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_ACCESS_PROJECT_ID_INFO_BY_LOGIC_EMPLATE_ID,\n            scrollSize, logicTemplateId, days);\n\n        List<ProjectTemplateAccessCountPO> accessCountPos = Lists.newLinkedList();\n        gatewayClient.queryWithScroll(indexName, typeName, dsl, scrollSize, null, ProjectTemplateAccessCountPO.class,\n            resultList -> {\n                if (resultList != null) {\n                    accessCountPos.addAll(resultList);\n                }\n            });\n\n        return accessCountPos;\n    }\n\n    /**\n     * 根据索引Id获取最近days天访问projectId详细信息\n     *\n     * @param logicTemplateId\n     * @return\n     */\n    public List<ProjectTemplateAccessCountPO> getAccessProjectIdsInfoByTemplateId(int logicTemplateId, Long startDate,\n                                                                                  Long endDate) {\n        final int scrollSize = 5000;\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n            DslsConstant.GET_ACCESS_PROJECT_ID_INFO_BY_LOGIC_TEMPLATE_ID_AND_DATE_RANGE, scrollSize, logicTemplateId,\n            getDateStr(startDate), getDateStr(endDate));\n\n        List<ProjectTemplateAccessCountPO> accessCountPos = Lists.newLinkedList();\n        gatewayClient.queryWithScroll(indexName, typeName, dsl, scrollSize, null, ProjectTemplateAccessCountPO.class,\n            resultList -> {\n                if (resultList != null) {\n                    accessCountPos.addAll(resultList);\n                }\n            });\n\n        return accessCountPos;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/dsl/DslAnalyzeResultQpsESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslAnalyzeResultQpsPO;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport lombok.NoArgsConstructor;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.List;\n\n@Component\n@NoArgsConstructor\npublic class DslAnalyzeResultQpsESDAO extends BaseESDAO {\n\n    /**\n     * 索引名称\n     */\n    private String indexName;\n\n    /**\n     * type名称\n     */\n    private String typeName = \"type\";\n\n    @PostConstruct\n    public void init() {\n        this.indexName = dataCentreUtil.getAriusDslAnalyzeResult();\n    }\n\n    /**\n     * 批量保存projectId 查询模板qps信息到es\n     *\n     * @param projectIdTemplateQpsInfoList\n     * @return\n     */\n    public boolean bathInsert(List<DslAnalyzeResultQpsPO> projectIdTemplateQpsInfoList) {\n\n        return updateClient.batchInsert(EnvUtil.getWriteIndexNameByEnv(this.indexName), typeName,\n            projectIdTemplateQpsInfoList);\n    }\n\n    /**\n     * 获取最大查询qps根据projectid和templatemd5\n     *\n     * @param dslBase\n     * @return\n     */\n    public DslAnalyzeResultQpsPO getMaxProjectIdTemplateQpsInfoByProjectIdTemplateMd5(DslBase dslBase) {\n        if (null == dslBase) {\n            return null;\n        }\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_MAX_QPS_BY_PROJECT_ID_DSLTEMPLATE,\n            dslBase.getProjectId(), dslBase.getDslTemplateMd5());\n\n        return gatewayClient.performRequestAndTakeFirst(indexName, typeName, dsl, DslAnalyzeResultQpsPO.class);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/dsl/DslAnalyzeResultTypeESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslAnalyzeResultTypePO;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.google.common.collect.Lists;\nimport java.util.List;\nimport javax.annotation.Nullable;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.springframework.stereotype.Component;\n\n@Component\n@NoArgsConstructor\npublic class DslAnalyzeResultTypeESDAO extends BaseESDAO {\n\n    /**\n     * 索引名称\n     */\n    private String           indexName;\n    /**\n     * type名称\n     */\n    private String           typeName    = \"type\";\n\n    private static final int SCROLL_SIZE = 5000;\n\n    @PostConstruct\n    public void init() {\n        this.indexName = dataCentreUtil.getAriusDslAnalyzeResult();\n    }\n\n    /**\n     * 批量写入projectId维度分析查询结果到es\n     *\n     * @param projectIdAnalyzeResultList\n     * @return\n     */\n    public boolean batchInsert(List<DslAnalyzeResultTypePO> projectIdAnalyzeResultList) {\n        return updateClient.batchInsert(EnvUtil.getWriteIndexNameByEnv(this.indexName), typeName,\n            projectIdAnalyzeResultList);\n    }\n\n    /**\n     * 查询分析结果根据projectId\n     *\n     * @param projectId\n     * @return\n     */\n    @Nullable\n    @Deprecated\n    public List<DslAnalyzeResultTypePO> getDslAnalyzeResultByProjectId(Integer from, Long projectId) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_ANALYZE_RESULT_BY_PROJECT_ID, from,\n            projectId);\n\n        return gatewayClient.performRequest(indexName, typeName, dsl, DslAnalyzeResultTypePO.class);\n    }\n\n    /**\n     * 查询分析结果根据projectId\n     *\n     * @param projectId\n     * @return\n     */\n    @Nullable\n    @Deprecated\n    public List<DslAnalyzeResultTypePO> getDslAnalyzeResultByProjectIdAndRange(Long projectId, Long startDate,\n                                                                               Long endDate) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_ANALYZE_RESULT_BY_PROJECT_ID_AND_RANGE,\n            SCROLL_SIZE, startDate, endDate, projectId);\n\n        List<DslAnalyzeResultTypePO> dslAnalyzeResultTypePos = Lists.newLinkedList();\n        gatewayClient.queryWithScroll(indexName, typeName, dsl, SCROLL_SIZE, null, DslAnalyzeResultTypePO.class,\n            resultList -> {\n                if (resultList != null) {\n                    dslAnalyzeResultTypePos.addAll(resultList);\n                }\n            });\n\n        return dslAnalyzeResultTypePos;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/dsl/DslMetricsESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslMetricsPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESConstant;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.stereotype.Component;\n\n/**\n * dsl的指标信息，游flink任务解析dsl语句的时候写入数据\n */\n@Component\n@NoArgsConstructor\npublic class DslMetricsESDAO extends BaseESDAO {\n\n    private static final String VALUE    = \"value\";\n\n    /**\n     * 查询模板聚合数据的索引名称\n     */\n    private String              indexName;\n    /**\n     * type名称，主键id是topic_partition_offset\n     */\n    private String              typeName = \"type\";\n\n    @PostConstruct\n    public void init() {\n        this.indexName = dataCentreUtil.getAriusDslMetrices();\n    }\n\n    /**\n     * 根据时间范围查询某个projectId的记录数\n     *\n     * @param projectId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public Long queryTotalHitsByProjectIdDate(Integer projectId, String startDate, String endDate) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOTAL_HITS_BY_PROJECT_ID, projectId,\n            startDate, endDate);\n\n        return gatewayClient.performRequestAndGetTotalCount(indexName, typeName, dsl);\n    }\n\n    /**\n     * 查询某一天出现的projectid和dslTemplateMd5\n     *\n     * @param date\n     * @return\n     */\n    public List<DslMetricsPO> getProjectIdTemplateMd5InfoByDate(String date) {\n        List<DslMetricsPO> list = Lists.newLinkedList();\n\n        String realIndexName = String.format(\"%s_%s\", this.indexName.replace(\"*\", \"\"), date);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_PROJECT_ID_TEMPLATE_MD5_INFO);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, typeName, dsl);\n        if (esAggrMap != null && esAggrMap.getEsAggrMap() != null) {\n            ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"projectIdDslTemplateMd5\");\n            if (esAggr != null) {\n                List<ESBucket> esBucketList = esAggr.getBucketList();\n                if (esBucketList != null) {\n                    handleBucketList(list, esBucketList);\n                }\n            }\n        }\n\n        return list;\n    }\n\n    private void handleBucketList(List<DslMetricsPO> list, List<ESBucket> esBucketList) {\n        DslMetricsPO dslMetricsPo;\n        String key;\n        int index;\n        for (ESBucket esBucket : esBucketList) {\n            if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                continue;\n            }\n\n            key = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n            index = key.indexOf(\"_\");\n            if (index > 0) {\n                dslMetricsPo = new DslMetricsPO();\n                dslMetricsPo.setProjectId(Integer.valueOf(key.substring(0, index)));\n                dslMetricsPo.setDslTemplateMd5(key.substring(index + 1));\n\n                list.add(dslMetricsPo);\n            }\n        }\n    }\n\n    /**\n     * 获取最大一分钟查询量\n     *\n     * @param dslBase\n     * @return\n     */\n    public DslMetricsPO getMaxProjectIdTemplateQpsInfoByProjectIdTemplateMd5(DslBase dslBase) {\n        if (null == dslBase) {\n            return null;\n        }\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_MAX_QPS_BY_KEY, dslBase.getProjectId(),\n            dslBase.getDslTemplateMd5());\n        String realIndexName = IndexNameUtils.genCurrentDailyIndexName(indexName);\n        return gatewayClient.performRequestAndTakeFirst(realIndexName, typeName, dsl, DslMetricsPO.class);\n    }\n\n    public List<DslMetricsPO> getDslDetailMetricByProjectIdAndDslTemplateMd5(int projectId, String dslTemplteMd5,\n                                                                             long startDate, long endDate) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startDate, endDate);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n            DslsConstant.GET_DSL_DETAIL_METRICS_BY_PROJECT_ID_AND_MD5_AND_RANGE, projectId, dslTemplteMd5, startDate,\n            endDate, startDate, endDate);\n\n        return gatewayClient.performRequest(realIndexName, typeName, dsl, s -> {\n            List<DslMetricsPO> dslMetricsPos = new ArrayList<>();\n            if (s == null) {\n                return dslMetricsPos;\n            }\n\n            List<ESBucket> esBuckets = s.getAggs().getEsAggrMap().get(\"groupByTimeStamp\").getBucketList();\n\n            if (CollectionUtils.isNotEmpty(esBuckets)) {\n                esBuckets.forEach(esBucket -> {\n                    try {\n                        Map<String, Object> unUsedMap = esBucket.getUnusedMap();\n                        Map<String, ESAggr> aggrMap = esBucket.getAggrMap();\n                        if (null != unUsedMap && null != aggrMap) {\n                            DslMetricsPO dslMetricsPo = new DslMetricsPO();\n\n                            dslMetricsPo.setDslTemplateMd5(dslTemplteMd5);\n                            dslMetricsPo.setProjectId(projectId);\n                            dslMetricsPo.setDslLenAvg(\n                                Double.valueOf(aggrMap.get(\"dslLenAvg\").getUnusedMap().get(VALUE).toString()));\n                            dslMetricsPo.setEsCostAvg(\n                                Double.valueOf(aggrMap.get(\"esCostAvg\").getUnusedMap().get(VALUE).toString()));\n                            dslMetricsPo.setFailedShardsAvg(\n                                Double.valueOf(aggrMap.get(\"failedShardsAvg\").getUnusedMap().get(VALUE).toString()));\n                            dslMetricsPo.setResponseLenAvg(\n                                Double.valueOf(aggrMap.get(\"responseLenAvg\").getUnusedMap().get(VALUE).toString()));\n                            dslMetricsPo.setSearchCount(Double\n                                .valueOf(aggrMap.get(\"searchCount\").getUnusedMap().get(VALUE).toString()).longValue());\n                            dslMetricsPo.setTotalCostAvg(\n                                Double.valueOf(aggrMap.get(\"totalCostAvg\").getUnusedMap().get(VALUE).toString()));\n                            dslMetricsPo.setTotalHitsAvg(\n                                Double.valueOf(aggrMap.get(\"totalHitsAvg\").getUnusedMap().get(VALUE).toString()));\n                            dslMetricsPo.setTotalShardsAvg(\n                                Double.valueOf(aggrMap.get(\"totalShardsAvg\").getUnusedMap().get(VALUE).toString()));\n                            dslMetricsPo.setTimeStamp(Long.valueOf(unUsedMap.get(\"key\").toString()));\n\n                            dslMetricsPos.add(dslMetricsPo);\n                        }\n                    } catch (Exception e) {\n                        LOGGER.error(\n                            \"class=AriusStatsInfoEsDao||method=getDslDetailMetricByProjectIdAndDslTemplateMd5||exceptionMsg:{}\",\n                            e);\n                    }\n                });\n            }\n\n            return dslMetricsPos;\n        }, 3);\n    }\n\n    /**\n     * 查询某个projectId一天查询次数\n     *\n     * @param projectId\n     * @param date\n     * @return\n     */\n    public Long getTotalSearchByProjectIdDate(Integer projectId, String date) {\n        String index = String.format(\"%s_%s\", indexName.replace(\"*\", \"\"), date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOTAL_SEARCHCOUNT_BY_PROJECT_ID, projectId);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(index, typeName, dsl);\n        if (esAggrMap == null) {\n            return null;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"totalSearchCnt\");\n        Double value = Double.valueOf(esAggr.getUnusedMap().getOrDefault(ESConstant.SUM_VALUE, \"0\").toString());\n\n        return value.longValue();\n    }\n\n    /**\n     *\n     * 获取一个查询模板的数据\n     *\n     * @param projectId\n     * @param dslTemplateMd5\n     * @return\n     */\n    public DslMetricsPO getNeariestDslMetricsByProjectIdTemplateMd5(Integer projectId, String dslTemplateMd5) {\n        String queryDsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_METRICS_BY_KEY, projectId,\n            dslTemplateMd5);\n\n        return gatewayClient.performRequestAndTakeFirst(indexName, typeName, queryDsl, DslMetricsPO.class);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/dsl/DslTemplateESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.dsl;\n\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.template.DslTemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.DslQueryLimit;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateRequest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.DSLSearchUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.DateTimeUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport javax.annotation.Nullable;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.BooleanUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n@Component\n@NoArgsConstructor\npublic class DslTemplateESDAO extends BaseESDAO {\n\n    /**\n     * 查询模板数据的索引名称\n     */\n    private String           indexName;\n    /**\n     * 查询模板过期删除时间\n     */\n    @Value(\"${delete.expired.template.time}\")\n    private String           deleteExpireDslTime;\n    /**\n     * 查询历史数据时间\n     */\n    @Value(\"${history.query.time}\")\n    private String           historyQueryTime;\n    /**\n     * type名称\n     */\n    private String           typeName    = \"type\";\n    /**\n     * 滚动查询大小\n     */\n    private static final int SCROLL_SIZE = 1000;\n\n    @PostConstruct\n    public void init() {\n        this.indexName = dataCentreUtil.getAriusDslTemplate();\n    }\n\n    /**\n     * 更新查询模板信息\n     *\n     * @param list\n     * @return\n     */\n    public boolean updateTemplates(List<DslTemplatePO> list) {\n\n        return updateClient.batchUpdate(indexName, typeName, list);\n    }\n\n    /**\n     * 获取所有查询模板最近修改时间在(now-1d,now)范围内，并且不启用的查询模板，然后删除过期的查询模板数据\n     *\n     * @return\n     */\n    public boolean deleteExpiredDslTemplate() {\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_EXPIRED_DSL_TEMPLATE, SCROLL_SIZE,\n            deleteExpireDslTime);\n\n        List<DslTemplatePO> list = getTemplatesByDsl(dsl);\n        List<String> ids = Lists.newLinkedList();\n        for (DslTemplatePO dslTemplate : list) {\n            ids.add(dslTemplate.getKey());\n        }\n\n        return updateClient.batchDelete(indexName, typeName, ids);\n    }\n\n    /**\n     * 更新查询限流值\n     *\n     * @param dslQueryLimitList\n     * @return\n     */\n    public boolean updateQueryLimitByProjectIdDslTemplate(List<DslQueryLimit> dslQueryLimitList) {\n        String ariusModifyTime = DateTimeUtil.getCurrentFormatDateTime();\n        List<DslTemplatePO> list = Lists.newLinkedList();\n        DslTemplatePO item = null;\n\n        for (DslQueryLimit dslQueryLimit : dslQueryLimitList) {\n            item = new DslTemplatePO();\n            item.setQueryLimit(dslQueryLimit.getQueryLimit());\n            // 强制设置查询限流值设置为 true\n            item.setForceSetQueryLimit(true);\n            item.setAriusModifyTime(ariusModifyTime);\n            item.setProjectId(dslQueryLimit.getProjectId());\n            item.setDslTemplateMd5(dslQueryLimit.getDslTemplateMd5());\n\n            list.add(item);\n        }\n\n        return updateTemplates(list);\n    }\n\n    /**\n     * 获取查询模板信息\n     *\n     * @param dslBases\n     * @return\n     */\n    public Map<String, DslTemplatePO> getDslTemplateByKeys(List<? extends DslBase> dslBases) {\n        Map<String, DslTemplatePO> result = Maps.newHashMap();\n        for (DslBase dslBase : dslBases) {\n            result.put(dslBase.getProjectIdDslTemplateMd5(),\n                getDslTemplateByKey(dslBase.getProjectId(), dslBase.getDslTemplateMd5()));\n        }\n        return result;\n    }\n\n    /**\n     * 根据主键id获取查询模板\n     *\n     * @param projectId\n     * @param dslTemplateMd5\n     * @return\n     */\n    public DslTemplatePO getDslTemplateByKey(Integer projectId, String dslTemplateMd5) {\n        return getDslTemplateByKey(String.format(\"%d_%s\", projectId, dslTemplateMd5));\n    }\n\n    /**\n     * 根据主键id获取查询模板\n     *\n     * @param key\n     * @return\n     */\n    public DslTemplatePO getDslTemplateByKey(String key) {\n        return gatewayClient.doGet(indexName, typeName, key, DslTemplatePO.class);\n    }\n\n    /**\n     * 获取某个project id的所有查询模板数据,已排除老查询模板\n     *\n     * @param projectId\n     * @return\n     */\n    public List<DslTemplatePO> getAllDslTemplateByProjectId(Integer projectId) {\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_TEMPLATE_BY_PROJECT_ID, SCROLL_SIZE,\n            projectId);\n\n        return getTemplatesByDsl(dsl);\n    }\n\n    /**\n     * 获取查询模板创建时间大于指定天偏移的查询模板数据，用于设置慢查耗时阈值\n     *\n     * @param dayOffset\n     * @return\n     */\n    public List<DslTemplatePO> getDslTemplatesByDateRange(int dayOffset) {\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_TEMPLATES_BY_RANGE, SCROLL_SIZE,\n            dayOffset);\n\n        return getTemplatesByDsl(dsl);\n    }\n\n    /**\n     * 获取早期查询模板，不包括手动修改限流值\n     *\n     * @return\n     */\n    public List<DslTemplatePO> getEarliestDslTemplate() {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_EARLIEST_DSL_TEMPLATES, SCROLL_SIZE);\n\n        return getTemplatesByDsl(dsl);\n    }\n\n    /**\n     * 获取一段时间不使用的查询模板，不包括黑名单和手动修改限流值\n     *\n     * @return\n     */\n    public List<DslTemplatePO> getLongTimeNotUseDslTemplate() {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_LONG_TIME_NOT_USE_DSL_TEMPLATES, SCROLL_SIZE,\n            historyQueryTime);\n\n        return getTemplatesByDsl(dsl);\n    }\n\n    public List<DslTemplatePO> getDslMetricsByProjectId(Integer projectId, Long startDate, Long endDate) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_TEMPLATE_BY_PROJECT_ID_AND_RANGE, 10000,\n            startDate, endDate, projectId);\n\n        return gatewayClient.performRequest(indexName, typeName, dsl, DslTemplatePO.class);\n    }\n\n    private String buildQueryCriteriaDsl(Integer projectId, String dslTemplateMd5, String queryIndex, Long startTime,\n                                         Long endTime) {\n        return \"[\" + buildQueryCriteriaCell(projectId, dslTemplateMd5, queryIndex, startTime, endTime) + \"]\";\n    }\n\n    private String buildQueryCriteriaCell(Integer projectId, String dslTemplateMd5, String queryIndex, Long startTime,\n                                          Long endTime) {\n        List<String> cellList = Lists.newArrayList();\n\n        // 最近时间范围条件\n        cellList.add(DSLSearchUtils.getTermCellForRangeSearch(startTime, endTime, \"timeStamp\"));\n        // projectId 条件\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(projectId, \"projectId\"));\n\n        if (StringUtils.isNotBlank(dslTemplateMd5)) {\n            // 优先使用 dslTemplateMd5 条件\n            cellList.add(DSLSearchUtils.getTermCellForExactSearch(dslTemplateMd5, \"dslTemplateMd5\"));\n        } else if (StringUtils.isNotBlank(queryIndex)) {\n            // queryIndex 条件\n            cellList.add(DSLSearchUtils.getTermCellForPrefixSearch(queryIndex, \"indices\"));\n        }\n        return ListUtils.strList2String(cellList);\n    }\n\n    /**\n     * 根据查询条件分页获取DSL模板数据\n     *\n     * @param projectId    应用id\n     * @param queryDTO 查询条件\n     */\n    public Tuple<Long, List<DslTemplatePO>> getDslTemplatePage(Integer projectId, DslTemplateConditionDTO queryDTO)\n            throws ESOperateException {\n        String queryCriteriaDsl = buildQueryCriteriaDsl(projectId, queryDTO.getDslTemplateMd5(),\n            queryDTO.getQueryIndex(), queryDTO.getStartTime(), queryDTO.getEndTime());\n\n        // 排序条件，默认根据使用时间排序 desc\n        String sortInfo = \"timeStamp\";\n        String sortOrder = \"desc\";\n        if (!StringUtils.isEmpty(queryDTO.getSortInfo())) {\n            // 根据用户自定义条件排序\n            sortOrder = BooleanUtils.isTrue(queryDTO.getOrderByDesc()) ? \"desc\" : \"asc\";\n            sortInfo = queryDTO.getSortInfo();\n        }\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_TEMPLATE_BY_CONDITION,\n            (queryDTO.getPage() - 1) * queryDTO.getSize(), queryDTO.getSize(), queryCriteriaDsl, sortInfo, sortOrder);\n\n        return ESOpTimeoutRetry.esRetryExecute(\"getDslTemplatePage\",3,\n                () -> gatewayClient.performRequestListAndGetTotalCount(null, indexName, typeName, dsl, DslTemplatePO.class),\n                Objects::isNull);\n    }\n\n    /**\n     * 根据查询条件获取查询模板数据\n     *\n     * @param projectId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public Tuple<Long, List<DslTemplatePO>> getDslTemplateByCondition(Integer projectId, String searchKeyword,\n                                                                      String dslTag, String sortInfo, Long from,\n                                                                      Long size, Long startDate, Long endDate) {\n        try {\n            String dsl = null;\n            JSONArray mustJson = new JSONArray();\n            mustJson.add(JSON.parse(\"{\\\"term\\\":{\\\"version\\\":{\\\"value\\\":\\\"V2\\\"}}}\"));\n            // 根据最近使用的时间（timeStamp字段）来筛选\n            mustJson.add(\n                JSON.parse(String.format(\"{\\\"range\\\":{\\\"timeStamp\\\":{\\\"gte\\\":%d,\\\"lte\\\":%d}}}\", startDate, endDate)));\n\n            if (projectId != null) {\n                mustJson.add(JSON.parse(String.format(\"{\\\"term\\\":{\\\"projectId\\\":{\\\"value\\\":%d}}}\", projectId)));\n            }\n            if (StringUtils.isNoneBlank(searchKeyword)) {\n                mustJson.add(JSON.parse(String.format(\"{\\\"wildcard\\\":{\\\"my_all_fields\\\":\\\"%s\\\"}}\", searchKeyword)));\n            }\n            if (StringUtils.isNoneBlank(dslTag)) {\n                String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(dslTag, \",\");\n                JSONArray dslTagJson = new JSONArray();\n                Arrays.asList(items).forEach(dslTagJson::add);\n                String terms = String.format(\"{\\\"terms\\\":{\\\"dslTag\\\":%s}}\", dslTagJson.toJSONString());\n                mustJson.add(JSON.parse(terms));\n            }\n            if (StringUtils.isBlank(sortInfo)) {\n                // 默认根据使用时间排序 desc\n                sortInfo = \"\\\"timeStamp\\\": {\\\"order\\\": \\\"desc\\\"}\";\n            }\n\n            // 存在深分页问题, 解决方案scroll（官方不推荐）/search after（官方推荐使用）/业务上限制 1000后的分页\n            dsl = String.format(\"{\\\"from\\\":%d,\\\"size\\\":%d,\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[%s]}},\\\"sort\\\":{%s}}\", from,\n                size, mustJson.toJSONString(), sortInfo);\n\n            return gatewayClient.performRequestListAndGetTotalCount(null, indexName, typeName, dsl,\n                DslTemplatePO.class);\n\n        } catch (Exception e) {\n            LOGGER.error(\"class=DslTemplateEsDao||method=getDslTemplateByCondition||errMsg=search template error\", e);\n            return null;\n        }\n    }\n\n    /**\n     * 获取过期的查询模板信息\n     *\n     * @return\n     */\n    public List<DslTemplatePO> getExpiredAndWillDeleteDslTemplate() {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_EXPIRED_DELETED_DSL_TEMPLATE, SCROLL_SIZE,\n            deleteExpireDslTime);\n\n        return getTemplatesByDsl(dsl);\n    }\n\n    /**\n     * 获取最近查询模板，不包括手动修改限流值和黑名单\n     *\n     * @return\n     */\n    public List<DslTemplatePO> getNearestDslTemplate() {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_NEAREST_DSL_TEMPLATES, SCROLL_SIZE);\n\n        return getTemplatesByDsl(dsl);\n    }\n\n    /**\n     * 获取最近没有设置黑白名单的查询模板,已排除老查询模板\n     *\n     * @return\n     */\n    public List<DslTemplatePO> getNearestDslTemplateAccessable() {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_NEAREST_DSL_TEMPLATE_ACCESSABLE,\n            SCROLL_SIZE);\n\n        return getTemplatesByDsl(dsl);\n    }\n\n    /**\n     * 获取到缺少ariusCreateTime字段的文档\n     *\n     * @return\n     */\n    public List<DslTemplatePO> getMissingAriusCreateTme() {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_MISSING_ARIUS_CREATE_TIME, SCROLL_SIZE);\n\n        return getTemplatesByDsl(dsl);\n    }\n\n    /**\n     * 获取某个projectId的查询模板个数,已排除老版本查询模板\n     *\n     * @param projectId\n     * @return\n     */\n    public Long getTemplateCountByProjectId(Integer projectId) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_TEMPLATE_COUNT_BY_PROJECT_ID, projectId);\n\n        return gatewayClient.performRequestAndGetTotalCount(indexName, typeName, dsl);\n    }\n\n    /**\n     * 获取某个projectId的新增查询模板个数,已排除老查询模板\n     *\n     * @param projectId\n     * @param date\n     * @param today\n     * @return\n     */\n    public Long getIncreaseTemplateCountByProjectId(Integer projectId, String date, String today) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_INCREASE_DSL_TEMPLATE_BY_PROJECT_ID,\n            projectId, date, today);\n\n        return gatewayClient.performRequestAndGetTotalCount(indexName, typeName, dsl);\n    }\n\n    /**\n     * 根据index获得对应的templateMD5\n     *\n     * @param indexName\n     * @return\n     */\n    public Map<String/*dslMd5*/, Set<String>/*dsls*/> getTemplateMD5ByIndexName(String indexName, Integer dayOffset) {\n\n        Map<String/*dslMd5*/, Set<String>/*dsls*/> dslMap = Maps.newHashMap();\n        String dsl = null;\n        if (dayOffset == -1) {\n            dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_TEMPLATES_BY_INDEXNAME, SCROLL_SIZE,\n                indexName);\n        } else {\n            dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_TEMPLATES_BY_INDEXNAME_WITH_DAY_RANGE,\n                SCROLL_SIZE, indexName, dayOffset);\n        }\n\n        gatewayClient.queryWithScroll(this.indexName, typeName, dsl, SCROLL_SIZE, null, DslTemplatePO.class,\n            resultList -> {\n                if (resultList != null) {\n                    for (DslTemplatePO dslTemplate : resultList) {\n                        dslMap.computeIfAbsent(dslTemplate.getDslTemplateMd5(), key -> Sets.newLinkedHashSet())\n                            .add(dslTemplate.getDsl());\n                    }\n                }\n            });\n\n        return dslMap;\n    }\n\n    /**\n     * 根据index获得对应的templateMD5\n     *\n     * @param indexName\n     * @return\n     */\n    public Map<String/*dskMd5*/, Set<String>/*dsls*/> getTemplateMD5ByIndexNameAndProjectId(String indexName,\n                                                                                            String projectId,\n                                                                                            Integer dayOffset) {\n\n        Map<String/*dskMd5*/, Set<String>/*dsls*/> dslMap = Maps.newHashMap();\n\n        String dsl = null;\n        if (dayOffset == -1) {\n            dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_TEMPLATES_BY_INDEXNAME_PROJECT_ID,\n                SCROLL_SIZE, indexName, projectId);\n        } else {\n            dsl = dslLoaderUtil.getFormatDslByFileName(\n                DslsConstant.GET_DSL_TEMPLATES_BY_INDEXNAME_PROJECT_ID_WITH_DAY_RANGE, SCROLL_SIZE, indexName,\n                projectId, dayOffset);\n        }\n\n        gatewayClient.queryWithScroll(this.indexName, typeName, dsl, SCROLL_SIZE, null, DslTemplatePO.class,\n            resultList -> {\n                if (resultList != null) {\n                    for (DslTemplatePO dslTemplate : resultList) {\n                        dslMap.computeIfAbsent(dslTemplate.getDslTemplateMd5(), key -> Sets.newLinkedHashSet())\n                            .add(dslTemplate.getDsl());\n                    }\n                }\n            });\n\n        return dslMap;\n    }\n\n    /**\n     * 滚动获取查询模板\n     *\n     * @param request\n     * @return\n     */\n    @Nullable\n    public ScrollDslTemplateResponse handleScrollDslTemplates(ScrollDslTemplateRequest request) {\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.SCROLL_DSL_TEMPLATES, request.getScrollSize(),\n            request.getLastModifyTime(), request.getDslTemplateVersion());\n\n        List<DslTemplatePO> list = Lists.newLinkedList();\n        ESQueryResponse response = null;\n        // 没有游标id，则开始滚动查询\n        if (StringUtils.isBlank(request.getScrollId())) {\n\n            response = gatewayClient.prepareScrollQuery(indexName, typeName, dsl, null, DslTemplatePO.class,\n                resultList -> {\n                    if (resultList != null) {\n                        list.addAll(resultList);\n                    }\n                });\n\n        } else {\n            response = gatewayClient.queryScrollQuery(indexName, request.getScrollId(), DslTemplatePO.class,\n                resultList -> {\n                    if (resultList != null) {\n                        list.addAll(resultList);\n                    }\n                });\n        }\n\n        if (response == null) {\n            return null;\n        }\n\n        String scrollId = response.getUnusedMap().get(\"_scroll_id\").toString();\n\n        return ScrollDslTemplateResponse.builder().dslTemplatePoList(list).scrollId(scrollId).build();\n    }\n\n    /**\n     * 根据查询语句获取查询模板数据\n     *\n     * @param dsl\n     * @return\n     */\n    private List<DslTemplatePO> getTemplatesByDsl(String dsl) {\n        List<DslTemplatePO> list = Lists.newLinkedList();\n\n        gatewayClient.queryWithScroll(indexName, typeName, dsl, SCROLL_SIZE, null, DslTemplatePO.class, resultList -> {\n            if (resultList != null) {\n                list.addAll(resultList);\n            }\n        });\n\n        return list;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/gateway/GatewayAppMetricsDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.gateway;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContentCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.GatewayMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.metric.BaseTopNMetricsDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.google.common.collect.Lists;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\n@Component\n@NoArgsConstructor\npublic class GatewayAppMetricsDAO extends BaseTopNMetricsDAO {\n    private static final String TYPE = \"type\";\n    private static final String  AGG_KEY_TIMESTAMP = \"group_by_timeStamp\";\n    private static final String  AGG_KEY_APP       = \"group_by_app\";\n    private static final String  KEY               = \"key\";\n    private static final String AVG         = \"avg\";\n    \n    private static final String SEARCH_COST = \"searchCost\";\n    private static final String  TOTAL_COST        = \"totalCost\";\n    private static final Integer AGG_SIZE          = 5000;\n    \n    @PostConstruct\n    public void init() {\n        super.indexName = dataCentreUtil.getAriusStatsGatewayInfo();\n    }\n\n    /**\n     * 获取某个字段分布.(searchCost，totalCost)  topN\n     */\n    public List<VariousLineChartMetrics> getAggFieldByRange(Long startTime, Long endTime, List<String> metricsTypes,\n                                                            Integer topNu) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_APP_FIELD, startTime, endTime,\n            interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldAggMetrics(response, metricsTypes, topNu, interval), 3);\n    }\n\n    /**\n     * 获取某个字段分布.(searchCost，totalCost) by projectId\n     */\n    public List<VariousLineChartMetrics> getAggFieldByRange(Long startTime, Long endTime, List<String> metricsTypes,\n                                                            String projectId) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_APP_FIELD_BY_PROJECT_ID, projectId,\n            startTime, endTime, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldByProjectIdAggMetrics(response, metricsTypes, projectId, interval),\n            3);\n    }\n\n    /**\n     * 获取各App查询量 count  topN\n     */\n    public VariousLineChartMetrics getProjectCountByRange(Long startTime, Long endTime, Integer topNu) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_APP_FIELD_COUNT, startTime, endTime,\n            interval, startTime, endTime);\n        List<VariousLineChartMetrics> variousLineChartMetrics = gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldAggMetrics(response,\n                Lists.newArrayList(GatewayMetricsTypeEnum.QUERY_APP_COUNT.getType()), topNu, interval),\n            3);\n        return variousLineChartMetrics.get(0);\n    }\n\n    /**\n     * 获取各project查询量 count by projectId\n     */\n    public VariousLineChartMetrics getProjectCountByRange(Long startTime, Long endTime, String projectId) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_APP_FIELD_COUNT_BY_PROJECT_ID,\n            projectId, startTime, endTime, interval, startTime, endTime);\n        List<VariousLineChartMetrics> variousLineChartMetrics = gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldByProjectIdAggMetrics(response,\n                Lists.newArrayList(GatewayMetricsTypeEnum.QUERY_APP_COUNT.getType()), projectId, interval),\n            3);\n        return variousLineChartMetrics.get(0);\n    }\n\n    private List<VariousLineChartMetrics> fetchFieldAggMetrics(ESQueryResponse response, List<String> metricsTypes,\n                                                               Integer topNu, String interval) {\n        List<VariousLineChartMetrics> list = Lists.newArrayList();\n        for (String metricsType : metricsTypes) {\n            VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n            variousLineChartMetrics.setType(metricsType);\n            variousLineChartMetrics.setMetricsContents(Lists.newArrayList());\n            list.add(variousLineChartMetrics);\n            Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                .orElse(null);\n            if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_APP)) {\n                handleBucketList(interval, metricsType, variousLineChartMetrics, esAggrMap);\n\n                //根据第一个时间点的值进行倒排，取topNu\n                List<MetricsContent> sortedList = variousLineChartMetrics\n                    .getMetricsContents().stream().sorted(Comparator\n                        .comparing(x -> x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder()))\n                    .limit(topNu).collect(Collectors.toList());\n                variousLineChartMetrics.setMetricsContents(sortedList);\n            }\n\n        }\n\n        return list;\n    }\n\n    private void handleBucketList(String interval, String metricsType, VariousLineChartMetrics variousLineChartMetrics,\n                                  Map<String, ESAggr> esAggrMap) {\n        for (ESBucket esBucket : esAggrMap.get(AGG_KEY_APP).getBucketList()) {\n            String projectId = esBucket.getUnusedMap().get(KEY).toString();\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(projectId);\n            metricsContent.setMetricsContentCells(Lists.newArrayList());\n            variousLineChartMetrics.getMetricsContents().add(metricsContent);\n            if (null != esBucket.getAggrMap() && null != esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP)) {\n                for (ESBucket bucket : esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).getBucketList()) {\n                    Long timeStamp = Long.valueOf(bucket.getUnusedMap().get(KEY).toString());\n                    String aggKey = GatewayMetricsTypeEnum.type2AggKey(metricsType);\n                    Double value;\n                    if (MetricsUtils.needConvertUnit(aggKey)) {\n                        value = MetricsUtils.getDoubleValuePerMin(interval,\n                            bucket.getUnusedMap().get(aggKey).toString());\n                    } else {\n                        value = MetricsUtils.getAggMapDoubleValue(bucket, aggKey);\n                    }\n                    metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                }\n            }\n        }\n    }\n\n    private List<VariousLineChartMetrics> fetchFieldByProjectIdAggMetrics(ESQueryResponse response,\n                                                                          List<String> metricsTypes, String projectId,\n                                                                          String interval) {\n        List<VariousLineChartMetrics> vos = Lists.newArrayList();\n        for (String metricsType : metricsTypes) {\n            VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n            variousLineChartMetrics.setType(metricsType);\n\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(projectId);\n            metricsContent.setMetricsContentCells(Lists.newArrayList());\n\n            variousLineChartMetrics.setMetricsContents(Lists.newArrayList(metricsContent));\n            vos.add(variousLineChartMetrics);\n\n            Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                .orElse(null);\n            if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_TIMESTAMP)) {\n                for (ESBucket esBucket : esAggrMap.get(AGG_KEY_TIMESTAMP).getBucketList()) {\n                    Long timeStamp = Long.valueOf(esBucket.getUnusedMap().get(KEY).toString());\n                    Double value;\n                    String aggKey = GatewayMetricsTypeEnum.type2AggKey(metricsType);\n                    if (MetricsUtils.needConvertUnit(aggKey)) {\n                        value = MetricsUtils.getDoubleValuePerMin(interval,\n                            esBucket.getUnusedMap().get(aggKey).toString());\n                    } else {\n                        value = MetricsUtils.getAggMapDoubleValue(esBucket, aggKey);\n                    }\n                    metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                }\n            }\n        }\n\n        return vos;\n    }\n    \n    public List<VariousLineChartMetrics> fetchTopMetric(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                                        Long endTime, Integer topNu, String valueProjectId)\n            throws AdminOperateException {\n        return fetchTopMetric(gatewayMetricsTypeEnum, startTime, endTime, topNu, null, valueProjectId);\n    }\n    \n    @Override\n    public List<VariousLineChartMetrics> fetchTopMetric(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                                        Long endTime, Integer topNu, Integer projectId, String value)\n            throws AdminOperateException {\n        //构建一个空的query\n        String queryHasDataTimeDsl = EMPTY_STR;\n        String interval = MetricsUtils.Interval.ONE_MIN.getStr();\n        Object[] param;\n        switch (gatewayMetricsTypeEnum) {\n            case QUERY_APP_SEARCH_COST:\n                param = new Object[] { queryHasDataTimeDsl, AGG_KEY_APP, PROJECT_ID, AGG_SIZE, interval,\n                                       gatewayMetricsTypeEnum.getAggKey(), AVG, SEARCH_COST };\n                break;\n            case QUERY_APP_TOTAL_COST:\n                param = new Object[] { queryHasDataTimeDsl, AGG_KEY_APP, PROJECT_ID, AGG_SIZE, interval,\n                                       gatewayMetricsTypeEnum.getAggKey(), AVG, TOTAL_COST };\n                break;\n            case QUERY_APP_COUNT:\n                param = new Object[] { queryHasDataTimeDsl, AGG_KEY_APP, PROJECT_ID, AGG_SIZE, interval };\n                break;\n            default:\n                return Collections.emptyList();\n        }\n        return this.performFetchTopMetric(gatewayMetricsTypeEnum, startTime, endTime,\n                (ESQueryResponse response) -> Collections.singletonList(\n                        fetchFieldAggMetrics(response, gatewayMetricsTypeEnum, topNu, interval)), queryHasDataTimeDsl,\n                value, param);\n    }\n    \n    public List<MetricsContent> getByRangeTopN(List<String> values, GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                               Long startTime, Long endTime) throws AdminOperateException {\n        return getByRangeTopN(values, gatewayMetricsTypeEnum, startTime, endTime, null);\n    }\n    \n    @Override\n    public List<MetricsContent> getByRangeTopN(List<String> values, GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                               Long startTime, Long endTime, Integer projectId)\n            throws AdminOperateException {\n        if (CollectionUtils.isEmpty(values)) {\n            return Collections.emptyList();\n        }\n        final List<Object> projectIds = values.stream().map(Integer::parseInt).collect(Collectors.toList());\n        String queryDslFragment = buildTermsByField(PROJECT_ID, projectIds);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        final String valueInclude = new JSONArray().fluentAddAll(values).toJSONString();\n        Object[] param;\n        switch (gatewayMetricsTypeEnum) {\n            case QUERY_APP_SEARCH_COST:\n                param = new Object[] { startTime, endTime, queryDslFragment, AGG_KEY_APP, PROJECT_ID, values.size(),\n                                       valueInclude, interval, startTime, endTime, gatewayMetricsTypeEnum.getAggKey(),\n                                       AVG, SEARCH_COST };\n                break;\n            case QUERY_APP_TOTAL_COST:\n                param = new Object[] { startTime, endTime, queryDslFragment, AGG_KEY_APP, PROJECT_ID, values.size(),\n                                       valueInclude, interval, startTime, endTime, gatewayMetricsTypeEnum.getAggKey(),\n                                       AVG, TOTAL_COST };\n                break;\n            case QUERY_APP_COUNT:\n                param = new Object[] { startTime, endTime, queryDslFragment, AGG_KEY_APP, PROJECT_ID, values.size(),\n                                       valueInclude, interval, startTime, endTime };\n                break;\n            default:\n                return Collections.emptyList();\n        }\n        return performGetByRangeTopN(gatewayMetricsTypeEnum, startTime, endTime,\n                response -> fetchFieldAggMetrics(response, gatewayMetricsTypeEnum.getType(), interval), param);\n    }\n    \n    private VariousLineChartMetrics fetchFieldAggMetrics(ESQueryResponse response, GatewayMetricsTypeEnum metricsTypes,\n                                                         Integer topNu, String interval) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(metricsTypes.getType());\n        variousLineChartMetrics.setMetricsContents(Lists.newArrayList());\n        Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                .orElse(null);\n        if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_APP)) {\n            handleBucketList(interval, metricsTypes.getType(), variousLineChartMetrics, esAggrMap);\n            //根据第一个时间点的值进行倒排，取topNu\n            List<MetricsContent> sortedList = variousLineChartMetrics.getMetricsContents().stream()\n                    .sorted(Comparator.comparing(x -> CollectionUtils.isEmpty(x.getMetricsContentCells())\n                            ? -1\n                            : x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder())).limit(topNu)\n                    .collect(Collectors.toList());\n            variousLineChartMetrics.setMetricsContents(sortedList);\n        }\n        return variousLineChartMetrics;\n    }\n    \n    @Override\n    protected String getFinalDslByOneStep(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Object[] args) {\n        switch (gatewayMetricsTypeEnum) {\n            case QUERY_APP_SEARCH_COST:\n            case QUERY_APP_TOTAL_COST:\n                return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOTAL_COST_BY_FIELD, args);\n            case QUERY_APP_COUNT:\n                return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_COUNT_BY_FILELD, args);\n            default:\n                return null;\n        }\n    }\n      @Override\n      protected String getFinalDslBySecondStep(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Object[] args) {\n         \n          switch (gatewayMetricsTypeEnum) {\n              case QUERY_APP_SEARCH_COST:\n              case QUERY_APP_TOTAL_COST:\n                  return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOTAL_COST_EXTENDED_BOUNDS_BY_FIELD,\n                          args);\n              case QUERY_APP_COUNT:\n                  return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_COUNT_EXTENDED_BOUNDS_BY_FILELD,\n                          args);\n              default:\n                  return null;\n          }\n      }\n    \n    @Override\n    public List<VariousLineChartMetrics> checkMetricsValue(GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                           String metricsValue) {\n        // 当该指标存在时候，直接进行返回\n        if (StringUtils.isNotBlank(metricsValue)) {\n            VariousLineChartMetrics metrics = new VariousLineChartMetrics();\n            metrics.setType(gatewayMetricsTypeEnum.getType());\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(metricsValue);\n            metrics.setMetricsContents(Collections.singletonList(metricsContent));\n            return Collections.singletonList(metrics);\n        }\n        return Collections.emptyList();\n    }\n    \n    private List<MetricsContent> fetchFieldAggMetrics(ESQueryResponse response, String metricsType, String interval) {\n        final Optional<List<ESBucket>> esBucketsOptional = Optional.ofNullable(response).map(ESQueryResponse::getAggs)\n                .map(ESAggrMap::getEsAggrMap)\n                //判断是否会存在AGG_KEY_APP\n                .filter(esAggrMap -> esAggrMap.containsKey(AGG_KEY_APP))\n                //获取到appke\n                .map(esAggrMap -> esAggrMap.get(AGG_KEY_APP).getBucketList());\n        if (!esBucketsOptional.isPresent()) {\n            return Collections.emptyList();\n        }\n        String aggKey = GatewayMetricsTypeEnum.type2AggKey(metricsType);\n        List<MetricsContent> metricsContents = Lists.newArrayList();\n        for (ESBucket esBucket : esBucketsOptional.get()) {\n            String projectId = esBucket.getUnusedMap().get(KEY).toString();\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(projectId);\n            metricsContent.setMetricsContentCells(Lists.newArrayList());\n            if (esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).getBucketList() != null) {\n                for (ESBucket bucket : esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).getBucketList()) {\n                    Long timeStamp = Long.valueOf(bucket.getUnusedMap().get(KEY).toString());\n                    Double value;\n                    if (MetricsUtils.needConvertUnit(aggKey)) {\n                        value = MetricsUtils.getDoubleValuePerMin(interval,\n                                bucket.getUnusedMap().get(aggKey).toString());\n                    } else {\n                        value = MetricsUtils.getAggMapDoubleValue(bucket, aggKey);\n                    }\n                    metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                }\n            } else {\n                esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).toJson().getJSONObject(BUCKETS).values()\n                        .forEach(groupByTimeStampBucket -> {\n                            Long timeStamp = Long.valueOf(((JSONObject) groupByTimeStampBucket).get(KEY).toString());\n                            Double value;\n                            if (MetricsUtils.needConvertUnit(aggKey)) {\n                                value = MetricsUtils.getDoubleValuePerMin(interval, Optional.ofNullable(\n                                                ((JSONObject) groupByTimeStampBucket).get(aggKey).toString())\n                                        .map(Object::toString).orElse(\"0\"));\n                            } else {\n                                value = Optional.ofNullable(\n                                                ((JSONObject) groupByTimeStampBucket).getJSONObject(aggKey).get(VALUE))\n                                        .map(d -> Double.valueOf(d.toString())).orElse(0.0);\n                            }\n                            metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                        });\n            }\n            metricsContents.add(metricsContent);\n        }\n        return metricsContents;\n    }\n  \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/gateway/GatewayDslMetricsDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.gateway;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContentCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.GatewayMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.metric.BaseTopNMetricsDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.google.common.collect.Lists;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\n@Component\n@NoArgsConstructor\npublic class GatewayDslMetricsDAO extends BaseTopNMetricsDAO {\n    private static final String TYPE = \"type\";\n    private static final String AGG_KEY_TIMESTAMP = \"group_by_timeStamp\";\n    private static final String AGG_KEY_DSL       = \"group_by_dsl\";\n    private static final String KEY               = \"key\";\n    private static final String EXISTS            = \"exists\";\n    private static final String FIELD             = \"field\";\n    private static final String EMPTY_STR         = \"\";\n    private static final Long   AGG_TERMS_SIZE    = 1000L;\n    private static final String TERMS             = \"terms\";\n    private static final String DSL_TEMPLATE_MD5  = \"dslTemplateMd5\";\n    private static final String TOTAL_COST        = \"totalCost\";\n    private static final String TOTAL_COST_AVG    = \"total_cost_avg\";\n    private static final String AVG               = \"avg\";\n    \n    @PostConstruct\n    public void init() {\n        super.indexName = dataCentreUtil.getAriusStatsGatewayInfo();\n    }\n\n    /**\n     * 获取各查询模版访问量 count  topN\n     */\n    public VariousLineChartMetrics getDslCountByRange(Long startTime, Long endTime, Integer topNu, Integer projectId) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_DSL_COUNT, startTime, endTime,\n            projectId, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchDslResult(response, GatewayMetricsTypeEnum.QUERY_DSL_COUNT, topNu,\n                interval),\n            3);\n    }\n\n    /**\n     * 获取某个查询模版访问量 count by dslTemplateMd5\n     */\n    public VariousLineChartMetrics getDslCountByRangeAndMd5(Long startTime, Long endTime, String dslMd5,\n                                                            Integer projectId) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_DSL_COUNT_BY_MD5, dslMd5, startTime,\n            endTime, projectId, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchDslResultByMd5(response, GatewayMetricsTypeEnum.QUERY_DSL_COUNT, dslMd5,\n                interval),\n            3);\n    }\n\n    /**\n     * 获取各个查询模版访问耗时  topN\n     */\n    public VariousLineChartMetrics getDslTotalCostByRange(Long startTime, Long endTime, Integer topNu,\n                                                          Integer projectId) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_DSL_TOTAL_COST, startTime, endTime,\n            projectId, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchDslResult(response, GatewayMetricsTypeEnum.QUERY_DSL_TOTAL_COST, topNu,\n                interval),\n            3);\n    }\n\n    /**\n     * 获取某个查询模版访问耗时  by dslTemplateMd5 GET_GATEWAY_DSLMD5_BY_PROJECT_ID\n     */\n    public VariousLineChartMetrics getDslTotalCostByRangeAndMd5(Long startTime, Long endTime, String dslMd5,\n                                                                Integer projectId) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_DSL_TOTAL_COST_BY_MD5, dslMd5,\n            startTime, endTime, projectId, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchDslResultByMd5(response, GatewayMetricsTypeEnum.QUERY_DSL_TOTAL_COST,\n                dslMd5, interval),\n            3);\n    }\n\n    /**\n     * 获取某个projectId下的dslTemplateMd5\n     */\n    public List<String> getDslMd5List(Long startTime, Long endTime, Integer projectId) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_DSL_MD5_BY_PROJECT_ID, projectId,\n            startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl, (ESQueryResponse response) -> {\n            List<String> list = Lists.newArrayList();\n            Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                .orElse(null);\n            if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_DSL)) {\n                for (ESBucket esBucket : esAggrMap.get(AGG_KEY_DSL).getBucketList()) {\n                    String dslMd5 = esBucket.getUnusedMap().get(KEY).toString();\n                    list.add(dslMd5);\n                }\n            }\n            return list;\n        }, 3);\n    }\n\n    private VariousLineChartMetrics fetchDslResult(ESQueryResponse response,\n                                                   GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Integer topNu,\n                                                   String interval) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(gatewayMetricsTypeEnum.getType());\n        variousLineChartMetrics.setMetricsContents(Lists.newArrayList());\n\n        Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n            .orElse(null);\n        if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_DSL)) {\n            for (ESBucket esBucket : esAggrMap.get(AGG_KEY_DSL).getBucketList()) {\n                String dslMd5 = esBucket.getUnusedMap().get(KEY).toString();\n                MetricsContent metricsContent = new MetricsContent();\n                metricsContent.setName(dslMd5);\n                metricsContent.setMetricsContentCells(Lists.newArrayList());\n                variousLineChartMetrics.getMetricsContents().add(metricsContent);\n                if (null != esBucket.getAggrMap() && null != esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP)) {\n                    handleBucketList(gatewayMetricsTypeEnum, interval, esBucket, metricsContent);\n                }\n            }\n\n            // 根据第一个时间点的值进行倒排，取topNu\n            List<MetricsContent> sortedList = variousLineChartMetrics.getMetricsContents().stream()\n                .sorted(\n                    Comparator.comparing(x -> x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder()))\n                .limit(topNu).collect(Collectors.toList());\n            variousLineChartMetrics.setMetricsContents(sortedList);\n        }\n\n        return variousLineChartMetrics;\n    }\n\n    private void handleBucketList(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, String interval, ESBucket esBucket,\n                                  MetricsContent metricsContent) {\n        for (ESBucket bucket : esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).getBucketList()) {\n            Long timeStamp = Long.valueOf(bucket.getUnusedMap().get(KEY).toString());\n            String aggKey = gatewayMetricsTypeEnum.getAggKey();\n            Double value;\n            if (MetricsUtils.needConvertUnit(aggKey)) {\n                value = MetricsUtils.getDoubleValuePerMin(interval, bucket.getUnusedMap().get(aggKey).toString());\n            } else {\n                value = MetricsUtils.getAggMapDoubleValue(bucket, aggKey);\n            }\n            metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n        }\n    }\n\n    private VariousLineChartMetrics fetchDslResultByMd5(ESQueryResponse response,\n                                                        GatewayMetricsTypeEnum gatewayMetricsTypeEnum, String dslMd5,\n                                                        String interval) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(gatewayMetricsTypeEnum.getType());\n\n        MetricsContent metricsContent = new MetricsContent();\n        metricsContent.setName(dslMd5);\n        metricsContent.setMetricsContentCells(Lists.newArrayList());\n\n        variousLineChartMetrics.setMetricsContents(Lists.newArrayList(metricsContent));\n\n        Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n            .orElse(null);\n        if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_TIMESTAMP)) {\n            for (ESBucket esBucket : esAggrMap.get(AGG_KEY_TIMESTAMP).getBucketList()) {\n                Long timeStamp = Long.valueOf(esBucket.getUnusedMap().get(KEY).toString());\n                String aggKey = gatewayMetricsTypeEnum.getAggKey();\n                Double value;\n                if (MetricsUtils.needConvertUnit(aggKey)) {\n                    value = MetricsUtils.getDoubleValuePerMin(interval, esBucket.getUnusedMap().get(aggKey).toString());\n                } else {\n                    value = MetricsUtils.getAggMapDoubleValue(esBucket, aggKey);\n                }\n                metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n            }\n        }\n\n        return variousLineChartMetrics;\n    }\n    \n    @Override\n    protected String getFinalDslByOneStep(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Object[] args) {\n        switch (gatewayMetricsTypeEnum) {\n            case QUERY_DSL_COUNT:\n                return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_COUNT_BY_FILELD, args);\n            case QUERY_DSL_TOTAL_COST:\n                return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOTAL_COST_BY_FIELD, args);\n            default:\n                return null;\n        }\n    }\n    \n    @Override\n    protected String getFinalDslBySecondStep(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Object[] args) {\n        if (gatewayMetricsTypeEnum.equals(GatewayMetricsTypeEnum.QUERY_DSL_COUNT)) {\n            return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_COUNT_EXTENDED_BOUNDS_BY_FILELD, args);\n        } else if (gatewayMetricsTypeEnum.equals(GatewayMetricsTypeEnum.QUERY_DSL_TOTAL_COST)) {\n            return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOTAL_COST_EXTENDED_BOUNDS_BY_FIELD, args);\n        }\n        return null;\n    }\n    \n    @Override\n    public List<VariousLineChartMetrics> fetchTopMetric(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                                        Long endTime, Integer topNu, Integer projectId, String dslMd5)\n            throws AdminOperateException {\n        //构建has data time的第一个时间片段\n        String queryDslFragmentByHasDataTime =  buildTermByProjectId(projectId);\n        //构建has data time最终的query dsl\n        String queryDslByHasDataTime = dslLoaderUtil.getFormatDslByFileName(\n                DslsConstant.GET_HAS_METRIC_INFO_TIME_BY_FIELD, startTime, endTime, queryDslFragmentByHasDataTime);\n        //获取query filter terms 片段\n        String queryDslFragment = buildTermByProjectId(projectId);\n        String interval = MetricsUtils.Interval.FIVE_MIN.getStr();\n        Object[] param;\n        switch (gatewayMetricsTypeEnum) {\n            case QUERY_DSL_COUNT:\n                param = new Object[] { queryDslFragment, AGG_KEY_DSL, DSL_TEMPLATE_MD5, AGG_TERMS_SIZE, interval };\n                break;\n            case QUERY_DSL_TOTAL_COST:\n                param = new Object[] { queryDslFragment, AGG_KEY_DSL, DSL_TEMPLATE_MD5, AGG_TERMS_SIZE, interval,\n                                       TOTAL_COST_AVG, AVG, TOTAL_COST };\n                break;\n            default:\n                return Collections.emptyList();\n        }\n        return this.performFetchTopMetric(gatewayMetricsTypeEnum, startTime, endTime,\n                (ESQueryResponse response) -> Collections.singletonList(\n                        fetchDslResult(response, gatewayMetricsTypeEnum, topNu, interval)), queryDslByHasDataTime,\n                dslMd5, param);\n    }\n   \n    \n    /**\n     * <pre>     ,\n     * {\n     *           \"terms\": {\n     *             \"dslTemplateMd5\": [\n     *               \"VALUE1\",\n     *               \"VALUE2\"\n     *             ]\n     *           }\n     *         }\n     *\n     * </pre>\n     * @param names\n     * {@linkplain GatewayDslMetricsDAO DSL_TEMPLATE_MD5} 的 value 值 * @return str\n     */\n    private String buildTermsByDslTemplateMd5Field(List<String> names) {\n        return String.format(\",%s\",\n                new JSONObject().fluentPut(TERMS, new JSONObject().fluentPut(DSL_TEMPLATE_MD5, names)).toJSONString());\n    }\n    @Override\n    public List<MetricsContent> getByRangeTopN(List<String> values, GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                               Long startTime, Long endTime, Integer projectId)\n            throws AdminOperateException {\n        if (CollectionUtils.isEmpty(values)) {\n            return Collections.emptyList();\n        }\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String queryDslFragment = buildTermsByDslTemplateMd5Field(values) + buildTermByProjectId(projectId);\n        final String valueInclude = new JSONArray().fluentAddAll(values).toJSONString();\n        Object[] param;\n        switch (gatewayMetricsTypeEnum) {\n            case QUERY_DSL_COUNT:\n                param = new Object[] { startTime, endTime, queryDslFragment, AGG_KEY_DSL, DSL_TEMPLATE_MD5,\n                                       values.size(), valueInclude, interval, startTime, endTime };\n                break;\n            case QUERY_DSL_TOTAL_COST:\n                param = new Object[] { startTime, endTime, queryDslFragment, AGG_KEY_DSL, DSL_TEMPLATE_MD5,\n                                       values.size(), valueInclude, interval, startTime, endTime, TOTAL_COST_AVG, AVG,\n                                       TOTAL_COST };\n                break;\n            default:\n                return Collections.emptyList();\n        }\n        return performGetByRangeTopN(gatewayMetricsTypeEnum, startTime, endTime,\n                (ESQueryResponse response) -> fetchDslResultByFiled(response, gatewayMetricsTypeEnum, interval), param);\n    }\n    \n    private List<MetricsContent> fetchDslResultByFiled(ESQueryResponse response,\n                                                       GatewayMetricsTypeEnum gatewayMetricsTypeEnum, String interval) {\n        Optional<List<ESBucket>> esBucketOptional = Optional.ofNullable(response).map(ESQueryResponse::getAggs)\n                .map(ESAggrMap::getEsAggrMap)\n                //确定map不为空/null\n                .filter(MapUtils::isNotEmpty)\n                //确定含有key\n                .filter(esAggrMap -> esAggrMap.containsKey(AGG_KEY_DSL))\n                .map(esAggrMap -> esAggrMap.get(AGG_KEY_DSL).getBucketList())\n                //确定buckets不为空\n                .filter(CollectionUtils::isNotEmpty);\n        List<MetricsContent> metricsContents = Lists.newArrayList();\n        String aggKey = gatewayMetricsTypeEnum.getAggKey();\n        if (esBucketOptional.isPresent()) {\n            for (ESBucket esBucket : esBucketOptional.get()) {\n                //group_by_dsl 的key值\n                String fieldByValue = esBucket.getUnusedMap().get(KEY).toString();\n                MetricsContent metricsContent = new MetricsContent();\n                metricsContent.setName(fieldByValue);\n                metricsContent.setMetricsContentCells(Lists.newArrayList());\n                //group_by_timeStamp 的buckets的结果值\n                if (esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).getBucketList() != null) {\n                    for (ESBucket groupByTimeStampBucket : esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP)\n                            .getBucketList()) {\n                        Long timeStamp = Long.valueOf(groupByTimeStampBucket.getUnusedMap().get(KEY).toString());\n                        Double value;\n                        if (MetricsUtils.needConvertUnit(aggKey)) {\n                            value = MetricsUtils.getDoubleValuePerMin(interval,\n                                    groupByTimeStampBucket.getUnusedMap().get(aggKey).toString());\n                        } else {\n                            value = MetricsUtils.getAggMapDoubleValue(groupByTimeStampBucket, aggKey);\n                        }\n                        metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                    }\n                } else {\n                    esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).toJson().getJSONObject(BUCKETS).values()\n                            .forEach(groupByTimeStampBucket -> {\n                                Long timeStamp = Long.valueOf(\n                                        ((JSONObject) groupByTimeStampBucket).get(KEY).toString());\n                                Double value;\n                                if (MetricsUtils.needConvertUnit(aggKey)) {\n                                    value = MetricsUtils.getDoubleValuePerMin(interval, Optional.ofNullable(\n                                                    ((JSONObject) groupByTimeStampBucket).get(aggKey).toString())\n                                            .map(Object::toString).orElse(\"0\"));\n                                } else {\n                                    value = Optional.ofNullable(\n                                                    ((JSONObject) groupByTimeStampBucket).getJSONObject(aggKey).get(VALUE))\n                                            .map(d -> Double.valueOf(d.toString())).orElse(0.0);\n                                }\n                                metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                            });\n                }\n                metricsContents.add(metricsContent);\n            }\n        }\n        return metricsContents;\n    }\n    \n    @Override\n    public List<VariousLineChartMetrics> checkMetricsValue(GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                           String metricsValue) {\n        \n        // 当该指标存在时候，直接进行返回\n        if (StringUtils.isNotBlank(metricsValue)) {\n            VariousLineChartMetrics metrics = new VariousLineChartMetrics();\n            metrics.setType(gatewayMetricsTypeEnum.getType());\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(metricsValue);\n            metrics.setMetricsContents(Collections.singletonList(metricsContent));\n            return Collections.singletonList(metrics);\n        }\n        return Collections.emptyList();\n    }\n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/gateway/GatewayIndexMetricsDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.gateway;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContentCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.GatewayMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.metric.BaseTopNMetricsDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.google.common.collect.Lists;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\n@Component\n@NoArgsConstructor\npublic class GatewayIndexMetricsDAO extends BaseTopNMetricsDAO {\n    private static final String TYPE = \"type\";\n    private static final String  AGG_KEY_TIMESTAMP         = \"group_by_timeStamp\";\n    private static final String  AGG_KEY_TEMPLATE          = \"group_by_template\";\n    private static final String  DEST_TEMPLATE_NAME        = \"destTemplateName\";\n    private static final String  TOTAL_COST                = \"totalCost\";\n    private static final String  TOTAL_COST_AVG            = \"total_cost_avg\";\n    private static final String  AVG                       = \"avg\";\n    private static final String  QUERY_REQUEST             = \"queryRequest\";\n    private static final boolean QUERY_REQUEST_VALUE_TRUE  = true;\n    private static final boolean QUERY_REQUEST_VALUE_FALSE = false;\n    private static final String  KEY                       = \"key\";\n    private static final String  TERMS                     = \"terms\";\n    private static final String  TERM                      = \"term\";\n    private static final String  EXISTS                    = \"exists\";\n    private static final String  FIELD                     = \"field\";\n    private static final Long    AGG_TERMS_SIZE            = 5000L;\n    \n    @PostConstruct\n    public void init() {\n        super.indexName = dataCentreUtil.getAriusStatsGatewayInfo();\n    }\n    /**\n     * 获取各索引写入. topNu\n     */\n    public List<VariousLineChartMetrics> getWriteIndex(List<String> metricsTypes, Long startTime, Long endTime,\n                                                       Integer projectId, Integer topNu) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_INDEX_WRITE, projectId, startTime,\n            endTime, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldAggMetrics(response, metricsTypes, topNu, interval), 3);\n    }\n\n    /**\n     * 获取某个索引写入 by templateName\n     */\n    public List<VariousLineChartMetrics> getWriteIndexByTemplateName(List<String> metricsTypes, Long startTime,\n                                                                     Long endTime, Integer projectId,\n                                                                     String templateName) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_INDEX_WRITE_BY_TEMPLATE_NAME,\n            projectId, templateName, startTime, endTime, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldByTemplateAggMetrics(response, metricsTypes, templateName,\n                interval),\n            3);\n    }\n\n    /**\n     * 获取各索引查询. topNu\n     */\n    public List<VariousLineChartMetrics> getSearchIndex(List<String> metricsTypes, Long startTime, Long endTime,\n                                                        Integer projectId, Integer topNu) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_INDEX_SEARCH, projectId, startTime,\n            endTime, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldAggMetrics(response, metricsTypes, topNu, interval), 3);\n    }\n\n    /**\n     * 获取某个索引查询 by templateName\n     */\n    public List<VariousLineChartMetrics> getSearchIndexByTemplateName(List<String> metricsTypes, Long startTime,\n                                                                      Long endTime, Integer projectId,\n                                                                      String templateName) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_INDEX_SEARCH_BY_TEMPLATE_NAME,\n            projectId, templateName, startTime, endTime, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldByTemplateAggMetrics(response, metricsTypes, templateName,\n                interval),\n            3);\n    }\n\n    private List<VariousLineChartMetrics> fetchFieldAggMetrics(ESQueryResponse response, List<String> metricsTypes,\n                                                               Integer topNu, String interval) {\n        List<VariousLineChartMetrics> list = Lists.newArrayList();\n        for (String metricsType : metricsTypes) {\n            VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n            variousLineChartMetrics.setType(metricsType);\n            variousLineChartMetrics.setMetricsContents(Lists.newArrayList());\n            list.add(variousLineChartMetrics);\n            Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                .orElse(null);\n            if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_TEMPLATE)) {\n                handleBucketList(interval, metricsType, variousLineChartMetrics, esAggrMap);\n\n                //根据第一个时间点的值进行倒排，取topNu\n                List<MetricsContent> sortedList = variousLineChartMetrics\n                    .getMetricsContents().stream().sorted(Comparator\n                        .comparing(x -> x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder()))\n                    .limit(topNu).collect(Collectors.toList());\n                variousLineChartMetrics.setMetricsContents(sortedList);\n            }\n\n        }\n\n        return list;\n    }\n\n    private void handleBucketList(String interval, String metricsType, VariousLineChartMetrics variousLineChartMetrics,\n                                  Map<String, ESAggr> esAggrMap) {\n        for (ESBucket esBucket : esAggrMap.get(AGG_KEY_TEMPLATE).getBucketList()) {\n            String indexTemplate = esBucket.getUnusedMap().get(KEY).toString();\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(indexTemplate);\n            metricsContent.setMetricsContentCells(Lists.newArrayList());\n            variousLineChartMetrics.getMetricsContents().add(metricsContent);\n            if (null != esBucket.getAggrMap() && null != esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP)) {\n                for (ESBucket bucket : esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).getBucketList()) {\n                    Long timeStamp = Long.valueOf(bucket.getUnusedMap().get(KEY).toString());\n                    String aggKey = GatewayMetricsTypeEnum.type2AggKey(metricsType);\n                    Double value;\n                    if (MetricsUtils.needConvertUnit(aggKey)) {\n                        value = MetricsUtils.getDoubleValuePerMin(interval,\n                            bucket.getUnusedMap().get(aggKey).toString());\n                    } else {\n                        value = MetricsUtils.getAggMapDoubleValue(bucket, aggKey);\n                    }\n                    metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                }\n            }\n        }\n    }\n\n    private List<VariousLineChartMetrics> fetchFieldByTemplateAggMetrics(ESQueryResponse response,\n                                                                         List<String> metricsTypes, String templateName,\n                                                                         String interval) {\n        List<VariousLineChartMetrics> list = Lists.newArrayList();\n        for (String metricsType : metricsTypes) {\n            VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n            variousLineChartMetrics.setType(metricsType);\n\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(templateName);\n            metricsContent.setMetricsContentCells(Lists.newArrayList());\n\n            variousLineChartMetrics.setMetricsContents(Lists.newArrayList(metricsContent));\n            list.add(variousLineChartMetrics);\n\n            Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                .orElse(null);\n            if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_TIMESTAMP)) {\n                for (ESBucket esBucket : esAggrMap.get(AGG_KEY_TIMESTAMP).getBucketList()) {\n                    Long timeStamp = Long.valueOf(esBucket.getUnusedMap().get(KEY).toString());\n                    String aggKey = GatewayMetricsTypeEnum.type2AggKey(metricsType);\n                    Double value;\n                    if (MetricsUtils.needConvertUnit(aggKey)) {\n                        value = MetricsUtils.getDoubleValuePerMin(interval,\n                            esBucket.getUnusedMap().get(aggKey).toString());\n                    } else {\n                        value = MetricsUtils.getAggMapDoubleValue(esBucket, aggKey);\n                    }\n                    metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                }\n            }\n        }\n        return list;\n    }\n    \n    @Override\n    public List<VariousLineChartMetrics> fetchTopMetric(GatewayMetricsTypeEnum metricsType, Long startTime,\n                                                        Long endTime, Integer topNu, Integer projectId,\n                                                        String destTemplateName) throws AdminOperateException {\n        \n        if (Objects.isNull(buildQueryRequestFragment(metricsType))) {\n            return Collections.emptyList();\n        }\n        //获取第一个时间点的dsl 片段\n        String queryDslByHasDataTime = \",\" + buildQueryRequestFragment(metricsType);\n        String queryDslByFiled = queryDslByHasDataTime + buildTermByProjectId(projectId);\n        //构建存在第一个时间位点的dsl\n        String hasDataTimeDsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_HAS_METRIC_INFO_TIME_BY_FIELD,\n                startTime, endTime, queryDslByFiled);\n       \n              \n        // 注意这里不用MetricsUtils.getIntervalForDashBoard\n        String interval = MetricsUtils.Interval.FIVE_MIN.getStr();\n        Object[] param = new Object[] { queryDslByFiled, AGG_KEY_TEMPLATE, DEST_TEMPLATE_NAME, AGG_TERMS_SIZE, interval,\n                                        TOTAL_COST_AVG, AVG, TOTAL_COST };\n        \n        return this.performFetchTopMetric(metricsType, startTime, endTime,\n                (ESQueryResponse response) -> fetchFieldAggMetrics(response, metricsType, topNu, interval),\n                hasDataTimeDsl, destTemplateName, param);\n    }\n    \n    @Override\n    public List<MetricsContent> getByRangeTopN(List<String> values, GatewayMetricsTypeEnum metricsType, Long startTime,\n                                               Long endTime, Integer projectId) throws AdminOperateException {\n        if (CollectionUtils.isEmpty(values)) {\n            return Collections.emptyList();\n        }\n        final String valueInclude = new JSONArray().fluentAddAll(values).toJSONString();\n        String queryDslByFiled =\n                buildTermsByDslTemplateMd5AndQueryRequest(values, metricsType) + buildTermByProjectId(projectId);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        Object[] param = new Object[] { startTime, endTime, queryDslByFiled, AGG_KEY_TEMPLATE, DEST_TEMPLATE_NAME,\n                                        values.size(), valueInclude, interval, startTime, endTime, TOTAL_COST_AVG, AVG,\n                                        TOTAL_COST };\n        return this.performGetByRangeTopN(metricsType, startTime, endTime,\n                (ESQueryResponse response) -> fetchDslResultByFiled(response, metricsType, interval), param);\n    }\n    \n    @Override\n    public List<VariousLineChartMetrics> checkMetricsValue(GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                           String metricsValue) {\n        // 当该指标存在时候，直接进行返回\n        if (StringUtils.isNotBlank(metricsValue)) {\n            VariousLineChartMetrics metrics = new VariousLineChartMetrics();\n            metrics.setType(gatewayMetricsTypeEnum.getType());\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(metricsValue);\n            metrics.setMetricsContents(Collections.singletonList(metricsContent));\n            return Collections.singletonList(metrics);\n        }\n        return Collections.emptyList();\n    }\n    \n    private List<MetricsContent> fetchDslResultByFiled(ESQueryResponse response, GatewayMetricsTypeEnum metricsType,\n                                                       String interval) {\n        Optional<List<ESBucket>> esBucketOptional = Optional.ofNullable(response).map(ESQueryResponse::getAggs)\n                .map(ESAggrMap::getEsAggrMap)\n                //确定map不为空/null\n                .filter(MapUtils::isNotEmpty)\n                //确定含有key\n                .filter(esAggrMap -> esAggrMap.containsKey(AGG_KEY_TEMPLATE))\n                .map(esAggrMap -> esAggrMap.get(AGG_KEY_TEMPLATE).getBucketList())\n                //确定buckets不为空\n                .filter(CollectionUtils::isNotEmpty);\n        List<MetricsContent> metricsContents = Lists.newArrayList();\n        String aggKey = GatewayMetricsTypeEnum.type2AggKey(metricsType.getType());\n        if (esBucketOptional.isPresent()) {\n            for (ESBucket esBucket : esBucketOptional.get()) {            //group_by_dsl 的key值\n                String indexTemplate = esBucket.getUnusedMap().get(KEY).toString();\n                MetricsContent metricsContent = new MetricsContent();\n                metricsContent.setName(indexTemplate);\n                metricsContent.setMetricsContentCells(\n                        Lists.newArrayList());            //group_by_timeStamp 的buckets的结果值\n                if (esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).getBucketList() != null) {\n                    for (ESBucket groupByTimeStampBucket : esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP)\n                            .getBucketList()) {\n                        Long timeStamp = Long.valueOf(groupByTimeStampBucket.getUnusedMap().get(KEY).toString());\n                        Double value;\n                        if (MetricsUtils.needConvertUnit(aggKey)) {\n                            value = MetricsUtils.getDoubleValuePerMin(interval,\n                                    groupByTimeStampBucket.getUnusedMap().get(aggKey).toString());\n                        } else {\n                            value = MetricsUtils.getAggMapDoubleValue(groupByTimeStampBucket, aggKey);\n                        }\n                        metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                    }\n                } else {\n                    esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).toJson().getJSONObject(BUCKETS).values()\n                            .forEach(groupByTimeStampBucket -> {\n                                Long timeStamp = Long.valueOf(\n                                        ((JSONObject) groupByTimeStampBucket).get(KEY).toString());\n                                Double value;\n                                if (MetricsUtils.needConvertUnit(aggKey)) {\n                                    value = MetricsUtils.getDoubleValuePerMin(interval, Optional.ofNullable(\n                                                    ((JSONObject) groupByTimeStampBucket).get(aggKey).toString())\n                                            .map(Object::toString).orElse(\"0\"));\n                                } else {\n                                    value = Optional.ofNullable(\n                                                    ((JSONObject) groupByTimeStampBucket).getJSONObject(aggKey).get(VALUE))\n                                            .map(d -> Double.valueOf(d.toString())).orElse(0.0);\n                                }\n                                metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                            });\n                }\n                metricsContents.add(metricsContent);\n            }\n        }\n        return metricsContents;\n    }\n    \n    /**\n     * <B>write</B>\n     * <pre>\n     *      ,{\n     *           \"term\": {\n     *             \"queryRequest\": false\n     *           }\n     *         },\n     *         {\n     *           \"terms\": {\n     *             \"destTemplateName\": [\n     *               \"VALUE1\",\n     *               \"VALUE2\"\n     *             ]\n     *           }\n     *         }\n     *\n     *\n     * </pre>  or\n     * <B>search</B>\n     * <pre>\n     *     ,\n     *      {\n     *           \"term\": {\n     *             \"queryRequest\": true\n     *           }\n     *         },\n     *         {\n     *           \"terms\": {\n     *             \"destTemplateName\": [\n     *               \"VALUE1\",\n     *               \"VALUE2\"\n     *             ]\n     *           }\n     *         }\n     * </pre>\n     * @param destTemplateNames\n     * {@linkplain GatewayIndexMetricsDAO DEST_TEMPLATE_NAME}的values\n     * @param metricsType {@link GatewayMetricsTypeEnum}\n     * * @return {@link String}\n     */\n    private String buildTermsByDslTemplateMd5AndQueryRequest(List<String> destTemplateNames,\n                                                             GatewayMetricsTypeEnum metricsType) {\n        String queryRequestFragment = buildQueryRequestFragment(metricsType);\n        if (Objects.isNull(queryRequestFragment)) {\n            return null;\n        }\n        return String.format(\",%s,%s\", queryRequestFragment,\n                new JSONObject().fluentPut(TERMS, new JSONObject().fluentPut(DEST_TEMPLATE_NAME, destTemplateNames))\n                        .toJSONString());\n    }\n    \n    /**\n     * 建立查询请求片段\n     * <pre>\n     *     {\n     *     \"term\": {\n     *       \"queryRequest\": false\n     *     }\n     *   }\n     * </pre>\n     * or\n     * <pre>\n     *     {\n     *     \"term\": {\n     *       \"queryRequest\": false\n     *     }\n     *   }\n     * </pre>\n     * @param metricsType 指标类型\n     * @return {@link String}\n     */\n    private String buildQueryRequestFragment(GatewayMetricsTypeEnum metricsType) {\n        switch (metricsType) {\n            //wirte\n            // queryRequest  fasle\n            case WRITE_INDEX_COUNT:\n            case WRITE_INDEX_TOTAL_COST:\n                return new JSONObject().fluentPut(TERM,\n                        new JSONObject().fluentPut(QUERY_REQUEST, QUERY_REQUEST_VALUE_FALSE)).toJSONString();\n            //search  queryRequest true\n            case SEARCH_INDEX_COUNT:\n            case SEARCH_INDEX_TOTAL_COST:\n                return new JSONObject().fluentPut(TERM,\n                        new JSONObject().fluentPut(QUERY_REQUEST, QUERY_REQUEST_VALUE_TRUE)).toJSONString();\n            default:\n                return null;\n        }\n    }\n    \n    \n    \n    private List<VariousLineChartMetrics> fetchFieldAggMetrics(ESQueryResponse response,\n                                                               GatewayMetricsTypeEnum metricsType, Integer topNu,\n                                                               String interval) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(metricsType.getType());\n        variousLineChartMetrics.setMetricsContents(Lists.newArrayList());\n        Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                .orElse(null);\n        if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_TEMPLATE)) {\n            handleBucketList(interval, metricsType.getType(), variousLineChartMetrics, esAggrMap);\n        }\n        //根据第一个时间点的值进行倒排，取topNu\n        List<MetricsContent> sortedList = variousLineChartMetrics.getMetricsContents().stream()\n                .sorted(Comparator.nullsLast(Comparator.comparing(\n                        x -> CollectionUtils.isEmpty(x.getMetricsContentCells())\n                                ? -1\n                                : x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder())))\n                .limit(topNu).collect(Collectors.toList());\n        variousLineChartMetrics.setMetricsContents(sortedList);\n        return Collections.singletonList(variousLineChartMetrics);\n    }\n    \n    @Override\n    protected String getFinalDslByOneStep(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Object[] args) {\n        return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOTAL_COST_BY_FIELD, args);\n    }\n    \n    @Override\n    protected String getFinalDslBySecondStep(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Object[] args) {\n        return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOTAL_COST_EXTENDED_BOUNDS_BY_FIELD, args);\n    }\n   \n    \n    \n    \n\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/gateway/GatewayJoinESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.gateway;\n\nimport java.text.SimpleDateFormat;\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport javax.annotation.Nullable;\nimport javax.annotation.PostConstruct;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.BooleanUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.GatewayJoinQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ExceptionDslRequest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.QueryQpsMetric;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayJoinPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.query.ProjectQueryPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESConstant;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHit;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHits;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\n\nimport lombok.NoArgsConstructor;\n\n/**\n *\n *\n * @author shizeying\n * @date 2022/06/11\n */\n@Component\n@NoArgsConstructor\npublic class GatewayJoinESDAO extends BaseESDAO {\n\n    private static final String DOC_COUNT                     = \"doc_count\";\n    private static final String INDICES                       = \"indices\";\n    private static final String DOUBLE_STRING_WITH_UNDER_LINE = \"%s_%s\";\n\n    /**\n     * gateway join索引\n     */\n    private String              indexName;\n    /**\n     * type名称\n     */\n    private String              typeName                      = \"type\";\n\n    @PostConstruct\n    public void init() {\n        this.indexName = dataCentreUtil.getAriusGatewayJoin();\n    }\n\n    private static final long ONE_DAY = 24 * 60 * 60 * 1000L;\n\n    /**\n     * 根据index获得对应的templateMD5\n     *\n     * @param templateName\n     * @return\n     */\n    public Map<String/*dslMd5*/, Set<String>/*dsls*/> getTemplateMD5ByRealIndexName(String templateName) {\n        Map<String/*dslMd5*/, Set<String>/*dsls*/> dslMap = Maps.newHashMap();\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSLS_BY_INDEX_NAME, templateName);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(getTemplateExpression(), null, dsl);\n        if (esAggrMap == null) {\n            return dslMap;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"md5s\");\n        if (esAggr == null) {\n            return dslMap;\n        }\n\n        try {\n            List<ESBucket> esBucketList = esAggr.getBucketList();\n            if (esBucketList != null) {\n                handleBucketListInGetTemplateMD5ByRealIndexName(dslMap, esBucketList);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=GatewayJoinEsDao||method=getTemplateMD5ByrealIndexName||errMsg={} fail to get dsls\",\n                templateName, e);\n        }\n\n        return dslMap;\n    }\n\n    /**\n     * 根据projectId获得对应的99分位查询耗时\n     * @param projectId\n     * @param startTime\n     * @param endTime\n     * @return ArrayList 排序后返回前10条\n     */\n    public List<Double> getRtCostByProjectId(Integer projectId, Long startTime, Long endTime) {\n        List<Double> rtCostList = Lists.newArrayList();\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_QUERY_RT_BY_PROJECT_ID, projectId, startTime,\n            endTime);\n        return gatewayClient.performRequest(getIndexByTimeRange(startTime, endTime), typeName, dsl, response -> {\n            Map<String, ESAggr> esAggrMap = response.getAggs().getEsAggrMap();\n            if (null != esAggrMap && esAggrMap.containsKey(\"queryByTimeStamp\")) {\n                ESAggr queryByTimeStamp = esAggrMap.get(\"queryByTimeStamp\");\n                if (null != queryByTimeStamp && CollectionUtils.isNotEmpty(queryByTimeStamp.getBucketList())) {\n                    handleBucketListInGetRtCostByProjectId(rtCostList, queryByTimeStamp);\n                }\n            }\n            if (CollectionUtils.isEmpty(rtCostList) || rtCostList.size() < 10) {\n                return rtCostList;\n            }\n            rtCostList.sort(Comparator.reverseOrder());\n            return rtCostList.subList(0, 10);\n\n        }, 3);\n    }\n\n    /**\n     * 根据projectId获得查询topNum信息\n     * @param projectId\n     * @param startTime\n     * @param endTime\n     * @param topNum\n     * @return\n     */\n    public List<ProjectQueryPO> getQueryTopNumInfoByProjectId(Integer projectId, Long startTime, Long endTime,\n                                                              int topNum) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOP_NUM_QUERY_INFO_BY_PROJECT_ID, projectId,\n            startTime, endTime, topNum);\n        return gatewayClient.performRequest(getIndexByTimeRange(startTime, endTime), typeName, dsl, response -> {\n            List<ESHit> hits = response.getHits().getHits();\n            List<ProjectQueryPO> quetyInfoList = Lists.newArrayList();\n            if (CollectionUtils.isNotEmpty(hits)) {\n                for (ESHit hit : hits) {\n                    try {\n                        ProjectQueryPO projectQuery = ConvertUtil.obj2ObjByJSON(hit.getSource(), ProjectQueryPO.class);\n                        if (null != projectQuery) {\n                            quetyInfoList.add(projectQuery);\n                        }\n                    } catch (Exception e) {\n                        LOGGER.error(\"class=GatewayJoinEsDao||method=getQueryTopNumInfoByProjectId||errMsg={}\", e);\n                    }\n                }\n                return quetyInfoList;\n            }\n            return quetyInfoList;\n        }, 3);\n    }\n\n    /**\n     * 根据index获得查询请求\n     *\n     * @param templateName\n     * @return\n     */\n    public Map<String/*dslMd5*/, GatewayJoinPO> getSearchRequestByRealIndexName(String templateName) {\n        Map<String/*dslMd5*/, GatewayJoinPO> dslMap = Maps.newHashMap();\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_SEARCH_REQUEST_BY_INDEX_NAME, templateName);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(getTemplateExpression(), null, dsl);\n        if (esAggrMap == null) {\n            return dslMap;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"md5s\");\n        if (esAggr == null) {\n            return dslMap;\n        }\n\n        try {\n            List<ESBucket> esBucketList = esAggr.getBucketList();\n            if (esBucketList != null) {\n                handleESBucketListInGetSearchRequestByRealIndexName(dslMap, esBucketList);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=GatewayJoinEsDao||method=getSearchRequestByrealIndexName||errMsg={} fail to get dsls\",\n                templateName, e);\n        }\n\n        return dslMap;\n    }\n\n    private void handleESBucketListInGetSearchRequestByRealIndexName(Map<String, GatewayJoinPO> dslMap,\n                                                                     List<ESBucket> esBucketList) {\n        ESAggr subEsAggr;\n        String md5;\n        for (ESBucket esBucket : esBucketList) {\n            if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                continue;\n            }\n            md5 = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n\n            subEsAggr = esBucket.getAggrMap().get(\"samples\");\n            if (subEsAggr == null) {\n                continue;\n            }\n\n            Object obj = subEsAggr.getUnusedMap().get(\"hits\");\n            handleHits(dslMap, md5, obj);\n        }\n    }\n\n    private void handleHits(Map<String, GatewayJoinPO> dslMap, String md5, Object obj) {\n        GatewayJoinPO gatewayJoinPO;\n        if (obj instanceof JSONObject) {\n            JSONObject jsonObject = (JSONObject) obj;\n            JSONArray jsonArray = jsonObject.getJSONArray(\"hits\");\n            if (jsonArray != null && !jsonArray.isEmpty()) {\n                JSONObject hitJsonObj = jsonArray.getJSONObject(0);\n                JSONObject sourceJsonObj = hitJsonObj.getJSONObject(\"_source\");\n                if (sourceJsonObj != null) {\n                    gatewayJoinPO = JSON.parseObject(sourceJsonObj.toJSONString(), GatewayJoinPO.class);\n                    if (Objects.nonNull(gatewayJoinPO)) {\n                        dslMap.put(md5, gatewayJoinPO);\n                    }\n                }\n            }\n        }\n    }\n\n    public List<GatewayJoinPO> getGatewaySlowList(Long projectId, Long startDate, Long endDate) {\n        String realrealIndexName = IndexNameUtils.genDailyIndexName(getTemplateName(), startDate, endDate);\n        String dsl = null;\n        if (null == projectId) {\n            dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_SLOW_LIST_BY_RANGE, startDate, endDate);\n        } else {\n            dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_SLOW_LIST_BY_PROJECT_ID_AND_RANGE,\n                startDate, endDate, projectId);\n        }\n\n        return gatewayClient.performRequest(realrealIndexName, typeName, dsl, GatewayJoinPO.class);\n    }\n\n    public List<GatewayJoinPO> getGatewayErrorList(Long projectId, Long startDate, Long endDate) {\n        String realrealIndexName = IndexNameUtils.genDailyIndexName(getTemplateName(), startDate, endDate);\n        String dsl = null;\n        if (null == projectId) {\n            dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_ERROR_LIST_BY_RANGE, startDate,\n                endDate);\n        } else {\n            dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_ERROR_LIST_BY_PROJECT_ID_AND_RANGE,\n                startDate, endDate, projectId);\n        }\n\n        return gatewayClient.performRequest(realrealIndexName, typeName, dsl, GatewayJoinPO.class);\n    }\n\n    /**\n     * 根据projectId获取指定数据中心一段时间查询量\n     *\n     * @param projectId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public Long getSearchCountByProjectId(Long projectId, Long startDate, Long endDate) {\n        String realrealIndexName = IndexNameUtils.genDailyIndexName(getTemplateName(), startDate, endDate);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_SEARCH_COUNT_BY_PROJECT_ID_TIME_RANGE,\n            projectId, startDate, endDate);\n\n        return gatewayClient.performRequestAndGetTotalCount(realrealIndexName, typeName, dsl);\n    }\n\n    /**\n     * 获取指定索引的查询错误个数\n     *\n     * @param templateName\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public Long getErrorCntByTemplateName(String templateName, Long startDate, Long endDate) {\n        String realrealIndexName = IndexNameUtils.genDailyIndexName(getTemplateName(), startDate, endDate);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_ERROR_CNT_BY_TEMPLATE_NAME, templateName,\n            startDate, endDate);\n\n        return gatewayClient.performRequestAndGetTotalCount(realrealIndexName, typeName, dsl);\n    }\n\n    /**\n     * 获取指定索引的慢查询个数\n     *\n     * @param templateName\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public Long getSlowCntByTemplateName(String templateName, Long totalCost, Long startDate, Long endDate) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(getTemplateName(), startDate, endDate);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_SLOW_CNT_BY_TEMPLATE_NAME, templateName,\n            totalCost, startDate, endDate);\n        return gatewayClient.performRequestAndGetTotalCount(realIndexName, typeName, dsl);\n    }\n\n    /**\n     * 聚合获取某个应用访问的索引列表\n     *\n     * @param projectId\n     * @param dayCount\n     * @return\n     */\n    public Map<String, Long> getAccessRealIndexNameByProjectId(Integer projectId, Integer dayCount) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_ACCESS_INDEX_NAME_BY_PROJECT_ID, projectId);\n\n        StringBuilder stringBuilder = new StringBuilder(64);\n        for (int i = 0; i < dayCount; ++i) {\n            if (i > 0) {\n                stringBuilder.append(\",\");\n            }\n            stringBuilder\n                .append(String.format(DOUBLE_STRING_WITH_UNDER_LINE, indexName, DateTimeUtil.getFormatDayByOffset(i)));\n        }\n\n        Map<String, Long> realIndexNameCountMap = Maps.newHashMap();\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(stringBuilder.toString(), typeName, dsl);\n        if (esAggrMap == null) {\n            return realIndexNameCountMap;\n        }\n\n        String key = null;\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(INDICES);\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n\n                key = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n                realIndexNameCountMap.put(key,\n                    Long.valueOf(esBucket.getUnusedMap().get(ESConstant.AGG_DOC_COUNT).toString()));\n            }\n        }\n\n        return realIndexNameCountMap;\n    }\n\n    /**\n     * 获取指定projectId和时间范围下查询方式统计次数\n     *\n     * @param projectId\n     * @param dayCount\n     * @return\n     */\n    public Map<String, Long> getRequestTypeByProjectId(Integer projectId, String indexExp, Integer dayCount) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_REQUEST_TYPE_BY_PROJECT_ID, projectId,\n            indexExp);\n\n        StringBuilder stringBuilder = new StringBuilder(64);\n        for (int i = 0; i < dayCount; ++i) {\n            if (i > 0) {\n                stringBuilder.append(\",\");\n            }\n            stringBuilder\n                .append(String.format(DOUBLE_STRING_WITH_UNDER_LINE, indexName, DateTimeUtil.getFormatDayByOffset(i)));\n        }\n\n        Map<String, Long> requestTypeMap = Maps.newHashMap();\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(stringBuilder.toString(), typeName, dsl);\n        if (esAggrMap == null) {\n            return requestTypeMap;\n        }\n\n        String key = null;\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"requestType\");\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n\n                key = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n                requestTypeMap.put(key, Long.valueOf(esBucket.getUnusedMap().get(ESConstant.AGG_DOC_COUNT).toString()));\n            }\n        }\n\n        return requestTypeMap;\n    }\n\n    /**\n     * 获取某个查询模板一周内查询次数\n     *\n     * @param md5\n     * @return\n     */\n    public Long getWeekSearchCountByMd5(String md5) {\n        Long searchCount = 0L;\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_WEEK_SEARCH_COUNT_BY_MD5, md5);\n        Long count = gatewayClient.performRequestAndGetTotalCount(getTemplateExpression(), null, dsl);\n        if (count != null) {\n            searchCount = Math.max(searchCount, count);\n        }\n\n        return searchCount;\n    }\n\n    /**\n     * 根据索引名称和MD5获取一条查询明细中使用的字段信息\n     *\n     * @param indexDate\n     * @param indices\n     * @param md5\n     * @return\n     */\n    public Tuple<Long, GatewayJoinPO> getPoByIndicesAndMd5(String indexDate, String indices, String md5) {\n\n        String realIndexName = getIndex(indexDate);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_JOIN_BY_INDICES_MD5, indices, md5);\n\n        Tuple<Long, GatewayJoinPO> tuple = gatewayClient.performRequestAndGetTotalCount(realIndexName, null, dsl,\n            GatewayJoinPO.class);\n\n        if (tuple != null && tuple.v1() > 0) {\n            return tuple;\n        }\n\n        return null;\n    }\n\n    /**\n     * 聚合查询gateway join日志索引，获取到某个索引查询使用的MD5列表\n     *\n     * @param indexDate\n     * @param startTick\n     * @param endTick\n     */\n    public Map<String, Set<String>> aggIndicesDslMd5ByRange(String indexDate, long startTick, long endTick) {\n\n        Map<String/* realIndexName*/, Set<String> /*md5s*/> accessIndicesDslMd5Maps = Maps.newHashMap();\n\n        String realIndexName = getIndex(indexDate);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_INDICES_MD5, startTick, endTick);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, null, dsl);\n        if (esAggrMap == null) {\n            return accessIndicesDslMd5Maps;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(INDICES);\n        if (esAggr == null) {\n            return accessIndicesDslMd5Maps;\n        }\n\n        handleBucketListInAggIndicesDslMd5ByRange(accessIndicesDslMd5Maps, esAggr);\n\n        return accessIndicesDslMd5Maps;\n    }\n\n    private void handleBucketListInAggIndicesDslMd5ByRange(Map<String, Set<String>> accessIndicesDslMd5Maps,\n                                                           ESAggr esAggr) {\n        List<ESBucket> subEsBucketList;\n        String indices;\n        ESAggr subEsAggr;\n\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n                indices = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n\n                subEsAggr = esBucket.getAggrMap().get(\"md5\");\n                if (subEsAggr == null) {\n                    continue;\n                }\n\n                subEsBucketList = subEsAggr.getBucketList();\n                handleSubEsBucketList(accessIndicesDslMd5Maps, subEsBucketList, indices);\n\n            }\n        }\n    }\n\n    private void handleSubEsBucketList(Map<String, Set<String>> accessIndicesDslMd5Maps, List<ESBucket> subEsBucketList,\n                                       String indices) {\n        String md5;\n        if (CollectionUtils.isEmpty(subEsBucketList)) {\n            return;\n        }\n\n        for (ESBucket subEsBucket : subEsBucketList) {\n            if (subEsBucket.getUnusedMap() == null || subEsBucket.getUnusedMap().isEmpty()) {\n                continue;\n            }\n            md5 = subEsBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n            accessIndicesDslMd5Maps.computeIfAbsent(indices, k -> Sets.newHashSet()).add(md5);\n        }\n    }\n\n    /**\n     * 获取查询被限流的MD5\n     *\n     * @param date\n     * @return\n     */\n    public Set<String> getQueryLimitErrorMd5(String date) {\n        String realIndexName = getIndex(date);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_QUERY_LIMIT_ERROR_MD5);\n\n        Set<String> projectIdMd5Sets = Sets.newLinkedHashSet();\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, null, dsl);\n        if (esAggrMap == null) {\n            return new HashSet<>();\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"projectId\");\n        if (esAggr == null) {\n            return new HashSet<>();\n        }\n\n        handleBucketListInGetQueryLimitErrorMd5(projectIdMd5Sets, esAggr);\n\n        return projectIdMd5Sets;\n    }\n\n    private void handleBucketListInGetQueryLimitErrorMd5(Set<String> projectIdMd5Sets, ESAggr esAggr) {\n        String projectId;\n        ESAggr subEsAggr;\n\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n                projectId = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n\n                subEsAggr = esBucket.getAggrMap().get(\"dslTemplateMd5\");\n                if (subEsAggr == null) {\n                    continue;\n                }\n\n                handleSubEsBucketList(projectIdMd5Sets, projectId, subEsAggr);\n\n            }\n        }\n    }\n\n    private void handleSubEsBucketList(Set<String> projectIdMd5Sets, String projectId, ESAggr subEsAggr) {\n        List<ESBucket> subEsBucketList;\n        String dslTemplateMd5;\n        subEsBucketList = subEsAggr.getBucketList();\n        if (CollectionUtils.isEmpty(subEsBucketList)) {\n            return;\n        }\n\n        for (ESBucket subEsBucket : subEsBucketList) {\n            if (subEsBucket.getUnusedMap() == null || subEsBucket.getUnusedMap().isEmpty()) {\n                continue;\n            }\n            dslTemplateMd5 = subEsBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n            projectIdMd5Sets.add(String.format(DOUBLE_STRING_WITH_UNDER_LINE, projectId, dslTemplateMd5));\n        }\n    }\n\n    /**\n     * 根据projectId和MD5获取最新的一次查询记录\n     *\n     * @param projectId\n     * @param dslTemplateMd5\n     * @return\n     */\n    public GatewayJoinPO getFirstByProjectIdAndTemplateMd5(Long projectId, String dslTemplateMd5) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_ONE_GATEWAY_JOIN_BY_KEY, projectId,\n            dslTemplateMd5);\n\n        return gatewayClient.performRequestAndTakeFirst(getTemplateExpression(), null, dsl, GatewayJoinPO.class);\n    }\n\n    /**\n     * 获取一小时内查询模板提取失败的次数\n     *\n     * @param date\n     * @return\n     */\n    public Long getFailedDslTemplateCount(String date) {\n        String realIndexName = getIndex(date);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_FAILED_DSL_TEMPLATE);\n\n        return gatewayClient.performRequestAndGetTotalCount(realIndexName, typeName, dsl);\n    }\n\n    /**\n     * 获取查询模板提取失败的索引信息\n     *\n     * @param date\n     * @return\n     */\n    public Set<String> getFailedDslTemplateSearchIndices(String date) {\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_FAILED_DSL_TEMPLATE_INDICES);\n\n        Set<String> indicesSets = Sets.newLinkedHashSet();\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, typeName, dsl);\n        if (esAggrMap == null) {\n            return new HashSet<>();\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(INDICES);\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n\n                indicesSets.add(esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString());\n            }\n        }\n\n        return indicesSets;\n    }\n\n    /**\n     * 查询某个projectId 一天查询总量\n     *\n     * @param projectId\n     * @param date\n     * @return\n     */\n    public Long getTotalSearchCountByProjectIdAndDate(Integer projectId, String date) {\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_SEARCH_COUNT_BY_PROJECT_ID, projectId);\n\n        return gatewayClient.performRequestAndGetTotalCount(realIndexName, typeName, dsl);\n    }\n\n    /**\n     * 获取qps信息(最大qps，平均qps，最小qps)\n     *\n     * @param projectId\n     * @param date\n     * @return\n     */\n    public QueryQpsMetric getQpsInfoByProjectIdAndDate(Integer projectId, String date) {\n        QueryQpsMetric queryQpsMetric = new QueryQpsMetric();\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_QPS_INFO_BY_PROJECT_ID, projectId);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, typeName, dsl);\n        if (esAggrMap == null) {\n            return queryQpsMetric;\n        }\n\n        List<Tuple<Long, Long>> qpsList = Lists.newLinkedList();\n        Tuple<Long, Long> tuple;\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"searchCount\");\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        Long docCount;\n\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n                docCount = Long.valueOf(esBucket.getUnusedMap().get(ESConstant.AGG_DOC_COUNT).toString());\n                if (docCount <= 0) {\n                    continue;\n                }\n\n                tuple = new Tuple<>(docCount, Long.valueOf(esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString()));\n\n                qpsList.add(tuple);\n            }\n        }\n\n        if (qpsList.isEmpty()) {\n            return queryQpsMetric;\n        }\n\n        long totalQps = 0L;\n        for (Tuple<Long, Long> t : qpsList) {\n            totalQps += t.v1();\n        }\n\n        queryQpsMetric.setMaxQps(qpsList.get(0).v1());\n        queryQpsMetric.setMaxQpsTime(DateTimeUtil.formatTimestamp(qpsList.get(0).v2()));\n        queryQpsMetric.setMinQps(qpsList.get(qpsList.size() - 1).v1());\n        queryQpsMetric.setMinQpsTime(DateTimeUtil.formatTimestamp(qpsList.get(qpsList.size() - 1).v2()));\n        queryQpsMetric.setAvgQps((long) Math.floor(1.0 * totalQps / qpsList.size()));\n\n        return queryQpsMetric;\n    }\n\n    /**\n     * 获取查询耗时分位图\n     *\n     * @param projectId\n     * @param date\n     * @return\n     */\n    public Map<String, Object> getCostInfoByProjectIdAndDate(Integer projectId, String date) {\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_COST_INFO_BY_PROJECT_ID, projectId);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, typeName, dsl);\n        if (esAggrMap == null) {\n            return null;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"totalCost\");\n        if (esAggr == null) {\n            return null;\n        }\n\n        Map<String, Object> totalCostMap = Maps.newHashMap();\n        Object value = esAggr.getUnusedMap().get(\"values\");\n        if (value instanceof Map) {\n            for (Map.Entry<String, Object> entry : ((Map<String, Object>) value).entrySet()) {\n                if (\"NaN\".equals(entry.getValue())) {\n                    continue;\n                }\n                // 替换分位中的.\n                totalCostMap.put(entry.getKey().replace(\".\", \"_\"), entry.getValue());\n            }\n        }\n\n        return totalCostMap;\n    }\n\n    /**\n     * 获取慢查语句dslTemplateMd5和次数\n     *\n     * @param projectId\n     * @param date\n     * @return\n     */\n    public Map<String, Long> querySlowDslByProjectIdAndDate(Long projectId, String date) {\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_SLOW_DSL_BY_PROJECT_ID, projectId);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, typeName, dsl);\n        if (esAggrMap == null) {\n            return null;\n        }\n\n        Map<String, Long> slowDslMap = Maps.newHashMap();\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"slowDsl\");\n        if (esAggr == null) {\n            return null;\n        }\n\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n                slowDslMap.put(esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString(),\n                    Long.valueOf(esBucket.getUnusedMap().get(ESConstant.AGG_DOC_COUNT).toString()));\n            }\n        }\n\n        return slowDslMap;\n    }\n\n    /**\n     * 根据projectId和dsl查询模板MD5获取具体慢查语句\n     *\n     * @param date\n     * @param projectId\n     * @param dslTemplateMd5\n     * @return\n     */\n    public Tuple<Long, GatewayJoinPO> querySlowDslCountAndDetailByByProjectIdAndDslTemplate(String date,\n                                                                                            Integer projectId,\n                                                                                            String dslTemplateMd5,\n                                                                                            Long slowDslThreshold) {\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_SLOW_DSL_BY_KEY, projectId, slowDslThreshold,\n            dslTemplateMd5);\n\n        return gatewayClient.performRequestAndGetTotalCount(realIndexName, typeName, dsl, GatewayJoinPO.class);\n    }\n\n    /**\n     * 根据projectId和查询模板获取某一天查询最大值\n     *\n     * @param projectId\n     * @param dslTemplateMd5\n     * @return\n     */\n    @Nullable\n    public Tuple<Long, Long> queryMaxSearchQpsByProjectIdAndDslTemplate(String date, Integer projectId,\n                                                                        String dslTemplateMd5) {\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_JOIN_MAX_QPS_BY_KEY, projectId,\n            dslTemplateMd5);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, typeName, dsl);\n        if (esAggrMap == null) {\n            return null;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"searchCountPerSecond\");\n        if (esAggr == null) {\n            return null;\n        }\n\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n\n                return new Tuple<>((Long) esBucket.getUnusedMap().get(ESConstant.AGG_KEY),\n                    Long.valueOf(esBucket.getUnusedMap().get(ESConstant.AGG_DOC_COUNT).toString()));\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * 获取某个projectId某一天的查询错误数和错误信息\n     *\n     * @param projectId\n     * @param date\n     * @return\n     */\n    public Tuple<Long, List<Tuple<String, Long>>> getErrorSearchCountAndErrorDetailByProjectIdDate(Integer projectId,\n                                                                                                   String date) {\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_EXCEPTION_NAME_BY_PROJECT_ID, projectId);\n\n        ESQueryResponse esQueryResponse = gatewayClient.performRequest(realIndexName, typeName, dsl);\n        if (esQueryResponse == null || esQueryResponse.getHits() == null) {\n            return null;\n        }\n        List<Tuple<String, Long>> tupleList = Lists.newLinkedList();\n\n        long errSearchCnt = Long\n            .parseLong(esQueryResponse.getHits().getUnusedMap().getOrDefault(ESConstant.HITS_TOTAL, \"0\").toString());\n\n        if (esQueryResponse.getAggs() == null) {\n            return new Tuple<>(errSearchCnt, tupleList);\n        }\n\n        ESAggr esAggr = esQueryResponse.getAggs().getEsAggrMap().get(\"groupByError\");\n        if (esAggr == null) {\n            return new Tuple<>(errSearchCnt, tupleList);\n        }\n\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n\n                tupleList.add(new Tuple<>(esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString(),\n                    Long.valueOf(esBucket.getUnusedMap().get(ESConstant.AGG_DOC_COUNT).toString())));\n            }\n        }\n\n        return new Tuple<>(errSearchCnt, tupleList);\n    }\n\n    /**\n     * 获取到错误查询语句模板，根据错误名称\n     *\n     * @param date\n     * @param projectId\n     * @param exceptionName\n     * @return\n     */\n    public Map<String, Long> queryErrorDslByProjectIdExceptionAndDate(String date, Integer projectId,\n                                                                      String exceptionName) {\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_MD5_BY_EXCEPTION_NAME, projectId,\n            exceptionName);\n\n        Map<String, Long> errorDslMap = Maps.newHashMap();\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, typeName, dsl);\n        if (esAggrMap == null) {\n            return errorDslMap;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"top_dsltemplate\");\n        if (esAggr == null) {\n            return errorDslMap;\n        }\n\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n\n                errorDslMap.put(esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString(),\n                    Long.valueOf(esBucket.getUnusedMap().get(ESConstant.AGG_DOC_COUNT).toString()));\n            }\n        }\n\n        return errorDslMap;\n    }\n\n    /**\n     * 根据projectId，dslTemplateMd5获取异常查询具体信息\n     *\n     * @param date\n     * @param projectId\n     * @param dslTemplateMd5\n     * @param exceptionName\n     * @return\n     */\n    public GatewayJoinPO queryErrorDslDetailByProjectIdTemplateAndDate(String date, Integer projectId,\n                                                                       String dslTemplateMd5, String exceptionName) {\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_EXCEPTION_BY_MD5, projectId, dslTemplateMd5,\n            exceptionName);\n\n        return gatewayClient.performRequestAndTakeFirst(realIndexName, typeName, dsl, GatewayJoinPO.class);\n    }\n\n    /**\n     * 获取某个projectId某一天的查询gateway 分布情况\n     *\n     * @param projectId\n     * @param date\n     * @return\n     */\n    public String getAccessGatewayInfoByProjectIdDate(Integer projectId, String date) {\n        String realIndexName = getIndex(date);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_ACCESS_GATEWAY_INFO_BY_PROJECT_ID,\n            projectId);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, typeName, dsl);\n        if (esAggrMap == null) {\n            return null;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"groupByGateway\");\n        if (esAggr == null) {\n            return null;\n        }\n\n        if (CollectionUtils.isEmpty(esAggr.getBucketList())) {\n            return \"\";\n        }\n\n        List<Map<String, Object>> list = Lists.newLinkedList();\n        for (ESBucket esBucket : esAggr.getBucketList()) {\n            list.add(esBucket.getUnusedMap());\n        }\n        return JSON.toJSONString(list);\n    }\n\n    /**\n     *  根据index获得对应的templateMD5\n     *\n     * @param realIndexName\n     * @return\n     */\n    public Set<String> getDslByIndexAndTemplateMD5(String realIndexName, String templateMD5, int count) {\n\n        String queryDsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_BY_MD5_INDICES, count,\n            realIndexName, templateMD5);\n\n        Set<String> dslSet = new HashSet<>();\n\n        List<JSONObject> list = gatewayClient.performRequest(realIndexName + \"*\", typeName, queryDsl, JSONObject.class);\n\n        if (list != null) {\n            for (JSONObject jsonObject : list) {\n                dslSet.add(jsonObject.getString(\"dsl\"));\n            }\n        }\n\n        return dslSet;\n    }\n\n    /**\n     * 获得start和end这个时间段内，有查询请求的projectId和对应的templateMD5\n     */\n    public Map<Integer/*projectId*/, Set<String/*templateMD5*/>> getIds(long start, long end,\n                                                                        ExceptionDslRequest request) {\n        String subDsl = \"\";\n        if (request.getFilterDsl() != null) {\n            subDsl = \",\" + request.getFilterDsl().toJSONString();\n        }\n\n        Long minCheckQps = request.getMinCheckQps();\n        if (minCheckQps == null) {\n            minCheckQps = 1L;\n        }\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_PROJECT_ID_MD5, start, end, subDsl,\n            minCheckQps);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(getIndexByTimeRange(start, end), null, dsl);\n        if (esAggrMap == null) {\n            return null;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"result\");\n        if (esAggr == null) {\n            return null;\n        }\n\n        final Map<Integer, Set<String>> ret = Maps.newHashMap();\n        handleBucketListInGetIds(esAggr, ret);\n\n        return ret;\n    }\n\n    public Map<String/*md5*/, Map<Long/*timeStamp*/, Long/*qps*/>> getInfoByIds(long start, long end, Integer projectId,\n                                                                                ExceptionDslRequest request) {\n        String subDsl = \"\";\n        if (request.getFilterDsl() != null) {\n            subDsl = \",\" + request.getFilterDsl().toJSONString();\n        }\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_MD5_BY_TIMESTAMP, start, end, projectId,\n            subDsl, request.getInterval(), request.getMinQps());\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(getIndexByTimeRange(start, end), null, dsl);\n        if (esAggrMap == null) {\n            return null;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"template\");\n        if (esAggr == null) {\n            return null;\n        }\n\n        final Map<String, Map<Long, Long>> ret = Maps.newHashMap();\n\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            handleBucketListInGetInfoByIds(ret, esBucketList);\n        }\n\n        return ret;\n    }\n\n    public String matchIndices(Integer projectId, String templateMd5, long start, long end, Set<String> needIndexes) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.MATCH_GATEWAY_INDICES, start, end, projectId,\n            templateMd5);\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(getIndexByTimeRange(start, end), null, dsl);\n\n        if (esAggrMap == null) {\n            return null;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(INDICES);\n        if (esAggr == null) {\n            return null;\n        }\n\n        AtomicReference<String> matchIndex = new AtomicReference<>(null);\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        handleBucketList(needIndexes, matchIndex, esBucketList);\n\n        return matchIndex.get();\n    }\n\n    public Map<String, Long> getIndicesForAggDsl(String date) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_INDICES_FOR_AGGS);\n        String realIndexName = getIndex(date);\n\n        Map<String, Long> ret = Maps.newHashMap();\n\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, null, dsl);\n\n        if (esAggrMap == null) {\n            return ret;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"aggName\");\n        if (esAggr == null) {\n            return ret;\n        }\n\n        for (ESBucket bucket : esAggr.getBucketList()) {\n            String keys = String.valueOf(bucket.getUnusedMap().get(\"key\"));\n            Long count = Long.valueOf(bucket.getUnusedMap().get(DOC_COUNT) + \"\");\n\n            for (String key : keys.split(\",\")) {\n                ret.putIfAbsent(key, 0L);\n                ret.put(key, ret.get(key) + count);\n            }\n        }\n\n        return ret;\n    }\n\n    public Map<String, Long> getIndexForNormalDsl(long start, long end, String date) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_INDEX_FOR_NORMALS, start, end);\n        String realIndexName = getIndex(date);\n\n        Map<String, Long> ret = Maps.newHashMap();\n        ESAggrMap esAggrMap = gatewayClient.performAggRequest(realIndexName, null, dsl);\n\n        if (esAggrMap == null) {\n            return ret;\n        }\n\n        ESAggr esAggr = esAggrMap.getEsAggrMap().get(\"aggName\");\n        if (esAggr == null) {\n            return ret;\n        }\n\n        for (ESBucket bucket : esAggr.getBucketList()) {\n            String keys = String.valueOf(bucket.getUnusedMap().get(\"key\"));\n            Long count = Long.valueOf(bucket.getUnusedMap().get(DOC_COUNT) + \"\");\n\n            JSONObject keyObj = JSON.parseObject(keys);\n            for (String key : keyObj.keySet()) {\n                ret.putIfAbsent(key, 0L);\n                ret.put(key, ret.get(key) + count);\n            }\n        }\n\n        return ret;\n    }\n\n    /**\n     * 获取索引名称\n     *\n     * @param date\n     * @return\n     */\n    public String getIndex(String date) {\n        return String.format(DOUBLE_STRING_WITH_UNDER_LINE, getTemplateName(), date);\n    }\n\n    public String getTemplateName() {\n        return indexName;\n    }\n\n    private String buildGatewayJoinSlowQueryCriteriaDsl(Integer projectId, GatewayJoinQueryDTO queryDTO) {\n        return \"[\" + buildGatewayJoinSlowQueryCriteriaCell(projectId, queryDTO) + \"]\";\n    }\n\n    private String buildGatewayJoinSlowQueryCriteriaCell(Integer projectId, GatewayJoinQueryDTO queryDTO) {\n        List<String> cellList = Lists.newArrayList();\n        // 最近时间范围条件\n        cellList\n            .add(DSLSearchUtils.getTermCellForRangeSearch(queryDTO.getStartTime(), queryDTO.getEndTime(), \"timeStamp\"));\n        // projectId 条件\n        cellList.add(buildProjectIdCriteriaCell(projectId,queryDTO.getProjectId()));\n        // phyCLusterName 条件\n        cellList.add(DSLSearchUtils.getTermCellForPrefixSearch(queryDTO.getClusterName(), \"clusterName\"));\n        // queryIndex 条件\n        cellList.add(DSLSearchUtils.getTermCellForPrefixSearch(queryDTO.getQueryIndex(), \"indices\"));\n        // totalCost>=1000即为慢查询\n        cellList.add(DSLSearchUtils.getTermCellForRangeSearch(queryDTO.getTotalCost(), null, \"totalCost\"));\n        // 只获取ariusType为type（正常的）的文档\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(\"type\", \"ariusType\"));\n        return ListUtils.strList2String(cellList);\n    }\n\n    private String buildGatewayJoinErrorQueryCriteriaDsl(Integer projectId, GatewayJoinQueryDTO queryDTO) {\n        return \"[\" + buildGatewayJoinErrorQueryCriteriaCell(projectId, queryDTO) + \"]\";\n    }\n\n    private String buildGatewayJoinErrorQueryCriteriaCell(Integer projectId, GatewayJoinQueryDTO queryDTO) {\n        List<String> cellList = Lists.newArrayList();\n        // 最近时间范围条件\n        cellList\n            .add(DSLSearchUtils.getTermCellForRangeSearch(queryDTO.getStartTime(), queryDTO.getEndTime(), \"timeStamp\"));\n        // projectId 条件\n        cellList.add(buildProjectIdCriteriaCell(projectId,queryDTO.getProjectId()));\n        // phyCLusterName 条件\n        cellList.add(DSLSearchUtils.getTermCellForPrefixSearch(queryDTO.getClusterName(), \"clusterName\"));\n        // queryIndex 条件\n        cellList.add(DSLSearchUtils.getTermCellForPrefixSearch(queryDTO.getQueryIndex(), \"indices\"));\n        // 只获取 ariusType 为error 即为异常\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(\"error\", \"ariusType\"));\n        return ListUtils.strList2String(cellList);\n    }\n\n    private String buildProjectIdCriteriaCell(Integer currentProjectId, Integer queryProjectId) {\n        // 仅超级项目可用queryProjectId查询\n        if (AuthConstant.SUPER_PROJECT_ID.equals(currentProjectId)) {\n            return DSLSearchUtils.getTermCellForExactSearch(queryProjectId, \"projectId\");\n        }\n        return DSLSearchUtils.getTermCellForExactSearch(currentProjectId, \"projectId\");\n    }\n\n    public String getOneDSLByProjectIdAndIndexName(Integer projectId, String index) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_ONE_DSL_BY_PROJECT_ID_AND_INDEX_NAME,\n                index,projectId);\n        String realName =  IndexNameUtils.genCurrentDailyIndexName(indexName);\n        return gatewayClient.performRequest(realName, typeName, dsl,\n                res -> Optional.ofNullable(res).map(ESQueryResponse::getHits).map(ESHits::getHits)\n                        .filter(CollectionUtils::isNotEmpty).map(hits -> hits.get(0)).map(ESHit::getSource)\n                        .map(String::valueOf).orElse(null), 3);\n    }\n\n    /**************************************************** private methods ****************************************************/\n    private String getIndexByTimeRange(long start, long end) {\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd\");\n        StringBuilder sb = new StringBuilder();\n\n        String index = getTemplateName();\n\n        start = start / ONE_DAY * ONE_DAY;\n        end = end / ONE_DAY * ONE_DAY;\n\n        long time = start;\n        while (time <= end) {\n            String timeStr = index.trim() + \"_\" + sdf.format(time);\n            sb.append(timeStr).append(\",\");\n\n            time += ONE_DAY;\n        }\n\n        if (sb.length() > 0) {\n            return sb.substring(0, sb.length() - 1);\n        } else {\n            return sb.toString();\n        }\n    }\n\n    /**\n     * 获取索引表达式\n     *\n     * @return\n     */\n    private String getTemplateExpression() {\n        return String.format(\"%s*\", getTemplateName());\n    }\n\n    private void handleBucketListInGetTemplateMD5ByRealIndexName(Map<String, Set<String>> dslMap,\n                                                                 List<ESBucket> esBucketList) {\n        String md5;\n        ESAggr subEsAggr;\n\n        for (ESBucket esBucket : esBucketList) {\n            if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                continue;\n            }\n            md5 = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n\n            subEsAggr = esBucket.getAggrMap().get(\"samples\");\n            if (subEsAggr == null) {\n                continue;\n            }\n\n            Object obj = subEsAggr.getUnusedMap().get(\"hits\");\n            handleHitsByHandleBucketListInGetTemplateMD5ByRealIndexName(dslMap, md5, obj);\n        }\n    }\n\n    private void handleHitsByHandleBucketListInGetTemplateMD5ByRealIndexName(Map<String, Set<String>> dslMap,\n                                                                             String md5, Object obj) {\n        String dslSample;\n\n        if (obj instanceof JSONObject) {\n            JSONObject jsonObject = (JSONObject) obj;\n            JSONArray jsonArray = jsonObject.getJSONArray(\"hits\");\n            if (jsonArray != null && !jsonArray.isEmpty()) {\n                JSONObject hitJsonObj = jsonArray.getJSONObject(0);\n                JSONObject sourceJsonObj = hitJsonObj.getJSONObject(\"_source\");\n                if (sourceJsonObj != null) {\n                    dslSample = sourceJsonObj.getString(\"dsl\");\n                    dslMap.computeIfAbsent(md5, k -> Sets.newHashSet()).add(dslSample);\n                }\n            }\n        }\n    }\n\n    private void handleBucketList(Set<String> needIndexes, AtomicReference<String> matchIndex,\n                                  List<ESBucket> esBucketList) {\n        String indices;\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n                indices = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n\n                for (String i : needIndexes) {\n                    if (indices.startsWith(i)) {\n                        matchIndex.set(indices);\n                    }\n                }\n            }\n        }\n    }\n\n    private void handleBucketListInGetInfoByIds(Map<String, Map<Long, Long>> ret, List<ESBucket> esBucketList) {\n        ESAggr subEsAggr;\n        String md5;\n        List<ESBucket> subEsBucketList;\n        for (ESBucket esBucket : esBucketList) {\n            if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                continue;\n            }\n            md5 = esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n\n            subEsAggr = esBucket.getAggrMap().get(\"minute_hist\");\n            if (subEsAggr == null) {\n                continue;\n            }\n\n            subEsBucketList = subEsAggr.getBucketList();\n            if (CollectionUtils.isEmpty(subEsBucketList)) {\n                continue;\n            }\n\n            for (ESBucket subEsBucket : subEsBucketList) {\n                if (subEsBucket.getUnusedMap() == null || subEsBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n                Long timeStamp = Long.valueOf(subEsBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString());\n                Long count = Long.valueOf(subEsBucket.getUnusedMap().get(ESConstant.AGG_DOC_COUNT).toString());\n\n                ret.computeIfAbsent(md5, k -> Maps.newHashMap()).put(timeStamp, count);\n            }\n        }\n    }\n\n    private void handleBucketListInGetRtCostByProjectId(List<Double> rtCostList, ESAggr queryByTimeStamp) {\n        queryByTimeStamp.getBucketList().stream().forEach(esBucket -> {\n            try {\n                List<ESBucket> queryByProjectIdBucket = esBucket.getAggrMap().get(\"queryByProjectId\").getBucketList();\n                if (CollectionUtils.isNotEmpty(queryByProjectIdBucket)) {\n                    for (ESBucket bucket : queryByProjectIdBucket) {\n                        JSONObject valueObj = (JSONObject) bucket.getAggrMap().get(\"1\").getUnusedMap().get(\"values\");\n                        Double value = valueObj.getDouble(\"99.0\");\n                        if (null == value) {\n                            continue;\n                        }\n                        rtCostList.add(value);\n                    }\n                }\n            } catch (Exception e) {\n                LOGGER.error(\"class=GatewayJoinEsDao||method=handleBucketListInGetRtCostByProjectId||errMsg={}\", e);\n            }\n        });\n    }\n\n    private void handleBucketListInGetIds(ESAggr esAggr, Map<Integer, Set<String>> ret) {\n        List<ESBucket> subEsBucketList;\n        ESAggr subEsAggr;\n        Integer projectId;\n\n        List<ESBucket> esBucketList = esAggr.getBucketList();\n        if (esBucketList != null) {\n            for (ESBucket esBucket : esBucketList) {\n                if (esBucket.getUnusedMap() == null || esBucket.getUnusedMap().isEmpty()) {\n                    continue;\n                }\n                projectId = Integer.valueOf(esBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString());\n\n                subEsAggr = esBucket.getAggrMap().get(\"template\");\n                if (subEsAggr == null) {\n                    continue;\n                }\n\n                subEsBucketList = subEsAggr.getBucketList();\n                handleSubEsBucketList(ret, subEsBucketList, projectId);\n\n            }\n        }\n    }\n\n    private void handleSubEsBucketList(Map<Integer, Set<String>> ret, List<ESBucket> subEsBucketList,\n                                       Integer projectId) {\n        String md5;\n        if (CollectionUtils.isEmpty(subEsBucketList)) {\n            return;\n        }\n\n        for (ESBucket subEsBucket : subEsBucketList) {\n            if (subEsBucket.getUnusedMap() == null || subEsBucket.getUnusedMap().isEmpty()) {\n                continue;\n            }\n            md5 = subEsBucket.getUnusedMap().get(ESConstant.AGG_KEY).toString();\n            ret.computeIfAbsent(projectId, k -> Sets.newHashSet()).add(md5);\n        }\n    }\n\n    public Tuple<Long, List<GatewayJoinPO>> getGatewayJoinSlowQueryPage(Integer projectId, GatewayJoinQueryDTO queryDTO) throws ESOperateException {\n        String queryCriteriaDsl = buildGatewayJoinSlowQueryCriteriaDsl(projectId, queryDTO);\n        String realName = IndexNameUtils.genDailyIndexName(indexName, queryDTO.getStartTime(), queryDTO.getEndTime());\n        // 排序条件，默认根据使用时间排序 desc\n        String sortTerm = \"timeStamp\";\n        String sortOrder = \"desc\";\n        if (!StringUtils.isEmpty(queryDTO.getSortTerm())) {\n            // 根据用户自定义条件排序\n            sortOrder = BooleanUtils.isTrue(queryDTO.getOrderByDesc()) ? \"desc\" : \"asc\";\n            sortTerm = queryDTO.getSortTerm();\n        }\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_SLOW_BY_CONDITION,\n                (queryDTO.getPage() - 1) * queryDTO.getSize(), queryDTO.getSize(), queryCriteriaDsl, sortTerm, sortOrder);\n\n        return ESOpTimeoutRetry.esRetryExecute(\"getGatewayJoinSlowQueryPage\",3,\n                () -> gatewayClient.performRequestListAndGetTotalCount(null, realName, typeName, dsl, GatewayJoinPO.class),\n                Objects::isNull);\n    }\n\n    public Tuple<Long, List<GatewayJoinPO>> getGatewayJoinErrorPage(Integer projectId, GatewayJoinQueryDTO queryDTO) throws ESOperateException {\n        String queryCriteriaDsl = buildGatewayJoinErrorQueryCriteriaDsl(projectId, queryDTO);\n        String realName = IndexNameUtils.genDailyIndexName(indexName, queryDTO.getStartTime(), queryDTO.getEndTime());\n        // 排序条件，默认根据使用时间排序 desc\n        String sortTerm = \"timeStamp\";\n        String sortOrder = \"desc\";\n        if (!StringUtils.isEmpty(queryDTO.getSortTerm())) {\n            // 根据用户自定义条件排序\n            sortOrder = BooleanUtils.isTrue(queryDTO.getOrderByDesc()) ? \"desc\" : \"asc\";\n            sortTerm = queryDTO.getSortTerm();\n        }\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_ERROR_BY_CONDITION,\n                (queryDTO.getPage() - 1) * queryDTO.getSize(), queryDTO.getSize(), queryCriteriaDsl, sortTerm, sortOrder);\n\n        return ESOpTimeoutRetry.esRetryExecute(\"getGatewayJoinErrorPage\",3,\n                () -> gatewayClient.performRequestListAndGetTotalCount(null, realName, typeName, dsl, GatewayJoinPO.class),\n                Objects::isNull);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/gateway/GatewayNodeMetricsDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.gateway;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\nimport javax.annotation.PostConstruct;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContentCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.GatewayMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.MetricsConstant;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.metric.BaseTopNMetricsDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.google.common.collect.Lists;\n\nimport lombok.NoArgsConstructor;\n\n@Component\n@NoArgsConstructor\npublic class GatewayNodeMetricsDAO extends BaseTopNMetricsDAO {\n    private static final String TYPE = \"type\";\n    private static final String AGG_KEY_TIMESTAMP = \"group_by_timeStamp\";\n    private static final String AGG_KEY_FIELD     = \"group_by_field\";\n    private static final String KEY               = \"key\";\n    /**\n     * 成功率/失败率 百分比 最小值\n     */\n    private static final double ZERO = 0.0;\n    /**\n     * 成功率/失败率 百分百 总值\n     */\n    private static final double SUM_RATE              = 100.0;\n    private static final String NOW_2M                = \"now-2m\";\n    private static final String NOW_1M                = \"now-1m\";\n    private static final String EMPTY_STR             = \"\";\n    private static final String GATEWAY_NODE          = \"gatewayNode\";\n    private static final String CLIENT_NODE           = \"clientNode\";\n    private static final String CLUSTER_NAME          = \"clusterName\";\n    private static final String QUERY_REQUEST         = \"queryRequest\";\n    private static final String EXISTS                = \"exists\";\n    private static final String TIMESTAMP             = \"timeStamp\";\n    private static final String TERM                  = \"term\";\n    private static final String TERMS                 = \"terms\";\n    private static final String FIELD                 = \"field\";\n    private static final String DSL_LEN               = \"dslLen\";\n    private static final String DSL_LEN_AVG           = \"dsl_len\";\n    private static final String AVG                   = \"avg\";\n    private static final String PROJECT_ID            = \"projectId\";\n    private static final String GATEWAY_SUCCESS_COUNT = \"gatewaySuccessCount\";\n    private static final String DOC_COUNT             = \"doc_count\";\n    private static final int    AGG_TERMS_SIZE        = 1000;\n    \n    @PostConstruct\n    public void init() {\n        super.indexName = dataCentreUtil.getAriusStatsGatewayInfo();\n    }\n\n    /**\n     * 获取某 clientNode 读分布\n     */\n    public VariousLineChartMetrics getClientNodeAggFieldByRange(GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                                Long startTime, Long endTime, Integer projectId,\n                                                                String gatewayNodeIp, String clientNodeIp) {\n        List<String> cellList = buildBaseTermCondition(gatewayNodeIp, startTime, endTime, projectId);\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(clientNodeIp, \"clientNode\"));\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(true, \"queryRequest\"));\n        String condition = \"[\" + ListUtils.strList2String(cellList) + \"]\";\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLIENT_NODE_FIELD_BY_IP, condition, interval,\n            startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldByIpAggMetrics(response, clientNodeIp, gatewayMetricsTypeEnum,\n                interval),\n            3);\n    }\n\n    /**\n     * 获取 topN clientNode 读分布\n     */\n    public VariousLineChartMetrics getClientNodeAggFieldByRange(GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                                Long startTime, Long endTime, Integer projectId,\n                                                                Integer topNu, String gatewayNodeIp) {\n        List<String> cellList = buildBaseTermCondition(gatewayNodeIp, startTime, endTime, projectId);\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(true, \"queryRequest\"));\n        String condition = \"[\" + ListUtils.strList2String(cellList) + \"]\";\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLIENT_NODE_FIELD, condition, interval,\n            startTime, endTime);\n        VariousLineChartMetrics variousLineChartMetrics = gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldAggMetrics(response, gatewayMetricsTypeEnum, interval), 3);\n        //根据第一个时间点的值进行倒排，取topNu\n        List<MetricsContent> sortedList = variousLineChartMetrics.getMetricsContents().stream()\n            .sorted(Comparator.comparing(x -> x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder()))\n            .limit(topNu).collect(Collectors.toList());\n        variousLineChartMetrics.setMetricsContents(sortedList);\n        return variousLineChartMetrics;\n    }\n\n    /**\n     * 获取 topN clientNode 分布\n     */\n    public VariousLineChartMetrics getClientNodeTopN(Long startTime, Long endTime, Integer projectId, Integer topNu,\n                                                     String gatewayNodeIp,\n                                                     GatewayMetricsTypeEnum gatewayMetricsTypeEnum) {\n        List<String> cellList = buildBaseTermCondition(gatewayNodeIp, startTime, endTime, projectId);\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(false, \"queryRequest\"));\n        String condition = \"[\" + ListUtils.strList2String(cellList) + \"]\";\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLIENT_NODE_WRITE, condition, interval,\n            startTime, endTime);\n        VariousLineChartMetrics variousLineChartMetrics = gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldAggMetrics(response, gatewayMetricsTypeEnum, interval), 3);\n        //根据第一个时间点的值进行倒排，取topNu\n        List<MetricsContent> sortedList = variousLineChartMetrics.getMetricsContents().stream()\n            .sorted(Comparator.comparing(x -> x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder()))\n            .limit(topNu).collect(Collectors.toList());\n        variousLineChartMetrics.setMetricsContents(sortedList);\n        return variousLineChartMetrics;\n    }\n\n    public VariousLineChartMetrics getClientNodeWrite(Long startTime, Long endTime, Integer projectId, Integer topNu,\n                                                      String gatewayNodeIp) {\n        return getClientNodeTopN(startTime, endTime, projectId, topNu, gatewayNodeIp,\n            GatewayMetricsTypeEnum.WRITE_CLIENT_NODE);\n    }\n\n    public VariousLineChartMetrics getClientNodeDSLLENByIp(Long startTime, Long endTime, Integer projectId,\n                                                           Integer topNu, String gatewayNodeIp) {\n        return getClientNodeTopN(startTime, endTime, projectId, topNu, gatewayNodeIp,\n            GatewayMetricsTypeEnum.DSLLEN_CLIENT_NODE);\n    }\n\n    /**\n     * 获取某 clientNode 分布\n     */\n    public VariousLineChartMetrics getSingleClientNodeWriteByIp(Long startTime, Long endTime, Integer projectId,\n                                                                String gatewayNodeIp, String clientNodeIp,\n                                                                GatewayMetricsTypeEnum gatewayMetricsTypeEnum) {\n        List<String> cellList = buildBaseTermCondition(gatewayNodeIp, startTime, endTime, projectId);\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(clientNodeIp, \"clientNode\"));\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(false, \"queryRequest\"));\n        String condition = \"[\" + ListUtils.strList2String(cellList) + \"]\";\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLIENT_NODE_WRITE_BY_IP, condition, interval,\n            startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldByIpAggMetrics(response, clientNodeIp, gatewayMetricsTypeEnum,\n                interval),\n            3);\n    }\n\n    public VariousLineChartMetrics getClientNodeWriteByIp(Long startTime, Long endTime, Integer projectId,\n                                                          String gatewayNodeIp, String clientNodeIp) {\n        return getSingleClientNodeWriteByIp(startTime, endTime, projectId, gatewayNodeIp, clientNodeIp,\n            GatewayMetricsTypeEnum.WRITE_CLIENT_NODE);\n    }\n\n    public VariousLineChartMetrics getClientNodeDSLLENByIp(Long startTime, Long endTime, Integer projectId,\n                                                           String gatewayNodeIp, String clientNodeIp) {\n        return getSingleClientNodeWriteByIp(startTime, endTime, projectId, gatewayNodeIp, clientNodeIp,\n            GatewayMetricsTypeEnum.DSLLEN_CLIENT_NODE);\n    }\n\n    /**\n     * 获取 topN gatewayNode 读分布\n     */\n    public VariousLineChartMetrics getAggFieldByRange(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                                      Long endTime, Integer projectId, Integer topNu) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_NODE_FIELD, startTime, endTime,\n            projectId, interval, startTime, endTime);\n        VariousLineChartMetrics variousLineChartMetrics = gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldAggMetrics(response, gatewayMetricsTypeEnum, interval), 3);\n        //根据第一个时间点的值进行倒排，取topNu\n        List<MetricsContent> sortedList = variousLineChartMetrics.getMetricsContents().stream()\n            .sorted(Comparator.comparing(x -> x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder()))\n            .limit(topNu).collect(Collectors.toList());\n        variousLineChartMetrics.setMetricsContents(sortedList);\n        return variousLineChartMetrics;\n    }\n\n    /**\n     * 获取某 gatewayNode 读分布\n     */\n    public VariousLineChartMetrics getAggFieldByRange(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                                      Long endTime, Integer projectId, String nodeIp) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_NODE_FIELD_BY_IP, nodeIp, startTime,\n            endTime, projectId, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldByIpAggMetrics(response, nodeIp, gatewayMetricsTypeEnum, interval),\n            3);\n    }\n\n    /**\n     * 获取 topN gatewayNode 分布\n     */\n    public VariousLineChartMetrics getWriteGatewayNodeTopN(Long startTime, Long endTime, Integer projectId,\n                                                           Integer topNu,\n                                                           GatewayMetricsTypeEnum gatewayMetricsTypeEnum) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_NODE_WRITE, startTime, endTime,\n            projectId, interval, startTime, endTime);\n        VariousLineChartMetrics variousLineChartMetrics = gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldAggMetrics(response, gatewayMetricsTypeEnum, interval), 3);\n        //根据第一个时间点的值进行倒排，取topNu\n        List<MetricsContent> sortedList = variousLineChartMetrics.getMetricsContents().stream()\n            .sorted(Comparator.comparing(x -> x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder()))\n            .limit(topNu).collect(Collectors.toList());\n        variousLineChartMetrics.setMetricsContents(sortedList);\n        return variousLineChartMetrics;\n    }\n\n    /**\n     * 获取 topN gatewayNode 写分布\n     */\n    public VariousLineChartMetrics getWriteGatewayNode(Long startTime, Long endTime, Integer projectId, Integer topNu) {\n        return getWriteGatewayNodeTopN(startTime, endTime, projectId, topNu, GatewayMetricsTypeEnum.WRITE_GATEWAY_NODE);\n    }\n\n    /**\n     * 获取某 gatewayNode 写入的数据量\n     */\n    public VariousLineChartMetrics getSingleGatewayNodeWriteByIp(Long startTime, Long endTime, Integer projectId,\n                                                                 String nodeIp,\n                                                                 GatewayMetricsTypeEnum gatewayMetricsTypeEnum) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_NODE_WRITE_BY_IP, nodeIp, startTime,\n            endTime, projectId, interval, startTime, endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchFieldByIpAggMetrics(response, nodeIp, gatewayMetricsTypeEnum, interval),\n            3);\n    }\n\n    /**\n     * 获取某 gatewayNode 写分布\n     */\n    public VariousLineChartMetrics getWriteGatewayNodeByIp(Long startTime, Long endTime, Integer projectId,\n                                                           String nodeIp) {\n        return getSingleGatewayNodeWriteByIp(startTime, endTime, projectId, nodeIp,\n            GatewayMetricsTypeEnum.WRITE_GATEWAY_NODE);\n    }\n\n    /**\n     * 获取 topN gatewayNode dsl 长度\n     */\n    public VariousLineChartMetrics getWriteGatewayDSLLen(Long startTime, Long endTime, Integer projectId,\n                                                         Integer topNu) {\n        return getWriteGatewayNodeTopN(startTime, endTime, projectId, topNu,\n            GatewayMetricsTypeEnum.DSLLEN_GATEWAY_NODE);\n    }\n\n    /**\n     * 获取某 gatewayNode dsl 长度\n     */\n    public VariousLineChartMetrics getWriteGatewayDSLLenByIp(Long startTime, Long endTime, Integer projectId,\n                                                             String nodeIp) {\n        return getSingleGatewayNodeWriteByIp(startTime, endTime, projectId, nodeIp,\n            GatewayMetricsTypeEnum.DSLLEN_GATEWAY_NODE);\n    }\n\n    /**\n     * 获取 gatewayNode 相关的 clientNode ip 信息\n     */\n    public List<Tuple<String, String>> getEsClientNodeIpListByGatewayNode(String gatewayNode, Long startTime, Long endTime,\n                                                                          Integer projectId) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        List<String> cellList = buildBaseTermCondition(gatewayNode, startTime, endTime, projectId);\n        String condition = \"[\" + ListUtils.strList2String(cellList) + \"]\";\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLIENT_NODE_BY_GATEWAY_NODE, condition);\n\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl, (ESQueryResponse response) -> {\n            List<Tuple<String, String>> list = Lists.newArrayList();\n            Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                .orElse(null);\n            if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_FIELD)) {\n                for (ESBucket esBucket : esAggrMap.get(AGG_KEY_FIELD).getBucketList()) {\n                    JSONObject clusterNameClientNode = JSON.parseObject(esBucket.getAggrMap().get(KEY).toString());\n                    list.add(new Tuple<>(clusterNameClientNode.getString(CLUSTER_NAME),\n                        clusterNameClientNode.getString(CLIENT_NODE)));\n                }\n            }\n            return list;\n        }, 3);\n    }\n\n    public List<Tuple<String, String>> getEsClientNodeIpListByClientNodes(List<String> clientNodes, Long startTime, Long endTime,\n                                                                          Integer projectId) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        List<String> cellList = buildBaseTermCondition(clientNodes, startTime, endTime, projectId);\n        String condition = \"[\" + ListUtils.strList2String(cellList) + \"]\";\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLIENT_NODE_BY_GATEWAY_NODE, condition);\n\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl, (ESQueryResponse response) -> {\n            List<Tuple<String, String>> list = Lists.newArrayList();\n            Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                    .orElse(null);\n            if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_FIELD)) {\n                for (ESBucket esBucket : esAggrMap.get(AGG_KEY_FIELD).getBucketList()) {\n                    JSONObject clusterNameClientNode = JSON.parseObject(esBucket.getAggrMap().get(KEY).toString());\n                    list.add(new Tuple<>(clusterNameClientNode.getString(CLUSTER_NAME),\n                            clusterNameClientNode.getString(CLIENT_NODE)));\n                }\n            }\n            return list;\n        }, 3);\n    }\n\n    /**\n     * 网关成功率和失败率\n     *\n     * @param cluster 集群\n     * @return {@code Tuple<Double, Double>} tuple.1:成功率；tuple.2:失败率\n     */\n    public Tuple<Double/*成功率*/, Double/*失败率*/> getGatewaySuccessRateAndFailureRate(String cluster) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, System.currentTimeMillis(),\n            System.currentTimeMillis());//网关总数\n        String gatewayCountDsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_COUNT, cluster, NOW_2M,\n            NOW_1M);\n        Tuple</*count总数*/Long, /*成功率总数*/Long> gatewayCountTotalAndGatewaySuccessCountTuple = gatewayClient\n            .performRequest(cluster, realIndexName, TYPE, gatewayCountDsl,\n                esQueryResponse -> Optional.ofNullable(esQueryResponse).map(response -> {\n                    Long totalCount = Long\n                        .valueOf(response.getHits().getUnusedMap().getOrDefault(ESConstant.HITS_TOTAL, \"0\").toString());\n                    Long gatewaySuccessCount = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                        .map(aggrMap -> aggrMap.get(GATEWAY_SUCCESS_COUNT)).map(ESAggr::getUnusedMap)\n                        .map(aggrMap -> aggrMap.get(DOC_COUNT)).map(String::valueOf).map(Long::valueOf).orElse(0L);\n                    return new Tuple<>(totalCount, gatewaySuccessCount);\n                }).orElse(new Tuple<>(0L, 0L)), 3);\n        // 网关成功数\n        double successRate = CommonUtils.divideDoubleAndFormatDouble(\n            gatewayCountTotalAndGatewaySuccessCountTuple.getV2().doubleValue(),\n            gatewayCountTotalAndGatewaySuccessCountTuple.getV1().doubleValue(), 2, 1);\n        double success = -1;\n        double failed = -1;\n        if (successRate > ZERO) {\n            success = successRate * 100;\n            failed = SUM_RATE - success;\n        }\n        return new Tuple<>(success, failed);\n    }\n\n    /**************************************** private methods ****************************************/\n    private List<String> buildBaseTermCondition(String gatewayNode, Long startTime, Long endTime, Integer projectId) {\n        List<String> cellList = Lists.newArrayList();\n        cellList.add(DSLSearchUtils.getTermCellForRangeSearch(startTime, endTime, \"timeStamp\"));\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(projectId, \"projectId\"));\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(gatewayNode, \"gatewayNode\"));\n        return cellList;\n    }\n\n    private List<String> buildBaseTermCondition(List<String> clientNodes, Long startTime, Long endTime,\n                                                Integer projectId) {\n        List<String> cellList = Lists.newArrayList();\n        cellList.add(DSLSearchUtils.getTermCellForRangeSearch(startTime, endTime, \"timeStamp\"));\n        cellList.add(DSLSearchUtils.getTermCellForExactSearch(projectId, \"projectId\"));\n        if (CollectionUtils.isNotEmpty(clientNodes)) {\n            cellList.add(DSLSearchUtils.getTermCellsForExactSearch(clientNodes, \"clientNode\"));\n        }\n        return cellList;\n    }\n\n    private Long getTotal(String cluster, String realIndexName, String dsl) {\n\n        return gatewayClient.performRequestAndGetTotalCount(cluster, realIndexName, TYPE, dsl, 3);\n\n    }\n\n    private VariousLineChartMetrics fetchFieldAggMetrics(ESQueryResponse response,\n                                                         GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                         String interval) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(gatewayMetricsTypeEnum.getType());\n        variousLineChartMetrics.setMetricsContents(Lists.newArrayList());\n        Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n            .orElse(null);\n        if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_FIELD)) {\n            handleESBucket(gatewayMetricsTypeEnum, interval, variousLineChartMetrics, esAggrMap);\n        }\n        return variousLineChartMetrics;\n    }\n\n    private void handleESBucket(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, String interval,\n                                VariousLineChartMetrics variousLineChartMetrics, Map<String, ESAggr> esAggrMap) {\n        for (ESBucket esBucket : esAggrMap.get(AGG_KEY_FIELD).getBucketList()) {\n            String nodeName = esBucket.getUnusedMap().get(KEY).toString();\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(nodeName);\n            metricsContent.setMetricsContentCells(Lists.newArrayList());\n            variousLineChartMetrics.getMetricsContents().add(metricsContent);\n            if (null != esBucket.getAggrMap() && null != esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP)) {\n                for (ESBucket bucket : esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).getBucketList()) {\n                    long timeStamp = Long.parseLong(bucket.getUnusedMap().get(KEY).toString());\n                    double value;\n                    String aggKey = gatewayMetricsTypeEnum.getAggKey();\n                    if (MetricsUtils.needConvertUnit(aggKey)) {\n                        value = MetricsUtils.getDoubleValuePerMin(interval,\n                            bucket.getUnusedMap().get(aggKey).toString());\n                    } else if (GatewayMetricsTypeEnum.DSL_LEN.getAggKey().equals(aggKey)) {\n                        value = MetricsUtils.getAggMapDoubleValue(bucket, aggKey);\n                    } else {\n                        value = Double.parseDouble(bucket.getUnusedMap().get(aggKey).toString());\n                    }\n                    metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                }\n            }\n        }\n    }\n\n    private VariousLineChartMetrics fetchFieldByIpAggMetrics(ESQueryResponse response, String nodeIp,\n                                                             GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                             String interval) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(gatewayMetricsTypeEnum.getType());\n\n        MetricsContent metricsContent = new MetricsContent();\n        metricsContent.setName(nodeIp);\n        metricsContent.setMetricsContentCells(Lists.newArrayList());\n\n        variousLineChartMetrics.setMetricsContents(Lists.newArrayList(metricsContent));\n\n        Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n            .orElse(null);\n        if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_TIMESTAMP)) {\n            for (ESBucket esBucket : esAggrMap.get(AGG_KEY_TIMESTAMP).getBucketList()) {\n                long timeStamp = Long.parseLong(esBucket.getUnusedMap().get(KEY).toString());\n                String aggKey = gatewayMetricsTypeEnum.getAggKey();\n                double value;\n                if (MetricsUtils.needConvertUnit(aggKey)) {\n                    value = MetricsUtils.getDoubleValuePerMin(interval, esBucket.getUnusedMap().get(aggKey).toString());\n                } else if (GatewayMetricsTypeEnum.DSLLEN_GATEWAY_NODE.getAggKey().equals(aggKey)) {\n                    value = MetricsUtils.getAggMapDoubleValue(esBucket, aggKey);\n                } else {\n                    value = Double.parseDouble(esBucket.getUnusedMap().get(aggKey).toString());\n                }\n                metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n            }\n        }\n        return variousLineChartMetrics;\n    }\n    \n    @Override\n    public List<VariousLineChartMetrics> fetchTopMetric(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                                        Long endTime, Integer topNu, Integer projectId, String value)\n            throws AdminOperateException {\n        return fetchTopMetric(gatewayMetricsTypeEnum, startTime, endTime, topNu, projectId, value, null);\n    }\n    \n    /**\n     * 对于\n     *\n     * @param gatewayMetricsTypeEnum 网关指标类型枚举\n     * @param startTime              开始时间\n     * @param endTime                结束时间\n     * @param topNu                  top n\n     * @param projectId                  projectId\n     * @param value                  单个指标值\n     * @param nodeIp                 节点ip {@linkplain  GatewayMetricsTypeEnum CLIENT_NODE} 需要设置该参数\n     * @return {@link List}<{@link VariousLineChartMetrics}>\n     * @see MetricsConstant#CLIENT_NODE\n     */\n    public List<VariousLineChartMetrics> fetchTopMetric(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                                        Long endTime, Integer topNu, Integer projectId, String value,\n                                                        String nodeIp) throws AdminOperateException {\n        //构建hasDataTime的查询片段\n        String queryDsl = buildExistField(gatewayMetricsTypeEnum, nodeIp);\n        if (Objects.isNull(queryDsl)) {\n            return Collections.emptyList();\n        }\n        //获取最终的dsl\n        String hasDataTimeDsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_HAS_METRIC_INFO_TIME_BY_FIELD,\n                startTime, endTime, queryDsl + buildTermByProjectId(projectId));\n        //根据不同的gatewayMetricsTypeEnum来进行query 片段构建\n        String queryDslByFiled =\n                buildTermsQueryRequestFieldByValue(Collections.emptyList(), gatewayMetricsTypeEnum, nodeIp) + buildTermByProjectId(projectId);\n        // 注意这里不用MetricsUtils.getIntervalForDashBoard\n        String interval = MetricsUtils.Interval.FIVE_MIN.getStr();\n        Object[] params;\n        switch (gatewayMetricsTypeEnum) {\n            case DSLLEN_GATEWAY_NODE:\n                //queryRequest false\n                // queryRequest false\n            case WRITE_GATEWAY_NODE:\n                params = new Object[] { queryDslByFiled, AGG_KEY_FIELD, GATEWAY_NODE, AGG_TERMS_SIZE, interval,\n                                        DSL_LEN_AVG, AVG, DSL_LEN };\n                break;\n            case QUERY_GATEWAY_NODE:\n                //queryRequest true\n                params = new Object[] { queryDslByFiled, AGG_KEY_FIELD, GATEWAY_NODE, AGG_TERMS_SIZE, interval };\n                break;\n            //queryRequest false\n            case WRITE_CLIENT_NODE:\n            case DSLLEN_CLIENT_NODE:\n                params = new Object[] { queryDslByFiled, AGG_KEY_FIELD, CLIENT_NODE, AGG_TERMS_SIZE, interval,\n                                        DSL_LEN_AVG, AVG, DSL_LEN };\n                break;\n            //query true\n            case QUERY_CLIENT_NODE:\n                params = new Object[] { queryDslByFiled, AGG_KEY_FIELD, CLIENT_NODE, AGG_TERMS_SIZE, interval };\n                break;\n            default:\n                return Collections.emptyList();\n        }\n        return super.performFetchTopMetric(gatewayMetricsTypeEnum, startTime, endTime,\n                response -> fetchFieldAggMetricsByList(response, gatewayMetricsTypeEnum, interval, topNu),\n                hasDataTimeDsl, value, params);\n    }\n    \n    @Override\n    public List<MetricsContent> getByRangeTopN(List<String> values, GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                               Long startTime, Long endTime, Integer projectId)\n            throws AdminOperateException {\n        return getByRangeTopN(values, gatewayMetricsTypeEnum, startTime, endTime, projectId, null);\n    }\n    \n    /**\n     * 查询指定范围的结果 *\n     *\n     * @param values                 第一阶段召回的结果\n     * @param gatewayMetricsTypeEnum 网关指标类型枚举\n     * @param startTime              开始时间\n     * @param endTime                结束时间\n     * @param projectId              应用程序id\n     * @param nodeIp                 节点ip 该参数是来自于{@link MetricsConstant#CLIENT_NODE};\n     *                               但是对于{@link MetricsConstant#NODE}默认是null\n     * @return {@link List}<{@link MetricsContent}>\n     */\n    public List<MetricsContent> getByRangeTopN(List<String> values, GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                               Long startTime, Long endTime, Integer projectId, String nodeIp)\n            throws AdminOperateException {\n        if (CollectionUtils.isEmpty(values)) {\n            return Collections.emptyList();\n        }    //构建query terms 查询的片段\n        String queryDslByFiled =\n                buildTermsQueryRequestFieldByValue(values, gatewayMetricsTypeEnum, nodeIp) + buildTermByProjectId(projectId);\n        String interval = MetricsUtils.getInterval((endTime - startTime));    //构建出必须包含的values结果，保证该结果可以正常返回\n        String include = new JSONArray().fluentAddAll(values).toJSONString();\n        Object[] params;\n        switch (gatewayMetricsTypeEnum) {\n            case DSLLEN_GATEWAY_NODE:\n                //queryRequest false\n                // queryRequest false\n            case WRITE_GATEWAY_NODE:\n                params = new Object[] { startTime, endTime, queryDslByFiled, AGG_KEY_FIELD, GATEWAY_NODE, values.size(),\n                                        include, interval, startTime, endTime, DSL_LEN_AVG, AVG, DSL_LEN };\n                break;\n            case QUERY_GATEWAY_NODE:\n                params = new Object[] { startTime, endTime, queryDslByFiled, AGG_KEY_FIELD, GATEWAY_NODE, values.size(),\n                                        include, interval, startTime, endTime };\n                //queryRequest true\n                break;\n            //queryRequest false\n            case WRITE_CLIENT_NODE:\n            case DSLLEN_CLIENT_NODE:\n                params = new Object[] { startTime, endTime, queryDslByFiled, AGG_KEY_FIELD, CLIENT_NODE, values.size(),\n                                        include, interval, startTime, endTime, DSL_LEN_AVG, AVG, DSL_LEN };\n                break;\n            //query true\n            case QUERY_CLIENT_NODE:\n                params = new Object[] { startTime, endTime, queryDslByFiled, AGG_KEY_FIELD, CLIENT_NODE, values.size(),\n                                        include, interval, startTime, endTime };\n                break;\n            default:\n                return Collections.emptyList();\n        }\n        return this.performGetByRangeTopN(gatewayMetricsTypeEnum, startTime, endTime,\n                response -> fetchDslResultByFiled(response, gatewayMetricsTypeEnum, interval), params);\n    }\n    \n    @Override\n    public List<VariousLineChartMetrics> checkMetricsValue(GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                           String metricsValue) {    // 当该指标存在时候，直接进行返回\n        if (StringUtils.isNotBlank(metricsValue)) {\n            VariousLineChartMetrics metrics = new VariousLineChartMetrics();\n            metrics.setType(gatewayMetricsTypeEnum.getType());\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(metricsValue);\n            metrics.setMetricsContents(Collections.singletonList(metricsContent));\n            return Collections.singletonList(metrics);\n        }\n        return Collections.emptyList();\n    }\n    \n    private List<VariousLineChartMetrics> fetchFieldAggMetricsByList(ESQueryResponse response,\n                                                                     GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                                     String interval, Integer topNu) {\n        final VariousLineChartMetrics variousLineChartMetrics = fetchFieldAggMetrics(response, gatewayMetricsTypeEnum,\n                interval, topNu);\n        return Collections.singletonList(variousLineChartMetrics);\n    }\n    \n    /**\n     * 构建 queryRequest 的请求为：false或者true的term和{@linkplain  GatewayNodeMetricsDAO#GATEWAY_NODE/> 或者{@link  GatewayNodeMetricsDAO#CLIENT_NODE}\n     * 的term dsl片段\n     * <pre>\n     *     ,{\n     *     \"term\": {\n     *     \"queryRequest\": false\n     *     }\n     *     }, {\n     *     \"terms\": {\n     *     \"FIELD\": [\n     * *        \"VALUE1\",         \"VALUE2\"\n     * ]     }\n     * }\n     * </pre>\n     * 其中这里的<B>FIELD</B>为{@linkplain  GatewayNodeMetricsDAO#GATEWAY_NODE/> 或者{@link  GatewayNodeMetricsDAO#CLIENT_NODE}\n     *  @param values\n     *  @return {@link String}\n     */\n    private String buildTermsQueryRequestFieldByValue(List<String> values, GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                      String nodeIp) {\n        String byQueryRequestContent = buildByQueryRequestContent(gatewayMetricsTypeEnum);\n        String termsContentByField = buildTermsContentByField(values, gatewayMetricsTypeEnum);\n        if (Objects.nonNull(byQueryRequestContent) && CollectionUtils.isEmpty(values)) {\n            return String.format(\",%s\", byQueryRequestContent)\n                   //加入node ip 的query 查询\n                   + (StringUtils.isNotBlank(nodeIp) ? \",\" + new JSONObject().fluentPut(TERM,\n                    new JSONObject().fluentPut(GATEWAY_NODE, nodeIp)).toJSONString() : EMPTY_STR);\n        } else if (Objects.nonNull(byQueryRequestContent) && Objects.nonNull(termsContentByField)) {\n            return String.format(\",%s,%s\", byQueryRequestContent, termsContentByField) + (StringUtils.isNotBlank(nodeIp)\n                    ? \",\" + new JSONObject().fluentPut(TERM, new JSONObject().fluentPut(GATEWAY_NODE, nodeIp))\n                    .toJSONString()\n                    : EMPTY_STR);\n        }\n        return null;\n    }\n    \n    /**\n     * 构建queryRequest查询请求\n     * <pre>\n     *     {\n     *     \"term\": {\n     *     \"queryRequest\": false\n     *     }\n     *     }\n     * </pre>\n     * or\n     * <pre>\n     *     {\n     * \"term\": {\n     * \"queryRequest\": true\n     * }  }\n     * </pre>\n     *\n     * @param gatewayMetricsTypeEnum 网关指标类型枚举\n     * @return {@link JSONObject}\n     */\n    private String buildByQueryRequestContent(GatewayMetricsTypeEnum gatewayMetricsTypeEnum) {\n        JSONObject content;\n        switch (gatewayMetricsTypeEnum) {\n            //queryRequest false\n            case WRITE_CLIENT_NODE:\n            case DSLLEN_CLIENT_NODE:\n            case WRITE_GATEWAY_NODE:\n            case DSLLEN_GATEWAY_NODE:\n                //queryRequest false\n                content = new JSONObject().fluentPut(QUERY_REQUEST, false);\n                break;\n            case QUERY_CLIENT_NODE:\n            case QUERY_GATEWAY_NODE:\n                //queryRequest true\n                content = new JSONObject().fluentPut(QUERY_REQUEST, true);\n                break;\n            default:\n                return null;\n        }\n        return new JSONObject().fluentPut(TERM, content).toJSONString();\n    }\n    \n    /**\n     * 构建t{@link  GatewayNodeMetricsDAO#GATEWAY_NODE/> 或者{@link  GatewayNodeMetricsDAO#CLIENT_NODE}的查询\n     * <pre>\n     *   {\n     *           \"terms\": {\n     *             \"FIELD\": [\n     *               \"VALUE1\",\n     *               \"VALUE2\"\n     *             ]\n     *           }\n     *         }\n     *  </pre>\n     * 其中这里的<B>FIELD</B>为{@link  GatewayNodeMetricsDAO#GATEWAY_NODE/> 或者{@link  GatewayNodeMetricsDAO#CLIENT_NODE}\n     *\n     * @param values                 值\n     * @param gatewayMetricsTypeEnum 网关指标类型枚举\n     * @return {@link Optional}<{@link JSONObject}>\n     */\n    private String buildTermsContentByField(List<String> values, GatewayMetricsTypeEnum gatewayMetricsTypeEnum) {\n        JSONObject content;\n        switch (gatewayMetricsTypeEnum) {\n            case WRITE_GATEWAY_NODE:\n            case DSLLEN_GATEWAY_NODE:\n            case QUERY_GATEWAY_NODE:\n                content = new JSONObject().fluentPut(GATEWAY_NODE, values);\n                break;\n            case WRITE_CLIENT_NODE:\n            case QUERY_CLIENT_NODE:\n            case DSLLEN_CLIENT_NODE:\n                content = new JSONObject().fluentPut(CLIENT_NODE, values);\n                break;\n            default:\n                return null;\n        }\n        return new JSONObject().fluentPut(TERMS, content).toJSONString();\n    }\n    \n    /**\n     * 构建术语\n     * <pre>\n     *     {    \"term\": {\n     *     \"queryRequest\": false\n     *     }\n     *     }\n     *\n     * </pre> *\n     *\n     * @param gatewayMetricsTypeEnum {@link  GatewayMetricsTypeEnum}\n     * @param nodeIp                 {@linkplain GatewayNodeMetricsDAO GATEWAY_NODE} 的value\n     * @return {@link String}\n     */\n    private String buildExistField(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, String nodeIp) {\n        String queryRequestFragment = buildByQueryRequestContent(gatewayMetricsTypeEnum);\n        if (Objects.nonNull(queryRequestFragment)) {\n            return String.format(\",%s\", queryRequestFragment)\n                   //nodeIp 确定不为空\n                   + (StringUtils.isNotBlank(nodeIp) ? \",\" + new JSONObject().fluentPut(TERM,\n                    new JSONObject().fluentPut(GATEWAY_NODE, nodeIp)).toJSONString() : EMPTY_STR);\n        }\n        return null;\n    }\n    \n    private List<MetricsContent> fetchDslResultByFiled(ESQueryResponse response,\n                                                       GatewayMetricsTypeEnum gatewayMetricsTypeEnum, String interval) {\n        final Optional<Map<String, ESAggr>> esAggrMapOptional = Optional.ofNullable(response)\n                .map(ESQueryResponse::getAggs).map(ESAggrMap::getEsAggrMap).filter(MapUtils::isNotEmpty);\n        if (!esAggrMapOptional.isPresent()) {\n            return Collections.emptyList();\n        }\n        String aggKey = gatewayMetricsTypeEnum.getAggKey();\n        List<MetricsContent> metricsContents = Lists.newArrayList();\n        for (ESBucket esBucket : esAggrMapOptional.get().get(AGG_KEY_FIELD).getBucketList()) {\n            String nodeName = esBucket.getUnusedMap().get(KEY).toString();\n            MetricsContent metricsContent = new MetricsContent();\n            metricsContent.setName(nodeName);\n            metricsContent.setMetricsContentCells(Lists.newArrayList());\n            if (null != esBucket.getAggrMap() && null != esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP)) {\n                if (esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).getBucketList() != null) {\n                    for (ESBucket bucket : esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).getBucketList()) {\n                        long timeStamp = Long.parseLong(bucket.getUnusedMap().get(KEY).toString());\n                        double value;\n                        if (MetricsUtils.needConvertUnit(aggKey)) {\n                            value = MetricsUtils.getDoubleValuePerMin(interval,\n                                    bucket.getUnusedMap().get(aggKey).toString());\n                        } else if (GatewayMetricsTypeEnum.DSL_LEN.getAggKey().equals(aggKey)) {\n                            value = MetricsUtils.getAggMapDoubleValue(bucket, aggKey);\n                        } else {\n                            value = Double.parseDouble(bucket.getUnusedMap().get(aggKey).toString());\n                        }\n                        metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                    }\n                } else {\n                    esBucket.getAggrMap().get(AGG_KEY_TIMESTAMP).toJson().getJSONObject(BUCKETS).values()\n                            .forEach(groupByTimeStampBucket -> {\n                                Long timeStamp = Long.valueOf(\n                                        ((JSONObject) groupByTimeStampBucket).get(KEY).toString());\n                                Double value;\n                                if (MetricsUtils.needConvertUnit(aggKey)) {\n                                    value = MetricsUtils.getDoubleValuePerMin(interval, Optional.ofNullable(\n                                                    ((JSONObject) groupByTimeStampBucket).get(aggKey).toString())\n                                            .map(Object::toString).orElse(\"0\"));\n                                } else if (GatewayMetricsTypeEnum.DSL_LEN.getAggKey().equals(aggKey)) {\n                                    value = Optional.ofNullable(\n                                                    ((JSONObject) groupByTimeStampBucket).getJSONObject(aggKey).get(VALUE))\n                                            .map(d -> Double.valueOf(d.toString())).orElse(0.0);\n                                } else {\n                                    value = Optional.ofNullable(\n                                                    ((JSONObject) groupByTimeStampBucket).getJSONObject(aggKey).get(VALUE))\n                                            .map(d -> Double.valueOf(d.toString())).orElse(0.0);\n                                }\n                                metricsContent.getMetricsContentCells().add(new MetricsContentCell(value, timeStamp));\n                            });\n                }\n            }\n            metricsContents.add(metricsContent);\n        }\n        return metricsContents;\n    }\n    \n    private VariousLineChartMetrics fetchFieldAggMetrics(ESQueryResponse response,\n                                                         GatewayMetricsTypeEnum gatewayMetricsTypeEnum, String interval,\n                                                         Integer topNu) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(gatewayMetricsTypeEnum.getType());\n        variousLineChartMetrics.setMetricsContents(Lists.newArrayList());\n        Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n                .orElse(null);\n        if (null != esAggrMap && null != esAggrMap.get(AGG_KEY_FIELD)) {\n            handleESBucket(gatewayMetricsTypeEnum, interval, variousLineChartMetrics, esAggrMap);\n        }\n        //根据第一个时间点的值进行倒排，取topNu\n        List<MetricsContent> sortedList = variousLineChartMetrics.getMetricsContents().stream()\n                .sorted(Comparator.nullsLast(Comparator.comparing(\n                        x -> CollectionUtils.isEmpty(x.getMetricsContentCells())\n                                ? -1\n                                : x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder())))\n                .limit(topNu).collect(Collectors.toList());\n        variousLineChartMetrics.setMetricsContents(sortedList);\n        return variousLineChartMetrics;\n    }\n    \n    @Override\n    protected String getFinalDslByOneStep(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Object[] args) {\n        switch (gatewayMetricsTypeEnum) {\n            case DSLLEN_GATEWAY_NODE:\n                //queryRequest false\n                // queryRequest false\n            case WRITE_GATEWAY_NODE:\n            case WRITE_CLIENT_NODE:\n            case DSLLEN_CLIENT_NODE:\n                return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOTAL_COST_BY_FIELD, args);\n            case QUERY_GATEWAY_NODE:            //query true\n            case QUERY_CLIENT_NODE:\n                //queryRequest true\n                return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_COUNT_BY_FILELD, args);\n            default:\n                return null;\n        }\n    }\n    \n    @Override\n    protected String getFinalDslBySecondStep(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Object[] args) {\n        switch (gatewayMetricsTypeEnum) {\n            case DSLLEN_GATEWAY_NODE:            //queryRequest false\n                // queryRequest false\n            case WRITE_GATEWAY_NODE:\n            case WRITE_CLIENT_NODE:\n            case DSLLEN_CLIENT_NODE:\n                return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOTAL_COST_EXTENDED_BOUNDS_BY_FIELD,\n                        args);\n            case QUERY_GATEWAY_NODE:\n            case QUERY_CLIENT_NODE:\n                //queryRequest true\n                return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_DSL_COUNT_EXTENDED_BOUNDS_BY_FILELD,\n                        args);\n            default:\n                return null;\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/gateway/GatewayOverviewMetricsDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.gateway;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.GatewayOverviewMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContentCell;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.GatewayMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.DSLSearchUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.google.common.collect.Lists;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\n@Component\n@NoArgsConstructor\npublic class GatewayOverviewMetricsDAO extends BaseESDAO {\n\n    private static final String TYPE    = \"type\";\n    private static final String AGG_KEY = \"group_by_timeStamp\";\n    private static final String KEY     = \"key\";\n    private String              indexName;\n\n    @PostConstruct\n    public void init() {\n        this.indexName = dataCentreUtil.getAriusStatsGatewayInfo();\n    }\n\n    /**\n     * 获取总览视图公共部分指标\n     */\n    public List<GatewayOverviewMetrics> getAggCommonMetricsByRange(List<String> metricsTypes, Long startTime,\n                                                                   Long endTime) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String aggDsl = getAggDsl(metricsTypes);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_COMMON_METRICS, startTime, endTime,\n            interval, startTime, endTime, aggDsl);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchCommonAggMetrics(response, metricsTypes, interval), 3);\n    }\n\n    /**\n     * 获取总览视图单项指标\n     */\n    public GatewayOverviewMetrics getAggSingleMetricsByRange(String dslTemplate,\n                                                             GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                             Long startTime, Long endTime) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String dsl = dslLoaderUtil.getFormatDslByFileName(dslTemplate, startTime, endTime, interval, startTime,\n            endTime);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchSingleAggMetrics(response, gatewayMetricsTypeEnum, interval), 3);\n    }\n\n    /**\n     * 获取总览写入指标\n     */\n    public List<GatewayOverviewMetrics> getAggWriteMetricsByRange(List<String> metricsTypes, Long startTime,\n                                                                  Long endTime) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval((endTime - startTime));\n        String aggDsl = getAggDsl(metricsTypes);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_GATEWAY_WRITE_METRICS, startTime, endTime,\n            interval, startTime, endTime, aggDsl);\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchCommonAggMetrics(response, metricsTypes, interval), 3);\n    }\n\n    /**************************************************** private methods ****************************************************/\n    private List<GatewayOverviewMetrics> fetchCommonAggMetrics(ESQueryResponse response, List<String> metricsTypes,\n                                                               String interval) {\n        Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n            .orElse(null);\n        List<GatewayOverviewMetrics> overviewMetricsArrayList = Lists.newArrayList();\n        if (null != esAggrMap && null != esAggrMap.get(AGG_KEY)) {\n            for (ESBucket esBucket : esAggrMap.get(AGG_KEY).getBucketList()) {\n                handleESBucket(metricsTypes, interval, overviewMetricsArrayList, esBucket);\n            }\n        }\n        return overviewMetricsArrayList;\n    }\n\n    private void handleESBucket(List<String> metricsTypes, String interval,\n                                List<GatewayOverviewMetrics> overviewMetricsArrayList, ESBucket esBucket) {\n        Long timeStamp = Long.valueOf(esBucket.getUnusedMap().get(KEY).toString());\n\n        for (String metricsType : metricsTypes) {\n            String aggKey = GatewayMetricsTypeEnum.type2AggKey(metricsType);\n            if (StringUtils.isBlank(aggKey)) {\n                continue;\n            }\n            double value;\n            if (MetricsUtils.needConvertUnit(aggKey)) {\n                value = MetricsUtils.getDoubleValuePerMin(interval, esBucket.getUnusedMap().get(aggKey).toString());\n            } else {\n                value = MetricsUtils.getAggMapDoubleValue(esBucket, aggKey);\n            }\n            MetricsContentCell contentCell = new MetricsContentCell(value, timeStamp);\n            GatewayOverviewMetrics gatewayOverviewMetrics = new GatewayOverviewMetrics();\n            gatewayOverviewMetrics.setType(metricsType);\n            if (overviewMetricsArrayList.contains(gatewayOverviewMetrics)) {\n                overviewMetricsArrayList.get(overviewMetricsArrayList.indexOf(gatewayOverviewMetrics))\n                    .addMetrics(contentCell);\n            } else {\n                gatewayOverviewMetrics.setMetrics(Lists.newArrayList(contentCell));\n                overviewMetricsArrayList.add(gatewayOverviewMetrics);\n            }\n        }\n    }\n\n    private GatewayOverviewMetrics fetchSingleAggMetrics(ESQueryResponse response, GatewayMetricsTypeEnum metricsType,\n                                                         String interval) {\n        Map<String, ESAggr> esAggrMap = Optional.ofNullable(response.getAggs()).map(ESAggrMap::getEsAggrMap)\n            .orElse(null);\n        GatewayOverviewMetrics gatewayOverviewMetrics = new GatewayOverviewMetrics();\n        gatewayOverviewMetrics.setType(metricsType.getType());\n        gatewayOverviewMetrics.setMetrics(Lists.newArrayList());\n        if (null != esAggrMap && null != esAggrMap.get(AGG_KEY)) {\n            for (ESBucket esBucket : esAggrMap.get(AGG_KEY).getBucketList()) {\n                Long timeStamp = Long.valueOf(esBucket.getUnusedMap().get(KEY).toString());\n                String aggKey = metricsType.getAggKey();\n                Double value;\n                if (MetricsUtils.needConvertUnit(aggKey)) {\n                    value = MetricsUtils.getDoubleValuePerMin(interval, esBucket.getUnusedMap().get(aggKey).toString());\n                } else {\n                    value = Double.valueOf(esBucket.getUnusedMap().get(aggKey).toString());\n                }\n                MetricsContentCell metricsContentCell = new MetricsContentCell(value, timeStamp);\n                gatewayOverviewMetrics.addMetrics(metricsContentCell);\n            }\n        }\n        return gatewayOverviewMetrics;\n    }\n\n    private String getAggDsl(List<String> metricsTypes) {\n        JSONObject json = new JSONObject();\n        for (String metricsType : metricsTypes) {\n            if (GatewayMetricsTypeEnum.QUERY_TOTAL_HITS_AVG_COUNT.getType().equals(metricsType)) {\n                json.put(GatewayMetricsTypeEnum.QUERY_TOTAL_HITS_AVG_COUNT.getAggKey(),\n                    DSLSearchUtils.buildAggItem(\"avg\", \"totalHits\"));\n            } else if (GatewayMetricsTypeEnum.QUERY_COST_AVG.getType().equals(metricsType)) {\n                json.put(GatewayMetricsTypeEnum.QUERY_COST_AVG.getAggKey(),\n                    DSLSearchUtils.buildAggItem(\"avg\", \"totalCost\"));\n            } else if (GatewayMetricsTypeEnum.QUERY_TOTAL_SHARDS_AVG.getType().equals(metricsType)) {\n                json.put(GatewayMetricsTypeEnum.QUERY_TOTAL_SHARDS_AVG.getAggKey(),\n                    DSLSearchUtils.buildAggItem(\"avg\", \"totalShards\"));\n            } else if (GatewayMetricsTypeEnum.QUERY_FAILED_SHARDS_AVG.getType().equals(metricsType)) {\n                json.put(GatewayMetricsTypeEnum.QUERY_FAILED_SHARDS_AVG.getAggKey(),\n                    DSLSearchUtils.buildAggItem(\"avg\", \"failedShards\"));\n            } else if (GatewayMetricsTypeEnum.WRITE_TOTAL_COST.getType().equals(metricsType)) {\n                json.put(GatewayMetricsTypeEnum.WRITE_TOTAL_COST.getAggKey(),\n                    DSLSearchUtils.buildAggItem(\"avg\", \"totalCost\"));\n            } else if (GatewayMetricsTypeEnum.WRITE_RESPONSE_LEN.getType().equals(metricsType)) {\n                json.put(GatewayMetricsTypeEnum.WRITE_RESPONSE_LEN.getAggKey(),\n                    DSLSearchUtils.buildAggItem(\"avg\", \"responseLen\"));\n            } else if (GatewayMetricsTypeEnum.DSL_LEN.getType().equals(metricsType)) {\n                json.put(GatewayMetricsTypeEnum.DSL_LEN.getAggKey(), DSLSearchUtils.buildAggItem(\"avg\", \"dslLen\"));\n            }\n        }\n        return json.toString();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/index/IndexCatESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.index;\n\nimport static com.didichuxing.datachannel.arius.admin.persistence.constant.ESOperateConstant.ES_OPERATE_TIMEOUT;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexCatCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.index.IndexCatCellPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.index.IndexStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.function.BiFunctionWithESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.DSLSearchUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ParsingExceptionUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpTimeoutRetry;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ScrollResultVisitor;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHit;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHits;\nimport com.google.common.collect.Lists;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Predicate;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.stereotype.Component;\n\n@Component\n@NoArgsConstructor\npublic class IndexCatESDAO extends BaseESDAO {\n    @Value(\"${es.update.cluster.name}\")\n    private String metadataClusterName;\n    \n    /**\n     * 索引名称\n     */\n    private             String indexName;\n    /**\n     * type名称\n     */\n    private             String typeName       = \"_doc\";\n    public static final String SEGMENTS       = \"/_segments\";\n    public static final String INDICES        = \"indices\";\n    public static final String SHARDS         = \"shards\";\n    public static final String SEGMENTS_SHARD = \"segments\";\n    private              String TYPE           = \"type\";\n    private static final String  INDEX = \"index\";\n    private static final String  KEY = \"key\";\n    private static final String  DOC_COUNT = \"doc_count\";\n    private static final Integer AGG_SIZE       = 5000;\n    private static final String GROUP_BY_CLUSTER=\"group_by_cluster\";\n\n    @PostConstruct\n    public void init() {\n        this.indexName = dataCentreUtil.getAriusCatIndexInfo();\n    }\n\n    /**\n     * 批量保存索引大小结果\n     *\n     * @param list\n     * @return\n     */\n    public boolean batchInsert(List<IndexCatCellPO> list, int retryCount) {\n        try {\n            return ESOpTimeoutRetry.esRetryExecute(\"batchInsert\", retryCount,\n                    () -> updateClient.batchInsert(IndexNameUtils.genCurrentDailyIndexName(indexName), typeName, list));\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=IndexCatESDAO||method=batchInsert||errMsg={}\", e.getMessage(), e);\n        }\n        return false;\n    }\n    public boolean batchUpsert(List<IndexCatCellPO> list, int retryCount) {\n        try {\n            return ESOpTimeoutRetry.esRetryExecute(\"batchInsert\", retryCount,\n                    () -> updateClient.batchUpdate(IndexNameUtils.genCurrentDailyIndexName(indexName), typeName, list));\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=IndexCatESDAO||method=batchInsert||errMsg={}\", e.getMessage(), e);\n        }\n        return false;\n    }\n\n\n    /**\n     * 更新查询模板信息\n     *\n     * @param list\n     * @return\n     */\n    public boolean updateCatIndexInfo(List<IndexCatCellPO> list) {\n        return updateClient.batchUpdate(IndexNameUtils.genCurrentDailyIndexName(indexName), typeName, list);\n    }\n\n    /**\n     * 根据条件获取CatIndex信息\n     *\n     * @param index        索引名称（可选）\n     * @param health       健康度（可选）\n     * @param from         起始值\n     * @param size         每页大小\n     * @param sortTerm     排序字段\n     * @param orderByDesc  是否降序\n     * @return             Tuple<Long, List<IndexCatCellPO>> 命中数 具体数据\n     */\n    public Tuple<Long, List<IndexCatCellPO>> getCatIndexInfo(String cluster, String index, String health, String status,\n                                                             Integer projectId, Long from, Long size, String sortTerm,\n                                                             Boolean orderByDesc) {\n        Tuple<Long, List<IndexCatCellPO>> totalHitAndIndexCatCellListTuple;\n        String queryTermDsl = buildQueryTermDsl(cluster, index, health, status, projectId);\n        String sortType = buildSortType(orderByDesc);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CAT_INDEX_INFO_BY_CONDITION, queryTermDsl,\n            sortTerm, sortType, from, size);\n        int retryTime = 3;\n        do {\n            totalHitAndIndexCatCellListTuple = gatewayClient.performRequestListAndGetTotalCount(metadataClusterName,\n                IndexNameUtils.genCurrentDailyIndexName(indexName), typeName, dsl, IndexCatCellPO.class);\n        } while (retryTime-- > 0 && null == totalHitAndIndexCatCellListTuple);\n\n        return totalHitAndIndexCatCellListTuple;\n    }\n\n    public Tuple<Long, List<IndexCatCellPO>> getIndexListByTerms(String cluster,Integer projectId){\n        Tuple<Long, List<IndexCatCellPO>> totalHitAndIndexCatCellListTuple;\n        String queryTermDsl = buildQueryTermDsl( cluster,null, null, null, projectId);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_ALL_CAT_INDEX_INFO_BY_TERMS, queryTermDsl);\n        int retryTime = 3;\n        do {\n            totalHitAndIndexCatCellListTuple = gatewayClient.performRequestListAndGetTotalCount(metadataClusterName,\n                    IndexNameUtils.genCurrentDailyIndexName(indexName), typeName, dsl, IndexCatCellPO.class);\n        } while (retryTime-- > 0 && null == totalHitAndIndexCatCellListTuple);\n        return totalHitAndIndexCatCellListTuple;\n    }\n\n    /**\n     * 更新索引删除标识, 用于真实索引删除后同步删除记录索引信息的元数据索引信息\n     *\n     * @param cluster           索引所在集群\n     * @param indexNameList     索引名称\n     * @param retryCount        重试次数\n     * @return\n     */\n    public Boolean batchUpdateCatIndexDeleteFlag(String cluster, List<String> indexNameList, int retryCount) {\n        try {\n            return ESOpTimeoutRetry.esRetryExecute(\"batchUpdateCatIndexDeleteFlag\", retryCount,\n                () -> updateCatIndexDeleteFlag(cluster, indexNameList));\n        } catch (ESOperateException e) {\n            LOGGER.warn(\"class=IndexCatESDAO||method=batchUpdateCatIndexDeleteFlag||errMsg={}\", e.getMessage(), e);\n        }\n\n        return false;\n    }\n\n    /**\n     * 更新索引开启或关闭标识\n     * @param cluster           索引所在集群\n     * @param indexNameList     索引名称\n     * @param status    索引标识，\"open\" 开启，\"close\" 关闭\n     * @param retryCount        重试次数\n     * @return\n     */\n    public Boolean batchUpdateCatIndexStatus(String cluster, List<String> indexNameList, String status,\n                                             int retryCount) {\n        try {\n            return ESOpTimeoutRetry.esRetryExecute(\"batchUpdateCatIndexStatus\", retryCount,\n                () -> updateCatIndexStatus(cluster, indexNameList, status));\n        } catch (ESOperateException e) {\n            LOGGER.warn(\"class=IndexCatESDAO||method=batchUpdateCatIndexStatus||errMsg={}\", e.getMessage(), e);\n        }\n\n        return false;\n    }\n\n    /**\n     * 获取不包含模板id并且包含projectId的IndexCatCell信息，作用于平台索引管理新建索引侧\n     *\n     * @return List<IndexCatCell>\n     */\n    public  List<IndexCatCell> getPlatformCreateCatIndexList( Integer searchSize) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_PLATFORM_CREATE_CAT_INDEX,searchSize);\n   \n        // 这里两个时间 用于拿到今天和昨天的数据, 否则无法个获取昨天用户创建的索引数据\n        long nowTime = System.currentTimeMillis();\n        long oneDayAgo = nowTime - 20 * 60 * 60 * 1000;\n        List<IndexCatCell> indexCatCellList = Lists.newCopyOnWriteArrayList();\n        String genDailyIndexName = IndexNameUtils.genDailyIndexName(indexName, oneDayAgo, nowTime);\n        ScrollResultVisitor<IndexCatCell> scrollResultVisitor = resultList -> {\n            if (CollectionUtils.isNotEmpty(resultList)) {\n                indexCatCellList.addAll(resultList);\n            }\n        };\n        try {\n            ESOpTimeoutRetry.esRetryExecute(\"getPlatformCreateCatIndexList\", 3, () -> {\n            \n                gatewayClient.queryWithScroll(metadataClusterName, genDailyIndexName, TYPE, dsl, searchSize, null,\n                        IndexCatCell.class, scrollResultVisitor);\n                return true;\n            \n            });\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=IndexCatESDAO||method=getPlatformCreateCatIndexList\", e);\n        }\n    \n        return indexCatCellList;\n    }\n    \n    public List<IndexCatCellDTO> syncGetSegmentsIndexList(String cluster, Collection<String> indexList)\n            throws ESOperateException {\n        ESClient esClient = esOpClient.getESClient(cluster);\n        if (esClient == null) {\n            LOGGER.error(\"class={}||method=syncGetSegmentsIndexList||clusterName={}||errMsg=esClient is null\",\n                    getClass().getSimpleName(), cluster);\n            throw new NullPointerException(cluster);\n        }\n        if (CollectionUtils.isEmpty(indexList)) {\n            return Collections.emptyList();\n        }\n        String uri = String.format(\"/%s%s\", String.join(\",\", indexList), SEGMENTS);\n        DirectRequest directRequest = new DirectRequest(HttpMethod.GET.name(), uri);\n        Predicate<DirectResponse> directRequestPredicate = directResponse -> Objects.isNull(directResponse)\n                                                                             || RestStatus.OK\n                                                                                != directResponse.getRestStatus();\n        BiFunctionWithESOperateException<Long, TimeUnit, DirectResponse> directRequestBiFunction = (timeout, unit) -> {\n            try {\n                return esClient.direct(directRequest).actionGet(timeout, unit);\n            } catch (Exception e) {\n                LOGGER.error(\"class=ESIndexDAO||cluster={}||method=syncGetSegmentsIndexList\", cluster, e);\n                ParsingExceptionUtils.abnormalTermination(e);\n            }\n            return null;\n        };\n    \n        DirectResponse response = ESOpTimeoutRetry.esRetryExecute(\"syncGetSegmentsIndexList\", 3,\n                () -> directRequestBiFunction.apply(Long.valueOf(ES_OPERATE_TIMEOUT), TimeUnit.SECONDS),\n                directRequestPredicate\n    \n        );\n        \n    \n        return Optional.ofNullable(response).filter(r -> RestStatus.OK == r.getRestStatus())\n                .map(DirectResponse::getResponseContent).map(JSON::parseObject).map(json -> json.getJSONObject(INDICES))\n                .map(i -> buildIndexCatCellDTOList(i, cluster))\n            \n                .orElse(Lists.newArrayList());\n    }\n    \n    public List<String> syncGetIndexListByProjectIdAndClusterLogic(Integer projectId,\n                                                                   String clusterLogic) {\n        String realIndexName =IndexNameUtils.genCurrentDailyIndexName(indexName);\n        if (Objects.isNull(projectId)) {\n            return Collections.emptyList();\n        }\n        \n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_PLATFORM_CREATE_CAT_INDEX_BY_INDEX_PROJECT,\n                clusterLogic, projectId, AGG_SIZE);\n        return gatewayClient.performRequest(metadataClusterName, realIndexName, TYPE, dsl,\n                IndexCatESDAO::buildIndexListByResponse, 3);\n    }\n     public List<String> syncGetIndexListByProjectIdAndFuzzyIndexAndClusterLogic(Integer projectId, String clusterLogicName,\n                                                                                 String index) {\n         String realIndexName = IndexNameUtils.genCurrentDailyIndexName(indexName);\n         if (Objects.isNull(projectId)) {\n             return Collections.emptyList();\n         }\n    \n         String dsl = dslLoaderUtil.getFormatDslByFileName(\n                 DslsConstant.GET_PLATFORM_CREATE_CAT_INDEX_BY_INDEX_PROJECT_AND_FUZZY_INDEX_AND_CLUSTER_LOGIC,\n                 clusterLogicName, projectId, StringUtils.isNotBlank(index) ? index : \"\", AGG_SIZE);\n         return gatewayClient.performRequest(metadataClusterName, realIndexName, TYPE, dsl,\n                 IndexCatESDAO::buildIndexListByResponse, 3);\n    }\n    \n    public List<String> syncGetIndexListByProjectIdAndFuzzyIndexAndClusterPhy( String clusterPhyName,\n                                                                              String index) {\n         String realIndexName = IndexNameUtils.genCurrentDailyIndexName(indexName);\n       \n         String dsl = dslLoaderUtil.getFormatDslByFileName(\n                 DslsConstant.GET_PLATFORM_CREATE_CAT_INDEX_BY_INDEX_PROJECT_AND_FUZZY_INDEX_AND_CLUSTER_PHY,\n                 clusterPhyName, StringUtils.isNotBlank(index) ? index : \"\", AGG_SIZE);\n         return gatewayClient.performRequest(metadataClusterName, realIndexName, TYPE, dsl,\n                 IndexCatESDAO::buildIndexListByResponse, 3);\n    }\n    \n    \n    \n    public Map<String, Integer> syncGetByClusterPhyList(List<String> clusterPhyList) {\n        if (CollectionUtils.isEmpty(clusterPhyList)) {\n            return Collections.emptyMap();\n        }\n        String realIndexName = IndexNameUtils.genCurrentDailyIndexName(indexName);\n        final String clusterPhyStr = JSON.toJSONString(clusterPhyList);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_PLATFORM_CREATE_CAT_INDEX_GROUP_BY_CLUSTER,\n                clusterPhyStr, clusterPhyList.size(), clusterPhyStr);\n        return gatewayClient.performRequest(metadataClusterName, realIndexName, TYPE, dsl,\n                res -> Optional.ofNullable(res).map(ESQueryResponse::getAggs).map(ESAggrMap::getEsAggrMap)\n                        .map(i -> i.get(GROUP_BY_CLUSTER)).map(ESAggr::getBucketList).orElse(Collections.emptyList())\n                        .stream().map(ESBucket::getUnusedMap)\n                        .map(map -> Tuples.of(map.get(KEY).toString(), ((Integer) map.getOrDefault(DOC_COUNT, 0))))\n                        .collect(Collectors.toMap(TupleTwo::v1, TupleTwo::v2))\n                \n                , 3);\n    }\n    \n    public IndexCatCell syncGetCatIndexInfoById(/* clusterPhy*/String clusterPhy,/*IndexName*/ String index) {\n        \n        List<String> ids = Collections.singletonList(String.format(\"%s@%s\", clusterPhy, index));\n        \n        final String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_PLATFORM_CREATE_CAT_INDEX_BY_ID,\n                ids.size(), JSON.toJSONString(ids));\n    \n        Tuple<Long, List<IndexCatCellPO>> tuple = null;\n        try {\n            tuple = ESOpTimeoutRetry.esRetryExecute(\"syncGetSegmentsIndexList\", 3,\n                    () -> gatewayClient.performRequestListAndGetTotalCount(metadataClusterName,\n                            IndexNameUtils.genCurrentDailyIndexName(indexName), typeName, dsl, IndexCatCellPO.class),\n                    Objects::isNull\n        \n            );\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class={}||cluster={}||method=syncGetCatIndexInfoById\", getClass().getSimpleName(), clusterPhy,\n                    e);\n        }\n        \n        \n        return Optional.ofNullable(tuple).map(Tuple::getV2).map(i -> ConvertUtil.list2List(i, IndexCatCell.class))\n                .filter(CollectionUtils::isNotEmpty).orElse(Collections.emptyList()).stream().findFirst().orElse(null);\n        \n    }\n\n    /**\n     * 获取多个物理集群下的索引名称\n     *\n     * @return List<IndexCatCell>\n     */\n    public List<IndexCatCell> getAllCatIndexNameListByClusters(Integer searchSize, List<String> phyClusterNames) {\n        String clusterPhyStr = JSON.toJSONString(phyClusterNames);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_ALL_CAT_INDEX_NAME_BY_CLUSTERS, searchSize,clusterPhyStr);\n        List<IndexCatCell> indexCatCellList = getIndexCellWithScroll(searchSize, dsl);\n        return indexCatCellList;\n    }\n\n    /**************************************************private******************************************************/\n    /**\n     * 构建模糊查询dsl语法, 如下\n     * {\n     * \t\"term\": {\n     * \t\t\"index\": {\n     * \t\t\t\"value\": \"cn_arius.template.label\"\n     *                } \t}\n     * }\n     * @param cluster\n     * @param index\n     * @param health\n     * @return\n     */\n    private String buildQueryTermDsl(String cluster, String index, String health, String status, Integer projectId) {\n        return \"[\" + buildTermCell(cluster, index, health, status, projectId) + \"]\";\n    }\n\n    private String buildTermCell(String cluster, String index, String health, String status, Integer projectId) {\n        List<String> termCellList = Lists.newArrayList();\n        //projectId == null 时，属于超级项目访问；\n        if (null == projectId) {\n            //get cluster dsl term\n            termCellList.add(DSLSearchUtils.getTermCellForExactSearch(cluster, \"cluster\"));\n        } else {\n            //get projectId dsl term\n            termCellList.add(DSLSearchUtils.getTermCellForExactSearch(projectId, \"projectId\"));\n\n            //get resourceId dsl term\n            termCellList.add(DSLSearchUtils.getTermCellForExactSearch(cluster, \"clusterLogic\"));\n\n        }\n        //get index dsl term\n        termCellList.add(DSLSearchUtils.getTermCellForWildcardSearch(index, \"index\"));\n\n        //get index status term\n        if (IndexStatusEnum.isStatusExit(health)) {\n            termCellList.add(DSLSearchUtils.getTermCellForExactSearch(health, \"health\"));\n        }\n\n        //get index status term\n        if (IndexStatusEnum.isStatusExit(status)) {\n            termCellList.add(DSLSearchUtils.getTermCellForExactSearch(status, \"status\"));\n        }\n\n        //get index deleteFlag term\n        String deleteFlag = \"false\";\n        termCellList.add(DSLSearchUtils.getTermCellForExactSearch(deleteFlag, \"deleteFlag\"));\n        return ListUtils.strList2String(termCellList);\n    }\n\n    private boolean updateCatIndexDeleteFlag(String cluster, List<String> indexNameList) {\n        List<IndexCatCellPO> indexCatCellPOSList = Lists.newArrayList();\n        long currentTimeMillis = System.currentTimeMillis();\n        for (String index : indexNameList) {\n            IndexCatCellPO indexCatCellPO = new IndexCatCellPO();\n            indexCatCellPO.setCluster(cluster);\n            indexCatCellPO.setIndex(index);\n            indexCatCellPO.setDeleteFlag(true);\n            indexCatCellPO.setTimestamp(currentTimeMillis);\n            indexCatCellPOSList.add(indexCatCellPO);\n        }\n\n        return updateCatIndexInfo(indexCatCellPOSList);\n    }\n\n    private boolean updateCatIndexStatus(String cluster, List<String> indexNameList, String status) {\n        List<IndexCatCellPO> indexCatCellPOSList = Lists.newArrayList();\n        long currentTimeMillis = System.currentTimeMillis();\n        for (String index : indexNameList) {\n            IndexCatCellPO indexCatCellPO = new IndexCatCellPO();\n            indexCatCellPO.setCluster(cluster);\n            indexCatCellPO.setIndex(index);\n            indexCatCellPO.setStatus(status);\n            indexCatCellPO.setTimestamp(currentTimeMillis);\n            indexCatCellPOSList.add(indexCatCellPO);\n        }\n\n        return updateCatIndexInfo(indexCatCellPOSList);\n    }\n    \n\n    private String buildSortType(Boolean orderByDesc) {\n        String sortType = \"desc\";\n        if (orderByDesc == null) {\n            return sortType;\n        }\n\n        if (orderByDesc) {\n            return sortType;\n        }\n\n        return \"asc\";\n    }\n\n     private List<IndexCatCellDTO> buildIndexCatCellDTOList(JSONObject jsonObject, String clusterPhy) {\n        List<IndexCatCellDTO> indexCatCellDTOList = Lists.newArrayList();\n        for (Entry<String, Object> indexJson : jsonObject.entrySet()) {\n            String index = indexJson.getKey();\n            \n            JSONObject value = (JSONObject) indexJson.getValue();\n            Long shardSizeIndex = (long) value.getJSONObject(SHARDS).size();\n            Long indexShardSegmentsSize = value.getJSONObject(SHARDS).values().stream().filter(Objects::nonNull)\n                    .map(JSONArray.class::cast).flatMap(Collection::stream).map(JSONObject.class::cast)\n                    .map(json -> json.getJSONObject(SEGMENTS_SHARD)).mapToLong(JSONObject::size).sum();\n            IndexCatCellDTO catCellDTO = new IndexCatCellDTO();\n            catCellDTO.setIndex(index);\n            catCellDTO.setPri(shardSizeIndex);\n            catCellDTO.setTotalSegmentCount(indexShardSegmentsSize);\n            catCellDTO.setCluster(clusterPhy);\n            indexCatCellDTOList.add(catCellDTO);\n        }\n        return indexCatCellDTOList;\n    }\n    private static List<String> buildIndexListByResponse(ESQueryResponse response) {\n        return Optional.ofNullable(response).map(ESQueryResponse::getHits).map(ESHits::getHits)\n                .orElse(Collections.emptyList()).stream().filter(Objects::nonNull).map(ESHit::getSource)\n                .filter(Objects::nonNull).map(JSONObject.class::cast).map(jsonObject -> jsonObject.getString(INDEX))\n                .filter(Objects::nonNull).distinct().collect(Collectors.toList());\n    }\n\n    private List<IndexCatCell> getIndexCellWithScroll(Integer searchSize, String dsl) {\n        // 这里两个时间 用于拿到今天和昨天的数据, 否则无法个获取昨天用户创建的索引数据\n        long nowTime = System.currentTimeMillis();\n        long oneDayAgo = nowTime - 20 * 60 * 60 * 1000;\n        List<IndexCatCell> indexCatCellList = Lists.newCopyOnWriteArrayList();\n        String genDailyIndexName = IndexNameUtils.genDailyIndexName(indexName, oneDayAgo, nowTime);\n        ScrollResultVisitor<IndexCatCell> scrollResultVisitor = resultList -> {\n            if (CollectionUtils.isNotEmpty(resultList)) {\n                indexCatCellList.addAll(resultList);\n            }\n        };\n        try {\n            ESOpTimeoutRetry.esRetryExecute(\"getIndexCellWithScroll\", 3, () -> {\n                gatewayClient.queryWithScroll(metadataClusterName, genDailyIndexName, TYPE, dsl, searchSize, null, IndexCatCell.class, scrollResultVisitor);\n                return true;\n            });\n        } catch (ESOperateException e) {\n            LOGGER.error(\"class=IndexCatESDAO||method=getIndexCellWithScroll\", e);\n        }\n        return indexCatCellList;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/stats/AriusStatsClusterInfoESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusStatsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHit;\nimport com.google.common.collect.Maps;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.ObjectUtils;\n\nimport javax.annotation.PostConstruct;\nimport java.util.*;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.*;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ESHttpRequestContent.GET_CLUSTER_STATS;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ESHttpRequestContent.GET_PENDING_TASKS;\n\n@Component\npublic class AriusStatsClusterInfoESDAO extends BaseAriusStatsESDAO {\n\n    @PostConstruct\n    public void init() {\n        super.indexName = dataCentreUtil.getAriusStatsClusterInfo();\n        BaseAriusStatsESDAO.register(AriusStatsEnum.CLUSTER_INFO, this);\n    }\n\n    /**\n     * 获取物理集群分位指标信息\n     * @param clusterName         集群名称\n     * @param clusterMetricsType  集群指标类型\n     * @param aggType             聚合类型 avg sum min max\n     * @param percentilesType     分位类型\n     * @param startTime           开始时间\n     * @param endTime             结束时间\n     * @return\n     */\n    public Map<Long, Double> getAggSinglePercentilesMetrics(String clusterName,long clusterType, String clusterMetricsType,\n                                                            String aggType, String percentilesType, Long startTime,\n                                                            Long endTime) {\n        Map<Long, Double> resultMap = Maps.newHashMap();\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n        try {\n            String dsl = dslLoaderUtil.getFormatDslByFileName(\n                DslsConstant.GET_CLUSTER_PHY_AGG_PERCENTILES_METRICS_BY_AGG_PARAM, clusterName,clusterType, percentilesType,\n                startTime, endTime, interval, clusterMetricsType, aggType, clusterMetricsType);\n\n            resultMap = gatewayClient.performRequestWithRouting(metadataClusterName, clusterName, realIndexName, TYPE,\n                dsl,\n                (ESQueryResponse response) -> fetchAggSinglePercentilesMetrics(response, clusterMetricsType, aggType),\n                3);\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=AriusStatsClusterInfoESDAO||method=getAggSinglePercentilesMetrics||clusterName={}||clusterMetricsType={}\"\n                         + \"percentilesType={}||startTime={}||endTime={}\",\n                clusterName, clusterMetricsType, percentilesType, startTime, endTime, e);\n            return resultMap;\n        }\n\n        return resultMap;\n    }\n\n    /**\n     * 获取物理集群其他统计信息\n     */\n    public <T> List<T> getAggClusterPhyMetrics(String clusterName,long clusterType, String aggType, Long startTime, Long endTime,\n                                               Class<T> clazz) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        long intervalTime = endTime - startTime;\n\n        String interval = MetricsUtils.getInterval(intervalTime);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_METRICS_BY_RANGE_AND_INTERVAL,\n            clusterName,clusterType, startTime, endTime, interval, buildAggsDSL(clazz, aggType));\n\n        return gatewayClient.performRequest(metadataClusterName, realIndexName, TYPE, dsl,\n            (ESQueryResponse response) -> fetchAggClusterPhyMetrics(response, clazz), 3);\n    }\n\n    /**\n     * 获取集群分片总数\n     *\n     * @param cluster 集群\n     * @return {@code Long}\n     */\n    public Long getClustersShardTotal(String cluster) throws ESOperateException {\n        Long value = null;\n        int tryTimes = 3;\n        do {\n            value = Optional.ofNullable(this.getDirectResponse(cluster, \"Get\", GET_CLUSTER_STATS))\n                .filter(directResponse -> directResponse.getRestStatus() == RestStatus.OK\n                                          && StringUtils.isNotBlank(directResponse.getResponseContent()))\n                .map(DirectResponse::getResponseContent).map(JSON::parseObject).map(json -> json.getJSONObject(INDICES))\n                .map(json -> json.getJSONObject(SHARDS)).map(json -> json.getLong(TOTAL)).orElse(null);\n        } while (tryTimes-- > 0 && Objects.isNull(value));\n\n        return Objects.isNull(value) ? 0L : value;\n    }\n\n    /**\n     * 获取pending task 数量\n     *\n     * @param cluster 集群\n     * @return {@code Long}\n     */\n    public Long getPendingTaskTotal(String cluster) throws ESOperateException {\n\n        Long value = null;\n        int tryTimes = 3;\n        do {\n            value = Optional.ofNullable(this.getDirectResponse(cluster, \"Get\", GET_PENDING_TASKS))\n                .filter(directResponse -> directResponse.getRestStatus() == RestStatus.OK\n                                          && StringUtils.isNotBlank(directResponse.getResponseContent()))\n                .map(DirectResponse::getResponseContent).map(JSON::parseObject).map(json -> json.getJSONArray(TASKS))\n                .filter(array -> !ObjectUtils.isEmpty(array)).map(json -> (long) json.size()).orElse(null);\n        } while (tryTimes-- > 0 && Objects.isNull(value));\n        return Objects.isNull(value) ? 0L : value;\n    }\n\n    /************************************************private**************************************************/\n\n    /**\n     * 构建单个分位类型的指标数据\n     * @param response            ES响应体\n     * @param clusterMetricsType  指标类型\n     * @param aggType             聚合类型\n     * @return  Map<Long, Double>   time ——> value\n     */\n    private Map<Long, Double> fetchAggSinglePercentilesMetrics(ESQueryResponse response, String clusterMetricsType,\n                                                               String aggType) {\n        Map<Long, Double> timeSlip2ValueMap = Maps.newHashMap();\n        if (null == response || null == response.getAggs()) {\n            return timeSlip2ValueMap;\n        }\n\n        Map<String, ESAggr> esAggrMap = response.getAggs().getEsAggrMap();\n        List<Long> keys = new ArrayList<>();\n        if (null != esAggrMap && null != esAggrMap.get(HIST)) {\n            esAggrMap.get(HIST).getBucketList().forEach(r -> {\n                //获取时间戳\n                long timeSlip = 0;\n                if (null != r.getUnusedMap() && null != r.getUnusedMap().get(KEY)) {\n                    timeSlip = Long.valueOf(r.getUnusedMap().get(KEY).toString());\n                }\n                keys.add(timeSlip);\n                timeSlip2ValueMap.put(timeSlip, 0d);\n                //获取聚合值\n                if (null != r.getAggrMap() && null != r.getAggrMap().get(clusterMetricsType)\n                    && null != r.getAggrMap().get(clusterMetricsType).getUnusedMap().get(VALUE)) {\n                    double aggCal = Double\n                        .parseDouble(r.getAggrMap().get(clusterMetricsType).getUnusedMap().get(VALUE).toString());\n                    if (aggCal > 0) {\n                        timeSlip2ValueMap.put(timeSlip, aggCal);\n                    }\n                }\n            });\n        }\n\n        return timeSlip2ValueMap;\n    }\n\n    /**\n     * {\n     *   \"size\": 1,\n     *   \"sort\": [\n     *     {\n     *       \"timestamp\": {\n     *         \"order\": \"DESC\"\n     *       }\n     *     }\n     *   ]\n     * }\n     * @param cluster\n     */\n    public Long getTimeDifferenceBetweenNearestPointAndNow(String cluster) {\n        long startTime = System.currentTimeMillis();\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, startTime);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TIME_DIFFERENCE_BETWEEN_NEAREST_POINT_AND_NOW,cluster);\n        return gatewayClient.performRequest(metadataClusterName, realIndexName, TYPE, dsl,\n                (ESQueryResponse response) -> getNearestTime(response), 3);\n    }\n\n    private Long getNearestTime(ESQueryResponse response) {\n        if (null == response) {\n            return 0L;\n        }\n        List<ESHit> hits = Optional.ofNullable(response.getHits().getHits()).orElse(new ArrayList<ESHit>());\n        return hits.stream().map(esHit -> esHit.getSource()).filter(Objects::nonNull)\n                .map(source -> ((JSONObject) source).getLong(\"timestamp\")).findFirst().orElse(0L);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/stats/AriusStatsClusterTaskInfoESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.TopMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ESClusterTaskDetail;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusStatsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ESConstant;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHits;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport java.util.Optional;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.*;\n\n/**\n * @author didi\n * @date 2022-01-13 3:26 下午\n */\n@Component\npublic class AriusStatsClusterTaskInfoESDAO extends BaseAriusStatsESDAO {\n\n    public static final String            RUNNING_TIME = \"runningTime\";\n    private static final FutureUtil<Void> futureUtil   = FutureUtil.init(\"AriusStatsClusterTaskInfoESDAO\", 10, 10, 500);\n\n    @PostConstruct\n    public void init() {\n        super.indexName = dataCentreUtil.getAriusStatsClusterTaskInfo();\n        BaseAriusStatsESDAO.register(AriusStatsEnum.TASK_INFO, this);\n    }\n\n    public Map<String, Double> getTaskCostMinAvgAndPercentiles(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_TASK_REAL_TIME_AVG_AND_PERCENT,\n            cluster, NOW_2M, NOW_1M, RUNNING_TIME, RUNNING_TIME);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, cluster, realIndex, TYPE, dsl,\n            this::getAvgAndPercentilesFromESQueryResponse, 3);\n    }\n\n    public Map<String, Double> getTaskCostMinAvgAndPercentilesWithNodes(List<String> nodes,String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_LOGIC_TASK_REAL_TIME_AVG_AND_PERCENT,\n                JSON.toJSONString(nodes), NOW_2M, NOW_1M, RUNNING_TIME, RUNNING_TIME);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, cluster, realIndex, TYPE, dsl,\n                this::getAvgAndPercentilesFromESQueryResponse, 3);\n    }\n\n    public long getTaskCount(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_TASK_COUNT, cluster, NOW_2M, NOW_1M);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, cluster, realIndex, TYPE, dsl,\n            response -> Optional.ofNullable(response).map(ESQueryResponse::getHits)\n\n                .map(ESHits::getUnusedMap).map(map -> map.getOrDefault(ESConstant.HITS_TOTAL, \"0\").toString())\n                .map(Long::parseLong).orElse(0L),\n            3);\n    }\n\n    /**\n     * 获取最新时间间隔（NOW_1M ~ NOW_2M）集群各个节点的总任务耗时\n     * @param cluster 集群名称\n     * @return  map key:节点名称 value 节点任务耗时\n     */\n    public Map<String/*节点名称*/, Double/*值*/> getClusterNodesTaskTotalCost(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_NODES_TASK_COST, cluster, NOW_2M,\n            NOW_1M, clusterMaxNum);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, cluster, realIndex, TYPE, dsl, s -> {\n\n            Map<String/*节点名称*/, Double/*值*/> node2TotalTaskCostMap = Maps.newHashMap();\n            if (null == s) {\n                return node2TotalTaskCostMap;\n            }\n            if (null == s.getAggs()) {\n                return node2TotalTaskCostMap;\n            }\n            if (null == s.getAggs().getEsAggrMap()) {\n                return node2TotalTaskCostMap;\n            }\n            if (null == s.getAggs().getEsAggrMap().get(HIST)) {\n                return node2TotalTaskCostMap;\n            }\n            if (CollectionUtils.isEmpty(s.getAggs().getEsAggrMap().get(HIST).getBucketList())) {\n                return node2TotalTaskCostMap;\n            }\n\n            List<ESBucket> bucketList = s.getAggs().getEsAggrMap().get(HIST).getBucketList();\n            for (ESBucket esBucket : bucketList) {\n                // build key\n                Map<String, Object> unusedMap = esBucket.getUnusedMap();\n                if (MapUtils.isEmpty(unusedMap)) {\n                    continue;\n                }\n\n                String key = null == unusedMap.get(KEY) ? null : unusedMap.get(KEY).toString();\n                if (null == key) {\n                    continue;\n                }\n\n                // build value\n                Map<String, ESAggr> aggrMap = esBucket.getAggrMap();\n                if (MapUtils.isNotEmpty(aggrMap) && null != aggrMap.get(HIST)\n                    && null != aggrMap.get(HIST).getUnusedMap().get(VALUE)) {\n                    Double value = Double.valueOf(aggrMap.get(HIST).getUnusedMap().get(VALUE).toString());\n                    node2TotalTaskCostMap.put(key, value);\n                    continue;\n                }\n\n                node2TotalTaskCostMap.put(key, 0d);\n            }\n\n            return node2TotalTaskCostMap;\n        }, 3);\n    }\n\n    /**\n     *  获取最新时间分片中指标数值前TopN的节点名称\n     *  如果延迟后的最新时间分片的指标值为null，最新时间迭代 - 1, 直到不为空, 迭代上限为3次。\n     *\n     * @param clusterPhyName   集群名称\n     * @param metricsTypes     指标类型\n     * @param topNu            topN\n     * @param aggTypes          聚合类型\n     * @param esNodesMaxNum    聚合节点数量最大值（agg bucket number）\n     * @param startTime        开始时间\n     * @param endTime          结束时间\n     * @return\n     */\n    private List<TopMetrics> getTopNNodeMetricsInfo(String clusterPhyName, List<String> metricsTypes, Integer topNu,\n                                                    List<String> aggTypes, int esNodesMaxNum, Long startTime,\n                                                    Long endTime) {\n\n        int retryTime = 0;\n        List<VariousLineChartMetrics> variousLineChartMetrics = new ArrayList<>();\n        do {\n            Long timePoint = getHasDataTime(clusterPhyName, startTime, endTime,\n                DslsConstant.GET_HAS_CLUSTER_NODE_TASK_DATA_TIME);\n            //没有数据则提前终止\n            if (null == timePoint) {\n                break;\n            }\n\n            Tuple<Long, Long> firstInterval = MetricsUtils.getSortInterval(endTime - startTime, timePoint);\n            long startTimeForOneInterval = firstInterval.getV1();\n            long endTimeForOneInterval = firstInterval.getV2();\n\n            String interval = MetricsUtils.getInterval(endTime - startTime);\n\n            String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_CLUSTER_NODE_TASK_INFO,\n                clusterPhyName, startTimeForOneInterval, endTimeForOneInterval, esNodesMaxNum, interval,\n                buildAggDSL(metricsTypes, aggTypes));\n\n            String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTimeForOneInterval,\n                endTimeForOneInterval);\n\n            variousLineChartMetrics = gatewayClient.performRequestWithRouting(metadataClusterName, clusterPhyName,\n                realIndexName, TYPE, dsl, s -> fetchMultipleAggMetrics(s, null, metricsTypes, topNu), 3);\n        } while (retryTime++ > 3 && CollectionUtils.isEmpty(variousLineChartMetrics));\n\n        return variousLineChartMetrics.stream().map(this::buildTopMetrics).collect(Collectors.toList());\n    }\n\n    public String buildAggDSL(List<String> metrics, List<String> aggTypes) {\n        JSONObject jsonObject = new JSONObject();\n        for (int i = 0; i < metrics.size(); i++) {\n            JSONObject sub = new JSONObject();\n            jsonObject.put(metrics.get(i), sub);\n            JSONObject subSub = new JSONObject();\n            sub.put(aggTypes.get(i) == null ? DEFAULT_AGG : aggTypes.get(i), subSub);\n            subSub.put(FIELD, METRICS + metrics.get(i));\n        }\n        return jsonObject.toString();\n    }\n\n    /**\n     * 获取多个节点折线图指标信息\n     *\n     * @param clusterPhyName 集群名称\n     * @param metricsTypes        指标类型\n     * @param topNu          top\n     * @param aggTypes        聚合类型\n     * @param startTime      开始时间\n     * @param endTime        结束时间\n     * @return List<VariousLineChartMetrics>\n     */\n    public List<VariousLineChartMetrics> getTopNNodeAggMetrics(String clusterPhyName, List<String> metricsTypes,\n                                                               Integer topNu, List<String> aggTypes, Long startTime,\n                                                               Long endTime) {\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n        //获取TopN指标节点名称信息\n        List<TopMetrics> topNIndexMetricsList = getTopNNodeMetricsInfo(clusterPhyName, metricsTypes, topNu, aggTypes,\n            esNodesMaxNum, startTime, endTime);\n\n        //构建多个指标TopN数据\n        for (TopMetrics topMetrics : topNIndexMetricsList) {\n            List<String> correspondenceAggType = Lists\n                .newArrayList(aggTypes.get(metricsTypes.indexOf(topMetrics.getType())));\n            futureUtil.runnableTask(() -> buildTopNSingleMetricsForNode(buildMetrics, clusterPhyName,\n                correspondenceAggType, esNodesMaxNum, startTime, endTime, topMetrics));\n        }\n        futureUtil.waitExecute();\n\n        return buildMetrics;\n    }\n\n    private void buildTopNSingleMetricsForNode(List<VariousLineChartMetrics> buildMetrics, String clusterPhyName,\n                                               List<String> aggTypes, int esNodesMaxNum, Long startTime, Long endTime,\n                                               TopMetrics topMetrics) {\n        String topNameStr = null;\n        if (CollectionUtils.isNotEmpty(topMetrics.getTopNames())) {\n            topNameStr = buildTopNameStr(topMetrics.getTopNames());\n        }\n\n        if (StringUtils.isBlank(topNameStr)) {\n            return;\n        }\n\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n        List<String> metricsKeys = Lists.newArrayList(topMetrics.getType());\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_CLUSTER_TOP_NODE_TASK_INFO,\n            clusterPhyName, topNameStr, startTime, endTime, esNodesMaxNum, interval, startTime, endTime,\n            buildAggDSL(metricsKeys, aggTypes));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        List<VariousLineChartMetrics> variousLineChartMetrics = gatewayClient.performRequestWithRouting(\n            metadataClusterName, clusterPhyName, realIndexName, TYPE, dsl,\n            s -> fetchMultipleAggMetrics(s, null, metricsKeys, null), 3);\n        buildMetrics.addAll(variousLineChartMetrics);\n    }\n\n    /**\n     * 获取单个指标信息\n     *\n     * @param clusterPhyName    集群名称\n     * @param metrics           指标类型\n     * @param nodeName          节点名称\n     * @param aggTypes           聚合类型\n     * @param startTime         开始时间\n     * @param endTime           结束时间\n     * @return  List<VariousLineChartMetrics>\n     */\n    public List<VariousLineChartMetrics> getAggClusterPhySingleNodeMetrics(String clusterPhyName, List<String> metrics,\n                                                                           String nodeName, List<String> aggTypes,\n                                                                           long startTime, long endTime) {\n\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_CLUSTER_SINGLE_NODE_TASK_INFO,\n            clusterPhyName, nodeName, startTime, endTime, interval, startTime, endTime, buildAggDSL(metrics, aggTypes));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, clusterPhyName, realIndexName, TYPE, dsl,\n            s -> fetchSingleAggMetrics(s, metrics, nodeName), 3);\n    }\n\n    public List<ESClusterTaskDetail> getTaskDetailByNode(String cluster, String node, long startTime, long endTime) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_SINGLE_NODE_TASK_DETAIL_INFO,\n            cluster, node, startTime, endTime);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, cluster, realIndex, TYPE, dsl,\n            this::buildTaskDetailInfo, 3);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/stats/AriusStatsDashBoardInfoESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.DashboardTopMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.list.MetricList;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.list.MetricListContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.ClusterPhyHealthMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusStatsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricListTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricOtherTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricTopTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.OneLevelTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHit;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHits;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.FIELD;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.DashBoardMetricTopTypeEnum.listNoNegativeMetricTypes;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.routing.ESRoutingConstant.CLUSTER_PHY_HEALTH_ROUTING;\n\n@Component\npublic class AriusStatsDashBoardInfoESDAO extends BaseAriusStatsESDAO {\n    private static final FutureUtil<Void> FUTURE_UTIL = FutureUtil.init(\"AriusStatsDashBoardInfoESDAO\", 10, 10, 500);\n    public static final String            GTE         = \"gte\";\n    public static final String            CLUSTER     = \"cluster\";\n    public static final String            EMPTY_STR   = \"\";\n    public static final String            INDEX_COUNT = \"indexCount\";\n\n\n\n    @PostConstruct\n    public void init() {\n        super.indexName = dataCentreUtil.getAriusStatsDashBoardInfo();\n        BaseAriusStatsESDAO.register(AriusStatsEnum.DASHBOARD_INFO, this);\n    }\n\n    /**\n     * 获取dashboard大盘list列表类异常指标信息 针对dashboard_status 中 的flag字段\n     * @see                  DashBoardMetricListTypeEnum\n     * @param oneLevelType  一级指标 支持cluster node index template thread\n     * @param metricsType   二级指标\n     * @param sources       _source内容\n     * @param flag          是否为异常列表 true 是， false 否\n     * @param sortType      排序类型   asc decs\n     * @return              List<MetricList>\n     */\n    public MetricList fetchListFlagMetric(String oneLevelType, String metricsType,String  sortItem,String valueMetric, List<String> sources, String flag,\n                                          String sortType) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.FETCH_LIST_FLAG_METRIC, oneLevelType, sortItem,sortType,\n                JSON.toJSONString(sources), oneLevelType, metricsType, flag, oneLevelType, NOW_6M, NOW_1M);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n            s -> fetchRespMetrics(s, oneLevelType, metricsType, /*是否需要设置指标具体值*/true,valueMetric), 3);\n    }\n\n\n    /**\n     * 获取dashboard大盘list列表指标信息\n     * @see                  DashBoardMetricListTypeEnum\n     * @param oneLevelType  一级指标 支持cluster node index template thread\n     * @param metricsType   二级指标\n     * @param aggType       聚合类型\n     * @param sortType      排序类型   asc decs\n     * @return              List<MetricList>\n     */\n    public MetricList fetchListValueMetrics(String oneLevelType, String metricsType, String aggType, String sortType) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.FETCH_LIST_VALUE_METRIC, oneLevelType,\n            oneLevelType, oneLevelType, oneLevelType, metricsType, oneLevelType, NOW_6M, NOW_1M, oneLevelType,\n            metricsType, oneLevelType, metricsType, sortType);\n\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n            s -> fetchRespMetrics(s, oneLevelType, metricsType, /*是否需要设置指标具体值*/true,metricsType), 3);\n    }\n\n    /**\n     * 处理返回结果\n     *\n     * @param s              返回结果\n     * @param oneLevelType   一级指标项\n     * @param metricsType    二级指标项\n     * @param hasGetValue    是否需要设置指标项值\n     * @param valueMetric    值的字段\n     * @return               MetricList\n     */\n    private MetricList fetchRespMetrics(ESQueryResponse s, String oneLevelType, String metricsType,\n                                        boolean hasGetValue,String valueMetric) {\n        MetricList metricList = new MetricList();\n        metricList.setType(metricsType);\n        List<MetricListContent> metricListContents = Lists.newArrayList();\n        // 去重列表\n        List<String> repeatList = Lists.newArrayList();\n        ESHits hits = s.getHits();\n        if (null != hits && CollectionUtils.isNotEmpty(hits.getHits())) {\n            for (ESHit hit : hits.getHits()) {\n                if (null != hit.getSource() && null != ((JSONObject) hit.getSource()).getJSONObject(oneLevelType)\n                    && null != ((JSONObject) hit.getSource()).getJSONObject(oneLevelType).getString(CLUSTER)\n                    && null != ((JSONObject) hit.getSource()).getJSONObject(oneLevelType).getString(oneLevelType)){\n\n                    JSONObject healthMetricsJb = ((JSONObject) hit.getSource()).getJSONObject(oneLevelType);\n                    String cluster = healthMetricsJb.getString(CLUSTER);\n                    String metricsTypeValue/*node template index thread-pool*/ = healthMetricsJb\n                        .getString(oneLevelType);\n                    if (AriusObjUtils.isBlank(metricsTypeValue)) {\n                        continue;\n                    }\n\n                    // 去重处理\n                    String repeatKey = cluster + \"@\" + metricsTypeValue;\n                    if (repeatList.contains(repeatKey)) {\n                        continue;\n                    } else {\n                        repeatList.add(repeatKey);\n                    }\n\n                    MetricListContent metricListContent = new MetricListContent();\n                    metricListContent.setClusterPhyName(cluster);\n                    metricListContent.setName(metricsTypeValue);\n\n                    // 是否需要指标具体值\n                    if (hasGetValue\n                            && StringUtils.isNotBlank(valueMetric)\n                            && null != ((JSONObject) hit.getSource()).getJSONObject(oneLevelType).getString(valueMetric)) {\n                        Double value = healthMetricsJb.getDouble(valueMetric);\n                        value = Double.valueOf(String.format(\"%.2f\", value));\n                        metricListContent.setValue(value);\n                    }\n                    metricListContents.add(metricListContent);\n                }\n            }\n        }\n\n        metricList.setMetricListContents(metricListContents);\n        metricList.setCurrentTime(System.currentTimeMillis());\n        return metricList;\n    }\n    \n    \n     /**\n     * 处理阈值指标返回结果\n     *\n     * @param s              返回结果\n     * @param oneLevelType   一级指标项\n     * @param metricsType    二级指标项\n     * @param valueName    值名称\n     * @return               MetricList\n     */\n    private MetricList fetchRespThresholdsMetrics(ESQueryResponse s, String oneLevelType, String metricsType,\n                                        String valueName) {\n        MetricList metricList = new MetricList();\n        metricList.setType(metricsType);\n        List<MetricListContent> metricListContents = Lists.newArrayList();\n        // 去重列表\n        List<String> repeatList = Lists.newArrayList();\n        ESHits hits = s.getHits();\n        if (null != hits && CollectionUtils.isNotEmpty(hits.getHits())) {\n            for (ESHit hit : hits.getHits()) {\n                if (null != hit.getSource() && null != ((JSONObject) hit.getSource()).getJSONObject(oneLevelType)\n                    && null != ((JSONObject) hit.getSource()).getJSONObject(oneLevelType).getString(CLUSTER)\n                    && null != ((JSONObject) hit.getSource()).getJSONObject(oneLevelType).getString(oneLevelType)) {\n                \n                    JSONObject healthMetricsJb = ((JSONObject) hit.getSource()).getJSONObject(oneLevelType);\n                    String cluster = healthMetricsJb.getString(CLUSTER);\n                    String metricsTypeValue/*node template index thread-pool*/ = healthMetricsJb.getString(\n                            oneLevelType);\n                    if (AriusObjUtils.isBlank(metricsTypeValue)) {\n                        continue;\n                    }\n                \n                    // 去重处理\n                    String repeatKey = cluster + \"@\" + metricsTypeValue;\n                    if (repeatList.contains(repeatKey)) {\n                        continue;\n                    } else {\n                        repeatList.add(repeatKey);\n                    }\n                \n                    MetricListContent metricListContent = new MetricListContent();\n                    metricListContent.setClusterPhyName(cluster);\n                    metricListContent.setName(metricsTypeValue);\n                \n                    // 是否需要指标具体值\n                    Double value = 0D;\n                    if (healthMetricsJb.containsKey(valueName)) {\n                        value = healthMetricsJb.getDouble(valueName);\n                    }\n                    value = Double.valueOf(String.format(\"%.2f\", value));\n                    metricListContent.setValue(value);\n                \n                    metricListContents.add(metricListContent);\n                }\n            }\n        }\n    \n        metricList.setMetricListContents(metricListContents);\n        metricList.setCurrentTime(System.currentTimeMillis());\n        return metricList;\n    }\n\n    /**\n     * 获取dashboard大盘TopN指标信息\n     * @see   DashBoardMetricTopTypeEnum\n     * @param oneLevelType        目前仅支持 cluster node template index\n     * @param metricsTypes        指标类型列表\n     * @param topNu               5 10 15 20\n     * @param aggType             单个间隔内聚合类型\n     * @param startTime           开始时间\n     * @param endTime             结束时间\n     * @return\n     */\n    public List<VariousLineChartMetrics> fetchTopMetric(String oneLevelType, List<String> metricsTypes, Integer topNu,\n                                                        String aggType, Long startTime, Long endTime) {\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n        //获取TopN指标节点/模板/索引/等名称信息\n        List<DashboardTopMetrics> dashboardTopMetricsList = getTopMetricsForDashboard(oneLevelType, metricsTypes, topNu,\n            aggType, esNodesMaxNum, startTime, endTime);\n\n        //构建多个指标TopN数据\n        for (DashboardTopMetrics dashboardTopMetrics : dashboardTopMetricsList) {\n            FUTURE_UTIL.runnableTask(() -> buildTopNSingleMetrics(buildMetrics, oneLevelType, aggType, clusterMaxNum,\n                startTime, endTime, dashboardTopMetrics));\n        }\n        FUTURE_UTIL.waitExecute();\n\n        return buildMetrics;\n    }\n\n    /**\n     * 获取dashboard大盘健康状态信息\n     * @see        DashBoardMetricOtherTypeEnum\n     * @return     ClusterPhyHealthMetrics\n     */\n    public ClusterPhyHealthMetrics fetchClusterHealthInfo() {\n        String key = DashBoardMetricOtherTypeEnum.CLUSTER_HEALTH.getType();\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.FETCH_CLUSTER_HEALTH_INFO, key, key);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, CLUSTER_PHY_HEALTH_ROUTING, realIndex, TYPE,\n            dsl, s -> {\n                ClusterPhyHealthMetrics clusterPhyHealthMetrics = new ClusterPhyHealthMetrics();\n                if (null == s) {\n                    LOGGER.warn(\n                        \"class=AriusStatsDashBoardInfoESDAO||method=fetchClusterHealthInfo||msg=response is null\");\n                    return clusterPhyHealthMetrics;\n                }\n\n                try {\n                    ESHits hits = s.getHits();\n                    if (null != hits && CollectionUtils.isNotEmpty(hits.getHits())) {\n                        for (ESHit hit : hits.getHits()) {\n                            if (null != hit.getSource()) {\n                                JSONObject source = (JSONObject) hit.getSource();\n                                JSONObject healthMetricsJb = source.getJSONObject(key);\n                                return null == healthMetricsJb ? clusterPhyHealthMetrics\n                                    : ConvertUtil.obj2ObjByJSON(healthMetricsJb, ClusterPhyHealthMetrics.class);\n                            }\n                        }\n                    }\n                } catch (Exception e) {\n                    LOGGER.error(\n                        \"class=AriusStatsDashBoardInfoESDAO||method=fetchClusterHealthInfo||sumKey={}||value={}||response={}\",\n                        e);\n                }\n                return clusterPhyHealthMetrics;\n            }, 3);\n    }\n\n    /****************************************************private*************************************************************/\n    /**\n     *  获取最新时间分片中指标数值前TopN的节点名称\n     *  如果延迟后的最新时间分片的指标值为null，最新时间迭代 - 1, 直到不为空, 迭代上限为3次。\n     *\n     *\n     * @param oneLevelType     目前仅支持 cluster node template index\n     * @param metricsTypes     指标类型\n     * @param topNu            topN\n     * @param aggType          聚合类型\n     * @param dashboardClusterMaxNum    聚合节点数量最大值（agg bucket number）\n     * @param startTime        开始时间\n     * @param endTime          结束时间\n     * @return\n     */\n    private List<DashboardTopMetrics> getTopMetricsForDashboard(String oneLevelType, List<String> metricsTypes,\n                                                                Integer topNu, String aggType,\n                                                                int dashboardClusterMaxNum, Long startTime,\n                                                                Long endTime) {\n        // 获取有数据的第一个时间点\n        Long timePoint = getDashboardHasDataTime(oneLevelType, startTime, endTime);\n        // 查询剪支\n        if (null == timePoint) {\n            return Lists.newArrayList();\n        }\n\n        Tuple<Long, Long> firstInterval = MetricsUtils.getSortInterval(endTime - startTime, timePoint);\n        long startInterval = firstInterval.getV1();\n        long endInterval = firstInterval.getV2();\n\n        // 注意这里不用MetricsUtils.getIntervalForDashBoard\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startInterval, endInterval);\n\n        Tuple<List<String>/*普通指标列表*/, List<String>/*指标值为非负类型指标列表*/> commonAndNoNegativeMetricsTuple = getCommonMetricsAndNoNegativeMetrics(\n            metricsTypes);\n        List<String> commonMetricTypeList = commonAndNoNegativeMetricsTuple.getV1();\n        List<String> noNegativeMetricsList = commonAndNoNegativeMetricsTuple.getV2();\n        List<DashboardTopMetrics> finalTopMetrics = Lists.newArrayList();\n\n        // 处理普通指标\n        if (CollectionUtils.isNotEmpty(commonMetricTypeList)) {\n            String aggsDsl = dynamicBuildDashboardAggsDSLForTop(oneLevelType, commonMetricTypeList, aggType);\n            String dsl = getFinalDslByOneLevelType(oneLevelType, startInterval, endInterval, dashboardClusterMaxNum,\n                interval, aggsDsl);\n            if (null == dsl) {\n                return finalTopMetrics;\n            }\n\n            List<VariousLineChartMetrics> variousLineChartMetrics = gatewayClient.performRequest(metadataClusterName,\n                realIndexName, TYPE, dsl, s -> fetchMultipleAggMetrics(s, oneLevelType, commonMetricTypeList, topNu),\n                3);\n\n            variousLineChartMetrics.stream().map(this::buildDashboardTopMetrics).forEach(finalTopMetrics::add);\n        }\n\n        // 处理非负类型指标\n        if (CollectionUtils.isNotEmpty(noNegativeMetricsList)) {\n            // 对非非负类型指标指标进行agg_filter模式过滤\n            String aggsDsl = dynamicBuildDashboardNoNegativeAggsDSLForTop(oneLevelType, noNegativeMetricsList, aggType);\n            String dsl = getFinalDslByOneLevelType(oneLevelType, startInterval, endInterval, dashboardClusterMaxNum,\n                interval, aggsDsl);\n            if (null == dsl) {\n                return finalTopMetrics;\n            }\n\n            List<VariousLineChartMetrics> variousLineChartMetrics = gatewayClient.performRequest(metadataClusterName,\n                realIndexName, TYPE, dsl,\n                s -> fetchMultipleNoNegativeAggMetrics(s, oneLevelType, noNegativeMetricsList, topNu), 3);\n\n            variousLineChartMetrics.stream().map(this::buildDashboardTopMetrics).forEach(finalTopMetrics::add);\n        }\n        return finalTopMetrics;\n    }\n\n    DashboardTopMetrics buildDashboardTopMetrics(VariousLineChartMetrics variousLineChartMetrics) {\n        DashboardTopMetrics dashboardTopMetrics = new DashboardTopMetrics();\n        dashboardTopMetrics.setType(variousLineChartMetrics.getType());\n        List<Tuple<String/*集群名称*/, String/*索引名称/节点名称/集群名称/模板名称*/>> dashboardTopInfo = Lists.newArrayList();\n        for (MetricsContent metricsContent : variousLineChartMetrics.getMetricsContents()) {\n            Tuple<String/*集群名称*/, String/*索引名称/节点名称/集群名称/模板名称*/> cluster2NameTuple = new Tuple<>();\n            String cluster = metricsContent.getCluster();\n            // 兼容老版本, 上游查询补丁\n            if (!AriusObjUtils.isBlank(cluster)) {\n                cluster2NameTuple.setV1(cluster);\n            } else {\n                cluster2NameTuple.setV1(metricsContent.getName());\n            }\n\n            cluster2NameTuple.setV2(metricsContent.getName());\n            dashboardTopInfo.add(cluster2NameTuple);\n        }\n\n        dashboardTopMetrics.setDashboardTopInfo(dashboardTopInfo);\n        return dashboardTopMetrics;\n    }\n\n    /**\n     * 由于非负型指标的结果不能再<em>query</em>条件进行<em>filter</em>过滤，问题是会导致召回结果数量不正常，\n     * 这里使用<em>agg</em>的<em>filter</em>模式进行构建，同时可以拉去更多的召回数据，若后续对结果进行处理时，\n     * 可参照{#fetchMultipleNoNegativeAggMetrics(com.didiglobal.logi.elasticsearch.client.response.query.query.ESQueryResponse, java.lang.String, java.util.List, java.lang.Integer)(ESQueryResponse, List, Integer)}\n     * 的方法进行结果处理\n     * agg:\n     *             \"gatewaySucPer\": {\n     *               \"filter\": {\n     *                 \"range\": {\n     *                   \"cluster.gatewaySucPer\": {\n     *                     \"gte\": 0\n     *                   }\n     *                 }\n     *               },\n     *               \"aggs\": {\n     *                 \"gatewaySucPer\": {\n     *                   \"avg\": {\n     *                     \"field\": \"cluster.gatewaySucPer\",\n     *                     \"missing\": 0\n     *                   }\n     *                 }\n     *               }\n     *             }\n     * @param oneLevelType\n     * @param noNegativeMetricsList\n     * @param aggType 只支持：avg、sum、avg等统计类型指标\n     * @return\n     */\n    private String dynamicBuildDashboardNoNegativeAggsDSLForTop(String oneLevelType, List<String> noNegativeMetricsList,\n                                                                String aggType) {\n        List<String> dslList = Lists.newArrayList();\n        for (String field : noNegativeMetricsList) {\n            final String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_FILTER_FRAGMENT, field,\n                oneLevelType, field, GTE, 0, field, aggType, oneLevelType, field);\n            dslList.add(dsl);\n\n        }\n        return String.join(\",\", dslList);\n    }\n\n    /**\n     * 获取普通指标列表 非负类型指标列表(@link CLUSTER_GATEWAY_FAILED_PER CLUSTER_GATEWAY_SUC_PER)\n     *\n     * @param metricsTypes 二级指标类型\n     * @return Tuple\n     */\n    private Tuple<List<String>/*普通指标列表*/, List<String>/*指标值为非负类型指标列表*/> getCommonMetricsAndNoNegativeMetrics(List<String> metricsTypes) {\n        Tuple<List<String>, List<String>> noNegativeMetricsAndCommonMetricsTuple = new Tuple<>();\n        List<String> commonMetricTypeList = Lists.newArrayList();\n        List<String> noNegativeMetricTypeList = Lists.newArrayList();\n        // 处理非负值的指标类型\n        for (String metricsType : metricsTypes) {\n            if (listNoNegativeMetricTypes().contains(metricsType)) {\n                noNegativeMetricTypeList.add(metricsType);\n            } else {\n                commonMetricTypeList.add(metricsType);\n            }\n        }\n\n        noNegativeMetricsAndCommonMetricsTuple.setV1(commonMetricTypeList);\n        noNegativeMetricsAndCommonMetricsTuple.setV2(noNegativeMetricTypeList);\n        return noNegativeMetricsAndCommonMetricsTuple;\n    }\n\n    /**\n     * 根据一级指标类型构建最终查询dsl全文\n     * @param oneLevelType             一级指标类型\n     * @param startInterval            起始时刻\n     * @param endInterval              结束时刻\n     * @param dashboardClusterMaxNum   支持的聚合集群总量，平台集群量超出此数查询会异常\n     * @param interval                 agg聚合间隔类型 如1m, 5m 10m 等等\n     * @param aggsDsl                  动态构建的agg聚合子句\n     * @return  dsl全文\n     */\n    private String getFinalDslByOneLevelType(String oneLevelType, long startInterval, long endInterval,\n                                             int dashboardClusterMaxNum, String interval, String aggsDsl) {\n        // 获取 clusterThreadPoolQueue维度 相关全文dsl\n        if (OneLevelTypeEnum.CLUSTER_THREAD_POOL_QUEUE.getType().equals(oneLevelType)) {\n            return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_DASHBOARD_CLUSTER_TOP_NAME_INFO,\n                oneLevelType, startInterval, endInterval, oneLevelType, CLUSTER, dashboardClusterMaxNum, oneLevelType,\n                interval, aggsDsl);\n        }\n\n        // 获取 cluster维度 相关全文dsl\n        if (OneLevelTypeEnum.CLUSTER.getType().equals(oneLevelType)) {\n            return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_DASHBOARD_CLUSTER_TOP_NAME_INFO,\n                oneLevelType, startInterval, endInterval, oneLevelType, oneLevelType, dashboardClusterMaxNum,\n                oneLevelType, interval, aggsDsl);\n        }\n\n        // 获取 非cluster维度 相关全文dsl\n        if (OneLevelTypeEnum.listNoClusterOneLevelType().contains(oneLevelType)) {\n            return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_DASHBOARD_NO_CLUSTER_TOP_NAME_INFO,\n                oneLevelType, startInterval, endInterval, oneLevelType, oneLevelType, oneLevelType,\n                dashboardClusterMaxNum, oneLevelType, interval, aggsDsl);\n        }\n        return null;\n    }\n\n    /**\n     *\n     * @param oneLevelType     一级指标类型\n     * @param topClustersStr   top集群名称\n     * @param topNameStr       top名称 （索引名称、集群名称、节点名称、模板名称）\n     * @param startTime        开始时间\n     * @param endTime          结束时间\n     * @param dashboardClusterMaxNum   统计集群最大数量\n     * @param interval                 时间间隔\n     * @param aggsDsl                  聚合指标项\n     * @return\n     */\n    private String getFinalDslByOneLevelType(String oneLevelType, String topClustersStr, String topNameStr,\n                                             Long startTime, Long endTime, int dashboardClusterMaxNum, String interval,\n                                             String aggsDsl, String noNegativeStr) {\n\n        // 处理特殊类型dsl（如 clusterThreadPoolQueue）\n        if (OneLevelTypeEnum.CLUSTER_THREAD_POOL_QUEUE.getType().equals(oneLevelType)) {\n            return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOP_DASHBOARD_CLUSTER_AGG_METRICS_INFO,\n                noNegativeStr, oneLevelType, CLUSTER, topNameStr, oneLevelType, startTime, endTime, oneLevelType,\n                CLUSTER, dashboardClusterMaxNum, oneLevelType, interval, startTime, endTime, aggsDsl);\n        }\n\n        // 获取 cluster维度 相关全文dsl\n        if (OneLevelTypeEnum.CLUSTER.getType().equals(oneLevelType)) {\n            return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOP_DASHBOARD_CLUSTER_AGG_METRICS_INFO,\n                noNegativeStr, oneLevelType, oneLevelType, topNameStr, oneLevelType, startTime, endTime, oneLevelType,\n                oneLevelType, dashboardClusterMaxNum, oneLevelType, interval, startTime, endTime, aggsDsl);\n        }\n\n        // 获取 非cluster维度 相关全文dsl\n        if (OneLevelTypeEnum.listNoClusterOneLevelType().contains(oneLevelType)) {\n            return dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOP_DASHBOARD_NO_CLUSTER_AGG_METRICS_INFO,\n                noNegativeStr, oneLevelType, topClustersStr, oneLevelType, oneLevelType, topNameStr, oneLevelType,\n                startTime, endTime, oneLevelType, oneLevelType, oneLevelType, dashboardClusterMaxNum, oneLevelType,\n                interval, startTime, endTime, aggsDsl);\n        }\n        return null;\n    }\n\n    /**\n     * 构建单个TopN中的全量数据信息\n     * @param buildMetrics              需要构建的元数据\n     * @param oneLevelType              一级指标\n     * @param aggType                   聚合类型\n     * @param dashboardClusterMaxNum    dashboard允许最大的集群数\n     * @param startTime                 开始时间\n     * @param endTime                   结束时间\n     * @param dashboardTopMetrics       查询信息，需要取出的topN数据信息（包括topN的集群/模板/索引/等名称）\n     */\n    private void buildTopNSingleMetrics(List<VariousLineChartMetrics> buildMetrics, String oneLevelType, String aggType,\n                                        int dashboardClusterMaxNum, Long startTime, Long endTime,\n                                        DashboardTopMetrics dashboardTopMetrics) {\n        List<Tuple<String, String>> dashboardTopInfo = dashboardTopMetrics.getDashboardTopInfo();\n        // 获取最终topN集群列表\n        List<String> topDistinctClusters = dashboardTopInfo.stream().map(Tuple::getV1).filter(Objects::nonNull)\n            .distinct().collect(Collectors.toList());\n        String topClustersStr = CollectionUtils.isNotEmpty(topDistinctClusters) ? buildTopNameStr(topDistinctClusters)\n            : null;\n        if (StringUtils.isBlank(topClustersStr)) {\n            return;\n        }\n\n        // 获取最终topN节点/模板/索引列表\n        List<String> topDistinctNames = dashboardTopInfo.stream().map(Tuple::getV2).filter(Objects::nonNull).distinct()\n            .collect(Collectors.toList());\n        String topNameStr = CollectionUtils.isNotEmpty(topDistinctNames) ? buildTopNameStr(topDistinctNames) : null;\n        if (StringUtils.isBlank(topNameStr)) {\n            return;\n        }\n\n        String interval = MetricsUtils.getIntervalForDashBoard(endTime - startTime);\n        List<String> metricsKeys = Lists.newArrayList(dashboardTopMetrics.getType());\n        String noNegativeStr = EMPTY_STR;\n        if (listNoNegativeMetricTypes().contains(dashboardTopMetrics.getType())) {\n            noNegativeStr = buildTermNoNegativeDsl(dashboardTopMetrics.getType(), oneLevelType);\n        }\n        String aggsDsl = dynamicBuildDashboardAggsDSLForTop(oneLevelType, metricsKeys, aggType);\n        String dsl = getFinalDslByOneLevelType(oneLevelType, topClustersStr, topNameStr, startTime, endTime,\n            dashboardClusterMaxNum, interval, aggsDsl, noNegativeStr);\n        if (null == dsl) {\n            return;\n        }\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        List<VariousLineChartMetrics> variousLineChartMetrics = gatewayClient.performRequestWithRouting(\n            metadataClusterName, null, realIndexName, TYPE, dsl,\n            s -> fetchMultipleAggMetrics(s, oneLevelType, metricsKeys, null), 3);\n\n        // 过滤出有效指标项，解决不同集群存在相同节点/模板/索引名称的场景\n        filterValidMetricsInfo(variousLineChartMetrics, dashboardTopMetrics);\n\n        buildMetrics.addAll(variousLineChartMetrics);\n    }\n\n    /**\n     * { *     \"range\":{ *         “field”:{ * *             gte:0 *         } *     } * },\n     *\n     * @param type * @return {@link String}\n     */\n    private String buildTermNoNegativeDsl(String type, String oneLevelType) {\n        Map range = new HashMap<String, Map<String, Object>>() {\n            {\n                put(\"range\", new HashMap<String, Object>() {\n                    {\n                        put(String.format(\"%s.%s\", oneLevelType, type), new HashMap<String, Object>() {\n                            {\n                                put(\"gte\", 0);\n                            }\n                        });\n                    }\n                });\n            }\n        };\n        return String.format(\"%s,\", JSON.toJSONString(range));\n    }\n\n    /**\n     * 过滤出有效指标项，解决不同集群存在相同节点/模板/索引名称的场景\n     * @param variousLineChartMetrics    源数据信息\n     * @param dashboardTopMetrics        根据类中属性过滤条件\n     */\n    private void filterValidMetricsInfo(List<VariousLineChartMetrics> variousLineChartMetrics,\n                                        DashboardTopMetrics dashboardTopMetrics) {\n\n        for (VariousLineChartMetrics variousLineChartMetric : variousLineChartMetrics) {\n            if (!dashboardTopMetrics.getType().equals(variousLineChartMetric.getType())) {\n                return;\n            }\n\n            List<MetricsContent> metricsContents = variousLineChartMetric.getMetricsContents();\n            if (CollectionUtils.isEmpty(metricsContents)) {\n                return;\n            }\n\n            List<Tuple<String, String>> dashboardTopInfo = dashboardTopMetrics.getDashboardTopInfo();\n            List<String> validMetricInfo = Lists.newArrayList();\n            for (Tuple<String, String> cluster2NameTuple : dashboardTopInfo) {\n                String cluster = cluster2NameTuple.getV1();\n                String name = cluster2NameTuple.getV2();\n                validMetricInfo.add(CommonUtils.getUniqueKey(cluster, name));\n            }\n\n            List<MetricsContent> validMetricsContentList = Lists.newArrayList();\n            for (MetricsContent metricsContent : metricsContents) {\n                String cluster = metricsContent.getCluster();\n                String name = metricsContent.getName();\n                if (validMetricInfo.contains(CommonUtils.getUniqueKey(cluster, name))) {\n                    validMetricsContentList.add(metricsContent);\n                }\n            }\n            // 更新\n            variousLineChartMetric.setMetricsContents(validMetricsContentList);\n        }\n    }\n\n    /**\n     * 获取dashboard 指标信息中有数据的第一个时间点\n     * @param oneLevelType\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    private Long getDashboardHasDataTime(String oneLevelType, long startTime, long endTime) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_HAS_DASHBOARD_METRICS_DATA_TIME,\n            oneLevelType, oneLevelType, startTime, endTime, oneLevelType);\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndexName, TYPE, dsl, s -> {\n            ESHits hits = s.getHits();\n            if (null != hits && CollectionUtils.isNotEmpty(hits.getHits())) {\n                for (ESHit hit : hits.getHits()) {\n                    if (null != hit.getSource()) {\n                        JSONObject source = (JSONObject) hit.getSource();\n                        JSONObject healthMetricsJb = source.getJSONObject(oneLevelType);\n                        return null == healthMetricsJb ? null : healthMetricsJb.getLongValue(\"timestamp\");\n                    }\n                }\n            }\n            return null;\n        }, 3);\n    }\n\n    /**\n     * 对于topN场景, 动态构建agg子句\n     * \"cluster.indexingLatency\": {\n     *               \"max\": {\n     *                 \"field\": \"cluster.indexingLatency\"\n     *               }\n     *             },\n     *             \"cluster.searchLatency\": {\n     *               \"max\": {\n     *                 \"field\": \"cluster.searchLatency\"\n     *               }\n     *             }\n     *\n     * @param oneLevelType 一级指标类型\n     * @param metrics      二级指标列表\n     * @param aggType      聚合类型\n     * @return             StringText\n     */\n    private String dynamicBuildDashboardAggsDSLForTop(String oneLevelType, List<String> metrics, String aggType) {\n        metrics.add(INDEX_COUNT);\n        StringBuilder sb = new StringBuilder();\n\n        for (int i = 0; i < metrics.size(); i++) {\n            String metricName = metrics.get(i);\n            Map<String, String> aggsSubSubCellMap = Maps.newHashMap();\n            aggsSubSubCellMap.put(FIELD, oneLevelType + \".\" + metricName);\n\n            buildAggsDslMap(aggType, sb, metricName, aggsSubSubCellMap);\n            if (i != metrics.size() - 1) {\n                sb.append(\",\").append(\"\\n\");\n            }\n        }\n\n        return sb.toString();\n    }\n    \n    public MetricList fetchListThresholdsMetric(String oneLevelType, String metricsType, String valueName, String aggType, String flag, String sortType) {\n       \n       String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.FETCH_LIST_THRESHOLDS_METRIC, oneLevelType, sortType,\n               oneLevelType, oneLevelType, oneLevelType,oneLevelType,valueName, oneLevelType, metricsType, flag,\n               oneLevelType,NOW_6M, NOW_1M);\n\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n            s -> fetchRespThresholdsMetrics(s, oneLevelType, metricsType, /*是否需要设置指标具体值*/valueName), 3);\n    }\n    \n    public MetricList fetchListThresholdsSegmentNumMetric(String oneLevelType, String metricsType, String valueName,\n                                                          String aggType, String flag, String sortType) {\n       \n       String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.FETCH_LIST_THRESHOLDS_METRIC, oneLevelType, sortType,\n               oneLevelType, oneLevelType, oneLevelType,oneLevelType,valueName, oneLevelType, metricsType, flag,\n               oneLevelType,NOW_6M, NOW_1M);\n\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n            s -> fetchRespThresholdsMetrics(s, oneLevelType, metricsType, /*是否需要设置指标具体值*/valueName), 3);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/stats/AriusStatsIndexInfoESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.index.IndexRealTimeInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.TopMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.query.IndexNameQueryAvgRatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.stats.TemplateTpsMetricPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusStatsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHit;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHits;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.*;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyIndicesMetricsEnum.INDEXING_RATE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyIndicesMetricsEnum.QUERY_RATE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.MetricsConstant.INDEX;\n\n@Component\npublic class AriusStatsIndexInfoESDAO extends BaseAriusStatsESDAO {\n    /**\n     * 突增定义倍数 上个时间间隔请求数的两倍，\n     * 例子: 上一个时间间隔是 1000r/s  当前时间间隔是 2500 r/s 超过2000 则定义为突增\n     */\n    private static final String           SIZE_NUM             = \"sizeSum\";\n    private static final String           VALUE                = \"value\";\n    private static final String           VALUES               = \"values\";\n    private static final String           MAX_TPS              = \"max_tps\";\n    private static final String           GROUP_BY_TEMPLATE_ID = \"groupByTemplateId\";\n    private static final FutureUtil<Void> futureUtil           = FutureUtil.init(\"AriusStatsIndexInfoESDAO\", 10, 10,\n        100);\n    private static final long             ONE_MIN              = 60 * 1000;\n\n    @PostConstruct\n    public void init() {\n        super.indexName = dataCentreUtil.getAriusStatsIndexInfo();\n\n        BaseAriusStatsESDAO.register(AriusStatsEnum.INDEX_INFO, this);\n    }\n\n    /**\n     * 根据集群名称，获取集群[now-2m, now-1m]总的qps 在index维度汇总\n     * @param cluster\n     * @return\n     */\n    public double getClusterQps(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_REAL_TIME_TPS_QPS_INFO, cluster,\n            \"now-2m\", \"now-1m\", QUERY_RATE.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 根据集群名称，获取集群[now-2m, now-1m]总的tps\n     * @param cluster\n     * @return\n     */\n    public double getClusterTps(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_REAL_TIME_TPS_QPS_INFO, cluster,\n            \"now-2m\", \"now-1m\", INDEXING_RATE.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 根据模板名称和集群名称，获取模板的总大小(单位：byte)\n     * @param template\n     * @param cluster\n     * @return\n     */\n    public double getTemplateTotalSize(String template, String cluster) {\n        Long now = System.currentTimeMillis();\n        return getTemplateTotalSizeByTimeRange(template, cluster, now - 15 * ONE_MIN, now);\n    }\n\n    /**\n     * 查询模板一段时间访问内的最大容量\n     * @param template\n     * @param cluster\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    public double getTemplateTotalSizeByTimeRange(String template, String cluster, Long startTime, Long endTime) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TEMPLATE_TOTAL_SIZE_BY_TIME_RANGE, template,\n            cluster, startTime, endTime);\n        String realIndex = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, SIZE_NUM), 3);\n    }\n\n    /**\n     * 根据物理模板ID获取模板的总大小\n     * @param templateId\n     * @return\n     */\n    public double getTemplateTotalSize(Long templateId) {\n        Long now = System.currentTimeMillis();\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TEMPLATE_TOTAL_SIZE_BY_TEMPLATE_ID,\n            templateId, now - 15 * ONE_MIN, now);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, SIZE_NUM), 3);\n    }\n\n    /**\n     * 根据逻辑模板ID，获取模板的总大小(单位：byte)，主备情况下，主备索引总量都会统计\n     * @param logicTemplateId\n     * @return\n     */\n    public double getLogicTemplateTotalSize(Long logicTemplateId) {\n        Long now = System.currentTimeMillis();\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_LOGIC_TEMPLATE_TOTAL_SIZE_BY_TEMPLATE_ID,\n            logicTemplateId, now - 15 * ONE_MIN, now);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, SIZE_NUM), 3);\n    }\n\n    /**\n     * 获取索引模板一段时间的最大索引容量\n     * @param template\n     * @param cluster\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    public long getTemplateMaxIndexSize(String template, String cluster, Long startTime, Long endTime) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TEMPLATE_MAX_INDEX_SIZE, template, cluster,\n            startTime, endTime);\n        String realIndex = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl,\n            s -> getSumFromESQueryResponse(s, \"sizeMax\").longValue(), 3);\n    }\n\n    /**\n     * 根据模板名称，获取模板的总文档数\n     * @param template\n     * @param cluster\n     * @return\n     */\n    public long getTemplateTotalDocNu(String template, String cluster) {\n        Long now = System.currentTimeMillis();\n        return getTemplateTotalDocNuByTimeRange(template, cluster, now - 15 * ONE_MIN, now);\n    }\n\n    /**\n     * 查询模板一段时间访问内的最大模板总文档数\n     * @param template\n     * @param cluster\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    public long getTemplateTotalDocNuByTimeRange(String template, String cluster, Long startTime, Long endTime) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TEMPLATE_TOTAL_DOC_BY_TIME_RANGE, template,\n            cluster, startTime, endTime);\n        String realIndex = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl,\n            s -> getSumFromESQueryResponse(s, \"docSum\").longValue(), 3);\n    }\n\n    /**\n     * 查询模板一段时间访问内的最大模板总文档数\n     * @param logicTemplateId\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    public long getTemplateTotalDocNuByTimeRange(Long logicTemplateId, Long startTime, Long endTime) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n            DslsConstant.GET_TEMPLATE_TOTAL_DOC_BY_LOGIC_TEMPLATE_ID_AND_TIME_RANGE, logicTemplateId, startTime,\n            endTime);\n        String realIndex = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl,\n            s -> getSumFromESQueryResponse(s, \"docSum\").longValue(), 3);\n    }\n\n    /**\n     * 获取索引模板一段时间的最大文档条数\n     * @param template\n     * @param cluster\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    public long getTemplateMaxIndexDoc(String template, String cluster, Long startTime, Long endTime) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TEMPLATE_MAX_INDEX_DOC, template, cluster,\n            startTime, endTime);\n        String realIndex = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl,\n            s -> getSumFromESQueryResponse(s, \"docMax\").longValue(), 3);\n    }\n\n    /**\n     * 查询模板一段时间访问内的总的tps\n     * @param logicTemplateId\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    public double getTemplateMaxTpsByTimeRange(Long logicTemplateId, Long startTime, Long endTime) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TEMPLATE_TOTAL_MAX_TPS_BY_TIME_RANGE,\n            logicTemplateId, startTime, endTime);\n        String realIndex = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"tpsMax\"), 3);\n    }\n\n    public double getTemplateMaxTpsByTimeRangeNoPercent(Long logicTemplateId, Long startTime, Long endTime) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n            DslsConstant.GET_TEMPLATE_TOTAL_MAX_TPS_BY_TIME_RANGE_NO_PERCENT, logicTemplateId, startTime, endTime);\n        String realIndex = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"tpsMax\"), 3);\n    }\n\n    /**\n     * 根据模板和集群，获取一段时间内的模板分钟级别平均实时数据\n     * @param startDate\n     * @param endDate\n     * @param template\n     * @param cluster\n     * @return\n     */\n    public IndexRealTimeInfo getIndexRealTimeInfoByTemplateAndCluster(int offset, long startDate, long endDate,\n                                                                      String template, String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TEMPLATE_REAL_INFO_BY_TEMPLATE_AND_CLUSTER,\n            startDate, endDate, cluster, template);\n        String realIndex = IndexNameUtils.genDailyIndexName(indexName, offset);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, response -> {\n\n            if (response == null) {\n                return null;\n            }\n\n            IndexRealTimeInfo indexRealTimeInfo = new IndexRealTimeInfo();\n            indexRealTimeInfo.setTemplate(template);\n            indexRealTimeInfo.setCluster(cluster);\n            indexRealTimeInfo.setStart(new Date(startDate));\n            indexRealTimeInfo.setEnd(new Date(endDate));\n\n            try {\n                Map<String, ESAggr> esAggrMap = response.getAggs().getEsAggrMap();\n\n                ESAggr avgQueryTotalRate = esAggrMap.get(\"avg_search-query_total_rate\");\n                ESAggr avgIndexTotalRate = esAggrMap.get(\"avg_indexing-index_total_rate\");\n                ESAggr avgQueryAvgRate = esAggrMap.get(\"avg_indices-search-query_avg_time\");\n\n                if (null != avgQueryTotalRate.getUnusedMap() && null != avgQueryTotalRate.getUnusedMap().get(VALUE)) {\n                    indexRealTimeInfo.setAvgSearchQueryTotalRate(\n                        Double.parseDouble(avgQueryTotalRate.getUnusedMap().get(VALUE).toString()));\n                }\n\n                if (null != avgIndexTotalRate.getUnusedMap() && null != avgIndexTotalRate.getUnusedMap().get(VALUE)) {\n                    indexRealTimeInfo.setAvgIndexingIndexTotalRate(\n                        Double.parseDouble(avgIndexTotalRate.getUnusedMap().get(VALUE).toString()));\n                }\n\n                if (null != avgQueryAvgRate.getUnusedMap() && null != avgQueryAvgRate.getUnusedMap().get(VALUE)) {\n                    indexRealTimeInfo.setAvgIndicesSearchQueryTime(\n                        Double.parseDouble(avgQueryAvgRate.getUnusedMap().get(VALUE).toString()));\n                }\n            } catch (Exception e) {\n                LOGGER.error(\n                    \"class=AriusStatsIndexInfoEsDao||method=getIndexRealTimeInfoByTemplateAndCluster||errMsg=exception! response:{}\",\n                    response.toString(), e);\n            }\n\n            return indexRealTimeInfo;\n        }, 3);\n    }\n\n    /**\n     * 根据集群名称和模板名称获取模板的最大统计信息\n     * @param tempalte\n     * @param cluster\n     * @return\n     */\n    public Map<String, String> getTemplateMaxInfo(String tempalte, String cluster, Long startTime, Long endTime) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String maxPercentRate = \"95.0\";\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_MAXINFO_BY_TIME_RANGE_AND_TEMPLATE,\n            startTime, endTime, tempalte, cluster, maxPercentRate, maxPercentRate, maxPercentRate);\n\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl, response -> {\n            Map<String, String> ret = new HashMap<>();\n\n            if (response == null) {\n                return ret;\n            }\n\n            try {\n                Map<String, ESAggr> esAggrMap = response.getAggs().getEsAggrMap();\n\n                ESAggr maxTpsESAggr = esAggrMap.get(MAX_TPS);\n                ESAggr maxQueryTimeESAggr = esAggrMap.get(\"max_query_time\");\n                ESAggr maxScrollTimeESAggr = esAggrMap.get(\"max_scroll_time\");\n\n                handleMaxTpsESAggr(maxPercentRate, ret, maxTpsESAggr);\n\n                handleMaxQueryTimeESAggr(maxPercentRate, ret, maxQueryTimeESAggr);\n\n                handleMaxScrollTimeESAggr(maxPercentRate, ret, maxScrollTimeESAggr);\n            } catch (Exception e) {\n                LOGGER.error(\"class=AriusStatsIndexInfoEsDao||method=getTemplateMaxInfo||errMsg=exception! response:{}\",\n                    response.toString(), e);\n            }\n\n            return ret;\n\n        }, 3);\n    }\n\n    /**\n     * 获取指定时间范围的指定索引模板写入最大值和最近15分钟均值\n     * @param logicId\n     * @param startTime 毫秒\n     * @param endTime   毫秒\n     * @return\n     */\n\n    /**\n     * 解析结果\n            {\n                \"groupByTemplateId\" : {\n                  \"doc_count_error_upper_bound\" : 0,\n                  \"sum_other_doc_count\" : 0,\n                  \"buckets\" : [\n                    {\n                      \"key\" : 14679,\n                      \"doc_count\" : 47520,\n                      \"hour_buckets\" : {\n                        \"buckets\" : []\n                      },\n                      \"max_tps\" : {\n                        \"value\" : 445788.5691677049,\n                        \"keys\" : [\"1566432000000\"]\n                      }\n                    },\n                    {\n                      \"key\" : 15737,\n                      \"doc_count\" : 47520,\n                      \"hour_buckets\" : {\n                        \"buckets\" : []\n                      },\n                      \"max_tps\" : {\n                        \"value\" : 445098.5182184981,\n                        \"keys\" : [\"1566432000000\"]\n                      }\n                    }\n                  ]\n                },\n                \"max_tps_templateId\" : {\n                  \"value\" : 445788.5691677049,\n                  \"keys\" : [\"14679\"]\n                }\n         }\n     */\n\n    /**\n     * 解析结果\n            {\n                \"groupByTemplateId\" : {\n                \"doc_count_error_upper_bound\" : 0,\n                    \"sum_other_doc_count\" : 0,\n                    \"buckets\" : [\n                    {\n                      \"key\" : 14505,\n                      \"doc_count\" : 180,\n                      \"minute_buckets\" : {\n                        \"buckets\" : [\n                          {\n                            \"key_as_string\" : \"1573084800000\",\n                            \"key\" : 1573084800000,\n                            \"doc_count\" : 60,\n                            \"sum_tps\" : {\n                              \"value\" : 5272.678903963821\n                            }\n                          }\n                          .....\n                        ]\n                      },\n                      \"avg_tps\" : {\n                        \"value\" : 6332.870640468049\n                      }\n                    }\n                  ]\n                }\n            }\n            */\n    public TemplateTpsMetricPO getTemplateTpsMetricInfo(Integer logicId, Long startTime, Long endTime,\n                                                        Long currentStartDate, Long currentEndDate) {\n\n        TemplateTpsMetricPO tpsMetricPO = new TemplateTpsMetricPO();\n        Map<Long/*templateId*/, Double> currentTpsMap = Maps.newHashMap();\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        // 获取指定时间范围的指定索引模板写入每小时的最大值\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_HISTORY_MAX_TPS_BY_LOGIC_ID_AND_TIME_RANGE,\n            startTime, endTime, logicId);\n\n        ESQueryResponse esQueryResponse = gatewayClient.performRequest(realIndexName, TYPE, dsl);\n        if (esQueryResponse != null && esQueryResponse.getAggs() != null) {\n            Map<String, ESAggr> esAggrMap = esQueryResponse.getAggs().getEsAggrMap();\n            setMaxTpsTimestamp(tpsMetricPO, esAggrMap, getMaxTpsValue(tpsMetricPO, esAggrMap));\n        }\n\n        // 获取指定索引模板写入最近一段时间的总和\n        String indexNames = IndexNameUtils.genDailyIndexName(indexName, currentStartDate, currentEndDate);\n        dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AVG_TPS_BY_LOGIC_ID_AND_TIME_RANGE,\n            currentStartDate, currentEndDate, logicId);\n        esQueryResponse = gatewayClient.performRequest(indexNames, TYPE, dsl);\n        handleESQueryResponse(currentTpsMap, esQueryResponse);\n\n        tpsMetricPO.setCurrentTpsMap(currentTpsMap);\n\n        return tpsMetricPO;\n    }\n\n    /**\n     * 获取指定索引的查询率\n     *\n     * @param indexNames\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    /**\n     * 解析结果\n        {\n            \"groupByIndex\" : {\n              \"doc_count_error_upper_bound\" : 0,\n              \"sum_other_doc_count\" : 0,\n              \"buckets\" : [\n                {\n                  \"key\" : \"router_access_20191227\",\n                  \"doc_count\" : 4892,\n                  \"date_bucket\" : {\n                    \"buckets\" : [\n                      {\n                        \"key_as_string\" : \"2019-12-26\",\n                        \"key\" : 1577318400000,\n                        \"doc_count\" : 958,\n                        \"query_rate_avg\" : {\n                          \"value\" : 56.1850716890672\n                        }\n                      }\n                    ]\n                  }\n                },\n                {\n                  \"key\" : \"router_access_20191228\",\n                  \"doc_count\" : 4804,\n                  \"date_bucket\" : {\n                    \"buckets\" : [\n                      {\n                        \"key_as_string\" : \"2019-12-27\",\n                        \"key\" : 1577404800000,\n                        \"doc_count\" : 959,\n                        \"query_rate_avg\" : {\n                          \"value\" : 51.70561018127233\n                        }\n                      }\n                    ]\n                  }\n                }\n              ]\n            }\n          }\n     */\n    public List<IndexNameQueryAvgRatePO> getIndexNameQueryAvgRate(String indexNames, Long startDate, Long endDate) {\n\n        List<IndexNameQueryAvgRatePO> indexNameQueryAvgRatePoList = Lists.newLinkedList();\n\n        String[] indexNameArr = StringUtils.splitByWholeSeparatorPreserveAllTokens(indexNames, \",\");\n        String indexNameFormat = CommonUtils.strConcat(Lists.newArrayList(indexNameArr));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startDate, endDate);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_QUERY_RATE_BY_INDEX_DATE_RANGE,\n            indexNameFormat);\n\n        ESQueryResponse esQueryResponse = gatewayClient.performRequest(realIndexName, TYPE, dsl);\n        if (esQueryResponse != null && esQueryResponse.getAggs() != null) {\n\n            Map<String, ESAggr> esAggrMap = esQueryResponse.getAggs().getEsAggrMap();\n            if (esAggrMap != null && esAggrMap.containsKey(\"groupByIndex\")) {\n                ESAggr groupByIndexESAggr = esAggrMap.get(\"groupByIndex\");\n                if (groupByIndexESAggr != null && CollectionUtils.isNotEmpty(groupByIndexESAggr.getBucketList())) {\n                    handleBucketList(indexNameQueryAvgRatePoList, groupByIndexESAggr);\n                }\n            }\n        }\n\n        return indexNameQueryAvgRatePoList;\n    }\n\n    /**\n     * 根据索引逻辑模板ID获取指定范围内索引统计信息\n     *\n     * @param logicTemplateId\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public List<ESIndexStats> getTemplateRealStatis(Long logicTemplateId, Long startDate, Long endDate) {\n        String realIndex = IndexNameUtils.genDailyIndexName(indexName, startDate, endDate);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n            DslsConstant.GET_TEMPLATE_REAL_STATIS_INFO_BY_TEMPLATE_AND_CLUSTER, logicTemplateId, startDate, endDate);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> {\n            List<ESIndexStats> esIndexStatsList = Lists.newLinkedList();\n\n            if (null == s) {\n                return esIndexStatsList;\n            }\n\n            List<ESBucket> esBuckets = s.getAggs().getEsAggrMap().get(\"groupByTimeStamp\").getBucketList();\n\n            if (CollectionUtils.isNotEmpty(esBuckets)) {\n                esBuckets.forEach(esBucket -> {\n                    try {\n                        Map<String, Object> unUsedMap = esBucket.getUnusedMap();\n                        Map<String, ESAggr> aggrMap = esBucket.getAggrMap();\n                        if (null != unUsedMap && null != aggrMap) {\n                            ESIndexStats esIndexStats = new ESIndexStats();\n\n                            esIndexStats.putMetrics(\"store-size_in_bytes-total\",\n                                aggrMap.get(\"store-size_in_bytes-total\").getUnusedMap().get(VALUE).toString());\n                            esIndexStats.putMetrics(\"indexing-index_total_rate\",\n                                aggrMap.get(\"indexing-index_total_rate\").getUnusedMap().get(VALUE).toString());\n                            esIndexStats.putMetrics(\"indexing-index_time_in_millis_rate\",\n                                aggrMap.get(\"indexing-index_time_in_millis_rate\").getUnusedMap().get(VALUE).toString());\n                            esIndexStats.putMetrics(\"indexing-index_failed_rate\",\n                                aggrMap.get(\"indexing-index_failed_rate\").getUnusedMap().get(VALUE).toString());\n                            esIndexStats.putMetrics(\"search-scroll_time_in_millis_rate\",\n                                aggrMap.get(\"search-scroll_time_in_millis_rate\").getUnusedMap().get(VALUE).toString());\n                            esIndexStats.putMetrics(\"search-query_time_in_millis_rate\",\n                                aggrMap.get(\"search-query_time_in_millis_rate\").getUnusedMap().get(VALUE).toString());\n                            esIndexStats.putMetrics(\"search-query_total_rate\",\n                                aggrMap.get(\"search-query_total_rate\").getUnusedMap().get(VALUE).toString());\n                            esIndexStats.putMetrics(\"docs-count-total\",\n                                aggrMap.get(\"docs-count-total\").getUnusedMap().get(VALUE).toString());\n                            esIndexStats.setTimestamp(Long.parseLong(unUsedMap.get(\"key\").toString()));\n                            esIndexStats.setLogicTemplateId(logicTemplateId);\n\n                            esIndexStatsList.add(esIndexStats);\n                        }\n                    } catch (Exception e) {\n                        LOGGER.error(\n                            \"class=AriusStatsIndexInfoEsDao||method=getTemplateRealStatis||errMsg=get logic id {} error, response:{}\",\n                            logicTemplateId, s.toString(), e);\n                    }\n                });\n            }\n\n            return esIndexStatsList;\n\n        }, 3);\n    }\n\n    /**\n     * 获取指定时间范围的指定索引模板写入均值\n     *\n     * @param templateId\n     * @param startDate 毫秒\n     * @param endDate   毫秒\n     * @return\n     */\n    public Double getTemplateTpsAvgInfo(Long templateId, Long startDate, Long endDate) {\n        List<ESIndexStats> esIndexStats = getIndexStats(templateId, startDate, endDate);\n        if (CollectionUtils.isEmpty(esIndexStats)) {\n            return null;\n        }\n\n        final Double[] totalIndexing = { 0.0d };\n\n        esIndexStats.forEach(esIndexStats1 -> totalIndexing[0] += Double\n            .parseDouble(esIndexStats1.getMetrics().get(INDEXING_RATE.getType())));\n\n        // TPS_METRICS已经是毫秒级别的统计数据，monitor每分钟统计一次\n        return totalIndexing[0] * 1000 * 60 / (endDate - startDate);\n    }\n\n    /**\n     * 获取指定时间范围的指定索引模板均值查询均值\n     *\n     * @param templateId\n     * @param startDate 毫秒\n     * @param endDate   毫秒\n     * @return\n     */\n    public Double getTemplateQpsAvgInfo(Long templateId, Long startDate, Long endDate) {\n        List<ESIndexStats> esIndexStats = getIndexStats(templateId, startDate, endDate);\n        if (CollectionUtils.isEmpty(esIndexStats)) {\n            return null;\n        }\n\n        final Double[] totalQps = { 0.0d };\n\n        esIndexStats.forEach(s -> totalQps[0] += Double.parseDouble(s.getMetrics().get(QUERY_RATE.getType())));\n\n        // TPS_METRICS已经是毫秒级别的统计数据，monitor每分钟统计一次\n        return totalQps[0] * 1000 * 60 / (endDate - startDate);\n    }\n\n    /**\n     * 获取一段时间内索引的index_node统计信息\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public List<ESIndexStats> getIndexStats(Long templateId, Long startDate, Long endDate) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startDate, endDate);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_INDEX_STATS_BY_TIME_RANGE_AND_TEMPLATEID,\n            SCROLL_SIZE, startDate, endDate, templateId);\n\n        List<ESIndexStats> esIndexStats = Lists.newLinkedList();\n        gatewayClient.queryWithScroll(realIndexName, TYPE, dsl, SCROLL_SIZE, null, ESIndexStats.class, resultList -> {\n            if (resultList != null) {\n                esIndexStats.addAll(resultList);\n            }\n        });\n\n        return esIndexStats;\n    }\n\n    /**\n     * 获取最新时间分片中指标数值前TopN的索引名称\n     * 如果延迟后的最新时间分片的指标值为null，最新时间迭代 - 1, 直到不为空, 迭代上限为3次。\n     *\n     * @param clusterPhyName          集群名称\n     * @param metricsTypes            指标类型\n     * @param topNu                   topN\n     * @param aggType                 聚合类型\n     * @param indicesBucketsMaxNum    DSL第一层bucket大小 , 聚合索引数量最大值（agg bucket number）\n     * @param startTime               开始时间\n     * @param endTime                 结束时间\n     * @return\n     */\n    public List<TopMetrics> buildTopNIndexMetricsInfo(String clusterPhyName, List<String> metricsTypes, Integer topNu,\n                                                      String aggType, int indicesBucketsMaxNum, Long startTime,\n                                                      Long endTime) {\n        List<VariousLineChartMetrics> variousLineChartMetrics;\n        Long timePoint = getHasDataTime(clusterPhyName, startTime, endTime,\n            DslsConstant.GET_HAS_INDEX_METRICS_DATA_TIME);\n        //没有数据则提前终止\n        if (null == timePoint) {\n            return new ArrayList<>();\n        }\n\n        Tuple<Long, Long> firstInterval = MetricsUtils.getSortInterval(endTime - startTime, timePoint);\n        long startTimeForOneInterval = firstInterval.getV1();\n        long endTimeForOneInterval = firstInterval.getV2();\n\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_MULTIPLE_INDEX_FIRST_INTERVAL_AGG_METRICS,\n            clusterPhyName, startTimeForOneInterval, endTimeForOneInterval, indicesBucketsMaxNum, interval,\n            buildAggsDSL(metricsTypes, aggType));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTimeForOneInterval,\n            endTimeForOneInterval);\n\n        variousLineChartMetrics = gatewayClient.performRequestWithRouting(metadataClusterName, null, realIndexName,\n            TYPE, dsl, s -> fetchMultipleAggMetrics(s, null, metricsTypes, topNu), 3);\n\n        return variousLineChartMetrics.stream().map(this::buildTopMetrics).collect(Collectors.toList());\n    }\n\n    /**\n     * 获取topN的模板指标信息\n     * @param clusterPhyName\n     * @param metricsTypes\n     * @param topNu\n     * @param aggType\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    public List<VariousLineChartMetrics> getTopNTemplateAggMetrics(String clusterPhyName, List<String> metricsTypes,\n                                                                   Integer topNu, String aggType, Long startTime,\n                                                                   Long endTime) {\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n        List<TopMetrics> topNTemplateMetricsList = buildTopNTemplateMetricsInfo(clusterPhyName, metricsTypes, topNu,\n            aggType, indicesBucketsMaxNum, startTime, endTime);\n\n        for (TopMetrics topMetrics : topNTemplateMetricsList) {\n            futureUtil.runnableTask(() -> buildTopNSingleMetricsForTemplate(buildMetrics, clusterPhyName, aggType,\n                indicesBucketsMaxNum, startTime, endTime, topMetrics));\n        }\n        futureUtil.waitExecute();\n\n        return buildMetrics;\n    }\n\n    private List<TopMetrics> buildTopNTemplateMetricsInfo(String clusterPhyName, List<String> metricsTypes,\n                                                          Integer topNu, String aggType, int indicesBucketsMaxNum,\n                                                          Long startTime, Long endTime) {\n        List<VariousLineChartMetrics> variousLineChartMetrics;\n        Long timePoint = getHasDataTime(clusterPhyName, startTime, endTime,\n            DslsConstant.GET_HAS_INDEX_METRICS_DATA_TIME);\n        //没有数据则提前终止\n        if (null == timePoint) {\n            return new ArrayList<>();\n        }\n\n        Tuple<Long, Long> firstInterval = MetricsUtils.getSortInterval(endTime - startTime, timePoint);\n        long startTimeForOneInterval = firstInterval.getV1();\n        long endTimeForOneInterval = firstInterval.getV2();\n\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n            DslsConstant.GET_MULTIPLE_TEMPLATE_FIRST_INTERVAL_AGG_METRICS_WITH_STEP, clusterPhyName,\n            startTimeForOneInterval, endTimeForOneInterval, indicesBucketsMaxNum, interval,\n            buildAggsDSL(metricsTypes, aggType));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTimeForOneInterval,\n            endTimeForOneInterval);\n\n        variousLineChartMetrics = gatewayClient.performRequestWithRouting(metadataClusterName, null, realIndexName,\n            TYPE, dsl, s -> fetchMultipleAggMetrics(s, null, metricsTypes, topNu), 3);\n\n        return variousLineChartMetrics.stream().map(this::buildTopMetrics).collect(Collectors.toList());\n    }\n\n    /**\n     * 获取topN指标信息\n     * @param clusterPhyName\n     * @param metricsTypes\n     * @param topNu\n     * @param aggType\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    @Deprecated\n    public List<VariousLineChartMetrics> getTopNIndicesAggMetrics(String clusterPhyName, List<String> metricsTypes,\n                                                                  Integer topNu, String aggType, Long startTime,\n                                                                  Long endTime) {\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n        List<TopMetrics> topNIndexMetricsList = buildTopNIndexMetricsInfo(clusterPhyName, metricsTypes, topNu, aggType,\n            indicesBucketsMaxNum, startTime, endTime);\n\n        for (TopMetrics topMetrics : topNIndexMetricsList) {\n            futureUtil.runnableTask(() -> buildTopNSingleMetricsForIndex(buildMetrics, clusterPhyName, aggType,\n                indicesBucketsMaxNum, startTime, endTime, topMetrics));\n        }\n        futureUtil.waitExecute();\n\n        return buildMetrics;\n    }\n\n    private void buildTopNSingleMetricsForIndex(List<VariousLineChartMetrics> buildMetrics, String clusterPhyName,\n                                                String aggType, int indicesBucketsMaxNum, Long startTime, Long endTime,\n                                                TopMetrics topMetrics) {\n        String topNameStr = null;\n        if (CollectionUtils.isNotEmpty(topMetrics.getTopNames())) {\n            topNameStr = buildTopNameStr(topMetrics.getTopNames());\n        }\n\n        if (StringUtils.isBlank(topNameStr)) {\n            return;\n        }\n\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n        List<String> metricsTypes = Lists.newArrayList(topMetrics.getType());\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOPN_INDEX_AGG_METRICS, clusterPhyName,\n            topNameStr, startTime, endTime, indicesBucketsMaxNum, interval, startTime, endTime,\n            buildAggsDSL(metricsTypes, aggType));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        List<VariousLineChartMetrics> variousLineChartMetrics = gatewayClient.performRequestWithRouting(\n            metadataClusterName, null, realIndexName, TYPE, dsl,\n            s -> fetchMultipleAggMetrics(s, null, metricsTypes, null), 3);\n        buildMetrics.addAll(variousLineChartMetrics);\n    }\n\n    /**\n     * 获取单个模板指标信息\n     *\n     * @param clusterPhyName    集群名称\n     * @param metrics           指标类型\n     * @param logicTemplateId   逻辑模板id\n     * @param aggType           聚合类型\n     * @param startTime         开始时间\n     * @param endTime           结束时间\n     * @return  List<VariousLineChartMetrics>\n     */\n    public List<VariousLineChartMetrics> getAggSingleTemplateMetrics(String clusterPhyName, List<String> metrics,\n                                                                     Integer logicTemplateId, String aggType,\n                                                                     Long startTime, Long endTime) {\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_SINGLE_TEMPLATE_METRICS, clusterPhyName,\n            logicTemplateId, startTime, endTime, interval, buildAggsDSL(metrics, aggType));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, String.valueOf(logicTemplateId),\n            realIndexName, TYPE, dsl, s -> fetchSingleAggMetrics(s, metrics, logicTemplateId.toString()), 3);\n    }\n\n    private void buildTopNSingleMetricsForTemplate(List<VariousLineChartMetrics> buildMetrics, String clusterPhyName,\n                                                   String aggType, int indicesBucketsMaxNum, Long startTime,\n                                                   Long endTime, TopMetrics topMetrics) {\n        String topNameStr = null;\n        if (CollectionUtils.isNotEmpty(topMetrics.getTopNames())) {\n            topNameStr = buildTopNameStr(topMetrics.getTopNames());\n        }\n\n        if (StringUtils.isBlank(topNameStr)) {\n            return;\n        }\n\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n        List<String> metricsKeys = Lists.newArrayList(topMetrics.getType());\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOPN_TEMPLATE_AGG_METRICS, clusterPhyName,\n            topNameStr, startTime, endTime, indicesBucketsMaxNum, interval, startTime, endTime,\n            buildAggsDSL(metricsKeys, aggType));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        List<VariousLineChartMetrics> variousLineChartMetrics = gatewayClient.performRequestWithRouting(\n            metadataClusterName, null, realIndexName, TYPE, dsl,\n            s -> fetchMultipleAggMetrics(s, null, metricsKeys, null), 3);\n        buildMetrics.addAll(variousLineChartMetrics);\n    }\n\n    /**\n     * 获取单个索引指标信息\n     *\n     * @param clusterPhyName    集群名称\n     * @param metrics           指标类型\n     * @param searchIndexName   索引名称\n     * @param aggType           聚合类型\n     * @param startTime         开始时间\n     * @param endTime           结束时间\n     * @return  List<VariousLineChartMetrics>\n     */\n    public List<VariousLineChartMetrics> getAggSingleIndexMetrics(String clusterPhyName, List<String> metrics,\n                                                                  String searchIndexName, String aggType,\n                                                                  Long startTime, Long endTime) {\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_SINGLE_INDEX_METRICS, clusterPhyName,\n            searchIndexName, startTime, endTime, interval, buildAggsDSL(metrics, aggType));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, searchIndexName, realIndexName, TYPE, dsl,\n            s -> fetchSingleAggMetrics(s, metrics, searchIndexName), 3);\n    }\n\n    /**\n     * 获取索引search-query量\n     *\n     * @param cluster      集群\n     * @param indexList   索引列表\n     * @return {@code Map<String, Double>}\n     */\n    public Map<String, Double> getIndex2CurrentSearchQueryMap(String cluster, List<String> indexList) {\n        return commonGetMetricValue(cluster, indexList, SEARCH_QUERY_TOTAL_DIFF);\n    }\n\n    /**\n     * 获取索引indexing-index量\n     *\n     * @param cluster     集群\n     * @param indexList   索引列表\n     * @return {@code Map<String, Double>}\n     */\n    public Map<String, Double> getIndex2CurrentIndexingIndexMap(String cluster, List<String> indexList) {\n        return commonGetMetricValue(cluster, indexList, INDEX_INDEX_TOTAL_DIFF);\n    }\n\n    /********************************************* private methods *********************************************/\n    /**\n     * 获取索引级别metrics指标项\n     *\n     * @param cluster    集群名称\n     * @param indexList  索引名称列表\n     * @param metricType 指标类型\n     * @return metrics 指标数值\n     */\n    private Map<String, Double> commonGetMetricValue(String cluster, List<String> indexList, String metricType) {\n        String termsDsl = DslTermUtil.buildTermsDslByIndexList(indexList);\n        String commonRequestDsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_SINGLE_METRICS, cluster,\n            termsDsl, BaseAriusStatsESDAO.NOW_2M, BaseAriusStatsESDAO.NOW_1M, metricType);\n\n        return gatewayClient.performRequest(cluster, IndexNameUtils.genCurrentDailyIndexName(indexName), TYPE,\n            commonRequestDsl, s -> fetchMap(s, metricType, indexList), 3);\n    }\n\n    private Map<String, Double> fetchMap(ESQueryResponse s, String metricType, List<String> indexList) {\n        Map<String, Double> index2MetricValueMap = Maps.newHashMap();\n        if (null == s) {\n            return index2MetricValueMap;\n        }\n        if (null == s.getSourceList()) {\n            return index2MetricValueMap;\n        }\n        ESHits hits = s.getHits();\n        if (null != hits && CollectionUtils.isNotEmpty(hits.getHits())) {\n            for (ESHit esHit : hits.getHits()) {\n                JSONObject metricsJb = (JSONObject) esHit.getSource();\n                Object metricsObj = metricsJb.get(\"metrics\");\n\n                JSONObject subMetrics = (JSONObject) metricsObj;\n                if (null == subMetrics) {\n                    continue;\n                }\n\n                double value = null == subMetrics.getDouble(metricType) ? 0d : subMetrics.getDouble(metricType);\n                String index = metricsJb.getString(INDEX);\n                if (null != index) {\n                    index2MetricValueMap.put(index, value);\n                }\n            }\n\n            // 添加未匹配到的索引指标信息\n            List<String> addIndexNameList = indexList.stream().filter(r -> !index2MetricValueMap.containsKey(r))\n                .distinct().collect(Collectors.toList());\n            for (String addIndexName : addIndexNameList) {\n                index2MetricValueMap.put(addIndexName, 0d);\n            }\n        }\n        return index2MetricValueMap;\n    }\n\n    private void handleMaxScrollTimeESAggr(String maxPercentRate, Map<String, String> ret, ESAggr maxScrollTimeESAggr) {\n        if (null != maxScrollTimeESAggr.getUnusedMap() && null != maxScrollTimeESAggr.getUnusedMap().get(VALUES)) {\n            JSONObject values = (JSONObject) maxScrollTimeESAggr.getUnusedMap().get(VALUES);\n            if (Objects.nonNull(values) && values.containsKey(maxPercentRate)\n                && Objects.nonNull(values.get(maxPercentRate))) {\n                ret.put(\"max_scroll_time\", values.get(maxPercentRate).toString());\n            }\n        }\n    }\n\n    private void handleMaxQueryTimeESAggr(String maxPercentRate, Map<String, String> ret, ESAggr maxQueryTimeESAggr) {\n        if (null != maxQueryTimeESAggr.getUnusedMap() && null != maxQueryTimeESAggr.getUnusedMap().get(VALUES)) {\n            JSONObject values = (JSONObject) maxQueryTimeESAggr.getUnusedMap().get(VALUES);\n            if (Objects.nonNull(values) && values.containsKey(maxPercentRate)\n                && Objects.nonNull(values.get(maxPercentRate))) {\n                ret.put(\"max_query_time\", values.get(maxPercentRate).toString());\n            }\n        }\n    }\n\n    private void handleMaxTpsESAggr(String maxPercentRate, Map<String, String> ret, ESAggr maxTpsESAggr) {\n        if (null != maxTpsESAggr.getUnusedMap() && null != maxTpsESAggr.getUnusedMap().get(VALUES)) {\n            JSONObject values = (JSONObject) maxTpsESAggr.getUnusedMap().get(VALUES);\n            if (Objects.nonNull(values) && values.containsKey(maxPercentRate)\n                && Objects.nonNull(values.get(maxPercentRate))) {\n                ret.put(MAX_TPS, values.get(maxPercentRate).toString());\n            }\n        }\n    }\n\n    private void handleBucketList(List<IndexNameQueryAvgRatePO> indexNameQueryAvgRatePoList,\n                                  ESAggr groupByIndexESAggr) {\n        for (ESBucket esBucket : groupByIndexESAggr.getBucketList()) {\n            String indexName = esBucket.getUnusedMap().get(\"key\").toString();\n            ESAggr dateBucketESAggr = esBucket.getAggrMap().get(\"date_bucket\");\n\n            if (dateBucketESAggr != null && CollectionUtils.isNotEmpty(dateBucketESAggr.getBucketList())) {\n                for (ESBucket subBucket : dateBucketESAggr.getBucketList()) {\n                    String date = subBucket.getUnusedMap().get(\"key_as_string\").toString();\n\n                    ESAggr queryRateAvgESAggr = subBucket.getAggrMap().get(\"query_rate_avg\");\n                    if (queryRateAvgESAggr != null && queryRateAvgESAggr.getUnusedMap().get(VALUE) != null) {\n                        IndexNameQueryAvgRatePO indexNameQueryAvgRatePo = new IndexNameQueryAvgRatePO();\n                        indexNameQueryAvgRatePo.setDate(date);\n                        indexNameQueryAvgRatePo.setIndexName(indexName);\n                        indexNameQueryAvgRatePo\n                            .setQueryTotalRate(Double.valueOf(queryRateAvgESAggr.getUnusedMap().get(VALUE).toString()));\n\n                        indexNameQueryAvgRatePoList.add(indexNameQueryAvgRatePo);\n                    }\n                }\n            }\n        }\n    }\n\n    private void handleESQueryResponse(Map<Long, Double> currentTpsMap, ESQueryResponse esQueryResponse) {\n        if (esQueryResponse != null && esQueryResponse.getAggs() != null) {\n            Map<String, ESAggr> esAggrMap = esQueryResponse.getAggs().getEsAggrMap();\n\n            if (esAggrMap != null && esAggrMap.containsKey(GROUP_BY_TEMPLATE_ID)) {\n                ESAggr groupByTemplateIdESAggr = esAggrMap.get(GROUP_BY_TEMPLATE_ID);\n                if (groupByTemplateIdESAggr != null\n                    && CollectionUtils.isNotEmpty(groupByTemplateIdESAggr.getBucketList())) {\n\n                    handleBucketList(currentTpsMap, groupByTemplateIdESAggr);\n                }\n            }\n        }\n    }\n\n    private void handleBucketList(Map<Long, Double> currentTpsMap, ESAggr groupByTemplateIdESAggr) {\n        for (ESBucket esBucket : groupByTemplateIdESAggr.getBucketList()) {\n            Long templateId = Long.valueOf(esBucket.getUnusedMap().get(\"key\").toString());\n            ESAggr avgAggr = esBucket.getAggrMap().get(\"avg_tps\");\n            if (avgAggr != null) {\n                Map<String, Object> values;\n                values = (Map<String, Object>) avgAggr.getUnusedMap().get(VALUES);\n                currentTpsMap.put(templateId, Double.valueOf(values.get(\"50.0\").toString()));\n            }\n        }\n    }\n\n    private void setMaxTpsTimestamp(TemplateTpsMetricPO tpsMetricPO, Map<String, ESAggr> esAggrMap,\n                                    String maxTpsValue) {\n        if (maxTpsValue != null && esAggrMap != null && esAggrMap.containsKey(GROUP_BY_TEMPLATE_ID)) {\n            ESAggr groupByTemplateIdESAggr = esAggrMap.get(GROUP_BY_TEMPLATE_ID);\n            if (groupByTemplateIdESAggr != null\n                && CollectionUtils.isNotEmpty(groupByTemplateIdESAggr.getBucketList())) {\n                handleBucketList(tpsMetricPO, maxTpsValue, groupByTemplateIdESAggr);\n            }\n        }\n    }\n\n    private void handleBucketList(TemplateTpsMetricPO tpsMetricPO, String maxTpsValue, ESAggr groupByTemplateIdESAggr) {\n        for (ESBucket esBucket : groupByTemplateIdESAggr.getBucketList()) {\n            ESAggr maxAggr = esBucket.getAggrMap().get(MAX_TPS);\n            if (maxAggr != null && maxTpsValue.equals(maxAggr.getUnusedMap().get(VALUE).toString())) {\n                Object obj = maxAggr.getUnusedMap().get(\"keys\");\n                if (obj instanceof JSONArray) {\n                    JSONArray jsonArray = (JSONArray) obj;\n                    for (Object o : jsonArray) {\n                        Long maxTpsTimestamp = Long.valueOf(o.toString());\n                        tpsMetricPO.setMaxTpsTimestamp(DateTimeUtil.formatTimestamp(maxTpsTimestamp));\n                    }\n                }\n                break;\n            }\n        }\n    }\n\n    private String getMaxTpsValue(TemplateTpsMetricPO tpsMetricPO, Map<String, ESAggr> esAggrMap) {\n        String maxTpsValue = null;\n        if (esAggrMap != null && esAggrMap.containsKey(\"max_tps_templateId\")) {\n            ESAggr maxTpsESAggr = esAggrMap.get(\"max_tps_templateId\");\n            if (maxTpsESAggr != null && maxTpsESAggr.getUnusedMap() != null\n                && maxTpsESAggr.getUnusedMap().get(VALUE) != null) {\n                maxTpsValue = maxTpsESAggr.getUnusedMap().get(VALUE).toString();\n                tpsMetricPO.setMaxTps(Double.valueOf(maxTpsValue));\n                Object obj = maxTpsESAggr.getUnusedMap().get(\"keys\");\n                if (obj instanceof JSONArray) {\n                    JSONArray jsonArray = (JSONArray) obj;\n                    for (Object o : jsonArray) {\n                        tpsMetricPO.setMaxTpsTemplateId(Long.valueOf(o.toString()));\n                    }\n                }\n            }\n        }\n        return maxTpsValue;\n    }\n\n    /**\n     * 获取topN指标信息\n     * @param clusterPhyName\n     * @param metricsTypes\n     * @param topNu\n     * @param aggType\n     * @param startTime\n     * @param endTime\n     * @return\n     */\n    public List<VariousLineChartMetrics> getTopNIndicesAggMetricsWithStep(String clusterPhyName,\n                                                                          List<String> metricsTypes, Integer topNu,\n                                                                          String topMethod, Integer topTimeStep,\n                                                                          String aggType, Long startTime,\n                                                                          Long endTime) {\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n        List<TopMetrics> topNIndexMetricsList = buildTopNIndexMetricsInfoWithStep(clusterPhyName, metricsTypes, topNu,\n            topMethod, topTimeStep, indicesBucketsMaxNum, startTime, endTime);\n\n        for (TopMetrics topMetrics : topNIndexMetricsList) {\n            futureUtil.runnableTask(() -> buildTopNSingleMetricsForIndex(buildMetrics, clusterPhyName, aggType,\n                indicesBucketsMaxNum, startTime, endTime, topMetrics));\n        }\n        futureUtil.waitExecute();\n\n        return buildMetrics;\n    }\n\n    public List<VariousLineChartMetrics> getTopNIndicesAggMetricsWithStep(String clusterPhyName,\n                                                                          List<String> metricsTypes, Integer topNu,\n                                                                          String topMethod, Integer topTimeStep,\n                                                                          String aggType, Long startTime,\n                                                                          Long endTime, List<String> belongToProjectIndexName) {\n        if (CollectionUtils.isEmpty(belongToProjectIndexName)) {\n            return Collections.emptyList();\n        }\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n\n        List<TopMetrics> topNIndexMetricsList = Lists.newArrayList();\n        if (belongToProjectIndexName.size() < topNu) {\n            Function<String,TopMetrics> metricsFunction=metricsType->{\n                TopMetrics topMetrics = new TopMetrics();\n                topMetrics.setType(metricsType);\n                topMetrics.setTopNames(belongToProjectIndexName);\n                return topMetrics;\n            };\n            topNIndexMetricsList = metricsTypes.stream().map(type->metricsFunction.apply(type)).collect(Collectors.toList());\n        }else {\n            topNIndexMetricsList = buildTopNIndexMetricsInfoWithStep(clusterPhyName, metricsTypes, topNu,\n                    topMethod, topTimeStep, indicesBucketsMaxNum, startTime, endTime, belongToProjectIndexName);\n        }\n\n        for (TopMetrics topMetrics : topNIndexMetricsList) {\n            futureUtil.runnableTask(() -> buildTopNSingleMetricsForIndex(buildMetrics, clusterPhyName, aggType,\n                    indicesBucketsMaxNum, startTime, endTime, topMetrics));\n        }\n        futureUtil.waitExecute();\n\n        return buildMetrics;\n    }\n    private List<TopMetrics> buildTopNIndexMetricsInfoWithStep(String clusterPhyName, List<String> metricsTypes,\n                                                               Integer topNu, String topMethod, Integer topTimeStep,\n                                                               int indicesBucketsMaxNum, Long startTime, Long endTime) {\n        List<VariousLineChartMetrics> variousLineChartMetrics;\n        Long timePoint = getHasDataTime(clusterPhyName, startTime, endTime,\n            DslsConstant.GET_HAS_INDEX_METRICS_DATA_TIME);\n        //没有数据则提前终止\n        if (null == timePoint) {\n            return new ArrayList<>();\n        }\n\n        long startTimeForOneInterval = timePoint - topTimeStep;\n        long endTimeForOneInterval = timePoint;\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n            DslsConstant.GET_MULTIPLE_INDEX_FIRST_INTERVAL_AGG_METRICS_WITH_STEP, clusterPhyName,\n            startTimeForOneInterval, endTimeForOneInterval, indicesBucketsMaxNum, STEP_INTERVAL,\n            buildAggsDSL(metricsTypes, topMethod), buildAggsDSLWithStep(metricsTypes, topMethod));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTimeForOneInterval,\n            endTimeForOneInterval);\n\n        variousLineChartMetrics = gatewayClient.performRequestWithRouting(metadataClusterName, null, realIndexName,\n            TYPE, dsl, s -> fetchMultipleAggMetricsWithStep(s, metricsTypes, topNu, topMethod, null), 3);\n\n        return variousLineChartMetrics.stream().map(this::buildTopMetrics).collect(Collectors.toList());\n    }\n    \n    private List<TopMetrics> buildTopNIndexMetricsInfoWithStep(String clusterPhyName, List<String> metricsTypes,\n                                                               Integer topNu, String topMethod, Integer topTimeStep,\n                                                               int indicesBucketsMaxNum, Long startTime, Long endTime,\n                                                               List<String> belongToProjectIndexName) {\n        List<VariousLineChartMetrics> variousLineChartMetrics;\n        Long timePoint = getHasDataTime(clusterPhyName, startTime, endTime,\n                DslsConstant.GET_HAS_INDEX_METRICS_DATA_TIME);\n        //没有数据则提前终止\n        if (null == timePoint) {\n            return new ArrayList<>();\n        }\n        \n        long startTimeForOneInterval = timePoint - topTimeStep;\n        long endTimeForOneInterval = timePoint;\n        \n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n                DslsConstant.GET_AGG_MULTIPLE_INDICES_METRICS_WITH_STEP_AND_INDEX_LIST, clusterPhyName,\n                JSON.toJSONString(belongToProjectIndexName), startTimeForOneInterval, endTimeForOneInterval,\n                indicesBucketsMaxNum, STEP_INTERVAL, buildAggsDSL(metricsTypes, topMethod),\n                buildAggsDSLWithStep(metricsTypes, topMethod));\n        \n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTimeForOneInterval,\n                endTimeForOneInterval);\n        \n        variousLineChartMetrics = gatewayClient.performRequestWithRouting(metadataClusterName, null, realIndexName,\n                TYPE, dsl, s -> fetchMultipleAggMetricsWithStep(s, metricsTypes, topNu, topMethod, null), 3);\n        \n        return variousLineChartMetrics.stream().map(this::buildTopMetrics).collect(Collectors.toList());\n    }\n\n    public List<VariousLineChartMetrics> getTopNTemplateAggMetricsWithStep(String clusterPhyName,\n                                                                           List<String> metricsTypes, Integer topNu,\n                                                                           String topMethod, Integer topTimeStep,\n                                                                           String aggType, Long startTime,\n                                                                           Long endTime) {\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n        List<TopMetrics> topNTemplateMetricsList = buildTopNTemplateMetricsInfoWithStep(clusterPhyName, metricsTypes,\n            topNu, topMethod, topTimeStep, aggType, indicesBucketsMaxNum, startTime, endTime);\n\n        for (TopMetrics topMetrics : topNTemplateMetricsList) {\n            futureUtil.runnableTask(() -> buildTopNSingleMetricsForTemplate(buildMetrics, clusterPhyName, aggType,\n                indicesBucketsMaxNum, startTime, endTime, topMetrics));\n        }\n        futureUtil.waitExecute();\n\n        return buildMetrics;\n    }\n     public List<VariousLineChartMetrics> getTopNTemplateAggMetricsWithStep(String clusterPhyName,\n                                                                           List<String> metricsTypes, Integer topNu,\n                                                                           String topMethod, Integer topTimeStep,\n                                                                           String aggType, Long startTime,\n                                                                           Long endTime,List<Integer> belongToProjectIdLogicTemplateIdList) {\n         if (CollectionUtils.isEmpty(belongToProjectIdLogicTemplateIdList)) {\n             return Collections.emptyList();\n         }\n         List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n\n         List<TopMetrics> topNTemplateMetricsList = Lists.newArrayList();\n         if (belongToProjectIdLogicTemplateIdList.size() < topNu) {\n             Function<String,TopMetrics> metricsFunction=metricsType->{\n                 TopMetrics topMetrics = new TopMetrics();\n                 topMetrics.setType(metricsType);\n                 topMetrics.setTopNames(belongToProjectIdLogicTemplateIdList.stream().map(String::valueOf).collect(Collectors.toList()));\n                 return topMetrics;\n             };\n             topNTemplateMetricsList = metricsTypes.stream().map(type->metricsFunction.apply(type)).collect(Collectors.toList());\n         }else {\n             topNTemplateMetricsList = buildTopNTemplateMetricsInfoWithStep(clusterPhyName, metricsTypes,\n                     topNu, topMethod, topTimeStep, aggType, indicesBucketsMaxNum, startTime, endTime,belongToProjectIdLogicTemplateIdList);\n         }\n\n\n        for (TopMetrics topMetrics : topNTemplateMetricsList) {\n            futureUtil.runnableTask(() -> buildTopNSingleMetricsForTemplate(buildMetrics, clusterPhyName, aggType,\n                indicesBucketsMaxNum, startTime, endTime, topMetrics));\n        }\n        futureUtil.waitExecute();\n\n        return buildMetrics;\n    }\n\n    private List<TopMetrics> buildTopNTemplateMetricsInfoWithStep(String clusterPhyName, List<String> metricsTypes,\n                                                                  Integer topNu, String topMethod, Integer topTimeStep,\n                                                                  String aggType, int indicesBucketsMaxNum,\n                                                                  Long startTime, Long endTime) {\n        List<VariousLineChartMetrics> variousLineChartMetrics = new ArrayList<>();\n        Long timePoint = getHasDataTime(clusterPhyName, startTime, endTime,\n            DslsConstant.GET_HAS_INDEX_METRICS_DATA_TIME);\n        //没有数据则提前终止\n        if (null == timePoint) {\n            return new ArrayList<>();\n        }\n\n        long startTimeForOneInterval = timePoint - topTimeStep;\n        long endTimeForOneInterval = timePoint;\n\n        String interval = \"1m\";\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n            DslsConstant.GET_MULTIPLE_TEMPLATE_FIRST_INTERVAL_AGG_METRICS_WITH_STEP, clusterPhyName,\n            startTimeForOneInterval, endTimeForOneInterval, indicesBucketsMaxNum, interval,\n            buildAggsDSL(metricsTypes, topMethod), buildAggsDSLWithStep(metricsTypes, topMethod));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTimeForOneInterval,\n            endTimeForOneInterval);\n\n        variousLineChartMetrics = gatewayClient.performRequestWithRouting(metadataClusterName, null, realIndexName,\n            TYPE, dsl, s -> fetchMultipleAggMetricsWithStep(s, metricsTypes, topNu, topMethod, null), 3);\n\n        return variousLineChartMetrics.stream().map(this::buildTopMetrics).collect(Collectors.toList());\n    }\n    private List<TopMetrics> buildTopNTemplateMetricsInfoWithStep(String clusterPhyName, List<String> metricsTypes,\n                                                                  Integer topNu, String topMethod, Integer topTimeStep,\n                                                                  String aggType, int indicesBucketsMaxNum,\n                                                                  Long startTime, Long endTime,List<Integer> belongToProjectIdLogicTemplateIdList) {\n        List<VariousLineChartMetrics> variousLineChartMetrics ;\n        Long timePoint = getHasDataTime(clusterPhyName, startTime, endTime,\n            DslsConstant.GET_HAS_INDEX_METRICS_DATA_TIME);\n        //没有数据则提前终止\n        if (null == timePoint) {\n            return new ArrayList<>();\n        }\n\n        long startTimeForOneInterval = timePoint - topTimeStep;\n        long endTimeForOneInterval = timePoint;\n\n        String interval = \"1m\";\n    \n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n            DslsConstant.GET_AGG_MULTIPLE_TEMPLATE_METRICS_WITH_STEP_AND_LOGIC_IDS, JSON.toJSONString(belongToProjectIdLogicTemplateIdList),clusterPhyName,\n            startTimeForOneInterval, endTimeForOneInterval, indicesBucketsMaxNum, interval,\n            buildAggsDSL(metricsTypes, topMethod), buildAggsDSLWithStep(metricsTypes, topMethod));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTimeForOneInterval,\n            endTimeForOneInterval);\n\n        variousLineChartMetrics = gatewayClient.performRequestWithRouting(metadataClusterName, null, realIndexName,\n            TYPE, dsl, s -> fetchMultipleAggMetricsWithStep(s, metricsTypes, topNu, topMethod, null), 3);\n\n        return variousLineChartMetrics.stream().map(this::buildTopMetrics).collect(Collectors.toList());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/stats/AriusStatsNodeInfoESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.TopMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESNodeStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterLogicDiskUsedInfoPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusStatsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.*;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.METRICS;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.TIMESTAMP;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.AggMetricsTypeEnum.SUM;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyIndicesMetricsEnum.INDEXING_RATE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyNodeMetricsEnum.*;\n\n@Component\npublic class AriusStatsNodeInfoESDAO extends BaseAriusStatsESDAO {\n    private static final String           NOW_2M            = \"now-2m\";\n    private static final String           NOW_1M            = \"now-1m\";\n    public static final String            INDEX_TOTAL       = \"index_total\";\n    public static final String            INDEX_TOTAL_FIELD = \"indices-indexing-index_total\";\n    public static final String            QUERY_TOTAL       = \"query_total\";\n    public static final String            QUERY_TOTAL_FIELD = \"indices-search-query_total\";\n    public static final String            OPEN_HTTP         = \"open_http\";\n    public static final String            OPEN_HTTP_FIELD   = \"http-current_open\";\n    private static final String           VALUE             = \"value\";\n    private static final String           WRITE_REJECTED_TOTAL             = \"write_rejected_total\";\n\n    private static final String           THREAD_POOL_WRITE_REJECTED       = \"thread_pool-write-rejected\";\n    private static final String           SEARCH_REJECTED_TOTAL            = \"search_rejected_total\";\n    private static final String           THREAD_POOL_SEARCH_REJECTED      = \"thread_pool-search-rejected\";\n    private static final String           BREAKERS                         = \"breakers\";\n    private static final String           LIMIT_SIZE_IN_BYTES              = \"limit_size_in_bytes\";\n    private static final String           ESTIMATED_SIZE_IN_BYTES          = \"estimated_size_in_bytes\";\n\n\n    private static final FutureUtil<Void> futureUtil        = FutureUtil.init(\"AriusStatsNodeInfoESDAO\", 10, 10, 500);\n\n    @PostConstruct\n    public void init() {\n        super.indexName = dataCentreUtil.getAriusStatsNodeInfo();\n\n        BaseAriusStatsESDAO.register(AriusStatsEnum.NODE_INFO, this);\n    }\n\n    /**\n     * 根据集群名称，获取集群[now-2m, now-1m]总的tps\n     * @param cluster\n     * @return\n     */\n    public double getClusterTps(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_REAL_TIME_TPS_QPS_INFO, cluster,\n                \"now-2m\", \"now-1m\", INDICES_INDEXING_RATE.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 根据集群名称，获取集群[now-2m, now-1m]总的接收的流量\n     * @param cluster 集群\n     * @return\n     */\n    public Double getClusterRx(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_REAL_TIME_RX_TX_INFO, cluster,\n            NOW_2M, NOW_1M, TRANS_RX_SIZE.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 根据集群名称，获取集群[now-2m, now-1m]总的发送的流量\n     * @param cluster\n     * @return\n     */\n    public Double getClusterTx(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_REAL_TIME_RX_TX_INFO, cluster,\n            NOW_2M, NOW_1M, TRANS_TX_SIZE.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 根据集群名称，获取集群[now-2m, now-1m]  cpu平均使用率 (求每个节点cpu的平均值)\n     * @param cluster\n     * @return\n     */\n    public Double getClusterCpuAvg(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_REAL_TIME_CPU_AVG_INFO, cluster,\n            NOW_2M, NOW_1M, CPU_USAGE_PERCENT.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"avg\"), 3);\n    }\n\n    /**\n     * 获取集群实时cpu分位值(统计节点维度)和平均使用率\n     *\n     * @param cluster\n     * @return\n     */\n    public Map<String, Double> getClusterCpuAvgAndPercentiles(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_REAL_TIME_AVG_AND_PERCENT, cluster,\n            NOW_2M, NOW_1M, CPU_USAGE_PERCENT.getType(), CPU_USAGE_PERCENT.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n            this::getAvgAndPercentilesFromESQueryResponse, 3);\n    }\n\n    /**\n     * 获取集群实时cpu load 1m分位值(统计节点维度)和平均使用率\n     *\n     * @param cluster\n     * @return\n     */\n    public Map<String, Double> getClusterCpuLoad1MinAvgAndPercentiles(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_REAL_TIME_AVG_AND_PERCENT, cluster,\n            NOW_2M, NOW_1M, CPU_LOAD_AVERAGE_1M.getType(), CPU_LOAD_AVERAGE_1M.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n            this::getAvgAndPercentilesFromESQueryResponse, 3);\n    }\n\n    /**\n     * 获取集群实时cpu load 5m分位值(统计节点维度)和平均使用率\n     *\n     * @param cluster\n     * @return\n     */\n    public Map<String, Double> getClusterCpuLoad5MinAvgAndPercentiles(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_REAL_TIME_AVG_AND_PERCENT, cluster,\n            NOW_2M, NOW_1M, CPU_LOAD_AVERAGE_5M.getType(), CPU_LOAD_AVERAGE_5M.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n            this::getAvgAndPercentilesFromESQueryResponse, 3);\n    }\n\n    /**\n     * 获取集群实时cpu load 15m分位值(统计节点维度)和平均使用率\n     *\n     * @param cluster\n     * @return\n     */\n    public Map<String, Double> getClusterCpuLoad15MinAvgAndPercentiles(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_REAL_TIME_AVG_AND_PERCENT, cluster,\n            NOW_2M, NOW_1M, CPU_LOAD_AVERAGE_15M.getType(), CPU_LOAD_AVERAGE_15M.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n            this::getAvgAndPercentilesFromESQueryResponse, 3);\n\n    }\n\n    /**\n     * 获取集群写入耗时\n     */\n    public double getClusterIndexingLatency(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_INDEXING_LATENCY_MAX, cluster,\n            NOW_2M, NOW_1M, INDICES_INDEXING_INDEX_TIME_PER_DOC.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"max\"), 3);\n    }\n\n    /**\n     * 获取集群查询耗时\n     */\n    public double getClusterSearchLatency(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_SEARCH_LATENCY_MAX, cluster, NOW_2M,\n            NOW_1M, INDICES_QUERY_LATENCY.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"max\"), 3);\n    }\n\n    /**\n     * 获取集群写入耗时分位值(统计节点维度)和平均使用率\n     */\n    public double getClusterIndexingLatencySum(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_INDEXING_SEARCH_TIME_SUM, cluster,\n            NOW_2M, NOW_1M, INDICES_INDEXING_LATENCY.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, cluster, realIndex, TYPE, dsl,\n                s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 获取集群所有节点间隔时间nodes.{nodeName}.indices.docs.count差值累加值\n     * @param cluster 集群名称\n     * @return\n     */\n    public double getClusterIndexingDocSum(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_INDEXING_SEARCH_TIME_SUM, cluster,\n                NOW_2M, NOW_1M, INDICES_NUM_DIFF.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, cluster, realIndex, TYPE, dsl,\n                s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 获取集群查询耗时分位值(统计节点维度)和平均使用率\n     */\n    public double getClusterSearchLatencySum(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_INDEXING_SEARCH_TIME_SUM, cluster,\n            NOW_2M, NOW_1M, INDICES_QUERY_TIME_IN_MILLIS.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 获取集群所有节点间隔时间nodes.{nodeName}.indices.search.query_total差值累加值\n     * @param cluster 集群名称\n     * @return\n     */\n    public double getClusterSearchQueryTotal(String cluster){\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_INDEXING_SEARCH_TIME_SUM, cluster,\n                NOW_2M, NOW_1M, INDICES_QUERY_TOTAL.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 获取集群磁盘空闲使用率分位值(统计节点维度)和平均使用率\n     */\n    public Map<String, Double> getClusterDiskFreeUsagePercentAvgAndPercentiles(String cluster) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n            DslsConstant.AGG_CLUSTER_AVG_AND_PERCENT_FOR_DISK_FREE_USAGE_PERCENT, cluster, NOW_2M, NOW_1M);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n            this::getAvgAndPercentilesFromESQueryResponse, 3);\n    }\n\n    /**\n     * 获取所有集群节点的物理存储空间大小\n     * @return\n     */\n    public Double getAllClusterNodePhyStoreSize(final boolean bWithOutCeph) {\n        String realIndexName = IndexNameUtils.genCurrentDailyIndexName(indexName);\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_ALL_CLUSTER_NODE_PHY_STORE_SIZE,\n            SCROLL_SIZE);\n\n        final Set<String> nodeNameSet = new HashSet<>();\n        final double[] totalPhySize = new double[1];\n        final String fs_total_size_key = \"fs-total-total_in_bytes\";\n\n        gatewayClient.queryWithScroll(realIndexName, TYPE, dsl, SCROLL_SIZE, null, ESNodeStats.class, resultList -> {\n            if (CollectionUtils.isEmpty(resultList)) {\n                return;\n            }\n\n            for (ESNodeStats stats : resultList) {\n                if (null == stats.getMetrics() || StringUtils.isBlank(stats.getMetrics().get(fs_total_size_key))) {\n                    continue;\n                }\n\n                String node = stats.getNode();\n                String fsSize = stats.getMetrics().get(fs_total_size_key);\n\n                if (bWithOutCeph && node.contains(\"ceph\")) {\n                    continue;\n                }\n\n                //由于物理机上可能存在节点混部，而混部的节点es在统计的时候获取的是物理机的整个磁盘空间，所以获取一个节点统计的信息即可\n                if (!nodeNameSet.contains(node)) {\n                    totalPhySize[0] += Double.valueOf(fsSize);\n                    nodeNameSet.add(node);\n                }\n            }\n        });\n\n        return totalPhySize[0];\n    }\n\n    public List<VariousLineChartMetrics> getTopNNodeAggMetricsWithStep(String clusterPhyName,\n                                                                       List<String> nodeNamesUnderClusterLogic,\n                                                                       List<String> metricsTypes, Integer topNu,\n                                                                       String topMethod, Integer topTimeStep,\n                                                                       String aggType, Long startTime, Long endTime) {\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n        //获取TopN指标节点名称信息\n        List<TopMetrics> topNIndexMetricsList = getTopNNodeMetricsInfoWithStep(clusterPhyName,\n            nodeNamesUnderClusterLogic, metricsTypes, topNu, topMethod, topTimeStep, esNodesMaxNum, startTime, endTime);\n        //构建多个指标TopN数据\n        for (TopMetrics topMetrics : topNIndexMetricsList) {\n            futureUtil.runnableTask(() -> buildTopNSingleMetricsForNode(buildMetrics, clusterPhyName, aggType,\n                esNodesMaxNum, startTime, endTime, topMetrics));\n        }\n        futureUtil.waitExecute();\n\n        return buildMetrics;\n    }\n\n    /**\n     * 获取多个节点折线图指标信息\n     *\n     * @param clusterPhyName 集群名称\n     * @param metricsTypes        指标类型\n     * @param topNu          top\n     * @param aggType        聚合类型\n     * @param startTime      开始时间\n     * @param endTime        结束时间\n     * @return List<VariousLineChartMetrics>\n     */\n    public List<VariousLineChartMetrics> getTopNNodeAggMetrics(String clusterPhyName, List<String> metricsTypes,\n                                                               Integer topNu, String aggType, Long startTime,\n                                                               Long endTime) {\n        List<VariousLineChartMetrics> buildMetrics = Lists.newCopyOnWriteArrayList();\n        //获取TopN指标节点名称信息\n        List<TopMetrics> topNIndexMetricsList = getTopNNodeMetricsInfo(clusterPhyName, metricsTypes, topNu, aggType,\n            esNodesMaxNum, startTime, endTime);\n\n        //构建多个指标TopN数据\n        for (TopMetrics topMetrics : topNIndexMetricsList) {\n            futureUtil.runnableTask(() -> buildTopNSingleMetricsForNode(buildMetrics, clusterPhyName, aggType,\n                esNodesMaxNum, startTime, endTime, topMetrics));\n        }\n        futureUtil.waitExecute();\n\n        return buildMetrics;\n    }\n\n    private void buildTopNSingleMetricsForNode(List<VariousLineChartMetrics> buildMetrics, String clusterPhyName,\n                                               String aggType, int esNodesMaxNum, Long startTime, Long endTime,\n                                               TopMetrics topMetrics) {\n        String topNameStr = null;\n        if (CollectionUtils.isNotEmpty(topMetrics.getTopNames())) {\n            topNameStr = buildTopNameStr(topMetrics.getTopNames());\n        }\n\n        if (StringUtils.isBlank(topNameStr)) {\n            return;\n        }\n\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n        List<String> metricsKeys = Lists.newArrayList(topMetrics.getType());\n        if (topMetrics.getType().contains(BREAKERS)){\n            metricsKeys.add(topMetrics.getType().replaceAll(LIMIT_SIZE_IN_BYTES,ESTIMATED_SIZE_IN_BYTES));\n        }\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_TOPN_NODE_AGG_METRICS_INFO, clusterPhyName,\n            topNameStr, startTime, endTime, esNodesMaxNum, interval, startTime, endTime,\n            buildAggsDSL(metricsKeys, aggType));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        List<VariousLineChartMetrics> variousLineChartMetrics = gatewayClient.performRequestWithRouting(\n            metadataClusterName, null, realIndexName, TYPE, dsl,\n            s -> fetchMultipleAggMetrics(s, null, metricsKeys, null), 3);\n        buildMetrics.addAll(variousLineChartMetrics);\n    }\n\n    /**\n     *  获取最新时间分片中指标数值前TopN的节点名称\n     *  如果延迟后的最新时间分片的指标值为null，最新时间迭代 - 1, 直到不为空, 迭代上限为3次。\n     *\n     * @param clusterPhyName   集群名称\n     * @param metricsTypes     指标类型\n     * @param topNu            topN\n     * @param aggType          聚合类型\n     * @param esNodesMaxNum    聚合节点数量最大值（agg bucket number）\n     * @param startTime        开始时间\n     * @param endTime          结束时间\n     * @return\n     */\n    private List<TopMetrics> getTopNNodeMetricsInfo(String clusterPhyName, List<String> metricsTypes, Integer topNu,\n                                                    String aggType, int esNodesMaxNum, Long startTime, Long endTime) {\n\n        List<VariousLineChartMetrics> variousLineChartMetrics;\n        // 获取有数据的第一个时间点\n        Long timePoint = getHasDataTime(clusterPhyName, startTime, endTime,\n            DslsConstant.GET_HAS_NODE_METRICS_DATA_TIME);\n        //没有数据则提前终止\n        if (null == timePoint) {\n            return new ArrayList<>();\n        }\n\n        Tuple<Long, Long> firstInterval = MetricsUtils.getSortInterval(endTime - startTime, timePoint);\n        long startTimeForOneInterval = firstInterval.getV1();\n        long endTimeForOneInterval = firstInterval.getV2();\n\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_CLUSTER_PHY_NODES_INFO, clusterPhyName,\n            startTimeForOneInterval, endTimeForOneInterval, esNodesMaxNum, interval,\n            buildAggsDSL(metricsTypes, aggType));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTimeForOneInterval,\n            endTimeForOneInterval);\n\n        variousLineChartMetrics = gatewayClient.performRequestWithRouting(metadataClusterName, null, realIndexName,\n            TYPE, dsl, s -> fetchMultipleAggMetrics(s, null, metricsTypes, topNu), 3);\n        return variousLineChartMetrics.stream().map(this::buildTopMetrics).collect(Collectors.toList());\n    }\n\n    /**\n     *  获取最新时间分片中指标数值前TopN的节点名称\n     *  如果延迟后的最新时间分片的指标值为null，最新时间迭代 - 1, 直到不为空, 迭代上限为3次。\n     *\n     * @param clusterPhyName   集群名称\n     * @param metricsTypes     指标类型\n     * @param topNu            topN\n     * @param esNodesMaxNum    聚合节点数量最大值（agg bucket number）\n     * @param startTime        开始时间\n     * @param endTime          结束时间\n     * @return\n     */\n    private List<TopMetrics> getTopNNodeMetricsInfoWithStep(String clusterPhyName,\n                                                            List<String> nodeNamesUnderClusterLogic,\n                                                            List<String> metricsTypes, Integer topNu, String topMethod,\n                                                            Integer topTimeStep, int esNodesMaxNum, Long startTime,\n                                                            Long endTime) {\n\n        List<VariousLineChartMetrics> variousLineChartMetrics;\n        // 获取有数据的第一个时间点\n        Long timePoint = getHasDataTime(clusterPhyName, startTime, endTime,\n            DslsConstant.GET_HAS_NODE_METRICS_DATA_TIME);\n        //没有数据则提前终止\n        if (null == timePoint) {\n            return new ArrayList<>();\n        }\n\n        long startTimeForOneInterval = timePoint - topTimeStep;\n        long endTimeForOneInterval = timePoint;\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_CLUSTER_NODE_INFO_WITH_STEP,\n            clusterPhyName, startTimeForOneInterval, endTimeForOneInterval, esNodesMaxNum, STEP_INTERVAL,\n            buildAggsDSL(metricsTypes, topMethod), buildAggsDSLWithStep(metricsTypes, topMethod));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTimeForOneInterval,\n            endTimeForOneInterval);\n\n        variousLineChartMetrics = gatewayClient.performRequestWithRouting(metadataClusterName, null, realIndexName,\n            TYPE, dsl,\n            s -> fetchMultipleAggMetricsWithStep(s, metricsTypes, topNu, topMethod, nodeNamesUnderClusterLogic), 3);\n        return variousLineChartMetrics.stream().map(this::buildTopMetrics).collect(Collectors.toList());\n    }\n\n    /**\n     * 获取单个指标信息\n     *\n     * @param clusterPhyName    集群名称\n     * @param metrics           指标类型\n     * @param nodeName          节点名称\n     * @param aggType           聚合类型\n     * @param startTime         开始时间\n     * @param endTime           结束时间\n     * @return  List<VariousLineChartMetrics>\n     */\n    public List<VariousLineChartMetrics> getAggClusterPhySingleNodeMetrics(String clusterPhyName, List<String> metrics,\n                                                                           String nodeName, String aggType,\n                                                                           long startTime, long endTime) {\n        List<String> metricsLimit = new ArrayList<>();\n        metrics.forEach(metric -> {\n            if (metric.contains(BREAKERS)&&metric.contains(LIMIT_SIZE_IN_BYTES)) {\n                metricsLimit.add(metric.replaceAll(LIMIT_SIZE_IN_BYTES, ESTIMATED_SIZE_IN_BYTES));\n            }\n        });\n        metricsLimit.addAll(metrics);\n        String interval = MetricsUtils.getInterval(endTime - startTime);\n\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_AGG_CLUSTER_PHY_SINGLE_NODE_NODE,\n            clusterPhyName, nodeName, startTime, endTime, interval, buildAggsDSL(metricsLimit, aggType));\n\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, nodeName, realIndexName, TYPE, dsl,\n            s -> fetchSingleAggMetrics(s, metricsLimit, nodeName), 3);\n    }\n\n    /**\n     * 获取集群写文档总数\n     * @param cluster 集群名称\n     * @return {@link Long}\n     */\n    public Long getCurrentIndexTotal(String cluster) {\n        return commonGetCurrentAggMetrics(cluster, METRICS, INDEX_TOTAL, INDEX_TOTAL_FIELD);\n    }\n\n    /**\n     * 获取集群写文档总数\n     * @param cluster 集群名称\n     * @return {@link Long}\n     */\n    public Long getCurrentQueryTotal(String cluster) {\n        return commonGetCurrentAggMetrics(cluster, METRICS, QUERY_TOTAL, QUERY_TOTAL_FIELD);\n    }\n\n    /**\n     * 集群http连接数\n     *\n     * @param cluster 集群\n     * @return {@code Long}\n     */\n    public Long getHttpConnectionTotal(String cluster) {\n        return commonGetCurrentAggMetrics(cluster, METRICS, OPEN_HTTP, OPEN_HTTP_FIELD);\n    }\n\n    /**\n     * WriteRejected数\n     *\n     * @param cluster 集群 WriteRejectedNum\n     * @return {@code Long}\n     */\n    public Long getWriteRejectedNum(String cluster,String node) {\n        return commonGetNodeCurrentAggMetrics(cluster,node, METRICS, WRITE_REJECTED_TOTAL, THREAD_POOL_WRITE_REJECTED);\n    }\n\n    /**\n     * SearchRejected数\n     *\n     * @param cluster 集群 WriteRejectedNum\n     * @return {@code Long}\n     */\n    public Long getSearchRejectedNum(String cluster,String node) {\n        return commonGetNodeCurrentAggMetrics(cluster,node, METRICS, SEARCH_REJECTED_TOTAL, THREAD_POOL_SEARCH_REJECTED);\n    }\n\n    /**************************************** private methods ****************************************/\n    /**\n     *\n     * @param cluster          集群名称\n     * @param oneLevelMetrics  dsl中一级指标\n     * @param metricsType1     dsl中二级指标项1字段\n     * @param metricsType2     dsl中二级指标项2字段\n     * @return\n     */\n    private Long commonGetCurrentAggMetrics(String cluster, String oneLevelMetrics, String metricsType1,\n                                            String metricsType2) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_FIELD_SUM_AND_RANGE_FIELD_TOTAL, cluster,\n            TIMESTAMP, NOW_2M, NOW_1M, metricsType1, SUM.getType(), String.format(\"%s%s\", oneLevelMetrics, metricsType2));\n        String realIndexName = getIndexNameByNowTimestamp(indexName);\n        return gatewayClient.performRequest(cluster, realIndexName, TYPE, dsl,\n            response -> Optional.ofNullable(response).map(ESQueryResponse::getAggs).map(ESAggrMap::getEsAggrMap)\n                .map(map -> map.get(metricsType1)).map(ESAggr::getUnusedMap).map(map -> map.get(VALUE))\n                .map(String::valueOf).map(Double::parseDouble).map(Double::longValue).orElse(0L),\n            3);\n    }\n\n    /**\n     *\n     * @param cluster          集群名称\n     * @param oneLevelMetrics  dsl中一级指标\n     * @param metricsType1     dsl中二级指标项1字段\n     * @param metricsType2     dsl中二级指标项2字段\n     * @return\n     */\n    private Long commonGetNodeCurrentAggMetrics(String cluster,String node, String oneLevelMetrics, String metricsType1,\n                                            String metricsType2) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_NODE_FIELD_SUM_AND_RANGE_FIELD_TOTAL, cluster,node,\n                TIMESTAMP, NOW_2M, NOW_1M, metricsType1, SUM.getType(), String.format(\"%s%s\", oneLevelMetrics, metricsType2));\n        String realIndexName = getIndexNameByNowTimestamp(indexName);\n        return gatewayClient.performRequest(cluster, realIndexName, TYPE, dsl,\n                response -> Optional.ofNullable(response).map(ESQueryResponse::getAggs).map(ESAggrMap::getEsAggrMap)\n                        .map(map -> map.get(metricsType1)).map(ESAggr::getUnusedMap).map(map -> map.get(VALUE))\n                        .map(String::valueOf).map(Double::parseDouble).map(Double::longValue).orElse(0L),\n                3);\n    }\n\n    /**\n     * 根据现在时间戳获取IndexName\n     *\n     * @param indexName 索引名称\n     * @return {@code String}\n     */\n    private String getIndexNameByNowTimestamp(String indexName) {\n        return IndexNameUtils.genCurrentDailyIndexName(indexName);\n    }\n\n    private ClusterLogicDiskUsedInfoPO buildDiskInfoESQueryResponse(ESQueryResponse esQueryResponse) {\n        ClusterLogicDiskUsedInfoPO clusterLogicDiskUsedInfoPO = new ClusterLogicDiskUsedInfoPO();\n        if (esQueryResponse != null && esQueryResponse.getAggs() != null) {\n            Map<String, ESAggr> esAggrMap = esQueryResponse.getAggs().getEsAggrMap();\n            if (esAggrMap != null && esAggrMap.containsKey(\"hist\")) {\n                ESAggr minuteBucketESAggr = esAggrMap.get(\"hist\");\n                List<ESBucket> esBuckets = minuteBucketESAggr.getBucketList();\n                if (esBuckets.size() != 0) {\n                    Map<String, ESAggr> aggrMap = esBuckets.get(0).getAggrMap();\n                    Double total = Double.valueOf(aggrMap.get(\"diskTotal\").getUnusedMap().get(VALUE).toString());\n                    Double free = Double.valueOf(aggrMap.get(\"diskFree\").getUnusedMap().get(VALUE).toString());\n                    Double used = total - free;\n                    Double percent = used / total;\n                    clusterLogicDiskUsedInfoPO.setDiskTotal(total.longValue());\n                    clusterLogicDiskUsedInfoPO.setDiskUsage(used.longValue());\n                    clusterLogicDiskUsedInfoPO.setDiskUsagePercent(percent);\n                }\n            }\n        }\n        return clusterLogicDiskUsedInfoPO;\n    }\n\n    public Long getClusterStatusElapsedTime(String cluster) throws ESOperateException {\n        long startTime = System.currentTimeMillis();\n        getDirectResponse(cluster, \"GET\",\"_cluster/stats\");\n        long endTime = System.currentTimeMillis();\n        return endTime-startTime;\n    }\n\n    public Long getNodeStatusElapsedTime(String cluster) throws ESOperateException {\n        long startTime = System.currentTimeMillis();\n        getDirectResponse(cluster, \"GET\",\"_nodes/stats\");\n        long endTime = System.currentTimeMillis();\n        return endTime-startTime;\n    }\n\n    /**\n     * 取逻辑集群实时cpu分位值(统计节点维度)和平均使用率\n     * @param nodes\n     * @param phyClusterName\n     * @return\n     */\n    public Map<String, Double> getClusterLogicCpuAvgAndPercentiles(List<String> nodes,String phyClusterName) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_LOGIC_REAL_TIME_AVG_AND_PERCENT, phyClusterName,JSON.toJSONString(nodes),\n                NOW_2M, NOW_1M, CPU_USAGE_PERCENT.getType(), CPU_USAGE_PERCENT.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                this::getAvgAndPercentilesFromESQueryResponse, 3);\n    }\n\n    /**\n     * 获取逻辑集群磁盘空闲使用率分位值(统计节点维度)和平均使用率\n     */\n    public Map<String, Double> getClusterLogicDiskFreeUsagePercentAvgAndPercentiles(List<String> nodes,String phyClusterName) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(\n                DslsConstant.AGG_CLUSTER_LOGIC_AVG_AND_PERCENT_FOR_DISK_FREE_USAGE_PERCENT,phyClusterName, JSON.toJSONString(nodes), NOW_2M, NOW_1M);\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                this::getAvgAndPercentilesFromESQueryResponse, 3);\n    }\n\n    /**\n     * 获取逻辑集群实时cpu load 1m分位值(统计节点维度)和平均使用率\n     *\n     * @param nodes\n     * @return\n     */\n    public Map<String, Double> getClusterLogicCpuLoad1MinAvgAndPercentiles(List<String> nodes,String phyClusterName) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_LOGIC_REAL_TIME_AVG_AND_PERCENT, phyClusterName,JSON.toJSONString(nodes),\n                NOW_2M, NOW_1M, CPU_LOAD_AVERAGE_1M.getType(), CPU_LOAD_AVERAGE_1M.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                this::getAvgAndPercentilesFromESQueryResponse, 3);\n    }\n\n    /**\n     * 获取集群实时cpu load 5m分位值(统计节点维度)和平均使用率\n     *\n     * @param nodes\n     * @return\n     */\n    public Map<String, Double> getClusterLogicCpuLoad5MinAvgAndPercentiles(List<String> nodes,String phyClusterName) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_LOGIC_REAL_TIME_AVG_AND_PERCENT,phyClusterName, JSON.toJSONString(nodes),\n                NOW_2M, NOW_1M, CPU_LOAD_AVERAGE_5M.getType(), CPU_LOAD_AVERAGE_5M.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                this::getAvgAndPercentilesFromESQueryResponse, 3);\n    }\n\n    /**\n     * 获取集群实时cpu load 15m分位值(统计节点维度)和平均使用率\n     *\n     * @param nodes\n     * @return\n     */\n    public Map<String, Double> getClusterLogicCpuLoad15MinAvgAndPercentiles(List<String> nodes,String phyClusterName) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_LOGIC_REAL_TIME_AVG_AND_PERCENT,phyClusterName, JSON.toJSONString(nodes),\n                NOW_2M, NOW_1M, CPU_LOAD_AVERAGE_15M.getType(), CPU_LOAD_AVERAGE_15M.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                this::getAvgAndPercentilesFromESQueryResponse, 3);\n\n    }\n\n    /**\n     * 获取逻辑集群QPS\n     * @param nodes\n     * @return\n     */\n    public Double getClusterLogicQps(String phyClusterName,List<String> nodes) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_LOGIC_REAL_TIME_TPS_QPS_INFO, phyClusterName,JSON.toJSONString(nodes),\n                \"now-2m\", \"now-1m\", INDICES_QUERY_RATE.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 根据逻辑集群名称，获取集群[now-2m, now-1m]总的tps\n     * @param phyClusterName\n     * @return\n     */\n    public double getClusterLogicTps(String phyClusterName,List<String> nodes) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_LOGIC_REAL_TIME_TPS_QPS_INFO, phyClusterName,JSON.toJSONString(nodes),\n                \"now-2m\", \"now-1m\", INDICES_INDEXING_RATE.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 根据逻辑集群名称，获取集群[now-2m, now-1m]总的接收的流量\n     * @param nodes 集群\n     * @return\n     */\n    public Double getClusterLogicRx(String phyClusterName,List<String> nodes) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_LOGIC_REAL_TIME_RX_TX_INFO, phyClusterName,JSON.toJSONString(nodes),\n                NOW_2M, NOW_1M, TRANS_RX_SIZE.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 根据逻辑集群名称，获取集群[now-2m, now-1m]总的发送的流量\n     * @param nodes\n     * @return\n     */\n    public Double getClusterLogicTx(String phyClusterName,List<String> nodes) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_CLUSTER_LOGIC_REAL_TIME_RX_TX_INFO, phyClusterName,JSON.toJSONString(nodes),\n                NOW_2M, NOW_1M, TRANS_TX_SIZE.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(realIndex, TYPE, dsl, s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 获取集群查询耗时分位值(统计节点维度)和平均使用率\n     */\n    public double getClusterLogicSearchLatencySum(String phyClusterName,List<String> nodes) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_LOGIC_INDEXING_SEARCH_TIME_SUM, phyClusterName,JSON.toJSONString(nodes),\n                NOW_2M, NOW_1M, INDICES_QUERY_TIME_IN_MILLIS.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 获取集群所有节点间隔时间nodes.{nodeName}.indices.search.query_total差值累加值\n     * @param cluster 集群名称\n     * @return\n     */\n    public double getClusterLogicSearchQueryTotal(String phyClusterName,List<String> nodes){\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_LOGIC_INDEXING_SEARCH_TIME_SUM, phyClusterName,JSON.toJSONString(nodes),\n                NOW_2M, NOW_1M, INDICES_QUERY_TOTAL.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 获取集群写入耗时分位值(统计节点维度)和平均使用率\n     */\n    public double getClusterLogicIndexingLatencySum(String phyClusterName,List<String> nodes) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_LOGIC_INDEXING_SEARCH_TIME_SUM,phyClusterName, JSON.toJSONString(nodes),\n                NOW_2M, NOW_1M, INDICES_INDEXING_LATENCY.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n\n    /**\n     * 获取集群所有节点间隔时间nodes.{nodeName}.indices.docs.count差值累加值\n     * @param nodes 集群下的节点\n     * @return\n     */\n    public double getClusterLogicIndexingDocSum(String phyClusterName,List<String> nodes) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.AGG_CLUSTER_LOGIC_INDEXING_SEARCH_TIME_SUM,phyClusterName, JSON.toJSONString(nodes),\n                NOW_2M, NOW_1M, INDICES_NUM_DIFF.getType());\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n\n        return gatewayClient.performRequest(metadataClusterName, realIndex, TYPE, dsl,\n                s -> getSumFromESQueryResponse(s, \"sum\"), 3);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/stats/BaseAriusStatsESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.JSONPath;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContentCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.TopMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ESClusterTaskDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.BaseESPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusStatsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PercentilesEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.OneLevelTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.DateTimeUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.index.IndexCatESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESAggr;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.aggs.ESBucket;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHits;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\n\nimport java.beans.IntrospectionException;\nimport java.beans.PropertyDescriptor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.math.BigDecimal;\nimport java.util.*;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterPhyMetricsConstant.*;\nimport static com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsDashBoardInfoESDAO.INDEX_COUNT;\n\n@NoArgsConstructor\npublic class BaseAriusStatsESDAO extends BaseESDAO {\n\n    @Value(\"${es.metrics.cluster.buckets.max.num}\")\n    protected int                                                         clusterMaxNum;\n\n    @Value(\"${es.metrics.nodes.buckets.max.num}\")\n    protected int                                                         esNodesMaxNum;\n\n    @Value(\"${es.update.cluster.name}\")\n    protected String                                                      metadataClusterName;\n\n    @Value(\"${es.metrics.indices.buckets.max.num}\")\n    protected int                                                         indicesBucketsMaxNum;\n    /**\n     * 操作的索引名称\n     */\n    protected String                                                      indexName;\n\n    /**\n     * 索引type名称为type\n     */\n    protected static final String                                         TYPE                    = \"type\";\n\n    protected static final int                                            SCROLL_SIZE             = 5000;\n    protected static final Long                                           ONE_GB                  = 1024 * 1024 * 1024L;\n\n    protected static final String                                         NOW_7M                  = \"now-7m\";\n    protected static final String                                         NOW_6M                  = \"now-6m\";\n    protected static final String                                         NOW_5M                  = \"now-5m\";\n    protected static final String                                         NOW_4M                  = \"now-4m\";\n    protected static final String                                         NOW_2M                  = \"now-2m\";\n    protected static final String                                         NOW_3M                  = \"now-3m\";\n    protected static final String                                         NOW_1M                  = \"now-1m\";\n    protected static final String                                         DEFAULT_AGG             = \"avg\";\n    public static final String                                            INDEX_INDEX_TOTAL_DIFF  = \"indexing-index_total\";\n    public static final String                                            SEARCH_QUERY_TOTAL_DIFF = \"search-query_total\";\n\n    public static final String                                            STEP_INTERVAL           = \"1m\";\n    public static final String                                            STEP_METHOD_AVG         = \"avg\";\n    public static final String                                            STEP_METHOD_MAX         = \"max\";\n    public static final String                                            BUCKETS_PATH            = \"buckets_path\";\n    public static final String                                            HISTS_GT                = \"hist>\";\n    public static final String                                            BUCKET                  = \"_bucket\";\n    public static final String                                            VALUE                   = \"value\";\n\n    @Autowired\n    private IndexCatESDAO indexCatESDAO;\n\n    /**\n     * 不同维度es监控数据\n     */\n    private static Map<AriusStatsEnum/*stats type*/, BaseAriusStatsESDAO> ariusStatsEsDaoMap      = Maps\n        .newConcurrentMap();\n\n    public static BaseAriusStatsESDAO getByStatsType(AriusStatsEnum statsType) {\n        return ariusStatsEsDaoMap.get(statsType);\n    }\n\n    /**\n     * 注册不同维度数据对应操作的es类\n     *\n     * @param statsType\n     * @param baseAriusStatsEsDao\n     */\n    public static void register(AriusStatsEnum statsType, BaseAriusStatsESDAO baseAriusStatsEsDao) {\n        ariusStatsEsDaoMap.put(statsType, baseAriusStatsEsDao);\n    }\n\n    /**\n     * 批量插入索引统计信息\n     *\n     * @param statsInfo\n     */\n    public void batchInsertStats(List<? extends BaseESPO> statsInfo) {\n        String realIndex = IndexNameUtils.genCurrentDailyIndexName(indexName);\n        updateClient.batchInsert(realIndex, TYPE, statsInfo);\n    }\n\n    /**\n     * 从es返回结果中得到求和值\n     *\n     * @param response\n     * @param sumKey\n     * @return\n     */\n    Double getSumFromESQueryResponse(ESQueryResponse response, String sumKey) {\n        if (null == response || response.getAggs() == null) {\n            LOGGER.warn(\"class=BaseAriusStatsEsDao||method=getSumFromESQueryResponse||msg=response is null\");\n            return 0d;\n        }\n\n        String value = null;\n        try {\n            Map<String, ESAggr> esAggrMap = response.getAggs().getEsAggrMap();\n\n            if (esAggrMap != null && esAggrMap.containsKey(sumKey) && esAggrMap.get(sumKey).getUnusedMap() != null\n                && esAggrMap.get(sumKey).getUnusedMap().get(\"value\") != null) {\n                value = esAggrMap.get(sumKey).getUnusedMap().get(\"value\").toString();\n                return Double.valueOf(value);\n            }\n\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=BaseAriusStatsEsDao||method=getSumFromESQueryResponse||sumKey={}||value={}||response={}\", sumKey,\n                value, response, e);\n        }\n        return 0d;\n    }\n\n    Map<String, Double> getAvgAndPercentilesFromESQueryResponse(ESQueryResponse response) {\n        Map<String, Double> percentiles2ValueMap = Maps.newHashMap();\n        if (null == response || null == response.getAggs()) {\n            LOGGER.warn(\n                \"class=BaseAriusStatsEsDao||method=getAvgAndPercentilesFromESQueryResponse||msg=response is null\");\n            return percentiles2ValueMap;\n        }\n\n        try {\n            Map<String, ESAggr> esAggrMap = response.getAggs().getEsAggrMap();\n            if (null != esAggrMap) {\n                //构建分位值\n                setPercentiles(percentiles2ValueMap, esAggrMap);\n\n                //构建平均值\n                if (null != esAggrMap.get(AVG) && null != esAggrMap.get(AVG).getUnusedMap()\n                    && null != esAggrMap.get(AVG).getUnusedMap().get(VALUE)) {\n                    Map<String, Object> avgMapFromES = esAggrMap.get(AVG).getUnusedMap();\n                    percentiles2ValueMap.put(AVG, Double.valueOf(avgMapFromES.get(VALUE).toString()));\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=BaseAriusStatsEsDao||method=getAvgAndPercentilesFromESQueryResponse||response={}\",\n                response, e);\n        }\n\n        return percentiles2ValueMap;\n    }\n\n    /**\n     * 生成查询的索引名称，默认7天\n     *\n     * @param indexCount\n     * @return\n     */\n    String genIndexNames(Integer indexCount) {\n        try {\n            if (indexCount == null) {\n                indexCount = 7;\n            }\n\n            List<String> indices = Lists.newArrayList();\n\n            for (int day = 0; day < indexCount; day++) {\n                String realIndexName = this.indexName.concat(\"_\").concat(DateTimeUtil.getFormatDayByOffset(day))\n                    .concat(\"*\");\n                indices.add(realIndexName);\n            }\n            return StringUtils.join(indices, \",\");\n\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=BaseAriusStatsEsDao||method=genIndexNames||errMsg=gen last 7 days index names error.||stack={}\",\n                e);\n        }\n\n        // 异常时查询所有时间段的索引\n        return this.indexName.concat(\"*\");\n    }\n\n    <T> List<T> fetchAggClusterPhyMetrics(ESQueryResponse response, Class<T> clazz) {\n        List<T> aggMetrics = Lists.newCopyOnWriteArrayList();\n\n        if (response == null || response.getAggs() == null) {\n            return aggMetrics;\n        }\n\n        try {\n            Map<String, ESAggr> esAggrMap = response.getAggs().getEsAggrMap();\n            if (null != esAggrMap && null != esAggrMap.get(HIST)) {\n                esAggrMap.get(HIST).getBucketList().parallelStream().forEach(r -> {\n\n                    T obj;\n                    long timeStamp = 0;\n                    try {\n                        obj = clazz.newInstance();\n                        if (null != r.getUnusedMap() && null != r.getUnusedMap().get(KEY)) {\n                            timeStamp = Long.parseLong(r.getUnusedMap().get(KEY).toString());\n                        }\n                        handleFields(r, obj, timeStamp);\n                        aggMetrics.add(obj);\n                    } catch (Exception e) {\n                        LOGGER.error(\n                            \"class=BaseAriusStatsESDAO||method=fetchAggClusterPhyMetrics||errMsg=exception! response:{}\",\n                            response.toString(), e);\n                    }\n                });\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=BaseAriusStatsESDAO||method=fetchAggClusterPhyMetrics||errMsg=exception! response:{}\",\n                response.toString(), e);\n        }\n        return aggMetrics;\n    }\n\n    private <T> void handleFields(ESBucket eSBucket, T obj, long timeStamp) throws IntrospectionException,\n                                                                            IllegalAccessException,\n                                                                            InvocationTargetException {\n        for (Field field : Objects.requireNonNull(obj).getClass().getDeclaredFields()) {\n            PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass());\n            //1. get method of setter\n            Method writeMethod = pd.getWriteMethod();\n            Class<?>[] parameterTypes = writeMethod.getParameterTypes();\n\n            //获取时间戳\n            if (TIME_STAMP.equals(field.getName()) && parameterTypes.length > 0) {\n                String type = parameterTypes[0].getName();\n                if (LONG.equals(type)) {\n                    writeMethod.invoke(obj, timeStamp);\n                    continue;\n                }\n            }\n\n            //获取统计数据\n            handleStatisticalData(eSBucket, obj, field, writeMethod, parameterTypes);\n        }\n    }\n\n    private <T> void handleStatisticalData(ESBucket eSBucket, T obj, Field field, Method writeMethod,\n                                           Class<?>[] parameterTypes) throws IllegalAccessException,\n                                                                      InvocationTargetException {\n        String metricKey = field.getName();\n        if (null != eSBucket.getAggrMap() && null != eSBucket.getAggrMap().get(metricKey)\n            && null != eSBucket.getAggrMap().get(metricKey).getUnusedMap().get(VALUE) && parameterTypes.length > 0) {\n            String type = parameterTypes[0].getName();\n            if (DOUBLE.equals(type)) {\n                writeMethod.invoke(obj,\n                    Double.valueOf(eSBucket.getAggrMap().get(metricKey).getUnusedMap().get(VALUE).toString()));\n            }\n            if (LONG.equals(type)) {\n                writeMethod.invoke(obj, Double\n                    .valueOf(eSBucket.getAggrMap().get(metricKey).getUnusedMap().get(VALUE).toString()).longValue());\n            }\n            if (INT.equals(type)) {\n                writeMethod.invoke(obj, Double\n                    .valueOf(eSBucket.getAggrMap().get(metricKey).getUnusedMap().get(VALUE).toString()).intValue());\n            }\n        }\n    }\n\n    /**\n     * 利用反射获取属性\n     * 注意：入参的clazz 中 timeStamp 放置在类属性的第一位置 来适配反射的应用\n     * {\n     *         \"max_shardNu\": {\n     *           \"max\": {\n     *             \"field\": \"statis.writeTps\"\n     *           }\n     *         },\n     *         \"max_unAssignedShards\": {\n     *           \"max\": {\n     *             \"field\": \"statis.readTps\"\n     *           }\n     *         },\n     *         ...\n     *       }\n     */\n    <T> String buildAggsDSL(Class<T> clazz, String aggType) {\n        StringBuilder sb = new StringBuilder();\n        Field[] fields = clazz.getDeclaredFields();\n        for (int i = 0; i < fields.length; i++) {\n            if (TIME_STAMP.equals(fields[i].getName())) {\n                continue;\n            }\n\n            Map<String, String> aggsSubSubCellMap = Maps.newHashMap();\n            aggsSubSubCellMap.put(FIELD, STATIS + fields[i].getName());\n\n            buildAggsDslMap(aggType, sb, fields[i].getName(), aggsSubSubCellMap);\n            if (i != fields.length - 1) {\n                sb.append(\",\").append(\"\\n\");\n            }\n        }\n\n        return sb.toString();\n    }\n\n    /**\n     * example\n     *\n     * \"os-cpu-percent\":{\"max\":{\"field\":\"metrics.os-cpu-percent\"}},\n     * \"fs-total-disk_free_percent\":{\"max\":{\"field\":\"metrics.fs-total-disk_free_percent\"}},\n     * \"os-cpu-load_average-1m\":{\"max\":{\"field\":\"metrics.os-cpu-load_average-1m\"}},\n     * \"os-cpu-load_average-5m\":{\"max\":{\"field\":\"metrics.os-cpu-load_average-5m\"}},\n     * \"os-cpu-load_average-15m\":{\"max\":{\"field\":\"metrics.os-cpu-load_average-15m\"}},\n     * \"transport-tx_count_rate\":{\"max\":{\"field\":\"metrics.transport-tx_count_rate\"}},\n     *\n     * @param metrics\n     * @param aggType\n     * @return\n     */\n    String buildAggsDSL(List<String> metrics, String aggType) {\n        StringBuilder sb = new StringBuilder();\n\n        for (int i = 0; i < metrics.size(); i++) {\n            String metricName = metrics.get(i);\n            Map<String, String> aggsSubSubCellMap = Maps.newHashMap();\n            aggsSubSubCellMap.put(FIELD, METRICS + metricName);\n\n            buildAggsDslMap(aggType, sb, metricName, aggsSubSubCellMap);\n            if (i != metrics.size() - 1) {\n                sb.append(\",\").append(\"\\n\");\n            }\n        }\n\n        return sb.toString();\n    }\n\n    /**\n     * 根据topMethod构造获取最大值/平均值dsl\n     * @param metrics\n     * @param topMethod\n     * @return\n     *\n     * ,\"shardNu_avg_value\":{\"avg_bucket\":{\"buckets_path\":\"hist>shardNu\"}},\n     * \"docs-count_avg_value\":{\"avg_bucket\":{\"buckets_path\":\"hist>docs-count\"}},\n     * \"store-size_in_bytes_avg_value\":{\"avg_bucket\":{\"buckets_path\":\"hist>store-size_in_bytes\"}}\n     */\n    String buildAggsDSLWithStep(List<String> metrics, String topMethod) {\n        StringBuilder sb = new StringBuilder();\n        sb.append(\",\");\n        for (int i = 0; i < metrics.size(); i++) {\n            String metricName = metrics.get(i);\n            Map<String, Object> aggsSubSubCellMap = new HashMap();\n            Map bucket = new HashMap();\n\n            Map bucketsPath = new HashMap();\n            bucketsPath.put(BUCKETS_PATH, HISTS_GT + metricName);\n            bucket.put(topMethod + BUCKET, bucketsPath);\n\n            aggsSubSubCellMap.put(metricName + \"_\" + topMethod + \"_\" + VALUE, bucket);\n            JSONObject jsonObject = new JSONObject(aggsSubSubCellMap);\n            String str = jsonObject.toJSONString();\n            sb.append(str, 1, str.length() - 1);\n\n            if (i != metrics.size() - 1) {\n                sb.append(\",\").append(\"\\n\");\n            }\n        }\n        return sb.toString();\n    }\n\n    protected void buildAggsDslMap(String aggType, StringBuilder sb, String metricName,\n                                   Map<String, String> aggsSubSubCellMap) {\n        Map<String, Object> aggsSubCellMap = Maps.newHashMap();\n        aggsSubCellMap.put(aggType, aggsSubSubCellMap);\n\n        Map<String, Object> aggsCellMap = Maps.newHashMap();\n        aggsCellMap.put(metricName, aggsSubCellMap);\n\n        JSONObject jsonObject = new JSONObject(aggsCellMap);\n        String str = jsonObject.toJSONString();\n        sb.append(str, 1, str.length() - 1);\n    }\n\n    /**\n     * 根据时间段内的值值进行倒排\n     */\n    void mergeTopNuWithStep(VariousLineChartMetrics variousLineChartsMetrics, Integer topNu,\n                            List<String> nodeNamesUnderClusterLogic) {\n        List<MetricsContent> sortedList;\n        sortedList = variousLineChartsMetrics.getMetricsContents().stream()\n                //如果nodeNamesUnderClusterLogic为空，就是索引和模板，不需要这里拦截\n                //如果是节点，nodeNamesUnderClusterLogic就不为空，就判断拦截\n            .filter(metricsContent -> CollectionUtils.isEmpty(nodeNamesUnderClusterLogic)\n                                      || (nodeNamesUnderClusterLogic.contains(metricsContent.getName())))\n            .sorted(Comparator.comparing(x -> x.getValueInTimePeriod(), Comparator.reverseOrder()))\n            .limit(topNu != null ? topNu : 0).collect(Collectors.toList());\n\n        //根据第一个时间点的值进行倒排，取topNu\n        variousLineChartsMetrics.setMetricsContents(sortedList);\n    }\n\n    /**\n     * 根据第一个时间点的值进行倒排，取topNu\n     */\n    void mergeTopNu(VariousLineChartMetrics variousLineChartsMetrics, Integer topNu) {\n        //根据第一个时间点的值进行倒排，取topNu\n        List<MetricsContent> sortedList = variousLineChartsMetrics.getMetricsContents().stream()\n            .sorted(Comparator.comparing(x -> x.getMetricsContentCells().get(0).getValue(), Comparator.reverseOrder()))\n            .limit(topNu != null ? topNu : 0).collect(Collectors.toList());\n\n        variousLineChartsMetrics.setMetricsContents(sortedList);\n    }\n\n    /**\n     * 获取单个ES实例/索引名称的指标信息\n     * @param s                es响应体\n     * @param metricsKeys      指标key\n     * @param name             ES节点名称/索引名称/节点任务\n     * @return\n     */\n    List<VariousLineChartMetrics> fetchSingleAggMetrics(ESQueryResponse s, List<String> metricsKeys, String name) {\n        List<VariousLineChartMetrics> variousLineChartsMetrics = Lists.newArrayList();\n\n        if (null == s || s.getAggs() == null) {\n            LOGGER.warn(\"class=BaseAriusStatsESDAO||method=fetchSingleAggMetrics||msg=esQueryResponse is null\");\n            return variousLineChartsMetrics;\n        }\n\n        Map<String, ESAggr> esAggrMap = s.getAggs().getEsAggrMap();\n        if (null != esAggrMap && null != esAggrMap.get(HIST)) {\n            for (String metricsKey : metricsKeys) {\n\n                try {\n                    variousLineChartsMetrics.add(buildVariousLineChartMetricsForOneNode(metricsKey, name, esAggrMap));\n                } catch (Exception e) {\n                    LOGGER.error(\n                        \"class=BaseAriusStatsESDAO||method=fetchSingleAggMetrics||name={}||metricsKey={}||errMsg=exception! response:{}\",\n                        name, metricsKey, e);\n                }\n            }\n        }\n\n        return variousLineChartsMetrics;\n    }\n\n    /**\n     *  此方法是用来处理非负型指标\n     * @param\n     * @param\n     * @param topNu\n     * @return\n     */\n    List<VariousLineChartMetrics> fetchMultipleNoNegativeAggMetrics(ESQueryResponse response, String oneLevelType,\n                                                                    List<String> metricsKeys, Integer topNu) {\n        List<VariousLineChartMetrics> variousLineChartsMetrics = Lists.newArrayList();\n\n        if (null == response || response.getAggs() == null) {\n            LOGGER.warn(\"class=BaseAriusStatsESDAO||method=fetchMultipleAggMetrics||msg=esQueryResponse is null\");\n            return variousLineChartsMetrics;\n        }\n        Map<String, ESAggr> esAggrMap = response.getAggs().getEsAggrMap();\n        if (null != esAggrMap && null != esAggrMap.get(HIST)) {\n            metricsKeys.stream()\n                //对非负型指标进行获取\n                .map(key -> buildVariousLineNoNegativeChartMetrics(oneLevelType, key, esAggrMap))\n                //过滤除节点指标为空的状态\n                .filter(\n                    variousLineChartMetric -> CollectionUtils.isNotEmpty(variousLineChartMetric.getMetricsContents()))\n                .forEach(variousLineChartsMetrics::add);\n        }\n\n        //get topNu\n        if (topNu != null) {\n            variousLineChartsMetrics.forEach(metrics -> mergeTopNu(metrics, topNu));\n        }\n        return variousLineChartsMetrics;\n    }\n\n    /**\n     * @param response    返回值\n     * @param metricsKeys 多个指标类型\n     * @param topNu       topN\n     * @return 结果\n     */\n    List<VariousLineChartMetrics> fetchMultipleAggMetricsWithStep(ESQueryResponse response, List<String> metricsKeys,\n                                                                  Integer topNu, String topMethod,\n                                                                  List<String> nodeNamesUnderClusterLogic) {\n        List<VariousLineChartMetrics> variousLineChartsMetrics = Lists.newArrayList();\n\n        if (null == response || response.getAggs() == null) {\n            LOGGER.warn(\"class=BaseAriusStatsESDAO||method=fetchMultipleAggMetrics||msg=esQueryResponse is null\");\n            return variousLineChartsMetrics;\n        }\n\n        Map<String, ESAggr> esAggrMap = response.getAggs().getEsAggrMap();\n        if (null != esAggrMap && null != esAggrMap.get(HIST)) {\n            metricsKeys.forEach(\n                key -> variousLineChartsMetrics.add(buildVariousLineChartMetricsWithStep(key, esAggrMap, topMethod)));\n        }\n\n        //get topNu\n        if (topNu != null) {\n            variousLineChartsMetrics.forEach(metrics -> mergeTopNuWithStep(metrics, topNu, nodeNamesUnderClusterLogic));\n        }\n\n        return variousLineChartsMetrics;\n    }\n\n    /**\n     *\n     * @param response         返回值\n     * @param oneLevelType     一级指标类型(@link OneLevelTypeEnum)\n     * @param metricsKeys      多个指标类型\n     * @param topNu            topN\n     * @return                 结果\n     */\n    List<VariousLineChartMetrics> fetchMultipleAggMetrics(ESQueryResponse response, String oneLevelType,\n                                                          List<String> metricsKeys, Integer topNu) {\n        List<VariousLineChartMetrics> variousLineChartsMetrics = Lists.newArrayList();\n\n        if (null == response || response.getAggs() == null) {\n            LOGGER.warn(\"class=BaseAriusStatsESDAO||method=fetchMultipleAggMetrics||msg=esQueryResponse is null\");\n            return variousLineChartsMetrics;\n        }\n\n        Map<String, ESAggr> esAggrMap = response.getAggs().getEsAggrMap();\n        if (null != esAggrMap && null != esAggrMap.get(HIST)) {\n            metricsKeys.forEach(\n                key -> variousLineChartsMetrics.add(buildVariousLineChartMetrics(oneLevelType, key, esAggrMap)));\n        }\n\n        //get topNu\n        if (topNu != null) {\n            variousLineChartsMetrics.forEach(metrics -> mergeTopNu(metrics, topNu));\n        }\n\n        return variousLineChartsMetrics;\n    }\n\n    TopMetrics buildTopMetrics(VariousLineChartMetrics variousLineChartMetrics) {\n        TopMetrics topMetrics = new TopMetrics();\n        topMetrics.setType(variousLineChartMetrics.getType());\n        List<String> topNames = variousLineChartMetrics.getMetricsContents().stream().map(MetricsContent::getName)\n            .collect(Collectors.toList());\n        topMetrics.setTopNames(topNames);\n        return topMetrics;\n    }\n\n    String buildTopNameStr(List<String> topName) {\n        StringBuilder topNameStrSb = new StringBuilder();\n        topNameStrSb.append(\"[\");\n        for (int i = 0; i < topName.size(); i++) {\n            topNameStrSb.append(\"\\\"\").append(topName.get(i)).append(\"\\\"\");\n            if (i == topName.size() - 1) {\n                topNameStrSb.append(\"]\");\n            } else {\n                topNameStrSb.append(\",\");\n            }\n        }\n        return topNameStrSb.toString();\n    }\n\n    /**********************************************private*************************************************/\n\n    private VariousLineChartMetrics buildVariousLineChartMetricsForOneNode(String key, String nodeName,\n                                                                           Map<String, ESAggr> esAggrMap) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(key);\n        variousLineChartMetrics.setMetricsContents(buildMetricsContentsForOneNode(key, nodeName, esAggrMap));\n        return variousLineChartMetrics;\n    }\n\n    private List<MetricsContent> buildMetricsContentsForOneNode(String key, String nodeName,\n                                                                Map<String, ESAggr> esAggrMap) {\n        List<MetricsContent> metricsContents = Lists.newArrayList();\n        MetricsContent metricsContent = new MetricsContent();\n        metricsContent.setName(nodeName);\n\n        List<MetricsContentCell> contentCells = Lists.newArrayList();\n        esAggrMap.get(HIST).getBucketList().forEach(esBucket -> {\n            if (null != esBucket.getUnusedMap().get(KEY)) {\n                contentCells.add(buildMetricsContentCellsForOneNode(key, esBucket));\n            }\n        });\n\n        metricsContent.setMetricsContentCells(contentCells);\n        metricsContents.add(metricsContent);\n        return metricsContents;\n\n    }\n\n    private MetricsContentCell buildMetricsContentCellsForOneNode(String key, ESBucket esBucket) {\n        MetricsContentCell metricsContentCell = new MetricsContentCell();\n        //get value\n        ESAggr value = esBucket.getAggrMap().get(key);\n        if (null != value && null != value.getUnusedMap().get(VALUE)) {\n            metricsContentCell.setValue(Double.parseDouble(value.getUnusedMap().get(VALUE).toString()));\n        }\n\n        //get time\n        if (null != esBucket.getUnusedMap().get(KEY)) {\n            metricsContentCell.setTimeStamp(Long.parseLong(esBucket.getUnusedMap().get(KEY).toString()));\n        }\n\n        return metricsContentCell;\n    }\n\n    private VariousLineChartMetrics buildVariousLineChartMetricsWithStep(String key, Map<String, ESAggr> esAggrMap,\n                                                                         String topMethod) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(key);\n        variousLineChartMetrics.setMetricsContents(buildMetricsContentsWithStep(null, key, esAggrMap, topMethod));\n        return variousLineChartMetrics;\n    }\n\n    private VariousLineChartMetrics buildVariousLineChartMetrics(String oneLevelType, String key,\n                                                                 Map<String, ESAggr> esAggrMap) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(key);\n        variousLineChartMetrics.setMetricsContents(buildMetricsContents(oneLevelType, key, esAggrMap));\n        return variousLineChartMetrics;\n    }\n\n    private VariousLineChartMetrics buildVariousLineNoNegativeChartMetrics(String oneLevelType, String key,\n                                                                           Map<String, ESAggr> esAggrMap) {\n        VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics();\n        variousLineChartMetrics.setType(key);\n        variousLineChartMetrics.setMetricsContents(buildMetricsNoNegativeContents(oneLevelType, key, esAggrMap));\n        return variousLineChartMetrics;\n    }\n\n    private List<MetricsContent> buildMetricsNoNegativeContents(String oneLevelType, String key,\n                                                                Map<String, ESAggr> esAggrMap) {\n        List<MetricsContent> metricsContents = Lists.newArrayList();\n\n        if (Objects.nonNull(esAggrMap.get(HIST))) {\n            final List<ESBucket> bucketList = esAggrMap.get(HIST).getBucketList();\n            if (CollectionUtils.isNotEmpty(bucketList)) {\n                for (ESBucket esBucket : bucketList) {\n                    //get nodeName\n                    if (null != esBucket.getUnusedMap()) {\n                        MetricsContent metricsContent = new MetricsContent();\n                        if (Objects.nonNull(esBucket.getUnusedMap().get(KEY))) {\n                            String keyValue = esBucket.getUnusedMap().get(KEY).toString();\n                            if (null != oneLevelType\n                                && OneLevelTypeEnum.listNoClusterOneLevelType().contains(oneLevelType)) {\n                                // 针对非集群维度指标，需要区分节点、模板、索引等所属集群\n                                String[] keyArr = keyValue.split(\"@\");\n                                if (keyArr.length > 1) {\n                                    String clusterName = keyArr[0];\n                                    String name/*节点、模板、索引等名称*/ = keyArr[1];\n                                    metricsContent.setCluster(clusterName);\n                                    metricsContent.setName(name);\n                                }\n                            } else {\n                                // 针对集群维度指标\n                                metricsContent.setName(keyValue);\n                                metricsContent.setCluster(keyValue);\n                            }\n                            final List<MetricsContentCell> metricsContentCells = buildMetricsNoNegativeContentCells(key,\n                                esBucket);\n                            //确定指标集合不为空\n                            if (CollectionUtils.isNotEmpty(metricsContentCells)) {\n                                metricsContent.setMetricsContentCells(metricsContentCells);\n                                metricsContents.add(metricsContent);\n                            }\n                        }\n\n                    }\n                }\n            }\n        }\n        return metricsContents;\n    }\n\n    private List<MetricsContent> buildMetricsContentsWithStep(String oneLevelType, String key,\n                                                              Map<String, ESAggr> esAggrMap, String topMethod) {\n        List<MetricsContent> metricsContents = Lists.newArrayList();\n        esAggrMap.get(HIST).getBucketList().forEach(esBucket -> {\n            if (null != esBucket.getUnusedMap().get(KEY)) {\n                MetricsContent metricsContent = new MetricsContent();\n                String itemName = esBucket.getUnusedMap().get(KEY).toString();\n                metricsContent.setName(itemName);\n                //例如：http-current_open_max_value\n                ESAggr esAggr = esBucket.getAggrMap().get(key + \"_\" + topMethod + \"_value\");\n                Double valueInTimePeriod = Optional.ofNullable(esAggr.getUnusedMap().get(\"value\"))\n                    .map(val -> Double.valueOf(val.toString())).orElse(0D);\n                metricsContent.setValueInTimePeriod(valueInTimePeriod);\n                metricsContents.add(metricsContent);\n            }\n        });\n        return metricsContents;\n    }\n\n    private List<MetricsContent> buildMetricsContents(String oneLevelType, String key, Map<String, ESAggr> esAggrMap) {\n        List<MetricsContent> metricsContents = Lists.newArrayList();\n        esAggrMap.get(HIST).getBucketList().forEach(esBucket -> {\n            //get nodeName\n            if (null != esBucket.getUnusedMap().get(KEY)) {\n                MetricsContent metricsContent = new MetricsContent();\n                String keyValue = esBucket.getUnusedMap().get(KEY).toString();\n                if (null != oneLevelType && OneLevelTypeEnum.listNoClusterOneLevelType().contains(oneLevelType)) {\n                    // 针对非集群维度指标，需要区分节点、模板、索引等所属集群\n                    String[] keyArr = keyValue.split(\"@\");\n                    if (keyArr.length > 1) {\n                        String clusterName = keyArr[0];\n                        String name/*节点、模板、索引等名称*/ = keyArr[1];\n                        metricsContent.setCluster(clusterName);\n                        metricsContent.setName(name);\n                    }\n                } else {\n                    // 针对集群维度指标\n                    metricsContent.setName(keyValue);\n                    metricsContent.setCluster(keyValue);\n                }\n                buildMetricsContentCells(metricsContent,key, esBucket);\n                metricsContents.add(metricsContent);\n            }\n        });\n\n        return metricsContents;\n    }\n\n    private void buildMetricsContentCells(MetricsContent metricsContent,String key, ESBucket esBucket) {\n        List<MetricsContentCell> metricsContentCells = Lists.newArrayList();\n\n        esBucket.getAggrMap().get(HIST).getBucketList().forEach(esSubBucket -> {\n            MetricsContentCell metricsContentCell = new MetricsContentCell();\n\n            // get timeStamp\n            if (null != esSubBucket.getUnusedMap().get(KEY)) {\n                metricsContentCell.setTimeStamp(Long.parseLong(esSubBucket.getUnusedMap().get(KEY).toString()));\n            }\n\n            //get value\n            ESAggr esAggr = esSubBucket.getAggrMap().get(key);\n            if (null != esAggr && null != esAggr.getUnusedMap().get(VALUE)) {\n                metricsContentCell.setValue(Double.parseDouble(esAggr.getUnusedMap().get(VALUE).toString()));\n            }\n            //get indexCount\n            if (INDEX_COUNT.equals(key)&&null != esAggr && null != esAggr.getUnusedMap().get(VALUE)) {\n                BigDecimal indexCount = (BigDecimal) esAggr.getUnusedMap().get(VALUE);\n                metricsContent.setIndexCount(indexCount.longValue());\n            }\n\n            metricsContentCells.add(metricsContentCell);\n        });\n\n        metricsContent.setMetricsContentCells(metricsContentCells);\n    }\n\n    private List<MetricsContentCell> buildMetricsNoNegativeContentCells(String key, ESBucket esBucket) {\n        List<MetricsContentCell> metricsContentCells = Lists.newArrayList();\n\n        esBucket.getAggrMap().get(HIST).getBucketList().forEach(esSubBucket -> {\n            MetricsContentCell metricsContentCell = new MetricsContentCell();\n\n            // get timeStamp\n            final Object time = JSONPath.eval(esSubBucket.toJson(), String.format(\"$.%s\", KEY));\n            if (Objects.nonNull(time)) {\n                metricsContentCell.setTimeStamp(Long.parseLong(String.valueOf(time)));\n            }\n\n            //get value\n            final Object value = JSONPath.eval(esSubBucket.toJson(), String.format(\"$.%s.%s.%s\", key, key, VALUE));\n            /**\n             * 由于采用了<em></>agg</em>中<em>filter</em>聚合模式，会导致到聚合字段的结果在获取不到的状态下是null状态，\n             * 这里采用jsonpath{@link  JSONPath#eval(Object, String)}解析出来结果值，为了保证我们处理到的value不为空，所以将集合添加这一块一并加入判断\n             * ，如果后续需要加入value值为空的，那么放开即可，但是同时需要对\n             * {@link BaseAriusStatsESDAO#mergeTopNu(VariousLineChartMetrics, Integer)}中的<em>sorted</em>\n             * 进行修改\n             *   {\n             *           \"key\" : \"iNGVb_yJUrm\",\n             *           \"doc_count\" : 1,\n             *           \"hist\" : {\n             *             \"buckets\" : [\n             *               {\n             *                 \"key_as_string\" : \"1648810200000\",\n             *                 \"key\" : 1648810200000,\n             *                 \"doc_count\" : 1,\n             *                 \"gatewayFailedPer\" : {\n             *                   \"doc_count\" : 0,\n             *                   \"gatewayFailedPer\" : {\n             *                     \"value\" : null\n             *                   }\n             *                 }\n             *               }\n             *             ]\n             *           }\n             *         }，\n             *          {\n             *           \"key\" : \"logi-elasticsearch-7.6.0\",\n             *           \"doc_count\" : 1,\n             *           \"hist\" : {\n             *             \"buckets\" : [\n             *               {\n             *                 \"key_as_string\" : \"1648810200000\",\n             *                 \"key\" : 1648810200000,\n             *                 \"doc_count\" : 1,\n             *                 \"gatewayFailedPer\" : {\n             *                   \"doc_count\" : 1,\n             *                   \"gatewayFailedPer\" : {\n             *                     \"value\" : 0.0\n             *                   }\n             *                 }\n             *               }\n             *             ]\n             *           }\n             *         }\n             *\n             */\n\n            if (Objects.nonNull(value)) {\n                metricsContentCell.setValue(Double.parseDouble(String.valueOf(value)));\n                metricsContentCells.add(metricsContentCell);\n\n            }\n\n        });\n\n        return metricsContentCells;\n    }\n\n    /**\n     * 构建分位值\n     * @param percentiles2ValueMap\n     * @param esAggMap\n     */\n    private void setPercentiles(Map<String, Double> percentiles2ValueMap, Map<String, ESAggr> esAggMap) {\n        if (null != esAggMap.get(PERCENTILES) && null != esAggMap.get(PERCENTILES).getUnusedMap()\n            && null != esAggMap.get(PERCENTILES).getUnusedMap().get(VALUES)) {\n            JSONObject values = (JSONObject) esAggMap.get(PERCENTILES).getUnusedMap().get(VALUES);\n            for (String percentilesType : PercentilesEnum.listAllType()) {\n                if (null != values && null != values.getDouble(percentilesType)) {\n                    percentiles2ValueMap.put(percentilesType, values.getDouble(percentilesType));\n                }\n            }\n        }\n    }\n\n    /**\n     * 构建task detail info\n     * @param esQueryResponse\n     * @return\n     */\n    protected List<ESClusterTaskDetail> buildTaskDetailInfo(ESQueryResponse esQueryResponse) {\n        return esQueryResponse.getHits().getHits().stream().map(hit -> {\n            ((JSONObject) hit.getSource()).getJSONObject(\"metrics\");\n            return ConvertUtil.obj2ObjByJSON(((JSONObject) hit.getSource()).getJSONObject(\"metrics\"),\n                ESClusterTaskDetail.class);\n        }).collect(Collectors.toList());\n    }\n\n    /**\n     * 获取有数据的第一个时间点\n     * @param clusterPhyName\n     * @param startTime\n     * @param endTime\n     * @param dslFormat\n     * @return\n     */\n    protected Long getHasDataTime(String clusterPhyName, long startTime, long endTime, String dslFormat) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(dslFormat, clusterPhyName, startTime, endTime);\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n\n        return gatewayClient.performRequestWithRouting(metadataClusterName, null, realIndexName, TYPE, dsl,\n            response -> Optional.ofNullable(response).map(ESQueryResponse::getHits).map(ESHits::getHits)\n                .filter(CollectionUtils::isNotEmpty)\n                .map(esHits -> ((Map<String, Long>) esHits.get(0).getSource()).get(\"timestamp\")).orElse(null),\n            3);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dao/template/TemplateAccessESDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.access.TemplateAccessHistory;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.query.TemplateAccessCountPO;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls.DslsConstant;\nimport com.google.common.collect.Lists;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Date;\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.util.AriusDateUtils.getBeforeDays;\nimport static com.didichuxing.datachannel.arius.admin.common.util.DateTimeUtil.getDateStr;\n\n@Component\n@NoArgsConstructor\npublic class TemplateAccessESDAO extends BaseESDAO {\n\n    /**\n     * 索引名称\n     */\n    private String indexName;\n    /**\n     * type名称\n     */\n    private String typeName = \"type\";\n\n    @PostConstruct\n    public void init() {\n        this.indexName = dataCentreUtil.getAriusTemplateAccess();\n    }\n\n    /**\n     * 批量保存结果\n     *\n     * @return\n     */\n    public boolean batchInsert(List<TemplateAccessCountPO> list) {\n        return updateClient.batchInsert(EnvUtil.getWriteIndexNameByEnv(this.indexName), typeName, list);\n    }\n\n    /**\n     * 根据时间范围获取索引模板查询统计次数\n     *\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public List<TemplateAccessCountPO> getAllTemplateAccessByDateRange(String startDate, String endDate) {\n        int scrollSize = 1000;\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.SCROLL_GET_TEMPLATE_ACCESS_BY_RANGE, scrollSize,\n            startDate, endDate);\n\n        return getTemplateAccessByDsl(dsl, scrollSize);\n    }\n\n    public List<TemplateAccessCountPO> getAllTemplateAccessByDateRange(String cluster, String startDate,\n                                                                       String endDate) {\n        int scrollSize = 1000;\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.SCROLL_GET_TEMPLATE_ACCESS_BY_RANGE_AND_CLUSTER,\n            scrollSize, cluster, startDate, endDate);\n\n        return getTemplateAccessByDsl(dsl, scrollSize);\n    }\n\n    /**\n     * 获取昨天总的访问次数\n     * @return\n     */\n    public Long getYesterDayAllTemplateAccess(String cluster) {\n        String startDate = getDateStr(getBeforeDays(new Date(), 1));\n        String endDate = getDateStr(new Date());\n\n        List<TemplateAccessCountPO> list = StringUtils.isBlank(cluster)\n            ? getAllTemplateAccessByDateRange(startDate, endDate)\n            : getAllTemplateAccessByDateRange(cluster, startDate, endDate);\n\n        Long count = 0L;\n        for (TemplateAccessCountPO po : list) {\n            count += po.getCount();\n        }\n\n        return count;\n    }\n\n    /**\n     * 根据时间范围获取指定索引模板查询统计次数\n     *\n     * @param templateName\n     * @param startDate\n     * @param endDate\n     * @return\n     */\n    public List<TemplateAccessCountPO> getAllTemplateAccessByTemplateDateRange(String templateName, String startDate,\n                                                                               String endDate) {\n        int scrollSize = 1000;\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.SCROLL_GET_TEMPLATE_BY_TEMPLATE_RANGE,\n            scrollSize, templateName, startDate, endDate);\n\n        return getTemplateAccessByDsl(dsl, scrollSize);\n    }\n\n    /**\n     * 根据索引模板名称获取历史查询次数统计\n     *\n     * @param templateAccessHistory\n     * @return\n     */\n    public List<TemplateAccessCountPO> getAllTemplateAccessHistoryByTemplate(TemplateAccessHistory templateAccessHistory) {\n        int scrollSize = 1000;\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.SCROLL_GET_TEMPLATE_HISTORY_BY_TEMPLATE,\n            scrollSize, templateAccessHistory.getClusterName(), templateAccessHistory.getTemplateName());\n\n        return getTemplateAccessByDsl(dsl, scrollSize);\n    }\n\n    /**\n     * 根据索引模板ID获取历史查询次数统计\n     *\n     * @param templateId\n     * @return\n     */\n    public List<TemplateAccessCountPO> getAllTemplateAccessHistoryByTemplateId(Integer templateId) {\n        int scrollSize = 1000;\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.SCROLL_GET_TEMPLATE_HISTORY_BY_ID, scrollSize,\n            templateId);\n\n        return getTemplateAccessByDsl(dsl, scrollSize);\n    }\n\n    /**\n     * 根据索引模板Id获取近7天访问记录\n     *\n     * @param templateId\n     * @return\n     */\n    public List<TemplateAccessCountPO> getTemplateAccessLast7DayByTemplateId(Integer templateId) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_LAST_7_DAY_ACCESS_BY_TEMPLATE_ID,\n            templateId);\n\n        return gatewayClient.performRequest(indexName, typeName, dsl, TemplateAccessCountPO.class);\n    }\n\n    /**\n     * 根据索引模板Id获取近7天访问记录\n     *\n     * @param logicTemplateId\n     * @return\n     */\n    public List<TemplateAccessCountPO> getTemplateAccessLastNDayByLogicTemplateId(Integer logicTemplateId,\n                                                                                  Integer days) {\n        String dsl = dslLoaderUtil.getFormatDslByFileName(DslsConstant.GET_LAST_N_DAY_ACCESS_BY_LOGIC_TEMPLATE_ID, days,\n            logicTemplateId);\n\n        return gatewayClient.performRequest(indexName, typeName, dsl, TemplateAccessCountPO.class);\n    }\n\n    /**\n     * 获取昨日模板访问总量\n     * @param template\n     * @return\n     */\n    public Long getYesterDayTemplateAccessCount(String template) {\n        String startDate = getDateStr(getBeforeDays(new Date(), 1));\n        String endDate = getDateStr(new Date());\n\n        List<TemplateAccessCountPO> list = getAllTemplateAccessByTemplateDateRange(template, startDate, endDate);\n        Long count = 0L;\n        for (TemplateAccessCountPO po : list) {\n            count += po.getCount();\n        }\n\n        return count;\n    }\n\n    /**\n     * 根据查询语句获取索引模板访问次数统计\n     *\n     * @param dsl\n     * @param scrollSize\n     * @return\n     */\n    private List<TemplateAccessCountPO> getTemplateAccessByDsl(String dsl, int scrollSize) {\n        List<TemplateAccessCountPO> list = Lists.newLinkedList();\n\n        gatewayClient.queryWithScroll(indexName, typeName, dsl, scrollSize, null, TemplateAccessCountPO.class,\n            resultList -> {\n                if (resultList != null) {\n                    list.addAll(resultList);\n                }\n            });\n\n        return list;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/datacentre/DataCentreUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.datacentre;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\n\n@Component\n@NoArgsConstructor\npublic class DataCentreUtil {\n    private static final ILog LOGGER = LogFactory.getLog(DataCentreUtil.class);\n\n   \n\n    @Value(\"${es.dsl.analyze.index.name:arius.dsl.analyze.result}\")\n    private String ariusDslAnalyzeResult;\n    @Value(\"${es.dsl.metrics.index.name:arius.dsl.metrics}\")\n    private String ariusDslMetrices;\n    @Value(\"${arius.gateway.join.name:arius.gateway.join}\")\n    private String ariusGatewayJoin;\n\n    @Value(\"${es.dsl.template.index.name:arius.dsl.template}\")\n    private String ariusDslTemplate;\n    \n    \n\n   \n \n\n    // projectId维度访问次数索引\n    @Value(\"${es.projectId.template.access.index.name:arius.appid.template.access}\")\n    private String ariusProjectIdTemplateAccess;\n    // 索引模板维度访问次数索引\n    @Value(\"${es.template.access.index.name:arius.template.access}\")\n    private String  ariusTemplateAccess;\n\n\n    \n    @Value(\"${es.node.info.index.name:arius_stats_node_info}\")\n    private String ariusStatsNodeInfo;\n    @Value(\"${es.dashboard.info.name:arius_stats_dashboard_info}\")\n    private String ariusStatsDashboardInfo;\n    @Value(\"${es.index.info.index.name:arius_stats_index_info}\")\n    private String ariusStatsIndexInfo;\n    @Value(\"${es.cat.index.info:arius_cat_index_info}\")\n    private String ariusCatIndexInfo;\n    @Value(\"${es.cat.shard.info:arius_cat_shard_info}\")\n    private String ariusCatShardInfo;\n    @Value(\"${es.cluster.info.index.name:arius_stats_cluster_info}\")\n    private String ariusStatsClusterInfo;\n  \n   \n   \n\n\n  \n    \n \n\n    // gateway 访问统计索引\n    @Value(\"${es.gateway.info.index.name:arius.gateway.join}\")\n    private String ariusStatsGatewayInfo;\n\n    @Value(\"${es.cluster.task.info.index.name:arius_stats_cluster_task_info}\")\n    private String ariusStatsClusterTaskInfo;\n\n    @PostConstruct\n    public void init() {\n        LOGGER.info(\"class=DataCentreUtil||method=init||DataCentreUtil init start.\");\n\n        LOGGER.info(\"class=DataCentreUtil||method=init||env info={}\",                           EnvUtil.getStr());\n        LOGGER.info(\"class=DataCentreUtil||method=init||ariusDslAnalyzeResult={}\",              getAriusDslAnalyzeResult());\n        LOGGER.info(\"class=DataCentreUtil||method=init||ariusDslMetrices={}\",                   getAriusDslMetrices());\n        LOGGER.info(\"class=DataCentreUtil||method=init||ariusGatewayJoin={}\",                   getAriusGatewayJoin());\n        LOGGER.info(\"class=DataCentreUtil||method=init||ariusDslTemplate={}\",                   getAriusDslTemplate());\n        LOGGER.info(\"class=DataCentreUtil||method=init||ariusProjectIdTemplateAccess={}\",           getAriusProjectIdTemplateAccess());\n       \n        LOGGER.info(\"class=DataCentreUtil||method=init||ariusTemplateAccess={}\",                getAriusTemplateAccess());\n        LOGGER.info(\"class=DataCentreUtil||method=init||ariusStatsClusterInfo={}\",              getAriusStatsClusterInfo());\n        LOGGER.info(\"class=DataCentreUtil||method=init||ariusStatsIndexInfo={}\",                getAriusStatsIndexInfo());\n        LOGGER.info(\"class=DataCentreUtil||method=init||ariusStatsGatewayInfo={}\",              getAriusStatsGatewayInfo());\n        LOGGER.info(\"class=DataCentreUtil||method=init||ariusStatsDashBoardInfo={}\",            getAriusStatsDashBoardInfo());\n        LOGGER.info(\"class=DataCentreUtil||method=init||DataCentreUtil init finished.\");\n\n    }\n    \n   \n\n    public String getAriusStatsIndexInfo(){\n        return getIndexName(ariusStatsIndexInfo);\n    }\n\n   \n\n    public String getAriusStatsClusterInfo(){\n        return getIndexName(ariusStatsClusterInfo);\n    }\n\n    public String getAriusStatsNodeInfo(){\n        return getIndexName(ariusStatsNodeInfo);\n    }\n\n \n\n  \n    public String getAriusTemplateAccess(){\n        return getIndexName(ariusTemplateAccess);\n    }\n\n  \n\n    public String getAriusProjectIdTemplateAccess(){\n        return getIndexName(ariusProjectIdTemplateAccess);\n    }\n\n    public String getAriusGatewayJoin() { return getIndexName(ariusGatewayJoin); }\n\n\n    public String getAriusDslAnalyzeResult(){\n        return getIndexName(ariusDslAnalyzeResult);\n    }\n\n    public String getAriusDslMetrices(){\n        return getIndexName(ariusDslMetrices);\n    }\n\n    public String getAriusDslTemplate(){\n        return getIndexName(ariusDslTemplate);\n    }\n\n    \n\n   \n\n    \n\n \n   \n\n    public String getAriusStatsGatewayInfo(){ return ariusStatsGatewayInfo;}\n\n    public String getAriusCatIndexInfo(){return getIndexName(ariusCatIndexInfo);}\n\n    public String getAriusCatShardInfo(){return getIndexName(ariusCatShardInfo);}\n\n    public String getAriusStatsClusterTaskInfo(){return getIndexName(ariusStatsClusterTaskInfo);}\n\n    public String getAriusStatsDashBoardInfo(){ return ariusStatsDashboardInfo;}\n\n\n\n    /*************************************** private method ***************************************/\n    private String getIndexName(String originIndexName) {\n        return originIndexName;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dsls/DslLoaderUtil.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.parser.DefaultJSONParser;\nimport com.alibaba.fastjson.parser.Feature;\nimport com.alibaba.fastjson.parser.ParserConfig;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.lang.reflect.Field;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/28 上午10:08\n * @modified By D10865\n *\n * 加载dsl查询语句工具类\n *\n */\n@Component\npublic class DslLoaderUtil {\n    private static final ILog                                     LOGGER  = LogFactory.getLog(DslLoaderUtil.class);\n    /**\n     * 查询语句容器\n     */\n    private Map<String/*fileRelativePath*/, String/*dslContent*/> dslsMap = Maps.newHashMap();\n\n    @PostConstruct\n    public void init() {\n        LOGGER.info(\"class=DslLoaderUtil||method=init||DslLoaderUtil init start.\");\n        List<String> dslFileNames = Lists.newLinkedList();\n\n        // 反射获取接口中定义的变量中的值\n        Field[] fields = DslsConstant.class.getDeclaredFields();\n        for (int i = 0; i < fields.length; ++i) {\n            fields[i].setAccessible(true);\n            try {\n                dslFileNames.add(fields[i].get(null).toString());\n            } catch (IllegalAccessException e) {\n                LOGGER.error(\"class=DslLoaderUtil||method=init||errMsg=fail to read {} error. \", fields[i].getName(),\n                    e);\n            }\n        }\n\n        // 加载dsl文件及内容\n        for (String fileName : dslFileNames) {\n            dslsMap.put(fileName, readDslFileInJarFile(fileName));\n        }\n\n        // 输出加载的查询语句\n        LOGGER.info(\"class=DslLoaderUtil||method=init||msg=dsl files count {}\", dslsMap.size());\n        for (Map.Entry<String/*fileRelativePath*/, String/*dslContent*/> entry : dslsMap.entrySet()) {\n            LOGGER.info(\"class=DslLoaderUtil||method=init||msg=file name {}, dsl content {}\", entry.getKey(),\n                entry.getValue());\n        }\n\n        LOGGER.info(\"class=DslLoaderUtil||method=init||DslLoaderUtil init finished.\");\n    }\n\n    /**\n     * 获取查询语句\n     *\n     * @param fileName\n     * @return\n     */\n    public String getDslByFileName(String fileName) {\n        return dslsMap.get(fileName);\n    }\n\n    /**\n     * 获取格式化的查询语句\n     *\n     * @param fileName\n     * @param args\n     * @return\n     */\n    public String getFormatDslByFileName(String fileName, Object... args) {\n        String loadDslContent = getDslByFileName(fileName);\n\n        if (StringUtils.isBlank(loadDslContent)) {\n            LOGGER.error(\"class=DslLoaderUtil||method=getFormatDslByFileName||errMsg=dsl file {} content is empty\",\n                fileName);\n            return \"\";\n        }\n\n        // 格式化查询语句\n        String dsl = trimJsonBank(String.format(loadDslContent, args));\n        // 如果不是线上环境，则输出dsl语句\n        LOGGER.debug(\"class=DslLoaderUtil||method=getFormatDslByFileName||dsl={}\", dsl);\n\n\n        return dsl;\n    }\n\n    /**************************************** private method ****************************************************/\n    /**\n     * 去除json中的空格\n     *\n     * @param sourceDsl\n     * @return\n     */\n    private String trimJsonBank(String sourceDsl) {\n        List<String> dslList = Lists.newArrayList();\n\n        DefaultJSONParser parser = null;\n        Object obj = null;\n        String dsl = sourceDsl;\n\n        // 解析多个json，直到pos为0\n        for (;;) {\n            try {\n                // 这里需要Feature.OrderedField.getMask()保持有序\n                parser = new DefaultJSONParser(dsl, ParserConfig.getGlobalInstance(),\n                    JSON.DEFAULT_PARSER_FEATURE | Feature.OrderedField.getMask());\n                obj = parser.parse();\n            } catch (Exception t) {\n                LOGGER.error(\"class=DslLoaderUtil||method=trimJsonBank||errMsg=parse json {} error. \", dsl, t);\n            }\n            if (obj == null) {\n                break;\n            }\n\n            if (obj instanceof JSONObject) {\n                dslList.add(JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue));\n                int pos = parser.getLexer().pos();\n                if (pos <= 0) {\n                    break;\n                }\n                dsl = dsl.substring(pos);\n                parser.getLexer().close();\n            } else {\n                parser.getLexer().close();\n                break;\n            }\n        }\n\n        // 格式化异常或者有多个查询语句，返回原来的查询语句\n        if (dslList.isEmpty() || dslList.size() > 1) {\n            return sourceDsl;\n        }\n\n        return dslList.get(0);\n    }\n\n    /**\n     * 从jar包中读取dsl语句文件\n     *\n     * @param fileName\n     * @return\n     */\n    private String readDslFileInJarFile(String fileName) {\n        InputStream inputStream = this.getClass().getClassLoader()\n            .getResourceAsStream(String.format(\"dsl/%s\", fileName));\n        if (inputStream != null) {\n            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));\n            String line = null;\n            List<String> lines = Lists.newLinkedList();\n            try {\n                while ((line = bufferedReader.readLine()) != null) {\n                    lines.add(line);\n                }\n                return StringUtils.join(lines, \"\");\n\n            } catch (IOException e) {\n                LOGGER.error(\"class=DslLoaderUtil||method=readDslFileInJarFile||errMsg=read file {} error. \", fileName,\n                    e);\n\n                return \"\";\n            } finally {\n                try {\n                    inputStream.close();\n                } catch (IOException e) {\n                    LOGGER.error(\n                        \"class=DslLoaderUtil||method=readDslFileInJarFile||errMsg=fail to close file {} error. \",\n                        fileName, e);\n                }\n            }\n        } else {\n            LOGGER.error(\"class=DslLoaderUtil||method=readDslFileInJarFile||errMsg=fail to read file {} content\",\n                fileName);\n            return \"\";\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/index/dsls/DslsConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.index.dsls;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/28 上午10:23\n * @modified By D10865\n *\n * 查询语句文件名常量\n *\n * 命名规则 类名/方法名\n *\n * 在dslFiles目录下新建以类名为名称的文件夹，以方法名为名称的文件名\n *\n */\npublic class DslsConstant {\n\n    private DslsConstant() {\n    }\n\n\n\n    /**\n     * 获得所有aggs请求的indices字段值\n     */\n    public static final String GET_INDICES_FOR_AGGS                                          = \"IndexHit/getIndicesForAggs\";\n    /**\n     * 获得普通请求的的index字段值\n     */\n    public static final String GET_INDEX_FOR_NORMALS                                         = \"IndexHit/getIndexForNormal\";\n\n    /************************************************************** IndexTemplateLabelESDao **************************************************************/\n    /**\n     * 根据索引模板ID获取标签\n     */\n    public static final String V2_SCROLL_LABEL_BY_TEMPLATE_ID                                = \"IndexTemplateLabelESDao/getLabelByLogicTemplateId\";\n    /**\n     * 根据标签ID获取标签\n     */\n    public static final String V2_SCROLL_LABEL_BY_LABEL_ID                                   = \"IndexTemplateLabelESDao/getLabelByLabelId\";\n\n\n    /************************************************************** AriusStatsClusterInfoEsDao **************************************************************/\n\n    /**\n     * 查询一段时间内物理集群分位使用信息\n     */\n    public static final String GET_CLUSTER_PHY_AGG_PERCENTILES_METRICS_BY_AGG_PARAM          = \"AriusStatsClusterPhyInfoEsDao/getAggPercentilesMetricsByRange\";\n\n    /**\n     * 查询一段时间内物理集群其他使用信息\n     */\n    public static final String GET_CLUSTER_METRICS_BY_RANGE_AND_INTERVAL                     = \"AriusStatsClusterPhyInfoEsDao/getClusterMetricsByRangeAndInterval\";\n\n    /**\n     * 获取网关数量\n     */\n    public static final String GET_GATEWAY_COUNT                                             = \"AriusStatsClusterPhyInfoEsDao/getGatewayCount\";\n\n\n    /************************************************************** AriusStatsIndexInfoEsDao **************************************************************/\n    /**\n     * 查询索引模板一段时间访问内的最大容量\n     */\n    public static final String GET_TEMPLATE_TOTAL_SIZE_BY_TIME_RANGE                         = \"AriusStatsIndexInfoEsDao/getTemplateTotalSizeByTimeRange\";\n    /**\n     * 查询索引模板一段时间tps的最大容量\n     */\n    public static final String GET_TEMPLATE_TOTAL_MAX_TPS_BY_TIME_RANGE                      = \"AriusStatsIndexInfoEsDao/getTemplateTotalMaxTpsByTimeRange\";\n    /**\n     * 查询索引模板一段时间tps的最大容量\n     */\n    public static final String GET_TEMPLATE_TOTAL_MAX_TPS_BY_TIME_RANGE_NO_PERCENT           = \"AriusStatsIndexInfoEsDao/getTemplateTotalMaxTpsByTimeRangeNoPercent\";\n    /**\n     * 根据物理索引模板获取模板总的大小\n     */\n    public static final String GET_TEMPLATE_TOTAL_SIZE_BY_TEMPLATE_ID                        = \"AriusStatsIndexInfoEsDao/getTemplateTotalSizeByTemplateId\";\n    /**\n     * 根据逻辑索引模板获取模板总的大小\n     */\n    public static final String GET_LOGIC_TEMPLATE_TOTAL_SIZE_BY_TEMPLATE_ID                  = \"AriusStatsIndexInfoEsDao/getTemplateTotalSizeByLogicTemplateId\";\n    /**\n     * 根据索引模板一段时间获取模板总的文档大小\n     */\n    public static final String GET_TEMPLATE_TOTAL_DOC_BY_TIME_RANGE                          = \"AriusStatsIndexInfoEsDao/getTemplateTotalDocNuByTimeRange\";\n    /**\n     * 根据索引模板ID一段时间获取模板总的文档大小\n     */\n    public static final String GET_TEMPLATE_TOTAL_DOC_BY_LOGIC_TEMPLATE_ID_AND_TIME_RANGE    = \"AriusStatsIndexInfoEsDao/getTemplateTotalDocNuByLogicTemplateIdAndTimeRange\";\n    /**\n     * 获取索引模板最大索引的容量\n     */\n    public static final String GET_TEMPLATE_MAX_INDEX_SIZE                                   = \"AriusStatsIndexInfoEsDao/getTemplateMaxIndexSize\";\n    /**\n     * 获取索引模板最大索引的文档条数\n     */\n    public static final String GET_TEMPLATE_MAX_INDEX_DOC                                    = \"AriusStatsIndexInfoEsDao/getTemplateMaxIndexDoc\";\n    /**\n     * 根据索引模板和集群获取相关统计信息\n     */\n    public static final String GET_TEMPLATE_REAL_STATIS_INFO_BY_TEMPLATE_AND_CLUSTER         = \"AriusStatsIndexInfoEsDao/getIndexRealTimeStatisInfoByTemplateAndCluster\";\n    /**\n     * 根据索引模板和集群获取相关统计信息\n     */\n    public static final String GET_TEMPLATE_REAL_INFO_BY_TEMPLATE_AND_CLUSTER                = \"AriusStatsIndexInfoEsDao/getIndexRealTimeInfoByTemplateAndCluster\";\n    /**\n     * 查询一段时间内的索引的最大值值信息\n     */\n    public static final String GET_MAXINFO_BY_TIME_RANGE_AND_TEMPLATE                        = \"AriusStatsIndexInfoEsDao/getMaxInfoByRangeTimeAndTemplate\";\n    /**\n     * 根据模板Id查询一段时间内的索引节点统计信息\n     */\n    public static final String GET_INDEX_STATS_BY_TIME_RANGE_AND_TEMPLATEID                  = \"AriusStatsIndexInfoEsDao/getIndexStatsByTempalteId\";\n    /**\n     * 获取集群实时总的tps/qps信息\n     */\n    public static final String GET_CLUSTER_REAL_TIME_TPS_QPS_INFO                            = \"AriusStatsIndexInfoEsDao/getClusterTpsQpsInfo\";\n    /**\n     * 获取逻辑集群实时总的tps/qps信息\n     */\n    public static final String GET_CLUSTER_LOGIC_REAL_TIME_TPS_QPS_INFO                      = \"AriusStatsIndexInfoEsDao/getClusterLogicTpsQpsInfo\";\n\n    /**\n     * 获取某个索引模板最近一段时间tps总和\n     */\n    public static final String GET_AVG_TPS_BY_LOGIC_ID_AND_TIME_RANGE                        = \"AriusStatsIndexInfoEsDao/getAvgTpsByLogicIdAndTimeRange\";\n    /**\n     * 获取某个逻辑模板历史一段时间tps每小时最大值\n     */\n    public static final String GET_HISTORY_MAX_TPS_BY_LOGIC_ID_AND_TIME_RANGE                = \"AriusStatsIndexInfoEsDao/getHistoryMaxTpsByLogicIdAndTimeRange\";\n    /**\n     * 查询一段时间内的索引查询率\n     */\n    public static final String GET_QUERY_RATE_BY_INDEX_DATE_RANGE                            = \"AriusStatsIndexInfoEsDao/getQueryRateByIndexDateRange\";\n\n    /**\n     * 查询单个索引聚合信息\n     */\n    public static final String GET_AGG_SINGLE_INDEX_METRICS                                  = \"AriusStatsIndexInfoEsDao/getAggSingleIndexMetrics\";\n\n    /**\n     * 查询topN索引聚合信息\n     */\n    public static final String GET_TOPN_INDEX_AGG_METRICS                                    = \"AriusStatsIndexInfoEsDao/getTopNIndicesAggMetrics\";\n\n    /**\n     * 获取指定集群有索引信息的时间戳\n     */\n    public static final String GET_HAS_INDEX_METRICS_DATA_TIME                               = \"AriusStatsIndexInfoEsDao/getHasIndexMetricsDataTime\";\n\n    /**\n     * 查询第一个时间分片中指标数值的索引指标信息\n     */\n    public static final String GET_MULTIPLE_INDEX_FIRST_INTERVAL_AGG_METRICS                 = \"AriusStatsIndexInfoEsDao/getAggMultipleIndicesMetrics\";\n\n    /**\n     * 查询第一个时间分片中指标数值的索引指标信息\n     */\n    public static final String GET_MULTIPLE_INDEX_FIRST_INTERVAL_AGG_METRICS_WITH_STEP       = \"AriusStatsIndexInfoEsDao/getAggMultipleIndicesMetricsWithStep\";\n    public static final String GET_AGG_MULTIPLE_INDICES_METRICS_WITH_STEP_AND_INDEX_LIST       = \"AriusStatsIndexInfoEsDao/getAggMultipleIndicesMetricsWithStepAndIndexList\";\n\n\n    /**\n     * 查询第一个时间分片中指标数值的逻辑模板指标信息\n     */\n    public static final String GET_MULTIPLE_TEMPLATE_FIRST_INTERVAL_AGG_METRICS_WITH_STEP    = \"AriusStatsIndexInfoEsDao/getAggMultipleTemplateMetricsWithStep\";\n\n    /**\n     * 查询topN模板聚合信息\n     */\n    public static final String GET_TOPN_TEMPLATE_AGG_METRICS                                 = \"AriusStatsIndexInfoEsDao/getTopNTemplateAggMetrics\";\n\n    /**\n     * 查询单个模板聚合信息\n     */\n    public static final String GET_AGG_SINGLE_TEMPLATE_METRICS                               = \"AriusStatsIndexInfoEsDao/getAggSingleTemplateMetrics\";\n    public static final String GET_AGG_MULTIPLE_TEMPLATE_METRICS_WITH_STEP_AND_LOGIC_IDS                               = \"AriusStatsIndexInfoEsDao/getAggMultipleTemplateMetricsWithStepAndLogicIds\";\n\n    /**\n     * 获取单个指标项\n     */\n    public static final String GET_SINGLE_METRICS                                            = \"AriusStatsIndexInfoEsDao/getSingleMetrics\";\n\n    /************************************************************** AriusStatsIndexNodeInfoEsDao **************************************************************/\n    /**\n     * 查询一段时间内的索引节点统计信息\n     */\n    public static final String GET_INDEX_NODE_STATS_BY_TIME_RANGE                            = \"AriusStatsIndexNodeInfoEsDao/getIndexToNodeStats\";\n    /**\n     * 查询一段时间内的索引节点统计信息\n     */\n    public static final String GET_INDEX_NODE_STATS_BY_TIME_RANGE_AND_TEMPALTEID             = \"AriusStatsIndexNodeInfoEsDao/getIndexToNodeStatsByTemplateId\";\n\n    /************************************************************** AriusStatsIngestInfoEsDao **************************************************************/\n    /**\n     * 获取某个索引模板最近一段时间限流导致的失败数量\n     */\n    public static final String GET_INGEST_FAILED_COUNT_BY_LOGIC_ID_AND_TIME_RANGE            = \"AriusStatsIngestInfoEsDao/getIngestFailCountByLogicIdAndTimeRange\";\n\n    /************************************************************** AriusStatsNodeInfoEsDao   **************************************************************/\n\n    /**\n     * 获取所有集群节点的物理存储空间大小\n     */\n    public static final String GET_ALL_CLUSTER_NODE_PHY_STORE_SIZE                           = \"AriusStatsNodeInfoEsDao/getAllClusterNodePhyStoreSize\";\n    /**\n     * 获取集群实时总的发送流量和接收流量信息\n     */\n    public static final String GET_CLUSTER_REAL_TIME_RX_TX_INFO                              = \"AriusStatsNodeInfoEsDao/getClusterRxTxInfo\";\n    /**\n     * 获取逻辑集群实时总的发送流量和接收流量信息\n     */\n    public static final String GET_CLUSTER_LOGIC_REAL_TIME_RX_TX_INFO                        = \"AriusStatsNodeInfoEsDao/getClusterLogicRxTxInfo\";\n    /**\n     * 获取集群实时cpu平均使用率\n     */\n    public static final String GET_CLUSTER_REAL_TIME_CPU_AVG_INFO                            = \"AriusStatsNodeInfoEsDao/getClusterCpuAvgInfo\";\n\n    /**\n     * 获取集群实时分位值和平均使用率\n     */\n    public static final String AGG_CLUSTER_REAL_TIME_AVG_AND_PERCENT                         = \"AriusStatsNodeInfoEsDao/aggClusterAvgAndPercentiles\";\n\n    /**\n     * 获取集群实时分位值和平均使用率\n     */\n    public static final String AGG_CLUSTER_LOGIC_REAL_TIME_AVG_AND_PERCENT                         = \"AriusStatsNodeInfoEsDao/aggClusterLogicAvgAndPercentiles\";\n\n\n    /**\n     * 获取集群查询/写入总耗时\n     */\n    public static final String AGG_CLUSTER_INDEXING_SEARCH_TIME_SUM                         = \"AriusStatsNodeInfoEsDao/aggClusterIndexingOrSearchTimeSum\";\n\n    /**\n     * 获取集群查询/写入总耗时\n     */\n    public static final String AGG_CLUSTER_LOGIC_INDEXING_SEARCH_TIME_SUM                         = \"AriusStatsNodeInfoEsDao/aggClusterLogicIndexingOrSearchTimeSum\";\n\n\n    /**\n     * 获取集群磁盘空闲率实时分位值和平均使用率\n     */\n    public static final String AGG_CLUSTER_AVG_AND_PERCENT_FOR_DISK_FREE_USAGE_PERCENT       = \"AriusStatsNodeInfoEsDao/aggClusterAvgAndPercentilesForDiskFreeUsagePercent\";\n\n    /**\n     * 获取逻辑集群磁盘空闲率实时分位值和平均使用率\n     */\n    public static final String AGG_CLUSTER_LOGIC_AVG_AND_PERCENT_FOR_DISK_FREE_USAGE_PERCENT       = \"AriusStatsNodeInfoEsDao/aggClusterLogicAvgAndPercentilesForDiskFreeUsagePercent\";\n\n\n    /**\n     * 获取获取集群写入耗时最大值\n     */\n    public static final String GET_CLUSTER_INDEXING_LATENCY_MAX                              = \"AriusStatsNodeInfoEsDao/getClusterIndexingLatency\";\n    /**\n     * 获取获取集群查询耗时最大值\n     */\n    public static final String GET_CLUSTER_SEARCH_LATENCY_MAX                                = \"AriusStatsNodeInfoEsDao/getClusterSearchLatency\";\n\n    /**\n     * 获取topN节点维度统计信息\n     */\n    public static final String GET_TOPN_NODE_AGG_METRICS_INFO                                = \"AriusStatsNodeInfoEsDao/getTopNNodeAggMetricsInfo\";\n\n    /**\n     * 获取集群多个节点维度统计信息\n     */\n    public static final String GET_AGG_CLUSTER_PHY_NODES_INFO                                = \"AriusStatsNodeInfoEsDao/getAggClusterPhyNodesInfo\";\n\n    /**\n     * 获取集群单个节点维度统计信息\n     */\n    public static final String GET_AGG_CLUSTER_PHY_SINGLE_NODE_NODE                          = \"AriusStatsNodeInfoEsDao/getAggClusterPhySingleNodeInfo\";\n\n    /**\n     * 获取指定集群节点有节点信息的时间戳\n     */\n    public static final String GET_HAS_NODE_METRICS_DATA_TIME                                = \"AriusStatsNodeInfoEsDao/getHasNodeMetricInfoTime\";\n    /**\n     * 获取某个区间范围内的某个sum聚合值\n     */\n    public static final String GET_FIELD_SUM_AND_RANGE_FIELD_TOTAL                           = \"AriusStatsNodeInfoEsDao/getFieldSumAndRangeFieldTotal\";\n\n    /**\n     * 获取某个区间范围内节点的某个sum聚合值\n     */\n    public static final String GET_NODE_FIELD_SUM_AND_RANGE_FIELD_TOTAL                      = \"AriusStatsNodeInfoEsDao/getNodeFieldSumAndRangeFieldTotal\";\n\n    /**\n     * 获取时间段内指标的最大值或平均值\n     */\n    public static final String GET_AGG_CLUSTER_NODE_INFO_WITH_STEP                           = \"AriusStatsNodeInfoEsDao/getAggClusterNodeInfoWithStep\";\n\n\n\n\n    /************************************************************** TemplateAccessCountEsDao **************************************************************/\n    /**\n     * 根据时间范围获取索引模板查询统计次数\n     */\n    public static final String SCROLL_GET_TEMPLATE_ACCESS_BY_RANGE                           = \"TemplateAccessCountEsDao/getAllTemplateAccessByDateRange\";\n    /**\n     * 根据时间范围和集群获取索引模板查询统计次数\n     */\n    public static final String SCROLL_GET_TEMPLATE_ACCESS_BY_RANGE_AND_CLUSTER               = \"TemplateAccessCountEsDao/getAllTemplateAccessByDateRangeAndCluster\";\n    /**\n     * 根据索引模板名称获取历史查询次数统计\n     */\n    public static final String SCROLL_GET_TEMPLATE_HISTORY_BY_TEMPLATE                       = \"TemplateAccessCountEsDao/getAllTemplateAccessHistoryByTemplate\";\n    /**\n     * 根据索引模板ID获取历史查询次数统计\n     */\n    public static final String SCROLL_GET_TEMPLATE_HISTORY_BY_ID                             = \"TemplateAccessCountEsDao/getAllTemplateAccessHistoryByTemplateId\";\n    /**\n     * 根据时间范围获取指定索引模板查询统计次数\n     */\n    public static final String SCROLL_GET_TEMPLATE_BY_TEMPLATE_RANGE                         = \"TemplateAccessCountEsDao/getAllTemplateAccessByTemplateDateRange\";\n    /**\n     * 根据索引模板Id获取近7天访问记录\n     */\n    public static final String GET_LAST_7_DAY_ACCESS_BY_TEMPLATE_ID                          = \"TemplateAccessCountEsDao/getTemplateAccessLast7DayByTemplateId\";\n    /**\n     * 根据索引模板Id获取近7天访问记录\n     */\n    public static final String GET_LAST_N_DAY_ACCESS_BY_LOGIC_TEMPLATE_ID                    = \"TemplateAccessCountEsDao/getTemplateAccessLastNDayByLogicTemplateId\";\n\n    /************************************************************** GatewayJoinEsDao **************************************************************/\n    /**\n     * 分页获取dsl异常查询列表\n     */\n    public static final String GET_GATEWAY_ERROR_BY_CONDITION                           = \"GatewayJoinEsDao/getGatewayErrorByCondition\";\n    /**\n     * 分页获取dsl慢查询列表\n     */\n    public static final String GET_GATEWAY_SLOW_BY_CONDITION                            = \"GatewayJoinEsDao/getGatewaySlowByCondition\";\n    /**\n     * 根据index获得对应的templateMD5\n     */\n    public static final String GET_DSLS_BY_INDEX_NAME                                        = \"GatewayJoinEsDao/getTemplateMD5ByIndexName\";\n    public static final String GET_ONE_DSL_BY_PROJECT_ID_AND_INDEX_NAME = \"GatewayJoinEsDao/getOneDSLByProjectIdAndIndexName\";\n\n    /**\n     * 根据index获得对应的查询请求\n     */\n    public static final String GET_SEARCH_REQUEST_BY_INDEX_NAME = \"GatewayJoinEsDao/getSearchRequestByIndexName\";\n    /**\n     * 根据projectId获得对应的查询99分位\n     */\n    public static final String GET_QUERY_RT_BY_PROJECT_ID           = \"GatewayJoinEsDao/getQueryRtByProjectId\";\n    /**\n     * 根据projectId获得查询topNum信息\n     */\n    public static final String GET_TOP_NUM_QUERY_INFO_BY_PROJECT_ID = \"GatewayJoinEsDao/getQueryTopNumInfoByProjectId\";\n    /**\n     * 获取某个查询模板一周内查询次数\n     */\n    public static final String GET_WEEK_SEARCH_COUNT_BY_MD5         = \"GatewayJoinEsDao/getWeekSearchCountByMd5\";\n \n    /**\n     * 根据索引名称和MD5获取一条查询明细中使用的字段信息\n     */\n    public static final String GET_GATEWAY_JOIN_BY_INDICES_MD5                               = \"GatewayJoinEsDao/getPoByIndicesAndMd5\";\n    /**\n     * 聚合查询gateway join日志索引，获取到某个索引查询使用的MD5列表\n     */\n    public static final String AGG_INDICES_MD5                                               = \"GatewayJoinEsDao/aggIndicesDslMd5ByRange\";\n    /**\n     * 获取查询被限流的MD5\n     */\n    public static final String GET_QUERY_LIMIT_ERROR_MD5                                     = \"GatewayJoinEsDao/getQueryLimitErrorMd5\";\n    /**\n     * 根据project id和MD5获取最新的一次查询记录\n     */\n    public static final String GET_ONE_GATEWAY_JOIN_BY_KEY                                   = \"GatewayJoinEsDao/getFirstByProjectIdAndTemplateMd5\";\n    /**\n     * 获取匹配的索引\n     */\n    public static final String MATCH_GATEWAY_INDICES                                         = \"GatewayJoinEsDao/matchIndices\";\n    /**\n     * 按时间聚合获取查询模板\n     */\n    public static final String AGG_MD5_BY_TIMESTAMP   = \"GatewayJoinEsDao/getInfoByIds\";\n    /**\n     * 按PROJECT id和查询模板进行聚合\n     */\n    public static final String AGG_PROJECT_ID_MD5     = \"GatewayJoinEsDao/getIds\";\n    /**\n     * 根据索引和MD5获取查询语句\n     */\n    public static final String GET_DSL_BY_MD5_INDICES = \"GatewayJoinEsDao/getDslByIndexAndTemplateMD5\";\n\n    /**\n     * 获取某个PROJECT id某一天的查询gateway 分布情况\n     */\n    public static final String GET_ACCESS_GATEWAY_INFO_BY_PROJECT_ID = \"GatewayJoinEsDao/getAccessGatewayInfoByProjectIdDate\";\n    /**\n     * 根据查询模板获取错误详情\n     */\n    public static final String GET_EXCEPTION_BY_MD5                  = \"GatewayJoinEsDao/queryErrorDslDetailByProjectIdTemplateAndDate\";\n    /**\n     * 根据异常名称获取查询模板MD5\n     */\n    public static final String AGG_MD5_BY_EXCEPTION_NAME                                     = \"GatewayJoinEsDao/queryErrorDslByProjectIdExceptionAndDate\";\n    /**\n     * 获取一小时内查询模板提取失败的次数\n     */\n    public static final String GET_FAILED_DSL_TEMPLATE                                       = \"GatewayJoinEsDao/getFailedDslTemplateCount\";\n    /**\n     * 获取查询模板提取失败的索引信息\n     */\n    public static final String GET_FAILED_DSL_TEMPLATE_INDICES = \"GatewayJoinEsDao/getFailedDslTemplateSearchIndices\";\n    /**\n     * 查询某个PROJECT id 一天查询总量\n     */\n    public static final String GET_SEARCH_COUNT_BY_PROJECT_ID = \"GatewayJoinEsDao/getTotalSearchCountByProjectIdAndDate\";\n    /**\n     * 获取qps信息(最大qps，平均qps，最小qps)\n     */\n    public static final String GET_QPS_INFO_BY_PROJECT_ID     = \"GatewayJoinEsDao/getQpsInfoByProjectIdAndDate\";\n    /**\n     * 获取查询耗时分位图\n     */\n    public static final String GET_COST_INFO_BY_PROJECT_ID = \"GatewayJoinEsDao/getCostInfoByProjectIdAndDate\";\n    /**\n     * 获取慢查语句dslTemplateMd5和次数\n     */\n    public static final String GET_SLOW_DSL_BY_PROJECT_ID  = \"GatewayJoinEsDao/querySlowDslByProjectIdAndDate\";\n    /**\n     * 根据projectId和dsl查询模板MD5获取具体慢查语句\n     */\n    public static final String GET_SLOW_DSL_BY_KEY         = \"GatewayJoinEsDao/querySlowDslCountAndDetailByByProjectIdAndDslTemplate\";\n    /**\n     * 根据projectId和查询模板获取某一天查询最大值\n     */\n    public static final String GET_GATEWAY_JOIN_MAX_QPS_BY_KEY  = \"GatewayJoinEsDao/queryMaxSearchQpsByProjectIdAndDslTemplate\";\n    /**\n     * 获取某个projectId某一天的查询错误数和错误信息\n     */\n    public static final String AGG_EXCEPTION_NAME_BY_PROJECT_ID = \"GatewayJoinEsDao/getErrorSearchCountAndErrorDetailByProjectIdDate\";\n    /**\n     * 获取指定projectId和时间范围下查询方式统计次数\n     */\n    public static final String GET_REQUEST_TYPE_BY_PROJECT_ID            = \"GatewayJoinEsDao/getRequestTypeByProjectId\";\n    /**\n     * GET_ACCESS_INDEX_NAME_BY_PROJECT_ID\n     */\n    public static final String GET_ACCESS_INDEX_NAME_BY_PROJECT_ID            = \"GatewayJoinEsDao/getAccessIndexNameByProjectId\";\n    /**\n     * 获取指定projectId一段时间内的错误查询记录\n     */\n    public static final String GET_GATEWAY_ERROR_LIST_BY_PROJECT_ID_AND_RANGE = \"GatewayJoinEsDao/getGatewayErrorListByProjectId\";\n    /**\n     * 获取指定一段时间内的错误查询记录\n     */\n    public static final String GET_GATEWAY_ERROR_LIST_BY_RANGE                = \"GatewayJoinEsDao/getGatewayErrorList\";\n    /**\n     * 获取指定索引的查询错误个数\n     */\n    public static final String GET_ERROR_CNT_BY_TEMPLATE_NAME                                = \"GatewayJoinEsDao/getErrorCntByTemplateName\";\n    /**\n     * 获取指定索引的查询错误个数\n     */\n    public static final String GET_SLOW_CNT_BY_TEMPLATE_NAME                 = \"GatewayJoinEsDao/getSlowCntByTemplateName\";\n    /**\n     * 获取指定projectId一段时间内的慢查询记录\n     */\n    public static final String GET_GATEWAY_SLOW_LIST_BY_PROJECT_ID_AND_RANGE = \"GatewayJoinEsDao/getGatewaySlowListByProjectId\";\n    /**\n     * 获取指定projectId一段时间内的慢查询记录\n     */\n    public static final String GET_GATEWAY_SLOW_LIST_BY_RANGE       = \"GatewayJoinEsDao/getGatewaySlowList\";\n    /**\n     * 根据索引模板逻辑id，获取查询语句中使用的type名称\n     */\n    public static final String GET_SEARCH_TYPES_BY_LOGIC_ID               = \"GatewayJoinEsDao/getSearchTypesByLogicId\";\n    /**\n     * 根据时间范围和projectId获取查询量\n     */\n    public static final String GET_SEARCH_COUNT_BY_PROJECT_ID_TIME_RANGE   = \"GatewayJoinEsDao/getSearchCountByProjectId\";\n    /**\n     * 获取多type查询映射后的索引信息\n     */\n    public static final String SCROLL_MULITY_TYPE_GATEWAY_JOIN_BY_SHARD_NO = \"GatewayJoinEsDao/scrollMulityTypeByShardNo\";\n    /**\n     * 获取请求日志\n     */\n    public static final String SCROLL_REQUEST_LOG_GATEWAY_JOIN_BY_SHARD_NO = \"GatewayJoinEsDao/scrollRequestLogByShardNo\";\n\n    /************************************************************** GatewayOverviewMetricsDao **************************************************************/\n    /**\n     * 获取总览公共指标。totalHits，totalCost，totalShards，failedShards\n     */\n    public static final String GET_GATEWAY_COMMON_METRICS                                    = \"GatewayOverviewMetricsDao/getCommonMetrics\";\n\n    /**\n     * 获取查询量\n     */\n    public static final String GET_GATEWAY_READ_COUNT                                        = \"GatewayOverviewMetricsDao/getReadCount\";\n    /**\n     * 获取dsl/sql分布。searchType\n     */\n    public static final String GET_GATEWAY_SEARCH_TYPE                                       = \"GatewayOverviewMetricsDao/getSearchType\";\n    /**\n     * 获取写入指标。写入量，写入平均耗时，写入平均响应长度\n     */\n    public static final String GET_GATEWAY_WRITE_METRICS                                     = \"GatewayOverviewMetricsDao/getWriteMetrics\";\n\n    /************************************************************** GatewayIndexMetricsDao **************************************************************/\n    /**\n     * 获取索引模版写入量，写入耗时 topN\n     */\n    public static final String GET_GATEWAY_INDEX_WRITE                                       = \"GatewayIndexMetricsDao/getAggWrite\";\n\n    /**\n     * 获取索引模版写入量，写入耗时 by templateName\n     */\n    public static final String GET_GATEWAY_INDEX_WRITE_BY_TEMPLATE_NAME                      = \"GatewayIndexMetricsDao/getAggWriteByTemplateName\";\n\n    /**\n     * 获取索引模版查询量，查询耗时 topN\n     */\n    public static final String GET_GATEWAY_INDEX_SEARCH                                      = \"GatewayIndexMetricsDao/getAggSearch\";\n\n    /**\n     * 获取索引模版查询量，查询耗时 by templateName\n     */\n    public static final String GET_GATEWAY_INDEX_SEARCH_BY_TEMPLATE_NAME                     = \"GatewayIndexMetricsDao/getAggSearchByTemplateName\";\n\n    /************************************************************** GatewayNodeMetricsDao **************************************************************/\n\n    /**\n     * 获取某 gatewayNode 读分布\n     */\n    public static final String GET_GATEWAY_NODE_FIELD_BY_IP                                  = \"GatewayNodeMetricsDao/getAggFieldByIp\";\n\n    /**\n     * 获取 topN gatewayNode 读分布\n     */\n    public static final String GET_GATEWAY_NODE_FIELD                                        = \"GatewayNodeMetricsDao/getAggField\";\n\n    /**\n     * 获取 topN gatewayNode 写分布\n     */\n    public static final String GET_GATEWAY_NODE_WRITE                                        = \"GatewayNodeMetricsDao/getAggWriteAndGatewayNode\";\n\n    /**\n     * 获取某 gatewayNode 写分布\n     */\n    public static final String GET_GATEWAY_NODE_WRITE_BY_IP                                  = \"GatewayNodeMetricsDao/getAggWriteAndGatewayNodeByIp\";\n\n    /**\n     * 获取某 clientNode 读分布\n     */\n    public static final String GET_CLIENT_NODE_FIELD_BY_IP                                   = \"GatewayNodeMetricsDao/getClientNodeAggFieldByIp\";\n\n    /**\n     * 获取 topN clientNode 读分布\n     */\n    public static final String GET_CLIENT_NODE_FIELD                                         = \"GatewayNodeMetricsDao/getClientNodeAggField\";\n\n    /**\n     * 获取 topN clientNode 写分布\n     */\n    public static final String GET_CLIENT_NODE_WRITE                                         = \"GatewayNodeMetricsDao/getClientNodeAggWrite\";\n\n    /**\n     * 获取某 clientNode 写分布\n     */\n    public static final String GET_CLIENT_NODE_WRITE_BY_IP                                   = \"GatewayNodeMetricsDao/getClientNodeAggWriteByIp\";\n\n    /**\n     * 获取 gatewayNode 相关的 clientNode ip 信息\n     */\n    public static final String GET_CLIENT_NODE_BY_GATEWAY_NODE                               = \"GatewayNodeMetricsDao/getClientNodeByGatewayNode\";\n\n    /************************************************************** GatewayAppMetricsDao **************************************************************/\n    /**\n     * 获取某个字段分布.(searchCost，totalCost)\n     */\n    public static final String GET_GATEWAY_APP_FIELD                                         = \"GatewayAppMetricsDao/getAggField\";\n\n    /**\n     * 获取某个字段分布.(searchCost，totalCost) by projectId\n     */\n    public static final String GET_GATEWAY_APP_FIELD_BY_PROJECT_ID = \"GatewayAppMetricsDao/getAggFieldByProjectId\";\n    /**\n     * 获取各App查询量\n     */\n    public static final String GET_GATEWAY_APP_FIELD_COUNT         = \"GatewayAppMetricsDao/getAggFieldCount\";\n\n    /**\n     * 获取各App查询量 by projectId\n     */\n    public static final String GET_GATEWAY_APP_FIELD_COUNT_BY_PROJECT_ID = \"GatewayAppMetricsDao/getAggFieldCountByProjectId\";\n\n    /************************************************************** GatewayDslMetricsDao **************************************************************/\n    public static final String GET_TOTAL_COST_BY_FIELD = \"GatewayDslMetricsDao/getTotalCostByField\";\n    public static final String GET_DSL_COUNT_BY_FILELD = \"GatewayDslMetricsDao/getDslCountByFileld\";\n    public static final String GET_DSL_COUNT_EXTENDED_BOUNDS_BY_FILELD = \"GatewayDslMetricsDao/getDslCountExtendedBoundsByFileld\";\n    /**\n     * 获取某个指定字段下第一个有时间的数据\n     */\n    public static final String GET_HAS_METRIC_INFO_TIME_BY_FIELD = \"GatewayDslMetricsDao/getHasMetricInfoTimeByField\";\n    /**\n     * 保持和之前的结果相同\n     */\n    public static final String GET_TOTAL_COST_EXTENDED_BOUNDS_BY_FIELD = \"GatewayDslMetricsDao/getTotalCostExtendedBoundsByField\";\n    /**\n     * 获取各个查询模版访问量 topNu\n     */\n    public static final String GET_GATEWAY_DSL_COUNT                                         = \"GatewayDslMetricsDao/getDslCount\";\n\n    /**\n     * 获取某个查询模版访问量 by dslTemplateMd5\n     */\n    public static final String GET_GATEWAY_DSL_COUNT_BY_MD5                                  = \"GatewayDslMetricsDao/getDslCountByMd5\";\n    /**\n     * 获取各个查询模版访问耗时 topNu\n     */\n    public static final String GET_GATEWAY_DSL_TOTAL_COST                                    = \"GatewayDslMetricsDao/getDslTotalCost\";\n\n    /**\n     * 获取某个查询模版访问耗时 by dslTemplateMd5\n     */\n    public static final String GET_GATEWAY_DSL_TOTAL_COST_BY_MD5 = \"GatewayDslMetricsDao/getDslTotalCostByMd5\";\n    /**\n     * 获取某个projectId下的 dslTemplateMd5\n     */\n    public static final String GET_GATEWAY_DSL_MD5_BY_PROJECT_ID = \"GatewayDslMetricsDao/getDslMd5ByProjectId\";\n\n    /************************************************************** DslAnalyzeResultTypeEsDao **************************************************************/\n    /**\n     * 根据projectId查询分析结果\n     */\n    public static final String GET_DSL_ANALYZE_RESULT_BY_PROJECT_ID           = \"DslAnalyzeResultTypeEsDao/getDslAnalyzeResultByProjectId\";\n    /**\n     * 根据projectId查询[startDate, endDate]分析结果\n     */\n    public static final String GET_DSL_ANALYZE_RESULT_BY_PROJECT_ID_AND_RANGE = \"DslAnalyzeResultTypeEsDao/getDslAnalyzeResultByProjectIdAndRange\";\n\n    /**************************************************************      DslTemplateEsDao     **************************************************************/\n    /**\n     * 根据指定条件分页获取dsl查询模版数据\n     */\n    public static final String GET_DSL_TEMPLATE_BY_CONDITION                                 = \"DslTemplateEsDao/getDslTemplateByCondition\";\n    /**\n     * 获取所有查询模板最近修改时间在(now-1d,now)范围内，并且不启用的查询模板，然后删除过期的查询模板数据\n     */\n    public static final String GET_EXPIRED_DSL_TEMPLATE       = \"DslTemplateEsDao/deleteExpiredDslTemplate\";\n    /**\n     * 获取某个projectId的所有查询模板数据,已排除老查询模板\n     */\n    public static final String GET_DSL_TEMPLATE_BY_PROJECT_ID = \"DslTemplateEsDao/getAllDslTemplatePoByProjectId\";\n    /**\n     * 获取查询模板创建时间大于指定天偏移的查询模板数据，用于设置慢查耗时阈值\n     */\n    public static final String GET_DSL_TEMPLATES_BY_RANGE     = \"DslTemplateEsDao/getDslTemplatesByDateRange\";\n    /**\n     * 滚动获取查询模板\n     */\n    public static final String SCROLL_DSL_TEMPLATES                                          = \"DslTemplateEsDao/handleScrollDslTemplates\";\n    /**\n     * 根据索引名称获取查询的查询模板\n     */\n    public static final String GET_DSL_TEMPLATES_BY_INDEXNAME                                = \"DslTemplateEsDao/getTemplateMD5ByIndexName\";\n    /**\n     * 根据索引名称获取查询的查询模板\n     */\n    public static final String GET_DSL_TEMPLATES_BY_INDEXNAME_WITH_DAY_RANGE       = \"DslTemplateEsDao/getTemplateMD5ByIndexNameWithDayRange\";\n    /**\n     * 根据索引名称获取查询的查询模板\n     */\n    public static final String GET_DSL_TEMPLATES_BY_INDEXNAME_PROJECT_ID                = \"DslTemplateEsDao/getTemplateMD5ByIndexNameAndProjectId\";\n    /**\n     * 根据索引名称获取查询的查询模板\n     */\n    public static final String GET_DSL_TEMPLATES_BY_INDEXNAME_PROJECT_ID_WITH_DAY_RANGE = \"DslTemplateEsDao/getTemplateMD5ByIndexNameAndProjectIdWithDayRange\";\n    /**\n     * 获取早期查询模板，不包括手动修改限流值\n     */\n    public static final String GET_EARLIEST_DSL_TEMPLATES                               = \"DslTemplateEsDao/getEarliestDslTemplate\";\n    /**\n     * 获取一段时间不使用的查询模板，不包括黑名单和手动修改限流值\n     */\n    public static final String GET_LONG_TIME_NOT_USE_DSL_TEMPLATES      = \"DslTemplateEsDao/getLongTimeNotUseDslTemplate\";\n    /**\n     * 获取projectId一段时间内的dslMetrics\n     */\n    public static final String GET_DSL_TEMPLATE_BY_PROJECT_ID_AND_RANGE = \"DslTemplateEsDao/getDslTemplateByProjectIdAndRange\";\n    /**\n     * 获取过期的查询模板信息\n     */\n    public static final String GET_EXPIRED_DELETED_DSL_TEMPLATE        = \"DslTemplateEsDao/getExpiredAndWillDeleteDslTemplate\";\n    /**\n     * 获取某个projectId的新增查询模板个数,已排除老查询模板\n     */\n    public static final String GET_INCREASE_DSL_TEMPLATE_BY_PROJECT_ID = \"DslTemplateEsDao/getIncreaseTemplateCountByProjectId\";\n    /**\n     * 获取某个projectId的查询模板个数,已排除老版本查询模板\n     */\n    public static final String GET_DSL_TEMPLATE_COUNT_BY_PROJECT_ID    = \"DslTemplateEsDao/getTemplateCountByProjectId\";\n    /**\n     * 获取最近查询模板，不包括手动修改限流值和黑名单\n     */\n    public static final String GET_NEAREST_DSL_TEMPLATES               = \"DslTemplateEsDao/getNearestDslTemplate\";\n    /**\n     * 获取最近没有设置黑白名单的查询模板,已排除老查询模板\n     */\n    public static final String GET_NEAREST_DSL_TEMPLATE_ACCESSABLE                           = \"DslTemplateEsDao/getNearestDslTemplateAccessable\";\n    /**\n     * 获取到缺少ariusCreateTime字段的文档\n     */\n    public static final String GET_MISSING_ARIUS_CREATE_TIME                                 = \"DslTemplateEsDao/getMissingAriusCreateTime\";\n\n    /**************************************************************      IndexSizeEsDao     **************************************************************/\n    /**\n     * 根据索引模板名称获取索引大小信息\n     */\n    public static final String GET_INDEX_SIZE_BY_TEMPLATE                                    = \"IndexSizeEsDao/getIndexSizeByTemplateName\";\n    /**\n     * 获取昨天索引大小\n     */\n    public static final String GET_YESTERDAY_INDEX_SIZE                                      = \"IndexSizeEsDao/getYesterDayIndexSize\";\n\n    /************************************************************      IndexCatESDAO     **************************************************************/\n    /**\n     * 条件查询索引cat/index信息\n     */\n    public static final String GET_CAT_INDEX_INFO_BY_CONDITION                               = \"IndexCatESDAO/getCatIndexInfoByCondition\";\n\n    public static final String GET_ALL_CAT_INDEX_NAME_BY_CLUSTERS                            = \"IndexCatESDAO/getAllCatIndexNameByClusters\";\n    /**\n     * 条件查询索引cat/index信息\n     */\n    public static final String GET_ALL_CAT_INDEX_INFO_BY_TERMS                               = \"IndexCatESDAO/getAllCatIndexInfoByTerms\";\n\n    public static final String GET_PLATFORM_CREATE_CAT_INDEX  = \"IndexCatESDAO/getPlatformCreateCatIndex\";\n    public static final String GET_PLATFORM_CREATE_CAT_INDEX_BY_INDEX_PROJECT  = \"IndexCatESDAO/getPlatformCreateCatIndexByIndexProject\";\n    public static final String GET_PLATFORM_CREATE_CAT_INDEX_BY_INDEX_PROJECT_AND_FUZZY_INDEX_AND_CLUSTER_LOGIC  = \"IndexCatESDAO/getPlatformCreateCatIndexByIndexProjectAndFuzzyIndex\";\n    public static final String GET_PLATFORM_CREATE_CAT_INDEX_BY_INDEX_PROJECT_AND_FUZZY_INDEX_AND_CLUSTER_PHY  =\n            \"IndexCatESDAO/getPlatformCreateCatIndexByIndexProjectAndFuzzyIndexAndClusterPhy\";\n    public static final String GET_PLATFORM_CREATE_CAT_INDEX_GROUP_BY_CLUSTER  = \"IndexCatESDAO/getPlatformCreateCatIndexGroupByCluster\";\n    \n    public static final String GET_PLATFORM_CREATE_CAT_INDEX_BY_ID  = \"IndexCatESDAO/getPlatformCreateCatIndexById\";\n\n    /**\n     * 获取模版所有索引健康状态\n     */\n    public static final String GET_TEMPLATE_INDICES_HEALTH                                   = \"IndexCatESDAO/getTemplateIndicesHealth\";\n\n    /************************************************************      ShardCatESDAO     **************************************************************/\n    /**\n     * 条件查询索引cat/shard信息\n     */\n    public static final String GET_CAT_SHARD_INFO_BY_CONDITION                               = \"ShardCatESDAO/getCatShardInfoByCondition\";\n\n    /**\n     * 构造多字段模糊查询\n     */\n    public static final String SHOULD_TERM_CELL                                              = \"ShardCatESDAO/shouldTermCell\";\n\n\n\n\n    /**************************************************************  IndexNameAccessCountEsDao **************************************************************/\n    /**\n     * 根据索引模板名称获取查询的具体索引统计次数\n     */\n    public static final String SCROLL_GET_TEMPLATE_DETAIL_BY_TEMPLATE                        = \"IndexNameAccessCountEsDao/getIndexNameAccessByTemplate\";\n    /**\n     * 根据索引模板ID获取查询的具体索引统计次数\n     */\n    public static final String SCROLL_GET_TEMPLATE_DETAIL_BY_ID                              = \"IndexNameAccessCountEsDao/getIndexNameAccessByTemplateId\";\n\n    /************************************************************** projecTTemplateAccessCountEsDao **************************************************************/\n    /**\n     * 根据索引模板获取访问projectId列表\n     */\n    public static final String GET_ACCESS_PROJECT_ID_BY_TEMPLATE_NAME                     = \"ProjectIdTemplateAccessCountEsDao/getAccessProjectIdByTemplateName\";\n    /**\n     * 根据索引模板Id获取最近days访问projectId详细信息\n     */\n    public static final String GET_ACCESS_PROJECT_ID_INFO_BY_LOGIC_EMPLATE_ID                 = \"ProjectIdTemplateAccessCountEsDao/getAccessProjectIdInfoByLogicTemplateId\";\n    /**\n     * 根据索引模板Id获取【statdDate,endDate】访问projectId详细信息\n     */\n    public static final String GET_ACCESS_PROJECT_ID_INFO_BY_LOGIC_TEMPLATE_ID_AND_DATE_RANGE = \"ProjectIdTemplateAccessCountEsDao/getAccessProjectIdInfoByLogicTemplateIdAndDateRange\";\n\n    /************************************************************** projectIdTemplateAccessCountEsDao **************************************************************/\n    /**\n     * 获取一个查询模板的数据\n     */\n    public static final String GET_DSL_METRICS_BY_KEY              = \"DslMetricsEsDao/getNeariestDslMetricsByProjectIdTemplateMd5\";\n    /**\n     * 查询某个projectId一天查询次数\n     */\n    public static final String GET_TOTAL_SEARCHCOUNT_BY_PROJECT_ID = \"DslMetricsEsDao/getTotalSearchByProjectIdDate\";\n    /**\n     * 获取最大一分钟查询量\n     */\n    public static final String GET_MAX_QPS_BY_KEY                                     = \"DslMetricsEsDao/getMaxProjectIdTemplateQpsInfoByProjectIdTemplateMd5\";\n    /**\n     * 根据projectId和dslMd5获取一段时间内的详细metrics\n     */\n    public static final String GET_DSL_DETAIL_METRICS_BY_PROJECT_ID_AND_MD5_AND_RANGE = \"DslMetricsEsDao/getDslDetailMetricByProjectIdAndDslTemplateMd5\";\n    /**\n     * 根据projectId和dslMd5获取一段时间内的详细metrics\n     */\n    public static final String GET_PROJECT_ID_TEMPLATE_MD5_INFO = \"DslMetricsEsDao/getProjectIdTemplateMd5Info\";\n    /**\n     * 根据时间范围查询某个projectId的记录数\n     */\n    public static final String GET_TOTAL_HITS_BY_PROJECT_ID     = \"DslMetricsEsDao/queryTotalHitsByProjectIdDate\";\n\n    /************************************************************** DslAnalyzeResultQpsEsDao **************************************************************/\n    /**\n     * 获取查询模板级别最大qps\n     */\n    public static final String GET_MAX_QPS_BY_PROJECT_ID_DSLTEMPLATE = \"DslAnalyzeResultQpsEsDao/getMaxProjectIdTemplateQpsInfoByProjectIdTemplateMd5\";\n\n    \n\n    /**************************************************************   IndexTemplateValueEsDao   **************************************************************/\n    /**\n     * 获取全部模板的价值\n     */\n    public static final String SCROLL_VALUE_LIST_ALL                                         = \"IndexTemplateValueEsDao/listAll\";\n\n\n\n    /**************************************************************   DslFieldUseEsDao   **************************************************************/\n    /**\n     * 根据模板名称获取字段使用信息,最多获取30天\n     */\n    public static final String GET_FIELD_USE_BY_TEMPLATE                                     = \"DslFieldUseEsDao/getFieldUseListByTemplateName\";\n    /**\n     * 根据模板名称获取字段使用信息\n     */\n    public static final String GET_ONE_FIELD_USE_BY_TEMPLATE                                 = \"DslFieldUseEsDao/getFieldUseInfoByTemplateName\";\n\n\n    /**\n     * 获取集群task耗时分位图\n     */\n    public static final String AGG_CLUSTER_TASK_REAL_TIME_AVG_AND_PERCENT                    = \"AriusStatsClusterTaskInfoEsDao/aggClusterTaskCostAvgAndPercentiles\";\n\n    /**\n     * 获取逻辑集群task耗时分位图\n     */\n    public static final String AGG_CLUSTER_LOGIC_TASK_REAL_TIME_AVG_AND_PERCENT                    = \"AriusStatsClusterTaskInfoEsDao/aggClusterLogicTaskCostAvgAndPercentiles\";\n\n\n    /**\n     * 获取集群task数量\n     */\n    public static final String AGG_CLUSTER_TASK_COUNT                                        = \"AriusStatsClusterTaskInfoEsDao/aggClusterTaskCount\";\n\n    /**\n     * 获取集群各个节点上的任务总耗时\n     */\n    public static final String AGG_CLUSTER_NODES_TASK_COST                                   = \"AriusStatsClusterTaskInfoEsDao/aggClusterNodesTaskCost\";\n\n    /**\n     * 获取集群节点task统计信息\n     */\n    public static final String GET_AGG_CLUSTER_NODE_TASK_INFO                                = \"AriusStatsClusterTaskInfoEsDao/getAggClusterPhyNodesTaskInfo\";\n\n    /**\n     * 获取集群节点top的task统计信息\n     */\n    public static final String GET_AGG_CLUSTER_TOP_NODE_TASK_INFO                            = \"AriusStatsClusterTaskInfoEsDao/getTopNNodeTaskAggMetricsInfo\";\n\n    /**\n     * 获取指定集群节点的task统计信息\n     */\n    public static final String GET_AGG_CLUSTER_SINGLE_NODE_TASK_INFO                         = \"AriusStatsClusterTaskInfoEsDao/getAggClusterPhySingleNodeTaskInfo\";\n\n    /**\n     * 获取指定集群节点的task详细信息\n     */\n    public static final String GET_CLUSTER_SINGLE_NODE_TASK_DETAIL_INFO                      = \"AriusStatsClusterTaskInfoEsDao/getClusterPhySingleNodeTaskDetailInfo\";\n\n    /**\n     * 获取指定集群节点有task信息的时间戳\n     */\n    public static final String GET_HAS_CLUSTER_NODE_TASK_DATA_TIME                           = \"AriusStatsClusterTaskInfoEsDao/getHasNodeTaskInfoTime\";\n\n    /**\n     * 获取指定集群采集最近的时间点\n     * getTimeDifferenceBetweenNearestPointAndNow\n     */\n    public static final String GET_TIME_DIFFERENCE_BETWEEN_NEAREST_POINT_AND_NOW             = \"AriusStatsClusterPhyInfoEsDao/getTimeDifferenceBetweenNearestPointAndNow\";\n\n    /***********************************************   AriusStatsDashBoardInfoESDAO   **************************************************************/\n    public static final String FETCH_CLUSTER_HEALTH_INFO                                     = \"AriusStatsDashBoardInfoESDAO/fetchClusterHealthInfo\";\n\n    public static final String GET_HAS_DASHBOARD_METRICS_DATA_TIME                           = \"AriusStatsDashBoardInfoESDAO/getHasDashboardMetricInfoTime\";\n\n    /**\n     * 根据一级指标类型构建最终查询dsl（针对cluster\\clusterThreadPoolQueue维度指标）\n     */\n    public static final String GET_AGG_DASHBOARD_CLUSTER_TOP_NAME_INFO                       = \"AriusStatsDashBoardInfoESDAO/getAggDashboardClusterTopNameInfo\";\n    /**\n     * 根据一级指标类型构建最终查询dsl（针对非cluster维度指标）\n     */\n    public static final String GET_AGG_DASHBOARD_NO_CLUSTER_TOP_NAME_INFO                    = \"AriusStatsDashBoardInfoESDAO/getAggDashboardNoClusterTopNameInfo\";\n\n    /**\n     * 获取filter agg 的过滤片段\n     */\n    public static final String GET_AGG_FILTER_FRAGMENT                                       = \"AriusStatsDashBoardInfoESDAO/getAggFilterFragment\";\n\n\n\n    /**\n     * 获取top Dashboard维度统计信息(针对cluster维度、clusterThreadPoolQueue维度指标)\n     */\n    public static final String GET_TOP_DASHBOARD_CLUSTER_AGG_METRICS_INFO                    = \"AriusStatsDashBoardInfoESDAO/getTopDashboardClusterAggMetricsInfo\";\n\n    /**\n     * 获取top Dashboard维度统计信息(针对非cluster维度指标)\n     */\n    public static final String GET_TOP_DASHBOARD_NO_CLUSTER_AGG_METRICS_INFO                    = \"AriusStatsDashBoardInfoESDAO/getTopDashboardNoClusterAggMetricsInfo\";\n\n    /**\n     * 获取List类型 Dashboard维度统计信息(带标识的类型)\n     */\n    public static final String FETCH_LIST_FLAG_METRIC                                        =\n            \"AriusStatsDashBoardInfoESDAO/fetchListFlagMetric\";\n    \n        /**\n     * 获取List类型 Dashboard维度统计信息(阈值处理)\n     */\n    public static final String FETCH_LIST_THRESHOLDS_METRIC                                        =\n            \"AriusStatsDashBoardInfoESDAO/fetchListThresholdsMetric\";\n\n    /**\n     * 获取List类型 Dashboard维度统计信息(带数据值的类型)\n     */\n    public static final String FETCH_LIST_VALUE_METRIC                                       = \"AriusStatsDashBoardInfoESDAO/fetchListValueMetrics\";\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/es/metric/BaseTopNMetricsDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.es.metric;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.GatewayMetricsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.BaseESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didiglobal.knowframework.elasticsearch.client.response.query.query.hits.ESHits;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Value;\n\n/**\n * top n 指标采集dao\n *\n * @author shizeying\n * @date 2022/05/10\n */\npublic abstract class BaseTopNMetricsDAO extends BaseESDAO {\n    @Value(\"${es.update.cluster.name}\")\n    protected              String metadataClusterName;\n    protected static final ILog   LOGGER     = LogFactory.getLog(BaseTopNMetricsDAO.class);\n    protected              String indexName;\n    protected static final String TYPE       = \"type\";\n    protected static final String TIMESTAMP  = \"timeStamp\";\n    protected static final String TERM       = \"term\";\n    protected static final String TERMS      = \"terms\";\n    protected static final String PROJECT_ID = \"projectId\";\n    protected static final String VALUE      = \"value\";\n    protected static final String EMPTY_STR  = \"\";\n    protected static final String BUCKETS    = \"buckets\";\n    \n    /**\n     * 执行具体的top N 拉取查询 *\n     *\n     * @param gatewayMetricsTypeEnum 网关指标类型枚举\n     * @param startTime              开始时间\n     * @param endTime                结束时间\n     * @param func                   函数\n     * @param hasDataTimeDsl         数据时间dsl\n     * @param metricValue            指标值\n     * @param params                 传入方式参照 *\n     *                               {@link BaseTopNMetricsDAO#getFinalDslByOneStep(GatewayMetricsTypeEnum, Object[])}\n     * @return {@link List}<{@link VariousLineChartMetrics}>\n     */\n    protected <R> List<R> performFetchTopMetric(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                                Long endTime, Function<ESQueryResponse, List<R>> func,\n                                                String hasDataTimeDsl, String metricValue,Object... params) throws AdminOperateException {\n        //校验指标值是否存在\n        final List<R> metrics = checkMetricsValue(gatewayMetricsTypeEnum, metricValue);\n        if (CollectionUtils.isNotEmpty(metrics)) {\n            return metrics;\n        }\n        final Long timePoint = getGatewayHasDataTimeByField(startTime, endTime, hasDataTimeDsl);    // 查询剪支\n        if (Objects.isNull(timePoint)) {\n            return Collections.emptyList();\n        }\n        Tuple<Long, Long> firstInterval = MetricsUtils.getSortInterval(endTime - startTime, timePoint);\n        long startInterval = firstInterval.getV1();\n        long endInterval = MetricsUtils.getDailyNextOneMinute(startInterval);\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startInterval, endInterval);\n        final List<Object> arrayList = Lists.newArrayList(params);\n        arrayList.add(0, startInterval);\n        arrayList.add(1, endInterval);\n        final Object[] args = arrayList.toArray();\n        //同时匹配多种枚举类型\n        String dsl = getFinalDslByOneStep(gatewayMetricsTypeEnum , args);\n        //TODO performRequest出错未处理，返回结果为NULL，需要优化\n        return gatewayClient.performRequest(metadataClusterName, realIndexName, TYPE, dsl, func, 3);\n    }\n    \n    /**\n     * 对具体的{@link  GatewayMetricsTypeEnum} 进行召回 *\n     *\n     * @param gatewayMetricsTypeEnum 网关指标类型枚举\n     * @param startTime              开始时间 用于计算真实查询的索引列表\n     * @param endTime                结束时间 用于计算真实查询的索引列表\n     * @param func                   函数\n     * @param params                 参数个数 传入方式参照\n     *                               {@link BaseTopNMetricsDAO#getFinalDslBySecondStep(GatewayMetricsTypeEnum, Object[])} *\n     *                               @return {@link List}<{@link MetricsContent}>\n     */\n    protected List<MetricsContent> performGetByRangeTopN(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                                         Long endTime,\n                                                         Function<ESQueryResponse, List<MetricsContent>> func,\n                                                         Object... args)\n            throws AdminOperateException {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        String dsl = getFinalDslBySecondStep(gatewayMetricsTypeEnum , args);\n        if (Objects.isNull(dsl)) {\n            return Collections.emptyList();\n        }\n        return gatewayClient.performRequest(realIndexName, TYPE, dsl, func, 3);\n    }\n    \n\n    \n    /**\n     * 网关有时间数据字段 *\n     *\n     * @param startTime      开始时间\n     * @param endTime        结束时间\n     * @param hasDataTimeDsl 数据时间dsl\n     * @return {@link Long}\n     */\n    private Long getGatewayHasDataTimeByField(Long startTime, Long endTime, String hasDataTimeDsl) {\n        String realIndexName = IndexNameUtils.genDailyIndexName(indexName, startTime, endTime);\n        return gatewayClient.performRequest(metadataClusterName, realIndexName, TYPE, hasDataTimeDsl,\n                response -> Optional.ofNullable(response).map(ESQueryResponse::getHits).map(ESHits::getHits)\n                        .filter(CollectionUtils::isNotEmpty)\n                        //由于过滤出来不为空的hits，那么我们只需要获取第一个值即可，这就是我们想要的hit，请注意这里不会产生NPE异常\n                        .map(hits -> hits.get(0).getSource()).map(hit -> ((JSONObject) hit).getLongValue(TIMESTAMP))\n                        .orElse(null), 3);\n    }\n    \n    /**\n     * 判断project id 是否存在并进行构建\n     * <pre>\n     *     {\n     *     \"term\": {\n     *     \"projectId\": {\n     *     \"value\": %d\n     *           }\n     *           }\n     *           }\n     *           </pre>  or\n     * <pre> \"\"     </pre>\n     *\n     * @param projectId projectId\n     * @return {@link String}\n     */\n    protected String buildTermByProjectId(Integer projectId) {\n        return Objects.nonNull(projectId)\n                ? \",\" + new JSONObject().fluentPut(TERM,\n                new JSONObject().fluentPut(PROJECT_ID, new JSONObject().fluentPut(VALUE, projectId))).toJSONString()\n                : EMPTY_STR;\n    }\n    \n    /**\n     * 这里不带,的terms\n     * <pre>\n     *      {\n     *           \"terms\": {\n     *             \"FIELD\": [\n     *               \"VALUE1\",\n     *               \"VALUE2\"\n     *             ]\n     *           }\n     *         }\n     * </pre>\n     *\n     * @param field\n     * @param values 值\n     * @return {@link String}\n     */\n    protected String buildTermsByField(String field, List<Object> values) {\n        return new JSONObject().fluentPut(TERMS, new JSONObject().fluentPut(field, values)).toJSONString();\n    }\n    \n    /**\n     * 构建第一阶段查询的dsl\n     *\n     * @param gatewayMetricsTypeEnum 网关指标类型枚举\n     * @param args\n     * @return {@link String}\n     */\n    protected abstract String getFinalDslByOneStep(GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                   Object[] args);\n    \n    protected abstract String getFinalDslBySecondStep(GatewayMetricsTypeEnum gatewayMetricsTypeEnum,\n                                                      Object[] args);\n    \n    /**\n     * 获取指定范围的指标top n *\n     *\n     * @param values                 第一阶段召回的结果\n     * @param gatewayMetricsTypeEnum 网关指标类型枚举\n     * @param startTime              开始时间 *\n     * @param endTime                结束时间\n     * @param projectId              projectId\n     * @return {@link List}<{@link MetricsContent}>\n     */\n    public abstract List<MetricsContent> getByRangeTopN(List<String> values,\n                                                        GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                                        Long endTime, Integer projectId) throws AdminOperateException;\n    \n    /**\n     * 检查指标value,如果存在则返回{@link Collections#singleton(R)}，如果不存在则则返回{@link Collections#emptyList()} * * @param\n     * gatewayMetricsTypeEnum 网关指标类型枚举 * @param metricsValue 指标value * @return {@link List}<{@link R}>\n     */\n    public abstract <R> List<R> checkMetricsValue(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, String metricsValue);\n    \n    /**\n     * 获取最高规 *\n     *\n     * @param gatewayMetricsTypeEnum 网关指标类型枚举\n     * @param startTime              开始时间\n     * @param endTime                结束时间\n     * @param topNu                  top n\n     * @param projectId              projectId\n     * @param value                  value 指标值 *\n     * @return {@link List}<{@link VariousLineChartMetrics}>\n     */\n    public abstract <R> List<R> fetchTopMetric(GatewayMetricsTypeEnum gatewayMetricsTypeEnum, Long startTime,\n                                               Long endTime, Integer topNu, Integer projectId, String value)\n            throws AdminOperateException;\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/config/AriusConfigInfoDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.config;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.config.AriusConfigInfoPO;\n\n/**\n * 配置表需要在开启mybatis中的二级缓存\n * @author d06679\n * @date 2019/3/14\n */\n@Repository\npublic interface AriusConfigInfoDAO {\n\n    /**\n     * 插入平台配置\n     * @param param po\n     * @return 插入数量\n     */\n    int insert(AriusConfigInfoPO param);\n\n    /**\n     * 更新平台配置\n     * @param param po\n     * @return 更新数量\n     */\n    int update(AriusConfigInfoPO param);\n\n    /**\n     * 通过id去更新status\n     * @param id 平台配置id\n     * @param status 状态\n     * @return 更新数量\n     */\n    int updateByIdAndStatus(@Param(\"id\") Integer id, @Param(\"status\") int status);\n\n    /**\n     * 通过条件获取平台配置\n     * @param condition 条件\n     * @return 平台配置list\n     */\n    List<AriusConfigInfoPO> listByCondition(AriusConfigInfoPO condition);\n\n    /**\n     * 通过id获取平台配置\n     * @param configId 配置id\n     * @return 平台配置po\n     */\n    AriusConfigInfoPO getById(Integer configId);\n\n    /**\n     * 通过group和name获取平台配置\n     * @param valueGroup 配置组\n     * @param valueName 配置名称\n     * @return 平台配置po\n     */\n    AriusConfigInfoPO getByGroupAndName(@Param(\"valueGroup\") String valueGroup, @Param(\"valueName\") String valueName);\n\n    /**\n     * 通过配置组获取平台配置list\n     * @param group 配置组\n     * @return 配置po\n     */\n    List<AriusConfigInfoPO> listByGroup(String group);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/ecm/ESClusterConfigDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.esconfig.ESConfigPO;\nimport java.util.List;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author lyn\n * @date 2020-12-30\n */\n@Repository\npublic interface ESClusterConfigDAO {\n    List<ESConfigPO> listByClusterId(Long clusterId);\n\n    ESConfigPO getByClusterIdAndTypeAndEngin(@Param(\"clusterId\") Long clusterId, @Param(\"type\") String type,\n                                             @Param(\"engin\") String engin);\n\n    int insert(ESConfigPO param);\n\n    int update(ESConfigPO param);\n\n    ESConfigPO getValidEsConfigById(Long id);\n\n    ESConfigPO getById(Long id);\n\n    int delete(Long id);\n\n    ESConfigPO getByClusterIdAndTypeAndEnginAndVersion(@Param(\"clusterId\") Long clusterId, @Param(\"type\") String type,\n                                                       @Param(\"engin\") String enginName,\n                                                       @Param(\"version\") Integer version);\n\n    int updateConfigValidById(Long id);\n\n    int insertSelective(ESConfigPO param);\n\n    int deleteByClusterIdAndTypeAndEngin(@Param(\"clusterId\") Long clusterId, @Param(\"type\") String type,\n                                         @Param(\"engin\") String enginName);\n\n    Integer getClusterIdByConfigId(@Param(\"id\") Long configId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/ecm/ESClusterRoleDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRolePO;\nimport java.util.List;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * 集群角色DAO\n * @author chengxiang\n * @date 2022/5/9\n */\n@Repository\npublic interface ESClusterRoleDAO {\n\n    /**\n     * 插入一条记录\n     * @param param\n     * @return\n     */\n    int insert(ESClusterRolePO param);\n\n    /**\n     * 根据id 获取集群角色信息\n     * @param id\n     * @return\n     */\n    ESClusterRolePO getById(Long id);\n\n    /**\n     * 根据clusterId 和 roleClusterName 查询详情\n     * @param clusterId\n     * @param roleClusterName\n     * @return\n     */\n    ESClusterRolePO getByClusterIdAndClusterRole(@Param(\"clusterId\") Long clusterId,\n                                                 @Param(\"roleClusterName\") String roleClusterName);\n\n    /**\n     * 根据clusterId 和 role 查询详情\n     * @param clusterId\n     * @return\n     */\n    List<ESClusterRolePO> listByClusterId(String clusterId);\n\n    /**\n     * 根据clusterId 查询详情\n     * @param clusterIds\n     * @return\n     */\n    List<ESClusterRolePO> listByClusterIds(List<String> clusterIds);\n\n    /**\n     * 根据clusterId 和 role 修改podCount\n     * @param param\n     * @return\n     */\n    int update(ESClusterRolePO param);\n\n    /**\n     * 根据clusterId 和 role 修改es版本\n     * @param elasticClusterId\n     * @param role\n     * @param esVersion\n     * @return\n     */\n    int updateVersionByClusterIdAndRole(@Param(\"elasticClusterId\") Long elasticClusterId, @Param(\"role\") String role,\n                                        @Param(\"esVersion\") String esVersion);\n\n    /**\n     * 根据clusterId 和 role 查询详情\n     * @param clusterId\n     * @param role\n     * @return\n     */\n    ESClusterRolePO getByClusterIdAndRole(@Param(\"clusterId\") Long clusterId, @Param(\"role\") String role);\n\n    /**\n     * 根据clusterId 删除记录\n     * @param clusterId\n     * @return\n     */\n    int delete(Integer clusterId);\n\n    /**\n     * 根据clusterId 和 role 删除记录\n     * @param clusterId\n     * @param role\n     * @return\n     */\n    int deleteRoleClusterByCluterIdAndRole(@Param(\"clusterId\") Long clusterId, @Param(\"role\") String role);\n    \n    int countByClusterId(@Param(\"clusterId\")Integer clusterId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/ecm/ESClusterRoleHostDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRoleHostPO;\nimport java.util.List;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * ES集群表对应各角色主机列表 Mapper 接口\n * @author chengxiang\n * @date 20222/4/22\n */\n@Repository\npublic interface ESClusterRoleHostDAO {\n    /**\n     * 插入一条主机记录\n     * @param param\n     * @return\n     */\n    int insert(ESClusterRoleHostPO param);\n\n    /**\n     * 根据id 获取一条主机记录\n     * @param id\n     * @return\n     */\n    ESClusterRoleHostPO getById(Long id);\n\n    /**\n     * 根据roleId 获取主机名称列表\n     * @param roleId\n     * @return\n     */\n    List<String> listHostNamesByRoleId(String roleId);\n\n    /**\n     * 根据roleClusterId 获取主机信息列表\n     * @param roleClusterId\n     * @return\n     */\n    List<ESClusterRoleHostPO> listByRoleClusterId(Long roleClusterId);\n\n    /**\n     * 根据多条roleClusterId 获取主机信息列表\n     * @param roleClusterIds\n     * @return\n     */\n    List<ESClusterRoleHostPO> listByRoleClusterIds(List<Long> roleClusterIds);\n\n    /**\n     * 根据集群和nodeSet 信息查询符合条件的主机信息列表\n     * @param cluster\n     * @param nodeSets\n     * @return\n     */\n    List<ESClusterRoleHostPO> listByClusterAndNodeSets(@Param(\"cluster\") String cluster,\n                                                       @Param(\"nodeSets\") List<String> nodeSets);\n\n    /**\n     * 根据条件查询符合条件的主机信息列表\n     * @param param\n     * @return\n     */\n    List<ESClusterRoleHostPO> listByCondition(ESClusterRoleHostPO param);\n\n    /**\n     * 根据集群信息查询符合条件的主机信息列表\n     * @param cluster\n     * @return\n     */\n    List<ESClusterRoleHostPO> listByCluster(String cluster);\n\n    /**\n     * 更新主机信息\n     * @param param\n     * @return\n     */\n    int update(ESClusterRoleHostPO param);\n\n    int updateRegionId(@Param(\"ids\") List<Integer> ids, @Param(\"regionId\") Integer regionId);\n\n    /**\n     * 将所有在线的节点置为离线,在同步集群节点时调用;需要在事务内调用,保证失败后回滚\n     * @param cluster\n     * @return\n     */\n    int offlineByCluster(String cluster);\n\n    /**\n     * 查询在线节点信息列表\n     * @return\n     */\n    List<ESClusterRoleHostPO> listOnlineNode();\n\n    /**\n     * 根据集群删除主机信息\n     * @param cluster\n     * @return\n     */\n    int deleteByCluster(String cluster);\n\n    /**\n     * 根据主机名和roleId 重置主机状态\n     * @param hostname\n     * @param roleId\n     * @return\n     */\n    int restoreByHostNameAndRoleId(@Param(\"hostname\") String hostname, @Param(\"roleId\") Long roleId);\n\n    /**\n     * 获取所有节点信息\n     * @return       List<ESClusterRoleHostPO>\n     */\n    List<ESClusterRoleHostPO> listAll();\n\n    /**\n     * 获取指定角色节点信息\n     * @return           List<ESClusterRoleHostPO>\n     */\n    List<ESClusterRoleHostPO> listAllByRoleCode(Integer roleCode);\n\n    /**\n     * 根据主机名获取主机信息\n     * @param hostName\n     * @return\n     */\n    ESClusterRoleHostPO getByHostName(String hostName);\n\n    /**\n     * 根据id 删除主机信息\n     * @param id\n     * @return\n     */\n    int delete(Long id);\n    int deleteByIds(@Param(\"ids\")List<Integer> ids);\n\n    /**\n     * 根据主机名和roleId 删除主机信息\n     * @param hostnames\n     * @param roleId\n     * @return\n     */\n    int deleteByHostNameAndRoleId(@Param(\"hostNames\") List<String> hostnames, @Param(\"roleId\") Long roleId);\n\n    /**\n     * 根据主机名和roleId 获取已删除的主机信息\n     * @param hostname\n     * @param roleId\n     * @return\n     */\n    ESClusterRoleHostPO getDeleteHostByHostNameAnRoleId(@Param(\"hostname\") String hostname,\n                                                        @Param(\"roleId\") Long roleId);\n\n    /**\n     * 更新主机状态，并将状态置为有效\n     * @param param\n     * @return\n     */\n    int updateHostValid(ClusterRoleHost param);\n\n    /**\n     *  根据主机名和roleId 获取主机数量\n     * @param roleId\n     * @return\n     */\n    int getPodNumberByRoleId(@Param(\"roleId\") Long roleId);\n\n    /**\n     * 根据regionId获取节点列表\n     * @param regionId  regionId\n     * @return   List<ESClusterRoleHostPO>\n     */\n    List<ESClusterRoleHostPO> listByRegionId(Integer regionId);\n\n    /**\n     * 根据集群名称获取region节点信息,\n     * @param cluster  集群名称\n     * @return         List<ESClusterRoleHostPO>\n     */\n    List<ESClusterRoleHostPO> listDataNodeByCluster(String cluster);\n    \n    /**\n     * 它返回 ClusterRoleHost 对象的列表。\n     *\n     * @param ids 要查询的id列表。\n     * @return 列表<ClusterRoleHost>\n     */\n    List<ESClusterRoleHostPO> listByIds(@Param(\"ids\") List<Integer> ids);\n\n    /**\n     * 物理集群下的节点\n     * @param phyClusterNames\n     * @return\n     */\n    List<ESClusterRoleHostPO> listByClusters(List<String> phyClusterNames);\n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/ecm/ESMachineNormsDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm;\n\nimport java.util.List;\n\nimport org.springframework.stereotype.Repository;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESMachineNormsPO;\n\n/**\n * 容器规格列表 Mapper 接口\n * @author didi\n * @since 2020-08-24\n */\n@Repository\npublic interface ESMachineNormsDAO {\n\n    List<ESMachineNormsPO> listMachineNorms();\n\n    ESMachineNormsPO getById(Long id);\n\n    int insert(ESMachineNormsPO param);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/ecm/ESPackageDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.espackage.ESPackagePO;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\nimport java.util.List;\n\n/**\n * 程序包版本管理 Dao 接口\n * @author didi\n * @since 2020-08-24\n */\n@Repository\npublic interface ESPackageDAO {\n\n    /**\n     * 获取所有es package\n     * @return es安装包list\n     */\n    List<ESPackagePO> listAll();\n\n    /**\n     * 新增es安装包\n     * @param param 安装包\n     * @return 插入成功数\n     */\n    int insert(ESPackagePO param);\n\n    /**\n     * 更新es安装包\n     * @param param 安装包\n     * @return 更新数\n     */\n    int update(ESPackagePO param);\n\n    /**\n     * 根据id获取es安装包\n     * @param id 安装包id\n     * @return es安装包po\n     */\n    ESPackagePO getById(Long id);\n\n    /**\n     * 通过版本和类型获取安装包\n     * @param esVersion es版本\n     * @param manifest 类型\n     * @return es安装包po\n     */\n    ESPackagePO getByVersionAndType(@Param(\"esVersion\") String esVersion, @Param(\"manifest\") Integer manifest);\n\n    /**\n     * 通过es版本、类型以及id获取安装包\n     * @param esVersion es版本\n     * @param manifest 类型\n     * @param id 安装包id\n     * @return es安装包po\n     */\n    ESPackagePO getByVersionAndManifestNotSelf(@Param(\"esVersion\") String esVersion,\n                                               @Param(\"manifest\") Integer manifest, @Param(\"id\") Long id);\n\n    /**\n     * 通过id删除es安装包\n     * @param id es版本id\n     * @return 删除数量\n     */\n    int delete(Long id);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/ecm/ESPluginDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin.PluginPO;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n@Repository\npublic interface ESPluginDAO {\n\n    List<PluginPO> listAll();\n\n    List<PluginPO> getAllSysDefaultPlugins();\n\n    int insert(PluginPO pluginPO);\n\n    int update(PluginPO param);\n\n    int updateDesc(@Param(\"id\") Long id, @Param(\"desc\") String desc);\n\n    int insertBatch(List<PluginPO> params);\n\n    PluginPO getById(Long id);\n\n    List<PluginPO> getByNameAndVersion(@Param(\"name\") String name, @Param(\"version\") String version);\n\n    int delete(Long id);\n\n    List<PluginPO> getByNameAndVersionAndPhysicClusterId(@Param(\"name\") String name, @Param(\"version\") String version,\n                                                         @Param(\"physicClusterId\") String physicClusterId);\n\n    List<PluginPO> listByPhyClusterId(String phyClusterId);\n\n    List<PluginPO> listByPlugIds(List<Long> plugIds);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/gateway/GatewayClusterDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.gateway;\n\nimport java.util.List;\n\nimport org.springframework.stereotype.Repository;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayClusterPO;\n\n/**\n * @author d06679\n */\n@Repository\npublic interface GatewayClusterDAO {\n\n    /**\n     * 插入数据\n     * @param param po\n     * @return int\n     */\n    int insert(GatewayClusterPO param);\n\n    /**\n     * 查询所有数据\n     * @return List<GatewayClusterPO>\n     */\n    List<GatewayClusterPO> listAll();\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/gateway/GatewayClusterNodeDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.gateway;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayClusterNodePO;\n\n/**\n * @author d06679\n */\n@Repository\npublic interface GatewayClusterNodeDAO {\n\n    /**\n     * 插入数据\n     * @param gatewayClusterNodePO 对应po类\n     * @return int\n     */\n    int recordGatewayNode(GatewayClusterNodePO gatewayClusterNodePO);\n\n    /**\n     * 根据集群名和时间获取存活的节点数\n     * @param clusterName 集群名\n     * @param time 时间\n     * @return int\n     */\n    int aliveCountByClusterNameAndTime(@Param(\"clusterName\") String clusterName, @Param(\"time\") Date time);\n\n    /**\n     * 根据集群名和时间获取列表\n     * @param clusterName 集群名\n     * @param time 时间\n     * @return List<GatewayClusterNodePO> 列表\n     */\n    List<GatewayClusterNodePO> listAliveNodeByClusterNameAndTime(@Param(\"clusterName\") String clusterName,\n                                                                 @Param(\"time\") Date time);\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/metrics/MetricsDictionaryDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.metrics;\n\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricDictionaryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.metrics.MetricsDictionaryPO;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n/**\n * 用户指标配置dao\n *\n * @author gyp\n * @date 2022/05/24\n */\n@Repository\npublic interface MetricsDictionaryDAO extends BaseMapper<MetricsDictionaryPO> {\n    /**\n     * 查询所有的配置\n     * @return 集群列表\n     */\n    List<MetricsDictionaryPO> listAll();\n\n    /**\n     * 通过model查询所有的配置\n     * @return 集群列表\n     */\n    List<MetricsDictionaryPO> listByModel(String model);\n\n    List<MetricsDictionaryPO> listByCondition(MetricDictionaryDTO param);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/metrics/UserConfigDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.metrics;\n\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.metrics.UserConfigPO;\nimport org.springframework.stereotype.Repository;\n\n/**\n * 用户指标配置dao\n *\n * @author shizeying\n * @date 2022/05/24\n */\n@Repository\npublic interface UserConfigDAO extends BaseMapper<UserConfigPO> {\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/monitor/AriusMetaJobClusterDistributeDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.monitor;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.monitor.AriusMetaJobClusterDistributePO;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author ohushenglin_v\n */\n@Repository\npublic interface AriusMetaJobClusterDistributeDAO {\n\n    /**\n     * 获取所有的采集集群\n     *\n     * @return 可采集的集群信息\n     */\n    List<AriusMetaJobClusterDistributePO> getAllTask();\n\n    /**\n     * 根据数据中心获取所有的采集集群\n     *\n     * @param dataCentre 数据中心\n     * @return 可采集的集群信息\n     */\n    List<AriusMetaJobClusterDistributePO> getAllTaskByDataCentre(String dataCentre);\n\n    /**\n     * 根据host获取所有的采集集群\n     *\n     * @param monitorHost   host\n     * @param size          size\n     * @return 可采集的集群信息\n     */\n    List<AriusMetaJobClusterDistributePO> getTaskByHost(@Param(\"monitorHost\") String monitorHost,\n                                                        @Param(\"size\") int size);\n\n    /**\n     * 使用这个方法时要特别小心\n     * @param ariusMetaJobClusterDistributePO  变更数据\n     * @return 变更数量\n     */\n    int updateMonitorHost(AriusMetaJobClusterDistributePO ariusMetaJobClusterDistributePO);\n\n    /**\n     * 更新监控时间\n     * @param ariusMetaJobClusterDistributePO   变更数据\n     * @return 变更数量\n     */\n    int updateMonitorTime(AriusMetaJobClusterDistributePO ariusMetaJobClusterDistributePO);\n\n    /**\n     * 批量插入\n     * @param newTasks 插入的数据\n     * @return 变更数量\n     */\n    int insertBatch(List<AriusMetaJobClusterDistributePO> newTasks);\n\n    /**\n     * 新增\n     * @param taskEntity 插入的数据\n     * @return 变更数量\n     */\n    int insert(AriusMetaJobClusterDistributePO taskEntity);\n\n    /**\n     * 批量删除\n     * @param deleteIds 删除ID列表\n     * @return 变更数量\n     */\n    int deleteBatch(List<Long> deleteIds);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/optrecord/OperateRecordDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.optrecord;\n\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.operaterecord.OperateRecordInfoPO;\n\nimport java.util.Date;\nimport java.util.List;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author d06679\n * @date 2019/3/14\n */\n@Repository\npublic interface OperateRecordDAO {\n    /**\n     * 通过条件查询列表\n     * @param param OperateRecordInfoPO\n     * @return List<OperateRecordPO>\n     */\n    List<OperateRecordInfoPO> listByCondition(OperateRecordDTO param);\n\n    /**\n     * 总数计算\n     *\n     * @param param 入参\n     * @return int\n     */\n    Long countByCondition(OperateRecordDTO param);\n\n    /**\n     * 插入一条数据\n     * @param po    OperateRecordInfoPO\n     * @return      int\n     */\n    int insert(OperateRecordInfoPO po);\n\n    /**\n     * 通过moduleId和topN获取数据\n     * @param moduleId 操作id\n     * @param topN     top数\n     * @return OperateRecordPO\n     */\n    OperateRecordInfoPO selectDescTopNByModuleId(@Param(\"moduleId\") int moduleId, @Param(\"topN\") int topN);\n\n    /**\n     * 删除saveTime之前的数据\n     * @param saveTime 规定的保存时间\n     * @return OperateRecordPO\n     */\n     void deleteExprieData(@Param(\"saveTime\") Date saveTime);\n\n    /**\n     * 通过moduleId和id删除数据\n     * @param moduleId  操作id\n     * @param id        id\n     */\n    void deleteByModuleIdAndLessThanId(@Param(\"moduleId\") int moduleId, @Param(\"id\") int id);\n\n    /**\n     * 获取通过id\n     *\n     * @param id id\n     * @return {@code OperateRecordInfoPO}\n     */\n    OperateRecordInfoPO getById(Integer id);\n\n    /**\n     * 获取一条操作记录\n     * @param operateRecordDTO\n     * @return\n     */\n    OperateRecordInfoPO selectOneOperateRecord(OperateRecordDTO operateRecordDTO);\n\n    /**\n     * 根据id更新\n     * @param convertOperateRecordInfoPO\n     * @return\n     */\n    int updateById(OperateRecordInfoPO convertOperateRecordInfoPO);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/project/ESUserDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO;\nimport java.util.List;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * es 用户\n *\n * @author shizeying\n * @date 2022/05/25\n */\n@Repository\npublic interface ESUserDAO {\n\n    /**\n     * 条件查询\n     * @param  param   param\n     * @return         List<AppPO>\n     */\n    List<ESUserPO> listByCondition(ESUserPO param);\n\n    /**\n     * 插入\n     * @param param param\n     * @return      插入成功条数\n     */\n    int insert(ESUserPO param);\n\n    int countByProjectId(@Param(\"projectId\") Integer projectId);\n\n    /**\n     * 根据id获取App\n     * @param esUser    主键\n     * @return         AppPO\n     */\n    ESUserPO getByESUser(@Param(\"esUser\") Integer esUser);\n\n    /**\n     * 更新\n     * @param param   param\n     * @return   更新成功条数\n     */\n    int update(ESUserPO param);\n\n    /**\n     * 删除\n     * @param esUser  主键\n     * @return   删除成功条数\n     */\n    int delete(@Param(\"esUser\") Integer esUser);\n\n    /**\n     * 删除项目中所有的es user\n     *\n     * @param projectId 项目id\n     * @return int\n     */\n    int deleteByProjectId(@Param(\"projectId\") Integer projectId);\n\n    /**\n     * 根据项目id获取app信息\n     * @param projectId  项目名称\n     * @return      List<AppPO>\n     */\n    List<ESUserPO> listByProjectId(@Param(\"projectId\") Integer projectId);\n\n    /**\n     * 根据主键列表获取app信息\n     * @param projectIds    项目集合\n     * @return           List<AppPO>\n     */\n    List<ESUserPO> listByProjectIds(@Param(\"projectIds\") List<Integer> projectIds);\n\n\n\n    Integer maxById();\n\n    /**\n     * 通过项目id获取默认的es user\n     *\n     * @param projectId 项目id\n     * @return {@code ESUser}\n     */\n    ESUser getDefaultESUserByProject(@Param(\"projectId\") Integer projectId);\n\n    /**\n     * 获取项目中的默认es user\n     *\n     * @param projectId 项目id\n     * @return int\n     */\n    int countDefaultESUserByProject(@Param(\"projectId\") Integer projectId);\n\n    /**\n     * 获取项目id通过搜索类型\n     *\n     * @param searchType 搜索类型\n     * @return {@code List<Integer>}\n     */\n    List<Integer> getProjectIdBySearchType(@Param(\"searchType\") Integer searchType);\n\n    /**\n     * 通过项目id和搜索类型\n     *\n     * @param searchType 搜索类型\n     * @param projectId  项目id\n     * @return int\n     */\n    int countByProjectIdAndSearchType(@Param(\"searchType\") Integer searchType, @Param(\"projectId\") Integer projectId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/project/ProjectConfigDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectConfigPO;\nimport java.util.List;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * esconfigdao\n *\n * @author shizeying\n * @date 2022/05/25\n */\n@Repository\npublic interface ProjectConfigDAO {\n\n    ProjectConfigPO getByProjectId(@Param(\"projectId\") int projectId);\n\n    int insert(ProjectConfigPO param);\n\n    int update(ProjectConfigPO param);\n\n    List<ProjectConfigPO> listAll();\n\n    boolean checkProjectConfigByProjectId(@Param(\"projectId\") int projectId);\n\n    int deleteByProjectId(@Param(\"projectId\") int projectId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/project/ProjectLogicClusterAuthDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectClusterLogicAuthPO;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n/**\n * @author wangshu\n * @date 2020/09/17\n */\n@Repository\npublic interface ProjectLogicClusterAuthDAO {\n\n    List<ProjectClusterLogicAuthPO> listByCondition(ProjectClusterLogicAuthPO param);\n\n    int insert(ProjectClusterLogicAuthPO param);\n\n    int update(ProjectClusterLogicAuthPO param);\n\n    int delete(Long authId);\n\n    int deleteByLogicClusterId(Long logicClusterId);\n\n    List<ProjectClusterLogicAuthPO> listByProjectId(@Param(\"projectId\") int projectId);\n\n    List<ProjectClusterLogicAuthPO> listWithAccessByProjectId(@Param(\"projectId\") int projectId);\n\n    ProjectClusterLogicAuthPO getById(Long authId);\n\n    ProjectClusterLogicAuthPO getByProjectIdAndLogicClusterId(@Param(\"projectId\") Integer projectId,\n                                                              @Param(\"logicClusterId\") Long logicClusterId);\n\n    ProjectClusterLogicAuthPO getByProjectIdAndLogicClusterIdAndType(@Param(\"projectId\") Integer projectId,\n                                                                     @Param(\"logicClusterId\") Long logicClusterId,\n                                                                     @Param(\"type\") Integer type);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/project/ProjectTemplateAuthDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.project;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectTemplateAuthPO;\nimport java.util.List;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author d06679\n * @date 2019/4/16\n */\n@Repository\npublic interface ProjectTemplateAuthDAO {\n\n    List<ProjectTemplateAuthPO> listByCondition(ProjectTemplateAuthPO param);\n\n    int insert(ProjectTemplateAuthPO param);\n\n    int update(ProjectTemplateAuthPO param);\n\n    int delete(Long authId);\n\n    int deleteByTemplate(Integer templateId);\n\n    int batchDeleteByTemplateIds(List<Integer> templateIds);\n\n    List<ProjectTemplateAuthPO> listWithRwAuthsByProjectId(@Param(\"projectId\") int projectId);\n\n    List<ProjectTemplateAuthPO> getByTemplateId(Integer templateId);\n\n    ProjectTemplateAuthPO getById(Long authId);\n\n    ProjectTemplateAuthPO getByProjectIdAndTemplateId(@Param(\"projectId\") Integer projectId,\n                                                      @Param(\"templateId\") String templateId);\n\n    ProjectTemplateAuthPO getByProjectIdAndTemplateIdAndType(@Param(\"projectId\") Integer projectId,\n                                                             @Param(\"templateId\") String templateId,\n                                                             @Param(\"type\") Integer type);\n\n    List<ProjectTemplateAuthPO> listByLogicTemplateId(String logicTemplateId);\n\n    List<ProjectTemplateAuthPO> listWithRwAuths();\n\n    List<ProjectTemplateAuthPO> listWithOwnerAuths();\n\n    Integer getProjectIdById(Long authId);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/region/ClusterRegionDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.region;\n\nimport java.util.List;\n\nimport org.springframework.stereotype.Repository;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterRegionPO;\n\n@Repository\npublic interface ClusterRegionDAO {\n\n    ClusterRegionPO getById(Long regionId);\n\n    ClusterRegionPO getByName(String regionName);\n\n    ClusterRegionPO getByLogicClusterId(Long logicClusterId);\n\n    List<ClusterRegionPO> getByPhyClusterName(String phyClusterName);\n\n    List<ClusterRegionPO> listByPhyClusterNames(List<String> phyClusterNames);\n\n    int insert(ClusterRegionPO param);\n\n    int update(ClusterRegionPO param);\n\n    int delete(Long regionId);\n\n    int deleteByClusterPhyName(String clusterPhyName);\n\n    List<ClusterRegionPO> listAll();\n\n    List<ClusterRegionPO> listBoundRegions();\n\n    /**\n     * 条件查询\n     * @param condt 查询参数，仅仅id，logicClusterId，phyClusterName有效\n     * @return\n     */\n    List<ClusterRegionPO> listBoundRegionsByCondition(ClusterRegionPO condt);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/resource/LogicClusterDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.resource;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterLogicPO;\nimport java.util.List;\nimport java.util.Set;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * 逻辑集群DAO\n * @author d06679\n * @date 2019/3/22\n */\n@Repository\npublic interface LogicClusterDAO {\n\n    List<ClusterLogicPO> listByCondition(ClusterLogicPO param);\n\n    List<ClusterLogicPO> listByNameAndProjectId(@Param(\"name\") String name, @Param(\"projectId\") Integer projectId);\n\n    int insert(ClusterLogicPO param);\n\n    int update(ClusterLogicPO param);\n\n    int delete(Long id);\n\n    ClusterLogicPO getById(Long id);\n\n    List<ClusterLogicPO> listByIds(@Param(\"ids\") Set<Long> ids);\n\n    ClusterLogicPO getByName(String name);\n\n    ClusterLogicPO getLastCommon();\n\n    List<ClusterLogicPO> listByProjectId(@Param(\"projectId\") Integer projectId);\n\n    List<ClusterLogicPO> listAll();\n\n\n    List<ClusterLogicPO> pagingByCondition(ClusterLogicConditionDTO param);\n\n    Long getTotalHitByCondition(ClusterLogicConditionDTO param);\n    \n    List<ClusterLogicPO> listByLevel(Integer level);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/resource/PhyClusterDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.resource;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterPhyPO;\nimport java.util.List;\nimport java.util.Set;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * 物理集群信息 DAO\n *\n * @author ohushenglin_v\n */\n@Repository\npublic interface PhyClusterDAO {\n\n    /**\n     * 条件查询物理集群信息\n     * @param param 查询条件\n     * @return  物理集群列表\n     */\n    List<ClusterPhyPO> listByCondition(ClusterPhyPO param);\n\n    /**\n     * 分页查询物理集群信息\n     * @param conditionDTO   查询条件\n     * @return  物理集群列表\n     */\n    List<ClusterPhyPO> pagingByCondition(ClusterPhyConditionDTO conditionDTO);\n\n    /**\n     * 跟据查询条件获取物理集群总量\n     * @param conditionDTO     查询条件\n     * @return  集群数量\n     */\n    long getTotalHitByCondition(ClusterPhyConditionDTO conditionDTO);\n\n    /**\n     * insert\n     * @param param 待插入数量\n     * @return  变更数量\n     */\n    int insert(ClusterPhyPO param);\n\n    /**\n     * update\n     * @param param 待更新数据\n     * @return  变更数量\n     */\n    int update(ClusterPhyPO param);\n\n    /**\n     * 更新插件ID\n     * @param plugIds 插件ID\n     * @param clusterId 集群ID\n     * @return 变更数量\n     */\n    int updatePluginIdsById(@Param(\"plugIds\") String plugIds, @Param(\"clusterId\") Integer clusterId);\n\n    /**\n     * 删除集群\n     * @param clusterId 集群ID\n     * @return 变更数量\n     */\n    int delete(Integer clusterId);\n\n    /**\n     * 跟据ID获取单个集群信息\n     * @param clusterId 集群ID\n     * @return 集群信息\n     */\n    ClusterPhyPO getById(Integer clusterId);\n\n    /**\n     * 跟据集群名称查询单个集群\n     * @param clusterName 集群名称\n     * @return 集群信息\n     */\n    ClusterPhyPO getByName(String clusterName);\n\n    /**\n     * 跟据多个集群名称获取集群列表\n     * @param names 集群名称列表\n     * @return  集群列表\n     */\n    List<ClusterPhyPO> listByNames(List<String> names);\n\n    /**\n     * 查询所有的集群列表\n     * @return 集群列表\n     */\n    List<ClusterPhyPO> listAll();\n\n    /**\n     * 查询所有的集群名称\n     * @return 集群名称列表\n     */\n    List<String> listAllName();\n\n    /**\n     * 跟据多个集群ID获取集群列表\n     * @param ids 集群IDs\n     * @return 集群列表\n     */\n    List<ClusterPhyPO> listByIds(@Param(\"ids\") Set<Long> ids);\n\n    /**\n     * 获取绑定对应安装包的集群数量\n     * @param packageId 安装包id\n     * @return  long count\n     */\n    long getTotalHitByPackageId(@Param(\"packageId\") Long packageId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/task/EcmTaskDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskPO;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n@Repository\npublic interface EcmTaskDAO {\n    int save(EcmTaskPO param);\n\n    List<EcmTaskPO> listAll();\n\n    EcmTaskPO getById(Long id);\n\n    int update(EcmTaskPO param);\n\n    int updateStatusById(@Param(\"id\") Long id, @Param(\"status\") String status);\n\n    List<EcmTaskPO> listUndoEcmTaskByClusterId(Long physicClusterId);\n\n    EcmTaskPO getUsefulEcmTaskByClusterId(Integer physicClusterId);\n\n    List<EcmTaskPO> listRunningTasks();\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/task/EcmTaskDetailDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskDetailPO;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n/**\n * ES集群 工单任务详情 Mapper 接口\n * @author didi\n * @since 2020-08-24\n */\n@Repository\npublic interface EcmTaskDetailDAO {\n    int replace(EcmTaskDetailPO param);\n\n    int save(EcmTaskDetailPO param);\n\n    EcmTaskDetailPO getById(Long taskDetailId);\n\n    List<EcmTaskDetailPO> listByWorkOrderTaskId(Long workOrderTaskId);\n\n    int updateStatus(@Param(\"workOrderTaskId\") Long workOrderTaskId, @Param(\"hostname\") String hostname,\n                     @Param(\"status\") String status);\n\n    List<EcmTaskDetailPO> listByTaskIdAndRoleAndWorkOrderTaskId(@Param(\"workOrderTaskId\") Integer workOrderTaskId,\n                                                                @Param(\"role\") String role,\n                                                                @Param(\"taskId\") Integer taskId);\n\n    int updateTaskIdByRoleAndWorkOrderTaskId(@Param(\"workOrderTaskId\") Long workOrderTaskId, @Param(\"role\") String role,\n                                             @Param(\"taskId\") Long taskId);\n\n    int update(EcmTaskDetailPO param);\n\n    EcmTaskDetailPO getByWorkOderIdAndHostName(@Param(\"workOrderTaskId\") Long workOrderId,\n                                               @Param(\"hostname\") String hostname);\n\n    int deleteEcmTaskDetailsByTaskOrder(Long workOrderTaskId);\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/task/OpTaskDAO.java",
    "content": "/*\n * Copyright (c) 2015, WINIT and/or its affiliates. All rights reserved. Use, Copy is subject to authorized license.\n */\npackage com.didichuxing.datachannel.arius.admin.persistence.mysql.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.task.OpTaskPO;\nimport java.util.List;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * OpTask Dao\n * \n * @author fengqiongfeng\n * @date 2020-12-21\n */\n@Repository\npublic interface OpTaskDAO {\n    /**\n     * 新增\n     *\n     * @param param 参数\n     * @return int\n     */\n    int insert(OpTaskPO param);\n\n    /**\n     * 获取通过id\n     *\n     * @param id id\n     * @return {@link OpTaskPO}\n     */\n    OpTaskPO getById(@Param(\"id\") Integer id);\n\n    /**\n     * 获取所有集合\n     *\n     * @return {@link List}<{@link OpTaskPO}>\n     */\n    List<OpTaskPO> listAll();\n\n    /**\n     * 通过入参条件动态获取集合\n     *\n     * @param param 入参\n     * @return {@link List}<{@link OpTaskPO}>\n     */\n    List<OpTaskPO> listByCondition(OpTaskPO param);\n\n    /**\n     * 更新\n     *\n     * @param param 入参\n     * @return int\n     */\n    int update(OpTaskPO param);\n\n    /**\n     * 获取最新任务\n     *\n     * @param businessKey 业务关键\n     * @param taskType 任务类型\n     *\n     * @return {@link OpTaskPO}\n     */\n    OpTaskPO getLatestTask(@Param(\"businessKey\") String businessKey, @Param(\"taskType\") Integer taskType);\n\n    /**\n     * 获取pending任务\n     *\n     * @param businessKey 业务key\n     * @param taskType 任务类型\n     * @return {@link OpTaskPO}\n     */\n    OpTaskPO getPendingTask(@Param(\"businessKey\") String businessKey, @Param(\"taskType\") Integer taskType);\n\n    /**\n     * 通过任务类型获取pending任务\n     *\n     * @param taskType 任务类型\n     * @return {@link List}<{@link OpTaskPO}>\n     */\n    List<OpTaskPO> getPendingTaskByType(@Param(\"taskType\") Integer taskType);\n\n    /**\n     *  通过任务类型获取成功任务\n     *\n     * @param taskType 任务类型\n     * @return {@link List}<{@link OpTaskPO}>\n     */\n    List<OpTaskPO> getSuccessTaskByType(@Param(\"taskType\") Integer taskType);\n\n    /**\n     * 任务中心分页查询数据\n     * @param queryDTO\n     * @param from\n     * @param size\n     * @param sortTerm\n     * @param sortType\n     * @return\n     */\n    List<OpTaskPO> pagingByCondition(@Param(\"param\")OpTaskQueryDTO queryDTO, @Param(\"from\")Long from,\n                                     @Param(\"size\")Long size, @Param(\"sortTerm\")String sortTerm, @Param(\"sortType\")String sortType);\n\n    /**\n     * 任务中心分页查询条数\n     * @param queryDTO\n     * @return\n     */\n    Long countByCondition(OpTaskQueryDTO queryDTO);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/template/IndexTemplateAliasDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.template;\n\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateAliasPO;\n\n/**\n *\n *\n * @author d06679\n * @date 2018/6/11\n */\n@Repository\npublic interface IndexTemplateAliasDAO {\n\n    List<TemplateAliasPO> listAll();\n\n    List<TemplateAliasPO> listByTemplateId(int logicId);\n\n    int insert(TemplateAliasPO param);\n\n    int delete(@Param(\"logicId\") Integer logicId, @Param(\"name\") String name);\n\n    int insertBatch(List<TemplateAliasPO> list);\n\n    int deleteBatch(@Param(\"logicIds\") List<Integer> logicId, @Param(\"name\") String name);\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/template/IndexTemplateConfigDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateConfigPO;\nimport java.util.List;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author d06679\n * @date 2019/3/29\n */\n@Repository\npublic interface IndexTemplateConfigDAO {\n\n    List<TemplateConfigPO> listByCondition(TemplateConfigPO param);\n\n    List<TemplateConfigPO> listAll();\n\n    int insert(TemplateConfigPO param);\n\n    int update(TemplateConfigPO param);\n\n    int delete(Long configId);\n\n    int deleteByLogicId(Integer logicId);\n\n    TemplateConfigPO getById(Long configId);\n\n    TemplateConfigPO getByLogicId(Integer logicId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/template/IndexTemplateDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport java.util.List;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author chengxiang\n * @date 2022/5/10\n */\n@Repository\npublic interface IndexTemplateDAO {\n\n    List<IndexTemplatePO> listByCondition(IndexTemplatePO param);\n\n    int insert(IndexTemplatePO param);\n\n    int update(IndexTemplatePO param);\n\n    int delete(Integer logicId);\n\n    IndexTemplatePO getById(Integer logicId);\n\n    List<IndexTemplatePO> listByProjectId(Integer projectId);\n\n    List<IndexTemplatePO> listAll();\n\n    List<IndexTemplatePO> listByIds(@Param(\"logicIds\") List<Integer> logicIds);\n\n    List<IndexTemplatePO> listByResourceIds(@Param(\"resourceIds\") List<Long> resourceIds);\n\n    List<IndexTemplatePO> listByDataCenter(String dataCenter);\n\n    List<IndexTemplatePO> listByName(String name);\n\n    List<IndexTemplatePO> likeByCondition(IndexTemplatePO param);\n\n    List<IndexTemplatePO> pagingByCondition(@Param(\"param\") IndexTemplatePO param, @Param(\"from\") Long from,\n                                            @Param(\"size\") Long size, @Param(\"sortTerm\") String sortTerm,\n                                            @Param(\"sortType\") String sortType);\n    List<IndexTemplatePO> pagingByConditionAndLogicClusterIdList(@Param(\"param\") IndexTemplatePO param,\n                                                                 @Param(\"from\") Long from,\n                                                                 @Param(\"size\") Long size, @Param(\"sortTerm\") String sortTerm,\n                                                                 @Param(\"sortType\") String sortType, @Param(\"logicClusterIdList\")List<Integer> logicClusterIdList);\n\n    long getTotalHitByCondition(IndexTemplatePO param);\n    long getTotalHitByConditionAndLogicClusterIdList(@Param(\"param\")IndexTemplatePO param,@Param(\"logicClusterIdList\")List<Integer> logicClusterIdList);\n\n    int batchChangeHotDay(@Param(\"days\") Integer days, @Param(\"templateIdList\") List<Integer> templateIdList);\n\n    int updateBlockReadState(@Param(\"logicId\") Integer logicId, @Param(\"blockRead\") Boolean blockRead);\n\n    int updateBlockWriteState(@Param(\"logicId\") Integer logicId, @Param(\"blockWrite\") Boolean blockWrite);\n\n    List<String> listAllNames();\n\n    Integer getProjectIdByTemplateLogicId(@Param(\"logicId\") Integer templateLogicId);\n\n    String getNameByTemplateLogicId(@Param(\"logicId\") Integer logicTemplateId);\n    \n    List<Integer> getLogicTemplateIdListByProjectId(@Param(\"projectId\")Integer projectId);\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/template/IndexTemplatePhyDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO;\nimport java.util.List;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author chengxiang\n * @date 2022/5/9\n */\n@Repository\npublic interface IndexTemplatePhyDAO {\n\n    List<IndexTemplatePhyPO> listByCondition(IndexTemplatePhyPO param);\n\n    int insert(IndexTemplatePhyPO param);\n\n    IndexTemplatePhyPO getById(Long physicalId);\n\n    List<IndexTemplatePhyPO> listByLogicId(Integer logicId);\n    IndexTemplatePhyPO getTemplateByLogicIdAndRole(@Param(\"logicId\") Integer logicId, @Param(\"role\") Integer role);\n\n    List<IndexTemplatePhyPO> getByLogicIdAndStatus(@Param(\"logicId\") Integer logicId, @Param(\"status\") Integer status);\n\n    int update(IndexTemplatePhyPO param);\n\n    int updateStatus(@Param(\"physicalId\") Long physicalId, @Param(\"status\") Integer status);\n\n    List<IndexTemplatePhyPO> getByClusterAndStatus(@Param(\"cluster\") String cluster, @Param(\"status\") Integer status);\n\n    List<IndexTemplatePhyPO> getByClusterAndNameAndStatus(@Param(\"cluster\") String cluster, @Param(\"name\") String name,\n                                                          @Param(\"status\") Integer status);\n\n    List<IndexTemplatePhyPO> listByClusterAndStatus(@Param(\"cluster\") String cluster, @Param(\"status\") Integer status);\n\n    List<IndexTemplatePhyPO> listByMatchClusterAndStatus(@Param(\"cluster\") String cluster,\n                                                         @Param(\"status\") Integer status);\n\n    IndexTemplatePhyPO getByClusterAndName(@Param(\"cluster\") String cluster, @Param(\"name\") String name);\n\n    int deleteDirtyByClusterAndName(@Param(\"cluster\") String cluster, @Param(\"name\") String name);\n\n    List<IndexTemplatePhyPO> listByLogicIds(List<Integer> logicIds);\n\n    List<IndexTemplatePhyPO> listByIds(List<Long> physicalIds);\n\n    List<IndexTemplatePhyPO> listAll();\n\n    List<IndexTemplatePhyPO> listByName(String template);\n\n    IndexTemplatePhyPO getNormalAndDeletingById(Long physicalId);\n\n    /**\n     * 用于聚合logicId计数，仅查询了logicId和id\n     * @return\n     */\n    List<IndexTemplatePhyPO> countListByLogicId();\n\n    List<IndexTemplatePhyPO> listByRegionId(Integer regionId);\n    \n    int updateShardNumByLogicId(@Param(\"logicId\")Integer logicId, @Param(\"shardNum\")Integer shardNum);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/template/IndexTemplateTypeDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.template;\n\nimport java.util.List;\n\nimport org.springframework.stereotype.Repository;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateTypePO;\n\n/**\n *\n *\n * @author d06679\n * @date 2018/6/11\n */\n@Repository\npublic interface IndexTemplateTypeDAO {\n\n    List<TemplateTypePO> listByIndexTemplateId(Integer indexTemplateId);\n\n    int update(TemplateTypePO param);\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/java/com/didichuxing/datachannel/arius/admin/persistence/mysql/workorder/WorkOrderDAO.java",
    "content": "package com.didichuxing.datachannel.arius.admin.persistence.mysql.workorder;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport org.apache.ibatis.annotations.Param;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO;\nimport org.springframework.stereotype.Repository;\n\n/**\n * @author fengqiongfeng\n * @date 2020/8/26\n */\n@Repository\npublic interface WorkOrderDAO {\n\n    /**\n     * 新增\n     *\n     * @param param 入参\n     * @return int\n     */\n    int insert(WorkOrderPO param);\n\n    /**\n     * 获取通过id\n     *\n     * @param id id\n     * @return {@link WorkOrderPO}\n     */\n    WorkOrderPO getById(@Param(\"id\") Long id);\n\n    List<WorkOrderPO> list();\n\n    /**\n     * 更新订单状态通过id\n     *\n     * @param id id\n     * @param status 状态\n     * @return int\n     */\n    int updateOrderStatusById(@Param(\"id\") Long id, @Param(\"status\") Integer status);\n\n    int update(WorkOrderPO param);\n\n    /**\n     * 由申请人和状态列表\n     *\n     * @param applicantProjectId 项目id\n     * @param status 状态\n     * @return {@link List}<{@link WorkOrderPO}>\n     */\n    List<WorkOrderPO> listByStatusAndProjectId(@Param(\"status\") Integer status,\n                                               @Param(\"applicantProjectId\") Integer applicantProjectId);\n\n    /**\n    * 由申请人和状态列表\n    *\n    * @param applicant 申请人\n    * @param status 状态\n    * @return {@link List}<{@link WorkOrderPO}>\n    */\n    List<WorkOrderPO> listByApplicantAndStatus(@Param(\"applicant\") String applicant, @Param(\"status\") Integer status);\n\n    /**\n     * 审批人列表\n     *\n     * @param approver 审批人\n     * @param status 状态\n     * @return {@link List}<{@link WorkOrderPO}>\n     */\n    List<WorkOrderPO> listByApproverAndStatus(@Param(\"approver\") String approver, @Param(\"status\") Integer status);\n\n    /**\n     * 列表状态\n     *\n     * @param status\n     * @return {@link List}<{@link WorkOrderPO}>\n     */\n    List<WorkOrderPO> listByStatus(@Param(\"status\") Integer status);\n\n    /**\n     * 更新扩展id\n     *\n     * @param param 入参\n     * @return int\n     */\n    int updateExtensionsById(WorkOrderPO param);\n\n    /**\n     * 列表处理时间\n     *\n     * @param startTime 开始时间\n     * @param endTime 结束时间\n     * @return {@link List}<{@link WorkOrderPO}>\n     */\n    List<WorkOrderPO> listByHandleTime(@Param(\"startTime\") Date startTime, @Param(\"endTime\") Date endTime);\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterPhyInfoEsDao/getAggPercentilesMetricsByRange",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n        \t \"physicCluster\": {\n        \t   \"value\": \"%s\"\n        \t  }\n           }\n        },\n        {\n          \"term\": {\n            \"percentilesType\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"date_histogram\": {\n        \"field\": \"timestamp\",\n        \"fixed_interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0\n      },\n      \"aggs\": {\n        \"%s\": {\n          \"%s\": {\n            \"field\": \"statis.%s\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterPhyInfoEsDao/getClusterMetricsByRangeAndInterval",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n                     \"term\": {\n                         \"physicCluster\": {\n                        \t \"value\": \"%s\"\n                          }\n                     }\n                },\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n\t\t\t\t\t\t\t\"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"hist\": {\n\t\t\t\"date_histogram\": {\n\t\t\t\t\"field\": \"timestamp\",\n\t\t\t\t\"fixed_interval\": \"%s\",\n\t\t\t\t\"time_zone\": \"Asia/Shanghai\",\n\t\t\t\t\"min_doc_count\": 0\n\t\t\t},\n\t\t\t\"aggs\": {\n               %s\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterPhyInfoEsDao/getGatewayCount",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"terms\": {\n            \"clusterName\": [\n              \"%s\"\n            ]\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"gatewaySuccessCount\": {\n      \"filter\": {\n        \"terms\": {\n          \"status\": [\n            200,\n            201\n          ]\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterPhyInfoEsDao/getTimeDifferenceBetweenNearestPointAndNow",
    "content": "{\n  \"size\": 1,\n  \"sort\": [\n    {\n      \"timestamp\": {\n        \"order\": \"DESC\"\n      }\n    }\n  ],\n  \"_source\": [\n    \"timestamp\"\n  ],\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"term\": {\n            \"cluster\": \"%s\"\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterTaskInfoEsDao/aggClusterLogicTaskCostAvgAndPercentiles",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [\n\t\t\t    {\n\t\t\t    \"terms\": {\n                       \"node\": %s\n                    }\n\t\t\t    },\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": \"%s\",\n\t\t\t\t\t\t\t\"lte\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"percentiles\": {\n\t\t\t\"percentiles\": {\n\t\t\t\t\"field\": \"metrics.%s\",\n\t\t\t\t\"percents\": [55, 75, 95, 99]\n\t\t\t}\n\t\t},\n\t\t\"avg\": {\n\t\t\t\"avg\": {\n\t\t\t\t\"field\": \"metrics.%s\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterTaskInfoEsDao/aggClusterNodesTaskCost",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"term\": {\n            \"cluster\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"metrics.node\",\n        \"size\": %d\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"sum\": {\n            \"field\": \"metrics.runningTime\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterTaskInfoEsDao/aggClusterTaskCostAvgAndPercentiles",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": \"%s\",\n\t\t\t\t\t\t\t\"lte\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"percentiles\": {\n\t\t\t\"percentiles\": {\n\t\t\t\t\"field\": \"metrics.%s\",\n\t\t\t\t\"percents\": [55, 75, 95, 99]\n\t\t\t}\n\t\t},\n\t\t\"avg\": {\n\t\t\t\"avg\": {\n\t\t\t\t\"field\": \"metrics.%s\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterTaskInfoEsDao/aggClusterTaskCount",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": \"%s\",\n\t\t\t\t\t\t\t\"lte\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterTaskInfoEsDao/getAggClusterPhyNodesTaskInfo",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n\t\t\t\t\t\t\t\"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"hist\": {\n\t\t\t\"terms\": {\n\t\t\t\t\"field\": \"metrics.node\",\n\t\t\t\t\"size\": %d,\n\t\t\t\t\"collect_mode\": \"breadth_first\"\n\t\t\t},\n\t\t\t\"aggs\": {\n\t\t\t\t\"hist\": {\n\t\t\t\t\t\"date_histogram\": {\n\t\t\t\t\t\t\"field\": \"timestamp\",\n\t\t\t\t\t\t\"fixed_interval\": \"%s\",\n\t\t\t\t\t\t\"time_zone\": \"Asia/Shanghai\",\n\t\t\t\t\t\t\"min_doc_count\": 0\n\t\t\t\t\t},\n\t\t\t\t\t\"aggs\": %s\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterTaskInfoEsDao/getAggClusterPhySingleNodeTaskInfo",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"filter\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": \"%s\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"metrics.node\": \"%s\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n\t\t\t\t\t\t\t\"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"hist\": {\n\t\t\t\"date_histogram\": {\n\t\t\t\t\"field\": \"timestamp\",\n\t\t\t\t\"fixed_interval\": \"%s\",\n\t\t\t\t\"time_zone\": \"Asia/Shanghai\",\n\t\t\t\t\"min_doc_count\": 0,\n                \"extended_bounds\" : {\n                    \"min\" : %d,\n                    \"max\" : %d\n                }\n\t\t\t},\n\t\t\t\"aggs\": %s\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterTaskInfoEsDao/getClusterPhySingleNodeTaskDetailInfo",
    "content": "{\n\t\"size\": 1000,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"filter\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": \"%s\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"metrics.node\": \"%s\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n\t\t\t\t\t\t\t\"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"sort\": [\n        {\n          \"metrics.startTime\": {\n            \"order\": \"asc\"\n          }\n        }\n    ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterTaskInfoEsDao/getHasNodeTaskInfoTime",
    "content": "{\n    \"_source\": \"timestamp\",\n\t\"size\": 1,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n                            \"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"sort\": [\n\t  {\n\t    \"timestamp\": {\n\t      \"order\": \"desc\"\n\t    }\n\t  }\n\t]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsClusterTaskInfoEsDao/getTopNNodeTaskAggMetricsInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"terms\": {\n            \"metrics.node\": %s\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"metrics.node\",\n        \"size\": %d\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n            }\n          },\n          \"aggs\": %s\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsDashBoardInfoESDAO/fetchClusterHealthInfo",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"exists\": {\n            \"field\": \"%s\"\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": \"%s\",\n  \"sort\": [\n    {\n      \"timestamp\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsDashBoardInfoESDAO/fetchListFlagMetric",
    "content": "{\n  \"size\": 10000,\n  \"sort\": [\n      {\n        \"%s.%s\": {\n          \"order\": \"%s\"\n        }\n      }\n  ],\n  \"_source\": %s,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"term\": {\n            \"%s.%s\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"%s.timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsDashBoardInfoESDAO/fetchListThresholdsMetric",
    "content": "{\n  \"size\": 10000,\n  \"sort\": [\n      {\n        \"%s.timestamp\": {\n          \"order\": \"%s\"\n        }\n      }\n  ],\n  \"_source\": [\"%s.cluster\", \"%s.%s\", \"%s.%s\"],\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"term\": {\n            \"%s.%s\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"%s.timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsDashBoardInfoESDAO/fetchListValueMetrics",
    "content": "{\n  \"size\": 10000,\n  \"_source\": [\n    \"%s.cluster\",\n    \"%s.%s\",\n    \"%s.%s\"\n  ],\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"range\": {\n            \"%s.timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        },\n        {\n           \"range\": {\n             \"%s.%s\": {\n               \"gte\": 1,\n             }\n           }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"%s.%s\": {\n        \"order\": \"%s\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsDashBoardInfoESDAO/getAggDashboardClusterTopNameInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"range\": {\n            \"%s.timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"%s.%s\",\n        \"size\": %d,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"%s.timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0\n          },\n          \"aggs\": {\n            %s\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsDashBoardInfoESDAO/getAggDashboardNoClusterTopNameInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"range\": {\n            \"%s.timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"script\": {\n          \"source\": \"doc['%s.cluster'].value+'@'+doc['%s.%s'].value\"\n        },\n        \"size\": %d,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"%s.timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0\n          },\n          \"aggs\": {\n            %s\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsDashBoardInfoESDAO/getAggFilterFragment",
    "content": "\"%s\": {\n              \"filter\": {\n                \"range\": {\n                  \"%s.%s\": {\n                    \"%s\": %d\n                  }\n                }\n              },\n              \"aggs\": {\n                \"%s\": {\n                  \"%s\": {\n                    \"field\": \"%s.%s\"\n                  }\n                }\n              }\n            }"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsDashBoardInfoESDAO/getHasDashboardMetricInfoTime",
    "content": "{\n  \"_source\": \"%s.timestamp\",\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"range\": {\n            \"%s.timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"%s.timestamp\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsDashBoardInfoESDAO/getTopDashboardClusterAggMetricsInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n      %s\n        {\n          \"terms\": {\n            \"%s.%s\": %s\n          }\n        },\n        {\n          \"range\": {\n            \"%s.timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"%s.%s\",\n        \"size\": %d,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"%s.timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\": {\n              \"min\": %d,\n              \"max\": %d\n            }\n          },\n          \"aggs\": {\n            %s\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsDashBoardInfoESDAO/getTopDashboardNoClusterAggMetricsInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n      %s\n        {\n           \"terms\": {\n             \"%s.cluster\": %s\n           }\n        },\n        {\n          \"terms\": {\n            \"%s.%s\": %s\n          }\n        },\n        {\n          \"range\": {\n            \"%s.timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"script\": {\n          \"source\": \"doc['%s.cluster'].value+'@'+doc['%s.%s'].value\"\n        },\n        \"size\": %d,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"%s.timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\": {\n              \"min\": %d,\n              \"max\": %d\n            }\n          },\n          \"aggs\": {\n            %s\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getAggMultipleIndicesMetrics",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"index\",\n        \"size\": %d,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0\n          },\n          \"aggs\": {\n             %s\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getAggMultipleIndicesMetricsWithStep",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"index\",\n        \"size\": %d,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0\n          },\n          \"aggs\": {\n             %s\n          }\n        },\n         %s\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getAggMultipleIndicesMetricsWithStepAndIndexList",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"terms\": {\n            \"index\": %s\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"index\",\n        \"size\": %d,\n        \"min_doc_count\": 1,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0\n          },\n          \"aggs\": {\n             %s\n          }\n        },\n         %s\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getAggMultipleTemplateMetrics",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must_not\": [\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": \"0\"\n            }\n          }\n        }\n      ],\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"logicTemplateId\",\n        \"size\": %d,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0\n          },\n          \"aggs\": {\n             %s\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getAggMultipleTemplateMetricsWithStep",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must_not\": [\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": \"0\"\n            }\n          }\n        }\n      ],\n      \"filter\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"logicTemplateId\",\n        \"size\": %d,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0\n          },\n          \"aggs\": {\n             %s\n          }\n        }\n        ,%s\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getAggMultipleTemplateMetricsWithStepAndLogicIds",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n       {\n          \"terms\": {\n            \"logicTemplateId\": %s\n          }\n        },\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"logicTemplateId\",\n        \"size\": %d,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0\n          },\n          \"aggs\": {\n             %s\n          }\n        }\n        ,%s\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getAggSingleIndexMetrics",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"filter\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": \"%s\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"index\": \"%s\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n\t\t\t\t\t\t\t\"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"hist\": {\n\t\t\t\"date_histogram\": {\n\t\t\t\t\"field\": \"timestamp\",\n\t\t\t\t\"fixed_interval\": \"%s\",\n\t\t\t\t\"time_zone\": \"Asia/Shanghai\",\n\t\t\t\t\"min_doc_count\": 0\n\t\t\t},\n\t\t\t\"aggs\": {\n\t\t\t\t%s\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getAggSingleTemplateMetrics",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"filter\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": \"%s\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"logicTemplateId\": \"%d\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n\t\t\t\t\t\t\t\"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"hist\": {\n\t\t\t\"date_histogram\": {\n\t\t\t\t\"field\": \"timestamp\",\n\t\t\t\t\"fixed_interval\": \"%s\",\n\t\t\t\t\"time_zone\": \"Asia/Shanghai\",\n\t\t\t\t\"min_doc_count\": 0\n\t\t\t},\n\t\t\t\"aggs\": {\n\t\t\t\t%s\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getAvgTpsByLogicIdAndTimeRange",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lt\": \"%d\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"groupByTemplateId\": {\n      \"terms\": {\n        \"field\": \"templateId\",\n        \"size\": 10\n      },\n      \"aggs\": {\n        \"minute_buckets\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"interval\": \"1m\"\n          },\n          \"aggs\": {\n            \"sum_tps\": {\n              \"sum\": {\n                \"field\": \"metrics.indexing-index_total_rate\"\n              }\n            }\n          }\n        },\n        \"avg_tps\": {\n          \"percentiles_bucket\": {\n            \"buckets_path\": \"minute_buckets>sum_tps\",\n            \"percents\": [\n              50\n            ]\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getClusterLogicTpsQpsInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n           \"term\": {\n             \"cluster\": {\n                \"value\": \"%s\"\n             }\n          }\n        },\n        {\n          \"terms\": {\n\t\t\t\"node\": %s\n\t\t  }\n\t\t},\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"sum\": {\n      \"sum\": {\n        \"field\": \"metrics.%s\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getClusterTpsQpsInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"sum\": {\n      \"sum\": {\n        \"field\": \"metrics.%s\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getHasIndexMetricsDataTime",
    "content": "{\n    \"_source\": \"timestamp\",\n\t\"size\": 1,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n                            \"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"sort\": [\n\t  {\n\t    \"timestamp\": {\n\t      \"order\": \"desc\"\n\t    }\n\t  }\n\t]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getHistoryMaxTpsByLogicIdAndTimeRange",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lt\": \"%d\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"groupByTemplateId\": {\n      \"terms\": {\n        \"field\": \"templateId\",\n        \"size\": 10\n      },\n      \"aggs\": {\n        \"hour_hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"interval\": \"30m\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 1\n          },\n          \"aggs\": {\n            \"minute_hist\": {\n              \"date_histogram\": {\n                \"field\": \"timestamp\",\n                \"interval\": \"1m\",\n                \"time_zone\": \"Asia/Shanghai\",\n                \"min_doc_count\": 1\n              },\n              \"aggs\": {\n                \"minute_tps_sum\": {\n                  \"sum\": {\n                    \"field\": \"metrics.indexing-index_total_rate\"\n                  }\n                }\n              }\n            },\n            \"hour_tps_avg\": {\n              \"percentiles_bucket\": {\n                \"buckets_path\": \"minute_hist>minute_tps_sum\",\n                \"percents\": [\n                  50\n                ]\n              }\n            }\n          }\n        },\n        \"max_tps\": {\n          \"max_bucket\": {\n            \"buckets_path\": \"hour_hist>hour_tps_avg[50.0]\"\n          }\n        }\n      }\n    },\n    \"max_tps_templateId\": {\n      \"max_bucket\": {\n        \"buckets_path\": \"groupByTemplateId>max_tps\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getIndexRealTimeInfoByTemplateAndCluster",
    "content": "{\n    \"query\":{\n        \"bool\":{\n            \"must\":[\n                {\n                    \"range\":{\n                        \"timestamp\":{\n                            \"gte\":%d,\n                            \"lte\":%d\n                        }\n                    }\n                },\n                {\n                    \"term\":{\n                        \"cluster\":{\n                            \"value\":\"%s\"\n                        }\n                    }\n                },\n                {\n                    \"term\":{\n                        \"template\":{\n                            \"value\":\"%s\"\n                        }\n                    }\n                }\n            ]\n        }\n    },\n    \"aggs\":{\n        \"time\":{\n            \"date_histogram\":{\n                \"field\":\"timestamp\",\n                \"interval\":\"minute\"\n            },\n            \"aggs\":{\n                \"search-query_total_rate\":{\n                    \"sum\":{\n                        \"field\":\"metrics.search-query_total_rate\"\n                    }\n                },\n                \"indexing-index_total_rate\":{\n                    \"sum\":{\n                        \"field\":\"metrics.indexing-index_total_rate\"\n                    }\n                },\n                \"indices-search-query_avg_time\":{\n                    \"sum\":{\n                        \"field\":\"metrics.indices-search-query_avg_time\"\n                    }\n                }\n            }\n        },\n        \"avg_search-query_total_rate\":{\n            \"avg_bucket\":{\n                \"buckets_path\":\"time>search-query_total_rate\"\n            }\n        },\n        \"avg_indexing-index_total_rate\":{\n            \"avg_bucket\":{\n                \"buckets_path\":\"time>indexing-index_total_rate\"\n            }\n        },\n        \"avg_indices-search-query_avg_time\":{\n            \"avg_bucket\":{\n                \"buckets_path\":\"time>indices-search-query_avg_time\"\n            }\n        }\n    },\n    \"size\":0\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getIndexRealTimeStatisInfoByTemplateAndCluster",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"groupByTimeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timestamp\",\n        \"interval\": \"1m\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 1\n      },\n      \"aggs\": {\n        \"store-size_in_bytes-total\": {\n          \"sum\": {\n            \"field\": \"metrics.store-size_in_bytes-total\"\n          }\n        },\n        \"indexing-index_total_rate\": {\n          \"sum\": {\n            \"field\": \"metrics.indexing-index_total_rate\"\n          }\n        },\n        \"indexing-index_time_in_millis_rate\": {\n          \"sum\": {\n            \"field\": \"metrics.indexing-index_time_in_millis_rate\"\n          }\n        },\n        \"indexing-index_failed_rate\": {\n          \"sum\": {\n            \"field\": \"metrics.indexing-index_failed_rate\"\n          }\n        },\n        \"search-scroll_time_in_millis_rate\": {\n          \"sum\": {\n            \"field\": \"metrics.search-scroll_time_in_millis_rate\"\n          }\n        },\n        \"search-query_time_in_millis_rate\": {\n          \"sum\": {\n            \"field\": \"metrics.search-query_time_in_millis_rate\"\n          }\n        },\n        \"docs-count-total\": {\n          \"sum\": {\n            \"field\": \"metrics.docs-count-total\"\n          }\n        },\n        \"search-query_total_rate\": {\n          \"sum\": {\n            \"field\": \"metrics.search-query_total_rate\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getIndexStatsByTempalteId",
    "content": "{\n  \"size\": %d,\n  \"query\":{\n        \"bool\":{\n            \"must\":[\n                {\n                    \"range\":{\n                        \"timestamp\":{\n                            \"gte\": \"%d\",\n                            \"lte\": \"%d\"\n                        }\n                    }\n                },\n                {\n                    \"term\":{\n                        \"templateId\":{\n                            \"value\":%d\n                        }\n                    }\n                }\n            ]\n        }\n    },\n  \"sort\": [\n    {\n      \"timestamp\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getMaxInfoByRangeTimeAndTemplate",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"template\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hour_hist\": {\n      \"date_histogram\": {\n        \"field\": \"timestamp\",\n        \"interval\": \"30m\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 1\n      },\n      \"aggs\": {\n        \"minute_hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"interval\": \"1m\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 1\n          },\n          \"aggs\": {\n            \"minute_tps_sum\": {\n              \"sum\": {\n                \"field\": \"metrics.indexing-index_total_rate\"\n              }\n            },\n            \"minute_query_sum\": {\n              \"sum\": {\n                \"field\": \"metrics.search-query_time_in_millis_rate\"\n              }\n            },\n            \"minute_scroll_sum\": {\n              \"sum\": {\n                \"field\": \"metrics.search-scroll_time_in_millis_rate\"\n              }\n            }\n          }\n        },\n        \"hour_tps_avg\": {\n          \"percentiles_bucket\": {\n            \"buckets_path\": \"minute_hist>minute_tps_sum\",\n            \"percents\": [\n              50\n            ]\n          }\n        },\n        \"hour_query_avg\": {\n          \"percentiles_bucket\": {\n            \"buckets_path\": \"minute_hist>minute_query_sum\",\n            \"percents\": [\n              50\n            ]\n          }\n        },\n        \"hour_scroll_avg\": {\n          \"percentiles_bucket\": {\n            \"buckets_path\": \"minute_hist>minute_scroll_sum\",\n            \"percents\": [\n              50\n            ]\n          }\n        }\n      }\n    },\n    \"max_tps\": {\n      \"percentiles_bucket\": {\n        \"buckets_path\": \"hour_hist>hour_tps_avg[50.0]\",\n        \"percents\": [\n          %s\n        ]\n      }\n    },\n    \"max_query_time\": {\n      \"percentiles_bucket\": {\n        \"buckets_path\": \"hour_hist>hour_query_avg[50.0]\",\n        \"percents\": [\n          %s\n        ]\n      }\n    },\n    \"max_scroll_time\": {\n      \"percentiles_bucket\": {\n        \"buckets_path\": \"hour_hist>hour_scroll_avg[50.0]\",\n        \"percents\": [\n          %s\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getQueryRateByIndexDateRange",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"terms\": {\n            \"index\": [\n              %s\n            ]\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"groupByIndex\": {\n      \"terms\": {\n        \"field\": \"index\",\n        \"size\": 100\n      },\n      \"aggs\": {\n        \"day_bucket\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"interval\": \"1d\",\n            \"format\": \"yyyy-MM-dd\",\n            \"min_doc_count\": 1\n          },\n          \"aggs\": {\n            \"query_rate_avg\": {\n              \"avg\": {\n                \"field\": \"metrics.search-query_total_rate\"\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getSingleMetrics",
    "content": "{\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"term\": {\n            \"cluster\": \"%s\"\n          }\n        },\n        {\n          \"terms\": {\n            \"index\": %s\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\"metrics.%s\",\"index\"]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTemplateMaxIndexDoc",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"template\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n      \"indexList\": {\n        \"terms\": {\n          \"field\": \"index\",\n          \"size\": 1,\n          \"order\": {\n            \"indexDoc\": \"desc\"\n          }\n        },\n        \"aggs\": {\n          \"indexDoc\": {\n            \"max\": {\n              \"field\": \"metrics.docs-count-total\"\n            }\n          }\n        }\n      },\n      \"docMax\": {\n        \"max_bucket\": {\n          \"buckets_path\": \"indexList>indexDoc\"\n        }\n      }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTemplateMaxIndexSize",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"template\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n      \"indexList\": {\n        \"terms\": {\n          \"field\": \"index\",\n          \"size\": 1,\n          \"order\": {\n            \"indexSize\": \"desc\"\n          }\n        },\n        \"aggs\": {\n          \"indexSize\": {\n            \"max\": {\n              \"field\": \"metrics.store-size_in_bytes-total\"\n            }\n          }\n        }\n      },\n      \"sizeMax\": {\n        \"max_bucket\": {\n          \"buckets_path\": \"indexList>indexSize\"\n        }\n      }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTemplateTotalDocNuByLogicTemplateIdAndTimeRange",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": \"%d\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"minute_hist\": {\n      \"date_histogram\": {\n        \"field\": \"timestamp\",\n        \"interval\": \"1m\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 1\n      },\n      \"aggs\": {\n        \"minute_sum\": {\n          \"sum\": {\n            \"field\": \"metrics.docs-count-total\"\n          }\n        }\n      }\n    },\n    \"docSum\": {\n      \"max_bucket\": {\n        \"buckets_path\": \"minute_hist>minute_sum\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTemplateTotalDocNuByTimeRange",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"template\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"minute_hist\": {\n      \"date_histogram\": {\n        \"field\": \"timestamp\",\n        \"interval\": \"1m\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 1\n      },\n      \"aggs\": {\n        \"minute_sum\": {\n          \"sum\": {\n            \"field\": \"metrics.docs-count-total\"\n          }\n        }\n      }\n    },\n    \"docSum\": {\n      \"max_bucket\": {\n        \"buckets_path\": \"minute_hist>minute_sum\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTemplateTotalMaxTpsByTimeRange",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hour_hist\": {\n      \"date_histogram\": {\n        \"field\": \"timestamp\",\n        \"interval\": \"30m\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 1\n      },\n      \"aggs\": {\n        \"minute_hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"interval\": \"1m\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 1\n          },\n          \"aggs\": {\n            \"minute_tps_sum\": {\n              \"sum\": {\n                \"field\": \"metrics.indexing-index_total_rate\"\n              }\n            }\n          }\n        },\n        \"hour_tps_avg\": {\n          \"percentiles_bucket\": {\n            \"buckets_path\": \"minute_hist>minute_tps_sum\",\n            \"percents\": [\n              50\n            ]\n          }\n        }\n      }\n    },\n    \"tpsMax\": {\n      \"max_bucket\": {\n        \"buckets_path\": \"hour_hist>hour_tps_avg[50.0]\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTemplateTotalMaxTpsByTimeRangeNoPercent",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"minute_hist\": {\n      \"date_histogram\": {\n        \"field\": \"timestamp\",\n        \"interval\": \"1m\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 1\n      },\n      \"aggs\": {\n        \"minute_sum\": {\n          \"sum\": {\n            \"field\": \"metrics.indexing-index_total_rate\"\n          }\n        }\n      }\n    },\n    \"tpsMax\": {\n      \"max_bucket\": {\n        \"buckets_path\": \"minute_hist>minute_sum\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTemplateTotalSizeByLogicTemplateId",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"minute_hist\": {\n      \"date_histogram\": {\n        \"field\": \"timestamp\",\n        \"interval\": \"1m\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 1\n      },\n      \"aggs\": {\n        \"minute_sum\": {\n          \"sum\": {\n            \"field\": \"metrics.store-size_in_bytes-total\"\n          }\n        }\n      }\n    },\n    \"sizeSum\": {\n      \"max_bucket\": {\n        \"buckets_path\": \"minute_hist>minute_sum\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTemplateTotalSizeByTemplateId",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"templateId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"minute_hist\": {\n      \"date_histogram\": {\n        \"field\": \"timestamp\",\n        \"interval\": \"1m\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 1\n      },\n      \"aggs\": {\n        \"minute_sum\": {\n          \"sum\": {\n            \"field\": \"metrics.store-size_in_bytes-total\"\n          }\n        }\n      }\n    },\n    \"sizeSum\": {\n      \"max_bucket\": {\n        \"buckets_path\": \"minute_hist>minute_sum\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTemplateTotalSizeByTimeRange",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"template\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"minute_hist\": {\n      \"date_histogram\": {\n        \"field\": \"timestamp\",\n        \"interval\": \"1m\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 1\n      },\n      \"aggs\": {\n        \"minute_sum\": {\n          \"sum\": {\n            \"field\": \"metrics.store-size_in_bytes-total\"\n          }\n        }\n      }\n    },\n    \"sizeSum\": {\n      \"max_bucket\": {\n        \"buckets_path\": \"minute_hist>minute_sum\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTopNIndicesAggMetrics",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"terms\": {\n            \"index\": %s\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"index\",\n        \"size\": %d\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n            }\n          },\n          \"aggs\": {\n             %s\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexInfoEsDao/getTopNTemplateAggMetrics",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"terms\": {\n            \"logicTemplateId\": %s\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"logicTemplateId\",\n        \"size\": %d\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n            }\n          },\n          \"aggs\": {\n             %s\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexNodeInfoEsDao/getIndexToNodeStats",
    "content": "{\n  \"size\": %d,\n  \"query\":{\n        \"bool\":{\n            \"must\":[\n                {\n                    \"range\":{\n                        \"timestamp\":{\n                            \"gte\": \"%d\",\n                            \"lte\": \"%d\"\n                        }\n                    }\n                },\n                {\n                    \"term\":{\n                        \"template\":{\n                            \"value\":\"%s\"\n                        }\n                    }\n                },\n                {\n                  \"term\": {\n                    \"cluster\": {\n                      \"value\": \"%s\"\n                    }\n                  }\n                }\n            ]\n        }\n    },\n  \"sort\": [\n    {\n      \"timestamp\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIndexNodeInfoEsDao/getIndexToNodeStatsByTemplateId",
    "content": "{\n  \"size\": %d,\n  \"query\":{\n        \"bool\":{\n            \"must\":[\n                {\n                    \"range\":{\n                        \"timestamp\":{\n                            \"gte\": \"%d\",\n                            \"lte\": \"%d\"\n                        }\n                    }\n                },\n                {\n                    \"term\":{\n                        \"templateId\":{\n                            \"value\":%d\n                        }\n                    }\n                }\n            ]\n        }\n    },\n  \"sort\": [\n    {\n      \"timestamp\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsIngestInfoEsDao/getIngestFailCountByLogicIdAndTimeRange",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%d\",\n              \"lt\": \"%d\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"groupByTemplateId\": {\n      \"terms\": {\n        \"field\": \"templateId\",\n        \"size\": 10\n      },\n      \"aggs\": {\n        \"minute_buckets\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"interval\": \"1m\"\n          },\n          \"aggs\": {\n            \"sum_failed\": {\n              \"sum\": {\n                \"field\": \"metrics.ingest-failed\"\n              }\n            }\n          }\n        },\n        \"avg_count_templateId\": {\n          \"avg_bucket\": {\n            \"buckets_path\": \"minute_buckets>sum_failed\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/aggClusterAvgAndPercentiles",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": \"%s\",\n\t\t\t\t\t\t\t\"lte\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"percentiles\": {\n\t\t\t\"percentiles\": {\n\t\t\t\t\"field\": \"metrics.%s\",\n\t\t\t\t\"percents\": [55, 75, 95, 99]\n\t\t\t}\n\t\t},\n\t\t\"avg\": {\n\t\t\t\"avg\": {\n\t\t\t\t\"field\": \"metrics.%s\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/aggClusterAvgAndPercentilesForDiskFreeUsagePercent",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": \"%s\",\n\t\t\t\t\t\t\t\"lte\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"percentiles\": {\n\t\t\t\"percentiles\": {\n\t\t\t\t\"field\": \"metrics.fs-total-disk_free_percent\",\n\t\t\t\t\"percents\": [1, 5, 25, 45]\n\t\t\t}\n\t\t},\n\t\t\"avg\": {\n\t\t\t\"avg\": {\n\t\t\t\t\"field\": \"metrics.fs-total-disk_free_percent\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/aggClusterIndexingOrSearchTimeSum",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": \"%s\",\n\t\t\t\t\t\t\t\"lte\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"sum\": {\n\t\t\t\"sum\": {\n\t\t\t\t\"field\": \"metrics.%s\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/aggClusterLogicAvgAndPercentiles",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [\n\t\t\t   {\n            \t\t\"term\": {\n            \t\t\t\"cluster\": {\n            \t\t\t\t\"value\": \"%s\"\n            \t\t\t}\n            \t\t}\n            \t},\n            \t{\n\t\t\t\t\t\"terms\": {\n\t\t\t\t\t\t\"node\": %s\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": \"%s\",\n\t\t\t\t\t\t\t\"lte\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"percentiles\": {\n\t\t\t\"percentiles\": {\n\t\t\t\t\"field\": \"metrics.%s\",\n\t\t\t\t\"percents\": [55, 75, 95, 99]\n\t\t\t}\n\t\t},\n\t\t\"avg\": {\n\t\t\t\"avg\": {\n\t\t\t\t\"field\": \"metrics.%s\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/aggClusterLogicAvgAndPercentilesForDiskFreeUsagePercent",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [\n\t\t\t{\n                        \t\t\"term\": {\n                        \t\t\t\"cluster\": {\n                        \t\t\t\t\"value\": \"%s\"\n                        \t\t\t}\n                        \t\t}\n                        \t},{\n\t\t\t\t\t\"terms\": {\n                    \t\"node\": %s\n                    }\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": \"%s\",\n\t\t\t\t\t\t\t\"lte\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"percentiles\": {\n\t\t\t\"percentiles\": {\n\t\t\t\t\"field\": \"metrics.fs-total-disk_free_percent\",\n\t\t\t\t\"percents\": [1, 5, 25, 45]\n\t\t\t}\n\t\t},\n\t\t\"avg\": {\n\t\t\t\"avg\": {\n\t\t\t\t\"field\": \"metrics.fs-total-disk_free_percent\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/aggClusterLogicIndexingOrSearchTimeSum",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [\n\t\t\t    {\n                   \"term\": {\n                       \"cluster\": {\n                        \t\"value\": \"%s\"\n                        }\n                    }\n                },\n                {\n                    \"terms\": {\n                         \"node\": %s\n                    }\n                },\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": \"%s\",\n\t\t\t\t\t\t\t\"lte\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"sum\": {\n\t\t\t\"sum\": {\n\t\t\t\t\"field\": \"metrics.%s\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getAggClusterNodeInfoWithStep",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"node\",\n        \"size\": %d,\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0\n          },\n          \"aggs\": {\n            %s\n          }\n        },\n         %s\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getAggClusterPhyNodesInfo",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n\t\t\t\t\t\t\t\"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"hist\": {\n\t\t\t\"terms\": {\n\t\t\t\t\"field\": \"node\",\n\t\t\t\t\"size\": %d,\n\t\t\t\t\"collect_mode\": \"breadth_first\"\n\t\t\t},\n\t\t\t\"aggs\": {\n\t\t\t\t\"hist\": {\n\t\t\t\t\t\"date_histogram\": {\n\t\t\t\t\t\t\"field\": \"timestamp\",\n\t\t\t\t\t\t\"fixed_interval\": \"%s\",\n\t\t\t\t\t\t\"time_zone\": \"Asia/Shanghai\",\n\t\t\t\t\t\t\"min_doc_count\": 0\n\t\t\t\t\t},\n\t\t\t\t\t\"aggs\": {\n\t\t\t\t\t     %s\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getAggClusterPhySingleNodeInfo",
    "content": "{\n\t\"size\": 0,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"filter\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": \"%s\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"node\": \"%s\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n\t\t\t\t\t\t\t\"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"aggs\": {\n\t\t\"hist\": {\n\t\t\t\"date_histogram\": {\n\t\t\t\t\"field\": \"timestamp\",\n\t\t\t\t\"fixed_interval\": \"%s\",\n\t\t\t\t\"time_zone\": \"Asia/Shanghai\",\n\t\t\t\t\"min_doc_count\": 0\n\t\t\t},\n\t\t\t\"aggs\": {\n\t\t\t\t%s\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getAllClusterNodePhyStoreSize",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\":\"now-3m\",\n              \"lte\":\"now-2m\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getClusterCpuAvgInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"avg\": {\n      \"avg\": {\n        \"field\": \"metrics.%s\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getClusterIndexingLatency",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"max\": {\n      \"max\": {\n        \"field\": \"metrics.%s\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getClusterLogicRxTxInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n                \"value\": \"%s\"\n             }\n          }\n        },\n        {\n          \"terms\": {\n              \"node\": %s\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"sum\": {\n      \"sum\": {\n        \"field\": \"metrics.%s\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getClusterRxTxInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"sum\": {\n      \"sum\": {\n        \"field\": \"metrics.%s\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getClusterSearchLatency",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"max\": {\n      \"max\": {\n        \"field\": \"metrics.%s\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getFieldSumAndRangeFieldTotal",
    "content": "{\n    \"size\":0,\n    \"query\":{\n        \"bool\":{\n            \"filter\":[\n                {\n                    \"term\":{\n                        \"cluster\":\"%s\"\n                    }\n                },\n                {\n                    \"range\":{\n                        \"%s\":{\n                            \"gte\":\"%s\",\n                            \"lte\":\"%s\"\n                        }\n                    }\n                }\n            ]\n        }\n    },\n    \"aggs\":{\n        \"%s\":{\n            \"%s\":{\n                \"field\":\"%s\"\n            }\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getHasNodeMetricInfoTime",
    "content": "{\n    \"_source\": \"timestamp\",\n\t\"size\": 1,\n\t\"query\": {\n\t\t\"bool\": {\n\t\t\t\"must\": [{\n\t\t\t\t\t\"term\": {\n\t\t\t\t\t\t\"cluster\": {\n\t\t\t\t\t\t\t\"value\": \"%s\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\"timestamp\": {\n\t\t\t\t\t\t\t\"gte\": %d,\n                            \"lte\": %d\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"sort\": [\n\t  {\n\t    \"timestamp\": {\n\t      \"order\": \"desc\"\n\t    }\n\t  }\n\t]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getNodeFieldSumAndRangeFieldTotal",
    "content": "{\n    \"size\":0,\n    \"query\":{\n        \"bool\":{\n            \"filter\":[\n                {\n                    \"term\":{\n                        \"cluster\":\"%s\"\n                    }\n                },\n                {\n                    \"term\":{\n                         \"node\":\"%s\"\n                    }\n                },\n                {\n                    \"range\":{\n                        \"%s\":{\n                            \"gte\":\"%s\",\n                            \"lte\":\"%s\"\n                        }\n                    }\n                }\n            ]\n        }\n    },\n    \"aggs\":{\n        \"%s\":{\n            \"%s\":{\n                \"field\":\"%s\"\n            }\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/AriusStatsNodeInfoEsDao/getTopNNodeAggMetricsInfo",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"cluster\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"terms\": {\n            \"node\": %s\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"hist\": {\n      \"terms\": {\n        \"field\": \"node\",\n        \"size\": %d\n      },\n      \"aggs\": {\n        \"hist\": {\n          \"date_histogram\": {\n            \"field\": \"timestamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n            }\n          },\n          \"aggs\": {\n             %s\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslAnalyzeResultQpsEsDao/getMaxProjectIdTemplateQpsInfoByProjectIdTemplateMd5",
    "content": "{\n  \"size\":1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n           \"term\": {\n            \"ariusType\": {\n              \"value\": \"qps\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"searchCount\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslAnalyzeResultTypeEsDao/getDslAnalyzeResultByProjectId",
    "content": "{\n  \"from\": %d,\n  \"size\": 7,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n             \"ariusType\": {\n              \"value\": \"appid query\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslAnalyzeResultTypeEsDao/getDslAnalyzeResultByProjectIdAndRange",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"date\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"appid query\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslFieldUseEsDao/getFieldUseInfoByTemplateName",
    "content": "{\n  \"size\":2,\n  \"query\": {\n    \"term\": {\n      \"name\": {\n        \"value\": \"%s\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslFieldUseEsDao/getFieldUseListByTemplateName",
    "content": "{\n  \"size\":60,\n  \"query\": {\n    \"term\": {\n      \"name\": {\n        \"value\": \"%s\"\n      }\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslMetricsEsDao/getDslDetailMetricByProjectIdAndDslTemplateMd5",
    "content": "{\n    \"size\":0,\n    \"query\":{\n        \"bool\":{\n            \"must\":[\n                {\n                    \"term\":{\n                        \"projectId\":{\n                            \"value\":%d\n                        }\n                    }\n                },\n                {\n                    \"term\":{\n                        \"dslTemplateMd5\":{\n                            \"value\":\"%s\"\n                        }\n                    }\n                },\n                {\n                    \"range\":{\n                        \"timeStamp\":{\n                            \"gte\":%d,\n                            \"lte\":%d,\n                            \"format\":\"epoch_millis\"\n                        }\n                    }\n                }\n            ]\n        }\n    },\n    \"aggs\":{\n        \"groupByTimeStamp\":{\n            \"date_histogram\":{\n                \"field\":\"timeStamp\",\n                \"interval\":\"20m\",\n                \"time_zone\":\"Asia/Shanghai\",\n                \"min_doc_count\":1,\n                \"extended_bounds\":{\n                    \"min\":%d,\n                    \"max\":%d\n                }\n            },\n            \"aggs\":{\n                \"searchCount\":{\n                    \"avg\":{\n                        \"field\":\"searchCount\"\n                    }\n                },\n                \"totalCostAvg\":{\n                    \"avg\":{\n                        \"field\":\"totalCostAvg\"\n                    }\n                },\n                \"esCostAvg\":{\n                    \"avg\":{\n                        \"field\":\"esCostAvg\"\n                    }\n                },\n                \"totalShardsAvg\":{\n                    \"avg\":{\n                        \"field\":\"totalShardsAvg\"\n                    }\n                },\n                \"totalHitsAvg\":{\n                    \"avg\":{\n                        \"field\":\"totalHitsAvg\"\n                    }\n                },\n                \"failedShardsAvg\":{\n                    \"avg\":{\n                        \"field\":\"failedShardsAvg\"\n                    }\n                },\n                \"dslLenAvg\":{\n                    \"avg\":{\n                        \"field\":\"dslLenAvg\"\n                    }\n                },\n                \"responseLenAvg\":{\n                    \"avg\":{\n                        \"field\":\"responseLenAvg\"\n                    }\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslMetricsEsDao/getMaxProjectIdTemplateQpsInfoByProjectIdTemplateMd5",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"searchCount\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslMetricsEsDao/getNeariestDslMetricsByProjectIdTemplateMd5",
    "content": "{\n  \"size\":1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"ariusCreateTime\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslMetricsEsDao/getProjectIdTemplateMd5Info",
    "content": "{\n  \"size\":0,\n  \"aggs\": {\n    \"projectIdDslTemplateMd5\": {\n      \"terms\": {\n        \"field\": \"projectIdDslTemplateMd5\",\n        \"size\": 500000\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslMetricsEsDao/getTotalSearchByProjectIdDate",
    "content": "{\n  \"size\":0,\n  \"query\": {\n    \"term\": {\n      \"projectId\": {\n        \"value\": %d\n      }\n    }\n  },\n  \"aggs\": {\n    \"totalSearchCnt\": {\n      \"sum\": {\n        \"field\": \"searchCount\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslMetricsEsDao/queryTotalHitsByProjectIdDate",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": \"%s 00:00:00.000 +0800\",\n              \"lt\": \"%s 00:00:00.000 +0800\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/deleteExpiredDslTemplate",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"ariusModifyTime\": {\n              \"lt\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"enable\": {\n              \"value\": \"false\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"dslTemplateMd5\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getAllDslTemplatePoByProjectId",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"bool\": {\n            \"must_not\": [\n              {\n                \"term\": {\n                  \"version\": {\n                    \"value\": \"V1\"\n                  }\n                }\n              }\n            ]\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"dslTemplateMd5\",\n    \"totalCostAvg\",\n    \"slowDslThreshold\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getDslTemplateByCondition",
    "content": "{\n  \"from\": %d,\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": %s,\n      \"must_not\": [\n        {\n          \"prefix\": {\n            \"indices\": {\n              \"value\": \".\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n      {\n        \"%s\": {\n          \"order\": \"%s\"\n        }\n      }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getDslTemplateByProjectIdAndRange",
    "content": "{\n  \"size\":%d,\n  \"query\": {\n        \"bool\":{\n                \"must\":[\n                    {\n                        \"range\":{\n                            \"timeStamp\":{\n                                \"gte\":%d,\n                                \"lte\":%d\n                            }\n                        }\n                    },\n                    {\n                        \"term\":{\n                            \"projectId\":{\n                                \"value\":%d\n                            }\n                        }\n                    }\n                ]\n            }\n  },\n \"sort\": [\n   {\n     \"projectId\": {\n       \"order\": \"asc\"\n     }\n   },\n   {\n     \"searchCount\":{\n       \"order\": \"desc\"\n     }\n   }\n ],\n \"_source\": {\n     \"includes\": [\n       \"projectId\",\n       \"indiceSample\",\n       \"dsl\",\n       \"dslTemplate\",\n       \"dslTemplateMd5\",\n       \"searchCount\",\n       \"totalCostAvg\",\n       \"esCostAvg\",\n       \"beforeCostAvg\",\n       \"dslLenAvg\",\n       \"responseLenAvg\",\n       \"totalShardsAvg\",\n       \"totalHitsAvg\",\n       \"timeStamp\",\n       \"failedShardsAvg\"\n       \"queryLimit\"\n     ]\n   }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getDslTemplatesByDateRange",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"range\": {\n      \"ariusCreateTime\": {\n        \"gte\": \"now-%dd\"\n      }\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"dslTemplateMd5\",\n    \"totalCostAvg\",\n    \"slowDslThreshold\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getEarliestDslTemplate",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"ariusCreateTime\": {\n              \"lt\": \"now-1d\",\n              \"gt\": \"now-30d\"\n            }\n          }\n        },\n        {\n          \"bool\": {\n            \"must_not\": [\n              {\n                \"term\": {\n                  \"forceSetQueryLimit\": {\n                    \"value\": \"true\"\n                  }\n                }\n              },\n              {\n                \"term\": {\n                  \"enable\": {\n                    \"value\": \"false\"\n                  }\n                }\n              }\n            ]\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"projectId\": {\n        \"order\": \"asc\"\n      }\n    }\n  ],\n  \"_source\": [\n    \"projectId\",\n    \"dslTemplateMd5\",\n    \"indices\",\n    \"queryLimit\",\n    \"totalCostAvg\",\n    \"totalShardsAvg\",\n    \"totalHitsAvg\",\n    \"responseLenAvg\",\n    \"dslType\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getExpiredAndWillDeleteDslTemplate",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"ariusModifyTime\": {\n              \"lt\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"enable\": {\n              \"value\": false\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"dslTemplateMd5\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getIncreaseTemplateCountByProjectId",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"ariusCreateTime\": {\n              \"gte\": \"%s 00:00:00.000 +0800\",\n              \"lte\": \"%s 00:00:00.000 +0800\"\n            }\n          }\n        },\n        {\n          \"bool\": {\n            \"must_not\": [\n              {\n                \"term\": {\n                  \"version\": {\n                    \"value\": \"V1\"\n                  }\n                }\n              }\n            ]\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getLongTimeNotUseDslTemplate",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"flinkTime\": {\n              \"lt\": \"%s\"\n            }\n          }\n        },\n        {\n          \"bool\": {\n            \"must_not\": [\n              {\n                \"term\": {\n                  \"forceSetQueryLimit\": {\n                    \"value\": \"true\"\n                  }\n                }\n              },\n              {\n                \"term\": {\n                  \"enable\": {\n                    \"value\": \"false\"\n                  }\n                }\n              },\n              {\n                \"term\": {\n                  \"checkMode\": {\n                    \"value\": \"black\"\n                  }\n                }\n              }\n            ]\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"flinkTime\": {\n        \"order\": \"asc\"\n      }\n    }\n  ],\n  \"_source\": [\n    \"projectId\",\n    \"dslTemplateMd5\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getMissingAriusCreateTime",
    "content": "{\n  \"size\":%d,\n  \"query\": {\n    \"bool\": {\n      \"must_not\": [\n        {\n          \"exists\": {\n            \"field\": \"ariusCreateTime\"\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getNearestDslTemplate",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"ariusCreateTime\": {\n              \"gte\": \"now-1d\"\n            }\n          }\n        },\n        {\n          \"bool\": {\n            \"must_not\": [\n              {\n                \"term\": {\n                  \"forceSetQueryLimit\": {\n                    \"value\": \"true\"\n                  }\n                }\n              },\n              {\n                \"term\": {\n                  \"enable\": {\n                    \"value\": \"false\"\n                  }\n                }\n              },\n              {\n                \"term\": {\n                  \"checkMode\": {\n                    \"value\": \"black\"\n                  }\n                }\n              }\n            ]\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"projectId\": {\n        \"order\": \"asc\"\n      }\n    }\n  ],\n  \"_source\": [\n    \"totalCostAvg\",\n    \"totalShardsAvg\",\n    \"totalHitsAvg\",\n    \"responseLenAvg\",\n    \"projectId\",\n    \"dslTemplateMd5\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getNearestDslTemplateAccessable",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"ariusCreateTime\": {\n              \"gte\": \"now-1d\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"isFromUserConsole\": {\n              \"value\": \"false\"\n            }\n          }\n        },\n        {\n          \"bool\": {\n            \"must_not\": [\n              {\n                \"term\": {\n                  \"enable\": {\n                    \"value\": \"false\"\n                  }\n                }\n              },\n              {\n                \"term\": {\n                  \"version\": {\n                    \"value\": \"V1\"\n                  }\n                }\n              },\n              {\n                \"exists\": {\n                  \"field\": \"checkMode\"\n                }\n              }\n            ]\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"projectId\": {\n        \"order\": \"asc\"\n      }\n    }\n  ],\n  \"_source\": [\n    \"projectId\",\n    \"dslTemplateMd5\",\n    \"indices\",\n    \"dsl\",\n    \"ariusCreateTime\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getTemplateCountByProjectId",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"bool\": {\n            \"must_not\": [\n              {\n                \"term\": {\n                  \"version\": {\n                    \"value\": \"V1\"\n                  }\n                }\n              }\n            ]\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getTemplateMD5ByIndexName",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"version\": {\n              \"value\": \"V2\"\n            }\n          }\n        },\n        {\n          \"wildcard\": {\n            \"indices\": {\n              \"value\": \"%s*\"\n            }\n          }\n        },\n        {\n          \"bool\": {\n            \"must_not\": [\n              {\n                \"term\": {\n                  \"checkMode\": {\n                    \"value\": \"black\"\n                  }\n                }\n              }\n            ]\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"dslTemplateMd5\",\n    \"dsl\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getTemplateMD5ByIndexNameAndProjectId",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"version\": {\n              \"value\": \"V2\"\n            }\n          }\n        },\n        {\n          \"wildcard\": {\n            \"indices\": {\n              \"value\": \"%s*\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %s\n            }\n          }\n        },\n        {\n            \"bool\": {\n              \"must_not\": [\n                {\n                  \"term\": {\n                    \"checkMode\": {\n                      \"value\": \"black\"\n                    }\n                  }\n                }\n              ]\n            }\n         }\n      ]\n    }\n  },\n  \"_source\": [\n    \"dslTemplateMd5\",\n    \"dsl\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getTemplateMD5ByIndexNameAndProjectIdWithDayRange",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"version\": {\n              \"value\": \"V2\"\n            }\n          }\n        },\n        {\n          \"wildcard\": {\n            \"indices\": {\n              \"value\": \"%s*\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %s\n            }\n          }\n        },\n         {\n           \"range\": {\n             \"flinkTime\": {\n               \"gte\": \"now-%dd\"\n             }\n           }\n         },\n         {\n             \"bool\": {\n               \"must_not\": [\n                 {\n                   \"term\": {\n                     \"checkMode\": {\n                       \"value\": \"black\"\n                     }\n                   }\n                 }\n               ]\n             }\n          }\n      ]\n    }\n  },\n  \"_source\": [\n    \"dslTemplateMd5\",\n    \"dsl\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/getTemplateMD5ByIndexNameWithDayRange",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"version\": {\n              \"value\": \"V2\"\n            }\n          }\n        },\n        {\n          \"wildcard\": {\n            \"indices\": {\n              \"value\": \"%s*\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"flinkTime\": {\n              \"gte\": \"now-%dd\"\n            }\n          }\n        },\n        {\n           \"bool\": {\n             \"must_not\": [\n               {\n                 \"term\": {\n                   \"checkMode\": {\n                     \"value\": \"black\"\n                   }\n                 }\n               }\n             ]\n           }\n         }\n      ]\n    }\n  },\n  \"_source\": [\n    \"dslTemplateMd5\",\n    \"dsl\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/DslTemplateEsDao/handleScrollDslTemplates",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"ariusModifyTime\": {\n              \"gte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"version\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"dslTemplateMd5\",\n    \"queryLimit\",\n    \"checkMode\",\n    \"enable\",\n    \"esCostAvg\",\n    \"totalHitsAvg\",\n    \"totalShardsAvg\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayAppMetricsDao/getAggField",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_app\": {\n      \"terms\": {\n        \"field\": \"projectId\",\n        \"size\": 1000\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n                \"min\" : %d,\n                \"max\" : %d\n            }\n          },\n          \"aggs\": {\n            \"search_cost_avg\": {\n              \"avg\": {\n                \"field\": \"searchCost\"\n              }\n            },\n            \"total_cost_avg\": {\n              \"avg\": {\n                \"field\": \"totalCost\"\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayAppMetricsDao/getAggFieldByProjectId",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      },\n      \"aggs\": {\n        \"search_cost_avg\": {\n          \"avg\": {\n            \"field\": \"searchCost\"\n          }\n        },\n        \"total_cost_avg\": {\n          \"avg\": {\n            \"field\": \"totalCost\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayAppMetricsDao/getAggFieldCount",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_app\": {\n      \"terms\": {\n        \"field\": \"projectId\"\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n                \"min\" : %d,\n                \"max\" : %d\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayAppMetricsDao/getAggFieldCountByProjectId",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayDslMetricsDao/getDslCount",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_dsl\": {\n      \"terms\": {\n        \"field\": \"dslTemplateMd5\"\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n                \"min\" : %d,\n                \"max\" : %d\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayDslMetricsDao/getDslCountByFileld",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n        %s\n      ]\n    }\n  },\n  \"aggs\": {\n    \"%s\": {\n      \"terms\": {\n        \"field\": \"%s\",\n        \"size\": %d,\n        \"execution_hint\": \"map\",\n        \"order\": {\n          \"_count\": \"desc\"\n        },\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayDslMetricsDao/getDslCountByMd5",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"dslTemplateMd5\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayDslMetricsDao/getDslCountExtendedBoundsByFileld",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n        %s\n      ]\n    }\n  },\n  \"aggs\": {\n    \"%s\": {\n      \"terms\": {\n        \"field\": \"%s\",\n        \"min_doc_count\": 0,\n        \"order\": {\n          \"_count\": \"desc\"\n        },\n        \"size\": %d,\n        \"include\": %s\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\": {\n              \"min\": %d,\n              \"max\": %d\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayDslMetricsDao/getDslMd5ByProjectId",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_dsl\": {\n      \"terms\": {\n        \"field\": \"dslTemplateMd5\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayDslMetricsDao/getDslTotalCost",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_dsl\": {\n      \"terms\": {\n        \"field\": \"dslTemplateMd5\",\n        \"size\": 1000\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n                \"min\" : %d,\n                \"max\" : %d\n            }\n          },\n          \"aggs\": {\n            \"total_cost_avg\": {\n              \"avg\": {\n                \"field\": \"totalCost\"\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayDslMetricsDao/getDslTotalCostByMd5",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"dslTemplateMd5\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      },\n      \"aggs\": {\n        \"total_cost_avg\": {\n          \"avg\": {\n            \"field\": \"totalCost\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayDslMetricsDao/getHasMetricInfoTimeByField",
    "content": "{\n  \"_source\": \"timeStamp\",\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n        %s\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"timeStamp\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayDslMetricsDao/getTotalCostByField",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n        %s\n      ]\n    }\n  },\n  \"aggs\": {\n    \"%s\": {\n      \"terms\": {\n        \"field\": \"%s\",\n        \"size\": %d,\n        \"execution_hint\": \"map\",\n        \"order\": {\n          \"_count\": \"desc\"\n        },\n        \"collect_mode\": \"breadth_first\"\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\"\n          },\n          \"aggs\": {\n            \"%s\": {\n              \"%s\": {\n                \"field\": \"%s\"\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayDslMetricsDao/getTotalCostExtendedBoundsByField",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n        %s\n      ]\n    }\n  },\n  \"aggs\": {\n    \"%s\": {\n      \"terms\": {\n        \"field\": \"%s\",\n        \"min_doc_count\": 0,\n        \"order\": {\n          \"_count\": \"desc\"\n        },\n        \"size\": %d,\n        \"include\": %s\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"fixed_interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\": {\n              \"min\": %d,\n              \"max\": %d\n            }\n          },\n          \"aggs\": {\n            \"%s\": {\n              \"%s\": {\n                \"field\": \"%s\"\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayIndexMetricsDao/getAggSearch",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"queryRequest\": true\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_template\": {\n      \"terms\": {\n        \"field\": \"destTemplateName\"\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n                \"min\" : %d,\n                \"max\" : %d\n            }\n          },\n          \"aggs\": {\n            \"total_cost_avg\": {\n              \"avg\": {\n                \"field\": \"totalCost\"\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayIndexMetricsDao/getAggSearchByTemplateName",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"queryRequest\": true\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        },\n        {\n          \"term\": {\n            \"destTemplateName\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      },\n      \"aggs\": {\n        \"total_cost_avg\": {\n          \"avg\": {\n            \"field\": \"totalCost\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayIndexMetricsDao/getAggWrite",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"queryRequest\": false\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_template\": {\n      \"terms\": {\n        \"field\": \"destTemplateName\"\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n                \"min\" : %d,\n                \"max\" : %d\n            }\n          },\n          \"aggs\": {\n            \"total_cost_avg\": {\n              \"avg\": {\n                \"field\": \"totalCost\"\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayIndexMetricsDao/getAggWriteByTemplateName",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"queryRequest\": false\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        },\n        {\n          \"term\": {\n            \"destTemplateName\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      },\n      \"aggs\": {\n        \"total_cost_avg\": {\n          \"avg\": {\n            \"field\": \"totalCost\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/aggIndicesDslMd5ByRange",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"range\": {\n      \"timeStamp\": {\n        \"gte\": %d,\n        \"lt\": %d\n      }\n    }\n  },\n  \"aggs\": {\n    \"indices\": {\n      \"terms\": {\n        \"field\": \"indices\",\n        \"size\": 9999\n      },\n      \"aggs\": {\n        \"md5\": {\n          \"terms\": {\n            \"field\": \"dslTemplateMd5\",\n            \"size\": 0\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getAccessGatewayInfoByProjectIdDate",
    "content": "{\n  \"size\":0,\n  \"query\": {\n    \"term\": {\n      \"projectId\": {\n        \"value\": %d\n      }\n    }\n  },\n  \"aggs\": {\n    \"groupByGateway\": {\n      \"terms\": {\n        \"field\": \"gatewayNode\",\n        \"size\": 0\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getAccessIndexNameByProjectId",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"indices\": {\n      \"terms\": {\n        \"field\": \"indices\",\n        \"size\": 10000\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getCostInfoByProjectIdAndDate",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"type\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"totalCost\":{\n      \"percentiles\": {\n        \"field\": \"totalCost\",\n        \"percents\": [\n          50,\n          75,\n          95,\n          99\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getDslByIndexAndTemplateMD5",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"wildcard\": {\n            \"indices\": {\n              \"value\": \"%s*\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"dsl\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getErrorCntByTemplateName",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"wildcard\": {\n            \"indices\": {\n              \"value\": \"%s*\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"error\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getErrorSearchCountAndErrorDetailByProjectIdDate",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"error\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"groupByError\": {\n      \"terms\": {\n        \"field\": \"exceptionName\",\n        \"size\": 0\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getFailedDslTemplateCount",
    "content": "{\n  \"size\": 10,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": \"now-1h\",\n              \"lte\": \"now\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"searchType\": {\n              \"value\": \"dsl\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplate\": {\n              \"value\": \"FAILED\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"indices\",\n    \"dsl\",\n    \"requestId\",\n    \"ariusCreateTime\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getFailedDslTemplateSearchIndices",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"searchType\": {\n              \"value\": \"dsl\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplate\": {\n              \"value\": \"FAILED\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"indices\": {\n      \"terms\": {\n        \"field\": \"indices\",\n        \"size\": 0\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getFirstByProjectIdAndTemplateMd5",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"timeStamp\": {\n        \"order\": \"desc\"\n      }\n    }\n  ],\n  \"_source\": [\n    \"timeStamp\",\n    \"ariusCreateTime\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getGatewayErrorByCondition",
    "content": "{\n  \"from\": %d,\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": %s,\n      \"must_not\": [\n        {\n          \"wildcard\": {\n            \"uri\": {\n              \"value\": \"*/_bulk\"\n            }\n          }\n        },\n        {\n          \"prefix\": {\n            \"indices\": {\n              \"value\": \".\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"indiceSample\",\n    \"dsl\",\n    \"exceptionName\",\n    \"timeStamp\",\n    \"indices\",\n    \"uri\",\n    \"requestId\",\n    \"clusterName\"\n  ],\n  \"sort\": [\n      {\n        \"%s\": {\n          \"order\": \"%s\"\n        }\n      }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getGatewayErrorList",
    "content": "{\n  \"size\": 1000,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"error\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"indiceSample\",\n    \"dsl\",\n    \"exceptionName\",\n    \"timeStamp\"\n  ],\n  \"sort\": [\n    {\n      \"timeStamp\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getGatewayErrorListByProjectId",
    "content": "{\n  \"size\": 500,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"error\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"timeStamp\": {\n        \"order\": \"desc\"\n      }\n    }\n  ],\n  \"_source\": {\n    \"includes\": [\n      \"projectId\",\n      \"indiceSample\",\n      \"dsl\",\n      \"exceptionName\",\n      \"timeStamp\"\n    ]\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getGatewaySlowByCondition",
    "content": "{\n  \"from\": %d,\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": %s,\n      \"must_not\": [\n        {\n          \"prefix\": {\n            \"indices\": {\n              \"value\": \".\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"timeStamp\",\n    \"indices\",\n    \"dsl\",\n    \"esCost\",\n    \"totalCost\",\n    \"totalHits\",\n    \"totalShards\",\n    \"responseLen\",\n    \"isTimedOut\",\n    \"clusterName\"\n  ],\n  \"sort\": [\n      {\n        \"%s\": {\n          \"order\": \"%s\"\n        }\n      }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getGatewaySlowList",
    "content": "{\n  \"size\": 1000,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"totalCost\": {\n              \"gte\": 1000\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n         {\n           \"term\": {\n             \"ariusType\": {\n               \"value\": \"type\"\n             }\n           }\n         }\n      ]\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"timeStamp\",\n    \"indiceSample\",\n    \"dsl\",\n    \"esCost\",\n    \"totalCost\",\n    \"totalHits\",\n    \"totalShards\",\n    \"responseLen\",\n    \"isTimedOut\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getGatewaySlowListByProjectId",
    "content": "{\n  \"size\":500,\n  \"query\": {\n        \"bool\":{\n                \"must\":[\n                    {\n                        \"range\":{\n                            \"totalCost\":{\n                                \"gte\":1000\n                            }\n                        }\n                    },\n                    {\n                        \"range\":{\n                            \"timeStamp\":{\n                                \"gte\":%d,\n                                \"lte\":%d\n                            }\n                        }\n                    },\n                    {\n                        \"term\":{\n                            \"projectId\":{\n                                \"value\":%d\n                            }\n                        }\n                    },\n                      {\n                        \"term\": {\n                          \"ariusType\": {\n                            \"value\": \"type\"\n                          }\n                        }\n                      }\n                ]\n            }\n  },\n \"sort\": [\n   {\n     \"timeStamp\":{\n       \"order\": \"desc\"\n     }\n   }\n ],\n  \"_source\": {\n       \"includes\": [\n         \"projectId\",\n         \"indiceSample\",\n         \"dsl\",\n         \"exceptionName\",\n         \"timeStamp\",\n         \"esCost\",\n         \"totalCost\",\n         \"totalHits\",\n         \"totalShards\",\n         \"responseLen\",\n         \"isTimedOut\",\n         \"isTimeOut\"\n       ]\n     }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getIds",
    "content": "{\n  \"from\": 0,\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n        %s\n      ]\n    }\n  },\n  \"aggs\": {\n    \"result\": {\n      \"terms\": {\n        \"field\": \"projectId\",\n        \"size\": 10000\n      },\n      \"aggs\": {\n        \"template\": {\n          \"terms\": {\n            \"field\": \"dslTemplateMd5\",\n            \"size\": 10000,\n            \"min_doc_count\":%d\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getInfoByIds",
    "content": "{\n  \"from\": 0,\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        }\n        %s\n      ]\n    }\n  },\n  \"aggs\": {\n    \"template\": {\n      \"terms\": {\n        \"field\": \"dslTemplateMd5\",\n        \"size\": 2000\n      },\n      \"aggs\": {\n        \"minute_hist\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\":\"Asia/Shanghai\",\n            \"min_doc_count\":%d\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getOneDSLByProjectIdAndIndexName",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"exists\": {\n            \"field\": \"indices\"\n          }\n        },\n        {\n          \"term\": {\n            \"queryRequest\": \"true\"\n          }\n        },\n        {\n          \"term\": {\n            \"indices\": \"%s\"\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"timeStamp\": {\n        \"order\": \"desc\"\n      }\n    }\n  ],\n  \"_source\": \"dsl\"\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getPoByIndicesAndMd5",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"indices\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"selectFields\",\n    \"whereFields\",\n    \"groupByFields\",\n    \"orderByFields\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getQpsInfoByProjectIdAndDate",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n      \"bool\": {\n        \"must\": [\n          {\n            \"term\": {\n              \"projectId\": {\n                \"value\": %d\n              }\n            }\n          },\n          {\n            \"term\": {\n              \"ariusType\": {\n                \"value\": \"type\"\n              }\n            }\n          }\n        ]\n      }\n    },\n  \"aggs\": {\n    \"searchCount\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"1s\",\n        \"order\": {\n          \"_count\": \"desc\"\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getQueryLimitErrorMd5",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"term\": {\n      \"exceptionName\": {\n        \"value\": \"com.didi.arius.gateway.exception.DslRateLimitException\"\n      }\n    }\n  },\n  \"aggs\": {\n    \"projectId\": {\n      \"terms\": {\n        \"field\": \"projectId\",\n        \"size\": 0\n      },\n      \"aggs\": {\n        \"dslTemplateMd5\": {\n          \"terms\": {\n            \"field\": \"dslTemplateMd5\",\n            \"size\": 0\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getQueryRtByProjectId",
    "content": "{\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"match\": {\n            \"projectId\": {\n              \"query\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\",\n              \"format\": \"epoch_millis\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"size\": 0,\n  \"aggs\": {\n    \"queryByTimeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"1m\",\n        \"time_zone\": \"Etc/GMT-8\",\n        \"min_doc_count\": 1,\n        \"extended_bounds\": {\n          \"min\": 1584953823664,\n          \"max\": 1584957423664\n        }\n      },\n      \"aggs\": {\n        \"queryByProjectId\": {\n          \"terms\": {\n            \"field\": \"projectId\",\n            \"size\": 20,\n            \"order\": {\n              \"1.99\": \"desc\"\n            }\n          },\n          \"aggs\": {\n            \"1\": {\n              \"percentiles\": {\n                \"field\": \"totalCost\",\n                \"percents\": [\n                  99\n                ]\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getQueryTopNumInfoByProjectId",
    "content": "{\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"match\": {\n            \"projectId\": {\n              \"query\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": \"%d\",\n              \"lte\": \"%d\",\n              \"format\": \"epoch_millis\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"size\": %d,\n  \"sort\": [\n    {\n      \"totalCost\": {\n        \"order\": \"desc\"\n      }\n    }\n  ],\n  \"_source\": [\n    \"dslTemplate\",\n    \"indiceSample\",\n    \"timeStamp\",\n    \"dslTemplateMd5\",\n    \"totalCost\"\n    ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getRequestTypeByProjectId",
    "content": "{\n  \"size\":0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"wildcard\": {\n            \"indices\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"requestType\": {\n      \"terms\": {\n        \"field\": \"requestType\",\n        \"size\": 10\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getSearchCountByProjectId",
    "content": "{\n  \"size\":1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": \"%d\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getSearchRequestByIndexName",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"wildcard\": {\n            \"indices\": {\n              \"value\": \"%s*\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"type\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"md5s\": {\n      \"terms\": {\n        \"field\": \"dslTemplateMd5\",\n        \"size\": 1000\n      },\n      \"aggs\": {\n        \"samples\": {\n          \"top_hits\": {\n            \"size\": 1,\n            \"_source\": [\n              \"dsl\",\n              \"dslTemplateMd5\",\n              \"indices\",\n              \"typeName\",\n              \"totalCost\",\n              \"totalHits\",\n              \"searchType\"\n            ]\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getSearchTypesByLogicId",
    "content": "{\n  \"size\":0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"logicId\": {\n              \"value\": \"%d\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"typeNames\": {\n      \"terms\": {\n        \"field\": \"typeName\",\n        \"size\": 1000\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getSlowCntByTemplateName",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"wildcard\": {\n            \"indices\": {\n              \"value\": \"%s*\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"totalCost\": {\n              \"gte\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"type\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getTemplateMD5ByIndexName",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"wildcard\": {\n            \"indices\": {\n              \"value\": \"%s*\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"md5s\": {\n      \"terms\": {\n        \"field\": \"dslTemplateMd5\",\n        \"size\": 0\n      },\n      \"aggs\": {\n        \"samples\": {\n          \"top_hits\": {\n            \"size\": 1,\n            \"_source\": [\n              \"dsl\",\n              \"dslTemplateMd5\"\n            ]\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getTotalSearchCountByProjectIdAndDate",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"type\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/getWeekSearchCountByMd5",
    "content": "{\n  \"size\":1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": \"now-7d\",\n              \"lte\": \"now\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/matchIndices",
    "content": "{\n  \"size\":0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"indices\": {\n      \"terms\": {\n        \"field\": \"indices\",\n        \"size\": 0\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/queryErrorDslByProjectIdExceptionAndDate",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"exceptionName\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"error\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"top_dsltemplate\": {\n      \"terms\": {\n        \"field\": \"dslTemplateMd5\",\n        \"size\": 0\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/queryErrorDslDetailByProjectIdTemplateAndDate",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"exceptionName\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n         {\n           \"term\": {\n             \"ariusType\": {\n               \"value\": \"error\"\n             }\n           }\n         }\n      ]\n    }\n  },\n  \"_source\": [\n    \"indices\",\n    \"dsl\",\n    \"dslTemplate\",\n    \"dslTemplateMd5\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/queryMaxSearchQpsByProjectIdAndDslTemplate",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n         \"term\": {\n           \"ariusType\": {\n             \"value\": \"type\"\n           }\n         }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"searchCountPerSecond\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"1s\",\n        \"order\": {\n          \"_count\": \"desc\"\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/querySlowDslByProjectIdAndDate",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"totalCost\": {\n              \"gt\": 1000\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"slowDsl\": {\n      \"terms\": {\n        \"field\": \"dslTemplateMd5\",\n        \"size\": 0\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/querySlowDslCountAndDetailByByProjectIdAndDslTemplate",
    "content": "{\n  \"size\": 1,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"projectId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"totalCost\": {\n              \"gt\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"dslTemplateMd5\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n         {\n           \"term\": {\n             \"ariusType\": {\n               \"value\": \"type\"\n             }\n           }\n         }\n      ]\n    }\n  },\n  \"_source\": [\n    \"indices\",\n    \"dsl\",\n    \"dslTemplate\",\n    \"dslType\",\n    \"esCost\",\n    \"totalCost\",\n    \"totalShards\",\n    \"totalHits\",\n    \"responseLen\"\n    ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/scrollMulityTypeByShardNo",
    "content": "{\n  \"size\":%d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"exists\": {\n            \"field\": \"destIndexName\"\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\"projectId\",\"destIndexName\",\"requestId\"]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayJoinEsDao/scrollRequestLogByShardNo",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must_not\": [\n        {\n          \"term\": {\n            \"ariusType\": {\n              \"value\": \"meta\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"_source\": [\n    \"projectId\",\n    \"indices\",\n    \"requestId\",\n    \"destIndexName\"\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayNodeMetricsDao/getAggField",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"queryRequest\": true\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_field\": {\n      \"terms\": {\n        \"field\": \"gatewayNode\"\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n                \"min\" : %d,\n                \"max\" : %d\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayNodeMetricsDao/getAggFieldByIp",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"queryRequest\": true\n          }\n        },\n        {\n          \"term\": {\n            \"gatewayNode\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayNodeMetricsDao/getAggWriteAndGatewayNode",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"queryRequest\": false\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_field\": {\n      \"terms\": {\n        \"field\": \"gatewayNode\"\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n                \"min\" : %d,\n                \"max\" : %d\n            }\n          },\n          \"aggs\": {\n            \"dsl_len\": {\n              \"avg\": {\n                \"field\": \"dslLen\"\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayNodeMetricsDao/getAggWriteAndGatewayNodeByIp",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"queryRequest\": false\n          }\n        },\n        {\n          \"term\": {\n            \"gatewayNode\": \"%s\"\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      },\n      \"aggs\": {\n        \"dsl_len\": {\n          \"avg\": {\n            \"field\": \"dslLen\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayNodeMetricsDao/getClientNodeAggField",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": %s\n    }\n  },\n  \"aggs\": {\n    \"group_by_field\": {\n      \"terms\": {\n        \"field\": \"clientNode\"\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n                \"min\" : %d,\n                \"max\" : %d\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayNodeMetricsDao/getClientNodeAggFieldByIp",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": %s\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayNodeMetricsDao/getClientNodeAggWrite",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": %s\n    }\n  },\n  \"aggs\": {\n    \"group_by_field\": {\n      \"terms\": {\n        \"field\": \"clientNode\"\n      },\n      \"aggs\": {\n        \"group_by_timeStamp\": {\n          \"date_histogram\": {\n            \"field\": \"timeStamp\",\n            \"interval\": \"%s\",\n            \"time_zone\": \"Asia/Shanghai\",\n            \"min_doc_count\": 0,\n            \"extended_bounds\" : {\n                \"min\" : %d,\n                \"max\" : %d\n            }\n          },\n          \"aggs\": {\n            \"dsl_len\": {\n              \"avg\": {\n                \"field\": \"dslLen\"\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayNodeMetricsDao/getClientNodeAggWriteByIp",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": %s\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      },\n      \"aggs\": {\n        \"dsl_len\": {\n          \"avg\": {\n            \"field\": \"dslLen\"\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayNodeMetricsDao/getClientNodeByGatewayNode",
    "content": "{\n    \"size\": 0,\n    \"query\": {\n        \"bool\": {\n            \"filter\": %s\n        }\n    },\n    \"aggs\": {\n        \"group_by_field\": {\n            \"composite\": {\n                \"size\": 2000,\n                \"sources\": [\n                    {\n                        \"clusterName\": {\n                            \"terms\": {\n                                \"field\": \"clusterName\"\n                            }\n                        }\n                    },\n                    {\n                        \"clientNode\": {\n                            \"terms\": {\n                                \"field\": \"clientNode\"\n                            }\n                        }\n                    }\n                ]\n            }\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayOverviewMetricsDao/getCommonMetrics",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      },\n      \"aggs\": %s\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayOverviewMetricsDao/getReadCount",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"queryRequest\": true\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayOverviewMetricsDao/getSearchType",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"terms\": {\n            \"searchType\": [\"dsl\",\"sql\"]\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/GatewayOverviewMetricsDao/getWriteMetrics",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"queryRequest\": false\n          }\n        },\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"gte\": %d,\n              \"lte\": %d\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_timeStamp\": {\n      \"date_histogram\": {\n        \"field\": \"timeStamp\",\n        \"interval\": \"%s\",\n        \"time_zone\": \"Asia/Shanghai\",\n        \"min_doc_count\": 0,\n        \"extended_bounds\" : {\n            \"min\" : %d,\n            \"max\" : %d\n        }\n      },\n      \"aggs\": %s\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexCatESDAO/getAllCatIndexInfoByTerms",
    "content": "{\n  \"query\": {\n    \"bool\": {\n      \"must\": %s\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexCatESDAO/getAllCatIndexNameByClusters",
    "content": "{\n    \"size\": %d,\n    \"query\": {\n        \"bool\": {\n            \"filter\": [\n            {\n                \"term\": {\n                    \"deleteFlag\": false\n                }\n            },\n            {\n                \"terms\": {\n                    \"cluster\": %s\n                }\n            },\n            {\n                \"exists\": {\n                    \"field\": \"resourceId\"\n                }\n            }\n            ]\n        }\n    },\n    \"_source\":\n    [\n    \"index\",\n    \"cluster\",\n    \"resourceId\"\n    ]}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexCatESDAO/getCatIndexInfoByCondition",
    "content": "{\n  \"query\": {\n    \"bool\": {\n      \"must\": %s\n    }\n  },\n  \"sort\": [\n      {\n        \"%s\": {\n          \"order\": \"%s\"\n        }\n      }\n    ],\n  \"from\": %d,\n  \"size\": %d\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexCatESDAO/getPlatformCreateCatIndex",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"should\": [\n        {\n          \"term\": {\n            \"platformCreateFlag\": {\n              \"value\": true\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"deleteFlag\": {\n              \"value\": false\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexCatESDAO/getPlatformCreateCatIndexById",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"ids\": {\n            \"values\": %s\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexCatESDAO/getPlatformCreateCatIndexByIndexProject",
    "content": "{\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n      {\n          \"term\": {\n            \"deleteFlag\": false\n          }\n        },\n          {\n          \"term\": {\n            \"clusterLogic\": \"%s\"\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        }\n      ]\n    }\n  },\n   \"_source\": \"index\",\n   \"size\":%d\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexCatESDAO/getPlatformCreateCatIndexByIndexProjectAndFuzzyIndex",
    "content": "{\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n      {\n          \"term\": {\n            \"deleteFlag\": false\n          }\n        },\n          {\n          \"term\": {\n            \"clusterLogic\": \"%s\"\n          }\n        },\n        {\n          \"term\": {\n            \"projectId\": %d\n          }\n        },\n        {\n          \"wildcard\": {\n            \"index\": {\n              \"value\": \"%s*\"\n            }\n          }\n        }\n      ]\n    }\n  },\n   \"_source\": \"index\",\n   \"size\":%d\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexCatESDAO/getPlatformCreateCatIndexByIndexProjectAndFuzzyIndexAndClusterPhy",
    "content": "{\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n      {\n          \"term\": {\n            \"deleteFlag\": false\n          }\n        },\n          {\n          \"term\": {\n            \"cluster\": \"%s\"\n          }\n        },\n        {\n          \"wildcard\": {\n            \"index\": {\n              \"value\": \"%s*\"\n            }\n          }\n        }\n      ]\n    }\n  },\n   \"_source\": \"index\",\n   \"size\":%d\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexCatESDAO/getPlatformCreateCatIndexGroupByCluster",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"filter\": [\n        {\n          \"terms\": {\n            \"cluster\": %s\n          }\n        },\n        {\n          \"term\": {\n            \"deleteFlag\": {\n              \"value\": \"false\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"group_by_cluster\": {\n      \"terms\": {\n        \"field\": \"cluster\",\n        \"min_doc_count\": 1,\n        \"size\": %d,\n        \"include\":%s\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexCatESDAO/getTemplateIndicesHealth",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"wildcard\": {\n            \"index\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"timestamp\": {\n              \"gte\": \"now-3m\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"health\": {\n      \"terms\": {\n        \"field\": \"health\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexHit/getIndexForNormal",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"range\": {\n            \"timeStamp\": {\n              \"from\": %d,\n              \"to\": %d,\n              \"include_lower\": true,\n              \"include_upper\": false\n            }\n          }\n        },\n        {\n          \"bool\": {\n            \"must_not\": {\n              \"term\": {\n                \"dslType\": {\n                  \"value\": \"aggs\"\n                }\n              }\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"aggName\": {\n      \"terms\": {\n        \"field\": \"index\",\n        \"size\": 100000,\n        \"min_doc_count\": 1\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexHit/getIndicesForAggs",
    "content": "{\n  \"size\": 0,\n  \"query\": {\n    \"bool\": {\n      \"should\": [\n        {\n          \"term\": {\n            \"dslType\": {\n              \"value\": \"aggs\"\n            }\n          }\n        },\n        {\n          \"bool\": {\n            \"must_not\": {\n              \"term\": {\n                \"groupByFields\": {\n                  \"value\": \"\"\n                }\n              }\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"aggName\": {\n      \"terms\": {\n        \"field\": \"indices\",\n        \"size\": 100000,\n        \"min_doc_count\": 1\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexNameAccessCountEsDao/getIndexNameAccessByTemplate",
    "content": "{\n  \"size\":%d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"clusterName\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"templateName\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"date\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"indexName\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexNameAccessCountEsDao/getIndexNameAccessByTemplateId",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"templateId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"date\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"indexName\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexSizeEsDao/getIndexSizeByTemplateName",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"term\": {\n      \"templateName\": {\n        \"value\": \"%s\"\n      }\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexSizeEsDao/getYesterDayIndexSize",
    "content": "{\n  \"size\": 10000,\n  \"query\": {\n    \"term\": {\n      \"date\": {\n        \"value\": \"%s\"\n      }\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexTemplateLabelESDao/getLabelByLabelId",
    "content": "{\n  \"size\":%d,\n  \"query\": {\n    \"term\": {\n      \"labelId\": {\n        \"value\": \"%s\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexTemplateLabelESDao/getLabelByLogicTemplateId",
    "content": "{\n  \"size\":%d,\n  \"query\": {\n    \"term\": {\n      \"indexTemplateId\": {\n        \"value\": %d\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/IndexTemplateValueEsDao/listAll",
    "content": "{\n  \"size\":%d,\n  \"query\": {\n    \"match_all\":{}\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/ProjectIdTemplateAccessCountEsDao/getAccessProjectIdByTemplateName",
    "content": "{\n  \"size\":0,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"templateName\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"date\": {\n              \"gte\": \"now-7d\",\n              \"lte\": \"now\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"aggs\": {\n    \"projectId\": {\n      \"terms\": {\n        \"field\": \"projectId\",\n        \"size\": 1000\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/ProjectIdTemplateAccessCountEsDao/getAccessProjectIdInfoByLogicTemplateId",
    "content": "{\n  \"size\":%d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"date\": {\n              \"gte\": \"now-%dd\",\n              \"lte\": \"now\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/ProjectIdTemplateAccessCountEsDao/getAccessProjectIdInfoByLogicTemplateIdAndDateRange",
    "content": "{\n  \"size\":%d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"logicTemplateId\": {\n              \"value\": %d\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"date\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/ShardCatESDAO/getCatShardInfoByCondition",
    "content": "{\n  \"query\": {\n    \"bool\": {\n      \"must\": %s\n    }\n  },\n  \"sort\": [\n      {\n        \"%s\": {\n          \"order\": \"%s\"\n        }\n      }\n    ],\n  \"from\": %d,\n  \"size\": %d\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/ShardCatESDAO/shouldTermCell",
    "content": "{\n  \"bool\": {\n      \"should\": [%s]\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/TemplateAccessCountEsDao/getAllTemplateAccessByDateRange",
    "content": "{\n  \"size\":%d,\n  \"query\": {\n    \"range\": {\n      \"date\": {\n        \"gte\": \"%s\",\n        \"lte\": \"%s\"\n      }\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/TemplateAccessCountEsDao/getAllTemplateAccessByDateRangeAndCluster",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"clusterName\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"date\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/TemplateAccessCountEsDao/getAllTemplateAccessByTemplateDateRange",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"templateName\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"range\": {\n            \"date\": {\n              \"gte\": \"%s\",\n              \"lte\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/TemplateAccessCountEsDao/getAllTemplateAccessHistoryByTemplate",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        {\n          \"term\": {\n            \"clusterName\": {\n              \"value\": \"%s\"\n            }\n          }\n        },\n        {\n          \"term\": {\n            \"templateName\": {\n              \"value\": \"%s\"\n            }\n          }\n        }\n      ]\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/TemplateAccessCountEsDao/getAllTemplateAccessHistoryByTemplateId",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"term\": {\n      \"templateId\": {\n        \"value\": %d\n      }\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/TemplateAccessCountEsDao/getTemplateAccessLast7DayByTemplateId",
    "content": "{\n  \"size\": 7,\n  \"query\": {\n    \"term\": {\n      \"templateId\": {\n        \"value\": %d\n      }\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/dsl/TemplateAccessCountEsDao/getTemplateAccessLastNDayByLogicTemplateId",
    "content": "{\n  \"size\": %d,\n  \"query\": {\n    \"term\": {\n      \"logicTemplateId\": {\n        \"value\": %d\n      }\n    }\n  },\n  \"sort\": [\n    {\n      \"date\": {\n        \"order\": \"desc\"\n      }\n    }\n  ]\n}"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/AriusConfigInfo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.config.AriusConfigInfoDAO\">\n    <resultMap id=\"BaseResultMap\"\n               type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.config.AriusConfigInfoPO\">\n        <result column=\"id\" jdbcType=\"INTEGER\" property=\"id\"/>\n        <result column=\"value_group\" jdbcType=\"VARCHAR\" property=\"valueGroup\"/>\n        <result column=\"value_name\" jdbcType=\"VARCHAR\" property=\"valueName\"/>\n        <result column=\"value\" jdbcType=\"VARCHAR\" property=\"value\"/>\n        <result column=\"dimension\" jdbcType=\"INTEGER\" property=\"dimension\"/>\n        <result column=\"status\" jdbcType=\"INTEGER\" property=\"status\"/>\n        <result column=\"memo\" jdbcType=\"VARCHAR\" property=\"memo\"/>\n        <result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n        <result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n       id, `value_group`, value_name, `value`, dimension, status, memo, create_time, update_time\n    </sql>\n\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.config.AriusConfigInfoPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into arius_config_info (`value_group`, value_name, `value`, dimension, status, memo)\n        values (#{valueGroup}, #{valueName}, #{value}, #{dimension}, #{status}, #{memo})\n    </insert>\n\n    <update id=\"update\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.config.AriusConfigInfoPO\">\n        update arius_config_info\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"valueGroup != null\">,`value_group` = #{valueGroup}</if>\n            <if test=\"valueName != null\">,value_name = #{valueName}</if>\n            <if test=\"value != null\">,`value` = #{value}</if>\n            <if test=\"dimension != null\">,dimension = #{dimension}</if>\n            <if test=\"memo != null\">,memo = #{memo}</if>\n        </trim>\n        where id = #{id}\n    </update>\n\n\n    <update id=\"updateByIdAndStatus\" parameterType=\"map\">\n        update arius_config_info\n        set status = #{status}\n        where id = #{id}\n    </update>\n\n    <select id=\"listByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.config.AriusConfigInfoPO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from arius_config_info\n        where status != -1\n        <if test=\"id != null\">and id = #{id}</if>\n        <if test=\"valueGroup != null\">and `value_group` = #{valueGroup}</if>\n        <if test=\"valueName != null\">and value_name = #{valueName}</if>\n        <if test=\"dimension != null\">and dimension = #{dimension}</if>\n        <if test=\"status != null\">and status = #{status}</if>\n        order by id desc\n    </select>\n\n\n    <select id=\"getById\" parameterType=\"integer\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from arius_config_info\n        where status != -1 and id = #{id}\n    </select>\n\n    <select id=\"getByGroupAndName\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from arius_config_info\n        where value_group = #{valueGroup} and value_name = #{valueName} and status != -1\n        limit 1\n    </select>\n\n    <select id=\"listByGroup\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from arius_config_info\n        where value_group = #{valueGroup}\n    </select>\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/AriusMetaJobClusterDistributeDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.monitor.AriusMetaJobClusterDistributeDAO\">\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.monitor.AriusMetaJobClusterDistributePO\">\n        <result column=\"id\"             jdbcType=\"BIGINT\"       property=\"id\"/>\n        <result column=\"cluster_id\"     jdbcType=\"INTEGER\"      property=\"clusterId\"/>\n        <result column=\"cluster\"        jdbcType=\"VARCHAR\"      property=\"cluster\"/>\n        <result column=\"dataCentre\"     jdbcType=\"VARCHAR\"      property=\"dataCentre\"/>\n        <result column=\"monitor_host\"   jdbcType=\"VARCHAR\"      property=\"monitorHost\"/>\n        <result column=\"monitor_time\"   jdbcType=\"TIMESTAMP\"    property=\"monitorTime\"/>\n        <result column=\"gmt_create\"     jdbcType=\"TIMESTAMP\"    property=\"gmtCreate\"/>\n        <result column=\"gmt_modify\"     jdbcType=\"TIMESTAMP\"    property=\"gmtModify\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n    id, cluster_id, cluster, dataCentre, monitor_host, monitor_time, gmt_create, gmt_modify\n    </sql>\n\n    <select id=\"getAllTask\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from arius_meta_job_cluster_distribute\n    </select>\n\n    <select id=\"getAllTaskByDataCentre\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from arius_meta_job_cluster_distribute\n        where dataCentre = #{dataCentre}\n    </select>\n\n    <select id=\"getTaskByHost\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from arius_meta_job_cluster_distribute\n        where monitor_host = #{monitorHost} order by monitor_time desc limit #{size}\n    </select>\n\n    <update id=\"updateMonitorHost\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.monitor.AriusMetaJobClusterDistributePO\">\n        update arius_meta_job_cluster_distribute\n        set monitor_host = #{destMonitorHost}, monitor_time = #{monitorTime}\n        where id = #{id} and monitor_host = #{monitorHost}\n    </update>\n\n    <update id=\"updateMonitorTime\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.monitor.AriusMetaJobClusterDistributePO\">\n        update arius_meta_job_cluster_distribute\n        set monitor_time = #{monitorTime}\n        where id = #{id} and monitor_host = #{monitorHost}\n    </update>\n\n    <insert id=\"insertBatch\" parameterType=\"java.util.List\">\n        insert into arius_meta_job_cluster_distribute\n        (cluster_id)\n        values\n        <foreach collection=\"list\" index=\"index\" item=\"item\" separator=\",\">\n            (#{item.clusterId})\n        </foreach>\n    </insert>\n\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.monitor.AriusMetaJobClusterDistributePO\">\n        <selectKey resultType=\"java.lang.Long\" keyProperty=\"id\" order=\"AFTER\">\n            SELECT LAST_INSERT_ID()\n        </selectKey>\n        insert into arius_meta_job_cluster_distribute\n        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n            <if test=\"clusterId != null\">\n                cluster_id,\n            </if>\n            <if test=\"cluster != null\">\n                cluster,\n            </if>\n            <if test=\"dataCentre != null\">\n                dataCentre,\n            </if>\n            <if test=\"monitorHost != null\">\n                monitor_host,\n            </if>\n            <if test=\"monitorTime != null\">\n                monitor_time,\n            </if>\n            <if test=\"gmtCreate != null\">\n                gmt_create,\n            </if>\n            <if test=\"gmtModify != null\">\n                gmt_modify,\n            </if>\n        </trim>\n        <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\">\n            <if test=\"clusterId != null\">\n                #{clusterId,jdbcType=INTEGER},\n            </if>\n            <if test=\"cluster != null\">\n                #{cluster,jdbcType=CHAR},\n            </if>\n            <if test=\"dataCentre != null\">\n                #{dataCentre,jdbcType=CHAR},\n            </if>\n            <if test=\"monitorHost != null\">\n                #{monitorHost,jdbcType=CHAR},\n            </if>\n            <if test=\"monitorTime != null\">\n                #{monitorTime,jdbcType=DATE},\n            </if>\n            <if test=\"gmtCreate != null\">\n                #{gmtCreate,jdbcType=DATE},\n            </if>\n            <if test=\"gmtModify != null\">\n                #{gmtModify,jdbcType=DATE},\n            </if>\n        </trim>\n    </insert>\n\n    <delete id=\"deleteBatch\" parameterType=\"list\">\n        delete from arius_meta_job_cluster_distribute\n        where id in\n        <foreach collection=\"list\" item=\"id\" open=\"(\" separator=\",\" close=\")\">\n            #{id}\n        </foreach>\n    </delete>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ClusterRegion.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.region.ClusterRegionDAO\">\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterRegionPO\">\n        <result column=\"id\"                jdbcType=\"BIGINT\"        property=\"id\"/>\n        <result column=\"name\"              jdbcType=\"VARCHAR\"       property=\"name\"/>\n        <result column=\"logic_cluster_id\"  jdbcType=\"VARCHAR\"       property=\"logicClusterIds\"/>\n        <result column=\"phy_cluster_name\"  jdbcType=\"VARCHAR\"       property=\"phyClusterName\"/>\n        <result column=\"create_time\"       jdbcType=\"TIMESTAMP\"     property=\"createTime\"/>\n        <result column=\"update_time\"       jdbcType=\"TIMESTAMP\"     property=\"updateTime\"/>\n        <result column=\"config\"            jdbcType=\"VARCHAR\"       property=\"config\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n        id, name, logic_cluster_id, phy_cluster_name, create_time, update_time, config\n    </sql>\n\n    <insert id=\"insert\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterRegionPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into es_cluster_region\n        (name, logic_cluster_id,phy_cluster_name, config)\n        values\n        (#{name}, #{logicClusterIds}, #{phyClusterName}, #{config})\n    </insert>\n\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_region\n        where id = #{regionId} and delete_flag = 0\n    </select>\n\n    <select id=\"getByName\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_region\n        where name = #{regionName} and delete_flag = 0\n    </select>\n\n    <select id=\"getByLogicClusterId\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_region\n        where delete_flag = 0\n        and find_in_set(#{logicClusterId},logic_cluster_id)\n    </select>\n\n    <select id=\"getByPhyClusterName\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_region\n        where phy_cluster_name = #{phyClusterName} and delete_flag = 0\n    </select>\n\n    <select id=\"listByPhyClusterNames\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_region\n        where delete_flag = 0\n        <foreach collection=\"list\" separator=\",\" item=\"item\" close=\")\" open=\"and phy_cluster_name in (\">\n            #{item}\n        </foreach>\n    </select>\n\n    <select id=\"listAll\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_region\n        where delete_flag = 0\n    </select>\n\n    <select id=\"listBoundRegions\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_region\n        where delete_flag = 0 and logic_cluster_id != '-1'\n    </select>\n\n    <select id=\"listBoundRegionsByCondition\" resultMap=\"BaseResultMap\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterRegionPO\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_region\n        where delete_flag = 0\n        <if test=\"id != null\">and id = #{id}</if>\n        <if test=\"name != null\">and name = #{name}</if>\n        <if test=\"logicClusterIds != null\">and logic_cluster_id = #{logicClusterIds}</if>\n        <if test=\"phyClusterName != null\">and phy_cluster_name = #{phyClusterName}</if>\n    </select>\n\n    <update id=\"update\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterRegionPO\">\n        update es_cluster_region\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"name != null\">,name = #{name}</if>\n            <if test=\"logicClusterIds != null\">,logic_cluster_id = #{logicClusterIds}</if>\n            <if test=\"phyClusterName != null\">,phy_cluster_name = #{phyClusterName}</if>\n            <if test=\"config != null\">,config = #{config}</if>\n        </trim>\n        where id = #{id} and delete_flag = 0\n    </update>\n\n    <update id=\"delete\" parameterType=\"long\">\n        update es_cluster_region set delete_flag = 1\n        where id = #{regionId}\n    </update>\n\n    <update id=\"deleteByClusterPhyName\" parameterType=\"String\">\n        update es_cluster_region set delete_flag = 1\n        where phy_cluster_name = #{clusterPhyName}\n    </update>\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ESClusterConfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESClusterConfigDAO\">\n\n    <!-- 通用查询映射结果 -->\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.esconfig.ESConfigPO\">\n        <id column=\"id\"                 property=\"id\" />\n        <result column=\"cluster_id\"     property=\"clusterId\" />\n        <result column=\"type_name\"      property=\"typeName\" />\n        <result column=\"engin_name\"     property=\"enginName\" />\n        <result column=\"config_data\"    property=\"configData\" />\n        <result column=\"desc\"           property=\"desc\" />\n        <result column=\"version_tag\"    property=\"versionTag\" />\n        <result column=\"version_config\" property=\"versionConfig\" />\n        <result column=\"selected\"       property=\"selected\" />\n        <result column=\"create_time\"    property=\"createTime\" />\n        <result column=\"update_time\"    property=\"updateTime\" />\n        <result column=\"delete_flag\"    property=\"deleteFlag\" />\n    </resultMap>\n\n    <!-- 通用查询结果列 -->\n    <sql id=\"Base_Column_List\">\n        id, cluster_id, type_name, engin_name, config_data, `desc`, version_tag, version_config, selected,create_time,update_time, delete_flag\n    </sql>\n\n    <!-- 保存 Es配置信息 -->\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.esconfig.ESConfigPO\" useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into es_config\n        (cluster_id, type_name, engin_name, config_data, `desc`, version_tag, version_config, selected)\n        values\n        (#{clusterId}, #{typeName}, #{enginName}, #{configData}, #{desc}, #{versionTag}, #{versionConfig}, #{selected})\n    </insert>\n\n    <update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.esconfig.ESConfigPO\">\n        update es_config\n        <set>\n            <if test=\"clusterId != null\">cluster_id = #{clusterId},</if>\n            <if test=\"typeName != null\">type_name = #{typeName},</if>\n            <if test=\"enginName != null\">engin_name = #{enginName},</if>\n            <if test=\"configData != null\">config_data = #{configData},</if>\n            <if test=\"desc != null\">`desc` = #{desc},</if>\n            <if test=\"versionTag != null\">version_tag = #{versionTag},</if>\n            <if test=\"versionConfig != null\">version_config = #{versionConfig},</if>\n            <if test=\"selected != null\">selected = #{selected},</if>\n        </set>\n        where id = #{id}\n    </update>\n\n    <!-- 根据ID  查询详情 -->\n    <select id=\"getValidEsConfigById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_config\n        where id = #{id} and selected = 1 and delete_flag = 0;\n    </select>\n\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_config\n        where id = #{id} and delete_flag = 0;\n    </select>\n\n    <select id=\"getByClusterIdAndTypeAndEngin\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_config\n        where cluster_id = #{clusterId} and type_name = #{type} and engin_name = #{engin} and delete_flag = 0\n        and selected = 1\n    </select>\n\n    <select id=\"listByClusterId\" parameterType=\"Long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_config\n        where cluster_id = #{clusterId} and selected = 1 and delete_flag = 0 order by id desc\n    </select>\n\n    <delete id=\"delete\" parameterType=\"Long\">\n        update es_config\n        set delete_flag = 1, selected = 0\n        where id = #{id}\n    </delete>\n\n    <delete id=\"deleteByClusterIdAndTypeAndEngin\">\n        update es_config\n        set delete_flag = 1, selected = 0\n        where cluster_id = #{clusterId} and type_name = #{type} and engin_name = #{engin}\n    </delete>\n\n    <select id=\"getByClusterIdAndTypeAndEnginAndVersion\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_config\n        where cluster_id = #{clusterId} and type_name = #{type} and engin_name = #{engin} and version_config = #{version}\n        and delete_flag = 0\n    </select>\n\n    <update id=\"updateConfigValidById\" parameterType=\"Long\">\n        update es_config\n        set selected = 1\n        where id = #{id}\n    </update>\n    <insert id=\"insertSelective\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.esconfig.ESConfigPO\" useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into es_config\n        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\" >\n            <if test=\"clusterId != null\">\n                cluster_id,\n            </if>\n            <if test=\"typeName != null\">\n                type_name,\n            </if>\n            <if test=\"enginName != null\">\n                engin_name,\n            </if>\n            <if test=\"configData != null\">\n                config_data,\n            </if>\n            <if test=\"desc != null\">\n                `desc`,\n            </if>\n            version_config,\n        </trim>\n        <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\" >\n            <if test=\"clusterId != null\">\n                #{clusterId},\n            </if>\n            <if test=\"typeName != null\">\n                #{typeName},\n            </if>\n            <if test=\"enginName != null\">\n                #{enginName},\n            </if>\n            <if test=\"configData != null\">\n                #{configData},\n            </if>\n            <if test=\"desc != null\">\n                #{desc},\n            </if>\n                #{versionConfig},\n        </trim>\n    </insert>\n    \n    <select id=\"getClusterIdByConfigId\" resultType=\"java.lang.Integer\">\n        select cluster_id from es_config where id=#{id}\n    </select>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ESClusterRoleDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESClusterRoleDAO\">\n\n    <!-- 通用查询映射结果 -->\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRolePO\">\n        <id column=\"id\"                     jdbcType=\"BIGINT\"    property=\"id\" />\n        <result column=\"elastic_cluster_id\" jdbcType=\"BIGINT\"    property=\"elasticClusterId\" />\n        <result column=\"role_cluster_name\"  jdbcType=\"VARCHAR\"   property=\"roleClusterName\" />\n        <result column=\"role\"               jdbcType=\"VARCHAR\"   property=\"role\" />\n        <result column=\"pod_number\"         jdbcType=\"INTEGER\"   property=\"podNumber\" />\n        <result column=\"pid_count\"          jdbcType=\"INTEGER\"   property=\"pidCount\" />\n        <result column=\"machine_spec\"       jdbcType=\"VARCHAR\"   property=\"machineSpec\" />\n        <result column=\"es_version\"         jdbcType=\"VARCHAR\"   property=\"esVersion\" />\n        <result column=\"cfg_id\"             jdbcType=\"INTEGER\"   property=\"cfgId\" />\n        <result column=\"create_time\"        jdbcType=\"TIMESTAMP\" property=\"createTime\" />\n        <result column=\"update_time\"        jdbcType=\"TIMESTAMP\" property=\"updateTime\" />\n        <result column=\"delete_flag\"        jdbcType=\"TINYINT\"   property=\"deleteFlag\" />\n    </resultMap>\n\n    <!-- 通用查询结果列 -->\n    <sql id=\"Base_Column_List\">\n        id, elastic_cluster_id, role_cluster_name, `role`, pod_number, pid_count, machine_spec, es_version, cfg_id, create_time, update_time, delete_flag\n    </sql>\n\n    <!-- 保存 机器规格信息 -->\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRolePO\" useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\" >\n        insert into es_cluster_role_info\n        (elastic_cluster_id, role_cluster_name, `role`, pod_number, pid_count,\n            machine_spec, es_version, cfg_id, create_time, delete_flag)\n        values\n        (#{elasticClusterId},#{roleClusterName},#{role},#{podNumber},#{pidCount},\n            #{machineSpec}, #{esVersion}, #{cfgId}, now(), '0')\n    </insert>\n\n    <!-- 根据ID  查询详情 -->\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_info\n        where id = #{id}\n    </select>\n\n    <!-- 根据clusterId 和 roleClusterName  查询详情 -->\n    <select id=\"getByClusterIdAndClusterRole\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_info\n        where elastic_cluster_id = #{clusterId}  and role_cluster_name = #{roleClusterName} and delete_flag = '0'\n    </select>\n\n    <!-- 根据clusterId 和 role  查询详情 -->\n    <select id=\"getByClusterIdAndRole\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_info\n        where elastic_cluster_id = #{clusterId}  and  `role` = #{role} and delete_flag = '0'\n    </select>\n\n    <!-- 根据clusterId 和 role  查询详情 -->\n    <select id=\"listByClusterId\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_info\n        where elastic_cluster_id = #{clusterId}  and  delete_flag = 0 order by id\n    </select>\n\n    <!-- 根据clusterId 和 role  查询详情 -->\n    <select id=\"listByClusterIds\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_info\n        where elastic_cluster_id in\n        <foreach collection=\"list\" separator=\",\" item=\"item\" close=\")\" open=\"(\">\n            #{item}\n        </foreach>\n        and  delete_flag = 0 order by id;\n    </select>\n\n    <!-- 根据clusterId 和 role  修改podCount -->\n    <update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRolePO\" >\n        update es_cluster_role_info\n        set pod_number = #{podNumber}\n        where elastic_cluster_id = #{elasticClusterId} and `role` = #{role}\n    </update>\n\n    <!-- 根据clusterId 和 role  修改es版本 -->\n    <update id=\"updateVersionByClusterIdAndRole\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRolePO\" >\n        update es_cluster_role_info\n        set es_version = #{esVersion}\n        where elastic_cluster_id = #{elasticClusterId} and `role` = #{role}\n    </update>\n\n    <update id=\"delete\" parameterType=\"integer\">\n            update es_cluster_role_info\n            set delete_flag = 1\n            where elastic_cluster_id = #{clusterId}\n    </update>\n\n    <update id=\"deleteRoleClusterByCluterIdAndRole\">\n        update es_cluster_role_info\n        set delete_flag = 1\n        where elastic_cluster_id = #{clusterId} and `role` = #{role}\n    </update>\n    \n    <select id=\"countByClusterId\" resultType=\"int\">\n        select count(1) from es_cluster_role_info  where delete_flag = 0 and elastic_cluster_id = #{clusterId}\n    </select>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ESClusterRoleHostDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESClusterRoleHostDAO\">\n    <!-- 通用查询映射结果 -->\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRoleHostPO\">\n        <id column=\"id\"                  jdbcType=\"INTEGER\"   property=\"id\" />\n        <result column=\"role_cluster_id\" jdbcType=\"INTEGER\"   property=\"roleClusterId\" />\n        <result column=\"hostname\"        jdbcType=\"VARCHAR\"   property=\"hostname\" />\n        <result column=\"ip\"              jdbcType=\"VARCHAR\"   property=\"ip\" />\n        <result column=\"cluster\"         jdbcType=\"VARCHAR\"   property=\"cluster\" />\n        <result column=\"port\"            jdbcType=\"VARCHAR\"   property=\"port\"/>\n        <result column=\"status\"          jdbcType=\"TINYINT\"   property=\"status\"/>\n        <result column=\"role\"            jdbcType=\"TINYINT\"   property=\"role\"/>\n        <result column=\"rack\"            jdbcType=\"VARCHAR\"   property=\"rack\"/>\n        <result column=\"node_set\"        jdbcType=\"VARCHAR\"   property=\"nodeSet\"/>\n        <result column=\"create_time\"     jdbcType=\"TIMESTAMP\" property=\"createTime\" />\n        <result column=\"update_time\"     jdbcType=\"TIMESTAMP\" property=\"updateTime\" />\n        <result column=\"machine_spec\"    jdbcType=\"VARCHAR\"   property=\"machineSpec\"/>\n        <result column=\"region_id\"       jdbcType=\"INTEGER\"   property=\"regionId\" />\n        <result column=\"attributes\"      jdbcType=\"LONGVARCHAR\" property=\"attributes\" />\n    </resultMap>\n\n    <!-- 通用查询结果列 -->\n    <sql id=\"Base_Column_List\">\n        id, role_cluster_id, hostname,ip, cluster,`port`,`status`,`role`,rack,node_set,create_time, update_time, delete_flag, machine_spec\n        ,region_id, attributes\n    </sql>\n\n    <!-- 保存 角色对应主机 -->\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRoleHostPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into es_cluster_role_host_info\n        (role_cluster_id, hostname,ip, cluster,`role`, `port`, `status`, node_set, machine_spec, region_id, attributes)\n        values\n        (#{roleClusterId}, #{hostname}, #{ip}, #{cluster},#{role},#{port},#{status}, #{nodeSet}, #{machineSpec}, #{regionId}\n        ,#{attributes})\n    </insert>\n\n    <!-- 根据ID  查询详情 -->\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info where id = #{id} and delete_flag = 0;\n    </select>\n\n    <!-- 根据role_cluster_id  查询 -->\n    <select id=\"listHostNamesByRoleId\" parameterType=\"string\" resultType=\"string\">\n        select  hostname from es_cluster_role_host_info\n        where role_cluster_id = #{roleId} and  delete_flag = '0'\n    </select>\n\n    <!-- 根据role_cluster_id  查询 -->\n    <select id=\"listByRoleClusterId\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where role_cluster_id = #{roleClusterId} and delete_flag = '0'\n    </select>\n\n    <!-- 根据多个 role_cluster_id  查询 -->\n    <select id=\"listByRoleClusterIds\" parameterType=\"list\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where delete_flag = '0'\n        and role_cluster_id in\n        <foreach collection=\"list\" separator=\",\" item=\"item\" close=\");\" open=\"(\">\n            #{item}\n        </foreach>\n    </select>\n\n    <select id=\"listByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRoleHostPO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        <trim prefix=\"where\" prefixOverrides=\"and\">\n            <if test=\"id != null\">and id = #{id}</if>\n            <if test=\"roleClusterId != null\">and role_cluster_id = #{roleClusterId}</if>\n            <if test=\"hostname != null\">and `hostname` = #{hostname}</if>\n            <if test=\"ip != null\">and ip = #{ip}</if>\n            <if test=\"cluster != null\">and cluster = #{cluster}</if>\n            <if test=\"port != null\">and port = #{port}</if>\n            <if test=\"status != null\">and `status` = #{status}</if>\n            <if test=\"role != null\">and `role` = #{role}</if>\n            <if test=\"rack != null\">and rack = #{rack}</if>\n            <if test=\"nodeSet != null\">and node_set = #{nodeSet}</if>\n            <if test=\"machineSpec != null\">and machine_spec = #{machineSpec}</if>\n            <if test=\"regionId != null\">and region_id = #{regionId}</if>\n            <if test=\"attributes != null\">and attributes = #{attributes}</if>\n            and delete_flag = 0\n        </trim>\n    </select>\n\n    <select id=\"listByClusterAndNodeSets\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where cluster = #{cluster} and node_set in <foreach collection=\"nodeSets\" item=\"nodeSet\" open=\"(\" separator=\",\" close=\")\">#{nodeSet}</foreach>\n    </select>\n\n    <select id=\"listByCluster\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where cluster = #{cluster} and delete_flag = 0;\n    </select>\n\n    <update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRoleHostPO\">\n        update es_cluster_role_host_info\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"roleClusterId != null\">, role_cluster_id = #{roleClusterId}</if>\n            <if test=\"hostname != null\">, `hostname` = #{hostname}</if>\n            <if test=\"ip != null\">, ip = #{ip}</if>\n            <if test=\"cluster != null\">, cluster = #{cluster}</if>\n            <if test=\"port != null\">, `port` = #{port}</if>\n            <if test=\"role != null\">, `role` = #{role}</if>\n            <if test=\"status != null\">, `status` = #{status}</if>\n            <if test=\"rack != null\">, rack = #{rack}</if>\n            <if test=\"nodeSet != null\">, node_set = #{nodeSet}</if>\n            <if test=\"machineSpec != null\">, machine_spec = #{machineSpec}</if>\n            <if test=\"regionId != null\">, region_id = #{regionId}</if>\n            <if test=\"attributes != null\">, attributes = #{attributes}</if>\n        </trim>\n        where id = #{id} and delete_flag = 0;\n    </update>\n\n    <update id=\"updateRegionId\">\n        update es_cluster_role_host_info\n        set region_id = #{regionId}\n        where\n        <choose>\n            <when test=\"ids != null and ids.size > 0\">\n                id in <foreach collection=\"ids\" item=\"id\" open=\"(\" separator=\",\" close=\")\">#{id}</foreach>\n            </when>\n            <otherwise>\n                1=0\n            </otherwise>\n        </choose>\n    </update>\n\n\n\n    <!--  根据主机名称和角色id删除节点  -->\n    <update id=\"deleteByHostNameAndRoleId\">\n        update es_cluster_role_host_info\n        set delete_flag = 1\n        where role_cluster_id = #{roleId} and hostname in\n        <foreach collection=\"hostNames\" index=\"index\" item=\"item\" open=\"(\" close=\")\" separator=\",\">\n            #{item}\n        </foreach>\n    </update>\n\n    <update id=\"offlineByCluster\" parameterType=\"string\">\n        update es_cluster_role_host_info\n        set status = 2\n        where cluster = #{cluster} and status = 1\n    </update>\n\n    <select id=\"listOnlineNode\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where status = 1 and delete_flag = 0;\n    </select>\n\n    <update id=\"deleteByCluster\" parameterType=\"String\">\n        update es_cluster_role_host_info\n        set delete_flag = 1\n        where cluster = #{cluster}\n    </update>\n\n    <update id=\"restoreByHostNameAndRoleId\">\n        update es_cluster_role_host_info\n        set delete_flag = 0, status = 1\n        where hostname = #{hostname} and role_cluster_id = #{roleId} and delete_flag = 1;\n    </update>\n\n    <select id=\"listAll\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where delete_flag = 0;\n    </select>\n\n    <select id=\"listAllByRoleCode\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where role = #{roleCode} and delete_flag = 0;\n    </select>\n\n    <select id=\"getByHostName\" parameterType=\"String\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info where hostname = #{hostname} and delete_flag = 0;\n    </select>\n\n    <update id=\"delete\" parameterType=\"Long\">\n        update es_cluster_role_host_info\n        set delete_flag = 1\n        where id = #{id}\n    </update>\n    <delete id=\"deleteByIds\" parameterType=\"Long\">\n        update es_cluster_role_host_info\n        set delete_flag = 1\n        where id IN\n        <foreach collection=\"ids\" item=\"id\" open=\"(\" separator=\",\" close=\")\">\n            #{id}\n        </foreach>\n    \n    </delete>\n\n\n    <select id=\"getDeleteHostByHostNameAnRoleId\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info where hostname = #{hostname} and role_cluster_id = #{roleId} and delete_flag = 1;\n    </select>\n\n    <select id=\"getPodNumberByRoleId\" resultType=\"java.lang.Integer\">\n        select count(distinct `hostname`) from es_cluster_role_host_info where role_cluster_id = #{roleId} and delete_flag = 0;\n    </select>\n\n    <update id=\"updateHostValid\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESClusterRoleHostPO\">\n        update es_cluster_role_host_info\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"roleClusterId != null\">, role_cluster_id = #{roleClusterId}</if>\n            <if test=\"hostname != null\">, `hostname` = #{hostname}</if>\n            <if test=\"ip != null\">, ip = #{ip}</if>\n            <if test=\"cluster != null\">, cluster = #{cluster}</if>\n            <if test=\"port != null\">, `port` = #{port}</if>\n            <if test=\"role != null\">, `role` = #{role}</if>\n            <if test=\"status != null\">, `status` = #{status}</if>\n            <if test=\"rack != null\">, rack = #{rack}</if>\n            <if test=\"nodeSet != null\">, node_set = #{nodeSet}</if>\n            <if test=\"machineSpec != null\">, machine_spec = #{machineSpec}</if>\n            <if test=\"regionId != null\">, region_id = #{regionId}</if>\n            <if test=\"attributes != null\">, attributes = #{attributes}</if>\n             ,delete_flag = 0\n        </trim>\n        where id = #{id}\n    </update>\n\n    <!-- 根据role_cluster_id  查询 -->\n    <select id=\"listByRegionId\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where region_id = #{regionId} and delete_flag = '0'\n    </select>\n\n    <!-- 根据role_cluster_id  查询 -->\n    <select id=\"listDataNodeByCluster\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where cluster = #{cluster} and role = 1 and delete_flag = '0'\n    </select>\n    \n    <select id=\"listByIds\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where id IN\n        <foreach collection=\"ids\" item=\"id\" open=\"(\" separator=\",\" close=\")\">\n            #{id}\n        </foreach>\n        \n        \n        and delete_flag = '0'\n    </select>\n\n    <select id=\"listByClusters\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_role_host_info\n        where delete_flag = 0\n        <foreach collection=\"list\" separator=\",\" item=\"item\" close=\")\" open=\"and cluster in (\">\n            #{item}\n        </foreach>\n    </select>\n    \n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ESMachineNorms.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESMachineNormsDAO\">\n\n    <!-- 通用查询映射结果 -->\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESMachineNormsPO\">\n        <id column=\"id\" property=\"id\" />\n        <result column=\"role\" property=\"role\" />\n        <result column=\"spec\" property=\"spec\" />\n        <result column=\"create_time\" property=\"createTime\" />\n        <result column=\"delete_flag\" property=\"deleteFlag\" />\n    </resultMap>\n\n    <!-- 通用查询结果列 -->\n    <sql id=\"Base_Column_List\">\n        id, `role`, spec, create_time, delete_flag\n    </sql>\n\n    <select id=\"listMachineNorms\"  resultMap=\"BaseResultMap\" >\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_machine_norms\n        where delete_flag = '0'\n        order by id desc\n    </select>\n\n    <!-- 根据ID  查询详情 -->\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_machine_norms\n        where id = #{id}\n    </select>\n    <!-- 保存 机器规格信息 -->\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESMachineNormsPO\" useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into es_machine_norms\n        (`role`, spec, create_time, delete_flag)\n        values\n        (#{role},#{spec},now(),'0')\n    </insert>\n\n</mapper>\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ESPackage.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESPackageDAO\">\n\n    <!-- 通用查询映射结果 -->\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.espackage.ESPackagePO\">\n        <id column=\"id\"              property=\"id\" />\n        <result column=\"url\"         property=\"url\" />\n        <result column=\"es_version\"  property=\"esVersion\" />\n        <result column=\"creator\"     property=\"creator\" />\n        <result column=\"release\"     property=\"release\" />\n        <result column=\"manifest\"    property=\"manifest\" />\n        <result column=\"desc\"        property=\"desc\" />\n        <result column=\"create_time\" property=\"createTime\" />\n        <result column=\"update_time\" property=\"updateTime\" />\n        <result column=\"delete_flag\" property=\"deleteFlag\" />\n    </resultMap>\n\n    <!-- 通用查询结果列 -->\n    <sql id=\"Base_Column_List\">\n        id, url, es_version, creator,`release`, `desc`,manifest, create_time, update_time, delete_flag\n    </sql>\n\n    <!-- 查询全部程序包 -->\n    <select id=\"listAll\"  resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_package\n        where delete_flag = '0'\n        order by id desc\n    </select>\n\n    <!-- 保存 Es程序包 -->\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.espackage.ESPackagePO\" useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\" >\n        insert into es_package\n        ( url, es_version, creator, manifest,`desc`, create_time,  delete_flag)\n        values\n        (#{url},#{esVersion},#{creator},#{manifest},#{desc},now(),'0')\n    </insert>\n\n    <!-- 根据ID  修改程序包 -->\n    <update id=\"update\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.espackage.ESPackagePO\"  >\n        update es_package\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"url != null\">,`url` = #{url}</if>\n            <if test=\"esVersion != null\">,es_version = #{esVersion}</if>\n            <if test=\"manifest != null\">,manifest = #{manifest}</if>\n            <if test=\"desc != null\">,`desc` = #{desc}</if>\n            <if test=\"creator != null\">,creator = #{creator}</if>\n        </trim>\n        where id = #{id}  and delete_flag = '0'\n    </update>\n\n    <!-- 根据ID  查询详情 -->\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_package\n        where id = #{id} and delete_flag = '0'\n    </select>\n\n    <!-- 根据版本 和 类型 获取 程序包 -->\n    <select id=\"getByVersionAndType\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_package\n        where es_version = #{esVersion} and manifest = #{manifest} and delete_flag = '0'\n    </select>\n\n    <!-- 根据版本 和 类型  id取反  获取 程序包  -->\n    <select id=\"getByVersionAndManifestNotSelf\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_package\n        where es_version = #{esVersion} and manifest = #{manifest} and id != #{id} and delete_flag = '0'\n    </select>\n\n    <!-- 根据ID  删除程序包 -->\n    <update id=\"delete\"  >\n          update es_package  set delete_flag = '1'  where id = #{id}\n    </update>\n\n</mapper>\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ESPlugin.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.ecm.ESPluginDAO\">\n\n    <!-- 通用查询映射结果 -->\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin.PluginPO\">\n        <id column=\"id\" property=\"id\"/>\n        <result column=\"name\" property=\"name\"/>\n        <result column=\"physic_cluster_ids\" property=\"physicClusterId\"/>\n        <result column=\"version\" property=\"version\"/>\n        <result column=\"url\" property=\"url\"/>\n        <result column=\"md5\" property=\"md5\"/>\n        <result column=\"desc\" property=\"desc\"/>\n        <result column=\"p_default\" property=\"pDefault\"/>\n        <result column=\"creator\" property=\"creator\"/>\n        <result column=\"create_time\" property=\"createTime\"/>\n        <result column=\"delete_flag\" property=\"deleteFlag\"/>\n    </resultMap>\n\n    <!-- 通用查询结果列 -->\n    <sql id=\"Base_Column_List\">\n        id, `name`, physic_cluster_ids, version, url, md5, `desc`, p_default,creator, create_time, delete_flag\n    </sql>\n\n    <!-- 查询全部插件 -->\n    <select id=\"listAll\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_plugin\n        where delete_flag = 0\n        order by id desc\n    </select>\n\n    <!-- 查询所有系统默认的插件 -->\n    <select id=\"getAllSysDefaultPlugins\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_plugin\n        where delete_flag = 0 and p_default = 0\n    </select>\n\n    <!-- 保存 Es插件信息 -->\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin.PluginPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into es_plugin\n        (`name`, physic_cluster_ids, version, url, md5, `desc`, creator, p_default)\n        values (#{name}, #{physicClusterId}, #{version}, #{url}, #{md5}, #{desc}, #{creator}, #{pDefault})\n    </insert>\n\n    <!-- 批量保存 ES 插件信息 -->\n    <insert id=\"insertBatch\" parameterType=\"java.util.List\">\n        insert into es_plugin\n        (`name`, physic_cluster_ids, version, url, md5, `desc`, creator, p_default)\n        values\n        <foreach collection=\"list\" index=\"index\" item=\"item\" separator=\",\">\n            (#{item.name}, #{item.physicClusterId}, #{item.version}, #{item.url},\n            #{item.md5}, #{item.desc}, #{item.creator}, #{item.pDefault})\n        </foreach>\n    </insert>\n\n    <!-- 根据ID  查询详情 -->\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_plugin\n        where id = #{id} and delete_flag = 0\n    </select>\n\n    <!-- 根据name  查询详情 -->\n    <select id=\"getByNameAndVersion\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_plugin\n        where `name` = #{name} and version = #{version} and delete_flag = 0\n    </select>\n\n    <!-- 根据ID  修改插件 -->\n    <update id=\"update\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin.PluginPO\">\n        update es_plugin\n        <set>\n            <if test=\"name != null\">`name` = #{name},</if>\n            <if test=\"physicClusterId != null\">`physic_cluster_ids` = #{physicClusterId},</if>\n            <if test=\"version != null\">version = #{version},</if>\n            <if test=\"url != null\">url = #{url},</if>\n            <if test=\"md5 != null\">md5 = #{md5},</if>\n            <if test=\"desc != null\">`desc` = #{desc},</if>\n        </set>\n        where id = #{id} and delete_flag = 0\n    </update>\n\n    <update id=\"updateDesc\">\n        update es_plugin\n        set `desc` = #{desc}\n        where id = #{id} and delete_flag = 0\n    </update>\n\n    <!-- 查询默认 或者 某个集群名下上传的插件 列表 -->\n    <select id=\"listByPhyClusterId\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        FROM es_plugin WHERE\n        find_in_set(#{physicClusterId}, physic_cluster_ids)  and delete_flag = 0\n    </select>\n    <!--根据 ID list 查询插件 列表 -->\n    <select id=\"listByPlugIds\" parameterType=\"list\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        FROM es_plugin\n        <where>\n            <foreach collection=\"list\" item=\"id\" open=\"id IN (\" separator=\",\" close=\") AND \">\n                #{id}\n            </foreach>\n            delete_flag = 0\n        </where>\n    </select>\n    <!-- 根据ID  删除插件 -->\n    <update id=\"delete\">\n        update es_plugin\n        set delete_flag = 1\n        where id = #{id}\n    </update>\n\n    <!-- 根据插件 name version physicClusterId 查询插件信息，用于判重-->\n    <select id=\"getByNameAndVersionAndPhysicClusterId\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_plugin\n        where `name` = #{name} and version = #{version} and physic_cluster_ids = #{physicClusterId} and delete_flag = 0\n    </select>\n\n</mapper>\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ESUser.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n\t\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.project.ESUserDAO\">\n\t<resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO\">\n\t\t<!--@mbg.generated-->\n\t\t<!--@Table arius_es_user-->\n\t\t<id column=\"id\" jdbcType=\"BIGINT\" property=\"id\"/>\n\t\t<result column=\"index_exp\" jdbcType=\"LONGVARCHAR\" property=\"indexExp\"/>\n\t\t<result column=\"data_center\" jdbcType=\"VARCHAR\" property=\"dataCenter\"/>\n\t\t<result column=\"is_root\" jdbcType=\"TINYINT\" property=\"isRoot\"/>\n\t\t<result column=\"memo\" jdbcType=\"VARCHAR\" property=\"memo\"/>\n\t\t<result column=\"ip\" jdbcType=\"VARCHAR\" property=\"ip\"/>\n\t\t<result column=\"verify_code\" jdbcType=\"VARCHAR\" property=\"verifyCode\"/>\n\t\t<result column=\"is_active\" jdbcType=\"TINYINT\" property=\"isActive\"/>\n\t\t<result column=\"query_threshold\" jdbcType=\"INTEGER\" property=\"queryThreshold\"/>\n\t\t<result column=\"cluster\" jdbcType=\"VARCHAR\" property=\"cluster\"/>\n\t\t<result column=\"search_type\" jdbcType=\"TINYINT\" property=\"searchType\"/>\n\t\t<result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n\t\t<result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n\t\t<result column=\"project_id\" jdbcType=\"BIGINT\" property=\"projectId\"/>\n\t\t<result column=\"is_default_display\" jdbcType=\"TINYINT\" property=\"defaultDisplay\"/>\n\t</resultMap>\n\t\n\t<sql id=\"Base_Column_List\">\n\t\tid,\n\t\tproject_id,\n\t\tis_root,\n\t\tmemo,\n\t\tquery_threshold,\n\t\tverify_code,\n\t\tcluster,\n\t\tis_active,\n\t\tsearch_type,\n\t\tip,\n\t\tdata_center,\n\t\tindex_exp,\n\t\tcreate_time,\n\t\tupdate_time,\n\t\tis_default_display\n\t</sql>\n\t<select id=\"getDefaultESUserByProject\" resultType=\"com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser\">\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom arius_es_user\n\t\twhere is_active = 1\n\t\tand is_default_display=1 and project_id=#{projectId} limit  1\n\t</select>\n\t<select id=\"countDefaultESUserByProject\" resultType=\"java.lang.Integer\">\n\t\tselect count(id)\n\t\tfrom arius_es_user\n\t\twhere is_active = 1\n\t\t\tand is_default_display = 1\n\t\t\tand project_id = #{projectId}\n\t</select>\n\n\t\n\t<select id=\"listByCondition\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO\"\n\t        resultMap=\"BaseResultMap\">\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom arius_es_user\n\t\twhere is_active = 1\n\t\t<if test=\"id != null\">\n\t\t\tand id = #{id}\n\t\t</if>\n\t\t<if test=\"queryThreshold != null\">\n\t\t\tand query_threshold = #{queryThreshold}\n\t\t</if>\n\t\t<if test=\"cluster != null\">\n\t\t\tand cluster = #{cluster}\n\t\t</if>\n\t\t<if test=\"searchType != null\">\n\t\t\tand search_type = #{searchType}\n\t\t</if>\n\t\t<if test=\"isRoot != null\">\n\t\t\tand is_root = #{isRoot}\n\t\t</if>\n\t\t<if test=\"projectId != null\">\n\t\t\tand project_id = #{projectId}\n\t\t</if>\n\t\torder by id desc\n\t</select>\n\t<insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO\"\n\t        useGeneratedKeys=\"true\" keyColumn=\"id\" keyProperty=\"id\">\n\t\t<!--@mbg.generated-->\n\t\tinsert into arius_es_user\n\t\t( is_root, memo, query_threshold, verify_code, cluster,  search_type, data_center, project_id,\n\t\t is_default_display)\n\t\tvalues ( #{isRoot}, #{memo}, #{queryThreshold}, #{verifyCode}, #{cluster}, #{searchType},\n\t\t        #{dataCenter}, #{projectId}, #{defaultDisplay})\n\t</insert>\n\t\n\t<select id=\"getByESUser\" parameterType=\"integer\" resultMap=\"BaseResultMap\">\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom arius_es_user\n\t\twhere is_active = 1\n\t\t\tand id = #{esUser}\n\t</select>\n\t\n\t<select id=\"listByProjectId\" parameterType=\"integer\" resultMap=\"BaseResultMap\">\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom arius_es_user\n\t\twhere is_active = 1\n\t\t\tand project_id = #{projectId}\n\t</select>\n\t\n\t<select id=\"listByProjectIds\" parameterType=\"list\" resultMap=\"BaseResultMap\">\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom arius_es_user\n\t\twhere is_active = 1\n\t\t\tand\n\t\t\tproject_id in\n\t\t<foreach collection=\"projectIds\" item=\"projectId\" open=\"(\" separator=\",\" close=\")\">\n\t\t\t#{projectId}\n\t\t</foreach>\n\t</select>\n\t\n\t<update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO\">\n\t\tupdate arius_es_user\n\t\t<trim prefix=\"set\" prefixOverrides=\",\">\n\t\t\t<if test=\"projectId != null\">\n\t\t\t\t,project_id = #{projectId}\n\t\t\t</if>\n\t\t\t<if test=\"queryThreshold != null\">\n\t\t\t\t, query_threshold = #{queryThreshold}\n\t\t\t</if>\n\t\t\t<if test=\"verifyCode != null\">\n\t\t\t\t, verify_code = #{verifyCode}\n\t\t\t</if>\n\t\t\t<if test=\"cluster != null\">\n\t\t\t\t, cluster = #{cluster}\n\t\t\t</if>\n\t\t\t<if test=\"searchType != null\">\n\t\t\t\t, search_type = #{searchType}\n\t\t\t</if>\n\t\t\t<if test=\"memo != null\">\n\t\t\t\t, memo = #{memo}\n\t\t\t</if>\n\t\t\t<if test=\"isRoot != null\">\n\t\t\t\t, is_root = #{isRoot}\n\t\t\t</if>\n\t\t\t<if test=\"defaultDisplay != null\">\n\t\t\t\t, is_default_display = #{defaultDisplay}\n\t\t\t</if>\n\t\t</trim>\n\t\twhere id = #{id}\n\t\t\tand is_active = 1\n\t</update>\n\t\n\t<update id=\"delete\" parameterType=\"integer\">\n\t\tupdate arius_es_user\n\t\tset is_active = 0\n\t\twhere id = #{esUser}\n\t</update>\n\n\t\t<update id=\"deleteByProjectId\" parameterType=\"integer\">\n\t\tupdate arius_es_user\n\t\tset is_active = 0\n\t\twhere project_id = #{projectId}\n\t</update>\n\n\t<select id=\"countByProjectId\" resultType=\"java.lang.Integer\">\n\t\tselect count(project_id)\n\t\tfrom arius_es_user\n\t\twhere is_active = 1\n\t\t\tand project_id = #{projectId}\n\t</select>\n\t<select id=\"maxById\" resultType=\"java.lang.Integer\">\n\t\tselect max(id)\n\t\tfrom arius_es_user\n\t</select>\n\t\n\t<select id=\"getProjectIdBySearchType\" resultType=\"java.lang.Integer\">\n\t\tselect distinct project_id\n\t\tfrom arius_es_user\n\t\twhere search_type = #{searchType}\n\t\t\tand is_active = 1\n\t</select>\n\t\n\t<select id=\"countByProjectIdAndSearchType\" resultType=\"int\">\n\t\tselect count(id)\n\t\tfrom arius_es_user\n\t\twhere is_active = 1\n\t\t\tand search_type = #{searchType}\n\t\t\tand project_id = #{projectId}\n\t</select>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/EcmTask.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.task.EcmTaskDAO\">\n\n    <!-- 通用查询映射结果 -->\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskPO\">\n        <id column=\"id\"                     property=\"id\" />\n        <result column=\"title\"              property=\"title\" />\n        <result column=\"work_order_id\"      property=\"workOrderId\" />\n        <result column=\"physic_cluster_id\"  property=\"physicClusterId\" />\n        <result column=\"cluster_node_role\"  property=\"clusterNodeRole\" />\n        <result column=\"type\"               property=\"type\" />\n        <result column=\"order_type\"         property=\"orderType\" />\n        <result column=\"status\"             property=\"status\" />\n        <result column=\"handle_data\"        property=\"handleData\" />\n        <result column=\"creator\"            property=\"creator\" />\n        <result column=\"create_time\"        property=\"createTime\" />\n        <result column=\"update_time\"        property=\"updateTime\" />\n    </resultMap>\n\n    <!-- 通用查询结果列 -->\n    <sql id=\"Base_Column_List\">\n        id, title, work_order_id, physic_cluster_id,cluster_node_role,handle_data, `type`,order_type,status, creator,create_time,update_time\n    </sql>\n    <!-- 保存 工单任务信息 -->\n    <insert id=\"save\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskPO\" useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\" >\n        insert into es_work_order_task\n        (title, work_order_id, physic_cluster_id, cluster_node_role,`type`,order_type,status,handle_data,creator,create_time)\n        values\n        (#{title},#{workOrderId},#{physicClusterId},#{clusterNodeRole},#{type},#{orderType},#{status},#{handleData},#{creator},now())\n    </insert>\n\n    <!-- 根据ID  查询工单任务详情 -->\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_work_order_task\n        where id = #{id} and delete_flag = 0\n    </select>\n    <!-- 根据taskId 修改工单任务 -->\n    <update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskPO\" >\n        update es_work_order_task\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"title != null\">,`title` = #{title}</if>\n            <if test=\"physicClusterId != null\">,physic_cluster_id = #{physicClusterId}</if>\n            <if test=\"clusterNodeRole != null\">,cluster_node_role = #{clusterNodeRole}</if>\n            <if test=\"type != null\">,`type` = #{type}</if>\n            <if test=\"orderType != null\">,order_type = #{orderType}</if>\n            <if test=\"status != null\">,status = #{status}</if>\n            <if test=\"handleData != null\">,handle_data = #{handleData}</if>\n        </trim>\n        where id = #{id}\n    </update>\n\n    <!-- 根据taskId 只修改工单任务状态 -->\n    <update id=\"updateStatusById\" parameterType=\"map\" >\n        update es_work_order_task set  status = #{status} where id = #{id}\n    </update>\n\n    <!-- 根据物理集群ID 查询未执行的任务-->\n    <select id=\"listUndoEcmTaskByClusterId\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select  <include refid=\"Base_Column_List\"/>\n        from es_work_order_task\n        where physic_cluster_id = #{physicClusterId} and status in ('waiting','pause','running','failed') and  delete_flag = '0'\n    </select>\n\n    <!-- 查询  全部的工单任务-->\n    <select id=\"listAll\" parameterType=\"string\" resultType=\"list\" resultMap=\"BaseResultMap\">\n        select  <include refid=\"Base_Column_List\"/>\n        from es_work_order_task\n        where  delete_flag = 0 order by id  desc\n    </select>\n\n    <!-- 根据物理集群id，查询处于 waiting 或 running 状态的任务 -->\n    <select id=\"getUsefulEcmTaskByClusterId\" resultMap=\"BaseResultMap\">\n        select  <include refid=\"Base_Column_List\"/>\n        from es_work_order_task\n        where physic_cluster_id = #{physicClusterId} and status in ('waiting','pause','running') and  delete_flag = '0'\n    </select>\n\n    <select id=\"listRunningTasks\" parameterType=\"string\" resultType=\"list\" resultMap=\"BaseResultMap\">\n        select  <include refid=\"Base_Column_List\"/>\n        from es_work_order_task\n        where  delete_flag = 0 and status ='running'\n        order by id  desc\n    </select>\n</mapper>\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/EcmTaskDetail.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.task.EcmTaskDetailDAO\">\n\n    <!-- 通用查询映射结果 -->\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskDetailPO\">\n        <id column=\"id\" property=\"id\" />\n        <result column=\"work_order_task_id\" property=\"workOrderTaskId\" />\n        <result column=\"role\" property=\"role\" />\n        <result column=\"hostname\" property=\"hostname\" />\n        <result column=\"grp\" property=\"grp\" />\n        <result column=\"idx\" property=\"idx\" />\n        <result column=\"status\" property=\"status\" />\n        <result column=\"task_id\" property=\"taskId\" />\n        <result column=\"create_time\" property=\"createTime\" />\n        <result column=\"update_time\" property=\"updateTime\" />\n    </resultMap>\n\n    <!-- 通用查询结果列 -->\n    <sql id=\"Base_Column_List\">\n        id, work_order_task_id, `role`, hostname, grp, idx, status, task_id, create_time, update_time\n    </sql>\n\n    <!-- replace工单任务信息 -->\n    <insert id=\"replace\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskDetailPO\" useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\" >\n        replace into es_work_order_task_detail\n        (work_order_task_id, `role`, hostname, grp, idx, status, task_id, delete_flag)\n        values\n        (#{workOrderTaskId}, #{role}, #{hostname}, #{grp}, #{idx}, #{status}, #{taskId}, '0')\n    </insert>\n\n    <!-- 保存 工单任务信息 -->\n    <insert id=\"save\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskDetailPO\" useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\" >\n        insert into es_work_order_task_detail\n        (work_order_task_id, `role`, hostname, grp, idx, status, task_id)\n        values\n        (#{workOrderTaskId},#{role},#{hostname},#{grp},#{idx},#{status},#{taskId})\n    </insert>\n\n    <delete id=\"deleteEcmTaskDetailsByTaskOrder\">\n        update es_work_order_task_detail\n        set delete_flag = '1'\n        where work_order_task_id = #{workOrderTaskId}\n    </delete>\n\n    <!-- 根据工单任务ID  查询工单任务详情 -->\n    <select id=\"listByWorkOrderTaskId\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_work_order_task_detail\n        where work_order_task_id = #{workOrderTaskId} and delete_flag = '0'\n    </select>\n\n    <!-- 根据工单任务ID、hostname 修改状态 -->\n    <update id=\"updateStatus\" parameterType=\"map\" >\n        update es_work_order_task_detail\n        set status = #{status}\n        where work_order_task_id = #{workOrderTaskId} and hostname = #{hostname} and  delete_flag = '0'\n    </update>\n\n    <!-- 根据工单任务ID、role获取全部hostnames -->\n    <select id=\"listByTaskIdAndRoleAndWorkOrderTaskId\" parameterType=\"map\" resultType=\"list\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_work_order_task_detail\n        where work_order_task_id = #{workOrderTaskId}  and `role` = #{role} and task_id =#{taskId} and delete_flag = 0\n    </select>\n    <!-- 根据ID  查询工单任务详情 -->\n    <select id=\"getById\"\n            parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_work_order_task_detail\n        where id = #{taskDetailId} and delete_flag = '0'\n    </select>\n\n    <!-- 根据工单任务ID、role 修改 taskId -->\n    <update id=\"updateTaskIdByRoleAndWorkOrderTaskId\" parameterType=\"map\">\n        update es_work_order_task_detail\n        set task_id = #{taskId}\n        where work_order_task_id = #{workOrderTaskId} and `role` = #{role} and  delete_flag = '0'\n    </update>\n\n    <update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskDetailPO\">\n        update es_work_order_task_detail\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"workOrderTaskId != null\">, work_order_task_id = #{workOrderTaskId}</if>\n            <if test=\"role != null\">,role = #{role}</if>\n            <if test=\"hostname != null\">,hostname = #{hostname}</if>\n            <if test=\"grp != null\">,grp = #{grp}</if>\n            <if test=\"idx != null\">,idx = #{idx}</if>\n            <if test=\"status != null\">,status = #{status}</if>\n            <if test=\"taskId != null\">,task_id = #{taskId}</if>\n        </trim>\n        where id = #{id}\n    </update>\n\n    <select id=\"getByWorkOderIdAndHostName\" parameterType=\"map\" resultType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.task.ecm.EcmTaskDetailPO\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_work_order_task_detail\n        where work_order_task_id = #{workOrderTaskId}  and hostname = #{hostname} and delete_flag = 0\n    </select>\n</mapper>\n"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/GatewayCluster.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.gateway.GatewayClusterDAO\">\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayClusterPO\">\n        <result column=\"id\" jdbcType=\"BIGINT\" property=\"id\" />\n        <result column=\"cluster_name\" jdbcType=\"VARCHAR\" property=\"clusterName\" />\n        <result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\" />\n        <result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\" />\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n        id, cluster_name, create_time, update_time\n    </sql>\n\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayClusterPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert ignore into gateway_cluster_info\n        (cluster_name)\n        values\n        (#{clusterName})\n    </insert>\n\n    <select id=\"getByClusterName\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from gateway_cluster_info\n        where cluster_name = #{clusterName}\n    </select>\n\n    <select id=\"listAll\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from gateway_cluster_info\n    </select>\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/GatewayNode.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.gateway.GatewayClusterNodeDAO\">\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayClusterNodePO\">\n        <result column=\"id\" jdbcType=\"BIGINT\" property=\"id\"/>\n        <result column=\"cluster_name\" jdbcType=\"VARCHAR\" property=\"clusterName\"/>\n        <result column=\"host_name\" jdbcType=\"VARCHAR\" property=\"hostName\"/>\n        <result column=\"port\" jdbcType=\"INTEGER\" property=\"port\"/>\n        <result column=\"heartbeat_time\" jdbcType=\"TIMESTAMP\" property=\"heartbeatTime\"/>\n        <result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n        <result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n        id, cluster_name, host_name, port, heartbeat_time, create_time, update_time\n    </sql>\n\n    <insert id=\"recordGatewayNode\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayClusterNodePO\"\n            keyColumn=\"id\">\n        insert into gateway_cluster_node_info\n            (cluster_name, host_name, port, heartbeat_time)\n        values (#{clusterName}, #{hostName}, #{port}, #{heartbeatTime}) ON DUPLICATE KEY\n        UPDATE heartbeat_time= #{heartbeatTime}\n    </insert>\n\n    <select id=\"aliveCountByClusterNameAndTime\" parameterType=\"map\" resultType=\"integer\">\n        select count(*)\n        from gateway_cluster_node_info\n        where cluster_name = #{clusterName} AND heartbeat_time > #{time}\n    </select>\n\n    <select id=\"listAliveNodeByClusterNameAndTime\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from gateway_cluster_node_info\n        where cluster_name = #{clusterName} AND heartbeat_time > #{time}\n    </select>\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/IndexTemplateAlias.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateAliasDAO\">\n    <resultMap id=\"BaseResultMap\"\n               type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateAliasPO\">\n        <result column=\"id\" jdbcType=\"INTEGER\" property=\"id\"/>\n        <result column=\"index_template_id\" jdbcType=\"INTEGER\" property=\"logicId\"/>\n        <result column=\"name\" jdbcType=\"VARCHAR\" property=\"name\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n       id, index_template_id, `name`\n    </sql>\n\n    <select id=\"listAll\" resultMap=\"BaseResultMap\" parameterType=\"int\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_alias\n    </select>\n\n    <select id=\"listByTemplateId\" resultMap=\"BaseResultMap\" parameterType=\"int\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_alias\n        where index_template_id = #{logicId}\n    </select>\n\n    <insert id=\"insert\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateAliasPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into index_template_alias\n        (index_template_id, `name`)\n        values\n        (#{logicId}, #{name})\n    </insert>\n\n    <delete id=\"delete\" parameterType=\"map\">\n        delete from index_template_alias\n        where index_template_id = #{logicId} and `name` = #{name}\n    </delete>\n\n    <insert id=\"insertBatch\" parameterType=\"java.util.List\" useGeneratedKeys=\"true\" keyColumn=\"id\" keyProperty=\"id\">\n        insert into index_template_alias (index_template_id, `name`) values\n        <foreach collection=\"list\" index=\"index\" item=\"item\" separator=\",\">(#{item.logicId}, #{item.name})</foreach>\n    </insert>\n\n    <delete id=\"deleteBatch\" parameterType=\"java.util.List\">delete from index_template_alias where `name` = #{name}\n        <foreach collection=\"logicIds\" item=\"item\" separator=\",\" open=\"and index_template_id IN (\" close=\")\">#{item}\n        </foreach>\n    </delete>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/IndexTemplateConfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateConfigDAO\">\n    <resultMap id=\"BaseResultMap\"\n               type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateConfigPO\">\n        <result column=\"id\" jdbcType=\"BIGINT\" property=\"id\"/>\n        <result column=\"logic_id\" jdbcType=\"INTEGER\" property=\"logicId\"/>\n        <result column=\"is_source_separated\" jdbcType=\"TINYINT\" property=\"isSourceSeparated\"/>\n        <result column=\"adjust_rack_tps_factor\" jdbcType=\"DECIMAL\" property=\"adjustTpsFactor\"/>\n        <result column=\"adjust_rack_shard_factor\" jdbcType=\"DECIMAL\" property=\"adjustShardFactor\"/>\n        <result column=\"dynamic_limit_enable\" jdbcType=\"TINYINT\" property=\"dynamicLimitEnable\"/>\n        <result column=\"mapping_improve_enable\" jdbcType=\"TINYINT\" property=\"mappingImproveEnable\"/>\n        <result column=\"pre_create_flags\" jdbcType=\"TINYINT\" property=\"preCreateFlags\" />\n        <result column=\"disable_source_flags\" jdbcType=\"TINYINT\" property=\"disableSourceFlags\" />\n        <result column=\"disable_index_rollover\" jdbcType=\"TINYINT\" property=\"disableIndexRollover\" />\n        <result column=\"shard_num\" jdbcType=\"INTEGER\" property=\"shardNum\" />\n        <result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n        <result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n        id, logic_id, is_source_separated, adjust_rack_tps_factor, adjust_rack_shard_factor, dynamic_limit_enable,\n    mapping_improve_enable, pre_create_flags, disable_source_flags, disable_index_rollover, shard_num, create_time, update_time\n    </sql>\n\n    <select id=\"listByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateConfigPO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_config\n        <trim prefix=\"where\" prefixOverrides=\"and\">\n            <if test=\"id != null\">and id = #{id}</if>\n            <if test=\"logicId != null\">and logic_id = #{logicId}</if>\n            <if test=\"isSourceSeparated != null\">and is_source_separated = #{isSourceSeparated}</if>\n            <if test=\"dynamicLimitEnable != null\">and dynamic_limit_enable = #{dynamicLimitEnable}</if>\n            <if test=\"mappingImproveEnable != null\">and mapping_improve_enable = #{mappingImproveEnable}</if>\n            <if test=\"preCreateFlags != null\">and pre_create_flags = #{preCreateFlags}</if>\n            <if test=\"disableSourceFlags != null\">and disable_source_flags = #{disableSourceFlags}</if>\n            <if test=\"disableIndexRollover != null\">and disable_index_rollover = #{disableIndexRollover}</if>\n            <if test=\"shardNum != null\">and shard_num = #{shardNum}</if>\n        </trim>\n    </select>\n\n    <select id=\"listAll\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_config\n    </select>\n\n    <insert id=\"insert\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateConfigPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into index_template_config\n        (logic_id, is_source_separated, adjust_rack_tps_factor, adjust_rack_shard_factor,\n        dynamic_limit_enable, mapping_improve_enable,\n        pre_create_flags, disable_source_flags, disable_index_rollover, shard_num)\n        values\n        (#{logicId}, #{isSourceSeparated}, #{adjustTpsFactor}, #{adjustShardFactor},\n        #{dynamicLimitEnable}, #{mappingImproveEnable},\n        #{preCreateFlags}, #{disableSourceFlags}, #{disableIndexRollover}, #{shardNum})\n    </insert>\n\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_config\n        where id = #{configId}\n    </select>\n\n    <select id=\"getByLogicId\" parameterType=\"integer\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_config\n        where logic_id = #{logicId}\n    </select>\n\n    <update id=\"update\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateConfigPO\">\n        update index_template_config\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"isSourceSeparated != null\">,is_source_separated = #{isSourceSeparated}</if>\n            <if test=\"adjustTpsFactor != null\">,adjust_rack_tps_factor = #{adjustTpsFactor}</if>\n            <if test=\"adjustShardFactor != null\">,adjust_rack_shard_factor = #{adjustShardFactor}</if>\n            <if test=\"dynamicLimitEnable != null\">,dynamic_limit_enable = #{dynamicLimitEnable}</if>\n            <if test=\"mappingImproveEnable != null\">,mapping_improve_enable = #{mappingImproveEnable}</if>\n            <if test=\"preCreateFlags != null\">,pre_create_flags = #{preCreateFlags}</if>\n            <if test=\"disableSourceFlags != null\">,disable_source_flags = #{disableSourceFlags}</if>\n            <if test=\"disableIndexRollover != null\">,disable_index_rollover = #{disableIndexRollover}</if>\n            <if test=\"shardNum != null\">,shard_num = #{shardNum}</if>\n        </trim>\n        where logic_id = #{logicId}\n    </update>\n\n    <delete id=\"delete\" parameterType=\"long\">\n        delete from index_template_config\n        where id = #{configId}\n    </delete>\n    \n    <delete id=\"deleteByLogicId\">\n        delete from index_template_config\n        where logic_id = #{logicId}\n    </delete>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/IndexTemplateDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateDAO\">\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO\">\n        <result column=\"id\"                      jdbcType=\"INTEGER\" property=\"id\"/>\n        <result column=\"name\"                    jdbcType=\"VARCHAR\" property=\"name\"/>\n        <result column=\"data_type\"               jdbcType=\"TINYINT\" property=\"dataType\"/>\n        <result column=\"date_format\"             jdbcType=\"VARCHAR\" property=\"dateFormat\"/>\n        <result column=\"data_center\"             jdbcType=\"VARCHAR\" property=\"dataCenter\"/>\n        <result column=\"expire_time\"             jdbcType=\"BIGINT\" property=\"expireTime\"/>\n        <result column=\"hot_time\"                jdbcType=\"BIGINT\" property=\"hotTime\"/>\n        <result column=\"date_field\"              jdbcType=\"VARCHAR\" property=\"dateField\"/>\n        <result column=\"date_field_format\"       jdbcType=\"VARCHAR\" property=\"dateFieldFormat\"/>\n        <result column=\"id_field\"                jdbcType=\"VARCHAR\" property=\"idField\"/>\n        <result column=\"routing_field\"           jdbcType=\"VARCHAR\" property=\"routingField\"/>\n        <result column=\"expression\"              jdbcType=\"VARCHAR\" property=\"expression\"/>\n        <result column=\"desc\"                    jdbcType=\"VARCHAR\" property=\"desc\"/>\n        <result column=\"quota\"                   jdbcType=\"DECIMAL\" property=\"quota\"/>\n        <result column=\"write_rate_limit\"        jdbcType=\"INTEGER\" property=\"writeRateLimit\"/>\n        <result column=\"project_id\"                  jdbcType=\"INTEGER\" property=\"projectId\"/>\n        <result column=\"ingest_pipeline\"         jdbcType=\"VARCHAR\" property=\"ingestPipeline\"/>\n        <result column=\"block_read\"              jdbcType=\"BOOLEAN\" property=\"blockRead\"/>\n        <result column=\"block_write\"             jdbcType=\"BOOLEAN\" property=\"blockWrite\"/>\n        <result column=\"check_point_diff\"        jdbcType=\"BIGINT\" property=\"checkPointDiff\"/>\n        <result column=\"has_dcdr\"                jdbcType=\"BOOLEAN\" property=\"hasDCDR\"/>\n        <result column=\"create_time\"             jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n        <result column=\"update_time\"             jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n        <result column=\"resource_id\"             jdbcType=\"BIGINT\" property=\"resourceId\"/>\n        <result column=\"level\"                   jdbcType=\"TINYINT\" property=\"level\"/>\n        <result column=\"open_srv\"                jdbcType=\"VARCHAR\" property=\"openSrv\"/>\n        <result column=\"disk_size\"               jdbcType=\"DECIMAL\" property=\"diskSize\"/>\n        <result column=\"health\"               jdbcType=\"BIGINT\" property=\"health\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n         id, `name`, data_type, date_format, data_center, expire_time, hot_time,\n           date_field, date_field_format, id_field, routing_field, expression,\n         `desc`, quota, write_rate_limit, project_id, ingest_pipeline,block_read, block_write, resource_id,\n          check_point_diff, has_dcdr, create_time, update_time, `level`, `open_srv`, disk_size,health\n    </sql>\n\n    <select id=\"listByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info\n        where is_active = 1\n        <if test=\"id != null\">and id = #{id}</if>\n        <if test=\"name != null\">and `name` = #{name}</if>\n        <if test=\"dataCenter != null\">and data_center = #{dataCenter}</if>\n         <if test=\"projectId != null\">and project_id = #{projectId}</if>\n        <if test=\"resourceId != null\">and resource_id = #{resourceId}</if>\n        <if test=\"health != null\">and health = #{health}</if>\n        order by id desc\n    </select>\n\n    <select id=\"likeByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info\n        where is_active               = 1\n        <if test=\"name != null\">     and `name` LIKE CONCAT(#{name}, '%')</if>\n        <if test=\"dataType != null\"> and `data_type` = #{dataType}</if>\n        order by id desc\n    </select>\n\n    <select id=\"pagingByCondition\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info\n        where is_active = 1\n        <if test=\"param.id != null\"> and `id` = #{param.id}</if>\n        <if test=\"param.name != null\">     and `name` LIKE CONCAT('%', #{param.name}, '%')</if>\n        <if test=\"param.dataType != null\"> and `data_type` = #{param.dataType}</if>\n        <if test=\"param.resourceId != null\"> and `resource_id` = #{param.resourceId}</if>\n        <if test=\"param.desc != null\"> and `desc` LIKE CONCAT('%', #{param.desc}, '%')</if>\n        <if test=\"param.projectId != null\"> and `project_id` = #{param.projectId}</if>\n        <if test=\"param.health != null\"> and `health` = #{param.health}</if>\n        <if test=\"param.hasDCDR != null and (param.openSrv == null or param.openSrv == '')\">\n            and `has_dcdr` = #{param.hasDCDR}\n        </if>\n        <if test=\"param.hasDCDR == null and param.openSrv != null and param.openSrv != ''\">\n             and FIND_IN_SET(#{param.openSrv}, open_srv) > 0 AND has_dcdr = 0\n        </if>\n        <if test=\"param.hasDCDR != null and param.openSrv != null and param.openSrv != ''\">\n            and (`has_dcdr` =\n                 #{param.hasDCDR} or FIND_IN_SET(#{param.openSrv}, open_srv))\n        </if>\n        order by  ${sortTerm}  ${sortType}\n        limit #{from}, #{size}\n    </select>\n    <select id=\"pagingByConditionAndLogicClusterIdList\"\n      resultType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info where is_active = 1\n        <if test=\"param.id != null\">and `id` = #{param.id}</if>\n        <if test=\"param.name != null\">and `name` LIKE CONCAT('%', #{param.name}, '%')</if>\n        <if test=\"param.dataType != null\">and `data_type` = #{param.dataType}</if>\n        <if test=\"(logicClusterIdList == null or logicClusterIdList.size() == 0) and param.resourceId != null\">\n            and `resource_id` = #{param.resourceId}\n        </if>\n        <if test=\"param.desc != null\">and `desc` LIKE CONCAT('%', #{param.desc}, '%')</if>\n        <if test=\"param.projectId != null\">and `project_id` = #{param.projectId}</if>\n   \n        <if test=\"param.health != null\">\n            and `health` = #{param.health}\n        </if>\n        <!--        dcdr opensrv-->\n        <if test=\"param.hasDCDR != null and (param.openSrv == null or param.openSrv == '')\">\n            and `has_dcdr` =\n                #{param.hasDCDR}\n        </if>\n        <if test=\"param.openSrv != null and param.openSrv != ''and param.hasDCDR == null\">\n             and FIND_IN_SET(#{param.openSrv}, open_srv) > 0 AND has_dcdr = 0\n        </if>\n        <if test=\"param.hasDCDR != null and param.openSrv != null and param.openSrv != ''\">\n            and (`has_dcdr` =\n                 #{param.hasDCDR} or FIND_IN_SET(#{param.openSrv}, open_srv))\n        </if>\n        <if test=\"logicClusterIdList != null and logicClusterIdList.size() != 0 and param.resourceId==null \">\n            and `resource_id` in\n            <foreach collection=\"logicClusterIdList\" item=\"resourceId\" open=\"(\" separator=\",\" close=\")\">\n                #{resourceId}\n            </foreach>\n        </if>\n    \n    \n        order by ${sortTerm} ${sortType} limit #{from}, #{size}\n    \n    \n    </select>\n\n    <select id=\"getTotalHitByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO\" resultType=\"long\">\n        select\n        count(1)\n        from index_template_info\n        where is_active = 1\n        <if test=\"id != null\"> and `id` = #{id}</if>\n        <if test=\"name != null\">     and `name` LIKE CONCAT('%', #{name}, '%')</if>\n        <if test=\"dataType != null\"> and `data_type` = #{dataType}</if>\n        <if test=\"resourceId != null\"> and `resource_id` = #{resourceId}</if>\n        <if test=\"desc != null\"> and `desc` LIKE CONCAT('%', #{desc}, '%')</if>\n        <if test=\"projectId != null\"> and `project_id` = #{projectId}</if>\n        <if test=\"health != null\"> and `health` = #{health}</if>\n          <!--        hash dcdr open srv-->\n        <if test=\"hasDCDR != null and (openSrv == null or openSrv == '')\">\n            and `has_dcdr` = #{hasDCDR}\n        </if>\n        <if test=\"hasDCDR == null and openSrv != null and openSrv != ''\">\n             and FIND_IN_SET(#{openSrv}, open_srv) > 0 AND has_dcdr = 0\n        </if>\n        <if test=\"hasDCDR != null and openSrv != null and openSrv != ''\">\n            and (`has_dcdr` = #{hasDCDR} OR FIND_IN_SET(#{openSrv}, open_srv))\n        </if>\n       \n    </select>\n    \n    <select id=\"getTotalHitByConditionAndLogicClusterIdList\"\n      parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO\" resultType=\"long\">\n        select count(1)\n        from index_template_info\n        where is_active = 1\n        <if test=\"param.id != null\">\n            and `id` = #{param.id}\n        </if>\n        <if test=\"param.name != null\">\n            and `name` LIKE CONCAT('%', #{param.name}, '%')\n        </if>\n        <if test=\"param.dataType != null\">\n            and `data_type` = #{param.dataType}\n        </if>\n        <if test=\"(logicClusterIdList == null or logicClusterIdList.size() == 0) and param.resourceId != null\">\n            and `resource_id` = #{param.resourceId}\n        </if>\n        <if test=\"param.desc != null\">\n            and `desc` LIKE CONCAT('%', #{param.desc}, '%')\n        </if>\n        <if test=\"param.projectId != null\">\n            and `project_id` = #{param.projectId}\n        </if>\n        <if test=\"param.health != null\">\n            and `health` = #{param.health}\n        </if>\n        <!--        hash dcdr open srv-->\n        <if test=\"param.hasDCDR != null and (param.openSrv == null or param.openSrv == '')\">\n            and `has_dcdr` = #{param.hasDCDR}\n        </if>\n        <if test=\"param.hasDCDR == null and param.openSrv != null and param.openSrv != ''\">\n            and FIND_IN_SET(#{param.openSrv}, open_srv) > 0 AND has_dcdr = 0\n        </if>\n        <if test=\"param.hasDCDR != null and param.openSrv != null and param.openSrv != ''\">\n            and (`has_dcdr` = #{param.hasDCDR} OR FIND_IN_SET(#{param.openSrv}, open_srv))\n        </if>\n        <if test=\"logicClusterIdList != null and logicClusterIdList.size() != 0 and param.resourceId == null\">\n            and `resource_id` in\n            <foreach collection=\"logicClusterIdList\" item=\"resourceId\" open=\"(\" separator=\",\" close=\")\">\n                #{resourceId}\n            </foreach>\n        </if>\n    </select>\n\n    <select id=\"listAll\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info\n        where is_active = 1\n        order by id desc\n    </select>\n\n    <insert id=\"insert\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into index_template_info\n          (is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  date_field, date_field_format, id_field, routing_field, expression,\n         `desc`, quota, write_rate_limit, project_id, ingest_pipeline, resource_id, `level`, open_srv, disk_size,health)\n        values\n        (1, #{name}, #{dataType}, #{dateFormat}, #{dataCenter}, #{expireTime}, #{hotTime},\n          #{dateField}, #{dateFieldFormat}, #{idField},\n         #{routingField}, #{expression}, #{desc}, #{quota}, #{writeRateLimit}, #{projectId}, #{ingestPipeline}, #{resourceId}, #{level}\n        , #{openSrv}, #{diskSize},0)\n    </insert>\n\n    <select id=\"getById\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info\n        where id = #{logicId} and is_active = 1\n    </select>\n\n    <select id=\"listByProjectId\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info\n        where project_id = #{projectId} and is_active = 1\n    </select>\n\n    <select id=\"listByDataCenter\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info\n        where data_center = #{dataCenter} and is_active = 1\n    </select>\n\n    <select id=\"listByName\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info\n        where `name` = #{name} and is_active = 1\n    </select>\n\n    <update id=\"update\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO\">\n        update index_template_info\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"projectId != null\">,project_id = #{projectId}</if>\n            <if test=\"name != null\">,`name` = #{name}</if>\n            <if test=\"dataType != null\">,data_type = #{dataType}</if>\n            <if test=\"dateFormat != null\">,date_format = #{dateFormat}</if>\n            <if test=\"dateFieldFormat != null\">,date_field_format = #{dateFieldFormat}</if>\n            <if test=\"idField != null\">,id_field = #{idField}</if>\n            <if test=\"routingField != null\">,routing_field = #{routingField}</if>\n            <if test=\"expireTime != null\">,expire_time = #{expireTime}</if>\n            <if test=\"hotTime != null\">,hot_time = #{hotTime}</if>\n            <if test=\"dateField != null\">,date_field = #{dateField}</if>\n            <if test=\"expression != null\">,expression = #{expression}</if>\n            <if test=\"desc != null\">,`desc` = #{desc}</if>\n            <if test=\"writeRateLimit != null\">,write_rate_limit = #{writeRateLimit}</if>\n            <if test=\"quota != null\">,quota = #{quota}</if>\n            <if test=\"ingestPipeline != null\">,ingest_pipeline = #{ingestPipeline}</if>\n            <if test=\"blockRead != null\">,block_read = #{blockRead}</if>\n            <if test=\"blockWrite != null\">,block_Write = #{blockWrite}</if>\n            <if test=\"resourceId != null\">,resource_id = #{resourceId}</if>\n            <if test=\"level != null\">,`level` = #{level}</if>\n            <if test=\"checkPointDiff != null\">,check_point_diff = #{checkPointDiff}</if>\n            <if test=\"hasDCDR != null\">,has_dcdr = #{hasDCDR}</if>\n            <if test=\"openSrv != null\">,open_srv = #{openSrv}</if>\n            <if test=\"diskSize != null\">,disk_size = #{diskSize}</if>\n            <if test=\"health != null\">,health = #{health}</if>\n        </trim>\n        where id = #{id}\n    </update>\n\n    <update id=\"batchChangeHotDay\"\n      parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO\">\n        update index_template_info set hot_time =  #{days}\n        <where>\n             id in\n        <foreach collection=\"templateIdList\" item=\"id\" open=\"(\" separator=\",\" close=\")\">#{id}</foreach>\n           \n           and is_active = 1\n        </where>\n    </update>\n\n    <delete id=\"delete\" parameterType=\"int\">\n        update index_template_info set  is_active = 0\n        where id = #{logicId}\n    </delete>\n\n    <select id=\"listByIds\" parameterType=\"list\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info\n        where is_active = 1 and\n        id in\n        <foreach collection=\"logicIds\" item=\"id\" open=\"(\" separator=\",\" close=\")\">#{id}</foreach>\n    </select>\n\n    <select id=\"listByResourceIds\" parameterType=\"list\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_info\n        where is_active = 1 and\n        resource_id in\n        <foreach collection=\"resourceIds\" item=\"resourceId\" open=\"(\" separator=\",\" close=\")\">#{resourceId}</foreach>\n    </select>\n\n    \n    <update id=\"updateBlockReadState\">\n        update index_template_info\n        set block_read = #{blockRead}\n        where id = #{logicId} and is_active = 1\n    </update>\n\n    <update id=\"updateBlockWriteState\">\n        update index_template_info\n        set block_write = #{blockWrite}\n        where id = #{logicId} and is_active = 1\n    </update>\n \n    \n    <select id=\"listAllNames\" resultType=\"java.lang.String\">\n        select `name`\n        from index_template_info\n        where is_active = 1\n        order by id desc\n    </select>\n\t\n    <select id=\"getProjectIdByTemplateLogicId\" resultType=\"java.lang.Integer\">\n        select project_id\n        from index_template_info\n        where id = #{logicId}\n          and is_active = 1\n    </select>\n\n    <select id=\"getNameByTemplateLogicId\" resultType=\"java.lang.String\">\n        select name\n        from index_template_info\n        where id = #{logicId}\n          and is_active = 1\n    </select>\n    <select id=\"getLogicTemplateIdListByProjectId\" resultType=\"java.lang.Integer\">\n        select id\n        from index_template_info\n        where project_id = #{projectId}\n          and is_active = 1\n    </select>\n  \n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/IndexTemplatePhyDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplatePhyDAO\">\n    <resultMap id=\"BaseResultMap\"\n               type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO\">\n        <result column=\"id\" jdbcType=\"BIGINT\" property=\"id\"/>\n        <result column=\"logic_id\" jdbcType=\"INTEGER\" property=\"logicId\"/>\n        <result column=\"name\" jdbcType=\"VARCHAR\" property=\"name\"/>\n        <result column=\"expression\" jdbcType=\"VARCHAR\" property=\"expression\"/>\n        <result column=\"cluster\" jdbcType=\"VARCHAR\" property=\"cluster\"/>\n        <result column=\"rack\" jdbcType=\"VARCHAR\" property=\"rack\"/>\n        <result column=\"shard\" jdbcType=\"INTEGER\" property=\"shard\"/>\n        <result column=\"shard_routing\" jdbcType=\"INTEGER\" property=\"shardRouting\"/>\n        <result column=\"version\" jdbcType=\"INTEGER\" property=\"version\"/>\n        <result column=\"role\" jdbcType=\"TINYINT\" property=\"role\"/>\n        <result column=\"status\" jdbcType=\"TINYINT\" property=\"status\"/>\n        <result column=\"config\" jdbcType=\"VARCHAR\" property=\"config\"/>\n        <result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n        <result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n        <result column=\"region_id\" jdbcType=\"INTEGER\" property=\"regionId\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n        id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, status, config, create_time, update_time, region_id\n    </sql>\n\n    <select id=\"listByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where status > 0\n        <if test=\"id != null\">and id = #{id}</if>\n        <if test=\"logicId != null\">and logic_id = #{logicId}</if>\n        <if test=\"name != null\">and `name` = #{name}</if>\n        <if test=\"cluster != null\">and cluster = #{cluster}</if>\n        <if test=\"role != null\">and role = #{role}</if>\n        <if test=\"regionId != null\">and region_id = #{regionId}</if>\n        order by id desc\n    </select>\n\n    <insert id=\"insert\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into index_template_physical_info\n        (logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config, region_id)\n        values\n        (#{logicId}, #{name}, #{expression}, #{cluster},\n         #{rack}, #{shard}, #{shardRouting}, #{version}, #{role}, #{config}, #{regionId})\n    </insert>\n\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where id = #{physicalId} and status > 0\n    </select>\n\n    <select id=\"getNormalAndDeletingById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where id = #{physicalId} and (status = 1 or status = -1)\n    </select>\n\n\n    <select id=\"listAll\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where status > 0\n    </select>\n\n    <select id=\"listByLogicId\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where logic_id = #{logicId} and status > 0\n    </select>\n\n    <select id=\"listByName\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where `name` = #{name} and status > 0\n    </select>\n\n    <select id=\"listByLogicIds\" parameterType=\"list\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where status > 0 and\n        logic_id in\n        <foreach collection=\"list\" item=\"id\" open=\"(\" separator=\",\" close=\")\">#{id}</foreach>\n    </select>\n\n    <select id=\"listByIds\" parameterType=\"list\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where status > 0 and\n        id in\n        <foreach collection=\"list\" item=\"id\" open=\"(\" separator=\",\" close=\")\">#{id}</foreach>\n    </select>\n\n\n    <update id=\"update\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO\">\n        update index_template_physical_info\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"name != null\">,`name` = #{name}</if>\n            <if test=\"expression != null\">,expression = #{expression}</if>\n            <if test=\"rack != null\">,rack = #{rack}</if>\n            <if test=\"shard != null\">,shard = #{shard}</if>\n            <if test=\"shardRouting != null\">,shard_routing = #{shardRouting}</if>\n            <if test=\"version != null\">,version = #{version}</if>\n            <if test=\"role != null\">,role = #{role}</if>\n            <if test=\"config != null\">,config = #{config}</if>\n            <if test=\"regionId != null\">,region_id = #{regionId}</if>\n        </trim>\n        where id = #{id} and status > 0\n    </update>\n\n    <update id=\"updateStatus\" parameterType=\"map\">\n        update index_template_physical_info\n        set status = #{status}\n        where id = #{physicalId}\n    </update>\n\t<update id=\"updateShardNumByLogicId\">\n      update index_template_physical_info\n        set shard = #{shardNum}\n        where logic_id = #{logicId}\n\t</update>\n\t\n\t<select id=\"getByLogicIdAndStatus\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where logic_id = #{logicId} and status = #{status}\n    </select>\n    <select id=\"getTemplateByLogicIdAndRole\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info where status > 0 and logic_id = #{logicId} and role = #{role}\n    </select>\n\n    <select id=\"getByClusterAndStatus\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where status = #{status} and cluster = #{cluster}\n    </select>\n\n    <select id=\"getByClusterAndNameAndStatus\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where status = #{status} and cluster = #{cluster} and `name` = #{name}\n    </select>\n\n    <select id=\"listByClusterAndStatus\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where status = #{status} and cluster = #{cluster}\n    </select>\n\n    <select id=\"listByMatchClusterAndStatus\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where status = #{status} and cluster LIKE CONCAT(#{cluster},'%')\n    </select>\n\n    <select id=\"getByClusterAndName\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where `name` = #{name} and cluster = #{cluster}  and status > 0\n    </select>\n    <select id=\"countListByLogicId\" resultMap=\"BaseResultMap\">\n        select id, logic_id\n        from index_template_physical_info\n        where `status` > 0\n    </select>\n\n    <delete id=\"deleteDirtyByClusterAndName\" parameterType=\"map\">\n        delete from index_template_physical_info\n        where `name` = #{name} and cluster = #{cluster} and status &lt; 0\n    </delete>\n\n    <select id=\"listByRegionId\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_physical_info\n        where region_id = #{regionId} and status > 0\n    </select>\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/IndexTemplateType.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateTypeDAO\">\n    <resultMap id=\"BaseResultMap\"\n               type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateTypePO\">\n        <result column=\"id\" jdbcType=\"INTEGER\" property=\"id\"/>\n        <result column=\"index_template_id\" jdbcType=\"INTEGER\" property=\"indexTemplateId\"/>\n        <result column=\"index_template_name\" jdbcType=\"VARCHAR\" property=\"indexTemplateName\"/>\n        <result column=\"name\" jdbcType=\"VARCHAR\" property=\"name\"/>\n        <result column=\"id_field\" jdbcType=\"VARCHAR\" property=\"idField\"/>\n        <result column=\"routing\" jdbcType=\"VARCHAR\" property=\"routing\"/>\n        <result column=\"source\" jdbcType=\"BOOLEAN\" property=\"source\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n       id, index_template_id, index_template_name, `name`, id_field, routing, source\n    </sql>\n\n    <select id=\"listByIndexTemplateId\" resultMap=\"BaseResultMap\" parameterType=\"integer\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from index_template_type\n        where is_active = 1 and index_template_id = #{indexTemplateId}\n        order by id desc\n    </select>\n\n    <update id=\"update\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateTypePO\">\n        update index_template_type\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"name != null\">,`name` = #{name}</if>\n            <if test=\"idField != null\">,id_field = #{idField}</if>\n            <if test=\"routing != null\">,routing = #{routing}</if>\n            <if test=\"source != null\">,source = #{source}</if>\n        </trim>\n        where id = #{id} and is_active = 1\n    </update>\n\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/LogicCluster.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.resource.LogicClusterDAO\">\n    <resultMap id=\"BaseResultMap\"\n               type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterLogicPO\">\n        <result column=\"id\" jdbcType=\"BIGINT\" property=\"id\"/>\n        <result column=\"name\" jdbcType=\"VARCHAR\" property=\"name\"/>\n        <result column=\"type\"                       jdbcType=\"TINYINT\" property=\"type\"/>\n        <result column=\"project_id\"                 jdbcType=\"VARCHAR\" property=\"projectId\"/>\n        <result column=\"data_center\"                jdbcType=\"VARCHAR\" property=\"dataCenter\"/>\n        <result column=\"memo\"                       jdbcType=\"VARCHAR\" property=\"memo\"/>\n        <result column=\"quota\"                      jdbcType=\"DECIMAL\" property=\"quota\"/>\n        <result column=\"level\"                      jdbcType=\"TINYINT\" property=\"level\"/>\n        <result column=\"config_json\"                jdbcType=\"VARCHAR\" property=\"configJson\"/>\n        <result column=\"create_time\"                jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n        <result column=\"update_time\"                jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n        <result column=\"health\"                     jdbcType=\"TINYINT\" property=\"health\"/>\n        <result column=\"data_node_spec\"             jdbcType=\"VARCHAR\" property=\"dataNodeSpec\"/>\n        <result column=\"disk_total\"                 jdbcType=\"BIGINT\" property=\"diskTotal\"/>\n        <result column=\"disk_usage\"                 jdbcType=\"BIGINT\" property=\"diskUsage\"/>\n        <result column=\"disk_usage_percent\"         jdbcType=\"DECIMAL\" property=\"diskUsagePercent\"/>\n        <result column=\"es_cluster_version\"         jdbcType=\"VARCHAR\" property=\"esClusterVersion\"/>\n        <result column=\"data_node_num\"              jdbcType=\"INTEGER\" property=\"dataNodeNum\"/>\n\n\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n        id , `name`, `type`, project_id, data_center,  memo, quota, `level`, config_json, create_time, update_time, health,data_node_spec,\n            disk_total,disk_usage,disk_usage_percent,es_cluster_version,data_node_num\n    </sql>\n\n    <select id=\"listByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterLogicPO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_arius_resource_logic\n        <trim prefix=\"where\" prefixOverrides=\"and\">\n            <if test=\"id != null\">and id = #{id}</if>\n            <if test=\"name != null\">and `name` = #{name}</if>\n            <if test=\"type != null\">and `type` = #{type}</if>\n            <if test=\"level != null\">and `level` = #{level}</if>\n            <if test=\"projectId != null\">and ( project_id = #{projectId} or find_in_set(#{projectId}, project_id))</if>\n            <if test=\"dataCenter != null\">and data_center = #{dataCenter}</if>\n            <if test=\"health != null\">and health = #{health}</if>\n        </trim>\n        order by id desc\n    </select>\n\n    <select id=\"listByNameAndProjectId\" parameterType=\"String\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_arius_resource_logic\n        <trim prefix=\"where\" prefixOverrides=\"and\">\n            <if test=\"name != null and name != ''\">and `name` LIKE CONCAT('%',#{name},'%')</if>\n            <if test=\"projectId != null\">and ( project_id = #{projectId} or find_in_set(#{projectId}, project_id))</if>\n        </trim>\n        order by id desc\n    </select>\n\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterLogicPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into project_arius_resource_logic\n        (`name`, `type`, project_id, data_center,   memo, quota, `level`, config_json,\n         health,`data_node_spec`)\n        values (#{name}, #{type}, #{projectId}, #{dataCenter},\n                #{memo}, #{quota}, #{level}, #{configJson}, #{health},#{dataNodeSpec})\n    </insert>\n\n    <update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterLogicPO\">\n        update project_arius_resource_logic\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"name != null\">,`name` = #{name}</if>\n            <if test=\"type != null\">,`type` = #{type}</if>\n            <if test=\"projectId != null\">,project_id = #{projectId}</if>\n           \n            <if test=\"memo != null\">,memo = #{memo}</if>\n            <if test=\"quota != null\">,quota = #{quota}</if>\n            <if test=\"level != null\">,`level` = #{level}</if>\n            <if test=\"configJson != null\">,config_json = #{configJson}</if>\n            <if test=\"health != null\">,health = #{health}</if>\n            <if test=\"diskTotal != null\">, disk_total = #{diskTotal}</if>\n            <if test=\"diskUsage != null\">, disk_usage = #{diskUsage}</if>\n            <if test=\"diskUsagePercent != null\">, disk_usage_percent = #{diskUsagePercent}</if>\n            <if test=\"esClusterVersion != null\">, es_cluster_version = #{esClusterVersion}</if>\n            <if test=\"dataNodeNum != null\">, data_node_num = #{dataNodeNum}</if>\n        </trim>\n        where id = #{id}\n    </update>\n    \n    <delete id=\"delete\" parameterType=\"long\">\n        delete from project_arius_resource_logic\n        where id = #{resourceId}\n    </delete>\n\n    <select id=\"listAll\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_arius_resource_logic\n        order by id desc\n    </select>\n\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_arius_resource_logic\n        where id = #{resourceId}\n    </select>\n\n    <select id=\"listByIds\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_arius_resource_logic\n        where\n        <choose>\n            <when test=\"ids != null and ids.size > 0\">\n                id in\n                <foreach collection=\"ids\" item=\"id\" open=\"(\" separator=\",\" close=\")\">#{id}</foreach>\n            </when>\n            <otherwise>\n                1=0\n            </otherwise>\n        </choose>\n    </select>\n\n    <select id=\"getByName\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_arius_resource_logic\n        where `name` = #{name}\n    </select>\n\n    <select id=\"listByProjectId\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_arius_resource_logic\n        where project_id = #{projectId}\n           or find_in_set(#{projectId}, project_id)\n    </select>\n\n    <select id=\"getLastCommon\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_arius_resource_logic\n        where `type` = 1\n        order by id desc\n        limit 1\n    </select>\n\n   \n\n    <select id=\"pagingByCondition\" resultMap=\"BaseResultMap\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicConditionDTO\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_arius_resource_logic\n        where id > 0\n        <if test=\"id != null\">and id = #{id}</if>\n        <if test=\"name != null\">and `name` LIKE CONCAT('%',#{name},'%')</if>\n        <if test=\"projectId != null\">and ( project_id = #{projectId} or find_in_set(#{projectId}, project_id))</if>\n        <if test=\"health != null\">and health = #{health}</if>\n        <if test=\"type != null\">and type = #{type}</if>\n        <if test=\"memo != null\">and `memo` LIKE CONCAT('%',#{memo},'%')</if>\n        <if test=\"sortTerm != null\">\n            order by ${sortTerm} ${sortType}\n        </if>\n        limit #{from}, #{size}\n    </select>\n\n    <select id=\"getTotalHitByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicConditionDTO\"\n            resultType=\"long\">\n        select\n        count(1)\n        from project_arius_resource_logic\n        where id > 0\n        <if test=\"id != null\">and id = #{id}</if>\n        <if test=\"name != null\">and `name` LIKE CONCAT('%',#{name},'%')</if>\n        <if test=\"projectId != null\">and ( project_id = #{projectId} or find_in_set(#{projectId}, project_id)) </if>\n        <if test=\"health != null\">and health = #{health}</if>\n        <if test=\"type != null\">and type = #{type}</if>\n        <if test=\"memo != null\">and `memo` LIKE CONCAT('%',#{memo},'%')</if>\n    </select>\n    <select id=\"listByLevel\"\n      resultType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterLogicPO\">\n         select\n        <include refid=\"Base_Column_List\"/>\n        from project_arius_resource_logic where level=#{level}\n    </select>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/MetricsDictionaryDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n\t\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.metrics.MetricsDictionaryDAO\">\n\t<resultMap id=\"BaseResultMap\"\n\t           type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.metrics.MetricsDictionaryPO\">\n\t\t<!--@mbg.generated--><!--@Table user_metrics_config_info-->\n\t\t<id column=\"id\" jdbcType=\"BIGINT\" property=\"id\"/>\n\t\t<result column=\"type\" jdbcType=\"VARCHAR\" property=\"type\"/>\n\t\t<result column=\"metric_type\" jdbcType=\"VARCHAR\" property=\"metricType\"/>\n\t\t<result column=\"name\" jdbcType=\"VARCHAR\" property=\"name\"/>\n\t\t<result column=\"price\" jdbcType=\"VARCHAR\" property=\"price\"/>\n\t\t<result column=\"interval\" jdbcType=\"VARCHAR\" property=\"interval\"/>\n\t\t<result column=\"current_cal_logic\" jdbcType=\"VARCHAR\" property=\"currentCalLogic\"/>\n\t\t<result column=\"is_gold\" jdbcType=\"TINYINT\" property=\"isGold\"/>\n\t\t<result column=\"unit\" jdbcType=\"VARCHAR\" property=\"unit\"/>\n\t\t<result column=\"is_warning\" jdbcType=\"TINYINT\" property=\"isWarning\"/>\n\t\t<result column=\"interactive_form\" jdbcType=\"VARCHAR\" property=\"interactiveForm\"/>\n\t\t<result column=\"source\" jdbcType=\"VARCHAR\" property=\"source\"/>\n\t\t<result column=\"tags\" jdbcType=\"VARCHAR\" property=\"tags\"/>\n\t\t<result column=\"model\" jdbcType=\"VARCHAR\" property=\"model\"/>\n\t\t<result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n\t\t<result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n\t</resultMap>\n\n\n\t<sql id=\"Base_Column_List\">\n\t\tid, `type`, `name`, price, `interval`, current_cal_logic, `is_gold`, `unit`, is_warning,interactive_form, `source`,\n        tags, `model`,`metric_type`\n\t</sql>\n\n\t<select id=\"listAll\" resultMap=\"BaseResultMap\">\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom metric_dictionary_info where is_active = 1;\n\t</select>\n\n\t<select id=\"listByCondition\" resultMap=\"BaseResultMap\"\n\t\t\tparameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricDictionaryDTO\" >\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom metric_dictionary_info\n\t\twhere id > 0\n\t\t<if test=\"type != null\">and `type` = #{type}</if>\n\t\t<if test=\"name != null\">and `name` = #{name}</if>\n\t\t<if test=\"metricType != null\">and `metric_type` = #{metricType}</if>\n\t\t<if test=\"isGold != null\">and is_gold = #{isGold}</if>\n\t\t<if test=\"isWarning != null\">and is_warning = #{isWarning}</if>\n\t\t<if test=\"source != null\">and source = #{source}</if>\n\t\t<if test=\"tags != null\">and tags = #{tags}</if>\n\t\t<if test=\"model != null\">and model = #{model}</if>\n\t\t<if test=\"isThreshold != null\">and is_hreshold = #{isThreshold}</if>\n;\n\t</select>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/OpTaskDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.task.OpTaskDAO\">\n  <resultMap id=\"WorkTaskMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.task.OpTaskPO\">\n    <result column=\"title\" jdbcType=\"VARCHAR\" property=\"title\"/>\n    <result column=\"task_type\" jdbcType=\"INTEGER\" property=\"taskType\"/>\n    <result column=\"business_key\" jdbcType=\"VARCHAR\" property=\"businessKey\"/>\n    <result column=\"status\" jdbcType=\"VARCHAR\" property=\"status\"/>\n    <result column=\"creator\" jdbcType=\"VARCHAR\" property=\"creator\"/>\n    <result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n    <result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n    <result column=\"delete_flag\" jdbcType=\"BOOLEAN\" property=\"deleteFlag\"/>\n    <result column=\"expand_data\" jdbcType=\"LONGVARCHAR\" property=\"expandData\"/>\n  </resultMap>\n    \n    <sql id=\"columns\">\n        <![CDATA[\n        id, title, task_type, business_key, `status`, creator, create_time, update_time, delete_flag, expand_data\n        ]]>\n    </sql>\n    \n    <sql id=\"where\">\n        <where>\n           <if test=\"id != null and '' != id\">\n                AND id = #{id}\n            </if>\n           <if test=\"title != null and '' != title\">\n                AND title = #{title}\n            </if>\n           <if test=\"taskType != null and '' != taskType\">\n                AND task_type = #{taskType}\n            </if>\n           <if test=\"businessKey != null and '' != businessKey\">\n                AND business_key = #{businessKey}\n            </if>\n           <if test=\"status != null\">\n                AND status = #{status}\n            </if>\n           <if test=\"creator != null and '' != creator\">\n                AND creator = #{creator}\n            </if>\n           <if test=\"deleteFlag != null and '' != deleteFlag\">\n                AND delete_flag = #{deleteFlag}\n            </if>\n           <if test=\"expandData != null and '' != expandData\">\n                AND expand_data = #{expandData}\n            </if>\n        </where>\n    </sql>\n    \n    <select id=\"getById\" resultMap=\"WorkTaskMap\">\n        SELECT <include refid=\"columns\" />\n        <![CDATA[\n            FROM\n                arius_op_task\n            WHERE \n                id = #{id} \n        ]]>\n    </select>\n\n    <select id=\"getLatestTask\" resultMap=\"WorkTaskMap\">\n        SELECT <include refid=\"columns\" />\n        <![CDATA[\n            FROM\n                arius_op_task\n            WHERE\n                 business_key LIKE CONCAT(#{businessKey},'%')\n                 AND task_type = #{taskType}\n                order by id desc limit 1\n        ]]>\n    </select>\n\n    <select id=\"getPendingTask\" resultMap=\"WorkTaskMap\">\n        SELECT <include refid=\"columns\" />\n        <![CDATA[\n            FROM\n                arius_op_task\n            WHERE\n                business_key LIKE CONCAT(#{businessKey},'%')\n                AND task_type = #{taskType}\n                and status in ('waiting','pause','running')\n                limit 1\n        ]]>\n    </select>\n\n    <select id=\"getPendingTaskByType\" resultMap=\"WorkTaskMap\">\n        SELECT <include refid=\"columns\" />\n        FROM\n            arius_op_task\n        WHERE task_type = #{taskType}\n        AND status in ('waiting','pause','running')\n    </select>\n\n    <select id=\"getSuccessTaskByType\" resultMap=\"WorkTaskMap\">\n        SELECT <include refid=\"columns\" />\n        FROM\n        arius_op_task\n        WHERE task_type = #{taskType}\n        AND status in ('success')\n    </select>\n\n    <select id=\"listAll\" resultMap=\"WorkTaskMap\">\n        SELECT\n        <include refid=\"columns\" />\n        FROM\n        arius_op_task\n        where  delete_flag = '0' order by id  desc\n    </select>\n    \n    <select id=\"listByCondition\" resultMap=\"WorkTaskMap\">\n        SELECT\n            <include refid=\"columns\" />\n        FROM\n            arius_op_task \n        <include refid=\"where\"/>\n    </select>\n\n    <select id=\"pagingByCondition\" resultMap=\"WorkTaskMap\">\n        select\n        <include refid=\"columns\" />\n        FROM\n        arius_op_task\n        where delete_flag = '0'\n        <if test=\"param.title != null\">     and `title` LIKE CONCAT('%', #{param.title}, '%')</if>\n        <if test=\"param.startTime != null\">\n            and create_time &gt;= #{param.startTime}\n        </if>\n        <if test=\"param.endTime != null\">\n            and create_time &lt;= #{param.endTime}\n        </if>\n        order by  ${sortTerm}  ${sortType}\n        limit #{from}, #{size}\n    </select>\n\n    <select id=\"countByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskQueryDTO\" resultType=\"long\">\n        select\n        count(1)\n        from arius_op_task\n        where delete_flag = '0'\n        <if test=\"title != null\">     and `title` LIKE CONCAT('%', #{title}, '%')</if>\n        <if test=\"startTime != null\">\n            and create_time &gt;= #{startTime}\n        </if>\n        <if test=\"endTime != null\">\n            and create_time &lt;= #{endTime}\n        </if>\n    </select>\n\n    <insert id=\"insert\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n        <![CDATA[\n            INSERT INTO arius_op_task (\n                title,\n                task_type,\n                business_key,\n                status,\n                creator,\n                create_time,\n                update_time,\n                delete_flag,\n                expand_data\n            ) VALUES (\n                #{title},\n                #{taskType},\n                #{businessKey},\n                #{status},\n                #{creator},\n                #{createTime},\n                #{updateTime},\n                #{deleteFlag},\n                #{expandData}\n            )\n        ]]>\n    </insert>\n\n    <update id=\"update\">\n            UPDATE\n                arius_op_task\n            <set>\n                <if test=\"title != null and '' != title\">\n                \t<![CDATA[ title = #{title} ]]>,\n                </if>\n                <if test=\"taskType != null and '' != taskType\">\n                \t<![CDATA[ task_type = #{taskType} ]]>,\n                </if>\n                <if test=\"businessKey != null and '' != businessKey\">\n                \t<![CDATA[ business_key = #{businessKey} ]]>,\n                </if>\n                <if test=\"status != null\">\n                \t<![CDATA[ status = #{status} ]]>,\n                </if>\n                <if test=\"updateTime != null\">\n                \t<![CDATA[ update_time = #{updateTime} ]]>,\n                </if>\n                <if test=\"deleteFlag != null and '' != deleteFlag\">\n                \t<![CDATA[ delete_flag = #{deleteFlag} ]]>,\n                </if>\n                <if test=\"expandData != null and '' != expandData\">\n                \t<![CDATA[ expand_data = #{expandData} ]]>\n                </if>\n            </set>\n            <where>\n                id = #{id}\n            </where>\n    </update>\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/OperateRecord.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n\t\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.optrecord.OperateRecordDAO\">\n\t<resultMap id=\"BaseResultMap\"\n\t           type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.operaterecord.OperateRecordInfoPO\">\n\t\t<!--@mbg.generated-->\n\t\t<!--@Table operate_record_info-->\n\t\t<id column=\"id\" jdbcType=\"BIGINT\" property=\"id\"/>\n\t\t<result column=\"project_name\" jdbcType=\"INTEGER\" property=\"projectName\"/>\n\t\t<result column=\"module_id\" jdbcType=\"INTEGER\" property=\"moduleId\"/>\n\t\t<result column=\"operate_id\" jdbcType=\"INTEGER\" property=\"operateId\"/>\n\t\t<result column=\"trigger_way_id\" jdbcType=\"INTEGER\" property=\"triggerWayId\"/>\n\t\t<result column=\"user_operation\" jdbcType=\"VARCHAR\" property=\"userOperation\"/>\n\t\t<result column=\"biz_id\" jdbcType=\"INTEGER\" property=\"bizId\"/>\n\t\t<result column=\"content\" jdbcType=\"INTEGER\" property=\"content\"/>\n\t\t<result column=\"operate_time\" jdbcType=\"TIMESTAMP\" property=\"operateTime\"/>\n\t\t<result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n\t\t<result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n\t</resultMap>\n\t\n\t<sql id=\"Base_Column_List\">\n\t\t<!--@mbg.generated-->\n\t\t<!--@Table operate_record_info-->    id,\n\t\t                                project_name,\n\t\t                                module_id,\n\t\t                                operate_id,\n\t\t                                trigger_way_id,\n\t\t                                user_operation,\n\t\t                                operate_time,\n\t\t                                create_time,\n\t\t                                update_time,\n\t\t                                biz_id,\n\t\t                                content\n\t</sql>\n\t\n\t<insert id=\"insert\"\n\t        parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.operaterecord.OperateRecordInfoPO\"\n\t        useGeneratedKeys=\"true\" keyColumn=\"id\" keyProperty=\"id\">\n\t\t<!--@mbg.generated-->    insert into operate_record_info (project_name, module_id, operate_id, trigger_way_id,\n\t\t                                                     user_operation, operate_time,\n\t\t                                                     content, biz_id)\n\t\t                         values (#{projectName}, #{moduleId}, #{operateId}, #{triggerWayId}, #{userOperation},\n\t\t                                 #{operateTime}, #{content}, #{bizId})\n\t</insert>\n\t\n\t<select id=\"listByCondition\" resultMap=\"BaseResultMap\"\n\t        parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO\">\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom operate_record_info\n\t\t<where >\n\t\t\t<if test=\"id != null\">\n\t\t\t\tand id = #{id}\n\t\t\t</if>\n\t\t\t<if test=\"moduleId != null\">\n\t\t\t\tand module_id = #{moduleId}\n\t\t\t</if>\n\t\t\t<if test=\"bizId != null  and bizId != ''\">\n\t\t\t\tand biz_id = #{bizId}\n\t\t\t</if>\n\t\t\t<if test=\"operateId != null\">\n\t\t\t\tand operate_id = #{operateId}\n\t\t\t</if>\n\t\t\t<if test=\"triggerWayId != null\">\n\t\t\t\tand trigger_way_id = #{triggerWayId}\n\t\t\t</if>\n\t\t\t<if test=\"beginTime != null\">\n\t\t\t\tand operate_time &gt;= #{beginTime}\n\t\t\t</if>\n\t\t\t<if test=\"endTime != null\">\n\t\t\t\tand operate_time &lt;= #{endTime}\n\t\t\t</if>\n\t\t\t<if test=\"projectName != null  and projectName != ''\">\n\t\t\t\tand (project_name = #{projectName} OR project_name LIKE CONCAT(#{projectName}, '%') OR project_name LIKE\n\t\t\t\t                                                                                       CONCAT('%', #{projectName}) OR\n\t\t\t\t     project_name LIKE CONCAT('%', #{projectName}, '%'))\n\t\t\t</if>\n\t\t\t<if test=\"userOperation != null  and userOperation != ''\">\n\t\t\t\tand user_operation = #{userOperation}\n\t\t\t</if>\n\t\t\t<if test=\"content != null and content != ''\">\n\t\t\t\tand (content = #{content} OR content LIKE CONCAT(#{content}, '%') OR content LIKE CONCAT('%',\n\t\t\t\t                                                                                         #{content}) OR\n\t\t\t\t     content LIKE CONCAT('%', #{content}, '%'))\n\t\t\t</if>\n\t\t</where>\n\t\t<if test=\"sortTerm != null\">\n\t\t\torder by ${sortTerm} ${sortType}\n\t\t</if>\n\t\tLIMIT #{from},#{size}\n\t</select>\n\t\n\t\n\t<select id=\"selectDescTopNByModuleId\" resultMap=\"BaseResultMap\"\n\t        parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.operaterecord.OperateRecordInfoPO\">\n\t\tselect id, module_id\n\t\tfrom operate_record_info\n\t\twhere module_id = #{moduleId}\n\t\torder by id DESC\n\t\tLIMIT #{topN}, 1\n\t</select>\n\n\t<select id=\"countByCondition\" resultType=\"java.lang.Long\"\n\t        parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO\">\n\t\tselect count(id)\n\t\tfrom operate_record_info\n\t\t<where >\n\t\t\t<if test=\"id != null\">\n\t\t\t\tand id = #{id}\n\t\t\t</if>\n\t\t\t<if test=\"moduleId != null\">\n\t\t\t\tand module_id = #{moduleId}\n\t\t\t</if>\n\t\t\t<if test=\"bizId != null\">\n\t\t\t\tand biz_id = #{bizId}\n\t\t\t</if>\n\t\t\t<if test=\"operateId != null\">\n\t\t\t\tand operate_id = #{operateId}\n\t\t\t</if>\n\t\t\t<if test=\"triggerWayId != null\">\n\t\t\t\tand trigger_way_id = #{triggerWayId}\n\t\t\t</if>\n\t\t\t<if test=\"beginTime != null\">\n\t\t\t\tand operate_time &gt;= #{beginTime}\n\t\t\t</if>\n\t\t\t<if test=\"endTime != null\">\n\t\t\t\tand operate_time &lt;= #{endTime}\n\t\t\t</if>\n\t\t\t<if test=\"projectName != null\">\n\t\t\t\tand (project_name = #{projectName} OR project_name LIKE CONCAT(#{projectName}, '%') OR project_name LIKE\n\t\t\t\t                                                                                       CONCAT('%', #{projectName}) OR\n\t\t\t\t     project_name LIKE CONCAT('%', #{projectName}, '%'))\n\t\t\t</if>\n\t\t\t<if test=\"userOperation != null\">\n\t\t\t\tand user_operation = #{userOperation}\n\t\t\t</if>\n\t\t\t<if test=\"content != null and content != ''\">\n\t\t\t\tand (content = #{content} OR content LIKE CONCAT(#{content}, '%') OR content LIKE CONCAT('%',\n\t\t\t\t                                                                                         #{content}) OR\n\t\t\t\t     content LIKE CONCAT('%', #{content}, '%'))\n\t\t\t</if>\n\t\t</where>\n\t\tORDER BY id\n\t</select>\n\t<select id=\"getById\"\n\t        resultType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.operaterecord.OperateRecordInfoPO\">\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom operate_record_info\n\t\twhere id = #{id}\n\t</select>\n\n\t<select id=\"selectOneOperateRecord\" resultMap=\"BaseResultMap\"\n\t\t\tparameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO\">\n\t\tselect\n\t\tid\n\t\tfrom operate_record_info\n\t\t<where >\n\t\t\t<if test=\"moduleId != null\">\n\t\t\t\tand module_id = #{moduleId}\n\t\t\t</if>\n\t\t\t<if test=\"operateId != null\">\n\t\t\t\tand operate_id = #{operateId}\n\t\t\t</if>\n\t\t\t<if test=\"triggerWayId != null\">\n\t\t\t\tand trigger_way_id = #{triggerWayId}\n\t\t\t</if>\n\t\t\t<if test=\"projectName != null  and projectName != ''\">\n\t\t\t\tand project_name = #{projectName}\n\t\t\t</if>\n\t\t\t<if test=\"userOperation != null  and userOperation != ''\">\n\t\t\t\tand user_operation = #{userOperation}\n\t\t\t</if>\n\t\t</where>\n\t</select>\n\n\t<update id=\"updateById\"\n\t\t\tparameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.operaterecord.OperateRecordInfoPO\">\n\t\tupdate operate_record_info\n\t\t<trim prefix=\"set\" prefixOverrides=\",\">\n\t\t\t<if test=\"content != null\">,`content` = #{content}</if>\n\t\t\t<if test=\"operateTime != null\">,`operate_time` = #{operateTime}</if>\n\t\t\t<if test=\"updateTime != null\">,`update_time` = #{updateTime}</if>\n\t\t</trim>\n\t\twhere id = #{id}\n\t</update>\n\t\n\t<update id=\"deleteByModuleIdAndLessThanId\">\n\t\tdelete\n\t\tfrom operate_record_info\n\t\twhere module_id = #{moduleId}\n\t\t\tand id &lt; #{id}\n\t</update>\n\n\t<update id=\"deleteExprieData\">\n\t\tdelete\n\t\tfrom operate_record_info\n\t\twhere cast(operate_time as datetime) &lt; #{saveTime}\n\t</update>\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/PhyClusterDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.resource.PhyClusterDAO\">\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterPhyPO\">\n        <result column=\"id\"                         jdbcType=\"INTEGER\" property=\"id\"/>\n        <result column=\"cluster\"                    jdbcType=\"VARCHAR\" property=\"cluster\"/>\n        <result column=\"read_address\"               jdbcType=\"VARCHAR\" property=\"readAddress\"/>\n        <result column=\"write_address\"              jdbcType=\"VARCHAR\" property=\"writeAddress\"/>\n        <result column=\"http_address\"               jdbcType=\"VARCHAR\" property=\"httpAddress\"/>\n        <result column=\"http_write_address\"         jdbcType=\"VARCHAR\" property=\"httpWriteAddress\"/>\n        <result column=\"desc\"                       jdbcType=\"VARCHAR\" property=\"desc\"/>\n        <result column=\"type\"                       jdbcType=\"TINYINT\" property=\"type\"/>\n        <result column=\"data_center\"                jdbcType=\"VARCHAR\" property=\"dataCenter\"/>\n        <result column=\"idc\"                        jdbcType=\"VARCHAR\" property=\"idc\"/>\n        <result column=\"level\"                      jdbcType=\"TINYINT\" property=\"level\"/>\n        <result column=\"es_version\"                 jdbcType=\"VARCHAR\" property=\"esVersion\"/>\n        <result column=\"cfg_id\"                     jdbcType=\"VARCHAR\" property=\"cfgId\"/>\n        <result column=\"package_id\"                 jdbcType=\"VARCHAR\" property=\"packageId\"/>\n        <result column=\"plug_ids\"                   jdbcType=\"VARCHAR\" property=\"plugIds\"/>\n        <result column=\"creator\"                    jdbcType=\"VARCHAR\" property=\"creator\"/>\n        <result column=\"ns_tree\"                    jdbcType=\"VARCHAR\" property=\"nsTree\"/>\n        <result column=\"image_name\"                 jdbcType=\"VARCHAR\" property=\"imageName\"/>\n        <result column=\"create_time\"                jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n        <result column=\"update_time\"                jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n        <result column=\"run_mode\"                   jdbcType=\"TINYINT\" property=\"runMode\"/>\n        <result column=\"write_action\"               jdbcType=\"VARCHAR\" property=\"writeAction\"/>\n        <result column=\"health\"                     jdbcType=\"TINYINT\" property=\"health\"/>\n        <result column=\"active_shard_num\"           jdbcType=\"BIGINT\"  property=\"activeShardNum\"/>\n        <result column=\"disk_total\"                 jdbcType=\"BIGINT\" property=\"diskTotal\"/>\n        <result column=\"disk_usage\"                 jdbcType=\"BIGINT\" property=\"diskUsage\"/>\n        <result column=\"disk_usage_percent\"         jdbcType=\"DECIMAL\" property=\"diskUsagePercent\"/>\n        <result column=\"tags\"                 jdbcType=\"VARCHAR\" property=\"tags\" />\n        <result column=\"platform_type\"                       jdbcType=\"VARCHAR\" property=\"platformType\"/>\n        <result column=\"resource_type\"                jdbcType=\"TINYINT\" property=\"resourceType\"/>\n        <result column=\"gateway_url\"                jdbcType=\"VARCHAR\" property=\"gatewayUrl\"/>\n        <result column=\"kibana_address\"                jdbcType=\"VARCHAR\" property=\"kibanaAddress\"/>\n        <result column=\"cerebro_address\"                jdbcType=\"VARCHAR\" property=\"cerebroAddress\"/>\n        <result column=\"proxy_address\"                jdbcType=\"VARCHAR\" property=\"proxyAddress\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n       id, cluster, read_address, write_address, http_address, http_write_address, `desc`, `type`, data_center,image_name, idc,\n        es_version, `level`, `password`, cfg_id, package_id, plug_ids, creator,ns_tree,  create_time, update_time,\n           run_mode, write_action, health, active_shard_num, disk_total, disk_usage, disk_usage_percent, tags,platform_type,resource_type,gateway_url, kibana_address, cerebro_address, proxy_address\n    </sql>\n\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterPhyPO\"\n            useGeneratedKeys=\"true\" keyColumn=\"id\" keyProperty=\"id\">\n        insert into es_cluster_phy_info\n        (cluster, read_address, write_address, http_address, http_write_address, `desc`, `type`, data_center,\n         image_name, idc, es_version, `level`, package_id, plug_ids, creator, ns_tree, run_mode,\n         write_action, health, `password`, active_shard_num, disk_total, disk_usage, disk_usage_percent, `tags`,\n         platform_type, resource_type, gateway_url, kibana_address, cerebro_address, proxy_address)\n        values (#{cluster}, #{readAddress}, #{writeAddress}, #{httpAddress}, #{httpWriteAddress}, #{desc}, #{type},\n                #{dataCenter}, #{imageName}, #{idc}, #{esVersion}, #{level}, #{packageId}, #{plugIds}, #{creator},\n                #{nsTree}, #{runMode}, #{writeAction}, #{health}, #{password}, #{activeShardNum},\n                #{diskTotal}, #{diskUsage}, #{diskUsagePercent}, #{tags}, #{platformType}, #{resourceType},\n                #{gatewayUrl},#{kibanaAddress},#{cerebroAddress},#{proxyAddress})\n    </insert>\n\n    <update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterPhyPO\">\n        update es_cluster_phy_info\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"readAddress != null\">read_address = #{readAddress}</if>\n            <if test=\"writeAddress != null\">,write_address = #{writeAddress}</if>\n            <if test=\"httpAddress != null\">,http_address = #{httpAddress}</if>\n            <if test=\"httpWriteAddress != null\">,http_write_address = #{httpWriteAddress}</if>\n            <if test=\"desc != null\">,`desc` = #{desc}</if>\n            <if test=\"type != null\">,`type` = #{type}</if>\n            <if test=\"dataCenter != null\">,data_center = #{dataCenter}</if>\n            <if test=\"imageName != null\">,image_name = #{imageName}</if>\n            <if test=\"idc != null\">,idc = #{idc}</if>\n            <if test=\"level != null\">,`level` = #{level}</if>\n            <if test=\"esVersion != null\">,es_version = #{esVersion}</if>\n            <if test=\"password != null\">,password = #{password}</if>\n            <if test=\"cfgId != null\">,cfg_id = #{cfgId}</if>\n            <if test=\"packageId != null\">,package_id = #{packageId}</if>\n            <if test=\"plugIds != null\">,plug_ids = #{plugIds}</if>\n            <if test=\"creator != null\">,creator = #{creator}</if>\n            <if test=\"nsTree != null\">,ns_tree = #{nsTree}</if>\n            <if test=\"runMode != null\">,run_mode = #{runMode}</if>\n            <if test=\"writeAction != null\">,write_action = #{writeAction}</if>\n            <if test=\"health != null\">,health = #{health}</if>\n            <if test=\"activeShardNum != null\">,active_shard_num = #{activeShardNum}</if>\n            <if test=\"health != null\">, health = #{health}</if>\n            <if test=\"diskTotal != null\">, disk_total = #{diskTotal}</if>\n            <if test=\"diskUsage != null\">, disk_usage = #{diskUsage}</if>\n            <if test=\"diskUsagePercent != null\">, disk_usage_percent = #{diskUsagePercent}</if>\n            <if test=\"tags != null\">, `tags` = #{tags}</if>\n            <if test=\"gatewayUrl != null\">, gateway_url = #{gatewayUrl}</if>\n            <if test=\"kibanaAddress != null\">, kibana_address = #{kibanaAddress}</if>\n            <if test=\"cerebroAddress != null\">, cerebro_address = #{cerebroAddress}</if>\n            <if test=\"proxyAddress != null\">, proxy_address = #{proxyAddress}</if>\n        </trim>\n        where id = #{id} and is_active = 1;\n    </update>\n\n    <update id=\"updatePluginIdsById\">\n        update es_cluster_phy_info\n        set plug_ids = #{plugIds}\n        where id = #{clusterId} and is_active = 1;\n    </update>\n\n    <delete id=\"delete\" parameterType=\"integer\">\n        update es_cluster_phy_info\n        set is_active = 0 where id = #{clusterId};\n    </delete>\n\n    <select id=\"listByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterPhyPO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_phy_info\n        <trim prefix=\"where\" prefixOverrides=\"and\">\n            <if test=\"id != null\">and id = #{id}</if>\n            <if test=\"cluster != null\">and cluster = #{cluster}</if>\n            <if test=\"type != null\">and `type` = #{type}</if>\n            <if test=\"dataCenter != null\">and data_center = #{dataCenter}</if>\n            <if test=\"idc != null\">and idc = #{idc}</if>\n            <if test=\"level != null\">and `level` = #{level}</if>\n            <if test=\"esVersion != null\">and es_version = #{esVersion}</if>\n            <if test=\"health != null\">and health = #{health}</if>\n            <if test=\"activeShardNum != null\">and active_shard_num = #{activeShardNum}</if>\n            <if test=\"platformType != null\">and platform_type = #{platformType}</if>\n            <if test=\"resourceType != null\">and resource_type = #{resourceType}</if>\n            and is_active = 1;\n        </trim>\n    </select>\n\n    <select id=\"pagingByCondition\" resultMap=\"BaseResultMap\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_phy_info\n        where is_active = 1\n        <if test=\"id != null\">and id = #{id}</if>\n        <if test=\"desc != null\">and `desc` LIKE CONCAT('%',#{desc},'%')</if>\n        <if test=\"cluster != null\">and cluster LIKE CONCAT('%',#{cluster},'%')</if>\n        <if test=\"esVersion != null\">and es_version = #{esVersion}</if>\n        <if test=\"health != null\">and health = #{health}</if>\n        <if test=\"activeShardNum != null\">and active_shard_num = #{activeShardNum}</if>\n        <if test=\"platformType != null\">and platform_type = #{platformType}</if>\n        <if test=\"resourceType != null\">and resource_type = #{resourceType}</if>\n        <if test=\"clusterNames != null and clusterNames.size() > 0\">\n            and cluster in\n            <foreach collection=\"clusterNames\" separator=\",\" item=\"item\" close=\")\" open=\"(\">\n                #{item}\n            </foreach>\n        </if>\n        <if test=\"sortTerm != null\">\n            order by ${sortTerm} ${sortType}\n        </if>\n        limit #{from}, #{size}\n    </select>\n\n    <select id=\"getTotalHitByCondition\" resultType=\"long\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO\">\n        select\n        count(1)\n        from es_cluster_phy_info\n        where is_active = 1\n        <if test=\"id != null\">and id = #{id}</if>\n        <if test=\"desc != null\">and `desc` LIKE CONCAT('%',#{desc},'%')</if>\n        <if test=\"cluster != null\">and cluster LIKE CONCAT('%',#{cluster},'%')</if>\n        <if test=\"esVersion != null\">and es_version = #{esVersion}</if>\n        <if test=\"health != null\">and health = #{health}</if>\n        <if test=\"activeShardNum != null\">and active_shard_num = #{activeShardNum}</if>\n        <if test=\"platformType != null\">and platform_type = #{platformType}</if>\n        <if test=\"resourceType != null\">and resource_type = #{resourceType}</if>\n        <if test=\"clusterNames != null and clusterNames.size() > 0\">\n            and cluster in\n            <foreach collection=\"clusterNames\" separator=\",\" item=\"item\" close=\")\" open=\"(\">\n                #{item}\n            </foreach>\n        </if>\n    </select>\n\n    <select id=\"getById\" parameterType=\"integer\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_phy_info\n        where id = #{clusterId} and is_active = 1;\n    </select>\n\n    <select id=\"getByName\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_phy_info\n        where cluster = #{clusterName} and is_active = 1;\n    </select>\n\n    <select id=\"listByNames\" parameterType=\"list\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_phy_info\n        where is_active = 1 and cluster in\n        <foreach collection=\"list\" separator=\",\" item=\"item\" close=\");\" open=\"(\">\n            #{item}\n        </foreach>\n    </select>\n\n\n    <select id=\"listAll\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_phy_info where is_active = 1;\n    </select>\n\n    <select id=\"listAllName\" resultType=\"String\">\n        select cluster\n        from es_cluster_phy_info where is_active = 1;\n    </select>\n\n    <select id=\"listByIds\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from es_cluster_phy_info\n        where\n        <choose>\n            <when test=\"ids != null and ids.size > 0\">\n                id in <foreach collection=\"ids\" item=\"id\" open=\"(\" separator=\",\" close=\")\">#{id}</foreach>\n            </when>\n            <otherwise>\n                1=0\n            </otherwise>\n        </choose>\n    </select>\n\n    <select id=\"getTotalHitByPackageId\"\n            parameterType=\"long\"\n            resultType=\"long\">\n        select\n        count(1)\n        from es_cluster_phy_info\n        where is_active = 1\n        and package_id = #{packageId}\n    </select>\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ProjectConfigDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n\t\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.project.ProjectConfigDAO\">\n\t<resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectConfigPO\">\n\t\t<result column=\"project_id\" jdbcType=\"INTEGER\" property=\"projectId\"/>\n\t\t<result column=\"dsl_analyze_enable\" jdbcType=\"INTEGER\" property=\"dslAnalyzeEnable\"/>\n\t\t<result column=\"aggr_analyze_enable\" jdbcType=\"INTEGER\" property=\"aggrAnalyzeEnable\"/>\n\t\t<result column=\"is_source_separated\" jdbcType=\"TINYINT\" property=\"isSourceSeparated\"/>\n\t\t<result column=\"analyze_response_enable\" jdbcType=\"TINYINT\" property=\"analyzeResponseEnable\"/>\n\t\t<result column=\"slow_query_times\" jdbcType=\"INTEGER\" property=\"slowQueryTimes\"/>\n\t\t<result column=\"memo\" jdbcType=\"INTEGER\" property=\"memo\"/>\n\t\t<result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n\t\t<result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n\t</resultMap>\n\t\n\t<sql id=\"Base_Column_List\">\n\t\tproject_id\n\t\t,\n\t\tdsl_analyze_enable,\n\t\taggr_analyze_enable,\n\t\tis_source_separated,\n\t\tanalyze_response_enable,\n\t\tcreate_time,\n\t\tupdate_time,\n\t\tslow_query_times,\n\t\t    memo\n\t</sql>\n\t\n\t\n\t<select id=\"getByProjectId\" parameterType=\"integer\" resultMap=\"BaseResultMap\">\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom project_arius_config where project_id = #{projectId}\n\t</select>\n\t\n\t<select id=\"listAll\" resultMap=\"BaseResultMap\">\n\t\tselect\n\t\t<include refid=\"Base_Column_List\"/>\n\t\tfrom project_arius_config where is_active = 1\n\t</select>\n\t<select id=\"checkProjectConfigByProjectId\" resultType=\"java.lang.Boolean\">\n\t\tselect count(project_id)\n\t\tfrom project_arius_config\n\t\twhere project_id = #{projectId}\n\t\t\tand is_active = 1\n\t</select>\n\t\n\t\n\t<insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectConfigPO\" >\n\t\tinsert into project_arius_config\n\t\t(project_id, dsl_analyze_enable, aggr_analyze_enable, is_source_separated, analyze_response_enable,\n\t\t slow_query_times, memo)\n\t\tvalues (#{projectId}, #{dslAnalyzeEnable}, #{aggrAnalyzeEnable}, #{isSourceSeparated}, #{aggrAnalyzeEnable},\n\t\t        #{slowQueryTimes}, #{memo})\n\t</insert>\n\t\n\t<update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectConfigPO\">\n\t\tupdate project_arius_config\n\t\t<trim prefix=\"set\" prefixOverrides=\",\">\n\t\t\t<if test=\"dslAnalyzeEnable != null\">\n\t\t\t\tdsl_analyze_enable = #{dslAnalyzeEnable}\n\t\t\t</if>\n\t\t\t<if test=\"aggrAnalyzeEnable != null\">\n\t\t\t\t, aggr_analyze_enable = #{aggrAnalyzeEnable}\n\t\t\t</if>\n\t\t\t<if test=\"isSourceSeparated != null\">\n\t\t\t\t, is_source_separated = #{isSourceSeparated}\n\t\t\t</if>\n\t\t\t<if test=\"analyzeResponseEnable != null\">\n\t\t\t\t, analyze_response_enable = #{analyzeResponseEnable}\n\t\t\t</if>\n\t\t\t<if test=\"slowQueryTimes != null\">\n\t\t\t\t, slow_query_times = #{slowQueryTimes}\n\t\t\t</if>\n\t\t\t<if test=\"memo != null\">\n\t\t\t\t,memo=#{memo}\n\t\t\t</if>\n\t\t</trim>\n\t\twhere project_id = #{projectId} and is_active = 1\n\t</update>\n\t<update id=\"deleteByProjectId\">\n\t\tupdate project_arius_config\n\t\tset is_active=0\n\t\twhere project_id = #{projectId}\n\t</update>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ProjectLogicClusterAuthDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.project.ProjectLogicClusterAuthDAO\">\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectClusterLogicAuthPO\">\n        <result column=\"id\" jdbcType=\"BIGINT\" property=\"id\"/>\n        <result column=\"project_id\" jdbcType=\"INTEGER\" property=\"projectId\"/>\n        <result column=\"logic_cluster_id\" jdbcType=\"BIGINT\" property=\"logicClusterId\"/>\n        <result column=\"type\" jdbcType=\"INTEGER\" property=\"type\"/>\n        <result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n        <result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n        id, project_id, logic_cluster_id, `type`,  create_time, update_time\n    </sql>\n\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectClusterLogicAuthPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into project_logi_cluster_auth (project_id, logic_cluster_id, `type`)\n        values (#{projectId}, #{logicClusterId}, #{type})\n    </insert>\n\n    <update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectClusterLogicAuthPO\">\n        update project_logi_cluster_auth\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"type != null\">,`type` = #{type}</if>\n        </trim>\n        where id = #{id}\n    </update>\n\n    <select id=\"listByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectClusterLogicAuthPO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_logi_cluster_auth\n        <trim prefix=\"where\" prefixOverrides=\"and\">\n            <if test=\"id != null\">and id = #{id}</if>\n            <if test=\"projectId != null\">and project_id = #{projectId}</if>\n            <if test=\"logicClusterId != null\">and logic_cluster_id = #{logicClusterId}</if>\n            <if test=\"type != null\">and `type` &lt;= #{type}</if>\n        </trim>\n        order by id desc\n    </select>\n\n    <delete id=\"delete\" parameterType=\"long\">\n        update project_logi_cluster_auth\n        set status = 0\n        where id = #{authId}\n    </delete>\n\n    <delete id=\"deleteByLogicClusterId\" parameterType=\"long\">\n        update project_logi_cluster_auth\n        set status = 0\n        where logic_cluster_id = #{logicClusterId}\n    </delete>\n\n    <select id=\"listByProjectId\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_logi_cluster_auth\n        where project_id = #{projectId} and (`type` != -1) and status = 1\n    </select>\n\n    <select id=\"listWithAccessByProjectId\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_logi_cluster_auth\n        where project_id = #{projectId} and (`type` = 2) and status = 1\n    </select>\n\n    <select id=\"getByProjectIdAndLogicClusterId\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_logi_cluster_auth\n        where project_id = #{projectId} and logic_cluster_id = #{logicClusterId} and (`type` != -1) and status = 1\n    </select>\n\n    <select id=\"getByProjectIdAndLogicClusterIdAndType\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_logi_cluster_auth\n        where project_id = #{projectId} and logic_cluster_id = #{logicClusterId} and `type` = #{type} and status = 1\n    </select>\n\n  \n\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_logi_cluster_auth\n        where id = #{authId} and status = 1\n    </select>\n\n\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/ProjectTemplateAuth.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.project.ProjectTemplateAuthDAO\">\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectTemplateAuthPO\">\n        <result column=\"id\" jdbcType=\"BIGINT\" property=\"id\"/>\n        <result column=\"project_id\" jdbcType=\"INTEGER\" property=\"projectId\"/>\n        <result column=\"template\" jdbcType=\"VARCHAR\" property=\"templateId\"/>\n        <result column=\"type\" jdbcType=\"INTEGER\" property=\"type\"/>\n        <result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n        <result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n    </resultMap>\n\n    <sql id=\"Base_Column_List\">\n       id, project_id, template, `type`,  create_time, update_time\n    </sql>\n\n    <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectTemplateAuthPO\"\n            useGeneratedKeys=\"true\"\n            keyColumn=\"id\" keyProperty=\"id\">\n        insert into project_template_info (project_id, template, `type`)\n        values (#{projectId}, #{templateId}, #{type})\n    </insert>\n\n    <update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectTemplateAuthPO\">\n        update project_template_info\n        <trim prefix=\"set\" prefixOverrides=\",\">\n            <if test=\"type != null\">`type` = #{type}</if>\n        </trim>\n        where id = #{id}\n    </update>\n\n    <select id=\"listByCondition\"\n            parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectTemplateAuthPO\"\n            resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_template_info\n        <trim prefix=\"where\" prefixOverrides=\"and\">\n            <if test=\"id != null\">and id = #{id}</if>\n            <if test=\"projectId != null\">and project_id = #{projectId}</if>\n            <if test=\"templateId != null\">and template = #{templateId}</if>\n            <if test=\"type != null\">and `type` = #{type}</if>\n            \n        </trim>\n        and status = 1\n        order by id desc\n    </select>\n\n    <delete id=\"delete\" parameterType=\"long\">\n        update project_template_info\n        set status = 0\n        where id = #{authId}\n    </delete>\n\n    <delete id=\"deleteByTemplate\" parameterType=\"int\">\n        update project_template_info\n        set status = 0\n        where template = #{templateId}\n    </delete>\n\n    <delete id=\"batchDeleteByTemplateIds\" parameterType=\"java.util.List\">\n        delete from project_template_info\n        where template in\n        <foreach item=\"item\" collection=\"list\" open=\"(\" separator=\",\" close=\")\">\n            #{item}\n        </foreach>\n    </delete>\n\n    <select id=\"listWithRwAuthsByProjectId\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_template_info\n        where project_id = #{projectId} and (`type` = 2 or `type` = 3) and status = 1\n    </select>\n\n    <select id=\"getByProjectIdAndTemplateId\" parameterType=\"map\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_template_info\n        where project_id = #{projectId} and template = #{templateId} and (`type` = 2 or `type` = 3) and status = 1\n    </select>\n\n    <select id=\"getByProjectIdAndTemplateIdAndType\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_template_info\n        where project_id = #{projectId} and template = #{templateId} and `type` = #{type} and status = 1\n    </select>\n\n    <select id=\"listByLogicTemplateId\" parameterType=\"string\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_template_info\n        where template = #{templateId} and (`type` = 2 or `type` = 3) and status = 1\n    </select>\n\n    <select id=\"getByTemplateId\" parameterType=\"int\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_template_info\n        where template = #{templateId} and status = 1\n    </select>\n\n    <select id=\"getById\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_template_info\n        where id = #{authId} and status = 1\n    </select>\n\n    <select id=\"listWithRwAuths\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_template_info\n        where (`type` = 2 or `type` = 3) and status = 1\n    </select>\n\n\n    <select id=\"listWithOwnerAuths\" parameterType=\"long\" resultMap=\"BaseResultMap\">\n        select\n        <include refid=\"Base_Column_List\"/>\n        from project_template_info\n        where `type` = 1 and status = 1\n    </select>\n    <select id=\"getProjectIdById\" resultType=\"java.lang.Integer\">\n        select project_id\n        from project_template_info\n        where id = #{authId}\n          and status = 1\n    </select>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/UserMetricsConfigDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n\t\"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.metrics.UserConfigDAO\">\n\t<resultMap id=\"BaseResultMap\"\n\t           type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.metrics.UserConfigPO\">\n\t\t<!--@mbg.generated--><!--@Table user_metrics_config_info-->\n\t\t<id column=\"id\" jdbcType=\"BIGINT\" property=\"id\"/>\n\t\t<result column=\"user_name\" jdbcType=\"VARCHAR\" property=\"userName\"/>\n\t\t<result column=\"project_id\" jdbcType=\"INTEGER\" property=\"projectId\"/>\n\t\t<result column=\"config_type\" jdbcType=\"INTEGER\" property=\"configType\"/>\n\t\t<result column=\"config_info\" jdbcType=\"LONGVARCHAR\" property=\"configInfo\"/>\n\t\t<result column=\"create_time\" jdbcType=\"TIMESTAMP\" property=\"createTime\"/>\n\t\t<result column=\"update_time\" jdbcType=\"TIMESTAMP\" property=\"updateTime\"/>\n\t</resultMap>\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-persistence/src/main/resources/mybatis/WorkOrderDAO.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.didichuxing.datachannel.arius.admin.persistence.mysql.workorder.WorkOrderDAO\">\n\n    <!-- 通用查询映射结果 -->\n    <resultMap id=\"BaseResultMap\" type=\"com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO\">\n        <id column=\"id\"                   jdbcType=\"BIGINT\"       property=\"id\" />\n        <result column=\"type\"             jdbcType=\"VARCHAR\"      property=\"type\" />\n        <result column=\"title\"            jdbcType=\"VARCHAR\"      property=\"title\" />\n        <result column=\"approver_project_id\"  jdbcType=\"INTEGER\"      property=\"approverProjectId\" />\n        <result column=\"applicant\"        jdbcType=\"VARCHAR\"      property=\"applicant\" />\n        <result column=\"extensions\"       jdbcType=\"LONGVARCHAR\"  property=\"extensions\" />\n        <result column=\"description\"      jdbcType=\"LONGVARCHAR\"  property=\"description\" />\n        <result column=\"approver\"         jdbcType=\"VARCHAR\"      property=\"approver\" />\n        <result column=\"finish_time\"       jdbcType=\"TIMESTAMP\"   property=\"finishTime\" />\n        <result column=\"opinion\"           jdbcType=\"VARCHAR\"     property=\"opinion\" />\n        <result column=\"status\"            jdbcType=\"INTEGER\"     property=\"status\" />\n        <result column=\"create_time\"       jdbcType=\"TIMESTAMP\"   property=\"createTime\" />\n        <result column=\"update_time\"       jdbcType=\"TIMESTAMP\"   property=\"updateTime\" />\n        <result column=\"applicant_project_id\"  jdbcType=\"INTEGER\"     property=\"applicantProjectId\" />\n    </resultMap>\n\n    <!-- 通用查询结果列 -->\n    <sql id=\"Base_Column_List\">\n        id, type, title,  applicant,approver_project_id, extensions, description, approver, finish_time, opinion, status, create_time, update_time, applicant_project_id\n    </sql>\n    \n    \n  <insert id=\"insert\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO\" useGeneratedKeys=\"true\" keyProperty=\"id\">\n    insert into arius_work_order_info (\n    type,title, applicant, applicant_project_id, description, extensions,approver_project_id\n    )\n    values (\n    #{type},#{title}, #{applicant}, #{applicantProjectId}, #{description},#{extensions},\n    #{approverProjectId}\n    )\n  </insert>\n\n  <select id=\"list\" resultMap=\"BaseResultMap\">\n    select <include refid=\"Base_Column_List\"/>\n    from arius_work_order_info\n    order by create_time desc\n  </select>\n\n  <select id=\"getById\" parameterType=\"java.lang.Long\" resultMap=\"BaseResultMap\">\n    select <include refid=\"Base_Column_List\"/>\n    from arius_work_order_info\n    where id=#{id}\n  </select>\n\n  <update id=\"updateOrderStatusById\" parameterType=\"java.util.Map\">\n    update arius_work_order_info\n    set status = #{status}, update_time=now()\n    where id = #{id}\n  </update>\n\n  <update id=\"update\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO\">\n    update arius_work_order_info\n    set approver = #{approver}, finish_time=now(), opinion= #{opinion}, status = #{status}, update_time=now()\n    where id = #{id}\n  </update>\n\n  <select id=\"listByStatusAndProjectId\" parameterType=\"java.util.Map\" resultMap=\"BaseResultMap\">\n    select <include refid=\"Base_Column_List\"/>\n    from arius_work_order_info\n    where applicant_project_id=#{applicantProjectId}\n    <trim>\n      <if test=\"status!=null\">\n        and status=#{status}\n      </if>\n    </trim>\n    order by status,create_time desc\n  </select>\n\n  <select id=\"listByApplicantAndStatus\" parameterType=\"java.util.Map\" resultMap=\"BaseResultMap\">\n    select <include refid=\"Base_Column_List\"/>\n    from arius_work_order_info\n    where applicant=#{applicant}\n    <trim>\n      <if test=\"status!=null\">\n        and status=#{status}\n      </if>\n \n    </trim>\n    order by status,create_time desc\n  </select>\n\n  <select id=\"listByApproverAndStatus\" parameterType=\"java.util.Map\" resultMap=\"BaseResultMap\">\n    select <include refid=\"Base_Column_List\"/>\n    from arius_work_order_info\n    where approver=#{approver}\n    <trim>\n      <if test=\"status!=null\">\n        and status=#{status}\n      </if>\n    </trim>\n    order by status,create_time desc\n  </select>\n\n  <select id=\"listByStatus\" parameterType=\"java.lang.Integer\" resultMap=\"BaseResultMap\">\n    select <include refid=\"Base_Column_List\"/>\n    from arius_work_order_info\n    where status=#{status}\n    order by create_time desc\n  </select>\n\n  <update id=\"updateExtensionsById\" parameterType=\"com.didichuxing.datachannel.arius.admin.common.bean.po.order.WorkOrderPO\">\n    UPDATE arius_work_order_info SET\n      extensions=#{extensions},\n      update_time=now()\n    WHERE id = #{id}\n  </update>\n\n  <select id=\"listByHandleTime\" parameterType=\"java.util.Map\" resultMap=\"BaseResultMap\">\n    select <include refid=\"Base_Column_List\"/>\n    from arius_work_order_info\n    where finish_time >= #{startTime} and #{endTime} >= finish_time\n  </select>\n\n</mapper>"
  },
  {
    "path": "arius-admin/arius-admin-remote/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <artifactId>arius-admin</artifactId>\n        <version>${revision}${sha1}${changelist}</version>\n    </parent>\n\n    <artifactId>arius-admin-remote</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-common</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.github.ben-manes.caffeine</groupId>\n            <artifactId>caffeine</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.minio</groupId>\n            <artifactId>minio</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.guava</groupId>\n            <artifactId>guava</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-test</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.httpcomponents</groupId>\n            <artifactId>httpmime</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.httpcomponents</groupId>\n            <artifactId>httpclient</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>commons-codec</groupId>\n            <artifactId>commons-codec</artifactId>\n        </dependency>\n\n    </dependencies>\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/storage/FileStorageHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.storage;\n\nimport org.springframework.web.multipart.MultipartFile;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.component.BaseHandle;\n\n/**\n * @author linyunan\n * @date 2021-05-19\n */\npublic interface FileStorageHandle extends BaseHandle {\n    /**\n     * 上传\n     * @param fileName 文件名\n     * @param fileMd5 文件md5\n     * @param uploadFile 文件\n     * @return 上传结果\n     */\n    Result<String> upload(String fileName, String fileMd5, MultipartFile uploadFile);\n\n    /**\n     * 下载文件\n     * @param fileName 文件名\n     * @return 文件\n     */\n    Result<MultipartFile> download(String fileName);\n\n    Result<Void> remove(String fileName);\n\n    /**\n     * 下载base地址\n     */\n    String getDownloadBaseUrl();\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/storage/content/FileStorageTypeEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.storage.content;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\n\n/**\n * 文件存储枚举\n *\n * @author linyunan\n * @date 2021-04-26\n */\npublic enum FileStorageTypeEnum {\n                                 S3(1, \"s3\"),\n\n                                 UNKNOWN(-1, \"unknown\");\n\n    private Integer code;\n\n    private String  type;\n\n    FileStorageTypeEnum(Integer code, String type) {\n        this.code = code;\n        this.type = type;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public Integer getCode() {\n        return code;\n    }\n\n    public static FileStorageTypeEnum valueOfType(String type) {\n        if (AriusObjUtils.isNull(type)) {\n            return FileStorageTypeEnum.UNKNOWN;\n        }\n        for (FileStorageTypeEnum typeEnum : FileStorageTypeEnum.values()) {\n            if (type.equals(typeEnum.getType())) {\n                return typeEnum;\n            }\n        }\n\n        return FileStorageTypeEnum.UNKNOWN;\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/storage/s3/S3FileStorageHandle.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.storage.s3;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.remote.storage.FileStorageHandle;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport io.minio.*;\nimport io.minio.messages.Item;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.compress.utils.Lists;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.mock.web.MockMultipartFile;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport javax.annotation.PostConstruct;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.List;\n\n/**\n * @author linyunan\n * @date 2021-05-19\n */\n@Component\n@NoArgsConstructor\npublic class S3FileStorageHandle implements FileStorageHandle {\n\n    private static final ILog LOGGER = LogFactory.getLog(S3FileStorageHandle.class);\n\n    @Value(\"${s3.endpoint:}\")\n    private String              endpoint;\n\n    @Value(\"${s3.access-key:}\")\n    private String              accessKey;\n\n    @Value(\"${s3.secret-key:}\")\n    private String              secretKey;\n\n    @Value(\"${s3.bucket:}\")\n    private String              bucket;\n\n    private MinioClient         minioClient;\n\n    @PostConstruct\n    public void init() {\n        try {\n            if (AriusObjUtils.anyBlank(this.endpoint, this.accessKey, this.secretKey, this.bucket)) {\n                // without config s3\n                return;\n            }\n            minioClient = MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();\n        } catch (Exception e) {\n            LOGGER.error(\"class=S3FileStorageHandle||method=init||fields={}||errMsg={}\", this, e.getMessage());\n        }\n    }\n\n    @Override\n    public synchronized Result<String> upload(String fileName, String fileMd5, MultipartFile uploadFile) {\n        InputStream inputStream = null;\n        try {\n            if (!createBucketIfNotExist()) {\n                return Result.build(Boolean.FALSE, \"\");\n            }\n\n            if (this.getFileNames().contains(fileName)) {\n                return Result.buildFail(\"fileName has existed,please modify!\");\n            }\n\n            inputStream = uploadFile.getInputStream();\n            minioClient.putObject(PutObjectArgs.builder().bucket(this.bucket).object(fileName)\n                .stream(inputStream, inputStream.available(), -1).build());\n            String url = minioClient.getObjectUrl(bucket, fileName);\n            return Result.build(Boolean.TRUE, url);\n        } catch (Exception e) {\n            LOGGER.error(\"class=S3FileStorageHandle||method=upload||fileName={}||errMsg={}||msg=upload failed\",\n                fileName, e.getMessage());\n        } finally {\n            if (inputStream != null) {\n                try {\n                    inputStream.close();\n                } catch (IOException e) {\n                    LOGGER.error(\n                        \"class=S3FileStorageHandle||method=upload||fileName={}||errMsg={}||msg=inputStream close failed\",\n                        fileName, e.getMessage());\n                }\n            }\n        }\n        return Result.build(Boolean.FALSE, \"\");\n    }\n\n    @Override\n    public synchronized Result<Void> remove(String fileName) {\n        try {\n            minioClient.removeObject(RemoveObjectArgs.builder().bucket(this.bucket).object(fileName).build());\n            return Result.buildSucc();\n        } catch (Exception e) {\n            LOGGER.error(\"class=S3FileStorageHandle||method=remove||fileName={}||errMsg={}||msg=upload failed\",\n                fileName, e.getMessage());\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public Result<MultipartFile> download(String fileName) {\n        try {\n            final ObjectStat stat = minioClient\n                .statObject(StatObjectArgs.builder().bucket(this.bucket).object(fileName).build());\n\n            InputStream is = minioClient\n                .getObject(GetObjectArgs.builder().bucket(this.bucket).object(fileName).build());\n            return Result.buildSucc(new MockMultipartFile(fileName, fileName, stat.contentType(), is));\n        } catch (Exception e) {\n            LOGGER.error(\"class=S3FileStorageHandle||method=download||fileName={}||errMsg={}||msg=download failed\",\n                fileName, e.getMessage());\n        }\n        return Result.build(ResultType.STORAGE_DOWNLOAD_FILE_FAILED);\n    }\n\n    @Override\n    public String getDownloadBaseUrl() {\n        if (this.endpoint.startsWith(\"http://\")) {\n            return this.endpoint + \"/\" + this.bucket;\n        }\n        return \"http://\" + this.endpoint + \"/\" + this.bucket;\n    }\n\n    private boolean createBucketIfNotExist() {\n        try {\n            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(this.bucket).build());\n            if (!found) {\n                minioClient.makeBucket(MakeBucketArgs.builder().bucket(this.bucket).build());\n            }\n\n            LOGGER.info(\n                \"class=S3FileStorageHandle||method=createBucketIfNotExist||bucket={}||msg=check and create bucket success\",\n                this.bucket);\n            return true;\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=S3FileStorageHandle||method=createBucketIfNotExist||bucket={}||errMsg={}||msg=create bucket failed\",\n                this.bucket, e.getMessage());\n        }\n        return false;\n    }\n\n    @Override\n    public String toString() {\n        return \"S3Service{\" + \"endpoint='\" + endpoint + '\\'' + \", accessKey='\" + accessKey + '\\'' + \", secretKey='\"\n               + secretKey + '\\'' + \", bucket='\" + bucket + '\\'' + '}';\n    }\n\n    /**\n     * 获取指定存储桶下的文件名称列表\n     * @return fileNamesOfBucket List<String>\n     */\n    private List<String> getFileNames() {\n        Iterable<io.minio.Result<Item>> results = minioClient\n            .listObjects(ListObjectsArgs.builder().bucket(this.bucket).build());\n        List<String> fileNamesOfBucket = Lists.newArrayList();\n        results.forEach(itemResult -> {\n            try {\n                fileNamesOfBucket.add(itemResult.get().objectName());\n            } catch (Exception e) {\n                LOGGER.warn(\"class=S3FileStorageHandle||method=getFileNames||bucket={}||warnMsg={}\", this.bucket,\n                    e.getMessage());\n            }\n        });\n        return fileNamesOfBucket;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/zeus/ZeusClusterRemoteService.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.zeus;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmOperateAppBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmSubTaskLog;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmTaskStatus;\n\npublic interface ZeusClusterRemoteService {\n    Result<EcmOperateAppBase> createTask(List<String> hostList, String args);\n\n    /**\n     * 部署 or 继续部署 宙斯集群\n     * @param taskId  宙斯任务Id\n     * @param action  部署动作\n     * start    开始\n     * pause    暂停createTask\n     * kill     结束\n     * cancel   撤销\n     *\n     * @return Result\n     */\n    Result<Object> actionTask(Integer taskId, String action);\n\n    /**\n     * 部署 or 继续部署 宙斯集群\n     * @param taskId  宙斯任务Id\n     * @param hostname 主机名称\n     * @param action  部署动作\n     * @return Result\n     */\n    Result<Object> actionHostTask(Integer taskId, String hostname, String action);\n\n    /**\n     *  获取 宙斯任务部署 结果\n     * @param taskId  宙斯任务Id\n     * @return Result\n     */\n    Result<List<EcmTaskStatus>> getZeusTaskStatus(Integer taskId);\n\n    /**\n     *  获取 宙斯任务部署 日志\n     * @param taskId   宙斯任务Id\n     * @param hostname 主机名称\n     * @return Result\n     */\n    Result<EcmSubTaskLog> getTaskLog(Integer taskId, String hostname);\n\n    /**\n     *  获取 宙斯部署 ip列表\n     * @return Result\n     */\n    Result<List<String>> getAgentsList();\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/zeus/ZeusClusterRemoteServiceImpl.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.zeus;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmCreateApp;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmOperateAppBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmSubTaskLog;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmTaskStatus;\nimport com.didichuxing.datachannel.arius.admin.common.util.BaseHttpUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.*;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.request.ZeusCreateTaskParam;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\n@Service\n@NoArgsConstructor\npublic class ZeusClusterRemoteServiceImpl implements ZeusClusterRemoteService {\n    private static final ILog LOGGER   = LogFactory.getLog(ZeusClusterRemoteServiceImpl.class);\n\n    @Value(\"${zeus.server}\")\n    private String              zeusServer;\n\n    @Value(\"${zeus.token}\")\n    private String              zeusToken;\n\n    @Value(\"${zeus.templateId}\")\n    private Integer             zeusTemplateIdId;\n\n    @Value(\"${zeus.user}\")\n    private String              zeusUser;\n\n    @Value(\"${zeus.batch}\")\n    private Integer             zeusBatch;\n\n    @Value(\"${zeus.timeOut}\")\n    private Integer             zeusTimeOut;\n\n    @Value(\"${zeus.tolerance}\")\n    private Integer             zeusTolerance;\n\n    private static final String API_TASK = \"/api/task/\";\n\n    private static final String API_AGENTS_LIST = \"/api/agents-list\";\n\n    @Override\n    public Result<EcmOperateAppBase> createTask(List<String> hostList, String args) {\n        ZeusCreateTaskParam zeusCreateTaskParam = buildCreateZeusTaskParam(hostList, args);\n\n        String url = zeusServer + \"/api/task?token=\" + zeusToken;\n        String response = null;\n        try {\n            LOGGER.info(\"class=ZeusClusterRemoteServiceImpl||method=createTask||params={}\", zeusCreateTaskParam);\n            response = BaseHttpUtil.postForString(url, JSON.toJSONString(zeusCreateTaskParam), buildHeader());\n\n            Result<Object> createResult = convert2Result(JSON.parseObject(response, ZeusResult.class));\n            if (createResult.failed()) {\n                return Result.buildFail(createResult.getMessage());\n            }\n            return Result.buildSucc(new EcmCreateApp(Integer.valueOf(createResult.getData().toString()), hostList));\n        } catch (Exception e) {\n            LOGGER.error(\"class=ZeusClusterRemoteServiceImpl||method=createTask||params={}||response={}||error={}\",\n                zeusCreateTaskParam, response, e.getMessage());\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public Result<Object> actionTask(Integer taskId, String action) {\n        Map<String, Object> params = Maps.newHashMap();\n        params.put(\"task_id\", taskId);\n        params.put(\"action\", action);\n\n        String url = zeusServer + \"/api/task/action?token=\" + zeusToken;\n        String response = null;\n        try {\n            LOGGER.info(\"class=ZeusClusterRemoteServiceImpl||method=actionTask||taskId={}||action={}\", taskId, action);\n\n            response = BaseHttpUtil.postForString(url, JSON.toJSONString(params), null);\n\n            return convert2Result(JSON.parseObject(response, ZeusResult.class));\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=ZeusClusterRemoteServiceImpl||method=actionTask||taskId={}||action={}||response={}||error={}\",\n                taskId, action, response, e.getMessage());\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public Result<Object> actionHostTask(Integer taskId, String hostname, String action) {\n        Map<String, Object> params = Maps.newHashMap();\n        params.put(\"task_id\", taskId);\n        params.put(\"hostname\", hostname);\n        params.put(\"action\", action);\n\n        String url = zeusServer + \"/api/task/host-action?token=\" + zeusToken;\n        String response = null;\n        try {\n            LOGGER.info(\"class=ZeusClusterRemoteServiceImpl||method=actionHostTask||taskId={}||hostname={}||action={}\",\n                taskId, hostname, action);\n\n            response = BaseHttpUtil.postForString(url, JSON.toJSONString(params), buildHeader());\n\n            return convert2Result(JSON.parseObject(response, ZeusResult.class));\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=ZeusClusterRemoteServiceImpl||method=actionTask||taskId={}||hostname={}||action={}||response={}||error={}\",\n                taskId, hostname, action, response, e.getMessage());\n        }\n        return Result.buildFail();\n    }\n\n    @Override\n    public Result<List<EcmTaskStatus>> getZeusTaskStatus(Integer taskId) {\n        String url = zeusServer + API_TASK + taskId + \"/result\";\n\n        String response = null;\n        try {\n            LOGGER.info(\"class=ZeusClusterRemoteServiceImpl||method=getZeusTaskStatus||taskId={}\", taskId);\n\n            response = BaseHttpUtil.get(url, null);\n\n            ZeusResult zeusResult = JSON.parseObject(response, ZeusResult.class);\n            if (zeusResult.failed()) {\n                LOGGER.error(\"class=ZeusClusterRemoteServiceImpl||method=getZeusTaskStatus||taskId={}||response={}\",\n                    taskId, response);\n                return Result.buildFail(zeusResult.getMsg());\n            }\n\n            ZeusTaskStatus zeusTaskStatus = JSON.parseObject(JSON.toJSONString(zeusResult.getData()),\n                ZeusTaskStatus.class);\n            return Result.buildSucc(zeusTaskStatus.convert2EcmHostStatusEnumList(taskId));\n        } catch (Exception e) {\n            LOGGER.error(\"class=ZeusClusterRemoteServiceImpl||method=getZeusTaskStatus||taskId={}response={}||error={}\",\n                taskId, response, e.getMessage());\n        }\n        return Result.buildFail(response);\n    }\n\n    @Override\n    public Result<EcmSubTaskLog> getTaskLog(Integer taskId, String hostname) {\n        Result<String> stdoutResult = getTaskStdOutLog(taskId, hostname);\n        Result<String> stderrResult = getTaskStdErrLog(taskId, hostname);\n        if (stderrResult.failed() && stdoutResult.failed()) {\n            return Result.buildFail();\n        }\n        return Result.buildSucc(new EcmSubTaskLog(stdoutResult.getData(), stderrResult.getData()));\n    }\n\n    @Override\n    public Result<List<String>> getAgentsList(){\n        String url = zeusServer + API_AGENTS_LIST + \"?token=\" + zeusToken;\n        String  response = null;\n        try {\n            LOGGER.info(\"class=ZeusClusterRemoteServiceImpl||method=getAgentsList\");\n            response = BaseHttpUtil.get(url,null,buildHeader());\n            Result<Object> result = convert2Result(JSON.parseObject(response,ZeusResult.class));\n            if (result.failed()) {\n                return Result.buildFrom(result);\n            }\n            //获取Zeus的Agents列表并将获取zeus中的ip列表\n            ZeusAgentsList zeusAgentsList = JSON.parseObject(JSON.toJSONString(result.getData()),\n                    ZeusAgentsList.class);\n            List<String> ipList = zeusAgentsList.getDat().stream().map(ZeusDat::getIp).distinct().collect(Collectors.toList());\n            return Result.buildSucc(ipList);\n        } catch (Exception e) {\n            LOGGER.error(\n                    \"class=ZeusClusterRemoteServiceImpl||method=getAgentsList||response={}||error={}\",\n                     response, e.getMessage());\n        }\n        return Result.buildFail();\n    }\n\n    private Result<String> getTaskStdOutLog(Integer taskId, String hostname) {\n        String url = zeusServer + API_TASK + taskId + \"/stdouts.json?hostname=\" + hostname;\n        String response = null;\n        try {\n            LOGGER.info(\"class=ZeusClusterRemoteServiceImpl||method=getTaskStdOutLog||taskId={}||hostname={}\", taskId,\n                hostname);\n\n            response = BaseHttpUtil.get(url, null, buildHeader());\n\n            Result<Object> result = convert2Result(JSON.parseObject(response, ZeusResult.class));\n            if (result.failed()) {\n                return Result.buildFrom(result);\n            }\n            List<ZeusSubTaskLog> zeusSubTaskLogs = JSON.parseArray(JSON.toJSONString(result.getData()),\n                ZeusSubTaskLog.class);\n            if (zeusSubTaskLogs == null || zeusSubTaskLogs.isEmpty()) {\n                return Result.buildSuccWithMsg(\"\");\n            }\n            return Result.buildSucc(zeusSubTaskLogs.get(0).getStdout(), \"\");\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=ZeusClusterRemoteServiceImpl||method=getTaskStdOutLog||taskId={}||hostname={}||response={}||error={}\",\n                taskId, hostname, response, e.getMessage());\n        }\n        return Result.buildFail();\n    }\n\n    private Result<String> getTaskStdErrLog(Integer taskId, String hostname) {\n        String url = zeusServer + API_TASK + taskId + \"/stderrs.json?hostname=\" + hostname;\n        String response = null;\n        try {\n            LOGGER.info(\"class=ZeusClusterRemoteServiceImpl||method=getTaskStdErrLog||taskId={}||hostname={}\", taskId,\n                hostname);\n\n            response = BaseHttpUtil.get(url, null, buildHeader());\n\n            Result<Object> result = convert2Result(JSON.parseObject(response, ZeusResult.class));\n            if (result.failed()) {\n                return Result.buildFrom(result);\n            }\n            List<ZeusSubTaskLog> zeusSubTaskLogs = JSON.parseArray(JSON.toJSONString(result.getData()),\n                ZeusSubTaskLog.class);\n            if (zeusSubTaskLogs == null || zeusSubTaskLogs.isEmpty()) {\n                return Result.buildSuccWithMsg(\"\");\n            }\n            return Result.buildSucc(zeusSubTaskLogs.get(0).getStderr(), \"\");\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=ZeusClusterRemoteServiceImpl||method=getTaskStdErrLog||taskId={}||hostname={}||response={}||error={}\",\n                taskId, hostname, response, e.getMessage());\n        }\n        return Result.buildFail();\n    }\n\n    private Result<Object> convert2Result(ZeusResult zeusResult) {\n        if (zeusResult.failed()) {\n            return Result.buildFail(zeusResult.getMsg());\n        }\n        return Result.buildSucc(zeusResult.getData());\n    }\n\n    private Map<String, String> buildHeader() {\n        Map<String, String> headers = Maps.newHashMap();\n        headers.put(\"Content-Type\", \"application/json\");\n        return headers;\n    }\n\n    private ZeusCreateTaskParam buildCreateZeusTaskParam(List<String> hostList, String args) {\n        ZeusCreateTaskParam zeusCreateTaskParam = new ZeusCreateTaskParam();\n        zeusCreateTaskParam.setTpl_id(zeusTemplateIdId);\n        zeusCreateTaskParam.setAccount(zeusUser);\n        zeusCreateTaskParam.setHosts(hostList);\n        zeusCreateTaskParam.setBatch(zeusBatch);\n        zeusCreateTaskParam.setTolerance(zeusTolerance);\n        zeusCreateTaskParam.setPause(getPauseHosts(hostList));\n        zeusCreateTaskParam.setTimeout(zeusTimeOut);\n        zeusCreateTaskParam.setArgs(args);\n        return zeusCreateTaskParam;\n    }\n\n    /**\n     * 根据传入的主机列表设计暂停点，便于线上机器部署，设置的是2个机器为一组\n     */\n    private String getPauseHosts(List<String> hostList) {\n        List<String> pauseHosts = Lists.newArrayList();\n        for (int count = 0; count < hostList.size(); count = count + zeusBatch) {\n            pauseHosts.add(hostList.get(count));\n        }\n        return ListUtils.strList2String(pauseHosts);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/zeus/bean/ZeusAgentsList.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.zeus.bean;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ZeusAgentsList {\n    private List<ZeusDat> dat;\n\n    private Integer total;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/zeus/bean/ZeusDat.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.zeus.bean;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ZeusDat {\n    private String ident;\n\n    private String ip;\n\n    private String ts;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/zeus/bean/ZeusResult.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.zeus.bean;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ZeusResult {\n    private Object data;\n\n    private String msg;\n\n    public boolean failed() {\n        if (msg == null || msg.isEmpty()) {\n            return false;\n        }\n        return true;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/zeus/bean/ZeusSubTaskLog.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.zeus.bean;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ZeusSubTaskLog {\n    private String hostname;\n\n    private String stdout;\n\n    private String stderr;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/zeus/bean/ZeusTaskStatus.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.zeus.bean;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmTaskStatus;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmHostStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class ZeusTaskStatus {\n    private List<String> success;\n\n    private List<String> failed;\n\n    private List<String> running;\n\n    private List<String> waiting;\n\n    private List<String> timeout;\n\n    private List<String> killing;\n\n    private List<String> kill_failed;\n\n    private List<String> cancelled;\n\n    private List<String> ignored;\n\n    public List<EcmTaskStatus> convert2EcmHostStatusEnumList(Integer taskId) {\n        List<EcmTaskStatus> statusList = new ArrayList<>();\n        if (!AriusObjUtils.isEmptyList(success)) {\n            handleSuccess(taskId, statusList);\n        }\n        if (!AriusObjUtils.isEmptyList(failed)) {\n            handleFailed(taskId, statusList);\n        }\n        if (!AriusObjUtils.isEmptyList(running)) {\n            handleRunning(taskId, statusList);\n        }\n        if (!AriusObjUtils.isEmptyList(waiting)) {\n            handleWaiting(taskId, statusList);\n        }\n        if (!AriusObjUtils.isEmptyList(timeout)) {\n            handleTimeout(taskId, statusList);\n        }\n        if (!AriusObjUtils.isEmptyList(killing)) {\n            handleKilling(taskId, statusList);\n        }\n        if (!AriusObjUtils.isEmptyList(kill_failed)) {\n            handleKillFailed(taskId, statusList);\n        }\n        if (!AriusObjUtils.isEmptyList(cancelled)) {\n            handleCancelled(taskId, statusList);\n        }\n        if (!AriusObjUtils.isEmptyList(ignored)) {\n            handleIgnored(taskId, statusList);\n        }\n        return statusList;\n    }\n\n    private void handleCancelled(Integer taskId, List<EcmTaskStatus> statusList) {\n        for (String hostname : cancelled) {\n            EcmTaskStatus ecmTaskStatus = new EcmTaskStatus();\n            ecmTaskStatus.setTaskId(taskId);\n            ecmTaskStatus.setHostname(hostname);\n            ecmTaskStatus.setStatusEnum(EcmHostStatusEnum.CANCELLED);\n            statusList.add(ecmTaskStatus);\n        }\n    }\n\n    private void handleIgnored(Integer taskId, List<EcmTaskStatus> statusList) {\n        for (String hostname : ignored) {\n            EcmTaskStatus ecmTaskStatus = new EcmTaskStatus();\n            ecmTaskStatus.setTaskId(taskId);\n            ecmTaskStatus.setHostname(hostname);\n            ecmTaskStatus.setStatusEnum(EcmHostStatusEnum.IGNORE);\n            statusList.add(ecmTaskStatus);\n        }\n    }\n\n    private void handleKillFailed(Integer taskId, List<EcmTaskStatus> statusList) {\n        for (String hostname : kill_failed) {\n            EcmTaskStatus ecmTaskStatus = new EcmTaskStatus();\n            ecmTaskStatus.setTaskId(taskId);\n            ecmTaskStatus.setHostname(hostname);\n            ecmTaskStatus.setStatusEnum(EcmHostStatusEnum.KILL_FAILED);\n            statusList.add(ecmTaskStatus);\n        }\n    }\n\n    private void handleKilling(Integer taskId, List<EcmTaskStatus> statusList) {\n        for (String hostname : killing) {\n            EcmTaskStatus ecmTaskStatus = new EcmTaskStatus();\n            ecmTaskStatus.setTaskId(taskId);\n            ecmTaskStatus.setHostname(hostname);\n            ecmTaskStatus.setStatusEnum(EcmHostStatusEnum.KILLING);\n            statusList.add(ecmTaskStatus);\n        }\n    }\n\n    private void handleTimeout(Integer taskId, List<EcmTaskStatus> statusList) {\n        for (String hostname : timeout) {\n            EcmTaskStatus ecmTaskStatus = new EcmTaskStatus();\n            ecmTaskStatus.setTaskId(taskId);\n            ecmTaskStatus.setHostname(hostname);\n            ecmTaskStatus.setStatusEnum(EcmHostStatusEnum.TIMEOUT);\n            statusList.add(ecmTaskStatus);\n        }\n    }\n\n    private void handleWaiting(Integer taskId, List<EcmTaskStatus> statusList) {\n        for (String hostname : waiting) {\n            EcmTaskStatus ecmTaskStatus = new EcmTaskStatus();\n            ecmTaskStatus.setTaskId(taskId);\n            ecmTaskStatus.setHostname(hostname);\n            ecmTaskStatus.setStatusEnum(EcmHostStatusEnum.WAITING);\n            statusList.add(ecmTaskStatus);\n        }\n    }\n\n    private void handleRunning(Integer taskId, List<EcmTaskStatus> statusList) {\n        for (String hostname : running) {\n            EcmTaskStatus ecmTaskStatus = new EcmTaskStatus();\n            ecmTaskStatus.setTaskId(taskId);\n            ecmTaskStatus.setHostname(hostname);\n            ecmTaskStatus.setStatusEnum(EcmHostStatusEnum.RUNNING);\n            statusList.add(ecmTaskStatus);\n        }\n    }\n\n    private void handleFailed(Integer taskId, List<EcmTaskStatus> statusList) {\n        for (String hostname : failed) {\n            EcmTaskStatus ecmTaskStatus = new EcmTaskStatus();\n            ecmTaskStatus.setTaskId(taskId);\n            ecmTaskStatus.setHostname(hostname);\n            ecmTaskStatus.setStatusEnum(EcmHostStatusEnum.FAILED);\n            statusList.add(ecmTaskStatus);\n        }\n    }\n\n    private void handleSuccess(Integer taskId, List<EcmTaskStatus> statusList) {\n        for (String hostname : success) {\n            EcmTaskStatus ecmTaskStatus = new EcmTaskStatus();\n            ecmTaskStatus.setTaskId(taskId);\n            ecmTaskStatus.setHostname(hostname);\n            ecmTaskStatus.setStatusEnum(EcmHostStatusEnum.SUCCESS);\n            statusList.add(ecmTaskStatus);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/zeus/bean/constant/EcmActionEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant;\n\npublic enum EcmActionEnum {\n                           START(\"start\"),\n                           //    SCALE(\"scale\"),\n                           //    UPGRADE(\"upgrade\"),\n                           //    RESTART(\"restart\"),\n                           REMOVE(\"remove\"),\n                           //    MODIFY(\"modify\"),\n\n                           PAUSE(\"pause\"), CONTINUE(\"continue\"), REDO_FAILED(\"redo\"), SKIP_FAILED(\"ignore\"), CANCEL(\"cancel\")\n\n    ;\n\n    private String action;\n\n    EcmActionEnum(String action) {\n        this.action = action;\n    }\n\n    public String getAction() {\n        return action;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/zeus/bean/constant/ZeusClusterActionEnum.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant;\n\n/**\n * 宙斯物理集群操作动作枚举类型\n * new  创建\n * expand  扩容  shrink 缩容\n * restart  重启\n * @author didi\n * @date 2020/9/18\n */\npublic enum ZeusClusterActionEnum {\n                                   NEW(\"new\"),\n\n                                   EXPAND(\"expand\"),\n\n                                   SHRINK(\"shrink\"),\n\n                                   UPDATE(\"deploy\"),\n\n                                   RESTART(\"restart\");\n\n    private String value;\n\n    ZeusClusterActionEnum(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public static ZeusClusterActionEnum valueFrom(String value) {\n        if (value == null) {\n            return null;\n        }\n        for (ZeusClusterActionEnum state : ZeusClusterActionEnum.values()) {\n            if (state.getValue().equals(value)) {\n                return state;\n            }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-remote/src/main/java/com/didichuxing/datachannel/arius/admin/remote/zeus/bean/request/ZeusCreateTaskParam.java",
    "content": "package com.didichuxing.datachannel.arius.admin.remote.zeus.bean.request;\n\nimport io.swagger.annotations.ApiModel;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\n@ApiModel(description = \"新建宙斯任务参数\")\npublic class ZeusCreateTaskParam {\n\n    /**\n     * 宙斯环境模板Id\n     */\n    private Integer      tpl_id;\n\n    /**\n     * 宙斯环境 账号\n     */\n    private String       account;\n\n    /**\n     * 主机名称 集合\n     */\n    private List<String> hosts;\n    /**\n     * 并发度，默认是0，表示全并发执行，1表示顺序执行，2表示每次执行2台\n     */\n    private Integer      batch;\n\n    /**\n     * 容忍几台机器失败，默认是0，表示一台都不容忍，只要失败了，立马暂停\n     */\n    private Integer      tolerance;\n\n    /**\n     * 暂停点 入参为机器hostname\n     */\n    private String       pause;\n\n    /**\n     * 单机脚本执行的超时时间，单位：秒\n     */\n    private Integer      timeout;\n\n    /**\n     * 附于脚本之后的参数，多个参数之间用双逗号,,分隔，比如arg1,,arg 2,,arg3\n     */\n    private String       args;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/APP_META/990-startapp.required.sh",
    "content": "#!/bin/bash\n\nSERVICE_PATH=\"/home/xiaoju/${APPNAME}\"\n\n#nginx logs ln\nif [ ! -L /home/xiaoju/nginx/logs ]; then\n    rm -rf /home/xiaoju/nginx/logs\n    mkdir -p /home/xiaoju/data1/nginx-logs && \\\n    ln -s /home/xiaoju/data1/nginx-logs /home/xiaoju/nginx/logs\nfi\n\nif [ -f \"/home/xiaoju/$APPNAME/.deploy/service.json\" ]; then\n    # cp service.json for nginx metric collect.\n    su xiaoju -c \"mkdir -p /home/xiaoju/nginx/.deploy && cp /home/xiaoju/$APPNAME/.deploy/service.json /home/xiaoju/nginx/.deploy\"\nfi\n\nif [[ \"x$env\" == \"xtest\" || \"x$env\" == \"xpressure\" || \"x$env\" == \"xstable\" ]] && [ ! -f \"/home/xiaoju/$APPNAME/.deploy/service.cluster.txt\" ]; then\n    su xiaoju -c \"mkdir -p /home/xiaoju/$APPNAME/.deploy && touch /home/xiaoju/$APPNAME/.deploy/service.cluster.txt && echo $env >> /home/xiaoju/$APPNAME/.deploy/service.cluster.txt\"\n    su logger -c \"touch /home/logger/swan-log-collector/var/crtfile &&  sh /home/logger/swan-log-collector/bin/stop.sh\"\nfi\n\n#tomcat logs ln\nif [ ! -L /home/xiaoju/tomcat/logs ]; then\n    rm -rf /home/xiaoju/tomcat/logs\n    mkdir -p /home/xiaoju/data1/tomcat-logs && \\\n    ln -s /home/xiaoju/data1/tomcat-logs /home/xiaoju/tomcat/logs\nfi\n\n#application logs ln\nif [ ! -L /home/xiaoju/${APPNAME}/logs ]; then\n    mkdir -p /home/xiaoju/data1/${APPNAME}-logs && \\\n    ln -s /home/xiaoju/data1/${APPNAME}-logs /home/xiaoju/${APPNAME}/logs\nfi\n\nif [ ! -L /data1 ]; then\n    ln -s /home/xiaoju/data1 /data1\nfi\n\nchown -R  xiaoju.xiaoju /home/xiaoju/data1/\nchown -R  xiaoju.xiaoju /data1/\n\nmkdir -p '/etc/odin-super-agent/'; echo 'consul-client' >> /etc/odin-super-agent/agents.deny; chmod +x /home/odin/super-agent/data/install/consul-client/current/control &&  /home/odin/super-agent/data/install/consul-client/current/control stop\nsudo su - xiaoju -c \"cd $SERVICE_PATH && chmod +x control.sh && ./control.sh start\"\n\n/usr/bin/monit -c /etc/monitrc\n\nif [[ \"x$env\" == \"xtest\" || \"x$env\" == \"xstable\" || \"x$env\" == \"xpressure\" ]]; then\n    /usr/sbin/sshd -D\nfi\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/APP_META/990-stopapp.sh",
    "content": "#!/bin/bash\n\nSERVICE_PATH=\"/home/xiaoju/${APPNAME}\"\n\n/usr/bin/monit stop all\n\nsu xiaoju -c \"cd $SERVICE_PATH && ./control.sh stop\"\n\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/APP_META/990-webterminal.sh",
    "content": "#!/bin/bash\n\n# start web-terminal\nif [[ \"x$env\" == \"xtest\" || \"x$env\" == \"xstable\" || \"x$env\" == \"xpressure\" ]] ; then\n    # prepare web-terminal environment\n    mkdir -p /home/xiaoju/local\n    curl --connect-timeout 5 -m 30 -o /home/xiaoju/local/node-v8.9.4-linux-x64-web-terminal.tar.gz https://artifactory.intra.xiaojukeji.com:443/artifactory/oe-release-local/webterminal/node-v8.9.4-linux-x64-web-terminal.tar.gz\n    export PATH=/home/xiaoju/local/node-v8.9.4-linux-x64-web-terminal/bin:$PATH\n    cd /home/xiaoju/local && tar xvzf node-v8.9.4-linux-x64-web-terminal.tar.gz\n    cd /home/xiaoju/local/node-v8.9.4-linux-x64-web-terminal/web-terminal-client && pm2 start pm2_deploy.json\n    cd /home/xiaoju/local/node-v8.9.4-linux-x64-web-terminal/web-terminal-monit && pm2 start pm2_deploy.json\nelse\n    echo \"skip install web-terminal service on prod env\"\nfi\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/APP_META/Dockerfile",
    "content": "FROM registry.xiaojukeji.com/didionline/bigdatadatabus-didi-jdk8-tomcat-nginx-centos6:stable\nMAINTAINER zhuyefeng <zhuyefeng@didichuxing.com>\n\nENV JAVA_HOME /usr/local/jdk1.8.0_65\n# 设置模块名字\nENV APPNAME arius-admin-rest\n\nRUN mkdir -p /etc/container/prestop\nADD ./APP_META/nginx/conf/nginx.conf /home/xiaoju/nginx/conf/\nADD ./APP_META/monit/monitrc /etc/monitrc\nADD ./APP_META/monit/nginx.cfg /etc/monit.d/\nADD ./APP_META/990-startapp.required.sh /etc/container/init/990-startapp.required.sh\nADD ./APP_META/990-stopapp.sh /etc/container/prestop/990-stopapp.sh\n\nRUN mkdir -p /home/xiaoju/${APPNAME} && \\\n    # 如果tomcat容器应用需要下面这步\n    # mkdir -p /home/xiaoju/tomcat/webapps && \\\n    chmod 0700 /etc/monitrc && \\\n    chmod a+x /etc/container/init/990-startapp.required.sh && \\\n    chmod a+x /etc/container/prestop/990-stopapp.sh\n\nCOPY ./home-xiaoju-${APPNAME} /home/xiaoju/${APPNAME}\n\nRUN yum install mysql\n\n# 如果tomcat容器应用需要下面这步\n#RUN ln -s /home/xiaoju/${APPNAME} /home/xiaoju/tomcat/webapps/\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/APP_META/DockerfileOffline",
    "content": "FROM registry.xiaojukeji.com/didionline/bigdatadatabus-didi-jdk8-tomcat-nginx-centos7:stable\nMAINTAINER zhuyefeng <zhuyefeng@didichuxing.com>\n\nENV JAVA_HOME /usr/local/jdk1.8.0_65\n# 设置模块名字\nENV APPNAME arius-admin-rest\n\nRUN mkdir -p /etc/container/prestop\nADD ./APP_META/nginx/conf/nginx.conf /home/xiaoju/nginx/conf/ \nADD ./APP_META/990-startapp.required.sh /etc/container/init/990-startapp.required.sh\nADD ./APP_META/990-stopapp.sh /etc/container/prestop/990-stopapp.sh\nADD ./APP_META/990-webterminal.sh  /etc/container/init/990-webterminal.required.sh\n\nRUN rpm --rebuilddb && yum --enablerepo=didi_op_toa install -y openssh-server openssl-devel passwd\nRUN sed -i 's/#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config && \\\n    echo -e 'y\\n' | ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N '' && \\\n    echo -e 'y\\n' | ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' && \\\n    mkdir -p /var/run/sshd\n\nRUN mkdir -p /home/xiaoju/${APPNAME} && \\\n    # 如果tomcat容器应用需要下面这步\n    # mkdir -p /home/xiaoju/tomcat/webapps && \\\n    chmod a+x /etc/container/init/990-startapp.required.sh && \\\n    chmod a+x /etc/container/prestop/990-stopapp.sh && \\\n    chmod a+x /etc/container/init/990-webterminal.required.sh\n\n#COPY ./home-xiaoju-${APPNAME} /home/xiaoju/${APPNAME}\nCOPY . /home/xiaoju/${APPNAME}\n\n# 如果tomcat容器应用需要下面这步\n#RUN ln -s /home/xiaoju/${APPNAME} /home/xiaoju/tomcat/webapps/\n\nRUN echo -e 'diditest@bdt\\ndiditest@bdt' | passwd root\nexpose 22\n\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/APP_META/clean_nginx_log.sh",
    "content": "log_dir=\"/home/xiaoju/nginx/logs\"\ndate=`date +%Y%m%d`\ndate_rm=`date +%Y%m%d -d '3 days ago'`\nmv ${log_dir}/access.log  ${log_dir}/${date}_access.log\n/home/xiaoju/nginx/sbin/nginx -s reopen\nrm -f ${log_dir}/${date_rm}_access.log"
  },
  {
    "path": "arius-admin/arius-admin-rest/APP_META/monit/monitrc",
    "content": "set daemon  10              # check services at 10 seconds intervals\nset log syslog\n\nset httpd port 2812 and\n    use address localhost  # only accept connection from localhost\n    allow localhost        # allow localhost to connect to the server and\n    allow admin:monit      # require user 'admin' with password 'monit'\n    #with ssl {            # enable SSL/TLS and set path to server certificate\n    #    pemfile: /etc/ssl/certs/monit.pem\n    #}\n\ninclude /etc/monit.d/*\n\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/APP_META/monit/nginx.cfg",
    "content": "check process nginx with pidfile /home/xiaoju/nginx/run/nginx.pid\n       start = \"/etc/container/init/990-startapp.required.sh\" with timeout 15 seconds\n       stop  = \"/etc/container/prestop/990-stopapp.sh\" with timeout 60 seconds\n       group xiaoju\n       if failed\n          host 127.0.0.1\n          port 8010\n          type tcp\n          then exec \"/home/xiaoju/nginx/load.sh stop\"\n\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/APP_META/nginx/conf/nginx-pre-v3-cn.conf",
    "content": "#user xiaoju xiaoju;\n\nworker_rlimit_nofile 204800;\nworker_processes 4;\nerror_log /home/xiaoju/nginx/logs/error.log;\npid /home/xiaoju/nginx/run/nginx.pid;\n\n# Load dynamic modules. See /usr/share/nginx/README.dynamic.\ninclude /home/xiaoju/nginx/modules/*.conf;\n\n\nevents {\n    use epoll;\n    worker_connections  204800;\n\n    accept_mutex on;\n    accept_mutex_delay 5ms;\n    multi_accept on;\n}\n\n\nhttp {\n    include       mime.types;\n    default_type  application/octet-stream;\n\n    server_names_hash_bucket_size 128;\n    #server_tag off;\n    #server_info off;\n    server_tokens off;\n\n    sendfile        on;\n    tcp_nopush      on;\n    tcp_nodelay     on;\n\n    fastcgi_connect_timeout 5;\n    fastcgi_send_timeout 10;\n    fastcgi_read_timeout 10;\n    fastcgi_buffer_size 64k;\n    fastcgi_buffers 4 64k;\n    fastcgi_busy_buffers_size 128k;\n    fastcgi_temp_file_write_size 128k;\n\n    keepalive_timeout  60;\n    keepalive_requests 1024;\n    client_header_buffer_size 4k;\n    large_client_header_buffers 4 32k;\n    client_max_body_size 1024m;\n\n    client_body_buffer_size 512k;\n    client_body_timeout 45;\n    client_header_timeout 10;\n    send_timeout 240;\n\n    proxy_connect_timeout   10s;\n    proxy_send_timeout      120s;\n    proxy_read_timeout      120s;\n    proxy_buffers           64 8k;\n    proxy_busy_buffers_size    128k;\n    proxy_temp_file_write_size 64k;\n    proxy_redirect off;\n    # proxy_next_upstream_tries 1;\n    proxy_next_upstream error invalid_header timeout http_502 http_504;\n\n    gzip on;\n    gzip_min_length 1k;\n    gzip_buffers 4 16k;\n    gzip_http_version 1.0;\n    gzip_comp_level 4;\n    gzip_types text/plain application/x-javascript text/css text/xml application/xml+css application/json text/javascript;\n    gzip_vary on;\n\n    proxy_set_header X-Real-IP $remote_addr;\n    proxy_set_header X-Real-Port $remote_port;\n    proxy_set_header Host $http_host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    proxy_pass_header Server;\n\n    #operationid on;\n    #operationid_header didi-header-rid;\n    #operationid_eth eth0;\n    #proxy_set_header didi-header-rid $operationid;\n\n    log_format main '$server_addr\\t$host\\t'\n        '$remote_addr\\t$http_x_forwarded_for\\t'\n        '$time_local\\t'\n        '$scheme\\t$request\\t'\n        '$status\\t$upstream_status\\t'\n        '$request_time\\t$upstream_addr\\t$upstream_response_time\\t'\n        '$request_length\\t$bytes_sent\\t'\n        '$http_referer\\t$http_cookie\\t$http_user_agent\\t'\n        '$limit_rate\\t$http_didi_header_omgid\\t$remote_port';\n\n\n    set_real_ip_from 10.0.0.0/8;\n    set_real_ip_from 100.64.0.0/10;\n    real_ip_header X-Real-IP;\n\n    server {\n        listen       8080 backlog=4096;\n        underscores_in_headers on;\n        server_name  localhost;\n        access_log logs/access.log main;\n\n        location /index.html {\n            proxy_pass http://10.88.128.23:8002/static/bp_fe_pre/bigdata_cloud_logi_es_manager_fe/gn/index.html;\n            proxy_hide_header Cache-Control;\n            add_header Cache-Control  \"no-cache\";\n        }\n\n        location / {\n            rewrite ^.*$ /index.html;\n        }\n\n        # gateway\n        location ~ ^/_sql {\n          proxy_pass http://10.85.129.96:20055;\n        }   \n\n        # admin\n        location ~ ^/api/es/admin/ {\n           rewrite ^/api/es/admin/(.*)$ /admin/api/$1 break;\n           proxy_pass http://127.0.0.1:8010;\n        }\n\n        # kibana\n        location ^~ /console/arius/kibana7/ {\n            proxy_set_header Upgrade $http_upgrade;\n            proxy_set_header Connection 'upgrade';\n            proxy_set_header Host $host;\n            proxy_set_header X-Real-IP $remote_addr;\n            proxy_set_header X-NginX-Proxy true;\n            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n            proxy_set_header Authorization 'Basic $cookie_Authorization';\n            proxy_pass_request_headers on;\n            proxy_cache_bypass $http_upgrade $http_authorization;\n            proxy_pass http://10.160.80.135:8061/;\n            rewrite ^/console/arius/kibana7/(.*)$ /console/arius/kibana7/$1 break;\n        }\n\n        location = /status.do {\n            root /home/xiaoju/nginx/html;\n        }\n\n        error_page   500 502 503 504  /50x.html;\n        location = /50x.html {\n            root   html;\n        }\n    }\n\n    include conf.d/*.conf;\n    #   include servers/*.conf;\n    #   include server_conf/*.conf;\n    #   include upstream_conf/*.conf;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/APP_META/nginx/conf/nginx.conf",
    "content": "#user xiaoju xiaoju;\n\nworker_rlimit_nofile 204800;\nworker_processes 4;\nerror_log /home/xiaoju/nginx/logs/error.log;\npid /home/xiaoju/nginx/run/nginx.pid;\n\n# Load dynamic modules. See /usr/share/nginx/README.dynamic.\ninclude /home/xiaoju/nginx/modules/*.conf;\n\n\nevents {\n    use epoll;\n    worker_connections  204800;\n\n    accept_mutex on;\n    accept_mutex_delay 5ms;\n    multi_accept on;\n}\n\n\nhttp {\n    include       mime.types;\n    default_type  application/octet-stream;\n\n    server_names_hash_bucket_size 128;\n    #server_tag off;\n    #server_info off;\n    server_tokens off;\n\n    sendfile        on;\n    tcp_nopush      on;\n    tcp_nodelay     on;\n\n    fastcgi_connect_timeout 5;\n    fastcgi_send_timeout 10;\n    fastcgi_read_timeout 10;\n    fastcgi_buffer_size 64k;\n    fastcgi_buffers 4 64k;\n    fastcgi_busy_buffers_size 128k;\n    fastcgi_temp_file_write_size 128k;\n\n    keepalive_timeout  60;\n    keepalive_requests 1024;\n    client_header_buffer_size 4k;\n    large_client_header_buffers 4 32k;\n    client_max_body_size 1024m;\n\n    client_body_buffer_size 512k;\n    client_body_timeout 45;\n    client_header_timeout 10;\n    send_timeout 240;\n\n    proxy_connect_timeout   10s;\n    proxy_send_timeout      120s;\n    proxy_read_timeout      120s;\n    proxy_buffers           64 8k;\n    proxy_busy_buffers_size    128k;\n    proxy_temp_file_write_size 64k;\n    proxy_redirect off;\n    # proxy_next_upstream_tries 1;\n    proxy_next_upstream error invalid_header timeout http_502 http_504;\n\n    gzip on;\n    gzip_min_length 1k;\n    gzip_buffers 4 16k;\n    gzip_http_version 1.0;\n    gzip_comp_level 2;\n    gzip_types text/plain application/x-javascript text/css text/xml application/xml+css application/json text/javascript;\n    gzip_vary on;\n\n    proxy_set_header X-Real-IP $remote_addr;\n    proxy_set_header X-Real-Port $remote_port;\n    proxy_set_header Host $http_host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    proxy_pass_header Server;\n\n    #operationid on;\n    #operationid_header didi-header-rid;\n    #operationid_eth eth0;\n    #proxy_set_header didi-header-rid $operationid;\n\n    log_format main '$server_addr\\t$host\\t'\n                 '$remote_addr\\t$http_x_forwarded_for\\t'\n                 '$time_local\\t'\n                 '$scheme\\t$request\\t'\n                 '$status\\t$upstream_status\\t'\n                 '$request_time\\t$upstream_addr\\t$upstream_response_time\\t'\n                 '$request_length\\t$bytes_sent\\t'\n                 '$http_referer\\t$http_cookie\\t$http_user_agent\\t'\n                 '$limit_rate\\t$http_didi_header_omgid\\t$remote_port';\n\n\n    set_real_ip_from 10.0.0.0/8;\n    set_real_ip_from 100.64.0.0/10;\n    real_ip_header X-Real-IP;\n\n    server {\n        listen       8080 backlog=4096;\n        server_name  localhost;\n        access_log logs/access.log main;\n\n        location = /status.do {\n          root /home/xiaoju/nginx/html;\n        }\n\n        # gateway\n        location ~ ^/_sql {\n          proxy_pass http://10.190.34.104:8200;\n        }\n\n        # admin\n        location ~ ^/api/es/admin/ {\n           rewrite ^/api/es/admin/(.*)$ /admin/api/$1 break;\n           proxy_pass http://127.0.0.1:8010;\n        }\n\n        # kibana\n        location ^~ /console/arius/kibana7/ {\n            proxy_set_header Upgrade $http_upgrade;\n            proxy_set_header Connection 'upgrade';\n            proxy_set_header Host $host;\n            proxy_set_header X-Real-IP $remote_addr;\n            proxy_set_header X-NginX-Proxy true;\n            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n            proxy_set_header Authorization 'Basic $cookie_Authorization';\n            proxy_pass_request_headers on;\n            proxy_cache_bypass $http_upgrade $http_authorization;\n            proxy_pass http://10.160.80.135:8061/;\n            rewrite ^/console/arius/kibana7/(.*)$ /console/arius/kibana7/$1 break;\n        }\n\n        location / {\n            proxy_pass http://127.0.0.1:8010;\n        }\n\n        error_page   500 502 503 504  /50x.html;\n        location = /50x.html {\n            root   html;\n        }\n    }\n\n     include conf.d/*.conf;\n #   include servers/*.conf;\n #   include server_conf/*.conf;\n #   include upstream_conf/*.conf;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/control.sh",
    "content": "#!/bin/bash\n#############################################\n## main\n## 非托管方式, 启动服务\n## control.sh脚本, 必须实现start和stop两个方法\n#############################################\nworkspace=$(cd $(dirname $0) && pwd -P)\ncd ${workspace}\n\n\nmodule=arius-admin-rest\napp=${module}\n\ncfgname=config\ncfg=\"$workspace/WEB-INF/classes/${cfgname}.properties\"\ncfgdir=\"$workspace/WEB-INF/classes\"\nlogfile=${workspace}/var/app.log\npidfile=${workspace}/var/app.pid\n#export CATALINA_PID=${pidfile}\n\n#nginx check\n#如果不需要nginx服务，请设置NGINX_CHECK=0\nNGINX_CHECK=1\nLOCAL_CHECK=0\nenv=online\nsource ./nginxfunc.sh\nnginx_conf=\"nginx.conf\"\n\n## function\nfunction start() {\n    # 创建日志目录\n    mkdir -p var &>/dev/null\n\n    rm -rf ${pidfile}\n\n    # check服务是否存活,如果存在则返回\n    check_pid\n    if [ $? -ne 0 ];then\n        local pid=$(get_pid)\n        echo \"${app} is started, pid=${pid}\"\n        return 0\n    fi\n\n    # XXX 如果各个机房节点级别有差异使用如下方式\n    # cfg\n    local clusterfile=\"$workspace/.deploy/service.cluster.txt\"\n    if [[ -f \"$clusterfile\" ]]; then\n        local cluster=`cat $clusterfile`\n        if [[ $cluster == \"hnb-pre-v\" ]]; then\n            env=pre\n        elif [[ $cluster == \"hnc-pre-v\" ]]; then\n            env=pre\n            nginx_conf=\"nginx-pre-v3-cn.conf\"\n        elif [[ \"x$cluster\" == \"xtest\" || \"x$cluster\" == \"xstable\" || \"x$cluster\" == \"xpressure\" ]]; then\n            env=$cluster\n        fi\n    else\n        echo \"$clusterfile is not existed!!!\"\n        exit 1\n    fi\n\n    # 以后台方式 启动程序\n    echo -e \"Starting the $module in $env...\\c\"\n\n    ### XXX JAVA类程序启停\n    echo \"start application with env:$env\"\n\n    if [[ $cluster == \"test\" ]]; then\n        nohup java -Xmx8g -Xms8g -Xmn3g -Dlog4j2.AsyncQueueFullPolicy=Discard -Dlog4j2.DiscardThreshold=ERROR -XX:MaxDirectMemorySize=2G -XX:MaxMetaspaceSize=256M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./logs/heapdump.hprof -Djdk.nio.maxCachedBufferSize=262144 -jar $module.jar --spring.profiles.active=$env &\n    else\n        nohup java -Xmx8g -Xms8g -Xmn3g -Dlog4j2.AsyncQueueFullPolicy=Discard -Dlog4j2.DiscardThreshold=ERROR -XX:MaxDirectMemorySize=2G -XX:MaxMetaspaceSize=256M -Djdk.nio.maxCachedBufferSize=262144 -jar $module.jar --spring.profiles.active=$env &\n    fi\n\n    # 保存pid到pidfile文件中\n    echo $! > ${pidfile}\n\n    # 检查服务是否启动成功\n    check_pid\n    if [ $? -eq 0 ];then\n        echo \"${app} start failed, please check!!!\"\n        exit 1\n    fi\n\n    echo \"${app} start ok, pid=${pid}\"\n    # 启动成功, 退出码为 0\n    return 0\n}\n\nfunction stop() {\n    local timeout=60\n    # 循环stop服务, 直至60s超时\n    for (( i = 0; i < $timeout; i++ )); do\n        # 检查服务是否停止,如果停止则直接返回\n        check_pid\n        if [ $? -eq 0 ];then\n            echo \"${app} is stopped\"\n            rm -rf ${pidfile}\n            return 0\n        fi\n        # 检查pid是否存在\n        local pid=$(get_pid)\n        if [ ${pid} == \"\" ];then\n            echo \"${app} is stopped, can't find pid on ${pidfile}\"\n            exit 0\n        fi\n\n        # 停止该服务\n        if [ $i -eq $((timeout-1)) ]; then\n            kill -9 ${pid} &>/dev/null\n        else\n            kill ${pid} &>/dev/null\n        fi\n        # 检查该服务是否停止ok\n        check_pid\n        if [ $? -eq 0 ];then\n            # stop服务成功, 返回码为 0\n            echo \"${app} stop ok\"\n            rm -rf ${pidfile}\n            exit 0\n        fi\n        # 服务未停止, 继续循环\n        sleep 1\n    done\n\n    rm -rf ${pidfile}\n\n    # stop服务失败, 返回码为 非0\n    echo \"stop timeout(${timeout}s)\"\n    return 1\n}\n\nfunction update() {\n    echo \"update service\"\n    exit 0\n}\n\nfunction status(){\n    check_pid\n    local running=$?\n    if [ ${running} -ne 0 ];then\n        local pid=$(get_pid)\n        echo \"${app} is started, pid=${pid}\"\n    else\n        echo \"${app} is stopped\"\n    fi\n    exit 0\n}\n\n## internals\nfunction get_pid() {\n    if [ -f $pidfile ];then\n        cat $pidfile\n        #pid=$(cat $pidfile | sed 's/ //g')\n        #(ps -fp $pid | grep $app &>/dev/null) && echo $pid\n    fi\n}\n\nfunction check_pid() {\n    pid=$(get_pid)\n    if [ \"x_\" != \"x_${pid}\" ]; then\n        running=$(ps -p ${pid}|grep -v \"PID TTY\" |wc -l)\n        return ${running}\n    fi\n    return 0\n}\n\naction=$1\ncase $action in\n    \"start\" )\n        # 启动服务\n        start\n        cp -f ./nginx/conf/${nginx_conf} ~/nginx/conf/nginx.conf\n        http_start\n        ;;\n    \"stop\" )\n        # 停止服务\n        http_stop\n        stop\n        ;;\n    \"status\" )\n        # 检查服务\n        status\n        ;;\n    \"update\" )\n        # 更新操作\n        update\n        ;;\n    * )\n        echo \"unknown command\"\n        exit 1\n        ;;\nesac\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/elevate/pipeline.3_test.yml",
    "content": "name: 3_test\nstages:\n  - name: 编译打包\n    jobs:\n      - name: compile-job-centos7.2\n        tasks:\n          - name: compile-task\n            type: oe-compile\n            params:\n              image: true\n              osType: centos7.2\n              env: test\n  - name: deploy-container\n    trigger: manual\n    jobs:\n      - name: deploy-container-job\n        tasks:\n          - name: deploy-container\n            type: oe-deploy:test\n            params:\n              flavor: T4\n              port: 8080\n              replicas: 1\n              domain: http://api-kylin-xg02.intra.xiaojukeji.com/bigdata_databus_arius_admin_v2_3_test_test\n              region: zjy02\n            variables:\n              env: test\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/elevate/pipeline.merge.yml",
    "content": "name: arius-admin-v2\nstages: \n    - name: Compile-stable\n      jobs:\n        - name: compile-job-stable\n          tasks:\n            - name: compile-stable\n              type: oe-compile\n              params:\n                image: true\n                osType: centos7.2\n                env: stable\n    - name: Deploy-stable\n      jobs:\n        - name: deploy-job-stable\n          tasks:\n            - name: deploy-stable\n              type: oe-deploy:stable\n              params:\n                flavor: T4\n                port: 8080\n                replicas: 1\n                env: stable\n                region: zjy02\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/elevate/pipeline.test.yml",
    "content": "name: arius-admin-v2\nstages: \n    - name: Compile-test\n      jobs: \n        - name: compile-job-test\n          tasks: \n            - name: compile-test\n              type: oe-compile\n              params: \n                image: true\n                osType: centos7.2\n                env: test\n    - name: Deploy-test\n      jobs: \n        - name: deploy-job-test\n          tasks: \n            - name: deploy-test\n              type: oe-deploy:test\n              params: \n                flavor: S2\n                port: 8080\n                replicas: 1\n                domain: http://api-kylin-xg02.intra.xiaojukeji.com/bigdata_databus_arius_admin_v2_test_test\n                region: zjy02\n            - name: 未命名串行子任务\n              type: oe-compile\n              params: \n                osType: centos6.7\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/elevate/pipeline.zhaoqingrong-dev.yml",
    "content": "name: arius-admin-v2-zhaoqingrong-dev\nstages: \n    - name: Compile-test\n      jobs: \n        - name: compile-job-test\n          tasks: \n            - name: compile-test\n              type: oe-compile\n              params: \n                image: true\n                osType: centos7.2\n                env: test\n    - name: Deploy-test\n      jobs: \n        - name: deploy-job-test\n          tasks: \n            - name: deploy-test\n              type: oe-deploy:test\n              params: \n                flavor: S2\n                port: 8080\n                replicas: 1\n                domain: http://api-kylin-xg02.intra.xiaojukeji.com/bigdata_databus_arius_admin_v2_zhaoqingrong_dev_test\n                region: hl\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/nginxfunc.sh",
    "content": "#!/usr/bin/env bash\n###########################################################################\n#  nginxfunc.sh\n#  实现http_start 、http_stop 方法用于启停nginx 以及 status.do文件rename\n##########################################################################\n\n\n\n#variables\nNGINX_PATH=\"/home/${USER}/nginx\"\nSTATUS_FILE=\"${NGINX_PATH}/html/status.do\"\nNGXPID_FILE=\"${NGINX_PATH}/run/nginx.pid\"\nNGXBIN_STOP=\"${NGINX_PATH}/load.sh stop\"\nNGXBIN_START=\"${NGINX_PATH}/load.sh start\"\nNGINX_URL=\"http://127.0.0.1:8080/status.do\"\nLOCAL_URL=\"http://127.0.0.1:8010/admin/api/health\"\n\n\nfunction rm_status_do() {\n    if [ -f ${STATUS_FILE} ];then\n        rm -rf ${STATUS_FILE}\n        if [ $? == 0 ];then\n            return 0;\n        else\n            exit 1;\n        fi\n    fi\n}\n\nfunction http_stop() {\n    local timeout=20\n    if [ ! -f ${NGXPID_FILE} ];then\n        echo \"Nginx is stop!\"\n    else\n        rm -rf ${STATUS_FILE}\n        echo \"Sleep [ 20 ] sec. Wait Inrouter Remove RS!\"\n        for((i=1;i<=$timeout;i++));do\n            sleep 1;\n            echo \"Sleep [ $i ] \"\n        done\n\n        $NGXBIN_STOP\n        if [ $? != 0 ]; then\n            echo \"Nginx stop failed!!!\"\n            exit 1\n        else\n            echo \"Nginx is stop!\"\n        fi\n    fi\n}\n\nfunction http_start() {\n\n    local timeout=120\n    local health=0\n    for (( i = 0; i < $timeout; i++ )); do\n        echo \"check tomcat health [ $i ] \"\n\n        local_check=$(curl -s --connect-timeout 3 --max-time 5 ${LOCAL_URL} -o /dev/null -w %{http_code})\n        if [ \"${local_check}\" == \"200\" ];then\n            echo \"Tomcat ${LOCAL_URL} 200 OK\"\n            health=1\n            break\n        fi\n\n        sleep 1s\n    done\n\n    if [ \"x$health\" == \"x0\" ]; then\n        echo \"Tomcat ${LOCAL_URL} failed in $timeout sec.\"\n        exit 1\n    fi\n\n    echo \"200 OK\" > ${STATUS_FILE}\n    if [[ ! -f ${NGXPID_FILE} ]];then\n        echo \"Nginx server starting!\"\n        ${NGXBIN_START}\n    else\n        echo \"Nginx server Running...\"\n    fi\n\n    sleep 1\n    nginx_status=$(curl -s --max-time 5 --retry-delay 2 --retry 5 ${NGINX_URL} -o /dev/null -w %{http_code})\n    if [ \"${nginx_status}\" == \"200\" ];then\n        echo \"Nginx ${NGINX_URL} 200 OK\"\n    else\n        echo \"Nginx ${NGINX_URL} curl Faild!\"\n        rm_status_do\n    fi\n}\n\nif [ -z ${APPNAME} ];then\n    function http_start(){\n        return 0;\n    }\n    function http_stop(){\n        return 0;\n    }\nfi\n\nif [ $NGINX_CHECK == 0 ];then\n    function http_start(){\n        return 0\n    }\n    function http_stop(){\n        return 0\n    }\nfi\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <artifactId>arius-admin</artifactId>\n        <version>${revision}${sha1}${changelist}</version>\n    </parent>\n\n    <artifactId>arius-admin-rest</artifactId>\n\n\n    <dependencies>\n    \n        <!-- https://mvnrepository.com/artifact/net.bytebuddy/byte-buddy -->\n        <dependency>\n            <groupId>net.bytebuddy</groupId>\n            <artifactId>byte-buddy</artifactId>\n            <version>1.9.10</version>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-junit-jupiter</artifactId>\n            <version>3.9.0</version>\n            <scope>test</scope>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.mockito</groupId>\n                    <artifactId>mockito-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n    \n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-inline</artifactId>\n            <version>3.9.0</version>\n            <scope>test</scope>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.mockito</groupId>\n                    <artifactId>mockito-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-core</artifactId>\n            <exclusions>\n                <exclusion>\n                    <artifactId>mybatis</artifactId>\n                    <groupId>org.mybatis</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-common</artifactId>\n            <exclusions>\n                <exclusion>\n                    <artifactId>mybatis</artifactId>\n                    <groupId>org.mybatis</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-task</artifactId>\n            <exclusions>\n                <exclusion>\n                    <artifactId>mybatis-spring</artifactId>\n                    <groupId>org.mybatis</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-biz</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-remote</artifactId>\n        </dependency>\n\n        <!-- https://mvnrepository.com/artifact/net.bytebuddy/byte-buddy -->\n        <dependency>\n            <groupId>net.bytebuddy</groupId>\n            <artifactId>byte-buddy</artifactId>\n            <version>1.9.10</version>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-junit-jupiter</artifactId>\n            <version>3.9.0</version>\n            <scope>test</scope>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.mockito</groupId>\n                    <artifactId>mockito-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-inline</artifactId>\n            <version>3.9.0</version>\n            <scope>test</scope>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.mockito</groupId>\n                    <artifactId>mockito-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n\n        <dependency>\n            <groupId>org.mockito</groupId>\n           <artifactId>mockito-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-log</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>commons-io</groupId>\n            <artifactId>commons-io</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.annotation</groupId>\n                    <artifactId>javax.annotation-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <artifactId>log4j-to-slf4j</artifactId>\n                    <groupId>org.apache.logging.log4j</groupId>\n                </exclusion>\n                <exclusion>\n                    <groupId>>ch.qos.logback</groupId>\n                    <artifactId>ch.qos.logback:logback-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.yaml</groupId>\n            <artifactId>snakeyaml</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-webmvc</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>javax.servlet-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-web</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.hibernate.validator</groupId>\n            <artifactId>hibernate-validator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.tomcat.embed</groupId>\n            <artifactId>tomcat-embed-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.fasterxml.jackson.datatype</groupId>\n            <artifactId>jackson-datatype-jsr310</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-autoconfigure</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>net.minidev</groupId>\n            <artifactId>json-smart</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-aop</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger2</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>net.bytebuddy</groupId>\n                    <artifactId>byte-buddy</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger-ui</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>druid-spring-boot-starter</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.faces</groupId>\n                    <artifactId>jsf-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.resource</groupId>\n                    <artifactId>connector-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>servlet-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.mail</groupId>\n                    <artifactId>mail</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>javax.servlet-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.persistence</groupId>\n                    <artifactId>persistence-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>mysql</groupId>\n                    <artifactId>mysql-connector-java</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>jsp-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>jstl</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.apache.logging.log4j</groupId>\n                    <artifactId>log4j-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.h2database</groupId>\n                    <artifactId>h2</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.mchange</groupId>\n                    <artifactId>c3p0</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mortbay.jetty</groupId>\n            <artifactId>jetty</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>fastjson</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-utils</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>osgi-resource-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.openjdk.jol</groupId>\n                    <artifactId>jol-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-utils</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jersey.bundles.repackaged</groupId>\n                    <artifactId>jersey-guava</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jersey.core</groupId>\n                    <artifactId>jersey-common</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.postgresql</groupId>\n            <artifactId>postgresql</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.servlet</groupId>\n                    <artifactId>javax.servlet-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.hibernate</groupId>\n            <artifactId>hibernate-validator</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.hibernate</groupId>\n            <artifactId>hibernate-core</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.el</groupId>\n                    <artifactId>javax.el-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.interceptor</groupId>\n                    <artifactId>javax.interceptor-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.activation</groupId>\n                    <artifactId>javax.activation-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.jboss.spec.javax.transaction</groupId>\n                    <artifactId>jboss-transaction-api_1.2_spec</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jaxb</groupId>\n                    <artifactId>jaxb-runtime</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jaxb</groupId>\n                    <artifactId>txw2</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>net.bytebuddy</groupId>\n                    <artifactId>byte-buddy</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.zookeeper</groupId>\n            <artifactId>zookeeper</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>io.netty</groupId>\n            <artifactId>netty-all</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.eclipse.jetty</groupId>\n            <artifactId>jetty-server</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.eclipse.jetty</groupId>\n            <artifactId>jetty-io</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.thrift</groupId>\n            <artifactId>libthrift</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.annotation</groupId>\n                    <artifactId>javax.annotation-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.mina</groupId>\n            <artifactId>mina-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.httpcomponents</groupId>\n            <artifactId>httpclient</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.cxf</groupId>\n            <artifactId>cxf-rt-bindings-soap</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.sun.xml.bind</groupId>\n                    <artifactId>jaxb-impl</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>com.sun.xml.bind</groupId>\n                    <artifactId>jaxb-xjc</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.cxf</groupId>\n            <artifactId>cxf-rt-transports-http</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.glassfish.jaxb</groupId>\n                    <artifactId>jaxb-runtime</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jaxb</groupId>\n                    <artifactId>txw2</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.cxf</groupId>\n            <artifactId>cxf-api</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.sun.xml.bind</groupId>\n                    <artifactId>jaxb-impl</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>javax.xml.stream</groupId>\n                    <artifactId>stax-api</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.calcite</groupId>\n            <artifactId>calcite-core</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>com.fasterxml.jackson.core</groupId>\n                    <artifactId>jackson-databind</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.guava</groupId>\n            <artifactId>guava</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.ant</groupId>\n            <artifactId>ant</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-dbcp2</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>commons-codec</groupId>\n            <artifactId>commons-codec</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.thoughtworks.xstream</groupId>\n            <artifactId>xstream</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>xmlpull</groupId>\n                    <artifactId>xmlpull</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.protobuf</groupId>\n            <artifactId>protobuf-java</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-params</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-api</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-log4j2</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.apache.logging.log4j</groupId>\n                    <artifactId>log4j-core</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n\n        <dependency>\n            <groupId>com.lmax</groupId>\n            <artifactId>disruptor</artifactId>\n        </dependency>\n     \n    </dependencies>\n\n\n    <build>\n        <finalName>arius-admin-rest</finalName>\n\n        <plugins>\n\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-surefire-plugin</artifactId>\n                <version>2.22.2</version>\n                <configuration>\n                    <!--表示执行任何子目录下所有命名以Test结尾的java类-->\n                    <includes>\n                        <include>**/*Test.java</include>\n                    </includes>\n                    <!--表示不执行任何子目录下所有命名以Test开头的java类-->\n                    <excludes>\n                        <exclude>**/Test*.java</exclude>\n                    </excludes>\n                    <reportsDirectory>${basedir}/test_output</reportsDirectory>\n                    <!-- 忽略测试套件执行过程中失败的测试方法，继续执行剩余的测试类和测试方法 -->\n                    <testFailureIgnore>true</testFailureIgnore>\n                    <!-- 并行执行最大线程数 -->\n                    <forkCount>2</forkCount>\n                    <!-- 是否可以重用 -->\n                    <reuseForks>true</reuseForks>\n                </configuration>\n            </plugin>\n\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n                <version>${spring.boot.version}</version>\n                <executions>\n                    <execution>\n                        <goals>\n                            <goal>repackage</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n\n\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <version>2.5.1</version>\n                <configuration>\n                    <source>1.8</source>\n                    <target>1.8</target>\n                    <encoding>UTF-8</encoding>\n                </configuration>\n            </plugin>\n\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-resources-plugin</artifactId>\n                <version>2.6</version>\n                <configuration>\n                    <encoding>utf-8</encoding>\n                    <useDefaultDelimiters>true</useDefaultDelimiters>\n                </configuration>\n            </plugin>\n\n            <plugin>\n                <groupId>org.jacoco</groupId>\n                <artifactId>jacoco-maven-plugin</artifactId>\n                <version>0.8.3</version>\n                <executions>\n                    <execution>\n                        <id>report-aggregate</id>\n                        <phase>test</phase>\n                        <goals>\n                            <goal>report-aggregate</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n\n        </plugins>\n\n    </build>\n\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/AriusAdminApplication.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.biz.listener.LoggingListener;\nimport com.didichuxing.datachannel.arius.admin.rest.swagger.SwaggerConfiguration;\nimport com.didichuxing.datachannel.arius.admin.rest.web.WebConstant;\nimport com.didichuxing.datachannel.arius.admin.rest.web.WebRequestLogFilter;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;\nimport org.springframework.boot.web.servlet.FilterRegistrationBean;\nimport org.springframework.boot.web.servlet.ServletComponentScan;\nimport org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;\nimport org.springframework.cache.annotation.EnableCaching;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\nimport javax.servlet.*;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\n/**\n * 启动类\n */\n@NoArgsConstructor\n@EnableScheduling\n@EnableCaching\n@ServletComponentScan\n@SpringBootApplication(scanBasePackages = { \"com.didichuxing.datachannel.arius.admin\", \"com.didiglobal.knowframework.job\", \"com.didiglobal.knowframework\" })\npublic class AriusAdminApplication {\n\n    private static final ILog LOGGER           = LogFactory.getLog(AriusAdminApplication.class);\n\n    static final String[]     ALL_EXCLUDE_URLS = new String[] { \"/admin/api/swagger-ui.html\",\n                                                                \"/admin/api/swagger-resources/configuration/ui\",\n                                                                \"/admin/api/webjars/springfox-swagger-ui/favicon-32x32.png\",\n                                                                \"/admin/api/swagger-resources/configuration/security\",\n                                                                \"/admin/api/swagger-resources\",\n                                                                \"/admin/api/v1/client-docs\", \"/admin/api/\",\n                                                                \"/admin/api/v2/client-docs\", \"/admin/api/csrf\",\n                                                                \"/admin/api/druid/login.html\",\n                                                                \"/admin/api/druid/css/bootstrap.min.css\",\n                                                                \"/admin/api/druid/js/bootstrap.min.js\",\n                                                                \"/admin/api/druid/js/doT.js\",\n                                                                \"/admin/api/druid/js/jquery.min.js\",\n                                                                \"/admin/api/druid/index.html\",\n                                                                \"/admin/api/druid/js/client.js\",\n                                                                \"/admin/api/druid/css/style.css\",\n                                                                \"/admin/api/druid/js/lang.js\",\n                                                                \"/admin/api/druid/header.html\",\n                                                                \"/admin/api/druid/basic.json\",\n                                                                \"/admin/api/druid/datasource.html\",\n                                                                \"/admin/api/druid/datasource.json\",\n                                                                \"/admin/api/druid/sql.html\",\n                                                                \"/admin/api/druid/sql.json\",\n                                                                \"/admin/api/druid/wall.html\",\n                                                                \"/admin/api/druid/wall.json\",\n                                                                \"/admin/api/druid/webapp.html\",\n                                                                \"/admin/api/druid/js/doT.js\",\n                                                                \"/admin/api/druid/weburi.html\",\n                                                                \"/admin/api/druid/webapp.json\",\n                                                                \"/admin/api/druid/weburi.json\",\n                                                                \"/admin/api/druid/websession.html\",\n                                                                \"/admin/api/druid/websession.json\",\n                                                                \"/admin/api/druid/spring.html\",\n                                                                \"/admin/api/druid/spring.json\",\n                                                                \"/admin/api/druid/client.html\" };\n\n    @Value(value = \"${admin.port.web}\")\n    private int               port;\n\n    @Value(value = \"${admin.contextPath}\")\n    private String            contextPath;\n\n    public static void main(String[] args) {\n        try {\n            LOGGER.info(\"AriusAdminApplication init starting!\");\n\n            EnvUtil.setLoadActiveProfiles(args);\n            SwaggerConfiguration.initEnv(args);\n            SpringApplication ariusAdminApplication = new SpringApplication(AriusAdminApplication.class);\n            // 添加 日志监听器，使 log4j2-xx.xml 可以间接读取到配置文件的属性\n            ariusAdminApplication.addListeners(new LoggingListener());\n\n            ApplicationContext ctx = ariusAdminApplication.run(args);\n            for (String profile : ctx.getEnvironment().getActiveProfiles()) {\n                LOGGER.info(\"class=AriusAdminApplication||method=main||Spring Boot use profile: {}\", profile);\n            }\n            LOGGER.info(\"class=AriusAdminApplication||method=main||AriusAdminApplication started\");\n        } catch (Exception e) {\n            LOGGER.error(\"class=AriusAdminApplication||method=main||AriusAdminApplication start failed\", e);\n        }\n    }\n\n    @Bean\n    public ConfigurableServletWebServerFactory configurableServletWebServerFactory() {\n        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();\n        factory.setPort(port);\n        factory.setContextPath(contextPath);\n        return factory;\n    }\n\n    @Bean\n    public FilterRegistrationBean<Filter> traceRegistrationBean() {\n        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();\n        registrationBean.addInitParameter(WebRequestLogFilter.EXCLUDE_URLS, StringUtils.join(ALL_EXCLUDE_URLS, \",\"));\n        registrationBean.setOrder(5);\n        Filter traceFilter = new Filter() {\n\n            @Override\n            public void init(FilterConfig filterConfig) {\n                // Do nothing\n            }\n\n            @Override\n            public void doFilter(ServletRequest request, ServletResponse response,\n                                 FilterChain chain) throws IOException, ServletException {\n                ((HttpServletResponse) response).setHeader(WebConstant.X_REQUEST_ID, LogFactory.getFlag());\n                chain.doFilter(request, response);\n            }\n\n            @Override\n            public void destroy() {\n                // Do nothing\n            }\n        };\n        registrationBean.setFilter(traceFilter);\n        return registrationBean;\n    }\n\n    @Bean\n    public FilterRegistrationBean<WebRequestLogFilter> logFilterRegistrationBean() {\n        FilterRegistrationBean<WebRequestLogFilter> registrationBean = new FilterRegistrationBean<>();\n        WebRequestLogFilter requestLogFilter = new WebRequestLogFilter();\n\n        registrationBean.addInitParameter(WebRequestLogFilter.EXCLUDE_URLS, StringUtils.join(ALL_EXCLUDE_URLS, \",\"));\n        registrationBean.addInitParameter(WebRequestLogFilter.RESPONSE_LOG_ENABLE, \"false\");\n        registrationBean.setFilter(requestLogFilter);\n        registrationBean.setOrder(4);\n        return registrationBean;\n    }\n\n}\n\n\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/config/AriusWebMvcConfigurer.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.config;\n\nimport com.didichuxing.datachannel.arius.admin.rest.interceptor.PermissionInterceptor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Profile;\nimport org.springframework.web.servlet.config.annotation.InterceptorRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\n@Configuration\n@Profile(\"!dev\")\npublic class AriusWebMvcConfigurer implements WebMvcConfigurer {\n\n    @Autowired\n    private PermissionInterceptor permissionInterceptor;\n\n    @Override\n    public void addInterceptors(InterceptorRegistry registry) {\n        registry.addInterceptor(permissionInterceptor).addPathPatterns(\"/**\");\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/HealthController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController(\"healthController\")\n@RequestMapping(\"/health\")\n@Api(\"web应用探活接口(REST)\")\npublic class HealthController {\n\n    /**\n     * 探活接口\n     *\n     * @return\n     */\n    @GetMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"探活接口\", notes = \"\")\n    public Result<String> demo() {\n        return Result.buildSuccWithMsg(\"let's go\");\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/normal/NormalMachineNormsController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.normal;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESMachineNormsPO;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESMachineNormsService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_NORMAL;\n\n@RestController\n@RequestMapping(V3_NORMAL + \"/ecm/machineNorms\")\n@Api(tags = \"ECM-ELASTIC接口(REST)\")\npublic class NormalMachineNormsController {\n\n    @Autowired\n    private ESMachineNormsService machineNormsService;\n\n    @GetMapping(\"/list\")\n    @ResponseBody\n    @ApiOperation(value = \"根据类型获取全部机器规格列表接口/类型\")\n    public Result<List<ESMachineNormsPO>> listMachineNorms(String type) {\n        return Result.buildSucc(ConvertUtil.list2List(machineNormsService.listMachineNorms(), ESMachineNormsPO.class));\n    }\n\n    @PostMapping(\"/{id}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取机器规格详情接口\")\n    public Result<ESMachineNormsPO> machineNormsDetail(@PathVariable Long id) {\n        ESMachineNormsPO machineNormsPO = machineNormsService.getById(id);\n        if (AriusObjUtils.isNull(machineNormsPO)) {\n            return Result.buildFail(ResultType.NOT_EXIST.getMessage());\n        }\n        return Result.buildSucc(machineNormsPO);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/normal/NormalOperateRecordController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.normal;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.OperateRecordManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.UserConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.operaterecord.OperateRecordVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.ModuleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperateTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.TriggerWayEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\n\nimport java.util.List;\nimport java.util.Map;\nimport javax.servlet.http.HttpServletRequest;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\n/**\n * 用户操作记录接口(REST)\n * @author gyp\n * @date 2022/5/10\n * @version 1.0\n */\n@RestController\n@RequestMapping(V3 + \"/record\")\n@Api(tags = \"用户操作记录接口(REST)\")\npublic class NormalOperateRecordController {\n\n    @Autowired\n    private OperateRecordManager operateRecordManager;\n\n    @GetMapping(\"/module\")\n    @ResponseBody\n    @ApiOperation(value = \"获取所有模块\")\n    public Result<Map<String, Integer>> mapModules() {\n        return Result.buildSucc(ModuleEnum.toMap());\n    }\n\n    @GetMapping(\"/operation-type/{moduleCode}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取操作类型\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"String\", name = \"moduleCode\", value = \"模块code:为空则会返回全部\", required = false) })\n    public Result<Map<Integer, String>> listOperationType(@PathVariable(value = \"moduleCode\", required = false) String moduleCode) {\n        return Result.buildSucc(OperateTypeEnum\n            .getOperationTypeByModule(StringUtils.isNumeric(moduleCode) ? Integer.valueOf(moduleCode) : null));\n    }\n\n    @GetMapping(\"/trigger-way\")\n    @ResponseBody\n    @ApiOperation(value = \"获取触发方式\")\n    public Result<Map<String, Integer>> listTriggerWay() {\n        return Result.buildSucc(TriggerWayEnum.getOperationList());\n    }\n\n    @PostMapping(\"/page\")\n    @ApiOperation(value = \"查询操作日志列表\", notes = \"分页和条件查询\")\n    public PaginationResult<OperateRecordVO> page(HttpServletRequest request,\n                                                  @RequestBody OperateRecordDTO queryDTO) throws NotFindSubclassException {\n\n        return operateRecordManager.pageOplogPage(queryDTO, HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"获取操作日志详情\", notes = \"根据操作日志id获取操作日志详情\")\n    @ApiImplicitParam(name = \"id\", value = \"操作日志id\", dataType = \"int\", required = true)\n    public Result<OperateRecordVO> get(@PathVariable Integer id) {\n        return operateRecordManager.getOplogDetailByOplogId(id);\n    }\n\n    @PostMapping (\"/sense-operate-record\")\n    @ResponseBody\n    @ApiOperation(value = \"获取sense操作记录列表\")\n    public Result<List<String>> listSenseOperateRecord(HttpServletRequest request, @RequestBody OperateRecordDTO queryDTO) {\n        return operateRecordManager.listSenseOperateRecord(queryDTO,HttpRequestUtil.getOperator(request),HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"/sense-operate-record\")\n    @ResponseBody\n    @ApiOperation(value = \"更新账号应用下sense操作记录\")\n    public Result<Integer> updateSenseOperateRecord(@RequestBody OperateRecordDTO operateRecordDTO, HttpServletRequest request) {\n        return operateRecordManager.updateSenseOperateRecord(operateRecordDTO, HttpRequestUtil.getOperator(request),HttpRequestUtil.getProjectId(request));\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/normal/NormalOrderController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.normal;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.workorder.WorkOrderManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder.WorkOrderDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.workorder.WorkOrderProcessDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.AriusWorkOrderInfoSubmittedVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.OrderTypeVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.WorkOrderVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.order.detail.OrderDetailBaseVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.OperateForbiddenException;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author fengqiongfeng\n * @date 2020/08/24\n */\n@Api(tags = \"Normal-工单相关接口(REST)\")\n@RestController\n@RequestMapping(V3 + \"/order\")\npublic class NormalOrderController {\n\n    @Autowired\n    private WorkOrderManager workOrderManager;\n\n    @GetMapping(\"/type-enums\")\n    @ResponseBody\n    @ApiOperation(value = \"获取工单类型\")\n    public Result<List<OrderTypeVO>> getOrderTypes() {\n        return workOrderManager.getOrderTypes();\n    }\n\n    @PutMapping(\"/{type}/submit\")\n    @ResponseBody\n    @ApiOperation(value = \"提交工单接口\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"String\", name = \"type\", value = \"工单类型\", required = true) })\n    public Result<AriusWorkOrderInfoSubmittedVO> submit(@PathVariable(value = \"type\") String type,\n                                                        @RequestBody WorkOrderDTO workOrderDTO) throws AdminOperateException {\n        return workOrderManager.submit(workOrderDTO);\n    }\n    \n    @PutMapping(\"/join-logic-cluster/submit\")\n    @ResponseBody\n    @ApiOperation(value = \"项目加入已经存在的逻辑集群\",notes = \"三方接口\")\n    @ApiImplicitParams({\n            @ApiImplicitParam(paramType = \"path\", dataType = \"String\", name = \"type\", value = \"工单类型\", required = true) })\n    public Result<AriusWorkOrderInfoSubmittedVO> submitByJoinLogicCluster(@RequestBody WorkOrderDTO workOrderDTO)\n            throws AdminOperateException {\n        return workOrderManager.submitByJoinLogicCluster(workOrderDTO);\n    }\n    \n    @PutMapping(\"/join-logic-cluster/{orderId}\")\n    @ResponseBody\n    @ApiOperation(value = \"审核\",notes = \"三方接口\")\n    public Result<Void> processByJoinLogicCluster(HttpServletRequest httpServletRequest,@PathVariable(value = \"orderId\") Long orderId,\n                                                  @RequestBody WorkOrderProcessDTO processDTO)\n            throws NotFindSubclassException, OperateForbiddenException {\n        //设置当前操作人\n        processDTO.setAssignee(SpringTool.getUserName());\n        return workOrderManager.processByJoinLogicCluster(processDTO,HttpRequestUtil.getProjectId(httpServletRequest));\n    }\n\n    @PutMapping(\"/{orderId}\")\n    @ResponseBody\n    @ApiOperation(value = \"审核\")\n    public Result<Void> process(HttpServletRequest httpServletRequest,@PathVariable(value = \"orderId\") Long orderId,\n                                @RequestBody WorkOrderProcessDTO processDTO) throws NotFindSubclassException,\n                                                                             OperateForbiddenException {\n        //设置当前操作人\n        processDTO.setAssignee(SpringTool.getUserName());\n        return workOrderManager.process(processDTO,HttpRequestUtil.getProjectId(httpServletRequest));\n    }\n\n    @DeleteMapping(\"/{orderId}\")\n    @ResponseBody\n    @ApiOperation(value = \"工单撤销\")\n    public Result<Void> cancelOrder(@PathVariable(value = \"orderId\") Long orderId) throws OperateForbiddenException {\n        return workOrderManager.cancelOrder(orderId, SpringTool.getUserName());\n    }\n\n    @GetMapping(\"/{orderId}\")\n    @ResponseBody\n    @ApiOperation(value = \"工单详情\")\n    public Result<OrderDetailBaseVO> getOrderDetail(@PathVariable(value = \"orderId\") Long orderId) {\n        return workOrderManager.getById(orderId);\n    }\n\n    @GetMapping(\"/orders\")\n    @ResponseBody\n    @ApiOperation(value = \"工单申请列表\")\n    public Result<List<WorkOrderVO>> getOrderApplyList(HttpServletRequest httpServletRequest,\n                                                       @RequestParam(value = \"status\") Integer status) throws OperateForbiddenException {\n        return workOrderManager.getOrderApplyList(status, HttpRequestUtil.getProjectId(httpServletRequest));\n    }\n\n    @GetMapping(\"/approvals\")\n    @ResponseBody\n    @ApiOperation(value = \"工单审核列表\")\n    public Result<List<WorkOrderVO>> getOrderApprovalList(@RequestParam(value = \"status\", required = false) Integer status) throws OperateForbiddenException {\n        return workOrderManager.getOrderApprovalListByStatus(status);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/normal/NormalPackageController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.normal;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_NORMAL;\n\nimport com.didichuxing.datachannel.arius.admin.biz.espackage.ESPackageManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESPackageDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.espackage.ESPackageVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(V3_NORMAL + \"/ecm/package\")\n@Api(tags = \"ECM-ELASTIC接口(REST)\")\npublic class NormalPackageController {\n\n    @Autowired\n    private ESPackageManager packageManager;\n\n    @GetMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"获取程序包列表接口\")\n    public Result<List<ESPackageVO>> listPackage() {\n        return packageManager.listESPackage();\n    }\n\n    @GetMapping(\"/{id}\")\n    @ResponseBody\n    @ApiOperation(value = \"根据ID获取程序包详情接口\")\n    public Result<ESPackageVO> getPackageDetailInfo(@PathVariable Long id) {\n        return packageManager.getESPackageById(id);\n    }\n\n    @PostMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"新增程序包接口\", notes = \"\")\n    public Result<Long> savePackage(HttpServletRequest request, ESPackageDTO esPackageDTO) {\n        return packageManager.addESPackage(esPackageDTO, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/update\")\n    @ResponseBody\n    @ApiOperation(value = \"修改程序包接口\", notes = \"\")\n    public Result<ESPackageVO> updatePackage(HttpServletRequest request, ESPackageDTO esPackageDTO) {\n        return packageManager.updateESPackage(esPackageDTO, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @DeleteMapping(\"/{id}\")\n    @ResponseBody\n    @ApiOperation(value = \"删除程序包接口\", notes = \"\")\n    public Result<Long> deletePackage(HttpServletRequest request,\n                                      @PathVariable Long id) throws NotFindSubclassException {\n        return packageManager.deleteESPackage(id, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/config/ESClusterConfigController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.config;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ESClusterConfigManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm.ESConfigVO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport java.util.Set;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author lyn\n * @date 2020-12-30\n */\n@RestController\n@RequestMapping({ V3 + \"/cluster/phy/config-file\" })\n@Api(tags = \"ES集群Config接口(REST)\")\npublic class ESClusterConfigController {\n\n    @Autowired\n    private ESClusterConfigManager esClusterConfigManager;\n\n    @GetMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"获取ES集群配置列表\")\n    @ApiImplicitParam(paramType = \"query\", dataType = \"String\", name = \"clusterId\", value = \"物理集群ID\", required = true)\n    public Result<List<ESConfigVO>> gainEsClusterConfigs(@RequestParam(\"clusterId\") Long clusterId) {\n\n        return esClusterConfigManager.gainEsClusterConfigs(clusterId);\n    }\n\n    @GetMapping(\"/{configId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取ES集群配置\")\n    public Result<ESConfigVO> gainEsClusterConfig(@PathVariable Long configId) {\n        return esClusterConfigManager.getEsClusterConfigById(configId);\n    }\n\n    @GetMapping(\"/roles/{clusterId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取可操作配置文件的ES集群角色\")\n    public Result<Set<String>> gainEsClusterRoles(@PathVariable Long clusterId) {\n\n        return esClusterConfigManager.gainEsClusterRoles(clusterId);\n\n    }\n\n    @GetMapping(\"/template/{type}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取ES集群模板配置\")\n    public Result<ESConfigVO> gainEsClusterTemplateConfig(@PathVariable String type) {\n\n        return esClusterConfigManager.getEsClusterTemplateConfig(type);\n    }\n\n    @PutMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"更新ES集群配置描述\")\n    public Result<Void> editEsClusterConfigDesc(HttpServletRequest request, @RequestBody ESConfigDTO param) {\n        return esClusterConfigManager.editConfigDesc(param, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/config/ESClusterDynamicConfigController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.config;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterDynamicConfigsTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.Map;\nimport java.util.Set;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-30\n */\n@RestController\n@RequestMapping({ V3 + \"/cluster/phy/dynamic-config\" })\n@Api(tags = \"ES集群DynamicConfig接口(REST)\")\npublic class ESClusterDynamicConfigController {\n\n    @Autowired\n    private ClusterPhyManager clusterPhyManager;\n\n    @GetMapping(\"/{cluster}\")\n    @ApiOperation(value = \"获取当前集群下的动态配置项信息\")\n    public Result<Map<ClusterDynamicConfigsTypeEnum, Map<String, Object>>> getPhyClusterDynamicConfigs(@PathVariable String cluster)\n            throws ESOperateException {\n        return clusterPhyManager.getPhyClusterDynamicConfigs(cluster);\n    }\n\n    @PutMapping(\"\")\n    @ApiOperation(value = \"更新集群配置项的信息\")\n    public Result<Boolean> updateDynamicConfig(HttpServletRequest request, @RequestBody ClusterSettingDTO param) throws ESOperateException {\n        return clusterPhyManager.updatePhyClusterDynamicConfig(param, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/attributes/{cluster}\")\n    @ApiOperation(value = \"获取当前集群下的属性分配选项\")\n    public Result<Set<String>> getRoutingAllocationAwarenessAttributes(@PathVariable String cluster) {\n        return clusterPhyManager.getRoutingAllocationAwarenessAttributes(cluster);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/logic/ClusterLogicTemplateSrvController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.logic;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.TemplateSrvManager;\nimport io.swagger.annotations.Api;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n@RestController\n@RequestMapping(V3 + \"/logic/cluster/templateSrv\")\n@Api(tags = \"ES逻辑集群索引服务接口(REST)\")\n@Deprecated\npublic class ClusterLogicTemplateSrvController {\n\n    @Autowired\n    private TemplateSrvManager templateSrvManager;\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/logic/ESLogicClusterIndexController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.logic;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterNodeManager;\nimport io.swagger.annotations.Api;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n/**\n * ES逻辑集群索引接口.\n *\n * @ClassName ESLogicClusterNodeController\n * @Author gyp\n * @Date 2022/6/13\n * @Version 1.0\n */\n@RestController\n@RequestMapping({ V3 + \"/cluster/logic/index\" })\n@Api(tags = \"ES逻辑集群索引接口(REST)\")\npublic class ESLogicClusterIndexController {\n    @Autowired\n    private ClusterNodeManager clusterNodeManager;\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/logic/ESLogicClusterNodeController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.logic;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterNodeManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterNodeInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n/**\n * ES逻辑集群节点接口.\n *\n * @ClassName ESLogicClusterNodeController\n * @Author gyp\n * @Date 2022/6/13\n * @Version 1.0\n */\n@RestController\n@RequestMapping({ V3 + \"/cluster/logic/node\" })\n@Api(tags = \"ES逻辑集群节点接口(REST)\")\npublic class ESLogicClusterNodeController {\n    @Autowired\n    private ClusterNodeManager clusterNodeManager;\n\n    @GetMapping(\"/{clusterId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取节点列表\")\n    public Result<List<ESClusterRoleHostVO>> getClusterLogicNodes(@PathVariable Integer clusterId) {\n        return clusterNodeManager.listClusterLogicNode(clusterId);\n    }\n\n    @GetMapping(\"/{clusterLogicName}/names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取逻辑集群下的节点名称\")\n    public Result<List<String>> listClusterLogicNodeName(@PathVariable String clusterLogicName) {\n        return clusterNodeManager.listClusterLogicNodeByName(clusterLogicName);\n    }\n\n    @GetMapping(\"/{clusterLogicName}/infos\")\n    @ResponseBody\n    @ApiOperation(value = \"获取逻辑集群下的节点信息\")\n    public Result<List<ClusterNodeInfoVO>> listClusterLogicNodeInfos(@PathVariable String clusterLogicName) {\n        return clusterNodeManager.listClusterLogicNodeInfosByName(clusterLogicName);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/logic/ESLogicClusterOpV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.logic;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterLogicManager;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterLogicTemplateIndexCountVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterLogicVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterPhyVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterPhyWithLogicClusterVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.PluginVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author guoyoupeng_v\n * @date 2022/05/25\n */\n@RestController\n@RequestMapping({ V3 + \"/cluster/logic\" })\n@Api(tags = \"ES我的集群接口(REST)\")\npublic class ESLogicClusterOpV3Controller {\n\n    @Autowired\n    private ClusterLogicManager clusterLogicManager;\n\n    @GetMapping(\"/ids-names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取project拥有的逻辑集群id和名称列表\")\n    public Result<List<Tuple<Long/*逻辑集群Id*/, String/*逻辑集群名称*/>>> getAppClusterLogicIdsAndNames(HttpServletRequest request) {\n        return clusterLogicManager.listProjectClusterLogicIdsAndNames(HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/names\")\n    @ResponseBody\n    @ApiOperation(value = \"根据项目获取逻辑集群下的物理集群名称\")\n    public Result<List<String>> listClusterLogicNameByProjectId(HttpServletRequest request) {\n        return clusterLogicManager.listClusterLogicNameByProjectId(HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping()\n    @ResponseBody\n    @ApiOperation(value = \"根据projectId获取有权限的逻辑集群信息\")\n    public Result<List<ClusterLogicVO>> getAppLogicClusterInfo(HttpServletRequest request) {\n        return clusterLogicManager.getLogicClustersByProjectId(HttpRequestUtil.getProjectId(request));\n    }\n    \n    @GetMapping(\"/level/{level}\")\n    @ResponseBody\n    @ApiOperation(value = \"根据逻辑集群的等级获取逻辑集群信息列表\",notes = \"三方接口\")\n    public Result<List<ClusterLogicVO>> getLogicClusterByLevel(HttpServletRequest request,\n                                                               @PathVariable(\"level\") Integer level) {\n        return clusterLogicManager.getLogicClustersByLevel(level);\n    }\n\n    @GetMapping(\"/{type}\")\n    @ResponseBody\n    @ApiOperation(value = \"根据项目和集群类型获取逻辑集群(项目对其有管理权限)列表\")\n    public Result<List<ClusterLogicVO>> getAppLogicClusterInfoByType(HttpServletRequest request,\n                                                                     @PathVariable Integer type) {\n        return clusterLogicManager.getProjectLogicClusterInfoByType(HttpRequestUtil.getProjectId(request), type);\n    }\n\n    @PostMapping(\"/page\")\n    @ResponseBody\n    @ApiOperation(value = \"条件获取逻辑集群列表\")\n    public PaginationResult<ClusterLogicVO> pageGetClusterLogics(HttpServletRequest request,\n                                                                 @RequestBody ClusterLogicConditionDTO condition) throws NotFindSubclassException, ESOperateException {\n        return clusterLogicManager.pageGetClusterLogics(condition, HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/detail/{clusterLogicId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取逻辑集群概览信息接口\")\n    @ApiImplicitParam(type = \"Long\", name = \"clusterLogicId\", value = \"逻辑集群ID\", required = true)\n    public Result<ClusterLogicVO> detail(HttpServletRequest request, @PathVariable Long clusterLogicId) {\n        return Result\n            .buildSucc(clusterLogicManager.getClusterLogic(clusterLogicId, HttpRequestUtil.getProjectId(request)));\n    }\n\n    @GetMapping(\"/{clusterLogicId}/check-region-not-empty\")\n    @ResponseBody\n    @ApiOperation(value = \"检查逻辑集群所拥有的region是否不为空\")\n    public Result<Boolean> checkLogicClusterRegionIsNotEmpty(@PathVariable(\"clusterLogicId\") Long clusterLogicId) {\n        return clusterLogicManager.isLogicClusterRegionIsNotEmpty(clusterLogicId);\n    }\n\n    @PutMapping()\n    @ResponseBody\n    @ApiOperation(value = \"编辑逻辑集群接口\")\n    public Result<Void> modifyLogicCluster(HttpServletRequest request, @RequestBody ESLogicClusterDTO param) {\n        return clusterLogicManager.editLogicCluster(param, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @DeleteMapping(\"{clusterLogicId}\")\n    @ResponseBody\n    @ApiOperation(value = \"下线集群\")\n\n    public Result<Void> delete(HttpServletRequest request,\n                               @PathVariable Long clusterLogicId) throws AdminOperateException {\n        return clusterLogicManager.deleteLogicCluster(clusterLogicId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/index-template-count/{clusterLogicId}\")\n    @ResponseBody\n    @ApiOperation(value = \"提示用户索引和模板的数量\")\n    public Result<ClusterLogicTemplateIndexCountVO> indexTemplateCount(HttpServletRequest request,\n                                                                       @PathVariable Long clusterLogicId) {\n        return clusterLogicManager.indexTemplateCount(clusterLogicId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/estimated-disk-size/{clusterLogicId}/{count}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取预估磁盘大小\")\n    public Result<Long> estimatedDiskSize(@PathVariable Long clusterLogicId, @PathVariable Integer count) {\n        return clusterLogicManager.estimatedDiskSize(clusterLogicId, count);\n    }\n\n    @GetMapping(\"/dataNodeSpec/{clusterLogicId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取逻辑集群对应region的机器规格\")\n    public Result<String> getClusterDataNodeSpec(@PathVariable Long clusterLogicId) {\n        return clusterLogicManager.getClusterDataNodeSpec(clusterLogicId);\n    }\n\n    //超级应展示全部物理集群、普通应用展示普通应用有权限的逻辑集群\n    @GetMapping(\"/cluster-phy-relation\")\n    @ResponseBody\n    @ApiOperation(value = \"根据项目id获取逻辑集群与物理集群映射\")\n    public Result<List<Tuple<String, ClusterPhyVO>>> getClusterRelationByProjectId(HttpServletRequest request) {\n        return clusterLogicManager.getClusterRelationByProjectId(HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/plugins\")\n    @ResponseBody\n    @ApiOperation(value = \"获取逻辑集群插件列表(用户侧获取)\")\n    public Result<List<PluginVO>> pluginList(Long clusterId) {\n        return clusterLogicManager.getClusterLogicPlugins(clusterId);\n    }\n\n    //展示物理集群对应的逻辑集群名\n    @GetMapping(\"/cluster-phy-logic-names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群所对应的逻辑集群名\")\n    public Result<List<String>> listClusterLogicNameByPhy(@RequestParam(value = \"phyClusterName\",required = false) String phyClusterName) {\n        return Result.buildSucc(clusterLogicManager.listClusterLogicNameByPhyName(phyClusterName));\n    }\n\n    //展示有应用权限的逻辑集群名称列表\n    @GetMapping(\"/cluster-app-logic-names\")\n    @ResponseBody\n    @ApiOperation(value = \"根据项目Id获取对应的逻辑集群名称列表\")\n    public Result<List<String>> listClusterLogicNameByPhy(HttpServletRequest request) {\n        return Result.buildSucc(clusterLogicManager.listClusterLogicNameByApp(HttpRequestUtil.getProjectId(request)));\n    }\n    \n    @GetMapping(\"/phy-relation-logic/{projectId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取项目下逻辑集群和物理集群的关系\")\n    public Result<List<ClusterPhyWithLogicClusterVO>> listLogicClusterWithClusterPhyByProjectId(HttpServletRequest request,\n                                                                                                @PathVariable(\"projectId\")Integer projectId) {\n        return clusterLogicManager.listLogicClusterWithClusterPhyByProjectId(projectId);\n    }\n\n    @GetMapping(\"/logic-cluster-by-phy-name\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群所对应的逻辑集群名\")\n    public Result<List<ClusterLogicVO>> listClusterLogicByPhyName(@RequestParam(value = \"phyClusterName\", required = false) String phyClusterName) {\n        return clusterLogicManager.listClusterLogicByPhyName(phyClusterName);\n    }\n\n    @DeleteMapping(\"/templates-indices-info/{clusterLogicId}\")\n    @ResponseBody\n    @ApiOperation(value = \"删除从模板及索引数据\")\n    public Result<Void> templatesIndicesInfo(@PathVariable Long clusterLogicId,HttpServletRequest request) {\n        return clusterLogicManager.deleteTemplatesIndicesInfo(clusterLogicId,HttpRequestUtil.getProjectId(request),HttpRequestUtil.getOperator(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/logic/ESLogicClusterRegionController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.logic;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterRegionManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterRegionVO;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author wangshu\n * @date 2020/10/10\n */\n@RestController\n@RequestMapping(V3 + \"/cluster/logic/region\")\n@Api(tags = \"ES逻辑集群region接口(REST)\")\npublic class ESLogicClusterRegionController {\n\n\n    @Autowired\n    private ClusterRegionManager clusterRegionManager;\n\n    @GetMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"查询逻辑集群region列表接口\", notes = \"\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Long\", name = \"logicClusterId\", value = \"logicClusterId\", required = true) })\n    public Result<List<ClusterRegionVO>> listLogicClusterRegions(@RequestParam(\"logicClusterId\") Long logicClusterId) {\n    \n        return clusterRegionManager.buildLogicClusterRegionVOByLogicClusterId(logicClusterId);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/phy/ESPhyClusterController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.phy;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterJoinDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterPhyVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * 物理集群接口\n *\n * @author ohushenglin_v\n * @date 2022-05-20\n */\n@RestController(\"esPhyClusterControllerV3\")\n@RequestMapping({ V3 + \"/cluster/phy\" })\n@Api(tags = \"ES物理集群集群接口(REST)\")\npublic class ESPhyClusterController {\n\n    @Autowired\n    private ClusterPhyManager clusterPhyManager;\n\n    @Value(\"${zeus.server}\")\n    private String            zeusServerUrl;\n\n    /**\n     * 根据物理集群ID获取全部角色\n     */\n    @GetMapping(\"/{clusterId}/roles\")\n    @ResponseBody\n    @ApiOperation(value = \"根据物理集群ID获取全部角色列表\", notes = \"\")\n    public Result<List<ESClusterRoleVO>> roleList(@PathVariable Integer clusterId) {\n        List<ClusterRoleInfo> clusterRoleInfos = clusterPhyManager.listClusterRolesByClusterId(clusterId);\n\n        if (AriusObjUtils.isNull(clusterRoleInfos)) {\n            return Result.buildFail(ResultType.NOT_EXIST.getMessage());\n        }\n        return Result.buildSucc(ConvertUtil.list2List(clusterRoleInfos, ESClusterRoleVO.class));\n    }\n\n    @PostMapping(\"/join\")\n    @ResponseBody\n    @ApiOperation(value = \"接入集群\", notes = \"支持多类型集群加入\")\n    public Result<ClusterPhyVO> joinCluster(HttpServletRequest request, @RequestBody ClusterJoinDTO param) {\n        return clusterPhyManager.joinCluster(param, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/{clusterLogicType}/{clusterLogicId}/can-associated-names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取逻辑集群可关联region的物理集群名称列表\")\n    public Result<List<String>> listCanBeAssociatedRegionOfClustersPhys(@PathVariable Integer clusterLogicType,\n                                                                        @PathVariable Long clusterLogicId) {\n        return clusterPhyManager.listCanBeAssociatedRegionOfClustersPhys(clusterLogicType, clusterLogicId);\n    }\n\n    @GetMapping(\"/{clusterLogicType}/can-associated-names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取逻辑集群可进行关联的物理集群名称\")\n    public Result<List<String>> listCanBeAssociatedClustersPhys(@PathVariable Integer clusterLogicType) {\n        return clusterPhyManager.listCanBeAssociatedClustersPhys(clusterLogicType);\n    }\n\n    @GetMapping(\"/{clusterResourceType}/names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取项目下的物理集群名称，可根据类型筛选\")\n    public Result<List<String>> listClusterPhyNameByResourceType(@PathVariable Integer clusterResourceType,\n                                                                 HttpServletRequest request) {\n        return clusterPhyManager.listClusterPhyNameByResourceType(clusterResourceType,\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/names\")\n    @ResponseBody\n    @ApiOperation(value = \"根据项目获取逻辑集群下的物理集群名称\")\n    public Result<List<String>> listClusterPhyNameByProjectId(HttpServletRequest request) {\n        return Result.buildSucc(clusterPhyManager.listClusterPhyNameByProjectId(HttpRequestUtil.getProjectId(request)));\n    }\n\n    @GetMapping(\"/{templateId}/same-version/cluster-names\")\n    @ResponseBody\n    @ApiOperation(value = \"根据模板所在集群，获取与该集群相同版本号的集群名称列表\")\n    public Result<List<String>> getTemplateSameVersionClusterNamesByTemplateId(HttpServletRequest request,\n                                                                               @PathVariable Integer templateId) {\n        return clusterPhyManager.getTemplateSameVersionClusterNamesByTemplateId(HttpRequestUtil.getProjectId(request),\n            templateId);\n    }\n    \n    @GetMapping(\"/{templateId}/same-version-and-dcdr-plugin/cluster-names\")\n    @ResponseBody\n    @ApiOperation(value = \"根据模板所在集群，获取与该集群相同版本号具备dcdr插件的集群名称列表\")\n    public Result<List<String>> getTemplateSameVersionClusterNamesByTemplateIdExistDCDR(HttpServletRequest request,\n                                                                                        @PathVariable Integer templateId) {\n        return clusterPhyManager.getTemplateSameVersionClusterNamesByTemplateIdExistDCDR(\n                HttpRequestUtil.getProjectId(request), templateId);\n    }\n\n    @PostMapping(\"/page\")\n    @ResponseBody\n    @ApiOperation(value = \"按条件分页获取物理集群列表\")\n    public PaginationResult<ClusterPhyVO> pageGetClusterPhys(HttpServletRequest request,\n                                                             @RequestBody ClusterPhyConditionDTO condition) throws NotFindSubclassException {\n        return clusterPhyManager.pageGetClusterPhys(condition, HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/super-phy-names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取超级项目下的物理集群列表\")\n    public Result<List<String>> listClusterPhyNameBySuperApp(HttpServletRequest request) {\n        return clusterPhyManager.listClusterPhyNameBySuperApp(HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/{clusterPhyId}/overview\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群概览信息接口\")\n    @ApiImplicitParam(type = \"Integer\", name = \"clusterPhyId\", value = \"物理集群ID\", required = true)\n    public Result<ClusterPhyVO> overview(@PathVariable(\"clusterPhyId\") Integer clusterId, HttpServletRequest request) {\n        return Result\n            .buildSucc(clusterPhyManager.getClusterPhyOverview(clusterId, HttpRequestUtil.getProjectId(request)));\n    }\n\n    @GetMapping(\"/{clusterLogicType}/{clusterName}/version/list\")\n    @ResponseBody\n    @ApiOperation(value = \"根据逻辑集群类型和物理集群名称获取相同版本的可关联的物理名称列表\")\n    @Deprecated\n    public Result<List<String>> getPhyClusterNameWithSameEsVersion(@PathVariable(\"clusterLogicType\") Integer clusterLogicType,\n                                                                   @PathVariable(name = \"clusterName\", required = false) String clusterName) {\n        return clusterPhyManager.getPhyClusterNameWithSameEsVersion(clusterLogicType, clusterName);\n    }\n\n    @GetMapping(\"/{clusterLogicId}/bind/version/list\")\n    @ResponseBody\n    @ApiOperation(value = \"新建的逻辑集群绑定region的时候进行物理集群版本的校验\")\n    @Deprecated\n    public Result<List<String>> getPhyClusterNameWithSameEsVersionAfterBuildLogic(@PathVariable(\"clusterLogicId\") Long clusterLogicId) {\n        return clusterPhyManager.getPhyClusterNameWithSameEsVersionAfterBuildLogic(clusterLogicId);\n    }\n\n    @GetMapping(\"/zeus-url\")\n    @ResponseBody\n    @ApiOperation(value = \"获取zeus管控平台跳转接口\")\n    public Result<String> zeusUrl() {\n        return Result.buildSucc(zeusServerUrl);\n    }\n\n    @PutMapping(\"/gateway\")\n    @ResponseBody\n    @ApiOperation(value = \"更新物理集群的gateway\")\n    public Result<ClusterPhyVO> updateClusterGateway(HttpServletRequest request, @RequestBody ClusterPhyDTO param) {\n        return clusterPhyManager.updateClusterGateway(param, HttpRequestUtil.getOperator(request));\n    }\n\n    @PutMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"编辑集群接口\")\n    public Result<Boolean> edit(HttpServletRequest request, @RequestBody ClusterPhyDTO param) {\n        return clusterPhyManager.editCluster(param, HttpRequestUtil.getOperator(request));\n    }\n\n    @DeleteMapping(\"{clusterPhyId}\")\n    @ResponseBody\n    @ApiOperation(value = \"删除物理集群\")\n    public Result<Boolean> delete(HttpServletRequest request, @PathVariable(\"clusterPhyId\") Integer clusterId) {\n        return clusterPhyManager.deleteCluster(clusterId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/condition-list\")\n    @ResponseBody\n    @ApiOperation(value = \"获取集群列表接口【三方接口】\", tags = \"【三方接口】\")\n    public Result<List<ClusterPhyVO>> list(@RequestBody ClusterPhyDTO param, HttpServletRequest request) {\n        return Result.buildSucc(clusterPhyManager.listClusterPhys(param));\n    }\n\n    @PostMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"新建集群接口【三方接口】\", tags = \"【三方接口】\")\n    public Result<Boolean> add(HttpServletRequest request, @RequestBody ClusterPhyDTO param) {\n        return clusterPhyManager.addCluster(param, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/phy/ESPhyClusterNodeController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.phy;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterNodeManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionWithNodeInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterNodeInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostWithRegionInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author ohushenglin_v\n * @date 2022-05-30\n */\n@RestController\n@RequestMapping({ V3 + \"/cluster/phy/node\" })\n@Api(tags = \"ES物理集群节点接口(REST)\")\npublic class ESPhyClusterNodeController {\n\n    @Autowired\n    private ClusterNodeManager clusterNodeManager;\n\n    @Autowired\n    private ClusterPhyManager  clusterPhyManager;\n\n    @GetMapping(\"/{clusterId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取节点列表\")\n    public Result<List<ESClusterRoleHostVO>> getClusterPhyRegionInfos(@PathVariable Integer clusterId) {\n        return clusterNodeManager.listClusterPhyNode(clusterId);\n    }\n\n    @GetMapping(\"/{clusterId}/region/\")\n    @ResponseBody\n    @ApiOperation(value = \"获取可划分至region的节点信息\")\n    public Result<List<ESClusterRoleHostWithRegionInfoVO>> listDivide2ClusterNodeInfo(@PathVariable Long clusterId) {\n        return clusterNodeManager.listDivide2ClusterNodeInfo(clusterId);\n    }\n\n    @PostMapping(\"/divide-region-check\")\n    @ResponseBody\n    @ApiOperation(value = \"节点划分校验\")\n    public Result<Boolean> checkMultiNode2Region(HttpServletRequest request,\n                                                     @RequestBody List<ClusterRegionWithNodeInfoDTO> params) throws AdminOperateException {\n\n        return clusterNodeManager.checkMultiNode2Region(params, HttpRequestUtil.getOperator(request),\n                HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/divide-region\")\n    @ResponseBody\n    @ApiOperation(value = \"节点划分且创建region\")\n    public Result<List<Long>> createMultiNode2Region(HttpServletRequest request,\n                                                     @RequestBody List<ClusterRegionWithNodeInfoDTO> params) throws AdminOperateException {\n\n        return clusterNodeManager.createMultiNode2Region(params, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"/divide-region\")\n    @ResponseBody\n    @ApiOperation(value = \"编辑多个region中的节点信息（扩缩容）\")\n    public Result<Boolean> editMultiNode2Region(HttpServletRequest request,\n                                                @RequestBody List<ClusterRegionWithNodeInfoDTO> params) throws AdminOperateException {\n\n        return clusterNodeManager.editMultiNode2Region(params, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request), OperationEnum.EDIT);\n    }\n\n    @GetMapping(\"/{clusterPhyName}/names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群下的节点名称\")\n    public Result<List<String>> listClusterPhyNodeName(@PathVariable String clusterPhyName) {\n        return Result.buildSucc(clusterPhyManager.listClusterPhyNodeName(clusterPhyName));\n    }\n\n    @GetMapping(\"/names\")\n    @ResponseBody\n    @ApiOperation(value = \"根据projectId获取物理集群下的节点名称\")\n    public Result<List<String>> getAppNodeNames(HttpServletRequest request) {\n        return Result.buildSucc(clusterPhyManager.listNodeNameByProjectId(HttpRequestUtil.getProjectId(request)));\n    }\n\n    @PutMapping(\"/{clusterPhyName}/collect-settings\")\n    @ResponseBody\n    @ApiOperation(value = \"采集集群节点配置信息接口【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParam(type = \"String\", name = \"phyClusterName\", value = \"物理集群名称\", required = true)\n    public Result<Void> collectNodeSettings(@PathVariable String clusterPhyName) throws AdminTaskException {\n        return Result.build(clusterNodeManager.collectNodeSettings(clusterPhyName));\n    }\n    \n    @DeleteMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"批量下线离线节点\")\n    @ApiImplicitParam(type = \"String\", name = \"phyClusterName\", value = \"物理集群名称\", required = true)\n    public Result<Void> delete(@RequestBody List<Integer> ids, HttpServletRequest request) {\n        return clusterNodeManager.delete(ids, HttpRequestUtil.getProjectId(request),\n                        HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/{clusterPhyName}/infos\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群下的节点信息\")\n    public Result<List<ClusterNodeInfoVO>> listClusterLogicNodeInfos(@PathVariable String clusterPhyName) {\n        return clusterNodeManager.listClusterPhyNodeInfosByName(clusterPhyName);\n    }\n\n    @GetMapping(\"/machineSpecs\")\n    @ResponseBody\n    @ApiOperation(value = \"获取当前平台所有的机器规格\")\n    public Result<List<String>> listAllMachineSpecs() {\n        return clusterNodeManager.listAllMachineSpecs();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/phy/ESPhyClusterQuickCommandController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.phy;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyQuickCommandManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyQuickCommandIndicesQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyQuickCommandShardsQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.quickcommand.*;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n/**\n * 物理集群快捷命令\n *\n * @ClassName ESPhyClusterQuickCommandController\n * @Author gyp\n * @Date 2022/6/1\n * @Version 1.0\n */\n\n@RestController\n@RequestMapping({ V3 + \"/cluster/phy\" })\n@Api(tags = \"ES物理集群集群快捷命令接口(REST)\")\npublic class ESPhyClusterQuickCommandController {\n\n    @Autowired\n    private ClusterPhyQuickCommandManager clusterPhyQuickCommandManager;\n\n    @PutMapping(\"/{cluster}/node-state-analysis\")\n    @ResponseBody\n    @ApiOperation(value = \"node_state分析\")\n    public Result<List<NodeStateVO>> nodeStateAnalysis(@PathVariable String cluster) {\n        return clusterPhyQuickCommandManager.nodeStateAnalysis(cluster);\n    }\n\n\n    @PostMapping(\"/indices-distribution\")\n    @ResponseBody\n    @ApiOperation(value = \"indices分布\")\n    public Result<List<IndicesDistributionVO>> indicesDistribution(HttpServletRequest request,\n                                                                       @RequestBody ClusterPhyQuickCommandIndicesQueryDTO condition) throws NotFindSubclassException {\n        return Result.buildSucc(clusterPhyQuickCommandManager.indicesDistributionPage(condition, HttpRequestUtil.getProjectId(request)));\n    }\n\n    @PostMapping(\"/shard-distribution\")\n    @ResponseBody\n    @ApiOperation(value = \"shard分布\")\n    public Result<List<ShardDistributionVO>> shardDistribution(HttpServletRequest request,\n                                                               @RequestBody ClusterPhyQuickCommandShardsQueryDTO condition) throws ESOperateException{\n        return Result.buildSucc(clusterPhyQuickCommandManager.shardDistributionPage(condition, HttpRequestUtil.getProjectId(request)));\n    }\n\n    @PutMapping(\"/{cluster}/pending-task-analysis\")\n    @ResponseBody\n    @ApiOperation(value = \"pending task分析\")\n    public Result<List<PendingTaskAnalysisVO>> pendingTaskAnalysis(@PathVariable String cluster) {\n        return clusterPhyQuickCommandManager.pendingTaskAnalysis(cluster);\n    }\n\n    @PutMapping(\"/{cluster}/task-mission-analysis\")\n    @ResponseBody\n    @ApiOperation(value = \"task任务分析\")\n    public Result<List<TaskMissionAnalysisVO>> taskMissionAnalysis(@PathVariable String cluster) {\n        return clusterPhyQuickCommandManager.taskMissionAnalysis(cluster);\n    }\n\n    @PutMapping(\"/{cluster}/hot-thread-analysis\")\n    @ResponseBody\n    @ApiOperation(value = \"热点线程分析\")\n    public Result<String> hotThreadAnalysis(@PathVariable String cluster) {\n        return clusterPhyQuickCommandManager.hotThreadAnalysis(cluster);\n    }\n\n    @PutMapping(\"/{cluster}/shard-assignment-description\")\n    @ResponseBody\n    @ApiOperation(value = \"shard分配说明\")\n    public Result<ShardAssignmentDescriptionVO> shardAssignmentDescription(@PathVariable String cluster) {\n        return clusterPhyQuickCommandManager.shardAssignmentDescription(cluster);\n    }\n\n    @PutMapping(\"/{cluster}/abnormal-shard-allocation-retry\")\n    @ResponseBody\n    @ApiOperation(value = \"异常shard分配重试\")\n    public Result<Void> abnormalShardAllocationRetry(@PathVariable String cluster) {\n        return clusterPhyQuickCommandManager.abnormalShardAllocationRetry(cluster);\n    }\n\n    @PutMapping(\"/{cluster}/clear-field-data-memory\")\n    @ResponseBody\n    @ApiOperation(value = \"清除fieldData内存\")\n    public Result<Void> clearFieldDataMemory(@PathVariable String cluster) {\n        return clusterPhyQuickCommandManager.clearFieldDataMemory(cluster);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/phy/ESPhyClusterRegionController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.phy;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterNodeManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterRegionManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterLogicSpecCondition;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterRegionVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterRegionWithNodeInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n/**\n * 新版逻辑集群Controller\n * 新的逻辑集群是由Region组成的\n */\n@RestController\n@RequestMapping({ V3 + \"/cluster/phy/region\" })\n@Api(tags = \"ES物理集群region接口(REST)\")\npublic class ESPhyClusterRegionController {\n\n    @Autowired\n    private ClusterRegionManager clusterRegionManager;\n    @Autowired\n    private ClusterNodeManager   clusterNodeManager;\n\n    @Deprecated\n    @GetMapping(\"{cluster}/{clusterLogicType}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群region列表接口，不包含cold region\", notes = \"支持各种纬度检索集群Region信息\")\n    public Result<List<ClusterRegionVO>> listPhyClusterRegionsByLogicClusterTypeAndCluster(@PathVariable(\"cluster\") String cluster,\n                                                                                           @PathVariable(\"clusterLogicType\") Integer clusterLogicType) {\n        return clusterRegionManager.listPhyClusterRegionsByLogicClusterTypeAndCluster(cluster, clusterLogicType);\n    }\n\n    @PutMapping(\"{cluster}/{clusterLogicType}\")\n    @ResponseBody\n    @ApiOperation(value = \"根据申请的逻辑集群规格获取满足条件的物理集群region列表，不包含cold region\", notes = \"支持各种纬度检索集群Region信息\")\n    public Result<List<ClusterRegionVO>> listPhyClusterRegionsByCondition(@PathVariable(\"cluster\") String cluster,\n                                                                          @PathVariable(\"clusterLogicType\") Integer clusterLogicType,\n                                                                          @RequestBody ClusterLogicSpecCondition condition) {\n        return clusterRegionManager.listPhyClusterRegionsByCondition(cluster, clusterLogicType, condition);\n    }\n\n    @GetMapping(\"/{regionId}/nodes\")\n    @ResponseBody\n    @ApiOperation(value = \"获取region下的节点列表\", notes = \"\")\n    public Result<List<ESClusterRoleHostVO>> getRegionNodes(@PathVariable Long regionId) {\n\n        return clusterNodeManager.listClusterRoleHostByRegionId(regionId);\n    }\n\n    @DeleteMapping(\"/{regionId}\")\n    @ResponseBody\n    @ApiOperation(value = \"删除物理集群region接口\", notes = \"\")\n    public Result<Void> removeRegion(HttpServletRequest request,\n                                     @PathVariable(\"regionId\") Long regionId) throws AdminOperateException {\n        return clusterRegionManager.deletePhyClusterRegion(regionId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/{clusterName}\")\n    @ResponseBody\n    @ApiOperation(value = \"根据物理集群名称获region信息，包含region中的数据节点信息\")\n    public Result<List<ClusterRegionWithNodeInfoVO>> listClusterRegionWithNodeInfoByClusterName(HttpServletRequest request,\n                                                                                                @PathVariable String clusterName) {\n        return clusterRegionManager.listClusterRegionWithNodeInfoByClusterName(clusterName);\n    }\n\n    @GetMapping(\"/{clusterName}/dcdr\")\n    @ResponseBody\n    @ApiOperation(value = \"获取可分配至dcdr的物理集群名称region列表\", notes = \"不包含空region\")\n    public Result<List<ClusterRegionVO>> listNotEmptyClusterRegionByClusterName(@PathVariable String clusterName) {\n        return clusterRegionManager.listNotEmptyClusterRegionByClusterName(clusterName);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/cluster/plugins/PhyClusterPluginController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.cluster.plugins;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport java.util.List;\n\nimport javax.servlet.http.HttpServletRequest;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPluginManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.PluginDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.PluginVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\n\n/**\n * @author linyunan\n * @date 2021-03-15\n */\n@RestController\n@RequestMapping({ V3 + \"/cluster/phy/plugins\" })\n@Api(tags = \"ES物理集群插件接口\")\npublic class PhyClusterPluginController {\n\n    @Autowired\n    private ClusterPhyManager    clusterPhyManager;\n\n    @Autowired\n    private ClusterPluginManager clusterPluginManager;\n\n    @GetMapping(\"/{cluster}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取ES集群插件列表\")\n    public Result<List<PluginVO>> pluginList(@PathVariable(value = \"cluster\") String cluster) {\n        return clusterPhyManager.listPlugins(cluster);\n    }\n\n    @PostMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"上传插件\")\n    public Result<Long> add(HttpServletRequest request, PluginDTO param) throws NotFindSubclassException {\n\n        return clusterPluginManager.addPlugins(param, HttpRequestUtil.getProjectId(request));\n    }\n\n    @DeleteMapping(\"/{pluginId}\")\n    @ResponseBody\n    @ApiOperation(value = \"删除ES本地插件信息\")\n    public Result<Long> deleteEsClusterConfig(HttpServletRequest request,\n                                              @PathVariable(value = \"pluginId\") Long pluginId) throws NotFindSubclassException {\n\n        return clusterPluginManager.deletePluginById(pluginId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"编辑本地插件描述\")\n    public Result<Void> edit(HttpServletRequest request, @RequestBody PluginDTO pluginDTO) {\n\n        return clusterPluginManager.editPluginDesc(pluginDTO, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/config/AriusConfigV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.config;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.config.AriusConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.config.AriusConfigInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AdminConstant.COMMA;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n/**\n * \n *\n * @author d06679\n * @date 2017/10/23\n */\n@RestController\n@RequestMapping(V3 + \"/config\")\n@Api(tags = \"运维配置接口(REST)\")\npublic class AriusConfigV3Controller {\n\n    @Autowired\n    private AriusConfigInfoService ariusConfigInfoService;\n\n    @PostMapping(\"/list\")\n    @ResponseBody\n    @ApiOperation(value = \"获取配置列表接口\")\n    public Result<List<AriusConfigInfoVO>> listConfig(@RequestBody AriusConfigInfoDTO param) {\n        return Result\n            .buildSucc(ConvertUtil.list2List(ariusConfigInfoService.queryByCondition(param), AriusConfigInfoVO.class));\n    }\n\n    @PostMapping(\"/switch\")\n    @ResponseBody\n    @ApiOperation(value = \"使能配置接口\")\n    public Result<Void> switchConfig(HttpServletRequest request, @RequestBody AriusConfigInfoDTO param) {\n        return ariusConfigInfoService.switchConfig(param.getId(), param.getStatus(),\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @DeleteMapping(\"/{id}\")\n    @ResponseBody\n    @ApiOperation(value = \"删除配置接口\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Integer\", name = \"id\", value = \"配置ID\", required = true) })\n    public Result<Void> deleteConfig(HttpServletRequest request, @PathVariable Integer id) {\n        return ariusConfigInfoService.delConfig(id, HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(\"/add\")\n    @ResponseBody\n    @ApiOperation(value = \"新建配置接口\")\n    public Result<Integer> addConfig(HttpServletRequest request, @RequestBody AriusConfigInfoDTO param) {\n        return ariusConfigInfoService.addConfig(param, HttpRequestUtil.getOperator(request));\n    }\n\n    @PutMapping()\n    @ResponseBody\n    @ApiOperation(value = \"编辑配置接口\")\n    public Result<Void> editConfig(HttpServletRequest request, @RequestBody AriusConfigInfoDTO param) {\n        return ariusConfigInfoService.editConfig(param, HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/cluster-version\")\n    @ResponseBody\n    @ApiOperation(value = \"获取集群版本列表\")\n    public Result<List<String>> listClusterVersion() {\n        return Result.buildSucc(new ArrayList<>(ariusConfigInfoService.stringSettingSplit2Set(\n            AriusConfigConstant.ARIUS_COMMON_GROUP, AriusConfigConstant.CLUSTER_PACKAGE_VERSION_LIST,\n            AriusConfigConstant.CLUSTER_PACKAGE_VERSION_LIST_DEFAULT_VALUE, COMMA)));\n    }\n\n    @GetMapping(\"/cluster-data-center\")\n    @ResponseBody\n    @ApiOperation(value = \"获取数据中心列表\")\n    public Result<List<String>> listClusterDataCenter() {\n        return Result.buildSucc(new ArrayList<>(ariusConfigInfoService.stringSettingSplit2Set(\n            AriusConfigConstant.ARIUS_COMMON_GROUP, AriusConfigConstant.CLUSTER_DATA_CENTER_LIST,\n            AriusConfigConstant.CLUSTER_DATA_CENTER_LIST_DEFAULT_VALUE, COMMA)));\n    }\n\n    @GetMapping(\"/cluster-resource-type\")\n    @ResponseBody\n    @ApiOperation(value = \"获取集群资源列表\")\n    public Result<List<String>> listClusterResourceType() {\n        return Result.buildSucc(new ArrayList<>(ariusConfigInfoService.stringSettingSplit2Set(\n            AriusConfigConstant.ARIUS_COMMON_GROUP, AriusConfigConstant.CLUSTER_RESOURCE_TYPE_LIST,\n            AriusConfigConstant.CLUSTER_RESOURCE_TYPE_LIST_DEFAULT_VALUE, COMMA)));\n    }\n\n    @GetMapping(\"/logic-template-business-type\")\n    @ResponseBody\n    @ApiOperation(value = \"获取模板业务类型\")\n    public Result<List<String>> listLogicTemplateBusinessType() {\n        return Result.buildSucc(new ArrayList<>(ariusConfigInfoService.stringSettingSplit2Set(\n                AriusConfigConstant.ARIUS_TEMPLATE_GROUP, AriusConfigConstant.LOGIC_TEMPLATE_BUSINESS_TYPE_LIST,\n                AriusConfigConstant.LOGIC_TEMPLATE_BUSINESS_TYPE_LIST_DEFAULT_VALUE, COMMA)));\n    }\n\n    @GetMapping(\"/cluster-node-count\")\n    @ResponseBody\n    @ApiOperation(value = \"获取集群节点数\")\n    public Result<List<String>> listClusterNodeCount() {\n        return Result.buildSucc(new ArrayList<>(ariusConfigInfoService.stringSettingSplit2Set(\n            AriusConfigConstant.ARIUS_COMMON_GROUP, AriusConfigConstant.CLUSTER_NODE_COUNT_LIST,\n            AriusConfigConstant.CLUSTER_NODE_COUNT_LIST_DEFAULT_VALUE, COMMA)));\n    }\n\n    @GetMapping(\"/time-format\")\n    @ResponseBody\n    @ApiOperation(value = \"获取时间格式列表\")\n    public Result<List<String>> listTimeFormat() {\n        return Result.buildSucc(new ArrayList<>(ariusConfigInfoService.stringSettingSplit2Set(\n            AriusConfigConstant.ARIUS_TEMPLATE_GROUP, AriusConfigConstant.LOGIC_TEMPLATE_TIME_FORMAT_LIST,\n            AriusConfigConstant.LOGIC_TEMPLATE_TIME_FORMAT_LIST_DEFAULT_VALUE, COMMA)));\n    }\n\n    @GetMapping(\"/node-specification\")\n    @ResponseBody\n    @ApiOperation(value = \"获取节点规格列表\")\n    public Result<List<String>> listClusterNodeSpecification() {\n        return Result.buildSucc(new ArrayList<>(ariusConfigInfoService.stringSettingSplit2Set(\n            AriusConfigConstant.ARIUS_COMMON_GROUP, AriusConfigConstant.CLUSTER_NODE_SPECIFICATION_LIST,\n            AriusConfigConstant.CLUSTER_NODE_SPECIFICATION_LIST_DEFAULT_VALUE, COMMA)));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/dsl/DslMetricsController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.dsl.DslMetricsManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.SearchDslTemplateResponseVO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n@NoArgsConstructor\n@RestController()\n@RequestMapping(V3 + \"/dsl/metrics\")\n@Api(tags = \"DSL指标接口(REST)\")\npublic class DslMetricsController {\n\n    @Autowired\n    private DslMetricsManager dslMetricsManager;\n\n    @GetMapping(path = \"/project\")\n    @ApiOperation(value = \"根据projectId获取dsl的指标信息【三方接口】\", tags = \"【三方接口】\", notes = \"根据projectId获取dsl的指标信息\", httpMethod = \"GET\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"projectId\", value = \"应用账号\", required = false, example = \"1\"),\n                         @ApiImplicitParam(name = \"startDate\", value = \"开始时刻\", required = true, example = \"1550160000000\"),\n                         @ApiImplicitParam(name = \"startDate\", value = \"开始时刻\", required = true, example = \"1550160000000\") })\n    public Result<List<DslTemplateVO>> listByProjectId(@RequestParam(value = \"projectId\", required = false) Integer projectId,\n                                                       @RequestParam(value = \"startDate\") Long startDate,\n                                                       @RequestParam(value = \"endDate\") Long endDate,\n                                                       HttpServletRequest request) {\n        projectId = projectId == null ? HttpRequestUtil.getProjectId(request) : projectId;\n        return dslMetricsManager.getDSLMetricsInfoByProjectId(projectId, startDate, endDate);\n    }\n\n    @GetMapping(path = \"/detail\")\n    @ApiOperation(value = \"根据projectId和模板名称获取dsl的指标信息【三方接口】\", tags = \"【三方接口】\", notes = \"根据projectId获取dsl的指标信息\", httpMethod = \"GET\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"projectId\", value = \"应用账号\", required = false, example = \"1\"),\n                         @ApiImplicitParam(name = \"dslTemplateMd5\", value = \"查询模板MD5\", required = true, example = \"V2_EA317B2029682DB83A191CBD797A66FE\"),\n                         @ApiImplicitParam(name = \"startDate\", value = \"开始时刻\", required = true, example = \"1550160000000\"),\n                         @ApiImplicitParam(name = \"endDate\", value = \"结束时刻\", required = true, example = \"1550246399999\") })\n    public Result<List<DslMetricsVO>> getDetailMetrics(@RequestParam(value = \"projectId\", required = false) Integer projectId,\n                                                       @RequestParam(value = \"dslTemplateMd5\") String dslTemplateMd5,\n                                                       @RequestParam(value = \"startDate\") Long startDate,\n                                                       @RequestParam(value = \"endDate\") Long endDate,\n                                                       HttpServletRequest request) {\n        projectId = projectId == null ? HttpRequestUtil.getProjectId(request) : projectId;\n        return dslMetricsManager.getDetailMetrics(projectId, dslTemplateMd5, startDate, endDate);\n    }\n\n    @GetMapping(path = \"/condition\")\n    @ApiOperation(value = \"根据查询条件获取查询模板数据\", notes = \"根据查询条件获取查询模板数据\", httpMethod = \"GET\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"projectId\", value = \"应用账号\", required = false, example = \"1\"),\n                         @ApiImplicitParam(name = \"searchKeyword\", value = \"查询关键字（如果是模糊查询则后面带上*）\", required = false, example = \"dos_order*\"),\n                         @ApiImplicitParam(name = \"dslTag\", value = \"危害标签\", required = false, example = \"dslTag\"),\n                         @ApiImplicitParam(name = \"sortInfo\", value = \"排序信息\", required = false, example = \"\"),\n                         @ApiImplicitParam(name = \"from\", value = \"分页起始\", required = true, example = \"0\"),\n                         @ApiImplicitParam(name = \"size\", value = \"每页记录数\", required = true, example = \"10\"),\n                         @ApiImplicitParam(name = \"startDate\", value = \"开始时刻\", required = true, example = \"1550160000000\"),\n                         @ApiImplicitParam(name = \"endDate\", value = \"结束时刻\", required = true, example = \"1550246399999\") })\n    public Result<SearchDslTemplateResponseVO> searchTemplate(@RequestParam(value = \"projectId\", required = false) Integer projectId,\n                                                              @RequestParam(value = \"searchKeyword\", required = false) String searchKeyword,\n                                                              @RequestParam(value = \"dslTag\", required = false) String dslTag,\n                                                              @RequestParam(value = \"sortInfo\", required = false) String sortInfo,\n                                                              @RequestParam(value = \"from\") Long from,\n                                                              @RequestParam(value = \"size\") Long size,\n                                                              @RequestParam(value = \"startDate\") Long startDate,\n                                                              @RequestParam(value = \"endDate\") Long endDate,\n                                                              HttpServletRequest request) {\n        projectId = projectId == null ? HttpRequestUtil.getProjectId(request) : projectId;\n        return dslMetricsManager.getDslTemplateByCondition(projectId, searchKeyword, dslTag, sortInfo, from, size,\n            startDate, endDate);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/dsl/DslTemplateController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.dsl;\n\nimport com.didichuxing.datachannel.arius.admin.biz.dsl.DslTemplateManager;\nimport com.didichuxing.datachannel.arius.admin.biz.gateway.GatewayJoinLogManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.DslQueryLimitDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.dsl.template.DslTemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.GatewayJoinQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.UserConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DslTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayJoinVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.QueryDiagnosisTabNameEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n/**\n * @author cjm\n */\n@NoArgsConstructor\n@RestController()\n@RequestMapping(V3 + \"/dsl/template\")\n@Api(tags = \"DSL模版管理接口(REST)\")\npublic class DslTemplateController {\n\n    @Autowired\n    private DslTemplateManager    dslTemplateManager;\n\n    @Autowired\n    private GatewayJoinLogManager gatewayJoinLogManager;\n\n    @PostMapping(\"/page\")\n    @ApiOperation(value = \"分页获取DSL模版信息\", notes = \"根据一些条件分页获取DSL模版信息\")\n    public PaginationResult<DslTemplateVO> page(@RequestBody DslTemplateConditionDTO query,\n                                                HttpServletRequest request) throws NotFindSubclassException {\n        return dslTemplateManager.getDslTemplatePage(HttpRequestUtil.getProjectId(request), query);\n    }\n\n    @GetMapping(path = \"/detail/{dslTemplateMd5}\")\n    @ApiOperation(value = \"根据dslTemplateMd5称获取DSL模版详情\", notes = \"根据DSL模板MD5称获取DSL模版详情\")\n    @ApiImplicitParams({@ApiImplicitParam(name = \"dslTemplateMd5\", value = \"查询模板MD5\", required = true),\n                        @ApiImplicitParam(name = \"projectId\", value = \"查询模板对应的projectId\", required = false)})\n    public Result<DslTemplateVO> getDetailTemplate(@PathVariable(value = \"dslTemplateMd5\") String dslTemplateMd5,\n                                                   @RequestParam(value = \"projectId\") Integer projectId,\n                                                   HttpServletRequest request) {\n        return dslTemplateManager.getDslTemplateDetail(null!=projectId?projectId:HttpRequestUtil.getProjectId(request), dslTemplateMd5);\n    }\n\n    @PutMapping(path = \"/status/{dslTemplateMd5}\")\n    @ApiOperation(value = \"根据dslTemplateMd5修改DSL模版状态（启用或停用）\", notes = \"调用该接口，直接对状态取反\")\n    @ApiImplicitParams({@ApiImplicitParam(name = \"dslTemplateMd5\", value = \"查询模板MD5List\", required = true),\n                        @ApiImplicitParam(name = \"projectId\", value = \"查询模板对应的projectId\", required = false)})\n    public Result<Boolean> changeStatus(@PathVariable(value = \"dslTemplateMd5\") String dslTemplateMd5,\n                                        @RequestParam(value = \"projectId\",required = false) Integer projectId, HttpServletRequest request) {\n\n        return dslTemplateManager.changeDslTemplateStatus(null != projectId ? projectId : HttpRequestUtil.getProjectId(request),HttpRequestUtil.getOperator(request), dslTemplateMd5);\n    }\n\n    @PutMapping(path = \"/query-limit\")\n    @ApiOperation(value = \"根据dslTemplateMd5修改查询模版限流值\", notes = \"可批量修改\")\n    public Result<Boolean> updateQueryLimit(@RequestBody List<DslQueryLimitDTO> dslTemplateList, HttpServletRequest request) {\n        return dslTemplateManager.updateDslTemplateQueryLimit(HttpRequestUtil.getProjectId(request),HttpRequestUtil.getOperator(),dslTemplateList);\n    }\n\n    @PostMapping(\"/slow/page\")\n    @ApiOperation(value = \"dsl慢查询分页\", notes = \"根据指定页获取dsl慢查询列表\")\n    public PaginationResult<GatewayJoinVO> slowPage(@RequestBody GatewayJoinQueryDTO queryDTO, HttpServletRequest request) throws NotFindSubclassException {\n        queryDTO.setTabName(QueryDiagnosisTabNameEnum.SLOW_QUERY.getTabName());\n        return gatewayJoinLogManager.getGatewayJoinPage(HttpRequestUtil.getProjectId(request), queryDTO);\n    }\n\n    @PostMapping(\"/error/page\")\n    @ApiOperation(value = \"dsl慢查询分页\", notes = \"根据指定页获取dsl慢查询列表\")\n    public PaginationResult<GatewayJoinVO> errorPage(@RequestBody GatewayJoinQueryDTO queryDTO, HttpServletRequest request) throws NotFindSubclassException {\n        queryDTO.setTabName(QueryDiagnosisTabNameEnum.ERROR_QUERY.getTabName());\n        return gatewayJoinLogManager.getGatewayJoinPage(HttpRequestUtil.getProjectId(request), queryDTO);\n    }\n\n    @GetMapping(\"/{indexName}\")\n    public Result<String> getDSLByProjectIdAndIndexName(@PathVariable(value = \"indexName\") String indexName,\n                                                        HttpServletRequest request) {\n        return gatewayJoinLogManager.getDSLByProjectIdAndIndexName(HttpRequestUtil.getProjectId(request), indexName);\n    }\n    @PostMapping(\"/dsl-template-config\")\n    @ResponseBody\n    @ApiOperation(value = \"获取账号下已配置字段类型\")\n    public Result<List<String>> listDslTemplateFields(@RequestBody UserConfigInfoDTO param,\n                                                       HttpServletRequest request) {\n        return Result\n                .buildSucc(dslTemplateManager.listConfigDslTemplateFields(param, HttpRequestUtil.getOperator(request),HttpRequestUtil.getProjectId(request)));\n    }\n\n    @PutMapping(\"/dsl-template-config\")\n    @ResponseBody\n    @ApiOperation(value = \"更新账号下已配置指标类型\")\n    public Result<Integer> updateConfigDslTemplateFields(@RequestBody UserConfigInfoDTO param,\n                                                        HttpServletRequest request) {\n        return dslTemplateManager.updateConfigDslTemplateFields(param, HttpRequestUtil.getOperator(request),HttpRequestUtil.getProjectId(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/gateway/GatewayJoinController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.gateway;\n\nimport com.didichuxing.datachannel.arius.admin.biz.gateway.GatewayJoinLogManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayJoinVO;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport io.swagger.annotations.ApiParam;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n@NoArgsConstructor\n@RestController()\n@RequestMapping(V3 + \"/gateway/join\")\n@Api(tags = \"GatewayJoin日志接口\")\npublic class GatewayJoinController {\n\n    @Autowired\n    private GatewayJoinLogManager gatewayJoinManager;\n\n    @GetMapping(path = \"/error/project\")\n    @ApiOperation(value = \"获取projectid的错误gateway请求日志【三方接口】\", tags = \"【三方接口】\", notes = \"获取projectId的错误gateway请求日志【三方接口】\", httpMethod = \"GET\")\n    public Result<List<GatewayJoinVO>> getGatewayErrorList(@ApiParam(name = \"projectId\", value = \"应用账号\", required = false, example = \"1\") @RequestParam(value = \"projectId\", required = false) Long projectId,\n                                                           @ApiParam(name = \"dataCenter\", value = \"数据中心\", required = true, example = \"cn\") @RequestParam(value = \"dataCenter\") String dataCenter,\n                                                           @ApiParam(name = \"startDate\", value = \"开始时刻\", required = true, example = \"1550160000000\") @RequestParam(value = \"startDate\") Long startDate,\n                                                           @ApiParam(name = \"endDate\", value = \"结束时刻\", required = true, example = \"1550246399999\") @RequestParam(value = \"endDate\") Long endDate) {\n        return gatewayJoinManager.getGatewayErrorList(projectId, startDate, endDate);\n    }\n\n    @GetMapping(path = \"/slow/project\")\n    @ApiOperation(value = \"获取projectId的慢查gateway请求日志【三方接口】\", tags = \"【三方接口】\", notes = \"获取projectId的慢查gateway请求日志【三方接口】\", httpMethod = \"GET\")\n    public Result<List<GatewayJoinVO>> getGatewaySlowList(@ApiParam(name = \"projectId\", value = \"应用账号\", required = false, example = \"1\") @RequestParam(value = \"projectId\", required = false) Long projectId,\n                                                          @ApiParam(name = \"dataCenter\", value = \"数据中心\", required = true, example = \"cn\") @RequestParam(value = \"dataCenter\") String dataCenter,\n                                                          @ApiParam(name = \"startDate\", value = \"开始时刻\", required = true, example = \"1550160000000\") @RequestParam(value = \"startDate\") Long startDate,\n                                                          @ApiParam(name = \"endDate\", value = \"结束时刻\", required = true, example = \"1550246399999\") @RequestParam(value = \"endDate\") Long endDate) {\n        return gatewayJoinManager.getGatewaySlowList(projectId, startDate, endDate);\n    }\n\n    @GetMapping(path = \"/query/count-project\")\n    @ApiOperation(value = \"获取projectId的查询次数\", notes = \"获取projectId的查询次数\", httpMethod = \"GET\")\n    public Result<Long> getSearchCountByProjectId(@ApiParam(name = \"projectId\", value = \"应用账号\", required = false, example = \"1\") @RequestParam(value = \"projectId\", required = true) Long projectId,\n                                                  @ApiParam(name = \"dataCenter\", value = \"数据中心\", required = true, example = \"cn\") @RequestParam(value = \"dataCenter\") String dataCenter,\n                                                  @ApiParam(name = \"startDate\", value = \"开始时刻\", required = true, example = \"1550160000000\") @RequestParam(value = \"startDate\") Long startDate,\n                                                  @ApiParam(name = \"endDate\", value = \"结束时刻\", required = true, example = \"1550246399999\") @RequestParam(value = \"endDate\") Long endDate) {\n        return gatewayJoinManager.getSearchCountByProjectId(dataCenter, projectId, startDate, endDate);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/gateway/GatewaySqlController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.gateway;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.gateway.GatewayManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport javax.servlet.http.HttpServletRequest;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n@NoArgsConstructor\n@RestController()\n@RequestMapping(V3 + \"/gateway/sql\")\n@Api(tags = \"Gateway中sql语句的翻译和查询\")\npublic class GatewaySqlController {\n    @Autowired\n    private GatewayManager gatewayManager;\n\n    @PostMapping(value = { \"/{phyClusterName}\"})\n    @ResponseBody\n    @ApiOperation(value = \"根据sql语句查询gateway集群\")\n    public Result<String> directSqlSearch(@RequestBody String sql,\n                                          @PathVariable(\"phyClusterName\") String phyClusterName,\n                                          HttpServletRequest request) {\n        return gatewayManager.directSqlSearch(sql, phyClusterName, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/{phyClusterName}/explain\")\n    @ResponseBody\n    @ApiOperation(value = \"根据sql语句解释\")\n    public Result<String> sqlExplain(@RequestBody String sql ,@PathVariable(\"phyClusterName\") String phyClusterName) {\n        return gatewayManager.sqlExplain(sql, phyClusterName,AuthConstant.SUPER_PROJECT_ID);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/indices/BaseIndicesController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.indices;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * Created by linyunan on 2022/7/7\n */\n\npublic abstract class BaseIndicesController {\n\n    @Autowired\n    private AriusConfigInfoService ariusConfigInfoService;\n\n    /**\n     * 临时黑名单列表, 禁止通过索引管理操作物理集群\n     * @param clusterPhyNames   物理集群列表\n     * @return                  Result<Boolean>\n     */\n    protected Result<Boolean> checkClusterValid(List<String> clusterPhyNames) {\n        if (CollectionUtils.isEmpty(clusterPhyNames)) {\n            return Result.buildSucc();\n        }\n\n        // 暂时代码写死，防止页面上通过配置修改\n        List<String> filterClustersFromDidi = Lists.newArrayList(\"didi-cluster-test\");\n\n        Set<String> filterClustersFromAriusConfig = ariusConfigInfoService\n            .stringSettingSplit2Set(\"arius.cluster.blacklist\", \"cluster.phy.name\", \"\", \",\");\n\n        filterClustersFromAriusConfig.addAll(filterClustersFromDidi);\n\n        for (String clusterPhyName : clusterPhyNames) {\n            if (filterClustersFromAriusConfig.contains(clusterPhyName)) {\n                return Result.buildFail(String.format(\"该物理集群[%s]已添加黑名单, 禁止对集群进行任何新增、编辑、删除等操作\", clusterPhyName));\n            }\n        }\n\n        return Result.buildSucc();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/indices/IndicesController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.indices;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.indices.IndicesManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndicesBlockSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.manage.IndexCatCellWithConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexCatCellVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexMappingVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexSettingVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.indices.IndexShardInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport com.google.common.collect.Lists;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiModelProperty;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author lyn\n * @date 2021/09/28\n **/\n@RestController\n@RequestMapping(V3 + \"/indices\")\n@Api(tags = \"索引管理接口(REST)\")\npublic class IndicesController extends BaseIndicesController {\n    @Autowired\n    private IndicesManager indicesManager;\n\n    @PostMapping(\"/page\")\n    @ResponseBody\n    @ApiOperation(value = \"分页获取索引列表信息\", notes = \"携带可读可写标志位\")\n    public PaginationResult<IndexCatCellVO> pageGetIndexCatInfoVO(HttpServletRequest request,\n                                                                  @RequestBody IndexQueryDTO condition) throws NotFindSubclassException {\n        return indicesManager.pageGetIndex(condition, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"创建索引\")\n    public Result<Void> createIndex(HttpServletRequest request, @RequestBody IndexCatCellWithConfigDTO param)\n            throws AdminOperateException {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(Lists.newArrayList(param.getCluster()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.createIndex(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/{cluster}/{indexName}\")\n    @ResponseBody\n    @ApiOperation(value = \"查询索引\")\n    public Result<IndexCatCellVO> getIndex(HttpServletRequest request, @PathVariable String cluster,\n                                           @PathVariable String indexName) {\n        return indicesManager.getIndexCatInfo(cluster, indexName, HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/{cluster}/{indexName}/exists\")\n    @ResponseBody\n    @ApiOperation(value = \"查询索引\")\n    public Result<Boolean> isExists(HttpServletRequest request, @PathVariable String cluster,\n                                    @PathVariable String indexName) {\n        return indicesManager.isExists(cluster, indexName, HttpRequestUtil.getProjectId(request));\n    }\n\n    @DeleteMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"删除索引\")\n    public Result<Boolean> deleteIndex(HttpServletRequest request, @RequestBody List<IndexCatCellDTO> params) {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(\n            params.stream().map(IndexCatCellDTO::getCluster).distinct().collect(Collectors.toList()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.deleteIndex(params, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @PutMapping(\"/mapping\")\n    @ResponseBody\n    @ApiOperation(value = \"编辑mapping\")\n    public Result<Void> editMapping(HttpServletRequest request, @RequestBody IndexCatCellWithConfigDTO param)\n            throws AdminOperateException {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(Lists.newArrayList(param.getCluster()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.editMapping(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/{cluster}/{indexName}/mapping\")\n    @ResponseBody\n    @ApiOperation(value = \"查询mapping\")\n    public Result<IndexMappingVO> getMapping(@PathVariable String cluster, @PathVariable String indexName,\n                                             HttpServletRequest request) {\n        return indicesManager.getMapping(cluster, indexName, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"/setting\")\n    @ResponseBody\n    @ApiOperation(value = \"编辑setting\")\n    public Result<Void> editSetting(HttpServletRequest request,\n                                    @RequestBody IndexCatCellWithConfigDTO param) throws ESOperateException {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(Lists.newArrayList(param.getCluster()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.editSetting(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/{cluster}/{indexName}/setting\")\n    @ResponseBody\n    @ApiOperation(value = \"查询setting\")\n    public Result<IndexSettingVO> getSetting(@PathVariable String cluster, @PathVariable String indexName,\n                                             HttpServletRequest request) {\n        return indicesManager.getSetting(cluster, indexName, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"/close\")\n    @ResponseBody\n    @ApiOperation(value = \"关闭索引\")\n    public Result<Boolean> close(HttpServletRequest request, @RequestBody List<IndexCatCellDTO> params) {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(\n            params.stream().map(IndexCatCellDTO::getCluster).distinct().collect(Collectors.toList()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.closeIndex(params, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @PutMapping(\"/open\")\n    @ResponseBody\n    @ApiOperation(value = \"关闭索引\")\n    public Result<Boolean> open(HttpServletRequest request, @RequestBody List<IndexCatCellDTO> params) {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(\n            params.stream().map(IndexCatCellDTO::getCluster).distinct().collect(Collectors.toList()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.openIndex(params, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @PutMapping(\"/block\")\n    @ResponseBody\n    @ApiOperation(value = \"批量编辑索引阻塞设置\")\n    public Result<Boolean> editIndexBlockSetting(@RequestBody List<IndicesBlockSettingDTO> params,\n                                                 HttpServletRequest request) {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(\n            params.stream().map(IndicesBlockSettingDTO::getCluster).distinct().collect(Collectors.toList()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n        Result<Void> result = indicesManager.editIndexBlockSetting(params, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n        return Result.buildSucc(result.success() ? Boolean.TRUE : Boolean.FALSE);\n    }\n\n    @GetMapping(\"/{cluster}/{indexName}/alias\")\n    @ResponseBody\n    @ApiOperation(value = \"获取索引别名\")\n    public Result<List<String>> getIndexAliases(HttpServletRequest request, @PathVariable String cluster,\n                                                @PathVariable String indexName) {\n        return indicesManager.getIndexAliases(cluster, indexName, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"/alias\")\n    @ResponseBody\n    @ApiOperation(value = \"编辑别名\")\n    public Result<Void> alias(HttpServletRequest request, @RequestBody IndexCatCellWithConfigDTO param) {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(Lists.newArrayList(param.getCluster()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.addIndexAliases(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @DeleteMapping(\"/alias\")\n    @ResponseBody\n    @ApiOperation(value = \"删除别名\")\n    public Result<Void> deleteAlias(HttpServletRequest request, @RequestBody IndexCatCellWithConfigDTO param) {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(Lists.newArrayList(param.getCluster()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.deleteIndexAliases(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/{cluster}/{indexName}/shard\")\n    @ResponseBody\n    @ApiOperation(value = \"获取索引shard分配详情\")\n    public Result<List<IndexShardInfoVO>> getIndexShard(@PathVariable String cluster, @PathVariable String indexName,\n                                                        HttpServletRequest request) {\n        return indicesManager.getIndexShardsInfo(cluster, indexName, HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/{clusterPhyName}/phy/indices\")\n    @ResponseBody\n    @ApiModelProperty(value = \"获取物理集群索引列表\")\n    public Result<List<String>> getClusterPhyIndexName(@PathVariable String clusterPhyName,\n                                                       @RequestParam(value = \"index\",required = false) String index,\n                                                       HttpServletRequest request) {\n        return indicesManager.getClusterPhyIndexName(clusterPhyName, HttpRequestUtil.getProjectId(request),index);\n    }\n\n    @GetMapping(\"/{clusterLogicName}/logic/indices\")\n    @ResponseBody\n    @ApiModelProperty(value = \"获取逻辑集群索引列表\")\n    public Result<List<String>> getClusterLogicIndexName(@PathVariable String clusterLogicName,  @RequestParam(value = \"index\",required = false) String index,\n                                                         HttpServletRequest request) {\n        return indicesManager.getClusterLogicIndexName(clusterLogicName, HttpRequestUtil.getProjectId(request),index);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/indices/IndicesSrvController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.indices;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.indices.IndicesManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.IndexCatCellDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.manage.IndexCatCellWithConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.srv.IndexForceMergeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.indices.srv.IndexRolloverDTO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport com.google.common.collect.Lists;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author chengxiang\n * @date 2022/5/31\n */\n@RestController\n@RequestMapping(V3 + \"/indices/srv\")\n@Api(tags = \"索引服务\")\npublic class IndicesSrvController extends BaseIndicesController {\n\n    @Autowired\n    private IndicesManager indicesManager;\n\n    @PostMapping(\"/rollover\")\n    @ResponseBody\n    @ApiOperation(value = \"rollover\")\n    public Result<Void> rollover(HttpServletRequest request, @RequestBody IndexRolloverDTO param) {\n        List<IndexCatCellDTO> indices = param.getIndices();\n        Result<Boolean> checkClusterValidResult = checkClusterValid(\n            indices.stream().map(IndexCatCellDTO::getCluster).distinct().collect(Collectors.toList()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.rollover(param, HttpRequestUtil.getOperator(request),HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/shrink\")\n    @ResponseBody\n    @ApiOperation(value = \"shrink\")\n    public Result<Void> shrink(HttpServletRequest request, @RequestBody IndexCatCellWithConfigDTO param) {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(Lists.newArrayList(param.getCluster()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.shrink(param, HttpRequestUtil.getOperator(request),HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/split\")\n    @ResponseBody\n    @ApiOperation(value = \"split\")\n    public Result<Void> split(HttpServletRequest request, @RequestBody IndexCatCellWithConfigDTO param) {\n        Result<Boolean> checkClusterValidResult = checkClusterValid(Lists.newArrayList(param.getCluster()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.split(param, HttpRequestUtil.getOperator(request),HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/force-merge\")\n    @ResponseBody\n    @ApiOperation(value = \"forceMerge\")\n    public Result<Void> forceMerge(HttpServletRequest request, @RequestBody IndexForceMergeDTO param) {\n        List<IndexCatCellDTO> indices = param.getIndices();\n        Result<Boolean> checkClusterValidResult = checkClusterValid(\n            indices.stream().map(IndexCatCellDTO::getCluster).distinct().collect(Collectors.toList()));\n        if (checkClusterValidResult.failed()) {\n            return Result.buildFrom(checkClusterValidResult);\n        }\n\n        return indicesManager.forceMerge(param, HttpRequestUtil.getOperator(request),HttpRequestUtil.getProjectId(request));\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/metrics/ClusterPhyMetricsController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.ClusterPhyMetricsManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.ESClusterOverviewMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.ESClusterTaskDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyTypeMetricsEnum;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiModelProperty;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n/**\n * @author linyunan\n * @date 2021-07-30\n */\n@RestController()\n@RequestMapping({ V3 + \"/metrics/cluster\" })\n@Api(tags = \"ES物理集群监控信息\")\npublic class ClusterPhyMetricsController {\n    @Autowired\n    private ClusterPhyMetricsManager clusterPhyMetricsManager;\n\n    @Autowired\n    private ClusterPhyManager        clusterPhyManager;\n\n    @GetMapping(\"/clusters\")\n    @ResponseBody\n    @ApiOperation(value = \"根据ProjectId获取集群名称列表\")\n    public Result<List<String>> getClusterPhyNames(HttpServletRequest request) {\n        return Result.buildSucc(clusterPhyManager.listClusterPhyNameByProjectId(HttpRequestUtil.getProjectId(request)));\n    }\n\n    @GetMapping(\"/{type}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群看板指标类型\", notes = \"type = clusterOverview, clusterNode, clusterNodeIndices\")\n    public Result<List<String>> getClusterPhyMetricsTypes(@PathVariable String type) {\n        return Result.buildSucc(clusterPhyMetricsManager.getMetricsCode2TypeMap(type));\n    }\n\n    @PostMapping(\"/config-metrics\")\n    @ResponseBody\n    @ApiOperation(value = \"获取账号下已配置指标类型\")\n    public Result<List<String>> listClusterPhyMetricsTypes(@RequestBody UserConfigInfoDTO param,\n                                                          HttpServletRequest request) {\n        return Result\n            .buildSucc(clusterPhyMetricsManager.listConfigMetricsByCondition(param, HttpRequestUtil.getOperator(request),HttpRequestUtil.getProjectId(request)));\n    }\n\n    @PutMapping(\"/config-metrics\")\n    @ResponseBody\n    @ApiOperation(value = \"更新账号下已配置指标类型\")\n    public Result<Integer> updateClusterPhyMetricsTypes(@RequestBody UserConfigInfoDTO param,\n                                                        HttpServletRequest request) {\n        return clusterPhyMetricsManager.updateConfigMetricsByCondition(param, HttpRequestUtil.getOperator(request),HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/overview\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群总览指标信息\")\n    public Result<ESClusterOverviewMetricsVO> getClusterPhyMetrics(@RequestBody MetricsClusterPhyDTO param,\n                                                                   HttpServletRequest request) {\n        return clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request), ClusterPhyTypeMetricsEnum.CLUSTER);\n    }\n\n    @PostMapping(\"/node\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群节点指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getClusterPhyNodesMetrics(@RequestBody MetricsClusterPhyNodeDTO param,\n                                                                             HttpServletRequest request) {\n        return clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request), ClusterPhyTypeMetricsEnum.NODE);\n    }\n\n    @PostMapping(\"/nodes\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群多个节点指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getMultiClusterPhyNodesMetrics(@RequestBody MultiMetricsClusterPhyNodeDTO param,\n                                                                                  HttpServletRequest request) {\n        return clusterPhyMetricsManager.getMultiClusterMetrics(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request), ClusterPhyTypeMetricsEnum.NODE);\n    }\n\n    @PostMapping(\"/index\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群索引指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getClusterPhyIndicesMetrics(@RequestBody MetricsClusterPhyIndicesDTO param,\n                                                                               HttpServletRequest request) {\n        return clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request), ClusterPhyTypeMetricsEnum.INDICES);\n    }\n\n    @PostMapping(\"/indices\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群多个索引指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getMultiClusterPhyIndicesMetrics(@RequestBody MultiMetricsClusterPhyIndicesDTO param,\n                                                                               HttpServletRequest request) {\n        return clusterPhyMetricsManager.getMultiClusterIndicesMetrics(param, HttpRequestUtil.getProjectId(request),\n                HttpRequestUtil.getOperator(request), ClusterPhyTypeMetricsEnum.INDICES);\n    }\n\n    @PostMapping(\"/template\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群索引模板指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getClusterPhyTemplateMetrics(@RequestBody MetricsClusterPhyTemplateDTO param,\n                                                                                HttpServletRequest request) {\n        return clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request), ClusterPhyTypeMetricsEnum.TEMPLATES);\n    }\n\n    @PostMapping(\"/templates\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群多个索引模板指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getMultiClusterPhyTemplateMetrics(@RequestBody MultiMetricsClusterPhyTemplateDTO param,\n                                                                                HttpServletRequest request) {\n        return clusterPhyMetricsManager.getMultiClusterTemplatesMetrics(param, HttpRequestUtil.getProjectId(request),\n                HttpRequestUtil.getOperator(request), ClusterPhyTypeMetricsEnum.TEMPLATES);\n    }\n\n    @GetMapping(\"{clusterPhyName}/{node}/task\")\n    @ResponseBody\n    @ApiModelProperty(value = \"获取物理集群节点task详情\")\n    public Result<List<ESClusterTaskDetailVO>> getClusterPhyTaskDetail(@PathVariable String clusterPhyName,\n                                                                       @PathVariable String node,\n                                                                       @RequestParam(\"startTime\") String startTime,\n                                                                       @RequestParam(\"endTime\") String endTime,\n                                                                       HttpServletRequest request) {\n        return clusterPhyMetricsManager.getClusterPhyTaskDetail(clusterPhyName, node, startTime, endTime,\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/node/task\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群节点task指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getClusterPhyNodesTaskMetrics(@RequestBody MultiMetricsClusterPhyNodeTaskDTO param,\n                                                                                 HttpServletRequest request) {\n        return clusterPhyMetricsManager.getMultiClusterMetrics(param, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request), ClusterPhyTypeMetricsEnum.NODE_TASKS);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/metrics/DashboardMetricsController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.DashboardMetricsManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardListDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardTopNDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.config.AriusConfigInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.list.MetricListVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.dashboard.ClusterPhyHealthMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n/**\n * Created by linyunan on 3/14/22\n */\n@RestController()\n@RequestMapping(V3 + \"/dashboard/metrics\")\n@Api(tags = \"dashboard监控信息\")\npublic class DashboardMetricsController {\n    @Autowired\n    private DashboardMetricsManager dashboardMetricsManager;\n\n    @GetMapping(\"/health\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard大盘健康状态信息\")\n    public Result<ClusterPhyHealthMetricsVO> getClusterHealthInfo(HttpServletRequest request) {\n        return dashboardMetricsManager.getClusterHealthInfo(HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/top/cluster\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard大盘TopN集群相关指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getTopClusterMetricsInfo(@RequestBody MetricsDashboardTopNDTO param,\n                                                                            HttpServletRequest request) {\n        return dashboardMetricsManager.getTopClusterMetricsInfo(param, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/top/node\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard大盘TopN节点相关指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getTopNodeMetricsInfo(@RequestBody MetricsDashboardTopNDTO param,\n                                                                         HttpServletRequest request) {\n        return dashboardMetricsManager.getTopNodeMetricsInfo(param, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/top/template\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard大盘TopN模板相关指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getTopTemplateMetricsInfo(@RequestBody MetricsDashboardTopNDTO param,\n                                                                             HttpServletRequest request) {\n        return dashboardMetricsManager.getTopTemplateMetricsInfo(param, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/top/index\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard大盘TopN索引相关指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getTopIndexMetricsInfo(@RequestBody MetricsDashboardTopNDTO param,\n                                                                          HttpServletRequest request) {\n        return dashboardMetricsManager.getTopIndexMetricsInfo(param, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/top/cluster-thread-pool-queue\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard大盘TopNES线程池相关指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getTopClusterThreadPoolQueueMetricsInfo(@RequestBody MetricsDashboardTopNDTO param,\n                                                                                           HttpServletRequest request) {\n        return dashboardMetricsManager.getTopClusterThreadPoolQueueMetricsInfo(param,\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/list/cluster\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard大盘集群相关list列表指标信息\")\n    public Result<List<MetricListVO>> getListClusterMetricsInfo(@RequestBody MetricsDashboardListDTO param,\n                                                                HttpServletRequest request) {\n        return dashboardMetricsManager.getListClusterMetricsInfo(param, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/list/node\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard大盘节点相关list列表指标信息\")\n    public Result<List<MetricListVO>> getListNodeMetricsInfo(@RequestBody MetricsDashboardListDTO param,\n                                                             HttpServletRequest request) {\n        return dashboardMetricsManager.getListNodeMetricsInfo(param, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/list/template\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard大盘模板相关list列表指标信息\")\n    public Result<List<MetricListVO>> getListTemplateMetricsInfo(@RequestBody MetricsDashboardListDTO param,\n                                                                 HttpServletRequest request) {\n        return dashboardMetricsManager.getListTemplateMetricsInfo(param, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/list/index\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard大盘索引相关list列表指标信息\")\n    public Result<List<MetricListVO>> getListIndexMetricsInfo(@RequestBody MetricsDashboardListDTO param,\n                                                              HttpServletRequest request) {\n        return dashboardMetricsManager.getListIndexMetricsInfo(param, HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/dashboard-threshold\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dashboard阈值\")\n    public Result<List<AriusConfigInfoVO>> dashboardThresholds() {\n        return Result.buildSucc(dashboardMetricsManager.dashboardThresholds());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/metrics/GatewayMetricsController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.metrics;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport javax.servlet.http.HttpServletRequest;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport com.didichuxing.datachannel.arius.admin.biz.gateway.GatewayManager;\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.GatewayMetricsManager;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.gateway.GatewayOverviewMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.GatewayMetricsTypeEnum;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiModelProperty;\nimport io.swagger.annotations.ApiOperation;\n\n@RestController\n@RequestMapping({ V3 + \"/metrics/gateway\" })\n@Api(tags = \"Gateway指标监控信息\")\npublic class GatewayMetricsController {\n\n    @Autowired\n    private GatewayMetricsManager gatewayMetricsManager;\n    @Autowired\n    private GatewayManager        gatewayManager;\n\n    @GetMapping(\"/alive-nodes\")\n    @ResponseBody\n    @ApiOperation(value = \"获取gateway存活节点名称列表接口\")\n    public Result<List<String>> getGatewayAliveNodeNames(HttpServletRequest request) {\n        return gatewayManager.getGatewayAliveNodeNames(\"Normal\");\n    }\n\n    @GetMapping(\"/config/{group}\")\n    @ApiOperation(value = \"获取不同组的指标\")\n    public Result<List<String>> getGatewayMetrics(@PathVariable String group) {\n        return gatewayMetricsManager.getGatewayMetricsEnums(group);\n    }\n\n    @GetMapping(\"/dsl-md5\")\n    @ApiOperation(value = \"获取当前项目下的dslMd5列表\")\n    public Result<List<String>> getDslMd5List(Long startTime, Long endTime, HttpServletRequest request) {\n        return gatewayMetricsManager.getDslMd5List(HttpRequestUtil.getProjectId(request), startTime, endTime);\n    }\n\n    @PostMapping(\"/overview\")\n    @ApiOperation(value = \"获取gateway概览\")\n    public Result<List<GatewayOverviewMetricsVO>> getGatewayOverviewMetrics(@RequestBody GatewayOverviewDTO dto) {\n        validateParam(dto);\n        return gatewayMetricsManager.getGatewayOverviewMetrics(dto);\n    }\n\n    @PostMapping(\"/node\")\n    @ApiOperation(value = \"获取gateway节点指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getGatewayNodeMetrics(@RequestBody GatewayNodeDTO dto,\n                                                                         HttpServletRequest request) {\n        validateParam(dto);\n        return gatewayMetricsManager.getGatewayNodeMetrics(dto, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/nodes\")\n    @ApiOperation(value = \"获取多节点gateway节点指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getMultiGatewayNodesMetrics(@RequestBody MultiGatewayNodesDTO dto,\n                                                                               HttpServletRequest request) {\n        validateParam(dto);\n        return gatewayMetricsManager.getMultiGatewayNodesMetrics(dto, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/client-node\")\n    @ApiOperation(value = \"获取gatewayNode相关的clientNode指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getClientNodeMetrics(@RequestBody ClientNodeDTO dto,\n                                                                        HttpServletRequest request) {\n        validateParam(dto);\n        return gatewayMetricsManager.getClientNodeMetrics(dto, HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/client-node-ip\")\n    @ApiOperation(value = \"获取取gatewayNode相关的clientNode ip列表\")\n    public Result<List<Tuple<String,String>>> getClientNodeIpList(String gatewayNode, Long startTime, Long endTime,\n                                                          HttpServletRequest request) {\n        return gatewayMetricsManager.getClientNodeIdList(gatewayNode, startTime, endTime,\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/index\")\n    @ApiOperation(value = \"获取gateway索引指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getGatewayIndexMetrics(@RequestBody GatewayIndexDTO dto,\n                                                                          HttpServletRequest request) {\n        validateParam(dto);\n        return gatewayMetricsManager.getGatewayIndexMetrics(dto, HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/projects\")\n    @ApiModelProperty(value = \"获取gateway项目指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getGatewayAppMetrics(@RequestBody GatewayProjectDTO dto) {\n        validateParam(dto);\n        return gatewayMetricsManager.getGatewayAppMetrics(dto);\n    }\n\n    @PostMapping(\"/dsl\")\n    @ApiModelProperty(value = \"获取gateway查询模版指标信息\")\n    public Result<List<VariousLineChartMetricsVO>> getGatewayDslMetrics(@RequestBody GatewayDslDTO dto,\n                                                                        HttpServletRequest request) {\n        validateParam(dto);\n        return gatewayMetricsManager.getGatewayDslMetrics(dto, HttpRequestUtil.getProjectId(request));\n    }\n\n    private void validateParam(GatewayMetricsDTO dto) {\n        dto.validParam();\n        //检查是否有不合法的指标传过来\n        List<String> metricsByGroup = GatewayMetricsTypeEnum.getMetricsByGroup(dto.getGroup());\n        String invalidMetrics = dto.getMetricsTypes().stream().filter(x -> !metricsByGroup.contains(x))\n            .collect(Collectors.joining(\",\"));\n        if (StringUtils.isNotBlank(invalidMetrics)) {\n            throw new RuntimeException(\"非法指标:\" + invalidMetrics);\n        }\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/metrics/MetricsDictionaryController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.MetricsDictionaryManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricDictionaryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.dictionary.MetricsDictionaryVO;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n/**\n * 详细介绍类情况.\n *\n * @ClassName MetricsDictionaryController\n * @Author gyp\n * @Date 2022/9/28\n * @Version 1.0\n */\n@RestController\n@RequestMapping({V3 + \"/metrics/dictionary\"})\n@Api(tags = \"指标字典信息\")\npublic class MetricsDictionaryController {\n    @Autowired\n    private MetricsDictionaryManager metricsDictionaryManager;\n\n    @PostMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"通过model筛选获取指标字典信息\")\n    public Result<List<MetricsDictionaryVO>> listMetricsDictionaries(@RequestBody MetricDictionaryDTO param) {\n        return metricsDictionaryManager.listByCondition(param);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/task/OpTaskController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.task;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.task.OpTaskQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.OpTaskVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.TaskTypeVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.WorkTaskVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n/**\n * @author fengqiongfeng\n * @date 2020/08/24\n */\n@Api(tags = \"任务相关接口(REST)\")\n@RestController\n@RequestMapping({ V3 + \"/op-task\" })\npublic class OpTaskController {\n    private static final ILog LOGGER = LogFactory.getLog(OpTaskController.class);\n\n    @Autowired\n    private OpTaskManager     opTaskManager;\n\n    @ApiOperation(value = \"任务类型\", notes = \"\")\n    @GetMapping(value = \"/type-enums\")\n    @ResponseBody\n    public Result<List<TaskTypeVO>> getOrderTypes() {\n        List<TaskTypeVO> voList = new ArrayList<>();\n        for (OpTaskTypeEnum elem : OpTaskTypeEnum.values()) {\n            voList.add(new TaskTypeVO(elem.getType(), elem.getMessage()));\n        }\n        return Result.buildSucc(voList);\n    }\n\n    @ApiOperation(value = \"任务详情\", notes = \"\")\n    @GetMapping(value = \"/{taskId}\")\n    @ResponseBody\n    public Result<WorkTaskVO> getOrderDetail(@PathVariable(value = \"taskId\") Integer taskId) {\n        Result<OpTask> result = opTaskManager.getById(taskId);\n        if (result.failed()) {\n            return Result.buildFrom(result);\n        }\n        return Result.buildSucc(ConvertUtil.obj2Obj(result.getData(), WorkTaskVO.class));\n    }\n\n    @ApiOperation(value = \"任务列表\", notes = \"\")\n    @GetMapping(value = \"tasks\")\n    @ResponseBody\n    @Deprecated\n    public Result<List<WorkTaskVO>> getTaskList() {\n        return Result.buildSucc(ConvertUtil.list2List(opTaskManager.list().getData(), WorkTaskVO.class));\n    }\n\n    @ApiOperation(value = \"任务中心分页列表\", notes = \"\")\n    @PostMapping(value = \"page\")\n    @ResponseBody\n    public PaginationResult<OpTaskVO> pageGetTasks(@RequestBody OpTaskQueryDTO queryDTO, HttpServletRequest request) throws NotFindSubclassException {\n        return opTaskManager.pageGetTasks(HttpRequestUtil.getProjectId(request), queryDTO);\n    }\n\n    @PostMapping(path = \"/{type}\")\n    @ResponseBody\n    @ApiOperation(value = \"提交任务接口\", notes = \"\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"String\", name = \"type\", value = \"任务类型\", required = true) })\n    public Result<WorkTaskVO> addTask(HttpServletRequest request, @PathVariable(value = \"type\") String code,\n                                      @RequestBody OpTaskDTO opTaskDTO) throws NotFindSubclassException {\n        String dataCenter = opTaskDTO.getDataCenter();\n        String user = HttpRequestUtil.getOperator(request);\n\n        opTaskDTO.setTaskType(OpTaskTypeEnum.valueOfPath(code).getType());\n        opTaskDTO.setCreator(user);\n        LOGGER.info(\n            \"class=OpTaskController||method=OpTaskController.addTask||workTaskDTO={}||envInfo={}||dataCenter={}\",\n            JSON.toJSONString(opTaskDTO), EnvUtil.getStr(), dataCenter);\n\n        Result<OpTask> result = opTaskManager.addTask(opTaskDTO, AuthConstant.SUPER_PROJECT_ID);\n        if (result.failed()) {\n            return Result.buildFail(result.getMessage());\n        }\n        return Result.buildSucc(ConvertUtil.obj2Obj(result.getData(), WorkTaskVO.class));\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/task/OpTaskDCDRController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.task;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.dcdr.TemplateDCDRManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.DCDRMasterSlaveSwitchDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.task.WorkTaskVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DCDRSingleTemplateMasterSlaveSwitchDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.DCDRTasksDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(V3 + \"/dcdr/work-order/task\")\n@Api(tags = \"DCDR任务相关接口(REST)\")\npublic class OpTaskDCDRController {\n\n    @Autowired\n    private TemplateDCDRManager templateDCDRManager;\n\n    @GetMapping(\"/{taskId}/detail\")\n    @ResponseBody\n    @ApiOperation(value = \"获取dcdr主从切换任务详情\")\n    public Result<DCDRTasksDetailVO> getDCDRMasterSlaveSwitchDetailVO(@PathVariable(\"taskId\") Integer taskId) {\n        return templateDCDRManager.getDCDRMasterSlaveSwitchDetailVO(taskId);\n    }\n\n    @GetMapping(\"/{taskId}/{templateId}/detail\")\n    @ResponseBody\n    @ApiOperation(value = \"获取模板dcdr主从切换任务详情\")\n    public Result<DCDRSingleTemplateMasterSlaveSwitchDetailVO> getDCDRSingleTemplateMasterSlaveSwitchDetailVO(@PathVariable(\"taskId\") Integer taskId,\n                                                                                                              @PathVariable(\"templateId\") Long templateId) {\n        return templateDCDRManager.getDCDRSingleTemplateMasterSlaveSwitchDetailVO(taskId, templateId);\n    }\n\n    @PostMapping(\"/switch-master-slave\")\n    @ResponseBody\n    @ApiOperation(value = \"DCDR主从切换接口\", notes = \"\")\n    public Result<WorkTaskVO> dcdrSwitchMasterSlave(HttpServletRequest request,\n                                                    @RequestBody DCDRMasterSlaveSwitchDTO dcdrMasterSlaveSwitchDTO) {\n        return templateDCDRManager.batchDCDRSwitchMaster2Slave(dcdrMasterSlaveSwitchDTO,\n            HttpRequestUtil.getOperator(request), HttpRequestUtil.getProjectId(request));\n    }\n\n    @DeleteMapping(\"/{taskId}/{templateIds}/cancel\")\n    @ResponseBody\n    @ApiOperation(value = \"根据任务id和模板id取消单个DCDR主从切换任务\", notes = \"\")\n    public Result<Void> cancelDcdrSwitchMasterSlaveByTaskIdAndTemplateIds(HttpServletRequest request,\n                                                                          @PathVariable(\"taskId\") Integer taskId,\n                                                                          @PathVariable(\"templateIds\") List<Long> templateIds) throws ESOperateException {\n        return templateDCDRManager.cancelDCDRSwitchMasterSlaveByTaskIdAndTemplateIds(taskId, templateIds, false,\n            HttpRequestUtil.getOperator(request), HttpRequestUtil.getProjectId(request));\n    }\n\n    @DeleteMapping(\"/{taskId}/cancel\")\n    @ResponseBody\n    @ApiOperation(value = \"根据任务id取消全量DCDR主从切换任务\")\n    public Result<Void> cancelDcdrSwitchMasterSlaveByTaskId(HttpServletRequest request,\n                                                            @PathVariable(\"taskId\") Integer taskId) throws ESOperateException {\n        return templateDCDRManager.cancelDCDRSwitchMasterSlaveByTaskId(taskId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/{taskId}/{templateId}/refresh\")\n    @ResponseBody\n    @ApiOperation(value = \"刷新dcdr链路任务\")\n    public Result<Void> refreshDcdrChannelState(HttpServletRequest request, @PathVariable(\"taskId\") Integer taskId,\n                                                @PathVariable(\"templateId\") Integer templateId) {\n        return templateDCDRManager.refreshDCDRChannelState(taskId, templateId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"/{taskId}/{templateId}/forceSwitch\")\n    @ResponseBody\n    @ApiOperation(value = \"dcdr主从强制切换接口\")\n    public Result<Void> forceSwitchMasterSlave(HttpServletRequest request, @PathVariable(\"taskId\") Integer taskId,\n                                               @PathVariable(\"templateId\") Integer templateId) {\n        return templateDCDRManager.forceSwitchMasterSlave(taskId, templateId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/task/OpTaskEcmController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.task;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_OP;\n\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskDetailManager;\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.EcmTaskBasic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmOperateAppBase;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ecm.response.EcmSubTaskLog;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.ecm.EcmTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm.EcmTaskBasicVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm.EcmTaskDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.ecm.EcmTaskVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.EcmRemoteException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.remote.zeus.bean.constant.EcmActionEnum;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author didi\n * @since 2020-08-24\n */\n@RestController\n@RequestMapping(V3_OP + \"/ecm/work-order/task\")\n@Api(tags = \"ECM任务相关接口(REST)\")\npublic class OpTaskEcmController {\n    private final EcmTaskManager       ecmTaskManager;\n    private final EcmTaskDetailManager ecmTaskDetailManager;\n\n    @Autowired\n    public OpTaskEcmController(EcmTaskManager ecmTaskManager, EcmTaskDetailManager ecmTaskDetailManager) {\n        this.ecmTaskManager = ecmTaskManager;\n        this.ecmTaskDetailManager = ecmTaskDetailManager;\n    }\n\n    @PostMapping(path = \"{taskId}/create\")\n    @ResponseBody\n    @ApiOperation(value = \"启动集群任务\", notes = \"\")\n    public Result<EcmOperateAppBase> savaAndActionEcmTask(HttpServletRequest request,\n                                                          @PathVariable Long taskId) throws EcmRemoteException {\n        return ecmTaskManager.savaAndActionEcmTask(taskId, HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(path = \"{taskId}/continue\")\n    @ResponseBody\n    @ApiOperation(value = \"继续集群任务\", notes = \"\")\n    public Result<EcmOperateAppBase> continueWorkOrderTask(HttpServletRequest request,\n                                                           @PathVariable Long taskId) throws EcmRemoteException {\n        return ecmTaskManager.actionClusterEcmTask(taskId, EcmActionEnum.START, null,\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(path = \"{taskId}/scale\")\n    @ResponseBody\n    @ApiOperation(value = \"扩缩容集群任务\", notes = \"\")\n    public Result<EcmOperateAppBase> scaleWorkOrderTask(HttpServletRequest request,\n                                                        @PathVariable Long taskId) throws EcmRemoteException {\n        return ecmTaskManager.actionClusterEcmTask(taskId, HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(path = \"{taskId}/upgrade\")\n    @ResponseBody\n    @ApiOperation(value = \"升级集群任务\", notes = \"\")\n    public Result<EcmOperateAppBase> upgradeWorkOrderTask(HttpServletRequest request,\n                                                          @PathVariable Long taskId) throws EcmRemoteException {\n        return ecmTaskManager.actionClusterEcmTask(taskId, HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(path = \"{taskId}/restart\")\n    @ResponseBody\n    @ApiOperation(value = \"重启集群任务\", notes = \"\")\n    public Result<EcmOperateAppBase> restartWorkOrderTask(HttpServletRequest request,\n                                                          @PathVariable Long taskId) throws EcmRemoteException {\n        return ecmTaskManager.actionClusterEcmTask(taskId, HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(path = \"{taskId}/pause\")\n    @ResponseBody\n    @ApiOperation(value = \"暂停集群任务\", notes = \"\")\n    public Result<Void> pauseWorkOrderTask(HttpServletRequest request, @PathVariable Long taskId) {\n        return ecmTaskManager.pauseClusterEcmTask(taskId, HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(path = \"{taskId}/retry\")\n    @ResponseBody\n    @ApiOperation(value = \"重试集群任务\", notes = \"\")\n    public Result<Void> retryWorkOrderTask(HttpServletRequest request, @PathVariable Long taskId) {\n        return ecmTaskManager.retryClusterEcmTask(taskId, HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(path = \"{taskId}/skip-failed\")\n    @ResponseBody\n    @ApiOperation(value = \"跳过失败集群节点任务\", notes = \"\")\n    public Result<Void> skipFailedWorkOrderTask(HttpServletRequest request, @PathVariable Long taskId,\n                                                @RequestParam(\"hostname\") String hostname) {\n        return ecmTaskManager.actionClusterHostEcmTask(taskId, EcmActionEnum.SKIP_FAILED, hostname,\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(path = \"{taskId}/redo-failed\")\n    @ResponseBody\n    @ApiOperation(value = \"重做集群失败节点任务\", notes = \"\")\n    public Result<Void> redoFailedWorkOrderTask(HttpServletRequest request, @PathVariable Long taskId,\n                                                @RequestParam(\"hostname\") String hostname) {\n        return ecmTaskManager.actionClusterHostEcmTask(taskId, EcmActionEnum.REDO_FAILED, hostname,\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(path = \"{taskId}/cancel\")\n    @ResponseBody\n    @ApiOperation(value = \"取消整个集群任务\", notes = \"\")\n    public Result<Void> cancelWorkOrderTask(HttpServletRequest request, @PathVariable Long taskId) {\n        return ecmTaskManager.cancelClusterEcmTask(taskId, HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(path = \"\")\n    @ResponseBody\n    @ApiOperation(value = \"任务列表接口\", notes = \"\")\n    public Result<List<EcmTaskVO>> listWorkOrderTask() {\n        List<EcmTask> ecmTaskPOList = ecmTaskManager.listEcmTask();\n        if (AriusObjUtils.isNull(ecmTaskPOList)) {\n            return Result.buildNotExist(ResultType.NOT_EXIST.getMessage());\n        }\n\n        return Result.buildSucc(ConvertUtil.list2List(ecmTaskPOList, EcmTaskVO.class));\n    }\n\n    @GetMapping(path = \"/{taskId}/basic-info\")\n    @ResponseBody\n    @ApiOperation(value = \"任务基本信息\", notes = \"\")\n    public Result<EcmTaskBasicVO> getWorkOrderTaskBasic(@PathVariable Long taskId) {\n        Result<EcmTaskBasic> workOrderTaskBasicResult = ecmTaskManager.getEcmTaskBasicByTaskId(taskId);\n        if (workOrderTaskBasicResult.failed()) {\n            return Result.buildFail(workOrderTaskBasicResult.getMessage());\n        }\n        return Result.buildSucc(ConvertUtil.obj2Obj(workOrderTaskBasicResult.getData(), EcmTaskBasicVO.class));\n    }\n\n    @GetMapping(path = \"{taskId}/task-details\")\n    @ResponseBody\n    @ApiOperation(value = \"任务详细信息\", notes = \"\")\n    public Result<EcmTaskDetailVO> clusterTaskDetails(@PathVariable Long taskId) throws AdminTaskException {\n        return Result.buildSucc(\n            ConvertUtil.obj2Obj(ecmTaskDetailManager.getEcmTaskDetailInfo(taskId).getData(), EcmTaskDetailVO.class));\n    }\n\n    @GetMapping(path = \"{detailId}/task-detail/log\")\n    @ResponseBody\n    @ApiOperation(value = \"工单任务详情操作日志接口\", notes = \"\")\n    public Result<EcmSubTaskLog> clusterTaskDetailLog(HttpServletRequest request, @PathVariable Long detailId) {\n        return ecmTaskDetailManager.getTaskDetailLog(detailId, HttpRequestUtil.getOperator(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/template/BaseTemplateController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport org.springframework.beans.factory.annotation.Autowired;\n\npublic class BaseTemplateController {\n\n    protected static final ILog    LOGGER = LogFactory.getLog(TemplateController.class);\n\n    @Autowired\n    protected IndexTemplateService indexTemplateService;\n\n   \n\n    @Autowired\n    protected ProjectService       projectService;\n\n    /**\n     * Check是否有逻辑索引操作权限\n     *\n     * @param logicId 逻辑模板ID\n     * @return\n     */\n    protected Result<Void> checkProjectAuth(Integer logicId) {\n\n\n        return Result.buildSucc();\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/template/TemplateAccessController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.template;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplatePhyStaticsManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ProjectIdTemplateAccessCountVO;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport io.swagger.annotations.ApiParam;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n@RestController\n@RequestMapping(V3 + \"/template/access\")\n@Api(tags = \"Console-用户侧索引模板访问统计信息接口(REST)\")\npublic class TemplateAccessController extends BaseTemplateController {\n\n    @Autowired\n    private TemplatePhyStaticsManager templatePhyStaticsManager;\n\n    /**\n     * 根据模板名称获取最近days天的projectId访问统计信息\n     *\n     * @param logicTemplateId 逻辑索引模板ID\n     * @param days 最近多少天\n     * @return\n     */\n    @GetMapping(path = \"/project-ids\")\n    @ApiOperation(value = \"根据模板名称获取最近days天的projectId访问统计信息【三方接口】\", tags = \"【三方接口】\")\n    public Result<Map<Integer, Long>> getAccessProjectIds(@ApiParam(name = \"templateId\", value = \"逻辑索引模板ID\", required = true) @RequestParam(value = \"templateId\") int logicTemplateId,\n\n                                                          @ApiParam(name = \"days\", value = \"最近多少天\", required = true) @RequestParam(value = \"days\") int days) {\n        return templatePhyStaticsManager.getAccessStatsInfoByTemplateIdAndDays(logicTemplateId, days);\n    }\n\n    /**\n     * 根据模板Id获取[startDate, endDate]的projectId访问统计信息\n     *\n     * @param logicTemplateId 逻辑索引模板ID\n     * @param startDate 开始时刻\n     * @param endDate 结束时刻\n     * @return\n     */\n    @GetMapping(path = \"/project-info-date-range\")\n    @ApiOperation(value = \"根据模板Id获取[startDate, endDate(毫秒)]的projectId访问统计信息【三方接口】\", tags = \"【三方接口】\")\n    public Result<List<ProjectIdTemplateAccessCountVO>> getAccessAppInfos(@ApiParam(name = \"templateId\", value = \"逻辑索引模板ID\", required = true) @RequestParam(value = \"templateId\") int logicTemplateId,\n\n                                                                          @ApiParam(name = \"startDate\", value = \"开始时刻\", required = true) @RequestParam(value = \"startDate\") Long startDate,\n\n                                                                          @ApiParam(name = \"endDate\", value = \"结束时刻\", required = true) @RequestParam(value = \"endDate\") Long endDate) {\n        return templatePhyStaticsManager.getAccessAppInfos(logicTemplateId, startDate, endDate);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/template/TemplateController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.template;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterLogicManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplateLogicManager;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateRateLimitDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateUpdateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateClearDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateClearVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateDeleteVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateRateLimitVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateCyclicalRollInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AmsRemoteException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author d06679\n * @date 2019/5/15\n */\n@RestController\n@RequestMapping(V3 + \"/template\")\n@Api(tags = \"Console-用户侧索引模板接口(REST)\")\npublic class TemplateController extends BaseTemplateController {\n\n    private static final ILog    LOGGER = LogFactory.getLog(TemplateController.class);\n\n    @Autowired\n    private TemplateLogicManager templateLogicManager;\n\n    @Autowired\n    private ClusterLogicManager  clusterLogicManager;\n\n    @GetMapping(\"/{projectId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取索引列表【三方接口】\", tags = \"【三方接口】\", notes = \"包含权限、集群信息、权限信息；\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"projectId\", value = \"应用ID，不会过滤索引，会影响权限信息\", required = true) })\n    public Result<List<ConsoleTemplateVO>> getConsoleTemplates(@PathVariable(value = \"projectId\", required = true) Integer projectId) {\n\n        return Result.buildSucc(templateLogicManager.getConsoleTemplatesVOS(projectId));\n    }\n\n    @GetMapping(\"/detail/{logicId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取模板详细信息接口【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParam(type = \"Integer\", name = \"logicId\", value = \"逻辑模板ID\", required = true)\n    public Result<ConsoleTemplateDetailVO> detail(HttpServletRequest request,\n                                                  @PathVariable(\"logicId\") Integer logicId) {\n\n        return templateLogicManager.getDetailVoByLogicId(logicId, HttpRequestUtil.getProjectId(request));\n\n    }\n\n    @PutMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"用户编辑模板接口【三方接口】\", tags = \"【三方接口】\", notes = \"支持修改数据类型、责任人、备注\")\n    public Result<Void> modifyConsoleTemplate(HttpServletRequest request,\n                                              @RequestBody ConsoleTemplateUpdateDTO templateLogicDTO) throws AdminOperateException {\n        return templateLogicManager.editTemplate(ConvertUtil.obj2Obj(templateLogicDTO, IndexTemplateDTO.class),\n            HttpRequestUtil.getOperator(request), HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/logic/indices\")\n    @ResponseBody\n    @ApiOperation(value = \"获取索引清理信息接口【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Integer\", name = \"logicId\", value = \"索引ID\", required = true) })\n    public Result<ConsoleTemplateClearVO> getLogicTemplateClearInfo(@RequestParam(\"logicId\") Integer logicId) throws AmsRemoteException {\n\n        return templateLogicManager.getLogicTemplateClearInfo(logicId);\n    }\n\n    @PutMapping(\"/clear-info\")\n    @ResponseBody\n    @ApiOperation(value = \"清理索引信息接口【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"header\", dataType = \"String\", name = HttpRequestUtil.PROJECT_ID, value = \"应用ID\", required = true) })\n    @Deprecated\n    public Result<Void> clearLogicTemplateIndices(HttpServletRequest request,\n                                                  @RequestBody TemplateClearDTO clearDTO) throws ESOperateException {\n        Result<Void> checkAuthResult = checkProjectAuth(clearDTO.getLogicId());\n        if (checkAuthResult.failed()) {\n            return checkAuthResult;\n        }\n\n        return clusterLogicManager.clearIndices(clearDTO, HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/delete-info/{logicId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取将要索引下线信息接口【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"logicId\", value = \"索引ID\", required = true) })\n    public Result<ConsoleTemplateDeleteVO> getLogicTemplateDeleteInfo(@PathVariable(\"logicId\") Integer logicId) throws AmsRemoteException {\n\n        return templateLogicManager.getLogicTemplateDeleteInfo(logicId);\n    }\n\n    @DeleteMapping(\"/delete-info/{logicId}\")\n    @ResponseBody\n    @ApiOperation(value = \"下线索引信息接口【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"logicId\", value = \"索引ID\", required = true) })\n    public Result<Void> deleteTemplate(HttpServletRequest request,\n                                       @PathVariable(\"logicId\") Integer logicId) throws AdminOperateException {\n        Result<Void> checkAuthResult = checkProjectAuth(logicId);\n        if (checkAuthResult.failed()) {\n            return checkAuthResult;\n        }\n        return templateLogicManager.delTemplate(logicId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/indices/{projectId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取project Id所有模板的索引【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"projectId\", value = \"应用ID\", required = true) })\n    public Result<List<Tuple<String, String>>> getLogicTemplatesByProjectId(HttpServletRequest request,\n                                                                            @PathVariable(\"projectId\") Integer projectId) {\n        return templateLogicManager.listLogicTemplatesByProjectId(projectId);\n    }\n\n    @GetMapping(\"/cyclical-roll\")\n    @ResponseBody\n    @ApiOperation(value = \"获取索引分区信息\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Integer\", name = \"logicId\", value = \"索引ID\", required = true) })\n    public Result<List<TemplateCyclicalRollInfoVO>> getCyclicalRollInfo(HttpServletRequest request,\n                                                                        @RequestParam(\"logicId\") Integer logicId) {\n\n        return templateLogicManager.getCyclicalRollInfo(logicId);\n    }\n\n    /**\n     * 获取模板当前限流值\n     */\n    @GetMapping(path = \"/rate-limit\")\n    @ResponseBody\n    @ApiOperation(value = \"获取模板当前限流值接口【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Integer\", name = \"logicId\", value = \"索引ID\", required = true) })\n    public Result<ConsoleTemplateRateLimitVO> getTemplateRateLimit(@RequestParam(\"logicId\") Integer logicId) { // 一个逻辑模板可能有master slave两种，限流查看时，默认查看master即可\n\n        return templateLogicManager.getTemplateRateLimit(logicId);\n\n    }\n\n    /**\n     * 更新模板当前限流值，更新时复用存量逻辑，调整时以百分比变更[-99,1000]\n     *  @param consoleTemplateRateLimitDTO 索引模板限流调整表单信息\n     *  @return\n     *  @throws AdminOperateException\n     */\n    @PutMapping(path = \"/rate-limit\")\n    @ResponseBody\n    @ApiOperation(value = \"更新模板当前限流值接口【三方接口】\", tags = \"【三方接口】\")\n    public Result updateTemplateRateLimit(HttpServletRequest request,\n                                          @RequestBody ConsoleTemplateRateLimitDTO consoleTemplateRateLimitDTO) {\n\n        return templateLogicManager.updateTemplateWriteRateLimit(consoleTemplateRateLimitDTO,\n            HttpRequestUtil.getOperator(request), HttpRequestUtil.getProjectId(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/template/TemplateDCDRController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.template;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.dcdr.TemplateDCDRManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateDCDRInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping({ V3 + \"/template/dcdr\" })\n@Api(tags = \"模板DCDR接口(REST)\")\npublic class TemplateDCDRController {\n\n    @Autowired\n    private TemplateDCDRManager templateDCDRManager;\n\n    @PostMapping(\"/{templateId}/{regionId}/{targetCluster}\")\n    @ResponseBody\n    @ApiOperation(value = \"DCDR链路创建接口\", notes = \"\")\n    public Result<Void> createDCDR(HttpServletRequest request, @PathVariable(\"templateId\") Integer templateId,\n                                   @PathVariable(\"targetCluster\") String targetCluster,\n                                   @PathVariable(\"regionId\") Integer regionId) throws AdminOperateException {\n        return templateDCDRManager.copyAndCreateDCDR(templateId, targetCluster, regionId,\n            HttpRequestUtil.getOperator(request), HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/{templateId}\")\n    @ResponseBody\n    @ApiOperation(\"获取模板DCDR详情\")\n    public Result<TemplateDCDRInfoVO> getTemplateDCDRInfo(@PathVariable(\"templateId\") Integer templateId)\n            throws ESOperateException {\n        return templateDCDRManager.getTemplateDCDRInfoVO(templateId);\n    }\n\n    @DeleteMapping(\"/{templateId}\")\n    @ResponseBody\n    @ApiOperation(value = \"DCDR链路删除接口\", notes = \"\")\n    public Result<Void> deleteDcdr(HttpServletRequest request,\n                                   @PathVariable(value = \"templateId\") Integer templateId) throws AdminOperateException {\n\n        return templateDCDRManager.deleteDCDR(templateId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request),false);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/template/TemplateLogicV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.template;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplateLogicManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.setting.TemplateLogicSettingsManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateWithCreateInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateClearDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplateSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateSettingVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.template.DataTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport java.util.Map;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Created by linyunan on 2021-07-30\n */\n@RestController\n@RequestMapping({ V3 + \"/template/logic\" })\n@Api(tags = \"逻辑模板接口(REST)\")\npublic class TemplateLogicV3Controller {\n\n    @Autowired\n    private TemplateLogicManager         templateLogicManager;\n\n    @Autowired\n    private TemplateLogicSettingsManager templateLogicSettingManager;\n\n    @GetMapping(\"/data-type\")\n    @ResponseBody\n    @ApiOperation(value = \"获取逻辑模版创建的类型\")\n    public Result<Map<Integer, String>> templateLogicDataType(HttpServletRequest request) {\n        return Result.buildSucc(DataTypeEnum.code2DescMap());\n    }\n\n    @GetMapping(\"/names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取逻辑模板名称列表接口\")\n    public Result<List<String>> listTemplateLogicNames(HttpServletRequest request) {\n        return Result.buildSucc(templateLogicManager.getTemplateLogicNames(HttpRequestUtil.getProjectId(request)));\n    }\n\n    @PostMapping(\"/page\")\n    @ResponseBody\n    @ApiOperation(value = \"模糊查询模板列表\")\n    public PaginationResult<ConsoleTemplateVO> pageGetConsoleTemplateVOS(HttpServletRequest request,\n                                                                         @RequestBody TemplateConditionDTO condition) throws NotFindSubclassException {\n        return templateLogicManager.pageGetConsoleTemplateVOS(condition, HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/{templateName}/name-check\")\n    @ResponseBody\n    @ApiOperation(value = \"校验模板名称是否合法\")\n    public Result<Void> checkTemplateValidForCreate(@PathVariable(\"templateName\") String templateName) {\n        return templateLogicManager.checkTemplateValidForCreate(templateName);\n    }\n\n    @GetMapping(\"/{templateId}/check-edit-mapping\")\n    @ResponseBody\n    @ApiOperation(value = \"校验可否编辑模板mapping\")\n    public Result<Boolean> checkTemplateEditMapping(@PathVariable Integer templateId) {\n        return templateLogicManager.checkTemplateEditMapping(templateId);\n    }\n\n    @GetMapping(\"/{templateId}/{templateSrvId}/check-edit-template-srv/\")\n    @ResponseBody\n    @ApiOperation(value = \"校验模板是否可以使用指定的索引模板服务，例如是否可以编辑mapping,setting等\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"templateId\", dataType = \"Integer\", value = \"逻辑模板id\", required = true),\n                         @ApiImplicitParam(name = \"templateSrvId\", dataType = \"Integer\", value = \"索引模板服务的id，例如mapping设置\", required = true) })\n    public Result<Boolean> checkTemplateEditService(@PathVariable(\"templateId\") Integer templateId,\n                                                    @PathVariable(\"templateSrvId\") Integer templateSrvId) {\n        return templateLogicManager.checkTemplateEditService(templateId, templateSrvId);\n    }\n\n    @PutMapping(\"/rollover/switch/{templateLogicId}/{status}\")\n    @ResponseBody\n    @ApiOperation(value = \"更改逻辑模版的rollover能力\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"templateLogicId\", dataType = \"Integer\", value = \"逻辑模版id\", required = true),\n                         @ApiImplicitParam(name = \"status\", dataType = \"Integer\", value = \"停启rollover能力（1 启用，0 禁用）\", required = true) })\n    public Result<Void> switchRolloverStatus(@PathVariable Integer templateLogicId, @PathVariable Integer status,\n                                             HttpServletRequest request) {\n        String operator = HttpRequestUtil.getOperator(request);\n        return templateLogicManager.switchRolloverStatus(templateLogicId, status, operator,\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"/setting\")\n    @ResponseBody\n    @ApiOperation(value = \"更新索引Setting接口\", notes = \"\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"header\", dataType = \"String\", name = \"X-ARIUS-APP-ID\", value = \"应用ID\", required = true) })\n    public Result<Void> customizeSetting(HttpServletRequest request,\n                                         @RequestBody TemplateSettingDTO settingDTO) throws AdminOperateException {\n        Result<Void> checkAuthResult = templateLogicManager.checkProjectAuthOnLogicTemplate(settingDTO.getLogicId(),\n            HttpRequestUtil.getProjectId(request));\n        if (checkAuthResult.failed()) {\n            return checkAuthResult;\n        }\n\n        return templateLogicSettingManager.customizeSetting(settingDTO, HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/setting\")\n    @ResponseBody\n    @ApiOperation(value = \"获取索引Setting接口\", notes = \"\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Integer\", name = \"logicId\", value = \"索引ID\", required = true) })\n    @Deprecated\n    public Result<TemplateSettingVO> getTemplateSettings(@RequestParam(\"logicId\") Integer logicId) throws AdminOperateException {\n        return templateLogicSettingManager.buildTemplateSettingVO(logicId);\n    }\n\n    @GetMapping(\"/templates\")\n    @ResponseBody\n    @ApiOperation(value = \"根据物理集群名称获取对应全量逻辑模板列表\", notes = \"\")\n    public Result<List<ConsoleTemplateVO>> getLogicTemplatesByCluster(HttpServletRequest request,\n                                                                      @RequestParam(\"cluster\") String cluster) {\n        return templateLogicManager.getTemplateVOByPhyCluster(cluster);\n    }\n   \n\n    @PostMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"创建逻辑模板\")\n    public Result<Void> createTemplate(HttpServletRequest request,\n                                       @RequestBody IndexTemplateWithCreateInfoDTO param) throws AdminOperateException {\n        return templateLogicManager.create(param, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping()\n    @ResponseBody\n    @ApiOperation(value = \"用户编辑模板\")\n    public Result<Void> editTemplate(HttpServletRequest request, @RequestBody IndexTemplateDTO param) {\n        return templateLogicManager.editTemplate(param, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @DeleteMapping(\"/indices\")\n    @ResponseBody\n    @ApiOperation(value = \"清理索引\")\n    public Result<Void> clearIndices(HttpServletRequest request, @RequestBody TemplateClearDTO clearDTO) {\n        return templateLogicManager.clearIndices(clearDTO, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"/{templateId}/{shardNum}/adjust-shard\")\n    @ResponseBody\n    @ApiOperation(value = \"扩缩容\")\n    public Result<Void> adjustShard(HttpServletRequest request, @PathVariable(\"templateId\") Integer templateId,\n                                    @PathVariable(\"shardNum\") Integer shardNum) throws AdminOperateException {\n        return templateLogicManager.adjustShard(templateId, shardNum, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n    }\n\n    @PutMapping(\"/{templateId}/upgrade\")\n    @ResponseBody\n    @ApiOperation(value = \"升版本\")\n    public Result<Void> upgrade(HttpServletRequest request,\n                                @PathVariable Integer templateId) throws AdminOperateException {\n        return templateLogicManager.upgrade(templateId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"/{clusterPhyName}/phy/templates\")\n    @ResponseBody\n    @ApiOperation(value = \"根据物理集群名称获取对应全量逻辑模板列表\", notes = \"\")\n    public Result<List<ConsoleTemplateVO>> getLogicTemplatesByPhyCluster(HttpServletRequest request,\n                                                                         @PathVariable String clusterPhyName) {\n        return templateLogicManager.getTemplateVOByPhyCluster(clusterPhyName);\n    }\n\n    @GetMapping(\"/{clusterLogicName}/logic/templates\")\n    @ResponseBody\n    @ApiOperation(value = \"根据逻辑集群名称获取对应全量逻辑模板列表\", notes = \"\")\n    public Result<List<ConsoleTemplateVO>> listTemplateVOByLogicCluster(HttpServletRequest request,\n                                                                        @PathVariable String clusterLogicName) {\n        return templateLogicManager.listTemplateVOByLogicCluster(clusterLogicName,\n            HttpRequestUtil.getProjectId(request));\n    }\n    \n    @PutMapping(\"/{templateId}/block-write\")\n    @ResponseBody\n    @ApiOperation(value = \"写变更\")\n    public Result<Void> write(HttpServletRequest request, @PathVariable Integer templateId,\n                              @RequestParam(\"status\") Boolean status)  {\n        return templateLogicManager.blockWrite(templateId, status, HttpRequestUtil.getOperator(request),\n                HttpRequestUtil.getProjectId(request));\n    }\n    \n    @PutMapping(\"/{templateId}/block-read\")\n    @ResponseBody\n    @ApiOperation(value = \"读变更\")\n    public Result<Void> read(HttpServletRequest request, @PathVariable Integer templateId,\n                             @RequestParam(\"status\") Boolean status) {\n        return templateLogicManager.blockRead(templateId, status, HttpRequestUtil.getOperator(request),\n                HttpRequestUtil.getProjectId(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/template/TemplatePhysicalV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.template;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport java.util.List;\n\nimport javax.servlet.http.HttpServletRequest;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplatePhysicalCopyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplatePhyVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplatePhyManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplatePhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.TemplatePhysicalUpgradeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.IndexTemplatePhysicalVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\n\n/**\n * Created by linyunan on 2021-07-30\n */\n@RestController\n@RequestMapping(V3 + \"/templates/physical\")\n@Api(tags = \"索引模板管理接口(REST)\")\npublic class TemplatePhysicalV3Controller {\n\n    @Autowired\n    private TemplatePhyManager templatePhyManager;\n\n    @GetMapping(\"/{logicId}\")\n    @ResponseBody\n    @ApiOperation(value = \"根据逻辑模板Id获取多个物理模板信息\", notes = \"\")\n    public Result<List<IndexTemplatePhysicalVO>> list(@PathVariable(\"logicId\") Integer logicId) {\n        return templatePhyManager.getTemplatePhies(logicId);\n    }\n\n    @GetMapping(\"/names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理模板名称列表接口\")\n    public Result<List<String>> listTemplatePhyNames(HttpServletRequest request) {\n        return Result.buildSucc(templatePhyManager.getTemplatePhyNames(HttpRequestUtil.getProjectId(request)));\n    }\n\n    @GetMapping(\"/{templatePhyId}/copy-cluster-phy-names\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理模板可复制的物理集群名称\")\n    public Result<List<String>> getAppNodeNames(@PathVariable Long templatePhyId) {\n        return Result.buildSucc(templatePhyManager.getCanCopyTemplatePhyClusterPhyNames(templatePhyId));\n    }\n\n    @PutMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"编辑多个物理模板接口\", notes = \"\")\n    public Result<Boolean> multipleEdit(HttpServletRequest request,\n                                        @RequestBody List<IndexTemplatePhyDTO> params) throws ESOperateException {\n        return templatePhyManager.editMultipleTemplate(params, HttpRequestUtil.getOperator(request));\n    }\n\n    @PostMapping(\"/upgrade\")\n    @ResponseBody\n    @ApiOperation(value = \"升级多个物理模板接口\", notes = \"\")\n    public Result<Boolean> multipleUpgrade(HttpServletRequest request,\n                                           @RequestBody List<TemplatePhysicalUpgradeDTO> params) throws ESOperateException {\n        return templatePhyManager.upgradeMultipleTemplate(params, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    /**\n     * @param param\n     * @param request\n     * @return\n     *\n     */\n    @PostMapping(\"/condition-list\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理模板列表接口【三方接口】\",tags = \"【三方接口】\")\n    public Result<List<ConsoleTemplatePhyVO>> list(@RequestBody IndexTemplatePhyDTO param,\n                                                   HttpServletRequest request) {\n        return Result.buildSucc(templatePhyManager.getConsoleTemplatePhyVOS(param, HttpRequestUtil.getProjectId(request)));\n    }\n\n    @DeleteMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"删除物理模板接口\" )\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Long\", name = \"physicalId\", value = \"物理模板ID\", required = true) })\n    public Result<Void> delete(HttpServletRequest request,\n                               @RequestParam(value = \"physicalId\") Long physicalId) throws ESOperateException {\n        return templatePhyManager.delTemplate(physicalId, HttpRequestUtil.getOperator(request));\n    }\n\n    @PutMapping(\"/copy\")\n    @ResponseBody\n    @ApiOperation(value = \"复制物理模板接口\" )\n    public Result<Void> copy(HttpServletRequest request,\n                             @RequestBody TemplatePhysicalCopyDTO param) throws AdminOperateException {\n        return templatePhyManager.copyTemplate(param, HttpRequestUtil.getOperator(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/template/TemplateSchemaController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.template;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping.TemplateLogicMappingManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.ConsoleTemplateSchemaDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.ConsoleTemplateFieldConvertVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateMappingVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.AriusTypeProperty;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.Field;\nimport com.didichuxing.datachannel.arius.admin.common.mapping.SpecialField;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(V3 + \"/template\")\n@Api(tags = \"Console-用户侧索引模板mapping接口(REST)\")\npublic class TemplateSchemaController extends BaseTemplateController {\n\n    @Autowired\n    private TemplateLogicMappingManager templateLogicMappingManager;\n\n    @PutMapping(\"/schema/convert\")\n    @ResponseBody\n    @ApiOperation(value = \"模板field转mapping接口【三方接口】\", tags = \"【三方接口】\")\n    public Result<ConsoleTemplateFieldConvertVO> convertSchema(@RequestBody List<Field> fields) {\n        AriusTypeProperty typeProperty = templateLogicMappingManager.fields2Mapping(fields);\n\n        SpecialField specialField = SpecialField.analyzeFromFields(fields);\n        typeProperty.setIdField(specialField.getIdField());\n        typeProperty.setRoutingField(specialField.getRoutingField());\n\n        ConsoleTemplateFieldConvertVO convertVO = new ConsoleTemplateFieldConvertVO();\n        convertVO.setDateField(specialField.getDateField());\n        convertVO.setDateFieldFormat(specialField.getDateFieldFormat());\n        convertVO.setMapping(typeProperty.getProperties().toJSONString());\n        convertVO.setIdField(specialField.getIdField());\n        convertVO.setRoutingField(specialField.getRoutingField());\n\n        return Result.buildSucc(convertVO);\n    }\n\n    @GetMapping(\"/schema\")\n    @ResponseBody\n    @ApiOperation(value = \"获取索引Schema信息接口【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Integer\", name = \"logicId\", value = \"索引ID\", required = true) })\n    public Result<TemplateMappingVO> getSchema(@RequestParam(\"logicId\") Integer logicId) {\n        return templateLogicMappingManager.getSchema(logicId);\n    }\n\n    @PutMapping(\"/schema\")\n    @ResponseBody\n    @ApiOperation(value = \"更新索引Schema信息接口【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"header\", dataType = \"String\", name = \"X-ARIUS-APP-ID\", value = \"应用ID\", required = true) })\n    public Result<Void> modifySchema(HttpServletRequest request,\n                                     @RequestBody ConsoleTemplateSchemaDTO schemaDTO) throws AdminOperateException {\n\n        Result<Void> checkAuthResult = checkProjectAuth(schemaDTO.getLogicId());\n        if (checkAuthResult.failed()) {\n            return checkAuthResult;\n        }\n\n        return templateLogicMappingManager.editMapping(schemaDTO, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/template/TemplateSettingController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.template;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.setting.TemplateLogicSettingsManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhySetting;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(V3 + \"/template/setting\")\n@Api(tags = \"Console-用户侧索引模板setting接口(REST)\")\npublic class TemplateSettingController {\n\n    @Autowired\n    private TemplateLogicSettingsManager templateLogicSettingManager;\n\n    @PutMapping(\"/{logicId}\")\n    @ResponseBody\n    @ApiOperation(value = \"更新索引Setting接口\")\n    public Result<Void> modifySetting(HttpServletRequest request, @PathVariable(\"logicId\") Integer logicId,\n                                      @RequestBody String settingDTO) throws AdminOperateException {\n        IndexTemplatePhySetting settings = new IndexTemplatePhySetting(JSONObject.parseObject(settingDTO));\n        return templateLogicSettingManager.updateSettings(logicId, settings, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @GetMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"获取索引Setting接口\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Integer\", name = \"logicId\", value = \"索引ID\", required = true) })\n    public Result<IndexTemplatePhySetting> getTemplateSettings(@RequestParam(\"logicId\") Integer logicId) throws AdminOperateException {\n        return templateLogicSettingManager.getSettings(logicId);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/template/TemplateSrvController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.template;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.TemplateSrvManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.PaginationResult;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv.ColdSrvOpenDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.srv.TemplateQueryDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.srv.TemplateWithSrvVO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\n/**\n * @author chengxiang\n * @date 2022/5/18\n */\n@RestController\n@RequestMapping(V3 + \"/template/srv\")\n@Api(tags = \"模板服务接口\")\npublic class TemplateSrvController {\n\n    @Autowired\n    private TemplateSrvManager templateSrvManager;\n\n    @PostMapping(\"/page\")\n    @ResponseBody\n    @ApiOperation(value = \"分页查询模板服务列表\")\n    public PaginationResult<TemplateWithSrvVO> pageGetTemplateWithSrv(HttpServletRequest request,\n                                                                      @RequestBody TemplateQueryDTO condition) throws NotFindSubclassException {\n        final Integer projectId = HttpRequestUtil.getProjectId(request);\n        \n        return templateSrvManager.pageGetTemplateWithSrv(condition,projectId);\n    }\n\n    @PutMapping(\"/{srvCode}/{templateIdList}\")\n    @ResponseBody\n    @ApiOperation(value = \"开启模板服务\")\n    public Result<Void> openTemplateSrv(HttpServletRequest request, @PathVariable(\"srvCode\") Integer srvCode,\n                                        @PathVariable(\"templateIdList\") List<Integer> templateIdList,\n                                        @RequestBody(required = false) ColdSrvOpenDTO data) {\n        return templateSrvManager.openSrv(srvCode, templateIdList, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request), data);\n    }\n\n    @DeleteMapping(\"/{srvCode}/{templateIdList}\")\n    @ResponseBody\n    @ApiOperation(value = \"关闭模板服务\")\n    public Result<Void> closeTemplateSrv(HttpServletRequest request, @PathVariable(\"srvCode\") Integer srvCode,\n                                         @PathVariable(\"templateIdList\") List<Integer> templateIdList) {\n        return templateSrvManager.closeSrv(srvCode, templateIdList, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"/{templateId}/block-write\")\n    @ResponseBody\n    @ApiOperation(value = \"写变更\")\n    public Result<Void> write(HttpServletRequest request, @PathVariable Integer templateId,\n                              @RequestParam(\"status\") Boolean status)  {\n        return templateSrvManager.blockWrite(templateId, status, HttpRequestUtil.getOperator(request),\n                HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"/{templateId}/block-read\")\n    @ResponseBody\n    @ApiOperation(value = \"读变更\")\n    public Result<Void> read(HttpServletRequest request, @PathVariable Integer templateId,\n                             @RequestParam(\"status\") Boolean status) {\n        return templateSrvManager.blockRead(templateId, status, HttpRequestUtil.getOperator(request),\n                HttpRequestUtil.getProjectId(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/op/template/TemplateStatisticsController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.op.template;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplatePhyStaticsManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESIndexStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.TemplateStatsInfoVO;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\n@NoArgsConstructor\n@RestController()\n@RequestMapping(V3 + \"/template/statistics\")\n@Api(tags = \"Console-用户侧索引模板统计信息接口(REST)\")\npublic class TemplateStatisticsController extends BaseTemplateController {\n\n    @Autowired\n    private TemplatePhyStaticsManager templatePhyStaticsManager;\n\n    /**\n     * 根据逻辑模板id获取模板的monitor统计信息\n     *\n     * @param logicTemplateId 模板id\n     * @param startDate       毫秒\n     * @param endDate         毫秒\n     * @return\n     */\n    @GetMapping(path = \"/query\")\n    @ApiOperation(value = \"获取索引模板的统计信息【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Long\", name = \"logicTemplateId\", value = \"模板id\", required = true),\n                         @ApiImplicitParam(paramType = \"query\", dataType = \"Long\", name = \"startDate\", value = \"查询开始时间，毫秒时间戳\", required = true),\n                         @ApiImplicitParam(paramType = \"query\", dataType = \"Long\", name = \"endDate\", value = \"查询结束时间，毫秒时间戳\", required = true) })\n    public Result<List<ESIndexStats>> getIndexStatics(@RequestParam(value = \"templateId\") Long logicTemplateId,\n                                                      @RequestParam(value = \"startDate\") Long startDate,\n                                                      @RequestParam(value = \"endDate\") Long endDate) {\n        return templatePhyStaticsManager.getIndexStatics(logicTemplateId, startDate, endDate);\n    }\n\n    /**\n     * 根据模板id获取模板的基本统计信息\n     *\n     * @param logicTemplateId 模板id\n     * @return\n     */\n    @GetMapping(path = \"/statistics-info\")\n    @ApiOperation(value = \"根据模板id，查询模板的基本统计信息【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Long\", name = \"templateId\", value = \"模板id\", required = true) })\n    public Result<TemplateStatsInfoVO> getTemplateBaseStatisticsInfo(@RequestParam(value = \"templateId\") Long logicTemplateId) {\n        return templatePhyStaticsManager.getTemplateBaseStatisticalInfoByLogicTemplateId(logicTemplateId);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/project/ESUserV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.project;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport java.util.List;\n\nimport javax.servlet.http.HttpServletRequest;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.ESUserManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ESUserDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ConsoleESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ESUserVO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\n\n/**\n * 项目关联的es user\n *\n * @author shizeying\n * @date 2022/05/26\n * @since 0.3\n */\n@RestController\n@RequestMapping({ V3 + \"/es-user\" })\n@Api(tags = \"应用关联es user (REST)\")\npublic class ESUserV3Controller {\n\n    @Autowired\n    private ESUserManager esUserManager;\n\n    @PostMapping(\"/{projectId}\")\n    @ResponseBody\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Integer\", name = \"projectId\", value = \"projectId\", required = true) })\n    @ApiOperation(value = \"新增es user\")\n    public Result<Integer> createESUerByProject(HttpServletRequest request,\n                                                @PathVariable(\"projectId\") Integer projectId,\n                                                @RequestBody ESUserDTO appDTO) {\n        return esUserManager.registerESUser(appDTO, projectId, HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/project/{projectId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取项目下的es user\")\n    @ApiImplicitParam(name = \"projectId\", value = \"项目id\", dataType = \"String\", required = true)\n    public Result<List<ESUserVO>> listESUserByProjectId(HttpServletRequest request,\n                                                        @PathVariable(\"projectId\") String projectId) {\n\n        return esUserManager.listESUsersByProjectId(projectId, request);\n    }\n\n    @DeleteMapping(\"/{projectId}/{esUser}\")\n    @ResponseBody\n    @ApiOperation(value = \"删除项目下指定的es user\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"projectId\", value = \"projectId\", required = true),\n                         @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"esUser\", value = \"es user\", required = true) })\n    public Result<Void> deleteESUserByProject(HttpServletRequest request, @PathVariable(\"projectId\") Integer projectId,\n                                              @PathVariable(\"esUser\") Integer esUserName) {\n\n        return esUserManager.deleteESUserByProject(esUserName, projectId, HttpRequestUtil.getOperator(request));\n    }\n\n    @DeleteMapping(\"/{projectId}\")\n    @ResponseBody\n    @ApiOperation(value = \"删除项目下全部的es user\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"projectId\", value = \"projectId\", required = true) })\n    public Result<Void> deleteAllESUserByProject(HttpServletRequest request,\n                                                 @PathVariable(\"projectId\") Integer projectId) {\n\n        return esUserManager.deleteAllESUserByProject(projectId, HttpRequestUtil.getOperator(request));\n    }\n\n    @PutMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"编辑es user接口\", notes = \"支持修改数据中心、备注\")\n    public Result<Void> update(HttpServletRequest request, @RequestBody ESUserDTO esUserDTO) {\n        //获取操作用户\n        String userName = HttpRequestUtil.getOperator(request);\n        return esUserManager.editESUser(esUserDTO, userName);\n    }\n\n    @PutMapping(\"/{projectId}/{esUser}/defaultDisplay\")\n    @ResponseBody\n    @ApiOperation(value = \"设置es User为应用默认es User\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"projectId\", value = \"projectId\", required = true),\n                         @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"esUser\", value = \"es user\", required = true) })\n    public Result<Void> setDefaultDisplay(HttpServletRequest request, @PathVariable(\"projectId\") Integer projectId,\n                                          @PathVariable(\"esUser\") Integer esUserName) {\n        return esUserManager.setDefaultDisplay(esUserName, projectId, HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/{esUser}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取es user详情接口\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"esUser\", value = \"esUser详情\", required = true) })\n    public Result<ConsoleESUserVO> get(@PathVariable(\"esUser\") Integer esUser) {\n        return esUserManager.get(esUser);\n    }\n\n    @GetMapping(\"/{projectId}/primitive/cluster/list\")\n    @ResponseBody\n    @ApiOperation(value = \"获取原生模式下项目对应的访问集群列表\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"projectId\", value = \"projectId\", required = true) })\n    public Result<List<String>> listClusterByAppInPrimitiveType(@PathVariable(\"projectId\") Integer projectId) {\n        return esUserManager.listClusterByAppInPrimitiveType(projectId);\n    }\n\n    @GetMapping(\"/{projectId}/cluster/list\")\n    @ResponseBody\n    @ApiOperation(value = \"获取集群模式下项目对应的访问集群列表\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"path\", dataType = \"Integer\", name = \"projectId\", value = \"projectId\", required = true) })\n    public Result<List<String>> listClusterByAppInClusterType(@PathVariable(\"projectId\") Integer projectId) {\n        return esUserManager.listClusterByAppInClusterType(projectId);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/project/LoginV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.project;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_SECURITY;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.LoginManager;\nimport com.didiglobal.knowframework.security.common.Result;\nimport com.didiglobal.knowframework.security.common.constant.Constants;\nimport com.didiglobal.knowframework.security.common.dto.account.AccountLoginDTO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author cjm\n */\n@RestController\n@Api(value = \"登录相关API接口\", tags = { \"权限相关接口\" })\n@RequestMapping(V3_SECURITY + Constants.ACCOUNT_LOGIN)\npublic class LoginV3Controller {\n\n    @Autowired\n    private LoginManager loginManager;\n\n    @PostMapping(\"/login\")\n    @ApiOperation(value = \"登录检查\", notes = \"检查SSO返回的Code\")\n    public Result<UserBriefVO> login(HttpServletRequest request, HttpServletResponse response,\n                                     @RequestBody AccountLoginDTO loginDTO) {\n\n        return loginManager.verifyLogin(loginDTO, request, response);\n    }\n\n    @PostMapping(\"/logout\")\n    @ApiOperation(value = \"登出\", notes = \"检查SSO返回的Code\")\n    public Result<Boolean> logout(HttpServletRequest request, HttpServletResponse response) {\n        return loginManager.logout(request, response);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/project/PermissionV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.project;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_SECURITY;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.PermissionExtendManager;\nimport com.didiglobal.knowframework.security.common.Result;\nimport com.didiglobal.knowframework.security.common.vo.permission.PermissionTreeVO;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * 权限点v3控制器\n *\n * @author shizeying\n * @date 2022/06/14\n */\n@RestController\n@Api(value = \"权限相关API接口\", tags = { \"权限相关API接口\" })\n@RequestMapping(V3_SECURITY + \"/permission\")\npublic class PermissionV3Controller {\n    @Autowired\n    private PermissionExtendManager permissionExtendManager;\n\n    @GetMapping(\"/resource-owner\")\n    @ResponseBody\n    @ApiOperation(value = \"获取资源own角色权限树\", notes = \"以树的形式返回所有权限\")\n    public Result<PermissionTreeVO> isAdmin(HttpServletRequest request) {\n\n        return permissionExtendManager.buildPermissionTreeByResourceOwn();\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/project/ProjectTemplateAuthV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.project;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.ProjectLogicTemplateAuthManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectTemplateAuthDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectTemplateAuthVO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author ohushenglin_v\n */\n@RestController\n@RequestMapping({ V3 + \"/project/auth/template\" })\n@Api(tags = \"project模板权限接口(REST)\")\npublic class ProjectTemplateAuthV3Controller {\n\n    @Autowired\n    private ProjectLogicTemplateAuthManager projectLogicTemplateAuthManager;\n\n    @GetMapping(\"/{projectId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取project权限接口\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Integer\", name = \"projectId\", value = \"应用ID\", required = true) })\n    public Result<List<ProjectTemplateAuthVO>> getAppTemplateAuths(@PathVariable(\"projectId\") Integer projectId) {\n\n        return projectLogicTemplateAuthManager.getProjectTemplateAuths(projectId);\n    }\n\n    @PostMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"增加project权限接口\")\n    public Result<Void> addTemplateAuth(HttpServletRequest request, @RequestBody ProjectTemplateAuthDTO authDTO) {\n        return projectLogicTemplateAuthManager.addTemplateAuth(authDTO, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PutMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"更新project权限接口\")\n    public Result<Void> updateTemplateAuth(HttpServletRequest request, @RequestBody ProjectTemplateAuthDTO authDTO) {\n        return projectLogicTemplateAuthManager.updateTemplateAuth(authDTO, HttpRequestUtil.getOperator(request));\n    }\n\n    @DeleteMapping(\"/{authId}\")\n    @ResponseBody\n    @ApiOperation(value = \"删除project权限接口\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"Long\", name = \"authId\", value = \"权限ID\", required = true) })\n    public Result<Void> deleteTemplateAuth(HttpServletRequest request, @PathVariable(\"authId\") Long authId) {\n        return projectLogicTemplateAuthManager.deleteTemplateAuth(authId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @DeleteMapping(\"/redundancy\")\n    @ResponseBody\n    @ApiOperation(value = \"删除多余的模板权限数据\")\n    public Result<Void> deleteRedundancyTemplateAuths() {\n        return projectLogicTemplateAuthManager.deleteRedundancyTemplateAuths(true);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/project/ProjectV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.project;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_SECURITY;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.ProjectConfigManager;\nimport com.didichuxing.datachannel.arius.admin.biz.project.ProjectExtendManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectExtendSaveDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectQueryExtendDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectBriefExtendVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectConfigVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectExtendVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didiglobal.knowframework.security.common.PagingResult;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectDeleteCheckVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport java.util.Objects;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * 项目v3控制器\n *\n * @author shizeying\n * @date 2022/06/01\n */\n@RestController\n@RequestMapping({ V3_SECURITY + \"/project\" })\n@Api(value = \"应用 (REST)\", tags = { \"项目相关API接口\" })\npublic class ProjectV3Controller {\n    @Autowired\n    private RoleTool             roleTool;\n    @Autowired\n    private ProjectExtendManager projectExtendManager;\n    @Autowired\n    private ProjectConfigManager projectConfigManager;\n\n    @GetMapping(\"/config/{projectId}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取项目配置\", notes = \"\")\n    @ApiImplicitParam(name = \"projectId\", value = \"项目id\", dataType = \"int\", required = true)\n    public Result<ProjectConfigVO> get(HttpServletRequest request, @PathVariable(\"projectId\") Integer projectId) {\n        //获取操作用户慢查询耗时：ms\n        Integer id = Objects.isNull(projectId) ? HttpRequestUtil.getProjectId(request) : projectId;\n        return projectConfigManager.get(id);\n    }\n\n    @GetMapping(\"/admin-project\")\n    @ResponseBody\n    @ApiOperation(value = \"获取超级应用id\")\n    public Result<Integer> isAdminProject(HttpServletRequest request) {\n        final String operator = HttpRequestUtil.getOperator(request);\n        if (!roleTool.isAdmin(operator)) {\n            return Result.buildFail(\"当前角色非管理员\");\n        }\n        return Result.buildSucc(AuthConstant.SUPER_PROJECT_ID);\n    }\n\n    @GetMapping(\"/{id}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取项目详情\", notes = \"根据项目id获取项目详情\")\n    @ApiImplicitParam(name = \"id\", value = \"项目id\", dataType = \"int\", paramType = \"path\", required = true)\n    public Result<ProjectExtendVO> detail(@PathVariable Integer id) {\n        return projectExtendManager.getProjectDetailByProjectId(id);\n    }\n\n    @PostMapping\n    @ResponseBody\n    @ApiOperation(value = \"创建项目\", notes = \"创建项目\")\n    public Result<ProjectExtendVO> create(@RequestBody ProjectExtendSaveDTO saveDTO, HttpServletRequest request) {\n\n        return projectExtendManager.createProject(saveDTO, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getOperatorId(request));\n    }\n\n    @DeleteMapping(\"/{id}\")\n    @ResponseBody\n    @ApiOperation(value = \"删除项目\", notes = \"根据项目id删除项目\")\n    @ApiImplicitParam(name = \"id\", value = \"项目id\", dataType = \"int\", paramType = \"path\", required = true)\n    public Result<Void> delete(@PathVariable Integer id, HttpServletRequest request) {\n\n        return projectExtendManager.deleteProjectByProjectId(id, HttpRequestUtil.getOperator(request));\n    }\n    \n    @GetMapping(\"/check-resources/{id}\")\n    @ResponseBody\n    @ApiOperation(value = \"检查一个项目的资源是否可用\", notes = \"检查一个项目的资源是否可用\")\n    @ApiImplicitParam(name = \"id\", value = \"项目 id\", dataType = \"int\", paramType = \"path\", required = true)\n    public Result<Void> checkResourcesByProjectId(@PathVariable Integer id, HttpServletRequest request) {\n        \n        return projectExtendManager.checkResourcesByProjectId(id);\n    }\n    @GetMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"获取所有项目简要信息\", notes = \"获取全部项目简要信息（只返回id、项目名）\")\n    public Result<List<ProjectBriefExtendVO>> list(HttpServletRequest request) {\n        return projectExtendManager.getProjectBriefList();\n    }\n\n    @GetMapping(\"/{id}/exist\")\n    @ApiOperation(value = \"校验项目是否存在\", notes = \"校验项目是否存在\")\n    @ApiImplicitParam(name = \"id\", value = \"项目id\", dataType = \"int\", paramType = \"path\", required = true)\n    public Result<Void> checkExist(@PathVariable Integer id) {\n        return projectExtendManager.checkProjectExist(id);\n    }\n\n    @PutMapping(\"/switch/{id}\")\n    @ApiOperation(value = \"更改项目运行状态\", notes = \"调用该接口则项目运行状态被反转\")\n    @ApiImplicitParam(name = \"id\", value = \"项目id\", dataType = \"int\", paramType = \"path\", required = true)\n    public Result<Void> switched(@PathVariable Integer id, HttpServletRequest request) {\n\n        return projectExtendManager.changeProjectStatus(id, HttpRequestUtil.getOperator(request));\n    }\n\n    @PutMapping\n    @ApiOperation(value = \"更新项目\", notes = \"根据项目id更新项目信息\")\n    public Result<Void> update(@RequestBody ProjectExtendSaveDTO saveDTO, HttpServletRequest request) {\n\n        return projectExtendManager.updateProject(saveDTO, HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/delete/check/{id}\")\n    @ApiOperation(value = \"删除项目前的检查\", notes = \"检查是否有服务引用了该项目、是否有具体资源挂上了该项目\")\n    @ApiImplicitParam(name = \"id\", value = \"项目id\", dataType = \"int\", paramType = \"path\", required = true)\n    public Result<ProjectDeleteCheckVO> deleteCheck(@PathVariable Integer id) {\n        return projectExtendManager.checkBeforeDelete(id);\n    }\n\n    @PostMapping(\"/page\")\n    @ApiOperation(value = \"分页查询项目列表\", notes = \"分页和条件查询\")\n    public PagingResult<ProjectExtendVO> page(@RequestBody ProjectQueryExtendDTO queryDTO, HttpServletRequest request) {\n        return projectExtendManager.getProjectPage(queryDTO, request);\n    }\n\n    @PutMapping(\"/{id}/owner\")\n    @ApiOperation(value = \"从角色中增加该项目下的负责人\", notes = \"从角色中增加该项目下的用户\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"id\", value = \"项目id\", dataType = \"int\", paramType = \"path\", required = true),\n                         @ApiImplicitParam(name = \"ownerList\", value = \"用户id列表\", allowMultiple = true, dataType = \"int\", paramType = \"body\", required = true) })\n    public Result<Void> addProjectOwner(@PathVariable(\"id\") Integer id, @RequestBody List<Integer> ownerList,\n                                        HttpServletRequest request) {\n\n        return projectExtendManager.addProjectOwner(id, ownerList, HttpRequestUtil.getOperator(request));\n    }\n\n    @DeleteMapping(\"/{id}/owner/{ownerId}\")\n    @ApiOperation(value = \"从项目中删除该项目下的负责人\", notes = \"从项目中删除该项目下的负责人\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"id\", value = \"项目id\", dataType = \"int\", paramType = \"path\", required = true),\n                         @ApiImplicitParam(name = \"ownerId\", value = \"项目id\", dataType = \"int\", paramType = \"path\", required = true) })\n    public Result<Void> deleteProjectOwner(@PathVariable Integer id, @PathVariable Integer ownerId,\n                                           HttpServletRequest request) {\n        return projectExtendManager.delProjectOwner(id, ownerId, HttpRequestUtil.getOperator(request));\n    }\n\n    @PutMapping(\"/{id}/user\")\n    @ApiOperation(value = \"从角色中增加该项目下的用户\", notes = \"从角色中增加该项目下的用户\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"id\", value = \"项目id\", dataType = \"int\", paramType = \"path\", required = true),\n                         @ApiImplicitParam(name = \"userList\", value = \"用户id列表\", allowMultiple = true, dataType = \"int\", paramType = \"body\", required = true) })\n    public Result<Void> addProjectUser(@PathVariable Integer id, @RequestBody List<Integer> userList,\n                                       HttpServletRequest request) {\n\n        return projectExtendManager.addProjectUser(id, userList, HttpRequestUtil.getOperator(request));\n    }\n\n    @DeleteMapping(\"/{id}/user/{userId}\")\n    @ApiOperation(value = \"从项目中删除该项目下的用户\", notes = \"从项目中删除该项目下的用户\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"id\", value = \"项目id\", dataType = \"int\", required = true, paramType = \"path\"),\n                         @ApiImplicitParam(name = \"userId\", value = \"用户id\", dataType = \"int\", required = true, paramType = \"path\") })\n    public Result<Void> deleteProjectUser(@PathVariable Integer id, @PathVariable Integer userId,\n                                          HttpServletRequest request) {\n\n        return projectExtendManager.delProjectUser(id, userId, HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/unassigned\")\n    @ApiOperation(value = \"获取项目未分配的用户列表\", notes = \"获取项目未分配的用户列表\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"id\", value = \"项目 id\", dataType = \"int\", required = true),\n                         @ApiImplicitParam(name = \"containsAdminRole\", value = \"是否包含管理员\", dataType = \"Boolean\", required =\n                                 true)\n    \n    })\n    public Result<List<UserBriefVO>> unassigned(@RequestParam(\"id\") Integer id,\n                                                @RequestParam(value = \"containsAdminRole\",required = false,defaultValue = \"false\") Boolean containsAdminRole) {\n\n        return projectExtendManager.unassignedByProjectId(id,containsAdminRole);\n    }\n\n    @GetMapping(\"/user/{userId}\")\n    @ApiOperation(value = \"获取用户绑定的项目列表\", notes = \"获取用户绑定的项目列表\")\n    @ApiImplicitParam(name = \"userId\", value = \"用户id\", dataType = \"int\", required = true, paramType = \"path\")\n    public Result<List<ProjectBriefExtendVO>> getProjectBriefByUserId(@PathVariable(\"userId\") Integer userId) {\n        if (roleTool.isAdmin(userId)) {\n            return projectExtendManager.getProjectBriefList();\n        }\n        return projectExtendManager.getProjectBriefByUserId(userId);\n    }\n\n    @GetMapping(\"/bind-user\")\n    @ApiOperation(value = \"获取项目绑定的用户列表\", notes = \"获取项目绑定的用户列表\")\n    public Result<List<UserBriefVO>> getProjectBriefByUserId(HttpServletRequest request) {\n\n        return projectExtendManager.listUserListByProjectId(HttpRequestUtil.getProjectId(request));\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/project/RoleV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.project;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_SECURITY;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.RoleExtendManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.RoleExtendVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didiglobal.knowframework.security.common.PagingResult;\nimport com.didiglobal.knowframework.security.common.dto.role.RoleAssignDTO;\nimport com.didiglobal.knowframework.security.common.dto.role.RoleQueryDTO;\nimport com.didiglobal.knowframework.security.common.dto.role.RoleSaveDTO;\nimport com.didiglobal.knowframework.security.common.vo.role.AssignInfoVO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport com.google.common.collect.Lists;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * 角色v3控制器\n *\n * @author shizeying\n * @date 2022/06/08\n */\n@RestController\n@RequestMapping({ V3_SECURITY + \"/role\" })\n@Api(value = \"role相关API接口\", tags = { \"角色相关API接口\" })\npublic class RoleV3Controller {\n    @Autowired\n    private RoleTool          roleTool;\n    @Autowired\n    private RoleExtendManager roleExtendManager;\n\n    @GetMapping(\"/is-admin\")\n    @ResponseBody\n    @ApiOperation(value = \"判断是否为管理员\")\n    public Result<Void> isAdmin(HttpServletRequest request) {\n        final String operator = HttpRequestUtil.getOperator(request);\n        if (!roleTool.isAdmin(operator)) {\n            return Result.buildFail(\"当前角色非管理员\");\n        }\n        return Result.buildSucc();\n    }\n\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除角色\", notes = \"如果该角色是否已经分配给用户，如有分配给用户，则返回用户的信息list；否则直接删除\")\n    @ApiImplicitParam(name = \"id\", value = \"角色id\", dataType = \"int\", required = true)\n    public Result delete(@PathVariable Integer id, HttpServletRequest request) {\n\n        return roleExtendManager.deleteRoleByRoleId(id, request);\n    }\n\n    @GetMapping(\"/admin\")\n    @ResponseBody\n    @ApiOperation(value = \"返回管理员列表id\")\n    public Result<List<Integer>> getAdminRoleIds(HttpServletRequest request) {\n        return Result.buildSucc(Lists.newArrayList(AuthConstant.ADMIN_ROLE_ID));\n    }\n\n    @GetMapping(\"/resource-owner\")\n    @ResponseBody\n    @ApiOperation(value = \"资源owner角色id\")\n    public Result<List<Integer>> getResourceOwnerId(HttpServletRequest request) {\n        return Result.buildSucc(Lists.newArrayList(AuthConstant.ADMIN_ROLE_ID));\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"获取角色详情\", notes = \"根据角色id或角色code获取角色详情\")\n    @ApiImplicitParam(name = \"id\", value = \"角色id\", dataType = \"int\", required = true)\n    public Result<RoleExtendVO> detail(@PathVariable Integer id) {\n        return roleExtendManager.getRoleDetailByRoleId(id);\n    }\n\n    @PutMapping\n    @ApiOperation(value = \"更新角色信息\", notes = \"根据角色id更新角色信息\")\n    public Result<Void> update(@RequestBody RoleSaveDTO saveDTO, HttpServletRequest request) {\n        return roleExtendManager.updateRole(saveDTO, request);\n    }\n\n    @PostMapping\n    @ApiOperation(value = \"创建角色\", notes = \"创建角色\")\n    public Result<Void> create(@RequestBody RoleSaveDTO saveDTO, HttpServletRequest request) {\n        return roleExtendManager.createRole(saveDTO, request);\n    }\n\n    @DeleteMapping(\"/{id}/user/{userId}\")\n    @ApiOperation(value = \"从角色中删除该角色下的用户\", notes = \"从角色中删除该角色下的用户\")\n    @ApiImplicitParam(name = \"id\", value = \"角色id\", dataType = \"int\", required = true)\n    public Result<Void> deleteUser(@PathVariable Integer id, @PathVariable Integer userId, HttpServletRequest request) {\n\n        return roleExtendManager.deleteUserFromRole(id, userId, request);\n    }\n\n    @PostMapping(\"/page\")\n    @ApiOperation(value = \"分页查询角色列表\", notes = \"分页和条件查询\")\n    public PagingResult<RoleExtendVO> page(@RequestBody RoleQueryDTO queryDTO) {\n        return roleExtendManager.getRolePage(queryDTO);\n    }\n\n    @PostMapping(\"/assign\")\n    @ApiOperation(value = \"分配角色\", notes = \"分配一个角色给多个用户或分配多个角色给一个用户\")\n    public Result<Void> assign(@RequestBody RoleAssignDTO assignDTO, HttpServletRequest request) {\n\n        return roleExtendManager.assignRoles(assignDTO, request);\n\n    }\n\n    @GetMapping(value = \"/assign/{roleId}\")\n    @ApiOperation(value = \"角色管理/分配用户/列表\", notes = \"查询所有用户列表，并根据角色id，标记哪些用户拥有该角色\")\n    @ApiImplicitParam(name = \"roleId\", value = \"角色id\", dataType = \"int\", required = true)\n    public Result<List<AssignInfoVO>> assignList(@PathVariable Integer roleId) {\n        return roleExtendManager.getAssignInfoByRoleId(roleId);\n\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/project/UserV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.project;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_SECURITY;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.UserExtendManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.UserExtendDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.UserQueryExtendDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.UserExtendVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.UserWithPwVO;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didiglobal.knowframework.security.common.PagingResult;\nimport com.didiglobal.knowframework.security.common.dto.user.UserDTO;\nimport com.didiglobal.knowframework.security.common.vo.role.AssignInfoVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserVO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport java.util.Optional;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * 用户v3控制器\n *\n * @author shizeying\n * @date 2022/06/14\n */\n@RestController\n@Api(value = \"user相关API (REST)\", tags = { \"用户相关API接口\" })\n@RequestMapping(V3_SECURITY + \"/user\")\npublic class UserV3Controller {\n    @Autowired\n    private RoleTool          roleTool;\n    @Autowired\n    private UserExtendManager userManager;\n\n    @GetMapping()\n    @ResponseBody\n    @ApiOperation(value = \"获取管理员列表\")\n    public Result<List<UserBriefVO>> getAdminList(HttpServletRequest request) {\n        return Result.buildSucc(roleTool.getAdminList());\n    }\n\n    @PostMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"用户新增接口，暂时没有考虑权限\", notes = \"\")\n    public Result<Void> add(HttpServletRequest request, @RequestBody UserDTO param) {\n        return userManager.addUser(param, HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"/{type}/{value}/check\")\n    @ApiOperation(value = \"获取用户详情\", notes = \"根据用户id获取用户详情\")\n    @ApiImplicitParam(name = \"type\", value = \"用户id\", dataType = \"int\", required = true)\n    public Result<Void> check(@PathVariable Integer type, @PathVariable String value) {\n        return userManager.check(type, value);\n    }\n\n    @GetMapping(\"/{id}\")\n    @ApiOperation(value = \"获取用户详情\", notes = \"根据用户id获取用户详情\")\n    @ApiImplicitParams({ @ApiImplicitParam(name = \"id\", value = \"用户id\", dataType = \"int\", paramType = \"query\", required = true) })\n    public Result<UserWithPwVO> detail(HttpServletRequest request, @PathVariable Integer id) throws Exception {\n        Integer projectId = Optional.ofNullable(HttpRequestUtil.getProjectId(request)).filter(i -> i > 0).orElse(null);\n\n        return userManager.getUserDetailByUserId(id, projectId);\n    }\n\n    @PostMapping(\"/page\")\n    @ApiOperation(value = \"查询用户列表\", notes = \"分页和条件查询\")\n    public PagingResult<UserExtendVO> page(@RequestBody UserQueryExtendDTO queryDTO) {\n        return userManager.getUserPage(queryDTO);\n    }\n\n    @GetMapping(\"/dept/{deptId}\")\n    @ApiOperation(value = \"根据部门id获取用户list\", notes = \"根据部门id获取用户简要信息list\")\n    @ApiImplicitParam(name = \"deptId\", value = \"部门id\", dataType = \"int\", required = true)\n    public Result<List<UserBriefVO>> listByDeptId(@PathVariable Integer deptId) {\n        return userManager.getUserBriefListByDeptId(deptId);\n    }\n\n    @GetMapping(\"/role/{roleId}\")\n    @ApiOperation(value = \"根据角色id获取用户list\", notes = \"根据角色id获取用户简要信息list\")\n    @ApiImplicitParam(name = \"roleId\", value = \"角色id\", dataType = \"int\", required = true)\n    public Result<List<UserBriefVO>> listByRoleId(@PathVariable Integer roleId) {\n        return userManager.getUserBriefListByRoleId(roleId);\n    }\n\n    @GetMapping(value = \"/assign/{userId}\")\n    @ApiOperation(value = \"用户管理/分配角色/列表\", notes = \"查询所有角色列表，并根据用户id，标记该用户拥有哪些角色\")\n    @ApiImplicitParam(name = \"userId\", value = \"用户id\", dataType = \"int\", required = true)\n    public Result<List<AssignInfoVO>> assignList(@PathVariable Integer userId) {\n\n        return userManager.getAssignDataByUserId(userId);\n    }\n\n    @PutMapping(\"\")\n    @ResponseBody\n    @ApiOperation(value = \"编辑用户接口，暂时没有考虑权限\", notes = \"\")\n    public Result<Void> edit(HttpServletRequest request, @RequestBody UserExtendDTO param) {\n        return userManager.editUser(param, HttpRequestUtil.getOperator(request));\n    }\n\n    @DeleteMapping(\"/{id}\")\n    @ApiOperation(value = \"删除用户\", notes = \"根据用户id删除用户\")\n    @ApiImplicitParam(name = \"id\", value = \"用户id\", dataType = \"int\", required = true)\n    public Result<Void> del(HttpServletRequest request, @PathVariable Integer id) {\n        return userManager.deleteByUserId(id, HttpRequestUtil.getProjectId(request), HttpRequestUtil.getOperator());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/white/ESPhyClusterWhiteController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.white;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_WHITE_PART;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.zeus.ZeusCollectManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESZeusHostInfoDTO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Created by linyunan on 2021-06-25\n */\n@RestController\n@RequestMapping(V3_WHITE_PART + \"/phy/cluster\")\n@Api(tags = \"物理集群白名单接口\")\npublic class ESPhyClusterWhiteController {\n\n    @Autowired\n    private ClusterPhyManager  clusterPhyManager;\n\n    @Autowired\n    private ZeusCollectManager zeusCollectManager;\n\n    @DeleteMapping(\"{clusterId}/deleteClusterJoin\")\n    @ResponseBody\n    @ApiOperation(value = \"删除接入集群\")\n    public Result<Void> deleteClusterJoin(HttpServletRequest request, @PathVariable Integer clusterId) {\n        return clusterPhyManager.deleteClusterJoin(clusterId, HttpRequestUtil.getOperator(request),\n            HttpRequestUtil.getProjectId(request));\n    }\n\n    @PostMapping(\"/updateHttpAddress\")\n    @ResponseBody\n    @ApiOperation(value = \"更新物理集群http读写地址\", notes = \"用于zeus新建操作, 由启动脚本访问此接口\")\n    public Result<Boolean> updateHttpAddress(@RequestBody ESZeusHostInfoDTO esZeusHostInfoDTO) {\n        return zeusCollectManager.updateHttpAddressFromZeus(esZeusHostInfoDTO);\n    }\n\n    @GetMapping(\"{clusterPhyName}/checkHealth\")\n    @ResponseBody\n    @ApiOperation(value = \"检查集群状态\")\n    public Result<Boolean> checkClusterHealth(HttpServletRequest request, @PathVariable String clusterPhyName) {\n        return clusterPhyManager.checkClusterHealth(clusterPhyName, HttpRequestUtil.getOperator(request));\n    }\n\n    @GetMapping(\"{clusterPhyName}/isExit\")\n    @ResponseBody\n    @ApiOperation(value = \"集群是否存在\")\n    public Result<Boolean> checkClusterIsExit(HttpServletRequest request, @PathVariable String clusterPhyName) {\n        return clusterPhyManager.checkClusterIsExit(clusterPhyName, HttpRequestUtil.getOperator(request));\n    }\n\n    @DeleteMapping(\"{clusterPhyName}/del\")\n    @ResponseBody\n    @ApiOperation(value = \"删除存在的集群\")\n    public Result<Boolean> deleteClusterExit(HttpServletRequest request, @PathVariable String clusterPhyName) {\n        return clusterPhyManager.deleteClusterExit(clusterPhyName, HttpRequestUtil.getProjectId(request),\n            HttpRequestUtil.getOperator(request));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/white/thirdpart/ThirdpartCommonController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.white.thirdpart;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_THIRD_PART;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterLogicManager;\nimport com.didichuxing.datachannel.arius.admin.biz.thardpart.CommonManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterJoinDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.config.AriusConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ThirdPartClusterVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.config.ThirdpartConfigVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport java.util.List;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(V3_THIRD_PART + \"/common\")\n@Api(tags = \"第三方公共接口(REST)\")\npublic class ThirdpartCommonController {\n\n    @Autowired\n    private CommonManager commonManager;\n    @Autowired\n    private ClusterLogicManager clusterLogicManager;\n\n    @GetMapping(\"/cluster\")\n    @ResponseBody\n    @ApiOperation(value = \"获取物理集群列表接口【三方接口】\", tags = \"【三方接口】\")\n    public Result<List<ThirdPartClusterVO>> listDataCluster() {\n        return commonManager.listDataCluster();\n\n    }\n\n    @GetMapping(\"/cluster/name\")\n    @ResponseBody\n    @ApiOperation(value = \"获取集群接口【三方接口】\", tags = \"【三方接口】\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"String\", name = \"cluster\", value = \"集群名称\", required = true) })\n    public Result<ThirdPartClusterVO> getDataCluster(@RequestParam(\"cluster\") String cluster) {\n        return commonManager.getDataCluster(cluster);\n\n    }\n\n    @PostMapping(\"/config/query\")\n    @ResponseBody\n    @ApiOperation(value = \"获取配置列表接口\", notes = \"\")\n    public Result<List<ThirdpartConfigVO>> queryConfig(@RequestBody AriusConfigInfoDTO param) {\n        return commonManager.queryConfig(param);\n    }\n    @PostMapping(\"/cluster/join-with-logic\")\n    @ResponseBody\n    @ApiOperation(value = \"加入物理集群并创建逻辑集群\", notes = \"\")\n    public Result<Long> joinClusterPhyAndCreateLogicCluster(\n                                                                               @RequestBody ClusterJoinDTO param)\n            throws AdminOperateException {\n        return clusterLogicManager.joinClusterPhyAndCreateLogicCluster(param, AuthConstant.SUPER_PROJECT_ID);\n    }\n    \n    \n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/white/thirdpart/ThirdpartGatewayV3Controller.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.white.thirdpart;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V3_THIRD_PART;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant.GATEWAY_GET_PROJECT_TICKET;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant.GATEWAY_GET_PROJECT_TICKET_NAME;\n\nimport com.didichuxing.datachannel.arius.admin.biz.gateway.GatewayManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.GatewayHeartbeat;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.IndexTemplateAliasDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateRequest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.GatewayESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplateDeployInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplatePhysicalVO;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport io.swagger.annotations.ApiParam;\nimport java.util.List;\nimport java.util.Map;\nimport javax.servlet.http.HttpServletRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n *\n * @author d06679\n * @date 2019/3/13\n */\n@RestController\n@RequestMapping(V3_THIRD_PART + \"/gateway\")\n@Api(tags = \"第三方gateway接口(REST)\")\npublic class ThirdpartGatewayV3Controller {\n\n    @Autowired\n    private GatewayManager gatewayManager;\n\n    @PutMapping(\"/heartbeat\")\n    @ResponseBody\n    @ApiOperation(value = \"gateway心跳接口\")\n    public Result<Void> heartbeat(@RequestBody GatewayHeartbeat heartbeat) {\n        return gatewayManager.heartbeat(heartbeat);\n    }\n\n    @GetMapping(\"/alivecount\")\n    @ResponseBody\n    @ApiOperation(value = \"gateway存活接口\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"String\", name = \"clusterName\", value = \"集群名称\", required = true) })\n    public Result<Integer> heartbeat(@RequestParam(value = \"clusterName\") String clusterName) {\n        return gatewayManager.heartbeat(clusterName);\n    }\n\n    @GetMapping(\"/alive-node-name\")\n    @ResponseBody\n    @ApiOperation(value = \"获取gateway存活节点名称列表接口\")\n    public Result<List<String>> getGatewayAliveNodeNames(HttpServletRequest request) {\n        return gatewayManager.getGatewayAliveNodeNames(\"Normal\");\n    }\n\n    @GetMapping(\"/project\")\n    @ResponseBody\n    @ApiOperation(value = \"获取APP列表接口\", notes = \"获取es user列表,包含es user全部元信息\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"header\", dataType = \"String\", name = \"X-ARIUS-GATEWAY-TICKET\", value = \"接口ticket\", required = true) })\n    public Result<List<GatewayESUserVO>> listApp(HttpServletRequest request) {\n        String ticket = HttpRequestUtil.getHeaderValue(GATEWAY_GET_PROJECT_TICKET_NAME);\n        if (!GATEWAY_GET_PROJECT_TICKET.equals(ticket)) {\n            return Result.buildParamIllegal(\"ticket错误\");\n        }\n        return gatewayManager.listESUserByProject();\n    }\n\n    @GetMapping(\"/template\")\n    @ResponseBody\n    @ApiOperation(value = \"获取模板信息\", notes = \"以map结构组织,key是表达式\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"String\", name = \"cluster\", value = \"集群名称\", required = true) })\n    public Result<Map<String, GatewayTemplatePhysicalVO>> getTemplateMap(@RequestParam(\"cluster\") String cluster) {\n        return gatewayManager.getTemplateMap(cluster);\n    }\n\n    @GetMapping(\"/deploy-info\")\n    @ResponseBody\n    @ApiOperation(value = \"获取模板信息\", notes = \"主主从结构组织\")\n    @ApiImplicitParams({ @ApiImplicitParam(paramType = \"query\", dataType = \"String\", name = \"dataCenter\", value = \"数据中心\", required = true) })\n    public Result<Map<String, GatewayTemplateDeployInfoVO>> listDeployInfo(@RequestParam(value = \"dataCenter\") String dataCenter) {\n        return gatewayManager.listDeployInfo();\n    }\n\n    @PostMapping(path = \"dsl/scroll-dsl-template\")\n    @ApiOperation(value = \"滚动获取查询模板数据\", notes = \"滚动获取查询模板数据\", httpMethod = \"POST\")\n    public Result<ScrollDslTemplateResponse> scrollSearchDslTemplate(@ApiParam(name = \"request\", value = \"滚动查询参数\", required = true) @RequestBody ScrollDslTemplateRequest request) {\n        return gatewayManager.scrollSearchDslTemplate(request);\n    }\n\n    @PostMapping(path = \"/alias\")\n    @ResponseBody\n    @ApiOperation(value = \"设置一个模板的别名\", notes = \"设置一个模板的别名\")\n    public Result<Boolean> addAlias(@RequestBody IndexTemplateAliasDTO indexTemplateAliasDTO) {\n        return gatewayManager.addAlias(indexTemplateAliasDTO);\n    }\n\n    @DeleteMapping(path = \"/alias\")\n    @ResponseBody\n    @ApiOperation(value = \"删除一个模板的别名\", notes = \"删除一个模板的别名\")\n    public Result<Boolean> delAlias(@RequestBody IndexTemplateAliasDTO indexTemplateAliasDTO) {\n        return gatewayManager.delAlias(indexTemplateAliasDTO);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/controller/v3/white/thirdpart/ThirdpartZeusController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.controller.v3.white.thirdpart;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.V2_THIRD_PART;\n\nimport java.util.List;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESZeusConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.PluginVO;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESClusterConfigService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPluginService;\n\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\n\n/**\n * //todo ecm部署相关，0.3.1重构替换\n *\n * @author didi\n * @date 2019/3/13\n */\n@RestController\n@RequestMapping(V2_THIRD_PART + \"/zeus\")\n@Api(tags = \"第三方Zeus接口(REST)\")\npublic class ThirdpartZeusController {\n\n    @Autowired\n    private ESPluginService  esPluginService;\n\n    @Autowired\n    private EcmTaskManager ecmTaskManager;\n\n    @Autowired\n    private ESClusterConfigService esClusterConfigService;\n\n    @GetMapping(\"/plugins/{clusterName}\")\n    @ResponseBody\n    @ApiOperation(value = \"获取集群插件信息\", notes = \"\")\n    public List<PluginVO> getPluginsByClusterName(@PathVariable String clusterName)  {\n       return ConvertUtil.list2List(esPluginService.getPluginsByClusterName(clusterName), PluginVO.class);\n    }\n\n    @GetMapping(path = \"/plugin/info\")\n    @ResponseBody\n    @ApiOperation(value = \"获取宙斯ES执行脚本插件信息\", notes = \"\")\n    @ApiImplicitParam(paramType = \"query\", dataType = \"String\", name = \"cluster_name\", value = \"集群名称\", required = true)\n    public String getPluginDetail(@RequestParam(value = \"cluster_name\") String cluster) {\n        Result<String> ecmTaskOrderDetailInfo = ecmTaskManager.getEcmTaskOrderDetailInfo(cluster);\n        if (ecmTaskOrderDetailInfo.failed()) {\n            return \"\";\n        }\n\n        return ecmTaskOrderDetailInfo.getData();\n    }\n\n    @GetMapping(\"/cluster/config/file\")\n    @ResponseBody\n    @ApiOperation(value = \"获取宙斯ES执行脚本配置内容\", notes = \"\")\n    @ApiImplicitParams({\n            @ApiImplicitParam(paramType = \"query\", dataType = \"String\", name = \"cluster_name\", value = \"集群名称\", required = true),\n            @ApiImplicitParam(paramType = \"query\", dataType = \"String\", name = \"engin_name\", value = \"组件名称\", required = true),\n            @ApiImplicitParam(paramType = \"query\", dataType = \"String\", name = \"type_name\", value = \"配置名称\", required = true)})\n    public String getConfigDetail(@RequestParam(value = \"cluster_name\") String cluster,\n                                  @RequestParam(value = \"engin_name\") String engin,\n                                  @RequestParam(value = \"type_name\") String type,\n                                  @RequestParam(value = \"config_action\")Integer configAction) {\n        return esClusterConfigService.getZeusConfigContent(buildESConfigZeus(cluster, engin, type),configAction).getData();\n    }\n\n    /***********************************************private********************************************************/\n\n    private ESZeusConfigDTO buildESConfigZeus(String cluster, String engin, String type) {\n        ESZeusConfigDTO esZeusConfigDTO = new ESZeusConfigDTO();\n        esZeusConfigDTO.setClusterName(cluster);\n        esZeusConfigDTO.setEnginName(engin);\n        esZeusConfigDTO.setTypeName(type);\n        return esZeusConfigDTO;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/exception/ExceptionHandleController.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.exception;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType.ADMIN_OPERATE_ERROR;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType.ES_OPERATE_ERROR;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.LoginManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.ResultWorkOrder;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.common.exception.*;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.exception.KfSecurityException;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.aop.ThrowsAdvice;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.RestControllerAdvice;\n\n/**\n *\n * Created by d06679 on 2019/3/13.\n */\n@RestControllerAdvice(basePackages = { \"com.didichuxing.datachannel.arius.admin.rest.controller\" }, basePackageClasses = { LoginManager.class })\npublic class ExceptionHandleController implements ThrowsAdvice {\n\n    private static final ILog LOGGER = LogFactory.getLog(ExceptionHandleController.class);\n\n    @ExceptionHandler(WorkOrderOperateException.class)\n    public ResponseEntity<ResultWorkOrder> handleWorkOrderOperateException(WorkOrderOperateException e) {\n        return new ResponseEntity<>(new ResultWorkOrder(e.getMessage(), ADMIN_OPERATE_ERROR.getCode()),\n            HttpStatus.INTERNAL_SERVER_ERROR);\n    }\n\n    @ExceptionHandler(ESOperateException.class)\n    public Result<Object> handleESOperateException(ESOperateException e) {\n        LOGGER.warn(\n            \"class=ExceptionHandleController||method=handleESOperateException||msg=arius es rest process error.\", e);\n        Result<Object> result = Result.build(ES_OPERATE_ERROR);\n        StringBuilder stringBuilder = new StringBuilder(e.getMessage());\n        Throwable throwable = e.getCause();\n        while (throwable != null) {\n            stringBuilder.append(\":\").append(throwable.getMessage());\n            throwable = throwable.getCause();\n        }\n        result.setMessage(stringBuilder.toString());\n\n        return result;\n    }\n\n    @ExceptionHandler(BaseException.class)\n    public Result<Object> handleBaseException(BaseException e) {\n        return handlerExceptionWithResult(e, e.getResultType());\n    }\n\n    @ExceptionHandler(AdminOperateException.class)\n    public Result<Object> handleBaseRunTimeException(AdminOperateException e) {\n        return handlerExceptionWithResult(e, e.getResultType());\n    }\n\n    @ExceptionHandler(IllegalArgumentException.class)\n    public Result<Object> handleIllegalArgumentException(IllegalArgumentException e) {\n        LOGGER.warn(\n            \"class=ExceptionHandleController||method=handleIllegalArgumentException||msg=Illegal Argument error \", e);\n        Result<Object> result = Result.build(ResultType.ILLEGAL_PARAMS);\n        result.setMessage(e.getMessage());\n        return result;\n    }\n\n    @ExceptionHandler(Exception.class)\n    public Result<Object> handleException(Exception e) {\n        LOGGER.warn(\"class=ExceptionHandleController||method=handleException||arius admin process error||errMsg={}\",\n            e.getMessage(), e);\n        LOGGER.warn(\"class=ExceptionHandleController||method=handleException||arius admin process error||errStack={}\",\n            e.getStackTrace());\n        Result<Object> result = Result.build(ResultType.FAIL);\n        if (StringUtils.isNotBlank(e.getMessage())) {\n            result.setMessage(e.getMessage());\n        }\n        return result;\n    }\n\n    @ExceptionHandler(KfSecurityException.class)\n    public Result<Object> handleLogiSecurityException(KfSecurityException e) {\n        LOGGER.warn(\n            \"class=ExceptionHandleController||method=handleLogiSecurityException||arius admin process error||errMsg={}\",\n            e.getMessage(), e);\n        LOGGER.warn(\n            \"class=ExceptionHandleController||method=handleLogiSecurityException||arius admin process error||errStack={}\",\n            e.getStackTrace());\n        Result<Object> result = Result.build(ResultType.FAIL);\n        if (StringUtils.isNotBlank(e.getMessage())) {\n            result.setMessage(e.getMessage());\n        }\n        return result;\n    }\n\n    @ExceptionHandler(OperateForbiddenException.class)\n    public Result<Object> handleOperateForbiddenException(OperateForbiddenException e) {\n        LOGGER.warn(\n            \"class=ExceptionHandleController||method=handleOperateForbiddenException||arius admin process error||errMsg={}\",\n            e.getMessage(), e);\n        LOGGER.warn(\n            \"class=ExceptionHandleController||method=handleOperateForbiddenException||arius admin process error||errStack={}\",\n            e.getStackTrace());\n        Result<Object> result = Result.build(ResultType.FAIL);\n        if (StringUtils.isNotBlank(e.getMessage())) {\n            result.setMessage(e.getMessage());\n        }\n        return result;\n    }\n\n    private Result<Object> handlerExceptionWithResult(Exception e, ResultType resultType) {\n        LOGGER.warn(\n            \"class=ExceptionHandleController||method=handlerExceptionWithResult||arius admin rest process error.\", e);\n        Result<Object> result = Result.build(resultType);\n        if (StringUtils.isNotBlank(e.getMessage())) {\n            result.setMessage(e.getMessage());\n        }\n        return result;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/filter/DruidStatFilter.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.filter;\n\nimport javax.servlet.annotation.WebFilter;\nimport javax.servlet.annotation.WebInitParam;\n\nimport com.alibaba.druid.support.http.WebStatFilter;\n\n/**\n * druid 监控入口filter\n * \n * @author jinbinbin\n * @version $Id: DruidStatFilter.java, v 0.1 2018年09月26日 16:12 jinbinbin Exp $\n */\n@WebFilter(filterName = \"druidWebStatFilter\", urlPatterns = { \"/*\" }, initParams = { @WebInitParam(name = \"exclusions\", value = \"*.js,*.jpg,*.png,*.gif,*.ico,*.css,/druid/*\") })\npublic class DruidStatFilter extends WebStatFilter {\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/interceptor/PermissionInterceptor.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.interceptor;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.LoginManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.GlobalParam;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.method.HandlerMethod;\nimport org.springframework.web.servlet.HandlerInterceptor;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ApiVersion.*;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.*;\n\n/**\n * 登陆拦截 && 权限校验\n */\n@Component\npublic class PermissionInterceptor implements HandlerInterceptor {\n    private static final ILog      LOGGER = LogFactory.getLog(PermissionInterceptor.class);\n\n    @Autowired\n    private LoginManager           loginManager;\n\n    @Autowired\n    private AriusConfigInfoService ariusConfigInfoService;\n\n    /**\n     * 拦截预处理\n     * @return boolean false:拦截, 不向下执行, true:放行\n     */\n    @Override\n    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,\n                             Object handler) throws Exception {\n\n        if (hasNoInterceptor(request)) {\n            return true;\n\n        }\n\n        String classRequestMappingValue = null;\n        try {\n            classRequestMappingValue = getClassRequestMappingValue(handler);\n        } catch (Exception e) {\n            LOGGER.error(\n                \"class=PermissionInterceptor||method=preHandle||uri={}||msg=parse class request-mapping failed\",\n                request.getRequestURI(), e);\n        }\n        List<String> whiteMappingValues = Lists.newArrayList(HEALTH, V2_THIRD_PART, V3_THIRD_PART, V3_WHITE_PART,\n            V3_SECURITY);\n\n        return loginManager.interceptorCheck(request, response, classRequestMappingValue, whiteMappingValues);\n    }\n\n    @Override\n    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,\n                                Exception ex) {\n        GlobalParam.CURRENT_USER.remove();\n        GlobalParam.CURRENT_PROJECT_ID.remove();\n    }\n\n    /**\n     * 通过反射获取带有@RequestMapping的Controller\n     * @param handler 请求处理器\n     * @return @RequestMapping的value\n     */\n    private String getClassRequestMappingValue(Object handler) {\n        RequestMapping requestMapping;\n        if (handler instanceof HandlerMethod) {\n            HandlerMethod hm = (HandlerMethod) handler;\n            requestMapping = hm.getMethod().getDeclaringClass().getAnnotation(RequestMapping.class);\n        } else if (handler instanceof org.springframework.web.servlet.mvc.Controller) {\n            org.springframework.web.servlet.mvc.Controller hm = (org.springframework.web.servlet.mvc.Controller) handler;\n            Class<? extends org.springframework.web.servlet.mvc.Controller> hmClass = hm.getClass();\n            requestMapping = hmClass.getAnnotation(RequestMapping.class);\n        } else {\n            requestMapping = handler.getClass().getAnnotation(RequestMapping.class);\n        }\n        if (AriusObjUtils.isNull(requestMapping) || requestMapping.value().length == 0) {\n            return null;\n        }\n        return requestMapping.value()[0];\n    }\n\n    /**\n     * 是否需要拦截\n     */\n    private boolean hasNoInterceptor(HttpServletRequest request) {\n\n        if (EnvUtil.isDev()) {\n            return Boolean.TRUE;\n        }\n\n        if (request.getServletPath().contains(SWAGGER)) {\n            return Boolean.TRUE;\n        }\n\n        boolean interceptorSwitch = ariusConfigInfoService.booleanSetting(ARIUS_COMMON_GROUP,\n            REQUEST_INTERCEPTOR_SWITCH_OPEN, REQUEST_INTERCEPTOR_SWITCH_OPEN_DEFAULT_VALUE);\n        if (!interceptorSwitch) {\n            return Boolean.TRUE;\n        }\n\n        return Boolean.FALSE;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/servlet/DruidStatViewServlet.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.servlet;\n\n/**\n * \n * druid 监控入口servlet\n * \n * @author jinbinbin\n * @version $Id: DruidStatViewServlet.java, v 0.1 2018年09月26日 16:14 jinbinbin Exp $\n */\n\nimport javax.servlet.Servlet;\nimport javax.servlet.annotation.WebInitParam;\nimport javax.servlet.annotation.WebServlet;\n\nimport com.alibaba.druid.support.http.StatViewServlet;\n\n@WebServlet(urlPatterns = { \"/druid/*\" }, initParams = {\n                                                         // @WebInitParam(name = \"allow\", value = \"127.0.0.1\"),\n                                                         @WebInitParam(name = \"loginUsername\", value = \"druid\"),\n                                                         @WebInitParam(name = \"loginPassword\", value = \"druid\"),\n                                                         @WebInitParam(name = \"resetEnable\", value = \"false\") })\npublic class DruidStatViewServlet extends StatViewServlet implements Servlet {\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/swagger/SwaggerConfiguration.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.swagger;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.EnvUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport com.google.common.collect.Lists;\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport springfox.documentation.builders.ApiInfoBuilder;\nimport springfox.documentation.builders.ParameterBuilder;\nimport springfox.documentation.builders.PathSelectors;\nimport springfox.documentation.builders.RequestHandlerSelectors;\nimport springfox.documentation.builders.ResponseMessageBuilder;\nimport springfox.documentation.schema.ModelRef;\nimport springfox.documentation.service.ApiInfo;\nimport springfox.documentation.service.Parameter;\nimport springfox.documentation.service.ResponseMessage;\nimport springfox.documentation.spi.DocumentationType;\nimport springfox.documentation.spring.web.plugins.Docket;\nimport springfox.documentation.swagger2.annotations.EnableSwagger2;\n\n/**\n * Swagger配置类\n */\n@Configuration\n@EnableSwagger2\n@NoArgsConstructor\npublic class SwaggerConfiguration {\n\n    private static final ILog   LOGGER = LogFactory.getLog(SwaggerConfiguration.class);\n\n    private static List<String> envs   = Lists.newArrayList();\n    private final static String HEADER = \"header\";\n\n    @Value(\"${swagger.enable:false}\")\n    private boolean             enable;\n    @Value(value = \"${admin.port.web}\")\n    private int                 port;\n\n    @Bean\n    public Docket createRestApi() {\n        String envStr = String.join(\",\", Lists.newArrayList(envs));\n        if (!envStr.contains(EnvUtil.EnvType.TEST.getStr()) && !envStr.contains(EnvUtil.EnvType.DEV.getStr())) {\n            return new Docket(DocumentationType.SWAGGER_2).enable(enable);\n        }\n\n        LOGGER.info(\"class=SwaggerConfiguration||method=createRestApi||swagger started||env={}\", envStr);\n\n        List<ResponseMessage> responseMessageList = new ArrayList<>();\n        responseMessageList.add(new ResponseMessageBuilder().code(200)\n            .message(\"OK；服务正常返回或者异常都返回200，通过返回结构中的code来区分异常；code为0表示操作成功，其他为异常\").build());\n        responseMessageList.add(new ResponseMessageBuilder().code(404).message(\"资源找不到；请确认URL是否正确\").build());\n\n        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()\n            .apis(RequestHandlerSelectors.basePackage(\"com.didichuxing.datachannel.arius.admin\"))\n            .paths(PathSelectors.any()).build().globalOperationParameters(parameters()).useDefaultResponseMessages(true)\n            .globalResponseMessage(RequestMethod.GET, responseMessageList)\n            .globalResponseMessage(RequestMethod.POST, responseMessageList)\n            .globalResponseMessage(RequestMethod.PUT, responseMessageList)\n            .globalResponseMessage(RequestMethod.DELETE, responseMessageList);\n    }\n\n    private List<Parameter> parameters() {\n\n        final Parameter user = new ParameterBuilder().name(HttpRequestUtil.USER).description(\"操作人\")\n            .modelRef(new ModelRef(\"string\")).parameterType(HEADER).required(false).defaultValue(\"\").build();\n        final Parameter userId = new ParameterBuilder().name(HttpRequestUtil.USER_ID).description(\"操作人id\")\n            .modelRef(new ModelRef(\"integer\")).parameterType(HEADER).required(false).build();\n        final Parameter projectId = new ParameterBuilder().name(HttpRequestUtil.PROJECT_ID)\n            .description(\"项目id:在项目创建后，各个接口都需要带此header\").modelRef(new ModelRef(\"integer\")).parameterType(HEADER)\n            .required(false).build();\n\n        return Lists.newArrayList(user, userId, projectId);\n    }\n\n    /**\n     * 创建该Api的基本信息（这些基本信息会展现在文档页面中）\n     *\n     * @return\n     */\n    private ApiInfo apiInfo() {\n        return new ApiInfoBuilder().title(\"AriusAdmin接口文档\").description(String.format(\"当前环境:%s\", envs))\n            .version(\"1.0_\" + String.join(\",\", envs)).build();\n    }\n\n    public static void initEnv(String[] args) {\n        if (args == null) {\n            return;\n        }\n\n        try {\n            for (String arg : args) {\n                String[] argArr = arg.split(\"=\");\n                if (argArr[0].toLowerCase().contains(\"spring.profiles.active\")) {\n                    envs.add(argArr[1]);\n                }\n            }\n            LOGGER.info(\"class=SwaggerConfiguration||method=initEnv||swagger||env={}\", envs);\n        } catch (Exception e) {\n            LOGGER.warn(\"class=SwaggerConfiguration||method=initEnv||initEnv error||args={}\", args, e);\n        }\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/web/TranslateHttpServletRequestWrapper.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.web;\n\nimport org.apache.commons.io.IOUtils;\nimport org.apache.commons.lang3.StringUtils;\n\nimport javax.servlet.ServletInputStream;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletRequestWrapper;\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\n\n/**\n * @author jinbinbin\n * @version $Id: TranslateHttpServletRequestWrapper.java, v 0.1 2018年11月22日 10:28 jinbinbin Exp $\n */\nclass TranslateHttpServletRequestWrapper extends HttpServletRequestWrapper {\n\n    private String body;\n    private String encoding = \"UTF-8\";\n\n    public TranslateHttpServletRequestWrapper(HttpServletRequest request) throws IOException {\n        super(request);\n        if (StringUtils.isNotBlank(request.getCharacterEncoding())) {\n            this.encoding = request.getCharacterEncoding();\n        }\n        body = IOUtils.toString(request.getInputStream(), encoding);\n    }\n\n    @Override\n    public BufferedReader getReader() throws IOException {\n        return new BufferedReader(new InputStreamReader(getInputStream()));\n    }\n\n    @Override\n    public ServletInputStream getInputStream() throws IOException {\n        ServletInputStream inputStream;\n        if (StringUtils.isNotEmpty(body)) {\n            inputStream = new TranslateServletInputStream(body.getBytes(encoding));\n        } else {\n            inputStream = new TranslateServletInputStream(new byte[0]);\n        }\n        return inputStream;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/web/TranslateServletInputStream.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.web;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\n\nimport javax.servlet.ReadListener;\nimport javax.servlet.ServletInputStream;\n\n/**\n * @author jinbinbin\n * @version $Id: TranslateServletInputStream.java, v 0.1 2018年10月17日 14:49 jinbinbin Exp $\n */\npublic class TranslateServletInputStream extends ServletInputStream {\n\n    private ByteArrayInputStream inputStream;\n\n    private boolean              finished = false;\n\n    public TranslateServletInputStream(byte[] buffer) {\n        this.inputStream = new ByteArrayInputStream(buffer);\n    }\n\n    @Override\n    public int available() throws IOException {\n        return inputStream.available();\n    }\n\n    @Override\n    public int read() throws IOException {\n        int data = this.inputStream.read();\n        if (data == -1) {\n            this.finished = true;\n        }\n        return data;\n    }\n\n    @Override\n    public int read(byte[] b, int off, int len) throws IOException {\n        int data = this.inputStream.read(b, off, len);\n        if (data == -1) {\n            this.finished = true;\n        }\n        return data;\n    }\n\n    @Override\n    public void close() throws IOException {\n        super.close();\n        this.inputStream.close();\n    }\n\n    @Override\n    public boolean isFinished() {\n        return this.finished;\n    }\n\n    @Override\n    public boolean isReady() {\n        return true;\n    }\n\n    @Override\n    public void setReadListener(ReadListener readListener) {\n        throw new UnsupportedOperationException();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/web/UrlHelper.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.web;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * 比较杂的工具类\n *\n * @author wangxiaoxue\n * @version $Id: URLHelper.java, v 0.1 2015年7月16日 上午10:44:10 Administrator Exp $\n */\npublic class UrlHelper {\n\n    private UrlHelper() {\n    }\n\n    private static final String UK = \"unknown\";\n\n    public static String getIpAddr(HttpServletRequest request) {\n        String ip = request.getHeader(\"x-forwarded-for\");\n        if (StringUtils.isBlank(ip) || UK.equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"Proxy-Client-IP\");\n        }\n        if (StringUtils.isBlank(ip) || UK.equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"WL-Proxy-Client-IP\");\n        }\n        if (StringUtils.isBlank(ip) || UK.equalsIgnoreCase(ip)) {\n            ip = request.getRemoteAddr();\n        }\n\n        return fixIp(ip);\n    }\n\n    /**\n     * x-forwarded-for nginx多层ip处理\n     * @param ip\n     * @return\n     */\n    private static String fixIp(String ip) {\n        String realIp = ip;\n        if (StringUtils.isNotBlank(ip) && ip.contains(\",\")) {\n            String[] ipArray = ip.split(\",\");\n            realIp = ipArray[ipArray.length - 1];\n        }\n        return realIp != null ? realIp.trim() : null;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/web/WebConstant.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.web;\n\npublic class WebConstant {\n    private WebConstant() {\n    }\n\n    public static final String X_REQUEST_ID    = \"X-Request-ID\";\n    public static final String USER_HEADER_KEY = \"X-SSO-USER\";\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/java/com/didichuxing/datachannel/arius/admin/rest/web/WebRequestLogFilter.java",
    "content": "package com.didichuxing.datachannel.arius.admin.rest.web;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.log.common.Constants;\nimport com.didiglobal.knowframework.log.common.TraceContext;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.io.IOUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.core.Ordered;\nimport org.springframework.web.util.ContentCachingResponseWrapper;\nimport org.springframework.web.util.WebUtils;\n\nimport javax.servlet.*;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.io.UnsupportedEncodingException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.*;\n\n/**\n * @author jinbinbin\n * @version $Id: AccessLogFilter.java, v 0.1 2018年03月05日 22:01 jinbinbin Exp $\n */\npublic class WebRequestLogFilter implements Ordered, Filter {\n\n    private static final ILog        LOGGER                            = LogFactory.getLog(\"accessLogger\");\n    private static final ILog        RESP_LOGGER                       = LogFactory.getLog(\"responseLogger\");\n\n    public static final String       RESPONSE_LOG_ENABLE               = \"responseLogEnable\";\n    public static final String       EXCLUDE_URLS                      = \"excludeAllUrls\";\n    public static final String       EXCLUDE_REQUEST_BODY_URLS         = \"excludeReqBodyUrls\";\n    public static final String       EXCLUDE_RESPONSE_BODY_URLS        = \"excludeRespBodyUrls\";\n    public static final String       EXCLUDE_RESPONSE_BODY_URLS_PREFER = \"excludeRespBodyUrlsPrefer\";\n\n    private static final Set<String> ALL_EXCLUDE_URLS                  = new HashSet<>();\n    private static final Set<String> REQ_BODY_EXCLUDE_URLS             = new HashSet<>();\n    private static final Set<String> RESP_BODY_EXCLUDE_URLS            = new HashSet<>();\n    private static final Set<String> RESP_BODY_EXCLUDE_URLS_PREFER     = new HashSet<>();\n\n    private Boolean                  respLogEnable                     = Boolean.TRUE;\n\n    @Override\n    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException,\n                                                                                      ServletException {\n\n        long begin = System.currentTimeMillis();\n\n        HttpServletRequest request = (HttpServletRequest) req;\n        HttpServletResponse response = (HttpServletResponse) resp;\n        // spring 的ContentCachingRequestWrapper存在bug，无法读取request body\n        TranslateHttpServletRequestWrapper wrapperRequest = new TranslateHttpServletRequestWrapper(request);\n        ContentCachingResponseWrapper wrapperResponse = new ContentCachingResponseWrapper(response);\n\n        String requestUrl = request.getRequestURI();\n        try {\n            initTrace(request);\n            logRequest(wrapperRequest, requestUrl);\n            chain.doFilter(wrapperRequest, wrapperResponse);\n        } finally {\n            try {\n                logResponse(begin, wrapperResponse, requestUrl);\n                wrapperResponse.copyBodyToResponse();\n            } finally {\n                LogFactory.removeFlag();\n            }\n        }\n    }\n\n    private void initTrace(HttpServletRequest request) {\n        String traceid = request.getHeader(Constants.TRACE_ID);\n        if (traceid == null) {\n            traceid = request.getHeader(Constants.X_REQUEST_ID);\n        }\n        if (traceid == null) {\n            traceid = request.getHeader(Constants.FLAG);\n        }\n        if (traceid == null) {\n            traceid = LogFactory.getUniqueFlag();\n        }\n\n        String cspanId = request.getHeader(Constants.CSPAN_ID);\n        if (cspanId == null) {\n            cspanId = \"-1\";\n        }\n        TraceContext traceContext = new TraceContext(traceid, cspanId);\n        LogFactory.setTrace(traceContext);\n        LogFactory.setFlag(traceid);\n    }\n\n    private void logResponse(long begin, ContentCachingResponseWrapper wrapperResponse, String requestUrl) {\n        if (!respLogEnable.booleanValue()) {\n            return;\n        }\n\n        if (ALL_EXCLUDE_URLS.contains(requestUrl)) {\n            return;\n        }\n\n        String responseBody;\n\n        if (RESP_BODY_EXCLUDE_URLS.contains(requestUrl) || matchPrefer(RESP_BODY_EXCLUDE_URLS_PREFER, requestUrl)) {\n            responseBody = \"{\\\"exclude\\\":true}\";\n        } else {\n            responseBody = getResponseBody(wrapperResponse);\n        }\n        RESP_LOGGER.info(\"class=WebRequestLogFilter||method=logResponse||response||responseBody={}||timeCost={}\",\n            responseBody, (System.currentTimeMillis() - begin));\n    }\n\n    private void logRequest(TranslateHttpServletRequestWrapper request, String requestUrl) {\n        if (ALL_EXCLUDE_URLS.contains(requestUrl)) {\n            return;\n        }\n\n        Map<String, String> headers = getHeaders(request);\n        String requestBody;\n        if (REQ_BODY_EXCLUDE_URLS.contains(requestUrl)) {\n            requestBody = \"{\\\"exclude\\\":true}\";\n        } else {\n            requestBody = getRequestBody(request);\n        }\n        LOGGER.info(\n            \"class=WebRequestLogFilter||method=logRequest||request||url={}||method={}||remoteAddr={}||headers={}||urlParams={}||body={}\",\n            request.getRequestURI(), request.getMethod(), UrlHelper.getIpAddr(request), headers,\n            request.getQueryString(), requestBody, StandardCharsets.UTF_8);\n    }\n\n    @Override\n    public void init(FilterConfig filterConfig) throws ServletException {\n        initExcludeUrl(filterConfig, EXCLUDE_URLS, ALL_EXCLUDE_URLS);\n        initExcludeUrl(filterConfig, EXCLUDE_REQUEST_BODY_URLS, REQ_BODY_EXCLUDE_URLS);\n        initExcludeUrl(filterConfig, EXCLUDE_RESPONSE_BODY_URLS, RESP_BODY_EXCLUDE_URLS);\n        initExcludeUrl(filterConfig, EXCLUDE_RESPONSE_BODY_URLS_PREFER, RESP_BODY_EXCLUDE_URLS_PREFER);\n        if (filterConfig.getInitParameter(RESPONSE_LOG_ENABLE) != null) {\n            respLogEnable = Boolean.valueOf(filterConfig.getInitParameter(RESPONSE_LOG_ENABLE));\n        }\n    }\n\n    /**\n     * 打印请求参数\n     *\n     * @param response\n     */\n    private String getResponseBody(ContentCachingResponseWrapper response) {\n        ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response,\n            ContentCachingResponseWrapper.class);\n        if (wrapper != null) {\n            byte[] buf = wrapper.getContentAsByteArray();\n            if (buf.length > 0) {\n                String payload;\n                try {\n                    payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding());\n                } catch (UnsupportedEncodingException e) {\n                    payload = new String(buf, 0, buf.length, StandardCharsets.UTF_8);\n                }\n                return payload;\n            }\n        }\n        return \"\";\n    }\n\n    private Map<String, String> getHeaders(HttpServletRequest request) {\n        Map<String, String> params = new HashMap<>();\n        params.put(\"refer\", request.getHeader(\"referer\"));\n        params.put(\"agent\", request.getHeader(\"User-Agent\"));\n        params.put(WebConstant.USER_HEADER_KEY, request.getHeader(WebConstant.USER_HEADER_KEY));\n\n        return params;\n    }\n\n    /**\n     * 打印请求参数\n     *\n     * @param request\n     */\n    private String getRequestBody(TranslateHttpServletRequestWrapper request) {\n        try {\n            String body = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);\n            return body.replace(\"\\n\", \"\");\n        } catch (Exception e) {\n            return \"\";\n        }\n    }\n\n    private void initExcludeUrl(FilterConfig filterConfig, String excludeUrls, Set<String> urlContainers) {\n        String allExcludeUrls = filterConfig.getInitParameter(excludeUrls);\n        if (StringUtils.isNotBlank(allExcludeUrls)) {\n            String[] pattern = allExcludeUrls.split(\",\");\n            urlContainers.addAll(Arrays.asList(pattern));\n        }\n    }\n\n    private boolean matchPrefer(Set<String> preferSet, String requestUrl) {\n\n        if (CollectionUtils.isEmpty(preferSet)) {\n            return false;\n        }\n\n        for (String prefer : preferSet) {\n            if (requestUrl.startsWith(prefer)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public void destroy() {\n        // doNothing\n    }\n\n    @Override\n    public int getOrder() {\n        return Ordered.LOWEST_PRECEDENCE - 8;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/resources/application-test.yml",
    "content": "#索引统计相关配置\nes.metrics.cluster.buckets.max.num: 5000\nes.metrics.nodes.buckets.max.num: 5000\nes.metrics.indices.buckets.max.num: 10000\n\n#DSL查询模版相关配置\n# 默认的查询限流值\ndefault.query.limit: 800\n# 查询模板过期删除时间\ndelete.expired.template.time: now-1d\n# 查询历史数据时间\nhistory.query.time: now-93d\n\n#admin相关配置\nadmin.port.web: 8010\nadmin.contextPath: /admin/api\nadmin.url.console: http://10.190.6.107/\nadmin.url.kibana: http://10.160.80.135:8061/\nadmin.thread.size.op: 20\n\n#gateway相关配置\nes.gateway.url: 10.190.44.150,10.190.42.122\nes.gateway.port: 8200\nes.user: 1\nes.password: azAWiJhxkho33ac\nscroll.timeout: 60s\n\n#ES元数据集群相关配置\nes.update.cluster.name: logi-elasticsearch-7.6.0\n\n#ES客户端相关配置\nes.client.cluster.port: 8061\nes.client.io.thread.count: 8\n\n#可观测性相关配置\nmonitorJob.threadPool.initsize: 20\nmonitorJob.threadPool.maxsize: 20\n\n#扩展服务相关配置\nextend.service:\nextend.fileStorage: s3\nextend.employee: defaultEmployee\nextend.loginProtocol: defaultLogin\n\n#dcdr相关配置\n# 并发执行数\ndcdr.concurrent: 2\n# 容错数\ndcdr.fault.tolerant: 5\n\n#依赖的 remote 接口的配置\n#zeus的相关信息\nzeus.server: http://10.96.65.64:8010\nzeus.token: 9e2dbb6e5b1e594d1820e0f21669b240\nzeus.templateId: 3\nzeus.user: root\nzeus.batch: 2\nzeus.timeOut: 300\nzeus.tolerance: 0\n#s3的相关配置\ns3.endpoint: s3-gzpu-inter.didistatic.com\ns3.access-key: \ns3.secret-key: \ns3.bucket: logi-data-es\n#swagger\nswagger.enable: true\n\n#集成测试相关配置\nintegrate.test.admin.ip: 127.0.0.1\nintegrate.test.admin.port: 8010\nintegrate.test.es.ip: 10.190.55.161\nintegrate.test.es.port: 8888\nintegrate.test.esuser: 1\nintegrate.test.operator: admin\n\n\n#统计项目对应各方法代码行相关配置\nstat.method.line.standardLineOfMethod: 60\n\n#日志相关配置\nlogging.pattern.file: \"[%level][%d{yyyy-MM-dd'T'HH:mm:ss.SSS}][%t] %msg%xEx%n\"\nlogging.config: classpath:log4j2-dev.xml\nlogging.path: .\nlogging.file.max-history: 5\n\n#spring公共配置\nspring:\n  http:\n    encoding:\n      force: true\n      charset: UTF-8\n      enabled: true\n  messages:\n    encoding: UTF-8\n  profiles:\n    active: dev\n  datasource:\n    name: data\n    type: com.alibaba.druid.pool.DruidDataSource\n    druid:\n      driver-class-name: org.mariadb.jdbc.Driver\n      url: jdbc:mariadb://127.0.0.1:3306/knowsearch_0312?useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=true&allowMultiQueries=true&useSSL=false&alwaysAutoGeneratedKeys=true&serverTimezone=GMT%2B8\n      username: root\n      password: \n      initialSize: 10\n      validationQueryTimeout: 5000\n      transactionQueryTimeout: 60000\n      minIdle: 10\n      maxActive: 30\n      max-wait: 60000\n      keepAlive: true\n      time-between-eviction-runs-millis: 1000\n      min-evictable-idle-time-millis: 300000\n      defaultAutoCommit: true\n      validationQuery: select 'x'\n      testWhileIdle: true\n      testOnReturn: false\n      testOnBorrow: true\n      logAbandoned: true\n      pool-prepared-statements: true\n      max-open-prepared-statements: 50\n      filters: stat,wall\n  servlet:\n    multipart:\n      max-file-size: 600MB\n      max-request-size: 600MB\n  logi-job:\n    jdbc-url: jdbc:mariadb://127.0.0.1:3306/knowsearch_0312?useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=true&allowMultiQueries=true&useSSL=false&alwaysAutoGeneratedKeys=true&serverTimezone=GMT%2B8\n    username: root\n    password: \n    driver-class-name: org.mariadb.jdbc.Driver\n    max-lifetime: 60000\n    init-sql: true\n    init-thread-num: 50\n    max-thread-num: 100\n    log-exipre: 3 # 日志保存天数，以天为单位\n    app_name: arius_test03\n    claim-strategy: com.didiglobal.knowframework.job.core.consensual.RandomConsensual\n    node-name: node1\n    job-log-fetcher-extend-bean-name: com.didiglobal.knowframework.job.extend.impl.DefaultJobLogFetcherExtendImpl\n    elasticsearch-address: 116.85.23.222\n    elasticsearch-port: 18303\n    elasticsearch-user: elastic\n    elasticsearch-password: Didiyun@888\n    elasticsearch-index-name: test\n    elasticsearch-type-name: type\n  kf-security:\n    app-name: know_search\n    driver-class-name: ${spring.datasource.druid.driver-class-name}\n    jdbc-url: ${spring.datasource.druid.url}\n    password: ${spring.datasource.druid.password}\n    username: ${spring.datasource.druid.username}\n    resource-extend-bean-name: resourceExtendManager\n    #    0.3.1.1新增\n    login-extend-bean-name: logiSecurityDefaultLoginExtendImpl\n  application:\n    admin:\n      enabled:\n  transaction:\n    default-timeout: 60\n  jackson:\n    time-zone: GMT+8\n    date-format: yyyy-MM-dd HH:mm:ss\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/resources/application.yml",
    "content": "#索引统计相关配置\nes.metrics.cluster.buckets.max.num: 5000\nes.metrics.nodes.buckets.max.num: 5000\nes.metrics.indices.buckets.max.num: 10000\n\n#DSL查询模版相关配置\n# 默认的查询限流值\ndefault.query.limit: 800\n# 查询模板过期删除时间\ndelete.expired.template.time: now-1d\n# 查询历史数据时间\nhistory.query.time: now-93d\n\n#admin相关配置\nadmin.port.web: 8010\nadmin.contextPath: /admin/api\nadmin.url.console: http://10.96.75.13/\nadmin.url.kibana: http://10.96.75.13:18967/\nadmin.thread.size.op: 20\n\n#gateway相关配置\nes.gateway.url: 10.96.75.13\nes.gateway.port: 18278\nes.user: 1\nes.password: azAWiJhxkho33ac\nscroll.timeout: 60s\n\n#ES元数据集群相关配置\nes.update.cluster.name: logi-elasticsearch-meta\n\n#ES客户端相关配置\nes.client.cluster.port: 18143\nes.client.io.thread.count: 8\n\n#可观测性相关配置\nmonitorJob.threadPool.initsize: 20\nmonitorJob.threadPool.maxsize: 20\n\n#扩展服务相关配置\nextend.service:\nextend.fileStorage: s3\nextend.employee: defaultEmployee\nextend.loginProtocol: defaultLogin\n\n#dcdr相关配置\n# 并发执行数\ndcdr.concurrent: 2\n# 容错数\ndcdr.fault.tolerant: 5\n\n#依赖的 remote 接口的配置\n#zeus的相关信息\nzeus.server: http://10.96.65.64:8010\nzeus.token: 9e2dbb6e5b1e594d1820e0f21669b240\nzeus.templateId: 3\nzeus.user: root\nzeus.batch: 2\nzeus.timeOut: 300\nzeus.tolerance: 0\n#s3的相关配置\ns3.endpoint: s3-gzpu-inter.didistatic.com\ns3.access-key: AKDD00000000000O5XVS8IBAXT7R9X\ns3.secret-key: ASDDhiAaCIjLqFswvIXzyVvkqLJKYtLNLAlabXFS\ns3.bucket: logi-data-es\n#swagger\nswagger.enable: true\n\n#集成测试相关配置\nintegrate.test.admin.ip: 127.0.0.1\nintegrate.test.admin.port: 8010\nintegrate.test.es.ip: 10.190.55.161\nintegrate.test.es.port: 8888\nintegrate.test.esuser: 1\nintegrate.test.operator: admin\n\n\n#统计项目对应各方法代码行相关配置\nstat.method.line.standardLineOfMethod: 60\n\n#日志相关配置\nlogging.pattern.file: \"[%level][%d{yyyy-MM-dd'T'HH:mm:ss.SSS}][%t] %msg%xEx%n\"\nlogging.config: classpath:log4j2-dev.xml\nlogging.path: .\nlogging.file.max-history: 5\n\n#spring公共配置\nspring:\n  http:\n    encoding:\n      force: true\n      charset: UTF-8\n      enabled: true\n  messages:\n    encoding: UTF-8\n  profiles:\n    active: dev\n  datasource:\n    name: data\n    type: com.alibaba.druid.pool.DruidDataSource\n    druid:\n      driver-class-name: org.mariadb.jdbc.Driver\n      url: jdbc:mariadb://10.96.75.13:3306/knowsearch_0312?useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=true&allowMultiQueries=true&useSSL=false&alwaysAutoGeneratedKeys=true&serverTimezone=GMT%2B8\n      username: root\n      password: MmNhMzkyOD_Di2\n      initialSize: 10\n      validationQueryTimeout: 5000\n      transactionQueryTimeout: 60000\n      minIdle: 10\n      maxActive: 30\n      max-wait: 60000\n      keepAlive: true\n      time-between-eviction-runs-millis: 1000\n      min-evictable-idle-time-millis: 300000\n      defaultAutoCommit: true\n      validationQuery: select 'x'\n      testWhileIdle: true\n      testOnReturn: false\n      testOnBorrow: true\n      logAbandoned: true\n      pool-prepared-statements: true\n      max-open-prepared-statements: 50\n      filters: stat,wall\n  servlet:\n    multipart:\n      max-file-size: 600MB\n      max-request-size: 600MB\n  logi-job:\n    jdbc-url: jdbc:mariadb://10.96.75.13:3306/knowsearch_0312?useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=true&allowMultiQueries=true&useSSL=false&alwaysAutoGeneratedKeys=true&serverTimezone=GMT%2B8\n    username: root\n    password: MmNhMzkyOD_Di2\n    driver-class-name: org.mariadb.jdbc.Driver\n    max-lifetime: 60000\n    init-sql: true\n    init-thread-num: 50\n    max-thread-num: 100\n    log-exipre: 3 # 日志保存天数，以天为单位\n    app_name: arius_test03\n    claim-strategy: com.didiglobal.knowframework.job.core.consensual.RandomConsensual\n    node-name: node1\n    job-log-fetcher-extend-bean-name: com.didiglobal.knowframework.job.extend.impl.DefaultJobLogFetcherExtendImpl\n    elasticsearch-address: 10.96.75.13\n    elasticsearch-port: 18143\n    elasticsearch-user: elastic\n    elasticsearch-password: Didiyun@888\n    elasticsearch-index-name: index_observability\n    elasticsearch-type-name: type\n  kf-security:\n    app-name: know_search\n    driver-class-name: ${spring.datasource.druid.driver-class-name}\n    jdbc-url: ${spring.datasource.druid.url}\n    password: ${spring.datasource.druid.password}\n    username: ${spring.datasource.druid.username}\n    resource-extend-bean-name: resourceExtendManager\n#    0.3.1.1新增\n    login-extend-bean-name: logiSecurityDefaultLoginExtendImpl\n  application:\n    admin:\n      enabled:\n  transaction:\n    default-timeout: 60\n  jackson:\n    time-zone: GMT+8\n    date-format: yyyy-MM-dd HH:mm:ss"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/resources/banner.txt",
    "content": "    __                                                                    __\n   / /__   ____   ____  _      __   _____  ___   ____ _   _____  _____   / /_\n  / //_/  / __ \\ / __ \\| | /| / /  / ___/ / _ \\ / __ `/  / ___/ / ___/  / __ \\\n / ,<    / / / // /_/ /| |/ |/ /  (__  ) /  __// /_/ /  / /    / /__   / / / /\n/_/|_|  /_/ /_/ \\____/ |__/|__/  /____/  \\___/ \\__,_/  /_/     \\___/  /_/ /_/\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/resources/log4j2-dev.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Configuration package=\"org.apache.logging.log4j.core,com.didiglobal.knowframework.log.log4j2.appender\">\n    <Properties>\n        <Property name=\"address\" value=\"${spring.logi-job.elasticsearch-address}\"/>\n        <Property name=\"port\" value=\"${spring.logi-job.elasticsearch-port}\"/>\n        <Property name=\"user\" value=\"${spring.logi-job.elasticsearch-user}\"/>\n        <Property name=\"password\" value=\"${spring.logi-job.elasticsearch-password}\"/>\n        <Property name=\"indexName\" value=\"${spring.logi-job.elasticsearch-index-name}\"/>\n        <Property name=\"typeName\" value=\"${spring.logi-job.elasticsearch-type-name}\"/>\n        <!-- 基础日志配置 -->\n        <Property name=\"PID\">????</Property>\n        <Property name=\"LOG_EXCEPTION_CONVERSION_WORD\">%xwEx</Property>\n        <Property name=\"LOG_LEVEL_PATTERN\">%5p</Property>\n        <Property name=\"LOG_DATEFORMAT_PATTERN\">yyyy-MM-dd HH:mm:ss.SSS</Property>\n        <Property name=\"CONSOLE_LOG_PATTERN\">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>\n        <Property name=\"log_pattern\">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>\n        <!-- name的值是变量的名称，value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后，可以使\"${}\"来使用变量。 -->\n        <property name=\"log.path\">./logs/</property>\n    </Properties>\n    <Appenders>\n        <Console name=\"Console\" target=\"SYSTEM_OUT\"/>\n        <ElasticsearchAppender name=\"esAppender\" address=\"${address}\" port=\"${port}\" user=\"${user}\"\n                               password=\"${password}\" indexName=\"${indexName}\" typeName=\"${typeName}\" threshold=\"all\"\n                               bufferSize=\"10000\" numberOfShards=\"5\" numberOfReplicas=\"0\" logExpire=\"3\"\n                               extendsMappingClass=\"\" requestTimeoutMillis=\"3000\" discardWhenBufferIsFull=\"true\">\n            <Filters>\n                <!--配置日志表达式，-->\n                <!-- 开启所有日志-->\n                <!--                <RegexFilter regex='.*\"logEventType\":\"(LOG|METRIC|TRACE)\".*' onMatch=\"ACCEPT\" onMismatch=\"DENY\"/>-->\n                <!-- 仅开启LOG和METRIC-->\n                <!-- <RegexFilter regex='.*\"logEventType\":\"(LOG|METRIC)\".*' onMatch=\"ACCEPT\" onMismatch=\"DENY\"/> -->\n                <!-- 开启LOG和METRIC，TRACE日志仅当traceId不为空时打印-->\n                <!--            <RegexFilter regex='.*\"logEventType\":\"(LOG|METRIC)\".*' onMatch=\"ACCEPT\" onMismatch=\"NEUTRAL\"/>-->\n                <!--            <RegexFilter regex='.*\"logEventType\":\"TRACE\".*' onMatch=\"NEUTRAL\" onMismatch=\"DENY\"/>-->\n                <!--            <RegexFilter regex='.*\"traceId\":\"[a-z0-9]+\".*' onMatch=\"NEUTRAL\" onMismatch=\"DENY\"/>-->\n            </Filters>\n        </ElasticsearchAppender>\n        <RollingFile name=\"systemLog\"\n                     filename=\"${log.path}/system.log\" filePattern=\"${log.path}/system.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Filters>\n                <!-- 只要level及其以上级别的信息（onMatch），其他的直接拒绝（onMismatch）-->\n                <ThresholdFilter level=\"INFO\" onMatch=\"ACCEPT\" onMismatch=\"DENY\"/>\n            </Filters>\n\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"1\">\n                <!-- 配置日志滚动删除策略 IfLastModified 的单位需要配合 filePattern中的规则使用 -->\n                <Delete basePath=\"${log.path}\" maxDepth=\"1\">\n                    <IfFileName glob=\"*.log.*\"/>\n                    <IfLastModified age=\"3d\"/>\n                </Delete>\n            </DefaultRolloverStrategy>\n        </RollingFile>\n\n        <RollingFile name=\"errorLog\"\n                     filename=\"${log.path}/error.log\" filePattern=\"${log.path}/error.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Filters>\n                <!-- 只要level及其以上级别的信息（onMatch），其他的直接拒绝（onMismatch）-->\n                <ThresholdFilter level=\"ERROR\" onMatch=\"ACCEPT\" onMismatch=\"DENY\"/>\n            </Filters>\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n    </Appenders>\n    <Loggers>\n        <root level=\"INFO\">\n            <!--            <appender-ref ref=\"Console\"/>-->\n            <AppenderRef ref=\"esAppender\"/>\n            <AppenderRef ref=\"systemLog\"/>\n            <AppenderRef ref=\"errorLog\"/>\n        </root>\n    </Loggers>\n</Configuration>\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/resources/log4j2-test-env.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Configuration package=\"org.apache.logging.log4j.core,com.didiglobal.knowframework.log.log4j2.appender\">\n    <Properties>\n        <Property name=\"address\" value=\"${spring.logi-job.elasticsearch-address}\"/>\n        <Property name=\"port\" value=\"${spring.logi-job.elasticsearch-port}\"/>\n        <Property name=\"user\" value=\"${spring.logi-job.elasticsearch-user}\"/>\n        <Property name=\"password\" value=\"${spring.logi-job.elasticsearch-password}\"/>\n        <Property name=\"indexName\" value=\"${spring.logi-job.elasticsearch-index-name}\"/>\n        <Property name=\"typeName\" value=\"${spring.logi-job.elasticsearch-type-name}\"/>\n        <!-- 基础日志配置 -->\n        <Property name=\"PID\">????</Property>\n        <Property name=\"LOG_EXCEPTION_CONVERSION_WORD\">%xwEx</Property>\n        <Property name=\"LOG_LEVEL_PATTERN\">%5p</Property>\n        <Property name=\"LOG_DATEFORMAT_PATTERN\">yyyy-MM-dd HH:mm:ss.SSS</Property>\n        <Property name=\"CONSOLE_LOG_PATTERN\">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>\n        <Property name=\"log_pattern\">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>\n        <!-- name的值是变量的名称，value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后，可以使\"${}\"来使用变量。 -->\n        <property name=\"log.path\">./logs/</property>\n    </Properties>\n    <Appenders>\n        <Console name=\"Console\" target=\"SYSTEM_OUT\"/>\n        <ElasticsearchAppender name=\"esAppender\" address=\"${address}\" port=\"${port}\" user=\"${user}\"\n                               password=\"${password}\" indexName=\"${indexName}\" typeName=\"${typeName}\" threshold=\"all\"\n                               bufferSize=\"10000\" numberOfShards=\"5\" numberOfReplicas=\"0\" logExpire=\"3\"\n                               extendsMappingClass=\"\" requestTimeoutMillis=\"3000\" discardWhenBufferIsFull=\"true\">\n            <Filters>\n                <!--配置日志表达式，-->\n                <!-- 开启所有日志-->\n                <!--                <RegexFilter regex='.*\"logEventType\":\"(LOG|METRIC|TRACE)\".*' onMatch=\"ACCEPT\" onMismatch=\"DENY\"/>-->\n                <!-- 仅开启LOG和METRIC-->\n                <!-- <RegexFilter regex='.*\"logEventType\":\"(LOG|METRIC)\".*' onMatch=\"ACCEPT\" onMismatch=\"DENY\"/> -->\n                <!-- 开启LOG和METRIC，TRACE日志仅当traceId不为空时打印-->\n                <!--            <RegexFilter regex='.*\"logEventType\":\"(LOG|METRIC)\".*' onMatch=\"ACCEPT\" onMismatch=\"NEUTRAL\"/>-->\n                <!--            <RegexFilter regex='.*\"logEventType\":\"TRACE\".*' onMatch=\"NEUTRAL\" onMismatch=\"DENY\"/>-->\n                <!--            <RegexFilter regex='.*\"traceId\":\"[a-z0-9]+\".*' onMatch=\"NEUTRAL\" onMismatch=\"DENY\"/>-->\n            </Filters>\n        </ElasticsearchAppender>\n        <RollingFile name=\"systemLog\"\n                     filename=\"${log.path}/system.log\" filePattern=\"${log.path}/system.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Filters>\n                <!-- 只要level及其以上级别的信息（onMatch），其他的直接拒绝（onMismatch）-->\n                <ThresholdFilter level=\"INFO\" onMatch=\"ACCEPT\" onMismatch=\"DENY\"/>\n            </Filters>\n\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"1\">\n                <!-- 配置日志滚动删除策略 IfLastModified 的单位需要配合 filePattern中的规则使用 -->\n                <Delete basePath=\"${log.path}\" maxDepth=\"1\">\n                    <IfFileName glob=\"*.log.*\"/>\n                    <IfLastModified age=\"3d\"/>\n                </Delete>\n            </DefaultRolloverStrategy>\n        </RollingFile>\n\n        <RollingFile name=\"errorLog\"\n                     filename=\"${log.path}/error.log\" filePattern=\"${log.path}/error.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Filters>\n                <!-- 只要level及其以上级别的信息（onMatch），其他的直接拒绝（onMismatch）-->\n                <ThresholdFilter level=\"ERROR\" onMatch=\"ACCEPT\" onMismatch=\"DENY\"/>\n            </Filters>\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n    </Appenders>\n    <Loggers>\n        <root level=\"INFO\">\n            <!--            <appender-ref ref=\"Console\"/>-->\n            <AppenderRef ref=\"esAppender\"/>\n            <AppenderRef ref=\"systemLog\"/>\n            <AppenderRef ref=\"errorLog\"/>\n        </root>\n    </Loggers>\n</Configuration>\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/main/resources/observability.properties",
    "content": "application.name=arius-admin\nmetric.export.interval.ms=60000\nobservability.initializer.classes=com.didiglobal.knowframework.log.log4j2.appender.ElasticsearchAppenderMetricsInitializer\n# ???????exporter?LoggingMetricExporter,LoggingSpanExporter\nobservability.exporter.names=LoggingMetricExporter,LoggingSpanExporter\npointcut=execution(* com.didiglobal..*.*(..)) || execution(* com.didichuxing..*.*(..))"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ClusterNodeManagerImplTest.java",
    "content": "\npackage com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport static com.didichuxing.datachannel.arius.admin.util.CustomDataSource.*;\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.when;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.context.SpringBootTest.WebEnvironment;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.impl.ClusterNodeManagerImpl;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\n\n@ActiveProfiles(\"test\")\n@ExtendWith({ SpringExtension.class, MockitoExtension.class })\n@MockitoSettings(strictness = Strictness.LENIENT)\n@RunWith(SpringRunner.class)\n@ContextConfiguration(classes = { SpringTool.class })\n@SpringBootTest(webEnvironment = WebEnvironment.NONE)\nclass ClusterNodeManagerImplTest {\n\n    @Mock\n    private ClusterRoleHostService clusterRoleHostService;\n    @Mock\n    private ClusterPhyService      clusterPhyService;\n    @Mock\n    private ESClusterNodeService   esClusterNodeService;\n\n    @InjectMocks\n    private ClusterNodeManagerImpl clusterNodeManager;\n\n    @Test\n    void listClusterPhyInstanceTest() {\n        when(clusterPhyService.getClusterById(0)).thenReturn(getClusterPhy());\n\n        when(clusterRoleHostService.getNodesByCluster(Mockito.any()))\n            .thenReturn(Collections.singletonList(getClusterRoleHost()));\n\n        when(esClusterNodeService.syncGetNodesDiskUsage(PHY_CLUSTER_NAME)).thenReturn(new HashMap<>());\n\n        final Result<List<ESClusterRoleHostVO>> result = clusterNodeManager.listClusterPhyNode(0);\n\n        assertThat(result).isEqualTo(Result.buildSucc(Collections.singletonList(getESClusterRoleHostVO())));\n    }\n\n    @Test\n    void listClusterPhyInstanceClusterRoleHostServiceReturnsNoItemsTest() {\n        when(clusterPhyService.getClusterById(0)).thenReturn(getClusterPhy());\n\n        when(clusterRoleHostService.getNodesByCluster(Mockito.any())).thenReturn(Collections.emptyList());\n        when(esClusterNodeService.syncGetNodesDiskUsage(PHY_CLUSTER_NAME)).thenReturn(new HashMap<>());\n\n        final Result<List<ESClusterRoleHostVO>> result = clusterNodeManager.listClusterPhyNode(0);\n\n        assertThat(result).isEqualTo(Result.buildSucc(Collections.emptyList()));\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/biz/cluster/ClusterPhyManagerTest.java",
    "content": "\npackage com.didichuxing.datachannel.arius.admin.biz.cluster;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.openMocks;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.impl.ClusterPhyManagerImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplatePhyManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.mapping.TemplatePhyMappingManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.pipeline.PipelineManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterJoinDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleHostDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.PluginDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.setting.ESClusterGetSettingsAllResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ClusterPhyVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterConnectionStatus;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterHealthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESOpClient;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.google.common.collect.Lists;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport org.apache.commons.beanutils.BeanUtils;\nimport org.elasticsearch.common.unit.ByteSizeUnit;\nimport org.elasticsearch.common.unit.ByteSizeValue;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@ActiveProfiles(\"test\")\n@ExtendWith({ SpringExtension.class })\n@RunWith(SpringRunner.class)\n@ContextConfiguration(classes = { SpringTool.class })\n@SpringBootTest\nclass ClusterPhyManagerTest {\n\n    public static final String            CLUSTER           = \"clusterPhyName\";\n    public static final String            TEMPLATE          = \"template\";\n    public static final String            EXPRESSION        = \"expression\";\n    public static final String            DATE_FORMAT       = \"yyyy-MM-dd\";\n\n    public static final int               LOGIC_TEMPLATE_ID = 0;\n    public static final long              PHYSICAL_ID       = 0L;\n    @Mock\n    private ESTemplateService             mockEsTemplateService;\n    @Mock\n    private ClusterPhyService             mockClusterPhyService;\n    @Mock\n    private ClusterLogicService           mockClusterLogicService;\n    @Mock\n    private ClusterRoleService            mockClusterRoleService;\n    @Mock\n    private ClusterRoleHostService        mockClusterRoleHostService;\n    @Mock\n    private IndexTemplatePhyService       mockIndexTemplatePhyService;\n    @Mock\n    private TemplatePhyMappingManager     mockTemplatePhyMappingManager;\n    @Mock\n    private PipelineManager               mockTemplatePipelineManager;\n    @Mock\n    private IndexTemplateService          mockIndexTemplateService;\n    @Mock\n    private TemplatePhyManager            mockTemplatePhyManager;\n    @Mock\n    private ClusterRegionService          mockClusterRegionService;\n    @Mock\n    private ClusterContextManager         mockClusterContextManager;\n    @Mock\n    private ProjectService                mockAppService;\n    @Mock\n    private OperateRecordService          mockOperateRecordService;\n    @Mock\n    private ESClusterNodeService          mockEsClusterNodeService;\n    @Mock\n    private ESClusterService              mockEsClusterService;\n    @Mock\n    private ESOpClient                    mockEsOpClient;\n\n    @InjectMocks\n    private ClusterPhyManagerImpl         clusterPhyManager;\n\n    private IndexTemplate                 indexTemplate;\n    private IndexTemplatePhy              indexTemplatePhy;\n    private List<IndexTemplatePhy>        indexTemplatePhyList;\n    private IndexTemplateWithPhyTemplates indexTemplateWithPhyTemplates;\n    private ClusterPhyDTO                 clusterPhyDTO;\n    ESConfigDTO                           esConfigDTO;\n    PluginDTO                             pluginDTO;\n    ESClusterRoleDTO                      esClusterRoleDTO;\n    ESClusterRoleHostDTO                  esClusterRoleHostDTO;\n    ClusterPhyVO                          clusterPhyVO;\n    ClusterPhyVO                          clusterPhyVOWithNotRole;\n    ClusterRoleHost                       clusterRoleHost;\n    ClusterRoleInfo                       clusterRoleInfo;\n\n    List<ClusterPhy>                      clusterPhyList;\n    ESClusterStatsResponse                esClusterStatsResponse;\n    List<ClusterRoleInfo>                 clusterRoleInfos;\n    ClusterPhy                            clusterPhy;\n    ClusterPhy                            privateClusterPhy;\n    ClusterPhy                            exclusiveClusterPhy;\n    ClusterLogic                          clusterLogic;\n    ClusterRegion                         region;\n    List<ClusterRoleHost>                 roleHostList;\n    List<ClusterRegion>                   regions;\n\n    @BeforeEach\n    void setUp() {\n        openMocks(this);\n        indexTemplate = new IndexTemplate(LOGIC_TEMPLATE_ID, \"name\", 0, 0, DATE_FORMAT, \"dataCenter\", 0, 0, 0,\n           \"dateField\", \"dateFieldFormat\", \"idField\",\n            \"routingField\", EXPRESSION, 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0,\n            0.0,1);\n        indexTemplatePhy = new IndexTemplatePhy(PHYSICAL_ID, 0, TEMPLATE, EXPRESSION, CLUSTER, \"rack\", 0, 0, 0, 1, 0,\n            \"config\", 0);\n        indexTemplatePhyList = Collections.singletonList(indexTemplatePhy);\n        indexTemplateWithPhyTemplates = new IndexTemplateWithPhyTemplates(indexTemplatePhyList);\n        esConfigDTO = new ESConfigDTO(0L, 0L, \"typeName\", \"enginName\", \"configData\", \"desc\", \"versionTag\", 0, 0);\n        pluginDTO = new PluginDTO(0L, \"name\", \"physicClusterId\", \"version\", \"url\", \"md5\", \"desc\", \"creator\", 0,\n            \"fileName\", null);\n        esClusterRoleDTO = new ESClusterRoleDTO(0L, 0L, \"roleClusterName\", \"role\", 0, 0, \"machineSpec\", \"esVersion\", 0,\n            \"plugIds\", false);\n        esClusterRoleHostDTO = new ESClusterRoleHostDTO(0L, 0L, \"hostname\", \"ip\", CLUSTER, \"port\", false, 0, 0,\n            \"nodeSet\", 0, \"attributes\", \"16c-32g-1t\");\n        clusterPhyDTO = new ClusterPhyDTO(0, CLUSTER, \"desc\", \"readAddress\", \"writeAddress\", \"httpAddress\",\n            \"httpAddress\", 0, \"tags\", \"code\", \"idc\", 0, \"esVersion\", \"imageName\", \"nsTree\", \"plugIds\", 0L, esConfigDTO,\n            Collections.singletonList(pluginDTO), Collections.singletonList(esClusterRoleDTO),\n            Collections.singletonList(esClusterRoleHostDTO), 0, \"machineSpec\", \"operator\",  \"password\",\n            0, \"writeAction\", 0, 0L, 0L, 0L, 0.0, \"platformType\", 0, \"gatewayUrl\",\"\",\"\",\"\",false,-1);\n\n        clusterPhyVO = new ClusterPhyVO(0, CLUSTER, \"desc\", \"readAddress\", \"writeAddress\", \"httpAddress\",\n            \"httpWriteAddress\", 0, \"tags\", \"dataCenter\", 0, \"machineSpec\", 0, \"esVersion\", \"imageName\", null,\n            Collections.singletonList(\n                new ESClusterRoleVO(0L, 0L, \"roleClusterName\", \"role\", 0, 0, \"machineSpec\", Lists.newArrayList())),\n            0.0, 0L, 0L, \"password\", \"idc\", 0, \"writeAction\", 0, 0L, \"platformType\", 0, \"gatewayUrl\",null,null ,null,null,null,null);\n\n        clusterRoleHost = new ClusterRoleHost(0L, 0L, \"hostname\", \"ip\", CLUSTER, \"port\", 0, 0, \"rack\", \"nodeSet\",\n            \"machineSpec\", 0, \"attributes\");\n        clusterRoleInfo = new ClusterRoleInfo(0L, 0L, \"roleClusterName\", \"role\", 0, 0, \"machineSpec\", \"esVersion\", 0,\n            \"plugIds\", false, Collections.singletonList(clusterRoleHost));\n        clusterPhy = new ClusterPhy(0, CLUSTER, \"desc\", \"readAddress\", \"writeAddress\", \"httpAddress\",\n            \"httpWriteAddress\", 0, \"tags\", \"dataCenter\", \"idc\", 0, \"esVersion\", 0L, \"plugIds\", 0L, \"imageName\",\n            \"nsTree\", 0, \"machineSpec\", \"password\", \"creator\",\n            Collections.singletonList(clusterRoleInfo), Collections.singletonList(clusterRoleHost), 0, \"writeAction\", 0,\n            0L, 0L, 0L, 0.0, \"platformType\", 1, \"gatewayUrl\",null,null,null);\n        privateClusterPhy = new ClusterPhy(0, CLUSTER, \"desc\", \"readAddress\", \"writeAddress\", \"httpAddress\",\n            \"httpWriteAddress\", 0, \"tags\", \"dataCenter\", \"idc\", 0, \"esVersion\", 0L, \"plugIds\", 0L, \"imageName\",\n            \"nsTree\", 0, \"machineSpec\", \"password\", \"creator\",\n            Collections.singletonList(clusterRoleInfo), Collections.singletonList(clusterRoleHost), 0, \"writeAction\", 0,\n            0L, 0L, 0L, 0.0, \"platformType\", 1, \"gatewayUrl\",null,null,null);\n        exclusiveClusterPhy = new ClusterPhy(0, CLUSTER, \"desc\", \"readAddress\", \"writeAddress\", \"httpAddress\",\n            \"httpWriteAddress\", 0, \"tags\", \"dataCenter\", \"idc\", 0, \"esVersion\", 0L, \"plugIds\", 0L, \"imageName\",\n            \"nsTree\", 0, \"machineSpec\", \"password\", \"creator\",\n            Collections.singletonList(clusterRoleInfo), Collections.singletonList(clusterRoleHost), 0, \"writeAction\", 0,\n            0L, 0L, 0L, 0.0, \"platformType\", 1, \"gatewayUrl\",null,null,null);\n        clusterPhyList = Collections.singletonList(clusterPhy);\n        esClusterStatsResponse = new ESClusterStatsResponse(\"status\", 0L, 0L, 0L,new ByteSizeValue(0L, ByteSizeUnit.BYTES), 0L, 0L, 0L, 0L, 0L, 0L,0L, 0L,\n            new ByteSizeValue(0L, ByteSizeUnit.BYTES), new ByteSizeValue(0L, ByteSizeUnit.BYTES),\n            new ByteSizeValue(0L, ByteSizeUnit.BYTES), 0L, 0L, new ByteSizeValue(0L, ByteSizeUnit.BYTES),\n            new ByteSizeValue(0L, ByteSizeUnit.BYTES), new ByteSizeValue(0L, ByteSizeUnit.BYTES),\n            new ByteSizeValue(0L, ByteSizeUnit.BYTES));\n        clusterRoleInfos = Collections.singletonList(clusterRoleInfo);\n        clusterPhyVOWithNotRole = new ClusterPhyVO(0, CLUSTER, \"desc\", \"readAddress\", \"writeAddress\", \"httpAddress\",\n            \"httpWriteAddress\", 0, \"tags\", \"dataCenter\", 0, \"machineSpec\", 0, \"esVersion\", \"imageName\", null,\n            Lists.newArrayList(), 0.0, 0L, 0L, \"password\", \"idc\", 0, \"writeAction\", 0, 0L, \"platformType\", 1,\n            \"gatewayUrl\", null,null,null,null,null,null);\n\n        clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0,\n           \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        region = new ClusterRegion(0L, \"name\", \"logicClusterIds\", CLUSTER, \"config\");\n\n        roleHostList = Collections.singletonList(new ClusterRoleHost(0L, 0L, \"hostname\", \"ip\", CLUSTER, \"port\", 0, 0,\n            \"rack\", \"nodeSet\", \"machineSpec\", -1, \"attributes\"));\n        regions = Collections.singletonList(region);\n    }\n\n    @Test\n    void testCopyMapping() throws Exception {\n        final Result<MappingConfig> succ = Result.buildSucc(new MappingConfig(new JSONObject(0, false)));\n        final Result<MappingConfig> fail = Result.buildFail();\n        when(mockIndexTemplatePhyService.getNormalTemplateByCluster(CLUSTER)).thenReturn(indexTemplatePhyList);\n        when(mockIndexTemplateService.getLogicTemplateById(0)).thenReturn(indexTemplate);\n        when(mockTemplatePhyMappingManager.syncMappingConfig(CLUSTER, TEMPLATE, EXPRESSION, DATE_FORMAT))\n            .thenReturn(succ);\n        when(mockEsTemplateService.syncUpsertSetting(CLUSTER, TEMPLATE, new HashMap<>(), 0)).thenReturn(false);\n        assertTrue(clusterPhyManager.copyMapping(CLUSTER, 0));\n\n        when(mockTemplatePhyMappingManager.syncMappingConfig(CLUSTER, TEMPLATE, EXPRESSION, DATE_FORMAT))\n            .thenReturn(fail);\n        when(mockEsTemplateService.syncUpsertSetting(CLUSTER, TEMPLATE, new HashMap<>(), 0)).thenReturn(false);\n        assertFalse(clusterPhyManager.copyMapping(CLUSTER, 0));\n\n        when(mockIndexTemplatePhyService.getNormalTemplateByCluster(CLUSTER)).thenReturn(Collections.emptyList());\n        assertTrue(clusterPhyManager.copyMapping(CLUSTER, 0));\n\n        when(mockTemplatePhyMappingManager.syncMappingConfig(CLUSTER, TEMPLATE, EXPRESSION, DATE_FORMAT))\n            .thenThrow(RuntimeException.class);\n        assertTrue(clusterPhyManager.copyMapping(CLUSTER, 0));\n    }\n\n    @Test\n    void testSyncTemplateMetaData() throws Exception {\n        when(mockIndexTemplatePhyService.getNormalTemplateByCluster(CLUSTER)).thenReturn(indexTemplatePhyList);\n        when(mockIndexTemplateService.getLogicTemplateWithPhysicalsById(LOGIC_TEMPLATE_ID))\n            .thenReturn(indexTemplateWithPhyTemplates);\n\n        clusterPhyManager.syncTemplateMetaData(CLUSTER, 0);\n\n        verify(mockTemplatePhyManager).syncMeta(PHYSICAL_ID, 0);\n    }\n\n    @Test\n    void testSyncTemplateMetaData_IndexTemplatePhyServiceReturnsNoItems() throws ESOperateException {\n        when(mockIndexTemplatePhyService.getNormalTemplateByCluster(CLUSTER)).thenReturn(Collections.emptyList());\n        when(mockIndexTemplateService.getLogicTemplateWithPhysicalsById(LOGIC_TEMPLATE_ID))\n            .thenReturn(indexTemplateWithPhyTemplates);\n\n        clusterPhyManager.syncTemplateMetaData(CLUSTER, 0);\n\n        verify(mockTemplatePhyManager, times(0)).syncMeta(PHYSICAL_ID, 0);\n\n    }\n\n    @Test\n    void testSyncTemplateMetaData_TemplatePhyManagerThrowsESOperateException() throws Exception {\n        when(mockIndexTemplatePhyService.getNormalTemplateByCluster(CLUSTER)).thenReturn(indexTemplatePhyList);\n\n        doThrow(ESOperateException.class).when(mockTemplatePhyManager).syncMeta(PHYSICAL_ID, 0);\n\n        clusterPhyManager.syncTemplateMetaData(CLUSTER, 0);\n    }\n\n    @Test\n    void testIsClusterExists() {\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(false);\n\n        final boolean result = clusterPhyManager.isClusterExists(CLUSTER);\n\n        assertFalse(result);\n    }\n\n    @Test\n    void testGetClusterPhys() throws InvocationTargetException, IllegalAccessException {\n\n        when(mockClusterPhyService.listClustersByCondt(clusterPhyDTO)).thenReturn(clusterPhyList);\n\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(false);\n\n        when(mockEsClusterService.syncGetClusterStats(CLUSTER)).thenReturn(esClusterStatsResponse);\n\n        when(mockClusterRoleService.getAllRoleClusterByClusterId(0)).thenReturn(clusterRoleInfos);\n\n        when(mockClusterRoleHostService.getByRoleClusterIds(Collections.singletonList(0L))).thenReturn(new HashMap<>());\n\n        final List<ClusterPhyVO> result = clusterPhyManager.listClusterPhys(clusterPhyDTO);\n        ClusterPhyVO vo = new ClusterPhyVO();\n        BeanUtils.copyProperties(vo, clusterPhyVO);\n        vo.setResourceType(1);\n        assertEquals(Collections.singletonList(vo), result);\n    }\n\n    @Test\n    void testGetClusterPhys_ClusterPhyServiceGetClustersByCondtReturnsNoItems() {\n\n        when(mockClusterPhyService.listClustersByCondt(clusterPhyDTO)).thenReturn(Collections.emptyList());\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(false);\n\n        when(mockEsClusterService.syncGetClusterStats(CLUSTER)).thenReturn(esClusterStatsResponse);\n        when(mockClusterRoleService.getAllRoleClusterByClusterId(0)).thenReturn(clusterRoleInfos);\n\n        when(mockClusterRoleHostService.getByRoleClusterIds(Collections.singletonList(0L))).thenReturn(new HashMap<>());\n\n        final List<ClusterPhyVO> result = clusterPhyManager.listClusterPhys(clusterPhyDTO);\n\n        assertEquals(Collections.emptyList(), result);\n    }\n\n    @Test\n    void testGetClusterPhys_ESClusterServiceReturnsNull() throws InvocationTargetException, IllegalAccessException {\n        // Setup\n        when(mockClusterPhyService.listClustersByCondt(clusterPhyDTO)).thenReturn(clusterPhyList);\n\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(false);\n        when(mockEsClusterService.syncGetClusterStats(CLUSTER)).thenReturn(null);\n\n        when(mockClusterRoleService.getAllRoleClusterByClusterId(0)).thenReturn(clusterRoleInfos);\n\n        when(mockClusterRoleHostService.getByRoleClusterIds(Collections.singletonList(0L))).thenReturn(new HashMap<>());\n\n        final List<ClusterPhyVO> result = clusterPhyManager.listClusterPhys(clusterPhyDTO);\n        ClusterPhyVO vo = new ClusterPhyVO();\n        BeanUtils.copyProperties(vo, clusterPhyVO);\n        vo.setResourceType(1);\n        assertEquals(Collections.singletonList(vo), result);\n    }\n\n    @Test\n    void testGetClusterPhys_ClusterRoleServiceReturnsNoItems() {\n        when(mockClusterPhyService.listClustersByCondt(clusterPhyDTO)).thenReturn(clusterPhyList);\n\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(false);\n\n        when(mockEsClusterService.syncGetClusterStats(CLUSTER)).thenReturn(esClusterStatsResponse);\n\n        when(mockClusterRoleService.getAllRoleClusterByClusterId(0)).thenReturn(Collections.emptyList());\n        when(mockClusterRoleHostService.getByRoleClusterIds(Collections.singletonList(0L))).thenReturn(new HashMap<>());\n\n        final List<ClusterPhyVO> result = clusterPhyManager.listClusterPhys(clusterPhyDTO);\n\n        assertEquals(Collections.singletonList(clusterPhyVOWithNotRole), result);\n    }\n\n    @Test\n    void testBuildClusterInfo() {\n        assertEquals(Collections.emptyList(), clusterPhyManager.buildClusterInfo(Collections.emptyList()));\n\n        when(mockClusterRoleService.getAllRoleClusterByClusterIds(Collections.singletonList(0)))\n            .thenReturn(new HashMap<>());\n        when(mockClusterRoleHostService.getByRoleClusterIds(Collections.singletonList(0L))).thenReturn(new HashMap<>());\n        assertEquals(Collections.singletonList(clusterPhyVOWithNotRole),\n            clusterPhyManager.buildClusterInfo(clusterPhyList));\n    }\n\n    @Test\n    void testGetClusterPhyOverview() throws InvocationTargetException, IllegalAccessException {\n        when(mockClusterPhyService.getClusterById(0)).thenReturn(clusterPhy);\n\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(false);\n\n        when(mockEsClusterService.syncGetClusterStats(CLUSTER)).thenReturn(esClusterStatsResponse);\n\n        when(mockClusterRoleService.getAllRoleClusterByClusterId(0)).thenReturn(clusterRoleInfos);\n\n        when(mockClusterRoleHostService.getByRoleClusterIds(Collections.singletonList(0L))).thenReturn(new HashMap<>());\n\n        final ClusterPhyVO result = clusterPhyManager.getClusterPhyOverview(0, 0);\n        ClusterPhyVO vo = new ClusterPhyVO();\n        BeanUtils.copyProperties(vo, clusterPhyVO);\n        vo.setResourceType(1);\n        assertEquals(vo, result);\n    }\n\n    @Test\n    void testGetClusterPhyOverview_ClusterPhyServiceGetClusterByIdReturnsNull() {\n        when(mockClusterPhyService.getClusterById(0)).thenReturn(null);\n\n        final ClusterPhyVO result = clusterPhyManager.getClusterPhyOverview(0, 0);\n\n        assertEquals(new ClusterPhyVO(), result);\n    }\n\n    @Test\n    void testGetClusterPhyOverview_ESClusterServiceReturnsNull() throws InvocationTargetException,\n                                                                 IllegalAccessException {\n        when(mockClusterPhyService.getClusterById(0)).thenReturn(clusterPhy);\n\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(false);\n        when(mockEsClusterService.syncGetClusterStats(CLUSTER)).thenReturn(null);\n\n        when(mockClusterRoleService.getAllRoleClusterByClusterId(0)).thenReturn(clusterRoleInfos);\n\n        when(mockClusterRoleHostService.getByRoleClusterIds(Arrays.asList(0L))).thenReturn(new HashMap<>());\n\n        final ClusterPhyVO result = clusterPhyManager.getClusterPhyOverview(0, 0);\n        ClusterPhyVO vo = new ClusterPhyVO();\n        BeanUtils.copyProperties(vo, clusterPhyVO);\n        vo.setResourceType(1);\n        assertEquals(vo, result);\n    }\n\n    @Test\n    void testGetClusterPhyOverview_ClusterRoleServiceReturnsNoItems() {\n        when(mockClusterPhyService.getClusterById(0)).thenReturn(clusterPhy);\n\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(false);\n\n        when(mockEsClusterService.syncGetClusterStats(CLUSTER)).thenReturn(esClusterStatsResponse);\n\n        when(mockClusterRoleService.getAllRoleClusterByClusterId(0)).thenReturn(Collections.emptyList());\n        when(mockClusterRoleHostService.getByRoleClusterIds(Collections.singletonList(0L))).thenReturn(new HashMap<>());\n\n        final ClusterPhyVO result = clusterPhyManager.getClusterPhyOverview(0, 0);\n\n        assertEquals(clusterPhyVOWithNotRole, result);\n    }\n\n    @Test\n    void testListCanBeAssociatedRegionOfClustersPhys() {\n\n        Result<List<String>> result = clusterPhyManager.listCanBeAssociatedRegionOfClustersPhys(0, 0L);\n        assertEquals(Result.buildParamIllegal(\"集群资源类型非法\").getMessage(), result.getMessage());\n\n        when(mockClusterLogicService.getClusterLogicByIdAndProjectId(0L, null)).thenReturn(clusterLogic);\n        when(mockClusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(region);\n        result = clusterPhyManager.listCanBeAssociatedRegionOfClustersPhys(1, 0L);\n        assertEquals(Collections.emptyList(), result.getData());\n\n        List<String> clusterNames = Collections.singletonList(CLUSTER);\n        when(mockClusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(null);\n        ClusterPhyDTO clusterPhyDTO = new ClusterPhyDTO();\n        clusterPhyDTO.setResourceType(1);\n        when(mockClusterPhyService.listClustersByCondt(clusterPhyDTO)).thenReturn(clusterPhyList);\n        result = clusterPhyManager.listCanBeAssociatedRegionOfClustersPhys(1, 0L);\n        assertEquals(clusterNames, result.getData());\n    }\n\n    @Test\n    void testListCanBeAssociatedClustersPhys() {\n        Result<List<String>> result = clusterPhyManager.listCanBeAssociatedClustersPhys(0);\n        assertEquals(Result.buildParamIllegal(\"集群资源类型非法\").getMessage(), result.getMessage());\n\n        List<String> clusterNames = Collections.singletonList(CLUSTER);\n        when(mockClusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(null);\n        ClusterPhyDTO clusterPhyDTO = new ClusterPhyDTO();\n        clusterPhyDTO.setResourceType(1);\n        when(mockClusterPhyService.listClustersByCondt(clusterPhyDTO)).thenReturn(clusterPhyList);\n        result = clusterPhyManager.listCanBeAssociatedClustersPhys(1);\n        assertEquals(clusterNames, result.getData());\n\n        when(mockClusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(null);\n        clusterPhyDTO = new ClusterPhyDTO();\n        clusterPhyDTO.setResourceType(3);\n        when(mockClusterPhyService.listClustersByCondt(clusterPhyDTO))\n            .thenReturn(Collections.singletonList(privateClusterPhy));\n        when(mockClusterRegionService.listPhyClusterRegions(CLUSTER)).thenReturn(regions);\n        when(mockClusterRegionService.isRegionBound(region)).thenReturn(false);\n        result = clusterPhyManager.listCanBeAssociatedClustersPhys(3);\n        assertEquals(clusterNames, result.getData());\n\n        when(mockClusterRegionService.isRegionBound(region)).thenReturn(true);\n        when(mockClusterRoleHostService.getByRoleAndClusterId(0L, \"datanode\")).thenReturn(roleHostList);\n        result = clusterPhyManager.listCanBeAssociatedClustersPhys(3);\n        assertEquals(clusterNames, result.getData());\n\n        when(mockClusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(null);\n        clusterPhyDTO = new ClusterPhyDTO();\n        clusterPhyDTO.setResourceType(2);\n        when(mockClusterPhyService.listClustersByCondt(clusterPhyDTO))\n            .thenReturn(Collections.singletonList(exclusiveClusterPhy));\n        when(mockClusterRegionService.getLogicClusterIdByPhyClusterId(0)).thenReturn(new HashSet<>());\n        result = clusterPhyManager.listCanBeAssociatedClustersPhys(2);\n        assertEquals(clusterNames, result.getData());\n    }\n\n    @Test\n    void testJoinCluster() throws InvocationTargetException, IllegalAccessException, AdminTaskException, ESOperateException {\n        Integer projectId = 1;\n        ClusterJoinDTO param = new ClusterJoinDTO(0, 0, \"clusterPhyName\", \"esVersion\", Lists.newArrayList(),\n                \"desc\", \"passwd\", 4, \"{\\\"createSource\\\":1}\", \"cn\", \"acs\", 1,null,null,null,null,null);\n        ESClusterRoleHostDTO roleHostDTO = new ESClusterRoleHostDTO(0L, 0L, \"hostname\", \"\", CLUSTER, \"port\", false, 0,\n            0, \"nodeSet\", 0, \"attributes\", \"16c-32g-1t\");\n        assertEquals(Result.buildParamIllegal(\"参数为空\").getMessage(),\n            clusterPhyManager.joinCluster(null, \"admin\", projectId).getMessage());\n        assertEquals(Result.buildParamIllegal(\"操作人不存在\").getMessage(),\n            clusterPhyManager.joinCluster(param, null, projectId).getMessage());\n        assertEquals(Result.buildParamIllegal(\"非支持的集群类型\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n        param.setType(4);\n        param.setResourceType(0);\n        assertEquals(Result.buildParamIllegal(\"非支持的集群资源类型\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n        param.setResourceType(1);\n        assertEquals(Result.buildParamIllegal(\"非集群接入来源\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n        param.setTags(\"{\\\"createSource\\\":0}\");\n        assertEquals(Result.buildParamIllegal(\"非支持的接入规则\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n        param.setImportRule(1);\n        assertEquals(Result.buildParamIllegal(\"集群节点信息为空\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n        param.setRoleClusterHosts(Collections.singletonList(roleHostDTO));\n        assertEquals(Result.buildParamIllegal(\"接入集群中端口号存在异常[port]\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n        roleHostDTO.setPort(\"997\");\n        param.setRoleClusterHosts(Collections.singletonList(roleHostDTO));\n        assertEquals(Result.buildParamIllegal(\"集群缺少类型为masternode的节点\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n        roleHostDTO.setRole(3);\n        roleHostDTO.setIp(\"127.0.0.1\");\n        ESClusterRoleHostDTO clientNode = new ESClusterRoleHostDTO();\n        BeanUtils.copyProperties(clientNode, roleHostDTO);\n        clientNode.setRole(2);\n        ESClusterRoleHostDTO dataNode = new ESClusterRoleHostDTO();\n        BeanUtils.copyProperties(dataNode, roleHostDTO);\n        dataNode.setRole(1);\n        param.setRoleClusterHosts(Arrays.asList(roleHostDTO, roleHostDTO, clientNode, clientNode, dataNode, dataNode));\n        assertEquals(Result.buildParamIllegal(\"集群ip:127.0.0.1重复, 请重新输入\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n        param.setRoleClusterHosts(Arrays.asList(roleHostDTO, clientNode, clientNode, dataNode, dataNode));\n        assertEquals(Result.buildParamIllegal(\"集群ip:127.0.0.1重复, 请重新输入\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n        param.setRoleClusterHosts(Arrays.asList(roleHostDTO, clientNode, dataNode, dataNode));\n        assertEquals(Result.buildParamIllegal(\"集群ip:127.0.0.1重复, 请重新输入\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n\n        param.setImportRule(0);\n        roleHostDTO.setIp(\"\");\n        param.setRoleClusterHosts(Arrays.asList(roleHostDTO, roleHostDTO, roleHostDTO));\n        assertEquals(Result.buildParamIllegal(String.format(\"集群%s的节点个数要求大于等于1，且不重复\", param.getCluster())).getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n        roleHostDTO.setIp(\"127.0.0.1\");\n        param.setRoleClusterHosts(Arrays.asList(roleHostDTO, clientNode, dataNode));\n        assertEquals(Result.buildParamIllegal(\"集群ip:127.0.0.1重复, 请重新输入\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n\n        param.setRoleClusterHosts(Collections.singletonList(roleHostDTO));\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(true);\n        assertEquals(Result.buildParamIllegal(String.format(\"物理集群名称:%s已存在\", param.getCluster())).getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(false);\n        when(mockClusterRoleHostService.buildESClientHttpAddressesStr(Mockito.anyList()))\n            .thenReturn(\"esClientHttpAddressesStr\");\n        when(mockEsClusterService.checkClusterPassword(\"esClientHttpAddressesStr\", null))\n            .thenReturn(ClusterConnectionStatus.DISCONNECTED);\n        assertEquals(Result.buildParamIllegal(\"集群离线未能连通\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n\n        when(mockEsClusterService.checkClusterPassword(\"esClientHttpAddressesStr\", null))\n            .thenReturn(ClusterConnectionStatus.NORMAL);\n        assertEquals(Result.buildParamIllegal(\"未设置密码的集群，请勿输入账户信息\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n\n        when(mockEsClusterService.checkClusterPassword(\"esClientHttpAddressesStr\", null))\n            .thenReturn(ClusterConnectionStatus.UNAUTHORIZED);\n        when(mockEsClusterService.checkClusterPassword(\"esClientHttpAddressesStr\", \"passwd\"))\n            .thenReturn(ClusterConnectionStatus.UNAUTHORIZED);\n        assertEquals(Result.buildParamIllegal(\"集群的账户信息错误\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n\n        param.setPassword(null);\n        assertEquals(Result.buildParamIllegal(\"集群设置有密码，请输入账户信息\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n\n        when(mockEsClusterService.checkClusterPassword(\"esClientHttpAddressesStr\", null))\n            .thenReturn(ClusterConnectionStatus.NORMAL);\n        when(mockClusterRoleHostService.buildESAllRoleHttpAddressesList(Mockito.anyList()))\n            .thenReturn(Lists.newArrayList(\"esClientHttpAddressesStr\"));\n        when(mockEsClusterService.checkSameCluster(Mockito.any(), Mockito.any())).thenReturn(Result.buildFail());\n        assertEquals(Result.buildParamIllegal(\"禁止同时接入超过两个不同集群节点\").getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n\n        when(mockEsClusterService.checkSameCluster(Mockito.any(), Mockito.any())).thenReturn(Result.buildSucc());\n        when(mockEsClusterService.synGetESVersionByHttpAddress(\"esClientHttpAddressesStr\", \"passwd\")).thenReturn(null);\n        when(mockEsClusterService.synGetESVersionByHttpAddress(\"esClientHttpAddressesStr\", null)).thenReturn(null);\n        assertEquals(Result.buildParamIllegal(String.format(\"%s无法获取es版本\", \"esClientHttpAddressesStr\")).getMessage(),\n            clusterPhyManager.joinCluster(param, \"admin\", projectId).getMessage());\n\n        when(mockEsClusterService.synGetESVersionByHttpAddress(\"esClientHttpAddressesStr\", null))\n            .thenReturn(\"7.6.0.1401\");\n        param.setDataCenter(\"\");\n        when(mockClusterRoleHostService.collectClusterNodeSettings(CLUSTER)).thenReturn(true);\n        when(mockClusterPhyService.createCluster(Mockito.any(), Mockito.anyString())).thenReturn(Result.buildSucc());\n        assertTrue(clusterPhyManager.joinCluster(param, \"admin\", projectId).success());\n        verify(mockEsOpClient).connect(CLUSTER);\n        verify(mockClusterRoleHostService).collectClusterNodeSettings(CLUSTER);\n\n        param.setImportRule(1);\n        when(mockClusterPhyService.getClusterByName(CLUSTER)).thenReturn(clusterPhy);\n        when(mockEsClusterService.syncGetClusterHealthEnum(CLUSTER)).thenReturn(ClusterHealthEnum.GREEN);\n\n        when(mockClusterPhyService.editCluster(Mockito.any(), Mockito.anyString())).thenReturn(Result.buildFail(null));\n        assertTrue(clusterPhyManager.joinCluster(param, \"admin\", projectId).success());\n\n        verify(mockClusterRoleHostService).saveClusterNodeSettings(Mockito.any());\n\n    }\n\n    @Test\n    void testDeleteClusterJoin() {\n        final Integer projectId = 1;\n        when(mockClusterPhyService.getClusterById(0)).thenReturn(null);\n        assertEquals(Result.buildParamIllegal(\"物理集群不存在\").getMessage(),\n            clusterPhyManager.deleteClusterJoin(0, \"operator\", projectId).getMessage());\n\n        when(mockClusterPhyService.getClusterById(0)).thenReturn(clusterPhy);\n        when(mockClusterContextManager.getClusterPhyContext(\"clusterPhyName\")).thenReturn(null);\n        assertEquals(Result.buildSucc(), clusterPhyManager.deleteClusterJoin(0, \"operator\", projectId));\n    }\n\n    @Test\n    void testGetPhyClusterDynamicConfigs() throws ESOperateException  {\n        when(mockClusterPhyService.isClusterExists(Mockito.anyString())).thenReturn(false);\n        assertEquals(Result.buildFail(\"集群[\" + CLUSTER + \"]不存在\").getMessage(),\n            clusterPhyManager.getPhyClusterDynamicConfigs(CLUSTER).getMessage());\n\n        when(mockClusterPhyService.isClusterExists(Mockito.anyString())).thenReturn(true);\n        when(mockEsClusterService.syncGetClusterSetting(CLUSTER)).thenReturn(null);\n\n        assertEquals(Result.buildFail(String.format(\"获取集群动态配置信息失败, 请确认是否集群[%s]是否正常\", CLUSTER)).getMessage(),\n            clusterPhyManager.getPhyClusterDynamicConfigs(CLUSTER).getMessage());\n        final ESClusterGetSettingsAllResponse esClusterGetSettingsAllResponse = new ESClusterGetSettingsAllResponse(\n            new JSONObject(0, false));\n        when(mockEsClusterService.syncGetClusterSetting(CLUSTER)).thenReturn(esClusterGetSettingsAllResponse);\n\n        assertTrue(clusterPhyManager.getPhyClusterDynamicConfigs(CLUSTER).success());\n    }\n\n    @Test\n    void testUpdatePhyClusterDynamicConfig() {\n        final ClusterSettingDTO param = new ClusterSettingDTO(\"clusterName\", \"key\", \"value\");\n        final Result<Boolean> expectedResult = Result.buildFail(false);\n        when(mockClusterPhyService.updatePhyClusterDynamicConfig(new ClusterSettingDTO(\"clusterName\", \"key\", \"value\")))\n            .thenReturn(Result.buildFail(false));\n        Integer projectId = 1;\n        final Result<Boolean> result;\n        try {\n            result = clusterPhyManager.updatePhyClusterDynamicConfig(param, \"operator\", projectId);\n        } catch (ESOperateException e) {\n            throw new RuntimeException(e);\n        }\n    \n        assertEquals(expectedResult, result);\n    }\n\n    @Test\n    void testGetAppClusterPhyNames() {\n        when(mockClusterPhyService.listAllClusters()).thenReturn(clusterPhyList);\n        assertEquals(Collections.singletonList(CLUSTER), clusterPhyManager.listClusterPhyNameByProjectId(0));\n    }\n\n    @Test\n    void testGetAppClusterPhyNodeNames() {\n\n        when(mockEsClusterNodeService.syncGetNodeNames(\"clusterPhyName\"))\n            .thenReturn(Collections.singletonList(\"value\"));\n        assertEquals(Collections.singletonList(\"value\"), clusterPhyManager.listClusterPhyNodeName(\"clusterPhyName\"));\n\n        when(mockEsClusterNodeService.syncGetNodeNames(\"clusterPhyName\")).thenReturn(Collections.emptyList());\n        assertEquals(Collections.emptyList(), clusterPhyManager.listClusterPhyNodeName(\"clusterPhyName\"));\n\n        assertEquals(Collections.emptyList(), clusterPhyManager.listClusterPhyNodeName(null));\n    }\n\n    @Test\n    void testDeleteCluster() {\n        final Integer projectId = 1;\n        when(mockClusterPhyService.getClusterById(0)).thenReturn(null);\n        assertEquals(Result.buildFail(String.format(\"物理集群Id[%s]不存在\", 0)),\n            clusterPhyManager.deleteCluster(0, \"operator\", projectId));\n\n        when(mockClusterRegionService.getLogicClusterIdByPhyClusterId(0)).thenReturn(Collections.emptySet());\n        when(mockIndexTemplatePhyService.getNormalTemplateByCluster(CLUSTER)).thenReturn(Collections.emptyList());\n        when(mockClusterPhyService.getClusterById(0)).thenReturn(clusterPhy);\n        when(mockClusterRoleHostService.getNodesByCluster(CLUSTER)).thenReturn(Collections.emptyList());\n        when(mockClusterRoleService.deleteRoleClusterByClusterId(0, projectId)).thenReturn(Result.buildSucc());\n        when(mockClusterRegionService.listPhyClusterRegions(CLUSTER)).thenReturn(Collections.emptyList());\n        when(mockClusterPhyService.deleteClusterById(0, projectId)).thenReturn(Result.buildSucc(true));\n        assertEquals(Result.buildSucc(true), clusterPhyManager.deleteCluster(0, \"operator\", projectId));\n\n        when(mockClusterRoleHostService.getNodesByCluster(CLUSTER)).thenReturn(roleHostList);\n        when(mockClusterRoleHostService.deleteByCluster(CLUSTER, projectId)).thenReturn(Result.buildSucc());\n        when(mockClusterRoleService.deleteRoleClusterByClusterId(0, projectId)).thenReturn(Result.buildSucc());\n\n        when(mockClusterRegionService.listPhyClusterRegions(CLUSTER)).thenReturn(regions);\n        when(mockClusterRegionService.deleteByClusterPhy(CLUSTER)).thenReturn(Result.buildSucc());\n        when(mockClusterPhyService.deleteClusterById(0, projectId)).thenReturn(Result.buildSucc(true));\n        assertEquals(Result.buildSucc(true), clusterPhyManager.deleteCluster(0, \"operator\", projectId));\n    }\n\n    @Test\n    void testAddCluster() {\n        when(mockClusterPhyService.createCluster(clusterPhyDTO, \"operator\")).thenReturn(Result.buildBoolen(true));\n        assertEquals(Result.buildBoolen(true), clusterPhyManager.addCluster(clusterPhyDTO, \"operator\", 0));\n    }\n\n    @Test\n    void testBuildPhyClusterStatics() {\n        when(mockClusterPhyService.isClusterExists(CLUSTER)).thenReturn(false);\n\n        when(mockEsClusterService.syncGetClusterStats(CLUSTER)).thenReturn(esClusterStatsResponse);\n\n        clusterPhyManager.buildPhyClusterStatics(clusterPhyVO);\n\n    }\n\n    @Test\n    void testBuildClusterRole1() {\n\n        when(mockClusterRoleService.getAllRoleClusterByClusterId(0)).thenReturn(clusterRoleInfos);\n\n        when(mockClusterRoleHostService.getByRoleClusterIds(Collections.singletonList(0L))).thenReturn(new HashMap<>());\n\n        clusterPhyManager.buildClusterRole(clusterPhyVO);\n\n    }\n\n    @Test\n    void testBuildClusterRole2() {\n        when(mockClusterRoleHostService.getByRoleClusterIds(Collections.singletonList(0L))).thenReturn(new HashMap<>());\n\n        clusterPhyManager.buildClusterRole(clusterPhyVO, clusterRoleInfos);\n\n    }\n\n    @Test\n    void testUpdateClusterHealth() throws ESOperateException {\n        when(mockClusterPhyService.getClusterByName(CLUSTER)).thenReturn(null);\n        assertFalse(clusterPhyManager.updateClusterHealth(CLUSTER, \"operator\"));\n\n        when(mockClusterPhyService.getClusterByName(CLUSTER)).thenReturn(clusterPhy);\n        when(mockEsClusterService.syncGetClusterHealthEnum(CLUSTER)).thenReturn(ClusterHealthEnum.GREEN);\n        when(mockClusterPhyService.editCluster(Mockito.any(), Mockito.anyString())).thenReturn(Result.buildFail(null));\n        assertFalse(clusterPhyManager.updateClusterHealth(CLUSTER, \"operator\"));\n\n        when(mockClusterPhyService.editCluster(Mockito.any(), Mockito.anyString())).thenReturn(Result.buildSucc());\n        assertTrue(clusterPhyManager.updateClusterHealth(CLUSTER, \"operator\"));\n    }\n\n    @Test\n    void testUpdateClusterInfo() {\n        when(mockClusterPhyService.getClusterByName(CLUSTER)).thenReturn(null);\n        assertFalse(clusterPhyManager.updateClusterInfo(CLUSTER, \"operator\"));\n\n        when(mockClusterPhyService.getClusterByName(CLUSTER)).thenReturn(clusterPhy);\n        ESClusterStatsResponse response = new ESClusterStatsResponse(\"status\", 0L, 0L, 0L,new ByteSizeValue(0L, ByteSizeUnit.BYTES), 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,\n            new ByteSizeValue(0L, ByteSizeUnit.BYTES), new ByteSizeValue(0L, ByteSizeUnit.BYTES),\n            new ByteSizeValue(0L, ByteSizeUnit.BYTES), 0L, 0L, new ByteSizeValue(100L, ByteSizeUnit.BYTES),\n            new ByteSizeValue(40L, ByteSizeUnit.BYTES), new ByteSizeValue(0L, ByteSizeUnit.BYTES),\n            new ByteSizeValue(0L, ByteSizeUnit.BYTES));\n        when(mockEsClusterService.syncGetClusterStats(CLUSTER)).thenReturn(response);\n        when(mockClusterPhyService.editCluster(Mockito.any(), Mockito.anyString())).thenReturn(Result.buildFail(null));\n        assertFalse(clusterPhyManager.updateClusterInfo(CLUSTER, \"operator\"));\n\n        when(mockClusterPhyService.editCluster(Mockito.any(), Mockito.anyString())).thenReturn(Result.buildSucc());\n        assertTrue(clusterPhyManager.updateClusterInfo(CLUSTER, \"operator\"));\n    }\n\n    @Test\n    void testCheckClusterHealth() throws ESOperateException {\n        when(mockClusterPhyService.getClusterByName(CLUSTER)).thenReturn(null);\n        assertFalse(clusterPhyManager.checkClusterHealth(CLUSTER, \"operator\").success());\n        ClusterPhy clusterPhy = new ClusterPhy();\n        clusterPhy.setHealth(0);\n        when(mockClusterPhyService.getClusterByName(CLUSTER)).thenReturn(clusterPhy);\n        assertTrue(clusterPhyManager.checkClusterHealth(CLUSTER, \"operator\").getData());\n        clusterPhy.setHealth(2);\n        when(mockEsClusterService.syncGetClusterHealthEnum(CLUSTER)).thenReturn(ClusterHealthEnum.GREEN);\n        when(mockClusterPhyService.editCluster(Mockito.any(), Mockito.anyString())).thenReturn(Result.buildSucc());\n        assertEquals(Result.buildSucc(), clusterPhyManager.checkClusterHealth(CLUSTER, \"operator\"));\n    }\n\n    @Test\n    void testUpdateClusterGateway() {\n        when(mockClusterPhyService.getClusterById(0)).thenReturn(clusterPhy);\n\n        when(mockClusterPhyService.editCluster(Mockito.any(), Mockito.anyString())).thenReturn(Result.buildFail(false));\n        assertEquals(Result.buildFail(\"编辑gateway失败！\").getMessage(),\n            clusterPhyManager.updateClusterGateway(clusterPhyDTO, \"operator\").getMessage());\n\n        when(mockClusterPhyService.editCluster(Mockito.any(), Mockito.anyString())).thenReturn(Result.buildSucc(true));\n        assertTrue(clusterPhyManager.updateClusterGateway(clusterPhyDTO, \"operator\").success());\n\n    }\n\n    @Test\n    void testListClusterRolesByClusterId() {\n        // Setup\n        final List<ClusterRoleInfo> expectedResult = Arrays.asList(new ClusterRoleInfo(0L, 0L, \"roleClusterName\",\n            \"role\", 0, 0, \"machineSpec\", \"esVersion\", 0, \"plugIds\", false, Arrays.asList(new ClusterRoleHost(0L, 0L,\n                \"hostname\", \"ip\", CLUSTER, \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\"))));\n\n        // Configure ClusterRoleService.getAllRoleClusterByClusterId(...).\n        final List<ClusterRoleInfo> clusterRoleInfos = Arrays.asList(new ClusterRoleInfo(0L, 0L, \"roleClusterName\",\n            \"role\", 0, 0, \"machineSpec\", \"esVersion\", 0, \"plugIds\", false, Arrays.asList(new ClusterRoleHost(0L, 0L,\n                \"hostname\", \"ip\", CLUSTER, \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\"))));\n        when(mockClusterRoleService.getAllRoleClusterByClusterId(0)).thenReturn(clusterRoleInfos);\n\n        // Run the test\n        final List<ClusterRoleInfo> result = clusterPhyManager.listClusterRolesByClusterId(0);\n\n        // Verify the results\n        assertEquals(expectedResult, result);\n    }\n\n    @Test\n    void testListClusterRolesByClusterId_ClusterRoleServiceReturnsNoItems() {\n        // Setup\n        when(mockClusterRoleService.getAllRoleClusterByClusterId(0)).thenReturn(Collections.emptyList());\n\n        // Run the test\n        final List<ClusterRoleInfo> result = clusterPhyManager.listClusterRolesByClusterId(0);\n\n        // Verify the results\n        assertEquals(Collections.emptyList(), result);\n    }\n\n    @Test\n    public void getTemplateSameVersionClusterNamesByTemplateIdTest() {\n        Result<List<String>> rest = clusterPhyManager.getTemplateSameVersionClusterNamesByTemplateId(1, 37529);\n        Assertions.assertTrue(rest.success());\n\n        when(mockClusterPhyService.listAllClusters()).thenReturn(clusterPhyList);\n        when(mockIndexTemplateService.getLogicTemplateWithPhysicalsById(Mockito.any()))\n            .thenReturn(new IndexTemplateWithPhyTemplates(null));\n        Assertions.assertEquals(\n            Result.buildFail(String.format(\"the physicals of templateId[%s] is empty\", 37529)).getMessage(),\n            clusterPhyManager.getTemplateSameVersionClusterNamesByTemplateId(1, 37529).getMessage());\n\n        when(mockIndexTemplateService.getLogicTemplateWithPhysicalsById(Mockito.any()))\n            .thenReturn(indexTemplateWithPhyTemplates);\n        when(mockClusterPhyService.getClusterByName(CLUSTER)).thenReturn(clusterPhy);\n        rest = clusterPhyManager.getTemplateSameVersionClusterNamesByTemplateId(1, 37529);\n        Assertions.assertTrue(rest.success());\n    }\n\n    @Test\n    public void testDeleteClusterExit() {\n        int projectId = 1;\n        Assertions.assertEquals(Result.buildFail(\"无权限删除集群\").getMessage(),\n            clusterPhyManager.deleteClusterExit(CLUSTER, 2, \"operator\").getMessage());\n        when(mockClusterPhyService.getClusterByName(CLUSTER)).thenReturn(clusterPhy);\n        when(mockClusterPhyService.getClusterById(0)).thenReturn(clusterPhy);\n        when(mockClusterRoleHostService.getNodesByCluster(CLUSTER)).thenReturn(Collections.emptyList());\n        when(mockClusterRoleService.deleteRoleClusterByClusterId(0, projectId)).thenReturn(Result.buildSucc());\n        when(mockClusterRegionService.listPhyClusterRegions(CLUSTER)).thenReturn(Collections.emptyList());\n        when(mockClusterPhyService.deleteClusterById(0, projectId)).thenReturn(Result.buildSucc(true));\n        Assertions.assertTrue(clusterPhyManager.deleteClusterExit(CLUSTER, 1, \"operator\").success());\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/biz/gateway/GatewayManagerTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.gateway;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\nimport com.didichuxing.datachannel.arius.admin.biz.gateway.impl.GatewayManagerImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.aliases.TemplateLogicAliasManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.GatewayHeartbeat;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.IndexTemplateAliasDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateRequest;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.dsl.ScrollDslTemplateResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.gateway.GatewayClusterNode;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateAlias;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.dsl.DslTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.gateway.GatewayClusterNodeVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.GatewayESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplateDeployInfoVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.template.GatewayTemplatePhysicalVO;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.gateway.GatewayService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ESUserService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectConfigService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectLogicTemplateAuthService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.TemplateLogicAliasService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.DslStatisticsService;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport java.util.Arrays;\nimport java.util.Calendar;\nimport java.util.GregorianCalendar;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport javax.servlet.http.HttpServletRequest;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.mock.web.MockHttpServletRequest;\nimport org.springframework.test.annotation.Rollback;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Transactional\n@Rollback\npublic class GatewayManagerTest {\n    @Autowired\n    private GatewayManager                  gatewayManager;\n\n    @Mock\n    private ESUserService                   mockEsUserService;\n    @Mock\n    private ProjectService                  mockProjectService;\n    @Mock\n    private ProjectLogicTemplateAuthService mockProjectLogicTemplateAuthService;\n    @Mock\n    private IndexTemplateService            mockIndexTemplateService;\n    @Mock\n    private IndexTemplatePhyService         mockIndexTemplatePhyService;\n    @Mock\n    private TemplateLogicAliasManager       mockTemplateLogicAliasManager;\n    @Mock\n    private GatewayService                  mockGatewayService;\n    @Mock\n    private AriusConfigInfoService          mockAriusConfigInfoService;\n    @Mock\n    private DslStatisticsService            mockDslStatisticsService;\n    @Mock\n    private TemplateLogicAliasService       mockTemplateLogicAliasService;\n    @Mock\n    private ProjectConfigService            mockProjectConfigService;\n    protected HttpHeaders                   headers;\n\n    @InjectMocks\n    private GatewayManagerImpl              gatewayManagerImplUnderTest;\n\n    @BeforeEach\n    void setUp() {\n        headers = new HttpHeaders();\n        headers.add(HttpRequestUtil.USER, \"admin\");\n        initMocks(this);\n    }\n\n    @Test\n    void heartbeatTest1() {\n        // Setup\n        final GatewayHeartbeat heartbeat = new GatewayHeartbeat(\"clusterName\", \"hostName\", 0);\n        when(mockGatewayService.heartbeat(new GatewayHeartbeat(\"clusterName\", \"hostName\", 0)))\n            .thenReturn(Result.buildFail(null));\n\n        // Run the test\n        final Result<Void> result = gatewayManagerImplUnderTest.heartbeat(heartbeat);\n\n        // Verify the results\n    }\n\n    @Test\n    void heartbeatTest2() {\n        // Setup\n        final Result<Integer> expectedResult = Result.buildSucc(0);\n        when(mockGatewayService.aliveCount(\"clusterName\", 0L)).thenReturn(Result.buildSucc(0));\n\n        // Run the test\n        final Result<Integer> result = gatewayManagerImplUnderTest.heartbeat(\"clusterName\");\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayAliveNodeTest() {\n        // Setup\n        final Result<List<GatewayClusterNodeVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new GatewayClusterNodeVO(0, \"clusterName\", \"hostName\", 0,\n                new GregorianCalendar(2020, Calendar.JANUARY, 1).getTime())));\n\n        // Configure GatewayService.getAliveNode(...).\n        final List<GatewayClusterNode> gatewayClusterNodes = Arrays.asList(new GatewayClusterNode(0, \"clusterName\",\n            \"hostName\", 0, new GregorianCalendar(2020, Calendar.JANUARY, 1).getTime()));\n        when(mockGatewayService.getAliveNode(\"clusterName\", 0L)).thenReturn(gatewayClusterNodes);\n\n        // Run the test\n        final Result<List<GatewayClusterNodeVO>> result = gatewayManagerImplUnderTest\n            .getGatewayAliveNode(\"clusterName\");\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayAliveNodeNamesTest() {\n        // Setup\n        final Result<List<String>> expectedResult = Result.buildSucc(Arrays.asList(\"value\"));\n\n        // Configure GatewayService.getAliveNode(...).\n        final List<GatewayClusterNode> gatewayClusterNodes = Arrays.asList(new GatewayClusterNode(0, \"clusterName\",\n            \"hostName\", 0, new GregorianCalendar(2020, Calendar.JANUARY, 1).getTime()));\n        when(mockGatewayService.getAliveNode(\"clusterName\", 0L)).thenReturn(gatewayClusterNodes);\n\n        // Run the test\n        final Result<List<String>> result = gatewayManagerImplUnderTest.getGatewayAliveNodeNames(\"clusterName\");\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void listProjectTest() {\n        final MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest();\n        mockHttpServletRequest.addHeader(\"X-ARIUS-GATEWAY-TICKET\", \"xTc59aY72\");\n        // Setup\n        final HttpServletRequest request = mockHttpServletRequest;\n        final Result<List<GatewayESUserVO>> expectedResult = Result.buildSucc(Arrays.asList(new GatewayESUserVO()));\n\n        // Configure ProjectService.getProjectBriefList(...).\n        final ProjectBriefVO projectBriefVO = new ProjectBriefVO();\n        projectBriefVO.setId(1);\n        projectBriefVO.setProjectCode(\"projectCode\");\n        projectBriefVO.setProjectName(\"projectName\");\n        final List<ProjectBriefVO> projectBriefVOS = Arrays.asList(projectBriefVO);\n        when(mockProjectService.getProjectBriefList()).thenReturn(projectBriefVOS);\n\n        // Configure ESUserService.listESUsers(...).\n        final List<ESUser> esUsers = Arrays.asList(new ESUser(0, \"name\", 0, \"verifyCode\",  \"memo\", 0, 0, \"cluster\", 0, \"dataCenter\", 1, false, \"ip\", \"indexExp\"));\n        when(mockEsUserService.listESUsers(Arrays.asList(1))).thenReturn(esUsers);\n\n        when(mockProjectConfigService.projectId2ProjectConfigMap()).thenReturn(new HashMap<>());\n        when(mockProjectLogicTemplateAuthService.getAllProjectTemplateAuths()).thenReturn(new HashMap<>());\n        when(mockAriusConfigInfoService.stringSetting(\"arius.common.group\", \"app.default.read.auth.indices\", \"\"))\n            .thenReturn(\"result\");\n        when(mockIndexTemplateService.getAllLogicTemplatesMap()).thenReturn(new HashMap<>());\n        when(mockTemplateLogicAliasService.listAliasMapWithCache()).thenReturn(new HashMap<>());\n\n        // Run the test\n        final Result<List<GatewayESUserVO>> result = gatewayManagerImplUnderTest.listESUserByProject();\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getTemplateMapTest() {\n        // Setup\n        final Result<Map<String, GatewayTemplatePhysicalVO>> expectedResult = Result.buildFail(new HashMap<>());\n\n        // Configure IndexTemplatePhyService.getNormalTemplateByCluster(...).\n        final List<IndexTemplatePhy> indexTemplatePhies = Arrays\n            .asList(new IndexTemplatePhy(0L, 0, \"name\", \"expression\", \"cluster\", \"rack\", 0, 0, 0, 0, 0, \"config\", 0));\n        when(mockIndexTemplatePhyService.getNormalTemplateByCluster(\"cluster\")).thenReturn(indexTemplatePhies);\n\n        when(mockIndexTemplateService.getAllLogicTemplatesMap()).thenReturn(new HashMap<>());\n\n        // Configure TemplateLogicAliasesManager.listAlias(...).\n        final List<IndexTemplateAlias> indexTemplateAliases = Arrays.asList(new IndexTemplateAlias(0, 0, \"name\"));\n        when(mockTemplateLogicAliasManager.listAlias()).thenReturn(indexTemplateAliases);\n\n        // Run the test\n        final Result<Map<String, GatewayTemplatePhysicalVO>> result = gatewayManagerImplUnderTest\n            .getTemplateMap(\"cluster\");\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void listDeployInfoTest() {\n        // Setup\n        final Result<Map<String, GatewayTemplateDeployInfoVO>> expectedResult = Result.buildSucc(new HashMap<>());\n\n        // Configure IndexTemplateService.getTemplateWithPhysicalByDataCenter(...).\n        final List<IndexTemplateWithPhyTemplates> indexTemplateWithPhyTemplates = Arrays\n            .asList(new IndexTemplateWithPhyTemplates(Arrays.asList(\n                new IndexTemplatePhy(0L, 0, \"name\", \"expression\", \"cluster\", \"rack\", 0, 0, 0, 0, 0, \"config\", 0))));\n        when(mockIndexTemplateService.listTemplateWithPhysical())\n            .thenReturn(indexTemplateWithPhyTemplates);\n\n        // Configure TemplateLogicAliasesManager.listAlias(...).\n        final List<IndexTemplateAlias> indexTemplateAliases = Arrays.asList(new IndexTemplateAlias(0, 0, \"name\"));\n        when(mockTemplateLogicAliasManager.listAlias(Arrays.asList(new IndexTemplateWithPhyTemplates(Arrays.asList(\n            new IndexTemplatePhy(0L, 0, \"name\", \"expression\", \"cluster\", \"rack\", 0, 0, 0, 0, 0, \"config\", 0))))))\n                .thenReturn(indexTemplateAliases);\n\n        // Run the test\n        final Result<Map<String, GatewayTemplateDeployInfoVO>> result = gatewayManagerImplUnderTest\n            .listDeployInfo();\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void scrollSearchDslTemplateTest() {\n        // Setup\n        final ScrollDslTemplateRequest request = new ScrollDslTemplateRequest();\n        request.setScrollSize(0L);\n        request.setDslTemplateVersion(\"dslTemplateVersion\");\n        request.setLastModifyTime(0L);\n        request.setScrollId(\"scrollId\");\n\n        final Result<ScrollDslTemplateResponse> expectedResult = Result\n            .buildSucc(new ScrollDslTemplateResponse(Arrays.asList(new DslTemplatePO(\"ariusCreateTime\",\n                \"ariusModifyTime\", 0.0, \"requestType\", \"searchType\", 0L, 0.0, 0.0, 0.0, 0.0, 0.0, \"logTime\",\n                \"indiceSample\", \"dslTemplate\", 0L, \"dslType\", \"indices\", \"dslTemplateMd5\", 0.0, 0.0, 0L, 0, \"dsl\", 0.0,\n                \"flinkTime\", 0.0, false, false, false, \"checkMode\", 0L, \"version\", \"dslTag\")), \"scrollId\"));\n\n        // Configure DslStatisService.scrollSearchDslTemplate(...).\n        final Result<ScrollDslTemplateResponse> scrollDslTemplateResponseResult = Result\n            .buildSucc(new ScrollDslTemplateResponse(Arrays.asList(new DslTemplatePO(\"ariusCreateTime\",\n                \"ariusModifyTime\", 0.0, \"requestType\", \"searchType\", 0L, 0.0, 0.0, 0.0, 0.0, 0.0, \"logTime\",\n                \"indiceSample\", \"dslTemplate\", 0L, \"dslType\", \"indices\", \"dslTemplateMd5\", 0.0, 0.0, 0L, 0, \"dsl\", 0.0,\n                \"flinkTime\", 0.0, false, false, false, \"checkMode\", 0L, \"version\", \"dslTag\")), \"scrollId\"));\n        when(mockDslStatisticsService.scrollSearchDslTemplate(new ScrollDslTemplateRequest()))\n            .thenReturn(scrollDslTemplateResponseResult);\n\n        // Run the test\n        final Result<ScrollDslTemplateResponse> result = gatewayManagerImplUnderTest.scrollSearchDslTemplate(request);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void addAliasTest() {\n        // Setup\n        final IndexTemplateAliasDTO indexTemplateAliasDTO = new IndexTemplateAliasDTO();\n        indexTemplateAliasDTO.setLogicId(0);\n        indexTemplateAliasDTO.setName(\"name\");\n\n        final Result<Boolean> expectedResult = Result.buildSucc();\n        when(mockTemplateLogicAliasService.addAlias(new IndexTemplateAliasDTO())).thenReturn(Result.buildSucc());\n\n        // Run the test\n        final Result<Boolean> result = gatewayManagerImplUnderTest.addAlias(indexTemplateAliasDTO);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void delAliasTest() {\n        // Setup\n        final IndexTemplateAliasDTO indexTemplateAliasDTO = new IndexTemplateAliasDTO();\n        indexTemplateAliasDTO.setLogicId(0);\n        indexTemplateAliasDTO.setName(\"name\");\n\n        final Result<Boolean> expectedResult = Result.buildSucc();\n        when(mockTemplateLogicAliasService.delAlias(new IndexTemplateAliasDTO())).thenReturn(Result.buildSucc());\n\n        // Run the test\n        final Result<Boolean> result = gatewayManagerImplUnderTest.delAlias(indexTemplateAliasDTO);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void sqlExplainTest() {\n        // Setup\n        final Result<String> expectedResult = Result.buildFail(\"value\");\n        when(mockEsUserService.checkDefaultESUserByProject(0)).thenReturn(false);\n\n        // Configure ESUserService.getDefaultESUserByProject(...).\n        final ESUser esUser = new ESUser(0, \"name\", 0, \"verifyCode\",\n            \"memo\", 0, 0, \"cluster\", 0, \"dataCenter\", 0, false, \"ip\", \"indexExp\");\n        when(mockEsUserService.getDefaultESUserByProject(0)).thenReturn(esUser);\n\n        when(\n            mockGatewayService.sqlOperate(\"sql\", \"phyClusterName\",\n                new ESUser(0, \"name\", 0, \"verifyCode\",  \"memo\", 0, 0,\n                    \"cluster\", 0, \"dataCenter\", 0, false, \"ip\", \"indexExp\"),\n                \"SQL_EXPLAIN\")).thenReturn(Result.buildFail(\"value\"));\n\n        // Run the test\n        final Result<String> result = gatewayManagerImplUnderTest.sqlExplain(\"sql\", \"\", 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void directSqlSearchTest() {\n        // Setup\n        final Result<String> expectedResult = Result.buildFail(\"value\");\n        when(mockEsUserService.checkDefaultESUserByProject(0)).thenReturn(false);\n\n        // Configure ESUserService.getDefaultESUserByProject(...).\n        final ESUser esUser = new ESUser(0, \"name\", 0, \"verifyCode\",\n            \"memo\", 0, 0, \"cluster\", 0, \"dataCenter\", 0, false, \"ip\", \"indexExp\");\n        when(mockEsUserService.getDefaultESUserByProject(0)).thenReturn(esUser);\n\n        when(\n            mockGatewayService.sqlOperate(\"sql\", \"phyClusterName\",\n                new ESUser(0, \"name\", 0, \"verifyCode\",  \"memo\", 0, 0,\n                    \"cluster\", 0, \"dataCenter\", 0, false, \"ip\", \"indexExp\"),\n                \"SQL_SEARCH\")).thenReturn(Result.buildFail(\"value\"));\n\n        // Run the test\n        final Result<String> result = gatewayManagerImplUnderTest.directSqlSearch(\"sql\", \"phyClusterName\", 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/biz/metrics/ClusterPhyMetricsManagerTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.when;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.impl.ClusterPhyMetricsManagerImpl;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.UserConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MultiMetricsClusterPhyNodeDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ESClusterTaskDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.cluster.ESClusterTaskDetailVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.MetricsContentCellVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.MetricsContentVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.metrics.ClusterPhyTypeMetricsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.NotFindSubclassException;\nimport com.didichuxing.datachannel.arius.admin.core.component.HandleFactory;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.region.ClusterRegionService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.metrics.UserConfigService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.NodeStatsService;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport com.didiglobal.knowframework.security.util.HttpRequestUtil;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.context.SpringBootTest.WebEnvironment;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@ActiveProfiles(\"test\")\n@ExtendWith({ SpringExtension.class, MockitoExtension.class })\n@MockitoSettings(strictness = Strictness.LENIENT)\n@RunWith(SpringRunner.class)\n@ContextConfiguration(classes = { SpringTool.class })\n@SpringBootTest(webEnvironment = WebEnvironment.NONE)\nclass ClusterPhyMetricsManagerTest {\n\n    @Mock\n    private ProjectService               projectService;\n    @Mock\n    private UserConfigService     userConfigService;\n    @Mock\n    private NodeStatsService             nodeStatsService;\n    @Mock\n    private HandleFactory                handleFactory;\n    @Mock\n    private ClusterLogicService          clusterLogicService;\n    @Mock\n    private ClusterRegionService         clusterRegionService;\n    @Mock\n    private ClusterRoleHostService       clusterRoleHostService;\n    @Mock\n    private IndexTemplateService         indexTemplateService;\n    @Mock\n    private ESIndexService               esIndexService;\n\n    @InjectMocks\n    private ClusterPhyMetricsManagerImpl clusterPhyMetricsManager;\n\n    @Test\n    void getMetricsCode2TypeMap() throws Exception {\n        assertThat(clusterPhyMetricsManager.getMetricsCode2TypeMap(\"type\")).isEqualTo(Arrays.asList(\"value\"));\n        assertThat(clusterPhyMetricsManager.getMetricsCode2TypeMap(\"type\")).isEqualTo(Collections.emptyList());\n    }\n\n    @Test\n    void getClusterMetricsByMetricsTypeTest() throws NotFindSubclassException {\n        // Setup\n        final MetricsClusterPhyDTO param = new MetricsClusterPhyDTO(\"clusterPhyName\", \"clusterLogicName\", 0L, 0L,\n            \"aggType\", Arrays.asList(\"value\"), 0, 0, \"topMethod\", Arrays.asList(\"value\"),null);\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic  = new ClusterLogic(0L, \"name\", 0, 0, \"projectName\" ,\"dataCenter\", \"dataNodeSpec\", 0,\n                \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Arrays.asList(new ClusterRoleHost(0L, 0L,\n            \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\")));\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(\n            Arrays.asList(new IndexTemplate(0, \"name\", 0, 0, \"dateFormat\", \"dataCenter\", 0, 0, 0, \"dateField\", \"dateFieldFormat\", \"idField\", \"routingField\",\n                \"expression\", 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0, 0.0,1)));\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result resultClusterMetrics = clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, 0,\n            \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n    }\n\n    @Test\n    void getClusterMetricsByMetricsTypeClusterRegionServiceReturnsNullTest() {\n        // Setup\n        final MetricsClusterPhyDTO param = new MetricsClusterPhyDTO(\"clusterPhyName\", \"clusterLogicName\", 0L, 0L,\n            \"aggType\", Arrays.asList(\"value\"), 0, 0, \"topMethod\", Arrays.asList(\"value\"),null);\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0, \"projectName\", \"dataCenter\", \"dataNodeSpec\", 0,  \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(null);\n\n        // Run the test\n        final Result result = clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, 0, \"userName\",\n            ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n    }\n\n    @Test\n    void getClusterMetricsByMetricsTypeClusterRoleHostServiceReturnsNoItemTest() throws NotFindSubclassException {\n        // Setup\n        final MetricsClusterPhyDTO param = new MetricsClusterPhyDTO(\"clusterPhyName\", \"clusterLogicName\", 0L, 0L,\n            \"aggType\", Arrays.asList(\"value\"), 0, 0, \"topMethod\", Arrays.asList(\"value\"),null);\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0, \"ProjectName\", \"dataCenter\", \"dataNodeSpec\", 0,\n            \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(Result.buildSucc());\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(\n            Arrays.asList(new IndexTemplate(0, \"name\", 0, 0, \"dateFormat\", \"dataCenter\", 0, 0, 0,  \"dateField\", \"dateFieldFormat\", \"idField\", \"routingField\",\n                \"expression\", 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0, 0.0,1)));\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result result = clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, 0, \"userName\",\n            ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n    }\n\n    @Test\n    void getClusterMetricsByMetricsTypeClusterRoleHostServiceReturnsNoItemsTest() throws NotFindSubclassException {\n        // Setup\n        final MetricsClusterPhyDTO param = new MetricsClusterPhyDTO(\"clusterPhyName\", \"clusterLogicName\", 0L, 0L,\n            \"aggType\", Arrays.asList(\"value\"), 0, 0, \"topMethod\", Arrays.asList(\"value\"),null);\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectNama\", \"dataCenter\", \"dataNodeSpec\", 0, \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Collections.emptyList());\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(\n            Arrays.asList(new IndexTemplate(0, \"name\", 0, 0, \"dateFormat\", \"dataCenter\", 0, 0, 0, \"dateField\", \"dateFieldFormat\", \"idField\", \"routingField\",\n                \"expression\", 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0, 0.0,1)));\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result resultClusterMetrics = clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, 0,\n            \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n    }\n\n    @Test\n    void getClusterMetricsByMetricsTypeClusterRoleHostServiceReturnsFailureTest() throws NotFindSubclassException {\n        // Setup\n        final MetricsClusterPhyDTO param = new MetricsClusterPhyDTO(\"clusterPhyName\", \"clusterLogicName\", 0L, 0L,\n            \"aggType\", Arrays.asList(\"value\"), 0, 0, \"topMethod\", Arrays.asList(\"value\"),null);\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0, \"projectName\",\"dataCenter\", \"dataNodeSpec\", 0, \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail();\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(\n            Arrays.asList(new IndexTemplate(0, \"name\", 0, 0, \"dateFormat\", \"dataCenter\", 0, 0, 0,  \"dateField\", \"dateFieldFormat\", \"idField\", \"routingField\",\n                \"expression\", 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0, 0.0,1)));\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result resultClusterMetrics = clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, 0,\n            \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n    }\n\n    @Test\n    void getClusterMetricsByMetricsTypeIndexTemplateServiceReturnsNoItemTest() throws NotFindSubclassException {\n        // Setup\n        final MetricsClusterPhyDTO param = new MetricsClusterPhyDTO(\"clusterPhyName\", \"clusterLogicName\", 0L, 0L,\n            \"aggType\", Arrays.asList(\"value\"), 0, 0, \"topMethod\", Arrays.asList(\"value\"),null);\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0,  \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Arrays.asList(new ClusterRoleHost(0L, 0L,\n            \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\")));\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        when(indexTemplateService.listByRegionId(0)).thenReturn(Result.buildSucc());\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result resultClusterMetrics = clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, 0,\n            \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n    }\n\n    @Test\n    void getClusterMetricsByMetricsTypeIndexTemplateServiceReturnsNoItemsTest() throws NotFindSubclassException {\n        // Setup\n        final MetricsClusterPhyDTO param = new MetricsClusterPhyDTO(\"clusterPhyName\", \"clusterLogicName\", 0L, 0L,\n            \"aggType\", Arrays.asList(\"value\"), 0, 0, \"topMethod\", Arrays.asList(\"value\"),null);\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0,  \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Arrays.asList(new ClusterRoleHost(0L, 0L,\n            \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\")));\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(Collections.emptyList());\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result resultClusterMetrics = clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, 0,\n            \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n    }\n\n    @Test\n    void getClusterMetricsByMetricsTypeIndexTemplateServiceReturnsFailureTest() throws NotFindSubclassException {\n        // Setup\n        final MetricsClusterPhyDTO param = new MetricsClusterPhyDTO(\"clusterPhyName\", \"clusterLogicName\", 0L, 0L,\n            \"aggType\", Arrays.asList(\"value\"), 0, 0, \"topMethod\", Arrays.asList(\"value\"),null);\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0,  \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Arrays.asList(new ClusterRoleHost(0L, 0L,\n            \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\")));\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail();\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result resultClusterMetrics = clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, 0,\n            \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n    }\n\n    @Test\n    void getClusterMetricsByMetricsTypeESIndexServiceReturnsNoItemsTest() throws NotFindSubclassException {\n        // Setup\n        final MetricsClusterPhyDTO param = new MetricsClusterPhyDTO(\"clusterPhyName\", \"clusterLogicName\", 0L, 0L,\n            \"aggType\", Arrays.asList(\"value\"), 0, 0, \"topMethod\", Arrays.asList(\"value\"),null);\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0, \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Arrays.asList(new ClusterRoleHost(0L, 0L,\n            \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\")));\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(\n            Arrays.asList(new IndexTemplate(0, \"name\", 0, 0, \"dateFormat\", \"dataCenter\", 0, 0, 0,  \"dateField\", \"dateFieldFormat\", \"idField\", \"routingField\",\n                \"expression\", 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0, 0.0,1)));\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\"))\n            .thenReturn(Collections.emptyList());\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result resultClusterMetrics = clusterPhyMetricsManager.getClusterMetricsByMetricsType(param, 0,\n            \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n    }\n\n    @Test\n    void getMultiClusterMetricsTest() throws NotFindSubclassException {\n        // Setup\n        final MultiMetricsClusterPhyNodeDTO param = new MultiMetricsClusterPhyNodeDTO(Arrays.asList(\"value\"));\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0, \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Arrays.asList(new ClusterRoleHost(0L, 0L,\n            \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\")));\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(\n            Arrays.asList(new IndexTemplate(0, \"name\", 0, 0, \"dateFormat\", \"dataCenter\", 0, 0, 0,  \"dateField\", \"dateFieldFormat\", \"idField\", \"routingField\",\n                \"expression\", 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0, 0.0,1)));\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> resultClusterMetrics = clusterPhyMetricsManager\n            .getMultiClusterMetrics(param, 0, \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiClusterMetricsClusterRegionServiceReturnsNullTest() {\n        // Setup\n        final MultiMetricsClusterPhyNodeDTO param = new MultiMetricsClusterPhyNodeDTO(Arrays.asList(\"value\"));\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0, \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(null);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = clusterPhyMetricsManager.getMultiClusterMetrics(param, 0,\n            \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiClusterMetricsClusterRoleHostServiceReturnsNoItemTest() throws NotFindSubclassException {\n        // Setup\n        final MultiMetricsClusterPhyNodeDTO param = new MultiMetricsClusterPhyNodeDTO(Arrays.asList(\"value\"));\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0,  \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(Result.buildSucc());\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(\n            Arrays.asList(new IndexTemplate(0, \"name\", 0, 0, \"dateFormat\", \"dataCenter\", 0, 0, 0, \"dateField\", \"dateFieldFormat\", \"idField\", \"routingField\",\n                \"expression\", 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0, 0.0,1)));\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = clusterPhyMetricsManager.getMultiClusterMetrics(param, 0,\n            \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiClusterMetricsClusterRoleHostServiceReturnsNoItemsTest() throws NotFindSubclassException {\n        // Setup\n        final MultiMetricsClusterPhyNodeDTO param = new MultiMetricsClusterPhyNodeDTO(Arrays.asList(\"value\"));\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0,\"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Collections.emptyList());\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(\n            Arrays.asList(new IndexTemplate(0, \"name\", 0, 0, \"dateFormat\", \"dataCenter\", 0, 0, 0, \"dateField\", \"dateFieldFormat\", \"idField\", \"routingField\",\n                \"expression\", 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0, 0.0,1)));\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> resultClusterMetrics = clusterPhyMetricsManager\n            .getMultiClusterMetrics(param, 0, \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiClusterMetricsClusterRoleHostServiceReturnsFailureTest() throws NotFindSubclassException {\n        // Setup\n        final MultiMetricsClusterPhyNodeDTO param = new MultiMetricsClusterPhyNodeDTO(Arrays.asList(\"value\"));\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0,  \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail();\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(\n            Arrays.asList(new IndexTemplate(0, \"name\", 0, 0, \"dateFormat\", \"dataCenter\", 0, 0, 0, \"dateField\", \"dateFieldFormat\", \"idField\", \"routingField\",\n                \"expression\", 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0, 0.0,1)));\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> resultClusterMetrics = clusterPhyMetricsManager\n            .getMultiClusterMetrics(param, 0, \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiClusterMetricsIndexTemplateServiceReturnsNoItemTest() throws NotFindSubclassException {\n        // Setup\n        final MultiMetricsClusterPhyNodeDTO param = new MultiMetricsClusterPhyNodeDTO(Arrays.asList(\"value\"));\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0, \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Arrays.asList(new ClusterRoleHost(0L, 0L,\n            \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\")));\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        when(indexTemplateService.listByRegionId(0)).thenReturn(Result.buildSucc());\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> resultClusterMetrics = clusterPhyMetricsManager\n            .getMultiClusterMetrics(param, 0, \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiClusterMetricsIndexTemplateServiceReturnsNoItemsTest() throws NotFindSubclassException {\n        // Setup\n        final MultiMetricsClusterPhyNodeDTO param = new MultiMetricsClusterPhyNodeDTO(Arrays.asList(\"value\"));\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0,  \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Arrays.asList(new ClusterRoleHost(0L, 0L,\n            \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\")));\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(Collections.emptyList());\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> resultClusterMetrics = clusterPhyMetricsManager\n            .getMultiClusterMetrics(param, 0, \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiClusterMetricsIndexTemplateServiceReturnsFailureTest() throws NotFindSubclassException {\n        // Setup\n        final MultiMetricsClusterPhyNodeDTO param = new MultiMetricsClusterPhyNodeDTO(Arrays.asList(\"value\"));\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0,  \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Arrays.asList(new ClusterRoleHost(0L, 0L,\n            \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\")));\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail();\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        // Configure ESIndexService.syncCatIndexByExpression(...).\n        final CatIndexResult catIndexResult = new CatIndexResult();\n        catIndexResult.setHealth(\"health\");\n        catIndexResult.setStatus(\"status\");\n        catIndexResult.setIndex(\"index\");\n        catIndexResult.setPri(\"pri\");\n        catIndexResult.setRep(\"rep\");\n        catIndexResult.setDocsCount(\"docsCount\");\n        catIndexResult.setDocsDeleted(\"docsDeleted\");\n        catIndexResult.setStoreSize(\"storeSize\");\n        catIndexResult.setPriStoreSize(\"priStoreSize\");\n        final List<CatIndexResult> catIndexResultList = Arrays.asList(catIndexResult);\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\")).thenReturn(catIndexResultList);\n\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> resultClusterMetrics = clusterPhyMetricsManager\n            .getMultiClusterMetrics(param, 0, \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiClusterMetricsESIndexServiceReturnsNoItemsTest() throws NotFindSubclassException {\n        // Setup\n        final MultiMetricsClusterPhyNodeDTO param = new MultiMetricsClusterPhyNodeDTO(Arrays.asList(\"value\"));\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure ClusterLogicService.getClusterLogicByName(...).\n        final ClusterLogic clusterLogic = new ClusterLogic(0L, \"name\", 0, 0,\"projectName\", \"dataCenter\", \"dataNodeSpec\", 0, \"memo\", 0.0, 0, \"configJson\", 0,0D,0L,0L,\"\",0);\n        when(clusterLogicService.getClusterLogicByNameAndProjectId(\"clusterLogicName\", null)).thenReturn(clusterLogic);\n\n        // Configure ClusterRegionService.getRegionByLogicClusterId(...).\n        final ClusterRegion clusterRegion = new ClusterRegion(0L, \"name\", \"logicClusterIds\", \"clusterPhyName\",\n            \"config\");\n        when(clusterRegionService.getRegionByLogicClusterId(0L)).thenReturn(clusterRegion);\n\n        // Configure ClusterRoleHostService.listByRegionId(...).\n        final Result<List<ClusterRoleHost>> result = Result.buildFail(Arrays.asList(new ClusterRoleHost(0L, 0L,\n            \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\", 0, \"attributes\")));\n        when(clusterRoleHostService.listByRegionId(0)).thenReturn(result);\n\n        // Configure IndexTemplateService.listByRegionId(...).\n        final Result<List<IndexTemplate>> listResult = Result.buildFail(\n            Arrays.asList(new IndexTemplate(0, \"name\", 0, 0, \"dateFormat\", \"dataCenter\", 0, 0, 0, \"dateField\", \"dateFieldFormat\", \"idField\", \"routingField\",\n                \"expression\", 0L, \"desc\", 0.0, 0, \"ingestPipeline\", false, false, 0, false, 0L, \"openSrv\", 0, 0.0,1)));\n        when(indexTemplateService.listByRegionId(0)).thenReturn(listResult);\n\n        when(esIndexService.syncCatIndexByExpression(\"clusterPhyName\", \"expression\"))\n            .thenReturn(Collections.emptyList());\n        when(handleFactory.getByHandlerNamePer(\"type\")).thenReturn(null);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> resultClusterMetrics = clusterPhyMetricsManager\n            .getMultiClusterMetrics(param, 0, \"userName\", ClusterPhyTypeMetricsEnum.UNKNOWN);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void listConfigMetricsByConditionTest() {\n        // Setup\n        final UserConfigInfoDTO userConfigInfoDTO = new UserConfigInfoDTO(\"userName\", \"firstUserConfigType\",\n            \"secondUserConfigType\", Arrays.asList(\"value\"),1,1);\n        when(userConfigService.getUserConfigByConfigTypeAndUserNameAndProjectId(\n            new UserConfigInfoDTO(\"userName\", \"firstUserConfigType\", \"secondUserConfigType\", Arrays.asList(\"value\"),1,1)))\n                .thenReturn(Arrays.asList(\"value\"));\n\n        // Run the test\n        final List<String> result = clusterPhyMetricsManager.listConfigMetricsByCondition(userConfigInfoDTO, \"userName\", 1);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Arrays.asList(\"value\"));\n    }\n\n    @Test\n    void listConfigMetricsByConditionUserConfigServiceReturnsNoItemsTest() {\n        // Setup\n        final UserConfigInfoDTO userConfigInfoDTO = new UserConfigInfoDTO(\"userName\", \"firstUserConfigType\",\n            \"secondUserConfigType\", Arrays.asList(\"value\"),1,1);\n        when(userConfigService.getUserConfigByConfigTypeAndUserNameAndProjectId(\n            new UserConfigInfoDTO(\"userName\", \"firstUserConfigType\", \"secondUserConfigType\", Arrays.asList(\"value\"),1,1)))\n                .thenReturn(Collections.emptyList());\n\n        // Run the test\n        final List<String> result = clusterPhyMetricsManager.listConfigMetricsByCondition(userConfigInfoDTO, \"userName\", 1);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Collections.emptyList());\n    }\n\n    @Test\n    void updateConfigMetricsByConditionTest() {\n        // Setup\n        final UserConfigInfoDTO param = new UserConfigInfoDTO(\"userName\", \"firstUserConfigType\", \"secondUserConfigType\",\n            Arrays.asList(\"value\"),1,1);\n        final Result<Integer> expectedResult = Result.buildFail(0);\n        when(userConfigService.updateUserConfigByConfigTypeAndUserNameAndProjectId(\n            new UserConfigInfoDTO(\"userName\", \"firstUserConfigType\", \"secondUserConfigType\", Arrays.asList(\"value\"),1,1)))\n                .thenReturn(Result.buildFail(0));\n\n        // Run the test\n        final Result<Integer> result = clusterPhyMetricsManager.updateConfigMetricsByCondition(param, \"userName\",1);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void updateConfigMetricsByConditionUserConfigServiceReturnsNoItemTest() {\n        // Setup\n        final UserConfigInfoDTO param = new UserConfigInfoDTO(\"userName\", \"firstUserConfigType\", \"secondUserConfigType\",\n            Arrays.asList(\"value\"),1,1);\n        when(userConfigService.updateUserConfigByConfigTypeAndUserNameAndProjectId(\n            new UserConfigInfoDTO(\"userName\", \"firstUserConfigType\", \"secondUserConfigType\", Arrays.asList(\"value\"),1,1)))\n                .thenReturn(Result.buildSucc());\n\n        // Run the test\n        final Result<Integer> result = clusterPhyMetricsManager.updateConfigMetricsByCondition(param, \"userName\",1);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildSucc());\n    }\n\n    @Test\n    void updateConfigMetricsByConditionUserConfigServiceReturnsFailureTest() {\n        // Setup\n        final UserConfigInfoDTO param = new UserConfigInfoDTO(\"userName\", \"firstUserConfigType\", \"secondUserConfigType\",\n            Arrays.asList(\"value\"),1,1);\n        final Result<Integer> expectedResult = Result.buildFail(0);\n        when(userConfigService.updateUserConfigByConfigTypeAndUserNameAndProjectId(\n            new UserConfigInfoDTO(\"userName\", \"firstUserConfigType\", \"secondUserConfigType\", Arrays.asList(\"value\"),1,1)))\n                .thenReturn(Result.buildFail());\n\n        // Run the test\n        final Result<Integer> result = clusterPhyMetricsManager.updateConfigMetricsByCondition(param, \"userName\",1);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getClusterPhyTaskDetailTest() {\n        // Setup\n        final Result<List<ESClusterTaskDetailVO>> expectedResult = Result.buildFail(Arrays\n            .asList(new ESClusterTaskDetailVO(\"taskId\", \"node\", \"action\", 0L, 0L, \"runningTimeString\", \"description\")));\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n\n        // Configure NodeStatisService.getClusterTaskDetail(...).\n        final List<ESClusterTaskDetail> esClusterTaskDetails = Arrays\n            .asList(new ESClusterTaskDetail(\"taskId\", \"node\", \"action\", 0L, 0L, \"runningTimeString\", \"description\"));\n        when(nodeStatsService.getClusterTaskDetail(\"clusterPhyName\", \"node\", 0L, 0L)).thenReturn(esClusterTaskDetails);\n\n        // Run the test\n        final Result<List<ESClusterTaskDetailVO>> result = clusterPhyMetricsManager\n            .getClusterPhyTaskDetail(\"clusterPhyName\", \"node\", \"startTime\", \"endTime\", 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getClusterPhyTaskDetailNodeStatisServiceReturnsNoItemsTest() {\n        // Setup\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n        when(nodeStatsService.getClusterTaskDetail(\"clusterPhyName\", \"node\", 0L, 0L))\n            .thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<ESClusterTaskDetailVO>> result = clusterPhyMetricsManager\n            .getClusterPhyTaskDetail(\"clusterPhyName\", \"node\", \"startTime\", \"endTime\", 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/biz/metrics/DashboardMetricsManagerTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics;\n\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.impl.DashboardMetricsManagerImpl;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardListDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.MetricsDashboardTopNDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContentCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.list.MetricList;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.list.MetricListContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.list.MetricListContentVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.list.MetricListVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.MetricsContentCellVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.MetricsContentVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.DashBoardMetricsService;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.context.SpringBootTest.WebEnvironment;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.when;\n\n@ActiveProfiles(\"test\")\n@ExtendWith({ SpringExtension.class, MockitoExtension.class })\n@MockitoSettings(strictness = Strictness.LENIENT)\n@RunWith(SpringRunner.class)\n@ContextConfiguration(classes = { SpringTool.class })\n@SpringBootTest(webEnvironment = WebEnvironment.NONE)\nclass DashboardMetricsManagerTest {\n\n    @Mock\n    private ProjectService              projectService;\n    @Mock\n    private DashBoardMetricsService     dashBoardMetricsService;\n    @Mock\n    private AriusConfigInfoService      ariusConfigInfoService;\n\n    @InjectMocks\n    private DashboardMetricsManagerImpl dashboardMetricsManager;\n\n    @Test\n    void getTopClusterMetricsInfoTest() {\n        // Setup\n        final MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n\n        // Configure DashBoardMetricsService.getToNMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(dashBoardMetricsService\n            .getToNMetrics(new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0), \"oneLevelType\"))\n                .thenReturn(variousLineChartMetrics);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = dashboardMetricsManager.getTopClusterMetricsInfo(param,\n            0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getTopClusterMetricsInfoDashBoardMetricsServiceReturnsNoItemsTest() {\n        // Setup\n        final MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0);\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n        when(dashBoardMetricsService\n            .getToNMetrics(new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0), \"oneLevelType\"))\n                .thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = dashboardMetricsManager.getTopClusterMetricsInfo(param,\n            0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n\n    @Test\n    void getTopNodeMetricsInfoTest() {\n        // Setup\n        final MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n\n        // Configure DashBoardMetricsService.getToNMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(dashBoardMetricsService\n            .getToNMetrics(new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0), \"oneLevelType\"))\n                .thenReturn(variousLineChartMetrics);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = dashboardMetricsManager.getTopNodeMetricsInfo(param, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getTopNodeMetricsInfoDashBoardMetricsServiceReturnsNoItemsTest() {\n        // Setup\n        final MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0);\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n        when(dashBoardMetricsService\n            .getToNMetrics(new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0), \"oneLevelType\"))\n                .thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = dashboardMetricsManager.getTopNodeMetricsInfo(param, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n\n    @Test\n    void getTopTemplateMetricsInfoTest() {\n        // Setup\n        final MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n\n        // Configure DashBoardMetricsService.getToNMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(dashBoardMetricsService\n            .getToNMetrics(new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0), \"oneLevelType\"))\n                .thenReturn(variousLineChartMetrics);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = dashboardMetricsManager.getTopTemplateMetricsInfo(param,\n            0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getTopTemplateMetricsInfoDashBoardMetricsServiceReturnsNoItemsTest() {\n        // Setup\n        final MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0);\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n        when(dashBoardMetricsService\n            .getToNMetrics(new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0), \"oneLevelType\"))\n                .thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = dashboardMetricsManager.getTopTemplateMetricsInfo(param,\n            0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n\n    @Test\n    void getTopIndexMetricsInfoTest() {\n        // Setup\n        final MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n\n        // Configure DashBoardMetricsService.getToNMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(dashBoardMetricsService\n            .getToNMetrics(new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0), \"oneLevelType\"))\n                .thenReturn(variousLineChartMetrics);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = dashboardMetricsManager.getTopIndexMetricsInfo(param, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getTopIndexMetricsInfoDashBoardMetricsServiceReturnsNoItemsTest() {\n        // Setup\n        final MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0);\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n        when(dashBoardMetricsService\n            .getToNMetrics(new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0), \"oneLevelType\"))\n                .thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = dashboardMetricsManager.getTopIndexMetricsInfo(param, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n\n    @Test\n    void getTopClusterThreadPoolQueueMetricsInfoTest() {\n        // Setup\n        final MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n\n        // Configure DashBoardMetricsService.getToNMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(dashBoardMetricsService\n            .getToNMetrics(new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0), \"oneLevelType\"))\n                .thenReturn(variousLineChartMetrics);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = dashboardMetricsManager\n            .getTopClusterThreadPoolQueueMetricsInfo(param, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getTopClusterThreadPoolQueueMetricsInfoDashBoardMetricsServiceReturnsNoItemsTest() {\n        // Setup\n        final MetricsDashboardTopNDTO param = new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0);\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n        when(dashBoardMetricsService\n            .getToNMetrics(new MetricsDashboardTopNDTO(0L, 0L, \"aggType\", Arrays.asList(\"value\"), 0), \"oneLevelType\"))\n                .thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = dashboardMetricsManager\n            .getTopClusterThreadPoolQueueMetricsInfo(param, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n\n    @Test\n    void getListClusterMetricsInfoTest() {\n        // Setup\n        final MetricsDashboardListDTO param = new MetricsDashboardListDTO(\"aggType\", false, Arrays.asList(\"value\"));\n        final Result<List<MetricListVO>> expectedResult = Result.buildFail(Arrays.asList(\n            new MetricListVO(0L, \"type\", Arrays.asList(new MetricListContentVO(\"clusterPhyName\", \"name\", 0.0)))));\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n\n        // Configure DashBoardMetricsService.getListFaultMetrics(...).\n        final MetricList metricList = new MetricList(0L, \"type\",\n            Arrays.asList(new MetricListContent(\"clusterPhyName\", \"name\", 0.0,0L)));\n        when(dashBoardMetricsService.getListFaultMetrics(\"oneLevelType\", \"metricsType\", \"aggType\", false))\n            .thenReturn(metricList);\n\n        // Configure DashBoardMetricsService.getListValueMetrics(...).\n        final MetricList metricList1 = new MetricList(0L, \"type\",\n            Arrays.asList(new MetricListContent(\"clusterPhyName\", \"name\", 0.0,0L)));\n        when(dashBoardMetricsService.getListValueMetrics(\"oneLevelType\", \"metricsType\", \"aggType\", false))\n            .thenReturn(metricList1);\n\n        when(ariusConfigInfoService.stringSetting(\"dashboard.threshold\", \"type\", \"defaultValue\")).thenReturn(\"result\");\n\n        // Run the test\n        final Result<List<MetricListVO>> result = dashboardMetricsManager.getListClusterMetricsInfo(param, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getListNodeMetricsInfoTest() {\n        // Setup\n        final MetricsDashboardListDTO param = new MetricsDashboardListDTO(\"aggType\", false, Arrays.asList(\"value\"));\n        final Result<List<MetricListVO>> expectedResult = Result.buildFail(Arrays.asList(\n            new MetricListVO(0L, \"type\", Arrays.asList(new MetricListContentVO(\"clusterPhyName\", \"name\", 0.0)))));\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n\n        // Configure DashBoardMetricsService.getListFaultMetrics(...).\n        final MetricList metricList = new MetricList(0L, \"type\",\n            Arrays.asList(new MetricListContent(\"clusterPhyName\", \"name\", 0.0,0L)));\n        when(dashBoardMetricsService.getListFaultMetrics(\"oneLevelType\", \"metricsType\", \"aggType\", false))\n            .thenReturn(metricList);\n\n        // Configure DashBoardMetricsService.getListValueMetrics(...).\n        final MetricList metricList1 = new MetricList(0L, \"type\",\n            Arrays.asList(new MetricListContent(\"clusterPhyName\", \"name\", 0.0,0L)));\n        when(dashBoardMetricsService.getListValueMetrics(\"oneLevelType\", \"metricsType\", \"aggType\", false))\n            .thenReturn(metricList1);\n\n        when(ariusConfigInfoService.stringSetting(\"dashboard.threshold\", \"type\", \"defaultValue\")).thenReturn(\"result\");\n\n        // Run the test\n        final Result<List<MetricListVO>> result = dashboardMetricsManager.getListNodeMetricsInfo(param, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getListTemplateMetricsInfoTest() {\n        // Setup\n        final MetricsDashboardListDTO param = new MetricsDashboardListDTO(\"aggType\", false, Arrays.asList(\"value\"));\n        final Result<List<MetricListVO>> expectedResult = Result.buildFail(Arrays.asList(\n            new MetricListVO(0L, \"type\", Arrays.asList(new MetricListContentVO(\"clusterPhyName\", \"name\", 0.0)))));\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n\n        // Configure DashBoardMetricsService.getListFaultMetrics(...).\n        final MetricList metricList = new MetricList(0L, \"type\",\n            Arrays.asList(new MetricListContent(\"clusterPhyName\", \"name\", 0.0,0L)));\n        when(dashBoardMetricsService.getListFaultMetrics(\"oneLevelType\", \"metricsType\", \"aggType\", false))\n            .thenReturn(metricList);\n\n        // Configure DashBoardMetricsService.getListValueMetrics(...).\n        final MetricList metricList1 = new MetricList(0L, \"type\",\n            Arrays.asList(new MetricListContent(\"clusterPhyName\", \"name\", 0.0,0L)));\n        when(dashBoardMetricsService.getListValueMetrics(\"oneLevelType\", \"metricsType\", \"aggType\", false))\n            .thenReturn(metricList1);\n\n        when(ariusConfigInfoService.stringSetting(\"dashboard.threshold\", \"type\", \"defaultValue\")).thenReturn(\"result\");\n\n        // Run the test\n        final Result<List<MetricListVO>> result = dashboardMetricsManager.getListTemplateMetricsInfo(param, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getListIndexMetricsInfoTest() {\n        // Setup\n        final MetricsDashboardListDTO param = new MetricsDashboardListDTO(\"aggType\", false, Arrays.asList(\"value\"));\n        final Result<List<MetricListVO>> expectedResult = Result.buildFail(Arrays.asList(\n            new MetricListVO(0L, \"type\", Arrays.asList(new MetricListContentVO(\"clusterPhyName\", \"name\", 0.0)))));\n        when(projectService.checkProjectExist(0)).thenReturn(false);\n\n        // Configure DashBoardMetricsService.getListFaultMetrics(...).\n        final MetricList metricList = new MetricList(0L, \"type\",\n            Arrays.asList(new MetricListContent(\"clusterPhyName\", \"name\", 0.0,0L)));\n        when(dashBoardMetricsService.getListFaultMetrics(\"oneLevelType\", \"metricsType\", \"aggType\", false))\n            .thenReturn(metricList);\n\n        // Configure DashBoardMetricsService.getListValueMetrics(...).\n        final MetricList metricList1 = new MetricList(0L, \"type\",\n            Arrays.asList(new MetricListContent(\"clusterPhyName\", \"name\", 0.0,0L)));\n        when(dashBoardMetricsService.getListValueMetrics(\"oneLevelType\", \"metricsType\", \"aggType\", false))\n            .thenReturn(metricList1);\n\n        when(ariusConfigInfoService.stringSetting(\"dashboard.threshold\", \"type\", \"defaultValue\")).thenReturn(\"result\");\n\n        // Run the test\n        final Result<List<MetricListVO>> result = dashboardMetricsManager.getListIndexMetricsInfo(param, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/biz/metrics/GatewayMetricsManagerTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.metrics;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.when;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.context.SpringBootTest.WebEnvironment;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport com.didichuxing.datachannel.arius.admin.biz.gateway.GatewayManager;\nimport com.didichuxing.datachannel.arius.admin.biz.metrics.impl.GatewayMetricsManagerImpl;\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplateLogicManager;\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.*;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.GatewayOverviewMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContent;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.MetricsContentCell;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.linechart.VariousLineChartMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.other.gateway.GatewayOverviewMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.MetricsContentCellVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.MetricsContentVO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.metrics.top.VariousLineChartMetricsVO;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.GatewayMetricsService;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\n\n@ActiveProfiles(\"test\")\n@ExtendWith({ SpringExtension.class, MockitoExtension.class })\n@MockitoSettings(strictness = Strictness.LENIENT)\n@RunWith(SpringRunner.class)\n@ContextConfiguration(classes = { SpringTool.class })\n@SpringBootTest(webEnvironment = WebEnvironment.NONE)\nclass GatewayMetricsManagerTest {\n\n    @Mock\n    private GatewayMetricsService     gatewayMetricsService;\n    @Mock\n    private GatewayManager            gatewayManager;\n    @Mock\n    private ProjectService            projectService;\n    @Mock\n    private TemplateLogicManager      templateLogicManager;\n\n    @InjectMocks\n    private GatewayMetricsManagerImpl gatewayMetricsManager;\n\n    @Test\n    void getGatewayMetricsEnumsTest() {\n        // Setup\n        final Result<List<String>> expectedResult = Result.buildFail(Arrays.asList(\"value\"));\n\n        // Run the test\n        final Result<List<String>> result = gatewayMetricsManager.getGatewayMetricsEnums(\"group\");\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getDslMd5ListTest() {\n        // Setup\n        final Result<List<String>> expectedResult = Result.buildFail(Arrays.asList(\"value\"));\n        when(gatewayMetricsService.getDslMd5List(0L, 0L, 0)).thenReturn(Arrays.asList(\"value\"));\n\n        // Run the test\n        final Result<List<String>> result = gatewayMetricsManager.getDslMd5List(0, 0L, 0L);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getDslMd5ListGatewayMetricsServiceReturnsNoItemsTest() {\n        // Setup\n        when(gatewayMetricsService.getDslMd5List(0L, 0L, 0)).thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<String>> result = gatewayMetricsManager.getDslMd5List(0, 0L, 0L);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n\n    @Test\n    void getGatewayOverviewMetricsTest() {\n        // Setup\n        final GatewayOverviewDTO dto = new GatewayOverviewDTO();\n        dto.setStartTime(0L);\n        dto.setEndTime(0L);\n        dto.setMetricsTypes(Arrays.asList(\"value\"));\n\n        final Result<List<GatewayOverviewMetricsVO>> expectedResult = Result.buildFail(\n            Arrays.asList(new GatewayOverviewMetricsVO(\"type\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))));\n\n        // Configure GatewayMetricsService.getOverviewCommonMetrics(...).\n        final List<GatewayOverviewMetrics> gatewayOverviewMetrics = Arrays\n            .asList(new GatewayOverviewMetrics(\"type\", Arrays.asList(new MetricsContentCell(0.0, 0L))));\n        when(gatewayMetricsService.getOverviewCommonMetrics(Arrays.asList(\"value\"), 0L, 0L))\n            .thenReturn(gatewayOverviewMetrics);\n\n        // Configure GatewayMetricsService.getOverviewWriteMetrics(...).\n        final List<GatewayOverviewMetrics> gatewayOverviewMetrics1 = Arrays\n            .asList(new GatewayOverviewMetrics(\"type\", Arrays.asList(new MetricsContentCell(0.0, 0L))));\n        when(gatewayMetricsService.getOverviewWriteMetrics(Arrays.asList(\"value\"), 0L, 0L))\n            .thenReturn(gatewayOverviewMetrics1);\n\n        // Configure GatewayMetricsService.getOverviewReadCountMetrics(...).\n        final GatewayOverviewMetrics gatewayOverviewMetrics2 = new GatewayOverviewMetrics(\"type\",\n            Arrays.asList(new MetricsContentCell(0.0, 0L)));\n        when(gatewayMetricsService.getOverviewReadCountMetrics(0L, 0L)).thenReturn(gatewayOverviewMetrics2);\n\n        // Configure GatewayMetricsService.getOverviewSearchTypeMetrics(...).\n        final GatewayOverviewMetrics gatewayOverviewMetrics3 = new GatewayOverviewMetrics(\"type\",\n            Arrays.asList(new MetricsContentCell(0.0, 0L)));\n        when(gatewayMetricsService.getOverviewSearchTypeMetrics(0L, 0L)).thenReturn(gatewayOverviewMetrics3);\n\n        // Run the test\n        final Result<List<GatewayOverviewMetricsVO>> result = gatewayMetricsManager.getGatewayOverviewMetrics(dto);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayOverviewMetricsGatewayMetricsServiceGetOverviewCommonMetricsReturnsNoItemsTest() {\n        // Setup\n        final GatewayOverviewDTO dto = new GatewayOverviewDTO();\n        dto.setStartTime(0L);\n        dto.setEndTime(0L);\n        dto.setMetricsTypes(Arrays.asList(\"value\"));\n\n        final Result<List<GatewayOverviewMetricsVO>> expectedResult = Result.buildFail(\n            Arrays.asList(new GatewayOverviewMetricsVO(\"type\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))));\n        when(gatewayMetricsService.getOverviewCommonMetrics(Arrays.asList(\"value\"), 0L, 0L))\n            .thenReturn(Collections.emptyList());\n\n        // Configure GatewayMetricsService.getOverviewWriteMetrics(...).\n        final List<GatewayOverviewMetrics> gatewayOverviewMetrics = Arrays\n            .asList(new GatewayOverviewMetrics(\"type\", Arrays.asList(new MetricsContentCell(0.0, 0L))));\n        when(gatewayMetricsService.getOverviewWriteMetrics(Arrays.asList(\"value\"), 0L, 0L))\n            .thenReturn(gatewayOverviewMetrics);\n\n        // Configure GatewayMetricsService.getOverviewReadCountMetrics(...).\n        final GatewayOverviewMetrics gatewayOverviewMetrics1 = new GatewayOverviewMetrics(\"type\",\n            Arrays.asList(new MetricsContentCell(0.0, 0L)));\n        when(gatewayMetricsService.getOverviewReadCountMetrics(0L, 0L)).thenReturn(gatewayOverviewMetrics1);\n\n        // Configure GatewayMetricsService.getOverviewSearchTypeMetrics(...).\n        final GatewayOverviewMetrics gatewayOverviewMetrics2 = new GatewayOverviewMetrics(\"type\",\n            Arrays.asList(new MetricsContentCell(0.0, 0L)));\n        when(gatewayMetricsService.getOverviewSearchTypeMetrics(0L, 0L)).thenReturn(gatewayOverviewMetrics2);\n\n        // Run the test\n        final Result<List<GatewayOverviewMetricsVO>> result = gatewayMetricsManager.getGatewayOverviewMetrics(dto);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayOverviewMetricsGatewayMetricsServiceGetOverviewWriteMetricsReturnsNoItemsTest() {\n        // Setup\n        final GatewayOverviewDTO dto = new GatewayOverviewDTO();\n        dto.setStartTime(0L);\n        dto.setEndTime(0L);\n        dto.setMetricsTypes(Arrays.asList(\"value\"));\n\n        final Result<List<GatewayOverviewMetricsVO>> expectedResult = Result.buildFail(\n            Arrays.asList(new GatewayOverviewMetricsVO(\"type\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))));\n\n        // Configure GatewayMetricsService.getOverviewCommonMetrics(...).\n        final List<GatewayOverviewMetrics> gatewayOverviewMetrics = Arrays\n            .asList(new GatewayOverviewMetrics(\"type\", Arrays.asList(new MetricsContentCell(0.0, 0L))));\n        when(gatewayMetricsService.getOverviewCommonMetrics(Arrays.asList(\"value\"), 0L, 0L))\n            .thenReturn(gatewayOverviewMetrics);\n\n        when(gatewayMetricsService.getOverviewWriteMetrics(Arrays.asList(\"value\"), 0L, 0L))\n            .thenReturn(Collections.emptyList());\n\n        // Configure GatewayMetricsService.getOverviewReadCountMetrics(...).\n        final GatewayOverviewMetrics gatewayOverviewMetrics1 = new GatewayOverviewMetrics(\"type\",\n            Arrays.asList(new MetricsContentCell(0.0, 0L)));\n        when(gatewayMetricsService.getOverviewReadCountMetrics(0L, 0L)).thenReturn(gatewayOverviewMetrics1);\n\n        // Configure GatewayMetricsService.getOverviewSearchTypeMetrics(...).\n        final GatewayOverviewMetrics gatewayOverviewMetrics2 = new GatewayOverviewMetrics(\"type\",\n            Arrays.asList(new MetricsContentCell(0.0, 0L)));\n        when(gatewayMetricsService.getOverviewSearchTypeMetrics(0L, 0L)).thenReturn(gatewayOverviewMetrics2);\n\n        // Run the test\n        final Result<List<GatewayOverviewMetricsVO>> result = gatewayMetricsManager.getGatewayOverviewMetrics(dto);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayNodeMetricsTest() {\n        // Setup\n        final GatewayNodeDTO dto = new GatewayNodeDTO(\"nodeIp\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics3);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics4 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics4);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics5 = new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics5);\n\n        when(gatewayManager.getGatewayAliveNodeNames(\"Normal\")).thenReturn(Result.buildFail(Arrays.asList(\"value\")));\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayNodeMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayNodeMetricsGatewayManagerReturnsNoItemTest() {\n        // Setup\n        final GatewayNodeDTO dto = new GatewayNodeDTO(\"nodeIp\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics3);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics4 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics4);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics5 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics5);\n\n        when(gatewayManager.getGatewayAliveNodeNames(\"Normal\")).thenReturn(Result.buildSucc());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayNodeMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayNodeMetricsGatewayManagerReturnsNoItemsTest() {\n        // Setup\n        final GatewayNodeDTO dto = new GatewayNodeDTO(\"nodeIp\", 0);\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics3);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics4 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics4);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics5 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics5);\n\n        when(gatewayManager.getGatewayAliveNodeNames(\"Normal\")).thenReturn(Result.buildFail(Collections.emptyList()));\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayNodeMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n\n    @Test\n    void getGatewayNodeMetricsGatewayManagerReturnsFailureTest() {\n        // Setup\n        final GatewayNodeDTO dto = new GatewayNodeDTO(\"nodeIp\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics3);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics4 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics4);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics5 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics5);\n\n        when(gatewayManager.getGatewayAliveNodeNames(\"Normal\")).thenReturn(Result.buildFail());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayNodeMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiGatewayNodesMetricsTest() {\n        // Setup\n        final MultiGatewayNodesDTO dto = new MultiGatewayNodesDTO(Arrays.asList(\"value\"), 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics3);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics4 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics4);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics5 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics5);\n\n        when(gatewayManager.getGatewayAliveNodeNames(\"Normal\")).thenReturn(Result.buildFail(Arrays.asList(\"value\")));\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getMultiGatewayNodesMetrics(dto,\n            0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiGatewayNodesMetricsGatewayManagerReturnsNoItemTest() {\n        // Setup\n        final MultiGatewayNodesDTO dto = new MultiGatewayNodesDTO(Arrays.asList(\"value\"), 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics3);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics4 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics4);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics5 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics5);\n\n        when(gatewayManager.getGatewayAliveNodeNames(\"Normal\")).thenReturn(Result.buildSucc());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getMultiGatewayNodesMetrics(dto,\n            0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getMultiGatewayNodesMetricsGatewayManagerReturnsNoItemsTest() {\n        // Setup\n        final MultiGatewayNodesDTO dto = new MultiGatewayNodesDTO(Arrays.asList(\"value\"), 0);\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics3);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics4 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics4);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics5 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics5);\n\n        when(gatewayManager.getGatewayAliveNodeNames(\"Normal\")).thenReturn(Result.buildFail(Collections.emptyList()));\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getMultiGatewayNodesMetrics(dto,\n            0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n\n    @Test\n    void getMultiGatewayNodesMetricsGatewayManagerReturnsFailureTest() {\n        // Setup\n        final MultiGatewayNodesDTO dto = new MultiGatewayNodesDTO(Arrays.asList(\"value\"), 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getGatewayNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeWriteMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics3);\n\n        // Configure GatewayMetricsService.getGatewayNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics4 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics4);\n\n        // Configure GatewayMetricsService.getGatewayNodeDSLLenMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics5 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getGatewayNodeDSLLenMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics5);\n\n        when(gatewayManager.getGatewayAliveNodeNames(\"Normal\")).thenReturn(Result.buildFail());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getMultiGatewayNodesMetrics(dto,\n            0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getClientNodeMetricsTest() {\n        // Setup\n        final ClientNodeDTO dto = new ClientNodeDTO(\"clientNodeIp\");\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getClientNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeWriteMetrics(0L, 0L, 0, \"nodeIp\", \"clientNodeIp\"))\n            .thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getClientNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeMetrics(0L, 0L, 0, \"nodeIp\", \"clientNodeIp\"))\n            .thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getClientNodeDSLLENMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeDSLLENMetrics(0L, 0L, 0, \"nodeIp\", \"clientNodeIp\"))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getClientNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeWriteMetrics(0L, 0L, 0, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics3);\n\n        // Configure GatewayMetricsService.getClientNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics4 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeMetrics(0L, 0L, 0, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics4);\n\n        // Configure GatewayMetricsService.getClientNodeDSLLENMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics5 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeDSLLENMetrics(0L, 0L, 0, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics5);\n\n        when(gatewayMetricsService.getEsClientNodeIpListByGatewayNode(\"nodeIp\", 0L, 0L, 0))\n            .thenReturn(Collections.singletonList(new Tuple<>(\"value1\", \"value\")));\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getClientNodeMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getClientNodeMetricsGatewayMetricsServiceGetEsClientNodeIpListByGatewayNodeReturnsNoItemsTest() {\n        // Setup\n        final ClientNodeDTO dto = new ClientNodeDTO(\"clientNodeIp\");\n\n        // Configure GatewayMetricsService.getClientNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeWriteMetrics(0L, 0L, 0, \"nodeIp\", \"clientNodeIp\"))\n            .thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getClientNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeMetrics(0L, 0L, 0, \"nodeIp\", \"clientNodeIp\"))\n            .thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getClientNodeDSLLENMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeDSLLENMetrics(0L, 0L, 0, \"nodeIp\", \"clientNodeIp\"))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getClientNodeWriteMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeWriteMetrics(0L, 0L, 0, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics3);\n\n        // Configure GatewayMetricsService.getClientNodeMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics4 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeMetrics(0L, 0L, 0, 0, \"nodeIp\")).thenReturn(variousLineChartMetrics4);\n\n        // Configure GatewayMetricsService.getClientNodeDSLLENMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics5 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getClientNodeDSLLENMetrics(0L, 0L, 0, 0, \"nodeIp\"))\n            .thenReturn(variousLineChartMetrics5);\n\n        when(gatewayMetricsService.getEsClientNodeIpListByGatewayNode(\"nodeIp\", 0L, 0L, 0))\n            .thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getClientNodeMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n\n    @Test\n    void getGatewayIndexMetricsTest() {\n        // Setup\n        final GatewayIndexDTO dto = new GatewayIndexDTO(\"indexName\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getGatewayIndexWriteMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexWriteMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, \"indexName\"))\n            .thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayIndexSearchMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics1 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexSearchMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, \"indexName\"))\n            .thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayIndexWriteMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics2 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexWriteMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, 0))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getGatewayIndexSearchMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics3 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexSearchMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, 0))\n            .thenReturn(variousLineChartMetrics3);\n\n        when(templateLogicManager.getTemplateLogicNames(0)).thenReturn(Arrays.asList(\"value\"));\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayIndexMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayIndexMetricsGatewayMetricsServiceGetGatewayIndexWriteMetricsReturnsNoItemsTest() {\n        // Setup\n        final GatewayIndexDTO dto = new GatewayIndexDTO(\"indexName\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getGatewayIndexWriteMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexWriteMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, \"indexName\"))\n            .thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayIndexSearchMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics1 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexSearchMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, \"indexName\"))\n            .thenReturn(variousLineChartMetrics1);\n\n        when(gatewayMetricsService.getGatewayIndexWriteMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, 0))\n            .thenReturn(Collections.emptyList());\n\n        // Configure GatewayMetricsService.getGatewayIndexSearchMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics2 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexSearchMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, 0))\n            .thenReturn(variousLineChartMetrics2);\n\n        when(templateLogicManager.getTemplateLogicNames(0)).thenReturn(Arrays.asList(\"value\"));\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayIndexMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayIndexMetricsGatewayMetricsServiceGetGatewayIndexSearchMetricsReturnsNoItemsTest() {\n        // Setup\n        final GatewayIndexDTO dto = new GatewayIndexDTO(\"indexName\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getGatewayIndexWriteMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexWriteMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, \"indexName\"))\n            .thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayIndexSearchMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics1 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexSearchMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, \"indexName\"))\n            .thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayIndexWriteMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics2 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexWriteMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, 0))\n            .thenReturn(variousLineChartMetrics2);\n\n        when(gatewayMetricsService.getGatewayIndexSearchMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, 0))\n            .thenReturn(Collections.emptyList());\n        when(templateLogicManager.getTemplateLogicNames(0)).thenReturn(Arrays.asList(\"value\"));\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayIndexMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayIndexMetricsTemplateLogicManagerReturnsNoItemsTest() {\n        // Setup\n        final GatewayIndexDTO dto = new GatewayIndexDTO(\"indexName\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getGatewayIndexWriteMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexWriteMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, \"indexName\"))\n            .thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getGatewayIndexSearchMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics1 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexSearchMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, \"indexName\"))\n            .thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getGatewayIndexWriteMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics2 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexWriteMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, 0))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getGatewayIndexSearchMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics3 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getGatewayIndexSearchMetrics(Arrays.asList(\"value\"), 0L, 0L, 0, 0))\n            .thenReturn(variousLineChartMetrics3);\n\n        when(templateLogicManager.getTemplateLogicNames(0)).thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayIndexMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayAppMetricsTest() {\n        // Setup\n        final GatewayProjectDTO dto = new GatewayProjectDTO(\"projectId\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getAppCommonMetricsByProjectId(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getAppCommonMetricsByProjectId(0L, 0L, Arrays.asList(\"value\"), \"projectId\"))\n            .thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getAppCountMetricsByProjectId(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getAppCountMetricsByProjectId(0L, 0L, \"projectId\"))\n            .thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getAppCommonMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics2 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getAppCommonMetrics(0L, 0L, Arrays.asList(\"value\"), 0))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getAppCountMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getAppCountMetrics(0L, 0L, 0)).thenReturn(variousLineChartMetrics3);\n\n        // Configure ProjectService.getProjectBriefList(...).\n        final ProjectBriefVO projectBriefVO = new ProjectBriefVO();\n        projectBriefVO.setId(0);\n        projectBriefVO.setProjectCode(\"projectCode\");\n        projectBriefVO.setProjectName(\"projectName\");\n        final List<ProjectBriefVO> projectBriefVOS = Arrays.asList(projectBriefVO);\n        when(projectService.getProjectBriefList()).thenReturn(projectBriefVOS);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayAppMetrics(dto);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayAppMetricsGatewayMetricsServiceGetAppCommonMetricsByProjectIdReturnsNoItemsTest() {\n        // Setup\n        final GatewayProjectDTO dto = new GatewayProjectDTO(\"projectId\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n        when(gatewayMetricsService.getAppCommonMetricsByProjectId(0L, 0L, Arrays.asList(\"value\"), \"projectId\"))\n            .thenReturn(Collections.emptyList());\n\n        // Configure GatewayMetricsService.getAppCountMetricsByProjectId(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getAppCountMetricsByProjectId(0L, 0L, \"projectId\"))\n            .thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getAppCommonMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics1 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getAppCommonMetrics(0L, 0L, Arrays.asList(\"value\"), 0))\n            .thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getAppCountMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getAppCountMetrics(0L, 0L, 0)).thenReturn(variousLineChartMetrics2);\n\n        // Configure ProjectService.getProjectBriefList(...).\n        final ProjectBriefVO projectBriefVO = new ProjectBriefVO();\n        projectBriefVO.setId(0);\n        projectBriefVO.setProjectCode(\"projectCode\");\n        projectBriefVO.setProjectName(\"projectName\");\n        final List<ProjectBriefVO> projectBriefVOS = Arrays.asList(projectBriefVO);\n        when(projectService.getProjectBriefList()).thenReturn(projectBriefVOS);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayAppMetrics(dto);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayAppMetricsGatewayMetricsServiceGetAppCommonMetricsReturnsNoItemsTest() {\n        // Setup\n        final GatewayProjectDTO dto = new GatewayProjectDTO(\"projectId\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getAppCommonMetricsByProjectId(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getAppCommonMetricsByProjectId(0L, 0L, Arrays.asList(\"value\"), \"projectId\"))\n            .thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getAppCountMetricsByProjectId(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getAppCountMetricsByProjectId(0L, 0L, \"projectId\"))\n            .thenReturn(variousLineChartMetrics1);\n\n        when(gatewayMetricsService.getAppCommonMetrics(0L, 0L, Arrays.asList(\"value\"), 0))\n            .thenReturn(Collections.emptyList());\n\n        // Configure GatewayMetricsService.getAppCountMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getAppCountMetrics(0L, 0L, 0)).thenReturn(variousLineChartMetrics2);\n\n        // Configure ProjectService.getProjectBriefList(...).\n        final ProjectBriefVO projectBriefVO = new ProjectBriefVO();\n        projectBriefVO.setId(0);\n        projectBriefVO.setProjectCode(\"projectCode\");\n        projectBriefVO.setProjectName(\"projectName\");\n        final List<ProjectBriefVO> projectBriefVOS = Arrays.asList(projectBriefVO);\n        when(projectService.getProjectBriefList()).thenReturn(projectBriefVOS);\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayAppMetrics(dto);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayAppMetricsProjectServiceReturnsNoItemsTest() {\n        // Setup\n        final GatewayProjectDTO dto = new GatewayProjectDTO(\"projectId\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getAppCommonMetricsByProjectId(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getAppCommonMetricsByProjectId(0L, 0L, Arrays.asList(\"value\"), \"projectId\"))\n            .thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getAppCountMetricsByProjectId(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getAppCountMetricsByProjectId(0L, 0L, \"projectId\"))\n            .thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getAppCommonMetrics(...).\n        final List<VariousLineChartMetrics> variousLineChartMetrics2 = Arrays.asList(new VariousLineChartMetrics(\"type\",\n            Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L))));\n        when(gatewayMetricsService.getAppCommonMetrics(0L, 0L, Arrays.asList(\"value\"), 0))\n            .thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getAppCountMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getAppCountMetrics(0L, 0L, 0)).thenReturn(variousLineChartMetrics3);\n\n        when(projectService.getProjectBriefList()).thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayAppMetrics(dto);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayDslMetricsTest() {\n        // Setup\n        final GatewayDslDTO dto = new GatewayDslDTO(\"dslMd5\", 0);\n        final Result<List<VariousLineChartMetricsVO>> expectedResult = Result\n            .buildFail(Arrays.asList(new VariousLineChartMetricsVO(\"type\", Arrays\n                .asList(new MetricsContentVO(\"cluster\", \"name\", Arrays.asList(new MetricsContentCellVO(0.0, 0L)))))));\n\n        // Configure GatewayMetricsService.getDslCountMetricsByMd5(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getDslCountMetricsByMd5(0L, 0L, \"dslMd5\", 0)).thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getDslTotalCostMetricsByMd5(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getDslTotalCostMetricsByMd5(0L, 0L, \"dslMd5\", 0))\n            .thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getDslCountMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getDslCountMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getDslTotalCostMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getDslTotalCostMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics3);\n\n        when(gatewayMetricsService.getDslMd5List(0L, 0L, 0)).thenReturn(Arrays.asList(\"value\"));\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayDslMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getGatewayDslMetricsGatewayMetricsServiceGetDslMd5ListReturnsNoItemsTest() {\n        // Setup\n        final GatewayDslDTO dto = new GatewayDslDTO(\"dslMd5\", 0);\n\n        // Configure GatewayMetricsService.getDslCountMetricsByMd5(...).\n        final VariousLineChartMetrics variousLineChartMetrics = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getDslCountMetricsByMd5(0L, 0L, \"dslMd5\", 0)).thenReturn(variousLineChartMetrics);\n\n        // Configure GatewayMetricsService.getDslTotalCostMetricsByMd5(...).\n        final VariousLineChartMetrics variousLineChartMetrics1 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getDslTotalCostMetricsByMd5(0L, 0L, \"dslMd5\", 0))\n            .thenReturn(variousLineChartMetrics1);\n\n        // Configure GatewayMetricsService.getDslCountMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics2 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getDslCountMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics2);\n\n        // Configure GatewayMetricsService.getDslTotalCostMetrics(...).\n        final VariousLineChartMetrics variousLineChartMetrics3 = new VariousLineChartMetrics(\"type\",\n           Arrays.asList(new MetricsContent(\"cluster\", \"name\", Arrays.asList(new MetricsContentCell(0.0, 0L)), 0.0,0L)));\n        when(gatewayMetricsService.getDslTotalCostMetrics(0L, 0L, 0, 0)).thenReturn(variousLineChartMetrics3);\n\n        when(gatewayMetricsService.getDslMd5List(0L, 0L, 0)).thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<VariousLineChartMetricsVO>> result = gatewayMetricsManager.getGatewayDslMetrics(dto, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n\n    @Test\n    void getClientNodeIdListTest() {\n        // Setup\n        final Result<List<Tuple<String, String>>> expectedResult = Result.buildFail(Collections.singletonList(new Tuple<>(\"value1\", \"value\")));\n        when(gatewayMetricsService.getEsClientNodeIpListByGatewayNode(\"gatewayNode\", 0L, 0L, 0))\n            .thenReturn(Collections.singletonList(new Tuple<>(\"value1\", \"value\")));\n\n        // Run the test\n        final Result<List<Tuple<String, String>>> result = gatewayMetricsManager.getClientNodeIdList(\"gatewayNode\", 0L, 0L, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void getClientNodeIdListGatewayMetricsServiceReturnsNoItemsTest() {\n        // Setup\n        when(gatewayMetricsService.getEsClientNodeIpListByGatewayNode(\"gatewayNode\", 0L, 0L, 0))\n            .thenReturn(Collections.emptyList());\n\n        // Run the test\n        final Result<List<Tuple<String, String>>> result = gatewayMetricsManager.getClientNodeIdList(\"gatewayNode\", 0L, 0L, 0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Result.buildFail(Collections.emptyList()));\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/biz/project/ESUserManagerTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.anyList;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.when;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.impl.ESUserManagerImpl;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ESUserDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ConsoleESUserVO;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.Tuples;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.RoleTool;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ESUserService;\nimport com.didichuxing.datachannel.arius.admin.util.CustomDataSource;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectVO;\nimport com.didiglobal.knowframework.security.service.ProjectService;\nimport java.util.stream.Collectors;\nimport org.assertj.core.util.Lists;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.context.SpringBootTest.WebEnvironment;\nimport org.springframework.boot.test.mock.mockito.MockBean;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@ActiveProfiles(\"test\")\n@ExtendWith({ SpringExtension.class, MockitoExtension.class })\n@MockitoSettings(strictness = Strictness.LENIENT)\n@RunWith(SpringRunner.class)\n@ContextConfiguration(classes = { SpringTool.class })\n@SpringBootTest(webEnvironment = WebEnvironment.NONE)\nclass ESUserManagerTest {\n\n    @Mock\n    private ProjectService       projectService;\n\n    @Mock\n    private ESUserService        esUserService;\n    @Mock\n    private RoleTool             roleTool;\n    @MockBean\n    private OperateRecordService operateRecordService;\n    @InjectMocks\n    private ESUserManagerImpl    esUserManager;\n\n    @Test\n    void testListESUsersByProjectId() {\n        final ESUserPO esUserPO = CustomDataSource.esUserPO();\n        final ESUser esUser = ConvertUtil.obj2Obj(esUserPO, ESUser.class);\n        final ProjectVO projectVO = CustomDataSource.projectVO();\n        String projectStr = 1 + \"\";\n\n        when(projectService.getProjectDetailByProjectId(anyInt())).thenReturn(null);\n\n        when(roleTool.isAdmin(anyString())).thenReturn(false);\n        /**\n        Assertions.assertEquals(Result.buildParamIllegal(String.format(\"项目:[%s]不存在成员:[%s]\", 1, \"aaaa\")).getMessage(),\n        \t\tesUserManager.listESUsersByProjectId(1+\"\", \"aaaa\").getMessage());\n        when(roleTool.isAdmin(anyString())).thenReturn(false);\n        when(projectService.getProjectDetailByProjectId(anyInt())).thenReturn(CustomDataSource.projectVO());\n        \n        Assertions.assertEquals(Result.buildParamIllegal(String.format(\"项目:[%s]不存在成员:[%s]\", 1, \"aaaa\")).getMessage(),\n        \t\tesUserManager.listESUsersByProjectId(1, \"aaaa\").getMessage());\n        when(roleTool.isAdmin(anyString())).thenReturn(true);\n        when(projectService.getProjectDetailByProjectId(anyInt())).thenReturn(null);\n        Assertions.assertTrue(esUserManager.listESUsersByProjectId(1, \"aaaa\").success());\n        when(roleTool.isAdmin(anyString())).thenReturn(false);\n        when(projectService.getProjectDetailByProjectId(anyInt())).thenReturn(projectVO);\n        when(esUserService.listESUsers(anyList())).thenReturn(Lists.newArrayList(esUser));\n        when(roleTool.isAdmin(anyString())).thenReturn(false);\n        Assertions.assertTrue(esUserManager.listESUsersByProjectId(1, \"admin\").success());\n         **/\n\n    }\n\n    @Test\n    void testRegisterESUser() {\n        final ESUserPO esUserPO = CustomDataSource.esUserPO();\n        final ESUserDTO esUserDTO = ConvertUtil.obj2Obj(esUserPO, ESUserDTO.class);\n        when(roleTool.isAdmin(anyString())).thenReturn(false);\n        Assertions.assertEquals(\n            Result.buildParamIllegal(String.format(\"当前操作[%s] 不能创建es user\")).getMessage(),\n            esUserManager.registerESUser(esUserDTO, 1, \"admin\").getMessage());\n        when(roleTool.isAdmin(anyString())).thenReturn(true);\n        when(esUserService.validateESUser(any(), any())).thenReturn(Result.buildParamIllegal(\"应用信息为空\"));\n        when(esUserService.registerESUser(null, null))\n            .thenReturn(Tuples.of(Result.buildParamIllegal(\"应用信息为空\"), esUserPO));\n        Assertions.assertEquals(Result.buildParamIllegal(\"应用信息为空\").getMessage(),\n            esUserManager.registerESUser(null, null, null).getMessage());\n        when(esUserService.registerESUser(any(), anyString())).thenReturn(Tuples.of(Result.buildSucc(1), esUserPO));\n        Assertions.assertTrue(esUserManager.registerESUser(esUserDTO, 1, \"a\").success());\n    }\n\n    @Test\n    void testEditESUser() {\n        final ESUserPO esUserPO = CustomDataSource.esUserPO();\n        final ESUserDTO esUserDTO = ConvertUtil.obj2Obj(esUserPO, ESUserDTO.class);\n        when(projectService.checkProjectExist(anyInt())).thenReturn(false);\n        when(esUserService.validateESUser(any(), any())).thenReturn(Result.buildFail(\"应用不存在\"));\n        Assertions.assertEquals(Result.buildFail(\"应用不存在\").getMessage(),\n            esUserManager.editESUser(esUserDTO, \"admin\").getMessage());\n        when(esUserService.validateESUser(any(), any())).thenReturn(Result.buildSucc());\n        when(esUserService.editUser(any())).thenReturn(Tuples.of(Result.buildSucc(), esUserPO));\n        Assertions\n            .assertTrue(Assertions.assertDoesNotThrow(() -> esUserManager.editESUser(esUserDTO, \"admin\").success()));\n\n    }\n\n    @Test\n    void testDeleteESUserByProject() {\n        final ESUserPO esUserPO = CustomDataSource.esUserPO();\n        final ProjectVO projectVO = CustomDataSource.projectVO();\n        final ESUser esUser = ConvertUtil.obj2Obj(esUserPO, ESUser.class);\n\n        Assertions.assertEquals(Result.buildFail(\"当前操作者权限不足,需要管理员权限\"), esUserManager.deleteESUserByProject(1, 1, null));\n        when(esUserService.listESUsers(anyList())).thenReturn(Lists.newArrayList(esUser));\n        when(roleTool.isAdmin(\"admin\")).thenReturn(true);\n        Assertions.assertEquals(Result.buildFail(String.format(\"当前项目[%s]下只存在一个es user,不能被删除\", 1)).getMessage(),\n            esUserManager.deleteESUserByProject(1, 1, \"admin\").getMessage());\n        esUser.setDefaultDisplay(true);\n        esUser.setId(1);\n        when(esUserService.listESUsers(anyList())).thenReturn(Lists.newArrayList(esUser, esUser));\n        Assertions.assertEquals(Result\n            .buildParamIllegal(String.format(\"当前项目[%s]不存在es user:[%s]\", 1,\n                Lists.newArrayList(esUser, esUser).stream().map(ESUser::getId).collect(Collectors.toList())))\n            .getMessage(), esUserManager.deleteESUserByProject(2, 1, \"admin\").getMessage());\n\n        when(esUserService.listESUsers(anyList())).thenReturn(Lists.newArrayList(esUser, esUser));\n        Assertions.assertEquals(\n            Result.buildFail(String.format(\"项目[%s]中es user:[%s],属于项目默认的es user,请先进行解绑\", 1, 1)).getMessage(),\n            esUserManager.deleteESUserByProject(1, 1, \"admin\").getMessage());\n        esUser.setDefaultDisplay(false);\n        when(esUserService.listESUsers(anyList())).thenReturn(Lists.newArrayList(esUser, esUser));\n        when(esUserService.deleteESUserById(1)).thenReturn(Tuples.of(Result.buildSucc(), esUserPO));\n        Assertions.assertTrue(esUserManager.deleteESUserByProject(1, 1, \"admin\").success());\n\n    }\n\n    @Test\n    void testDeleteAllESUserByProject() {\n        when(roleTool.isAdmin(\"admin\")).thenReturn(true);\n        when(roleTool.isAdmin(\"\")).thenReturn(false);\n        when(esUserService.deleteByESUsers(anyInt()))\n            .thenReturn(Tuples.of(Result.buildSucc(), Lists.newArrayList(CustomDataSource.esUserPO())));\n        Assertions.assertEquals(Result.buildFail(\"当前操作者权限不足,需要管理员权限\").getMessage(),\n            esUserManager.deleteAllESUserByProject(1, \"\").getMessage());\n\n        Assertions.assertTrue(esUserManager.deleteAllESUserByProject(1, \"admin\").success());\n\n    }\n\n    @Test\n    void testGet() {\n        final ESUserPO esUserPO = CustomDataSource.esUserPO();\n        final ESUser esUser = ConvertUtil.obj2Obj(esUserPO, ESUser.class);\n        when(esUserService.getEsUserById(anyInt())).thenReturn(esUser);\n        final Result<ConsoleESUserVO> consoleESUserVOResult = esUserManager.get(1);\n        Assertions.assertEquals(consoleESUserVOResult.getData().getId(), esUser.getId());\n\n    }\n\n    @Test\n    void testGetNoCodeESUser() {\n        final ESUserPO esUserPO = CustomDataSource.esUserPO();\n        final ESUser esUser = ConvertUtil.obj2Obj(esUserPO, ESUser.class);\n        final ProjectVO projectVO = CustomDataSource.projectVO();\n        when(roleTool.isAdmin(anyString())).thenReturn(false);\n        projectVO.setOwnerList(null);\n        projectVO.setUserList(null);\n        when(projectService.getProjectDetailByProjectId(anyInt())).thenReturn(projectVO);\n\n        when(esUserService.listESUsers(anyList())).thenReturn(Lists.newArrayList(esUser));\n        Assertions.assertEquals(Result.buildFail(\"权限不足\").getMessage(),\n            esUserManager.getNoCodeESUser(1, \"a1231\").getMessage());\n        when(roleTool.isAdmin(anyString())).thenReturn(false);\n        projectVO.setUserList(CustomDataSource.projectVO().getUserList());\n        when(projectService.getProjectDetailByProjectId(anyInt())).thenReturn(projectVO);\n\n        Assertions.assertTrue(esUserManager.getNoCodeESUser(1, \"admin\").success());\n\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/biz/project/ProjectConfigManagerTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.biz.project;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\nimport com.didichuxing.datachannel.arius.admin.biz.project.impl.ProjectConfigManagerImpl;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.project.ProjectConfigVO;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.ProjectConfigService;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@ActiveProfiles(\"test\")\n@ExtendWith(SpringExtension.class)\n@RunWith(SpringRunner.class)\n@ContextConfiguration(classes = { SpringTool.class })\n@SpringBootTest\nclass ProjectConfigManagerTest {\n\n    @Mock\n    private ProjectConfigService     projectConfigService;\n    @Mock\n    private OperateRecordService     operateRecordService;\n\n    @InjectMocks\n    private ProjectConfigManagerImpl projectConfigManager;\n\n    @BeforeEach\n    void setUp() {\n        initMocks(this);\n\n    }\n\n    @Test\n    void testGet() {\n        // Setup\n        final Result<ProjectConfigVO> expectedResult = Result.buildSucc(new ProjectConfigVO(0, 0, 0, 0, 0, 0, \"memo\"));\n\n        // Configure ProjectConfigService.getProjectConfig(...).\n        final ProjectConfig projectConfig = new ProjectConfig(0, 0, 0, 0, 0, 0, \"memo\");\n        when(projectConfigService.getProjectConfig(0)).thenReturn(projectConfig);\n\n        // Run the test\n        final Result<ProjectConfigVO> result = projectConfigManager.get(0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/common/util/ClusterDynamicConfigTypeCheckFunUtilTest.java",
    "content": "\npackage com.didichuxing.datachannel.arius.admin.common.util;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClusterDynamicConfigTypeCheckFunUtilTest {\n\n    @Test\n    void testBandwidthCheck() {\n\n        assertFalse(ClusterDynamicConfigTypeCheckFunUtil.bandwidthCheck(\"proStoreSize\"));\n        assertTrue(ClusterDynamicConfigTypeCheckFunUtil.bandwidthCheck(\"100MB\"));\n        assertTrue(ClusterDynamicConfigTypeCheckFunUtil.bandwidthCheck(\"100Mb\"));\n        assertTrue(ClusterDynamicConfigTypeCheckFunUtil.bandwidthCheck(\"100Gb\"));\n        assertTrue(ClusterDynamicConfigTypeCheckFunUtil.bandwidthCheck(\"100kb\"));\n        assertTrue(ClusterDynamicConfigTypeCheckFunUtil.bandwidthCheck(\"100b\"));\n        assertTrue(ClusterDynamicConfigTypeCheckFunUtil.bandwidthCheck(\"100k\"));\n        assertTrue(ClusterDynamicConfigTypeCheckFunUtil.bandwidthCheck(\"100p\"));\n        assertTrue(ClusterDynamicConfigTypeCheckFunUtil.bandwidthCheck(\"100t\"));\n\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/core/service/cluster/physic/ClusterPhyServiceTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.cluster.physic;\n\nimport static org.mockito.MockitoAnnotations.initMocks;\n\nimport java.util.*;\n\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Plugin;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyConditionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.PluginDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.cluster.ClusterPhyPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin.PluginPO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.ecm.ESPluginService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.impl.ClusterPhyServiceImpl;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.resource.PhyClusterDAO;\nimport com.didichuxing.datachannel.arius.admin.util.CustomDataSource;\n\n/**\n * @author wpk\n * @date 2021/07/08\n */\npublic class ClusterPhyServiceTest {\n\n    @InjectMocks\n    private ClusterPhyServiceImpl  ClusterPhyService;\n\n    @Mock\n    private PhyClusterDAO          clusterDAO;\n\n    @Mock\n    private ESClusterService       esClusterService;\n\n    @Mock\n    private ClusterRoleService     clusterRoleService;\n\n    @Mock\n    private ClusterRoleHostService clusterRoleHostService;\n\n    @Mock\n    private ESPluginService        esPluginService;\n\n    private final String           cluster      = \"lyn-test-public12-08\";\n    private final String           existCluster = \"hsl-test-exist-Cluster\";\n    private final Integer          id           = 157;\n\n    @BeforeEach\n    public void setUp() {\n        initMocks(this);\n        ClusterPhyPO po = new ClusterPhyPO();\n        po.setCluster(cluster);\n        po.setId(id);\n        po.setHttpWriteAddress(\"2.0.0.0\");\n        po.setPlugIds(\"1234,4321\");\n        List<String> strList = new ArrayList<>();\n        strList.add(cluster);\n        List<ClusterPhyPO> poList = new ArrayList<>();\n        poList.add(po);\n\n        Mockito.when(clusterDAO.listAllName()).thenReturn(strList);\n        Mockito.when(clusterDAO.listByNames(Mockito.anyList())).thenReturn(poList);\n        Mockito.when(clusterDAO.listByCondition(Mockito.any())).thenReturn(poList);\n        Mockito.when(clusterDAO.listAll()).thenReturn(poList);\n        Mockito.when(clusterDAO.pagingByCondition(Mockito.any())).thenReturn(poList);\n        Mockito.when(clusterDAO.getById(id)).thenReturn(po);\n        Mockito.when(clusterDAO.getById(id + 1)).thenReturn(null);\n        Mockito.when(clusterDAO.delete(id)).thenReturn(1);\n        Mockito.when(clusterDAO.insert(Mockito.any())).thenReturn(1);\n        Mockito.when(clusterDAO.update(Mockito.any())).thenReturn(1);\n        Mockito.when(clusterDAO.getByName(cluster)).thenReturn(po);\n        Mockito.when(clusterDAO.getByName(existCluster)).thenReturn(null);\n        Mockito.when(clusterDAO.getTotalHitByCondition(Mockito.any())).thenReturn(10L);\n    }\n\n    @Test\n    public void listClustersTest() {\n        ClusterPhyDTO esClusterDTO = CustomDataSource.esClusterDTOFactory();\n        Assertions.assertTrue(ClusterPhyService.listClustersByCondt(esClusterDTO).stream()\n            .anyMatch(esClusterPhy -> esClusterPhy.getCluster().equals(esClusterDTO.getCluster())));\n        Mockito.when(clusterDAO.listByCondition(Mockito.any())).thenReturn(null);\n        Assertions.assertTrue(CollectionUtils.isEmpty(ClusterPhyService.listClustersByCondt(esClusterDTO)));\n    }\n\n    @Test\n    public void deleteClusterByIdTest() {\n        Integer projectId = 1;\n        Assertions.assertEquals(Result.buildNotExist(\"集群不存在\").getMessage(),\n            ClusterPhyService.deleteClusterById(id + 1, projectId).getMessage());\n        Assertions.assertTrue(ClusterPhyService.deleteClusterById(id, projectId).success());\n    }\n\n    @Test\n    public void createClusterTest() {\n        ClusterPhyDTO esClusterDTO = CustomDataSource.esClusterDTOFactory();\n        esClusterDTO.setCluster(existCluster);\n        Assertions.assertEquals(Result.buildParamIllegal(\"集群信息为空\").getMessage(),\n            ClusterPhyService.createCluster(null, CustomDataSource.OPERATOR).getMessage());\n        esClusterDTO.setEsVersion(null);\n        Assertions.assertEquals(Result.buildParamIllegal(\"es版本为空\").getMessage(),\n            ClusterPhyService.createCluster(esClusterDTO, CustomDataSource.OPERATOR).getMessage());\n        esClusterDTO.setIdc(null);\n        Assertions.assertEquals(Result.buildParamIllegal(\"机房信息为空\").getMessage(),\n            ClusterPhyService.createCluster(esClusterDTO, CustomDataSource.OPERATOR).getMessage());\n        esClusterDTO.setDataCenter(null);\n        Assertions.assertEquals(Result.buildParamIllegal(\"数据中心为空\").getMessage(),\n            ClusterPhyService.createCluster(esClusterDTO, CustomDataSource.OPERATOR).getMessage());\n        esClusterDTO.setType(null);\n        Assertions.assertEquals(Result.buildParamIllegal(\"集群类型为空\").getMessage(),\n            ClusterPhyService.createCluster(esClusterDTO, CustomDataSource.OPERATOR).getMessage());\n        esClusterDTO.setHttpAddress(null);\n        Assertions.assertEquals(Result.buildParamIllegal(\"集群HTTP地址为空\").getMessage(),\n            ClusterPhyService.createCluster(esClusterDTO, CustomDataSource.OPERATOR).getMessage());\n        esClusterDTO.setCluster(null);\n        Assertions.assertEquals(Result.buildParamIllegal(\"集群名称为空\").getMessage(),\n            ClusterPhyService.createCluster(esClusterDTO, CustomDataSource.OPERATOR).getMessage());\n        esClusterDTO = CustomDataSource.esClusterDTOFactory();\n        esClusterDTO.setCluster(existCluster);\n        esClusterDTO.setEsVersion(\"test.test.test\");\n        Assertions.assertEquals(Result.buildParamIllegal(\"es版本号非法\").getMessage(),\n            ClusterPhyService.createCluster(esClusterDTO, CustomDataSource.OPERATOR).getMessage());\n        esClusterDTO.setDataCenter(\"wpkTest\");\n        Assertions.assertEquals(Result.buildParamIllegal(\"数据中心非法\").getMessage(),\n            ClusterPhyService.createCluster(esClusterDTO, CustomDataSource.OPERATOR).getMessage());\n        esClusterDTO = CustomDataSource.esClusterDTOFactory();\n        esClusterDTO.setCluster(existCluster);\n        Assertions.assertTrue(ClusterPhyService.createCluster(esClusterDTO, CustomDataSource.OPERATOR).success());\n    }\n\n    @Test\n    public void editClusterTest() {\n        ClusterPhyDTO esClusterDTO = CustomDataSource.esClusterDTOFactory();\n        Assertions.assertTrue(ClusterPhyService.editCluster(esClusterDTO, CustomDataSource.OPERATOR).success());\n        esClusterDTO.setId(null);\n        Assertions.assertEquals(Result.buildParamIllegal(\"集群ID为空\").getMessage(),\n            ClusterPhyService.editCluster(esClusterDTO, CustomDataSource.OPERATOR).getMessage());\n        esClusterDTO.setId(id + 1);\n        Assertions.assertEquals(Result.buildNotExist(\"集群不存在\").getMessage(),\n            ClusterPhyService.editCluster(esClusterDTO, CustomDataSource.OPERATOR).getMessage());\n    }\n\n    @Test\n    public void getClusterByNameTest() {\n        ClusterRoleInfo clusterRoleInfo = new ClusterRoleInfo();\n        clusterRoleInfo.setRole(\"wpk\");\n        Mockito.when(clusterRoleService.getAllRoleClusterByClusterId(Mockito.any()))\n            .thenReturn(Collections.singletonList(clusterRoleInfo));\n        ClusterRoleHost clusterRoleHost = new ClusterRoleHost();\n        Mockito.when(clusterRoleHostService.getByRoleClusterId(Mockito.anyLong()))\n            .thenReturn(Collections.singletonList(clusterRoleHost));\n        ClusterPhy clusterPhy = ClusterPhyService.getClusterByName(cluster);\n        Assertions.assertTrue(clusterPhy.getClusterRoleInfos().stream()\n            .anyMatch(esRoleCluster1 -> esRoleCluster1.getRole().equals(clusterRoleInfo.getRole())));\n    }\n\n    @Test\n    public void listAllClustersTest() {\n        Assertions.assertTrue(\n            ClusterPhyService.listAllClusters().stream().anyMatch(esClusterPhy -> esClusterPhy.getId().equals(id)));\n    }\n\n    @Test\n    public void listClusterNamesTest() {\n        Assertions.assertTrue(\n            ClusterPhyService.listClusterNames().stream().anyMatch(clusterName -> clusterName.equals(cluster)));\n        Mockito.when(clusterDAO.listAllName()).thenThrow(new RuntimeException());\n        Assertions.assertTrue(CollectionUtils.isEmpty(ClusterPhyService.listClusterNames()));\n    }\n\n    @Test\n    public void listClustersByNamesTest() {\n        Assertions.assertTrue(ClusterPhyService.listClustersByNames(Arrays.asList(cluster, existCluster)).stream()\n            .anyMatch(esClusterPhy -> esClusterPhy.getCluster().equals(cluster)));\n        Assertions.assertTrue(CollectionUtils.isEmpty(ClusterPhyService.listClustersByNames(Collections.emptyList())));\n    }\n\n    @Test\n    public void isClusterExistsTest() {\n        Assertions.assertFalse(ClusterPhyService.isClusterExists(existCluster));\n        Assertions.assertTrue(ClusterPhyService.isClusterExists(cluster));\n    }\n\n    @Test\n    public void listClusterPluginsTest() {\n        PluginDTO pluginDTO = CustomDataSource.esPluginDTOFactory();\n        // 为mock的插件对象设置插件的文件名称\n        pluginDTO.setFileName(\"test\");\n        pluginDTO.setId(1234L);\n        Mockito.when(esPluginService.listClusterAndDefaultESPlugin(id.toString())).thenReturn(null);\n        Assertions.assertTrue(ClusterPhyService.listClusterPlugins(cluster).isEmpty());\n        Assertions.assertTrue(ClusterPhyService.listClusterPlugins(existCluster).isEmpty());\n        Mockito.when(esPluginService.listClusterAndDefaultESPlugin(id.toString()))\n            .thenReturn(Collections.singletonList(ConvertUtil.obj2Obj(pluginDTO, PluginPO.class)));\n        Assertions.assertTrue(ClusterPhyService.listClusterPlugins(cluster).stream().map(Plugin::getId)\n            .anyMatch(pId -> pluginDTO.getId().equals(pId)));\n    }\n\n    @Test\n    public void getClusterByIdTest() {\n        Assertions.assertNull(ClusterPhyService.getClusterById(id + 1));\n        Assertions.assertNotNull(ClusterPhyService.getClusterById(id));\n    }\n\n    @Test\n    public void ensureDcdrRemoteClusterTest() throws ESOperateException {\n        Assertions.assertFalse(ClusterPhyService.ensureDCDRRemoteCluster(cluster, null));\n        Mockito.when(esClusterService.hasSettingExist(Mockito.anyString(), Mockito.anyString())).thenReturn(true);\n        Assertions.assertTrue(ClusterPhyService.ensureDCDRRemoteCluster(cluster, cluster));\n        Mockito.when(esClusterService.hasSettingExist(Mockito.anyString(), Mockito.anyString())).thenReturn(false);\n        Mockito.when(esClusterService.syncPutRemoteCluster(Mockito.anyString(), Mockito.anyString(), Mockito.isNull(),\n            Mockito.anyInt())).thenReturn(true);\n        Assertions.assertFalse(ClusterPhyService.ensureDCDRRemoteCluster(cluster, existCluster));\n        Assertions.assertFalse(ClusterPhyService.ensureDCDRRemoteCluster(existCluster, cluster));\n        Mockito.when(esClusterService.hasSettingExist(Mockito.any(), Mockito.any())).thenReturn(false);\n        Mockito\n            .when(esClusterService.syncPutRemoteCluster(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyInt()))\n            .thenReturn(true);\n        Assertions.assertTrue(ClusterPhyService.ensureDCDRRemoteCluster(cluster, cluster));\n    }\n\n    @Test\n    public void getRoutingAllocationAwarenessAttributesTest() {\n        Assertions.assertTrue(ClusterPhyService.getRoutingAllocationAwarenessAttributes(existCluster).isEmpty());\n        Mockito.when(esClusterService.syncGetAllNodesAttributes(Mockito.anyString())).thenReturn(new HashSet<String>() {\n            {\n                add(\"aaa\");\n            }\n        });\n        ;\n        Assertions.assertFalse(ClusterPhyService.getRoutingAllocationAwarenessAttributes(cluster).isEmpty());\n    }\n\n    @Test\n    public void updatePhyClusterDynamicConfigTest() {\n        ClusterSettingDTO clusterSettingDTO = CustomDataSource.clusterSettingDTOFactory();\n        clusterSettingDTO.setClusterName(existCluster);\n        Assertions.assertEquals(Result.buildNotExist(\"集群不存在\").getMessage(),\n            ClusterPhyService.updatePhyClusterDynamicConfig(clusterSettingDTO).getMessage());\n        clusterSettingDTO.setClusterName(cluster);\n        clusterSettingDTO.setKey(\"unknown\");\n        Assertions.assertEquals(Result.buildNotExist(\"传入的字段类型未知\").getMessage(),\n            ClusterPhyService.updatePhyClusterDynamicConfig(clusterSettingDTO).getMessage());\n        clusterSettingDTO.setKey(\"cluster.routing.allocation.node_concurrent_recoveries\");\n        clusterSettingDTO.setValue(\"=aa\");\n        Assertions.assertEquals(Result.buildNotExist(\"传入的字段参数格式有误\").getMessage(),\n            ClusterPhyService.updatePhyClusterDynamicConfig(clusterSettingDTO).getMessage());\n        clusterSettingDTO = CustomDataSource.clusterSettingDTOFactory();\n        clusterSettingDTO.setClusterName(cluster);\n        //设置对应的配置\n        Mockito.when(esClusterService.syncPutPersistentConfig(Mockito.anyString(), Mockito.anyMap())).thenReturn(true);\n        Assertions.assertTrue(ClusterPhyService.updatePhyClusterDynamicConfig(clusterSettingDTO).success());\n    }\n\n    @Test\n    public void pagingGetClusterPhyByConditionTest() {\n        //条件查询\n        ClusterPhyConditionDTO clusterPhyConditionDTO = clusterPhyConditionDTOFactory();\n        //按照集群名称进行查询\n        Assertions.assertTrue(ClusterPhyService.pagingGetClusterPhyByCondition(clusterPhyConditionDTO).stream()\n            .anyMatch(clusterPhy -> clusterPhy.getCluster().equals(cluster)));\n        Mockito.when(clusterDAO.pagingByCondition(Mockito.any())).thenThrow(new RuntimeException());\n        Assertions.assertTrue(ClusterPhyService.pagingGetClusterPhyByCondition(clusterPhyConditionDTO).isEmpty());\n    }\n\n    @Test\n    public void fuzzyClusterPhyHitByConditionTest() {\n        //模糊查询\n        ClusterPhyConditionDTO clusterPhyConditionDTO = clusterPhyConditionDTOFactory();\n        //按照集群名称进行查询\n        Assertions.assertTrue(ClusterPhyService.fuzzyClusterPhyHitByCondition(clusterPhyConditionDTO) >= 1);\n    }\n\n    @Test\n    public void isClusterExistsByPackageIdTest() {\n        //模糊查询\n\n        Mockito.when(clusterDAO.getTotalHitByPackageId(Mockito.any())).thenReturn(2L);\n        //按照集群名称进行查询\n        Assertions.assertTrue(ClusterPhyService.isClusterExistsByPackageId(1234L));\n    }\n\n    @Test\n    public void updatePluginIdsByIdTest() {\n        Mockito.when(clusterDAO.updatePluginIdsById(Mockito.any(), Mockito.anyInt())).thenReturn(1);\n        String pluginIds = null;\n        Assertions.assertTrue(ClusterPhyService.updatePluginIdsById(pluginIds, id).success());\n        pluginIds = \"135\";\n        Assertions.assertTrue(ClusterPhyService.updatePluginIdsById(pluginIds, id).success());\n        pluginIds = \"555\";\n        Assertions.assertTrue(ClusterPhyService.updatePluginIdsById(pluginIds, id).success());\n    }\n\n    private ClusterPhyConditionDTO clusterPhyConditionDTOFactory() {\n        ClusterPhyConditionDTO clusterPhyConditionDTO = new ClusterPhyConditionDTO();\n        clusterPhyConditionDTO.setCluster(cluster);\n        clusterPhyConditionDTO.setPage(1L);\n        clusterPhyConditionDTO.setSize(10L);\n        return clusterPhyConditionDTO;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/core/service/gateway/GatewayServiceTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.gateway;\n\nimport static com.didichuxing.datachannel.arius.admin.util.CustomDataSource.gatewayHeartbeatFactory;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.GatewayHeartbeat;\nimport com.didichuxing.datachannel.arius.admin.core.service.gateway.impl.GatewayServiceImpl;\nimport com.didichuxing.datachannel.arius.admin.persistence.component.ESGatewayClient;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.gateway.GatewayClusterDAO;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.gateway.GatewayClusterNodeDAO;\nimport com.didichuxing.datachannel.arius.admin.util.CustomDataSource;\nimport java.util.HashSet;\nimport java.util.Set;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.springframework.test.util.ReflectionTestUtils;\n\n/**\n * @author wuxuan\n * @Date 2022/5/31\n */\npublic class GatewayServiceTest {\n\n    @InjectMocks\n    GatewayServiceImpl    gatewayService;\n    @Mock\n    GatewayClusterDAO     gatewayClusterDAO;\n    @Mock\n    GatewayClusterNodeDAO gatewayClusterNodeDAO;\n    @Mock\n    ESGatewayClient       esGatewayClient;\n\n    Set<String>           clusterNames = new HashSet<>();\n\n    @BeforeEach\n    public void init() {\n        clusterNames.add(\"admin\");\n        //通过反射机制实现对应的对象中参数的赋值\n        initMocks(this);\n        ReflectionTestUtils.setField(gatewayService, \"clusterNames\", clusterNames);\n    }\n\n    @Test\n    void heartbeatTest() {\n        // 生成新的记录\n        GatewayHeartbeat gatewayHeartbeat = gatewayHeartbeatFactory();\n        // 设置不同的空参数使能够遍历checkResult.failed()所包含的所有分支\n        gatewayHeartbeat.setClusterName(null);\n        Assertions.assertEquals(\"参数错误:cluster name is null，请检查后再提交！\",\n            gatewayService.heartbeat(gatewayHeartbeat).getMessage());\n        gatewayHeartbeat.setClusterName(CustomDataSource.PHY_CLUSTER_NAME);\n        gatewayHeartbeat.setHostName(null);\n        Assertions.assertEquals(\"参数错误:host name is null，请检查后再提交！\",\n            gatewayService.heartbeat(gatewayHeartbeat).getMessage());\n        gatewayHeartbeat.setHostName(\"admin\");\n        gatewayHeartbeat.setPort(-1);\n        Assertions.assertEquals(\"参数错误:port illegal，请检查后再提交！\", gatewayService.heartbeat(gatewayHeartbeat).getMessage());\n        //通过设置recordHeartbeat(heartbeat)返回的值小于0，实现Result.buildFail(\"save db fail\");\n        gatewayHeartbeat = gatewayHeartbeatFactory();\n        Mockito.when(gatewayClusterNodeDAO.recordGatewayNode(Mockito.any())).thenReturn(-1);\n        Assertions.assertEquals(\"save db fail\", gatewayService.heartbeat(gatewayHeartbeat).getMessage());\n        // 记录的正确执行操作\n        //通过Mockito.when().thenReturn()返回所需要的与数据库关联的对象的返回值\n        Mockito.when(gatewayClusterDAO.insert(Mockito.any())).thenReturn(1);\n        Mockito.when(gatewayClusterNodeDAO.recordGatewayNode(Mockito.any())).thenReturn(1);\n        Assertions.assertTrue(gatewayService.heartbeat(gatewayHeartbeat).success());\n    }\n\n    @Test\n    void aliveCountTest() {\n        // 遍历到所有的异常处理的分支\n        long gapTime = -1;\n        Assertions.assertEquals(\"参数错误:gapTime name illegal，请检查后再提交！\",\n            gatewayService.aliveCount(CustomDataSource.PHY_CLUSTER_NAME, gapTime).getMessage());\n        gapTime = 10000;\n        Assertions.assertEquals(\"参数错误:cluster name is null，请检查后再提交！\",\n            gatewayService.aliveCount(null, gapTime).getMessage());\n        // 执行正确的记录的执行\n        ReflectionTestUtils.setField(gatewayService, \"gatewayClusterNodeDAO\", gatewayClusterNodeDAO);\n        Mockito.when(gatewayClusterNodeDAO.aliveCountByClusterNameAndTime(Mockito.anyString(), Mockito.any()))\n            .thenReturn(1);\n        Assertions.assertTrue(gatewayService.aliveCount(CustomDataSource.PHY_CLUSTER_NAME, gapTime).success());\n    }\n\n    @Test\n    void sqlOperateTest() {\n        //设置不同参数遍历preSqlParamCheck的fail分支(String sql, String phyClusterName, Integer projectId, String postFix)\n        int projectId = 1;\n        String sql = \"show databases\";\n        Assertions.assertEquals(\"参数错误:查询的sql语句为空，请检查后再提交！\",\n            gatewayService.sqlOperate(\"\", CustomDataSource.PHY_CLUSTER_NAME, null, \"postFix\").getMessage());\n        Assertions.assertEquals(\"参数错误:查询gateway的路径后缀为空，请检查后再提交！\",\n            gatewayService.sqlOperate(sql, CustomDataSource.PHY_CLUSTER_NAME, null, null).getMessage());\n        Assertions.assertEquals(\"参数错误:对应的projectId字段非法，请检查后再提交！\",\n            gatewayService.sqlOperate(sql, CustomDataSource.PHY_CLUSTER_NAME, null, \"postFix\").getMessage());\n        //App app = new App();\n        //app.setId(projectId);\n        //List<App> apps = new ArrayList<>();\n        //apps.add(app);\n        //Mockito.when(appService.listApps()).thenReturn(apps);\n        //Mockito.when(appService.getAppById(Mockito.anyInt())).thenReturn(app);\n        Mockito.when(esGatewayClient.getSingleGatewayAddress()).thenReturn(\"10.190.32.30\");\n        Assertions.assertFalse(\n            gatewayService.sqlOperate(\"sql\", CustomDataSource.PHY_CLUSTER_NAME, null, \"postFix\").success());\n    }\n\n    @Test\n    void getAliveNodeTest() {\n        Mockito.when(gatewayClusterDAO.insert(Mockito.any())).thenReturn(1);\n        Mockito.when(gatewayClusterNodeDAO.recordGatewayNode(Mockito.any())).thenReturn(1);\n        Mockito.when(gatewayClusterNodeDAO.listAliveNodeByClusterNameAndTime(Mockito.any(), Mockito.any()))\n            .thenReturn(CustomDataSource.getGatewayNodePOList());\n        Assertions.assertFalse(gatewayService.getAliveNode(CustomDataSource.PHY_CLUSTER_NAME, 1000).isEmpty());\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/core/service/metrics/UserMetricsConfigServiceTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.metrics;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.UserConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.metrics.UserConfigPO;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.metrics.impl.UserConfigServiceImpl;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.metrics.UserConfigDAO;\nimport com.didichuxing.datachannel.arius.admin.util.CustomDataSource;\nimport java.util.Arrays;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@ActiveProfiles(\"test\")\n@ExtendWith({ SpringExtension.class, MockitoExtension.class })\n@MockitoSettings(strictness = Strictness.LENIENT)\n@RunWith(SpringRunner.class)\n@ContextConfiguration(classes = { SpringTool.class })\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)\nclass UserConfigServiceTest {\n\n    @Mock\n    private UserConfigDAO     userConfigDAO;\n\n    @InjectMocks\n    private UserConfigServiceImpl userConfigService;\n\n    @Test\n    void testGetMetricsByTypeAndUserName() {\n        final UserConfigPO metricsConfigPO = CustomDataSource.getMetricsConfigPO();\n        metricsConfigPO.setConfigInfo(CustomDataSource.metricInfo());\n        // Setup\n        final UserConfigInfoDTO param = new UserConfigInfoDTO(\"admin\", \"cluster\", \"overview\",\n            Arrays.asList(\"cpuUsage\", \"cpuLoad1M\"),1,1);\n\n        // Configure UserConfigDAO.selectOne(...).\n        when(userConfigDAO.selectOne(any(QueryWrapper.class))).thenReturn(metricsConfigPO);\n\n        // Run the test\n        param.setUserName(null);\n        Assertions.assertFalse(CollectionUtils.isNotEmpty(userConfigService.getUserConfigByConfigTypeAndUserNameAndProjectId(param)));\n        param.setUserName(\"admin\");\n        metricsConfigPO.setConfigInfo(null);\n\n        when(userConfigDAO.selectOne(any(QueryWrapper.class))).thenReturn(metricsConfigPO);\n        Assertions.assertFalse(CollectionUtils.isNotEmpty(userConfigService.getUserConfigByConfigTypeAndUserNameAndProjectId(param)));\n        metricsConfigPO.setConfigInfo(\"[]\");\n        when(userConfigDAO.selectOne(any(QueryWrapper.class))).thenReturn(metricsConfigPO);\n        Assertions.assertFalse(CollectionUtils.isNotEmpty(userConfigService.getUserConfigByConfigTypeAndUserNameAndProjectId(param)));\n        metricsConfigPO.setConfigInfo(CustomDataSource.metricInfo());\n        when(userConfigDAO.selectOne(any(QueryWrapper.class))).thenReturn(metricsConfigPO);\n        Assertions.assertTrue(CollectionUtils.isNotEmpty(userConfigService.getUserConfigByConfigTypeAndUserNameAndProjectId(param)));\n    }\n\n    @Test\n    void testupdateUserConfigByConfigTypeAndUserNameAndProjectId() {\n        final UserConfigPO metricsConfigPO = CustomDataSource.getMetricsConfigPO();\n        metricsConfigPO.setConfigInfo(CustomDataSource.metricInfo());\n\n        // Configure UserConfigDAO.selectOne(...).\n\n        when(userConfigDAO.insert(any())).thenReturn(1);\n\n        final UserConfigInfoDTO param = new UserConfigInfoDTO(\"admin\", \"cluster\", \"overview\",\n            Arrays.asList(\"cpuUsage\", \"cpuLoad1M\"),1,1);\n        param.setUserName(null);\n\n        // Verify the results\n        assertThat(userConfigService.updateUserConfigByConfigTypeAndUserNameAndProjectId(param).getMessage())\n            .isEqualTo(Result.buildFail(\"用户账号为空\").getMessage());\n        param.setUserName(\"admin\");\n        param.setFirstUserConfigType(null);\n        // Verify the results\n        assertThat(userConfigService.updateUserConfigByConfigTypeAndUserNameAndProjectId(param).getMessage())\n            .isEqualTo(Result.buildFail(\"配置类型未知\").getMessage());\n        param.setFirstUserConfigType(\"cluster\");\n        param.setSecondUserConfigType(null);\n        assertThat(userConfigService.updateUserConfigByConfigTypeAndUserNameAndProjectId(param).getMessage())\n            .isEqualTo(Result.buildFail(\"配置类型未知\").getMessage());\n        param.setSecondUserConfigType(\"overview\");\n        when(userConfigDAO.selectOne(any())).thenReturn(null);\n\n        assertThat(userConfigService.updateUserConfigByConfigTypeAndUserNameAndProjectId(param).success()).isTrue();\n        when(userConfigDAO.selectOne(any())).thenReturn(metricsConfigPO);\n        when(userConfigDAO.update(any(), any())).thenReturn(1);\n        assertThat(userConfigService.updateUserConfigByConfigTypeAndUserNameAndProjectId(param).success()).isTrue();\n    }\n\n    @Test\n    void testDeleteByUserName() {\n        // Setup\n        when(userConfigDAO.delete(any())).thenReturn(1);\n\n        // Run the test\n        userConfigService.deleteByUserName(\"userName\",1);\n\n        // Verify the results\n        verify(userConfigDAO).delete(any());\n    }\n    \n    //void setTemplateInit(){\n    //      for (IndexTemplate indexTemplateDTO : indexTemplateService.listAllLogicTemplates()) {\n    //        final Integer logicTemplateId = indexTemplateDTO.getId();\n    //        List<Integer> openSrvList = Lists.newArrayList();\n    //        final String openSrv = indexTemplateDTO.getOpenSrv();\n    //        if (StringUtils.isNotBlank(openSrv)) {\n    //            for (String s : StringUtils.split(openSrv, \",\")) {\n    //                if (StringUtils.isNumeric(s)) {\n    //                    openSrvList.add(Integer.parseInt(s));\n    //                }\n    //            }\n    //        }\n    //\n    //\n    //        if (openSrvList.contains(TemplateServiceEnum.TEMPLATE_PRE_CREATE.getCode()) && openSrvList.contains(\n    //                TemplateServiceEnum.TEMPLATE_DEL_EXPIRE.getCode()) && openSrvList.contains(\n    //                TemplateServiceEnum.TEMPLATE_PIPELINE.getCode())) {\n    //            System.out.println(\"跳过\");\n    //            continue;\n    //        }\n    //        //如果是分区模版\n    //        final boolean isExpression = indexTemplateDTO.getExpression().endsWith(\"*\");\n    //\n    //        if (Boolean.TRUE.equals(isExpression)) {\n    //            openSrvList.add(TemplateServiceEnum.TEMPLATE_PRE_CREATE.getCode());\n    //            openSrvList.add(TemplateServiceEnum.TEMPLATE_DEL_EXPIRE.getCode());\n    //        }\n    //        final ClusterRegion clusterRegion = clusterRegionService.getRegionByLogicClusterId(\n    //                indexTemplateDTO.getResourceId());\n    //        final TupleTwo</*dcdrExist*/Boolean,/*pipelineExist*/ Boolean> existDCDRAndPipelineModule = esClusterNodeService.existDCDRAndPipelineModule(\n    //                clusterRegion.getPhyClusterName());\n    //        if (logicTemplateId.equals(25135)){\n    //            System.out.println(25135);\n    //        }\n    //        if (Boolean.TRUE.equals(existDCDRAndPipelineModule.v2)) {\n    //            openSrvList.add(TemplateServiceEnum.TEMPLATE_PIPELINE.getCode());\n    //        }\n    //        final IndexTemplatePO indexTemplatePO = new IndexTemplatePO();\n    //        if (CollectionUtils.isNotEmpty(openSrvList)) {\n    //            //如果集群支持pipelien\n    //            indexTemplatePO.setOpenSrv(\n    //                    ConvertUtil.list2String(openSrvList.stream().distinct().collect(Collectors.toList()), \",\"));\n    //            indexTemplatePO.setId(logicTemplateId);\n    //            final boolean update = indexTemplateService.update(indexTemplatePO);\n    //            if (update) {\n    //                System.err.println(\"success\");\n    //            }\n    //        }\n    //\n    //    }\n    //    System.out.println(\"执行更新完成.......\");\n    //}\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/core/service/project/ESUserServiceTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.project;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.anyList;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ESUserDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ESUser;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.operaterecord.OperationEnum;\nimport com.didichuxing.datachannel.arius.admin.common.tuple.TupleTwo;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.impl.ESUserServiceImpl;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.project.ESUserDAO;\nimport com.didichuxing.datachannel.arius.admin.util.CustomDataSource;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.assertj.core.util.Lists;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.annotation.Rollback;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Transactional(timeout = 1000)\n@Rollback\n@RunWith(SpringRunner.class)\n@AutoConfigureMockMvc\n@SpringBootTest\nclass ESUserServiceTest {\n    @InjectMocks\n    private ESUserServiceImpl esUserService;\n\n    @Mock\n    private ESUserDAO         esUserDAO;\n\n    @BeforeEach\n    void setUp() {\n        initMocks(this);\n    }\n\n    @Test\n    void testListESUsers() {\n\n        when(esUserDAO.listByProjectIds(anyList())).thenReturn(Collections.singletonList(CustomDataSource.esUserPO()));\n\n        // Run the test\n        final List<ESUser> result = esUserService.listESUsers(Collections.singletonList(1));\n\n    }\n\n    @Test\n    void testRegisterESUser() {\n        Assertions.assertEquals(Result.buildParamIllegal(\"应用信息为空\").getMessage(),\n            esUserService.registerESUser(null, \"operator\").v1().getMessage());\n        ESUserPO esUserPO = CustomDataSource.esUserPO();\n        final ESUserDTO esUserDTO = ConvertUtil.obj2Obj(esUserPO, ESUserDTO.class);\n\n        esUserDTO.setProjectId(null);\n        esUserDTO.setId(1);\n        Assertions.assertEquals(Result.buildParamIllegal(\"项目id为空\").getMessage(),\n            esUserService.registerESUser(esUserDTO, \"operator\").v1().getMessage());\n\n        when(esUserDAO.getByESUser(anyInt())).thenReturn(esUserPO);\n        when(esUserDAO.insert(any())).thenReturn(1);\n        esUserDTO.setProjectId(1);\n        Assertions.assertTrue(esUserService.registerESUser(esUserDTO, \"operator\").v1().success());\n\n    }\n\n    @Test\n    void testEditUser() {\n\n        when(esUserDAO.update(any())).thenReturn(1);\n        ESUserPO esUserPO = CustomDataSource.esUserPO();\n        ESUserDTO esUserDTO = ConvertUtil.obj2Obj(esUserPO, ESUserDTO.class);\n        esUserDTO.setProjectId(1);\n        esUserDTO.setId(1);\n        when(esUserDAO.getByESUser(anyInt())).thenReturn(esUserPO);\n        // Run the test\n        final TupleTwo<Result<Void>, ESUserPO> result = esUserService.editUser(esUserDTO);\n        Assertions.assertTrue(result.v1().success());\n        // Verify the results\n    }\n\n    @Test\n    void testDeleteESUserById() {\n\n        when(esUserDAO.delete(anyInt())).thenReturn(1);\n\n        // Run the test\n        final TupleTwo<Result<Void>, ESUserPO> result = esUserService.deleteESUserById(1);\n        Assertions.assertTrue(result.v1().success());\n        // Verify the results\n    }\n\n    @Test\n    void testDeleteByESUsers() {\n        // Setup\n        // Configure ESUserDAO.listByProjectId(...).\n        final List<ESUserPO> esUserPOS = Arrays.asList(new ESUserPO(0, 0, \"verifyCode\", \"memo\", 0, 0, \"cluster\", 0,\n            \"dataCenter\", 0, false, \"ip\", \"indexExp\"));\n        when(esUserDAO.listByProjectId(0)).thenReturn(esUserPOS);\n\n        when(esUserDAO.deleteByProjectId(0)).thenReturn(0);\n\n        // Run the test\n        esUserService.deleteByESUsers(0);\n\n        // Verify the results\n    }\n\n    @Test\n    void testCountByProjectId() {\n        // Setup\n        when(esUserDAO.countByProjectId(0)).thenReturn(0);\n\n        // Run the test\n        final int result = esUserService.countByProjectId(0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(0);\n    }\n\n    @Test\n    void testGetEsUserById() {\n        final ESUserPO esUserPO = CustomDataSource.esUserPO();\n        when(esUserDAO.getByESUser(anyInt())).thenReturn(esUserPO);\n\n        // Run the test\n        final ESUser result = esUserService.getEsUserById(1);\n\n        // Verify the results\n        Assertions.assertTrue(Objects.nonNull(result));\n    }\n\n    @Test\n    void testVerifyAppCode() {\n        final ESUserPO esUserPO = CustomDataSource.esUserPO();\n        when(esUserDAO.getByESUser(anyInt())).thenReturn(esUserPO);\n\n        assertThat(Result.buildNotExist(\"es user 不存在\").getMessage())\n            .isEqualTo(esUserService.verifyAppCode(null, \"verifyCode\").getMessage());\n        assertThat(Result.buildParamIllegal(\"校验码错误\").getMessage())\n            .isEqualTo(esUserService.verifyAppCode(1, \"verifyCode1\").getMessage());\n        assertThat(esUserService.verifyAppCode(1, \"verifyCode\").success()).isTrue();\n\n    }\n\n    @Test\n    void testValidateESUser() {\n\n        final ESUserPO esUserPO = CustomDataSource.esUserPO();\n        final ESUserDTO esUserDTO = ConvertUtil.obj2Obj(esUserPO, ESUserDTO.class);\n        Assertions.assertEquals(Result.buildParamIllegal(\"应用信息为空\").getMessage(),\n            esUserService.validateESUser(null, null).getMessage());\n        esUserDTO.setMemo(null);\n        Assertions.assertEquals(Result.buildParamIllegal(\"备注为空\").getMessage(),\n            esUserService.validateESUser(esUserDTO, OperationEnum.ADD).getMessage());\n        esUserDTO.setMemo(\"a\");\n        esUserDTO.setProjectId(null);\n\n        Assertions.assertEquals(Result.buildParamIllegal(\"项目id为空\").getMessage(),\n            esUserService.validateESUser(esUserDTO, OperationEnum.ADD).getMessage());\n        esUserPO.setProjectId(2);\n        when(esUserDAO.getByESUser(anyInt())).thenReturn(esUserPO);\n        esUserDTO.setProjectId(1);\n        esUserDTO.setId(1);\n        Assertions.assertEquals(\n            Result.buildParamIllegal(String.format(\"es user [%s] 已存在\", esUserDTO.getId())).getMessage(),\n            esUserService.validateESUser(esUserDTO, OperationEnum.ADD).getMessage());\n\n        esUserDTO.setId(null);\n        Assertions.assertEquals(Result.buildNotExist(\"es user 不存在\").getMessage(),\n            esUserService.validateESUser(esUserDTO, OperationEnum.EDIT).getMessage());\n        when(esUserDAO.getByESUser(anyInt())).thenReturn(null);\n        Assertions.assertEquals(Result.buildNotExist(\"es user 不存在\").getMessage(),\n            esUserService.validateESUser(esUserDTO, OperationEnum.EDIT).getMessage());\n        esUserPO.setProjectId(2);\n        esUserDTO.setId(1);\n        esUserPO.setId(1);\n        when(esUserDAO.getByESUser(anyInt())).thenReturn(esUserPO);\n        esUserDTO.setProjectId(1);\n        Assertions.assertEquals(\n            Result.buildParamIllegal(String.format(\"es user 已经存在在项目[%s],不能为项目[%s]创建,请重新提交es user\",\n                esUserPO.getProjectId(), esUserDTO.getProjectId())).getMessage(),\n            esUserService.validateESUser(esUserDTO, OperationEnum.EDIT).getMessage());\n        esUserPO.setProjectId(1);\n        when(esUserDAO.getByESUser(anyInt())).thenReturn(esUserPO);\n        esUserDTO.setIsRoot(null);\n        Assertions.assertEquals(Result.buildParamIllegal(\"超管标记非法\").getMessage(),\n            esUserService.validateESUser(esUserDTO, OperationEnum.EDIT).getMessage());\n        esUserDTO.setIsRoot(2);\n        Assertions.assertEquals(Result.buildParamIllegal(\"超管标记非法\").getMessage(),\n            esUserService.validateESUser(esUserDTO, OperationEnum.EDIT).getMessage());\n        esUserDTO.setIsRoot(1);\n        esUserDTO.setSearchType(3);\n        Assertions.assertEquals(Result.buildParamIllegal(\"查询模式非法\").getMessage(),\n\n            esUserService.validateESUser(esUserDTO, OperationEnum.EDIT).getMessage());\n        esUserDTO.setSearchType(1);\n        esUserDTO.setVerifyCode(null);\n        Assertions.assertEquals(Result.buildParamIllegal(\"校验码不能为空\").getMessage(),\n            esUserService.validateESUser(esUserDTO, OperationEnum.EDIT).getMessage());\n\n        esUserDTO.setVerifyCode(\"aa\");\n        Assertions.assertTrue(esUserService.validateESUser(esUserDTO, OperationEnum.EDIT).success());\n    }\n\n    @Test\n    void testGetProjectWithoutCodeApps() {\n        final ESUserPO esUserPO = CustomDataSource.esUserPO();\n        when(esUserDAO.listByProjectIds(anyList())).thenReturn(Lists.newArrayList(esUserPO));\n        final List<ESUser> projectWithoutCodeApps = esUserService.getProjectWithoutCodeApps(1);\n        Assertions.assertTrue(CollectionUtils.isNotEmpty(projectWithoutCodeApps));\n    }\n\n    @Test\n    void testGetProjectWithoutCodeApps_ESUserDAOReturnsNoItems() {\n        // Setup\n        when(esUserDAO.listByProjectIds(Arrays.asList(0))).thenReturn(Collections.emptyList());\n\n        // Run the test\n        final List<ESUser> result = esUserService.getProjectWithoutCodeApps(0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(Collections.emptyList());\n    }\n\n    @Test\n    void testCheckDefaultESUserByProject() {\n        // Setup\n        when(esUserDAO.countDefaultESUserByProject(0)).thenReturn(0);\n\n        // Run the test\n        final boolean result = esUserService.checkDefaultESUserByProject(0);\n\n        // Verify the results\n        assertThat(result).isFalse();\n    }\n\n    @Test\n    void testGetDefaultESUserByProject() {\n        // Setup\n        final ESUser expectedResult = new ESUser(0, \"name\", 0, \"verifyCode\",\n           \"memo\", 0, 0, \"cluster\", 0, \"dataCenter\", 0, false, \"ip\", \"indexExp\");\n\n        // Configure ESUserDAO.getDefaultESUserByProject(...).\n        final ESUser esUser = new ESUser(0, \"name\", 0, \"verifyCode\",\n            \"memo\", 0, 0, \"cluster\", 0, \"dataCenter\", 0, false, \"ip\", \"indexExp\");\n        when(esUserDAO.getDefaultESUserByProject(0)).thenReturn(esUser);\n\n        // Run the test\n        final ESUser result = esUserService.getDefaultESUserByProject(0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/core/service/project/ProjectConfigServiceTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.core.service.project;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectConfig;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.project.impl.ProjectConfigServiceImpl;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.project.ProjectConfigDAO;\nimport com.didichuxing.datachannel.arius.admin.util.CustomDataSource;\nimport com.google.common.collect.Maps;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.annotation.Rollback;\nimport org.springframework.test.context.junit4.SpringRunner;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Transactional(timeout = 1000)\n@Rollback\n@RunWith(SpringRunner.class)\n@AutoConfigureMockMvc\n@SpringBootTest\nclass ProjectConfigServiceTest {\n\n    @Mock\n    private ProjectConfigDAO         projectConfigDAO;\n\n    @InjectMocks\n    private ProjectConfigServiceImpl projectConfigService;\n\n    @BeforeEach\n    void setUp() {\n        initMocks(this);\n    }\n\n    @Test\n    void testGetProjectConfig() {\n        // Setup\n        final ProjectConfig expectedResult = new ProjectConfig(0, 0, 0, 0, 0, 0, \"memo\");\n\n        // Configure ProjectConfigDAO.getByProjectId(...).\n        final ProjectConfigPO projectConfigPO = new ProjectConfigPO(0, 0, 0, 0, 0, 0, \"memo\");\n        when(projectConfigDAO.getByProjectId(0)).thenReturn(projectConfigPO);\n\n        // Run the test\n        final ProjectConfig result = projectConfigService.getProjectConfig(0);\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void testProjectId2ProjectConfigMap() {\n        // Setup\n\n        // Configure ProjectConfigDAO.listAll(...).\n        final List<ProjectConfigPO> projectConfigPOS = Arrays.asList(new ProjectConfigPO(1, 0, 0, 0, 0, 0, \"memo\"));\n        when(projectConfigDAO.listAll()).thenReturn(projectConfigPOS);\n        final Map<Integer, ProjectConfig> expectedResult = Maps.newHashMap();\n        for (Entry<Integer, ProjectConfigPO> configPOEntry : ConvertUtil\n            .list2Map(projectConfigPOS, ProjectConfigPO::getProjectId).entrySet()) {\n            expectedResult.put(configPOEntry.getKey(),\n                ConvertUtil.obj2Obj(configPOEntry.getValue(), ProjectConfig.class));\n        }\n\n        // Run the test\n        final Map<Integer, ProjectConfig> result = projectConfigService.projectId2ProjectConfigMap();\n\n        // Verify the results\n        assertThat(result).isEqualTo(expectedResult);\n    }\n\n    @Test\n    void testUpdateOrInitProjectConfig() {\n        // Setup\n        final ProjectConfigPO projectConfigPO = CustomDataSource.projectConfigPO();\n        final ProjectConfigDTO projectConfigDTO = ConvertUtil.obj2Obj(projectConfigPO, ProjectConfigDTO.class);\n\n        assertThat(projectConfigService.updateOrInitProjectConfig(null, null).v1().getMessage())\n            .isEqualTo(Result.buildParamIllegal(\"配置信息为空\").getMessage());\n        projectConfigDTO.setProjectId(null);\n        assertThat(projectConfigService.updateOrInitProjectConfig(projectConfigDTO, null).v1().getMessage())\n            .isEqualTo(Result.buildParamIllegal(\"应用ID为空\").getMessage());\n        projectConfigDTO.setProjectId(1);\n        projectConfigDTO.setAnalyzeResponseEnable(23);\n        assertThat(projectConfigService.updateOrInitProjectConfig(projectConfigDTO, null).v1().getMessage())\n            .isEqualTo(Result.buildParamIllegal(\"解析响应结果开关非法\").getMessage());\n        projectConfigDTO.setAnalyzeResponseEnable(1);\n        projectConfigDTO.setDslAnalyzeEnable(23);\n        assertThat(projectConfigService.updateOrInitProjectConfig(projectConfigDTO, null).v1().getMessage())\n            .isEqualTo(Result.buildParamIllegal(\"DSL分析开关非法\").getMessage());\n        projectConfigDTO.setDslAnalyzeEnable(1);\n        projectConfigDTO.setAggrAnalyzeEnable(23);\n        assertThat(projectConfigService.updateOrInitProjectConfig(projectConfigDTO, null).v1().getMessage())\n            .isEqualTo(Result.buildParamIllegal(\"聚合分析开关非法\").getMessage());\n        projectConfigDTO.setAggrAnalyzeEnable(1);\n        projectConfigDTO.setIsSourceSeparated(23);\n        assertThat(projectConfigService.updateOrInitProjectConfig(projectConfigDTO, null).v1().getMessage())\n            .isEqualTo(Result.buildParamIllegal(\"索引存储分离开关非法\").getMessage());\n        projectConfigDTO.setIsSourceSeparated(1);\n        when(projectConfigDAO.checkProjectConfigByProjectId(1)).thenReturn(true);\n        when(projectConfigDAO.update(any())).thenReturn(1);\n        assertThat(projectConfigService.updateOrInitProjectConfig(projectConfigDTO, null).v1().success()).isTrue();\n        when(projectConfigDAO.checkProjectConfigByProjectId(1)).thenReturn(false);\n        when(projectConfigDAO.insert(any())).thenReturn(1);\n        assertThat(projectConfigService.updateOrInitProjectConfig(projectConfigDTO, null).v1().success()).isTrue();\n        // Verify the results\n    }\n\n    @Test\n    void testDeleteByProjectId() {\n        // Setup\n        when(projectConfigDAO.checkProjectConfigByProjectId(anyInt())).thenReturn(true);\n        when(projectConfigDAO.deleteByProjectId(anyInt())).thenReturn(1);\n\n        // Run the test\n        projectConfigService.deleteByProjectId(0);\n\n        // Verify the results\n        verify(projectConfigDAO).deleteByProjectId(0);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/task/JudgeTemplateBlockWriteTaskTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task;\n\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\nimport com.didichuxing.datachannel.arius.admin.biz.indices.IndicesManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.util.SizeUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.util.CustomDataSource;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport java.util.List;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.junit.Test;\nimport org.junit.jupiter.api.Assertions;\nimport org.mockito.Mock;\n\n/**\n * @Authoer: zyl\n * @Date: 2022/07/11\n * @Version: 1.0\n */\n\npublic class JudgeTemplateBlockWriteTaskTest {\n\n    @Mock\n    private IndicesManager       indicesManager;\n\n    @Mock\n    private IndexTemplateService indexTemplateService;\n\n    @Test\n    public void executeTest() {\n        initMocks(this);\n        Result<Void> result = new Result<>();\n        result.setCode(1);\n\n        when(indexTemplateService.getLogicTemplateWithPhysicalsById(1))\n            .thenReturn(CustomDataSource.getIndexTemplateWithPhyTemplates());\n        IndexTemplateWithPhyTemplates indexTemplateWithPhyTemplates = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(1);\n        long limitDiskSize = (long) (indexTemplateWithPhyTemplates.getDiskSize() * 1024 * 1024 * 1024);\n        IndexTemplatePhy masterPhyTemplate = indexTemplateWithPhyTemplates.getMasterPhyTemplate();\n        when(indicesManager.listIndexCatInfoByTemplatePhyId(masterPhyTemplate.getId()))\n            .thenReturn(CustomDataSource.getCatIndexResult());\n\n        List<CatIndexResult> catIndexResults = indicesManager\n            .listIndexCatInfoByTemplatePhyId(masterPhyTemplate.getId());\n        long templateIndicesDiskSum = 0;\n        if (CollectionUtils.isNotEmpty(catIndexResults)) {\n            templateIndicesDiskSum = catIndexResults.stream().mapToLong(r -> SizeUtil.getUnitSize(r.getStoreSize()))\n                .sum();\n        }\n\n        if (templateIndicesDiskSum >= templateIndicesDiskSum) {\n            when(indexTemplateService.updateBlockWriteState(1, true)).thenReturn(CustomDataSource.getResult());\n            result = indexTemplateService.updateBlockWriteState(1, true);\n        }\n\n        Assertions.assertEquals(result.getCode(), 0);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/util/CustomDataSource.java",
    "content": "package com.didichuxing.datachannel.arius.admin.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.GatewayHeartbeat;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.app.ProjectTemplateAuthDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterPhyDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterRegionDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ClusterSettingDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESClusterRoleHostDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESLogicClusterDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESPackageDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.ESZeusConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.cluster.PluginDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.config.AriusConfigInfoDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.oprecord.OperateRecordDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateConfigDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.IndexTemplateDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.template.alias.IndexTemplateAliasDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleInfo;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectClusterLogicAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.project.ProjectTemplateAuth;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.region.ClusterRegion;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.config.AriusConfigInfoPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.ecm.ESMachineNormsPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.esplugin.PluginPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.gateway.GatewayClusterNodePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.metrics.UserConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.operaterecord.OperateRecordInfoPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ESUserPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectClusterLogicAuthPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.project.ProjectTemplateAuthPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePhyPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateAliasPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateConfigPO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.TemplateTypePO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.vo.cluster.ESClusterRoleHostVO;\nimport com.didichuxing.datachannel.arius.admin.common.constant.DataCenterEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.PluginTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.RunModeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterDynamicConfigsEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.cluster.ClusterResourceTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectClusterLogicAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.project.ProjectTemplateAuthEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeRoleEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterNodeStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.resource.ESClusterTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectBriefVO;\nimport com.didiglobal.knowframework.security.common.vo.project.ProjectVO;\nimport com.didiglobal.knowframework.security.common.vo.user.UserBriefVO;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.stream.Stream;\nimport org.springframework.mock.web.MockMultipartFile;\n\npublic class CustomDataSource {\n\n    public static final String PHY_CLUSTER_NAME      = \"admin_test_1\";\n    public static final String PHY_CLUSTER_NAME_LOGI = \"logi-em-matedata-cluster\";\n\n    public static final String OPERATOR              = \"admin\";\n\n    public static final int    SIZE                  = 10;\n\n    public static <T> Stream<T> fromJSON(String json, Class<T> cls) {\n        return Stream.of(JSON.parseObject(json, cls));\n    }\n\n    public static AriusConfigInfoDTO ariusConfigInfoDTOFactory() {\n        AriusConfigInfoDTO configInfoDTO = new AriusConfigInfoDTO();\n        configInfoDTO.setValue(\"1234\");\n        configInfoDTO.setValueName(\"wp\");\n        configInfoDTO.setValueGroup(\"1\");\n        configInfoDTO.setDimension(1);\n        configInfoDTO.setMemo(\"\");\n        configInfoDTO.setStatus(1);\n        return configInfoDTO;\n    }\n\n    public static OperateRecordDTO OperateRecordDTOFatory() {\n        OperateRecordDTO operateRecordDTO = new OperateRecordDTO();\n        operateRecordDTO.setContent(\"\");\n        operateRecordDTO.setModuleId(2);\n        operateRecordDTO.setOperateId(9);\n        return operateRecordDTO;\n    }\n\n    public static GatewayHeartbeat gatewayHeartbeatFactory() {\n        GatewayHeartbeat gatewayHeartbeat = new GatewayHeartbeat();\n        gatewayHeartbeat.setClusterName(PHY_CLUSTER_NAME);\n        gatewayHeartbeat.setHostName(\"www.wpk.com\");\n        gatewayHeartbeat.setPort(8080);\n        return gatewayHeartbeat;\n    }\n\n    public static ESZeusConfigDTO esZeusConfigDTOFactory() {\n        ESZeusConfigDTO esZeusConfigDTO = new ESZeusConfigDTO();\n        esZeusConfigDTO.setClusterName(PHY_CLUSTER_NAME);\n        esZeusConfigDTO.setEnginName(\"engin\");\n        esZeusConfigDTO.setTypeName(\"es\");\n        esZeusConfigDTO.setContent(\"\");\n        esZeusConfigDTO.setClusterId(1l);\n        return esZeusConfigDTO;\n    }\n\n    public static ClusterPhy esClusterPhyFactory() {\n        ClusterPhy clusterPhy = new ClusterPhy();\n        clusterPhy.setId(1);\n        clusterPhy.setCluster(PHY_CLUSTER_NAME);\n        clusterPhy.setPlugIds(\"1,2,3,4,5\");\n        return clusterPhy;\n    }\n\n    public static ESConfigDTO esConfigDTOFactory() {\n        ESConfigDTO esConfigDTO = new ESConfigDTO();\n        esConfigDTO.setClusterId(1l);\n        esConfigDTO.setEnginName(\"wpkEngin\");\n        esConfigDTO.setTypeName(\"wpk\");\n        esConfigDTO.setVersionConfig(1);\n        esConfigDTO.setDesc(\"\");\n        esConfigDTO.setSelected(1);\n        esConfigDTO.setConfigData(\"you are right\");\n        esConfigDTO.setVersionTag(\"1.0\");\n        esConfigDTO.setVersionConfig(1);\n        return esConfigDTO;\n    }\n\n    public static ESPackageDTO esPackageDTOFactory() {\n        ESPackageDTO esPackageDTO = new ESPackageDTO();\n        esPackageDTO.setUrl(\"www.baidu.com\");\n        esPackageDTO.setCreator(\"wpk\");\n        esPackageDTO.setDesc(\"\");\n        esPackageDTO.setEsVersion(\"7.6.0.0\");\n        esPackageDTO.setFileName(\"wpk\");\n        esPackageDTO.setManifest(3);\n        esPackageDTO.setMd5(\"\");\n        esPackageDTO.setUploadFile(new MockMultipartFile(\"wpk\", new byte[3]));\n        return esPackageDTO;\n    }\n\n    public static ESMachineNormsPO esMachineNormsPOFactory() {\n        ESMachineNormsPO esMachineNormsPO = new ESMachineNormsPO();\n        esMachineNormsPO.setRole(\"wpk\");\n        esMachineNormsPO.setSpec(\"wpk\");\n        return esMachineNormsPO;\n    }\n\n    public static PluginDTO esPluginDTOFactory() {\n        PluginDTO pluginDTO = new PluginDTO();\n        pluginDTO.setVersion(\"1.1.1.1000\");\n        pluginDTO.setPDefault(PluginTypeEnum.DEFAULT_PLUGIN.getCode());\n        pluginDTO.setName(\"test\");\n        pluginDTO.setCreator(\"wpk\");\n        pluginDTO.setDesc(\"test\");\n        pluginDTO.setFileName(\"test\");\n        pluginDTO.setUrl(\"\");\n        pluginDTO.setMd5(\"\");\n        pluginDTO.setUploadFile(new MockMultipartFile(\"test\", new byte[] { 0, 1, 2 }));\n        return pluginDTO;\n    }\n\n    public static ClusterPhyDTO esClusterDTOFactory() {\n        ClusterPhyDTO esClusterDTO = new ClusterPhyDTO();\n        esClusterDTO.setId(157);\n        esClusterDTO.setCluster(\"lyn-test-public12-08\");\n        esClusterDTO.setDesc(\"test\");\n        esClusterDTO.setHttpAddress(\"1234\");\n        esClusterDTO.setType(ESClusterTypeEnum.ES_DOCKER.getCode());\n        esClusterDTO.setDataCenter(DataCenterEnum.CN.getCode());\n        esClusterDTO.setIdc(\"a test\");\n        esClusterDTO.setEsVersion(\"7.6.0.0\");\n        esClusterDTO.setImageName(\"test\");\n        esClusterDTO.setCreator(\"wpk\");\n        esClusterDTO.setLevel(0);\n        esClusterDTO.setPackageId(1L);\n        esClusterDTO.setRunMode(RunModeEnum.READ_WRITE_SHARE.getRunMode());\n        esClusterDTO.setHttpWriteAddress(\"2.0.0.0\");\n        esClusterDTO.setWriteAddress(\"2.0.0.0\");\n        esClusterDTO.setReadAddress(\"2.0.0.0\");\n        esClusterDTO.setNsTree(\"test\");\n        esClusterDTO.setHealth(1);\n        esClusterDTO.setPassword(\"\");\n        return esClusterDTO;\n    }\n\n    public static TemplateAliasPO templateAliasSource() {\n        TemplateAliasPO po = new TemplateAliasPO();\n        po.setId(1);\n        po.setName(\"test\");\n        po.setLogicId(1);\n        po.setLogicId(1);\n        return po;\n    }\n\n    public static IndexTemplateAliasDTO indexTemplateAliasDTOFactory() {\n        IndexTemplateAliasDTO dto = new IndexTemplateAliasDTO();\n        dto.setName(\"test\");\n        dto.setLogicId(1);\n        return dto;\n    }\n\n    public static IndexTemplateConfigDTO indexTemplateConfigDTOFactory() {\n        IndexTemplateConfigDTO dto = new IndexTemplateConfigDTO();\n        dto.setId(1L);\n        dto.setLogicId(1);\n        dto.setDynamicLimitEnable(1);\n        dto.setMappingImproveEnable(1);\n        dto.setAdjustTpsFactor(1d);\n        dto.setIsSourceSeparated(1);\n        dto.setDynamicLimitEnable(1);\n        dto.setDisableIndexRollover(true);\n        return dto;\n    }\n\n    public static ESUserPO esUserPO() {\n        ESUserPO esUserPO = new ESUserPO();\n        esUserPO.setIsRoot(0);\n        esUserPO.setVerifyCode(\"verifyCode\");\n        esUserPO.setMemo(\"memo\");\n        esUserPO.setQueryThreshold(100);\n        esUserPO.setCluster(\"cluster\");\n        esUserPO.setSearchType(0);\n        esUserPO.setDataCenter(\"dataCenter\");\n        esUserPO.setProjectId(1);\n        esUserPO.setIp(\"192.168.111.111\");\n        return esUserPO;\n    }\n\n    public static ProjectBriefVO projectBriefVO() {\n        final ProjectBriefVO projectBriefVO = new ProjectBriefVO();\n        projectBriefVO.setId(1);\n        projectBriefVO.setProjectCode(\"123456\");\n        projectBriefVO.setProjectName(\"test\");\n        return projectBriefVO;\n\n    }\n\n    public static ProjectVO projectVO() {\n        final ProjectVO projectVO = new ProjectVO();\n        projectVO.setId(1);\n        projectVO.setProjectCode(\"123456\");\n        projectVO.setProjectName(\"test\");\n        final UserBriefVO userBriefVO = new UserBriefVO();\n        userBriefVO.setId(1);\n        userBriefVO.setUserName(\"admin\");\n        userBriefVO.setRealName(\"admin\");\n        userBriefVO.setDeptId(1);\n        projectVO.setUserList(Collections.singletonList(userBriefVO));\n        projectVO.setOwnerList(Collections.singletonList(userBriefVO));\n        projectVO.setDescription(\"test\");\n        return projectVO;\n    }\n\n    public static ProjectConfigPO projectConfigPO() {\n        ProjectConfigPO projectConfigPO = new ProjectConfigPO();\n        projectConfigPO.setProjectId(1);\n        projectConfigPO.setSlowQueryTimes(1000);\n        projectConfigPO.setMemo(\"\");\n        return projectConfigPO;\n    }\n\n    public static TemplateConfigPO templateConfigSource() {\n        TemplateConfigPO po = new TemplateConfigPO();\n        po.setLogicId(1);\n        po.setId(1L);\n        po.setAdjustShardFactor(1d);\n        return po;\n    }\n\n    public static IndexTemplatePhyPO templatePhysicalSource() {\n        IndexTemplatePhyPO po = new IndexTemplatePhyPO();\n        po.setLogicId(1);\n        po.setName(\"test\");\n        po.setExpression(\"1\");\n        po.setCluster(PHY_CLUSTER_NAME);\n        po.setRack(\"1\");\n        po.setShard(1);\n        po.setShardRouting(1);\n        po.setVersion(1);\n        po.setRole(1);\n        po.setStatus(1);\n        po.setConfig(\"{}\");\n        return po;\n    }\n\n    public static IndexTemplatePO templateLogicSource() {\n        IndexTemplatePO po = new IndexTemplatePO();\n        po.setId(1);\n        po.setProjectId(1);\n        po.setName(\"test\");\n        po.setDataType(1);\n        po.setDateFormat(\"\");\n        po.setDataCenter(\"\");\n        po.setExpireTime(3);\n        po.setHotTime(3);\n        po.setDateField(\"\");\n        po.setDateFieldFormat(\"\");\n        po.setIdField(\"\");\n        po.setRoutingField(\"\");\n        po.setExpression(\"\");\n        po.setDesc(\"\");\n        po.setQuota(0D);\n        po.setIngestPipeline(\"\");\n        po.setWriteRateLimit(-1);\n        return po;\n    }\n\n    public static ESClusterRoleDTO esRoleClusterDTOFactory() {\n        ESClusterRoleDTO esClusterRoleDTO = new ESClusterRoleDTO();\n        esClusterRoleDTO.setRoleClusterName(\"wpk\");\n        esClusterRoleDTO.setRole(ESClusterNodeRoleEnum.CLIENT_NODE.getDesc());\n        esClusterRoleDTO.setMachineSpec(\"\");\n        esClusterRoleDTO.setPlugIds(\"\");\n        esClusterRoleDTO.setElasticClusterId(12345L);\n        esClusterRoleDTO.setPodNumber(3);\n        esClusterRoleDTO.setCfgId(1);\n        esClusterRoleDTO.setPlugIds(\"\");\n        esClusterRoleDTO.setEsVersion(\"\");\n        esClusterRoleDTO.setPidCount(1);\n        return esClusterRoleDTO;\n    }\n\n    public static ESClusterRoleHostDTO esRoleClusterHostDTOFactory() {\n        ESClusterRoleHostDTO esClusterRoleHostDTO = new ESClusterRoleHostDTO();\n        esClusterRoleHostDTO.setCluster(\"test_cluster\");\n        esClusterRoleHostDTO.setIp(\"127.0.0.0\");\n        esClusterRoleHostDTO.setHostname(\"wpk\");\n        esClusterRoleHostDTO.setPort(\"8080\");\n        esClusterRoleHostDTO.setRole(ESClusterNodeRoleEnum.DATA_NODE.getCode());\n        esClusterRoleHostDTO.setStatus(ESClusterNodeStatusEnum.ONLINE.getCode());\n        esClusterRoleHostDTO.setRoleClusterId(1234L);\n        esClusterRoleHostDTO.setNodeSet(\"\");\n        esClusterRoleHostDTO.setRegionId(100);\n        return esClusterRoleHostDTO;\n    }\n\n    public static ESLogicClusterDTO esLogicClusterDTOFactory() {\n        ESLogicClusterDTO esLogicClusterDTO = new ESLogicClusterDTO();\n        esLogicClusterDTO.setName(\"wpkTest\");\n        esLogicClusterDTO.setProjectId(1);\n        esLogicClusterDTO.setType(ClusterResourceTypeEnum.EXCLUSIVE.getCode());\n        esLogicClusterDTO.setQuota(3d);\n        esLogicClusterDTO.setMemo(\"Test\");\n        return esLogicClusterDTO;\n    }\n\n    public static ClusterRegionDTO clusterRegionDTOFactory() {\n        ClusterRegionDTO clusterRegionDTO = new ClusterRegionDTO();\n        //clusterRegionDTO.setLogicClusterId(AdminConstant.REGION_NOT_BOUND_LOGIC_CLUSTER_ID);\n        clusterRegionDTO.setPhyClusterName(\"wpk\");\n        return clusterRegionDTO;\n    }\n\n    public static ClusterSettingDTO clusterSettingDTOFactory() {\n        ClusterSettingDTO clusterSettingDTO = new ClusterSettingDTO();\n        clusterSettingDTO.setClusterName(PHY_CLUSTER_NAME);\n        clusterSettingDTO.setKey(ClusterDynamicConfigsEnum.CLUSTER_ROUTING_ALLOCATION_BALANCE_INDEX.getName());\n        clusterSettingDTO.setValue(\"0.61\");\n        return clusterSettingDTO;\n    }\n\n    public static ProjectTemplateAuthDTO appTemplateAuthDTOFactory() {\n        ProjectTemplateAuthDTO projectTemplateAuthDTO = new ProjectTemplateAuthDTO();\n        projectTemplateAuthDTO.setProjectId(1);\n        projectTemplateAuthDTO.setTemplateId(1);\n        projectTemplateAuthDTO.setType(ProjectTemplateAuthEnum.RW.getCode());\n        return projectTemplateAuthDTO;\n    }\n\n    public static IndexTemplateDTO indexTemplateLogicDTOFactory() {\n        IndexTemplateDTO indexTemplateDTO = new IndexTemplateDTO();\n        indexTemplateDTO.setName(\"wpkTest-1\");\n        indexTemplateDTO.setProjectId(1);\n        indexTemplateDTO.setDataType(1);\n        indexTemplateDTO.setDateFormat(\"_yyyy-MM-dd\");\n        indexTemplateDTO.setExpression(\"wpkTest-1*\");\n        indexTemplateDTO.setDateField(\"timeStamp\");\n        indexTemplateDTO.setDataCenter(\"cn\");\n        indexTemplateDTO.setQuota(30D);\n\n        return indexTemplateDTO;\n    }\n\n    public static TemplateTypePO templateTypeSource() {\n        TemplateTypePO po = new TemplateTypePO();\n        po.setId(1);\n        po.setName(\"test\");\n        return po;\n    }\n\n    public static List<TemplateAliasPO> getTemplateAliasPOList() {\n        List<TemplateAliasPO> list = new ArrayList<>();\n        for (int i = 0; i <= SIZE; i++) {\n            TemplateAliasPO templateAliasPO = CustomDataSource.templateAliasSource();\n            templateAliasPO.setName(templateAliasPO.getName() + i);\n            list.add(templateAliasPO);\n        }\n        return list;\n    }\n\n    public static ProjectClusterLogicAuth appClusterLogicAuthSource() {\n        ProjectClusterLogicAuth projectClusterLogicAuth = new ProjectClusterLogicAuth();\n        projectClusterLogicAuth.setLogicClusterId(897L);\n        projectClusterLogicAuth.setProjectId(1);\n        projectClusterLogicAuth.setId(451L);\n        projectClusterLogicAuth.setType(ProjectClusterLogicAuthEnum.ACCESS.getCode());\n        return projectClusterLogicAuth;\n    }\n\n    public static ProjectTemplateAuth appTemplateAuthSource() {\n        ProjectTemplateAuth projectTemplateAuth = new ProjectTemplateAuth();\n        projectTemplateAuth.setProjectId(1);\n        projectTemplateAuth.setTemplateId(1);\n        projectTemplateAuth.setId(1l);\n        return projectTemplateAuth;\n    }\n\n    public static List<ProjectTemplateAuth> getAppTemplateAuthList() {\n        List<ProjectTemplateAuth> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            ProjectTemplateAuth po = CustomDataSource.appTemplateAuthSource();\n            po.setTemplateId(i);\n            po.setId((long) i);\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static ProjectTemplateAuthPO projectTemplateAuthPO() {\n        ProjectTemplateAuthPO projectTemplateAuthPO = new ProjectTemplateAuthPO();\n        projectTemplateAuthPO.setId(1L);\n        projectTemplateAuthPO.setProjectId(1);\n        projectTemplateAuthPO.setTemplateId(1);\n        projectTemplateAuthPO.setType(ProjectTemplateAuthEnum.R.getCode());\n        return projectTemplateAuthPO;\n    }\n\n    public static ProjectClusterLogicAuthPO projectClusterLogicAuthPO() {\n        ProjectClusterLogicAuthPO projectClusterLogicAuthPO = new ProjectClusterLogicAuthPO();\n        projectClusterLogicAuthPO.setId(1L);\n        projectClusterLogicAuthPO.setProjectId(1);\n        projectClusterLogicAuthPO.setLogicClusterId(1L);\n        projectClusterLogicAuthPO.setType(1);\n        return projectClusterLogicAuthPO;\n\n    }\n\n    public static List<IndexTemplatePO> getTemplateLogicPOList() {\n        List<IndexTemplatePO> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            IndexTemplatePO po = CustomDataSource.templateLogicSource();\n            po.setId(i);\n            po.setName(po.getName() + \"i\");\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static List<IndexTemplatePhyPO> getTemplatePhysicalPOList() {\n        List<IndexTemplatePhyPO> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            IndexTemplatePhyPO po = CustomDataSource.templatePhysicalSource();\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static List<TemplateTypePO> getTemplateTypePOList() {\n        List<TemplateTypePO> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            TemplateTypePO po = CustomDataSource.templateTypeSource();\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static List<ProjectClusterLogicAuth> getAppClusterLogicAuthList() {\n        List<ProjectClusterLogicAuth> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            ProjectClusterLogicAuth po = CustomDataSource.appClusterLogicAuthSource();\n            po.setId((long) i);\n            po.setLogicClusterId((long) i);\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static IndexTemplatePhy getIndexTemplatePhy() {\n        IndexTemplatePhy indexTemplatePhy = new IndexTemplatePhy();\n        indexTemplatePhy.setId(1L);\n        indexTemplatePhy.setLogicId(1099);\n        return indexTemplatePhy;\n    }\n\n    public static List<IndexTemplatePhy> getIndexTemplatePhyList() {\n        List<IndexTemplatePhy> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            IndexTemplatePhy po = CustomDataSource.getIndexTemplatePhy();\n            po.setId((long) i);\n            po.setLogicId(i);\n            po.setCluster(PHY_CLUSTER_NAME);\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static ClusterLogic getClusterLogic() {\n        ClusterLogic clusterLogic = new ClusterLogic();\n        clusterLogic.setId(1L);\n        clusterLogic.setName(\"test\");\n        return clusterLogic;\n    }\n\n    public static List<ClusterLogic> getClusterLogicList() {\n        List<ClusterLogic> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            ClusterLogic po = CustomDataSource.getClusterLogic();\n            po.setId((long) i);\n            po.setName(\"test\" + i);\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static UserConfigPO getMetricsConfigPO() {\n        UserConfigPO userConfigPO = new UserConfigPO();\n        userConfigPO.setId(1);\n        userConfigPO.setConfigInfo(\n            \"[{\\\"domainAccount\\\":\\\"admin\\\",\\\"firstUserConfigType\\\":\\\"cluster\\\",\\\"userConfigTypes\\\":[\\\"cpuUsage\\\",\\\"cpuLoad1M\\\",\\\"cpuLoad5M\\\",\\\"cpuLoad15M\\\",\\\"diskUsage\\\",\\\"diskInfo\\\",\\\"nodesForDiskUsageGte75Percent\\\",\\\"recvTransSize\\\",\\\"sendTransSize\\\",\\\"readTps\\\",\\\"writeTps\\\",\\\"searchLatency\\\",\\\"indexingLatency\\\",\\\"shardNu\\\",\\\"movingShards\\\",\\\"bigShards\\\",\\\"bigIndices\\\",\\\"invalidNodes\\\",\\\"pendingTasks\\\"],\\\"secondUserConfigType\\\":\\\"overview\\\"},{\\\"domainAccount\\\":\\\"admin\\\",\\\"firstUserConfigType\\\":\\\"cluster\\\",\\\"userConfigTypes\\\":[\\\"os-cpu-percent\\\",\\\"os-cpu-load_average-1m\\\",\\\"os-cpu-load_average-5m\\\",\\\"os-cpu-load_average-15m\\\",\\\"fs-total-disk_free_percent\\\",\\\"transport-tx_count_rate\\\",\\\"transport-rx_count_rate\\\",\\\"transport-tx_size_in_bytes_rate\\\",\\\"transport-rx_size_in_bytes_rate\\\",\\\"indices-indexing-index_total_rate\\\",\\\"indices-indexing-index_time_in_millis\\\",\\\"thread_pool-bulk-rejected\\\",\\\"thread_pool-bulk-queue\\\",\\\"indices-search-query_total_rate\\\",\\\"indices-search-fetch_total_rate\\\",\\\"indices-search-query_time_in_millis\\\",\\\"indices-search-fetch_time_in_millis\\\",\\\"thread_pool-search-queue\\\",\\\"thread_pool-search-rejected\\\",\\\"indices-search-scroll_current\\\",\\\"indices-search-scroll_time_in_millis\\\",\\\"indices-merges-total_time_in_millis\\\",\\\"indices-refresh-total_time_in_millis\\\",\\\"indices-flush-total_time_in_millis\\\",\\\"indices-query_cache-hit_count\\\",\\\"indices-query_cache-miss_count\\\",\\\"indices-request_cache-hit_count\\\",\\\"indices-request_cache-miss_count\\\",\\\"http-current_open\\\",\\\"indices-segments-count\\\",\\\"indices-segments-memory_in_bytes\\\",\\\"indices-segments-term_vectors_memory_in_bytes\\\",\\\"indices-segments-points_memory_in_bytes\\\",\\\"indices-segments-doc_values_memory_in_bytes\\\",\\\"indices-segments-index_writer_memory_in_bytes\\\",\\\"indices-docs-count\\\",\\\"indices-store-size_in_bytes\\\",\\\"indices-translog-uncommitted_size_in_bytes\\\",\\\"indices-query_cache-memory_size_in_bytes\\\",\\\"indices-request_cache-memory_size_in_bytes\\\",\\\"jvm-gc-young-collection_count_rate\\\",\\\"jvm-gc-old-collection_count_rate\\\",\\\"jvm-gc-young-collection_time_in_millis\\\",\\\"jvm-gc-old-collection_time_in_millis\\\",\\\"jvm-mem-heap_used_in_bytes\\\",\\\"jvm-mem-non_heap_used_in_bytes\\\",\\\"jvm-mem-heap_used_percent\\\"],\\\"secondUserConfigType\\\":\\\"node\\\"},{\\\"domainAccount\\\":\\\"admin\\\",\\\"firstUserConfigType\\\":\\\"user_show\\\",\\\"userConfigTypes\\\":[\\\"docsCount\\\",\\\"docsDeleted\\\",\\\"priStoreSize\\\",\\\"storeSize\\\"],\\\"secondUserConfigType\\\":\\\"indexSearch\\\"},{\\\"domainAccount\\\":\\\"admin\\\",\\\"firstUserConfigType\\\":\\\"user_show\\\",\\\"userConfigTypes\\\":[\\\"searchCount\\\",\\\"totalCostAvg\\\"],\\\"secondUserConfigType\\\":\\\"dslTemplate\\\"},{\\\"domainAccount\\\":\\\"admin\\\",\\\"firstUserConfigType\\\":\\\"cluster\\\",\\\"userConfigTypes\\\":[\\\"shardNu\\\",\\\"store-size_in_bytes\\\",\\\"docs-count\\\",\\\"search-query_total_rate\\\",\\\"search-fetch_total_rate\\\",\\\"merges-total_rate\\\",\\\"refresh-total_rate\\\",\\\"flush-total_rate\\\",\\\"indexing-index_total_rate\\\",\\\"indexing-index_time_in_millis\\\",\\\"search-query_time_in_millis\\\",\\\"search-fetch_time_in_millis\\\",\\\"search-scroll_total_rate\\\",\\\"search-scroll_time_in_millis\\\",\\\"merges-total_time_in_millis\\\",\\\"refresh-total_time_in_millis\\\",\\\"flush-total_time_in_millis\\\",\\\"query_cache-memory_size_in_bytes\\\",\\\"segments-memory_in_bytes\\\",\\\"segments-term_vectors_memory_in_bytes\\\",\\\"segments-points_memory_in_bytes\\\",\\\"segments-doc_values_memory_in_bytes\\\",\\\"segments-index_writer_memory_in_bytes\\\",\\\"translog-size_in_bytes\\\"],\\\"secondUserConfigType\\\":\\\"index\\\"}]\");\n        return userConfigPO;\n    }\n\n    public static String metricInfo() {\n        return \"[{\\\"firstUserConfigType\\\":\\\"cluster\\\",\\\"userName\\\":\\\"admin\\\",\\\"userConfigTypes\\\":[\\\"cpuUsage\\\",\\\"cpuLoad1M\\\",\\\"cpuLoad5M\\\",\\\"cpuLoad15M\\\",\\\"diskUsage\\\",\\\"diskInfo\\\",\\\"nodesForDiskUsageGte75Percent\\\",\\\"recvTransSize\\\",\\\"sendTransSize\\\",\\\"readTps\\\",\\\"writeTps\\\",\\\"searchLatency\\\",\\\"indexingLatency\\\",\\\"shardNu\\\",\\\"movingShards\\\",\\\"bigShards\\\",\\\"bigIndices\\\",\\\"invalidNodes\\\",\\\"pendingTasks\\\"],\\\"secondUserConfigType\\\":\\\"overview\\\"},{\\\"firstUserConfigType\\\":\\\"cluster\\\",\\\"userName\\\":\\\"admin\\\",\\\"userConfigTypes\\\":[\\\"os-cpu-percent\\\",\\\"os-cpu-load_average-1m\\\",\\\"os-cpu-load_average-5m\\\",\\\"os-cpu-load_average-15m\\\",\\\"fs-total-disk_free_percent\\\",\\\"transport-tx_count_rate\\\",\\\"transport-rx_count_rate\\\",\\\"transport-tx_size_in_bytes_rate\\\",\\\"transport-rx_size_in_bytes_rate\\\",\\\"indices-indexing-index_total_rate\\\",\\\"indices-indexing-index_time_in_millis\\\",\\\"thread_pool-bulk-rejected\\\",\\\"thread_pool-bulk-queue\\\",\\\"indices-search-query_total_rate\\\",\\\"indices-search-fetch_total_rate\\\",\\\"indices-search-query_time_in_millis\\\",\\\"indices-search-fetch_time_in_millis\\\",\\\"thread_pool-search-queue\\\",\\\"thread_pool-search-rejected\\\",\\\"indices-search-scroll_current\\\",\\\"indices-search-scroll_time_in_millis\\\",\\\"indices-merges-total_time_in_millis\\\",\\\"indices-refresh-total_time_in_millis\\\",\\\"indices-flush-total_time_in_millis\\\",\\\"indices-query_cache-hit_count\\\",\\\"indices-query_cache-miss_count\\\",\\\"indices-request_cache-hit_count\\\",\\\"indices-request_cache-miss_count\\\",\\\"http-current_open\\\",\\\"indices-segments-count\\\",\\\"indices-segments-memory_in_bytes\\\",\\\"indices-segments-term_vectors_memory_in_bytes\\\",\\\"indices-segments-points_memory_in_bytes\\\",\\\"indices-segments-doc_values_memory_in_bytes\\\",\\\"indices-segments-index_writer_memory_in_bytes\\\",\\\"indices-docs-count\\\",\\\"indices-store-size_in_bytes\\\",\\\"indices-translog-uncommitted_size_in_bytes\\\",\\\"indices-query_cache-memory_size_in_bytes\\\",\\\"indices-request_cache-memory_size_in_bytes\\\",\\\"jvm-gc-young-collection_count_rate\\\",\\\"jvm-gc-old-collection_count_rate\\\",\\\"jvm-gc-young-collection_time_in_millis\\\",\\\"jvm-gc-old-collection_time_in_millis\\\",\\\"jvm-mem-heap_used_in_bytes\\\",\\\"jvm-mem-non_heap_used_in_bytes\\\",\\\"jvm-mem-heap_used_percent\\\"],\\\"secondUserConfigType\\\":\\\"node\\\"},{\\\"firstUserConfigType\\\":\\\"user_show\\\",\\\"userName\\\":\\\"admin\\\",\\\"userConfigTypes\\\":[\\\"docsCount\\\",\\\"docsDeleted\\\",\\\"priStoreSize\\\",\\\"storeSize\\\"],\\\"secondUserConfigType\\\":\\\"indexSearch\\\"},{\\\"firstUserConfigType\\\":\\\"user_show\\\",\\\"userName\\\":\\\"admin\\\",\\\"userConfigTypes\\\":[\\\"searchCount\\\",\\\"totalCostAvg\\\"],\\\"secondUserConfigType\\\":\\\"dslTemplate\\\"},{\\\"firstUserConfigType\\\":\\\"cluster\\\",\\\"userName\\\":\\\"admin\\\",\\\"userConfigTypes\\\":[\\\"shardNu\\\",\\\"store-size_in_bytes\\\",\\\"docs-count\\\",\\\"search-query_total_rate\\\",\\\"search-fetch_total_rate\\\",\\\"merges-total_rate\\\",\\\"refresh-total_rate\\\",\\\"flush-total_rate\\\",\\\"indexing-index_total_rate\\\",\\\"indexing-index_time_in_millis\\\",\\\"search-query_time_in_millis\\\",\\\"search-fetch_time_in_millis\\\",\\\"search-scroll_total_rate\\\",\\\"search-scroll_time_in_millis\\\",\\\"merges-total_time_in_millis\\\",\\\"refresh-total_time_in_millis\\\",\\\"flush-total_time_in_millis\\\",\\\"query_cache-memory_size_in_bytes\\\",\\\"segments-memory_in_bytes\\\",\\\"segments-term_vectors_memory_in_bytes\\\",\\\"segments-points_memory_in_bytes\\\",\\\"segments-doc_values_memory_in_bytes\\\",\\\"segments-index_writer_memory_in_bytes\\\",\\\"translog-size_in_bytes\\\"],\\\"secondUserConfigType\\\":\\\"index\\\"}]\";\n    }\n\n    public static void main(String[] args) {\n        final UserConfigPO metricsConfigPO = CustomDataSource.getMetricsConfigPO();\n        final String metricInfo = metricsConfigPO.getConfigInfo();\n        final JSONArray parse = JSONArray.parseArray(metricInfo);\n        for (Object o : parse) {\n            String userName = ((JSONObject) o).getString(\"domainAccount\");\n            ((JSONObject) o).remove(\"domainAccount\");\n            ((JSONObject) o).put(\"userName\", userName);\n        }\n\n        System.out.println(parse.get(0));\n    }\n\n    public static GatewayClusterNodePO getGatewayNodePO() {\n        GatewayClusterNodePO gatewayClusterNodePO = new GatewayClusterNodePO();\n        gatewayClusterNodePO.setId(1);\n        gatewayClusterNodePO.setClusterName(PHY_CLUSTER_NAME);\n        return gatewayClusterNodePO;\n    }\n\n    public static List<GatewayClusterNodePO> getGatewayNodePOList() {\n        List<GatewayClusterNodePO> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            GatewayClusterNodePO po = CustomDataSource.getGatewayNodePO();\n            po.setId(i);\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static PluginDTO getESPluginDTO() {\n        PluginDTO pluginDTO = new PluginDTO();\n        pluginDTO.setId(1L);\n        pluginDTO.setDesc(\"test\");\n        pluginDTO.setName(\"name_test\");\n        pluginDTO.setPhysicClusterId(\"1\");\n        pluginDTO.setDesc(\"test_desc\");\n        pluginDTO.setUploadFile(new MockMultipartFile(\"test\", new byte[10]));\n        return pluginDTO;\n    }\n\n    public static PluginPO getESPluginPO() {\n        PluginPO pluginPO = new PluginPO();\n        pluginPO.setId(1L);\n        pluginPO.setDesc(\"test\");\n        pluginPO.setName(\"name_test\");\n        pluginPO.setPhysicClusterId(\"1\");\n        pluginPO.setDesc(\"test_desc\");\n        return pluginPO;\n    }\n\n    public static List<PluginPO> getESPluginPOList() {\n        List<PluginPO> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            PluginPO po = CustomDataSource.getESPluginPO();\n            po.setId((long) i);\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static OperateRecordInfoPO getOperateRecordPO() {\n        OperateRecordInfoPO operateRecordPO = new OperateRecordInfoPO();\n        operateRecordPO.setId(1);\n        return operateRecordPO;\n    }\n\n    public static List<OperateRecordInfoPO> getOperateRecordPOList() {\n        List<OperateRecordInfoPO> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            OperateRecordInfoPO po = CustomDataSource.getOperateRecordPO();\n            po.setId(i);\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static AriusConfigInfoPO getAriusConfigInfoPO() {\n        AriusConfigInfoPO ariusConfigInfoPO = new AriusConfigInfoPO();\n        ariusConfigInfoPO.setId(1);\n        ariusConfigInfoPO.setValueGroup(\"test\");\n        ariusConfigInfoPO.setValueName(\"test_name\");\n        return ariusConfigInfoPO;\n    }\n\n    public static List<AriusConfigInfoPO> getAriusConfigInfoPOList() {\n        List<AriusConfigInfoPO> list = new ArrayList<>();\n        for (int i = 1; i <= SIZE; i++) {\n            AriusConfigInfoPO po = CustomDataSource.getAriusConfigInfoPO();\n            po.setId(i);\n            po.setValueGroup(\"test\" + i);\n            po.setValueName(\"test_name\" + i);\n            list.add(po);\n        }\n        return list;\n    }\n\n    public static ClusterRoleHost getClusterRoleHost() {\n        return new ClusterRoleHost(0L, 0L, \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\",\n            0, \"attributes\");\n    }\n\n    public static ClusterRoleHost getClusterRoleHostByRealIp() {\n        return new ClusterRoleHost(0L, 0L, \"hostname\", \"ip\", \"cluster\", \"port\", 0, 0, \"rack\", \"nodeSet\", \"machineSpec\",\n            0, \"attributes\");\n    }\n\n    public static ClusterRegion getClusterRegion() {\n        return new ClusterRegion(0L, \"name\", \"logicClusterIds\", PHY_CLUSTER_NAME, \"config\");\n    }\n\n    public static ESClusterRoleHostVO getESClusterRoleHostVO() {\n        return new ESClusterRoleHostVO(0L, 0L, \"hostname\", \"ip\", PHY_CLUSTER_NAME, \"clusterLogicNames\", \"port\", 1, 0,\n            \"rack\", \"machineSpec\", \"nodeSet\", 0, \"logicDepart\", \"attributes\", \"regionName\", 0.0, 2L, 1L);\n    }\n\n    public static ClusterRoleInfo getClusterRoleInfo() {\n        return new ClusterRoleInfo(0L, 0L, \"roleClusterName\", \"role\", 0, 0, \"machineSpec\", \"esVersion\", 0, \"plugIds\",\n            false, Collections.singletonList(getClusterRoleHost()));\n    }\n\n    public static ClusterPhy getClusterPhy() {\n\n        return new ClusterPhy(0, \"cluster\", \"desc\", \"readAddress\", \"writeAddress\", \"httpAddress\", \"httpWriteAddress\", 0,\n            \"tags\", \"dataCenter\", \"idc\", 0, \"esVersion\", 0L, \"plugIds\", 0L, \"imageName\", \"nsTree\", 0, \"machineSpec\",\n            \"password\", \"creator\", Collections.singletonList(getClusterRoleInfo()),\n            Collections.singletonList(getClusterRoleHost()), 0, \"writeAction\", 0, 0L, 0L, 0L, 0.0, \"platformType\", 0,\n            \"gatewayUrl\",\"\",\"\",\"\");\n    }\n\n    public static IndexTemplateWithPhyTemplates getIndexTemplateWithPhyTemplates() {\n        IndexTemplateWithPhyTemplates indexTemplateWithPhyTemplates = new IndexTemplateWithPhyTemplates();\n        indexTemplateWithPhyTemplates.setDiskSize(1.0);\n        List<IndexTemplatePhy> physicals = new ArrayList<>();\n        IndexTemplatePhy physical = new IndexTemplatePhy();\n        physical.setRole(1);\n        physical.setId(1L);\n        physicals.add(physical);\n        indexTemplateWithPhyTemplates.setPhysicals(physicals);\n        return indexTemplateWithPhyTemplates;\n    }\n\n    public static List<CatIndexResult> getCatIndexResult() {\n        List<CatIndexResult> catIndexResults = new ArrayList<>();\n        CatIndexResult catIndexResult1 = new CatIndexResult();\n        catIndexResult1.setStoreSize(\"1gb\");\n        catIndexResults.add(catIndexResult1);\n        CatIndexResult catIndexResult2 = new CatIndexResult();\n        catIndexResult2.setStoreSize(\"2gb\");\n        catIndexResults.add(catIndexResult2);\n        return catIndexResults;\n    }\n\n    public static Result<Void> getResult() {\n        Result<Void> result = new Result<>();\n        result.setCode(ResultType.SUCCESS.getCode());\n        return result;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/util/RandomGenerator.java",
    "content": "package com.didichuxing.datachannel.arius.admin.util;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.Random;\n\npublic class RandomGenerator {\n\n    private RandomGenerator() {\n    }\n\n    private static final Random random = new Random();\n\n    private static final ILog LOGGER = LogFactory.getLog(RandomGenerator.class);\n\n    public static Integer randomInt(int low, int high) {\n        if (high <= low) {\n            throw new IllegalArgumentException(\"bound should be higher\");\n        }\n        return low + random.nextInt(high - low);\n    }\n\n    public static Double randomDouble(double low, double high) {\n        if (high <= low) {\n            throw new IllegalArgumentException(\"bound should be higher\");\n        }\n        return random.nextDouble() * (high - low) + low;\n    }\n\n    public static String randomString(int length) {\n        char[] value = new char[length];\n        for (int i = 0; i < length; i++) {\n            value[i] = randomWritableChar();\n        }\n        return new String(value);\n    }\n\n    public static char randomWritableChar() {\n        return (char) (97 + random.nextInt(26));\n    }\n\n    public static <T> T randomFromEnum(Class<? extends Enum> c) {\n        try {\n            Method method = c.getMethod(\"values\");\n            T[] ts = (T[]) method.invoke(c);\n            int index = new Random().nextInt(ts.length);\n            return ts[index];\n        } catch (NoSuchMethodException e) {\n            LOGGER.error(\"class=RandomGenerator||method=randomFromEnum||errMsg=get enum failed\", e);\n        } catch (IllegalAccessException | InvocationTargetException e) {\n            LOGGER.error(\"class=RandomGenerator||method=randomFromEnum||errMsg=\", e);\n        }\n        return null;\n    }\n\n    public static boolean randomBoolean() {\n        return new Random().nextInt() % 2 == 0;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-rest/src/test/java/com/didichuxing/datachannel/arius/admin/util/StatLineOfMethodTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.util;\n\nimport com.didichuxing.datachannel.arius.admin.common.util.YamlUtil;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport javassist.ClassPool;\nimport javassist.CtClass;\nimport javassist.CtMethod;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.io.BufferedWriter;\nimport java.io.File;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * @author wuxuan\n * @Date 2022/7/12\n */\npublic class StatLineOfMethodTest {\n    /**\n     * 将该类运行时抛出的异常记录到日志中\n     */\n    private static final ILog LOGGER            = LogFactory.getLog(StatLineOfMethodTest.class);\n    /**\n     * 统计项目中有多少超过规定代码行数的方法\n     */\n    private int                 exceedMethod      = 0;\n    /**\n     * 统计项目中有多少方法\n     */\n    private int                 methodNumber      = 0;\n    /**\n     * 记录项目中的类\n     */\n    private List<Class>         classes           = new ArrayList<>();\n    /**\n     * 记录项目中类的各个方法的信息\n     */\n    private List<InfoOfMethod>  infoOfMethods     = new ArrayList<>();\n    /**\n     * 规定的代码行数\n     */\n    private int                 standardLineOfMethod;\n    /**\n     * 输出统计代码行的文件路径\n     */\n    public static final String  STORE_FILE        = \"src/test/java/com/didichuxing/datachannel/arius/admin/statMethodLine.txt\";\n    /**\n     * 项目的根路径\n     */\n    public static final String  FILE_OF_ADMIN     = getFileOfAdmin();\n    /**\n     * 包的前缀\n     */\n    public static final String  PREFIX_OF_PACKAGE = \"com/didichuxing\";\n\n    /**\n     * 获得项目的根路径\n     */\n    public static String getFileOfAdmin() {\n        String filepath = new File(\"\").getAbsolutePath();\n        File file = new File(filepath);\n        filepath = file.getParent();\n        return filepath;\n    }\n\n    /**\n     * 初始化创建统计代码行数的文件\n     */\n    @BeforeEach\n    private void setup() throws IOException {\n        initProperties();\n        BufferedWriter bufferedWriter = null;\n        FileWriter fileWriter = null;\n        try {\n            fileWriter = new FileWriter(STORE_FILE);\n            bufferedWriter = new BufferedWriter(fileWriter);\n            bufferedWriter.write(\"本文本用于记录项目中代码行数超过60行的方法(其中方法中的空行以及注释所在行的行数都记录在内)\");\n            bufferedWriter.newLine();\n            bufferedWriter.write(\"项目中代码行数超过60行的方法记录如下：\");\n            bufferedWriter.newLine();\n            bufferedWriter.newLine();\n            bufferedWriter.write(String.format(\"%-40s\", \"类名\"));\n            bufferedWriter.write(String.format(\"%-45s\", \"方法名\"));\n            bufferedWriter.write(String.format(\"%-8s\", \"方法行数\"));\n            bufferedWriter.newLine();\n            bufferedWriter.flush();\n        } catch (Exception exception) {\n            LOGGER.error(\"class=StatLineOfMethodTest||method=setup||msg=open and write file fail\");\n        } finally {\n            bufferedWriter.close();\n            fileWriter.close();\n        }\n    }\n\n    @AfterEach\n    private void end() throws IOException {\n        BufferedWriter bufferedWriter = null;\n        FileWriter fileWriter = null;\n        try {\n            fileWriter = new FileWriter(STORE_FILE, true);\n            bufferedWriter = new BufferedWriter(fileWriter);\n            bufferedWriter.newLine();\n            bufferedWriter.write(\"据统计，项目中包含的类的个数为:\");\n            bufferedWriter.write(String.format(\"【\" + classes.size() + \"】\"));\n            bufferedWriter.newLine();\n            bufferedWriter.write(\"其中，项目中包含的方法个数为:\");\n            bufferedWriter.write(String.format(\"【\" + methodNumber + \"】\"));\n            bufferedWriter.write(\"，代码行数超过60行的方法总数为:\");\n            bufferedWriter.write(String.format(\"【\" + exceedMethod + \"】\"));\n            bufferedWriter.newLine();\n            bufferedWriter.write(\"项目中超过60行的方法占比为:\");\n            bufferedWriter.write(String.format(\"%.3f%%\", (double) exceedMethod / methodNumber * 100));\n            bufferedWriter.newLine();\n            bufferedWriter.flush();\n        } catch (Exception exception) {\n            LOGGER.error(\"class=StatLineOfMethodTest||method=end||msg=open and write file fail\");\n        } finally {\n            bufferedWriter.close();\n            fileWriter.close();\n        }\n    }\n\n    /**\n     * 从配置文件中取出规定的不能超过的标准行数赋值给standardLineOfMethod变量\n     */\n    private void initProperties() throws IOException {\n        String[] ymlPaths = { \"arius-admin-rest\", \"target\", \"classes\", \"application.yml\"};\n        String path = System.getProperty(\"user.dir\");\n        path = path.substring(0, path.lastIndexOf(File.separator) + 1) + StringUtils.join(ymlPaths, File.separator);\n        String standardLine = YamlUtil.getValue(path, \"stat.method.line.standardLineOfMethod\");\n        if (StringUtils.isEmpty(standardLine)) {\n            throw new RuntimeException(\"统计代码行需要规定的代码行数，请配置文件application.yml中设置：stat.method.line.standardLineOfMethod\");\n        } else {\n            standardLineOfMethod = Integer.parseInt(YamlUtil.getValue(path, \"stat.method.line.standardLineOfMethod\"));\n        }\n    }\n\n    /**\n     * 统计项目中各个类各个方法的代码行数，并对超过标准行数的方法进行记录\n     */\n    @Test\n    public void statNumForMethodTest() {\n        try {\n            File file = new File(FILE_OF_ADMIN);\n            // 调用函数遍历目录下的所有java文件\n            ergodicDir(file);\n            for (Class c : classes) {\n                // 不统计测试类的方法\n                if (c.getName().contains(\"test\") || c.getName().contains(\"Test\")) {\n                    continue;\n                }\n                ClassPool pool = ClassPool.getDefault();\n                // 获取一个ctClass对象\n                CtClass ctClass = pool.get(c.getName());\n                Method[] methods = c.getDeclaredMethods();\n                for (Method method : methods) {\n                    // 为了防止流水线进行jacoco命令测试出现异常，这里进行try..catch进行捕获\n                    try {\n                        methodNumber = methodNumber + 1;\n                        CtMethod ctMethod = ctClass.getDeclaredMethod(method.getName());\n                        int beginLineOfMethod = ctMethod.getMethodInfo().getLineNumber(0);\n                        int endLineOfMethod = ctMethod.getMethodInfo().getLineNumber(10000);\n                        int linenumber = endLineOfMethod - beginLineOfMethod;\n                        if (linenumber >= standardLineOfMethod) {\n                            exceedMethod = exceedMethod + 1;\n                            InfoOfMethod infoOfMethod = new InfoOfMethod(linenumber, method.getName(),\n                                c.getSimpleName());\n                            infoOfMethods.add(infoOfMethod);\n                        }\n                    } catch (Exception exception) {\n                        LOGGER.warn(\n                            \"class=StatLineOfMethodTest||method=statNumForMethodTest||msg=current capture method exception\");\n                    }\n                }\n            }\n            recordExceedMethodToFile();\n        } catch (Exception ex) {\n            LOGGER.error(\"class=StatLineOfMethodTest||method=statNumForMethodTest||msg=open file fail\");\n        }\n    }\n\n    /**\n     * 将超过标准行数的方法按照行数从高到低排序并记录到文件中\n     */\n    public void recordExceedMethodToFile() throws IOException {\n        Collections.sort(infoOfMethods);\n        for (InfoOfMethod infoOfMethod : infoOfMethods) {\n            BufferedWriter bufferedWriter = null;\n            FileWriter fileWriter = null;\n            try {\n                fileWriter = new FileWriter(STORE_FILE, true);\n                bufferedWriter = new BufferedWriter(fileWriter);\n                bufferedWriter.write(String.format(\"%-40s\", infoOfMethod.className));\n                bufferedWriter.write(String.format(\"%-45s\", infoOfMethod.methodName));\n                bufferedWriter.write(String.format(\"%8d\", infoOfMethod.methodLine));\n                bufferedWriter.newLine();\n                bufferedWriter.flush();\n            } catch (Exception exception) {\n                LOGGER\n                    .error(\"class=StatLineOfMethodTest||method=recordExceedMethodToFile||msg=open and write file fail\");\n            } finally {\n                fileWriter.close();\n                bufferedWriter.close();\n            }\n        }\n    }\n\n    /**\n     * 遍历目录下的所有java文件\n     *\n     * @param dir\n     */\n    private void ergodicDir(File dir) {\n        if (dir.isDirectory()) {\n            for (File file : dir.listFiles()) {\n                if (file.isDirectory()) {\n                    ergodicDir(file);\n                }\n\n                if (file.isFile() && file.getName().endsWith(\"java\") && file.length() > 0) {\n                    // 截取出className 将路径分割符替换为.（windows是\\ linux、mac是/）\n                    String filePath = file.getPath();\n                    // 判断是否是我们所需要统计的包名\n                    if (filePath.contains(PREFIX_OF_PACKAGE)) {\n                        filePath = filePath.substring(filePath.indexOf(PREFIX_OF_PACKAGE)).replace(\"/\", \".\");\n                        filePath = filePath.replaceAll(\"\\\\.java\", \"\");\n                        try {\n                            classes.add(Class.forName(filePath));\n                        } catch (Exception e) {\n                            LOGGER.warn(\"class=StatLineOfMethodTest||method=ergodicDir||msg=Class didn't found\");\n                        }\n                    }\n                }\n\n            }\n        }\n    }\n\n    /**\n     * 创建记录方法相关信息的类\n     */\n    public class InfoOfMethod implements Comparable<InfoOfMethod> {\n        int    methodLine;\n        String methodName;\n        String className;\n\n        public InfoOfMethod(int lineOfMethod, String nameOfMethod, String nameOfClass) {\n            this.methodLine = lineOfMethod;\n            this.className = nameOfClass;\n            this.methodName = nameOfMethod;\n        }\n\n        @Override\n        public int compareTo(InfoOfMethod infoOfMethod) { //重写compareTo方法\n            return infoOfMethod.methodLine - this.methodLine; //  根据methodLine进行降序排序\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.didichuxing.datachannel</groupId>\n        <artifactId>arius-admin</artifactId>\n        <version>${revision}${sha1}${changelist}</version>\n    </parent>\n\n    <artifactId>arius-admin-task</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-core</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-common</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didichuxing.datachannel</groupId>\n            <artifactId>arius-admin-biz</artifactId>\n        </dependency>\n\n        <!-- logi -->\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-job-spring-boot-starter</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-log</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.lmax</groupId>\n            <artifactId>disruptor</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.apache.logging.log4j</groupId>\n                    <artifactId>log4j-to-slf4j</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-api</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-api</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n</project>"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/BaseConcurrentClusterLogicTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterContextManager;\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterLogicManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterLogic;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.compress.utils.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * base任务 集群级别并发处理 记录任务完成时间  检查任务前置依赖\n * @author d06679\n * @date 2019/3/21\n */\npublic abstract class BaseConcurrentClusterLogicTask extends BaseConcurrentTask<ClusterLogic> {\n\n    private static final ILog       LOGGER = LogFactory.getLog(BaseConcurrentClusterLogicTask.class);\n\n    @Autowired\n    protected ClusterLogicManager   clusterLogicManager;\n\n    @Autowired\n    protected ClusterLogicService   clusterLogicService;\n\n    @Autowired\n    protected ClusterPhyService     clusterPhyService;\n\n    @Autowired\n    protected ClusterContextManager clusterContextManager;\n\n    /**\n     * 任务全集\n     *\n     * @return\n     */\n    @Override\n    protected List<ClusterLogic> getAllItems() {\n        return clusterLogicService.listAllClusterLogics();\n    }\n\n    /**\n     * 处理一个批次任务\n     *\n     * @param taskBatch\n     */\n    @Override\n    protected boolean executeByBatch(TaskBatch<ClusterLogic> taskBatch) throws AdminOperateException {\n        List<ClusterLogic> items = taskBatch.getItems();\n        if (CollectionUtils.isEmpty(items)) {\n            return true;\n        }\n\n        boolean succ = true;\n        List<String> succeedClusterList = Lists.newArrayList();\n        List<String> failedClusterList = Lists.newArrayList();\n\n        LOGGER.info(\n                \"class=BaseConcurrentClusterLogicTask||method=executeByBatch||taskBatch executeByClusterLogic begin||task={}||clusterListSize={}||clusters={}\",\n                getTaskName(), items.size(), items.stream().map(ClusterLogic::getName).collect(Collectors.joining(\",\")));\n\n        // 只要有一个集群失败就认为batch失败\n        for (ClusterLogic item : items) {\n            try {\n                if (executeByClusterLogic(item.getId())) {\n                    succeedClusterList.add(item.getName());\n                } else {\n                    succ = false;\n                    failedClusterList.add(item.getName());\n                }\n            } catch (Exception e) {\n                succ = false;\n                LOGGER.warn(\"executeByClusterLogic error||cluster={}||task={}||errMsg={}\", item.getName(),\n                    getTaskName(), e.getMessage(), e);\n            }\n        }\n        if (succ) {\n            LOGGER.info(\n                    \"class=BaseConcurrentClusterLogicTask||method=executeByBatch||taskBatch executeByClusterLogic succ||task={}||clusterListSize={}||clusters={}\",\n                    getTaskName(), succeedClusterList.size(), String.join(\",\", succeedClusterList));\n        } else {\n            LOGGER.info(\n                    \"class=BaseConcurrentClusterLogicTask||method=executeByBatch||taskBatch executeByClusterLogic fail||task={}||clusterListSize={}||succeedClusterListSize={}||failedClusterListSize={}||succeedClusters={}||failedClusters={}\",\n                    getTaskName(), items.size(), succeedClusterList.size(), failedClusterList.size(), StringUtils.join(succeedClusterList, \",\"), StringUtils.join(failedClusterList, \",\"));\n        }\n        return succ;\n    }\n\n    /**\n     * 处理一个集群\n     * @param clusterLogicId 逻辑集群Id\n     * @throws AdminOperateException\n     * @return 执行结果\n     */\n    protected abstract boolean executeByClusterLogic(Long clusterLogicId) throws AdminOperateException;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/BaseConcurrentClusterTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task;\n\nimport com.didichuxing.datachannel.arius.admin.biz.cluster.ClusterPhyManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.compress.utils.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * base任务 集群级别并发处理 记录任务完成时间  检查任务前置依赖\n * @author d06679\n * @date 2019/3/21\n */\npublic abstract class BaseConcurrentClusterTask extends BaseConcurrentTask<ClusterPhy> {\n\n    private static final ILog     LOGGER         = LogFactory.getLog(BaseConcurrentClusterTask.class);\n\n    protected static final String TASK_RETRY_URL = \"\";\n\n    @Autowired\n    protected ClusterPhyService   clusterPhyService;\n\n    @Autowired\n    protected ClusterPhyManager   clusterPhyManager;\n\n    /**\n     * 任务全集\n     *\n     * @return\n     */\n    @Override\n    protected List<ClusterPhy> getAllItems() {\n        return clusterPhyService.listAllClusters();\n    }\n\n    /**\n     * 处理一个批次任务\n     *\n     * @param taskBatch\n     */\n    @Override\n    protected boolean executeByBatch(TaskBatch<ClusterPhy> taskBatch) throws AdminOperateException {\n        List<ClusterPhy> items = taskBatch.getItems();\n        if (CollectionUtils.isEmpty(items)) {\n            return true;\n        }\n\n        boolean succ = true;\n        List<String> succeedClusterList = Lists.newArrayList();\n        List<String> failedClusterList = Lists.newArrayList();\n\n        LOGGER.info(\n                \"class=BaseConcurrentClusterTask||method=executeByBatch||taskBatch executeByCluster begin||task={}||clusterListSize={}||clusters={}\",\n                getTaskName(), items.size(), items.stream().map(ClusterPhy::getCluster).collect(Collectors.joining(\",\")));\n\n        // 只要有一个集群失败就认为batch失败\n        for (ClusterPhy item : items) {\n            ClusterPhy cluster = item;\n            try {\n                if (executeByCluster(cluster.getCluster())) {\n                    succeedClusterList.add(cluster.getCluster());\n                } else {\n                    succ = false;\n                    failedClusterList.add(cluster.getCluster());\n                }\n            } catch (Exception e) {\n                succ = false;\n                LOGGER.warn(\"executeByCluster error||cluster={}||task={}||errMsg={}\", cluster.getCluster(),\n                        getTaskName(), e.getMessage(), e);\n            }\n        }\n\n        if (succ) {\n            LOGGER.info(\n                    \"class=BaseConcurrentClusterTask||method=executeByBatch||taskBatch executeByCluster succ||task={}||clusterListSize={}||clusters={}\",\n                    getTaskName(), succeedClusterList.size(), String.join(\",\", succeedClusterList));\n        } else {\n            LOGGER.info(\n                    \"class=BaseConcurrentClusterTask||method=executeByBatch||taskBatch executeByCluster fail||task={}||clusterListSize={}||succeedClusterListSize={}||failedClusterListSize={}||succeedClusters={}||failedClusters={}\",\n                    getTaskName(), items.size(), succeedClusterList.size(), failedClusterList.size(), StringUtils.join(succeedClusterList, \",\"), StringUtils.join(failedClusterList, \",\"));\n        }\n        return succ;\n    }\n\n    /**\n     * 处理一个集群\n     * @param cluster 集群名字\n     * @throws AdminOperateException\n     * @return\n     */\n    protected abstract boolean executeByCluster(String cluster) throws AdminOperateException;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/BaseConcurrentTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.threadpool.AriusTaskThreadPool;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.OperateRecordService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport javax.annotation.PostConstruct;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * base任务 模板并发处理\n * @author d06679\n * @date 2019/3/21\n */\npublic abstract class BaseConcurrentTask<T> {\n\n    private static final ILog     LOGGER     = LogFactory.getLog(BaseConcurrentTask.class);\n    private static final int      QUEUE_SIZE = 50000;\n\n    protected AriusTaskThreadPool ariusTaskThreadPool;\n\n    @Autowired\n    private OperateRecordService  operateRecordService;\n\n    @PostConstruct\n    public void init() {\n        ariusTaskThreadPool = new AriusTaskThreadPool();\n        ariusTaskThreadPool.init(poolSize(), getTaskName(), QUEUE_SIZE);\n    }\n\n    /**\n     * 并发处理任务\n     */\n    public boolean execute() {\n        long start = System.currentTimeMillis();\n\n        List<TaskBatch<T>> batches = splitBatch(getAllItems());\n        int currentQueueWorkerSize = ariusTaskThreadPool.getCurrentQueueWorkerSize();\n        if (currentQueueWorkerSize >= QUEUE_SIZE) {\n            LOGGER.warn(\n                \"class=BaseConcurrentTask||method=execute||msg=currentQueueWorkerSize:{} is more than thread pool queue size:{}\",\n                getTaskName(), currentQueueWorkerSize, QUEUE_SIZE);\n            return false;\n        }\n        if (CollectionUtils.isEmpty(batches)) {\n            LOGGER.warn(\"class=BaseConcurrentTask||method=execute||batches is empty||task={}\", getTaskName());\n            return true;\n        }\n\n        LOGGER.info(\n            \"class=BaseConcurrentTask||method=execute||ConcurrentClusterTask||msg=task start||task={}||batchSize={}\",\n            getTaskName(), batches.size());\n\n        CountDownLatch countDownLatch = new CountDownLatch(batches.size());\n        AtomicBoolean succ = new AtomicBoolean(true);\n\n        for (TaskBatch<T> taskBatch : batches) {\n            ariusTaskThreadPool.run(() -> {\n                try {\n                    if (!executeByBatch(taskBatch)) {\n                        succ.set(false);\n                    }\n                } catch (Exception e) {\n                    succ.set(false);\n                    // 需要Odin监控错误日志\n                    LOGGER.error(\"class=BaseConcurrentTask||method=execute||errMsg={}||task={}\", e.getMessage(),\n                        getTaskName(), e);\n                } finally {\n                    countDownLatch.countDown();\n                }\n            });\n\n            try {\n                Thread.sleep(TimeUnit.SECONDS.toMillis(TaskConcurrentConstants.SLEEP_SECONDS_PER_BATCH));\n            } catch (InterruptedException e) {\n                Thread.currentThread().interrupt();\n                LOGGER.warn(\"class=BaseConcurrentTask||method=execute||ConcurrentClusterTask Interrupted||task={}\",\n                    getTaskName(), e);\n            }\n        }\n\n        try {\n            //等待所有任务完成\n            if (countDownLatch.await(60L, TimeUnit.MINUTES)) {\n                LOGGER.info(\n                    \"class=BaseConcurrentTask||method=execute||ConcurrentClusterTask||msg=all task finish||task={}\",\n                    getTaskName());\n            } else {\n                LOGGER.warn(\n                    \"class=BaseConcurrentTask||method=execute||ConcurrentClusterTask||msg=has task time out||task={}\",\n                    getTaskName());\n            }\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            LOGGER.warn(\"class=BaseConcurrentTask||method=execute||ConcurrentClusterTask Interrupted||task={}\",\n                getTaskName(), e);\n        }\n        return succ.get();\n    }\n\n    /**\n     * 任务全集\n     * @return\n     */\n    protected abstract List<T> getAllItems();\n\n    /**\n     * 处理一个批次任务\n     * @param taskBatch\n     */\n    protected abstract boolean executeByBatch(TaskBatch<T> taskBatch) throws AdminOperateException;\n\n    /**\n     * 获取任务名称\n     * @return 任务名称\n     */\n    public  String getTaskName(){\n        return getClass().getSimpleName();\n    }\n\n    /**\n     * 任务的线程个数\n     * @return\n     */\n    public abstract int poolSize();\n\n    /**\n     * 并发度\n     * @return\n     */\n    public abstract int current();\n\n    /**************************************************** private method ****************************************************/\n\n    /**\n     * 获取任务批次\n     * @return\n     */\n    private List<TaskBatch<T>> splitBatch(List<T> allItems) {\n\n        if (CollectionUtils.isEmpty(allItems)) {\n            return Lists.newArrayList();\n        }\n\n        // 打乱顺序\n        Collections.shuffle(allItems);\n\n        int workerCount = Math.min(ariusTaskThreadPool.getPoolSize(), current());\n        if (workerCount < 1) {\n            workerCount = 1;\n        }\n\n        int batchSize = allItems.size() / workerCount + 1;\n\n        LOGGER.info(\n            \"class=BaseConcurrentTask||method=splitBatch||ConcurrentClusterTask||msg=splitBatch||task={}||workerCount={}||batchSize={}\",\n            getTaskName(), workerCount, batchSize);\n\n        List<TaskBatch<T>> taskBatches = Lists.newArrayList();\n        TaskBatch<T> batch = new TaskBatch<>();\n        for (int i = 0; i < allItems.size(); i++) {\n            if (batch.getItems().size() >= batchSize) {\n                taskBatches.add(batch);\n                batch = new TaskBatch<>();\n            }\n            batch.getItems().add(allItems.get(i));\n        }\n\n        if (!batch.getItems().isEmpty()) {\n            taskBatches.add(batch);\n        }\n\n        return taskBatches;\n    }\n\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/BaseConcurrentTemplateTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.TemplateLogicManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.po.template.IndexTemplatePO;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.persistence.mysql.template.IndexTemplateDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.compress.utils.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.Collectors;\n\n/**\n * base任务 模板并发处理\n * @author d06679\n * @date 2019/3/21\n */\npublic abstract class BaseConcurrentTemplateTask extends BaseConcurrentTask<IndexTemplatePO> {\n\n    private static final ILog      LOGGER = LogFactory.getLog(BaseConcurrentClusterTask.class);\n\n    @Autowired\n    private IndexTemplateDAO       templateLogicDAO;\n\n    @Autowired\n    protected TemplateLogicManager templateLogicManager;\n\n    /**\n     * 任务全集\n     *\n     * @return\n     */\n    @Override\n    protected List<IndexTemplatePO> getAllItems() {\n        return templateLogicDAO.listAll();\n    }\n\n    /**\n     * 处理一个批次任务\n     *\n     * @param taskBatch\n     */\n    @Override\n    protected boolean executeByBatch(TaskBatch<IndexTemplatePO> taskBatch) throws AdminOperateException {\n        List<IndexTemplatePO> items = taskBatch.getItems();\n        if (CollectionUtils.isEmpty(items)) {\n            return true;\n        }\n\n        boolean succeed = true;\n\n        List<String> succeedTemplateNameList = Lists.newArrayList();\n        List<String> failedTemplateNameList = Lists.newArrayList();\n\n        LOGGER.info(\n                \"class=BaseConcurrentTemplateTask||method=executeByBatch||taskBatch executeByLogicTemplate begin||task={}||templateSize={}||template={}\",\n                getTaskName(), items.size(), items.stream().map(IndexTemplatePO::getName).collect(Collectors.joining(\",\")));\n        for (IndexTemplatePO item : items) {\n            IndexTemplatePO logicPO = item;\n            try {\n                if (executeByLogicTemplate(logicPO.getId())) {\n                    succeedTemplateNameList.add(logicPO.getName());\n                } else {\n                    succeed = false;\n                    failedTemplateNameList.add(logicPO.getName());\n                }\n\n                Thread.sleep(100);\n            } catch (InterruptedException e) {\n                Thread.currentThread().interrupt();\n                LOGGER.warn(\n                    \"class=BaseConcurrentTemplateTask||method=executeByBatch||BaseConcurrentTemplateTask Interrupted||task={}\",\n                    getTaskName(), e);\n            } catch (Exception e) {\n                succeed = false;\n                LOGGER.error(\"class=BaseConcurrentTemplateTask||method=executeByBatch||errMsg={}||template={}||task={}\",\n                    e.getMessage(), logicPO.getName(), getTaskName(), e);\n            }\n        }\n\n        if (succeed) {\n            LOGGER.info(\n                    \"class=BaseConcurrentTemplateTask||method=executeByBatch||taskBatch executeByLogicTemplate succ||task={}||templateSize={}||template={}\",\n                    getTaskName(), succeedTemplateNameList.size(), String.join(\",\", succeedTemplateNameList));\n        } else {\n            LOGGER.info(\n                    \"class=BaseConcurrentTemplateTask||method=executeByBatch||taskBatch executeByLogicTemplate fail||task={}||templateSize={}||succeedTemplateSize={}||failedTemplateSize={}||succeedTemplate={}||failedTemplate={}\",\n                    getTaskName(), items.size(), succeedTemplateNameList.size(), failedTemplateNameList.size(), StringUtils.join(succeedTemplateNameList, \",\"), StringUtils.join(failedTemplateNameList, \",\"));\n        }\n\n        return succeed;\n    }\n\n    /**\n     * 处理\n     * @param logicId\n     * @return\n     */\n    protected abstract boolean executeByLogicTemplate(Integer logicId) throws AdminOperateException;\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/TaskBatch.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task;\n\nimport java.util.List;\n\nimport com.google.common.collect.Lists;\n\nimport lombok.Data;\n\n/**\n * @author d06679\n * @date 2019/4/10\n */\n@Data\npublic class TaskBatch<T> {\n    /**\n     * 批次中需要处理的内容\n     */\n    private List<T> items = Lists.newArrayList();\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/TaskConcurrentConstants.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task;\n\n/**\n * 定时任务并发度配置\n * @author wangshu\n * @date 2020/06/05\n */\npublic class TaskConcurrentConstants {\n\n    private TaskConcurrentConstants() {\n    }\n\n    public static final int ADJUST_PIPELINE_RATE_LIMIT_TASK_CONCURRENT           = 100;\n    public static final int CAPACITY_AREA_CHECK_TASK_CONCURRENT                  = 10;\n    public static final int CAPACITY_AREA_PLAN_TASK_CONCURRENT                   = 5;\n    public static final int CAPACITY_AREA_STATICS_TASK_CONCURRENT                = 1;\n    public static final int CLOSE_CLUSTER_TASK_CONCURRENT                        = 20;\n    public static final int CLUSTER_CURRENT_TEST_TASK_CONCURRENT                 = 20;\n    public static final int COLD_DATA_MOVE_TASK_CONCURRENT                       = 10;\n    public static final int COLLECT_CLUSTER_NODE_SETTING_FROM_ES_TASK_CONCURRENT = 20;\n    public static final int COPY_INDEX_MAPPING2_TEMPLATE_TASK_CONCURRENT         = 20;\n    public static final int DELETE_EXPIRE_INDEX_TASK_CONCURRENT                  = 20;\n    public static final int PRE_CREATE_INDEX_TASK_CONCURRENT                     = 20;\n    public static final int SECURITY_META_CHECK_TASK_CONCURRENT                  = 20;\n    public static final int SYNC_TEMPLATE_META_DATE_TASK_CONCURRENT              = 20;\n    public static final int TEMPLATE_QUOTA_CTL_TASK_CONCURRENT                   = 20;\n    public static final int INDEX_ROLLOVER_TASK_CONCURRENT                       = 10;\n\n    public static final int SLEEP_SECONDS_PER_EXECUTE                            = 3;\n    public static final int SLEEP_SECONDS_PER_BATCH                              = 2;\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/component/TaskResultBuilder.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.component;\n\nimport com.didiglobal.knowframework.job.common.TaskResult;\n\npublic class TaskResultBuilder {\n    private StringBuffer failMsg = new StringBuffer();\n\n    public void append(String msg) {\n        failMsg.append(msg + '\\n');\n    }\n\n    public TaskResult build() {\n        if (failMsg.length() > 0) {\n            return new TaskResult(TaskResult.FAIL_CODE, failMsg.toString());\n        } else {\n            return TaskResult.buildSuccess();\n        }\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/dashboard/DashboardAllClusterCollectorRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.dashboard;\n\nimport java.util.List;\nimport java.util.Map;\nimport com.didichuxing.datachannel.arius.admin.task.component.TaskResultBuilder;\nimport com.didichuxing.datachannel.arius.admin.task.dashboard.collector.BaseDashboardCollector;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * Created by linyunan on 3/11/22\n */\n@Task(name = \"DashboardAllClusterCollectorRandomTask\", description = \"采集DashBoard平台全集群汇总数据信息\", cron = \"0 0/5 * * * ? *\", autoRegister = true)\n@Component\npublic class DashboardAllClusterCollectorRandomTask implements Job {\n    private static final ILog                         LOGGER                       = LogFactory\n        .getLog(DashboardAllClusterCollectorRandomTask.class);\n\n    @Autowired\n    private ClusterPhyService                         clusterPhyService;\n\n    private final Map<String, BaseDashboardCollector> BASE_DASHBOARD_COLLECTOR_MAP = SpringTool\n        .getBeansOfType(BaseDashboardCollector.class);\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\n            \"class=DashboardAllClusterCollectorRandomTask||method=execute||msg=DashboardAllClusterCollectorRandomTask start.\");\n        long currentTimeMillis = System.currentTimeMillis();\n        long currentTime = CommonUtils.monitorTimestamp2min(currentTimeMillis);\n        TaskResultBuilder taskResultBuilder = new TaskResultBuilder();\n        List<String> clusterNameList = clusterPhyService.listClusterNames();\n        if (CollectionUtils.isEmpty(clusterNameList)) {\n            LOGGER.warn(\"class=DashboardAllClusterCollectorRandomTask||method=execute||msg=clusterNameList is empty\");\n            return TaskResult.buildSuccess();\n        }\n\n        for (Map.Entry<String, BaseDashboardCollector> entry : BASE_DASHBOARD_COLLECTOR_MAP.entrySet()) {\n            BaseDashboardCollector collector = entry.getValue();\n            if (null == collector) {\n                continue;\n            }\n            try {\n                collector.collectAllCluster(clusterNameList, currentTime);\n            } catch (Exception e) {\n                Thread.currentThread().interrupt();\n                String errLog = \"class=DashboardAllClusterCollectorRandomTask||collectorName=\" + collector.getName()\n                                + \"||method=execute||errMsg=\" + e.getMessage();\n                LOGGER.error(errLog, e);\n                taskResultBuilder.append(errLog);\n            }\n        }\n\n        LOGGER.info(\n            \"class=DashboardAllClusterCollectorRandomTask||method=execute||msg=DashboardAllClusterCollectorRandomTask finish, cost:{}ms\",\n            System.currentTimeMillis() - currentTimeMillis);\n        return taskResultBuilder.build();\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/dashboard/DashboardSingleClusterCollectorBroadcastTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.dashboard;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ClusterPhy;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.HttpHostUtil;\nimport com.didichuxing.datachannel.arius.admin.core.component.SpringTool;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.monitortask.AriusMetaJobClusterDistributeService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.task.component.TaskResultBuilder;\nimport com.didichuxing.datachannel.arius.admin.task.dashboard.collector.BaseDashboardCollector;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.consensual.ConsensualEnum;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.collections.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Created by linyunan on 3/11/22\n * @author linyunan\n */\n@Task(name = \"DashboardSingleClusterCollectorBroadcastTask\", description = \"采集DashBoard单个集群数据信息\", cron = \"0 0/5 * * * ? *\", autoRegister = true, consensual = ConsensualEnum.BROADCAST)\n@Component\npublic class DashboardSingleClusterCollectorBroadcastTask implements Job {\n    private static final ILog                         LOGGER                       = LogFactory\n        .getLog(DashboardSingleClusterCollectorBroadcastTask.class);\n\n    /**\n     * 单组采集的集群数量，每个组会并发采集，分组为了降低 Gateway QPS\n     */\n    private static final int                          SINGLE_GROUP_CLUSTER_NUM     = 5;\n\n    @Autowired\n    private AriusMetaJobClusterDistributeService      ariusMetaJobClusterDistributeService;\n    @Autowired\n    private ClusterPhyService                         clusterPhyService;\n    @Autowired\n    private AriusConfigInfoService ariusConfigInfoService;\n\n    private static final FutureUtil<Void>             BATCH_COLLECTOR_FUTURE_UTIL  = FutureUtil\n        .init(\"batchCollectorFutureUtil\", 30, 30, 1000);\n\n    private String                                    hostName                     = HttpHostUtil.HOST_NAME;\n\n    private final Map<String, BaseDashboardCollector> BASE_DASHBOARD_COLLECTOR_MAP = SpringTool\n        .getBeansOfType(BaseDashboardCollector.class);\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\n            \"class=DashboardSingleClusterCollectorBroadcastTask||method=execute||msg=DashboardSingleClusterCollectorBroadcastTask start.\");\n        // 获取单台admin实例能采集的集群数\n        List<ClusterPhy> monitorCluster = ariusMetaJobClusterDistributeService.getSingleMachineMonitorCluster(hostName);\n        if (CollectionUtils.isEmpty(monitorCluster)) {\n            return TaskResult.buildSuccess();\n        }\n\n        long currentTimeMillis = System.currentTimeMillis();\n        long currentTime = CommonUtils.monitorTimestamp2min(currentTimeMillis);\n        TaskResultBuilder taskResultBuilder = new TaskResultBuilder();\n\n        // 分组\n        List<List<ClusterPhy>> partitionClusterList = Lists.partition(monitorCluster, SINGLE_GROUP_CLUSTER_NUM);\n        for (List<ClusterPhy> partitionCluster : partitionClusterList) {\n            // 各组执行, 单组并发执行\n            for (ClusterPhy clusterPhy : partitionCluster) {\n                for (Map.Entry<String, BaseDashboardCollector> entry : BASE_DASHBOARD_COLLECTOR_MAP.entrySet()) {\n                    BATCH_COLLECTOR_FUTURE_UTIL.runnableTask(() -> {\n                        // 并发执行多个不同集群的采集器\n                        BaseDashboardCollector collector = entry.getValue();\n                        try {\n                            collector.collectSingleCluster(clusterPhy.getCluster(), currentTime);\n                        } catch (Exception e) {\n                            Thread.currentThread().interrupt();\n                            String errLog = \"class=DashboardSingleClusterCollectorBroadcastTask||collectorName=\"\n                                            + collector.getName() + \"||method=execute||errMsg=\" + e.getMessage();\n                            LOGGER.error(errLog, e);\n                            taskResultBuilder.append(errLog);\n                        }\n                    });\n                }\n            }\n            // 阻塞等待多个采集器执行结束\n            BATCH_COLLECTOR_FUTURE_UTIL.waitExecute();\n        }\n\n        LOGGER.info(\n            \"class=DashboardSingleClusterCollectorBroadcastTask||method=execute||msg=DashboardSingleClusterCollectorBroadcastTask finish, cost:{}ms\",\n            System.currentTimeMillis() - currentTimeMillis);\n        return taskResultBuilder.build();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/dashboard/collector/BaseDashboardCollector.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.dashboard.collector;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.common.bean.dto.metrics.DashBoardMetricThresholdDTO;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.DashBoardStats;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusUnitUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.logic.ClusterLogicService;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterPhyService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESTemplateService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.MonitorMetricsSender;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsDashBoardInfoESDAO;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport java.util.List;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.ARIUS_DASHBOARD_THRESHOLD_GROUP;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.ClusterConstant.PHY_CLUSTER;\n\n/**\n * Created by linyunan on 3/11/22\n */\npublic abstract class BaseDashboardCollector {\n    @Autowired\n    protected ClusterPhyService            clusterPhyService;\n\n    @Autowired\n    protected ClusterLogicService          clusterLogicService;\n\n    @Autowired\n    protected IndexTemplateService         indexTemplateService;\n\n    @Autowired\n    protected ESClusterService             esClusterService;\n\n    @Autowired\n    protected ESIndexService               esIndexService;\n\n    @Autowired\n    protected ESTemplateService            esTemplateService;\n\n    @Autowired\n    protected MonitorMetricsSender         monitorMetricsSender;\n\n    @Autowired\n    protected AriusStatsDashBoardInfoESDAO ariusStatsDashBoardInfoESDAO;\n\n    @Autowired\n    protected AriusConfigInfoService ariusConfigInfoService;\n\n    private static final ILog LOGGER                            = LogFactory\n            .getLog(BaseDashboardCollector.class);\n\n\n    /**\n     * 采集单个集群\n     * @param cluster 集群名称\n     * @param currentTime   当前时间戳\n     */\n    public abstract void collectSingleCluster(String cluster, long currentTime) throws ESOperateException;\n\n    /**\n     * 采集多个集群\n     * @param clusterList   集群列表\n     * @param currentTime   时间戳\n     */\n    public abstract void collectAllCluster(List<String> clusterList, long currentTime);\n\n    /**\n     * 获取任务名称\n     * @return 任务名称\n     */\n    public abstract String getName();\n\n    protected DashBoardStats buildInitDashBoardStats(Long timestamp) {\n        DashBoardStats dashBoardStats = new DashBoardStats();\n        dashBoardStats.setPhysicCluster(PHY_CLUSTER);\n        dashBoardStats.setTimestamp(timestamp);\n        return dashBoardStats;\n    }\n\n    /**\n     * 获取dashboard配置值\n     * catch:获取和转换都发生错误后，使用系统配置的默认配置项\n     * @param valueName    配置名称\n     * @param defaultValue 默认值\n     * @return\n     */\n    public long getConfigOrDefaultValue(String valueName, String defaultValue, String unitStyle) {\n        DashBoardMetricThresholdDTO configThreshold = ariusConfigInfoService.objectSetting(\n                ARIUS_DASHBOARD_THRESHOLD_GROUP, valueName,\n                JSON.parseObject(defaultValue, DashBoardMetricThresholdDTO.class), DashBoardMetricThresholdDTO.class);\n        return AriusUnitUtil.unitChange(configThreshold.getValue().longValue(), configThreshold.getUnit(), unitStyle);\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/dashboard/collector/ClusterDashBoardCollector.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.dashboard.collector;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterStatsResponse;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.ClusterMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.DashBoardStats;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.MetricsUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.ESClusterPhyStatsService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.DASHBOARD_CLUSTER_METRIC_COLLECTOR_DELAYED_DEFAULT_VALUE;\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.DASHBOARD_CLUSTER_METRIC_COLLECTOR_DELAYED_THRESHOLD;\nimport static com.didichuxing.datachannel.arius.admin.common.util.AriusUnitUtil.TIME;\n\n/**\n * Created by linyunan on 3/11/22\n * dashboard单个集群维度采集器\n */\n@Component\npublic class ClusterDashBoardCollector extends BaseDashboardCollector {\n    private static final ILog                                                LOGGER                            = LogFactory\n        .getLog(ClusterDashBoardCollector.class);\n    @Autowired\n    protected ESClusterPhyStatsService                                       esClusterPhyStatsService;\n    @Autowired\n    protected AriusConfigInfoService                                         ariusConfigInfoService;\n\n    private static final Map<String/*集群名称*/, ClusterMetrics /*上一次采集到的集群数据*/> cluster2LastTimeClusterMetricsMap = Maps\n        .newConcurrentMap();\n\n    private static final long                                                FIVE_MINUTE                       = 5 * 60\n                                                                                                                 * 1000;\n\n    @Override\n    public void collectSingleCluster(String cluster, long startTime) throws ESOperateException {\n        DashBoardStats dashBoardStats = buildInitDashBoardStats(startTime);\n\n        ClusterMetrics clusterMetrics = cluster2LastTimeClusterMetricsMap.getOrDefault(cluster, new ClusterMetrics());\n        ESClusterStatsResponse clusterStats = esClusterService.syncGetClusterStats(cluster);\n        clusterMetrics.setTimestamp(startTime);\n        clusterMetrics.setCluster(cluster);\n        // 1. 写入耗时\n        //TODO 指标-最大值，各个节点当前写入耗时最大值\n        clusterMetrics.setIndexingLatency(esClusterPhyStatsService.getClusterIndexingLatency(cluster));\n        // 2. 查询耗时\n        //TODO 指标-最大值，各节点当前查询耗时最大值\n        clusterMetrics.setSearchLatency(esClusterPhyStatsService.getClusterSearchLatency(cluster));\n        //TODO 指标-轻量级获取_cat/health?format=json\n        //4. 集群shard总数\n        clusterMetrics.setShardNum(clusterStats.getTotalShard());\n        // 5. 写入请求数\n        clusterMetrics.setIndexReqNum(esClusterPhyStatsService.getCurrentIndexTotal(cluster));\n        // 6. 网关成功率、失败率\n        Tuple<Double/*成功率*/, Double/*失败率*/> gatewaySuccessRateAndFailureRate = esClusterPhyStatsService\n            .getGatewaySuccessRateAndFailureRate(cluster);\n        clusterMetrics.setGatewaySucPer(gatewaySuccessRateAndFailureRate.getV1());\n        clusterMetrics.setGatewayFailedPer(gatewaySuccessRateAndFailureRate.getV2());\n        // 7. 集群Pending task数\n        //TODO 指标-轻量级获取_cat/health?format=json\n        clusterMetrics.setPendingTaskNum(clusterStats.getPendingTasks());\n        // 8. 集群http连接数\n        clusterMetrics.setHttpNum(esClusterPhyStatsService.getHttpConnectionTotal(cluster));\n        //9. 查询请求数突增量 （上个时间间隔请求数的两倍）\n        clusterMetrics.setReqUprushNum(getReqUprushNum(cluster));\n        //10.写入文档数突增量（上个时间间隔的写文档数的两倍\n        clusterMetrics.setDocUprushNum(getDocUprushNum(cluster));\n\n        //11._cluster/stats 和_nodes/stats 消耗时间\n        clusterMetrics.setClusterElapsedTime(esClusterPhyStatsService.getClusterStatusElapsedTime(cluster));\n        clusterMetrics.setNodeElapsedTime(esClusterPhyStatsService.getNodeStatusElapsedTime(cluster));\n        long collectorDelayed = getCollectorDelayed(cluster);\n        long configCollectorDelayed = getConfigCollectorDelayed();\n        //TODO 指标-_cluster/stats，加参数过滤\n        //12.消耗时间是否大于5分钟,开始采集到结束采集的时间，指标看板的采集任务，当前时间到最近一次采集的时间\n        clusterMetrics.setClusterElapsedTimeGte5Min(collectorDelayed > configCollectorDelayed);\n        clusterMetrics.setCollectorDelayed(collectorDelayed);\n        //13.集群下索引数量\n        clusterMetrics.setIndexCount(clusterStats.getIndexCount());\n\n        dashBoardStats.setCluster(clusterMetrics);\n        monitorMetricsSender.sendDashboardStats(Lists.newArrayList(dashBoardStats));\n\n        // 暂存当前集群指标信息 针对特殊场景，即集群不可用后, 当前的策略是会使用上一次采集到的数据\n        cluster2LastTimeClusterMetricsMap.put(cluster, clusterMetrics);\n    }\n\n    /**\n     * 获取采集延时\n     * @param cluster 集群\n     * @return\n     */\n    private long getCollectorDelayed(String cluster) {\n        long currentTimeMillis = System.currentTimeMillis();\n        //最近一个采集点的时间\n        Long nearestPoint = esClusterPhyStatsService.getTimeDifferenceBetweenNearestPointAndNow(cluster);\n        long collectorDelayed = currentTimeMillis - nearestPoint;\n        return collectorDelayed;\n    }\n\n    @Override\n    public void collectAllCluster(List<String> clusterList, long currentTime) {\n\n    }\n\n    @Override\n    public String getName() {\n        return \"ClusterDashBoardCollector\";\n    }\n\n    /**\n     * 计算索引写入文档突增量\n     * @param cluster   集群名称\n     * @return {@link Long}\n     */\n    private Long getDocUprushNum(String cluster) {\n        ClusterMetrics clusterMetrics = cluster2LastTimeClusterMetricsMap.get(cluster);\n        // web第一次启动无暂存采集数据\n        if (null == clusterMetrics) {\n            return 0L;\n        }\n\n        Long lastTimeDocNum = clusterMetrics.getDocUprushNum();\n        Long currentTimeDocNum = esClusterPhyStatsService.getCurrentIndexTotal(cluster);\n        return MetricsUtils.computerUprushNum(currentTimeDocNum.doubleValue(), lastTimeDocNum.doubleValue())\n            .longValue();\n    }\n\n    /**\n     * 计算索引写入文档突增量\n     * @param cluster  集群名称\n     * @return {@link Long}\n     */\n    private Long getReqUprushNum(String cluster) {\n        ClusterMetrics clusterMetrics = cluster2LastTimeClusterMetricsMap.get(cluster);\n        // web第一次启动无暂存采集数据\n        if (null == clusterMetrics) {\n            return 0L;\n        }\n\n        Long lastTimeQueryTotal = clusterMetrics.getReqUprushNum();\n        Long currentQueryTotal = esClusterPhyStatsService.getCurrentQueryTotal(cluster);\n\n        return MetricsUtils.computerUprushNum(currentQueryTotal.doubleValue(), lastTimeQueryTotal.doubleValue())\n            .longValue();\n    }\n\n    /**\n     * 获取配置的采集延时\n     * @return\n     */\n    private long getConfigCollectorDelayed() {\n        return getConfigOrDefaultValue(DASHBOARD_CLUSTER_METRIC_COLLECTOR_DELAYED_THRESHOLD,DASHBOARD_CLUSTER_METRIC_COLLECTOR_DELAYED_DEFAULT_VALUE,TIME);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/dashboard/collector/ClusterHealthDashBoardCollector.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.dashboard.collector;\n\nimport java.util.List;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.stereotype.Component;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.ClusterPhyHealthMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.DashBoardStats;\nimport com.didichuxing.datachannel.arius.admin.common.util.ListUtils;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\n\n/**\n * Created by linyunan on 3/11/22\n * dashboard汇总多个集群健康度采集器\n */\n@Component\npublic class ClusterHealthDashBoardCollector extends BaseDashboardCollector {\n    private static final ILog       LOGGER      = LogFactory.getLog(ClusterHealthDashBoardCollector.class);\n\n    private static final FutureUtil FUTURE_UTIL = FutureUtil.init(\"ClusterHealthDashBoardCollector\", 10, 10, 500);\n\n    @Override\n    public void collectSingleCluster(String cluster, long currentTime) throws ESOperateException {\n    }\n\n    @Override\n    public void collectAllCluster(List<String> clusterList, long currentTime) {\n        if (CollectionUtils.isEmpty(clusterList)) {\n            LOGGER.warn(\"class=ClusterHealthDashBoardCollector||method=collectAllCluster||msg=clusterList is empty\");\n            return;\n        }\n\n        DashBoardStats dashBoardStats = buildInitDashBoardStats(currentTime);\n        ClusterPhyHealthMetrics clusterPhyHealthMetrics = new ClusterPhyHealthMetrics();\n        clusterPhyHealthMetrics.setTimestamp(currentTime);\n\n        List<String> greenClusterList = Lists.newCopyOnWriteArrayList();\n        List<String> yellowClusterList = Lists.newCopyOnWriteArrayList();\n        List<String> redClusterList = Lists.newCopyOnWriteArrayList();\n        List<String> unknownClusterList = Lists.newCopyOnWriteArrayList();\n        for (String cluster : clusterList) {\n            // do concurrent \n            FUTURE_UTIL.runnableTask(() -> {\n                try {\n                    switch (esClusterService.syncGetClusterHealthEnum(cluster)) {\n                        case GREEN:\n                            greenClusterList.add(cluster);\n                            break;\n                        case YELLOW:\n                            yellowClusterList.add(cluster);\n                            break;\n                        case RED:\n                            redClusterList.add(cluster);\n                            break;\n                        default:\n                            unknownClusterList.add(cluster);\n                    }\n                } catch (Exception e) {\n                    LOGGER.error(\"class=ClusterHealthDashBoardCollector||method=collectAllCluster||errMsg={}\",\n                        e.getMessage(), e);\n                }\n            });\n        }\n\n        // 阻塞等待采集结束\n        FUTURE_UTIL.waitExecute();\n\n        clusterPhyHealthMetrics.setTotalNum(clusterList.size());\n        clusterPhyHealthMetrics.setGreenNum(greenClusterList.size());\n        clusterPhyHealthMetrics.setYellowNum(yellowClusterList.size());\n        clusterPhyHealthMetrics.setRedNum(redClusterList.size());\n        clusterPhyHealthMetrics.setUnknownNum(unknownClusterList.size());\n\n        clusterPhyHealthMetrics.setYellowClusterListStr(ListUtils.strList2String(yellowClusterList));\n        clusterPhyHealthMetrics.setRedClusterListStr(ListUtils.strList2String(redClusterList));\n        clusterPhyHealthMetrics.setUnknownClusterListStr(ListUtils.strList2String(unknownClusterList));\n        clusterPhyHealthMetrics.setGreenClusterListStr(ListUtils.strList2String(greenClusterList));\n\n        dashBoardStats.setClusterPhyHealth(clusterPhyHealthMetrics);\n        monitorMetricsSender.sendDashboardStats(Lists.newArrayList(dashBoardStats));\n    }\n\n    @Override\n    public String getName() {\n        return \"ClusterHealthDashBoardCollector\";\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/dashboard/collector/ClusterThreadPoolDashBoardCollector.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.dashboard.collector;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.ESClusterThreadStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.ClusterThreadPoolQueueMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.DashBoardStats;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n * Created by linyunan on 3/11/22\n * dashboard单个集群线程池采集器\n */\n@Component\npublic class ClusterThreadPoolDashBoardCollector extends BaseDashboardCollector {\n    private static final ILog LOGGER = LogFactory.getLog(ClusterThreadPoolDashBoardCollector.class);\n\n    @Override\n    public void collectSingleCluster(String cluster, long currentTime) {\n        DashBoardStats dashBoardStats = buildInitDashBoardStats(currentTime);\n        ClusterThreadPoolQueueMetrics clusterThreadPoolQueueMetrics = new ClusterThreadPoolQueueMetrics();\n        clusterThreadPoolQueueMetrics.setTimestamp(currentTime);\n        clusterThreadPoolQueueMetrics.setCluster(cluster);\n\n        //1集群线程池queue大小(management、refresh、flush、merge、search、write)\n        buildClusterThreadPoolQueueMetrics(cluster, clusterThreadPoolQueueMetrics);\n\n        dashBoardStats.setClusterThreadPoolQueue(clusterThreadPoolQueueMetrics);\n        monitorMetricsSender.sendDashboardStats(Lists.newArrayList(dashBoardStats));\n    }\n\n    @Override\n    public void collectAllCluster(List<String> clusterList, long currentTime) {\n\n    }\n\n    @Override\n    public String getName() {\n        return \"NodeThreadPoolDashBoardCollector\";\n    }\n\n    private void buildClusterThreadPoolQueueMetrics(String cluster,\n                                                    ClusterThreadPoolQueueMetrics clusterThreadPoolQueueMetrics) {\n        try {\n            ESClusterThreadStats esClusterThreadStats = esClusterService.syncGetThreadStatsByCluster(cluster);\n            if (esClusterThreadStats != null) {\n                org.springframework.beans.BeanUtils.copyProperties(clusterThreadPoolQueueMetrics, esClusterThreadStats);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"buildClusterThreadPoolQueueMetrics error{}\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/dashboard/collector/IndexDashBoardCollector.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.dashboard.collector;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.metrics.ordinary.ShardMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.shard.Segment;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.DashBoardStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.IndexMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.constant.index.IndexStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.util.*;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESIndexService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESShardService;\nimport com.didichuxing.datachannel.arius.admin.metadata.service.ESIndicesStatsService;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.elasticsearch.client.response.setting.index.IndexConfig;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.stream.Collectors;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.*;\nimport static com.didichuxing.datachannel.arius.admin.common.util.AriusUnitUtil.SIZE;\n\n/**\n * Created by linyunan on 3/11/22\n * dashboard单个集群索引采集器\n */\n@Component\npublic class IndexDashBoardCollector extends BaseDashboardCollector {\n    private static final ILog                                                       LOGGER                        = LogFactory\n        .getLog(IndexDashBoardCollector.class);\n    private static final String                                                     NO_REPLICA                    = \"0\";\n\n    @Autowired\n    private ESShardService                                                          esShardService;\n\n    @Autowired\n    private ESIndexService                                                          esIndexService;\n\n    @Autowired\n    private ESIndicesStatsService                                                   esIndicesStatsService;\n\n    private static final Map<String/*cluster@index*/, IndexMetrics /*上一次采集到的索引数据*/> index2LastTimeIndexMetricsMap = Maps\n        .newConcurrentMap();\n\n    private static final FutureUtil                                                 FUTURE_UTIL                   = FutureUtil\n        .init(\"IndexDashBoardCollector\", 10, 10, 100);\n\n    @Override\n    public void collectSingleCluster(String cluster, long currentTime) {\n        List<CatIndexResult> catIndexResults = esIndexService.syncCatIndex(cluster, 2);\n        if (CollectionUtils.isEmpty(catIndexResults)) {\n            return;\n        }\n\n        List<DashBoardStats> dashBoardStatsList = Lists.newArrayList();\n        AtomicReference<List<Segment>> segmentsListRef = new AtomicReference<>(Lists.newArrayList());\n        AtomicReference<Tuple<List<ShardMetrics>, List<ShardMetrics>>> bigAndSmallListTupleRef = new AtomicReference<>();\n        AtomicReference<Map<String, IndexConfig>> index2IndexConfigMapRef = new AtomicReference<>(Maps.newHashMap());\n        AtomicReference<Map<String, Double>> index2IndexingIndexIncrementMapRef = new AtomicReference<>(\n            Maps.newHashMap());\n        AtomicReference<Map<String, Double>> index2SearchQueryIncrementMapRef = new AtomicReference<>(\n            Maps.newHashMap());\n        // 获取集群mapping信息、读、写文档突增等信息\n        List<String> indexList = catIndexResults.stream().map(CatIndexResult::getIndex).distinct()\n            .collect(Collectors.toList());\n\n        FUTURE_UTIL.runnableTask(() -> segmentsListRef.set(esShardService.syncGetSegments(cluster)))\n                //TODO 指标-shard和小shard是采集侧过滤的\n            .runnableTask(() -> bigAndSmallListTupleRef.set(esShardService.syncGetBigAndSmallShards(cluster,getConfigBigShard(),getConfigSmallShard())))\n            .runnableTask(() -> index2IndexConfigMapRef.set(batchGetIndexConfigMap(cluster, indexList)))\n            .runnableTask(\n                () -> index2IndexingIndexIncrementMapRef.set(batchGetIndexingIndexIncrementMap(cluster, indexList)))\n            .runnableTask(\n                () -> index2SearchQueryIncrementMapRef.set(batchGetSearchQueryIncrementMap(cluster, indexList)))\n            .waitExecute();\n\n        // 获取集群大shard、小shard\n        List<ShardMetrics> bigShardListList = null != bigAndSmallListTupleRef.get()\n            ? bigAndSmallListTupleRef.get().getV1()\n            : Lists.newArrayList();\n        List<ShardMetrics> smallShardListList = null != bigAndSmallListTupleRef.get()\n            ? bigAndSmallListTupleRef.get().getV2()\n            : Lists.newArrayList();\n        Map<String, List<ShardMetrics>> index2BigShardListMap = ConvertUtil.list2MapOfList(bigShardListList,\n            ShardMetrics::getIndex, c -> c);\n        Map<String, List<ShardMetrics>> index2SmallShardListMap = ConvertUtil.list2MapOfList(smallShardListList,\n            ShardMetrics::getIndex, c -> c);\n\n        // 获取集群segments\n        Map<String, List<Segment>> index2SegmentsListMap = ConvertUtil.list2MapOfList(segmentsListRef.get(),\n            Segment::getIndex, c -> c);\n\n        for (CatIndexResult index : catIndexResults) {\n            DashBoardStats dashBoardStats = buildInitDashBoardStats(currentTime);\n            String uniqueIndexKey = CommonUtils.getUniqueKey(cluster, index.getIndex());\n            IndexMetrics indexMetrics = index2LastTimeIndexMetricsMap.getOrDefault(uniqueIndexKey, new IndexMetrics());\n            indexMetrics.setTimestamp(currentTime);\n            indexMetrics.setIndex(index.getIndex());\n            indexMetrics.setCluster(cluster);\n\n            // 1. 是否RED索引\n            indexMetrics.setRed(IndexStatusEnum.RED.getStatus().equals(index.getHealth()));\n            // 2. 是否单副本索引\n            indexMetrics.setSingReplicate(NO_REPLICA.equals(index.getRep()));\n            // 3. 是否未分配shard索引\n            indexMetrics.setUnassignedShard(!IndexStatusEnum.GREEN.getStatus().equals(index.getHealth()));\n            // 4. 是否为大shard索引(大于50G)\n            indexMetrics.setBigShard(index2BigShardListMap.containsKey(index.getIndex()));\n            // 5. 是否为小shard索引(小于1G)\n            indexMetrics.setSmallShard(index2SmallShardListMap.containsKey(index.getIndex()));\n            indexMetrics.setShardSize(countShardSize(index2BigShardListMap,index2SmallShardListMap,index.getIndex()));\n            //获取shard数量\n            indexMetrics.setShardNum(countShardNum(index2BigShardListMap,index2SmallShardListMap,index.getIndex()));\n            // 6. 索引Mapping字段个数\n            int mappingNum = 0;\n            IndexConfig indexConfig = index2IndexConfigMapRef.get().get(index.getIndex());\n            if (null != indexConfig && null != indexConfig.getMappings()) {\n                mappingNum = MappingConfigUtil.countMappingFieldNum(indexConfig.getMappings());\n            }\n            indexMetrics.setMappingNum((long) mappingNum);\n            // 7. 索引Segements个数\n            List<Segment> indexSegmentList = index2SegmentsListMap.getOrDefault(index.getIndex(), Lists.newArrayList());\n            indexMetrics.setSegmentNum((long) indexSegmentList.size());\n            // 8. 索引Segements内存大小（MB）\n            indexMetrics\n                .setSegmentMemSize(indexSegmentList.stream().mapToDouble(Segment::getMemoSize).sum() );\n            // 9. 写入文档数突增个数 （上个时间间隔的两倍）\n            double indexingIndexIncrementValue = index2IndexingIndexIncrementMapRef.get().getOrDefault(index.getIndex(),\n                0d);\n            indexMetrics.setDocUprushNum((long) indexingIndexIncrementValue);\n            // 10. 查询请求数突增个数（上个时间间隔的两倍）\n            double SearchQueryIncrementValue = index2SearchQueryIncrementMapRef.get().getOrDefault(index.getIndex(),\n                0d);\n            indexMetrics.setReqUprushNum((long) SearchQueryIncrementValue);\n\n            dashBoardStats.setIndex(indexMetrics);\n            dashBoardStatsList.add(dashBoardStats);\n\n            index2LastTimeIndexMetricsMap.put(uniqueIndexKey, indexMetrics);\n        }\n\n        if (CollectionUtils.isEmpty(dashBoardStatsList)) {\n            return;\n        }\n\n        monitorMetricsSender.sendDashboardStats(dashBoardStatsList);\n    }\n    \n    /**\n     *  计算对于索引shard大小\n     * @param index2BigShardListMap 大shard集合\n     * @param index2SmallShardListMap 小shard集合\n     * @param index 索引\n     * @return 索引大小\n     */\n    private Long countShardSize(Map<String, List<ShardMetrics>> index2BigShardListMap, Map<String, List<ShardMetrics>> index2SmallShardListMap, String index) {\n        List<ShardMetrics> metrics= new ArrayList<>();\n        if (index2BigShardListMap.containsKey(index)){\n            metrics = index2BigShardListMap.get(index);\n        }else if (index2SmallShardListMap.containsKey(index)){\n            metrics = index2SmallShardListMap.get(index);\n        }\n        Long size = 0L;\n        for(ShardMetrics metric:metrics){\n            if (Objects.nonNull(metric.getStore())) {\n                size += SizeUtil.getUnitSize(metric.getStore());\n        \n            }\n        }\n        return size;\n    }\n\n    /**\n     *  计算对于索引shard数量\n     * @param index2BigShardListMap 大shard集合\n     * @param index2SmallShardListMap 小shard集合\n     * @param index 索引\n     * @return 索引大小\n     */\n    private Long countShardNum(Map<String, List<ShardMetrics>> index2BigShardListMap, Map<String, List<ShardMetrics>> index2SmallShardListMap, String index) {\n        List<ShardMetrics> metrics= new ArrayList<>();\n        if (index2BigShardListMap.containsKey(index)){\n            metrics = index2BigShardListMap.get(index);\n        }else if (index2SmallShardListMap.containsKey(index)){\n            metrics = index2SmallShardListMap.get(index);\n        }\n        return Long.valueOf(metrics.size());\n    }\n    \n    /**\n     * 分批采集 + 计算索引列表SearchQuery突增量\n     * @param cluster        集群名称\n     * @param indexList      索引名称列表\n     * @return               Map<String, Double>\n     */\n    private Map<String, Double> batchGetSearchQueryIncrementMap(String cluster, List<String> indexList) {\n        Map<String, Double> index2CurrentSearchQueryMap = Maps.newHashMap();\n        List<List<String>> indexListList = Lists.partition(indexList, 20);\n        for (List<String> subIndexList : indexListList) {\n            index2CurrentSearchQueryMap\n                .putAll(esIndicesStatsService.getIndex2CurrentSearchQueryMap(cluster, subIndexList));\n        }\n\n        // 计算索引列表SearchQuery突增量\n        Map<String, Double> index2SearchQueryIncrementMap = Maps.newHashMap();\n        for (String index : indexList) {\n            String uniqueIndexKey = CommonUtils.getUniqueKey(cluster, index);\n            IndexMetrics indexMetrics = index2LastTimeIndexMetricsMap.get(uniqueIndexKey);\n            if (null == indexMetrics) {\n                index2SearchQueryIncrementMap.put(index, 0d);\n                continue;\n            }\n\n            Double currentTimeSearchQuery = index2CurrentSearchQueryMap.get(index);\n            Double lastTimeSearchQuery = indexMetrics.getReqUprushNum().doubleValue();\n            // 计算突增值\n            Double incrementValue = MetricsUtils.computerUprushNum(currentTimeSearchQuery, lastTimeSearchQuery);\n            index2SearchQueryIncrementMap.put(index, incrementValue);\n        }\n\n        return index2SearchQueryIncrementMap;\n    }\n\n    /**\n     * 分批采集 + 计算索引列表IndexingIndex突增量\n     * @param cluster        集群名称\n     * @param indexList      索引名称列表\n     * @return               Map<String, Double>\n     */\n    private Map<String, Double> batchGetIndexingIndexIncrementMap(String cluster, List<String> indexList) {\n        Map<String, Double> index2CurrentIndexingIndexMap = Maps.newHashMap();\n        List<List<String>> indexListList = Lists.partition(indexList, 20);\n        for (List<String> subIndexList : indexListList) {\n            index2CurrentIndexingIndexMap\n                .putAll(esIndicesStatsService.getIndex2CurrentIndexingIndexMap(cluster, subIndexList));\n        }\n\n        // 计算索引列表IndexingIndex突增量\n        Map<String, Double> index2IndexingIndexIncrementMap = Maps.newHashMap();\n        for (String index : indexList) {\n            String uniqueIndexKey = CommonUtils.getUniqueKey(cluster, index);\n            IndexMetrics indexMetrics = index2LastTimeIndexMetricsMap.get(uniqueIndexKey);\n            if (null == indexMetrics) {\n                index2IndexingIndexIncrementMap.put(index, 0d);\n                continue;\n            }\n\n            Double currentTimeSearchQuery = index2CurrentIndexingIndexMap.get(index);\n            Double lastTimeSearchQuery = indexMetrics.getDocUprushNum().doubleValue();\n            // 计算突增值\n            Double incrementValue = MetricsUtils.computerUprushNum(currentTimeSearchQuery, lastTimeSearchQuery);\n            index2IndexingIndexIncrementMap.put(index, incrementValue);\n        }\n\n        return index2IndexingIndexIncrementMap;\n    }\n\n    /**\n     * 分批采集\n     * @param cluster        集群名称\n     * @param indexList      索引名称列表\n     * @return               Map<String, IndexConfig>\n     */\n    private Map<String, IndexConfig> batchGetIndexConfigMap(String cluster, List<String> indexList) {\n        Map<String, IndexConfig> index2IndexConfigMap = Maps.newHashMap();\n        List<List<String>> indexListList = Lists.partition(indexList, 20);\n        for (List<String> subIndexList : indexListList) {\n            index2IndexConfigMap.putAll(esIndexService.syncBatchGetIndexConfig(cluster, subIndexList));\n        }\n        return index2IndexConfigMap;\n    }\n\n    @Override\n    public void collectAllCluster(List<String> clusterList, long currentTime) {\n\n    }\n\n    @Override\n    public String getName() {\n        return \"IndexDashBoardCollector\";\n    }\n\n    /**\n     * 获取配置的大shard列表\n     * @return\n     */\n    private long getConfigBigShard() {\n        return getConfigOrDefaultValue(INDEX_SHARD_BIG_THRESHOLD,DASHBOARD_INDEX_SHARD_BIG_THRESHOLD_DEFAULT_VALUE,SIZE);\n    }\n\n    /**\n     * 获取配置的小shard列表\n     * @return\n     */\n    private long getConfigSmallShard() {\n        return getConfigOrDefaultValue(INDEX_SHARD_SMALL_THRESHOLD,DASHBOARD_INDEX_SHARD_SMALL_THRESHOLD_DEFAULT_VALUE,SIZE);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/dashboard/collector/NodeDashBoardCollector.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.dashboard.collector;\n\nimport com.didichuxing.datachannel.arius.admin.common.Tuple;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.cluster.ecm.ClusterRoleHost;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.DashBoardStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.NodeMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.util.CommonUtils;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didichuxing.datachannel.arius.admin.common.util.FutureUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.core.service.common.AriusConfigInfoService;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESClusterNodeService;\nimport com.didichuxing.datachannel.arius.admin.persistence.es.index.dao.stats.AriusStatsClusterTaskInfoESDAO;\nimport com.didiglobal.knowframework.elasticsearch.client.response.cluster.nodesstats.ClusterNodeStats;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.fs.FSTotal;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.jvm.JvmMem;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.os.OsCpu;\nimport com.didiglobal.knowframework.elasticsearch.client.response.model.threadpool.ThreadPoolNode;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.apache.commons.collections4.MapUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static com.didichuxing.datachannel.arius.admin.common.constant.AriusConfigConstant.*;\nimport static com.didichuxing.datachannel.arius.admin.common.util.AriusUnitUtil.COMMON;\nimport static com.didichuxing.datachannel.arius.admin.common.util.AriusUnitUtil.TIME;\n\n/**\n * Created by linyunan on 3/11/22\n *\n * dashboard单个集群节点采集器\n */\n@Component\npublic class NodeDashBoardCollector extends BaseDashboardCollector {\n    private static final int                                                                     NODE_LARGE_DISK_THRESHOLD         = 85;\n    private static final int                                                                     HEAD_USED_PERCENT_THRESHOLD       = 80;\n    private static final int                                                                     CPU_PERCENT_THRESHOLD             = 80;\n    private static final long                                                                    LARGE_HEAD_USED_PERCENT_TIME      = 10\n                                                                                                                                     * 60\n                                                                                                                                     * 1000;\n    private static final long                                                                    LARGE_CPU_PERCENT_TIME            = 30\n                                                                                                                                     * 60\n                                                                                                                                     * 1000;\n    private static final ILog                                                                    LOGGER                            = LogFactory\n        .getLog(NodeDashBoardCollector.class);\n    private static final Map<String/*cluster@node*/, NodeMetrics>                                nodeName2NodeMetricsMap           = Maps\n        .newConcurrentMap();\n    private static final Map<String/*cluster@node*/, Tuple<Long/*最新采集时间*/, Long/*超过红线的堆内存利用率*/>> nodeName2LargeHeadUsedPerTupleMap = Maps\n        .newConcurrentMap();\n    private static final Map<String/*cluster@node*/, Tuple<Long/*最新采集时间*/, Long/*超过红线的cpu利用率*/>> nodeName2LargeCpuUsedPerTupleMap  = Maps\n        .newConcurrentMap();\n    private static final Map<String/*cluster@node*/, Long/*write-reject-num*/>                   nodeName2WriteRejectNumMap        = Maps\n        .newConcurrentMap();\n    private static final Map<String/*cluster@node*/, Long/*search-reject-num*/>                  nodeName2SearchRejectNumMap       = Maps\n        .newConcurrentMap();\n\n    @Autowired\n    protected ESClusterNodeService                                                               esClusterNodeService;\n\n    @Autowired\n    protected ClusterRoleHostService                                                             clusterRoleHostService;\n\n    @Autowired\n    protected AriusStatsClusterTaskInfoESDAO                                                     ariusStatsClusterTaskInfoESDAO;\n    @Autowired\n    protected AriusConfigInfoService                                                             ariusConfigInfoService;\n\n    private static final FutureUtil                                                              futureUtil                        = FutureUtil\n        .init(\"NodeDashBoardCollector\", 10, 10, 100);\n\n    @Override\n    public void collectSingleCluster(String cluster, long startTime) {\n        List<ClusterRoleHost> clusterRoleHostList = clusterRoleHostService.getNodesByCluster(cluster);\n        if (CollectionUtils.isEmpty(clusterRoleHostList)) {\n            return;\n        }\n\n        AtomicReference<Map<String, ClusterNodeStats>> clusterNodeStatsMapAtomic = new AtomicReference<>(\n            Maps.newHashMap());\n        AtomicReference<Map<String, Long>> node2ShardNumMapAtomic = new AtomicReference<>(Maps.newHashMap());\n        AtomicReference<Map<String, Double>> clusterNodesTaskTotalCostAtomic = new AtomicReference<>(Maps.newHashMap());\n        futureUtil\n            // 注意这里单集群节点比较多会比较慢\n            .runnableTask(() -> clusterNodeStatsMapAtomic.set(esClusterNodeService.syncGetNodePartStatsMap(cluster)))\n            .runnableTask(() -> node2ShardNumMapAtomic.set(esClusterNodeService.syncGetNode2ShardNumMap(cluster)))\n            .runnableTask(() -> clusterNodesTaskTotalCostAtomic\n                .set(ariusStatsClusterTaskInfoESDAO.getClusterNodesTaskTotalCost(cluster)))\n            .waitExecute();\n\n        if (MapUtils.isEmpty(clusterNodeStatsMapAtomic.get())) {\n            LOGGER\n                .error(\"class=NodeDashBoardCollector||method=collectSingleCluster||errMsg=clusterNodeStatsMap is null\");\n        }\n\n        List<ClusterNodeStats> clusterNodeStatsList = Lists.newArrayList(clusterNodeStatsMapAtomic.get().values());\n        Map<String, ClusterNodeStats> name2NodeStatsMap = ConvertUtil.list2Map(clusterNodeStatsList,\n            ClusterNodeStats::getName);\n\n        if (MapUtils.isEmpty(node2ShardNumMapAtomic.get())) {\n            LOGGER\n                .error(\"class=NodeDashBoardCollector||method=collectSingleCluster||errMsg=clusterNodeStatsMap is null\");\n        }\n\n        if (MapUtils.isEmpty(clusterNodesTaskTotalCostAtomic.get())) {\n            LOGGER.error(\n                \"class=NodeDashBoardCollector||method=collectSingleCluster||errMsg=clusterNodesTaskTotalCost is null\");\n        }\n\n        List<DashBoardStats> dashBoardStatsList = Lists.newArrayList();\n        for (ClusterRoleHost clusterRoleHost : clusterRoleHostList) {\n            DashBoardStats dashBoardStats = buildInitDashBoardStats(startTime);\n            String nodeName = clusterRoleHost.getNodeSet();\n\n            String uniqueNodeKey = CommonUtils.getUniqueKey(cluster, nodeName);\n            NodeMetrics nodeMetrics = nodeName2NodeMetricsMap.getOrDefault(uniqueNodeKey, new NodeMetrics());\n            nodeMetrics.setTimestamp(startTime);\n            nodeMetrics.setCluster(cluster);\n            nodeMetrics.setNode(nodeName);\n\n            ClusterNodeStats clusterNodeStats = name2NodeStatsMap.get(nodeName);\n            // 1. 是否Dead节点\n            buildDeadInfo(nodeMetrics, clusterNodeStats);\n            // 2. 是否磁盘利用率超红线 （阈值85%）\n            buildLargeDiskUsageInfo(nodeMetrics, clusterNodeStats);\n            // 3. 是否堆内存利用率超红线 （阈值80% 且持续10分钟）\n            buildLargeHead(nodeMetrics, clusterNodeStats, uniqueNodeKey);\n            // 4. 是否CPU利用率超红线 （80%  持续30分钟）\n            buildLargeCpuUsage(nodeMetrics, clusterNodeStats, uniqueNodeKey);\n            // 5. 节点shard个数\n            nodeMetrics.setShardNum(node2ShardNumMapAtomic.get().getOrDefault(nodeName, 0L));\n            // 6. WriteRejected数\n            buildWriteRejectedNum(nodeMetrics, clusterNodeStats, uniqueNodeKey);\n            // 7. SearchRejected数\n            buildSearchRejectedNum(nodeMetrics, clusterNodeStats, uniqueNodeKey);\n            //8. 节点执行任务耗时\n            nodeMetrics.setTaskConsuming(clusterNodesTaskTotalCostAtomic.get().getOrDefault(nodeName, 0d).longValue());\n\n            long currentTimeMillis = System.currentTimeMillis();\n            long elapsedTime = currentTimeMillis - startTime;\n            nodeMetrics.setNodeElapsedTime(elapsedTime);\n\n            // 设置dashboard中节点维度指标数据\n            dashBoardStats.setNode(nodeMetrics);\n\n            dashBoardStatsList.add(dashBoardStats);\n\n            // 暂存当前节点指标信息 针对特殊场景，即节点掉线后, 当前的策略是会使用上一次采集到的数据\n            nodeName2NodeMetricsMap.put(uniqueNodeKey, nodeMetrics);\n        }\n\n        if (CollectionUtils.isEmpty(dashBoardStatsList)) {\n            return;\n        }\n\n        monitorMetricsSender.sendDashboardStats(dashBoardStatsList);\n    }\n\n    @Override\n    public void collectAllCluster(List<String> clusterList, long currentTime) {\n\n    }\n\n    @Override\n    public String getName() {\n        return \"NodeDashBoardCollector\";\n    }\n\n    /****************************************************private********************************************************/\n    private void buildSearchRejectedNum(NodeMetrics nodeMetrics, ClusterNodeStats clusterNodeStats,\n                                        String uniqueNodeKey) {\n        if (null == clusterNodeStats) {\n            return;\n        }\n        if (null == clusterNodeStats.getThreadPool()) {\n            return;\n        }\n        if (null == clusterNodeStats.getThreadPool().getSearch()) {\n            return;\n        }\n\n        ThreadPoolNode search = clusterNodeStats.getThreadPool().getSearch();\n        // get diff\n        long diff = esClusterNodeService.getSearchRejectedNum(uniqueNodeKey.split(\"@\")[0],uniqueNodeKey.split(\"@\")[1]);\n        nodeMetrics.setSearchRejectedNum(diff <= 0 ? 0 : diff);\n    }\n\n    private void buildWriteRejectedNum(NodeMetrics nodeMetrics, ClusterNodeStats clusterNodeStats,\n                                       String uniqueNodeKey) {\n        if (null == clusterNodeStats) {\n            return;\n        }\n        if (null == clusterNodeStats.getThreadPool()) {\n            return;\n        }\n        if (null == clusterNodeStats.getThreadPool().getWrite()) {\n            return;\n        }\n        ThreadPoolNode write = clusterNodeStats.getThreadPool().getWrite();\n        // get diff\n        long diff = esClusterNodeService.getWriteRejectedNum(uniqueNodeKey.split(\"@\")[0],uniqueNodeKey.split(\"@\")[1]);\n        nodeMetrics.setWriteRejectedNum(diff <= 0 ? 0 : diff);\n    }\n\n    private void buildLargeCpuUsage(NodeMetrics nodeMetrics, ClusterNodeStats clusterNodeStats, String uniqueNodeKey) {\n        // 如果节点掉线不去设置，保留上一次采集到的disk info\n        if (null == clusterNodeStats) {\n            nodeName2LargeCpuUsedPerTupleMap.remove(uniqueNodeKey);\n            return;\n        }\n        if (null == clusterNodeStats.getOs()) {\n            nodeName2LargeCpuUsedPerTupleMap.remove(uniqueNodeKey);\n            return;\n        }\n        if (null == clusterNodeStats.getOs().getCpu()) {\n            nodeName2LargeCpuUsedPerTupleMap.remove(uniqueNodeKey);\n            return;\n        }\n\n        OsCpu cpu = clusterNodeStats.getOs().getCpu();\n        long cpuPer = cpu.getPercent();\n\n        // cpuPer大于上限, save to nodeName2LargeCpuUsedPerTupleMap, 若连续出现大于上限, 仅保留第一次超过上限的时间点\n\n        if (cpuPer >= getConfigLargeCpuPercentThreshold()) {\n            // 连续出现大于上限, tuple中时间保持不变\n            nodeName2LargeCpuUsedPerTupleMap.put(uniqueNodeKey, nodeName2LargeCpuUsedPerTupleMap\n                .getOrDefault(uniqueNodeKey, new Tuple<>(System.currentTimeMillis(), cpuPer)).setV2(cpuPer));\n        } else {\n            nodeName2LargeCpuUsedPerTupleMap.remove(uniqueNodeKey);\n        }\n\n        Tuple<Long, Long> nodeName2LargeCpuUsedPerTupleFromMap = nodeName2LargeCpuUsedPerTupleMap.get(uniqueNodeKey);\n        if (null == nodeName2LargeCpuUsedPerTupleFromMap) {\n            nodeMetrics.setLargeCpuUsage(0D);\n        } else {\n            long interval = System.currentTimeMillis() - nodeName2LargeCpuUsedPerTupleFromMap.getV1();\n            if (interval >= getConfigLargeCpuPercentTimeThreshold()) {\n                nodeMetrics.setLargeCpuUsage((double) cpuPer);\n            } else {\n                nodeMetrics.setLargeCpuUsage(-1D);\n            }\n        }\n\n    }\n\n    private void buildLargeHead(NodeMetrics nodeMetrics, ClusterNodeStats clusterNodeStats, String uniqueNodeKey) {\n        // 如果节点掉线不去设置，保留上一次采集到的head info\n        if (null == clusterNodeStats) {\n            nodeName2LargeHeadUsedPerTupleMap.remove(uniqueNodeKey);\n            return;\n        }\n        if (null == clusterNodeStats.getJvm()) {\n            nodeName2LargeHeadUsedPerTupleMap.remove(uniqueNodeKey);\n            return;\n        }\n        if (null == clusterNodeStats.getJvm().getMem()) {\n            nodeName2LargeHeadUsedPerTupleMap.remove(uniqueNodeKey);\n            return;\n        }\n        if (null == clusterNodeStats.getJvm().getMem()) {\n            nodeName2LargeHeadUsedPerTupleMap.remove(uniqueNodeKey);\n            return;\n        }\n\n        JvmMem jvmMem = clusterNodeStats.getJvm().getMem();\n        long heapUsedPercent = jvmMem.getHeapUsedPercent();\n\n        // heapUsedPercent大于上限, save to nodeName2LargeHeadUsedPerTupleMap, 若连续出现大于上限, 仅保留第一次超过上限的时间点\n        if (heapUsedPercent >= getConfigLargeHeadPercentThreshold()) {\n            // 连续出现大于上限, tuple中时间保持不变\n            nodeName2LargeHeadUsedPerTupleMap.put(uniqueNodeKey,\n                nodeName2LargeHeadUsedPerTupleMap\n                    .getOrDefault(uniqueNodeKey, new Tuple<>(System.currentTimeMillis(), heapUsedPercent))\n                    .setV2(heapUsedPercent));\n        } else {\n            nodeName2LargeHeadUsedPerTupleMap.remove(uniqueNodeKey);\n        }\n\n        Tuple<Long, Long> time2HeadUsedPerTupleFromMap = nodeName2LargeHeadUsedPerTupleMap.get(uniqueNodeKey);\n        if (null == time2HeadUsedPerTupleFromMap) {\n            nodeMetrics.setLargeHead(0D);\n        } else {\n            long interval = System.currentTimeMillis() - time2HeadUsedPerTupleFromMap.getV1();\n            if (interval >= getConfigLargeHeadPercentTimeThreshold()) {\n                nodeMetrics.setLargeHead((double) heapUsedPercent);\n            } else {\n                nodeMetrics.setLargeHead(-1D);\n            }\n        }\n    }\n\n    private void buildDeadInfo(NodeMetrics nodeMetrics, ClusterNodeStats clusterNodeStats) {\n        nodeMetrics.setDead(null == clusterNodeStats);\n    }\n\n    private void buildLargeDiskUsageInfo(NodeMetrics nodeMetrics, ClusterNodeStats clusterNodeStats) {\n        // 如果节点掉线不去设置，保留上一次采集到的disk info\n        if (null == clusterNodeStats) {\n            return;\n        }\n        if (null == clusterNodeStats.getFs()) {\n            return;\n        }\n        if (null == clusterNodeStats.getFs().getTotal()) {\n            return;\n        }\n\n        FSTotal total = clusterNodeStats.getFs().getTotal();\n        double freeDiskPer = CommonUtils.divideDoubleAndFormatDouble(total.getFreeInBytes(), total.getTotalInBytes(), 5,\n            100);\n\n        if (freeDiskPer <= 100 -getConfigLargeDiskUsage()) {\n            nodeMetrics.setLargeDiskUsage(100 - freeDiskPer);\n        } else {\n            nodeMetrics.setLargeDiskUsage(-1D);\n        }\n    }\n\n    /**\n     * 获取从磁盘使用率配置\n     * @return large.disk.usage.threshold\n     */\n    private long getConfigLargeDiskUsage() {\n        return getConfigOrDefaultValue(NODE_DISK_USED_PERCENT_THRESHOLD,DASHBOARD_NODE_DISK_USED_PERCENT_THRESHOLD_DEFAULT_VALUE,COMMON);\n    }\n\n    /**\n     * 获取堆内存利用率超红线阈值\n     * node.large.head.used.percent.threshold\n     * @return\n     */\n    private long getConfigLargeHeadPercentThreshold() {\n        return getConfigOrDefaultValue(NODE_LARGE_HEAD_USAGE_PERCENT_THRESHOLD,DASHBOARD_HEAD_USED_PERCENT_THRESHOLD_DEFAULT_VALUE,COMMON);\n    }\n\n    /**\n     * 获堆内存利用率持续时间红线\n     * node.large.head.used.percent.time.threshold\n     * @return\n     */\n    private long getConfigLargeHeadPercentTimeThreshold() {\n        return getConfigOrDefaultValue(NODE_LARGE_HEAD_USED_PERCENT_TIME_USAGE_THRESHOLD,DASHBOARD_LARGE_HEAD_USED_PERCENT_TIME_DEFAULT_VALUE,TIME);\n    }\n\n    /**\n     * 获堆CPU利用率超红线\n     * node.large.cpu.used.percent.threshold\n     * @return\n     */\n    private long getConfigLargeCpuPercentThreshold() {\n        return getConfigOrDefaultValue(NODE_LARGE_CPU_USAGE_PERCENT_THRESHOLD,DASHBOARD_CPU_PERCENT_THRESHOLD_DEFAULT_VALUE,COMMON);\n    }\n\n    /**\n     * cpu利用率持续时间超红线阈值\n     * node.large.cpu.used.percent.time.threshold\n     * @return\n     */\n    private long getConfigLargeCpuPercentTimeThreshold() {\n        return getConfigOrDefaultValue(NODE_CPU_USED_PERCENT_THRESHOLD_TIME_DURATION_THRESHOLD,\n                DASHBOARD_NODE_CPU_USED_PERCENT_THRESHOLD_TIME_DURATION_THRESHOLD_DEFAULT_VALUE,TIME);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/dashboard/collector/TemplateDashBoardCollector.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.dashboard.collector;\n\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.shard.Segment;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.DashBoardStats;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.stats.dashboard.TemplateMetrics;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplate;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhyWithLogic;\nimport com.didichuxing.datachannel.arius.admin.common.util.IndexNameUtils;\nimport com.didichuxing.datachannel.arius.admin.core.service.es.ESShardService;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.physic.IndexTemplatePhyService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * Created by linyunan on 3/11/22\n * dashboard单个集群模板采集器\n */\n@Component\npublic class TemplateDashBoardCollector extends BaseDashboardCollector {\n    private static final ILog LOGGER = LogFactory.getLog(TemplateDashBoardCollector.class);\n\n    @Autowired\n    IndexTemplatePhyService   indexTemplatePhyService;\n\n    @Autowired\n    ESShardService            esShardService;\n\n    @Override\n    public void collectSingleCluster(String cluster, long currentTime) {\n        List<IndexTemplatePhyWithLogic> logicTemplates = indexTemplatePhyService.getTemplateByPhyCluster(cluster);\n        if (logicTemplates.isEmpty()) {\n            LOGGER.error(\n                \"class=TemplateDashBoardCollector||method=collectSingleCluster||errMsg=clusterTemplateList is null\");\n            return;\n        }\n        List<Segment> segments = esShardService.syncGetSegments(cluster);\n        if (segments.isEmpty()) {\n            LOGGER.error(\"class=TemplateDashBoardCollector||method=collectSingleCluster||errMsg=segments is null\");\n            return;\n        }\n\n        List<DashBoardStats> dashBoardStatsList = Lists.newArrayList();\n        for (IndexTemplatePhyWithLogic indexTemplatePhyWithLogic : logicTemplates) {\n            DashBoardStats dashBoardStats = buildInitDashBoardStats(currentTime);\n            IndexTemplate indexTemplate = indexTemplatePhyWithLogic.getLogicTemplate();\n\n            TemplateMetrics templateMetrics = new TemplateMetrics();\n            templateMetrics.setTimestamp(currentTime);\n            templateMetrics.setCluster(cluster);\n            templateMetrics.setTemplate(indexTemplate.getName());\n            templateMetrics.setTemplateId((long) indexTemplate.getId());\n\n            //1 template segments 数量以及占用内存大小\n            buildTemplateStats(templateMetrics, segments, indexTemplatePhyWithLogic.getExpression());\n\n            dashBoardStats.setTemplate(templateMetrics);\n            dashBoardStatsList.add(dashBoardStats);\n        }\n\n        if (CollectionUtils.isEmpty(dashBoardStatsList)) {\n            return;\n        }\n\n        monitorMetricsSender.sendDashboardStats(dashBoardStatsList);\n    }\n\n    @Override\n    public void collectAllCluster(List<String> clusterList, long currentTime) {\n    }\n\n    @Override\n    public String getName() {\n        return \"TemplateDashBoardCollector\";\n    }\n\n    private void buildTemplateStats(TemplateMetrics templateMetrics, List<Segment> clusterSegments, String expression) {\n        //这里传入的segments 是整个cluster 所有segments，先按照template expression 过滤出该模板所有的segments\n        List<Segment> matchExpSegments = clusterSegments.stream()\n            .filter(s -> IndexNameUtils.indexExpMatch(s.getIndex(), expression)).collect(Collectors.toList());\n\n        templateMetrics.setSegmentNum((long) matchExpSegments.size());\n        templateMetrics.setSegmentMemSize(matchExpSegments.stream().mapToDouble(Segment::getMemoSize).sum() );\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/ecmtask/SyncEcmTaskStatus.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.ecmtask;\n\nimport java.util.List;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport com.didichuxing.datachannel.arius.admin.biz.task.ecm.EcmTaskManager;\nimport com.didichuxing.datachannel.arius.admin.common.constant.ecm.EcmTaskStatusEnum;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.workorder.ecm.EcmTask;\nimport com.didichuxing.datachannel.arius.admin.common.util.AriusObjUtils;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\n\n/**\n * 定时同步集群任务状态\n */\n//@Task(name = \"syncEcmTaskStatus\", description = \"定时同步集群任务状态\", cron = \"0 0/2 * * * ?\", autoRegister = true)\npublic class SyncEcmTaskStatus implements Job {\n    private static final ILog LOGGER = LogFactory.getLog(SyncEcmTaskStatus.class);\n\n    @Autowired\n    private EcmTaskManager      ecmTaskManager;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=SyncEcmTaskStatus||method=syncTaskStatus||msg=start\");\n\n        // 获取处于running状态的ecm任务列表\n        List<EcmTask> ecmTasks = ecmTaskManager.listRunningEcmTask();\n        if (AriusObjUtils.isEmptyList(ecmTasks)) {\n            LOGGER.info(\"class=SyncEcmTaskStatus||method=syncTaskStatus||msg=worktask empty and finished\");\n            return TaskResult.buildSuccess();\n        }\n\n        // todo:对于集群新建，扩缩容这些可能修改物理集群读写地址的任务，可能会出现重试中阻塞的问题，从而影响到下一个任务的执行，考虑是否采用线程池\n        for (EcmTask ecmTask : ecmTasks) {\n            try {\n                EcmTaskStatusEnum ecmTaskStatusEnum = ecmTaskManager.refreshEcmTask(ecmTask);\n                LOGGER.info(\"class=SyncEcmTaskStatus||method=syncTaskStatus||taskId={}||resultStatus={}\",\n                    ecmTask.getId(), ecmTaskStatusEnum.getValue());\n            } catch (Exception e) {\n                LOGGER.error(\"class=SyncEcmTaskStatus||method=syncTaskStatus||errMsg={}||worktask={}\", e.getMessage(),\n                    ecmTask);\n            }\n        }\n        LOGGER.info(\"class=SyncEcmTaskStatus||method=syncTaskStatus||msg=finish\");\n\n        return TaskResult.buildSuccess();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/metadata/DslTemplateDelExpiredRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.metadata;\n\nimport com.didichuxing.datachannel.arius.admin.metadata.job.dsl.DslTemplateDelExpiredJob;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n@Task(name = \"DslTemplateDelExpiredRandomTask\", description = \"删除过期查询模板\", cron = \"0 0 5 */1 * ?\", autoRegister = true)\npublic class DslTemplateDelExpiredRandomTask implements Job {\n\n    @Autowired\n    private DslTemplateDelExpiredJob dslTemplateDelExpiredJob;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n\n        dslTemplateDelExpiredJob.handleJobTask(\"\");\n\n        return TaskResult.buildSuccess();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/metadata/DslTemplateUpdateNearestQueryLimitRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.metadata;\n\nimport com.didichuxing.datachannel.arius.admin.metadata.job.dsl.DslTemplateUpdateNearestQueryLimitJob;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * @author cjm\n * 更新最近的DSL模版限流值任务\n * 每分钟执行一次\n */\n@Task(name = \"DslTemplateUpdateNearestQueryLimitRandomTask\", description = \"更新最近的DSL模版限流值任务\", cron = \"0 */5 * * * ?\", autoRegister = true)\npublic class DslTemplateUpdateNearestQueryLimitRandomTask implements Job {\n\n    @Autowired\n    private DslTemplateUpdateNearestQueryLimitJob dslTemplateUpdateNearestQueryLimitJob;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        // 更新最近的DSL模版限流值任务\n        dslTemplateUpdateNearestQueryLimitJob.handleJobTask(\"\");\n        return TaskResult.buildSuccess();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/metadata/ESClusterMetricsCollectorBroadcastTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.metadata;\n\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.ClusterMonitorJobHandler;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.consensual.ConsensualEnum;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n@Task(name = \"ESClusterMetricsCollectorBroadcastTask\", description = \"集群指标采集调度任务\", cron = \"0 0/1 * * * ? *\", autoRegister = true, consensual = ConsensualEnum.BROADCAST)\npublic class ESClusterMetricsCollectorBroadcastTask implements Job {\n\n    @Autowired\n    private ClusterMonitorJobHandler clusterMonitorJobHandler;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        clusterMonitorJobHandler.handleJobTask(\"\");\n        return TaskResult.buildSuccess();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/metadata/ESLogicClusterMetricsCollectorBroadcastTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.metadata;\n\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.LogicClusterMonitorJobHandler;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.consensual.ConsensualEnum;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n@Task(name = \"ESLogicClusterMetricsCollectorBroadcastTask\", description = \"逻辑集群调度任务\", cron = \"0 0/1 * * * ? *\", autoRegister = true, consensual = ConsensualEnum.BROADCAST)\npublic class ESLogicClusterMetricsCollectorBroadcastTask implements Job {\n    private static final ILog LOGGER = LogFactory\n        .getLog(ESLogicClusterMetricsCollectorBroadcastTask.class);\n\n    @Autowired\n    private LogicClusterMonitorJobHandler logicClusterMonitorJobHandler;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=ESLogicClusterMetricsCollectorBroadcastTask||method=execute||msg=start\");\n        logicClusterMonitorJobHandler.handleJobTask(\"\");\n        return TaskResult.buildSuccess();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/metadata/ESNodeAndIndicesMetricsCollectorBroadcastTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.metadata;\n\nimport com.didiglobal.knowframework.job.core.consensual.ConsensualEnum;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport com.didichuxing.datachannel.arius.admin.metadata.job.cluster.monitor.esmonitorjob.MonitorJobHandler;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\n\n@Task(name = \"ESNodeAndIndicesMetricsCollectorBroadcastTask\", description = \"节点和索引指标信息采集调度任务\", cron = \"0 0/1 * * * ? *\", autoRegister = true, consensual = ConsensualEnum.BROADCAST)\npublic class ESNodeAndIndicesMetricsCollectorBroadcastTask implements Job {\n    private static final ILog LOGGER = LogFactory.getLog(ESNodeAndIndicesMetricsCollectorBroadcastTask.class);\n\n    @Autowired\n    private MonitorJobHandler   monitorJobHandler;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=ESNodeAndIndicesMetricsCollectorBroadcastTask||method=execute||msg=start\");\n        monitorJobHandler.handleBrocastJobTask(\"\", jobContext.getCurrentWorkerCode(), jobContext.getAllWorkerCodes());\n        return TaskResult.buildSuccess();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/metadata/IndicesCatInfoCollectorRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.metadata;\n\nimport com.didichuxing.datachannel.arius.admin.metadata.job.index.IndexCatInfoCollector;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n@Task(name = \"IndicesCatInfoCollectorRandomTask\", description = \"采集索引Cat/Index基本信息\", cron = \"0 0/3 * * * ? *\", autoRegister = true)\npublic class IndicesCatInfoCollectorRandomTask implements Job {\n    private static final ILog LOGGER = LogFactory.getLog(IndicesCatInfoCollectorRandomTask.class);\n\n    @Autowired\n    private IndexCatInfoCollector indexCatInfoCollector;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception{\n        LOGGER.info(\"class=IndicesCatInfoCollectorRandomTask||method=execute||msg=start\");\n        indexCatInfoCollector.handleJobTask(\"\");\n        return TaskResult.buildSuccess();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/metadata/ShardsCatInfoCollectorRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.metadata;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport com.didichuxing.datachannel.arius.admin.metadata.job.shard.ShardCatInfoCollector;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\n\n//@Task(name = \"ShardsCatInfoCollectorRandomTask\", description = \"采集索引Cat/Shards基本信息\", cron = \"0 0/3 * * * ? *\", autoRegister = true)\npublic class ShardsCatInfoCollectorRandomTask implements Job {\n    private static final ILog LOGGER = LogFactory.getLog(ShardsCatInfoCollectorRandomTask.class);\n\n    @Autowired\n    private ShardCatInfoCollector shardCatInfoCollector;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=ShardsCatInfoCollectorRandomTask||method=execute||msg=start\");\n        shardCatInfoCollector.handleJobTask(\"\");\n        return TaskResult.buildSuccess();\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/resource/ClusterLogicHealthCollectorRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.resource;\n\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentClusterLogicTask;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * Created by linyunan on 2021-10-15\n */\n@Task(name = \"ClusterLogicHealthCollectorRandomTask\", description = \"采集逻辑集群状态信息\", cron = \"0 0/2 * * * ? *\", autoRegister = true)\npublic class ClusterLogicHealthCollectorRandomTask extends BaseConcurrentClusterLogicTask implements Job {\n    private static final ILog LOGGER = LogFactory.getLog(ClusterLogicHealthCollectorRandomTask.class);\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=ClusterLogicHealthCollectorRandomTask||method=execute||msg=start\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n    @Override\n    public String getTaskName() {\n        return \"ClusterLogicHealthCollectorRandomTask\";\n    }\n\n    @Override\n    public int poolSize() {\n        return 5;\n    }\n\n    @Override\n    public int current() {\n        return 10;\n    }\n\n    @Override\n    protected boolean executeByClusterLogic(Long clusterLogicId) {\n        return clusterLogicManager.updateClusterLogicHealth(clusterLogicId);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/resource/ClusterNodeSettingCollectorRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.resource;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminTaskException;\nimport com.didichuxing.datachannel.arius.admin.core.service.cluster.physic.ClusterRoleHostService;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentClusterTask;\nimport com.didichuxing.datachannel.arius.admin.task.TaskConcurrentConstants;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n@Task(name = \"ClusterNodeSettingCollectorRandomTask\", description = \"同步节点配置任务\", cron = \"0 0/3 * * * ?\", autoRegister = true)\npublic class ClusterNodeSettingCollectorRandomTask extends BaseConcurrentClusterTask implements Job {\n\n    private static final ILog      LOGGER = LogFactory.getLog(ClusterNodeSettingCollectorRandomTask.class);\n\n    @Autowired\n    private ClusterRoleHostService clusterRoleHostService;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\n            \"class=ClusterNodeSettingCollectorRandomTask||method=execute||msg=ClusterNodeSettingCollectorRandomTask start.\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n    /**\n     * 获取任务名称\n     *\n     * @return 任务名称\n     */\n    @Override\n    public String getTaskName() {\n        return \"ClusterNodeSettingCollectorRandomTask\";\n    }\n\n    /**\n     * 任务的线程个数\n     * @return 任务的线程个数\n     */\n    @Override\n    public int poolSize() {\n        return 3;\n    }\n\n    /**\n     * 并发度\n     *\n     * @return\n     */\n    @Override\n    public int current() {\n        return TaskConcurrentConstants.COLLECT_CLUSTER_NODE_SETTING_FROM_ES_TASK_CONCURRENT;\n    }\n\n    /**\n     * 同步处理指定集群\n     *\n     * 1、获取es集群中的所有节点\n     * 2、获取数据库中的全部节点\n     * 3、对比\n     * 4、刷库\n     *\n     * @param cluster 集群名字\n     */\n    @Override\n    public boolean executeByCluster(String cluster) throws AdminTaskException {\n        return clusterRoleHostService.collectClusterNodeSettings(cluster);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/resource/ClusterResourceInfoCollectorRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.resource;\n\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentClusterTask;\nimport com.didichuxing.datachannel.arius.admin.task.metadata.IndicesCatInfoCollectorRandomTask;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * Created by linyunan on 2021-10-15\n */\n@Task(name = \"ClusterResourceInfoCollectorRandomTask\", description = \"采集物理集群资源信息\", cron = \"0 0/3 * * * ? *\", autoRegister = true)\npublic class ClusterResourceInfoCollectorRandomTask extends BaseConcurrentClusterTask implements Job {\n    private static final ILog LOGGER = LogFactory.getLog(ClusterResourceInfoCollectorRandomTask.class);\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=ClusterResourceInfoCollectorRandomTask||method=execute||msg=start\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n    @Override\n    public String getTaskName() {\n        return \"ClusterResourceInfoCollectorRandomTask\";\n    }\n\n    @Override\n    public int poolSize() {\n        return 5;\n    }\n\n    @Override\n    public int current() {\n        return 10;\n    }\n\n    @Override\n    protected boolean executeByCluster(String cluster) {\n        return clusterPhyManager.updateClusterInfo(cluster, AriusUser.SYSTEM.getDesc());\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/CopyIndexMapping2TemplateRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentClusterTask;\nimport com.didichuxing.datachannel.arius.admin.task.TaskConcurrentConstants;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\n\n/**\n * @author didi\n * Created by d06679 on 2018/3/14.\n */\n@Task(name = \"CopyIndexMapping2TemplateRandomTask\", description = \"copyMapping任务，定期将索引中的mapping拷贝到模板中，避免大量的put-mappin\", cron = \"0 45 9/12 * * ?\", autoRegister = true)\npublic class CopyIndexMapping2TemplateRandomTask extends BaseConcurrentClusterTask implements Job {\n\n    private static final ILog LOGGER = LogFactory.getLog(CopyIndexMapping2TemplateRandomTask.class);\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\n            \"class=CopyIndexMapping2TemplateRandomTask||method=execute||msg=CopyIndexMapping2TemplateRandomTask start.\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n    /**\n     * 获取任务名称\n     *\n     * @return 任务名称\n     */\n    @Override\n    public String getTaskName() {\n        return \"CopyIndexMapping2TemplateRandomTask\";\n    }\n\n    /**\n     * 任务的线程个数\n     * @return 任务的线程个数\n     */\n    @Override\n    public int poolSize() {\n        return 20;\n    }\n\n    /**\n     * 并发度\n     *\n     * @return\n     */\n    @Override\n    public int current() {\n        return TaskConcurrentConstants.COPY_INDEX_MAPPING2_TEMPLATE_TASK_CONCURRENT;\n    }\n\n    /**\n     * 同步处理指定集群\n     *\n     * @param cluster 集群名字\n     */\n    @Override\n    public boolean executeByCluster(String cluster) throws AdminOperateException {\n        return clusterPhyManager.copyMapping(cluster, 5);\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/JudgeTemplateBlockWriteTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template;\n\nimport com.didichuxing.datachannel.arius.admin.biz.indices.IndicesManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplatePhy;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.template.IndexTemplateWithPhyTemplates;\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.SizeUtil;\nimport com.didichuxing.datachannel.arius.admin.core.service.template.logic.IndexTemplateService;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentTemplateTask;\nimport com.didiglobal.knowframework.elasticsearch.client.response.indices.catindices.CatIndexResult;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport java.util.List;\nimport java.util.Objects;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * 定时判断是否对模版禁写\n *    判断依据：模版下所有分区总存储大小 > 模版配额磁盘大小\n *    每五分钟执行一次\n *\n * @Authoer: zyl\n * @Date: 2022/07/07\n * @Version: 1.0\n */\n\n@Task(name = \"JudgeTemplateBlockWriteTask\", description = \"检查模版磁盘使用率是否达到上限\", cron = \"0 */5 * * * ?\", autoRegister = true)\npublic class JudgeTemplateBlockWriteTask extends BaseConcurrentTemplateTask implements Job {\n    private static final ILog LOGGER = LogFactory.getLog(JudgeTemplateBlockWriteTask.class);\n\n    @Autowired\n    private IndexTemplateService indexTemplateService;\n\n    @Autowired\n    private IndicesManager       indicesManager;\n\n    @Override\n    public String getTaskName() {\n        return \"检查模版磁盘使用率是否达到上限\";\n    }\n\n    @Override\n    public int poolSize() {\n        return 10;\n    }\n\n    @Override\n    public int current() {\n        return 10;\n    }\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=JudgeTemplateBlockWriteTask||method=execute||msg=JudgeTemplateBlockWriteTask start.\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n    @Override\n    protected boolean executeByLogicTemplate(Integer logicId) throws AdminOperateException {\n        IndexTemplateWithPhyTemplates indexTemplateWithPhyTemplates = indexTemplateService\n            .getLogicTemplateWithPhysicalsById(logicId);\n\n        if (indexTemplateWithPhyTemplates == null) {\n            throw new AdminOperateException(String.format(\"模板[%s]不存在\", logicId));\n        }\n\n        long limitDiskSize = (long) (indexTemplateWithPhyTemplates.getDiskSize() * 1024 * 1024 * 1024);\n\n        IndexTemplatePhy masterPhyTemplate = indexTemplateWithPhyTemplates.getMasterPhyTemplate();\n        if (masterPhyTemplate == null) {\n            throw new AdminOperateException(String.format(\"模板[%s]对应的物理模板不存在\", logicId));\n        }\n\n        List<CatIndexResult> catIndexResults = indicesManager\n            .listIndexCatInfoByTemplatePhyId(masterPhyTemplate.getId());\n\n        long templateIndicesDiskSum = 0;\n        if (CollectionUtils.isNotEmpty(catIndexResults)) {\n            // 统计逻辑模版所有索引的占用磁盘大小\n            // storeSize属性为string类型，把单位统一转换为byte\n            templateIndicesDiskSum = catIndexResults.stream()\n                    .filter(r-> Objects.nonNull(r.getStoreSize()))\n                    .mapToLong(r -> SizeUtil.getUnitSize(r.getStoreSize()))\n                .sum();\n        }\n\n        // 判断是否禁写\n        if (templateIndicesDiskSum < limitDiskSize) {\n            return true;\n        }\n\n        Result<Void> ret = indexTemplateService.updateBlockWriteState(indexTemplateWithPhyTemplates.getId(), true);\n        return !ret.failed();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/SyncTemplateMetadataRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentClusterTask;\nimport com.didichuxing.datachannel.arius.admin.task.TaskConcurrentConstants;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\n\n/**\n * @author didi\n * Created by d06679 on 2018/3/14.\n */\n@Task(name = \"SyncTemplateMetadataRandomTask\", description = \"集群模板元数据同步任务\", cron = \"0 20 2 * * ?\", autoRegister = true)\npublic class SyncTemplateMetadataRandomTask extends BaseConcurrentClusterTask implements Job {\n\n    private static final ILog LOGGER = LogFactory.getLog(SyncTemplateMetadataRandomTask.class);\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=SyncTemplateMetadataRandomTask||method=execute||msg=SyncTemplateMetadataRandomTask start.\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n    /**\n     * 获取任务名称\n     *\n     * @return 任务名称\n     */\n    @Override\n    public String getTaskName() {\n        return \"SyncTemplateMetadataRandomTask\";\n    }\n\n    /**\n     * 任务的线程个数\n     * @return 任务的线程个数\n     */\n    @Override\n    public int poolSize() {\n        return 20;\n    }\n\n    /**\n     * 并发度\n     *\n     * @return\n     */\n    @Override\n    public int current() {\n        return TaskConcurrentConstants.SYNC_TEMPLATE_META_DATE_TASK_CONCURRENT;\n    }\n\n    /**\n     * 同步处理指定集群\n     *\n     * @param cluster 集群名字\n     */\n    @Override\n    public boolean executeByCluster(String cluster) throws AdminOperateException {\n        clusterPhyManager.syncTemplateMetaData(cluster, 5);\n        return true;\n    }\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/srv/ColdDataMoveRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.cold.ColdManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentTemplateTask;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * @author chengxiang\n * @date 2022/06/07\n */\n@Task(name = \"ColdDataMoveRandomTask\", description = \"admin冷数据搬迁服务\", cron = \"0 30 22 * * ?\", autoRegister = true)\npublic class ColdDataMoveRandomTask extends BaseConcurrentTemplateTask implements Job {\n\n    private static final ILog LOGGER = LogFactory.getLog(ColdDataMoveRandomTask.class);\n\n    @Autowired\n    private ColdManager       coldManager;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=ColdDataMoveRandomTask||method=execute||msg=ColdDataMoveRandomTask start\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n  \n\n    @Override\n    public int poolSize() {\n        return 10;\n    }\n\n    @Override\n    public int current() {\n        return 5;\n    }\n    \n    @Override\n    protected boolean executeByLogicTemplate(Integer logicId) {\n        try {\n            final Result<Boolean> result = coldManager.move2ColdNode(logicId);\n            if (Boolean.FALSE.equals(result.getData())) {\n                LOGGER.warn(\"class=ColdDataMoveRandomTask||method=executeByLogicTemplate||logicId={}||msg={}\", logicId,\n                        result.getMessage());\n            }\n            return result.getData();\n        } catch (Exception e) {\n            LOGGER.error(\"class=ColdDataMoveRandomTask||method=executeByLogicTemplate||logicId={}||msg=admin冷数据搬迁服务\",\n                    logicId, e);\n        }\n        \n        return Boolean.TRUE;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/srv/DcdrInfoCollectorRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentTemplateTask;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n@Task(name = \"DcdrInfoCollectorRandomTask\", description = \"采集dcdr相关数据\", cron = \"0 0/5 * * * ? *\", autoRegister = true)\npublic class DcdrInfoCollectorRandomTask extends BaseConcurrentTemplateTask implements Job {\n\n    private static final ILog LOGGER = LogFactory.getLog(DcdrInfoCollectorRandomTask.class);\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=DcdrInfoCollectorRandomTask||method=execute||msg=DcdrInfoCollectorRandomTask start.\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n    @Override\n    public String getTaskName() {\n        return \"DcdrInfoCollectorRandomTask\";\n    }\n\n    @Override\n    public int poolSize() {\n        return 10;\n    }\n\n    @Override\n    public int current() {\n        return 5;\n    }\n\n    @Override\n    protected boolean executeByLogicTemplate(Integer logicId) throws AdminOperateException {\n        return templateLogicManager.updateDCDRInfo(logicId);\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/srv/DeleteDirtyDCDRLinksRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template.srv;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didichuxing.datachannel.arius.admin.biz.task.OpTaskManager;\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.dcdr.TemplateDCDRManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.OpTask;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.detail.DCDRSingleTemplateMasterSlaveSwitchDetail;\nimport com.didichuxing.datachannel.arius.admin.common.bean.entity.task.detail.DCDRTasksDetail;\nimport com.didichuxing.datachannel.arius.admin.common.constant.AuthConstant;\nimport com.didichuxing.datachannel.arius.admin.common.constant.arius.AriusUser;\nimport com.didichuxing.datachannel.arius.admin.common.constant.dcdr.DCDRSwithTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.constant.task.OpTaskTypeEnum;\nimport com.didichuxing.datachannel.arius.admin.common.exception.ESOperateException;\nimport com.didichuxing.datachannel.arius.admin.common.util.ConvertUtil;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport java.util.List;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.collections4.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * 删除脏dcdrlinks随机任务\n *\n * @author shizeying\n * @date 2022/05/09\n */\n@Task(name = \"DeleteDirtyDCDRLinksRandomTask\", description = \"删除成功任务中的dcdr脏链路\", cron = \"0 0 2 */1 * ?\", autoRegister = true)\npublic class DeleteDirtyDCDRLinksRandomTask implements Job {\n    private static final ILog LOGGER = LogFactory.getLog(DeleteDirtyDCDRLinksRandomTask.class);\n\n    @Autowired\n    private OpTaskManager       opTaskManager;\n\n    @Autowired\n    private TemplateDCDRManager templateDcdrManager;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=DeleteDirtyDCDRLinksRandomTask||method=execute||msg=start\");\n\n        //获取成功的dcdr主从切换任务\n        List<OpTask> successDcdrSwitchTaskList = opTaskManager\n            .getSuccessTaskByType(OpTaskTypeEnum.TEMPLATE_DCDR.getType());\n        if (CollectionUtils.isEmpty(successDcdrSwitchTaskList)) {\n            return TaskResult.buildSuccess();\n        }\n\n        for (OpTask successDcdrSwitchTask : successDcdrSwitchTaskList) {\n            DCDRTasksDetail dcdrTasksDetail = JSON.parseObject(successDcdrSwitchTask.getExpandData(),\n                DCDRTasksDetail.class);\n\n            if (null == dcdrTasksDetail) {\n                continue;\n            }\n\n            List<DCDRSingleTemplateMasterSlaveSwitchDetail> switchDetailList = dcdrTasksDetail\n                .getDcdrSingleTemplateMasterSlaveSwitchDetailList();\n            if (CollectionUtils.isEmpty(switchDetailList)) {\n                continue;\n            }\n\n            for (DCDRSingleTemplateMasterSlaveSwitchDetail switchDetail : switchDetailList) {\n                //强切任务失败，删除脏链路\n                if (DCDRSwithTypeEnum.FORCE.getCode().equals(switchDetail.getSwitchType())\n                    && (switchDetail.getDeleteDcdrChannelFlag() == null || !switchDetail.getDeleteDcdrChannelFlag())) {\n                    try {\n                        Result<Void> deleteDcdrResult = templateDcdrManager.deleteDCDR(\n                            switchDetail.getTemplateId().intValue(), AriusUser.SYSTEM.getDesc(),\n                            AuthConstant.SUPER_PROJECT_ID,true);\n\n                        if (deleteDcdrResult.failed()) {\n                            LOGGER.error(\"class=DeleteDirtyDCDRLinksRandomTask||templateId={}||method=execute||msg={}\",\n                                switchDetail.getTemplateId(), deleteDcdrResult.getMessage());\n                            switchDetail.setDeleteDcdrChannelFlag(false);\n                        } else {\n                            switchDetail.setDeleteDcdrChannelFlag(true);\n                        }\n                    } catch (ESOperateException e) {\n                        LOGGER.error(\n                            \"class=DeleteDirtyDCDRLinksRandomTask||templateId={}||method=execute||msg=failed to delete dcdr channel\",\n                            switchDetail.getTemplateId(), e);\n                        switchDetail.setDeleteDcdrChannelFlag(false);\n                    }\n                }\n            }\n\n            successDcdrSwitchTask.setExpandData(ConvertUtil.obj2Json(dcdrTasksDetail));\n            opTaskManager.updateTask(successDcdrSwitchTask);\n        }\n\n        return TaskResult.buildSuccess();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/srv/DeleteExpireIndexRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.expire.ExpireManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentTemplateTask;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * @author chengxiang\n * @date 2022/5/13\n */\n@Task(name = \"DeleteExpireIndexRandomTask\", description = \"删除过期索引任务\", cron = \"0 55 23 */1 * ?\", autoRegister = true)\npublic class DeleteExpireIndexRandomTask extends BaseConcurrentTemplateTask implements Job {\n    private static final ILog LOGGER = LogFactory.getLog(DeleteExpireIndexRandomTask.class);\n\n    @Autowired\n    private ExpireManager     expireManager;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=DeleteExpireIndexRandomTask||method=execute||msg=DeleteExpireIndexRandomTask start\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n    \n\n    @Override\n    public int poolSize() {\n        return 10;\n    }\n\n    @Override\n    public int current() {\n        return 5;\n    }\n\n    @Override\n    protected boolean executeByLogicTemplate(Integer logicId) {\n        final Result<Void> result = expireManager.deleteExpireIndex(logicId);\n        if (result.failed()){\n            LOGGER.warn(\"class=DeleteExpireIndexRandomTask||method=executeByLogicTemplate||logicId={}||msg={}\", logicId,\n                        result.getMessage());\n        }\n        return result.success();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/srv/IndexRolloverRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.indexplan.IndexPlanManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentTemplateTask;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * @author chengxiang, jiamin\n *\n * rollover能力，目标是保证单个索引的大小在合适的范围内（即索引的主shard数 * 50G），一小时执行一次、或者更频繁的执行\n * 获取主shard个数，只能从ES中获取，不能从数据库表获取\n * 按天滚动的模版：\n *    如果当天索引主shard占用磁盘大小小于主shardCnt*30G，则不进行升级版本\n *    如果当天索引主shard占用磁盘大小大于主shardCnt*50G，则直接升级版本\n *    否则为了应对突发的数据大量递增（一般都是业务方的索引会出现这种情况），如果当天的索引大小超过了过去7天索引大小的最大值\n *    则需要做好预防措施，创建当天新的高版本索引（同时升级该索引对应模版的版本）。\n * 按月滚动的模版：\n *    如果当天索引主shard占用磁盘大小大于主shardCnt*50G，则直接升级版本，其他情况不升级版本\n * 不滚动的模版：\n *    如果当天索引主shard占用磁盘大小大于主shardCnt*50G，则直接升级版本，其他情况不升级版本\n *\n * xxxx-2021-10-22 -> xxxx-2021-10-22_v1\n */\n@Task(name = \"IndexRolloverRandomTask\", description = \"模板Rollover实现\", cron = \"0 0 0/1 * * ?\", autoRegister = true)\npublic class IndexRolloverRandomTask extends BaseConcurrentTemplateTask implements Job {\n\n    private static final ILog LOGGER = LogFactory.getLog(IndexRolloverRandomTask.class);\n\n    @Autowired\n    private IndexPlanManager  indexPlanManager;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=IndexRolloverRandomTask||method=execute||msg=IndexRolloverRandomTask start\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n   \n\n    @Override\n    public int poolSize() {\n        return 10;\n    }\n\n    @Override\n    public int current() {\n        return 5;\n    }\n\n    @Override\n    protected boolean executeByLogicTemplate(Integer logicId) {\n        final Result<Void> result = indexPlanManager.indexRollover(logicId);\n        if (result.failed()){\n             LOGGER.warn(\"class=IndexRolloverRandomTask||method=executeByLogicTemplate||logicId={}||msg={}\", logicId,\n                        result.getMessage());\n             return result.failed();\n        }\n        return result.success();\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/srv/PreCreateIndexRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.precreate.PreCreateManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.common.constant.result.ResultType;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentTemplateTask;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.consensual.ConsensualEnum;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * @author chengxiang\n * @date 2022/5/12\n */\n@Task(name = \"PreCreateIndexRandomTask\", description = \"明天索引预先创建任务，预先创建平台中模板明天索引，避免凌晨大规模创建索引\", cron = \"0 0 03-06 * * ?\", autoRegister = true, consensual = ConsensualEnum.RANDOM)\npublic class PreCreateIndexRandomTask extends BaseConcurrentTemplateTask implements Job {\n\n    private static final ILog LOGGER = LogFactory.getLog(PreCreateIndexRandomTask.class);\n\n    @Autowired\n    private PreCreateManager  preCreateManager;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=PreCreateIndexRandomTask||method=execute||msg=PreCreateIndexRandomTask start\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n    \n\n    @Override\n    public int poolSize() {\n        return 10;\n    }\n\n    @Override\n    public int current() {\n        return 5;\n    }\n\n    @Override\n    protected boolean executeByLogicTemplate(Integer logicId) {\n        try {\n            final Result<Boolean> result = preCreateManager.preCreateIndex(logicId);\n            if (ResultType.FAIL.getCode() == result.getCode()) {\n                LOGGER.warn(\"class=PreCreateIndexRandomTask||method=executeByLogicTemplate||logicId={}||msg={}\", logicId,\n                        result.getMessage());\n            }\n            return result.getCode() == ResultType.SUCCESS.getCode();\n        } catch (Exception e) {\n            LOGGER.error(\"class=PreCreateIndexRandomTask||method=executeByLogicTemplate||logicId={}||msg=预创建失败\", logicId, e);\n        }\n\n        return Boolean.TRUE;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/srv/ShardNumAdjustRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.biz.template.srv.indexplan.IndexPlanManager;\nimport com.didichuxing.datachannel.arius.admin.common.bean.common.Result;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentTemplateTask;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * @author chengxiang, jiamin\n * 每天凌晨3点执行\n * 模版shard动态调整能力，目标是为了调控索引主shard的个数在合适的大小，因为索引创建后就不能改变主shard，所以影响的是后天的创建的索引主shard个数\n * 为什么是后天呢？假如某一时刻索引模版的主shardCnt更变了，但由于索引预创建定时任务是一小时执行一次，所以第二天的索引早就早已被创建，这个时候新的shardCnt只能到后天才能落实到具体的索引中\n * 为了优化这个点，就是想要明天的索引就能使用最新的shardCnt，我们就要删除明天已经被创建出来的索引\n *\n * 按天滚动的模版：\n *    获取所有物理模版，判断是否存在主从（先改主，再改从）\n *    计算物理模版合适的shard个数，获取近七天（今天是10-22，则获取10-15~10-21的索引），某一天的索引可能会有多个版本（则累加汇做一天）\n *    取这近七天，某一天索引占用磁盘容量的最大值，用于计算shard，如果计算出的shard与原来的不一致，则对模版进行修改。\n * 非滚动的模版：\n *    不动态调整shard，首先模版就只对应一个索引（并且再创建该模版的时候，计算主shard的个数为diskQuota/50G）\n * 按月滚动的模版：\n *    不动态调整shard\n */\n@Task(name = \"ShardNumAdjustRandomTask\", description = \"shard规划任务\", cron = \"0 0 3 1/1 * ? *\", autoRegister = true)\npublic class ShardNumAdjustRandomTask extends BaseConcurrentTemplateTask implements Job {\n\n    private static final ILog LOGGER = LogFactory.getLog(ShardNumAdjustRandomTask.class);\n\n    @Autowired\n    private IndexPlanManager  indexPlanManager;\n\n    @Override\n    public TaskResult execute(JobContext jobContext) throws Exception {\n        LOGGER.info(\"class=ShardNumAdjustRandomTask||method=execute||msg=ShardNumAdjustRandomTask start\");\n        if (execute()) {\n            return TaskResult.buildSuccess();\n        }\n        return TaskResult.buildFail();\n    }\n\n    \n\n    @Override\n    public int poolSize() {\n        return 10;\n    }\n\n    @Override\n    public int current() {\n        return 5;\n    }\n    \n    @Override\n    protected boolean executeByLogicTemplate(Integer logicId) {\n        try {\n            final Result<Boolean> result = indexPlanManager.adjustShardNum(logicId);\n            if (Boolean.FALSE.equals(result.getData())) {\n                LOGGER.warn(\"class=ShardNumAdjustRandomTask||method=executeByLogicTemplate||logicId={}||msg={}\", logicId,\n                        result.getMessage());\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"class=ShardNumAdjustRandomTask||method=executeByLogicTemplate||logicId={}||msg=shard规划任务\", logicId,\n                    e);\n        }\n        \n        return Boolean.TRUE;\n    }\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/main/java/com/didichuxing/datachannel/arius/admin/task/template/srv/TemplateLogicHealthLogRandomTask.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.template.srv;\n\nimport com.didichuxing.datachannel.arius.admin.common.exception.AdminOperateException;\nimport com.didichuxing.datachannel.arius.admin.task.BaseConcurrentTemplateTask;\nimport com.didiglobal.knowframework.job.annotation.Task;\nimport com.didiglobal.knowframework.job.common.TaskResult;\nimport com.didiglobal.knowframework.job.core.job.Job;\nimport com.didiglobal.knowframework.job.core.job.JobContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\n/**\n * 健康随机任务 这是一个每 5 分钟运行一次的任务，名为 HealthRandomTask。\n *\n * @author shizeying\n * @date 2022/08/16\n */\n@Task(name = \"TemplateLogicHealthLogRandomTask\", description = \"逻辑模板健康率同步任务\", cron = \"0 0/5 * * * ? *\", autoRegister =\n\t\ttrue)\npublic class TemplateLogicHealthLogRandomTask extends BaseConcurrentTemplateTask implements Job {\n\tprivate static final ILog LOGGER = LogFactory.getLog(ColdDataMoveRandomTask.class);\n\t\n\t@Override\n\tpublic TaskResult execute(JobContext jobContext) throws Exception {\n\t\tLOGGER.info(\"class={}||method=execute||msg=HealthRandomTask start\",getClass().getSimpleName());\n\t\tif (execute()) {\n\t\t\treturn TaskResult.buildSuccess();\n\t\t}\n\t\treturn TaskResult.buildFail();\n\t}\n\t\n\n\t@Override\n\tprotected boolean executeByLogicTemplate(Integer logicId) throws AdminOperateException {\n\t\treturn templateLogicManager.updateTemplateHealthByLogicId(logicId);\n\t}\n\t\n\t/**\n\t * 任务的线程个数\n\t *\n\t * @return\n\t */\n\t@Override\n\tpublic int poolSize() {\n\t\treturn 10;\n\t}\n\t\n\t/**\n\t * 并发度\n\t *\n\t * @return\n\t */\n\t@Override\n\tpublic int current() {\n\t\treturn 5;\n\t}\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/test/java/com/didichuxing/datachannel/arius/admin/task/config/AriusAdminTaskConfiguration.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.config;\n\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.PropertySource;\n\n/**\n * @author zhangliang\n * @version : AriusAdminTaskConfiguration.java, v 0.1 2022年03月23日 15:48 zhangliang Exp $\n */\n@Configuration\n@ComponentScan(basePackages = { \"com.didichuxing.datachannel.arius.admin.task\",\n                                \"com.didichuxing.datachannel.arius.admin.persistence\",\n                                \"com.didichuxing.datachannel.arius.admin.client\",\n                                \"com.didichuxing.datachannel.arius.admin.common\",\n                                \"com.didichuxing.datachannel.arius.admin.core\",\n                                \"com.didichuxing.datachannel.arius.admin.metadata\",\n                                \"com.didichuxing.datachannel.arius.admin.extend\",\n                                \"com.didichuxing.datachannel.arius.admin.biz\",\n                                \"com.didichuxing.datachannel.arius.admin.remote\" })\n@PropertySource(\"classpath:application.properties\")\n@EnableAutoConfiguration\npublic class AriusAdminTaskConfiguration {\n}"
  },
  {
    "path": "arius-admin/arius-admin-task/src/test/java/com/didichuxing/datachannel/arius/admin/task/dashboard/IndexDashBoardCollectorTest.java",
    "content": "package com.didichuxing.datachannel.arius.admin.task.dashboard;\n\nimport com.didichuxing.datachannel.arius.admin.task.config.AriusAdminTaskConfiguration;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n/**\n * @author zhangliang\n * @version : IndexDashBoardCollectorTest.java, v 0.1 2022年03月18日 18:27 zhangliang Exp $\n */\n@RunWith(SpringRunner.class)\n@ContextConfiguration(classes = { AriusAdminTaskConfiguration.class })\npublic class IndexDashBoardCollectorTest {\n\n    private static final ILog LOGGER = LogFactory.getLog(IndexDashBoardCollectorTest.class);\n\n    @Autowired\n    ApplicationContext        wac;\n\n    @Test\n    public void testBuildBySingleCluster() {\n    }\n\n}\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/test/resources/application.properties",
    "content": "admin.thread.size.op=20\nspring.logi-job.jdbc-url=jdbc:mariadb://10.179.222.237:4859/es_manager_test?useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=true&allowMultiQueries=true&useSSL=false&alwaysAutoGeneratedKeys=true&serverTimezone=GMT%2B8\nspring.logi-job.username=didi_cCHn\nspring.logi-job.password=KEA9kEPR4\nspring.logi-job.driver-class-name=org.mariadb.jdbc.Driver\nspring.logi-job.max-lifetime=60000\nspring.logi-job.init-sql=true\nspring.logi-job.init-thread-num=50\nspring.logi-job.max-thread-num=100\nspring.logi-job.log-exipre=3 # 日志保存天数，以天为单位\nspring.logi-job.app_name=arius_test1234\nspring.logi-job.claim-strategy=com.didiglobal.logi.job.core.consensual.RandomConsensual\nspring.datasource.name=data\nspring.datasource.type=com.alibaba.druid.pool.DruidDataSource\nspring.datasource.druid.driver-class-name=org.mariadb.jdbc.Driver\nspring.datasource.druid.url=jdbc:mariadb://10.179.222.237:4859/es_manager_test?useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=true&allowMultiQueries=true&useSSL=false&alwaysAutoGeneratedKeys=true&serverTimezone=GMT%2B8\nspring.datasource.druid.username=didi_cCHn\nspring.datasource.druid.password=KEA9kEPR4\nspring.datasource.druid.initialSize=10\nspring.datasource.druid.validationQueryTimeout=5000\nspring.datasource.druid.transactionQueryTimeout=60000\nspring.datasource.druid.minIdle=10\nspring.datasource.druid.maxActive=30\nspring.datasource.druid.max-wait=60000\nspring.datasource.druid.keepAlive=true\nspring.datasource.druid.time-between-eviction-runs-millis=1000\nspring.datasource.druid.min-evictable-idle-time-millis=300000\nspring.datasource.druid.defaultAutoCommit=true\nspring.datasource.druid.validationQuery=select 'x'\nspring.datasource.druid.testWhileIdle=true\nspring.datasource.druid.testOnReturn=false\nspring.datasource.druid.testOnBorrow=true\nspring.datasource.druid.logAbandoned=true\nspring.datasource.druid.pool-prepared-statements=true\nspring.datasource.druid.max-open-prepared-statements=50\nspring.datasource.druid.filters=stat,wall\nes.update.cluster.name=logi-elasticsearch-7.6.0\nes.client.cluster.port=8061\nes.client.io.thread.count=2\n########################### 索引名称相关配置 begin ###########################\n# 索引名称的配置只需要配置名称，不需要配置数中心前缀\n# DataCentreUtil会根据单元化部署的数据中心给索引加上数据中心前缀\narius.template.qutoa.notiry.record=arius_template_qutoa_notiry_record\narius.template.quota.usage=arius_template_quota_usage\narius.template.record.quota.usage=record_arius_template_quota_usage\narius.template.capacity.plan.region.statis=arius_capacity_plan_region_statis\nes.dsl.analyze.index.name=arius.dsl.analyze.result\nes.dsl.metrics.index.name=arius.dsl.metrics\narius.gateway.join.name=arius.gateway.join\nes.dsl.template.index.name=arius.dsl.template\nes.template.field.index.name=arius.template.field\nes.dsl.field.use.index.name=arius.dsl.field.use\nes.template.mapping.index.name=arius.template.mapping\nes.index.size.index.name=arius.index.size\nes.template.hit.index.name=arius.template.hit\n# 国内原始gateway日志索引\narius.gateway.original.log.index.name=foundation_fd.data-online.arius.gateway\n# appid维度访问次数索引\nes.projectId.template.access.index.name=arius.appid.template.access\n# 索引维度访问次数索引\nes.indexname.access.index.name=arius.indexname.access\n# 索引模板维度访问次数索引\nes.template.access.index.name=arius.template.access\n# gateway 访问统计索引\nes.gateway.info.index.name=arius.gateway.join\n# 不同维度的es监控数据索引\nes.node_index.info.index.name=arius_stats_node_index_info\nes.node.info.index.name=arius_stats_node_info\nes.dashboard.info.name=arius_stats_dashboard_info\nes.index.info.index.name=arius_stats_index_info\nes.index.cat.info=arius_cat_index_info\nes.cluster.info.index.name=arius_stats_cluster_info\nes.index_node.info.index.name=arius_stats_index_node_info\nes.ingest.info.index.name=arius_stats_ingest_info\nes.dcdr.info.index.name=arius_stats_dcdr_info\n# es 索引标签数据\nes.template.label.index.name=v2.arius.template.label\n# es 索引健康分\nes.template.health.degree.index.name=arius.template.health.degree\n# es 索引价值\nes.template.value.index.name=arius.template.value\nes.template.value.record.index.name=record.arius.template.value\n########################### 索引名称相关配置 end ###########################\n########################### 索引统计相关配置 begin ###########################\n# 全平台集群数量统计指标中上限\nes.metrics.cluster.buckets.max.num=2000\n# 单集群获取统计指标中节点数量上限\nes.metrics.nodes.buckets.max.num=1000\n# 单集群获取统计指标中索引数量上限\nes.metrics.indices.buckets.max.num=10000\n########################### 索引统计相关配置 end ###########################\n# gateway相关配置\nes.gateway.url=10.190.34.104\n# gateway server http port\nes.gateway.port=8200\nes.user=1\nes.password=azAWiJhxkho33ac\nscroll.timeout=60s\nextend.service=\nextend.fileStorage=s3\nextend.employee=defaultEmployee\nextend.loginProtocol=defaultLogin\ndefault.query.limit=800\ndelay.delete.expired.template.time=now-1d\nhistory.query.time=now-93d\nrecent.create.field.day.count=7\nmonitor.n9e.url=http://10.86.76.13:8085/api/n9e  #夜莺监控mock地址\nmonitor.n9e.collector-url=http://10.86.76.13:8085/v1/n9e #夜莺监控上报地址\nmonitor.odin.enable=true\nmonitor.odin.tree.url=http://tree.odin.intra.xiaojukeji.com\nmonitor.odin.monitor.url=http://monitor.odin.xiaojukeji.com\nmonitor.odin.collector=url: http://collect.odin.xiaojukeji.com\nmonitor.odin.namespace=kafka-manager-custom.kafka-manager.YS01.Bigdata-Kafka-Cloud.bigdata-infra.didi.com\nmonitor.odin.securename=sys.kafka-manager\nmonitor.odin.securekey=5fBbD6p84Oe7UT4qrttEBiwaR77S63do\ncloud.default.server=http://ddcloud.xiaojukeji.com/kube/api/v2\ncloud.default.token=e9bbe810d7567dc28e9240cf4b14d869\ncloud.us01.server=http://us.ddcloud.xiaojukeji.com/kube/api/v2\ncloud.us01.token=8b1232c1ce661b7ea424987b50934bf5\ncloud.basic.admins=zhuyefeng,dingshilei,xiaosonglin\ncloud.basic.permServer=http://perm.odin.intra.xiaojukeji.com\ncloud.basic.treeServer=http://tree.odin.intra.xiaojukeji.com\ncloud.basic.maxRollbackCnt=20\ncloud.basic.selfServer=http://10.168.116.116:8081\ncloud.basic.cluster.default=pluginIds: 6,8,10,12,14,16,18,20,22,24\ncert.disable=false\ncert.server=http://cert.odin.intra.xiaojukeji.com\ncert.calleeName=sys.data_commercializ\ncert.keyName=Nnl8x7liPMar1rYsJL9p9f4p8U7Nz6lc\nzeus.server=http://10.96.65.64:8010\nzeus.token=9e2dbb6e5b1e594d1820e0f21669b240\nzeus.templateId=3\nzeus.user=root\nzeus.batch=2\nzeus.timeOut=300\nzeus.tolerance=0\nfs.minio.endpoint=http://10.90.27.13:8095\nfs.minio.accessKeyID=AKDD000000000017NLIIDATA33GNAZ\nfs.minio.secretAccessKey:=\nfs.minio.bucket=datamarket\nfs.gift.upload-url=http://10.14.128.20:8000/resource/\nfs.gift.download-url=http://10.14.128.20:8002/static/\nfs.gift.namespace=bigdata_kafka\ns3.endpoint=s3-gzpu-inter.didistatic.com\ns3.access-key=\ns3.secret-key=\ns3.bucket=logi-data-es\nadmin.url.console=http://10.190.6.107/\nadmin.url.kibana=http://10.160.80.135:8061/\nadmin.thread.size=\nadmin.thread.op=20\n#健康检查\nhealth.check.empty.indices.threshold.day=30\nhealth.check.index.doc.averge.size=2048\nhealth.check.index.doc.result.level=5,10,15,20,25\nhealth.check.index.mapping.large.size=5000\nhealth.check.index.mapping.result.level=5,10,15,20,25\nhealth.check.small.shard.size=60\nhealth.check.small.shard.result.level=5,10,15,20,25\nhealth.check.small.shard.repair=false\n"
  },
  {
    "path": "arius-admin/arius-admin-task/src/test/resources/log4j2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- status=\"OFF\"，可以去掉，它的含义为是否记录log4j2本身的event信息，默认是OFF -->\n<configuration status=\"debug\" monitorInterval=\"30\">\n    <!-- 定义下面的引用名 -->\n    <Properties>\n        <Property name=\"PID\">????</Property>\n        <Property name=\"LOG_EXCEPTION_CONVERSION_WORD\">%xwEx</Property>\n        <Property name=\"LOG_LEVEL_PATTERN\">%5p</Property>\n        <Property name=\"LOG_DATEFORMAT_PATTERN\">yyyy-MM-dd HH:mm:ss.SSS</Property>\n        <Property name=\"CONSOLE_LOG_PATTERN\">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}}\n            %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint}\n            %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}\n        </Property>\n        <Property name=\"log_pattern\">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.}\n            : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}\n        </Property>\n        <!-- name的值是变量的名称，value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后，可以使\"${}\"来使用变量。 -->\n        <property name=\"log.path\">./logs/</property>\n    </Properties>\n    <!--先定义所有的appender -->\n    <appenders>\n\n        <RollingFile name=\"logiJobLogger\"\n                     filename=\"${log.path}/logiJob.log\" filePattern=\"${log.path}/logiJob.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n\n            <DefaultRolloverStrategy max=\"1\">\n                <!-- 配置日志滚动删除策略 IfLastModified 的单位需要配合 filePattern中的规则使用 -->\n                <Delete basePath=\"${log.path}\" maxDepth=\"1\">\n                    <IfFileName glob=\"*.log.*\"/>\n                    <IfLastModified age=\"3d\"/>\n                </Delete>\n            </DefaultRolloverStrategy>\n        </RollingFile>\n\n        <RollingFile name=\"accessLogger\"\n                     filename=\"${log.path}/access.log\" filePattern=\"${log.path}/access.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n\n        <RollingFile name=\"responseLogger\"\n                     filename=\"${log.path}/response.log\" filePattern=\"${log.path}/response.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n        <RollingFile name=\"thirdReqLogger\"\n                     filename=\"${log.path}/thirdReq.log\" filePattern=\"${log.path}/thirdReq.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n\n        <RollingFile name=\"thirdRespLogger\"\n                     filename=\"${log.path}/thirdResp.log\" filePattern=\"${log.path}/thirdResp.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n        <RollingFile name=\"systemLog\"\n                     filename=\"${log.path}/system.log\" filePattern=\"${log.path}/system.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Filters>\n                <!-- 只要level及其以上级别的信息（onMatch），其他的直接拒绝（onMismatch）-->\n                <ThresholdFilter level=\"INFO\" onMatch=\"ACCEPT\" onMismatch=\"DENY\"/>\n            </Filters>\n\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"3\"/>\n        </RollingFile>\n\n        <RollingFile name=\"errorLog\"\n                     filename=\"${log.path}/error.log\" filePattern=\"${log.path}/error.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Filters>\n                <!-- 只要level及其以上级别的信息（onMatch），其他的直接拒绝（onMismatch）-->\n                <ThresholdFilter level=\"ERROR\" onMatch=\"ACCEPT\" onMismatch=\"DENY\"/>\n            </Filters>\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n\n        <RollingFile name=\"threadLog\"\n                     filename=\"${log.path}/thread.log\" filePattern=\"${log.path}/thread.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n        <RollingFile name=\"sqlLog\"\n                     filename=\"${log.path}/sql.log\" filePattern=\"${log.path}/sql.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <!--输出日志的格式 -->\n            <PatternLayout pattern=\"${log_pattern}\"/>\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\"/>\n            </Policies>\n            <DefaultRolloverStrategy max=\"3\"/>\n        </RollingFile>\n\n    </appenders>\n    <!-- 非开发环境只需要打印到文件就行 -->\n    <loggers>\n\n        <AsyncRoot level=\"DEBUG\" includeLocation=\"true\">\n            <AppenderRef ref=\"systemLog\"/>\n            <AppenderRef ref=\"errorLog\"/>\n        </AsyncRoot>\n\n        <!-- http请求请求日志记录  -->\n        <AsyncLogger name=\"accessLogger\" level=\"INFO\" additivity=\"false\">\n            <appender-ref ref=\"accessLogger\"/>\n        </AsyncLogger>\n\n        <!-- http请求响应日志记录  -->\n        <AsyncLogger name=\"responseLogger\" level=\"INFO\" additivity=\"false\">\n            <appender-ref ref=\"responseLogger\"/>\n        </AsyncLogger>\n\n        <!-- admin 与第三方服务交互请求日志记录 RestTool  -->\n        <AsyncLogger name=\"thirdRespLogger\" level=\"INFO\" additivity=\"false\">\n            <appender-ref ref=\"thirdRespLogger\"/>\n        </AsyncLogger>\n\n        <!-- admin 与第三方服务交互响应日志记录 RestTool  -->\n        <AsyncLogger name=\"thirdReqLogger\" level=\"INFO\" additivity=\"false\">\n            <appender-ref ref=\"thirdReqLogger\"/>\n        </AsyncLogger>\n\n        <!-- admin 线程池日志记录 -->\n        <AsyncLogger name=\"com.didichuxing.datachannel.arius.admin.common.threadpool\" level=\"WARN\" additivity=\"false\">\n            <appender-ref ref=\"threadLog\"/>\n        </AsyncLogger>\n\n        <!-- admin FutureUtil工具日志记录 -->\n        <AsyncLogger name=\"com.didichuxing.datachannel.arius.admin.common.util.FutureUtil\" level=\"WARN\"\n                     additivity=\"false\">\n            <appender-ref ref=\"threadLog\"/>\n        </AsyncLogger>\n\n        <!-- logi job 日子记录 -->\n        <AsyncLogger name=\"com.didiglobal.logi.job\" level=\"DEBUG\" additivity=\"false\">\n            <appender-ref ref=\"logiJobLogger\"/>\n        </AsyncLogger>\n\n        <!-- 记录sql -->\n        <AsyncLogger name=\"com.didichuxing.datachannel.arius.admin.persistence.mysql\" level=\"debug\" additivity=\"true\">\n            <appender-ref ref=\"sqlLog\" level=\"debug\"/>\n        </AsyncLogger>\n\n    </loggers>\n</configuration>"
  },
  {
    "path": "arius-admin/build.sh",
    "content": "#!/bin/bash\nworkspace=$(cd $(dirname $0) && pwd -P)/arius-admin-rest\ncd $workspace\n\nmodule=arius-admin-rest\napp=$module\n\n# OE不再支持直接传递参数，使用环境变量\n# env=$1\nif [[ $# -ne 0 ]];then\n  env=$1\nfi\n\necho \"env is $env\"\n\ngitversion=.gitversion\ncontrol=./control.sh\nngxfunc=./nginxfunc.sh\n\n## function\nfunction build() {\n    # 进行编译\n    # cmd\n    JVERSION=`java -version 2>&1 | awk 'NR==1{gsub(/\"/,\"\");print $3}'`\n    major=`echo $JVERSION | awk -F. '{print $1}'`\n    mijor=`echo $JVERSION | awk -F. '{print $2}'`\n    if [ $major -le 1 ] && [ $mijor -lt 8 ]; then\n        export JAVA_HOME=/usr/local/jdk1.8.0_65  #(使用jdk8请设置)\n        export PATH=$JAVA_HOME/bin:$PATH\n    fi\n    # XXX 编译命令\n    cd ..\n    mvn -U clean package -Dmaven.test.skip=true\n    mvn clean test org.jacoco:jacoco-maven-plugin:0.8.3:prepare-agent install -Dmaven.test.failure.ignore=true\n\n    local sc=$?\n    if [ $sc -ne 0 ];then\n    \t## 编译失败, 退出码为 非0\n        echo \"$app build error\"\n        exit $sc\n    else\n        echo -n \"$app build ok, vsn=\"\n        gitversion\n    fi\n\n     cd $module\n}\n\nfunction make_output() {\n\t# 新建output目录\n\tlocal output=\"./output\"\n\trm -rf $output &>/dev/null\n\tmkdir -p $output &>/dev/null\n\n\t# 填充output目录, output内的内容 即为 线上部署内容\n\t(\n        cp -rf $control $output &&         # 拷贝 control.sh脚本 至output目录\n        cp -rf $ngxfunc $output &&\n        cp -rf ./APP_META $output &&\n        cp -rf ./APP_META/Dockerfile $output &&\n        mkdir $output/nginx && cp -rf ./APP_META/nginx/conf $output/nginx &&\n        mkdir $output/代码行统计 && cp -rf ./src/test/java/com/didichuxing/datachannel/arius/admin/statMethodLine.txt $output/代码行统计 &&\n        mkdir $output/测试覆盖率报告 && mv target/site/jacoco-aggregate output/测试覆盖率报告 &&\n        mv target/${module}.jar output  #拷贝目标war包或者jar包等 至output目录下\n        echo -e \"make output ok.\"\n\t) || { echo -e \"make output error\"; exit 2; } # 填充output目录失败后, 退出码为 非0\n\n        (\n            if [[ \"x$env\" == \"xtest\" || \"x$env\" == \"xpressure\" || \"x$env\" == \"xstable\" ]];then\n            cp -rf ./APP_META/DockerfileOffline $output/Dockerfile\n        fi\n        ) || { echo -e \"make offline output error\"; exit 2; } # 填充output目录失败后, 退出码为 非0\n\n        mv output  ../\n}\n\n## internals\nfunction gitversion() {\n    git log -1 --pretty=%h > $gitversion\n    local gv=`cat $gitversion`\n    echo \"$gv\"\n}\n\n\n##########################################\n## main\n## 其中,\n## \t\t1.进行编译\n##\t\t2.生成部署包output\n##########################################\n\n# 1.进行编译\nbuild\n\n# 2.生成部署包output\nmake_output\n\n# 编译成功\necho -e \"build done\"\nexit 0\n"
  },
  {
    "path": "arius-admin/coverage-report.sh",
    "content": "#!/bin/bash\n\nset -x\n\nps -ef | egrep arius-admin-rest\\|stop-server.sh\\|sleep | grep -v grep | awk '{print $2}'  |xargs kill -9\nexport USER=root\n\nrm -r output/arius-admin-rest/coverage-reports/\nrm output/arius-admin-rest/arius-admin.log\nrm report.tar.gz\n\nnohup java -javaagent:/lib/java-1.8.0/jacocoagent.jar='output=file,destfile=output/arius-admin-rest/coverage-reports/jacoco.exec,excludes=*bean*:*thirdpart*:*notify*:*task*' -jar output/arius-admin-rest/arius-admin-rest.jar --spring.profiles.active=integration >output/arius-admin-rest/arius-admin.log 2>&1 &\nsleep 100\n\nbash -c ./stop-server.sh &\ndate\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/Readme.md",
    "content": "# `kndowersearch 0.3.1`升级方案\n1. 导入权限和项目的sql\n2. 配置`cluster-phy-join.json`中\n   1. 其中`clusterRegionDTOS`中需要根据有几个ip和port进行进行对应的匹配\n   2. 其中`cluster`需要和脚本中的几个`cluster`名称相同，最好不要改\n3. 配置`init_knowersearch.sh`\n   1. 其中`url_prefix`是需要配置的，这个是部署之后请求的`admin`的地址\n   2. 其余的默认就可以了"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/cluster-phy-join",
    "content": "{\n  \"type\": 4,\n  \"resourceType\": 2,\n  \"dataCenter\": \"\",\n  \"platformType\": \"\",\n  \"tags\": \"{\\\"createSource\\\":0}\",\n  \"importRule\": \"0\",\n  \"projectId\": 1,\n  \"cluster\": \"logi-elasticsearch-meta\",\n  \"divide\": true,\n  \"phyClusterDesc\": \"\",\n  \"roleClusterHosts\": [\n    {\n      \"cluster\": \"logi-elasticsearch-meta\",\n      \"id\": 0,\n      \"ip\": \"这里填ip\",\n      \"nodeSet\": \"\",\n      \"port\": \"这里填端口号\",\n      \"role\": 3,\n      \"roleClusterId\": 0,\n      \"status\": 0\n    }\n  ],\n  \"password\": \"elastic:123456\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/init_knowsearch_linux.sh",
    "content": "#!/bin/bash\n#需要变更一些地址\nurl_prefix='http://127.0.0.1:8015/admin/api'\n#元数据项目，默认不变\nsubject=2\n#接入物理集群并创建逻辑集群的接口\nput_cluster_url='/v3/thirdpart/common/cluster/join-with-logic'\nheader=\"-H  'X-SSO-USER: admin'  -H 'X-LOGI-SECURITY-PROJECT-ID: 1'  -H 'X-SSO-USER-ID: 1593'  -H 'Content-Type:application/json' \"\nheader_subject=\"-H  'X-SSO-USER: admin'  -H 'X-LOGI-SECURITY-PROJECT-ID: $subject'  -H 'X-SSO-USER-ID: 1593'  -H 'Content-Type:application/json' \"\n#逻辑集群id\nlogic_cluster_id=0\njoin_cluster(){\n data_path=`dirname $0`\n url=$url_prefix$put_cluster_url\n data=`cat $data_path/cluster-phy-join`\n join_cluster=\"curl -s $header  -XPOST $url -d '$data'\"\n response=`eval $join_cluster`\n echo \"response $response\"\n logic_cluster_id=`echo $response | awk -F 'data\":' '{print $NF}'|awk -F \",\" '{print $1}'`\n echo \"logic_cluster_id $logic_cluster_id\"\n}\n\n\n\ncreate_logic_template(){\n  num_exec='echo \"$logic_cluster_id\" | sed -n \"/^[0-9]\\+$/p\" '\n  num=`eval $num_exec` \n  if [ ! -n \"$num\" ]; then\n        echo '逻辑集群id未获取到'\n        exit\n  fi\n  \n  echo $logic_cluster_id\n  data_path=`dirname $0`\n  for i in `ls $data_path/template_in_arius/*`\n  do\n    create_logic_template_exec=\"cat $i| sed 's/#resourceId/$logic_cluster_id/g'\"\n    create_logic_template_data=`eval eval $create_logic_template_exec`\n    url=$url_prefix/v3/template/logic\n    create_logic_template_exec=\"curl -s  $header_subject  -XPOST $url -d '$create_logic_template_data'\"\n    result=`eval $create_logic_template_exec`\n    echo \"Create template results : $result ....\"\n  done\n}\nurl_status=$(curl -s -m 5 -IL $url_prefix/health  |grep 200)\nif [\"$url_status\" == \"\"];then\n\techo \"服务异常，无法执行脚本\"\nfi\n#接入物理集群\njoin_cluster\n\n\n\n\n#创建元数据模版\ncreate_logic_template"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/initializeSql.sql",
    "content": "#项目、用户、权限点\n-- auto-generated definition\ncreate table logi_security_config\n(\n    id          bigint unsigned auto_increment comment '主键自增'\n        primary key,\n    value_group varchar(100)  default ''                not null comment ' 配置项组 ',\n    value_name  varchar(100)  default ''                not null comment ' 配置项名字 ',\n    value       text                                    null comment '配置项的值',\n    edit        int(4)        default 1                 not null comment '是否可以编辑 1 不可编辑（程序获取） 2 可编辑',\n    status      int(4)        default 1                 not null comment '1 正常 2 禁用',\n    memo        varchar(1000) default ''                not null comment ' 备注 ',\n    create_time timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间',\n    is_delete   tinyint(1)    default 0                 not null comment '逻辑删除',\n    app_name    varchar(16) collate utf8_bin            null comment '应用名称',\n    operator    varchar(16) collate utf8_bin            null comment '操作者'\n)\n    comment 'logi 配置项' charset = utf8;\n\ncreate index idx_group_name\n    on logi_security_config (value_group, value_name);\n\n-- auto-generated definition\ncreate table logi_security_dept\n(\n    id          int auto_increment\n        primary key,\n    dept_name   varchar(10)                          not null comment '部门名',\n    parent_id   int                                  not null comment '父部门 id',\n    leaf        tinyint(1)                           not null comment '是否叶子部门',\n    level       tinyint                              not null comment 'parentId 为 0 的层级为 1',\n    description varchar(20)                          null comment '描述',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '部门信息表' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_message\n(\n    id          int auto_increment\n        primary key,\n    title       varchar(60)                          not null comment '标题',\n    content     varchar(256)                         null comment '内容',\n    read_tag    tinyint(1) default 0                 null comment '是否已读',\n    oplog_id    int                                  null comment '操作日志 id',\n    user_id     int                                  null comment '这条消息属于哪个用户的，用户 id',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '消息中心' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_oplog\n(\n    id                int auto_increment\n        primary key,\n    operator_ip       varchar(20)                            not null comment '操作者 ip',\n    operator          varchar(20)                            null comment '操作者账号',\n    operate_page      varchar(16)                            null comment '操作页面',\n    operate_type      varchar(16)                            not null comment '操作类型',\n    target_type       varchar(16)                            not null comment '对象分类',\n    target            varchar(20)                            not null comment '操作对象',\n    detail            text                                   null comment '日志详情',\n    create_time       timestamp    default CURRENT_TIMESTAMP null,\n    update_time       timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete         tinyint(1)   default 0                 not null comment '逻辑删除',\n    app_name          varchar(16)                            null comment '应用名称',\n    operation_methods varchar(255) default ''                null\n)\n    comment '操作日志' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_oplog_extra\n(\n    id          int auto_increment\n        primary key,\n    info        varchar(16)                          null comment '信息',\n    type        tinyint                              not null comment '哪种信息：1：操作页面;2：操作类型;3：对象分类',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '操作日志信息（操作页面、操作类型、对象分类）' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_permission\n(\n    id              int auto_increment\n        primary key,\n    permission_name varchar(40)                          not null comment '权限名字',\n    parent_id       int                                  not null comment '父权限 id',\n    leaf            tinyint(1)                           not null comment '是否叶子权限点（具体的操作）',\n    level           tinyint                              not null comment '权限点的层级（parentId 为 0 的层级为 1）',\n    description     varchar(64)                          null comment '权限点描述',\n    create_time     timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time     timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete       tinyint(1) default 0                 null comment '逻辑删除',\n    app_name        varchar(16)                          null comment '应用名称'\n)\n    comment '权限表' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_project\n(\n    id           int auto_increment comment '项目 id'\n        primary key,\n    project_code varchar(128)                           not null comment '项目编号',\n    project_name varchar(128)                           not null comment '项目名',\n    description  varchar(512) default ''                not null comment ' 项目描述 ',\n    dept_id      int                                    not null comment '部门 id',\n    running      tinyint(1)   default 1                 not null comment '启用 or 停用',\n    create_time  timestamp    default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time  timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete    tinyint(1)   default 0                 not null comment '逻辑删除',\n    app_name     varchar(16)                            null comment '应用名称'\n)\n    comment '项目表' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_resource_type\n(\n    id          int auto_increment\n        primary key,\n    type_name   varchar(16)                          null comment '资源类型名',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '资源类型表' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_role\n(\n    id           int auto_increment\n        primary key,\n    role_code    varchar(128)                         not null comment '角色编号',\n    role_name    varchar(128)                         not null comment '名称',\n    description  varchar(128)                         null comment '角色描述',\n    last_reviser varchar(30)                          null comment '最后修改人',\n    create_time  timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time  timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete    tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name     varchar(16)                          null comment '应用名称'\n)\n    comment '角色信息' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_role_permission\n(\n    id            int auto_increment\n        primary key,\n    role_id       int                                  not null comment '角色 id',\n    permission_id int                                  not null comment '权限 id',\n    create_time   timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time   timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete     tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name      varchar(16)                          null comment '应用名称'\n)\n    comment '角色权限表（只保留叶子权限与角色关系）' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_user\n(\n    id          int auto_increment\n        primary key,\n    user_name   varchar(64)                            not null comment '用户账号',\n    pw          varchar(2048)                          not null comment '用户密码',\n    salt        char(5)      default ''                not null comment ' 密码盐 ',\n    real_name   varchar(128) default ''                not null comment ' 真实姓名 ',\n    phone       char(11)     default ''                not null comment 'mobile',\n    email       varchar(30)  default ''                not null comment 'email',\n    dept_id     int                                    null comment '所属部门 id',\n    is_delete   tinyint(1)   default 0                 not null comment '逻辑删除',\n    create_time timestamp    default CURRENT_TIMESTAMP null comment '注册时间',\n    update_time timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    app_name    varchar(16)                            null comment '应用名称'\n)\n    comment '用户信息' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_user_project\n(\n    id          int auto_increment\n        primary key,\n    user_id     int                                   not null comment '用户 id',\n    project_id  int                                   not null comment '项目 id',\n    create_time timestamp   default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp   default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1)  default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                           null comment '应用名称',\n    user_type   tinyint(10) default 0                 not null comment '用户类型：0：普通项目用户；1：项目 owner'\n)\n    comment '用户项目关系表（项目负责人）' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_user_resource\n(\n    id               int auto_increment\n        primary key,\n    user_id          int                                  not null comment '用户 id',\n    project_id       int                                  not null comment '资源所属项目 id',\n    resource_type_id int                                  not null comment '资源类别 id',\n    resource_id      int                                  not null comment '资源 id',\n    control_level    tinyint                              not null comment '管理级别：1（查看权限）2（管理权限）',\n    create_time      timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time      timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete        tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name         varchar(16)                          null comment '应用名称'\n)\n    comment '用户和资源关系表' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_user_role\n(\n    id          int auto_increment\n        primary key,\n    user_id     int                                  not null comment '用户 id',\n    role_id     int                                  not null comment '角色 id',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '用户角色表' charset = utf8;\n\n-- auto-generated definition\ncreate table arius_es_user\n(\n    id                 bigint(10) unsigned auto_increment comment '主键 自增'\n        primary key,\n    index_exp          text                                    null comment '索引表达式',\n    data_center        varchar(20)   default ''                not null comment ' 数据中心 ',\n    is_root            tinyint       default 0                 not null comment '是都是超级用户 超级用户具有所有索引的访问权限 0 不是 1 是',\n    memo               varchar(1000) default ''                not null comment ' 备注 ',\n    ip                 varchar(500)  default ''                not null comment ' 白名单 ip 地址 ',\n    verify_code        varchar(50)   default ''                not null comment 'app 验证码 ',\n    is_active          tinyint(2)    default 1                 not null comment '1 为可用，0 不可用',\n    query_threshold    int(10)       default 100               not null comment '限流值',\n    cluster            varchar(100)  default ''                not null comment ' 查询集群 ',\n    responsible        varchar(500)  default ''                null comment ' 责任人 ',\n    search_type        tinyint       default 0                 not null comment '0 表示 app 的查询请求需要 app 里配置的集群 (一般配置的都是 trib 集群) 1 表示 app 的查询请求必须只能访问一个模板 2 表示集群模式（可支持多模板查询）',\n    create_time        timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time        timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间',\n    project_id         bigint(10)                              not null comment '项目 id',\n    is_default_display tinyint(2)    default 0                 not null comment '1：项目默认的 es user；0: 项目新增的 es user'\n)\n    comment 'es 操作用户表' charset = utf8;\ncreate table project_arius_config\n(\n    project_id              bigint(10) unsigned auto_increment comment 'project id'\n        primary key,\n    analyze_response_enable tinyint       default 1                 not null comment '响应结果解析开关 默认是 0：关闭，1：开启',\n    is_source_separated     tinyint       default 0                 not null comment '是否是索引存储分离的 0 不是 1 是',\n    aggr_analyze_enable     tinyint       default 1                 not null comment '1 生效 0 不生效',\n    dsl_analyze_enable      tinyint(2)    default 1                 not null comment '1 为生效 dsl 分析查询限流值，0 不生效 dsl 分析查询限流值',\n    slow_query_times        int(10)       default 100               not null comment '慢查询耗时',\n    is_active               tinyint(2)    default 1                 not null comment '1 为可用，0 不可用',\n    memo                    varchar(1000) default ''                not null comment ' 备注 ',\n    create_time             timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time             timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间'\n)\n    comment '项目配置' charset = utf8;\n\n-- auto-generated definition\n\n\n#### 核心表结构\nCREATE TABLE `arius_config_info`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `value_group` varchar(100)        NOT NULL DEFAULT '' COMMENT ' 配置项组 ',\n    `value_name`  varchar(100)        NOT NULL DEFAULT '' COMMENT ' 配置项名字 ',\n    `value`       text COMMENT '配置项的值',\n    `edit`        int(4)              NOT NULL DEFAULT '1' COMMENT '是否可以编辑 1 不可编辑（程序获取） 2 可编辑',\n    `dimension`   int(4)              NOT NULL DEFAULT '-1' COMMENT '配置项维度 1 集群 2 模板',\n    `status`      int(4)              NOT NULL DEFAULT '1' COMMENT '1 正常 2 禁用 -1 删除',\n    `memo`        varchar(1000)       NOT NULL DEFAULT '' COMMENT ' 备注 ',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `search_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '配置查询时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_group_name` (`value_group`, `value_name`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1662\n  DEFAULT CHARSET = utf8 COMMENT ='arius 配置项';\n\n\n\n-- ----------------------------\n-- Table structure for arius_meta_job_cluster_distribute\n-- ----------------------------\nCREATE TABLE `arius_meta_job_cluster_distribute`\n(\n    `id`           bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 id',\n    `cluster_id`   int(11)             NOT NULL DEFAULT '-1' COMMENT '集群 id',\n    `monitor_host` varchar(128)        NOT NULL DEFAULT '' COMMENT ' 当前执行主机名 ',\n    `monitor_time` timestamp           NOT NULL DEFAULT '2000-01-02 00:00:00' COMMENT '上一次监控时间',\n    `gmt_create`   timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `gmt_modify`   timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `cluster`      varchar(128)        NOT NULL DEFAULT '' COMMENT ' 集群名称 ',\n    `dataCentre`   varchar(16)         NOT NULL DEFAULT 'cn' COMMENT '集群数据中心',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_cluster_id` (`cluster_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 435089\n  DEFAULT CHARSET = utf8 COMMENT ='monitor 任务分配';\n\n-- ----------------------------\n-- Table structure for arius_op_task\n-- ----------------------------\nCREATE TABLE `arius_op_task`\n(\n    `id`           bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `title`        varchar(100)        NOT NULL DEFAULT '' COMMENT ' 标题 ',\n    `business_key` varchar(1000)       NOT NULL DEFAULT '0' COMMENT '业务数据主键',\n    `status`       varchar(20)         NOT NULL DEFAULT 'waiting' COMMENT '任务状态：success: 成功 failed: 失败 running: 执行中 waiting: 等待 cancel: 取消 pause: 暂停',\n    `creator`      varchar(100)        NOT NULL DEFAULT '' COMMENT ' 创建人 ',\n    `create_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`  tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    `expand_data`  longtext COMMENT '扩展数据',\n    `task_type`    int(11)             NOT NULL DEFAULT '0' COMMENT '任务类型 1：集群新增，2：集群扩容，3：集群缩容，4：集群重，5：集群升级，6：集群插件操作，10：模版 dcdr 任务',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2302\n  DEFAULT CHARSET = utf8 COMMENT ='arius 任务表';\n\n-- ----------------------------\n-- Table structure for arius_work_order_info\n-- ----------------------------\nCREATE TABLE `arius_work_order_info`\n(\n    `id`                   bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',\n    `type`                 varchar(25)         NOT NULL DEFAULT 'unknown' COMMENT 'appcreate 创建 app,clustercreate 创建集群,clusterindecrease 集群扩缩溶,clusteroffline 集群下线,clusterupdate 集群修改,templateauth 索引申请,templatecreate 索引创建,templateindecrease 索引扩容,templatequerydsl 查询语句创建,templatetransfer 索引转让,querydsllimitedit 查询语句编辑,responsiblegovern 员工离职,unhealthytemplategovern 不健康索引处理',\n    `title`                varchar(64)         NOT NULL DEFAULT '' COMMENT ' 标题 ',\n    `approver_project_id`  int(16)             NOT NULL DEFAULT '-1' COMMENT '审批人 projectid',\n    `applicant`            varchar(64)         NOT NULL DEFAULT '' COMMENT ' 申请人 ',\n    `extensions`           text COMMENT '拓展字段',\n    `description`          text COMMENT '备注信息',\n    `approver`             varchar(64)         NOT NULL DEFAULT '' COMMENT ' 审批人 ',\n    `finish_time`          timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '结束时间',\n    `opinion`              varchar(256)        NOT NULL DEFAULT '' COMMENT ' 审批信息 ',\n    `status`               int(16)             NOT NULL DEFAULT '0' COMMENT '工单状态, 0: 待审批, 1: 通过, 2: 拒绝, 3: 取消',\n    `create_time`          timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`          timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修 \\n 改时间',\n    `applicant_project_id` int(16)             NOT NULL DEFAULT '-1' COMMENT '申请人 projectid',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2522\n  DEFAULT CHARSET = utf8 COMMENT ='工单表';\n\n-- ----------------------------\n-- Table structure for es_cluster_phy_info\n-- ----------------------------\nCREATE TABLE `es_cluster_phy_info`\n(\n    `id`                      bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `cluster`                 varchar(128)        NOT NULL DEFAULT '' COMMENT 'es 集群名 ',\n    `read_address`            varchar(1000)       NOT NULL DEFAULT '' COMMENT ' 读地址 tcp',\n    `write_address`           varchar(2000)       NOT NULL DEFAULT '' COMMENT ' 写地址 tcp',\n    `http_address`            varchar(1000)       NOT NULL DEFAULT '' COMMENT 'http 服务地址 ',\n    `http_write_address`      varchar(8000)       NOT NULL DEFAULT '' COMMENT 'http 写地址 ',\n    `desc`                    varchar(2000)       NOT NULL DEFAULT '' COMMENT ' 描述 ',\n    `type`                    tinyint(4)          NOT NULL DEFAULT '-1' COMMENT '集群类型，3-docker 集群，4-host 集群',\n    `data_center`             varchar(10)         NOT NULL DEFAULT 'cn' COMMENT '数据中心',\n    `idc`                     varchar(10)         NOT NULL DEFAULT '' COMMENT ' 机房信息 ',\n    `es_version`              varchar(100)        NOT NULL DEFAULT '' COMMENT 'es 版本 ',\n    `create_time`             timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`             timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `level`                   tinyint(4)          NOT NULL DEFAULT '1' COMMENT '服务等级',\n    `password`                varchar(255)        NOT NULL DEFAULT '' COMMENT ' 集群访问密码 ',\n    `ecm_cluster_id`          int(11)             NOT NULL DEFAULT '-1' COMMENT 'ecm 集群 id',\n    `cluster_config_template` text COMMENT '集群安装模板',\n    `image_name`              varchar(500)        NOT NULL DEFAULT '' COMMENT ' 镜像名 ',\n    `cfg_id`                  int(11)             NOT NULL DEFAULT '-1' COMMENT '配置包 id',\n    `package_id`              int(11)             NOT NULL DEFAULT '-1' COMMENT '程序包 id',\n    `plug_ids`                varchar(100)                 DEFAULT '' COMMENT ' 插件包 id 列表 ',\n    `creator`                 varchar(255)        NOT NULL DEFAULT '' COMMENT ' 集群创建人 ',\n    `ns_tree`                 varchar(100)        NOT NULL DEFAULT '' COMMENT ' 机器节点 ',\n    `template_srvs`           varchar(255)                 DEFAULT '' COMMENT ' 集群的索引模板服务 ',\n    `is_active`               tinyint(4)          NOT NULL DEFAULT '1' COMMENT '是否生效',\n    `run_mode`                tinyint(255)        NOT NULL DEFAULT '0' COMMENT 'client 运行模式，0 读写共享，1 读写分离',\n    `write_action`            varchar(1000)                DEFAULT NULL COMMENT '指定写 client 的 action',\n    `health`                  tinyint(2)          NOT NULL DEFAULT '3' COMMENT '集群状态 1 green 2 yellow 3 red',\n    `active_shard_num`        bigint(25)          NOT NULL DEFAULT '0' COMMENT '有效 shard 总数量',\n    `disk_total`              bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘总量 单位 byte',\n    `disk_usage`              bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘使用量 单位 byte',\n    `disk_usage_percent`      decimal(10, 5)      NOT NULL COMMENT '集群磁盘空闲率 单位 0 ~1',\n    `tags`                    text COMMENT '拓展字段, 这里用于存放集群展示用属性标签，如「集群所属资源类型」等等',\n    `platform_type`           varchar(100)        NOT NULL DEFAULT '' COMMENT 'IaaS 平台类型 ',\n    `resource_type`           tinyint(4)          NOT NULL DEFAULT '-1' COMMENT '集群资源类型，1- 共享资源，2- 独立资源，3- 独享资源',\n    `gateway_url`             varchar(200)        NOT NULL DEFAULT '' COMMENT ' 集群 gateway 地址 ',\n    PRIMARY KEY (`id`),\n    KEY `idx_cluster` (`cluster`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 4710\n  DEFAULT CHARSET = utf8 COMMENT ='物理集群表';\n\n-- ----------------------------\n-- Table structure for es_cluster_region\n-- ----------------------------\nCREATE TABLE `es_cluster_region`\n(\n    `id`               bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `logic_cluster_id` varchar(200)        NOT NULL DEFAULT '-1' COMMENT '逻辑集群 ID',\n    `phy_cluster_name` varchar(128)        NOT NULL DEFAULT '' COMMENT ' 物理集群名 ',\n    `racks`            varchar(2048)                DEFAULT '' COMMENT 'region 的 rack，逗号分隔 ',\n    `create_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`      tinyint(1)          NOT NULL DEFAULT '0' COMMENT '删除标记，1- 已删除，0- 未删除',\n    `name`             varchar(100)        NOT NULL DEFAULT '' COMMENT 'region 名称 ',\n    `config`           varchar(1024)                DEFAULT '' COMMENT 'region 配置项 ',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 4008\n  DEFAULT CHARSET = utf8 COMMENT ='es 集群 region 表';\n\n-- ----------------------------\n-- Table structure for es_cluster_role_host_info\n-- ----------------------------\nCREATE TABLE `es_cluster_role_host_info`\n(\n    `id`              bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `role_cluster_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '关联集群角色表外键',\n    `hostname`        varchar(100)        NOT NULL DEFAULT '' COMMENT ' 节点名称 ',\n    `ip`              varchar(50)         NOT NULL DEFAULT '' COMMENT ' 主机 ip',\n    `cluster`         varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群 ',\n    `port`            varchar(20)         NOT NULL DEFAULT '' COMMENT ' 端口，如果是节点上启动了多个进程，可以是多个，用逗号隔开 ',\n    `role`            tinyint(4)          NOT NULL DEFAULT '-1' COMMENT '角色信息， 1data 2client 3master 4tribe',\n    `status`          tinyint(4)          NOT NULL DEFAULT '1' COMMENT '节点状态，1 在线 2 离线',\n    `rack`            varchar(30)                  DEFAULT '' COMMENT ' 节点 rack 信息 ',\n    `node_set`        varchar(500)        NOT NULL DEFAULT '' COMMENT ' 节点 set 信息 ',\n    `create_time`     timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`     timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`     tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    `machine_spec`    varchar(100)                 DEFAULT '',\n    `region_id`       bigint(20)          NOT NULL DEFAULT '-1' COMMENT '节点所属 regionId',\n    `attributes`      text COMMENT 'es 节点 attributes 信息 , 逗号分隔',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_elastic_cluster_id_role_node_set` (`role_cluster_id`, `ip`, `port`, `node_set`),\n    KEY `idx_cluster` (`cluster`),\n    KEY `idx_hostname` (`hostname`),\n    KEY `idx_rack` (`rack`),\n    KEY `idx_region_id` (`region_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2274\n  DEFAULT CHARSET = utf8 COMMENT ='es 集群表对应各角色主机列表';\n\n-- ----------------------------\n-- Table structure for es_cluster_role_info\n-- ----------------------------\nCREATE TABLE `es_cluster_role_info`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `elastic_cluster_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'elastic_cluster 外键 id',\n    `role_cluster_name`  varchar(256)        NOT NULL DEFAULT '' COMMENT 'role 集群名称 ',\n    `role`               varchar(20)         NOT NULL DEFAULT '' COMMENT ' 集群角色 (masternode/datanode/clientnode)',\n    `pod_number`         int(11)             NOT NULL DEFAULT '0' COMMENT 'pod 数量',\n    `pid_count`          int(11)             NOT NULL DEFAULT '1' COMMENT '单机实例数',\n    `machine_spec`       varchar(100)                 DEFAULT '' COMMENT ' 机器规格 ',\n    `es_version`         varchar(150)        NOT NULL DEFAULT '' COMMENT 'es 版本 ',\n    `cfg_id`             int(11)             NOT NULL DEFAULT '-1' COMMENT '配置包 id',\n    `plug_ids`           varchar(100)        NOT NULL DEFAULT '' COMMENT ' 插件包 id 列表 ',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`        tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_elastic_cluster_id_ddcloud_cluster_name` (`elastic_cluster_id`, `role_cluster_name`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1138\n  DEFAULT CHARSET = utf8 COMMENT ='es 集群角色表';\n\n-- ----------------------------\n-- Table structure for es_config\n-- ----------------------------\nCREATE TABLE `es_config`\n(\n    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `cluster_id`     bigint(20)          NOT NULL DEFAULT '-1' COMMENT '集群 id',\n    `type_name`      varchar(255)        NOT NULL DEFAULT '' COMMENT ' 配置文件名称 ',\n    `engin_name`     varchar(100)        NOT NULL DEFAULT '' COMMENT ' 组件名称 ',\n    `config_data`    longtext COMMENT '配置内容',\n    `desc`           varchar(255)        NOT NULL DEFAULT '' COMMENT ' 配置描述 ',\n    `version_tag`    varchar(100)        NOT NULL DEFAULT '' COMMENT ' 配置 tag',\n    `version_config` bigint(20)          NOT NULL DEFAULT '-1' COMMENT '配置版本',\n    `selected`       smallint(6)         NOT NULL DEFAULT '0' COMMENT '是否在使用',\n    `create_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`    tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1130\n  DEFAULT CHARSET = utf8 COMMENT ='es 配置表';\n\n-- ----------------------------\n-- Table structure for es_machine_norms\n-- ----------------------------\nCREATE TABLE `es_machine_norms`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `role`        varchar(20)         NOT NULL DEFAULT '' COMMENT ' 角色 (masternode/datanode/clientnode/datanode-ceph)',\n    `spec`        varchar(32)         NOT NULL DEFAULT '' COMMENT ' 规格 (16-48gi-100g)',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `delete_flag` tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 16\n  DEFAULT CHARSET = utf8 COMMENT ='容器规格列表';\n\n-- ----------------------------\n-- Table structure for es_package\n-- ----------------------------\nCREATE TABLE `es_package`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `url`         varchar(255)        NOT NULL DEFAULT '' COMMENT ' 镜像地址或包地址 ',\n    `es_version`  varchar(100)        NOT NULL DEFAULT '' COMMENT ' 版本标识 ',\n    `creator`     varchar(100)        NOT NULL DEFAULT '' COMMENT ' 包创建人 ',\n    `release`     tinyint(1)          NOT NULL DEFAULT '0' COMMENT '是否为发布版本',\n    `manifest`    varchar(32)         NOT NULL DEFAULT '' COMMENT ' 类型 (3 docker/4 host)',\n    `desc`        varchar(384)                 DEFAULT '' COMMENT ' 备注 ',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag` tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除 0 未删 1 已删',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 318\n  DEFAULT CHARSET = utf8 COMMENT ='程序包版本管理';\n\n-- ----------------------------\n-- Table structure for es_plugin\n-- ----------------------------\nCREATE TABLE `es_plugin`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `name`               varchar(50)         NOT NULL DEFAULT '' COMMENT ' 插件名 ',\n    `physic_cluster_ids` varchar(100)        NOT NULL DEFAULT '' COMMENT ' 物理集群 id',\n    `version`            varchar(50)         NOT NULL DEFAULT '' COMMENT ' 插件版本 ',\n    `url`                varchar(1024)       NOT NULL DEFAULT '' COMMENT ' 插件存储地址 ',\n    `md5`                varchar(100)        NOT NULL DEFAULT '' COMMENT ' 插件文件 md5',\n    `desc`               varchar(255)        NOT NULL DEFAULT '' COMMENT ' 插件描述 ',\n    `creator`            varchar(100)        NOT NULL DEFAULT '' COMMENT ' 插件创建人 ',\n    `p_default`          tinyint(1)          NOT NULL DEFAULT '0' COMMENT '是否为系统默认：0 否 1 是',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `delete_flag`        tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 416\n  DEFAULT CHARSET = utf8 COMMENT ='es 插件包管理';\n\n-- ----------------------------\n-- Table structure for es_work_order_task\n-- ----------------------------\nCREATE TABLE `es_work_order_task`\n(\n    `id`                bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `title`             varchar(100)        NOT NULL DEFAULT '' COMMENT ' 标题 ',\n    `work_order_id`     bigint(20)          NOT NULL DEFAULT '-1' COMMENT '工单 id',\n    `physic_cluster_id` bigint(20)          NOT NULL DEFAULT '-1' COMMENT '物理集群 id',\n    `cluster_node_role` varchar(512)        NOT NULL DEFAULT '-1' COMMENT '集群节点角色',\n    `task_ids`          varchar(128)        NOT NULL DEFAULT '' COMMENT ' 各角色任务 ids',\n    `type`              varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群类型:3 docker 容器云 / 4 host 物理机 ',\n    `order_type`        varchar(50)         NOT NULL DEFAULT '' COMMENT ' 工单类型 1 集群新增 2 集群扩容 3 集群缩容 4 集群重启 5 集群升级 ',\n    `status`            varchar(20)         NOT NULL DEFAULT '' COMMENT ' 任务状态 ',\n    `creator`           varchar(100)        NOT NULL DEFAULT '' COMMENT ' 工单创建人 ',\n    `create_time`       timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`       timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`       tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    `handle_data`       longtext COMMENT '工单数据',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1958\n  DEFAULT CHARSET = utf8 COMMENT ='es 工单任务表';\n\n-- ----------------------------\n-- Table structure for es_work_order_task_detail\n-- ----------------------------\nCREATE TABLE `es_work_order_task_detail`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `work_order_task_id` bigint(20)          NOT NULL DEFAULT '-1' COMMENT '工单任务 id',\n    `role`               varchar(100)        NOT NULL DEFAULT '' COMMENT ' 所属角色 ',\n    `hostname`           varchar(100)        NOT NULL DEFAULT '' COMMENT ' 主机名称 /ip',\n    `grp`                int(11)             NOT NULL DEFAULT '0' COMMENT '机器的分组',\n    `idx`                int(11)             NOT NULL DEFAULT '0' COMMENT '机器在分组中的索引',\n    `task_id`            bigint(20)          NOT NULL DEFAULT '-1' COMMENT '容器云 / 物理机 接口返回任务 id',\n    `status`             varchar(20)         NOT NULL DEFAULT '' COMMENT ' 任务状态 ',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`        tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_work_order_task_id_role_hostname_delete_flag` (`work_order_task_id`, `role`, `hostname`, `delete_flag`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 6592\n  DEFAULT CHARSET = utf8 COMMENT ='es 工单任务详情表';\n\n-- ----------------------------\n-- Table structure for gateway_cluster_info\n-- ----------------------------\nCREATE TABLE `gateway_cluster_info`\n(\n    `id`           bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `cluster_name` varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群名称 ',\n    `create_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_cluster_name` (`cluster_name`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 188\n  DEFAULT CHARSET = utf8 COMMENT ='gateway 集群信息';\n\n-- ----------------------------\n-- Table structure for gateway_cluster_node_info\n-- ----------------------------\nCREATE TABLE `gateway_cluster_node_info`\n(\n    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `cluster_name`   varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群名称 ',\n    `host_name`      varchar(50)         NOT NULL DEFAULT '' COMMENT ' 主机名 ',\n    `port`           int(10)             NOT NULL DEFAULT '-1' COMMENT '端口',\n    `heartbeat_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '心跳时间',\n    `create_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_ip_port` (`host_name`, `port`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 490264\n  DEFAULT CHARSET = utf8 COMMENT ='gateway 节点信息';\n\n-- ----------------------------\n-- Table structure for index_template_alias\n-- ----------------------------\nCREATE TABLE `index_template_alias`\n(\n    `id`                bigint(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `index_template_id` int(10)             NOT NULL DEFAULT '-1' COMMENT '索引模板 id',\n    `name`              varchar(50)         NOT NULL DEFAULT '' COMMENT ' 别名 ',\n    `filterterm`        varchar(255)        NOT NULL DEFAULT '' COMMENT ' 过滤器 ',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 4\n  DEFAULT CHARSET = utf8 COMMENT ='索引别名';\n\n-- ----------------------------\n-- Table structure for index_template_config\n-- ----------------------------\nCREATE TABLE `index_template_config`\n(\n    `is_source_separated`      tinyint(4)          NOT NULL DEFAULT '0' COMMENT '是否是索引处分分离的 0 不是 1 是',\n    `idc_flags`                tinyint(1)          NOT NULL DEFAULT '0' COMMENT 'idc 标识',\n    `adjust_rack_shard_factor` decimal(10, 2)      NOT NULL DEFAULT '1.00' COMMENT '模板 shard 的资源消耗因子',\n    `mapping_improve_enable`   tinyint(4)          NOT NULL DEFAULT '1' COMMENT 'mapping 优化开关 1 开 0 关',\n    `pre_create_flags`         tinyint(1)          NOT NULL DEFAULT '1' COMMENT '预创建标识',\n    `update_time`              timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `disable_source_flags`     tinyint(1)          NOT NULL DEFAULT '0' COMMENT '禁用 source 标识',\n    `disable_index_rollover`   tinyint(1)          NOT NULL DEFAULT '1' COMMENT '禁用 indexRollover 功能',\n    `dynamic_limit_enable`     tinyint(4)          NOT NULL DEFAULT '1' COMMENT '动态限流开关 1 开 0 关',\n    `logic_id`                 int(10)             NOT NULL DEFAULT '-1' COMMENT '逻辑模板 id',\n    `create_time`              timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `shard_num`                int(11)             NOT NULL DEFAULT '1' COMMENT 'shard 数量',\n    `adjust_rack_tps_factor`   decimal(10, 2)      NOT NULL DEFAULT '1.00' COMMENT '容量规划时，tps 的系数',\n    `id`                       bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n    PRIMARY KEY (`id`),\n    KEY `idx_logic_id` (`logic_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1546\n  DEFAULT CHARSET = utf8 COMMENT ='模板配置信息';\n\n-- ----------------------------\n-- Table structure for index_template_info\n-- ----------------------------\nCREATE TABLE `index_template_info`\n(\n    `id`                bigint(20) unsigned          NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `name`              varchar(128)                 NOT NULL DEFAULT '' COMMENT ' 名称 ',\n    `data_type`         tinyint(4)                   NOT NULL DEFAULT '-1' COMMENT '数据类型',\n    `date_format`       varchar(50)                  NOT NULL DEFAULT '' COMMENT ' 索引分区的时间后缀 ',\n    `is_active`         tinyint(2)                   NOT NULL DEFAULT '1' COMMENT '有效标记',\n    `data_center`       varchar(20)                  NOT NULL DEFAULT '' COMMENT ' 数据中心 ',\n    `expire_time`       bigint(20)                   NOT NULL DEFAULT '-1' COMMENT '保存时长',\n    `hot_time`          int(10)                      NOT NULL DEFAULT '-1' COMMENT '热数据保存时长',\n    `responsible`       varchar(500)                          DEFAULT '' COMMENT ' 责任人 ',\n    `date_field`        varchar(50)                  NOT NULL DEFAULT '' COMMENT ' 时间字段 ',\n    `date_field_format` varchar(128)                 NOT NULL DEFAULT '' COMMENT ' 时间字段的格式 ',\n    `id_field`          varchar(512)                          DEFAULT '' COMMENT 'id 字段 ',\n    `routing_field`     varchar(512)                          DEFAULT '' COMMENT 'routing 字段 ',\n    `expression`        varchar(100)                 NOT NULL DEFAULT '' COMMENT ' 索引表达式 ',\n    `desc`              varchar(500)                 NOT NULL DEFAULT '' COMMENT ' 索引描述 ',\n    `quota`             decimal(10, 3)               NOT NULL DEFAULT '-1.000' COMMENT '规格',\n    `project_id`        int(10)                      NOT NULL DEFAULT '-1' COMMENT 'project_id',\n    `ingest_pipeline`   varchar(512)                 NOT NULL DEFAULT '' COMMENT 'ingest_pipeline',\n    `block_read`        tinyint(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否禁读，0：否，1：是',\n    `block_write`       tinyint(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否禁写，0：否，1：是',\n    `create_time`       timestamp                    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`       timestamp                    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `write_rate_limit`  bigint(255)                  NOT NULL DEFAULT '-1' COMMENT '写入限流值',\n    `resource_id`       bigint(20)                   NOT NULL DEFAULT '-1' COMMENT '逻辑集群 id',\n    `check_point_diff`  bigint(100)                  NOT NULL DEFAULT '0' COMMENT 'dcdr 位点差',\n    `level`             tinyint(4)                   NOT NULL DEFAULT '1' COMMENT '服务等级分为 1,2,3',\n    `has_dcdr`          tinyint(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否开启 dcdr',\n    `open_srv`          varchar(255)                          DEFAULT NULL COMMENT '已开启的模板服务',\n    `disk_size`         decimal(10, 3)                        DEFAULT '-1.000' COMMENT '可用磁盘容量',\n    `health`            int(11)                               DEFAULT '-1' COMMENT '模版健康；-1 是 UNKNOW',\n    PRIMARY KEY (`id`),\n    KEY `idx_data_center` (`data_center`),\n    KEY `idx_is_active` (`is_active`),\n    KEY `idx_name` (`name`),\n    KEY `idx_project_id` (`project_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 25998\n  DEFAULT CHARSET = utf8 COMMENT ='逻辑索引模板表';\n\n-- ----------------------------\n-- Table structure for index_template_physical_info\n-- ----------------------------\nCREATE TABLE `index_template_physical_info`\n(\n    `id`            bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `logic_id`      int(10)             NOT NULL DEFAULT '-1' COMMENT '逻辑模板 id',\n    `name`          varchar(128)        NOT NULL DEFAULT '' COMMENT ' 模板名字 ',\n    `expression`    varchar(128)        NOT NULL DEFAULT '' COMMENT ' 表达式 ',\n    `cluster`       varchar(128)        NOT NULL DEFAULT '' COMMENT ' 集群名字 ',\n    `rack`          varchar(512)        NOT NULL DEFAULT '' COMMENT 'rack',\n    `shard`         int(10)             NOT NULL DEFAULT '1' COMMENT 'shard 个数',\n    `shard_routing` int(10)             NOT NULL DEFAULT '1' COMMENT '内核的逻辑 shard',\n    `version`       int(10)             NOT NULL DEFAULT '0' COMMENT '版本',\n    `role`          tinyint(4)          NOT NULL DEFAULT '1' COMMENT '角色 1master 2slave',\n    `status`        tinyint(4)          NOT NULL DEFAULT '1' COMMENT '1 常规 -1 索引删除中 -2 已删除',\n    `config`        text COMMENT '配置 json 格式',\n    `create_time`   timestamp           NULL     DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`   timestamp           NULL     DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `region_id`     int(10)             NOT NULL DEFAULT '-1' COMMENT '模板关联的 regionId',\n    PRIMARY KEY (`id`),\n    KEY `idx_cluster_name_status` (`cluster`, `name`, `status`),\n    KEY `idx_log_id_statud` (`logic_id`, `status`),\n    KEY `idx_logic_id` (`logic_id`),\n    KEY `idx_region_id` (`region_id`),\n    KEY `idx_status` (`status`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 23700\n  DEFAULT CHARSET = utf8 COMMENT ='物理模板信息';\n\n-- ----------------------------\n-- Table structure for index_template_type\n-- ----------------------------\nCREATE TABLE `index_template_type`\n(\n    `id`                  bigint(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `index_template_id`   int(10)             NOT NULL DEFAULT '-1' COMMENT '索引模板 id',\n    `index_template_name` varchar(100)        NOT NULL DEFAULT '' COMMENT ' 索引模板名称 ',\n    `name`                varchar(100)        NOT NULL DEFAULT '' COMMENT 'type 名称 ',\n    `id_field`            varchar(128)        NOT NULL DEFAULT '' COMMENT 'id 字段 ',\n    `routing`             varchar(100)        NOT NULL DEFAULT '' COMMENT 'routing 字段 ',\n    `source`              tinyint(4)          NOT NULL DEFAULT '1' COMMENT '0 不存 source 1 存 source',\n    `is_active`           tinyint(2)          NOT NULL DEFAULT '1' COMMENT '是否激活 1 是 0 否',\n    `create_time`         timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`         timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='索引模板 type';\n\n-- ----------------------------\n-- Table structure for logi_job\n-- ----------------------------\nCREATE TABLE `logi_job`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `job_code`    varchar(100) NOT NULL DEFAULT '' COMMENT 'task taskCode',\n    `task_code`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务 code',\n    `class_name`  varchar(255) NOT NULL DEFAULT '' COMMENT ' 类的全限定名 ',\n    `try_times`   int(10)      NOT NULL DEFAULT '0' COMMENT '第几次重试',\n    `worker_code` varchar(200) NOT NULL DEFAULT '' COMMENT ' 执行机器 ',\n    `app_name`    varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `start_time`  datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '开始时间',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `job_code` (`job_code`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 381677\n  DEFAULT CHARSET = utf8 COMMENT ='正在执行的 job 信息';\n\n-- ----------------------------\n-- Table structure for logi_job_log\n-- ----------------------------\nCREATE TABLE `logi_job_log`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `job_code`    varchar(100) NOT NULL DEFAULT '' COMMENT 'job taskCode',\n    `task_code`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务 code',\n    `task_name`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务名称 ',\n    `task_desc`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务描述 ',\n    `task_id`     bigint(20)   NOT NULL DEFAULT '0' COMMENT '任务 id',\n    `class_name`  varchar(255) NOT NULL DEFAULT '' COMMENT ' 类的全限定名 ',\n    `try_times`   int(10)      NOT NULL DEFAULT '0' COMMENT '第几次重试',\n    `worker_code` varchar(200) NOT NULL DEFAULT '' COMMENT ' 执行机器 ',\n    `worker_ip`   varchar(200) NOT NULL DEFAULT '' COMMENT ' 执行机器 ip',\n    `start_time`  datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '开始时间',\n    `end_time`    datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '结束时间',\n    `status`      tinyint(4)   NOT NULL DEFAULT '0' COMMENT '执行结果 1 成功 2 失败 3 取消',\n    `error`       text         NOT NULL COMMENT '错误信息',\n    `result`      text         NOT NULL COMMENT '执行结果',\n    `app_name`    varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_job_code` (`job_code`) USING BTREE\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 381395\n  DEFAULT CHARSET = utf8 COMMENT ='job 执行历史日志';\n\n\n\n-- ----------------------------\n-- Table structure for logi_task\n-- ----------------------------\nCREATE TABLE `logi_task`\n(\n    `id`              bigint(20)    NOT NULL AUTO_INCREMENT,\n    `task_code`       varchar(100)  NOT NULL DEFAULT '' COMMENT 'task taskCode',\n    `task_name`       varchar(255)  NOT NULL DEFAULT '' COMMENT ' 名称 ',\n    `task_desc`       varchar(1000) NOT NULL DEFAULT '' COMMENT ' 任务描述 ',\n    `cron`            varchar(100)  NOT NULL DEFAULT '' COMMENT 'cron 表达式 ',\n    `class_name`      varchar(255)  NOT NULL DEFAULT '' COMMENT ' 类的全限定名 ',\n    `params`          varchar(1000) NOT NULL DEFAULT '' COMMENT ' 执行参数 map 形式 {key1:value1,key2:value2}',\n    `retry_times`     int(10)       NOT NULL DEFAULT '0' COMMENT '允许重试次数',\n    `last_fire_time`  datetime               DEFAULT CURRENT_TIMESTAMP COMMENT '上次执行时间',\n    `timeout`         bigint(20)    NOT NULL DEFAULT '0' COMMENT '超时 毫秒',\n    `status`          tinyint(4)    NOT NULL DEFAULT '0' COMMENT '1 等待 2 运行中 3 暂停',\n    `sub_task_codes`  varchar(1000) NOT NULL DEFAULT '' COMMENT ' 子任务 code 列表, 逗号分隔 ',\n    `consensual`      varchar(200)  NOT NULL DEFAULT '' COMMENT ' 执行策略 ',\n    `owner`           varchar(200)  NOT NULL DEFAULT '' COMMENT ' 责任人 ',\n    `task_worker_str` varchar(3000) NOT NULL DEFAULT '' COMMENT ' 机器执行信息 ',\n    `app_name`        varchar(100)  NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `create_time`     datetime               DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`     datetime               DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `task_code` (`task_code`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 548\n  DEFAULT CHARSET = utf8 COMMENT ='任务信息';\n\n-- ----------------------------\n-- Table structure for logi_task_lock\n-- ----------------------------\nCREATE TABLE `logi_task_lock`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `task_code`   varchar(100) NOT NULL DEFAULT '' COMMENT 'task taskCode',\n    `worker_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n    `app_name`    varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `expire_time` bigint(20)   NOT NULL DEFAULT '0' COMMENT '过期时间',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uni_task_app` (`task_code`, `app_name`) USING BTREE\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 569\n  DEFAULT CHARSET = utf8 COMMENT ='任务锁';\n\n-- ----------------------------\n-- Table structure for logi_worker\n-- ----------------------------\nCREATE TABLE `logi_worker`\n(\n    `id`              bigint(20)   NOT NULL AUTO_INCREMENT,\n    `worker_code`     varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n    `worker_name`     varchar(100) NOT NULL DEFAULT '' COMMENT 'worker 名 ',\n    `ip`              varchar(100) NOT NULL DEFAULT '' COMMENT 'worker 的 ip',\n    `cpu`             int(11)      NOT NULL DEFAULT '0' COMMENT 'cpu 数量',\n    `cpu_used`        double       NOT NULL DEFAULT '0' COMMENT 'cpu 使用率',\n    `memory`          double       NOT NULL DEFAULT '0' COMMENT '内存, 以 M 为单位',\n    `memory_used`     double       NOT NULL DEFAULT '0' COMMENT '内存使用率',\n    `jvm_memory`      double       NOT NULL DEFAULT '0' COMMENT 'jvm 堆大小，以 M 为单位',\n    `jvm_memory_used` double       NOT NULL DEFAULT '0' COMMENT 'jvm 堆使用率',\n    `job_num`         int(10)      NOT NULL DEFAULT '0' COMMENT '正在执行 job 数',\n    `heartbeat`       datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '心跳时间',\n    `app_name`        varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `create_time`     datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`     datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `worker_code` (`worker_code`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 8\n  DEFAULT CHARSET = utf8 COMMENT ='worker 信息';\n\n-- ----------------------------\n-- Table structure for logi_worker_blacklist\n-- ----------------------------\nCREATE TABLE `logi_worker_blacklist`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `worker_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `worker_code` (`worker_code`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='worker 黑名单列表';\n\n-- ----------------------------\n-- Table structure for operate_record_info\n-- ----------------------------\nCREATE TABLE `operate_record_info`\n(\n    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `project_name`   varchar(255)                 DEFAULT NULL COMMENT '应用',\n    `module_id`      int(10)             NOT NULL DEFAULT '-1' COMMENT '模块 id',\n    `operate_id`     int(10)             NOT NULL DEFAULT '-1' COMMENT '操作 id',\n    `trigger_way_id` int(11)                      DEFAULT NULL COMMENT '触发方式',\n    `user_operation` varchar(50)         NOT NULL DEFAULT '' COMMENT ' 操作人 ',\n    `content`        longtext COMMENT '操作内容',\n    `operate_time`   timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',\n    `create_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `biz_id`         varchar(255)                 DEFAULT NULL,\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 8218\n  DEFAULT CHARSET = utf8 COMMENT ='操作记录表';\n\n\n-- ----------------------------\n-- Table structure for project_arius_resource_logic\n-- ----------------------------\nCREATE TABLE `project_arius_resource_logic`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `name`               varchar(128)        NOT NULL DEFAULT '' COMMENT ' 资源名称 ',\n    `type`               tinyint(4)          NOT NULL DEFAULT '2' COMMENT '资源类型 1 共享公共资源 2 独享资源',\n    `project_id`         varchar(1024)       NOT NULL DEFAULT '-1' COMMENT '资源所属的 project_id',\n    `data_center`        varchar(20)         NOT NULL DEFAULT '' COMMENT ' 数据中心 cn/us01',\n    `responsible`        varchar(128)                 DEFAULT '' COMMENT ' 资源责任人 ',\n    `memo`               varchar(512)        NOT NULL DEFAULT '' COMMENT ' 资源备注 ',\n    `quota`              decimal(8, 2)       NOT NULL DEFAULT '1.00' COMMENT '资源的大小',\n    `level`              tinyint(4)          NOT NULL DEFAULT '1' COMMENT '服务等级 1 normal 2 important 3 vip',\n    `config_json`        varchar(1024)       NOT NULL DEFAULT '' COMMENT ' 集群配置 ',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `health`             tinyint(4)          NOT NULL DEFAULT '3' COMMENT '集群状态 1 green 2 yellow 3 red -1 未知',\n    `data_node_spec`     varchar(20)         NOT NULL DEFAULT '' COMMENT ' 节点规格 ',\n    `disk_total`         bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘总量 单位 byte',\n    `disk_usage`         bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘使用量 单位 byte',\n    `disk_usage_percent` decimal(10, 5)      default NULL COMMENT '集群磁盘空闲率 单位 0 ~1',\n    `es_cluster_version` varchar(20)         default NULL COMMENT 'es 集群版本',\n    `node_num`           int(10)             NOT NULL DEFAULT '0' COMMENT '节点个数',\n    `data_node_num`      int(10)             NOT NULL DEFAULT '0' COMMENT '节点个数',\n    PRIMARY KEY (`id`),\n    KEY `idx_name` (`name`),\n    KEY `idx_project_id` (`project_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 3922\n  DEFAULT CHARSET = utf8 COMMENT ='逻辑资源信息';\n\n-- ----------------------------\n-- Table structure for project_logi_cluster_auth\n-- ----------------------------\nCREATE TABLE `project_logi_cluster_auth`\n(\n    `id`               bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `project_id`       int(10)             NOT NULL DEFAULT '-1' COMMENT '项目 id',\n    `logic_cluster_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '逻辑集群 id',\n    `type`             int(10)             NOT NULL DEFAULT '-1' COMMENT '权限类型，0- 超管，1- 配置管理，2- 访问，-1- 无权限',\n    `responsible`      varchar(100)                 DEFAULT '' COMMENT ' 责任人 id 列表 ',\n    `status`           int(10)             NOT NULL DEFAULT '1' COMMENT '状态 1 有效 0 无效',\n    `create_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_project_id` (`project_id`),\n    KEY `idx_logic_cluster_id` (`logic_cluster_id`),\n    KEY `idx_status` (`status`),\n    KEY `idx_type` (`type`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='project 逻辑集群权限';\n\n-- ----------------------------\n-- Table structure for project_template_info\n-- ----------------------------\nCREATE TABLE `project_template_info`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `project_id`  int(10)             NOT NULL DEFAULT '-1' COMMENT '项目 id',\n    `template`    varchar(100)        NOT NULL DEFAULT '' COMMENT ' 模板名称, 不能关联模板 id 模板会跨集群迁移，id 会变 ',\n    `type`        int(10)             NOT NULL DEFAULT '-1' COMMENT 'appid 的权限 1 读写 2 读 -1 未知',\n    `status`      int(10)             NOT NULL DEFAULT '1' COMMENT '状态 1 有效 0 无效',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_project_id` (`project_id`),\n    KEY `idx_status` (`status`),\n    KEY `idx_template_id` (`template`),\n    KEY `idx_type` (`type`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='project 模板信息';\n\n-- ----------------------------\n-- Table structure for user_metrics_config_info\n-- ----------------------------\nCREATE TABLE `user_metrics_config_info` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `user_name` varchar(255) NOT NULL COMMENT '用户账号',\n  `metric_info` text COMMENT '指标看板的配置',\n  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=1602 DEFAULT CHARSET=utf8 COMMENT='用户关联到指标的配置信息表';\n\n\n#权限点和角色的初始化数据\ninsert into logi_security_role_permission (id, role_id, permission_id, create_time, update_time, is_delete, app_name)\nvalues (1597, 1, 0, '2022-06-01 21:19:42.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1935, 1, 1593, '2022-06-14 17:41:03.0', '2022-08-27 17:36:58.0', 0, 'know_search'),\n       (1937, 1, 1637, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1939, 1, 1639, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1941, 1, 1641, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1943, 1, 1643, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1945, 1, 1645, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1947, 1, 1647, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1949, 1, 1649, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1951, 1, 1651, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1953, 1, 1653, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1955, 1, 1655, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1957, 1, 1657, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1959, 1, 1659, '2022-06-14 17:41:03.0', '2022-08-25 10:33:59.0', 1, 'know_search'),\n       (1961, 1, 1661, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1963, 1, 1597, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1965, 1, 1673, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1967, 1, 1675, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1969, 1, 1677, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1971, 1, 1679, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1973, 1, 1599, '2022-06-14 17:41:03.0', '2022-08-25 10:36:08.0', 1, 'know_search'),\n       (1975, 1, 1681, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1977, 1, 1683, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1979, 1, 1685, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1981, 1, 1687, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1983, 1, 1601, '2022-06-14 17:41:03.0', '2022-08-25 10:36:44.0', 1, 'know_search'),\n       (1985, 1, 1689, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1987, 1, 1691, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1989, 1, 1693, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1991, 1, 1695, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1993, 1, 1697, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1995, 1, 1699, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1997, 1, 1603, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1999, 1, 1701, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2001, 1, 1703, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2003, 1, 1705, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2005, 1, 1707, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2007, 1, 1709, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2009, 1, 1711, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2011, 1, 1713, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2013, 1, 1715, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2015, 1, 1717, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2017, 1, 1719, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2019, 1, 1721, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2021, 1, 1723, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2023, 1, 1605, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2025, 1, 1725, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2027, 1, 1727, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2029, 1, 1729, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2031, 1, 1731, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2033, 1, 1733, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2035, 1, 1735, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2037, 1, 1737, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2039, 1, 1739, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2041, 1, 1741, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2043, 1, 1743, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2045, 1, 1607, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2047, 1, 1745, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2049, 1, 1747, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2051, 1, 1749, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2053, 1, 1751, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2055, 1, 1753, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2057, 1, 1755, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2059, 1, 1609, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2061, 1, 1757, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2063, 1, 1855, '2022-06-14 17:41:03.0', '2022-08-25 10:34:13.0', 0, 'know_search'),\n       (2065, 1, 1857, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2067, 1, 1611, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2069, 1, 1759, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2071, 1, 1859, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2073, 1, 1861, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2075, 1, 1863, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2077, 1, 1865, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2079, 1, 1867, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2081, 1, 1613, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2083, 1, 1761, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2085, 1, 1615, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2087, 1, 1763, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2089, 1, 1619, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2091, 1, 1769, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2093, 1, 1771, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2095, 1, 1773, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2097, 1, 1621, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2099, 1, 1775, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2101, 1, 1777, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2103, 1, 1779, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2105, 1, 1781, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2107, 1, 1783, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2109, 1, 1785, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2111, 1, 1787, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2113, 1, 1789, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2115, 1, 1791, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2117, 1, 1793, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2119, 1, 1795, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2121, 1, 1797, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2123, 1, 1799, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2125, 1, 1801, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2127, 1, 1623, '2022-06-14 17:41:03.0', '2022-08-27 17:34:08.0', 0, 'know_search'),\n       (2129, 1, 1803, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2131, 1, 1805, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2133, 1, 1807, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2135, 1, 1809, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2137, 1, 1625, '2022-06-14 17:41:03.0', '2022-08-27 17:34:08.0', 0, 'know_search'),\n       (2139, 1, 1811, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2141, 1, 1813, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2143, 1, 1815, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2145, 1, 1817, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2147, 1, 1627, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2149, 1, 1819, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2151, 1, 1821, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2153, 1, 1629, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2155, 1, 1823, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2157, 1, 1825, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2159, 1, 1827, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2161, 1, 1829, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2163, 1, 1831, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2165, 1, 1631, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2167, 1, 1833, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2169, 1, 1835, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2171, 1, 1837, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2173, 1, 1839, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2175, 1, 1841, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2177, 1, 1633, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2179, 1, 1843, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2181, 1, 1845, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2183, 1, 1847, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2185, 1, 1849, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2187, 1, 1851, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2189, 1, 1635, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2191, 1, 1853, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2193, 2, 1595, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2195, 2, 1663, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2197, 2, 1665, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2199, 2, 1667, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2201, 2, 1669, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2203, 2, 1671, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2205, 2, 1601, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2207, 2, 1689, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2209, 2, 1691, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2211, 2, 1693, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2213, 2, 1695, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2215, 2, 1697, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2217, 2, 1699, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2219, 2, 1605, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2221, 2, 1725, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2223, 2, 1727, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2225, 2, 1729, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2227, 2, 1731, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2229, 2, 1733, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2231, 2, 1735, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2233, 2, 1737, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2235, 2, 1739, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2237, 2, 1741, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2239, 2, 1743, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2241, 2, 1609, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2243, 2, 1757, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2245, 2, 1855, '2022-06-14 18:08:56.0', '2022-08-25 10:33:12.0', 1, 'know_search'),\n       (2247, 2, 1857, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2249, 2, 1611, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2251, 2, 1759, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2253, 2, 1859, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2255, 2, 1861, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2257, 2, 1863, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2259, 2, 1865, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2261, 2, 1867, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2263, 2, 1613, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2265, 2, 1761, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2267, 2, 1615, '2022-06-14 18:08:56.0', '2022-08-25 20:27:55.0', 1, 'know_search'),\n       (2269, 2, 1763, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2271, 2, 1617, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2273, 2, 1765, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2275, 2, 1767, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2277, 2, 1631, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2279, 2, 1833, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2281, 2, 1835, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2283, 2, 1837, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2285, 2, 1839, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2287, 2, 1841, '2022-06-14 18:08:56.0', '2022-08-26 17:59:49.0', 1, 'know_search'),\n       (2643, 1, 1595, '2022-06-17 16:39:23.0', '2022-08-25 10:35:06.0', 1, 'know_search'),\n       (4505, 1, 1869, '2022-07-04 15:45:59.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (4507, 1, 1871, '2022-07-04 15:46:56.0', '2022-08-27 17:37:22.0', 0, 'know_search'),\n       (5275, 1, 1873, '2022-06-17 15:53:54.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5277, 2, 1873, '2022-06-17 15:53:54.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5349, 1, 1875, '2022-06-17 15:53:54.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5591, 1, 1759, '2022-08-11 10:39:01.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5593, 2, 1759, '2022-08-11 10:39:59.0', '2022-08-25 10:31:42.0', 0, 'know_search');\n#权限点初始化数据\ninsert into logi_security_permission (id, permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name)\nvalues  (1593, '物理集群', 0, 0, 1, '物理集群', '2022-05-24 18:08:22.0', '2022-08-24 20:07:31.0', 0, 'know_search'),\n        (1595, '我的集群', 0, 0, 1, '我的集群', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1597, '集群版本', 0, 0, 1, '集群版本', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1599, 'Gateway管理', 0, 0, 1, 'Gateway管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1601, '模板管理', 0, 0, 1, '模板管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1603, '模板服务', 0, 0, 1, '模板服务', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1605, '索引管理', 0, 0, 1, '索引管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1607, '索引服务', 0, 0, 1, '索引服务', '2022-05-24 18:08:22.0', '2022-05-24 18:24:16.0', 0, 'know_search'),\n        (1609, '索引查询', 0, 0, 1, '索引查询', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1611, '查询诊断', 0, 0, 1, '查询诊断', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1613, '集群看板', 0, 0, 1, '集群看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1615, '网关看板', 0, 0, 1, '网关看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1617, '我的申请', 0, 0, 1, '我的申请', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1619, '我的审批', 0, 0, 1, '我的审批', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1621, '任务列表', 0, 0, 1, '任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1623, '调度任务列表', 0, 0, 1, '调度任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1625, '调度日志', 0, 0, 1, '调度日志', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1627, '用户管理', 0, 0, 1, '用户管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1629, '角色管理', 0, 0, 1, '角色管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1631, '应用管理', 0, 0, 1, '应用管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1633, '平台配置', 0, 0, 1, '平台配置', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1635, '操作记录', 0, 0, 1, '操作记录', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1637, '查看集群列表及详情', 1593, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1639, '接入集群', 1593, 1, 2, '接入集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1641, '新建集群', 1593, 1, 2, '新建集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1643, '扩缩容', 1593, 1, 2, '扩缩容', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1645, '升级', 1593, 1, 2, '升级', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1647, '重启', 1593, 1, 2, '重启', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1649, '配置变更', 1593, 1, 2, '配置变更', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1651, 'Region划分', 1593, 1, 2, 'Region划分', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1653, 'Region管理', 1593, 1, 2, 'Region管理', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1655, '快捷命令', 1593, 1, 2, '快捷命令', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1657, '编辑', 1593, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1659, '绑定Gateway', 1593, 1, 2, '绑定Gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1661, '下线', 1593, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1663, '查看集群列表及详情', 1595, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1665, '申请集群', 1595, 1, 2, '申请集群', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1667, '编辑', 1595, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1669, '扩缩容', 1595, 1, 2, '扩缩容', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1671, '下线', 1595, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1673, '查看版本列表', 1597, 1, 2, '查看版本列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1675, '新增版本', 1597, 1, 2, '新增版本', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1677, '编辑', 1597, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1679, '删除', 1597, 1, 2, '删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1681, '查看Gateway 集群列表', 1599, 1, 2, '查看Gateway 集群列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1683, '接入gateway', 1599, 1, 2, '接入gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1685, '编辑', 1599, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1687, '下线', 1599, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1689, '查看模板列表及详情', 1601, 1, 2, '查看模板列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1691, '申请模板', 1601, 1, 2, '申请模板', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1693, '编辑', 1601, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1695, '下线', 1601, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1697, '编辑Mapping', 1601, 1, 2, '编辑Mapping', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1699, '编辑Setting', 1601, 1, 2, '编辑Setting', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1701, '查看模板列表', 1603, 1, 2, '查看模板列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1703, '开关：预创建', 1603, 1, 2, '开关：预创建', '2022-05-24 18:08:23.0', '2022-06-14 16:49:48.0', 0, 'know_search'),\n        (1705, '开关：过期删除', 1603, 1, 2, '开关：过期删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1707, '开关：冷热分离', 1603, 1, 2, '开关：冷热分离', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1709, '开关：pipeline', 1603, 1, 2, '开关：写入限流', '2022-05-24 18:08:23.0', '2022-06-14 16:49:49.0', 0, 'know_search'),\n        (1711, '开关：Rollover', 1603, 1, 2, '开关：Rollover', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1713, '查看DCDR链路', 1603, 1, 2, '查看DCDR链路', '2022-05-24 18:08:23.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1715, '创建DCDR链路', 1603, 1, 2, '创建DCDR链路', '2022-05-24 18:08:24.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1717, '清理', 1603, 1, 2, '清理', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1719, '扩缩容', 1603, 1, 2, '扩缩容', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1721, '升版本', 1603, 1, 2, '升版本', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1723, '批量操作', 1603, 1, 2, '批量操作', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1725, '查看索引列表及详情', 1605, 1, 2, '查看索引列表及详情', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1727, '编辑Mapping', 1605, 1, 2, '编辑Mapping', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1729, '编辑Setting', 1605, 1, 2, '编辑Setting', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1731, '禁用读', 1607, 1, 2, '禁用读', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1733, '禁用写', 1607, 1, 2, '禁用写', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1735, '设置别名', 1605, 1, 2, '设置别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1737, '删除别名', 1605, 1, 2, '删除别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1739, '关闭索引', 1607, 1, 2, '关闭索引', '2022-05-24 18:08:24.0', '2022-07-15 09:52:25.0', 0, 'know_search'),\n        (1741, '下线', 1605, 1, 2, '下线', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1743, '批量删除', 1605, 1, 2, '批量删除', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1745, '查看列表', 1607, 1, 2, '查看列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1747, '执行Rollover', 1607, 1, 2, '执行Rollover', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1749, '执行shrink', 1607, 1, 2, '执行shrink', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1751, '执行split', 1607, 1, 2, '执行split', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1753, '执行ForceMerge', 1607, 1, 2, '执行ForceMerge', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1755, '批量执行', 1607, 1, 2, '批量执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1757, 'DSL查询', 1609, 1, 2, 'DSL查询', '2022-05-24 18:08:24.0', '2022-06-14 16:39:48.0', 0, 'know_search'),\n        (1759, '查询模板', 0, 0, 1, '查看查询模板列表', '2022-05-24 18:08:24.0', '2022-08-11 10:37:43.0', 0, 'know_search'),\n        (1761, '查看集群看板', 1613, 1, 2, '查看集群看板', '2022-05-24 18:08:24.0', '2022-06-14 16:37:54.0', 0, 'know_search'),\n        (1763, '查看网关看板', 1615, 1, 2, '查看网关看板', '2022-05-24 18:08:24.0', '2022-06-14 16:38:14.0', 0, 'know_search'),\n        (1765, '查看我的申请列表', 1617, 1, 2, '查看我的申请列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1767, '撤回', 1617, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1769, '查看我的审批列表', 1619, 1, 2, '查看我的审批列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1771, '驳回', 1619, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-07-18 20:57:33.0', 0, 'know_search'),\n        (1773, '通过', 1619, 1, 2, '通过', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1775, '查看任务列表', 1621, 1, 2, '查看任务列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1777, '查看进度', 1621, 1, 2, '查看进度', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1779, '执行', 1621, 1, 2, '执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1781, '暂停', 1621, 1, 2, '暂停', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1783, '重试', 1621, 1, 2, '重试', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1785, '取消', 1621, 1, 2, '取消', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1787, '查看日志（子任务）', 1621, 1, 2, '查看日志（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1789, '重试（子任务）', 1621, 1, 2, '重试（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1791, '忽略（子任务）', 1621, 1, 2, '忽略（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1793, '查看详情（DCDR）', 1621, 1, 2, '查看详情（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1795, '取消（DCDR）', 1621, 1, 2, '取消（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1797, '重试（DCDR）', 1621, 1, 2, '重试（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1799, '强切（DCDR）', 1621, 1, 2, '强切（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1801, '返回（DCDR）', 1621, 1, 2, '返回（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1803, '查看任务列表', 1623, 1, 2, '查看任务列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1805, '查看日志', 1623, 1, 2, '查看日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1807, '执行', 1623, 1, 2, '执行', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1809, '暂停', 1623, 1, 2, '暂停', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1811, '查看调度日志列表', 1625, 1, 2, '查看调度日志列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1813, '调度详情', 1625, 1, 2, '调度详情', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1815, '执行日志', 1625, 1, 2, '执行日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1817, '终止任务', 1625, 1, 2, '终止任务', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1819, '查看用户列表', 1627, 1, 2, '查看用户列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1821, '分配角色', 1627, 1, 2, '分配角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1823, '查看角色列表', 1629, 1, 2, '查看角色列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1825, '编辑', 1629, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1827, '绑定用户', 1629, 1, 2, '绑定用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1829, '回收用户', 1629, 1, 2, '回收用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1831, '删除角色', 1629, 1, 2, '删除角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1833, '查看应用列表', 1631, 1, 2, '查看应用列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1835, '新建应用', 1631, 1, 2, '新建应用', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1837, '编辑', 1631, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1839, '删除', 1631, 1, 2, '删除', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1841, '访问设置', 1631, 1, 2, '访问设置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1843, '查看平台配置列表', 1633, 1, 2, '查看平台配置列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1845, '新增平台配置', 1633, 1, 2, '新增平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1847, '禁用平台配置', 1633, 1, 2, '禁用平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1849, '编辑平台配置', 1633, 1, 2, '编辑平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1851, '删除平台配置', 1633, 1, 2, '删除平台配置', '2022-05-24 18:08:26.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1853, '查看操作记录列表', 1635, 1, 2, '查看操作记录列表', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1855, 'Kibana', 1609, 1, 2, 'Kibana', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1857, 'SQL查询', 1609, 1, 2, 'SQL查询', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1859, '批量修改限流值', 1759, 1, 2, '批量修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1861, '禁用', 1759, 1, 2, '禁用', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1863, '修改限流值', 1759, 1, 2, '修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1865, '查看异常查询列表', 1611, 1, 2, '查看异常查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1867, '查看慢查询列表', 1611, 1, 2, '查看慢查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:21.0', 0, 'know_search'),\n        (1869, '新增角色', 1629, 1, 2, '新增角色', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1871, 'Dashboard', 0, 0, 1, '查看dashboard', '2022-05-24 18:08:26.0', '2022-08-27 17:35:50.0', 0, 'know_search'),\n        (1873, '新建索引', 1605, 1, 2, '新建索引', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1875, '查看dashboard', 1871, 1, 2, '查看dashboard', '2022-05-24 18:08:24.0', '2022-08-27 17:35:50.0', 0,\n         'know_search');\n#角色初始化数据\ninsert into logi_security_role (id, role_code, role_name, description, last_reviser, create_time, update_time,\n                                is_delete, app_name)\nvalues (1, 'r14715628', '管理员', '管理员', 'admin', '2022-06-01 21:19:42.0', '2022-07-06 22:23:59.0', 0,\n        'know_search'),\n       (2, 'r14481382', '资源 owner', '普通用户拥有的最大权限', 'admin', '2022-06-14 18:08:56.0',\n        '2022-07-06 20:36:31.0', 0, 'know_search');\n#初始化用户\ninsert into logi_security_user (id, user_name, pw, salt, real_name, phone, email, dept_id, is_delete,\n                                create_time, update_time, app_name)\nvalues (1, 'admin',\n        'V1ZkU2RHRlhOSGhOYWs0M1VVWmFjVk5xVW1oaE0zUmlTVEJCZUZGRFRtUm1WVzh5VlcxNGMyRkZRamw3UUZacVNqUmhhM3RiSTBBeVFDTmRmVW8yVW14c2FFQjl7QFZqSjRha3tbI0AzQCNdfUo2UmxsaEB9Mv{#cdRgJ45Lqx}3IubEW87!==',\n        '', 'admin', '18888888888', 'admin@12345.com', null, 0, '2022-05-26 05:46:12.0', '2022-08-26 09:06:19.0',\n        'know_search');\n#初始化用户和角色的关系\ninsert into logi_security_user_role (id, user_id, role_id, create_time, update_time, is_delete, app_name)\nvalues (1, 1, 2, '2022-08-26 19:54:22.0', '2022-08-26 19:54:22.0', 0, 'know_search'),\n       (2, 1, 1, '2022-08-30 21:05:17.0', '2022-08-30 21:05:17.0', 0, 'know_search');\n#项目和项目配置、es user 的关系\ninsert into project_arius_config (project_id, analyze_response_enable, is_source_separated, aggr_analyze_enable,\n                                  dsl_analyze_enable, slow_query_times, is_active, memo, create_time, update_time)\nvalues (1, 1, 0, 1, 1, 1000, 1, '超级应用', '2022-06-14 18:52:08.0', '2022-08-27 23:13:14.0'),\n       (2, 1, 0, 1, 1, 1000, 1, '元数据模版应用 不可以被删除', '2022-08-25 11:18:45.0', '2022-08-25 11:18:45.0');\ninsert into logi_security_project (id, project_code, project_name, description, dept_id, running, create_time,\n                                   update_time, is_delete, app_name)\nvalues (1, 'p14000143', 'SuperApp', '超级应用', 0, 1, '2022-05-26 05:49:08.0', '2022-08-24 11:09:49.0', 0,\n        'know_search'),\n       (2, 'p18461793', '元数据模版应用 _ 误删', '元数据模版应用 不可以被删除', 0, 1, '2022-08-25 11:06:04.0',\n        '2022-08-25 11:18:45.0', 0, 'know_search');\ninsert into arius_es_user (id, index_exp, data_center, is_root, memo, ip, verify_code, is_active,\n                           query_threshold, cluster, responsible, search_type, create_time, update_time,\n                           project_id, is_default_display)\nvalues (1, null, 'cn', 1, '管理员 APP', '', 'azAWiJhxkho33ac', 1, 100, 'logi-elasticsearch-7.6.0', 'admin', 1,\n        '2022-05-26 09:35:38.0', '2022-06-23 00:16:47.0', 1, 1),\n       (2, null, 'cn', 0, '元数据模版 APP', '', 'vkDgPEfD3jQJ1YY', 1, 1000, '', null, 0, '2022-07-05 08:16:17.0',\n        '2022-08-25 21:48:58.0', 2, 0);\n\n\n## 配置初始化数据\ninsert into arius_config_info (id, value_group, value_name, value, edit, dimension, status, memo,\n                                               create_time, update_time, search_time)\nvalues (187, 'arius.cache.switch', 'logic.template.cache.enable', 'true', 1, -1, -1, '逻辑模板缓存是否开启',\n        '2021-09-01 20:37:47.0', '2021-11-29 14:57:47.0', '2021-09-01 20:37:47.0'),\n       (189, 'arius.cache.switch', 'physical.template.cache.enable', 'true', 1, -1, -1,\n        '获取物理模板列表是否开启全局缓存', '2021-09-01 20:41:22.0', '2021-11-29 14:57:45.0', '2021-09-01 20:41:22.0'),\n       (191, 'arius.cache.switch', 'cluster.phy.cache.enable', 'true', 1, -1, -1, '获取物理集群列表是否开启全局缓存',\n        '2021-09-01 20:42:31.0', '2021-11-29 14:57:42.0', '2021-09-01 20:42:31.0'),\n       (193, 'arius.cache.switch', 'cluster.logic.cache.enable', 'true', 1, -1, -1, '获取逻辑集群列表是否开启全局缓存',\n        '2021-09-01 20:43:08.0', '2021-11-29 14:57:39.0', '2021-09-01 20:43:08.0'),\n       (1217, 'arius.meta.monitor', 'nodestat.collect.concurrent', 'true', 1, -1, -1, '', '2021-11-18 20:24:54.0',\n        '2021-11-19 16:05:39.0', '2021-11-18 20:24:54.0'),\n       (1223, 'arius.common.group', 'app.default.read.auth.indices', '\"\"', 1, -1, 2, 'app 可读写的权限 ',\n        '2021-12-15 20:17:06.0', '2021-12-16 11:17:26.0', '2021-12-15 20:17:06.0'),\n       (1225, 'arius.common.group', 'delete.expire.index.ahead.clusters', '\"\"', 1, -1, 2, ' 删除过期权限 ',\n        '2021-12-15 20:17:48.0', '2021-12-16 11:17:24.0', '2021-12-15 20:17:48.0'),\n       (1227, 'arius.common.group', 'operate.index.ahead.seconds', '2 * 60 * 60', 1, -1, 2, '索引操作提前时间',\n        '2021-12-15 20:18:37.0', '2021-12-16 11:17:22.0', '2021-12-15 20:18:37.0'),\n       (1229, 'arius.common.group', 'platform.govern.admin.hot.days', '-1', 1, -1, 2, '平台治理导入热存的天数',\n        '2021-12-15 20:19:13.0', '2021-12-16 11:17:19.0', '2021-12-15 20:19:13.0'),\n       (1231, 'arius.common.group', 'quota.dynamic.limit.black.appIds', 'none', 1, -1, 2, 'appid 黑名单控制',\n        '2021-12-15 20:20:11.0', '2021-12-16 11:17:17.0', '2021-12-15 20:20:11.0'),\n       (1233, 'arius.common.group', 'quota.dynamic.limit.black.cluster', '\"\"', 1, -1, 2, 'cluster 黑名单控制 ',\n        '2021-12-15 20:20:39.0', '2021-12-16 11:17:15.0', '2021-12-15 20:20:39.0'),\n       (1235, 'arius.common.group', 'quota.dynamic.limit.black.logicId', 'none', 1, -1, 2, '模板黑名单控制',\n        '2021-12-15 20:21:21.0', '2021-12-16 11:17:12.0', '2021-12-15 20:21:21.0'),\n       (1237, 'arius.common.group', 'arius.wo.auto.process.create.template.disk.maxG', '10.0', 1, -1, 2,\n        '模板创建时设置的磁盘空间最大值', '2021-12-15 20:21:49.0', '2021-12-16 11:15:12.0', '2021-12-15 20:21:49.0'),\n       (1239, 'arius.common.group', 'request.interceptor.switch.open', 'true', 1, -1, 2, '请求拦截开关',\n        '2021-12-15 20:22:14.0', '2021-12-16 11:15:10.0', '2021-12-15 20:22:14.0'),\n       (1241, 'arius.common.group', 'arius.didi.t2.leader.mail', '\"\"', 1, -1, 2, 'didi 领导者邮箱 ',\n        '2021-12-15 20:22:40.0', '2021-12-16 11:15:07.0', '2021-12-15 20:22:40.0'),\n       (1243, 'arius.common.group', 'defaultDay', '\"\"', 1, -1, 2, ' 默认 hotDay 值 ', '2021-12-15 20:23:17.0',\n        '2021-12-16 11:15:04.0', '2021-12-15 20:23:17.0'),\n       (1245, 'arius.quota.config.group', 'arius.quota.config.tps.per.cpu.with.replica', '1000.0', 1, -1, 2,\n        '资源管控 cpu 项', '2021-12-15 20:23:56.0', '2021-12-16 11:15:01.0', '2021-12-15 20:23:56.0'),\n       (1247, 'arius.quota.config.group', 'arius.quota.config.tps.per.cpu.NO.replica', '2300.0', 1, -1, 2,\n        '资源管控 cpu 项', '2021-12-15 20:24:27.0', '2021-12-16 11:14:58.0', '2021-12-15 20:24:27.0'),\n       (1249, 'arius.quota.config.group', 'arius.quota.config.cost.per.g.per.month', '1.06', 1, -1, 2,\n        '资源配置模板费用', '2021-12-15 20:24:59.0', '2021-12-16 11:14:56.0', '2021-12-15 20:24:59.0'),\n       (1251, 'arius.meta.monitor.group', 'nodestat.collect.concurrent', 'fasle', 1, -1, 2, '节点状态信息是否并行采集',\n        '2021-12-15 20:25:35.0', '2022-08-26 18:10:50.0', '2021-12-15 20:25:35.0'),\n       (1253, 'arius.meta.monitor.group', 'indexstat.collect.concurrent', 'fasle', 1, -1, 2, '索引状态信息是否并行采集',\n        '2021-12-15 20:26:00.0', '2022-08-26 18:10:45.0', '2021-12-15 20:26:00.0'),\n       (1255, 'arius.common.group', 'indices.recovery.ceph_max_bytes_per_sec', '10MB', 1, -1, 2, '单节点分片恢复的速率',\n        '2021-12-15 21:33:29.0', '2022-04-08 17:43:14.0', '2021-12-15 21:33:29.0'),\n       (1257, 'arius.common.group', 'cluster.routing.allocation.node_concurrent_incoming_recoveries', '2', 1, -1, 2,\n        '一个节点上允许多少并发的传入分片还原, 表示为传入还原', '2021-12-16 14:41:51.0', '2021-12-16 14:42:24.0',\n        '2021-12-16 14:41:51.0'),\n       (1259, 'arius.common', 'cluster.routing.allocation.node_concurrent_outgoing_recoveries', '2', 1, -1, 2,\n        '一个节点上允许多少并发的传入分片还原, 传出还原', '2021-12-16 14:42:15.0', '2022-02-22 11:11:48.0',\n        '2021-12-16 14:42:15.0'),\n       (1585, 'test.test', 'testt', '21', 1, -1, -1, '请忽略 2221', '2022-01-13 14:25:40.0', '2022-01-15 16:27:05.0',\n        '2022-01-13 14:25:40.0'),\n       (1587, 'zptest', 'test', '<script>alert(1)</script>', 1, -1, -1, 'alert(1)', '2022-01-18 16:14:12.0',\n        '2022-01-18 16:15:49.0', '2022-01-18 16:14:12.0'),\n       (1589, 'test1ddd', 'dd ddd', 'dssdddd', 1, -1, -1, 'sddsdssd', '2022-01-26 11:39:23.0', '2022-01-26 11:39:42.0',\n        '2022-01-26 11:39:23.0'),\n       (1591, 'yyftemptest-01s', 'yyftemptest-01d', '', 1, -1, -1, '', '2022-03-01 16:44:12.0', '2022-03-01 16:44:39.0',\n        '2022-03-01 16:44:12.0'),\n       (1593, 'test1', 's', '', 1, -1, -1, '', '2022-03-07 11:37:39.0', '2022-03-07 11:37:43.0',\n        '2022-03-07 11:37:39.0'),\n       (1595, 'test1', '22',\n        'm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2', 1, -1, -1, '',\n        '2022-03-15 11:19:49.0', '2022-03-15 11:20:08.0', '2022-03-15 11:19:49.0'),\n       (1597, 'r''r', '22', 'EE', 1, -1, -1, 'EEEE', '2022-03-15 12:19:26.0', '2022-08-01 08:52:43.0',\n        '2022-03-15 12:19:26.0'),\n       (1599, 'test1', 'testtemp1', 'uu''uuuu', 1, -1, -1, '那你能', '2022-03-29 15:30:59.0', '2022-03-29 15:31:26.0',\n        '2022-03-29 15:30:59.0'),\n       (1601, 'yyyYF223', 'WEFWfwef', '', 1, -1, -1, '', '2022-03-31 19:31:01.0', '2022-08-01 08:52:47.0',\n        '2022-03-31 19:31:01.0'),\n       (1603, 'yyftestYY0411-01', 'yyftestYY0411-01', 'sdsd', 1, -1, -1, 'sdsdcsg 参赛暗杀诉法设计风格！@',\n        '2022-04-11 15:22:22.0', '2022-04-11 15:26:29.0', '2022-04-11 15:22:22.0'),\n       (1607, 'arius.dashboard.threshold.group', 'index.segment.num_threshold',\n        '{\"name\":\" 索引 Segments 个数 \",\"metrics\":\"segmentNum\",\"unit\":\" 个 \",\"compare\":\">\",\"value\":100}', 1, -1, 1,\n        '索引 Segment 个数阈值定义', '2022-06-17 09:52:11.0', '2022-08-27 16:05:06.0', '2022-06-17 09:52:11.0'),\n       (1609, 'arius.dashboard.threshold.group', 'index.template.segment_num_threshold',\n        '{\"name\":\" 模板 Segments 个数 \",\"metrics\":\"segmentNum\",\"unit\":\" 个 \",\"compare\":\">\",\"value\":700}', 1, -1, 1,\n        '索引模板 [Segment 个数阈值] 定义', '2022-06-17 09:53:34.0', '2022-08-27 19:01:57.0', '2022-06-17 09:53:34.0'),\n       (1611, 'arius.dashboard.threshold.group', 'index.segment.memory_size_threshold',\n        '{\"name\":\" 索引 Segments 内存大小 \",\"metrics\":\"segmentMemSize\",\"unit\":\"MB\",\"compare\":\">\",\"value\":50}', 1, -1, 1,\n        '索引 [Segment 内存大小阈值] 定义', '2022-06-17 09:54:20.0', '2022-08-27 22:24:52.0', '2022-06-17 09:54:20.0'),\n       (1613, 'arius.dashboard.threshold.group', 'index.template.segment_memory_size_threshold',\n        '{\"name\":\" 模板 Segments 内存大小 \",\"metrics\":\"segmentMemSize\",\"unit\":\"MB\",\"compare\":\">\",\"value\":100}', 1, -1,\n        1, '索引模板 [Segment 内存大小阈值] 定义', '2022-06-17 09:54:50.0', '2022-08-27 19:18:54.0',\n        '2022-06-17 09:54:50.0'),\n       (1617, 'arius.dashboard.threshold.group', 'node.shard.num_threshold',\n        '{\"name\":\" 节点分片个数 \",\"metrics\":\"shardNum\",\"unit\":\" 个 \",\"compare\":\">\",\"value\":1000}', 1, -1, 1,\n        '节点 [分片个数阈值] 定义', '2022-06-17 10:01:40.0', '2022-08-27 19:09:44.0', '2022-06-17 10:01:40.0'),\n       (1619, 'arius.dashboard.threshold.group', 'index.shard.small_threshold',\n        '{\"name\":\" 小 shard 索引列表 \",\"metrics\":\"shardSize\",\"unit\":\"MB\",\"compare\":\"<\",\"value\":1000}', 1, -1, 1,\n        '索引 [小 Shard 阈值] 定义', '2022-06-17 16:11:53.0', '2022-08-27 19:04:19.0', '2022-06-17 16:11:53.0'),\n       (1623, 'settingGroup', 'name', 'value', 1, -1, -1, 'test', '2022-06-23 14:17:56.0', '2022-06-23 15:47:26.0',\n        '2022-06-23 14:17:56.0'),\n       (1625, 'group11', 'name1', 'value1', 1, -1, -1, 'des-edit', '2022-06-23 15:22:51.0', '2022-06-24 09:40:51.0',\n        '2022-06-23 15:22:51.0'),\n       (1627, 'arius.common.group', 'cluster.node.specification_list', '16c-64g-3072g,16c-48g-3071g,1c-48g-3071g,', 1,\n        -1, 1, '节点规格列表，机型列表', '2022-07-05 14:10:27.0', '2022-07-18 15:01:29.0', '2022-07-05 14:10:27.0'),\n       (1629, 'ccccccccccccccdcdccccccccccccccdcdccccccccccccccdb', 'dccccccccccccccdcdcccccccc', 'vjh', 1, -1, -1,\n        'cdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccc',\n        '2022-07-05 15:27:38.0', '2022-07-05 15:28:09.0', '2022-07-05 15:27:38.0'),\n       (1631, '2', '3', '', 1, -1, -1, '', '2022-07-06 15:26:45.0', '2022-07-06 15:26:58.0', '2022-07-06 15:26:45.0'),\n       (1633, 'arius.common.group', 'cluster.data.center_list', 'cn,en', 1, -1, 1, '数据中心列表',\n        '2022-07-06 16:14:03.0', '2022-08-27 19:11:25.0', '2022-07-06 16:14:03.0'),\n       (1635, 'arius.common.group', 'cluster.package.version_list', '7.6.1.1,6.6.6.6,7.6.1.2', 1, -1, 1,\n        '系统预制支持的版本', '2022-07-06 16:17:25.0', '2022-07-06 16:17:25.0', '2022-07-06 16:17:25.0'),\n       (1637, 'template.time.type', 'format', '[\n  \"yyyy-MM-dd HH:mm:ss\",\n  \"yyyy-MM-dd HH:mm:ss.SSS\",\n  \"yyyy-MM-dd''T''HH:mm:ss\",\n  \"yyyy-MM-dd''T''HH:mm:ss.SSS\",\n  \"yyyy-MM-dd HH:mm:ss.SSS Z\",\n  \"yyyy/MM/dd HH:mm:ss\",\n  \"epoch_seconds\",\n  \"epoch_millis\"\n]', 1, -1, 1, ' 新建模版的时间格式 ', '2022-07-07 16:15:37.0', '2022-07-07 16:15:37.0', '2022-07-07 16:15:37.0'),\n       (1639, 'arius.cluster.blacklist', 'cluster.phy.name', 'didi-cluster-test', 1, -1, 1,\n        '滴滴内部测试环境集群, 禁止任何编辑删除新增操作', '2022-07-07 17:58:02.0', '2022-07-07 18:44:42.0',\n        '2022-07-07 17:58:02.0'),\n       (1641, 'arius.common.group', 'cluster.resource.type_list', '信创,acs,vmware', 1, -1, 1,\n        '所属资源类型列表,IaaS 平台类型列表', '2022-07-07 19:13:13.0', '2022-08-27 19:11:50.0',\n        '2022-07-07 19:13:13.0'),\n       (1643, '55', '666', '1', 1, -1, -1, '143', '2022-07-13 16:59:41.0', '2022-07-13 17:01:48.0',\n        '2022-07-13 16:59:41.0'),\n       (1645, 'arius.common.group', 'index.rollover.threshold', '0.0001', 1, -1, 1, '主分片大小达到 1G 后升版本',\n        '2022-07-15 21:03:12.0', '2022-07-22 16:53:26.0', '2022-07-15 21:03:12.0'),\n       (1647, 'yyftemptest-01', 'yyf', 'sdv', 1, -1, -1, 'sdv', '2022-07-18 15:02:08.0', '2022-07-18 15:02:24.0',\n        '2022-07-18 15:02:08.0'),\n       (1649, 'arius.common.group', 'cluster.node.count_list', '2,4,6,10', 1, -1, 1, '集群节点个数列表',\n        '2022-07-18 15:22:33.0', '2022-08-27 19:13:09.0', '2022-07-18 15:22:33.0'),\n       (1651, '调度 yyfceshi', '是对的 s''d''c''d 测试', '等待的', 1, -1, -1, '的士速递', '2022-07-20 17:06:43.0',\n        '2022-07-20 17:10:39.0', '2022-07-20 17:06:43.0'),\n       (1653, 'arius.common.group', 'arius.system.template', '[\n    \"arius.dsl.analyze.result\",\n    \"arius.dsl.metrics\",\n    \"arius.dsl.template\",\n    \"arius.gateway.join\",\n    \"arius_stats_index_info\",\n    \"arius_stats_node_info\",\n    \"arius.template.access\",\n    \"arius_cat_index_info\",\n    \"arius_gateway_metrics\",\n    \"arius_stats_cluster_info\",\n    \"arius_stats_cluster_task_info\",\n    \"arius_stats_dashboard_info\",\n    \"arius.appid.template.access\"\n]', 1, -1, 1, ' 系统核心模版集合 ', '2022-07-21 12:25:48.0', '2022-07-21 12:30:06.0', '2022-07-21 12:25:48.0'),\n       (1655, 'ds12', 'sd34', 'sdsddsd', 1, -1, -1, 'ds78', '2022-07-21 17:00:44.0', '2022-08-01 08:52:35.0',\n        '2022-07-21 17:00:44.0'),\n       (1656, 'arius.dashboard.threshold.group', 'index.mapping.num_threshold',\n        '{\"name\":\" 索引 Mapping 个数 \",\"metrics\":\"mappingNum\",\"unit\":\" 个 \",\"compare\":\">\",\"value\":100}', 1, -1, 1,\n        '索引 [Mapping 个数阈值] 定义', '2022-07-28 15:50:59.0', '2022-08-27 18:36:48.0', '2022-07-28 15:50:59.0'),\n       (1657, 'arius.common.group', 'cluster.shard.big_threshold', '10', 1, -1, 1,\n        '用于设置集群看板中的大 Shard 阈值，单位为 gb，大于这个值就认为是大 shard', '2022-07-28 17:49:59.0',\n        '2022-08-26 18:08:56.0', '2022-07-28 17:49:59.0'),\n       (1659, 'arius.dashboard.threshold.group', 'cluster.shard.num_threshold',\n        '{\"name\":\" 集群 shard 个数 \",\"metrics\":\"shardNum\",\"unit\":\" 个 \",\"compare\":\">\",\"value\":2000}', 1, -1, 1,\n        '集群 [Shard 个数阈值] 定义', '2022-08-05 15:58:22.0', '2022-08-27 18:31:22.0', '2022-08-05 15:58:22.0'),\n       (1661, 'arius.dashboard.threshold.group', 'cluster.metric.collector.delayed_threshold',\n        '{\"name\":\"node_status 指标采集延时 \",\"metrics\":\"clusterElapsedTimeGte5Min\",\"unit\":\"m\",\"compare\":\">\",\"value\":5}',\n        1, -1, 1, '集群 [指标采集延时阈值] 定义', '2022-08-10 14:10:47.0', '2022-08-27 18:28:59.0',\n        '2022-08-10 14:10:47.0'),\n       (1663, 'arius.dashboard.threshold.group', 'node.disk.used_percent_threshold',\n        '{\"name\":\" 磁盘利用率 \",\"metrics\":\"largeDiskUsage\",\"unit\":\"%\",\"compare\":\">\",\"value\":40}', 1, -1, 1,\n        '节点 [磁盘利用率阈值] 定义', '2022-08-25 14:50:41.0', '2022-08-27 19:20:14.0', '2022-08-25 14:50:41.0'),\n       (1665, 'arius.dashboard.threshold.group', 'node.jvm.heap.used_percent_threshold',\n        '{\"name\":\" 堆内存利用率 \",\"metrics\":\"largeHead\",\"unit\":\"%\",\"compare\":\">\",\"value\":35}', 1, -1, 1,\n        '节点 [堆内存利用率阈值] 定义', '2022-08-25 16:45:33.0', '2022-08-27 19:20:20.0', '2022-08-25 16:45:33.0'),\n       (1666, 'arius.dashboard.threshold.group', 'node.cpu.used_percent_threshold',\n        '{\"name\":\"CPU 利用率红线 \",\"metrics\":\"largeCpuUsage\",\"unit\":\"%\",\"compare\":\">\",\"value\":40}', 1, -1, 1,\n        '节点 [CPU 利用率阈值] 定义', '2022-08-25 16:45:33.0', '2022-08-27 19:20:08.0', '2022-08-25 16:45:33.0'),\n       (1667, 'arius.dashboard.threshold.group', 'node.jvm.heap.used_percent_time_duration_threshold',\n        '{\"name\":\"node.jvm.heap.used_percent_threshold_time_duration\",\"metrics\":\"jvmHeapUsedPercentThresholdTimeDuration\",\"unit\":\"m\",\"compare\":\">\",\"value\":10}',\n        1, -1, 1, '节点堆内存利用率阈值的 [持续时间]', '2022-08-25 16:45:33.0', '2022-08-27 15:44:06.0',\n        '2022-08-25 16:45:33.0'),\n       (1668, 'arius.dashboard.threshold.group', 'node.cpu.used_percent_threshold_time_duration_threshold',\n        '{\"name\":\"node.large.cpu.used.percent.time.threshold\",\"metrics\":\"largeCpuUsage\",\"unit\":\"s\",\"compare\":\">\",\"value\":60}',\n        1, -1, 1, '节点 CPU 利用率超阈值的 [持续时间]', '2022-08-25 16:45:33.0', '2022-08-27 19:28:08.0',\n        '2022-08-25 16:45:33.0'),\n       (1669, 'arius.dashboard.threshold.group', 'index.shard.big_threshold',\n        '{\"name\":\"index.shard.big_threshold\",\"metrics\":\"shardSize\",\"unit\":\"G\",\"compare\":\">\",\"value\":20}', 1, -1, 1,\n        '索引 [大 shard 阈值] 定义', '2022-08-26 15:25:07.0', '2022-08-29 10:28:24.0', '2022-08-26 15:25:07.0'),\n       (1671, 'arius.template.group', 'logic.template.business_type',\n        '系统数据, 日志数据, 业务上报数据,RDS 数据, 离线导入数据,testset', 1, -1, 1, '模板业务类型',\n        '2022-08-26 18:02:47.0', '2022-08-27 19:14:56.0', '2022-08-26 18:02:47.0'),\n       (1673, 'arius.common.group', 'logic.template.time_format_list',\n        'yyyy-MM-dd HH:mm:ss,yyyy-MM-dd HH:mm:ss.SSS,yyyy-MM-dd HH:mm:ss.SSS Z,yyyy-MM-dd''T''HH:mm:ss,yyyy-MM-dd''T''HH:mm:ss.SSS,yyyy-MM-dd''T''HH:mm:ssZ,yyyy-MM-dd''T''HH:mm:ss.SSSZ,yyyy/MM/dd HH:mm:ss,epoch_second,epoch_millis,yyyy-MM-dd',\n        1, -1, 1, '模板时间格式列表', '2022-08-26 18:06:07.0', '2022-08-27 19:14:06.0', '2022-08-26 18:06:07.0'),\n       (1675, 'arius.common.group', 'history.template.physic.indices.allocation.is_effective', 'ture', 1, -1, 1,\n        '历史索引模板 shard 分配是否自动调整', '2022-08-26 18:07:53.0', '2022-08-26 18:07:53.0',\n        '2022-08-26 18:07:53.0');\n\n####\ninsert into es_package (id, url, es_version, creator, `release`, manifest, `desc`, create_time, update_time, delete_flag)\nvalues  (1, 'registry.xiaojukeji.com/didibuild/elasticsearch-image.hnb-pre-v.arius.data-online.fd.didi.com.centos72:9721f7f4', '7.6.1.302', 'linyunan', 0, '3', '', '2021-03-30 20:35:03.0', '2021-10-11 16:07:51.0', 1),\n        (3, 'registry.xiaojukeji.com/didibuild/elasticsearch-image.hnb-pre-v.arius.data-online.fd.didi.com.centos72:06b79e62', '7.6.0.1203', 'linyunan', 0, '3', '', '2021-04-01 14:56:42.0', '2021-04-01 14:56:42.0', 0),\n        (15, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/elasticsearch.tar.gz', '7.6.0.1401', 'linyunan', 0, '4', '', '2021-06-21 14:56:09.0', '2021-09-14 15:33:36.0', 0),\n        (17, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/elasticsearch.tar.gz', '7.6.0.1402', 'admin', 0, '4', 'fdsafsd2', '2021-06-21 14:57:53.0', '2021-10-27 10:34:09.0', 0),\n        (23, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.6.0.13%404', '7.6.0.13', 'admin', 0, '4', 'ss', '2021-10-28 12:28:07.0', '2021-10-28 12:30:24.0', 1),\n        (27, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/234.2.3%404', '234.2.3', 'admin', 0, '4', 'dd', '2021-10-28 19:47:08.0', '2021-10-28 19:55:01.0', 1),\n        (29, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/234.2.4%404.tar.gz', '234.2.4', 'admin', 0, '4', 'dd', '2021-10-28 19:54:38.0', '2021-11-23 14:36:35.0', 1),\n        (31, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.1.2.1%404.tar.gz', '2.1.2.1', 'admin', 0, '4', 'yyf测试', '2021-11-01 10:41:20.0', '2021-11-01 17:13:38.0', 1),\n        (33, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.12.3.4%404.tar.gz', '2.12.3.4', 'admin', 0, '4', 'ceshi ', '2021-11-01 17:19:04.0', '2021-11-02 11:15:43.0', 1),\n        (35, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.3.4.5%404.tar.gz', '2.3.4.5', 'admin', 0, '4', 'ceshi ', '2021-11-01 17:19:59.0', '2021-11-02 11:15:41.0', 1),\n        (37, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/4.1.2.2%404.tar.gz', '4.1.2.2', 'admin', 0, '4', '测试沃尔特与会计银行股份大晚上是的法规环境股份的地方VG东风股份更好地发挥过', '2021-11-02 10:56:31.0', '2021-11-02 11:15:38.0', 1),\n        (39, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/3.3.3.3%404.tar.gz', '3.3.3.3', 'admin', 0, '4', '测试', '2021-11-02 11:14:49.0', '2021-11-02 11:15:35.0', 1),\n        (41, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.1.1.2%404.tar.gz', '1.1.1.2', 'admin', 0, '4', '测试测试', '2021-11-08 18:27:02.0', '2021-11-08 18:29:20.0', 1),\n        (43, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/8.8.8.8%404.tar.gz', '8.8.8.8', 'admin', 0, '4', '测试请忽略、', '2021-11-17 14:47:20.0', '2021-11-23 14:36:33.0', 1),\n        (45, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.7.7.7%404.tar.gz', '7.7.7.7', 'admin', 0, '4', '测试', '2021-11-18 14:48:38.0', '2021-11-23 14:36:30.0', 1),\n        (47, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.3.4%404.tar.gz', '1.2.3.4', 'admin', 0, '4', '', '2021-11-19 19:08:06.0', '2021-11-23 14:36:27.0', 1),\n        (49, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.9.89.1%404.tar.gz', '1.9.89.1', 'admin', 0, '4', '', '2021-11-19 19:08:55.0', '2021-11-23 14:36:23.0', 1),\n        (51, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.2.2.2%404.tar.gz', '2.2.2.3', 'admin', 0, '4', '测试测试测试', '2021-11-25 18:00:47.0', '2021-11-25 20:21:44.0', 1),\n        (53, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.2.2.5-4.tar.gz', '2.2.2.5', 'admin', 0, '4', null, '2021-11-25 20:16:51.0', '2021-11-25 20:17:23.0', 1),\n        (55, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.6.6-4.tar.gz', '6.6.6.6', 'admin', 0, '4', '测试', '2021-11-26 10:39:19.0', '2021-11-26 10:39:45.0', 1),\n        (57, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.6.6-4.tar.gz', '6.6.6.5', 'admin', 0, '4', '测试请忽略人', '2021-12-21 10:49:03.0', '2021-12-21 10:49:38.0', 0),\n        (89, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.10.2.0-4.tar.gz', '7.10.2.0', 'admin', 0, '4', 'test', '2021-12-25 11:56:11.0', '2022-06-22 14:38:24.0', 0),\n        (203, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.1.0-4.tar.gz', '6.6.1.0', 'admin', 0, '4', 'ssd', '2022-01-10 19:14:54.0', '2022-06-13 17:32:19.0', 1),\n        (205, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.2.0-4.tar.gz', '6.6.2.0', 'admin', 0, '4', 'ss', '2022-01-10 20:23:07.0', '2022-01-10 20:23:07.0', 0),\n        (211, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.3.3.5-4.tar.gz', '2.3.3.5', 'admin', 0, '4', 'ss', '2022-01-28 15:59:57.0', '2022-01-28 16:56:42.0', 1),\n        (213, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.3.3.6-4.tar.gz', '2.3.3.6', 'admin', 0, '4', 'dd', '2022-01-28 16:58:46.0', '2022-01-28 16:58:46.0', 0),\n        (215, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.1.1.1-4.tar.gz', '1.1.1.1', 'admin', 0, '4', '测试请忽略，使用完毕，QA会删除', '2022-02-18 10:49:07.0', '2022-03-23 19:55:04.0', 1),\n        (217, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.2.2.2-4.tar.gz', '2.2.2.2', 'admin', 0, '4', '测试请忽略，使用完毕，QA会删除', '2022-02-18 10:49:37.0', '2022-05-17 17:38:47.0', 1),\n        (219, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/3.3.3.3-4.tar.gz', '3.3.3.3', 'admin', 0, '4', '测试请忽略，使用完毕，QA会删除哦f', '2022-02-18 10:50:03.0', '2022-03-29 14:32:32.0', 1),\n        (221, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/4.4.4.4-4.tar.gz', '4.4.4.4', 'admin', 0, '4', '测试', '2022-03-01 11:32:58.0', '2022-03-01 11:33:05.0', 1),\n        (223, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.7.7.7-4.tar.gz', '7.7.7.7', 'admin', 0, '4', 'ceshi ', '2022-03-01 17:40:56.0', '2022-05-23 10:17:09.0', 1),\n        (225, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/99.2.2.2222-4.tar.gz', '99.2.2.2222', 'admin', 0, '4', '测试请忽略', '2022-03-29 14:34:50.0', '2022-03-29 14:47:04.0', 1),\n        (227, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/10.20.30.40-4.tar.gz', '10.20.30.40', 'admin', 0, '4', '测试请忽略', '2022-03-29 14:57:14.0', '2022-03-29 14:59:26.0', 1),\n        (233, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.3.3333-4.tar.gz', '1.2.3.3333', 'yyfQA_admin', 0, '4', '测试请忽略', '2022-04-11 14:18:18.0', '2022-07-04 17:25:18.0', 0),\n        (257, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/elasticsearch.tar.gz', '7.6.2.1', '', 0, '4', 'test', '2021-06-21 14:56:09.0', '2022-06-24 18:16:58.0', 1),\n        (259, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.2.1-4.tar.gz', '1.2.2.1', '', 0, '4', 'test0624', '2022-06-24 18:07:38.0', '2022-06-24 18:16:53.0', 1),\n        (261, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/9.9.9.9-4.tar.gz', '9.9.9.9', '', 0, '4', '111', '2022-06-24 18:08:22.0', '2022-06-24 18:16:50.0', 1),\n        (263, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.1.1.3-4.tar.gz', '1.1.1.4', 'yyfQA_admin', 0, '4', 'test111服务范围框架发改委开复工文件和管控', '2022-06-24 18:17:43.0', '2022-07-05 10:10:46.0', 0),\n        (265, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/9.9.9.9-4.tar.gz', '9.9.9.9', 'admin', 0, '4', 'test', '2022-06-27 10:11:50.0', '2022-08-07 10:45:40.0', 1),\n        (267, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.6.2.1-4.tar.gz', '7.6.2.1', 'admin', 0, '4', 'test1', '2022-06-27 18:26:06.0', '2022-07-07 12:13:01.0', 0),\n        (281, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.6.0.1403-4.tar.gz', '7.6.0.1403', 'admin', 0, '4', '7.6.0.1401', '2022-07-07 16:15:42.0', '2022-07-07 16:15:42.0', 0),\n        (283, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/5.6.2.0-4.tar.gz', '5.6.2.0', 'yyfQA_admin', 0, '4', '开源版本', '2022-07-12 10:58:51.0', '2022-07-26 15:35:53.0', 1),\n        (285, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.1.0-4.tar.gz', '6.6.1.0', 'yyfQA_admin', 0, '4', '开源版本', '2022-07-12 10:59:32.0', '2022-07-12 10:59:32.0', 0),\n        (287, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/8.0.1.0-4.tar.gz', '8.0.1.0', 'admin', 0, '4', '开源版本', '2022-07-13 16:51:07.0', '2022-08-08 18:08:44.0', 0),\n        (289, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.3.4-4.tar.gz', '1.2.3.4', 'admin', 0, '4', '的', '2022-07-21 20:30:03.0', '2022-07-21 20:30:16.0', 1),\n        (291, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.1.3-null.tar.gz', '1.2.1.3', 'admin', 0, '4', '233', '2022-07-26 15:31:14.0', '2022-08-09 11:43:41.0', 1),\n        (293, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.2.2.6-4.tar.gz', '2.2.2.6', 'admin', 0, '4', '9', '2022-07-28 16:06:11.0', '2022-08-07 10:44:22.0', 1),\n        (295, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.5.6.1-4.tar.gz', '1.5.6.1', 'admin', 0, '4', '11', '2022-07-28 17:18:50.0', '2022-07-28 17:18:56.0', 1),\n        (297, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.1.2.4-4.tar.gz', '1.1.2.4', 'admin', 0, '4', '123', '2022-07-28 20:31:10.0', '2022-08-07 10:44:18.0', 1),\n        (299, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/8.8.1.8-4.tar.gz', '8.8.1.8', 'admin', 0, '4', '测试删除', '2022-08-08 10:29:18.0', '2022-08-08 10:29:23.0', 1),\n        (301, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.6.2.0-4.tar.gz', '7.6.2.0', 'admin', 0, '4', '开源版本', '2022-08-08 18:08:30.0', '2022-08-08 18:08:30.0', 0),\n        (303, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.8.20.0-4.tar.gz', '6.8.20.0', 'admin', 0, '4', '开源版本', '2022-08-08 18:10:12.0', '2022-08-08 18:10:12.0', 0),\n        (305, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/5.6.2.0-4.tar.gz', '5.6.2.0', 'admin', 0, '4', '开源版本', '2022-08-08 18:11:17.0', '2022-08-08 18:11:17.0', 0),\n        (307, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.1.1.2-4.tar.gz', '2.1.1.2', 'admin', 0, '4', 'hhh', '2022-08-08 18:16:44.0', '2022-08-08 18:16:51.0', 1),\n        (309, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.3.1-4.tar.gz', '1.2.3.1', 'admin', 0, '4', 'lll', '2022-08-09 10:33:14.0', '2022-08-09 10:35:06.0', 1),\n        (311, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.1.3-4.tar.gz', '1.2.1.3', 'admin', 0, '4', '123', '2022-08-09 11:44:32.0', '2022-08-09 11:45:03.0', 1),\n        (313, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.1.3-4.tar.gz', '7.6.1.2', 'admin', 0, '4', '123123', '2022-08-09 11:50:30.0', '2022-08-25 20:29:25.0', 0),\n        (317, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/4.3.2.2-4.tar.gz', '4.3.2.2', 'admin', 0, '4', 'temp特色图等待', '2022-08-16 11:12:39.0', '2022-08-16 11:14:00.0', 1),\n        (319, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.6.3-4.tar.gz', '6.6.6.3', 'admin', 0, '4', '测试', '2022-08-25 21:45:02.0', '2022-08-25 21:45:17.0', 1),\n        (321, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.3.1-4.tar.gz', '6.6.6.6', 'admin', 0, '4', '1', '2022-08-26 15:47:48.0', '2022-08-27 14:55:35.0', 0);"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius.appid.template.access",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.appid.template.access\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": -1,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"\\nappid 维度访问次数索引 \\n\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"date\\\":{\\\"format\\\":\\\"strict_date_optional_time||yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||yyyy-MM-dd||yyyyMMdd||yyyyMM||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"accessDetailInfo\\\":{\\\"dynamic\\\":\\\"false\\\",\\\"type\\\":\\\"object\\\"},\\\"templateName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"clusterName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"logicTemplateId\\\":{\\\"type\\\":\\\"long\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius.dsl.analyze.result",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.dsl.analyze.result\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": 3,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"DSL分析结果\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"date\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis||yyyy-MM-dd\\\",\\\"type\\\":\\\"date\\\"},\\\"overview\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"costQuantile\\\":{\\\"properties\\\":{\\\"50_0\\\":{\\\"type\\\":\\\"float\\\"},\\\"75_0\\\":{\\\"type\\\":\\\"float\\\"},\\\"95_0\\\":{\\\"type\\\":\\\"float\\\"},\\\"99_0\\\":{\\\"type\\\":\\\"float\\\"}}},\\\"qpsMetric\\\":{\\\"properties\\\":{\\\"minQpsTime\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"},\\\"avgQps\\\":{\\\"type\\\":\\\"long\\\"},\\\"maxQpsTime\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"},\\\"minQps\\\":{\\\"type\\\":\\\"long\\\"},\\\"maxQps\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"count\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"errorDsls\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"details\\\":{\\\"properties\\\":{\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"name\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"details\\\":{\\\"properties\\\":{\\\"dslTemplate\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"indices\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"dslTemplateMd5\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"}}}}}}},\\\"dslTotalCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"slowDsls\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"details\\\":{\\\"properties\\\":{\\\"dslTemplate\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"indices\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"cost\\\":{\\\"type\\\":\\\"float\\\"},\\\"dslTemplateMd5\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"cause\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"slowDslThreshold\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"slowReasonType\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"}}}}},\\\"errDetailInfo\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"slowSearchCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"errSearchCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis||yyyy-MM-dd\\\",\\\"type\\\":\\\"date\\\"},\\\"dslTemplates\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"dslTotalCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslIncCnt\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"searchTotalCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"accessGatewayInfo\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"ariusType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslIncCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"day\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis||yyyy-MM-dd\\\",\\\"type\\\":\\\"date\\\"}}}\",\n  \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius.dsl.metrics",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.dsl.metrics\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timeStamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"用户查询聚合信息\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"ariusCreateTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"projectIdDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"searchCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslLevel\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"successfulShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTemplate\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"dslType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appidDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"responseLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"requestType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"searchType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"esCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"gatewayNode\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"dslLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalHitsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"version\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"indiceSample\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indices\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"dslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"isFromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"totalCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"failedShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"long\\\"},\\\"beforeCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius.dsl.template",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.dsl.template\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": -1,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"DSL 审核与分析\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"ariusCreateTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"projectIdDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"fromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"searchCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslLevel\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"my_all_fields\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"successfulShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTemplate\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"ignore_above\\\":32766,\\\"type\\\":\\\"keyword\\\"},\\\"dslType\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"appidDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"enable\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"sinkTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"day\\\":{\\\"type\\\":\\\"date\\\"},\\\"responseLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"requestType\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"searchType\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"ariusModifyTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"slowDslThreshold\\\":{\\\"type\\\":\\\"long\\\"},\\\"esCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"gatewayNode\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"totalHitsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"version\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"forceSetQueryLimit\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"boolean\\\"},\\\"indiceSample\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indices\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"ignore_above\\\":32766,\\\"type\\\":\\\"keyword\\\"},\\\"dslTemplateMd5\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"isFromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"totalCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"checkMode\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"failedShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"queryLimit\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"double\\\"},\\\"dsl\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"long\\\"},\\\"beforeCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"flinkTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius.gateway.join",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.gateway.join\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timeStamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"gateway 日志按照 requestId 进行 join\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"String \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_query_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"selectFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"stack\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"orderId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"searchCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"String\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"responseLen\\\":{\\\"type\\\":\\\"long\\\"},\\\"Count\\\":{\\\"type\\\":\\\"long\\\"},\\\"beforeCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"isTimedOut\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_exception_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dslTemplate\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"searchId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"x-username\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"action\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_replace_index_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"internalCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"exceptionName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"tookInMillis\\\":{\\\"type\\\":\\\"long\\\"},\\\"traceId\\\":{\\\"type\\\":\\\"float\\\"},\\\"customKey\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_exception_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"method\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_query_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"index\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"indexTypeName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"whereFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"queryString\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"Long` from newton_strategy_2020-07-18_v2 WHERE bizType \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"version\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_tcp_response_length_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dslLen\\\":{\\\"type\\\":\\\"long\\\"},\\\"flowModuleId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"totalHits\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_request_node_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"before_cost\\\":{\\\"type\\\":\\\"long\\\"},\\\"statusCode\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_pre_exception_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"status\\\":{\\\"type\\\":\\\"long\\\"},\\\"traceid\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"isUrgent\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"TimeUsed\\\":{\\\"type\\\":\\\"long\\\"},\\\"pre_alloctication_group\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"sourceTemplateName\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"groupByFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"typeName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"failedShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"routing\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"instanceId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_indices_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"client_node\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_replace_index_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"esCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"requestId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"clusterName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"sortByFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"Long` \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_exception_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"remoteAddr\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"lastBucketNumber\\\":{\\\"type\\\":\\\"long\\\"},\\\"dltagCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"Long \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"successfulShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"String` \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"gatewayNode\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"uri\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"destIndexName\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"url\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_tcp_search_scroll_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indices\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"scrollIdList\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"@timestamp\\\":{\\\"format\\\":\\\"strict_date_optional_time\\\",\\\"type\\\":\\\"date\\\"},\\\"stage\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"postBody\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clientIp\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_pre_exception_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"postBodyLen\\\":{\\\"type\\\":\\\"long\\\"},\\\"proc_time\\\":{\\\"type\\\":\\\"long\\\"},\\\"logicId\\\":{\\\"type\\\":\\\"long\\\"},\\\"Decimal \\\":{\\\"type\\\":\\\"float\\\"},\\\"ariusCreateTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"totalHitsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"xUserName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clientVersion\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"operator\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"Name\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"fetchCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_tcp_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"successShardsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"costTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"paramCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"ariusType\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_indices_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indiceCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_aggs_detail_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_search_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"group\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"orderByFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"res\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"timedOut\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"clientHost\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_fetch_message_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"totalShardsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"isTimeoutList\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"searchType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"Targ\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_before_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dltag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_before_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_request_node_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_tcp_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"success\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"dslTag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"name\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"memUsed\\\":{\\\"type\\\":\\\"long\\\"},\\\"bucketNumber\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"totalCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"sourceIndexNames\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"getClientCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"Errno\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexTemplateCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"dslLevel\\\":{\\\"type\\\":\\\"long\\\"},\\\"timeout\\\":{\\\"type\\\":\\\"long\\\"},\\\"failedShardsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"totalShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"scrollId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"sql\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"destTemplateName\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_aggs_detail_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dslType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"preProcessCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_tcp_response_length_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"newDslTemplate\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"param\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_internal_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"aggsLevel\\\":{\\\"type\\\":\\\"long\\\"},\\\"json\\\":{\\\"type\\\":\\\"object\\\"},\\\"_arius_query_tcp_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clientNode\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"rcvTimeout\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_scroll_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"types\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"cost\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_exception_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"requestType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"fetchSize\\\":{\\\"type\\\":\\\"long\\\"},\\\"esCostList\\\":{\\\"type\\\":\\\"long\\\"},\\\"aggsBukcetInfo\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"fetchMetric\\\":{\\\"properties\\\":{\\\"parseMessageCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"fetchMissingCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"getConsumeCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"fetchOffsetCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"brokerHost\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"fetchMetricInfo\\\":{\\\"properties\\\":{\\\"cost\\\":{\\\"type\\\":\\\"long\\\"},\\\"partition\\\":{\\\"type\\\":\\\"long\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"topic\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"}}},\\\"partitionTotalCost\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"_arius_response_index_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"message\\\":{\\\"ignore_above\\\":2048,\\\"index\\\":false,\\\"type\\\":\\\"keyword\\\"},\\\"userName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_msg\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_fetch_message_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indiceSample\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_internal_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"isFromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"dslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"service\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"user\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_response_index_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"queryRequest\\\":{\\\"type\\\":\\\"boolean\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"60s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius.template.access",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.template.access\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": -1,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"索引模板维度访问次数索引\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"date\\\":{\\\"format\\\":\\\"strict_date_optional_time||yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||yyyy-MM-dd||yyyyMMdd||yyyyMM||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"templateName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"clusterName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"logicTemplateId\\\":{\\\"type\\\":\\\"long\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius_cat_index_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_cat_index_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"索引列表\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"priStoreSize\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"clusterLogic\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"resourceId\\\":{\\\"type\\\":\\\"long\\\"},\\\"platformCreateFlag\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"pri\\\":{\\\"type\\\":\\\"long\\\"},\\\"health\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"docsDeleted\\\":{\\\"type\\\":\\\"long\\\"},\\\"deleteFlag\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"totalSegmentCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterPhy\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"storeSize\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"primariesSegmentCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"rep\\\":{\\\"type\\\":\\\"long\\\"},\\\"docsCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"key\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"status\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius_gateway_metrics",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_gateway_metrics\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"gateway 指标数据\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"query_totalHits_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_request_avg_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_aggs_count\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_count\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_response_avg_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_avg_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_min_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_imin_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"type\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"index_response_length\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_max_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_response_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_imax_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_cost_imax_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_stdev_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_max_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_imax_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_request_length\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_stdev_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"slowlog_cost_imax_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_imin_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_cost_min_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_totalShards_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_request_avg_length_stdev_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_cost_stdev_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_tookInMillis_avg_millis\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_max_length\\\":{\\\"type\\\":\\\"long\\\"},\\\"slowlog_cost_imin_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"template\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"hostName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"index_cost_imax_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_cost_imin_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_failedShards_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_failedShards_avg_count\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_tookInMillis_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_max_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_max_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_response_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_FLINK_SINK_TIME\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"index_response_avg_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_avg_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_request_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"index_response_avg_length_stdev_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_min_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_request_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_totalHits_avg_count\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_count\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_min_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_totalShards_avg_count\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_min_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_imin_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"operation\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"index_cost_avg_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_count\\\":{\\\"type\\\":\\\"long\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius_stats_cluster_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_cluster_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"physicCluster\\\":{\\\"type\\\":\\\"long\\\"},\\\"dataCenter\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"es_index_time\\\":{\\\"type\\\":\\\"long\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"cleanTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"statis\\\":{\\\"properties\\\":{\\\"cpuUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"statusType\\\":{\\\"type\\\":\\\"long\\\"},\\\"numberPendingTasks\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalTemplateNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"activeNodeNu\\\":{\\\"type\\\":\\\"long\\\"},\\\"invalidNodeNu\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"esNodeNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalIndicesNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalStoreSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"level\\\":{\\\"type\\\":\\\"long\\\"},\\\"sla\\\":{\\\"type\\\":\\\"double\\\"},\\\"sendTransSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"taskCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"cpuLoad15M\\\":{\\\"type\\\":\\\"double\\\"},\\\"alivePercent\\\":{\\\"type\\\":\\\"long\\\"},\\\"shardNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"freeStoreSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"memUsed\\\":{\\\"type\\\":\\\"long\\\"},\\\"memFreePercent\\\":{\\\"type\\\":\\\"float\\\"},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"unAssignedShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"appNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"cpuLoad1M\\\":{\\\"type\\\":\\\"double\\\"},\\\"cpuLoad5M\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexStoreSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"nodeNamesForDiskUsageGte75Percent\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"totalDocNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"extendInfoMap\\\":{\\\"type\\\":\\\"object\\\"},\\\"memUsedPercent\\\":{\\\"type\\\":\\\"float\\\"},\\\"clusterName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"storeSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexingLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"nodeIpsForDiskUsageGte75Percent\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"numberNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"recvTransSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"memFree\\\":{\\\"type\\\":\\\"long\\\"},\\\"readTps\\\":{\\\"type\\\":\\\"double\\\"},\\\"memTotal\\\":{\\\"type\\\":\\\"long\\\"},\\\"numberDataNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"writeTps\\\":{\\\"type\\\":\\\"double\\\"},\\\"numberIngestNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"numberMasterNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"queryTimesPreDay\\\":{\\\"type\\\":\\\"double\\\"},\\\"taskCost\\\":{\\\"type\\\":\\\"double\\\"},\\\"numberClientNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"diskUsage\\\":{\\\"type\\\":\\\"double\\\"}}},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"percentilesType\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius_stats_cluster_task_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_cluster_task_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"physicCluster\\\":{\\\"type\\\":\\\"long\\\"},\\\"dataCenter\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"metrics\\\":{\\\"properties\\\":{\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"parentTaskId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"ip\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"action\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"runningTimeString\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"description\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"startTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"runningTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"type\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"taskId\\\":{\\\"type\\\":\\\"keyword\\\"}}},\\\"key\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n  \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius_stats_dashboard_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_dashboard_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 15,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"template\\\":{\\\"properties\\\":{\\\"template\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"segmentMemSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"templateName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"cluster\\\":{\\\"properties\\\":{\\\"elapsedTimeGte5Min\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"gatewayFailedPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"clusterElapsedTimeGte5Min\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"httpNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"collectorDelayed\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexReqNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"nodeElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"gatewaySucPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"pendingTaskNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexingLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"elapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"nodeMetrics\\\":{\\\"properties\\\":{\\\"largeHead\\\":{\\\"type\\\":\\\"double\\\"},\\\"nodeElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"taskConsuming\\\":{\\\"type\\\":\\\"long\\\"},\\\"largeDiskUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"largeCpuUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"writeRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"dead\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"SearchRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"templateMetrics\\\":{\\\"properties\\\":{\\\"template\\\":{\\\"type\\\":\\\"long\\\"},\\\"segmentMemSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"physicCluster\\\":{\\\"type\\\":\\\"integer\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"nodeThreadPoolQueueMetrics\\\":{\\\"properties\\\":{\\\"search\\\":{\\\"type\\\":\\\"long\\\"},\\\"flush\\\":{\\\"type\\\":\\\"long\\\"},\\\"management\\\":{\\\"type\\\":\\\"long\\\"},\\\"merge\\\":{\\\"type\\\":\\\"long\\\"},\\\"refresh\\\":{\\\"type\\\":\\\"long\\\"},\\\"write\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"index\\\":{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"mappingNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"red\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"segmentMemSize\\\":{\\\"type\\\":\\\"float\\\"},\\\"smallShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"bigShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"shardSize\\\":{\\\"type\\\":\\\"long\\\"},\\\"singReplicate\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"memSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"unassignedShard\\\":{\\\"type\\\":\\\"boolean\\\"}}},\\\"clusterPhyHealth\\\":{\\\"properties\\\":{\\\"unknownClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"unknownNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"redNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"totalNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"greenClusterListStr\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"greenNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"yellowClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"yellowNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"redClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"clusterPhyHealthMetrics\\\":{\\\"properties\\\":{\\\"unknownClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"unknownNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"redNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"totalNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"greenNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"active\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"yellowClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"yellowNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"redClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"node\\\":{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"taskConsuming\\\":{\\\"type\\\":\\\"long\\\"},\\\"dead\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"nodeElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"largeHead\\\":{\\\"type\\\":\\\"double\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"largeDiskUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"searchRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"largeCpuUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"writeRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"SearchRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"elapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"clusterThreadPoolQueue\\\":{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"search\\\":{\\\"type\\\":\\\"long\\\"},\\\"flush\\\":{\\\"type\\\":\\\"long\\\"},\\\"management\\\":{\\\"type\\\":\\\"long\\\"},\\\"merge\\\":{\\\"type\\\":\\\"long\\\"},\\\"refresh\\\":{\\\"type\\\":\\\"long\\\"},\\\"write\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"indexMetrics\\\":{\\\"properties\\\":{\\\"red\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"mappingNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"smallShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"bigShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"singReplicate\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"memSize\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"unassignedShard\\\":{\\\"type\\\":\\\"boolean\\\"}}},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clusterMetrics\\\":{\\\"properties\\\":{\\\"indexReqNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"gatewaySucPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"pendingTaskNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"gatewayFailedPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexingLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"httpNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius_stats_index_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_index_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"template\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"long\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"cleanTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"shardNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"metrics\\\":{\\\"properties\\\":{\\\"refresh-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"store-size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"docs-count-total\\\":{\\\"type\\\":\\\"float\\\"},\\\"search-fetch_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"merges-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-doc_values_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_time_per_doc\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-index_writer_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"store-size_in_bytes_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"query_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"docs-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"shardNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"refresh-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"merges-total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"flush-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-fetch_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"refresh-total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"translog-size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"flush-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-fetch_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_total_times\\\":{\\\"type\\\":\\\"double\\\"},\\\"flush-total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merge_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"merges-current\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_total\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"indices-indexing-index_time_per_doc\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-points_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_latency\\\":{\\\"type\\\":\\\"float\\\"},\\\"segments-term_vectors_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-stored_fields_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"store-size_in_bytes-total\\\":{\\\"type\\\":\\\"float\\\"},\\\"merges-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_failed_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush_avg_time\\\":{\\\"type\\\":\\\"double\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"logicTemplateId\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1/template_in_arius/arius_stats_node_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_node_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"rack\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"ip\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"cleanTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"port\\\":{\\\"type\\\":\\\"long\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"metrics\\\":{\\\"properties\\\":{\\\"os-cpu-percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-heap_used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-heap_used_percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-cache_size\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-bulk-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-miss_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-hit_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-load_average-5m\\\":{\\\"type\\\":\\\"double\\\"},\\\"process-cpu-percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-rx_size_in_bytes_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-load_average-1m\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-stored_fields_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-norms_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-version_map_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-fixed_bit_set_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-breakers-fielddata-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_current\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-store-size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges-current\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-non_heap_used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-write-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-refresh-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-rollup_indexing-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-management-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-force_merge-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-translog-operations_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-server_open\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-threads-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-translog-uncommitted_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-rx_count_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-index_writer_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-tx_count_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-term_vectors_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-delete_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-tx_size_in_bytes_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-doc_values_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-total_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-points_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-load_average-15m\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-search-completed\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"ingest-total-failed\\\":{\\\"type\\\":\\\"float\\\"},\\\"indices-search-scroll_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"http-current_open\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-write-rejected\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_count_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"process-process-open_file_descriptors\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-index_latency\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-pools-old-used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-available_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-disk_free_percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-free_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-bulk-rejected\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-bulk-completed\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_latency\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-search-rejected\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-write-completed\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-docs-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"ingest-total-current\\\":{\\\"type\\\":\\\"float\\\"},\\\"indices-segments-memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"ingest-total-count\\\":{\\\"type\\\":\\\"float\\\"},\\\"ingest-total-time_in_millis\\\":{\\\"type\\\":\\\"float\\\"},\\\"thread_pool-search-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu_percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-miss_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-pools-young-used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-hit_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_count_rate\\\":{\\\"type\\\":\\\"double\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/0.3.1.1增量.sql",
    "content": "insert into logi_security_permission (id, permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name)\nvalues  (1593, '物理集群', 0, 0, 1, '物理集群', '2022-05-24 18:08:22.0', '2022-08-24 20:07:31.0', 0, 'know_search'),\n        (1595, '我的集群', 0, 0, 1, '我的集群', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1597, '集群版本', 0, 0, 1, '集群版本', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1599, 'Gateway管理', 0, 0, 1, 'Gateway管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1601, '模板管理', 0, 0, 1, '模板管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1603, '模板服务', 0, 0, 1, '模板服务', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1605, '索引管理', 0, 0, 1, '索引管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1607, '索引服务', 0, 0, 1, '索引服务', '2022-05-24 18:08:22.0', '2022-05-24 18:24:16.0', 0, 'know_search'),\n        (1609, '索引查询', 0, 0, 1, '索引查询', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1611, '查询诊断', 0, 0, 1, '查询诊断', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1613, '集群看板', 0, 0, 1, '集群看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1615, '网关看板', 0, 0, 1, '网关看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1617, '我的申请', 0, 0, 1, '我的申请', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1619, '我的审批', 0, 0, 1, '我的审批', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1621, '任务列表', 0, 0, 1, '任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1623, '调度任务列表', 0, 0, 1, '调度任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1625, '调度日志', 0, 0, 1, '调度日志', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1627, '用户管理', 0, 0, 1, '用户管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1629, '角色管理', 0, 0, 1, '角色管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1631, '应用管理', 0, 0, 1, '应用管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1633, '平台配置', 0, 0, 1, '平台配置', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1635, '操作记录', 0, 0, 1, '操作记录', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1637, '查看集群列表及详情', 1593, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1639, '接入集群', 1593, 1, 2, '接入集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1641, '新建集群', 1593, 1, 2, '新建集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1643, '扩缩容', 1593, 1, 2, '扩缩容', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1645, '升级', 1593, 1, 2, '升级', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1647, '重启', 1593, 1, 2, '重启', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1649, '配置变更', 1593, 1, 2, '配置变更', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1651, 'Region划分', 1593, 1, 2, 'Region划分', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1653, 'Region管理', 1593, 1, 2, 'Region管理', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1655, '快捷命令', 1593, 1, 2, '快捷命令', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1657, '编辑', 1593, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1659, '绑定Gateway', 1593, 1, 2, '绑定Gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1661, '下线', 1593, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1663, '查看集群列表及详情', 1595, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1665, '申请集群', 1595, 1, 2, '申请集群', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1667, '编辑', 1595, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1669, '扩缩容', 1595, 1, 2, '扩缩容', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1671, '下线', 1595, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1673, '查看版本列表', 1597, 1, 2, '查看版本列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1675, '新增版本', 1597, 1, 2, '新增版本', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1677, '编辑', 1597, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1679, '删除', 1597, 1, 2, '删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1681, '查看Gateway 集群列表', 1599, 1, 2, '查看Gateway 集群列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1683, '接入gateway', 1599, 1, 2, '接入gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1685, '编辑', 1599, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1687, '下线', 1599, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1689, '查看模板列表及详情', 1601, 1, 2, '查看模板列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1691, '申请模板', 1601, 1, 2, '申请模板', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1693, '编辑', 1601, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1695, '下线', 1601, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1697, '编辑Mapping', 1601, 1, 2, '编辑Mapping', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1699, '编辑Setting', 1601, 1, 2, '编辑Setting', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1701, '查看模板列表', 1603, 1, 2, '查看模板列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1703, '开关：预创建', 1603, 1, 2, '开关：预创建', '2022-05-24 18:08:23.0', '2022-06-14 16:49:48.0', 0, 'know_search'),\n        (1705, '开关：过期删除', 1603, 1, 2, '开关：过期删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1707, '开关：冷热分离', 1603, 1, 2, '开关：冷热分离', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1709, '开关：pipeline', 1603, 1, 2, '开关：写入限流', '2022-05-24 18:08:23.0', '2022-06-14 16:49:49.0', 0, 'know_search'),\n        (1711, '开关：Rollover', 1603, 1, 2, '开关：Rollover', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1713, '查看DCDR链路', 1603, 1, 2, '查看DCDR链路', '2022-05-24 18:08:23.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1715, '创建DCDR链路', 1603, 1, 2, '创建DCDR链路', '2022-05-24 18:08:24.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1717, '清理', 1603, 1, 2, '清理', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1719, '扩缩容', 1603, 1, 2, '扩缩容', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1721, '升版本', 1603, 1, 2, '升版本', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1723, '批量操作', 1603, 1, 2, '批量操作', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1725, '查看索引列表及详情', 1605, 1, 2, '查看索引列表及详情', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1727, '编辑Mapping', 1605, 1, 2, '编辑Mapping', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1729, '编辑Setting', 1605, 1, 2, '编辑Setting', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1731, '禁用读', 1607, 1, 2, '禁用读', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1733, '禁用写', 1607, 1, 2, '禁用写', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1735, '设置别名', 1605, 1, 2, '设置别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1737, '删除别名', 1605, 1, 2, '删除别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1739, '关闭索引', 1607, 1, 2, '关闭索引', '2022-05-24 18:08:24.0', '2022-07-15 09:52:25.0', 0, 'know_search'),\n        (1741, '下线', 1605, 1, 2, '下线', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1743, '批量删除', 1605, 1, 2, '批量删除', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1745, '查看列表', 1607, 1, 2, '查看列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1747, '执行Rollover', 1607, 1, 2, '执行Rollover', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1749, '执行shrink', 1607, 1, 2, '执行shrink', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1751, '执行split', 1607, 1, 2, '执行split', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1753, '执行ForceMerge', 1607, 1, 2, '执行ForceMerge', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1755, '批量执行', 1607, 1, 2, '批量执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1757, 'DSL查询', 1877, 1, 2, 'DSL查询', '2022-05-24 18:08:24.0', '2022-09-05 14:24:00.0', 0, 'know_search'),\n        (1759, '查询模板', 0, 0, 1, '查看查询模板列表', '2022-05-24 18:08:24.0', '2022-08-11 10:37:43.0', 0, 'know_search'),\n        (1761, '查看集群看板', 1613, 1, 2, '查看集群看板', '2022-05-24 18:08:24.0', '2022-06-14 16:37:54.0', 0, 'know_search'),\n        (1763, '查看网关看板', 1615, 1, 2, '查看网关看板', '2022-05-24 18:08:24.0', '2022-06-14 16:38:14.0', 0, 'know_search'),\n        (1765, '查看我的申请列表', 1617, 1, 2, '查看我的申请列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1767, '撤回', 1617, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1769, '查看我的审批列表', 1619, 1, 2, '查看我的审批列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1771, '驳回', 1619, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-07-18 20:57:33.0', 0, 'know_search'),\n        (1773, '通过', 1619, 1, 2, '通过', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1775, '查看任务列表', 1621, 1, 2, '查看任务列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1777, '查看进度', 1621, 1, 2, '查看进度', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1779, '执行', 1621, 1, 2, '执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1781, '暂停', 1621, 1, 2, '暂停', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1783, '重试', 1621, 1, 2, '重试', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1785, '取消', 1621, 1, 2, '取消', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1787, '查看日志（子任务）', 1621, 1, 2, '查看日志（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1789, '重试（子任务）', 1621, 1, 2, '重试（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1791, '忽略（子任务）', 1621, 1, 2, '忽略（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1793, '查看详情（DCDR）', 1621, 1, 2, '查看详情（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1795, '取消（DCDR）', 1621, 1, 2, '取消（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1797, '重试（DCDR）', 1621, 1, 2, '重试（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1799, '强切（DCDR）', 1621, 1, 2, '强切（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1801, '返回（DCDR）', 1621, 1, 2, '返回（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1803, '查看任务列表', 1623, 1, 2, '查看任务列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1805, '查看日志', 1623, 1, 2, '查看日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1807, '执行', 1623, 1, 2, '执行', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1809, '暂停', 1623, 1, 2, '暂停', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1811, '查看调度日志列表', 1625, 1, 2, '查看调度日志列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1813, '调度详情', 1625, 1, 2, '调度详情', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1815, '执行日志', 1625, 1, 2, '执行日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1817, '终止任务', 1625, 1, 2, '终止任务', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1819, '查看用户列表', 1627, 1, 2, '查看用户列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1821, '分配角色', 1627, 1, 2, '分配角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1823, '查看角色列表', 1629, 1, 2, '查看角色列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1825, '编辑', 1629, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1827, '绑定用户', 1629, 1, 2, '绑定用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1829, '回收用户', 1629, 1, 2, '回收用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1831, '删除角色', 1629, 1, 2, '删除角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1833, '查看应用列表', 1631, 1, 2, '查看应用列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1835, '新建应用', 1631, 1, 2, '新建应用', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1837, '编辑', 1631, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1839, '删除', 1631, 1, 2, '删除', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1841, '访问设置', 1631, 1, 2, '访问设置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1843, '查看平台配置列表', 1633, 1, 2, '查看平台配置列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1845, '新增平台配置', 1633, 1, 2, '新增平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1847, '禁用平台配置', 1633, 1, 2, '禁用平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1849, '编辑平台配置', 1633, 1, 2, '编辑平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1851, '删除平台配置', 1633, 1, 2, '删除平台配置', '2022-05-24 18:08:26.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1853, '查看操作记录列表', 1635, 1, 2, '查看操作记录列表', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1855, 'Kibana查询', 1879, 1, 2, 'Kibana查询', '2022-05-24 18:08:26.0', '2022-09-05 14:24:00.0', 0, 'know_search'),\n        (1857, 'SQL查询', 1881, 1, 2, 'SQL查询', '2022-05-24 18:08:26.0', '2022-09-05 14:24:00.0', 0, 'know_search'),\n        (1859, '批量修改限流值', 1759, 1, 2, '批量修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1861, '禁用', 1759, 1, 2, '禁用', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1863, '修改限流值', 1759, 1, 2, '修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1865, '查看异常查询列表', 1611, 1, 2, '查看异常查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1867, '查看慢查询列表', 1611, 1, 2, '查看慢查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:21.0', 0, 'know_search'),\n        (1869, '新增角色', 1629, 1, 2, '新增角色', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1871, 'Dashboard', 0, 0, 1, '查看dashboard', '2022-05-24 18:08:26.0', '2022-08-27 17:35:50.0', 0, 'know_search'),\n        (1873, '新建索引', 1605, 1, 2, '新建索引', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1875, '查看dashboard', 1871, 1, 2, '查看dashboard', '2022-05-24 18:08:24.0', '2022-08-27 17:35:50.0', 0, 'know_search'),\n        (1877, 'DSL', 0, 0, 1, 'DSL', '2022-05-24 18:08:24.0', '2022-09-02 19:01:17.0', 0, 'know_search'),\n        (1879, 'Kibana', 0, 0, 1, 'Kibana', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search'),\n        (1881, 'SQL', 0, 0, 1, 'SQL', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search');\n\n\n/*\n0.3.1原始sql\nUPDATE logi_security_permission SET permission_name = 'Kibana', parent_id = 1609, leaf = 1, level = 2, description = 'Kibana', create_time = '2022-05-24 18:08:26.0', update_time = '2022-06-14 16:44:02.0', is_delete = 0, app_name = 'know_search' WHERE id = 1855;\nUPDATE logi_security_permission SET permission_name = 'SQL查询', parent_id = 1609, leaf = 1, level = 2, description = 'SQL查询', create_time = '2022-05-24 18:08:26.0', update_time = '2022-06-14 16:44:02.0', is_delete = 0, app_name = 'know_search' WHERE id = 1857;\nUPDATE logi_security_permission SET permission_name = 'DSL查询', parent_id = 1609, leaf = 1, level = 2, description = 'DSL查询', create_time = '2022-05-24 18:08:24.0', update_time = '2022-06-14 16:39:48.0', is_delete = 0, app_name = 'know_search' WHERE id = 1757;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1609, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2059;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1757, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2061;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1855, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:34:13.0', is_delete = 0, app_name = 'know_search' WHERE id = 2063;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1857, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2065;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1609, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2241;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1757, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2243;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1855, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:33:12.0', is_delete = 1, app_name = 'know_search' WHERE id = 2245;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1857, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2247;\n*/\n# 0.3.1.1变更sql\n# 1.更新level和leaf\nUPDATE logi_security_permission SET permission_name = 'DSL查询', parent_id = 0, leaf = 0, level = 1, description = 'DSL查询', create_time = '2022-05-24 18:08:24.0', update_time = '2022-09-02 19:01:17.0', is_delete = 0, app_name = 'know_search' WHERE id = 1757;\nUPDATE logi_security_permission SET permission_name = 'Kibana', parent_id = 0, leaf = 0, level = 1, description = 'Kibana', create_time = '2022-05-24 18:08:26.0', update_time = '2022-09-02 19:01:17.0', is_delete = 0, app_name = 'know_search' WHERE id = 1855;\nUPDATE logi_security_permission SET permission_name = 'SQL查询', parent_id = 0, leaf = 0, level = 1, description = 'SQL查询', create_time = '2022-05-24 18:08:26.0', update_time = '2022-09-02 19:01:17.0', is_delete = 0, app_name = 'know_search' WHERE id = 1857;\n#1.1修改logi_security_role_permission\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1609, create_time = '2022-06-14 17:41:03.0', update_time = '2022-09-02 19:04:07.0', is_delete = 1, app_name = 'know_search' WHERE id = 2059;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1757, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2061;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1855, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:34:13.0', is_delete = 0, app_name = 'know_search' WHERE id = 2063;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1857, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2065;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1609, create_time = '2022-06-14 18:08:56.0', update_time = '2022-09-02 19:04:07.0', is_delete = 1, app_name = 'know_search' WHERE id = 2241;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1757, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2243;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1855, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:33:12.0', is_delete = 1, app_name = 'know_search' WHERE id = 2245;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1857, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2247;\n#2.更新name\nUPDATE logi_security_permission SET permission_name = 'Kibana查询', parent_id = 0, leaf = 0, level = 1, description = 'Kibana查询', create_time = '2022-05-24 18:08:26.0', update_time = '2022-09-05 14:19:29.0', is_delete = 0, app_name = 'know_search' WHERE id = 1855;\n#3.新增3个权限点\nINSERT INTO logi_security_permission (permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name) VALUES ('DSL', 0, 0, 1, 'DSL', '2022-05-24 18:08:24.0', '2022-09-02 19:01:17.0', 0, 'know_search');\nINSERT INTO logi_security_permission (permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name) VALUES ('Kibana', 0, 0, 1, 'Kibana', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search');\nINSERT INTO logi_security_permission (permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name) VALUES ('SQL', 0, 0, 1, 'SQL', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search');\n#3.1 新增logi_security_role_permission\ninsert into logi_security_role_permission(role_id, permission_id, is_delete, app_name)\nvalues (1, 1877, 0, 'know_search'),\n       (1, 1879, 0, 'know_search'),\n       (1, 1881, 0, 'know_search'),\n       (2, 1877, 0, 'know_search'),\n       (2, 1879, 1, 'know_search'),\n       (2, 1881, 0, 'know_search');\n\n#4.再次更新level和leaf\nUPDATE logi_security_permission SET permission_name = 'DSL查询', parent_id = 1877, leaf = 1, level = 2, description = 'DSL查询' WHERE id = 1757;\nUPDATE logi_security_permission SET permission_name = 'Kibana查询', parent_id = 1879, leaf = 1, level = 2, description = 'Kibana查询' WHERE id = 1855;\nUPDATE logi_security_permission SET permission_name = 'SQL查询', parent_id = 1881, leaf = 1, level = 2, description = 'SQL查询' WHERE id = 1857;\n\n\n#5.用户和应用配置信息表\nalter table user_metrics_config_info rename to user_config_info;\nalter table user_config_info COMMENT '用户和应用配置信息表';\nalter table `user_config_info` change COLUMN metric_info config_info text COMMENT '用户下某个应用的配置';\nalter table `user_config_info` add column project_id int(10) NOT NULL DEFAULT '-1' COMMENT '项目 id' after user_name;\nalter table `user_config_info` add column config_type int(10) NOT NULL DEFAULT '1' COMMENT '配置类型,1- 指标看板和 dashboard，2- 查询模板列表' after project_id;\ntruncate table user_config_info;\n\nINSERT INTO `user_config_info`(`user_name`, `project_id`, `config_type`, `config_info`)\nselect DISTINCT t1.user_name,t2.project_id,2,\n                concat('[{\\\"firstUserConfigType\\\":\\\"searchQuery\\\",\\\"projectId\\\":',t2.project_id,',\\\"secondUserConfigType\\\":\\\"searchTemplate\\\",\\\"userConfigTypes\\\":[\\\"totalCostAvg\\\",\\\"totalShardsAvg\\\"],\\\"userName\\\":\\\"',t1.user_name,'\\\"}]') as config_info\nfrom logi_security_user t1 inner join\n     logi_security_user_project t2 on t1.id=t2.user_id and t2.is_delete='0'\nwhere  t1.is_delete='0';\n\nDROP TABLE IF EXISTS `metric_dictionary_info`;\nCREATE TABLE `metric_dictionary_info`  (\n                                           `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,\n                                           `type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标分类',\n                                           `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '指标名称',\n                                           `price` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '-1' COMMENT '指标价值',\n                                           `interval` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '1' COMMENT '计算间隔',\n                                           `current_cal_logic` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '当前计算逻辑',\n                                           `is_gold` tinyint(1) UNSIGNED ZEROFILL NULL DEFAULT 0 COMMENT '是否黄金指标(0否1是)',\n                                           `unit` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '单位',\n                                           `interactive_form` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '交互形式',\n                                           `is_warning` tinyint(1) UNSIGNED ZEROFILL NULL DEFAULT 0 COMMENT '告警指标(0否1是)',\n                                           `source` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标来源',\n                                           `tags` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标标签',\n                                           `model` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '模块',\n                                           `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n                                           `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n                                           `is_active` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否生效',\n                                           `is_threshold` tinyint(1) UNSIGNED ZEROFILL NOT NULL DEFAULT 0 COMMENT '是否有阈值',\n                                           `threshold` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '阈值',\n                                           `metric_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '阈值信息',\n                                           PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 5754 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户和应用配置信息表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Records of metric_dictionary_info\n-- ----------------------------\nINSERT INTO `metric_dictionary_info` VALUES (4915, '集群统计', '集群状态、shard总数、索引模板总数、文档总数、索引数、节点分配（Master节点数/Data节点数/Client节点数）、堆内存总量（已用内存、空闲内存）、磁盘总量（已用磁盘、空闲磁盘）、节点总数（活跃节点数、死亡节点数）、集群索引存储量、未分配Shard数', '集群当前运行状态概览信息', '当前值', '索引模板总数: /_template命令获取的数组大小\\n通过_cluster/stats命令直接获取\\n  集群状态：status\\n  shard总数：shards.total\\n  文档总数：indices.docs.count\\n  索引数:indices.count\\n  Master节点数:nodes.count.master\\n  Data节点数:nodes.count.data \\n  Client节点数:nodes.count.total - nodes.count.master-nodes.count.data\\n  堆内存总量:nodes.os.mem.total_in_bytes\\n  已用内存:nodes.os.mem.used_in_bytes\\n  空闲内存:nodes.os.mem.free_percent\\n  磁盘总量:nodes.fs.total_in_bytes\\n  已用磁盘:nodes.fs.total_in_bytes - nodes.fs.free_in_bytes\\n  空闲磁盘:nodes.fs.free_in_bytes\\n  节点总数:nodes.count.total\\n  活跃节点数，死亡节点数:查询配置的集群节点列表后和ES集群节点ip列表进行匹配，可以匹配上的为活跃节点 \\n  集群索引存储量：indices.store.size_in_bytes  ->  新增字段indicesStoreSize\\n未分配Shard数：通过 _cat/health?format=json 获取unassign字段 -> 新增字段unassignedShardNum', 1, NULL, '状态栏', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:20:01', 1, 0, NULL, 'basic');\nINSERT INTO `metric_dictionary_info` VALUES (4917, '系统指标', 'CPU使用率（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群CPU使用率与均衡情况观察', '当前值', '[当前值] 集群下所有节点，通过_node/stats命令获取nodes.{nodeName}.os.cpu.percent ，根据分位进行聚合', 1, '%', '折线图', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:49:28', 1, 0, NULL, 'cpuUsage');\nINSERT INTO `metric_dictionary_info` VALUES (4919, '系统指标', 'CPU 1分钟负载（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群1分钟负载与均衡情况观察', '当前值', '[当前值] 集群下所有节点，通过_node/stats命令获取nodes.{nodeName}.os.cpu.load_average.1m，根据分位进行聚合', 0, NULL, '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:49:30', 1, 0, NULL, 'cpuLoad1M');\nINSERT INTO `metric_dictionary_info` VALUES (4921, '系统指标', '磁盘使用率（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群磁盘利用率与均衡情况观察', '当前值', '[当前值]集群下所有节点，通过_node/stats命令获取（nodes.{nodeName}.fs.total.total_in_bytes - nodes.{nodeName}.fs.total.free_in_bytes）/nodes.{nodeName}.fs.total.total_in_bytes，根据分位进行聚合', 0, '%', '折线图', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:20:16', 1, 0, NULL, 'diskUsage');\nINSERT INTO `metric_dictionary_info` VALUES (4923, '系统指标', '磁盘使用情况（磁盘空闲量/磁盘使用量/磁盘总量）', '集群磁盘使用情况概览', '当前值', '通过_cluster/stats命令获取\\n磁盘总量 : nodes.{nodeName}.fs.total_in_bytes\\n磁盘使用量 : nodes.{nodeName}.fs.total_in_bytes - nodes.fs.free_in_bytes\\n磁盘空闲量 : nodes.{nodeName}.fs.free_in_bytes', 0, 'GB', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, 'diskInfo');\nINSERT INTO `metric_dictionary_info` VALUES (4925, '系统指标', '网络出口流量', '集群网络出口流量/网络入口流量走势', '当前值', '[当前值] 集群下的所有节点，通过_node/stats命令获取nodes.{nodeName}.transport.rx_size_in_bytes、nodes.{nodeName}.transport.tx_size_in_bytes（接收、发送）的累加值', 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:47:08', 1, 0, NULL, 'sendTransSize');\nINSERT INTO `metric_dictionary_info` VALUES (4927, '系统指标', '指标采集失败率', '集群指标采集失败率（采集失败次数/采集窗口大小）', '60S', NULL, 1, '%', '折线图', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-28 11:31:36', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4929, '性能指标', '执行任务耗时（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群节点任务执行耗时与均衡情况观察', '当前值', '[当前值] _cat/tasks?v&detailed&format=json命令获取结果集中running_time字段的分位值', 0, 'S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-10 16:00:21', 1, 0, NULL, 'taskCost');\nINSERT INTO `metric_dictionary_info` VALUES (4931, '性能指标', '执行任务数量', '集群全部节点每秒执行任务数走势', '当前值', '[当前值] _cat/tasks?v&detailed&format=json命令获取结果集的大小', 0, '个/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:07', 1, 0, NULL, 'taskCount');\nINSERT INTO `metric_dictionary_info` VALUES (4932, '系统指标', '网络入口流量', '集群网络出口流量/网络入口流量走势', '当前值', '[当前值] 集群下的所有节点，通过_node/stats命令获取nodes.{nodeName}.transport.rx_size_in_bytes、nodes.{nodeName}.transport.tx_size_in_bytes（接收、发送）的累加值', 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:47:11', 1, 0, NULL, 'recvTransSize');\nINSERT INTO `metric_dictionary_info` VALUES (4933, '性能指标', '查询QPS', '集群Shard级别查询并发量概览', '60S', '[平均值] 集群下的所有节点，间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.search.query_total的差值累加值/间隔时间', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:07', 1, 0, NULL, 'readTps');\nINSERT INTO `metric_dictionary_info` VALUES (4935, '性能指标', '写入TPS', '集群Shard级别写入并发量概览', '60S', '[累加值] 集群下的所有节点，间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.indexing.index_total的差值累加值/间隔时间', 1, '个/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-25 15:47:20', 1, 0, NULL, 'writeTps');\nINSERT INTO `metric_dictionary_info` VALUES (4937, '性能指标', '查询耗时', '集群Shard级别查询耗时概览', '60S', '[平均值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.search.query_total差值累加值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:08', 1, 0, NULL, 'searchLatency');\nINSERT INTO `metric_dictionary_info` VALUES (4939, '性能指标', '写入耗时', '集群文档级别写入耗时概览', '60S', '[平均值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.docs.count差值累加值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:08', 1, 0, NULL, 'indexingLatency');\nINSERT INTO `metric_dictionary_info` VALUES (4941, '性能指标', '网关写入TPS', '通过网关每秒写入集群的写入请求次数', '60S', NULL, 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:08', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4943, '性能指标', '网关写入吞吐量', '通过网关每秒写入集群的文档字节数', '60S', NULL, 1, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4945, '性能指标', '网关写入请求耗时', '通过网关写入请求的平均耗时', '60S', NULL, 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4947, '性能指标', '网关写入请求响应体大小', '通过网关写入请求的响应体平均大小', '60S', NULL, 0, 'B', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4949, '性能指标', '网关查询QPS', '通过网关每秒查询的请求次数', '60S', NULL, 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4951, '性能指标', '网关查询请求耗时', '通过网关查询请求的平均耗时', '60S', NULL, 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4953, '性能指标', '网关单次查询命中Shard数', '通过网关查询请求的命中Shard平均数', '60S', NULL, 0, '个', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4955, '状态指标', '迁移中shard列表', '集群Shard迁移感知', '当前值', '[当前值] 通过_cat/recovery?v&h=i,s,t,st,shost,thost&active_only=true命令获取的集合详情', 0, NULL, '列表展示（index,source_host,target_host,bytes_recovered bytes_percen,translog_ops_percentt）', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'movingShards');\nINSERT INTO `metric_dictionary_info` VALUES (4957, '状态指标', '未分配Shard列表', '集群节点掉线感知', '当前值', '[当前值]通过_cat/shards?format=json命令获取state=UNASSIGN的shard列表', 0, NULL, '列表项（index，shard，prirep，state）', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-30 08:56:42', 1, 0, NULL, 'unAssignShards');\nINSERT INTO `metric_dictionary_info` VALUES (4959, '状态指标', 'Dead节点列表', '', '当前值', '[当前值] 通过_nodes命令获取集群节点信息，与平台集群节点列表对比缺失的节点', 0, NULL, '列表项（节点IP、主机名、实例名）', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:42:21', 1, 0, NULL, 'invalidNodes');\nINSERT INTO `metric_dictionary_info` VALUES (4961, '状态指标', 'PendingTask列表', '集群PengingTask感知', '当前值', '[当前值] 通过/_cluster/pending_tasks命令获取的集合', 0, NULL, '列表项（插入顺序、优先级、任务来源、执行任务前等待时间）', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:42:38', 1, 0, NULL, 'pendingTasks');\nINSERT INTO `metric_dictionary_info` VALUES (4963, '系统指标', 'CPU利用率', 'CPU使用率，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.os.cpu.percent字段', 1, '%', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:42:08', 1, 0, NULL, 'os-cpu-percent');\nINSERT INTO `metric_dictionary_info` VALUES (4965, '系统指标', '磁盘空闲率', '磁盘空闲率，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.fs.total.free_in_bytes/nodes.{nodeName}.fs.total.total_in_bytes', 1, '%', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:36:11', 1, 0, NULL, 'fs-total-disk_free_percent');\nINSERT INTO `metric_dictionary_info` VALUES (4967, '系统指标', '网络发送流量', '网络包为单位的每秒发送流量，Top节点趋势', '当前值', '[平均值]，间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.transport.tx_size_in_byte的差值/时间间隔', 0, 'MB/S', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:53:56', 1, 0, NULL, 'transport-tx_size_in_bytes_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4969, '系统指标', '网络接收流量', '网络包为单位的接收流量，Top节点趋势', '当前值', '[平均值]，间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.transport.rx_size_in_bytes的差值/时间间隔', 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:54:17', 1, 0, NULL, 'transport-rx_size_in_bytes_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4971, '系统指标', 'CPU近1分钟负载', 'CPU近1分钟负载，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.os.cpu.load_average.1m', 0, NULL, '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:36:49', 1, 0, NULL, 'os-cpu-load_average-1m');\nINSERT INTO `metric_dictionary_info` VALUES (4973, '基本性能指标', '写入TPS', '节点索引写入速率平均值，Top节点趋势', '60S', '[平均值] (当前时刻减去上一时刻通过_nodes/stats命令获取nodes.{nodeName}.indices.indexing.index_total的差值)/时间间隔(S)', 1, '个/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 09:45:25', 1, 0, NULL, 'indices-indexing-index_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4975, '基本性能指标', '网关查询QPS', '网关通过ClientNode节点每秒查询的请求数，Top节点趋势', '60S', NULL, 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-28 11:31:36', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4977, '基本性能指标', '网关写入TPS', '网关通过ClientNode节点每秒写入的请求数，Top节点趋势', '60S', NULL, 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-28 11:31:36', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4979, '基本性能指标', '网关写入吞吐量', '网关通过ClientNode节点每秒写入的吞吐量，Top节点趋势', '60S', NULL, 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:10:44', 1, 0, NULL, 'collectorDelayed');\nINSERT INTO `metric_dictionary_info` VALUES (4981, '基本性能指标', '写入耗时', '节点索引写入耗时平均值，Top节点趋势', '60S', '[平均值],间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.docs.count的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:06:05', 1, 0, NULL, 'indices-indexing-index_time_per_doc');\nINSERT INTO `metric_dictionary_info` VALUES (4983, '基本性能指标', 'Query QPS', '节点索引Query速率平均值，Top节点趋势', '60S', '[平均值],间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.search.query_total的差值/时间间隔', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 09:45:49', 1, 0, NULL, 'indices-search-query_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4985, '基本性能指标', 'Fetch QPS', '节点索引Fetch速率平均值，Top节点趋势', '60S', '[平均值] ,间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.search.fetch_total的差值/时间间隔', 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 09:46:00', 1, 0, NULL, 'indices-search-fetch_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4987, '基本性能指标', 'Query耗时', '节点索引Query耗时平均值，Top节点趋势', '60S', '[平均值],间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.search.query_total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:37:36', 1, 0, NULL, 'indices-search-query_time_per_query');\nINSERT INTO `metric_dictionary_info` VALUES (4989, '基本性能指标', 'Fetch耗时', '节点索引Fetch耗时平均值，Top节点趋势', '60S', '[平均值] ,间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.search.fetch_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.search.fetch_total的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:37:46', 1, 0, NULL, 'indices-search-fetch_time_per_fetch');\nINSERT INTO `metric_dictionary_info` VALUES (4991, '基本性能指标', 'Scroll当下请求量', '节点索引Scroll请求量，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.search.scroll_current的值', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:37:56', 1, 0, NULL, 'indices-search-scroll_current');\nINSERT INTO `metric_dictionary_info` VALUES (4993, '基本性能指标', 'Scroll请求耗时', '节点Scroll耗时平均值，Top节点趋势', '60S', '[平均值] ,间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.search.scroll_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.search.scroll_total的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:38:05', 1, 0, NULL, 'indices-search-scroll_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (4995, '基本性能指标', 'Merge操作耗时', '节点Merge耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.merges.total_time_in_millis的差值/间隔时间内nodes.{nodeName}.indices.merges.total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:42:21', 1, 0, NULL, 'indices-merges_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (4997, '基本性能指标', 'Refresh操作耗时', '节点Refresh耗时平均值，Top节点趋势', '60S', '[平均值]间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.refresh.total_time_in_millis的差值/间隔时间内nodes.{nodeName}.indices.refresh.total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:42:29', 1, 0, NULL, 'indices-refresh_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (4999, '基本性能指标', 'Flush操作耗时', '节点Flush耗时平均值，Top节点趋势', '60S', '[平均值]间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.flush.total_time_in_millis的差值/间隔时间内nodes.{nodeName}.indices.flush.total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:45:15', 1, 0, NULL, 'indices-flush_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (5000, '基本性能指标', 'request Cache eviction', '节点Request Cache缓存驱逐数，Top节点趋势', '当前值', '[差值] 间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.request_cache.evictions的差值/时间间隔(S)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:57:08', 1, 0, NULL, 'indices-request_cache-evictions');\nINSERT INTO `metric_dictionary_info` VALUES (5001, '基本性能指标', 'Write Rejected个数', '节点写入拒绝数，Top节点趋势', '60S', '[平均值]间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.thread_pool.bulk.rejected的差值/时间间隔', 1, '个/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 10:00:54', 1, 0, NULL, 'thread_pool-bulk-rejected');\nINSERT INTO `metric_dictionary_info` VALUES (5003, '基本性能指标', 'Write Queue个数', '节点写入队列堆积数，Top节点趋势', '当前值', '[当前值]  _nodes/stats命令获取nodes.{nodeName}.thread_pool.bulk.queue', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:05:43', 1, 0, NULL, 'thread_pool-bulk-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5005, '基本性能指标', 'Search Queue个数', '节点查询队列堆积数，Top节点趋势', '当前值', '[当前值]  _nodes/stats命令获取nodes.{nodeName}.thread_pool.search.queue', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:45:52', 1, 0, NULL, 'indices-search-query_total');\nINSERT INTO `metric_dictionary_info` VALUES (5007, '基本性能指标', 'Search Rejected个数', '节点查询拒绝数，Top节点趋势', '60S', '[差值] 间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.thread_pool.search.rejected的差值/时间间隔(MIN)', 1, '个/MIN', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 10:01:05', 1, 0, NULL, 'thread_pool-search-rejected');\nINSERT INTO `metric_dictionary_info` VALUES (5009, '基本性能指标', 'Merge次数', '节点Merge次数，Top节点趋势', '60S', '[差值] 间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.merges.total的差值/时间间隔(MIN)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:46:27', 1, 0, NULL, 'indices-merges-total');\nINSERT INTO `metric_dictionary_info` VALUES (5011, '基本性能指标', 'Refresh次数', '节点Refresh次数，Top节点趋势', '60S', '[差值] 间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.refresh.total的差值/时间间隔(MIN)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:46:40', 1, 0, NULL, 'indices-refresh-total');\nINSERT INTO `metric_dictionary_info` VALUES (5013, '基本性能指标', 'Flush次数', '节点Flush次数，Top节点趋势', '60S', '[差值] 间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.flush.total的差值/时间间隔(MIN)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:46:56', 1, 0, NULL, 'indices-flush-total');\nINSERT INTO `metric_dictionary_info` VALUES (5015, '基本性能指标', 'Query Cache内存命中率', '节点Query Cache内存命中率，Top节点趋势', '', '[当前值] 通过_nodes/stats命令获取nodes.{nodeName}.indices.query_cache.hit_count/nodes.{nodeName}.indices.query_cache.total_count', 0, '%', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 14:27:12', 1, 0, NULL, 'indices-query_cache-hit_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5017, '基本性能指标', 'Reques Cache内存命中率', '节点Reques Cache内存命中率，Top节点趋势', '', '[当前值] 通过_nodes/stats命令获取nodes.{nodeName}.indices.request_cache.hit_count/(nodes.{nodeName}.indices.request_cache.hit_count+nodes.{nodeName}.indices.request_cache.miss_count)', 0, '%', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 14:27:13', 1, 0, NULL, 'indices-request_cache-hit_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5019, '内存大小指标', 'Query Cache内存大小', '节点所有Shard Query Cache(Cached Filters/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.query_cache.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:22', 1, 0, NULL, 'indices-query_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5021, '内存大小指标', 'Request Cache内存大小', '节点所有Shard Request Cache(Cached Aggregation Results/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.request_cache.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:40', 1, 0, NULL, 'indices-request_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5023, '高级性能指标', '未提交的Translog大小', '节点所有Shard未提交Translog的大小累加值，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.translog.uncommitted_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:47:50', 1, 0, NULL, 'indices-translog-uncommitted_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5025, '高级性能指标', 'Http活跃连接数', '节点的Http活跃连接数，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.http.current_open', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:47:57', 1, 0, NULL, 'http-current_open');\nINSERT INTO `metric_dictionary_info` VALUES (5027, '高级性能指标', 'Segement数 ', '节点所有Shard的Segment汇总数，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.segments.count', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:48:05', 1, 0, NULL, 'indices-segments-count');\nINSERT INTO `metric_dictionary_info` VALUES (5029, '高级性能指标', 'Segement内存大小', '节点所有Shard的Segment底层Lucene内存汇总占用，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.segments.memory_in_bytes', 1, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:48:13', 1, 0, NULL, 'indices-segments-memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5031, '内存大小指标', 'Terms内存大小', '节点所有Shard的Segment底层Terms(Text/Keyword/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.segments.term_vectors_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:53:27', 1, 0, NULL, 'indices-segments-term_vectors_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5033, '内存大小指标', 'Points内存大小', '节点所有Shard的Segment底层Points(Numbers/IPs/Geo/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.segments.points_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:53:41', 1, 0, NULL, 'indices-segments-points_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5035, '内存大小指标', 'Doc Values内存大小', '节点所有Shard的Doc Values内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.segments.doc_values_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:53:57', 1, 0, NULL, 'indices-segments-doc_values_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5037, '内存大小指标', 'Index Writer内存大小', '节点所有Shard的Index Writer内存大小累加值，不在Lucene内存占用统计范围内,Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.segments.index_writer_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:04', 1, 0, NULL, 'indices-segments-index_writer_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5039, '高级性能指标', '文档总数', '节点所有Shard索引文档数累加值，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.docs.count', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:49:31', 1, 0, NULL, 'indices-docs-count');\nINSERT INTO `metric_dictionary_info` VALUES (5041, '高级性能指标', '总存储大小', '节点所有Shard索引存储大小累加值，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.store.size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:49:38', 1, 0, NULL, 'indices-store-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5043, '高级性能指标', '执行任务耗时', '节点执行任务平均耗时，Top节点趋势', '当前值', '[平均值] _cat/tasks?v&detailed&format=json命令根据node筛选并获取running_time的平均值', 0, 'S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:50:50', 1, 0, NULL, 'runningTime');\nINSERT INTO `metric_dictionary_info` VALUES (5045, '高级性能指标', '执行任务数量', '节点执行任务总数量，Top节点趋势', '当前值', '[当前值] _cat/tasks?v&detailed&format=json命令根据node筛选并获取到的集合大小', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:05:00', 1, 0, NULL, 'taskId');\nINSERT INTO `metric_dictionary_info` VALUES (5047, '内存大小指标', 'Stored Fields大小', '节点所有Shard Stored Fields(_source/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.indices.segments.stored_fields_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:50', 1, 0, NULL, 'indices-segments-stored_fields_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5049, '内存大小指标', 'Norms内存大小', '节点所有Shard Norms(normalization factors for query time/text scoring)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取indices.segments.norms_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:59', 1, 0, NULL, 'indices-segments-norms_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5051, '内存大小指标', 'Version Map内存大小', '节点所有Shard Version Map(update/delete)内存大小累加值，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取indices.segments.version_map_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:55:09', 1, 0, NULL, 'indices-segments-version_map_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5053, '内存大小指标', 'Fixed Bitsets内存大小', '节点所有Shard Fixed Bitsets(deeply nested object/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取indices.segments.fixed_bit_set_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:55:20', 1, 0, NULL, 'indices-segments-fixed_bit_set_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5055, '内存大小指标', 'Fielddata内存大小', '节点所有Shard的Fielddata(global ordinals /enable fielddata on text field/...)内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取indices.segments.breakers.fielddata.estimated_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-25 14:43:19', 1, 0, NULL, 'indices-segments-breakers-fielddata-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5057, '高级性能指标', '写入线程池queue数', '节点写入线程池队列当前值', '当前值', '[当前值] _nodes/stats命令获取thread_pool.write.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-write-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5059, '高级性能指标', '查询线程池queue数', '节点查询线程池池队列当前值', '当前值', '[当前值] _nodes/stats命令获取thread_pool.search.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-08 18:39:32', 1, 0, NULL, 'thread_pool-search-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5061, '高级性能指标', '刷新线程池queue数', '节点刷新线程池队列当前值', '当前值', '[当前值] _nodes/stats命令获取thread_pool.refresh.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-refresh-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5063, '高级性能指标', '落盘线程池queue数', '节点落盘线程池队列当前值', '当前值', '[当前值] _nodes/stats命令获取thread_pool.rollup_indexing.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-rollup_indexing-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5065, '高级性能指标', '管理线程池queue数', '节点管理线程池队列当前值', '当前值', '[当前值] _nodes/stats命令获取thread_pool.management.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-management-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5067, '高级性能指标', '合并线程池queue数', '节点合并线程池队列当前值', '当前值', '[当前值] _nodes/stats命令获取thread_pool.force_merge.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-force_merge-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5069, 'JVM指标', 'Young GC次数', '节点Young GC次数，Top节点趋势', '60S', '[平均值]当前时刻减去上一时刻通过_nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.young.collection_count的值/时间间隔', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:40', 1, 0, NULL, 'jvm-gc-young-collection_count_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5071, 'JVM指标', 'Old GC次数', '节点Old GC次数，Top节点趋势', '60S', '[平均值]当前时刻减去上一时刻通过_nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.old.collection_count的值/时间间隔', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:33', 1, 0, NULL, 'jvm-gc-old-collection_count_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5073, 'JVM指标', 'Young GC耗时', '节点Young GC平均耗时，Top节点趋势', '60S', '[差值]  间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.young.collection_time_in_millis的差值/ 间隔时间内nodes.{nodeName}.jvm.gc.collectors.young.collection_count的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:26', 1, 0, NULL, 'jvm-gc-young-collection_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (5075, 'JVM指标', 'Old GC耗时', '节点Old GC平均耗时，Top节点趋势', '60S', '[差值]  间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.old.collection_time_in_millis的差值/ 间隔时间内nodes.{nodeName}.jvm.gc.collectors.old.collection_count的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:17', 1, 0, NULL, 'jvm-gc-old-collection_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (5077, 'JVM指标', 'JVM堆内存使用量', '节点JVM堆内存使用量，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.jvm.mem.heap_used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:52', 1, 0, NULL, 'jvm-mem-heap_used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5079, 'JVM指标', 'JVM堆外存使用量', '节点JVM堆外存使用量，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.jvm.mem.non_heap_used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:44', 1, 0, NULL, 'jvm-mem-non_heap_used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5081, 'JVM指标', 'JVM堆使用率', '节点JVM堆使用率，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.jvm.mem.heap_used_percent', 1, '%', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:18', 1, 0, NULL, 'jvm-mem-heap_used_percent');\nINSERT INTO `metric_dictionary_info` VALUES (5083, 'JVM指标', '堆内存young区使用空间', '节点年轻代堆内存使用空间，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.jvm.mem.pools.young.used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:10', 1, 0, NULL, 'jvm-mem-pools-young-used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5085, 'JVM指标', '堆内存old区使用空间', '节点老年代堆内存使用空间，Top节点趋势', '当前值', '[当前值] _nodes/stats命令获取nodes.{nodeName}.jvm.mem.pools.old.used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:03', 1, 0, NULL, 'jvm-mem-pools-old-used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5087, 'breaker指标', 'Field data circuit breaker 内存占用', '统计当前fielddata占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] _nodes/stats命令获取breakers.fielddata.limit_size_in_bytes[阈值]，breakers.fielddata.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:16:52', 1, 0, NULL, 'breakers-fielddata-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5089, 'breaker指标', 'Request circuit breaker 内存占用', '统计当前请求(比如聚合请求临时内存构建）占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] _nodes/stats命令获取breakers.request.limit_size_in_bytes[阈值]，breakers.request.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:03', 1, 0, NULL, 'breakers-request-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5090, '基本性能指标', 'query Cache evictions', '节点Query Cache缓存驱逐数，Top节点趋势', '当前值', '[差值] 间隔时间内通过_nodes/stats命令获取nodes.{nodeName}.indices.query_cache.evictions的差值/时间间隔(S)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:56:51', 1, 0, NULL, 'indices-query_cache-evictions');\nINSERT INTO `metric_dictionary_info` VALUES (5091, 'breaker指标', 'inflight requests circuit breaker 内存占用', '统计当前请求body占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] _nodes/stats命令获取breakers.in_flight_requests.limit_size_in_bytes[阈值]，breakers.in_flight_requests.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:04', 1, 0, NULL, 'breakers-in_flight_requests-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5093, 'breaker指标', 'Accounting requests circuit breaker 内存占用', '统计当前请求结束后不能释放的对象(例如segment常驻的内存占用)所占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] _nodes/stats命令获取breakers.accounting.limit_size_in_bytes[阈值]，breakers.accounting.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:29', 1, 0, NULL, 'breakers-accounting-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5095, 'breaker指标', 'Script compilation circuit breaker 编译次数', '统计一段时间内脚本编译次数，与阀值比较，超过则熔断请求', '当前值', '[平均值] 当前时刻减去上个时刻通过_nodes/stats命令获取script.compilations的数量差值/时间间隔MIN', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-11 14:58:57', 1, 0, NULL, 'script-compilations');\nINSERT INTO `metric_dictionary_info` VALUES (5097, 'breaker指标', 'Parent circuit breaker JVM真实内存占用', '统计JVM真实内存占用，与阀值比较，超过则熔断请求', '当前值', '[当前值] _nodes/stats命令获取breakers.parent.limit_size_in_bytes[阈值]，breakers.parent.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:33', 1, 0, NULL, 'breakers-parent-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5099, '索引基础指标', '索引Shard数', '索引Shard个数，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_shards.total', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:16', 1, 0, NULL, 'shardNu');\nINSERT INTO `metric_dictionary_info` VALUES (5101, '索引基础指标', '索引存储大小', '索引存储总大小，Top节点趋势', '当前值', '[当前值] {indexName}/stats?level=shards命令获取_all.total.store.size_in_bytes', 0, 'GB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:16', 1, 0, NULL, 'store-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5103, '索引基础指标', '文档总数', '索引的文档总数，Top节点趋势', '当前值', '[当前值] {indexName}/stats?level=shards命令获取_all.total.docs.count', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, 'docs-count');\nINSERT INTO `metric_dictionary_info` VALUES (5105, '索引性能指标', '写入TPS', '索引写入速率平均值，Top节点趋势', '60S', '[平均值] ( 间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.docs.count的差值)/时间间隔(S)', 1, '个/S', '折线', 1, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 09:23:43', 1, 0, NULL, 'indexing-index_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5107, '索引性能指标', '写入耗时', '索引写入耗时平均值，Top节点趋势', '60S', '[平均值] ( 间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.indexing.index_time_in_millis的差值)/ 间隔时间内_all.total.docs.count的差值', 1, 'MS', '折线', 1, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-25 18:02:13', 1, 0, NULL, 'indices-indexing-index_time_per_doc');\nINSERT INTO `metric_dictionary_info` VALUES (5109, '索引性能指标', '网关写入TPS', 'Index通过网关的每秒写入请求数', '60S', '[平均值] ( 间隔时间内通过查询网关索引获取命中写入条件总数的差值)/时间间隔(S)', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5111, '索引性能指标', '网关写入耗时', 'Index通过网关的写入平均耗时', '60S', '[平均值]  间隔时间内通过查询网关索引获取命中写入条件耗时的平均值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5113, '索引性能指标', '网关查询QPS', 'Index通过网关的每秒查询请求量', '60S', '[平均值] ( 间隔时间内通过查询网关索引获取命中查询总数的差值)/时间间隔(S)', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5115, '索引性能指标', '网关查询耗时', 'Index通过网关的查询平均耗时', '60S', '[平均值]  间隔时间内通过查询网关索引获取命中查询耗时的平均值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5117, '索引性能指标', '查询Query QPS', '索引Query速率平均值，Top节点趋势', '60S', '[平均值] ( 间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.search.query_total的差值)/时间间隔(S)', 1, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, 'search-query_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5119, '索引性能指标', 'Fetch QPS', '索引Fetch速率平均值，Top节点趋势', '60S', '[平均值] ( 间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.search.fetch_total的差值)/时间间隔(S)', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-11 11:23:19', 1, 0, NULL, 'search-fetch_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5121, '索引性能指标', '查询Query耗时', '索引Query耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.search.query_time_in_millis的差值/ 间隔时间内_all.total.search.query_total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:14:56', 1, 0, NULL, 'cost-query_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5123, '索引性能指标', '查询Fetch耗时', '索引Fetch耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.search.fetch_time_in_millis的差值/ 间隔时间内_all.total.search.fetch_total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:15:06', 1, 0, NULL, 'cost-fetch_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5125, '索引性能指标', '查询Scroll量', '索引间隔时间内所有Shard Scroll请求量，Top节点趋势', '60S', '[平均值] ( 间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.search.scroll_total的差值)/时间间隔(S)', 0, '个', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:02', 1, 0, NULL, 'search-scroll_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5127, '索引性能指标', '查询Scroll耗时', '索引Scorll耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.search.scroll_time_in_millis的差值/ 间隔时间内_all.total.search.scroll_total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:19:31', 1, 0, NULL, 'cost-scroll_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5129, '索引性能指标', 'Merge耗时', '索引Merge耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.merges.total_time_in_millis的差值/ 间隔时间内_all.total.merges.total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:17:24', 1, 0, NULL, 'cost-merges-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5131, '索引性能指标', 'Refresh耗时', '索引Refresh耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.refresh.total_time_in_millis的差值/ 间隔时间内_all.total.refresh.total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:17:39', 1, 0, NULL, 'cost-refresh-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5133, '索引性能指标', 'Flush耗时', '索引Flush耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.indices.flush.total_time_in_millis的差值/ 间隔时间内_all.total.indices.flush.total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:18:08', 1, 0, NULL, 'cost-flush-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5135, '索引性能指标', 'Merge次数', '索引Merge次数，Top节点趋势', '60S', '[平均值] ( 间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.merges.total的差值)/时间间隔(MIN)', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:02', 1, 0, NULL, 'merges-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5137, '索引性能指标', 'Refresh次数', '索引Refresh次数，Top节点趋势', '60S', '[平均值] ( 间隔时间内通过{indexName}/stats?level=shards命令获取_all.total.refresh.total的差值)/时间间隔(MIN)', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:02', 1, 0, NULL, 'refresh-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5139, '索引性能指标', 'Flush次数', '索引Flush次数，Top节点趋势', '60S', '[平均值] ( 间隔时间内通过{indexName}/stats?level=shards命令获取flush.total的差值)/时间间隔(MIN)', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:03', 1, 0, NULL, 'flush-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5141, '索引内存指标', 'Segements大小', '索引所有Shard的Segment底层Lucene内存汇总占用，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.primaries.segments.memory_in_bytes', 1, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:03', 1, 0, NULL, 'segments-memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5143, '索引内存指标', 'Terms内存大小', '索引所有Shard的Segment底层Terms(Text/Keyword/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.primaries..segments.term_vectors_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:03', 1, 0, NULL, 'segments-term_vectors_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5145, '索引内存指标', 'Points内存大小', '索引所有Shard的Segment底层Points(Numbers/IPs/Geo/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.primaries..segments.points_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:03', 1, 0, NULL, 'segments-points_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5147, '索引内存指标', 'Doc Values内存大小', '索引所有Shard的Doc Values内存大小，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.primaries..segments.doc_values_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:03', 1, 0, NULL, 'segments-doc_values_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5149, '索引内存指标', 'Index Writer内存大小', '索引所有Shard的Index Writer内存大小，不在Lucene内存占用统计范围内,Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.primaries.segments.index_writer_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:03', 1, 0, NULL, 'segments-index_writer_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5151, '索引内存指标', '未提交的Translog大小', '索引所有Shard的未提交Translog的大小累加值，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.primaries.translog.uncommitted_size_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:04', 1, 0, NULL, 'translog-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5153, '索引内存指标', 'Query Cache内存大小', '索引所有Shard Query Cache(Cached Filters/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] {indexName}_/stats?level=shards命令获取_all.primaries.query_cache.memory_size_in_bytes', 1, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:04', 1, 0, NULL, 'query_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5155, '索引内存指标', 'Stored Fields大小', '索引stored_fields_memory内存大小', '当前值', '[当前值] {indexName}_/stats?level=shards命令获取_all.primaries.segments.stored_fields_memory_in_bytes', 0, 'MB', NULL, 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:04', 1, 0, NULL, 'segments-stored_fields_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5157, '索引内存指标', 'Norms内存大小', '索引所有Shard Norms(normalization factors for query time/text scoring)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}_/stats?level=shards命令获取_all.primaries.segments.norms_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:04', 1, 0, NULL, 'segments-norms_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5159, '索引内存指标', 'Version Map内存大小', '索引所有Shard Version Map(update/delete)内存大小累加值，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] {indexName}_/stats?level=shards命令获取_all.primaries.segments.version_map_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:04', 1, 0, NULL, 'segments-version_map_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5161, '索引内存指标', 'Fixed Bitsets内存大小', '索引所有Shard Fixed Bitsets(deeply nested object/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}_/stats?level=shards命令获取_all.primaries.segments.fixed_bit_set_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:04', 1, 0, NULL, 'segments-fixed_bit_set_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5163, '索引内存指标', 'Fielddata内存大小', '索引所有Shard Fielddata(global ordinals /enable fielddata on text field/...)内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] {indexName}_/stats?level=shards命令获取_all.primaries.fielddata.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:05', 1, 0, NULL, 'fielddata-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5165, '索引内存指标', 'Request Cache内存大小', '索引所有Shard Request Cache(Cached Aggregation Results/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] {indexName}_/stats?level=shards命令获取_all.primaries.segments.request_cache.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:05', 1, 0, NULL, 'segments-request_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5167, '索引模板基础指标', '索引Shard数', '索引模板下索引Shard个数，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取shards数量之和', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:05', 1, 0, NULL, 'shardNu');\nINSERT INTO `metric_dictionary_info` VALUES (5169, '索引模板基础指标', '索引存储大小', '索引模板下索引Shard存储总大小，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.primaries.store-size_in_bytes之和', 0, 'GB', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:05', 1, 0, NULL, 'store-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5171, '索引模板基础指标', '文档总数', '索引模板下索引的文档数，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.primaries.docs.count之和', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:05', 1, 0, NULL, 'docs-count');\nINSERT INTO `metric_dictionary_info` VALUES (5173, '索引模板性能指标', '写入TPS', '索引模板写入速率平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过{indexName}/stats?level=shards命令获取 _all.primaries.search.query_total的差值累加值/间隔时间', 1, '个/S', '折线', 1, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:45:23', 1, 0, NULL, 'indexing-index_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5175, '索引模板性能指标', '写入耗时', '索引模板写入耗时平均值，Top节点趋势', '60S', '[平均值] 获取 间隔时间内模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.primaries..search-query_time_in_millis的差值再累加值/间隔时间', 1, 'MS', '折线', 1, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-25 14:24:23', 1, 0, NULL, 'indices-indexing-index_time_per_doc');\nINSERT INTO `metric_dictionary_info` VALUES (5177, '索引模板性能指标', '查询Query QPS', '索引模板Query速率平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过{indexName}/stats?level=shards命令获取 all.primaries.search.query_total的差值累加值/间隔时间', 1, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:46:46', 1, 0, NULL, 'search-query_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5179, '索引模板性能指标', '网关写入TPS', 'IndexTemplate所属Index通过网关的每秒写入请求数', '60S', NULL, 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5181, '索引模板性能指标', '网关写入耗时', 'IndexTemplate所属Index通过网关的写入平均耗时', '60S', NULL, 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5183, '索引模板性能指标', '网关查询QPS', 'IndexTemplate所属Index通过网关的每秒查询请求量', '60S', NULL, 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5185, '索引模板性能指标', '网关查询耗时', 'IndexTemplate所属Index通过网关的查询平均耗时', '60S', NULL, 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:07', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5187, '索引模板性能指标', '查询Fetch QPS', '索引模板Fetch速率平均值，Top节点趋势', '60S', '[平均值]  间隔时间内获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.search.fetch_total的差值累加值/时间间隔', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:58:35', 1, 0, NULL, 'search-fetch_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5189, '索引模板性能指标', '查询Query耗时', '索引模板Query耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过{indexName}/stats?level=shards命令_all.total.search.query_time_in_millis的差值累加值/_all.total.search.query_total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:57:12', 1, 0, NULL, 'cost-query_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5191, '索引模板性能指标', '查询Fetch耗时', '索引模板Fetch耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.search.fetch_time_in_millis的差值累加值/_all.total.search.fetch_total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:59:22', 1, 0, NULL, 'cost-fetch_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5193, '索引模板性能指标', '查询Scroll量', '索引模板下索引Shard 级别 Scroll请求量，Top节点趋势', '60S', '[平均值] 获取间隔时间内模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.search.scroll_total的差值累加值/时间间隔', 0, '个', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:44:38', 1, 0, NULL, 'search-scroll_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5195, '索引模板性能指标', '查询Scroll耗时', '索引模板Scorll耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.search.scroll_time_in_millis的差值累加值/_all.total.search.scroll_total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-30 11:19:09', 1, 0, NULL, 'cost-scroll_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5197, '索引模板性能指标', 'Merge耗时', '索引模板Merge耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.merges.total_time_in_millis的差值累加值/_all.total.merges.total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:08', 1, 0, NULL, 'cost-merges-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5199, '索引模板性能指标', 'Refresh耗时', '索引模板Refresh耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.refresh.total_time_in_millis的差值累加值/_all.total.refresh.total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, 'cost-refresh-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5201, '索引模板性能指标', 'Flush耗时', '索引模板Flush耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.flush.total_time_in_millis的差值累加值/all.total.flush.total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, 'cost-flush-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5203, '索引模板性能指标', 'Merge次数', '索引模板Merge次数，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.merges.total的差值累加值/时间间隔', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:59:59', 1, 0, NULL, 'merges-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5205, '索引模板性能指标', 'Refresh次数', '索引模板Refresh次数，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.refresh.total的差值累加值/时间间隔', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:57:58', 1, 0, NULL, 'refresh-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5207, '索引模板性能指标', 'Flush次数', '索引模板Flush次数，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.flush-total_rate的累加值差值/时间间隔', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'flush-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5209, '索引模板内存指标', 'Segements大小', '索引模板下索引所有Shard的Segment底层Lucene内存汇总占用，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.segments.memory_in_bytes的总和', 1, 'MB', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'segments-memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5211, '索引模板内存指标', 'Terms内存大小', '索引模板下索引所有Shard的Segment底层Terms(Text/Keyword/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.segments.term_vectors_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'segments-term_vectors_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5213, '索引模板内存指标', 'Points内存大小', '索引模板下索引所有Shard的Segment底层Points(Numbers/IPs/Geo/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.segments.points_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'segments-points_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5215, '索引模板内存指标', 'Doc Values内存大小', '索引模板下索引所有Shard的Doc Values内存大小，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.segments.doc_values_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'segments-doc_values_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5217, '索引模板内存指标', 'Index Writer内存大小', '索引模板下索引所有Shard的Index Writer内存大小，不在Lucene内存占用统计范围内,Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.segments.index_writer_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'segments-index_writer_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5219, '索引模板内存指标', '未提交的Translog大小', '索引模板下索引所有Shard的未提交Translog的大小累加值，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.translog.uncommitted_size_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'translog-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5221, '索引模板内存指标', 'Query Cache内存大小', '索引模板下索引所有Shard Query Cache(Cached Filters/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.query_cache.memory_size_in_bytes的总和', 1, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'query_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5223, '索引模板内存指标', 'Stored Fields大小', '索引模板下索引stored_fields_memory内存大小', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取_all.total.segments.stored_fields_memory_in_bytes的总和', 0, NULL, NULL, 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:12', 1, 0, NULL, 'segments-stored_fields_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5225, '索引模板内存指标', 'Norms内存大小', '索引模板下索引所有Shard Norms(normalization factors for query time/text scoring)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取segments-norms_memory_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:12', 1, 0, NULL, 'segments-norms_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5227, '索引模板内存指标', 'Version Map内存大小', '索引模板下索引所有Shard Version Map(update/delete)内存大小累加值，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取segments-version_map_memory_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:12', 1, 0, NULL, 'segments-version_map_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5229, '索引模板内存指标', 'Fixed Bitsets内存大小', '索引模板下索引所有Shard Fixed Bitsets(deeply nested object/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取fixed_bit_set_memory_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:12', 1, 0, NULL, 'segments-fixed_bit_set_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5231, '索引模板内存指标', 'Fielddata内存大小', '索引模板下索引所有Shard Fielddata(global ordinals /enable fielddata on text field/...)内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取fielddata.memory_size_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:12', 1, 0, NULL, 'fielddata-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5233, '索引模板内存指标', 'Request Cache内存大小', '索引模板下索引所有Shard Request Cache(Cached Aggregation Results/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/stats?level=shards命令获取request_cache.memory_size_in_bytes的总和', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:12', 1, 0, NULL, 'segments-request_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5235, '集群', '集群健康状态', '不同健康状态集群分布感知，快速定位故障集群', '当前值', '[当前值] 通过_cluster/health命令获取status', 0, NULL, '状态栏', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 15:18:40', 1, 0, NULL, 'health');\nINSERT INTO `metric_dictionary_info` VALUES (5237, '集群', '指标采集延时', '指标数据质量风险集群预警', '当前值', '[当前值] 采集数据最近一个时间点和当前时间点的差值', 0, 'S', '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:01', 1, 0, NULL, 'clusterElapsedTimeGte5Min');\nINSERT INTO `metric_dictionary_info` VALUES (5239, '集群', 'shard个数大于10000集群', 'Shard膨胀风险集群预警', '当前值', '[当前值] 通过_cat/health?format=json获取shards总数量(包括unassign状态)', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-10 15:49:42', 1, 0, NULL, 'shardNum');\nINSERT INTO `metric_dictionary_info` VALUES (5241, '集群', '写入耗时', '索引写入性能对比分析，性能不足集群预警', '5*60S', '[平均值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.docs.count差值累加值', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-09 19:32:27', 1, 0, NULL, 'indexingLatency');\nINSERT INTO `metric_dictionary_info` VALUES (5243, '集群', 'node_stats接口平均采集耗时', 'Master指标采集性能问题集群预警', '当前值', '[当前值] 调用一次_nodes/stats命令所消耗的时间', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-10 15:50:23', 1, 0, NULL, 'nodeElapsedTime');\nINSERT INTO `metric_dictionary_info` VALUES (5245, '集群', '集群pending task数', 'pending task持续堆积，Master元数据处理性能问题集群预警', '当前值', '[当前值] 通过 _cluster/health命令获取number_of_pending_tasks', 0, '个', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:23', 1, 0, NULL, 'pendingTaskNum');\nINSERT INTO `metric_dictionary_info` VALUES (5247, '集群', '网关失败率', '各组网关业务查询健康预警', '5*60S', '5分钟执行一次，获取近一分钟内的网关失败率', 0, '%', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:26', 1, 0, NULL, 'gatewayFailedPer');\nINSERT INTO `metric_dictionary_info` VALUES (5249, '集群', '查询耗时', '索引查询性能对比分析，查询性能不足集群预警', '5*60S', '[平均值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.search.query_total差值累加值', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-09 19:32:45', 1, 0, NULL, 'searchLatency');\nINSERT INTO `metric_dictionary_info` VALUES (5251, '节点', '节点执行任务耗时', '节点执行任务平均耗时高', '5*60S', '[平均值]根据_cat/tasks?v&detailed&format=json命令获取到当前时间的各节点任务执行总和/节点执行的次数', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:56', 1, 0, NULL, 'taskConsuming');\nINSERT INTO `metric_dictionary_info` VALUES (5253, '节点', '磁盘利用率超红线节点', '磁盘利用率超安全水位节点预警', '当前值', '[当前值]根据node/stats命令获取到(nodes.{nodeName}.fs.total-nodes.{nodeName}.fs.free_in_bytes)/nodes.{nodeName}.fs.total大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:34', 1, 0, NULL, 'largeDiskUsage');\nINSERT INTO `metric_dictionary_info` VALUES (5255, '节点', '分片个数大于500节点', '分片数超安全水位节点预警', '当前值', '[当前值]根据_cat/shards?v&h=node命令获取到结果个数大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:55:51', 1, 0, NULL, 'shardNum');\nINSERT INTO `metric_dictionary_info` VALUES (5257, '节点', '堆内存利用率超红线节点', '堆内存利用率超红线节点预警', '当前值', '[当前值]根据node/stats命令获取nodes.{nodeName}.jvm.mem.heap_used_percent大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:28', 1, 0, NULL, 'largeHead');\nINSERT INTO `metric_dictionary_info` VALUES (5259, '节点', 'CPU利用率超红线节点', 'CPU利用率超红线节点预警', '当前值', '[当前值]根据node/stats命令获取到nodes.{nodeName}.os.cpu.percent大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:32', 1, 0, NULL, 'largeCpuUsage');\nINSERT INTO `metric_dictionary_info` VALUES (5261, '节点', 'SearchRejected节点', 'SearchRejected节点预警', '5*60S', '[当前值]当前时间和上次时间通过_nodes/stats命令nodes.{nodeName}.thread_pool.search.rejected差值不为0的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:41', 1, 0, NULL, 'searchRejectedNum');\nINSERT INTO `metric_dictionary_info` VALUES (5263, '节点', 'WriteRejected节点', 'WriteRejected节点预警', '5*60S', '[当前值]当前时间和上次时间通过_nodes/stats命令nodes.{nodeName}.thread_pool.write.rejected差值不为0的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:43', 1, 0, NULL, 'writeRejectedNum');\nINSERT INTO `metric_dictionary_info` VALUES (5265, '索引', 'segments内存大于1MB索引模板', '索引模板超大内存占用风险预警', '当前值', '[当前值]根据_cat/segments/命令获取size字段大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:59:56', 1, 1, 'segments内存大于1MB索引模板', 'tplSegmentMemSize');\nINSERT INTO `metric_dictionary_info` VALUES (5267, '索引', 'segments个数大于20索引模板', '索引模板Segements数超红线预警', '当前值', '[当前值]根据_cat/segments/命令获取segment个数大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:59:58', 1, 0, NULL, 'tplSegmentNum');\nINSERT INTO `metric_dictionary_info` VALUES (5269, '索引', '未分配shard索引', 'shard未分配索引预警', '当前值', '[当前值]根据GET {indexName}/stats命令获取索引状态不等于green的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:09', 1, 0, NULL, 'unassignedShard');\nINSERT INTO `metric_dictionary_info` VALUES (5271, '索引', 'mapping字段个数大于100索引', '索引mapping字段膨胀预警', '当前值', '[当前值]根据GET {indexName}命令mapping的字段个数大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:13', 1, 0, NULL, 'mappingNum');\nINSERT INTO `metric_dictionary_info` VALUES (5273, '索引', 'segments内存大于100B索引', '索引超大内存占用风险预警', '当前值', '[当前值]根据_cat/segments/命令获取segment内存（size）大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:20', 1, 0, NULL, 'segmentMemSize');\nINSERT INTO `metric_dictionary_info` VALUES (5275, '索引', 'segments个数大于100索引', '索引Segements数超红线预警', '当前值', '[当前值]根据_cat/segments/命令获取segment个数大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:24', 1, 0, NULL, 'segmentNum');\nINSERT INTO `metric_dictionary_info` VALUES (5277, '索引', 'RED索引', 'RED索引预警', '当前值', '[当前值]根据_cat/indices?format=json命令获取健康状态(health)等于red的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:59', 1, 0, NULL, 'red');\nINSERT INTO `metric_dictionary_info` VALUES (5279, '索引', '单个shard大于500MB索引', '单Shard过大索引预警', '当前值', '[当前值]根据_cat/shards命令获取大小大于指定的阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:57:51', 1, 0, NULL, 'bigShard');\nINSERT INTO `metric_dictionary_info` VALUES (5281, '索引', '无副本索引', '无副本索引稳定性预警', '当前值', '[当前值]根据_cat/indices命令获取副本数等于0的索引', 0, NULL, '列表', 0, NULL, NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:25:12', 1, 0, NULL, 'singReplicate');\nINSERT INTO `metric_dictionary_info` VALUES (5283, '索引', '单个shard小于500MB索引', '索引Shard数分配不合理预警', '当前值', '[当前值]根据_cat/shards命令获取大小(store)小于指定的阀值并且shard数量大于1的索引', 0, NULL, '列表', 0, NULL, NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:58:06', 1, 0, NULL, 'smallShard');\n\nDROP TABLE IF EXISTS `arius_config_info`;\nCREATE TABLE `arius_config_info`  (\n                                      `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n                                      `value_group` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置项组',\n                                      `value_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置项名字',\n                                      `value` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '配置项的值',\n                                      `edit` int(4) NOT NULL DEFAULT 1 COMMENT '是否可以编辑 1 不可编辑（程序获取） 2 可编辑',\n                                      `dimension` int(4) NOT NULL DEFAULT -1 COMMENT '配置项维度 1 集群 2 模板 ',\n                                      `status` int(4) NOT NULL DEFAULT 1 COMMENT '1 正常 2 禁用 -1 删除',\n                                      `memo` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '备注',\n                                      `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n                                      `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n                                      `search_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '配置查询时间',\n                                      PRIMARY KEY (`id`) USING BTREE,\n                                      INDEX `idx_group_name`(`value_group`, `value_name`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1686 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'arius配置项' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Records of arius_config_info\n-- ----------------------------\nINSERT INTO `arius_config_info` VALUES (187, 'arius.cache.switch', 'logic.template.cache.enable', 'true', 1, -1, -1, '逻辑模板缓存是否开启', '2021-09-01 20:37:47', '2021-11-29 14:57:47', '2021-09-01 20:37:47');\nINSERT INTO `arius_config_info` VALUES (189, 'arius.cache.switch', 'physical.template.cache.enable', 'true', 1, -1, -1, '获取物理模板列表是否开启全局缓存', '2021-09-01 20:41:22', '2021-11-29 14:57:45', '2021-09-01 20:41:22');\nINSERT INTO `arius_config_info` VALUES (191, 'arius.cache.switch', 'cluster.phy.cache.enable', 'true', 1, -1, -1, '获取物理集群列表是否开启全局缓存', '2021-09-01 20:42:31', '2021-11-29 14:57:42', '2021-09-01 20:42:31');\nINSERT INTO `arius_config_info` VALUES (193, 'arius.cache.switch', 'cluster.logic.cache.enable', 'true', 1, -1, -1, '获取逻辑集群列表是否开启全局缓存', '2021-09-01 20:43:08', '2021-11-29 14:57:39', '2021-09-01 20:43:08');\nINSERT INTO `arius_config_info` VALUES (1217, 'arius.meta.monitor', 'nodestat.collect.concurrent', 'true', 1, -1, -1, '', '2021-11-18 20:24:54', '2021-11-19 16:05:39', '2021-11-18 20:24:54');\nINSERT INTO `arius_config_info` VALUES (1223, 'arius.common.group', 'app.default.read.auth.indices', '\\\"\\\"', 1, -1, 2, 'app可读写的权限', '2021-12-15 20:17:06', '2021-12-16 11:17:26', '2021-12-15 20:17:06');\nINSERT INTO `arius_config_info` VALUES (1225, 'arius.common.group', 'delete.expire.index.ahead.clusters', '\\\"\\\"', 1, -1, 2, '删除过期权限', '2021-12-15 20:17:48', '2021-12-16 11:17:24', '2021-12-15 20:17:48');\nINSERT INTO `arius_config_info` VALUES (1227, 'arius.common.group', 'operate.index.ahead.seconds', '2 * 60 * 60', 1, -1, 2, '索引操作提前时间', '2021-12-15 20:18:37', '2021-12-16 11:17:22', '2021-12-15 20:18:37');\nINSERT INTO `arius_config_info` VALUES (1229, 'arius.common.group', 'platform.govern.admin.hot.days', '-1', 1, -1, 2, '平台治理导入热存的天数', '2021-12-15 20:19:13', '2021-12-16 11:17:19', '2021-12-15 20:19:13');\nINSERT INTO `arius_config_info` VALUES (1231, 'arius.common.group', 'quota.dynamic.limit.black.appIds', 'none', 1, -1, 2, 'appid黑名单控制', '2021-12-15 20:20:11', '2021-12-16 11:17:17', '2021-12-15 20:20:11');\nINSERT INTO `arius_config_info` VALUES (1233, 'arius.common.group', 'quota.dynamic.limit.black.cluster', '\\\"\\\"', 1, -1, 2, 'cluster黑名单控制', '2021-12-15 20:20:39', '2021-12-16 11:17:15', '2021-12-15 20:20:39');\nINSERT INTO `arius_config_info` VALUES (1235, 'arius.common.group', 'quota.dynamic.limit.black.logicId', 'none', 1, -1, 2, '模板黑名单控制', '2021-12-15 20:21:21', '2021-12-16 11:17:12', '2021-12-15 20:21:21');\nINSERT INTO `arius_config_info` VALUES (1237, 'arius.common.group', 'arius.wo.auto.process.create.template.disk.maxG', '10.0', 1, -1, 2, '模板创建时设置的磁盘空间最大值', '2021-12-15 20:21:49', '2021-12-16 11:15:12', '2021-12-15 20:21:49');\nINSERT INTO `arius_config_info` VALUES (1239, 'arius.common.group', 'request.interceptor.switch.open', 'true', 1, -1, 2, '请求拦截开关', '2021-12-15 20:22:14', '2021-12-16 11:15:10', '2021-12-15 20:22:14');\nINSERT INTO `arius_config_info` VALUES (1241, 'arius.common.group', 'arius.didi.t2.leader.mail', '\\\"\\\"', 1, -1, 2, 'didi领导者邮箱', '2021-12-15 20:22:40', '2021-12-16 11:15:07', '2021-12-15 20:22:40');\nINSERT INTO `arius_config_info` VALUES (1243, 'arius.common.group', 'defaultDay', '\\\"\\\"', 1, -1, 2, '默认hotDay值', '2021-12-15 20:23:17', '2021-12-16 11:15:04', '2021-12-15 20:23:17');\nINSERT INTO `arius_config_info` VALUES (1245, 'arius.quota.config.group', 'arius.quota.config.tps.per.cpu.with.replica', '1000.0', 1, -1, 2, '资源管控cpu项', '2021-12-15 20:23:56', '2021-12-16 11:15:01', '2021-12-15 20:23:56');\nINSERT INTO `arius_config_info` VALUES (1247, 'arius.quota.config.group', 'arius.quota.config.tps.per.cpu.NO.replica', '2300.0', 1, -1, 2, '资源管控cpu项', '2021-12-15 20:24:27', '2021-12-16 11:14:58', '2021-12-15 20:24:27');\nINSERT INTO `arius_config_info` VALUES (1249, 'arius.quota.config.group', 'arius.quota.config.cost.per.g.per.month', '1.06', 1, -1, 2, '资源配置模板费用', '2021-12-15 20:24:59', '2021-12-16 11:14:56', '2021-12-15 20:24:59');\nINSERT INTO `arius_config_info` VALUES (1251, 'arius.meta.monitor.group', 'nodestat.collect.concurrent', 'fasle', 1, -1, 2, '节点状态信息是否并行采集', '2021-12-15 20:25:35', '2022-08-26 18:10:50', '2021-12-15 20:25:35');\nINSERT INTO `arius_config_info` VALUES (1253, 'arius.meta.monitor.group', 'indexstat.collect.concurrent', 'fasle', 1, -1, 2, '索引状态信息是否并行采集', '2021-12-15 20:26:00', '2022-08-26 18:10:45', '2021-12-15 20:26:00');\nINSERT INTO `arius_config_info` VALUES (1255, 'arius.common.group', 'indices.recovery.ceph_max_bytes_per_sec', '10MB', 1, -1, 2, '单节点分片恢复的速率', '2021-12-15 21:33:29', '2022-04-08 17:43:14', '2021-12-15 21:33:29');\nINSERT INTO `arius_config_info` VALUES (1257, 'arius.common.group', 'cluster.routing.allocation.node_concurrent_incoming_recoveries', '2', 1, -1, 2, '一个节点上允许多少并发的传入分片还原,表示为传入还原', '2021-12-16 14:41:51', '2021-12-16 14:42:24', '2021-12-16 14:41:51');\nINSERT INTO `arius_config_info` VALUES (1259, 'arius.common', 'cluster.routing.allocation.node_concurrent_outgoing_recoveries', '2', 1, -1, 2, '一个节点上允许多少并发的传入分片还原,传出还原', '2021-12-16 14:42:15', '2022-02-22 11:11:48', '2021-12-16 14:42:15');\nINSERT INTO `arius_config_info` VALUES (1585, 'test.test', 'testt', '21', 1, -1, -1, '请忽略2221', '2022-01-13 14:25:40', '2022-01-15 16:27:05', '2022-01-13 14:25:40');\nINSERT INTO `arius_config_info` VALUES (1587, 'zptest', 'test', '<script>alert(1)</script>', 1, -1, -1, 'alert(1)', '2022-01-18 16:14:12', '2022-01-18 16:15:49', '2022-01-18 16:14:12');\nINSERT INTO `arius_config_info` VALUES (1589, 'test1ddd', 'dd ddd', 'dssdddd', 1, -1, -1, 'sddsdssd', '2022-01-26 11:39:23', '2022-01-26 11:39:42', '2022-01-26 11:39:23');\nINSERT INTO `arius_config_info` VALUES (1591, 'yyftemptest-01s', 'yyftemptest-01d', '', 1, -1, -1, '', '2022-03-01 16:44:12', '2022-03-01 16:44:39', '2022-03-01 16:44:12');\nINSERT INTO `arius_config_info` VALUES (1593, 'test1', 's', '', 1, -1, -1, '', '2022-03-07 11:37:39', '2022-03-07 11:37:43', '2022-03-07 11:37:39');\nINSERT INTO `arius_config_info` VALUES (1595, 'test1', '22', 'm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2', 1, -1, -1, '', '2022-03-15 11:19:49', '2022-03-15 11:20:08', '2022-03-15 11:19:49');\nINSERT INTO `arius_config_info` VALUES (1601, 'yyyYF223', 'WEFWfwef', '', 1, -1, -1, '', '2022-03-31 19:31:01', '2022-08-01 08:52:47', '2022-03-31 19:31:01');\nINSERT INTO `arius_config_info` VALUES (1603, 'yyftestYY0411-01', 'yyftestYY0411-01', 'sdsd', 1, -1, -1, 'sdsdcsg参赛暗杀诉法设计风格！@', '2022-04-11 15:22:22', '2022-04-11 15:26:29', '2022-04-11 15:22:22');\nINSERT INTO `arius_config_info` VALUES (1623, 'settingGroup', 'name', 'value', 1, -1, -1, 'test', '2022-06-23 14:17:56', '2022-06-23 15:47:26', '2022-06-23 14:17:56');\nINSERT INTO `arius_config_info` VALUES (1625, 'group11', 'name1', 'value1', 1, -1, -1, 'des-edit', '2022-06-23 15:22:51', '2022-06-24 09:40:51', '2022-06-23 15:22:51');\nINSERT INTO `arius_config_info` VALUES (1627, 'arius.common.group', 'cluster.node.specification_list', '16c-64g-3072g,16c-48g-3071g,1c-48g-3071g,', 1, -1, 1, '节点规格列表，机型列表', '2022-07-05 14:10:27', '2022-07-18 15:01:29', '2022-07-05 14:10:27');\nINSERT INTO `arius_config_info` VALUES (1629, 'ccccccccccccccdcdccccccccccccccdcdccccccccccccccdb', 'dccccccccccccccdcdcccccccc', 'vjh', 1, -1, -1, 'cdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccc', '2022-07-05 15:27:38', '2022-07-05 15:28:09', '2022-07-05 15:27:38');\nINSERT INTO `arius_config_info` VALUES (1631, '2', '3', '', 1, -1, -1, '', '2022-07-06 15:26:45', '2022-07-06 15:26:58', '2022-07-06 15:26:45');\nINSERT INTO `arius_config_info` VALUES (1633, 'arius.common.group', 'cluster.data.center_list', 'cn,en', 1, -1, 1, '数据中心列表', '2022-07-06 16:14:03', '2022-08-27 19:11:25', '2022-07-06 16:14:03');\nINSERT INTO `arius_config_info` VALUES (1635, 'arius.common.group', 'cluster.package.version_list', '7.6.1.1,6.6.6.6,7.6.1.2', 1, -1, 1, '系统预制支持的版本', '2022-07-06 16:17:25', '2022-07-06 16:17:25', '2022-07-06 16:17:25');\nINSERT INTO `arius_config_info` VALUES (1637, 'template.time.type', 'format', '[\\n  \\\"yyyy-MM-dd HH:mm:ss\\\",\\n  \\\"yyyy-MM-dd HH:mm:ss.SSS\\\",\\n  \\\"yyyy-MM-dd\\'T\\'HH:mm:ss\\\",\\n  \\\"yyyy-MM-dd\\'T\\'HH:mm:ss.SSS\\\",\\n  \\\"yyyy-MM-dd HH:mm:ss.SSS Z\\\",\\n  \\\"yyyy/MM/dd HH:mm:ss\\\",\\n  \\\"epoch_seconds\\\",\\n  \\\"epoch_millis\\\"\\n]', 1, -1, 1, '新建模版的时间格式', '2022-07-07 16:15:37', '2022-07-07 16:15:37', '2022-07-07 16:15:37');\nINSERT INTO `arius_config_info` VALUES (1639, 'arius.cluster.blacklist', 'cluster.phy.name', 'didi-cluster-test', 1, -1, 1, '滴滴内部测试环境集群, 禁止任何编辑删除新增操作', '2022-07-07 17:58:02', '2022-07-07 18:44:42', '2022-07-07 17:58:02');\nINSERT INTO `arius_config_info` VALUES (1641, 'arius.common.group', 'cluster.resource.type_list', '信创,acs,vmware', 1, -1, 1, '所属资源类型列表,IaaS平台类型列表', '2022-07-07 19:13:13', '2022-08-31 16:38:37', '2022-07-07 19:13:13');\nINSERT INTO `arius_config_info` VALUES (1643, '55', '666', '1', 1, -1, -1, '143', '2022-07-13 16:59:41', '2022-07-13 17:01:48', '2022-07-13 16:59:41');\nINSERT INTO `arius_config_info` VALUES (1645, 'arius.common.group', 'index.rollover.threshold', '0.00001', 1, -1, 1, '主分片大小达到1G后升版本', '2022-07-15 21:03:12', '2022-09-22 15:28:54', '2022-07-15 21:03:12');\nINSERT INTO `arius_config_info` VALUES (1647, 'yyftemptest-01', 'yyf', 'sdv', 1, -1, -1, 'sdv', '2022-07-18 15:02:08', '2022-07-18 15:02:24', '2022-07-18 15:02:08');\nINSERT INTO `arius_config_info` VALUES (1649, 'arius.common.group', 'cluster.node.count_list', '2,4,6,10', 1, -1, 1, '集群节点个数列表', '2022-07-18 15:22:33', '2022-08-27 19:13:09', '2022-07-18 15:22:33');\nINSERT INTO `arius_config_info` VALUES (1653, 'arius.common.group', 'arius.system.template', '[\\n    \\\"arius.dsl.analyze.result\\\",\\n    \\\"arius.dsl.metrics\\\",\\n    \\\"arius.dsl.template\\\",\\n    \\\"arius.gateway.join\\\",\\n    \\\"arius_stats_index_info\\\",\\n    \\\"arius_stats_node_info\\\",\\n    \\\"arius.template.access\\\",\\n    \\\"arius_cat_index_info\\\",\\n    \\\"arius_gateway_metrics\\\",\\n    \\\"arius_stats_cluster_info\\\",\\n    \\\"arius_stats_cluster_task_info\\\",\\n    \\\"arius_stats_dashboard_info\\\",\\n    \\\"arius.appid.template.access\\\"\\n]', 1, -1, 1, '系统核心模版集合', '2022-07-21 12:25:48', '2022-07-21 12:30:06', '2022-07-21 12:25:48');\nINSERT INTO `arius_config_info` VALUES (1655, 'ds12', 'sd34', 'sdsddsd', 1, -1, -1, 'ds78', '2022-07-21 17:00:44', '2022-08-01 08:52:35', '2022-07-21 17:00:44');\nINSERT INTO `arius_config_info` VALUES (1657, 'arius.common.group', 'cluster.shard.big_threshold', '10', 1, -1, 1, '用于设置集群看板中的大Shard阈值，单位为gb，大于这个值就认为是大shard', '2022-07-28 17:49:59', '2022-08-26 18:08:56', '2022-07-28 17:49:59');\nINSERT INTO `arius_config_info` VALUES (1671, 'arius.template.group', 'logic.template.business_type', '系统数据,日志数据,业务上报数据,test_businesss_type1,RDS数据,离线导入数据,testset,123,test_businesss_type1', 1, -1, 1, '模板业务类型', '2022-08-26 18:02:47', '2022-09-01 15:16:11', '2022-08-26 18:02:47');\nINSERT INTO `arius_config_info` VALUES (1673, 'arius.template.group', 'logic.template.time_format_list', 'yyyy-MM-dd HH:mm:ss,yyyy-MM-dd HH:mm:ss.SSS,yyyy-MM-dd HH:mm:ss.SSS Z,yyyy-MM-dd\\'T\\'HH:mm:ss,yyyy-MM-dd\\'T\\'HH:mm:ss.SSS,yyyy-MM-dd\\'T\\'HH:mm:ssZ,yyyy-MM-dd\\'T\\'HH:mm:ss.SSSZ,yyyy/MM/dd HH:mm:ss,epoch_second,epoch_millis,yyyy-MM-dd', 1, -1, 1, '模板时间格式列表', '2022-08-26 18:06:07', '2022-08-31 17:16:03', '2022-08-26 18:06:07');\nINSERT INTO `arius_config_info` VALUES (1675, 'arius.template.group', 'history.template.physic.indices.allocation.is_effective', 'ture', 1, -1, 1, '历史索引模板shard分配是否自动调整', '2022-08-26 18:07:53', '2022-08-31 17:07:02', '2022-08-26 18:07:53');\nINSERT INTO `arius_config_info` VALUES (1677, 'arius.common.group', 'operate.record.save.time', '29', 1, -1, -1, '操作记录的保存时间', '2022-09-01 16:44:03', '2022-09-01 17:23:48', '2022-09-01 16:44:03');\nINSERT INTO `arius_config_info` VALUES (1679, 'arius.common.group', 'operate.record.save_time', '25', 1, -1, 1, '操作记录的保存时间(天)', '2022-09-01 19:34:33', '2022-09-19 15:14:59', '2022-09-01 19:34:33');\nINSERT INTO `arius_config_info` VALUES (1681, 'arius.common.group', 'super_app.default.dsl.command', '#获取节点状态\\nGET _nodes/stats\\n\\n#获取集群信息\\nGET _cluster/stats\\n\\n#获取集群健康信息\\nGET _cluster/health?v\\n\\n#查看当前集群的热点线程\\nGET _nodes/hot_threads\\n\\n#查看当前集群运行中的任务信息\\nGET _tasks?actions=*&detailed\\n\\n#shard分配说明，会在分片未分配的事后去通过这个命令查看下具体原因\\nGET /_cluster/allocation/explain\\n\\n#异常shard分配重试，当集群red有shard未分配的情况下会通过这个命令来重试分配\\nPOST /_cluster/reroute?retry_failed=true\\n\\n#清除fielddata内存，当集群因为fileddata太大导致熔断或占用很多内存，可以通过此命令释放内存\\nPOST _cache/clear?fielddata=true\\n', 1, -1, 1, '超级应用默认就有的命令', '2022-09-20 10:26:08', '2022-09-26 11:34:14', '2022-09-20 10:26:08');\nINSERT INTO `arius_config_info` VALUES (1683, 'arius.common.group', 'operate.record.save.num', '30', 1, -1, -1, 'DSL和kibana操作记录保存条数', '2022-09-20 10:45:31', '2022-09-22 16:49:16', '2022-09-20 10:45:31');\nINSERT INTO `arius_config_info` VALUES (1685, 'ddd', 'sdd', 'sd', 1, -1, -1, 'ds', '2022-09-21 15:22:31', '2022-09-21 15:23:00', '2022-09-21 15:22:31');\nINSERT INTO `arius_config_info` VALUES (1659, 'arius.dashboard.threshold.group', 'cluster.shard.num_threshold', '{\\\"name\\\":\\\" 集群 shard 个数 \\\",\\\"metrics\\\":\\\"shardNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":2000}', 1, -1, 1, '集群 [Shard 个数阈值] 定义', '2022-08-05 15:58:22', '2022-10-21 11:56:23', '2022-08-05 15:58:22');\nINSERT INTO `arius_config_info` VALUES (1661, 'arius.dashboard.threshold.group', 'cluster.metric.collector.delayed_threshold', '{\\\"name\\\":\\\"node_status 指标采集延时 \\\",\\\"metrics\\\":\\\"clusterElapsedTimeGte5Min\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":5}', 1, -1, 1, '集群 [指标采集延时阈值] 定义', '2022-08-10 14:10:47', '2022-10-26 16:20:17', '2022-08-10 14:10:47');\nINSERT INTO `arius_config_info` VALUES (1663, 'arius.dashboard.threshold.group', 'node.disk.used_percent_threshold', '{\\\"name\\\":\\\" 磁盘利用率 \\\",\\\"metrics\\\":\\\"largeDiskUsage\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":80}', 1, -1, 1, '节点 [磁盘利用率阈值] 定义', '2022-08-25 14:50:41', '2022-10-26 18:48:54', '2022-08-25 14:50:41');\nINSERT INTO `arius_config_info` VALUES (1665, 'arius.dashboard.threshold.group', 'node.jvm.heap.used_percent_threshold', '{\\\"name\\\":\\\" 堆内存利用率 \\\",\\\"metrics\\\":\\\"largeHead\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":75}', 1, -1, 1, '节点 [堆内存利用率阈值] 定义', '2022-08-25 16:45:33', '2022-10-26 18:48:40', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info` VALUES (1666, 'arius.dashboard.threshold.group', 'node.cpu.used_percent_threshold', '{\\\"name\\\":\\\"CPU 利用率红线 \\\",\\\"metrics\\\":\\\"largeCpuUsage\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":60}', 1, -1, 1, '节点 [CPU 利用率阈值] 定义', '2022-08-25 16:45:33', '2022-10-26 18:48:18', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info` VALUES (1667, 'arius.dashboard.threshold.group', 'node.jvm.heap.used_percent_time_duration_threshold', '{\\\"name\\\":\\\"node.jvm.heap.used_percent_threshold_time_duration\\\",\\\"metrics\\\":\\\"jvmHeapUsedPercentThresholdTimeDuration\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":10}', 1, -1, 1, '节点堆内存利用率阈值的 [持续时间]', '2022-08-25 16:45:33', '2022-10-26 18:47:52', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info` VALUES (1668, 'arius.dashboard.threshold.group', 'node.cpu.used_percent_threshold_time_duration_threshold', '{\\\"name\\\":\\\"node.large.cpu.used.percent.time.threshold\\\",\\\"metrics\\\":\\\"largeCpuUsage\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":5}', 1, -1, 1, '节点 CPU 利用率超阈值的 [持续时间]', '2022-08-25 16:45:33', '2022-10-26 18:47:21', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info` VALUES (1669, 'arius.dashboard.threshold.group', 'index.shard.big_threshold', '{\\\"name\\\":\\\"index.shard.big_threshold\\\",\\\"metrics\\\":\\\"shardSize\\\",\\\"unit\\\":\\\"G\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":20}', 1, -1, 1, '索引 [大 shard 阈值] 定义', '2022-08-26 15:25:07', '2022-08-29 10:28:24', '2022-08-26 15:25:07');\nINSERT INTO `arius_config_info` VALUES (1607, 'arius.dashboard.threshold.group', 'index.segment.num_threshold', '{\\\"name\\\":\\\" 索引 Segments 个数 \\\",\\\"metrics\\\":\\\"segmentNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":100}', 1, -1, 1, '索引 Segment 个数阈值定义', '2022-06-17 09:52:11', '2022-08-27 16:05:06', '2022-06-17 09:52:11');\nINSERT INTO `arius_config_info` VALUES (1609, 'arius.dashboard.threshold.group', 'index.template.segment_num_threshold', '{\\\"name\\\":\\\" 模板 Segments 个数 \\\",\\\"metrics\\\":\\\"segmentNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":700}', 1, -1, 1, '索引模板 [Segment 个数阈值] 定义', '2022-06-17 09:53:34', '2022-08-27 19:01:57', '2022-06-17 09:53:34');\nINSERT INTO `arius_config_info` VALUES (1611, 'arius.dashboard.threshold.group', 'index.segment.memory_size_threshold', '{\\\"name\\\":\\\" 索引 Segments 内存大小 \\\",\\\"metrics\\\":\\\"segmentMemSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":500}', 1, -1, 1, '索引 [Segment 内存大小阈值] 定义', '2022-06-17 09:54:20', '2022-10-26 18:50:50', '2022-06-17 09:54:20');\nINSERT INTO `arius_config_info` VALUES (1613, 'arius.dashboard.threshold.group', 'index.template.segment_memory_size_threshold', '{\\\"name\\\":\\\" 模板 Segments 内存大小 \\\",\\\"metrics\\\":\\\"segmentMemSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":3000}', 1, -1, 1, '索引模板 [Segment 内存大小阈值] 定义', '2022-06-17 09:54:50', '2022-10-26 18:50:27', '2022-06-17 09:54:50');\nINSERT INTO `arius_config_info` VALUES (1617, 'arius.dashboard.threshold.group', 'node.shard.num_threshold', '{\\\"name\\\":\\\" 节点分片个数 \\\",\\\"metrics\\\":\\\"shardNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":1000}', 1, -1, 1, '节点 [分片个数阈值] 定义', '2022-06-17 10:01:40', '2022-08-27 19:09:44', '2022-06-17 10:01:40');\nINSERT INTO `arius_config_info` VALUES (1619, 'arius.dashboard.threshold.group', 'index.shard.small_threshold', '{\\\"name\\\":\\\" 小 shard 索引列表 \\\",\\\"metrics\\\":\\\"shardSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\"<\\\",\\\"value\\\":1000}', 1, -1, 1, '索引 [小 Shard 阈值] 定义', '2022-06-17 16:11:53', '2022-08-27 19:04:19', '2022-06-17 16:11:53');\nINSERT INTO `arius_config_info` VALUES (1656, 'arius.dashboard.threshold.group', 'index.mapping.num_threshold', '{\\\"name\\\":\\\" 索引 Mapping 个数 \\\",\\\"metrics\\\":\\\"mappingNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":100}', 1, -1, 1, '索引 [Mapping 个数阈值] 定义', '2022-07-28 15:50:59', '2022-08-27 18:36:48', '2022-07-28 15:50:59');\n\n\n\n\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/cluster-phy-join",
    "content": "{\n  \"type\": 4,\n  \"resourceType\": 2,\n  \"dataCenter\": \"\",\n  \"platformType\": \"\",\n  \"tags\": \"{\\\"createSource\\\":0}\",\n  \"importRule\": \"0\",\n  \"projectId\": 1,\n  \"cluster\": \"logi-elasticsearch-meta\",\n  \"divide\": true,\n  \"phyClusterDesc\": \"\",\n  \"roleClusterHosts\": [\n    {\n      \"cluster\": \"logi-elasticsearch-meta\",\n      \"id\": 0,\n      \"ip\": \"这里填ip\",\n      \"nodeSet\": \"\",\n      \"port\": \"这里填端口号\",\n      \"role\": 3,\n      \"roleClusterId\": 0,\n      \"status\": 0\n    }\n  ],\n  \"password\": \"elastic:123456\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/init.sql",
    "content": "#项目、用户、权限点\n-- auto-generated definition\ncreate table logi_security_config\n(\n    id          bigint unsigned auto_increment comment '主键自增'\n        primary key,\n    value_group varchar(100)  default ''                not null comment ' 配置项组 ',\n    value_name  varchar(100)  default ''                not null comment ' 配置项名字 ',\n    value       text                                    null comment '配置项的值',\n    edit        int(4)        default 1                 not null comment '是否可以编辑 1 不可编辑（程序获取） 2 可编辑',\n    status      int(4)        default 1                 not null comment '1 正常 2 禁用',\n    memo        varchar(1000) default ''                not null comment ' 备注 ',\n    create_time timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间',\n    is_delete   tinyint(1)    default 0                 not null comment '逻辑删除',\n    app_name    varchar(16) collate utf8_bin            null comment '应用名称',\n    operator    varchar(16) collate utf8_bin            null comment '操作者'\n)\n    comment 'logi 配置项' charset = utf8;\n\ncreate index idx_group_name\n    on logi_security_config (value_group, value_name);\n\n-- auto-generated definition\ncreate table logi_security_dept\n(\n    id          int auto_increment\n        primary key,\n    dept_name   varchar(10)                          not null comment '部门名',\n    parent_id   int                                  not null comment '父部门 id',\n    leaf        tinyint(1)                           not null comment '是否叶子部门',\n    level       tinyint                              not null comment 'parentId 为 0 的层级为 1',\n    description varchar(20)                          null comment '描述',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '部门信息表' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_message\n(\n    id          int auto_increment\n        primary key,\n    title       varchar(60)                          not null comment '标题',\n    content     varchar(256)                         null comment '内容',\n    read_tag    tinyint(1) default 0                 null comment '是否已读',\n    oplog_id    int                                  null comment '操作日志 id',\n    user_id     int                                  null comment '这条消息属于哪个用户的，用户 id',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '消息中心' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_oplog\n(\n    id                int auto_increment\n        primary key,\n    operator_ip       varchar(20)                            not null comment '操作者 ip',\n    operator          varchar(20)                            null comment '操作者账号',\n    operate_page      varchar(16)                            null comment '操作页面',\n    operate_type      varchar(16)                            not null comment '操作类型',\n    target_type       varchar(16)                            not null comment '对象分类',\n    target            varchar(255)                            not null comment '操作对象',\n    detail            text                                   null comment '日志详情',\n    create_time       timestamp    default CURRENT_TIMESTAMP null,\n    update_time       timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete         tinyint(1)   default 0                 not null comment '逻辑删除',\n    app_name          varchar(16)                            null comment '应用名称',\n    operation_methods varchar(255) default ''                null\n)\n    comment '操作日志' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_oplog_extra\n(\n    id          int auto_increment\n        primary key,\n    info        varchar(16)                          null comment '信息',\n    type        tinyint                              not null comment '哪种信息：1：操作页面;2：操作类型;3：对象分类',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '操作日志信息（操作页面、操作类型、对象分类）' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_permission\n(\n    id              int auto_increment\n        primary key,\n    permission_name varchar(40)                          not null comment '权限名字',\n    parent_id       int                                  not null comment '父权限 id',\n    leaf            tinyint(1)                           not null comment '是否叶子权限点（具体的操作）',\n    level           tinyint                              not null comment '权限点的层级（parentId 为 0 的层级为 1）',\n    description     varchar(64)                          null comment '权限点描述',\n    create_time     timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time     timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete       tinyint(1) default 0                 null comment '逻辑删除',\n    app_name        varchar(16)                          null comment '应用名称'\n)\n    comment '权限表' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_project\n(\n    id           int auto_increment comment '项目 id'\n        primary key,\n    project_code varchar(128)                           not null comment '项目编号',\n    project_name varchar(128)                           not null comment '项目名',\n    description  varchar(512) default ''                not null comment ' 项目描述 ',\n    dept_id      int                                    not null comment '部门 id',\n    running      tinyint(1)   default 1                 not null comment '启用 or 停用',\n    create_time  timestamp    default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time  timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete    tinyint(1)   default 0                 not null comment '逻辑删除',\n    app_name     varchar(16)                            null comment '应用名称'\n)\n    comment '项目表' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_resource_type\n(\n    id          int auto_increment\n        primary key,\n    type_name   varchar(16)                          null comment '资源类型名',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '资源类型表' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_role\n(\n    id           int auto_increment\n        primary key,\n    role_code    varchar(128)                         not null comment '角色编号',\n    role_name    varchar(128)                         not null comment '名称',\n    description  varchar(128)                         null comment '角色描述',\n    last_reviser varchar(30)                          null comment '最后修改人',\n    create_time  timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time  timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete    tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name     varchar(16)                          null comment '应用名称'\n)\n    comment '角色信息' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_role_permission\n(\n    id            int auto_increment\n        primary key,\n    role_id       int                                  not null comment '角色 id',\n    permission_id int                                  not null comment '权限 id',\n    create_time   timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time   timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete     tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name      varchar(16)                          null comment '应用名称'\n)\n    comment '角色权限表（只保留叶子权限与角色关系）' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_user\n(\n    id          int auto_increment\n        primary key,\n    user_name   varchar(64)                            not null comment '用户账号',\n    pw          varchar(2048)                          not null comment '用户密码',\n    salt        char(5)      default ''                not null comment ' 密码盐 ',\n    real_name   varchar(128) default ''                not null comment ' 真实姓名 ',\n    phone       char(11)     default ''                not null comment 'mobile',\n    email       varchar(30)  default ''                not null comment 'email',\n    dept_id     int                                    null comment '所属部门 id',\n    is_delete   tinyint(1)   default 0                 not null comment '逻辑删除',\n    create_time timestamp    default CURRENT_TIMESTAMP null comment '注册时间',\n    update_time timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    app_name    varchar(16)                            null comment '应用名称'\n)\n    comment '用户信息' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_user_project\n(\n    id          int auto_increment\n        primary key,\n    user_id     int                                   not null comment '用户 id',\n    project_id  int                                   not null comment '项目 id',\n    create_time timestamp   default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp   default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1)  default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                           null comment '应用名称',\n    user_type   tinyint(10) default 0                 not null comment '用户类型：0：普通项目用户；1：项目 owner'\n)\n    comment '用户项目关系表（项目负责人）' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_user_resource\n(\n    id               int auto_increment\n        primary key,\n    user_id          int                                  not null comment '用户 id',\n    project_id       int                                  not null comment '资源所属项目 id',\n    resource_type_id int                                  not null comment '资源类别 id',\n    resource_id      int                                  not null comment '资源 id',\n    control_level    tinyint                              not null comment '管理级别：1（查看权限）2（管理权限）',\n    create_time      timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time      timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete        tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name         varchar(16)                          null comment '应用名称'\n)\n    comment '用户和资源关系表' charset = utf8;\n\n-- auto-generated definition\ncreate table logi_security_user_role\n(\n    id          int auto_increment\n        primary key,\n    user_id     int                                  not null comment '用户 id',\n    role_id     int                                  not null comment '角色 id',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '用户角色表' charset = utf8;\n\n-- auto-generated definition\ncreate table arius_es_user\n(\n    id                 bigint(10) unsigned auto_increment comment '主键 自增'\n        primary key,\n    index_exp          text                                    null comment '索引表达式',\n    data_center        varchar(20)   default ''                not null comment ' 数据中心 ',\n    is_root            tinyint       default 0                 not null comment '是都是超级用户 超级用户具有所有索引的访问权限 0 不是 1 是',\n    memo               varchar(1000) default ''                not null comment ' 备注 ',\n    ip                 varchar(500)  default ''                not null comment ' 白名单 ip 地址 ',\n    verify_code        varchar(50)   default ''                not null comment 'app 验证码 ',\n    is_active          tinyint(2)    default 1                 not null comment '1 为可用，0 不可用',\n    query_threshold    int(10)       default 100               not null comment '限流值',\n    cluster            varchar(100)  default ''                not null comment ' 查询集群 ',\n    responsible        varchar(500)  default ''                null comment ' 责任人 ',\n    search_type        tinyint       default 0                 not null comment '0 表示 app 的查询请求需要 app 里配置的集群 (一般配置的都是 trib 集群) 1 表示 app 的查询请求必须只能访问一个模板 2 表示集群模式（可支持多模板查询）',\n    create_time        timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time        timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间',\n    project_id         bigint(10)                              not null comment '项目 id',\n    is_default_display tinyint(2)    default 0                 not null comment '1：项目默认的 es user；0: 项目新增的 es user'\n)\n    comment 'es 操作用户表' charset = utf8;\ncreate table project_arius_config\n(\n    project_id              bigint(10) unsigned auto_increment comment 'project id'\n        primary key,\n    analyze_response_enable tinyint       default 1                 not null comment '响应结果解析开关 默认是 0：关闭，1：开启',\n    is_source_separated     tinyint       default 0                 not null comment '是否是索引存储分离的 0 不是 1 是',\n    aggr_analyze_enable     tinyint       default 1                 not null comment '1 生效 0 不生效',\n    dsl_analyze_enable      tinyint(2)    default 1                 not null comment '1 为生效 dsl 分析查询限流值，0 不生效 dsl 分析查询限流值',\n    slow_query_times        int(10)       default 100               not null comment '慢查询耗时',\n    is_active               tinyint(2)    default 1                 not null comment '1 为可用，0 不可用',\n    memo                    varchar(1000) default ''                not null comment ' 备注 ',\n    create_time             timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time             timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间'\n)\n    comment '项目配置' charset = utf8;\n\n-- auto-generated definition\n\n\n#### 核心表结构\nCREATE TABLE `arius_config_info`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `value_group` varchar(100)        NOT NULL DEFAULT '' COMMENT ' 配置项组 ',\n    `value_name`  varchar(100)        NOT NULL DEFAULT '' COMMENT ' 配置项名字 ',\n    `value`       text COMMENT '配置项的值',\n    `edit`        int(4)              NOT NULL DEFAULT '1' COMMENT '是否可以编辑 1 不可编辑（程序获取） 2 可编辑',\n    `dimension`   int(4)              NOT NULL DEFAULT '-1' COMMENT '配置项维度 1 集群 2 模板',\n    `status`      int(4)              NOT NULL DEFAULT '1' COMMENT '1 正常 2 禁用 -1 删除',\n    `memo`        varchar(1000)       NOT NULL DEFAULT '' COMMENT ' 备注 ',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `search_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '配置查询时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_group_name` (`value_group`, `value_name`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1662\n  DEFAULT CHARSET = utf8 COMMENT ='arius 配置项';\n\n\n\n-- ----------------------------\n-- Table structure for arius_meta_job_cluster_distribute\n-- ----------------------------\nCREATE TABLE `arius_meta_job_cluster_distribute`\n(\n    `id`           bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 id',\n    `cluster_id`   int(11)             NOT NULL DEFAULT '-1' COMMENT '集群 id',\n    `monitor_host` varchar(128)        NOT NULL DEFAULT '' COMMENT ' 当前执行主机名 ',\n    `monitor_time` timestamp           NOT NULL DEFAULT '2000-01-02 00:00:00' COMMENT '上一次监控时间',\n    `gmt_create`   timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `gmt_modify`   timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `cluster`      varchar(128)        NOT NULL DEFAULT '' COMMENT ' 集群名称 ',\n    `dataCentre`   varchar(16)         NOT NULL DEFAULT 'cn' COMMENT '集群数据中心',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_cluster_id` (`cluster_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 435089\n  DEFAULT CHARSET = utf8 COMMENT ='monitor 任务分配';\n\n-- ----------------------------\n-- Table structure for arius_op_task\n-- ----------------------------\nCREATE TABLE `arius_op_task`\n(\n    `id`           bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `title`        varchar(100)        NOT NULL DEFAULT '' COMMENT ' 标题 ',\n    `business_key` varchar(1000)       NOT NULL DEFAULT '0' COMMENT '业务数据主键',\n    `status`       varchar(20)         NOT NULL DEFAULT 'waiting' COMMENT '任务状态：success: 成功 failed: 失败 running: 执行中 waiting: 等待 cancel: 取消 pause: 暂停',\n    `creator`      varchar(100)        NOT NULL DEFAULT '' COMMENT ' 创建人 ',\n    `create_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`  tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    `expand_data`  longtext COMMENT '扩展数据',\n    `task_type`    int(11)             NOT NULL DEFAULT '0' COMMENT '任务类型 1：集群新增，2：集群扩容，3：集群缩容，4：集群重，5：集群升级，6：集群插件操作，10：模版 dcdr 任务',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2302\n  DEFAULT CHARSET = utf8 COMMENT ='arius 任务表';\n\n-- ----------------------------\n-- Table structure for arius_work_order_info\n-- ----------------------------\nCREATE TABLE `arius_work_order_info`\n(\n    `id`                   bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',\n    `type`                 varchar(25)         NOT NULL DEFAULT 'unknown' COMMENT 'appcreate 创建 app,clustercreate 创建集群,clusterindecrease 集群扩缩溶,clusteroffline 集群下线,clusterupdate 集群修改,templateauth 索引申请,templatecreate 索引创建,templateindecrease 索引扩容,templatequerydsl 查询语句创建,templatetransfer 索引转让,querydsllimitedit 查询语句编辑,responsiblegovern 员工离职,unhealthytemplategovern 不健康索引处理',\n    `title`                varchar(64)         NOT NULL DEFAULT '' COMMENT ' 标题 ',\n    `approver_project_id`  int(16)             NOT NULL DEFAULT '-1' COMMENT '审批人 projectid',\n    `applicant`            varchar(64)         NOT NULL DEFAULT '' COMMENT ' 申请人 ',\n    `extensions`           text COMMENT '拓展字段',\n    `description`          text COMMENT '备注信息',\n    `approver`             varchar(64)         NOT NULL DEFAULT '' COMMENT ' 审批人 ',\n    `finish_time`          timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '结束时间',\n    `opinion`              varchar(256)        NOT NULL DEFAULT '' COMMENT ' 审批信息 ',\n    `status`               int(16)             NOT NULL DEFAULT '0' COMMENT '工单状态, 0: 待审批, 1: 通过, 2: 拒绝, 3: 取消',\n    `create_time`          timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`          timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修 \\n 改时间',\n    `applicant_project_id` int(16)             NOT NULL DEFAULT '-1' COMMENT '申请人 projectid',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2522\n  DEFAULT CHARSET = utf8 COMMENT ='工单表';\n\n-- ----------------------------\n-- Table structure for es_cluster_phy_info\n-- ----------------------------\nCREATE TABLE `es_cluster_phy_info`\n(\n    `id`                      bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `cluster`                 varchar(128)        NOT NULL DEFAULT '' COMMENT 'es 集群名 ',\n    `read_address`            varchar(1000)       NOT NULL DEFAULT '' COMMENT ' 读地址 tcp',\n    `write_address`           varchar(2000)       NOT NULL DEFAULT '' COMMENT ' 写地址 tcp',\n    `http_address`            varchar(1000)       NOT NULL DEFAULT '' COMMENT 'http 服务地址 ',\n    `http_write_address`      varchar(8000)       NOT NULL DEFAULT '' COMMENT 'http 写地址 ',\n    `desc`                    varchar(2000)       NOT NULL DEFAULT '' COMMENT ' 描述 ',\n    `type`                    tinyint(4)          NOT NULL DEFAULT '-1' COMMENT '集群类型，3-docker 集群，4-host 集群',\n    `data_center`             varchar(10)         NOT NULL DEFAULT 'cn' COMMENT '数据中心',\n    `idc`                     varchar(10)         NOT NULL DEFAULT '' COMMENT ' 机房信息 ',\n    `es_version`              varchar(100)        NOT NULL DEFAULT '' COMMENT 'es 版本 ',\n    `create_time`             timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`             timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `level`                   tinyint(4)          NOT NULL DEFAULT '1' COMMENT '服务等级',\n    `password`                varchar(255)        NOT NULL DEFAULT '' COMMENT ' 集群访问密码 ',\n    `ecm_cluster_id`          int(11)             NOT NULL DEFAULT '-1' COMMENT 'ecm 集群 id',\n    `cluster_config_template` text COMMENT '集群安装模板',\n    `image_name`              varchar(500)        NOT NULL DEFAULT '' COMMENT ' 镜像名 ',\n    `cfg_id`                  int(11)             NOT NULL DEFAULT '-1' COMMENT '配置包 id',\n    `package_id`              int(11)             NOT NULL DEFAULT '-1' COMMENT '程序包 id',\n    `plug_ids`                varchar(100)                 DEFAULT '' COMMENT ' 插件包 id 列表 ',\n    `creator`                 varchar(255)        NOT NULL DEFAULT '' COMMENT ' 集群创建人 ',\n    `ns_tree`                 varchar(100)        NOT NULL DEFAULT '' COMMENT ' 机器节点 ',\n    `template_srvs`           varchar(255)                 DEFAULT '' COMMENT ' 集群的索引模板服务 ',\n    `is_active`               tinyint(4)          NOT NULL DEFAULT '1' COMMENT '是否生效',\n    `run_mode`                tinyint(255)        NOT NULL DEFAULT '0' COMMENT 'client 运行模式，0 读写共享，1 读写分离',\n    `write_action`            varchar(1000)                DEFAULT NULL COMMENT '指定写 client 的 action',\n    `health`                  tinyint(2)          NOT NULL DEFAULT '3' COMMENT '集群状态 1 green 2 yellow 3 red',\n    `active_shard_num`        bigint(25)          NOT NULL DEFAULT '0' COMMENT '有效 shard 总数量',\n    `disk_total`              bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘总量 单位 byte',\n    `disk_usage`              bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘使用量 单位 byte',\n    `disk_usage_percent`      decimal(10, 5)      NOT NULL COMMENT '集群磁盘空闲率 单位 0 ~1',\n    `tags`                    text COMMENT '拓展字段, 这里用于存放集群展示用属性标签，如「集群所属资源类型」等等',\n    `platform_type`           varchar(100)        NOT NULL DEFAULT '' COMMENT 'IaaS 平台类型 ',\n    `resource_type`           tinyint(4)          NOT NULL DEFAULT '-1' COMMENT '集群资源类型，1- 共享资源，2- 独立资源，3- 独享资源',\n    `gateway_url`             varchar(200)        NOT NULL DEFAULT '' COMMENT ' 集群 gateway 地址 ',\n    PRIMARY KEY (`id`),\n    KEY `idx_cluster` (`cluster`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 4710\n  DEFAULT CHARSET = utf8 COMMENT ='物理集群表';\n\n-- ----------------------------\n-- Table structure for es_cluster_region\n-- ----------------------------\nCREATE TABLE `es_cluster_region`\n(\n    `id`               bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `logic_cluster_id` varchar(200)        NOT NULL DEFAULT '-1' COMMENT '逻辑集群 ID',\n    `phy_cluster_name` varchar(128)        NOT NULL DEFAULT '' COMMENT ' 物理集群名 ',\n    `racks`            varchar(2048)                DEFAULT '' COMMENT 'region 的 rack，逗号分隔 ',\n    `create_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`      tinyint(1)          NOT NULL DEFAULT '0' COMMENT '删除标记，1- 已删除，0- 未删除',\n    `name`             varchar(100)        NOT NULL DEFAULT '' COMMENT 'region 名称 ',\n    `config`           varchar(1024)                DEFAULT '' COMMENT 'region 配置项 ',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 4008\n  DEFAULT CHARSET = utf8 COMMENT ='es 集群 region 表';\n\n-- ----------------------------\n-- Table structure for es_cluster_role_host_info\n-- ----------------------------\nCREATE TABLE `es_cluster_role_host_info`\n(\n    `id`              bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `role_cluster_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '关联集群角色表外键',\n    `hostname`        varchar(100)        NOT NULL DEFAULT '' COMMENT ' 节点名称 ',\n    `ip`              varchar(50)         NOT NULL DEFAULT '' COMMENT ' 主机 ip',\n    `cluster`         varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群 ',\n    `port`            varchar(20)         NOT NULL DEFAULT '' COMMENT ' 端口，如果是节点上启动了多个进程，可以是多个，用逗号隔开 ',\n    `role`            tinyint(4)          NOT NULL DEFAULT '-1' COMMENT '角色信息， 1data 2client 3master 4tribe',\n    `status`          tinyint(4)          NOT NULL DEFAULT '1' COMMENT '节点状态，1 在线 2 离线',\n    `rack`            varchar(30)                  DEFAULT '' COMMENT ' 节点 rack 信息 ',\n    `node_set`        varchar(500)        NOT NULL DEFAULT '' COMMENT ' 节点 set 信息 ',\n    `create_time`     timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`     timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`     tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    `machine_spec`    varchar(100)                 DEFAULT '',\n    `region_id`       bigint(20)          NOT NULL DEFAULT '-1' COMMENT '节点所属 regionId',\n    `attributes`      text COMMENT 'es 节点 attributes 信息 , 逗号分隔',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_elastic_cluster_id_role_node_set` (`role_cluster_id`, `ip`, `port`, `node_set`),\n    KEY `idx_cluster` (`cluster`),\n    KEY `idx_hostname` (`hostname`),\n    KEY `idx_rack` (`rack`),\n    KEY `idx_region_id` (`region_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2274\n  DEFAULT CHARSET = utf8 COMMENT ='es 集群表对应各角色主机列表';\n\n-- ----------------------------\n-- Table structure for es_cluster_role_info\n-- ----------------------------\nCREATE TABLE `es_cluster_role_info`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `elastic_cluster_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'elastic_cluster 外键 id',\n    `role_cluster_name`  varchar(256)        NOT NULL DEFAULT '' COMMENT 'role 集群名称 ',\n    `role`               varchar(20)         NOT NULL DEFAULT '' COMMENT ' 集群角色 (masternode/datanode/clientnode)',\n    `pod_number`         int(11)             NOT NULL DEFAULT '0' COMMENT 'pod 数量',\n    `pid_count`          int(11)             NOT NULL DEFAULT '1' COMMENT '单机实例数',\n    `machine_spec`       varchar(100)                 DEFAULT '' COMMENT ' 机器规格 ',\n    `es_version`         varchar(150)        NOT NULL DEFAULT '' COMMENT 'es 版本 ',\n    `cfg_id`             int(11)             NOT NULL DEFAULT '-1' COMMENT '配置包 id',\n    `plug_ids`           varchar(100)        NOT NULL DEFAULT '' COMMENT ' 插件包 id 列表 ',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`        tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_elastic_cluster_id_ddcloud_cluster_name` (`elastic_cluster_id`, `role_cluster_name`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1138\n  DEFAULT CHARSET = utf8 COMMENT ='es 集群角色表';\n\n-- ----------------------------\n-- Table structure for es_config\n-- ----------------------------\nCREATE TABLE `es_config`\n(\n    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `cluster_id`     bigint(20)          NOT NULL DEFAULT '-1' COMMENT '集群 id',\n    `type_name`      varchar(255)        NOT NULL DEFAULT '' COMMENT ' 配置文件名称 ',\n    `engin_name`     varchar(100)        NOT NULL DEFAULT '' COMMENT ' 组件名称 ',\n    `config_data`    longtext COMMENT '配置内容',\n    `desc`           varchar(255)        NOT NULL DEFAULT '' COMMENT ' 配置描述 ',\n    `version_tag`    varchar(100)        NOT NULL DEFAULT '' COMMENT ' 配置 tag',\n    `version_config` bigint(20)          NOT NULL DEFAULT '-1' COMMENT '配置版本',\n    `selected`       smallint(6)         NOT NULL DEFAULT '0' COMMENT '是否在使用',\n    `create_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`    tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1130\n  DEFAULT CHARSET = utf8 COMMENT ='es 配置表';\n\n-- ----------------------------\n-- Table structure for es_machine_norms\n-- ----------------------------\nCREATE TABLE `es_machine_norms`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `role`        varchar(20)         NOT NULL DEFAULT '' COMMENT ' 角色 (masternode/datanode/clientnode/datanode-ceph)',\n    `spec`        varchar(32)         NOT NULL DEFAULT '' COMMENT ' 规格 (16-48gi-100g)',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `delete_flag` tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 16\n  DEFAULT CHARSET = utf8 COMMENT ='容器规格列表';\n\n-- ----------------------------\n-- Table structure for es_package\n-- ----------------------------\nCREATE TABLE `es_package`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `url`         varchar(255)        NOT NULL DEFAULT '' COMMENT ' 镜像地址或包地址 ',\n    `es_version`  varchar(100)        NOT NULL DEFAULT '' COMMENT ' 版本标识 ',\n    `creator`     varchar(100)        NOT NULL DEFAULT '' COMMENT ' 包创建人 ',\n    `release`     tinyint(1)          NOT NULL DEFAULT '0' COMMENT '是否为发布版本',\n    `manifest`    varchar(32)         NOT NULL DEFAULT '' COMMENT ' 类型 (3 docker/4 host)',\n    `desc`        varchar(384)                 DEFAULT '' COMMENT ' 备注 ',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag` tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除 0 未删 1 已删',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 318\n  DEFAULT CHARSET = utf8 COMMENT ='程序包版本管理';\n\n-- ----------------------------\n-- Table structure for es_plugin\n-- ----------------------------\nCREATE TABLE `es_plugin`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `name`               varchar(50)         NOT NULL DEFAULT '' COMMENT ' 插件名 ',\n    `physic_cluster_ids` varchar(100)        NOT NULL DEFAULT '' COMMENT ' 物理集群 id',\n    `version`            varchar(50)         NOT NULL DEFAULT '' COMMENT ' 插件版本 ',\n    `url`                varchar(1024)       NOT NULL DEFAULT '' COMMENT ' 插件存储地址 ',\n    `md5`                varchar(100)        NOT NULL DEFAULT '' COMMENT ' 插件文件 md5',\n    `desc`               varchar(255)        NOT NULL DEFAULT '' COMMENT ' 插件描述 ',\n    `creator`            varchar(100)        NOT NULL DEFAULT '' COMMENT ' 插件创建人 ',\n    `p_default`          tinyint(1)          NOT NULL DEFAULT '0' COMMENT '是否为系统默认：0 否 1 是',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `delete_flag`        tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 416\n  DEFAULT CHARSET = utf8 COMMENT ='es 插件包管理';\n\n-- ----------------------------\n-- Table structure for es_work_order_task\n-- ----------------------------\nCREATE TABLE `es_work_order_task`\n(\n    `id`                bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `title`             varchar(100)        NOT NULL DEFAULT '' COMMENT ' 标题 ',\n    `work_order_id`     bigint(20)          NOT NULL DEFAULT '-1' COMMENT '工单 id',\n    `physic_cluster_id` bigint(20)          NOT NULL DEFAULT '-1' COMMENT '物理集群 id',\n    `cluster_node_role` varchar(512)        NOT NULL DEFAULT '-1' COMMENT '集群节点角色',\n    `task_ids`          varchar(128)        NOT NULL DEFAULT '' COMMENT ' 各角色任务 ids',\n    `type`              varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群类型:3 docker 容器云 / 4 host 物理机 ',\n    `order_type`        varchar(50)         NOT NULL DEFAULT '' COMMENT ' 工单类型 1 集群新增 2 集群扩容 3 集群缩容 4 集群重启 5 集群升级 ',\n    `status`            varchar(20)         NOT NULL DEFAULT '' COMMENT ' 任务状态 ',\n    `creator`           varchar(100)        NOT NULL DEFAULT '' COMMENT ' 工单创建人 ',\n    `create_time`       timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`       timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`       tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    `handle_data`       longtext COMMENT '工单数据',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1958\n  DEFAULT CHARSET = utf8 COMMENT ='es 工单任务表';\n\n-- ----------------------------\n-- Table structure for es_work_order_task_detail\n-- ----------------------------\nCREATE TABLE `es_work_order_task_detail`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `work_order_task_id` bigint(20)          NOT NULL DEFAULT '-1' COMMENT '工单任务 id',\n    `role`               varchar(100)        NOT NULL DEFAULT '' COMMENT ' 所属角色 ',\n    `hostname`           varchar(100)        NOT NULL DEFAULT '' COMMENT ' 主机名称 /ip',\n    `grp`                int(11)             NOT NULL DEFAULT '0' COMMENT '机器的分组',\n    `idx`                int(11)             NOT NULL DEFAULT '0' COMMENT '机器在分组中的索引',\n    `task_id`            bigint(20)          NOT NULL DEFAULT '-1' COMMENT '容器云 / 物理机 接口返回任务 id',\n    `status`             varchar(20)         NOT NULL DEFAULT '' COMMENT ' 任务状态 ',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`        tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_work_order_task_id_role_hostname_delete_flag` (`work_order_task_id`, `role`, `hostname`, `delete_flag`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 6592\n  DEFAULT CHARSET = utf8 COMMENT ='es 工单任务详情表';\n\n-- ----------------------------\n-- Table structure for gateway_cluster_info\n-- ----------------------------\nCREATE TABLE `gateway_cluster_info`\n(\n    `id`           bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `cluster_name` varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群名称 ',\n    `create_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_cluster_name` (`cluster_name`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 188\n  DEFAULT CHARSET = utf8 COMMENT ='gateway 集群信息';\n\n-- ----------------------------\n-- Table structure for gateway_cluster_node_info\n-- ----------------------------\nCREATE TABLE `gateway_cluster_node_info`\n(\n    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `cluster_name`   varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群名称 ',\n    `host_name`      varchar(50)         NOT NULL DEFAULT '' COMMENT ' 主机名 ',\n    `port`           int(10)             NOT NULL DEFAULT '-1' COMMENT '端口',\n    `heartbeat_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '心跳时间',\n    `create_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_ip_port` (`host_name`, `port`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 490264\n  DEFAULT CHARSET = utf8 COMMENT ='gateway 节点信息';\n\n-- ----------------------------\n-- Table structure for index_template_alias\n-- ----------------------------\nCREATE TABLE `index_template_alias`\n(\n    `id`                bigint(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `index_template_id` int(10)             NOT NULL DEFAULT '-1' COMMENT '索引模板 id',\n    `name`              varchar(50)         NOT NULL DEFAULT '' COMMENT ' 别名 ',\n    `filterterm`        varchar(255)        NOT NULL DEFAULT '' COMMENT ' 过滤器 ',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 4\n  DEFAULT CHARSET = utf8 COMMENT ='索引别名';\n\n-- ----------------------------\n-- Table structure for index_template_config\n-- ----------------------------\nCREATE TABLE `index_template_config`\n(\n    `is_source_separated`      tinyint(4)          NOT NULL DEFAULT '0' COMMENT '是否是索引处分分离的 0 不是 1 是',\n    `idc_flags`                tinyint(1)          NOT NULL DEFAULT '0' COMMENT 'idc 标识',\n    `adjust_rack_shard_factor` decimal(10, 2)      NOT NULL DEFAULT '1.00' COMMENT '模板 shard 的资源消耗因子',\n    `mapping_improve_enable`   tinyint(4)          NOT NULL DEFAULT '1' COMMENT 'mapping 优化开关 1 开 0 关',\n    `pre_create_flags`         tinyint(1)          NOT NULL DEFAULT '1' COMMENT '预创建标识',\n    `update_time`              timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `disable_source_flags`     tinyint(1)          NOT NULL DEFAULT '0' COMMENT '禁用 source 标识',\n    `disable_index_rollover`   tinyint(1)          NOT NULL DEFAULT '1' COMMENT '禁用 indexRollover 功能',\n    `dynamic_limit_enable`     tinyint(4)          NOT NULL DEFAULT '1' COMMENT '动态限流开关 1 开 0 关',\n    `logic_id`                 int(10)             NOT NULL DEFAULT '-1' COMMENT '逻辑模板 id',\n    `create_time`              timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `shard_num`                int(11)             NOT NULL DEFAULT '1' COMMENT 'shard 数量',\n    `adjust_rack_tps_factor`   decimal(10, 2)      NOT NULL DEFAULT '1.00' COMMENT '容量规划时，tps 的系数',\n    `id`                       bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n    PRIMARY KEY (`id`),\n    KEY `idx_logic_id` (`logic_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1546\n  DEFAULT CHARSET = utf8 COMMENT ='模板配置信息';\n\n-- ----------------------------\n-- Table structure for index_template_info\n-- ----------------------------\nCREATE TABLE `index_template_info`\n(\n    `id`                bigint(20) unsigned          NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `name`              varchar(128)                 NOT NULL DEFAULT '' COMMENT ' 名称 ',\n    `data_type`         tinyint(4)                   NOT NULL DEFAULT '-1' COMMENT '数据类型',\n    `date_format`       varchar(50)                  NOT NULL DEFAULT '' COMMENT ' 索引分区的时间后缀 ',\n    `is_active`         tinyint(2)                   NOT NULL DEFAULT '1' COMMENT '有效标记',\n    `data_center`       varchar(20)                  NOT NULL DEFAULT '' COMMENT ' 数据中心 ',\n    `expire_time`       bigint(20)                   NOT NULL DEFAULT '-1' COMMENT '保存时长',\n    `hot_time`          int(10)                      NOT NULL DEFAULT '-1' COMMENT '热数据保存时长',\n    `responsible`       varchar(500)                          DEFAULT '' COMMENT ' 责任人 ',\n    `date_field`        varchar(50)                  NOT NULL DEFAULT '' COMMENT ' 时间字段 ',\n    `date_field_format` varchar(128)                 NOT NULL DEFAULT '' COMMENT ' 时间字段的格式 ',\n    `id_field`          varchar(512)                          DEFAULT '' COMMENT 'id 字段 ',\n    `routing_field`     varchar(512)                          DEFAULT '' COMMENT 'routing 字段 ',\n    `expression`        varchar(100)                 NOT NULL DEFAULT '' COMMENT ' 索引表达式 ',\n    `desc`              varchar(500)                 NOT NULL DEFAULT '' COMMENT ' 索引描述 ',\n    `quota`             decimal(10, 3)               NOT NULL DEFAULT '-1.000' COMMENT '规格',\n    `project_id`        int(10)                      NOT NULL DEFAULT '-1' COMMENT 'project_id',\n    `ingest_pipeline`   varchar(512)                 NOT NULL DEFAULT '' COMMENT 'ingest_pipeline',\n    `block_read`        tinyint(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否禁读，0：否，1：是',\n    `block_write`       tinyint(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否禁写，0：否，1：是',\n    `create_time`       timestamp                    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`       timestamp                    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `write_rate_limit`  bigint(255)                  NOT NULL DEFAULT '-1' COMMENT '写入限流值',\n    `resource_id`       bigint(20)                   NOT NULL DEFAULT '-1' COMMENT '逻辑集群 id',\n    `check_point_diff`  bigint(100)                  NOT NULL DEFAULT '0' COMMENT 'dcdr 位点差',\n    `level`             tinyint(4)                   NOT NULL DEFAULT '1' COMMENT '服务等级分为 1,2,3',\n    `has_dcdr`          tinyint(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否开启 dcdr',\n    `open_srv`          varchar(255)                          DEFAULT NULL COMMENT '已开启的模板服务',\n    `disk_size`         decimal(10, 3)                        DEFAULT '-1.000' COMMENT '可用磁盘容量',\n    `health`            int(11)                               DEFAULT '-1' COMMENT '模版健康；-1 是 UNKNOW',\n    PRIMARY KEY (`id`),\n    KEY `idx_data_center` (`data_center`),\n    KEY `idx_is_active` (`is_active`),\n    KEY `idx_name` (`name`),\n    KEY `idx_project_id` (`project_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 25998\n  DEFAULT CHARSET = utf8 COMMENT ='逻辑索引模板表';\n\n-- ----------------------------\n-- Table structure for index_template_physical_info\n-- ----------------------------\nCREATE TABLE `index_template_physical_info`\n(\n    `id`            bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `logic_id`      int(10)             NOT NULL DEFAULT '-1' COMMENT '逻辑模板 id',\n    `name`          varchar(128)        NOT NULL DEFAULT '' COMMENT ' 模板名字 ',\n    `expression`    varchar(128)        NOT NULL DEFAULT '' COMMENT ' 表达式 ',\n    `cluster`       varchar(128)        NOT NULL DEFAULT '' COMMENT ' 集群名字 ',\n    `rack`          varchar(512)        NOT NULL DEFAULT '' COMMENT 'rack',\n    `shard`         int(10)             NOT NULL DEFAULT '1' COMMENT 'shard 个数',\n    `shard_routing` int(10)             NOT NULL DEFAULT '1' COMMENT '内核的逻辑 shard',\n    `version`       int(10)             NOT NULL DEFAULT '0' COMMENT '版本',\n    `role`          tinyint(4)          NOT NULL DEFAULT '1' COMMENT '角色 1master 2slave',\n    `status`        tinyint(4)          NOT NULL DEFAULT '1' COMMENT '1 常规 -1 索引删除中 -2 已删除',\n    `config`        text COMMENT '配置 json 格式',\n    `create_time`   timestamp           NULL     DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`   timestamp           NULL     DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `region_id`     int(10)             NOT NULL DEFAULT '-1' COMMENT '模板关联的 regionId',\n    PRIMARY KEY (`id`),\n    KEY `idx_cluster_name_status` (`cluster`, `name`, `status`),\n    KEY `idx_log_id_statud` (`logic_id`, `status`),\n    KEY `idx_logic_id` (`logic_id`),\n    KEY `idx_region_id` (`region_id`),\n    KEY `idx_status` (`status`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 23700\n  DEFAULT CHARSET = utf8 COMMENT ='物理模板信息';\n\n-- ----------------------------\n-- Table structure for index_template_type\n-- ----------------------------\nCREATE TABLE `index_template_type`\n(\n    `id`                  bigint(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `index_template_id`   int(10)             NOT NULL DEFAULT '-1' COMMENT '索引模板 id',\n    `index_template_name` varchar(100)        NOT NULL DEFAULT '' COMMENT ' 索引模板名称 ',\n    `name`                varchar(100)        NOT NULL DEFAULT '' COMMENT 'type 名称 ',\n    `id_field`            varchar(128)        NOT NULL DEFAULT '' COMMENT 'id 字段 ',\n    `routing`             varchar(100)        NOT NULL DEFAULT '' COMMENT 'routing 字段 ',\n    `source`              tinyint(4)          NOT NULL DEFAULT '1' COMMENT '0 不存 source 1 存 source',\n    `is_active`           tinyint(2)          NOT NULL DEFAULT '1' COMMENT '是否激活 1 是 0 否',\n    `create_time`         timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`         timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='索引模板 type';\n\n-- ----------------------------\n-- Table structure for logi_job\n-- ----------------------------\nCREATE TABLE `logi_job`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `job_code`    varchar(100) NOT NULL DEFAULT '' COMMENT 'task taskCode',\n    `task_code`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务 code',\n    `class_name`  varchar(255) NOT NULL DEFAULT '' COMMENT ' 类的全限定名 ',\n    `try_times`   int(10)      NOT NULL DEFAULT '0' COMMENT '第几次重试',\n    `worker_code` varchar(200) NOT NULL DEFAULT '' COMMENT ' 执行机器 ',\n    `app_name`    varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `start_time`  datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '开始时间',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `job_code` (`job_code`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 381677\n  DEFAULT CHARSET = utf8 COMMENT ='正在执行的 job 信息';\n\n-- ----------------------------\n-- Table structure for logi_job_log\n-- ----------------------------\nCREATE TABLE `logi_job_log`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `job_code`    varchar(100) NOT NULL DEFAULT '' COMMENT 'job taskCode',\n    `task_code`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务 code',\n    `task_name`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务名称 ',\n    `task_desc`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务描述 ',\n    `task_id`     bigint(20)   NOT NULL DEFAULT '0' COMMENT '任务 id',\n    `class_name`  varchar(255) NOT NULL DEFAULT '' COMMENT ' 类的全限定名 ',\n    `try_times`   int(10)      NOT NULL DEFAULT '0' COMMENT '第几次重试',\n    `worker_code` varchar(200) NOT NULL DEFAULT '' COMMENT ' 执行机器 ',\n    `worker_ip`   varchar(200) NOT NULL DEFAULT '' COMMENT ' 执行机器 ip',\n    `start_time`  datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '开始时间',\n    `end_time`    datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '结束时间',\n    `status`      tinyint(4)   NOT NULL DEFAULT '0' COMMENT '执行结果 1 成功 2 失败 3 取消',\n    `error`       text         NOT NULL COMMENT '错误信息',\n    `result`      text         NOT NULL COMMENT '执行结果',\n    `app_name`    varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_job_code` (`job_code`) USING BTREE\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 381395\n  DEFAULT CHARSET = utf8 COMMENT ='job 执行历史日志';\n\n\n\n-- ----------------------------\n-- Table structure for logi_task\n-- ----------------------------\nCREATE TABLE `logi_task`\n(\n    `id`              bigint(20)    NOT NULL AUTO_INCREMENT,\n    `task_code`       varchar(100)  NOT NULL DEFAULT '' COMMENT 'task taskCode',\n    `task_name`       varchar(255)  NOT NULL DEFAULT '' COMMENT ' 名称 ',\n    `task_desc`       varchar(1000) NOT NULL DEFAULT '' COMMENT ' 任务描述 ',\n    `cron`            varchar(100)  NOT NULL DEFAULT '' COMMENT 'cron 表达式 ',\n    `class_name`      varchar(255)  NOT NULL DEFAULT '' COMMENT ' 类的全限定名 ',\n    `params`          varchar(1000) NOT NULL DEFAULT '' COMMENT ' 执行参数 map 形式 {key1:value1,key2:value2}',\n    `retry_times`     int(10)       NOT NULL DEFAULT '0' COMMENT '允许重试次数',\n    `last_fire_time`  datetime               DEFAULT CURRENT_TIMESTAMP COMMENT '上次执行时间',\n    `timeout`         bigint(20)    NOT NULL DEFAULT '0' COMMENT '超时 毫秒',\n    `status`          tinyint(4)    NOT NULL DEFAULT '0' COMMENT '1 等待 2 运行中 3 暂停',\n    `sub_task_codes`  varchar(1000) NOT NULL DEFAULT '' COMMENT ' 子任务 code 列表, 逗号分隔 ',\n    `consensual`      varchar(200)  NOT NULL DEFAULT '' COMMENT ' 执行策略 ',\n    `owner`           varchar(200)  NOT NULL DEFAULT '' COMMENT ' 责任人 ',\n    `task_worker_str` varchar(3000) NOT NULL DEFAULT '' COMMENT ' 机器执行信息 ',\n    `app_name`        varchar(100)  NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `create_time`     datetime               DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`     datetime               DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `task_code` (`task_code`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 548\n  DEFAULT CHARSET = utf8 COMMENT ='任务信息';\n\n-- ----------------------------\n-- Table structure for logi_task_lock\n-- ----------------------------\nCREATE TABLE `logi_task_lock`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `task_code`   varchar(100) NOT NULL DEFAULT '' COMMENT 'task taskCode',\n    `worker_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n    `app_name`    varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `expire_time` bigint(20)   NOT NULL DEFAULT '0' COMMENT '过期时间',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uni_task_app` (`task_code`, `app_name`) USING BTREE\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 569\n  DEFAULT CHARSET = utf8 COMMENT ='任务锁';\n\n-- ----------------------------\n-- Table structure for logi_worker\n-- ----------------------------\nCREATE TABLE `logi_worker`\n(\n    `id`              bigint(20)   NOT NULL AUTO_INCREMENT,\n    `worker_code`     varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n    `worker_name`     varchar(100) NOT NULL DEFAULT '' COMMENT 'worker 名 ',\n    `ip`              varchar(100) NOT NULL DEFAULT '' COMMENT 'worker 的 ip',\n    `cpu`             int(11)      NOT NULL DEFAULT '0' COMMENT 'cpu 数量',\n    `cpu_used`        double       NOT NULL DEFAULT '0' COMMENT 'cpu 使用率',\n    `memory`          double       NOT NULL DEFAULT '0' COMMENT '内存, 以 M 为单位',\n    `memory_used`     double       NOT NULL DEFAULT '0' COMMENT '内存使用率',\n    `jvm_memory`      double       NOT NULL DEFAULT '0' COMMENT 'jvm 堆大小，以 M 为单位',\n    `jvm_memory_used` double       NOT NULL DEFAULT '0' COMMENT 'jvm 堆使用率',\n    `job_num`         int(10)      NOT NULL DEFAULT '0' COMMENT '正在执行 job 数',\n    `heartbeat`       datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '心跳时间',\n    `app_name`        varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `create_time`     datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`     datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `worker_code` (`worker_code`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 8\n  DEFAULT CHARSET = utf8 COMMENT ='worker 信息';\n\n-- ----------------------------\n-- Table structure for logi_worker_blacklist\n-- ----------------------------\nCREATE TABLE `logi_worker_blacklist`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `worker_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `worker_code` (`worker_code`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='worker 黑名单列表';\n\n-- ----------------------------\n-- Table structure for operate_record_info\n-- ----------------------------\nCREATE TABLE `operate_record_info`\n(\n    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `project_name`   varchar(255)                 DEFAULT NULL COMMENT '应用',\n    `module_id`      int(10)             NOT NULL DEFAULT '-1' COMMENT '模块 id',\n    `operate_id`     int(10)             NOT NULL DEFAULT '-1' COMMENT '操作 id',\n    `trigger_way_id` int(11)                      DEFAULT NULL COMMENT '触发方式',\n    `user_operation` varchar(50)         NOT NULL DEFAULT '' COMMENT ' 操作人 ',\n    `content`        longtext COMMENT '操作内容',\n    `operate_time`   timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',\n    `create_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `biz_id`         varchar(255)                 DEFAULT NULL,\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 8218\n  DEFAULT CHARSET = utf8 COMMENT ='操作记录表';\n\n\n-- ----------------------------\n-- Table structure for project_arius_resource_logic\n-- ----------------------------\nCREATE TABLE `project_arius_resource_logic`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `name`               varchar(128)        NOT NULL DEFAULT '' COMMENT ' 资源名称 ',\n    `type`               tinyint(4)          NOT NULL DEFAULT '2' COMMENT '资源类型 1 共享公共资源 2 独享资源',\n    `project_id`         varchar(1024)       NOT NULL DEFAULT '-1' COMMENT '资源所属的 project_id',\n    `data_center`        varchar(20)         NOT NULL DEFAULT '' COMMENT ' 数据中心 cn/us01',\n    `responsible`        varchar(128)                 DEFAULT '' COMMENT ' 资源责任人 ',\n    `memo`               varchar(512)        NOT NULL DEFAULT '' COMMENT ' 资源备注 ',\n    `quota`              decimal(8, 2)       NOT NULL DEFAULT '1.00' COMMENT '资源的大小',\n    `level`              tinyint(4)          NOT NULL DEFAULT '1' COMMENT '服务等级 1 normal 2 important 3 vip',\n    `config_json`        varchar(1024)       NOT NULL DEFAULT '' COMMENT ' 集群配置 ',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `health`             tinyint(4)          NOT NULL DEFAULT '3' COMMENT '集群状态 1 green 2 yellow 3 red -1 未知',\n    `data_node_spec`     varchar(20)         NOT NULL DEFAULT '' COMMENT ' 节点规格 ',\n    `disk_total`         bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘总量 单位 byte',\n    `disk_usage`         bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘使用量 单位 byte',\n    `disk_usage_percent` decimal(10, 5)      default NULL COMMENT '集群磁盘空闲率 单位 0 ~1',\n    `es_cluster_version` varchar(20)         default NULL COMMENT 'es 集群版本',\n    `node_num`           int(10)             NOT NULL DEFAULT '0' COMMENT '节点个数',\n    `data_node_num`      int(10)             NOT NULL DEFAULT '0' COMMENT '节点个数',\n    PRIMARY KEY (`id`),\n    KEY `idx_name` (`name`),\n    KEY `idx_project_id` (`project_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 3922\n  DEFAULT CHARSET = utf8 COMMENT ='逻辑资源信息';\n\n-- ----------------------------\n-- Table structure for project_logi_cluster_auth\n-- ----------------------------\nCREATE TABLE `project_logi_cluster_auth`\n(\n    `id`               bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `project_id`       int(10)             NOT NULL DEFAULT '-1' COMMENT '项目 id',\n    `logic_cluster_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '逻辑集群 id',\n    `type`             int(10)             NOT NULL DEFAULT '-1' COMMENT '权限类型，0- 超管，1- 配置管理，2- 访问，-1- 无权限',\n    `responsible`      varchar(100)                 DEFAULT '' COMMENT ' 责任人 id 列表 ',\n    `status`           int(10)             NOT NULL DEFAULT '1' COMMENT '状态 1 有效 0 无效',\n    `create_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_project_id` (`project_id`),\n    KEY `idx_logic_cluster_id` (`logic_cluster_id`),\n    KEY `idx_status` (`status`),\n    KEY `idx_type` (`type`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='project 逻辑集群权限';\n\n-- ----------------------------\n-- Table structure for project_template_info\n-- ----------------------------\nCREATE TABLE `project_template_info`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `project_id`  int(10)             NOT NULL DEFAULT '-1' COMMENT '项目 id',\n    `template`    varchar(100)        NOT NULL DEFAULT '' COMMENT ' 模板名称, 不能关联模板 id 模板会跨集群迁移，id 会变 ',\n    `type`        int(10)             NOT NULL DEFAULT '-1' COMMENT 'appid 的权限 1 读写 2 读 -1 未知',\n    `status`      int(10)             NOT NULL DEFAULT '1' COMMENT '状态 1 有效 0 无效',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_project_id` (`project_id`),\n    KEY `idx_status` (`status`),\n    KEY `idx_template_id` (`template`),\n    KEY `idx_type` (`type`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='project 模板信息';\n\n-- ----------------------------\n-- Table structure for user_metrics_config_info\n-- ----------------------------\nCREATE TABLE `user_metrics_config_info` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `user_name` varchar(255) NOT NULL COMMENT '用户账号',\n  `metric_info` text COMMENT '指标看板的配置',\n  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=1602 DEFAULT CHARSET=utf8 COMMENT='用户关联到指标的配置信息表';\n\n\n#权限点和角色的初始化数据\ninsert into logi_security_role_permission (id, role_id, permission_id, create_time, update_time, is_delete, app_name)\nvalues (1597, 1, 0, '2022-06-01 21:19:42.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1935, 1, 1593, '2022-06-14 17:41:03.0', '2022-08-27 17:36:58.0', 0, 'know_search'),\n       (1937, 1, 1637, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1939, 1, 1639, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1941, 1, 1641, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1943, 1, 1643, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1945, 1, 1645, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1947, 1, 1647, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1949, 1, 1649, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1951, 1, 1651, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1953, 1, 1653, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1955, 1, 1655, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1957, 1, 1657, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1959, 1, 1659, '2022-06-14 17:41:03.0', '2022-08-25 10:33:59.0', 1, 'know_search'),\n       (1961, 1, 1661, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1963, 1, 1597, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1965, 1, 1673, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1967, 1, 1675, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1969, 1, 1677, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1971, 1, 1679, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1973, 1, 1599, '2022-06-14 17:41:03.0', '2022-08-25 10:36:08.0', 1, 'know_search'),\n       (1975, 1, 1681, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1977, 1, 1683, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1979, 1, 1685, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1981, 1, 1687, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1983, 1, 1601, '2022-06-14 17:41:03.0', '2022-08-25 10:36:44.0', 1, 'know_search'),\n       (1985, 1, 1689, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1987, 1, 1691, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1989, 1, 1693, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1991, 1, 1695, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1993, 1, 1697, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1995, 1, 1699, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1997, 1, 1603, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1999, 1, 1701, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2001, 1, 1703, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2003, 1, 1705, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2005, 1, 1707, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2007, 1, 1709, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2009, 1, 1711, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2011, 1, 1713, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2013, 1, 1715, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2015, 1, 1717, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2017, 1, 1719, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2019, 1, 1721, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2021, 1, 1723, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2023, 1, 1605, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2025, 1, 1725, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2027, 1, 1727, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2029, 1, 1729, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2031, 1, 1731, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2033, 1, 1733, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2035, 1, 1735, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2037, 1, 1737, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2039, 1, 1739, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2041, 1, 1741, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2043, 1, 1743, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2045, 1, 1607, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2047, 1, 1745, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2049, 1, 1747, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2051, 1, 1749, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2053, 1, 1751, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2055, 1, 1753, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2057, 1, 1755, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2059, 1, 1609, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2061, 1, 1757, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2063, 1, 1855, '2022-06-14 17:41:03.0', '2022-08-25 10:34:13.0', 0, 'know_search'),\n       (2065, 1, 1857, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2067, 1, 1611, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2069, 1, 1759, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2071, 1, 1859, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2073, 1, 1861, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2075, 1, 1863, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2077, 1, 1865, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2079, 1, 1867, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2081, 1, 1613, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2083, 1, 1761, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2085, 1, 1615, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2087, 1, 1763, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2089, 1, 1619, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2091, 1, 1769, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2093, 1, 1771, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2095, 1, 1773, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2097, 1, 1621, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2099, 1, 1775, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2101, 1, 1777, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2103, 1, 1779, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2105, 1, 1781, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2107, 1, 1783, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2109, 1, 1785, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2111, 1, 1787, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2113, 1, 1789, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2115, 1, 1791, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2117, 1, 1793, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2119, 1, 1795, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2121, 1, 1797, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2123, 1, 1799, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2125, 1, 1801, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2127, 1, 1623, '2022-06-14 17:41:03.0', '2022-08-27 17:34:08.0', 0, 'know_search'),\n       (2129, 1, 1803, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2131, 1, 1805, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2133, 1, 1807, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2135, 1, 1809, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2137, 1, 1625, '2022-06-14 17:41:03.0', '2022-08-27 17:34:08.0', 0, 'know_search'),\n       (2139, 1, 1811, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2141, 1, 1813, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2143, 1, 1815, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2145, 1, 1817, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2147, 1, 1627, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2149, 1, 1819, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2151, 1, 1821, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2153, 1, 1629, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2155, 1, 1823, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2157, 1, 1825, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2159, 1, 1827, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2161, 1, 1829, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2163, 1, 1831, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2165, 1, 1631, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2167, 1, 1833, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2169, 1, 1835, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2171, 1, 1837, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2173, 1, 1839, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2175, 1, 1841, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2177, 1, 1633, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2179, 1, 1843, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2181, 1, 1845, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2183, 1, 1847, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2185, 1, 1849, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2187, 1, 1851, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2189, 1, 1635, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2191, 1, 1853, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2193, 2, 1595, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2195, 2, 1663, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2197, 2, 1665, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2199, 2, 1667, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2201, 2, 1669, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2203, 2, 1671, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2205, 2, 1601, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2207, 2, 1689, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2209, 2, 1691, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2211, 2, 1693, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2213, 2, 1695, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2215, 2, 1697, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2217, 2, 1699, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2219, 2, 1605, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2221, 2, 1725, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2223, 2, 1727, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2225, 2, 1729, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2227, 2, 1731, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2229, 2, 1733, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2231, 2, 1735, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2233, 2, 1737, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2235, 2, 1739, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2237, 2, 1741, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2239, 2, 1743, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2241, 2, 1609, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2243, 2, 1757, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2245, 2, 1855, '2022-06-14 18:08:56.0', '2022-08-25 10:33:12.0', 1, 'know_search'),\n       (2247, 2, 1857, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2249, 2, 1611, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2251, 2, 1759, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2253, 2, 1859, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2255, 2, 1861, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2257, 2, 1863, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2259, 2, 1865, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2261, 2, 1867, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2263, 2, 1613, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2265, 2, 1761, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2267, 2, 1615, '2022-06-14 18:08:56.0', '2022-08-25 20:27:55.0', 1, 'know_search'),\n       (2269, 2, 1763, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2271, 2, 1617, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2273, 2, 1765, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2275, 2, 1767, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2277, 2, 1631, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2279, 2, 1833, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2281, 2, 1835, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2283, 2, 1837, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2285, 2, 1839, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2287, 2, 1841, '2022-06-14 18:08:56.0', '2022-08-26 17:59:49.0', 1, 'know_search'),\n       (2643, 1, 1595, '2022-06-17 16:39:23.0', '2022-08-25 10:35:06.0', 1, 'know_search'),\n       (4505, 1, 1869, '2022-07-04 15:45:59.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (4507, 1, 1871, '2022-07-04 15:46:56.0', '2022-08-27 17:37:22.0', 0, 'know_search'),\n       (5275, 1, 1873, '2022-06-17 15:53:54.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5277, 2, 1873, '2022-06-17 15:53:54.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5349, 1, 1875, '2022-06-17 15:53:54.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5591, 1, 1759, '2022-08-11 10:39:01.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5593, 2, 1759, '2022-08-11 10:39:59.0', '2022-08-25 10:31:42.0', 0, 'know_search');\n#权限点初始化数据\ninsert into logi_security_permission (id, permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name)\nvalues  (1593, '物理集群', 0, 0, 1, '物理集群', '2022-05-24 18:08:22.0', '2022-08-24 20:07:31.0', 0, 'know_search'),\n        (1595, '我的集群', 0, 0, 1, '我的集群', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1597, '集群版本', 0, 0, 1, '集群版本', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1599, 'Gateway管理', 0, 0, 1, 'Gateway管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1601, '模板管理', 0, 0, 1, '模板管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1603, '模板服务', 0, 0, 1, '模板服务', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1605, '索引管理', 0, 0, 1, '索引管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1607, '索引服务', 0, 0, 1, '索引服务', '2022-05-24 18:08:22.0', '2022-05-24 18:24:16.0', 0, 'know_search'),\n        (1609, '索引查询', 0, 0, 1, '索引查询', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1611, '查询诊断', 0, 0, 1, '查询诊断', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1613, '集群看板', 0, 0, 1, '集群看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1615, '网关看板', 0, 0, 1, '网关看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1617, '我的申请', 0, 0, 1, '我的申请', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1619, '我的审批', 0, 0, 1, '我的审批', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1621, '任务列表', 0, 0, 1, '任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1623, '调度任务列表', 0, 0, 1, '调度任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1625, '调度日志', 0, 0, 1, '调度日志', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1627, '用户管理', 0, 0, 1, '用户管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1629, '角色管理', 0, 0, 1, '角色管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1631, '应用管理', 0, 0, 1, '应用管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1633, '平台配置', 0, 0, 1, '平台配置', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1635, '操作记录', 0, 0, 1, '操作记录', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1637, '查看集群列表及详情', 1593, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1639, '接入集群', 1593, 1, 2, '接入集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1641, '新建集群', 1593, 1, 2, '新建集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1643, '扩缩容', 1593, 1, 2, '扩缩容', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1645, '升级', 1593, 1, 2, '升级', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1647, '重启', 1593, 1, 2, '重启', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1649, '配置变更', 1593, 1, 2, '配置变更', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1651, 'Region划分', 1593, 1, 2, 'Region划分', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1653, 'Region管理', 1593, 1, 2, 'Region管理', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1655, '快捷命令', 1593, 1, 2, '快捷命令', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1657, '编辑', 1593, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1659, '绑定Gateway', 1593, 1, 2, '绑定Gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1661, '下线', 1593, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1663, '查看集群列表及详情', 1595, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1665, '申请集群', 1595, 1, 2, '申请集群', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1667, '编辑', 1595, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1669, '扩缩容', 1595, 1, 2, '扩缩容', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1671, '下线', 1595, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1673, '查看版本列表', 1597, 1, 2, '查看版本列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1675, '新增版本', 1597, 1, 2, '新增版本', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1677, '编辑', 1597, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1679, '删除', 1597, 1, 2, '删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1681, '查看Gateway 集群列表', 1599, 1, 2, '查看Gateway 集群列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1683, '接入gateway', 1599, 1, 2, '接入gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1685, '编辑', 1599, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1687, '下线', 1599, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1689, '查看模板列表及详情', 1601, 1, 2, '查看模板列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1691, '申请模板', 1601, 1, 2, '申请模板', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1693, '编辑', 1601, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1695, '下线', 1601, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1697, '编辑Mapping', 1601, 1, 2, '编辑Mapping', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1699, '编辑Setting', 1601, 1, 2, '编辑Setting', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1701, '查看模板列表', 1603, 1, 2, '查看模板列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1703, '开关：预创建', 1603, 1, 2, '开关：预创建', '2022-05-24 18:08:23.0', '2022-06-14 16:49:48.0', 0, 'know_search'),\n        (1705, '开关：过期删除', 1603, 1, 2, '开关：过期删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1707, '开关：冷热分离', 1603, 1, 2, '开关：冷热分离', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1709, '开关：pipeline', 1603, 1, 2, '开关：写入限流', '2022-05-24 18:08:23.0', '2022-06-14 16:49:49.0', 0, 'know_search'),\n        (1711, '开关：Rollover', 1603, 1, 2, '开关：Rollover', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1713, '查看DCDR链路', 1603, 1, 2, '查看DCDR链路', '2022-05-24 18:08:23.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1715, '创建DCDR链路', 1603, 1, 2, '创建DCDR链路', '2022-05-24 18:08:24.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1717, '清理', 1603, 1, 2, '清理', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1719, '扩缩容', 1603, 1, 2, '扩缩容', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1721, '升版本', 1603, 1, 2, '升版本', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1723, '批量操作', 1603, 1, 2, '批量操作', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1725, '查看索引列表及详情', 1605, 1, 2, '查看索引列表及详情', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1727, '编辑Mapping', 1605, 1, 2, '编辑Mapping', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1729, '编辑Setting', 1605, 1, 2, '编辑Setting', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1731, '禁用读', 1607, 1, 2, '禁用读', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1733, '禁用写', 1607, 1, 2, '禁用写', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1735, '设置别名', 1605, 1, 2, '设置别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1737, '删除别名', 1605, 1, 2, '删除别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1739, '关闭索引', 1607, 1, 2, '关闭索引', '2022-05-24 18:08:24.0', '2022-07-15 09:52:25.0', 0, 'know_search'),\n        (1741, '下线', 1605, 1, 2, '下线', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1743, '批量删除', 1605, 1, 2, '批量删除', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1745, '查看列表', 1607, 1, 2, '查看列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1747, '执行Rollover', 1607, 1, 2, '执行Rollover', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1749, '执行shrink', 1607, 1, 2, '执行shrink', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1751, '执行split', 1607, 1, 2, '执行split', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1753, '执行ForceMerge', 1607, 1, 2, '执行ForceMerge', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1755, '批量执行', 1607, 1, 2, '批量执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1757, 'DSL查询', 1609, 1, 2, 'DSL查询', '2022-05-24 18:08:24.0', '2022-06-14 16:39:48.0', 0, 'know_search'),\n        (1759, '查询模板', 0, 0, 1, '查看查询模板列表', '2022-05-24 18:08:24.0', '2022-08-11 10:37:43.0', 0, 'know_search'),\n        (1761, '查看集群看板', 1613, 1, 2, '查看集群看板', '2022-05-24 18:08:24.0', '2022-06-14 16:37:54.0', 0, 'know_search'),\n        (1763, '查看网关看板', 1615, 1, 2, '查看网关看板', '2022-05-24 18:08:24.0', '2022-06-14 16:38:14.0', 0, 'know_search'),\n        (1765, '查看我的申请列表', 1617, 1, 2, '查看我的申请列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1767, '撤回', 1617, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1769, '查看我的审批列表', 1619, 1, 2, '查看我的审批列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1771, '驳回', 1619, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-07-18 20:57:33.0', 0, 'know_search'),\n        (1773, '通过', 1619, 1, 2, '通过', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1775, '查看任务列表', 1621, 1, 2, '查看任务列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1777, '查看进度', 1621, 1, 2, '查看进度', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1779, '执行', 1621, 1, 2, '执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1781, '暂停', 1621, 1, 2, '暂停', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1783, '重试', 1621, 1, 2, '重试', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1785, '取消', 1621, 1, 2, '取消', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1787, '查看日志（子任务）', 1621, 1, 2, '查看日志（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1789, '重试（子任务）', 1621, 1, 2, '重试（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1791, '忽略（子任务）', 1621, 1, 2, '忽略（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1793, '查看详情（DCDR）', 1621, 1, 2, '查看详情（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1795, '取消（DCDR）', 1621, 1, 2, '取消（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1797, '重试（DCDR）', 1621, 1, 2, '重试（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1799, '强切（DCDR）', 1621, 1, 2, '强切（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1801, '返回（DCDR）', 1621, 1, 2, '返回（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1803, '查看任务列表', 1623, 1, 2, '查看任务列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1805, '查看日志', 1623, 1, 2, '查看日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1807, '执行', 1623, 1, 2, '执行', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1809, '暂停', 1623, 1, 2, '暂停', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1811, '查看调度日志列表', 1625, 1, 2, '查看调度日志列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1813, '调度详情', 1625, 1, 2, '调度详情', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1815, '执行日志', 1625, 1, 2, '执行日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1817, '终止任务', 1625, 1, 2, '终止任务', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1819, '查看用户列表', 1627, 1, 2, '查看用户列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1821, '分配角色', 1627, 1, 2, '分配角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1823, '查看角色列表', 1629, 1, 2, '查看角色列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1825, '编辑', 1629, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1827, '绑定用户', 1629, 1, 2, '绑定用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1829, '回收用户', 1629, 1, 2, '回收用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1831, '删除角色', 1629, 1, 2, '删除角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1833, '查看应用列表', 1631, 1, 2, '查看应用列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1835, '新建应用', 1631, 1, 2, '新建应用', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1837, '编辑', 1631, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1839, '删除', 1631, 1, 2, '删除', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1841, '访问设置', 1631, 1, 2, '访问设置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1843, '查看平台配置列表', 1633, 1, 2, '查看平台配置列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1845, '新增平台配置', 1633, 1, 2, '新增平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1847, '禁用平台配置', 1633, 1, 2, '禁用平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1849, '编辑平台配置', 1633, 1, 2, '编辑平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1851, '删除平台配置', 1633, 1, 2, '删除平台配置', '2022-05-24 18:08:26.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1853, '查看操作记录列表', 1635, 1, 2, '查看操作记录列表', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1855, 'Kibana', 1609, 1, 2, 'Kibana', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1857, 'SQL查询', 1609, 1, 2, 'SQL查询', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1859, '批量修改限流值', 1759, 1, 2, '批量修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1861, '禁用', 1759, 1, 2, '禁用', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1863, '修改限流值', 1759, 1, 2, '修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1865, '查看异常查询列表', 1611, 1, 2, '查看异常查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1867, '查看慢查询列表', 1611, 1, 2, '查看慢查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:21.0', 0, 'know_search'),\n        (1869, '新增角色', 1629, 1, 2, '新增角色', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1871, 'Dashboard', 0, 0, 1, '查看dashboard', '2022-05-24 18:08:26.0', '2022-08-27 17:35:50.0', 0, 'know_search'),\n        (1873, '新建索引', 1605, 1, 2, '新建索引', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1875, '查看dashboard', 1871, 1, 2, '查看dashboard', '2022-05-24 18:08:24.0', '2022-08-27 17:35:50.0', 0,\n         'know_search');\n#角色初始化数据\ninsert into logi_security_role (id, role_code, role_name, description, last_reviser, create_time, update_time,\n                                is_delete, app_name)\nvalues (1, 'r14715628', '管理员', '管理员', 'admin', '2022-06-01 21:19:42.0', '2022-07-06 22:23:59.0', 0,\n        'know_search'),\n       (2, 'r14481382', '资源 owner', '普通用户拥有的最大权限', 'admin', '2022-06-14 18:08:56.0',\n        '2022-07-06 20:36:31.0', 0, 'know_search');\n#初始化用户\ninsert into logi_security_user (id, user_name, pw, salt, real_name, phone, email, dept_id, is_delete,\n                                create_time, update_time, app_name)\nvalues (1, 'admin',\n        'V1ZkU2RHRlhOSGhOYWs0M1VVWmFjVk5xVW1oaE0zUmlTVEJCZUZGRFRtUm1WVzh5VlcxNGMyRkZRamw3UUZacVNqUmhhM3RiSTBBeVFDTmRmVW8yVW14c2FFQjl7QFZqSjRha3tbI0AzQCNdfUo2UmxsaEB9Mv{#cdRgJ45Lqx}3IubEW87!==',\n        '', 'admin', '18888888888', 'admin@12345.com', null, 0, '2022-05-26 05:46:12.0', '2022-08-26 09:06:19.0',\n        'know_search');\n#初始化用户和角色的关系\ninsert into logi_security_user_role (id, user_id, role_id, create_time, update_time, is_delete, app_name)\nvalues (1, 1, 2, '2022-08-26 19:54:22.0', '2022-08-26 19:54:22.0', 0, 'know_search'),\n       (2, 1, 1, '2022-08-30 21:05:17.0', '2022-08-30 21:05:17.0', 0, 'know_search');\n#项目和项目配置、es user 的关系\ninsert into project_arius_config (project_id, analyze_response_enable, is_source_separated, aggr_analyze_enable,\n                                  dsl_analyze_enable, slow_query_times, is_active, memo, create_time, update_time)\nvalues (1, 1, 0, 1, 1, 1000, 1, '超级应用', '2022-06-14 18:52:08.0', '2022-08-27 23:13:14.0'),\n       (2, 1, 0, 1, 1, 1000, 1, '元数据模版应用 不可以被删除', '2022-08-25 11:18:45.0', '2022-08-25 11:18:45.0');\ninsert into logi_security_project (id, project_code, project_name, description, dept_id, running, create_time,\n                                   update_time, is_delete, app_name)\nvalues (1, 'p14000143', 'SuperApp', '超级应用', 0, 1, '2022-05-26 05:49:08.0', '2022-08-24 11:09:49.0', 0,\n        'know_search'),\n       (2, 'p18461793', '元数据模版应用 _ 误删', '元数据模版应用 不可以被删除', 0, 1, '2022-08-25 11:06:04.0',\n        '2022-08-25 11:18:45.0', 0, 'know_search');\ninsert into arius_es_user (id, index_exp, data_center, is_root, memo, ip, verify_code, is_active,\n                           query_threshold, cluster, responsible, search_type, create_time, update_time,\n                           project_id, is_default_display)\nvalues (1, null, 'cn', 1, '管理员 APP', '', 'azAWiJhxkho33ac', 1, 100, 'logi-elasticsearch-meta',\n        'admin', 0,\n        '2022-05-26 09:35:38.0', '2022-06-23 00:16:47.0', 1, 1),\n       (2, null, 'cn', 0, '元数据模版 APP', '', 'vkDgPEfD3jQJ1YY', 1, 1000, '', null, 1, '2022-07-05 08:16:17.0',\n        '2022-08-25 21:48:58.0', 2, 1);\n\n\n## 配置初始化数据\nTRUNCATE  table `arius_config_info`;\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (187, 'arius.cache.switch', 'logic.template.cache.enable', 'true', 1, -1, -1, '逻辑模板缓存是否开启', '2021-09-01 20:37:47', '2021-11-29 14:57:47', '2021-09-01 20:37:47');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (189, 'arius.cache.switch', 'physical.template.cache.enable', 'true', 1, -1, -1, '获取物理模板列表是否开启全局缓存', '2021-09-01 20:41:22', '2021-11-29 14:57:45', '2021-09-01 20:41:22');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (191, 'arius.cache.switch', 'cluster.phy.cache.enable', 'true', 1, -1, -1, '获取物理集群列表是否开启全局缓存', '2021-09-01 20:42:31', '2021-11-29 14:57:42', '2021-09-01 20:42:31');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (193, 'arius.cache.switch', 'cluster.logic.cache.enable', 'true', 1, -1, -1, '获取逻辑集群列表是否开启全局缓存', '2021-09-01 20:43:08', '2021-11-29 14:57:39', '2021-09-01 20:43:08');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1217, 'arius.meta.monitor', 'nodestat.collect.concurrent', 'true', 1, -1, -1, '', '2021-11-18 20:24:54', '2021-11-19 16:05:39', '2021-11-18 20:24:54');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1223, 'arius.common.group', 'app.default.read.auth.indices', '\\\"\\\"', 1, -1, 2, 'app可读写的权限', '2021-12-15 20:17:06', '2021-12-16 11:17:26', '2021-12-15 20:17:06');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1225, 'arius.common.group', 'delete.expire.index.ahead.clusters', '\\\"\\\"', 1, -1, 2, '删除过期权限', '2021-12-15 20:17:48', '2021-12-16 11:17:24', '2021-12-15 20:17:48');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1227, 'arius.common.group', 'operate.index.ahead.seconds', '2 * 60 * 60', 1, -1, 2, '索引操作提前时间', '2021-12-15 20:18:37', '2021-12-16 11:17:22', '2021-12-15 20:18:37');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1229, 'arius.common.group', 'platform.govern.admin.hot.days', '-1', 1, -1, 2, '平台治理导入热存的天数', '2021-12-15 20:19:13', '2021-12-16 11:17:19', '2021-12-15 20:19:13');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1231, 'arius.common.group', 'quota.dynamic.limit.black.appIds', 'none', 1, -1, 2, 'appid黑名单控制', '2021-12-15 20:20:11', '2021-12-16 11:17:17', '2021-12-15 20:20:11');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1233, 'arius.common.group', 'quota.dynamic.limit.black.cluster', '\\\"\\\"', 1, -1, 2, 'cluster黑名单控制', '2021-12-15 20:20:39', '2021-12-16 11:17:15', '2021-12-15 20:20:39');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1235, 'arius.common.group', 'quota.dynamic.limit.black.logicId', 'none', 1, -1, 2, '模板黑名单控制', '2021-12-15 20:21:21', '2021-12-16 11:17:12', '2021-12-15 20:21:21');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1237, 'arius.common.group', 'arius.wo.auto.process.create.template.disk.maxG', '10.0', 1, -1, 2, '模板创建时设置的磁盘空间最大值', '2021-12-15 20:21:49', '2021-12-16 11:15:12', '2021-12-15 20:21:49');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1239, 'arius.common.group', 'request.interceptor.switch.open', 'true', 1, -1, 2, '请求拦截开关', '2021-12-15 20:22:14', '2021-12-16 11:15:10', '2021-12-15 20:22:14');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1241, 'arius.common.group', 'arius.didi.t2.leader.mail', '\\\"\\\"', 1, -1, 2, 'didi领导者邮箱', '2021-12-15 20:22:40', '2021-12-16 11:15:07', '2021-12-15 20:22:40');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1243, 'arius.common.group', 'defaultDay', '\\\"\\\"', 1, -1, 2, '默认hotDay值', '2021-12-15 20:23:17', '2021-12-16 11:15:04', '2021-12-15 20:23:17');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1245, 'arius.quota.config.group', 'arius.quota.config.tps.per.cpu.with.replica', '1000.0', 1, -1, 2, '资源管控cpu项', '2021-12-15 20:23:56', '2021-12-16 11:15:01', '2021-12-15 20:23:56');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1247, 'arius.quota.config.group', 'arius.quota.config.tps.per.cpu.NO.replica', '2300.0', 1, -1, 2, '资源管控cpu项', '2021-12-15 20:24:27', '2021-12-16 11:14:58', '2021-12-15 20:24:27');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1249, 'arius.quota.config.group', 'arius.quota.config.cost.per.g.per.month', '1.06', 1, -1, 2, '资源配置模板费用', '2021-12-15 20:24:59', '2021-12-16 11:14:56', '2021-12-15 20:24:59');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1251, 'arius.meta.monitor.group', 'nodestat.collect.concurrent', 'fasle', 1, -1, 2, '节点状态信息是否并行采集', '2021-12-15 20:25:35', '2022-08-26 18:10:50', '2021-12-15 20:25:35');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1253, 'arius.meta.monitor.group', 'indexstat.collect.concurrent', 'fasle', 1, -1, 2, '索引状态信息是否并行采集', '2021-12-15 20:26:00', '2022-08-26 18:10:45', '2021-12-15 20:26:00');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1255, 'arius.common.group', 'indices.recovery.ceph_max_bytes_per_sec', '10MB', 1, -1, 2, '单节点分片恢复的速率', '2021-12-15 21:33:29', '2022-04-08 17:43:14', '2021-12-15 21:33:29');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1257, 'arius.common.group', 'cluster.routing.allocation.node_concurrent_incoming_recoveries', '2', 1, -1, 2, '一个节点上允许多少并发的传入分片还原,表示为传入还原', '2021-12-16 14:41:51', '2021-12-16 14:42:24', '2021-12-16 14:41:51');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1259, 'arius.common', 'cluster.routing.allocation.node_concurrent_outgoing_recoveries', '2', 1, -1, 2, '一个节点上允许多少并发的传入分片还原,传出还原', '2021-12-16 14:42:15', '2022-02-22 11:11:48', '2021-12-16 14:42:15');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1585, 'test.test', 'testt', '21', 1, -1, -1, '请忽略2221', '2022-01-13 14:25:40', '2022-01-15 16:27:05', '2022-01-13 14:25:40');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1587, 'zptest', 'test', '<script>alert(1)</script>', 1, -1, -1, 'alert(1)', '2022-01-18 16:14:12', '2022-01-18 16:15:49', '2022-01-18 16:14:12');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1589, 'test1ddd', 'dd ddd', 'dssdddd', 1, -1, -1, 'sddsdssd', '2022-01-26 11:39:23', '2022-01-26 11:39:42', '2022-01-26 11:39:23');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1591, 'yyftemptest-01s', 'yyftemptest-01d', '', 1, -1, -1, '', '2022-03-01 16:44:12', '2022-03-01 16:44:39', '2022-03-01 16:44:12');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1593, 'test1', 's', '', 1, -1, -1, '', '2022-03-07 11:37:39', '2022-03-07 11:37:43', '2022-03-07 11:37:39');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1595, 'test1', '22', 'm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2', 1, -1, -1, '', '2022-03-15 11:19:49', '2022-03-15 11:20:08', '2022-03-15 11:19:49');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1623, 'settingGroup', 'name', 'value', 1, -1, -1, 'test', '2022-06-23 14:17:56', '2022-06-23 15:47:26', '2022-06-23 14:17:56');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1625, 'group11', 'name1', 'value1', 1, -1, -1, 'des-edit', '2022-06-23 15:22:51', '2022-06-24 09:40:51', '2022-06-23 15:22:51');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1627, 'arius.common.group', 'cluster.node.specification_list', '16c-64g-3072g,16c-48g-3071g,1c-48g-3071g,', 1, -1, 1, '节点规格列表，机型列表', '2022-07-05 14:10:27', '2022-07-18 15:01:29', '2022-07-05 14:10:27');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1629, 'ccccccccccccccdcdccccccccccccccdcdccccccccccccccdb', 'dccccccccccccccdcdcccccccc', 'vjh', 1, -1, -1, 'cdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccc', '2022-07-05 15:27:38', '2022-07-05 15:28:09', '2022-07-05 15:27:38');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1631, '2', '3', '', 1, -1, -1, '', '2022-07-06 15:26:45', '2022-07-06 15:26:58', '2022-07-06 15:26:45');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1633, 'arius.common.group', 'cluster.data.center_list', 'cn,en', 1, -1, 1, '数据中心列表', '2022-07-06 16:14:03', '2022-08-27 19:11:25', '2022-07-06 16:14:03');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1635, 'arius.common.group', 'cluster.package.version_list', '7.6.1.1,6.6.6.6,7.6.1.2', 1, -1, 1, '系统预制支持的版本', '2022-07-06 16:17:25', '2022-07-06 16:17:25', '2022-07-06 16:17:25');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1637, 'template.time.type', 'format', '[\\n  \\\"yyyy-MM-dd HH:mm:ss\\\",\\n  \\\"yyyy-MM-dd HH:mm:ss.SSS\\\",\\n  \\\"yyyy-MM-dd\\'T\\'HH:mm:ss\\\",\\n  \\\"yyyy-MM-dd\\'T\\'HH:mm:ss.SSS\\\",\\n  \\\"yyyy-MM-dd HH:mm:ss.SSS Z\\\",\\n  \\\"yyyy/MM/dd HH:mm:ss\\\",\\n  \\\"epoch_seconds\\\",\\n  \\\"epoch_millis\\\"\\n]', 1, -1, 1, '新建模版的时间格式', '2022-07-07 16:15:37', '2022-07-07 16:15:37', '2022-07-07 16:15:37');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1639, 'arius.cluster.blacklist', 'cluster.phy.name', 'didi-cluster-test', 1, -1, 1, '滴滴内部测试环境集群, 禁止任何编辑删除新增操作', '2022-07-07 17:58:02', '2022-07-07 18:44:42', '2022-07-07 17:58:02');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1641, 'arius.common.group', 'cluster.resource.type_list', '信创,acs,vmware', 1, -1, 1, '所属资源类型列表,IaaS平台类型列表', '2022-07-07 19:13:13', '2022-08-31 16:38:37', '2022-07-07 19:13:13');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1643, '55', '666', '1', 1, -1, -1, '143', '2022-07-13 16:59:41', '2022-07-13 17:01:48', '2022-07-13 16:59:41');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1645, 'arius.common.group', 'index.rollover.threshold', '0.00001', 1, -1, 1, '主分片大小达到1G后升版本', '2022-07-15 21:03:12', '2022-09-22 15:28:54', '2022-07-15 21:03:12');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1647, 'yyftemptest-01', 'yyf', 'sdv', 1, -1, -1, 'sdv', '2022-07-18 15:02:08', '2022-07-18 15:02:24', '2022-07-18 15:02:08');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1649, 'arius.common.group', 'cluster.node.count_list', '2,4,6,10', 1, -1, 1, '集群节点个数列表', '2022-07-18 15:22:33', '2022-08-27 19:13:09', '2022-07-18 15:22:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1653, 'arius.common.group', 'arius.system.template', '[\\n    \\\"arius.dsl.analyze.result\\\",\\n    \\\"arius.dsl.metrics\\\",\\n    \\\"arius.dsl.template\\\",\\n    \\\"arius.gateway.join\\\",\\n    \\\"arius_stats_index_info\\\",\\n    \\\"arius_stats_node_info\\\",\\n    \\\"arius.template.access\\\",\\n    \\\"arius_cat_index_info\\\",\\n    \\\"arius_gateway_metrics\\\",\\n    \\\"arius_stats_cluster_info\\\",\\n    \\\"arius_stats_cluster_task_info\\\",\\n    \\\"arius_stats_dashboard_info\\\",\\n    \\\"arius.appid.template.access\\\"\\n]', 1, -1, 1, '系统核心模版集合', '2022-07-21 12:25:48', '2022-07-21 12:30:06', '2022-07-21 12:25:48');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1655, 'ds12', 'sd34', 'sdsddsd', 1, -1, -1, 'ds78', '2022-07-21 17:00:44', '2022-08-01 08:52:35', '2022-07-21 17:00:44');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1657, 'arius.common.group', 'cluster.shard.big_threshold', '10', 1, -1, 1, '用于设置集群看板中的大Shard阈值，单位为gb，大于这个值就认为是大shard', '2022-07-28 17:49:59', '2022-08-26 18:08:56', '2022-07-28 17:49:59');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1671, 'arius.template.group', 'logic.template.business_type', '系统数据,日志数据,业务上报数据,test_businesss_type1,RDS数据,离线导入数据,testset,123,test_businesss_type1', 1, -1, 1, '模板业务类型', '2022-08-26 18:02:47', '2022-09-01 15:16:11', '2022-08-26 18:02:47');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1673, 'arius.template.group', 'logic.template.time_format_list', 'yyyy-MM-dd HH:mm:ss,yyyy-MM-dd HH:mm:ss.SSS,yyyy-MM-dd HH:mm:ss.SSS Z,yyyy-MM-dd\\'T\\'HH:mm:ss,yyyy-MM-dd\\'T\\'HH:mm:ss.SSS,yyyy-MM-dd\\'T\\'HH:mm:ssZ,yyyy-MM-dd\\'T\\'HH:mm:ss.SSSZ,yyyy/MM/dd HH:mm:ss,epoch_second,epoch_millis,yyyy-MM-dd', 1, -1, 1, '模板时间格式列表', '2022-08-26 18:06:07', '2022-08-31 17:16:03', '2022-08-26 18:06:07');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1675, 'arius.template.group', 'history.template.physic.indices.allocation.is_effective', 'ture', 1, -1, 1, '历史索引模板shard分配是否自动调整', '2022-08-26 18:07:53', '2022-08-31 17:07:02', '2022-08-26 18:07:53');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1677, 'arius.common.group', 'operate.record.save.time', '29', 1, -1, -1, '操作记录的保存时间', '2022-09-01 16:44:03', '2022-09-01 17:23:48', '2022-09-01 16:44:03');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1679, 'arius.common.group', 'operate.record.save_time', '25', 1, -1, 1, '操作记录的保存时间(天)', '2022-09-01 19:34:33', '2022-09-19 15:14:59', '2022-09-01 19:34:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1681, 'arius.common.group', 'super_app.default.dsl.command', '#获取节点状态\\nGET _nodes/stats\\n\\n#获取集群信息\\nGET _cluster/stats\\n\\n#获取集群健康信息\\nGET _cluster/health?v\\n\\n#查看当前集群的热点线程\\nGET _nodes/hot_threads\\n\\n#查看当前集群运行中的任务信息\\nGET _tasks?actions=*&detailed\\n\\n#shard分配说明，会在分片未分配的事后去通过这个命令查看下具体原因\\nGET /_cluster/allocation/explain\\n\\n#异常shard分配重试，当集群red有shard未分配的情况下会通过这个命令来重试分配\\nPOST /_cluster/reroute?retry_failed=true\\n\\n#清除fielddata内存，当集群因为fileddata太大导致熔断或占用很多内存，可以通过此命令释放内存\\nPOST _cache/clear?fielddata=true\\n', 1, -1, 1, '超级应用默认就有的命令', '2022-09-20 10:26:08', '2022-09-26 11:34:14', '2022-09-20 10:26:08');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1683, 'arius.common.group', 'operate.record.save.num', '30', 1, -1, -1, 'DSL和kibana操作记录保存条数', '2022-09-20 10:45:31', '2022-09-22 16:49:16', '2022-09-20 10:45:31');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1685, 'ddd', 'sdd', 'sd', 1, -1, -1, 'ds', '2022-09-21 15:22:31', '2022-09-21 15:23:00', '2022-09-21 15:22:31');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1607, 'arius.dashboard.threshold.group', 'index.segment.num_threshold', '{\\\"name\\\":\\\" 索引 Segments 个数 \\\",\\\"metrics\\\":\\\"segmentNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":100}', 1, -1, 1, '索引 Segment 个数阈值定义', '2022-06-17 09:52:11', '2022-08-27 16:05:06', '2022-06-17 09:52:11');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1609, 'arius.dashboard.threshold.group', 'index.template.segment_num_threshold', '{\\\"name\\\":\\\" 模板 Segments 个数 \\\",\\\"metrics\\\":\\\"segmentNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":700}', 1, -1, 1, '索引模板 [Segment 个数阈值] 定义', '2022-06-17 09:53:34', '2022-08-27 19:01:57', '2022-06-17 09:53:34');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1611, 'arius.dashboard.threshold.group', 'index.segment.memory_size_threshold', '{\\\"name\\\":\\\" 索引 Segments 内存大小 \\\",\\\"metrics\\\":\\\"segmentMemSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":500}', 1, -1, 1, '索引 [Segment 内存大小阈值] 定义', '2022-06-17 09:54:20', '2022-10-26 18:50:50', '2022-06-17 09:54:20');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1613, 'arius.dashboard.threshold.group', 'index.template.segment_memory_size_threshold', '{\\\"name\\\":\\\" 模板 Segments 内存大小 \\\",\\\"metrics\\\":\\\"segmentMemSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":3000}', 1, -1, 1, '索引模板 [Segment 内存大小阈值] 定义', '2022-06-17 09:54:50', '2022-10-26 18:50:27', '2022-06-17 09:54:50');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1617, 'arius.dashboard.threshold.group', 'node.shard.num_threshold', '{\\\"name\\\":\\\" 节点分片个数 \\\",\\\"metrics\\\":\\\"shardNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":1000}', 1, -1, 1, '节点 [分片个数阈值] 定义', '2022-06-17 10:01:40', '2022-08-27 19:09:44', '2022-06-17 10:01:40');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1619, 'arius.dashboard.threshold.group', 'index.shard.small_threshold', '{\\\"name\\\":\\\" 小 shard 索引列表 \\\",\\\"metrics\\\":\\\"shardSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\"<\\\",\\\"value\\\":1000}', 1, -1, 1, '索引 [小 Shard 阈值] 定义', '2022-06-17 16:11:53', '2022-08-27 19:04:19', '2022-06-17 16:11:53');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1656, 'arius.dashboard.threshold.group', 'index.mapping.num_threshold', '{\\\"name\\\":\\\" 索引 Mapping 个数 \\\",\\\"metrics\\\":\\\"mappingNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":100}', 1, -1, 1, '索引 [Mapping 个数阈值] 定义', '2022-07-28 15:50:59', '2022-08-27 18:36:48', '2022-07-28 15:50:59');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1659, 'arius.dashboard.threshold.group', 'cluster.shard.num_threshold', '{\\\"name\\\":\\\" 集群 shard 个数 \\\",\\\"metrics\\\":\\\"shardNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":10000}', 1, -1, 1, '集群 [Shard 个数阈值] 定义', '2022-08-05 15:58:22', '2022-10-27 12:00:25', '2022-08-05 15:58:22');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1661, 'arius.dashboard.threshold.group', 'cluster.metric.collector.delayed_threshold', '{\\\"name\\\":\\\"node_status 指标采集延时 \\\",\\\"metrics\\\":\\\"clusterElapsedTimeGte5Min\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":5}', 1, -1, 1, '集群 [指标采集延时阈值] 定义', '2022-08-10 14:10:47', '2022-10-26 16:20:17', '2022-08-10 14:10:47');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1663, 'arius.dashboard.threshold.group', 'node.disk.used_percent_threshold', '{\\\"name\\\":\\\" 磁盘利用率 \\\",\\\"metrics\\\":\\\"largeDiskUsage\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":80}', 1, -1, 1, '节点 [磁盘利用率阈值] 定义', '2022-08-25 14:50:41', '2022-10-26 18:48:54', '2022-08-25 14:50:41');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1665, 'arius.dashboard.threshold.group', 'node.jvm.heap.used_percent_threshold', '{\\\"name\\\":\\\" 堆内存利用率 \\\",\\\"metrics\\\":\\\"largeHead\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":75}', 1, -1, 1, '节点 [堆内存利用率阈值] 定义', '2022-08-25 16:45:33', '2022-10-26 18:48:40', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1666, 'arius.dashboard.threshold.group', 'node.cpu.used_percent_threshold', '{\\\"name\\\":\\\"CPU 利用率红线 \\\",\\\"metrics\\\":\\\"largeCpuUsage\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":60}', 1, -1, 1, '节点 [CPU 利用率阈值] 定义', '2022-08-25 16:45:33', '2022-10-26 18:48:18', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1667, 'arius.dashboard.threshold.group', 'node.jvm.heap.used_percent_time_duration_threshold', '{\\\"name\\\":\\\"node.jvm.heap.used_percent_threshold_time_duration\\\",\\\"metrics\\\":\\\"jvmHeapUsedPercentThresholdTimeDuration\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":10}', 1, -1, 1, '节点堆内存利用率阈值的 [持续时间]', '2022-08-25 16:45:33', '2022-10-26 18:47:52', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1668, 'arius.dashboard.threshold.group', 'node.cpu.used_percent_threshold_time_duration_threshold', '{\\\"name\\\":\\\"node.large.cpu.used.percent.time.threshold\\\",\\\"metrics\\\":\\\"largeCpuUsage\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":5}', 1, -1, 1, '节点 CPU 利用率超阈值的 [持续时间]', '2022-08-25 16:45:33', '2022-10-26 18:47:21', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1669, 'arius.dashboard.threshold.group', 'index.shard.big_threshold', '{\\\"name\\\":\\\"index.shard.big_threshold\\\",\\\"metrics\\\":\\\"shardSize\\\",\\\"unit\\\":\\\"G\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":20}', 1, -1, 1, '索引 [大 shard 阈值] 定义', '2022-08-26 15:25:07', '2022-08-29 10:28:24', '2022-08-26 15:25:07');\n\n\n####\ninsert into es_package (id, url, es_version, creator, `release`, manifest, `desc`, create_time, update_time, delete_flag)\nvalues  (1, 'registry.xiaojukeji.com/didibuild/elasticsearch-image.hnb-pre-v.arius.data-online.fd.didi.com.centos72:9721f7f4', '7.6.1.302', 'linyunan', 0, '3', '', '2021-03-30 20:35:03.0', '2021-10-11 16:07:51.0', 1),\n        (3, 'registry.xiaojukeji.com/didibuild/elasticsearch-image.hnb-pre-v.arius.data-online.fd.didi.com.centos72:06b79e62', '7.6.0.1203', 'linyunan', 0, '3', '', '2021-04-01 14:56:42.0', '2021-04-01 14:56:42.0', 0),\n        (15, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/elasticsearch.tar.gz', '7.6.0.1401', 'linyunan', 0, '4', '', '2021-06-21 14:56:09.0', '2021-09-14 15:33:36.0', 0),\n        (17, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/elasticsearch.tar.gz', '7.6.0.1402', 'admin', 0, '4', 'fdsafsd2', '2021-06-21 14:57:53.0', '2021-10-27 10:34:09.0', 0),\n        (23, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.6.0.13%404', '7.6.0.13', 'admin', 0, '4', 'ss', '2021-10-28 12:28:07.0', '2021-10-28 12:30:24.0', 1),\n        (27, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/234.2.3%404', '234.2.3', 'admin', 0, '4', 'dd', '2021-10-28 19:47:08.0', '2021-10-28 19:55:01.0', 1),\n        (29, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/234.2.4%404.tar.gz', '234.2.4', 'admin', 0, '4', 'dd', '2021-10-28 19:54:38.0', '2021-11-23 14:36:35.0', 1),\n        (31, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.1.2.1%404.tar.gz', '2.1.2.1', 'admin', 0, '4', 'yyf测试', '2021-11-01 10:41:20.0', '2021-11-01 17:13:38.0', 1),\n        (33, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.12.3.4%404.tar.gz', '2.12.3.4', 'admin', 0, '4', 'ceshi ', '2021-11-01 17:19:04.0', '2021-11-02 11:15:43.0', 1),\n        (35, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.3.4.5%404.tar.gz', '2.3.4.5', 'admin', 0, '4', 'ceshi ', '2021-11-01 17:19:59.0', '2021-11-02 11:15:41.0', 1),\n        (37, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/4.1.2.2%404.tar.gz', '4.1.2.2', 'admin', 0, '4', '测试沃尔特与会计银行股份大晚上是的法规环境股份的地方VG东风股份更好地发挥过', '2021-11-02 10:56:31.0', '2021-11-02 11:15:38.0', 1),\n        (39, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/3.3.3.3%404.tar.gz', '3.3.3.3', 'admin', 0, '4', '测试', '2021-11-02 11:14:49.0', '2021-11-02 11:15:35.0', 1),\n        (41, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.1.1.2%404.tar.gz', '1.1.1.2', 'admin', 0, '4', '测试测试', '2021-11-08 18:27:02.0', '2021-11-08 18:29:20.0', 1),\n        (43, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/8.8.8.8%404.tar.gz', '8.8.8.8', 'admin', 0, '4', '测试请忽略、', '2021-11-17 14:47:20.0', '2021-11-23 14:36:33.0', 1),\n        (45, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.7.7.7%404.tar.gz', '7.7.7.7', 'admin', 0, '4', '测试', '2021-11-18 14:48:38.0', '2021-11-23 14:36:30.0', 1),\n        (47, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.3.4%404.tar.gz', '1.2.3.4', 'admin', 0, '4', '', '2021-11-19 19:08:06.0', '2021-11-23 14:36:27.0', 1),\n        (49, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.9.89.1%404.tar.gz', '1.9.89.1', 'admin', 0, '4', '', '2021-11-19 19:08:55.0', '2021-11-23 14:36:23.0', 1),\n        (51, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.2.2.2%404.tar.gz', '2.2.2.3', 'admin', 0, '4', '测试测试测试', '2021-11-25 18:00:47.0', '2021-11-25 20:21:44.0', 1),\n        (53, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.2.2.5-4.tar.gz', '2.2.2.5', 'admin', 0, '4', null, '2021-11-25 20:16:51.0', '2021-11-25 20:17:23.0', 1),\n        (55, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.6.6-4.tar.gz', '6.6.6.6', 'admin', 0, '4', '测试', '2021-11-26 10:39:19.0', '2021-11-26 10:39:45.0', 1),\n        (57, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.6.6-4.tar.gz', '6.6.6.5', 'admin', 0, '4', '测试请忽略人', '2021-12-21 10:49:03.0', '2021-12-21 10:49:38.0', 0),\n        (89, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.10.2.0-4.tar.gz', '7.10.2.0', 'admin', 0, '4', 'test', '2021-12-25 11:56:11.0', '2022-06-22 14:38:24.0', 0),\n        (203, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.1.0-4.tar.gz', '6.6.1.0', 'admin', 0, '4', 'ssd', '2022-01-10 19:14:54.0', '2022-06-13 17:32:19.0', 1),\n        (205, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.2.0-4.tar.gz', '6.6.2.0', 'admin', 0, '4', 'ss', '2022-01-10 20:23:07.0', '2022-01-10 20:23:07.0', 0),\n        (211, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.3.3.5-4.tar.gz', '2.3.3.5', 'admin', 0, '4', 'ss', '2022-01-28 15:59:57.0', '2022-01-28 16:56:42.0', 1),\n        (213, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.3.3.6-4.tar.gz', '2.3.3.6', 'admin', 0, '4', 'dd', '2022-01-28 16:58:46.0', '2022-01-28 16:58:46.0', 0),\n        (215, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.1.1.1-4.tar.gz', '1.1.1.1', 'admin', 0, '4', '测试请忽略，使用完毕，QA会删除', '2022-02-18 10:49:07.0', '2022-03-23 19:55:04.0', 1),\n        (217, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.2.2.2-4.tar.gz', '2.2.2.2', 'admin', 0, '4', '测试请忽略，使用完毕，QA会删除', '2022-02-18 10:49:37.0', '2022-05-17 17:38:47.0', 1),\n        (219, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/3.3.3.3-4.tar.gz', '3.3.3.3', 'admin', 0, '4', '测试请忽略，使用完毕，QA会删除哦f', '2022-02-18 10:50:03.0', '2022-03-29 14:32:32.0', 1),\n        (221, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/4.4.4.4-4.tar.gz', '4.4.4.4', 'admin', 0, '4', '测试', '2022-03-01 11:32:58.0', '2022-03-01 11:33:05.0', 1),\n        (223, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.7.7.7-4.tar.gz', '7.7.7.7', 'admin', 0, '4', 'ceshi ', '2022-03-01 17:40:56.0', '2022-05-23 10:17:09.0', 1),\n        (225, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/99.2.2.2222-4.tar.gz', '99.2.2.2222', 'admin', 0, '4', '测试请忽略', '2022-03-29 14:34:50.0', '2022-03-29 14:47:04.0', 1),\n        (227, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/10.20.30.40-4.tar.gz', '10.20.30.40', 'admin', 0, '4', '测试请忽略', '2022-03-29 14:57:14.0', '2022-03-29 14:59:26.0', 1),\n        (233, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.3.3333-4.tar.gz', '1.2.3.3333', 'yyfQA_admin', 0, '4', '测试请忽略', '2022-04-11 14:18:18.0', '2022-07-04 17:25:18.0', 0),\n        (257, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/elasticsearch.tar.gz', '7.6.2.1', '', 0, '4', 'test', '2021-06-21 14:56:09.0', '2022-06-24 18:16:58.0', 1),\n        (259, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.2.1-4.tar.gz', '1.2.2.1', '', 0, '4', 'test0624', '2022-06-24 18:07:38.0', '2022-06-24 18:16:53.0', 1),\n        (261, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/9.9.9.9-4.tar.gz', '9.9.9.9', '', 0, '4', '111', '2022-06-24 18:08:22.0', '2022-06-24 18:16:50.0', 1),\n        (263, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.1.1.3-4.tar.gz', '1.1.1.4', 'yyfQA_admin', 0, '4', 'test111服务范围框架发改委开复工文件和管控', '2022-06-24 18:17:43.0', '2022-07-05 10:10:46.0', 0),\n        (265, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/9.9.9.9-4.tar.gz', '9.9.9.9', 'admin', 0, '4', 'test', '2022-06-27 10:11:50.0', '2022-08-07 10:45:40.0', 1),\n        (267, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.6.2.1-4.tar.gz', '7.6.2.1', 'admin', 0, '4', 'test1', '2022-06-27 18:26:06.0', '2022-07-07 12:13:01.0', 0),\n        (281, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.6.0.1403-4.tar.gz', '7.6.0.1403', 'admin', 0, '4', '7.6.0.1401', '2022-07-07 16:15:42.0', '2022-07-07 16:15:42.0', 0),\n        (283, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/5.6.2.0-4.tar.gz', '5.6.2.0', 'yyfQA_admin', 0, '4', '开源版本', '2022-07-12 10:58:51.0', '2022-07-26 15:35:53.0', 1),\n        (285, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.1.0-4.tar.gz', '6.6.1.0', 'yyfQA_admin', 0, '4', '开源版本', '2022-07-12 10:59:32.0', '2022-07-12 10:59:32.0', 0),\n        (287, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/8.0.1.0-4.tar.gz', '8.0.1.0', 'admin', 0, '4', '开源版本', '2022-07-13 16:51:07.0', '2022-08-08 18:08:44.0', 0),\n        (289, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.3.4-4.tar.gz', '1.2.3.4', 'admin', 0, '4', '的', '2022-07-21 20:30:03.0', '2022-07-21 20:30:16.0', 1),\n        (291, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.1.3-null.tar.gz', '1.2.1.3', 'admin', 0, '4', '233', '2022-07-26 15:31:14.0', '2022-08-09 11:43:41.0', 1),\n        (293, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.2.2.6-4.tar.gz', '2.2.2.6', 'admin', 0, '4', '9', '2022-07-28 16:06:11.0', '2022-08-07 10:44:22.0', 1),\n        (295, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.5.6.1-4.tar.gz', '1.5.6.1', 'admin', 0, '4', '11', '2022-07-28 17:18:50.0', '2022-07-28 17:18:56.0', 1),\n        (297, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.1.2.4-4.tar.gz', '1.1.2.4', 'admin', 0, '4', '123', '2022-07-28 20:31:10.0', '2022-08-07 10:44:18.0', 1),\n        (299, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/8.8.1.8-4.tar.gz', '8.8.1.8', 'admin', 0, '4', '测试删除', '2022-08-08 10:29:18.0', '2022-08-08 10:29:23.0', 1),\n        (301, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/7.6.2.0-4.tar.gz', '7.6.2.0', 'admin', 0, '4', '开源版本', '2022-08-08 18:08:30.0', '2022-08-08 18:08:30.0', 0),\n        (303, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.8.20.0-4.tar.gz', '6.8.20.0', 'admin', 0, '4', '开源版本', '2022-08-08 18:10:12.0', '2022-08-08 18:10:12.0', 0),\n        (305, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/5.6.2.0-4.tar.gz', '5.6.2.0', 'admin', 0, '4', '开源版本', '2022-08-08 18:11:17.0', '2022-08-08 18:11:17.0', 0),\n        (307, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/2.1.1.2-4.tar.gz', '2.1.1.2', 'admin', 0, '4', 'hhh', '2022-08-08 18:16:44.0', '2022-08-08 18:16:51.0', 1),\n        (309, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.3.1-4.tar.gz', '1.2.3.1', 'admin', 0, '4', 'lll', '2022-08-09 10:33:14.0', '2022-08-09 10:35:06.0', 1),\n        (311, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.1.3-4.tar.gz', '1.2.1.3', 'admin', 0, '4', '123', '2022-08-09 11:44:32.0', '2022-08-09 11:45:03.0', 1),\n        (313, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.1.3-4.tar.gz', '7.6.1.2', 'admin', 0, '4', '123123', '2022-08-09 11:50:30.0', '2022-08-25 20:29:25.0', 0),\n        (317, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/4.3.2.2-4.tar.gz', '4.3.2.2', 'admin', 0, '4', 'temp特色图等待', '2022-08-16 11:12:39.0', '2022-08-16 11:14:00.0', 1),\n        (319, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.6.3-4.tar.gz', '6.6.6.3', 'admin', 0, '4', '测试', '2022-08-25 21:45:02.0', '2022-08-25 21:45:17.0', 1),\n        (321, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/1.2.3.1-4.tar.gz', '6.6.6.6', 'admin', 0, '4', '1', '2022-08-26 15:47:48.0', '2022-08-27 14:55:35.0', 0);\n/*\n0.3.1原始sql\nUPDATE logi_security_permission SET permission_name = 'Kibana', parent_id = 1609, leaf = 1, level = 2, description = 'Kibana', create_time = '2022-05-24 18:08:26.0', update_time = '2022-06-14 16:44:02.0', is_delete = 0, app_name = 'know_search' WHERE id = 1855;\nUPDATE logi_security_permission SET permission_name = 'SQL查询', parent_id = 1609, leaf = 1, level = 2, description = 'SQL查询', create_time = '2022-05-24 18:08:26.0', update_time = '2022-06-14 16:44:02.0', is_delete = 0, app_name = 'know_search' WHERE id = 1857;\nUPDATE logi_security_permission SET permission_name = 'DSL查询', parent_id = 1609, leaf = 1, level = 2, description = 'DSL查询', create_time = '2022-05-24 18:08:24.0', update_time = '2022-06-14 16:39:48.0', is_delete = 0, app_name = 'know_search' WHERE id = 1757;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1609, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2059;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1757, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2061;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1855, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:34:13.0', is_delete = 0, app_name = 'know_search' WHERE id = 2063;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1857, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2065;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1609, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2241;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1757, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2243;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1855, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:33:12.0', is_delete = 1, app_name = 'know_search' WHERE id = 2245;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1857, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2247;\n*/\n# 0.3.1.1变更sql\n# 1.更新level和leaf\nUPDATE logi_security_permission SET permission_name = 'DSL查询', parent_id = 0, leaf = 0, level = 1, description = 'DSL查询', create_time = '2022-05-24 18:08:24.0', update_time = '2022-09-02 19:01:17.0', is_delete = 0, app_name = 'know_search' WHERE id = 1757;\nUPDATE logi_security_permission SET permission_name = 'Kibana', parent_id = 0, leaf = 0, level = 1, description = 'Kibana', create_time = '2022-05-24 18:08:26.0', update_time = '2022-09-02 19:01:17.0', is_delete = 0, app_name = 'know_search' WHERE id = 1855;\nUPDATE logi_security_permission SET permission_name = 'SQL查询', parent_id = 0, leaf = 0, level = 1, description = 'SQL查询', create_time = '2022-05-24 18:08:26.0', update_time = '2022-09-02 19:01:17.0', is_delete = 0, app_name = 'know_search' WHERE id = 1857;\n#1.1修改logi_security_role_permission\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1609, create_time = '2022-06-14 17:41:03.0', update_time = '2022-09-02 19:04:07.0', is_delete = 1, app_name = 'know_search' WHERE id = 2059;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1757, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2061;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1855, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:34:13.0', is_delete = 0, app_name = 'know_search' WHERE id = 2063;\nUPDATE logi_security_role_permission SET role_id = 1, permission_id = 1857, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2065;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1609, create_time = '2022-06-14 18:08:56.0', update_time = '2022-09-02 19:04:07.0', is_delete = 1, app_name = 'know_search' WHERE id = 2241;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1757, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2243;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1855, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:33:12.0', is_delete = 1, app_name = 'know_search' WHERE id = 2245;\nUPDATE logi_security_role_permission SET role_id = 2, permission_id = 1857, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2247;\n#2.更新name\nUPDATE logi_security_permission SET permission_name = 'Kibana查询', parent_id = 0, leaf = 0, level = 1, description = 'Kibana查询', create_time = '2022-05-24 18:08:26.0', update_time = '2022-09-05 14:19:29.0', is_delete = 0, app_name = 'know_search' WHERE id = 1855;\n#3.新增3个权限点\nINSERT INTO logi_security_permission (permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name) VALUES ('DSL', 0, 0, 1, 'DSL', '2022-05-24 18:08:24.0', '2022-09-02 19:01:17.0', 0, 'know_search');\nINSERT INTO logi_security_permission (permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name) VALUES ('Kibana', 0, 0, 1, 'Kibana', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search');\nINSERT INTO logi_security_permission (permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name) VALUES ('SQL', 0, 0, 1, 'SQL', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search');\n#3.1 新增logi_security_role_permission\ninsert into logi_security_role_permission(role_id, permission_id, is_delete, app_name)\nvalues (1, 1877, 0, 'know_search'),\n       (1, 1879, 0, 'know_search'),\n       (1, 1881, 0, 'know_search'),\n       (2, 1877, 0, 'know_search'),\n       (2, 1879, 1, 'know_search'),\n       (2, 1881, 0, 'know_search');\n\n#4.再次更新level和leaf\nUPDATE logi_security_permission SET permission_name = 'DSL查询', parent_id = 1877, leaf = 1, level = 2, description = 'DSL查询' WHERE id = 1757;\nUPDATE logi_security_permission SET permission_name = 'Kibana查询', parent_id = 1879, leaf = 1, level = 2, description = 'Kibana查询' WHERE id = 1855;\nUPDATE logi_security_permission SET permission_name = 'SQL查询', parent_id = 1881, leaf = 1, level = 2, description = 'SQL查询' WHERE id = 1857;\n\n#5.用户和应用配置信息表\nalter table user_metrics_config_info rename to user_config_info;\nalter table user_config_info COMMENT '用户和应用配置信息表';\nalter table `user_config_info` change COLUMN metric_info config_info text COMMENT '用户下某个应用的配置';\nalter table `user_config_info` add column project_id int(10) NOT NULL DEFAULT '-1' COMMENT '项目 id' after user_name;\nalter table `user_config_info` add column config_type int(10) NOT NULL DEFAULT '1' COMMENT '配置类型,1- 指标看板和 dashboard，2- 查询模板列表' after project_id;\ntruncate table user_config_info;\n\nINSERT INTO `user_config_info`(`user_name`, `project_id`, `config_type`, `config_info`)\nselect DISTINCT t1.user_name,t2.project_id,2,\n                concat('[{\\\"firstUserConfigType\\\":\\\"searchQuery\\\",\\\"projectId\\\":',t2.project_id,',\\\"secondUserConfigType\\\":\\\"searchTemplate\\\",\\\"userConfigTypes\\\":[\\\"totalCostAvg\\\",\\\"totalShardsAvg\\\"],\\\"userName\\\":\\\"',t1.user_name,'\\\"}]') as config_info\nfrom logi_security_user t1 inner join\n     logi_security_user_project t2 on t1.id=t2.user_id and t2.is_delete='0'\nwhere  t1.is_delete='0';\n-- ----------------------------\n-- Table structure for metric_dictionary_info\n-- ----------------------------\nDROP TABLE IF EXISTS `metric_dictionary_info`;\nCREATE TABLE `metric_dictionary_info`  (\n                                           `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,\n                                           `type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标分类',\n                                           `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '指标名称',\n                                           `price` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '-1' COMMENT '指标价值',\n                                           `interval` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '1' COMMENT '计算间隔',\n                                           `current_cal_logic` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '当前计算逻辑',\n                                           `is_gold` tinyint(1) UNSIGNED ZEROFILL NULL DEFAULT 0 COMMENT '是否黄金指标(0否1是)',\n                                           `unit` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '单位',\n                                           `interactive_form` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '交互形式',\n                                           `is_warning` tinyint(1) UNSIGNED ZEROFILL NULL DEFAULT 0 COMMENT '告警指标(0否1是)',\n                                           `source` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标来源',\n                                           `tags` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标标签',\n                                           `model` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '模块',\n                                           `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n                                           `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n                                           `is_active` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否生效',\n                                           `is_threshold` tinyint(1) UNSIGNED ZEROFILL NOT NULL DEFAULT 0 COMMENT '是否有阈值',\n                                           `threshold` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '阈值',\n                                           `metric_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '阈值信息',\n                                           PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 5754 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户和应用配置信息表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Records of metric_dictionary_info\n-- ----------------------------\nINSERT INTO `metric_dictionary_info` VALUES (4915, '集群统计', '集群状态、shard总数、索引模板总数、文档总数、索引数、节点分配（Master节点数/Data节点数/Client节点数）、堆内存总量（已用内存、空闲内存）、磁盘总量（已用磁盘、空闲磁盘）、节点总数（活跃节点数、死亡节点数）、集群索引存储量、未分配Shard数', '集群当前运行状态概览信息', '当前值', '索引模板总数: /_template命令获取的数组大小\\n通过GET _cluster/stats命令直接获取\\n  集群状态：status\\n  shard总数：shards.total\\n  文档总数：indices.docs.count\\n  索引数:indices.count\\n  Master节点数:nodes.count.master\\n  Data节点数:nodes.count.data \\n  Client节点数:nodes.count.total - nodes.count.master-nodes.count.data\\n  堆内存总量:nodes.os.mem.total_in_bytes\\n  已用内存:nodes.os.mem.used_in_bytes\\n  空闲内存:nodes.os.mem.free_percent\\n  磁盘总量:nodes.fs.total_in_bytes\\n  已用磁盘:nodes.fs.total_in_bytes - nodes.fs.free_in_bytes\\n  空闲磁盘:nodes.fs.free_in_bytes\\n  节点总数:nodes.count.total\\n  活跃节点数，死亡节点数:查询配置的集群节点列表后和ES集群节点ip列表进行匹配，可以匹配上的为活跃节点 \\n  集群索引存储量：indices.store.size_in_bytes  ->  新增字段indicesStoreSize\\n未分配Shard数：通过 _cat/health?format=json 获取unassign字段 -> 新增字段unassignedShardNum', 1, NULL, '状态栏', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:20:01', 1, 0, NULL, 'basic');\nINSERT INTO `metric_dictionary_info` VALUES (4917, '系统指标', 'CPU使用率（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群CPU使用率与均衡情况观察', '当前值', '[当前值] 集群下所有节点，通过GET _nodes/stats命令获取nodes.{nodeName}.os.cpu.percent ，根据分位进行聚合', 1, '%', '折线图', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:49:28', 1, 0, NULL, 'cpuUsage');\nINSERT INTO `metric_dictionary_info` VALUES (4919, '系统指标', 'CPU 1分钟负载（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群1分钟负载与均衡情况观察', '当前值', '[当前值] 集群下所有节点，通过GET _nodes/stats命令获取nodes.{nodeName}.os.cpu.load_average.1m，根据分位进行聚合', 0, NULL, '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:49:30', 1, 0, NULL, 'cpuLoad1M');\nINSERT INTO `metric_dictionary_info` VALUES (4921, '系统指标', '磁盘使用率（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群磁盘利用率与均衡情况观察', '当前值', '[当前值]集群下所有节点，通过GET _nodes/stats命令获取（nodes.{nodeName}.fs.total.total_in_bytes - nodes.{nodeName}.fs.total.free_in_bytes）/nodes.{nodeName}.fs.total.total_in_bytes，根据分位进行聚合', 0, '%', '折线图', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:20:16', 1, 0, NULL, 'diskUsage');\nINSERT INTO `metric_dictionary_info` VALUES (4923, '系统指标', '磁盘使用情况（磁盘空闲量/磁盘使用量/磁盘总量）', '集群磁盘使用情况概览', '当前值', '通过GET _cluster/stats命令获取\\n磁盘总量 : nodes.{nodeName}.fs.total_in_bytes\\n磁盘使用量 : nodes.{nodeName}.fs.total_in_bytes - nodes.fs.free_in_bytes\\n磁盘空闲量 : nodes.{nodeName}.fs.free_in_bytes', 0, 'GB', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, 'diskInfo');\nINSERT INTO `metric_dictionary_info` VALUES (4925, '系统指标', '网络出口流量', '集群网络出口流量/网络入口流量走势', '当前值', '[当前值] 集群下的所有节点，通过GET _nodes/stats命令获取nodes.{nodeName}.transport.rx_size_in_bytes、nodes.{nodeName}.transport.tx_size_in_bytes（接收、发送）的累加值', 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:47:08', 1, 0, NULL, 'sendTransSize');\nINSERT INTO `metric_dictionary_info` VALUES (4927, '系统指标', '指标采集失败率', '集群指标采集失败率（采集失败次数/采集窗口大小）', '60S', NULL, 1, '%', '折线图', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-28 11:31:36', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4929, '性能指标', '执行任务耗时（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群节点任务执行耗时与均衡情况观察', '当前值', '[当前值] _cat/tasks?v&detailed&format=json命令获取结果集中running_time字段的分位值', 0, 'S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-10 16:00:21', 1, 0, NULL, 'taskCost');\nINSERT INTO `metric_dictionary_info` VALUES (4931, '性能指标', '执行任务数量', '集群全部节点每秒执行任务数走势', '当前值', '[当前值] _cat/tasks?v&detailed&format=json命令获取结果集的大小', 0, '个/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:07', 1, 0, NULL, 'taskCount');\nINSERT INTO `metric_dictionary_info` VALUES (4932, '系统指标', '网络入口流量', '集群网络出口流量/网络入口流量走势', '当前值', '[当前值] 集群下的所有节点，通过GET _nodes/stats命令获取nodes.{nodeName}.transport.rx_size_in_bytes、nodes.{nodeName}.transport.tx_size_in_bytes（接收、发送）的累加值', 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:47:11', 1, 0, NULL, 'recvTransSize');\nINSERT INTO `metric_dictionary_info` VALUES (4933, '性能指标', '查询QPS', '集群Shard级别查询并发量概览', '60S', '[累加值]  集群下的所有节点，间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.query_total的差值累加值/间隔时间', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-11-02 19:17:58', 1, 0, NULL, 'readTps');\nINSERT INTO `metric_dictionary_info` VALUES (4935, '性能指标', '写入TPS', '集群Shard级别写入并发量概览', '60S', '[累加值] 集群下的所有节点，间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.indexing.index_total的差值累加值/间隔时间', 1, '个/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-25 15:47:20', 1, 0, NULL, 'writeTps');\nINSERT INTO `metric_dictionary_info` VALUES (4937, '性能指标', '查询耗时', '集群Shard级别查询耗时概览', '60S', '[最大值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.search.query_total差值累加值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-11-02 19:25:44', 1, 0, NULL, 'searchLatency');\nINSERT INTO `metric_dictionary_info` VALUES (4939, '性能指标', '写入耗时', '集群文档级别写入耗时概览', '60S', '[最大值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.indexing.index_total差值累加值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-11-02 19:25:17', 1, 0, NULL, 'indexingLatency');\nINSERT INTO `metric_dictionary_info` VALUES (4941, '性能指标', '网关写入TPS', '通过网关每秒写入集群的写入请求次数', '60S', NULL, 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:08', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4943, '性能指标', '网关写入吞吐量', '通过网关每秒写入集群的文档字节数', '60S', NULL, 1, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4945, '性能指标', '网关写入请求耗时', '通过网关写入请求的平均耗时', '60S', NULL, 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4947, '性能指标', '网关写入请求响应体大小', '通过网关写入请求的响应体平均大小', '60S', NULL, 0, 'B', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4949, '性能指标', '网关查询QPS', '通过网关每秒查询的请求次数', '60S', NULL, 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4951, '性能指标', '网关查询请求耗时', '通过网关查询请求的平均耗时', '60S', NULL, 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4953, '性能指标', '网关单次查询命中Shard数', '通过网关查询请求的命中Shard平均数', '60S', NULL, 0, '个', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4955, '状态指标', '迁移中shard列表', '集群Shard迁移感知', '当前值', '[当前值] 通过GET _cat/recovery?v&h=i,s,t,st,shost,thost&active_only=true命令获取的集合详情', 0, NULL, '列表展示（index,source_host,target_host,bytes_recovered bytes_percen,translog_ops_percentt）', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'movingShards');\nINSERT INTO `metric_dictionary_info` VALUES (4957, '状态指标', '未分配Shard列表', '集群节点掉线感知', '当前值', '[当前值]通过GET _cat/shards?format=json命令获取state=UNASSIGN的shard列表', 0, NULL, '列表项（index，shard，prirep，state）', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-30 08:56:42', 1, 0, NULL, 'unAssignShards');\nINSERT INTO `metric_dictionary_info` VALUES (4959, '状态指标', 'Dead节点列表', '', '当前值', '[当前值] 通过GET _nodes命令获取集群节点信息，与平台集群节点列表对比缺失的节点', 0, NULL, '列表项（节点IP、主机名、实例名）', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:42:21', 1, 0, NULL, 'invalidNodes');\nINSERT INTO `metric_dictionary_info` VALUES (4961, '状态指标', 'PendingTask列表', '集群PengingTask感知', '当前值', '[当前值] 通过/_cluster/pending_tasks命令获取的集合', 0, NULL, '列表项（插入顺序、优先级、任务来源、执行任务前等待时间）', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:42:38', 1, 0, NULL, 'pendingTasks');\nINSERT INTO `metric_dictionary_info` VALUES (4963, '系统指标', 'CPU利用率', 'CPU使用率，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.os.cpu.percent字段', 1, '%', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:42:08', 1, 0, NULL, 'os-cpu-percent');\nINSERT INTO `metric_dictionary_info` VALUES (4965, '系统指标', '磁盘空闲率', '磁盘空闲率，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.fs.total.free_in_bytes/nodes.{nodeName}.fs.total.total_in_bytes', 1, '%', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:36:11', 1, 0, NULL, 'fs-total-disk_free_percent');\nINSERT INTO `metric_dictionary_info` VALUES (4967, '系统指标', '网络发送流量', '网络包为单位的每秒发送流量，Top节点趋势', '当前值', '[平均值]，间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.transport.tx_size_in_bytes的差值/时间间隔', 0, 'MB/S', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:53:56', 1, 0, NULL, 'transport-tx_size_in_bytes_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4969, '系统指标', '网络接收流量', '网络包为单位的接收流量，Top节点趋势', '当前值', '[平均值]，间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.transport.rx_size_in_bytes的差值/时间间隔', 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:54:17', 1, 0, NULL, 'transport-rx_size_in_bytes_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4971, '系统指标', 'CPU近1分钟负载', 'CPU近1分钟负载，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.os.cpu.load_average.1m', 0, NULL, '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:36:49', 1, 0, NULL, 'os-cpu-load_average-1m');\nINSERT INTO `metric_dictionary_info` VALUES (4973, '基本性能指标', '写入TPS', '节点索引写入速率平均值，Top节点趋势', '60S', '[平均值] (当前时刻减去上一时刻通过GET _nodes/stats命令获取nodes.{nodeName}.indices.indexing.index_total的差值)/时间间隔(S)', 1, '个/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 09:45:25', 1, 0, NULL, 'indices-indexing-index_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4975, '基本性能指标', '网关查询QPS', '网关通过ClientNode节点每秒查询的请求数，Top节点趋势', '60S', NULL, 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-28 11:31:36', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4977, '基本性能指标', '网关写入TPS', '网关通过ClientNode节点每秒写入的请求数，Top节点趋势', '60S', NULL, 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-28 11:31:36', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4979, '基本性能指标', '网关写入吞吐量', '网关通过ClientNode节点每秒写入的吞吐量，Top节点趋势', '60S', NULL, 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:10:44', 1, 0, NULL, 'collectorDelayed');\nINSERT INTO `metric_dictionary_info` VALUES (4981, '基本性能指标', '写入耗时', '节点索引写入耗时平均值，Top节点趋势', '60S', '[平均值],间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.docs.count的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:06:05', 1, 0, NULL, 'indices-indexing-index_time_per_doc');\nINSERT INTO `metric_dictionary_info` VALUES (4983, '基本性能指标', 'Query QPS', '节点索引Query速率平均值，Top节点趋势', '60S', '[平均值],间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.query_total的差值/时间间隔', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 09:45:49', 1, 0, NULL, 'indices-search-query_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4985, '基本性能指标', 'Fetch QPS', '节点索引Fetch速率平均值，Top节点趋势', '60S', '[平均值] ,间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.fetch_total的差值/时间间隔', 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 09:46:00', 1, 0, NULL, 'indices-search-fetch_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4987, '基本性能指标', 'Query耗时', '节点索引Query耗时平均值，Top节点趋势', '60S', '[平均值],间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.search.query_total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:37:36', 1, 0, NULL, 'indices-search-query_time_per_query');\nINSERT INTO `metric_dictionary_info` VALUES (4989, '基本性能指标', 'Fetch耗时', '节点索引Fetch耗时平均值，Top节点趋势', '60S', '[平均值] ,间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.fetch_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.search.fetch_total的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:37:46', 1, 0, NULL, 'indices-search-fetch_time_per_fetch');\nINSERT INTO `metric_dictionary_info` VALUES (4991, '基本性能指标', 'Scroll当下请求量', '节点索引Scroll请求量，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.search.scroll_current的值', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:37:56', 1, 0, NULL, 'indices-search-scroll_current');\nINSERT INTO `metric_dictionary_info` VALUES (4993, '基本性能指标', 'Scroll请求耗时', '节点Scroll耗时平均值，Top节点趋势', '60S', '[平均值] ,间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.scroll_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.search.scroll_total的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:38:05', 1, 0, NULL, 'indices-search-scroll_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (4995, '基本性能指标', 'Merge操作耗时', '节点Merge耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.merges.total_time_in_millis的差值/间隔时间内nodes.{nodeName}.indices.merges.total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:42:21', 1, 0, NULL, 'indices-merges_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (4997, '基本性能指标', 'Refresh操作耗时', '节点Refresh耗时平均值，Top节点趋势', '60S', '[平均值]间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.refresh.total_time_in_millis的差值/间隔时间内nodes.{nodeName}.indices.refresh.total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:42:29', 1, 0, NULL, 'indices-refresh_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (4999, '基本性能指标', 'Flush操作耗时', '节点Flush耗时平均值，Top节点趋势', '60S', '[平均值]间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.flush.total_time_in_millis的差值/间隔时间内nodes.{nodeName}.indices.flush.total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:45:15', 1, 0, NULL, 'indices-flush_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (5000, '基本性能指标', 'request Cache eviction', '节点Request Cache缓存驱逐数，Top节点趋势', '当前值', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.request_cache.evictions的差值/时间间隔(S)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:57:08', 1, 0, NULL, 'indices-request_cache-evictions');\nINSERT INTO `metric_dictionary_info` VALUES (5001, '基本性能指标', 'Write Rejected个数', '节点写入拒绝数，Top节点趋势', '60S', '[平均值]间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.thread_pool.bulk.rejected的差值/时间间隔', 1, '个/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 10:00:54', 1, 0, NULL, 'thread_pool-bulk-rejected');\nINSERT INTO `metric_dictionary_info` VALUES (5003, '基本性能指标', 'Write Queue个数', '节点写入队列堆积数，Top节点趋势', '当前值', '[当前值]  _nodes/stats命令获取nodes.{nodeName}.thread_pool.bulk.queue', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:05:43', 1, 0, NULL, 'thread_pool-bulk-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5005, '基本性能指标', 'Search Queue个数', '节点查询队列堆积数，Top节点趋势', '当前值', '[当前值]  _nodes/stats命令获取nodes.{nodeName}.thread_pool.search.queue', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:45:52', 1, 0, NULL, 'indices-search-query_total');\nINSERT INTO `metric_dictionary_info` VALUES (5007, '基本性能指标', 'Search Rejected个数', '节点查询拒绝数，Top节点趋势', '60S', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.thread_pool.search.rejected的差值/时间间隔(MIN)', 1, '个/MIN', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 10:01:05', 1, 0, NULL, 'thread_pool-search-rejected');\nINSERT INTO `metric_dictionary_info` VALUES (5009, '基本性能指标', 'Merge次数', '节点Merge次数，Top节点趋势', '60S', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.merges.total的差值/时间间隔(MIN)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:46:27', 1, 0, NULL, 'indices-merges-total');\nINSERT INTO `metric_dictionary_info` VALUES (5011, '基本性能指标', 'Refresh次数', '节点Refresh次数，Top节点趋势', '60S', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.refresh.total的差值/时间间隔(MIN)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:46:40', 1, 0, NULL, 'indices-refresh-total');\nINSERT INTO `metric_dictionary_info` VALUES (5013, '基本性能指标', 'Flush次数', '节点Flush次数，Top节点趋势', '60S', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.flush.total的差值/时间间隔(MIN)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:46:56', 1, 0, NULL, 'indices-flush-total');\nINSERT INTO `metric_dictionary_info` VALUES (5015, '基本性能指标', 'Query Cache内存命中率', '节点Query Cache内存命中率，Top节点趋势', '', '[差值] 通过GET _nodes/stats命令获取nodes.{nodeName}.indices.query_cache.hit_count/nodes.{nodeName}.indices.query_cache.total_count', 0, '%', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-28 16:31:04', 1, 0, NULL, 'indices-query_cache-hit_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5017, '基本性能指标', 'Reques Cache内存命中率', '节点Reques Cache内存命中率，Top节点趋势', '', '[差值] 通过GET _nodes/stats命令获取nodes.{nodeName}.indices.request_cache.hit_count/(nodes.{nodeName}.indices.request_cache.hit_count+nodes.{nodeName}.indices.request_cache.miss_count)', 0, '%', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-28 16:31:09', 1, 0, NULL, 'indices-request_cache-hit_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5019, '内存大小指标', 'Query Cache内存大小', '节点所有Shard Query Cache(Cached Filters/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.query_cache.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:22', 1, 0, NULL, 'indices-query_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5021, '内存大小指标', 'Request Cache内存大小', '节点所有Shard Request Cache(Cached Aggregation Results/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.request_cache.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:40', 1, 0, NULL, 'indices-request_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5023, '高级性能指标', '未提交的Translog大小', '节点所有Shard未提交Translog的大小累加值，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.translog.uncommitted_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:47:50', 1, 0, NULL, 'indices-translog-uncommitted_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5025, '高级性能指标', 'Http活跃连接数', '节点的Http活跃连接数，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.http.current_open', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:47:57', 1, 0, NULL, 'http-current_open');\nINSERT INTO `metric_dictionary_info` VALUES (5027, '高级性能指标', 'Segement数 ', '节点所有Shard的Segment汇总数，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.count', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:48:05', 1, 0, NULL, 'indices-segments-count');\nINSERT INTO `metric_dictionary_info` VALUES (5029, '高级性能指标', 'Segement内存大小', '节点所有Shard的Segment底层Lucene内存汇总占用，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.memory_in_bytes', 1, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:48:13', 1, 0, NULL, 'indices-segments-memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5031, '内存大小指标', 'Terms内存大小', '节点所有Shard的Segment底层Terms(Text/Keyword/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.term_vectors_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:53:27', 1, 0, NULL, 'indices-segments-term_vectors_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5033, '内存大小指标', 'Points内存大小', '节点所有Shard的Segment底层Points(Numbers/IPs/Geo/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.points_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:53:41', 1, 0, NULL, 'indices-segments-points_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5035, '内存大小指标', 'Doc Values内存大小', '节点所有Shard的Doc Values内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.doc_values_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:53:57', 1, 0, NULL, 'indices-segments-doc_values_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5037, '内存大小指标', 'Index Writer内存大小', '节点所有Shard的Index Writer内存大小累加值，不在Lucene内存占用统计范围内,Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.index_writer_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:04', 1, 0, NULL, 'indices-segments-index_writer_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5039, '高级性能指标', '文档总数', '节点所有Shard索引文档数累加值，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.docs.count', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:49:31', 1, 0, NULL, 'indices-docs-count');\nINSERT INTO `metric_dictionary_info` VALUES (5041, '高级性能指标', '总存储大小', '节点所有Shard索引存储大小累加值，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.store.size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:49:38', 1, 0, NULL, 'indices-store-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5043, '高级性能指标', '执行任务耗时', '节点执行任务平均耗时，Top节点趋势', '当前值', '[平均值] _cat/tasks?v&detailed&format=json命令根据node筛选并获取running_time的平均值', 0, 'S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:50:50', 1, 0, NULL, 'runningTime');\nINSERT INTO `metric_dictionary_info` VALUES (5045, '高级性能指标', '执行任务数量', '节点执行任务总数量，Top节点趋势', '当前值', '[当前值] _cat/tasks?v&detailed&format=json命令根据node筛选并获取到的集合大小', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:05:00', 1, 0, NULL, 'taskId');\nINSERT INTO `metric_dictionary_info` VALUES (5047, '内存大小指标', 'Stored Fields大小', '节点所有Shard Stored Fields(_source/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.stored_fields_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:50', 1, 0, NULL, 'indices-segments-stored_fields_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5049, '内存大小指标', 'Norms内存大小', '节点所有Shard Norms(normalization factors for query time/text scoring)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取indices.segments.norms_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:59', 1, 0, NULL, 'indices-segments-norms_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5051, '内存大小指标', 'Version Map内存大小', '节点所有Shard Version Map(update/delete)内存大小累加值，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取indices.segments.version_map_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:55:09', 1, 0, NULL, 'indices-segments-version_map_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5053, '内存大小指标', 'Fixed Bitsets内存大小', '节点所有Shard Fixed Bitsets(deeply nested object/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取indices.segments.fixed_bit_set_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:55:20', 1, 0, NULL, 'indices-segments-fixed_bit_set_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5055, '内存大小指标', 'Fielddata内存大小', '节点所有Shard的Fielddata(global ordinals /enable fielddata on text field/...)内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取indices.segments.breakers.fielddata.estimated_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-11-01 09:13:09', 1, 0, NULL, 'breakers-fielddata-estimated_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5057, '高级性能指标', '写入线程池queue数', '节点写入线程池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.write.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-write-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5059, '高级性能指标', '查询线程池queue数', '节点查询线程池池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.search.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-08 18:39:32', 1, 0, NULL, 'thread_pool-search-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5061, '高级性能指标', '刷新线程池queue数', '节点刷新线程池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.refresh.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-refresh-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5063, '高级性能指标', '落盘线程池queue数', '节点落盘线程池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.rollup_indexing.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-rollup_indexing-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5065, '高级性能指标', '管理线程池queue数', '节点管理线程池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.management.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-management-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5067, '高级性能指标', '合并线程池queue数', '节点合并线程池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.force_merge.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-force_merge-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5069, 'JVM指标', 'Young GC次数', '节点Young GC次数，Top节点趋势', '60S', '[平均值]当前时刻减去上一时刻通过GET _nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.young.collection_count的值/时间间隔', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:40', 1, 0, NULL, 'jvm-gc-young-collection_count_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5071, 'JVM指标', 'Old GC次数', '节点Old GC次数，Top节点趋势', '60S', '[平均值]当前时刻减去上一时刻通过GET _nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.old.collection_count的值/时间间隔', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:33', 1, 0, NULL, 'jvm-gc-old-collection_count_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5073, 'JVM指标', 'Young GC耗时', '节点Young GC平均耗时，Top节点趋势', '60S', '[差值]  间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.young.collection_time_in_millis的差值/ 间隔时间内nodes.{nodeName}.jvm.gc.collectors.young.collection_count的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:26', 1, 0, NULL, 'jvm-gc-young-collection_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (5075, 'JVM指标', 'Old GC耗时', '节点Old GC平均耗时，Top节点趋势', '60S', '[差值]  间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.old.collection_time_in_millis的差值/ 间隔时间内nodes.{nodeName}.jvm.gc.collectors.old.collection_count的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:17', 1, 0, NULL, 'jvm-gc-old-collection_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (5077, 'JVM指标', 'JVM堆内存使用量', '节点JVM堆内存使用量，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.heap_used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:52', 1, 0, NULL, 'jvm-mem-heap_used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5079, 'JVM指标', 'JVM堆外存使用量', '节点JVM堆外存使用量，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.non_heap_used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:44', 1, 0, NULL, 'jvm-mem-non_heap_used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5081, 'JVM指标', 'JVM堆使用率', '节点JVM堆使用率，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.heap_used_percent', 1, '%', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:18', 1, 0, NULL, 'jvm-mem-heap_used_percent');\nINSERT INTO `metric_dictionary_info` VALUES (5083, 'JVM指标', '堆内存young区使用空间', '节点年轻代堆内存使用空间，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.pools.young.used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:10', 1, 0, NULL, 'jvm-mem-pools-young-used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5085, 'JVM指标', '堆内存old区使用空间', '节点老年代堆内存使用空间，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.pools.old.used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:03', 1, 0, NULL, 'jvm-mem-pools-old-used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5087, 'breaker指标', 'Field data circuit breaker 内存占用', '统计当前fielddata占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] GET _nodes/stats命令获取breakers.fielddata.limit_size_in_bytes[阈值]，breakers.fielddata.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:16:52', 1, 0, NULL, 'breakers-fielddata-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5089, 'breaker指标', 'Request circuit breaker 内存占用', '统计当前请求(比如聚合请求临时内存构建）占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] GET _nodes/stats命令获取breakers.request.limit_size_in_bytes[阈值]，breakers.request.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:03', 1, 0, NULL, 'breakers-request-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5090, '基本性能指标', 'query Cache evictions', '节点Query Cache缓存驱逐数，Top节点趋势', '当前值', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.query_cache.evictions的差值/时间间隔(S)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:56:51', 1, 0, NULL, 'indices-query_cache-evictions');\nINSERT INTO `metric_dictionary_info` VALUES (5091, 'breaker指标', 'inflight requests circuit breaker 内存占用', '统计当前请求body占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] GET _nodes/stats命令获取breakers.in_flight_requests.limit_size_in_bytes[阈值]，breakers.in_flight_requests.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:04', 1, 0, NULL, 'breakers-in_flight_requests-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5093, 'breaker指标', 'Accounting requests circuit breaker 内存占用', '统计当前请求结束后不能释放的对象(例如segment常驻的内存占用)所占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] GET _nodes/stats命令获取breakers.accounting.limit_size_in_bytes[阈值]，breakers.accounting.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:29', 1, 0, NULL, 'breakers-accounting-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5095, 'breaker指标', 'Script compilation circuit breaker 编译次数', '统计一段时间内脚本编译次数，与阀值比较，超过则熔断请求', '当前值', '[平均值] 当前时刻减去上个时刻通过GET _nodes/stats命令获取script.compilations的数量差值/时间间隔MIN', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-11 14:58:57', 1, 0, NULL, 'script-compilations');\nINSERT INTO `metric_dictionary_info` VALUES (5097, 'breaker指标', 'Parent circuit breaker JVM真实内存占用', '统计JVM真实内存占用，与阀值比较，超过则熔断请求', '当前值', '[当前值] GET _nodes/stats命令获取breakers.parent.limit_size_in_bytes[阈值]，breakers.parent.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:33', 1, 0, NULL, 'breakers-parent-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5099, '索引基础指标', '索引Shard数', '索引Shard个数，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_shards.total', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:16', 1, 0, NULL, 'shardNu');\nINSERT INTO `metric_dictionary_info` VALUES (5101, '索引基础指标', '索引存储大小', '索引存储总大小，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.store.size_in_bytes', 0, 'GB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:16', 1, 0, NULL, 'store-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5103, '索引基础指标', '文档总数', '索引的文档总数，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.docs.count', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, 'docs-count');\nINSERT INTO `metric_dictionary_info` VALUES (5105, '索引性能指标', '写入TPS', '索引写入速率平均值，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.docs.count的差值)/时间间隔(S)', 1, '个/S', '折线', 1, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 09:23:43', 1, 0, NULL, 'indexing-index_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5107, '索引性能指标', '写入耗时', '索引写入耗时平均值，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.indexing.index_time_in_millis的差值)/ 间隔时间内_all.total.indexing.index_total的差值', 1, 'MS', '折线', 1, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 16:55:05', 1, 0, NULL, 'indices-indexing-index_time_per_doc');\nINSERT INTO `metric_dictionary_info` VALUES (5109, '索引性能指标', '网关写入TPS', 'Index通过网关的每秒写入请求数', '60S', '[平均值] (间隔时间内通过查询网关索引获取命中写入条件总数的差值)/时间间隔(S)', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5111, '索引性能指标', '网关写入耗时', 'Index通过网关的写入平均耗时', '60S', '[平均值]  间隔时间内通过查询网关索引获取命中写入条件耗时的平均值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5113, '索引性能指标', '网关查询QPS', 'Index通过网关的每秒查询请求量', '60S', '[平均值] (间隔时间内通过查询网关索引获取命中查询总数的差值)/时间间隔(S)', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5115, '索引性能指标', '网关查询耗时', 'Index通过网关的查询平均耗时', '60S', '[平均值]  间隔时间内通过查询网关索引获取命中查询耗时的平均值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5117, '索引性能指标', '查询Query QPS', '索引Query速率平均值，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.query_total的差值)/时间间隔(S)', 1, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, 'search-query_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5119, '索引性能指标', 'Fetch QPS', '索引Fetch速率平均值，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.fetch_total的差值)/时间间隔(S)', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-11 11:23:19', 1, 0, NULL, 'search-fetch_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5121, '索引性能指标', '查询Query耗时', '索引Query耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.query_time_in_millis的差值/ 间隔时间内_all.total.search.query_total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:14:56', 1, 0, NULL, 'cost-query_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5123, '索引性能指标', '查询Fetch耗时', '索引Fetch耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.fetch_time_in_millis的差值/ 间隔时间内_all.total.search.fetch_total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:15:06', 1, 0, NULL, 'cost-fetch_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5125, '索引性能指标', '查询Scroll量', '索引间隔时间内所有Shard Scroll请求量，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.scroll_total的差值)/时间间隔(S)', 0, '个', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:02', 1, 0, NULL, 'search-scroll_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5127, '索引性能指标', '查询Scroll耗时', '索引Scorll耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.scroll_time_in_millis的差值/ 间隔时间内_all.total.search.scroll_total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:19:31', 1, 0, NULL, 'cost-scroll_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5129, '索引性能指标', 'Merge耗时', '索引Merge耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.merges.total_time_in_millis的差值/ 间隔时间内_all.total.merges.total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:17:24', 1, 0, NULL, 'cost-merges-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5131, '索引性能指标', 'Refresh耗时', '索引Refresh耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.refresh.total_time_in_millis的差值/ 间隔时间内_all.total.refresh.total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:17:39', 1, 0, NULL, 'cost-refresh-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5133, '索引性能指标', 'Flush耗时', '索引Flush耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.indices.flush.total_time_in_millis的差值/ 间隔时间内_all.total.indices.flush.total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:18:08', 1, 0, NULL, 'cost-flush-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5135, '索引性能指标', 'Merge次数', '索引Merge次数，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.merges.total的差值)/时间间隔(MIN)', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:02', 1, 0, NULL, 'merges-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5137, '索引性能指标', 'Refresh次数', '索引Refresh次数，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.refresh.total的差值)/时间间隔(MIN)', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:02', 1, 0, NULL, 'refresh-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5139, '索引性能指标', 'Flush次数', '索引Flush次数，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取flush.total的差值)/时间间隔(MIN)', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:03', 1, 0, NULL, 'flush-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5141, '索引内存指标', 'Segements大小', '索引所有Shard的Segment底层Lucene内存汇总占用，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.segments.memory_in_bytes', 1, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:13:35', 1, 0, NULL, 'segments-memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5143, '索引内存指标', 'Terms内存大小', '索引所有Shard的Segment底层Terms(Text/Keyword/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.segments.term_vectors_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:13:40', 1, 0, NULL, 'segments-term_vectors_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5145, '索引内存指标', 'Points内存大小', '索引所有Shard的Segment底层Points(Numbers/IPs/Geo/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.segments.points_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:14:44', 1, 0, NULL, 'segments-points_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5147, '索引内存指标', 'Doc Values内存大小', '索引所有Shard的Doc Values内存大小，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.segments.doc_values_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:15:01', 1, 0, NULL, 'segments-doc_values_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5149, '索引内存指标', 'Index Writer内存大小', '索引所有Shard的Index Writer内存大小，不在Lucene内存占用统计范围内,Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.segments.index_writer_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:15:06', 1, 0, NULL, 'segments-index_writer_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5151, '索引内存指标', '未提交的Translog大小', '索引所有Shard的未提交Translog的大小累加值，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.translog.uncommitted_size_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:15:10', 1, 0, NULL, 'translog-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5153, '索引内存指标', 'Query Cache内存大小', '索引所有Shard Query Cache(Cached Filters/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.query_cache.memory_size_in_bytes', 1, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:35', 1, 0, NULL, 'query_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5155, '索引内存指标', 'Stored Fields大小', '索引stored_fields_memory内存大小', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.segments.stored_fields_memory_in_bytes', 0, 'MB', NULL, 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:40', 1, 0, NULL, 'segments-stored_fields_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5157, '索引内存指标', 'Norms内存大小', '索引所有Shard Norms(normalization factors for query time/text scoring)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.segments.norms_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:42', 1, 0, NULL, 'segments-norms_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5159, '索引内存指标', 'Version Map内存大小', '索引所有Shard Version Map(update/delete)内存大小累加值，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.segments.version_map_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:45', 1, 0, NULL, 'segments-version_map_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5161, '索引内存指标', 'Fixed Bitsets内存大小', '索引所有Shard Fixed Bitsets(deeply nested object/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.segments.fixed_bit_set_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:49', 1, 0, NULL, 'segments-fixed_bit_set_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5163, '索引内存指标', 'Fielddata内存大小', '索引所有Shard Fielddata(global ordinals /enable fielddata on text field/...)内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.fielddata.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:54', 1, 0, NULL, 'fielddata-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5165, '索引内存指标', 'Request Cache内存大小', '索引所有Shard Request Cache(Cached Aggregation Results/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.request_cache.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:58', 1, 0, NULL, 'segments-request_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5167, '索引模板基础指标', '索引Shard数', '索引模板下索引Shard个数，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取shards数量之和', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:05', 1, 0, NULL, 'shardNu');\nINSERT INTO `metric_dictionary_info` VALUES (5169, '索引模板基础指标', '索引存储大小', '索引模板下索引Shard存储总大小，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.store.size_in_bytes之和', 0, 'GB', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-27 11:15:43', 1, 0, NULL, 'store-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5171, '索引模板基础指标', '文档总数', '索引模板下索引的文档数，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.docs.count之和', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-27 11:15:48', 1, 0, NULL, 'docs-count');\nINSERT INTO `metric_dictionary_info` VALUES (5173, '索引模板性能指标', '写入TPS', '索引模板写入速率平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.docs.count的差值累加值/间隔时间', 1, '个/S', '折线', 1, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-27 11:15:53', 1, 0, NULL, 'indexing-index_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5175, '索引模板性能指标', '写入耗时', '索引模板写入耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过GET {indexName}/_stats?level=shards命令获取_all.total.indexing.index_time_in_millis的差值)/ 间隔时间内_all.total.indexing.index_total的差值', 1, 'MS', '折线', 1, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 16:58:37', 1, 0, NULL, 'indices-indexing-index_time_per_doc');\nINSERT INTO `metric_dictionary_info` VALUES (5177, '索引模板性能指标', '查询Query QPS', '索引模板Query速率平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过{indexName}/_stats?level=shards命令获取 all.total.search.query_total的差值累加值/间隔时间', 1, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-27 11:16:07', 1, 0, NULL, 'search-query_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5179, '索引模板性能指标', '网关写入TPS', 'IndexTemplate所属Index通过网关的每秒写入请求数', '60S', NULL, 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5181, '索引模板性能指标', '网关写入耗时', 'IndexTemplate所属Index通过网关的写入平均耗时', '60S', NULL, 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5183, '索引模板性能指标', '网关查询QPS', 'IndexTemplate所属Index通过网关的每秒查询请求量', '60S', NULL, 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5185, '索引模板性能指标', '网关查询耗时', 'IndexTemplate所属Index通过网关的查询平均耗时', '60S', NULL, 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:07', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5187, '索引模板性能指标', '查询Fetch QPS', '索引模板Fetch速率平均值，Top节点趋势', '60S', '[平均值]  间隔时间内获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.search.fetch_total的差值累加值/时间间隔', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:58:35', 1, 0, NULL, 'search-fetch_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5189, '索引模板性能指标', '查询Query耗时', '索引模板Query耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过{indexName}/_stats?level=shards命令_all.total.search.query_time_in_millis的差值累加值/_all.total.search.query_total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:57:12', 1, 0, NULL, 'cost-query_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5191, '索引模板性能指标', '查询Fetch耗时', '索引模板Fetch耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.search.fetch_time_in_millis的差值累加值/_all.total.search.fetch_total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:59:22', 1, 0, NULL, 'cost-fetch_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5193, '索引模板性能指标', '查询Scroll量', '索引模板下索引Shard 级别 Scroll请求量，Top节点趋势', '60S', '[平均值] 获取间隔时间内模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.search.scroll_total的差值累加值/时间间隔', 0, '个', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:44:38', 1, 0, NULL, 'search-scroll_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5195, '索引模板性能指标', '查询Scroll耗时', '索引模板Scorll耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.search.scroll_time_in_millis的差值累加值/_all.total.search.scroll_total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-30 11:19:09', 1, 0, NULL, 'cost-scroll_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5197, '索引模板性能指标', 'Merge耗时', '索引模板Merge耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.merges.total_time_in_millis的差值累加值/_all.total.merges.total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:08', 1, 0, NULL, 'cost-merges-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5199, '索引模板性能指标', 'Refresh耗时', '索引模板Refresh耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.refresh.total_time_in_millis的差值累加值/_all.total.refresh.total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, 'cost-refresh-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5201, '索引模板性能指标', 'Flush耗时', '索引模板Flush耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.flush.total_time_in_millis的差值累加值/all.total.flush.total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, 'cost-flush-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5203, '索引模板性能指标', 'Merge次数', '索引模板Merge次数，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.merges.total的差值累加值/时间间隔', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:59:59', 1, 0, NULL, 'merges-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5205, '索引模板性能指标', 'Refresh次数', '索引模板Refresh次数，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.refresh.total的差值累加值/时间间隔', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:57:58', 1, 0, NULL, 'refresh-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5207, '索引模板性能指标', 'Flush次数', '索引模板Flush次数，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.flush-total_rate的累加值差值/时间间隔', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'flush-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5209, '索引模板内存指标', 'Segements大小', '索引模板下索引所有Shard的Segment底层Lucene内存汇总占用，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.memory_in_bytes的总和', 1, 'MB', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'segments-memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5211, '索引模板内存指标', 'Terms内存大小', '索引模板下索引所有Shard的Segment底层Terms(Text/Keyword/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.term_vectors_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'segments-term_vectors_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5213, '索引模板内存指标', 'Points内存大小', '索引模板下索引所有Shard的Segment底层Points(Numbers/IPs/Geo/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.points_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'segments-points_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5215, '索引模板内存指标', 'Doc Values内存大小', '索引模板下索引所有Shard的Doc Values内存大小，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.doc_values_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'segments-doc_values_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5217, '索引模板内存指标', 'Index Writer内存大小', '索引模板下索引所有Shard的Index Writer内存大小，不在Lucene内存占用统计范围内,Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.index_writer_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'segments-index_writer_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5219, '索引模板内存指标', '未提交的Translog大小', '索引模板下索引所有Shard的未提交Translog的大小累加值，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.translog.uncommitted_size_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'translog-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5221, '索引模板内存指标', 'Query Cache内存大小', '索引模板下索引所有Shard Query Cache(Cached Filters/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.query_cache.memory_size_in_bytes的总和', 1, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'query_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5223, '索引模板内存指标', 'Stored Fields大小', '索引模板下索引stored_fields_memory内存大小', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.stored_fields_memory_in_bytes的总和', 0, NULL, NULL, 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:12', 1, 0, NULL, 'segments-stored_fields_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5225, '索引模板内存指标', 'Norms内存大小', '索引模板下索引所有Shard Norms(normalization factors for query time/text scoring)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments-norms_memory_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 19:22:53', 1, 0, NULL, 'segments-norms_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5227, '索引模板内存指标', 'Version Map内存大小', '索引模板下索引所有Shard Version Map(update/delete)内存大小累加值，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.version_map_memory_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 19:23:20', 1, 0, NULL, 'segments-version_map_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5229, '索引模板内存指标', 'Fixed Bitsets内存大小', '索引模板下索引所有Shard Fixed Bitsets(deeply nested object/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.fixed_bit_set_memory_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 19:23:39', 1, 0, NULL, 'segments-fixed_bit_set_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5231, '索引模板内存指标', 'Fielddata内存大小', '索引模板下索引所有Shard Fielddata(global ordinals /enable fielddata on text field/...)内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.fielddata.memory_size_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 19:23:49', 1, 0, NULL, 'fielddata-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5233, '索引模板内存指标', 'Request Cache内存大小', '索引模板下索引所有Shard Request Cache(Cached Aggregation Results/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.request_cache.memory_size_in_bytes的总和', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 19:20:19', 1, 0, NULL, 'segments-request_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5235, '集群', '集群健康状态', '不同健康状态集群分布感知，快速定位故障集群', '当前值', '[当前值] 通过GET _cluster/health命令获取status', 0, NULL, '状态栏', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 15:18:40', 1, 0, NULL, 'health');\nINSERT INTO `metric_dictionary_info` VALUES (5237, '集群', '指标采集延时', '指标数据质量风险集群预警', '当前值', '[当前值] 采集数据最近一个时间点和当前时间点的差值', 0, 'S', '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:01', 1, 0, NULL, 'clusterElapsedTimeGte5Min');\nINSERT INTO `metric_dictionary_info` VALUES (5239, '集群', 'shard个数大于10000集群', 'Shard膨胀风险集群预警', '当前值', '[当前值] 通过GET _cat/health?format=json获取shards总数量(包括unassign状态)', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-10 15:49:42', 1, 0, NULL, 'shardNum');\nINSERT INTO `metric_dictionary_info` VALUES (5241, '集群', '写入耗时', '索引写入性能对比分析，性能不足集群预警', '5*60S', '[最大值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.indexing.index_total差值累加值', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-11-02 19:51:22', 1, 0, NULL, 'indexingLatency');\nINSERT INTO `metric_dictionary_info` VALUES (5243, '集群', 'node_stats接口平均采集耗时', 'Master指标采集性能问题集群预警', '当前值', '[当前值] 调用一次_nodes/stats命令所消耗的时间', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-10 15:50:23', 1, 0, NULL, 'nodeElapsedTime');\nINSERT INTO `metric_dictionary_info` VALUES (5245, '集群', '集群pending task数', 'pending task持续堆积，Master元数据处理性能问题集群预警', '当前值', '[当前值] 通过 _cluster/health命令获取number_of_pending_tasks', 0, '个', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:23', 1, 0, NULL, 'pendingTaskNum');\nINSERT INTO `metric_dictionary_info` VALUES (5247, '集群', '网关失败率', '各组网关业务查询健康预警', '5*60S', '5分钟执行一次，获取近一分钟内的网关失败率', 0, '%', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:26', 1, 0, NULL, 'gatewayFailedPer');\nINSERT INTO `metric_dictionary_info` VALUES (5249, '集群', '查询耗时', '索引查询性能对比分析，查询性能不足集群预警', '5*60S', '[最大值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.search.query_total差值累加值', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-11-02 19:51:08', 1, 0, NULL, 'searchLatency');\nINSERT INTO `metric_dictionary_info` VALUES (5251, '节点', '节点执行任务耗时', '节点执行任务平均耗时高', '5*60S', '[平均值]根据_cat/tasks?v&detailed&format=json命令获取到当前时间的各节点任务执行总和/节点执行的次数', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:56', 1, 0, NULL, 'taskConsuming');\nINSERT INTO `metric_dictionary_info` VALUES (5253, '节点', '磁盘利用率超红线节点', '磁盘利用率超安全水位节点预警', '当前值', '[当前值]根据GET _nodes/stats命令获取到(nodes.{nodeName}.fs.total-nodes.{nodeName}.fs.free_in_bytes)/nodes.{nodeName}.fs.total大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:34', 1, 0, NULL, 'largeDiskUsage');\nINSERT INTO `metric_dictionary_info` VALUES (5255, '节点', '分片个数大于500节点', '分片数超安全水位节点预警', '当前值', '[当前值]根据_cat/shards?v&h=node命令获取到结果个数大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:55:51', 1, 0, NULL, 'shardNum');\nINSERT INTO `metric_dictionary_info` VALUES (5257, '节点', '堆内存利用率超红线节点', '堆内存利用率超红线节点预警', '当前值', '[当前值]根据GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.heap_used_percent大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:28', 1, 0, NULL, 'largeHead');\nINSERT INTO `metric_dictionary_info` VALUES (5259, '节点', 'CPU利用率超红线节点', 'CPU利用率超红线节点预警', '当前值', '[当前值]根据GET _nodes/stats命令获取到nodes.{nodeName}.os.cpu.percent大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:32', 1, 0, NULL, 'largeCpuUsage');\nINSERT INTO `metric_dictionary_info` VALUES (5261, '节点', 'SearchRejected节点', 'SearchRejected节点预警', '5*60S', '[当前值]当前时间和上次时间通过GET _nodes/stats命令nodes.{nodeName}.thread_pool.search.rejected差值不为0的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:41', 1, 0, NULL, 'searchRejectedNum');\nINSERT INTO `metric_dictionary_info` VALUES (5263, '节点', 'WriteRejected节点', 'WriteRejected节点预警', '5*60S', '[当前值]当前时间和上次时间通过GET _nodes/stats命令nodes.{nodeName}.thread_pool.write.rejected差值不为0的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:43', 1, 0, NULL, 'writeRejectedNum');\nINSERT INTO `metric_dictionary_info` VALUES (5265, '索引', 'segments内存大于1MB索引模板', '索引模板超大内存占用风险预警', '当前值', '[当前值]根据_cat/segments/命令获取size字段大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:59:56', 1, 1, 'segments内存大于1MB索引模板', 'tplSegmentMemSize');\nINSERT INTO `metric_dictionary_info` VALUES (5267, '索引', 'segments个数大于20索引模板', '索引模板Segements数超红线预警', '当前值', '[当前值]根据_cat/segments/命令获取segment个数大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:59:58', 1, 0, NULL, 'tplSegmentNum');\nINSERT INTO `metric_dictionary_info` VALUES (5269, '索引', '未分配shard索引', 'shard未分配索引预警', '当前值', '[当前值]根据GET {indexName}/_stats命令获取索引状态不等于green的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:09', 1, 0, NULL, 'unassignedShard');\nINSERT INTO `metric_dictionary_info` VALUES (5271, '索引', 'mapping字段个数大于100索引', '索引mapping字段膨胀预警', '当前值', '[当前值]根据GET {indexName}命令mapping的字段个数大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:13', 1, 0, NULL, 'mappingNum');\nINSERT INTO `metric_dictionary_info` VALUES (5273, '索引', 'segments内存大于100B索引', '索引超大内存占用风险预警', '当前值', '[当前值]根据_cat/segments/命令获取segment内存（size）大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:20', 1, 0, NULL, 'segmentMemSize');\nINSERT INTO `metric_dictionary_info` VALUES (5275, '索引', 'segments个数大于100索引', '索引Segements数超红线预警', '当前值', '[当前值]根据_cat/segments/命令获取segment个数大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:24', 1, 0, NULL, 'segmentNum');\nINSERT INTO `metric_dictionary_info` VALUES (5277, '索引', 'RED索引', 'RED索引预警', '当前值', '[当前值]根据_cat/indices?format=json命令获取健康状态(health)等于red的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:59', 1, 0, NULL, 'red');\nINSERT INTO `metric_dictionary_info` VALUES (5279, '索引', '单个shard大于500MB索引', '单Shard过大索引预警', '当前值', '[当前值]根据_cat/shards命令获取大小大于指定的阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:57:51', 1, 0, NULL, 'bigShard');\nINSERT INTO `metric_dictionary_info` VALUES (5281, '索引', '无副本索引', '无副本索引稳定性预警', '当前值', '[当前值]根据_cat/indices命令获取副本数等于0的索引', 0, NULL, '列表', 0, NULL, NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:25:12', 1, 0, NULL, 'singReplicate');\nINSERT INTO `metric_dictionary_info` VALUES (5283, '索引', '单个shard小于500MB索引', '索引Shard数分配不合理预警', '当前值', '[当前值]根据_cat/shards命令获取大小(store)小于指定的阀值并且shard数量大于1的索引', 0, NULL, '列表', 0, NULL, NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:58:06', 1, 0, NULL, 'smallShard');\n\n\n\n#重新全量导入权限点表\ntruncate table logi_security_permission;\ninsert into logi_security_permission (id, permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name)\nvalues  (1593, '物理集群', 0, 0, 1, '物理集群', '2022-05-24 18:08:22.0', '2022-08-24 20:07:31.0', 0, 'know_search'),\n        (1595, '我的集群', 0, 0, 1, '我的集群', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1597, '集群版本', 0, 0, 1, '集群版本', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1599, 'Gateway管理', 0, 0, 1, 'Gateway管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1601, '模板管理', 0, 0, 1, '模板管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1603, '模板服务', 0, 0, 1, '模板服务', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1605, '索引管理', 0, 0, 1, '索引管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1607, '索引服务', 0, 0, 1, '索引服务', '2022-05-24 18:08:22.0', '2022-05-24 18:24:16.0', 0, 'know_search'),\n        (1609, '索引查询', 0, 0, 1, '索引查询', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1611, '查询诊断', 0, 0, 1, '查询诊断', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1613, '集群看板', 0, 0, 1, '集群看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1615, '网关看板', 0, 0, 1, '网关看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1617, '我的申请', 0, 0, 1, '我的申请', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1619, '我的审批', 0, 0, 1, '我的审批', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1621, '任务列表', 0, 0, 1, '任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1623, '调度任务列表', 0, 0, 1, '调度任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1625, '调度日志', 0, 0, 1, '调度日志', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1627, '用户管理', 0, 0, 1, '用户管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1629, '角色管理', 0, 0, 1, '角色管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1631, '应用管理', 0, 0, 1, '应用管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1633, '平台配置', 0, 0, 1, '平台配置', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1635, '操作记录', 0, 0, 1, '操作记录', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1637, '查看集群列表及详情', 1593, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1639, '接入集群', 1593, 1, 2, '接入集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1641, '新建集群', 1593, 1, 2, '新建集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1643, '扩缩容', 1593, 1, 2, '扩缩容', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1645, '升级', 1593, 1, 2, '升级', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1647, '重启', 1593, 1, 2, '重启', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1649, '配置变更', 1593, 1, 2, '配置变更', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1651, 'Region划分', 1593, 1, 2, 'Region划分', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1653, 'Region管理', 1593, 1, 2, 'Region管理', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1655, '快捷命令', 1593, 1, 2, '快捷命令', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1657, '编辑', 1593, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1659, '绑定Gateway', 1593, 1, 2, '绑定Gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1661, '下线', 1593, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1663, '查看集群列表及详情', 1595, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1665, '申请集群', 1595, 1, 2, '申请集群', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1667, '编辑', 1595, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1669, '扩缩容', 1595, 1, 2, '扩缩容', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1671, '下线', 1595, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1673, '查看版本列表', 1597, 1, 2, '查看版本列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1675, '新增版本', 1597, 1, 2, '新增版本', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1677, '编辑', 1597, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1679, '删除', 1597, 1, 2, '删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1681, '查看Gateway 集群列表', 1599, 1, 2, '查看Gateway 集群列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1683, '接入gateway', 1599, 1, 2, '接入gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1685, '编辑', 1599, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1687, '下线', 1599, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1689, '查看模板列表及详情', 1601, 1, 2, '查看模板列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1691, '申请模板', 1601, 1, 2, '申请模板', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1693, '编辑', 1601, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1695, '下线', 1601, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1697, '编辑Mapping', 1601, 1, 2, '编辑Mapping', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1699, '编辑Setting', 1601, 1, 2, '编辑Setting', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1701, '查看模板列表', 1603, 1, 2, '查看模板列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1703, '开关：预创建', 1603, 1, 2, '开关：预创建', '2022-05-24 18:08:23.0', '2022-06-14 16:49:48.0', 0, 'know_search'),\n        (1705, '开关：过期删除', 1603, 1, 2, '开关：过期删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1707, '开关：冷热分离', 1603, 1, 2, '开关：冷热分离', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1709, '开关：pipeline', 1603, 1, 2, '开关：写入限流', '2022-05-24 18:08:23.0', '2022-06-14 16:49:49.0', 0, 'know_search'),\n        (1711, '开关：Rollover', 1603, 1, 2, '开关：Rollover', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1713, '查看DCDR链路', 1603, 1, 2, '查看DCDR链路', '2022-05-24 18:08:23.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1715, '创建DCDR链路', 1603, 1, 2, '创建DCDR链路', '2022-05-24 18:08:24.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1717, '清理', 1603, 1, 2, '清理', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1719, '扩缩容', 1603, 1, 2, '扩缩容', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1721, '升版本', 1603, 1, 2, '升版本', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1723, '批量操作', 1603, 1, 2, '批量操作', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1725, '查看索引列表及详情', 1605, 1, 2, '查看索引列表及详情', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1727, '编辑Mapping', 1605, 1, 2, '编辑Mapping', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1729, '编辑Setting', 1605, 1, 2, '编辑Setting', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1731, '禁用读', 1607, 1, 2, '禁用读', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1733, '禁用写', 1607, 1, 2, '禁用写', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1735, '设置别名', 1605, 1, 2, '设置别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1737, '删除别名', 1605, 1, 2, '删除别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1739, '关闭索引', 1607, 1, 2, '关闭索引', '2022-05-24 18:08:24.0', '2022-07-15 09:52:25.0', 0, 'know_search'),\n        (1741, '下线', 1605, 1, 2, '下线', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1743, '批量删除', 1605, 1, 2, '批量删除', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1745, '查看列表', 1607, 1, 2, '查看列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1747, '执行Rollover', 1607, 1, 2, '执行Rollover', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1749, '执行shrink', 1607, 1, 2, '执行shrink', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1751, '执行split', 1607, 1, 2, '执行split', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1753, '执行ForceMerge', 1607, 1, 2, '执行ForceMerge', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1755, '批量执行', 1607, 1, 2, '批量执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1757, 'DSL查询', 1877, 1, 2, 'DSL查询', '2022-05-24 18:08:24.0', '2022-09-05 14:24:00.0', 0, 'know_search'),\n        (1759, '查询模板', 0, 0, 1, '查看查询模板列表', '2022-05-24 18:08:24.0', '2022-08-11 10:37:43.0', 0, 'know_search'),\n        (1761, '查看集群看板', 1613, 1, 2, '查看集群看板', '2022-05-24 18:08:24.0', '2022-06-14 16:37:54.0', 0, 'know_search'),\n        (1763, '查看网关看板', 1615, 1, 2, '查看网关看板', '2022-05-24 18:08:24.0', '2022-06-14 16:38:14.0', 0, 'know_search'),\n        (1765, '查看我的申请列表', 1617, 1, 2, '查看我的申请列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1767, '撤回', 1617, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1769, '查看我的审批列表', 1619, 1, 2, '查看我的审批列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1771, '驳回', 1619, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-07-18 20:57:33.0', 0, 'know_search'),\n        (1773, '通过', 1619, 1, 2, '通过', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1775, '查看任务列表', 1621, 1, 2, '查看任务列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1777, '查看进度', 1621, 1, 2, '查看进度', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1779, '执行', 1621, 1, 2, '执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1781, '暂停', 1621, 1, 2, '暂停', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1783, '重试', 1621, 1, 2, '重试', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1785, '取消', 1621, 1, 2, '取消', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1787, '查看日志（子任务）', 1621, 1, 2, '查看日志（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1789, '重试（子任务）', 1621, 1, 2, '重试（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1791, '忽略（子任务）', 1621, 1, 2, '忽略（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1793, '查看详情（DCDR）', 1621, 1, 2, '查看详情（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1795, '取消（DCDR）', 1621, 1, 2, '取消（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1797, '重试（DCDR）', 1621, 1, 2, '重试（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1799, '强切（DCDR）', 1621, 1, 2, '强切（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1801, '返回（DCDR）', 1621, 1, 2, '返回（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1803, '查看任务列表', 1623, 1, 2, '查看任务列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1805, '查看日志', 1623, 1, 2, '查看日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1807, '执行', 1623, 1, 2, '执行', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1809, '暂停', 1623, 1, 2, '暂停', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1811, '查看调度日志列表', 1625, 1, 2, '查看调度日志列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1813, '调度详情', 1625, 1, 2, '调度详情', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1815, '执行日志', 1625, 1, 2, '执行日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1817, '终止任务', 1625, 1, 2, '终止任务', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1819, '查看用户列表', 1627, 1, 2, '查看用户列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1821, '分配角色', 1627, 1, 2, '分配角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1823, '查看角色列表', 1629, 1, 2, '查看角色列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1825, '编辑', 1629, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1827, '绑定用户', 1629, 1, 2, '绑定用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1829, '回收用户', 1629, 1, 2, '回收用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1831, '删除角色', 1629, 1, 2, '删除角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1833, '查看应用列表', 1631, 1, 2, '查看应用列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1835, '新建应用', 1631, 1, 2, '新建应用', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1837, '编辑', 1631, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1839, '删除', 1631, 1, 2, '删除', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1841, '访问设置', 1631, 1, 2, '访问设置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1843, '查看平台配置列表', 1633, 1, 2, '查看平台配置列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1845, '新增平台配置', 1633, 1, 2, '新增平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1847, '禁用平台配置', 1633, 1, 2, '禁用平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1849, '编辑平台配置', 1633, 1, 2, '编辑平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1851, '删除平台配置', 1633, 1, 2, '删除平台配置', '2022-05-24 18:08:26.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1853, '查看操作记录列表', 1635, 1, 2, '查看操作记录列表', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1855, 'Kibana查询', 1879, 1, 2, 'Kibana查询', '2022-05-24 18:08:26.0', '2022-09-05 14:24:00.0', 0, 'know_search'),\n        (1857, 'SQL查询', 1881, 1, 2, 'SQL查询', '2022-05-24 18:08:26.0', '2022-09-05 14:24:00.0', 0, 'know_search'),\n        (1859, '批量修改限流值', 1759, 1, 2, '批量修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1861, '禁用', 1759, 1, 2, '禁用', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1863, '修改限流值', 1759, 1, 2, '修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1865, '查看异常查询列表', 1611, 1, 2, '查看异常查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1867, '查看慢查询列表', 1611, 1, 2, '查看慢查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:21.0', 0, 'know_search'),\n        (1869, '新增角色', 1629, 1, 2, '新增角色', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1871, 'Dashboard', 0, 0, 1, '查看dashboard', '2022-05-24 18:08:26.0', '2022-08-27 17:35:50.0', 0, 'know_search'),\n        (1873, '新建索引', 1605, 1, 2, '新建索引', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1875, '查看dashboard', 1871, 1, 2, '查看dashboard', '2022-05-24 18:08:24.0', '2022-08-27 17:35:50.0', 0, 'know_search'),\n        (1877, 'DSL', 0, 0, 1, 'DSL', '2022-05-24 18:08:24.0', '2022-09-02 19:01:17.0', 0, 'know_search'),\n        (1879, 'Kibana', 0, 0, 1, 'Kibana', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search'),\n        (1881, 'SQL', 0, 0, 1, 'SQL', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search');\n\nalter table logi_security_oplog\n    modify target varchar(225) not null comment '操作对象';"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/init_knowsearch_linux.sh",
    "content": "#!/bin/bash\n#需要变更一些地址\nurl_prefix='http://127.0.0.1:8015/admin/api'\ndata=\".\"\n#元数据项目，默认不变\nsubject=2\n#接入物理集群并创建逻辑集群的接口\nput_cluster_url='/v3/thirdpart/common/cluster/join-with-logic'\nheader=\"-H  'X-SSO-USER: admin'  -H 'X-LOGI-SECURITY-PROJECT-ID: 1'  -H 'X-SSO-USER-ID: 1593'  -H 'Content-Type:application/json' \"\nheader_subject=\"-H  'X-SSO-USER: admin'  -H 'X-LOGI-SECURITY-PROJECT-ID: $subject'  -H 'X-SSO-USER-ID: 1593'  -H 'Content-Type:application/json' \"\n#逻辑集群id\nlogic_cluster_id=0\nrun_join_cluster(){\n data_path=`dirname $0`\n url=$url_prefix$put_cluster_url\n data=`cat $data_path/cluster-phy-join`\n join_cluster=\"curl -s $header  -XPOST $url -d '$data'\"\n response=`eval $join_cluster`\n echo \"response $response\"\n logic_cluster_id=`echo $response | awk -F 'data\":' '{print $NF}'|awk -F \",\" '{print $1}'`\n echo \"logic_cluster_id $logic_cluster_id\" >> /vat/log/install_knowsearch.log\n}\n\n\n\ncreate_logic_template(){\n  num_exec='echo \"$logic_cluster_id\" | sed -n \"/^[0-9]\\+$/p\" '\n  num=`eval $num_exec`\n  if [ ! -n \"$num\" ]; then\n        echo '逻辑集群id未获取到' >> /vat/log/install_knowsearch.log\n        exit\n  fi\n\n  echo $logic_cluster_id\n  data_path=`dirname $0`\n  for i in `ls $data_path/template_in_arius/*`\n  do\n    create_logic_template_exec=\"cat $i| sed 's/#resourceId/$logic_cluster_id/g'\"\n    create_logic_template_data=`eval eval $create_logic_template_exec`\n    url=$url_prefix/v3/template/logic\n    create_logic_template_exec=\"curl -s  $header_subject  -XPOST $url -d '$create_logic_template_data'\"\n    result=`eval $create_logic_template_exec`\n    echo \"Create template results : $result ....\" >> /vat/log/install_knowsearch.log\n  done\n}\n\nperform_run_task(){\n  task_url=$url_prefix/v1/logi-job/task/list\n  data=`cat $data_path/task`\n  echo $data >> /vat/log/install_knowsearch.log\n\tget_task_date=\"curl -s $header  -XPOST $task_url -d '$data'\"\n\tresponse=`eval $get_task_date`\n\ttaskCode=`echo $response |  grep  -E 'taskCode\":\"\\d+\"' -o| grep -E \"\\d+\" -o`\n\ttaskCode_url=$url_prefix/v1/logi-job/task/$taskCode/do\n\techo $taskCode_url >> /vat/log/install_knowsearch.log\n\ttaskCode_url_run=\"curl -s $header  -XPOST $taskCode_url -d '{}'\"\n\tresult=`eval $taskCode_url_run`\n\techo $result >> /vat/log/install_knowsearch.log\n\n}\n\nurl_status=$(curl -s -m 5 -IL $url_prefix/health  |grep 200)\nif [\"$url_status\" == \"\"];then\n\techo \"服务异常，无法执行脚本\" >> /vat/log/install_knowsearch.log\n\texit\nfi\n#接入物理集群\nrun_join_cluster\n\n\n#创建元数据模版\ncreate_logic_template\n#执行定时任务\nperform_run_task\nsleep 10\n\necho \"请重启admin工程\""
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/task",
    "content": "{\"taskDesc\":\"明天索引预先创建任务，预先创建平台中模板明天索引，避免凌晨大规模创建索引\",\"page\":1,\"size\":1}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius.appid.template.access",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.appid.template.access\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": -1,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"\\nappid 维度访问次数索引 \\n\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"date\\\":{\\\"format\\\":\\\"strict_date_optional_time||yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||yyyy-MM-dd||yyyyMMdd||yyyyMM||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"accessDetailInfo\\\":{\\\"dynamic\\\":\\\"false\\\",\\\"type\\\":\\\"object\\\"},\\\"templateName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"clusterName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"logicTemplateId\\\":{\\\"type\\\":\\\"long\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius.dsl.analyze.result",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.dsl.analyze.result\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": 3,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"DSL分析结果\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"date\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis||yyyy-MM-dd\\\",\\\"type\\\":\\\"date\\\"},\\\"overview\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"costQuantile\\\":{\\\"properties\\\":{\\\"50_0\\\":{\\\"type\\\":\\\"float\\\"},\\\"75_0\\\":{\\\"type\\\":\\\"float\\\"},\\\"95_0\\\":{\\\"type\\\":\\\"float\\\"},\\\"99_0\\\":{\\\"type\\\":\\\"float\\\"}}},\\\"qpsMetric\\\":{\\\"properties\\\":{\\\"minQpsTime\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"},\\\"avgQps\\\":{\\\"type\\\":\\\"long\\\"},\\\"maxQpsTime\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"},\\\"minQps\\\":{\\\"type\\\":\\\"long\\\"},\\\"maxQps\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"count\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"errorDsls\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"details\\\":{\\\"properties\\\":{\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"name\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"details\\\":{\\\"properties\\\":{\\\"dslTemplate\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"indices\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"dslTemplateMd5\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"}}}}}}},\\\"dslTotalCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"slowDsls\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"details\\\":{\\\"properties\\\":{\\\"dslTemplate\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"indices\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"cost\\\":{\\\"type\\\":\\\"float\\\"},\\\"dslTemplateMd5\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"cause\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"slowDslThreshold\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"slowReasonType\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"}}}}},\\\"errDetailInfo\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"slowSearchCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"errSearchCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis||yyyy-MM-dd\\\",\\\"type\\\":\\\"date\\\"},\\\"dslTemplates\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"dslTotalCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslIncCnt\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"searchTotalCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"accessGatewayInfo\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"ariusType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslIncCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"day\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis||yyyy-MM-dd\\\",\\\"type\\\":\\\"date\\\"}}}\",\n  \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius.dsl.metrics",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.dsl.metrics\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timeStamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"用户查询聚合信息\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"ariusCreateTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"projectIdDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"searchCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslLevel\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"successfulShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTemplate\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"dslType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appidDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"responseLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"requestType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"searchType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"esCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"gatewayNode\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"dslLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalHitsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"version\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"indiceSample\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indices\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"dslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"isFromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"totalCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"failedShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"long\\\"},\\\"beforeCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius.dsl.template",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.dsl.template\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": -1,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"DSL 审核与分析\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"ariusCreateTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"projectIdDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"fromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"searchCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslLevel\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"my_all_fields\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"successfulShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTemplate\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"ignore_above\\\":32766,\\\"type\\\":\\\"keyword\\\"},\\\"dslType\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"appidDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"enable\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"sinkTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"day\\\":{\\\"type\\\":\\\"date\\\"},\\\"responseLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"requestType\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"searchType\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"ariusModifyTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"slowDslThreshold\\\":{\\\"type\\\":\\\"long\\\"},\\\"esCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"gatewayNode\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"totalHitsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"version\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"forceSetQueryLimit\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"boolean\\\"},\\\"indiceSample\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indices\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"ignore_above\\\":32766,\\\"type\\\":\\\"keyword\\\"},\\\"dslTemplateMd5\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"isFromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"totalCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"checkMode\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"failedShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"queryLimit\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"double\\\"},\\\"dsl\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"long\\\"},\\\"beforeCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"flinkTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius.gateway.join",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.gateway.join\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timeStamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"gateway 日志按照 requestId 进行 join\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"String \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_query_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"selectFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"stack\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"orderId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"searchCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"String\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"responseLen\\\":{\\\"type\\\":\\\"long\\\"},\\\"Count\\\":{\\\"type\\\":\\\"long\\\"},\\\"beforeCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"isTimedOut\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_exception_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dslTemplate\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"searchId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"x-username\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"action\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_replace_index_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"internalCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"exceptionName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"tookInMillis\\\":{\\\"type\\\":\\\"long\\\"},\\\"traceId\\\":{\\\"type\\\":\\\"float\\\"},\\\"customKey\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_exception_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"method\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_query_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"index\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"indexTypeName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"whereFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"queryString\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"Long` from newton_strategy_2020-07-18_v2 WHERE bizType \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"version\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_tcp_response_length_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dslLen\\\":{\\\"type\\\":\\\"long\\\"},\\\"flowModuleId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"totalHits\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_request_node_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"before_cost\\\":{\\\"type\\\":\\\"long\\\"},\\\"statusCode\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_pre_exception_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"status\\\":{\\\"type\\\":\\\"long\\\"},\\\"traceid\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"isUrgent\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"TimeUsed\\\":{\\\"type\\\":\\\"long\\\"},\\\"pre_alloctication_group\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"sourceTemplateName\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"groupByFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"typeName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"failedShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"routing\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"instanceId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_indices_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"client_node\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_replace_index_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"esCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"requestId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"clusterName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"sortByFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"Long` \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_exception_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"remoteAddr\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"lastBucketNumber\\\":{\\\"type\\\":\\\"long\\\"},\\\"dltagCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"Long \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"successfulShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"String` \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"gatewayNode\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"uri\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"destIndexName\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"url\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_tcp_search_scroll_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indices\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"scrollIdList\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"@timestamp\\\":{\\\"format\\\":\\\"strict_date_optional_time\\\",\\\"type\\\":\\\"date\\\"},\\\"stage\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"postBody\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clientIp\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_pre_exception_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"postBodyLen\\\":{\\\"type\\\":\\\"long\\\"},\\\"proc_time\\\":{\\\"type\\\":\\\"long\\\"},\\\"logicId\\\":{\\\"type\\\":\\\"long\\\"},\\\"Decimal \\\":{\\\"type\\\":\\\"float\\\"},\\\"ariusCreateTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"totalHitsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"xUserName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clientVersion\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"operator\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"Name\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"fetchCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_tcp_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"successShardsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"costTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"paramCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"ariusType\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_indices_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indiceCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_aggs_detail_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_search_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"group\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"orderByFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"res\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"timedOut\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"clientHost\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_fetch_message_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"totalShardsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"isTimeoutList\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"searchType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"Targ\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_before_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dltag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_before_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_request_node_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_tcp_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"success\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"dslTag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"name\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"memUsed\\\":{\\\"type\\\":\\\"long\\\"},\\\"bucketNumber\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"totalCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"sourceIndexNames\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"getClientCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"Errno\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexTemplateCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"dslLevel\\\":{\\\"type\\\":\\\"long\\\"},\\\"timeout\\\":{\\\"type\\\":\\\"long\\\"},\\\"failedShardsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"totalShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"scrollId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"sql\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"destTemplateName\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_aggs_detail_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dslType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"preProcessCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_tcp_response_length_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"newDslTemplate\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"param\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_internal_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"aggsLevel\\\":{\\\"type\\\":\\\"long\\\"},\\\"json\\\":{\\\"type\\\":\\\"object\\\"},\\\"_arius_query_tcp_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clientNode\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"rcvTimeout\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_scroll_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"types\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"cost\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_exception_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"requestType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"fetchSize\\\":{\\\"type\\\":\\\"long\\\"},\\\"esCostList\\\":{\\\"type\\\":\\\"long\\\"},\\\"aggsBukcetInfo\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"fetchMetric\\\":{\\\"properties\\\":{\\\"parseMessageCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"fetchMissingCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"getConsumeCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"fetchOffsetCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"brokerHost\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"fetchMetricInfo\\\":{\\\"properties\\\":{\\\"cost\\\":{\\\"type\\\":\\\"long\\\"},\\\"partition\\\":{\\\"type\\\":\\\"long\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"topic\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"}}},\\\"partitionTotalCost\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"_arius_response_index_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"message\\\":{\\\"ignore_above\\\":2048,\\\"index\\\":false,\\\"type\\\":\\\"keyword\\\"},\\\"userName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_msg\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_fetch_message_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indiceSample\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_internal_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"isFromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"dslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"service\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"user\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_response_index_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"queryRequest\\\":{\\\"type\\\":\\\"boolean\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"60s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius.template.access",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.template.access\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": -1,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"索引模板维度访问次数索引\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"date\\\":{\\\"format\\\":\\\"strict_date_optional_time||yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||yyyy-MM-dd||yyyyMMdd||yyyyMM||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"templateName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"clusterName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"logicTemplateId\\\":{\\\"type\\\":\\\"long\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius_cat_index_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_cat_index_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"索引列表\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"priStoreSize\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"clusterLogic\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"resourceId\\\":{\\\"type\\\":\\\"long\\\"},\\\"platformCreateFlag\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"pri\\\":{\\\"type\\\":\\\"long\\\"},\\\"health\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"docsDeleted\\\":{\\\"type\\\":\\\"long\\\"},\\\"deleteFlag\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"totalSegmentCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterPhy\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"storeSize\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"primariesSegmentCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"rep\\\":{\\\"type\\\":\\\"long\\\"},\\\"docsCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"key\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"status\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius_cat_shard_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_cat_shard_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"shard 分配数据\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"prirep\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"docs\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterPhy\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"ip\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shard\\\":{\\\"type\\\":\\\"long\\\"},\\\"state\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"store\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n  \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius_gateway_metrics",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_gateway_metrics\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"gateway 指标数据\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"query_totalHits_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_request_avg_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_aggs_count\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_count\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_response_avg_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_avg_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_min_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_imin_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"type\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"index_response_length\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_max_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_response_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_imax_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_cost_imax_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_stdev_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_max_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_imax_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_request_length\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_stdev_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"slowlog_cost_imax_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_imin_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_cost_min_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_totalShards_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_request_avg_length_stdev_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_cost_stdev_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_tookInMillis_avg_millis\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_max_length\\\":{\\\"type\\\":\\\"long\\\"},\\\"slowlog_cost_imin_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"template\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"hostName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"index_cost_imax_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_cost_imin_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_failedShards_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_failedShards_avg_count\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_tookInMillis_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_max_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_max_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_response_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_FLINK_SINK_TIME\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"index_response_avg_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_avg_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_request_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"index_response_avg_length_stdev_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_min_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_request_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_totalHits_avg_count\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_count\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_min_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_totalShards_avg_count\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_min_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_imin_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"operation\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"index_cost_avg_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_count\\\":{\\\"type\\\":\\\"long\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius_stats_cluster_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_cluster_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"physicCluster\\\":{\\\"type\\\":\\\"long\\\"},\\\"dataCenter\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"es_index_time\\\":{\\\"type\\\":\\\"long\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"cleanTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"statis\\\":{\\\"properties\\\":{\\\"cpuUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"statusType\\\":{\\\"type\\\":\\\"long\\\"},\\\"numberPendingTasks\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalTemplateNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"activeNodeNu\\\":{\\\"type\\\":\\\"long\\\"},\\\"invalidNodeNu\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"esNodeNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalIndicesNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalStoreSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"level\\\":{\\\"type\\\":\\\"long\\\"},\\\"sla\\\":{\\\"type\\\":\\\"double\\\"},\\\"sendTransSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"taskCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"cpuLoad15M\\\":{\\\"type\\\":\\\"double\\\"},\\\"alivePercent\\\":{\\\"type\\\":\\\"long\\\"},\\\"shardNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"freeStoreSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"memUsed\\\":{\\\"type\\\":\\\"long\\\"},\\\"memFreePercent\\\":{\\\"type\\\":\\\"float\\\"},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"unAssignedShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"appNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"cpuLoad1M\\\":{\\\"type\\\":\\\"double\\\"},\\\"cpuLoad5M\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexStoreSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"nodeNamesForDiskUsageGte75Percent\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"totalDocNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"extendInfoMap\\\":{\\\"type\\\":\\\"object\\\"},\\\"memUsedPercent\\\":{\\\"type\\\":\\\"float\\\"},\\\"clusterName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"storeSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexingLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"nodeIpsForDiskUsageGte75Percent\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"numberNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"recvTransSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"memFree\\\":{\\\"type\\\":\\\"long\\\"},\\\"readTps\\\":{\\\"type\\\":\\\"double\\\"},\\\"memTotal\\\":{\\\"type\\\":\\\"long\\\"},\\\"numberDataNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"writeTps\\\":{\\\"type\\\":\\\"double\\\"},\\\"numberIngestNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"numberMasterNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"queryTimesPreDay\\\":{\\\"type\\\":\\\"double\\\"},\\\"taskCost\\\":{\\\"type\\\":\\\"double\\\"},\\\"numberClientNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"diskUsage\\\":{\\\"type\\\":\\\"double\\\"}}},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"percentilesType\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius_stats_cluster_task_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_cluster_task_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"physicCluster\\\":{\\\"type\\\":\\\"long\\\"},\\\"dataCenter\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"metrics\\\":{\\\"properties\\\":{\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"parentTaskId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"ip\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"action\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"runningTimeString\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"description\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"startTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"runningTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"type\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"taskId\\\":{\\\"type\\\":\\\"keyword\\\"}}},\\\"key\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n  \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius_stats_dashboard_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_dashboard_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 15,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"template\\\":{\\\"properties\\\":{\\\"template\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"segmentMemSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"templateName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"cluster\\\":{\\\"properties\\\":{\\\"elapsedTimeGte5Min\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"gatewayFailedPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"clusterElapsedTimeGte5Min\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"httpNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"collectorDelayed\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexReqNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"nodeElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"gatewaySucPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"pendingTaskNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexingLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"elapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"nodeMetrics\\\":{\\\"properties\\\":{\\\"largeHead\\\":{\\\"type\\\":\\\"double\\\"},\\\"nodeElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"taskConsuming\\\":{\\\"type\\\":\\\"long\\\"},\\\"largeDiskUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"largeCpuUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"writeRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"dead\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"SearchRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"templateMetrics\\\":{\\\"properties\\\":{\\\"template\\\":{\\\"type\\\":\\\"long\\\"},\\\"segmentMemSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"physicCluster\\\":{\\\"type\\\":\\\"integer\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"nodeThreadPoolQueueMetrics\\\":{\\\"properties\\\":{\\\"search\\\":{\\\"type\\\":\\\"long\\\"},\\\"flush\\\":{\\\"type\\\":\\\"long\\\"},\\\"management\\\":{\\\"type\\\":\\\"long\\\"},\\\"merge\\\":{\\\"type\\\":\\\"long\\\"},\\\"refresh\\\":{\\\"type\\\":\\\"long\\\"},\\\"write\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"index\\\":{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"mappingNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"red\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"segmentMemSize\\\":{\\\"type\\\":\\\"float\\\"},\\\"smallShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"bigShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"shardSize\\\":{\\\"type\\\":\\\"long\\\"},\\\"singReplicate\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"memSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"unassignedShard\\\":{\\\"type\\\":\\\"boolean\\\"}}},\\\"clusterPhyHealth\\\":{\\\"properties\\\":{\\\"unknownClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"unknownNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"redNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"totalNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"greenClusterListStr\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"greenNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"yellowClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"yellowNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"redClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"clusterPhyHealthMetrics\\\":{\\\"properties\\\":{\\\"unknownClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"unknownNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"redNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"totalNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"greenNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"active\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"yellowClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"yellowNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"redClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"node\\\":{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"taskConsuming\\\":{\\\"type\\\":\\\"long\\\"},\\\"dead\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"nodeElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"largeHead\\\":{\\\"type\\\":\\\"double\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"largeDiskUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"searchRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"largeCpuUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"writeRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"SearchRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"elapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"clusterThreadPoolQueue\\\":{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"search\\\":{\\\"type\\\":\\\"long\\\"},\\\"flush\\\":{\\\"type\\\":\\\"long\\\"},\\\"management\\\":{\\\"type\\\":\\\"long\\\"},\\\"merge\\\":{\\\"type\\\":\\\"long\\\"},\\\"refresh\\\":{\\\"type\\\":\\\"long\\\"},\\\"write\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"indexMetrics\\\":{\\\"properties\\\":{\\\"red\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"mappingNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"smallShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"bigShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"singReplicate\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"memSize\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"unassignedShard\\\":{\\\"type\\\":\\\"boolean\\\"}}},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clusterMetrics\\\":{\\\"properties\\\":{\\\"indexReqNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"gatewaySucPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"pendingTaskNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"gatewayFailedPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexingLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"httpNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius_stats_index_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_index_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"template\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"long\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"cleanTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"shardNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"metrics\\\":{\\\"properties\\\":{\\\"refresh-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_scroll_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"store-size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-docs-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"docs-count-total\\\":{\\\"type\\\":\\\"float\\\"},\\\"fielddata-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-fetch_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-refresh-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"merges-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-doc_values_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments_segments_request_cache_memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-query_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_time_per_doc\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_index_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-index_writer_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-merges-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-request_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"request_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-index_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"store-size_in_bytes_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"query_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_refresh_total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments_fielddata_memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-scroll_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments_fixed_bit_set_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"docs-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"shardNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-fetch_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-version_map_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"refresh-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"merges-total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments_norms_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_fetch_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_query_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"flush-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_flush_total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-fetch_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-docs-count_diff\\\":{\\\"type\\\":\\\"double\\\"},\\\"refresh-total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments_version_map_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-breakers-fieldd-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"translog-size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"flush-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-fetch_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"flush-total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_total_times\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merge_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"merges-current\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-fixed_bit_set_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-breakers-fielddata-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_time_per_doc\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-flush-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-points_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_merges_total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-norms_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_latency\\\":{\\\"type\\\":\\\"float\\\"},\\\"segments-term_vectors_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-stored_fields_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"store-size_in_bytes-total\\\":{\\\"type\\\":\\\"float\\\"},\\\"merges-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-cost-merges-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_failed_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-fetch_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush_avg_time\\\":{\\\"type\\\":\\\"double\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"logicTemplateId\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.1/template_in_arius/arius_stats_node_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_node_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"rack\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"ip\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"cleanTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"port\\\":{\\\"type\\\":\\\"long\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"metrics\\\":{\\\"properties\\\":{\\\"thread_pool-force_merge-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-heap_used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-bulk-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-miss_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-hit_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-load_average-5m\\\":{\\\"type\\\":\\\"double\\\"},\\\"process-cpu-percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_current\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-store-size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges-current\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-breakers-fielddata-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-write-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-request-estimated_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-server_open\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-in_flight_requests-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-translog-uncommitted_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-hit_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-index_writer_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-total_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-term_vectors_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-refresh-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-tx_size_in_bytes_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"script-compilations\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-total_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-load_average-15m\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-search-completed\\\":{\\\"type\\\":\\\"double\\\"},\\\"http-current_open\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_count_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-index_latency\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-pools-old-used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-disk_free_percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-bulk-rejected\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-bulk-completed\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_latency\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-search-rejected\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_time_per_query\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-docs-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu_percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-miss_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-pools-young-used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-heap_used_percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-norms_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-cache_size\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-rx_size_in_bytes_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-load_average-1m\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-stored_fields_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-parent-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_time_per_fetch\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-non_heap_used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-evictions\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-rollup_indexing-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-evictions\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-translog-operations_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-threads-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-accounting-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-rx_count_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-tx_count_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-fielddata-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-request-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-parent-estimated_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-delete_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-docs-count_diff\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-fixed_bit_set_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-management-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-doc_values_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-points_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"ingest-total-failed\\\":{\\\"type\\\":\\\"float\\\"},\\\"indices-search-scroll_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-write-rejected\\\":{\\\"type\\\":\\\"double\\\"},\\\"process-process-open_file_descriptors\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-accounting-estimated_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-in_flight_requests-estimated_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-total_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-available_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-free_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_time_per_doc\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-fielddata-estimated_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-write-completed\\\":{\\\"type\\\":\\\"double\\\"},\\\"ingest-total-current\\\":{\\\"type\\\":\\\"float\\\"},\\\"ingest-total-count\\\":{\\\"type\\\":\\\"float\\\"},\\\"ingest-total-time_in_millis\\\":{\\\"type\\\":\\\"float\\\"},\\\"thread_pool-search-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-hit_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-hit_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-version_map_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_count_rate\\\":{\\\"type\\\":\\\"double\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/0.3.1.2.增量.sql",
    "content": "# admin表修改\nalter table es_cluster_phy_info\n    add  kibana_address varchar(200) default '' null comment 'kibana外链地址';\nalter table es_cluster_phy_info\n    add  cerebro_address varchar(200) default '' null comment 'cerebro外链地址';\nalter table es_cluster_phy_info\n    add  cerebro_address varchar(200) default '' null comment '代理地址';\nALTER TABLE es_cluster_phy_info\n    ADD proxy_address VARCHAR(255) DEFAULT '' NULL COMMENT ' 代理地址 ';\n# 可观测性组件:\n# 1. 所有logi_security_*表名都改成了kf_security_*\n# 2. logi_task表新增字段\"node_name_white_list_str\", logi_worker表新增字段\"node_name\"\n\nrename table logi_security_config to kf_security_config;\nrename table logi_security_dept to kf_security_dept;\nrename table logi_security_message to kf_security_message;\nrename table logi_security_oplog to kf_security_oplog;\nrename table logi_security_oplog_extra to kf_security_oplog_extra;\nrename table logi_security_permission to kf_security_permission;\nrename table logi_security_project to kf_security_project;\nrename table logi_security_resource_type to kf_security_resource_type;\nrename table logi_security_role to kf_security_role;\nrename table logi_security_role_permission to kf_security_role_permission;\nrename table logi_security_user to kf_security_user;\nrename table logi_security_user_project to kf_security_user_project;\nrename table logi_security_user_resource to kf_security_user_resource;\nrename table logi_security_user_role to kf_security_user_role;\n\nalter table logi_task\n    add node_name_white_list_str varchar(3000) default '' not null comment '执行节点名对应白名单集';\n\nalter table logi_worker\n    add node_name varchar(100) default '' not null comment 'node 名';\n\nINSERT INTO `kf_security_permission` (`permission_name`, `parent_id`, `leaf`, `level`, `description`, `create_time`, `update_time`, `is_delete`, `app_name`) VALUES ('Grafana', 0, 0, 1, 'Grafana', '2022-05-24 18:08:26', '2022-12-22 15:16:17', 0, 'know_search');\nINSERT INTO `kf_security_role_permission` (`role_id`, `permission_id`, `create_time`, `update_time`, `is_delete`, `app_name`) VALUES (1, (select id from kf_security_permission ksp where ksp.permission_name='Grafana' and ksp.app_name='know_search' and ksp.is_delete=0 ), '2022-06-01 21:19:42', '2022-08-25 10:31:42', 0, 'know_search');\nINSERT INTO `kf_security_permission` (`permission_name`, `parent_id`, `leaf`, `level`, `description`, `create_time`, `update_time`, `is_delete`, `app_name`) VALUES ('查看Grafana', (select id from kf_security_permission ksp where ksp.permission_name='Grafana' and ksp.app_name='know_search' and ksp.is_delete=0 ), 1, 2, '查看Grafana', '2022-05-24 18:08:26', '2022-12-22 15:16:17', 0, 'know_search');\nINSERT INTO `kf_security_role_permission` (`role_id`, `permission_id`, `create_time`, `update_time`, `is_delete`, `app_name`) VALUES (1, (select id from kf_security_permission ksp where ksp.permission_name='查看Grafana' and ksp.app_name='know_search' and ksp.is_delete=0 ), '2022-06-01 21:19:42', '2022-08-25 10:31:42', 0, 'know_search');\n\n-- 设置supperapp为索引模式\nupdate `arius_es_user` set cluster='' , search_type=1  where id=1;\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/init.sql",
    "content": "#项目、用户、权限点\n-- auto-generated definition\ncreate table kf_security_config\n(\n    id          bigint unsigned auto_increment comment '主键自增'\n        primary key,\n    value_group varchar(100)  default ''                not null comment ' 配置项组 ',\n    value_name  varchar(100)  default ''                not null comment ' 配置项名字 ',\n    value       text                                    null comment '配置项的值',\n    edit        int(4)        default 1                 not null comment '是否可以编辑 1 不可编辑（程序获取） 2 可编辑',\n    status      int(4)        default 1                 not null comment '1 正常 2 禁用',\n    memo        varchar(1000) default ''                not null comment ' 备注 ',\n    create_time timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间',\n    is_delete   tinyint(1)    default 0                 not null comment '逻辑删除',\n    app_name    varchar(16) collate utf8_bin            null comment '应用名称',\n    operator    varchar(16) collate utf8_bin            null comment '操作者'\n)\n    comment 'logi 配置项' charset = utf8;\n\ncreate index idx_group_name\n    on kf_security_config (value_group, value_name);\n\n-- auto-generated definition\ncreate table kf_security_dept\n(\n    id          int auto_increment\n        primary key,\n    dept_name   varchar(10)                          not null comment '部门名',\n    parent_id   int                                  not null comment '父部门 id',\n    leaf        tinyint(1)                           not null comment '是否叶子部门',\n    level       tinyint                              not null comment 'parentId 为 0 的层级为 1',\n    description varchar(20)                          null comment '描述',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '部门信息表' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_message\n(\n    id          int auto_increment\n        primary key,\n    title       varchar(60)                          not null comment '标题',\n    content     varchar(256)                         null comment '内容',\n    read_tag    tinyint(1) default 0                 null comment '是否已读',\n    oplog_id    int                                  null comment '操作日志 id',\n    user_id     int                                  null comment '这条消息属于哪个用户的，用户 id',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '消息中心' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_oplog\n(\n    id                int auto_increment\n        primary key,\n    operator_ip       varchar(20)                            not null comment '操作者 ip',\n    operator          varchar(20)                            null comment '操作者账号',\n    operate_page      varchar(16)                            null comment '操作页面',\n    operate_type      varchar(16)                            not null comment '操作类型',\n    target_type       varchar(16)                            not null comment '对象分类',\n    target            varchar(255)                            not null comment '操作对象',\n    detail            text                                   null comment '日志详情',\n    create_time       timestamp    default CURRENT_TIMESTAMP null,\n    update_time       timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete         tinyint(1)   default 0                 not null comment '逻辑删除',\n    app_name          varchar(16)                            null comment '应用名称',\n    operation_methods varchar(255) default ''                null\n)\n    comment '操作日志' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_oplog_extra\n(\n    id          int auto_increment\n        primary key,\n    info        varchar(16)                          null comment '信息',\n    type        tinyint                              not null comment '哪种信息：1：操作页面;2：操作类型;3：对象分类',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '操作日志信息（操作页面、操作类型、对象分类）' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_permission\n(\n    id              int auto_increment\n        primary key,\n    permission_name varchar(40)                          not null comment '权限名字',\n    parent_id       int                                  not null comment '父权限 id',\n    leaf            tinyint(1)                           not null comment '是否叶子权限点（具体的操作）',\n    level           tinyint                              not null comment '权限点的层级（parentId 为 0 的层级为 1）',\n    description     varchar(64)                          null comment '权限点描述',\n    create_time     timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time     timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete       tinyint(1) default 0                 null comment '逻辑删除',\n    app_name        varchar(16)                          null comment '应用名称'\n)\n    comment '权限表' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_project\n(\n    id           int auto_increment comment '项目 id'\n        primary key,\n    project_code varchar(128)                           not null comment '项目编号',\n    project_name varchar(128)                           not null comment '项目名',\n    description  varchar(512) default ''                not null comment ' 项目描述 ',\n    dept_id      int                                    not null comment '部门 id',\n    running      tinyint(1)   default 1                 not null comment '启用 or 停用',\n    create_time  timestamp    default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time  timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete    tinyint(1)   default 0                 not null comment '逻辑删除',\n    app_name     varchar(16)                            null comment '应用名称'\n)\n    comment '项目表' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_resource_type\n(\n    id          int auto_increment\n        primary key,\n    type_name   varchar(16)                          null comment '资源类型名',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '资源类型表' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_role\n(\n    id           int auto_increment\n        primary key,\n    role_code    varchar(128)                         not null comment '角色编号',\n    role_name    varchar(128)                         not null comment '名称',\n    description  varchar(128)                         null comment '角色描述',\n    last_reviser varchar(30)                          null comment '最后修改人',\n    create_time  timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time  timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete    tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name     varchar(16)                          null comment '应用名称'\n)\n    comment '角色信息' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_role_permission\n(\n    id            int auto_increment\n        primary key,\n    role_id       int                                  not null comment '角色 id',\n    permission_id int                                  not null comment '权限 id',\n    create_time   timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time   timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete     tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name      varchar(16)                          null comment '应用名称'\n)\n    comment '角色权限表（只保留叶子权限与角色关系）' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_user\n(\n    id          int auto_increment\n        primary key,\n    user_name   varchar(64)                            not null comment '用户账号',\n    pw          varchar(2048)                          not null comment '用户密码',\n    salt        char(5)      default ''                not null comment ' 密码盐 ',\n    real_name   varchar(128) default ''                not null comment ' 真实姓名 ',\n    phone       char(11)     default ''                not null comment 'mobile',\n    email       varchar(30)  default ''                not null comment 'email',\n    dept_id     int                                    null comment '所属部门 id',\n    is_delete   tinyint(1)   default 0                 not null comment '逻辑删除',\n    create_time timestamp    default CURRENT_TIMESTAMP null comment '注册时间',\n    update_time timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    app_name    varchar(16)                            null comment '应用名称'\n)\n    comment '用户信息' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_user_project\n(\n    id          int auto_increment\n        primary key,\n    user_id     int                                   not null comment '用户 id',\n    project_id  int                                   not null comment '项目 id',\n    create_time timestamp   default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp   default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1)  default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                           null comment '应用名称',\n    user_type   tinyint(10) default 0                 not null comment '用户类型：0：普通项目用户；1：项目 owner'\n)\n    comment '用户项目关系表（项目负责人）' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_user_resource\n(\n    id               int auto_increment\n        primary key,\n    user_id          int                                  not null comment '用户 id',\n    project_id       int                                  not null comment '资源所属项目 id',\n    resource_type_id int                                  not null comment '资源类别 id',\n    resource_id      int                                  not null comment '资源 id',\n    control_level    tinyint                              not null comment '管理级别：1（查看权限）2（管理权限）',\n    create_time      timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time      timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete        tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name         varchar(16)                          null comment '应用名称'\n)\n    comment '用户和资源关系表' charset = utf8;\n\n-- auto-generated definition\ncreate table kf_security_user_role\n(\n    id          int auto_increment\n        primary key,\n    user_id     int                                  not null comment '用户 id',\n    role_id     int                                  not null comment '角色 id',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '用户角色表' charset = utf8;\n\n-- auto-generated definition\ncreate table arius_es_user\n(\n    id                 bigint(10) unsigned auto_increment comment '主键 自增'\n        primary key,\n    index_exp          text                                    null comment '索引表达式',\n    data_center        varchar(20)   default ''                not null comment ' 数据中心 ',\n    is_root            tinyint       default 0                 not null comment '是都是超级用户 超级用户具有所有索引的访问权限 0 不是 1 是',\n    memo               varchar(1000) default ''                not null comment ' 备注 ',\n    ip                 varchar(500)  default ''                not null comment ' 白名单 ip 地址 ',\n    verify_code        varchar(50)   default ''                not null comment 'app 验证码 ',\n    is_active          tinyint(2)    default 1                 not null comment '1 为可用，0 不可用',\n    query_threshold    int(10)       default 100               not null comment '限流值',\n    cluster            varchar(100)  default ''                not null comment ' 查询集群 ',\n    responsible        varchar(500)  default ''                null comment ' 责任人 ',\n    search_type        tinyint       default 0                 not null comment '0 表示 app 的查询请求需要 app 里配置的集群 (一般配置的都是 trib 集群) 1 表示 app 的查询请求必须只能访问一个模板 2 表示集群模式（可支持多模板查询）',\n    create_time        timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time        timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间',\n    project_id         bigint(10)                              not null comment '项目 id',\n    is_default_display tinyint(2)    default 0                 not null comment '1：项目默认的 es user；0: 项目新增的 es user'\n)\n    comment 'es 操作用户表' charset = utf8;\ncreate table project_arius_config\n(\n    project_id              bigint(10) unsigned auto_increment comment 'project id'\n        primary key,\n    analyze_response_enable tinyint       default 1                 not null comment '响应结果解析开关 默认是 0：关闭，1：开启',\n    is_source_separated     tinyint       default 0                 not null comment '是否是索引存储分离的 0 不是 1 是',\n    aggr_analyze_enable     tinyint       default 1                 not null comment '1 生效 0 不生效',\n    dsl_analyze_enable      tinyint(2)    default 1                 not null comment '1 为生效 dsl 分析查询限流值，0 不生效 dsl 分析查询限流值',\n    slow_query_times        int(10)       default 100               not null comment '慢查询耗时',\n    is_active               tinyint(2)    default 1                 not null comment '1 为可用，0 不可用',\n    memo                    varchar(1000) default ''                not null comment ' 备注 ',\n    create_time             timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time             timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间'\n)\n    comment '项目配置' charset = utf8;\n\n-- auto-generated definition\n\n\n#### 核心表结构\nCREATE TABLE `arius_config_info`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `value_group` varchar(100)        NOT NULL DEFAULT '' COMMENT ' 配置项组 ',\n    `value_name`  varchar(100)        NOT NULL DEFAULT '' COMMENT ' 配置项名字 ',\n    `value`       text COMMENT '配置项的值',\n    `edit`        int(4)              NOT NULL DEFAULT '1' COMMENT '是否可以编辑 1 不可编辑（程序获取） 2 可编辑',\n    `dimension`   int(4)              NOT NULL DEFAULT '-1' COMMENT '配置项维度 1 集群 2 模板',\n    `status`      int(4)              NOT NULL DEFAULT '1' COMMENT '1 正常 2 禁用 -1 删除',\n    `memo`        varchar(1000)       NOT NULL DEFAULT '' COMMENT ' 备注 ',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `search_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '配置查询时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_group_name` (`value_group`, `value_name`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1662\n  DEFAULT CHARSET = utf8 COMMENT ='arius 配置项';\n\n\n\n-- ----------------------------\n-- Table structure for arius_meta_job_cluster_distribute\n-- ----------------------------\nCREATE TABLE `arius_meta_job_cluster_distribute`\n(\n    `id`           bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 id',\n    `cluster_id`   int(11)             NOT NULL DEFAULT '-1' COMMENT '集群 id',\n    `monitor_host` varchar(128)        NOT NULL DEFAULT '' COMMENT ' 当前执行主机名 ',\n    `monitor_time` timestamp           NOT NULL DEFAULT '2000-01-02 00:00:00' COMMENT '上一次监控时间',\n    `gmt_create`   timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `gmt_modify`   timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `cluster`      varchar(128)        NOT NULL DEFAULT '' COMMENT ' 集群名称 ',\n    `dataCentre`   varchar(16)         NOT NULL DEFAULT 'cn' COMMENT '集群数据中心',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_cluster_id` (`cluster_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 435089\n  DEFAULT CHARSET = utf8 COMMENT ='monitor 任务分配';\n\n-- ----------------------------\n-- Table structure for arius_op_task\n-- ----------------------------\nCREATE TABLE `arius_op_task`\n(\n    `id`           bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `title`        varchar(100)        NOT NULL DEFAULT '' COMMENT ' 标题 ',\n    `business_key` varchar(1000)       NOT NULL DEFAULT '0' COMMENT '业务数据主键',\n    `status`       varchar(20)         NOT NULL DEFAULT 'waiting' COMMENT '任务状态：success: 成功 failed: 失败 running: 执行中 waiting: 等待 cancel: 取消 pause: 暂停',\n    `creator`      varchar(100)        NOT NULL DEFAULT '' COMMENT ' 创建人 ',\n    `create_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`  tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    `expand_data`  longtext COMMENT '扩展数据',\n    `task_type`    int(11)             NOT NULL DEFAULT '0' COMMENT '任务类型 1：集群新增，2：集群扩容，3：集群缩容，4：集群重，5：集群升级，6：集群插件操作，10：模版 dcdr 任务',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2302\n  DEFAULT CHARSET = utf8 COMMENT ='arius 任务表';\n\n-- ----------------------------\n-- Table structure for arius_work_order_info\n-- ----------------------------\nCREATE TABLE `arius_work_order_info`\n(\n    `id`                   bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',\n    `type`                 varchar(25)         NOT NULL DEFAULT 'unknown' COMMENT 'appcreate 创建 app,clustercreate 创建集群,clusterindecrease 集群扩缩溶,clusteroffline 集群下线,clusterupdate 集群修改,templateauth 索引申请,templatecreate 索引创建,templateindecrease 索引扩容,templatequerydsl 查询语句创建,templatetransfer 索引转让,querydsllimitedit 查询语句编辑,responsiblegovern 员工离职,unhealthytemplategovern 不健康索引处理',\n    `title`                varchar(64)         NOT NULL DEFAULT '' COMMENT ' 标题 ',\n    `approver_project_id`  int(16)             NOT NULL DEFAULT '-1' COMMENT '审批人 projectid',\n    `applicant`            varchar(64)         NOT NULL DEFAULT '' COMMENT ' 申请人 ',\n    `extensions`           text COMMENT '拓展字段',\n    `description`          text COMMENT '备注信息',\n    `approver`             varchar(64)         NOT NULL DEFAULT '' COMMENT ' 审批人 ',\n    `finish_time`          timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '结束时间',\n    `opinion`              varchar(256)        NOT NULL DEFAULT '' COMMENT ' 审批信息 ',\n    `status`               int(16)             NOT NULL DEFAULT '0' COMMENT '工单状态, 0: 待审批, 1: 通过, 2: 拒绝, 3: 取消',\n    `create_time`          timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`          timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修 \\n 改时间',\n    `applicant_project_id` int(16)             NOT NULL DEFAULT '-1' COMMENT '申请人 projectid',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2522\n  DEFAULT CHARSET = utf8 COMMENT ='工单表';\n\n-- ----------------------------\n-- Table structure for es_cluster_phy_info\n-- ----------------------------\nCREATE TABLE `es_cluster_phy_info`\n(\n    `id`                      bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `cluster`                 varchar(128)        NOT NULL DEFAULT '' COMMENT 'es 集群名 ',\n    `read_address`            varchar(1000)       NOT NULL DEFAULT '' COMMENT ' 读地址 tcp',\n    `write_address`           varchar(2000)       NOT NULL DEFAULT '' COMMENT ' 写地址 tcp',\n    `http_address`            varchar(1000)       NOT NULL DEFAULT '' COMMENT 'http 服务地址 ',\n    `http_write_address`      varchar(8000)       NOT NULL DEFAULT '' COMMENT 'http 写地址 ',\n    `desc`                    varchar(2000)       NOT NULL DEFAULT '' COMMENT ' 描述 ',\n    `type`                    tinyint(4)          NOT NULL DEFAULT '-1' COMMENT '集群类型，3-docker 集群，4-host 集群',\n    `data_center`             varchar(10)         NOT NULL DEFAULT 'cn' COMMENT '数据中心',\n    `idc`                     varchar(10)         NOT NULL DEFAULT '' COMMENT ' 机房信息 ',\n    `es_version`              varchar(100)        NOT NULL DEFAULT '' COMMENT 'es 版本 ',\n    `create_time`             timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`             timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `level`                   tinyint(4)          NOT NULL DEFAULT '1' COMMENT '服务等级',\n    `password`                varchar(255)        NOT NULL DEFAULT '' COMMENT ' 集群访问密码 ',\n    `ecm_cluster_id`          int(11)             NOT NULL DEFAULT '-1' COMMENT 'ecm 集群 id',\n    `cluster_config_template` text COMMENT '集群安装模板',\n    `image_name`              varchar(500)        NOT NULL DEFAULT '' COMMENT ' 镜像名 ',\n    `cfg_id`                  int(11)             NOT NULL DEFAULT '-1' COMMENT '配置包 id',\n    `package_id`              int(11)             NOT NULL DEFAULT '-1' COMMENT '程序包 id',\n    `plug_ids`                varchar(100)                 DEFAULT '' COMMENT ' 插件包 id 列表 ',\n    `creator`                 varchar(255)        NOT NULL DEFAULT '' COMMENT ' 集群创建人 ',\n    `ns_tree`                 varchar(100)        NOT NULL DEFAULT '' COMMENT ' 机器节点 ',\n    `template_srvs`           varchar(255)                 DEFAULT '' COMMENT ' 集群的索引模板服务 ',\n    `is_active`               tinyint(4)          NOT NULL DEFAULT '1' COMMENT '是否生效',\n    `run_mode`                tinyint(255)        NOT NULL DEFAULT '0' COMMENT 'client 运行模式，0 读写共享，1 读写分离',\n    `write_action`            varchar(1000)                DEFAULT NULL COMMENT '指定写 client 的 action',\n    `health`                  tinyint(2)          NOT NULL DEFAULT '3' COMMENT '集群状态 1 green 2 yellow 3 red',\n    `active_shard_num`        bigint(25)          NOT NULL DEFAULT '0' COMMENT '有效 shard 总数量',\n    `disk_total`              bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘总量 单位 byte',\n    `disk_usage`              bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘使用量 单位 byte',\n    `disk_usage_percent`      decimal(10, 5)      NOT NULL COMMENT '集群磁盘空闲率 单位 0 ~1',\n    `tags`                    text COMMENT '拓展字段, 这里用于存放集群展示用属性标签，如「集群所属资源类型」等等',\n    `platform_type`           varchar(100)        NOT NULL DEFAULT '' COMMENT 'IaaS 平台类型 ',\n    `resource_type`           tinyint(4)          NOT NULL DEFAULT '-1' COMMENT '集群资源类型，1- 共享资源，2- 独立资源，3- 独享资源',\n    `gateway_url`             varchar(200)        NOT NULL DEFAULT '' COMMENT ' 集群 gateway 地址 ',\n    `kibana_address`          varchar(200)                 DEFAULT '' COMMENT 'kibana外链地址',\n    `cerebro_address`         varchar(200)                 DEFAULT '' COMMENT 'cerebro外链地址',\n    PRIMARY KEY (`id`),\n    KEY `idx_cluster` (`cluster`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 4710\n  DEFAULT CHARSET = utf8 COMMENT ='物理集群表';\n\n-- ----------------------------\n-- Table structure for es_cluster_region\n-- ----------------------------\nCREATE TABLE `es_cluster_region`\n(\n    `id`               bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `logic_cluster_id` varchar(200)        NOT NULL DEFAULT '-1' COMMENT '逻辑集群 ID',\n    `phy_cluster_name` varchar(128)        NOT NULL DEFAULT '' COMMENT ' 物理集群名 ',\n    `racks`            varchar(2048)                DEFAULT '' COMMENT 'region 的 rack，逗号分隔 ',\n    `create_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`      tinyint(1)          NOT NULL DEFAULT '0' COMMENT '删除标记，1- 已删除，0- 未删除',\n    `name`             varchar(100)        NOT NULL DEFAULT '' COMMENT 'region 名称 ',\n    `config`           varchar(1024)                DEFAULT '' COMMENT 'region 配置项 ',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 4008\n  DEFAULT CHARSET = utf8 COMMENT ='es 集群 region 表';\n\n-- ----------------------------\n-- Table structure for es_cluster_role_host_info\n-- ----------------------------\nCREATE TABLE `es_cluster_role_host_info`\n(\n    `id`              bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `role_cluster_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '关联集群角色表外键',\n    `hostname`        varchar(100)        NOT NULL DEFAULT '' COMMENT ' 节点名称 ',\n    `ip`              varchar(50)         NOT NULL DEFAULT '' COMMENT ' 主机 ip',\n    `cluster`         varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群 ',\n    `port`            varchar(20)         NOT NULL DEFAULT '' COMMENT ' 端口，如果是节点上启动了多个进程，可以是多个，用逗号隔开 ',\n    `role`            tinyint(4)          NOT NULL DEFAULT '-1' COMMENT '角色信息， 1data 2client 3master 4tribe',\n    `status`          tinyint(4)          NOT NULL DEFAULT '1' COMMENT '节点状态，1 在线 2 离线',\n    `rack`            varchar(30)                  DEFAULT '' COMMENT ' 节点 rack 信息 ',\n    `node_set`        varchar(500)        NOT NULL DEFAULT '' COMMENT ' 节点 set 信息 ',\n    `create_time`     timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`     timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`     tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    `machine_spec`    varchar(100)                 DEFAULT '',\n    `region_id`       bigint(20)          NOT NULL DEFAULT '-1' COMMENT '节点所属 regionId',\n    `attributes`      text COMMENT 'es 节点 attributes 信息 , 逗号分隔',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_elastic_cluster_id_role_node_set` (`role_cluster_id`, `ip`, `port`, `node_set`),\n    KEY `idx_cluster` (`cluster`),\n    KEY `idx_hostname` (`hostname`),\n    KEY `idx_rack` (`rack`),\n    KEY `idx_region_id` (`region_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 2274\n  DEFAULT CHARSET = utf8 COMMENT ='es 集群表对应各角色主机列表';\n\n-- ----------------------------\n-- Table structure for es_cluster_role_info\n-- ----------------------------\nCREATE TABLE `es_cluster_role_info`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `elastic_cluster_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'elastic_cluster 外键 id',\n    `role_cluster_name`  varchar(256)        NOT NULL DEFAULT '' COMMENT 'role 集群名称 ',\n    `role`               varchar(20)         NOT NULL DEFAULT '' COMMENT ' 集群角色 (masternode/datanode/clientnode)',\n    `pod_number`         int(11)             NOT NULL DEFAULT '0' COMMENT 'pod 数量',\n    `pid_count`          int(11)             NOT NULL DEFAULT '1' COMMENT '单机实例数',\n    `machine_spec`       varchar(100)                 DEFAULT '' COMMENT ' 机器规格 ',\n    `es_version`         varchar(150)        NOT NULL DEFAULT '' COMMENT 'es 版本 ',\n    `cfg_id`             int(11)             NOT NULL DEFAULT '-1' COMMENT '配置包 id',\n    `plug_ids`           varchar(100)        NOT NULL DEFAULT '' COMMENT ' 插件包 id 列表 ',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`        tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_elastic_cluster_id_ddcloud_cluster_name` (`elastic_cluster_id`, `role_cluster_name`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1138\n  DEFAULT CHARSET = utf8 COMMENT ='es 集群角色表';\n\n-- ----------------------------\n-- Table structure for es_config\n-- ----------------------------\nCREATE TABLE `es_config`\n(\n    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `cluster_id`     bigint(20)          NOT NULL DEFAULT '-1' COMMENT '集群 id',\n    `type_name`      varchar(255)        NOT NULL DEFAULT '' COMMENT ' 配置文件名称 ',\n    `engin_name`     varchar(100)        NOT NULL DEFAULT '' COMMENT ' 组件名称 ',\n    `config_data`    longtext COMMENT '配置内容',\n    `desc`           varchar(255)        NOT NULL DEFAULT '' COMMENT ' 配置描述 ',\n    `version_tag`    varchar(100)        NOT NULL DEFAULT '' COMMENT ' 配置 tag',\n    `version_config` bigint(20)          NOT NULL DEFAULT '-1' COMMENT '配置版本',\n    `selected`       smallint(6)         NOT NULL DEFAULT '0' COMMENT '是否在使用',\n    `create_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`    tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1130\n  DEFAULT CHARSET = utf8 COMMENT ='es 配置表';\n\n-- ----------------------------\n-- Table structure for es_machine_norms\n-- ----------------------------\nCREATE TABLE `es_machine_norms`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `role`        varchar(20)         NOT NULL DEFAULT '' COMMENT ' 角色 (masternode/datanode/clientnode/datanode-ceph)',\n    `spec`        varchar(32)         NOT NULL DEFAULT '' COMMENT ' 规格 (16-48gi-100g)',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `delete_flag` tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 16\n  DEFAULT CHARSET = utf8 COMMENT ='容器规格列表';\n\n-- ----------------------------\n-- Table structure for es_package\n-- ----------------------------\nCREATE TABLE `es_package`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `url`         varchar(255)        NOT NULL DEFAULT '' COMMENT ' 镜像地址或包地址 ',\n    `es_version`  varchar(100)        NOT NULL DEFAULT '' COMMENT ' 版本标识 ',\n    `creator`     varchar(100)        NOT NULL DEFAULT '' COMMENT ' 包创建人 ',\n    `release`     tinyint(1)          NOT NULL DEFAULT '0' COMMENT '是否为发布版本',\n    `manifest`    varchar(32)         NOT NULL DEFAULT '' COMMENT ' 类型 (3 docker/4 host)',\n    `desc`        varchar(384)                 DEFAULT '' COMMENT ' 备注 ',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag` tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除 0 未删 1 已删',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 318\n  DEFAULT CHARSET = utf8 COMMENT ='程序包版本管理';\n\n-- ----------------------------\n-- Table structure for es_plugin\n-- ----------------------------\nCREATE TABLE `es_plugin`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `name`               varchar(50)         NOT NULL DEFAULT '' COMMENT ' 插件名 ',\n    `physic_cluster_ids` varchar(100)        NOT NULL DEFAULT '' COMMENT ' 物理集群 id',\n    `version`            varchar(50)         NOT NULL DEFAULT '' COMMENT ' 插件版本 ',\n    `url`                varchar(1024)       NOT NULL DEFAULT '' COMMENT ' 插件存储地址 ',\n    `md5`                varchar(100)        NOT NULL DEFAULT '' COMMENT ' 插件文件 md5',\n    `desc`               varchar(255)        NOT NULL DEFAULT '' COMMENT ' 插件描述 ',\n    `creator`            varchar(100)        NOT NULL DEFAULT '' COMMENT ' 插件创建人 ',\n    `p_default`          tinyint(1)          NOT NULL DEFAULT '0' COMMENT '是否为系统默认：0 否 1 是',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `delete_flag`        tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 416\n  DEFAULT CHARSET = utf8 COMMENT ='es 插件包管理';\n\n-- ----------------------------\n-- Table structure for es_work_order_task\n-- ----------------------------\nCREATE TABLE `es_work_order_task`\n(\n    `id`                bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `title`             varchar(100)        NOT NULL DEFAULT '' COMMENT ' 标题 ',\n    `work_order_id`     bigint(20)          NOT NULL DEFAULT '-1' COMMENT '工单 id',\n    `physic_cluster_id` bigint(20)          NOT NULL DEFAULT '-1' COMMENT '物理集群 id',\n    `cluster_node_role` varchar(512)        NOT NULL DEFAULT '-1' COMMENT '集群节点角色',\n    `task_ids`          varchar(128)        NOT NULL DEFAULT '' COMMENT ' 各角色任务 ids',\n    `type`              varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群类型:3 docker 容器云 / 4 host 物理机 ',\n    `order_type`        varchar(50)         NOT NULL DEFAULT '' COMMENT ' 工单类型 1 集群新增 2 集群扩容 3 集群缩容 4 集群重启 5 集群升级 ',\n    `status`            varchar(20)         NOT NULL DEFAULT '' COMMENT ' 任务状态 ',\n    `creator`           varchar(100)        NOT NULL DEFAULT '' COMMENT ' 工单创建人 ',\n    `create_time`       timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`       timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`       tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    `handle_data`       longtext COMMENT '工单数据',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1958\n  DEFAULT CHARSET = utf8 COMMENT ='es 工单任务表';\n\n-- ----------------------------\n-- Table structure for es_work_order_task_detail\n-- ----------------------------\nCREATE TABLE `es_work_order_task_detail`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id 主键自增',\n    `work_order_task_id` bigint(20)          NOT NULL DEFAULT '-1' COMMENT '工单任务 id',\n    `role`               varchar(100)        NOT NULL DEFAULT '' COMMENT ' 所属角色 ',\n    `hostname`           varchar(100)        NOT NULL DEFAULT '' COMMENT ' 主机名称 /ip',\n    `grp`                int(11)             NOT NULL DEFAULT '0' COMMENT '机器的分组',\n    `idx`                int(11)             NOT NULL DEFAULT '0' COMMENT '机器在分组中的索引',\n    `task_id`            bigint(20)          NOT NULL DEFAULT '-1' COMMENT '容器云 / 物理机 接口返回任务 id',\n    `status`             varchar(20)         NOT NULL DEFAULT '' COMMENT ' 任务状态 ',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n    `delete_flag`        tinyint(1)          NOT NULL DEFAULT '0' COMMENT '标记删除',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_work_order_task_id_role_hostname_delete_flag` (`work_order_task_id`, `role`, `hostname`, `delete_flag`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 6592\n  DEFAULT CHARSET = utf8 COMMENT ='es 工单任务详情表';\n\n-- ----------------------------\n-- Table structure for gateway_cluster_info\n-- ----------------------------\nCREATE TABLE `gateway_cluster_info`\n(\n    `id`           bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `cluster_name` varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群名称 ',\n    `create_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`  timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_cluster_name` (`cluster_name`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 188\n  DEFAULT CHARSET = utf8 COMMENT ='gateway 集群信息';\n\n-- ----------------------------\n-- Table structure for gateway_cluster_node_info\n-- ----------------------------\nCREATE TABLE `gateway_cluster_node_info`\n(\n    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `cluster_name`   varchar(50)         NOT NULL DEFAULT '' COMMENT ' 集群名称 ',\n    `host_name`      varchar(50)         NOT NULL DEFAULT '' COMMENT ' 主机名 ',\n    `port`           int(10)             NOT NULL DEFAULT '-1' COMMENT '端口',\n    `heartbeat_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '心跳时间',\n    `create_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uniq_ip_port` (`host_name`, `port`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 490264\n  DEFAULT CHARSET = utf8 COMMENT ='gateway 节点信息';\n\n-- ----------------------------\n-- Table structure for index_template_alias\n-- ----------------------------\nCREATE TABLE `index_template_alias`\n(\n    `id`                bigint(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `index_template_id` int(10)             NOT NULL DEFAULT '-1' COMMENT '索引模板 id',\n    `name`              varchar(50)         NOT NULL DEFAULT '' COMMENT ' 别名 ',\n    `filterterm`        varchar(255)        NOT NULL DEFAULT '' COMMENT ' 过滤器 ',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 4\n  DEFAULT CHARSET = utf8 COMMENT ='索引别名';\n\n-- ----------------------------\n-- Table structure for index_template_config\n-- ----------------------------\nCREATE TABLE `index_template_config`\n(\n    `is_source_separated`      tinyint(4)          NOT NULL DEFAULT '0' COMMENT '是否是索引处分分离的 0 不是 1 是',\n    `idc_flags`                tinyint(1)          NOT NULL DEFAULT '0' COMMENT 'idc 标识',\n    `adjust_rack_shard_factor` decimal(10, 2)      NOT NULL DEFAULT '1.00' COMMENT '模板 shard 的资源消耗因子',\n    `mapping_improve_enable`   tinyint(4)          NOT NULL DEFAULT '1' COMMENT 'mapping 优化开关 1 开 0 关',\n    `pre_create_flags`         tinyint(1)          NOT NULL DEFAULT '1' COMMENT '预创建标识',\n    `update_time`              timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `disable_source_flags`     tinyint(1)          NOT NULL DEFAULT '0' COMMENT '禁用 source 标识',\n    `disable_index_rollover`   tinyint(1)          NOT NULL DEFAULT '1' COMMENT '禁用 indexRollover 功能',\n    `dynamic_limit_enable`     tinyint(4)          NOT NULL DEFAULT '1' COMMENT '动态限流开关 1 开 0 关',\n    `logic_id`                 int(10)             NOT NULL DEFAULT '-1' COMMENT '逻辑模板 id',\n    `create_time`              timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `shard_num`                int(11)             NOT NULL DEFAULT '1' COMMENT 'shard 数量',\n    `adjust_rack_tps_factor`   decimal(10, 2)      NOT NULL DEFAULT '1.00' COMMENT '容量规划时，tps 的系数',\n    `id`                       bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n    PRIMARY KEY (`id`),\n    KEY `idx_logic_id` (`logic_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 1546\n  DEFAULT CHARSET = utf8 COMMENT ='模板配置信息';\n\n-- ----------------------------\n-- Table structure for index_template_info\n-- ----------------------------\nCREATE TABLE `index_template_info`\n(\n    `id`                bigint(20) unsigned          NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `name`              varchar(128)                 NOT NULL DEFAULT '' COMMENT ' 名称 ',\n    `data_type`         tinyint(4)                   NOT NULL DEFAULT '-1' COMMENT '数据类型',\n    `date_format`       varchar(50)                  NOT NULL DEFAULT '' COMMENT ' 索引分区的时间后缀 ',\n    `is_active`         tinyint(2)                   NOT NULL DEFAULT '1' COMMENT '有效标记',\n    `data_center`       varchar(20)                  NOT NULL DEFAULT '' COMMENT ' 数据中心 ',\n    `expire_time`       bigint(20)                   NOT NULL DEFAULT '-1' COMMENT '保存时长',\n    `hot_time`          int(10)                      NOT NULL DEFAULT '-1' COMMENT '热数据保存时长',\n    `responsible`       varchar(500)                          DEFAULT '' COMMENT ' 责任人 ',\n    `date_field`        varchar(50)                  NOT NULL DEFAULT '' COMMENT ' 时间字段 ',\n    `date_field_format` varchar(128)                 NOT NULL DEFAULT '' COMMENT ' 时间字段的格式 ',\n    `id_field`          varchar(512)                          DEFAULT '' COMMENT 'id 字段 ',\n    `routing_field`     varchar(512)                          DEFAULT '' COMMENT 'routing 字段 ',\n    `expression`        varchar(100)                 NOT NULL DEFAULT '' COMMENT ' 索引表达式 ',\n    `desc`              varchar(1000)                NOT NULL DEFAULT '' COMMENT ' 索引描述 ',\n    `quota`             decimal(10, 3)               NOT NULL DEFAULT '-1.000' COMMENT '规格',\n    `project_id`        int(10)                      NOT NULL DEFAULT '-1' COMMENT 'project_id',\n    `ingest_pipeline`   varchar(512)                 NOT NULL DEFAULT '' COMMENT 'ingest_pipeline',\n    `block_read`        tinyint(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否禁读，0：否，1：是',\n    `block_write`       tinyint(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否禁写，0：否，1：是',\n    `create_time`       timestamp                    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`       timestamp                    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `write_rate_limit`  bigint(255)                  NOT NULL DEFAULT '-1' COMMENT '写入限流值',\n    `resource_id`       bigint(20)                   NOT NULL DEFAULT '-1' COMMENT '逻辑集群 id',\n    `check_point_diff`  bigint(100)                  NOT NULL DEFAULT '0' COMMENT 'dcdr 位点差',\n    `level`             tinyint(4)                   NOT NULL DEFAULT '1' COMMENT '服务等级分为 1,2,3',\n    `has_dcdr`          tinyint(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否开启 dcdr',\n    `open_srv`          varchar(255)                          DEFAULT NULL COMMENT '已开启的模板服务',\n    `disk_size`         decimal(10, 3)                        DEFAULT '-1.000' COMMENT '可用磁盘容量',\n    `health`            int(11)                               DEFAULT '-1' COMMENT '模版健康；-1 是 UNKNOW',\n    PRIMARY KEY (`id`),\n    KEY `idx_data_center` (`data_center`),\n    KEY `idx_is_active` (`is_active`),\n    KEY `idx_name` (`name`),\n    KEY `idx_project_id` (`project_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 25998\n  DEFAULT CHARSET = utf8 COMMENT ='逻辑索引模板表';\n\n-- ----------------------------\n-- Table structure for index_template_physical_info\n-- ----------------------------\nCREATE TABLE `index_template_physical_info`\n(\n    `id`            bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `logic_id`      int(10)             NOT NULL DEFAULT '-1' COMMENT '逻辑模板 id',\n    `name`          varchar(128)        NOT NULL DEFAULT '' COMMENT ' 模板名字 ',\n    `expression`    varchar(128)        NOT NULL DEFAULT '' COMMENT ' 表达式 ',\n    `cluster`       varchar(128)        NOT NULL DEFAULT '' COMMENT ' 集群名字 ',\n    `rack`          varchar(512)        NOT NULL DEFAULT '' COMMENT 'rack',\n    `shard`         int(10)             NOT NULL DEFAULT '1' COMMENT 'shard 个数',\n    `shard_routing` int(10)             NOT NULL DEFAULT '1' COMMENT '内核的逻辑 shard',\n    `version`       int(10)             NOT NULL DEFAULT '0' COMMENT '版本',\n    `role`          tinyint(4)          NOT NULL DEFAULT '1' COMMENT '角色 1master 2slave',\n    `status`        tinyint(4)          NOT NULL DEFAULT '1' COMMENT '1 常规 -1 索引删除中 -2 已删除',\n    `config`        text COMMENT '配置 json 格式',\n    `create_time`   timestamp           NULL     DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`   timestamp           NULL     DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `region_id`     int(10)             NOT NULL DEFAULT '-1' COMMENT '模板关联的 regionId',\n    PRIMARY KEY (`id`),\n    KEY `idx_cluster_name_status` (`cluster`, `name`, `status`),\n    KEY `idx_log_id_statud` (`logic_id`, `status`),\n    KEY `idx_logic_id` (`logic_id`),\n    KEY `idx_region_id` (`region_id`),\n    KEY `idx_status` (`status`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 23700\n  DEFAULT CHARSET = utf8 COMMENT ='物理模板信息';\n\n-- ----------------------------\n-- Table structure for index_template_type\n-- ----------------------------\nCREATE TABLE `index_template_type`\n(\n    `id`                  bigint(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `index_template_id`   int(10)             NOT NULL DEFAULT '-1' COMMENT '索引模板 id',\n    `index_template_name` varchar(100)        NOT NULL DEFAULT '' COMMENT ' 索引模板名称 ',\n    `name`                varchar(100)        NOT NULL DEFAULT '' COMMENT 'type 名称 ',\n    `id_field`            varchar(128)        NOT NULL DEFAULT '' COMMENT 'id 字段 ',\n    `routing`             varchar(100)        NOT NULL DEFAULT '' COMMENT 'routing 字段 ',\n    `source`              tinyint(4)          NOT NULL DEFAULT '1' COMMENT '0 不存 source 1 存 source',\n    `is_active`           tinyint(2)          NOT NULL DEFAULT '1' COMMENT '是否激活 1 是 0 否',\n    `create_time`         timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`         timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='索引模板 type';\n\n-- ----------------------------\n-- Table structure for logi_job\n-- ----------------------------\nCREATE TABLE `logi_job`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `job_code`    varchar(100) NOT NULL DEFAULT '' COMMENT 'task taskCode',\n    `task_code`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务 code',\n    `class_name`  varchar(255) NOT NULL DEFAULT '' COMMENT ' 类的全限定名 ',\n    `try_times`   int(10)      NOT NULL DEFAULT '0' COMMENT '第几次重试',\n    `worker_code` varchar(200) NOT NULL DEFAULT '' COMMENT ' 执行机器 ',\n    `app_name`    varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `start_time`  datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '开始时间',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `job_code` (`job_code`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 381677\n  DEFAULT CHARSET = utf8 COMMENT ='正在执行的 job 信息';\n\n-- ----------------------------\n-- Table structure for logi_job_log\n-- ----------------------------\nCREATE TABLE `logi_job_log`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `job_code`    varchar(100) NOT NULL DEFAULT '' COMMENT 'job taskCode',\n    `task_code`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务 code',\n    `task_name`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务名称 ',\n    `task_desc`   varchar(255) NOT NULL DEFAULT '' COMMENT ' 任务描述 ',\n    `task_id`     bigint(20)   NOT NULL DEFAULT '0' COMMENT '任务 id',\n    `class_name`  varchar(255) NOT NULL DEFAULT '' COMMENT ' 类的全限定名 ',\n    `try_times`   int(10)      NOT NULL DEFAULT '0' COMMENT '第几次重试',\n    `worker_code` varchar(200) NOT NULL DEFAULT '' COMMENT ' 执行机器 ',\n    `worker_ip`   varchar(200) NOT NULL DEFAULT '' COMMENT ' 执行机器 ip',\n    `start_time`  datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '开始时间',\n    `end_time`    datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '结束时间',\n    `status`      tinyint(4)   NOT NULL DEFAULT '0' COMMENT '执行结果 1 成功 2 失败 3 取消',\n    `error`       text         NOT NULL COMMENT '错误信息',\n    `result`      text         NOT NULL COMMENT '执行结果',\n    `app_name`    varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_job_code` (`job_code`) USING BTREE\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 381395\n  DEFAULT CHARSET = utf8 COMMENT ='job 执行历史日志';\n\n\n\n-- ----------------------------\n-- Table structure for logi_task\n-- ----------------------------\nCREATE TABLE `logi_task`\n(\n    `id`              bigint(20)    NOT NULL AUTO_INCREMENT,\n    `task_code`       varchar(100)  NOT NULL DEFAULT '' COMMENT 'task taskCode',\n    `task_name`       varchar(255)  NOT NULL DEFAULT '' COMMENT ' 名称 ',\n    `task_desc`       varchar(1000) NOT NULL DEFAULT '' COMMENT ' 任务描述 ',\n    `cron`            varchar(100)  NOT NULL DEFAULT '' COMMENT 'cron 表达式 ',\n    `class_name`      varchar(255)  NOT NULL DEFAULT '' COMMENT ' 类的全限定名 ',\n    `params`          varchar(1000) NOT NULL DEFAULT '' COMMENT ' 执行参数 map 形式 {key1:value1,key2:value2}',\n    `retry_times`     int(10)       NOT NULL DEFAULT '0' COMMENT '允许重试次数',\n    `last_fire_time`  datetime               DEFAULT CURRENT_TIMESTAMP COMMENT '上次执行时间',\n    `timeout`         bigint(20)    NOT NULL DEFAULT '0' COMMENT '超时 毫秒',\n    `status`          tinyint(4)    NOT NULL DEFAULT '0' COMMENT '1 等待 2 运行中 3 暂停',\n    `sub_task_codes`  varchar(1000) NOT NULL DEFAULT '' COMMENT ' 子任务 code 列表, 逗号分隔 ',\n    `consensual`      varchar(200)  NOT NULL DEFAULT '' COMMENT ' 执行策略 ',\n    `owner`           varchar(200)  NOT NULL DEFAULT '' COMMENT ' 责任人 ',\n    `task_worker_str` varchar(3000) NOT NULL DEFAULT '' COMMENT ' 机器执行信息 ',\n    `app_name`        varchar(100)  NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `node_name_white_list_str` VARCHAR(3000) DEFAULT '' NOT NULL COMMENT '执行节点名对应白名单集',\n    `create_time`     datetime               DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`     datetime               DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `task_code` (`task_code`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 548\n  DEFAULT CHARSET = utf8 COMMENT ='任务信息';\n\n-- ----------------------------\n-- Table structure for logi_task_lock\n-- ----------------------------\nCREATE TABLE `logi_task_lock`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `task_code`   varchar(100) NOT NULL DEFAULT '' COMMENT 'task taskCode',\n    `worker_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n    `app_name`    varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `expire_time` bigint(20)   NOT NULL DEFAULT '0' COMMENT '过期时间',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `uni_task_app` (`task_code`, `app_name`) USING BTREE\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 569\n  DEFAULT CHARSET = utf8 COMMENT ='任务锁';\n\n-- ----------------------------\n-- Table structure for logi_worker\n-- ----------------------------\nCREATE TABLE `logi_worker`\n(\n    `id`              bigint(20)   NOT NULL AUTO_INCREMENT,\n    `worker_code`     varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n    `worker_name`     varchar(100) NOT NULL DEFAULT '' COMMENT 'worker 名 ',\n    `ip`              varchar(100) NOT NULL DEFAULT '' COMMENT 'worker 的 ip',\n    `cpu`             int(11)      NOT NULL DEFAULT '0' COMMENT 'cpu 数量',\n    `cpu_used`        double       NOT NULL DEFAULT '0' COMMENT 'cpu 使用率',\n    `memory`          double       NOT NULL DEFAULT '0' COMMENT '内存, 以 M 为单位',\n    `memory_used`     double       NOT NULL DEFAULT '0' COMMENT '内存使用率',\n    `jvm_memory`      double       NOT NULL DEFAULT '0' COMMENT 'jvm 堆大小，以 M 为单位',\n    `jvm_memory_used` double       NOT NULL DEFAULT '0' COMMENT 'jvm 堆使用率',\n    `job_num`         int(10)      NOT NULL DEFAULT '0' COMMENT '正在执行 job 数',\n    `heartbeat`       datetime              DEFAULT '1971-01-01 00:00:00' COMMENT '心跳时间',\n    `app_name`        varchar(100) NOT NULL DEFAULT '' COMMENT ' 被调度的应用名称 ',\n    `create_time`     datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`     datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `node_name`     VARCHAR(100) DEFAULT '' NOT NULL COMMENT 'node 名',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `worker_code` (`worker_code`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 8\n  DEFAULT CHARSET = utf8 COMMENT ='worker 信息';\n\n-- ----------------------------\n-- Table structure for logi_worker_blacklist\n-- ----------------------------\nCREATE TABLE `logi_worker_blacklist`\n(\n    `id`          bigint(20)   NOT NULL AUTO_INCREMENT,\n    `worker_code` varchar(100) NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n    `create_time` datetime              DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` datetime              DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    UNIQUE KEY `worker_code` (`worker_code`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='worker 黑名单列表';\n\n-- ----------------------------\n-- Table structure for operate_record_info\n-- ----------------------------\nCREATE TABLE `operate_record_info`\n(\n    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n    `project_name`   varchar(255)                 DEFAULT NULL COMMENT '应用',\n    `module_id`      int(10)             NOT NULL DEFAULT '-1' COMMENT '模块 id',\n    `operate_id`     int(10)             NOT NULL DEFAULT '-1' COMMENT '操作 id',\n    `trigger_way_id` int(11)                      DEFAULT NULL COMMENT '触发方式',\n    `user_operation` varchar(50)         NOT NULL DEFAULT '' COMMENT ' 操作人 ',\n    `content`        longtext COMMENT '操作内容',\n    `operate_time`   timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',\n    `create_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`    timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `biz_id`         varchar(255)                 DEFAULT NULL,\n    PRIMARY KEY (`id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 8218\n  DEFAULT CHARSET = utf8 COMMENT ='操作记录表';\n\n\n-- ----------------------------\n-- Table structure for project_arius_resource_logic\n-- ----------------------------\nCREATE TABLE `project_arius_resource_logic`\n(\n    `id`                 bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `name`               varchar(128)        NOT NULL DEFAULT '' COMMENT ' 资源名称 ',\n    `type`               tinyint(4)          NOT NULL DEFAULT '2' COMMENT '资源类型 1 共享公共资源 2 独享资源',\n    `project_id`         varchar(1024)       NOT NULL DEFAULT '-1' COMMENT '资源所属的 project_id',\n    `data_center`        varchar(20)         NOT NULL DEFAULT '' COMMENT ' 数据中心 cn/us01',\n    `responsible`        varchar(128)                 DEFAULT '' COMMENT ' 资源责任人 ',\n    `memo`               varchar(512)        NOT NULL DEFAULT '' COMMENT ' 资源备注 ',\n    `quota`              decimal(8, 2)       NOT NULL DEFAULT '1.00' COMMENT '资源的大小',\n    `level`              tinyint(4)          NOT NULL DEFAULT '1' COMMENT '服务等级 1 normal 2 important 3 vip',\n    `config_json`        varchar(1024)       NOT NULL DEFAULT '' COMMENT ' 集群配置 ',\n    `create_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`        timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    `health`             tinyint(4)          NOT NULL DEFAULT '3' COMMENT '集群状态 1 green 2 yellow 3 red -1 未知',\n    `data_node_spec`     varchar(20)         NOT NULL DEFAULT '' COMMENT ' 节点规格 ',\n    `disk_total`         bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘总量 单位 byte',\n    `disk_usage`         bigint(50)          NOT NULL DEFAULT '0' COMMENT '集群磁盘使用量 单位 byte',\n    `disk_usage_percent` decimal(10, 5)      default NULL COMMENT '集群磁盘空闲率 单位 0 ~1',\n    `es_cluster_version` varchar(20)         default NULL COMMENT 'es 集群版本',\n    `node_num`           int(10)             NOT NULL DEFAULT '0' COMMENT '节点个数',\n    `data_node_num`      int(10)             NOT NULL DEFAULT '0' COMMENT '节点个数',\n    PRIMARY KEY (`id`),\n    KEY `idx_name` (`name`),\n    KEY `idx_project_id` (`project_id`)\n) ENGINE = InnoDB\n  AUTO_INCREMENT = 3922\n  DEFAULT CHARSET = utf8 COMMENT ='逻辑资源信息';\n\n-- ----------------------------\n-- Table structure for project_logi_cluster_auth\n-- ----------------------------\nCREATE TABLE `project_logi_cluster_auth`\n(\n    `id`               bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `project_id`       int(10)             NOT NULL DEFAULT '-1' COMMENT '项目 id',\n    `logic_cluster_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '逻辑集群 id',\n    `type`             int(10)             NOT NULL DEFAULT '-1' COMMENT '权限类型，0- 超管，1- 配置管理，2- 访问，-1- 无权限',\n    `responsible`      varchar(100)                 DEFAULT '' COMMENT ' 责任人 id 列表 ',\n    `status`           int(10)             NOT NULL DEFAULT '1' COMMENT '状态 1 有效 0 无效',\n    `create_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time`      timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_project_id` (`project_id`),\n    KEY `idx_logic_cluster_id` (`logic_cluster_id`),\n    KEY `idx_status` (`status`),\n    KEY `idx_type` (`type`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='project 逻辑集群权限';\n\n-- ----------------------------\n-- Table structure for project_template_info\n-- ----------------------------\nCREATE TABLE `project_template_info`\n(\n    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `project_id`  int(10)             NOT NULL DEFAULT '-1' COMMENT '项目 id',\n    `template`    varchar(100)        NOT NULL DEFAULT '' COMMENT ' 模板名称, 不能关联模板 id 模板会跨集群迁移，id 会变 ',\n    `type`        int(10)             NOT NULL DEFAULT '-1' COMMENT 'appid 的权限 1 读写 2 读 -1 未知',\n    `status`      int(10)             NOT NULL DEFAULT '1' COMMENT '状态 1 有效 0 无效',\n    `create_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` timestamp           NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n    PRIMARY KEY (`id`),\n    KEY `idx_project_id` (`project_id`),\n    KEY `idx_status` (`status`),\n    KEY `idx_template_id` (`template`),\n    KEY `idx_type` (`type`)\n) ENGINE = InnoDB\n  DEFAULT CHARSET = utf8 COMMENT ='project 模板信息';\n\n-- ----------------------------\n-- Table structure for user_metrics_config_info\n-- ----------------------------\nCREATE TABLE `user_metrics_config_info` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `user_name` varchar(255) NOT NULL COMMENT '用户账号',\n  `metric_info` text COMMENT '指标看板的配置',\n  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=1602 DEFAULT CHARSET=utf8 COMMENT='用户关联到指标的配置信息表';\n\n\n#权限点和角色的初始化数据\ninsert into kf_security_role_permission (id, role_id, permission_id, create_time, update_time, is_delete, app_name)\nvalues (1597, 1, 0, '2022-06-01 21:19:42.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1935, 1, 1593, '2022-06-14 17:41:03.0', '2022-08-27 17:36:58.0', 0, 'know_search'),\n       (1937, 1, 1637, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1939, 1, 1639, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1941, 1, 1641, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1943, 1, 1643, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1945, 1, 1645, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1947, 1, 1647, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1949, 1, 1649, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1951, 1, 1651, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1953, 1, 1653, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1955, 1, 1655, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1957, 1, 1657, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1959, 1, 1659, '2022-06-14 17:41:03.0', '2022-08-25 10:33:59.0', 1, 'know_search'),\n       (1961, 1, 1661, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1963, 1, 1597, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1965, 1, 1673, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1967, 1, 1675, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1969, 1, 1677, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1971, 1, 1679, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1973, 1, 1599, '2022-06-14 17:41:03.0', '2022-08-25 10:36:08.0', 1, 'know_search'),\n       (1975, 1, 1681, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1977, 1, 1683, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1979, 1, 1685, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1981, 1, 1687, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1983, 1, 1601, '2022-06-14 17:41:03.0', '2022-08-25 10:36:44.0', 1, 'know_search'),\n       (1985, 1, 1689, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1987, 1, 1691, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1989, 1, 1693, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1991, 1, 1695, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1993, 1, 1697, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1995, 1, 1699, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1997, 1, 1603, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (1999, 1, 1701, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2001, 1, 1703, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2003, 1, 1705, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2005, 1, 1707, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2007, 1, 1709, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2009, 1, 1711, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2011, 1, 1713, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2013, 1, 1715, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2015, 1, 1717, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2017, 1, 1719, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2019, 1, 1721, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2021, 1, 1723, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2023, 1, 1605, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2025, 1, 1725, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2027, 1, 1727, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2029, 1, 1729, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2031, 1, 1731, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2033, 1, 1733, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2035, 1, 1735, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2037, 1, 1737, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2039, 1, 1739, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2041, 1, 1741, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2043, 1, 1743, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2045, 1, 1607, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2047, 1, 1745, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2049, 1, 1747, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2051, 1, 1749, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2053, 1, 1751, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2055, 1, 1753, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2057, 1, 1755, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2059, 1, 1609, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2061, 1, 1757, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2063, 1, 1855, '2022-06-14 17:41:03.0', '2022-08-25 10:34:13.0', 0, 'know_search'),\n       (2065, 1, 1857, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2067, 1, 1611, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2069, 1, 1759, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2071, 1, 1859, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2073, 1, 1861, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2075, 1, 1863, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2077, 1, 1865, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2079, 1, 1867, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2081, 1, 1613, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2083, 1, 1761, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2085, 1, 1615, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2087, 1, 1763, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2089, 1, 1619, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2091, 1, 1769, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2093, 1, 1771, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2095, 1, 1773, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2097, 1, 1621, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2099, 1, 1775, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2101, 1, 1777, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2103, 1, 1779, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2105, 1, 1781, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2107, 1, 1783, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2109, 1, 1785, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2111, 1, 1787, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2113, 1, 1789, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2115, 1, 1791, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2117, 1, 1793, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2119, 1, 1795, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2121, 1, 1797, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2123, 1, 1799, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2125, 1, 1801, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2127, 1, 1623, '2022-06-14 17:41:03.0', '2022-08-27 17:34:08.0', 0, 'know_search'),\n       (2129, 1, 1803, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2131, 1, 1805, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2133, 1, 1807, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2135, 1, 1809, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2137, 1, 1625, '2022-06-14 17:41:03.0', '2022-08-27 17:34:08.0', 0, 'know_search'),\n       (2139, 1, 1811, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2141, 1, 1813, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2143, 1, 1815, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2145, 1, 1817, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2147, 1, 1627, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2149, 1, 1819, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2151, 1, 1821, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2153, 1, 1629, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2155, 1, 1823, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2157, 1, 1825, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2159, 1, 1827, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2161, 1, 1829, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2163, 1, 1831, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2165, 1, 1631, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2167, 1, 1833, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2169, 1, 1835, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2171, 1, 1837, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2173, 1, 1839, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2175, 1, 1841, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2177, 1, 1633, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2179, 1, 1843, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2181, 1, 1845, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2183, 1, 1847, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2185, 1, 1849, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2187, 1, 1851, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2189, 1, 1635, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2191, 1, 1853, '2022-06-14 17:41:03.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2193, 2, 1595, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2195, 2, 1663, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2197, 2, 1665, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2199, 2, 1667, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2201, 2, 1669, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2203, 2, 1671, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2205, 2, 1601, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2207, 2, 1689, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2209, 2, 1691, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2211, 2, 1693, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2213, 2, 1695, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2215, 2, 1697, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2217, 2, 1699, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2219, 2, 1605, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2221, 2, 1725, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2223, 2, 1727, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2225, 2, 1729, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2227, 2, 1731, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2229, 2, 1733, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2231, 2, 1735, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2233, 2, 1737, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2235, 2, 1739, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2237, 2, 1741, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2239, 2, 1743, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2241, 2, 1609, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2243, 2, 1757, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2245, 2, 1855, '2022-06-14 18:08:56.0', '2022-08-25 10:33:12.0', 1, 'know_search'),\n       (2247, 2, 1857, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2249, 2, 1611, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2251, 2, 1759, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2253, 2, 1859, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2255, 2, 1861, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2257, 2, 1863, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2259, 2, 1865, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2261, 2, 1867, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2263, 2, 1613, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2265, 2, 1761, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2267, 2, 1615, '2022-06-14 18:08:56.0', '2022-08-25 20:27:55.0', 1, 'know_search'),\n       (2269, 2, 1763, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2271, 2, 1617, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2273, 2, 1765, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2275, 2, 1767, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2277, 2, 1631, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2279, 2, 1833, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2281, 2, 1835, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2283, 2, 1837, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2285, 2, 1839, '2022-06-14 18:08:56.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (2287, 2, 1841, '2022-06-14 18:08:56.0', '2022-08-26 17:59:49.0', 1, 'know_search'),\n       (2643, 1, 1595, '2022-06-17 16:39:23.0', '2022-08-25 10:35:06.0', 1, 'know_search'),\n       (4505, 1, 1869, '2022-07-04 15:45:59.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (4507, 1, 1871, '2022-07-04 15:46:56.0', '2022-08-27 17:37:22.0', 0, 'know_search'),\n       (5275, 1, 1873, '2022-06-17 15:53:54.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5277, 2, 1873, '2022-06-17 15:53:54.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5349, 1, 1875, '2022-06-17 15:53:54.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5591, 1, 1759, '2022-08-11 10:39:01.0', '2022-08-25 10:31:42.0', 0, 'know_search'),\n       (5593, 2, 1759, '2022-08-11 10:39:59.0', '2022-08-25 10:31:42.0', 0, 'know_search');\n#权限点初始化数据\ninsert into kf_security_permission (id, permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name)\nvalues  (1593, '物理集群', 0, 0, 1, '物理集群', '2022-05-24 18:08:22.0', '2022-08-24 20:07:31.0', 0, 'know_search'),\n        (1595, '我的集群', 0, 0, 1, '我的集群', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1597, '集群版本', 0, 0, 1, '集群版本', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1599, 'Gateway管理', 0, 0, 1, 'Gateway管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1601, '模板管理', 0, 0, 1, '模板管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1603, '模板服务', 0, 0, 1, '模板服务', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1605, '索引管理', 0, 0, 1, '索引管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1607, '索引服务', 0, 0, 1, '索引服务', '2022-05-24 18:08:22.0', '2022-05-24 18:24:16.0', 0, 'know_search'),\n        (1609, '索引查询', 0, 0, 1, '索引查询', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1611, '查询诊断', 0, 0, 1, '查询诊断', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1613, '集群看板', 0, 0, 1, '集群看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1615, '网关看板', 0, 0, 1, '网关看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1617, '我的申请', 0, 0, 1, '我的申请', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1619, '我的审批', 0, 0, 1, '我的审批', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1621, '任务列表', 0, 0, 1, '任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1623, '调度任务列表', 0, 0, 1, '调度任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1625, '调度日志', 0, 0, 1, '调度日志', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1627, '用户管理', 0, 0, 1, '用户管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1629, '角色管理', 0, 0, 1, '角色管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1631, '应用管理', 0, 0, 1, '应用管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1633, '平台配置', 0, 0, 1, '平台配置', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1635, '操作记录', 0, 0, 1, '操作记录', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1637, '查看集群列表及详情', 1593, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1639, '接入集群', 1593, 1, 2, '接入集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1641, '新建集群', 1593, 1, 2, '新建集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1643, '扩缩容', 1593, 1, 2, '扩缩容', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1645, '升级', 1593, 1, 2, '升级', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1647, '重启', 1593, 1, 2, '重启', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1649, '配置变更', 1593, 1, 2, '配置变更', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1651, 'Region划分', 1593, 1, 2, 'Region划分', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1653, 'Region管理', 1593, 1, 2, 'Region管理', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1655, '快捷命令', 1593, 1, 2, '快捷命令', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1657, '编辑', 1593, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1659, '绑定Gateway', 1593, 1, 2, '绑定Gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1661, '下线', 1593, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1663, '查看集群列表及详情', 1595, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1665, '申请集群', 1595, 1, 2, '申请集群', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1667, '编辑', 1595, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1669, '扩缩容', 1595, 1, 2, '扩缩容', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1671, '下线', 1595, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1673, '查看版本列表', 1597, 1, 2, '查看版本列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1675, '新增版本', 1597, 1, 2, '新增版本', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1677, '编辑', 1597, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1679, '删除', 1597, 1, 2, '删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1681, '查看Gateway 集群列表', 1599, 1, 2, '查看Gateway 集群列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1683, '接入gateway', 1599, 1, 2, '接入gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1685, '编辑', 1599, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1687, '下线', 1599, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1689, '查看模板列表及详情', 1601, 1, 2, '查看模板列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1691, '申请模板', 1601, 1, 2, '申请模板', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1693, '编辑', 1601, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1695, '下线', 1601, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1697, '编辑Mapping', 1601, 1, 2, '编辑Mapping', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1699, '编辑Setting', 1601, 1, 2, '编辑Setting', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1701, '查看模板列表', 1603, 1, 2, '查看模板列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1703, '开关：预创建', 1603, 1, 2, '开关：预创建', '2022-05-24 18:08:23.0', '2022-06-14 16:49:48.0', 0, 'know_search'),\n        (1705, '开关：过期删除', 1603, 1, 2, '开关：过期删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1707, '开关：冷热分离', 1603, 1, 2, '开关：冷热分离', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1709, '开关：pipeline', 1603, 1, 2, '开关：写入限流', '2022-05-24 18:08:23.0', '2022-06-14 16:49:49.0', 0, 'know_search'),\n        (1711, '开关：Rollover', 1603, 1, 2, '开关：Rollover', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1713, '查看DCDR链路', 1603, 1, 2, '查看DCDR链路', '2022-05-24 18:08:23.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1715, '创建DCDR链路', 1603, 1, 2, '创建DCDR链路', '2022-05-24 18:08:24.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1717, '清理', 1603, 1, 2, '清理', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1719, '扩缩容', 1603, 1, 2, '扩缩容', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1721, '升版本', 1603, 1, 2, '升版本', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1723, '批量操作', 1603, 1, 2, '批量操作', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1725, '查看索引列表及详情', 1605, 1, 2, '查看索引列表及详情', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1727, '编辑Mapping', 1605, 1, 2, '编辑Mapping', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1729, '编辑Setting', 1605, 1, 2, '编辑Setting', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1731, '禁用读', 1607, 1, 2, '禁用读', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1733, '禁用写', 1607, 1, 2, '禁用写', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1735, '设置别名', 1605, 1, 2, '设置别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1737, '删除别名', 1605, 1, 2, '删除别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1739, '关闭索引', 1607, 1, 2, '关闭索引', '2022-05-24 18:08:24.0', '2022-07-15 09:52:25.0', 0, 'know_search'),\n        (1741, '下线', 1605, 1, 2, '下线', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1743, '批量删除', 1605, 1, 2, '批量删除', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1745, '查看列表', 1607, 1, 2, '查看列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1747, '执行Rollover', 1607, 1, 2, '执行Rollover', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1749, '执行shrink', 1607, 1, 2, '执行shrink', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1751, '执行split', 1607, 1, 2, '执行split', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1753, '执行ForceMerge', 1607, 1, 2, '执行ForceMerge', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1755, '批量执行', 1607, 1, 2, '批量执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1757, 'DSL查询', 1609, 1, 2, 'DSL查询', '2022-05-24 18:08:24.0', '2022-06-14 16:39:48.0', 0, 'know_search'),\n        (1759, '查询模板', 0, 0, 1, '查看查询模板列表', '2022-05-24 18:08:24.0', '2022-08-11 10:37:43.0', 0, 'know_search'),\n        (1761, '查看集群看板', 1613, 1, 2, '查看集群看板', '2022-05-24 18:08:24.0', '2022-06-14 16:37:54.0', 0, 'know_search'),\n        (1763, '查看网关看板', 1615, 1, 2, '查看网关看板', '2022-05-24 18:08:24.0', '2022-06-14 16:38:14.0', 0, 'know_search'),\n        (1765, '查看我的申请列表', 1617, 1, 2, '查看我的申请列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1767, '撤回', 1617, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1769, '查看我的审批列表', 1619, 1, 2, '查看我的审批列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1771, '驳回', 1619, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-07-18 20:57:33.0', 0, 'know_search'),\n        (1773, '通过', 1619, 1, 2, '通过', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1775, '查看任务列表', 1621, 1, 2, '查看任务列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1777, '查看进度', 1621, 1, 2, '查看进度', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1779, '执行', 1621, 1, 2, '执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1781, '暂停', 1621, 1, 2, '暂停', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1783, '重试', 1621, 1, 2, '重试', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1785, '取消', 1621, 1, 2, '取消', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1787, '查看日志（子任务）', 1621, 1, 2, '查看日志（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1789, '重试（子任务）', 1621, 1, 2, '重试（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1791, '忽略（子任务）', 1621, 1, 2, '忽略（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1793, '查看详情（DCDR）', 1621, 1, 2, '查看详情（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1795, '取消（DCDR）', 1621, 1, 2, '取消（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1797, '重试（DCDR）', 1621, 1, 2, '重试（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1799, '强切（DCDR）', 1621, 1, 2, '强切（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1801, '返回（DCDR）', 1621, 1, 2, '返回（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1803, '查看任务列表', 1623, 1, 2, '查看任务列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1805, '查看日志', 1623, 1, 2, '查看日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1807, '执行', 1623, 1, 2, '执行', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1809, '暂停', 1623, 1, 2, '暂停', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1811, '查看调度日志列表', 1625, 1, 2, '查看调度日志列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1813, '调度详情', 1625, 1, 2, '调度详情', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1815, '执行日志', 1625, 1, 2, '执行日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1817, '终止任务', 1625, 1, 2, '终止任务', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1819, '查看用户列表', 1627, 1, 2, '查看用户列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1821, '分配角色', 1627, 1, 2, '分配角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1823, '查看角色列表', 1629, 1, 2, '查看角色列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1825, '编辑', 1629, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1827, '绑定用户', 1629, 1, 2, '绑定用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1829, '回收用户', 1629, 1, 2, '回收用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1831, '删除角色', 1629, 1, 2, '删除角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1833, '查看应用列表', 1631, 1, 2, '查看应用列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1835, '新建应用', 1631, 1, 2, '新建应用', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1837, '编辑', 1631, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1839, '删除', 1631, 1, 2, '删除', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1841, '访问设置', 1631, 1, 2, '访问设置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1843, '查看平台配置列表', 1633, 1, 2, '查看平台配置列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1845, '新增平台配置', 1633, 1, 2, '新增平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1847, '禁用平台配置', 1633, 1, 2, '禁用平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1849, '编辑平台配置', 1633, 1, 2, '编辑平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1851, '删除平台配置', 1633, 1, 2, '删除平台配置', '2022-05-24 18:08:26.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1853, '查看操作记录列表', 1635, 1, 2, '查看操作记录列表', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1855, 'Kibana', 1609, 1, 2, 'Kibana', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 1, 'know_search'),\n        (1857, 'SQL查询', 1609, 1, 2, 'SQL查询', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1859, '批量修改限流值', 1759, 1, 2, '批量修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1861, '禁用', 1759, 1, 2, '禁用', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1863, '修改限流值', 1759, 1, 2, '修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1865, '查看异常查询列表', 1611, 1, 2, '查看异常查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1867, '查看慢查询列表', 1611, 1, 2, '查看慢查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:21.0', 0, 'know_search'),\n        (1869, '新增角色', 1629, 1, 2, '新增角色', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1871, 'Dashboard', 0, 0, 1, '查看dashboard', '2022-05-24 18:08:26.0', '2022-08-27 17:35:50.0', 0, 'know_search'),\n        (1873, '新建索引', 1605, 1, 2, '新建索引', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1875, '查看dashboard', 1871, 1, 2, '查看dashboard', '2022-05-24 18:08:24.0', '2022-08-27 17:35:50.0', 0,\n         'know_search');\n#角色初始化数据\ninsert into kf_security_role (id, role_code, role_name, description, last_reviser, create_time, update_time,\n                                is_delete, app_name)\nvalues (1, 'r14715628', '管理员', '管理员', 'admin', '2022-06-01 21:19:42.0', '2022-07-06 22:23:59.0', 0,\n        'know_search'),\n       (2, 'r14481382', '资源 owner', '普通用户拥有的最大权限', 'admin', '2022-06-14 18:08:56.0',\n        '2022-07-06 20:36:31.0', 0, 'know_search');\n#初始化用户\ninsert into kf_security_user (id, user_name, pw, salt, real_name, phone, email, dept_id, is_delete,\n                                create_time, update_time, app_name)\nvalues (1, 'admin',\n        'V1ZkU2RHRlhOSGhOYWs0M1VVWmFjVk5xVW1oaE0zUmlTVEJCZUZGRFRtUm1WVzh5VlcxNGMyRkZRamw3UUZacVNqUmhhM3RiSTBBeVFDTmRmVW8yVW14c2FFQjl7QFZqSjRha3tbI0AzQCNdfUo2UmxsaEB9Mv{#cdRgJ45Lqx}3IubEW87!==',\n        '', 'admin', '18888888888', 'admin@12345.com', null, 0, '2022-05-26 05:46:12.0', '2022-08-26 09:06:19.0',\n        'know_search');\n#初始化用户和角色的关系\ninsert into kf_security_user_role (id, user_id, role_id, create_time, update_time, is_delete, app_name)\nvalues (1, 1, 2, '2022-08-26 19:54:22.0', '2022-08-26 19:54:22.0', 0, 'know_search'),\n       (2, 1, 1, '2022-08-30 21:05:17.0', '2022-08-30 21:05:17.0', 0, 'know_search');\n#项目和项目配置、es user 的关系\ninsert into project_arius_config (project_id, analyze_response_enable, is_source_separated, aggr_analyze_enable,\n                                  dsl_analyze_enable, slow_query_times, is_active, memo, create_time, update_time)\nvalues (1, 1, 0, 1, 1, 1000, 1, '超级应用', '2022-06-14 18:52:08.0', '2022-08-27 23:13:14.0'),\n       (2, 1, 0, 1, 1, 1000, 1, '元数据模版应用 不可以被删除', '2022-08-25 11:18:45.0', '2022-08-25 11:18:45.0');\ninsert into kf_security_project (id, project_code, project_name, description, dept_id, running, create_time,\n                                   update_time, is_delete, app_name)\nvalues (1, 'p14000143', 'SuperApp', '超级应用', 0, 1, '2022-05-26 05:49:08.0', '2022-08-24 11:09:49.0', 0,\n        'know_search'),\n       (2, 'p18461793', '元数据模版应用_误删', '元数据模版应用 不可以被删除', 0, 1, '2022-08-25 11:06:04.0',\n        '2022-08-25 11:18:45.0', 0, 'know_search');\ninsert into arius_es_user (id, index_exp, data_center, is_root, memo, ip, verify_code, is_active,\n                           query_threshold, cluster, responsible, search_type, create_time, update_time,\n                           project_id, is_default_display)\nvalues (1, null, 'cn', 1, '管理员 APP', '', 'azAWiJhxkho33ac', 1, 100, '',\n        'admin', 1,\n        '2022-05-26 09:35:38.0', '2022-06-23 00:16:47.0', 1, 1),\n       (2, null, 'cn', 0, '元数据模版 APP', '', 'vkDgPEfD3jQJ1YY', 1, 1000, '', 'admin', 1, '2022-07-05 08:16:17.0',\n        '2022-08-25 21:48:58.0', 2, 1);\n\n\n## 配置初始化数据\nTRUNCATE  table `arius_config_info`;\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (187, 'arius.cache.switch', 'logic.template.cache.enable', 'true', 1, -1, -1, '逻辑模板缓存是否开启', '2021-09-01 20:37:47', '2021-11-29 14:57:47', '2021-09-01 20:37:47');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (189, 'arius.cache.switch', 'physical.template.cache.enable', 'true', 1, -1, -1, '获取物理模板列表是否开启全局缓存', '2021-09-01 20:41:22', '2021-11-29 14:57:45', '2021-09-01 20:41:22');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (191, 'arius.cache.switch', 'cluster.phy.cache.enable', 'true', 1, -1, -1, '获取物理集群列表是否开启全局缓存', '2021-09-01 20:42:31', '2021-11-29 14:57:42', '2021-09-01 20:42:31');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (193, 'arius.cache.switch', 'cluster.logic.cache.enable', 'true', 1, -1, -1, '获取逻辑集群列表是否开启全局缓存', '2021-09-01 20:43:08', '2021-11-29 14:57:39', '2021-09-01 20:43:08');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1217, 'arius.meta.monitor', 'nodestat.collect.concurrent', 'true', 1, -1, -1, '', '2021-11-18 20:24:54', '2021-11-19 16:05:39', '2021-11-18 20:24:54');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1223, 'arius.common.group', 'app.default.read.auth.indices', '\\\"\\\"', 1, -1, 2, 'app可读写的权限', '2021-12-15 20:17:06', '2021-12-16 11:17:26', '2021-12-15 20:17:06');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1225, 'arius.common.group', 'delete.expire.index.ahead.clusters', '\\\"\\\"', 1, -1, 2, '删除过期权限', '2021-12-15 20:17:48', '2021-12-16 11:17:24', '2021-12-15 20:17:48');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1227, 'arius.common.group', 'operate.index.ahead.seconds', '2 * 60 * 60', 1, -1, 2, '索引操作提前时间', '2021-12-15 20:18:37', '2021-12-16 11:17:22', '2021-12-15 20:18:37');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1229, 'arius.common.group', 'platform.govern.admin.hot.days', '-1', 1, -1, 2, '平台治理导入热存的天数', '2021-12-15 20:19:13', '2021-12-16 11:17:19', '2021-12-15 20:19:13');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1231, 'arius.common.group', 'quota.dynamic.limit.black.appIds', 'none', 1, -1, 2, 'appid黑名单控制', '2021-12-15 20:20:11', '2021-12-16 11:17:17', '2021-12-15 20:20:11');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1233, 'arius.common.group', 'quota.dynamic.limit.black.cluster', '\\\"\\\"', 1, -1, 2, 'cluster黑名单控制', '2021-12-15 20:20:39', '2021-12-16 11:17:15', '2021-12-15 20:20:39');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1235, 'arius.common.group', 'quota.dynamic.limit.black.logicId', 'none', 1, -1, 2, '模板黑名单控制', '2021-12-15 20:21:21', '2021-12-16 11:17:12', '2021-12-15 20:21:21');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1237, 'arius.common.group', 'arius.wo.auto.process.create.template.disk.maxG', '10.0', 1, -1, 2, '模板创建时设置的磁盘空间最大值', '2021-12-15 20:21:49', '2021-12-16 11:15:12', '2021-12-15 20:21:49');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1239, 'arius.common.group', 'request.interceptor.switch.open', 'true', 1, -1, 2, '请求拦截开关', '2021-12-15 20:22:14', '2021-12-16 11:15:10', '2021-12-15 20:22:14');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1241, 'arius.common.group', 'arius.didi.t2.leader.mail', '\\\"\\\"', 1, -1, 2, 'didi领导者邮箱', '2021-12-15 20:22:40', '2021-12-16 11:15:07', '2021-12-15 20:22:40');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1243, 'arius.common.group', 'defaultDay', '\\\"\\\"', 1, -1, 2, '默认hotDay值', '2021-12-15 20:23:17', '2021-12-16 11:15:04', '2021-12-15 20:23:17');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1245, 'arius.quota.config.group', 'arius.quota.config.tps.per.cpu.with.replica', '1000.0', 1, -1, 2, '资源管控cpu项', '2021-12-15 20:23:56', '2021-12-16 11:15:01', '2021-12-15 20:23:56');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1247, 'arius.quota.config.group', 'arius.quota.config.tps.per.cpu.NO.replica', '2300.0', 1, -1, 2, '资源管控cpu项', '2021-12-15 20:24:27', '2021-12-16 11:14:58', '2021-12-15 20:24:27');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1249, 'arius.quota.config.group', 'arius.quota.config.cost.per.g.per.month', '1.06', 1, -1, 2, '资源配置模板费用', '2021-12-15 20:24:59', '2021-12-16 11:14:56', '2021-12-15 20:24:59');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1251, 'arius.meta.monitor.group', 'nodestat.collect.concurrent', 'fasle', 1, -1, 2, '节点状态信息是否并行采集', '2021-12-15 20:25:35', '2022-08-26 18:10:50', '2021-12-15 20:25:35');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1253, 'arius.meta.monitor.group', 'indexstat.collect.concurrent', 'fasle', 1, -1, 2, '索引状态信息是否并行采集', '2021-12-15 20:26:00', '2022-08-26 18:10:45', '2021-12-15 20:26:00');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1255, 'arius.common.group', 'indices.recovery.ceph_max_bytes_per_sec', '10MB', 1, -1, 2, '单节点分片恢复的速率', '2021-12-15 21:33:29', '2022-04-08 17:43:14', '2021-12-15 21:33:29');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1257, 'arius.common.group', 'cluster.routing.allocation.node_concurrent_incoming_recoveries', '2', 1, -1, 2, '一个节点上允许多少并发的传入分片还原,表示为传入还原', '2021-12-16 14:41:51', '2021-12-16 14:42:24', '2021-12-16 14:41:51');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1259, 'arius.common', 'cluster.routing.allocation.node_concurrent_outgoing_recoveries', '2', 1, -1, 2, '一个节点上允许多少并发的传入分片还原,传出还原', '2021-12-16 14:42:15', '2022-02-22 11:11:48', '2021-12-16 14:42:15');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1585, 'test.test', 'testt', '21', 1, -1, -1, '请忽略2221', '2022-01-13 14:25:40', '2022-01-15 16:27:05', '2022-01-13 14:25:40');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1587, 'zptest', 'test', '<script>alert(1)</script>', 1, -1, -1, 'alert(1)', '2022-01-18 16:14:12', '2022-01-18 16:15:49', '2022-01-18 16:14:12');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1589, 'test1ddd', 'dd ddd', 'dssdddd', 1, -1, -1, 'sddsdssd', '2022-01-26 11:39:23', '2022-01-26 11:39:42', '2022-01-26 11:39:23');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1591, 'yyftemptest-01s', 'yyftemptest-01d', '', 1, -1, -1, '', '2022-03-01 16:44:12', '2022-03-01 16:44:39', '2022-03-01 16:44:12');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1593, 'test1', 's', '', 1, -1, -1, '', '2022-03-07 11:37:39', '2022-03-07 11:37:43', '2022-03-07 11:37:39');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1595, 'test1', '22', 'm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2wsx3edc4rfv5tgb6yhn7ujm1qaz2', 1, -1, -1, '', '2022-03-15 11:19:49', '2022-03-15 11:20:08', '2022-03-15 11:19:49');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1623, 'settingGroup', 'name', 'value', 1, -1, -1, 'test', '2022-06-23 14:17:56', '2022-06-23 15:47:26', '2022-06-23 14:17:56');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1625, 'group11', 'name1', 'value1', 1, -1, -1, 'des-edit', '2022-06-23 15:22:51', '2022-06-24 09:40:51', '2022-06-23 15:22:51');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1627, 'arius.common.group', 'cluster.node.specification_list', '16c-64g-3072g,16c-48g-3071g,1c-48g-3071g,', 1, -1, 1, '节点规格列表，机型列表', '2022-07-05 14:10:27', '2022-07-18 15:01:29', '2022-07-05 14:10:27');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1629, 'ccccccccccccccdcdccccccccccccccdcdccccccccccccccdb', 'dccccccccccccccdcdcccccccc', 'vjh', 1, -1, -1, 'cdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccccccccccccdcdccccc', '2022-07-05 15:27:38', '2022-07-05 15:28:09', '2022-07-05 15:27:38');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1631, '2', '3', '', 1, -1, -1, '', '2022-07-06 15:26:45', '2022-07-06 15:26:58', '2022-07-06 15:26:45');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1633, 'arius.common.group', 'cluster.data.center_list', 'cn,en', 1, -1, 1, '数据中心列表', '2022-07-06 16:14:03', '2022-08-27 19:11:25', '2022-07-06 16:14:03');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1635, 'arius.common.group', 'cluster.package.version_list', '7.6.1.1,6.6.6.6,7.6.1.2', 1, -1, 1, '系统预制支持的版本', '2022-07-06 16:17:25', '2022-07-06 16:17:25', '2022-07-06 16:17:25');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1637, 'template.time.type', 'format', '[\\n  \\\"yyyy-MM-dd HH:mm:ss\\\",\\n  \\\"yyyy-MM-dd HH:mm:ss.SSS\\\",\\n  \\\"yyyy-MM-dd\\'T\\'HH:mm:ss\\\",\\n  \\\"yyyy-MM-dd\\'T\\'HH:mm:ss.SSS\\\",\\n  \\\"yyyy-MM-dd HH:mm:ss.SSS Z\\\",\\n  \\\"yyyy/MM/dd HH:mm:ss\\\",\\n  \\\"epoch_seconds\\\",\\n  \\\"epoch_millis\\\"\\n]', 1, -1, 1, '新建模版的时间格式', '2022-07-07 16:15:37', '2022-07-07 16:15:37', '2022-07-07 16:15:37');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1639, 'arius.cluster.blacklist', 'cluster.phy.name', 'didi-cluster-test', 1, -1, 1, '滴滴内部测试环境集群, 禁止任何编辑删除新增操作', '2022-07-07 17:58:02', '2022-07-07 18:44:42', '2022-07-07 17:58:02');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1641, 'arius.common.group', 'cluster.resource.type_list', '信创,acs,vmware', 1, -1, 1, '所属资源类型列表,IaaS平台类型列表', '2022-07-07 19:13:13', '2022-08-31 16:38:37', '2022-07-07 19:13:13');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1643, '55', '666', '1', 1, -1, -1, '143', '2022-07-13 16:59:41', '2022-07-13 17:01:48', '2022-07-13 16:59:41');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1645, 'arius.common.group', 'index.rollover.threshold', '0.00001', 1, -1, 1, '主分片大小达到1G后升版本', '2022-07-15 21:03:12', '2022-09-22 15:28:54', '2022-07-15 21:03:12');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1647, 'yyftemptest-01', 'yyf', 'sdv', 1, -1, -1, 'sdv', '2022-07-18 15:02:08', '2022-07-18 15:02:24', '2022-07-18 15:02:08');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1649, 'arius.common.group', 'cluster.node.count_list', '2,4,6,10', 1, -1, 1, '集群节点个数列表', '2022-07-18 15:22:33', '2022-08-27 19:13:09', '2022-07-18 15:22:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1653, 'arius.common.group', 'arius.system.template', '[\\n    \\\"arius.dsl.analyze.result\\\",\\n    \\\"arius.dsl.metrics\\\",\\n    \\\"arius.dsl.template\\\",\\n    \\\"arius.gateway.join\\\",\\n    \\\"arius_stats_index_info\\\",\\n    \\\"arius_stats_node_info\\\",\\n    \\\"arius.template.access\\\",\\n    \\\"arius_cat_index_info\\\",\\n    \\\"arius_gateway_metrics\\\",\\n    \\\"arius_stats_cluster_info\\\",\\n    \\\"arius_stats_cluster_task_info\\\",\\n    \\\"arius_stats_dashboard_info\\\",\\n    \\\"arius.appid.template.access\\\"\\n]', 1, -1, 1, '系统核心模版集合', '2022-07-21 12:25:48', '2022-07-21 12:30:06', '2022-07-21 12:25:48');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1655, 'ds12', 'sd34', 'sdsddsd', 1, -1, -1, 'ds78', '2022-07-21 17:00:44', '2022-08-01 08:52:35', '2022-07-21 17:00:44');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1657, 'arius.common.group', 'cluster.shard.big_threshold', '10', 1, -1, 1, '用于设置集群看板中的大Shard阈值，单位为gb，大于这个值就认为是大shard', '2022-07-28 17:49:59', '2022-08-26 18:08:56', '2022-07-28 17:49:59');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1671, 'arius.template.group', 'logic.template.business_type', '系统数据,日志数据,业务上报数据,test_businesss_type1,RDS数据,离线导入数据,testset,123,test_businesss_type1', 1, -1, 1, '模板业务类型', '2022-08-26 18:02:47', '2022-09-01 15:16:11', '2022-08-26 18:02:47');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1673, 'arius.template.group', 'logic.template.time_format_list', 'yyyy-MM-dd HH:mm:ss,yyyy-MM-dd HH:mm:ss.SSS,yyyy-MM-dd HH:mm:ss.SSS Z,yyyy-MM-dd\\'T\\'HH:mm:ss,yyyy-MM-dd\\'T\\'HH:mm:ss.SSS,yyyy-MM-dd\\'T\\'HH:mm:ssZ,yyyy-MM-dd\\'T\\'HH:mm:ss.SSSZ,yyyy/MM/dd HH:mm:ss,epoch_second,epoch_millis,yyyy-MM-dd', 1, -1, 1, '模板时间格式列表', '2022-08-26 18:06:07', '2022-08-31 17:16:03', '2022-08-26 18:06:07');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1675, 'arius.template.group', 'history.template.physic.indices.allocation.is_effective', 'ture', 1, -1, 1, '历史索引模板shard分配是否自动调整', '2022-08-26 18:07:53', '2022-08-31 17:07:02', '2022-08-26 18:07:53');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1677, 'arius.common.group', 'operate.record.save.time', '29', 1, -1, -1, '操作记录的保存时间', '2022-09-01 16:44:03', '2022-09-01 17:23:48', '2022-09-01 16:44:03');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1679, 'arius.common.group', 'operate.record.save_time', '25', 1, -1, 1, '操作记录的保存时间(天)', '2022-09-01 19:34:33', '2022-09-19 15:14:59', '2022-09-01 19:34:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1681, 'arius.common.group', 'super_app.default.dsl.command', '#获取节点状态\\nGET _nodes/stats\\n\\n#获取集群信息\\nGET _cluster/stats\\n\\n#获取集群健康信息\\nGET _cluster/health?v\\n\\n#查看当前集群的热点线程\\nGET _nodes/hot_threads\\n\\n#查看当前集群运行中的任务信息\\nGET _tasks?actions=*&detailed\\n\\n#shard分配说明，会在分片未分配的事后去通过这个命令查看下具体原因\\nGET /_cluster/allocation/explain\\n\\n#异常shard分配重试，当集群red有shard未分配的情况下会通过这个命令来重试分配\\nPOST /_cluster/reroute?retry_failed=true\\n\\n#清除fielddata内存，当集群因为fileddata太大导致熔断或占用很多内存，可以通过此命令释放内存\\nPOST _cache/clear?fielddata=true\\n', 1, -1, 1, '超级应用默认就有的命令', '2022-09-20 10:26:08', '2022-09-26 11:34:14', '2022-09-20 10:26:08');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1683, 'arius.common.group', 'operate.record.save.num', '30', 1, -1, -1, 'DSL和kibana操作记录保存条数', '2022-09-20 10:45:31', '2022-09-22 16:49:16', '2022-09-20 10:45:31');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1685, 'ddd', 'sdd', 'sd', 1, -1, -1, 'ds', '2022-09-21 15:22:31', '2022-09-21 15:23:00', '2022-09-21 15:22:31');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1607, 'arius.dashboard.threshold.group', 'index.segment.num_threshold', '{\\\"name\\\":\\\" 索引 Segments 个数 \\\",\\\"metrics\\\":\\\"segmentNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":100}', 1, -1, 1, '索引 Segment 个数阈值定义', '2022-06-17 09:52:11', '2022-08-27 16:05:06', '2022-06-17 09:52:11');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1609, 'arius.dashboard.threshold.group', 'index.template.segment_num_threshold', '{\\\"name\\\":\\\" 模板 Segments 个数 \\\",\\\"metrics\\\":\\\"segmentNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":700}', 1, -1, 1, '索引模板 [Segment 个数阈值] 定义', '2022-06-17 09:53:34', '2022-08-27 19:01:57', '2022-06-17 09:53:34');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1611, 'arius.dashboard.threshold.group', 'index.segment.memory_size_threshold', '{\\\"name\\\":\\\" 索引 Segments 内存大小 \\\",\\\"metrics\\\":\\\"segmentMemSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":500}', 1, -1, 1, '索引 [Segment 内存大小阈值] 定义', '2022-06-17 09:54:20', '2022-10-26 18:50:50', '2022-06-17 09:54:20');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1613, 'arius.dashboard.threshold.group', 'index.template.segment_memory_size_threshold', '{\\\"name\\\":\\\" 模板 Segments 内存大小 \\\",\\\"metrics\\\":\\\"segmentMemSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":3000}', 1, -1, 1, '索引模板 [Segment 内存大小阈值] 定义', '2022-06-17 09:54:50', '2022-10-26 18:50:27', '2022-06-17 09:54:50');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1617, 'arius.dashboard.threshold.group', 'node.shard.num_threshold', '{\\\"name\\\":\\\" 节点分片个数 \\\",\\\"metrics\\\":\\\"shardNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":1000}', 1, -1, 1, '节点 [分片个数阈值] 定义', '2022-06-17 10:01:40', '2022-08-27 19:09:44', '2022-06-17 10:01:40');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1619, 'arius.dashboard.threshold.group', 'index.shard.small_threshold', '{\\\"name\\\":\\\" 小 shard 索引列表 \\\",\\\"metrics\\\":\\\"shardSize\\\",\\\"unit\\\":\\\"MB\\\",\\\"compare\\\":\\\"<\\\",\\\"value\\\":1000}', 1, -1, 1, '索引 [小 Shard 阈值] 定义', '2022-06-17 16:11:53', '2022-08-27 19:04:19', '2022-06-17 16:11:53');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1656, 'arius.dashboard.threshold.group', 'index.mapping.num_threshold', '{\\\"name\\\":\\\" 索引 Mapping 个数 \\\",\\\"metrics\\\":\\\"mappingNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":100}', 1, -1, 1, '索引 [Mapping 个数阈值] 定义', '2022-07-28 15:50:59', '2022-08-27 18:36:48', '2022-07-28 15:50:59');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1659, 'arius.dashboard.threshold.group', 'cluster.shard.num_threshold', '{\\\"name\\\":\\\" 集群 shard 个数 \\\",\\\"metrics\\\":\\\"shardNum\\\",\\\"unit\\\":\\\" 个 \\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":10000}', 1, -1, 1, '集群 [Shard 个数阈值] 定义', '2022-08-05 15:58:22', '2022-10-27 12:00:25', '2022-08-05 15:58:22');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1661, 'arius.dashboard.threshold.group', 'cluster.metric.collector.delayed_threshold', '{\\\"name\\\":\\\"node_status 指标采集延时 \\\",\\\"metrics\\\":\\\"clusterElapsedTimeGte5Min\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":5}', 1, -1, 1, '集群 [指标采集延时阈值] 定义', '2022-08-10 14:10:47', '2022-10-26 16:20:17', '2022-08-10 14:10:47');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1663, 'arius.dashboard.threshold.group', 'node.disk.used_percent_threshold', '{\\\"name\\\":\\\" 磁盘利用率 \\\",\\\"metrics\\\":\\\"largeDiskUsage\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":80}', 1, -1, 1, '节点 [磁盘利用率阈值] 定义', '2022-08-25 14:50:41', '2022-10-26 18:48:54', '2022-08-25 14:50:41');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1665, 'arius.dashboard.threshold.group', 'node.jvm.heap.used_percent_threshold', '{\\\"name\\\":\\\" 堆内存利用率 \\\",\\\"metrics\\\":\\\"largeHead\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":75}', 1, -1, 1, '节点 [堆内存利用率阈值] 定义', '2022-08-25 16:45:33', '2022-10-26 18:48:40', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1666, 'arius.dashboard.threshold.group', 'node.cpu.used_percent_threshold', '{\\\"name\\\":\\\"CPU 利用率红线 \\\",\\\"metrics\\\":\\\"largeCpuUsage\\\",\\\"unit\\\":\\\"%\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":60}', 1, -1, 1, '节点 [CPU 利用率阈值] 定义', '2022-08-25 16:45:33', '2022-10-26 18:48:18', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1667, 'arius.dashboard.threshold.group', 'node.jvm.heap.used_percent_time_duration_threshold', '{\\\"name\\\":\\\"node.jvm.heap.used_percent_threshold_time_duration\\\",\\\"metrics\\\":\\\"jvmHeapUsedPercentThresholdTimeDuration\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":10}', 1, -1, 1, '节点堆内存利用率阈值的 [持续时间]', '2022-08-25 16:45:33', '2022-10-26 18:47:52', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1668, 'arius.dashboard.threshold.group', 'node.cpu.used_percent_threshold_time_duration_threshold', '{\\\"name\\\":\\\"node.large.cpu.used.percent.time.threshold\\\",\\\"metrics\\\":\\\"largeCpuUsage\\\",\\\"unit\\\":\\\"MIN\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":5}', 1, -1, 1, '节点 CPU 利用率超阈值的 [持续时间]', '2022-08-25 16:45:33', '2022-10-26 18:47:21', '2022-08-25 16:45:33');\nINSERT INTO `arius_config_info`(`id`, `value_group`, `value_name`, `value`, `edit`, `dimension`, `status`, `memo`, `create_time`, `update_time`, `search_time`) VALUES (1669, 'arius.dashboard.threshold.group', 'index.shard.big_threshold', '{\\\"name\\\":\\\"index.shard.big_threshold\\\",\\\"metrics\\\":\\\"shardSize\\\",\\\"unit\\\":\\\"G\\\",\\\"compare\\\":\\\">\\\",\\\"value\\\":20}', 1, -1, 1, '索引 [大 shard 阈值] 定义', '2022-08-26 15:25:07', '2022-08-29 10:28:24', '2022-08-26 15:25:07');\n\n\n\nINSERT INTO `es_package` (`id`, `url`, `es_version`, `creator`, `release`, `manifest`, `desc`, `create_time`, `update_time`, `delete_flag`) VALUES (1, 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.16.tar.gz', '5.X', 'admin', 0, '4', '5.X社区开源版本', '2022-07-12 10:59:32', '2022-07-12 10:59:32', 0);\nINSERT INTO `es_package` (`id`, `url`, `es_version`, `creator`, `release`, `manifest`, `desc`, `create_time`, `update_time`, `delete_flag`) VALUES (2, 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.23.tar.gz', '6.X', 'admin', 0, '4', '6.X社区开源版本', '2022-07-12 10:59:32', '2022-12-27 16:06:30', 0);\nINSERT INTO `es_package` (`id`, `url`, `es_version`, `creator`, `release`, `manifest`, `desc`, `create_time`, `update_time`, `delete_flag`) VALUES (3, 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.8-linux-x86_64.tar.gz', '7.X', 'admin', 0, '4', '7.X社区开源版本', '2022-07-12 10:59:32', '2022-12-27 16:06:29', 0);\nINSERT INTO `es_package` (`id`, `url`, `es_version`, `creator`, `release`, `manifest`, `desc`, `create_time`, `update_time`, `delete_flag`) VALUES (4, 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.5.3-linux-x86_64.tar.gz', '8.X', 'admin', 0, '4', '8.X社区开源版本', '2022-07-12 10:59:32', '2022-12-27 15:50:37', 0);\nINSERT INTO `es_package` (`id`, `url`, `es_version`, `creator`, `release`, `manifest`, `desc`, `create_time`, `update_time`, `delete_flag`) VALUES (5, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/6.6.1.0-4.tar.gz', '6.6.1.903', 'admin', 0, '4', '6.6.1.903滴滴内部版本', '2022-07-12 10:59:32', '2022-12-27 15:48:23', 0);\nINSERT INTO `es_package` (`id`, `url`, `es_version`, `creator`, `release`, `manifest`, `desc`, `create_time`, `update_time`, `delete_flag`) VALUES (6, 'https://s3-gzpu-inter.didistatic.com/logi-data-es/elasticsearch.tar.gz', '7.6.0.1401', 'admin', 0, '4', '7.6.0.1401滴滴内部版本', '2022-07-12 10:59:32', '2022-07-12 10:59:32', 0);\n\n/*\n0.3.1原始sql\nUPDATE kf_security_permission SET permission_name = 'Kibana', parent_id = 1609, leaf = 1, level = 2, description = 'Kibana', create_time = '2022-05-24 18:08:26.0', update_time = '2022-06-14 16:44:02.0', is_delete = 0, app_name = 'know_search' WHERE id = 1855;\nUPDATE kf_security_permission SET permission_name = 'SQL查询', parent_id = 1609, leaf = 1, level = 2, description = 'SQL查询', create_time = '2022-05-24 18:08:26.0', update_time = '2022-06-14 16:44:02.0', is_delete = 0, app_name = 'know_search' WHERE id = 1857;\nUPDATE kf_security_permission SET permission_name = 'DSL查询', parent_id = 1609, leaf = 1, level = 2, description = 'DSL查询', create_time = '2022-05-24 18:08:24.0', update_time = '2022-06-14 16:39:48.0', is_delete = 0, app_name = 'know_search' WHERE id = 1757;\nUPDATE kf_security_role_permission SET role_id = 1, permission_id = 1609, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2059;\nUPDATE kf_security_role_permission SET role_id = 1, permission_id = 1757, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2061;\nUPDATE kf_security_role_permission SET role_id = 1, permission_id = 1855, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:34:13.0', is_delete = 0, app_name = 'know_search' WHERE id = 2063;\nUPDATE kf_security_role_permission SET role_id = 1, permission_id = 1857, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2065;\nUPDATE kf_security_role_permission SET role_id = 2, permission_id = 1609, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2241;\nUPDATE kf_security_role_permission SET role_id = 2, permission_id = 1757, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2243;\nUPDATE kf_security_role_permission SET role_id = 2, permission_id = 1855, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:33:12.0', is_delete = 1, app_name = 'know_search' WHERE id = 2245;\nUPDATE kf_security_role_permission SET role_id = 2, permission_id = 1857, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2247;\n*/\n# 0.3.1.1变更sql\n# 1.更新level和leaf\nUPDATE kf_security_permission SET permission_name = 'DSL查询', parent_id = 0, leaf = 0, level = 1, description = 'DSL查询', create_time = '2022-05-24 18:08:24.0', update_time = '2022-09-02 19:01:17.0', is_delete = 0, app_name = 'know_search' WHERE id = 1757;\n-- UPDATE kf_security_permission SET permission_name = 'Kibana', parent_id = 0, leaf = 0, level = 1, description = 'Kibana', create_time = '2022-05-24 18:08:26.0', update_time = '2022-09-02 19:01:17.0', is_delete = 0, app_name = 'know_search' WHERE id = 1855;\nUPDATE kf_security_permission SET permission_name = 'SQL查询', parent_id = 0, leaf = 0, level = 1, description = 'SQL查询', create_time = '2022-05-24 18:08:26.0', update_time = '2022-09-02 19:01:17.0', is_delete = 0, app_name = 'know_search' WHERE id = 1857;\n#1.1修改kf_security_role_permission\nUPDATE kf_security_role_permission SET role_id = 1, permission_id = 1609, create_time = '2022-06-14 17:41:03.0', update_time = '2022-09-02 19:04:07.0', is_delete = 1, app_name = 'know_search' WHERE id = 2059;\nUPDATE kf_security_role_permission SET role_id = 1, permission_id = 1757, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2061;\nUPDATE kf_security_role_permission SET role_id = 1, permission_id = 1855, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:34:13.0', is_delete = 0, app_name = 'know_search' WHERE id = 2063;\nUPDATE kf_security_role_permission SET role_id = 1, permission_id = 1857, create_time = '2022-06-14 17:41:03.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2065;\nUPDATE kf_security_role_permission SET role_id = 2, permission_id = 1609, create_time = '2022-06-14 18:08:56.0', update_time = '2022-09-02 19:04:07.0', is_delete = 1, app_name = 'know_search' WHERE id = 2241;\nUPDATE kf_security_role_permission SET role_id = 2, permission_id = 1757, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2243;\nUPDATE kf_security_role_permission SET role_id = 2, permission_id = 1855, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:33:12.0', is_delete = 1, app_name = 'know_search' WHERE id = 2245;\nUPDATE kf_security_role_permission SET role_id = 2, permission_id = 1857, create_time = '2022-06-14 18:08:56.0', update_time = '2022-08-25 10:31:42.0', is_delete = 0, app_name = 'know_search' WHERE id = 2247;\n#2.更新name\n-- UPDATE kf_security_permission SET permission_name = 'Kibana查询', parent_id = 0, leaf = 0, level = 1, description = 'Kibana查询', create_time = '2022-05-24 18:08:26.0', update_time = '2022-09-05 14:19:29.0', is_delete = 0, app_name = 'know_search' WHERE id = 1855;\n#3.新增3个权限点\nINSERT INTO kf_security_permission (permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name) VALUES ('DSL', 0, 0, 1, 'DSL', '2022-05-24 18:08:24.0', '2022-09-02 19:01:17.0', 0, 'know_search');\n-- INSERT INTO kf_security_permission (permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name) VALUES ('Kibana', 0, 0, 1, 'Kibana', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search');\nINSERT INTO kf_security_permission (permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name) VALUES ('SQL', 0, 0, 1, 'SQL', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search');\n#3.1 新增kf_security_role_permission\ninsert into kf_security_role_permission(role_id, permission_id, is_delete, app_name)\nvalues (1, 1877, 0, 'know_search'),\n       (1, 1879, 1, 'know_search'),\n       (1, 1881, 0, 'know_search'),\n       (2, 1877, 0, 'know_search'),\n       (2, 1879, 1, 'know_search'),\n       (2, 1881, 0, 'know_search');\n\n#4.再次更新level和leaf\nUPDATE kf_security_permission SET permission_name = 'DSL查询', parent_id = 1877, leaf = 1, level = 2, description = 'DSL查询' WHERE id = 1757;\n-- UPDATE kf_security_permission SET permission_name = 'Kibana查询', parent_id = 1879, leaf = 1, level = 2, description = 'Kibana查询' WHERE id = 1855;\nUPDATE kf_security_permission SET permission_name = 'SQL查询', parent_id = 1881, leaf = 1, level = 2, description = 'SQL查询' WHERE id = 1857;\n\n#5.用户和应用配置信息表\nalter table user_metrics_config_info rename to user_config_info;\nalter table user_config_info COMMENT '用户和应用配置信息表';\nalter table `user_config_info` change COLUMN metric_info config_info text COMMENT '用户下某个应用的配置';\nalter table `user_config_info` add column project_id int(10) NOT NULL DEFAULT '-1' COMMENT '项目 id' after user_name;\nalter table `user_config_info` add column config_type int(10) NOT NULL DEFAULT '1' COMMENT '配置类型,1- 指标看板和 dashboard，2- 查询模板列表' after project_id;\ntruncate table user_config_info;\n\nINSERT INTO `user_config_info`(`user_name`, `project_id`, `config_type`, `config_info`)\nselect DISTINCT t1.user_name,t2.project_id,2,\n                concat('[{\\\"firstUserConfigType\\\":\\\"searchQuery\\\",\\\"projectId\\\":',t2.project_id,',\\\"secondUserConfigType\\\":\\\"searchTemplate\\\",\\\"userConfigTypes\\\":[\\\"totalCostAvg\\\",\\\"totalShardsAvg\\\"],\\\"userName\\\":\\\"',t1.user_name,'\\\"}]') as config_info\nfrom kf_security_user t1 inner join\n     kf_security_user_project t2 on t1.id=t2.user_id and t2.is_delete='0'\nwhere  t1.is_delete='0';\n-- ----------------------------\n-- Table structure for metric_dictionary_info\n-- ----------------------------\nDROP TABLE IF EXISTS `metric_dictionary_info`;\nCREATE TABLE `metric_dictionary_info`  (\n                                           `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,\n                                           `type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标分类',\n                                           `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '指标名称',\n                                           `price` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '-1' COMMENT '指标价值',\n                                           `interval` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '1' COMMENT '计算间隔',\n                                           `current_cal_logic` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '当前计算逻辑',\n                                           `is_gold` tinyint(1) UNSIGNED ZEROFILL NULL DEFAULT 0 COMMENT '是否黄金指标(0否1是)',\n                                           `unit` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '单位',\n                                           `interactive_form` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '交互形式',\n                                           `is_warning` tinyint(1) UNSIGNED ZEROFILL NULL DEFAULT 0 COMMENT '告警指标(0否1是)',\n                                           `source` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标来源',\n                                           `tags` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标标签',\n                                           `model` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '模块',\n                                           `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n                                           `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n                                           `is_active` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否生效',\n                                           `is_threshold` tinyint(1) UNSIGNED ZEROFILL NOT NULL DEFAULT 0 COMMENT '是否有阈值',\n                                           `threshold` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '阈值',\n                                           `metric_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '阈值信息',\n                                           PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 5754 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户和应用配置信息表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Records of metric_dictionary_info\n-- ----------------------------\nINSERT INTO `metric_dictionary_info` VALUES (4915, '集群统计', '集群状态、shard总数、索引模板总数、文档总数、索引数、节点分配（Master节点数/Data节点数/Client节点数）、堆内存总量（已用内存、空闲内存）、磁盘总量（已用磁盘、空闲磁盘）、节点总数（活跃节点数、死亡节点数）、集群索引存储量、未分配Shard数', '集群当前运行状态概览信息', '当前值', '索引模板总数: /_template命令获取的数组大小\\n通过GET _cluster/stats命令直接获取\\n  集群状态：status\\n  shard总数：shards.total\\n  文档总数：indices.docs.count\\n  索引数:indices.count\\n  Master节点数:nodes.count.master\\n  Data节点数:nodes.count.data \\n  Client节点数:nodes.count.total - nodes.count.master-nodes.count.data\\n  堆内存总量:nodes.os.mem.total_in_bytes\\n  已用内存:nodes.os.mem.used_in_bytes\\n  空闲内存:nodes.os.mem.free_percent\\n  磁盘总量:nodes.fs.total_in_bytes\\n  已用磁盘:nodes.fs.total_in_bytes - nodes.fs.free_in_bytes\\n  空闲磁盘:nodes.fs.free_in_bytes\\n  节点总数:nodes.count.total\\n  活跃节点数，死亡节点数:查询配置的集群节点列表后和ES集群节点ip列表进行匹配，可以匹配上的为活跃节点 \\n  集群索引存储量：indices.store.size_in_bytes  ->  新增字段indicesStoreSize\\n未分配Shard数：通过 _cat/health?format=json 获取unassign字段 -> 新增字段unassignedShardNum', 1, NULL, '状态栏', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:20:01', 1, 0, NULL, 'basic');\nINSERT INTO `metric_dictionary_info` VALUES (4917, '系统指标', 'CPU使用率（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群CPU使用率与均衡情况观察', '当前值', '[当前值] 集群下所有节点，通过GET _nodes/stats命令获取nodes.{nodeName}.os.cpu.percent ，根据分位进行聚合', 1, '%', '折线图', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:49:28', 1, 0, NULL, 'cpuUsage');\nINSERT INTO `metric_dictionary_info` VALUES (4919, '系统指标', 'CPU 1分钟负载（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群1分钟负载与均衡情况观察', '当前值', '[当前值] 集群下所有节点，通过GET _nodes/stats命令获取nodes.{nodeName}.os.cpu.load_average.1m，根据分位进行聚合', 0, NULL, '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:49:30', 1, 0, NULL, 'cpuLoad1M');\nINSERT INTO `metric_dictionary_info` VALUES (4921, '系统指标', '磁盘使用率（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群磁盘利用率与均衡情况观察', '当前值', '[当前值]集群下所有节点，通过GET _nodes/stats命令获取（nodes.{nodeName}.fs.total.total_in_bytes - nodes.{nodeName}.fs.total.free_in_bytes）/nodes.{nodeName}.fs.total.total_in_bytes，根据分位进行聚合', 0, '%', '折线图', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:20:16', 1, 0, NULL, 'diskUsage');\nINSERT INTO `metric_dictionary_info` VALUES (4923, '系统指标', '磁盘使用情况（磁盘空闲量/磁盘使用量/磁盘总量）', '集群磁盘使用情况概览', '当前值', '通过GET _cluster/stats命令获取\\n磁盘总量 : nodes.{nodeName}.fs.total_in_bytes\\n磁盘使用量 : nodes.{nodeName}.fs.total_in_bytes - nodes.fs.free_in_bytes\\n磁盘空闲量 : nodes.{nodeName}.fs.free_in_bytes', 0, 'GB', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, 'diskInfo');\nINSERT INTO `metric_dictionary_info` VALUES (4925, '系统指标', '网络出口流量', '集群网络出口流量/网络入口流量走势', '当前值', '[当前值] 集群下的所有节点，通过GET _nodes/stats命令获取nodes.{nodeName}.transport.rx_size_in_bytes、nodes.{nodeName}.transport.tx_size_in_bytes（接收、发送）的累加值', 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:47:08', 1, 0, NULL, 'sendTransSize');\nINSERT INTO `metric_dictionary_info` VALUES (4927, '系统指标', '指标采集失败率', '集群指标采集失败率（采集失败次数/采集窗口大小）', '60S', NULL, 1, '%', '折线图', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-28 11:31:36', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4929, '性能指标', '执行任务耗时（平均分位值、99分位值、95分位值、75分位值、55分位值）', '集群节点任务执行耗时与均衡情况观察', '当前值', '[当前值] _cat/tasks?v&detailed&format=json命令获取结果集中running_time字段的分位值', 0, 'S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-10 16:00:21', 1, 0, NULL, 'taskCost');\nINSERT INTO `metric_dictionary_info` VALUES (4931, '性能指标', '执行任务数量', '集群全部节点每秒执行任务数走势', '当前值', '[当前值] _cat/tasks?v&detailed&format=json命令获取结果集的大小', 0, '个/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:07', 1, 0, NULL, 'taskCount');\nINSERT INTO `metric_dictionary_info` VALUES (4932, '系统指标', '网络入口流量', '集群网络出口流量/网络入口流量走势', '当前值', '[当前值] 集群下的所有节点，通过GET _nodes/stats命令获取nodes.{nodeName}.transport.rx_size_in_bytes、nodes.{nodeName}.transport.tx_size_in_bytes（接收、发送）的累加值', 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-24 09:47:11', 1, 0, NULL, 'recvTransSize');\nINSERT INTO `metric_dictionary_info` VALUES (4933, '性能指标', '查询QPS', '集群Shard级别查询并发量概览', '60S', '[累加值]  集群下的所有节点，间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.query_total的差值累加值/间隔时间', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-11-02 19:17:58', 1, 0, NULL, 'readTps');\nINSERT INTO `metric_dictionary_info` VALUES (4935, '性能指标', '写入TPS', '集群Shard级别写入并发量概览', '60S', '[累加值] 集群下的所有节点，间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.indexing.index_total的差值累加值/间隔时间', 1, '个/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-10-25 15:47:20', 1, 0, NULL, 'writeTps');\nINSERT INTO `metric_dictionary_info` VALUES (4937, '性能指标', '查询耗时', '集群Shard级别查询耗时概览', '60S', '[最大值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.search.query_total差值累加值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-11-02 19:25:44', 1, 0, NULL, 'searchLatency');\nINSERT INTO `metric_dictionary_info` VALUES (4939, '性能指标', '写入耗时', '集群文档级别写入耗时概览', '60S', '[最大值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.indexing.index_total差值累加值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-11-02 19:25:17', 1, 0, NULL, 'indexingLatency');\nINSERT INTO `metric_dictionary_info` VALUES (4941, '性能指标', '网关写入TPS', '通过网关每秒写入集群的写入请求次数', '60S', NULL, 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:08', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4943, '性能指标', '网关写入吞吐量', '通过网关每秒写入集群的文档字节数', '60S', NULL, 1, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4945, '性能指标', '网关写入请求耗时', '通过网关写入请求的平均耗时', '60S', NULL, 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4947, '性能指标', '网关写入请求响应体大小', '通过网关写入请求的响应体平均大小', '60S', NULL, 0, 'B', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4949, '性能指标', '网关查询QPS', '通过网关每秒查询的请求次数', '60S', NULL, 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4951, '性能指标', '网关查询请求耗时', '通过网关查询请求的平均耗时', '60S', NULL, 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4953, '性能指标', '网关单次查询命中Shard数', '通过网关查询请求的命中Shard平均数', '60S', NULL, 0, '个', '折线图', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4955, '状态指标', '迁移中shard列表', '集群Shard迁移感知', '当前值', '[当前值] 通过GET _cat/recovery?v&h=i,s,t,st,shost,thost&active_only=true命令获取的集合详情', 0, NULL, '列表展示（index,source_host,target_host,bytes_recovered bytes_percen,translog_ops_percentt）', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'movingShards');\nINSERT INTO `metric_dictionary_info` VALUES (4957, '状态指标', '未分配Shard列表', '集群节点掉线感知', '当前值', '[当前值]通过GET _cat/shards?format=json命令获取state=UNASSIGN的shard列表', 0, NULL, '列表项（index，shard，prirep，state）', 0, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-30 08:56:42', 1, 0, NULL, 'unAssignShards');\nINSERT INTO `metric_dictionary_info` VALUES (4959, '状态指标', 'Dead节点列表', '', '当前值', '[当前值] 通过GET _nodes命令获取集群节点信息，与平台集群节点列表对比缺失的节点', 0, NULL, '列表项（节点IP、主机名、实例名）', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:42:21', 1, 0, NULL, 'invalidNodes');\nINSERT INTO `metric_dictionary_info` VALUES (4961, '状态指标', 'PendingTask列表', '集群PengingTask感知', '当前值', '[当前值] 通过/_cluster/pending_tasks命令获取的集合', 0, NULL, '列表项（插入顺序、优先级、任务来源、执行任务前等待时间）', 1, 'ES引擎', NULL, 'OverView', '2022-09-28 11:31:36', '2022-09-29 09:42:38', 1, 0, NULL, 'pendingTasks');\nINSERT INTO `metric_dictionary_info` VALUES (4963, '系统指标', 'CPU利用率', 'CPU使用率，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.os.cpu.percent字段', 1, '%', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:42:08', 1, 0, NULL, 'os-cpu-percent');\nINSERT INTO `metric_dictionary_info` VALUES (4965, '系统指标', '磁盘空闲率', '磁盘空闲率，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.fs.total.free_in_bytes/nodes.{nodeName}.fs.total.total_in_bytes', 1, '%', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:36:11', 1, 0, NULL, 'fs-total-disk_free_percent');\nINSERT INTO `metric_dictionary_info` VALUES (4967, '系统指标', '网络发送流量', '网络包为单位的每秒发送流量，Top节点趋势', '当前值', '[平均值]，间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.transport.tx_size_in_bytes的差值/时间间隔', 0, 'MB/S', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:53:56', 1, 0, NULL, 'transport-tx_size_in_bytes_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4969, '系统指标', '网络接收流量', '网络包为单位的接收流量，Top节点趋势', '当前值', '[平均值]，间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.transport.rx_size_in_bytes的差值/时间间隔', 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:54:17', 1, 0, NULL, 'transport-rx_size_in_bytes_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4971, '系统指标', 'CPU近1分钟负载', 'CPU近1分钟负载，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.os.cpu.load_average.1m', 0, NULL, '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:36:49', 1, 0, NULL, 'os-cpu-load_average-1m');\nINSERT INTO `metric_dictionary_info` VALUES (4973, '基本性能指标', '写入TPS', '节点索引写入速率平均值，Top节点趋势', '60S', '[平均值] (当前时刻减去上一时刻通过GET _nodes/stats命令获取nodes.{nodeName}.indices.indexing.index_total的差值)/时间间隔(S)', 1, '个/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 09:45:25', 1, 0, NULL, 'indices-indexing-index_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4975, '基本性能指标', '网关查询QPS', '网关通过ClientNode节点每秒查询的请求数，Top节点趋势', '60S', NULL, 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-28 11:31:36', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4977, '基本性能指标', '网关写入TPS', '网关通过ClientNode节点每秒写入的请求数，Top节点趋势', '60S', NULL, 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-28 11:31:36', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (4979, '基本性能指标', '网关写入吞吐量', '网关通过ClientNode节点每秒写入的吞吐量，Top节点趋势', '60S', NULL, 0, 'MB/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:10:44', 1, 0, NULL, 'collectorDelayed');\nINSERT INTO `metric_dictionary_info` VALUES (4981, '基本性能指标', '写入耗时', '节点索引写入耗时平均值，Top节点趋势', '60S', '[平均值],间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.docs.count的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:06:05', 1, 0, NULL, 'indices-indexing-index_time_per_doc');\nINSERT INTO `metric_dictionary_info` VALUES (4983, '基本性能指标', 'Query QPS', '节点索引Query速率平均值，Top节点趋势', '60S', '[平均值],间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.query_total的差值/时间间隔', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 09:45:49', 1, 0, NULL, 'indices-search-query_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4985, '基本性能指标', 'Fetch QPS', '节点索引Fetch速率平均值，Top节点趋势', '60S', '[平均值] ,间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.fetch_total的差值/时间间隔', 0, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 09:46:00', 1, 0, NULL, 'indices-search-fetch_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (4987, '基本性能指标', 'Query耗时', '节点索引Query耗时平均值，Top节点趋势', '60S', '[平均值],间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.search.query_total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:37:36', 1, 0, NULL, 'indices-search-query_time_per_query');\nINSERT INTO `metric_dictionary_info` VALUES (4989, '基本性能指标', 'Fetch耗时', '节点索引Fetch耗时平均值，Top节点趋势', '60S', '[平均值] ,间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.fetch_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.search.fetch_total的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:37:46', 1, 0, NULL, 'indices-search-fetch_time_per_fetch');\nINSERT INTO `metric_dictionary_info` VALUES (4991, '基本性能指标', 'Scroll当下请求量', '节点索引Scroll请求量，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.search.scroll_current的值', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:37:56', 1, 0, NULL, 'indices-search-scroll_current');\nINSERT INTO `metric_dictionary_info` VALUES (4993, '基本性能指标', 'Scroll请求耗时', '节点Scroll耗时平均值，Top节点趋势', '60S', '[平均值] ,间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.search.scroll_time_in_millis的差值/,间隔时间内nodes.{nodeName}.indices.search.scroll_total的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:38:05', 1, 0, NULL, 'indices-search-scroll_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (4995, '基本性能指标', 'Merge操作耗时', '节点Merge耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.merges.total_time_in_millis的差值/间隔时间内nodes.{nodeName}.indices.merges.total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:42:21', 1, 0, NULL, 'indices-merges_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (4997, '基本性能指标', 'Refresh操作耗时', '节点Refresh耗时平均值，Top节点趋势', '60S', '[平均值]间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.refresh.total_time_in_millis的差值/间隔时间内nodes.{nodeName}.indices.refresh.total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:42:29', 1, 0, NULL, 'indices-refresh_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (4999, '基本性能指标', 'Flush操作耗时', '节点Flush耗时平均值，Top节点趋势', '60S', '[平均值]间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.flush.total_time_in_millis的差值/间隔时间内nodes.{nodeName}.indices.flush.total的差值', 1, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:45:15', 1, 0, NULL, 'indices-flush_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (5000, '基本性能指标', 'request Cache eviction', '节点Request Cache缓存驱逐数，Top节点趋势', '当前值', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.request_cache.evictions的差值/时间间隔(S)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:57:08', 1, 0, NULL, 'indices-request_cache-evictions');\nINSERT INTO `metric_dictionary_info` VALUES (5001, '基本性能指标', 'Write Rejected个数', '节点写入拒绝数，Top节点趋势', '60S', '[平均值]间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.thread_pool.bulk.rejected的差值/时间间隔', 1, '个/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 10:00:54', 1, 0, NULL, 'thread_pool-bulk-rejected');\nINSERT INTO `metric_dictionary_info` VALUES (5003, '基本性能指标', 'Write Queue个数', '节点写入队列堆积数，Top节点趋势', '当前值', '[当前值]  _nodes/stats命令获取nodes.{nodeName}.thread_pool.bulk.queue', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:05:43', 1, 0, NULL, 'thread_pool-bulk-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5005, '基本性能指标', 'Search Queue个数', '节点查询队列堆积数，Top节点趋势', '当前值', '[当前值]  _nodes/stats命令获取nodes.{nodeName}.thread_pool.search.queue', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:45:52', 1, 0, NULL, 'indices-search-query_total');\nINSERT INTO `metric_dictionary_info` VALUES (5007, '基本性能指标', 'Search Rejected个数', '节点查询拒绝数，Top节点趋势', '60S', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.thread_pool.search.rejected的差值/时间间隔(MIN)', 1, '个/MIN', '折线图', 1, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 10:01:05', 1, 0, NULL, 'thread_pool-search-rejected');\nINSERT INTO `metric_dictionary_info` VALUES (5009, '基本性能指标', 'Merge次数', '节点Merge次数，Top节点趋势', '60S', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.merges.total的差值/时间间隔(MIN)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:46:27', 1, 0, NULL, 'indices-merges-total');\nINSERT INTO `metric_dictionary_info` VALUES (5011, '基本性能指标', 'Refresh次数', '节点Refresh次数，Top节点趋势', '60S', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.refresh.total的差值/时间间隔(MIN)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:46:40', 1, 0, NULL, 'indices-refresh-total');\nINSERT INTO `metric_dictionary_info` VALUES (5013, '基本性能指标', 'Flush次数', '节点Flush次数，Top节点趋势', '60S', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.flush.total的差值/时间间隔(MIN)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:46:56', 1, 0, NULL, 'indices-flush-total');\nINSERT INTO `metric_dictionary_info` VALUES (5015, '基本性能指标', 'Query Cache内存命中率', '节点Query Cache内存命中率，Top节点趋势', '', '[差值] 通过GET _nodes/stats命令获取nodes.{nodeName}.indices.query_cache.hit_count/nodes.{nodeName}.indices.query_cache.total_count', 0, '%', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-28 16:31:04', 1, 0, NULL, 'indices-query_cache-hit_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5017, '基本性能指标', 'Reques Cache内存命中率', '节点Reques Cache内存命中率，Top节点趋势', '', '[差值] 通过GET _nodes/stats命令获取nodes.{nodeName}.indices.request_cache.hit_count/(nodes.{nodeName}.indices.request_cache.hit_count+nodes.{nodeName}.indices.request_cache.miss_count)', 0, '%', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-28 16:31:09', 1, 0, NULL, 'indices-request_cache-hit_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5019, '内存大小指标', 'Query Cache内存大小', '节点所有Shard Query Cache(Cached Filters/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.query_cache.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:22', 1, 0, NULL, 'indices-query_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5021, '内存大小指标', 'Request Cache内存大小', '节点所有Shard Request Cache(Cached Aggregation Results/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.request_cache.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:40', 1, 0, NULL, 'indices-request_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5023, '高级性能指标', '未提交的Translog大小', '节点所有Shard未提交Translog的大小累加值，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.translog.uncommitted_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:47:50', 1, 0, NULL, 'indices-translog-uncommitted_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5025, '高级性能指标', 'Http活跃连接数', '节点的Http活跃连接数，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.http.current_open', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:47:57', 1, 0, NULL, 'http-current_open');\nINSERT INTO `metric_dictionary_info` VALUES (5027, '高级性能指标', 'Segement数 ', '节点所有Shard的Segment汇总数，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.count', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:48:05', 1, 0, NULL, 'indices-segments-count');\nINSERT INTO `metric_dictionary_info` VALUES (5029, '高级性能指标', 'Segement内存大小', '节点所有Shard的Segment底层Lucene内存汇总占用，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.memory_in_bytes', 1, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:48:13', 1, 0, NULL, 'indices-segments-memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5031, '内存大小指标', 'Terms内存大小', '节点所有Shard的Segment底层Terms(Text/Keyword/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.term_vectors_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:53:27', 1, 0, NULL, 'indices-segments-term_vectors_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5033, '内存大小指标', 'Points内存大小', '节点所有Shard的Segment底层Points(Numbers/IPs/Geo/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.points_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:53:41', 1, 0, NULL, 'indices-segments-points_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5035, '内存大小指标', 'Doc Values内存大小', '节点所有Shard的Doc Values内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.doc_values_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:53:57', 1, 0, NULL, 'indices-segments-doc_values_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5037, '内存大小指标', 'Index Writer内存大小', '节点所有Shard的Index Writer内存大小累加值，不在Lucene内存占用统计范围内,Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.index_writer_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:04', 1, 0, NULL, 'indices-segments-index_writer_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5039, '高级性能指标', '文档总数', '节点所有Shard索引文档数累加值，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.docs.count', 1, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:49:31', 1, 0, NULL, 'indices-docs-count');\nINSERT INTO `metric_dictionary_info` VALUES (5041, '高级性能指标', '总存储大小', '节点所有Shard索引存储大小累加值，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.store.size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:49:38', 1, 0, NULL, 'indices-store-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5043, '高级性能指标', '执行任务耗时', '节点执行任务平均耗时，Top节点趋势', '当前值', '[平均值] _cat/tasks?v&detailed&format=json命令根据node筛选并获取running_time的平均值', 0, 'S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:50:50', 1, 0, NULL, 'runningTime');\nINSERT INTO `metric_dictionary_info` VALUES (5045, '高级性能指标', '执行任务数量', '节点执行任务总数量，Top节点趋势', '当前值', '[当前值] _cat/tasks?v&detailed&format=json命令根据node筛选并获取到的集合大小', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 11:05:00', 1, 0, NULL, 'taskId');\nINSERT INTO `metric_dictionary_info` VALUES (5047, '内存大小指标', 'Stored Fields大小', '节点所有Shard Stored Fields(_source/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.indices.segments.stored_fields_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:50', 1, 0, NULL, 'indices-segments-stored_fields_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5049, '内存大小指标', 'Norms内存大小', '节点所有Shard Norms(normalization factors for query time/text scoring)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取indices.segments.norms_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:54:59', 1, 0, NULL, 'indices-segments-norms_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5051, '内存大小指标', 'Version Map内存大小', '节点所有Shard Version Map(update/delete)内存大小累加值，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取indices.segments.version_map_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:55:09', 1, 0, NULL, 'indices-segments-version_map_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5053, '内存大小指标', 'Fixed Bitsets内存大小', '节点所有Shard Fixed Bitsets(deeply nested object/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取indices.segments.fixed_bit_set_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-10 10:55:20', 1, 0, NULL, 'indices-segments-fixed_bit_set_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5055, '内存大小指标', 'Fielddata内存大小', '节点所有Shard的Fielddata(global ordinals /enable fielddata on text field/...)内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取indices.segments.breakers.fielddata.estimated_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-11-01 09:13:09', 1, 0, NULL, 'breakers-fielddata-estimated_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5057, '高级性能指标', '写入线程池queue数', '节点写入线程池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.write.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-write-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5059, '高级性能指标', '查询线程池queue数', '节点查询线程池池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.search.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-08 18:39:32', 1, 0, NULL, 'thread_pool-search-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5061, '高级性能指标', '刷新线程池queue数', '节点刷新线程池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.refresh.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-refresh-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5063, '高级性能指标', '落盘线程池queue数', '节点落盘线程池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.rollup_indexing.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-rollup_indexing-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5065, '高级性能指标', '管理线程池queue数', '节点管理线程池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.management.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-management-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5067, '高级性能指标', '合并线程池queue数', '节点合并线程池队列当前值', '当前值', '[当前值] GET _nodes/stats命令获取thread_pool.force_merge.queue', 0, '个', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-29 11:05:01', 1, 0, NULL, 'thread_pool-force_merge-queue');\nINSERT INTO `metric_dictionary_info` VALUES (5069, 'JVM指标', 'Young GC次数', '节点Young GC次数，Top节点趋势', '60S', '[平均值]当前时刻减去上一时刻通过GET _nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.young.collection_count的值/时间间隔', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:40', 1, 0, NULL, 'jvm-gc-young-collection_count_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5071, 'JVM指标', 'Old GC次数', '节点Old GC次数，Top节点趋势', '60S', '[平均值]当前时刻减去上一时刻通过GET _nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.old.collection_count的值/时间间隔', 1, '次/S', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:33', 1, 0, NULL, 'jvm-gc-old-collection_count_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5073, 'JVM指标', 'Young GC耗时', '节点Young GC平均耗时，Top节点趋势', '60S', '[差值]  间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.young.collection_time_in_millis的差值/ 间隔时间内nodes.{nodeName}.jvm.gc.collectors.young.collection_count的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:26', 1, 0, NULL, 'jvm-gc-young-collection_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (5075, 'JVM指标', 'Old GC耗时', '节点Old GC平均耗时，Top节点趋势', '60S', '[差值]  间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.jvm.gc.collectors.old.collection_time_in_millis的差值/ 间隔时间内nodes.{nodeName}.jvm.gc.collectors.old.collection_count的差值', 0, 'MS', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:41:17', 1, 0, NULL, 'jvm-gc-old-collection_avg_time');\nINSERT INTO `metric_dictionary_info` VALUES (5077, 'JVM指标', 'JVM堆内存使用量', '节点JVM堆内存使用量，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.heap_used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:52', 1, 0, NULL, 'jvm-mem-heap_used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5079, 'JVM指标', 'JVM堆外存使用量', '节点JVM堆外存使用量，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.non_heap_used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:44', 1, 0, NULL, 'jvm-mem-non_heap_used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5081, 'JVM指标', 'JVM堆使用率', '节点JVM堆使用率，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.heap_used_percent', 1, '%', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:18', 1, 0, NULL, 'jvm-mem-heap_used_percent');\nINSERT INTO `metric_dictionary_info` VALUES (5083, 'JVM指标', '堆内存young区使用空间', '节点年轻代堆内存使用空间，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.pools.young.used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:10', 1, 0, NULL, 'jvm-mem-pools-young-used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5085, 'JVM指标', '堆内存old区使用空间', '节点老年代堆内存使用空间，Top节点趋势', '当前值', '[当前值] GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.pools.old.used_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-09-30 10:40:03', 1, 0, NULL, 'jvm-mem-pools-old-used_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5087, 'breaker指标', 'Field data circuit breaker 内存占用', '统计当前fielddata占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] GET _nodes/stats命令获取breakers.fielddata.limit_size_in_bytes[阈值]，breakers.fielddata.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:16:52', 1, 0, NULL, 'breakers-fielddata-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5089, 'breaker指标', 'Request circuit breaker 内存占用', '统计当前请求(比如聚合请求临时内存构建）占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] GET _nodes/stats命令获取breakers.request.limit_size_in_bytes[阈值]，breakers.request.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:03', 1, 0, NULL, 'breakers-request-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5090, '基本性能指标', 'query Cache evictions', '节点Query Cache缓存驱逐数，Top节点趋势', '当前值', '[差值] 间隔时间内通过GET _nodes/stats命令获取nodes.{nodeName}.indices.query_cache.evictions的差值/时间间隔(S)', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-24 09:56:51', 1, 0, NULL, 'indices-query_cache-evictions');\nINSERT INTO `metric_dictionary_info` VALUES (5091, 'breaker指标', 'inflight requests circuit breaker 内存占用', '统计当前请求body占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] GET _nodes/stats命令获取breakers.in_flight_requests.limit_size_in_bytes[阈值]，breakers.in_flight_requests.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:04', 1, 0, NULL, 'breakers-in_flight_requests-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5093, 'breaker指标', 'Accounting requests circuit breaker 内存占用', '统计当前请求结束后不能释放的对象(例如segment常驻的内存占用)所占用内存总大小，与阀值比较，超过则熔断请求', '当前值', '[当前值] GET _nodes/stats命令获取breakers.accounting.limit_size_in_bytes[阈值]，breakers.accounting.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:29', 1, 0, NULL, 'breakers-accounting-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5095, 'breaker指标', 'Script compilation circuit breaker 编译次数', '统计一段时间内脚本编译次数，与阀值比较，超过则熔断请求', '当前值', '[平均值] 当前时刻减去上个时刻通过GET _nodes/stats命令获取script.compilations的数量差值/时间间隔MIN', 0, '次/MIN', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-11 14:58:57', 1, 0, NULL, 'script-compilations');\nINSERT INTO `metric_dictionary_info` VALUES (5097, 'breaker指标', 'Parent circuit breaker JVM真实内存占用', '统计JVM真实内存占用，与阀值比较，超过则熔断请求', '当前值', '[当前值] GET _nodes/stats命令获取breakers.parent.limit_size_in_bytes[阈值]，breakers.parent.estimated_size_in_bytes[当前值]', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Node', '2022-09-28 11:31:36', '2022-10-18 14:17:33', 1, 0, NULL, 'breakers-parent-limit_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5099, '索引基础指标', '索引Shard数', '索引Shard个数，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_shards.total', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:16', 1, 0, NULL, 'shardNu');\nINSERT INTO `metric_dictionary_info` VALUES (5101, '索引基础指标', '索引存储大小', '索引存储总大小，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.store.size_in_bytes', 0, 'GB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:16', 1, 0, NULL, 'store-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5103, '索引基础指标', '文档总数', '索引的文档总数，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.docs.count', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, 'docs-count');\nINSERT INTO `metric_dictionary_info` VALUES (5105, '索引性能指标', '写入TPS', '索引写入速率平均值，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.docs.count的差值)/时间间隔(S)', 1, '个/S', '折线', 1, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 09:23:43', 1, 0, NULL, 'indexing-index_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5107, '索引性能指标', '写入耗时', '索引写入耗时平均值，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.indexing.index_time_in_millis的差值)/ 间隔时间内_all.total.indexing.index_total的差值', 1, 'MS', '折线', 1, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 16:55:05', 1, 0, NULL, 'indices-indexing-index_time_per_doc');\nINSERT INTO `metric_dictionary_info` VALUES (5109, '索引性能指标', '网关写入TPS', 'Index通过网关的每秒写入请求数', '60S', '[平均值] (间隔时间内通过查询网关索引获取命中写入条件总数的差值)/时间间隔(S)', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5111, '索引性能指标', '网关写入耗时', 'Index通过网关的写入平均耗时', '60S', '[平均值]  间隔时间内通过查询网关索引获取命中写入条件耗时的平均值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5113, '索引性能指标', '网关查询QPS', 'Index通过网关的每秒查询请求量', '60S', '[平均值] (间隔时间内通过查询网关索引获取命中查询总数的差值)/时间间隔(S)', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5115, '索引性能指标', '网关查询耗时', 'Index通过网关的查询平均耗时', '60S', '[平均值]  间隔时间内通过查询网关索引获取命中查询耗时的平均值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5117, '索引性能指标', '查询Query QPS', '索引Query速率平均值，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.query_total的差值)/时间间隔(S)', 1, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:17', 1, 0, NULL, 'search-query_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5119, '索引性能指标', 'Fetch QPS', '索引Fetch速率平均值，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.fetch_total的差值)/时间间隔(S)', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-11 11:23:19', 1, 0, NULL, 'search-fetch_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5121, '索引性能指标', '查询Query耗时', '索引Query耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.query_time_in_millis的差值/ 间隔时间内_all.total.search.query_total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:14:56', 1, 0, NULL, 'cost-query_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5123, '索引性能指标', '查询Fetch耗时', '索引Fetch耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.fetch_time_in_millis的差值/ 间隔时间内_all.total.search.fetch_total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:15:06', 1, 0, NULL, 'cost-fetch_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5125, '索引性能指标', '查询Scroll量', '索引间隔时间内所有Shard Scroll请求量，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.scroll_total的差值)/时间间隔(S)', 0, '个', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:02', 1, 0, NULL, 'search-scroll_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5127, '索引性能指标', '查询Scroll耗时', '索引Scorll耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.search.scroll_time_in_millis的差值/ 间隔时间内_all.total.search.scroll_total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:19:31', 1, 0, NULL, 'cost-scroll_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5129, '索引性能指标', 'Merge耗时', '索引Merge耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.merges.total_time_in_millis的差值/ 间隔时间内_all.total.merges.total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:17:24', 1, 0, NULL, 'cost-merges-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5131, '索引性能指标', 'Refresh耗时', '索引Refresh耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.refresh.total_time_in_millis的差值/ 间隔时间内_all.total.refresh.total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:17:39', 1, 0, NULL, 'cost-refresh-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5133, '索引性能指标', 'Flush耗时', '索引Flush耗时平均值，Top节点趋势', '60S', '[平均值]  间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.indices.flush.total_time_in_millis的差值/ 间隔时间内_all.total.indices.flush.total的差值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-30 11:18:08', 1, 0, NULL, 'cost-flush-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5135, '索引性能指标', 'Merge次数', '索引Merge次数，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.merges.total的差值)/时间间隔(MIN)', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:02', 1, 0, NULL, 'merges-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5137, '索引性能指标', 'Refresh次数', '索引Refresh次数，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取_all.total.refresh.total的差值)/时间间隔(MIN)', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:02', 1, 0, NULL, 'refresh-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5139, '索引性能指标', 'Flush次数', '索引Flush次数，Top节点趋势', '60S', '[平均值] (间隔时间内通过{indexName}/_stats?level=shards命令获取flush.total的差值)/时间间隔(MIN)', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-09-29 11:06:03', 1, 0, NULL, 'flush-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5141, '索引内存指标', 'Segements大小', '索引所有Shard的Segment底层Lucene内存汇总占用，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.segments.memory_in_bytes', 1, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:13:35', 1, 0, NULL, 'segments-memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5143, '索引内存指标', 'Terms内存大小', '索引所有Shard的Segment底层Terms(Text/Keyword/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.segments.term_vectors_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:13:40', 1, 0, NULL, 'segments-term_vectors_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5145, '索引内存指标', 'Points内存大小', '索引所有Shard的Segment底层Points(Numbers/IPs/Geo/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.segments.points_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:14:44', 1, 0, NULL, 'segments-points_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5147, '索引内存指标', 'Doc Values内存大小', '索引所有Shard的Doc Values内存大小，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.segments.doc_values_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:15:01', 1, 0, NULL, 'segments-doc_values_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5149, '索引内存指标', 'Index Writer内存大小', '索引所有Shard的Index Writer内存大小，不在Lucene内存占用统计范围内,Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.segments.index_writer_memory_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:15:06', 1, 0, NULL, 'segments-index_writer_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5151, '索引内存指标', '未提交的Translog大小', '索引所有Shard的未提交Translog的大小累加值，Top节点趋势', '当前值', '[当前值] {indexName}/_stats?level=shards命令获取_all.total.translog.uncommitted_size_in_bytes', 0, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-10-27 11:15:10', 1, 0, NULL, 'translog-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5153, '索引内存指标', 'Query Cache内存大小', '索引所有Shard Query Cache(Cached Filters/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.query_cache.memory_size_in_bytes', 1, 'MB', '折线', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:35', 1, 0, NULL, 'query_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5155, '索引内存指标', 'Stored Fields大小', '索引stored_fields_memory内存大小', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.segments.stored_fields_memory_in_bytes', 0, 'MB', NULL, 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:40', 1, 0, NULL, 'segments-stored_fields_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5157, '索引内存指标', 'Norms内存大小', '索引所有Shard Norms(normalization factors for query time/text scoring)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.segments.norms_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:42', 1, 0, NULL, 'segments-norms_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5159, '索引内存指标', 'Version Map内存大小', '索引所有Shard Version Map(update/delete)内存大小累加值，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.segments.version_map_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:45', 1, 0, NULL, 'segments-version_map_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5161, '索引内存指标', 'Fixed Bitsets内存大小', '索引所有Shard Fixed Bitsets(deeply nested object/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.segments.fixed_bit_set_memory_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:49', 1, 0, NULL, 'segments-fixed_bit_set_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5163, '索引内存指标', 'Fielddata内存大小', '索引所有Shard Fielddata(global ordinals /enable fielddata on text field/...)内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.fielddata.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:54', 1, 0, NULL, 'fielddata-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5165, '索引内存指标', 'Request Cache内存大小', '索引所有Shard Request Cache(Cached Aggregation Results/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] GET {indexName}_/stats?level=shards命令获取_all.total.request_cache.memory_size_in_bytes', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index', '2022-09-28 11:31:36', '2022-11-02 20:54:58', 1, 0, NULL, 'segments-request_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5167, '索引模板基础指标', '索引Shard数', '索引模板下索引Shard个数，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取shards数量之和', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:05', 1, 0, NULL, 'shardNu');\nINSERT INTO `metric_dictionary_info` VALUES (5169, '索引模板基础指标', '索引存储大小', '索引模板下索引Shard存储总大小，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.store.size_in_bytes之和', 0, 'GB', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-27 11:15:43', 1, 0, NULL, 'store-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5171, '索引模板基础指标', '文档总数', '索引模板下索引的文档数，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.docs.count之和', 1, '个', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-27 11:15:48', 1, 0, NULL, 'docs-count');\nINSERT INTO `metric_dictionary_info` VALUES (5173, '索引模板性能指标', '写入TPS', '索引模板写入速率平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.docs.count的差值累加值/间隔时间', 1, '个/S', '折线', 1, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-27 11:15:53', 1, 0, NULL, 'indexing-index_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5175, '索引模板性能指标', '写入耗时', '索引模板写入耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过GET {indexName}/_stats?level=shards命令获取_all.total.indexing.index_time_in_millis的差值)/ 间隔时间内_all.total.indexing.index_total的差值', 1, 'MS', '折线', 1, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 16:58:37', 1, 0, NULL, 'indices-indexing-index_time_per_doc');\nINSERT INTO `metric_dictionary_info` VALUES (5177, '索引模板性能指标', '查询Query QPS', '索引模板Query速率平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过{indexName}/_stats?level=shards命令获取 all.total.search.query_total的差值累加值/间隔时间', 1, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-27 11:16:07', 1, 0, NULL, 'search-query_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5179, '索引模板性能指标', '网关写入TPS', 'IndexTemplate所属Index通过网关的每秒写入请求数', '60S', NULL, 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5181, '索引模板性能指标', '网关写入耗时', 'IndexTemplate所属Index通过网关的写入平均耗时', '60S', NULL, 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5183, '索引模板性能指标', '网关查询QPS', 'IndexTemplate所属Index通过网关的每秒查询请求量', '60S', NULL, 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:06', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5185, '索引模板性能指标', '网关查询耗时', 'IndexTemplate所属Index通过网关的查询平均耗时', '60S', NULL, 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:07', 1, 0, NULL, NULL);\nINSERT INTO `metric_dictionary_info` VALUES (5187, '索引模板性能指标', '查询Fetch QPS', '索引模板Fetch速率平均值，Top节点趋势', '60S', '[平均值]  间隔时间内获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.search.fetch_total的差值累加值/时间间隔', 0, '次/S', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:58:35', 1, 0, NULL, 'search-fetch_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5189, '索引模板性能指标', '查询Query耗时', '索引模板Query耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内模板下所有的索引通过{indexName}/_stats?level=shards命令_all.total.search.query_time_in_millis的差值累加值/_all.total.search.query_total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:57:12', 1, 0, NULL, 'cost-query_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5191, '索引模板性能指标', '查询Fetch耗时', '索引模板Fetch耗时平均值，Top节点趋势', '60S', '[平均值] 间隔时间内获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.search.fetch_time_in_millis的差值累加值/_all.total.search.fetch_total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:59:22', 1, 0, NULL, 'cost-fetch_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5193, '索引模板性能指标', '查询Scroll量', '索引模板下索引Shard 级别 Scroll请求量，Top节点趋势', '60S', '[平均值] 获取间隔时间内模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.search.scroll_total的差值累加值/时间间隔', 0, '个', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:44:38', 1, 0, NULL, 'search-scroll_total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5195, '索引模板性能指标', '查询Scroll耗时', '索引模板Scorll耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.search.scroll_time_in_millis的差值累加值/_all.total.search.scroll_total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-30 11:19:09', 1, 0, NULL, 'cost-scroll_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5197, '索引模板性能指标', 'Merge耗时', '索引模板Merge耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.merges.total_time_in_millis的差值累加值/_all.total.merges.total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:08', 1, 0, NULL, 'cost-merges-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5199, '索引模板性能指标', 'Refresh耗时', '索引模板Refresh耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.refresh.total_time_in_millis的差值累加值/_all.total.refresh.total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, 'cost-refresh-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5201, '索引模板性能指标', 'Flush耗时', '索引模板Flush耗时平均值，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.flush.total_time_in_millis的差值累加值/all.total.flush.total的差值累加值', 0, 'MS', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:09', 1, 0, NULL, 'cost-flush-total_time_in_millis');\nINSERT INTO `metric_dictionary_info` VALUES (5203, '索引模板性能指标', 'Merge次数', '索引模板Merge次数，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.merges.total的差值累加值/时间间隔', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:59:59', 1, 0, NULL, 'merges-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5205, '索引模板性能指标', 'Refresh次数', '索引模板Refresh次数，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.refresh.total的差值累加值/时间间隔', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-10-24 10:57:58', 1, 0, NULL, 'refresh-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5207, '索引模板性能指标', 'Flush次数', '索引模板Flush次数，Top节点趋势', '60S', '[平均值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.flush-total_rate的累加值差值/时间间隔', 0, '次/MIN', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'flush-total_rate');\nINSERT INTO `metric_dictionary_info` VALUES (5209, '索引模板内存指标', 'Segements大小', '索引模板下索引所有Shard的Segment底层Lucene内存汇总占用，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.memory_in_bytes的总和', 1, 'MB', '折线', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'segments-memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5211, '索引模板内存指标', 'Terms内存大小', '索引模板下索引所有Shard的Segment底层Terms(Text/Keyword/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.term_vectors_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:10', 1, 0, NULL, 'segments-term_vectors_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5213, '索引模板内存指标', 'Points内存大小', '索引模板下索引所有Shard的Segment底层Points(Numbers/IPs/Geo/...)内存汇总占用，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.points_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'segments-points_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5215, '索引模板内存指标', 'Doc Values内存大小', '索引模板下索引所有Shard的Doc Values内存大小，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.doc_values_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'segments-doc_values_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5217, '索引模板内存指标', 'Index Writer内存大小', '索引模板下索引所有Shard的Index Writer内存大小，不在Lucene内存占用统计范围内,Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.index_writer_memory_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'segments-index_writer_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5219, '索引模板内存指标', '未提交的Translog大小', '索引模板下索引所有Shard的未提交Translog的大小累加值，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.translog.uncommitted_size_in_bytes的总和', 0, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'translog-size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5221, '索引模板内存指标', 'Query Cache内存大小', '索引模板下索引所有Shard Query Cache(Cached Filters/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.query_cache.memory_size_in_bytes的总和', 1, 'MB', '折线', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:11', 1, 0, NULL, 'query_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5223, '索引模板内存指标', 'Stored Fields大小', '索引模板下索引stored_fields_memory内存大小', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.stored_fields_memory_in_bytes的总和', 0, NULL, NULL, 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-09-29 11:06:12', 1, 0, NULL, 'segments-stored_fields_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5225, '索引模板内存指标', 'Norms内存大小', '索引模板下索引所有Shard Norms(normalization factors for query time/text scoring)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments-norms_memory_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 19:22:53', 1, 0, NULL, 'segments-norms_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5227, '索引模板内存指标', 'Version Map内存大小', '索引模板下索引所有Shard Version Map(update/delete)内存大小累加值，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.version_map_memory_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 19:23:20', 1, 0, NULL, 'segments-version_map_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5229, '索引模板内存指标', 'Fixed Bitsets内存大小', '索引模板下索引所有Shard Fixed Bitsets(deeply nested object/...)内存大小累加值，是底层Lucene内存汇总占用的一个子项，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.segments.fixed_bit_set_memory_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 19:23:39', 1, 0, NULL, 'segments-fixed_bit_set_memory_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5231, '索引模板内存指标', 'Fielddata内存大小', '索引模板下索引所有Shard Fielddata(global ordinals /enable fielddata on text field/...)内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.fielddata.memory_size_in_bytes的总和', 0, 'MB', '折线图', 0, NULL, NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 19:23:49', 1, 0, NULL, 'fielddata-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5233, '索引模板内存指标', 'Request Cache内存大小', '索引模板下索引所有Shard Request Cache(Cached Aggregation Results/...)堆内存汇总占用，不在Lucene内存占用统计范围内，Top节点趋势', '当前值', '[当前值] 获取模板下所有的索引通过{indexName}/_stats?level=shards命令获取_all.total.request_cache.memory_size_in_bytes的总和', 0, 'MB', '折线图', 0, 'ES引擎', NULL, 'Index_template', '2022-09-28 11:31:36', '2022-11-02 19:20:19', 1, 0, NULL, 'segments-request_cache-memory_size_in_bytes');\nINSERT INTO `metric_dictionary_info` VALUES (5235, '集群', '集群健康状态', '不同健康状态集群分布感知，快速定位故障集群', '当前值', '[当前值] 通过GET _cluster/health命令获取status', 0, NULL, '状态栏', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 15:18:40', 1, 0, NULL, 'health');\nINSERT INTO `metric_dictionary_info` VALUES (5237, '集群', '指标采集延时', '指标数据质量风险集群预警', '当前值', '[当前值] 采集数据最近一个时间点和当前时间点的差值', 0, 'S', '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:01', 1, 0, NULL, 'clusterElapsedTimeGte5Min');\nINSERT INTO `metric_dictionary_info` VALUES (5239, '集群', 'shard个数大于10000集群', 'Shard膨胀风险集群预警', '当前值', '[当前值] 通过GET _cat/health?format=json获取shards总数量(包括unassign状态)', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-10 15:49:42', 1, 0, NULL, 'shardNum');\nINSERT INTO `metric_dictionary_info` VALUES (5241, '集群', '写入耗时', '索引写入性能对比分析，性能不足集群预警', '5*60S', '[最大值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.indexing.index_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.indexing.index_total差值累加值', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-11-02 19:51:22', 1, 0, NULL, 'indexingLatency');\nINSERT INTO `metric_dictionary_info` VALUES (5243, '集群', 'node_stats接口平均采集耗时', 'Master指标采集性能问题集群预警', '当前值', '[当前值] 调用一次_nodes/stats命令所消耗的时间', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-10 15:50:23', 1, 0, NULL, 'nodeElapsedTime');\nINSERT INTO `metric_dictionary_info` VALUES (5245, '集群', '集群pending task数', 'pending task持续堆积，Master元数据处理性能问题集群预警', '当前值', '[当前值] 通过 _cluster/health命令获取number_of_pending_tasks', 0, '个', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:23', 1, 0, NULL, 'pendingTaskNum');\nINSERT INTO `metric_dictionary_info` VALUES (5247, '集群', '网关失败率', '各组网关业务查询健康预警', '5*60S', '5分钟执行一次，获取近一分钟内的网关失败率', 0, '%', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:26', 1, 0, NULL, 'gatewayFailedPer');\nINSERT INTO `metric_dictionary_info` VALUES (5249, '集群', '查询耗时', '索引查询性能对比分析，查询性能不足集群预警', '5*60S', '[最大值] 集群下的所有节点,间隔时间内通过_node/stats命令获取nodes.{nodeName}.indices.search.query_time_in_millis差值累加值/节点间隔时间内nodes.{nodeName}.indices.search.query_total差值累加值', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-11-02 19:51:08', 1, 0, NULL, 'searchLatency');\nINSERT INTO `metric_dictionary_info` VALUES (5251, '节点', '节点执行任务耗时', '节点执行任务平均耗时高', '5*60S', '[平均值]根据_cat/tasks?v&detailed&format=json命令获取到当前时间的各节点任务执行总和/节点执行的次数', 0, 'S', '折线图，可选Top5-Top50', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:22:56', 1, 0, NULL, 'taskConsuming');\nINSERT INTO `metric_dictionary_info` VALUES (5253, '节点', '磁盘利用率超红线节点', '磁盘利用率超安全水位节点预警', '当前值', '[当前值]根据GET _nodes/stats命令获取到(nodes.{nodeName}.fs.total-nodes.{nodeName}.fs.free_in_bytes)/nodes.{nodeName}.fs.total大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:34', 1, 0, NULL, 'largeDiskUsage');\nINSERT INTO `metric_dictionary_info` VALUES (5255, '节点', '分片个数大于500节点', '分片数超安全水位节点预警', '当前值', '[当前值]根据_cat/shards?v&h=node命令获取到结果个数大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:55:51', 1, 0, NULL, 'shardNum');\nINSERT INTO `metric_dictionary_info` VALUES (5257, '节点', '堆内存利用率超红线节点', '堆内存利用率超红线节点预警', '当前值', '[当前值]根据GET _nodes/stats命令获取nodes.{nodeName}.jvm.mem.heap_used_percent大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:28', 1, 0, NULL, 'largeHead');\nINSERT INTO `metric_dictionary_info` VALUES (5259, '节点', 'CPU利用率超红线节点', 'CPU利用率超红线节点预警', '当前值', '[当前值]根据GET _nodes/stats命令获取到nodes.{nodeName}.os.cpu.percent大于阀值的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:32', 1, 0, NULL, 'largeCpuUsage');\nINSERT INTO `metric_dictionary_info` VALUES (5261, '节点', 'SearchRejected节点', 'SearchRejected节点预警', '5*60S', '[当前值]当前时间和上次时间通过GET _nodes/stats命令nodes.{nodeName}.thread_pool.search.rejected差值不为0的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:41', 1, 0, NULL, 'searchRejectedNum');\nINSERT INTO `metric_dictionary_info` VALUES (5263, '节点', 'WriteRejected节点', 'WriteRejected节点预警', '5*60S', '[当前值]当前时间和上次时间通过GET _nodes/stats命令nodes.{nodeName}.thread_pool.write.rejected差值不为0的节点', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:23:43', 1, 0, NULL, 'writeRejectedNum');\nINSERT INTO `metric_dictionary_info` VALUES (5265, '索引', 'segments内存大于1MB索引模板', '索引模板超大内存占用风险预警', '当前值', '[当前值]根据_cat/segments/命令获取size字段大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:59:56', 1, 1, 'segments内存大于1MB索引模板', 'tplSegmentMemSize');\nINSERT INTO `metric_dictionary_info` VALUES (5267, '索引', 'segments个数大于20索引模板', '索引模板Segements数超红线预警', '当前值', '[当前值]根据_cat/segments/命令获取segment个数大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:59:58', 1, 0, NULL, 'tplSegmentNum');\nINSERT INTO `metric_dictionary_info` VALUES (5269, '索引', '未分配shard索引', 'shard未分配索引预警', '当前值', '[当前值]根据GET {indexName}/_stats命令获取索引状态不等于green的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:09', 1, 0, NULL, 'unassignedShard');\nINSERT INTO `metric_dictionary_info` VALUES (5271, '索引', 'mapping字段个数大于100索引', '索引mapping字段膨胀预警', '当前值', '[当前值]根据GET {indexName}命令mapping的字段个数大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:13', 1, 0, NULL, 'mappingNum');\nINSERT INTO `metric_dictionary_info` VALUES (5273, '索引', 'segments内存大于100B索引', '索引超大内存占用风险预警', '当前值', '[当前值]根据_cat/segments/命令获取segment内存（size）大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:20', 1, 0, NULL, 'segmentMemSize');\nINSERT INTO `metric_dictionary_info` VALUES (5275, '索引', 'segments个数大于100索引', '索引Segements数超红线预警', '当前值', '[当前值]根据_cat/segments/命令获取segment个数大于阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:24', 1, 0, NULL, 'segmentNum');\nINSERT INTO `metric_dictionary_info` VALUES (5277, '索引', 'RED索引', 'RED索引预警', '当前值', '[当前值]根据_cat/indices?format=json命令获取健康状态(health)等于red的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:24:59', 1, 0, NULL, 'red');\nINSERT INTO `metric_dictionary_info` VALUES (5279, '索引', '单个shard大于500MB索引', '单Shard过大索引预警', '当前值', '[当前值]根据_cat/shards命令获取大小大于指定的阀值的索引', 0, NULL, '列表', 0, 'ES引擎', NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:57:51', 1, 0, NULL, 'bigShard');\nINSERT INTO `metric_dictionary_info` VALUES (5281, '索引', '无副本索引', '无副本索引稳定性预警', '当前值', '[当前值]根据_cat/indices命令获取副本数等于0的索引', 0, NULL, '列表', 0, NULL, NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-09-30 11:25:12', 1, 0, NULL, 'singReplicate');\nINSERT INTO `metric_dictionary_info` VALUES (5283, '索引', '单个shard小于500MB索引', '索引Shard数分配不合理预警', '当前值', '[当前值]根据_cat/shards命令获取大小(store)小于指定的阀值并且shard数量大于1的索引', 0, NULL, '列表', 0, NULL, NULL, 'Dashboard', '2022-09-28 11:31:36', '2022-10-08 16:58:06', 1, 0, NULL, 'smallShard');\n\n\n\n#重新全量导入权限点表\ntruncate table kf_security_permission;\ninsert into kf_security_permission (id, permission_name, parent_id, leaf, level, description, create_time, update_time, is_delete, app_name)\nvalues  (1593, '物理集群', 0, 0, 1, '物理集群', '2022-05-24 18:08:22.0', '2022-08-24 20:07:31.0', 0, 'know_search'),\n        (1595, '我的集群', 0, 0, 1, '我的集群', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1597, '集群版本', 0, 0, 1, '集群版本', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1599, 'Gateway管理', 0, 0, 1, 'Gateway管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1601, '模板管理', 0, 0, 1, '模板管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1603, '模板服务', 0, 0, 1, '模板服务', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1605, '索引管理', 0, 0, 1, '索引管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1607, '索引服务', 0, 0, 1, '索引服务', '2022-05-24 18:08:22.0', '2022-05-24 18:24:16.0', 0, 'know_search'),\n        (1609, '索引查询', 0, 0, 1, '索引查询', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1611, '查询诊断', 0, 0, 1, '查询诊断', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1613, '集群看板', 0, 0, 1, '集群看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1615, '网关看板', 0, 0, 1, '网关看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1617, '我的申请', 0, 0, 1, '我的申请', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1619, '我的审批', 0, 0, 1, '我的审批', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1621, '任务列表', 0, 0, 1, '任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1623, '调度任务列表', 0, 0, 1, '调度任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1625, '调度日志', 0, 0, 1, '调度日志', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1627, '用户管理', 0, 0, 1, '用户管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1629, '角色管理', 0, 0, 1, '角色管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1631, '应用管理', 0, 0, 1, '应用管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1633, '平台配置', 0, 0, 1, '平台配置', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1635, '操作记录', 0, 0, 1, '操作记录', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n        (1637, '查看集群列表及详情', 1593, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1639, '接入集群', 1593, 1, 2, '接入集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1641, '新建集群', 1593, 1, 2, '新建集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1643, '扩缩容', 1593, 1, 2, '扩缩容', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1645, '升级', 1593, 1, 2, '升级', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1647, '重启', 1593, 1, 2, '重启', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1649, '配置变更', 1593, 1, 2, '配置变更', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1651, 'Region划分', 1593, 1, 2, 'Region划分', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1653, 'Region管理', 1593, 1, 2, 'Region管理', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1655, '快捷命令', 1593, 1, 2, '快捷命令', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1657, '编辑', 1593, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1659, '绑定Gateway', 1593, 1, 2, '绑定Gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n        (1661, '下线', 1593, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1663, '查看集群列表及详情', 1595, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1665, '申请集群', 1595, 1, 2, '申请集群', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1667, '编辑', 1595, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1669, '扩缩容', 1595, 1, 2, '扩缩容', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n        (1671, '下线', 1595, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1673, '查看版本列表', 1597, 1, 2, '查看版本列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1675, '新增版本', 1597, 1, 2, '新增版本', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1677, '编辑', 1597, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n        (1679, '删除', 1597, 1, 2, '删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1681, '查看Gateway 集群列表', 1599, 1, 2, '查看Gateway 集群列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1683, '接入gateway', 1599, 1, 2, '接入gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1685, '编辑', 1599, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1687, '下线', 1599, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1689, '查看模板列表及详情', 1601, 1, 2, '查看模板列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1691, '申请模板', 1601, 1, 2, '申请模板', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1693, '编辑', 1601, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1695, '下线', 1601, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1697, '编辑Mapping', 1601, 1, 2, '编辑Mapping', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1699, '编辑Setting', 1601, 1, 2, '编辑Setting', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1701, '查看模板列表', 1603, 1, 2, '查看模板列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1703, '开关：预创建', 1603, 1, 2, '开关：预创建', '2022-05-24 18:08:23.0', '2022-06-14 16:49:48.0', 0, 'know_search'),\n        (1705, '开关：过期删除', 1603, 1, 2, '开关：过期删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1707, '开关：冷热分离', 1603, 1, 2, '开关：冷热分离', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1709, '开关：pipeline', 1603, 1, 2, '开关：写入限流', '2022-05-24 18:08:23.0', '2022-06-14 16:49:49.0', 0, 'know_search'),\n        (1711, '开关：Rollover', 1603, 1, 2, '开关：Rollover', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1713, '查看DCDR链路', 1603, 1, 2, '查看DCDR链路', '2022-05-24 18:08:23.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1715, '创建DCDR链路', 1603, 1, 2, '创建DCDR链路', '2022-05-24 18:08:24.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n        (1717, '清理', 1603, 1, 2, '清理', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1719, '扩缩容', 1603, 1, 2, '扩缩容', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1721, '升版本', 1603, 1, 2, '升版本', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1723, '批量操作', 1603, 1, 2, '批量操作', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1725, '查看索引列表及详情', 1605, 1, 2, '查看索引列表及详情', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1727, '编辑Mapping', 1605, 1, 2, '编辑Mapping', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1729, '编辑Setting', 1605, 1, 2, '编辑Setting', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1731, '禁用读', 1607, 1, 2, '禁用读', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1733, '禁用写', 1607, 1, 2, '禁用写', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n        (1735, '设置别名', 1605, 1, 2, '设置别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1737, '删除别名', 1605, 1, 2, '删除别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1739, '关闭索引', 1607, 1, 2, '关闭索引', '2022-05-24 18:08:24.0', '2022-07-15 09:52:25.0', 0, 'know_search'),\n        (1741, '下线', 1605, 1, 2, '下线', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1743, '批量删除', 1605, 1, 2, '批量删除', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1745, '查看列表', 1607, 1, 2, '查看列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1747, '执行Rollover', 1607, 1, 2, '执行Rollover', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1749, '执行shrink', 1607, 1, 2, '执行shrink', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1751, '执行split', 1607, 1, 2, '执行split', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n        (1753, '执行ForceMerge', 1607, 1, 2, '执行ForceMerge', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1755, '批量执行', 1607, 1, 2, '批量执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1757, 'DSL查询', 1877, 1, 2, 'DSL查询', '2022-05-24 18:08:24.0', '2022-09-05 14:24:00.0', 0, 'know_search'),\n        (1759, '查询模板', 0, 0, 1, '查看查询模板列表', '2022-05-24 18:08:24.0', '2022-08-11 10:37:43.0', 0, 'know_search'),\n        (1761, '查看集群看板', 1613, 1, 2, '查看集群看板', '2022-05-24 18:08:24.0', '2022-06-14 16:37:54.0', 0, 'know_search'),\n        (1763, '查看网关看板', 1615, 1, 2, '查看网关看板', '2022-05-24 18:08:24.0', '2022-06-14 16:38:14.0', 0, 'know_search'),\n        (1765, '查看我的申请列表', 1617, 1, 2, '查看我的申请列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1767, '撤回', 1617, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1769, '查看我的审批列表', 1619, 1, 2, '查看我的审批列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1771, '驳回', 1619, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-07-18 20:57:33.0', 0, 'know_search'),\n        (1773, '通过', 1619, 1, 2, '通过', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1775, '查看任务列表', 1621, 1, 2, '查看任务列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1777, '查看进度', 1621, 1, 2, '查看进度', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1779, '执行', 1621, 1, 2, '执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1781, '暂停', 1621, 1, 2, '暂停', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1783, '重试', 1621, 1, 2, '重试', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1785, '取消', 1621, 1, 2, '取消', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1787, '查看日志（子任务）', 1621, 1, 2, '查看日志（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n        (1789, '重试（子任务）', 1621, 1, 2, '重试（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1791, '忽略（子任务）', 1621, 1, 2, '忽略（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1793, '查看详情（DCDR）', 1621, 1, 2, '查看详情（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1795, '取消（DCDR）', 1621, 1, 2, '取消（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1797, '重试（DCDR）', 1621, 1, 2, '重试（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1799, '强切（DCDR）', 1621, 1, 2, '强切（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1801, '返回（DCDR）', 1621, 1, 2, '返回（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1803, '查看任务列表', 1623, 1, 2, '查看任务列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1805, '查看日志', 1623, 1, 2, '查看日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1807, '执行', 1623, 1, 2, '执行', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1809, '暂停', 1623, 1, 2, '暂停', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1811, '查看调度日志列表', 1625, 1, 2, '查看调度日志列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1813, '调度详情', 1625, 1, 2, '调度详情', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1815, '执行日志', 1625, 1, 2, '执行日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1817, '终止任务', 1625, 1, 2, '终止任务', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1819, '查看用户列表', 1627, 1, 2, '查看用户列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1821, '分配角色', 1627, 1, 2, '分配角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1823, '查看角色列表', 1629, 1, 2, '查看角色列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n        (1825, '编辑', 1629, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1827, '绑定用户', 1629, 1, 2, '绑定用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1829, '回收用户', 1629, 1, 2, '回收用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1831, '删除角色', 1629, 1, 2, '删除角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1833, '查看应用列表', 1631, 1, 2, '查看应用列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1835, '新建应用', 1631, 1, 2, '新建应用', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1837, '编辑', 1631, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1839, '删除', 1631, 1, 2, '删除', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1841, '访问设置', 1631, 1, 2, '访问设置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1843, '查看平台配置列表', 1633, 1, 2, '查看平台配置列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1845, '新增平台配置', 1633, 1, 2, '新增平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1847, '禁用平台配置', 1633, 1, 2, '禁用平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1849, '编辑平台配置', 1633, 1, 2, '编辑平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1851, '删除平台配置', 1633, 1, 2, '删除平台配置', '2022-05-24 18:08:26.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n        (1853, '查看操作记录列表', 1635, 1, 2, '查看操作记录列表', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1855, 'Kibana查询', 1879, 1, 2, 'Kibana查询', '2022-05-24 18:08:26.0', '2022-09-05 14:24:00.0', 1, 'know_search'),\n        (1857, 'SQL查询', 1881, 1, 2, 'SQL查询', '2022-05-24 18:08:26.0', '2022-09-05 14:24:00.0', 0, 'know_search'),\n        (1859, '批量修改限流值', 1759, 1, 2, '批量修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1861, '禁用', 1759, 1, 2, '禁用', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1863, '修改限流值', 1759, 1, 2, '修改限流值', '2022-05-24 18:08:26.0', '2022-08-11 10:37:13.0', 0, 'know_search'),\n        (1865, '查看异常查询列表', 1611, 1, 2, '查看异常查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n        (1867, '查看慢查询列表', 1611, 1, 2, '查看慢查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:21.0', 0, 'know_search'),\n        (1869, '新增角色', 1629, 1, 2, '新增角色', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1871, 'Dashboard', 0, 0, 1, '查看dashboard', '2022-05-24 18:08:26.0', '2022-08-27 17:35:50.0', 0, 'know_search'),\n        (1873, '新建索引', 1605, 1, 2, '新建索引', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n        (1875, '查看dashboard', 1871, 1, 2, '查看dashboard', '2022-05-24 18:08:24.0', '2022-08-27 17:35:50.0', 0, 'know_search'),\n        (1877, 'DSL', 0, 0, 1, 'DSL', '2022-05-24 18:08:24.0', '2022-09-02 19:01:17.0', 0, 'know_search'),\n        (1879, 'Kibana', 0, 0, 1, 'Kibana', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 1, 'know_search'),\n        (1881, 'SQL', 0, 0, 1, 'SQL', '2022-05-24 18:08:26.0', '2022-09-02 19:01:17.0', 0, 'know_search');\n\nalter table kf_security_oplog\n    modify target varchar(225) not null comment '操作对象';\n\nINSERT INTO `kf_security_permission` (`permission_name`, `parent_id`, `leaf`, `level`, `description`, `create_time`, `update_time`, `is_delete`, `app_name`) VALUES ('Grafana', 0, 0, 1, 'Grafana', '2022-05-24 18:08:26', '2022-12-22 15:16:17', 0, 'know_search');\nINSERT INTO `kf_security_role_permission` (`role_id`, `permission_id`, `create_time`, `update_time`, `is_delete`, `app_name`) VALUES (1, (select id from kf_security_permission ksp where ksp.permission_name='Grafana' and ksp.app_name='know_search' and ksp.is_delete=0 ), '2022-06-01 21:19:42', '2022-08-25 10:31:42', 0, 'know_search');\nINSERT INTO `kf_security_permission` (`permission_name`, `parent_id`, `leaf`, `level`, `description`, `create_time`, `update_time`, `is_delete`, `app_name`) VALUES ('查看Grafana', (select id from kf_security_permission ksp where ksp.permission_name='Grafana' and ksp.app_name='know_search' and ksp.is_delete=0 ), 1, 2, '查看Grafana', '2022-05-24 18:08:26', '2022-12-22 15:16:17', 0, 'know_search');\nINSERT INTO `kf_security_role_permission` (`role_id`, `permission_id`, `create_time`, `update_time`, `is_delete`, `app_name`) VALUES (1, (select id from kf_security_permission ksp where ksp.permission_name='查看Grafana' and ksp.app_name='know_search' and ksp.is_delete=0 ), '2022-06-01 21:19:42', '2022-08-25 10:31:42', 0, 'know_search');\n\n\nALTER TABLE es_cluster_phy_info\n    ADD proxy_address VARCHAR(255) DEFAULT '' NULL COMMENT ' 代理地址 ';"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius.appid.template.access",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.appid.template.access\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": -1,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"\\nappid 维度访问次数索引 \\n\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"date\\\":{\\\"format\\\":\\\"strict_date_optional_time||yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||yyyy-MM-dd||yyyyMMdd||yyyyMM||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"accessDetailInfo\\\":{\\\"dynamic\\\":\\\"false\\\",\\\"type\\\":\\\"object\\\"},\\\"templateName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"clusterName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"logicTemplateId\\\":{\\\"type\\\":\\\"long\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius.dsl.analyze.result",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.dsl.analyze.result\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": 3,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"DSL分析结果\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"date\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis||yyyy-MM-dd\\\",\\\"type\\\":\\\"date\\\"},\\\"overview\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"costQuantile\\\":{\\\"properties\\\":{\\\"50_0\\\":{\\\"type\\\":\\\"float\\\"},\\\"75_0\\\":{\\\"type\\\":\\\"float\\\"},\\\"95_0\\\":{\\\"type\\\":\\\"float\\\"},\\\"99_0\\\":{\\\"type\\\":\\\"float\\\"}}},\\\"qpsMetric\\\":{\\\"properties\\\":{\\\"minQpsTime\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"},\\\"avgQps\\\":{\\\"type\\\":\\\"long\\\"},\\\"maxQpsTime\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"},\\\"minQps\\\":{\\\"type\\\":\\\"long\\\"},\\\"maxQps\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"count\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"errorDsls\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"details\\\":{\\\"properties\\\":{\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"name\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"details\\\":{\\\"properties\\\":{\\\"dslTemplate\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"indices\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"dslTemplateMd5\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"}}}}}}},\\\"dslTotalCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"slowDsls\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"details\\\":{\\\"properties\\\":{\\\"dslTemplate\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"indices\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"cost\\\":{\\\"type\\\":\\\"float\\\"},\\\"dslTemplateMd5\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"cause\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"slowDslThreshold\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"slowReasonType\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"}}}}},\\\"errDetailInfo\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"slowSearchCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"errSearchCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis||yyyy-MM-dd\\\",\\\"type\\\":\\\"date\\\"},\\\"dslTemplates\\\":{\\\"dynamic\\\":\\\"true\\\",\\\"properties\\\":{\\\"dslTotalCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslIncCnt\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"searchTotalCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"accessGatewayInfo\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"ariusType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslIncCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"day\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis||yyyy-MM-dd\\\",\\\"type\\\":\\\"date\\\"}}}\",\n  \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius.dsl.metrics",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.dsl.metrics\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timeStamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"用户查询聚合信息\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"ariusCreateTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"projectIdDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"searchCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslLevel\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"successfulShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTemplate\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"dslType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appidDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"responseLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"requestType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"searchType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"esCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"gatewayNode\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"dslLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalHitsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"version\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"indiceSample\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indices\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"dslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"isFromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"totalCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"failedShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"long\\\"},\\\"beforeCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius.dsl.template",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.dsl.template\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": -1,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"DSL 审核与分析\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"ariusCreateTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"projectIdDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"fromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"searchCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"dslLevel\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"my_all_fields\\\":{\\\"ignore_above\\\":2048,\\\"type\\\":\\\"keyword\\\"},\\\"successfulShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTemplate\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"ignore_above\\\":32766,\\\"type\\\":\\\"keyword\\\"},\\\"dslType\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"appidDslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"enable\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"sinkTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"day\\\":{\\\"type\\\":\\\"date\\\"},\\\"responseLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"requestType\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"searchType\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"ariusModifyTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"slowDslThreshold\\\":{\\\"type\\\":\\\"long\\\"},\\\"esCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslLenAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"gatewayNode\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"totalHitsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"version\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"forceSetQueryLimit\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"boolean\\\"},\\\"indiceSample\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indices\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"ignore_above\\\":32766,\\\"type\\\":\\\"keyword\\\"},\\\"dslTemplateMd5\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"isFromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"totalCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"checkMode\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"keyword\\\"},\\\"failedShardsAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"dslTag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"queryLimit\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"type\\\":\\\"double\\\"},\\\"dsl\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"long\\\"},\\\"beforeCostAvg\\\":{\\\"type\\\":\\\"double\\\"},\\\"flinkTime\\\":{\\\"copy_to\\\":[\\\"my_all_fields\\\"],\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius.gateway.join",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.gateway.join\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timeStamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"gateway 日志按照 requestId 进行 join\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"String \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_query_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"selectFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"stack\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"orderId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"searchCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"String\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"responseLen\\\":{\\\"type\\\":\\\"long\\\"},\\\"Count\\\":{\\\"type\\\":\\\"long\\\"},\\\"beforeCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"isTimedOut\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_exception_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dslTemplate\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"searchId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"x-username\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"action\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_replace_index_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"internalCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"exceptionName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"tookInMillis\\\":{\\\"type\\\":\\\"long\\\"},\\\"traceId\\\":{\\\"type\\\":\\\"float\\\"},\\\"customKey\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_exception_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"method\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_query_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"index\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"indexTypeName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"whereFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"queryString\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"Long` from newton_strategy_2020-07-18_v2 WHERE bizType \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"version\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_tcp_response_length_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dslLen\\\":{\\\"type\\\":\\\"long\\\"},\\\"flowModuleId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"totalHits\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_request_node_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"before_cost\\\":{\\\"type\\\":\\\"long\\\"},\\\"statusCode\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_pre_exception_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"status\\\":{\\\"type\\\":\\\"long\\\"},\\\"traceid\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"isUrgent\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"TimeUsed\\\":{\\\"type\\\":\\\"long\\\"},\\\"pre_alloctication_group\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"sourceTemplateName\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"groupByFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"typeName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"failedShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"routing\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"instanceId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_indices_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"client_node\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_replace_index_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"esCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"requestId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"clusterName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"sortByFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"Long` \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_exception_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"remoteAddr\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"lastBucketNumber\\\":{\\\"type\\\":\\\"long\\\"},\\\"dltagCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"Long \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"successfulShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"String` \\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"gatewayNode\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"uri\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"destIndexName\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"url\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_tcp_search_scroll_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"timeStamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indices\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"scrollIdList\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"@timestamp\\\":{\\\"format\\\":\\\"strict_date_optional_time\\\",\\\"type\\\":\\\"date\\\"},\\\"stage\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"postBody\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clientIp\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_pre_exception_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"postBodyLen\\\":{\\\"type\\\":\\\"long\\\"},\\\"proc_time\\\":{\\\"type\\\":\\\"long\\\"},\\\"logicId\\\":{\\\"type\\\":\\\"long\\\"},\\\"Decimal \\\":{\\\"type\\\":\\\"float\\\"},\\\"ariusCreateTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"totalHitsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"xUserName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clientVersion\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"operator\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"Name\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"fetchCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_tcp_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"successShardsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"costTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"paramCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"ariusType\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_indices_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indiceCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_aggs_detail_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_search_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"group\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"orderByFields\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"res\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"timedOut\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"clientHost\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_fetch_message_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"totalShardsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"isTimeoutList\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"searchType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"Targ\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_before_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dltag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_request_before_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_request_node_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_response_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_query_tcp_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"success\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"dslTag\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"name\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"memUsed\\\":{\\\"type\\\":\\\"long\\\"},\\\"bucketNumber\\\":{\\\"type\\\":\\\"long\\\"},\\\"dsl\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"totalCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"sourceIndexNames\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"getClientCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"Errno\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexTemplateCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterId\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"dslLevel\\\":{\\\"type\\\":\\\"long\\\"},\\\"timeout\\\":{\\\"type\\\":\\\"long\\\"},\\\"failedShardsList\\\":{\\\"type\\\":\\\"long\\\"},\\\"totalShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"scrollId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"sql\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"destTemplateName\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_aggs_detail_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"dslType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"preProcessCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_query_tcp_response_length_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"newDslTemplate\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"param\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_internal_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"aggsLevel\\\":{\\\"type\\\":\\\"long\\\"},\\\"json\\\":{\\\"type\\\":\\\"object\\\"},\\\"_arius_query_tcp_request_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clientNode\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"rcvTimeout\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_scroll_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"types\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"cost\\\":{\\\"type\\\":\\\"long\\\"},\\\"_arius_exception_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"requestType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"fetchSize\\\":{\\\"type\\\":\\\"long\\\"},\\\"esCostList\\\":{\\\"type\\\":\\\"long\\\"},\\\"aggsBukcetInfo\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"fetchMetric\\\":{\\\"properties\\\":{\\\"parseMessageCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"fetchMissingCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"getConsumeCost\\\":{\\\"type\\\":\\\"long\\\"},\\\"fetchOffsetCnt\\\":{\\\"type\\\":\\\"long\\\"},\\\"brokerHost\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"fetchMetricInfo\\\":{\\\"properties\\\":{\\\"cost\\\":{\\\"type\\\":\\\"long\\\"},\\\"partition\\\":{\\\"type\\\":\\\"long\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"topic\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"}}},\\\"partitionTotalCost\\\":{\\\"type\\\":\\\"long\\\"}}},\\\"_arius_response_index_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"message\\\":{\\\"ignore_above\\\":2048,\\\"index\\\":false,\\\"type\\\":\\\"keyword\\\"},\\\"userName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_msg\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_search_request_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_fetch_message_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"indiceSample\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_internal_flinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"isFromUserConsole\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"dslTemplateMd5\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_tcp_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"service\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"user\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"_arius_query_search_response_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_arius_response_index_logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"queryRequest\\\":{\\\"type\\\":\\\"boolean\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"60s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius.template.access",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius.template.access\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": -1,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"索引模板维度访问次数索引\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"date\\\":{\\\"format\\\":\\\"strict_date_optional_time||yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||yyyy-MM-dd||yyyyMMdd||yyyyMM||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"templateName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"clusterName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"count\\\":{\\\"type\\\":\\\"long\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"logicTemplateId\\\":{\\\"type\\\":\\\"long\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius_cat_index_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_cat_index_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"索引列表\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"priStoreSize\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"clusterLogic\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"resourceId\\\":{\\\"type\\\":\\\"long\\\"},\\\"platformCreateFlag\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"pri\\\":{\\\"type\\\":\\\"long\\\"},\\\"health\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"docsDeleted\\\":{\\\"type\\\":\\\"long\\\"},\\\"deleteFlag\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"totalSegmentCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterPhy\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"appId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"storeSize\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"primariesSegmentCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"rep\\\":{\\\"type\\\":\\\"long\\\"},\\\"docsCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"integer\\\"},\\\"key\\\":{\\\"ignore_above\\\":1024,\\\"type\\\":\\\"keyword\\\"},\\\"status\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius_cat_shard_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_cat_shard_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"shard 分配数据\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"prirep\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"docs\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterPhy\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"ip\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shard\\\":{\\\"type\\\":\\\"long\\\"},\\\"state\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"store\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n  \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius_gateway_metrics",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_gateway_metrics\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"gateway 指标数据\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"query_totalHits_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_request_avg_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_aggs_count\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_count\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_response_avg_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_avg_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_min_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_imin_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"type\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"index_response_length\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_max_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_response_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_imax_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_cost_imax_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_stdev_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_max_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_imax_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_request_length\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_stdev_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"slowlog_cost_imax_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"_FLINK_DATA_TIME\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_imin_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_cost_min_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_totalShards_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_request_avg_length_stdev_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_cost_stdev_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_tookInMillis_avg_millis\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_max_length\\\":{\\\"type\\\":\\\"long\\\"},\\\"slowlog_cost_imin_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"template\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"hostName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"index_cost_imax_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_cost_imin_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_failedShards_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_failedShards_avg_count\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_tookInMillis_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_max_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_max_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_response_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"_FLINK_SINK_TIME\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"index_response_avg_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_cost_avg_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_request_length_avg_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"index_response_avg_length_stdev_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_min_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_request_length_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_totalHits_avg_count\\\":{\\\"type\\\":\\\"float\\\"},\\\"slowlog_count\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"index_cost_num_ops\\\":{\\\"type\\\":\\\"long\\\"},\\\"appid\\\":{\\\"type\\\":\\\"long\\\"},\\\"query_cost_min_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"query_totalShards_avg_count\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_response_avg_length_min_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_request_avg_length_imin_length\\\":{\\\"type\\\":\\\"float\\\"},\\\"operation\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"index_cost_avg_time\\\":{\\\"type\\\":\\\"float\\\"},\\\"index_count\\\":{\\\"type\\\":\\\"long\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius_stats_cluster_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_cluster_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"desc\": \"\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"physicCluster\\\":{\\\"type\\\":\\\"long\\\"},\\\"dataCenter\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"es_index_time\\\":{\\\"type\\\":\\\"long\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"cleanTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"statis\\\":{\\\"properties\\\":{\\\"cpuUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"statusType\\\":{\\\"type\\\":\\\"long\\\"},\\\"numberPendingTasks\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalTemplateNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"activeNodeNu\\\":{\\\"type\\\":\\\"long\\\"},\\\"invalidNodeNu\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"esNodeNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalIndicesNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"totalStoreSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"level\\\":{\\\"type\\\":\\\"long\\\"},\\\"sla\\\":{\\\"type\\\":\\\"double\\\"},\\\"sendTransSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"taskCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"cpuLoad15M\\\":{\\\"type\\\":\\\"double\\\"},\\\"alivePercent\\\":{\\\"type\\\":\\\"long\\\"},\\\"shardNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"freeStoreSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"memUsed\\\":{\\\"type\\\":\\\"long\\\"},\\\"memFreePercent\\\":{\\\"type\\\":\\\"float\\\"},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"unAssignedShards\\\":{\\\"type\\\":\\\"long\\\"},\\\"appNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"cpuLoad1M\\\":{\\\"type\\\":\\\"double\\\"},\\\"cpuLoad5M\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexStoreSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"nodeNamesForDiskUsageGte75Percent\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"totalDocNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"extendInfoMap\\\":{\\\"type\\\":\\\"object\\\"},\\\"memUsedPercent\\\":{\\\"type\\\":\\\"float\\\"},\\\"clusterName\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"storeSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexingLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"nodeIpsForDiskUsageGte75Percent\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"numberNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"recvTransSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"memFree\\\":{\\\"type\\\":\\\"long\\\"},\\\"readTps\\\":{\\\"type\\\":\\\"double\\\"},\\\"memTotal\\\":{\\\"type\\\":\\\"long\\\"},\\\"numberDataNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"writeTps\\\":{\\\"type\\\":\\\"double\\\"},\\\"numberIngestNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"numberMasterNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"queryTimesPreDay\\\":{\\\"type\\\":\\\"double\\\"},\\\"taskCost\\\":{\\\"type\\\":\\\"double\\\"},\\\"numberClientNodes\\\":{\\\"type\\\":\\\"long\\\"},\\\"diskUsage\\\":{\\\"type\\\":\\\"double\\\"}}},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"percentilesType\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius_stats_cluster_task_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_cluster_task_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"physicCluster\\\":{\\\"type\\\":\\\"long\\\"},\\\"dataCenter\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"metrics\\\":{\\\"properties\\\":{\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"parentTaskId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"ip\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"action\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"runningTimeString\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"description\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"startTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"runningTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"type\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"taskId\\\":{\\\"type\\\":\\\"keyword\\\"}}},\\\"key\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n  \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius_stats_dashboard_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_dashboard_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 15,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"template\\\":{\\\"properties\\\":{\\\"template\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"segmentMemSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"templateName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"cluster\\\":{\\\"properties\\\":{\\\"elapsedTimeGte5Min\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexCount\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"gatewayFailedPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"clusterElapsedTimeGte5Min\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"httpNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"collectorDelayed\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexReqNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"nodeElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"clusterElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"gatewaySucPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"pendingTaskNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"indexingLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"elapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"nodeMetrics\\\":{\\\"properties\\\":{\\\"largeHead\\\":{\\\"type\\\":\\\"double\\\"},\\\"nodeElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"taskConsuming\\\":{\\\"type\\\":\\\"long\\\"},\\\"largeDiskUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"largeCpuUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"writeRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"dead\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"SearchRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"templateMetrics\\\":{\\\"properties\\\":{\\\"template\\\":{\\\"type\\\":\\\"long\\\"},\\\"segmentMemSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"physicCluster\\\":{\\\"type\\\":\\\"integer\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"nodeThreadPoolQueueMetrics\\\":{\\\"properties\\\":{\\\"search\\\":{\\\"type\\\":\\\"long\\\"},\\\"flush\\\":{\\\"type\\\":\\\"long\\\"},\\\"management\\\":{\\\"type\\\":\\\"long\\\"},\\\"merge\\\":{\\\"type\\\":\\\"long\\\"},\\\"refresh\\\":{\\\"type\\\":\\\"long\\\"},\\\"write\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"index\\\":{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"mappingNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"red\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"segmentMemSize\\\":{\\\"type\\\":\\\"float\\\"},\\\"smallShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"bigShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"shardSize\\\":{\\\"type\\\":\\\"long\\\"},\\\"singReplicate\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"memSize\\\":{\\\"type\\\":\\\"double\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"unassignedShard\\\":{\\\"type\\\":\\\"boolean\\\"}}},\\\"clusterPhyHealth\\\":{\\\"properties\\\":{\\\"unknownClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"unknownNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"redNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"totalNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"greenClusterListStr\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"greenNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"yellowClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"yellowNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"redClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"clusterPhyHealthMetrics\\\":{\\\"properties\\\":{\\\"unknownClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"unknownNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"redNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"totalNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"greenNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"active\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"yellowClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"yellowNum\\\":{\\\"type\\\":\\\"integer\\\"},\\\"redClusterListStr\\\":{\\\"type\\\":\\\"text\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"node\\\":{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"taskConsuming\\\":{\\\"type\\\":\\\"long\\\"},\\\"dead\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"nodeElapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"largeHead\\\":{\\\"type\\\":\\\"double\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"largeDiskUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"searchRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"largeCpuUsage\\\":{\\\"type\\\":\\\"double\\\"},\\\"writeRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"SearchRejectedNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"elapsedTime\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"clusterThreadPoolQueue\\\":{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"search\\\":{\\\"type\\\":\\\"long\\\"},\\\"flush\\\":{\\\"type\\\":\\\"long\\\"},\\\"management\\\":{\\\"type\\\":\\\"long\\\"},\\\"merge\\\":{\\\"type\\\":\\\"long\\\"},\\\"refresh\\\":{\\\"type\\\":\\\"long\\\"},\\\"write\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"indexMetrics\\\":{\\\"properties\\\":{\\\"red\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"mappingNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"smallShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"segmentNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"bigShard\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"singReplicate\\\":{\\\"type\\\":\\\"boolean\\\"},\\\"memSize\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"unassignedShard\\\":{\\\"type\\\":\\\"boolean\\\"}}},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"clusterMetrics\\\":{\\\"properties\\\":{\\\"indexReqNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"shardNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"reqUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"gatewaySucPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"pendingTaskNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"searchLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"docUprushNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"gatewayFailedPer\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexingLatency\\\":{\\\"type\\\":\\\"double\\\"},\\\"httpNum\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius_stats_index_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_index_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"template\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"index\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"templateId\\\":{\\\"type\\\":\\\"long\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"cleanTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"shardNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"metrics\\\":{\\\"properties\\\":{\\\"refresh-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_scroll_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"store-size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-docs-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"docs-count-total\\\":{\\\"type\\\":\\\"float\\\"},\\\"fielddata-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-fetch_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-refresh-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"merges-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-doc_values_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments_segments_request_cache_memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-query_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_time_per_doc\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_index_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-index_writer_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-merges-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-request_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"request_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-index_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"store-size_in_bytes_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"query_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_refresh_total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments_fielddata_memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-scroll_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments_fixed_bit_set_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"docs-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"shardNu\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-fetch_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-version_map_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"refresh-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"merges-total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments_norms_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_fetch_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_query_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"flush-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_flush_total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-fetch_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-docs-count_diff\\\":{\\\"type\\\":\\\"double\\\"},\\\"refresh-total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments_version_map_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-breakers-fieldd-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"translog-size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"flush-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-fetch_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"flush-total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_total_times\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merge_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"merges-current\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-fixed_bit_set_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-breakers-fielddata-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-query_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_time_per_doc\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost-flush-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-scroll_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-points_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"cost_merges_total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-norms_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_latency\\\":{\\\"type\\\":\\\"float\\\"},\\\"segments-term_vectors_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"segments-stored_fields_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"store-size_in_bytes-total\\\":{\\\"type\\\":\\\"float\\\"},\\\"merges-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-cost-merges-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indexing-index_failed_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"search-fetch_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush_avg_time\\\":{\\\"type\\\":\\\"double\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"logicTemplateId\\\":{\\\"type\\\":\\\"long\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/arius_stats_node_info",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"arius_stats_node_info\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 1,\n  \"expireTime\": 3,\n  \"dateField\": \"timestamp\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 30,\n  \"dataType\": 0,\n  \"mapping\": \"{\\\"properties\\\":{\\\"cluster\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"collectTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"rack\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"routingValue\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"ignore_above\\\":256,\\\"type\\\":\\\"keyword\\\"}}},\\\"ip\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"logTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"cleanTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"node\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"port\\\":{\\\"type\\\":\\\"long\\\"},\\\"sinkTime\\\":{\\\"format\\\":\\\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\\\",\\\"type\\\":\\\"date\\\"},\\\"metrics\\\":{\\\"properties\\\":{\\\"thread_pool-force_merge-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-heap_used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-bulk-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-miss_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-hit_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-load_average-5m\\\":{\\\"type\\\":\\\"double\\\"},\\\"process-cpu-percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_current\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-store-size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges-current\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-breakers-fielddata-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-write-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-request-estimated_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-server_open\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-in_flight_requests-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-translog-uncommitted_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-hit_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-index_writer_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-total_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-term_vectors_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-refresh-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-tx_size_in_bytes_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"script-compilations\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-total_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-load_average-15m\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-search-completed\\\":{\\\"type\\\":\\\"double\\\"},\\\"http-current_open\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_count_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-index_latency\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-pools-old-used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-disk_free_percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-bulk-rejected\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-bulk-completed\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_latency\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-search-rejected\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_time_per_query\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-docs-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu_percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-miss_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-pools-young-used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-heap_used_percent\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-norms_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-cache_size\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-rx_size_in_bytes_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"os-cpu-load_average-1m\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-stored_fields_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-parent-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_time_per_fetch\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-mem-non_heap_used_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-evictions\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-rollup_indexing-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-evictions\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-translog-operations_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-threads-count\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-accounting-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-rx_count_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_avg_time\\\":{\\\"type\\\":\\\"double\\\"},\\\"transport-tx_count_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-fielddata-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-merges-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-request-limit_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-parent-estimated_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-delete_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-docs-count_diff\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-fixed_bit_set_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-scroll_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-management-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-doc_values_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_total_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-query_total\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-points_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-memory_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"ingest-total-failed\\\":{\\\"type\\\":\\\"float\\\"},\\\"indices-search-scroll_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-write-rejected\\\":{\\\"type\\\":\\\"double\\\"},\\\"process-process-open_file_descriptors\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-accounting-estimated_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-in_flight_requests-estimated_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-query_cache-total_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-available_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"fs-total-free_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-indexing-index_time_per_doc\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-young-collection_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-refresh-total\\\":{\\\"type\\\":\\\"double\\\"},\\\"breakers-fielddata-estimated_size_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-flush-total_time_in_millis\\\":{\\\"type\\\":\\\"double\\\"},\\\"thread_pool-write-completed\\\":{\\\"type\\\":\\\"double\\\"},\\\"ingest-total-current\\\":{\\\"type\\\":\\\"float\\\"},\\\"ingest-total-count\\\":{\\\"type\\\":\\\"float\\\"},\\\"ingest-total-time_in_millis\\\":{\\\"type\\\":\\\"float\\\"},\\\"thread_pool-search-queue\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-hit_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-request_cache-hit_count\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-segments-version_map_memory_in_bytes\\\":{\\\"type\\\":\\\"double\\\"},\\\"indices-search-fetch_time_in_millis_rate\\\":{\\\"type\\\":\\\"double\\\"},\\\"jvm-gc-old-collection_count_rate\\\":{\\\"type\\\":\\\"double\\\"}}},\\\"key\\\":{\\\"ignore_above\\\":512,\\\"type\\\":\\\"keyword\\\"},\\\"timestamp\\\":{\\\"format\\\":\\\"epoch_millis\\\",\\\"type\\\":\\\"date\\\"}}}\",\n   \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"30s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/0.3.1.2/template_in_arius/index_observability",
    "content": "{\n  \"dataCenter\": \"cn\",\n  \"name\": \"index_observability\",\n  \"resourceId\": #resourceId,\n  \"level\": 1,\n  \"cyclicalRoll\": 0,\n  \"expireTime\": -1,\n  \"dateField\": \"logTime\",\n  \"dateFieldFormat\": \"epoch_millis\",\n  \"diskSize\": 200,\n  \"dataType\": 0,\n  \"desc\": \"可观测性对接数据上报模版\",\n  \"mapping\": \"{\\\"properties\\\":{\\\"logType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"hostName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"fileName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"metricName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"httpTarget\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"endEpochNanos\\\":{\\\"type\\\":\\\"long\\\"},\\\"logThread\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"diskPath\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"metricValue\\\":{\\\"type\\\":\\\"double\\\"},\\\"className\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"httpMethod\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"deviceName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"metricUnit\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"spanId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"metricType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"logLevel\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"httpUrl\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"instrumentationScopeInfoName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"tracerName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"httpHost\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"applicationName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"traceId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"sqlStatement\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"spanKind\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"ip\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"methodName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"exemplarData\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"message\\\":{\\\"copy_to\\\":[\\\"message_full_name\\\"],\\\"type\\\":\\\"text\\\"},\\\"metricEpochNanos\\\":{\\\"type\\\":\\\"date\\\"},\\\"spentNanos\\\":{\\\"type\\\":\\\"long\\\"},\\\"httpScheme\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"parentSpanId\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"spanName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"component\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"sqlType\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"startEpochNanos\\\":{\\\"type\\\":\\\"long\\\"},\\\"metricDescription\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"logName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"TaskName\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"message_full_name\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"logMills\\\":{\\\"type\\\":\\\"date\\\"},\\\"tracerVersion\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"lineNumber\\\":{\\\"type\\\":\\\"long\\\"},\\\"statusData\\\":{\\\"type\\\":\\\"keyword\\\"},\\\"JobClassName\\\":{\\\"type\\\":\\\"keyword\\\"}}}\",\n  \"setting\": \"{\\\"index\\\":{\\\"translog.durability\\\":\\\"async\\\",\\\"translog.sync_interval\\\":\\\"15s\\\",\\\"refresh_interval\\\":\\\"1s\\\"}}\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/core_index_template/index_template.sql",
    "content": "# ----------------------------------------------平台核心索引模版元数据\n-- auto-generated definition\ncreate table if not exists index_template_info\n(\n    id                bigint unsigned auto_increment comment '主键自增'\n        primary key,\n    name              varchar(128)                 default ''                not null comment '名称',\n    data_type         tinyint                      default -1                not null comment '数据类型',\n    date_format       varchar(50)                  default ''                not null comment '索引分区的时间后缀',\n    is_active         tinyint(2)                   default 1                 not null comment '有效标记',\n    data_center       varchar(20)                  default ''                not null comment '数据中心',\n    expire_time       bigint                       default -1                not null comment '保存时长',\n    hot_time          int(10)                      default -1                not null comment '热数据保存时长',\n    responsible       varchar(500)                 default ''                null comment '责任人',\n    date_field        varchar(50)                  default ''                not null comment '时间字段',\n    date_field_format varchar(128)                 default ''                not null comment '时间字段的格式',\n    id_field          varchar(512)                 default ''                null comment 'id字段',\n    routing_field     varchar(512)                 default ''                null comment 'routing字段',\n    expression        varchar(100)                 default ''                not null comment '索引表达式',\n    `desc`            varchar(500)                 default ''                not null comment '索引描述',\n    quota             decimal(10, 3)               default -1.000            not null comment '规格',\n    project_id        int(10)                      default -1                not null comment 'project_id',\n    ingest_pipeline   varchar(512)                 default ''                not null comment 'ingest_pipeline',\n    block_read        tinyint(1) unsigned zerofill default 0                 not null comment '是否禁读，0：否，1：是',\n    block_write       tinyint(1) unsigned zerofill default 0                 not null comment '是否禁写，0：否，1：是',\n    create_time       timestamp                    default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time       timestamp                    default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间',\n    write_rate_limit  bigint(255)                  default -1                not null comment '写入限流值',\n    resource_id       bigint                       default -1                not null comment '逻辑集群id',\n    check_point_diff  bigint(100)                  default 0                 not null comment 'dcdr位点差',\n    level             tinyint                      default 1                 not null comment '服务等级分为1,2,3',\n    has_dcdr          tinyint(1) unsigned zerofill default 0                 not null comment '是否开启dcdr',\n    open_srv          varchar(255)                                           null comment '已开启的模板服务',\n    disk_size         decimal(10, 3)               default -1.000            null comment '可用磁盘容量'\n)\n    comment '逻辑索引模板表' charset = utf8;\n\ncreate index idx_data_center\n    on index_template_info (data_center);\n\ncreate index idx_is_active\n    on index_template_info (is_active);\n\ncreate index idx_name\n    on index_template_info (name);\n\ncreate index idx_project_id\n    on index_template_info (project_id);\ninsert into index_template_info (id, name, data_type, date_format, is_active, data_center, expire_time,\n                                 hot_time, responsible, date_field, date_field_format, id_field,\n                                 routing_field, expression, desc, quota, project_id, ingest_pipeline,\n                                 block_read, block_write, create_time, update_time, write_rate_limit,\n                                 resource_id, check_point_diff, level, has_dcdr, open_srv, disk_size)\nvalues (24007, 'arius.appid.template.access', 2, '', 1, 'cn', -1, -1, 'admin', 'logTime', '', '', '',\n        'arius.appid.template.access', 'appid维度访问次数索引', 1.000, 1, '', 0, 0, '2019-12-19 01:05:29.0',\n        '2022-07-21 15:43:00.0', -1, 3865, 0, 1, 0, '2', 1.000),\n       (1, 'arius.dsl.analyze.result', 0, '', 1, 'cn', -1, -1, '', 'logTime', '', '', '', 'arius.dsl.analyze.result',\n        'DSL分析结果', 60.000, 1, 'arius.dsl.analyze.result', 0, 0, '2021-07-24 15:21:49.0', '2022-07-21 12:21:13.0', -1,\n        3865, 0, 1, 0, '2', 60.000),\n       (5, 'arius.dsl.metrics', 0, '_yyyy-MM-dd', 1, 'cn', 150, -1, '', 'timeStamp', '', '', '', 'arius.dsl.metrics*',\n        '用户查询聚合信息', 60.000, 1, 'arius.dsl.metrics', 0, 0, '2021-07-24 15:21:52.0', '2022-07-21 15:43:18.0', -1, 3865, 0,\n        1, 0, '2,1,4', 60.000),\n       (7, 'arius.dsl.template', 0, '', 1, 'cn', -1, -1, '', 'logTime', '', '', '', 'arius.dsl.template', 'DSL审核与分析',\n        60.000, 1, 'arius.dsl.template', 0, 0, '2021-07-24 15:21:53.0', '2022-07-21 12:20:49.0', -1, 3865, 0, 1, 0, '2',\n        60.000),\n       (9, 'arius.gateway.join', 0, '_yyyy-MM-dd', 1, 'cn', 23, -1, '', 'timeStamp', '', '', '', 'arius.gateway.join*',\n        'gateway日志按照requestId进行join', 60.000, 1, 'arius.gateway.join', 0, 0, '2021-07-24 15:21:55.0',\n        '2022-07-21 15:43:15.0', -1, 3865, 0, 1, 0, '2,1,4', 60.000),\n       (14377, 'arius.template.access', 0, '', 1, 'cn', -1, -1, '1', 'logTime', '', '', '', 'arius.template.access',\n        '索引模板维度访问次数索引', 30.000, 1, 'arius.template.access', 0, 0, '2021-11-30 12:18:00.0', '2022-07-21 15:43:10.0', -1,\n        3865, 0, 1, 0, '2', 30.000),\n       (14379, 'arius_cat_index_info', 0, '_yyyy-MM-dd', 1, 'cn', 3, -1, '1', 'timestamp', '', '', '',\n        'arius_cat_index_info*', '索引列表', 30.000, 1, 'arius_cat_index_info', 0, 0, '2021-11-30 12:18:07.0',\n        '2022-07-21 15:43:09.0', -1, 3865, 0, 1, 0, '1,4,2', 30.000),\n       (14381, 'arius_gateway_metrics', 0, '_yyyy-MM-dd', 1, 'cn', 30, -1, '1', 'timestamp', '', '', '',\n        'arius_gateway_metrics*', 'gateway指标数据', 30.000, 1, 'arius_gateway_metrics', 0, 0, '2021-11-30 12:18:10.0',\n        '2022-07-21 15:43:07.0', -1, 3865, 0, 1, 0, '1,4,2', 30.000),\n       (14387, 'arius_stats_cluster_info', 0, '_yyyy-MM-dd', 1, 'cn', 180, -1, '1', 'timestamp', '', '', '',\n        'arius_stats_cluster_info*', '', 30.000, 1, 'arius_stats_cluster_info', 0, 0, '2021-11-30 12:18:20.0',\n        '2022-07-21 15:43:05.0', -1, 3865, 0, 1, 0, '1,4,2', 30.000),\n       (14493, 'arius_stats_cluster_task_info', 0, '_yyyy-MM-dd', 1, 'cn', 7, -1, '1', 'timestamp', 'epoch_millis', '',\n        '', 'arius_stats_cluster_task_info*', '111', 0.012, 1, 'arius_stats_cluster_task_info', 0, 1,\n        '2022-01-14 15:27:52.0', '2022-07-21 15:43:04.0', -1, 3865, 0, 1, 0, '1,4,2', 0.012),\n       (24001, 'arius_stats_dashboard_info', 2, '_yyyy-MM-dd', 1, 'cn', 15, -1, '59,312,60', 'timestamp',\n        'epoch_millis', '', '', 'arius_stats_dashboard_info*', '', 0.006, 1697, 'arius_stats_dashboard_info', 0, 1,\n        '2022-04-18 09:51:19.0', '2022-07-21 15:43:02.0', -1, 3865, 0, 1, 0, '1,4,2', 0.006),\n       (14353, 'arius_stats_index_info', 1, '_yyyy-MM-dd', 1, 'cn', 180, -1, '1', 'timestamp', 'epoch_millis', '', '',\n        'arius_stats_index_info*', '', 30.000, 1, 'arius_stats_index_info', 0, 1, '2021-11-30 12:16:44.0',\n        '2022-07-21 15:43:14.0', -1, 3865, 0, 1, 0, '1,4,2', 30.000),\n       (14361, 'arius_stats_node_info', 0, '_yyyy-MM-dd', 1, 'cn', 180, -1, '1', 'timestamp', 'epoch_millis', '', '',\n        'arius_stats_node_info*', '', 30.000, 1, 'arius_stats_node_info', 0, 0, '2021-11-30 12:17:03.0',\n        '2022-07-21 15:43:12.0', -1, 3865, 0, 1, 0, '1,4,2', 30.000);\n\n# ------------------------------------物理模版关联元数据逻辑模版信息\n-- auto-generated definition\ncreate table if not exists index_template_physical_info\n(\n    id            bigint unsigned auto_increment comment '主键自增'\n        primary key,\n    logic_id      int(10)      default -1                not null comment '逻辑模板id',\n    name          varchar(128) default ''                not null comment '模板名字',\n    expression    varchar(128) default ''                not null comment '表达式',\n    cluster       varchar(128) default ''                not null comment '集群名字',\n    rack          varchar(512) default ''                not null comment 'rack',\n    shard         int(10)      default 1                 not null comment 'shard个数',\n    shard_routing int(10)      default 1                 not null comment '内核的逻辑shard',\n    version       int(10)      default 0                 not null comment '版本',\n    role          tinyint      default 1                 not null comment '角色 1master 2slave',\n    status        tinyint      default 1                 not null comment '1 常规 -1 索引删除中 -2已删除',\n    config        text                                   null comment '配置 json格式',\n    create_time   timestamp    default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time   timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    region_id     int(10)      default -1                not null comment '模板关联的regionId'\n)\n    comment '物理模板信息' charset = utf8;\n\ncreate index idx_cluster_name_status\n    on index_template_physical_info (cluster, name, status);\n\ncreate index idx_log_id_statud\n    on index_template_physical_info (logic_id, status);\n\ncreate index idx_logic_id\n    on index_template_physical_info (logic_id);\n\ncreate index idx_region_id\n    on index_template_physical_info (region_id);\n\ncreate index idx_status\n    on index_template_physical_info (status);\ninsert into index_template_physical_info (id, logic_id, name, expression, cluster, rack, shard,\n                                          shard_routing, version, role, status, config, create_time,\n                                          update_time, region_id)\nvalues (6011, 24007, 'arius.appid.template.access', 'arius.appid.template.access', 'logi-elasticsearch-7.6.0',\n        'r1,r2,r3,r4,r5', 10, 1, 1, 1, 1, '{\"pipeLineRateLimit\":1000000}', '2019-12-19 01:05:30.0',\n        '2022-07-19 15:40:42.0', 3741),\n       (1, 1, 'arius.dsl.analyze.result', 'arius.dsl.analyze.result', 'logi-elasticsearch-7.6.0', 'r2', 1, 4, 0, 1, 1,\n        '{\"defaultWriterFlags\":true,\"groupId\":\"7f500f20-3b0b-41d9-bdfa-9d331b266f4b\",\"pipeLineRateLimit\":1000000}',\n        '2021-07-24 15:21:49.0', '2022-06-28 15:39:23.0', 3741),\n       (5, 5, 'arius.dsl.metrics', 'arius.dsl.metrics*', 'logi-elasticsearch-7.6.0', 'r2', 1, 4, 0, 1, 1,\n        '{\"defaultWriterFlags\":true,\"groupId\":\"ad7cd006-620c-447f-ab7e-30679c6104cf\",\"pipeLineRateLimit\":2208000}',\n        '2021-07-24 15:21:52.0', '2022-06-28 15:39:23.0', 3741),\n       (7, 7, 'arius.dsl.template', 'arius.dsl.template', 'logi-elasticsearch-7.6.0', 'r1', 1, 4, 0, 1, 1,\n        '{\"defaultWriterFlags\":true,\"groupId\":\"9d383c43-4445-4c36-bfed-2003d1eae6c0\",\"pipeLineRateLimit\":1000000}',\n        '2021-07-24 15:21:53.0', '2022-06-28 15:39:23.0', 3741),\n       (9, 9, 'arius.gateway.join', 'arius.gateway.join*', 'logi-elasticsearch-7.6.0', 'r2', 1, 4, 0, 1, 1,\n        '{\"defaultWriterFlags\":true,\"groupId\":\"dee03516-b674-4742-a399-82f83970ca50\",\"pipeLineRateLimit\":1104000}',\n        '2021-07-24 15:21:55.0', '2022-06-28 15:39:23.0', 3741),\n       (21259, 14377, 'arius.template.access', 'arius.template.access', 'logi-elasticsearch-7.6.0', 'r2', 1, 4, 0, 1, 1,\n        '{\"defaultWriterFlags\":true,\"groupId\":\"dee03516-b674-4742-a399-82f83970ca50\",\"pipeLineRateLimit\":1000000}',\n        '2021-07-24 15:21:55.0', '2022-07-01 02:24:22.0', 3741),\n       (21249, 14379, 'arius_cat_index_info', 'arius_cat_index_info*', 'logi-elasticsearch-7.6.0', 'r2', 1, 4, 0, 1, 1,\n        '{\"defaultWriterFlags\":true,\"groupId\":\"dee03516-b674-4742-a399-82f83970ca50\",\"pipeLineRateLimit\":1000000}',\n        '2021-07-24 15:21:55.0', '2022-07-01 02:22:36.0', 3741),\n       (21263, 14381, 'arius_gateway_metrics', 'arius_gateway_metrics*', 'logi-elasticsearch-7.6.0', '', 1, 4, 0, 1, 1,\n        '{\"defaultWriterFlags\":true,\"groupId\":\"dee03516-b674-4742-a399-82f83970ca50\",\"pipeLineRateLimit\":1000000}',\n        '2021-07-24 15:21:55.0', '2022-07-01 02:24:50.0', 3741),\n       (21261, 14387, 'arius_stats_cluster_info', 'arius_stats_cluster_info*', 'logi-elasticsearch-7.6.0', 'r2', 1, 4,\n        0, 1, 1,\n        '{\"defaultWriterFlags\":true,\"groupId\":\"dee03516-b674-4742-a399-82f83970ca50\",\"pipeLineRateLimit\":1104000}',\n        '2021-07-24 15:21:55.0', '2022-06-28 15:39:23.0', 3741),\n       (21257, 14493, 'arius_stats_cluster_task_info', 'arius_stats_cluster_task_info*', 'logi-elasticsearch-7.6.0',\n        'r2', 1, 4, 0, 1, 1,\n        '{\"defaultWriterFlags\":true,\"groupId\":\"dee03516-b674-4742-a399-82f83970ca50\",\"pipeLineRateLimit\":1000000}',\n        '2021-07-24 15:21:55.0', '2022-07-01 02:23:58.0', 3741),\n       (21245, 24001, 'arius_stats_dashboard_info', 'arius_stats_dashboard_info*', 'logi-elasticsearch-7.6.0',\n        'r2,r3,r4,r5,r1', 1, 1, 1, 1, 1,\n        '{\"defaultWriterFlags\":true,\"manualPipeLineRateLimit\":-1,\"pipeLineRateLimit\":1000000}', '2022-04-18 09:51:19.0',\n        '2022-07-19 15:40:43.0', 3741),\n       (21251, 14353, 'arius_stats_index_info', 'arius_stats_index_info*', 'logi-elasticsearch-7.6.0', 'r2', 1, 4, 0, 1,\n        1, '{\"defaultWriterFlags\":true,\"groupId\":\"dee03516-b674-4742-a399-82f83970ca50\",\"pipeLineRateLimit\":1000000}',\n        '2021-07-24 15:21:55.0', '2022-07-01 02:22:58.0', 3741),\n       (6001, 14361, 'arius_stats_node_info', 'arius_stats_node_info*', 'logi-elasticsearch-7.6.0', 'r2', 1, 4, 0, 1, 1,\n        '{\"defaultWriterFlags\":true,\"groupId\":\"8d14658c-e9b6-40a4-9db2-12707698c926\",\"pipeLineRateLimit\":1000000}',\n        '2021-07-24 15:22:21.0', '2022-07-01 03:00:03.0', 3741);\n# -----------------------------逻辑模版关联元数据配置信息\n-- auto-generated definition\ncreate table if not exists index_template_config\n(\n    is_source_separated      tinyint        default 0                 not null comment '是否是索引处分分离的 0 不是 1 是',\n    idc_flags                tinyint(1)     default 0                 not null comment 'idc标识',\n    adjust_rack_shard_factor decimal(10, 2) default 1.00              not null comment '模板shard的资源消耗因子',\n    mapping_improve_enable   tinyint        default 1                 not null comment 'mapping优化开关 1 开 0 关',\n    pre_create_flags         tinyint(1)     default 1                 not null comment '预创建标识',\n    update_time              timestamp      default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',\n    disable_source_flags     tinyint(1)     default 0                 not null comment '禁用source标识',\n    disable_index_rollover   tinyint(1)     default 1                 not null comment '禁用indexRollover功能',\n    dynamic_limit_enable     tinyint        default 1                 not null comment '动态限流开关 1 开 0 关',\n    logic_id                 int(10)        default -1                not null comment '逻辑模板id',\n    create_time              timestamp      default CURRENT_TIMESTAMP not null comment '创建时间',\n    shard_num                int            default 1                 not null comment 'shard数量',\n    adjust_rack_tps_factor   decimal(10, 2) default 1.00              not null comment '容量规划时，tps的系数 ',\n    id                       bigint unsigned auto_increment comment '主键'\n        primary key\n)\n    comment '模板配置信息' charset = utf8;\n\ncreate index idx_logic_id\n    on index_template_config (logic_id);\n\ninsert into index_template_config (is_source_separated, idc_flags, adjust_rack_shard_factor,\n                                   mapping_improve_enable, pre_create_flags, update_time,\n                                   disable_source_flags, disable_index_rollover, dynamic_limit_enable,\n                                   logic_id, create_time, shard_num, adjust_rack_tps_factor, id)\nvalues (0, 0, 1.00, 0, 1, '2022-04-18 09:51:19.0', 0, 0, 1, 24007, '2022-04-18 09:51:19.0', 1, 1.00, 25),\n       (0, 0, 1.00, 0, 1, '2022-07-15 10:36:39.0', 0, 1, 1, 1, '2021-10-12 22:03:22.0', -1, 1.00, 1),\n       (0, 0, 1.00, 0, 1, '2021-10-12 22:03:22.0', 0, 1, 1, 5, '2021-10-12 22:03:22.0', -1, 1.00, 3),\n       (0, 0, 1.00, 0, 1, '2021-10-12 22:03:22.0', 0, 1, 1, 7, '2021-10-12 22:03:22.0', -1, 1.00, 5),\n       (0, 0, 1.00, 0, 1, '2021-10-12 22:03:22.0', 0, 1, 1, 9, '2021-10-12 22:03:22.0', -1, 1.00, 7),\n       (0, 0, 1.00, 0, 1, '2021-10-14 22:01:36.0', 0, 1, 1, 14377, '2021-10-14 22:01:36.0', -1, 1.00, 13),\n       (0, 0, 1.00, 0, 1, '2021-10-14 22:01:38.0', 0, 1, 1, 14379, '2021-10-14 22:01:38.0', -1, 1.00, 15),\n       (0, 0, 1.00, 0, 1, '2021-10-14 22:01:44.0', 0, 1, 1, 14381, '2021-10-14 22:01:44.0', -1, 1.00, 17),\n       (0, 0, 1.00, 0, 1, '2021-10-14 22:31:55.0', 0, 1, 1, 14387, '2021-10-14 22:31:55.0', -1, 1.00, 19),\n       (0, 0, 1.00, 0, 1, '2021-10-14 22:31:55.0', 0, 1, 1, 14493, '2021-10-14 22:31:55.0', -1, 1.00, 21),\n       (0, 0, 1.00, 0, 1, '2022-03-08 13:11:17.0', 0, 0, 1, 24001, '2022-03-08 13:11:17.0', -1, 1.00, 23),\n       (0, 0, 1.00, 0, 1, '2021-10-14 21:59:35.0', 0, 1, 1, 14353, '2021-10-14 21:59:35.0', -1, 1.00, 9),\n       (0, 0, 1.00, 0, 1, '2021-10-14 21:59:35.0', 0, 1, 1, 14361, '2021-10-14 21:59:35.0', -1, 1.00, 11);"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/es_manager.sql",
    "content": "/*\n Navicat Premium Data Transfer\n\n Source Server         : 10.179.222.237\n Source Server Type    : MySQL\n Source Server Version : 50539\n Source Host           : 10.179.222.237:4859\n Source Schema         : es_manager_test\n\n Target Server Type    : MySQL\n Target Server Version : 50539\n File Encoding         : 65001\n\n Date: 18/10/2022 15:49:07\n*/\n\nSET NAMES utf8mb4;\nSET FOREIGN_KEY_CHECKS = 0;\n\n-- ----------------------------\n-- Table structure for arius_config_info\n-- ----------------------------\nDROP TABLE IF EXISTS `arius_config_info`;\nCREATE TABLE `arius_config_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n  `value_group` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置项组',\n  `value_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置项名字',\n  `value` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '配置项的值',\n  `edit` int(4) NOT NULL DEFAULT 1 COMMENT '是否可以编辑 1 不可编辑（程序获取） 2 可编辑',\n  `dimension` int(4) NOT NULL DEFAULT -1 COMMENT '配置项维度 1 集群 2 模板 ',\n  `status` int(4) NOT NULL DEFAULT 1 COMMENT '1 正常 2 禁用 -1 删除',\n  `memo` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '备注',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  `search_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '配置查询时间',\n  PRIMARY KEY (`id`) USING BTREE,\n  INDEX `idx_group_name`(`value_group`, `value_name`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1686 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'arius配置项' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for arius_es_user\n-- ----------------------------\nDROP TABLE IF EXISTS `arius_es_user`;\nCREATE TABLE `arius_es_user`  (\n  `id` bigint(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n  `index_exp` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '索引表达式',\n  `data_center` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '数据中心',\n  `is_root` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是都是超级用户 超级用户具有所有索引的访问权限 0 不是 1是',\n  `memo` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '备注',\n  `ip` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '白名单ip地址',\n  `verify_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'app验证码',\n  `is_active` tinyint(2) NOT NULL DEFAULT 1 COMMENT '1为可用，0不可用',\n  `query_threshold` int(10) NOT NULL DEFAULT 100 COMMENT '限流值',\n  `cluster` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '查询集群',\n  `responsible` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '责任人',\n  `search_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT '0表示app的查询请求需要app里配置的集群(一般配置的都是trib集群) 1表示app的查询请求必须只能访问一个模板 2表示集群模式（可支持多模板查询）',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  `project_id` bigint(10) NOT NULL COMMENT '项目id',\n  `is_default_display` tinyint(2) NOT NULL DEFAULT 0 COMMENT '1：项目默认的es user；0:项目新增的es user',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 544 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'es操作用户表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for arius_meta_job_cluster_distribute\n-- ----------------------------\nDROP TABLE IF EXISTS `arius_meta_job_cluster_distribute`;\nCREATE TABLE `arius_meta_job_cluster_distribute`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键id',\n  `cluster_id` int(11) NOT NULL DEFAULT -1 COMMENT '集群id',\n  `monitor_host` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '当前执行主机名',\n  `monitor_time` timestamp NOT NULL DEFAULT '2000-01-02 00:00:00' COMMENT '上一次监控时间',\n  `gmt_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `gmt_modify` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  `cluster` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群名称',\n  `dataCentre` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'cn' COMMENT '集群数据中心',\n  PRIMARY KEY (`id`) USING BTREE,\n  UNIQUE INDEX `uniq_cluster_id`(`cluster_id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 437118 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'monitor任务分配' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for arius_op_task\n-- ----------------------------\nDROP TABLE IF EXISTS `arius_op_task`;\nCREATE TABLE `arius_op_task`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id主键自增',\n  `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '标题',\n  `business_key` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '业务数据主键',\n  `status` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'waiting' COMMENT '任务状态：success:成功 failed:失败 running:执行中 waiting:等待cancel:取消 pause:暂停',\n  `creator` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '创建人',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  `delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '标记删除',\n  `expand_data` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '扩展数据',\n  `task_type` int(11) NOT NULL DEFAULT 0 COMMENT '任务类型1：集群新增，2：集群扩容，3：集群缩容，4：集群重，5：集群升级，6：集群插件操作，10：模版dcdr任务',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 2478 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'arius任务表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for arius_work_order_info\n-- ----------------------------\nDROP TABLE IF EXISTS `arius_work_order_info`;\nCREATE TABLE `arius_work_order_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',\n  `type` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'unknown' COMMENT 'appcreate 创建app,clustercreate 创建集群,clusterindecrease 集群扩缩溶,clusteroffline 集群下线,clusterupdate 集群修改,templateauth 索引申请,templatecreate 索引创建,templateindecrease 索引扩容,templatequerydsl 查询语句创建,templatetransfer 索引转让,querydsllimitedit 查询语句编辑,responsiblegovern 员工离职,unhealthytemplategovern 不健康索引处理',\n  `title` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '标题',\n  `approver_project_id` int(16) NOT NULL DEFAULT -1 COMMENT '审批人projectid',\n  `applicant` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '申请人',\n  `extensions` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '拓展字段',\n  `description` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '备注信息',\n  `approver` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '审批人',\n  `finish_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '结束时间',\n  `opinion` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '审批信息',\n  `status` int(16) NOT NULL DEFAULT 0 COMMENT '工单状态, 0:待审批, 1:通过, 2:拒绝, 3:取消',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修\\n改时间',\n  `applicant_project_id` int(16) NOT NULL DEFAULT -1 COMMENT '申请人projectid',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 2822 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '工单表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for es_cluster_phy_info\n-- ----------------------------\nDROP TABLE IF EXISTS `es_cluster_phy_info`;\nCREATE TABLE `es_cluster_phy_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n  `cluster` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'es集群名',\n  `read_address` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '读地址tcp',\n  `write_address` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '写地址tcp',\n  `http_address` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'http服务地址',\n  `http_write_address` varchar(8000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'http写地址',\n  `desc` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '描述',\n  `type` tinyint(4) NOT NULL DEFAULT -1 COMMENT '集群类型，3-docker集群，4-host集群',\n  `data_center` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'cn' COMMENT '数据中心',\n  `idc` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '机房信息',\n  `es_version` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'es版本',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  `level` tinyint(4) NOT NULL DEFAULT 1 COMMENT '服务等级',\n  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群访问密码',\n  `ecm_cluster_id` int(11) NOT NULL DEFAULT -1 COMMENT 'ecm集群id',\n  `cluster_config_template` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '集群安装模板',\n  `image_name` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '镜像名',\n  `cfg_id` int(11) NOT NULL DEFAULT -1 COMMENT '配置包id',\n  `package_id` int(11) NOT NULL DEFAULT -1 COMMENT '程序包id',\n  `plug_ids` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '插件包id列表',\n  `creator` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群创建人',\n  `ns_tree` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '机器节点',\n  `template_srvs` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '集群的索引模板服务',\n  `is_active` tinyint(4) NOT NULL DEFAULT 1 COMMENT '是否生效',\n  `run_mode` tinyint(255) NOT NULL DEFAULT 0 COMMENT 'client运行模式，0读写共享，1读写分离',\n  `write_action` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指定写client的action',\n  `health` tinyint(2) NOT NULL DEFAULT 3 COMMENT '集群状态 1 green 2 yellow 3 red',\n  `active_shard_num` bigint(25) NOT NULL DEFAULT 0 COMMENT '有效shard总数量',\n  `disk_total` bigint(50) NOT NULL DEFAULT 0 COMMENT '集群磁盘总量 单位byte',\n  `disk_usage` bigint(50) NOT NULL DEFAULT 0 COMMENT '集群磁盘使用量 单位byte',\n  `disk_usage_percent` decimal(10, 5) NOT NULL COMMENT '集群磁盘空闲率 单位 0 ~1',\n  `tags` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '拓展字段,这里用于存放集群展示用属性标签，如「集群所属资源类型」等等',\n  `platform_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'IaaS平台类型',\n  `resource_type` tinyint(4) NOT NULL DEFAULT -1 COMMENT '集群资源类型，1-共享资源，2-独立资源，3-独享资源',\n  `gateway_url` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群gateway地址',\n  PRIMARY KEY (`id`) USING BTREE,\n  INDEX `idx_cluster`(`cluster`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 4852 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '物理集群表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for es_cluster_region\n-- ----------------------------\nDROP TABLE IF EXISTS `es_cluster_region`;\nCREATE TABLE `es_cluster_region`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n  `logic_cluster_id` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '-1' COMMENT '逻辑集群ID',\n  `phy_cluster_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '物理集群名',\n  `racks` varchar(2048) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT 'region的rack，逗号分隔',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  `delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标记，1-已删除，0-未删除',\n  `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'region名称',\n  `config` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT 'region配置项',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 4216 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'es集群region表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for es_cluster_role_host_info\n-- ----------------------------\nDROP TABLE IF EXISTS `es_cluster_role_host_info`;\nCREATE TABLE `es_cluster_role_host_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id主键自增',\n  `role_cluster_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '关联集群角色表外键',\n  `hostname` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '节点名称',\n  `ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '主机ip',\n  `cluster` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群',\n  `port` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '端口，如果是节点上启动了多个进程，可以是多个，用逗号隔开',\n  `role` tinyint(4) NOT NULL DEFAULT -1 COMMENT '角色信息， 1data 2client 3master 4tribe',\n  `status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '节点状态，1 在线 2 离线',\n  `rack` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '节点rack信息',\n  `node_set` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '节点set信息',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  `delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '标记删除',\n  `machine_spec` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '',\n  `region_id` bigint(20) NOT NULL DEFAULT -1 COMMENT '节点所属regionId',\n  `attributes` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT 'es节点attributes信息 , 逗号分隔',\n  PRIMARY KEY (`id`) USING BTREE,\n  UNIQUE INDEX `uniq_elastic_cluster_id_role_node_set`(`role_cluster_id`, `ip`, `port`, `node_set`) USING BTREE,\n  INDEX `idx_cluster`(`cluster`) USING BTREE,\n  INDEX `idx_hostname`(`hostname`) USING BTREE,\n  INDEX `idx_rack`(`rack`) USING BTREE,\n  INDEX `idx_region_id`(`region_id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 2718 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'es集群表对应各角色主机列表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for es_cluster_role_info\n-- ----------------------------\nDROP TABLE IF EXISTS `es_cluster_role_info`;\nCREATE TABLE `es_cluster_role_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id主键自增',\n  `elastic_cluster_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'elastic_cluster外键id',\n  `role_cluster_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'role集群名称',\n  `role` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群角色(masternode/datanode/clientnode)',\n  `pod_number` int(11) NOT NULL DEFAULT 0 COMMENT 'pod数量',\n  `pid_count` int(11) NOT NULL DEFAULT 1 COMMENT '单机实例数',\n  `machine_spec` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '机器规格',\n  `es_version` varchar(150) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'es版本',\n  `cfg_id` int(11) NOT NULL DEFAULT -1 COMMENT '配置包id',\n  `plug_ids` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '插件包id列表',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  `delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '标记删除',\n  PRIMARY KEY (`id`) USING BTREE,\n  UNIQUE INDEX `uniq_elastic_cluster_id_ddcloud_cluster_name`(`elastic_cluster_id`, `role_cluster_name`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1454 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'es集群角色表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for es_config\n-- ----------------------------\nDROP TABLE IF EXISTS `es_config`;\nCREATE TABLE `es_config`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id主键自增',\n  `cluster_id` bigint(20) NOT NULL DEFAULT -1 COMMENT '集群id',\n  `type_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置文件名称',\n  `engin_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '组件名称',\n  `config_data` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '配置内容',\n  `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置描述',\n  `version_tag` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '配置tag',\n  `version_config` bigint(20) NOT NULL DEFAULT -1 COMMENT '配置版本',\n  `selected` smallint(6) NOT NULL DEFAULT 0 COMMENT '是否在使用',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  `delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '标记删除',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1152 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'es配置表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for es_machine_norms\n-- ----------------------------\nDROP TABLE IF EXISTS `es_machine_norms`;\nCREATE TABLE `es_machine_norms`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id主键自增',\n  `role` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '角色(masternode/datanode/clientnode/datanode-ceph)',\n  `spec` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '规格(16-48gi-100g)',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '标记删除',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '容器规格列表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for es_package\n-- ----------------------------\nDROP TABLE IF EXISTS `es_package`;\nCREATE TABLE `es_package`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id主键自增',\n  `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '镜像地址或包地址',\n  `es_version` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '版本标识',\n  `creator` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '包创建人',\n  `release` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否为发布版本',\n  `manifest` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类型(3 docker/4 host)',\n  `desc` varchar(384) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '备注',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  `delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '标记删除 0 未删 1 已删',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 332 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '程序包版本管理' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for es_plugin\n-- ----------------------------\nDROP TABLE IF EXISTS `es_plugin`;\nCREATE TABLE `es_plugin`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id主键自增',\n  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '插件名',\n  `physic_cluster_ids` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '物理集群id',\n  `version` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '插件版本',\n  `url` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '插件存储地址',\n  `md5` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '插件文件md5',\n  `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '插件描述',\n  `creator` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '插件创建人',\n  `p_default` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否为系统默认：0 否 1 是',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '标记删除',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 416 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'es插件包管理' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for es_work_order_task\n-- ----------------------------\nDROP TABLE IF EXISTS `es_work_order_task`;\nCREATE TABLE `es_work_order_task`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id主键自增',\n  `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '标题',\n  `work_order_id` bigint(20) NOT NULL DEFAULT -1 COMMENT '工单id',\n  `physic_cluster_id` bigint(20) NOT NULL DEFAULT -1 COMMENT '物理集群id',\n  `cluster_node_role` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '-1' COMMENT '集群节点角色',\n  `task_ids` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT ' 各角色任务ids',\n  `type` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群类型:3 docker容器云/ 4 host 物理机',\n  `order_type` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '工单类型 1 集群新增 2 集群扩容 3 集群缩容 4 集群重启 5 集群升级',\n  `status` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '任务状态',\n  `creator` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '工单创建人',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n  `delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '标记删除',\n  `handle_data` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '工单数据',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 2064 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'es工单任务表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for es_work_order_task_detail\n-- ----------------------------\nDROP TABLE IF EXISTS `es_work_order_task_detail`;\nCREATE TABLE `es_work_order_task_detail`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id主键自增',\n  `work_order_task_id` bigint(20) NOT NULL DEFAULT -1 COMMENT '工单任务id',\n  `role` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '所属角色',\n  `hostname` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '主机名称/ip',\n  `grp` int(11) NOT NULL DEFAULT 0 COMMENT '机器的分组',\n  `idx` int(11) NOT NULL DEFAULT 0 COMMENT '机器在分组中的索引',\n  `task_id` bigint(20) NOT NULL DEFAULT -1 COMMENT '容器云/物理机 接口返回任务id',\n  `status` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '任务状态',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n  `delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '标记删除',\n  PRIMARY KEY (`id`) USING BTREE,\n  UNIQUE INDEX `uniq_work_order_task_id_role_hostname_delete_flag`(`work_order_task_id`, `role`, `hostname`, `delete_flag`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 6810 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'es工单任务详情表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for gateway_cluster_info\n-- ----------------------------\nDROP TABLE IF EXISTS `gateway_cluster_info`;\nCREATE TABLE `gateway_cluster_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n  `cluster_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群名称',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' 创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  PRIMARY KEY (`id`) USING BTREE,\n  UNIQUE INDEX `uniq_cluster_name`(`cluster_name`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 122 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'gateway集群信息' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for gateway_cluster_node_info\n-- ----------------------------\nDROP TABLE IF EXISTS `gateway_cluster_node_info`;\nCREATE TABLE `gateway_cluster_node_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n  `cluster_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群名称',\n  `host_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '主机名',\n  `port` int(10) NOT NULL DEFAULT -1 COMMENT '端口',\n  `heartbeat_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '心跳时间',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' 创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  PRIMARY KEY (`id`) USING BTREE,\n  UNIQUE INDEX `uniq_ip_port`(`host_name`, `port`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1051872 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'gateway节点信息' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for index_template_alias\n-- ----------------------------\nDROP TABLE IF EXISTS `index_template_alias`;\nCREATE TABLE `index_template_alias`  (\n  `id` bigint(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n  `index_template_id` int(10) NOT NULL DEFAULT -1 COMMENT '索引模板id',\n  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '别名',\n  `filterterm` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '过滤器',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '索引别名' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for index_template_config\n-- ----------------------------\nDROP TABLE IF EXISTS `index_template_config`;\nCREATE TABLE `index_template_config`  (\n  `is_source_separated` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否是索引处分分离的 0 不是 1 是',\n  `idc_flags` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'idc标识',\n  `adjust_rack_shard_factor` decimal(10, 2) NOT NULL DEFAULT 1.00 COMMENT '模板shard的资源消耗因子',\n  `mapping_improve_enable` tinyint(4) NOT NULL DEFAULT 1 COMMENT 'mapping优化开关 1 开 0 关',\n  `pre_create_flags` tinyint(1) NOT NULL DEFAULT 1 COMMENT '预创建标识',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  `disable_source_flags` tinyint(1) NOT NULL DEFAULT 0 COMMENT '禁用source标识',\n  `disable_index_rollover` tinyint(1) NOT NULL DEFAULT 1 COMMENT '禁用indexRollover功能',\n  `dynamic_limit_enable` tinyint(4) NOT NULL DEFAULT 1 COMMENT '动态限流开关 1 开 0 关',\n  `logic_id` int(10) NOT NULL DEFAULT -1 COMMENT '逻辑模板id',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `shard_num` int(11) NOT NULL DEFAULT 1 COMMENT 'shard数量',\n  `adjust_rack_tps_factor` decimal(10, 2) NOT NULL DEFAULT 1.00 COMMENT '容量规划时，tps的系数 ',\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',\n  PRIMARY KEY (`id`) USING BTREE,\n  INDEX `idx_logic_id`(`logic_id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 2214 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '模板配置信息' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for index_template_info\n-- ----------------------------\nDROP TABLE IF EXISTS `index_template_info`;\nCREATE TABLE `index_template_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n  `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '名称',\n  `data_type` tinyint(4) NOT NULL DEFAULT -1 COMMENT '数据类型',\n  `date_format` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '索引分区的时间后缀',\n  `is_active` tinyint(2) NOT NULL DEFAULT 1 COMMENT '有效标记',\n  `data_center` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '数据中心',\n  `expire_time` bigint(20) NOT NULL DEFAULT -1 COMMENT '保存时长',\n  `hot_time` int(10) NOT NULL DEFAULT -1 COMMENT '热数据保存时长',\n  `responsible` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '责任人',\n  `date_field` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '时间字段',\n  `date_field_format` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '时间字段的格式',\n  `id_field` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT 'id字段',\n  `routing_field` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT 'routing字段',\n  `expression` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '索引表达式',\n  `desc` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '索引描述',\n  `quota` decimal(10, 3) NOT NULL DEFAULT -1.000 COMMENT '规格',\n  `project_id` int(10) NOT NULL DEFAULT -1 COMMENT 'project_id',\n  `ingest_pipeline` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'ingest_pipeline',\n  `block_read` tinyint(1) UNSIGNED ZEROFILL NOT NULL DEFAULT 0 COMMENT '是否禁读，0：否，1：是',\n  `block_write` tinyint(1) UNSIGNED ZEROFILL NOT NULL DEFAULT 0 COMMENT '是否禁写，0：否，1：是',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  `write_rate_limit` bigint(255) NOT NULL DEFAULT -1 COMMENT '写入限流值',\n  `resource_id` bigint(20) NOT NULL DEFAULT -1 COMMENT '逻辑集群id',\n  `check_point_diff` bigint(100) NOT NULL DEFAULT 0 COMMENT 'dcdr位点差',\n  `level` tinyint(4) NOT NULL DEFAULT 1 COMMENT '服务等级分为1,2,3',\n  `has_dcdr` tinyint(1) UNSIGNED ZEROFILL NOT NULL DEFAULT 0 COMMENT '是否开启dcdr',\n  `open_srv` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '已开启的模板服务',\n  `disk_size` decimal(10, 3) NULL DEFAULT -1.000 COMMENT '可用磁盘容量',\n  `health` int(11) NULL DEFAULT -1 COMMENT '模版健康；-1是UNKNOW',\n  `priority_level` tinyint(4) NULL DEFAULT 0 COMMENT '恢复优先级',\n  PRIMARY KEY (`id`) USING BTREE,\n  INDEX `idx_data_center`(`data_center`) USING BTREE,\n  INDEX `idx_is_active`(`is_active`) USING BTREE,\n  INDEX `idx_name`(`name`) USING BTREE,\n  INDEX `idx_project_id`(`project_id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 26772 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '逻辑索引模板表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for index_template_physical_info\n-- ----------------------------\nDROP TABLE IF EXISTS `index_template_physical_info`;\nCREATE TABLE `index_template_physical_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n  `logic_id` int(10) NOT NULL DEFAULT -1 COMMENT '逻辑模板id',\n  `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '模板名字',\n  `expression` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '表达式',\n  `cluster` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群名字',\n  `rack` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'rack',\n  `shard` int(10) NOT NULL DEFAULT 1 COMMENT 'shard个数',\n  `shard_routing` int(10) NOT NULL DEFAULT 1 COMMENT '内核的逻辑shard',\n  `version` int(10) NOT NULL DEFAULT 0 COMMENT '版本',\n  `role` tinyint(4) NOT NULL DEFAULT 1 COMMENT '角色 1master 2slave',\n  `status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '1 常规 -1 索引删除中 -2已删除',\n  `config` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '配置 json格式',\n  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  `region_id` int(10) NOT NULL DEFAULT -1 COMMENT '模板关联的regionId',\n  PRIMARY KEY (`id`) USING BTREE,\n  INDEX `idx_cluster_name_status`(`cluster`, `name`, `status`) USING BTREE,\n  INDEX `idx_log_id_statud`(`logic_id`, `status`) USING BTREE,\n  INDEX `idx_logic_id`(`logic_id`) USING BTREE,\n  INDEX `idx_region_id`(`region_id`) USING BTREE,\n  INDEX `idx_status`(`status`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 24738 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '物理模板信息' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for index_template_type\n-- ----------------------------\nDROP TABLE IF EXISTS `index_template_type`;\nCREATE TABLE `index_template_type`  (\n  `id` bigint(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n  `index_template_id` int(10) NOT NULL DEFAULT -1 COMMENT '索引模板id',\n  `index_template_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '索引模板名称',\n  `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'type名称',\n  `id_field` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'id字段',\n  `routing` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'routing字段',\n  `source` tinyint(4) NOT NULL DEFAULT 1 COMMENT '0 不存source 1存source',\n  `is_active` tinyint(2) NOT NULL DEFAULT 1 COMMENT '是否激活 1是 0否',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '索引模板type' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for logi_job\n-- ----------------------------\nDROP TABLE IF EXISTS `logi_job`;\nCREATE TABLE `logi_job`  (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `job_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'task taskCode',\n  `task_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '任务code',\n  `class_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类的全限定名',\n  `try_times` int(10) NOT NULL DEFAULT 0 COMMENT '第几次重试',\n  `worker_code` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '执行机器',\n  `app_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '被调度的应用名称',\n  `start_time` datetime NULL DEFAULT '1971-01-01 00:00:00' COMMENT '开始时间',\n  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n  PRIMARY KEY (`id`) USING BTREE,\n  UNIQUE INDEX `job_code`(`job_code`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1578412 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '正在执行的job信息' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for logi_job_log\n-- ----------------------------\nDROP TABLE IF EXISTS `logi_job_log`;\nCREATE TABLE `logi_job_log`  (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `job_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'job taskCode',\n  `task_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '任务code',\n  `task_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '任务名称',\n  `task_desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '任务描述',\n  `task_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '任务id',\n  `class_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类的全限定名',\n  `try_times` int(10) NOT NULL DEFAULT 0 COMMENT '第几次重试',\n  `worker_code` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '执行机器',\n  `worker_ip` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '执行机器ip',\n  `start_time` datetime NULL DEFAULT '1971-01-01 00:00:00' COMMENT '开始时间',\n  `end_time` datetime NULL DEFAULT '1971-01-01 00:00:00' COMMENT '结束时间',\n  `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '执行结果 1成功 2失败 3取消',\n  `error` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '错误信息',\n  `result` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '执行结果',\n  `app_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '被调度的应用名称',\n  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n  PRIMARY KEY (`id`) USING BTREE,\n  INDEX `index_job_code`(`job_code`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1567240 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'job执行历史日志' ROW_FORMAT = Dynamic;\n\n#-----------------------创建表-----------------------\nDROP TABLE IF EXISTS `kf_security_dept`;\nCREATE TABLE `kf_security_dept`\n(\n    id          int auto_increment  primary key,\n    dept_name   varchar(10) not null comment '部门名',\n    parent_id   int         not null comment '父部门id',\n    leaf        tinyint(1)  not null comment '是否叶子部门',\n    level       tinyint     not null comment 'parentId为0的层级为1',\n    description varchar(20) null comment '描述',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16) null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '部门信息表';\n\nDROP TABLE IF EXISTS `kf_security_message`;\nCREATE TABLE `kf_security_message`\n(\n    id          int auto_increment primary key,\n    title       varchar(60)                          not null comment '标题',\n    content     varchar(256)                         null comment '内容',\n    read_tag    tinyint(1) default 0                 null comment '是否已读',\n    oplog_id    int                                  null comment '操作日志id',\n    user_id     int                                  null comment '这条消息属于哪个用户的，用户id',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '消息中心';\n\nDROP TABLE IF EXISTS `kf_security_oplog`;\nCREATE TABLE `kf_security_oplog`\n(\n    id                int auto_increment primary key,\n    operator_ip       varchar(20)                          not null comment '操作者ip',\n    operator          varchar(20)                          null comment '操作者账号',\n    operate_page      varchar(16)                          not null comment '操作页面',\n    operate_type      varchar(16)                          not null comment '操作类型',\n    target_type       varchar(16)                          not null comment '对象分类',\n    target            varchar(20)                          not null comment '操作对象',\n    operation_methods            varchar(20)                          not null comment '操作方式',\n    detail            text                                 null comment '日志详情',\n    create_time       timestamp  default CURRENT_TIMESTAMP null,\n    update_time       timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete         tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name          varchar(16)                          null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '操作日志';\n\nDROP TABLE IF EXISTS `kf_security_oplog_extra`;\nCREATE TABLE `kf_security_oplog_extra`\n(\n    id          int auto_increment primary key,\n    info        varchar(16) null comment '信息',\n    type        tinyint     not null comment '哪种信息：1：操作页面;2：操作类型;3：对象分类',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16) null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '操作日志信息（操作页面、操作类型、对象分类）';\n\nDROP TABLE IF EXISTS `kf_security_permission`;\nCREATE TABLE `kf_security_permission`\n(\n    id              int auto_increment primary key,\n    permission_name varchar(40) not null comment '权限名字',\n    parent_id       int         not null comment '父权限id',\n    leaf            tinyint(1)  not null comment '是否叶子权限点（具体的操作）',\n    level           tinyint     not null comment '权限点的层级（parentId为0的层级为1）',\n    description     varchar(64) null comment '权限点描述',\n    create_time     timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time     timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete       tinyint(1) default 0                 null comment '逻辑删除',\n    app_name        varchar(16) null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '权限表';\n\nDROP TABLE IF EXISTS `kf_security_project`;\nCREATE TABLE `kf_security_project`\n(\n    id           int auto_increment comment '项目id'     primary key,\n    project_code varchar(128)                           not null comment '项目编号',\n    project_name varchar(128)                           not null comment '项目名',\n    description  varchar(512) default ''                not null comment '项目描述',\n    dept_id      int                                    not null comment '部门id',\n    running      tinyint(1)   default 1                 not null comment '启用 or 停用',\n    create_time  timestamp    default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time  timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete    tinyint(1)   default 0                 not null comment '逻辑删除',\n    app_name     varchar(16)                            null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '项目表';\n\nDROP TABLE IF EXISTS `kf_security_resource_type`;\nCREATE TABLE `kf_security_resource_type`\n(\n    id              int auto_increment primary key,\n    type_name       varchar(16) null comment '资源类型名',\n    create_time     timestamp    default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time     timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete       tinyint(1)   default 0                 not null comment '逻辑删除',\n    app_name        varchar(16) null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '资源类型表';\n\nDROP TABLE IF EXISTS `kf_security_role`;\nCREATE TABLE `kf_security_role`\n(\n    id           int auto_increment primary key,\n    role_code    varchar(128)                         not null comment '角色编号',\n    role_name    varchar(128)                         not null comment '名称',\n    description  varchar(128)                         null comment '角色描述',\n    last_reviser varchar(30)                          null comment '最后修改人',\n    create_time  timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time  timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete    tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name     varchar(16)                          null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '角色信息';\n\nDROP TABLE IF EXISTS `kf_security_role_permission`;\nCREATE TABLE `kf_security_role_permission`\n(\n    id              int auto_increment primary key,\n    role_id         int         not null comment '角色id',\n    permission_id   int         not null comment '权限id',\n    create_time     timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time     timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete       tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name        varchar(16) null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '角色权限表（只保留叶子权限与角色关系）';\n\nDROP TABLE IF EXISTS `kf_security_user`;\nCREATE TABLE `kf_security_user`\n(\n    id          int auto_increment primary key,\n    user_name   varchar(64)                            not null comment '用户账号',\n    pw          varchar(2048)                          not null comment '用户密码',\n    salt        char(5)      default ''                not null comment '密码盐',\n    real_name   varchar(128) default ''                not null comment '真实姓名',\n    phone       char(11)     default ''                not null comment 'mobile',\n    email       varchar(30)  default ''                not null comment 'email',\n    dept_id     int                                    null comment '所属部门id',\n    is_delete   tinyint(1)   default 0                 not null comment '逻辑删除',\n    create_time timestamp    default CURRENT_TIMESTAMP null comment '注册时间',\n    update_time timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    app_name    varchar(16)                            null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '用户信息';\n\nDROP TABLE IF EXISTS `kf_security_user_project`;\nCREATE TABLE `kf_security_user_project`\n(\n    id              int auto_increment primary key,\n    user_id         int         not null comment '用户id',\n    project_id      int         not null comment '项目id',\n    create_time     timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time     timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete       tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name        varchar(16) null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '用户项目关系表（项目负责人）';\n\nDROP TABLE IF EXISTS `kf_security_user_resource`;\nCREATE TABLE `kf_security_user_resource`\n(\n    id                  int auto_increment primary key,\n    user_id             int         not null comment '用户id',\n    project_id          int         not null comment '资源所属项目id',\n    resource_type_id    int         not null comment '资源类别id',\n    resource_id         int         not null comment '资源id',\n    control_level       tinyint     not null comment '管理级别：1（查看权限）2（管理权限）',\n    create_time         timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time         timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete           tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name            varchar(16) null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '用户和资源关系表';\n\nDROP TABLE IF EXISTS `kf_security_user_role`;\nCREATE TABLE `kf_security_user_role`\n(\n    id              int auto_increment primary key,\n    user_id         int         not null comment '用户id',\n    role_id         int         not null comment '角色id',\n    create_time     timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time     timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete       tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name        varchar(16) null comment '应用名称'\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 comment '用户角色表';\n\n-- ----------------------------\n-- Table structure for kf_config\n-- ----------------------------\nDROP TABLE IF EXISTS `kf_security_config`;\nCREATE TABLE `kf_security_config`\n(\n    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n    `value_group` varchar(100) NOT NULL DEFAULT '' COMMENT '配置项组',\n    `value_name` varchar(100) NOT NULL DEFAULT '' COMMENT '配置项名字',\n    `value` text COMMENT '配置项的值',\n    `edit` int(4) NOT NULL DEFAULT '1' COMMENT '是否可以编辑 1 不可编辑（程序获取） 2 可编辑',\n    `status` int(4) NOT NULL DEFAULT '1' COMMENT '1 正常 2 禁用',\n    `memo` varchar(1000) NOT NULL DEFAULT '' COMMENT '备注',\n    `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n    `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n    `is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除',\n    `app_name` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT '应用名称',\n    `operator` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT '操作者',\n    PRIMARY KEY (`id`),\n    KEY `idx_group_name` (`value_group`,`value_name`)\n) ENGINE=InnoDB AUTO_INCREMENT=1592 DEFAULT CHARSET=utf8 COMMENT='kf配置项';\n\n-- ----------------------------\n-- Table structure for logi_task\n-- ----------------------------\nDROP TABLE IF EXISTS `logi_task`;\nCREATE TABLE `logi_task`  (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `task_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'task taskCode',\n  `task_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '名称',\n  `task_desc` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '任务描述',\n  `cron` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'cron 表达式',\n  `class_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类的全限定名',\n  `params` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '执行参数 map 形式{key1:value1,key2:value2}',\n  `retry_times` int(10) NOT NULL DEFAULT 0 COMMENT '允许重试次数',\n  `last_fire_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上次执行时间',\n  `timeout` bigint(20) NOT NULL DEFAULT 0 COMMENT '超时 毫秒',\n  `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '1等待 2运行中 3暂停',\n  `sub_task_codes` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '子任务code列表,逗号分隔',\n  `consensual` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '执行策略',\n  `owner` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '责任人',\n  `task_worker_str` varchar(3000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '机器执行信息',\n  `app_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '被调度的应用名称',\n  `node_name_white_list_str` varchar(3000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '执行节点名对应白名单集',\n  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n  PRIMARY KEY (`id`) USING BTREE,\n  UNIQUE INDEX `task_code`(`task_code`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 48 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '任务信息' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for logi_task_lock\n-- ----------------------------\nDROP TABLE IF EXISTS `logi_task_lock`;\nCREATE TABLE `logi_task_lock`  (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `task_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'task taskCode',\n  `worker_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n  `app_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '被调度的应用名称',\n  `expire_time` bigint(20) NOT NULL DEFAULT 0 COMMENT '过期时间',\n  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 41392 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '任务锁' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for logi_worker\n-- ----------------------------\nDROP TABLE IF EXISTS `logi_worker`;\nCREATE TABLE `logi_worker`  (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `worker_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n  `worker_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'worker名',\n  `ip` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'worker的ip',\n  `cpu` int(11) NOT NULL DEFAULT 0 COMMENT 'cpu数量',\n  `cpu_used` double NOT NULL DEFAULT 0 COMMENT 'cpu使用率',\n  `memory` double NOT NULL DEFAULT 0 COMMENT '内存,以M为单位',\n  `memory_used` double NOT NULL DEFAULT 0 COMMENT '内存使用率',\n  `jvm_memory` double NOT NULL DEFAULT 0 COMMENT 'jvm堆大小，以M为单位',\n  `jvm_memory_used` double NOT NULL DEFAULT 0 COMMENT 'jvm堆使用率',\n  `job_num` int(10) NOT NULL DEFAULT 0 COMMENT '正在执行job数',\n  `heartbeat` datetime NULL DEFAULT '1971-01-01 00:00:00' COMMENT '心跳时间',\n  `app_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '被调度的应用名称',\n  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n  `node_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'node 名',\n  PRIMARY KEY (`id`) USING BTREE,\n  UNIQUE INDEX `worker_code`(`worker_code`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 2772 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'worker信息' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for logi_worker_blacklist\n-- ----------------------------\nDROP TABLE IF EXISTS `logi_worker_blacklist`;\nCREATE TABLE `logi_worker_blacklist`  (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `worker_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'worker taskCode',\n  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',\n  PRIMARY KEY (`id`) USING BTREE,\n  UNIQUE INDEX `worker_code`(`worker_code`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'worker黑名单列表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for metric_dictionary_info\n-- ----------------------------\nDROP TABLE IF EXISTS `metric_dictionary_info`;\nCREATE TABLE `metric_dictionary_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,\n  `type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标分类',\n  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '指标名称',\n  `price` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '-1' COMMENT '指标价值',\n  `interval` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '1' COMMENT '计算间隔',\n  `current_cal_logic` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '当前计算逻辑',\n  `is_gold` tinyint(1) UNSIGNED ZEROFILL NULL DEFAULT 0 COMMENT '是否黄金指标(0否1是)',\n  `unit` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '单位',\n  `interactive_form` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '交互形式',\n  `is_warning` tinyint(1) UNSIGNED ZEROFILL NULL DEFAULT 0 COMMENT '告警指标(0否1是)',\n  `source` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标来源',\n  `tags` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '指标标签',\n  `model` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '模块',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  `is_active` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否生效',\n  `is_threshold` tinyint(1) UNSIGNED ZEROFILL NOT NULL DEFAULT 0 COMMENT '是否有阈值',\n  `threshold` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '阈值',\n  `metric_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '阈值信息',\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 5754 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户和应用配置信息表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for operate_record_info\n-- ----------------------------\nDROP TABLE IF EXISTS `operate_record_info`;\nCREATE TABLE `operate_record_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键 自增',\n  `project_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '应用',\n  `module_id` int(10) NOT NULL DEFAULT -1 COMMENT '模块id',\n  `operate_id` int(10) NOT NULL DEFAULT -1 COMMENT '操作id',\n  `trigger_way_id` int(11) NULL DEFAULT NULL COMMENT '触发方式',\n  `user_operation` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '操作人',\n  `content` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '操作内容',\n  `operate_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  `biz_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 15584 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '操作记录表' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for project_arius_config\n-- ----------------------------\nDROP TABLE IF EXISTS `project_arius_config`;\nCREATE TABLE `project_arius_config`  (\n  `project_id` bigint(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'project id',\n  `analyze_response_enable` tinyint(4) NOT NULL DEFAULT 1 COMMENT '响应结果解析开关 默认是0：关闭，1：开启',\n  `is_source_separated` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否是索引存储分离的 0 不是 1 是',\n  `aggr_analyze_enable` tinyint(4) NOT NULL DEFAULT 1 COMMENT '1 生效 0 不生效',\n  `dsl_analyze_enable` tinyint(2) NOT NULL DEFAULT 1 COMMENT '1为生效dsl分析查询限流值，0不生效dsl分析查询限流值',\n  `slow_query_times` int(10) NOT NULL DEFAULT 100 COMMENT '慢查询耗时',\n  `is_active` tinyint(2) NOT NULL DEFAULT 1 COMMENT '1为可用，0不可用',\n  `memo` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '备注',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n  PRIMARY KEY (`project_id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1964 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '项目配置' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for project_arius_resource_logic\n-- ----------------------------\nDROP TABLE IF EXISTS `project_arius_resource_logic`;\nCREATE TABLE `project_arius_resource_logic`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n  `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '资源名称',\n  `type` tinyint(4) NOT NULL DEFAULT 2 COMMENT '资源类型 1 共享公共资源 2 独享资源',\n  `project_id` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '-1' COMMENT '资源所属的project_id ',\n  `data_center` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '数据中心 cn/us01',\n  `responsible` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '资源责任人',\n  `memo` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '资源备注',\n  `quota` decimal(8, 2) NOT NULL DEFAULT 1.00 COMMENT '资源的大小',\n  `level` tinyint(4) NOT NULL DEFAULT 1 COMMENT '服务等级 1 normal 2 important 3 vip ',\n  `config_json` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '集群配置',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  `health` tinyint(4) NOT NULL DEFAULT 3 COMMENT '集群状态 1 green 2 yellow 3 red -1 未知',\n  `data_node_spec` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '节点规格',\n  `disk_total` bigint(50) NOT NULL DEFAULT 0 COMMENT '集群磁盘总量 单位byte',\n  `disk_usage` bigint(50) NOT NULL DEFAULT 0 COMMENT '集群磁盘使用量 单位byte',\n  `disk_usage_percent` decimal(10, 5) NOT NULL DEFAULT 0.00000 COMMENT '集群磁盘空闲率 单位 0 ~1',\n  `es_cluster_version` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'es集群版本',\n  `node_num` int(10) NOT NULL DEFAULT 0 COMMENT '节点个数',\n  `data_node_num` int(10) NOT NULL DEFAULT 0 COMMENT '节点个数',\n  PRIMARY KEY (`id`) USING BTREE,\n  INDEX `idx_name`(`name`) USING BTREE,\n  INDEX `idx_project_id`(`project_id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 4090 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '逻辑资源信息' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for project_logi_cluster_auth\n-- ----------------------------\nDROP TABLE IF EXISTS `project_logi_cluster_auth`;\nCREATE TABLE `project_logi_cluster_auth`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n  `project_id` int(10) NOT NULL DEFAULT -1 COMMENT '项目id',\n  `logic_cluster_id` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '逻辑集群id',\n  `type` int(10) NOT NULL DEFAULT -1 COMMENT '权限类型，0-超管，1-配置管理，2-访问，-1-无权限',\n  `responsible` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '责任人id列表',\n  `status` int(10) NOT NULL DEFAULT 1 COMMENT '状态 1有效 0无效',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  PRIMARY KEY (`id`) USING BTREE,\n  INDEX `idx_project_id`(`project_id`) USING BTREE,\n  INDEX `idx_logic_cluster_id`(`logic_cluster_id`) USING BTREE,\n  INDEX `idx_status`(`status`) USING BTREE,\n  INDEX `idx_type`(`type`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'project逻辑集群权限' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for project_template_info\n-- ----------------------------\nDROP TABLE IF EXISTS `project_template_info`;\nCREATE TABLE `project_template_info`  (\n  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键自增',\n  `project_id` int(10) NOT NULL DEFAULT -1 COMMENT '项目id',\n  `template` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '模板名称, 不能关联模板id 模板会跨集群迁移，id会变',\n  `type` int(10) NOT NULL DEFAULT -1 COMMENT 'appid的权限 1 读写 2 读 -1 未知',\n  `status` int(10) NOT NULL DEFAULT 1 COMMENT '状态 1有效 0无效',\n  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\n  PRIMARY KEY (`id`) USING BTREE,\n  INDEX `idx_project_id`(`project_id`) USING BTREE,\n  INDEX `idx_status`(`status`) USING BTREE,\n  INDEX `idx_template_id`(`template`) USING BTREE,\n  INDEX `idx_type`(`type`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'project模板信息' ROW_FORMAT = Dynamic;\n\n-- ----------------------------\n-- Table structure for user_config_info\n-- ----------------------------\nDROP TABLE IF EXISTS `user_config_info`;\nCREATE TABLE `user_config_info`  (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户账号',\n  `project_id` int(10) NOT NULL DEFAULT -1 COMMENT '项目id',\n  `config_type` int(10) NOT NULL DEFAULT 1 COMMENT '配置类型,1-指标看板和dashboard，2-查询模板列表',\n  `config_info` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '用户下某个应用的配置',\n  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB AUTO_INCREMENT = 3090 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户和应用配置信息表' ROW_FORMAT = Dynamic;\n\nSET FOREIGN_KEY_CHECKS = 1;\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/init_es_templates_to_arius_linux.sh",
    "content": "#!/bin/bash\n\nworkspace=$(cd $(dirname $0) && pwd -P)\ncd ${workspace}\n\n# arius地址\nariusHost=$1\nariusPort=$2\n\n# 模板负责人，如root\nariusResponsible=$3\n# ES管控项目appId\nariusManagerAppId=$4\n\n# ES管控项目所在租户ID，如1\ndepartmentId=$5\n# ES管控项目所在租户名，如内置租户\ndepartment=$6\n\n# 逻辑集群ID\nlogicClusterId=$7\n# 物理集群名\nphyClusterName=$8\n# 管理员用户cookie里的ecmc-user\necmcUser=${10}\n\n# 模板数据所在的目录\ntemplateDir=${11}\n\n\nif [ -z ${ariusHost} ]; then\n    echo \"error: ariusHost not specified.\"\n    exit 1\nfi\n\nif [ -z ${ariusPort} ]; then\n    echo \"error: ariusPort not specified.\"\n    exit 1\nfi\n\nif [ -z ${ariusResponsible} ]; then\n    echo \"error: ariusResponsible not specified.\"\n    exit 1\nfi\n\nif [ -z ${ariusManagerAppId} ]; then\n    echo \"error: ariusManagerAppId not specified.\"\n    exit 1\nfi\n\nif [ -z ${departmentId} ]; then\n    echo \"error: departmentId not specified.\"\n    exit 1\nfi\n\nif [ -z ${department} ]; then\n    echo \"error: department not specified.\"\n    exit 1\nfi\n\nif [ -z ${logicClusterId} ]; then\n    echo \"error: logicClusterId not specified.\"\n    exit 1\nfi\n\nif [ -z ${phyClusterName} ]; then\n    echo \"error: phyClusterName not specified.\"\n    exit 1\nfi\n\nif [ -z ${templateDir} ]; then\n    echo \"error: templateDir not specified.\"\n    exit 1\nfi\n\n\nfor file in `ls ${templateDir}`\n    do\n        templateName=`echo ${file}`\n        file=\"${templateDir}/${file}\"\n        echo \"handle file ${file}\"\n        # 替换模板数据\n        # 负责人\n        sed -i \"s/\\\"responsible\\\":.*/\\\"responsible\\\": \\\"${ariusResponsible}\\\",/g\" ${file}\n\n        # 项目appId\n        sed -i \"s/\\\"appId\\\":.*/\\\"appId\\\": ${ariusManagerAppId},/g\" ${file}\n\n        # 租户ID\n        sed -i \"s/\\\"libraDepartmentId\\\":.*/\\\"libraDepartmentId\\\": \\\"${departmentId}\\\",/g\" ${file}\n\n        # 租户名\n        sed -i \"s/\\\"libraDepartment\\\":.*/\\\"libraDepartment\\\": \\\"${department}\\\",/g\" ${file}\n\n        # 逻辑集群ID\n        sed -i \"s/\\\"resourceId\\\":.*/\\\"resourceId\\\": ${logicClusterId},/g\" ${file}\n\n        # 物理集群名\n        sed -i \"s/\\\"cluster\\\":.*/\\\"cluster\\\": \\\"${phyClusterName}\\\",/g\" ${file}\n\n        # 物理模板角色\n        sed -i \"s/\\\"role\\\":.*/\\\"role\\\": 1,/g\" ${file}\n\n        # 数据类型-用户上报数据\n        sed -i \"s/\\\"dataType\\\":.*/\\\"dataType\\\": 2,/g\" ${file}\n\n        templateContent=`cat ${file}`\n\n        curlCmd=\"curl -i -X PUT 'http://${ariusHost}:${ariusPort}/api/es/admin/v2/op/template/logic/add' -H 'Cookie: ecmc-user=${ecmcUser}' -H 'X-SSO-USER: ${ariusResponsible}' -H 'X-ARIUS-APP-ID: ${ariusManagerAppId}' -H 'content-type: application/json' -d '${templateContent}'\"\n        echo \"${curlCmd}\"\n        eval \"${curlCmd}\"\n\n        # response=`curl -X PUT \"http://${ariusHost}:${ariusPort}/api/es/admin/v2/op/template/logic/add\" -H \"X-SSO-USER: ${ariusResponsible}\" -H \"X-ARIUS-APP-ID: ${ariusManagerAppId}\" -H 'content-type: application/json' -d \"${templateContent}\"`\ndone\n\necho -e \"\\nfinished.\"\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/init_es_templates_to_arius_mac.sh",
    "content": "#!/bin/bash\n\nworkspace=$(cd $(dirname $0) && pwd -P)\ncd ${workspace}\n\n# arius地址\nariusHost=$1\nariusPort=$2\n\n# 模板负责人，如root\nariusResponsible=$3\n# ES管控项目appId\nariusManagerAppId=$4\n\n# ES管控项目所在租户ID，如1\ndepartmentId=\"\"\n# ES管控项目所在租户名，如内置租户\ndepartment=\"\"\n\n# 逻辑集群ID\nlogicClusterId=$5\n# 物理集群名\nphyClusterName=$6\n\n# 管理员用户cookie里的ecmc-user\ndomainAccount=${8}\n\n# 模板数据所在的目录\ntemplateDir=${9}\n\n\nif [ -z ${ariusHost} ]; then\n    echo \"error: ariusHost not specified.\"\n    exit 1\nfi\n\nif [ -z ${ariusPort} ]; then\n    echo \"error: ariusPort not specified.\"\n    exit 1\nfi\n\nif [ -z ${ariusResponsible} ]; then\n    echo \"error: ariusResponsible not specified.\"\n    exit 1\nfi\n\nif [ -z ${ariusManagerAppId} ]; then\n    echo \"error: ariusManagerAppId not specified.\"\n    exit 1\nfi\n\nif [ -z ${departmentId} ]; then\n    echo \"error: departmentId not specified.\"\n    exit 1\nfi\n\nif [ -z ${department} ]; then\n    echo \"error: department not specified.\"\n    exit 1\nfi\n\nif [ -z ${logicClusterId} ]; then\n    echo \"error: logicClusterId not specified.\"\n    exit 1\nfi\n\nif [ -z ${phyClusterName} ]; then\n    echo \"error: phyClusterName not specified.\"\n    exit 1\nfi\n\nif [ -z ${domainAccount} ]; then\n    echo \"error: domainAccount not specified.\"\n    exit 1\nfi\n\nif [ -z ${templateDir} ]; then\n    echo \"error: templateDir not specified.\"\n    exit 1\nfi\n\n\nfor file in `ls ${templateDir}`\n    do\n        templateName=`echo ${file}`\n        file=\"${templateDir}/${file}\"\n        echo \"handle file ${file}\"\n        # 替换模板数据\n        # 负责人\n        sed -i '' \"s/\\\"responsible\\\":.*/\\\"responsible\\\": \\\"${ariusResponsible}\\\",/g\" ${file}\n\n        # 项目appId\n        sed -i '' \"s/\\\"appId\\\":.*/\\\"appId\\\": ${ariusManagerAppId},/g\" ${file}\n\n        # 租户ID\n        sed -i '' \"s/\\\"libraDepartmentId\\\":.*/\\\"libraDepartmentId\\\": \\\"${departmentId}\\\",/g\" ${file}\n\n        # 租户名\n        sed -i '' \"s/\\\"libraDepartment\\\":.*/\\\"libraDepartment\\\": \\\"${department}\\\",/g\" ${file}\n\n        # 逻辑集群ID\n        sed -i '' \"s/\\\"resourceId\\\":.*/\\\"resourceId\\\": ${logicClusterId},/g\" ${file}\n\n        # 物理集群名\n        sed -i '' \"s/\\\"cluster\\\":.*/\\\"cluster\\\": \\\"${phyClusterName}\\\",/g\" ${file}\n\n        # 物理模板角色\n        sed -i '' \"s/\\\"role\\\":.*/\\\"role\\\": 1,/g\" ${file}\n\n        # 数据类型-用户上报数据\n        sed -i '' \"s/\\\"dataType\\\":.*/\\\"dataType\\\": 2,/g\" ${file}\n\n        templateContent=`cat ${file}`\n\n        curlCmd=\"curl -i -X PUT 'http://${ariusHost}:${ariusPort}/admin/api/v2/op/template/logic/add' -H 'Cookie: domainAccount=${domainAccount}' -H 'X-SSO-USER: ${ariusResponsible}' -H 'X-ARIUS-APP-ID: ${ariusManagerAppId}' -H 'content-type: application/json' -d '${templateContent}'\"\n        echo \"${curlCmd}\"\n        eval \"${curlCmd}\"\n\n        # response=`curl -X PUT \"http://${ariusHost}:${ariusPort}/api/es/admin/v2/op/template/logic/add\" -H \"X-SSO-USER: ${ariusResponsible}\" -H \"X-ARIUS-APP-ID: ${ariusManagerAppId}\" -H 'content-type: application/json' -d \"${templateContent}\"`\ndone\n\necho -e \"\\nfinished.\"\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/init_es_templates_to_cluster_linux.sh",
    "content": "#!/bin/bash\n\nworkspace=$(cd $(dirname $0) && pwd -P)\ncd ${workspace}\n\nesHost=$1\nesPort=$2\ntemplateDir=$4\necho \"esHost:${esHost} esPort:${esPort} templateDir:${templateDir}\"\n\nif [ -z ${esHost} ]; then\n    echo \"error: esHost not specified.\"\n    exit 1\nfi\n\nif [ -z ${esPort} ]; then\n    echo \"error: esPort not specified.\"\n    exit 1\nfi\n\nif [ -z ${templateDir} ]; then\n    echo \"error: templateDir not specified.\"\n    exit 1\nfi\n\nfor file in `ls ${templateDir}`\n    do\n        templateName=`echo ${file}`\n        file=\"${templateDir}/${file}\"\n\n        templateContent=`cat ${file}`\n        echo -e \"\\ncreate admin template ${templateName}\"\n        response=`curl -X PUT \"http://${esHost}:${esPort}/_template/${templateName}\" -H 'content-type: application/json' -d \"${templateContent}\"`\n        echo \"${response}\"\ndone\n\necho \"finished.\"\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/init_es_templates_to_cluster_mac.sh",
    "content": "#!/bin/bash\n\nworkspace=$(cd $(dirname $0) && pwd -P)\ncd ${workspace}\n\nesHost=$1\nesPort=$2\ntemplateDir=$4\necho \"esHost:${esHost} esPort:${esPort}  templateDir:${templateDir}\"\n\nif [ -z ${esHost} ]; then\n    echo \"error: esHost not specified.\"\n    exit 1\nfi\n\nif [ -z ${esPort} ]; then\n    echo \"error: esPort not specified.\"\n    exit 1\nfi\n\nif [ -z ${templateDir} ]; then\n    echo \"error: templateDir not specified.\"\n    exit 1\nfi\n\nfor file in `ls ${templateDir}`\n    do\n        templateName=`echo ${file}`\n        file=\"${templateDir}/${file}\"\n\n        templateContent=`cat ${file}`\n        echo -e \"\\ncreate admin template ${templateName}\"\n        response=`curl -X PUT \"http://${esHost}:${esPort}/_template/${templateName}\" -H 'content-type: application/json' -d \"${templateContent}\"`\n        echo \"${response}\"\ndone\n\necho \"finished.\"\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/init_logi_em_linux.sh",
    "content": "#!/bin/bash\n\nworkspace=$(cd $(dirname $0) && pwd -P)\ncd ${workspace}\n\n# arius地址\nariusHost=$1\nariusPort=$2\n\nclusterMasterIp=$3\nclusterMasterPort=$4\n\ndeleteExitMateClusterFlag=$5\n\n# 模板负责人，admin\nariusResponsible=\"admin\"\n# ES管控项目appId\nariusManagerAppId=1\n\n# 逻辑集群ID\nlogicClusterId=0\n# 物理集群名\nphyClusterName=\"logi-em-matedata-cluster\"\n\n# 管理员用户cookie里的domainAccount\ndomainAccount=\"admin\"\n\n# 模板数据所在的目录\ntemplateDirForArius=\"./template_in_arius\"\n\nmetaDataClusterDir=\"./join_cluster_in_logi_em\"\n\ntemplateDirForCluster=\"./template_in_cluster\"\n\ncodeForCheckClusterHealthResp=\"1\"\n\ngetJsonValuesByAwk() {\n    awk -v json=\"$1\" -v key=\"$2\" -v defaultValue=\"$3\" 'BEGIN{\n        foundKeyCount = 0\n        while (length(json) > 0) {\n            pos = match(json, \"\\\"\"key\"\\\"[ \\\\t]*?:[ \\\\t]*\");\n            if (pos == 0) {if (foundKeyCount == 0) {print defaultValue;} exit 0;}\n\n            ++foundKeyCount;\n            start = 0; stop = 0; layer = 0;\n            for (i = pos + length(key) + 1; i <= length(json); ++i) {\n                lastChar = substr(json, i - 1, 1)\n                currChar = substr(json, i, 1)\n\n                if (start <= 0) {\n                    if (lastChar == \":\") {\n                        start = currChar == \" \" ? i + 1: i;\n                        if (currChar == \"{\" || currChar == \"[\") {\n                            layer = 1;\n                        }\n                    }\n                } else {\n                    if (currChar == \"{\" || currChar == \"[\") {\n                        ++layer;\n                    }\n                    if (currChar == \"}\" || currChar == \"]\") {\n                        --layer;\n                    }\n                    if ((currChar == \",\" || currChar == \"}\" || currChar == \"]\") && layer <= 0) {\n                        stop = currChar == \",\" ? i : i + 1 + layer;\n                        break;\n                    }\n                }\n            }\n\n            if (start <= 0 || stop <= 0 || start > length(json) || stop > length(json) || start >= stop) {\n                if (foundKeyCount == 0) {print defaultValue;} exit 0;\n            } else {\n                print substr(json, start, stop - start);\n            }\n\n            json = substr(json, stop + 1, length(json) - stop)\n        }\n    }'\n}\n\nif [ -z ${ariusHost} ]; then\n    echo \"error: ariusHost not specified.\"\n    exit 1\nfi\n\nif [ -z ${ariusPort} ]; then\n    echo \"error: ariusPort not specified.\"\n    exit 1\nfi\n\nif [ -z ${clusterMasterIp} ]; then\n    echo \"error: clusterMasterIp not specified.\"\n    exit 1\nfi\n\nif [ -z ${clusterMasterPort} ]; then\n    echo \"error: clusterMasterPort not specified.\"\n    exit 1\nfi\n\ncurlCmdForCheckClusterIsExitResp=$(curl -X GET \"http://${ariusHost}:${ariusPort}/admin/api/v3/white/phy/cluster/${phyClusterName}/isExit\" -H \"Cookie: domainAccount=${domainAccount}\" -H \"X-SSO-USER: ${ariusResponsible}\" -H \"X-ARIUS-APP-ID: ${ariusManagerAppId}\" -H \"content-type: application/json\")\ncodeForCheckClusterIsExitResp=$(getJsonValuesByAwk \"${curlCmdForCheckClusterIsExitResp}\" code \"\"  | sed 's/\\\"//g')\nif [ \"x$codeForCheckClusterIsExitResp\" == \"x0\" ]; then\n    echo \"join cluster is exit...\"\n    if [ \"x$:deleteExitMateClusterFlag\" == \"x1\" ]; then\n    curlCmdForDelMetaDataClusterResp=$(curl -X DELETE \"http://${ariusHost}:${ariusPort}/admin/api/v3/white/phy/cluster/${phyClusterName}/del\" -H \"Cookie: domainAccount=${domainAccount}\" -H \"X-SSO-USER: ${ariusResponsible}\" -H \"X-ARIUS-APP-ID: ${ariusManagerAppId}\" -H \"content-type: application/json\")\n    fi\nfi\n\necho \"starting join cluster...\"\n    for file in `ls ${metaDataClusterDir}`\n        do\n            joinClusterName=`echo ${file}`\n            file=\"${metaDataClusterDir}/${file}\"\n            echo \"handle file ${file}\"\n             # 替换数据\n            # 元数据集群master节点Ip\n            sed -i \"s/\\\"ip\\\":.*/\\\"ip\\\": \\\"${clusterMasterIp}\\\",/g\" ${file}\n\n            # 元数据集群端master节点端口号\n            sed -i \"s/\\\"port\\\":.*/\\\"port\\\": ${clusterMasterPort},/g\" ${file}\n\n            # 指定接入集群master角色\n            sed -i \"s/\\\"role\\\":.*/\\\"role\\\": 3,/g\" ${file}\n\n            joinClusterContent=`cat ${file}`\n\n            curlCmdForJoinResp=$(curl -X POST \"http://${ariusHost}:${ariusPort}/admin/api/v3/op/phy/cluster/join\" -H \"Cookie: domainAccount=${domainAccount}\" -H \"X-SSO-USER: ${ariusResponsible}\" -H \"X-ARIUS-APP-ID: ${ariusManagerAppId}\" -H \"content-type: application/json\" -d \"${joinClusterContent}\")\n\n            code=$(getJsonValuesByAwk \"${curlCmdForJoinResp}\" code \"\"  | sed 's/\\\"//g')\n\n            if [ \"x$code\" == \"x0\" ];\n            then\n                echo \"Get the return value successfully and start field parsing\"\n                logicClusterId=$(getJsonValuesByAwk \"${curlCmdForJoinResp}\" v1 \"\"  | sed 's/\\\"//g')\n                phyClusterName=$(getJsonValuesByAwk \"${curlCmdForJoinResp}\" v2 \"\"  | sed 's/\\\"//g')\n            else\n                echo \"Failed to join meta data cluster\"\n                exit 1;\n            fi\n\n            echo \"${curlCmdForJoinResp}\"\n            eval \"${curlCmdForJoinResp}\"\n    done\necho \"Successful join cluster!!!\"\n\necho \"start checking join cluster valid...\"\nfor i in `seq 1 50`\ndo\n    echo  \"Loop checking metadata cluster status, number of times: ${i}\"\n    curlCmdForCheckClusterHealthResp=$(curl -X GET \"http://${ariusHost}:${ariusPort}/admin/api/v3/white/phy/cluster/${phyClusterName}/checkHealth\" -H \"Cookie: domainAccount=${domainAccount}\" -H \"X-SSO-USER: ${ariusResponsible}\" -H \"X-ARIUS-APP-ID: ${ariusManagerAppId}\" -H \"content-type: application/json\")\n    codeForCheckClusterHealthResp=$(getJsonValuesByAwk \"${curlCmdForCheckClusterHealthResp}\" code \"\"  | sed 's/\\\"//g')\n    if [ \"x$codeForCheckClusterHealthResp\" == \"x0\" ];\n        then\n            break\n    fi\n    sleep 1\ndone\n\nif [ \"x$codeForCheckClusterHealthResp\" != \"x0\" ];\n    then\n        echo \"join matedata cluster is invalid\"\n    else\n        echo \"joined cluster is Effective!!!\"\nfi\n\necho \"${logicClusterId}\"\necho \"${phyClusterName}\"\nsleep 3\n\necho \"starting created system template for arius...\"\nfor file in `ls ${templateDirForArius}`\n    do\n        templateName=`echo ${file}`\n        file=\"${templateDirForArius}/${file}\"\n        echo \"handle file ${file}\"\n        # 替换模板数据\n        # 负责人\n        sed -i \"s/\\\"responsible\\\":.*/\\\"responsible\\\": \\\"${ariusResponsible}\\\",/g\" ${file}\n\n        # 项目appId\n        sed -i \"s/\\\"appId\\\":.*/\\\"appId\\\": ${ariusManagerAppId},/g\" ${file}\n\n        # 逻辑集群ID\n        sed -i \"s/\\\"resourceId\\\":.*/\\\"resourceId\\\": ${logicClusterId},/g\" ${file}\n\n        # 物理集群名\n        sed -i \"s/\\\"cluster\\\":.*/\\\"cluster\\\": \\\"${phyClusterName}\\\",/g\" ${file}\n\n        # 物理模板角色\n        sed -i \"s/\\\"role\\\":.*/\\\"role\\\": 1,/g\" ${file}\n\n        # 数据类型-系统数据\n        sed -i \"s/\\\"dataType\\\":.*/\\\"dataType\\\": 0,/g\" ${file}\n\n        templateContentForArius=$(cat ${file} | sed \"1a \\\\  \\\"resourceId\\\":${logicClusterId},\")\n\n        curlCmdForTemplate=\"curl -X PUT 'http://${ariusHost}:${ariusPort}/admin/api/v2/op/template/logic/add' -H 'Cookie: domainAccount=${domainAccount}' -H 'X-SSO-USER: ${ariusResponsible}' -H 'X-ARIUS-APP-ID: ${ariusManagerAppId}' -H 'content-type: application/json' -d '${templateContentForArius}'\"\n        echo \"${curlCmdForTemplate}\"\n        sleep 1\n        eval \"${curlCmdForTemplate}\"\n    done\n\necho \"starting created system template for mateDataCluster...\"\nfor file in `ls ${templateDirForCluster}`\n    do\n        templateName=`echo ${file}`\n        file=\"${templateDirForCluster}/${file}\"\n\n        templateContentForCluster=`cat ${file}`\n        echo -e \"\\ncreate admin template ${templateName}\"\n        response=`curl -X PUT \"http://${clusterMasterIp}:${clusterMasterPort}/_template/${templateName}\" -H 'content-type: application/json' -d \"${templateContentForCluster}\"`\n        echo \"${response}\"\ndone\necho \"System template created successfully!!!\"\n\necho -e \"\\nfinished.\""
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/init_logi_em_mac.sh",
    "content": "#!/bin/bash\n\nworkspace=$(cd $(dirname $0) && pwd -P)\ncd ${workspace}\n\n# arius地址\nariusHost=$1\nariusPort=$2\n\nclusterMasterIp=$3\nclusterMasterPort=$4\n\ndeleteExitMateClusterFlag=$5\n\n# 模板负责人，admin\nariusResponsible=\"admin\"\n# ES管控项目appId\nariusManagerAppId=1\n\n# 逻辑集群ID\nlogicClusterId=0\n# 物理集群名\nphyClusterName=\"logi-em-matedata-cluster\"\n\n# 管理员用户cookie里的domainAccount\ndomainAccount=\"admin\"\n\n# 模板数据所在的目录\ntemplateDirForArius=\"./template_in_arius\"\n\nmetaDataClusterDir=\"./join_cluster_in_logi_em\"\n\ntemplateDirForCluster=\"./template_in_cluster\"\n\ncodeForCheckClusterHealthResp=\"1\"\n\ngetJsonValuesByAwk() {\n    awk -v json=\"$1\" -v key=\"$2\" -v defaultValue=\"$3\" 'BEGIN{\n        foundKeyCount = 0\n        while (length(json) > 0) {\n            pos = match(json, \"\\\"\"key\"\\\"[ \\\\t]*?:[ \\\\t]*\");\n            if (pos == 0) {if (foundKeyCount == 0) {print defaultValue;} exit 0;}\n\n            ++foundKeyCount;\n            start = 0; stop = 0; layer = 0;\n            for (i = pos + length(key) + 1; i <= length(json); ++i) {\n                lastChar = substr(json, i - 1, 1)\n                currChar = substr(json, i, 1)\n\n                if (start <= 0) {\n                    if (lastChar == \":\") {\n                        start = currChar == \" \" ? i + 1: i;\n                        if (currChar == \"{\" || currChar == \"[\") {\n                            layer = 1;\n                        }\n                    }\n                } else {\n                    if (currChar == \"{\" || currChar == \"[\") {\n                        ++layer;\n                    }\n                    if (currChar == \"}\" || currChar == \"]\") {\n                        --layer;\n                    }\n                    if ((currChar == \",\" || currChar == \"}\" || currChar == \"]\") && layer <= 0) {\n                        stop = currChar == \",\" ? i : i + 1 + layer;\n                        break;\n                    }\n                }\n            }\n\n            if (start <= 0 || stop <= 0 || start > length(json) || stop > length(json) || start >= stop) {\n                if (foundKeyCount == 0) {print defaultValue;} exit 0;\n            } else {\n                print substr(json, start, stop - start);\n            }\n\n            json = substr(json, stop + 1, length(json) - stop)\n        }\n    }'\n}\n\nif [ -z ${ariusHost} ]; then\n    echo \"error: ariusHost not specified.\"\n    exit 1\nfi\n\nif [ -z ${ariusPort} ]; then\n    echo \"error: ariusPort not specified.\"\n    exit 1\nfi\n\nif [ -z ${clusterMasterIp} ]; then\n    echo \"error: clusterMasterIp not specified.\"\n    exit 1\nfi\n\nif [ -z ${clusterMasterPort} ]; then\n    echo \"error: clusterMasterPort not specified.\"\n    exit 1\nfi\n\ncurlCmdForCheckClusterIsExitResp=$(curl -X GET \"http://${ariusHost}:${ariusPort}/admin/api/v3/white/phy/cluster/${phyClusterName}/isExit\" -H \"Cookie: domainAccount=${domainAccount}\" -H \"X-SSO-USER: ${ariusResponsible}\" -H \"X-ARIUS-APP-ID: ${ariusManagerAppId}\" -H \"content-type: application/json\")\ncodeForCheckClusterIsExitResp=$(getJsonValuesByAwk \"${curlCmdForCheckClusterIsExitResp}\" code \"\"  | sed 's/\\\"//g')\nif [ \"x$codeForCheckClusterIsExitResp\" == \"x0\" ]; then\n    echo \"join cluster is exit...\"\n    if [ \"x$deleteExitMateClusterFlag\" == \"x1\" ]; then\n    curlCmdForDelMetaDataClusterResp=$(curl -X DELETE \"http://${ariusHost}:${ariusPort}/admin/api/v3/white/phy/cluster/${phyClusterName}/del\" -H \"Cookie: domainAccount=${domainAccount}\" -H \"X-SSO-USER: ${ariusResponsible}\" -H \"X-ARIUS-APP-ID: ${ariusManagerAppId}\" -H \"content-type: application/json\")\n    fi\nfi\n\necho \"starting join cluster...\"\n    for file in `ls ${metaDataClusterDir}`\n        do\n            joinClusterName=`echo ${file}`\n            file=\"${metaDataClusterDir}/${file}\"\n            echo \"handle file ${file}\"\n             # 替换数据\n            # 元数据集群master节点Ip\n            sed -i '' \"s/\\\"ip\\\":.*/\\\"ip\\\": \\\"${clusterMasterIp}\\\",/g\" ${file}\n\n            # 元数据集群端master节点端口号\n            sed -i '' \"s/\\\"port\\\":.*/\\\"port\\\": ${clusterMasterPort},/g\" ${file}\n\n            # 指定接入集群master角色\n            sed -i '' \"s/\\\"role\\\":.*/\\\"role\\\": 3,/g\" ${file}\n\n            joinClusterContent=`cat ${file}`\n\n            curlCmdForJoinResp=$(curl -X POST \"http://${ariusHost}:${ariusPort}/admin/api/v3/op/phy/cluster/join\" -H \"Cookie: domainAccount=${domainAccount}\" -H \"X-SSO-USER: ${ariusResponsible}\" -H \"X-ARIUS-APP-ID: ${ariusManagerAppId}\" -H \"content-type: application/json\" -d \"${joinClusterContent}\")\n\n            code=$(getJsonValuesByAwk \"${curlCmdForJoinResp}\" code \"\"  | sed 's/\\\"//g')\n\n            if [ \"x$code\" == \"x0\" ];\n            then\n                echo \"Get the return value successfully and start field parsing\"\n                logicClusterId=$(getJsonValuesByAwk \"${curlCmdForJoinResp}\" v1 \"\"  | sed 's/\\\"//g')\n                phyClusterName=$(getJsonValuesByAwk \"${curlCmdForJoinResp}\" v2 \"\"  | sed 's/\\\"//g')\n            else\n                echo \"Failed to join meta data cluster\"\n                exit 1;\n            fi\n\n            echo \"${curlCmdForJoinResp}\"\n            eval \"${curlCmdForJoinResp}\"\n    done\necho \"Successful join cluster!!!\"\n\n\necho \"start checking join cluster valid...\"\nfor i in `seq 1 50`\ndo\n    echo  \"Loop checking metadata cluster status, number of times: ${i}\"\n    curlCmdForCheckClusterHealthResp=$(curl -X GET \"http://${ariusHost}:${ariusPort}/admin/api/v3/white/phy/cluster/${phyClusterName}/checkHealth\" -H \"Cookie: domainAccount=${domainAccount}\" -H \"X-SSO-USER: ${ariusResponsible}\" -H \"X-ARIUS-APP-ID: ${ariusManagerAppId}\" -H \"content-type: application/json\")\n    codeForCheckClusterHealthResp=$(getJsonValuesByAwk \"${curlCmdForCheckClusterHealthResp}\" code \"\"  | sed 's/\\\"//g')\n    if [ \"x$codeForCheckClusterHealthResp\" == \"x0\" ];\n        then\n            break\n    fi\n    sleep 1\ndone\n\nif [ \"x$codeForCheckClusterHealthResp\" != \"x0\" ];\n    then\n        echo \"join matedata cluster is invalid\"\n    else\n        echo \"joined cluster is Effective!!!\"\nfi\n\n\necho \"${logicClusterId}\"\necho \"${phyClusterName}\"\nsleep 3\n\necho \"starting created system template for arius...\"\nfor file in `ls ${templateDirForArius}`\n    do\n        templateName=`echo ${file}`\n        file=\"${templateDirForArius}/${file}\"\n        echo \"handle file ${file}\"\n        # 替换模板数据\n        # 负责人\n        sed -i '' \"s/\\\"responsible\\\":.*/\\\"responsible\\\": \\\"${ariusResponsible}\\\",/g\" ${file}\n\n        # 项目appId\n        sed -i '' \"s/\\\"appId\\\":.*/\\\"appId\\\": ${ariusManagerAppId},/g\" ${file}\n\n        # 逻辑集群ID\n        sed -i '' \"s/\\\"resourceId\\\":.*/\\\"resourceId\\\": ${logicClusterId},/g\" ${file}\n\n        # 物理集群名\n        sed -i '' \"s/\\\"cluster\\\":.*/\\\"cluster\\\": \\\"${phyClusterName}\\\",/g\" ${file}\n\n        # 物理模板角色\n        sed -i '' \"s/\\\"role\\\":.*/\\\"role\\\": 1,/g\" ${file}\n\n        # 数据类型-系统数据\n        sed -i '' \"s/\\\"dataType\\\":.*/\\\"dataType\\\": 0,/g\" ${file}\n\n        templateContentForArius=`cat ${file}`\n\n        curlCmdForTemplate=\"curl -X PUT 'http://${ariusHost}:${ariusPort}/admin/api/v2/op/template/logic/add' -H 'Cookie: domainAccount=${domainAccount}' -H 'X-SSO-USER: ${ariusResponsible}' -H 'X-ARIUS-APP-ID: ${ariusManagerAppId}' -H 'content-type: application/json' -d '${templateContentForArius}'\"\n        echo \"${curlCmdForTemplate}\"\n        sleep 1\n        eval \"${curlCmdForTemplate}\"\n    done\n\n\necho \"starting created system template for mateDataCluster...\"\nfor file in `ls ${templateDirForCluster}`\n    do\n        templateName=`echo ${file}`\n        file=\"${templateDirForCluster}/${file}\"\n\n        templateContentForCluster=`cat ${file}`\n        echo -e \"\\ncreate admin template ${templateName}\"\n        response=`curl -X PUT \"http://${clusterMasterIp}:${clusterMasterPort}/_template/${templateName}\" -H 'content-type: application/json' -d \"${templateContentForCluster}\"`\n        echo \"${response}\"\ndone\necho \"System template created successfully!!!\"\n\necho -e \"\\nfinished.\""
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/init_template.sql",
    "content": "insert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time, department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1000, 1, 'arius.dsl.analyze.result', -1, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3',  'logTime', '', '', '', 'arius.dsl.analyze.result', 'DSL分析结果', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1000, 1000, 'arius.dsl.analyze.result', 'arius.dsl.analyze.result', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1001, 1, 'arius.dsl.metrics', 2, '_yyyy-MM-dd', 'cn', 150, '2', 'bu_809', '商业数据产品团队', '1,3',  'timeStamp', '', '', '', 'arius.dsl.metrics*', '用户查询聚合信息', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1001, 1001, 'arius.dsl.metrics', 'arius.dsl.metrics*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1002, 1, 'arius.gateway.join', 2, '_yyyy-MM-dd', 'cn', 150, '2', 'bu_809', '商业数据产品团队', '1,3', 'timeStamp', '', '', '', 'arius.gateway.join*', 'gateway日志按照requestId进行join', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1002, 1002, 'arius.gateway.join', 'arius.gateway.join*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1003, 1, 'arius_monitor_alarm_history', 2, '_yyyy-MM-dd', 'cn', 150, '2', 'bu_809', '商业数据产品团队', '1,3', 'etime', '', '', '', 'arius_monitor_alarm_history*', '日志服务所有历史报警入ES日志服务所有历史报警入ES日志服务所有历史报警入ES日志服务所有历史报警入ES', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1003, 1003, 'arius_monitor_alarm_history', 'arius_monitor_alarm_history*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1004, 1, 'arius.dsl.template', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.dsl.template', 'DSL审核与分析', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1004, 1004, 'arius.dsl.template', 'arius.dsl.template', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1005, 1, 'arius.template.field', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.template.field', '索引模板字段数据', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1005, 1005, 'arius.template.field', 'arius.template.field', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1006, 1, 'arius.dsl.field.use', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.dsl.field.use', '字段使用索引', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1006, 1006, 'arius.dsl.field.use', 'arius.dsl.field.use', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1007, 1, 'arius.template.mapping', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.template.mapping', '索引mapping', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1007, 1007, 'arius.template.mapping', 'arius.template.mapping', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1008, 1, 'arius.index.size', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.index.size', '索引大小', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1008, 1008, 'arius.index.size', 'arius.index.size', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1009, 1, 'arius.template.hit', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.template.hit', '查询索引命中', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1009, 1009, 'arius.template.hit', 'arius.template.hit', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1010, 1, 'arius.template.cold', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.template.cold', '冷存储模版配置', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1010, 1010, 'arius.template.cold', 'arius.template.cold', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1011, 1, 'arius.template.cold.core', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.template.cold.core', '核心索引', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1011, 1011, 'arius.template.cold.core', 'arius.template.cold.core', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1012, 1, 'arius.md5.relation', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.md5.relation', '查询模板平滑升级', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1012, 1012, 'arius.md5.relation', 'arius.md5.relation', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1013, 1, 'arius.schedule.job', 2, '\n', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.schedule.job', '调度记录', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1013, 1013, 'arius.schedule.job', 'arius.schedule.job', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1014, 1, 'arius_stats_info', 2, '_yyyy-MM-dd', 'cn', 90, '2', 'bu_809', '商业数据产品团队', '1,3', 'timestamp', '', '', '', 'arius_stats_info*', '调度记录', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1014, 1014, 'arius_stats_info', 'arius_stats_info*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1015, 1, 'arius.field.cardinal.number', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.field.cardinal.number', '索引基数统计', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1015, 1015, 'arius.field.cardinal.number', 'arius.field.cardinal.number', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1016, 1, 'foundation_fd.data-online.arius.gateway', 2, '_yyyy-MM-dd', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'foundation_fd.data-online.arius.gateway*', '索引基数统计', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1016, 1016, 'foundation_fd.data-online.arius.gateway', 'foundation_fd.data-online.arius.gateway*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1017, 1, 'arius.appid.template.access', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.appid.template.access', 'appid维度访问次数索引', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1017, 1017, 'arius.appid.template.access', 'arius.appid.template.access', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1018, 1, 'arius.indexname.access', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.indexname.access', '索引维度访问次数索引', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1018, 1018, 'arius.indexname.access', 'arius.indexname.access', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1019, 1, 'arius.template.label', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.template.label', '索引标签数据', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1019, 1019, 'arius.template.label', 'arius.template.label', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1020, 1, 'arius.template.label', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.template.label', '索引标签数据', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1020, 1020, 'arius.template.label', 'arius.template.label', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1021, 1, 'arius.admin.db', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.admin.db', 'Arius数据库索引', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1021, 1021, 'arius.admin.db', 'arius.admin.db', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1022, 1, 'arius.template.customize.label', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius.template.customize.label', '用户自定义标签', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1022, 1022, 'arius.template.customize.label', 'arius.template.customize.label', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1023, 1, 'health_check_info', 2, '_yyyy-MM-dd', 'cn', 30, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'health_check_info*', 'es健康检查统计', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1023, 1023, 'health_check_info', 'health_check_info*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1024, 1, 'healht_check_white_list', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'healht_check_white_list', 'es健康检查统计白名单, 不进行健康检查', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1024, 1024, 'healht_check_white_list', 'healht_check_white_list', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1025, 1, 'index_health_degree', 2, '_yyyy-MM-dd', 'cn', 15, '2', 'bu_809', '商业数据产品团队', '1,3', 'timestamp', '', '', '', 'index_health_degree*', '健康分计算结果索引', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1025, 1025, 'index_health_degree', 'index_health_degree*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1026, 1, 'arius_cost_depart_cluster_detail', 2, '_yyyy-MM-dd', 'cn', 15, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius_cost_depart_cluster_detail*', 'arius独立集群成本统计, 不要随意改成按月保存', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1026, 1026, 'arius_cost_depart_cluster_detail', 'arius_cost_depart_cluster_detail*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1027, 1, 'arius_cost_depart_index_detail', 2, '_yyyy-MM-dd', 'cn', 150, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius_cost_depart_index_detail*', 'arius索引成本统计, 不要随意改成按月保存', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1027, 1027, 'arius_cost_depart_index_detail', 'arius_cost_depart_index_detail*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1028, 1, 'arius_cost_t2_total', 2, '_yyyy-MM-dd', 'cn', 150, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius_cost_t2_total*', 'arius二级部门成本统计, 不要随意改成按月保存', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1028, 1028, 'arius_cost_t2_total', 'arius_cost_t2_total*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\n\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1029, 1, 'arius_cost_t3_total', 2, '_yyyy-MM-dd', 'cn', 150, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius_cost_t3_total*', 'arius三级部门成本统计, 不要随意改成按月保存', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1029, 1029, 'arius_cost_t3_total', 'arius_cost_t3_total*', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n\n\ninsert into index_template\n(id, is_active, `name`, data_type, date_format, data_center, expire_time, hot_time,  department_id, department, responsible, date_field, date_field_format, id_field, routing_field, expression,`desc`, quota, app_id, ingest_pipeline)\nvalues\n(1030, 1, 'arius_template_quota_usage', 2, '', 'cn', -1, '2', 'bu_809', '商业数据产品团队', '1,3', 'logTime', '', '', '', 'arius_template_quota_usage', 'DSL审核与分析', 1, 3, '');\n\ninsert into index_template_physical\n(id, logic_id, `name`, expression, cluster, rack, shard, shard_routing, version, role, config)\nvalues\n(1030, 1030, 'arius_template_quota_usage', 'arius_template_quota_usage', 'dc-es02', 'r1', 16, 10, 0, 1, \"\");\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/join_cluster_in_logi_em/join_cluster_info",
    "content": "{\n    \"tags\":\"{\\\"resourceType\\\":3, \\\"createSource\\\":0}\",\n    \"importRule\":\"0\",\n    \"type\": 4,\n    \"appId\": 1,\n    \"cluster\": \"logi-em-matedata-cluster\",\n    \"divide\": true,\n    \"esVersion\": \"7.6.0.1401\",\n    \"logicCluster\": \"logi-em-matedata-cluster\",\n    \"phyClusterDesc\": \"\",\n    \"regionRacks\": [],\n    \"clusterRoleHosts\": [\n        {\n            \"cluster\": \"logi-em-matedata-cluster\",\n            \"id\": 0,\n            \"ip\": \"10.96.65.63\",\n            \"nodeSet\": \"\",\n            \"port\": 8060,\n            \"role\": 3,\n            \"roleClusterId\": 0,\n            \"status\": 0\n        }\n    ]\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/security/logi_sercurity.sql",
    "content": "# -------------------------------------------------权限点表-----------------------------\n-- auto-generated definition\ncreate table if not exists logi_security_permission\n(\n    id              int auto_increment\n        primary key,\n    permission_name varchar(40)                          not null comment '权限名字',\n    parent_id       int                                  not null comment '父权限id',\n    leaf            tinyint(1)                           not null comment '是否叶子权限点（具体的操作）',\n    level           tinyint                              not null comment '权限点的层级（parentId为0的层级为1）',\n    description     varchar(64)                          null comment '权限点描述',\n    create_time     timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time     timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete       tinyint(1) default 0                 null comment '逻辑删除',\n    app_name        varchar(16)                          null comment '应用名称'\n)\n    comment '权限表' charset = utf8;\n\ninsert into logi_security_permission (id, permission_name, parent_id, leaf, level, description, create_time,\n                                      update_time, is_delete, app_name)\nvalues (1593, '物理集群', 0, 0, 1, '物理集群', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1595, '我的集群', 0, 0, 1, '我的集群', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1597, '集群版本', 0, 0, 1, '集群版本', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1599, 'Gateway管理', 0, 0, 1, 'Gateway管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0,\n        'know_search'),\n       (1601, '模板管理', 0, 0, 1, '模板管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1603, '模板服务', 0, 0, 1, '模板服务', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1605, '索引管理', 0, 0, 1, '索引管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1607, '索引服务', 0, 0, 1, '索引服务', '2022-05-24 18:08:22.0', '2022-05-24 18:24:16.0', 0, 'know_search'),\n       (1609, '索引查询', 0, 0, 1, '索引查询', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1611, '查询诊断', 0, 0, 1, '查询诊断', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1613, '集群看板', 0, 0, 1, '集群看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1615, '网关看板', 0, 0, 1, '网关看板', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1617, '我的申请', 0, 0, 1, '我的申请', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1619, '我的审批', 0, 0, 1, '我的审批', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1621, '任务列表', 0, 0, 1, '任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1623, '调度任务列表', 0, 0, 1, '调度任务列表', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0,\n        'know_search'),\n       (1625, '调度日志', 0, 0, 1, '调度日志', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1627, '用户管理', 0, 0, 1, '用户管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1629, '角色管理', 0, 0, 1, '角色管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1631, '应用管理', 0, 0, 1, '应用管理', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1633, '平台配置', 0, 0, 1, '平台配置', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1635, '操作记录', 0, 0, 1, '操作记录', '2022-05-24 18:08:22.0', '2022-05-24 18:08:22.0', 0, 'know_search'),\n       (1637, '查看集群列表及详情', 1593, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0',\n        0, 'know_search'),\n       (1639, '接入集群', 1593, 1, 2, '接入集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n       (1641, '新建集群', 1593, 1, 2, '新建集群', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n       (1643, '扩缩容', 1593, 1, 2, '扩缩容', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n       (1645, '升级', 1593, 1, 2, '升级', '2022-05-24 18:08:22.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n       (1647, '重启', 1593, 1, 2, '重启', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n       (1649, '配置变更', 1593, 1, 2, '配置变更', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n       (1651, 'Region划分', 1593, 1, 2, 'Region划分', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0,\n        'know_search'),\n       (1653, 'Region管理', 1593, 1, 2, 'Region管理', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0,\n        'know_search'),\n       (1655, '快捷命令', 1593, 1, 2, '快捷命令', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n       (1657, '编辑', 1593, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0, 'know_search'),\n       (1659, '绑定Gateway', 1593, 1, 2, '绑定Gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:10:32.0', 0,\n        'know_search'),\n       (1661, '下线', 1593, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n       (1663, '查看集群列表及详情', 1595, 1, 2, '查看集群列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0',\n        0, 'know_search'),\n       (1665, '申请集群', 1595, 1, 2, '申请集群', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n       (1667, '编辑', 1595, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n       (1669, '扩缩容', 1595, 1, 2, '扩缩容', '2022-05-24 18:08:23.0', '2022-05-24 18:10:52.0', 0, 'know_search'),\n       (1671, '下线', 1595, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n       (1673, '查看版本列表', 1597, 1, 2, '查看版本列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0,\n        'know_search'),\n       (1675, '新增版本', 1597, 1, 2, '新增版本', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n       (1677, '编辑', 1597, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:44.0', 0, 'know_search'),\n       (1679, '删除', 1597, 1, 2, '删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n       (1681, '查看Gateway 集群列表', 1599, 1, 2, '查看Gateway 集群列表', '2022-05-24 18:08:23.0',\n        '2022-05-24 18:20:45.0', 0,\n        'know_search'),\n       (1683, '接入gateway', 1599, 1, 2, '接入gateway', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0,\n        'know_search'),\n       (1685, '编辑', 1599, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n       (1687, '下线', 1599, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n       (1689, '查看模板列表及详情', 1601, 1, 2, '查看模板列表及详情', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0',\n        0, 'know_search'),\n       (1691, '申请模板', 1601, 1, 2, '申请模板', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n       (1693, '编辑', 1601, 1, 2, '编辑', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n       (1695, '下线', 1601, 1, 2, '下线', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0, 'know_search'),\n       (1697, '编辑Mapping', 1601, 1, 2, '编辑Mapping', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0,\n        'know_search'),\n       (1699, '编辑Setting', 1601, 1, 2, '编辑Setting', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0,\n        'know_search'),\n       (1701, '查看模板列表', 1603, 1, 2, '查看模板列表', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0,\n        'know_search'),\n       (1703, '开关：预创建', 1603, 1, 2, '开关：预创建', '2022-05-24 18:08:23.0', '2022-06-14 16:49:48.0', 0,\n        'know_search'),\n       (1705, '开关：过期删除', 1603, 1, 2, '开关：过期删除', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0,\n        'know_search'),\n       (1707, '开关：冷热分离', 1603, 1, 2, '开关：冷热分离', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0,\n        'know_search'),\n       (1709, '开关：pipeline', 1603, 1, 2, '开关：写入限流', '2022-05-24 18:08:23.0', '2022-06-14 16:49:49.0', 0,\n        'know_search'),\n       (1711, '开关：Rollover', 1603, 1, 2, '开关：Rollover', '2022-05-24 18:08:23.0', '2022-05-24 18:20:45.0', 0,\n        'know_search'),\n       (1713, '查看DCDR链路', 1603, 1, 2, '查看DCDR链路', '2022-05-24 18:08:23.0', '2022-05-24 18:20:46.0', 0,\n        'know_search'),\n       (1715, '创建DCDR链路', 1603, 1, 2, '创建DCDR链路', '2022-05-24 18:08:24.0', '2022-05-24 18:20:45.0', 0,\n        'know_search'),\n       (1717, '清理', 1603, 1, 2, '清理', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n       (1719, '扩缩容', 1603, 1, 2, '扩缩容', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n       (1721, '升版本', 1603, 1, 2, '升版本', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n       (1723, '批量操作', 1603, 1, 2, '批量操作', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n       (1725, '查看索引列表及详情', 1605, 1, 2, '查看索引列表及详情', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0',\n        0, 'know_search'),\n       (1727, '编辑Mapping', 1605, 1, 2, '编辑Mapping', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0,\n        'know_search'),\n       (1729, '编辑Setting', 1605, 1, 2, '编辑Setting', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0,\n        'know_search'),\n       (1731, '禁用读', 1607, 1, 2, '禁用读', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n       (1733, '禁用写', 1607, 1, 2, '禁用写', '2022-05-24 18:08:24.0', '2022-07-15 08:50:56.0', 0, 'know_search'),\n       (1735, '设置别名', 1605, 1, 2, '设置别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n       (1737, '删除别名', 1605, 1, 2, '删除别名', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n       (1739, '关闭索引', 1607, 1, 2, '关闭索引', '2022-05-24 18:08:24.0', '2022-07-15 09:52:25.0', 0, 'know_search'),\n       (1741, '下线', 1605, 1, 2, '下线', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n       (1743, '批量删除', 1605, 1, 2, '批量删除', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n       (1745, '查看列表', 1607, 1, 2, '查看列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n       (1747, '执行Rollover', 1607, 1, 2, '执行Rollover', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0,\n        'know_search'),\n       (1749, '执行shrink', 1607, 1, 2, '执行shrink', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0,\n        'know_search'),\n       (1751, '执行split', 1607, 1, 2, '执行split', '2022-05-24 18:08:24.0', '2022-05-24 18:20:46.0', 0, 'know_search'),\n       (1753, '执行ForceMerge', 1607, 1, 2, '执行ForceMerge', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0,\n        'know_search'),\n       (1755, '批量执行', 1607, 1, 2, '批量执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n       (1757, 'DSL查询', 1609, 1, 2, 'DSL查询', '2022-05-24 18:08:24.0', '2022-06-14 16:39:48.0', 0, 'know_search'),\n       (1759, '查看查询模板列表', 1611, 1, 2, '查看查询模板列表', '2022-05-24 18:08:24.0', '2022-06-14 16:40:21.0', 0,\n        'know_search'),\n       (1761, '查看集群看板', 1613, 1, 2, '查看集群看板', '2022-05-24 18:08:24.0', '2022-06-14 16:37:54.0', 0,\n        'know_search'),\n       (1763, '查看网关看板', 1615, 1, 2, '查看网关看板', '2022-05-24 18:08:24.0', '2022-06-14 16:38:14.0', 0,\n        'know_search'),\n       (1765, '查看我的申请列表', 1617, 1, 2, '查看我的申请列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0,\n        'know_search'),\n       (1767, '撤回', 1617, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n       (1769, '查看我的审批列表', 1619, 1, 2, '查看我的审批列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0,\n        'know_search'),\n       (1771, '驳回', 1619, 1, 2, '撤回', '2022-05-24 18:08:24.0', '2022-07-18 20:57:33.0', 0, 'know_search'),\n       (1773, '通过', 1619, 1, 2, '通过', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n       (1775, '查看任务列表', 1621, 1, 2, '查看任务列表', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0,\n        'know_search'),\n       (1777, '查看进度', 1621, 1, 2, '查看进度', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n       (1779, '执行', 1621, 1, 2, '执行', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n       (1781, '暂停', 1621, 1, 2, '暂停', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n       (1783, '重试', 1621, 1, 2, '重试', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n       (1785, '取消', 1621, 1, 2, '取消', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0, 'know_search'),\n       (1787, '查看日志（子任务）', 1621, 1, 2, '查看日志（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:47.0', 0,\n        'know_search'),\n       (1789, '重试（子任务）', 1621, 1, 2, '重试（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1791, '忽略（子任务）', 1621, 1, 2, '忽略（子任务）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1793, '查看详情（DCDR）', 1621, 1, 2, '查看详情（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1795, '取消（DCDR）', 1621, 1, 2, '取消（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1797, '重试（DCDR）', 1621, 1, 2, '重试（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1799, '强切（DCDR）', 1621, 1, 2, '强切（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1801, '返回（DCDR）', 1621, 1, 2, '返回（DCDR）', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1803, '查看任务列表', 1623, 1, 2, '查看任务列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1805, '查看日志', 1623, 1, 2, '查看日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n       (1807, '执行', 1623, 1, 2, '执行', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n       (1809, '暂停', 1623, 1, 2, '暂停', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n       (1811, '查看调度日志列表', 1625, 1, 2, '查看调度日志列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1813, '调度详情', 1625, 1, 2, '调度详情', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n       (1815, '执行日志', 1625, 1, 2, '执行日志', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n       (1817, '终止任务', 1625, 1, 2, '终止任务', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n       (1819, '查看用户列表', 1627, 1, 2, '查看用户列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1821, '分配角色', 1627, 1, 2, '分配角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0, 'know_search'),\n       (1823, '查看角色列表', 1629, 1, 2, '查看角色列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:48.0', 0,\n        'know_search'),\n       (1825, '编辑', 1629, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n       (1827, '绑定用户', 1629, 1, 2, '绑定用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n       (1829, '回收用户', 1629, 1, 2, '回收用户', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n       (1831, '删除角色', 1629, 1, 2, '删除角色', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n       (1833, '查看应用列表', 1631, 1, 2, '查看应用列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0,\n        'know_search'),\n       (1835, '新建应用', 1631, 1, 2, '新建应用', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n       (1837, '编辑', 1631, 1, 2, '编辑', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n       (1839, '删除', 1631, 1, 2, '删除', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n       (1841, '访问设置', 1631, 1, 2, '访问设置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0, 'know_search'),\n       (1843, '查看平台配置列表', 1633, 1, 2, '查看平台配置列表', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0,\n        'know_search'),\n       (1845, '新增平台配置', 1633, 1, 2, '新增平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0,\n        'know_search'),\n       (1847, '禁用平台配置', 1633, 1, 2, '禁用平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0,\n        'know_search'),\n       (1849, '编辑平台配置', 1633, 1, 2, '编辑平台配置', '2022-05-24 18:08:25.0', '2022-05-24 18:20:49.0', 0,\n        'know_search'),\n       (1851, '删除平台配置', 1633, 1, 2, '删除平台配置', '2022-05-24 18:08:26.0', '2022-05-24 18:20:49.0', 0,\n        'know_search'),\n       (1853, '查看操作记录列表', 1635, 1, 2, '查看操作记录列表', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0,\n        'know_search'),\n       (1855, 'Kibana', 1609, 1, 2, 'Kibana', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n       (1857, 'SQL查询', 1609, 1, 2, 'SQL查询', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n       (1859, '批量修改限流值', 1611, 1, 2, '批量修改限流值', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0,\n        'know_search'),\n       (1861, '禁用', 1611, 1, 2, '禁用', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0, 'know_search'),\n       (1863, '修改限流值', 1611, 1, 2, '修改限流值', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0,\n        'know_search'),\n       (1865, '查看异常查询列表', 1611, 1, 2, '查看异常查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:02.0', 0,\n        'know_search'),\n       (1867, '查看慢查询列表', 1611, 1, 2, '查看慢查询列表', '2022-05-24 18:08:26.0', '2022-06-14 16:44:21.0', 0,\n        'know_search'),\n       (1869, '新增角色', 1629, 1, 2, '新增角色', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n       (1871, 'Dashboard', 0, 0, 1, '查看dashboard', '2022-05-24 18:08:26.0', '2022-07-19 11:37:01.0', 0,\n        'know_search'),\n       (1873, '新建索引', 1605, 1, 2, '新建索引', '2022-05-24 18:08:26.0', '2022-05-24 18:23:34.0', 0, 'know_search'),\n       (1875, '查看dashboard', 1871, 1, 2, '查看dashboard', '2022-05-24 18:08:24.0', '2022-05-24 18:20:47.0', 0,\n        'know_search');\n\n\n# ---------------------------------------------角色表------------------------------\n-- auto-generated definition\ncreate table if not exists logi_security_role\n(\n    id           int auto_increment\n        primary key,\n    role_code    varchar(128)                         not null comment '角色编号',\n    role_name    varchar(128)                         not null comment '名称',\n    description  varchar(128)                         null comment '角色描述',\n    last_reviser varchar(30)                          null comment '最后修改人',\n    create_time  timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time  timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete    tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name     varchar(16)                          null comment '应用名称'\n)\n    comment '角色信息' charset = utf8;\ninsert into logi_security_role (id, role_code, role_name, description, last_reviser, create_time,\n                                update_time, is_delete, app_name)\nvalues (1, 'r14715628', '管理员', '管理员', 'admin', '2022-06-01 21:19:42.0', '2022-07-06 22:23:59.0', 0,\n        'know_search'),\n       (2, 'r14481382', '资源owner', '普通用户拥有的最大权限', 'admin', '2022-06-14 18:08:56.0',\n        '2022-07-06 20:36:31.0', 0,\n        'know_search');\n\n# --------------------------------------角色权限点关联表-------------------------------\n-- auto-generated definition\ncreate table if not exists logi_security_role_permission\n(\n    id            int auto_increment\n        primary key,\n    role_id       int                                  not null comment '角色id',\n    permission_id int                                  not null comment '权限id',\n    create_time   timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time   timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete     tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name      varchar(16)                          null comment '应用名称'\n)\n    comment '角色权限表（只保留叶子权限与角色关系）' charset = utf8;\ninsert into logi_security_role_permission (id, role_id, permission_id, create_time, update_time,\n                                           is_delete, app_name)\nvalues (1597, 1, 0, '2022-06-01 21:19:42.0', '2022-06-23 09:15:36.0', 1, 'know_search'),\n       (1935, 1, 1593, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1937, 1, 1637, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1939, 1, 1639, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1941, 1, 1641, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1943, 1, 1643, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1945, 1, 1645, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1947, 1, 1647, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1949, 1, 1649, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1951, 1, 1651, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1953, 1, 1653, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1955, 1, 1655, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1957, 1, 1657, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1959, 1, 1659, '2022-06-14 17:41:03.0', '2022-07-18 17:12:20.0', 1, 'know_search'),\n       (1961, 1, 1661, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1963, 1, 1597, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1965, 1, 1673, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1967, 1, 1675, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1969, 1, 1677, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1971, 1, 1679, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1973, 1, 1599, '2022-06-14 17:41:03.0', '2022-07-18 17:12:47.0', 1, 'know_search'),\n       (1975, 1, 1681, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1977, 1, 1683, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1979, 1, 1685, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1981, 1, 1687, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1983, 1, 1601, '2022-06-14 17:41:03.0', '2022-07-15 08:45:07.0', 1, 'know_search'),\n       (1985, 1, 1689, '2022-06-14 17:41:03.0', '2022-07-15 08:45:07.0', 1, 'know_search'),\n       (1987, 1, 1691, '2022-06-14 17:41:03.0', '2022-07-15 08:45:07.0', 1, 'know_search'),\n       (1989, 1, 1693, '2022-06-14 17:41:03.0', '2022-07-15 08:45:07.0', 1, 'know_search'),\n       (1991, 1, 1695, '2022-06-14 17:41:03.0', '2022-07-15 08:45:07.0', 1, 'know_search'),\n       (1993, 1, 1697, '2022-06-14 17:41:03.0', '2022-07-15 08:45:07.0', 1, 'know_search'),\n       (1995, 1, 1699, '2022-06-14 17:41:03.0', '2022-07-15 08:45:07.0', 1, 'know_search'),\n       (1997, 1, 1603, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (1999, 1, 1701, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2001, 1, 1703, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2003, 1, 1705, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2005, 1, 1707, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2007, 1, 1709, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2009, 1, 1711, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2011, 1, 1713, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2013, 1, 1715, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2015, 1, 1717, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2017, 1, 1719, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2019, 1, 1721, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2021, 1, 1723, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2023, 1, 1605, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2025, 1, 1725, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2027, 1, 1727, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2029, 1, 1729, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2031, 1, 1731, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2033, 1, 1733, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2035, 1, 1735, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2037, 1, 1737, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2039, 1, 1739, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2041, 1, 1741, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2043, 1, 1743, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2045, 1, 1607, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2047, 1, 1745, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2049, 1, 1747, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2051, 1, 1749, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2053, 1, 1751, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2055, 1, 1753, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2057, 1, 1755, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2059, 1, 1609, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2061, 1, 1757, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2063, 1, 1855, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2065, 1, 1857, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2067, 1, 1611, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2069, 1, 1759, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2071, 1, 1859, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2073, 1, 1861, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2075, 1, 1863, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2077, 1, 1865, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2079, 1, 1867, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2081, 1, 1613, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2083, 1, 1761, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2085, 1, 1615, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2087, 1, 1763, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2089, 1, 1619, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2091, 1, 1769, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2093, 1, 1771, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2095, 1, 1773, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2097, 1, 1621, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2099, 1, 1775, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2101, 1, 1777, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2103, 1, 1779, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2105, 1, 1781, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2107, 1, 1783, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2109, 1, 1785, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2111, 1, 1787, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2113, 1, 1789, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2115, 1, 1791, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2117, 1, 1793, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2119, 1, 1795, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2121, 1, 1797, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2123, 1, 1799, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2125, 1, 1801, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2127, 1, 1623, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2129, 1, 1803, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2131, 1, 1805, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2133, 1, 1807, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2135, 1, 1809, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2137, 1, 1625, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2139, 1, 1811, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2141, 1, 1813, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2143, 1, 1815, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2145, 1, 1817, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2147, 1, 1627, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2149, 1, 1819, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2151, 1, 1821, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2153, 1, 1629, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2155, 1, 1823, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2157, 1, 1825, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2159, 1, 1827, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2161, 1, 1829, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2163, 1, 1831, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2165, 1, 1631, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2167, 1, 1833, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2169, 1, 1835, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2171, 1, 1837, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2173, 1, 1839, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2175, 1, 1841, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2177, 1, 1633, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2179, 1, 1843, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2181, 1, 1845, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2183, 1, 1847, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2185, 1, 1849, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2187, 1, 1851, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2189, 1, 1635, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2191, 1, 1853, '2022-06-14 17:41:03.0', '2022-06-23 09:15:36.0', 0, 'know_search'),\n       (2643, 1, 1595, '2022-06-17 16:39:23.0', '2022-06-24 11:51:51.0', 1, 'know_search'),\n       (4505, 1, 1869, '2022-07-04 15:45:59.0', '2022-07-04 15:45:59.0', 0, 'know_search'),\n       (4507, 1, 1871, '2022-07-04 15:46:56.0', '2022-07-04 15:46:56.0', 0, 'know_search'),\n       (5275, 1, 1873, '2022-06-17 15:53:54.0', '2022-06-30 12:17:40.0', 0, 'know_search'),\n       (5349, 1, 1875, '2022-06-17 15:53:54.0', '2022-06-30 12:17:40.0', 0, 'know_search'),\n       (2193, 2, 1595, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2195, 2, 1663, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2197, 2, 1665, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2199, 2, 1667, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2201, 2, 1669, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2203, 2, 1671, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2205, 2, 1601, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2207, 2, 1689, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2209, 2, 1691, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2211, 2, 1693, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2213, 2, 1695, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2215, 2, 1697, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2217, 2, 1699, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2219, 2, 1605, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2221, 2, 1725, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2223, 2, 1727, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2225, 2, 1729, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2227, 2, 1731, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2229, 2, 1733, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2231, 2, 1735, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2233, 2, 1737, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2235, 2, 1739, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2237, 2, 1741, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2239, 2, 1743, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2241, 2, 1609, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2243, 2, 1757, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2245, 2, 1855, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2247, 2, 1857, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2249, 2, 1611, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2251, 2, 1759, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2253, 2, 1859, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2255, 2, 1861, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2257, 2, 1863, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2259, 2, 1865, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2261, 2, 1867, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2263, 2, 1613, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2265, 2, 1761, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2267, 2, 1615, '2022-06-14 18:08:56.0', '2022-07-19 19:18:42.0', 1, 'know_search'),\n       (2269, 2, 1763, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2271, 2, 1617, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2273, 2, 1765, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2275, 2, 1767, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2277, 2, 1631, '2022-06-14 18:08:56.0', '2022-07-17 09:49:00.0', 0, 'know_search'),\n       (2279, 2, 1833, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2281, 2, 1835, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2283, 2, 1837, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2285, 2, 1839, '2022-06-14 18:08:56.0', '2022-06-23 09:15:57.0', 0, 'know_search'),\n       (2287, 2, 1841, '2022-06-14 18:08:56.0', '2022-07-18 16:05:42.0', 1, 'know_search'),\n       (5277, 2, 1873, '2022-06-17 15:53:54.0', '2022-06-30 12:17:40.0', 0, 'know_search');\n\n\n# --------------------------------------------------------------项目表-----------------------\n-- auto-generated definition\ncreate table if not exists logi_security_project\n(\n    id           int auto_increment comment '项目id'\n        primary key,\n    project_code varchar(128)                           not null comment '项目编号',\n    project_name varchar(128)                           not null comment '项目名',\n    description  varchar(512) default ''                not null comment '项目描述',\n    dept_id      int                                    not null comment '部门id',\n    running      tinyint(1)   default 1                 not null comment '启用 or 停用',\n    create_time  timestamp    default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time  timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete    tinyint(1)   default 0                 not null comment '逻辑删除',\n    app_name     varchar(16)                            null comment '应用名称'\n)\n    comment '项目表' charset = utf8;\ninsert into logi_security_project (id, project_code, project_name, description, dept_id, running,\n                                   create_time, update_time, is_delete, app_name)\nvalues (1, 'p14000143', 'superApp', '超级应用', 0, 1, '2022-05-26 05:49:08.0', '2022-07-25 09:28:50.0', 0,\n        'know_search');\ninsert into logi_security_project (id, project_code, project_name, description, dept_id, running,\n                                   create_time, update_time, is_delete, app_name)\nvalues (2, 'p14000141', 'app', '应用', 0, 1, '2022-05-26 05:49:08.0', '2022-07-25 09:28:50.0', 0, 'know_search');\n\n# -----------------------------user\n-- auto-generated definition\ncreate table if not exists logi_security_user\n(\n    id          int auto_increment\n        primary key,\n    user_name   varchar(64)                            not null comment '用户账号',\n    pw          varchar(2048)                          not null comment '用户密码',\n    salt        char(5)      default ''                not null comment '密码盐',\n    real_name   varchar(128) default ''                not null comment '真实姓名',\n    phone       char(11)     default ''                not null comment 'mobile',\n    email       varchar(30)  default ''                not null comment 'email',\n    dept_id     int                                    null comment '所属部门id',\n    is_delete   tinyint(1)   default 0                 not null comment '逻辑删除',\n    create_time timestamp    default CURRENT_TIMESTAMP null comment '注册时间',\n    update_time timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    app_name    varchar(16)                            null comment '应用名称'\n)\n    comment '用户信息' charset = utf8;\n# 初始密码：admin\ninsert into logi_security_user (id, user_name, pw, salt, real_name, phone, email, dept_id, is_delete,\n                                create_time, update_time, app_name)\nvalues (1593, 'admin',\n        'V1ZkU2RHRlhOVGRSUmxweFUycFNhR0V6ZEdKSk1FRjRVVU5PWkdaVmJ6SlZiWGh6WVVWQ09YdEFWbXBLTkdGcmUxc2pRREpBSTExOVNqWlNiR3hvUUgwPXtAVmpKNGFre1sjQDNAI119SjZSbGxoQH0=Mv{#cdRgJ45Lqx}3IubEW87!==',\n        '', 'admin', '13900', '', null, 0, '2022-05-26 05:46:12.0', '2022-06-23 16:47:13.0', 'know_search');\n\n# ---------------------------用户项目表\n-- auto-generated definition\ncreate table if not exists logi_security_user_project\n(\n    id          int auto_increment\n        primary key,\n    user_id     int                                   not null comment '用户id',\n    project_id  int                                   not null comment '项目id',\n    create_time timestamp   default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp   default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1)  default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                           null comment '应用名称',\n    user_type   tinyint(10) default 0                 not null comment '用户类型：0：普通项目用户；1：项目owner'\n)\n    comment '用户项目关系表（项目负责人）' charset = utf8;\n\ninsert into logi_security_user_project (id, user_id, project_id, create_time, update_time, is_delete,\n                                        app_name, user_type)\nvalues (2327, 1593, 1, '2022-07-08 18:19:51.0', '2022-07-08 18:19:51.0', 0, 'know_search', 1),\n       (2329, 1593, 1, '2022-07-08 18:19:51.0', '2022-07-08 18:19:51.0', 0, 'know_search', 0),\n       (2330, 1593, 2, '2022-07-08 18:19:51.0', '2022-07-08 18:19:51.0', 0, 'know_search', 0);\n\n# ------------------------------用户角色表------------------------------\n-- auto-generated definition\ncreate table if not exists logi_security_user_role\n(\n    id          int auto_increment\n        primary key,\n    user_id     int                                  not null comment '用户id',\n    role_id     int                                  not null comment '角色id',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '用户角色表' charset = utf8;\n\ninsert into logi_security_user_role (id, user_id, role_id, create_time, update_time, is_delete, app_name)\nvalues (2369, 1593, 1, '2022-07-19 16:29:44.0', '2022-07-19 16:29:44.0', 0, 'know_search');\n\n# -----------------默认需要初始化的表\n-- auto-generated definition\ncreate table if not exists logi_security_config\n(\n    id          bigint unsigned auto_increment comment '主键自增'\n        primary key,\n    value_group varchar(100)  default ''                not null comment '配置项组',\n    value_name  varchar(100)  default ''                not null comment '配置项名字',\n    value       text                                    null comment '配置项的值',\n    edit        int(4)        default 1                 not null comment '是否可以编辑 1 不可编辑（程序获取） 2 可编辑',\n    status      int(4)        default 1                 not null comment '1 正常 2 禁用',\n    memo        varchar(1000) default ''                not null comment '备注',\n    create_time timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间',\n    is_delete   tinyint(1)    default 0                 not null comment '逻辑删除',\n    app_name    varchar(16) collate utf8_bin            null comment '应用名称',\n    operator    varchar(16) collate utf8_bin            null comment '操作者'\n)\n    comment 'logi配置项' charset = utf8;\n\ncreate index idx_group_name\n    on logi_security_config (value_group, value_name);\n\n-- auto-generated definition\ncreate table if not exists logi_security_dept\n(\n    id          int auto_increment\n        primary key,\n    dept_name   varchar(10)                          not null comment '部门名',\n    parent_id   int                                  not null comment '父部门id',\n    leaf        tinyint(1)                           not null comment '是否叶子部门',\n    level       tinyint                              not null comment 'parentId为0的层级为1',\n    description varchar(20)                          null comment '描述',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '部门信息表' charset = utf8;\n\n-- auto-generated definition\ncreate table if not exists logi_security_message\n(\n    id          int auto_increment\n        primary key,\n    title       varchar(60)                          not null comment '标题',\n    content     varchar(256)                         null comment '内容',\n    read_tag    tinyint(1) default 0                 null comment '是否已读',\n    oplog_id    int                                  null comment '操作日志id',\n    user_id     int                                  null comment '这条消息属于哪个用户的，用户id',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '消息中心' charset = utf8;\n\n-- auto-generated definition\ncreate table if not exists logi_security_oplog\n(\n    id                int auto_increment\n        primary key,\n    operator_ip       varchar(20)                            not null comment '操作者ip',\n    operator          varchar(20)                            null comment '操作者账号',\n    operate_page      varchar(16)                            null comment '操作页面',\n    operate_type      varchar(16)                            not null comment '操作类型',\n    target_type       varchar(16)                            not null comment '对象分类',\n    target            varchar(20)                            not null comment '操作对象',\n    detail            text                                   null comment '日志详情',\n    create_time       timestamp    default CURRENT_TIMESTAMP null,\n    update_time       timestamp    default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete         tinyint(1)   default 0                 not null comment '逻辑删除',\n    app_name          varchar(16)                            null comment '应用名称',\n    operation_methods varchar(255) default ''                null\n)\n    comment '操作日志' charset = utf8;\n-- auto-generated definition\ncreate table if not exists logi_security_oplog_extra\n(\n    id          int auto_increment\n        primary key,\n    info        varchar(16)                          null comment '信息',\n    type        tinyint                              not null comment '哪种信息：1：操作页面;2：操作类型;3：对象分类',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '操作日志信息（操作页面、操作类型、对象分类）' charset = utf8;\n\n-- auto-generated definition\ncreate table if not exists logi_security_resource_type\n(\n    id          int auto_increment\n        primary key,\n    type_name   varchar(16)                          null comment '资源类型名',\n    create_time timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete   tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name    varchar(16)                          null comment '应用名称'\n)\n    comment '资源类型表' charset = utf8;\n-- auto-generated definition\ncreate table if not exists logi_security_user_resource\n(\n    id               int auto_increment\n        primary key,\n    user_id          int                                  not null comment '用户id',\n    project_id       int                                  not null comment '资源所属项目id',\n    resource_type_id int                                  not null comment '资源类别id',\n    resource_id      int                                  not null comment '资源id',\n    control_level    tinyint                              not null comment '管理级别：1（查看权限）2（管理权限）',\n    create_time      timestamp  default CURRENT_TIMESTAMP null comment '创建时间',\n    update_time      timestamp  default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',\n    is_delete        tinyint(1) default 0                 not null comment '逻辑删除',\n    app_name         varchar(16)                          null comment '应用名称'\n)\n    comment '用户和资源关系表' charset = utf8;\n\n# ------------------------------项目关联es user核心数据\n-- auto-generated definition\ncreate table if not exists arius_es_user\n(\n    id                 bigint(10) unsigned auto_increment comment '主键 自增'\n        primary key,\n    index_exp          text                                    null comment '索引表达式',\n    data_center        varchar(20)   default ''                not null comment '数据中心',\n    is_root            tinyint       default 0                 not null comment '是都是超级用户 超级用户具有所有索引的访问权限 0 不是 1是',\n    memo               varchar(1000) default ''                not null comment '备注',\n    ip                 varchar(500)  default ''                not null comment '白名单ip地址',\n    verify_code        varchar(50)   default ''                not null comment 'app验证码',\n    is_active          tinyint(2)    default 1                 not null comment '1为可用，0不可用',\n    query_threshold    int(10)       default 100               not null comment '限流值',\n    cluster            varchar(100)  default ''                not null comment '查询集群',\n    responsible        varchar(500)  default ''                null comment '责任人',\n    search_type        tinyint       default 0                 not null comment '0表示app的查询请求需要app里配置的集群(一般配置的都是trib集群) 1表示app的查询请求必须只能访问一个模板',\n    create_time        timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time        timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间',\n    project_id         bigint(10)                              not null comment '项目id',\n    is_default_display tinyint(2)    default 0                 not null comment '1：项目默认的es user；0:项目新增的es user'\n)\n    comment 'es操作用户表' charset = utf8;\n\ninsert into arius_es_user (id, index_exp, data_center, is_root, memo, ip, verify_code, is_active,\n                           query_threshold, cluster, search_type, create_time, update_time, project_id,\n                           is_default_display)\nvalues (1, null, 'cn', 1, '管理员APP', '', 'azAWiJhxkho33ac', 1, 100, 'logi-elasticsearch-7.6.0', 1,\n        '2022-05-26 09:35:38.0', '2022-06-23 00:16:47.0', 1, 1),\n       (233, null, 'cn', 0, '新增', '', 'vkDgPEfD3jQJ1YY', 1, 1000, '', 2, '2022-07-05 08:16:17.0',\n        '2022-07-05 08:16:17.0', 1, 0),\n       (234, null, 'cn', 0, '新增', '', 'vkDgPEfD3jQJ1YY', 1, 1000, '', 2, '2022-07-05 08:16:17.0',\n        '2022-07-05 08:16:17.0', 2, 1);\n# 项目配置信息\n-- auto-generated definition\ncreate table if not exists project_arius_config\n(\n    project_id              bigint(10) unsigned auto_increment comment 'project id'\n        primary key,\n    analyze_response_enable tinyint       default 1                 not null comment '响应结果解析开关 默认是0：关闭，1：开启',\n    is_source_separated     tinyint       default 0                 not null comment '是否是索引存储分离的 0 不是 1 是',\n    aggr_analyze_enable     tinyint       default 1                 not null comment '1 生效 0 不生效',\n    dsl_analyze_enable      tinyint(2)    default 1                 not null comment '1为生效dsl分析查询限流值，0不生效dsl分析查询限流值',\n    slow_query_times        int(10)       default 100               not null comment '慢查询耗时',\n    is_active               tinyint(2)    default 1                 not null comment '1为可用，0不可用',\n    memo                    varchar(1000) default ''                not null comment '备注',\n    create_time             timestamp     default CURRENT_TIMESTAMP not null comment '创建时间',\n    update_time             timestamp     default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '修改时间'\n)\n    comment '项目配置' charset = utf8;\n\ninsert into project_arius_config (project_id, analyze_response_enable, is_source_separated,\n                                  aggr_analyze_enable, dsl_analyze_enable, slow_query_times, is_active,\n                                  memo, create_time, update_time)\nvalues (1, 1, 0, 1, 1, 8, 1, '超级应1用11', '2022-06-14 18:52:08.0', '2022-07-08 18:19:51.0'),\n       (2, 1, 0, 1, 1, 8, 1, '超级应1用11', '2022-06-14 18:52:08.0', '2022-07-08 18:19:51.0');"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_arius/arius.cat.index_info",
    "content": "{\n  \"level\":1,\n  \"expression\": \"arius.cat.index_info*\",\n  \"dateFormat\": \"_yyyy-MM-dd\",\n  \"dataCenter\": \"cn\",\n  \"dataType\": 0,\n  \"dateField\": \"timestamp\",\n  \"expireTime\": \"3\",\n  \"physicalInfos\": [\n    {\n      \"cluster\": \"logi-elasticsearch-7.6.0\",\n      \"resourceId\": 63,\n      \"role\": 1,\n      \"shard\": \"4\"\n    }\n  ],\n  \"quota\": 30,\n  \"appId\": 1,\n  \"responsible\": \"admin\",\n  \"name\": \"arius.cat.index_info\",\n  \"desc\": \"索引列表\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_arius/arius.dsl.metrics",
    "content": "{\n  \"level\":1,\n  \"expression\": \"arius.dsl.metrics*\",\n  \"dateFormat\": \"_yyyy-MM-dd\",\n  \"dataCenter\": \"cn\",\n  \"dataType\": 0,\n  \"dateField\": \"timeStamp\",\n  \"expireTime\": \"150\",\n  \"physicalInfos\": [\n    {\n      \"cluster\": \"logi-elasticsearch-7.6.0\",\n      \"resourceId\": 63,\n      \"role\": 1,\n      \"shard\": \"4\"\n    }\n  ],\n  \"quota\": 30,\n  \"appId\": 1,\n  \"responsible\": \"admin\",\n  \"name\": \"arius.dsl.metrics\",\n  \"desc\": \"用户查询聚合信息\"\n}\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_arius/arius.dsl.template",
    "content": "{\n  \"level\":1,\n  \"expression\": \"arius.dsl.template\",\n  \"dateFormat\": \"\",\n  \"dataCenter\": \"cn\",\n  \"dataType\": 0,\n  \"dateField\": \"logTime\",\n  \"expireTime\": \"-1\",\n  \"physicalInfos\": [\n    {\n      \"cluster\": \"logi-elasticsearch-7.6.0\",\n      \"resourceId\": 63,\n      \"role\": 1,\n      \"shard\": \"4\"\n    }\n  ],\n  \"quota\": 30,\n  \"appId\": 1,\n  \"responsible\": \"admin\",\n  \"name\": \"arius.dsl.template\",\n  \"desc\": \"DSL审核与分析\"\n}\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_arius/arius.gateway.join",
    "content": "{\n  \"level\":1,\n  \"expression\": \"arius.gateway.join*\",\n  \"dateFormat\": \"_yyyy-MM-dd\",\n  \"dataCenter\": \"cn\",\n  \"dataType\": 0,\n  \"dateField\": \"timeStamp\",\n  \"expireTime\": \"23\",\n  \"physicalInfos\": [\n    {\n      \"cluster\": \"logi-elasticsearch-7.6.0\",\n      \"resourceId\": 63,\n      \"role\": 1,\n      \"shard\": \"4\"\n    }\n  ],\n  \"quota\": 30,\n  \"appId\": 1,\n  \"responsible\": \"admin\",\n  \"name\": \"arius.gateway.join\",\n  \"desc\": \"gateway日志按照requestId进行join\"\n}\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_arius/arius.stats.cluster_info",
    "content": "{\n  \"level\":1,\n  \"expression\": \"arius.stats.cluster_info*\",\n  \"dateFormat\": \"_yyyy-MM-dd\",\n  \"dataCenter\": \"cn\",\n  \"dataType\": 0,\n  \"dateField\": \"timestamp\",\n  \"expireTime\": \"180\",\n  \"physicalInfos\": [\n    {\n      \"cluster\": \"logi-elasticsearch-7.6.0\",\n      \"resourceId\": 63,\n      \"role\": 1,\n      \"shard\": \"4\"\n    }\n  ],\n  \"quota\": 30,\n  \"appId\": 1,\n  \"responsible\": \"admin\",\n  \"name\": \"arius.stats.cluster_info\",\n  \"desc\": \"\"\n}\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_arius/arius.stats.cluster_task_info",
    "content": "{\n  \"level\":1,\n  \"expression\": \"arius.stats.cluster_task_info*\",\n  \"dateFormat\": \"_yyyy-MM-dd\",\n  \"dataCenter\": \"cn\",\n  \"dataType\": 0,\n  \"dateField\": \"timestamp\",\n  \"expireTime\": \"15\",\n  \"physicalInfos\": [\n    {\n      \"cluster\": \"logi-elasticsearch-7.6.0\",\n      \"resourceId\": 63,\n      \"role\": 1,\n      \"shard\": \"4\"\n    }\n  ],\n  \"quota\": 30,\n  \"appId\": 1,\n  \"responsible\": \"admin\",\n  \"name\": \"arius.stats.cluster_task_info\",\n  \"desc\": \"\"\n}\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_arius/arius.stats.dashboard_info",
    "content": "{\n  \"level\":1,\n  \"expression\": \"arius.stats.dashboard_info*\",\n  \"dateFormat\": \"_yyyy-MM-dd\",\n  \"dataCenter\": \"cn\",\n  \"dataType\": 0,\n  \"dateField\": \"timestamp\",\n  \"expireTime\": \"7\",\n  \"physicalInfos\": [\n    {\n      \"cluster\": \"logi-elasticsearch-7.6.0\",\n      \"resourceId\": 63,\n      \"role\": 1,\n      \"shard\": \"4\"\n    }\n  ],\n  \"quota\": 0.02,\n  \"appId\": 1,\n  \"responsible\": \"admin\",\n  \"name\": \"arius.stats.dashboard_info\",\n  \"desc\": \"\"\n}\n\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_arius/arius.stats.index_info",
    "content": "{\n  \"level\":1,\n  \"expression\": \"arius.stats.index_info*\",\n  \"dateFormat\": \"_yyyy-MM-dd\",\n  \"dataCenter\": \"cn\",\n  \"dataType\": 0,\n  \"dateField\": \"timestamp\",\n  \"expireTime\": \"180\",\n  \"physicalInfos\": [\n    {\n      \"cluster\": \"logi-elasticsearch-7.6.0\",\n      \"resourceId\": 63,\n      \"role\": 1,\n      \"shard\": \"4\"\n    }\n  ],\n  \"quota\": 30,\n  \"appId\": 1,\n  \"responsible\": \"admin\",\n  \"name\": \"arius.stats.index_info\",\n  \"desc\": \"\"\n}\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_arius/arius.stats.node_info",
    "content": "{\n  \"level\":1,\n  \"expression\": \"arius.stats.node_info*\",\n  \"dateFormat\": \"_yyyy-MM-dd\",\n  \"dataCenter\": \"cn\",\n  \"dataType\": 0,\n  \"dateField\": \"timestamp\",\n  \"expireTime\": \"180\",\n  \"physicalInfos\": [\n    {\n      \"cluster\": \"logi-elasticsearch-7.6.0\",\n      \"resourceId\": 63,\n      \"role\": 1,\n      \"shard\": \"4\"\n    }\n  ],\n  \"quota\": 30,\n  \"appId\": 1,\n  \"responsible\": \"admin\",\n  \"name\": \"arius.stats.node_info\",\n  \"desc\": \"\"\n}\n"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_arius/index_observability",
    "content": "{\n  \"level\":1,\n  \"expression\": \"index_observability\",\n  \"dateFormat\": \"\",\n  \"dataCenter\": \"cn\",\n  \"dataType\": 0,\n  \"dateField\": \"\",\n  \"expireTime\": \"-1\",\n  \"physicalInfos\": [\n    {\n      \"cluster\": \"logi-elasticsearch-7.6.0\",\n      \"resourceId\": 63,\n      \"role\": 1,\n      \"shard\": \"4\"\n    }\n  ],\n  \"quota\": 30,\n  \"appId\": 1,\n  \"responsible\": \"admin\",\n  \"name\": \"index_observability\",\n  \"desc\": \"日志数据上报索引\"\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/arius.cat.index_info",
    "content": "{\n  \"order\": 10,\n  \"index_patterns\": [\n    \"arius_cat_index_info*\"\n  ],\n  \"settings\": {\n    \"index\": {\n      \"routing\": {\n        \"allocation\": {\n          \"include\": {\n            \"_name\": \"logi03-datanode03,logi01-datanode01,logi02-datanode02\"\n          }\n        }\n      },\n      \"mapping\": {\n        \"single_type\": \"true\"\n      },\n      \"number_of_shards\": \"1\",\n      \"number_of_routing_size\": \"1\"\n    }\n  },\n  \"mappings\": {\n    \"properties\": {\n      \"cluster\": {\n        \"type\": \"keyword\"\n      },\n      \"clusterLogic\": {\n        \"type\": \"keyword\"\n      },\n      \"resourceId\": {\n        \"type\": \"long\"\n      },\n      \"projectId\": {\n        \"type\": \"integer\"\n      },\n      \"health\": {\n        \"type\": \"keyword\"\n      },\n      \"status\": {\n        \"type\": \"keyword\"\n      },\n      \"index\": {\n        \"type\": \"keyword\"\n      },\n      \"pri\": {\n        \"type\": \"long\"\n      },\n      \"rep\": {\n        \"type\": \"long\"\n      },\n      \"docsCount\": {\n        \"type\": \"long\"\n      },\n      \"docsDeleted\": {\n        \"type\": \"long\"\n      },\n      \"priStoreSize\": {\n        \"type\": \"keyword\"\n      },\n      \"storeSize\": {\n        \"type\": \"keyword\"\n      },\n      \"key\": {\n        \"ignore_above\": 1024,\n        \"type\": \"keyword\"\n      },\n      \"deleteFlag\": {\n        \"type\": \"boolean\"\n      },\n      \"platformCreateFlag\": {\n        \"type\": \"boolean\"\n      },\n      \"timestamp\": {\n        \"format\": \"epoch_millis\",\n        \"type\": \"date\"\n      },\n      \"totalSegmentCount\": {\n        \"type\": \"long\"\n      },\n      \"primariesSegmentCount\": {\n        \"type\": \"long\"\n      },\n      \"templateId\": {\n        \"type\": \"integer\"\n      }\n    }\n  },\n  \"aliases\": {}\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/arius.cat.shard_info",
    "content": "{\n    \"order\":10,\n    \"index_patterns\":[\n        \"arius.cat.shard_info*\"\n    ],\n    \"settings\":{\n        \"index\":{\n            \"mapping\":{\n                \"single_type\":\"true\"\n            },\n            \"number_of_shards\":\"4\",\n            \"number_of_routing_size\":\"1\",\n            \"refresh_interval\": \"1s\"\n        }\n    },\n    \"mappings\":{\n        \"_source\":{\n            \"enabled\":true\n        },\n        \"properties\":{\n            \"prirep\": {\n                \"type\": \"keyword\"\n            },\n            \"clusterPhy\": {\n                \"type\": \"keyword\"\n            },\n            \"node\": {\n                \"type\": \"keyword\"\n            },\n            \"docs\": {\n                \"type\": \"long\"\n            },\n            \"ip\": {\n                \"type\": \"keyword\"\n            },\n            \"index\": {\n                \"type\": \"keyword\"\n            },\n            \"shard\": {\n                \"type\": \"long\"\n            },\n            \"state\": {\n                \"type\": \"keyword\"\n            },\n            \"store\": {\n                \"type\":\"long\"\n            },\n            \"timestamp\":{\n                \"format\":\"epoch_millis\",\n                \"type\":\"date\"\n            }\n        }\n    },\n    \"aliases\":{\n\n    }\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/arius.dsl.metrics",
    "content": "{\n    \"order\":10,\n    \"index_patterns\":[\n        \"arius.dsl.metrics*\"\n    ],\n    \"settings\":{\n        \"index\":{\n            \"mapping\":{\n                \"single_type\":\"true\"\n            },\n            \"number_of_shards\":\"4\",\n            \"number_of_replicas\":\"1\",\n            \"refresh_interval\": \"1s\"\n        }\n    },\n    \"mappings\":{\n        \"properties\":{\n            \"ariusCreateTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"searchCount\":{\n                \"type\":\"long\"\n            },\n            \"dslLevel\":{\n                \"type\":\"keyword\"\n            },\n            \"successfulShardsAvg\":{\n                \"type\":\"double\"\n            },\n            \"totalShardsAvg\":{\n                \"type\":\"double\"\n            },\n            \"dslTemplate\":{\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"dslType\":{\n                \"type\":\"keyword\"\n            },\n            \"appidDslTemplateMd5\":{\n                \"type\":\"keyword\"\n            },\n            \"projectIdDslTemplateMd5\":{\n                \"type\":\"keyword\"\n            },\n            \"sinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"responseLenAvg\":{\n                \"type\":\"double\"\n            },\n            \"requestType\":{\n                \"type\":\"keyword\"\n            },\n            \"searchType\":{\n                \"type\":\"keyword\"\n            },\n            \"esCostAvg\":{\n                \"type\":\"double\"\n            },\n            \"gatewayNode\":{\n                \"type\":\"text\",\n                \"fields\":{\n                    \"keyword\":{\n                        \"ignore_above\":256,\n                        \"type\":\"keyword\"\n                    }\n                }\n            },\n            \"dslLenAvg\":{\n                \"type\":\"double\"\n            },\n            \"totalHitsAvg\":{\n                \"type\":\"double\"\n            },\n            \"_FLINK_DATA_TIME\":{\n                \"type\":\"long\"\n            },\n            \"version\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"indiceSample\":{\n                \"type\":\"keyword\"\n            },\n            \"logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"timeStamp\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"indices\":{\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"dslTemplateMd5\":{\n                \"type\":\"keyword\"\n            },\n            \"isFromUserConsole\":{\n                \"type\":\"boolean\"\n            },\n            \"totalCostAvg\":{\n                \"type\":\"double\"\n            },\n            \"failedShardsAvg\":{\n                \"type\":\"double\"\n            },\n            \"dslTag\":{\n                \"type\":\"keyword\"\n            },\n            \"appid\":{\n                \"type\":\"long\"\n            },\n            \"projectId\":{\n                \"type\":\"long\"\n            },\n            \"dsl\":{\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"beforeCostAvg\":{\n                \"type\":\"double\"\n            },\n            \"flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            }\n        }\n    },\n    \"aliases\":{\n\n    }\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/arius.dsl.template",
    "content": "{\n    \"order\":10,\n    \"index_patterns\":[\n        \"arius.dsl.template\"\n    ],\n    \"settings\":{\n        \"index\":{\n            \"number_of_shards\":\"4\",\n            \"mapping\":{\n                \"single_type\":\"true\"\n            },\n            \"number_of_replicas\":\"1\",\n            \"refresh_interval\": \"1s\"\n        }\n    },\n    \"mappings\":{\n        \"properties\":{\n            \"ariusCreateTime\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"fromUserConsole\":{\n                \"type\":\"boolean\"\n            },\n            \"searchCount\":{\n                \"type\":\"long\"\n            },\n            \"dslLevel\":{\n                \"type\":\"keyword\"\n            },\n            \"my_all_fields\":{\n                \"ignore_above\":2048,\n                \"type\":\"keyword\"\n            },\n            \"successfulShardsAvg\":{\n                \"type\":\"double\"\n            },\n            \"totalShardsAvg\":{\n                \"type\":\"double\"\n            },\n            \"dslTemplate\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"ignore_above\":32766,\n                \"type\":\"keyword\"\n            },\n            \"dslType\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"type\":\"keyword\"\n            },\n            \"appidDslTemplateMd5\":{\n                \"type\":\"keyword\"\n            },\n            \"projectIdDslTemplateMd5\":{\n                \"type\":\"keyword\"\n            },\n            \"enable\":{\n                \"type\":\"boolean\"\n            },\n            \"sinkTime\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"day\":{\n                \"type\":\"date\"\n            },\n            \"responseLenAvg\":{\n                \"type\":\"double\"\n            },\n            \"requestType\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"type\":\"keyword\"\n            },\n            \"searchType\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"type\":\"keyword\"\n            },\n            \"ariusModifyTime\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"slowDslThreshold\":{\n                \"type\":\"long\"\n            },\n            \"esCostAvg\":{\n                \"type\":\"double\"\n            },\n            \"dslLenAvg\":{\n                \"type\":\"double\"\n            },\n            \"gatewayNode\":{\n                \"type\":\"text\",\n                \"fields\":{\n                    \"keyword\":{\n                        \"ignore_above\":256,\n                        \"type\":\"keyword\"\n                    }\n                }\n            },\n            \"totalHitsAvg\":{\n                \"type\":\"double\"\n            },\n            \"_FLINK_DATA_TIME\":{\n                \"type\":\"long\"\n            },\n            \"version\":{\n                \"type\":\"keyword\"\n            },\n            \"forceSetQueryLimit\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"type\":\"boolean\"\n            },\n            \"indiceSample\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"type\":\"keyword\"\n            },\n            \"logTime\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"timeStamp\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"indices\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"ignore_above\":32766,\n                \"type\":\"keyword\"\n            },\n            \"dslTemplateMd5\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"type\":\"keyword\"\n            },\n            \"isFromUserConsole\":{\n                \"type\":\"boolean\"\n            },\n            \"totalCostAvg\":{\n                \"type\":\"double\"\n            },\n            \"checkMode\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"type\":\"keyword\"\n            },\n            \"failedShardsAvg\":{\n                \"type\":\"double\"\n            },\n            \"dslTag\":{\n                \"type\":\"keyword\"\n            },\n            \"appid\":{\n                \"type\":\"long\"\n            },\n             \"projectId\":{\n                \"type\":\"long\"\n            },\n            \"queryLimit\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"type\":\"double\"\n            },\n            \"dsl\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"beforeCostAvg\":{\n                \"type\":\"double\"\n            },\n            \"flinkTime\":{\n                \"copy_to\":[\n                    \"my_all_fields\"\n                ],\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            }\n        }\n    },\n    \"aliases\":{\n\n    }\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/arius.gateway.join",
    "content": "{\n    \"order\":10,\n    \"index_patterns\":[\n        \"arius.gateway.join*\"\n    ],\n    \"settings\":{\n        \"index\":{\n            \"mapping\":{\n                \"single_type\":\"true\"\n            },\n            \"number_of_shards\":\"4\",\n            \"number_of_replicas\":\"1\",\n            \"refresh_interval\": \"30s\"\n        }\n    },\n    \"mappings\":{\n        \"properties\":{\n            \"String \":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_search_query_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"selectFields\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"stack\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_request_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"orderId\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"Long` from newton_strategy_2020-07-18_v2 WHERE bizType \":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"searchCost\":{\n                \"type\":\"long\"\n            },\n            \"String\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"responseLen\":{\n                \"type\":\"long\"\n            },\n            \"Count\":{\n                \"type\":\"long\"\n            },\n            \"beforeCost\":{\n                \"type\":\"long\"\n            },\n            \"isTimedOut\":{\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_tcp_exception_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"dslTemplate\":{\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"searchId\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"x-username\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"action\":{\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_replace_index_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"internalCost\":{\n                \"type\":\"long\"\n            },\n            \"exceptionName\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"tookInMillis\":{\n                \"type\":\"long\"\n            },\n            \"traceId\":{\n                \"type\":\"float\"\n            },\n            \"customKey\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_exception_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"method\":{\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_search_query_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"index\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"indexTypeName\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"whereFields\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"queryString\":{\n                \"type\":\"keyword\"\n            },\n            \"version\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_FLINK_DATA_TIME\":{\n                \"type\":\"long\"\n            },\n            \"_arius_query_tcp_response_length_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"dslLen\":{\n                \"type\":\"long\"\n            },\n            \"flowModuleId\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"totalHits\":{\n                \"type\":\"long\"\n            },\n            \"_arius_query_request_node_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"_arius_query_request_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"before_cost\":{\n                \"type\":\"long\"\n            },\n            \"statusCode\":{\n                \"type\":\"long\"\n            },\n            \"_arius_pre_exception_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"status\":{\n                \"type\":\"long\"\n            },\n            \"traceid\":{\n                \"type\":\"text\",\n                \"fields\":{\n                    \"keyword\":{\n                        \"ignore_above\":256,\n                        \"type\":\"keyword\"\n                    }\n                }\n            },\n            \"isUrgent\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"TimeUsed\":{\n                \"type\":\"long\"\n            },\n            \"pre_alloctication_group\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"sourceTemplateName\":{\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_tcp_search_request_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"groupByFields\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"typeName\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"failedShards\":{\n                \"type\":\"long\"\n            },\n            \"routing\":{\n                \"type\":\"keyword\"\n            },\n            \"instanceId\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_request_indices_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"client_node\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_replace_index_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"esCost\":{\n                \"type\":\"long\"\n            },\n            \"sinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"requestId\":{\n                \"type\":\"keyword\"\n            },\n            \"clusterName\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"sortByFields\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"Long` \":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_tcp_exception_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"timestamp\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"remoteAddr\":{\n                \"type\":\"keyword\"\n            },\n            \"collectTime\":{\n                \"type\":\"long\"\n            },\n            \"lastBucketNumber\":{\n                \"type\":\"long\"\n            },\n            \"dltagCount\":{\n                \"type\":\"long\"\n            },\n            \"Long \":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"successfulShards\":{\n                \"type\":\"long\"\n            },\n            \"String` \":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"gatewayNode\":{\n                \"type\":\"keyword\"\n            },\n            \"uri\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"destIndexName\":{\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"url\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"_arius_query_tcp_search_scroll_request_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"timeStamp\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"indices\":{\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"scrollIdList\":{\n                \"type\":\"keyword\"\n            },\n            \"@timestamp\":{\n                \"format\":\"strict_date_optional_time\",\n                \"type\":\"date\"\n            },\n            \"stage\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"postBody\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_tcp_search_response_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"clientIp\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"appid\":{\n                \"type\":\"long\"\n            },\n            \"_arius_pre_exception_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"postBodyLen\":{\n                \"type\":\"long\"\n            },\n            \"proc_time\":{\n                \"type\":\"long\"\n            },\n            \"logicId\":{\n                \"type\":\"long\"\n            },\n            \"Decimal \":{\n                \"type\":\"float\"\n            },\n            \"ariusCreateTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"totalHitsList\":{\n                \"type\":\"long\"\n            },\n            \"xUserName\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_response_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"clientVersion\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"operator\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"Name\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"fetchCost\":{\n                \"type\":\"long\"\n            },\n            \"_arius_query_tcp_response_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"successShardsList\":{\n                \"type\":\"long\"\n            },\n            \"costTime\":{\n                \"type\":\"long\"\n            },\n            \"paramCost\":{\n                \"type\":\"long\"\n            },\n            \"ariusType\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_request_indices_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"indiceCount\":{\n                \"type\":\"long\"\n            },\n            \"_arius_aggs_detail_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"_arius_query_search_response_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"group\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_tcp_search_response_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"orderByFields\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"res\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"timedOut\":{\n                \"type\":\"boolean\"\n            },\n            \"clientHost\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_fetch_message_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"totalShardsList\":{\n                \"type\":\"long\"\n            },\n            \"isTimeoutList\":{\n                \"type\":\"keyword\"\n            },\n            \"searchType\":{\n                \"type\":\"keyword\"\n            },\n            \"Targ\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_request_before_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"dltag\":{\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_request_before_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"_arius_query_request_node_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"_arius_query_response_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"_arius_query_tcp_request_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"success\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"dslTag\":{\n                \"type\":\"keyword\"\n            },\n            \"name\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"memUsed\":{\n                \"type\":\"long\"\n            },\n            \"bucketNumber\":{\n                \"type\":\"long\"\n            },\n            \"dsl\":{\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"totalCost\":{\n                \"type\":\"long\"\n            },\n            \"sourceIndexNames\":{\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"getClientCost\":{\n                \"type\":\"long\"\n            },\n            \"Errno\":{\n                \"type\":\"long\"\n            },\n            \"indexTemplateCost\":{\n                \"type\":\"long\"\n            },\n            \"clusterId\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"dslLevel\":{\n                \"type\":\"long\"\n            },\n            \"timeout\":{\n                \"type\":\"long\"\n            },\n            \"failedShardsList\":{\n                \"type\":\"long\"\n            },\n            \"totalShards\":{\n                \"type\":\"long\"\n            },\n            \"scrollId\":{\n                \"type\":\"keyword\"\n            },\n            \"sql\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"destTemplateName\":{\n                \"ignore_above\":1024,\n                \"type\":\"keyword\"\n            },\n            \"_arius_aggs_detail_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"dslType\":{\n                \"type\":\"keyword\"\n            },\n            \"preProcessCost\":{\n                \"type\":\"long\"\n            },\n            \"_arius_query_tcp_response_length_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"newDslTemplate\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"param\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_search_internal_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"aggsLevel\":{\n                \"type\":\"long\"\n            },\n            \"json\":{\n                \"type\":\"object\"\n            },\n            \"_arius_query_tcp_request_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"clientNode\":{\n                \"type\":\"keyword\"\n            },\n            \"rcvTimeout\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_tcp_search_scroll_request_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"types\":{\n                \"type\":\"keyword\"\n            },\n            \"projectId\":{\n                \"type\":\"long\"\n            },\n            \"cost\":{\n                \"type\":\"long\"\n            },\n            \"_arius_exception_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"requestType\":{\n                \"type\":\"keyword\"\n            },\n            \"fetchSize\":{\n                \"type\":\"long\"\n            },\n            \"esCostList\":{\n                \"type\":\"long\"\n            },\n            \"aggsBukcetInfo\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"fetchMetric\":{\n                \"properties\":{\n                    \"parseMessageCost\":{\n                        \"type\":\"long\"\n                    },\n                    \"fetchMissingCnt\":{\n                        \"type\":\"long\"\n                    },\n                    \"getConsumeCost\":{\n                        \"type\":\"long\"\n                    },\n                    \"fetchOffsetCnt\":{\n                        \"type\":\"long\"\n                    },\n                    \"brokerHost\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"fetchMetricInfo\":{\n                        \"properties\":{\n                            \"cost\":{\n                                \"type\":\"long\"\n                            },\n                            \"partition\":{\n                                \"type\":\"long\"\n                            },\n                            \"count\":{\n                                \"type\":\"long\"\n                            },\n                            \"topic\":{\n                                \"ignore_above\":512,\n                                \"type\":\"keyword\"\n                            }\n                        }\n                    },\n                    \"partitionTotalCost\":{\n                        \"type\":\"long\"\n                    }\n                }\n            },\n            \"_arius_response_index_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"message\":{\n                \"ignore_above\":2048,\n                \"index\":false,\n                \"type\":\"keyword\"\n            },\n            \"userName\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_msg\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_tcp_search_request_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"_arius_fetch_message_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"indiceSample\":{\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_search_internal_flinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"isFromUserConsole\":{\n                \"type\":\"boolean\"\n            },\n            \"dslTemplateMd5\":{\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_tcp_response_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"service\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"user\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"_arius_query_search_response_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"_arius_response_index_logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss Z||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"queryRequest\":{\n                \"type\":\"boolean\"\n            }\n        }\n    },\n    \"aliases\":{\n\n    }\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/arius.stats.cluster_info",
    "content": "{\n    \"order\":10,\n    \"index_patterns\":[\n        \"arius.stats.cluster_info*\"\n    ],\n    \"settings\":{\n        \"index\":{\n            \"mapping\":{\n                \"single_type\":\"true\"\n            },\n            \"number_of_shards\":\"4\",\n            \"number_of_replicas\":\"1\",\n            \"refresh_interval\": \"10s\"\n        }\n    },\n    \"mappings\":{\n        \"properties\":{\n            \"cluster\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"collectTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"physicCluster\":{\n                \"type\":\"long\"\n            },\n            \"dataCenter\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"routingValue\":{\n                \"type\":\"text\",\n                \"fields\":{\n                    \"keyword\":{\n                        \"ignore_above\":256,\n                        \"type\":\"keyword\"\n                    }\n                }\n            },\n            \"es_index_time\":{\n                \"type\":\"long\"\n            },\n            \"logTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"cleanTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"statis\":{\n                \"properties\":{\n                    \"cpuUsage\":{\n                        \"type\":\"double\"\n                    },\n                    \"statusType\":{\n                        \"type\":\"long\"\n                    },\n                    \"numberPendingTasks\":{\n                        \"type\":\"long\"\n                    },\n                    \"searchLatency\":{\n                        \"type\":\"double\"\n                    },\n                    \"totalTemplateNu\":{\n                        \"type\":\"double\"\n                    },\n                    \"activeNodeNu\":{\n                        \"type\":\"long\"\n                    },\n                    \"invalidNodeNu\":{\n                        \"type\":\"long\"\n                    },\n                    \"clusterNu\":{\n                        \"type\":\"double\"\n                    },\n                    \"esNodeNu\":{\n                        \"type\":\"double\"\n                    },\n                    \"totalIndicesNu\":{\n                        \"type\":\"double\"\n                    },\n                    \"totalStoreSize\":{\n                        \"type\":\"double\"\n                    },\n                    \"level\":{\n                        \"type\":\"long\"\n                    },\n                    \"sla\":{\n                        \"type\":\"double\"\n                    },\n                    \"sendTransSize\":{\n                        \"type\":\"double\"\n                    },\n                    \"taskCount\":{\n                        \"type\":\"long\"\n                    },\n                    \"cpuLoad15M\":{\n                        \"type\":\"double\"\n                    },\n                    \"alivePercent\":{\n                        \"type\":\"long\"\n                    },\n                    \"shardNu\":{\n                        \"type\":\"double\"\n                    },\n                    \"freeStoreSize\":{\n                        \"type\":\"double\"\n                    },\n                    \"memUsed\":{\n                        \"type\":\"long\"\n                    },\n                    \"memFreePercent\":{\n                        \"type\":\"float\"\n                    },\n                    \"status\":{\n                        \"type\":\"text\",\n                        \"fields\":{\n                            \"keyword\":{\n                                \"ignore_above\":256,\n                                \"type\":\"keyword\"\n                            }\n                        }\n                    },\n                    \"unAssignedShards\":{\n                        \"type\":\"long\"\n                    },\n                    \"appNu\":{\n                        \"type\":\"double\"\n                    },\n                    \"cpuLoad1M\":{\n                        \"type\":\"double\"\n                    },\n                    \"cpuLoad5M\":{\n                        \"type\":\"double\"\n                    },\n                    \"indexStoreSize\":{\n                        \"type\":\"double\"\n                    },\n                    \"nodeNamesForDiskUsageGte75Percent\":{\n                        \"type\":\"text\",\n                        \"fields\":{\n                            \"keyword\":{\n                                \"ignore_above\":256,\n                                \"type\":\"keyword\"\n                            }\n                        }\n                    },\n                    \"totalDocNu\":{\n                        \"type\":\"double\"\n                    },\n                    \"extendInfoMap\":{\n                        \"type\":\"object\"\n                    },\n                    \"memUsedPercent\":{\n                        \"type\":\"float\"\n                    },\n                    \"clusterName\":{\n                        \"ignore_above\":512,\n                        \"type\":\"keyword\"\n                    },\n                    \"storeSize\":{\n                        \"type\":\"double\"\n                    },\n                    \"indexingLatency\":{\n                        \"type\":\"double\"\n                    },\n                    \"nodeIpsForDiskUsageGte75Percent\":{\n                        \"type\":\"text\",\n                        \"fields\":{\n                            \"keyword\":{\n                                \"ignore_above\":256,\n                                \"type\":\"keyword\"\n                            }\n                        }\n                    },\n                    \"key\":{\n                        \"ignore_above\":512,\n                        \"type\":\"keyword\"\n                    },\n                    \"numberNodes\":{\n                        \"type\":\"long\"\n                    },\n                    \"recvTransSize\":{\n                        \"type\":\"double\"\n                    },\n                    \"memFree\":{\n                        \"type\":\"long\"\n                    },\n                    \"readTps\":{\n                        \"type\":\"double\"\n                    },\n                    \"memTotal\":{\n                        \"type\":\"long\"\n                    },\n                    \"numberDataNodes\":{\n                        \"type\":\"long\"\n                    },\n                    \"writeTps\":{\n                        \"type\":\"double\"\n                    },\n                    \"numberIngestNodes\":{\n                        \"type\":\"long\"\n                    },\n                    \"numberMasterNodes\":{\n                        \"type\":\"long\"\n                    },\n                    \"queryTimesPreDay\":{\n                        \"type\":\"double\"\n                    },\n                    \"taskCost\":{\n                        \"type\":\"double\"\n                    },\n                    \"numberClientNodes\":{\n                        \"type\":\"long\"\n                    },\n                    \"diskUsage\":{\n                        \"type\":\"double\"\n                    }\n                }\n            },\n            \"sinkTime\":{\n                \"format\":\"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"percentilesType\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"key\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"timestamp\":{\n                \"format\":\"epoch_millis\",\n                \"type\":\"date\"\n            }\n        }\n    },\n    \"aliases\":{\n\n    }\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/arius.stats.cluster_task_info",
    "content": "{\n    \"order\":10,\n    \"index_patterns\":[\n        \"arius.stats.cluster_task_info*\"\n    ],\n    \"settings\":{\n        \"index\":{\n            \"mapping\":{\n                \"single_type\":\"true\"\n            },\n            \"number_of_shards\":\"4\",\n            \"number_of_replicas\":\"1\",\n            \"refresh_interval\": \"10s\"\n        }\n    },\n    \"mappings\":{\n        \"properties\":{\n            \"cluster\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"physicCluster\":{\n                \"type\":\"long\"\n            },\n            \"dataCenter\":{\n                \"type\":\"keyword\"\n            },\n            \"routingValue\":{\n                \"type\":\"text\",\n                \"fields\":{\n                    \"keyword\":{\n                        \"ignore_above\":256,\n                        \"type\":\"keyword\"\n                    }\n                }\n            },\n            \"metrics\":{\n                \"properties\":{\n                    \"node\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"parentTaskId\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"ip\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"action\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"runningTimeString\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"description\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"startTime\":{\n                        \"type\":\"long\"\n                    },\n                    \"runningTime\":{\n                        \"type\":\"long\"\n                    },\n                    \"type\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"taskId\":{\n                        \"type\":\"keyword\"\n                    }\n                }\n            },\n            \"key\":{\n                \"type\":\"text\",\n                \"fields\":{\n                    \"keyword\":{\n                        \"ignore_above\":256,\n                        \"type\":\"keyword\"\n                    }\n                }\n            },\n            \"timestamp\":{\n                \"format\":\"epoch_millis\",\n                \"type\":\"date\"\n            }\n        }\n    },\n    \"aliases\":{\n\n    }\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/arius.stats.dashboard.info",
    "content": "{\n    \"order\":10,\n    \"index_patterns\":[\n        \"arius.stats.dashboard_info*\"\n    ],\n    \"settings\":{\n        \"index\":{\n            \"mapping\":{\n                \"single_type\":\"true\"\n            },\n            \"number_of_shards\":\"4\",\n            \"number_of_replicas\":\"1\",\n            \"refresh_interval\": \"10s\"\n        }\n    },\n    \"mappings\":{\n        \"properties\":{\n            \"template\":{\n                \"properties\":{\n                    \"template\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"cluster\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"segmentMemSize\":{\n                        \"type\":\"double\"\n                    },\n                    \"templateName\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"segmentNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"templateId\":{\n                        \"type\":\"long\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    }\n                }\n            },\n            \"cluster\":{\n                \"properties\":{\n                    \"indexReqNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"cluster\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"shardNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"reqUprushNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"gatewaySucPer\":{\n                        \"type\":\"double\"\n                    },\n                    \"pendingTaskNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"searchLatency\":{\n                        \"type\":\"double\"\n                    },\n                    \"docUprushNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"gatewayFailedPer\":{\n                        \"type\":\"double\"\n                    },\n                    \"indexingLatency\":{\n                        \"type\":\"double\"\n                    },\n                    \"httpNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"clusterElapsedTime\":{\n                        \"type\":\"long\"\n                    },\n                    \"nodeElapsedTime\":{\n                         \"type\":\"long\"\n                    },\n                    \"collectorDelayed\":{\n                         \"type\":\"long\"\n                    },\n                    \"indexCount\":{\n                         \"type\":\"long\"\n                    },\n                    \"clusterElapsedTimeGte5Min\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    }\n                }\n            },\n            \"nodeMetrics\":{\n                \"properties\":{\n                    \"largeHead\":{\n                        \"type\":\"double\"\n                    },\n                    \"node\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"shardNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"taskConsuming\":{\n                        \"type\":\"long\"\n                    },\n                    \"largeDiskUsage\":{\n                        \"type\":\"double\"\n                    },\n                    \"largeCpuUsage\":{\n                        \"type\":\"double\"\n                    },\n                    \"writeRejectedNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"dead\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"SearchRejectedNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"nodeElapsedTime\":{\n                        \"type\":\"long\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    }\n                }\n            },\n            \"templateMetrics\":{\n                \"properties\":{\n                    \"template\":{\n                        \"type\":\"long\"\n                    },\n                    \"segmentMemSize\":{\n                        \"type\":\"double\"\n                    },\n                    \"segmentNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    }\n                }\n            },\n            \"physicCluster\":{\n                \"type\":\"integer\"\n            },\n            \"routingValue\":{\n                \"type\":\"keyword\"\n            },\n            \"nodeThreadPoolQueueMetrics\":{\n                \"properties\":{\n                    \"search\":{\n                        \"type\":\"long\"\n                    },\n                    \"flush\":{\n                        \"type\":\"long\"\n                    },\n                    \"management\":{\n                        \"type\":\"long\"\n                    },\n                    \"merge\":{\n                        \"type\":\"long\"\n                    },\n                    \"refresh\":{\n                        \"type\":\"long\"\n                    },\n                    \"write\":{\n                        \"type\":\"long\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    }\n                }\n            },\n            \"index\":{\n                \"properties\":{\n                    \"cluster\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"mappingNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"reqUprushNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"segmentNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"index\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"red\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"segmentMemSize\":{\n                        \"type\":\"float\"\n                    },\n                    \"smallShard\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"docUprushNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"bigShard\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"shardSize\":{\n                        \"type\":\"long\"\n                    },\n                    \"shardNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"singReplicate\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"memSize\":{\n                        \"type\":\"double\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    },\n                    \"unassignedShard\":{\n                        \"type\":\"boolean\"\n                    }\n                }\n            },\n            \"clusterPhyHealth\":{\n                \"properties\":{\n                    \"unknownClusterListStr\":{\n                        \"type\":\"text\"\n                    },\n                    \"unknownNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"redNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"totalNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"greenNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"yellowClusterListStr\":{\n                        \"type\":\"text\"\n                    },\n                    \"yellowNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"redClusterListStr\":{\n                        \"type\":\"text\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    }\n                }\n            },\n            \"clusterPhyHealthMetrics\":{\n                \"properties\":{\n                    \"unknownClusterListStr\":{\n                        \"type\":\"text\"\n                    },\n                    \"unknownNum\":{\n                        \"type\":\"integer\"\n                    },\n                    \"redNum\":{\n                        \"type\":\"integer\"\n                    },\n                    \"totalNum\":{\n                        \"type\":\"integer\"\n                    },\n                    \"greenNum\":{\n                        \"type\":\"integer\"\n                    },\n                    \"active\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"yellowClusterListStr\":{\n                        \"type\":\"text\"\n                    },\n                    \"yellowNum\":{\n                        \"type\":\"integer\"\n                    },\n                    \"redClusterListStr\":{\n                        \"type\":\"text\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    }\n                }\n            },\n            \"node\":{\n                \"properties\":{\n                    \"largeHead\":{\n                        \"type\":\"double\"\n                    },\n                    \"cluster\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"node\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"shardNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"taskConsuming\":{\n                        \"type\":\"long\"\n                    },\n                    \"largeDiskUsage\":{\n                        \"type\":\"double\"\n                    },\n                    \"searchRejectedNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"largeCpuUsage\":{\n                        \"type\":\"double\"\n                    },\n                    \"writeRejectedNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"dead\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"SearchRejectedNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    }\n                }\n            },\n            \"clusterThreadPoolQueue\":{\n                \"properties\":{\n                    \"cluster\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"search\":{\n                        \"type\":\"long\"\n                    },\n                    \"flush\":{\n                        \"type\":\"long\"\n                    },\n                    \"management\":{\n                        \"type\":\"long\"\n                    },\n                    \"merge\":{\n                        \"type\":\"long\"\n                    },\n                    \"refresh\":{\n                        \"type\":\"long\"\n                    },\n                    \"write\":{\n                        \"type\":\"long\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    }\n                }\n            },\n            \"key\":{\n                \"ignore_above\":512,\n                \"type\":\"keyword\"\n            },\n            \"indexMetrics\":{\n                \"properties\":{\n                    \"red\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"mappingNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"reqUprushNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"smallShard\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"docUprushNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"segmentNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"bigShard\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"index\":{\n                        \"type\":\"keyword\"\n                    },\n                    \"singReplicate\":{\n                        \"type\":\"boolean\"\n                    },\n                    \"memSize\":{\n                        \"type\":\"long\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    },\n                    \"unassignedShard\":{\n                        \"type\":\"boolean\"\n                    }\n                }\n            },\n            \"timestamp\":{\n                \"format\":\"epoch_millis\",\n                \"type\":\"date\"\n            },\n            \"clusterMetrics\":{\n                \"properties\":{\n                    \"indexReqNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"shardNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"reqUprushNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"gatewaySucPer\":{\n                        \"type\":\"double\"\n                    },\n                    \"pendingTaskNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"searchLatency\":{\n                        \"type\":\"double\"\n                    },\n                    \"docUprushNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"gatewayFailedPer\":{\n                        \"type\":\"double\"\n                    },\n                    \"indexingLatency\":{\n                        \"type\":\"double\"\n                    },\n                    \"httpNum\":{\n                        \"type\":\"long\"\n                    },\n                    \"timestamp\":{\n                        \"format\":\"epoch_millis\",\n                        \"type\":\"date\"\n                    }\n                }\n            }\n        }\n    },\n    \"aliases\":{\n\n    }\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/arius.stats.index_info",
    "content": "{\n    \"order\":10,\n    \"index_patterns\":[\n        \"arius.stats.index_info*\"\n    ],\n    \"settings\":{\n        \"index\":{\n            \"mapping\":{\n                \"single_type\":\"true\"\n            },\n            \"number_of_shards\":\"4\",\n            \"number_of_replicas\":\"1\",\n            \"refresh_interval\": \"10s\"\n        }\n    },\n    \"mappings\":{\n        \"_source\":{\n            \"enabled\":true\n        },\n\n    \"properties\": {\n        \"template\": {\n            \"type\": \"keyword\"\n        },\n        \"cluster\": {\n            \"type\": \"keyword\"\n        },\n        \"collectTime\": {\n            \"format\": \"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n            \"type\": \"date\"\n        },\n        \"routingValue\": {\n            \"type\": \"text\",\n            \"fields\": {\n                \"keyword\": {\n                    \"ignore_above\": 256,\n                    \"type\": \"keyword\"\n                }\n            }\n        },\n        \"index\": {\n            \"type\": \"keyword\"\n        },\n        \"templateId\": {\n            \"type\": \"long\"\n        },\n        \"logTime\": {\n            \"format\": \"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n            \"type\": \"date\"\n        },\n        \"cleanTime\": {\n            \"format\": \"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n            \"type\": \"date\"\n        },\n        \"shardNu\": {\n            \"type\": \"double\"\n        },\n        \"sinkTime\": {\n            \"format\": \"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n            \"type\": \"date\"\n        },\n        \"metrics\": {\n            \"properties\": {\n                \"refresh-total\": {\n                    \"type\": \"double\"\n                },\n                \"cost_scroll_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"indexing-index_time_in_millis_rate\": {\n                    \"type\": \"double\"\n                },\n                \"store-size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indexing-docs-count\": {\n                    \"type\": \"double\"\n                },\n                \"docs-count-total\": {\n                    \"type\": \"float\"\n                },\n                \"fielddata-memory_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"search-fetch_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"search-query_time_in_millis_rate\": {\n                    \"type\": \"double\"\n                },\n                \"cost-refresh-total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"merges-total\": {\n                    \"type\": \"double\"\n                },\n                \"segments-doc_values_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"segments_segments_request_cache_memory_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"search-query_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"search-scroll_total\": {\n                    \"type\": \"double\"\n                },\n                \"cost-query_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"indexing-index_time_per_doc\": {\n                    \"type\": \"double\"\n                },\n                \"cost_index_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"segments-index_writer_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"cost-merges-total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"indexing-index_total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"segments-request_cache-memory_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"cost-index_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"segments-memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"store-size_in_bytes_rate\": {\n                    \"type\": \"double\"\n                },\n                \"query_cache-memory_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"cost_refresh_total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"segments_fielddata_memory_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"cost-scroll_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"segments_fixed_bit_set_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"docs-count\": {\n                    \"type\": \"double\"\n                },\n                \"shardNu\": {\n                    \"type\": \"double\"\n                },\n                \"search-query_total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"cost-fetch_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"segments-version_map_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"refresh-total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"search-scroll_time_in_millis_rate\": {\n                    \"type\": \"double\"\n                },\n                \"merges-total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"segments_norms_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"cost_fetch_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"cost_query_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"flush-total\": {\n                    \"type\": \"double\"\n                },\n                \"cost_flush_total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"search-fetch_total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indexing-docs-count_diff\": {\n                    \"type\": \"double\"\n                },\n                \"refresh-total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"segments_version_map_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"segments-breakers-fieldd-limit_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"translog-size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"segments-count\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-query_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"flush-total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"indexing-index_total\": {\n                    \"type\": \"double\"\n                },\n                \"indexing-index_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"search-fetch_time_in_millis_rate\": {\n                    \"type\": \"double\"\n                },\n                \"flush-total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indexing-index_total_times\": {\n                    \"type\": \"double\"\n                },\n                \"indices-merge_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"merges-current\": {\n                    \"type\": \"double\"\n                },\n                \"search-scroll_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"segments-fixed_bit_set_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"segments-breakers-fielddata-limit_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"search-query_total\": {\n                    \"type\": \"double\"\n                },\n                \"indices-indexing-index_time_per_doc\": {\n                    \"type\": \"double\"\n                },\n                \"search-scroll_total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"segments-points_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"cost_merges_total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-fetch_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"segments-norms_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-indexing-index_latency\": {\n                    \"type\": \"float\"\n                },\n                \"segments-term_vectors_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"segments-stored_fields_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"store-size_in_bytes-total\": {\n                    \"type\": \"float\"\n                },\n                \"merges-total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"indices-refresh_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"indices-cost-merges-total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"indexing-index_failed_rate\": {\n                    \"type\": \"double\"\n                },\n                \"search-fetch_total\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-scroll_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"indices-flush_avg_time\": {\n                    \"type\": \"double\"\n                }\n            }\n        },\n        \"key\": {\n            \"ignore_above\": 512,\n            \"type\": \"keyword\"\n        },\n        \"logicTemplateId\": {\n            \"type\": \"long\"\n        },\n        \"timestamp\": {\n            \"format\": \"epoch_millis\",\n            \"type\": \"date\"\n        }\n    \n}\n    },\n    \"aliases\":{\n\n    }\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/arius.stats.node_info",
    "content": "{\n    \"order\":10,\n    \"index_patterns\":[\n        \"arius.stats.node_info*\"\n    ],\n    \"settings\":{\n        \"index\":{\n            \"mapping\":{\n                \"single_type\":\"true\"\n            },\n            \"number_of_shards\":\"4\",\n            \"number_of_replicas\":\"1\",\n            \"refresh_interval\": \"10s\"\n        }\n    },\n    \"mappings\":{\n        \"_source\":{\n            \"enabled\":true\n        },\n    \"properties\": {\n        \"cluster\": {\n            \"type\": \"keyword\"\n        },\n        \"collectTime\": {\n            \"format\": \"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n            \"type\": \"date\"\n        },\n        \"rack\": {\n            \"ignore_above\": 512,\n            \"type\": \"keyword\"\n        },\n        \"routingValue\": {\n            \"type\": \"text\",\n            \"fields\": {\n                \"keyword\": {\n                    \"ignore_above\": 256,\n                    \"type\": \"keyword\"\n                }\n            }\n        },\n        \"ip\": {\n            \"ignore_above\": 512,\n            \"type\": \"keyword\"\n        },\n        \"logTime\": {\n            \"format\": \"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n            \"type\": \"date\"\n        },\n        \"cleanTime\": {\n            \"format\": \"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n            \"type\": \"date\"\n        },\n        \"node\": {\n            \"type\": \"keyword\"\n        },\n        \"port\": {\n            \"type\": \"long\"\n        },\n        \"sinkTime\": {\n            \"format\": \"yyyy-MM-dd HH:mm:ss.SSS Z||yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss,SSS||yyyy/MM/dd HH:mm:ss||yyyy-MM-dd HH:mm:ss,SSS Z||yyyy/MM/dd HH:mm:ss,SSS Z||strict_date_optional_time||epoch_millis\",\n            \"type\": \"date\"\n        },\n        \"metrics\": {\n            \"properties\": {\n                \"thread_pool-force_merge-queue\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-fetch_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-mem-heap_used_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-bulk-queue\": {\n                    \"type\": \"double\"\n                },\n                \"indices-query_cache-miss_count\": {\n                    \"type\": \"double\"\n                },\n                \"indices-query_cache-hit_count\": {\n                    \"type\": \"double\"\n                },\n                \"os-cpu-load_average-5m\": {\n                    \"type\": \"double\"\n                },\n                \"process-cpu-percent\": {\n                    \"type\": \"double\"\n                },\n                \"indices-request_cache-memory_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-scroll_current\": {\n                    \"type\": \"double\"\n                },\n                \"indices-store-size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-count\": {\n                    \"type\": \"double\"\n                },\n                \"indices-merges-current\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-breakers-fielddata-limit_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-write-queue\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-scroll_total\": {\n                    \"type\": \"double\"\n                },\n                \"breakers-request-estimated_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"transport-server_open\": {\n                    \"type\": \"double\"\n                },\n                \"breakers-in_flight_requests-limit_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-translog-uncommitted_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-query_cache-hit_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indices-merges_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-index_writer_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-request_cache-total_count\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-term_vectors_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-refresh-queue\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-scroll_total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indices-merges-total\": {\n                    \"type\": \"double\"\n                },\n                \"indices-indexing-index_time_in_millis_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-query_total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"transport-tx_size_in_bytes_rate\": {\n                    \"type\": \"double\"\n                },\n                \"script-compilations\": {\n                    \"type\": \"double\"\n                },\n                \"fs-total-total_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"os-cpu-load_average-15m\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-search-completed\": {\n                    \"type\": \"double\"\n                },\n                \"http-current_open\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-gc-young-collection_count_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indices-index_latency\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-mem-pools-old-used_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"fs-total-disk_free_percent\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-fetch_total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-bulk-rejected\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-bulk-completed\": {\n                    \"type\": \"double\"\n                },\n                \"indices-query_latency\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-search-rejected\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-query_time_per_query\": {\n                    \"type\": \"double\"\n                },\n                \"indices-docs-count\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-gc-old-collection_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"indices-refresh_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"os-cpu_percent\": {\n                    \"type\": \"double\"\n                },\n                \"indices-request_cache-miss_count\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-fetch_total\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-scroll_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-mem-pools-young-used_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-flush_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"os-cpu-percent\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-mem-heap_used_percent\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-norms_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-query_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"indices-query_cache-cache_size\": {\n                    \"type\": \"double\"\n                },\n                \"transport-rx_size_in_bytes_rate\": {\n                    \"type\": \"double\"\n                },\n                \"os-cpu-load_average-1m\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-stored_fields_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"breakers-parent-limit_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-gc-old-collection_count\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-fetch_time_per_fetch\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-mem-non_heap_used_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-query_cache-evictions\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-rollup_indexing-queue\": {\n                    \"type\": \"double\"\n                },\n                \"indices-request_cache-evictions\": {\n                    \"type\": \"double\"\n                },\n                \"indices-translog-operations_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indices-indexing-index_total\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-query_time_in_millis_rate\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-threads-count\": {\n                    \"type\": \"double\"\n                },\n                \"breakers-accounting-limit_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"transport-rx_count_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indices-indexing-index_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-gc-young-collection_avg_time\": {\n                    \"type\": \"double\"\n                },\n                \"transport-tx_count_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indices-refresh-total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"indices-flush-total\": {\n                    \"type\": \"double\"\n                },\n                \"breakers-fielddata-limit_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-merges-total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"breakers-request-limit_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"breakers-parent-estimated_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-indexing-delete_total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indices-docs-count_diff\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-fixed_bit_set_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-scroll_time_in_millis_rate\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-management-queue\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-gc-old-collection_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-doc_values_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-indexing-index_total_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-query_total\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-points_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-query_cache-memory_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"ingest-total-failed\": {\n                    \"type\": \"float\"\n                },\n                \"indices-search-scroll_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-write-rejected\": {\n                    \"type\": \"double\"\n                },\n                \"process-process-open_file_descriptors\": {\n                    \"type\": \"double\"\n                },\n                \"breakers-accounting-estimated_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"breakers-in_flight_requests-estimated_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-query_cache-total_count\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-gc-young-collection_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"fs-total-available_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"fs-total-free_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-indexing-index_time_per_doc\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-gc-young-collection_count\": {\n                    \"type\": \"double\"\n                },\n                \"indices-refresh-total\": {\n                    \"type\": \"double\"\n                },\n                \"breakers-fielddata-estimated_size_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-flush-total_time_in_millis\": {\n                    \"type\": \"double\"\n                },\n                \"thread_pool-write-completed\": {\n                    \"type\": \"double\"\n                },\n                \"ingest-total-current\": {\n                    \"type\": \"float\"\n                },\n                \"ingest-total-count\": {\n                    \"type\": \"float\"\n                },\n                \"ingest-total-time_in_millis\": {\n                    \"type\": \"float\"\n                },\n                \"thread_pool-search-queue\": {\n                    \"type\": \"double\"\n                },\n                \"indices-request_cache-hit_rate\": {\n                    \"type\": \"double\"\n                },\n                \"indices-request_cache-hit_count\": {\n                    \"type\": \"double\"\n                },\n                \"indices-segments-version_map_memory_in_bytes\": {\n                    \"type\": \"double\"\n                },\n                \"indices-search-fetch_time_in_millis_rate\": {\n                    \"type\": \"double\"\n                },\n                \"jvm-gc-old-collection_count_rate\": {\n                    \"type\": \"double\"\n                }\n            }\n        },\n        \"key\": {\n            \"ignore_above\": 512,\n            \"type\": \"keyword\"\n        },\n        \"timestamp\": {\n            \"format\": \"epoch_millis\",\n            \"type\": \"date\"\n        }\n    }\n\n    },\n    \"aliases\":{\n\n    }\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-init/template_in_cluster/index_observability",
    "content": "{\n  \"order\": 10,\n  \"index_patterns\": [\n    \"index_observability\"\n  ],\n  \"settings\": {\n    \"index\": {\n      \"refresh_interval\": \"1s\",\n      \"number_of_shards\": \"5\",\n      \"translog\": {\n        \"sync_interval\": \"15s\",\n        \"durability\": \"async\"\n      }\n    }\n  },\n  \"mappings\": {\n    \"properties\": {\n      \"logType\": {\n        \"type\": \"keyword\"\n      },\n      \"hostName\": {\n        \"type\": \"keyword\"\n      },\n      \"fileName\": {\n        \"type\": \"keyword\"\n      },\n      \"metricName\": {\n        \"type\": \"keyword\"\n      },\n      \"httpTarget\": {\n        \"type\": \"keyword\"\n      },\n      \"endEpochNanos\": {\n        \"type\": \"long\"\n      },\n      \"logThread\": {\n        \"type\": \"keyword\"\n      },\n      \"diskPath\": {\n        \"type\": \"keyword\"\n      },\n      \"metricValue\": {\n        \"type\": \"double\"\n      },\n      \"className\": {\n        \"type\": \"keyword\"\n      },\n      \"httpMethod\": {\n        \"type\": \"keyword\"\n      },\n      \"deviceName\": {\n        \"type\": \"keyword\"\n      },\n      \"metricUnit\": {\n        \"type\": \"keyword\"\n      },\n      \"spanId\": {\n        \"type\": \"keyword\"\n      },\n      \"metricType\": {\n        \"type\": \"keyword\"\n      },\n      \"logLevel\": {\n        \"type\": \"keyword\"\n      },\n      \"httpUrl\": {\n        \"type\": \"keyword\"\n      },\n      \"instrumentationScopeInfoName\": {\n        \"type\": \"keyword\"\n      },\n      \"tracerName\": {\n        \"type\": \"keyword\"\n      },\n      \"httpHost\": {\n        \"type\": \"keyword\"\n      },\n      \"applicationName\": {\n        \"type\": \"keyword\"\n      },\n      \"traceId\": {\n        \"type\": \"keyword\"\n      },\n      \"sqlStatement\": {\n        \"type\": \"keyword\"\n      },\n      \"spanKind\": {\n        \"type\": \"keyword\"\n      },\n      \"ip\": {\n        \"type\": \"keyword\"\n      },\n      \"methodName\": {\n        \"type\": \"keyword\"\n      },\n      \"exemplarData\": {\n        \"type\": \"keyword\"\n      },\n      \"message\": {\n        \"copy_to\": [\n          \"message_full_name\"\n        ],\n        \"type\": \"text\"\n      },\n      \"metricEpochNanos\": {\n        \"type\": \"date\"\n      },\n      \"spentNanos\": {\n        \"type\": \"long\"\n      },\n      \"httpScheme\": {\n        \"type\": \"keyword\"\n      },\n      \"parentSpanId\": {\n        \"type\": \"keyword\"\n      },\n      \"spanName\": {\n        \"type\": \"keyword\"\n      },\n      \"component\": {\n        \"type\": \"keyword\"\n      },\n      \"sqlType\": {\n        \"type\": \"keyword\"\n      },\n      \"startEpochNanos\": {\n        \"type\": \"long\"\n      },\n      \"metricDescription\": {\n        \"type\": \"keyword\"\n      },\n      \"logName\": {\n        \"type\": \"keyword\"\n      },\n      \"TaskName\": {\n        \"type\": \"keyword\"\n      },\n      \"message_full_name\": {\n        \"type\": \"keyword\"\n      },\n      \"logMills\": {\n        \"type\": \"date\"\n      },\n      \"tracerVersion\": {\n        \"type\": \"keyword\"\n      },\n      \"lineNumber\": {\n        \"type\": \"long\"\n      },\n      \"statusData\": {\n        \"type\": \"keyword\"\n      },\n      \"JobClassName\": {\n        \"type\": \"keyword\"\n      }\n    }\n  },\n  \"aliases\": {}\n}"
  },
  {
    "path": "arius-admin/deploy/knowsearch-upgrade/.gitignore",
    "content": ""
  },
  {
    "path": "arius-admin/deploy/zeus-init/zeus_DeployES.sh",
    "content": "#!/bin/sh\n\n#set -x\n\n#获取当前文件的文件名称\nMYNAME=\"${0##*/}\"\nRET_OK=0\nRET_FAIL=1\n\n# 在这里做新的测试\ng_DeployUser=\"xiaoju\"\ng_DeployGroup=\"xiaoju\"\ng_EsHeapSize=31\ng_DeployPath=\"\"\n\ng_ClusterName=\"\"\ng_MasterNodes=\"\"\ng_CfgAddress=\"\"\ng_PackageUrl=\"\"\ng_Role=\"\"\ng_PidCount=\"\"\ng_Action=\"\"\ng_EsVersion=\"\"\ng_Port=\"\"\ng_Ip_Port=\"\"\ng_ConfigAction=\"\"\ng_Racks=\"\"\ng_HostLists=\"\"\n# 本机的ip地址\ng_Ip=\"\"\ng_rack=\"\"\n\n# ===== shuo =====\nplugin_operation_type=\"\"       # 插件操作类型：3（安装）4（卸载）\nplugin_file_name=\"\"            # 插件文件名\nplugin_s3_url=\"\"               # 插件安装需要的下载地址\nzeus_log=\"/soft/zeus-log-5-27\" # 注：zeus脚本执行过程中打印的信息重定向到该文件，用于调试\nopen_jdk=\"java-1.8.0-openjdk-1.8.0.161-0.b14.el7_4 java-1.8.0-openjdk-devel-1.8.0.161-0.b14.el7_4\"\n\nif [ -t 1 ]; then\n    RED=\"$(echo -e \"\\e[31m\")\"\n    HL_RED=\"$(echo -e \"\\e[31;1m\")\"\n    HL_BLUE=\"$(echo -e \"\\e[34;1m\")\"\n\n    NORMAL=\"$(echo -e \"\\e[0m\")\"\nfi\n\n_hl_red() { echo \"$HL_RED\"\"$@\"\"$NORMAL\"; }\n_hl_blue() { echo \"$HL_BLUE\"\"$@\"\"$NORMAL\"; }\n\n_trace() {\n    echo $(_hl_blue '  ->') \"$@\" >&2\n}\n\n_print_fatal() {\n    echo $(_hl_red '==>') \"$@\" >&2\n}\n\n_usage() {\n    cat <<USAGE\nUsage: bash ${MYNAME} [options]\n\nRequire:\n    --cluster_name=arius-log15     Operation cluster name.\n    --masters=xxx,yyy,zzz          Master nodes for cluster.\n    --cfg_address=http://xxx.git   Config file for cluster.\n    --package_url=http://xxxx      Package url address.\n    --es_version=version1          Version of elasticsearch.\n    --role=rolename                Node role in cluster(masternode/clientnode/datanode).\n    --pid_count=num                Es pid count in single machine(1/2...).\n    --action=action                Action for this operation(new/expand/deploy/restart).\n\nOptions:\n    -h, --help                     Print this help infomation.\n\nUSAGE\n\n    exit $RET_FAIL\n}\n\n#\n# Parses command-line options.\n#  usage: _parse_options \"$@\" || exit $?\n#\n# --cluster_name=arius-log15 --masters=xxx,yyy,zzz --cfg_address=https://git.xiaojukeji.com/bigdata-databus/elasticsearch-trib  \\\n#    --package_url=https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.0.0-linux-x86_64.tar.gz --es_version=version1 --role=masternode --pid_count=1 --action=restart\n_parse_options() {\n    declare -a argv\n\n    # $#表示的是传入参数的个数 -gt 表示的是大于\n    while [[ $# -gt 0 ]]; do\n        case $1 in\n        -h | --help)\n            _usage\n            exit\n            ;;\n        # 不断的匹配传入的参数来获取变量值\n        # 字符串的|可以表示或的操作\n        -c=* | --cluster_name=*)\n            g_ClusterName=\"${1#*=}\"\n            #作为脚本输入参数的偏移 不设置的话默认是偏移一位输入参数,不断的减少参数\n            shift # past argument=value\n            ;;\n        --masters=*)\n            g_MasterNodes=\"${1#*=}\"\n            shift # past argument=value\n            ;;\n        --config_action=*)\n            g_ConfigAction=\"${1#*=}\"\n            shift\n            ;;\n        --cfg_address=*)\n            g_CfgAddress=\"${1#*=}\"\n            shift # past argument=value\n            ;;\n        --hosts=*)\n            g_HostLists=\"${1#*=}\"\n            shift\n            ;;\n        --initial_rack=*)\n            g_Racks=\"${1#*=}\"\n            shift\n            ;;\n        -p=* | --package_url=*)\n            g_PackageUrl=\"${1#*=}\"\n            shift # past argument=value\n            ;;\n        -e=* | --es_version=*)\n            g_EsVersion=\"${1#*=}\"\n            shift # past argument=value\n            ;;\n        -r=* | --role=*)\n            g_Role=\"${1#*=}\"\n            shift # past argument=value\n            ;;\n        --pid_count=*)\n            g_PidCount=\"${1#*=}\"\n            shift # past argument=value\n            ;;\n        -a=* | --action=*)\n            g_Action=\"${1#*=}\"\n            shift # past argument=value\n            ;;\n        -p=* | --port=*)\n            g_Port=\"${1#*=}\"\n            shift # past argument=value\n            ;;\n        -*)\n            _print_fatal \"command line: unrecognized option $1\" >&2\n            return 1\n            ;;\n        *)\n            argv=(\"${argv[@]}\" \"${1}\")\n            shift\n            ;;\n        esac\n    done\n\n    # case ${#argv[@]} in\n    #     *)\n    #         _usage 1>&2\n    #         return 1\n    # ;;\n    # esac\n}\n\n# 检查执行是否成功，若失败，则打印错误信息，执行相应命令，并退出脚本\ncheck_result() {\n    ret=$1\n    message=$2\n    order=$3\n\n    #每一个基本的命令行指令执行之后都会有一个返回的值的指令\n    if [ \"${ret}\" -ne 0 ]; then\n        _print_fatal \"${message}\"\n        $($order)\n        exit \"${ret}\"\n    fi\n}\n\nfunction initKernelPatch() {\n    sudo su - -c \"yum-complete-transaction --cleanup-only\"\n    sudo su - -c \"yum --enablerepo=didi_kernel install -y didios-kpatch-modules-5.0-1.x86_64\"\n}\n\n# shellcheck disable=SC2112\nfunction user_add() {\n    id -u $1 &>/dev/null\n    if [[ $? == 0 ]]; then\n        # echo \"$1 user has eixst\"\n        echo -n\n        sudo chmod 755 /home/$1\n    else\n        # echo \"$1 user init...\"\n        sudo groupadd $1\n        sudo adduser -K UMASK=022 $1 -g $1\n    fi\n\n    sudo mkdir -p /home/$1/.ssh &>/dev/null\n    sudo sh -c \"echo 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAupQVnu0/ERr1WiR3ipKjbxW+NapmgRluTtb2t/S4D0jPS556gcsCwVZZr6cRuewt5B8ALNBsu3ZecGwpKE1jHkj/kgN3/wFzUiKJLcrdT861o+FKTPhXCc0K6/xiPFhTjSzqVoqMHasnM5EeKyotk5x+5qDcTKLnfvT2YV0zlPZ7ok+8hhvT8D3qUDogbkyMeGKsZqSt6A7ETxt3Ong9c3S0GcKGiMaDfp1Y1/Z4Q+xu1//B4f6WGSX305W93vf396QAOe4tiWdusPYlADobWNgKL/Utf4ULG/dMchbPQ83ab1+ZdbfE4y8K6lFPsBpiYKcqKLQuhvEhiEMFb7NYtQ== hadoop@bigdata-ops-control01.xg01' > /home/$1/.ssh/authorized_keys\"\n    sudo sh -c \"echo 'hadoop          ALL=(ALL)       NOPASSWD: ALL' > /etc/sudoers.d/07_hadoop\"\n\n    sudo chmod -R 700 /home/$1/.ssh\n    sudo chown -R $1:$1 /home/$1/.ssh\n\n}\n\n# shellcheck disable=SC2112\nfunction gmondinstall() {\n    if ! mysql -V &>/dev/null; then\n        sudo yum install mysql -y &>/dev/null\n    fi\n    sudo yum --enablerepo=didi_hadoop install libganglia ganglia-gmond ganglia-gmond-python MySQL-python -y && sudo /usr/sbin/groupadd -r ganglia -f && sudo /usr/sbin/useradd -s /sbin/nologin -r -d /var/lib/ganglia -g ganglia ganglia\n\n    if [ -f /tmp/gmond.conf ]; then\n        sudo rm /tmp/gmond.conf\n    fi\n\n    wget -q http://10.88.129.68/data/ganglia/gmond.conf -O /tmp/gmond.conf\n    if [ \"$cloneIp\" != \"\" ]; then\n        ip=$cloneIp\n    else\n        ip=$(hostname -i)\n    fi\n\n    info=$(mysql -h10.83.99.4 -usre_read -pSRE+ysqtlmy@308 -Dcmdb_asset -e \"select a.node, b.host, b.port from machine_odin as a, gmond_odin_master as b where a.ip = '$ip' and a.children_id = b.children_id \" | grep -v '\\-\\-\\-\\-\\-' | tail -n 1)\n    clustername=$(echo $info | awk '{print $1}')\n    host=$(echo $info | awk '{print $2}')\n    port=$(echo $info | awk '{print $3}')\n    location=$(echo $ip | awk -F\".\" '{print $1\".\"$2\".\"$3}')\n    if [ \"$host\" == \"\" -o \"$port\" == \"\" ]; then\n        echo $info\n        echo \"host: $host, port: $port\"\n        echo \"error\"\n        exit\n    fi\n    sed -i -e \"s/ClusterName/$clustername/g\" -e \"s/Location/$location/g\" -e \"s/HostName/$host/g\" -e \"s/HnPort/$port/g\" /tmp/gmond.conf\n    test -d /etc/ganglia || sudo mkdir /etc/ganglia\n    sudo cp /etc/ganglia/gmond.conf /etc/ganglia/gmond.conf.$(date +%Y%m%d)\n    sudo mv /tmp/gmond.conf /etc/ganglia/gmond.conf\n    sudo service gmond restart\n\n}\n\n# shellcheck disable=SC2112\nfunction exesudo() {\n    #\n    # I use underscores to remember it's been passed\n    local _funcname_=\"$1\"\n\n    local params=(\"$@\")              ## array containing all params passed here\n    local tmpfile=\"/dev/shm/$RANDOM\" ## temporary file\n    local filecontent                ## content of the temporary file\n    local regex                      ## regular expression\n    local func                       ## function source\n\n    #\n    # Shift the first param (which is the name of the function)\n    unset params[0] ## remove first element\n    # params=( \"${params[@]}\" )     ## repack array\n\n    #\n    # WORKING ON THE TEMPORARY FILE:\n    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    content=\"#!/bin/bash\\n\\n\"\n\n    #\n    # Write the params array\n    content=\"${content}params=(\\n\"\n    regex=\"\\s+\"\n    for param in \"${params[@]}\"; do\n        if [[ \"$param\" =~ $regex ]]; then\n            content=\"${content}\\t\\\"${param}\\\"\\n\"\n        else\n            content=\"${content}\\t${param}\\n\"\n        fi\n    done\n\n    content=\"$content)\\n\"\n    echo -e \"$content\" >\"$tmpfile\"\n\n    #\n    # Append the function source\n    echo \"#$(type \"$_funcname_\")\" >>\"$tmpfile\"\n\n    #\n    # Append the call to the function\n    echo -e \"\\n$_funcname_ \\\"\\${params[@]}\\\"\\n\" >>\"$tmpfile\"\n\n    #\n    # DONE: EXECUTE THE TEMPORARY FILE WITH SUDO\n    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    sudo bash \"$tmpfile\"\n    rm \"$tmpfile\"\n}\n\n# modify ulimit\n# shellcheck disable=SC2112\nfunction modify_ulimit() {\n    echo \"Start modify ulimit.\"\n\n    #################修改ulimit############\n    sed -i 's/\\(^\\*.*$\\)/#\\1/' /etc/security/limits.d/[0-9][0-9]-nproc.conf\n\n    test -f /etc/security/limits.conf && cp /etc/security/limits.conf /etc/security/limits_bak_$(date +%F_%H-%M-%S)\n    cat >/etc/security/limits.conf <<EOF\n# /etc/security/limits.conf\n#\n#Each line describes a limit for a user in the form:\n#\n#<domain>        <type>  <item>  <value>\n#\n#Where:\n#<domain> can be:\n#        - an user name\n#        - a group name, with @group syntax\n#        - the wildcard *, for default entry\n#        - the wildcard %, can be also used with %group syntax,\n#                 for maxlogin limit\n#\n#<type> can have the two values:\n#        - \"soft\" for enforcing the soft limits\n#        - \"hard\" for enforcing hard limits\n#\n#<item> can be one of the following:\n#        - core - limits the core file size (KB)\n#        - data - max data size (KB)\n#        - fsize - maximum filesize (KB)\n#        - memlock - max locked-in-memory address space (KB)\n#        - nofile - max number of open file descriptors\n#        - rss - max resident set size (KB)\n#        - stack - max stack size (KB)\n#        - cpu - max CPU time (MIN)\n#        - nproc - max number of processes\n#        - as - address space limit (KB)\n#        - maxlogins - max number of logins for this user\n#        - maxsyslogins - max number of logins on the system\n#        - priority - the priority to run user process with\n#        - locks - max number of file locks the user can hold\n#        - sigpending - max number of pending signals\n#        - msgqueue - max memory used by POSIX message queues (bytes)\n#        - nice - max nice priority allowed to raise to values: [-20, 19]\n#        - rtprio - max realtime priority\n#\n#<domain>      <type>  <item>         <value>\n#\n#*               soft    core            0\n#*               hard    rss             10000\n#@student        hard    nproc           20\n#@faculty        soft    nproc           20\n#@faculty        hard    nproc           50\n#ftp             hard    nproc           0\n#@student        -       maxlogins       4\n\n# End of file\n*          hard    nproc           100000\n*          soft    nproc           100000\n*          soft    nofile          100000\n*          hard    nofile          100000\n*          soft    stack           102400\n*          hard    stack           102400\n*          soft    sigpending      600000\n*          hard    sigpending      600000\n*          soft    core            100000\n*          hard    core            100000\nEOF\n}\n\n# modify sysctl\n# shellcheck disable=SC2112\n# 主要是内核当中的sysctl的网络连接部分的配置的修改\nfunction modify_sysctl() {\n    echo \"Start modify sysctl.\"\n\n    grep -q 'vm.swappiness=1' /etc/sysctl.conf || sudo su - root -c \"echo 'vm.swappiness=1' >> /etc/sysctl.conf\"\n    grep -q 'vm.max_map_count=262144' /etc/sysctl.conf || sudo su - root -c \"echo 'vm.max_map_count=262144' >> /etc/sysctl.conf\"\n\n    sudo su - root -c \"/sbin/sysctl -p &>/dev/null\"\n\n    return 0\n}\n\n# shellcheck disable=SC2112\nfunction test_java_version() {\n    ret=$(find /usr/local -maxdepth 1 -type d -regextype posix-egrep -regex \".*(jdk2|jdk1.8|jdk1.9).*\")\n    jpath=$(echo $ret | awk '{print $1}')\n\n    if [ -d \"${jpath}\" ]; then\n        export JAVA_HOME=\"${jpath}\"\n        export PATH=$JAVA_HOME/bin:$PATH\n\n        return 1\n    fi\n\n    command -v java >/dev/null 2>&1\n\n    if [ $? -eq 0 ]; then\n        ##检查java版本\n        JVERSION=$(java -version 2>&1 | awk 'NR==1{gsub(/\"/,\"\");print $3}')\n        major=$(echo $JVERSION | awk -F. '{print $1}')\n        mijor=$(echo $JVERSION | awk -F. '{print $2}')\n        if [ $major -le 1 ] && [ $mijor -lt 8 ]; then\n            return 0\n        else\n            return 1\n        fi\n    else\n        return 0\n    fi\n}\n\n# shellcheck disable=SC2112\nfunction check_java_version() {\n    ret=$(find /usr/local -maxdepth 1 -type d -regextype posix-egrep -regex \".*(jdk2|jdk1.8|jdk1.9).*\")\n    jpath=$(echo $ret | awk '{print $1}')\n\n    if [ -d \"${jpath}\" ]; then\n        export JAVA_HOME=\"${jpath}\"\n        export PATH=$JAVA_HOME/bin:$PATH\n    fi\n\n    command -v java >/dev/null 2>&1\n\n    if [ $? -eq 0 ]; then\n        ##检查java版本\n        JVERSION=$(java -version 2>&1 | awk 'NR==1{gsub(/\"/,\"\");print $3}')\n        major=$(echo $JVERSION | awk -F. '{print $1}')\n        mijor=$(echo $JVERSION | awk -F. '{print $2}')\n        number=$(echo $JVERSION | awk -F_ '{print $2}')\n        if [ $major -le 1 ] && [ $mijor -lt 8 ]; then\n            return 0\n        elif [ $number -lt 92 ] && [ $mijor -eq 8 ]; then\n\n            return 0\n        else\n            return 1\n        fi\n    else\n        return 0\n    fi\n}\n\n# shellcheck disable=SC2112\nfunction prepare_dir() {\n    # 创建/home/xiaoju目录 如果不存在的话就创建 -p\n    sudo su - root -c \"mkdir -p /home/xiaoju\"\n    check_result $? \"mkdir -p /home/xiaoju failed.\"\n    sudo su - root -c \"chmod 777 /home/xiaoju\"\n\n    sudo su - root -c \"grep -qw ${g_DeployGroup} /etc/group || groupadd ${g_DeployGroup} -g 2000\"\n    sudo su - root -c \"id ${g_DeployUser} || useradd ${g_DeployUser} -u 2000 -g 2000\"\n    # 增加这一行的阻断\n    check_result $? \"准备文件出错\"\n\n    ## check and prepare dir of (/data2 or /data3)\n    if [ ! -d /data2 ] || [ ! -d /data3 ]; then\n        data_dir=$(df | grep -v Used | sort -k 2 -n | tail -n 1 | awk '{print $NF}')\n        if [ ! -d ${data_dir} ]; then\n            echo \"get max data dir: ${data_dir} failed.\"\n            exit 1\n        fi\n\n        # 递归创建对应的目录\n        sudo su - root -c \"mkdir -p ${data_dir}/data2 && mkdir -p ${data_dir}/data3\"\n        check_result $? \"mkdir ${data_dir}/{data2,data3} failed.\"\n\n        sudo su - root -c \"chown -R ${g_DeployUser}:${g_DeployGroup} ${data_dir}/data2\"\n        sudo su - root -c \"chown -R ${g_DeployUser}:${g_DeployGroup} ${data_dir}/data3\"\n\n        if [ ! -d /data2 ]; then\n            sudo su - root -c \"ln -s ${data_dir}/data2 /data2\"\n        fi\n\n        if [ ! -d /data3 ]; then\n            sudo su - root -c \"ln -s ${data_dir}/data3 /data3\"\n        fi\n\n        if [ ! -d /data2 ] || [ ! -d /data3 ]; then\n            echo \"prepare /data2,/data3 failed.\"\n            exit 1\n        fi\n    fi\n\n    sudo su - root -c \"chown -R ${g_DeployUser}:${g_DeployGroup} /data2\"\n    sudo su - root -c \"chown -R ${g_DeployUser}:${g_DeployGroup} /data3\"\n}\n\n## install jdk 8\n# shellcheck disable=SC2112\nfunction install_jdk() {\n    echo \"Start install jdk.\"\n\n    test_java_version\n    if [ \"X0\" == \"X$?\" ]; then\n        if [ -f ${jdk_rpm} ]; then\n            sudo su - -c \"rpm -ivh ${jdk_rpm} -y\"\n            check_result $? \"安装jdk失败\"\n        else\n            sudo su - -c \"yum install ${open_jdk} -y\"\n            check_result $? \"安装jdk失败\"\n        fi\n    else\n        echo \"已安装jdk1.8版本\"\n    fi\n}\n\n## install jdk 11\n# shellcheck disable=SC2112\nfunction install_jdk11() {\n    echo \"Start install jdk11.\"\n\n    if [ \"X${g_EsVersion}\" == \"Xelasticsearch-2.3.3\" ]; then\n        return\n    fi\n\n    if [ ! -d /usr/local/jdk-11.0.2 ]; then\n        sudo su - root -c \"curl -SL https://n9e-server.s3.didiyunapi.com/openjdk-11.0.2_linux-x64_bin.tar.gz | tar -zxC /home/xiaoju\"\n        check_result $? \"install jdk-11.0.2 failed.\"\n    else\n        echo \"已安装jdk1.11版本\"\n    fi\n}\n\n## init bashrc\n# shellcheck disable=SC2112\nfunction init_bashrc() {\n    home_dir=/home/${g_DeployUser}\n    es_heap_size=${g_EsHeapSize}\n\n    cat ${home_dir}/.bashrc | grep ES_HEAP_SIZE || sudo su - ${g_DeployUser} -c \"{\n    echo \\\"export ES_HEAP_SIZE=${es_heap_size}g\\\" >> ${home_dir}/.bashrc\n    echo \\\"alias el='cd /data2/elasticsearch/logs/'\\\" >> ${home_dir}/.bashrc\n    echo \\\"alias es='cd /data2/elasticsearch/bin;./elasticsearch -d' \\\" >> ${home_dir}/.bashrc\n    echo \\\"alias ep='ps -ef|grep elasticsearch|grep -v grep'\\\" >> ${home_dir}/.bashrc\n    echo \\\"export ES_GC_LOG_FILE=/data2/elasticsearch/logs/gc.log\\\" >> ${home_dir}/.bashrc\n}\"\n\n    if [ -d /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.161-0.b14.el7_4.x86_64 ]; then\n        cat ${home_dir}/.bashrc | grep \"java-1.8.0-openjdk\" || sudo su - ${g_DeployUser} -c \"{\n     echo \\\"export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.161-0.b14.el7_4.x86_64\\\" >> ${home_dir}/.bashrc\n\n }\"\n    fi\n    if [ -d /usr/local/jdk-11.0.2 ]; then\n        sudo su - ${g_DeployUser} -c \"sed -i '/JAVA_HOME/d' ${home_dir}/.bashrc\"\n        sudo su - ${g_DeployUser} -c \"{\n     echo \\\"export JAVA_HOME=/usr/local/jdk-11.0.2\\\" >> ${home_dir}/.bashrc\n\n }\"\n\n    fi\n\n    #     if [ -d /usr/local/jdk-11.0.2 ]; then\n    #     cat ${home_dir}/.bashrc | grep \"jdk-11\" || sudo su - ${g_DeployUser} -c \"{\n    #     echo \\\"export JAVA_HOME=/usr/local/jdk-11.0.2\\\" >> ${home_dir}/.bashrc\n    # }\"\n    # fi\n\n}\n\nfunction join_by() {\n    local IFS=\"$1\"\n    shift\n    echo \"$*\"\n}\n\n######### prepare env for es\n# shellcheck disable=SC2112\nfunction prepare_env_es() {\n    prepare_dir\n    install_jdk\n    install_jdk11\n    exesudo modify_ulimit\n    modify_sysctl\n    init_bashrc\n    initKernelPatch\n    user_add hadoop\n    #这个地点要注意：原来就被注释掉了gmondinstall\n    #这一步执行出现了问题\n    hadoopinstall\n    #这一步没有问题\n    filebeatinstall\n}\n\n# shellcheck disable=SC2112\nfunction filebeatinstall() {\n    if [ ! -d /data2/filebeat-7.6.2-linux-x86_64/ ]; then\n        sudo su - ${g_DeployUser} -c \"curl -SL http://didiyum.sys.xiaojukeji.com/didiyum/didi/didi_hadoop/7/x86_64/filebeat-7.6.2-linux-x86_64.tar.gz | tar -zxC /data2/ \"\n        check_result $? \"install filebeat failed.\"\n    fi\n}\n\n# shellcheck disable=SC2112\nfunction hadoopinstall() {\n    if [ \"x$HOSTNAME\" == \"xus01\" ]; then\n        sudo su - -c \"yum-complete-transaction --cleanup-only\"\n        sudo yum install -y --enablerepo=didi_hadoop didi-hive-us\n    else\n        sudo su - -c \"yum-complete-transaction --cleanup-only\"\n        sudo yum install -y --enablerepo=didi_hadoop didi-hive-nmg\n    fi\n}\n\n### TODO: 解决对机器名的依赖，这里根据主机名来计算rack信息；\n# shellcheck disable=SC2112\nfunction gen_rack() {\n    hostname=$(hostname)\n    number=$(echo ${hostname} | awk -F. '{print $1}' | grep -oP \"\\d+$\")\n    rack=0\n\n    # 获取admin第三方服务中当前主机所处的位置\n    if [ \"_\" == \"${number}_\" ]; then\n        echo \"modify rack num failed.\"\n        exit 1\n    else\n        rack=$(expr ${number} / 2 + 1)\n    fi\n\n    if [[ \"$hostname\" =~ .*ceph.* ]]; then\n        echo \"c${rack}\"\n        ret=$(sudo su - root -c \"cat ${config_file} | grep 'node.attr.set'\")\n        if [ x$? != \"x0\" ]; then\n            sudo su - -c \"sed -i '\\$a\\node.attr.set: cold' ${config_file}\"\n        fi\n    else\n        echo \"r${rack}\"\n    fi\n}\n\n######### 集群节点启动成功之后向admin发送post请求来更新数据\nfunction get_ip() {\n    echo \"开始获取本机的ip地址\"\n    g_Ip=$(ifconfig | grep inet | grep -v 127.0.0.1 | grep -v 172 | grep -v inet6 | awk '{print $2}' | tr -d \"addr:\" | head -n 1)\n    echo \"${g_Ip}\"\n    g_Ip_Port=\"${g_Ip}:${g_Port}\"\n}\n\n## 这里根据传入的rack参数信息来解决对于机器名称的依赖\n# shellcheck disable=SC2112\nfunction get_rack() {\n    # 获取本机的ip地址\n    get_ip\n    echo \"本机的ip地址是${g_Ip}\"\n    # 本机在传入的主机列表当中的位置\n    local_place=0\n\n    echo \"开始计算rack的值\"\n    echo \"获取的到初始rack值：${g_Racks}\"\n    # 获取关于data节点的本次操作的所有主机列表\n    IFS=',' read -r -a array <<<\"${g_HostLists}\"\n    for host in ${array[*]}; do\n        #去除循环变量尾部的空格\n        host=$(echo \"${host}\" |sed 's/[ ]*$//g')\n        if [ ${host} == ${g_Ip} ]; then\n            break\n        fi\n        local_place++\n    done\n\n    #  获取到位置之后进行本机rack的值计算,取整操作\n    local_rack=$(sudo su - root -c \"echo ${g_Racks%%.*}\")\n    echo \"获取传入的rack的基准值是:${local_rack}\"\n    echo \"计算出本机的地址在传入主机列表中的位置，位置参数从0开始:${local_place}\"\n    ret=$(sudo su - root -c \"echo ${g_Racks} | grep '.'\")\n    # 获取.号之前的rack值\n    # 当rack以x.5结尾时\n    if [ x$? == \"x0\" ]; then\n        echo \"本次操作是有点号的操作\"\n        add_value=$(expr ${local_place} / 2 + 1)\n    # 当rack不以x.5结尾时\n    else\n        echo \"本次操作时没有点号的操作\"\n        let local_place++\n        add_value=$(expr ${local_place} / 2)\n    fi\n    echo \"rack计算中算出本机地址相对于rack的基准值的偏移操作:${add_value}\"\n    g_rack=$(expr ${local_rack} + ${add_value})\n    echo \"rack的值计算成功\"\n\n    if [ \"x$g_rack\" == \"x\" ]; then\n        g_rack=$(gen_rack)\n        echo \"rack计算为空，导致只能使用本机地址的参数作为rack计算值\"\n        echo \"$r{g_rack}\"\n    else\n        echo \"r${g_rack}\"\n    fi\n\n    g_rack=\"r${g_rack}\"\n    #开始判断当前的data节点是否是冷节点，根据当前的ip,port,clusterName调用admin提供的第三方接口来获取当前的rack信息，如果当前节点是冷节点，则返回值是\"cold\"字符串\n    echo \"开始进行冷节点的判断\"\n    echo \"访问admin接口的rack信息的url是:${admin_rack_info}/${g_ClusterName}/${g_Ip}/\"\n    response=$(curl \"${admin_rack_info}/${g_ClusterName}/${g_Ip}/\")\n    echo \"rack信息获取完毕\"\n    echo \"${response}\"\n    if [ x${response} == \"xcold\" ]; then\n       g_rack=\"cold\"\n       echo \"当前rack的节点属性:${g_rack}\"\n    fi\n}\n\n# shellcheck disable=SC2112\nfunction setup_rack() {\n    echo \"开始进行rack值的设置\"\n    get_rack\n    echo \"rack的设置已经完成:${g_rack}\"\n    if [ ! -f ${config_file} ]; then\n        echo \"ERR: ${config_file} is not existed.\"\n        exit 1\n    fi\n\n    # 不支持elasticsearch-2.3.3\n    echo \"当前配置的地址是：${config_file}\"\n    ret=$(sudo su - root -c \"cat ${config_file} | grep 'node.attr.rack'\")\n    if [ x$? == \"x0\" ]; then\n        echo \"原配置有相关的字段，直接进行替换\"\n        sudo su - root -c \"sed -i 's/node.attr.rack:.*/node.attr.rack: ${g_rack}/g' ${config_file}\"\n    else\n        echo \"配置中没有rack这个字段设置，所以在配置后面进行补充\"\n        sudo su - root -c \"sed -i '\\$a\\node.attr.rack: ${g_rack}' ${config_file}\"\n        #sudo su - root -c \"echo 'node.attr.rack: ${rack}' >> ${config_file}\"\n    fi\n    check_result $? \"setup_rack failed.\"\n}\n\nsetup_elastic_config_v1() {\n    if [ ! -f ${config_file} ]; then\n        echo \"${config_file} is not existed.\"\n        exit 1\n    fi\n\n    if [ \"x$g_ClusterName\" != \"x\" ]; then\n        sed -i \"s/cluster.name:.*/cluster.name: $g_ClusterName/g\" ${config_file}\n    else\n        echo \"parameter g_ClusterName must not null.\"\n        exit 1\n    fi\n\n    sudo su - -c \"sed -i 's/node.name:.*/node.name: $(hostname)/g' ${config_file}\"\n    # node role init\n    echo \"setup config file for $g_Role\"\n    g_Hosts=\"\"\n    sed_data_dir=\"\\\\\"$data_dir\n    datanode_dir=\"\"\n    for i in ${data_dir}; do\n        if [ \"x$g_Role\" == \"xdatanode\" ]; then\n            datanode_dir=$datanode_dir\"\\\\\"$i\"\\/es\"\",\"\n            if [ ! -d ${i}/es ]; then\n                sudo su - root -c \"chown -R ${g_DeployUser}:${g_DeployUser} ${i}\"\n                sudo su - $g_DeployUser -c \"mkdir -p ${i}/es\"\n            fi\n        fi\n    done\n    ret=$(cat ${config_file} | grep 'MASTERNODES')\n    if [ x$? == \"x0\" ]; then\n        if [ \"x${g_MasterNodes}\" != \"x\" ]; then\n            IFS=',' read -r -a array <<<\"${g_MasterNodes}\"\n            for node in ${array[*]}; do\n                g_Hosts=${g_Hosts}\"\\\"${node}:9300\\\",\"\n                if [[ \"x$g_Action\" == \"xexpand\" || \"x$g_Action\" == \"xdeploy\" ]]; then\n                    checkport=$(nc -v -w5 ${node} 9300 </dev/null)\n                    if [ x$? != \"x0\" ]; then\n                        echo \"MASTERNODE has not active.\"\n                        exit 1\n                    fi\n                fi\n            done\n            ret=$(cat ${config_file} | grep 'discovery.seed_hosts')\n            if [ x$? == \"x0\" ]; then\n                sed -i \"s/discovery.seed_hosts:.*/discovery.seed_hosts: [ ${g_Hosts%?} ]/g\" ${config_file}\n            else\n                sed -i \"s/discovery.zen.ping.unicast.hosts:.*/discovery.zen.ping.unicast.hosts: [ ${g_Hosts%?} ]/g\" ${config_file}\n            fi\n\n        else\n            echo \"ENV MASTERNODES must not null.\"\n            exit 1\n        fi\n    fi\n    if [ \"x$g_Role\" == \"xdatanode\" ]; then\n        sed -i \"s/path.data:.*/path.data: ${datanode_dir%?} /g\" ${config_file}\n        setup_rack\n    fi\n\n}\n\n# shellcheck disable=SC2112\nfunction refreshconfig() {\n\n    sudo su - root -c \"touch $config_file_tmp\"\n    sudo su - root -c \"touch $config_jvm_file_tmp\"\n    sudo su - root -c \"touch $config_filebeats_tmp\"\n\n    DATE=$(date +%Y%m%d%H%M)\n    # 主机名字带有ceph会有特殊操作\n    if [[ \"$HOSTNAME\" =~ .*ceph.* ]]; then\n        response=$(curl --write-out %{http_code} --silent --output $config_file_tmp \"${ecm_url}?cluster_name=${g_ClusterName}&engin_name=datanodeCeph&type_name=elasticsearch.yml&config_action=${g_ConfigAction}\" --cookie \"domainAccount=admin; Authorization=MTphekFXaUpoeGtobzMzYWM=\")\n        response_jvm=$(curl --write-out %{http_code} --silent --output $config_jvm_file_tmp \"${ecm_url}?cluster_name=${g_ClusterName}&engin_name=datanodeCeph&type_name=jvm.options&config_action=${g_ConfigAction}\" --cookie \"domainAccount=admin; Authorization=MTphekFXaUpoeGtobzMzYWM=\")\n    else\n        # --write-out %{http_code} 把http请求状态码打印控制台，请求admin项目下载用户自定义的ES配置文件，下载到 config_file_tmp，要记得带上cookie\n        response=$(curl --write-out %{http_code} --silent --output $config_file_tmp \"${ecm_url}?cluster_name=${g_ClusterName}&engin_name=${g_Role}&type_name=elasticsearch.yml&config_action=${g_ConfigAction}\" --cookie \"domainAccount=admin; Authorization=MTphekFXaUpoeGtobzMzYWM=\")\n        # 请求admin项目下载用户自定义的JVM配置文件，下载到 config_jvm_file_tmp，要记得带上cookie\n        response_jvm=$(curl --write-out %{http_code} --silent --output $config_jvm_file_tmp \"${ecm_url}?cluster_name=${g_ClusterName}&engin_name=${g_Role}&type_name=jvm.options&config_action=${g_ConfigAction}\" --cookie \"domainAccount=admin; Authorization=MTphekFXaUpoeGtobzMzYWM=\")\n    fi\n    # 心跳的配置文件\n    response_filebeats=$(curl --write-out %{http_code} --silent --output $config_filebeats_tmp \"${ecm_url}?cluster_name=${g_ClusterName}&engin_name=${g_Role}&type_name=filebeat.yml&config_action=${g_ConfigAction}\" --cookie \"domainAccount=admin; Authorization=MTphekFXaUpoeGtobzMzYWM=\")\n\n    echo \"${response_filebeats}\"\n    echo \"${response_jvm}\"\n    echo \"${response}\"\n\n    if [ $response_filebeats -eq 200 ] && [ -s $config_filebeats_tmp ]; then\n        # 保存历史配置文件\n        mv $config_filebeats ${config_filebeats}${DATE}.bak\n        # 用户自定义的配置文件\n        mv $config_filebeats_tmp $config_filebeats\n        sudo su - ${g_DeployUser} -c \"cd /data2/filebeat-7.6.2-linux-x86_64/ && nohup ./filebeat -e -c ${config_filebeats} > filebeat.log 2>&1 &\"\n        check_result $? \"setup elasticsearch config failed.\"\n    fi\n\n    ret=$(sudo su - root -c \"cat ${config_jvm_file_tmp} | grep 'Xms'\")\n    if [ x$? == \"x0\" ] && [ $response_jvm -eq 200 ] && [ -s $config_jvm_file_tmp ]; then\n        # 保存历史配置文件\n        mv $config_jvm_file ${config_jvm_file}${DATE}.bak\n        # 用户自定义的配置文件\n        mv $config_jvm_file_tmp $config_jvm_file\n    fi\n\n    # 判断配置文件中是否有必要信息而非乱码\n    ret=$(sudo su - root -c \"cat ${config_file_tmp} | grep 'cluster.name'\")\n    # 对于sed的文本编辑操作需要切换到root权限，否则会出现权限不足的问题:Permission denied\n    if [ x$? == \"x0\" ] && [ $response -eq 200 ] && [ -s $config_file_tmp ]; then\n        echo \"使用用户自定义配置文件\"\n        # 保存历史配置文件\n        mv $config_file ${config_file}${DATE}.bak\n        # 用户自定义的配置文件\n        mv $config_file_tmp $config_file\n        setup_elastic_config_v1\n        check_result $? \"setup elasticsearch config failed.\"\n    else\n        echo \"使用默认配置文件\"\n        # 如果，请求下载用户自定义配置文件失败 || 下载文件内容为空，就用默认配置\n        setup_elastic_config\n        check_result $? \"setup elasticsearch config failed.\"\n    fi\n\n    setup_log4j\n\n}\n\nsetup_elastic_config() {\n    if [ ! -f ${config_file} ]; then\n        echo \"${config_file} is not existed.\"\n        exit 1\n    fi\n\n    if [ \"x$g_ClusterName\" != \"x\" ]; then\n        # 设置集群名字\n        sudo su - -c \"sed -i 's/cluster.name:.*/cluster.name: $g_ClusterName/g' ${config_file}\"\n    else\n        echo \"parameter g_ClusterName must not null.\"\n        exit 1\n    fi\n\n    # 设置最小的恢复功能的集群节点数目为1\n    sudo su - -c \"sed -i 's/gateway.recover_after_nodes:.*/gateway.recover_after_nodes: 1/g' ${config_file}\"\n\n    # 设置节点角色\n    echo \"setup config file for $g_Role\"\n    g_Hosts=\"\"\n    sed_data_dir=\"\\\\\"$data_dir\n    datanode_dir=\"\"\n    for i in ${data_dir}; do\n        if [ \"x$g_Role\" == \"xdatanode\" ]; then\n            datanode_dir=$datanode_dir\"\\\\\"$i\"\\/es\"\",\"\n            if [ ! -d ${i}/es ]; then\n                sudo su - root -c \"chown -R ${g_DeployUser}:${g_DeployUser} ${i}\"\n                sudo su - $g_DeployUser -c \"mkdir -p ${i}/es\"\n            fi\n        fi\n    done\n\n    if [ \"x${datanode_dir}\" == \"x\" ]; then\n        datanode_dir=\"/data3/es\"\n    fi\n\n    # 设置初始的最小master节点数目\n    g_min_masters=0\n    if [ \"x${g_MasterNodes}\" != \"x\" ]; then\n        IFS=',' read -r -a array <<<\"${g_MasterNodes}\"\n        for node in ${array[*]}; do\n            g_Hosts=${g_Hosts}\"\\\"${node}:9300\\\",\"\n            let g_min_masters++\n        done\n        g_min_masters=\"$(expr ${g_min_masters} / 2)\"\n        let g_min_masters++\n        sudo su - -c \"sed -i 's/discovery.zen.minimum_master_nodes:.*/discovery.zen.minimum_master_nodes: ${g_min_masters}/g' ${config_file}\"\n        # 检测配置项中是否存在discovery.seed_hosts\n        ret=$(sudo su - root -c \"cat ${config_file} | grep 'discovery.seed_hosts'\")\n        # 对于sed的文本编辑操作需要切换到root权限，否则会出现权限不足的问题:Permission denied\n        if [ x$? == \"x0\" ]; then\n            sudo su - -c \"sed -i 's/discovery.seed_hosts:.*/discovery.seed_hosts: [ ${g_Hosts%?} ]/g' ${config_file}\"\n        else\n            sudo su - -c \"sed -i 's/discovery.zen.ping.unicast.hosts:.*/discovery.zen.ping.unicast.hosts: [ ${g_Hosts%?} ]/g' ${config_file}\"\n        fi\n\n    else\n\n        echo \"ENV MASTERNODES must not null.\"\n        exit 1\n    fi\n\n    if [ \"x$g_Role\" == \"xmasternode\" ]; then\n        sudo su - -c \"sed -i 's/node.name:.*/node.name: $(hostname)/g' ${config_file}\"\n        sudo su - -c \"sed -i 's/node.master:.*/node.master: true/g' ${config_file}\"\n        sudo su - -c \"sed -i 's/node.data:.*/node.data: false/g' ${config_file}\"                         ## XXX\n        sudo su - -c \"sed -i 's/http.enabled:.*/http.enabled: false/g' ${config_file}\"                   ## XXX\n        # 数据和日志注意放同一个文件夹\n        sudo su - -c \"sed -i 's/path.data:.*/path.data: \\/data3\\/${g_Role} /g' ${config_file}\"           ## XXX\n        sudo su - -c \"sed -i 's/transport.tcp.port:.*/transport.tcp.port: 9300/g' ${config_file}\"        ## XXX\n\n        # sudo su - -c \"sed -i 's/processors:.*/processors: 4/g' ${config_file}\"                           ## XXX\n        sudo su - -c \"sed -i 's/thread_pool.search.size:.*/thread_pool.search.size: 4/g' ${config_file}\" ## XXX\n        sudo su - -c \"sed -i 's/thread_pool.write.size:.*/thread_pool.write.size: 3/g' ${config_file}\"   ## XXX\n        echo ${g_Port}\n        sudo su - -c \"sed -i 's/http.port:.*/http.port: ${g_Port}/g' ${config_file}\"\n    elif [ \"x$g_Role\" == \"xdatanode\" ]; then\n        sudo su - -c \"sed -i 's/node.name:.*/node.name: $(hostname)/g' ${config_file}\"\n        sudo su - -c \"sed -i 's/node.master:.*/node.master: false/g' ${config_file}\"\n        sudo su - -c \"sed -i 's/node.data:.*/node.data: true/g' ${config_file}\"\n        sudo su - -c \"sed -i 's/path.data:.*/path.data: ${datanode_dir%?} /g' ${config_file}\"\n\n        ret=$(sudo su - -c \"cat ${config_file} | grep 'http.host'\")\n        if [ x$? == \"x0\" ]; then\n            sudo su - -c \"sed -i 's/http.enabled:.*/http.enabled: true/g' ${config_file}\"\n            sudo su - -c \"sed -i 's/http.host:.*/http.host: 127.0.0.1/g' ${config_file}\"\n        else\n            sudo su - -c \"sed -i 's/http.enabled:.*/http.enabled: false/g' ${config_file}\"\n        fi\n\n        sudo su - -c \"sed -i \"s/node.max_local_storage_nodes:.*/node.max_local_storage_nodes: ${g_PidCount}/g\" ${config_file}\" ## XXX\n        sudo su - -c \"sed -i \"/transport.tcp.port:.*/d\" ${config_file}\"                                                        ## XXX  否则无法起多个实例\n\n        sudo su - -c \"sed -i 's/processors:.*/processors: 16/g' ${config_file}\"                           ## XXX\n        sudo su - -c \"sed -i 's/thread_pool.search.size:.*/thread_pool.search.size: 16/g' ${config_file}\" ## XXX\n        sudo su - -c \"sed -i 's/thread_pool.write.size:.*/thread_pool.write.size: 12/g' ${config_file}\"   ## XXX\n        sudo su - -c \"sed -i 's/http.port:.*/http.port: ${g_Port}/g' ${config_file}\"\n    elif [ \"x$g_Role\" == \"xclientnode\" ]; then\n        sudo su - -c \"sed -i 's/node.name:.*/node.name: $(hostname)/g' ${config_file}\"\n        sudo su - -c \"sed -i 's/node.master:.*/node.master: false/g' ${config_file}\"\n        sudo su - -c \"sed -i 's/node.data:.*/node.data: false/g' ${config_file}\"\n        sudo su - -c \"sed -i 's/http.enabled:.*/http.enabled: true/g' ${config_file}\"\n        # 数据和日志注意放同一个文件夹\n        sudo su - -c \"sed -i \"s/path.data:.*/path.data: \\/data3\\/${g_Role} /g\" ${config_file}\"            ## XXX\n        sudo su - -c \"sed -i \"s/transport.tcp.port:.*/transport.tcp.port: 9300/g\" ${config_file}\"         ## XXX\n\n        sudo su - -c \"sed -i 's/processors:.*/processors: 12/g' ${config_file}\"                           ## XXX\n        sudo su - -c \"sed -i 's/thread_pool.search.size:.*/thread_pool.search.size: 12/g' ${config_file}\" ## XXX\n        sudo su - -c \"sed -i 's/thread_pool.write.size:.*/thread_pool.write.size: 9/g' ${config_file}\"    ## XXX\n        sudo su - -c \"sed -i 's/http.port:.*/http.port: ${g_Port}/g' ${config_file}\"\n    else\n        echo \"Bad Node role: $g_Role\"\n        exit 1\n    fi\n\n    if [ \"x$g_Role\" == \"xdatanode\" ]; then\n        setup_rack\n    fi\n\n}\n\n########## update log4j config for report es log to kafka.\n# shellcheck disable=SC2112\n# 这一块的逻辑暂时没有修改过\nfunction setup_log4j() {\n    hostname=$(hostname)\n    dir=$(dirname ${config_file})\n    file_path=$dir\"/log4j2.properties\"\n    location=$(echo ${hostname} | awk -F. '{print $NF}')\n\n    if [ -f ${file_path} ] && [ ${location} == \"us01\" ]; then\n        sed -i 's/appender.kafka.topic.*/appender.kafka.topic = us01_elasticsearch_log_topic/g' $file_path\n        sed -i 's/appender.kafka.property1.value.*/appender.kafka.property1.value = 10.14.128.13:30357/g' $file_path\n        sed -i 's/appender.kafka.property4.value.*/appender.kafka.property4.value = org.apache.kafka.common.security.plain.PlainLoginModule required username=\"44.appId_000128\" password=\"LzHybFh21kJU\";/g' $file_path\n        sed -i 's/appender.kafkaSlowlog.topic.*/appender.kafkaSlowlog.topic = us01_elasticsearch_slowlog_topic/g' $file_path\n        sed -i 's/appender.kafkaSlowlog.property1.value.*/appender.kafkaSlowlog.property1.value = 10.14.128.13:30357/g' $file_path\n        sed -i 's/appender.kafkaSlowlog.property4.value.*/appender.kafkaSlowlog.property4.value = org.apache.kafka.common.security.plain.PlainLoginModule required username=\"44.appId_000128\" password=\"LzHybFh21kJU\";/g' $file_path\n    fi\n}\n\n######### install es package\n# shellcheck disable=SC2112\nfunction install_es_package() {\n    if [[ \"x$g_Action\" == \"xexpand\" || \"x$g_Action\" == \"xnew\" ]]; then\n        prepare_env_es\n    fi\n\n    modify_sysctl\n\n    # g_DeployPath /data2/clientnode、/data2/masternode、/data2/\n    sudo su - ${g_DeployUser} -c \"mkdir -p ${g_DeployPath}\"\n    check_result $? \"mdkir ${g_DeployPath} failed.\"\n\n    # 如果是扩容，同时部署路径已经存在，跳过部署，不然会影响已经启动的服务；\n    #    if [ \"x$g_Action\" == \"xexpand\" ]; then\n    #        if [ -d \"${g_DeployPath}/elasticsearch\" ]; then\n    #            return\n    #        fi\n    #    fi\n\n    # 拼接下载路径，g_Role masternode、clientnode、kong，g_EsVersion ES版本号\n    down_path=\"/home/xiaoju/${g_Role}/${g_EsVersion}\"\n    if [ X\"${g_Role}\" == \"Xdatanode\" ]; then\n        down_path=\"/home/xiaoju/${g_EsVersion}\"\n    fi\n\n    # 递归创建目录（如果目录存在，则不创建）\n    sudo su - ${g_DeployUser} -c \"mkdir -p ${down_path}/elasticsearch\"\n    check_result $? \"mdkir ${down_path} failed.\"\n\n    # 创建ES日志保存文件夹\n    sudo su - ${g_DeployUser} -c \"mkdir -p /data3/${g_Role}-logs\"\n    check_result $? \"mdkir /data3/logs failed.\"\n\n    echo ${g_PackageUrl}\n    echo ${down_path}\n    # 判断该版本的ES是否已经下载\n    if [ ! -d \"${down_path}/elasticsearch/config\" ]; then\n        sudo su - root -c \"curl -SL '${g_PackageUrl}' | tar --strip-components 1 -zxC ${down_path}/elasticsearch\"\n        check_result $? \"install es to ${down_path} from ${g_PackageUrl} failed.测试测试测试\"\n        sudo su - root -c \"chmod -R 777 ${down_path}/elasticsearch\"\n    fi\n\n    # 删除老的软连接，g_DeployPath 即为 /data2/masternode、/data2/clientnode、/data2\n    if [ -d \"${g_DeployPath}/elasticsearch\" ]; then\n        sudo su - ${g_DeployUser} -c \"rm -rf ${g_DeployPath}/elasticsearch\"\n    fi\n\n    # /data2/masternode、/data2/clientnode、/data2 创建软链接，指向ES下载的源文件路径，/data3创建软链接，指向ES下载的源文件日志路径（data3也保存数据）\n    sudo su - root -c \"ln -nfs ${down_path}/elasticsearch ${g_DeployPath}/elasticsearch && ln -nfs /data3/${g_Role}-logs ${down_path}/elasticsearch/logs\"\n    check_result $? \"install es for move to ${g_DeployPath} failed.\"\n\n    echo \"环境部署已经完成，后续等待配置刷新操作\"\n    # 更新配置文件\n    refreshconfig\n    check_result $? \"setup elasticsearch config failed.\"\n\n    echo \"配置已经刷新，等待后续日志文件启动操作\"\n    setup_log4j\n    check_result $? \"setup log4j config failed.\"\n}\n\n# 向admin发送请求更新ip地址，其中请求体中的内容需要包含ip:port 集群名称 角色名称\nfunction send_ip() {\n    # 调试点打印详细的信息\n    echo \"${g_ClusterName}\"\n    echo \"${g_Role}\"\n    echo \"${g_Ip_Port}\"\n    response=$(curl --write-out %{http_code} --silent -H \"Content-Type:application/json\" -d \"{\\\"clusterPhyName\\\":\\\"${g_ClusterName}\\\",\\\"role\\\":\\\"${g_Role}\\\",\\\"httpAddress\\\":\\\"${g_Ip_Port}\\\"}\" ${ecm_cluster_url} --cookie \"domainAccount=admin; Authorization=MTphekFXaUpoeGtobzMzYWM=\")\n    if [ $response -ne 200 ]; then\n        stop_es\n        exit 1\n    fi\n\n}\n\n######### start es process\n# shellcheck disable=SC2112\nfunction start_es() {\n\n    echo \"开始进行 es 启动\"\n    deploy_count=${g_PidCount}\n    curdir=\"${g_DeployPath}/elasticsearch\"\n    deploy_dir=\"${curdir}\"\n\n    sudo su - ${g_DeployUser} -c \"mkdir -p ${deploy_dir}/logs\"\n    check_result $? \"start es mkdir ${deploy_dir}/logs failed.\"\n    # shellcheck disable=SC2039\n    if [ \"x$g_Role\" == \"xdatanode\" ]; then\n        sudo su - ${g_DeployUser} -c \"rm /data*/es/nodes/*/_state/segments*\"\n        sudo su - ${g_DeployUser} -c \"rm /data*/es/nodes/*/_state/manifest*\"\n    fi\n\n    # if [[ -f ${deploy_dir}/config/jvm.options ]];then\n    #     sed -i \"s/-Xms.*/-Xms${g_EsHeapSize}g/g\" ${deploy_dir}/config/jvm.options\n    #     sed -i \"s/-Xmx.*/-Xmx${g_EsHeapSize}g/g\" ${deploy_dir}/config/jvm.options\n    # fi\n\n    count=0\n    #### 如果是扩容，就不影响已经启动的混部实例\n    if [ \"x$g_Action\" == \"xexpand\" ]; then\n        count=$(ps aux | grep -i \"bootstrap.Elasticsearch\" | grep ${deploy_dir} | grep -v grep | wc -l)\n    fi\n\n    # 以同样的角色在一个机器上可以启动不同数目的节点实例\n    for ((i = ${count}; i < ${deploy_count}; ++i)); do\n        echo $i\n        if [ -d \"${deploy_dir}\" ]; then\n            sudo su - ${g_DeployUser} -c \"cd ${deploy_dir} && sh control.sh start\"\n            check_result $? \"start es failed.\"\n            check_es_pid ${deploy_dir}\n            # 向admin发送post请求发送集群的名称 机器节点的角色 ip地址和port端口\n            # 获取本机的ip和端口地址\n            #            get_ip\n            #            echo \"${g_Ip_Port}\"\n            #            echo \"开始向admin发送http_post请求\"\n            #            send_ip\n            sleep 5s\n        fi\n    done\n    echo \"es任务启动成功\"\n}\n\n#### 检查进程是否启动\n# shellcheck disable=SC2112\nfunction check_es_pid() {\n    curdir=$1\n    num_pid=$(ps aux | grep -i \"bootstrap.Elasticsearch\" | grep \"${curdir}\" | grep -v \"arius-gateway\" | grep -v elasticsearch-trib | grep -v grep | wc -l)\n    if [ ${num_pid} -lt 1 ]; then\n        echo \"ES start error\"\n        exit 1\n    fi\n}\n\n# shellcheck disable=SC2112\nfunction init_jdk11() {\n    if [ -d /usr/local/jdk-11.0.2 ]; then\n        home_dir=/home/${g_DeployUser}\n        sudo su - ${g_DeployUser} -c \"sed -i '/JAVA_HOME/d' ${home_dir}/.bashrc\"\n        cat ${home_dir}/.bashrc | grep \"jdk-11\" || sudo su - ${g_DeployUser} -c \"{\n     echo \\\"export JAVA_HOME=/usr/local/jdk-11.0.2\\\" >> ${home_dir}/.bashrc\n }\"\n        check_result $? \"set java_home failed\"\n    fi\n}\n######### stop es process\n# shellcheck disable=SC2112\nfunction stop_es() {\n    echo \"stop es\"\n    curdir=\"${g_DeployPath}/elasticsearch\"\n    check_java_version\n    if [ \"X0\" == \"X$?\" ]; then\n        install_jdk11\n        init_jdk11\n    else\n        echo \"已安装jdk1.8.0_92版本\"\n    fi\n\n    sudo su - ${g_DeployUser} -c \"cd ${curdir} && sh control.sh stop\"\n\n    pids=$(ps aux | grep -i \"bootstrap.Elasticsearch\" | grep \"${curdir}\" | grep -v \"arius-gateway\" | grep -v elasticsearch-trib | grep -v grep | awk '{print $2}')\n    #    if [ \"x${pids}\" == \"x\" ]; then\n    #        echo \"es stop failed\"\n    #        exit 1\n    #    fi\n\n    for pid in $pids; do\n        echo $pid\n        sudo su - ${g_DeployUser} -c \"kill $pid\"\n\n        local timeout=30\n        local i=0\n        # 循环stop服务, 直至60s超时\n        for ((i = 0; i < ${timeout}; i++)); do\n            # 检查服务是否停止,如果停止则直接返回\n            if ps -p $pid >/dev/null; then\n                echo \"$pid is running\"\n                sleep 2s\n            else\n                echo \"${app} is stopped\"\n                break\n            fi\n\n            # 停止该服务\n            if [ $i -ge $((timeout - 3)) ]; then\n                #                sudo su - ${g_DeployUser} -c \"kill -9 ${pid} &>/dev/null\"\n                sudo su - ${g_DeployUser} -c \"kill -9 ${pid} &>/dev/null\"\n            else\n                #                sudo su - ${g_DeployUser} -c \"kill ${pid} &>/dev/null\"\n                sudo su - ${g_DeployUser} -c \"kill ${pid} &>/dev/null\"\n            fi\n        done\n\n        if [ $i -ge ${timeout} ]; then\n            echo \"stop $pid failed.\"\n            exit 1\n        fi\n\n        sleep 5s\n    done\n    echo \"stop es 任务已完成\"\n}\n\n######### restart process\nfunction restart_es() {\n    stop_es\n    start_es\n}\n\n# 解析 json字符串\n# 网上的代码，可以使用的是Awk工具和字符串的正则匹配来处理json串的信息\n### 方法简要说明：\n### 1. 是先查找一个字符串：带双引号的key。如果没找到，则直接返回defaultValue。\n### 2. 查找最近的冒号，找到后认为值的部分开始了，直到在层数上等于0时找到这3个字符：,}]。\n### 3. 如果有多个同名key，则依次全部打印（不论层级，只按出现顺序）\n###\n### 3 params: json, key, defaultValue\ngetJsonValuesByAwk() {\n    awk -v json=\"$1\" -v key=\"$2\" -v defaultValue=\"$3\" 'BEGIN{\n        foundKeyCount = 0\n        while (length(json) > 0) {\n            pos = match(json, \"\\\"\"key\"\\\"[ \\\\t]*?:[ \\\\t]*\");\n            if (pos == 0) {if (foundKeyCount == 0) {print defaultValue;} exit 0;}\n\n            ++foundKeyCount;\n            start = 0; stop = 0; layer = 0;\n            for (i = pos + length(key) + 1; i <= length(json); ++i) {\n                lastChar = substr(json, i - 1, 1)\n                currChar = substr(json, i, 1)\n\n                if (start <= 0) {\n                    if (lastChar == \":\") {\n                        start = currChar == \" \" ? i + 1: i;\n                        if (currChar == \"{\" || currChar == \"[\") {\n                            layer = 1;\n                        }\n                    }\n                } else {\n                    if (currChar == \"{\" || currChar == \"[\") {\n                        ++layer;\n                    }\n                    if (currChar == \"}\" || currChar == \"]\") {\n                        --layer;\n                    }\n                    if ((currChar == \",\" || currChar == \"}\" || currChar == \"]\") && layer <= 0) {\n                        stop = currChar == \",\" ? i : i + 1 + layer;\n                        break;\n                    }\n                }\n            }\n\n            if (start <= 0 || stop <= 0 || start > length(json) || stop > length(json) || start >= stop) {\n                if (foundKeyCount == 0) {print defaultValue;} exit 0;\n            } else {\n                print substr(json, start, stop - start);\n            }\n\n            json = substr(json, stop + 1, length(json) - stop)\n        }\n    }'\n}\n\n######### 从 admin 的第三方接口获取插件操作的信息\n# 需要注意的是集群的重启删除更新的操作都是走的工单的形式，走工单的话就会在处理工单的时候向宙斯发送工单的任务请求\n# 所以在宙斯分发执行脚本的时候，脚本之中就会调用admin的接口来获取相关的信息从而获取插件的信息\nget_plugin_info_from_admin() {\n    # 在这里详细的介绍一下curl的指令\n    # curl是一个命令行工具，通过指定的URL来上传或下载数据，并将数据展示出来。curl中的c表示client，而URL，就是URL\n    # 暂时先注掉\n    response=$(curl --silent \"${admin_plugin_url}?cluster_name=${g_ClusterName}\")\n    # sed 参数s：替换文本,替换命令用替换模式替换指定模式\n    plugin_operation_type=$(getJsonValuesByAwk \"${response}\" operationType \"\" | sed 's/\\\"//g')\n    plugin_file_name=$(getJsonValuesByAwk \"${response}\" pluginFileName \"\" | sed 's/\\\"//g')\n    plugin_s3_url=$(getJsonValuesByAwk \"${response}\" url \"\" | sed 's/\\\"//g')\n}\n\n######### 安装es插件\ninstall_es_plugin() {\n    # 插件安装的目录\n    es_plugin_root=\"${g_DeployPath}/elasticsearch/plugins/\"\n    #find /tmp  -name \"._*\" | xargs rm -f 找到隐藏文件并且删除\n    # 从 S3 下载插件并解压到该文件夹中\n    # 解压的指令在linux当中zip需要使用unzip tar tar.gz需要使用tar\n    #curl -SL --silent \"${plugin_s3_url}\" | tar -xC \"${es_plugin_root}/${plugin_file_name}/\"\n    sudo su - root -c \"curl -SL --silent '${plugin_s3_url}' | tar -zxC '${es_plugin_root}'\"\n    # 检查解压结果\n    check_result $? \"install es plugin [${plugin_file_name}] to ${es_plugin_root} from ${plugin_s3_url} failed.\" \"rm -rf ${plugin_file_name}\"\n    # 将下载的插件设置为可执行 删除plugin文件夹和插件文件夹中的隐藏文件\n    sudo su - root -c \"cd '${es_plugin_root}' && chmod -R 777 '${plugin_file_name}' && find '${es_plugin_root}'  -name \"._*\" | xargs rm -f\"\n    sudo su - root -c \"cd '${es_plugin_root}' && find '${plugin_file_name}'  -name \"._*\" | xargs rm -f\"\n}\n\n######### 卸载es插件\nuninstall_es_plugin() {\n    es_plugin_root=\"${g_DeployPath}/elasticsearch/plugins\"\n    cd \"${es_plugin_root}\" || check_result $? \"enter es plugin directory failed\"\n    rm -rf \"${plugin_file_name}\"\n}\n\n######### 更新集群插件\n######### 目前定的是插件的更新是针对于整个集群的，所以不应该是单独的某个节点做插件的更新操作，这一步如何操作呢，暂时定的是单个节点伴随着重启任务更新插件列表\nrefresh_plugin() {\n    # 从 admin 第三方接口获取插件操作的信息\n    get_plugin_info_from_admin\n    echo \"开始进行插件的操作\"\n    echo \"${plugin_operation_type}\"\n    echo \"${plugin_file_name}\"\n    echo \"${plugin_s3_url}\"\n\n    if [ \"${plugin_operation_type}\" = \"3\" ]; then\n        # 安装插件\n        echo \"从[${plugin_s3_url}]安装es插件[${plugin_file_name}]开始...\"\n        install_es_plugin\n        echo \"从[${plugin_s3_url}]安装es插件[${plugin_file_name}]完成\"\n    elif [ \"${plugin_operation_type}\" = \"4\" ]; then\n        # 卸载插件\n        echo \"卸载es插件[${plugin_file_name}]开始...\"\n        uninstall_es_plugin\n        echo \"卸载es插件[${plugin_file_name}]完成\"\n    elif [ X\"${plugin_operation_type}\" = \"X\" ]; then\n        # 没有插件操作\n        echo \"当前没有插件操作任务\"\n    else\n        # 非法操作\n        echo \"插件操作不合法\"\n    fi\n\n    echo \"插件操作完毕\"\n}\n\n################################## main route #################################\n# shellcheck disable=SC2145\necho \"脚本参数: ${@}\"\n_parse_options \"${@}\" || _usage\n\n# Linux df（英文全拼：disk free） 命令用于显示目前在 Linux 系统上的文件系统磁盘使用情况统计。\n# grep是做一个抓取的动作 grep -v则是做排除性的抓取\n# sort是做一个排序的操作 -k 2表示的是按照文本中的第二个域进行排序比较，-n表示展示的是全部的行\n# awk AWK 是一种处理文本文件的语言，是一个强大的文本分析工具。 NF\t一条记录的字段的数目\n# echo >> 属于输出重定向的过程，可以将当前的字符串打印到对应文件的结尾，echo > 不会进行重定向，会直接清空掉原来的文件再进行输出字符串，相同点是如果原文件不存在，会首先进行创建\ndata2_flag=$(df | grep -v Used | sort -k 2 -n | grep data2 | awk '{print $NF}')\n#g_home=\"/home/xiaoju\"\n############\nif [[ X\"${g_Role}\" == \"Xclientnode\" || X\"${g_Role}\" == \"Xmasternode\" ]]; then\n    # 对于目录的确认，这里会根据传入的不同的角色设置不同的集群部署的路径\n    if [ ! -d \"/home/xiaoju/${g_Role}\" ] && [ X\"${data2_flag}\" != \"X\" ]; then\n        if [ -d /data2/${g_Role} ]; then\n            # 文件链接的命令 ln nfs网络文件系统 这里是生成一个文件的链接方便查询 主要就是做一些文件的转移\n            sudo su - ${g_DeployUser} -c \"mv /data2/${g_Role} /home/xiaoju/ && ln -nfs /home/xiaoju/${g_Role} /data2/${g_Role} && mv /home/xiaoju/${g_Role}/elasticsearch/logs /data3/ && ln -nfs /data3/logs  /home/xiaoju/${g_Role}/elasticsearch/logs\"\n            #      else\n            #        sudo su - ${g_DeployUser} -c \"mkdir -p /home/xiaoju/${g_Role} && ln -nfs /home/xiaoju/${g_Role} /data2/${g_Role}\"\n        fi\n\n    fi\n    # 说明是 clientnode 或 masternode 角色的ES\n    g_DeployPath=\"/data2/${g_Role}\"\nelse\n    if [ ! -d \"/home/xiaoju/elasticsearch\" ] && [ X\"${data2_flag}\" != \"X\" ]; then\n        if [ -d /data2/elasticsearch ]; then\n            sudo su - ${g_DeployUser} -c \"mv /data2/elasticsearch /home/xiaoju/ && ln -nfs /home/xiaoju/elasticsearch /data2/elasticsearch && mv /home/xiaoju/elasticsearch/logs /data3/ && ln -nfs /data3/logs  /home/xiaoju/elasticsearch/logs\"\n            #      else\n            #        sudo su - ${g_DeployUser} -c \"mkdir -p /home/xiaoju/elasticsearch && ln -nfs /home/xiaoju/elasticsearch /data2/elasticsearch\"\n        fi\n\n    fi\n    # 说明是 datanode 角色的ES\n    g_DeployPath=\"/data2\"\nfi\n\n# 给予data2权限，否则没有权限启动data2下的control.sh\nsudo su - root -c \"chmod -R 777 /data2\"\nconfig_file=\"${g_DeployPath}/elasticsearch/config/elasticsearch.yml\"\nconfig_jvm_file=\"${g_DeployPath}/elasticsearch/config/jvm.options\"\n\n# ES的备用配置文件\nconfig_file_tmp=\"${g_DeployPath}/elasticsearch/config/elasticsearch.yml.tmp\"\n# JVM的备用配置文件\nconfig_jvm_file_tmp=\"${g_DeployPath}/elasticsearch/config/jvm.options.tmp\"\n\n#可以使用的部署的的admin服务的地址\nadmin_service_url=\"http://172.23.164.19:8010\"\n\n# 预发环境的admin项目的配置文件获取地址\necm_url=\"${admin_service_url}/admin/api/v2/thirdpart/zeus/cluster/config/file\"\n\n# admin第三方接口，用于查询插件操作信息\nadmin_plugin_url=\"${admin_service_url}/admin/api/v2/thirdpart/zeus/plugin/info\"\n\n#admin第三方接口，用于查询当前的节点是否是冷节点\nadmin_rack_info=\"${admin_service_url}/admin/api/v2/thirdpart/zeus/cold\"\n\nconfig_filebeats_tmp=\"/data2/filebeat-7.6.2-linux-x86_64/filebeat.yml.tmp\"\nconfig_filebeats=\"/data2/filebeat-7.6.2-linux-x86_64/filebeat.yml\"\n\ndata_dir=$(df | grep -v Used | sort -k 2 -n | grep data | awk '{print $NF}')\n# awk是一个强大的文本分析工具，相对于grep的查找，sed的编辑，awk在其对数据分析并生成报告时，显得尤为强大。简单来说awk就是把文件逐行的读入，以空格为默认分隔符将每行切片，切开的部分再进行各种分析处理。\n\n# hostname会显示主机名称\nHOSTNAME=$(hostname | awk -F. '{print $NF}')\n#echo \"$g_ClusterName $g_PackageUrl $g_EsVersion $g_Role $g_PidCount $g_Action\"\n\ncase $g_Action in\n\"new\")\n    # 发布更新elasticsearch\n    echo $g_Action\n    # 停服务\n    stop_es\n    # 删除旧服务 安装服务\n    install_es_package\n    # 启动服务\n    start_es\n    ;;\n\"deploy\")\n    # 发布更新elasticsearch\n    echo $g_Action\n    # 停服务\n    stop_es\n    # 删除旧服务 安装服务\n    install_es_package\n    # 启动服务\n    start_es\n    ;;\n\"restart\")\n    # 重启单机elasticsearch\n    echo $g_Action\n    # 重启服务\n\n    # 配置刷新\n    # 如果当前只是单纯的集群重启操作，而不涉及配置，则不会进入该分支\n    if [ \"X$g_ConfigAction\" != \"X\" ] && [ \"X$g_ConfigAction\" != \"Xnull\" ]; then\n      echo $g_ConfigAction\n      refreshconfig\n    fi\n\n    # 如果当前只是单纯的集群重启操作，而不涉及插件，则不会进入该分支\n    refresh_plugin\n\n    restart_es\n    ;;\n\"updateconfig\")\n    # 发布更新elasticsearch\n    echo $g_Action\n    # 删除旧服务 安装服务\n    refreshconfig\n\n    restart_es\n    ;;\n\"expand\")\n    # 发布更新elasticsearch\n    # shellcheck disable=SC2086\n    echo $g_Action\n    # 删除旧服务 安装服务\n    install_es_package\n    # 启动服务\n    start_es\n    ;;\n\"shrink\")\n    # 重启单机elasticsearch\n    echo $g_Action\n    # 停服务\n    stop_es\n    ;;\n*)\n    echo \"unknown command\"\n    exit 1\n    ;;\nesac"
  },
  {
    "path": "arius-admin/deploy/zh_update/sql/app_id_rename_project_id.sql",
    "content": "alter table es_manager_test3.arius_work_order_info\n    change approver_app_id approver_project_id int default -1 not null comment '审批人projectid' after title;\n\nalter table es_manager_test3.arius_work_order_info\n    change applicant_app_id applicant_project_id int default -1 not null comment '申请人projectid';\n# appid->projectid\nalter table es_manager_test3.index_template_info\n    change app_id projectId int(10) default -1 not null comment 'project_id';\n# appid->project_id\nalter table es_manager_test3.project_arius_resource_logic\n    change app_id projectId int(10) default -1 not null comment 'project_id';\n# app_id ->project_id\nalter table es_manager_test3.project_logi_cluster_auth\n    change app_id projectId int(10) default -1 not null comment 'project_id';\n# app_id ->project_id\nalter table es_manager_test3.project_template_info\n    change app_id projectId int(10) default -1 not null comment 'project_id';\n# domain_account ->user_name\nalter table es_manager_test3.user_metrics_config_info\n    change domain_account user_name varchar(100) default '' not null comment '用户账号';"
  },
  {
    "path": "arius-admin/deploy/zh_update/sql/arius_user_transfer_logi_user.sql",
    "content": "drop function if exists PW_encode;\ncreate function PW_encode(pw varchar(2048)) returns varchar(2048)\nbegin\n    declare SALT0_START varchar(2048) default '{@VjJ4ak{[#@'; declare SALT0_END varchar(2048) default '@#]}J6Rllh@}';\n    declare SALT1 varchar(2048) default 'Mv{#cdRgJ45Lqx}3IubEW87!=='; declare i int default 1;\n    declare pw_temp varchar(2048) default '';\n    set pw_temp = pw;\n\n    while (i < 4)\n        do\n            set pw_temp = concat(pw_temp, SALT0_START, i, SALT0_END); set pw_temp = REPLACE(pw_temp, '\\n', '');\n            set pw_temp = to_base64(pw_temp); set i = i + 1;\n        end while;\n    set pw_temp = concat(pw_temp, SALT1); set pw_temp = REPLACE(pw_temp, '\\n', ''); return pw_temp;\nend;\n\n\n# 通过arius_user_info 生成 logi_security_user\ninsert into es_manager_test2.logi_security_user(id, user_name, pw, real_name, phone, email, dept_id, is_delete,\n                                                app_name, salt)\nselect id,\n       domain_account,\n       if(length(password) > 5, PW_encode(password), ''),\n       name,\n       mobile,\n       email,\n       0             as dept_id,\n       0             as is_delete,\n       'know_search' as app_name,\n       ''            as salt\nfrom admin_zh.arius_user_info\nwhere status = 1;\n\n# 通过arius_user_info 生成 logi_security_user_role\ninsert into es_manager_test2.logi_security_user_role(user_id, role_id, is_delete, app_name)\nselect id, 2 as role_id, 0 as is_delete, 'know_search' as app_name\nfrom admin_zh.arius_user_info\nwhere status = 1;\n# 修改admin为管理员\ninsert into es_manager_test2.logi_security_user_role(user_id, role_id, is_delete, app_name)\nselect id, 1 as role_id, 0 as is_delete, 'know_search' as app_name\nfrom admin_zh.arius_user_info\nwhere status = 1\n  and domain_account = 'admin';"
  },
  {
    "path": "arius-admin/deploy/zh_update/sql/create_index.sql",
    "content": "create index idx_project_id\n    on es_manager_test3.project_template_info (project_id);\ncreate index idx_project_id\n    on es_manager_test3.index_template_info (project_id);\ncreate index idx_data_center\n    on es_manager_test3.index_template_info (data_center);\n# 创建索引\ncreate index idx_project_id\n    on es_manager_test3.project_logi_cluster_auth (project_id);\ncreate index idx_project_id\n    on es_manager_test3.project_arius_resource_logic (project_id);\n\ncreate index idx_log_id_statud\n    on es_manager_test3.index_template_physical_info (logic_id, status);\n\ncreate index idx_region_id\n    on es_manager_test3.index_template_physical_info (region_id);\ncreate index idx_region_id\n    on es_manager_test3.es_cluster_role_host_info (region_id);"
  },
  {
    "path": "arius-admin/deploy/zh_update/sql/drop_index.sql",
    "content": "# 删除app_id和responsible的索引\ndrop index idx_app_id on appid_template_info;\n\ndrop index idx_responsibleids on appid_template_info;\n# 删除索引\ndrop index idx_app_id on es_manager_test3.project_logi_cluster_auth;\n\ndrop index idx_responsible on es_manager_test3.project_logi_cluster_auth;"
  },
  {
    "path": "arius-admin/deploy/zh_update/sql/drop_table_field.sql",
    "content": "alter table es_manager_test3.index_template_info\n    drop department_id ;\nalter table es_manager_test3.index_template_info\n    drop responsible ;\n\nalter table es_manager_test3.project_arius_resource_logic\n    drop responsible ;\n\nalter table es_manager_test3.project_arius_resource_logic\n    drop department_id;\nalter table es_manager_test3.project_arius_resource_logic\n    drop department;\n\nalter table es_manager_test3.project_logi_cluster_auth\n    drop responsible ;\nalter table es_manager_test3.project_template_info\n    drop responsible_ids ;"
  },
  {
    "path": "arius-admin/deploy/zh_update/sql/not_null_change_null.sql",
    "content": "# 字段内容变更\nalter table es_manager_test3.es_cluster_region\n    modify racks varchar(2048) default '' null comment 'region的rack，逗号分隔';"
  },
  {
    "path": "arius-admin/deploy/zh_update/sql/query_app_transfer_project.sql",
    "content": "# 通过query_app表反向生成project_id\n\ninsert into es_manager_test2.logi_security_project (id, project_name, description, dept_id, running, is_delete,\n                                                    app_name, project_code)\nselect id,\n       name                                            project_name,\n       memo                                            description,\n       0                                               dept_id,\n       1                                               running,\n       0                                               is_delete,\n       'know_search'                                   app_name,\n       concat('p', ceil(rand() * (100000000 - 1) + 1)) project_code\nfrom query_app;\n\n# 通过query_app生成project_config\ninsert into es_manager_test2.project_arius_config(project_id, analyze_response_enable, is_source_separated,\n                                                  aggr_analyze_enable, dsl_analyze_enable, slow_query_times, is_active,\n                                                  memo)\nselect id,\n       analyze_response_enable,\n       is_source_separated,\n       aggr_analyze_enable,\n       dsl_analyze_enable,\n       1000    slow_query_times,\n       1    as is_active,\n       memo as memo\nfrom query_app;\n\n# 通过query_app生成es_user\ninsert into es_manager_test2.arius_es_user(id, index_exp, data_center, is_root, memo, ip, verify_code, is_active,\n                                           query_threshold, cluster, search_type,\n                                           project_id, is_default_display)\nselect id,\n       index_exp,\n       data_center,\n       is_root,\n       memo,\n       ip,\n       verify_code,\n       is_active,\n       query_threshold,\n       cluster,\n       search_type,\n       id as project_id,\n       1  as is_default_display\nfrom query_app;"
  },
  {
    "path": "arius-admin/deploy/zh_update/sql/responsible_transfer_user_project.sql",
    "content": "#  user-》logi_security_user_project\ninsert into es_manager_test2.logi_security_user_project (project_id, user_id, app_name, user_type)\nselect distinct *\nfrom (select qa.id project_id, eds.id user_id, 'know_search' as app_name, 1 as user_type\n      from admin_zh.query_app qa\n               left join admin_zh.arius_user_info eds on find_in_set(eds.id, responsible)\n      order by project_id) t1\nwhere user_id is not null;\n#query_app( department,department_id) ->logi_security_dept\ninsert into es_manager_test3.logi_security_dept(id, dept_name, description, leaf, level, parent_id, app_name)\nSELECT id, department, department_id, false as leaf, 1 level, 0 parent_id, 'know_search' as app_name\nfrom admin_zh.query_app\nGROUP BY department\nHAVING COUNT(department) > 1;\n# query_app(department,department_id,id)->logi_security_dept\nupdate es_manager_test2.logi_security_project\nset dept_id=id\nwhere id in (SELECT id as app_name from admin_zh.query_app GROUP BY department HAVING COUNT(department) > 1);"
  },
  {
    "path": "arius-admin/deploy/zh_update/sql/table_add_field.sql",
    "content": "#字段新增\nalter table es_manager_test3.es_cluster_phy_info\n    add platform_type varchar(100) default '' not null comment 'IaaS平台类型';\n\nalter table es_manager_test3.es_cluster_phy_info\n    add resource_type tinyint default -1 not null comment '集群资源类型，1-共享资源，2-独立资源，3-独享资源';\n\nalter table es_manager_test3.es_cluster_phy_info\n    add gateway_url varchar(200) default '' not null comment '集群gateway地址';\n\n\n# 字段新增\nalter table es_manager_test3.es_cluster_role_host_info\n    modify rack varchar(30) default '' null comment '节点rack信息';\nalter table es_manager_test3.es_cluster_role_host_info\n    add region_id bigint default -1 not null comment '节点所属regionId';\nalter table es_manager_test3.es_cluster_role_host_info\n    add attributes text null comment 'es节点attributes信息 , 逗号分隔';\n\n\n# es_package->es_package\nalter table es_manager_test3.es_package\n    modify `desc` varchar(384) default '' null comment '备注';\n# es_work_order_task_detail->es_work_order_task_detail\nalter table es_manager_test3.es_work_order_task_detail\n    add constraint uniq_work_order_task_id_role_hostname_delete_flag\n        unique (work_order_task_id, role, hostname, delete_flag);\n\n# index_template_alias-> index_template_alias\n\n# index_template_config->index_template_config\n#字段内容变更\n\n\n#表字段修改\nalter table es_manager_test3.index_template_info\n    add open_srv varchar(255) null comment '已开启的模板服务';\n\nalter table es_manager_test3.index_template_info\n    add disk_size decimal(10, 3) default -1.000 null comment '可用磁盘容量';\n\n\n\n# 字段修改\n\n# 新增字段\nalter table es_manager_test3.index_template_physical_info\n    add region_id int(10) default -1 not null comment '模板关联的regionId';\n\n# index_template_type->index_template_type\n\n\n# 字段新增\nalter table es_manager_test3.project_arius_resource_logic\n    add data_node_spec varchar(20) default '' not null comment '节点规格';\n\nalter table es_manager_test3.project_arius_resource_logic\n    add disk_total bigint(50) default 0 not null comment '集群磁盘总量 单位byte';\n\nalter table es_manager_test3.project_arius_resource_logic\n    add disk_usage bigint(50) default 0 not null comment '集群磁盘使用量 单位byte';\n\nalter table es_manager_test3.project_arius_resource_logic\n    add disk_usage_percent decimal(10, 5) default 0 not null comment '集群磁盘空闲率 单位 0 ~1';\n\nalter table es_manager_test3.project_arius_resource_logic\n    add es_cluster_version varchar(20) default '' not null comment 'es集群版本';\n\nalter table es_manager_test3.project_arius_resource_logic\n    add node_num int(10) default 0 not null comment '节点个数';\n\n\n\nalter table es_manager_test3.es_cluster_region\n    add name varchar(100) default '' not null comment 'region名称';\n\nalter table es_manager_test3.es_cluster_region\n    add config varchar(1024) default '' null comment 'region配置项';"
  },
  {
    "path": "arius-admin/deploy/zh_update/sql/table_rename.sql",
    "content": "# config修改 arius_config_info\n\n# cluster_monitor_task_v2-> arius_meta_job_cluster_distribute\nALTER TABLE zh_test.cluster_monitor_task_v2 RENAME TO es_manager_test3.arius_meta_job_cluster_distribute;\n\n# arius_work_task->arius_op_task\nALTER TABLE zh_test.arius_work_task RENAME TO es_manager_test3.arius_op_task;\n\n\n# work_order->arius_work_order_info\nALTER TABLE zh_test.work_order RENAME TO es_manager_test3.arius_work_order_info;\n#  es_data_source-----》es_cluster_phy_info\nALTER TABLE zh_test.es_data_source RENAME TO es_manager_test3.es_cluster_phy_info;\n#  es_role_cluster_host-----》es_cluster_role_host_info\nALTER TABLE zh_test.es_role_cluster_host RENAME TO es_manager_test3.es_cluster_role_host_info;\n# es_role_cluster->es_cluster_role_info\nALTER TABLE zh_test.es_role_cluster RENAME TO es_manager_test3.es_cluster_role_info;\n# es_config->es_config\n# es_machine_norms->es_machine_norms\n# gateway_cluster->gateway_cluster_info\nALTER TABLE zh_test.gateway_cluster RENAME TO es_manager_test3.gateway_cluster_info;\n\n# gateway_node->gateway_cluster_info\nALTER TABLE zh_test.gateway_node RENAME TO es_manager_test3.gateway_cluster_info;\n#index_template->index_template_info\nALTER TABLE zh_test.index_template RENAME TO es_manager_test3.index_template_info;\n# index_template_physical -> index_template_physical_info\nALTER TABLE zh_test.index_template_physical RENAME TO es_manager_test3.index_template_physical_info;\n# arius_resource_logic->project_arius_resource_logic\nALTER TABLE zh_test.arius_resource_logic RENAME TO es_manager_test3.project_arius_resource_logic;\n# app_logic_cluster_auth ->project_logi_cluster_auth\nALTER TABLE zh_test.app_logic_cluster_auth RENAME TO es_manager_test3.project_logi_cluster_auth;\n# metrics_config-》user_metrics_config_info\nALTER TABLE zh_test.metrics_config RENAME TO es_manager_test3.user_metrics_config_info;\n# appid_template_info  -> project_template_info\nALTER TABLE zh_test.appid_template_info RENAME TO es_manager_test3.project_template_info;"
  },
  {
    "path": "arius-admin/deploy_admin.sh",
    "content": "#!/bin/bash\n\ngit pull --rebase\n\nWEB_NAME=arius-admin-rest\n\nsuffix=($(date +%Y%m%d%H%M))\nenvInfo=\n\nif [ $1 ]; then\n    envInfo=\"--spring.profiles.active=\"$1\nelse\n    envInfo=\"--spring.profiles.active=pre\"\nfi\n\necho \"==============\" + $1\n\nif [ ! -d \"output\" ] ; then\n    mkdir output\nfi\n\ncd output\n\nif [ ! -d $WEB_NAME ] ; then\n    mkdir $WEB_NAME\nfi\n\ncd ..\n\nmvn -U clean package  -Dmaven.test.skip=true\n\npid=($(ps -ax|grep -v 'grep'|grep  $WEB_NAME |awk '{print $1}'))\necho  $pid\nif [ ! -n \"$pid\" ]; then\n\techo $WEB_NAME is null\nelse\n\tkill -9 $pid\n\techo $WEB_NAME is stopped\nfi\n\ncp $WEB_NAME/target/$WEB_NAME*.jar output/$WEB_NAME\ncd output/$WEB_NAME\nnohup java -jar $WEB_NAME.jar $envInfo &\ncd ../..\n"
  },
  {
    "path": "arius-admin/didi-java-code-formatter.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<profiles version=\"12\">\n<profile kind=\"CodeFormatterProfile\" name=\"DIDI DC Convention\" version=\"12\">\n<setting id=\"org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.disabling_tag\" value=\"@formatter:off\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_field\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.use_on_off_tags\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_ellipsis\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_multiple_fields\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer\" value=\"18\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_conditional_expression\" value=\"84\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_binary_operator\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_array_initializer\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_after_package\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.continuation_indentation\" value=\"2\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation\" value=\"20\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_binary_operator\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_package\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.source\" value=\"1.7\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_line_comments\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.join_wrapped_lines\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call\" value=\"20\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_member_type\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.align_type_members_on_columns\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation\" value=\"20\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_unary_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.indent_parameter_description\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.lineSplit\" value=\"120\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indentation.size\" value=\"4\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.enabling_tag\" value=\"@formatter:on\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration\" value=\"18\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_assignment\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.problem.assertIdentifier\" value=\"error\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.tabulation.char\" value=\"space\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_statements_compare_to_body\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_method\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration\" value=\"18\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_method_declaration\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_switch\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.problem.enumIdentifier\" value=\"error\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_ellipsis\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_block\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_method_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.compact_else_if\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.indent_root_tags\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_enum_constant\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.tabulation.size\" value=\"4\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration\" value=\"18\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_empty_lines\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_block_in_case\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression\" value=\"20\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.compliance\" value=\"1.7\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer\" value=\"2\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression\" value=\"20\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_unary_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration\" value=\"18\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_binary_expression\" value=\"18\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode\" value=\"enabled\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_label\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant\" value=\"18\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_javadoc_comments\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.line_length\" value=\"80\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_between_import_groups\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_semicolon\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.wrap_before_binary_operator\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_statements_compare_to_block\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration\" value=\"18\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.join_lines_in_comments\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_compact_if\" value=\"16\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_before_imports\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_html\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration\" value=\"18\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_source_code\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration\" value=\"18\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.compiler.codegen.targetPlatform\" value=\"1.7\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_resources_in_try\" value=\"80\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation\" value=\"0\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_header\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.format_block_comments\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.alignment_for_enum_constants\" value=\"2\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.brace_position_for_type_declaration\" value=\"end_of_line\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.blank_lines_after_imports\" value=\"1\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header\" value=\"true\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for\" value=\"insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments\" value=\"do not insert\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column\" value=\"false\"/>\n<setting id=\"org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line\" value=\"false\"/>\n</profile>\n</profiles>\n"
  },
  {
    "path": "arius-admin/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.didichuxing.datachannel</groupId>\n    <artifactId>arius-admin</artifactId>\n    <version>${revision}${sha1}${changelist}</version>\n    <packaging>pom</packaging>\n\n    <modules>\n        <module>arius-admin-persistence</module>\n        <module>arius-admin-common</module>\n        <module>arius-admin-core</module>\n        <module>arius-admin-rest</module>\n        <module>arius-admin-remote</module>\n        <module>arius-admin-task</module>\n        <module>arius-admin-biz</module>\n        <module>arius-admin-metadata</module>\n        <module>arius-admin-integration-test</module>\n    </modules>\n\n    <properties>\n        <revision>1.0.1-SNAPSHOT</revision>\n        <sha1/>\n        <changelist/>\n        <spring.boot.version>2.2.13.RELEASE</spring.boot.version>\n        <spring-restdocs.version>2.0.2.RELEASE</spring-restdocs.version>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n        <java.version>1.8</java.version>\n        <springfox.version>2.9.1</springfox.version>\n        <swagger.version>1.5.21</swagger.version>\n        <mybatis-plus.version>3.4.2</mybatis-plus.version>\n        <maven.compiler.source>1.8</maven.compiler.source>\n        <maven.compiler.target>1.8</maven.compiler.target>\n        <flatten-maven-plugin.version>1.2.2</flatten-maven-plugin.version>\n        <java-diff-utils.version>4.11</java-diff-utils.version>\n        <json-patch.version>1.13</json-patch.version>\n        <kf-log.version>2.0.4</kf-log.version>\n        <kf-elasticsearch-client.version>1.0.1</kf-elasticsearch-client.version>\n        <kf-security.version>1.0.2</kf-security.version>\n        <kf-job.version>2.0.2</kf-job.version>\n    </properties>\n\n    <dependencyManagement>\n\n        <!--logicommon-->\n        <dependencies>\n            <!--diff文本工具-->\n            <dependency>\n                <groupId>com.github.java-json-tools</groupId>\n                <artifactId>json-patch</artifactId>\n                <version>${json-patch.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>io.github.java-diff-utils</groupId>\n                <artifactId>java-diff-utils</artifactId>\n                <version>${java-diff-utils.version}</version>\n            </dependency>\n            <dependency>\n                <version>${kf-security.version}</version>\n                <groupId>io.github.knowstack</groupId>\n                <artifactId>kf-security-spring-boot-starter</artifactId>\n            </dependency>\n            <!-- self -->\n            <dependency>\n                <groupId>com.didichuxing.datachannel</groupId>\n                <artifactId>arius-admin-persistence</artifactId>\n                <version>${revision}${sha1}${changelist}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.didichuxing.datachannel</groupId>\n                <artifactId>arius-admin-core</artifactId>\n                <version>${revision}${sha1}${changelist}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.didichuxing.datachannel</groupId>\n                <artifactId>arius-admin-metadata</artifactId>\n                <version>${revision}${sha1}${changelist}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.didichuxing.datachannel</groupId>\n                <artifactId>arius-admin-common</artifactId>\n                <version>${revision}${sha1}${changelist}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.didichuxing.datachannel</groupId>\n                <artifactId>arius-admin-rest</artifactId>\n                <version>${revision}${sha1}${changelist}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.didichuxing.datachannel</groupId>\n                <artifactId>arius-admin-remote</artifactId>\n                <version>${revision}${sha1}${changelist}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.didichuxing.datachannel</groupId>\n                <artifactId>arius-admin-task</artifactId>\n                <version>${revision}${sha1}${changelist}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.didichuxing.datachannel</groupId>\n                <artifactId>arius-admin-biz</artifactId>\n                <version>${revision}${sha1}${changelist}</version>\n            </dependency>\n\n\n            <dependency>\n                <groupId>javax.servlet</groupId>\n                <artifactId>javax.servlet-api</artifactId>\n                <version>4.0.1</version>\n            </dependency>\n\n            <!-- spring boot -->\n            <dependency>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-dependencies</artifactId>\n                <version>${spring.boot.version}</version>\n                <type>pom</type>\n                <scope>import</scope>\n                <exclusions>\n                    <exclusion>\n                        <groupId>org.elasticsearch</groupId>\n                        <artifactId>elasticsearch</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-starter-web</artifactId>\n                <version>${spring.boot.version}</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>com.fasterxml.jackson.core</groupId>\n                        <artifactId>jackson-databind</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>com.fasterxml.jackson.datatype</groupId>\n                        <artifactId>jackson-datatype-jsr310</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.tomcat.embed</groupId>\n                        <artifactId>tomcat-embed-core</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.hibernate.validator</groupId>\n                        <artifactId>hibernate-validator</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.springframework</groupId>\n                        <artifactId>spring-web</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.springframework</groupId>\n                        <artifactId>spring-webmvc</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.yaml</groupId>\n                        <artifactId>snakeyaml</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>ch.qos.logback</groupId>\n                        <artifactId>logback-classic</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>ch.qos.logback</groupId>\n                        <artifactId>logback-core</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-autoconfigure</artifactId>\n                <version>${spring.boot.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-starter-test</artifactId>\n                <version>${spring.boot.version}</version>\n                <scope>test</scope>\n                <exclusions>\n                    <exclusion>\n                        <groupId>org.junit.jupiter</groupId>\n                        <artifactId>junit-jupiter-api</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>junit</groupId>\n                        <artifactId>junit</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>net.minidev</groupId>\n                        <artifactId>json-smart</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.yaml</groupId>\n                        <artifactId>snakeyaml</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.mockito</groupId>\n                        <artifactId>mockito-core</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.hamcrest</groupId>\n                        <artifactId>hamcrest-core</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.hamcrest</groupId>\n                        <artifactId>hamcrest-library</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <!-- mybatis-plus   https://mp.baomidou.com/guide/ -->\n            <dependency>\n                <groupId>com.baomidou</groupId>\n                <artifactId>mybatis-plus-boot-starter</artifactId>\n                <version>${mybatis-plus.version}</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>org.mybatis</groupId>\n                        <artifactId>mybatis</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>org.mybatis</groupId>\n                <artifactId>mybatis</artifactId>\n                <version>3.5.6</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.hibernate.validator</groupId>\n                <artifactId>hibernate-validator</artifactId>\n                <version>6.1.4.Final</version>\n            </dependency>\n\n            <!-- alibaba -->\n            <dependency>\n                <groupId>com.alibaba</groupId>\n                <artifactId>fastjson</artifactId>\n                <version>1.2.69</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>org.apache.httpcomponents</groupId>\n                        <artifactId>httpclient</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>com.fasterxml.jackson.core</groupId>\n                        <artifactId>jackson-core</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <!-- commons -->\n            <dependency>\n                <groupId>commons-io</groupId>\n                <artifactId>commons-io</artifactId>\n                <version>2.7</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.commons</groupId>\n                <artifactId>commons-lang3</artifactId>\n                <version>3.4</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.commons</groupId>\n                <artifactId>commons-collections4</artifactId>\n                <version>4.1</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.commons</groupId>\n                <artifactId>commons-email</artifactId>\n                <version>1.5</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.google.guava</groupId>\n                <artifactId>guava</artifactId>\n                <version>30.0-jre</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>org.checkerframework</groupId>\n                        <artifactId>checker-qual</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.tomcat.embed</groupId>\n                <artifactId>tomcat-embed-core</artifactId>\n                <version>9.0.55</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.yaml</groupId>\n                <artifactId>snakeyaml</artifactId>\n                <version>1.26</version>\n            </dependency>\n\n            <dependency>\n                <groupId>junit</groupId>\n                <artifactId>junit</artifactId>\n                <version>4.13.2</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.projectlombok</groupId>\n                <artifactId>lombok</artifactId>\n                <version>1.18.16</version>\n            </dependency>\n\n            <dependency>\n                <groupId>net.minidev</groupId>\n                <artifactId>json-smart</artifactId>\n                <version>2.4.7</version>\n            </dependency>\n\n            <!--swagger2 -->\n            <dependency>\n                <groupId>io.springfox</groupId>\n                <artifactId>springfox-swagger2</artifactId>\n                <version>${springfox.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>io.springfox</groupId>\n                <artifactId>springfox-swagger-ui</artifactId>\n                <version>${springfox.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>io.swagger</groupId>\n                <artifactId>swagger-annotations</artifactId>\n                <version>${swagger.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>io.swagger</groupId>\n                <artifactId>swagger-models</artifactId>\n                <version>${swagger.version}</version>\n            </dependency>\n\n            <!--druid -->\n            <dependency>\n                <groupId>com.alibaba</groupId>\n                <artifactId>druid</artifactId>\n                <version>1.0.29</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>com.google.guava</groupId>\n                        <artifactId>guava</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>com.h2database</groupId>\n                        <artifactId>h2</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>com.mchange</groupId>\n                        <artifactId>c3p0</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>mysql</groupId>\n                        <artifactId>mysql-connector-java</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.hibernate</groupId>\n                        <artifactId>hibernate-core</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>org.hibernate</groupId>\n                <artifactId>hibernate-core</artifactId>\n                <version>5.4.24.Final</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.alibaba</groupId>\n                <artifactId>druid-spring-boot-starter</artifactId>\n                <version>1.1.10</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>com.google.protobuf</groupId>\n                        <artifactId>protobuf-java</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>com.h2database</groupId>\n                        <artifactId>h2</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>com.mchange</groupId>\n                        <artifactId>c3p0</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>com.thoughtworks.xstream</groupId>\n                        <artifactId>xstream</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>commons-codec</groupId>\n                        <artifactId>commons-codec</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>javax.servlet</groupId>\n                        <artifactId>jstl</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>mysql</groupId>\n                        <artifactId>mysql-connector-java</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.calcite</groupId>\n                        <artifactId>calcite-core</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.cxf</groupId>\n                        <artifactId>cxf-api</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.cxf</groupId>\n                        <artifactId>cxf-rt-transports-http</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.cxf</groupId>\n                        <artifactId>cxf-rt-bindings-soap</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.httpcomponents</groupId>\n                        <artifactId>httpclient</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.mina</groupId>\n                        <artifactId>mina-core</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.thrift</groupId>\n                        <artifactId>libthrift</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.zookeeper</groupId>\n                        <artifactId>zookeeper</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.hibernate</groupId>\n                        <artifactId>hibernate-core</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.hibernate</groupId>\n                        <artifactId>hibernate-validator</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.mortbay.jetty</groupId>\n                        <artifactId>jetty</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.postgresql</groupId>\n                        <artifactId>postgresql</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>com.alibaba</groupId>\n                        <artifactId>fastjson</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.jboss.netty</groupId>\n                        <artifactId>netty</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>org.mortbay.jetty</groupId>\n                <artifactId>jetty</artifactId>\n                <version>7.0.0.pre5</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.postgresql</groupId>\n                <artifactId>postgresql</artifactId>\n                <version>42.2.13</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.hibernate</groupId>\n                <artifactId>hibernate-validator</artifactId>\n                <version>6.1.4.Final</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.zookeeper</groupId>\n                <artifactId>zookeeper</artifactId>\n                <version>3.5.5</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>io.netty</groupId>\n                        <artifactId>netty-all</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.eclipse.jetty</groupId>\n                        <artifactId>jetty-io</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.eclipse.jetty</groupId>\n                        <artifactId>jetty-server</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>org.eclipse.jetty</groupId>\n                <artifactId>jetty-server</artifactId>\n                <version>11.0.3</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.eclipse.jetty</groupId>\n                <artifactId>jetty-io</artifactId>\n                <version>11.0.2</version>\n            </dependency>\n\n            <dependency>\n                <groupId>io.netty</groupId>\n                <artifactId>netty-all</artifactId>\n                <version>4.1.44.Final</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.thrift</groupId>\n                <artifactId>libthrift</artifactId>\n                <version>0.14.0</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.mina</groupId>\n                <artifactId>mina-core</artifactId>\n                <version>2.1.1</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.httpcomponents</groupId>\n                <artifactId>httpclient</artifactId>\n                <version>4.5.13</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.cxf</groupId>\n                <artifactId>cxf-rt-bindings-soap</artifactId>\n                <version>2.6.2</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.cxf</groupId>\n                <artifactId>cxf-rt-transports-http</artifactId>\n                <version>3.4.1</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.cxf</groupId>\n                <artifactId>cxf-api</artifactId>\n                <version>2.7.11</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.calcite</groupId>\n                <artifactId>calcite-core</artifactId>\n                <version>1.26.0</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>org.apache.commons</groupId>\n                        <artifactId>commons-dbcp2</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.ant</groupId>\n                        <artifactId>ant</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>com.google.guava</groupId>\n                        <artifactId>guava</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.ant</groupId>\n                <artifactId>ant</artifactId>\n                <version>1.10.11</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.commons</groupId>\n                <artifactId>commons-dbcp2</artifactId>\n                <version>2.9.0</version>\n            </dependency>\n\n            <dependency>\n                <groupId>commons-codec</groupId>\n                <artifactId>commons-codec</artifactId>\n                <version>1.14</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.thoughtworks.xstream</groupId>\n                <artifactId>xstream</artifactId>\n                <version>1.4.18</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.google.protobuf</groupId>\n                <artifactId>protobuf-java</artifactId>\n                <version>3.4.0</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.mariadb.jdbc</groupId>\n                <artifactId>mariadb-java-client</artifactId>\n                <version>1.3.0</version>\n            </dependency>\n\n            <dependency>\n                <groupId>joda-time</groupId>\n                <artifactId>joda-time</artifactId>\n                <version>2.8.2</version>\n            </dependency>\n\n            <dependency>\n                <groupId>commons-beanutils</groupId>\n                <artifactId>commons-beanutils</artifactId>\n                <version>1.9.4</version>\n            </dependency>\n\n            <dependency>\n                <groupId>io.minio</groupId>\n                <artifactId>minio</artifactId>\n                <version>7.1.0</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>com.fasterxml.jackson.core</groupId>\n                        <artifactId>jackson-databind</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>com.google.guava</groupId>\n                        <artifactId>guava</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>com.fasterxml.jackson.datatype</groupId>\n                <artifactId>jackson-datatype-jsr310</artifactId>\n                <version>2.9.8</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.commons</groupId>\n                <artifactId>commons-compress</artifactId>\n                <version>1.21</version>\n            </dependency>\n\n            <dependency>\n                <version>${kf-log.version}</version>\n                <groupId>io.github.knowstack</groupId>\n                <artifactId>kf-log</artifactId>\n            </dependency>\n\n            <dependency>\n                <groupId>io.github.knowstack</groupId>\n                <artifactId>kf-elasticsearch-client</artifactId>\n                <version>${kf-elasticsearch-client.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-starter-log4j2</artifactId>\n                <version>2.2.11.RELEASE</version>\n                <exclusions>\n                    <exclusion>\n                        <artifactId>log4j-to-slf4j</artifactId>\n                        <groupId>org.apache.logging.log4j</groupId>\n                    </exclusion>\n                    <exclusion>\n                        <artifactId>log4j-slf4j-impl</artifactId>\n                        <groupId>org.apache.logging.log4j</groupId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>com.lmax</groupId>\n                <artifactId>disruptor</artifactId>\n                <version>3.3.4</version>\n            </dependency>\n\n            <dependency>\n                <groupId>io.github.knowstack</groupId>\n                <artifactId>kf-job-spring-boot-starter</artifactId>\n                <version>${kf-job.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.junit.jupiter</groupId>\n                <artifactId>junit-jupiter-params</artifactId>\n                <version>5.7.2</version>\n                <scope>test</scope>\n            </dependency>\n\n            <dependency>\n                <groupId>org.junit.jupiter</groupId>\n                <artifactId>junit-jupiter-api</artifactId>\n                <version>5.7.2</version>\n                <scope>test</scope>\n            </dependency>\n\n            <dependency>\n                <groupId>org.junit.jupiter</groupId>\n                <artifactId>junit-jupiter-engine</artifactId>\n                <version>5.7.2</version>\n                <scope>test</scope>\n            </dependency>\n\n            <dependency>\n                <groupId>org.mockito</groupId>\n                <artifactId>mockito-core</artifactId>\n                <version>3.7.7</version>\n            </dependency>\n\n            <dependency>\n                <groupId>com.squareup.okhttp3</groupId>\n                <artifactId>okhttp</artifactId>\n                <version>4.2.0</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.reflections</groupId>\n                <artifactId>reflections</artifactId>\n                <version>0.9.11</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-context-support</artifactId>\n                <version>5.3.8</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.httpcomponents</groupId>\n                <artifactId>httpmime</artifactId>\n                <version>4.5.6</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>commons-codec</groupId>\n                        <artifactId>commons-codec</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.apache.httpcomponents</groupId>\n                        <artifactId>httpclient</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-1.2-api</artifactId>\n                <version>2.15.0</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-jul</artifactId>\n                <version>2.15.0</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-core</artifactId>\n                <version>2.15.0</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-api</artifactId>\n                <version>2.15.0</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-jcl</artifactId>\n                <version>2.15.0</version>\n            </dependency>\n\n        </dependencies>\n\n    </dependencyManagement>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-jdbc</artifactId>\n            <version>5.0.9.RELEASE</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.elasticsearch</groupId>\n            <artifactId>elasticsearch</artifactId>\n            <version>2.3.3</version>\n        </dependency>\n\n        <dependency>\n            <groupId>net.java.dev.jna</groupId>\n            <artifactId>jna</artifactId>\n            <version>5.9.0</version>\n        </dependency>\n\n        <dependency>\n            <groupId>net.java.dev.jna</groupId>\n            <artifactId>jna-platform</artifactId>\n            <version>5.9.0</version>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.codehaus.mojo</groupId>\n                <artifactId>flatten-maven-plugin</artifactId>\n                <version>${flatten-maven-plugin.version}</version>\n                <configuration>\n                    <updatePomFile>true</updatePomFile>\n                    <flattenMode>oss</flattenMode>\n                </configuration>\n                <executions>\n                    <execution>\n                        <id>flatten</id>\n                        <phase>process-resources</phase>\n                        <goals>\n                            <goal>flatten</goal>\n                        </goals>\n                    </execution>\n                    <execution>\n                        <id>flatten.clean</id>\n                        <phase>clean</phase>\n                        <goals>\n                            <goal>clean</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n            <plugin>\n                <groupId>org.jacoco</groupId>\n                <artifactId>jacoco-maven-plugin</artifactId>\n                <version>0.8.3</version>\n                <executions>\n                    <execution>\n                        <id>prepare-agent</id>\n                        <goals>\n                            <goal>prepare-agent</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n<!--            <plugin>-->\n<!--                <groupId>net.revelc.code.formatter</groupId>-->\n<!--                <artifactId>formatter-maven-plugin</artifactId>-->\n<!--                <version>2.16.0</version>-->\n<!--            </plugin>-->\n<!--            <plugin>-->\n<!--                <groupId>net.revelc.code.formatter</groupId>-->\n<!--                <artifactId>formatter-maven-plugin</artifactId>-->\n<!--                <executions>-->\n<!--                    <execution>-->\n<!--                        <goals>-->\n<!--                            <goal>format</goal>-->\n<!--                        </goals>-->\n<!--                        <configuration>-->\n<!--                            <configFile>${user.dir}/didi-java-code-formatter.xml</configFile>-->\n<!--                        </configuration>-->\n<!--                    </execution>-->\n<!--                </executions>-->\n<!--            </plugin>-->\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "arius-admin/stop-server.sh",
    "content": "#!/bin/bash\n\nset -x\n\ndate\nsleep 300\n\nps -ef | grep arius-admin-rest | grep -v grep | awk '{print $2}' | xargs kill\nsleep 5\nps -ef | grep arius-admin-rest | grep -v grep | awk '{print $2}' | xargs kill -9\n\njava -jar /lib/java-1.8.0/jacococli.jar report output/arius-admin-rest/coverage-reports/jacoco.exec \\\n --classfiles arius-admin-core/target/classes --sourcefiles arius-admin-core/src/main/java \\\n --classfiles arius-admin-rest/target/classes --sourcefiles arius-admin-rest/src/main/java \\\n --classfiles arius-admin-common/target/classes --sourcefiles arius-admin-common/src/main/java \\\n --classfiles arius-admin-client/target/classes --sourcefiles arius-admin-client/src/main/java \\\n --classfiles arius-admin-persistence/target/classes --sourcefiles arius-admin-persistence/src/main/java \\\n --classfiles arius-admin-remote/target/classes --sourcefiles arius-admin-remote/src/main/java \\\n --html site/ --csv coverage.csv\n# --classfiles arius-admin-task/target/classes --sourcefiles arius-admin-task/src/main/java \\\n\ntar -czf report.tar.gz site/\n"
  },
  {
    "path": "arius-console/.gitignore",
    "content": "*.iml\n.idea/\n.ipr\n.iws\n*~\n~*\n*.diff\n*.bak\n.DS_Store\nThumbs.db\n.project\n.*proj\n.svn/\n*.swp\n*.swo\n*.pyc\n*.pyo\nnode_modules/\nnpm-debug.log\ncoverage\n.cache-loader\npub\npackage-lock.json\n"
  },
  {
    "path": "arius-console/.gitkeep",
    "content": ""
  },
  {
    "path": "arius-console/config/d1-webpack.base.js",
    "content": "/* eslint-disable */\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst ProgressBarPlugin = require('progress-bar-webpack-plugin');\nconst CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');\nconst StatsPlugin = require('stats-webpack-plugin');\nconst { CleanWebpackPlugin } = require('clean-webpack-plugin');\nconst TerserJSPlugin = require('terser-webpack-plugin');\nconst OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');\nconst CopyWebpackPlugin = require('copy-webpack-plugin');\nconst HappyPack = require('happypack');\nconst os = require('os');\nconst happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });\nconst ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');\nconst AutoUpload = require('../plugin/AutoUpload');\nconst AutoUploadConfig = require('../contains');\n\nconst theme = require('./theme');\nvar cwd = process.cwd();\nconst execa = require('execa');\nconst webpack = require('webpack');\nconst path = require('path');\nconst isProd = process.env.NODE_ENV === 'production';\nconst buildPocEnv = process.env.BUILD_ENV === 'poc';\nconst babelOptions = {\n  cacheDirectory: true,\n  babelrc: false,\n  presets: [require.resolve('@babel/preset-env'), require.resolve('@babel/preset-typescript'), require.resolve('@babel/preset-react')],\n  plugins: [\n    [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }],\n    [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }],\n    [require.resolve('@babel/plugin-proposal-private-methods'), { loose: true }],\n    require.resolve('@babel/plugin-proposal-export-default-from'),\n    require.resolve('@babel/plugin-proposal-export-namespace-from'),\n    require.resolve('@babel/plugin-proposal-object-rest-spread'),\n    require.resolve('@babel/plugin-transform-runtime'),\n    require.resolve('@babel/plugin-proposal-optional-chaining'), //\n    require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'), // 解决 ?? 无法转义问题\n    require.resolve('@babel/plugin-proposal-numeric-separator'), // 转义 1_000_000\n    require.resolve('@babel/plugin-transform-modules-commonjs'),\n    !isProd && require.resolve('react-refresh/babel'),\n  ]\n    .filter(Boolean)\n    .concat([\n      [\n        'babel-plugin-import',\n        {\n          libraryName: 'antd',\n          style: true,\n        },\n      ],\n      [\n        \"import\",\n        {\n          libraryName: \"knowdesign\",\n          style: true,\n        },\n        \"knowdesign\"\n      ],\n      '@babel/plugin-transform-object-assign',\n    ]),\n};\n\nfunction getGitBranch() {\n  const res = execa.shellSync('git rev-parse --abbrev-ref HEAD');\n  return res.stdout;\n}\n\nmodule.exports = () => {\n  const manifestName = `manifest.json`;\n  const cssFileName = isProd ? '[name]-[chunkhash].css' : '[name].css';\n\n  const plugins = [\n    new ProgressBarPlugin(),\n    new CaseSensitivePathsPlugin(),\n    new MiniCssExtractPlugin({\n      filename: cssFileName,\n    }),\n    new StatsPlugin(manifestName, {\n      chunkModules: false,\n      source: true,\n      chunks: false,\n      modules: false,\n      assets: true,\n      children: false,\n      exclude: [/node_modules/],\n    }),\n    new HappyPack({\n      id: 'babel',\n      loaders: [\n        'cache-loader',\n        {\n          loader: 'babel-loader',\n          options: babelOptions,\n        },\n      ],\n      threadPool: happyThreadPool,\n    }),\n    !isProd &&\n    new ReactRefreshWebpackPlugin({\n      overlay: false\n    }),\n    // !isProd && new webpack.HotModuleReplacementPlugin(),\n    isProd && new CleanWebpackPlugin(),\n    isProd && new CopyWebpackPlugin({\n      patterns: [{\n        from: path.join(__dirname, '../polyfill'),\n        to: path.join(__dirname, '../pub/es/static'),\n      }, {\n        from: path.join(__dirname, '../favicon.ico'),\n        to: path.join(__dirname, '../pub/es'),\n      }]\n    }),\n    isProd && new webpack.ProvidePlugin({\n      diff_match_patch: [\"diff_match_patch/lib/diff_match_patch\", \"diff_match_patch\"],\n      DIFF_EQUAL: [\"diff_match_patch/lib/diff_match_patch\", \"DIFF_EQUAL\"],\n      DIFF_INSERT: [\"diff_match_patch/lib/diff_match_patch\", \"DIFF_INSERT\"],\n      DIFF_DELETE: [\"diff_match_patch/lib/diff_match_patch\", \"DIFF_DELETE\"],\n    }),\n    // isProd && !buildPocEnv && new AutoUpload(AutoUploadConfig)\n  ].filter(Boolean);\n\n  return {\n    resolve: {\n      extensions: ['.web.jsx', '.web.js', '.ts', '.tsx', '.js', '.jsx', '.json'],\n      alias: {\n        react: path.resolve('./node_modules/react'),\n        // 'react-dom': '@hot-loader/react-dom',\n        '@pkgs': path.resolve(cwd, 'src/d1-packages'),\n        '@interface': path.resolve(cwd, 'src/interface'),\n        'container': path.resolve(cwd, 'src/container'),\n        'component': path.resolve(cwd, 'src/component'),\n        'type': path.resolve(cwd, 'src/@types'),\n        'lib': path.resolve(cwd, 'src/lib'),\n        'store': path.resolve(cwd, 'src/store'),\n        'constants': path.resolve(cwd, 'src/constants'),\n        'styles': path.resolve(cwd, 'src/styles'),\n        'api': path.resolve(cwd, 'src/api'),\n        'actions': path.resolve(cwd, 'src/actions'),\n      },\n    },\n    plugins,\n    module: {\n      rules: [\n        {\n          test: /\\.(js|jsx|ts|tsx)$/,\n          exclude: /node_modules\\/(?!react-intl|@knowdesign\\/kbn-sense)/,\n          use: [\n            {\n              loader: 'happypack/loader?id=babel',\n            },\n          ],\n        },\n        {\n          test: /\\.(png|svg|jpeg|jpg|gif|ttf|woff|woff2|eot|pdf)$/,\n          use: [\n            {\n              loader: 'file-loader',\n              options: isProd ? {\n                name: 'static/[name].[hash:8].[ext]',\n                esModule: false,\n              } : {\n                esModule: false,\n\n              },\n            },\n          ],\n        },\n        {\n          test: /\\.(css|less)$/,\n          use: [\n            {\n              loader: MiniCssExtractPlugin.loader,\n            },\n            'css-loader',\n            {\n              loader: 'less-loader',\n              options: {\n                javascriptEnabled: true,\n                modifyVars: theme,\n              },\n            },\n          ],\n        },\n      ],\n    },\n    optimization: {\n      splitChunks: {\n        cacheGroups: {\n          vendor: {\n            test: /[\\\\/]node_modules[\\\\/]/,\n            chunks: 'all',\n            name: 'vendor',\n            priority: 10,\n            enforce: true,\n            minChunks: 1,\n            maxSize: 27000000,\n          },\n        },\n      },\n      minimizer: isProd ? [\n        new TerserJSPlugin({\n          cache: true,\n          sourceMap: true,\n        }),\n        new OptimizeCSSAssetsPlugin({}),\n      ] : [],\n    },\n    devtool: isProd ? 'cheap-module-source-map' : 'source-map',\n    node: {\n      fs: 'empty',\n      net: 'empty',\n      tls: 'empty',\n    },\n  };\n};\n"
  },
  {
    "path": "arius-console/config/feConfig.json",
    "content": "{\n  \"header\": {\n    \"mode\": \"complicated\",\n    \"logo\": \"../../assets/nav-logo.png\",\n    \"logohref\": \"/dashboard\",\n    \"userIconSrc\": \"../../assets/avatars.png\",\n    \"subTitle\": \"KnowSearch\",\n    \"theme\": \"light\",\n    \"rightEle\": [\n      {\n        \"type\": \"dropdown\",\n        \"scene\": \"admin\",\n        \"children\": [\n          {\n            \"label\": \"多集群管理\",\n            \"icon\": \"icon-duojiqunguanli\",\n            \"href\": \"/es/dasboard\",\n            \"key\": 0\n          },\n          {\n            \"label\": \"系统管理\",\n            \"icon\": \"icon-xitongguanli\",\n            \"href\": \"/es/system\",\n            \"key\": 1\n          }\n        ]\n      },\n      {\n        \"type\": \"dropdown\",\n        \"scene\": \"project\"\n      },\n      {\n        \"type\": \"divider\"\n      },\n      {\n        \"type\": \"icon\",\n        \"scene\": \"fullscreen\"\n      },\n      {\n        \"type\": \"dropdown\",\n        \"scene\": \"user\",\n        \"showUserDrawer\": true\n      }\n    ]\n  }\n}"
  },
  {
    "path": "arius-console/config/theme.js",
    "content": "const config = {\n  primaryColor: '#1473FF',\n  theme: {\n    \"primary-color\": \"#1473FF\",\n    \"border-radius-base\": \"4px\",\n    \"border-radius-sm\": \"2px\",\n    \"font-size-base\": \"14px\",\n    'font-family': 'Helvetica Neue, Helvetica, Arial, PingFang SC, Heiti SC, Hiragino Sans GB, Microsoft YaHei, sans-serif',\n  }\n};\n\nmodule.exports = {\n  \"prefix-cls\": \"es\",\n  ...config.theme,\n};\n"
  },
  {
    "path": "arius-console/config/webpack.dev.config.js",
    "content": "const process = require('process');\nconst StatsPlugin = require('stats-webpack-plugin');\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst webpackConfigResolveAlias = require('./webpackConfigResolveAlias');\nconst BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;\n\nmodule.exports = function getwebpackConfig(webpackConfig) {\n  webpackConfig.resolve.alias = webpackConfigResolveAlias;\n  webpackConfig.resolve.mainFields = ['main', 'module'];\n\n  if (!process.env.Mode) {\n    webpackConfig.output.publicPath = `/`;\n    webpackConfig.output.filename = '[name].js';\n    if (webpackConfig?.module?.rules[2]?.loader == 'url-loader' && webpackConfig?.module?.rules[2]?.options) {\n      webpackConfig.module.rules[2].options = { ...webpackConfig.module.rules[2].options, 'esModule': false }\n    }\n    webpackConfig.plugins = webpackConfig.plugins.filter((plugin) => {\n      if (plugin instanceof MiniCssExtractPlugin) {\n        return false;\n      }\n      return true;\n    });\n    webpackConfig.plugins.push(\n      new MiniCssExtractPlugin({\n        filename: '[name].css',\n        chunkFilename: '[name].css',\n      }),\n      // new BundleAnalyzerPlugin()\n    );\n    const manifestName = `manifest.json`;\n\n    webpackConfig.plugins.push(\n      new StatsPlugin(\n        manifestName,\n        {\n          chunkModules: false,\n          source: true,\n          chunks: false,\n          modules: false,\n          assets: true,\n          children: false,\n          exclude: [/node_modules/]\n        }\n      )\n    )\n  }\n  return webpackConfig;\n};\n"
  },
  {
    "path": "arius-console/contains.js",
    "content": "const AutoUploadConfig = {\n\n  host: '10.96.75.13',\n\n  username: 'root',\n\n  password: \"I*bH79FYM3B\",\n\n  serverDir: '/home/knowsearchtest0312/knowsearch-19670/es'\n}\n\n\n\nmodule.exports = AutoUploadConfig;"
  },
  {
    "path": "arius-console/d1.js",
    "content": "const d1Config = require(\"./d1.json\");\nvar path = require(\"path\");\nvar cwd = process.cwd();\n\nd1Config.appConfig.webpackCustom = {\n  resolve: {\n    alias: {\n      react: path.resolve(\"./node_modules/react\"),\n      container: path.resolve(cwd, \"src/container\"),\n      component: path.resolve(cwd, \"src/component\"),\n      typesPath: path.resolve(cwd, \"src/@types\"),\n      lib: path.resolve(cwd, \"src/lib\"),\n      store: path.resolve(cwd, \"src/store\"),\n      interface: path.resolve(cwd, \"src/interface\"),\n      constants: path.resolve(cwd, \"src/constants\"),\n      styles: path.resolve(cwd, \"src/styles\"),\n      api: path.resolve(cwd, \"src/api\"),\n      actions: path.resolve(cwd, \"src/actions\")\n    },\n  },\n  devServer: {\n    port: 8005,\n    inline: true,\n    proxy: {\n      \"/api/es/admin\": {\n        // target: \"http://10.162.81.178:8010\", // http://10.162.81.178/ // 10.160.46.242 // 172.23.141.2 : 8010\n        target:\n          \"http://api-kylin-xg02.intra.xiaojukeji.com/bigdata_commercial_es_admin_3_test\", // http://10.162.81.178:8010 // http://10.162.81.178/ // 10.160.46.242\n        changeOrigin: true,\n        pathRewrite: {\n          \"^/api/es/admin\": \"/admin/api\",\n        },\n      },\n      \"/api/es/ams\": {\n        target: \"http://api-kylin-xg02.intra.xiaojukeji.com\",\n        changeOrigin: true,\n        pathRewrite: {\n          \"^/api/es/ams\":\n            \"/bigdata_databus_arius_meta_arius_meta_server_test_test/api/es/ams\",\n        },\n      },\n      \"/_sql\": {\n        target: \"http://10.190.10.115:8200\",\n        changeOrigin: true,\n      },\n      \"/console/arius/kibana7\": {\n        target: \"http://10.96.97.90:5602\",\n        pathRewrite: { \"^/console/arius/kibana7\": \"\" },\n      },\n      \"/api/mock\": {\n        target: \"http://172.23.140.112:8010\",\n        pathRewrite: { \"^/api/mock\": \"/admin/api\" },\n        changeOrigin: true,\n      },\n    },\n    historyApiFallback: true,\n    headers: {\n      \"Access-Control-Allow-Origin\": \"*\",\n    },\n  },\n};\nmodule.exports = d1Config;\n"
  },
  {
    "path": "arius-console/d1.json",
    "content": "{\n  \"appConfig\": {\n    \"appName\": \"logi-es-manager-fe\",\n    \"ident\": \"logi-es-manager-fe\",\n    \"theme\": \"./config/theme.js\",\n    \"port\": \"8001\",\n    \"entry\": [\n      {\n        \"title\": \"es\",\n        \"name\": \"es\",\n        \"src\": \"./src/index.tsx\"\n      }\n    ]\n  },\n  \"preset\": \"@didi/d1-preset-opensource\",\n  \"builderType\": \"@didi/d1-preset-opensource\",\n  \"generatorType\": \"@didi/d1-generator-opensource\",\n  \"mockDir\": \"mock\"\n}"
  },
  {
    "path": "arius-console/fetk.config.js",
    "content": "const pkgJson = require(\"./package\");\nconst pre_build = process.env.PRE_BUILD;\n\nmodule.exports = {\n  devEntry: {\n    [pkgJson.systemName]: \"./src/index.tsx\",\n  },\n  buildEntry: {\n    [pkgJson.systemName]: \"./src/index.tsx\",\n  },\n  webpackDevConfig: \"config/webpack.dev.config.js\",\n  webpackBuildConfig: \"config/webpack.build.config.js\",\n  webpackDllConfig: \"config/webpack.dll.config.js\",\n  theme: \"config/theme.js\",\n  template: \"src/index.html\",\n  output: pre_build ? \"dist\" : `pub/${pkgJson.systemName}`,\n  eslintFix: true,\n  hmr: false,\n  port: pkgJson.port,\n  extraBabelPlugins: [\n    [\n      \"import\",\n      {\n        libraryName: \"antd\",\n        style: true,\n      },\n      \"antd\"\n    ],\n    [\n      \"import\",\n      {\n        libraryName: \"knowdesign\",\n        style: true,\n      },\n      \"knowdesign\"\n    ],\n    \"@babel/plugin-transform-object-assign\",\n    \"@babel/plugin-transform-modules-commonjs\",\n    \"@babel/plugin-proposal-optional-chaining\",\n    \"@babel/plugin-proposal-nullish-coalescing-operator\"\n  ],\n  devServer: {\n    inline: true,\n    proxy: {\n      \"/api/es/admin\": {\n        //target: \"https://api-kylin-xg02.intra.xiaojukeji.com/bigdata_commercial_es_admin_master\",\n        //target: \"http://api-kylin-xg02.intra.xiaojukeji.com/bigdata_commercial_es_admin_zh_0.3\",\n        target: \"http://10.96.75.19:19475\",\n        changeOrigin: true,\n        pathRewrite: {\n          \"^/api/es/admin\": \"/admin/api\",\n        },\n      },\n      \"/console/arius/kibana7\": {\n        target: \"http://10.96.64.32:8061\",\n        changeOrigin: true,\n        headers: {\n          'Authorization': \"Basic MTphekFXaUpoeGtobzMzYWM=\"\n        }\n      },\n    },\n    historyApiFallback: true,\n    headers: {\n      \"Access-Control-Allow-Origin\": \"*\",\n    },\n  },\n  jsLoaderExclude:\n    /node_modules\\/(?!react-intl|intl-messageformat|intl-messageformat-parser)/,\n};\n"
  },
  {
    "path": "arius-console/package.json",
    "content": "{\n  \"name\": \"logi-es-manager-fe\",\n  \"systemName\": \"es\",\n  \"version\": \"0.0.1\",\n  \"description\": \"es\",\n  \"main\": \"index.js\",\n  \"preset\": \"@didi/d1-preset-opensource\",\n  \"scripts\": {\n    \"postinstall\": \"patch-package\",\n    \"start\": \"cross-env NODE_ENV=development webpack-dev-server\",\n    \"build\": \"rm -rf ./pub & cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 webpack\",\n    \"build:poc\": \"cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 BUILD_ENV=poc webpack\",\n    \"pre-build\": \"rm -rf ./pub & cross-env PRE_BUILD=true webpack\",\n    \"daily-build\": \"rm -rf ./pub & cross-env PRE_BUILD=true webpack\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://git.xiaojukeji.com/eilenexuzhe/demo.git\"\n  },\n  \"keywords\": [\n    \"es\"\n  ],\n  \"author\": {\n    \"name\": \"eilenexu\"\n  },\n  \"license\": \"ISC\",\n  \"port\": \"8008\",\n  \"ident\": \"es\",\n  \"browserslist\": {\n    \"production\": [\n      \">0.2%\",\n      \"not dead\",\n      \"not ie < 11\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  },\n  \"dependencies\": {\n    \"@babel/polyfill\": \"^7.12.1\",\n    \"@knowdesign/icons\": \"^1.0.0\",\n    \"antd\": \"4.15.0\",\n    \"array-move\": \"^4.0.0\",\n    \"bowser\": \"^2.11.0\",\n    \"classnames\": \"^2.2.6\",\n    \"codemirror\": \"^5.62.0\",\n    \"diff-match-patch\": \"^1.0.5\",\n    \"diff_match_patch\": \"^0.1.1\",\n    \"echarts\": \"^5.1.2\",\n    \"file\": \"^0.2.2\",\n    \"jsencrypt\": \"^3.2.0\",\n    \"jsonlint\": \"^1.6.3\",\n    \"knowdesign\": \"^1.4.0\",\n    \"less\": \"4.1.1\",\n    \"lodash\": \"^4.17.11\",\n    \"moment\": \"^2.24.0\",\n    \"query-string\": \"^5.0.1\",\n    \"react\": \"16.13.0\",\n    \"react-dom\": \"16.13.0\",\n    \"react-intl\": \"^3.2.1\",\n    \"react-router-cache-route\": \"^1.12.1\",\n    \"react-router-dom\": \"4.x\",\n    \"react-sortable-hoc\": \"^2.0.0\",\n    \"react-text-loop\": \"^2.3.0\",\n    \"spark-md5\": \"^3.0.1\"\n  },\n  \"devDependencies\": {\n    \"@ant-design/compatible\": \"^1.0.8\",\n    \"@ant-design/icons\": \"^4.6.2\",\n    \"@babel/core\": \"^7.5.5\",\n    \"@babel/plugin-proposal-class-properties\": \"^7.4.0\",\n    \"@babel/plugin-proposal-decorators\": \"^7.4.0\",\n    \"@babel/plugin-proposal-export-default-from\": \"^7.2.0\",\n    \"@babel/plugin-proposal-export-namespace-from\": \"^7.5.2\",\n    \"@babel/plugin-proposal-nullish-coalescing-operator\": \"^7.14.5\",\n    \"@babel/plugin-proposal-object-rest-spread\": \"^7.4.3\",\n    \"@babel/plugin-proposal-optional-chaining\": \"^7.16.0\",\n    \"@babel/plugin-proposal-private-methods\": \"^7.14.5\",\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.12.1\",\n    \"@babel/plugin-transform-object-assign\": \"^7.12.1\",\n    \"@babel/plugin-transform-runtime\": \"^7.4.3\",\n    \"@babel/preset-env\": \"^7.4.2\",\n    \"@babel/preset-react\": \"^7.0.0\",\n    \"@babel/preset-typescript\": \"^7.14.5\",\n    \"@knowdesign/kbn-sense\": \"1.1.1\",\n    \"@pmmmwh/react-refresh-webpack-plugin\": \"^0.5.1\",\n    \"@types/lodash\": \"^4.14.138\",\n    \"@types/react-dom\": \"^16.9.0\",\n    \"@types/react-router-dom\": \"^4.3.5\",\n    \"@types/react-virtualized\": \"^9.21.12\",\n    \"@typescript-eslint/eslint-plugin\": \"^4.26.0\",\n    \"@typescript-eslint/parser\": \"^4.26.0\",\n    \"axios\": \"^0.19.2\",\n    \"babel-loader\": \"^8.2.2\",\n    \"babel-plugin-import\": \"^1.12.0\",\n    \"cache-loader\": \"^4.1.0\",\n    \"case-sensitive-paths-webpack-plugin\": \"^2.2.0\",\n    \"clean-webpack-plugin\": \"^3.0.0\",\n    \"copy-webpack-plugin\": \"^6.2.1\",\n    \"cross-env\": \"^7.0.3\",\n    \"crypto-js\": \"^4.1.1\",\n    \"css-loader\": \"^2.1.0\",\n    \"echarts\": \"^5.1.2\",\n    \"eslint\": \"7.5.0\",\n    \"eslint-plugin-prettier\": \"3.4.0\",\n    \"eslint-plugin-react\": \"7.22.0\",\n    \"file-loader\": \"^6.0.0\",\n    \"happypack\": \"^5.0.1\",\n    \"html-webpack-plugin\": \"^4.0.0\",\n    \"husky\": \"4.3.7\",\n    \"immer\": \"9.0.1\",\n    \"jquery\": \"3.4.1\",\n    \"less-loader\": \"^4.1.0\",\n    \"lint-staged\": \"10.5.3\",\n    \"mini-css-extract-plugin\": \"^1.3.0\",\n    \"node-ssh\": \"^12.0.0\",\n    \"optimize-css-assets-webpack-plugin\": \"^5.0.1\",\n    \"patch-package\": \"^6.4.7\",\n    \"prettier\": \"2.3.2\",\n    \"progress-bar-webpack-plugin\": \"^1.12.1\",\n    \"react-codemirror2\": \"^7.2.1\",\n    \"react-redux\": \"^7.2.2\",\n    \"react-refresh\": \"^0.10.0\",\n    \"react-text-loop\": \"^2.3.0\",\n    \"react-virtualized\": \"^9.22.3\",\n    \"redux\": \"^4.0.5\",\n    \"redux-thunk\": \"^2.3.0\",\n    \"stats-webpack-plugin\": \"^0.7.0\",\n    \"typescript\": \"^3.5.3\",\n    \"url-loader\": \"^4.1.1\",\n    \"webpack\": \"4.46.0\",\n    \"webpack-bundle-analyzer\": \"^4.7.0\",\n    \"webpack-cli\": \"^3.3.12\",\n    \"webpack-dev-server\": \"3.6.0\",\n    \"webpack-merge\": \"^4.2.1\",\n    \"whatwg-fetch\": \"^3.6.2\"\n  }\n}"
  },
  {
    "path": "arius-console/patches/text-diff+1.0.1.patch",
    "content": "diff --git a/node_modules/text-diff/diff.js b/node_modules/text-diff/diff.js\nindex a5afa51..7108220 100644\n--- a/node_modules/text-diff/diff.js\n+++ b/node_modules/text-diff/diff.js\n@@ -78,8 +78,8 @@ diff.Diff;\n  *     instead.\n  * @return {!Array.<!diff.Diff>} Array of diff tuples.\n  */\n-diff.prototype.main = function(text1, text2, opt_checklines,\n-    opt_deadline) {\n+diff.prototype.main = function (text1, text2, opt_checklines,\n+  opt_deadline) {\n   // Set a deadline by which time the diff must be complete.\n   if (typeof opt_deadline == 'undefined') {\n     if (this.Timeout <= 0) {\n@@ -147,8 +147,8 @@ diff.prototype.main = function(text1, text2, opt_checklines,\n  * @return {!Array.<!diff.Diff>} Array of diff tuples.\n  * @private\n  */\n-diff.prototype.compute_ = function(text1, text2, checklines,\n-    deadline) {\n+diff.prototype.compute_ = function (text1, text2, checklines,\n+  deadline) {\n   var diffs;\n \n   if (!text1) {\n@@ -167,8 +167,8 @@ diff.prototype.compute_ = function(text1, text2, checklines,\n   if (i != -1) {\n     // Shorter text is inside the longer text (speedup).\n     diffs = [[DIFF_INSERT, longtext.substring(0, i)],\n-             [DIFF_EQUAL, shorttext],\n-             [DIFF_INSERT, longtext.substring(i + shorttext.length)]];\n+    [DIFF_EQUAL, shorttext],\n+    [DIFF_INSERT, longtext.substring(i + shorttext.length)]];\n     // Swap insertions for deletions if diff is reversed.\n     if (text1.length > text2.length) {\n       diffs[0][0] = diffs[2][0] = DIFF_DELETE;\n@@ -216,7 +216,7 @@ diff.prototype.compute_ = function(text1, text2, checklines,\n  * @return {!Array.<!diff.Diff>} Array of diff tuples.\n  * @private\n  */\n-diff.prototype.lineMode_ = function(text1, text2, deadline) {\n+diff.prototype.lineMode_ = function (text1, text2, deadline) {\n   // Scan the text on a line-by-line basis first.\n   var a = this.linesToChars_(text1, text2);\n   text1 = a.chars1;\n@@ -253,7 +253,7 @@ diff.prototype.lineMode_ = function(text1, text2, deadline) {\n         if (count_delete >= 1 && count_insert >= 1) {\n           // Delete the offending records and add the merged ones.\n           diffs.splice(pointer - count_delete - count_insert,\n-                       count_delete + count_insert);\n+            count_delete + count_insert);\n           pointer = pointer - count_delete - count_insert;\n           var a = this.main(text_delete, text_insert, false, deadline);\n           for (var j = a.length - 1; j >= 0; j--) {\n@@ -285,7 +285,7 @@ diff.prototype.lineMode_ = function(text1, text2, deadline) {\n  * @return {!Array.<!diff.Diff>} Array of diff tuples.\n  * @private\n  */\n-diff.prototype.bisect_ = function(text1, text2, deadline) {\n+diff.prototype.bisect_ = function (text1, text2, deadline) {\n   // Cache the text lengths to prevent multiple calls.\n   var text1_length = text1.length;\n   var text2_length = text2.length;\n@@ -329,7 +329,7 @@ diff.prototype.bisect_ = function(text1, text2, deadline) {\n       }\n       var y1 = x1 - k1;\n       while (x1 < text1_length && y1 < text2_length &&\n-             text1.charAt(x1) == text2.charAt(y1)) {\n+        text1.charAt(x1) == text2.charAt(y1)) {\n         x1++;\n         y1++;\n       }\n@@ -364,8 +364,8 @@ diff.prototype.bisect_ = function(text1, text2, deadline) {\n       }\n       var y2 = x2 - k2;\n       while (x2 < text1_length && y2 < text2_length &&\n-             text1.charAt(text1_length - x2 - 1) ==\n-             text2.charAt(text2_length - y2 - 1)) {\n+        text1.charAt(text1_length - x2 - 1) ==\n+        text2.charAt(text2_length - y2 - 1)) {\n         x2++;\n         y2++;\n       }\n@@ -408,8 +408,8 @@ diff.prototype.bisect_ = function(text1, text2, deadline) {\n  * @return {!Array.<!diff.Diff>} Array of diff tuples.\n  * @private\n  */\n-diff.prototype.bisectSplit_ = function(text1, text2, x, y,\n-    deadline) {\n+diff.prototype.bisectSplit_ = function (text1, text2, x, y,\n+  deadline) {\n   var text1a = text1.substring(0, x);\n   var text2a = text2.substring(0, y);\n   var text1b = text1.substring(x);\n@@ -434,7 +434,7 @@ diff.prototype.bisectSplit_ = function(text1, text2, x, y,\n  *     The zeroth element of the array of unique strings is intentionally blank.\n  * @private\n  */\n-diff.prototype.linesToChars_ = function(text1, text2) {\n+diff.prototype.linesToChars_ = function (text1, text2) {\n   var lineArray = [];  // e.g. lineArray[4] == 'Hello\\n'\n   var lineHash = {};   // e.g. lineHash['Hello\\n'] == 4\n \n@@ -468,7 +468,7 @@ diff.prototype.linesToChars_ = function(text1, text2) {\n       lineStart = lineEnd + 1;\n \n       if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) :\n-          (lineHash[line] !== undefined)) {\n+        (lineHash[line] !== undefined)) {\n         chars += String.fromCharCode(lineHash[line]);\n       } else {\n         chars += String.fromCharCode(lineArrayLength);\n@@ -481,7 +481,7 @@ diff.prototype.linesToChars_ = function(text1, text2) {\n \n   var chars1 = diff_linesToCharsMunge_(text1);\n   var chars2 = diff_linesToCharsMunge_(text2);\n-  return {chars1: chars1, chars2: chars2, lineArray: lineArray};\n+  return { chars1: chars1, chars2: chars2, lineArray: lineArray };\n };\n \n \n@@ -492,7 +492,7 @@ diff.prototype.linesToChars_ = function(text1, text2) {\n  * @param {!Array.<string>} lineArray Array of unique strings.\n  * @private\n  */\n-diff.prototype.charsToLines_ = function(diffs, lineArray) {\n+diff.prototype.charsToLines_ = function (diffs, lineArray) {\n   for (var x = 0; x < diffs.length; x++) {\n     var chars = diffs[x][1];\n     var text = [];\n@@ -511,7 +511,7 @@ diff.prototype.charsToLines_ = function(diffs, lineArray) {\n  * @return {number} The number of characters common to the start of each\n  *     string.\n  */\n-diff.prototype.commonPrefix = function(text1, text2) {\n+diff.prototype.commonPrefix = function (text1, text2) {\n   // Quick check for common null cases.\n   if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) {\n     return 0;\n@@ -524,7 +524,7 @@ diff.prototype.commonPrefix = function(text1, text2) {\n   var pointerstart = 0;\n   while (pointermin < pointermid) {\n     if (text1.substring(pointerstart, pointermid) ==\n-        text2.substring(pointerstart, pointermid)) {\n+      text2.substring(pointerstart, pointermid)) {\n       pointermin = pointermid;\n       pointerstart = pointermin;\n     } else {\n@@ -542,10 +542,10 @@ diff.prototype.commonPrefix = function(text1, text2) {\n  * @param {string} text2 Second string.\n  * @return {number} The number of characters common to the end of each string.\n  */\n-diff.prototype.commonSuffix = function(text1, text2) {\n+diff.prototype.commonSuffix = function (text1, text2) {\n   // Quick check for common null cases.\n   if (!text1 || !text2 ||\n-      text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) {\n+    text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) {\n     return 0;\n   }\n   // Binary search.\n@@ -556,7 +556,7 @@ diff.prototype.commonSuffix = function(text1, text2) {\n   var pointerend = 0;\n   while (pointermin < pointermid) {\n     if (text1.substring(text1.length - pointermid, text1.length - pointerend) ==\n-        text2.substring(text2.length - pointermid, text2.length - pointerend)) {\n+      text2.substring(text2.length - pointermid, text2.length - pointerend)) {\n       pointermin = pointermid;\n       pointerend = pointermin;\n     } else {\n@@ -576,7 +576,7 @@ diff.prototype.commonSuffix = function(text1, text2) {\n  *     string and the start of the second string.\n  * @private\n  */\n-diff.prototype.commonOverlap_ = function(text1, text2) {\n+diff.prototype.commonOverlap_ = function (text1, text2) {\n   // Cache the text lengths to prevent multiple calls.\n   var text1_length = text1.length;\n   var text2_length = text2.length;\n@@ -609,7 +609,7 @@ diff.prototype.commonOverlap_ = function(text1, text2) {\n     }\n     length += found;\n     if (found == 0 || text1.substring(text_length - length) ==\n-        text2.substring(0, length)) {\n+      text2.substring(0, length)) {\n       best = length;\n       length++;\n     }\n@@ -628,7 +628,7 @@ diff.prototype.commonOverlap_ = function(text1, text2) {\n  *     text2 and the common middle.  Or null if there was no match.\n  * @private\n  */\n-diff.prototype.halfMatch_ = function(text1, text2) {\n+diff.prototype.halfMatch_ = function (text1, text2) {\n   if (this.Timeout <= 0) {\n     // Don't risk returning a non-optimal diff if we have unlimited time.\n     return null;\n@@ -660,12 +660,12 @@ diff.prototype.halfMatch_ = function(text1, text2) {\n     var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;\n     while ((j = shorttext.indexOf(seed, j + 1)) != -1) {\n       var prefixLength = dmp.commonPrefix(longtext.substring(i),\n-                                          shorttext.substring(j));\n+        shorttext.substring(j));\n       var suffixLength = dmp.commonSuffix(longtext.substring(0, i),\n-                                          shorttext.substring(0, j));\n+        shorttext.substring(0, j));\n       if (best_common.length < suffixLength + prefixLength) {\n         best_common = shorttext.substring(j - suffixLength, j) +\n-            shorttext.substring(j, j + prefixLength);\n+          shorttext.substring(j, j + prefixLength);\n         best_longtext_a = longtext.substring(0, i - suffixLength);\n         best_longtext_b = longtext.substring(i + prefixLength);\n         best_shorttext_a = shorttext.substring(0, j - suffixLength);\n@@ -674,7 +674,7 @@ diff.prototype.halfMatch_ = function(text1, text2) {\n     }\n     if (best_common.length * 2 >= longtext.length) {\n       return [best_longtext_a, best_longtext_b,\n-              best_shorttext_a, best_shorttext_b, best_common];\n+        best_shorttext_a, best_shorttext_b, best_common];\n     } else {\n       return null;\n     }\n@@ -682,10 +682,10 @@ diff.prototype.halfMatch_ = function(text1, text2) {\n \n   // First check if the second quarter is the seed for a half-match.\n   var hm1 = diff_halfMatchI_(longtext, shorttext,\n-                             Math.ceil(longtext.length / 4));\n+    Math.ceil(longtext.length / 4));\n   // Check again based on the third quarter.\n   var hm2 = diff_halfMatchI_(longtext, shorttext,\n-                             Math.ceil(longtext.length / 2));\n+    Math.ceil(longtext.length / 2));\n   var hm;\n   if (!hm1 && !hm2) {\n     return null;\n@@ -720,7 +720,7 @@ diff.prototype.halfMatch_ = function(text1, text2) {\n  * Reduce the number of edits by eliminating semantically trivial equalities.\n  * @param {!Array.<!diff.Diff>} diffs Array of diff tuples.\n  */\n-diff.prototype.cleanupSemantic = function(diffs) {\n+diff.prototype.cleanupSemantic = function (diffs) {\n   var changes = false;\n   var equalities = [];  // Stack of indices where equalities are found.\n   var equalitiesLength = 0;  // Keeping our own length var is faster in JS.\n@@ -751,12 +751,12 @@ diff.prototype.cleanupSemantic = function(diffs) {\n       // Eliminate an equality that is smaller or equal to the edits on both\n       // sides of it.\n       if (lastequality && (lastequality.length <=\n-          Math.max(length_insertions1, length_deletions1)) &&\n-          (lastequality.length <= Math.max(length_insertions2,\n-                                           length_deletions2))) {\n+        Math.max(length_insertions1, length_deletions1)) &&\n+        (lastequality.length <= Math.max(length_insertions2,\n+          length_deletions2))) {\n         // Duplicate record.\n         diffs.splice(equalities[equalitiesLength - 1], 0,\n-                     [DIFF_DELETE, lastequality]);\n+          [DIFF_DELETE, lastequality]);\n         // Change second copy to insert.\n         diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;\n         // Throw away the equality we just deleted.\n@@ -790,35 +790,35 @@ diff.prototype.cleanupSemantic = function(diffs) {\n   pointer = 1;\n   while (pointer < diffs.length) {\n     if (diffs[pointer - 1][0] == DIFF_DELETE &&\n-        diffs[pointer][0] == DIFF_INSERT) {\n+      diffs[pointer][0] == DIFF_INSERT) {\n       var deletion = diffs[pointer - 1][1];\n       var insertion = diffs[pointer][1];\n       var overlap_length1 = this.commonOverlap_(deletion, insertion);\n       var overlap_length2 = this.commonOverlap_(insertion, deletion);\n       if (overlap_length1 >= overlap_length2) {\n         if (overlap_length1 >= deletion.length / 2 ||\n-            overlap_length1 >= insertion.length / 2) {\n+          overlap_length1 >= insertion.length / 2) {\n           // Overlap found.  Insert an equality and trim the surrounding edits.\n           diffs.splice(pointer, 0,\n-              [DIFF_EQUAL, insertion.substring(0, overlap_length1)]);\n+            [DIFF_EQUAL, insertion.substring(0, overlap_length1)]);\n           diffs[pointer - 1][1] =\n-              deletion.substring(0, deletion.length - overlap_length1);\n+            deletion.substring(0, deletion.length - overlap_length1);\n           diffs[pointer + 1][1] = insertion.substring(overlap_length1);\n           pointer++;\n         }\n       } else {\n         if (overlap_length2 >= deletion.length / 2 ||\n-            overlap_length2 >= insertion.length / 2) {\n+          overlap_length2 >= insertion.length / 2) {\n           // Reverse overlap found.\n           // Insert an equality and swap and trim the surrounding edits.\n           diffs.splice(pointer, 0,\n-              [DIFF_EQUAL, deletion.substring(0, overlap_length2)]);\n+            [DIFF_EQUAL, deletion.substring(0, overlap_length2)]);\n           diffs[pointer - 1][0] = DIFF_INSERT;\n           diffs[pointer - 1][1] =\n-              insertion.substring(0, insertion.length - overlap_length2);\n+            insertion.substring(0, insertion.length - overlap_length2);\n           diffs[pointer + 1][0] = DIFF_DELETE;\n           diffs[pointer + 1][1] =\n-              deletion.substring(overlap_length2);\n+            deletion.substring(overlap_length2);\n           pointer++;\n         }\n       }\n@@ -835,7 +835,7 @@ diff.prototype.cleanupSemantic = function(diffs) {\n  * e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.\n  * @param {!Array.<!diff.Diff>} diffs Array of diff tuples.\n  */\n-diff.prototype.cleanupSemanticLossless = function(diffs) {\n+diff.prototype.cleanupSemanticLossless = function (diffs) {\n   /**\n    * Given two strings, compute a score representing whether the internal\n    * boundary falls on logical boundaries.\n@@ -862,17 +862,17 @@ diff.prototype.cleanupSemanticLossless = function(diffs) {\n     var nonAlphaNumeric1 = char1.match(diff.nonAlphaNumericRegex_);\n     var nonAlphaNumeric2 = char2.match(diff.nonAlphaNumericRegex_);\n     var whitespace1 = nonAlphaNumeric1 &&\n-        char1.match(diff.whitespaceRegex_);\n+      char1.match(diff.whitespaceRegex_);\n     var whitespace2 = nonAlphaNumeric2 &&\n-        char2.match(diff.whitespaceRegex_);\n+      char2.match(diff.whitespaceRegex_);\n     var lineBreak1 = whitespace1 &&\n-        char1.match(diff.linebreakRegex_);\n+      char1.match(diff.linebreakRegex_);\n     var lineBreak2 = whitespace2 &&\n-        char2.match(diff.linebreakRegex_);\n+      char2.match(diff.linebreakRegex_);\n     var blankLine1 = lineBreak1 &&\n-        one.match(diff.blanklineEndRegex_);\n+      one.match(diff.blanklineEndRegex_);\n     var blankLine2 = lineBreak2 &&\n-        two.match(diff.blanklineStartRegex_);\n+      two.match(diff.blanklineStartRegex_);\n \n     if (blankLine1 || blankLine2) {\n       // Five points for blank lines.\n@@ -897,7 +897,7 @@ diff.prototype.cleanupSemanticLossless = function(diffs) {\n   // Intentionally ignore the first and last element (don't need checking).\n   while (pointer < diffs.length - 1) {\n     if (diffs[pointer - 1][0] == DIFF_EQUAL &&\n-        diffs[pointer + 1][0] == DIFF_EQUAL) {\n+      diffs[pointer + 1][0] == DIFF_EQUAL) {\n       // This is a single edit surrounded by equalities.\n       var equality1 = diffs[pointer - 1][1];\n       var edit = diffs[pointer][1];\n@@ -917,13 +917,13 @@ diff.prototype.cleanupSemanticLossless = function(diffs) {\n       var bestEdit = edit;\n       var bestEquality2 = equality2;\n       var bestScore = diff_cleanupSemanticScore_(equality1, edit) +\n-          diff_cleanupSemanticScore_(edit, equality2);\n+        diff_cleanupSemanticScore_(edit, equality2);\n       while (edit.charAt(0) === equality2.charAt(0)) {\n         equality1 += edit.charAt(0);\n         edit = edit.substring(1) + equality2.charAt(0);\n         equality2 = equality2.substring(1);\n         var score = diff_cleanupSemanticScore_(equality1, edit) +\n-            diff_cleanupSemanticScore_(edit, equality2);\n+          diff_cleanupSemanticScore_(edit, equality2);\n         // The >= encourages trailing rather than leading whitespace on edits.\n         if (score >= bestScore) {\n           bestScore = score;\n@@ -965,7 +965,7 @@ diff.blanklineStartRegex_ = /^\\r?\\n\\r?\\n/;\n  * Reduce the number of edits by eliminating operationally trivial equalities.\n  * @param {!Array.<!diff.Diff>} diffs Array of diff tuples.\n  */\n-diff.prototype.cleanupEfficiency = function(diffs) {\n+diff.prototype.cleanupEfficiency = function (diffs) {\n   var changes = false;\n   var equalities = [];  // Stack of indices where equalities are found.\n   var equalitiesLength = 0;  // Keeping our own length var is faster in JS.\n@@ -984,7 +984,7 @@ diff.prototype.cleanupEfficiency = function(diffs) {\n   while (pointer < diffs.length) {\n     if (diffs[pointer][0] == DIFF_EQUAL) {  // Equality found.\n       if (diffs[pointer][1].length < this.EditCost &&\n-          (post_ins || post_del)) {\n+        (post_ins || post_del)) {\n         // Candidate found.\n         equalities[equalitiesLength++] = pointer;\n         pre_ins = post_ins;\n@@ -1011,11 +1011,11 @@ diff.prototype.cleanupEfficiency = function(diffs) {\n        * <ins>A</ins><del>B</del>X<del>C</del>\n        */\n       if (lastequality && ((pre_ins && pre_del && post_ins && post_del) ||\n-                           ((lastequality.length < this.EditCost / 2) &&\n-                            (pre_ins + pre_del + post_ins + post_del) == 3))) {\n+        ((lastequality.length < this.EditCost / 2) &&\n+          (pre_ins + pre_del + post_ins + post_del) == 3))) {\n         // Duplicate record.\n         diffs.splice(equalities[equalitiesLength - 1], 0,\n-                     [DIFF_DELETE, lastequality]);\n+          [DIFF_DELETE, lastequality]);\n         // Change second copy to insert.\n         diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;\n         equalitiesLength--;  // Throw away the equality we just deleted;\n@@ -1027,7 +1027,7 @@ diff.prototype.cleanupEfficiency = function(diffs) {\n         } else {\n           equalitiesLength--;  // Throw away the previous equality.\n           pointer = equalitiesLength > 0 ?\n-              equalities[equalitiesLength - 1] : -1;\n+            equalities[equalitiesLength - 1] : -1;\n           post_ins = post_del = false;\n         }\n         changes = true;\n@@ -1047,7 +1047,7 @@ diff.prototype.cleanupEfficiency = function(diffs) {\n  * Any edit section can move as long as it doesn't cross an equality.\n  * @param {!Array.<!diff.Diff>} diffs Array of diff tuples.\n  */\n-diff.prototype.cleanupMerge = function(diffs) {\n+diff.prototype.cleanupMerge = function (diffs) {\n   diffs.push([DIFF_EQUAL, '']);  // Add a dummy entry at the end.\n   var pointer = 0;\n   var count_delete = 0;\n@@ -1075,13 +1075,13 @@ diff.prototype.cleanupMerge = function(diffs) {\n             commonlength = this.commonPrefix(text_insert, text_delete);\n             if (commonlength !== 0) {\n               if ((pointer - count_delete - count_insert) > 0 &&\n-                  diffs[pointer - count_delete - count_insert - 1][0] ==\n-                  DIFF_EQUAL) {\n+                diffs[pointer - count_delete - count_insert - 1][0] ==\n+                DIFF_EQUAL) {\n                 diffs[pointer - count_delete - count_insert - 1][1] +=\n-                    text_insert.substring(0, commonlength);\n+                  text_insert.substring(0, commonlength);\n               } else {\n                 diffs.splice(0, 0, [DIFF_EQUAL,\n-                                    text_insert.substring(0, commonlength)]);\n+                  text_insert.substring(0, commonlength)]);\n                 pointer++;\n               }\n               text_insert = text_insert.substring(commonlength);\n@@ -1091,27 +1091,27 @@ diff.prototype.cleanupMerge = function(diffs) {\n             commonlength = this.commonSuffix(text_insert, text_delete);\n             if (commonlength !== 0) {\n               diffs[pointer][1] = text_insert.substring(text_insert.length -\n-                  commonlength) + diffs[pointer][1];\n+                commonlength) + diffs[pointer][1];\n               text_insert = text_insert.substring(0, text_insert.length -\n-                  commonlength);\n+                commonlength);\n               text_delete = text_delete.substring(0, text_delete.length -\n-                  commonlength);\n+                commonlength);\n             }\n           }\n           // Delete the offending records and add the merged ones.\n           if (count_delete === 0) {\n             diffs.splice(pointer - count_insert,\n-                count_delete + count_insert, [DIFF_INSERT, text_insert]);\n+              count_delete + count_insert, [DIFF_INSERT, text_insert]);\n           } else if (count_insert === 0) {\n             diffs.splice(pointer - count_delete,\n-                count_delete + count_insert, [DIFF_DELETE, text_delete]);\n+              count_delete + count_insert, [DIFF_DELETE, text_delete]);\n           } else {\n             diffs.splice(pointer - count_delete - count_insert,\n-                count_delete + count_insert, [DIFF_DELETE, text_delete],\n-                [DIFF_INSERT, text_insert]);\n+              count_delete + count_insert, [DIFF_DELETE, text_delete],\n+              [DIFF_INSERT, text_insert]);\n           }\n           pointer = pointer - count_delete - count_insert +\n-                    (count_delete ? 1 : 0) + (count_insert ? 1 : 0) + 1;\n+            (count_delete ? 1 : 0) + (count_insert ? 1 : 0) + 1;\n         } else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) {\n           // Merge this equality with the previous one.\n           diffs[pointer - 1][1] += diffs[pointer][1];\n@@ -1138,24 +1138,24 @@ diff.prototype.cleanupMerge = function(diffs) {\n   // Intentionally ignore the first and last element (don't need checking).\n   while (pointer < diffs.length - 1) {\n     if (diffs[pointer - 1][0] == DIFF_EQUAL &&\n-        diffs[pointer + 1][0] == DIFF_EQUAL) {\n+      diffs[pointer + 1][0] == DIFF_EQUAL) {\n       // This is a single edit surrounded by equalities.\n       if (diffs[pointer][1].substring(diffs[pointer][1].length -\n-          diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) {\n+        diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) {\n         // Shift the edit over the previous equality.\n         diffs[pointer][1] = diffs[pointer - 1][1] +\n-            diffs[pointer][1].substring(0, diffs[pointer][1].length -\n-                                        diffs[pointer - 1][1].length);\n+          diffs[pointer][1].substring(0, diffs[pointer][1].length -\n+            diffs[pointer - 1][1].length);\n         diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];\n         diffs.splice(pointer - 1, 1);\n         changes = true;\n       } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) ==\n-          diffs[pointer + 1][1]) {\n+        diffs[pointer + 1][1]) {\n         // Shift the edit over the next equality.\n         diffs[pointer - 1][1] += diffs[pointer + 1][1];\n         diffs[pointer][1] =\n-            diffs[pointer][1].substring(diffs[pointer + 1][1].length) +\n-            diffs[pointer + 1][1];\n+          diffs[pointer][1].substring(diffs[pointer + 1][1].length) +\n+          diffs[pointer + 1][1];\n         diffs.splice(pointer + 1, 1);\n         changes = true;\n       }\n@@ -1177,7 +1177,7 @@ diff.prototype.cleanupMerge = function(diffs) {\n  * @param {number} loc Location within text1.\n  * @return {number} Location within text2.\n  */\n-diff.prototype.xIndex = function(diffs, loc) {\n+diff.prototype.xIndex = function (diffs, loc) {\n   var chars1 = 0;\n   var chars2 = 0;\n   var last_chars1 = 0;\n@@ -1210,7 +1210,7 @@ diff.prototype.xIndex = function(diffs, loc) {\n  * @param {!Array.<!diff.Diff>} diffs Array of diff tuples.\n  * @return {string} HTML representation.\n  */\n-diff.prototype.prettyHtml = function(diffs) {\n+diff.prototype.prettyHtml = function (diffs) {\n   var html = [];\n   var pattern_amp = /&/g;\n   var pattern_lt = /</g;\n@@ -1220,7 +1220,7 @@ diff.prototype.prettyHtml = function(diffs) {\n     var op = diffs[x][0];    // Operation (insert, delete, equal)\n     var data = diffs[x][1];  // Text of change.\n     var text = data.replace(pattern_amp, '&amp;').replace(pattern_lt, '&lt;')\n-        .replace(pattern_gt, '&gt;').replace(pattern_br, '<br/>');\n+      .replace(pattern_gt, '&gt;').replace(pattern_br, '<br/>');\n     switch (op) {\n       case DIFF_INSERT:\n         html[x] = '<ins>' + text + '</ins>';\n@@ -1242,7 +1242,7 @@ diff.prototype.prettyHtml = function(diffs) {\n  * @param {!Array.<!diff.Diff>} diffs Array of diff tuples.\n  * @return {string} Source text.\n  */\n-diff.prototype.text1 = function(diffs) {\n+diff.prototype.text1 = function (diffs) {\n   var text = [];\n   for (var x = 0; x < diffs.length; x++) {\n     if (diffs[x][0] !== DIFF_INSERT) {\n@@ -1258,7 +1258,7 @@ diff.prototype.text1 = function(diffs) {\n  * @param {!Array.<!diff.Diff>} diffs Array of diff tuples.\n  * @return {string} Destination text.\n  */\n-diff.prototype.text2 = function(diffs) {\n+diff.prototype.text2 = function (diffs) {\n   var text = [];\n   for (var x = 0; x < diffs.length; x++) {\n     if (diffs[x][0] !== DIFF_DELETE) {\n@@ -1275,7 +1275,7 @@ diff.prototype.text2 = function(diffs) {\n  * @param {!Array.<!diff.Diff>} diffs Array of diff tuples.\n  * @return {number} Number of changes.\n  */\n-diff.prototype.levenshtein = function(diffs) {\n+diff.prototype.levenshtein = function (diffs) {\n   var levenshtein = 0;\n   var insertions = 0;\n   var deletions = 0;\n@@ -1310,7 +1310,7 @@ diff.prototype.levenshtein = function(diffs) {\n  * @param {!Array.<!diff.Diff>} diffs Array of diff tuples.\n  * @return {string} Delta text.\n  */\n-diff.prototype.toDelta = function(diffs) {\n+diff.prototype.toDelta = function (diffs) {\n   var text = [];\n   for (var x = 0; x < diffs.length; x++) {\n     switch (diffs[x][0]) {\n@@ -1337,7 +1337,7 @@ diff.prototype.toDelta = function(diffs) {\n  * @return {!Array.<!diff.Diff>} Array of diff tuples.\n  * @throws {!Error} If invalid input.\n  */\n-diff.prototype.fromDelta = function(text1, delta) {\n+diff.prototype.fromDelta = function (text1, delta) {\n   var diffs = [];\n   var diffsLength = 0;  // Keeping our own length var is faster in JS.\n   var pointer = 0;  // Cursor in text1\n@@ -1356,7 +1356,7 @@ diff.prototype.fromDelta = function(text1, delta) {\n         }\n         break;\n       case '-':\n-        // Fall through.\n+      // Fall through.\n       case '=':\n         var n = parseInt(param, 10);\n         if (isNaN(n) || n < 0) {\n@@ -1374,13 +1374,13 @@ diff.prototype.fromDelta = function(text1, delta) {\n         // Anything else is an error.\n         if (tokens[x]) {\n           throw new Error('Invalid diff operation in diff_fromDelta: ' +\n-                          tokens[x]);\n+            tokens[x]);\n         }\n     }\n   }\n   if (pointer != text1.length) {\n     throw new Error('Delta length (' + pointer +\n-        ') does not equal source text length (' + text1.length + ').');\n+      ') does not equal source text length (' + text1.length + ').');\n   }\n   return diffs;\n };\n@@ -1390,9 +1390,10 @@ diff.prototype.fromDelta = function(text1, delta) {\n // In a browser, 'this' will be 'window'.\n // Users of node.js should 'require' the uncompressed version since Google's\n // JS compiler may break the following exports for non-browser environments.\n-this['diff'] = diff;\n-this['DIFF_DELETE'] = DIFF_DELETE;\n-this['DIFF_INSERT'] = DIFF_INSERT;\n-this['DIFF_EQUAL'] = DIFF_EQUAL;\n+var _this = this || window || {};\n+_this['diff'] = diff;\n+_this['DIFF_DELETE'] = DIFF_DELETE;\n+_this['DIFF_INSERT'] = DIFF_INSERT;\n+_this['DIFF_EQUAL'] = DIFF_EQUAL;\n \n module.exports = diff;\n"
  },
  {
    "path": "arius-console/plugin/AutoUpload.js",
    "content": "const { NodeSSH } = require('node-ssh');\n\nclass AutoUpload {\n\n  constructor(option) {\n    this.ssh = new NodeSSH();\n    this.option = option;\n  }\n\n  async connectServer() {\n    try {\n      await this.ssh.connect({\n        host: this.option.host,\n        username: this.option.username,\n        password: this.option.password\n      });\n      console.log('链接成功');\n    } catch (error) {\n      console.log('链接失败');\n    }\n  }\n\n  async uploadFiles(localPath, remotePath) {\n    try {\n      const status = await this.ssh.putDirectory(localPath, remotePath, {\n        // 递归上传\n        recursive: true,\n        // 并发数\n        concurrency: 10\n      });\n      await this.ssh.putFile(__dirname.replace('plugin', 'favicon.ico'), `${remotePath}/favicon.ico`)\n      console.log(`上传${status ? '成功' : '失败'}!!!`);\n    } catch (error) {\n      console.log(`上传失败`);\n    }\n  }\n\n  apply(compiler) {\n    compiler.hooks.afterEmit.tapAsync(\"AutoUpload\", async (compilation, callback) => {\n      // 1. 获取输出文件夹\n      const outputPath = compilation.outputOptions.path\n      // 2. 连接服务器(SSH)\n      await this.connectServer();\n      // 3. 删除原来目录中的内容\n      const serverDir = this.option.serverDir;\n      await this.ssh.execCommand(`rm -rf ${serverDir}/*`);\n      // 4. 上传文件到服务器\n      await this.uploadFiles(outputPath, serverDir);\n      // 5. 关闭 ssh\n      this.ssh.dispose();\n      callback();\n    })\n  }\n}\n\nmodule.exports = AutoUpload;"
  },
  {
    "path": "arius-console/readme.md",
    "content": "## Environment Support\n\n- Modern browsers and Internet Explorer 11\n- node V10+\n\n## Getting Started\n\n### install\n\n```js\n  npm install\n```\n\nor\n\n```js\nyarn;\n```\n\n### Development\n\n#### start\n\n```js\n  npm run start\n```\n\nor\n\n```js\n  yarn start\n```\n\n#### access\n\nhttp://localhost:8002/es\n\n### Build\n\n```js\n  npm run build\n```\n\nor\n\n```js\n  yarn run build\n```\n\n## FAQ\n\n**Q:** 本地启动后页面请求接口不正确怎么办?\n**A:** 确认 fetk.config.js 中 devServer.proxy 配置的接口代理地址是否正确\n**Q:** 体验环境登录页账号密码是什么?\n**A:** admin/admin123\n**Q:** 执行 build 之后的包在哪里?\n**A:** 当前项目 arius-console 目录下 pub 文件夹中.\n"
  },
  {
    "path": "arius-console/src/@types/base-types.ts",
    "content": "export type HttpMethod = 'POST' | 'PUT' | 'GET' | 'DELETE';\n\nexport interface IFilter {\n  text: string;\n  value: string;\n}\n\nexport interface IDeteilId {\n  id: number;\n}\n\nexport interface ILabelValue {\n  disabled?: boolean;\n  value: string | number;\n  label?: string;\n  name?: string;\n  key?: number;\n  text?: string;\n  title?: string;\n}\n\nexport interface IStatusMap {\n  [key: number]: string;\n}\n\nexport interface ILeftMenu {\n  href: string;\n  i: string;\n  title: string;\n  className?: string;\n  hide?: boolean;\n  class?: string;\n  status?: string;\n  children?: ILeftMenu[];\n}\n\nexport interface IMenuItem {\n  name?: string;\n  key: string;\n  show?: boolean;\n  type?: number;\n  label?: string;\n  visible?: boolean;\n  content?: (data: any) => JSX.Element;\n}\n\nexport interface IBaseInfo {\n  key: string;\n  label: string;\n  unit?: string;\n  invisible?: boolean;\n  render?: (text: any) => any;\n}\n\nexport interface IUNSpecificInfo {\n  [key: string]: any;\n}\n\nexport interface IStringMap {\n  [key: string]: string;\n}\n\nexport interface IStringArray {\n  [key: string]: string[];\n}\n\ninterface IBtn {\n  icon?: string;\n  name: string;\n  group?: number[];\n  show?: boolean;\n  key?: string;\n  className?: string;\n  onClick: (...args: any) => any;\n  title?: string;\n  disable?: boolean;\n}\n\nexport type btnFunc = () => IBtn[];"
  },
  {
    "path": "arius-console/src/@types/cluster/cluster-types.ts",
    "content": "export interface ICluster {\n  projectId: string;\n  appName: string;\n  dataNodesNumber: number;\n  authId: number;\n  authType: number;\n  associatedPhyClusterName: string;\n  clusterConfigTemplate?: string;\n  clusterStatus: IClusterStatus;\n  dataCenter: string;\n  esClusterConfigTemplateVO?: string;\n  esRoleClusterVOS: IEsRoleCluster[];\n  podNumber: number | string;\n  id: number;\n  level: number;\n  libraDepartment: string;\n  libraDepartmentId: string;\n  logicCluster: boolean;\n  memo: string;\n  name: string;\n  quota: number;\n  type: number;\n  permissions: string;\n  status?: string;\n  authCode?: number;\n}\n\nexport interface IClusterInfo extends ICluster {\n  [key: string]: any;\n}\nexport interface IClusterStatus {\n  name: string;\n  status: string;\n  docNu: number;\n  id: number;\n  totalDisk: number;\n  usedDisk: number;\n}\n\nexport interface IClusterNode {\n  hosts: string;\n  machineSpec: string;\n  nu: number;\n  pidcount: number;\n}\n\nexport interface INode {\n  create_time?: string;\n  delete_flag?: number;\n  id: number;\n  role: string;\n  spec: string;\n  value?: string;\n  label?: string;\n  key?: number;\n}\n\n/*\n *@集群管理 => 操作记录\n */\nexport interface IOperaRecordt {\n  bizId: string;\n  content?: string;\n  id: number;\n  module: string;\n  moduleId: number;\n  operate: string;\n  operateId: number;\n  operateTime: string;\n  operator: string;\n}\n\n/*\n *@集群管理 => 物理集群\n */\nexport interface IOpClusterCreate {\n  cluster: string;\n  dataCenter: string;\n  desc: string;\n  esVersion: string;\n  httpAddress: string;\n  httpWriteAddress: string;\n  idc: string;\n  level: number;\n  type: number;\n}\n\nexport interface IOpLogicCluster {\n  projectId: number;\n  name: string;\n  authId: number;\n  clusterConfigTemplate?: string;\n  dataCenter: string;\n  desc: string;\n  ecmClusterId?: string;\n  esVersion: string;\n  httpAddress: string;\n  httpWriteAddress: string;\n  idc: string;\n  id: number;\n  level: number;\n  password?: string;\n  readAddress: string;\n  templateSrvs?: string;\n  type: number;\n  writeAddress: string;\n  updateTime: string;\n  createTime: string;\n  clusterStatus: IClusterStatus;\n  status: string;\n  permissions: string;\n  esRoleClusterVOS: IEsRoleCluster[];\n}\n\nexport interface IOpLogicClusterDetail {\n  projectId: number;\n  clusterConfigTemplate?: string;\n  configJson: string;\n  dataCenter: string;\n  esClusterConfigTemplateVO?: any;\n  id: string;\n  level: string;\n  libraDepartment: string;\n  libraDepartmentId: string;\n  memo: string;\n  name: string;\n  quota: number;\n}\n\nexport interface IOpPhysicsCluster {\n  usename?: string;\n  cluster: string;\n  clusterConfigTemplate?: string;\n  dataCenter: string;\n  desc: string;\n  ecmClusterId?: string;\n  esVersion: string;\n  httpAddress: string;\n  httpWriteAddress: string;\n  idc: string;\n  id: number;\n  level: number;\n  password?: string;\n  readAddress: string;\n  templateSrvs?: string;\n  type: number;\n  writeAddress: string;\n  name?: string;\n  clusterStatus: string;\n  currentAppAuth: number;\n  logicClusterAndRegionList?: any;\n  supportZeus?: boolean;\n}\n\nexport interface IOpPhysicsClusterDetail {\n  cluster: string;\n  clusterConfigTemplate: string;\n  clusterStatus: string;\n  createTime: string;\n  dataCenter: string;\n  desc: string;\n  diskUsage: number;\n  esClusterTemplateSrvVOS: IEsClusterTemplate[];\n  esRoleClusterVOS: IEsRoleCluster[];\n  ecmClusterId: number;\n  esVersion: string;\n  httpAddress: string;\n  httpWriteAddress: string;\n  id: number;\n  idc: string;\n  level: number;\n  password: string;\n  readAddress: string;\n  type: number;\n  updateTime: string;\n  writeAddress: string;\n  dataNodeNu?: string;\n  pidCount: number;\n  [key: string]: any;\n}\n\nexport interface IEsClusterTemplate {\n  esVersion: string;\n  serviceId: number;\n  serviceName: string;\n}\n\nexport interface IEsRoleCluster {\n  createTime: string;\n  elasticClusterId: number;\n  esRoleClusterHostVO: IEsRoleClusterHost[];\n  id: number;\n  pidCount: number;\n  podNumber: number;\n  role: string;\n  roleClusterName: string;\n  updateTime: string;\n  machineSpec: string;\n}\n\nexport interface IRoleIpList {\n  hostname: string;\n  role: string;\n  beCold: boolean;\n}\n\nexport interface IEsRoleClusterHost {\n  createTime: string;\n  hostname: string;\n  id: number;\n  role: string;\n  roleClusterId: number;\n  updateTime: string;\n}\n\nexport interface IOpClusterRoles {\n  cfgId: number;\n  createTime: string;\n  deleteFlag: boolean;\n  elasticClusterId: number;\n  esVersion: string;\n  id: number;\n  machineSpec: string;\n  pidCount: number;\n  plugIds: string;\n  podNumber: number;\n  role: string;\n  roleClusterName: string;\n  updateTime: string;\n  key?: number;\n  value?: string;\n  label?: string;\n}\n\nexport interface ITemplateSrv {\n  esVersion: string;\n  serviceId: number;\n  serviceName: string;\n}\n\nexport interface ITemplateSrvData {\n  item: ITemplateSrv;\n  disabled: boolean;\n  status: number; // 0: 已开启 1: 未开启\n}\n\nexport interface ICreatePhyCluster {\n  type: number;\n  phyClusterName: string;\n  dataCenter: string;\n  nsTree: string;\n  idc?: string;\n  esVersion: string;\n  plugs?: string;\n  creator?: string;\n  desc: string;\n  roleClusters?: IRoleCluster[];\n  pidCount?: number;\n  machineSpec?: string;\n  level?: string;\n  roleClusterHosts?: IRoleClusterHots[];\n  tags?: string;\n}\n\nexport interface IRoleCluster {\n  role: string;\n  podNumber: number;\n  pidCount: number;\n  machineSpec: string;\n}\n\nexport interface IRoleClusterHots {\n  hostname: string;\n  role: string;\n}\n\nexport interface IOpExpandValues {\n  clientNode: string;\n  dataNode: string;\n  description: string;\n  masterNode: string;\n  operationType: number;\n  phyClusterName: string;\n  pidCount: number;\n  type: number;\n}\n\nexport interface IRegion {\n  region: string;\n  racks: string;\n  key: string;\n}\n\nexport interface IAccessClusterRegion {\n  value: number;\n  regionList: IRegion[];\n}\n"
  },
  {
    "path": "arius-console/src/@types/cluster/order-types.ts",
    "content": "\ninterface IBase {\n  projectId: string;\n  appName: string;\n  appPrincipals: string;\n  clusterId: number;\n  clusterName: string;\n  topicName: string;\n  principals: string;\n  description: string;\n}\n\nexport interface ITypeEnums {\n  message?: string;\n  type?: string;\n  label?: string;\n  value?: string;\n  key?: number;\n}\n\nexport interface IBaseOrder extends IBase {\n  peakBytesInPerSec: number;\n  orderId: number;\n  gmtModify: number;\n  gmtCreate: number;\n  orderStatus: number;\n  approver: string;\n  approvalOpinions: string;\n  applicant: string;\n  predictBytesIn: number;\n  realBytesIn: number;\n  regionBrokerIdList: any[];\n  regionNameList: string[];\n  statusStr?: string;\n  replicaNum?: number;\n  retentionTime?: number;\n  peakBytesIn?: number;\n  regions?: string;\n  brokers?: string;\n  gmtHandle: number;\n  id: number;\n  status: number;\n  access: number;\n  name: string;\n  type: string;\n  createTime?: string;\n  title?: string;\n}\nexport interface IOrderInfo {\n  id: number;\n  title: string;\n  type: string;\n  approverList: any[];\n  applicant: any;\n  gmtCreate: string;\n  gmtHandle: string;\n  opinion: string;\n  status: number;\n  detail: any;\n  detailInfo?: any;\n  description?: string;\n  approvers?: string[];\n  currentStep?: 0 | 1 | 2;\n  createTime: string;\n  finishTime: string;\n  appDeptName: string;\n  outcome: string;\n  applicantAppName: string;\n}\n\nexport interface IApprovalOrder {\n  assignee: string;\n  checkAuthority: boolean;\n  comment: string;\n  orderId: number;\n  outcome: string;\n  contentObj: object;\n}\n"
  },
  {
    "path": "arius-console/src/@types/cluster/physics-type.ts",
    "content": "/*\n *@运维管理 => 操作记录\n */\nexport interface IOpRecord {\n  bizId: string;\n  content?: string;\n  id: number;\n  module: string;\n  moduleId: number;\n  operate: string;\n  operateId: number;\n  operateTime: string;\n  operator: string;\n}\n\n/*\n *@运维管理 => 版本管理\n */\nexport interface IVersions {\n  id: number;\n  name: string;\n  createTime: string;\n  creator: string;\n  deleteFlag: boolean;\n  esVersion: string;\n  manifest: number;\n  release: string;\n  updateTime: string;\n  url: string;\n  key?: number;\n  value?: string;\n  label?: string;\n}\n\n/*\n *@运维管理 => 配置管理\n */\nexport interface IDeploy {\n  createTime: string;\n  dimension?: number | string;\n  id: number;\n  status: number;\n  memo?: string;\n  updateTime?: string;\n  value: string;\n  valueGroup: string;\n  valueName: string;\n}\n\nexport interface IDeploySwitch {\n  status: number;\n  id: number;\n}\n\nexport interface ITemplateLogic {\n  projectId: number;\n  createTime: string;\n  authType: number;\n  dataCenter: string;\n  dataType: number;\n  dateField?: string;\n  dateFieldFormat?: string;\n  dateFormat?: string;\n  desc: string;\n  expression: string;\n  expireTime?: number;\n  hotTime: number;\n  id: number;\n  idField: string;\n  libraDepartment: string;\n  libraDepartmentId: string;\n  name: string;\n  quota: number;\n  routingField?: string;\n  updateTime: string;\n  [key: string]: any;\n}\n\nexport interface IOpPhysicsCluster {\n  cluster: string;\n  clusterConfigTemplate?: string;\n  dataCenter: string;\n  desc: string;\n  ecmClusterId?: string;\n  esVersion: string;\n  httpAddress: string;\n  httpWriteAddress: string;\n  idc: string;\n  id: number;\n  level: number;\n  password?: string;\n  readAddress: string;\n  templateSrvs?: string;\n  type: number;\n  writeAddress: string;\n  name?: string;\n  clusterStatus: string;\n}\n\n/*\n *@运维管理 => 集群管理 => 物理集群 => 配置信息\n */\n\nexport interface IPhyConfig {\n  clusterId: number;\n  enginName: string;\n  typeName: string;\n  configData?: string;\n  desc?: string;\n  versionConfig?: any;\n  versionTag?: any;\n  selected?: any;\n  id: number;\n}\n\nexport interface INewRegionRacks {\n  cluster: string;\n  rack: string;\n  usageFlags: number;\n}\n\nexport interface INewRegionRacksMap {\n  title: string;\n  value?: string;\n  key: string;\n  disabled: boolean;\n  description: string;\n}\n\nexport interface IRegionTask {\n  deltaRacks?: string;\n  finishTime: string;\n  regionCostCpuCount: number;\n  regionCostDiskG: number;\n  id: number;\n  regionId: number;\n  srcRacks: string;\n  startTime: string;\n  status: number;\n  task: number;\n  type: number;\n}\n\nexport interface IRegionTaskItem {\n  actualCpuCount: number;\n  actualDiskG: number;\n  cluster: string;\n  combinedCpuCount: number;\n  combinedDiskG: number;\n  createTime: string;\n  dateFormat: string;\n  expireTime: number;\n  expression: string;\n  hotDay: number;\n  id: number;\n  maxQueryTime: number;\n  maxScrollTime: number;\n  maxTps: number;\n  physicalId: number;\n  quota: number;\n  quotaCpuCount: number;\n  quotaDiskG: number;\n  replicaNum: number;\n  shardNum: number;\n  sumDocCount: number;\n  sumIndexSizeG: number;\n  taskId: number;\n  templateName: string;\n}\n"
  },
  {
    "path": "arius-console/src/@types/index-types.ts",
    "content": "export interface IQuotaUsage {\n  actualCpuCount: number;\n  actualDiskG: number;\n  quotaCpuCount: number;\n  quotaCpuUsage: number;\n  quotaDiskG: number;\n  quotaDiskUsage: number;\n  cpuPercent?: number;\n  diskGPercent?: number;\n}\nexport interface IIndex {\n  key?: number;\n  name: string;\n  authType: number;\n  cluster: string;\n  createTime: string;\n  dataCenter: string;\n  dataType: number;\n  desc: string;\n  id: number;\n  quotaUsage: IQuotaUsage;\n  value: number;\n  libraDepartment: string;\n  hasDCDR: boolean;\n  logicId: number;\n}\n\nexport interface INodeDivide {\n  ip: string;\n  logicClusterName: string;\n  clusterLogicNames: string;\n  rack: string;\n  regionId: number | string;\n  role: number;\n  status: number;\n}\n\nexport interface IInput {\n  order: number;\n  name: string;\n}\n\nexport interface INode {\n  description?: string;\n  inputs?: IInput[];\n  name: string;\n  order: string;\n  position?: string;\n}\nexport interface IPartition {\n  docsCount: number;\n  docsDeleted: number;\n  health: string;\n  index: string;\n  pri: number;\n  priStoreSize: string;\n  rep: number;\n  status: string;\n  storeSize: string;\n}\n\nexport interface IZoomInfo {\n  currentUsage: IQuotaUsage;\n  cyclicalRoll: boolean;\n  dateField: string;\n  expireTime: number;\n  id: number;\n  name: string;\n  quota: number;\n  topUsage: IQuotaUsage;\n  [key: string]: any;\n}\n\nexport interface IOpTemplateIndex {\n  cluster: string;\n  config: string;\n  createTime: string;\n  expression: string;\n  id: number;\n  logicId: number;\n  name: string;\n  rack?: string;\n  role: number;\n  shard: number;\n  shardRouting: number;\n  status: number;\n  version: number;\n}\n\nexport interface IOpTemplateIndexDetail {\n  cluster: string;\n  config: string;\n  createTime: string;\n  expression: string;\n  id: number;\n  logicId: number;\n  name: string;\n  rack: string;\n  role: number;\n  shard: number;\n  shardRouting: number;\n  status: number;\n  version: number;\n}\n"
  },
  {
    "path": "arius-console/src/@types/index.d.ts",
    "content": "\n"
  },
  {
    "path": "arius-console/src/@types/params-types.ts",
    "content": "export interface IWorkOrder {\n  contentObj: object;\n  dataCenter?: string;\n  submitor?: string;\n  submitorProjectId?: number;\n  description?: string;\n  type?: string;\n}\n\nexport interface IOperatRecord {\n  bizId?: string | number;\n  operator?: string;\n  moduleId?: number | string;\n  beginTime?: string;\n  content?: string;\n  endTime?: string;\n  page: number;\n  projectName?: string;\n  size: number;\n  triggerWayId?: number;\n  userOperation?: string;\n}\n\nexport interface IOpPackageParams {\n  creator: string;\n  desc: string;\n  esVersion: string;\n  manifest: number;\n  url: string;\n  fileName: string;\n  uploadFile?: any;\n  id?: string;\n  md5: string;\n}\n\nexport interface IOpClusterRegion {\n  logicClusterId: number;\n  configJson: string;\n  id: number;\n  racks: string;\n  share: number;\n}\n\nexport interface IClearIndexParams {\n  logicId: number;\n  delIndices: string[];\n  delQueryDsl: string;\n}\n\nexport interface IPhysicalTemplateParams {\n  cluster?: string;\n  role?: number;\n  logicId?: number;\n}\n"
  },
  {
    "path": "arius-console/src/@types/plug-types.ts",
    "content": "export interface IPlug {\n  createTime?: string;\n  id: number;\n  creator: string;\n  desc: string;\n  type?: number;\n  updateTime?: string;\n  md5: string;\n  name: string;\n  pdefault: number;\n  s3url: string;\n  url: string;\n  version?: string;\n  deleteFlag: boolean;\n  installed: boolean;\n}\n\n"
  },
  {
    "path": "arius-console/src/@types/task-types.ts",
    "content": "export interface ITask {\n  clusterNodeRole: string;\n  createTime: string;\n  creator: string;\n  deleteFlag: boolean;\n  id: number;\n  orderType: number;\n  physicClusterId: number;\n  status: string;\n  title: string;\n  type: string;\n  updateTime: string;\n  workOrderId: number;\n  esVersion: string;\n  key?: number;\n  taskType: number;\n  businessKey: number;\n  expandData: string;\n}\n\nexport interface ITaskBaseInfo {\n  clusterName: string;\n  clusterNodeRole: string;\n  createTime: string;\n  creator: string;\n  dept: string;\n  desc: string;\n  esVersion: string;\n  id: number;\n  idc: string;\n  imageName: string;\n  nsTree: string;\n  orderType: number;\n  status: string;\n  title: string;\n  type: number;\n  updateTime: string;\n  workOrderId: number;\n}\n\nexport interface ITaskDetail {\n  cancel: number;\n  creating: number;\n  roleNameTaskDetailMap: ITaskNodeMap;\n  failed: number;\n  ignore: number;\n  orderType: number;\n  percent: number;\n  status: string;\n  success: number;\n  sum: number;\n  waiting: number;\n  key?: number;\n}\n\nexport interface IDcdrStepDetail {\n  logicTemplateId: number;\n  createTime: string;\n  logicTemplateName: string;\n  logicClusterId: number;\n  logicClusterName: string;\n  masterPhysicalTemplateName: string;\n  masterPhysicalClusterName: string;\n  vicePhysicalTemplateName: string;\n  vicePhysicalClusterName: string;\n  status: string;\n  taskProgress: number;\n  content: string;\n}\n\nexport interface IDcdrStepDetailInfo extends IDcdrStepDetail {\n  [key: string]: any;\n}\nexport interface ITaskNodes {\n  header: string;\n  data: INodeTask[];\n  key: string;\n}\n\nexport interface ITaskNodeMap {\n  clientnode: INodeTask[];\n  datanode: INodeTask[];\n  masternode: INodeTask[];\n  coldnode: INodeTask[];\n}\n\nexport interface INodeTask {\n  grp: number;\n  hostname: string;\n  id: number;\n  idx: number;\n  role: string;\n  status: string;\n  taskId: number;\n  workOrderTaskId: number;\n  updateTime: string;\n  key?: number;\n}\n\nexport interface ITaskLog {\n  agent: string;\n  user: string;\n}\n"
  },
  {
    "path": "arius-console/src/@types/user-types.ts",
    "content": "export interface IUser {\n  domainAccount?: string;\n  chineseName: string;\n  label?: string;\n  value?: string;\n  role: number;\n  oldPassword: string;\n  roleName?: string;\n  key?: number;\n  status?: number;\n  mobile?: string;\n  email?: string;\n  name?: string;\n}\nexport interface NewIUser {\n  deptId?: number;\n  email?: string;\n  id?: number;\n  phone?: string;\n  realName?: string;\n  roleList?: string[];\n  userName?: string;\n}\n"
  },
  {
    "path": "arius-console/src/actions/actionTypes.ts",
    "content": "export default {\n  SET_LOADING: \"SET_LOADING\",\n\n  // 侧边栏是否收起展开\n  SET_SLIDER_MENU: \"SET_SLIDER_MENU\",\n\n  //\n  SET_USER_PERMISSION: \"SET_USER_PERMISSION\",\n  SET_USER_TYPE: \"SET_USER_TYPE\",\n  SET_USER: \"SET_USER\",\n  SET_MODAL_ID: \"SET_MODAL_ID\",\n  SET_DRAWER_ID: \"SET_DRAWER_ID\",\n  SET_CLUSTER_COST: \"SET_CLUSTER_COST\", // 设置集群成本\n  SET_CLUSTER_NODE_LIST: \"SET_CLUSTER_NODE_LIST\", // 节点列表\n  SET_CLUSTER_PACKEAGE: \"SET_CLUSTER_PACKEAGE\", // 版本列表\n\n  // 开启关闭全屏\n  SET_FULL_SCREEN_CONTENT: \"SET_FULL_SCREEN_CONTENT\",\n\n  SET_APP_LIST: \"SET_APP_LIST\", // 设置项目列表\n  SET_APP_SPIN: \"SET_APP_SPIN\", // 设置app列表spin\n  SET_PAGINATION: \"SET_PAGINATION\", // 分页\n  SET_APP_SUB_VALUE: \"SET_SUB_VALUE\", // 存储项目管理查询表单VALUE\n\n  //权限点action\n  SET_PERMISSION_POINTS: \"SET_PERMISSION_POINTS\",\n\n  // region\n  SET_PHY_CLUSTER_LIST: \"SET_PHY_CLUSTER_LIST\",\n  SET_REGION_LIST: \"SET_REGION_LIST\",\n  SET_RACKS: \"SET_RACKS\",\n  SET_RACKS_ARR: \"SET_RACKS_ARR\",\n\n  // 物理集群配置信息\n  SET_PHY_CLUSTER_CONFIG: \"SET_PHY_CLUSTER_CONFIG\",\n  SET_PHY_CLUSTER_CONFIG_LIST: \"SET_PHY_CLUSTER_CONFIG_LIST\",\n  SET_PHY_CLUSTER_CONFIG_ROLES: \"SET_PHY_CLUSTER_CONFIG_ROLES\",\n\n  // 创建索引\n  SET_INDEX_CREATE_TEMPORAYFORMMAP: \"SET_INDEX_CREATE_TEMPORAYFORMMAP\",\n  SET_CURRENT_STEP: \"SET_CURRENT_STEP\",\n  SET_FIELD_TYPE_MAP: \"SET_FIELD_TYPE_MAP\",\n  SET_THIRD_CHILD_MAP: \"SET_THIRD_CHILD_MAP\",\n  SET_INDEX_CREATE_LOADING_MAP: \"SET_INDEX_CREATE_LOADING_MAP\",\n  SET_INDEX_CREATE_SECOND_CHILD_MAP: \"SET_INDEX_CREATE_SECOND_CHILD_MAP\",\n  SET_EDITOR_INSTANCE: \"SET_EDITOR_INSTANCE\",\n  SET_CLEAR_CREATE_INDEX: \"SET_CLEAR_CREATE_INDEX\",\n  SET_CREATE_INDEX: \"SET_CREATE_INDEX\",\n\n  // task // dcdrStepDetail\n  SET_DCDR_STEP_DEL: \"SET_DCDR_STEP_DEL\",\n  SET_TASK_BASE_INFO: \"SET_TASK_BASE_INFO\",\n  SET_TASK_MENU: \"SET_TASK_MENU\",\n  SET_TASK_BASE_LOADING: \"SET_TASK_BASE_LOADING\",\n\n  // 集群看板\n  SET_CLUSTER_NAME_TIME: \"SET_CLUSTER_NAME_TIME\",\n  SET_CLUSTER_IS_UPDATE: \"SET_CLUSTER_IS_UPDATE\",\n  SET_KAN_BAN: \"SET_KAN_BAN\",\n\n  // Gateway 看板\n  SET_GATEWAY_TIME: \"SET_GATEWAY_TIME\",\n  SET_GATEWAY_IS_UPDATE: \"SET_GATEWAY__IS_UPDATE\",\n\n  // dashboard\n  SET_DASHBOARD: \"SET_DASHBOARD\",\n  SET_DASHBOARD_DYMANIC: \"SET_DASHBOARD_DYMANIC\",\n};\n"
  },
  {
    "path": "arius-console/src/actions/app.ts",
    "content": "import actionTypes from \"./actionTypes\";\n\nexport const setProjectList = (projectList: any) => {\n  return {\n    type: actionTypes.SET_APP_LIST,\n    payload: {\n      projectList,\n    },\n  };\n};\n"
  },
  {
    "path": "arius-console/src/actions/cluster-base.ts",
    "content": "import { INodeListObjet } from 'store/type';\nimport actionTypes from './actionTypes';\n\nexport const setClusterCost = (cost: number | string) => ({\n  type: actionTypes.SET_CLUSTER_COST,\n  payload: {\n    cost\n  }\n});\n\nexport const setClusterNodeList = (nodeList: INodeListObjet) => ({\n  type: actionTypes.SET_CLUSTER_NODE_LIST,\n  payload: {\n    nodeList\n  }\n});\n\nexport const setClusterPackage = (packageList: any) => ({\n  type: actionTypes.SET_CLUSTER_PACKEAGE,\n  payload: {\n    packageList\n  }\n});\n"
  },
  {
    "path": "arius-console/src/actions/cluster-kanban.ts",
    "content": "import { ClusterState } from 'store/type';\nimport actionTypes from './actionTypes';\n\nexport const setClusterForm = (clusterForm: ClusterState) => ({\n  type: actionTypes.SET_CLUSTER_NAME_TIME,\n  clusterForm\n});\n\nexport const setIsUpdate = (isUpdate: boolean) => ({\n  type: actionTypes.SET_CLUSTER_IS_UPDATE,\n  clusterForm: {\n    isUpdate\n  }\n})\nexport const setClusterKanban = (sliderMenuCollapsed: any) => {\n  //SET_KAN_BAN 保存接口返回的标题信息用于标题配置化\n  return ({\n    type: actionTypes.SET_KAN_BAN,\n    clusterForm: sliderMenuCollapsed\n  })\n}"
  },
  {
    "path": "arius-console/src/actions/create-index.ts",
    "content": "import actionTypes from './actionTypes';\n\nexport const setTemporaryFormMap = (key: string, result: any,) => ({\n  type: actionTypes.SET_INDEX_CREATE_TEMPORAYFORMMAP,\n  payload: {\n    key,\n    result,\n  }\n});\n\nexport const setSecondChildMap = (key: string, result: any,) => ({\n  type: actionTypes.SET_INDEX_CREATE_SECOND_CHILD_MAP,\n  payload: {\n    key,\n    result,\n  }\n});\n\nexport const setLoadingMap = (key: string, result: any,) => ({\n  type: actionTypes.SET_INDEX_CREATE_LOADING_MAP,\n  payload: {\n    key,\n    result,\n  }\n});\n\nexport const setCurrentStep = (currentStep: number,) => ({\n  type: actionTypes.SET_CURRENT_STEP,\n  payload: {\n    currentStep\n  }\n});\n\nexport const setFieldTypeMap = (fieldTypeMap: any) => ({\n  type: actionTypes.SET_FIELD_TYPE_MAP,\n  payload: {\n    fieldTypeMap\n  }\n});\n\nexport const setThirdChildMap = (key: string, result?: any,) => ({\n  type: actionTypes.SET_THIRD_CHILD_MAP,\n  payload: {\n    key,\n    result,\n  }\n});\n\nexport const setEditorInstance = (activeInstance: any,) => ({\n  type: actionTypes.SET_EDITOR_INSTANCE,\n  payload: {\n    activeInstance\n  }\n});\n\nexport const setClearCreateIndex = () => ({\n  type: actionTypes.SET_CLEAR_CREATE_INDEX,\n  payload: {}\n});\n\nexport const setCreateIndex = (payload: any) => {\n  return {\n    type: actionTypes.SET_CREATE_INDEX,\n    payload,\n  }\n};"
  },
  {
    "path": "arius-console/src/actions/dashBoard.ts",
    "content": "import { DashboardState } from \"store/type\";\nimport actionTypes from \"./actionTypes\";\n\nexport const setDashBoard = (payload: DashboardState | any) => ({\n  type: actionTypes.SET_DASHBOARD,\n  payload,\n});\n\nexport const setDashBoardDymanicMetrics = (payload: DashboardState | any) => ({\n  type: actionTypes.SET_DASHBOARD_DYMANIC,\n  payload,\n});\n"
  },
  {
    "path": "arius-console/src/actions/full-screen.ts",
    "content": "import actionTypes from './actionTypes';\n\nexport const setFullScreenContent = (content: string | JSX.Element) => ({\n  type: actionTypes.SET_FULL_SCREEN_CONTENT,\n  payload: {\n    content,\n  }\n});"
  },
  {
    "path": "arius-console/src/actions/gateway-kanban.ts",
    "content": "import { GatewayState } from 'store/type';\nimport actionTypes from './actionTypes';\n\nexport const setGatewayForm = (gatewayForm: GatewayState) => ({\n  type: actionTypes.SET_GATEWAY_TIME,\n  gatewayForm\n});\n\nexport const setIsUpdate = (isUpdate: boolean) => ({\n  type: actionTypes.SET_GATEWAY_IS_UPDATE,\n  gatewayForm: {\n    isUpdate\n  }\n})"
  },
  {
    "path": "arius-console/src/actions/index.ts",
    "content": "export * from \"./modal\";\nexport * from \"./region\";\nexport * from \"./full-screen\";\nexport * from \"./cluster-base\";\nexport * from \"./phy-cluster-config\";\nexport * from \"./create-index\";\nexport * from \"./task\";\nexport * from \"./user\";\nexport * from \"./app\";\nexport * from \"./silderMenu\";\n"
  },
  {
    "path": "arius-console/src/actions/modal.ts",
    "content": "import actionTypes from \"./actionTypes\";\n\nexport const setModalId = (modalId: string, params?: any, cb?: Function) => ({\n  type: actionTypes.SET_MODAL_ID,\n  payload: {\n    modalId,\n    params,\n    cb,\n  },\n});\n\nexport const setDrawerId = (drawerId: string, params?: any, cb?: Function) => ({\n  type: actionTypes.SET_DRAWER_ID,\n  payload: {\n    drawerId,\n    params,\n    cb,\n  },\n});\n"
  },
  {
    "path": "arius-console/src/actions/phy-cluster-config.ts",
    "content": "import actionTypes from './actionTypes';\n\nexport const setPhyClusterConfigType = (typeNameList: any,) => ({\n  type: actionTypes.SET_PHY_CLUSTER_CONFIG,\n  payload: {\n    typeNameList,\n  }\n});\n\nexport const setPhyClusterConfigList = (configList: any,) => ({\n  type: actionTypes.SET_PHY_CLUSTER_CONFIG_LIST,\n  payload: {\n    configList,\n  }\n});\n\nexport const setPhyClusterConfigRoles = (clusterRolesList: any,) => ({\n  type: actionTypes.SET_PHY_CLUSTER_CONFIG_ROLES,\n  payload: {\n    clusterRolesList,\n  }\n});"
  },
  {
    "path": "arius-console/src/actions/region.ts",
    "content": "import { ILabelValue } from 'typesPath/base-types';\nimport actionTypes from './actionTypes';\n\nexport const setPhyClusterList = (phyClusterList: ILabelValue[], type: string = \"\", tableData = []) => ({\n  type: actionTypes.SET_PHY_CLUSTER_LIST,\n  payload: {\n    phyClusterList,\n    type,\n    tableData\n  }\n});\n\nexport const setRegionList = (region: any) => ({\n  type: actionTypes.SET_REGION_LIST,\n  payload: {\n    region\n  }\n});\n\nexport const setRacks = (racks: string) => ({\n  type: actionTypes.SET_RACKS,\n  payload: {\n    racks\n  }\n});\n\nexport const setRacksArr = (racksArr: ILabelValue[]) => ({\n  type: actionTypes.SET_RACKS_ARR,\n  payload: {\n    racksArr\n  }\n});"
  },
  {
    "path": "arius-console/src/actions/silderMenu.ts",
    "content": "import actionTypes from './actionTypes';\n\nexport const setSlierMenu = (sliderMenuCollapsed: boolean) => {\n  return ({\n    type: actionTypes.SET_SLIDER_MENU,\n    payload: {\n      sliderMenuCollapsed\n    }\n  })\n}"
  },
  {
    "path": "arius-console/src/actions/task.ts",
    "content": "import { IDcdrStepDetailInfo } from 'typesPath/task-types';\nimport actionTypes from './actionTypes';\n\nexport const setTaskBaseInfo = (taskBaseInfo: any) => {\n  return {\n    type: actionTypes.SET_TASK_BASE_INFO,\n    payload: {\n      taskBaseInfo,\n    }\n  }\n};\n\nexport const setDcdrStepDetail = (dcdrStepDetail: IDcdrStepDetailInfo) => {\n  return {\n    type: actionTypes.SET_DCDR_STEP_DEL,\n    payload: {\n      dcdrStepDetail\n    }\n  }\n};\n\nexport const setTaskMenu = () => {\n  return {\n    type: actionTypes.SET_TASK_MENU,\n    payload: {\n      menu: window.location.hash.replace('#', '') || 'base'\n    }\n  }\n};\n\nexport const setTaskBaseLoading = (loading: boolean) => {\n  return {\n    type: actionTypes.SET_TASK_BASE_LOADING,\n    payload: {\n      loading\n    }\n  }\n};"
  },
  {
    "path": "arius-console/src/actions/user.ts",
    "content": "import { IPermission } from \"store/type\";\nimport actionTypes from \"./actionTypes\";\n\nexport const setIsAdminUser = (isAdminUser: boolean) => ({\n  type: actionTypes.SET_USER_TYPE,\n  payload: {\n    isAdminUser,\n  },\n});\n\nexport const setGlobalUserInfo = (userInfo: any) => ({\n  type: actionTypes.SET_USER,\n  payload: {\n    userInfo,\n  },\n});\n\nexport const setUserPermissionTree = (permissionTree: IPermission) => ({\n  type: actionTypes.SET_USER_PERMISSION,\n  payload: {\n    permissionTree,\n  },\n});\n"
  },
  {
    "path": "arius-console/src/api/Scheduling.ts",
    "content": "import fetch from '../lib/fetch';\n\ninterface ILogsList {\n  taskId?: number,\n  page: number,\n  size: number,\n  taskName?: string,\n  taskStatus?: number,\n  beginTime?: number,\n  endTime?: number\n}\n\ninterface ITastList {\n  taskId?: number,\n  page: number,\n  size: number,\n  taskStatus?: number,\n  taskDesc?: string,\n  className?: string,\n}\n\nexport const getTaskList = (params: ITastList) => {\n  return fetch(`/v1/logi-job/task/list`, {\n    method: 'POST',\n    body: params,\n  });\n};\n\nexport const taskDo = (taskCode: number) => {\n  return fetch(`/v1/logi-job/task/${taskCode}/do`, {\n    method: 'POST',\n    body: {},\n  });\n};\n\nexport const taskStatus = (taskCode: number, status: number) => {\n  return fetch(`/v1/logi-job/task/${taskCode}/${status}`, {\n    method: 'POST',\n    body: {},\n  });\n};\n\nexport const jobStop = (jobCode: number) => {\n  return fetch(`/v1/logi-job/job/${jobCode}/stop`, {\n    method: 'POST',\n    body: {},\n  });\n};\n\nexport const getLogsList = (params: ILogsList) => {\n  return fetch(`/v1/logi-job/logs/list`, {\n    method: 'POST',\n    body: params,\n  });\n};\n\nexport const upgradeTask = (taskCode: number) => {\n  return fetch(`/v1/logi-job/task/${taskCode}/detail`);\n};\n"
  },
  {
    "path": "arius-console/src/api/app-api.ts",
    "content": "import fetch from \"../lib/fetch\";\nimport { getCookie } from \"lib/utils\";\n\nconst v3Prefix = `/v3`;\nconst logiSecurityProject = `/security/project`;\n\nexport const getNoCodeLoginAppList = (projectId: number) => {\n  return fetch(`/v3/es-user/project/${projectId}`, {\n    headers: {\n      \"X-ARIUS-APP-TICKET\": \"xTc59aY72\",\n    },\n  });\n};\n\nexport const getApp = (id: number) => {\n  return fetch(`${v3Prefix}/project-config/${id}`);\n};\n\nexport const getAppByProjectId = (id: number) => {\n  return fetch(`${v3Prefix}/es-user/project/${id}`);\n};\n\nexport const updateAppByProjectId = (params) => {\n  return fetch(`${v3Prefix}/es-user/`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const createAppByProjectId = (id: number, params) => {\n  return fetch(`${v3Prefix}/es-user/${id}`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const deleteOneAppByProjectId = (projectId: number, esUser: number) => {\n  return fetch(`${v3Prefix}/es-user/${projectId}/${esUser}`, {\n    method: \"DELETE\",\n  });\n};\n\n// logi-security 接口迁移\n\nexport const getProjectListByUserId = (userId: number) => {\n  return fetch(`${v3Prefix}${logiSecurityProject}/user/${userId}`);\n};\n\nexport const getProjectMetaList = () => {\n  return fetch(`${v3Prefix}${logiSecurityProject}`);\n};\n\nexport const getProjectList = (params: any) => {\n  return fetch(`${v3Prefix}${logiSecurityProject}/page`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const getUnassignedUsers = (projectId: number) => {\n  let isAdmin = getCookie(\"isAdminUser\") === \"yes\";\n  return fetch(`${v3Prefix}${logiSecurityProject}/unassigned?id=${projectId}${isAdmin ? \"&containsAdminRole=true\" : \"\"}`);\n};\n\nexport const getProject = (projectId: number) => {\n  return fetch(`${v3Prefix}${logiSecurityProject}/${projectId}`);\n};\n\nexport const createProject = (params) => {\n  return fetch(`${v3Prefix}${logiSecurityProject}`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/security/project 更新项目\nexport const updateProject = (params) => {\n  return fetch(`${v3Prefix}${logiSecurityProject}`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/security/project/{id}/owner 从角色中增加该项目下的负责人\nexport const updateOwner = (id, params) => {\n  return fetch(`${v3Prefix}${logiSecurityProject}/${id}/owner`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/security/project/{id}/user 从角色中增加该项目下的用户\nexport const updateUser = (id, params) => {\n  return fetch(`${v3Prefix}${logiSecurityProject}/${id}/user`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const deleteProject = (id: number) => {\n  return fetch(`${v3Prefix}${logiSecurityProject}/${id}`, {\n    method: \"DELETE\",\n  });\n};\n\n// /v3/security/project/check-resources/{id} 检查一个项目的资源是否可用\nexport const checkResources = (id: number) => {\n  return fetch(`${v3Prefix}/security/project/check-resources/${id}`);\n};\n"
  },
  {
    "path": "arius-console/src/api/cluster-api.ts",
    "content": "import fetch, { formFetch } from \"../lib/fetch\";\nimport { IOpLogicClusterDetail, IOpPhysicsClusterDetail } from \"../@types/cluster/cluster-types\";\nimport { IOperatRecord, IOpPackageParams } from \"typesPath/params-types\";\nimport store from \"store\";\nimport { IDeploy, IDeploySwitch } from \"typesPath/cluster/physics-type\";\nimport { IDeteilId } from \"typesPath/base-types\";\n\nconst app = {\n  currentAppInfo: {\n    app: store.getState().app,\n  },\n};\n\nexport interface ILogicLike {\n  page: number;\n  size: number;\n  authType?: number;\n  name?: string;\n  health?: number;\n  projectId?: number;\n  type?: number;\n  sortTerm?: string;\n  orderByDesc?: boolean;\n  id?: number | string;\n  memo?: string;\n  //todo：版本字段未给出\n}\n\nexport interface IClusterList {\n  page: number;\n  size: number;\n  authType?: number;\n  cluster?: string;\n  health?: number;\n  esVersion?: string;\n  sortTerm?: string;\n  orderByDesc?: boolean;\n  id?: number | string;\n  desc?: string;\n  logicClusterName?: string;\n  //todo：版本字段未给出\n}\n/**\n * cluster 相关接口\n *\n */\n\nexport const opEditLogicCluster = (params: IOpLogicClusterDetail) => {\n  return fetch(`/v3/cluster/logic`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 获取我的集群详细信息\nexport const getOpLogicClusterInfo = (clusterLogicId: number) => {\n  return fetch(`/v3/cluster/logic/detail/${clusterLogicId}`);\n};\n\n// 获取物理集群详细信息\nexport const getPhysicsClusterDetail = (id: number) => {\n  return fetch(`/v3/cluster/phy/${id}/overview`);\n};\n\n// 按条件分页获取物理集群列表\nexport const getOpPhysicsClusterList = (params: IClusterList) => {\n  return fetch(`/v3/cluster/phy/page`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const getvailablePhysicsClusterListLogic = (clusterLogicType: number) => {\n  return fetch(`/v3/cluster/phy/${clusterLogicType}/names`);\n};\n\nexport const getPhysicsClusterList = (clusterLogicType: number) => {\n  return fetch(`/v3/cluster/phy/${clusterLogicType}/can-associated-names`);\n};\n\nexport const getOpLogicClusterList = (params: ILogicLike) => {\n  return fetch(`/v3/cluster/logic/page`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n//新全量逻辑集群\nexport const newLogicClusterList = () => {\n  return fetch(\"/v3/cluster/logic\");\n};\n\n//新物理集群\nexport const newPhysicClusterList = () => {\n  return fetch(\"/v3/cluster/phy/names\");\n};\n\nexport const newClusterList = () => {\n  return fetch(\"/v3/cluster/logic/cluster-phy-relation\");\n};\n\n// 新建模板逻辑集群列表\nexport const getClusterLogicNames = (type: number) => {\n  return fetch(`/v3/cluster/logic/${type}`);\n};\n\nexport const getPhysicClusterRoles = (physicClusterId: number) => {\n  return fetch(`/v3/cluster/phy/${physicClusterId}/roles`);\n};\n\n/*\n * 版本 相关接口\n */\n\nexport const getPackageList = () => {\n  return fetch(`/v3/normal/ecm/package`);\n};\n\nexport const addPackage = (params: IOpPackageParams) => {\n  const { creator, desc, fileName, md5, esVersion, manifest, uploadFile, url } = params;\n  const formData = new FormData();\n  formData.append(\"url\", url || \"\");\n  formData.append(\"creator\", creator);\n  formData.append(\"pDefault\", \"false\");\n  formData.append(\"esVersion\", esVersion);\n  formData.append(\"manifest\", manifest + \"\");\n  formData.append(\"desc\", desc || \"\");\n  if (uploadFile) {\n    formData.append(\"uploadFile\", uploadFile);\n    formData.append(\"md5\", md5);\n    formData.append(\"fileName\", fileName);\n  }\n  return formFetch(`/v3/normal/ecm/package`, {\n    method: \"POST\",\n    body: formData,\n  });\n};\n\nexport const delPackage = (id: number) => {\n  return fetch(`/v3/normal/ecm/package/${id}`, {\n    method: \"DELETE\",\n  });\n};\n\nexport const updatePackage = (params: IOpPackageParams) => {\n  const { creator, desc, fileName, md5, esVersion, manifest, uploadFile, url, id } = params;\n  const formData = new FormData();\n  formData.append(\"url\", url || \"\");\n  formData.append(\"creator\", creator);\n  formData.append(\"pDefault\", \"false\");\n  formData.append(\"esVersion\", esVersion);\n  formData.append(\"manifest\", manifest + \"\");\n  formData.append(\"desc\", desc || \"\");\n  formData.append(\"id\", id || \"\");\n  if (uploadFile) {\n    formData.append(\"uploadFile\", uploadFile);\n    formData.append(\"md5\", md5);\n    formData.append(\"fileName\", fileName);\n  }\n  return formFetch(`/v3/normal/ecm/package/update`, {\n    method: \"POST\",\n    body: formData,\n  });\n};\n\n/**\n * 操作记录 相关接口\n *\n */\nexport const getUserRecordList = (params: IOperatRecord) => {\n  return fetch(`/v3/record/page`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 获取所有模块\nexport const getlistModules = () => {\n  return fetch(`/v3/record/module`);\n};\n\n// 获取触发方式\nexport const getTriggerWay = () => {\n  return fetch(`/v3/record/trigger-way`);\n};\n\n// 获取操作类型\nexport const getOperationType = (moduleCode?: number) => {\n  return fetch(`/v3/record/operation-type/${moduleCode}`);\n};\n\n/*\n * 配置管理 相关接口\n *\n */\n\nexport const getDeployList = (params: object = {}) => {\n  return fetch(`/v3/config/list`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const newDeploy = (params: IDeploy) => {\n  return fetch(`/v3/config/add`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const switchDeploy = (params: IDeploySwitch) => {\n  return fetch(`/v3/config/switch`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const updateDeploy = (params: IDeploy) => {\n  return fetch(`/v3/config`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const deleteDeploy = (id: number) => {\n  return fetch(`/v3/config/${id}`, {\n    method: \"DELETE\",\n  });\n};\n\nexport const clusterJoin = (params: any) => {\n  return fetch(`/v3/cluster/phy/join`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n/**\n * 获取物理集群的动态配置项\n */\nexport const getDynamicConfig = (clusterName: string) => {\n  return fetch(`/v3/cluster/phy/dynamic-config/${clusterName}`, {\n    prefix: \"admin\",\n  });\n};\n\nexport const getClusterAttributes = (clusterName: string) => {\n  return fetch(`/v3/cluster/phy/dynamic-config/attributes/${clusterName}`, {\n    prefix: \"admin\",\n  });\n};\n\nexport const updateDynamicConfig = (clusterName: string, key: string, value: string | string[]) => {\n  return fetch(`/v3/cluster/phy/dynamic-config`, {\n    prefix: \"admin\",\n    method: \"PUT\",\n    body: {\n      clusterName,\n      key,\n      value,\n    },\n    returnRes: true,\n  });\n};\n\n// 获取数据中心列表 接口：/v3/config/cluster-data-center\nexport const getDataCenter = () => {\n  return fetch(`/v3/config/cluster-data-center`);\n};\n\n// 获取集群版本列表 接口：/v3/config/cluster-version\nexport const getClusterVersion = () => {\n  return fetch(`/v3/config/cluster-version`);\n};\n\n// 获取集群资源类型列表 接口：/v3/config/cluster-resource-type\nexport const getResourceType = () => {\n  return fetch(`/v3/config/cluster-resource-type`);\n};\n\n// 获取节点规格列表 接口：/v3/config/node-specification\nexport const getNodeSpecification = () => {\n  return fetch(`/v3/config/node-specification`);\n};\n\n// 获取申请集群节点规格列表 接口：/v3/cluster/phy/node/machineSpecs\nexport const getAccessClusterNodeSpecification = () => {\n  return fetch(`/v3/cluster/phy/node/machineSpecs`);\n};\n\n// 获取集群节点数列表 接口：/v3/config/cluster-node-count\nexport const getNodeCount = () => {\n  return fetch(`/v3/config/cluster-node-count`);\n};\n\n// 【物理集群：zeus管控】 接口：/v3/cluster/phy/zeus-url\nexport const getZeusUrl = () => {\n  return fetch(`/v3/cluster/phy/zeus-url`);\n};\n\n// 新建集群  接口：/v3/op-task/cluster-create\nexport const creatCluster = (params) => {\n  return fetch(`/v3/op-task/cluster-create`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 集群扩容 接口： /v3/op-task/cluster-expand\nexport const clusterExpand = (params: any) => {\n  return fetch(`/v3/op-task/cluster-expand`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 集群缩容 接口： /v3/op-task/cluster-shrink\nexport const clusterShrink = (params: any) => {\n  return fetch(`/v3/op-task/cluster-shrink`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 集群升级 接口： /v3/op-task/cluster-upgrade\nexport const clusterUpgrade = (params: any) => {\n  return fetch(`/v3/op-task/cluster-upgrade`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 集群重启 接口： /v3/op-task/cluster-restart\nexport const clusterRestart = (params: any) => {\n  return fetch(`/v3/op-task/cluster-restart`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 配置变更 接口： /v3/op-task/cluster-config-add\nexport const clusterConfigAdd = (params: any) => {\n  return fetch(`/v3/op-task/cluster-config-add`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 获取可划分至region的节点信息\nexport const getRegionNode = (clusterId: number) => {\n  return fetch(`/v3/cluster/phy/node/${clusterId}/region/`);\n};\n\n// 根据物理集群名称获region信息，包含region中的数据节点信息\nexport const getRegionList = (clusterName: string) => {\n  return fetch(`/v3/cluster/phy/region/${clusterName}`);\n};\n\n// 节点划分且创建region\nexport const divideRegionCheck = (params: any) => {\n  return fetch(`/v3/cluster/phy/node/divide-region-check`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n\n// 节点划分且创建region\nexport const divideRegion = (params: any) => {\n  return fetch(`/v3/cluster/phy/node/divide-region`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n\n// 编辑region中的节点\nexport const editRegion = (params: any) => {\n  return fetch(`/v3/cluster/phy/node/divide-region`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 删除物理集群region接口\nexport const deleteRegion = (id: number) => {\n  return fetch(`/v3/cluster/phy/region/${id}`, {\n    method: \"DELETE\",\n  });\n};\n\n// 绑定/编辑 gateway 接口：/v3/cluster/phy/gateway\nexport const bindGateway = (params: { id: number; gatewayUrl: string }) => {\n  return fetch(`/v3/cluster/phy/gateway`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 提示用户索引和模板的数量\nexport const getCount = (clusterId: number) => {\n  return fetch(`/v3/cluster/logic/index-template-count/${clusterId}`);\n};\n\n// 下线集群\nexport const deleteLogic = (clusterId: number) => {\n  return fetch(`/v3/cluster/logic/${clusterId}`, {\n    method: \"DELETE\",\n  });\n};\n\n// 获取预估磁盘大小\nexport const getDiskSize = (clusterLogicId: number, count: number) => {\n  return fetch(`/v3/cluster/logic/estimated-disk-size/${clusterLogicId}/${count}`);\n};\n// 物理集群编辑按钮接口\nexport const improveOpEditCluster = (params: IOpPhysicsClusterDetail) => {\n  return fetch(`/v3/cluster/phy/`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 获取gateway列表数据接口\n// export const GetGatewayList = (params: IOpPhysicsClusterDetail) => {\n//   return fetch(`/v3/phy/cluster/${params.id}/gateway`), {\n//     method: \"PUT\"\n//   }\n// }\n\n// 物理集群删除\nexport const clusterDelete = (params) => {\n  return fetch(`/v3/cluster/phy/${params.regionId}`, {\n    method: \"DELETE\",\n  });\n};\n\n// 快捷命令接口\n// node_state分析\nexport const nodeState = (cluster: any) => {\n  return fetch(`/v3/cluster/phy/${cluster}/node-state-analysis`, {\n    method: \"PUT\",\n    errorNoTips: true,\n  });\n};\n\n// indices分布\nexport const indicesDistribute = (params: any) => {\n  return fetch(`/v3/cluster/phy/indices-distribution`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n    errorNoTips: true,\n  });\n};\n\n// /v3/cluster/phy/shard-distribution shard分布\nexport const shardDistribute = (params: any) => {\n  return fetch(`/v3/cluster/phy/shard-distribution`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n    errorNoTips: true,\n  });\n};\n\n// task任务分析\nexport const task_mission_analysis = (cluster: any) => {\n  return fetch(`/v3/cluster/phy/${cluster}/task-mission-analysis`, {\n    method: \"PUT\",\n    errorNoTips: true,\n  });\n};\n\n// pending task分析\nexport const pendTaskAnalysis = (cluster: any) => {\n  return fetch(`/v3/cluster/phy/${cluster}/pending-task-analysis`, {\n    method: \"PUT\",\n    errorNoTips: true,\n  });\n};\n\n// 热点线程分析\nexport const hotThreadAnalysis = (cluster: any) => {\n  return fetch(`/v3/cluster/phy/${cluster}/hot-thread-analysis`, {\n    method: \"PUT\",\n    errorNoTips: true,\n  });\n};\n\n// shard分配说明\nexport const shardAssignDescription = (cluster: any) => {\n  //测试集群名字\n  return fetch(`/v3/cluster/phy/${cluster}/shard-assignment-description`, {\n    method: \"PUT\",\n    errorNoTips: true,\n  });\n};\n\n// 异常shard分配重试\nexport const abnormalShardRetry = (cluster: any) => {\n  return fetch(`/v3/cluster/phy/${cluster}/abnormal-shard-allocation-retry`, {\n    method: \"PUT\",\n    errorNoTips: true,\n    returnRes: true,\n  });\n};\n\n// 清除fieldData内存\nexport const clearFieldDataMemory = (cluster: any) => {\n  return fetch(`/v3/cluster/phy/${cluster}/clear-field-data-memory`, {\n    method: \"PUT\",\n    errorNoTips: true,\n    returnRes: true,\n  });\n};\n\n// 超级应用的物理集群名称列表\nexport const getSuperPhyClusterList = () => {\n  return fetch(`/v3/cluster/phy/super-phy-names`);\n};\n\n// 超级应用的逻辑集群名称列表，可按物理集群区分\nexport const getSuperLogiClusterList = (phyClusterName?: string) => {\n  return fetch(`/v3/cluster/logic/cluster-phy-logic-names${phyClusterName ? `?phyClusterName=${phyClusterName}` : \"\"}`);\n};\n\n// 普通应用的逻辑集群名称列表\nexport const getMyLogiClusterList = () => {\n  return fetch(`/v3/cluster/logic/cluster-app-logic-names`);\n};\n\n// 获取sense操作记录\nexport const getSenseOperate = (params: any) => {\n  return fetch(`/v3/record/sense-operate-record`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 设置sense操作记录\nexport const setSenseOperate = (params: any) => {\n  return fetch(`/v3/record/sense-operate-record`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n    errorNoTips: true,\n  });\n};\n\n// 获取原生模式下项目对应的访问集群列表\nexport const getEsUserPrimitiveList = (projectId: number) => {\n  return fetch(`/v3/es-user/${projectId}/primitive/cluster/list`);\n};\n\n// 获取集群模式下项目对应的访问集群列表\nexport const getEsUserList = (projectId: number) => {\n  return fetch(`/v3/es-user/${projectId}/cluster/list`);\n};\n\n// 设置应用默认的ES_User\nexport const setDefaultDisplay = (projectId: number, esUser: string) => {\n  return fetch(`/v3/es-user/${projectId}/${esUser}/defaultDisplay`, {\n    method: \"PUT\",\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/cluster-index-api.ts",
    "content": "import { IUNSpecificInfo } from \"typesPath/base-types\";\nimport fetch from \"../lib/fetch\";\nimport store from \"store\";\n\nconst app = store.getState().app;\nexport interface IAllIndexList {\n  page: number;\n  size: number;\n  //权限\n  // authType: number;\n  id?: number;\n  // 名称\n  name?: string;\n  health?: string;\n  //类型\n  dataType?: number;\n  projectId?: number;\n  resourceId?: number;\n  cluster?: string;\n  // hasDCDR?: boolean;\n  desc?: string;\n  sortTerm?: string;\n  orderByDesc?: boolean;\n  hasDCDR?: any;\n  openSrv?: number;\n}\n\nexport interface ISwitchMasterSlave {\n  templateIds: number[];\n  type: number;\n  timeout?: number;\n}\n\n// 获取模板列表\nexport const getAllIndexList = (params: IAllIndexList) => {\n  return fetch(`/v3/template/logic/page`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const getTimeFormat = () => {\n  return fetch(`/v3/config/time-format`);\n};\n\nexport const getIndexDataType = () => {\n  return fetch(`/v3/template/logic/data-type`);\n};\n\nexport const getIndexBaseInfo = (id: number) => {\n  return fetch(`/v3/template/detail/${id}`);\n};\n\nexport const getIndexPartitionList = (id: number) => {\n  return fetch(`/v3/template/cyclical-roll?logicId=${id}`);\n};\n\nexport const deleteIndexInfo = (id: number) => {\n  return fetch(`/v3/template/delete-info/${id}`, {\n    method: \"DELETE\",\n  });\n};\n\n// 校验集群是否能创建模板\nexport const getClusterCheck = (logicClusterId: number) => {\n  return fetch(`/v3/cluster/logic/${logicClusterId}/check-region-not-empty`, {\n    errorNoTips: true,\n    returnRes: true,\n  });\n};\n\nexport const createIndex = (params: any) => {\n  return fetch(`/v3/template/logic`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const updateIndexInfo = (params: any) => {\n  return fetch(`/v3/template`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const getClearInfo = (logicId: number) => {\n  return fetch(`/v3/template/logic/indices?logicId=${logicId}`);\n};\n\n// 模板清理\nexport const clearIndex = (logicId, delIndices) => {\n  return fetch(`/v3/template/logic/indices`, {\n    method: \"DELETE\",\n    body: { logicId, delIndices },\n  });\n};\n\n// 模板扩缩容\nexport const updateShard = (templateId, shardNum) => {\n  return fetch(`/v3/template/logic/${templateId}/${shardNum}/adjust-shard`, {\n    method: \"PUT\",\n  });\n};\n\n// 模板升版本\nexport const updateVision = (templateId) => {\n  return fetch(`/v3/template/logic/${templateId}/upgrade`, {\n    method: \"PUT\",\n  });\n};\n\nexport const getIndexMappingInfo = (logicId: number) => {\n  return fetch(`/v3/template/schema?logicId=${logicId}`);\n};\n\nexport const updateIndexMappingInfo = (params: IUNSpecificInfo) => {\n  return fetch(`/v3/template/schema`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 获取索引模板setting\nexport const getSetting = (logicId: number) => {\n  return fetch(`/v3/template/setting?logicId=${logicId}`);\n};\n\nexport const updateIndexSettingInfo = (params: IUNSpecificInfo) => {\n  return fetch(`/v3/template/setting/${params.logicId}`, {\n    method: \"PUT\",\n    body: JSON.stringify(params.params),\n  });\n};\n\n//获取物理集群索引列表\nexport const getPhyIndexNameList = (clusterPhyName: string) => {\n  return fetch(`/v3/indices/${clusterPhyName}/phy/indices`);\n};\n//获取逻辑集群索引列表\nexport const getLogIndexNameList = (clusterLogicName: string) => {\n  return fetch(`/v3/indices/${clusterLogicName}/logic/indices`);\n};\n\nexport const toDsl = (phyClusterName: string, sql: string) => {\n  return fetch(`/v3/gateway/sql${phyClusterName ? \"/\" + phyClusterName : \"\"}/explain`, {\n    method: \"POST\",\n    prefix: \"sql\",\n    body: sql,\n  });\n};\n\nexport const explainSql = (sql: string, phyClusterName?: string) => {\n  return fetch(`/v3/gateway/sql${phyClusterName ? \"/\" + phyClusterName : \"\"}`, {\n    method: \"POST\",\n    prefix: \"sql\",\n    body: sql,\n  });\n};\n\n// 模板扩缩容信息\nexport const getTemplateIndexDetail = (id: number) => {\n  return fetch(`/v3/templates/physical/${id}`);\n};\n\n// 检查模板名称\nexport const getNameCheck = (templateName: string) => {\n  return fetch(`/v3/template/logic/${templateName}/name-check`, {\n    errorNoTips: true,\n    returnRes: true,\n  });\n};\n\n// 检查索引名称\nexport const checkIndexName = (cluster: string, index: string) => {\n  return fetch(`/v3/indices/${cluster}/${index}/exists`, {\n    errorNoTips: true,\n    returnRes: true,\n  });\n};\n\n// DCDR主从切换接口\nexport const switchMasterSlave = (params: ISwitchMasterSlave) => {\n  return fetch(`/v3/dcdr/work-order/task/switch-master-slave`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n\n// 模版服务列表\nexport const getServiceList = (params: IAllIndexList) => {\n  return fetch(`/v3/template/srv/page`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\n// 模版服务各操作\nexport const updateTemplateSrv = (params: any, method = \"PUT\") => {\n  return fetch(`/v3/template/srv/${params.srvCode}/${params.templateIdList}`, {\n    method: method,\n    body: JSON.stringify(params.params),\n  });\n};\n\n// 创建DCDR链路\nexport const createDCDR = (params: any) => {\n  const { templateId, regionId, targetCluster } = params;\n  return fetch(`/v3/template/dcdr/${templateId}/${regionId}/${targetCluster}`, {\n    method: \"POST\",\n  });\n};\n\n// 查看DCDR链路\nexport const getDCDRDetail = (id: number) => {\n  return fetch(`/v3/template/dcdr/${id}`, { returnRes: true });\n};\n\n// 删除DCDR链路\nexport const deleteDCDR = (id: number) => {\n  return fetch(`/v3/template/dcdr/${id}`, {\n    method: \"DELETE\",\n  });\n};\n\n// 创建DCDR链路时集群下拉列表\nexport const getDCDRCluster = (id: number) => {\n  return fetch(`/v3/cluster/phy/${id}/same-version-and-dcdr-plugin/cluster-names`);\n};\n\n// 创建DCDR链路时region下拉列表\nexport const getDCDRRegion = (cluster: string) => {\n  return fetch(`/v3/cluster/phy/region/${cluster}/dcdr`);\n};\n\n// 不同应用下的逻辑集群\nexport const getClusterPerApp = () => {\n  return fetch(\"/v3/cluster/logic/ids-names\");\n};\n\n// 不同应用下的物理集群\nexport const getPhyClusterPerApp = () => {\n  return fetch(`/v3/cluster/phy/names`, {\n    errorNoTips: true,\n  });\n};\n\n// 不同应用下按type区分的物理集群\nexport const getPhyClusterPerType = (type?: number) => {\n  return fetch(`/v3/cluster/phy/${type}/names`);\n};\n\n// 写变更\nexport const disableWrite = (templateId: any, status) => {\n  return fetch(`/v3/template/srv/${templateId}/block-write?status=${status}`, {\n    method: \"PUT\",\n  });\n};\n\n// 读变更\nexport const disableRead = (templateId: any, status) => {\n  return fetch(`/v3/template/srv/${templateId}/block-read?status=${status}`, {\n    method: \"PUT\",\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/cluster-kanban.ts",
    "content": "import { indexConfigData } from \"container/indicators-kanban/cluster-kanban/node-view-config\";\nimport fetch from \"../lib/fetch\";\nimport { isSuperApp } from \"lib/utils\";\nconst Prefix = \"admin\";\nconst v3Prefix = \"/v3\";\nconst POST = \"POST\";\n\nexport const getLogicClusterNames = () => {\n  return fetch(`${v3Prefix}/cluster/logic/names`, {\n    errorNoTips: true,\n  });\n};\n\ntype secondUserConfigType = \"overview\" | \"node\" | \"index\" | \"template\";\ntype aggType = \"max\" | \"avg\";\n\n// 获取账号下已配置指标列表\nexport const getCheckedList = (secondUserConfigType: secondUserConfigType) => {\n  return fetch(`${v3Prefix}/metrics/cluster/config-metrics`, {\n    method: \"POST\",\n    body: {\n      userName: \"\",\n      firstUserConfigType: \"cluster\",\n      secondUserConfigType,\n      userConfigTypes: [],\n    },\n  });\n};\n\n// 设置账号下已配置指标列表\nexport const setCheckedList = (secondUserConfigType: secondUserConfigType, userConfigTypes: string[]) => {\n  return fetch(`${v3Prefix}/metrics/cluster/config-metrics`, {\n    method: \"PUT\",\n    body: {\n      userName: \"\",\n      firstUserConfigType: \"cluster\",\n      secondUserConfigType,\n      userConfigTypes,\n    },\n  });\n};\n\n// 获取总览视图数据 /v3/metrics/cluster/overview\nexport const getOverviewData = (metricsTypes: string[], clusterPhyName: string, startTime: number, endTime: number) => {\n  if (!clusterPhyName) {\n    return;\n  }\n  let body = {\n    aggType: \"max\",\n    metricsTypes,\n    clusterPhyName,\n    startTime,\n    endTime,\n  } as any;\n  const superApp = isSuperApp();\n  if (!superApp) {\n    delete body.clusterPhyName;\n    body.clusterLogicName = clusterPhyName;\n  }\n  return fetch(`${v3Prefix}/metrics/cluster/overview`, {\n    method: POST,\n    body,\n  });\n};\n\n// 获取节点视图数据 /v3/metrics/cluster/nodes\nexport const getNodeViewData = async (\n  metricsTypes: string[],\n  clusterPhyName: string,\n  startTime: number,\n  endTime: number,\n  topNu: number,\n  nodeIp: string[],\n  topMethod: string,\n  topTimeStep: number\n) => {\n  if (!clusterPhyName) {\n    return;\n  }\n  // 为了兼容task类型的新指标 在请求方式里兼容\n  const taskList = [];\n  const aggTypes = [];\n  let taskData = [];\n  let data = [];\n  const superApp = isSuperApp();\n  metricsTypes = metricsTypes.filter((item) => {\n    if (indexConfigData[item] && indexConfigData[item].newquota) {\n      taskList.push(item);\n      aggTypes.push(indexConfigData[item].newquota);\n      return false;\n    } else {\n      return true;\n    }\n  });\n  if (taskList && taskList.length) {\n    let body = {\n      aggTypes: aggTypes,\n      metricsTypes: taskList,\n      clusterPhyName,\n      startTime,\n      endTime,\n      topNu,\n      nodeNames: nodeIp,\n      topMethod,\n      topTimeStep,\n    } as any;\n    if (!superApp) {\n      delete body.clusterPhyName;\n      body.clusterLogicName = clusterPhyName;\n    }\n    taskData = await fetch(`${v3Prefix}/metrics/cluster/node/task`, {\n      method: POST,\n      body,\n    });\n  }\n  if (metricsTypes && metricsTypes.length) {\n    let body = {\n      aggType: \"avg\",\n      metricsTypes,\n      clusterPhyName,\n      startTime,\n      endTime,\n      topNu,\n      nodeNames: nodeIp,\n      topMethod,\n      topTimeStep,\n    } as any;\n    if (!superApp) {\n      delete body.clusterPhyName;\n      body.clusterLogicName = clusterPhyName;\n    }\n    data = await fetch(`${v3Prefix}/metrics/cluster/nodes`, {\n      method: POST,\n      body,\n    });\n  }\n  return [...data, ...taskData];\n};\n\n// 获取节点视图数据 Ip 名称列表\nexport const getNodeIpList = (clusterPhyName: string) => {\n  const superApp = isSuperApp();\n  return fetch(`${v3Prefix}/cluster/${superApp ? \"phy\" : \"logic\"}/node/${clusterPhyName}/names`, { prefix: Prefix });\n};\n\n// 获取节点视图数据 Ip 名称列表\nexport const getNodeInfoList = (clusterPhyName: string) => {\n  const superApp = isSuperApp();\n  return fetch(`${v3Prefix}/cluster/${superApp ? \"phy\" : \"logic\"}/node/${clusterPhyName}/infos`);\n};\n\n// 获取index视图数据\nexport const getIndexViewData = (\n  metricsTypes: string[],\n  clusterPhyName: string,\n  startTime: number,\n  endTime: number,\n  topNu: number,\n  indexNames: string[],\n  topMethod: string,\n  topTimeStep: number\n) => {\n  if (!clusterPhyName) {\n    return;\n  }\n  const superApp = isSuperApp();\n  let body = {\n    aggType: \"avg\",\n    metricsTypes,\n    clusterPhyName,\n    startTime,\n    endTime,\n    topNu,\n    indexNames,\n    topMethod,\n    topTimeStep,\n  } as any;\n  if (!superApp) {\n    delete body.clusterPhyName;\n    body.clusterLogicName = clusterPhyName;\n  }\n  return fetch(`${v3Prefix}/metrics/cluster/indices`, {\n    method: POST,\n    body,\n  });\n};\n\n// 获取索引模板视图数据 /v3/metrics/cluster/template\nexport const getTemplateViewData = (\n  metricsTypes: string[],\n  clusterPhyName: string,\n  startTime: number,\n  endTime: number,\n  topNu: number,\n  templateIdList: string[],\n  aggType,\n  topMethod: string,\n  topTimeStep: number\n) => {\n  if (!clusterPhyName) {\n    return;\n  }\n  const superApp = isSuperApp();\n  let body = {\n    aggType,\n    metricsTypes,\n    clusterPhyName,\n    startTime,\n    endTime,\n    topNu,\n    templateIdList,\n    topMethod,\n    topTimeStep,\n  } as any;\n  if (!superApp) {\n    delete body.clusterPhyName;\n    body.clusterLogicName = clusterPhyName;\n  }\n  return fetch(`${v3Prefix}/metrics/cluster/templates`, {\n    method: POST,\n    body,\n  });\n};\n\n// 获取index视图 index 列表数据\nexport const getPhyIndexNameList = (clusterPhyName) => {\n  return fetch(`${v3Prefix}/indices/${clusterPhyName}/phy/indices`);\n};\n\nexport const getLogicIndexNameList = (logicClusterName) => {\n  return fetch(`${v3Prefix}/indices/${logicClusterName}/logic/indices`);\n};\n\n// 获取索引模板 索引模板 列表数据\nexport const getPhyListTemplates = (clusterPhyName) => {\n  return fetch(`${v3Prefix}/template/logic/${clusterPhyName}/phy/templates`);\n};\n\nexport const getLogicListTemplates = (logicClusterName) => {\n  return fetch(`${v3Prefix}/template/logic/${logicClusterName}/logic/templates`);\n};\n\n// 获取chartTable\nexport const getChartTableList = (clusterPhyName, node, time) => {\n  return fetch(`${v3Prefix}/metrics/cluster/${clusterPhyName}/${node}/task?startTime=${time[0]}&endTime=${time[1]}`, {\n    prefix: Prefix,\n  });\n};\n\n// 通过model筛选获取指标字典信息\nexport const getDictionary = (params) => {\n  return fetch(`${v3Prefix}/metrics/dictionary`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/cluster-node-api.ts",
    "content": "import fetch from \"../lib/fetch\";\n\nexport const getLogicClusterNodeList = (clusterId: number) => {\n  return fetch(`/v3/cluster/logic/node/${clusterId}`);\n};\n"
  },
  {
    "path": "arius-console/src/api/common-api.ts",
    "content": "import fetch from \"../lib/fetch\";\nimport { apiCache } from \"lib/api-cache\";\nimport { showSubmitOrderSuccessModal } from \"container/custom-component\";\nimport { IWorkOrder } from \"typesPath/params-types\";\n\n/*\n * 外部的接口\n *@部门、用户\n */\n\nexport const getAllUserList = () => {\n  return fetch(\"/v3/security/project/bind-user\");\n};\n\n// 工单接口\nexport const submitWorkOrder = (params: any, history?: any, actionAfterSubmit?: () => any, modalWidth?: number) => {\n  return fetch(`/v3/order/${params.type}/submit`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  }).then((data) => {\n    actionAfterSubmit();\n    showSubmitOrderSuccessModal(\n      {\n        title: data?.title || \"\",\n        id: data.id,\n        width: modalWidth,\n      },\n      history\n    );\n    return data;\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/dashboard.ts",
    "content": "import fetch from \"../lib/fetch\";\nconst POST = \"POST\";\nconst v3Prefix = `/v3`;\nconst dashboardMetrics = `/dashboard/metrics`;\n\nexport interface ILineParams {\n  metricsTypes: string[];\n  startTime: number;\n  endTime: number;\n  topNu: number;\n  aggType: string;\n}\n\n// /v3/dashboard/metrics/health 获取dashboard大盘健康状态信息\nexport const dashboardHealth = () => {\n  return fetch(`${v3Prefix}${dashboardMetrics}/health`);\n};\n\n// /v3/dashboard/metrics/list/cluster 获取dashboard大盘集群相关list列表指标信息\nexport const clusterList = (params: { aggType: string; metricsTypes: string[] }) => {\n  return fetch(`${v3Prefix}${dashboardMetrics}/list/cluster`, {\n    method: POST,\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/dashboard/metrics/list/index 获取dashboard大盘索引相关list列表指标信息\nexport const indexList = (params: ILineParams) => {\n  return fetch(`${v3Prefix}${dashboardMetrics}/list/index`, {\n    method: POST,\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/dashboard/metrics/list/node 获取dashboard大盘节点相关list列表指标信息\nexport const nodeList = (params: ILineParams) => {\n  return fetch(`${v3Prefix}${dashboardMetrics}/list/node`, {\n    method: POST,\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/dashboard/metrics/list/template 获取dashboard大盘模板相关list列表指标信息\nexport const templatelist = (params: ILineParams) => {\n  return fetch(`${v3Prefix}${dashboardMetrics}/list/template`, {\n    method: POST,\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/dashboard/metrics/top/cluster 获取dashboard大盘TopN集群相关指标信息\nexport const clusterLine = (params: ILineParams) => {\n  return fetch(`${v3Prefix}${dashboardMetrics}/top/cluster`, {\n    method: POST,\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/dashboard/metrics/top/cluster-thread-pool-queue 获取dashboard大盘TopNES线程池相关指标信息\nexport const clusterThreadPoolQueue = (params: ILineParams) => {\n  return fetch(`${v3Prefix}${dashboardMetrics}/top/cluster-thread-pool-queue`, {\n    method: POST,\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/dashboard/metrics/top/index 获取dashboard大盘TopN索引相关指标信息\nexport const indexLine = (params: ILineParams) => {\n  return fetch(`${v3Prefix}${dashboardMetrics}/top/index`, {\n    method: POST,\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/dashboard/metrics/top/node 获取dashboard大盘TopN节点相关指标信息\nexport const nodeLine = (params: ILineParams) => {\n  return fetch(`${v3Prefix}${dashboardMetrics}/top/node`, {\n    method: POST,\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/dashboard/metrics/top/template 获取dashboard大盘TopN模板相关指标信息\nexport const templateLine = (params: ILineParams) => {\n  return fetch(`${v3Prefix}${dashboardMetrics}/top/template`, {\n    method: POST,\n    body: JSON.stringify(params),\n  });\n};\n\n// /v3/metrics/cluster/config-metrics 获取账号下已配置指标类型\nexport const getCheckedList = (secondUserConfigType: string) => {\n  return fetch(`${v3Prefix}/metrics/cluster/config-metrics`, {\n    method: POST,\n    body: {\n      userName: \"\",\n      firstUserConfigType: \"dashboard\",\n      secondUserConfigType,\n      userConfigTypes: [],\n    },\n  });\n};\n\n// /v3/metrics/cluster/config-metrics 更新账号下已配置指标类型\nexport const setCheckedList = (secondUserConfigType: string, userConfigTypes: string[]) => {\n  return fetch(`${v3Prefix}/metrics/cluster/config-metrics`, {\n    method: \"PUT\",\n    body: {\n      userName: \"\",\n      firstUserConfigType: \"dashboard\",\n      secondUserConfigType,\n      userConfigTypes,\n    },\n  });\n};\n\n// /v3/dashboard/metrics/health 获取dashboard大盘健康状态信息\nexport const dashboardIndex = () => {\n  return fetch(`/v3/dashboard/metrics/dashboard-threshold`);\n};\n\n// 通过model筛选获取指标字典信息\nexport const getDictionary = (params) => {\n  return fetch(`${v3Prefix}/metrics/dictionary`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/dcdr-api.ts",
    "content": "import fetch from \"../lib/fetch\";\n\n// 获取dcdr主从切换任务详情\nexport const getDcdrDetail = (taskId: number) => {\n  return fetch(`/v3/dcdr/work-order/task/${taskId}/detail`);\n};\n\n// 获取模板dcdr主从切换任务详情\nexport const getTemplateDcdrDetail = (taskId: number, templateId: number) => {\n  return fetch(`/v3/dcdr/work-order/task/${taskId}/${templateId}/detail`);\n};\n\n// 根据任务id取消全量DCDR主从切换任务\nexport const cancelDcdr = (taskId: number) => {\n  return fetch(`/v3/dcdr/work-order/task/${taskId}/cancel`, {\n    method: \"DELETE\",\n  });\n};\n\n// 根据任务id和模板id取消单个DCDR主从切换任务\nexport const canceltemplateDcdr = (taskId: number, templateIds: number) => {\n  return fetch(`/v3/dcdr/work-order/task/${taskId}/${templateIds}/cancel`, {\n    method: \"DELETE\",\n  });\n};\n\n// dcdr主从强制切换接口\nexport const dcdrForceSwitch = (taskId: number, templateId: number) => {\n  return fetch(`/v3/dcdr/work-order/task/${taskId}/${templateId}/forceSwitch`, {\n    method: \"PUT\",\n  });\n};\n\n// 刷新dcdr链路任务\nexport const dcdrRefresh = (taskId: number, templateId: number) => {\n  return fetch(`/v3/dcdr/work-order/task/${taskId}/${templateId}/refresh`, {\n    method: \"POST\",\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/gateway-kanban.ts",
    "content": "import fetch from \"../lib/fetch\";\nconst prefix = \"/v3\";\nconst POST = \"POST\";\n\ntype secondUserConfigType = \"overview\" | \"node\" | \"index\" | \"app\" | \"dsl\" | \"clientNode\";\n\n// 获取账号下已配置指标列表\nexport const getCheckedList = (secondUserConfigType: secondUserConfigType) => {\n  return fetch(`${prefix}/metrics/cluster/config-metrics`, {\n    method: \"POST\",\n    body: {\n      userName: \"\",\n      firstUserConfigType: \"gateway\",\n      secondUserConfigType,\n      userConfigTypes: [],\n    },\n  });\n};\n\n// 设置账号下已配置指标列表\nexport const setCheckedList = (secondUserConfigType: secondUserConfigType, userConfigTypes: string[]) => {\n  return fetch(`${prefix}/metrics/cluster/config-metrics`, {\n    method: \"PUT\",\n    body: {\n      userName: \"\",\n      firstUserConfigType: \"gateway\",\n      secondUserConfigType,\n      userConfigTypes,\n    },\n  });\n};\n\n//  获取总览视图数据\nexport const getOverviewData = (metricsTypes: string[], startTime: number, endTime: number) => {\n  return fetch(`${prefix}/metrics/gateway/overview`, {\n    method: POST,\n    body: {\n      metricsTypes,\n      startTime,\n      endTime,\n    },\n  });\n};\n\n// 获取节点视图\nexport const getNodeViewData = (\n  metricsTypes: string[],\n  startTime: number,\n  endTime: number,\n  topNu: number,\n  nodeIp: string[],\n  topMethod: string,\n  topTimeStep: number\n) => {\n  let body = {\n    metricsTypes,\n    startTime,\n    endTime,\n    nodeIps: nodeIp,\n    topNu,\n    topMethod,\n    topTimeStep,\n  };\n  return fetch(`${prefix}/metrics/gateway/nodes`, {\n    method: POST,\n    body,\n  });\n};\n\n// 获取clientNode节点视图\nexport const getClientNodeViewData = (\n  metricsTypes: string[],\n  startTime: number,\n  endTime: number,\n  topNu: number,\n  nodeIp: string,\n  clientNodeIp: string,\n  topMethod: string,\n  topTimeStep: number\n) => {\n  return fetch(`${prefix}/metrics/gateway/client-node`, {\n    method: POST,\n    body: {\n      metricsTypes,\n      startTime,\n      endTime,\n      nodeIp,\n      topNu,\n      clientNodeIp,\n      topMethod,\n      topTimeStep,\n    },\n  });\n};\n\nexport const getNodeIpList = () => {\n  return fetch(`${prefix}/metrics/gateway/alive-nodes`);\n};\n\n//获取取gatewayNode相关的clientNode ip列表\nexport const getClientNodeList = (gatewayNode, startTime, endTime) => {\n  return fetch(`${prefix}/metrics/gateway/client-node-ip?gatewayNode=${gatewayNode || \"\"}&startTime=${startTime}&endTime=${endTime}`);\n};\n\n// 获取索引视图数据\nexport const getIndexViewData = (\n  metricsTypes: string[],\n  startTime: number,\n  endTime: number,\n  topNu: number,\n  indexName: string,\n  topMethod: string,\n  topTimeStep: number\n) => {\n  return fetch(`${prefix}/metrics/gateway/index`, {\n    method: POST,\n    body: {\n      metricsTypes,\n      startTime,\n      endTime,\n      indexName,\n      topNu,\n      topMethod,\n      topTimeStep,\n    },\n  });\n};\n\n// 获取index视图 index 列表数据\nexport const getIndexNameList = () => {\n  return fetch(`${prefix}/template/logic/names`);\n};\n\n// 获取项目视图数据\nexport const getProjectViewData = (\n  metricsTypes: string[],\n  startTime: number,\n  endTime: number,\n  topNu: number,\n  projectId: string,\n  topMethod: string,\n  topTimeStep: number\n) => {\n  return fetch(`${prefix}/metrics/gateway/projects`, {\n    method: POST,\n    body: {\n      metricsTypes,\n      startTime,\n      endTime,\n      projectId,\n      topNu,\n      topMethod,\n      topTimeStep,\n    },\n  });\n};\n\nexport const getProjectIdList = () => {\n  return fetch(`${prefix}/security/project`);\n};\n\n// 获取查询模板数据\nexport const getQueryTemplateData = (\n  metricsTypes: string[],\n  startTime: number,\n  endTime: number,\n  topNu: number,\n  dslMd5: string,\n  topMethod: string,\n  topTimeStep: number\n) => {\n  return fetch(`${prefix}/metrics/gateway/dsl`, {\n    method: POST,\n    body: {\n      metricsTypes,\n      startTime,\n      endTime,\n      dslMd5,\n      topNu,\n      topMethod,\n      topTimeStep,\n    },\n  });\n};\n\nexport const getDslMd5List = (startTime: number, endTime: number) => {\n  return fetch(`${prefix}/metrics/gateway/dsl-md5?startTime=${startTime}&endTime=${endTime}`);\n};\n"
  },
  {
    "path": "arius-console/src/api/index-admin.ts",
    "content": "import fetch from \"../lib/fetch\";\n\nconst v3Prefix = \"/v3\";\n\ninterface indexAdminType {\n  page: number;\n  size: number;\n  cluster?: string;\n  index?: string;\n  health?: string;\n  orderByDesc?: boolean;\n  sortTerm?: string;\n}\n\n// 获取索引管理数据\nexport const getIndexAdminData = (data: indexAdminType) => {\n  return fetch(`${v3Prefix}/indices/page`, {\n    method: \"POST\",\n    body: data,\n  });\n};\n\nexport const addIndexAdmin = (data: any) => {\n  return fetch(`${v3Prefix}/indices`, {\n    method: \"POST\",\n    body: data,\n    returnRes: true,\n  });\n};\n\ninterface delListType {\n  clusterPhyName: string;\n  index: string;\n}\n\nexport const delIndexAdminData = (delList: delListType[]) => {\n  return fetch(`${v3Prefix}/indices`, {\n    method: \"DELETE\",\n    body: delList,\n  });\n};\n\ninterface configType {\n  cluster: string;\n  index: string;\n  type?: string;\n  value?: boolean;\n}\n\nexport const openOrCloseReadOrWrite = (configList: configType[]) => {\n  return fetch(`${v3Prefix}/indices/block`, {\n    method: \"PUT\",\n    body: configList,\n  });\n};\n\nexport const indicesClose = (configList: configType[]) => {\n  return fetch(`${v3Prefix}/indices/close`, {\n    method: \"PUT\",\n    body: configList,\n  });\n};\n\nexport const indicesOpen = (configList: configType[]) => {\n  return fetch(`${v3Prefix}/indices/open`, {\n    method: \"PUT\",\n    body: configList,\n  });\n};\n\n// 获取索引shard分配详情\nexport const getShardDetail = (cluster: string, index: string) => {\n  return fetch(`${v3Prefix}/indices/${cluster}/${index}/shard`);\n};\n\nexport const getMapping = (cluster: string, index: string) => {\n  return fetch(`${v3Prefix}/indices/${cluster}/${index}/mapping`);\n};\n\nexport const updateMapping = (params) => {\n  return fetch(`${v3Prefix}/indices/mapping`, {\n    method: \"PUT\",\n    body: params,\n  });\n};\n\nexport const getSetting = (cluster: string, index: string) => {\n  return fetch(`${v3Prefix}/indices/${cluster}/${index}/setting`);\n};\n\nexport const updateSetting = (params) => {\n  return fetch(`${v3Prefix}/indices/setting`, {\n    method: \"PUT\",\n    body: params,\n  });\n};\n\nexport const getIndexDetail = (cluster: string, index: string) => {\n  return fetch(`${v3Prefix}/indices/${cluster}/${index}`);\n};\n\nexport const setAlias = (params) => {\n  return fetch(`${v3Prefix}/indices/alias`, {\n    method: \"PUT\",\n    body: params,\n  });\n};\n\nexport const deleteAlias = (params) => {\n  return fetch(`${v3Prefix}/indices/alias`, {\n    method: \"DELETE\",\n    body: params,\n  });\n};\n\nexport const executeRollover = (params) => {\n  return fetch(`${v3Prefix}/indices/srv/rollover`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n\nexport const executeForceMerge = (params) => {\n  return fetch(`${v3Prefix}/indices/srv/force-merge`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n\nexport const executeShrink = (params) => {\n  return fetch(`${v3Prefix}/indices/srv/shrink`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n\nexport const executeSplit = (params) => {\n  return fetch(`${v3Prefix}/indices/srv/split`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/index.ts",
    "content": "export * from './app-api'"
  },
  {
    "path": "arius-console/src/api/logi-security.ts",
    "content": "import fetch, { formFetch } from \"../lib/fetch\";\n\nconst prefix = `/v3/security`;\n\nexport const userLogin = (params: any) => {\n  return fetch(`${prefix}/account/login`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const userLogout = () => {\n  return fetch(`${prefix}/account/logout`, {\n    method: \"POST\",\n  });\n};\n\nexport const userRegister = (params: any) => {\n  return fetch(`${prefix}/user`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const updateUserInfo = (params: any) => {\n  return fetch(`${prefix}/user`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const checkRegisterUser = (type: number, value: string) => {\n  return fetch(`${prefix}/user/${type}/${value}/check`);\n};\n\nexport const getUser = (id: number) => {\n  return fetch(`${prefix}/user/${id}`);\n};\n\nexport const getUserList = (params: any) => {\n  return fetch(`${prefix}/user/page`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const getRoleList = (params: any) => {\n  return fetch(`${prefix}/role/page`, {\n    method: \"POST\",\n    body: JSON.stringify(params),\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/op-cluster-config-api.ts",
    "content": "import fetch from \"../lib/fetch\";\n\n// 获取ES集群配置接口\nexport const getPhyClusterConfigList = (clusterId: number) => {\n  return fetch(`/v3/cluster/phy/config-file?clusterId=${clusterId}`);\n};\n\n// 获取ES集群配置接口\nexport const getPhyClusterConfig = (configId: number) => {\n  return fetch(`/v3/cluster/phy/config-file/${configId}`);\n};\n\n// 获取ES集群模板配置接口\nexport const getClusterTemplateCentent = (type: string) => {\n  return fetch(`/v3/cluster/phy/config-file/template/${type}`);\n};\n"
  },
  {
    "path": "arius-console/src/api/op-cluster-index-api.ts",
    "content": "import fetch, { formFetch } from \"../lib/fetch\";\n\nexport const getPhyNodeDivideList = (clusterId: number) => {\n  return fetch(`/v3/cluster/phy/node/${clusterId}`); // regioninfo\n};\n\n// 批量下线离线节点\nexport const deleteNode = (params) => {\n  return fetch(`/v3/cluster/phy/node`, {\n    method: \"DELETE\",\n    body: JSON.stringify(params),\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/op-cluster-region-api.ts",
    "content": "import fetch from \"../lib/fetch\";\n\n// GET /v3/cluster/phy/region/${clusterName}/${clusterLogicType} 获取物理集群region列表接口\nexport const getPhyClusterRegionList = (clusterName: string, clusterLogicType, params) => {\n  return fetch(`/v3/cluster/phy/region/${clusterName}/${clusterLogicType}`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n\nexport const logicClusterRegionList = (logicClusterId: any) => {\n  return fetch(`/v3/cluster/logic/region?logicClusterId=${logicClusterId}`);\n};\n\nexport const logicClusterNodesList = (id) => {\n  return fetch(`/v3/cluster/phy/region/${id}/nodes`);\n};\n\nexport const getRegionNodeSpec = (logicClusterId: any) => {\n  return fetch(`/v3/cluster/logic/dataNodeSpec/${logicClusterId}`);\n};\n"
  },
  {
    "path": "arius-console/src/api/order-api.ts",
    "content": "import fetch from \"../lib/fetch\";\n\n/**\n * order 相关接口\n *\n */\n\n// 获取工单类型\nexport const getTypeEnums = () => {\n  return fetch(`/v3/order/type-enums`);\n};\n\nexport const getApplyOrderList = (status: number) => {\n  return fetch(`/v3/order/orders?status=${status === 1 ? \"\" : status}`);\n};\n\nexport const getApprovalOrderList = (status: number) => {\n  return fetch(`/v3/order/approvals?status=${status === 1 ? \"\" : status}`);\n};\n\nexport const cancelOrder = (orderId: number) => {\n  return fetch(`/v3/order/${orderId}`, {\n    method: \"DELETE\",\n  });\n};\n\n// 工单详情\nexport const getOrderDetail = (orderId: number) => {\n  return fetch(`/v3/order/${orderId}`);\n};\n\nexport const approvalOrder = (params: any) => {\n  return fetch(`/v3/order/${params.orderId}`, {\n    method: \"PUT\",\n    body: JSON.stringify(params),\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/plug-api.ts",
    "content": "import { AlertTwoTone } from \"@ant-design/icons\";\nimport fetch, { formFetch } from \"../lib/fetch\";\n\n/*\n * 插件 相关接口\n */\nexport const getPlugList = () => {\n  return fetch(`/v3/normal/ecm/plugin`);\n};\n\n// 获取插件列表\nexport const getOpClusterPlugList = (name: string) => {\n  const cluster = name;\n  return fetch(`/v3/cluster/phy/plugins/${cluster}`);\n};\n\n// 添加插件\nexport const addPlug = (params: any) => {\n  const { creator, desc, name, md5, uploadFile, fileName, pDefault, logicClusterId, physicsClusterId } = params;\n  const formData = new FormData();\n  formData.append(\"uploadFile\", uploadFile);\n  formData.append(\"desc\", desc || \"\");\n  formData.append(\"md5\", md5);\n  formData.append(\"name\", fileName);\n  formData.append(\"creator\", creator);\n  formData.append(\"fileName\", fileName);\n  formData.append(\"pDefault\", pDefault);\n  // 后端需要返回值 physicClusterId， 没有 s\n  formData.append(\"physicClusterId\", physicsClusterId);\n  if (logicClusterId) {\n    formData.append(\"logicClusterId\", logicClusterId + \"\");\n  }\n  return formFetch(`/v3/cluster/phy/plugins`, {\n    method: \"POST\",\n    body: formData,\n  });\n};\n\n// 编辑插件\nexport const editPlug = (id: number | string, desc: string) => {\n  return fetch(`/v3/cluster/phy/plugins`, {\n    method: \"PUT\",\n    body: {\n      id: id,\n      desc: desc,\n    },\n  });\n};\n\n// 删除插件\nexport const userDelPlug = (id: number) => {\n  return fetch(`/v3/cluster/phy/plugins/${id}`, {\n    method: \"DELETE\",\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/search-query.ts",
    "content": "import fetch from \"../lib/fetch\";\nimport { objTransUrlParams } from \"../lib/utils\";\nconst Prefix = \"admin\";\nconst POST = \"POST\";\n\ninterface IErrorList {\n  queryIndex: string;\n  startDate: string;\n  endDate: string;\n}\n\ninterface ISlowList {\n  queryIndex: string;\n  startDate: string;\n  endDate: string;\n  from: number;\n  size: number;\n}\n\ninterface IDslList {\n  endTime: number;\n  startTime: number;\n  page: number;\n  size: number;\n  dslTemplateMd5?: string;\n  queryIndex?: string;\n  sortInfo?: string;\n  orderByDesc?: boolean;\n}\n\ninterface IDetail {\n  dslTemplateMd5: string;\n  endDate: number;\n  startDate: number;\n}\n\ninterface IqueryLimit {\n  dslTemplateMd5: string;\n  queryLimit: string;\n  projectId: number;\n}\n\nexport const getErrorQueryList = (params: IErrorList) => {\n  return fetch(`/v3/dsl/template/error/page`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n\nexport const getSlowQueryList = (params: ISlowList) => {\n  return fetch(`/v3/dsl/template/slow/page`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n\n// 根据查询条件获取查询模板数据\nexport const getDslList = (params: IDslList) => {\n  return fetch(\"/v3/dsl/template/page\", {\n    method: \"POST\",\n    body: params,\n  });\n};\n\n// 根据查询条件获取查询模板数据\nexport const changeStatus = (dslTemplateMd5: string, projectId) => {\n  return fetch(`/v3/dsl/template/status/${dslTemplateMd5}?projectId=${projectId}`, {\n    method: \"PUT\",\n  });\n};\n\n// 修改查询模板限流值\nexport const queryLimit = (params: IqueryLimit[]) => {\n  return fetch(`/v3/dsl/template/query-limit`, {\n    method: \"PUT\",\n    body: params,\n  });\n};\n\n// 获取dsl的指标信息\nexport const getDslDetail = (dslTemplateMd5: string, projectId) => {\n  return fetch(`/v3/dsl/template/detail/${dslTemplateMd5}?projectId=${projectId}`);\n};\n\n// 获取dsl的语句\nexport const getDslByIndex = (indexName: string) => {\n  return fetch(`/v3/dsl/template/${indexName}`);\n};\n\n// 获取账号下已配置的列\nexport const getCheckedList = () => {\n  return fetch(\"/v3/dsl/template/dsl-template-config\", {\n    prefix: Prefix,\n    method: \"POST\",\n    body: {\n      userName: \"\",\n      firstUserConfigType: \"searchQuery\",\n      secondUserConfigType: \"searchTemplate\",\n      userConfigTypes: [],\n    },\n  });\n};\n\n// 设置列\nexport const setCheckedList = (userConfigTypes: string[]) => {\n  return fetch(\"/v3/dsl/template/dsl-template-config\", {\n    prefix: Prefix,\n    method: \"PUT\",\n    body: {\n      userName: \"\",\n      firstUserConfigType: \"searchQuery\",\n      secondUserConfigType: \"searchTemplate\",\n      userConfigTypes,\n    },\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/task-api.ts",
    "content": "import fetch, { formFetch } from \"../lib/fetch\";\n\nexport const getTaskList = (params) => {\n  return fetch(`/v3/op-task/page`, {\n    method: \"POST\",\n    body: params,\n  });\n};\n\nexport const getTaskBaseInfo = (id: number) => {\n  return fetch(`/v3/op/ecm/work-order/task/${id}/basic-info`);\n};\n\nexport const getTaskDetail = (id: number) => {\n  return fetch(`/v3/op/ecm/work-order/task/${id}/task-details`);\n};\n\nexport const getTaskLog = (id: number) => {\n  return fetch(`/v3/op/ecm/work-order/task/${id}/task-detail/log`);\n};\n\nexport const redofailedTask = (id: number, hostname: string) => {\n  // 重试\n  return fetch(`/v3/op/ecm/work-order/task/${id}/redo-failed?hostname=${hostname}`, {\n    method: \"POST\",\n  });\n};\n\nexport const pauseTask = (id: number) => {\n  // 暂停\n  return fetch(`/v3/op/ecm/work-order/task/${id}/pause`, {\n    method: \"POST\",\n  });\n};\n\nexport const continueTask = (id: number) => {\n  // 继续\n  return fetch(`/v3/op/ecm/work-order/task/${id}/continue`, {\n    method: \"POST\",\n  });\n};\n\nexport const cancalTask = (id: number) => {\n  // 取消\n  return fetch(`/v3/op/ecm/work-order/task/${id}/cancel`, {\n    method: \"POST\",\n  });\n};\n\nexport const createTask = (id: number) => {\n  // 启动\n  return fetch(`/v3/op/ecm/work-order/task/${id}/create`, {\n    method: \"POST\",\n  });\n};\n\nexport const scaleTask = (id: number) => {\n  // 扩缩容\n  return fetch(`/v3/op/ecm/work-order/task/${id}/scale`, {\n    method: \"POST\",\n  });\n};\n\nexport const restartTask = (id: number) => {\n  // 重启\n  return fetch(`/v3/op/ecm/work-order/task/${id}/restart`, {\n    method: \"POST\",\n  });\n};\nexport const retryTask = (id: number) => {\n  // 重试\n  return fetch(`/v3/op/ecm/work-order/task/${id}/retry`, {\n    method: \"POST\",\n  });\n};\n\nexport const upgradeTask = (id: number) => {\n  // 升级\n  return fetch(`/v3/op/ecm/work-order/task/${id}/upgrade`, {\n    method: \"POST\",\n  });\n};\n"
  },
  {
    "path": "arius-console/src/api/user-api.ts",
    "content": "import fetch, { formFetch } from \"../lib/fetch\";\nconst v3Prefix = `/v3`;\nconst logiSecurityRole = `/security/role`;\n\nexport const judgeAdminUser = () => {\n  return fetch(`${v3Prefix}${logiSecurityRole}/is-admin`, { errorNoTips: true, returnRes: true });\n};\n"
  },
  {
    "path": "arius-console/src/app.tsx",
    "content": "import \"@babel/polyfill\";\nimport \"whatwg-fetch\";\nimport React, { useMemo, useState } from \"react\";\nimport { BrowserRouter, Switch, Route, Redirect } from \"react-router-dom\";\nimport _ from \"lodash\";\nimport { ConfigProvider, Modal, Spin } from \"antd\";\nimport zhCN from \"antd/lib/locale/zh_CN\";\nimport antdZhCN from \"antd/lib/locale/zh_CN\";\nimport antdEnUS from \"antd/lib/locale/en_US\";\nimport { IntlProvider } from \"react-intl\";\nimport intlZhCN, { permissions } from \"./locales/zh\";\nimport intlEnUS from \"./locales/en\";\nimport { LayoutHeaderNav } from \"./d1-packages\";\nimport { Page403, Page404 } from \"./d1-packages\";\nimport { LeftMenu } from \"./d1-packages\";\nimport { InjectIntlContext } from \"knowdesign/lib/hook/use-format-message\";\nimport { leftMenus, systemKey } from \"./constants/menu\";\nimport { Provider as ReduxProvider } from \"react-redux\";\nimport store, { useGlobalPathStatus, useGlobalLoginStatus } from \"./store\";\nimport \"./styles/common.less\";\nimport { LoginOrRegister } from \"./d1-packages/CommonPages/Login\";\nimport { getCookie, getCurrentProject, setCookie, dealPathname, isSuperApp, currentLeftIndex, redirectPath } from \"lib/utils\";\nimport { getUser, userLogout } from \"api/logi-security\";\nimport \"./assets/icon/iconfont.css\";\nimport \"./assets/icon/iconfont.js\";\nimport * as actions from \"actions\";\nimport { RouteGuard } from \"./d1-packages/RouterGuard\";\nimport { PageRoutes } from \"./pages/index\";\nimport { dropByCacheKey } from \"react-router-cache-route\";\nimport AllModalInOne from \"container/AllModalInOne\";\nimport FullScreen from \"container/full-screen\";\nimport { mulityPage } from \"./pages/cachePage\";\nimport { CURRENT_PROJECT_KEY } from \"constants/common\";\nimport { IProject } from \"interface/project\";\nimport { getProjectListByUserId, getNoCodeLoginAppList } from \"api/app-api\";\nimport { getPagePermission } from \"lib/permission\";\nimport { IPermission } from \"store/type\";\nimport { judgeAdminUser } from \"api/user-api\";\ninterface ILocaleMap {\n  [index: string]: any;\n}\n\nconst localeMap: ILocaleMap = {\n  zh: {\n    antd: antdZhCN,\n    intl: \"zh\",\n    intlMessages: intlZhCN,\n    title: systemKey,\n  },\n  en: {\n    antd: antdEnUS,\n    intl: \"en\",\n    intlMessages: intlEnUS,\n    title: systemKey,\n  },\n};\n\nexport const { Provider, Consumer } = React.createContext(\"zh\");\n\nconst defaultLanguage = window.localStorage.getItem(\"language\") || \"zh\"; // navigator.language.substr(0, 2)\nconst feConfig = require(\"../config/feConfig.json\");\n\nconst App = () => {\n  const [language, setLanguage] = useState(defaultLanguage);\n  const [projectList, setProjectList] = useState([]); // 项目列表\n  const [loading, setLoading] = useState(true);\n  const [currentProject, setCurrentProject] = useState(getCurrentProject());\n  const [permissionPoints, setPermissionPoints] = useState<IPermission[]>([]);\n  const [leftIndex, setLeftIndex] = useState(currentLeftIndex(isSuperApp()));\n\n  const intlMessages = _.get(localeMap[language], \"intlMessages\", intlZhCN);\n  const title = _.get(localeMap[language], \"title\");\n  const initCollapsed = getCookie(\"siderMenuCollapsed\");\n  const [siderMenuCollapsed, setSiderMenuCollapsed] = React.useState(initCollapsed === \"true\");\n  const [removePath, setRemovePaths] = useGlobalPathStatus();\n  const [loginStatus] = useGlobalLoginStatus();\n  const setHeaderClick = (key, props: any) => {\n    if (currentLeftIndex(isSuperApp()) !== key) {\n      props.history.push(key ? \"/system/project\" : isSuperApp() ? \"/dashboard\" : \"/cluster/logic\");\n    }\n  };\n\n  const getPermissions = () => {\n    const userId = getCookie(\"userId\");\n    setLoading(true);\n    getUser(+userId)\n      .then((res) => {\n        const _permissionPoints = res.permissionTreeVO?.childList || [];\n        _permissionPoints.push({\n          permissionName: \"dashboard\",\n          has: getCookie(\"isAdminUser\") === \"yes\" && isSuperApp(),\n        });\n        setPermissionPoints(_permissionPoints);\n        store.dispatch(actions.setUserPermissionTree(_permissionPoints));\n      })\n      .finally(() => {\n        setLoading(false);\n        store.dispatch(actions.setIsAdminUser(getCookie(\"isAdminUser\") === \"yes\"));\n      });\n  };\n\n  const setProjectInfo = (currentProject) => {\n    if (currentProject?.id) {\n      window.localStorage.setItem(CURRENT_PROJECT_KEY, JSON.stringify(currentProject));\n      getNoCodeLoginAppList(currentProject?.id).then((res) => {\n        let filterData = res.filter((item) => item.defaultDisplay);\n        let secret = `${(filterData[0] || res[0])?.id}:${(filterData[0] || res[0])?.verifyCode}`;\n        setCookie([{ key: \"Authorization\", value: btoa(secret) }]);\n      });\n    }\n    getPermissions();\n  };\n\n  const changeCurrentProject = (value, props: any) => {\n    setCurrentProject(value);\n    setProjectInfo(value);\n    setLeftIndex(0);\n    console.log(isSuperApp());\n    props.history.push(isSuperApp() ? \"/dashboard\" : \"/cluster/logic\");\n  };\n\n  React.useEffect(() => {\n    const userId = getCookie(\"userId\");\n    if (!userId && !window.location.pathname.includes(\"/login\")) {\n      window.location.href = \"/login\";\n      return;\n    }\n    if (window.location.pathname.includes(\"/login\")) {\n      return;\n    }\n    setLoading(true);\n    store.dispatch(actions.setGlobalUserInfo({ id: userId }));\n\n    getProjectListByUserId(+userId).then((data: IProject[]) => {\n      data = data.map((item) => ({\n        ...item,\n        name: item.projectName,\n      })) as unknown as IProject[];\n      const app = getCurrentProject();\n      const arr = data?.filter((item) => item.id === app.id);\n      let _currentProject = (arr.length ? arr[0] : data?.[0]) || ({} as IProject);\n\n      setCurrentProject(_currentProject);\n      setProjectInfo(_currentProject);\n      setProjectList(data);\n      store.dispatch(actions.setProjectList(data));\n    });\n    judgeAdminUser().then((res) => {\n      setCookie([{ key: \"isAdminUser\", value: res.code === 0 ? \"yes\" : \"no\" }]);\n    });\n  }, [loginStatus]);\n\n  const logout = () => {\n    userLogout().then(() => {\n      window.localStorage.setItem(CURRENT_PROJECT_KEY, JSON.stringify({}));\n      store.dispatch(actions.setGlobalUserInfo({}));\n      store.dispatch(actions.setProjectList([]));\n\n      setCookie([\n        { key: \"userName\", value: \"\" },\n        { key: \"userId\", value: \"\" },\n        { key: \"isAdminUser\", value: \"\" },\n      ]);\n    });\n  };\n\n  // 路由前置守卫\n  const routeBeforeEach = (props: any) => {\n    const { permissionPoint, history, path } = props;\n    if (path.includes(\"/dashboard\") && (getCookie(\"isAdminUser\") === \"no\" || !isSuperApp())) {\n      return Promise.reject(false);\n    }\n    if (permissionPoint) {\n      const hasPagePermission = getPagePermission(permissionPoint, permissionPoints);\n      if (!hasPagePermission) {\n        return Promise.reject(false);\n      }\n      return Promise.resolve(true);\n    }\n    return Promise.resolve(true);\n  };\n\n  const renderRouteGuard = () => {\n    const routeList = PageRoutes.map((item) => {\n      return item.needCache\n        ? {\n            ...item,\n            cacheKey: `menu.${systemKey}${item.path.split(\"/\").join(\".\")}`,\n          }\n        : item;\n    });\n    return (\n      <RouteGuard beforeEach={routeBeforeEach} routeList={routeList} attr={{ setRemovePaths: setRemovePaths }} mulityPage={mulityPage} />\n    );\n  };\n\n  const renderNoProjectModal = () => {\n    Modal.warning({\n      title: \"抱歉，请先创建应用！\",\n      content: \"您的账户还不具备应用信息\",\n      okText: \"创建应用\",\n      onOk: () => {\n        store.dispatch(actions.setDrawerId(\"addOrEditProjectModal\", { type: \"create\", callback: renderNoProjectModal }));\n      },\n    });\n  };\n\n  const renderPageLoading = () => {\n    return <Spin className=\"spin-name\" spinning={loading} />;\n  };\n\n  const RenderContent = useMemo(() => {\n    return loading ? renderPageLoading() : !projectList.length ? renderNoProjectModal() : renderRouteGuard();\n  }, [loading, projectList, permissionPoints]);\n\n  return (\n    <IntlProvider locale={_.get(localeMap[language], \"intl\", \"zh\")} messages={intlMessages}>\n      <ConfigProvider locale={zhCN}>\n        <InjectIntlContext>\n          <Provider value={language}>\n            <ReduxProvider store={store}>\n              <BrowserRouter basename={systemKey}>\n                <Switch>\n                  <Route\n                    path=\"/\"\n                    exact={true}\n                    component={() => <Redirect to={getCookie(\"isAdminUser\") === \"yes\" ? \"/dashboard\" : \"/cluster/physics\"} />}\n                  />\n                  <Route exact={true} path={\"/login\"} component={LoginOrRegister} />\n                  <Route exact={true} path={\"/register\"} component={() => <LoginOrRegister type=\"register\" />} />\n                  <LayoutHeaderNav\n                    logout={logout}\n                    feConf={feConfig}\n                    projectList={projectList}\n                    currentProject={currentProject}\n                    setCurrentProject={changeCurrentProject}\n                    setLeftIndex={setLeftIndex}\n                    leftIndex={leftIndex}\n                    setHeaderClick={setHeaderClick}\n                  >\n                    <LeftMenu\n                      siderMenuVisible={true}\n                      systemName={systemKey}\n                      systemNameChn={title}\n                      menus={leftMenus[leftIndex]}\n                      intlMessages={intlMessages}\n                      locale={_.get(localeMap[language], \"intl\", \"zh\")}\n                      onSiderMenuChange={setSiderMenuCollapsed}\n                      permissionPoints={permissionPoints}\n                      redirectPath={redirectPath}\n                      getPermission={getPagePermission}\n                    >\n                      {RenderContent}\n                      <Route exact={true} path=\"/403\" component={Page403} />\n                      <Route exact={true} path=\"/404\" component={Page404} />\n                      <AllModalInOne />\n                      <FullScreen />\n                    </LeftMenu>\n                  </LayoutHeaderNav>\n                  <Route render={() => <Redirect to=\"/404\" />} />\n                </Switch>\n              </BrowserRouter>\n            </ReduxProvider>\n          </Provider>\n        </InjectIntlContext>\n      </ConfigProvider>\n    </IntlProvider>\n  );\n};\n\nexport default App;\n"
  },
  {
    "path": "arius-console/src/assets/icon/demo.css",
    "content": "/* Logo 字体 */\n@font-face {\n  font-family: \"iconfont logo\";\n  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');\n  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),\n    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),\n    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),\n    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');\n}\n\n.logo {\n  font-family: \"iconfont logo\";\n  font-size: 160px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n/* tabs */\n.nav-tabs {\n  position: relative;\n}\n\n.nav-tabs .nav-more {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  height: 42px;\n  line-height: 42px;\n  color: #666;\n}\n\n#tabs {\n  border-bottom: 1px solid #eee;\n}\n\n#tabs li {\n  cursor: pointer;\n  width: 100px;\n  height: 40px;\n  line-height: 40px;\n  text-align: center;\n  font-size: 16px;\n  border-bottom: 2px solid transparent;\n  position: relative;\n  z-index: 1;\n  margin-bottom: -1px;\n  color: #666;\n}\n\n\n#tabs .active {\n  border-bottom-color: #f00;\n  color: #222;\n}\n\n.tab-container .content {\n  display: none;\n}\n\n/* 页面布局 */\n.main {\n  padding: 30px 100px;\n  width: 960px;\n  margin: 0 auto;\n}\n\n.main .logo {\n  color: #333;\n  text-align: left;\n  margin-bottom: 30px;\n  line-height: 1;\n  height: 110px;\n  margin-top: -50px;\n  overflow: hidden;\n  *zoom: 1;\n}\n\n.main .logo a {\n  font-size: 160px;\n  color: #333;\n}\n\n.helps {\n  margin-top: 40px;\n}\n\n.helps pre {\n  padding: 20px;\n  margin: 10px 0;\n  border: solid 1px #e7e1cd;\n  background-color: #fffdef;\n  overflow: auto;\n}\n\n.icon_lists {\n  width: 100% !important;\n  overflow: hidden;\n  *zoom: 1;\n}\n\n.icon_lists li {\n  width: 100px;\n  margin-bottom: 10px;\n  margin-right: 20px;\n  text-align: center;\n  list-style: none !important;\n  cursor: default;\n}\n\n.icon_lists li .code-name {\n  line-height: 1.2;\n}\n\n.icon_lists .icon {\n  display: block;\n  height: 100px;\n  line-height: 100px;\n  font-size: 42px;\n  margin: 10px auto;\n  color: #333;\n  -webkit-transition: font-size 0.25s linear, width 0.25s linear;\n  -moz-transition: font-size 0.25s linear, width 0.25s linear;\n  transition: font-size 0.25s linear, width 0.25s linear;\n}\n\n.icon_lists .icon:hover {\n  font-size: 100px;\n}\n\n.icon_lists .svg-icon {\n  /* 通过设置 font-size 来改变图标大小 */\n  width: 1em;\n  /* 图标和文字相邻时，垂直对齐 */\n  vertical-align: -0.15em;\n  /* 通过设置 color 来改变 SVG 的颜色/fill */\n  fill: currentColor;\n  /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示\n      normalize.css 中也包含这行 */\n  overflow: hidden;\n}\n\n.icon_lists li .name,\n.icon_lists li .code-name {\n  color: #666;\n}\n\n/* markdown 样式 */\n.markdown {\n  color: #666;\n  font-size: 14px;\n  line-height: 1.8;\n}\n\n.highlight {\n  line-height: 1.5;\n}\n\n.markdown img {\n  vertical-align: middle;\n  max-width: 100%;\n}\n\n.markdown h1 {\n  color: #404040;\n  font-weight: 500;\n  line-height: 40px;\n  margin-bottom: 24px;\n}\n\n.markdown h2,\n.markdown h3,\n.markdown h4,\n.markdown h5,\n.markdown h6 {\n  color: #404040;\n  margin: 1.6em 0 0.6em 0;\n  font-weight: 500;\n  clear: both;\n}\n\n.markdown h1 {\n  font-size: 28px;\n}\n\n.markdown h2 {\n  font-size: 22px;\n}\n\n.markdown h3 {\n  font-size: 16px;\n}\n\n.markdown h4 {\n  font-size: 14px;\n}\n\n.markdown h5 {\n  font-size: 12px;\n}\n\n.markdown h6 {\n  font-size: 12px;\n}\n\n.markdown hr {\n  height: 1px;\n  border: 0;\n  background: #e9e9e9;\n  margin: 16px 0;\n  clear: both;\n}\n\n.markdown p {\n  margin: 1em 0;\n}\n\n.markdown>p,\n.markdown>blockquote,\n.markdown>.highlight,\n.markdown>ol,\n.markdown>ul {\n  width: 80%;\n}\n\n.markdown ul>li {\n  list-style: circle;\n}\n\n.markdown>ul li,\n.markdown blockquote ul>li {\n  margin-left: 20px;\n  padding-left: 4px;\n}\n\n.markdown>ul li p,\n.markdown>ol li p {\n  margin: 0.6em 0;\n}\n\n.markdown ol>li {\n  list-style: decimal;\n}\n\n.markdown>ol li,\n.markdown blockquote ol>li {\n  margin-left: 20px;\n  padding-left: 4px;\n}\n\n.markdown code {\n  margin: 0 3px;\n  padding: 0 5px;\n  background: #eee;\n  border-radius: 3px;\n}\n\n.markdown strong,\n.markdown b {\n  font-weight: 600;\n}\n\n.markdown>table {\n  border-collapse: collapse;\n  border-spacing: 0px;\n  empty-cells: show;\n  border: 1px solid #e9e9e9;\n  width: 95%;\n  margin-bottom: 24px;\n}\n\n.markdown>table th {\n  white-space: nowrap;\n  color: #333;\n  font-weight: 600;\n}\n\n.markdown>table th,\n.markdown>table td {\n  border: 1px solid #e9e9e9;\n  padding: 8px 16px;\n  text-align: left;\n}\n\n.markdown>table th {\n  background: #F7F7F7;\n}\n\n.markdown blockquote {\n  font-size: 90%;\n  color: #999;\n  border-left: 4px solid #e9e9e9;\n  padding-left: 0.8em;\n  margin: 1em 0;\n}\n\n.markdown blockquote p {\n  margin: 0;\n}\n\n.markdown .anchor {\n  opacity: 0;\n  transition: opacity 0.3s ease;\n  margin-left: 8px;\n}\n\n.markdown .waiting {\n  color: #ccc;\n}\n\n.markdown h1:hover .anchor,\n.markdown h2:hover .anchor,\n.markdown h3:hover .anchor,\n.markdown h4:hover .anchor,\n.markdown h5:hover .anchor,\n.markdown h6:hover .anchor {\n  opacity: 1;\n  display: inline-block;\n}\n\n.markdown>br,\n.markdown>p>br {\n  clear: both;\n}\n\n\n.hljs {\n  display: block;\n  background: white;\n  padding: 0.5em;\n  color: #333333;\n  overflow-x: auto;\n}\n\n.hljs-comment,\n.hljs-meta {\n  color: #969896;\n}\n\n.hljs-string,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-strong,\n.hljs-emphasis,\n.hljs-quote {\n  color: #df5000;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-type {\n  color: #a71d5d;\n}\n\n.hljs-literal,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-attribute {\n  color: #0086b3;\n}\n\n.hljs-section,\n.hljs-name {\n  color: #63a35c;\n}\n\n.hljs-tag {\n  color: #333333;\n}\n\n.hljs-title,\n.hljs-attr,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n  color: #795da3;\n}\n\n.hljs-addition {\n  color: #55a532;\n  background-color: #eaffea;\n}\n\n.hljs-deletion {\n  color: #bd2c00;\n  background-color: #ffecec;\n}\n\n.hljs-link {\n  text-decoration: underline;\n}\n\n/* 代码高亮 */\n/* PrismJS 1.15.0\nhttps://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */\n/**\n * prism.js default theme for JavaScript, CSS and HTML\n * Based on dabblet (http://dabblet.com)\n * @author Lea Verou\n */\ncode[class*=\"language-\"],\npre[class*=\"language-\"] {\n  color: black;\n  background: none;\n  text-shadow: 0 1px white;\n  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;\n  text-align: left;\n  white-space: pre;\n  word-spacing: normal;\n  word-break: normal;\n  word-wrap: normal;\n  line-height: 1.5;\n\n  -moz-tab-size: 4;\n  -o-tab-size: 4;\n  tab-size: 4;\n\n  -webkit-hyphens: none;\n  -moz-hyphens: none;\n  -ms-hyphens: none;\n  hyphens: none;\n}\n\npre[class*=\"language-\"]::-moz-selection,\npre[class*=\"language-\"] ::-moz-selection,\ncode[class*=\"language-\"]::-moz-selection,\ncode[class*=\"language-\"] ::-moz-selection {\n  text-shadow: none;\n  background: #b3d4fc;\n}\n\npre[class*=\"language-\"]::selection,\npre[class*=\"language-\"] ::selection,\ncode[class*=\"language-\"]::selection,\ncode[class*=\"language-\"] ::selection {\n  text-shadow: none;\n  background: #b3d4fc;\n}\n\n@media print {\n\n  code[class*=\"language-\"],\n  pre[class*=\"language-\"] {\n    text-shadow: none;\n  }\n}\n\n/* Code blocks */\npre[class*=\"language-\"] {\n  padding: 1em;\n  margin: .5em 0;\n  overflow: auto;\n}\n\n:not(pre)>code[class*=\"language-\"],\npre[class*=\"language-\"] {\n  background: #f5f2f0;\n}\n\n/* Inline code */\n:not(pre)>code[class*=\"language-\"] {\n  padding: .1em;\n  border-radius: .3em;\n  white-space: normal;\n}\n\n.token.comment,\n.token.prolog,\n.token.doctype,\n.token.cdata {\n  color: slategray;\n}\n\n.token.punctuation {\n  color: #999;\n}\n\n.namespace {\n  opacity: .7;\n}\n\n.token.property,\n.token.tag,\n.token.boolean,\n.token.number,\n.token.constant,\n.token.symbol,\n.token.deleted {\n  color: #905;\n}\n\n.token.selector,\n.token.attr-name,\n.token.string,\n.token.char,\n.token.builtin,\n.token.inserted {\n  color: #690;\n}\n\n.token.operator,\n.token.entity,\n.token.url,\n.language-css .token.string,\n.style .token.string {\n  color: #9a6e3a;\n  background: hsla(0, 0%, 100%, .5);\n}\n\n.token.atrule,\n.token.attr-value,\n.token.keyword {\n  color: #07a;\n}\n\n.token.function,\n.token.class-name {\n  color: #DD4A68;\n}\n\n.token.regex,\n.token.important,\n.token.variable {\n  color: #e90;\n}\n\n.token.important,\n.token.bold {\n  font-weight: bold;\n}\n\n.token.italic {\n  font-style: italic;\n}\n\n.token.entity {\n  cursor: help;\n}\n"
  },
  {
    "path": "arius-console/src/assets/icon/demo_index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\"/>\n  <title>iconfont Demo</title>\n  <link rel=\"shortcut icon\" href=\"//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg\" type=\"image/x-icon\"/>\n  <link rel=\"icon\" type=\"image/svg+xml\" href=\"//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg\"/>\n  <link rel=\"stylesheet\" href=\"https://g.alicdn.com/thx/cube/1.3.2/cube.min.css\">\n  <link rel=\"stylesheet\" href=\"demo.css\">\n  <link rel=\"stylesheet\" href=\"iconfont.css\">\n  <script src=\"iconfont.js\"></script>\n  <!-- jQuery -->\n  <script src=\"https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js\"></script>\n  <!-- 代码高亮 -->\n  <script src=\"https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js\"></script>\n  <style>\n    .main .logo {\n      margin-top: 0;\n      height: auto;\n    }\n\n    .main .logo a {\n      display: flex;\n      align-items: center;\n    }\n\n    .main .logo .sub-title {\n      margin-left: 0.5em;\n      font-size: 22px;\n      color: #fff;\n      background: linear-gradient(-45deg, #3967FF, #B500FE);\n      -webkit-background-clip: text;\n      -webkit-text-fill-color: transparent;\n    }\n  </style>\n</head>\n<body>\n  <div class=\"main\">\n    <h1 class=\"logo\"><a href=\"https://www.iconfont.cn/\" title=\"iconfont 首页\" target=\"_blank\">\n      <img width=\"200\" src=\"https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg\">\n      \n    </a></h1>\n    <div class=\"nav-tabs\">\n      <ul id=\"tabs\" class=\"dib-box\">\n        <li class=\"dib active\"><span>Unicode</span></li>\n        <li class=\"dib\"><span>Font class</span></li>\n        <li class=\"dib\"><span>Symbol</span></li>\n      </ul>\n      \n      <a href=\"https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2457502\" target=\"_blank\" class=\"nav-more\">查看项目</a>\n      \n    </div>\n    <div class=\"tab-container\">\n      <div class=\"content unicode\" style=\"display: block;\">\n          <ul class=\"icon_lists dib-box\">\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe783;</span>\n                <div class=\"name\">拖拽</div>\n                <div class=\"code-name\">&amp;#xe783;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe784;</span>\n                <div class=\"name\">窗口放大</div>\n                <div class=\"code-name\">&amp;#xe784;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe785;</span>\n                <div class=\"name\">窗口缩小</div>\n                <div class=\"code-name\">&amp;#xe785;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe62d;</span>\n                <div class=\"name\">Dashboard</div>\n                <div class=\"code-name\">&amp;#xe62d;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe62e;</span>\n                <div class=\"name\">租户管理</div>\n                <div class=\"code-name\">&amp;#xe62e;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe655;</span>\n                <div class=\"name\">任务中心</div>\n                <div class=\"code-name\">&amp;#xe655;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe656;</span>\n                <div class=\"name\">索引管理</div>\n                <div class=\"code-name\">&amp;#xe656;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe657;</span>\n                <div class=\"name\">平台配置</div>\n                <div class=\"code-name\">&amp;#xe657;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe658;</span>\n                <div class=\"name\">模版管理</div>\n                <div class=\"code-name\">&amp;#xe658;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe659;</span>\n                <div class=\"name\">检索查询</div>\n                <div class=\"code-name\">&amp;#xe659;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe65a;</span>\n                <div class=\"name\">集群管理</div>\n                <div class=\"code-name\">&amp;#xe65a;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe65b;</span>\n                <div class=\"name\">调度任务</div>\n                <div class=\"code-name\">&amp;#xe65b;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe65c;</span>\n                <div class=\"name\">操作记录</div>\n                <div class=\"code-name\">&amp;#xe65c;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe65d;</span>\n                <div class=\"name\">工单任务</div>\n                <div class=\"code-name\">&amp;#xe65d;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe65e;</span>\n                <div class=\"name\">指标看板</div>\n                <div class=\"code-name\">&amp;#xe65e;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe77f;</span>\n                <div class=\"name\">编辑</div>\n                <div class=\"code-name\">&amp;#xe77f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe780;</span>\n                <div class=\"name\">详情</div>\n                <div class=\"code-name\">&amp;#xe780;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe781;</span>\n                <div class=\"name\">arrow-left</div>\n                <div class=\"code-name\">&amp;#xe781;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe77c;</span>\n                <div class=\"name\">top</div>\n                <div class=\"code-name\">&amp;#xe77c;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe77b;</span>\n                <div class=\"name\">日期</div>\n                <div class=\"code-name\">&amp;#xe77b;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe776;</span>\n                <div class=\"name\">应用</div>\n                <div class=\"code-name\">&amp;#xe776;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe772;</span>\n                <div class=\"name\">warning-circle</div>\n                <div class=\"code-name\">&amp;#xe772;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe773;</span>\n                <div class=\"name\">info-circle</div>\n                <div class=\"code-name\">&amp;#xe773;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe774;</span>\n                <div class=\"name\">error-circle</div>\n                <div class=\"code-name\">&amp;#xe774;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe775;</span>\n                <div class=\"name\">success-circle</div>\n                <div class=\"code-name\">&amp;#xe775;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe771;</span>\n                <div class=\"name\">know search</div>\n                <div class=\"code-name\">&amp;#xe771;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe76c;</span>\n                <div class=\"name\">头像</div>\n                <div class=\"code-name\">&amp;#xe76c;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe76d;</span>\n                <div class=\"name\">退出登录</div>\n                <div class=\"code-name\">&amp;#xe76d;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe76e;</span>\n                <div class=\"name\">退出全局</div>\n                <div class=\"code-name\">&amp;#xe76e;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe76f;</span>\n                <div class=\"name\">系统管理</div>\n                <div class=\"code-name\">&amp;#xe76f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe770;</span>\n                <div class=\"name\">多集群管理</div>\n                <div class=\"code-name\">&amp;#xe770;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe76b;</span>\n                <div class=\"name\">全局</div>\n                <div class=\"code-name\">&amp;#xe76b;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe61c;</span>\n                <div class=\"name\">软件管理</div>\n                <div class=\"code-name\">&amp;#xe61c;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe61d;</span>\n                <div class=\"name\">平台管理</div>\n                <div class=\"code-name\">&amp;#xe61d;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe61b;</span>\n                <div class=\"name\">任务中心</div>\n                <div class=\"code-name\">&amp;#xe61b;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe61a;</span>\n                <div class=\"name\">租户管理</div>\n                <div class=\"code-name\">&amp;#xe61a;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe617;</span>\n                <div class=\"name\">系统管理</div>\n                <div class=\"code-name\">&amp;#xe617;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe618;</span>\n                <div class=\"name\">操作记录</div>\n                <div class=\"code-name\">&amp;#xe618;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe619;</span>\n                <div class=\"name\">指标看板</div>\n                <div class=\"code-name\">&amp;#xe619;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe763;</span>\n                <div class=\"name\">红</div>\n                <div class=\"code-name\">&amp;#xe763;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe764;</span>\n                <div class=\"name\">黄</div>\n                <div class=\"code-name\">&amp;#xe764;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe765;</span>\n                <div class=\"name\">绿</div>\n                <div class=\"code-name\">&amp;#xe765;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe72f;</span>\n                <div class=\"name\">Right</div>\n                <div class=\"code-name\">&amp;#xe72f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe730;</span>\n                <div class=\"name\">left</div>\n                <div class=\"code-name\">&amp;#xe730;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe720;</span>\n                <div class=\"name\">未知</div>\n                <div class=\"code-name\">&amp;#xe720;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe714;</span>\n                <div class=\"name\">刷新</div>\n                <div class=\"code-name\">&amp;#xe714;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe710;</span>\n                <div class=\"name\">减少</div>\n                <div class=\"code-name\">&amp;#xe710;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe711;</span>\n                <div class=\"name\">增加</div>\n                <div class=\"code-name\">&amp;#xe711;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe708;</span>\n                <div class=\"name\">调度任务</div>\n                <div class=\"code-name\">&amp;#xe708;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe709;</span>\n                <div class=\"name\">检索查询</div>\n                <div class=\"code-name\">&amp;#xe709;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe70a;</span>\n                <div class=\"name\">索引管理</div>\n                <div class=\"code-name\">&amp;#xe70a;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe70b;</span>\n                <div class=\"name\">模版管理</div>\n                <div class=\"code-name\">&amp;#xe70b;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe70d;</span>\n                <div class=\"name\">工单任务</div>\n                <div class=\"code-name\">&amp;#xe70d;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe70e;</span>\n                <div class=\"name\">集群管理</div>\n                <div class=\"code-name\">&amp;#xe70e;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe70f;</span>\n                <div class=\"name\">指标看板</div>\n                <div class=\"code-name\">&amp;#xe70f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6fe;</span>\n                <div class=\"name\">箭头_右上</div>\n                <div class=\"code-name\">&amp;#xe6fe;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6f8;</span>\n                <div class=\"name\">筛选</div>\n                <div class=\"code-name\">&amp;#xe6f8;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6c8;</span>\n                <div class=\"name\">复制 - kafka</div>\n                <div class=\"code-name\">&amp;#xe6c8;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6c9;</span>\n                <div class=\"name\">更多 - kafka</div>\n                <div class=\"code-name\">&amp;#xe6c9;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6ca;</span>\n                <div class=\"name\">info - kafka</div>\n                <div class=\"code-name\">&amp;#xe6ca;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9e2;</span>\n                <div class=\"name\">es-logo</div>\n                <div class=\"code-name\">&amp;#xe9e2;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6ae;</span>\n                <div class=\"name\">版本变更</div>\n                <div class=\"code-name\">&amp;#xe6ae;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6af;</span>\n                <div class=\"name\">返回</div>\n                <div class=\"code-name\">&amp;#xe6af;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6b0;</span>\n                <div class=\"name\">磁盘扩容</div>\n                <div class=\"code-name\">&amp;#xe6b0;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6b2;</span>\n                <div class=\"name\">链接</div>\n                <div class=\"code-name\">&amp;#xe6b2;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6b3;</span>\n                <div class=\"name\">代运行</div>\n                <div class=\"code-name\">&amp;#xe6b3;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6b4;</span>\n                <div class=\"name\">日历间隔</div>\n                <div class=\"code-name\">&amp;#xe6b4;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6b5;</span>\n                <div class=\"name\">暂停</div>\n                <div class=\"code-name\">&amp;#xe6b5;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6b6;</span>\n                <div class=\"name\">节点扩容</div>\n                <div class=\"code-name\">&amp;#xe6b6;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6b7;</span>\n                <div class=\"name\">完成</div>\n                <div class=\"code-name\">&amp;#xe6b7;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6b8;</span>\n                <div class=\"name\">日历</div>\n                <div class=\"code-name\">&amp;#xe6b8;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6b9;</span>\n                <div class=\"name\">下线</div>\n                <div class=\"code-name\">&amp;#xe6b9;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6ba;</span>\n                <div class=\"name\">刷新</div>\n                <div class=\"code-name\">&amp;#xe6ba;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6bb;</span>\n                <div class=\"name\">新增</div>\n                <div class=\"code-name\">&amp;#xe6bb;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6bd;</span>\n                <div class=\"name\">Controller管理</div>\n                <div class=\"code-name\">&amp;#xe6bd;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6be;</span>\n                <div class=\"name\">Leader Rebalance</div>\n                <div class=\"code-name\">&amp;#xe6be;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6bf;</span>\n                <div class=\"name\">运行</div>\n                <div class=\"code-name\">&amp;#xe6bf;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe6c0;</span>\n                <div class=\"name\">region配置</div>\n                <div class=\"code-name\">&amp;#xe6c0;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9da;</span>\n                <div class=\"name\">Info-Circle备份 8</div>\n                <div class=\"code-name\">&amp;#xe9da;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d9;</span>\n                <div class=\"name\">保障</div>\n                <div class=\"code-name\">&amp;#xe9d9;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9c9;</span>\n                <div class=\"name\">二级告警</div>\n                <div class=\"code-name\">&amp;#xe9c9;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9ca;</span>\n                <div class=\"name\">一级告警</div>\n                <div class=\"code-name\">&amp;#xe9ca;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe62f;</span>\n                <div class=\"name\">表格解释</div>\n                <div class=\"code-name\">&amp;#xe62f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe630;</span>\n                <div class=\"name\">步骤完成</div>\n                <div class=\"code-name\">&amp;#xe630;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe631;</span>\n                <div class=\"name\">弹框删除</div>\n                <div class=\"code-name\">&amp;#xe631;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe632;</span>\n                <div class=\"name\">表格排序</div>\n                <div class=\"code-name\">&amp;#xe632;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe633;</span>\n                <div class=\"name\">顶部导航展开</div>\n                <div class=\"code-name\">&amp;#xe633;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe634;</span>\n                <div class=\"name\">多选已选状态</div>\n                <div class=\"code-name\">&amp;#xe634;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe635;</span>\n                <div class=\"name\">多选不可选状态</div>\n                <div class=\"code-name\">&amp;#xe635;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe636;</span>\n                <div class=\"name\">多选未选状态</div>\n                <div class=\"code-name\">&amp;#xe636;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe637;</span>\n                <div class=\"name\">更多操作收起</div>\n                <div class=\"code-name\">&amp;#xe637;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe638;</span>\n                <div class=\"name\">告警ICON</div>\n                <div class=\"code-name\">&amp;#xe638;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe639;</span>\n                <div class=\"name\">顶部导航收起</div>\n                <div class=\"code-name\">&amp;#xe639;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63a;</span>\n                <div class=\"name\">关</div>\n                <div class=\"code-name\">&amp;#xe63a;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63b;</span>\n                <div class=\"name\">链接</div>\n                <div class=\"code-name\">&amp;#xe63b;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63c;</span>\n                <div class=\"name\">开</div>\n                <div class=\"code-name\">&amp;#xe63c;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63d;</span>\n                <div class=\"name\">更多操作缩起</div>\n                <div class=\"code-name\">&amp;#xe63d;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63e;</span>\n                <div class=\"name\">面包屑关闭</div>\n                <div class=\"code-name\">&amp;#xe63e;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63f;</span>\n                <div class=\"name\">默认开不可点</div>\n                <div class=\"code-name\">&amp;#xe63f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe640;</span>\n                <div class=\"name\">面包屑删除</div>\n                <div class=\"code-name\">&amp;#xe640;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe641;</span>\n                <div class=\"name\">默认关不可点</div>\n                <div class=\"code-name\">&amp;#xe641;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe642;</span>\n                <div class=\"name\">上传中</div>\n                <div class=\"code-name\">&amp;#xe642;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe643;</span>\n                <div class=\"name\">日期</div>\n                <div class=\"code-name\">&amp;#xe643;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe644;</span>\n                <div class=\"name\">图标-info</div>\n                <div class=\"code-name\">&amp;#xe644;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe645;</span>\n                <div class=\"name\">刷新</div>\n                <div class=\"code-name\">&amp;#xe645;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe646;</span>\n                <div class=\"name\">日期悬浮</div>\n                <div class=\"code-name\">&amp;#xe646;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe647;</span>\n                <div class=\"name\">上传失败链接</div>\n                <div class=\"code-name\">&amp;#xe647;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe648;</span>\n                <div class=\"name\">图标-搜索</div>\n                <div class=\"code-name\">&amp;#xe648;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe649;</span>\n                <div class=\"name\">文件上传</div>\n                <div class=\"code-name\">&amp;#xe649;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64a;</span>\n                <div class=\"name\">悬浮文件上传</div>\n                <div class=\"code-name\">&amp;#xe64a;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64b;</span>\n                <div class=\"name\">文件删除</div>\n                <div class=\"code-name\">&amp;#xe64b;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64c;</span>\n                <div class=\"name\">左侧导航栏收起</div>\n                <div class=\"code-name\">&amp;#xe64c;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64d;</span>\n                <div class=\"name\">选择框收起</div>\n                <div class=\"code-name\">&amp;#xe64d;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64e;</span>\n                <div class=\"name\">选择框展开</div>\n                <div class=\"code-name\">&amp;#xe64e;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64f;</span>\n                <div class=\"name\">左侧导航收起</div>\n                <div class=\"code-name\">&amp;#xe64f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe650;</span>\n                <div class=\"name\">左侧导航栏展开</div>\n                <div class=\"code-name\">&amp;#xe650;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe651;</span>\n                <div class=\"name\">左侧导航了收</div>\n                <div class=\"code-name\">&amp;#xe651;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe652;</span>\n                <div class=\"name\">左侧导航栏缩</div>\n                <div class=\"code-name\">&amp;#xe652;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe653;</span>\n                <div class=\"name\">左侧导航缩起</div>\n                <div class=\"code-name\">&amp;#xe653;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe654;</span>\n                <div class=\"name\">es logo</div>\n                <div class=\"code-name\">&amp;#xe654;</div>\n              </li>\n          \n          </ul>\n          <div class=\"article markdown\">\n          <h2 id=\"unicode-\">Unicode 引用</h2>\n          <hr>\n\n          <p>Unicode 是字体在网页端最原始的应用方式，特点是：</p>\n          <ul>\n            <li>支持按字体的方式去动态调整图标大小，颜色等等。</li>\n            <li>默认情况下不支持多色，直接添加多色图标会自动去色。</li>\n          </ul>\n          <blockquote>\n            <p>注意：新版 iconfont 支持两种方式引用多色图标：SVG symbol 引用方式和彩色字体图标模式。（使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。）</p>\n          </blockquote>\n          <p>Unicode 使用步骤如下：</p>\n          <h3 id=\"-font-face\">第一步：拷贝项目下面生成的 <code>@font-face</code></h3>\n<pre><code class=\"language-css\"\n>@font-face {\n  font-family: 'iconfont';\n  src: url('iconfont.woff2?t=1672993974559') format('woff2'),\n       url('iconfont.woff?t=1672993974559') format('woff'),\n       url('iconfont.ttf?t=1672993974559') format('truetype');\n}\n</code></pre>\n          <h3 id=\"-iconfont-\">第二步：定义使用 iconfont 的样式</h3>\n<pre><code class=\"language-css\"\n>.iconfont {\n  font-family: \"iconfont\" !important;\n  font-size: 16px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n</code></pre>\n          <h3 id=\"-\">第三步：挑选相应图标并获取字体编码，应用于页面</h3>\n<pre>\n<code class=\"language-html\"\n>&lt;span class=\"iconfont\"&gt;&amp;#x33;&lt;/span&gt;\n</code></pre>\n          <blockquote>\n            <p>\"iconfont\" 是你项目下的 font-family。可以通过编辑项目查看，默认是 \"iconfont\"。</p>\n          </blockquote>\n          </div>\n      </div>\n      <div class=\"content font-class\">\n        <ul class=\"icon_lists dib-box\">\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontuozhuai\"></span>\n            <div class=\"name\">\n              拖拽\n            </div>\n            <div class=\"code-name\">.icontuozhuai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconchuangkoufangda\"></span>\n            <div class=\"name\">\n              窗口放大\n            </div>\n            <div class=\"code-name\">.iconchuangkoufangda\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconchuangkousuoxiao\"></span>\n            <div class=\"name\">\n              窗口缩小\n            </div>\n            <div class=\"code-name\">.iconchuangkousuoxiao\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconDashboard\"></span>\n            <div class=\"name\">\n              Dashboard\n            </div>\n            <div class=\"code-name\">.iconDashboard\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuhuguanli1\"></span>\n            <div class=\"name\">\n              租户管理\n            </div>\n            <div class=\"code-name\">.iconzuhuguanli1\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconrenwuzhongxin1\"></span>\n            <div class=\"name\">\n              任务中心\n            </div>\n            <div class=\"code-name\">.iconrenwuzhongxin1\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconsuoyinguanli1\"></span>\n            <div class=\"name\">\n              索引管理\n            </div>\n            <div class=\"code-name\">.iconsuoyinguanli1\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconpingtaipeizhi\"></span>\n            <div class=\"name\">\n              平台配置\n            </div>\n            <div class=\"code-name\">.iconpingtaipeizhi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconmobanguanli1\"></span>\n            <div class=\"name\">\n              模版管理\n            </div>\n            <div class=\"code-name\">.iconmobanguanli1\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconjiansuochaxun2\"></span>\n            <div class=\"name\">\n              检索查询\n            </div>\n            <div class=\"code-name\">.iconjiansuochaxun2\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconjiqunguanli2\"></span>\n            <div class=\"name\">\n              集群管理\n            </div>\n            <div class=\"code-name\">.iconjiqunguanli2\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontiaodurenwu1\"></span>\n            <div class=\"name\">\n              调度任务\n            </div>\n            <div class=\"code-name\">.icontiaodurenwu1\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconcaozuojilu1\"></span>\n            <div class=\"name\">\n              操作记录\n            </div>\n            <div class=\"code-name\">.iconcaozuojilu1\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icongongdanrenwu2\"></span>\n            <div class=\"name\">\n              工单任务\n            </div>\n            <div class=\"code-name\">.icongongdanrenwu2\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzhibiaokanban2\"></span>\n            <div class=\"name\">\n              指标看板\n            </div>\n            <div class=\"code-name\">.iconzhibiaokanban2\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconbianji\"></span>\n            <div class=\"name\">\n              编辑\n            </div>\n            <div class=\"code-name\">.iconbianji\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxiangqing\"></span>\n            <div class=\"name\">\n              详情\n            </div>\n            <div class=\"code-name\">.iconxiangqing\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconarrow-left\"></span>\n            <div class=\"name\">\n              arrow-left\n            </div>\n            <div class=\"code-name\">.iconarrow-left\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontop\"></span>\n            <div class=\"name\">\n              top\n            </div>\n            <div class=\"code-name\">.icontop\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconriqi1\"></span>\n            <div class=\"name\">\n              日期\n            </div>\n            <div class=\"code-name\">.iconriqi1\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconyingyong\"></span>\n            <div class=\"name\">\n              应用\n            </div>\n            <div class=\"code-name\">.iconyingyong\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconwarning-circle\"></span>\n            <div class=\"name\">\n              warning-circle\n            </div>\n            <div class=\"code-name\">.iconwarning-circle\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconinfo-circle\"></span>\n            <div class=\"name\">\n              info-circle\n            </div>\n            <div class=\"code-name\">.iconinfo-circle\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconerror-circle\"></span>\n            <div class=\"name\">\n              error-circle\n            </div>\n            <div class=\"code-name\">.iconerror-circle\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconsuccess-circle\"></span>\n            <div class=\"name\">\n              success-circle\n            </div>\n            <div class=\"code-name\">.iconsuccess-circle\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icona-knowsearch\"></span>\n            <div class=\"name\">\n              know search\n            </div>\n            <div class=\"code-name\">.icona-knowsearch\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontouxiang\"></span>\n            <div class=\"name\">\n              头像\n            </div>\n            <div class=\"code-name\">.icontouxiang\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontuichudenglu\"></span>\n            <div class=\"name\">\n              退出登录\n            </div>\n            <div class=\"code-name\">.icontuichudenglu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontuichuquanju\"></span>\n            <div class=\"name\">\n              退出全局\n            </div>\n            <div class=\"code-name\">.icontuichuquanju\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxitongguanli\"></span>\n            <div class=\"name\">\n              系统管理\n            </div>\n            <div class=\"code-name\">.iconxitongguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconduojiqunguanli\"></span>\n            <div class=\"name\">\n              多集群管理\n            </div>\n            <div class=\"code-name\">.iconduojiqunguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconquanju\"></span>\n            <div class=\"name\">\n              全局\n            </div>\n            <div class=\"code-name\">.iconquanju\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconruanjianguanli\"></span>\n            <div class=\"name\">\n              软件管理\n            </div>\n            <div class=\"code-name\">.iconruanjianguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconpingtaiguanli\"></span>\n            <div class=\"name\">\n              平台管理\n            </div>\n            <div class=\"code-name\">.iconpingtaiguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconrenwuzhongxin\"></span>\n            <div class=\"name\">\n              任务中心\n            </div>\n            <div class=\"code-name\">.iconrenwuzhongxin\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuhuguanli\"></span>\n            <div class=\"name\">\n              租户管理\n            </div>\n            <div class=\"code-name\">.iconzuhuguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxitongguanli2\"></span>\n            <div class=\"name\">\n              系统管理\n            </div>\n            <div class=\"code-name\">.iconxitongguanli2\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconcaozuojilu\"></span>\n            <div class=\"name\">\n              操作记录\n            </div>\n            <div class=\"code-name\">.iconcaozuojilu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzhibiaokanban1\"></span>\n            <div class=\"name\">\n              指标看板\n            </div>\n            <div class=\"code-name\">.iconzhibiaokanban1\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconhong\"></span>\n            <div class=\"name\">\n              红\n            </div>\n            <div class=\"code-name\">.iconhong\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconhuang\"></span>\n            <div class=\"name\">\n              黄\n            </div>\n            <div class=\"code-name\">.iconhuang\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconlv\"></span>\n            <div class=\"name\">\n              绿\n            </div>\n            <div class=\"code-name\">.iconlv\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconRight\"></span>\n            <div class=\"name\">\n              Right\n            </div>\n            <div class=\"code-name\">.iconRight\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconleft\"></span>\n            <div class=\"name\">\n              left\n            </div>\n            <div class=\"code-name\">.iconleft\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconweizhi\"></span>\n            <div class=\"name\">\n              未知\n            </div>\n            <div class=\"code-name\">.iconweizhi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconshuaxin2\"></span>\n            <div class=\"name\">\n              刷新\n            </div>\n            <div class=\"code-name\">.iconshuaxin2\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconjianshao\"></span>\n            <div class=\"name\">\n              减少\n            </div>\n            <div class=\"code-name\">.iconjianshao\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzengjia\"></span>\n            <div class=\"name\">\n              增加\n            </div>\n            <div class=\"code-name\">.iconzengjia\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontiaodurenwu\"></span>\n            <div class=\"name\">\n              调度任务\n            </div>\n            <div class=\"code-name\">.icontiaodurenwu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconjiansuochaxun\"></span>\n            <div class=\"name\">\n              检索查询\n            </div>\n            <div class=\"code-name\">.iconjiansuochaxun\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconsuoyinguanli\"></span>\n            <div class=\"name\">\n              索引管理\n            </div>\n            <div class=\"code-name\">.iconsuoyinguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconmobanguanli\"></span>\n            <div class=\"name\">\n              模版管理\n            </div>\n            <div class=\"code-name\">.iconmobanguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icongongdanrenwu\"></span>\n            <div class=\"name\">\n              工单任务\n            </div>\n            <div class=\"code-name\">.icongongdanrenwu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconjiqunguanli\"></span>\n            <div class=\"name\">\n              集群管理\n            </div>\n            <div class=\"code-name\">.iconjiqunguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzhibiaokanban\"></span>\n            <div class=\"name\">\n              指标看板\n            </div>\n            <div class=\"code-name\">.iconzhibiaokanban\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconjiantou_youshang\"></span>\n            <div class=\"name\">\n              箭头_右上\n            </div>\n            <div class=\"code-name\">.iconjiantou_youshang\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconshaixuan\"></span>\n            <div class=\"name\">\n              筛选\n            </div>\n            <div class=\"code-name\">.iconshaixuan\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconfuzhi\"></span>\n            <div class=\"name\">\n              复制 - kafka\n            </div>\n            <div class=\"code-name\">.iconfuzhi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icona-gengduo-kafka\"></span>\n            <div class=\"name\">\n              更多 - kafka\n            </div>\n            <div class=\"code-name\">.icona-gengduo-kafka\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconinfo\"></span>\n            <div class=\"name\">\n              info - kafka\n            </div>\n            <div class=\"code-name\">.iconinfo\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icones-logo\"></span>\n            <div class=\"name\">\n              es-logo\n            </div>\n            <div class=\"code-name\">.icones-logo\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconbanbenbiangeng\"></span>\n            <div class=\"name\">\n              版本变更\n            </div>\n            <div class=\"code-name\">.iconbanbenbiangeng\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconfanhui\"></span>\n            <div class=\"name\">\n              返回\n            </div>\n            <div class=\"code-name\">.iconfanhui\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconcipankuorong\"></span>\n            <div class=\"name\">\n              磁盘扩容\n            </div>\n            <div class=\"code-name\">.iconcipankuorong\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconlianjie1\"></span>\n            <div class=\"name\">\n              链接\n            </div>\n            <div class=\"code-name\">.iconlianjie1\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icondaiyunhang\"></span>\n            <div class=\"name\">\n              代运行\n            </div>\n            <div class=\"code-name\">.icondaiyunhang\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconrilijiange\"></span>\n            <div class=\"name\">\n              日历间隔\n            </div>\n            <div class=\"code-name\">.iconrilijiange\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzanting\"></span>\n            <div class=\"name\">\n              暂停\n            </div>\n            <div class=\"code-name\">.iconzanting\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconjiediankuorong\"></span>\n            <div class=\"name\">\n              节点扩容\n            </div>\n            <div class=\"code-name\">.iconjiediankuorong\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconwancheng\"></span>\n            <div class=\"name\">\n              完成\n            </div>\n            <div class=\"code-name\">.iconwancheng\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconrili\"></span>\n            <div class=\"name\">\n              日历\n            </div>\n            <div class=\"code-name\">.iconrili\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxiaxian\"></span>\n            <div class=\"name\">\n              下线\n            </div>\n            <div class=\"code-name\">.iconxiaxian\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconshuaxin1\"></span>\n            <div class=\"name\">\n              刷新\n            </div>\n            <div class=\"code-name\">.iconshuaxin1\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxinzeng\"></span>\n            <div class=\"name\">\n              新增\n            </div>\n            <div class=\"code-name\">.iconxinzeng\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconControllerguanli\"></span>\n            <div class=\"name\">\n              Controller管理\n            </div>\n            <div class=\"code-name\">.iconControllerguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icona-LeaderRebalance\"></span>\n            <div class=\"name\">\n              Leader Rebalance\n            </div>\n            <div class=\"code-name\">.icona-LeaderRebalance\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconyunhang\"></span>\n            <div class=\"name\">\n              运行\n            </div>\n            <div class=\"code-name\">.iconyunhang\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconregionpeizhi\"></span>\n            <div class=\"name\">\n              region配置\n            </div>\n            <div class=\"code-name\">.iconregionpeizhi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icona-Info-Circlebeifen8\"></span>\n            <div class=\"name\">\n              Info-Circle备份 8\n            </div>\n            <div class=\"code-name\">.icona-Info-Circlebeifen8\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconbaozhang\"></span>\n            <div class=\"name\">\n              保障\n            </div>\n            <div class=\"code-name\">.iconbaozhang\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconerjigaojing\"></span>\n            <div class=\"name\">\n              二级告警\n            </div>\n            <div class=\"code-name\">.iconerjigaojing\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconyijigaojing\"></span>\n            <div class=\"name\">\n              一级告警\n            </div>\n            <div class=\"code-name\">.iconyijigaojing\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconbiaogejieshi\"></span>\n            <div class=\"name\">\n              表格解释\n            </div>\n            <div class=\"code-name\">.iconbiaogejieshi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconbuzhouwancheng\"></span>\n            <div class=\"name\">\n              步骤完成\n            </div>\n            <div class=\"code-name\">.iconbuzhouwancheng\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icondankuangshanchu\"></span>\n            <div class=\"name\">\n              弹框删除\n            </div>\n            <div class=\"code-name\">.icondankuangshanchu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconbiaogepaixu\"></span>\n            <div class=\"name\">\n              表格排序\n            </div>\n            <div class=\"code-name\">.iconbiaogepaixu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icondingbudaohangzhankai\"></span>\n            <div class=\"name\">\n              顶部导航展开\n            </div>\n            <div class=\"code-name\">.icondingbudaohangzhankai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconduoxuanyixuanzhuangtai\"></span>\n            <div class=\"name\">\n              多选已选状态\n            </div>\n            <div class=\"code-name\">.iconduoxuanyixuanzhuangtai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconduoxuanbukexuanzhuangtai\"></span>\n            <div class=\"name\">\n              多选不可选状态\n            </div>\n            <div class=\"code-name\">.iconduoxuanbukexuanzhuangtai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconduoxuanweixuanzhuangtai\"></span>\n            <div class=\"name\">\n              多选未选状态\n            </div>\n            <div class=\"code-name\">.iconduoxuanweixuanzhuangtai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icongengduocaozuoshouqi\"></span>\n            <div class=\"name\">\n              更多操作收起\n            </div>\n            <div class=\"code-name\">.icongengduocaozuoshouqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icongaojingICON\"></span>\n            <div class=\"name\">\n              告警ICON\n            </div>\n            <div class=\"code-name\">.icongaojingICON\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icondingbudaohangshouqi\"></span>\n            <div class=\"name\">\n              顶部导航收起\n            </div>\n            <div class=\"code-name\">.icondingbudaohangshouqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconguan\"></span>\n            <div class=\"name\">\n              关\n            </div>\n            <div class=\"code-name\">.iconguan\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconlianjie\"></span>\n            <div class=\"name\">\n              链接\n            </div>\n            <div class=\"code-name\">.iconlianjie\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconkai\"></span>\n            <div class=\"name\">\n              开\n            </div>\n            <div class=\"code-name\">.iconkai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icongengduocaozuosuoqi\"></span>\n            <div class=\"name\">\n              更多操作缩起\n            </div>\n            <div class=\"code-name\">.icongengduocaozuosuoqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconmianbaoxieguanbi\"></span>\n            <div class=\"name\">\n              面包屑关闭\n            </div>\n            <div class=\"code-name\">.iconmianbaoxieguanbi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconmorenkaibukedian\"></span>\n            <div class=\"name\">\n              默认开不可点\n            </div>\n            <div class=\"code-name\">.iconmorenkaibukedian\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconmianbaoxieshanchu\"></span>\n            <div class=\"name\">\n              面包屑删除\n            </div>\n            <div class=\"code-name\">.iconmianbaoxieshanchu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconmorenguanbukedian\"></span>\n            <div class=\"name\">\n              默认关不可点\n            </div>\n            <div class=\"code-name\">.iconmorenguanbukedian\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconshangchuanzhong\"></span>\n            <div class=\"name\">\n              上传中\n            </div>\n            <div class=\"code-name\">.iconshangchuanzhong\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconriqi\"></span>\n            <div class=\"name\">\n              日期\n            </div>\n            <div class=\"code-name\">.iconriqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontubiao-info\"></span>\n            <div class=\"name\">\n              图标-info\n            </div>\n            <div class=\"code-name\">.icontubiao-info\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconshuaxin\"></span>\n            <div class=\"name\">\n              刷新\n            </div>\n            <div class=\"code-name\">.iconshuaxin\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconriqixuanfu\"></span>\n            <div class=\"name\">\n              日期悬浮\n            </div>\n            <div class=\"code-name\">.iconriqixuanfu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconshangchuanshibailianjie\"></span>\n            <div class=\"name\">\n              上传失败链接\n            </div>\n            <div class=\"code-name\">.iconshangchuanshibailianjie\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontubiao-sousuo\"></span>\n            <div class=\"name\">\n              图标-搜索\n            </div>\n            <div class=\"code-name\">.icontubiao-sousuo\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconwenjianshangchuan\"></span>\n            <div class=\"name\">\n              文件上传\n            </div>\n            <div class=\"code-name\">.iconwenjianshangchuan\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxuanfuwenjianshangchuan\"></span>\n            <div class=\"name\">\n              悬浮文件上传\n            </div>\n            <div class=\"code-name\">.iconxuanfuwenjianshangchuan\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconwenjianshanchu\"></span>\n            <div class=\"name\">\n              文件删除\n            </div>\n            <div class=\"code-name\">.iconwenjianshanchu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohanglanshouqi\"></span>\n            <div class=\"name\">\n              左侧导航栏收起\n            </div>\n            <div class=\"code-name\">.iconzuocedaohanglanshouqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxuanzekuangshouqi\"></span>\n            <div class=\"name\">\n              选择框收起\n            </div>\n            <div class=\"code-name\">.iconxuanzekuangshouqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxuanzekuangzhankai\"></span>\n            <div class=\"name\">\n              选择框展开\n            </div>\n            <div class=\"code-name\">.iconxuanzekuangzhankai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohangshouqi\"></span>\n            <div class=\"name\">\n              左侧导航收起\n            </div>\n            <div class=\"code-name\">.iconzuocedaohangshouqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohanglanzhankai\"></span>\n            <div class=\"name\">\n              左侧导航栏展开\n            </div>\n            <div class=\"code-name\">.iconzuocedaohanglanzhankai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohangleshou\"></span>\n            <div class=\"name\">\n              左侧导航了收\n            </div>\n            <div class=\"code-name\">.iconzuocedaohangleshou\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohanglansuo\"></span>\n            <div class=\"name\">\n              左侧导航栏缩\n            </div>\n            <div class=\"code-name\">.iconzuocedaohanglansuo\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohangsuoqi\"></span>\n            <div class=\"name\">\n              左侧导航缩起\n            </div>\n            <div class=\"code-name\">.iconzuocedaohangsuoqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconeslogo\"></span>\n            <div class=\"name\">\n              es logo\n            </div>\n            <div class=\"code-name\">.iconeslogo\n            </div>\n          </li>\n          \n        </ul>\n        <div class=\"article markdown\">\n        <h2 id=\"font-class-\">font-class 引用</h2>\n        <hr>\n\n        <p>font-class 是 Unicode 使用方式的一种变种，主要是解决 Unicode 书写不直观，语意不明确的问题。</p>\n        <p>与 Unicode 使用方式相比，具有如下特点：</p>\n        <ul>\n          <li>相比于 Unicode 语意明确，书写更直观。可以很容易分辨这个 icon 是什么。</li>\n          <li>因为使用 class 来定义图标，所以当要替换图标时，只需要修改 class 里面的 Unicode 引用。</li>\n        </ul>\n        <p>使用步骤如下：</p>\n        <h3 id=\"-fontclass-\">第一步：引入项目下面生成的 fontclass 代码：</h3>\n<pre><code class=\"language-html\">&lt;link rel=\"stylesheet\" href=\"./iconfont.css\"&gt;\n</code></pre>\n        <h3 id=\"-\">第二步：挑选相应图标并获取类名，应用于页面：</h3>\n<pre><code class=\"language-html\">&lt;span class=\"iconfont iconxxx\"&gt;&lt;/span&gt;\n</code></pre>\n        <blockquote>\n          <p>\"\n            iconfont\" 是你项目下的 font-family。可以通过编辑项目查看，默认是 \"iconfont\"。</p>\n        </blockquote>\n      </div>\n      </div>\n      <div class=\"content symbol\">\n          <ul class=\"icon_lists dib-box\">\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontuozhuai\"></use>\n                </svg>\n                <div class=\"name\">拖拽</div>\n                <div class=\"code-name\">#icontuozhuai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconchuangkoufangda\"></use>\n                </svg>\n                <div class=\"name\">窗口放大</div>\n                <div class=\"code-name\">#iconchuangkoufangda</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconchuangkousuoxiao\"></use>\n                </svg>\n                <div class=\"name\">窗口缩小</div>\n                <div class=\"code-name\">#iconchuangkousuoxiao</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconDashboard\"></use>\n                </svg>\n                <div class=\"name\">Dashboard</div>\n                <div class=\"code-name\">#iconDashboard</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuhuguanli1\"></use>\n                </svg>\n                <div class=\"name\">租户管理</div>\n                <div class=\"code-name\">#iconzuhuguanli1</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconrenwuzhongxin1\"></use>\n                </svg>\n                <div class=\"name\">任务中心</div>\n                <div class=\"code-name\">#iconrenwuzhongxin1</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconsuoyinguanli1\"></use>\n                </svg>\n                <div class=\"name\">索引管理</div>\n                <div class=\"code-name\">#iconsuoyinguanli1</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconpingtaipeizhi\"></use>\n                </svg>\n                <div class=\"name\">平台配置</div>\n                <div class=\"code-name\">#iconpingtaipeizhi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconmobanguanli1\"></use>\n                </svg>\n                <div class=\"name\">模版管理</div>\n                <div class=\"code-name\">#iconmobanguanli1</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconjiansuochaxun2\"></use>\n                </svg>\n                <div class=\"name\">检索查询</div>\n                <div class=\"code-name\">#iconjiansuochaxun2</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconjiqunguanli2\"></use>\n                </svg>\n                <div class=\"name\">集群管理</div>\n                <div class=\"code-name\">#iconjiqunguanli2</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontiaodurenwu1\"></use>\n                </svg>\n                <div class=\"name\">调度任务</div>\n                <div class=\"code-name\">#icontiaodurenwu1</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconcaozuojilu1\"></use>\n                </svg>\n                <div class=\"name\">操作记录</div>\n                <div class=\"code-name\">#iconcaozuojilu1</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icongongdanrenwu2\"></use>\n                </svg>\n                <div class=\"name\">工单任务</div>\n                <div class=\"code-name\">#icongongdanrenwu2</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzhibiaokanban2\"></use>\n                </svg>\n                <div class=\"name\">指标看板</div>\n                <div class=\"code-name\">#iconzhibiaokanban2</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconbianji\"></use>\n                </svg>\n                <div class=\"name\">编辑</div>\n                <div class=\"code-name\">#iconbianji</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxiangqing\"></use>\n                </svg>\n                <div class=\"name\">详情</div>\n                <div class=\"code-name\">#iconxiangqing</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconarrow-left\"></use>\n                </svg>\n                <div class=\"name\">arrow-left</div>\n                <div class=\"code-name\">#iconarrow-left</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontop\"></use>\n                </svg>\n                <div class=\"name\">top</div>\n                <div class=\"code-name\">#icontop</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconriqi1\"></use>\n                </svg>\n                <div class=\"name\">日期</div>\n                <div class=\"code-name\">#iconriqi1</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconyingyong\"></use>\n                </svg>\n                <div class=\"name\">应用</div>\n                <div class=\"code-name\">#iconyingyong</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconwarning-circle\"></use>\n                </svg>\n                <div class=\"name\">warning-circle</div>\n                <div class=\"code-name\">#iconwarning-circle</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconinfo-circle\"></use>\n                </svg>\n                <div class=\"name\">info-circle</div>\n                <div class=\"code-name\">#iconinfo-circle</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconerror-circle\"></use>\n                </svg>\n                <div class=\"name\">error-circle</div>\n                <div class=\"code-name\">#iconerror-circle</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconsuccess-circle\"></use>\n                </svg>\n                <div class=\"name\">success-circle</div>\n                <div class=\"code-name\">#iconsuccess-circle</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icona-knowsearch\"></use>\n                </svg>\n                <div class=\"name\">know search</div>\n                <div class=\"code-name\">#icona-knowsearch</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontouxiang\"></use>\n                </svg>\n                <div class=\"name\">头像</div>\n                <div class=\"code-name\">#icontouxiang</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontuichudenglu\"></use>\n                </svg>\n                <div class=\"name\">退出登录</div>\n                <div class=\"code-name\">#icontuichudenglu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontuichuquanju\"></use>\n                </svg>\n                <div class=\"name\">退出全局</div>\n                <div class=\"code-name\">#icontuichuquanju</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxitongguanli\"></use>\n                </svg>\n                <div class=\"name\">系统管理</div>\n                <div class=\"code-name\">#iconxitongguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconduojiqunguanli\"></use>\n                </svg>\n                <div class=\"name\">多集群管理</div>\n                <div class=\"code-name\">#iconduojiqunguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconquanju\"></use>\n                </svg>\n                <div class=\"name\">全局</div>\n                <div class=\"code-name\">#iconquanju</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconruanjianguanli\"></use>\n                </svg>\n                <div class=\"name\">软件管理</div>\n                <div class=\"code-name\">#iconruanjianguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconpingtaiguanli\"></use>\n                </svg>\n                <div class=\"name\">平台管理</div>\n                <div class=\"code-name\">#iconpingtaiguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconrenwuzhongxin\"></use>\n                </svg>\n                <div class=\"name\">任务中心</div>\n                <div class=\"code-name\">#iconrenwuzhongxin</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuhuguanli\"></use>\n                </svg>\n                <div class=\"name\">租户管理</div>\n                <div class=\"code-name\">#iconzuhuguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxitongguanli2\"></use>\n                </svg>\n                <div class=\"name\">系统管理</div>\n                <div class=\"code-name\">#iconxitongguanli2</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconcaozuojilu\"></use>\n                </svg>\n                <div class=\"name\">操作记录</div>\n                <div class=\"code-name\">#iconcaozuojilu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzhibiaokanban1\"></use>\n                </svg>\n                <div class=\"name\">指标看板</div>\n                <div class=\"code-name\">#iconzhibiaokanban1</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconhong\"></use>\n                </svg>\n                <div class=\"name\">红</div>\n                <div class=\"code-name\">#iconhong</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconhuang\"></use>\n                </svg>\n                <div class=\"name\">黄</div>\n                <div class=\"code-name\">#iconhuang</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconlv\"></use>\n                </svg>\n                <div class=\"name\">绿</div>\n                <div class=\"code-name\">#iconlv</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconRight\"></use>\n                </svg>\n                <div class=\"name\">Right</div>\n                <div class=\"code-name\">#iconRight</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconleft\"></use>\n                </svg>\n                <div class=\"name\">left</div>\n                <div class=\"code-name\">#iconleft</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconweizhi\"></use>\n                </svg>\n                <div class=\"name\">未知</div>\n                <div class=\"code-name\">#iconweizhi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconshuaxin2\"></use>\n                </svg>\n                <div class=\"name\">刷新</div>\n                <div class=\"code-name\">#iconshuaxin2</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconjianshao\"></use>\n                </svg>\n                <div class=\"name\">减少</div>\n                <div class=\"code-name\">#iconjianshao</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzengjia\"></use>\n                </svg>\n                <div class=\"name\">增加</div>\n                <div class=\"code-name\">#iconzengjia</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontiaodurenwu\"></use>\n                </svg>\n                <div class=\"name\">调度任务</div>\n                <div class=\"code-name\">#icontiaodurenwu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconjiansuochaxun\"></use>\n                </svg>\n                <div class=\"name\">检索查询</div>\n                <div class=\"code-name\">#iconjiansuochaxun</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconsuoyinguanli\"></use>\n                </svg>\n                <div class=\"name\">索引管理</div>\n                <div class=\"code-name\">#iconsuoyinguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconmobanguanli\"></use>\n                </svg>\n                <div class=\"name\">模版管理</div>\n                <div class=\"code-name\">#iconmobanguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icongongdanrenwu\"></use>\n                </svg>\n                <div class=\"name\">工单任务</div>\n                <div class=\"code-name\">#icongongdanrenwu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconjiqunguanli\"></use>\n                </svg>\n                <div class=\"name\">集群管理</div>\n                <div class=\"code-name\">#iconjiqunguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzhibiaokanban\"></use>\n                </svg>\n                <div class=\"name\">指标看板</div>\n                <div class=\"code-name\">#iconzhibiaokanban</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconjiantou_youshang\"></use>\n                </svg>\n                <div class=\"name\">箭头_右上</div>\n                <div class=\"code-name\">#iconjiantou_youshang</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconshaixuan\"></use>\n                </svg>\n                <div class=\"name\">筛选</div>\n                <div class=\"code-name\">#iconshaixuan</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconfuzhi\"></use>\n                </svg>\n                <div class=\"name\">复制 - kafka</div>\n                <div class=\"code-name\">#iconfuzhi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icona-gengduo-kafka\"></use>\n                </svg>\n                <div class=\"name\">更多 - kafka</div>\n                <div class=\"code-name\">#icona-gengduo-kafka</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconinfo\"></use>\n                </svg>\n                <div class=\"name\">info - kafka</div>\n                <div class=\"code-name\">#iconinfo</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icones-logo\"></use>\n                </svg>\n                <div class=\"name\">es-logo</div>\n                <div class=\"code-name\">#icones-logo</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconbanbenbiangeng\"></use>\n                </svg>\n                <div class=\"name\">版本变更</div>\n                <div class=\"code-name\">#iconbanbenbiangeng</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconfanhui\"></use>\n                </svg>\n                <div class=\"name\">返回</div>\n                <div class=\"code-name\">#iconfanhui</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconcipankuorong\"></use>\n                </svg>\n                <div class=\"name\">磁盘扩容</div>\n                <div class=\"code-name\">#iconcipankuorong</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconlianjie1\"></use>\n                </svg>\n                <div class=\"name\">链接</div>\n                <div class=\"code-name\">#iconlianjie1</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icondaiyunhang\"></use>\n                </svg>\n                <div class=\"name\">代运行</div>\n                <div class=\"code-name\">#icondaiyunhang</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconrilijiange\"></use>\n                </svg>\n                <div class=\"name\">日历间隔</div>\n                <div class=\"code-name\">#iconrilijiange</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzanting\"></use>\n                </svg>\n                <div class=\"name\">暂停</div>\n                <div class=\"code-name\">#iconzanting</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconjiediankuorong\"></use>\n                </svg>\n                <div class=\"name\">节点扩容</div>\n                <div class=\"code-name\">#iconjiediankuorong</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconwancheng\"></use>\n                </svg>\n                <div class=\"name\">完成</div>\n                <div class=\"code-name\">#iconwancheng</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconrili\"></use>\n                </svg>\n                <div class=\"name\">日历</div>\n                <div class=\"code-name\">#iconrili</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxiaxian\"></use>\n                </svg>\n                <div class=\"name\">下线</div>\n                <div class=\"code-name\">#iconxiaxian</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconshuaxin1\"></use>\n                </svg>\n                <div class=\"name\">刷新</div>\n                <div class=\"code-name\">#iconshuaxin1</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxinzeng\"></use>\n                </svg>\n                <div class=\"name\">新增</div>\n                <div class=\"code-name\">#iconxinzeng</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconControllerguanli\"></use>\n                </svg>\n                <div class=\"name\">Controller管理</div>\n                <div class=\"code-name\">#iconControllerguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icona-LeaderRebalance\"></use>\n                </svg>\n                <div class=\"name\">Leader Rebalance</div>\n                <div class=\"code-name\">#icona-LeaderRebalance</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconyunhang\"></use>\n                </svg>\n                <div class=\"name\">运行</div>\n                <div class=\"code-name\">#iconyunhang</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconregionpeizhi\"></use>\n                </svg>\n                <div class=\"name\">region配置</div>\n                <div class=\"code-name\">#iconregionpeizhi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icona-Info-Circlebeifen8\"></use>\n                </svg>\n                <div class=\"name\">Info-Circle备份 8</div>\n                <div class=\"code-name\">#icona-Info-Circlebeifen8</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconbaozhang\"></use>\n                </svg>\n                <div class=\"name\">保障</div>\n                <div class=\"code-name\">#iconbaozhang</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconerjigaojing\"></use>\n                </svg>\n                <div class=\"name\">二级告警</div>\n                <div class=\"code-name\">#iconerjigaojing</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconyijigaojing\"></use>\n                </svg>\n                <div class=\"name\">一级告警</div>\n                <div class=\"code-name\">#iconyijigaojing</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconbiaogejieshi\"></use>\n                </svg>\n                <div class=\"name\">表格解释</div>\n                <div class=\"code-name\">#iconbiaogejieshi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconbuzhouwancheng\"></use>\n                </svg>\n                <div class=\"name\">步骤完成</div>\n                <div class=\"code-name\">#iconbuzhouwancheng</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icondankuangshanchu\"></use>\n                </svg>\n                <div class=\"name\">弹框删除</div>\n                <div class=\"code-name\">#icondankuangshanchu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconbiaogepaixu\"></use>\n                </svg>\n                <div class=\"name\">表格排序</div>\n                <div class=\"code-name\">#iconbiaogepaixu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icondingbudaohangzhankai\"></use>\n                </svg>\n                <div class=\"name\">顶部导航展开</div>\n                <div class=\"code-name\">#icondingbudaohangzhankai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconduoxuanyixuanzhuangtai\"></use>\n                </svg>\n                <div class=\"name\">多选已选状态</div>\n                <div class=\"code-name\">#iconduoxuanyixuanzhuangtai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconduoxuanbukexuanzhuangtai\"></use>\n                </svg>\n                <div class=\"name\">多选不可选状态</div>\n                <div class=\"code-name\">#iconduoxuanbukexuanzhuangtai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconduoxuanweixuanzhuangtai\"></use>\n                </svg>\n                <div class=\"name\">多选未选状态</div>\n                <div class=\"code-name\">#iconduoxuanweixuanzhuangtai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icongengduocaozuoshouqi\"></use>\n                </svg>\n                <div class=\"name\">更多操作收起</div>\n                <div class=\"code-name\">#icongengduocaozuoshouqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icongaojingICON\"></use>\n                </svg>\n                <div class=\"name\">告警ICON</div>\n                <div class=\"code-name\">#icongaojingICON</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icondingbudaohangshouqi\"></use>\n                </svg>\n                <div class=\"name\">顶部导航收起</div>\n                <div class=\"code-name\">#icondingbudaohangshouqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconguan\"></use>\n                </svg>\n                <div class=\"name\">关</div>\n                <div class=\"code-name\">#iconguan</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconlianjie\"></use>\n                </svg>\n                <div class=\"name\">链接</div>\n                <div class=\"code-name\">#iconlianjie</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconkai\"></use>\n                </svg>\n                <div class=\"name\">开</div>\n                <div class=\"code-name\">#iconkai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icongengduocaozuosuoqi\"></use>\n                </svg>\n                <div class=\"name\">更多操作缩起</div>\n                <div class=\"code-name\">#icongengduocaozuosuoqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconmianbaoxieguanbi\"></use>\n                </svg>\n                <div class=\"name\">面包屑关闭</div>\n                <div class=\"code-name\">#iconmianbaoxieguanbi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconmorenkaibukedian\"></use>\n                </svg>\n                <div class=\"name\">默认开不可点</div>\n                <div class=\"code-name\">#iconmorenkaibukedian</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconmianbaoxieshanchu\"></use>\n                </svg>\n                <div class=\"name\">面包屑删除</div>\n                <div class=\"code-name\">#iconmianbaoxieshanchu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconmorenguanbukedian\"></use>\n                </svg>\n                <div class=\"name\">默认关不可点</div>\n                <div class=\"code-name\">#iconmorenguanbukedian</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconshangchuanzhong\"></use>\n                </svg>\n                <div class=\"name\">上传中</div>\n                <div class=\"code-name\">#iconshangchuanzhong</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconriqi\"></use>\n                </svg>\n                <div class=\"name\">日期</div>\n                <div class=\"code-name\">#iconriqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontubiao-info\"></use>\n                </svg>\n                <div class=\"name\">图标-info</div>\n                <div class=\"code-name\">#icontubiao-info</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconshuaxin\"></use>\n                </svg>\n                <div class=\"name\">刷新</div>\n                <div class=\"code-name\">#iconshuaxin</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconriqixuanfu\"></use>\n                </svg>\n                <div class=\"name\">日期悬浮</div>\n                <div class=\"code-name\">#iconriqixuanfu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconshangchuanshibailianjie\"></use>\n                </svg>\n                <div class=\"name\">上传失败链接</div>\n                <div class=\"code-name\">#iconshangchuanshibailianjie</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontubiao-sousuo\"></use>\n                </svg>\n                <div class=\"name\">图标-搜索</div>\n                <div class=\"code-name\">#icontubiao-sousuo</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconwenjianshangchuan\"></use>\n                </svg>\n                <div class=\"name\">文件上传</div>\n                <div class=\"code-name\">#iconwenjianshangchuan</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxuanfuwenjianshangchuan\"></use>\n                </svg>\n                <div class=\"name\">悬浮文件上传</div>\n                <div class=\"code-name\">#iconxuanfuwenjianshangchuan</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconwenjianshanchu\"></use>\n                </svg>\n                <div class=\"name\">文件删除</div>\n                <div class=\"code-name\">#iconwenjianshanchu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohanglanshouqi\"></use>\n                </svg>\n                <div class=\"name\">左侧导航栏收起</div>\n                <div class=\"code-name\">#iconzuocedaohanglanshouqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxuanzekuangshouqi\"></use>\n                </svg>\n                <div class=\"name\">选择框收起</div>\n                <div class=\"code-name\">#iconxuanzekuangshouqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxuanzekuangzhankai\"></use>\n                </svg>\n                <div class=\"name\">选择框展开</div>\n                <div class=\"code-name\">#iconxuanzekuangzhankai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohangshouqi\"></use>\n                </svg>\n                <div class=\"name\">左侧导航收起</div>\n                <div class=\"code-name\">#iconzuocedaohangshouqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohanglanzhankai\"></use>\n                </svg>\n                <div class=\"name\">左侧导航栏展开</div>\n                <div class=\"code-name\">#iconzuocedaohanglanzhankai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohangleshou\"></use>\n                </svg>\n                <div class=\"name\">左侧导航了收</div>\n                <div class=\"code-name\">#iconzuocedaohangleshou</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohanglansuo\"></use>\n                </svg>\n                <div class=\"name\">左侧导航栏缩</div>\n                <div class=\"code-name\">#iconzuocedaohanglansuo</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohangsuoqi\"></use>\n                </svg>\n                <div class=\"name\">左侧导航缩起</div>\n                <div class=\"code-name\">#iconzuocedaohangsuoqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconeslogo\"></use>\n                </svg>\n                <div class=\"name\">es logo</div>\n                <div class=\"code-name\">#iconeslogo</div>\n            </li>\n          \n          </ul>\n          <div class=\"article markdown\">\n          <h2 id=\"symbol-\">Symbol 引用</h2>\n          <hr>\n\n          <p>这是一种全新的使用方式，应该说这才是未来的主流，也是平台目前推荐的用法。相关介绍可以参考这篇<a href=\"\">文章</a>\n            这种用法其实是做了一个 SVG 的集合，与另外两种相比具有如下特点：</p>\n          <ul>\n            <li>支持多色图标了，不再受单色限制。</li>\n            <li>通过一些技巧，支持像字体那样，通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>\n            <li>兼容性较差，支持 IE9+，及现代浏览器。</li>\n            <li>浏览器渲染 SVG 的性能一般，还不如 png。</li>\n          </ul>\n          <p>使用步骤如下：</p>\n          <h3 id=\"-symbol-\">第一步：引入项目下面生成的 symbol 代码：</h3>\n<pre><code class=\"language-html\">&lt;script src=\"./iconfont.js\"&gt;&lt;/script&gt;\n</code></pre>\n          <h3 id=\"-css-\">第二步：加入通用 CSS 代码（引入一次就行）：</h3>\n<pre><code class=\"language-html\">&lt;style&gt;\n.icon {\n  width: 1em;\n  height: 1em;\n  vertical-align: -0.15em;\n  fill: currentColor;\n  overflow: hidden;\n}\n&lt;/style&gt;\n</code></pre>\n          <h3 id=\"-\">第三步：挑选相应图标并获取类名，应用于页面：</h3>\n<pre><code class=\"language-html\">&lt;svg class=\"icon\" aria-hidden=\"true\"&gt;\n  &lt;use xlink:href=\"#icon-xxx\"&gt;&lt;/use&gt;\n&lt;/svg&gt;\n</code></pre>\n          </div>\n      </div>\n\n    </div>\n  </div>\n  <script>\n  $(document).ready(function () {\n      $('.tab-container .content:first').show()\n\n      $('#tabs li').click(function (e) {\n        var tabContent = $('.tab-container .content')\n        var index = $(this).index()\n\n        if ($(this).hasClass('active')) {\n          return\n        } else {\n          $('#tabs li').removeClass('active')\n          $(this).addClass('active')\n\n          tabContent.hide().eq(index).fadeIn()\n        }\n      })\n    })\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "arius-console/src/assets/icon/iconfont.css",
    "content": "@font-face {\n  font-family: \"iconfont\"; /* Project id 2457502 */\n  src: url('iconfont.woff2?t=1672993974559') format('woff2'),\n       url('iconfont.woff?t=1672993974559') format('woff'),\n       url('iconfont.ttf?t=1672993974559') format('truetype');\n}\n\n.iconfont {\n  font-family: \"iconfont\" !important;\n  font-size: 16px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n.icontuozhuai:before {\n  content: \"\\e783\";\n}\n\n.iconchuangkoufangda:before {\n  content: \"\\e784\";\n}\n\n.iconchuangkousuoxiao:before {\n  content: \"\\e785\";\n}\n\n.iconDashboard:before {\n  content: \"\\e62d\";\n}\n\n.iconzuhuguanli1:before {\n  content: \"\\e62e\";\n}\n\n.iconrenwuzhongxin1:before {\n  content: \"\\e655\";\n}\n\n.iconsuoyinguanli1:before {\n  content: \"\\e656\";\n}\n\n.iconpingtaipeizhi:before {\n  content: \"\\e657\";\n}\n\n.iconmobanguanli1:before {\n  content: \"\\e658\";\n}\n\n.iconjiansuochaxun2:before {\n  content: \"\\e659\";\n}\n\n.iconjiqunguanli2:before {\n  content: \"\\e65a\";\n}\n\n.icontiaodurenwu1:before {\n  content: \"\\e65b\";\n}\n\n.iconcaozuojilu1:before {\n  content: \"\\e65c\";\n}\n\n.icongongdanrenwu2:before {\n  content: \"\\e65d\";\n}\n\n.iconzhibiaokanban2:before {\n  content: \"\\e65e\";\n}\n\n.iconbianji:before {\n  content: \"\\e77f\";\n}\n\n.iconxiangqing:before {\n  content: \"\\e780\";\n}\n\n.iconarrow-left:before {\n  content: \"\\e781\";\n}\n\n.icontop:before {\n  content: \"\\e77c\";\n}\n\n.iconriqi1:before {\n  content: \"\\e77b\";\n}\n\n.iconyingyong:before {\n  content: \"\\e776\";\n}\n\n.iconwarning-circle:before {\n  content: \"\\e772\";\n}\n\n.iconinfo-circle:before {\n  content: \"\\e773\";\n}\n\n.iconerror-circle:before {\n  content: \"\\e774\";\n}\n\n.iconsuccess-circle:before {\n  content: \"\\e775\";\n}\n\n.icona-knowsearch:before {\n  content: \"\\e771\";\n}\n\n.icontouxiang:before {\n  content: \"\\e76c\";\n}\n\n.icontuichudenglu:before {\n  content: \"\\e76d\";\n}\n\n.icontuichuquanju:before {\n  content: \"\\e76e\";\n}\n\n.iconxitongguanli:before {\n  content: \"\\e76f\";\n}\n\n.iconduojiqunguanli:before {\n  content: \"\\e770\";\n}\n\n.iconquanju:before {\n  content: \"\\e76b\";\n}\n\n.iconruanjianguanli:before {\n  content: \"\\e61c\";\n}\n\n.iconpingtaiguanli:before {\n  content: \"\\e61d\";\n}\n\n.iconrenwuzhongxin:before {\n  content: \"\\e61b\";\n}\n\n.iconzuhuguanli:before {\n  content: \"\\e61a\";\n}\n\n.iconxitongguanli2:before {\n  content: \"\\e617\";\n}\n\n.iconcaozuojilu:before {\n  content: \"\\e618\";\n}\n\n.iconzhibiaokanban1:before {\n  content: \"\\e619\";\n}\n\n.iconhong:before {\n  content: \"\\e763\";\n}\n\n.iconhuang:before {\n  content: \"\\e764\";\n}\n\n.iconlv:before {\n  content: \"\\e765\";\n}\n\n.iconRight:before {\n  content: \"\\e72f\";\n}\n\n.iconleft:before {\n  content: \"\\e730\";\n}\n\n.iconweizhi:before {\n  content: \"\\e720\";\n}\n\n.iconshuaxin2:before {\n  content: \"\\e714\";\n}\n\n.iconjianshao:before {\n  content: \"\\e710\";\n}\n\n.iconzengjia:before {\n  content: \"\\e711\";\n}\n\n.icontiaodurenwu:before {\n  content: \"\\e708\";\n}\n\n.iconjiansuochaxun:before {\n  content: \"\\e709\";\n}\n\n.iconsuoyinguanli:before {\n  content: \"\\e70a\";\n}\n\n.iconmobanguanli:before {\n  content: \"\\e70b\";\n}\n\n.icongongdanrenwu:before {\n  content: \"\\e70d\";\n}\n\n.iconjiqunguanli:before {\n  content: \"\\e70e\";\n}\n\n.iconzhibiaokanban:before {\n  content: \"\\e70f\";\n}\n\n.iconjiantou_youshang:before {\n  content: \"\\e6fe\";\n}\n\n.iconshaixuan:before {\n  content: \"\\e6f8\";\n}\n\n.iconfuzhi:before {\n  content: \"\\e6c8\";\n}\n\n.icona-gengduo-kafka:before {\n  content: \"\\e6c9\";\n}\n\n.iconinfo:before {\n  content: \"\\e6ca\";\n}\n\n.icones-logo:before {\n  content: \"\\e9e2\";\n}\n\n.iconbanbenbiangeng:before {\n  content: \"\\e6ae\";\n}\n\n.iconfanhui:before {\n  content: \"\\e6af\";\n}\n\n.iconcipankuorong:before {\n  content: \"\\e6b0\";\n}\n\n.iconlianjie1:before {\n  content: \"\\e6b2\";\n}\n\n.icondaiyunhang:before {\n  content: \"\\e6b3\";\n}\n\n.iconrilijiange:before {\n  content: \"\\e6b4\";\n}\n\n.iconzanting:before {\n  content: \"\\e6b5\";\n}\n\n.iconjiediankuorong:before {\n  content: \"\\e6b6\";\n}\n\n.iconwancheng:before {\n  content: \"\\e6b7\";\n}\n\n.iconrili:before {\n  content: \"\\e6b8\";\n}\n\n.iconxiaxian:before {\n  content: \"\\e6b9\";\n}\n\n.iconshuaxin1:before {\n  content: \"\\e6ba\";\n}\n\n.iconxinzeng:before {\n  content: \"\\e6bb\";\n}\n\n.iconControllerguanli:before {\n  content: \"\\e6bd\";\n}\n\n.icona-LeaderRebalance:before {\n  content: \"\\e6be\";\n}\n\n.iconyunhang:before {\n  content: \"\\e6bf\";\n}\n\n.iconregionpeizhi:before {\n  content: \"\\e6c0\";\n}\n\n.icona-Info-Circlebeifen8:before {\n  content: \"\\e9da\";\n}\n\n.iconbaozhang:before {\n  content: \"\\e9d9\";\n}\n\n.iconerjigaojing:before {\n  content: \"\\e9c9\";\n}\n\n.iconyijigaojing:before {\n  content: \"\\e9ca\";\n}\n\n.iconbiaogejieshi:before {\n  content: \"\\e62f\";\n}\n\n.iconbuzhouwancheng:before {\n  content: \"\\e630\";\n}\n\n.icondankuangshanchu:before {\n  content: \"\\e631\";\n}\n\n.iconbiaogepaixu:before {\n  content: \"\\e632\";\n}\n\n.icondingbudaohangzhankai:before {\n  content: \"\\e633\";\n}\n\n.iconduoxuanyixuanzhuangtai:before {\n  content: \"\\e634\";\n}\n\n.iconduoxuanbukexuanzhuangtai:before {\n  content: \"\\e635\";\n}\n\n.iconduoxuanweixuanzhuangtai:before {\n  content: \"\\e636\";\n}\n\n.icongengduocaozuoshouqi:before {\n  content: \"\\e637\";\n}\n\n.icongaojingICON:before {\n  content: \"\\e638\";\n}\n\n.icondingbudaohangshouqi:before {\n  content: \"\\e639\";\n}\n\n.iconguan:before {\n  content: \"\\e63a\";\n}\n\n.iconlianjie:before {\n  content: \"\\e63b\";\n}\n\n.iconkai:before {\n  content: \"\\e63c\";\n}\n\n.icongengduocaozuosuoqi:before {\n  content: \"\\e63d\";\n}\n\n.iconmianbaoxieguanbi:before {\n  content: \"\\e63e\";\n}\n\n.iconmorenkaibukedian:before {\n  content: \"\\e63f\";\n}\n\n.iconmianbaoxieshanchu:before {\n  content: \"\\e640\";\n}\n\n.iconmorenguanbukedian:before {\n  content: \"\\e641\";\n}\n\n.iconshangchuanzhong:before {\n  content: \"\\e642\";\n}\n\n.iconriqi:before {\n  content: \"\\e643\";\n}\n\n.icontubiao-info:before {\n  content: \"\\e644\";\n}\n\n.iconshuaxin:before {\n  content: \"\\e645\";\n}\n\n.iconriqixuanfu:before {\n  content: \"\\e646\";\n}\n\n.iconshangchuanshibailianjie:before {\n  content: \"\\e647\";\n}\n\n.icontubiao-sousuo:before {\n  content: \"\\e648\";\n}\n\n.iconwenjianshangchuan:before {\n  content: \"\\e649\";\n}\n\n.iconxuanfuwenjianshangchuan:before {\n  content: \"\\e64a\";\n}\n\n.iconwenjianshanchu:before {\n  content: \"\\e64b\";\n}\n\n.iconzuocedaohanglanshouqi:before {\n  content: \"\\e64c\";\n}\n\n.iconxuanzekuangshouqi:before {\n  content: \"\\e64d\";\n}\n\n.iconxuanzekuangzhankai:before {\n  content: \"\\e64e\";\n}\n\n.iconzuocedaohangshouqi:before {\n  content: \"\\e64f\";\n}\n\n.iconzuocedaohanglanzhankai:before {\n  content: \"\\e650\";\n}\n\n.iconzuocedaohangleshou:before {\n  content: \"\\e651\";\n}\n\n.iconzuocedaohanglansuo:before {\n  content: \"\\e652\";\n}\n\n.iconzuocedaohangsuoqi:before {\n  content: \"\\e653\";\n}\n\n.iconeslogo:before {\n  content: \"\\e654\";\n}\n\n"
  },
  {
    "path": "arius-console/src/assets/icon/iconfont.js",
    "content": "window._iconfont_svg_string_2457502='<svg><symbol id=\"icontuozhuai\" viewBox=\"0 0 1024 1024\"><path d=\"M367.219 273.868c-41.378 0-74.961-34.524-74.961-77.114 0-42.569 33.562-77.092 74.96-77.092s74.962 34.523 74.962 77.113c0 42.57-33.562 77.114-74.961 77.114z m0 308.433c-41.378 0-74.961-34.524-74.961-77.114s33.562-77.113 74.96-77.113 74.962 34.523 74.962 77.113c0 42.59-33.562 77.114-74.961 77.114z m0 308.412c-41.378 0-74.961-34.524-74.961-77.114 0-42.569 33.562-77.092 74.96-77.092s74.962 34.523 74.962 77.113c0 42.57-33.562 77.114-74.961 77.114z m299.865-616.845c-41.4 0-74.961-34.524-74.961-77.114 0-42.569 33.562-77.092 74.96-77.092 41.379 0 74.962 34.523 74.962 77.113 0 42.57-33.562 77.114-74.961 77.114z m0 308.433c-41.4 0-74.961-34.524-74.961-77.114s33.562-77.113 74.96-77.113c41.379 0 74.962 34.523 74.962 77.113 0 42.59-33.562 77.114-74.961 77.114z m0 308.412c-41.4 0-74.961-34.524-74.961-77.114 0-42.569 33.562-77.092 74.96-77.092 41.379 0 74.962 34.523 74.962 77.113 0 42.57-33.562 77.114-74.961 77.114z\"  ></path></symbol><symbol id=\"iconchuangkoufangda\" viewBox=\"0 0 1024 1024\"><path d=\"M214.267 549.533c16.593 0 30.051 13.458 30.051 30.051v168.375l184.404-184.425a30.051 30.051 0 0 1 42.485 0l1.84 1.84a30.051 30.051 0 0 1 0 42.485L288.683 792.242h168.292c16.593 0 30.03 13.437 30.03 30.03v2.612c0 16.593-13.437 30.052-30.03 30.052H211.655a30.051 30.051 0 0 1-30.03-30.052v-245.3c0-16.593 13.437-30.051 30.03-30.051h2.612z m608.381-360.344c16.593 0 30.03 13.459 30.03 30.051v245.3c0 16.594-13.437 30.052-30.03 30.052h-2.612a30.051 30.051 0 0 1-30.051-30.051V296.166L605.58 480.59a30.051 30.051 0 0 1-42.485 0l-1.84-1.839a30.051 30.051 0 0 1 0-42.485l184.362-184.383H577.327a30.051 30.051 0 0 1-30.03-30.03v-2.613c0-16.592 13.437-30.05 30.03-30.05h245.321z\"  ></path></symbol><symbol id=\"iconchuangkousuoxiao\" viewBox=\"0 0 1024 1024\"><path d=\"M446.527 549.533c16.593 0 30.03 13.458 30.03 30.051v245.3c0 16.593-13.437 30.052-30.03 30.052h-2.613a30.051 30.051 0 0 1-30.05-30.052V656.51L229.46 840.934a30.051 30.051 0 0 1-42.486 0l-1.839-1.84a30.051 30.051 0 0 1 0-42.485l184.362-184.382H201.206a30.051 30.051 0 0 1-30.03-30.03v-2.613c0-16.593 13.437-30.051 30.03-30.051h245.32z m122.942-360.344c16.593 0 30.052 13.459 30.052 30.051v168.375l184.403-184.424a30.051 30.051 0 0 1 42.486 0l1.839 1.839a30.051 30.051 0 0 1 0 42.485L643.887 431.898h168.291c16.593 0 30.03 13.438 30.03 30.03v2.613c0 16.593-13.437 30.051-30.03 30.051h-245.3a30.051 30.051 0 0 1-30.03-30.051v-245.3c0-16.593 13.437-30.052 30.03-30.052h2.612z\"  ></path></symbol><symbol id=\"iconDashboard\" viewBox=\"0 0 1024 1024\"><path d=\"M725.333333 149.333333a128 128 0 0 1 128 128v341.333334a128 128 0 0 1-128 128H298.666667a128 128 0 0 1-128-128V277.333333a128 128 0 0 1 128-128h426.666666z m0 64H298.666667a64 64 0 0 0-63.893334 60.245334L234.666667 277.333333v341.333334a64 64 0 0 0 60.245333 63.893333L298.666667 682.666667h426.666666a64 64 0 0 0 63.893334-60.245334L789.333333 618.666667V277.333333a64 64 0 0 0-60.245333-63.893333L725.333333 213.333333z m-6.357333 152.106667a32 32 0 0 1-2.005333 42.837333l-2.432 2.218667-155.968 128a32 32 0 0 1-40.576 0l-2.432-2.197333-87.04-87.573334-120.384 90.602667a32 32 0 0 1-42.837334-3.968l-1.962666-2.368a32 32 0 0 1 3.946666-42.837333l2.389334-1.984 142.677333-107.349334a32 32 0 0 1 39.594667 0.896l2.346666 2.133334 86.165334 86.698666 133.482666-109.546666a32 32 0 0 1 45.013334 4.437333zM352 810.666667h320a32 32 0 0 1 0 64h-320a32 32 0 0 1 0-64z\"  ></path></symbol><symbol id=\"iconzuhuguanli1\" viewBox=\"0 0 1024 1024\"><path d=\"M512 149.333333c123.712 0 224 100.288 224 224 0 76.501333-38.357333 144.042667-96.874667 184.469334a341.056 341.056 0 0 1 84.48 47.573333 32 32 0 1 1-39.082666 50.688C635.669333 618.410667 573.696 597.333333 507.946667 597.333333 357.12 597.333333 235.946667 707.861333 235.946667 842.666667a32 32 0 1 1-64 0c0-130.282667 87.146667-241.130667 210.133333-286.890667A223.637333 223.637333 0 0 1 288 373.333333C288 249.621333 388.288 149.333333 512 149.333333z m309.333333 661.333334a32 32 0 0 1 0 64h-213.333333a32 32 0 0 1 0-64h213.333333z m0-106.666667a32 32 0 0 1 0 64h-149.333333a32 32 0 0 1 0-64h149.333333zM512 213.333333a160 160 0 1 0 0 320 160 160 0 0 0 0-320z\"  ></path></symbol><symbol id=\"iconrenwuzhongxin1\" viewBox=\"0 0 1024 1024\"><path d=\"M725.333333 149.333333a128 128 0 0 1 128 128v469.333334a128 128 0 0 1-128 128H298.666667a128 128 0 0 1-128-128V277.333333a128 128 0 0 1 128-128h426.666666z m0 64H298.666667a64 64 0 0 0-63.893334 60.245334L234.666667 277.333333v469.333334a64 64 0 0 0 60.245333 63.893333L298.666667 810.666667h426.666666a64 64 0 0 0 63.893334-60.245334L789.333333 746.666667V277.333333a64 64 0 0 0-60.245333-63.893333L725.333333 213.333333z m-32 437.333334a32 32 0 0 1 0 64h-362.666666a32 32 0 0 1 0-64h362.666666z m-362.666666-170.666667a32 32 0 1 1 0 64 32 32 0 0 1 0-64z m362.666666 0a32 32 0 0 1 0 64h-256a32 32 0 0 1 0-64h256z m-362.666666-170.666667a32 32 0 1 1 0 64 32 32 0 0 1 0-64z m362.666666 0a32 32 0 0 1 0 64h-256a32 32 0 0 1 0-64h256z\"  ></path></symbol><symbol id=\"iconsuoyinguanli1\" viewBox=\"0 0 1024 1024\"><path d=\"M277.333333 128a128.042667 128.042667 0 0 1 125.034667 100.501333l14.442667 3.072 9.813333 2.133334 19.2 4.416 18.624 4.501333c9.173333 2.282667 18.133333 4.608 26.88 6.976l17.237333 4.778667 16.64 4.906666c2.730667 0.810667 5.44 1.642667 8.106667 2.474667l15.786667 5.077333c147.306667 48.682667 216.853333 113.109333 201.770666 198.933334-12.992 73.962667-64.618667 113.6-147.562666 125.994666l-10.794667 1.450667-11.925333 1.322667-7.936 0.704-8 0.576-8.149334 0.448-8.298666 0.32-8.533334 0.170666-13.333333 0.021334-14.165333-0.277334-9.984-0.362666-10.496-0.512-11.050667-0.64-17.728-1.216-19.306667-1.536-28.458666-2.538667-49.493334-4.864-28.16-2.944c-43.626667-4.565333-64.768 7.466667-72.32 30.976-7.317333 22.72-1.194667 55.68 14.08 78.250667 20.821333 30.826667 72.448 52.181333 148.48 62.250666l14.506667 1.749334 15.104 1.493333c7.68 0.682667 15.573333 1.258667 23.68 1.728l16.469333 0.810667c5.568 0.213333 11.242667 0.426667 16.981334 0.533333l17.493333 0.256c14.826667 0.106667 30.165333-0.085333 45.994667-0.597333l19.264-0.725334 9.813333-0.490666 12.053333-0.704a128 128 0 1 1 10.986667 63.488l-21.162667 1.237333-21.056 0.938667c-13.866667 0.533333-27.434667 0.853333-40.661333 0.96h-19.626667c-151.637333-1.28-257.621333-32.341333-301.354666-97.088-25.770667-38.144-35.626667-91.221333-21.973334-133.674667 17.344-53.994667 67.648-82.624 139.904-75.029333l28.032 2.858666 35.029334 3.328 32.469333 2.730667 22.72 1.664 14.378667 0.896 13.802666 0.725333 19.626667 0.789334 12.352 0.32 17.514667 0.149333 11.029333-0.128 10.474667-0.298667 5.056-0.213333 9.728-0.597333 9.237333-0.789334 8.746667-0.981333 4.224-0.554667 8.042666-1.28c39.125333-6.826667 61.248-21.269333 72.874667-45.12l2.197333-4.906666c0.682667-1.664 1.301333-3.392 1.92-5.141334l1.642667-5.418666c1.024-3.690667 1.877333-7.552 2.602667-11.605334 5.909333-33.6-21.013333-66.688-83.285334-97.173333l-10.709333-5.056a526.08 526.08 0 0 0-23.402667-9.962667l-12.672-4.906666a716.053333 716.053333 0 0 0-13.354666-4.821334l-14.037334-4.8a874.666667 874.666667 0 0 0-7.253333-2.346666l-15.04-4.693334c-7.68-2.346667-15.616-4.650667-23.808-6.912l-16.725333-4.522666c-8.533333-2.261333-17.322667-4.48-26.368-6.656l-18.432-4.352-19.114667-4.266667-3.84-0.853333A128 128 0 1 1 277.333333 128z m469.333334 576a64 64 0 1 0 0 128 64 64 0 0 0 0-128zM277.333333 192a64 64 0 1 0 0 128 64 64 0 0 0 0-128z\"  ></path></symbol><symbol id=\"iconpingtaipeizhi\" viewBox=\"0 0 1024 1024\"><path d=\"M725.333333 149.333333a128 128 0 0 1 128 128v341.333334a128 128 0 0 1-128 128H298.666667a128 128 0 0 1-128-128V277.333333a128 128 0 0 1 128-128h426.666666z m0 64H298.666667a64 64 0 0 0-63.893334 60.245334L234.666667 277.333333v341.333334a64 64 0 0 0 60.245333 63.893333L298.666667 682.666667h426.666666a64 64 0 0 0 63.893334-60.245334L789.333333 618.666667V277.333333a64 64 0 0 0-60.245333-63.893333L725.333333 213.333333z m-32 256a32 32 0 0 1 0 64h-362.666666a32 32 0 0 1 0-64h362.666666z m-362.666666-170.666666a32 32 0 1 1 0 64 32 32 0 0 1 0-64z m362.666666 0a32 32 0 0 1 0 64h-256a32 32 0 0 1 0-64h256z m-341.333333 512h320a32 32 0 0 1 0 64h-320a32 32 0 0 1 0-64z\"  ></path></symbol><symbol id=\"iconmobanguanli1\" viewBox=\"0 0 1024 1024\"><path d=\"M709.333333 128c77.973333 0 141.461333 62.592 143.936 140.757333l0.064 4.693334v349.098666c0 67.285333-45.226667 123.904-106.666666 140.501334V768a128 128 0 0 1-128 128H298.666667a128 128 0 0 1-128-128V384a128.042667 128.042667 0 0 1 107.52-126.357333c7.616-71.36 66.346667-127.253333 138.496-129.557334L421.333333 128h288zM618.666667 320H298.666667a64 64 0 0 0-63.893334 60.245333L234.666667 384v384a64 64 0 0 0 60.245333 63.893333L298.666667 832h320a64 64 0 0 0 63.893333-60.245333L682.666667 768V384a64 64 0 0 0-60.245334-63.893333L618.666667 320zM352 661.333333a32 32 0 0 1 0 64h-64a32 32 0 0 1 0-64h64zM709.333333 186.176h-288c-41.813333 0-76.672 29.994667-84.672 69.824H618.666667a128 128 0 0 1 128 128v317.269333a87.317333 87.317333 0 0 0 48.981333-74.624l0.085333-4.096V273.450667c0-46.826667-36.501333-85.034667-82.346666-87.168l-4.053334-0.106667zM501.333333 533.333333a32 32 0 0 1 0 64h-213.333333a32 32 0 0 1 0-64h213.333333z m85.333334-128a32 32 0 0 1 0 64h-298.666667a32 32 0 0 1 0-64h298.666667z\"  ></path></symbol><symbol id=\"iconjiansuochaxun2\" viewBox=\"0 0 1024 1024\"><path d=\"M181.333333 160h661.333334a32 32 0 0 1 0 64h-661.333334a32 32 0 0 1 0-64z m469.333334 640a32 32 0 0 1 0 64h-469.333334a32 32 0 0 1 0-64h469.333334zM640 384a170.666667 170.666667 0 0 1 134.549333 275.669333l92.16 102.336a32 32 0 1 1-47.573333 42.816L726.4 701.866667A170.666667 170.666667 0 1 1 640 384z m0 64a106.666667 106.666667 0 1 0 0 213.333333 106.666667 106.666667 0 0 0 0-213.333333z m-259.136 138.666667a32 32 0 0 1 0 64H181.333333a32 32 0 0 1 0-64h199.530667z m56.469333-213.333334a32 32 0 0 1 0 64h-256a32 32 0 0 1 0-64h256z\"  ></path></symbol><symbol id=\"iconjiqunguanli2\" viewBox=\"0 0 1024 1024\"><path d=\"M746.666667 149.333333a106.666667 106.666667 0 0 1 76.16 181.333334c18.858667 19.2 30.506667 45.589333 30.506666 74.666666s-11.648 55.466667-30.506666 74.688A106.666667 106.666667 0 0 1 746.666667 661.333333h-202.666667v26.24A106.837333 106.837333 0 0 1 616.533333 768h226.133334a32 32 0 0 1 0 64H609.792a106.688 106.688 0 0 1-195.584 0H181.333333a32 32 0 0 1 0-64h226.133334a106.837333 106.837333 0 0 1 72.533333-80.448V661.333333H277.333333a106.666667 106.666667 0 0 1-76.16-181.333333A106.282667 106.282667 0 0 1 170.666667 405.333333c0-29.077333 11.626667-55.424 30.506666-74.666666A106.666667 106.666667 0 0 1 277.333333 149.333333h469.333334zM512 746.666667a42.666667 42.666667 0 1 0 0 85.333333 42.666667 42.666667 0 0 0 0-85.333333z m234.666667-234.666667H277.333333a42.666667 42.666667 0 0 0-3.2 85.226667L277.333333 597.333333h469.333334a42.666667 42.666667 0 0 0 3.2-85.226666L746.666667 512z m0-149.333333H277.333333a42.666667 42.666667 0 0 0-3.2 85.226666L277.333333 448h469.333334a42.666667 42.666667 0 0 0 3.2-85.226667L746.666667 362.666667z m-448 21.333333a21.333333 21.333333 0 1 1 0 42.666667 21.333333 21.333333 0 0 1 0-42.666667z m448-170.666667H277.333333a42.666667 42.666667 0 0 0-3.2 85.226667L277.333333 298.666667h469.333334a42.666667 42.666667 0 0 0 3.2-85.226667L746.666667 213.333333z m-448 21.333334a21.333333 21.333333 0 1 1 0 42.666666 21.333333 21.333333 0 0 1 0-42.666666z\"  ></path></symbol><symbol id=\"icontiaodurenwu1\" viewBox=\"0 0 1024 1024\"><path d=\"M746.666667 170.666667a128 128 0 0 1 128 128v426.666666a128 128 0 0 1-128 128H277.333333a128 128 0 0 1-128-128V298.666667a128 128 0 0 1 128-128h469.333334z m0 64H277.333333a64 64 0 0 0-63.893333 60.245333L213.333333 298.666667v426.666666a64 64 0 0 0 60.245334 63.893334L277.333333 789.333333h469.333334a64 64 0 0 0 63.893333-60.245333L810.666667 725.333333V298.666667a64 64 0 0 0-60.245334-63.893334L746.666667 234.666667zM394.666667 554.666667a74.666667 74.666667 0 0 1 67.477333 42.666666H736a32 32 0 0 1 0 64l-273.856 0.021334a74.666667 74.666667 0 0 1-134.954667 0L288 661.333333a32 32 0 0 1 0-64h39.189333a74.666667 74.666667 0 0 1 67.477334-42.666666z m256-234.666667a74.666667 74.666667 0 0 1 67.477333 42.666667h17.856a32 32 0 0 1 0 64l-17.856 0.021333a74.666667 74.666667 0 0 1-134.954667 0L288 426.666667a32 32 0 0 1 0-64h295.189333a74.666667 74.666667 0 0 1 67.477334-42.666667z m0 42.666667a32 32 0 1 0 0 64 32 32 0 0 0 0-64z\"  ></path></symbol><symbol id=\"iconcaozuojilu1\" viewBox=\"0 0 1024 1024\"><path d=\"M684.010667 149.333333c79.829333 0 145.216 63.914667 147.904 144.192L832 298.666667v77.568c0 18.197333-14.336 32.96-32 32.96-16.64 0-30.293333-13.077333-31.850667-29.781334l-0.149333-3.2V298.666667c0-44.416-35.114667-81.045333-79.658667-83.285334l-4.330666-0.106666H297.301333c-45.12 0-81.642667 35.221333-83.882666 79.125333L213.333333 298.666667v426.666666c0 44.416 35.114667 81.045333 79.658667 83.285334l4.352 0.106666h77.290667c17.664 0 32 14.762667 32 32.981334 0 17.130667-12.693333 31.210667-28.928 32.810666l-3.072 0.149334h-77.290667c-79.850667 0-145.237333-63.914667-147.925333-144.192L149.333333 725.333333V298.666667c0-80.96 63.701333-146.56 142.933334-149.248L297.344 149.333333h386.645333z m118.805333 359.466667a96 96 0 0 1-4.757333 135.68l-222.250667 207.253333a21.333333 21.333333 0 0 1-15.381333 5.717334l-114.624-4.522667a21.333333 21.333333 0 0 1-20.48-22.165333l0.128-1.6 12.010666-103.978667a21.333333 21.333333 0 0 1 6.634667-13.162667l223.018667-207.978666a96 96 0 0 1 135.68 4.736z m-89.685333 40.064l-2.346667 1.984-211.541333 197.269333-4.928 42.666667 50.858666 2.026667 209.237334-195.157334a32 32 0 0 0 3.584-42.88l-2.005334-2.346666a32 32 0 0 0-42.88-3.562667zM458.666667 480a32 32 0 0 1 0 64h-149.333334a32 32 0 0 1 0-64h149.333334z m213.333333-170.666667a32 32 0 0 1 0 64h-362.666667a32 32 0 0 1 0-64h362.666667z\"  ></path></symbol><symbol id=\"icongongdanrenwu2\" viewBox=\"0 0 1024 1024\"><path d=\"M335.957333 170.666667c18.24 0 33.045333 14.336 33.045334 32 0 16.64-13.12 30.293333-29.866667 31.850666l-3.178667 0.149334h-16.64c-44.138667 0-80.256 33.962667-82.474666 76.778666l-0.106667 4.16v414.122667c0 43.370667 34.752 78.677333 78.336 80.853333l4.245333 0.085334h385.365334c44.138667 0 80.256-33.962667 82.474666-76.778667l0.106667-4.16V315.605333c0-43.370667-34.752-78.677333-78.336-80.853333L704.682667 234.666667H665.813333c-18.261333 0-33.045333-14.336-33.045333-32 0-16.64 13.098667-30.293333 29.866667-31.850667L665.770667 170.666667h38.890666c80.426667 0 145.813333 62.208 148.565334 139.861333l0.085333 5.077333v414.122667c0 78.293333-63.68 142.165333-143.424 144.853333l-5.226667 0.085334H319.317333c-80.426667 0-145.813333-62.208-148.565333-139.861334L170.666667 729.728V315.605333c0-78.293333 63.68-142.165333 143.424-144.853333L319.317333 170.666667h16.64zM693.333333 650.666667a32 32 0 0 1 0 64h-362.666666a32 32 0 0 1 0-64h362.666666z m0-170.666667a32 32 0 0 1 0 64h-362.666666a32 32 0 0 1 0-64h362.666666z m0-170.666667a32 32 0 0 1 0 64h-362.666666a32 32 0 0 1 0-64h362.666666z m-128-149.333333a32 32 0 0 1 0 64h-106.666666a32 32 0 0 1 0-64h106.666666z\"  ></path></symbol><symbol id=\"iconzhibiaokanban2\" viewBox=\"0 0 1024 1024\"><path d=\"M170.666667 584.533333a32 32 0 0 1 32 32v226.133334a32 32 0 0 1-64 0V616.533333A32 32 0 0 1 170.666667 584.533333zM384 512a32 32 0 0 1 32 32v298.666667a32 32 0 0 1-64 0v-298.666667A32 32 0 0 1 384 512z m213.333333 72.533333a32 32 0 0 1 32 32v226.133334a32 32 0 0 1-64 0V616.533333a32 32 0 0 1 32-32zM810.666667 512a32 32 0 0 1 32 32v298.666667a32 32 0 0 1-64 0v-298.666667A32 32 0 0 1 810.666667 512z m20.821333-351.594667a8.533333 8.533333 0 0 1-0.362667 5.376l-42.837333 103.744a8.533333 8.533333 0 0 1-14.336 2.346667l-13.354667-15.36-210.432 195.349333a32 32 0 0 1-43.626666-0.064l-2.197334-2.261333-136.426666-155.264-186.282667 158.506667a32 32 0 0 1-42.858667-1.237334l-2.24-2.389333a32 32 0 0 1 1.258667-42.88l2.368-2.218667 210.261333-178.922666a32 32 0 0 1 42.517334 0.917333l2.261333 2.346667 135.530667 154.176 187.861333-174.378667-10.496-12.074667a8.533333 8.533333 0 0 1 4.309333-13.866666L821.12 154.24a8.533333 8.533333 0 0 1 10.389333 6.144z\"  ></path></symbol><symbol id=\"iconbianji\" viewBox=\"0 0 1024 1024\"><path d=\"M192 817.28c0-15.36 12.544-27.968 28.032-27.968h578.624a28.032 28.032 0 0 1 0 56H220.032A27.968 27.968 0 0 1 192 817.344z m491.2-593.792a107.392 107.392 0 0 1 0 151.872l-314.88 314.88a18.688 18.688 0 0 1-13.12 5.44l-125.824 0.32a18.688 18.688 0 0 1-18.56-16.256l-0.128-2.496 0.32-125.824c0-4.928 1.92-9.6 5.44-13.12l314.88-314.88a107.392 107.392 0 0 1 151.872 0z m-39.616 39.616a51.392 51.392 0 0 0-70.4-2.176l-2.24 2.176-303.936 303.872-0.192 72.896 72.832-0.256 303.936-303.872a51.392 51.392 0 0 0 2.176-70.4l-2.176-2.24z\"  ></path></symbol><symbol id=\"iconxiangqing\" viewBox=\"0 0 1024 1024\"><path d=\"M789.312 128C848.192 128 896 175.744 896 234.688v554.624c0 58.88-47.744 106.688-106.688 106.688H234.688C175.808 896 128 848.256 128 789.312V234.688C128 175.808 175.744 128 234.688 128h554.624z m0 64H234.688a42.688 42.688 0 0 0-42.24 36.352L192 234.688v554.624c0 21.44 15.808 39.168 36.352 42.24l6.336 0.448h554.624a42.688 42.688 0 0 0 42.24-36.352l0.448-6.336V234.688a42.688 42.688 0 0 0-36.352-42.24L789.312 192zM568.064 339.52a32 32 0 0 1 20.48 40.32l-92.288 284.096a32 32 0 1 1-60.8-19.84l92.288-284.032a32 32 0 0 1 40.32-20.48z m125.888 8.832l1.92 2.368 109.504 141.696a32 32 0 0 1 1.92 36.352l-1.92 2.752-109.44 141.696a32 32 0 0 1-52.48-36.608l1.856-2.56L739.648 512l-94.336-122.112a32 32 0 0 1 3.392-42.88l2.368-2.048a32 32 0 0 1 42.88 3.392zM375.68 344.96a32 32 0 0 1 7.552 42.368l-1.792 2.56L287.168 512 381.44 634.112a32 32 0 0 1-3.392 42.88l-2.368 1.984a32 32 0 0 1-42.88-3.392l-1.984-2.368-109.44-141.632a32 32 0 0 1-1.92-36.416l1.92-2.752L330.88 350.72a32 32 0 0 1 44.8-5.76z\"  ></path></symbol><symbol id=\"iconarrow-left\" viewBox=\"0 0 1024 1024\"><path d=\"M247.9104 544l222.72 222.72-45.2608 45.2096-284.8768-284.8256a21.3504 21.3504 0 0 1 0-30.208l284.8768-284.8768 45.2608 45.2608-222.72 222.72H896v64H247.9104z\"  ></path></symbol><symbol id=\"icontop\" viewBox=\"0 0 1024 1024\"><path d=\"M480.023273 370.036364l-222.673455 223.883636-45.381818-45.149091 284.904727-286.487273a21.317818 21.317818 0 0 1 30.161455-0.093091l0.093091 0.093091 284.904727 286.487273-45.381818 45.149091-222.673455-223.883636v563.991272h-63.953454V370.036364zM128 149.317818V85.317818h768v64H128z\"  ></path></symbol><symbol id=\"iconriqi1\" viewBox=\"0 0 1024 1024\"><path d=\"M672 64c16.64 0 30.272 11.776 31.872 26.88l0.128 2.816V128h64a128 128 0 0 1 128 128v512a128 128 0 0 1-128 128H256a128 128 0 0 1-128-128V256a128 128 0 0 1 128-128h64v-34.304C320 77.312 334.336 64 352 64c16.64 0 30.272 11.776 31.872 26.88L384 93.632V128h256v-34.304c0-16.384 14.336-29.696 32-29.696zM832 448H192v320a64 64 0 0 0 64 64h512a64 64 0 0 0 64-64V448zM320 192H256a64 64 0 0 0-64 64v128h640V256a64 64 0 0 0-64-64h-64v55.68c0 16.384-14.336 29.632-32 29.632-16.64 0-30.272-11.776-31.872-26.816L640 247.68V192H384v55.68c0 16.384-14.336 29.632-32 29.632-16.64 0-30.272-11.776-31.872-26.816L320 247.68V192z\"  ></path></symbol><symbol id=\"iconyingyong\" viewBox=\"0 0 1024 1024\"><path d=\"M469.333333 192v213.333333c0 35.328-28.672 64-64 64h-213.333333A64 64 0 0 1 128 405.333333v-213.333333c0-35.328 28.672-64 64-64h213.333333c35.328 0 64 28.672 64 64z m-85.333333 0h-170.666667a21.333333 21.333333 0 0 0-21.333333 21.333333v170.666667c0 11.776 9.557333 21.333333 21.333333 21.333333h170.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-170.666667a21.333333 21.333333 0 0 0-21.333333-21.333333z m512 0v213.333333c0 35.328-28.672 64-64 64h-213.333333A64 64 0 0 1 554.666667 405.333333v-213.333333c0-35.328 28.672-64 64-64h213.333333c35.328 0 64 28.672 64 64z m-85.333333 0h-170.666667a21.333333 21.333333 0 0 0-21.333333 21.333333v170.666667c0 11.776 9.557333 21.333333 21.333333 21.333333h170.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-170.666667a21.333333 21.333333 0 0 0-21.333333-21.333333z m-341.333334 426.666667v213.333333c0 35.328-28.672 64-64 64h-213.333333a64 64 0 0 1-64-64v-213.333333c0-35.328 28.672-64 64-64h213.333333c35.328 0 64 28.672 64 64z m-85.333333 0h-170.666667a21.333333 21.333333 0 0 0-21.333333 21.333333v170.666667c0 11.776 9.557333 21.333333 21.333333 21.333333h170.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-170.666667a21.333333 21.333333 0 0 0-21.333333-21.333333z m512 0v213.333333c0 35.328-28.672 64-64 64h-213.333333a64 64 0 0 1-64-64v-213.333333c0-35.328 28.672-64 64-64h213.333333c35.328 0 64 28.672 64 64z m-85.333333 0h-170.666667a21.333333 21.333333 0 0 0-21.333333 21.333333v170.666667c0 11.776 9.557333 21.333333 21.333333 21.333333h170.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-170.666667a21.333333 21.333333 0 0 0-21.333333-21.333333z\"  ></path></symbol><symbol id=\"iconwarning-circle\" viewBox=\"0 0 1024 1024\"><path d=\"M512 938.6496a426.6496 426.6496 0 1 1 0-853.2992 426.6496 426.6496 0 1 1 0 853.2992z m-42.6496-277.2992v85.2992h85.2992v-85.2992H469.3504z m0-384v320h85.2992v-320H469.3504z\" fill=\"#FFC300\" ></path></symbol><symbol id=\"iconinfo-circle\" viewBox=\"0 0 1024 1024\"><path d=\"M512 85.3504a426.6496 426.6496 0 1 1 0 853.2992 426.6496 426.6496 0 1 1 0-853.2992z m42.6496 277.2992V277.3504H469.3504v85.2992h85.2992z m0 384v-320H469.3504v320h85.2992z\" fill=\"#1473FF\" ></path></symbol><symbol id=\"iconerror-circle\" viewBox=\"0 0 1024 1024\"><path d=\"M512 938.6496a426.6496 426.6496 0 1 1 0-853.2992 426.6496 426.6496 0 1 1 0 853.2992z m0-366.336l135.7824 135.7824 60.3136-60.3136L572.3136 512l135.7824-135.7824-60.3136-60.3136L512 451.6864 376.2176 315.904 315.904 376.2176 451.6864 512 315.904 647.7824l60.3136 60.3136L512 572.3136z\" fill=\"#F5483B\" ></path></symbol><symbol id=\"iconsuccess-circle\" viewBox=\"0 0 1024 1024\"><path d=\"M813.7216 813.7216A426.7008 426.7008 0 1 1 210.2784 210.2784a426.7008 426.7008 0 0 1 603.392 603.392z m-355.328-246.1184L337.6128 446.976 277.3504 507.2896l180.992 180.992 286.6176-286.6176-60.3136-60.3136-226.304 226.304z\" fill=\"#00B365\" ></path></symbol><symbol id=\"icona-knowsearch\" viewBox=\"0 0 5440 1024\"><path d=\"M510.464 591.872h-85.248c11.52-45.984 17.28-86.208 17.28-132.16 0-45.984-5.76-91.936-17.28-132.16h258.592c80.448 0 143.68 57.44 143.68 132.16 0 2.656-0.096 5.312-0.256 7.936a299.744 299.744 0 0 0-68.704-7.936 298.528 298.528 0 0 0-248.064 132.16z m-3.84 327.488l-6.72 0.064c-86.176 0-155.136-23.008-224.064-51.744 57.44-57.44 97.664-132.16 126.4-206.848l74.24-1.28a298.368 298.368 0 0 0-16.768 98.976 297.44 297.44 0 0 0 46.944 160.896v-0.064zM0 453.952c0-45.952 5.76-86.176 17.248-126.4h344.768c11.52 40.224 17.248 86.176 17.248 132.16 0 45.952-5.76 86.176-17.248 132.16H22.976C5.76 551.648 0 499.936 0 453.952zM51.712 264.32C86.208 189.632 149.44 126.4 224.096 80.448 270.08 132.16 310.304 195.36 344.768 264.32H51.712z m683.84 0L402.24 258.56c-28.736-74.688-68.96-149.376-126.4-206.848C344.736 17.28 413.76 0 499.904 0c172.384 0 327.52 74.688 419.488 189.632-45.984 45.984-109.184 74.688-183.904 74.688zM45.92 655.072h293.088c-28.736 68.96-68.96 132.16-120.672 178.144a467.232 467.232 0 0 1-172.384-178.144z\" fill=\"#FFFFFF\" ></path><path d=\"M752.32 1003.008a250.72 250.72 0 0 1-250.816-250.656 250.72 250.72 0 0 1 250.56-250.88h0.224a250.72 250.72 0 0 1 250.72 250.784 250.72 250.72 0 0 1-250.72 250.752z m0-45.6a205.12 205.12 0 0 0 205.12-205.152 205.12 205.12 0 1 0-205.12 205.12z\" fill=\"#FFFFFF\" ></path><path d=\"M740.128 666.944h-40.864v-51.456h45.216c73.472 0.928 131.456 63.04 133.056 135.904-0.48 74.016-58.88 136.608-133.12 137.6h-81.248c-8.288 0.096-13.664-5.12-13.568-13.056v-208.96h49.6l0.064 163.84c0 4.224 2.656 6.72 6.944 6.72h33.12c48.16-0.544 87.648-38.336 88.128-86.144-1.536-46.784-39.808-83.872-87.36-84.448z\" fill=\"#FFFFFF\" ></path><path d=\"M1414.4 309.12V736h-90.88V309.12h90.88z m3.2 211.2l163.2-211.2h119.68l-178.56 211.2L1692.16 736h-119.68l-154.88-215.68zM1743.36 424.32h165.12c24.736 0 43.616 1.824 56.64 5.44 13.024 3.616 24.864 10.144 35.52 19.52 21.76 20.064 32.64 51.616 32.64 94.72v192h-85.76v-201.6c0-15.36-3.424-26.464-10.24-33.28-6.816-6.816-18.144-10.24-33.92-10.24h-74.24V736h-85.76v-311.68zM2257.28 419.84c57.6 0 100.064 16.64 127.36 49.92 25.184 30.304 37.76 68.48 37.76 114.56 0 48.64-15.776 87.456-47.36 116.48-29.024 26.464-68.704 39.68-119.04 39.68-52.064 0-92.8-14.944-122.24-44.8-27.296-26.88-40.96-66.144-40.96-117.76 0-43.52 13.024-79.776 39.04-108.8 29.024-32.416 70.816-48.864 125.44-49.28z m0.64 65.28c-51.616 0-77.44 32-77.44 96 0 26.016 4.256 45.856 12.8 59.52 14.08 23.04 35.84 34.56 65.28 34.56 50.784 0 76.16-31.776 76.16-95.36 0-62.304-25.6-93.856-76.8-94.72zM2664.32 669.44v-245.12h85.76v245.12h92.16v-245.12h85.12V736h-314.88c-28.576 0-50.336-2.144-65.28-6.4a78.624 78.624 0 0 1-37.12-22.4c-18.784-20.48-28.16-48.64-28.16-84.48v-198.4h85.12v184.96c0 14.944 0.736 25.376 2.24 31.36 1.504 5.984 4.384 11.296 8.64 16 8.96 8.544 22.4 12.8 40.32 12.8h46.08zM3331.84 736v-76.16h195.2c31.136 0 51.84-2.976 62.08-8.96 14.944-8.96 22.4-22.4 22.4-40.32 0-20.896-8.736-36.064-26.24-45.44-9.824-5.536-25.6-8.32-47.36-8.32h-79.36c-48.224 0-82.976-8.736-104.32-26.24a114.656 114.656 0 0 1-31.04-41.6 129.792 129.792 0 0 1-11.2-53.76c0-29.856 8.736-57.184 26.24-81.92 17.056-23.904 44.384-37.984 81.92-42.24 12.8-1.28 31.776-1.92 56.96-1.92h211.84v76.16h-191.36c-28.576 0.416-47.584 1.696-56.96 3.84-19.2 4.704-28.8 19.2-28.8 43.52 0 20.48 8.096 34.144 24.32 40.96 10.656 5.12 28.576 7.68 53.76 7.68h68.48c34.976 0 61.024 2.976 78.08 8.96 30.304 10.24 51.2 28.16 62.72 53.76 8.96 20.48 13.44 42.464 13.44 65.92 0 26.016-5.984 49.28-17.92 69.76-16.64 29.024-41.6 46.496-74.88 52.48-16.224 2.56-40.736 3.84-73.6 3.84h-214.4zM4031.36 546.56v66.56h-180.48c1.696 20.48 8.32 34.976 19.84 43.52 11.52 8.544 30.304 12.8 56.32 12.8h104.32V736h-113.92c-24.736 0-44.896-2.24-60.48-6.72a134.784 134.784 0 0 1-43.84-22.08c-37.984-29.44-56.96-73.184-56.96-131.2 0-37.536 10.016-70.4 30.08-98.56 13.664-19.2 30.08-32.864 49.28-40.96 19.2-8.096 44.384-12.16 75.52-12.16h120.32v66.56h-113.92c-23.456 0-39.904 3.936-49.28 11.84-9.376 7.904-15.136 22.496-17.28 43.84h180.48zM4316.16 546.56c0-21.76-4.384-36.48-13.12-44.16-8.736-7.68-26.144-11.52-52.16-11.52h-144.64v-66.56h144.64c26.016 0 43.936 0.544 53.76 1.6 9.824 1.056 19.84 3.104 30.08 6.08 47.36 17.92 69.76 60.8 67.2 128.64V736h-180.48c-32.416 0-54.816-0.96-67.2-2.88a84.032 84.032 0 0 1-32.64-11.84c-25.184-17.056-37.76-42.88-37.76-77.44 0-20.896 5.024-39.584 15.04-56 10.016-16.416 23.36-27.616 40-33.6 14.496-5.12 38.624-7.68 72.32-7.68h104.96z m0 66.56h-113.28c-9.824 0-17.6 2.56-23.36 7.68-5.76 5.12-8.64 12.16-8.64 21.12 0 9.824 3.52 16.864 10.56 21.12 7.04 4.256 19.104 6.4 36.16 6.4h98.56v-56.32zM4481.92 424.32h126.72c26.016 0 46.176 1.824 60.48 5.44 14.304 3.616 26.144 9.696 35.52 18.24 9.376 8.544 16 19.2 19.84 32s5.76 31.136 5.76 55.04v30.08h-82.56v-16.64c0-22.176-3.84-37.344-11.52-45.44-7.68-8.096-22.4-12.16-44.16-12.16h-24.32V736h-85.76v-311.68zM5041.92 424.32v66.56h-102.4c-34.56 0-58.464 7.68-71.68 23.04-12.8 14.496-19.2 36.704-19.2 66.56 0 33.28 10.464 57.6 31.36 72.96 8.544 5.984 17.824 10.144 27.84 12.48 10.016 2.336 24 3.52 41.92 3.52h92.16V736h-117.12c-31.584 0-56.544-3.2-74.88-9.6a115.84 115.84 0 0 1-48.64-33.28c-26.88-29.856-40.32-67.84-40.32-113.92 0-55.456 16-96.864 48-124.16 12.8-11.104 28.16-18.976 46.08-23.68 17.92-4.704 41.184-7.04 69.76-7.04h117.12zM5192.96 309.12v115.2h87.68c26.016 0 46.4 2.016 61.12 6.08 14.72 4.064 27.2 11.2 37.44 21.44 19.616 17.92 29.44 48 29.44 90.24V736h-85.76v-177.28c0-16.64-0.736-28.48-2.24-35.52a38.208 38.208 0 0 0-9.28-18.24c-8.544-8.96-24.736-13.664-48.64-14.08h-69.76V736h-85.76V309.12h85.76z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"icontouxiang\" viewBox=\"0 0 1024 1024\"><path d=\"M512 448a128 128 0 1 0 0-256 128 128 0 0 0 0 256zM512 512a192 192 0 1 1 0-384 192 192 0 0 1 0 384z m162.304 64H349.696a215.7568 215.7568 0 0 0-200.6016 136.4992l-14.8992 37.632A106.6496 106.6496 0 0 0 233.4208 896H790.528a106.6496 106.6496 0 0 0 99.2256-145.8688l-14.848-37.632a215.7568 215.7568 0 0 0-200.704-136.4992z m0 64c62.2592 0 118.2208 38.0416 141.1072 96l14.848 37.632a42.6496 42.6496 0 0 1-39.68 58.368H233.472a42.6496 42.6496 0 0 1-39.68-58.368l14.848-37.632A151.7568 151.7568 0 0 1 349.7472 640h324.5056z\"  ></path></symbol><symbol id=\"icontuichudenglu\" viewBox=\"0 0 1024 1024\"><path d=\"M660.1216 554.6496H436.1216a32 32 0 1 1 0-64h224V432.3328a21.3504 21.3504 0 0 1 32.3072-18.2784l150.528 90.3168a21.3504 21.3504 0 0 1 0 36.608l-150.528 90.3168a21.3504 21.3504 0 0 1-32.256-18.3296v-58.3168z m-335.9744-448c-79.7696 0-144.0256 66.0992-144.0256 147.2v537.6c0 81.1008 64.256 147.2 144.0256 147.2h373.2992c79.7696 0 144.0256-66.048 144.0256-147.2v-65.024a32 32 0 0 0-64 0v65.024c0 46.1824-36.0448 83.2-80.0256 83.2H324.1472c-44.032 0-80.0256-37.0176-80.0256-83.2v-537.6c0-46.1312 36.0448-83.2 80.0256-83.2h373.2992c44.032 0 80.0256 37.0688 80.0256 83.2v24.7296a32 32 0 1 0 64 0v-24.7296c0-81.1008-64.256-147.2-144.0256-147.2H324.1472z\"  ></path></symbol><symbol id=\"icontuichuquanju\" viewBox=\"0 0 1024 1024\"><path d=\"M188.918 423.1c19.372 0 32.287-12.936 32.287-32.308V229.25h161.541c19.393 0 32.33-12.957 32.33-32.33 0-19.393-12.937-32.308-32.309-32.308h-193.87c-19.373 0-32.309 12.915-32.309 32.308v193.87c0 19.373 12.936 32.31 32.309 32.31z m646.164 193.85c-19.372 0-32.287 12.935-32.287 32.308v161.541H641.254c-19.393 0-32.33 12.936-32.33 32.33 0 19.372 12.937 32.307 32.309 32.307h193.87c19.373 0 32.309-12.935 32.309-32.308v-193.87c0-19.373-12.936-32.308-32.309-32.308zM579.856 436.015c3.218 6.478 9.696 12.915 16.154 16.154 3.218 3.24 9.696 3.24 12.915 3.24h193.87c19.373 0 32.308-12.937 32.308-32.309 0-19.393-12.935-32.308-32.308-32.308H686.477l171.238-171.259c12.936-12.915 12.936-32.308 0-45.223-6.478-6.478-12.915-9.697-22.612-9.697-9.696 0-16.154 3.24-22.611 9.697L641.233 345.548V229.23c0-19.394-12.915-32.309-32.308-32.309-19.373 0-32.309 12.915-32.309 32.309V423.1c0 3.218 0 9.676 3.24 12.915zM211.487 865.74l171.26-171.238V810.82c0 19.372 12.914 32.308 32.307 32.308 19.373 0 32.309-12.936 32.309-32.308V616.95c0-3.24 0-9.697-3.24-12.915a38.933 38.933 0 0 0-16.154-16.155c-3.218-3.239-9.696-3.239-12.915-3.239h-193.87c-19.372 0-32.308 12.915-32.308 32.309s12.936 32.308 32.308 32.308h116.318L166.264 820.496c-12.936 12.936-12.936 32.329 0 45.244 12.915 12.915 32.308 12.915 45.223 0z\"  ></path></symbol><symbol id=\"iconxitongguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M536.090947 630.514526a20.210526 20.210526 0 0 1 0.538948 0.538948l82.674526 85.90821 58.260211 60.631579 80.734315 83.968a10.078316 10.078316 0 0 1-7.275789 17.084632H293.187368a10.132211 10.132211 0 0 1-7.275789-17.084632l221.615158-230.507789a20.210526 20.210526 0 0 1 28.56421-0.538948z m380.119579-297.498947v323.368421a121.263158 121.263158 0 0 1-121.263158 121.263158h-33.253052l-58.314105-60.685474h91.567157c33.468632 0 60.631579-27.162947 60.631579-60.631579v-323.368421c0-33.468632-27.162947-60.631579-60.631579-60.631579H229.052632c-33.468632 0-60.631579 27.162947-60.631579 60.631579v323.368421c0 33.468632 27.162947 60.631579 60.631579 60.631579h111.777684l-58.314105 60.631579H229.052632a121.263158 121.263158 0 0 1-121.263158-121.263158v-323.368421a121.263158 121.263158 0 0 1 121.263158-121.263158h565.894736a121.263158 121.263158 0 0 1 121.263158 121.263158z\"  ></path></symbol><symbol id=\"iconduojiqunguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M145.515789 269.743158v439.888842a64.673684 64.673684 0 0 0 64.673685 64.673684h603.621052a64.673684 64.673684 0 0 0 64.673685-64.673684V269.743158a64.673684 64.673684 0 0 0-64.673685-64.673684H210.189474a64.673684 64.673684 0 0 0-64.673685 64.673684z m64.673685-130.425263h603.621052a129.347368 129.347368 0 0 1 129.347369 129.347368v441.936842a129.347368 129.347368 0 0 1-129.347369 129.347369H210.189474a129.347368 129.347368 0 0 1-129.347369-129.347369v-441.936842a129.347368 129.347368 0 0 1 129.347369-129.347368z m140.665263 481.711158h322.290526a32.875789 32.875789 0 0 1 0 65.697684H350.854737a32.875789 32.875789 0 0 1 0-65.697684zM285.642105 292.648421a43.115789 43.115789 0 0 1 43.11579 43.11579v1.347368a43.115789 43.115789 0 1 1-86.231579 0V335.764211a43.115789 43.115789 0 0 1 43.115789-43.11579z m0 153.222737a43.115789 43.115789 0 0 1 43.11579 43.115789v1.347369a43.115789 43.115789 0 1 1-86.231579 0v-1.347369a43.115789 43.115789 0 0 1 43.115789-43.115789zM436.547368 292.648421a43.115789 43.115789 0 0 1 43.11579 43.11579v1.347368a43.115789 43.115789 0 1 1-86.231579 0V335.764211a43.115789 43.115789 0 0 1 43.115789-43.11579z m0 153.222737a43.115789 43.115789 0 0 1 43.11579 43.115789v1.347369a43.115789 43.115789 0 1 1-86.231579 0v-1.347369a43.115789 43.115789 0 0 1 43.115789-43.115789z m150.905264-153.222737a43.115789 43.115789 0 0 1 43.115789 43.11579v1.347368a43.115789 43.115789 0 1 1-86.231579 0V335.764211a43.115789 43.115789 0 0 1 43.11579-43.11579z m0 153.222737a43.115789 43.115789 0 0 1 43.115789 43.115789v1.347369a43.115789 43.115789 0 1 1-86.231579 0v-1.347369a43.115789 43.115789 0 0 1 43.11579-43.115789z m150.905263-153.222737a43.115789 43.115789 0 0 1 43.115789 43.11579v1.347368a43.115789 43.115789 0 1 1-86.231579 0V335.764211a43.115789 43.115789 0 0 1 43.11579-43.11579z m0 153.222737a43.115789 43.115789 0 0 1 43.115789 43.115789v1.347369a43.115789 43.115789 0 1 1-86.231579 0v-1.347369a43.115789 43.115789 0 0 1 43.11579-43.115789z\"  ></path></symbol><symbol id=\"iconquanju\" viewBox=\"0 0 1024 1024\"><path d=\"M188.918 423.1c19.372 0 32.287-12.936 32.287-32.308V229.25h161.541c19.393 0 32.33-12.957 32.33-32.33 0-19.393-12.937-32.308-32.309-32.308h-193.87c-19.373 0-32.309 12.915-32.309 32.308v193.87c0 19.373 12.936 32.31 32.309 32.31z m646.164 193.85c-19.372 0-32.287 12.935-32.287 32.308v161.541H641.254c-19.393 0-32.33 12.936-32.33 32.33 0 19.372 12.937 32.307 32.309 32.307h193.87c19.373 0 32.309-12.935 32.309-32.308v-193.87c0-19.373-12.936-32.308-32.309-32.308z m29.09-432.943a38.933 38.933 0 0 0-16.154-16.155c-3.218-3.239-9.696-3.239-12.915-3.239h-193.87c-19.372 0-32.308 12.915-32.308 32.308s12.936 32.309 32.308 32.309h116.318L586.313 400.468c-12.915 12.935-12.915 32.308 0 45.244 6.479 6.478 12.915 9.696 22.612 9.696 9.696 0 16.154-3.239 22.632-9.696l171.238-171.238v116.318c0 19.372 12.915 32.308 32.308 32.308 19.373 0 32.309-12.936 32.309-32.308v-193.87c0-3.24 0-9.697-3.24-12.915zM392.464 594.338L221.226 765.576V649.258c0-19.373-12.915-32.308-32.308-32.308-19.373 0-32.309 12.935-32.309 32.308v193.87c0 3.218 0 9.697 3.24 12.915 3.218 6.478 9.696 12.936 16.154 16.154 3.218 3.24 9.696 3.24 12.915 3.24h193.87c19.372 0 32.308-12.936 32.308-32.309 0-19.393-12.936-32.308-32.308-32.308H266.449l171.238-171.26c12.915-12.915 12.915-32.308 0-45.223-12.915-12.936-32.308-12.936-45.244 0z\"  ></path></symbol><symbol id=\"iconruanjianguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M970.816 806.4l-78.528 136a66.944 66.944 0 0 1-57.984 33.472h-157.056c-23.936 0-46.08-12.8-57.984-33.472L540.736 806.4a66.944 66.944 0 0 1 0-67.008l78.528-136c11.968-20.672 34.048-33.472 57.984-33.472h157.056c23.872 0 46.016 12.8 57.984 33.472l78.528 136c11.904 20.736 11.904 46.272 0 67.008z m-46.4-26.816a13.44 13.44 0 0 0 1.28-10.112l-1.28-3.264-78.528-136a13.44 13.44 0 0 0-8.128-6.272l-3.456-0.448h-157.056a13.44 13.44 0 0 0-9.472 3.904l-2.112 2.816-78.528 136a13.44 13.44 0 0 0-1.344 10.112l1.28 3.264 78.592 136a13.44 13.44 0 0 0 8.064 6.272l3.52 0.448h157.056a13.44 13.44 0 0 0 9.408-3.904l2.176-2.816 78.528-136z\" fill=\"#2F81F9\" ></path><path d=\"M896 40.192a96 96 0 0 1 96 96v251.072a96 96 0 0 1-96 96H128a96 96 0 0 1-96-96V136.192A96 96 0 0 1 128 40.192h768z m0 64H128a32 32 0 0 0-31.488 26.24l-0.512 5.76v251.072a32 32 0 0 0 26.24 31.488l5.76 0.512h768a32 32 0 0 0 31.488-26.24l0.512-5.76V136.192a32 32 0 0 0-26.24-31.488L896 104.192zM379.072 548.288a96 96 0 0 1 96 96v251.072a96 96 0 0 1-96 96H128a96 96 0 0 1-96-96v-251.072a96 96 0 0 1 96-96h251.072z m0 64H128a32 32 0 0 0-31.488 26.24l-0.512 5.76v251.072a32 32 0 0 0 26.24 31.488l5.76 0.512h251.072a32 32 0 0 0 31.488-26.24l0.512-5.76v-251.072a32 32 0 0 0-26.24-31.488l-5.76-0.512z\" fill=\"#303A51\" ></path><path d=\"M755.776 689.216a83.712 83.712 0 1 1 0 167.36 83.712 83.712 0 0 1 0-167.36z m0 33.472a50.24 50.24 0 1 0 0 100.48 50.24 50.24 0 0 0 0-100.48z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconpingtaiguanli\" viewBox=\"0 0 1088 1024\"><path d=\"M914.88 52.16a128 128 0 0 1 128 128v545.792a128 128 0 0 1-128 128H146.88a128 128 0 0 1-128-128V162.496C18.88 101.568 68.288 52.16 129.216 52.16H914.88z m0 64H129.216a46.336 46.336 0 0 0-45.888 40.064L82.88 162.496v563.456a64 64 0 0 0 56.512 63.616l7.488 0.384h768a64 64 0 0 0 63.552-56.512l0.448-7.488V180.16a64 64 0 0 0-56.512-63.552L914.88 116.16z\" fill=\"#303A51\" ></path><path d=\"M274.88 952.832m32 0l448 0q32 0 32 32l0 0q0 32-32 32l-448 0q-32 0-32-32l0 0q0-32 32-32Z\" fill=\"#303A51\" ></path><path d=\"M457.408 251.008h236.8a32 32 0 0 1 0 64h-236.8a32 32 0 0 1 0-64zM367.552 315.136a32 32 0 1 0 0-64 32 32 0 0 0 0 64z m0 97.088h326.656a32 32 0 0 1 0 64H367.552a32 32 0 1 1 0-64z m0 161.216h326.656a32 32 0 1 1 0 64H367.552a32 32 0 0 1 0-64z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconrenwuzhongxin\" viewBox=\"0 0 1024 1024\"><path d=\"M836.126118 9.999059a120.470588 120.470588 0 0 1 120.470588 120.470588v722.823529a120.470588 120.470588 0 0 1-120.470588 120.470589H189.921882a120.470588 120.470588 0 0 1-120.470588-120.470589v-722.823529a120.470588 120.470588 0 0 1 120.470588-120.470588H836.065882z m0 60.235294H189.921882a60.235294 60.235294 0 0 0-59.873882 53.187765l-0.361412 7.047529v722.823529a60.235294 60.235294 0 0 0 53.187765 59.813648l7.047529 0.421647H836.065882a60.235294 60.235294 0 0 0 59.813647-53.248l0.421647-6.987295v-722.823529a60.235294 60.235294 0 0 0-53.187764-59.873882l-7.04753-0.361412z\" fill=\"#303A51\" ></path><path d=\"M431.043765 250.940235h282.503529a34.394353 34.394353 0 1 1 0 68.788706h-282.503529a34.394353 34.394353 0 1 1 0-68.788706z m0 206.486589h282.503529a34.394353 34.394353 0 1 1 0 68.848941h-282.503529a34.394353 34.394353 0 1 1 0-68.848941z m-140.589177 206.546823h423.092706a34.394353 34.394353 0 1 1 0 68.848941H290.454588a34.394353 34.394353 0 0 1 0-68.848941z m0.722824-344.244706a34.755765 34.755765 0 0 0 35.177412-34.394353 34.755765 34.755765 0 0 0-35.177412-34.394353 34.755765 34.755765 0 0 0-35.117177 34.334118c0 19.094588 15.721412 34.454588 35.117177 34.454588z m0 206.546824a34.755765 34.755765 0 0 0 35.177412-34.394353 34.755765 34.755765 0 0 0-35.177412-34.454588 34.755765 34.755765 0 0 0-35.117177 34.454588c0 18.974118 15.721412 34.334118 35.117177 34.334117z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconzuhuguanli\" viewBox=\"0 0 1088 1024\"><path d=\"M737.216 770.432m32 0l243.2 0q32 0 32 32l0 0q0 32-32 32l-243.2 0q-32 0-32-32l0 0q0-32 32-32Z\" fill=\"#2F81F9\" ></path><path d=\"M660.416 914.688m32 0l320 0q32 0 32 32l0 0q0 32-32 32l-320 0q-32 0-32-32l0 0q0-32 32-32Z\" fill=\"#2F81F9\" ></path><path d=\"M546.56 0a272 272 0 1 1 0 544 272 272 0 0 1 0-544z m0 64a208 208 0 1 0 0 416 208 208 0 0 0 0-416z\" fill=\"#303A51\" ></path><path d=\"M532.352 480c120.384 0 233.856 44.928 320.896 124.544a32 32 0 1 1-43.2 47.232A411.52 411.52 0 0 0 120.832 955.52a32 32 0 1 1-64 0A475.52 475.52 0 0 1 532.352 480z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconxitongguanli2\" viewBox=\"0 0 1024 1024\"><path d=\"M719.510588 572.355765c3.192471 19.275294 20.540235 33.430588 40.96 33.490823a41.140706 41.140706 0 0 0 41.140706-33.310117c28.129882 5.601882 54.633412 16.865882 77.824 33.129411a38.671059 38.671059 0 0 0 1.264941 52.10353c13.854118 14.697412 36.803765 17.408 53.970824 6.384941 11.384471 18.612706 19.395765 38.791529 23.853176 59.753412a40.357647 40.357647 0 0 0-33.008941 39.03247 40.357647 40.357647 0 0 0 32.768 39.032471 188.536471 188.536471 0 0 1-27.346823 64.572235 42.947765 42.947765 0 0 0-49.392942 7.710118 38.550588 38.550588 0 0 0-5.903058 47.585882c-22.528 15.058824-47.826824 25.539765-74.390589 30.72a41.261176 41.261176 0 0 0-40.779294-31.382588 41.261176 41.261176 0 0 0-40.598588 31.623529 206.004706 206.004706 0 0 1-74.571294-30.418823 38.671059 38.671059 0 0 0-5.782588-48.188235 42.947765 42.947765 0 0 0-50.115765-7.228236 188.536471 188.536471 0 0 1-27.527529-64.752941 40.357647 40.357647 0 0 0 33.792-39.273412 40.357647 40.357647 0 0 0-34.032942-39.152941c4.517647-21.202824 12.649412-41.502118 24.154353-60.054588 17.106824 11.444706 40.478118 9.035294 54.573177-5.782588a38.671059 38.671059 0 0 0 1.024-52.705883c23.491765-16.263529 50.055529-27.467294 78.125176-32.88847z m40.598588 101.436235c-51.139765 0-92.581647 39.755294-92.581647 88.726588 0 49.031529 41.441882 88.847059 92.521412 88.847059 51.2 0 92.641882-39.755294 92.641883-88.847059 0-48.971294-41.441882-88.726588-92.581648-88.726588z\" fill=\"#2F81F9\" ></path><path d=\"M230.942118 204.619294m30.117647 0l468.931764 0q30.117647 0 30.117647 30.117647l0 0q0 30.117647-30.117647 30.117647l-468.931764 0q-30.117647 0-30.117647-30.117647l0 0q0-30.117647 30.117647-30.117647Z\" fill=\"#303A51\" ></path><path d=\"M230.942118 433.453176m30.117647 0l336.655059 0q30.117647 0 30.117647 30.117648l0 0q0 30.117647-30.117647 30.117647l-336.655059 0q-30.117647 0-30.117647-30.117647l0 0q0-30.117647 30.117647-30.117648Z\" fill=\"#303A51\" ></path><path d=\"M230.942118 662.226824m30.117647 0l167.815529 0q30.117647 0 30.117647 30.117647l0 0q0 30.117647-30.117647 30.117647l-167.815529 0q-30.117647 0-30.117647-30.117647l0 0q0-30.117647 30.117647-30.117647Z\" fill=\"#303A51\" ></path><path d=\"M811.008 5.842824c59.392 0 107.881412 46.561882 112.399059 105.472l0.301176 8.975058v318.162824a30.117647 30.117647 0 0 1-59.753411 5.421176l-0.481883-5.421176V120.289882a53.609412 53.609412 0 0 0-45.899294-53.790117l-6.565647-0.421647H178.176a53.127529 53.127529 0 0 0-52.043294 47.344941l-0.421647 6.866823V851.124706a53.609412 53.609412 0 0 0 45.899294 53.790118l6.565647 0.421647H434.296471a30.117647 30.117647 0 0 1 5.421176 59.753411l-5.421176 0.481883H178.176c-59.452235 0-107.881412-46.622118-112.399059-105.532236l-0.301176-8.914823V120.289882C65.475765 60.175059 111.073882 10.721882 169.261176 6.144l8.854589-0.301176h632.832z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconcaozuojilu\" viewBox=\"0 0 1024 1024\"><path d=\"M890.096941 627.410824c30.117647 30.900706 30.117647 80.896 0 111.73647l-225.761882 231.544471a13.251765 13.251765 0 0 1-9.456941 4.035764l-90.232471 0.240942a13.492706 13.492706 0 0 1-13.251765-11.986824l-0.180706-1.807059 0.240942-92.521412c0-3.614118 1.445647-7.107765 3.975529-9.637647l225.761882-231.604705a75.655529 75.655529 0 0 1 108.905412 0z m-28.431059 29.153882a36.141176 36.141176 0 0 0-50.416941-1.566118l-1.686588 1.566118-217.931294 223.533176-0.120471 53.609412 52.224-0.180706 217.931294-223.472941a38.490353 38.490353 0 0 0 1.566118-51.802353l-1.566118-1.686588z\" fill=\"#2F81F9\" ></path><path d=\"M293.526588 224.858353h474.051765a30.117647 30.117647 0 1 1 0 60.235294h-474.051765a30.117647 30.117647 0 1 1 0-60.235294z m0 221.003294h320.692706a30.117647 30.117647 0 1 1 0 60.235294H293.526588a30.117647 30.117647 0 1 1 0-60.235294z m0 222.268235h141.552941a30.117647 30.117647 0 1 1 0 60.235294h-141.552941a30.117647 30.117647 0 1 1 0-60.235294z\" fill=\"#303A51\" ></path><path d=\"M828.416 35.900235c59.392 0 107.881412 46.561882 112.399059 105.532236l0.301176 8.914823V468.630588a30.117647 30.117647 0 0 1-59.753411 5.421177l-0.481883-5.421177V150.347294a53.609412 53.609412 0 0 0-45.899294-53.790118l-6.565647-0.421647H195.584a53.127529 53.127529 0 0 0-52.043294 47.405177l-0.421647 6.806588v731.075765a53.609412 53.609412 0 0 0 45.899294 53.850353l6.565647 0.421647h256.120471a30.117647 30.117647 0 0 1 5.421176 59.753412l-5.421176 0.481882H195.584c-59.392 0-107.881412-46.622118-112.399059-105.532235l-0.301176-8.975059V150.347294C82.883765 90.352941 128.542118 40.779294 186.729412 36.201412l8.854588-0.301177h632.832z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconzhibiaokanban1\" viewBox=\"0 0 1024 1024\"><path d=\"M42.688 692.992m32 0l0 0q32 0 32 32l0 267.008q0 32-32 32l0 0q-32 0-32-32l0-267.008q0-32 32-32Z\" fill=\"#303A51\" ></path><path d=\"M554.944 692.992m32 0l0 0q32 0 32 32l0 267.008q0 32-32 32l0 0q-32 0-32-32l0-267.008q0-32 32-32Z\" fill=\"#303A51\" ></path><path d=\"M298.816 610.24m32 0l0 0q32 0 32 32l0 349.76q0 32-32 32l0 0q-32 0-32-32l0-349.76q0-32 32-32Z\" fill=\"#303A51\" ></path><path d=\"M811.072 610.24m32 0l0 0q32 0 32 32l0 349.76q0 32-32 32l0 0q-32 0-32-32l0-349.76q0-32 32-32Z\" fill=\"#303A51\" ></path><path d=\"M785.92 172.288a43.52 43.52 0 0 1 59.648 8.96 40.448 40.448 0 0 1-3.456 52.864l-5.76 4.928L494.72 481.28a43.712 43.712 0 0 1-55.424-4.16l-4.992-5.888-142.08-201.6-219.776 207.872a43.712 43.712 0 0 1-54.528 4.16L12.16 476.8a40.448 40.448 0 0 1-4.288-52.864L12.8 418.24l256.128-242.176a43.648 43.648 0 0 1 60.16 0.448l4.928 5.76 145.856 206.976 305.92-216.96z\" fill=\"#2F81F9\" ></path><path d=\"M948.416 115.328l-63.936 145.92a16.576 16.576 0 0 1-28.16 3.52L757.76 138.24a16.576 16.576 0 0 1 11.136-26.624l162.304-19.328a16.576 16.576 0 0 1 17.152 23.04z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconhong\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 312.896A199.104 199.104 0 0 0 312.896 512v256H256a28.416 28.416 0 0 0 0 56.896h512A28.416 28.416 0 0 0 768 768h-56.896V512A199.104 199.104 0 0 0 512 312.896z m3.84 145.152a22.784 22.784 0 0 1 30.976-8.448c9.6 5.44 13.824 17.024 9.92 28.032l-1.408 3.008-37.504 65.472h41.28a25.6 25.6 0 0 1 24.192 17.472l1.152 4.672 0.256 3.456a26.112 26.112 0 0 1-1.792 9.408l-1.6 3.328-54.4 95.296a22.784 22.784 0 0 1-31.104 8.448 22.912 22.912 0 0 1-9.856-28.032l1.408-3.008 37.312-65.536h-41.088a24.384 24.384 0 0 1-6.08-0.704l-3.328-1.088-3.328-1.536a25.728 25.728 0 0 1-11.008-31.808l1.472-3.136z m337.472 25.536h-56.896a28.416 28.416 0 0 0 0 56.832h56.96a28.416 28.416 0 1 0 0-56.832z m-625.728 0h-56.96a28.416 28.416 0 1 0 0 56.832h56.96a28.416 28.416 0 0 0 0-56.832z m545.92-233.088a28.416 28.416 0 0 0-40.256 0l-40.256 40.256a28.416 28.416 0 1 0 40.256 40.256l40.256-40.256a28.416 28.416 0 0 0 0-40.256z m-487.232-3.584a28.48 28.48 0 0 0-35.776 43.84l40.256 40.256 4.48 3.648a28.48 28.48 0 0 0 35.776-43.904l-40.256-40.256zM512 142.208a28.416 28.416 0 0 0-28.416 28.48v56.896a28.416 28.416 0 0 0 56.832 0v-56.96A28.416 28.416 0 0 0 512 142.272z\" fill=\"#F46A6A\" ></path></symbol><symbol id=\"iconhuang\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 312.896A199.104 199.104 0 0 0 312.896 512v256H256a28.416 28.416 0 0 0 0 56.896h512A28.416 28.416 0 0 0 768 768h-56.896V512A199.104 199.104 0 0 0 512 312.896z m3.84 145.152a22.784 22.784 0 0 1 30.976-8.448c9.6 5.44 13.824 17.024 9.92 28.032l-1.408 3.008-37.504 65.472h41.28a25.6 25.6 0 0 1 24.192 17.472l1.152 4.672 0.256 3.456a26.112 26.112 0 0 1-1.792 9.408l-1.6 3.328-54.4 95.296a22.784 22.784 0 0 1-31.104 8.448 22.912 22.912 0 0 1-9.856-28.032l1.408-3.008 37.312-65.536h-41.088a24.384 24.384 0 0 1-6.08-0.704l-3.328-1.088-3.328-1.536a25.728 25.728 0 0 1-11.008-31.808l1.472-3.136z m337.472 25.536h-56.896a28.416 28.416 0 0 0 0 56.832h56.96a28.416 28.416 0 1 0 0-56.832z m-625.728 0h-56.96a28.416 28.416 0 1 0 0 56.832h56.96a28.416 28.416 0 0 0 0-56.832z m545.92-233.088a28.416 28.416 0 0 0-40.256 0l-40.256 40.256a28.416 28.416 0 1 0 40.256 40.256l40.256-40.256a28.416 28.416 0 0 0 0-40.256z m-487.232-3.584a28.48 28.48 0 0 0-35.776 43.84l40.256 40.256 4.48 3.648a28.48 28.48 0 0 0 35.776-43.904l-40.256-40.256zM512 142.208a28.416 28.416 0 0 0-28.416 28.48v56.896a28.416 28.416 0 0 0 56.832 0v-56.96A28.416 28.416 0 0 0 512 142.272z\" fill=\"#F1B44C\" ></path></symbol><symbol id=\"iconlv\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 312.896A199.104 199.104 0 0 0 312.896 512v256H256a28.416 28.416 0 0 0 0 56.896h512A28.416 28.416 0 0 0 768 768h-56.896V512A199.104 199.104 0 0 0 512 312.896z m3.84 145.152a22.784 22.784 0 0 1 30.976-8.448c9.6 5.44 13.824 17.024 9.92 28.032l-1.408 3.008-37.504 65.472h41.28a25.6 25.6 0 0 1 24.192 17.472l1.152 4.672 0.256 3.456a26.112 26.112 0 0 1-1.792 9.408l-1.6 3.328-54.4 95.296a22.784 22.784 0 0 1-31.104 8.448 22.912 22.912 0 0 1-9.856-28.032l1.408-3.008 37.312-65.536h-41.088a24.384 24.384 0 0 1-6.08-0.704l-3.328-1.088-3.328-1.536a25.728 25.728 0 0 1-11.008-31.808l1.472-3.136z m337.472 25.536h-56.896a28.416 28.416 0 0 0 0 56.832h56.96a28.416 28.416 0 1 0 0-56.832z m-625.728 0h-56.96a28.416 28.416 0 1 0 0 56.832h56.96a28.416 28.416 0 0 0 0-56.832z m545.92-233.088a28.416 28.416 0 0 0-40.256 0l-40.256 40.256a28.416 28.416 0 1 0 40.256 40.256l40.256-40.256a28.416 28.416 0 0 0 0-40.256z m-487.232-3.584a28.48 28.48 0 0 0-35.776 43.84l40.256 40.256 4.48 3.648a28.48 28.48 0 0 0 35.776-43.904l-40.256-40.256zM512 142.208a28.416 28.416 0 0 0-28.416 28.48v56.896a28.416 28.416 0 0 0 56.832 0v-56.96A28.416 28.416 0 0 0 512 142.272z\" fill=\"#34C38F\" ></path></symbol><symbol id=\"iconRight\" viewBox=\"0 0 1024 1024\"><path d=\"M549.504 512L397.888 360.384a9.6 9.6 0 0 1 0-13.568l31.68-31.68a9.6 9.6 0 0 1 13.568 0l190.08 190.08a9.6 9.6 0 0 1 0 13.568l-190.08 190.08a9.6 9.6 0 0 1-13.568 0l-31.68-31.68a9.6 9.6 0 0 1 0-13.568L549.504 512z\"  ></path></symbol><symbol id=\"iconleft\" viewBox=\"0 0 1024 1024\"><path d=\"M474.496 512l151.616-151.616a9.6 9.6 0 0 0 0-13.568l-31.68-31.68a9.6 9.6 0 0 0-13.568 0l-190.08 190.08a9.6 9.6 0 0 0 0 13.568l190.08 190.08a9.6 9.6 0 0 0 13.568 0l31.68-31.68a9.6 9.6 0 0 0 0-13.568L474.496 512z\"  ></path></symbol><symbol id=\"iconweizhi\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 312.896A199.104 199.104 0 0 0 312.896 512v256H256a28.416 28.416 0 0 0 0 56.896h512A28.416 28.416 0 0 0 768 768h-56.896V512A199.104 199.104 0 0 0 512 312.896z m3.84 145.152a22.784 22.784 0 0 1 30.976-8.448c9.6 5.44 13.824 17.024 9.92 28.032l-1.408 3.008-37.504 65.472h41.28a25.6 25.6 0 0 1 24.192 17.472l1.152 4.672 0.256 3.456a26.112 26.112 0 0 1-1.792 9.408l-1.6 3.328-54.4 95.296a22.784 22.784 0 0 1-31.104 8.448 22.912 22.912 0 0 1-9.856-28.032l1.408-3.008 37.312-65.536h-41.088a24.384 24.384 0 0 1-6.08-0.704l-3.328-1.088-3.328-1.536a25.728 25.728 0 0 1-11.008-31.808l1.472-3.136z m337.472 25.536h-56.896a28.416 28.416 0 0 0 0 56.832h56.96a28.416 28.416 0 1 0 0-56.832z m-625.728 0h-56.96a28.416 28.416 0 1 0 0 56.832h56.96a28.416 28.416 0 0 0 0-56.832z m545.92-233.088a28.416 28.416 0 0 0-40.256 0l-40.256 40.256a28.416 28.416 0 1 0 40.256 40.256l40.256-40.256a28.416 28.416 0 0 0 0-40.256z m-487.232-3.584a28.48 28.48 0 0 0-35.776 43.84l40.256 40.256 4.48 3.648a28.48 28.48 0 0 0 35.776-43.904l-40.256-40.256zM512 142.208a28.416 28.416 0 0 0-28.416 28.48v56.896a28.416 28.416 0 0 0 56.832 0v-56.96A28.416 28.416 0 0 0 512 142.272z\" fill=\"#A8ADBD\" ></path></symbol><symbol id=\"iconshuaxin2\" viewBox=\"0 0 1024 1024\"><path d=\"M814.136889 162.247111A462.222222 462.222222 0 0 0 133.404444 777.329778L280.917333 512H142.222222a369.777778 369.777778 0 0 1 625.834667-266.808889l46.08-82.944zM209.92 861.752889A462.222222 462.222222 0 0 0 890.595556 246.670222L743.025778 512H881.777778a369.777778 369.777778 0 0 1-625.834667 266.808889l-46.08 82.944z\"  ></path></symbol><symbol id=\"iconjianshao\" viewBox=\"0 0 1024 1024\"><path d=\"M960 0C995.362133 0 1024 28.672 1024 64v896C1024 995.362133 995.328 1024 960 1024H64A64 64 0 0 1 0 960V64C0 28.637867 28.672 0 64 0h896z m0 32.017067H64a32.017067 32.017067 0 0 0-31.778133 28.2624l-0.2048 3.720533v896c0 16.384 12.322133 29.934933 28.2624 31.778133l3.720533 0.2048h896c16.384 0 29.934933-12.322133 31.778133-28.2624l0.2048-3.720533V64a32.017067 32.017067 0 0 0-28.2624-31.778133l-3.720533-0.2048z\" fill=\"#D7DAE0\" ></path><path d=\"M490.666667 490.666667h196.266666c3.549867 0 6.417067 2.8672 6.417067 6.417066v29.832534a6.382933 6.382933 0 0 1-6.417067 6.417066H337.066667a6.382933 6.382933 0 0 1-6.417067-6.417066v-29.832534c0-3.549867 2.8672-6.417067 6.417067-6.417066h153.6z\" fill=\"#5B6675\" ></path></symbol><symbol id=\"iconzengjia\" viewBox=\"0 0 1024 1024\"><path d=\"M960 0C995.362133 0 1024 28.672 1024 64v896C1024 995.362133 995.328 1024 960 1024H64A64 64 0 0 1 0 960V64C0 28.637867 28.672 0 64 0h896z m0 32.017067H64a32.017067 32.017067 0 0 0-31.778133 28.2624l-0.2048 3.720533v896c0 16.384 12.322133 29.934933 28.2624 31.778133l3.720533 0.2048h896c16.384 0 29.934933-12.322133 31.778133-28.2624l0.2048-3.720533V64a32.017067 32.017067 0 0 0-28.2624-31.778133l-3.720533-0.2048z\" fill=\"#D7DAE0\" ></path><path d=\"M490.666667 490.666667v-153.6c0-3.549867 2.8672-6.417067 6.417066-6.417067h29.832534c3.549867 0 6.417067 2.8672 6.417066 6.417067v153.6h153.6c3.549867 0 6.417067 2.8672 6.417067 6.417066v29.832534a6.382933 6.382933 0 0 1-6.417067 6.417066h-153.6v153.6a6.382933 6.382933 0 0 1-6.417066 6.417067h-29.832534a6.382933 6.382933 0 0 1-6.417066-6.417067v-153.6h-153.6a6.382933 6.382933 0 0 1-6.417067-6.417066v-29.832534c0-3.549867 2.8672-6.417067 6.417067-6.417066h153.6z\" fill=\"#5B6675\" ></path></symbol><symbol id=\"icontiaodurenwu\" viewBox=\"0 0 1024 1024\"><path d=\"M899.584 29.184A89.6 89.6 0 0 1 989.184 118.784v780.8a89.6 89.6 0 0 1-89.6 89.6H118.784A89.6 89.6 0 0 1 29.184 899.584V118.784A89.6 89.6 0 0 1 118.784 29.184h780.8z m0 64H118.784a25.6 25.6 0 0 0-25.088 20.48L93.184 118.784v780.8a25.6 25.6 0 0 0 20.48 25.088L118.784 925.184h780.8a25.6 25.6 0 0 0 25.088-20.48L925.184 899.584V118.784a25.6 25.6 0 0 0-20.48-25.088L899.584 93.184zM392.448 560.64a112 112 0 0 1 107.328 80h290.496c21.632 0 39.168 14.336 39.168 32 0 15.68-13.824 28.8-32.128 31.488l-7.04 0.512H499.776a112 112 0 0 1-214.656 0h-56.512c-21.632 0-39.168-14.336-39.168-32 0-15.68 13.888-28.8 32.128-31.488l7.04-0.512H285.184a112 112 0 0 1 107.328-80z m397.824-240.384c21.632 0 39.168 14.272 39.168 32 0 15.68-13.824 28.8-32.128 31.488l-7.04 0.512H228.608c-21.632 0-39.168-14.336-39.168-32 0-15.744 13.888-28.8 32.128-31.488l7.04-0.512h561.664z\" fill=\"#303A51\" ></path><path d=\"M639.68 352.064m-70.208 0a70.208 70.208 0 1 0 140.416 0 70.208 70.208 0 1 0-140.416 0Z\" fill=\"#FFFFFF\" ></path><path d=\"M638.72 224.384a128 128 0 1 1 0 256 128 128 0 0 1 0-256z m0 64a64 64 0 1 0 0 128 64 64 0 0 0 0-128z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconjiansuochaxun\" viewBox=\"0 0 1024 1024\"><path d=\"M838.144 712.768l4.416 3.712 165.12 165.568a32 32 0 0 1-40.832 48.96l-4.48-3.712-165.12-165.632a32 32 0 0 1 40.896-48.896z m-342.336 159.104a32 32 0 0 1 5.76 63.488l-5.76 0.512H37.12a32 32 0 0 1-5.76-63.488l5.76-0.512h458.752zM341.504 614.272a32 32 0 0 1 5.76 63.488l-5.76 0.512H37.056a32 32 0 0 1-5.76-63.488l5.76-0.512h304.448z m65.28-257.6a32 32 0 0 1 5.76 63.424l-5.76 0.576H37.056a32 32 0 0 1-5.76-63.488l5.76-0.512h369.728z m281.792-257.664a32 32 0 0 1 5.76 63.488l-5.76 0.512H37.056a32 32 0 0 1-5.76-63.488l5.76-0.512h651.52z\" fill=\"#303A51\" ></path><path d=\"M666.624 334.336a233.408 233.408 0 1 1 0 466.752 233.408 233.408 0 0 1 0-466.752z m0 64a169.408 169.408 0 1 0 0 338.752 169.408 169.408 0 0 0 0-338.752z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconsuoyinguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M272 8.448a182.4 182.4 0 0 1 180.672 156.992l-6.336-1.92c237.952 72.768 360.96 162.752 360.96 278.08 0 122.048-71.616 164.736-251.968 165.312l-31.104-0.32-33.152-1.024-35.2-1.728-37.376-2.432-39.488-3.008c-86.208-7.04-128.896 47.744-105.408 115.392 28.736 82.944 138.176 138.688 302.72 123.968a32 32 0 1 1 5.76 63.744c-191.616 17.152-329.6-53.12-368.96-166.72-38.592-111.36 38.848-211.008 171.072-200.192l56.832 4.224 34.688 2.048 32.256 1.344 29.76 0.64h27.52l25.152-0.704c112.448-5.248 152.96-35.2 152.96-100.544 0-73.984-95.424-146.368-293.504-209.92A182.528 182.528 0 0 1 89.6 190.912 182.4 182.4 0 0 1 272 8.512z m0 76.8a105.6 105.6 0 1 0 0 211.2 105.6 105.6 0 0 0 0-211.2z\" fill=\"#303A51\" ></path><path d=\"M741.632 649.216a182.4 182.4 0 1 0 0 364.8 182.4 182.4 0 0 0 0-364.8z m0 76.8a105.6 105.6 0 1 1 0 211.2 105.6 105.6 0 0 1 0-211.2z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconmobanguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M899.84 1.6a89.6 89.6 0 0 1 89.6 89.6v716.8a89.6 89.6 0 0 1-89.6 89.6H832v36.8a89.6 89.6 0 0 1-89.6 89.6H153.6A89.6 89.6 0 0 1 64 934.4V217.6A89.6 89.6 0 0 1 153.6 128h67.776l0.128-36.8a89.6 89.6 0 0 1 89.6-89.6h588.8zM742.4 192H153.6a25.6 25.6 0 0 0-25.088 20.48L128 217.6v716.8a25.6 25.6 0 0 0 20.48 25.088L153.6 960h588.8a25.6 25.6 0 0 0 25.088-20.48L768 934.4V217.6a25.6 25.6 0 0 0-20.48-25.088L742.4 192z m157.44-126.4h-588.8a25.6 25.6 0 0 0-25.024 20.48l-0.512 5.12L285.44 128h456.96A89.6 89.6 0 0 1 832 217.6v616h67.84a25.6 25.6 0 0 0 25.152-20.48l0.512-5.12v-716.8a25.6 25.6 0 0 0-20.48-25.088l-5.12-0.512z\" fill=\"#303A51\" ></path><path d=\"M352 709.376a32 32 0 0 1 1.856 63.936H224a32 32 0 0 1-1.856-63.872l1.92-0.064H352zM475.072 532.352c19.968 0 36.352 13.76 36.928 31.104 0.576 17.28-14.848 31.872-34.816 32.832l-2.112 0.064H228.928c-19.968 0-36.352-13.76-36.928-31.04-0.576-17.28 14.848-31.872 34.816-32.896h248.256zM606.4 355.392c18.176 0 33.024 13.76 33.6 31.04a32.64 32.64 0 0 1-31.68 32.896h-382.72A32.896 32.896 0 0 1 192 388.352a32.64 32.64 0 0 1 31.68-32.832l1.92-0.064h380.8z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"icongongdanrenwu\" viewBox=\"0 0 1024 1024\"><path d=\"M286.016 352.256h446.656a30.912 30.912 0 0 0 32.064-32.064 30.912 30.912 0 0 0-32.064-32.128h-446.72a30.912 30.912 0 0 0-32 32.128c0 18.688 16 32.064 32 32.064z m449.28 128.384H286.08a30.912 30.912 0 0 0-32.128 32.128c0 18.688 13.44 32.064 32.128 32.064h446.656a30.912 30.912 0 0 0 32.064-32.064c0-18.752-13.376-32.128-29.44-32.128z m0 189.952H286.08a30.912 30.912 0 0 0-32.128 32.064c0 18.752 13.44 32.128 32.128 32.128h446.656a30.912 30.912 0 0 0 32.064-32.128c0-16-13.376-32.064-29.44-32.064zM417.088 159.68h160.512a48 48 0 0 0 48.128-48.128 48 48 0 0 0-48.128-48.128H417.024a48 48 0 0 0-48.128 48.128 48 48 0 0 0 48.128 48.128z\" fill=\"#303A51\" ></path><path d=\"M828.928 95.488h-32.064a30.912 30.912 0 0 0-32.128 32.128c0 18.752 13.44 32.064 32.128 32.064h32.064a63.36 63.36 0 0 1 64.192 64.192v607.168c0 34.752-29.44 64.192-64.192 64.192H189.696c-34.752 0-64.192-29.44-64.192-64.192V223.872c0-34.752 29.44-64.192 64.192-64.192h32.128a30.912 30.912 0 0 0 32.064-32.064 30.912 30.912 0 0 0-32.064-32.128h-32.128C120.192 95.488 64 154.368 64 223.872v607.168c0 69.568 56.192 128.384 128.384 128.384h639.232A128.384 128.384 0 0 0 960 831.04V223.872c-2.688-69.504-58.88-128.384-131.072-128.384z\" fill=\"#303A51\" ></path><path d=\"M286.016 352.256h446.656a30.912 30.912 0 0 0 32.064-32.064 30.912 30.912 0 0 0-32.064-32.128h-446.72a30.912 30.912 0 0 0-32 32.128c0 18.688 16 32.064 32 32.064z m449.28 128.384H286.08a30.912 30.912 0 0 0-32.128 32.128c0 18.688 13.44 32.064 32.128 32.064h446.656a30.912 30.912 0 0 0 32.064-32.064c0-18.752-13.376-32.128-29.44-32.128z m0 189.952H286.08a30.912 30.912 0 0 0-32.128 32.064c0 18.752 13.44 32.128 32.128 32.128h446.656a30.912 30.912 0 0 0 32.064-32.128c0-16-13.376-32.064-29.44-32.064z\" fill=\"#2F81F9\" ></path><path d=\"M221.824 95.488c18.688 0 32.064 13.44 32.064 32.128a30.912 30.912 0 0 1-32.064 32.064h-32.128c-34.752 0-64.192 29.44-64.192 64.192v607.168c0 34.752 29.44 64.192 64.192 64.192h639.232c34.816 0 64.192-29.44 64.192-64.192V223.872a63.36 63.36 0 0 0-64.192-64.192h-32.064a30.912 30.912 0 0 1-32.128-32.064c0-18.752 13.44-32.128 32.128-32.128h32.064c72.256 0 128.384 58.88 131.072 128.384v607.168c0 72.192-58.88 128.384-128.384 128.384H192.384A128.384 128.384 0 0 1 64 831.04V223.872c0-69.504 56.192-128.384 125.696-128.384zM577.536 63.424a48 48 0 0 1 48.128 48.128 48 48 0 0 1-48.128 48.128H417.024a48 48 0 0 1-48.128-48.128 48 48 0 0 1 48.128-48.128z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconjiqunguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M986.176 816.512c15.552 0 28.16 14.272 28.16 32 0 15.68-9.92 28.8-23.104 31.424l-5.12 0.512H82.688c-15.616 0-28.224-14.272-28.224-32 0-15.68 9.984-28.8 23.168-31.424l5.056-0.512h903.552zM848.96 13.952a108.8 108.8 0 0 1 108.8 108.8v23.552c0 28.16-10.688 53.824-28.288 73.152l-6.912 6.976 6.4 6.272c17.856 19.392 28.8 45.312 28.8 73.792v23.552c0 28.16-10.688 53.824-28.288 73.152l-6.912 6.976 6.4 6.272c17.856 19.392 28.8 45.312 28.8 73.792v23.552a108.8 108.8 0 0 1-108.8 108.8H566.336v119.488a32 32 0 0 1-63.424 5.76l-0.512-5.76-0.064-119.488H219.84a108.8 108.8 0 0 1-108.8-108.8V490.24c0-28.16 10.688-53.824 28.288-73.152l6.848-6.912-6.336-6.4a108.416 108.416 0 0 1-28.8-73.728V306.56c0-28.16 10.688-53.824 28.288-73.152l6.848-6.912-6.336-6.4a108.416 108.416 0 0 1-28.8-73.728v-23.552a108.8 108.8 0 0 1 108.8-108.8h629.12z m0 425.088h-629.12a51.2 51.2 0 0 0-50.816 44.8l-0.384 6.4v23.552a51.2 51.2 0 0 0 44.8 50.816l6.4 0.384h629.12a51.2 51.2 0 0 0 50.816-44.8l0.384-6.4V490.24a51.2 51.2 0 0 0-44.8-50.816l-6.4-0.384z m-591.552 29.44c19.456 0 35.2 15.04 35.2 33.536a34.368 34.368 0 0 1-35.2 33.472 34.368 34.368 0 0 1-35.136-33.472c0-18.496 15.744-33.472 35.2-33.472z m591.552-213.184h-629.12a51.2 51.2 0 0 0-50.816 44.8l-0.384 6.4v23.552a51.2 51.2 0 0 0 44.8 50.816l6.4 0.384h629.12a51.2 51.2 0 0 0 50.816-44.8l0.384-6.4V306.56a51.2 51.2 0 0 0-44.8-50.816l-6.4-0.384z m-591.552 29.44c19.456 0 35.2 15.04 35.2 33.536a34.368 34.368 0 0 1-35.2 33.472 34.368 34.368 0 0 1-35.136-33.472c0-18.496 15.744-33.472 35.2-33.472z m591.552-213.184h-629.12a51.2 51.2 0 0 0-50.816 44.8l-0.384 6.4v23.552a51.2 51.2 0 0 0 44.8 50.816l6.4 0.384h629.12a51.2 51.2 0 0 0 50.816-44.8l0.384-6.4v-23.552a51.2 51.2 0 0 0-44.8-50.816l-6.4-0.384z m-591.552 29.44c19.456 0 35.2 15.04 35.2 33.536a34.368 34.368 0 0 1-35.2 33.472 34.368 34.368 0 0 1-35.136-33.472c0-18.496 15.744-33.472 35.2-33.472z\" fill=\"#303A51\" ></path><path d=\"M534.656 847.744m-82.816 0a82.816 82.816 0 1 0 165.632 0 82.816 82.816 0 1 0-165.632 0Z\" fill=\"#FFFFFF\" ></path><path d=\"M534.4 704.448a144 144 0 1 1 0 288 144 144 0 0 1 0-288z m0 64a80 80 0 1 0 0 160 80 80 0 0 0 0-160z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconzhibiaokanban\" viewBox=\"0 0 1024 1024\"><path d=\"M868.48 845.248H156.8c-86.08 0-156.16-71.04-156.16-158.528V158.528C0.704 71.04 70.784 0 156.864 0h711.68c86.144 0 156.16 71.04 156.16 158.528v528.192c0 87.424-70.08 158.528-156.224 158.528zM156.8 73.152c-46.336 0-84.096 38.272-84.096 85.376v528.192c0 47.104 37.76 85.376 84.096 85.376h711.68c46.336 0 84.096-38.272 84.096-85.376V158.528c0-47.104-37.76-85.376-84.096-85.376H156.8zM740.544 1024H284.8a36.352 36.352 0 0 1-36.096-36.608c0-20.16 16.192-36.544 36.096-36.544h455.68c19.84 0 36.032 16.384 36.032 36.544a36.352 36.352 0 0 1-36.032 36.608z\" fill=\"#303135\" ></path><path d=\"M213.056 568.704a35.648 35.648 0 0 1-26.24-11.52 36.864 36.864 0 0 1 1.472-51.648l190.976-183.296a35.648 35.648 0 0 1 49.088-0.384l152.192 141.44 206.848-201.6a35.648 35.648 0 0 1 50.944 1.088 36.992 36.992 0 0 1-1.024 51.712L606.08 539.776a35.712 35.712 0 0 1-49.28 0.64L404.352 398.72 237.824 558.72a35.84 35.84 0 0 1-24.768 9.984z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconjiantou_youshang\" viewBox=\"0 0 1024 1024\"><path d=\"M861.44 276.309333V650.24H1024V0H373.845333v162.56h373.76L0 910.250667 113.749333 1024z\" fill=\"#1473FF\" ></path></symbol><symbol id=\"iconshaixuan\" viewBox=\"0 0 1024 1024\"><path d=\"M944 33.216c42.688 0 63.104 52.48 31.616 81.28l-323.84 296.128-14.912 534.656a46.848 46.848 0 0 1-64.64 41.984l-6.208-3.2-216.064-129.856a46.784 46.784 0 0 1-22.656-40.128V408.192L46.08 112.256a46.848 46.848 0 0 1 26.88-78.528l7.04-0.512z m7.36 780.352a48.256 48.256 0 1 1 0 96.512H759.872a48.256 48.256 0 1 1 0-96.512H951.36z m-127.872-686.72H188.992L408 357.248a47.232 47.232 0 0 1 12.352 25.152l0.576 7.168-0.064 397.952 124.672 75.072 13.248-474.368a46.784 46.784 0 0 1 10.048-27.712l5.12-5.504 249.536-228.224z m127.872 528.64a48.256 48.256 0 1 1 0 96.512H759.872a48.256 48.256 0 1 1 0-96.512H951.36z m0-158.016a48.256 48.256 0 1 1 0 96.512H759.872a48.256 48.256 0 0 1 0-96.512H951.36z\"  ></path></symbol><symbol id=\"iconfuzhi\" viewBox=\"0 0 1024 1024\"><path d=\"M672 288a64 64 0 0 1 64 64v448a64 64 0 0 1-64 64H224a64 64 0 0 1-64-64V352a64 64 0 0 1 64-64h448z m0 64H224v448h448V352z\"  ></path><path d=\"M800 128a96 96 0 0 1 95.552 86.784L896 224v384a96 96 0 0 1-86.784 95.552L800 704h-61.248v-64H800a32 32 0 0 0 31.488-26.24L832 608V224a32 32 0 0 0-26.24-31.488L800 192H416a32 32 0 0 0-31.488 26.24L384 224v63.68h-64V224a96 96 0 0 1 86.784-95.552L416 128h384z\"  ></path></symbol><symbol id=\"icona-gengduo-kafka\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 85.333a426.667 426.667 0 1 0 0 853.334 426.667 426.667 0 0 0 0-853.334z\" fill=\"#A8ADBD\" ></path><path d=\"M256 460.8c-28.16 0-51.2 23.04-51.2 51.2 0 28.16 23.04 51.2 51.2 51.2 28.16 0 51.2-23.04 51.2-51.2 0-28.16-23.04-51.2-51.2-51.2z m512 0c-28.16 0-51.2 23.04-51.2 51.2 0 28.16 23.04 51.2 51.2 51.2 28.16 0 51.2-23.04 51.2-51.2 0-28.16-23.04-51.2-51.2-51.2z m-256 0c-28.16 0-51.2 23.04-51.2 51.2 0 28.16 23.04 51.2 51.2 51.2 28.16 0 51.2-23.04 51.2-51.2 0-28.16-23.04-51.2-51.2-51.2z\" fill=\"#A8ADBD\" ></path></symbol><symbol id=\"iconinfo\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m28.233 406.455c-15.36 4.535-29.184 9.07-41.472 13.604a1420.479 1420.479 0 0 0-35.547 13.605c-11.264 4.535-22.82 9.29-34.45 14.117-11.703 4.9-24.87 10.24-39.498 16.091l8.997 27.21c8.63-1.976 15.14-3.073 19.456-3.439a26.112 26.112 0 0 1 11.556 1.463c4.608 1.317 8.12 4.389 10.46 9.29a61.001 61.001 0 0 1 5.047 15.506c0.95 5.559 1.463 10.605 1.463 15.14v6.803c0 3.218-0.147 7.606-0.512 13.165l-0.951 14.775-1.024 15.36-4.023 61.294c-1.682 26.258-4.17 61.44-7.46 105.545 0 18.14 1.17 33.573 3.437 46.153 2.34 12.654 6.217 23.845 11.557 33.646 3.291 3.218 6.144 5.12 8.484 5.851a36.864 36.864 0 0 0 9.509 0.878 605.623 605.623 0 0 0 84.992-38.4c29.33-15.872 60.708-34.23 93.988-54.93l1.024-28.233c-14.043 5.12-24.503 8.923-31.451 11.19-7.095 2.195-13.166 4.023-18.578 5.34a136.777 136.777 0 0 1-20.48 3.438 205.531 205.531 0 0 1-19.53 1.462c-8.045 0.586-12.434-5.193-13.458-17.554a628.15 628.15 0 0 1-1.463-48.64v-7.753c0-3.291 0.293-9.143 0.951-17.554 0.658-8.412 1.463-20.92 2.487-37.45a8256.545 8256.545 0 0 1 4.535-68.607c1.975-26.551 3.657-50.542 4.974-71.973 1.316-21.358 1.974-35.035 1.974-40.814a16.823 16.823 0 0 0-4.973-12.653c-3.365-3.292-6.656-4.243-10.02-2.926zM523.264 201.07a64 64 0 1 0 0 128 64 64 0 0 0 0-128z\"  ></path></symbol><symbol id=\"icones-logo\" viewBox=\"0 0 1024 1024\"><path d=\"M521.152 604.256h-87.04c11.744-46.912 17.6-88 17.6-134.912 0-46.944-5.856-93.888-17.6-134.944h264c82.144 0 146.688 58.656 146.688 134.944 0 2.72-0.096 5.44-0.224 8.096a306.016 306.016 0 0 0-70.176-8.096 304.768 304.768 0 0 0-253.248 134.912z m-3.904 334.368l-6.848 0.032c-88 0-158.4-23.456-228.8-52.8 58.656-58.656 99.744-134.912 129.056-211.2l75.84-1.28a304.64 304.64 0 0 0-17.152 101.024 303.68 303.68 0 0 0 47.904 164.256v-0.032zM0 463.456c0-46.912 5.856-88 17.6-129.056h352c11.744 41.056 17.6 88 17.6 134.944 0 46.912-5.856 88-17.6 134.912H23.456C5.856 563.2 0 510.4 0 463.456z m52.8-193.6c35.2-76.256 99.744-140.8 176-187.712C275.744 134.944 316.8 199.456 352 269.856H52.8z m698.144 0L410.656 264c-29.312-76.256-70.4-152.544-129.056-211.2C352 17.6 422.4 0 510.4 0c176 0 334.4 76.256 428.256 193.6-46.912 46.944-111.456 76.256-187.712 76.256z m-704 398.944h299.2c-29.344 70.4-70.4 134.944-123.2 181.856a477.024 477.024 0 0 1-176-181.856z\" fill=\"#2F81F9\" ></path><path d=\"M768.064 1024A256 256 0 0 1 512 768.096 256 256 0 0 1 767.84 512h0.224A256 256 0 0 1 1024 768a256 256 0 0 1-255.936 256z m0-46.56A209.44 209.44 0 0 0 977.472 768a209.44 209.44 0 1 0-209.408 209.44z\" fill=\"#2F81F9\" ></path><path d=\"M755.616 680.928H713.92v-52.576h46.144c75.04 0.96 134.208 64.384 135.84 138.784-0.48 75.552-60.064 139.456-135.936 140.48h-82.88c-8.48 0.096-13.984-5.248-13.888-13.312v-213.376h50.656l0.064 167.264c0 4.32 2.72 6.88 7.04 6.88h33.856c49.152-0.544 89.472-39.136 89.952-87.936-1.536-47.776-40.64-85.664-89.152-86.208z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconbanbenbiangeng\" viewBox=\"0 0 1024 1024\"><path d=\"M102.400853 188.842667v730.026666h819.2V188.842667H102.400853zM51.200853 84.48h921.6c28.245333 0 51.2 23.381333 51.2 52.138667v834.389333a51.712 51.712 0 0 1-51.2 52.138667H51.200853a51.712 51.712 0 0 1-51.2-52.053334V136.533333c0-28.757333 22.954667-52.053333 51.2-52.053333zM512.000853 397.397333V240.981333l256 260.693334H307.200853V397.397333H512.000853zM256.000853 605.952h460.8v104.362667H512.000853v156.416L256.000853 605.952z\" fill=\"#919AAC\" ></path></symbol><symbol id=\"iconfanhui\" viewBox=\"0 0 1024 1024\"><path d=\"M333.994667 469.333333H853.333333v85.333334H333.994667l228.864 228.864-60.302223 60.302222L170.666667 512l331.889777-331.832889 60.302223 60.302222z\" fill=\"#374053\" ></path></symbol><symbol id=\"iconcipankuorong\" viewBox=\"0 0 1024 1024\"><path d=\"M249.462154 890.171077v-315.076923h525.075692v315.076923h105.078154V303.497846L730.978462 155.017846H144.384V890.092308h105.078154zM91.923692 50.018462h682.614154L984.615385 259.938462v682.692923a52.539077 52.539077 0 0 1-52.539077 52.539077H91.923692A52.539077 52.539077 0 0 1 39.384615 942.710154V102.4C39.384615 73.491692 62.857846 50.018462 91.923692 50.018462z m262.537846 630.153846V890.092308h315.076924V680.172308H354.461538z\" fill=\"#919AAC\" ></path></symbol><symbol id=\"iconlianjie1\" viewBox=\"0 0 1024 1024\"><path d=\"M676.132571 315.465143l-265.508571 265.508571a48.786286 48.786286 0 1 0 68.973714 68.900572l275.894857-275.748572A146.285714 146.285714 0 1 0 548.571429 167.204571L272.749714 443.026286a243.785143 243.785143 0 1 0 344.795429 344.795428l265.508571-265.508571a14.628571 14.628571 0 0 1 20.626286 0l48.274286 48.274286a14.628571 14.628571 0 0 1 0 20.699428l-265.508572 265.508572a341.357714 341.357714 0 1 1-482.742857-482.742858l275.894857-275.748571a243.785143 243.785143 0 0 1 344.795429 344.722286L548.571429 718.921143A146.285714 146.285714 0 1 1 341.650286 512l265.508571-265.508571a14.628571 14.628571 0 0 1 20.699429 0l48.274285 48.274285a14.628571 14.628571 0 0 1 0 20.699429z\" fill=\"#374053\" ></path></symbol><symbol id=\"icondaiyunhang\" viewBox=\"0 0 1024 1024\"><path d=\"M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z\" fill=\"#F4A838\" ></path><path d=\"M512 264.533333V512h166.485333a8.533333 8.533333 0 0 1 8.533334 8.533333v68.266667a8.533333 8.533333 0 0 1-8.533334 8.533333H435.2a8.533333 8.533333 0 0 1-8.533333-8.533333V264.533333a8.533333 8.533333 0 0 1 8.533333-8.533333h68.266667a8.533333 8.533333 0 0 1 8.533333 8.533333z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconrilijiange\" viewBox=\"0 0 2048 1024\"><path d=\"M1986.901333 736.597333L1549.653333 181.930667a85.333333 85.333333 0 0 0-67.072-32.597334H1309.866667a21.504 21.504 0 0 0-16.725334 34.645334l384.682667 488.106666H64a21.333333 21.333333 0 0 0-21.333333 21.162667V853.333333c0 11.776 9.557333 21.333333 21.333333 21.333334h1855.658667a85.333333 85.333333 0 0 0 67.242666-138.24z\" fill=\"#5B6675\" ></path></symbol><symbol id=\"iconzanting\" viewBox=\"0 0 1024 1024\"><path d=\"M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z\" fill=\"#FAAD14\" ></path><path d=\"M256 469.333333h512v85.333334H256z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconjiediankuorong\" viewBox=\"0 0 1024 1024\"><path d=\"M51.200853 70.570667h921.6c28.245333 0 51.2 23.381333 51.2 52.138666v834.389334a51.712 51.712 0 0 1-51.2 52.053333H51.200853a51.712 51.712 0 0 1-51.2-52.053333V122.709333C0.000853 93.952 22.95552 70.570667 51.200853 70.570667z m51.2 104.277333v730.112h819.2V174.848H102.400853zM597.334187 460.373333h170.666666v170.666667H597.334187v207.189333H426.66752V631.04H256.000853v-170.666667h170.666667V245.76h170.666667v214.528z\" fill=\"#919AAC\" ></path></symbol><symbol id=\"iconwancheng\" viewBox=\"0 0 1024 1024\"><path d=\"M512 1024A512 512 0 1 1 512 0a512 512 0 0 1 0 1024z m-40.106667-318.037333l340.224-340.309334a15.36 15.36 0 0 0 0-21.76l-50.688-50.688a15.36 15.36 0 0 0-17.749333-2.816l-4.010667 2.816-278.698666 278.784-133.973334-133.973333a15.36 15.36 0 0 0-21.76 0l-50.688 50.688a15.36 15.36 0 0 0 0 21.674667l195.584 195.584a15.36 15.36 0 0 0 17.664 2.816l4.010667-2.816z\" fill=\"#52C41A\" ></path></symbol><symbol id=\"iconrili\" viewBox=\"0 0 1024 1024\"><path d=\"M755.785143 146.285714H950.857143c26.916571 0 48.786286 21.796571 48.786286 48.786286v780.141714A48.786286 48.786286 0 0 1 950.857143 1024H73.142857a48.786286 48.786286 0 0 1-48.786286-48.786286V195.072C24.356571 168.082286 46.226286 146.285714 73.142857 146.285714h195.072V63.414857c0-8.045714 6.582857-14.628571 14.628572-14.628571H351.085714c8.045714 0 14.628571 6.582857 14.628572 14.628571V146.285714h292.571428V63.414857c0-8.045714 6.582857-14.628571 14.628572-14.628571h68.242285c8.045714 0 14.628571 6.582857 14.628572 14.628571V146.285714z m146.285714 97.499429h-146.285714v82.944a14.628571 14.628571 0 0 1-14.628572 14.628571H672.914286a14.628571 14.628571 0 0 1-14.628572-14.628571V243.785143H365.714286v82.944a14.628571 14.628571 0 0 1-14.628572 14.628571h-68.242285a14.628571 14.628571 0 0 1-14.628572-14.628571V243.785143h-146.285714V438.857143h780.141714V243.785143z m-780.141714 292.571428v390.144h780.141714V536.356571H121.929143zM234.057143 633.929143h214.528c8.045714 0 14.628571 6.582857 14.628571 14.628571v165.741715a14.628571 14.628571 0 0 1-14.628571 14.628571H234.057143a14.628571 14.628571 0 0 1-14.628572-14.628571V648.557714c0-8.045714 6.582857-14.628571 14.628572-14.628571z\" fill=\"#919AAC\" ></path></symbol><symbol id=\"iconxiaxian\" viewBox=\"0 0 1024 1024\"><path d=\"M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z\" fill=\"#A9AFBC\" ></path><path d=\"M355.157333 306.858667a8.533333 8.533333 0 0 1 11.946667 0L512 451.669333l144.810667-144.810666a8.533333 8.533333 0 0 1 12.032 0l48.298666 48.298666a8.533333 8.533333 0 0 1 0 11.946667L572.330667 512l144.810666 144.810667a8.533333 8.533333 0 0 1 0 12.032l-48.298666 48.298666a8.533333 8.533333 0 0 1-11.946667 0L512 572.330667 367.189333 717.141333a8.533333 8.533333 0 0 1-12.032 0l-48.298666-48.298666a8.533333 8.533333 0 0 1 0-11.946667L451.669333 512 306.858667 367.189333a8.533333 8.533333 0 0 1 0-12.032l48.298666-48.298666z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconshuaxin1\" viewBox=\"0 0 1024 1024\"><path d=\"M68.534857 512.731429a456.704 456.704 0 0 0 457.069714 456.411428c146.285714 0 276.553143-68.754286 360.228572-175.762286l54.857143 42.861715a9.142857 9.142857 0 0 0 14.774857-7.241143l-0.950857-190.829714a9.069714 9.069714 0 0 0-11.337143-8.777143l-185.490286 45.129143a9.142857 9.142857 0 0 0-3.364571 16.091428l59.538285 46.518857c-9.142857 11.702857-19.090286 22.893714-29.769142 33.499429A364.178286 364.178286 0 0 1 525.604571 877.714286a364.178286 364.178286 0 0 1-258.486857-107.081143A364.178286 364.178286 0 0 1 159.963429 512a364.178286 364.178286 0 0 1 107.081142-258.486857 364.178286 364.178286 0 0 1 258.56-107.081143 364.178286 364.178286 0 0 1 282.770286 133.851429c3.145143 3.803429 8.777143 4.388571 12.653714 1.316571l57.782858-45.056a9.289143 9.289143 0 0 0 1.462857-13.019429A457.069714 457.069714 0 0 0 68.534857 512.731429z\" fill=\"#919AAC\" ></path></symbol><symbol id=\"iconxinzeng\" viewBox=\"0 0 1194 1024\"><path d=\"M142.250667 910.250667h910.165333V512h113.834667v455.082667A56.917333 56.917333 0 0 1 1109.333333 1024H85.333333a56.917333 56.917333 0 0 1-56.917333-56.917333V512h113.834667v398.250667z m512-568.917334v398.250667H540.416V341.333333H256l341.333333-341.333333 341.333334 341.333333H654.250667z\" fill=\"#374053\" ></path></symbol><symbol id=\"iconControllerguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M669.538462 102.4H144.384v819.2h735.232V307.2H669.538462V102.4zM39.384615 50.806154C39.384615 22.764308 62.857846 0 91.844923 0h630.153846L984.615385 256v716.406154a50.569846 50.569846 0 0 1-15.123693 36.312615 53.169231 53.169231 0 0 1-37.021538 15.281231H91.529846A51.908923 51.908923 0 0 1 39.384615 973.193846V50.806154zM564.539077 512v204.8H459.460923V512h-157.538461L512 307.2l210.077538 204.8h-157.538461z\" fill=\"#919AAC\" ></path></symbol><symbol id=\"icona-LeaderRebalance\" viewBox=\"0 0 1024 1024\"><path d=\"M609.499429 357.449143v-237.714286h-438.857143v760.685714h295.350857c16.164571 20.041143 35.620571 37.522286 57.490286 51.565715l67.803428 43.52H121.563429A47.835429 47.835429 0 0 1 73.142857 928.329143V71.826286C73.142857 46.153143 95.085714 24.576 122.002286 24.576h536.137143L950.857143 309.906286v47.542857H609.499429zM512 452.534857h438.857143v282.770286c0 47.104-24.429714 91.136-65.097143 117.248L731.428571 951.588571l-154.331428-99.035428A139.556571 139.556571 0 0 1 512 735.378286V452.534857z m97.499429 282.770286c0 15.067429 7.899429 29.257143 21.284571 37.814857L731.428571 837.778286l100.644572-64.658286a45.129143 45.129143 0 0 0 21.211428-37.814857V547.620571H609.572571v187.684572z\" fill=\"#919AAC\" ></path></symbol><symbol id=\"iconyunhang\" viewBox=\"0 0 1024 1024\"><path d=\"M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z\" fill=\"#1473FF\" ></path><path d=\"M810.666667 512a300.885333 300.885333 0 0 0-161.28-265.386667 298.154667 298.154667 0 0 0-137.045334-33.28c-106.666667 0-210.432 56.32-264.362666 154.709334l-5.888 10.752 260.522666 0.085333-0.768-76.202667c38.656-2.048 77.141333 5.802667 109.909334 22.784a208.042667 208.042667 0 0 1 113.749333 186.453334H810.666667zM213.333333 512a300.885333 300.885333 0 0 0 161.28 265.386667c42.325333 21.845333 89.344 33.28 137.045334 33.28 106.666667 0 210.432-56.32 264.362666-154.709334l5.888-10.752L521.386667 645.12l0.768 76.202667a215.637333 215.637333 0 0 1-109.909334-22.784A208.042667 208.042667 0 0 1 298.496 512H213.333333z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconregionpeizhi\" viewBox=\"0 0 1024 1024\"><path d=\"M345.965714 550.619429a162.816 162.816 0 0 1 0-77.165715L297.618286 446.171429l48.713143-82.285715 48.420571 27.209143c19.382857-17.92 42.861714-31.158857 68.461714-38.619428v-54.418286h97.572572v54.418286c25.892571 7.533714 49.298286 20.918857 68.461714 38.619428l48.420571-27.209143L726.308571 446.171429l-48.347428 27.282285c6.144 25.307429 6.144 51.785143 0 77.092572l48.347428 27.282285-48.713142 82.285715-48.420572-27.209143a171.52 171.52 0 0 1-68.461714 38.619428v54.418286H463.213714v-54.418286a171.52 171.52 0 0 1-68.461714-38.619428l-48.420571 27.209143L297.691429 577.828571l48.347428-27.209142zM512 583.314286c40.374857 0 73.142857-31.963429 73.142857-71.314286a72.265143 72.265143 0 0 0-73.142857-71.314286c-40.374857 0-73.142857 31.963429-73.142857 71.314286s32.768 71.314286 73.142857 71.314286zM658.285714 131.657143H170.642286v760.685714h682.715428V321.828571H658.285714V131.657143z m-585.142857-47.908572C73.142857 57.709714 94.939429 36.571429 121.856 36.571429h585.142857L950.857143 274.285714v665.234286a46.957714 46.957714 0 0 1-14.043429 33.718857 49.371429 49.371429 0 0 1-34.377143 14.189714H121.563429A48.201143 48.201143 0 0 1 73.142857 940.251429V83.748571z\" fill=\"#919AAC\" ></path></symbol><symbol id=\"icona-Info-Circlebeifen8\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 86.893714a425.179429 425.179429 0 0 0 0 850.212572A425.179429 425.179429 0 0 0 512 86.893714zM539.428571 438.857143c5.046857 0 9.142857 4.096 9.142858 9.142857v310.857143a9.142857 9.142857 0 0 1-9.142858 9.142857h-54.857142a9.142857 9.142857 0 0 1-9.142858-9.142857v-310.857143c0-5.046857 4.096-9.142857 9.142858-9.142857zM512 256A54.857143 54.857143 0 1 1 512 365.714286a54.857143 54.857143 0 0 1 0-109.714286z\" fill=\"#000000\" fill-opacity=\".65\" ></path></symbol><symbol id=\"iconbaozhang\" viewBox=\"0 0 1024 1024\"><path d=\"M941.952 131.2L586.88 22.848a256 256 0 0 0-149.504 0L82.304 131.2C72.256 134.4 64 145.024 64 154.88v408a256 256 0 0 0 103.488 205.632l306.368 227.264a64 64 0 0 0 76.288 0l306.368-227.264A256 256 0 0 0 960 562.816V154.88c0.256-9.792-8-20.352-18.048-23.616zM512 589.952l-150.464 79.104 28.736-167.552-121.728-118.656L436.736 358.4 512 205.952 587.264 358.4l168.192 24.448-121.728 118.656 28.8 167.552L512 589.952z\" fill=\"#EF645C\" ></path></symbol><symbol id=\"iconerjigaojing\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 312.905143A199.094857 199.094857 0 0 0 312.905143 512v256H256a28.452571 28.452571 0 0 0 0 56.905143h512a28.452571 28.452571 0 0 0 0-56.905143h-56.905143V512A199.094857 199.094857 0 0 0 512 312.905143z m3.803429 145.115428a22.747429 22.747429 0 0 1 31.012571-8.411428 22.893714 22.893714 0 0 1 9.874286 28.013714l-1.389715 2.998857-37.522285 65.536h41.325714a25.6 25.6 0 0 1 24.137143 17.408l1.170286 4.681143 0.292571 3.510857c0 2.925714-0.512 5.851429-1.828571 9.362286l-1.536 3.291429-54.491429 95.305142a22.747429 22.747429 0 0 1-31.012571 8.484572 22.893714 22.893714 0 0 1-9.874286-28.013714l1.389714-2.998858 37.302857-65.536h-41.106285a24.356571 24.356571 0 0 1-6.070858-0.731428l-3.291428-1.097143-3.291429-1.536a25.746286 25.746286 0 0 1-11.044571-31.817143l1.462857-3.145143z m337.554285 25.6h-56.905143a28.452571 28.452571 0 0 0 0 56.832h56.905143a28.452571 28.452571 0 0 0 0-56.905142z m-625.810285 0h-56.905143a28.452571 28.452571 0 0 0 0 56.832h56.905143a28.452571 28.452571 0 0 0 0-56.905142z m545.938285-233.106285a28.452571 28.452571 0 0 0-40.228571 0l-40.228572 40.228571a28.452571 28.452571 0 1 0 40.228572 40.228572l40.228571-40.228572a28.452571 28.452571 0 0 0 0-40.228571z m-487.131428-3.657143a28.452571 28.452571 0 0 0-35.84 43.885714l40.228571 40.228572 4.461714 3.657142a28.452571 28.452571 0 0 0 35.84-43.885714l-40.228571-40.228571zM512 142.262857a28.452571 28.452571 0 0 0-28.452571 28.379429v56.905143a28.452571 28.452571 0 0 0 56.905142 0v-56.905143A28.452571 28.452571 0 0 0 512 142.189714z\" fill=\"#FFC800\" ></path></symbol><symbol id=\"iconyijigaojing\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 312.905143A199.094857 199.094857 0 0 0 312.905143 512v256H256a28.452571 28.452571 0 0 0 0 56.905143h512a28.452571 28.452571 0 0 0 0-56.905143h-56.905143V512A199.094857 199.094857 0 0 0 512 312.905143z m3.803429 145.115428a22.747429 22.747429 0 0 1 31.012571-8.411428 22.893714 22.893714 0 0 1 9.874286 28.013714l-1.389715 2.998857-37.522285 65.536h41.325714a25.6 25.6 0 0 1 24.137143 17.408l1.170286 4.681143 0.292571 3.510857c0 2.925714-0.512 5.851429-1.828571 9.362286l-1.536 3.291429-54.491429 95.305142a22.747429 22.747429 0 0 1-31.012571 8.484572 22.893714 22.893714 0 0 1-9.874286-28.013714l1.389714-2.998858 37.302857-65.536h-41.106285a24.356571 24.356571 0 0 1-6.070858-0.731428l-3.291428-1.097143-3.291429-1.536a25.746286 25.746286 0 0 1-11.044571-31.817143l1.462857-3.145143z m337.554285 25.6h-56.905143a28.452571 28.452571 0 0 0 0 56.832h56.905143a28.452571 28.452571 0 0 0 0-56.905142z m-625.810285 0h-56.905143a28.452571 28.452571 0 0 0 0 56.832h56.905143a28.452571 28.452571 0 0 0 0-56.905142z m545.938285-233.106285a28.452571 28.452571 0 0 0-40.228571 0l-40.228572 40.228571a28.452571 28.452571 0 1 0 40.228572 40.228572l40.228571-40.228572a28.452571 28.452571 0 0 0 0-40.228571z m-487.131428-3.657143a28.452571 28.452571 0 0 0-35.84 43.885714l40.228571 40.228572 4.461714 3.657142a28.452571 28.452571 0 0 0 35.84-43.885714l-40.228571-40.228571zM512 142.262857a28.452571 28.452571 0 0 0-28.452571 28.379429v56.905143a28.452571 28.452571 0 0 0 56.905142 0v-56.905143A28.452571 28.452571 0 0 0 512 142.189714z\" fill=\"#FF5656\" ></path></symbol><symbol id=\"iconbiaogejieshi\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 0 0 1024A512 512 0 0 0 512 0z\" fill=\"#515A6F\" ></path><path d=\"M512 819.2a51.2 51.2 0 1 1 0-102.4 51.2 51.2 0 0 1 0 102.4zM563.2 665.6H460.8V204.8h102.4z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconbuzhouwancheng\" viewBox=\"0 0 1536 1024\"><path d=\"M1417.045333 0L1536 119.466667 635.136 1024 0 386.218667l118.954667-119.466667 516.181333 518.229333z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"icondankuangshanchu\" viewBox=\"0 0 1024 1024\"><path d=\"M928.256 0L1024 95.744 607.6416 511.8976 1024 928.256 928.256 1024 512 607.6416 95.744 1024 0 928.256 416.256 512 0 95.744 95.744 0 512 416.256 928.256 0z\" fill=\"#8C8C8C\" ></path></symbol><symbol id=\"iconbiaogepaixu\" viewBox=\"0 0 1024 1024\"><path d=\"M846.326305 614.397542c20.069818 0 31.231094 20.069818 18.841053 33.791021L530.841054 1016.101093a26.418434 26.418434 0 0 1-37.682108 0L158.832642 648.188563C146.442601 634.46736 157.603877 614.397542 177.673695 614.397542zM530.841054 7.899931L865.167358 375.812461c12.390041 13.721202 1.228764 33.79102-18.841053 33.79102H177.673695C157.603877 409.603481 146.442601 389.533664 158.730245 375.812461L493.158946 7.899931a26.418434 26.418434 0 0 1 37.682108 0z\" fill=\"#A8ADBD\" ></path></symbol><symbol id=\"icondingbudaohangzhankai\" viewBox=\"0 0 2048 1024\"><path d=\"M1979.59424 1024H68.81024c-57.344 0-89.344-50.176-53.76-84.48L970.44224 19.712a83.2 83.2 0 0 1 107.52 0L2033.35424 939.52c35.584 34.304 3.584 84.48-53.76 84.48z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconduoxuanyixuanzhuangtai\" viewBox=\"0 0 1024 1024\"><path d=\"M55.768615 39.384615m157.538462 0l630.153846 0q157.538462 0 157.538462 157.538462l0 630.153846q0 157.538462-157.538462 157.538462l-630.153846 0q-157.538462 0-157.538462-157.538462l0-630.153846q0-157.538462 157.538462-157.538462Z\" fill=\"#2F81F9\" ></path><path d=\"M758.705231 275.692308L843.460923 359.424 430.08 748.307692 213.307077 548.785231l83.810461-84.598154L429.134769 585.806769z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconduoxuanbukexuanzhuangtai\" viewBox=\"0 0 1024 1024\"><path d=\"M95.153231 78.769231m157.538461 0l551.384616 0q157.538462 0 157.538461 157.538461l0 551.384616q0 157.538462-157.538461 157.538461l-551.384616 0q-157.538462 0-157.538461-157.538461l0-551.384616q0-157.538462 157.538461-157.538461Z\" fill=\"#D7DAE5\" fill-opacity=\".12\" ></path></symbol><symbol id=\"iconduoxuanweixuanzhuangtai\" viewBox=\"0 0 1024 1024\"><path d=\"M42.666667 42.666667m85.333333 0l768 0q85.333333 0 85.333333 85.333333l0 768q0 85.333333-85.333333 85.333333l-768 0q-85.333333 0-85.333333-85.333333l0-768q0-85.333333 85.333333-85.333333Z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"icongengduocaozuoshouqi\" viewBox=\"0 0 1462 1024\"><path d=\"M1310.016366 100.205714a95.817143 95.817143 0 0 1 121.709714-9.801143c32.621714 23.405714 40.228571 63.341714 20.041143 94.354286l-8.777143 11.117714L731.456366 950.857143 18.167223 193.828571C-11.08992 160.914286-4.360777 114.102857 33.527223 88.795429a96.841143 96.841143 0 0 1 110.592 3.510857l10.678857 9.801143 581.339429 609.426285L1310.016366 100.059429z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"icongaojingICON\" viewBox=\"0 0 1024 1024\"><path d=\"M512 512m-495.483871 0a495.483871 495.483871 0 1 0 990.967742 0 495.483871 495.483871 0 1 0-990.967742 0Z\" fill=\"#F4A838\" ></path><path d=\"M543.149419 661.20671l21.239742-432.326194h-114.688l21.239742 432.326194h72.208516z m-36.533677 174.146064c18.696258 0 33.990194-5.945806 47.566452-17.837419 11.891613-11.891613 18.696258-28.044387 18.696258-46.740645a62.76129 62.76129 0 0 0-18.696258-45.848775c-12.750452-11.891613-28.870194-17.837419-47.566452-17.837419s-33.957161 5.945806-45.848774 17.837419c-13.60929 11.891613-19.555097 27.185548-19.555097 45.848775 0 18.696258 5.945806 33.990194 19.555097 45.881806a62.76129 62.76129 0 0 0 45.848774 18.696258z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"icondingbudaohangshouqi\" viewBox=\"0 0 2048 1024\"><path d=\"M1979.392 0H68.608C11.264 0-20.48 50.176 14.848 84.48L970.24 1004.288a83.2 83.2 0 0 0 107.52 0L2033.152 84.48C2068.48 50.176 2036.736 0 1979.392 0z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconguan\" viewBox=\"0 0 1649 1024\"><path d=\"M455.111111 56.888889h739.555556a455.111111 455.111111 0 1 1 0 910.222222H455.111111A455.111111 455.111111 0 1 1 455.111111 56.888889z\" fill=\"#D7DAE5\" ></path></symbol><symbol id=\"iconlianjie\" viewBox=\"0 0 1024 1024\"><path d=\"M868.205714 188.269714c64.512 66.413714 62.610286 172.763429-2.925714 238.226286l-343.917714 343.844571h-0.073143l-54.125714 54.125715a223.012571 223.012571 0 0 1-314.514286 0l-4.242286-4.242286a223.012571 223.012571 0 0 1 0-314.441143L483.035429 171.154286a26.038857 26.038857 0 0 1 36.864 36.864L185.197714 542.646857a168.228571 168.228571 0 0 0-37.156571 56.100572 171.52 171.52 0 0 0 37.156571 184.685714l4.242286 4.242286a168.228571 168.228571 0 0 0 56.100571 37.229714 171.52 171.52 0 0 0 184.685715-37.229714l353.133714-353.060572 46.153143-46.08c21.942857-21.942857 34.157714-51.346286 34.157714-82.724571a116.150857 116.150857 0 0 0-116.882286-116.809143c-31.451429 0-60.708571 12.068571-82.724571 34.084571L277.577143 609.499429a58.148571 58.148571 0 0 0-16.969143 41.398857 58.148571 58.148571 0 0 0 58.441143 58.514285 58.148571 58.148571 0 0 0 41.398857-17.042285l321.828571-321.828572a26.038857 26.038857 0 0 1 36.864 36.790857L398.262857 728.502857a111.542857 111.542857 0 0 1-156.598857 1.609143 110.957714 110.957714 0 0 1-0.731429-157.257143l386.413715-386.413714a168.594286 168.594286 0 0 1 119.515428-49.298286 168.155429 168.155429 0 0 1 121.417143 51.2z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconkai\" viewBox=\"0 0 1706 1024\"><path d=\"\"  ></path></symbol><symbol id=\"icongengduocaozuosuoqi\" viewBox=\"0 0 1462 1024\"><path d=\"M1309.988571 923.794286c30.427429 31.890286 84.845714 36.132571 121.709715 9.801143 32.621714-23.405714 40.228571-63.341714 20.041143-94.354286l-8.777143-11.117714L731.428571 73.142857 18.139429 830.171429c-29.257143 32.768-22.381714 79.725714 15.36 105.033142 33.645714 22.528 80.164571 20.187429 110.592-3.510857l10.678857-9.801143 581.339428-609.426285 573.878857 611.474285z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconmianbaoxieguanbi\" viewBox=\"0 0 1024 1024\"><path d=\"M730.823196 294.729286l-1.599835-1.599835a34.236469 34.236469 0 0 0-48.379011 0L511.325831 462.83995l-169.582511-169.582512a34.172476 34.172476 0 1 0-48.443005 48.443004l169.582512 169.582512-169.646505 169.582512a34.172476 34.172476 0 0 0 0 48.379011l1.599835 1.599835c13.310627 13.374621 35.00439 13.374621 48.443004 0l169.582512-169.582512 169.582512 169.582512a34.236469 34.236469 0 1 0 48.379011-48.506998l-169.582512-169.582512 169.582512-169.582512a34.236469 34.236469 0 0 0 0-48.443004\" fill=\"#505568\" ></path><path d=\"M873.91244 149.976214a511.819219 511.819219 0 0 0-723.957342 0 511.947205 511.947205 0 0 0 0 724.021335 511.755225 511.755225 0 0 0 723.957342 0 511.755225 511.755225 0 0 0 0-724.021335M198.206122 825.746525a443.53826 443.53826 0 0 1 0-627.455294 443.53826 443.53826 0 0 1 627.455294 0 443.602254 443.602254 0 0 1 0 627.3913 443.602254 443.602254 0 0 1-627.455294 0z\" fill=\"#505568\" ></path></symbol><symbol id=\"iconmorenkaibukedian\" viewBox=\"0 0 1706 1024\"><path d=\"\"  ></path></symbol><symbol id=\"iconmianbaoxieshanchu\" viewBox=\"0 0 1024 1024\"><path d=\"M1001.654601 26.021424L998.198731 22.437559a76.54113 76.54113 0 0 0-108.283939 0L510.409023 402.071322 131.03125 22.693549a76.54113 76.54113 0 0 0-108.28394 0 76.285139 76.285139 0 0 0 0 108.283939l379.505769 379.505769L22.49132 889.86103a76.413135 76.413135 0 0 0 0 108.28394l3.711861 3.45587a76.669125 76.669125 0 0 0 108.283939 0L513.864894 622.095071l379.377773 379.377774a76.54113 76.54113 0 1 0 108.411934-108.411935L622.148833 513.811132 1001.654601 134.433359a76.669125 76.669125 0 0 0 0-108.411935\" fill=\"#505568\" ></path></symbol><symbol id=\"iconmorenguanbukedian\" viewBox=\"0 0 1649 1024\"><path d=\"M455.111111 56.888889h739.555556a455.111111 455.111111 0 1 1 0 910.222222H455.111111A455.111111 455.111111 0 1 1 455.111111 56.888889z\" fill=\"#D7DAE5\" ></path></symbol><symbol id=\"iconshangchuanzhong\" viewBox=\"0 0 1024 1024\"><path d=\"M512 28.672a485.632 485.632 0 0 1 485.376 485.290667h-69.376A416.085333 416.085333 0 0 0 512 97.962667V28.672z m0 901.290667a416.085333 416.085333 0 0 1-416-416H26.624A485.632 485.632 0 0 0 512 999.338667v-69.376z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconriqi\" viewBox=\"0 0 1024 1024\"><path d=\"M360.533333 26.709333c9.386667 0 17.066667 7.594667 17.066667 17.066667v55.466667l-0.256 2.048 343.893333 0.085333a17.237333 17.237333 0 0 1-0.170666-2.133333v-55.466667c0-9.472 7.68-17.066667 17.066666-17.066667h55.466667c9.386667 0 17.066667 7.594667 17.066667 17.066667v55.466667l-0.341334 2.048h172.032c8.277333 0 14.933333 6.741333 14.933334 14.933333v866.133333a14.933333 14.933333 0 0 1-14.933334 14.933334H41.728a14.933333 14.933333 0 0 1-14.933333-14.933334V116.224c0-8.192 6.656-14.933333 14.933333-14.933333l246.528 0.085333a17.237333 17.237333 0 0 1-0.170667-2.133333v-55.466667c0-9.472 7.68-17.066667 17.066667-17.066667h55.466667z m547.157334 164.181334H116.394667L116.053333 347.648l490.837334 0.085333c9.386667 0 17.066667 7.68 17.066666 17.066667v55.466667a17.066667 17.066667 0 0 1-17.066666 17.066666H116.053333l0.085334 470.357334h791.466666v-716.8z m-76.8 448c9.472 0 17.066667 7.68 17.066666 17.066666v174.933334a17.066667 17.066667 0 0 1-17.066666 17.066666h-174.933334a17.066667 17.066667 0 0 1-17.066666-17.066666v-174.933334c0-9.386667 7.68-17.066667 17.066666-17.066666h174.933334z\" fill=\"#505568\" ></path></symbol><symbol id=\"icontubiao-info\" viewBox=\"0 0 1024 1024\"><path d=\"M512 64a448 448 0 1 1 0 896A448 448 0 0 1 512 64z m-8.533333 645.461333a44.629333 44.629333 0 0 0-33.792 13.653334 43.264 43.264 0 0 0-13.312 33.536 46.165333 46.165333 0 0 0 47.104 47.957333 47.786667 47.786667 0 0 0 33.792-13.653333 44.373333 44.373333 0 0 0 14.165333-34.304 46.165333 46.165333 0 0 0-47.957333-47.189334zM519.082667 204.8c-60.245333 0-107.093333 18.432-140.544 55.296-31.317333 32.853333-47.274667 75.946667-49.152 129.28 0 6.485333 4.778667 11.349333 10.752 11.349333h51.882666l3.754667-0.853333a9.813333 9.813333 0 0 0 5.973333-8.789333l0.170667-4.266667c1.706667-31.488 9.557333-56.405333 23.381333-75.434667 17.237333-25.6 45.738667-41.216 81.664-41.216 30.208 0 65.536 6.656 87.04 32.682667 15.786667 17.066667 24.405333 35.669333 24.405334 66.730667 0 21.76-9.984 41.813333-24.405334 61.184-11.264 13.568-43.093333 37.973333-54.613333 50.432l-9.813333 9.642666c-24.490667 24.405333-34.986667 38.656-42.752 54.272l-5.632 12.117334c-8.618667 19.370667-16.554667 41.216-16.554667 66.901333v21.333333c0 5.888 4.778667 10.581333 10.666667 10.581334h55.637333l3.498667-0.682667a9.130667 9.130667 0 0 0 5.632-8.448v-10.069333l0.597333-13.312c1.621333-17.322667 6.570667-33.109333 15.274667-47.786667a172.373333 172.373333 0 0 1 39.253333-46.08l11.776-10.496c22.442667-20.138667 38.570667-35.413333 48.384-45.568l7.68-8.448c20.906667-27.562667 31.829333-60.245333 31.829333-97.962667 0-50.176-15.872-89.6-46.933333-118.016-32.597333-30.122667-75.264-44.373333-128.853333-44.373333z\" fill=\"#2A8FFF\" ></path></symbol><symbol id=\"iconshuaxin\" viewBox=\"0 0 1170 1024\"><path d=\"M1100.2125 402.284852V146.285401l-84.114106 83.528964A516.53375 516.53375 0 0 0 585.87303 0C301.055355 0 70.070707 229.229223 70.070707 511.998903s230.984648 511.998903 515.875466 511.998903a515.875466 515.875466 0 0 0 478.06069-319.414173 43.593049 43.593049 0 0 0-6.070844-43.446764 44.397619 44.397619 0 0 0-75.848981 10.459406A427.592227 427.592227 0 0 1 585.946173 936.226565c-236.104637 0-427.445941-189.951593-427.445941-424.227662s191.341304-424.227662 427.445941-424.227663a427.884797 427.884797 0 0 1 366.152358 205.530989L842.311338 402.284852h257.901162z\" fill=\"#505568\" ></path></symbol><symbol id=\"iconriqixuanfu\" viewBox=\"0 0 1024 1024\"><path d=\"M372.184615 64.039385c8.664615 0 15.753846 7.010462 15.753847 15.753846v51.2l-0.236308 1.890461 317.44 0.07877a15.911385 15.911385 0 0 1-0.157539-1.969231v-51.2c0-8.743385 7.089231-15.753846 15.753847-15.753846h51.2c8.664615 0 15.753846 7.010462 15.753846 15.753846v51.2l-0.315077 1.890461h158.798769c7.640615 0 13.784615 6.222769 13.784615 13.784616v799.507692a13.784615 13.784615 0 0 1-13.784615 13.784615H77.902769a13.784615 13.784615 0 0 1-13.784615-13.784615V146.668308c0-7.561846 6.144-13.784615 13.784615-13.784616l227.564308 0.07877a15.911385 15.911385 0 0 1-0.157539-1.969231v-51.2c0-8.743385 7.089231-15.753846 15.753847-15.753846h51.2z m505.068308 151.552H146.825846L146.510769 360.290462l453.080616 0.078769c8.664615 0 15.753846 7.089231 15.753846 15.753846v51.2a15.753846 15.753846 0 0 1-15.753846 15.753846H146.510769l0.078769 434.176h730.584616v-661.661538z m-70.892308 413.538461c8.743385 0 15.753846 7.089231 15.753847 15.753846v161.476923a15.753846 15.753846 0 0 1-15.753847 15.753847h-161.476923a15.753846 15.753846 0 0 1-15.753846-15.753847v-161.476923c0-8.664615 7.089231-15.753846 15.753846-15.753846h161.476923z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconshangchuanshibailianjie\" viewBox=\"0 0 1024 1024\"><path d=\"M868.205714 188.269714c64.512 66.413714 62.610286 172.763429-2.925714 238.226286l-343.917714 343.844571h-0.073143l-54.125714 54.125715a223.012571 223.012571 0 0 1-314.514286 0l-4.242286-4.242286a223.012571 223.012571 0 0 1 0-314.441143L483.035429 171.154286a26.038857 26.038857 0 0 1 36.864 36.864L185.197714 542.646857a168.228571 168.228571 0 0 0-37.156571 56.100572 171.52 171.52 0 0 0 37.156571 184.685714l4.242286 4.242286a168.228571 168.228571 0 0 0 56.100571 37.229714 171.52 171.52 0 0 0 184.685715-37.229714l353.133714-353.060572 46.153143-46.08c21.942857-21.942857 34.157714-51.346286 34.157714-82.724571a116.150857 116.150857 0 0 0-116.882286-116.809143c-31.451429 0-60.708571 12.068571-82.724571 34.084571L277.577143 609.499429a58.148571 58.148571 0 0 0-16.969143 41.398857 58.148571 58.148571 0 0 0 58.441143 58.514285 58.148571 58.148571 0 0 0 41.398857-17.042285l321.828571-321.828572a26.038857 26.038857 0 0 1 36.864 36.790857L398.262857 728.502857a111.542857 111.542857 0 0 1-156.598857 1.609143 110.957714 110.957714 0 0 1-0.731429-157.257143l386.413715-386.413714a168.594286 168.594286 0 0 1 119.515428-49.298286 168.155429 168.155429 0 0 1 121.417143 51.2z\" fill=\"#EF645C\" ></path></symbol><symbol id=\"icontubiao-sousuo\" viewBox=\"0 0 1024 1024\"><path d=\"M802.730667 739.498667l190.122666 190.037333a14.933333 14.933333 0 0 1 0 21.162667l-42.24 42.154666a14.933333 14.933333 0 0 1-21.162666 0L739.413333 802.816a14.933333 14.933333 0 0 1 0-21.077333l42.24-42.24a14.933333 14.933333 0 0 1 21.077334 0z m-75.008-592.469334a410.709333 410.709333 0 1 1-580.778667 580.778667 410.709333 410.709333 0 0 1 580.778667-580.778667z m-517.376 63.317334a321.024 321.024 0 1 0 453.973333 454.058666 321.024 321.024 0 0 0-453.973333-453.973333z\" fill=\"#A8ADBD\" ></path></symbol><symbol id=\"iconwenjianshangchuan\" viewBox=\"0 0 1088 1024\"><path d=\"M976 928h-832v-320h64v256h704v-256h64v320z m-416.192-832l271.488 271.552-45.248 45.248L592 218.688V736h-64V218.304L333.504 412.8l-45.248-45.248L559.808 96z\" fill=\"#505568\" ></path></symbol><symbol id=\"iconxuanfuwenjianshangchuan\" viewBox=\"0 0 1088 1024\"><path d=\"M944 928h-832v-320h64v256h704v-256h64v320z m-416.192-832l271.488 271.552-45.248 45.248L560 218.688V736h-64V218.304L301.504 412.8l-45.248-45.248L527.808 96z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconwenjianshanchu\" viewBox=\"0 0 1024 1024\"><path d=\"M721.92 103.594667v138.581333l208.042667 0.085333v69.376H826.88v623.957334H203.093333V311.552H97.962667V242.346667h207.957333V103.509333H721.92z m35.754667 208.042666H272.213333v554.666667H757.76v-554.666667z m-69.376 69.290667V797.013333h-69.290667V380.928h69.290667z m-277.333334 0V797.013333h-69.290666V380.928h69.290666z m138.666667 0V797.013333H480.426667V380.928h69.290666z m102.997333-207.957333h-277.333333v69.290666h277.333333v-69.290666z\" fill=\"#A8ADBD\" opacity=\".8\" ></path></symbol><symbol id=\"iconzuocedaohanglanshouqi\" viewBox=\"0 0 1024 1024\"><path d=\"M512 256l512 465.408-51.2 46.592L512 348.9792 51.2 768 0 721.408l460.8-418.816L512 256z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconxuanzekuangshouqi\" viewBox=\"0 0 2048 1024\"><path d=\"M1050.4192 103.2192L1856.512 909.312a37.2736 37.2736 0 0 1-26.4192 63.488H217.9072a37.2736 37.2736 0 0 1-26.4192-63.488L997.5808 103.2192a37.2736 37.2736 0 0 1 52.8384 0z\" fill=\"#505568\" ></path></symbol><symbol id=\"iconxuanzekuangzhankai\" viewBox=\"0 0 2048 1024\"><path d=\"M1050.4192 920.7808L1856.512 114.688a37.2736 37.2736 0 0 0-26.4192-63.488H217.9072a37.2736 37.2736 0 0 0-26.4192 63.488l806.0928 806.0928a37.2736 37.2736 0 0 0 52.8384 0z\" fill=\"#ffffff\" ></path></symbol><symbol id=\"iconzuocedaohangshouqi\" viewBox=\"0 0 1024 1024\"><path d=\"M602.88 150.254933L392.533333 0v1024l210.346667-150.254933A68.266667 68.266667 0 0 0 631.466667 818.210133V205.789867a68.266667 68.266667 0 0 0-28.586667-55.534934z\" fill=\"#FAFAFC\" ></path><path d=\"M500.053333 341.333333l62.702934 170.0352 0.443733 0.085334-0.221867 0.546133 0.221867 0.546133-0.443733 0.068267L500.0704 682.666667 460.8 675.0208 520.9088 512 460.8 348.9792 500.053333 341.333333z\" fill=\"#A8ADBD\" ></path></symbol><symbol id=\"iconzuocedaohanglanzhankai\" viewBox=\"0 0 1024 1024\"><path d=\"M512 768l512-465.408-51.2-46.592L512 675.0208 51.2 256l-51.2 46.592 460.8 418.816 51.2 46.592z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconzuocedaohangleshou\" viewBox=\"0 0 1024 1024\"><path d=\"M1024 804.544v73.152H0v-73.152h1024z m0-512v438.912L731.456 512 1024 292.544zM585.152 585.152v73.152H0V585.152h585.152z m0-219.456v73.152H0V365.696h585.152zM1024 146.304v73.152H0V146.304h1024z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconzuocedaohanglansuo\" viewBox=\"0 0 1024 1024\"><path d=\"M1024 804.544v73.152H0v-73.152h1024z m-292.544-512L1024 512l-292.544 219.456V292.48zM585.152 585.152v73.152H0V585.152h585.152z m0-219.456v73.152H0V365.696h585.152zM1024 146.304v73.152H0V146.304h1024z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconzuocedaohangsuoqi\" viewBox=\"0 0 1024 1024\"><path d=\"M602.88 150.254933L392.533333 0v1024l210.346667-150.254933A68.266667 68.266667 0 0 0 631.466667 818.210133V205.789867a68.266667 68.266667 0 0 0-28.586667-55.534934z\" fill=\"#FAFAFC\" ></path><path d=\"M523.946667 341.333333l-62.702934 170.0352-0.443733 0.085334 0.221867 0.546133-0.221867 0.546133 0.443733 0.068267L523.9296 682.666667 563.2 675.0208 503.0912 512 563.2 348.9792 523.946667 341.333333z\" fill=\"#A8ADBD\" ></path></symbol><symbol id=\"iconeslogo\" viewBox=\"0 0 1024 1024\"><path d=\"M510.464 591.872h-85.248c11.52-45.984 17.28-86.208 17.28-132.16 0-45.984-5.76-91.936-17.28-132.16h258.592c80.448 0 143.68 57.44 143.68 132.16 0 2.656-0.096 5.312-0.256 7.936a299.744 299.744 0 0 0-68.704-7.936 298.528 298.528 0 0 0-248.064 132.16z m-3.84 327.488l-6.72 0.064c-86.176 0-155.136-23.008-224.064-51.744 57.44-57.44 97.664-132.16 126.4-206.848l74.24-1.28a298.368 298.368 0 0 0-16.768 98.976 297.44 297.44 0 0 0 46.944 160.896v-0.064zM0 453.952c0-45.952 5.76-86.176 17.248-126.4h344.768c11.52 40.224 17.248 86.176 17.248 132.16 0 45.952-5.76 86.176-17.248 132.16H22.976C5.76 551.648 0 499.936 0 453.952zM51.712 264.32C86.208 189.632 149.44 126.4 224.096 80.448 270.08 132.16 310.304 195.36 344.768 264.32H51.712z m683.84 0L402.24 258.56c-28.736-74.688-68.96-149.376-126.4-206.848C344.736 17.28 413.76 0 499.904 0c172.384 0 327.52 74.688 419.488 189.632-45.984 45.984-109.184 74.688-183.904 74.688zM45.92 655.072h293.088c-28.736 68.96-68.96 132.16-120.672 178.144a467.232 467.232 0 0 1-172.384-178.144z\" fill=\"#FFFFFF\" ></path><path d=\"M752.32 1003.008a250.72 250.72 0 0 1-250.816-250.656 250.72 250.72 0 0 1 250.56-250.88h0.224a250.72 250.72 0 0 1 250.72 250.784 250.72 250.72 0 0 1-250.72 250.752z m0-45.6a205.12 205.12 0 0 0 205.12-205.152 205.12 205.12 0 1 0-205.12 205.12z\" fill=\"#FFFFFF\" ></path><path d=\"M740.128 666.944h-40.864v-51.456h45.216c73.472 0.928 131.456 63.04 133.056 135.904-0.48 74.016-58.88 136.608-133.12 137.6h-81.248c-8.288 0.096-13.664-5.12-13.568-13.056v-208.96h49.6l0.064 163.84c0 4.224 2.656 6.72 6.944 6.72h33.12c48.16-0.544 87.648-38.336 88.128-86.144-1.536-46.784-39.808-83.872-87.36-84.448z\" fill=\"#FFFFFF\" ></path></symbol></svg>',function(h){var a=(a=document.getElementsByTagName(\"script\"))[a.length-1],l=a.getAttribute(\"data-injectcss\"),a=a.getAttribute(\"data-disable-injectsvg\");if(!a){var i,o,c,m,t,z=function(a,l){l.parentNode.insertBefore(a,l)};if(l&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write(\"<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>\")}catch(a){console&&console.log(a)}}i=function(){var a,l=document.createElement(\"div\");l.innerHTML=h._iconfont_svg_string_2457502,(l=l.getElementsByTagName(\"svg\")[0])&&(l.setAttribute(\"aria-hidden\",\"true\"),l.style.position=\"absolute\",l.style.width=0,l.style.height=0,l.style.overflow=\"hidden\",l=l,(a=document.body).firstChild?z(l,a.firstChild):a.appendChild(l))},document.addEventListener?~[\"complete\",\"loaded\",\"interactive\"].indexOf(document.readyState)?setTimeout(i,0):(o=function(){document.removeEventListener(\"DOMContentLoaded\",o,!1),i()},document.addEventListener(\"DOMContentLoaded\",o,!1)):document.attachEvent&&(c=i,m=h.document,t=!1,n(),m.onreadystatechange=function(){\"complete\"==m.readyState&&(m.onreadystatechange=null,v())})}function v(){t||(t=!0,c())}function n(){try{m.documentElement.doScroll(\"left\")}catch(a){return void setTimeout(n,50)}v()}}(window);"
  },
  {
    "path": "arius-console/src/assets/icon/iconfont.json",
    "content": "{\n  \"id\": \"2457502\",\n  \"name\": \"Logi-ES icon\",\n  \"font_family\": \"iconfont\",\n  \"css_prefix_text\": \"icon\",\n  \"description\": \"\",\n  \"glyphs\": [\n    {\n      \"icon_id\": \"33682391\",\n      \"name\": \"拖拽\",\n      \"font_class\": \"tuozhuai\",\n      \"unicode\": \"e783\",\n      \"unicode_decimal\": 59267\n    },\n    {\n      \"icon_id\": \"33682392\",\n      \"name\": \"窗口放大\",\n      \"font_class\": \"chuangkoufangda\",\n      \"unicode\": \"e784\",\n      \"unicode_decimal\": 59268\n    },\n    {\n      \"icon_id\": \"33682393\",\n      \"name\": \"窗口缩小\",\n      \"font_class\": \"chuangkousuoxiao\",\n      \"unicode\": \"e785\",\n      \"unicode_decimal\": 59269\n    },\n    {\n      \"icon_id\": \"33412422\",\n      \"name\": \"Dashboard\",\n      \"font_class\": \"Dashboard\",\n      \"unicode\": \"e62d\",\n      \"unicode_decimal\": 58925\n    },\n    {\n      \"icon_id\": \"33412425\",\n      \"name\": \"租户管理\",\n      \"font_class\": \"zuhuguanli1\",\n      \"unicode\": \"e62e\",\n      \"unicode_decimal\": 58926\n    },\n    {\n      \"icon_id\": \"33412429\",\n      \"name\": \"任务中心\",\n      \"font_class\": \"renwuzhongxin1\",\n      \"unicode\": \"e655\",\n      \"unicode_decimal\": 58965\n    },\n    {\n      \"icon_id\": \"33412430\",\n      \"name\": \"索引管理\",\n      \"font_class\": \"suoyinguanli1\",\n      \"unicode\": \"e656\",\n      \"unicode_decimal\": 58966\n    },\n    {\n      \"icon_id\": \"33412431\",\n      \"name\": \"平台配置\",\n      \"font_class\": \"pingtaipeizhi\",\n      \"unicode\": \"e657\",\n      \"unicode_decimal\": 58967\n    },\n    {\n      \"icon_id\": \"33412432\",\n      \"name\": \"模版管理\",\n      \"font_class\": \"mobanguanli1\",\n      \"unicode\": \"e658\",\n      \"unicode_decimal\": 58968\n    },\n    {\n      \"icon_id\": \"33412433\",\n      \"name\": \"检索查询\",\n      \"font_class\": \"jiansuochaxun2\",\n      \"unicode\": \"e659\",\n      \"unicode_decimal\": 58969\n    },\n    {\n      \"icon_id\": \"33412434\",\n      \"name\": \"集群管理\",\n      \"font_class\": \"jiqunguanli2\",\n      \"unicode\": \"e65a\",\n      \"unicode_decimal\": 58970\n    },\n    {\n      \"icon_id\": \"33412435\",\n      \"name\": \"调度任务\",\n      \"font_class\": \"tiaodurenwu1\",\n      \"unicode\": \"e65b\",\n      \"unicode_decimal\": 58971\n    },\n    {\n      \"icon_id\": \"33412436\",\n      \"name\": \"操作记录\",\n      \"font_class\": \"caozuojilu1\",\n      \"unicode\": \"e65c\",\n      \"unicode_decimal\": 58972\n    },\n    {\n      \"icon_id\": \"33412437\",\n      \"name\": \"工单任务\",\n      \"font_class\": \"gongdanrenwu2\",\n      \"unicode\": \"e65d\",\n      \"unicode_decimal\": 58973\n    },\n    {\n      \"icon_id\": \"33412438\",\n      \"name\": \"指标看板\",\n      \"font_class\": \"zhibiaokanban2\",\n      \"unicode\": \"e65e\",\n      \"unicode_decimal\": 58974\n    },\n    {\n      \"icon_id\": \"32717834\",\n      \"name\": \"编辑\",\n      \"font_class\": \"bianji\",\n      \"unicode\": \"e77f\",\n      \"unicode_decimal\": 59263\n    },\n    {\n      \"icon_id\": \"32717835\",\n      \"name\": \"详情\",\n      \"font_class\": \"xiangqing\",\n      \"unicode\": \"e780\",\n      \"unicode_decimal\": 59264\n    },\n    {\n      \"icon_id\": \"32717836\",\n      \"name\": \"arrow-left\",\n      \"font_class\": \"arrow-left\",\n      \"unicode\": \"e781\",\n      \"unicode_decimal\": 59265\n    },\n    {\n      \"icon_id\": \"32239967\",\n      \"name\": \"top\",\n      \"font_class\": \"top\",\n      \"unicode\": \"e77c\",\n      \"unicode_decimal\": 59260\n    },\n    {\n      \"icon_id\": \"31931954\",\n      \"name\": \"日期\",\n      \"font_class\": \"riqi1\",\n      \"unicode\": \"e77b\",\n      \"unicode_decimal\": 59259\n    },\n    {\n      \"icon_id\": \"31221584\",\n      \"name\": \"应用\",\n      \"font_class\": \"yingyong\",\n      \"unicode\": \"e776\",\n      \"unicode_decimal\": 59254\n    },\n    {\n      \"icon_id\": \"31218948\",\n      \"name\": \"warning-circle\",\n      \"font_class\": \"warning-circle\",\n      \"unicode\": \"e772\",\n      \"unicode_decimal\": 59250\n    },\n    {\n      \"icon_id\": \"31218949\",\n      \"name\": \"info-circle\",\n      \"font_class\": \"info-circle\",\n      \"unicode\": \"e773\",\n      \"unicode_decimal\": 59251\n    },\n    {\n      \"icon_id\": \"31218950\",\n      \"name\": \"error-circle\",\n      \"font_class\": \"error-circle\",\n      \"unicode\": \"e774\",\n      \"unicode_decimal\": 59252\n    },\n    {\n      \"icon_id\": \"31218951\",\n      \"name\": \"success-circle\",\n      \"font_class\": \"success-circle\",\n      \"unicode\": \"e775\",\n      \"unicode_decimal\": 59253\n    },\n    {\n      \"icon_id\": \"31204137\",\n      \"name\": \"know search\",\n      \"font_class\": \"a-knowsearch\",\n      \"unicode\": \"e771\",\n      \"unicode_decimal\": 59249\n    },\n    {\n      \"icon_id\": \"31203140\",\n      \"name\": \"头像\",\n      \"font_class\": \"touxiang\",\n      \"unicode\": \"e76c\",\n      \"unicode_decimal\": 59244\n    },\n    {\n      \"icon_id\": \"31203141\",\n      \"name\": \"退出登录\",\n      \"font_class\": \"tuichudenglu\",\n      \"unicode\": \"e76d\",\n      \"unicode_decimal\": 59245\n    },\n    {\n      \"icon_id\": \"31203142\",\n      \"name\": \"退出全局\",\n      \"font_class\": \"tuichuquanju\",\n      \"unicode\": \"e76e\",\n      \"unicode_decimal\": 59246\n    },\n    {\n      \"icon_id\": \"31203143\",\n      \"name\": \"系统管理\",\n      \"font_class\": \"xitongguanli\",\n      \"unicode\": \"e76f\",\n      \"unicode_decimal\": 59247\n    },\n    {\n      \"icon_id\": \"31203144\",\n      \"name\": \"多集群管理\",\n      \"font_class\": \"duojiqunguanli\",\n      \"unicode\": \"e770\",\n      \"unicode_decimal\": 59248\n    },\n    {\n      \"icon_id\": \"31203139\",\n      \"name\": \"全局\",\n      \"font_class\": \"quanju\",\n      \"unicode\": \"e76b\",\n      \"unicode_decimal\": 59243\n    },\n    {\n      \"icon_id\": \"31123189\",\n      \"name\": \"软件管理\",\n      \"font_class\": \"ruanjianguanli\",\n      \"unicode\": \"e61c\",\n      \"unicode_decimal\": 58908\n    },\n    {\n      \"icon_id\": \"31123192\",\n      \"name\": \"平台管理\",\n      \"font_class\": \"pingtaiguanli\",\n      \"unicode\": \"e61d\",\n      \"unicode_decimal\": 58909\n    },\n    {\n      \"icon_id\": \"31123162\",\n      \"name\": \"任务中心\",\n      \"font_class\": \"renwuzhongxin\",\n      \"unicode\": \"e61b\",\n      \"unicode_decimal\": 58907\n    },\n    {\n      \"icon_id\": \"31123160\",\n      \"name\": \"租户管理\",\n      \"font_class\": \"zuhuguanli\",\n      \"unicode\": \"e61a\",\n      \"unicode_decimal\": 58906\n    },\n    {\n      \"icon_id\": \"31123069\",\n      \"name\": \"系统管理\",\n      \"font_class\": \"xitongguanli2\",\n      \"unicode\": \"e617\",\n      \"unicode_decimal\": 58903\n    },\n    {\n      \"icon_id\": \"31123153\",\n      \"name\": \"操作记录\",\n      \"font_class\": \"caozuojilu\",\n      \"unicode\": \"e618\",\n      \"unicode_decimal\": 58904\n    },\n    {\n      \"icon_id\": \"31123157\",\n      \"name\": \"指标看板\",\n      \"font_class\": \"zhibiaokanban1\",\n      \"unicode\": \"e619\",\n      \"unicode_decimal\": 58905\n    },\n    {\n      \"icon_id\": \"30590855\",\n      \"name\": \"红\",\n      \"font_class\": \"hong\",\n      \"unicode\": \"e763\",\n      \"unicode_decimal\": 59235\n    },\n    {\n      \"icon_id\": \"30590856\",\n      \"name\": \"黄\",\n      \"font_class\": \"huang\",\n      \"unicode\": \"e764\",\n      \"unicode_decimal\": 59236\n    },\n    {\n      \"icon_id\": \"30590857\",\n      \"name\": \"绿\",\n      \"font_class\": \"lv\",\n      \"unicode\": \"e765\",\n      \"unicode_decimal\": 59237\n    },\n    {\n      \"icon_id\": \"28794130\",\n      \"name\": \"Right\",\n      \"font_class\": \"Right\",\n      \"unicode\": \"e72f\",\n      \"unicode_decimal\": 59183\n    },\n    {\n      \"icon_id\": \"28794131\",\n      \"name\": \"left\",\n      \"font_class\": \"left\",\n      \"unicode\": \"e730\",\n      \"unicode_decimal\": 59184\n    },\n    {\n      \"icon_id\": \"28443850\",\n      \"name\": \"未知\",\n      \"font_class\": \"weizhi\",\n      \"unicode\": \"e720\",\n      \"unicode_decimal\": 59168\n    },\n    {\n      \"icon_id\": \"28329066\",\n      \"name\": \"刷新\",\n      \"font_class\": \"shuaxin2\",\n      \"unicode\": \"e714\",\n      \"unicode_decimal\": 59156\n    },\n    {\n      \"icon_id\": \"27880045\",\n      \"name\": \"减少\",\n      \"font_class\": \"jianshao\",\n      \"unicode\": \"e710\",\n      \"unicode_decimal\": 59152\n    },\n    {\n      \"icon_id\": \"27880046\",\n      \"name\": \"增加\",\n      \"font_class\": \"zengjia\",\n      \"unicode\": \"e711\",\n      \"unicode_decimal\": 59153\n    },\n    {\n      \"icon_id\": \"27776836\",\n      \"name\": \"调度任务\",\n      \"font_class\": \"tiaodurenwu\",\n      \"unicode\": \"e708\",\n      \"unicode_decimal\": 59144\n    },\n    {\n      \"icon_id\": \"27776837\",\n      \"name\": \"检索查询\",\n      \"font_class\": \"jiansuochaxun\",\n      \"unicode\": \"e709\",\n      \"unicode_decimal\": 59145\n    },\n    {\n      \"icon_id\": \"27776838\",\n      \"name\": \"索引管理\",\n      \"font_class\": \"suoyinguanli\",\n      \"unicode\": \"e70a\",\n      \"unicode_decimal\": 59146\n    },\n    {\n      \"icon_id\": \"27776839\",\n      \"name\": \"模版管理\",\n      \"font_class\": \"mobanguanli\",\n      \"unicode\": \"e70b\",\n      \"unicode_decimal\": 59147\n    },\n    {\n      \"icon_id\": \"27776841\",\n      \"name\": \"工单任务\",\n      \"font_class\": \"gongdanrenwu\",\n      \"unicode\": \"e70d\",\n      \"unicode_decimal\": 59149\n    },\n    {\n      \"icon_id\": \"27776842\",\n      \"name\": \"集群管理\",\n      \"font_class\": \"jiqunguanli\",\n      \"unicode\": \"e70e\",\n      \"unicode_decimal\": 59150\n    },\n    {\n      \"icon_id\": \"27776843\",\n      \"name\": \"指标看板\",\n      \"font_class\": \"zhibiaokanban\",\n      \"unicode\": \"e70f\",\n      \"unicode_decimal\": 59151\n    },\n    {\n      \"icon_id\": \"27345833\",\n      \"name\": \"箭头_右上\",\n      \"font_class\": \"jiantou_youshang\",\n      \"unicode\": \"e6fe\",\n      \"unicode_decimal\": 59134\n    },\n    {\n      \"icon_id\": \"27202690\",\n      \"name\": \"筛选\",\n      \"font_class\": \"shaixuan\",\n      \"unicode\": \"e6f8\",\n      \"unicode_decimal\": 59128\n    },\n    {\n      \"icon_id\": \"25703269\",\n      \"name\": \"复制 - kafka\",\n      \"font_class\": \"fuzhi\",\n      \"unicode\": \"e6c8\",\n      \"unicode_decimal\": 59080\n    },\n    {\n      \"icon_id\": \"25703270\",\n      \"name\": \"更多 - kafka\",\n      \"font_class\": \"a-gengduo-kafka\",\n      \"unicode\": \"e6c9\",\n      \"unicode_decimal\": 59081\n    },\n    {\n      \"icon_id\": \"25703271\",\n      \"name\": \"info - kafka\",\n      \"font_class\": \"info\",\n      \"unicode\": \"e6ca\",\n      \"unicode_decimal\": 59082\n    },\n    {\n      \"icon_id\": \"24326205\",\n      \"name\": \"es-logo\",\n      \"font_class\": \"es-logo\",\n      \"unicode\": \"e9e2\",\n      \"unicode_decimal\": 59874\n    },\n    {\n      \"icon_id\": \"24324496\",\n      \"name\": \"版本变更\",\n      \"font_class\": \"banbenbiangeng\",\n      \"unicode\": \"e6ae\",\n      \"unicode_decimal\": 59054\n    },\n    {\n      \"icon_id\": \"24324497\",\n      \"name\": \"返回\",\n      \"font_class\": \"fanhui\",\n      \"unicode\": \"e6af\",\n      \"unicode_decimal\": 59055\n    },\n    {\n      \"icon_id\": \"24324498\",\n      \"name\": \"磁盘扩容\",\n      \"font_class\": \"cipankuorong\",\n      \"unicode\": \"e6b0\",\n      \"unicode_decimal\": 59056\n    },\n    {\n      \"icon_id\": \"24324500\",\n      \"name\": \"链接\",\n      \"font_class\": \"lianjie1\",\n      \"unicode\": \"e6b2\",\n      \"unicode_decimal\": 59058\n    },\n    {\n      \"icon_id\": \"24324501\",\n      \"name\": \"代运行\",\n      \"font_class\": \"daiyunhang\",\n      \"unicode\": \"e6b3\",\n      \"unicode_decimal\": 59059\n    },\n    {\n      \"icon_id\": \"24324502\",\n      \"name\": \"日历间隔\",\n      \"font_class\": \"rilijiange\",\n      \"unicode\": \"e6b4\",\n      \"unicode_decimal\": 59060\n    },\n    {\n      \"icon_id\": \"24324503\",\n      \"name\": \"暂停\",\n      \"font_class\": \"zanting\",\n      \"unicode\": \"e6b5\",\n      \"unicode_decimal\": 59061\n    },\n    {\n      \"icon_id\": \"24324504\",\n      \"name\": \"节点扩容\",\n      \"font_class\": \"jiediankuorong\",\n      \"unicode\": \"e6b6\",\n      \"unicode_decimal\": 59062\n    },\n    {\n      \"icon_id\": \"24324505\",\n      \"name\": \"完成\",\n      \"font_class\": \"wancheng\",\n      \"unicode\": \"e6b7\",\n      \"unicode_decimal\": 59063\n    },\n    {\n      \"icon_id\": \"24324506\",\n      \"name\": \"日历\",\n      \"font_class\": \"rili\",\n      \"unicode\": \"e6b8\",\n      \"unicode_decimal\": 59064\n    },\n    {\n      \"icon_id\": \"24324507\",\n      \"name\": \"下线\",\n      \"font_class\": \"xiaxian\",\n      \"unicode\": \"e6b9\",\n      \"unicode_decimal\": 59065\n    },\n    {\n      \"icon_id\": \"24324508\",\n      \"name\": \"刷新\",\n      \"font_class\": \"shuaxin1\",\n      \"unicode\": \"e6ba\",\n      \"unicode_decimal\": 59066\n    },\n    {\n      \"icon_id\": \"24324509\",\n      \"name\": \"新增\",\n      \"font_class\": \"xinzeng\",\n      \"unicode\": \"e6bb\",\n      \"unicode_decimal\": 59067\n    },\n    {\n      \"icon_id\": \"24324511\",\n      \"name\": \"Controller管理\",\n      \"font_class\": \"Controllerguanli\",\n      \"unicode\": \"e6bd\",\n      \"unicode_decimal\": 59069\n    },\n    {\n      \"icon_id\": \"24324512\",\n      \"name\": \"Leader Rebalance\",\n      \"font_class\": \"a-LeaderRebalance\",\n      \"unicode\": \"e6be\",\n      \"unicode_decimal\": 59070\n    },\n    {\n      \"icon_id\": \"24324513\",\n      \"name\": \"运行\",\n      \"font_class\": \"yunhang\",\n      \"unicode\": \"e6bf\",\n      \"unicode_decimal\": 59071\n    },\n    {\n      \"icon_id\": \"24324514\",\n      \"name\": \"region配置\",\n      \"font_class\": \"regionpeizhi\",\n      \"unicode\": \"e6c0\",\n      \"unicode_decimal\": 59072\n    },\n    {\n      \"icon_id\": \"23815159\",\n      \"name\": \"Info-Circle备份 8\",\n      \"font_class\": \"a-Info-Circlebeifen8\",\n      \"unicode\": \"e9da\",\n      \"unicode_decimal\": 59866\n    },\n    {\n      \"icon_id\": \"23814989\",\n      \"name\": \"保障\",\n      \"font_class\": \"baozhang\",\n      \"unicode\": \"e9d9\",\n      \"unicode_decimal\": 59865\n    },\n    {\n      \"icon_id\": \"23022545\",\n      \"name\": \"二级告警\",\n      \"font_class\": \"erjigaojing\",\n      \"unicode\": \"e9c9\",\n      \"unicode_decimal\": 59849\n    },\n    {\n      \"icon_id\": \"23022546\",\n      \"name\": \"一级告警\",\n      \"font_class\": \"yijigaojing\",\n      \"unicode\": \"e9ca\",\n      \"unicode_decimal\": 59850\n    },\n    {\n      \"icon_id\": \"20760350\",\n      \"name\": \"表格解释\",\n      \"font_class\": \"biaogejieshi\",\n      \"unicode\": \"e62f\",\n      \"unicode_decimal\": 58927\n    },\n    {\n      \"icon_id\": \"20760351\",\n      \"name\": \"步骤完成\",\n      \"font_class\": \"buzhouwancheng\",\n      \"unicode\": \"e630\",\n      \"unicode_decimal\": 58928\n    },\n    {\n      \"icon_id\": \"20760352\",\n      \"name\": \"弹框删除\",\n      \"font_class\": \"dankuangshanchu\",\n      \"unicode\": \"e631\",\n      \"unicode_decimal\": 58929\n    },\n    {\n      \"icon_id\": \"20760353\",\n      \"name\": \"表格排序\",\n      \"font_class\": \"biaogepaixu\",\n      \"unicode\": \"e632\",\n      \"unicode_decimal\": 58930\n    },\n    {\n      \"icon_id\": \"20760354\",\n      \"name\": \"顶部导航展开\",\n      \"font_class\": \"dingbudaohangzhankai\",\n      \"unicode\": \"e633\",\n      \"unicode_decimal\": 58931\n    },\n    {\n      \"icon_id\": \"20760355\",\n      \"name\": \"多选已选状态\",\n      \"font_class\": \"duoxuanyixuanzhuangtai\",\n      \"unicode\": \"e634\",\n      \"unicode_decimal\": 58932\n    },\n    {\n      \"icon_id\": \"20760356\",\n      \"name\": \"多选不可选状态\",\n      \"font_class\": \"duoxuanbukexuanzhuangtai\",\n      \"unicode\": \"e635\",\n      \"unicode_decimal\": 58933\n    },\n    {\n      \"icon_id\": \"20760357\",\n      \"name\": \"多选未选状态\",\n      \"font_class\": \"duoxuanweixuanzhuangtai\",\n      \"unicode\": \"e636\",\n      \"unicode_decimal\": 58934\n    },\n    {\n      \"icon_id\": \"20760358\",\n      \"name\": \"更多操作收起\",\n      \"font_class\": \"gengduocaozuoshouqi\",\n      \"unicode\": \"e637\",\n      \"unicode_decimal\": 58935\n    },\n    {\n      \"icon_id\": \"20760359\",\n      \"name\": \"告警ICON\",\n      \"font_class\": \"gaojingICON\",\n      \"unicode\": \"e638\",\n      \"unicode_decimal\": 58936\n    },\n    {\n      \"icon_id\": \"20760360\",\n      \"name\": \"顶部导航收起\",\n      \"font_class\": \"dingbudaohangshouqi\",\n      \"unicode\": \"e639\",\n      \"unicode_decimal\": 58937\n    },\n    {\n      \"icon_id\": \"20760361\",\n      \"name\": \"关\",\n      \"font_class\": \"guan\",\n      \"unicode\": \"e63a\",\n      \"unicode_decimal\": 58938\n    },\n    {\n      \"icon_id\": \"20760362\",\n      \"name\": \"链接\",\n      \"font_class\": \"lianjie\",\n      \"unicode\": \"e63b\",\n      \"unicode_decimal\": 58939\n    },\n    {\n      \"icon_id\": \"20760363\",\n      \"name\": \"开\",\n      \"font_class\": \"kai\",\n      \"unicode\": \"e63c\",\n      \"unicode_decimal\": 58940\n    },\n    {\n      \"icon_id\": \"20760364\",\n      \"name\": \"更多操作缩起\",\n      \"font_class\": \"gengduocaozuosuoqi\",\n      \"unicode\": \"e63d\",\n      \"unicode_decimal\": 58941\n    },\n    {\n      \"icon_id\": \"20760365\",\n      \"name\": \"面包屑关闭\",\n      \"font_class\": \"mianbaoxieguanbi\",\n      \"unicode\": \"e63e\",\n      \"unicode_decimal\": 58942\n    },\n    {\n      \"icon_id\": \"20760366\",\n      \"name\": \"默认开不可点\",\n      \"font_class\": \"morenkaibukedian\",\n      \"unicode\": \"e63f\",\n      \"unicode_decimal\": 58943\n    },\n    {\n      \"icon_id\": \"20760367\",\n      \"name\": \"面包屑删除\",\n      \"font_class\": \"mianbaoxieshanchu\",\n      \"unicode\": \"e640\",\n      \"unicode_decimal\": 58944\n    },\n    {\n      \"icon_id\": \"20760368\",\n      \"name\": \"默认关不可点\",\n      \"font_class\": \"morenguanbukedian\",\n      \"unicode\": \"e641\",\n      \"unicode_decimal\": 58945\n    },\n    {\n      \"icon_id\": \"20760369\",\n      \"name\": \"上传中\",\n      \"font_class\": \"shangchuanzhong\",\n      \"unicode\": \"e642\",\n      \"unicode_decimal\": 58946\n    },\n    {\n      \"icon_id\": \"20760370\",\n      \"name\": \"日期\",\n      \"font_class\": \"riqi\",\n      \"unicode\": \"e643\",\n      \"unicode_decimal\": 58947\n    },\n    {\n      \"icon_id\": \"20760371\",\n      \"name\": \"图标-info\",\n      \"font_class\": \"tubiao-info\",\n      \"unicode\": \"e644\",\n      \"unicode_decimal\": 58948\n    },\n    {\n      \"icon_id\": \"20760372\",\n      \"name\": \"刷新\",\n      \"font_class\": \"shuaxin\",\n      \"unicode\": \"e645\",\n      \"unicode_decimal\": 58949\n    },\n    {\n      \"icon_id\": \"20760373\",\n      \"name\": \"日期悬浮\",\n      \"font_class\": \"riqixuanfu\",\n      \"unicode\": \"e646\",\n      \"unicode_decimal\": 58950\n    },\n    {\n      \"icon_id\": \"20760374\",\n      \"name\": \"上传失败链接\",\n      \"font_class\": \"shangchuanshibailianjie\",\n      \"unicode\": \"e647\",\n      \"unicode_decimal\": 58951\n    },\n    {\n      \"icon_id\": \"20760375\",\n      \"name\": \"图标-搜索\",\n      \"font_class\": \"tubiao-sousuo\",\n      \"unicode\": \"e648\",\n      \"unicode_decimal\": 58952\n    },\n    {\n      \"icon_id\": \"20760376\",\n      \"name\": \"文件上传\",\n      \"font_class\": \"wenjianshangchuan\",\n      \"unicode\": \"e649\",\n      \"unicode_decimal\": 58953\n    },\n    {\n      \"icon_id\": \"20760377\",\n      \"name\": \"悬浮文件上传\",\n      \"font_class\": \"xuanfuwenjianshangchuan\",\n      \"unicode\": \"e64a\",\n      \"unicode_decimal\": 58954\n    },\n    {\n      \"icon_id\": \"20760378\",\n      \"name\": \"文件删除\",\n      \"font_class\": \"wenjianshanchu\",\n      \"unicode\": \"e64b\",\n      \"unicode_decimal\": 58955\n    },\n    {\n      \"icon_id\": \"20760379\",\n      \"name\": \"左侧导航栏收起\",\n      \"font_class\": \"zuocedaohanglanshouqi\",\n      \"unicode\": \"e64c\",\n      \"unicode_decimal\": 58956\n    },\n    {\n      \"icon_id\": \"20760380\",\n      \"name\": \"选择框收起\",\n      \"font_class\": \"xuanzekuangshouqi\",\n      \"unicode\": \"e64d\",\n      \"unicode_decimal\": 58957\n    },\n    {\n      \"icon_id\": \"20760381\",\n      \"name\": \"选择框展开\",\n      \"font_class\": \"xuanzekuangzhankai\",\n      \"unicode\": \"e64e\",\n      \"unicode_decimal\": 58958\n    },\n    {\n      \"icon_id\": \"20760382\",\n      \"name\": \"左侧导航收起\",\n      \"font_class\": \"zuocedaohangshouqi\",\n      \"unicode\": \"e64f\",\n      \"unicode_decimal\": 58959\n    },\n    {\n      \"icon_id\": \"20760383\",\n      \"name\": \"左侧导航栏展开\",\n      \"font_class\": \"zuocedaohanglanzhankai\",\n      \"unicode\": \"e650\",\n      \"unicode_decimal\": 58960\n    },\n    {\n      \"icon_id\": \"20760384\",\n      \"name\": \"左侧导航了收\",\n      \"font_class\": \"zuocedaohangleshou\",\n      \"unicode\": \"e651\",\n      \"unicode_decimal\": 58961\n    },\n    {\n      \"icon_id\": \"20760385\",\n      \"name\": \"左侧导航栏缩\",\n      \"font_class\": \"zuocedaohanglansuo\",\n      \"unicode\": \"e652\",\n      \"unicode_decimal\": 58962\n    },\n    {\n      \"icon_id\": \"20760386\",\n      \"name\": \"左侧导航缩起\",\n      \"font_class\": \"zuocedaohangsuoqi\",\n      \"unicode\": \"e653\",\n      \"unicode_decimal\": 58963\n    },\n    {\n      \"icon_id\": \"20760387\",\n      \"name\": \"es logo\",\n      \"font_class\": \"eslogo\",\n      \"unicode\": \"e654\",\n      \"unicode_decimal\": 58964\n    }\n  ]\n}\n"
  },
  {
    "path": "arius-console/src/component/LogClusterEmpty/index.less",
    "content": ".log-cluster-empty{\n  height: calc(100vh - 130px);\n   background: #FFFFFF;\n   text-align: center;\n   img{\n    margin-top: 120px;\n   }\n   .empty-title{\n    font-family: PingFangSC-Medium;\n    font-size: 20px;\n    color: #1D2330;\n    letter-spacing: 0;\n    text-align: center;\n    line-height: 28px;\n    font-weight: 500;\n  }\n}\n\n\n.empty-desc{\n  font-family: PingFangSC-Regular;\n  font-size: 14px;\n  color: #A8ADBD;\n  letter-spacing: 0;\n  text-align: center;\n  line-height: 22px;\n  font-weight: 400;\n  margin-top: 8px;\n}\n.apply-button{\n  width: 80px;\n  height: 32px;\n  border-radius: 4px;\n  margin-top: 32px;\n}\n// .d1-layout-main >div:nth-child(2){\n//   height: 100%;\n// }\n"
  },
  {
    "path": "arius-console/src/component/LogClusterEmpty/index.tsx",
    "content": "import \"./index.less\";\nimport React, { useState } from \"react\";\nimport { Button } from \"antd\";\nimport { uuid } from \"lib/utils\";\nexport const RenderEmpty = (props) => {\n  return (\n    <div className=\"log-cluster-empty\">\n      <img src={require(\"../../assets/clusterLogEmpty.png\")} alt=\"\" />\n      <div className=\"empty-title\">无集群信息</div>\n      <div className=\"empty-desc\">请前往集群管理 ———— 「我的集群」，进行集群申请</div>\n      <div>\n        <Button\n          type=\"primary\"\n          onClick={() => {\n            props.history.push(`/cluster/logic?needApplyCluster=${uuid()}`);\n          }}\n          className=\"apply-button\"\n        >\n          申请集群\n        </Button>\n      </div>\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/component/TimeRangePicker/index.less",
    "content": ".custom-ranger-picker {\n  display: inline-block;\n  position: relative;\n\n  .ant-picker-range {\n    height: 32px;\n    width: 343px;\n    border-radius: 4px;\n  }\n\n  .ant-picker-input {\n    width: 44%;\n\n    input {\n      font-family: PingFangSC-Regular;\n      font-size: 14px;\n      color: rgba(0, 0, 0, 0.75);\n      font-weight: 400;\n    }\n  }\n\n  .ant-picker-range-separator {\n    font-family: PingFangSC-Regular;\n    font-size: 18px;\n    color: rgba(0, 0, 0, 0.24);\n    font-weight: 400;\n  }\n\n  .ant-picker-clear {\n    display: none;\n  }\n\n  .custom-btn {\n    position: absolute;\n    top: 0px;\n    right: 0px;\n    height: 32px;\n    line-height: 32px;\n    width: 32px;\n    background: rgba(20, 115, 255, 0.06);\n    border-radius: 0 4px 4px 0;\n    text-align: center;\n\n    .cal-icon {\n      color: @primary-color;\n      font-size: 13px;\n    }\n  }\n}\n\n.custom-popover {\n  padding-top: 0px;\n\n  .ant-popover-arrow {\n    display: none;\n  }\n\n  .ant-popover-inner-content {\n    width: 412px;\n    height: 234px;\n    background: #FFFFFF;\n    box-shadow: 0 -2px 4px 0 rgba(0, 0, 0, 0.02), 0 2px 6px 6px rgba(0, 0, 0, 0.02), 0 2px 6px 0 rgba(0, 0, 0, 0.06);\n    border-radius: 4px;\n    padding: 16px 24px;\n  }\n\n  .quick-select {\n    position: relative;\n    margin-bottom: 12px;\n  }\n\n  .quick-select-title {\n    font-family: PingFangSC-Medium;\n    font-size: 14px;\n    color: #212529;\n    letter-spacing: 0;\n    font-weight: 500;\n  }\n\n  .quick-select-icon {\n    color: @primary-color;\n    font-size: 9px;\n    position: absolute;\n    right: -7px;\n    top: -4px;\n    display: flex;\n    justify-content: space-between;\n\n    .icon {\n      width: 28px;\n      height: 28px;\n      line-height: 28px;\n      text-align: center;\n\n      &.disabled {\n        opacity: 0.6;\n        color: #74788D;\n      }\n\n      &.disabled:hover {\n        border-radius: 50%;\n        cursor: auto;\n        background: #fff;\n      }\n    }\n\n    .icon:hover {\n      border-radius: 50%;\n      cursor: pointer;\n      background: rgba(20, 115, 255, 0.06);\n    }\n\n\n  }\n\n  .options {\n    display: flex;\n\n    .ant-form-item {\n      height: 28px;\n      margin-bottom: 0px;\n    }\n\n    .ant-form-item-control-input {\n      min-height: 28px;\n    }\n\n    .ant-input-number {\n      height: 28px;\n    }\n\n    .ant-input-number-input {\n      height: 28px;\n    }\n\n    .ant-btn {\n      height: 28px;\n      line-height: 1;\n      width: 68px;\n      border-radius: 4px;\n    }\n\n    .ant-select:not(.ant-select-customize-input) .ant-select-selector {\n      height: 28px;\n      border: 1px solid rgba(0, 0, 0, 0.13);\n      border-radius: 4px;\n    }\n\n    .ant-select-single:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input {\n      height: 28px;\n    }\n\n    .ant-select-single .ant-select-selector .ant-select-selection-item,\n    .ant-select-single .ant-select-selector .ant-select-selection-placeholder {\n      line-height: 28px;\n    }\n  }\n\n\n\n  .type {\n    display: inline-block;\n    width: 104px;\n    background: #FFFFFF;\n    margin-right: 8px;\n  }\n\n  .content {\n    display: inline-block;\n    width: 84px;\n    margin-right: 8px;\n  }\n\n  .time-options {\n    margin-top: 23px;\n\n    .title {\n      font-family: PingFangSC-Medium;\n      font-size: 14px;\n      color: #212529;\n      letter-spacing: 0;\n      font-weight: 500;\n    }\n  }\n\n  .common-items {\n    width: 100%;\n    display: flex;\n    flex-flow: row wrap;\n    row-gap: 15px;\n    align-content: flex-start;\n    margin-top: 12px;\n\n    .item {\n      box-sizing: border-box;\n      flex: 0 50%;\n      height: 18px;\n      font-family: PingFangSC-Medium;\n      font-size: 13px;\n      color: #495057;\n      letter-spacing: 0;\n      font-weight: 500;\n\n      &.checked {\n        color: @primary-color;\n      }\n    }\n\n    .item:hover {\n      color: @primary-color;\n      cursor: pointer;\n    }\n  }\n}"
  },
  {
    "path": "arius-console/src/component/TimeRangePicker/index.tsx",
    "content": "import { LeftOutlined, RightOutlined } from \"@ant-design/icons\";\nimport { Button, DatePicker, Form, Input, InputNumber, Popover, Row, Select, Tooltip } from \"antd\";\nimport { getPopupContainer } from \"lib/utils\";\nimport moment, { Moment } from \"moment\";\nimport React, { useImperativeHandle, useRef, useState } from \"react\";\nimport \"./index.less\";\nconst { RangePicker } = DatePicker;\nconst { Option } = Select;\nconst FormItem = Form.Item;\n\nconst TIME_OPTIONS = [\n  {\n    label: \"最近 15 分钟\",\n    value: 15 * 60 * 1000,\n  },\n  {\n    label: \"最近 30 分钟\",\n    value: 30 * 60 * 1000,\n  },\n  {\n    label: \"最近 1 小时\",\n    value: 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 6 小时\",\n    value: 6 * 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 12 小时\",\n    value: 12 * 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 1 天\",\n    value: 24 * 60 * 60 * 1000,\n  },\n];\n\ninterface IProps {\n  value?: [Moment, Moment];\n  defaultValue?: [Moment, Moment];\n  onChange?: any;\n  defaultRange?: number;\n}\n\ntype RangeValue = [Moment | null, Moment | null] | null;\n\nexport const CustomTimeRangePicker = React.forwardRef((props: IProps, ref) => {\n  const { onChange, value, defaultValue, defaultRange } = props;\n  const defaultRangeTime = defaultValue || [moment(new Date().getTime() - (defaultRange ?? 60 * 60 * 1000)), moment(new Date().getTime())];\n  const [rangeTime, setRangeTime] = useState(value || defaultRangeTime);\n  const [hackValue, setHackValue] = useState<any>(null); //RangePicker打开面板后值设置为空\n  const [dates, setDates] = useState<RangeValue>(null);\n  const noNeedChange = useRef(null);\n  const [form] = Form.useForm();\n  const [iconDisabled, setIconDisabled] = useState(true);\n  const [commonTime, setCommonTime] = useState(defaultRange || 60 * 60 * 1000);\n  const [isLastTime, setIsLastTime] = useState(false);\n  const [open, setOpen] = useState(false);\n\n  const hide = () => {\n    setOpen(false);\n  };\n\n  const handleOpenChange = (newOpen: boolean) => {\n    setOpen(newOpen);\n  };\n\n  const onRangeTimeChange = (dates, dateStrings) => {\n    if (noNeedChange.current) {\n      return;\n    }\n    setCommonTime(null);\n    setIsLastTime(false);\n    if (dates[1].valueOf() < new Date().getTime()) {\n      setIconDisabled(false);\n    }\n    changeRangeTime(dates, true);\n  };\n\n  useImperativeHandle(ref, () => ({\n    rangeTime,\n    refresh,\n  }));\n\n  const onOpenChange = (open) => {\n    if (open) {\n      setDates([null, null]);\n    } else {\n      setHackValue(null);\n    }\n  };\n\n  const refresh = () => {\n    if (commonTime) {\n      changeRangeTime([moment(new Date().getTime() - commonTime), moment(new Date().getTime() - 120000)], false);\n    } else if (isLastTime) {\n      const values = form.getFieldsValue();\n      const { unit, input, type } = values;\n      const rangeValue = unit === \"hour\" ? input * 60 * 60 * 1000 : unit === \"min\" ? input * 60 * 1000 : input * 24 * 60 * 60 * 1000;\n      changeRangeTime([moment(new Date().getTime() - rangeValue), moment(new Date().getTime())], false);\n    } else {\n      changeRangeTime([rangeTime[0], rangeTime[1]], true);\n    }\n  };\n\n  const changeRangeTime = (dates: [Moment, Moment], isCustomTime) => {\n    setRangeTime(dates);\n    onChange && onChange([dates[0].valueOf(), dates[1].valueOf()], isCustomTime);\n  };\n\n  const onFormChange = (values, allValues) => {\n    // 时间范围不能超过14天\n    if (allValues.unit === \"day\" && +allValues.input > 14) {\n      form.setFieldsValue({\n        input: 14,\n      });\n    }\n    if (allValues.unit === \"hour\" && +allValues.input > 14 * 24) {\n      form.setFieldsValue({\n        input: 14 * 24,\n      });\n    }\n    if (allValues.unit === \"min\" && +allValues.input > 14 * 24 * 60) {\n      form.setFieldsValue({\n        input: 14 * 24 * 60,\n      });\n    }\n  };\n\n  // 点击确定后\n  const onQuickSelect = async () => {\n    const values = await form.validateFields();\n    const { unit, input, type } = values;\n    const rangeValue = unit === \"hour\" ? input * 60 * 60 * 1000 : unit === \"min\" ? input * 60 * 1000 : input * 24 * 60 * 60 * 1000;\n    setCommonTime(null);\n    setIsLastTime(true);\n    setIconDisabled(true);\n    hide();\n    const currentTime = new Date().getTime();\n    changeRangeTime([moment(currentTime - rangeValue), moment(currentTime)], false);\n  };\n\n  // 点击左右箭头后\n  const onQuickSwap = (direction: string) => {\n    if (direction === \"right\" && iconDisabled) {\n      return;\n    }\n\n    const gap = rangeTime[1].valueOf() - rangeTime[0].valueOf();\n    let newRangeTime = rangeTime;\n\n    if (direction === \"left\") {\n      setIconDisabled(false);\n      newRangeTime = [moment(rangeTime[0].valueOf() - gap), moment(rangeTime[1].valueOf() - gap)];\n    }\n    if (direction === \"right\") {\n      setIconDisabled(new Date().getTime() <= rangeTime[1].valueOf() + gap);\n      // 如果截止时间大于当前时间则选择当前时间\n      const endTime = new Date().getTime() - (rangeTime[1].valueOf() + gap) > 0 ? rangeTime[1].valueOf() + gap : new Date().getTime();\n      const startTime =\n        new Date().getTime() - (rangeTime[1].valueOf() + gap) > 0 ? rangeTime[0].valueOf() + gap : new Date().getTime() - gap;\n      newRangeTime = [moment(startTime), moment(endTime)];\n    }\n    setCommonTime(null);\n    setIsLastTime(false);\n    changeRangeTime(newRangeTime, true);\n  };\n\n  // 选择常用时间\n  const onChooseTime = (value) => {\n    setCommonTime(value);\n    setIsLastTime(false);\n    setIconDisabled(true);\n    hide();\n    changeRangeTime([moment(new Date().getTime() - value), moment(new Date().getTime())], false);\n  };\n\n  const disabledDate = (current: Moment) => {\n    if (!dates) {\n      return false;\n    }\n\n    const tooLate = dates[0] && current.diff(dates[0], \"days\") > 13;\n    const tooEarly = dates[1] && dates[1].diff(current, \"days\") > 13;\n    return !!tooEarly || !!tooLate || (current && current > moment().endOf(\"day\"));\n  };\n\n  const renderCustomTimeRange = () => {\n    return (\n      <>\n        <div className=\"quick-select\">\n          <div className=\"quick-select-title\">快速选择</div>\n          <div className=\"quick-select-icon\">\n            <Tooltip title=\"上一时间窗口\">\n              <div className=\"icon\" onClick={() => onQuickSwap(\"left\")}>\n                <LeftOutlined />\n              </div>\n            </Tooltip>\n            <Tooltip title=\"下一时间窗口\">\n              <div className={iconDisabled ? \"icon disabled\" : \"icon\"} onClick={() => onQuickSwap(\"right\")}>\n                <RightOutlined />\n              </div>\n            </Tooltip>\n          </div>\n        </div>\n        <div className=\"options\">\n          <Form onValuesChange={onFormChange} form={form}>\n            <Row>\n              <FormItem name=\"type\" initialValue={\"Last\"}>\n                <Select className=\"type\">\n                  <Option value=\"Last\">Last</Option>\n                  {/* <Option value=\"Next\">Next</Option> */}\n                </Select>\n              </FormItem>\n              <FormItem name=\"input\" initialValue={15}>\n                <InputNumber min={1} className=\"content\" />\n              </FormItem>\n              <FormItem name=\"unit\" initialValue={\"min\"}>\n                <Select className=\"content\">\n                  <Option value=\"min\">分钟</Option>\n                  <Option value=\"hour\">小时</Option>\n                  <Option value=\"day\">天</Option>\n                </Select>\n              </FormItem>\n              <FormItem>\n                <Button type=\"primary\" ghost onClick={onQuickSelect}>\n                  确定\n                </Button>\n              </FormItem>\n            </Row>\n          </Form>\n        </div>\n        <div className=\"time-options\">\n          <div className=\"title\">常用</div>\n          <div className=\"common-items\">\n            {TIME_OPTIONS.map((item) => {\n              return (\n                <div\n                  key={item.value}\n                  className={`item ${commonTime === item.value ? \"checked\" : \"\"}`}\n                  onClick={() => onChooseTime(item.value)}\n                >\n                  {item.label}\n                </div>\n              );\n            })}\n          </div>\n        </div>\n      </>\n    );\n  };\n\n  return (\n    <>\n      <div className=\"custom-ranger-picker\">\n        <RangePicker\n          showTime={{\n            format: \"HH:mm\",\n          }}\n          getPopupContainer={getPopupContainer}\n          format=\"YYYY-MM-DD HH:mm\"\n          separator=\"~\"\n          onCalendarChange={(val, dateStrings, info) => {\n            let _dates = val;\n\n            // 时间选择如果超过14天则清除待选择的日期\n            if (val[1]?.valueOf() - val[0]?.valueOf() > 14 * 24 * 60 * 60 * 1000) {\n              setHackValue([info.range === \"end\" ? null : val[0], info.range === \"start\" ? null : val[1]]);\n              _dates = [info.range === \"end\" ? null : val[0], info.range === \"start\" ? null : val[1]];\n              noNeedChange.current = true;\n            } else {\n              noNeedChange.current = false;\n            }\n            setDates(_dates);\n          }}\n          disabledDate={disabledDate}\n          value={hackValue || rangeTime}\n          onChange={onRangeTimeChange}\n          onOpenChange={onOpenChange}\n          suffixIcon={null}\n        />\n        <Popover\n          visible={open}\n          onVisibleChange={handleOpenChange}\n          overlayClassName=\"custom-popover\"\n          content={renderCustomTimeRange()}\n          getPopupContainer={getPopupContainer}\n          placement=\"bottom\"\n          trigger=\"click\"\n        >\n          <div className=\"custom-btn\">\n            <span className=\"icon iconfont iconriqi1 cal-icon\"></span>\n          </div>\n        </Popover>\n      </div>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/component/UserSelect.tsx",
    "content": "import { Select, Spin } from \"antd\";\nimport debounce from \"lodash/debounce\";\nimport React from \"react\";\nimport { getCookie } from \"lib/utils\";\n\nexport const UserSelect = (props: any) => {\n  const { fetchOptions, setOwnerIdList, targetKeys, ownersList, isNew, list } = props;\n\n  const [fetching, setFetching] = React.useState(false);\n  const [options, setOptions] = React.useState<any[]>(ownersList || []);\n  const [value, setValue] = React.useState(props.value || []);\n\n  const fetchRef = React.useRef(0);\n\n  React.useEffect(() => {\n    if (isNew) {\n      let option = {\n        label: getCookie(\"userName\"),\n        value: Number(getCookie(\"userId\")),\n      };\n      setValue([Number(getCookie(\"userId\"))]);\n      setOptions([option]);\n    }\n  }, [list]);\n\n  React.useEffect(() => {\n    let list = props?.list?.filter((item) => targetKeys?.includes(item.key));\n    let options = (list || []).map((item) => {\n      return {\n        label: item.label,\n        value: item.key,\n      };\n    });\n    let newValue = value.filter((item) => targetKeys?.includes(item));\n    setOptions(options);\n    setValue(newValue);\n    setOwnerIdList(newValue);\n  }, [targetKeys]);\n\n  const debounceFetcher = React.useMemo(() => {\n    const loadOptions = (value: string) => {\n      fetchRef.current += 1;\n      const fetchId = fetchRef.current;\n      setOptions([]);\n      setFetching(true);\n\n      fetchOptions(value).then((res) => {\n        if (fetchId !== fetchRef.current) {\n          // for fetch callback order\n          return;\n        }\n        const newOptions = (res || []).map((item) => ({\n          label: item.userName,\n          value: item.id,\n        }));\n        setOptions(newOptions);\n        setFetching(false);\n      });\n    };\n\n    return debounce(loadOptions, 800);\n  }, [fetchOptions]);\n\n  const handleChange = (values) => {\n    setValue(values);\n    setOwnerIdList(values);\n    props.onChange && props.onChange(values);\n  };\n\n  return (\n    <>\n      <Select\n        value={value}\n        filterOption={(val, option) => {\n          let label = `${option?.label}`;\n          return label?.includes(val);\n        }}\n        notFoundContent={fetching ? <Spin size=\"small\" /> : null}\n        onChange={handleChange}\n        options={options}\n        mode={props.mode}\n        placeholder={props.placeholder || \"\"}\n      />\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/component/dantd/base-detail/base.less",
    "content": ".max-title {\n  font-family: PingFangSC-Medium;\n  font-size: 16px;\n  color: #101724;\n  line-height: 24px;\n}\n\n.middle-title {\n  font-family: PingFangSC-Medium;\n  font-size: 14px;\n  color: #101724;\n  line-height: 24px;\n}\n\n.min-title {\n  font-family: PingFangSC-Medium;\n  font-size: 12px;\n  color: #303a51;\n  line-height: 20px;\n}\n.text-content {\n  font-family: PingFangSC-Regular;\n  font-size: 12px;\n  color: #303a51;\n  line-height: 20px;\n}\n"
  },
  {
    "path": "arius-console/src/component/dantd/base-detail/index.less",
    "content": "@import \"./base.less\";\n.base-info-box {\n  border: 1px solid #dcdfe6;\n  border-radius: 4px;\n  background-color: aliceblue;\n  &-row {\n    &-col {\n      display: flex;\n      &-label {\n        .min-title();\n        height: 40px;\n        line-height: 40px;\n        padding-left: 20px;\n        width: 25%;\n        text-overflow: ellipsis;\n        overflow: hidden;\n        white-space: nowrap;\n      }\n      &-content {\n        .text-content();\n        height: 40px;\n        line-height: 40px;\n      }\n    }\n  }\n  &-activ {\n    background-color: white;\n  }\n}\n.base-info {\n  .base-info-box {\n    background: #f8f9fa;\n    border-radius: 8px;\n    display: flex;\n    justify-content: flex-start;\n    flex-wrap: wrap;\n    padding: 12px 0;\n    &-row-col {\n      width: calc((100% - 20px) / 4);\n      padding-left: 20px;\n      flex-direction: column;\n      &-label {\n        .min-title();\n        width: 100%;\n        height: 40px;\n        padding-left: 0;\n        line-height: 40px;\n        font-family: PingFangSC-Regular;\n        font-size: 14px;\n        color: rgba(0, 0, 0, 0.6);\n      }\n      &-content {\n        .text-content();\n        height: 30px;\n        line-height: 16px;\n        font-size: 14px;\n        color: rgba(0, 0, 0, 0.87);\n      }\n    }\n  }\n}\n\n.base-info-title {\n  .middle-title();\n  border-bottom: 1px solid #dbe0e4;\n  padding-bottom: 8px;\n}\n"
  },
  {
    "path": "arius-console/src/component/dantd/base-detail/index.tsx",
    "content": "import { Col, Row } from \"antd\";\nimport * as React from \"react\";\nimport \"./index.less\";\n\nexport interface IBaseDetail {\n  title?: string | JSX.Element;\n  columns: IItem[][];\n  baseDetail: object;\n}\n\ninterface IItem {\n  label: string;\n  key: string;\n  render?: (value: any) => string | JSX.Element;\n}\n\nexport const BaseDetail = (props: IBaseDetail) => {\n  return (\n    <>\n      {props.title ? <div className=\"base-info-title\">{props.title}</div> : null}\n      <div className=\"base-info-box\">\n        {(props.columns || []).map((items: any, index: number) =>\n          items instanceof Array ? (\n            <Row className={`base-info-box-row ${index % 2 != 0 ? \"base-info-box-activ\" : \"\"}`} key={index + \"row\"}>\n              {items.map((item: IItem, indexC: number) => (\n                <Col span={12} className=\"base-info-box-row-col\" key={indexC + \"col\"}>\n                  <div className=\"base-info-box-row-col-label\">{item?.label}</div>\n                  <div className=\"base-info-box-row-col-content\">\n                    {item?.render ? item.render(props.baseDetail?.[item.key]) : props.baseDetail?.[item.key] ?? \"-\"}\n                  </div>\n                </Col>\n              ))}\n            </Row>\n          ) : (\n            <div className=\"base-info-box-row-col\" key={index + \"col\"}>\n              <div className=\"base-info-box-row-col-label\">{items?.label}：</div>\n              <div className=\"base-info-box-row-col-content\">\n                {items?.render ? items.render(props.baseDetail?.[items.key]) : props.baseDetail?.[items.key] ?? \"-\"}\n              </div>\n            </div>\n          )\n        )}\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/component/dantd/base-detail/readme.md",
    "content": "# BaseTatail\n\n## 何时使用\n\n- 详情展示\n\n## API\n\n| 参数       | 说明 | 类型 | 默认值   |\n| ---------- | ---- | ---- | -------- | ----------- |\n| title      | 标题 | null | string   | JSX.Element |\n| columns    | 配置 | []   | item[][] |\n| baseDetail | 数据 | {}   | objet    |\n\n## Demo\n\n```js\nconst columns = [\n  [\n    {\n      key: \"rack\",\n      label: \"所属rack\",\n    },\n    {\n      key: \"role\",\n      label: \"role\",\n      render: (value: number) => (\n        <>\n          <span>{value}</span>\n        </>\n      ),\n    },\n  ],\n  [\n    {\n      key: \"shard\",\n      label: \"shard\",\n    },\n    {\n      key: \"createTime\",\n      label: \"创建时间\",\n      render: (value: string) => <>{moment(value).format(timeFormat)}</>,\n    },\n  ],\n];\n```\n"
  },
  {
    "path": "arius-console/src/component/dantd/dtable/index.less",
    "content": ".d-table {\n  .d-table-box {\n    padding: 0 !important;\n\n    &-header {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      padding: 0 !important;\n\n      .table-op-btn {\n        padding-bottom: 10px;\n\n        Button {\n          margin-right: 10px;\n        }\n\n        .reload {\n          width: 32px;\n          height: 32px;\n          line-height: 32px;\n          vertical-align: top;\n          border: 1px solid #dbe0e4;\n          border-radius: 2px;\n          margin-right: 10px;\n        }\n\n        .reload:hover {\n          color: @primary-color;\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/component/dantd/dtable/index.tsx",
    "content": "import React from \"react\";\nimport \"@ant-design/compatible/assets/index.css\";\nimport { Input, Button, Table, Tooltip } from \"antd\";\nimport \"./index.less\";\nimport { pagination } from \"constants/table\";\nimport { ReloadOutlined } from \"@ant-design/icons\";\nimport { openSourceTip } from \"constants/status-map\";\nimport { cloneDeep } from \"lodash\";\n\nexport interface ITableBtn {\n  clickFunc?: (...args: any[]) => void;\n  isRouterNav?: boolean;\n  label: string | JSX.Element;\n  className?: string;\n  needConfirm?: boolean;\n  aHref?: string;\n  confirmText?: string;\n  noRefresh?: boolean;\n  loading?: boolean;\n  disabled?: boolean;\n  invisible?: boolean; // 不可见\n  isOpenUp?: boolean;\n  tip?: string | JSX.Element;\n  history?: { [key: string]: any };\n}\ninterface ISearchInput {\n  placeholder?: string;\n  submit: (params?: any) => any;\n  text?: string;\n  style?: object;\n}\n\ninterface IDTableProps {\n  paginationProps?: object;\n  rowKey: string;\n  columns: object[];\n  dataSource: object[];\n  loading?: boolean;\n  reloadData?: (params?: object) => any;\n  getOpBtns?: (params?: object) => ITableBtn[];\n  renderInnerOperation?: (params?: object) => JSX.Element;\n  tableHeaderSearchInput?: ISearchInput;\n  attrs?: object;\n}\n\nexport const DTable = (props: IDTableProps) => {\n  const renderSearch = () => {\n    if (!props?.tableHeaderSearchInput) return;\n    const Search = Input.Search;\n    const { placeholder = null, submit, text, style } = props?.tableHeaderSearchInput;\n    return (\n      <div>\n        <span>{text}</span>\n        <Search\n          allowClear\n          className=\"d-table-search\"\n          placeholder={placeholder || \"请输入关键字\"}\n          onSearch={submit}\n          style={style || { width: 200, paddingBottom: 10 }}\n        />\n      </div>\n    );\n  };\n\n  const renderTableInnerOp = (reloadFunc: any, btns?: ITableBtn[], element?: JSX.Element) => {\n    return (\n      <div className=\"table-op-btn\">\n        {reloadFunc && <ReloadOutlined className=\"reload\" onClick={reloadFunc} />}\n        {btns?.map((item, index) => {\n          if (item.isOpenUp) {\n            return (\n              <Tooltip key={index} title={openSourceTip}>\n                <Button disabled={true}> {item.label} </Button>\n              </Tooltip>\n            );\n          }\n          return item.noRefresh ? (\n            <Button className={item.className} key={index}>\n              {item.label}\n            </Button>\n          ) : (\n            <Button disabled={item.disabled} loading={item.loading} key={index} className={item.className} onClick={item.clickFunc}>\n              {\" \"}\n              {item.label}{\" \"}\n            </Button>\n          );\n        })}\n        {element}\n      </div>\n    );\n  };\n\n  const renderColumns = () => {\n    return props.columns?.map((columnItem: any) => {\n      const currentItem = cloneDeep(columnItem);\n      return {\n        ...currentItem,\n        render: (...args) => {\n          const value = args[0];\n          const renderData = currentItem.render\n            ? currentItem.render(...args)\n            : value === \"\" || value === null || value === undefined\n            ? \"-\"\n            : typeof (value === Boolean)\n            ? value + \"\"\n            : value;\n          return renderData;\n        },\n      };\n    });\n  };\n\n  const {\n    rowKey,\n    loading,\n    dataSource,\n    paginationProps = pagination,\n    reloadData,\n    getOpBtns = () => null,\n    renderInnerOperation = () => null,\n    attrs,\n  } = props;\n\n  return (\n    <>\n      <div className=\"d-table\">\n        <div className=\"d-table-box\">\n          <div className=\"d-table-box-header\">\n            {renderTableInnerOp(reloadData, getOpBtns(), renderInnerOperation())}\n            {renderSearch()}\n          </div>\n          <Table\n            loading={loading}\n            rowKey={rowKey}\n            dataSource={dataSource}\n            columns={renderColumns()}\n            pagination={{ ...pagination, ...paginationProps } as any}\n            {...attrs}\n          />\n        </div>\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/component/dantd/dtable/readme.md",
    "content": "# dtable\n\n## 何时使用 \n\n- 当有大量结构化的数据需要展现时；\n- 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。  \n\n## API\n\n| 参数                   | 说明                                                         | 类型                                                         | 默认值     |\n| ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ---------- |\n| paginationProps        | 分页器，参考[配置项](https://ant.design/components/table-cn/#pagination)或 [pagination](https://ant.design/components/pagination-cn/) 文档，设为 false 时不展示和进行分页 | object                                                       |            |\n| rowKey                 | 表格行 key 的取值，可以是字符串或一个函数(必填)              | string \\|function(record): string                            | key        |\n| columns                | 表格列的配置描述，具体项见下表(必填)                         | [ColumnsType](https://ant.design/components/table-cn/#Column)[] |            |\n| dataSource             | 数据数组(必填)                                               | object[]                                                     |            |\n| loading                | 页面是否加载中                                               | boolean \\| [Spin Props](https://ant.design/components/spin-cn/#API) | false      |\n| attrs                  | Table 其他的的一些扩展属性，参考 [Table API](https://ant.design/components/table-cn/#API) | object                                                       |            |\n| reloadData             | 点击刷新图标后执行的函数(必填)                               | (params?: object) => any                                     |            |\n| getOpBtns              | 需要显示的功能按钮                                           | (params?: object) => ITableBtn[];                            | () => null |\n| renderInnerOperation   | 自定义的 JSX 元素                                            | (params?: object) => JSX.Element                             | () => null |\n| tableHeaderSearchInput | 如果存在显示搜索框                                           | ISearchInput                     |            |\n\n## paginationProps\n\n分页的配置项\n\n| 参数     | 说明                                                         | 类型  | 默认值          |\n| -------- | ------------------------------------------------------------ | ----- | --------------- |\n| position | 指定分页显示的位置， 取值为指定分页显示的位置， 取值为`topLeft` |`topCenter` |`topRight` |`bottomLeft` |`bottomCenter` |`bottomRight` | Array | [`bottomRight`] |\n\n## ITableBtn\n\n| 参数       | 说明                                                      | 类型                 | 默认值 |\n| ---------- | --------------------------------------------------------- | -------------------- | ------ |\n| label      | 按钮中显示的文字                                          | string \\|JSX.Element |        |\n| isOpenUp   | 如果为 true 直接返回带有文字提示的禁用按钮                | boolean              |        |\n| className  | 如果 isOpenUp 为 false 是按钮的类名                       | string               |        |\n| noRefresh  | 如果为 false 返回带有点击事件、loading 和 disabled 的按钮 | boolean              |        |\n| disabled   | 如果 noRefresh 为 false 时生效，是否禁用按钮              | boolean              |        |\n| loading    | 如果 noRefresh 为 false 时生效，是否开启loading效果       | boolean              |        |\n| iclickFunc | 如果 noRefresh 为 false 时生效，是否开启loading效果       | () =>void            |        |\n\n## ISearchInput\n\n| 参数        | 说明                                               | 类型                     | 默认值       |\n| ----------- | -------------------------------------------------- | ------------------------ | ------------ |\n| submit      | 点击搜索图标、清除图标，或按下回车键时的回调(必填) | (params?: any) => any |              |\n| text        | 搜索框描述                                         | string                   |              |\n| placeholder | 属性提供可描述输入字段预期值的提示信息             | string                   | 请输入关键字 |\n\n"
  },
  {
    "path": "arius-console/src/component/dantd/index.tsx",
    "content": ""
  },
  {
    "path": "arius-console/src/component/dantd/query-form/QueryForm.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport classNames from \"classnames\";\nimport { ConfigProviderProps } from \"antd/es/config-provider\";\nimport useAntdMediaQuery from \"./use-media-antd-query\";\nimport { Button, Input, Form, Row, Col, Select, ConfigProvider, DatePicker, TimePicker } from \"antd\";\nimport { DownOutlined } from \"@ant-design/icons\";\n\nimport { useContext } from \"react\";\nimport IntlContext from \"./context\";\n\nconst { RangePicker: DateRangePicker } = DatePicker;\nconst { RangePicker: TimeRangePicker } = TimePicker;\n\nfunction useIntl(): any {\n  const i18n = useContext(IntlContext);\n  return i18n;\n}\n\ndeclare const ItemSizes: [\"large\", \"default\", \"small\", string];\nexport declare type ItemSize = typeof ItemSizes[number];\n\ndeclare const ColumnTypes: [\"select\", \"input\", \"datePicker\", \"dateRangePicker\", \"timePicker\", \"timeRangePicker\", \"custom\", string];\nexport declare type ColumnType = typeof ColumnTypes[number];\n\ndeclare const ModeTypes: [\"full\", \"align\", string];\nexport declare type ModeType = typeof ModeTypes[number];\n\ndeclare const ColTypes: [\"grid\", \"style\", string];\nexport declare type ColType = typeof ColTypes[number];\n\nconst FormItem = Form.Item;\nconst { Option } = Select;\n\nexport interface IColumnsType {\n  type: ColumnType;\n  dataIndex: string;\n  title: string | React.ReactNode;\n  placeholder?: string | string[];\n  valuePropName?: string;\n  required?: boolean;\n  colStyle?: React.CSSProperties;\n  isInputPressEnterCallSearch?: boolean;\n  size?: ItemSize;\n  rules?: any[]; // 校验规则\n  component?: React.ReactNode;\n  componentProps?: any; // 需要传给组件的其他属性\n  selectMode?: string; // 单选或者多选\n  options?: {\n    title: string;\n    value: string | number;\n  }[];\n  formItemLayout?: any;\n}\nexport interface FieldData {\n  name?: string;\n  level?: string;\n  status?: string[];\n  number?: Number;\n}\n\nexport interface IQueryFormProps {\n  onCollapse?: () => void;\n  prefixCls?: string;\n  className?: string;\n  style?: React.CSSProperties | any;\n  mode?: ModeType;\n  colMode?: ColType;\n  defaultColStyle?: React.CSSProperties;\n  columnStyleHideNumber?: number;\n  columns: IColumnsType[];\n  searchText?: string | React.ReactNode;\n  resetText?: string | React.ReactNode;\n  showOptionBtns?: boolean;\n  showCollapseButton?: boolean;\n  onChange?: (data: any) => any;\n  initialValues?: any;\n  onSearch?: (data: any) => any;\n  onReset?: (data: any) => any;\n  getFormInstance?: (form: any) => any;\n  isResetClearAll?: boolean;\n  isTrimOnSearch?: boolean;\n  antConfig?: ConfigProviderProps;\n  defaultCollapse?: boolean;\n  colConfig?:\n    | {\n        lg: number;\n        md: number;\n        xxl: number;\n        xl: number;\n        sm: number;\n        xs: number;\n      }\n    | undefined;\n}\n\nconst defaultColConfig = {\n  xs: 24,\n  sm: 24,\n  md: 12,\n  lg: 12,\n  xl: 8,\n  xxl: 6,\n};\n\nconst defaultFormItemLayout = {\n  labelCol: {\n    xs: { span: 5 },\n    sm: { span: 5 },\n    md: { span: 7 },\n    lg: { span: 7 },\n    xl: { span: 8 },\n    xxl: { span: 8 },\n  },\n  wrapperCol: {\n    xs: { span: 19 },\n    sm: { span: 19 },\n    md: { span: 17 },\n    lg: { span: 17 },\n    xl: { span: 16 },\n    xxl: { span: 16 },\n  },\n};\n\n/**\n * 合并用户和默认的配置\n * @param span\n * @param size\n */\nconst getSpanConfig = (span: number | typeof defaultColConfig, size: keyof typeof defaultColConfig): number => {\n  if (typeof span === \"number\") {\n    return span;\n  }\n  const config = {\n    ...defaultColConfig,\n    ...span,\n  };\n  return config[size];\n};\n\n/**\n * 获取最后一行的 offset，保证在最后一列\n * @param length\n * @param span\n */\nconst getOffset = (length: number, span: number = 8) => {\n  const cols = 24 / span;\n  return (cols - 1 - (length % cols)) * span;\n};\n\nconst getCollapseHideNum = (size: number) => {\n  const maps = {\n    6: 3,\n    8: 2,\n    12: 1,\n    24: 1,\n  } as { [key: number]: number };\n\n  return maps[size] || 1;\n};\n\nconst QueryForm = (props: IQueryFormProps) => {\n  const prefixCls = `${props.prefixCls || \"dantd\"}-query-form`;\n  const { t } = useIntl();\n  const {\n    onCollapse,\n    className,\n    style,\n    colConfig,\n    searchText,\n    resetText,\n    showOptionBtns = true,\n    showCollapseButton = true,\n    defaultCollapse = false,\n    isResetClearAll = false,\n    isTrimOnSearch = true,\n    onChange,\n    onSearch,\n    onReset,\n    getFormInstance,\n    columns = [] as IColumnsType[],\n    mode = \"full\",\n    colMode = \"grid\",\n    columnStyleHideNumber = 1,\n    defaultColStyle = {\n      width: \"300px\",\n    },\n    initialValues,\n    // valueType = 'object',\n  } = props;\n  const [form] = Form.useForm();\n  const wrapperClassName = classNames(prefixCls, className);\n  const formItemCls = classNames({\n    [`${prefixCls}-formitem`]: true,\n    [`${prefixCls}-formitem-full`]: mode === \"full\",\n  });\n  const windowSize = useAntdMediaQuery();\n  const itemColConfig = colConfig || defaultColConfig;\n  const [colSize, setColSize] = useState(getSpanConfig(itemColConfig || 8, windowSize));\n  const { validateFields, getFieldsValue, resetFields, setFieldsValue } = form;\n\n  const [collapsed, setCollapse] = useState(defaultCollapse);\n  const [isShowCollapseButton, setIsShowCollapseButton] = useState(true);\n\n  useEffect(() => {\n    setColSize(getSpanConfig(itemColConfig || 8, windowSize));\n    if (columns.length <= getCollapseHideNum(getSpanConfig(itemColConfig || 8, windowSize))) {\n      setIsShowCollapseButton(false);\n    } else {\n      setIsShowCollapseButton(true);\n    }\n  }, [windowSize]);\n\n  useEffect(() => {\n    if (getFormInstance) {\n      getFormInstance(form);\n    }\n  }, []);\n\n  const collapseHideNum = getCollapseHideNum(getSpanConfig(itemColConfig || 8, windowSize));\n\n  const handleSearch = () => {\n    validateFields()\n      .then((values) => {\n        if (onSearch) {\n          isTrimOnSearch ? handleTrimSearch(values) : onSearch(values);\n        }\n      })\n      .catch(() => {\n        //\n      });\n  };\n\n  const handleTrimSearch = (values = {}) => {\n    const data = {};\n    Object.keys(values).forEach((key) => {\n      if (typeof values[key] === \"string\") {\n        data[key] = values[key].trim();\n      } else {\n        data[key] = values[key];\n      }\n    });\n    onSearch(data);\n  };\n\n  const handleReset = () => {\n    if (isResetClearAll) {\n      const resetFieldsObj = columns.reduce((acc, cur: IColumnsType) => {\n        return {\n          ...acc,\n          [cur.dataIndex]: undefined,\n        };\n      }, {});\n      setFieldsValue(resetFieldsObj);\n      (onChange as any)?.(initialValues);\n    } else {\n      resetFields();\n      (onChange as any)?.({});\n    }\n\n    setTimeout(() => {\n      if (onReset) {\n        onReset(getFieldsValue());\n      }\n    });\n  };\n\n  const handlePressEnter = () => {\n    handleSearch();\n  };\n\n  const renderInputItem = (colItem: any) => {\n    const {\n      dataIndex,\n      title,\n      required,\n      componentProps = {},\n      placeholder,\n      isInputPressEnterCallSearch = true,\n      formItemLayout,\n      rules,\n      size = \"default\",\n    } = colItem;\n\n    const itemPlaceholder = placeholder ? placeholder : t(\"form.placeholder.prefix\");\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n    return (\n      <FormItem\n        shouldUpdate={true}\n        key=\"input\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        <Input\n          data-testid=\"field-input\"\n          size={size}\n          placeholder={itemPlaceholder}\n          onPressEnter={isInputPressEnterCallSearch ? handlePressEnter : () => {}}\n          allowClear\n          {...componentProps}\n        />\n      </FormItem>\n    );\n  };\n\n  const renderSelectItem = (colItem: any) => {\n    const {\n      dataIndex,\n      title,\n      required,\n      placeholder,\n      selectMode = \"single\",\n      rules,\n      formItemLayout,\n      options = [],\n      componentProps = {},\n      size = \"default\",\n      isSelectPressEnterCallSearch = true,\n    } = colItem;\n    const itemPlaceholder = placeholder ? (\n      placeholder\n    ) : (\n      <>\n        {t(\"form.selectplaceholder.prefix\")}\n        &nbsp;\n        {title}\n      </>\n    );\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n    const handlePressEnter = (e) => {\n      if (e.keyCode === 13) {\n        handleSearch();\n      }\n    };\n    return (\n      <FormItem\n        key=\"select\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        <Select\n          data-testid=\"select\"\n          mode={selectMode}\n          size={size}\n          allowClear\n          placeholder={itemPlaceholder}\n          showSearch={true}\n          optionFilterProp=\"children\"\n          className=\"form-item-style\"\n          style={{ width: \"100%\" }}\n          onInputKeyDown={isSelectPressEnterCallSearch ? handlePressEnter : () => {}}\n          filterOption={(val, option) => {\n            return option.children.includes(val.trim());\n          }}\n          {...componentProps}\n        >\n          {options.map((option: any) => {\n            return (\n              <Option data-testid=\"select-option\" value={option.value} key={option.value}>\n                {option.title}\n              </Option>\n            );\n          })}\n        </Select>\n      </FormItem>\n    );\n  };\n\n  const renderDateItem = (colItem: any) => {\n    const { dataIndex, title, required, componentProps = {}, placeholder, formItemLayout, rules, size = \"default\", type } = colItem;\n\n    const itemPlaceholder = placeholder ? placeholder : t(\"form.placeholder.prefix\");\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n    return (\n      <FormItem\n        shouldUpdate={true}\n        key=\"date\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        {type === \"dateRangePicker\" ? (\n          <DateRangePicker\n            data-testid=\"dateRangePicker\"\n            size={size}\n            allowClear\n            showTime\n            placeholder={itemPlaceholder}\n            style={{ width: \"100%\" }}\n            {...componentProps}\n          />\n        ) : (\n          <DatePicker\n            data-testid=\"datePicker\"\n            size={size}\n            allowClear\n            placeholder={itemPlaceholder}\n            style={{ width: \"100%\" }}\n            {...componentProps}\n          ></DatePicker>\n        )}\n      </FormItem>\n    );\n  };\n\n  const renderTimeItem = (colItem: any) => {\n    const { dataIndex, title, required, componentProps = {}, placeholder, formItemLayout, rules, size = \"default\", type } = colItem;\n\n    const itemPlaceholder = placeholder ? placeholder : t(\"form.placeholder.prefix\");\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n    return (\n      <FormItem\n        shouldUpdate={true}\n        key=\"date\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        {type === \"timeRangePicker\" ? (\n          <TimeRangePicker\n            data-testid=\"timerRangePicker\"\n            size={size}\n            allowClear\n            showTime\n            placeholder={itemPlaceholder}\n            style={{ width: \"100%\" }}\n            {...componentProps}\n          />\n        ) : (\n          <TimePicker\n            data-testid=\"timePicker\"\n            size={size}\n            allowClear\n            placeholder={itemPlaceholder}\n            style={{ width: \"100%\" }}\n            {...componentProps}\n          ></TimePicker>\n        )}\n      </FormItem>\n    );\n  };\n\n  const renderCustomItem = (colItem: any) => {\n    const { formItemLayout, dataIndex, title, required, placeholder, rules, valuePropName = \"value\", component } = colItem;\n\n    const itemPlaceholder = placeholder ? (\n      placeholder\n    ) : (\n      <>\n        {t(\"form.placeholder.prefix\")}\n        &nbsp;\n        {title}\n      </>\n    );\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n\n    return (\n      <FormItem\n        key=\"custom\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        valuePropName={valuePropName}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        {component}\n      </FormItem>\n    );\n  };\n  const renderOptionBtns = () => {\n    const offsetVal = collapsed\n      ? columns.length <= collapseHideNum\n        ? getOffset(columns.length, colSize)\n        : getOffset(collapseHideNum, colSize)\n      : getOffset(columns.length, colSize);\n    let optionStyle = {};\n    if (colMode === \"style\") {\n      optionStyle = {\n        position: \"absolute\",\n        width: 280,\n        bottom: 0,\n        right: 0,\n        marginLeft: 0,\n      };\n    }\n    return (\n      <Col\n        {...itemColConfig}\n        offset={offsetVal}\n        key=\"option\"\n        className={`${prefixCls}-option`}\n        style={{\n          display: \"flex\",\n          alignItems: \"flex-end\",\n          marginLeft: 0,\n          ...optionStyle,\n        }}\n      >\n        <Form.Item key=\"option\">\n          <span>\n            <Button onClick={handleReset}>{resetText || t(\"queryform.reset\")}</Button>\n            <Button onClick={handleSearch} style={{ marginLeft: 10 }} type=\"primary\" htmlType=\"submit\">\n              {searchText || t(\"queryform.search\")}\n            </Button>\n            {isShowCollapseButton && showCollapseButton && (\n              <a\n                className=\"collapsed-style\"\n                onClick={() => {\n                  onCollapse ? onCollapse() : setCollapse(!collapsed);\n                }}\n              >\n                {collapsed ? \"展开\" : \"收起\"}\n                <DownOutlined\n                  style={{\n                    marginLeft: \"0.5em\",\n                    transition: \"0.3s all\",\n                    transform: `rotate(${collapsed ? 0 : 0.5}turn)`,\n                  }}\n                />\n              </a>\n            )}\n          </span>\n        </Form.Item>\n      </Col>\n    );\n  };\n\n  return (\n    <ConfigProvider {...props.antConfig}>\n      <div className={wrapperClassName} style={style}>\n        <Row gutter={24} justify=\"start\">\n          {columns.map((colItem, colIndex) => {\n            let itemHide = collapsed && collapseHideNum <= colIndex;\n            let colItemStyle = {};\n            if (colMode === \"style\") {\n              colItemStyle = colItem.colStyle || defaultColStyle;\n              if (collapsed && colIndex >= columnStyleHideNumber) {\n                itemHide = true;\n              }\n            }\n            colItemStyle = {\n              ...colItemStyle,\n              display: itemHide ? \"none\" : \"block\",\n            };\n            return (\n              <Col style={colItemStyle} key={`query-form-col-${colItem.dataIndex}-${colIndex}`} {...itemColConfig}>\n                <Form\n                  form={form}\n                  onFieldsChange={(_changedFields, allFields) => {\n                    (onChange as any)?.(allFields);\n                  }}\n                  initialValues={initialValues}\n                  layout=\"vertical\"\n                >\n                  {colItem.type === \"input\" && renderInputItem(colItem)}\n                  {colItem.type === \"select\" && renderSelectItem(colItem)}\n                  {colItem.type === \"datePicker\" && renderDateItem(colItem)}\n                  {colItem.type === \"dateRangePicker\" && renderDateItem(colItem)}\n                  {colItem.type === \"timePicker\" && renderTimeItem(colItem)}\n                  {colItem.type === \"timeRangePicker\" && renderTimeItem(colItem)}\n                  {colItem.type === \"custom\" && renderCustomItem(colItem)}\n                </Form>\n              </Col>\n            );\n          })}\n          {showOptionBtns && renderOptionBtns()}\n        </Row>\n      </div>\n    </ConfigProvider>\n  );\n};\n\nexport default QueryForm;\n"
  },
  {
    "path": "arius-console/src/component/dantd/query-form/context.tsx",
    "content": "import { createContext } from 'react';\n\ninterface IContextProps {\n  t: (key: any) => any;\n}\n\n\nconst IntlContext = createContext<IContextProps>({\n  t: (key) => '展开',\n});\n\nexport default IntlContext;\n"
  },
  {
    "path": "arius-console/src/component/dantd/query-form/index.tsx",
    "content": "import './style/index.less';\nimport QueryForm from './QueryForm';\nexport default QueryForm;\n"
  },
  {
    "path": "arius-console/src/component/dantd/query-form/readme.md",
    "content": "# query-form\n\n## 何时使用\n\n需要一个数据查询组件时使用，组件会自己管理状态并返回查询的数据。\n\n## API\n\n\n### QueryForm\n\n| 参数       | 说明           | 类型                | 默认值 |\n| :--------- | :------------- | :------------------ | :----- |\n| columns | 表单列的配置描述，具体项见下表（必填） | ColumnProps | []     |\n| initialValues | 表单默认值，只有初始化时生效 | object | -     |\n| searchText | 搜索按钮的文案 | string \\| React.ReactNode | 查询     |\n| resetText | 重置按钮的文案 | string \\| React.ReactNode | 重置     |\n| mode      | `FormItem` 的标题展示模式，`full`是占满整行，左对齐； `align` 会根据标题右对齐 | `['full', 'align']`              | `'full'`     |\n| colMode      | `FormItem` 的展示模式，`grid`是等分的栅格布局； `style` 会根据会对每个 `Col` 增加固定 `300px` 的宽度，也可以通过 `Column.colStyle` 自定义宽度等样式 | `['grid', 'style']`              | `'grid'`     |\n| showOptionBtns | 是否展示右下角的「查询」「重置」按钮，以及「展开」「收起」 | boolean | true      |\n| showCollapseButton | 是否展示右下角的「展开」「收起」 | boolean | true     |\n| onChange | 表单的值改变时触发的回调 | Function(values, form) | - |\n| onSearch | 点击查询按钮的回调 | Function(values, form) | - |\n| onReset | 点击重置按钮的回调 | Function(form) | - |\n| isResetClearAll | 点击重置时，是清空form里面的值，还是根据 `initialValue` 重置 | boolean | false     |\n| getFormInstance | 只用来获取Form实例的回调 | Function(form) | - |\n| defaultCollapse | 是否默认「展开」 | boolean | true     |\n| colConfig | Col 布局配置 | `{lg:number;md:number;xxl:number;xl:number;sm:number;xs:number}` | `{xs:24,sm:24,md:12,lg:12,xl:8,xxl:6}` |\n| antConfig | 使用 `Antd ConfigProvider` 进行的全局配置，需要通过这个属性传进来 | [ConfigProviderProps](https://github.com/ant-design/ant-design/blob/master/components/config-provider/index.tsx) | - |\n\n### Columns\n\n表单列的配置描述，目前支持 `['input', 'select', 'custom']` 这三种。\n\n| 参数       | 说明           | 类型                | 默认值 |\n| :--------- | :------------- | :------------------ | :----- |\n| type      | 动态表单组件的类型，内置 `input`, `select`；也可以自定义  | `['input', 'select', 'custom']`              | -      |\n| title      | 标题    | string              |  -      |\n| dataIndex      | form表单的唯一标识，不可以重复   | string              |  -      |\n| placeholder | 占位文案，默认会根据 `title` 自动生成 | string | -     |\n| isInputPressEnterCallSearch | 输入框按回车的时候，触发搜索 | boolean | -     |\n| valuePropName | 子节点的值的属性，如 Switch 的是 'checked' | string | 'value'    |\n| required | 是否对参数进行必填校验 | boolean | true      |\n| colStyle | `colMode='style'` 时，可以设置单个 `Column` 的样式| `React.CSSProperties` | -      |\n| columnStyleHideNumber | `colMode='style'` 时，收起时默认只展示一项，可以设置展示多项| number | 1      |\n| formItemLayout | 表单的Layout | `{labelCol:{xs:{span:number},sm:{span:number},md:{span:number},lg:{span:number},xl:{span:number},xxl:{span:number}},wrapperCol:{xs:{span:number},sm:{span:number},md:{span:number},lg:{span:number},xl:{span:number},xxl:{span:number}}}` | `{labelCol:{xs:{span:5},sm:{span:5},md:{span:7},lg:{span:7},xl:{span:8},xxl:{span:8},},wrapperCol:{xs:{span:19},sm:{span:19},md:{span:17},lg:{span:17},xl:{span:16},xxl:{span:16},},}`     |\n| rules | 自定义表单项的校验规则 | `object[]` | -      |\n| size | 表单项的 `size` 属性 | `large` \\| `default` \\| `small` | `default`   |\n| componentProps | `type=\"input|select\"` 时，可以通过该属性 ant 组件的Props | any | -      |\n| component | `type=\"custom\"` 时，可以通过该属性传递 `React.ReactNode` |  React.ReactNode | -      |\n| selectMode | `type=\"select\"` 时的 `mode` 属性 | `default` \\| `multiple` | `default`      |\n| options | `type=\"select\"` 时，通过该属性设置下拉选项 | {title: string;value: string;}[] | []      |\n\n## Demo\n\n```js\nimport { useState } from 'react';\nimport { QueryForm, InputNumber, Card, Button, Modal } from 'antd-advanced';\n\n\nconst columns = [\n  {\n    type: 'input',\n    title: '实例名称',\n    dataIndex: 'name',\n  },\n  {\n    type: 'select',\n    title: '报警等级',\n    dataIndex: 'level',\n    options: [\n      {\n        title: '全部',\n        value: 'all',\n      },\n      {\n        title: 'P0',\n        value: 'p0',\n      },\n      {\n        title: 'P1',\n        value: 'p1',\n      },\n      {\n        title: 'P2',\n        value: 'p2',\n      },\n    ],\n  },\n  {\n    type: 'select',\n    title: '任务状态',\n    dataIndex: 'status',\n    selectMode: 'multiple',\n    options: [\n      {\n        title: '进行中',\n        value: 'processing',\n      },\n      {\n        title: '成功',\n        value: 'success',\n      },\n      {\n        title: '失败',\n        value: 'fail',\n      },\n    ],\n  },\n  {\n    type: 'custom',\n    title: '机器数量',\n    dataIndex: 'number',\n    component: (\n      <InputNumber\n        placeholder=\"请输入机器数量\"\n        style={{ marginTop: 4, width: '100%' }}\n        min={0}\n        precision={0}\n      />\n    ),\n  },\n];\n\nconst Demo: React.FC = () => {\n  const initialValues = {\n    name: 'test',\n    level: 'p1',\n  }\n  const [result, setResult] = useState(initialValues);\n  const [isModalVisible, setIsModalVisible] = useState(false);\n\n  const showModal = () => {\n    setIsModalVisible(true);\n  };\n\n  const handleOk = () => {\n    setIsModalVisible(false);\n  };\n\n  const handleCancel = () => {\n    setIsModalVisible(false);\n  };\n  const handleChange = queryValue => {\n    setResult(queryValue);\n  };\n  return (\n    <div>\n      <QueryForm \n        onChange={handleChange} \n        onSearch={handleChange}\n        columns={columns} \n        initialValues={initialValues}\n      />\n      <h3>结果：</h3>\n      <div>{JSON.stringify(result)}</div>\n\n      <Card>\n        <Button type=\"primary\" onClick={showModal}>\n          Open Modal\n        </Button>\n        <Modal title=\"Basic Modal\" visible={isModalVisible} onOk={handleOk} onCancel={handleCancel}>\n          <p>Some contents...</p>\n          <p>Some contents...</p>\n          <p>Some contents...</p>\n        </Modal>\n      </Card>\n    </div>\n  );\n}\n\nReactDOM.render(\n  <div>\n    <Demo />\n  </div>,\n  mountNode,\n);\n```"
  },
  {
    "path": "arius-console/src/component/dantd/query-form/style/index.less",
    "content": ".dantd-query-form {\n  padding: 20px 20px 0 20px;\n}\n\n.collapsed-style{\n  margin-left: 10px;\n  display: inline-block;\n}\n"
  },
  {
    "path": "arius-console/src/component/dantd/query-form/style/index.tsx",
    "content": "import './index.less';\n"
  },
  {
    "path": "arius-console/src/component/dantd/query-form/use-media-antd-query.ts",
    "content": "import { useState, useEffect } from 'react';\nimport useMediaQuery from './use-media';\n\nexport const MediaQueryEnum = {\n  xs: '(max-width: 575px)',\n  sm: '(min-width: 576px) and (max-width: 767px)',\n  md: '(min-width: 768px) and (max-width: 991px)',\n  lg: '(min-width: 992px) and (max-width: 1199px)',\n  xl: '(min-width: 1200px) and (max-width: 1599px)',\n  xxl: '(min-width: 1600px)',\n};\n\nexport type MediaQueryKey = keyof typeof MediaQueryEnum;\n\n/**\n * loop query screen className\n * Array.find will throw a error\n * `Rendered more hooks than during the previous render.`\n * So should use Array.forEach\n */\nexport const getScreenClassName = () => {\n  let className: MediaQueryKey = 'md';\n  // support ssr\n  if (typeof window === 'undefined') {\n    return className;\n  }\n  const mediaQueryKey = (Object.keys(MediaQueryEnum) as MediaQueryKey[]).find((key) => {\n    const matchMedia = MediaQueryEnum[key];\n    if (window.matchMedia(matchMedia).matches) {\n      return true;\n    }\n    return false;\n  });\n  className = (mediaQueryKey as unknown) as MediaQueryKey;\n  return className;\n};\n\nconst useMedia = () => {\n  const isMd = useMediaQuery(MediaQueryEnum.md);\n  const isLg = useMediaQuery(MediaQueryEnum.lg);\n  const isXxl = useMediaQuery(MediaQueryEnum.xxl);\n  const isXl = useMediaQuery(MediaQueryEnum.xl);\n  const isSm = useMediaQuery(MediaQueryEnum.sm);\n  const isXs = useMediaQuery(MediaQueryEnum.xs);\n  const [colSpan, setColSpan] = useState<keyof typeof MediaQueryEnum>(getScreenClassName());\n\n  useEffect(() => {\n    if (isXxl) {\n      setColSpan('xxl');\n      return;\n    }\n    if (isXl) {\n      setColSpan('xl');\n      return;\n    }\n    if (isLg) {\n      setColSpan('lg');\n      return;\n    }\n    if (isMd) {\n      setColSpan('md');\n      return;\n    }\n    if (isSm) {\n      setColSpan('sm');\n      return;\n    }\n    if (isXs) {\n      setColSpan('xs');\n      return;\n    }\n    setColSpan('md');\n  }, [isMd, isLg, isXxl, isXl, isSm, isXs]);\n\n  return colSpan;\n};\n\nexport default useMedia;\n"
  },
  {
    "path": "arius-console/src/component/dantd/query-form/use-media.ts",
    "content": "import { useEffect, useState } from 'react';\n\nexport const isClient = typeof window === 'object';\n\nconst useMedia = (query: string, defaultState: boolean = false) => {\n  const [state, setState] = useState(\n    isClient ? () => window.matchMedia(query).matches : defaultState,\n  );\n\n  useEffect(() => {\n    let mounted = true;\n    const mql = window.matchMedia(query);\n    const onChange = () => {\n      if (!mounted) {\n        return;\n      }\n      setState(!!mql.matches);\n    };\n\n    mql.addListener(onChange);\n    setState(mql.matches);\n\n    return () => {\n      mounted = false;\n      mql.removeListener(onChange);\n    };\n  }, [query]);\n\n  return state;\n};\n\nexport default useMedia;\n"
  },
  {
    "path": "arius-console/src/component/expand-card/index.less",
    "content": ".card-wrapper {\n  margin: 24px 0 32px;\n}\n.card-title {\n  font-family: PingFangSC-Medium;\n  font-size: 14px;\n  color: #333333;\n  height: 22px;\n  line-height: 22px;\n  margin: 15px 0;\n  display: flex;\n  align-items: center;\n  cursor: pointer;\n  i {\n    font-size: 14px;\n    margin-right: 8px;\n  }\n}\n.card-content {\n  background-color: #FAFAFA;\n  padding: 16px;\n  overflow: auto;\n  .chart-row {\n    overflow: hidden;\n    width: 100%;\n  }\n  .chart-row:not(:first-child) {\n    margin-top: 16px;\n  }\n  .chart-wrapper {\n    background-color: #FFFFFF;\n    width: calc(50% - 8px);\n    float: left;\n    padding: 16px;\n  }\n  .chart-wrapper:nth-child(2n) {\n    margin-left: 16px;\n  }\n}"
  },
  {
    "path": "arius-console/src/component/expand-card/index.tsx",
    "content": "import Icon from '@ant-design/icons';\nimport React from 'react';\nimport './index.less';\n\ninterface ICardProps {\n  title: string;\n  expand?: boolean;\n  charts?: JSX.Element[];\n  noTitle?: boolean;\n}\n\nexport class ExpandCard extends React.Component<ICardProps> {\n  public state = {\n    innerExpand: true,\n  };\n\n  public handleClick = () => {\n    this.setState({ innerExpand: !this.state.innerExpand });\n  }\n\n  public render() {\n    let { expand } = this.props;\n    const { noTitle } = this.props;\n    if (expand === undefined) expand = this.state.innerExpand;\n    const { charts } = this.props;\n    return (\n      <div className=\"card-wrapper\">\n        {!noTitle ? <div className=\"card-title\" onClick={this.handleClick}>\n          <Icon type={expand ? 'down' : 'up'} />\n          {this.props.title}\n        </div> : null}\n        {expand ?\n          <div className=\"card-content\">\n            {(charts || []).map((c, index) => {\n                if (index % 2 !== 0) return null;\n                return (\n                  <div className=\"chart-row\" key={index}>\n                    <div className=\"chart-wrapper\">{c}</div>\n                    {(index + 1 < charts.length) ? <div className=\"chart-wrapper\">{charts[index + 1]}</div> : null}\n                  </div>\n                );\n              })\n            }\n          </div> : null}\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/component/filterColumns/index.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { Button, Checkbox, message, Modal, Spin } from \"antd\";\nimport { SettingOutlined } from \"@ant-design/icons\";\n\nconst CheckboxGroup = Checkbox.Group;\n\ninterface IFilterColumnsProps {\n  // 全量的列\n  columns: object[];\n  // 设置外面的列\n  setColumns: any;\n  // 可选择的列\n  checkArr: string[];\n  defaultCheckedArr?: string[];\n  // 请求方法\n  getCheckFn: () => Promise<string[]>;\n  saveCheckFn: (list: string[]) => void;\n  filterColumnsVisible: boolean;\n  setFilterColumnsVisible: any;\n  sortObj?: any;\n}\n\nconst FilterColumns: React.FC<IFilterColumnsProps> = (props: IFilterColumnsProps) => {\n  const { filterColumnsVisible, setFilterColumnsVisible, sortObj } = props;\n  const list = props.checkArr;\n  const [checkAll, setCheckAll] = useState(true);\n  const [checkArr, setCheckArr] = useState(props.defaultCheckedArr || []);\n  const [indeterminate, setIndeterminate] = useState(true);\n  const [loading, setLoading] = useState(false);\n\n  const onOk = () => {\n    props.setColumns(\n      props.columns.filter((item: any) => {\n        if (list.includes(item.dataIndex) && !checkArr.includes(item.dataIndex)) {\n          return false;\n        }\n        return true;\n      })\n    );\n    props.saveCheckFn(checkArr);\n    setFilterColumnsVisible(false);\n  };\n\n  const cancel = () => {\n    setFilterColumnsVisible(false);\n  };\n\n  const onCheckAllChange = (e) => {\n    setCheckArr(e.target.checked ? [...list] : []);\n    setIndeterminate(false);\n    setCheckAll(e.target.checked);\n  };\n\n  const onCheckboxGroupChange = (values) => {\n    setCheckArr([...values]);\n    setIndeterminate(!!values.length && values.length < list.length);\n    setCheckAll(values.length === list.length);\n  };\n\n  const initCheckedItems = async () => {\n    setLoading(true);\n    const cacheCheck = await props.getCheckFn();\n    setLoading(false);\n\n    const checkedItems = cacheCheck?.length ? cacheCheck : props.defaultCheckedArr || [];\n    setCheckArr(list.filter((item) => checkedItems.includes(item)));\n\n    setIndeterminate(!!checkedItems.length && checkedItems.length < list.length);\n    setCheckAll(checkedItems.length === list.length);\n    props.setColumns(\n      props.columns.filter((item: any) => {\n        if (list.includes(item.dataIndex) && !checkedItems.includes(item.dataIndex)) {\n          return false;\n        }\n        return true;\n      })\n    );\n  };\n\n  useEffect(() => {\n    initCheckedItems();\n  }, [sortObj]);\n\n  useEffect(() => {\n    if (filterColumnsVisible) {\n      initCheckedItems();\n    }\n    // onOk();\n  }, [filterColumnsVisible]);\n\n  return (\n    <Modal visible={filterColumnsVisible} onOk={onOk} onCancel={cancel} width={600}>\n      <Spin spinning={loading}>\n        <Checkbox indeterminate={indeterminate} onChange={onCheckAllChange} checked={checkAll}>\n          全选\n        </Checkbox>\n        <br />\n        <CheckboxGroup\n          className=\"checkboxGroup\"\n          options={props.columns\n            .filter((item: any) => list.includes(item.dataIndex))\n            .map((item: any) => ({\n              label: item.title as string,\n              value: item.dataIndex as string,\n            }))}\n          value={checkArr}\n          onChange={onCheckboxGroupChange}\n        />\n      </Spin>\n    </Modal>\n  );\n};\n\nexport default FilterColumns;\n"
  },
  {
    "path": "arius-console/src/component/info-item/index.less",
    "content": ".info-item-wrapper {\n  padding-right: 20px;\n  display: inline-flex;\n\n  >label {\n    word-break: break-all;\n    font-family: PingFangSC-Regular;\n    font-size: 12px;\n    color: #333333;\n    letter-spacing: 0;\n    text-align: right;\n    line-height: 22px;\n  }\n\n  >div {\n    font-family: PingFangSC-Regular;\n    font-size: 12px;\n    color: #666666;\n    letter-spacing: 0;\n    text-align: left;\n    line-height: 22px;\n  }\n}"
  },
  {
    "path": "arius-console/src/component/info-item/index.tsx",
    "content": "import React from 'react';\nimport './index.less';\n\nexport interface IInfoItemProps {\n  label: string | number;\n  value: string | number | JSX.Element;\n  width?: number;\n  marginTop?: number;\n}\n\nexport class InfoItem extends React.Component<IInfoItemProps> {\n  public render() {\n    const { label, value } = this.props;\n    let { width, marginTop } = this.props;\n    if (!width) width = 250;\n    if (!marginTop) marginTop = 24;\n    return (\n      <div className=\"info-item-wrapper\" style={{ width: `${width}px` }}>\n        <label>{label}: </label>\n        <div className=\"ml-5\">{value}</div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/component/infoTooltip/index.less",
    "content": ".info-tooltip {\n  display: inline-block;\n  .icon {\n    width: 12px;\n    height: 12px;\n    color: #adb5bc;\n    position: absolute;\n    top: 5px;\n    margin-left: 4px;\n    cursor: pointer;\n    z-index: 1;\n    &:hover {\n      color: #495057;\n    }\n  }\n  .threshold {\n    margin-left: 14px;\n  }\n  .price,\n  .currentCalLogic,\n  .threshold {\n    display: flex;\n    .title,\n    .content {\n      font-family: PingFangSC-Regular;\n      font-size: 14px;\n      color: #ffffff;\n      line-height: 22px;\n      font-weight: 400;\n    }\n    .content {\n      width: 375px;\n      display: inline-block;\n    }\n  }\n  .ant-tooltip-placement-topLeft .ant-tooltip-arrow {\n    left: 0px;\n  }\n}\n\n.indicators-info {\n  .icon {\n    width: 16px;\n    height: 16px;\n  }\n}\n\n.info-content {\n  .ant-tooltip-content {\n    width: 470px;\n    .ant-tooltip-arrow {\n      right: 0px;\n      .ant-tooltip-arrow-content {\n        margin: auto;\n      }\n    }\n  }\n  .ant-tooltip-inner {\n    position: relative;\n    left: -90px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/component/infoTooltip/index.tsx",
    "content": "import React from \"react\";\nimport { Tooltip } from \"antd\";\nimport \"./index.less\";\n\nexport default function InfoTooltip(props) {\n  const { price, currentCalLogic, threshold, className } = props;\n\n  const renderTitle = () => {\n    let priceText = price ? (\n      <div className=\"price\">\n        <span className=\"title\">指标价值：</span>\n        <div className=\"content\">{price}</div>\n      </div>\n    ) : (\n      \"\"\n    );\n    let currentCalLogicText = currentCalLogic ? (\n      <div className=\"currentCalLogic\">\n        <span className=\"title\">计算逻辑：</span>\n        <div className=\"content\">{currentCalLogic}</div>\n      </div>\n    ) : (\n      \"\"\n    );\n    let thresholdText = threshold ? (\n      <div className=\"threshold\">\n        <span className=\"title\">阈值线：</span>\n        <div className=\"content\">{threshold}</div>\n      </div>\n    ) : (\n      \"\"\n    );\n    return (\n      <div>\n        {priceText}\n        {currentCalLogicText}\n        {thresholdText}\n      </div>\n    );\n  };\n\n  return (\n    <div className={`info-tooltip ${className ? className : \"\"}`}>\n      <Tooltip overlayClassName=\"info-content\" title={renderTitle()} placement=\"topLeft\" getPopupContainer={(node) => node.parentElement}>\n        <svg className=\"icon\" aria-hidden=\"true\">\n          <use xlinkHref=\"#iconinfo\"></use>\n        </svg>\n      </Tooltip>\n    </div>\n  );\n}\n"
  },
  {
    "path": "arius-console/src/component/jsonEditor/index.less",
    "content": ".readOnly .CodeMirror-sizer {\n  padding-bottom: 65px !important;\n}\n\n.CodeMirror {\n  pre.CodeMirror-placeholder {\n    color: #aaa;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/component/jsonEditor/index.tsx",
    "content": "import React from \"react\";\n// 引入codemirror\nimport { UnControlled as CodeMirror } from \"react-codemirror2\";\nimport \"codemirror/lib/codemirror.css\";\nimport \"codemirror/theme/material.css\";\nimport \"./index.less\";\n// 代码错误提示\nimport \"codemirror/addon/lint/lint\";\nimport \"codemirror/addon/lint/json-lint\";\nimport \"codemirror/addon/lint/lint.css\";\n// placeholder\nimport \"codemirror/addon/display/placeholder\";\n\n// 没有window.jsonlint错误校验会失效\nimport jsonlint from \"jsonlint\";\n// @ts-ignore\nwindow.jsonlint = jsonlint;\n\ninterface IJsonEditorProps {\n  editorDidMount: (result: any) => any;\n  options?: object;\n  attrs?: object;\n}\n\nexport const JsonEditor = (props: IJsonEditorProps) => {\n  const { editorDidMount, options, attrs } = props;\n\n  return (\n    <>\n      <CodeMirror\n        options={{\n          // mode: \"application/json\",\n          mode: { name: \"javascript\", json: true },\n          lineNumbers: true, // 显示行号\n          smartIndent: true, // 自动缩进\n          lineWrapping: true, // 自动换行\n          foldGutter: true, // 代码折叠\n          gutters: [\"CodeMirror-linenumbers\", \"CodeMirror-foldgutter\", \"CodeMirror-lint-markers\"],\n          lint: true, // 错误提示\n          indentUnit: 4, // 缩进配置（默认为2）\n          ...options,\n        }}\n        editorDidMount={editorDidMount}\n        {...attrs}\n      />\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/component/jsonEditorWrapper/config.ts",
    "content": "export const mappingExample = `{\n  \"properties\": {\n      \"key0-string类型不分词\": {\n          \"type\": \"keyword\"\n      },\n      \"key1-string类型分词\": {\n          \"type\": \"text\",\n          \"analyzer\": \"standard\"\n      },\n      \"key2-int类型\": {\n          \"type\": \"integer\"\n      },\n      \"key3-long类型\": {\n          \"type\": \"long\"\n      },\n      \"key4-double类型\": {\n          \"type\": \"double\"\n      },\n      \"key5-毫秒时间戳\": {\n          \"format\": \"epoch_millis\",\n          \"type\": \"date\"\n      },\n      \"key6-boolean类型不分词\": {\n          \"type\": \"boolean\"\n      },\n      \"key7-object类型\": {\n          \"type\": \"object\",\n          \"properties\": {\n              \"key5.1\": {\n                  \"type\": \"integer\"\n              },\n              \"key5.2\": {\n                  \"type\": \"keyword\"\n              }\n          }\n      },\n      \"key8-nest内嵌类型\": {\n          \"type\": \"nested\",\n          \"properties\": {\n              \"key6.1\": {\n                  \"type\": \"integer\"\n              },\n              \"key6.2\": {\n                  \"type\": \"keyword\"\n              }\n          }\n      }\n  }\n}`;\n\nexport const esDocLink = {\n  mapping: \"https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html\",\n  setting: \"https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html\",\n};\n\nexport function formatRequestBodyDoc(data: string, indent: boolean = true) {\n  let changed = false;\n  let newDoc = data;\n\n  try {\n    newDoc = JSON.parse(newDoc);\n    newDoc = jsonToString(newDoc, indent);\n    changed = changed || newDoc !== data;\n  } catch (e) {\n    // eslint-disable-next-line no-console\n    console.log(e);\n  }\n\n  return {\n    data: newDoc,\n    changed,\n  };\n}\n\nexport function jsonToString(data: any, indent: boolean) {\n  return JSON.stringify(data, null, indent ? 4 : 0);\n}\n"
  },
  {
    "path": "arius-console/src/component/jsonEditorWrapper/index.less",
    "content": ".json-editor-wrapper {\n  border-radius: 4px;\n\n  .application {\n    padding: 16px 0;\n    background: #f5f7fa;\n  }\n\n  .application .ace-tm .ace_gutter {\n    border-left: none;\n    background-color: #f5f7fa;\n  }\n\n  .json-content-title {\n    display: flex;\n    justify-content: space-between;\n    height: 36px;\n    background: #fff;\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: #303a51;\n    .tips-container {\n      height: 28px;\n      padding: 4px 4px 4px 0;\n      background: rgba(116, 120, 141, 0.1);\n      border-radius: 4px;\n    }\n  }\n}\n\n.json-content-title .tip {\n  display: inline-block;\n  height: 24px;\n  padding: 0px 8px;\n  font-size: 12px;\n  border-radius: 2px;\n  color: #5b6675;\n  line-height: 22px;\n  position: relative;\n  top: -3px;\n  left: 2px;\n  cursor: pointer;\n  &:hover {\n    color: @primary-color;\n  }\n  &.link {\n    background: #ffffff;\n    border-radius: 4px;\n    a {\n      color: @primary-color;\n      transition: none;\n      &:hover {\n        color: @primary-color;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/component/jsonEditorWrapper/index.tsx",
    "content": "import React, { useRef } from \"react\";\nimport { ACEJsonEditor } from \"@knowdesign/kbn-sense/lib/packages/kbn-ace/src/ace/json_editor\";\nimport { Spin, Tooltip } from \"antd\";\nimport { CopyOutlined } from \"@ant-design/icons\";\nimport { copyString } from \"lib/utils\";\nimport { esDocLink, formatRequestBodyDoc, mappingExample } from \"./config\";\nimport \"./index.less\";\n\ninterface IProps {\n  wrapperClassName?: string;\n  readOnly?: boolean;\n  data: any;\n  isShowTipLink?: boolean;\n  isShowMappingTip?: boolean;\n  isNeedAutoIndent?: boolean;\n  isNeedHeader?: boolean;\n  title: string;\n  loading: boolean;\n  setEditorInstance?: any;\n  setValid?: any;\n  jsonClassName?: string;\n  docType?: string;\n  docUrl?: string;\n  exampleElement?: React.ReactNode;\n}\n\nexport const mappingExampleElement = (title = \"ES索引mapping样例：\") => {\n  return (\n    <>\n      <div>\n        {title}\n        <CopyOutlined onClick={() => copyString(mappingExample)} />\n      </div>\n      <pre>{mappingExample}</pre>\n    </>\n  );\n};\n\nexport const JsonEditorWrapper = (props: IProps) => {\n  const {\n    wrapperClassName,\n    readOnly,\n    data,\n    docType,\n    title,\n    loading,\n    setEditorInstance,\n    setValid,\n    jsonClassName,\n    exampleElement,\n    docUrl,\n    isShowTipLink = true,\n    isShowMappingTip = true,\n    isNeedAutoIndent = false,\n    isNeedHeader = true,\n  } = props;\n\n  const currentEditor = useRef() as any;\n\n  const setAceEditorInstance = (editor) => {\n    currentEditor.current = editor;\n    setEditorInstance && setEditorInstance(editor);\n  };\n\n  return (\n    <Spin spinning={loading}>\n      <div className={`json-editor-wrapper ${wrapperClassName || \"\"}`}>\n        {isNeedHeader ? (\n          <div className=\"json-content-title\">\n            <div className=\"title\">{title}</div>\n            <div className=\"tips-container\">\n              {isShowTipLink ? (\n                <div className=\"tip link\">\n                  <a href={docUrl || esDocLink[docType]} rel=\"noreferrer\" target=\"_blank\">\n                    官方指导\n                  </a>\n                </div>\n              ) : null}\n              {isShowMappingTip ? (\n                <div className=\"tip\">\n                  <Tooltip overlayClassName=\"tip-example\" title={exampleElement || mappingExampleElement()} placement=\"bottom\">\n                    查看填写示例\n                  </Tooltip>\n                </div>\n              ) : null}\n              {isNeedAutoIndent ? (\n                <div className=\"tip\">\n                  <span\n                    onClick={async (event) => {\n                      event.preventDefault();\n                      if (currentEditor.current) {\n                        const value = formatRequestBodyDoc(currentEditor.current.getValue());\n                        if (value.changed) {\n                          currentEditor.current.setValue(value.data, -1);\n                        }\n                      }\n                    }}\n                  >\n                    自动缩进\n                  </span>\n                </div>\n              ) : null}\n            </div>\n          </div>\n        ) : null}\n        {!loading && (\n          <ACEJsonEditor\n            setEditorInstance={setAceEditorInstance}\n            setValid={setValid}\n            className={jsonClassName}\n            readOnly={readOnly}\n            data={data}\n          />\n        )}\n      </div>\n    </Spin>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/component/left-menu-layout/index.less",
    "content": ".layout-wrapper {\n  padding: 0px;\n  background-color: #fff;\n  position: relative;\n  > .menu-wrapper {\n    position: absolute;\n    padding: 16px 0;\n    .ant-menu-item-selected {\n      background-color: #fff;\n      border-right: 2px solid @primary-color;\n      transform: scaleY(1);\n      opacity: 1;\n    }\n  }\n  > .menu-content-wrapper {\n    padding-left: 15px;\n    height: 800px;\n    position: relative;\n    overflow: scroll;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/component/left-menu-layout/index.tsx",
    "content": "import React from 'react';\nimport { Menu } from 'antd';\nimport { IMenuItem } from 'typesPath/base-types';\nimport './index.less';\n\n\nexport interface ILMLayoutProps {\n  menu: IMenuItem[];\n  menuWidth?: number;\n  selectedKey?: string;\n  onMenuClick?: (param: any) => any;\n  className?: string;\n}\n\nexport class LeftMenuLayout extends React.Component<ILMLayoutProps> {\n  public render() {\n    const { selectedKey, onMenuClick, menu, menuWidth, children, className } = this.props;\n    const w = menuWidth || 72;\n    return (\n      <div className={`layout-wrapper ${className || ''}`}>\n        <Menu\n          mode=\"vertical\"\n          className=\"menu-wrapper\"\n          selectedKeys={[selectedKey]}\n          onClick={onMenuClick}\n          style={{width: `${w}px`}}\n        >\n        {menu.map(m => <Menu.Item key={m.key}>{m.label}</Menu.Item>)}\n        </Menu>\n        <div className=\"menu-content-wrapper\" style={{marginLeft: `${w}px`}}>\n        {children}\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/component/render-title/index.less",
    "content": "@import \"../../styles/base.less\";\n// .table-header {\n//   min-width: 800px;\n//   background-color: #fff;\n//   margin-bottom: 20px;\n//   &-box {\n//     // padding: 20px 20px 0;\n//     &-title {\n//       .max-title();\n//     }\n//     &-content {\n//       .middle-content();\n//     }\n//   }\n// }\n// .table-content {\n//   min-width: 800px;\n//   padding: 20px;\n//   background: white;\n// }\n"
  },
  {
    "path": "arius-console/src/component/render-title/index.tsx",
    "content": "\nimport \"./index.less\"\nimport React, { useState } from 'react';\n\ninterface ITitle {\n  title: string;\n  content: string;\n}\nexport const RenderTitle = (header: ITitle) => {\n  return (\n    <div className=\"table-header-box\">\n      <span className='table-header-box-title'>{header.title}</span>\n      {\n        header.content ?\n          <>\n            <span> / </span>\n            <span className='table-header-box-content'>{header.content}</span>\n          </>\n          :\n          null\n      }\n    </div>\n  )\n}"
  },
  {
    "path": "arius-console/src/component/x-form/index.less",
    "content": ".ant-input-number {\n  width: 314px\n}\n\n.footer-btn {\n  float: right;\n  text-align: right;\n  padding: 40px;\n\n  Button:first-child {\n    margin-right: 16px;\n  }\n}\n\n.ant-modal-body {\n  padding: 20px;\n}\n\n.ant-modal-header {\n  padding: 10px 20px;\n}\n\n.ant-form-item {\n  margin-bottom: 0;\n}\n\n.text-label {\n  color: #697687;\n}\n\n.text-custom-item {\n  padding-left: 10px;\n  color: #374053\n}"
  },
  {
    "path": "arius-console/src/component/x-form/index.tsx",
    "content": "import * as React from \"react\";\nimport { Button, Checkbox, DatePicker, Form, Input, InputNumber, Radio, Select, Switch, Upload, Cascader, Col, Row } from \"antd\";\nimport { UploadOutlined } from \"@ant-design/icons\";\nimport { filterOption } from \"lib/utils\";\n\nconst TextArea = Input.TextArea;\nconst { RangePicker } = DatePicker;\n\nexport enum FormItemType {\n  input = \"input\",\n  inputNumber = \"input_number\",\n  textArea = \"text_area\",\n  select = \"select\",\n  _switch = \"_switch\",\n  custom = \"custom\",\n  checkBox = \"check_box\",\n  datePicker = \"date_picker\",\n  rangePicker = \"range_picker\",\n  radioGroup = \"radio_group\",\n  upload = \"upload\",\n  text = \"text\",\n  cascader = \"cascader\",\n}\n\nexport interface IFormItem {\n  key: string;\n  label: string | React.ReactNode;\n  type: FormItemType;\n  value?: string;\n  options?: any[];\n  // 内部组件属性注入\n  attrs?: any;\n  // form属性注入\n  formAttrs?: any;\n  defaultValue?: string | number | any[];\n  rules?: any[];\n  invisible?: boolean;\n  extraElement?: JSX.Element;\n  colSpan?: any;\n  customClassName?: any;\n  radioType?: boolean;\n  isCustomStyle?: boolean;\n  CustomStyle?: any;\n  customFormItem?: any;\n  className?: any;\n}\n\nexport interface IFormSelect extends IFormItem {\n  options: Array<{\n    key?: string | number;\n    value: string | number;\n    label: string;\n    radioType?: boolean;\n    disabled?: boolean;\n  }>;\n}\n\ninterface IFormCustom extends IFormItem {\n  customFormItem: React.Component;\n}\ninterface IXFormProps {\n  formMap: IFormItem[];\n  formData: any;\n  form?: any;\n  wrappedComponentRef?: any;\n  onFinish?: any;\n  formLayout?: any;\n  layout?: \"inline\" | \"horizontal\" | \"vertical\";\n  onHandleValuesChange?: (value: any, allValues: object) => any;\n  className?: string;\n}\n\nexport const renderFormItem = (item: IFormItem) => {\n  switch (item.type) {\n    default:\n    case FormItemType.input:\n      return <Input allowClear key={item.key} {...item.attrs} />;\n    case FormItemType.inputNumber:\n      return <InputNumber {...item.attrs} />;\n    case FormItemType.textArea:\n      return <TextArea allowClear rows={2} {...item.attrs} />;\n    case FormItemType.select:\n      return (\n        <Select showSearch filterOption={filterOption} key={item.key} placeholder={item.attrs?.placeholder || \"请选择\"} {...item.attrs}>\n          {(item as IFormSelect).options &&\n            (item as IFormSelect).options.map((v, index) => (\n              <Select.Option key={v.value || v.key || index} value={v.value} disabled={v.disabled}>\n                {v.label || v.value}\n              </Select.Option>\n            ))}\n        </Select>\n      );\n    case FormItemType._switch:\n      return <Switch {...item.attrs} />;\n    case FormItemType.custom:\n      return (item as IFormCustom).customFormItem;\n    case FormItemType.checkBox:\n      return <Checkbox.Group options={(item as IFormSelect).options} />;\n    case FormItemType.datePicker:\n      return <DatePicker key={item.key} {...item.attrs} />;\n    case FormItemType.rangePicker:\n      return <RangePicker key={item.key} {...item.attrs} />;\n    case FormItemType.radioGroup:\n      return (\n        <Radio.Group key={item.key} {...item.attrs}>\n          {(item as IFormSelect).options.map((v, index) => {\n            if (v.radioType) {\n              return (\n                <Radio.Button key={v.value || v.key || index} value={v.value}>\n                  {v.label}\n                </Radio.Button>\n              );\n            }\n            return (\n              <Radio key={v.value || v.key || index} value={v.value}>\n                {v.label}\n              </Radio>\n            );\n          })}\n        </Radio.Group>\n      );\n    case FormItemType.upload:\n      return (\n        <Upload beforeUpload={false} {...item.attrs}>\n          <Button>\n            <UploadOutlined />\n            上传\n          </Button>\n        </Upload>\n      );\n    case FormItemType.cascader:\n      return <Cascader key={item.key} options={(item as IFormSelect).options} {...item.attrs} />;\n  }\n};\n\nexport const handleFormItem = (formItem: any, formData: any) => {\n  let initialValue = formData[formItem.key] || formItem.defaultValue || undefined;\n  let valuePropName = \"value\";\n\n  if (formItem.type === FormItemType.datePicker) {\n    initialValue = initialValue || null;\n  }\n\n  if (formItem.type === FormItemType._switch) {\n    initialValue = formData[formItem.key] ? true : false;\n  }\n\n  if (formItem.type === FormItemType._switch) {\n    valuePropName = \"checked\";\n  }\n\n  if (formItem.type === FormItemType.upload) {\n    valuePropName = \"fileList\";\n  }\n  return { initialValue, valuePropName };\n};\n\nexport const XForm: React.FC<IXFormProps> = (props: IXFormProps) => {\n  const { layout, formLayout, formData, formMap, form, wrappedComponentRef, onHandleValuesChange, className } = props;\n  const onUploadFileChange = (e: any) => {\n    if (Array.isArray(e)) {\n      return e;\n    }\n    return e && e.fileList;\n  };\n\n  const defaultLayout =\n    layout === \"vertical\"\n      ? null\n      : formLayout\n      ? formLayout\n      : {\n          labelCol: { span: 4 },\n          wrapperCol: { span: 16 },\n        };\n\n  const renderTwoArray = (formMap) => {\n    return (\n      <Row gutter={[24, 16]}>\n        <Col span={12}>{renderFormItemBox(formMap)[0]}</Col>\n        <Col span={12}>{renderFormItemBox(formMap)[1]}</Col>\n      </Row>\n    );\n  };\n\n  const renderFormItemBox = (formMap) => {\n    return formMap.map((formItem) => {\n      const { initialValue = undefined, valuePropName } = handleFormItem(formItem, formData);\n      if (Array.isArray(formItem)) {\n        return renderTwoArray(formItem);\n      }\n\n      if (formItem.type === FormItemType.text)\n        return (\n          <div\n            key={formItem.key}\n            className={formItem.className}\n            style={\n              formItem.isCustomStyle\n                ? { display: \"flex\", marginBottom: 10, ...formItem.CustomStyle }\n                : { display: \"flex\", marginBottom: 10 }\n            }\n          >\n            <div className=\"ant-form-item-label\" style={{ padding: 0, color: \"#697687\" }}>\n              <label className=\"text-label\">{typeof formItem.label === \"string\" ? formItem.label + \":\" : formItem.label}</label>\n            </div>\n            <div className=\"text-custom-item\">{(formItem as IFormCustom).customFormItem}</div>\n          </div>\n        );\n      return (\n        !formItem.invisible && (\n          <Form.Item\n            name={formItem.key}\n            key={formItem.key}\n            label={formItem.label}\n            rules={formItem.rules || [{ required: false, message: \"\" }]}\n            initialValue={initialValue}\n            valuePropName={valuePropName}\n            className={formItem.className ? formItem.className : formItem.isCustomStyle ? \"ant-form-item-custom\" : null} // 兼容负责人选择后表单样式变大\n            style={formItem.isCustomStyle ? { margin: \"16px 0\", ...formItem.CustomStyle } : { margin: \"16px 0\" }}\n            getValueFromEvent={formItem.type === FormItemType.upload ? onUploadFileChange : null}\n            {...formItem.formAttrs}\n          >\n            {renderFormItem(formItem)}\n          </Form.Item>\n        )\n      );\n    });\n  };\n\n  return (\n    <>\n      <Form\n        className={className}\n        ref={wrappedComponentRef}\n        form={form}\n        {...defaultLayout}\n        layout={layout || \"horizontal\"}\n        onValuesChange={onHandleValuesChange}\n      >\n        {renderFormItemBox(formMap)}\n      </Form>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/component/x-form-wrapper/index.less",
    "content": ".wrap-contain {\n  .ant-modal-header>.ant-modal-title {\n    color: rgba(0, 0, 0, 1);\n  }\n\n  .ant-drawer-header>.ant-drawer-title {\n    color: rgba(0, 0, 0, 1);\n  }\n\n  .ant-form-item-label>label {\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: rgba(0, 0, 0, 0.60);\n    line-height: 22px;\n    font-weight: 400;\n  }\n\n  .text-custom-item {\n    padding-left: 10px;\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: rgba(0, 0, 0, 0.87);\n    letter-spacing: 0;\n    line-height: 22px;\n    font-weight: 400;\n  }\n}\n\n.confirm-button {\n  margin-right: 10px\n}"
  },
  {
    "path": "arius-console/src/component/x-form-wrapper/index.tsx",
    "content": "/* eslint-disable react/display-name */\nimport * as React from \"react\";\nimport { message } from \"antd\";\nimport { Drawer, Modal, Button, Form } from \"knowdesign\";\nimport { XForm as XFormComponent } from \"component/x-form\";\nimport { IXFormWrapper } from \"interface/common\";\nimport \"./index.less\";\n\nexport const XFormWrapper = React.forwardRef((props: IXFormWrapper, ref) => {\n  const [confirmLoading, setConfirmLoading] = React.useState(false);\n  const {\n    type,\n    visible,\n    title,\n    width,\n    formLayout,\n    cancelText,\n    okText,\n    layout,\n    formData = {},\n    formMap,\n    onCancel,\n    onChangeVisible,\n    nofooter,\n    customRenderElement,\n    noform,\n    onHandleValuesChange,\n    needSuccessMessage = true,\n    className,\n  } = props;\n\n  const [form] = Form.useForm();\n\n  React.useEffect(() => {\n    form.setFieldsValue(formData);\n  }, [formData]);\n\n  const resetForm = (resetFields?: any) => {\n    form.resetFields(resetFields || \"\");\n  };\n\n  const closeModalWrapper = () => {\n    onChangeVisible && onChangeVisible(false);\n  };\n\n  const handleCancel = () => {\n    // tslint:disable-next-line:no-unused-expression\n    onCancel && onCancel();\n    resetForm();\n    closeModalWrapper();\n  };\n\n  const handleSubmit = () => {\n    form\n      .validateFields()\n      .then((result) => {\n        const { onSubmit, isWaitting, needBtnLoading, actionAfterFailedSubmit, actionAfterSubmit } = props;\n        if (typeof onSubmit === \"function\") {\n          if (isWaitting) {\n            setConfirmLoading(true);\n            onSubmit(result)\n              .then((res: any) => {\n                setConfirmLoading(false);\n\n                if (typeof actionAfterSubmit === \"function\") {\n                  actionAfterSubmit(res);\n                }\n                needSuccessMessage && message.success(\"操作成功\");\n                resetForm();\n                closeModalWrapper();\n              })\n              .catch((err) => {\n                if (typeof actionAfterFailedSubmit === \"function\") {\n                  actionAfterFailedSubmit();\n                }\n                setConfirmLoading(false);\n              })\n              .finally(() => {\n                setConfirmLoading(false);\n              });\n            return;\n          }\n          if (needBtnLoading) {\n            setConfirmLoading(true);\n            onSubmit(result).finally(() => setConfirmLoading(false));\n            return;\n          }\n\n          // tslint:disable-next-line:no-unused-expression\n          onSubmit && onSubmit(result);\n          closeModalWrapper();\n        }\n      })\n      .catch((errs) => {\n        //\n      });\n  };\n\n  const renderDrawer = () => {\n    return (\n      <Drawer\n        title={title}\n        visible={visible}\n        width={width}\n        closable={true}\n        className={`wrap-contain ${className ? className : \"\"}`}\n        onClose={handleCancel}\n        maskClosable={false}\n        destroyOnClose={true}\n        footer={\n          !nofooter && (\n            <div className=\"footer-btn\">\n              <Button className=\"confirm-button\" loading={confirmLoading} type=\"primary\" onClick={handleSubmit}>\n                {okText || \"确定\"}\n              </Button>\n              <Button onClick={handleCancel}>{cancelText || \"取消\"}</Button>\n            </div>\n          )\n        }\n      >\n        <>{customRenderElement}</>\n        {!noform && (\n          <XFormComponent\n            layout={layout || \"vertical\"}\n            form={form}\n            formData={formData}\n            formMap={formMap}\n            formLayout={formLayout}\n            onHandleValuesChange={onHandleValuesChange}\n          />\n        )}\n      </Drawer>\n    );\n  };\n  const renderModal = () => {\n    return (\n      <Modal\n        width={width || 600}\n        className={`wrap-contain ${className ? className : \"\"}`}\n        title={title}\n        visible={visible}\n        confirmLoading={confirmLoading}\n        maskClosable={false}\n        onOk={handleSubmit}\n        onCancel={handleCancel}\n        okText={okText || \"确定\"}\n        cancelText={cancelText || \"取消\"}\n      >\n        <XFormComponent\n          form={form}\n          formData={formData}\n          formMap={formMap}\n          formLayout={formLayout}\n          layout={layout || \"vertical\"}\n          onHandleValuesChange={onHandleValuesChange}\n        />\n      </Modal>\n    );\n  };\n\n  React.useImperativeHandle(ref, () => ({\n    form,\n  }));\n\n  return <>{type === \"drawer\" ? renderDrawer() : renderModal()}</>;\n});\n"
  },
  {
    "path": "arius-console/src/component/x-form-wrapper/types.ts",
    "content": "import { IFormItem } from 'component/x-form';\n\nexport interface IXFormWrapper {\n  type?: string;\n  title: string | React.ReactNode;\n  onSubmit: (result: any) => any;\n  onCancel?: () => any;\n  visible: boolean;\n  spinning?: boolean;\n  onChangeVisible?: (visible: boolean) => any;\n  formMap?: IFormItem[];\n  formData?: any;\n  width?: number;\n  formLayout?: any;\n  okText?: string;\n  cancelText?: string;\n  customRenderElement?: React.ReactNode;\n  noform?: boolean;\n  nofooter?: boolean;\n  isWaitting?: boolean;\n  okButtonProps?: object;\n  errorTip?: string;\n  renderExtraElement?: () => string | React.ReactNode;\n  action?: {onHandleValuesChange: (value: object, allValues: object) => any; };\n  actionAfterSubmit?: (res?: any) => any;\n  actionAfterFailedSubmit?: () => any;\n}\n"
  },
  {
    "path": "arius-console/src/component/x-notification/index.less",
    "content": ".notificate-name {\n  width: 348px;\n  background-color: #ffffff;\n  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.02), 0 4px 6px 6px rgba(0, 0, 0, 0.02), 0 4px 6px 0 rgba(0, 0, 0, 0.06);\n  border-radius: 4;\n  .svg-style {\n    font-size: 20px;\n    position: absolute;\n    margin-left: 4px;\n    line-height: 20px;\n    top: 2px;\n  }\n  .ant-notification-notice-message {\n    margin-left: 35px;\n  }\n  .ant-notification-notice-description {\n    margin-left: 35px;\n  }\n  .ant-notification-close-x {\n    position: relative;\n    top: 4px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/component/x-notification/index.tsx",
    "content": "import React, { CSSProperties, ReactNode } from \"react\";\nimport { notification } from \"antd\";\nimport \"./index.less\";\ninterface INotificationItem {\n  type: string;\n  message: string;\n  description?: string;\n  className?: string;\n  icon?: ReactNode;\n  duration?: number;\n  placement?: any;\n  style?: CSSProperties;\n  attrs?: object;\n}\nexport const XNotification = (item: INotificationItem) => {\n  const { type, message, description, className, icon, duration, placement, style, attrs } = item;\n  const iconNode = (type: string) => {\n    switch (type) {\n      case \"error\":\n        return (\n          <svg className=\"icon svg-icon svg-style\" aria-hidden=\"true\">\n            <use xlinkHref=\"#iconerror-circle\"></use>\n          </svg>\n        );\n      case \"info\":\n        return (\n          <svg className=\"icon svg-icon svg-style\" aria-hidden=\"true\">\n            <use xlinkHref=\"#iconinfo-circle\"></use>\n          </svg>\n        );\n      case \"success\":\n        return (\n          <svg className=\"icon svg-icon svg-style\" aria-hidden=\"true\">\n            <use xlinkHref=\"#iconsuccess-circle\"></use>\n          </svg>\n        );\n      case \"warning\":\n        return (\n          <svg className=\"icon svg-icon svg-style\" aria-hidden=\"true\">\n            <use xlinkHref=\"#iconwarning-circle\"></use>\n          </svg>\n        );\n    }\n  };\n  return notification?.[type]({\n    type,\n    message,\n    description,\n    className: `notificate-name ${className ? className : \"\"}`,\n    icon: icon || iconNode(type),\n    duration: duration || 3,\n    placement,\n    style,\n    ...attrs,\n  });\n};\n"
  },
  {
    "path": "arius-console/src/constants/api.ts",
    "content": "const prefixMap = {\n  demo: 'api',\n};\n\nexport const csrfTokenMethod = ['POST', 'PUT', 'DELETE'];\n\nfunction getApi(path: string, prefix: string = 'demo') {\n  return `${prefixMap[prefix] || ''}${path}`;\n}\n\nconst api = {\n  demo: getApi('/auth/login'),\n};\n\nexport default api;\n"
  },
  {
    "path": "arius-console/src/constants/common.ts",
    "content": "// 控制开源环境下部分功能的隐藏和禁用 true 禁用 false 启用\nexport const isOpenUp = false;\n\nexport const CURRENT_PROJECT_KEY = \"current-project\";\nexport const PERMISSION_TREE = \"permission-tree\";\n\n// 索引模板服务，开源环境下展示分类\n// 分类: 0 隐藏 1 开源正常展示 2 能力开发中 3 该功能仅面向商业版客户开放\nexport const showTag = {\n  Pipeline: 0,\n  索引别名: 0,\n  Shard调整: 0,\n  预创建: 1,\n  过期删除: 1,\n  Mapping设置: 1,\n  安全管控: 1,\n  冷热分离: 2,\n  Setting设置: 2,\n  资源管控: 3,\n  写入限流: 3,\n  容量规划: 3,\n  \"跨集群同步(DCDR)\": 3,\n};\n\nexport const oneDayMillims = 24 * 60 * 60 * 1000;\n\nexport const urlPrefix = \"\";\n\nexport const colorTheme = \"#526ecc\";\n\nexport const REGION_LIST = [\n  {\n    label: \"中国机房\",\n    value: \"cn\",\n  },\n];\n\nexport const WIKI_LIST = [\n  {\n    label: \"操作手册\",\n    href: \"http://wiki.intra.xiaojukeji.com/pages/viewpage.action?pageId=500193248\",\n    key: \"w1\",\n  },\n  {\n    label: \"用户指南\",\n    href: \"http://wiki.intra.xiaojukeji.com/pages/viewpage.action?pageId=343934369\",\n    key: \"w2\",\n  },\n  {\n    label: \"常见问答\",\n    href: \"http://wiki.intra.xiaojukeji.com/pages/viewpage.action?pageId=120871076\",\n    key: \"w3\",\n  },\n];\n\nexport const RESOURCE_TYPE_LIST = [\n  { value: 1, label: \"共享集群\" },\n  { value: 2, label: \"独立集群\" },\n  { value: 3, label: \"独享集群\" },\n];\n\nexport const LEVEL_MAP = [\n  { value: 1, label: \"核心\" },\n  { value: 2, label: \"重要\" },\n  { value: 3, label: \"一般\" },\n];\n\nexport const NEW_RESOURCE_TYPE_LIST = [\n  { value: 1, label: \"共享集群\" },\n  { value: 2, label: \"独立集群\" },\n  // { value: 3, label: '独享集群' }\n];\n\nexport const LEVEL_LIST = [\n  {\n    label: \"normal\",\n    value: 1,\n  },\n  {\n    label: \"important\",\n    value: 2,\n  },\n  {\n    label: \"vip\",\n    value: 3,\n  },\n];\n\nexport const IS_ROOT = [\n  {\n    label: \"不是 \",\n    value: 0,\n  },\n  {\n    label: \"是\",\n    value: 1,\n  },\n];\n\nexport const SEARCH_TYPE = [\n  {\n    label: \"索引模式 \",\n    value: 1,\n  },\n  {\n    label: \"集群模式\",\n    value: 2,\n  },\n];\n\nexport const ROLE_TYPE = [\n  { value: -1, label: \"unknown\" },\n  { value: 1, label: \"data_node\" },\n  { value: 2, label: \"client_node\" },\n  { value: 3, label: \"master_node\" },\n  { value: 4, label: \"ml_node\" },\n];\n\nexport const ROLE_TYPE_NO = [\n  { value: -1, label: \"unknown\" },\n  { value: 1, label: \"data\" },\n  { value: 2, label: \"client\" },\n  { value: 3, label: \"master\" },\n  { value: 4, label: \"ml\" },\n];\n\nexport const BOOLEAN_LIST = [\n  { value: \"false\", label: \"是\" },\n  { value: \"true\", label: \"否\" },\n];\n\nexport enum CodeType {\n  PreCreate = 1,\n  Pipeline = 2,\n  Rollover = 3,\n  Delete = 4,\n  Separate = 5,\n  Clear = 6,\n  UpgradeVersion = 7,\n  UpdateCapacity = 8,\n  DCDR = 10,\n}\n\nexport const CONFIRM_BUTTON_TEXT = {\n  okText: \"确定\",\n  cancelText: \"取消\",\n};\n"
  },
  {
    "path": "arius-console/src/constants/menu.ts",
    "content": "import {\n  ClusterPanelPermissions,\n  ClusterVersionPermissions,\n  Dashboard,\n  GatewayPanelPermissions,\n  IndexPermissions,\n  DslPermissions,\n  SqlPermissions,\n  KibanaPermissions,\n  IndexServicePermissions,\n  MyApplyPermissions,\n  MyApprovalPermissions,\n  MyClusterPermissions,\n  OPRecordPermissions,\n  PhyClusterPermissions,\n  PlatformPermissions,\n  ProjectPermissions,\n  RolePermissions,\n  SearchTemplatePermissions,\n  SearchQueryPermissions,\n  ShceduleLogPermissions,\n  ShceduleTaskPermissions,\n  TaskPermissions,\n  TempletPermissions,\n  TempletServicePermissions,\n  UserPermissions,\n  Grafana,\n} from \"./permission\";\n\nconst pkgJson = require(\"../../package\");\nexport const systemKey = pkgJson.ident;\nexport const urlPrefix = \"/\" + systemKey;\n\nexport const leftMenus = [\n  {\n    name: `${systemKey}`,\n    path: \"main\",\n    icon: \"#\",\n    children: [\n      {\n        name: \"dashboard\",\n        path: \"dashboard\",\n        icon: \"#iconDashboard\",\n        permissionPoint: Dashboard.PAGE,\n      },\n      {\n        name: \"cluster\",\n        path: \"cluster\",\n        icon: \"#iconjiqunguanli2\",\n        children: [\n          {\n            name: \"physics\",\n            path: \"physics\",\n            icon: \"#icon-luoji\",\n            permissionPoint: PhyClusterPermissions.PAGE,\n          },\n          {\n            name: \"logic\",\n            path: \"logic\",\n            icon: \"#icon-jiqun1\",\n            permissionPoint: MyClusterPermissions.PAGE,\n          },\n          {\n            name: \"edition\",\n            path: \"edition\",\n            icon: \"#icon-jiqun1\",\n            permissionPoint: ClusterVersionPermissions.PAGE,\n          },\n        ],\n      },\n      {\n        name: \"index-tpl\",\n        path: \"index-tpl\",\n        icon: \"#iconmobanguanli1\",\n        children: [\n          {\n            name: \"management\",\n            path: \"management\",\n            icon: \"#icon-luoji\",\n            permissionPoint: TempletPermissions.PAGE,\n          },\n          {\n            name: \"service\",\n            path: \"service\",\n            icon: \"#icon-luoji\",\n            permissionPoint: TempletServicePermissions.PAGE,\n          },\n        ],\n      },\n      {\n        name: \"index-admin\",\n        path: \"index-admin\",\n        icon: \"#iconsuoyinguanli1\",\n        children: [\n          {\n            name: \"management\",\n            path: \"management\",\n            icon: \"#icon-luoji\",\n            permissionPoint: IndexPermissions.PAGE,\n          },\n          {\n            name: \"service\",\n            path: \"service\",\n            icon: \"#icon-luoji\",\n            permissionPoint: IndexServicePermissions.PAGE,\n          },\n        ],\n      },\n      {\n        name: \"search-query\",\n        path: \"search-query\",\n        icon: \"#iconjiansuochaxun2\",\n        children: [\n          {\n            name: \"dsl\",\n            path: \"dsl\",\n            icon: \"#icon-luoji\",\n            permissionPoint: DslPermissions.PAGE,\n          },\n          {\n            name: \"sql\",\n            path: \"sql\",\n            icon: \"#icon-luoji\",\n            permissionPoint: SqlPermissions.PAGE,\n          },\n          {\n            name: \"search-template\",\n            path: \"search-template\",\n            icon: \"#icon-luoji\",\n            permissionPoint: SearchTemplatePermissions.PAGE,\n          },\n          {\n            name: \"dsl-tpl\",\n            path: \"dsl-tpl\",\n            icon: \"#icon-luoji\",\n            permissionPoint: SearchQueryPermissions.PAGE,\n          },\n          {\n            name: \"kibana\",\n            path: \"kibana\",\n            icon: \"#icon-luoji\",\n            permissionPoint: KibanaPermissions.PAGE,\n          },\n        ],\n      },\n      {\n        name: \"indicators\",\n        path: \"indicators\",\n        icon: \"#iconzhibiaokanban2\",\n        children: [\n          {\n            name: \"cluster\",\n            path: \"cluster\",\n            icon: \"#icon-luoji\",\n            permissionPoint: ClusterPanelPermissions.PAGE,\n          },\n          {\n            name: \"gateway\",\n            path: \"gateway\",\n            icon: \"#icon-luoji\",\n            permissionPoint: GatewayPanelPermissions.PAGE,\n          },\n        ],\n      },\n    ],\n  },\n  {\n    name: `${systemKey}`,\n    path: \"main\",\n    icon: \"#\",\n    children: [\n      {\n        name: \"scheduling\",\n        path: \"scheduling\",\n        icon: \"#icontiaodurenwu1\",\n        children: [\n          {\n            name: \"task\",\n            path: \"task\",\n            icon: \"#icon-luoji\",\n            permissionPoint: ShceduleTaskPermissions.PAGE,\n          },\n          {\n            name: \"log\",\n            path: \"log\",\n            icon: \"#icon-luoji\",\n            permissionPoint: ShceduleLogPermissions.PAGE,\n          },\n        ],\n      },\n      {\n        name: \"system.config\",\n        path: \"system/config\",\n        icon: \"#iconpingtaipeizhi\",\n        permissionPoint: PlatformPermissions.PAGE,\n      },\n      {\n        name: \"system.operation\",\n        path: \"system/operation\",\n        icon: \"#iconcaozuojilu1\",\n        permissionPoint: OPRecordPermissions.PAGE,\n      },\n      {\n        name: \"work-order.task\",\n        path: \"work-order/task\",\n        icon: \"#iconrenwuzhongxin1\",\n        permissionPoint: TaskPermissions.PAGE,\n      },\n      {\n        name: \"work-order\",\n        path: \"work-order\",\n        icon: \"#icongongdanrenwu2\",\n        children: [\n          {\n            name: \"my-application\",\n            path: \"my-application\",\n            icon: \"#icon-luoji\",\n            permissionPoint: MyApplyPermissions.PAGE,\n          },\n          {\n            name: \"my-approval\",\n            path: \"my-approval\",\n            icon: \"#icon-luoji\",\n            permissionPoint: MyApprovalPermissions.PAGE,\n          },\n        ],\n      },\n      {\n        name: \"system\",\n        path: \"system\",\n        icon: \"#iconzuhuguanli1\",\n        children: [\n          {\n            name: \"users\",\n            path: \"users\",\n            icon: \"#icon-luoji\",\n            permissionPoint: UserPermissions.PAGE,\n          },\n          {\n            name: \"role\",\n            path: \"role\",\n            icon: \"#icon-luoji\",\n            permissionPoint: RolePermissions.PAGE,\n          },\n          {\n            name: \"project\",\n            path: \"project\",\n            icon: \"#icon-luoji\",\n            permissionPoint: ProjectPermissions.PAGE,\n          },\n        ],\n      },\n      {\n        name: \"grafana\",\n        icon: \"#iconzhibiaokanban2\",\n        to: \"jumpToGrafana\",\n        target: \"_blank\",\n        permissionPoint: Grafana.PAGE,\n      },\n    ],\n  },\n];\n"
  },
  {
    "path": "arius-console/src/constants/permission.ts",
    "content": "export enum Dashboard {\n  PAGE = \"Dashboard\",\n}\n\nexport enum Grafana {\n  PAGE = \"Grafana\",\n}\n\nexport enum PhyClusterPermissions {\n  PAGE = \"物理集群\",\n  LIST_DETAIL = \"查看集群列表及详情\",\n  ACCESS = \"接入集群\",\n  ADD = \"新建集群\",\n  EDIT = \"编辑\",\n  EXPAND_SHRINK = \"扩缩容\",\n  UPGRADE = \"升级\",\n  RESTART = \"重启\",\n  CONFIG_UPDATE = \"配置变更\",\n  REGION_SET = \"Region划分\",\n  REGION_MANAGE = \"Region管理\",\n  SHORTCUTS = \"快捷命令\",\n  BIND_GATEWAY = \"绑定Gateway\",\n  OFFLINE = \"下线\",\n  BAT = \"批量操作\",\n}\nexport enum MyClusterPermissions {\n  PAGE = \"我的集群\",\n  LIST_DETAIL = \"查看集群列表及详情\",\n  APPLY = \"申请集群\",\n  EDIT = \"编辑\",\n  EXPAND_SHRINK = \"扩缩容\",\n  OFFLINE = \"下线\",\n}\n\nexport enum ClusterVersionPermissions {\n  PAGE = \"集群版本\",\n  LIST_DETAIL = \"查看版本列表\",\n  ADD = \"新增版本\",\n  EDIT = \"编辑\",\n  DELETE = \"删除\",\n}\n\nexport enum GatewayPermissions {\n  PAGE = \"Gateway管理\",\n  LIST_DETAIL = \"查看Gateway 集群列表\",\n  ACCESS = \"接入gateway\",\n  EDIT = \"编辑\",\n  OFFLINE = \"下线\",\n}\n\nexport enum TempletPermissions {\n  PAGE = \"模板管理\",\n  LIST_DETAIL = \"查看模板列表及详情\",\n  APPLY = \"申请模板\",\n  EDIT = \"编辑\",\n  EDIT_MAPPING = \"编辑Mapping\",\n  EDIT_SETTING = \"编辑Setting\",\n  OFFLINE = \"下线\",\n}\n\nexport enum TempletServicePermissions {\n  PAGE = \"模板服务\",\n  LIST_DETAIL = \"查看模板列表\",\n  PRE_CREATE = \"开关：预创建\",\n  EXPIRE_DELETE = \"开关：过期删除\",\n  HOT_COLD = \"开关：冷热分离\",\n  PIPELINE = \"开关：pipeline\",\n  ROLLOVER = \"开关：Rollover\",\n  GET_DCDR = \"查看DCDR链路\",\n  CREATE_DCDR = \"创建DCDR链路\",\n  CLEAN = \"清理\",\n  EXPAND_SHRINK = \"扩缩容\",\n  UPGRADE_VERSION = \"升版本\",\n  BAT = \"批量操作\",\n}\n\nexport enum IndexPermissions {\n  PAGE = \"索引管理\",\n  LIST_DETAIL = \"查看索引列表及详情\",\n  EDIT_MAPPING = \"编辑Mapping\",\n  EDIT_SETTING = \"编辑Setting\",\n  SET_ALIAS = \"设置别名\",\n  DELETE_ALIAS = \"删除别名\",\n  OFFLINE = \"下线\",\n  BAT_DELETE = \"批量删除\",\n  CREATE_INDEX = \"新建索引\",\n}\n\nexport enum IndexServicePermissions {\n  PAGE = \"索引服务\",\n  LIST_DETAIL = \"查看列表\",\n  ROLLOVER = \"执行Rollover\",\n  SHRINK = \"执行shrink\",\n  SPLIT = \"执行split\",\n  BAT = \"批量执行\",\n  DISABLE_READ = \"禁用读\",\n  DISABLE_WRITE = \"禁用写\",\n  CLOSE_INDEX = \"关闭索引\",\n  ForceMerge = \"执行ForceMerge\",\n}\n\nexport enum DslPermissions {\n  PAGE = \"DSL\",\n}\n\nexport enum SqlPermissions {\n  PAGE = \"SQL\",\n}\n\nexport enum KibanaPermissions {\n  PAGE = \"Kibana\",\n}\n\nexport enum SearchTemplatePermissions {\n  PAGE = \"查询模板\",\n  BAT_MODIFY = \"批量修改限流值\",\n  DISABLE = \"禁用\",\n  MODIFY_LIMIT = \"修改限流值\",\n}\n\nexport enum SearchQueryPermissions {\n  PAGE = \"查询诊断\",\n  ERROR_LIST = \"查看异常查询列表\",\n  SLOW_LIST = \"查看慢查询列表\",\n}\n\nexport enum ClusterPanelPermissions {\n  PAGE = \"集群看板\",\n  LIST = \"查看集群看板\",\n}\n\nexport enum GatewayPanelPermissions {\n  PAGE = \"网关看板\",\n  LIST = \"查看网关看板\",\n}\n\nexport enum MyApplyPermissions {\n  PAGE = \"我的申请\",\n  LIST = \"查看我的申请列表\",\n  CALLBACK = \"撤回\",\n}\n\nexport enum MyApprovalPermissions {\n  PAGE = \"我的审批\",\n  LIST = \"查看我的审批列表\",\n  CALLBACK = \"驳回\",\n  DNOE = \"通过\",\n}\n\nexport enum TaskPermissions {\n  PAGE = \"任务列表\",\n  LIST = \"查看任务列表\",\n  DETAIL = \"查看进度\",\n  EXE = \"执行\",\n  STOP = \"暂停\",\n  RETRY = \"重试\",\n  CANCEL = \"取消\",\n  LOG_CHILD = \"查看日志（子任务）\",\n  RETRY_CHILD = \"重试（子任务）\",\n  IGNORE_CHILD = \"忽略（子任务）\",\n  DETAIL_DCDR = \"查看详情（DCDR）\",\n  CANCEL_DCDR = \"取消（DCDR）\",\n  RETRY_DCDR = \"重试（DCDR）\",\n  CHANGE_DCDR = \"强切（DCDR）\",\n  RETURN_DCDR = \"返回（DCDR）\",\n}\n\nexport enum ShceduleTaskPermissions {\n  PAGE = \"调度任务列表\",\n  LIST = \"查看任务列表\",\n  DETAIL = \"查看日志\",\n  EXE = \"执行\",\n  STOP = \"暂停\",\n}\n\nexport enum ShceduleLogPermissions {\n  PAGE = \"调度日志\",\n  LIST = \"查看调度日志列表\",\n  DETAIL = \"调度详情\",\n  LOG = \"执行日志\",\n  END_MISSION = \"终止任务\",\n}\n\nexport enum UserPermissions {\n  PAGE = \"用户管理\",\n  LIST_DETAIL = \"查看用户列表\",\n  ASSGIN = \"分配角色\",\n}\n\nexport enum RolePermissions {\n  PAGE = \"角色管理\",\n  LIST_DETAIL = \"查看角色列表\",\n  EDIT = \"编辑\",\n  DELETE = \"删除角色\",\n  BIND = \"绑定用户\",\n  RECYCLE = \"回收用户\",\n  ADD = \"新增角色\",\n}\n\nexport enum ProjectPermissions {\n  PAGE = \"应用管理\",\n  LIST_DETAIL = \"查看应用列表\",\n  ADD = \"新建应用\",\n  EDIT = \"编辑\",\n  DELETE = \"删除\",\n  ACCESS = \"访问设置\",\n}\n\nexport enum PlatformPermissions {\n  PAGE = \"平台配置\",\n  LIST_DETAIL = \"查看平台配置列表\",\n  ADD = \"新增平台配置\",\n  EDIT = \"编辑平台配置\",\n  DELETE = \"删除平台配置\",\n  DISABLE = \"禁用平台配置\",\n}\n\nexport enum OPRecordPermissions {\n  PAGE = \"操作记录\",\n  LIST_DETAIL = \"查看操作记录列表\",\n}\n"
  },
  {
    "path": "arius-console/src/constants/reg.ts",
    "content": "export const regNonnegativeInteger = /^\\d+$/g; // 非负正整数\n\nexport const regOddNumber = /^\\d*[13579]$/; //奇数\n\nexport const regClusterName = /^[a-zA-Z0-9\\_-]*$/; // 大、小写字母、数字、-、_  new RegExp('\\[a-z0-9_-]$', 'g')\n\nexport const regExp = /^[ ]+$/; // 不能为空\n\nexport const regNonnegativeNumber = /^[+]{0,1}(\\d+)$|^[+]{0,1}(\\d+\\.\\d+)$/; // 非负数\n\nexport const regTwoNumber = /^-?\\d+\\.?\\d{0,2}$/; // 两位小数\n\nexport const regTemplateName = /^[a-z0-9\\._-]*$/; // 仅支持小写字母、数字、_、-、.的组合\n\nexport const regIp =\n  /^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\.((1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\.){2}(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$/; // ip\n\nexport const regUserPassword = /^[A-Za-z0-9_\\-!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~]*$/;\n\nexport const regPort = /^((6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])|[0-5]?\\d{0,4})$/g; // port\n\nexport const regRegionName = /^[\\u4e00-\\u9fa5_a-zA-Z0-9_-]+$/; // 支持文字，字母，数字，下划线，中划线\n"
  },
  {
    "path": "arius-console/src/constants/status-map.ts",
    "content": "import { IStatusMap, IStringMap, ILabelValue, IStringArray } from \"typesPath/base-types\";\n\nexport const selectAppAuth = [\n  // {\n  //   label: '管理',\n  //   value: 1,\n  // },\n  {\n    label: \"读写\",\n    value: 2,\n  },\n  {\n    label: \"读\",\n    value: 3,\n  },\n] as ILabelValue[];\n\nexport const ClusterAuth = [\n  {\n    title: \"无权限\",\n    value: -1,\n  },\n  {\n    title: \"管理\",\n    value: 1,\n  },\n  {\n    title: \"访问\",\n    value: 2,\n  },\n] as ILabelValue[];\n\nexport const ClusterAuthMaps = {\n  [-1]: \"无权限\",\n  0: \"超级管理员\",\n  1: \"管理\",\n  2: \"访问\",\n} as IStatusMap;\n\nexport const StatusMap = {\n  \"-1\": \"unknown\",\n  0: \"green\",\n  1: \"yellow\",\n  2: \"red\",\n};\n\nexport const ClusterStatus = [\n  {\n    title: \"green\",\n    value: \"0\",\n  },\n  {\n    title: \"yellow\",\n    value: \"1\",\n  },\n  {\n    title: \"red\",\n    value: \"2\",\n  },\n  {\n    title: \"unknown\",\n    value: \"-1\",\n  },\n] as ILabelValue[];\n\nexport const brokerMetrics = {\n  bytesIn: \"Bytes In（MB/ 秒)\",\n  bytesOut: \"Bytes Out（MB/ 秒)\",\n  messagesIn: \"Messages In（条)\",\n  totalFetchRequests: \"Total Fetch Requests（QPS)\",\n  totalProduceRequests: \"Total Produce Requests（QPS)\",\n};\n\nexport const roleMap = {\n  0: \"普通用户\",\n  1: \"研发人员\",\n  2: \"运维人员\",\n} as IStatusMap;\n\nexport const roleModel = [\n  {\n    text: roleMap[0],\n    label: roleMap[0],\n    value: 0,\n  },\n  {\n    text: roleMap[1],\n    label: roleMap[1],\n    value: 1,\n  },\n  {\n    text: roleMap[2],\n    label: roleMap[2],\n    value: 2,\n  },\n] as ILabelValue[];\n\nexport const deployStatus = {\n  1: \"正常\",\n  2: \"禁用\",\n} as IStatusMap;\n\nexport const selectModel = [\n  {\n    text: \"集群模式\",\n    value: 0,\n  },\n  {\n    text: \"索引模式\",\n    value: 1,\n  },\n] as ILabelValue[];\n\nexport const PLUG_RADIO_LIST = [\n  {\n    label: \"默认插件\",\n    value: 1,\n  },\n  {\n    label: \"自定义插件\",\n    value: 2,\n  },\n] as ILabelValue[];\n\nexport const weekOptions = [\n  { label: \"周一\", value: 1 },\n  { label: \"周二\", value: 2 },\n  { label: \"周三\", value: 3 },\n  { label: \"周四\", value: 4 },\n  { label: \"周五\", value: 5 },\n  { label: \"周六\", value: 6 },\n  { label: \"周日\", value: 0 },\n];\n\nexport const orderStatusMap = {\n  0: \"待审批\",\n  1: \"已通过\",\n  2: \"已驳回\",\n  3: \"已撤回\",\n} as IStatusMap;\n\nexport const authStatusMap = {\n  0: \"无权限\",\n  1: \"消费\",\n  2: \"发送\",\n  3: \"发送、消费\",\n  4: \"管理\",\n} as IStatusMap;\n\nexport const clusterTypeMap = {\n  1: \"共享集群\",\n  2: \"独立集群\",\n  3: \"独享集群\",\n} as IStatusMap;\n\nexport const logicClusterType = [\n  { value: 1, title: \"共享集群\" },\n  { value: 2, title: \"独立集群\" },\n  { value: 3, title: \"独享集群\" },\n];\n\nexport const logicClusterLevel = [\n  { value: 1, title: \"核心\" },\n  { value: 2, title: \"重要\" },\n  { value: 3, title: \"一般\" },\n];\n\nexport const INDEX_AUTH_TYPE_MAP = {\n  [-1]: \"无权限\",\n  1: \"管理\",\n  2: \"读/写\",\n  3: \"读\",\n} as IStatusMap;\n\nexport const INDEX_AUTH_TYPE_ARR = [-1, 1, 2, 3];\n\nexport const VERSION_MAINFEST_TYPE = {\n  3: \"docker\",\n  4: \"host\",\n  5: \"vm\",\n} as IStatusMap;\n\nexport const TASK_STATUS_TYPE_MAP = {\n  waiting: \"待执行\",\n  running: \"执行中\",\n  pause: \"已暂停\",\n  cancel: \"已取消\",\n  ignore: \"忽略\",\n  success: \"成功\",\n  failed: \"失败\",\n  timeout: \"超时\",\n  unknown: \"unknown\",\n} as IStringMap;\n\nexport const DCDR_TASK_STATUS_TYPE_MAP = {\n  0: \"success\", // 执行成功\n  1: \"failed\", // 执行失败\n  2: \"running\", // 执行中\n  3: \"waiting\", // 等待\n  4: \"pause\", // 暂停\n  5: \"cancel\", // 取消\n  99: \"未知\",\n} as IStatusMap;\n\nexport const TASK_TYPE_MAP = {\n  1: \"集群新增\",\n  2: \"集群扩容\",\n  3: \"集群缩容\",\n  4: \"集群重启\",\n  5: \"集群升级\",\n  6: \"集群插件操作\",\n  10: \"模板DCDR任务\",\n} as IStatusMap;\nexport const appTemplateAuthEnum = [\n  // { label: '管理', value: 1 },\n  { label: \"读/写\", value: 2 },\n  { label: \"读\", value: 3 },\n];\n\nexport const equalList = [\n  { label: \"大于\", value: \">\" },\n  { label: \"小于\", value: \"<\" },\n  { label: \"等于\", value: \"=\" },\n  { label: \"大于等于\", value: \">=\" },\n  { label: \"小于等于\", value: \"<=\" },\n  { label: \"不等于\", value: \"!=\" },\n];\n\nexport const funcList = [\n  { label: \"周期发生-happen\", value: \"happen\" },\n  { label: \"连续发生-all\", value: \"all\" },\n  { label: \"同比变化率-c_avg_rate_abs\", value: \"c_avg_rate_abs\" },\n  { label: \"突增突降值-diff\", value: \"diff\" },\n  { label: \"突增突降率-pdiff\", value: \"pdiff\" },\n  { label: \"求和-sum\", value: \"sum\" },\n];\n\nexport const funcKeyMap = {\n  happen: [\"period\", \"count\"],\n  ndiff: [\"period\", \"count\"],\n  c_avg_rate_abs: [\"period\", \"day\"],\n  all: [\"period\"],\n  diff: [\"period\"],\n  pdiff: [\"period\"],\n  sum: [\"period\"],\n} as IStringArray;\n\nexport const filterList = [\n  { label: \"集群\", value: \"clusterName\" },\n  { label: \"Topic\", value: \"topic\" },\n  { label: \"Location\", value: \"loaction\" },\n  { label: \"消费组\", value: \"consumerGroup\" },\n] as ILabelValue[];\n\nexport const TASK_TYPE_MAP_LIST = [\n  { value: 0, text: \"全部\", label: \"全部\" },\n  { value: 1, text: \"集群新增\", label: \"集群新增\" },\n  { value: 2, text: \"集群扩容\", label: \"集群扩容\" },\n  { value: 3, text: \"集群缩容\", label: \"集群缩容\" },\n  { value: 4, text: \"集群重启\", label: \"集群重启\" },\n  { value: 5, text: \"集群升级\", label: \"集群升级\" },\n] as ILabelValue[];\n\nexport const NODE_TYPE_MAP = [\n  { value: \"masternode\", text: \"master-node\" },\n  { value: \"clientnode\", text: \"client-node\" },\n  { value: \"datanode\", text: \"data-node\" },\n  // { value: 'datanode-ceph', text: 'datanode-ceph' },\n] as ILabelValue[];\n\nexport const PHY_NODE_TYPE = [\"masternode\", \"clientnode\", \"datanode\", \"coldnode\"];\n\nexport const STAUS_TYPE_MAP = [\n  { value: \"waiting\", text: \"待执行\" },\n  { value: \"running\", text: \"执行中\" },\n  { value: \"pause\", text: \"已暂停\" },\n  { value: \"cancel\", text: \"已取消\" },\n  { value: \"ignore\", text: \"忽略\" },\n  { value: \"success\", text: \"成功\" },\n  { value: \"failed\", text: \"失败\" },\n] as ILabelValue[];\n\nexport const FORCED_EXPANSION_MAP = [\n  { label: \"强制\", value: 1 },\n  { label: \"不强制\", value: 0 },\n] as ILabelValue[];\n\nexport const CONTROL_TYPE = [\n  { label: \"集群\", value: \"cluster\" },\n  { label: \"索引\", value: \"template\" },\n] as ILabelValue[];\nexport const RESOURCE_TYPE_LIST = [\n  { value: 1, label: \"共享集群\", title: \"共享集群\" },\n  { value: 2, label: \"独立集群\", title: \"独立集群\" },\n  { value: 3, label: \"独享集群\", title: \"独享集群\" },\n];\nexport const PHY_CLUSTER_TYPE = [\n  { value: 4, label: \"host\", title: \"host\" },\n  { value: 3, label: \"docker\", title: \"docker\" },\n] as ILabelValue[];\n\nexport const CLUSTER_INDECREASE_TYPE = [\n  { value: 2, label: \"扩容\" },\n  { value: 3, label: \"缩容\" },\n] as ILabelValue[];\n\nexport const filterKeys = [\"cluster\", \"index\"];\n\nexport const SPIT_STYLE_MAP = [\n  {\n    type: \"success\",\n    color: \"#10C038\",\n    back: \"success-back\",\n    text: \"成功\",\n  },\n  {\n    type: \"failed\",\n    color: \"#F04134\",\n    back: \"failed-back\",\n    text: \"失败\",\n  },\n  {\n    type: \"pause\",\n    color: \"#FF931D\",\n    back: \"pause-back\",\n    text: \"已暂停\",\n  },\n  {\n    type: \"running\",\n    color: \"#337DFF\",\n    back: \"running-back\",\n    text: \"执行中\",\n  },\n  {\n    type: \"waiting\",\n    color: \"#BFBFBF\",\n    back: \"waiting-back\",\n    text: \"待执行\",\n  },\n  {\n    type: \"cancel\",\n    color: \"#333\",\n    back: \"cancel-back\",\n    text: \"已取消\",\n  },\n];\n\nexport const opTemplateIndexRoleMap: IStatusMap = {\n  0: \"unknown\",\n  1: \"master\",\n  2: \"slave\",\n  3: \"故障\",\n};\n\nexport const openSourceTip: string = \"该功能仅面向商业版客户开放\";\n\nexport const queryFormText: { searchText: string; resetText: string } = {\n  searchText: \"查询\",\n  resetText: \"重置\",\n};\n\nexport const TOP_MAP = [\n  { value: 5, label: \"Top5\" },\n  { value: 10, label: \"Top10\" },\n  { value: 15, label: \"Top15\" },\n  { value: 20, label: \"Top20\" },\n];\n\nexport const TOP_TIME_RANGE = [\n  {\n    label: \"1 分钟\",\n    value: 1 * 60 * 1000,\n  },\n  {\n    label: \"5 分钟\",\n    value: 5 * 60 * 1000,\n  },\n  {\n    label: \"10 分钟\",\n    value: 10 * 60 * 1000,\n  },\n  {\n    label: \"15 分钟\",\n    value: 15 * 60 * 1000,\n  },\n];\n\nexport const TOP_TYPE = [\n  {\n    label: \"最大值\",\n    value: \"max\",\n  },\n  {\n    label: \"平均值\",\n    value: \"avg\",\n  },\n];\n\nexport const DCDR_STATE_MAP = {\n  0: \"cancel\",\n  1: \"success\",\n  2: \"running\",\n  3: \"failed\",\n  4: \"waiting\",\n};\n\nexport const filtersHasDCDR = [\n  { text: \"是\", value: true },\n  { text: \"否\", value: false },\n];\n\nexport const RESOURCE_TYPE_MAP = {\n  5: \"信创(tce)\",\n  4: \"vmware\",\n  3: \"acs\",\n} as IStatusMap;\n\nexport const CLUSTER_TYPE_MAP = {\n  1: \"共享资源\",\n  2: \"独立资源\",\n  3: \"独享资源\",\n} as IStatusMap;\n\nexport const INPUT_RULE_MAP = {\n  \"0\": \"自动获取\",\n  \"1\": \"全量录入\",\n} as IStatusMap;\n"
  },
  {
    "path": "arius-console/src/constants/table.ts",
    "content": "import { regNonnegativeInteger, regNonnegativeNumber, regTwoNumber } from \"constants/reg\";\n\nexport const pagination = {\n  position: \"bottomRight\",\n  showQuickJumper: true,\n  showSizeChanger: true,\n  pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n  showTotal: (total) => `共 ${total} 条`,\n  // hideOnSinglePage: true,\n};\n\nexport const customPagination = {\n  position: \"bottomRight\",\n  showQuickJumper: true,\n  showSizeChanger: true,\n  showTotal: (total) => `共 ${total} 条`,\n};\n\nexport const cellStyle = {\n  overflow: \"hidden\",\n  whiteSpace: \"nowrap\",\n  textOverflow: \"ellipsis\",\n  cursor: \"pointer\",\n  maxWidth: 150,\n};\n\nexport const textAreaRuleProps = {\n  validator: (rule: any, value: string) => {\n    return value?.trim().length >= 5;\n  },\n};\n\nexport const staffRuleProps = {\n  validator: (rule: any, value: string[]) => {\n    if (value && typeof value === \"string\") {\n      value = (value as string)?.split(\",\");\n    }\n    if (!value?.length) {\n      return Promise.reject(\"请选择责任人\");\n    }\n    if (value?.length < 1) {\n      return Promise.reject(\"请输入至少一位负责人\");\n    }\n    if (value?.length > 5) {\n      return Promise.reject(\"最多五位负责人\");\n    }\n\n    return Promise.resolve();\n  },\n};\n\nexport const nodeRuleProps = {\n  validator: (rule: any, value: any) => {\n    // if (!new RegExp(regNonnegativeInteger).test(value) || value <= 1) { return false; }\n    return true;\n  },\n};\n\nexport const numberRuleProps = {\n  validator: (rule: any, value: any) => {\n    // if (!new RegExp(regNonnegativeInteger).test(value) || value <= 0) { return false; }\n    return true;\n  },\n};\n\nexport const quotaRuleProps = {\n  validator: (rule: any, value: any) => {\n    if (!new RegExp(regNonnegativeNumber).test(value) || !new RegExp(regTwoNumber).test(value)) {\n      return Promise.reject();\n    }\n    return Promise.resolve();\n  },\n};\n\nexport const searchProps = {\n  showSearch: true,\n  optionFilterProp: \"children\",\n  filterOption: (input: any, option: any) => {\n    if (typeof option.props.children === \"object\") {\n      const { props } = option.props.children as any;\n      return (props.children + \"\").toLowerCase().indexOf(input.toLowerCase()) >= 0;\n    }\n    return (option.props.children + \"\").toLowerCase().indexOf(input.toLowerCase()) >= 0;\n  },\n};\n\nexport const initPaginationProps = () => {\n  return {\n    position: \"bottomRight\",\n    showQuickJumper: true,\n    showSizeChanger: true,\n    pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n    showTotal: (total) => `共 ${total} 条`,\n    total: 0,\n    current: 1,\n    pageSize: 10,\n  };\n};\n"
  },
  {
    "path": "arius-console/src/constants/time.ts",
    "content": "import moment from 'moment';\nexport interface IPeriod {\n  label: string;\n  key: string;\n  dateRange: [moment.Moment, moment.Moment];\n}\n\nexport const timeFormat = 'YYYY-MM-DD HH:mm:ss';\n\nexport const timeDate = 'YYYY-MM-DD';\n\nexport const oneDayMillims = 24 * 60 * 60 * 1000;\n\nexport const PERIOD_RADIO = [\n  {\n    label: '10分钟',\n    key: 'tenMin',\n    get dateRange() {\n      return [moment().subtract(10, 'minute'), moment()];\n    },\n  },\n  {\n    label: '6小时',\n    key: 'sixHour',\n    get dateRange() {\n      return [moment().subtract(6, 'hour'), moment()];\n    },\n  },\n  {\n    label: '近1天',\n    key: 'oneDay',\n    get dateRange() {\n      return [moment().subtract(1, 'day'), moment()];\n    },\n  },\n  {\n    label: '近1周',\n    key: 'oneWeek',\n    get dateRange() {\n      return [moment().subtract(1, 'week'), moment()];\n    },\n  },\n] as IPeriod[];\n\nconst periodRadioMap = new Map<string, IPeriod>();\nPERIOD_RADIO.forEach(p => {\n  periodRadioMap.set(p.key, p);\n});\nexport const PERIOD_RADIO_MAP = periodRadioMap;\n\nexport const KEEP_LIVE_LIST = [3, 7, 15, 30, 60, 90, 180, -1];\n\nexport const TIME_LENEND = {\n  today: '当前',\n  yesterday: '昨天',\n  lastWeek: '上周',\n} as {\n  [key: string]: string,\n};\n"
  },
  {
    "path": "arius-console/src/container/AllModalInOne.tsx",
    "content": "import * as React from \"react\";\nimport { connect } from \"react-redux\";\nimport ApplyClusterModal from \"./modal/logic-cluster/apply-cluster\";\nimport EditClusterModal from \"./modal/logic-cluster/edit-cluster\";\nimport ExpandShrinkModal from \"./modal/logic-cluster/expand-shrink-cluster\";\nimport ApplyAauthorityModal from \"./modal/logic-cluster/apply-authority\";\nimport AccessCluster from \"./modal/physics-cluster/access-cluster\";\nimport ApplyPhyClusterModal from \"./modal/physics-cluster/apply-cluster\";\nimport { UpgradeCluster } from \"./modal/physics-cluster/upgrade-cluster\";\nimport RestartClusterModal from \"./modal/physics-cluster/restart-cluster\";\nimport DockerExpandShrinkCluster from \"./modal/physics-cluster/docker-expand-shrink-cluster\";\nimport EditPhyCluster from \"./modal/physics-cluster/edit-cluster\";\nimport ExpandShrinkCluster from \"./modal/physics-cluster/expand-shrink-cluster\";\nimport RegionDivide from \"./modal/physics-cluster/region-divide\";\nimport RegionAdmin from \"./modal/physics-cluster/region-admin\";\nimport EditGatewayUrl from \"./modal/physics-cluster/edit-gateway-url\";\nimport BindGateway from \"./modal/physics-cluster/bind-gateway\";\nimport CustomPlugnModal from \"./modal/plugn/custom-plugn\";\nimport AddPackageModal from \"./modal/edition-cluster/add-package\";\nimport { NewConfigModal } from \"./modal/physics-cluster/new-config\";\nimport EditConfig from \"./modal/physics-cluster/edit-config\";\nimport { ClusterConfigModal } from \"./modal/system/cluster-config\";\nimport AddOrEditProjectModal from \"./modal/project/add-project\";\nimport TransferOfResources from \"./modal/project/transfer-of-resources\";\nimport ResourcesAssociated from \"./modal/project/resources-associated\";\nimport AddOrEditRole from \"./modal/role/add-or-edit-role\";\nimport ShowApprovalModal from \"./modal/work-order/approval-modal\";\nimport { BigPicture } from \"./modal/indicators/big-picture\";\nimport { IndexConfig } from \"./modal/indicators/index-config\";\nimport EditPluginDesc from \"./modal/physics-cluster/edit-plugin-desc\";\nimport { DeleteIndex } from \"./modal/index-admin/delete-index\";\nimport { SetAlias } from \"./modal/index-admin/set-alias\";\nimport { DeleteAlias } from \"./modal/index-admin/delete-alias\";\nimport { BatchExecute } from \"./modal/index-admin/batch-execute\";\nimport { ChartTableModal } from \"./modal/indicators/chart-tablemodal\";\nimport { DeleteCluster } from \"./modal/physics-cluster/deleteCluster\";\nimport { OfflineCluster } from \"./modal/logic-cluster/offlineLogicCluster\";\nimport { InstallPlugin } from \"./modal/physics-cluster/install\";\nimport { UninstallPlugin } from \"./modal/physics-cluster/unintallPlugn\";\nimport { ClearModal } from \"./modal/template/clear\";\nimport { ExpandShrinkCapacity } from \"./modal/template/expand-shrink-capacity\";\nimport { OpenSeparate } from \"./modal/template/open-separate\";\nimport { CreateDCDR } from \"./modal/template/create-DCDR\";\nimport { BatchUpdate } from \"./modal/template/batch-update\";\nimport { DeleteProject } from \"./modal/project/delete-project\";\nimport { DcdrTimeout } from \"./modal/template/dcdr-timeout\";\nimport { Mapping } from \"./modal/sql-query/mapping\";\n\n// drawer\nimport ConfigDetail from \"./drawer/config-detail\";\nimport NodeMonitorDrawer from \"./drawer/node-monitor\";\nimport { TaskLogModal } from \"./modal/work-order/task-log\";\nimport { ShardList } from \"./drawer/shard-list/index\";\nimport MappingSettingDiff from \"./drawer/mapping-diff\";\nimport AccessSetting from \"./modal/project/access-setting\";\nimport { DCDRDetail } from \"./modal/template/DCDR-detail\";\nimport CreateTemplate from \"./drawer/template-create\";\nimport EditTemplate from \"./drawer/template-edit\";\nimport CreateIndex from \"./drawer/index-create\";\nimport { EditIndexMapping } from \"./drawer/index-mapping-edit\";\nimport { EditIndexSetting } from \"./drawer/index-setting-edit\";\nimport { IndexSrvRollover } from \"./drawer/index-srv-rollover\";\nimport { IndexSrvForceMerge } from \"./drawer/index-srv-forceMerge\";\nimport { IndexSrvShrinkSplit } from \"./drawer/index-srv-shrinkSplit\";\nimport PhysicsClusterTask from \"./modal/physics-cluster/physicsClusterTask/index\";\nimport { ShowApprovalDrawer } from \"./modal/work-order/approval-drawer\";\nconst mapStateToProps = (state: any) => ({\n  isLoading: state.modal.loading,\n  modalId: state.modal.modalId,\n  drawerId: state.modal.drawerId,\n});\n\nconst AllModalInOne = (props: any) => {\n  const { modalId, drawerId } = props;\n  if (!modalId && !drawerId) return null;\n\n  return (\n    <>\n      {modalMap[modalId] || null}\n      {drawerMap[drawerId] || null}\n    </>\n  );\n};\n\nconst modalMap = {\n  applyCluster: <ApplyClusterModal />,\n  editCluster: <EditClusterModal />,\n  expandShrink: <ExpandShrinkModal />,\n  applyAauthority: <ApplyAauthorityModal />,\n  accessCluster: <AccessCluster />,\n  applyPhyCluster: <ApplyPhyClusterModal />,\n  expandShrinkCluster: <ExpandShrinkCluster />,\n  dockerExpandShrinkCluster: <DockerExpandShrinkCluster />,\n  editPhyCluster: <EditPhyCluster />,\n  customPlugn: <CustomPlugnModal />,\n  clusterConfigModal: <ClusterConfigModal />,\n  transferOfResources: <TransferOfResources />,\n  resourcesAssociated: <ResourcesAssociated />,\n  addOrEditRole: <AddOrEditRole />,\n  showApprovalModal: <ShowApprovalModal />,\n  taskLogModal: <TaskLogModal />,\n  editConfig: <EditConfig />,\n  bigPicture: <BigPicture />,\n  IndexConfig: <IndexConfig />,\n  EditPluginDesc: <EditPluginDesc />,\n  deleteIndex: <DeleteIndex />,\n  setAlias: <SetAlias />,\n  deleteAlias: <DeleteAlias />,\n  batchExecute: <BatchExecute />,\n  chartTableModal: <ChartTableModal />,\n  deleteCluster: <DeleteCluster />,\n  offlineCluster: <OfflineCluster />,\n  installplugin: <InstallPlugin />,\n  uninstallPlugin: <UninstallPlugin />,\n  expandShrinkCapacity: <ExpandShrinkCapacity />,\n  openSeparate: <OpenSeparate />,\n  createDCDR: <CreateDCDR />,\n  batchUpdate: <BatchUpdate />,\n  regionDivide: <RegionDivide />,\n  regionAdmin: <RegionAdmin />,\n  editGatewayUrl: <EditGatewayUrl />,\n  bindGateway: <BindGateway />,\n  deleteProject: <DeleteProject />,\n  dcdrTimeout: <DcdrTimeout />,\n  mapping: <Mapping />,\n} as {\n  [key: string]: JSX.Element;\n};\n\nconst drawerMap = {\n  configDetail: <ConfigDetail />,\n  nodeMonitorDrawer: <NodeMonitorDrawer />,\n  shardList: <ShardList />,\n  mappingSettingDiff: <MappingSettingDiff />,\n  addOrEditProjectModal: <AddOrEditProjectModal />,\n  AccessSetting: <AccessSetting />,\n  clearModal: <ClearModal />,\n  dcdrDetail: <DCDRDetail />,\n  createTemplate: <CreateTemplate />,\n  editTemplate: <EditTemplate />,\n  createIndex: <CreateIndex />,\n  editIndexMapping: <EditIndexMapping />,\n  editIndexSetting: <EditIndexSetting />,\n  indexSrvRollover: <IndexSrvRollover />,\n  indexSrvForceMerge: <IndexSrvForceMerge />,\n  indexSrvShrinkSplit: <IndexSrvShrinkSplit />,\n  physicsClusterTask: <PhysicsClusterTask />,\n  showApprovalDrawer: <ShowApprovalDrawer />,\n  addPackageModal: <AddPackageModal />,\n  upgradeCluster: <UpgradeCluster />,\n  restartCluster: <RestartClusterModal />,\n  newConfigModal: <NewConfigModal />,\n} as {\n  [key: string]: JSX.Element;\n};\n\nexport default connect(mapStateToProps)(AllModalInOne);\n"
  },
  {
    "path": "arius-console/src/container/IndexSelect.tsx",
    "content": "import { Select } from \"antd\";\nimport { getPhyIndexNameList } from \"api/cluster-index-api\";\nimport { getLogicIndexNameList } from \"api/cluster-kanban\";\nimport { getDslByIndex } from \"api/search-query\";\nimport { isSuperApp, uuid } from \"lib/utils\";\nimport debounce from \"lodash/debounce\";\nimport React, { useState, useEffect, forwardRef, useImperativeHandle } from \"react\";\n\nexport const IndexSelect = forwardRef((props: any, ref) => {\n  const [value, setValue] = useState();\n  const [list, setList] = useState([]);\n\n  useEffect(() => {\n    getIndexList();\n  }, [props.currentCluster?.id]);\n\n  const getIndexList = async (index?: string) => {\n    const superApp = isSuperApp();\n    const indexNameList = await (superApp\n      ? getPhyIndexNameList(props.currentCluster?.id)\n      : getLogicIndexNameList(props.currentCluster?.id));\n\n    setValue(indexNameList?.[0] || null);\n    setList(indexNameList);\n    props.resetProfile();\n    props.setBtnDisabled(!indexNameList.length);\n    if (indexNameList.length) {\n      getIndexDsl(indexNameList[0]);\n    }\n  };\n\n  const getIndexDsl = (indexName) => {\n    getDslByIndex(indexName).then((res) => {\n      let editorInstance = props.getEditorInstance();\n\n      let dsl = \"\";\n      try {\n        dsl = JSON.parse(res)?.dsl;\n        dsl = JSON.stringify(JSON.parse(dsl), null, 4);\n      } catch (err) {}\n\n      editorInstance?.setValue && editorInstance.setValue(dsl);\n    });\n  };\n\n  const onChange = (index) => {\n    setValue(index);\n    getIndexDsl(index);\n  };\n\n  const handleSearch = debounce((newValue: string) => {\n    getIndexList(newValue);\n  }, 200);\n\n  useImperativeHandle(ref, () => ({\n    value,\n  }));\n\n  return (\n    <Select showSearch value={value} onChange={onChange} placeholder=\"请选择索引\">\n      {list?.map((item: any) => (\n        <Select.Option value={item} key={uuid()}>\n          {item}\n        </Select.Option>\n      ))}\n    </Select>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/ProjectManager/AccessSetting.tsx",
    "content": "import React, { useEffect } from \"react\";\nimport _ from \"lodash\";\nimport { getAccessSettingColumns } from \"./config\";\nimport \"./index.less\";\nimport { DTable } from \"component/dantd/dtable\";\nimport url from \"lib/url-parser\";\nimport { getAppByProjectId } from \"api\";\n\nexport const AccessSetting = () => {\n  const projectId = +url().search.projectId;\n  const [list, setList] = React.useState([]);\n\n  useEffect(() => {\n    if (isNaN(projectId)) return;\n    getAppByProjectId(projectId).then((res) => {\n      setList(res);\n    });\n  }, []);\n\n  return (\n    <>\n      <DTable rowKey=\"id\" dataSource={list} columns={getAccessSettingColumns()} reloadData={null} />\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/ProjectManager/MemberList.tsx",
    "content": "import React from 'react';\nimport _ from 'lodash';\nimport { getMemberListColumns } from './config';\nimport './index.less'\nimport { DTable } from 'component/dantd/dtable';\n\nexport const MemberList = (props) => {\n  return (\n    <>\n      <DTable\n        rowKey=\"id\"\n        dataSource={props.list}\n        columns={getMemberListColumns()}\n        reloadData={null}\n      />\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/ProjectManager/config.tsx",
    "content": "/* eslint-disable react/display-name */\nimport * as React from \"react\";\nimport { IMenuItem } from \"interface/common\";\nimport { NavRouterLink, renderAttributes, renderOperationBtns } from \"container/custom-component\";\nimport { timeFormat } from \"constants/time\";\nimport { deleteProject, getProject, checkResources } from \"api\";\nimport { message, Modal } from \"antd\";\nimport { ProjectPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { getCookie } from \"lib/utils\";\nimport \"./index.less\";\nimport { Utils } from \"knowdesign\";\nconst formatDate = Utils.formatDate;\n\nexport const getProjectColumns = (params: {\n  setDrawerId: any;\n  setModalId: any;\n  reloadData?: any;\n  isAdminUser: boolean;\n  pagination?: any;\n}) => {\n  const { setDrawerId, setModalId, reloadData, isAdminUser, pagination } = params;\n  const columns = [\n    {\n      title: \"应用名称\",\n      dataIndex: \"projectName\",\n      key: \"projectName\",\n      width: 220,\n      render: (text: number, record: any) => <NavRouterLink element={text} href={`/system/project/detail?projectId=${record.id}`} />,\n    },\n    {\n      title: \"责任人\",\n      dataIndex: \"ownerList\",\n      key: \"ownerList\",\n      width: 220,\n      render: (text: any) => {\n        return renderAttributes({ data: text.map((item) => item.userName), limit: 2 });\n      },\n    },\n    {\n      title: \"成员数\",\n      dataIndex: \"userList\",\n      key: \"userList\",\n      width: 120,\n      render: (text: any, record: any) => {\n        let isAdmin = getCookie(\"isAdminUser\");\n        return <>{isAdmin === \"yes\" ? record?.userListWithBelongProjectAndAdminRole.length : text?.length}</>;\n      },\n    },\n    {\n      title: \"创建时间\",\n      dataIndex: \"createTime\",\n      key: \"createTime\",\n      width: 180,\n      render: (text: string) => {\n        return formatDate(text, timeFormat);\n      },\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      key: \"operation\",\n      width: 150,\n      render: (text: string, record: any) => {\n        const btns = [\n          {\n            invisible: !hasOpPermission(ProjectPermissions.PAGE, ProjectPermissions.EDIT),\n            clickFunc: async () => {\n              const info = await getProject(record.id);\n              const configInfo = info?.config || {};\n              setDrawerId(\"addOrEditProjectModal\", { ...record, ...info, ...configInfo }, reloadData);\n            },\n            label: \"编辑\",\n          },\n          {\n            invisible: record.isAdmin || !hasOpPermission(ProjectPermissions.PAGE, ProjectPermissions.DELETE),\n            clickFunc: async () => {\n              setModalId(\"deleteProject\", { ...record, pagination }, reloadData);\n            },\n            label: \"删除\",\n          },\n          {\n            invisible: !isAdminUser,\n            clickFunc: () => setDrawerId(\"AccessSetting\", record),\n            label: \"访问设置\",\n          },\n        ];\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n  return columns;\n};\n\nexport const getMemberListColumns = () => {\n  const columns = [\n    {\n      title: \"用户账号\",\n      dataIndex: \"userName\",\n      key: \"userName\",\n    },\n    {\n      title: \"用户实名\",\n      dataIndex: \"realName\",\n      key: \"realName\",\n    },\n    {\n      title: \"邮箱\",\n      dataIndex: \"email\",\n      key: \"email\",\n    },\n    {\n      title: \"电话\",\n      dataIndex: \"phone\",\n      key: \"phone\",\n    },\n    {\n      title: \"角色\",\n      dataIndex: \"roleList\",\n      key: \"roleList\",\n      render: (text: any) => {\n        return <>{text?.join(\",\") || \"-\"}</>;\n      },\n    },\n  ];\n  return columns;\n};\n\nexport const SEARCH_TYPE_MAP = {\n  0: \"集群模式\",\n  1: \"索引模式\",\n  2: \"原生模式\",\n};\nexport const getAccessSettingColumns = () => {\n  const columns = [\n    {\n      title: \"ES_User\",\n      dataIndex: \"id\",\n      key: \"id\",\n    },\n    {\n      title: \"检验码\",\n      dataIndex: \"verifyCode\",\n      key: \"verifyCode\",\n    },\n    {\n      title: \"访问模式\",\n      dataIndex: \"searchType\",\n      key: \"searchType\",\n      render: (text: number) => {\n        return <>{SEARCH_TYPE_MAP[text]}</>;\n      },\n    },\n    {\n      title: \"查询限流值\",\n      dataIndex: \"queryThreshold\",\n      key: \"queryThreshold\",\n    },\n    {\n      title: \"访问集群\",\n      dataIndex: \"cluster\",\n      key: \"cluster\",\n      render: (val: string) => val || \"-\",\n    },\n  ];\n  return columns;\n};\n\nexport const getResourcesListColumns = (setModalId: any, reloadList?: any) => {\n  const columns = [\n    {\n      title: \"资源名\",\n      dataIndex: \"name\",\n      key: \"name\",\n    },\n    {\n      title: \"资源类型\",\n      dataIndex: \"type\",\n      key: \"type\",\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      key: \"operation\",\n      render: (text: string, record: any) => {\n        const btns = [\n          {\n            clickFunc: () => setModalId(\"transferOfResources\", record, reloadList),\n            label: \"转让\",\n          },\n        ];\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n  return columns;\n};\n\nexport const getResourcesAssociatedListColumns = (setModalId: any, reloadList?: any) => {\n  const columns = [\n    {\n      title: \"资源名\",\n      dataIndex: \"name\",\n      key: \"name\",\n    },\n    {\n      title: \"资源类型\",\n      dataIndex: \"type\",\n      key: \"type\",\n    },\n    {\n      title: \"细分权限\",\n      dataIndex: \"auth\",\n      key: \"auth\",\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      key: \"operation\",\n      render: (text: string, record: any) => {\n        const btns = [\n          {\n            clickFunc: () => setModalId(\"resourcesAssociated\", record, reloadList),\n            label: \"编辑细分权限\",\n          },\n          {\n            clickFunc: () => setModalId(\"transferOfResources\", record, reloadList),\n            label: \"解绑\",\n          },\n        ];\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n  return columns;\n};\n\nexport const getProjectQueryXForm = () => {\n  return [\n    {\n      type: \"input\",\n      title: \"应用名称:\",\n      dataIndex: \"projectName\",\n      placeholder: \"请输入应用名称\",\n    },\n  ];\n};\n\nexport const baseInfo = (projectInfo) => {\n  return [\n    {\n      label: \"责任人\",\n      key: \"ownerList\",\n      render: (text: any) => {\n        const names = [];\n        text?.map((item) => {\n          names.push(item.userName);\n        });\n        return <span className=\"project-detail-owner\">{names?.join(\"，\") || \"-\"}</span>;\n      },\n    },\n    {\n      label: \"成员数\",\n      key: \"userList\",\n      render: (text: any) => {\n        let isAdmin = getCookie(\"isAdminUser\");\n        return <>{isAdmin === \"yes\" ? projectInfo?.userListWithBelongProjectAndAdminRole?.length : text?.length}</>;\n      },\n    },\n    {\n      label: \"慢查询耗时\",\n      key: \"slowQueryTimes\",\n    },\n    {\n      label: \"创建时间\",\n      key: \"createTime\",\n      render: (text: string) => {\n        return formatDate(text, timeFormat);\n      },\n    },\n    {\n      label: \"描述\",\n      key: \"description\",\n    },\n  ];\n};\n\nexport enum DETAIL_TAB_KEY {\n  members = \"members\",\n  access = \"access\",\n  resources = \"resources\",\n  resourcesAssociated = \"resourcesAssociated\",\n}\n\nexport const DETAIL_MENU = [\n  {\n    label: \"成员列表\",\n    key: DETAIL_TAB_KEY.members,\n  },\n  {\n    label: \"访问设置\",\n    key: DETAIL_TAB_KEY.access,\n  },\n] as IMenuItem[];\n\nconst menuMap = new Map<string, IMenuItem>();\nDETAIL_MENU.forEach((d) => {\n  menuMap.set(d.key, d);\n});\n\nexport const DETAIL_MENU_MAP = menuMap;\n"
  },
  {
    "path": "arius-console/src/container/ProjectManager/detail.tsx",
    "content": "import { PageHeader } from \"antd\";\nimport { Menu } from \"knowdesign\";\nimport * as React from \"react\";\nimport { baseInfo, DETAIL_MENU } from \"./config\";\nimport url from \"lib/url-parser\";\nimport \"../../styles/detail.less\";\nimport \"./index.less\";\nimport { InfoItem } from \"component/info-item\";\nimport { getApp, getProject } from \"api\";\nimport { MemberList } from \"./MemberList\";\nimport { AccessSetting } from \"./AccessSetting\";\nimport { getCookie } from \"lib/utils\";\n\nexport const ProjectDetail = () => {\n  const projectId = +url().search.projectId;\n  const defaultKey = window.location.hash.replace(\"#\", \"\") || DETAIL_MENU[0].key;\n  const [selectedKey, setSelectedKey] = React.useState(defaultKey);\n  const [projectInfo, setProjectInfo] = React.useState({} as any);\n\n  const listenHashChange = () => {\n    window.addEventListener(\"hashchange\", function (this: Window, ev: HashChangeEvent) {\n      setSelectedKey(window.location.hash.replace(\"#\", \"\"));\n    });\n  };\n\n  const handleMenuClick = (e) => {\n    setSelectedKey(e.key);\n    window.location.hash = e.key;\n  };\n\n  const getProjectInfo = async () => {\n    if (isNaN(projectId)) return;\n\n    try {\n      const pInfo = await getProject(projectId);\n      const info = pInfo?.config || {};\n      setProjectInfo({ ...info, ...pInfo });\n    } catch (e) {\n      //\n    }\n  };\n\n  React.useEffect(() => {\n    getProjectInfo();\n    listenHashChange();\n  }, []);\n\n  const renderContent = () => {\n    let isAdmin = getCookie(\"isAdminUser\");\n    return selectedKey === \"access\" ? (\n      <AccessSetting />\n    ) : (\n      <MemberList list={isAdmin === \"yes\" ? projectInfo.userListWithBelongProjectAndAdminRole : projectInfo.userList} />\n    );\n  };\n\n  const renderPageHeader = () => {\n    return (\n      <PageHeader className=\"project-detail-header\" backIcon={false} title={<h2>{projectInfo.projectName || \"\"}</h2>}>\n        {baseInfo(projectInfo)?.map((row, index) => (\n          <InfoItem\n            key={index}\n            label={row.label}\n            value={\n              row.render\n                ? row.render(projectInfo?.[row.key])\n                : row.key === \"slowQueryTimes\"\n                ? `${projectInfo?.[row.key] + \"ms\" || \"\"}`\n                : `${projectInfo?.[row.key] || \"\"}`\n            }\n            width={250}\n          />\n        ))}\n      </PageHeader>\n    );\n  };\n\n  return (\n    <>\n      {renderPageHeader()}\n      <div className=\"hash-menu-container menu-container project-manager\">\n        <Menu selectedKeys={[selectedKey]} mode=\"horizontal\" onClick={handleMenuClick}>\n          {DETAIL_MENU.map((d) => (\n            <Menu.Item key={d.key}>{d.label}</Menu.Item>\n          ))}\n        </Menu>\n      </div>\n      <div className=\"detail-wrapper project-manager-detail\">{renderContent()}</div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/ProjectManager/index.less",
    "content": ".status-content {\n  background-color: white;\n  padding: 18px;\n\n  h2 {\n    margin-top: 24px;\n    font-family: PingFangSC-Medium;\n    font-size: 14px;\n    color: #333333;\n  }\n\n  .run-topo-wrapper {\n    background-color: #f7f8fa;\n  }\n}\n\n.tp-editor-wrapper {\n  height: 500px;\n  background-color: white;\n  padding-top: 18px;\n\n  .op-btns {\n    text-align: right;\n    margin-right: 30px;\n  }\n}\n\n.log-filter {\n  padding-top: 18px;\n  background-color: white;\n}\n\n.node-wrapper {\n  background-color: #fff;\n  border: 1px solid #d3d9e6;\n  border-radius: 4px;\n  padding: 8px 16px;\n  width: 232px;\n  cursor: pointer;\n\n  > h2 {\n    font-family: PingFangSC-Medium;\n    font-size: 12px;\n    color: #333333;\n    margin: 0;\n    width: 100%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n  }\n\n  > .node-desp {\n    color: #666666;\n    height: 36px;\n    padding: 8px 0;\n    border-bottom: 1px solid #d3d9e6;\n    width: 100%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n  }\n\n  > .node-row {\n    padding-top: 8px;\n\n    > span {\n      display: inline-block;\n      width: 50%;\n      text-align: left;\n      color: #151515;\n\n      > label {\n        color: #666666;\n      }\n    }\n  }\n}\n\n.node-wrapper.node-red {\n  border: 1px solid #e57474;\n  background-color: rgba(236, 147, 147, 0.05);\n}\n\n.member-content {\n  background: white;\n  padding: 10px;\n  .member-content-head {\n    float: right;\n    overflow: hidden;\n    margin-bottom: 10px;\n    display: flex;\n    width: 300px;\n    justify-content: space-between;\n  }\n}\n\n.project-detail-owner {\n  width: 185px;\n  display: inline-block;\n}\n.project-detail-header {\n  background-color: #fff;\n  margin: 0 20px;\n  border-radius: 0 0 8px 8px;\n} \n.menu-container.project-manager {\n  background-color: transparent;\n  padding: 20px 0;\n  margin: 0 20px;\n}\n.project-manager-detail {\n  margin: 0 20px;\n}\n"
  },
  {
    "path": "arius-console/src/container/ProjectManager/index.tsx",
    "content": "import React, { useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getProjectColumns, getProjectQueryXForm } from \"./config\";\nimport { DTable, ITableBtn } from \"component/dantd/dtable\";\nimport { RenderTitle } from \"component/render-title\";\nimport QueryForm from \"component/dantd/query-form\";\nimport { queryFormText } from \"constants/status-map\";\nimport { getProjectList } from \"api/app-api\";\nimport { IPermission } from \"store/type\";\nimport { ProjectPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { getCookie } from \"lib/utils\";\nimport { ProTable } from \"knowdesign\";\nconst mapStateToProps = (state: any) => ({\n  isAdminUser: state.user.isAdminUser,\n  permissionTree: state.user.permissionTree,\n});\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setDrawerId: (modalId: string, params?: any, cb?: any) => dispatch(actions.setDrawerId(modalId, params, cb)),\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nexport const ProjectList = connect(\n  mapStateToProps,\n  mapDispatchToProps\n)((props: { permissionTree: IPermission[]; setDrawerId: any; setModalId: any; isAdminUser: boolean }) => {\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject] = useState({} as any);\n  const [data, setData] = useState([]);\n  const [pagination, setPagination] = useState({\n    current: 1,\n    pageSize: 10,\n    total: 0,\n  });\n\n  React.useEffect(() => {\n    reloadData({ pageNo: 1 });\n  }, [queryFormObject]);\n\n  const reloadData = (param: { pageNo?: number; pageSize?: number } = {}) => {\n    let { pageNo, pageSize } = param;\n    setloading(true);\n\n    pageNo = pageNo || pagination.current;\n    pageSize = pageSize || pagination.pageSize;\n    if (queryFormObject.searchType) {\n      queryFormObject.searchType = +queryFormObject.searchType;\n    }\n    const params = {\n      ...queryFormObject,\n      page: pageNo,\n      size: pageSize,\n    };\n    getProjectList(params)\n      .then((res) => {\n        if (res) {\n          let isAdmin = getCookie(\"isAdminUser\");\n          const list = (res.bizData || []).map((item) => {\n            const ownerIdList = [];\n            const userIdList = [];\n            item.ownersList = (item.ownerList || []).map((row) => {\n              ownerIdList.push(row.id);\n              return {\n                label: row.userName,\n                value: row.id,\n              };\n            });\n            item.usersList = (isAdmin === \"yes\" ? item.userListWithBelongProjectAndAdminRole : item.userList || []).map((row) => {\n              userIdList.push(row.id);\n              return {\n                label: row.userName,\n                title: row.id,\n                key: row.id,\n              };\n            });\n            return {\n              ...item,\n              userIdList,\n              ownerIdList,\n            };\n          });\n\n          setData(list);\n          setPagination({\n            ...pagination,\n            current: res.pagination.pageNo,\n            pageSize: res.pagination.pageSize,\n            total: res.pagination.total,\n          });\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const renderTitleContent = () => {\n    return {\n      title: \"应用管理\",\n      content: null,\n    };\n  };\n\n  const handleSubmit = (result) => {\n    for (const key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject(result);\n  };\n\n  const getOpBtns = (): ITableBtn[] => {\n    return [\n      hasOpPermission(ProjectPermissions.PAGE, ProjectPermissions.ADD) && {\n        label: \"新建应用\",\n        className: \"ant-btn-primary\",\n        clickFunc: () => props.setDrawerId(\"addOrEditProjectModal\", null, reloadData),\n      },\n    ].filter(Boolean);\n  };\n\n  const handleChange = (pagination, filters, sorter) => {\n    reloadData({ pageNo: pagination.current, pageSize: pagination.pageSize });\n  };\n\n  return (\n    <div className=\"table-layout-style\">\n      <ProTable\n        showQueryForm={true}\n        queryFormProps={{\n          defaultCollapse: true,\n          columns: getProjectQueryXForm(),\n          // onChange={() => null}\n          onReset: handleSubmit,\n          onSearch: handleSubmit,\n          isResetClearAll: true,\n        }}\n        tableProps={{\n          tableId: \"project_manager_table\",\n          isCustomPg: false,\n          loading,\n          rowKey: \"id\",\n          dataSource: data,\n          columns: getProjectColumns({\n            setDrawerId: props.setDrawerId,\n            setModalId: props.setModalId,\n            reloadData,\n            isAdminUser: props.isAdminUser,\n            pagination,\n          }),\n          reloadData,\n          getOpBtns,\n          customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n          paginationProps: pagination,\n          attrs: {\n            onChange: handleChange,\n          },\n        }}\n      />\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/ProjectManager/resources-associated.tsx",
    "content": "import React from 'react';\nimport { connect } from \"react-redux\";\nimport _ from 'lodash';\nimport { getResourcesAssociatedListColumns } from './config';\nimport './index.less'\nimport { Dispatch } from 'redux';\nimport * as actions from '../../actions';\nimport { DTable, ITableBtn } from 'component/dantd/dtable';\n\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nexport const ResourcesAssociatedList = (props) => {\n  const [tableData, setTableData] = React.useState([]);\n  const [loading, setLoading] = React.useState(false);\n  const [searchKey, setSearchKey] = React.useState(null);\n\n\n  const reloadData = () => {\n    setLoading(true)\n    const res = {\n      data: [\n        {\n          id: '1',\n          name: 'es-001',\n          type: 'es',\n          auth: '读写'\n        }\n      ]\n    }\n    setLoading(false);\n    setTableData(res.data);\n  }\n\n  const getData = (origin?: any[]) => {\n    if (!searchKey) return origin;\n    const searchKeys = (searchKey + '').trim().toLowerCase();\n    const data = searchKeys ? origin.filter(\n      (d) => {\n        let flat = false;\n        Object.keys(d).forEach((key) => {\n          if (typeof (key) === 'string' || typeof (key) === 'number') {\n            if ((d[key] + '').toLowerCase().includes((searchKeys + '') as string)) {\n              flat = true;\n              return;\n            }\n          }\n        });\n        return flat;\n      }\n    ) : origin;\n    return data;\n  }\n\n  React.useEffect(() => {\n    reloadData();\n  }, []);\n\n  const handleSubmit = (value) => {\n    setSearchKey(value);\n  }\n\n  const getOpBtns = (): ITableBtn[] => {\n    return [{\n      label: '关联资源',\n      className: 'ant-btn-primary',\n      clickFunc: () => props.setModalId('resourcesAssociated', null, reloadData),\n    }];\n  }\n\n  return (\n    <>\n      <DTable\n        loading={loading}\n        rowKey=\"id\"\n        dataSource={getData(tableData)}\n        columns={getResourcesAssociatedListColumns(props.setModalId, reloadData)}\n        reloadData={reloadData}\n        tableHeaderSearchInput={{ submit: handleSubmit }}\n        getOpBtns={getOpBtns}\n      />\n    </>\n  );\n};\n\nexport default connect(null, mapDispatchToProps)(ResourcesAssociatedList);\n"
  },
  {
    "path": "arius-console/src/container/ProjectManager/resources.tsx",
    "content": "import React from 'react';\nimport { connect } from \"react-redux\";\nimport _ from 'lodash';\nimport { getResourcesListColumns } from './config';\nimport './index.less'\nimport { Dispatch } from 'redux';\nimport * as actions from '../../actions';\nimport { DTable } from 'component/dantd/dtable';\n\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nexport const ResourcesList = (props) => {\n  const [tableData, setTableData] = React.useState([]);\n  const [loading, setLoading] = React.useState(false);\n  const [searchKey, setSearchKey] = React.useState(null);\n\n  const getData = (origin?: any[]) => {\n    if (!searchKey) return origin;\n    const searchKeys = (searchKey + '').trim().toLowerCase();\n    const data = searchKeys ? origin.filter(\n      (d) => {\n        let flat = false;\n        Object.keys(d).forEach((key) => {\n          if (typeof (key) === 'string' || typeof (key) === 'number') {\n            if ((d[key] + '').toLowerCase().includes((searchKeys + '') as string)) {\n              flat = true;\n              return;\n            }\n          }\n        });\n        return flat;\n      }\n    ) : origin;\n    return data;\n  }\n\n  const reloadData = () => {\n    setLoading(true)\n    const res = {\n      data: [\n        {\n          id: '1',\n          name: 'es-001',\n          type: 'es'\n        }\n      ]\n    }\n    setLoading(false);\n    setTableData(res.data);\n  }\n\n  React.useEffect(() => {\n    reloadData();\n  }, []);\n\n  const handleSubmit = (value) => {\n    setSearchKey(value);\n  }\n\n  return (\n    <>\n      <DTable\n        loading={loading}\n        rowKey=\"id\"\n        dataSource={getData(tableData)}\n        columns={getResourcesListColumns(props.setModalId, reloadData)}\n        reloadData={reloadData}\n        tableHeaderSearchInput={{ submit: handleSubmit }}\n      />\n    </>\n  );\n};\n\nexport default connect(null, mapDispatchToProps)(ResourcesList);\n"
  },
  {
    "path": "arius-console/src/container/ProjectManager/types.ts",
    "content": "export interface IUser {\n  name: string,\n  id: number,\n}"
  },
  {
    "path": "arius-console/src/container/RoleManager/authorized-list.tsx",
    "content": "import React from 'react';\nimport { connect } from \"react-redux\";\nimport _ from 'lodash';\nimport { getRoleAuthorizedListColumns } from './config';\nimport './index.less'\nimport { Dispatch } from 'redux';\nimport * as actions from '../../actions';\nimport { DTable } from 'component/dantd/dtable';\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nexport const AuthorizedList = (props) => {\n  const [tableData, setTableData] = React.useState([]);\n  const [loading, setLoading] = React.useState(false);\n  const [searchKey, setSearchKey] = React.useState(null);\n\n  const getData = (origin?: any[]) => {\n    if (!searchKey) return origin;\n    const searchKeys = (searchKey + '').trim().toLowerCase();\n    const data = searchKeys ? origin.filter(\n      (d) => {\n        let flat = false;\n        Object.keys(d).forEach((key) => {\n          if (typeof (key) === 'string' || typeof (key) === 'number') {\n            if ((d[key] + '').toLowerCase().includes((searchKeys + '') as string)) {\n              flat = true;\n              return;\n            }\n          }\n        });\n        return flat;\n      }\n    ) : origin;\n    return data;\n  }\n\n  const reloadData = () => {\n    setLoading(true)\n    const res = {\n      data: [\n        {\n          id: '1',\n          name: 'es-001',\n          type: 'es',\n          auth: '读写'\n        }\n      ]\n    }\n    setLoading(false);\n    setTableData(res.data);\n  }\n\n  React.useEffect(() => {\n    reloadData();\n  }, []);\n\n  const handleSubmit = (value) => {\n    setSearchKey(value);\n  }\n\n  return (\n    <>\n      <DTable\n        loading={loading}\n        rowKey=\"id\"\n        dataSource={getData(tableData)}\n        columns={getRoleAuthorizedListColumns(props.setModalId, reloadData)}\n        reloadData={reloadData}\n        tableHeaderSearchInput={{ submit: handleSubmit }}\n      />\n    </>\n  );\n};\n\nexport default connect(null, mapDispatchToProps)(AuthorizedList);\n"
  },
  {
    "path": "arius-console/src/container/RoleManager/config.tsx",
    "content": "import * as React from \"react\";\nimport { Badge, Select, DatePicker } from \"antd\";\nimport moment, { Moment } from \"moment\";\nimport { IMenuItem } from \"interface/common\";\nimport AuthorizedList from \"./authorized-list\";\nimport JurisdictionList from \"./jurisdiction-list\";\nimport { NavRouterLink, renderOperationBtns } from \"container/custom-component\";\nimport { Utils } from \"knowdesign\";\nconst formatDate = Utils.formatDate;\nimport { timeFormat } from \"constants/time\";\n\nconst { Option } = Select;\nconst { RangePicker } = DatePicker;\n\nexport const getRoleColumns = (setModalId: Function, reloadList?: Function) => {\n  // 角色名、涉及模块、授权用户数、描述、创建时间、操作\n  const columns = [\n    {\n      title: \"角色ID\",\n      dataIndex: \"id\",\n      key: \"id\",\n      render: (text: number, record: any) => <NavRouterLink element={text} href={`/es/user/role/detail?syncTaskId=${record.id}`} />,\n    },\n    {\n      title: \"角色名称\",\n      dataIndex: \"roleName\",\n      key: \"roleName\",\n      render: (text: number, record: any) => <NavRouterLink element={text} href={`/es/user/role/detail?syncTaskId=${record.id}`} />,\n    },\n    {\n      title: \"角色描述\",\n      dataIndex: \"description\",\n      key: \"description\",\n    },\n    {\n      title: \"绑定用户数\",\n      dataIndex: \" authedUserCnt\",\n      key: \" authedUserCnt\",\n      render: (text: string[]) => <span>{text?.length}</span>,\n    },\n    {\n      title: \"最后修改人\",\n      dataIndex: \"lastReviser\",\n      key: \"lastReviser\",\n    },\n    {\n      title: \"最后更新时间\",\n      dataIndex: \"updateTime\",\n      key: \"updateTime\",\n      render: (text: number) => {\n        return formatDate(text, timeFormat);\n      },\n    },\n    {\n      title: \"操作项\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      key: \"operation\",\n      render: (text: string, record: any) => {\n        const btns = [\n          {\n            clickFunc: () => setModalId(\"addOrEditRole\", record, reloadList),\n            label: \"编辑\",\n          },\n          {\n            clickFunc: () => setModalId(\"delTask\"),\n            label: \"绑定用户\",\n          },\n          {\n            clickFunc: () => setModalId(\"delTask\"),\n            label: \"删除\",\n          },\n        ];\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n  return columns;\n};\n\nexport const getRoleQueryXForm = () => {\n  return [\n    {\n      type: \"custom\",\n      title: \"创建时间\",\n      dataIndex: \"status\",\n      component: (\n        <RangePicker\n          ranges={{\n            近一天: [moment().subtract(1, \"day\"), moment()],\n            近一周: [moment().subtract(7, \"day\"), moment()],\n            近一月: [moment().subtract(1, \"month\"), moment()],\n          }}\n          format=\"YYYY/MM/DD\"\n        />\n      ),\n    },\n    {\n      type: \"select\",\n      title: \"涉及模块\",\n      dataIndex: \"id\",\n      option: [],\n    },\n    {\n      type: \"input\",\n      title: \"角色名\",\n      dataIndex: \"roleName\",\n      placeholder: \"请输入角色名\",\n    },\n  ];\n};\n\nexport const baseInfo = [\n  {\n    label: \"所属租户\",\n    key: \"name\",\n    render: (value: string) => <>{value}</>,\n  },\n  {\n    label: \"成员数\",\n    key: \"members\",\n  },\n  {\n    label: \"关联资源数\",\n    key: \"resources\",\n  },\n  {\n    label: \"创建时间\",\n    key: \"startTime\",\n  },\n  {\n    label: \"描述\",\n    key: \"desc\",\n  },\n];\n\nexport enum DETAIL_TAB_KEY {\n  authorizedUsers = \"authorizedUsers\",\n  jurisdiction = \"jurisdiction\",\n}\n\nexport const DETAIL_MENU = [\n  {\n    label: \"授权用户\",\n    key: DETAIL_TAB_KEY.authorizedUsers,\n    render: (value: any) => <AuthorizedList />,\n  },\n  {\n    label: \"权限点列表\",\n    key: DETAIL_TAB_KEY.jurisdiction,\n    render: (value: any) => <JurisdictionList />,\n  },\n] as IMenuItem[];\n\nconst menuMap = new Map<string, IMenuItem>();\nDETAIL_MENU.forEach((d) => {\n  menuMap.set(d.key, d);\n});\n\nexport const DETAIL_MENU_MAP = menuMap;\n\nexport const roleDetailBreadcrumb = [\n  {\n    aHref: `/system/role`,\n    label: \"角色列表\",\n  },\n  {\n    label: \"角色详情\",\n  },\n];\n\nexport const getRoleJurisdictionListColumns = (setModalId: Function, reloadList?: Function) => {\n  const columns = [\n    {\n      title: \"模块名\",\n      dataIndex: \"name\",\n      key: \"name\",\n    },\n    {\n      title: \"菜单路径\",\n      dataIndex: \"type\",\n      key: \"type\",\n    },\n    {\n      title: \"权限点\",\n      dataIndex: \"auth\",\n      key: \"auth\",\n    },\n  ];\n  return columns;\n};\n\nexport const getRoleAuthorizedListColumns = (setModalId: Function, reloadList?: Function) => {\n  const columns = [\n    {\n      title: \"用户账号\",\n      dataIndex: \"name\",\n      key: \"name\",\n    },\n    {\n      title: \"用户名\",\n      dataIndex: \"type\",\n      key: \"type\",\n    },\n    {\n      title: \"邮箱\",\n      dataIndex: \"auth\",\n      key: \"auth\",\n    },\n    {\n      title: \"电话\",\n      dataIndex: \"phone\",\n      key: \"phone\",\n    },\n  ];\n  return columns;\n};\n"
  },
  {
    "path": "arius-console/src/container/RoleManager/detail.tsx",
    "content": "import { Alert, Menu, PageHeader } from \"antd\";\nimport * as React from \"react\";\nimport {\n  baseInfo,\n  DETAIL_MENU,\n  DETAIL_MENU_MAP,\n  roleDetailBreadcrumb,\n} from \"./config\";\nimport url from \"lib/url-parser\";\nimport \"../../styles/detail.less\";\nimport \"./index.less\";\nimport { InfoItem } from \"component/info-item\";\n\nexport const RoleDetail = () => {\n  const syncTaskId = +url().search.syncTaskId;\n  const defaultKey =\n    window.location.hash.replace(\"#\", \"\") || DETAIL_MENU[0].key;\n  const [selectedKeys, setSelectedKeys] = React.useState([defaultKey]);\n  const [projectInfo, setTaskInfo] = React.useState({} as any);\n\n  const listenHashChange = () => {\n    window.addEventListener(\n      \"hashchange\",\n      function (this: Window, ev: HashChangeEvent) {\n        setSelectedKeys([window.location.hash.replace(\"#\", \"\")]);\n      }\n    );\n  };\n\n  const handleMenuClick = (e) => {\n    setSelectedKeys([e.key]);\n    window.location.hash = e.key;\n  };\n\n  const getTaskDetail = async () => {\n    if (isNaN(syncTaskId)) return;\n\n    try {\n      setTaskInfo({\n        name: \"xxx\",\n        members: 4,\n        resources: 9,\n        startTime: 222222 - 22,\n        desc: \"desc\",\n      });\n    } catch (e) {\n      //\n    }\n  };\n\n  React.useEffect(() => {\n    getTaskDetail();\n    listenHashChange();\n  }, []);\n\n  const renderContent = () => {\n    // if (!projectInfo) return null;\n\n    return (\n      DETAIL_MENU_MAP.get(selectedKeys?.[0])?.content ||\n      DETAIL_MENU_MAP.get(selectedKeys?.[0])?.render(projectInfo)\n    );\n  };\n\n  const renderPageHeader = () => {\n    return (\n      <PageHeader\n        className=\"detail-header\"\n        backIcon={false}\n        title={<h2>{projectInfo.title || \"dce基础平台部\"}</h2>}\n      >\n        {baseInfo.map((row, index) => (\n          <InfoItem\n            key={index}\n            label={row.label}\n            value={\n              row.render\n                ? row.render(projectInfo?.[row.key])\n                : `${projectInfo?.[row.key] || \"\"}`\n            }\n            width={250}\n          />\n        ))}\n      </PageHeader>\n    );\n  };\n\n  return (\n    <>\n      {renderPageHeader()}\n      <Menu\n        className=\"mt-15\"\n        selectedKeys={selectedKeys}\n        mode=\"horizontal\"\n        onClick={handleMenuClick}\n      >\n        {DETAIL_MENU.map((d) => (\n          <Menu.Item key={d.key}>{d.label}</Menu.Item>\n        ))}\n      </Menu>\n      <div className=\"detail-wrapper\">{renderContent()}</div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/RoleManager/index.less",
    "content": ".status-content {\n  background-color: white;\n  padding: 18px;\n\n  h2 {\n    margin-top: 24px;\n    font-family: PingFangSC-Medium;\n    font-size: 14px;\n    color: #333333;\n  }\n\n  .run-topo-wrapper {\n    background-color: #F7F8FA;\n  }\n}\n\n.tp-editor-wrapper {\n  height: 500px;\n  background-color: white;\n  padding-top: 18px;\n\n  .op-btns {\n    text-align: right;\n    margin-right: 30px;\n  }\n}\n\n.log-filter {\n  padding-top: 18px;\n  background-color: white;\n}\n\n.node-wrapper {\n  background-color: #fff;\n  border: 1px solid #D3D9E6;\n  border-radius: 4px;\n  padding: 8px 16px;\n  width: 232px;\n  cursor: pointer;\n\n  >h2 {\n    font-family: PingFangSC-Medium;\n    font-size: 12px;\n    color: #333333;\n    margin: 0;\n    width: 100%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n  }\n\n  >.node-desp {\n    color: #666666;\n    height: 36px;\n    padding: 8px 0;\n    border-bottom: 1px solid #D3D9E6;\n    width: 100%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n  }\n\n  >.node-row {\n    padding-top: 8px;\n\n    >span {\n      display: inline-block;\n      width: 50%;\n      text-align: left;\n      color: #151515;\n\n      >label {\n        color: #666666;\n      }\n    }\n  }\n}\n\n.node-wrapper.node-red {\n  border: 1px solid #E57474;\n  background-color: rgba(236, 147, 147, 0.05);\n}\n\n.member-content{\n  background: white;\n  padding: 10px;\n  .member-content-head{\n    float: right;\n    overflow: hidden;\n    margin-bottom: 10px;\n    display: flex;\n    width: 300px;\n    justify-content: space-between;\n  }\n}"
  },
  {
    "path": "arius-console/src/container/RoleManager/index.tsx",
    "content": "import React, { useState } from 'react';\nimport { connect } from \"react-redux\";\nimport _ from 'lodash';\nimport { getRoleColumns, getRoleQueryXForm } from './config';\nimport { Dispatch } from 'redux';\nimport * as actions from '../../actions';\nimport { DTable, ITableBtn } from 'component/dantd/dtable';\nimport { RenderTitle } from 'component/render-title';\nimport QueryForm from 'component/dantd/query-form';\nimport { queryFormText } from 'constants/status-map';\nimport { getRoleList } from 'api/logi-security';\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\ntype Props = ReturnType<typeof mapDispatchToProps>;\n\ninterface IQueryParams {\n  id: number;\n  taskName: string;\n  projectName: string;\n  status: string;\n  owner: string;\n}\n\nconst RoleList: React.FC<Props> = (props) => {\n  const department: string = localStorage.getItem('current-project');\n  const [loading, setLoading] = React.useState(false);\n  const [queryFormObject, setqueryFormObject] = useState({});\n  const [data, setData] = useState([]);\n  const [pagination, setPagination] = useState({\n    current: 1,\n    pageSize: 10,\n    total: 0,\n  });\n\n  React.useEffect(() => {\n    reloadData();\n  }, [department]);\n\n  const reloadData = () => {\n    const { current, pageSize } = pagination;\n    const params = {\n      ...queryFormObject,\n      page: current,\n      size: pageSize,\n    };\n    setLoading(true)\n    getRoleList(params).then((res) => {\n      if (res) {\n        setData(res.bizData)\n        setPagination({\n          current: res.pagination.pageNo,\n          pageSize: res.pagination.pageSize,\n          total: res.pagination.total,\n        });\n      }\n    }).finally(() => {\n      setLoading(false)\n    })\n  }\n\n  const renderTitleContent = () => {\n    return {\n      title: '角色',\n      content: null\n    }\n  }\n\n  const handleSubmit = (result) => {\n    for (var key in result) {\n      if (result[key] === '' || result[key] === undefined) {\n        delete result[key]\n      }\n    }\n    setqueryFormObject(result);\n  };\n\n  const getOpBtns = (): ITableBtn[] => {\n    return [{\n      label: '新增角色',\n      className: 'ant-btn-primary',\n      clickFunc: () => props.setModalId('addOrEditRole', null, reloadData),\n    }];\n  }\n\n  return (\n    <>\n      <div className=\"table-header\">\n        <RenderTitle {...renderTitleContent()} />\n        <QueryForm {...queryFormText} defaultCollapse columns={getRoleQueryXForm()} onChange={() => null} onReset={handleSubmit} onSearch={handleSubmit} initialValues={{}} isResetClearAll />\n      </div>\n      <div>\n        <div className=\"table-content\">\n          <DTable\n            loading={loading}\n            rowKey=\"id\"\n            dataSource={data}\n            columns={getRoleColumns(props.setModalId, reloadData)}\n            reloadData={reloadData}\n            getOpBtns={getOpBtns}\n          />\n        </div>\n      </div>\n    </>\n  )\n};\n\nexport default connect(null, mapDispatchToProps)(RoleList);\n"
  },
  {
    "path": "arius-console/src/container/RoleManager/jurisdiction-list.tsx",
    "content": "import React from 'react';\nimport { connect } from \"react-redux\";\nimport _ from 'lodash';\nimport { getRoleJurisdictionListColumns } from './config';\nimport './index.less'\nimport { Dispatch } from 'redux';\nimport * as actions from '../../actions';\nimport { DTable } from 'component/dantd/dtable';\n\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nexport const JurisdictionList = (props) => {\n  const [tableData, setTableData] = React.useState([]);\n  const [loading, setLoading] = React.useState(false);\n  const [searchKey, setSearchKey] = React.useState(null);\n\n  const getData = (origin?: any[]) => {\n    if (!searchKey) return origin;\n    const searchKeys = (searchKey + '').trim().toLowerCase();\n    const data = searchKeys ? origin.filter(\n      (d) => {\n        let flat = false;\n        Object.keys(d).forEach((key) => {\n          if (typeof (key) === 'string' || typeof (key) === 'number') {\n            if ((d[key] + '').toLowerCase().includes((searchKeys + '') as string)) {\n              flat = true;\n              return;\n            }\n          }\n        });\n        return flat;\n      }\n    ) : origin;\n    return data;\n  }\n\n  const reloadData = () => {\n    setLoading(true)\n    const res = {\n      data: [\n        {\n          id: '1',\n          name: 'es-001',\n          type: 'es',\n          auth: '读写'\n        }\n      ]\n    }\n    setLoading(false);\n    setTableData(res.data);\n  }\n\n  React.useEffect(() => {\n    reloadData();\n  }, []);\n\n  const handleSubmit = (value) => {\n    setSearchKey(value);\n  }\n\n  return (\n    <>\n      <DTable\n        loading={loading}\n        rowKey=\"id\"\n        dataSource={getData(tableData)}\n        columns={getRoleJurisdictionListColumns(props.setModalId, reloadData)}\n        reloadData={reloadData}\n        tableHeaderSearchInput={{ submit: handleSubmit }}\n      />\n    </>\n  );\n};\n\nexport default connect(null, mapDispatchToProps)(JurisdictionList);\n"
  },
  {
    "path": "arius-console/src/container/RoleManager/types.ts",
    "content": "export interface IUser {\n  name: string,\n  id: number,\n}"
  },
  {
    "path": "arius-console/src/container/Scheduling/config.tsx",
    "content": "import React from \"react\";\nimport { transTimeFormat } from \"lib/utils\";\nimport { Link } from \"react-router-dom\";\nimport { IColumnsType } from \"component/dantd/query-form/QueryForm\";\nimport { Modal, DatePicker, message } from \"antd\";\nimport { IStatusMap } from \"typesPath/base-types\";\nimport { renderOperationBtns } from \"container/custom-component\";\nimport { taskStatus, taskDo, jobStop } from \"api/Scheduling\";\nimport moment from \"moment\";\nimport DRangeTime from \"../../d1-packages/d-range-time\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { ShceduleLogPermissions } from \"constants/permission\";\n\nconst { confirm } = Modal;\n\nexport const StatusMap = {\n  0: \"Paused\",\n  1: \"Normal\",\n} as IStatusMap;\n\nexport const logStatusMap = {\n  0: \"调度启动中\",\n  1: \"调度运行中\",\n  2: \"调度成功\",\n  3: \"调度失败\",\n  4: \"调度取消\",\n};\n\nexport const resultMap = {\n  \"-1\": \"失败\",\n  0: \"运行中\",\n  1: \"成功\",\n};\n\nexport const mockData = [\n  {\n    id: 1001,\n    text: \"平滑迁移\",\n    taskType: \"10.166.189.142:9999\",\n    time: \"2021-08-16 13:15:00\",\n    result: \"成功\",\n    startTime: \"2021-08-16 13:15:00\",\n    endTime: \"2021-08-16 13:15:00\",\n  },\n];\n\nexport const getSchedulingLogColumns = (reloadData: Function, showDetail: Function, showLog: Function) => {\n  const getCongigBtnList = (reloadData: any, showDetail: Function, showLog: Function, record) => {\n    return [\n      hasOpPermission(ShceduleLogPermissions.PAGE, ShceduleLogPermissions.DETAIL) && {\n        label: \"调度详情\",\n        clickFunc: () => {\n          showDetail(record);\n        },\n      },\n      hasOpPermission(ShceduleLogPermissions.PAGE, ShceduleLogPermissions.LOG) && {\n        label: \"执行日志\",\n        clickFunc: (record: any) => {\n          showLog(record);\n        },\n      },\n      hasOpPermission(ShceduleLogPermissions.PAGE, ShceduleLogPermissions.END_MISSION) && {\n        label: `${record.status === 2 && record.result.indexOf(\"0\") !== -1 ? \"终止任务\" : \"\"}`,\n        clickFunc: () => {\n          showStop(record, reloadData);\n        },\n      },\n    ];\n  };\n  const orderColumns = [\n    {\n      title: \"任务ID\",\n      dataIndex: \"taskId\",\n      key: \"taskId\",\n      width: 70,\n    },\n    {\n      title: \"任务名称\",\n      dataIndex: \"taskDesc\",\n      key: \"taskDesc\",\n      width: 130,\n      lineClampTwo: true,\n      needTooltip: true,\n    },\n    {\n      title: \"调度地址\",\n      dataIndex: \"workerIp\",\n      key: \"workerIp\",\n      width: 120,\n      lineClampOne: true,\n      needTooltip: true,\n    },\n    {\n      title: \"调度时间\",\n      dataIndex: \"createTime\",\n      key: \"createTime\",\n      sorter: true,\n      width: 150,\n      render: (t: string) => transTimeFormat(t),\n    },\n    {\n      title: \"调度结果\",\n      dataIndex: \"status\",\n      key: \"status\",\n      width: 90,\n      sorter: true,\n      render: (text) => {\n        return logStatusMap[text];\n      },\n    },\n    {\n      title: \"执行开始时间\",\n      dataIndex: \"startTime\",\n      key: \"startTime\",\n      width: 150,\n      sorter: true,\n      render: (t: string) => transTimeFormat(t),\n    },\n    {\n      title: \"执行结束时间\",\n      dataIndex: \"endTime\",\n      key: \"endTime\",\n      width: 150,\n      sorter: true,\n      render: (t: string) => transTimeFormat(t),\n    },\n    {\n      title: \"执行结果\",\n      dataIndex: \"result\",\n      key: \"result\",\n      width: 90,\n      sorter: true,\n      render: (text) => {\n        if (text) {\n          const obj = JSON.parse(text);\n          return resultMap[obj.code];\n        }\n        return \"-\";\n      },\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      fixed: \"right\",\n      width: 220,\n      render: (text: any, record: any) => {\n        const btns: any = getCongigBtnList(reloadData, showDetail, showLog, record);\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n  return orderColumns;\n};\n\nexport const getSchedulingLogQueryXForm = (isDetail, handleTimeChange) => {\n  const customTimeOptions = [\n    {\n      label: \"最近 1 天\",\n      value: 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 7 天\",\n      value: 7 * 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 1 月\",\n      value: 30 * 24 * 60 * 60 * 1000,\n    },\n  ];\n  const log = [\n    {\n      dataIndex: \"taskId\",\n      title: \"任务ID\",\n      type: \"input\",\n      placeholder: \"请输入任务ID\",\n      rules: [\n        {\n          required: false,\n          validator: (rule: any, value: string) => {\n            if (value && !new RegExp(regNonnegativeInteger).test(value)) {\n              return Promise.reject(new Error(\"请输入正确格式\"));\n            }\n            if (value?.length > 16) {\n              return Promise.reject(new Error(\"请输入正确ID，0-16位字符\"));\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      // todo： 字段确认\n      dataIndex: \"taskDesc\",\n      title: \"任务名称\",\n      type: \"input\",\n      placeholder: \"请输入任务名称\",\n    },\n  ] as IColumnsType[];\n  let formMap = [\n    {\n      dataIndex: \"taskStatus\",\n      title: \"调度状态\",\n      type: \"select\",\n      options: Object.keys(logStatusMap).map((key) => ({\n        value: key,\n        title: logStatusMap[key],\n      })),\n      placeholder: \"请选择工单状态\",\n    },\n    {\n      dataIndex: \"createTime\",\n      title: \"调度时间\",\n      type: \"custom\",\n      component: (\n        <DRangeTime timeChange={handleTimeChange} popoverClassName=\"dashborad-popover\" customTimeOptions={customTimeOptions} />\n        // <DatePicker.RangePicker\n        //   style={{ width: \"100%\" }}\n        //   ranges={{\n        //     近一天: [moment().subtract(1, \"day\"), moment()],\n        //     近一周: [moment().subtract(7, \"day\"), moment()],\n        //     近一月: [moment().subtract(1, \"month\"), moment()],\n        //   }}\n        //   showTime={{ format: \"HH:mm\" }}\n        //   format=\"YYYY-MM-DD\"\n        // />\n      ),\n    },\n  ] as IColumnsType[];\n  if (!isDetail) {\n    formMap = [...log, ...formMap];\n  }\n  return formMap;\n};\n\nexport const getTaskListQueryXForm = () => {\n  let formMap = [\n    {\n      dataIndex: \"taskId\",\n      title: \"任务ID\",\n      type: \"input\",\n      placeholder: \"请输入任务ID\",\n      rules: [\n        {\n          required: false,\n          validator: (rule: any, value: string) => {\n            if (value && !new RegExp(regNonnegativeInteger).test(value)) {\n              return Promise.reject(new Error(\"请输入正确格式\"));\n            }\n            if (value?.length > 16) {\n              return Promise.reject(new Error(\"请输入正确ID，0-16位字符\"));\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      dataIndex: \"taskDesc\",\n      title: \"任务名称\",\n      type: \"input\",\n      placeholder: \"请输入任务名称\",\n    },\n    {\n      dataIndex: \"className\",\n      title: \"JobHandler\",\n      type: \"input\",\n      placeholder: \"请输入JobHandler\",\n    },\n    {\n      dataIndex: \"taskStatus\",\n      title: \"状态\",\n      type: \"select\",\n      options: Object.keys(StatusMap).map((key) => ({\n        value: Number(key),\n        title: StatusMap[key],\n      })),\n      placeholder: \"请选择\",\n    },\n  ] as IColumnsType[];\n  return formMap;\n};\n\n// 改变状态\nexport const showTaskStatus = (record, reloadData: Function) => {\n  confirm({\n    title: \"提示\",\n    content: `确定${record.status ? \"暂停\" : \"恢复\"}${record.taskDesc}【${record.id}】？`,\n    onOk() {\n      taskStatus(record.taskCode, record.status ? 0 : 1).then((res) => {\n        if (res) {\n          message.success(\"操作成功\");\n        } else {\n          message.warning(\"操作失败\");\n        }\n        reloadData();\n      });\n    },\n  });\n};\n\n// 执行操作\nexport const showTaskDo = (record, reloadData: Function) => {\n  confirm({\n    title: \"提示\",\n    content: `确定执行${record.taskDesc}【${record.id}】？`,\n    onOk() {\n      taskDo(record.taskCode).then((res) => {\n        message.success(\"操作成功\");\n        reloadData();\n      });\n    },\n  });\n};\n\n// 执行操作\nexport const showStop = (record, reloadData: Function) => {\n  confirm({\n    title: \"提示\",\n    content: `确定终止任务？`,\n    onOk() {\n      jobStop(record.jobCode).then((res) => {\n        if (res) {\n          message.success(\"操作成功\");\n        } else {\n          message.warning(\"操作失败\");\n        }\n        reloadData();\n      });\n    },\n  });\n};\n\nexport const getTaskListColumns = (reloadData: Function, showDetail: Function) => {\n  const getCongigBtnList = (reloadData: Function, record: any) => {\n    return [\n      {\n        label: \"执行\",\n        clickFunc: () => {\n          showTaskDo(record, reloadData);\n        },\n      },\n      {\n        label: `${record.status == 1 ? \"暂停\" : \"恢复\"}`,\n        clickFunc: () => {\n          showTaskStatus(record, reloadData);\n        },\n      },\n    ];\n  };\n  const orderColumns = [\n    {\n      title: \"任务ID\",\n      dataIndex: \"id\",\n      width: 90,\n      render: (text: any, record: any) => {\n        const btns: any = [\n          {\n            label: text,\n            clickFunc: () => {\n              showDetail(record);\n            },\n          },\n        ];\n        return renderOperationBtns(btns, record);\n      },\n    },\n    {\n      title: \"任务名称\",\n      dataIndex: \"taskDesc\",\n      width: \"20vw\",\n      lineClampTwo: true,\n      needTooltip: true,\n      render: (text) => <div style={{ wordWrap: \"break-word\", wordBreak: \"break-word\" }}>{text}</div>,\n    },\n    {\n      title: \"JobHandler\",\n      dataIndex: \"className\",\n      width: \"20vw\",\n      lineClampTwo: true,\n      needTooltip: true,\n      render: (text) => <div style={{ wordWrap: \"break-word\", wordBreak: \"break-word\" }}>{text}</div>,\n    },\n    {\n      title: \"Corn\",\n      dataIndex: \"cron\",\n    },\n    {\n      title: \"责任人\",\n      dataIndex: \"owner\",\n    },\n    {\n      title: \"状态\",\n      dataIndex: \"status\",\n      width: 120,\n      render: (t: number) => {\n        if (StatusMap[t] === \"Normal\") {\n          return (\n            <div>\n              <svg className=\"icon\" aria-hidden=\"true\" style={{ marginRight: 5 }}>\n                <use xlinkHref=\"#iconwancheng\"></use>\n              </svg>\n              {StatusMap[t]}\n            </div>\n          );\n        }\n        return (\n          <div>\n            <svg className=\"icon\" aria-hidden=\"true\" style={{ marginRight: 5 }}>\n              <use xlinkHref=\"#iconzanting\"></use>\n            </svg>\n            {StatusMap[t]}\n          </div>\n        );\n      },\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      width: 190,\n      render: (text: any, record: any) => {\n        const btns: any = getCongigBtnList(reloadData, record);\n        return (\n          <div>\n            {renderOperationBtns(btns, record)}\n            <Link to={`/scheduling/log/detail?taskId=${record.id}`} style={{ marginLeft: 10 }}>\n              查看日志\n            </Link>\n          </div>\n        );\n      },\n    },\n  ];\n  return orderColumns;\n};\n"
  },
  {
    "path": "arius-console/src/container/Scheduling/schedulinglog.tsx",
    "content": "import React, { useState, useEffect, useMemo, useRef } from \"react\";\nimport { getSchedulingLogQueryXForm, getSchedulingLogColumns, mockData } from \"./config\";\nimport QueryForm from \"component/dantd/query-form\";\nimport { getLogsList } from \"api/Scheduling\";\n// todo 接口好后增加类型判断\n// import { ITask } from '@types/task-types';\nimport { queryFormText } from \"constants/status-map\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { RenderTitle } from \"component/render-title\";\nimport SchDulingDetail from \"./../drawer/scheduling-detail\";\nimport SchDulingLog from \"./../drawer/scheduling-log\";\nimport getUrlParams from \"lib/url-parser\";\nimport { ProTable } from \"knowdesign\";\nexport const Schedulinglog = () => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject]: any = useState({});\n  const [pagination, setPagination] = useState({\n    current: 1,\n    pageSize: 10,\n  });\n  const [data, setData] = useState([] as any[]);\n  // 控制调度日志的状态\n  const [visible, setVisible] = useState(false);\n  const [record, setRecord]: any = useState({});\n  // 控制执行日志的状态\n  const [logVisible, setLogVisible] = useState(false);\n  const [urlParams, setUrlParams]: any = useState(getUrlParams().search);\n  const [total, setTotal] = useState(0);\n  const [startAndEnd, setStartAndEnd] = useState([]);\n  //const [resetValue, setResetValue] = useState(null);\n  const buttonTime = useRef(null);\n  useEffect(() => {\n    reloadData({});\n  }, [department, urlParams, queryFormObject]);\n  // React.useEffect(() => {\n  //   //setResetValue初始化只会执行一次\n  //   if (resetValue) {\n  //     for (var i in resetValue) {\n  //       resetValue[i](undefined)\n  //     }\n  //   }\n  // }, [resetValue]);\n  const reloadData = ({ page = pagination.current, size = pagination.pageSize }) => {\n    setloading(true);\n    const params = {\n      sortName: \"create_time\",\n      sortAsc: \"desc\",\n      ...urlParams,\n      ...queryFormObject,\n      page,\n      size,\n      beginTime: queryFormObject?.createTime?.length ? queryFormObject?.createTime[0]?.valueOf() : \"\",\n      endTime: queryFormObject?.createTime?.length ? queryFormObject?.createTime[1]?.valueOf() : \"\",\n    };\n    getLogsList(params)\n      .then((res: any) => {\n        if (res) {\n          setData(res?.bizData);\n          setTotal(res.pagination.total);\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const handleSubmit = (result) => {\n    // 增加点击刷新按钮先计算时间差 保持用户选择的事件范围\n    //判断此时是否是自定义时间情况，如果是则不需要实时更新时间戳，反之不需要。\n    const copyResult = JSON.parse(JSON.stringify(result));\n    const time = startAndEnd[1] - startAndEnd[0];\n    const currentTime = new Date().getTime();\n    const isCustomTime = buttonTime.current ? [currentTime - time, currentTime] : startAndEnd;\n    copyResult.createTime = isCustomTime;\n    for (var key in copyResult) {\n      if (copyResult[key] === \"\" || copyResult[key] === undefined) {\n        delete copyResult[key];\n      }\n    }\n    setPagination({ ...pagination, current: 1 });\n    setqueryFormObject({ ...copyResult });\n  };\n\n  const handleTimeChange = (times: number[], periodOrPicker: boolean) => {\n    //periodOrPicker为true表示此时时间选择器选的是period，false表示Picker\n    if (times) {\n      setStartAndEnd(times);\n      buttonTime.current = periodOrPicker;\n    }\n  };\n  // const resetAllValue = (obj = {}) => {\n  //   setResetValue({ ...obj })\n  // }\n  const resetSubmit = (result) => {\n    buttonTime.current = false;\n    setStartAndEnd([]);\n    // if (resetValue) {\n    //   for (var i in resetValue) {\n    //     resetValue[i](undefined)\n    //   }\n    // }\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject(result);\n  };\n\n  const renderTitleContent = () => {\n    return {\n      title: \"调度日志\",\n      content: null,\n    };\n  };\n\n  const showDetail = (record) => {\n    setRecord(record);\n    setVisible(true);\n  };\n\n  const onCancel = () => {\n    setVisible(false);\n  };\n\n  const showLog = (record) => {\n    setRecord(record);\n    setLogVisible(true);\n  };\n\n  const onLogCancel = () => {\n    setLogVisible(false);\n  };\n\n  const handleChange = ({ current, pageSize }, filters, sorter) => {\n    setPagination({\n      current,\n      pageSize,\n    });\n    const sorterObject: { [key: string]: any } = {};\n    if (sorter.columnKey && sorter.order) {\n      switch (sorter.columnKey) {\n        case \"createTime\":\n          sorterObject.sortName = \"create_time\";\n          sorterObject.sortAsc = sorter.order === \"ascend\" ? \"asc\" : \"desc\";\n          break;\n        case \"status\":\n          sorterObject.sortName = \"status\";\n          sorterObject.sortAsc = sorter.order === \"ascend\" ? \"asc\" : \"desc\";\n          break;\n        case \"startTime\":\n          sorterObject.sortName = \"start_time\";\n          sorterObject.sortAsc = sorter.order === \"ascend\" ? \"asc\" : \"desc\";\n          break;\n        case \"endTime\":\n          sorterObject.sortName = \"end_time\";\n          sorterObject.sortAsc = sorter.order === \"ascend\" ? \"asc\" : \"desc\";\n          break;\n        case \"result\":\n          sorterObject.sortName = \"result\";\n          sorterObject.sortAsc = sorter.order === \"ascend\" ? \"asc\" : \"desc\";\n          break;\n        default:\n          break;\n      }\n    }\n    setqueryFormObject((state) => {\n      if (!sorter.order) {\n        delete state.sortName;\n        delete state.sortAsc;\n      }\n      return {\n        ...state,\n        ...sorterObject,\n        page: current,\n        size: pageSize,\n      };\n    });\n  };\n\n  return (\n    <>\n      <div className=\"table-layout-style\">\n        <ProTable\n          showQueryForm={true}\n          queryFormProps={{\n            defaultCollapse: true,\n            columns: getSchedulingLogQueryXForm(urlParams.taskCode ? true : false, handleTimeChange),\n            // onChange={() => null}\n            onReset: resetSubmit,\n            onSearch: handleSubmit,\n            // initialValues={{}}\n            isResetClearAll: true,\n          }}\n          tableProps={{\n            tableId: \"scheduling_table\",\n            isCustomPg: false,\n            loading,\n            rowKey: \"id\",\n            dataSource: data,\n            columns: getSchedulingLogColumns(reloadData, showDetail, showLog),\n            reloadData,\n            isDividerHide: false,\n            customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n            paginationProps: {\n              position: \"bottomRight\",\n              showQuickJumper: true,\n              total: total,\n              showSizeChanger: true,\n              pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n              showTotal: (total) => `共 ${total} 条`,\n              current: pagination.current,\n              pageSize: pagination.pageSize,\n            },\n            attrs: {\n              onChange: handleChange,\n              scroll: { x: 1160, y: 600 },\n            },\n          }}\n        />\n        <SchDulingDetail visible={visible} record={record} onCancel={onCancel} />\n        <SchDulingLog visible={logVisible} error={record.result} onCancel={onLogCancel} />\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/Scheduling/taskList.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { getTaskListQueryXForm, getTaskListColumns } from \"./config\";\nimport QueryForm from \"component/dantd/query-form\";\nimport { getTaskList } from \"api/Scheduling\";\n// todo 接口好后增加类型判断\n// import { ITask } from '@types/task-types';\nimport { queryFormText } from \"constants/status-map\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { RenderTitle } from \"component/render-title\";\nimport TaskListDetail from \"./../drawer/tasklist-detail\";\nimport { ProTable } from \"knowdesign\";\nimport { cloneDeep } from \"lodash\";\n\nexport const TaskList = () => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject]: any = useState({\n    page: 1,\n    size: 10,\n    current: 1,\n  });\n  const [data, setData] = useState([] as any[]);\n  // 控制抽屉的状态\n  const [visible, setVisible] = useState(false);\n  const [detailData, setDetailData] = useState({});\n  const [total, setTotal] = useState(0);\n\n  useEffect(() => {\n    reloadData();\n  }, [department, queryFormObject]);\n\n  const reloadData = () => {\n    setloading(true);\n    const params = cloneDeep(queryFormObject);\n    delete params.current;\n    getTaskList(params)\n      .then((res: any) => {\n        if (res) {\n          setData(res.bizData);\n          setTotal(res.pagination.total);\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const handleSubmit = (result) => {\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject({ ...result, page: 1, size: queryFormObject.size, current: 1 });\n  };\n\n  const renderTitleContent = () => {\n    return {\n      title: \"任务列表\",\n      content: null,\n    };\n  };\n\n  const showDetail = (record) => {\n    setVisible(true);\n    setDetailData(record);\n  };\n\n  const onCancel = () => {\n    setVisible(false);\n  };\n\n  const handleChange = (pagination) => {\n    setqueryFormObject({\n      ...queryFormObject,\n      size: pagination.pageSize,\n      page: pagination.current,\n      current: pagination.current,\n    });\n  };\n\n  return (\n    <>\n      <div className=\"table-layout-style\">\n        <ProTable\n          showQueryForm={true}\n          queryFormProps={{\n            defaultCollapse: true,\n            columns: getTaskListQueryXForm(),\n            // onChange={() => null}\n            onReset: handleSubmit,\n            onSearch: handleSubmit,\n            // initialValues={{}}\n            isResetClearAll: true,\n          }}\n          tableProps={{\n            tableId: \"scheduling_task_table\",\n            isCustomPg: false,\n            loading,\n            rowKey: \"id\",\n            dataSource: data,\n            columns: getTaskListColumns(reloadData, showDetail),\n            reloadData,\n            isDividerHide: false,\n            customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n            paginationProps: {\n              total,\n              pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n              showTotal: (total) => `共 ${total} 条`,\n              current: queryFormObject.current,\n              pageSize: queryFormObject.size,\n            },\n            attrs: {\n              onChange: handleChange,\n            },\n          }}\n        />\n        <TaskListDetail visible={visible} onCancel={onCancel} detailData={detailData} />\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/cluster-edition.tsx",
    "content": "import React, { useRef, useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getEditionQueryXForm, getVersionsColumns } from \"./config\";\nimport { getPackageList } from \"api/cluster-api\";\nimport { DTable, ITableBtn } from \"component/dantd/dtable\";\nimport { RenderTitle } from \"component/render-title\";\nimport QueryForm from \"component/dantd/query-form\";\nimport moment from \"moment\";\nimport { queryFormText } from \"constants/status-map\";\nimport { isOpenUp } from \"constants/common\";\nimport { ClusterVersionPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { ProTable } from \"knowdesign\";\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params, cb)),\n});\n\nexport const EditionCluster = connect(\n  null,\n  mapDispatchToProps\n)((props: any) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject] = useState([]);\n  const [data, setData] = useState([]);\n  const [startAndEnd, setStartAndEnd] = useState([]);\n  //const [resetValue, setResetValue] = useState(null);\n  const buttonTime = useRef(null);\n\n  React.useEffect(() => {\n    reloadData();\n  }, [department]);\n  // React.useEffect(() => {\n  //   //setResetValue初始化只会执行一次\n  //   if (resetValue) {\n  //     for (var i in resetValue) {\n  //       resetValue[i](undefined)\n  //     }\n  //   }\n  // }, [resetValue]);\n  const getData = () => {\n    // 查询项的key 要与 数据源的key  对应\n    if (!queryFormObject) return data;\n    const keys = Object.keys(queryFormObject);\n    const filterData = data.filter((d) => {\n      let b = true;\n      keys.forEach((k: string) => {\n        if (k === \"createTime\") {\n          const time = moment(d[k]).unix() * 1000;\n          if (queryFormObject[k][0] > time || time > queryFormObject[k][1]) {\n            b = false;\n          }\n        } else {\n          (d[k] + \"\")?.toLowerCase().includes(queryFormObject[k]) ? \"\" : (b = false);\n        }\n      });\n      return b;\n    });\n    return filterData;\n  };\n\n  const reloadData = () => {\n    setloading(true);\n    getPackageList()\n      .then((res) => {\n        if (res) {\n          setData(res);\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const renderTitleContent = () => {\n    return {\n      title: \"集群版本\",\n      content: null,\n    };\n  };\n\n  const handleSubmit = (result) => {\n    const copyResult = JSON.parse(JSON.stringify(result));\n    // 增加点击刷新按钮先计算时间差 保持用户选择的事件范围\n    //判断此时是否是自定义时间情况，如果是则不需要实时更新时间戳，反之不需要。\n    const time = startAndEnd[1] - startAndEnd[0];\n    const currentTime = new Date().getTime();\n    const isCustomTime = buttonTime.current ? [currentTime - time, currentTime] : startAndEnd;\n    copyResult.createTime = isCustomTime;\n    for (var key in copyResult) {\n      if (copyResult[key] === \"\" || copyResult[key] === undefined) {\n        delete copyResult[key];\n      }\n    }\n    setqueryFormObject(copyResult);\n  };\n  const resetSubmit = (result) => {\n    buttonTime.current = false;\n    setStartAndEnd([]);\n    // if (resetValue) {\n    //   for (var i in resetValue) {\n    //     resetValue[i](undefined)\n    //   }\n    // }\n\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject(result);\n  };\n\n  const handleTimeChange = (times: number[], periodOrPicker: boolean) => {\n    //periodOrPicker为true表示此时时间选择器选的是period，false表示Picker\n    if (times) {\n      setStartAndEnd(times);\n      buttonTime.current = periodOrPicker;\n    }\n  };\n  // const resetAllValue = (obj = {}) => {\n  //   setResetValue({ ...obj })\n  // }\n\n  const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n\n  return (\n    <div className=\"table-layout-style\">\n      <ProTable\n        showQueryForm={true}\n        queryFormProps={{\n          // layout: \"inline\", //没有label的查询条件\n          // colMode: \"style\", //col默认设计样式\n          totalNumber: data.length || 0, //传入总条数\n          defaultCollapse: true,\n          columns: getEditionQueryXForm(data, handleTimeChange),\n          // onChange={() => null}\n          onReset: resetSubmit,\n          onSearch: handleSubmit,\n          // initialValues={{}}\n          isResetClearAll: true,\n        }}\n        tableProps={{\n          tableId: \"cluster_edition_list\", //开启表格自定义列\n          isCustomPg: false,\n          loading,\n          rowKey: \"id\",\n          dataSource: getData(),\n          columns: getVersionsColumns(props.setDrawerId, reloadData),\n          isDividerHide: false,\n          reloadData,\n          customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n          attrs: {\n            scroll: { x: \"max-content\" },\n          },\n        }}\n      />\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/cluster/config.tsx",
    "content": "import React from \"react\";\nimport { renderOperationBtns, NavRouterLink } from \"container/custom-component\";\nimport { InfoCircleOutlined } from \"@ant-design/icons\";\nimport { message, Tag, Modal, Tooltip, DatePicker } from \"antd\";\nimport { IOpLogicCluster, IOpPhysicsCluster } from \"typesPath/cluster/cluster-types\";\nimport { ClusterStatus, clusterTypeMap, logicClusterType, StatusMap } from \"constants/status-map\";\nimport { cellStyle } from \"constants/table\";\nimport { delPackage } from \"api/cluster-api\";\nimport { ITableBtn } from \"component/dantd/dtable\";\nimport { IVersions } from \"typesPath/cluster/physics-type\";\nimport store from \"store\";\nimport { IColumnsType } from \"component/dantd/query-form/QueryForm\";\nimport { isOpenUp, LEVEL_MAP } from \"constants/common\";\nimport { renderDiskRate } from \"../custom-component\";\nimport { PhyClusterPermissions, MyClusterPermissions, ClusterVersionPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { renderAttributes } from \"container/custom-component\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport DRangeTime from \"../../d1-packages/d-range-time\";\nimport { transTimeFormat } from \"lib/utils\";\nimport { XNotification } from \"component/x-notification\";\n\nconst loginInfo = {\n  userName: store.getState().user?.getName,\n  app: store.getState().app,\n};\nconst { RangePicker } = DatePicker;\nconst { confirm } = Modal;\n\nexport const getOptions = (data, type: string | number) => {\n  if (!data) return [];\n  const arr = Array.from(\n    new Set(\n      data.map((item) => {\n        return item?.[type];\n      })\n    )\n  );\n\n  const options = arr.map((item) => ({\n    title: item,\n    value: item,\n  }));\n\n  return options;\n};\n\nexport const getPhyClusterQueryXForm = (\n  data: IOpPhysicsCluster[],\n  packageHostList: any,\n  phyClusterList = [],\n  logiClusterList = [],\n  onPhyClusterChange\n) => {\n  const formMap = [\n    {\n      dataIndex: \"id\",\n      title: \"集群ID:\",\n      type: \"input\",\n      placeholder: \"请输入集群ID\",\n      componentProps: {\n        autoComplete: \"off\",\n      },\n      rules: [\n        {\n          required: false,\n          validator: (rule: any, value: string) => {\n            if (value && !new RegExp(regNonnegativeInteger).test(value)) {\n              return Promise.reject(new Error(\"请输入正确格式\"));\n            }\n            if (value?.length > 16) {\n              return Promise.reject(new Error(\"请输入正确ID，0-16位字符\"));\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      dataIndex: \"cluster\",\n      title: \"物理集群名称:\",\n      type: \"select\",\n      placeholder: \"请选择\",\n      options: phyClusterList,\n      componentProps: {\n        onChange: onPhyClusterChange,\n      },\n    },\n    {\n      dataIndex: \"logicClusterName\",\n      title: \"逻辑集群名称:\",\n      type: \"select\",\n      placeholder: \"请选择\",\n      options: logiClusterList,\n    },\n    {\n      dataIndex: \"health\",\n      title: \"集群状态:\",\n      type: \"select\",\n      options: ClusterStatus,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"esVersion\",\n      title: \"集群版本:\",\n      type: \"select\",\n      options: packageHostList,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"desc\",\n      title: \"描述:\",\n      type: \"input\",\n      placeholder: \"请输入集群描述\",\n      componentProps: {\n        autoComplete: \"off\",\n      },\n    },\n  ] as IColumnsType[];\n  return formMap;\n};\n\nexport const getLogicClusterQueryXForm = (data: IOpLogicCluster[], logiClusterList = []) => {\n  const formMap = [\n    {\n      dataIndex: \"id\",\n      title: \"集群ID\",\n      type: \"input\",\n      placeholder: \"请输入集群ID\",\n      rules: [\n        {\n          required: false,\n          validator: (rule: any, value: string) => {\n            if (value && !new RegExp(regNonnegativeInteger).test(value)) {\n              return Promise.reject(new Error(\"请输入正确格式\"));\n            }\n            if (value?.length > 16) {\n              return Promise.reject(new Error(\"请输入正确ID，0-16位字符\"));\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      dataIndex: \"name\",\n      title: \"集群名称\",\n      type: \"select\",\n      options: logiClusterList,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"health\",\n      title: \"集群状态\",\n      type: \"select\",\n      options: ClusterStatus,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"type\",\n      title: \"集群类型\",\n      type: \"select\",\n      options: logicClusterType,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"memo\",\n      title: \"描述\",\n      type: \"input\",\n      placeholder: \"请输入集群描述\",\n    },\n  ] as IColumnsType[];\n  return formMap;\n};\n\nexport const getServiceBtnList = (record: IOpPhysicsCluster, setModalId: any, setDrawerId: any, reloadDataFn): ITableBtn[] => {\n  let btn = [\n    {\n      invisible: !hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.SHORTCUTS),\n      label: \"快捷命令\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        setDrawerId(\"physicsClusterTask\", record, reloadDataFn);\n      },\n    },\n    {\n      invisible: !hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.REGION_SET),\n      label: \"Region划分\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        setModalId(\"regionDivide\", record, reloadDataFn);\n      },\n    },\n    {\n      invisible: !hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.REGION_MANAGE),\n      label: \"Region管理\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        setModalId(\"regionAdmin\", record, reloadDataFn);\n      },\n    },\n    {\n      invisible: !hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.EXPAND_SHRINK) || !record?.supportZeus,\n      label: \"扩缩容\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        if (record.type === 3) {\n          setModalId(\"dockerExpandShrinkCluster\", record, reloadDataFn);\n        } else if (record.type === 4) {\n          setModalId(\"expandShrinkCluster\", record, reloadDataFn);\n        }\n      },\n    },\n    {\n      invisible: !hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.UPGRADE) || !record?.supportZeus,\n      label: \"升级\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        setDrawerId(\"upgradeCluster\", record, reloadDataFn);\n      },\n    },\n    {\n      invisible: !hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.RESTART) || !record?.supportZeus,\n      label: \"重启\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        setDrawerId(\"restartCluster\", record, reloadDataFn);\n      },\n    },\n    {\n      invisible: !hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.CONFIG_UPDATE) || !record?.supportZeus,\n      label: \"配置变更\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        setDrawerId(\"newConfigModal\", record, reloadDataFn);\n      },\n    },\n  ];\n  return btn;\n};\n\nexport const getPhysicsBtnList = (record: IOpPhysicsCluster, setModalId: any, setDrawerId: any, reloadDataFn): ITableBtn[] => {\n  let btn = [\n    {\n      invisible: !hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.EDIT),\n      label: \"编辑\",\n      type: \"primary\",\n      clickFunc: () => {\n        let params = record;\n        if (params?.password) {\n          let password = params?.password.split(\":\");\n          params.usename = password[0];\n          params.password = password[1];\n        }\n\n        setModalId(\"editPhyCluster\", params, reloadDataFn);\n      },\n    },\n    //这个配置不要删除，下个版本还要继续开发\n    // {\n    //   invisible: !hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.BIND_GATEWAY),\n    //   label: \"绑定Gateway\",\n    //   type: \"primary\",\n    //   clickFunc: () => {\n    //     setModalId(\"bindGateway\", record, reloadDataFn);\n    //   },\n    // },\n    {\n      invisible: !hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.OFFLINE),\n      label: \"下线\",\n      type: \"primary\",\n      clickFunc: () => {\n        if (record?.logicClusterAndRegionList) {\n          XNotification({ type: \"error\", message: `下线失败，请解绑逻辑集群后重试` });\n          return;\n        }\n        setModalId(\"deleteCluster\", record, reloadDataFn);\n      },\n    },\n  ];\n  return btn;\n};\n\nexport const getPhysicsColumns = (setModalId: any, setDrawerId: any, reloadDataFn: any, props: any) => {\n  const columns = [\n    {\n      title: \"集群ID\",\n      dataIndex: \"id\",\n      key: \"id\",\n      width: 80,\n    },\n    {\n      title: \"物理集群名称\",\n      dataIndex: \"cluster\",\n      key: \"cluster\",\n      width: 180,\n      lineClampOne: true,\n      render: (text: string, record: IOpPhysicsCluster) => {\n        let permission = hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.LIST_DETAIL);\n        if (!permission) return text;\n        return (\n          <NavRouterLink\n            needToolTip={true}\n            element={text}\n            href={`/cluster/physics/detail?physicsCluster=${record.cluster}&physicsClusterId=${record.id}&type=${record.type}#info`}\n          />\n        );\n      },\n    },\n    {\n      title: \"逻辑集群名称\",\n      dataIndex: \"logicClusterAndRegionList\",\n      key: \"logicClusterAndRegionList\",\n      width: 240,\n      render: (list) => {\n        if (!list || !list[0]?.v1) return \"-\";\n        let limit = 2;\n        if (list[0]?.v1?.name?.length > 20 || list[0]?.v1?.name?.length + list[1]?.v1?.name?.length > 25) {\n          limit = 1;\n        }\n        return renderAttributes({ data: list?.map((item: any) => item && item?.v1?.name) || [], limit, placement: \"bottomLeft\" });\n      },\n    },\n    {\n      title: \"集群状态\",\n      dataIndex: \"health\",\n      key: \"health\",\n      width: 100,\n      render: (health: number) => {\n        return (\n          <div>\n            <Tag className={`tag ${StatusMap[health]}`} color={StatusMap[health]} style={{ width: 64, textAlign: \"center\" }}>\n              {StatusMap[health]}\n            </Tag>\n          </div>\n        );\n      },\n    },\n    {\n      title: \"集群类型\",\n      dataIndex: \"resourceType\",\n      key: \"resourceType\",\n      width: 100,\n      render: (type: number) => {\n        return <>{clusterTypeMap[type] || \"-\"}</>;\n      },\n    },\n    {\n      title: \"集群版本\",\n      dataIndex: \"esVersion\",\n      key: \"esVersion\",\n      width: 100,\n      render: (text: string) => text || \"-\",\n    },\n    {\n      title: \"磁盘使用率\",\n      dataIndex: \"diskInfo\",\n      key: \"diskInfo\",\n      width: 160,\n      sorter: true,\n      render: (_, diskInfo) => renderDiskRate(diskInfo),\n    },\n    {\n      title: \"活跃分片数\",\n      dataIndex: \"activeShardNum\",\n      key: \"activeShardNum\",\n      width: 120,\n      sorter: true,\n    },\n    {\n      title: \"描述\",\n      dataIndex: \"desc\",\n      key: \"desc\",\n      width: 130,\n      lineClampOne: true,\n      onCell: () => ({\n        style: { ...cellStyle, maxWidth: 100 },\n      }),\n      render: (text: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={text}>\n            {text ? text : \"-\"}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"集群服务\",\n      dataIndex: \"service\",\n      key: \"service\",\n      width: 220,\n      render: (id: number, records: IOpPhysicsCluster) => {\n        const record = { ...records, ...props };\n        const btns = getServiceBtnList(record, setModalId, setDrawerId, reloadDataFn);\n        return renderOperationBtns(btns, record, 3);\n      },\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      key: \"operation\",\n      width: 120,\n      filterTitle: true, //开启表格自定义列\n      fixed: \"right\",\n      render: (id: number, records: IOpPhysicsCluster) => {\n        const record = { ...records, ...props };\n        const btns = getPhysicsBtnList(record, setModalId, setDrawerId, reloadDataFn);\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n  return columns;\n};\n\nconst getLogicBtnList = (record: IOpLogicCluster | any, fn: any, reloadDataFn: any, indexTemFun: any): ITableBtn[] => {\n  let btn = [\n    {\n      invisible: !hasOpPermission(MyClusterPermissions.PAGE, MyClusterPermissions.EDIT),\n      label: \"编辑\",\n      clickFunc: () => {\n        fn(\"editCluster\", record, reloadDataFn);\n      },\n    },\n    {\n      invisible: !hasOpPermission(MyClusterPermissions.PAGE, MyClusterPermissions.EXPAND_SHRINK),\n      label: \"扩缩容\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        fn(\"expandShrink\", record, reloadDataFn);\n      },\n    },\n    {\n      invisible: !hasOpPermission(MyClusterPermissions.PAGE, MyClusterPermissions.OFFLINE),\n      label: \"下线\",\n      clickFunc: async () => {\n        let countState = await indexTemFun(record);\n        if (countState?.templateLogicAggregates || countState?.catIndexResults) {\n          XNotification({\n            type: \"error\",\n            message: `逻辑集群${record.name}下线失败`,\n            description: `该集群下还有${countState?.templateLogicAggregates || 0}项模板资源、${countState?.catIndexResults || 0}\n          项索引资源，如需下线集群，请前往模板管理、索引管理下线掉对应的模板及索引！`,\n            duration: 1000,\n          });\n        } else {\n          fn(\"offlineCluster\", record, reloadDataFn);\n        }\n      },\n    },\n  ];\n  return btn as ITableBtn[];\n};\n\nexport const getLogicColumns = (tableData: IOpLogicCluster[], fn: any, reloadDataFn: any, props: any, indexTemFun: any) => {\n  const columns = [\n    {\n      title: \"集群ID\",\n      dataIndex: \"id\",\n      key: \"id\",\n      width: 80,\n    },\n    {\n      title: \"集群名称\",\n      dataIndex: \"name\",\n      key: \"name\",\n      width: 150,\n      render: (text: string, record: IOpLogicCluster) => {\n        let permission = hasOpPermission(MyClusterPermissions.PAGE, MyClusterPermissions.LIST_DETAIL);\n        if (!permission) return text;\n        return (\n          <NavRouterLink\n            needToolTip={true}\n            element={text}\n            href={`/cluster/logic/detail?cluster=${text}&clusterId=${record.id}&type=${record.type}#info`}\n          />\n        );\n      },\n    },\n    {\n      title: \"集群状态\",\n      dataIndex: \"health\",\n      key: \"status\",\n      width: 100,\n      render: (health) => {\n        return (\n          <div>\n            <Tag className={`tag ${StatusMap[health]}`} style={{ width: 64, textAlign: \"center\" }} color={StatusMap[health]}>\n              {StatusMap[health]}\n            </Tag>\n          </div>\n        );\n      },\n    },\n    {\n      title: \"集群类型\",\n      dataIndex: \"type\",\n      key: \"type\",\n      width: 120,\n      sorter: true,\n      render: (type: number) => {\n        return <>{clusterTypeMap[type] || \"-\"}</>;\n      },\n    },\n    {\n      title: \"集群版本\",\n      dataIndex: \"esClusterVersion\",\n      key: \"esClusterVersion\",\n      width: 120,\n      sorter: true,\n      render: (text: string) => text || \"-\",\n    },\n    {\n      title: \"业务等级\",\n      dataIndex: \"level\",\n      key: \"level\",\n      width: 120,\n      sorter: true,\n      render: (text) => {\n        return LEVEL_MAP[Number(text) - 1]?.label || \"-\";\n      },\n    },\n    {\n      title: \"磁盘使用率\",\n      dataIndex: \"diskInfo\",\n      key: \"diskInfo\",\n      width: 150,\n      sorter: true,\n      render: (_, diskInfo) => renderDiskRate(diskInfo),\n    },\n    {\n      title: \"数据节点数\",\n      dataIndex: \"dataNodeNum\",\n      key: \"dataNodeNum\",\n      width: 130,\n      sorter: true,\n      render: (podNumber: string) => {\n        return <>{podNumber != null ? podNumber : \"-\"}</>;\n      },\n    },\n    {\n      title: \"描述\",\n      dataIndex: \"memo\",\n      key: \"memo\",\n      width: 150,\n      ellipsis: true,\n      onCell: () => ({\n        style: { ...cellStyle, maxWidth: 150 },\n      }),\n      render: (text: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={text}>\n            {text ? text : \"-\"}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      key: \"operation\",\n      width: 150,\n      fixed: \"right\",\n      filterTitle: true,\n      render: (id: number, records: IOpLogicCluster) => {\n        const record = { ...records, ...props };\n        const btns = getLogicBtnList(record, fn, reloadDataFn, indexTemFun);\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n  return columns;\n};\n\nexport const getVersionsColumns = (fn, reloadDataFn) => {\n  const cols = [\n    {\n      title: \"ID\",\n      dataIndex: \"id\",\n      key: \"ID\",\n      width: 80,\n      sorter: (a: IVersions, b: IVersions) => a.id - b.id,\n    },\n    {\n      title: \"版本名称\",\n      dataIndex: \"esVersion\",\n      key: \"esVersion\",\n      width: 120,\n    },\n    {\n      title: \"版本标识\",\n      dataIndex: \"packageType\",\n      key: \"packageType\",\n      width: 120,\n      render: (text: number) => {\n        let str = \"-\";\n        if (text == 1) {\n          str = \"滴滴内部版本\";\n        }\n        if (text == 2) {\n          str = \"社区开源版本\";\n        }\n        return str;\n      },\n    },\n    {\n      title: \"url\",\n      dataIndex: \"url\",\n      key: \"url\",\n      width: 180,\n      lineClampTwo: true,\n      onCell: () => ({\n        style: {\n          maxWidth: 200,\n          ...cellStyle,\n        },\n      }),\n      render: (url: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={url}>\n            {url}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"描述\",\n      dataIndex: \"desc\",\n      key: \"desc\",\n      width: 150,\n      onCell: () => ({\n        style: {\n          maxWidth: 200,\n          ...cellStyle,\n        },\n      }),\n      render: (desc: string) => {\n        return (\n          <>\n            <Tooltip placement=\"bottomLeft\" title={desc}>\n              {desc || \"_\"}\n            </Tooltip>\n          </>\n        );\n      },\n    },\n    {\n      title: \"创建人\",\n      dataIndex: \"creator\",\n      key: \"creator\",\n      width: 80,\n    },\n    {\n      title: \"创建时间\",\n      dataIndex: \"createTime\",\n      key: \"createTime\",\n      width: 150,\n      sorter: (a: IVersions, b: IVersions) => new Date(b.createTime).getTime() - new Date(a.createTime).getTime(),\n      render: (t: number) => transTimeFormat(t),\n    },\n  ];\n\n  return cols;\n};\n\nexport const getEditionQueryXForm = (data, handleTimeChange) => {\n  //export const getEditionQueryXForm = (data, handleTimeChange, resetAllValue: Function) => {\n  const customTimeOptions = [\n    {\n      label: \"最近 1 小时\",\n      value: 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 1 天\",\n      value: 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 7 天\",\n      value: 7 * 24 * 60 * 60 * 1000,\n    },\n  ];\n  const formMap = [\n    {\n      dataIndex: \"esVersion\",\n      title: \"版本名称:\",\n      type: \"select\",\n      options: getOptions(data, \"esVersion\"),\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"createTime\",\n      title: \"创建时间:\",\n      type: \"custom\",\n      //component: <RangePicker showTime={{ format: \"HH:mm\" }} format=\"YYYY-MM-DD HH:mm\" />,\n      component: (\n        <DRangeTime\n          timeChange={handleTimeChange}\n          popoverClassName=\"dashborad-popover\"\n          //resetAllValue={resetAllValue}\n          customTimeOptions={customTimeOptions}\n        />\n      ),\n    },\n  ] as IColumnsType[];\n  return formMap;\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/index.less",
    "content": ".zeus-url {\n  display: flex;\n  align-items: center;\n  &-tag {\n    font-size: 12px;\n    color: #1473ff;\n    background-color: rgba(20, 115, 255, 0.06);\n    border-radius: 4px;\n    border: none;\n    width: 80px;\n    text-align: center;\n    margin-left: 4px;\n    cursor: pointer;\n  }\n}\n\n// .ant-col #d-range-time .d-range-time-input {\n//   width: 360px;\n//   height: 32px !important;\n//   border-radius: 2px;\n// }\n.ant-col {\n  //对全局的改样式生效\n  //max-width:100%;\n  #d-range-time {\n    width: 100%;\n    .d-range-time-input {\n      width: 100% !important;\n      height: 32px !important;\n      border-radius: 2px;\n    }\n  }\n}\n.dashborad-popover {\n  background: #ffffff;\n  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.01), 0 3px 6px 3px rgba(0, 0, 0, 0.01), 0 2px 6px 0 rgba(0, 0, 0, 0.03);\n  border-radius: 4px;\n  padding-top: 4px;\n  .ant-popover-arrow {\n    opacity: 0;\n  }\n  .ant-popover-inner-content {\n    padding: 16px 24px;\n  }\n\n  .ant-picker-range {\n    background: rgba(33, 37, 41, 0.04);\n    border-radius: 8px;\n\n    .ant-picker-input > input {\n      font-family: PingFangSC-Regular;\n      font-size: 13px;\n      color: #74788d;\n    }\n  }\n  .d-range-time-input {\n    height: 32px;\n  }\n  .ant-radio-button-wrapper {\n    border: none !important;\n    height: 18px;\n    line-height: 18px;\n    padding: 0px;\n    font-family: PingFangSC-Medium;\n    font-size: 13px;\n    color: #495057;\n    letter-spacing: 0;\n    transition: none;\n\n    &.ant-radio-button-wrapper-checked {\n      color: #556ee6;\n    }\n  }\n\n  .dd-time-range-module .flx_con .time_title {\n    font-family: PingFangSC-Medium;\n    font-size: 14px;\n    color: #212529;\n    letter-spacing: 0;\n  }\n\n  .dd-time-range-module .flx_con .flx_l {\n    width: 144px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/index.tsx",
    "content": "export * from './physics';\nexport *  from './logic';"
  },
  {
    "path": "arius-console/src/container/cluster/logic-detail/base-info.tsx",
    "content": "import React from \"react\";\nimport { baseInfo } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { IClusterInfo } from \"typesPath/cluster/cluster-types\";\nimport \"./index.less\";\nimport { BaseDetail } from \"component/dantd/base-detail\";\n\nexport interface ITemplateSrv {\n  esVersion: string;\n  serviceId: number;\n  serviceName: string;\n}\nexport class ClusterInfo extends React.Component<{ logicBaseInfo: IClusterInfo }> {\n  public clusterId: number;\n  public clusterName: string;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.clusterId = Number(url.search.clusterId);\n    this.clusterName = url.search.physicsCluster;\n  }\n\n  public render() {\n    const { logicBaseInfo } = this.props;\n    return (\n      <div className=\"base-info\">\n        <BaseDetail columns={baseInfo} baseDetail={logicBaseInfo} />\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/logic-detail/config.tsx",
    "content": "import { IMenuItem, IBaseInfo } from \"typesPath/base-types\";\nimport React from \"react\";\nimport { DeleteOutlined } from \"@ant-design/icons\";\nimport { Modal, Tooltip } from \"antd\";\nimport { cellStyle } from \"constants/table\";\nimport { ROLE_TYPE, isOpenUp, LEVEL_MAP } from \"constants/common\";\nimport { IPlug } from \"typesPath/plug-types\";\nimport { submitWorkOrder } from \"api/common-api\";\nimport { IWorkOrder } from \"typesPath/params-types\";\nimport store from \"store\";\nimport { userDelPlug } from \"api/plug-api\";\nimport { clusterTypeMap } from \"constants/status-map\";\nimport { opNodeStatusMap } from \"../physics-detail/constants\";\nimport { renderDiskRate } from \"../../custom-component\";\nimport { transTimeFormat, getFormatJsonStr, isSuperApp } from \"lib/utils\";\nimport { ClusterInfo } from \"./base-info\";\nimport { LogicNodeList } from \"./logic-node-list\";\nimport \"./index.less\";\n\nconst appInfo = {\n  app: store.getState().app.appInfo,\n  user: store.getState().user.getName,\n};\n\nexport enum TAB_LIST_KEY {\n  info = \"info\",\n  index = \"index\",\n  indexTemplate = \"indexTemplate\",\n  search = \"search\",\n  monitor = \"monitor\",\n  pluggin = \"pluggin\",\n  node = \"node\",\n  region = \"region\",\n  diary = \"diary\",\n}\n\nexport const TAB_LIST = [\n  {\n    name: \"集群概览\",\n    key: TAB_LIST_KEY.info,\n    content: (params) => <ClusterInfo logicBaseInfo={params.clusterInfo} />,\n  },\n  {\n    name: \"节点列表\",\n    key: TAB_LIST_KEY.node,\n    content: () => <LogicNodeList />,\n  },\n];\n\nconst menuMap = new Map<string, IMenuItem>();\nTAB_LIST.forEach((d) => {\n  menuMap.set(d.key, d);\n});\n\nexport const DETAIL_MENU_MAP = menuMap;\n\nexport const baseInfo: any = [\n  {\n    label: \"ES版本\",\n    key: \"esClusterVersion\",\n  },\n  {\n    label: \"Gateway地址\",\n    key: \"gatewayAddress\",\n    render: (value: string) => <span>{value || \"-\"}</span>,\n  },\n  {\n    label: \"分片数\",\n    key: \"activeShardNum\",\n  },\n  {\n    label: \"数据节点数\",\n    key: \"dataNodeNum\",\n  },\n  {\n    label: \"创建时间\",\n    key: \"createTime\",\n    render: (time: number) => transTimeFormat(time),\n  },\n  {\n    label: \"集群描述\",\n    key: \"memo\",\n    render: (text: string) => (\n      <>\n        <Tooltip placement=\"bottomLeft\" title={text}>\n          {text ? (text.length > 20 ? text.slice(0, 20) + \"...\" : text) : \"_\"}\n        </Tooltip>\n      </>\n    ),\n  },\n];\ninterface ICardInfo {\n  label: string;\n  configList: IBaseInfo[];\n  btns?: JSX.Element[];\n  col: number;\n}\n\nexport const cardInfo = [\n  {\n    label: \"基本信息\",\n    configList: baseInfo,\n  },\n] as ICardInfo[];\n\nexport const getNodeColumns = () => {\n  const cols = [\n    {\n      title: \"节点名称\",\n      dataIndex: \"hostname\",\n      key: \"hostname\",\n      width: \"15%\",\n    },\n    {\n      title: \"节点ip\",\n      dataIndex: \"ip\",\n      key: \"ip\",\n      width: \"20%\",\n      onCell: () => ({\n        style: cellStyle,\n      }),\n      render: (text: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={text}>\n            {text}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"节点规格\",\n      dataIndex: \"nodeSpec\",\n      key: \"nodeSpec\",\n      width: \"20%\",\n    },\n    {\n      title: \"节点角色\",\n      dataIndex: \"role\",\n      key: \"role\",\n      width: \"15%\",\n      render: (role: number) => {\n        return <>{ROLE_TYPE[role].label}</>;\n      },\n    },\n  ];\n  return cols;\n};\n\nexport const DESC_LIST = [\n  {\n    label: \"集群类型\",\n    key: \"type\",\n    render: (value: number) => (\n      <>\n        <span>{clusterTypeMap[value] || \"-\"}</span>\n      </>\n    ),\n  },\n  {\n    label: \"集群版本\",\n    key: \"esClusterVersion\",\n    render: (val: number) => <span>{val || \"-\"}</span>,\n  },\n  {\n    label: \"业务等级\",\n    key: \"level\",\n    render: (value: number) => (\n      <>\n        <span>{LEVEL_MAP[value - 1]?.label || \"-\"}</span>\n      </>\n    ),\n  },\n];\n\nexport const getLogicNodeColumns = (dataList, reloadData: Function, type: string) => {\n  const columns = [\n    {\n      title: \"节点IP\",\n      dataIndex: \"ip\",\n      key: \"ip\",\n      width: 100,\n      render: (val: string) => {\n        return <Tooltip title={val}>{val ? val : \"-\"}</Tooltip>;\n      },\n    },\n    {\n      title: \"主机名称\",\n      dataIndex: \"hostname\",\n      key: \"hostname\",\n      width: 100,\n      render: (val: string) => {\n        return <Tooltip title={val}>{val ? val : \"-\"}</Tooltip>;\n      },\n    },\n    {\n      title: \"attribute\",\n      dataIndex: \"attributes\",\n      key: \"attributes\",\n      width: 180,\n      onCell: () => ({\n        style: { ...cellStyle, maxWidth: 180 },\n      }),\n      render: (val: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={val}>\n            {val ? val : \"-\"}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"节点名称\",\n      dataIndex: \"nodeSet\",\n      key: \"nodeSet\",\n      width: 100,\n      render: (val: string) => {\n        return val || \"-\";\n      },\n    },\n    {\n      title: \"磁盘使用率\",\n      dataIndex: \"diskUsage\",\n      key: \"diskUsage\",\n      width: 120,\n      render: (_, record) => renderDiskRate(record),\n    },\n    {\n      title: \"节点规格\",\n      dataIndex: \"machineSpec\",\n      key: \"machineSpec\",\n      width: 110,\n      onCell: () => ({\n        style: { ...cellStyle, maxWidth: 110 },\n      }),\n      render: (val: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={val}>\n            {val ? val : \"-\"}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"节点角色\",\n      dataIndex: \"role\",\n      key: \"role\",\n      width: 100,\n      render: (t: any) => {\n        let str;\n        if (Array.isArray(t)) {\n          str = t\n            .map((index) => {\n              return ROLE_TYPE[index].label || index;\n            })\n            .toString();\n        } else {\n          str = ROLE_TYPE[t].label || t;\n        }\n        return str;\n      },\n    },\n    {\n      title: \"节点状态\",\n      dataIndex: \"status\",\n      key: \"status\",\n      width: 100,\n      render: (status: number | number[]) => {\n        let str;\n        if (Array.isArray(status)) {\n          str = status\n            .map((index) => {\n              return opNodeStatusMap[index];\n            })\n            .toString();\n        } else {\n          str = opNodeStatusMap[status];\n        }\n        return (\n          <span className={status === 1 ? \"success\" : status === 2 ? \"unline\" : status === 3 ? \"fail\" : \"unknown\"}> {str || \"-\"}</span>\n        );\n      },\n    },\n  ];\n  return columns;\n};\n\nexport const indexExplain = [\n  {\n    label: \"预创建\",\n    content: \"对于分区创建的索引，支持预创建，减轻集群负担，提高稳定性\",\n  },\n  {\n    label: \"过期删除\",\n    content: \"支持索引根据保存周期自动清理，避免磁盘过满\",\n  },\n  {\n    label: \"Pipeline\",\n    content: \"提供索引分区规则（索引模板到具体的物理索引的映射）和写入限流能力\",\n  },\n  {\n    label: \"Mapping设置\",\n    content: \"提供修改索引的 mapping 的信息的功能\",\n  },\n  {\n    label: \"Setting设置\",\n    content: \"提供修改索引 Setting 的信息的功能\",\n  },\n  {\n    label: \"写入限流\",\n    content: \"对索引写入量进行限制，避免过大影响集群稳定性\",\n  },\n  {\n    label: \"跨集群同步(DCDR)\",\n    content: \"跨集群数据复制功能，用于集群间的数据复制，类似ES官方的CCR能力\",\n  },\n  {\n    label: \"索引别名\",\n    content: \"支持通过接口来设置和修改索引别名\",\n  },\n  {\n    label: \"资源管控\",\n    content: \"支持对索引资源(磁盘)大小的管控，超过设定值会被限流\",\n  },\n  {\n    label: \"安全管控\",\n    content: \"提供了引擎原生的租户和安全管控能力，可以保证引擎层面的数据安全\",\n  },\n  {\n    label: \"索引规划\",\n    content: \"保障集群节点的容量均衡，避免索引在节点上的分布不合理问题\",\n  },\n  {\n    label: \"冷热分离\",\n    content: \"提供SSD和HDD两种类型的磁盘来保存索引，从而降低成本\",\n  },\n  {\n    label: \"Shard调整\",\n    content: \"根依据索引写入的历史数据来每天定时计算未来一天索引的 shard 个数，保障索引 shard 个数的合理性\",\n  },\n];\n\nconst unintallPlugn = (data, reloadDataFn) => {\n  Modal.confirm({\n    title: `是否确定卸载该${data.name}插件`,\n    content: `插件卸载、安装需要重启集群，点击确认后，将自动提交工单。`,\n    width: 500,\n    okText: \"确定\",\n    cancelText: \"取消\",\n    onOk() {\n      const contentObj = {\n        operationType: 4,\n        logicClusterId: data.id,\n        logicClusterName: data.name,\n        plugIds: data.id,\n        plugName: data.name,\n        plugDesc: data.plugDesc,\n        type: \"6\",\n      };\n      const params: IWorkOrder = {\n        contentObj,\n        submitorProjectId: appInfo.app()?.id,\n        submitor: appInfo.user(\"userName\") || \"\",\n        description: \"\",\n        type: \"logicClusterPlugOperation\",\n      };\n      return submitWorkOrder(params, () => {\n        reloadDataFn();\n      });\n    },\n  });\n};\n\nconst intallPlugn = (data, reloadDataFn) => {\n  Modal.confirm({\n    title: `是否确定安装该${data.name}插件`,\n    content: `插件卸载、安装需要重启集群，点击确认后，将自动提交工单。`,\n    width: 500,\n    okText: \"确定\",\n    cancelText: \"取消\",\n    onOk() {\n      const contentObj = {\n        operationType: 3,\n        logicClusterId: data.id,\n        logicClusterName: data.name,\n        plugIds: data.id,\n        plugName: data.name,\n        plugDesc: data.plugDesc,\n        type: \"6\",\n      };\n      const params: IWorkOrder = {\n        contentObj,\n        submitorProjectId: appInfo.app()?.id,\n        submitor: appInfo.user(\"userName\") || \"\",\n        description: \"\",\n        type: \"logicClusterPlugOperation\",\n      };\n      return submitWorkOrder(params, () => {\n        reloadDataFn();\n      });\n    },\n  });\n};\n\nconst delPlugn = (data, reloadDataFn) => {\n  Modal.confirm({\n    title: `是否确定删除该${data.name}插件`,\n    icon: <DeleteOutlined style={{ color: \"red\" }} />,\n    content: `插件删除将永久在列表消失，请谨慎操作。`,\n    width: 500,\n    okText: \"确定\",\n    cancelText: \"取消\",\n    onOk() {\n      userDelPlug(data.id).then((res) => {\n        reloadDataFn();\n      });\n    },\n  });\n};\n\nexport const getPlugnBtnList = (record: IPlug, reloadDataFn: any) => {\n  const install = {\n    label: \"安装\",\n    clickFunc: () => {\n      intallPlugn(record, reloadDataFn);\n    },\n  };\n\n  const uninstall = {\n    label: \"卸载\",\n    isOpenUp: isOpenUp,\n    clickFunc: () => {\n      unintallPlugn(record, reloadDataFn);\n    },\n  };\n\n  const edit = {\n    label: \"编辑\",\n    isOpenUp: isOpenUp,\n    clickFunc: () => {\n      delPlugn(record, reloadDataFn);\n    },\n  };\n\n  const del = {\n    label: \"删除插件包\",\n    // needConfirm: true,\n    isOpenUp: isOpenUp,\n    // confirmText: \"删除插件包\",\n    clickFunc: (record: any) => {\n      delPlugn(record, reloadDataFn);\n    },\n  };\n\n  const btnList = [];\n  if (record.installed) {\n    btnList.push(uninstall, edit);\n  } else if (record.pdefault) {\n    btnList.push(install, edit);\n  } else {\n    btnList.push(install, edit, del);\n  }\n  return btnList;\n};\n\nexport const pDefaultMap = {\n  0: \"系统默认\",\n  1: \"ES能力\",\n  2: \"平台能力\",\n};\n\nexport const getPluginListColumns = (fn: () => any) => {\n  const columns = [\n    {\n      title: \"插件名称\",\n      dataIndex: \"name\",\n      key: \"name\",\n    },\n    {\n      title: \"插件类型\",\n      dataIndex: \"pdefault\",\n      key: \"pdefault\",\n      render: (value: number) => {\n        const text = pDefaultMap[value] || \"未知类型\";\n        return text;\n      },\n    },\n    {\n      title: \"使用版本\",\n      dataIndex: \"nodeSpec\",\n      key: \"nodeSpec\",\n    },\n    {\n      title: \"状态\",\n      dataIndex: \"installed\",\n      key: \"installed\",\n      render: (value: boolean) => {\n        return <>{value ? \"已安装\" : \"未安装\"}</>;\n      },\n    },\n    {\n      title: \"描述\",\n      dataIndex: \"desc\",\n      key: \"desc\",\n      render: (value: string) => {\n        return value || \"-\";\n      },\n    },\n  ];\n  return columns;\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/logic-detail/constants.ts",
    "content": "\nexport const LOGIC_CLUSTER_DETAIL_BREAD_BTNS = [{\n  aHref: '/admin/logic',\n  label: '逻辑集群',\n}, {\n  label: '集群详情',\n}];\n"
  },
  {
    "path": "arius-console/src/container/cluster/logic-detail/detail.tsx",
    "content": "import * as React from \"react\";\nimport { Menu, Spin, Tag, Divider } from \"knowdesign\";\nimport { DESC_LIST, TAB_LIST, DETAIL_MENU_MAP } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getOpLogicClusterInfo } from \"api/cluster-api\";\nimport { IClusterInfo } from \"typesPath/cluster/cluster-types\";\nimport { connect } from \"react-redux\";\nimport { StatusMap } from \"constants/status-map\";\nimport \"styles/detail.less\";\nimport \"./index.less\";\n\nexport interface IBaseButton {\n  label: string;\n  isOpenUp?: boolean;\n  type: \"primary\" | \"dashed\";\n  clickFunc: () => any;\n  attr?: any;\n}\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\nconst connects: Function = connect;\n@connects(null, mapDispatchToProps)\nexport class LogicClusterDetail extends React.Component<any> {\n  public clusterId: number;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.clusterId = Number(url.search.clusterId);\n    window.addEventListener(\"hashchange\", () => {\n      this.updateLogicMenu();\n    });\n  }\n\n  public state = {\n    menu: window.location.hash.replace(\"#\", \"\") || \"info\",\n    clusterInfo: {} as IClusterInfo,\n    loading: false,\n  };\n\n  public updateLogicMenu() {\n    this.setState({\n      menu: window.location.hash.replace(\"#\", \"\") || \"info\",\n    });\n  }\n\n  public componentDidMount() {\n    this.reloadData();\n  }\n\n  public componentWillUnmount() {\n    this.setState = () => false;\n  }\n\n  public reloadData = () => {\n    this.setState({\n      loading: true,\n    });\n    getOpLogicClusterInfo(this.clusterId)\n      .then((res) => {\n        if (res) {\n          this.setState({\n            clusterInfo: res,\n          });\n        }\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n  };\n\n  public renderPageHeader() {\n    const { clusterInfo } = this.state;\n\n    return (\n      <div className=\"detail-header\">\n        <div className=\"left-content\">\n          <span className=\"icon iconfont iconarrow-left\" onClick={() => this.props.history.push(\"/cluster/logic\")}></span>\n          <Divider type=\"vertical\"></Divider>\n          <div className=\"title\">\n            <span className=\"text\">{clusterInfo?.name || \"\"}</span>\n            <Tag className={`tag ${StatusMap[clusterInfo.health]}`} color={StatusMap[clusterInfo.health]}>\n              {StatusMap[clusterInfo.health]}\n            </Tag>\n          </div>\n        </div>\n        <div className=\"right-content\">\n          {DESC_LIST.map((row, index) => {\n            if (!clusterInfo) return null;\n            if (row.key === \"tags\" && Number(JSON.parse(clusterInfo[row.key] || \"{}\")?.createSource) !== 0) {\n              return null;\n            }\n            return (\n              <span className=\"cluster-detail\" key={index}>\n                <span className=\"label\">{row.label}：</span>\n                {/* @ts-ignore */}\n                <span className=\"value\">{row.render ? row.render(clusterInfo?.[row.key]) : `${clusterInfo?.[row.key] || \"-\"}`}</span>\n              </span>\n            );\n          })}\n          <div className=\"reload-icon\" onClick={this.reloadData}>\n            <span className=\"icon iconfont iconshuaxin2\"></span>\n          </div>\n        </div>\n      </div>\n    );\n  }\n\n  public changeMenu = (e) => {\n    window.location.hash = e.key;\n  };\n\n  public renderContent = () => {\n    return DETAIL_MENU_MAP.get(this.state.menu)?.content({\n      clusterInfo: this.state.clusterInfo,\n      reloadData: this.reloadData,\n      loading: this.state.loading,\n    });\n  };\n\n  public render() {\n    return (\n      <div className=\"detail-container\">\n        <Spin spinning={this.state.loading}>\n          {this.renderPageHeader()}\n          <div className=\"content\">\n            <div className=\"menu-container\">\n              <Menu className=\"menu\" selectedKeys={[this.state.menu]} mode=\"horizontal\" onClick={this.changeMenu}>\n                {TAB_LIST.map((d) => (\n                  <Menu.Item key={d.key}>{d.name}</Menu.Item>\n                ))}\n              </Menu>\n            </div>\n            <div className=\"detail-wrapper\">{this.renderContent()}</div>\n          </div>\n        </Spin>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/logic-detail/index.less",
    "content": "@import \"../../../styles/base.less\";\n.ant-spin-container {\n  .detail-header {\n    background-color: white;\n    margin: 0 20px 20px 20px;\n    border-radius: 8px;\n  }\n}\n.base-index-box {\n  &-title {\n    .middle-title();\n    padding: 20px 0;\n    border-bottom: 1px solid #dbe0e4;\n    margin-bottom: 10px;\n  }\n  &-tag {\n    padding-top: 20px;\n    display: flex;\n    flex-wrap: wrap;\n    &-item {\n      display: flex;\n      padding-right: 30px;\n      align-items: center;\n      &-title {\n        .min-title();\n        padding-right: 4px;\n        cursor: pointer;\n      }\n      &-title:hover {\n        color: #2a8fff;\n      }\n    }\n  }\n}\n.success {\n  color: #10c038;\n}\n.unline {\n  color: #f4a838;\n}\n.failed {\n  color: #f04134;\n}\n\n.logic-detail {\n  height: 100%;\n  min-width: 1200px;\n  .ant-spin-nested-loading,\n  .ant-spin-container {\n    height: 100%;\n    .detail-wrapper {\n      height: 79%;\n      padding: 20px;\n      min-width: 1000px;\n      .base-info-box {\n        margin-top: 0;\n      }\n    }\n  }\n}\n\n.logic-menu-container {\n  padding: 0 20px;\n  background: #fff;\n  .logic-menu {\n    padding-top: 16px;\n    .ant-menu-item {\n      margin: 0 40px 0 0;\n      line-height: 38px;\n      height: 38px;\n    }\n  }\n}\n\n.index-name {\n  word-wrap: break-word;\n  word-break: break-all;\n  cursor: pointer;\n}\n\n.detail-container {\n  height: 100%;\n  min-width: 1200px;\n  padding: 0 20px 20px 20px;\n  .dcloud-spin-nested-loading,\n  .dcloud-spin-container {\n    height: 100%;\n    .detail-wrapper {\n      padding: 20px;\n      height: 79%;\n      min-width: 1200px;\n    }\n  }\n  .content {\n    background: #fff;\n    border-radius: 8px;\n    height: 92%;\n  }\n  ::-webkit-scrollbar {\n    display: none\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/logic-detail/logic-node-list.tsx",
    "content": "import * as React from \"react\";\nimport \"styles/search-filter.less\";\nimport { getLogicNodeColumns } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { getLogicClusterNodeList } from \"api/cluster-node-api\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport _ from \"lodash\";\n\nexport interface INode {\n  createTime?: string;\n  id: number;\n  creator: string;\n  desc: string;\n  type?: number;\n  updateTime?: string;\n  md5: string;\n  name: string;\n  pdefault: string;\n  s3url: string;\n  url: string;\n  version?: string;\n  deleteFlag: boolean;\n  regionId: number;\n  cluster: string;\n  ip: string;\n  rack: string;\n}\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\nconst connects: Function = connect;\n\n@connects(null, mapDispatchToProps)\nexport class LogicNodeList extends React.Component<any> {\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.clusterId = Number(url.search.clusterId);\n    this.type = Number(url.search.type);\n  }\n\n  public state = {\n    searchKey: \"\",\n    loading: false,\n    pageSize: 10,\n    data: [],\n  };\n\n  public clusterId: number;\n  public type: number;\n\n  public getData = (origin?: any[]) => {\n    let { searchKey } = this.state;\n    searchKey = searchKey.trim().toLowerCase();\n    let data = searchKey\n      ? origin.filter((d) => {\n          if (d.nodeSet.toLowerCase().includes(searchKey)) {\n            return true;\n          }\n          return false;\n        })\n      : origin;\n    data = data.sort((a, b) => b.role - a.role);\n\n    return data;\n  };\n\n  public componentDidMount() {\n    this.reloadData();\n  }\n\n  public tableChange(pagination) {\n    const { pageSize } = pagination;\n    this.setState({ pageSize });\n  }\n\n  public reloadData = () => {\n    this.setState({\n      loading: true,\n    });\n\n    getLogicClusterNodeList(this.clusterId)\n      .then((res) => {\n        this.setState({ data: res });\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n  };\n\n  public handleSubmit = (value) => {\n    this.setState({\n      searchKey: value,\n    });\n  };\n\n  public render() {\n    const { data, loading } = this.state;\n    return (\n      <>\n        <DTable\n          loading={loading}\n          rowKey=\"id\"\n          dataSource={this.getData(data)}\n          columns={getLogicNodeColumns(data, this.reloadData, this.props.logicBaseInfo?.permissions)}\n          tableHeaderSearchInput={{\n            submit: this.handleSubmit,\n            placeholder: \"请输入实例名称\",\n          }}\n          attrs={{ bordered: true, onChange: this.tableChange.bind(this) }}\n          reloadData={this.reloadData}\n        />\n      </>\n    );\n  }\n\n  public defineTableWrapperClassNames = () => {\n    return \"no-padding\";\n  };\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/logic.tsx",
    "content": "import React, { useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getLogicClusterQueryXForm, getLogicColumns } from \"./config\";\nimport { getOpLogicClusterList, ILogicLike, getCount, getMyLogiClusterList } from \"api/cluster-api\";\nimport { DTable, ITableBtn } from \"component/dantd/dtable\";\nimport { RenderTitle } from \"component/render-title\";\nimport QueryForm from \"component/dantd/query-form\";\nimport { queryFormText } from \"constants/status-map\";\nimport { isOpenUp } from \"constants/common\";\nimport { MyClusterPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport Url from \"lib/url-parser\";\nimport { ProTable } from \"knowdesign\";\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nconst LogicClusterBox = (props) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject]: any = useState({\n    current: 1,\n    size: 10,\n  });\n  const [data, setData] = useState([]);\n  const [total, setTotal] = useState(0);\n  const [logiClusterList, setLogiClusterList] = useState([]);\n\n  const indexTemFun = async (record) => {\n    let indexCount = null;\n    await getCount(record.id).then((res) => {\n      if (res) {\n        indexCount = res;\n      }\n    });\n    return indexCount;\n  };\n  React.useEffect(() => {\n    reloadData();\n  }, [department, queryFormObject, Url().search.needApplyCluster]);\n\n  React.useEffect(() => {\n    getLogiClusterList();\n  }, [department]);\n\n  const getLogiClusterList = () => {\n    getMyLogiClusterList().then((res = []) => {\n      const list = res.map((item) => ({ title: item, value: item }));\n      setLogiClusterList(list);\n    });\n  };\n\n  // const getData = () => {\n  //   // 查询项的key 要与 数据源的key  对应\n  //   if (!queryFormObject) return data;\n  //   const keys = Object.keys(queryFormObject);\n  //   const filterData = data.filter((d) => {\n  //     let b = true;\n  //     keys.forEach((k: string) => {\n  //       if (k === \"clusterStatus\") {\n  //         (d[k].status + \"\")?.toLowerCase().includes(queryFormObject[k])\n  //           ? \"\"\n  //           : (b = false);\n  //       } else if (k === \"authType\") {\n  //         d[k] === queryFormObject[k] ? \"\" : (b = false);\n  //       } else {\n  //         (d[k] + \"\")?.toLowerCase().includes(queryFormObject[k])\n  //           ? \"\"\n  //           : (b = false);\n  //       }\n  //     });\n  //     return b;\n  //   });\n  //   return filterData;\n  // };\n\n  const reloadData = () => {\n    setloading(true);\n    const Params: ILogicLike = {\n      page: queryFormObject.current,\n      size: queryFormObject.size,\n      authType: queryFormObject.authType,\n      name: queryFormObject.name,\n      health: queryFormObject.health,\n      type: queryFormObject.type,\n      sortTerm: queryFormObject.sortTerm,\n      orderByDesc: queryFormObject.orderByDesc,\n      id: queryFormObject.id !== undefined ? +queryFormObject.id : undefined,\n      memo: queryFormObject.memo,\n    };\n    getOpLogicClusterList(Params)\n      .then((res) => {\n        if (res) {\n          if (Url().search.hasOwnProperty(\"needApplyCluster\") && !res.bizData?.length) {\n            props.setModalId(\"applyCluster\", { history: props.history }, reloadData);\n          }\n          res.bizData = res?.bizData?.map((item) => {\n            item.esClusterVersions = item.esClusterVersions?.join(\",\") || \"_\";\n            return item;\n          });\n          setData(res?.bizData);\n          setTotal(res?.pagination?.total);\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const renderTitleContent = () => {\n    return {\n      title: \"我的集群\",\n      content: null,\n    };\n  };\n\n  const handleSubmit = (result) => {\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject({ ...result, size: queryFormObject.size, current: 1 });\n  };\n\n  const getOpBtns = (): ITableBtn[] => {\n    return [\n      hasOpPermission(MyClusterPermissions.PAGE, MyClusterPermissions.APPLY) && {\n        className: \"ant-btn-primary\",\n        label: \"申请集群\",\n        isOpenUp: isOpenUp,\n        clickFunc: () => props.setModalId(\"applyCluster\", { history: props.history }, reloadData),\n      },\n    ].filter(Boolean);\n  };\n\n  const handleChange = (pagination, filters, sorter) => {\n    const sorterObject: { [key: string]: any } = {};\n    // 排序\n    if (sorter.columnKey && sorter.order) {\n      switch (sorter.columnKey) {\n        case \"type\":\n          sorterObject.sortTerm = \"type\";\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n        case \"esClusterVersion\":\n          sorterObject.sortTerm = \"es_cluster_version\";\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n        case \"level\":\n          sorterObject.sortTerm = \"level\";\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n        case \"diskInfo\":\n          sorterObject.sortTerm = \"disk_usage_percent\";\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n        case \"dataNodeNum\":\n          sorterObject.sortTerm = \"data_node_num\";\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n        default:\n          break;\n      }\n    }\n    setqueryFormObject((state) => {\n      if (!sorter.order) {\n        delete state.sortTerm;\n        delete state.orderByDesc;\n      }\n\n      return {\n        ...state,\n        ...sorterObject,\n        current: pagination.current,\n        size: pagination.pageSize,\n      };\n    });\n  };\n\n  const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n\n  return (\n    <>\n      <div className=\"table-layout-style\">\n        <ProTable\n          showQueryForm={true}\n          queryFormProps={{\n            defaultCollapse: true,\n            columns: getLogicClusterQueryXForm(data, logiClusterList),\n            onReset: handleSubmit,\n            onSearch: handleSubmit,\n            isResetClearAll: true,\n            showCollapseButton: false,\n          }}\n          tableProps={{\n            tableId: \"logic_cluster_list\", //开启表格自定义列\n            isCustomPg: false,\n            loading,\n            rowKey: \"id\",\n            dataSource: data,\n            columns: getLogicColumns(data, props.setModalId, reloadData, props, indexTemFun),\n            reloadData,\n            getOpBtns: getOpBtns,\n            customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n            paginationProps: {\n              position: \"bottomRight\",\n              showQuickJumper: true,\n              total: total,\n              showSizeChanger: true,\n              pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n              showTotal: (total) => `共 ${total} 条`,\n              current: queryFormObject.current,\n            },\n            attrs: {\n              onChange: handleChange,\n              scroll: {\n                x: \"max-content\",\n              },\n            },\n          }}\n        />\n      </div>\n    </>\n  );\n};\nexport const LogicCluster = connect(null, mapDispatchToProps)(LogicClusterBox);\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/base-info.tsx",
    "content": "import React from \"react\";\nimport { baseInfo, indexExplain } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport \"./index.less\";\nimport { BaseDetail } from \"component/dantd/base-detail\";\nimport { isOpenUp, showTag } from \"constants/common\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { connect } from \"react-redux\";\n\n// 动态配置换成单独的tabs\n// import { EditList } from \"./edit-list\";\nexport interface ITemplateSrv {\n  esVersion: string;\n  serviceId: number;\n  serviceName: string;\n}\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params)),\n});\nconst connects: Function = connect;\n@connects(null, mapDispatchToProps)\nexport class ClusterInfo extends React.Component<any> {\n  public clusterId: number;\n  public physicsCluster: string;\n  public auth: string;\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.auth = url.search.auth;\n    this.clusterId = Number(url.search.clusterId);\n    this.physicsCluster = url.search.physicsCluster;\n  }\n\n  public state = {\n    clusterTemplateSrvs: [],\n    hasCapacityServer: false,\n  };\n\n  public componentWillUnmount() {\n    this.setState = () => false;\n  }\n\n  public setPhyClusterTemplateSrvs = (data: ITemplateSrv[][]) => {\n    const avalibleSrvs = data?.[0] || [];\n    const currentSrvs = data?.[1] || [];\n    const phyClusterTemplateSrvs = [];\n    // 是否拥有容量规划服务\n    const hasCapacityServer = !!currentSrvs.find((row) => row.serviceId === 11);\n\n    for (const item of avalibleSrvs) {\n      // -1 -> 无权限\n      let disabled = this.auth === \"-1\" ? true : false;\n      if (isOpenUp) {\n        // 开源环境部分功能禁用\n        if (showTag[item.serviceName] === 3) {\n          disabled = true;\n        }\n        // 在开源环境下，分类为 0 隐藏\n        if (showTag[item.serviceName] !== 0) {\n          phyClusterTemplateSrvs.push({\n            disabled,\n            item,\n            status: !!currentSrvs.find((row) => row.serviceId === item.serviceId) ? 1 : 0,\n          });\n        }\n      } else {\n        phyClusterTemplateSrvs.push({\n          disabled,\n          item,\n          status: !!currentSrvs.find((row) => row.serviceId === item.serviceId) ? 1 : 0,\n        });\n      }\n    }\n    this.setState({\n      clusterTemplateSrvs: phyClusterTemplateSrvs,\n      hasCapacityServer: hasCapacityServer,\n    });\n  };\n\n  public renderTip = (label: string) => {\n    let tip = \"暂无相关信息\";\n    if (isOpenUp) {\n      if (showTag[label] === 3) {\n        return \"该功能仅面向商业版客户开放\";\n      }\n    }\n    indexExplain.forEach((item) => {\n      if (item.label === label) {\n        tip = item.content;\n      }\n    });\n    return tip;\n  };\n\n  public render() {\n    const { phyBaseInfo, setModalId, reloadData } = this.props;\n    return (\n      <div className=\"base-info\">\n        <BaseDetail columns={baseInfo(setModalId, reloadData, phyBaseInfo)} baseDetail={phyBaseInfo} />\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/config.tsx",
    "content": "import { IMenuItem } from \"typesPath/base-types\";\nimport { IOpPhysicsClusterDetail, ITemplateSrvData } from \"typesPath/cluster/cluster-types\";\nimport React from \"react\";\nimport { DeleteOutlined, EditOutlined, QuestionCircleOutlined } from \"@ant-design/icons\";\nimport { Modal, Tooltip, message } from \"antd\";\nimport { cellStyle } from \"constants/table\";\nimport { ROLE_TYPE, ROLE_TYPE_NO, colorTheme, isOpenUp } from \"constants/common\";\nimport { ClusterInfo } from \"./base-info\";\nimport { NavRouterLink, renderOperationBtns } from \"container/custom-component\";\nimport { PlugnList } from \"./plugn-list\";\nimport { PHY_CLUSTER_TYPE, RESOURCE_TYPE_MAP, clusterTypeMap } from \"constants/status-map\";\nimport { IPlug } from \"typesPath/plug-types\";\nimport { userDelPlug } from \"api/plug-api\";\nimport store from \"store\";\nimport { IPhyConfig } from \"typesPath/cluster/physics-type\";\nimport { PhysicsConfigInfo } from \"./physics-config-info.tsx\";\nimport { IIndex, INodeDivide } from \"typesPath/index-types\";\nimport { NodeDivide } from \"./node-divide\";\nimport { opNodeStatusMap } from \"./constants\";\nimport { ITableBtn } from \"component/dantd/dtable\";\nimport { EditList } from \"./edit-list\";\nimport { Sense } from \"./sense\";\nimport { renderDiskRate } from \"../../custom-component\";\nimport { LogicList } from \"./logic-list\";\nimport { transTimeFormat } from \"lib/utils\";\nimport { SearchProfiler } from \"./searchProfiler\";\n\nconst appInfo = {\n  app: store.getState().app,\n  user: store.getState().user,\n};\n\nexport enum TAB_LIST_KEY {\n  info = \"info\",\n  index = \"index\",\n  indexTemplate = \"indexTemplate\",\n  search = \"search\",\n  monitor = \"monitor\",\n  pluggin = \"pluggin\",\n  node = \"node\",\n  region = \"region\",\n  diary = \"diary\",\n  editList = \"editList\",\n  sense = \"sense\",\n  configList = \"configList\",\n  logicList = \"logicList\",\n  searchProfiler = \"searchProfiler\",\n}\n\nexport const TAB_LIST = [\n  {\n    name: \"集群概览\",\n    key: TAB_LIST_KEY.info,\n    content: (params: { clusterInfo: IOpPhysicsClusterDetail; reloadData: Function; loading: boolean }) => (\n      <ClusterInfo phyBaseInfo={params.clusterInfo} reloadData={params.reloadData} />\n    ),\n  },\n  {\n    name: \"Sense查询\",\n    key: TAB_LIST_KEY.sense,\n    content: () => <Sense />,\n  },\n  {\n    name: \"Search Profiler\",\n    key: TAB_LIST_KEY.searchProfiler,\n    content: () => <SearchProfiler />,\n  },\n  {\n    name: \"节点列表\",\n    key: TAB_LIST_KEY.indexTemplate,\n    content: (logicBaseInfo: IOpPhysicsClusterDetail) => <NodeDivide />,\n  },\n  {\n    name: \"逻辑集群列表\",\n    key: TAB_LIST_KEY.logicList,\n    content: (params: { clusterInfo: IOpPhysicsClusterDetail; reloadData: Function; loading: boolean }) => (\n      <LogicList logicList={params.clusterInfo?.logicClusterAndRegionList} reloadData={params.reloadData} loading={params.loading} />\n    ),\n  },\n  // {\n  //   name: \"插件列表\",\n  //   key: TAB_LIST_KEY.pluggin,\n  //   content: (logicBaseInfo: IOpPhysicsClusterDetail) => <PlugnList />,\n  // },\n  {\n    name: \"配置文件列表\",\n    key: TAB_LIST_KEY.configList,\n    content: (logicBaseInfo: IOpPhysicsClusterDetail) => <PhysicsConfigInfo />,\n  },\n  {\n    name: \"动态配置\",\n    key: TAB_LIST_KEY.editList,\n    content: () => <EditList />,\n  },\n];\n\nconst menuMap = new Map<string, IMenuItem>();\nTAB_LIST.forEach((d) => {\n  menuMap.set(d.key, d);\n});\n\nexport const DETAIL_MENU_MAP = menuMap;\n\nexport const baseInfo = (setModalId?: Function, reloadData?: Function, phyBaseInfo?: any) => {\n  const proxyAddressInfo = [\n    {\n      label: \"代理地址\",\n      key: \"proxyAddress\",\n      render: (value: string) => (\n        <span>{value?.length > 56 ? <Tooltip title={value}>{value?.substring(0, 54) + \"...\"}</Tooltip> : value}</span>\n      ),\n    },\n    {\n      label: \"分片数\",\n      key: \"activeShardNum\",\n    },\n\n    {\n      label: \"创建时间\",\n      key: \"createTime\",\n      render: (time: number) => transTimeFormat(time),\n    },\n    {\n      label: \"备注\",\n      key: \"desc\",\n      render: (value: string) => (\n        <>\n          <span>{value?.length > 56 ? <Tooltip title={value}>{value?.substring(0, 54) + \"...\"}</Tooltip> : value || \"-\"}</span>\n        </>\n      ),\n    },\n  ];\n\n  const httpWriteAddressInfo = [\n    {\n      label: \"读地址\",\n      key: \"httpAddress\",\n      render: (value: string) => (\n        <>\n          <span>{value?.length > 56 ? <Tooltip title={value}>{value?.substring(0, 54) + \"...\"}</Tooltip> : value}</span>\n        </>\n      ),\n    },\n    {\n      label: \"分片数\",\n      key: \"activeShardNum\",\n    },\n    {\n      label: \"写地址\",\n      key: \"httpWriteAddress\",\n      render: (value: string) => (\n        <>\n          <span>{value?.length > 56 ? <Tooltip title={value}>{value?.substring(0, 54) + \"...\"}</Tooltip> : value}</span>\n        </>\n      ),\n    },\n    {\n      label: \"创建时间\",\n      key: \"createTime\",\n      render: (time: number) => transTimeFormat(time),\n    },\n    {\n      label: \"备注\",\n      key: \"desc\",\n      render: (value: string) => (\n        <>\n          <span>{value?.length > 56 ? <Tooltip title={value}>{value?.substring(0, 54) + \"...\"}</Tooltip> : value || \"-\"}</span>\n        </>\n      ),\n    },\n  ];\n\n  const baseConfigInfo = [\n    {\n      label: \"ES版本\",\n      key: \"esVersion\",\n    },\n    {\n      label: \"Gateway地址\",\n      key: \"gatewayAddress\",\n      render: () => {\n        return (\n          <div>\n            <span>{phyBaseInfo.gatewayUrl || \"-\"}</span>\n            {/* <EditOutlined onClick={() => setModalId(\"editGatewayUrl\", phyBaseInfo, reloadData)} /> */}\n          </div>\n        );\n      },\n    },\n  ];\n\n  return phyBaseInfo?.proxyAddress\n    ? [].concat(baseConfigInfo).concat(proxyAddressInfo)\n    : [].concat(baseConfigInfo).concat(httpWriteAddressInfo);\n};\n\nconst formatNodeInfo = (node: any, str: string) => {\n  const esRoleClusterVOSItem = node?.find((item: any) => {\n    return item?.role === str;\n  });\n  const machineSpecArr = esRoleClusterVOSItem?.machineSpec.split(\"-\");\n  return esRoleClusterVOSItem\n    ? `${esRoleClusterVOSItem.podNumber} * CPU${machineSpecArr[0]}核-内存${machineSpecArr[1] || \"(-)\"}-磁盘${machineSpecArr[2] || \"(-)\"}`\n    : \"-\";\n};\n\nexport const configInfo: any = [\n  [\n    {\n      label: \"Masternode\",\n      key: \"esRoleClusterVOS\",\n      render: (value: any) => (\n        <>\n          <span>{formatNodeInfo(value, \"masternode\")}</span>\n        </>\n      ),\n    },\n    {\n      label: \"Datanode\",\n      key: \"esRoleClusterVOS\",\n      render: (value: any) => (\n        <>\n          <span>{formatNodeInfo(value, \"datanode\")}</span>\n        </>\n      ),\n    },\n  ],\n  [\n    {\n      label: \"Clientnode\",\n      key: \"esRoleClusterVOS\",\n      render: (value: any) => (\n        <>\n          <span>{formatNodeInfo(value, \"clientnode\")}</span>\n        </>\n      ),\n    },\n  ],\n];\ninterface ICardInfo {\n  label: string;\n  configList: () => [];\n  btns?: JSX.Element[];\n  col?: number;\n}\n\nexport const cardInfo = [\n  {\n    label: \"基本信息\",\n    configList: baseInfo,\n  },\n] as ICardInfo[];\n\nexport const getNodeColumns = () => {\n  const cols = [\n    {\n      title: \"节点名称\",\n      dataIndex: \"hostname\",\n      key: \"hostname\",\n      width: \"15%\",\n    },\n    {\n      title: \"节点ip\",\n      dataIndex: \"ip\",\n      key: \"ip\",\n      width: \"20%\",\n      onCell: () => ({\n        style: cellStyle,\n      }),\n      render: (text: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={text}>\n            {text}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"节点规格\",\n      dataIndex: \"nodeSpec\",\n      key: \"nodeSpec\",\n      width: \"20%\",\n    },\n    {\n      title: \"节点角色\",\n      dataIndex: \"role\",\n      key: \"role\",\n      width: \"15%\",\n      render: (role: number) => {\n        return <>{ROLE_TYPE[role].label}</>;\n      },\n    },\n  ];\n  return cols;\n};\n\nexport const arrToStr = (value, length = 10) => {\n  let str = \"\";\n  let tip = \"\";\n  if (value && value?.length) {\n    value.forEach((item, index) => {\n      // 数组多个时最后一个没有逗号\n      tip += item + (value.length - index == 1 ? \"\" : \",\");\n      // 识别到已经有胜率号后不在计算添加str\n      if (str.includes(\"...\")) {\n        return;\n      }\n      // 超长会导致换行\n      if (str.length > length || str.length + item.length > length) {\n        str += \"...\";\n      } else {\n        str += item + (value.length - index == 1 ? \"\" : \",\");\n      }\n    });\n  }\n  return (\n    <>\n      <Tooltip title={tip}>\n        <span>{str || \"-\"}</span>\n      </Tooltip>\n    </>\n  );\n};\n\nexport const PHYSICE_DESC_LIST = [\n  {\n    label: \"集群类型\",\n    key: \"resourceType\",\n    render: (value: number) => clusterTypeMap[value] || \"-\",\n  },\n  {\n    label: \"IaaS平台类型\",\n    key: \"platformType\",\n    render: (value: string) => value || \"-\",\n  },\n  {\n    label: \"数据中心\",\n    key: \"dataCenter\",\n  },\n];\n\nexport const getLogicNodeColumns = () => {\n  const columns = [\n    {\n      title: \"节点名称\",\n      dataIndex: \"hostname\",\n      key: \"hostname\",\n    },\n    {\n      title: \"节点IP\",\n      dataIndex: \"ip\",\n      key: \"ip\",\n    },\n    {\n      title: \"节点规格\",\n      dataIndex: \"nodeSpec\",\n      key: \"nodeSpec\",\n    },\n    {\n      title: \"节点角色\",\n      dataIndex: \"role\",\n      key: \"role\",\n      render: (t: number) => ROLE_TYPE[t].label,\n    },\n    {\n      title: \"所属region\",\n      dataIndex: \"regionId\",\n      key: \"regionId\",\n    },\n    {\n      title: \"所属物理集群\",\n      dataIndex: \"cluster\",\n      key: \"cluster\",\n    },\n  ];\n  return columns;\n};\n\nexport const getLogicListColumns = () => {\n  const columns = [\n    {\n      title: \"逻辑集群ID\",\n      dataIndex: \"logicClusterId\",\n      key: \"logicClusterId\",\n      width: 200,\n    },\n    {\n      title: \"逻辑集群名称\",\n      dataIndex: \"logicName\",\n      key: \"logicName\",\n      width: 200,\n    },\n    {\n      title: \"所属应用\",\n      dataIndex: \"projectNameList\",\n      key: \"projectNameList\",\n      width: 200,\n      ellipsis: true,\n      render: (val) => {\n        let text = val?.join(\"，\");\n        return <Tooltip title={text}>{text ? text : \"-\"}</Tooltip>;\n      },\n    },\n    {\n      title: \"关联Region\",\n      dataIndex: \"region\",\n      key: \"region\",\n      width: 200,\n    },\n  ];\n  return columns;\n};\n\nexport const indexExplain = [\n  {\n    label: \"预创建\",\n    content: \"对于分区创建的索引，支持预创建，减轻集群负担，提高稳定性\",\n  },\n  {\n    label: \"过期删除\",\n    content: \"支持索引根据保存周期自动清理，避免磁盘过满\",\n  },\n  {\n    label: \"Pipeline\",\n    content: \"提供索引分区规则（索引模板到具体的物理索引的映射）和写入限流能力\",\n  },\n  {\n    label: \"Mapping设置\",\n    content: \"提供修改索引的 mapping 的信息的功能\",\n  },\n  {\n    label: \"Setting设置\",\n    content: \"提供修改索引 Setting 的信息的功能\",\n  },\n  {\n    label: \"写入限流\",\n    content: \"对索引写入量进行限制，避免过大影响集群稳定性\",\n  },\n  {\n    label: \"跨集群同步(DCDR)\",\n    content: \"跨集群数据复制功能，用于集群间的数据复制，类似ES官方的CCR能力\",\n  },\n  {\n    label: \"索引别名\",\n    content: \"支持通过接口来设置和修改索引别名\",\n  },\n  {\n    label: \"资源管控\",\n    content: \"支持对索引资源(磁盘)大小的管控，超过设定值会被限流\",\n  },\n  {\n    label: \"安全管控\",\n    content: \"提供了引擎原生的租户和安全管控能力，可以保证引擎层面的数据安全\",\n  },\n  {\n    label: \"索引规划\",\n    content: \"保障集群节点的容量均衡，避免索引在节点上的分布不合理问题\",\n  },\n  {\n    label: \"冷热分离\",\n    content: \"提供SSD和HDD两种类型的磁盘来保存索引，从而降低成本\",\n  },\n  {\n    label: \"Shard调整\",\n    content: \"根依据索引写入的历史数据来每天定时计算未来一天索引的 shard 个数，保障索引 shard 个数的合理性\",\n  },\n];\n\nexport const getNodeDivideColumns = () => {\n  const columns = [\n    {\n      title: \"RegionID\",\n      dataIndex: \"regionId\",\n      key: \"regionId\",\n      width: 80,\n      render: (val: number) => {\n        if (val === -1) return \"-\";\n        return val;\n      },\n    },\n    {\n      title: \"Region名称\",\n      dataIndex: \"regionName\",\n      key: \"regionName\",\n      width: 110,\n      onCell: () => ({\n        style: { ...cellStyle, maxWidth: 100 },\n      }),\n      render: (val: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={val}>\n            {val ? val : \"-\"}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"节点IP\",\n      dataIndex: \"ip\",\n      key: \"ip\",\n      width: 100,\n      render: (val: string) => {\n        return <Tooltip title={val}>{val ? val : \"-\"}</Tooltip>;\n      },\n    },\n    {\n      title: \"主机名称\",\n      dataIndex: \"hostname\",\n      key: \"hostname\",\n      width: 100,\n      render: (val: string) => {\n        return <Tooltip title={val}>{val ? val : \"-\"}</Tooltip>;\n      },\n    },\n    {\n      title: \"attribute\",\n      dataIndex: \"attributes\",\n      key: \"attributes\",\n      width: 180,\n      onCell: () => ({\n        style: { ...cellStyle, maxWidth: 180 },\n      }),\n      render: (val: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={val}>\n            {val ? val : \"-\"}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"节点名称\",\n      dataIndex: \"nodeSet\",\n      key: \"nodeSet\",\n      width: 90,\n      render: (val: string) => {\n        return val || \"-\";\n      },\n    },\n    {\n      title: \"磁盘使用率\",\n      dataIndex: \"disk\",\n      key: \"disk\",\n      width: 120,\n      render: (_, record) => renderDiskRate(record),\n    },\n    {\n      title: \"节点规格\",\n      dataIndex: \"machineSpec\",\n      key: \"machineSpec\",\n      width: 110,\n      onCell: () => ({\n        style: { ...cellStyle, maxWidth: 110 },\n      }),\n      render: (val: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={val}>\n            {val ? val : \"-\"}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"节点角色\",\n      dataIndex: \"role\",\n      key: \"role\",\n      width: 90,\n      sorter: (a: any, b) => {\n        const sortA = Array.isArray(a.role)\n          ? a.role\n              .map((index) => {\n                return ROLE_TYPE_NO[index].label || index;\n              })\n              .sort()\n              .toString()\n          : a.role;\n        const sortB = Array.isArray(b.role)\n          ? b.role\n              .map((index) => {\n                return ROLE_TYPE_NO[index].label || index;\n              })\n              .sort()\n              .toString()\n          : b.role;\n        return ROLE_TYPE_NO[sortA].label[0].localeCompare(ROLE_TYPE_NO[sortB].label[0]);\n      },\n      showSorterTooltip: false,\n      render: (t: any) => {\n        let str;\n        if (Array.isArray(t)) {\n          str = t\n            .map((index) => {\n              return ROLE_TYPE_NO[index].label || index;\n            })\n            .toString();\n        } else {\n          str = ROLE_TYPE_NO[t].label || t;\n        }\n        return str;\n      },\n    },\n    {\n      title: \"节点状态\",\n      dataIndex: \"status\",\n      key: \"status\",\n      width: 90,\n      sorter: (a, b) => a.status - b.status,\n      showSorterTooltip: false,\n      render: (status: number | number[]) => {\n        let str;\n        if (Array.isArray(status)) {\n          str = status\n            .map((index) => {\n              return opNodeStatusMap[index];\n            })\n            .toString();\n        } else {\n          str = opNodeStatusMap[status];\n        }\n        return (\n          <span className={status === 1 ? \"success\" : status === 2 ? \"unline\" : status === 3 ? \"fail\" : \"unknown\"}> {str || \"-\"}</span>\n        );\n      },\n    },\n  ];\n  return columns;\n};\n\nconst delPlugn = (data, reloadDataFn) => {\n  Modal.confirm({\n    title: `是否确定删除该${data.name}插件`,\n    icon: <DeleteOutlined style={{ color: \"red\" }} />,\n    content: `插件删除将永久在列表消失，请谨慎操作。`,\n    width: 500,\n    okText: \"确定\",\n    cancelText: \"取消\",\n    onOk() {\n      userDelPlug(data.id).then((res) => {\n        reloadDataFn();\n      });\n    },\n  });\n};\n\nconst getPlugnBtnList = (record: IPlug, reloadDataFn: any, setModalId) => {\n  const install = {\n    label: \"安装\",\n    isOpenUp: isOpenUp,\n    clickFunc: () => {\n      setModalId(\"installplugin\", record, reloadDataFn);\n    },\n  };\n\n  const uninstall = {\n    label: \"卸载\",\n    isOpenUp: isOpenUp,\n    clickFunc: () => {\n      setModalId(\"uninstallPlugin\", record, reloadDataFn);\n    },\n  };\n\n  const edit = {\n    label: \"编辑\",\n    clickFunc: () => {\n      setModalId(\"EditPluginDesc\", { record }, reloadDataFn);\n    },\n  };\n\n  const del = {\n    label: \"删除插件包\",\n    // needConfirm: true,\n    isOpenUp: isOpenUp,\n    // confirmText: \"删除插件包\",\n    clickFunc: (record: any) => {\n      delPlugn(record, reloadDataFn);\n    },\n  };\n\n  const btnList = [];\n  if (record.installed) {\n    btnList.push(uninstall, edit);\n  } else {\n    btnList.push(install, edit, del);\n  }\n  return btnList;\n};\n\nexport const pDefaultMap = {\n  0: \"系统默认\",\n  1: \"ES能力\",\n  2: \"平台能力\",\n};\n\nexport const getPluginListColumns = (fn: () => any, setModalId) => {\n  const columns = [\n    {\n      title: \"插件名称\",\n      dataIndex: \"name\",\n      key: \"name\",\n    },\n    {\n      title: \"插件类型\",\n      dataIndex: \"pdefault\",\n      key: \"pdefault\",\n      sorter: true,\n      render: (value: number) => {\n        const text = pDefaultMap[value] || \"未知类型\";\n        return text;\n      },\n    },\n    {\n      title: \"使用版本\",\n      dataIndex: \"version\",\n      sorter: true,\n      key: \"version\",\n    },\n    {\n      title: \"状态\",\n      dataIndex: \"installed\",\n      sorter: true,\n      key: \"installed\",\n      render: (value: boolean) => {\n        return <>{value ? \"已安装\" : \"未安装\"}</>;\n      },\n    },\n    {\n      title: \"描述\",\n      dataIndex: \"desc\",\n      key: \"desc\",\n      width: \"25%\",\n      render: (value: string) => {\n        return value || \"-\";\n      },\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      key: \"operation\",\n      filterTitle: true,\n      render: (id: number, record: IPlug) => {\n        const btns = getPlugnBtnList(record, fn, setModalId);\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n  return columns;\n};\n\nexport const getConfigInfoColumns = (setDrawerId: any) => {\n  const operationList = [\n    {\n      label: \"查看\",\n      isOpenUp: isOpenUp,\n      clickFunc: (record: IPhyConfig) => {\n        setDrawerId(\"configDetail\", record.configData);\n        return;\n      },\n    },\n  ] as ITableBtn[];\n  const columns = [\n    {\n      title: \"节点角色\",\n      dataIndex: \"enginName\",\n      key: \"enginName\",\n    },\n    {\n      title: \"配置类别\",\n      dataIndex: \"typeName\",\n      key: \"typeName\",\n      render: (value: string) => <span>{value || \"-\"}</span>,\n    },\n    {\n      title: \"配置内容\",\n      dataIndex: \"configData\",\n      key: \"configData\",\n      onCell: () => ({\n        style: cellStyle,\n      }),\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"id\",\n      key: \"operation\",\n      width: \"20%\",\n      render: (id: number, record: IPhyConfig) => {\n        const btns = operationList;\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n  return columns;\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/constants.ts",
    "content": "export const LOGIC_CLUSTER_DETAIL_BREAD_BTNS = [\n  {\n    aHref: \"/admin/logic\",\n    label: \"逻辑集群\",\n  },\n  {\n    label: \"集群详情\",\n  },\n];\n\nexport const opNodeStatusMap = {\n  \"-1\": \"unknown\",\n  1: \"在线\",\n  2: \"离线\",\n  3: \"故障\",\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/detail.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { Menu, Spin, Tag, Divider } from \"knowdesign\";\nimport { PHYSICE_DESC_LIST, DETAIL_MENU_MAP, TAB_LIST } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getPhysicsClusterDetail } from \"api/cluster-api\";\nimport { IOpPhysicsClusterDetail } from \"typesPath/cluster/cluster-types\";\nimport { connect } from \"react-redux\";\nimport { StatusMap } from \"constants/status-map\";\nimport \"./index.less\";\nimport \"styles/detail.less\";\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params, cb)),\n});\nexport const PhyClusterDetail = connect(\n  null,\n  mapDispatchToProps\n)((props: any) => {\n  const [menu, setMenu] = useState(window.location.hash.replace(\"#\", \"\") || \"info\");\n  const [clusterInfo, setClusterInfo] = useState({} as IOpPhysicsClusterDetail);\n  const [loading, setLoading] = useState(false);\n\n  const url = Url();\n  const clusterId = Number(url.search.physicsClusterId);\n\n  useEffect(() => {\n    reloadData();\n    window.addEventListener(\"hashchange\", () => {\n      updateLogicMenu();\n    });\n    return () => {\n      window.removeEventListener(\"hashchange\", () => {\n        updateLogicMenu();\n      });\n    };\n  }, []);\n\n  const reloadData = () => {\n    setLoading(true);\n    getPhysicsClusterDetail(clusterId)\n      .then((res) => {\n        if (res) {\n          setClusterInfo(res);\n        }\n      })\n      .finally(() => {\n        setLoading(false);\n      });\n  };\n\n  const updateLogicMenu = () => {\n    setMenu(window.location.hash.replace(\"#\", \"\") || \"info\");\n  };\n\n  const renderPageHeader = () => {\n    return (\n      <div className=\"detail-header\">\n        <div className=\"left-content\">\n          <span className=\"icon iconfont iconarrow-left\" onClick={() => props.history.push(\"/cluster/physics\")}></span>\n          <Divider type=\"vertical\"></Divider>\n          <div className=\"title\">\n            <span className=\"text\">{clusterInfo?.cluster || \"\"}</span>\n            <Tag className={`tag ${StatusMap[clusterInfo.health]}`} color={StatusMap[clusterInfo.health]}>\n              {StatusMap[clusterInfo.health]}\n            </Tag>\n          </div>\n        </div>\n        <div className=\"right-content\">\n          {PHYSICE_DESC_LIST.map((row, index) => {\n            if (!clusterInfo) return null;\n            if (row.key === \"tags\" && Number(JSON.parse(clusterInfo[row.key] || \"{}\")?.createSource) !== 0) {\n              return null;\n            }\n            return (\n              <span className=\"detail\" key={index}>\n                <span className=\"label\">{row.label}：</span>\n                {/* @ts-ignore */}\n                <span className=\"value\">{row.render ? row.render(clusterInfo?.[row.key]) : `${clusterInfo?.[row.key] || \"-\"}`}</span>\n              </span>\n            );\n          })}\n          <div className=\"reload-icon\" onClick={reloadData}>\n            <span className=\"icon iconfont iconshuaxin2\"></span>\n          </div>\n        </div>\n      </div>\n    );\n  };\n\n  const changeMenu = (e) => {\n    window.location.hash = e.key;\n  };\n\n  const renderContent = () => {\n    return DETAIL_MENU_MAP.get(menu)?.content({\n      clusterInfo: clusterInfo,\n      reloadData: reloadData,\n      loading: loading,\n    });\n  };\n\n  return (\n    <div className=\"detail-container\">\n      <Spin spinning={loading}>\n        {renderPageHeader()}\n        <div className=\"content\">\n          <div className=\"menu-container\">\n            <Menu className=\"menu\" selectedKeys={[menu]} mode=\"horizontal\" onClick={changeMenu}>\n              {TAB_LIST.map((d) => (\n                <Menu.Item key={d.key}>{d.name}</Menu.Item>\n              ))}\n            </Menu>\n          </div>\n          <div className=\"detail-wrapper\">{renderContent()}</div>\n        </div>\n      </Spin>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/edit-list/config.tsx",
    "content": "import { number } from \"echarts\";\n\nconst percent = \"%\";\nconst input = \"input\";\nconst select = \"select\";\n\nconst isInt = (val: string) => {\n  // 整数\n  const intReg = /^\\d{1,}$/;\n  return intReg.test(val);\n};\n\nconst isTwoDecimal = (val: string) => {\n  // 两位小数\n  const twoDecimalReg = /^\\d{1,}\\.\\d{1,2}$/;\n  return twoDecimalReg.test(val);\n};\n\nconst maxEqual0AndMinEqual100 = (val: string) => {\n  const num = Number(val);\n  return num >= 0 && num <= 100;\n};\n\nconst max1AndMin100 = (val: string) => {\n  const num = Number(val);\n  return num > 1 && num < 100;\n};\n\n// node_concurrent_incoming_recoveries\nconst maxEqual0AndMin2147483647 = (val: string) => {\n  const num = Number(val);\n  return num >= 0 && num < 2147483647;\n};\n\nconst maxEqualNegative1AndMin2147483647 = (val: string) => {\n  const num = Number(val);\n  return num >= -1 && num < 2147483647;\n};\n\nconst max0 = (val: string) => {\n  const num = Number(val);\n  return num > 0;\n};\n\nconst maxEqual0 = (val: string) => {\n  const num = Number(val);\n  return num >= 0;\n};\nconst maxEqual0AndMinEqual120 = (val: string) => {\n  const num = Number(val);\n  return num >= 0 && num <= 120;\n};\n\nconst max1000 = (val: string) => {\n  const num = Number(val);\n  return num > 1000;\n};\n\n// 百分比\nconst checkPercent = (val) => {\n  if ((isInt(val) || isTwoDecimal(val)) && maxEqual0AndMinEqual100(val)) {\n    return \"\";\n  }\n  return \"请输入两位小数以内的数字且大于等于0小于等于100\";\n};\n\n// 效验 overhead\nconst checkIntTwoDecimalMax1AndMin100 = (val) => {\n  if ((isInt(val) || isTwoDecimal(val)) && max1AndMin100(val)) {\n    return \"\";\n  }\n  return \"请输入两位小数以内的数字且大于1小于等于100\";\n};\n\n// node_concurrent_incoming_recoveries  效验\nconst checkIntMaxEqual0AndMin2147483647 = (val) => {\n  if (isInt(val) && maxEqual0AndMin2147483647(val)) {\n    return \"\";\n  }\n  return \"请输入一个整数且大于等于0小于2147483647\";\n};\n\n// rebalance\nconst checkIntMaxEqualNegative1AndMin2147483647 = (val) => {\n  if (isInt(val) && maxEqualNegative1AndMin2147483647(val)) {\n    return \"\";\n  }\n  return \"请输入两位小数以内的数字且大于等于-1小于2147483647\";\n};\n\n// balance\nconst checkIntTwoDecimalMaxEqual0 = (val) => {\n  if ((isInt(val) || isTwoDecimal(val)) && maxEqual0(val)) {\n    return \"\";\n  }\n  return \"请输入两位小数以内的数字且大于等于0\";\n};\n\nconst checkMax1000 = (val) => {\n  if (isInt(val) && max1000(val)) {\n    return \"\";\n  }\n  return \"请输入一个整数且大于1000\";\n};\n\nconst checkInt = (val) => {\n  if (isInt(val)) {\n    return \"\";\n  }\n  return \"请输入一个整数\";\n};\n\n// 秒\nconst checkS = (val) => {\n  if (isInt(val) && maxEqual0AndMinEqual120(val)) {\n    return \"\";\n  }\n  return \"请输入一个整数大于等于0且小于等于120\";\n};\n\n// enable 下拉列表\nconst enableSelectList = [\"all\", \"primaries\", \"new_primaries\", \"none\"].map((item) => ({ name: item, value: item }));\n\n// rebalance\nconst rebalanceSelectList = [\"all\", \"primaries\", \"replicas\", \"none\"].map((item) => ({ name: item, value: item }));\n\n// boolean 下拉列表\nconst booleanSelectList = [\"true\", \"false\"].map((item) => ({\n  name: item,\n  value: item,\n}));\n\n// all write 下拉列表\nconst allWriteList = [\"all\", \"write\"].map((item) => ({\n  name: item,\n  value: item,\n}));\n\n// rebalanceList\nconst allow_rebalanceSelectList = [\"always\", \"indices_primaries_active\", \"indices_all_active\"].map((item) => ({ name: item, value: item }));\n\nexport const clusterSetting = {\n  BREAKER: {\n    \"indices.breaker.total.limit\": {\n      info: \"基础熔断器内存限制。\",\n      unit: percent,\n      type: input,\n      check: checkPercent,\n      confirmMessage: \"限制值不应该设置过低，有可能对程序处理性能造成影响，建议设置在40%\",\n    },\n    \"indices.breaker.fielddata.limit\": {\n      info: \"fielddata熔断器内存限制。\",\n      unit: percent,\n      type: input,\n      check: checkPercent,\n    },\n    \"indices.breaker.fielddata.overhead\": {\n      info: \"fielddata内存限制系数（估算值：系数乘以真实值）。\",\n      type: input,\n      check: checkIntTwoDecimalMax1AndMin100,\n      confirmMessage: \"限制值不应设置过低，有可能造成集群熔断，请谨慎操作，建议采用默认值\",\n    },\n    \"indices.breaker.request.limit\": {\n      info: \"request熔断器的限制。\",\n      unit: percent,\n      type: input,\n      check: checkPercent,\n    },\n    \"indices.breaker.request.overhead\": {\n      info: \"request内存限制系数（估算值：系数乘以真实值）。\",\n      type: input,\n      check: checkIntTwoDecimalMax1AndMin100,\n    },\n    \"network.breaker.inflight_requests.limit\": {\n      info: \"inflight_requests请求熔断器内存限制。\",\n      unit: percent,\n      type: input,\n      check: checkPercent,\n    },\n    \"network.breaker.inflight_requests.overhead\": {\n      info: \"inflight_requests内存限制系数。\",\n      type: input,\n      check: checkIntTwoDecimalMax1AndMin100,\n    },\n  },\n  ROUTING: {\n    \"cluster.routing.allocation.enable\": {\n      info: \"为特定类型的分片启用或禁用分配。\",\n      type: select,\n      selectList: enableSelectList,\n      confirmMessage: \"请谨慎修改，否则可能导致索引分片无法分配\",\n    },\n    \"cluster.routing.allocation.node_concurrent_incoming_recoveries\": {\n      info: \"一个节点上允许发生多少并发传入分片恢复。\",\n      type: input,\n      check: checkIntMaxEqual0AndMin2147483647,\n    },\n    \"cluster.routing.allocation.node_concurrent_outgoing_recoveries\": {\n      info: \"一个节点上允许发生多少并发传出分片恢复。\",\n      type: input,\n      check: checkIntMaxEqual0AndMin2147483647,\n    },\n    \"cluster.routing.allocation.node_concurrent_recoveries\": {\n      info: \"设置 cluster.routing.allocation.node_concurrent_incoming_recoveries 和 cluster.routing.allocation.node_concurrent_outgoing_recoveries 的快捷方式。\",\n      type: input,\n      check: checkInt,\n    },\n    \"cluster.routing.allocation.node_initial_primaries_recoveries\": {\n      info: \"初始化主分配恢复并发度。\",\n      type: input,\n      check: checkIntMaxEqual0AndMin2147483647,\n    },\n    \"cluster.routing.allocation.same_shard.host\": {\n      info: \"是否允许在单个主机上分配同一分片的多个副本。\",\n      type: select,\n      selectList: booleanSelectList,\n    },\n    \"cluster.routing.rebalance.enable\": {\n      info: \"启用或禁用特定类型分片的重新平衡。\",\n      type: select,\n      selectList: rebalanceSelectList,\n    },\n    \"cluster.routing.allocation.allow_rebalance\": {\n      info: \"指定何时允许分片重新平衡。\\nalways：一直允许重新平衡；\\nindices_primaries_active：只有当集群中的所有的 primaries 被分配；\\nindices_all_active：只有当集群中的所有分片（primaries and replicas）被分配（默认）。\",\n      type: select,\n      selectList: allow_rebalanceSelectList,\n    },\n    \"cluster.routing.allocation.cluster_concurrent_rebalance\": {\n      info: \"允许控制多个并发分片重新平衡在所允许的集群范围，默认为 2 。\",\n      type: input,\n      check: checkIntMaxEqualNegative1AndMin2147483647,\n    },\n    \"cluster.routing.allocation.balance.shard\": {\n      info: \"定义节点上分配的分片总数的权重因子（float），默认为 0.45f ，提高这个值会增加集群中所有节点的分片数量均衡的趋势。\",\n      type: input,\n      check: checkIntTwoDecimalMaxEqual0,\n    },\n    \"cluster.routing.allocation.balance.index\": {\n      info: \"定义在特定节点上分配的每个索引的分片数的权重因子（float），默认为 0.55f ，提高这个值会增加集群中所有节点每个索引的分片数量均衡的趋势。\",\n      type: input,\n      check: checkIntTwoDecimalMaxEqual0,\n    },\n    \"cluster.routing.allocation.balance.threshold\": {\n      info: \"应执行的操作的最小优化值（非负浮点），默认为 1.0f，提高这个值将导致集群在优化分片平衡方面不那么积极。\",\n      type: input,\n      check: checkIntTwoDecimalMaxEqual0,\n    },\n    \"cluster.routing.allocation.disk.threshold_enabled\": {\n      info: \"分片分配时是否考虑磁盘因素。\",\n      type: select,\n      selectList: booleanSelectList,\n    },\n    \"cluster.routing.allocation.disk.watermark.low\": {\n      info: \"磁盘使用的限制（low），默认值是85%，意味着当一个node的磁盘使用率达到了85%，那么就不会再往这个node上面分配shard了。\",\n      unit: percent,\n      type: input,\n      check: checkPercent,\n    },\n    \"cluster.routing.allocation.disk.watermark.high\": {\n      info: \"磁盘使用的限制（high），默认是90%，当某个node的磁盘使用率达到90%的时候，elasticsearch就会考虑将一部分shard从这个node上面迁移到别的node上面。\",\n      unit: percent,\n      type: input,\n      check: checkPercent,\n    },\n    \"cluster.routing.allocation.disk.watermark.flood_stage\": {\n      info: \"磁盘使用的限制（danger），默认值是95%，当某个node的磁盘使用达到这个水平以后，这个node上的shard对应的index都会被设置为 index.blocks.read_only_allow_delete，也就是只允许读操作和删除操作，这是es为了应对集群崩溃不得不采取的一个操作，而且在cluster中的node解除磁盘风险后需要手动进行只读设置的解除。\",\n      unit: percent,\n      type: input,\n      check: checkPercent,\n    },\n    \"cluster.routing.allocation.total_shards_per_node\": {\n      info: \"控制一个节点上最多可以分配多少个分片。\",\n      type: input,\n      check: checkMax1000,\n      confirmMessage: \"当集群索引内容较多时，建议不要减少每个节点上的总分片数目，建议保持在1000以上，-1 表示不限制\",\n    },\n    \"cluster.routing.allocation.awareness.attributes\": {\n      info: \"机架感知，主副分片不同机架分布。\",\n      type: select,\n      mode: \"multiple\",\n      selectList: [],\n      confirmMessage: \"设置之后对于集群主副分片会分配到对应属性下的节点上，请谨慎操作\",\n    },\n    \"indices.recovery.max_bytes_per_sec\": {\n      info: \"每个节点分片迁移的带宽限制\",\n      type: input,\n      mode: \"multiple\",\n    },\n  },\n  ZEN: {\n    \"discovery.zen.commit_timeout\": {\n      info: \"元数据预更新超时时间。\",\n      type: input,\n      unit: \"s\",\n      check: checkS,\n    },\n    \"discovery.zen.minimum_master_nodes\": {\n      info: \"设置了最少有多少个备选主节点才能开始选举。\",\n      type: input,\n      check: checkInt,\n    },\n    \"discovery.zen.no_master_block\": {\n      info: \"设置没有主节点时限制的操作。all：所有操作均不可进行，读写、包括集群状态的读写api，例如获得索引配置（index settings），putMapping，和集群状态（cluster state）api；write：默认，写操作被拒绝执行，基于最后一次已知的正常的集群状态可读，这也许会读取到已过时的数据。\",\n      type: select,\n      selectList: allWriteList,\n    },\n    \"discovery.zen.publish_diff.enable\": {\n      info: \"是否启用集群状态增量更新。\",\n      type: select,\n      selectList: booleanSelectList,\n    },\n    \"discovery.zen.publish_timeout\": {\n      info: \"元数据更新超时时间。\",\n      type: input,\n      unit: \"s\",\n      check: checkS,\n    },\n  },\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/edit-list/edit-list-grid.tsx",
    "content": "import React, { memo, useEffect, useState, Fragment } from \"react\";\nimport { Empty } from \"antd\";\nimport \"./index.less\";\n\nimport { EditListItem } from \"./edit-list-item\";\n\ninterface propsType {\n  title: string;\n  data: {\n    [key: string]: any;\n  };\n  configData: {\n    [key: string]: any;\n  };\n  inputValue?: string;\n  reloadData: any;\n}\n\nexport const EditListGrid: React.FC<propsType> = memo(({ reloadData, title, data, configData, inputValue }) => {\n  const [keyList, setKeyList] = useState(Object.keys(data));\n\n  useEffect(() => {\n    let keys = Object.keys(data);\n    let list = keys.filter((item) => item?.includes(inputValue) || data[item]?.includes(inputValue));\n    setKeyList(list);\n  }, [inputValue]);\n\n  return (\n    <div className=\"ant-list ant-list-split ant-list-bordered\">\n      <div className=\"ant-list-header\">{title}</div>\n      <div className=\"ant-list-item ant-row detail-edit-list-row\">\n        {keyList.map((item, index) => {\n          const configItemData = configData[item];\n          if (!configItemData) {\n            console.error(`动态配置, ${item} 属性配置不存在`);\n            return;\n          }\n          let value;\n          if (configItemData.unit) {\n            value = parseFloat(data[item]);\n          } else {\n            value = data[item];\n          }\n          return (\n            <Fragment key={item + index}>\n              {index !== 0 && index < keyList.length && index % 2 == 0 ? (\n                <div className=\"detail-edit-list-line\" key={\"detail-edit-list-line\" + item + index}></div>\n              ) : (\n                \"\"\n              )}\n              <EditListItem\n                setBackground={(index + 1) % 4 === 0 || (index + 1) % 4 === 3}\n                name={item}\n                title={title}\n                reloadData={reloadData}\n                info={configItemData.info}\n                value={value}\n                type={configItemData.type}\n                unit={configItemData.unit}\n                mode={configItemData.mode}\n                check={configItemData.check}\n                selectList={configItemData.selectList}\n                confirmMessage={configItemData.confirmMessage}\n              />\n              {index === keyList.length - 1 && (index + 1) % 4 === 3 && (\n                <div className={`ant-col ant-col-12 detail-edit-list-row-col background`}></div>\n              )}\n            </Fragment>\n          );\n        })}\n        {!keyList.length && <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description=\"数据为空\" />}\n      </div>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/edit-list/edit-list-item.tsx",
    "content": "import React, { memo, useState, useRef, Fragment, useEffect } from \"react\";\nimport { EditOutlined, SaveOutlined, QuestionCircleOutlined } from \"@ant-design/icons\";\nimport { Popover, Form, Input, Select, message, Popconfirm } from \"antd\";\nimport { useClickOutSide } from \"./useClickOutSide\";\nimport { updateDynamicConfig } from \"../../../../api/cluster-api\";\nimport _ from \"lodash\";\nimport urlParser from \"lib/url-parser\";\n\nconst { Option } = Select;\n\ninterface propsType {\n  name: string;\n  title: string;\n  info: string;\n  value: any;\n  type: \"input\" | \"select\";\n  unit?: string;\n  check?: (val: string) => string;\n  selectList?: { value: string; name: string }[];\n  mode?: \"tags\" | \"multiple\";\n  confirmMessage?: string;\n  setBackground?: boolean;\n  reloadData: any;\n}\ntype validateStatusType = \"\" | \"success\" | \"warning\" | \"error\" | \"validating\";\n\nexport const EditListItem: React.FC<propsType> = memo(\n  ({ name, title, info, value, type, check, mode, selectList = [], unit, confirmMessage, setBackground, reloadData }) => {\n    if (unit && unit == \"%\" && parseInt(value) != value) {\n      value = Number(value).toFixed(2);\n    }\n    if (String(value) == \"NaN\") {\n      value = \"\";\n    }\n    const [res, setRes] = useState(value);\n    const [isEdit, setIsEdit] = useState(false);\n    const [inpVal, setInpVal] = useState(value);\n    const [isRight, setIsRight] = useState(true);\n    const [validateStatus, setValidateStatus] = useState<validateStatusType>(\"validating\");\n    const [help, setHelp] = useState(\"\");\n    const isOutSide = useRef(true);\n    const componentRef = useRef<HTMLDivElement>(null);\n\n    const updateAsyncDynamicConfig = () => {\n      const clusterName = urlParser().search.physicsCluster;\n      if (Array.isArray(inpVal)) {\n        return updateDynamicConfig(clusterName, name, inpVal);\n      }\n      let val = inpVal;\n      if (unit) {\n        val += unit;\n      }\n      return updateDynamicConfig(clusterName, name, val);\n    };\n\n    useClickOutSide(\n      componentRef,\n      () => {\n        if (!isOutSide.current) {\n          return;\n        }\n        setValidateStatus(\"validating\");\n        setHelp(\"\");\n        setIsRight(true);\n        setInpVal(res);\n        setIsEdit(false);\n      },\n      true\n    );\n\n    const onInpValChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n      const help = check && check(e.target.value);\n      if (help) {\n        setIsRight(false);\n        setValidateStatus(\"error\");\n        setHelp(help);\n      } else {\n        setIsRight(true);\n        setValidateStatus(\"validating\");\n        setHelp(\"\");\n      }\n      setInpVal(e.target.value);\n    };\n\n    const onSelectChange = (value) => {\n      setInpVal(value);\n    };\n\n    const onSave = async () => {\n      isOutSide.current = false;\n      if (isRight) {\n        if (inpVal !== res) {\n          try {\n            const res = await updateAsyncDynamicConfig();\n            if (res && (res.code === 0 || res.code === 200)) {\n              message.success(\"修改成功\");\n              setRes(inpVal);\n              reloadData && reloadData(title, name, inpVal);\n            } else {\n              setInpVal(res);\n            }\n          } catch (error) {\n            setInpVal(res);\n          }\n        }\n        setIsEdit(false);\n      } else {\n        if (type === \"input\") {\n          message.error(help);\n        }\n      }\n      isOutSide.current = true;\n    };\n\n    const renderEdit = () => {\n      if (type === \"input\") {\n        return (\n          <Form>\n            <Form.Item validateStatus={validateStatus} help={help}>\n              <Input\n                onChange={onInpValChange}\n                value={inpVal}\n                allowClear\n                onPressEnter={() => {\n                  if (!confirmMessage) {\n                    onSave();\n                  }\n                }}\n              />\n            </Form.Item>\n          </Form>\n        );\n      }\n      return (\n        <Select\n          value={inpVal}\n          mode={mode}\n          onChange={onSelectChange}\n          getPopupContainer={() => document.getElementById(`detail-edit-list-row-col-item-${name}`)}\n        >\n          {selectList.map((item, index) => (\n            <Option value={item.value} key={item.value + index}>\n              {item.name}\n            </Option>\n          ))}\n        </Select>\n      );\n    };\n\n    const renderRes = () => {\n      if (Array.isArray(res)) {\n        return res.join(\", \");\n      }\n      if (res == null || res == \"null\") {\n        return \"-\";\n      }\n      return String(res) || \"-\";\n    };\n\n    return (\n      <div className={`ant-col ant-col-12 detail-edit-list-row-col ${setBackground ? \"background\" : \"\"}`} ref={componentRef}>\n        <div className=\"detail-edit-list-row-col-label\">\n          <Popover content={<div className=\"table-popover-content\">{info}</div>}>{name}</Popover>\n        </div>\n        <div className=\"detail-edit-content\">\n          <div className=\"detail-edit-list-row-col-item\" id={`detail-edit-list-row-col-item-${name}`}>\n            {isEdit ? (\n              renderEdit()\n            ) : (\n              <div className=\"edit-box\">\n                {renderRes() || \"-\"}\n                {renderRes() ? unit : null}\n              </div>\n            )}\n          </div>\n          {isEdit && confirmMessage ? (\n            <div className=\"detail-edit-list-btn\" id={`detail-edit-list-btn-${name}`}>\n              <Popconfirm\n                placement=\"topRight\"\n                title={confirmMessage}\n                icon={<QuestionCircleOutlined style={{ color: \"red\" }} />}\n                getPopupContainer={() => document.getElementById(`detail-edit-list-btn-${name}`)}\n                onConfirm={() => {\n                  onSave();\n                }}\n              >\n                <SaveOutlined />\n              </Popconfirm>{\" \"}\n            </div>\n          ) : null}\n          {isEdit && !confirmMessage ? (\n            <div className=\"detail-edit-list-btn\" onClick={onSave}>\n              <SaveOutlined />\n            </div>\n          ) : null}\n\n          {!isEdit ? (\n            <div className=\"detail-edit-list-btn\" onClick={() => setIsEdit(true)}>\n              <EditOutlined />\n            </div>\n          ) : null}\n        </div>\n      </div>\n    );\n  }\n);\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/edit-list/index.less",
    "content": ".detail-edit-list {\n  background: #fff;\n  .edit-from {\n    position: absolute;\n    width: 0;\n    right: 70px;\n    top: 18px;\n    overflow: hidden;\n    transition: width 0.3s;\n  }\n  .edit-from-transition {\n    display: block;\n    width: calc(100% - 90px);\n  }\n  .ant-form-item-control-input,\n  .ant-select {\n    width: 110px;\n  }\n  .ant-form-item-explain {\n    position: absolute;\n    top: 33px;\n    right: 0;\n    min-width: 500px;\n    text-align: right;\n  }\n  .ant-list-bordered {\n    border: 1px solid #d9d9d9;\n    border-radius: 4px;\n    margin-bottom: 20px;\n  }\n  .ant-list-header {\n    display: flex;\n    align-items: center;\n    padding-right: 24px;\n    padding-left: 24px;\n    min-height: 40px;\n    border-bottom: 1px solid #f0f0f0;\n    background-color: #f8fafd;\n    padding-top: 12px;\n    padding-bottom: 12px;\n    box-sizing: border-box;\n  }\n  .ant-empty-normal {\n    margin: 10px auto;\n  }\n  .detail-edit-list-row {\n    padding: 0;\n  }\n  .detail-edit-list-line {\n    height: 1px;\n    width: 100%;\n    background: rgb(219, 224, 228);\n  }\n  .detail-edit-list-row-col {\n    position: relative;\n    display: flex;\n    align-items: center;\n    padding: 0 24px;\n    min-height: 40px;\n  }\n  .background {\n    background-color: #f8fafd;\n  }\n  .detail-edit-content {\n    display: flex;\n    align-items: center;\n    width: 30%;\n  }\n  .edit-box {\n    justify-content: center;\n    align-items: center;\n    width: 140px;\n    padding: 0 10px 0 10px;\n    overflow: hidden;\n    word-wrap: break-word;\n    // line-height: 0px;\n    .ant-form-horizontal {\n      margin-top: 15px;\n    }\n    .ant-form-item-explain-validating {\n      min-height: auto;\n    }\n  }\n  .popover-inner-content {\n    max-width: 300px;\n  }\n  &-btn {\n    width: 50px;\n    text-align: center;\n  }\n  &-row {\n    width: 100%;\n    padding: 0;\n    &-col {\n      justify-content: space-between;\n      cursor: pointer;\n      &-label {\n        width: 70%;\n        &-max {\n          overflow: hidden;\n        }\n      }\n      &-item {\n        display: flex;\n        align-items: center;\n        min-width: 80px;\n        .ant-form-item {\n          margin: 0;\n        }\n      }\n      &-icon {\n        padding-left: 20px;\n      }\n      &-btn {\n        margin-left: 20px;\n      }\n    }\n  }\n  .ant-list-header {\n    font-family: PingFangSC-Semibold;\n    font-size: 14px;\n    color: #303a51;\n    line-height: 20px;\n    height: 40px;\n    font-weight: 600;\n  }\n}\n\n.edit-list-title {\n  display: flex;\n  justify-content: space-between;\n  margin-bottom: 8px;\n  .ant-btn-link {\n    width: 104px;\n    height: 30px;\n    border: 1px solid #2f81f9;\n    border-radius: 4px;\n  }\n  .ant-input-affix-wrapper {\n    position: relative;\n    width: 270px;\n    height: 32px;\n    border: 1px solid #dbe0e4;\n    border-radius: 4px;\n    .ant-input-prefix {\n      position: absolute;\n      right: 7px;\n      top: 9px;\n      cursor: pointer;\n    }\n    .ant-input {\n      margin-right: 20px;\n    }\n  }\n  .ant-input-affix-wrapper-focused {\n    border-color: #3d91ff;\n  }\n  .hasclear {\n    .ant-input-prefix {\n      right: 27px;\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/edit-list/index.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport \"./index.less\";\nimport { clusterSetting } from \"./config\";\nimport { EditListGrid } from \"./edit-list-grid\";\nimport { getDynamicConfig, getClusterAttributes } from \"../../../../api/cluster-api\";\nimport { Button, Skeleton, Input } from \"antd\";\nimport urlParser from \"lib/url-parser\";\n\nexport const EditList = () => {\n  const [isLoading, setIsLoading] = useState(false);\n  const [dynamicConfig, setDynamicConfig] = useState({});\n  const [configData, setConfigData] = useState(clusterSetting);\n  const [keyList, setKeyList] = useState([]);\n  const [inputValue, setInputValue] = useState(\"\");\n\n  const getAsyncDynamicConfig = async (clusterName: string) => {\n    try {\n      const dynamicConfig = await getDynamicConfig(clusterName);\n      setDynamicConfig(dynamicConfig);\n      setIsLoading(false);\n    } catch (error) {\n      setIsLoading(false);\n      console.log(error);\n    }\n  };\n\n  const getAsyncClusterAttributes = async (clusterName: string) => {\n    try {\n      const clusterAttributes = await getClusterAttributes(clusterName);\n      clusterSetting.ROUTING[\"cluster.routing.allocation.awareness.attributes\"].selectList = clusterAttributes.map((item) => ({\n        value: item,\n        name: item,\n      }));\n      setConfigData({ ...clusterSetting });\n    } catch (error) {\n      console.log(error);\n    } finally {\n      getAsyncDynamicConfig(clusterName);\n    }\n  };\n\n  const refreshData = (title: string, name: string, value: string | number) => {\n    if (dynamicConfig?.[title]) {\n      dynamicConfig[title][name] = value;\n    }\n  };\n\n  useEffect(() => {\n    setIsLoading(true);\n    const clusterName = urlParser().search.physicsCluster;\n    getAsyncClusterAttributes(clusterName);\n  }, []);\n\n  useEffect(() => {\n    setKeyList(Object.keys(dynamicConfig));\n  }, [dynamicConfig]);\n\n  const renderEditList = () => {\n    let list = keyList.map((item, index) => {\n      let data = JSON.parse(JSON.stringify(dynamicConfig[item]));\n      return (\n        <EditListGrid\n          reloadData={refreshData}\n          key={item + index}\n          title={item}\n          data={data}\n          configData={configData[item]}\n          inputValue={inputValue}\n        />\n      );\n    });\n    return list;\n  };\n\n  const inputChange = (e) => {\n    let value = e.target.value;\n    setInputValue(value);\n  };\n\n  return (\n    <>\n      <div className=\"detail-edit-list\">\n        <div className=\"edit-list-title\">\n          <Button\n            type=\"link\"\n            onClick={() => window.open(\"https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-update-settings.html\")}\n          >\n            官方文档链接\n          </Button>\n          <Input\n            allowClear\n            className={inputValue ? \"hasclear\" : \"\"}\n            onChange={inputChange}\n            placeholder=\"请输入关键词\"\n            prefix={\n              <svg className=\"icon svg-icon\" aria-hidden=\"true\">\n                <use xlinkHref=\"#icontubiao-sousuo\"></use>\n              </svg>\n            }\n          />\n        </div>\n        {isLoading ? (\n          <>\n            <Skeleton active />\n            <Skeleton active />\n            <Skeleton active />\n            <Skeleton active />\n            <Skeleton active />\n          </>\n        ) : (\n          renderEditList()\n        )}\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/edit-list/readme.md",
    "content": "```js\nimport React, { useEffect, useState } from \"react\";\nimport { EditOutlined } from \"@ant-design/icons\";\nimport { Button, Col, Form, List, Row, Tooltip } from \"antd\";\nimport {\n  FormItemType,\n  handleFormItem,\n  IFormItem,\n  renderFormItem,\n} from \"component/x-form\";\nimport { cloneDeep, isEqual } from \"lodash\";\nimport \"./index.less\";\nimport { clusterSetting } from \"./config\";\nimport { EditListGrid } from \"./edit-list-grid\";\nimport { getDynamicConfig } from \"../../../../api/cluster-api\";\nimport Item from \"antd/lib/list/Item\";\n\nexport const EditList = () => {\n  const [dynamicConfig, setDynamicConfig] = useState({});\n  const [keyList, setKeyList] = useState([]);\n  const getAsyncDynamicConfig = async () => {\n    const dynamicConfig = await getDynamicConfig(\"\");\n    setDynamicConfig(dynamicConfig);\n  };\n\n  useEffect(() => {\n    getAsyncDynamicConfig();\n    clusterSetting.routing[\n      \"cluster.routing.allocation.awareness.attributes\"\n    ].selectList = [\"1\", \"2\", \"3\"];\n  }, []);\n\n  useEffect(() => {\n    setKeyList(Object.keys(dynamicConfig));\n  }, [dynamicConfig]);\n\n  return (\n    <>\n      <div className=\"base-info-title\">动态配置</div>\n      <div className=\"detail-edit-list\">\n        {keyList.map((item) => (\n          <EditListGrid\n            title={item}\n            data={dynamicConfig[item]}\n            configData={clusterSetting[item]}\n          />\n        ))}\n      </div>\n    </>\n  );\n};\n```\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/edit-list/useClickOutSide.tsx",
    "content": "import { RefObject } from \"react\";\n\nimport { useEffect } from \"react\";\n\nexport const useClickOutSide = (ref: RefObject<HTMLElement>, handler: Function, options?: any) => {\n  useEffect(() => {\n    const listener = (event: MouseEvent) => {\n      if (!ref.current || ref.current.contains(event.target as HTMLElement)) {\n        return;\n      }\n      handler(event);\n    };\n    options ? document.addEventListener(\"click\", listener, options) : document.addEventListener(\"click\", listener);\n    return () => {\n      options ? document.addEventListener(\"click\", listener, options) : document.addEventListener(\"click\", listener);\n    };\n  }, [ref, handler]);\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/index.less",
    "content": "@import \"../../../styles/base.less\";\n\n.base-index-box {\n  padding-bottom: 20px;\n\n  &-tag {\n    padding-top: 20px;\n    display: flex;\n    flex-wrap: wrap;\n\n    &-item {\n      display: flex;\n      padding-right: 30px;\n      align-items: center;\n\n      &-title {\n        .min-title();\n        padding-right: 4px;\n        cursor: pointer;\n      }\n\n      &-title:hover {\n        color: #2a8fff;\n      }\n    }\n  }\n}\n\n.base-info-title {\n  .middle-title();\n  border-bottom: 1px solid #dbe0e4;\n  padding-bottom: 8px;\n}\n\n.tag {\n  &.green {\n    background: #ecfaf1;\n    border: 1px solid #46d677;\n    border-radius: 4px;\n    color: #52c41a;\n  }\n\n  &.yellow {\n    background: #fdf6eb;\n    border: 1px solid #f4a838;\n    border-radius: 4px;\n    color: #f27f0d;\n  }\n\n  &.red {\n    background: #fff2f0;\n    border: 1px solid rgba(255, 204, 199, 1);\n    border-radius: 4px;\n    color: #ff4d4f;\n  }\n\n  &.unknown {\n    background: #f4f4f6;\n    border: 1px solid rgba(215, 218, 224, 1);\n    border-radius: 4px;\n    color: #5b6675;\n  }\n}\n\n.success {\n  color: #10c038;\n}\n\n.unline {\n  color: #f4a838;\n}\n\n.failed {\n  color: #f04134;\n}\n\n.unknown {\n  color: #5b6675;\n}\n\n.detail-container {\n  height: 100%;\n  min-width: 1200px;\n  padding: 0 20px 20px 20px;\n  overflow: hidden;\n  .dcloud-spin-nested-loading,\n  .dcloud-spin-container {\n    height: 100%;\n    .detail-wrapper {\n      height: 92%;\n      padding: 20px;\n      min-width: 1080px;\n    }\n  }\n  .content {\n    background: #fff;\n    border-radius: 8px;\n    height: 92%;\n    overflow: auto;\n  }\n}\n\n.menu-container {\n  .menu {\n    padding: 16px 0 0 10px;\n    border-bottom: none;\n    .dcloud-menu-item {\n      padding: 0;\n      margin: 0 10px;\n      font-size: 16px;\n      color: rgba(0, 0, 0, 0.6);\n      font-weight: 600;\n      &:hover {\n        border-bottom: none;\n        color: rgba(0, 0, 0, 0.6);\n      }\n      &::after {\n        border-bottom: none !important;\n        background: transparent;\n      }\n    }\n    .dcloud-menu-item-selected {\n      font-size: 16px;\n      color: rgba(0, 0, 0, 0.87);\n      font-weight: 600;\n      &::after {\n        border-bottom: 2px solid #1473ff;\n        height: 4px;\n        border-radius: 8px;\n        background: #1473ff;\n        margin: 0 auto;\n        width: 100%;\n        position: absolute;\n        left: 0;\n      }\n    }\n  }\n}\n\n.cluster-info {\n  padding: 1px 20px;\n}\n\n.node-divide-content {\n  background: #fff;\n}\n\n.delete-batch-node {\n  .delete-title {\n    font-size: 14px;\n    font-weight: 500;\n  }\n\n  .delete-content {\n    margin: 10px 38px;\n\n    .delete-label {\n      font-weight: 500;\n      margin: 5px 0;\n    }\n\n    .delete-labels-box {\n      display: flex;\n      flex-wrap: wrap;\n\n      .delete-node {\n        display: inline-block;\n        margin-bottom: 12px;\n        margin-right: 12px;\n        padding: 2px 8px;\n        background: #ececf6;\n        border-radius: 4px;\n      }\n    }\n  }\n}\n\n.sense-page {\n  height: 100%;\n  .euiTab:focus {\n    background-color: #fff;\n    text-decoration: none;\n  }\n\n  .euiTab:hover:not(.euiTab-isSelected) {\n    text-decoration: none;\n  }\n\n  .euiTabs {\n    height: 30px;\n    line-height: 30px;\n    width: 204px;\n    background: rgba(116, 120, 141, 0.1);\n    border-radius: 4px;\n\n    .euiTab {\n      padding: 6px 9px;\n      font-size: 14px;\n      font-weight: 600;\n      color: rgba(0, 0, 0, 0.6);\n      font-family: PingfangSC-Semibold;\n    }\n  }\n\n  .euiTab.euiTab-isSelected::after {\n    height: 0px;\n  }\n\n  .euiTab.euiTab-isSelected {\n    background: #ffffff;\n    border-radius: 4px;\n    height: 26px;\n    margin: 2px;\n    line-height: 14px;\n    color: @primary-color;\n  }\n\n  .euiTabs:not(.euiTabs--condensed)::before {\n    height: 0px;\n  }\n\n  .search-profiler-page {\n    .appRoot {\n      height: calc(100vh - 204px);\n      border-radius: 8px;\n      margin-top: 4px;\n      padding: 0;\n    }\n  }\n\n  .euiButton.euiButton--primary {\n    border: none;\n    transform: none !important;\n  }\n\n  .euiButton--primary.euiButton--fill:enabled {\n    &:hover {\n      transform: none;\n      background: #3d91ff !important;\n    }\n  }\n\n  .euiTextColor--subdued {\n    h1 {\n      margin: 30px 0 2px 0;\n      font-size: 14px;\n    }\n  }\n\n  .consoleContainer {\n    padding: 0;\n  }\n}\n\n.detail-header {\n  height: 32px;\n  margin: 16px 0;\n  .left-content,\n  .right-content,\n  .title {\n    display: inline-block;\n  }\n  .left-content {\n    .iconarrow-left {\n      font-size: 20px;\n      cursor: pointer;\n    }\n    .dcloud-divider {\n      height: 20px;\n      background: rgba(0, 0, 0, 0.13);\n      margin: 0 12px;\n    }\n    .title {\n      .text {\n        font-size: 18px;\n        font-weight: 500;\n        margin-right: 8px;\n      }\n      .dcloud-tag {\n        line-height: 20px;\n        padding: 0 6px;\n      }\n    }\n  }\n  .right-content {\n    float: right;\n    .detail {\n      margin: 0 20px;\n      .label {\n        font-size: 14px;\n        color: rgba(0, 0, 0, 0.6);\n      }\n      .value {\n        font-size: 14px;\n        color: rgba(0, 0, 0, 0.87);\n      }\n    }\n    .reload-icon {\n      width: 32px;\n      height: 32px;\n      background: #ffffff;\n      border: 1px solid rgba(0, 0, 0, 0.13);\n      border-radius: 4px;\n      display: inline-block;\n      text-align: center;\n      cursor: pointer;\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/logic-list.tsx",
    "content": "import React, { useState } from \"react\";\nimport { getLogicListColumns } from \"./config\";\nimport { DTable } from \"component/dantd/dtable\";\n\nexport const LogicList = (props: { logicList: []; reloadData: any; loading: boolean }) => {\n  const [searchKey, setSearchKey] = useState(\"\");\n\n  const getData = (origin: { v1: { name: string; id: number; projectNameList: string[] }; v2: { name: string } }[]) => {\n    let data = [];\n    (origin || []).forEach((item) => {\n      let listItem = {\n        logicName: item?.v1?.name,\n        logicClusterId: item?.v1?.id,\n        region: item?.v2?.name,\n        projectNameList: item?.v1?.projectNameList,\n      };\n      data.push(listItem);\n    });\n    if (searchKey) {\n      data = data.filter((item) => item.logicName.includes(searchKey) || item.region.includes(searchKey));\n    }\n    return data;\n  };\n\n  const handleSubmit = (val: string) => setSearchKey(val);\n\n  const { logicList, reloadData, loading } = props;\n\n  return (\n    <div>\n      <DTable\n        loading={loading}\n        rowKey=\"logicClusterId\"\n        dataSource={getData(logicList)}\n        columns={getLogicListColumns()}\n        reloadData={reloadData}\n        tableHeaderSearchInput={{ submit: handleSubmit }}\n        attrs={{\n          bordered: true,\n        }}\n      />\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/logic-node-list.tsx",
    "content": "import * as React from 'react';\nimport 'styles/search-filter.less';\nimport { getLogicNodeColumns } from './config';\nimport Url from 'lib/url-parser';\nimport { getLogicClusterNodeList } from 'api/cluster-node-api';\nimport { DTable, ITableBtn } from 'component/dantd/dtable';\n\nexport interface INode {\n  createTime?: string;\n  id: number;\n  creator: string;\n  desc: string;\n  type?: number;\n  updateTime?: string;\n  md5: string;\n  name: string;\n  pdefault: string;\n  s3url: string;\n  url: string;\n  version?: string;\n  deleteFlag: boolean;\n}\n\nexport class LogicNodeList extends React.Component {\n  public state = {\n    searchKey: '',\n    nodeList: [] as INode[],\n    loading: false\n  };\n\n  public clusterId: number;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.clusterId = Number(url.search.clusterId);\n  }\n\n  public getData = (origin?: any[]) => {\n    let { searchKey } = this.state;\n    searchKey = (searchKey + '').trim().toLowerCase();\n    const data = searchKey ? origin.filter(\n      (d) =>\n        d.clusterName &&\n        d.clusterName.toLowerCase().includes(searchKey as string),\n    ) : origin;\n    return data;\n  }\n\n  public componentDidMount() {\n    this.reloadData();\n  }\n\n  public reloadData = () => {\n    this.setState({\n      loading: true\n    })\n    getLogicClusterNodeList( this.clusterId).then((res) => {\n      this.setState({\n        nodeList: res || []\n      })\n    }).finally(() => {\n      this.setState({\n        loading: false\n      })\n    })\n  }\n\n  public getOpBtns = (): ITableBtn[] => {\n    return [{\n      label: '关联region',\n      className: 'ant-btn-primary',\n      clickFunc: () => {},\n    }];\n  }\n\n  public handleSubmit = (value) => {\n    // \n  }\n\n  public render() {\n    const {nodeList, loading} = this.state;\n    return (\n      <>\n        <DTable\n          loading={loading}\n          rowKey=\"id\"\n          dataSource={this.getData(nodeList)}\n          columns={getLogicNodeColumns()}\n          reloadData={this.reloadData}\n          getOpBtns={this.getOpBtns}\n          tableHeaderSearchInput={{submit: this.handleSubmit}}\n        />\n      </>\n    );\n  }\n\n  public defineTableWrapperClassNames = () => {\n    return 'no-padding';\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/node-divide.tsx",
    "content": "import React, { useState, useEffect, useCallback } from \"react\";\nimport \"styles/search-filter.less\";\nimport { getNodeDivideColumns } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { getPhyNodeDivideList, deleteNode } from \"api/op-cluster-index-api\";\nimport { Modal, message, Button } from \"antd\";\nimport { QuestionCircleOutlined, ExclamationCircleOutlined } from \"@ant-design/icons\";\nimport _ from \"lodash\";\nimport \"./index.less\";\n\nexport const NodeDivide = (props) => {\n  const [searchKey, setSearchKey] = useState(\"\");\n  const [loading, setLoading] = useState(false);\n  const [data, setData] = useState([]);\n  const [clusterId, setClusterId] = useState(null);\n  const [selectedRowKeys, setSelectedRowKeys] = useState([]);\n  const [selectedRows, setSelectedRows] = useState([]);\n\n  useEffect(() => {\n    const url = Url();\n    setClusterId(Number(url.search.physicsClusterId));\n  }, []);\n\n  useEffect(() => {\n    clusterId && reloadData();\n  }, [clusterId]);\n\n  const reloadData = () => {\n    setLoading(true);\n    getPhyNodeDivideList(clusterId)\n      .then((res) => {\n        setData(res);\n      })\n      .finally(() => {\n        setLoading(false);\n      });\n  };\n\n  const getData = (origin?: any[]) => {\n    let key = (searchKey + \"\").trim().toLowerCase();\n    let data = key\n      ? origin.filter((d) => {\n          let flat = false;\n          Object.keys(d).forEach((objectKey) => {\n            if (typeof objectKey === \"string\" || typeof objectKey === \"number\") {\n              if ((d[objectKey] + \"\").toLowerCase().includes((key + \"\") as string)) {\n                flat = true;\n                return;\n              }\n            }\n          });\n          return flat;\n        })\n      : origin;\n    data = data.sort((a, b) => b.role - a.role);\n    return data;\n  };\n\n  const handleSubmit = (value) => {\n    setSearchKey(value);\n  };\n\n  const getOpBtns = useCallback(() => {\n    let content: string | React.ReactNode;\n    let icon: React.ReactNode;\n    let hasRegionList = selectedRows?.filter((item) => item?.regionId !== -1);\n    if (hasRegionList.length) {\n      let text = hasRegionList?.map((item) => item?.nodeSet);\n      content = `节点${text?.join(\"，\")}已被划分Region，请解绑后再下线。`;\n      icon = <ExclamationCircleOutlined />;\n    } else {\n      content =\n        selectedRows?.length === 1 ? (\n          `确定下线节点${selectedRows[0]?.nodeSet}吗？`\n        ) : (\n          <div className=\"delete-batch-node\">\n            <div className=\"delete-title\">确定批量下线节点？</div>\n            <div className=\"delete-content\">\n              <div className=\"delete-label\">操作对象</div>\n              <div className=\"delete-labels-box\">\n                {selectedRows?.map((item) => (\n                  <div className=\"delete-node\">{item.nodeSet}</div>\n                ))}\n              </div>\n            </div>\n          </div>\n        );\n      icon = <QuestionCircleOutlined />;\n    }\n    return selectedRows && selectedRows.length > 0 ? (\n      <Button\n        onClick={() => {\n          Modal.confirm({\n            icon,\n            content,\n            okText: \"确认\",\n            cancelText: \"取消\",\n            onOk: async () => {\n              if (hasRegionList.length) return;\n              await deleteNode(selectedRowKeys);\n              message.success(\"下线成功\");\n              reloadData();\n            },\n          });\n        }}\n        style={{ marginRight: 0 }}\n        type={\"primary\"}\n        disabled={selectedRows && selectedRows.length ? false : true}\n      >\n        批量下线\n      </Button>\n    ) : (\n      <></>\n    );\n  }, [selectedRows]);\n\n  return (\n    <div className=\"node-divide-content\">\n      <DTable\n        loading={loading}\n        rowKey=\"id\"\n        dataSource={getData(data)}\n        columns={getNodeDivideColumns()}\n        reloadData={reloadData}\n        tableHeaderSearchInput={{ submit: handleSubmit }}\n        attrs={{\n          bordered: true,\n          scroll: { x: \"max-content\" },\n          rowSelection: {\n            selectedRowKeys,\n            onChange: (selectedRowKeys, selectedRows) => {\n              setSelectedRowKeys(selectedRowKeys);\n              setSelectedRows(selectedRows);\n            },\n            getCheckboxProps: (record) => {\n              return {\n                disabled: record.status !== 2,\n              };\n            },\n          },\n        }}\n        renderInnerOperation={getOpBtns}\n      />\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/physics-config-info.tsx.tsx",
    "content": "import * as React from \"react\";\nimport \"styles/search-filter.less\";\nimport { getConfigInfoColumns } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { DTable, ITableBtn } from \"component/dantd/dtable\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getPhyClusterConfigList } from \"api/op-cluster-config-api\";\nimport { isOpenUp } from \"constants/common\";\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params)),\n  setPhyClusterConfigList: (configList: any) => dispatch(actions.setPhyClusterConfigList(configList)),\n});\nconst connects: Function = connect;\n\n@connects(null, mapDispatchToProps)\nexport class PhysicsConfigInfo extends React.Component<any> {\n  public state = {\n    searchKey: \"\",\n    configList: [],\n    loading: false,\n  };\n\n  public clusterId: number;\n  public cluster: string;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.clusterId = Number(url.search.physicsClusterId);\n    this.cluster = url.search.physicsCluster;\n  }\n\n  public getData = (origin?: any[]) => {\n    let { searchKey } = this.state;\n    searchKey = (searchKey + \"\").trim().toLowerCase();\n    const data = searchKey\n      ? origin.filter((d) => {\n          let flat = false;\n          Object.keys(d).forEach((key) => {\n            if (typeof key === \"string\" || typeof key === \"number\") {\n              if ((d[key] + \"\").toLowerCase().includes((searchKey + \"\") as string)) {\n                flat = true;\n                return;\n              }\n            }\n          });\n          return flat;\n        })\n      : origin;\n    return data;\n  };\n\n  public componentDidMount() {\n    this.reloadData();\n  }\n\n  public reloadData = () => {\n    this.setState({\n      loading: true,\n    });\n    getPhyClusterConfigList(this.clusterId)\n      .then((res) => {\n        this.setState({\n          configList: res,\n        });\n        this.props.setPhyClusterConfigList(res);\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n  };\n\n  public getOpBtns = (): ITableBtn[] => {\n    return [\n      {\n        label: \"新增配置\",\n        className: \"ant-btn-primary\",\n        isOpenUp: isOpenUp,\n        clickFunc: () => {\n          this.props.setModalId(\"newConfigModal\", {}, this.reloadData);\n        },\n      },\n    ];\n  };\n\n  public handleSubmit = (value) => {\n    this.setState({\n      searchKey: value,\n    });\n  };\n\n  public render() {\n    const { configList, loading } = this.state;\n    return (\n      <div>\n        <DTable\n          loading={loading}\n          rowKey=\"id\"\n          dataSource={this.getData(configList)}\n          columns={getConfigInfoColumns(this.props.setDrawerId)}\n          tableHeaderSearchInput={{ submit: this.handleSubmit, placeholder: \"请输入配置类别\" }}\n          reloadData={this.reloadData}\n        />\n      </div>\n    );\n  }\n\n  public defineTableWrapperClassNames = () => {\n    return \"no-padding\";\n  };\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/plugn-list.tsx",
    "content": "import * as React from \"react\";\nimport \"styles/search-filter.less\";\nimport { getPluginListColumns } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { DTable, ITableBtn } from \"component/dantd/dtable\";\nimport { getOpClusterPlugList } from \"api/plug-api\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { IPlug } from \"typesPath/plug-types\";\nimport { isOpenUp } from \"constants/common\";\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\nconst connects: Function = connect;\n\n@connects(null, mapDispatchToProps)\nexport class PlugnList extends React.Component<any> {\n  public state = {\n    searchKey: \"\",\n    plugnList: [] as IPlug[],\n    loading: false,\n  };\n\n  public cluster: string;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.cluster = url.search.physicsCluster;\n  }\n\n  public getData = (origin?: any[]) => {\n    let { searchKey } = this.state;\n    searchKey = (searchKey + \"\").trim().toLowerCase();\n    const data = searchKey\n      ? origin.filter((d) => {\n          let flat = false;\n          Object.keys(d).forEach((key) => {\n            if (typeof key === \"string\" || typeof key === \"number\") {\n              if ((d[key] + \"\").toLowerCase().includes((searchKey + \"\") as string)) {\n                flat = true;\n                return;\n              }\n            }\n          });\n          return flat;\n        })\n      : origin;\n    return data;\n  };\n\n  public componentDidMount() {\n    this.reloadData();\n  }\n\n  public reloadData = () => {\n    this.setState({\n      loading: true,\n    });\n    getOpClusterPlugList(this.cluster)\n      .then((res) => {\n        this.setState({\n          plugnList: res,\n        });\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n  };\n\n  public getOpBtns = (): ITableBtn[] => {\n    return [\n      {\n        label: \"上传自定义插件\",\n        className: \"ant-btn-primary\",\n        isOpenUp: isOpenUp,\n        clickFunc: () => {\n          this.props.setModalId(\"customPlugn\", {}, this.reloadData);\n        },\n      },\n    ];\n  };\n\n  public handleSubmit = (value) => {\n    this.setState({\n      searchKey: value,\n    });\n  };\n\n  public render() {\n    const { plugnList, loading } = this.state;\n    return (\n      <>\n        <DTable\n          loading={loading}\n          rowKey=\"id\"\n          dataSource={this.getData(plugnList)}\n          columns={getPluginListColumns(this.reloadData, this.props.setModalId)}\n          tableHeaderSearchInput={{ submit: this.handleSubmit }}\n          reloadData={this.reloadData}\n          getOpBtns={this.getOpBtns}\n        />\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/region-task-item-modal.tsx",
    "content": "import * as React from 'react';\nimport moment from 'moment';\nimport { Row, Col } from 'antd';\nimport { IRegionTaskItem } from 'typesPath/cluster/physics-type';\n\nexport const TaskItemModal = (props: IRegionTaskItem) => {\n    return (\n      <>\n        <Row>\n          <Col span={12}>\n              <label>id： {props.id}</label>\n          </Col>\n          <Col span={12}>\n            <label>物理模板id： {props.physicalId}</label>\n          </Col>\n        </Row>\n        <Row>\n          <Col span={12}>\n              <label>集群： {props.cluster}</label>\n          </Col>\n          <Col span={12}>\n            <label>模板名字：{props.templateName}</label>\n          </Col>\n        </Row>\n        <Row>\n          <Col span={12}>\n            <label>数据保存时长： {props.expireTime}</label>\n          </Col>\n          <Col span={12}>\n            <label>shard个数：{props.shardNum}</label>\n          </Col>\n        </Row>\n        <Row>\n          <Col span={12}>\n            <label>模板创建时间： {moment(props.createTime).format('YYYY-MM-DD  hh:mm:ss')}</label>\n          </Col>\n          <Col span={12}>\n            <label>时间后缀：: {props.dateFormat}</label>\n          </Col>\n        </Row>\n        <Row>\n          <Col span={12}>\n            <label>模板总的磁盘消耗： {props.sumIndexSizeG}</label>\n          </Col>\n          <Col span={12}>\n            <label>总条数： {props.sumDocCount}</label>\n          </Col>\n        </Row>\n        <Row>\n          <Col span={12}>\n            <label>冷数据的天数： {''}</label>\n          </Col>\n          <Col span={12}>\n            <label>tps峰值：: {props.maxTps}</label>\n          </Col>\n        </Row>\n        <Row>\n          <Col span={12}>\n            <label>查询的峰值： {props.maxQueryTime}</label>\n          </Col>\n          <Col span={12}>\n            <label>scroll的峰值：{props.maxScrollTime}</label>\n          </Col>\n        </Row>\n        <Row>\n          <Col span={12}>\n            <label>副本个数： {props.replicaNum}</label>\n          </Col>\n          <Col span={12}>\n            <label>实际的磁盘消耗：{props.actualDiskG}</label>\n          </Col>\n        </Row>\n        <Row>\n          <Col span={12}>\n            <label>实际的CPU消耗： {props.actualCpuCount}</label>\n          </Col>\n          <Col span={12}>\n            <label>Quota的磁盘消耗：{props.quotaDiskG}</label>\n          </Col>\n        </Row>\n        <Row>\n          <Col span={12}>\n            <label>Quota的CPU消耗： {props.quotaCpuCount}</label>\n          </Col>\n          <Col span={12}>\n            <label>综合的磁盘消耗：{props.combinedDiskG}</label>\n          </Col>\n        </Row>\n      </>\n    );\n}\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/searchProfiler.tsx",
    "content": "import React, { useEffect } from \"react\";\nimport { DevToolsPage } from \"@knowdesign/kbn-sense\";\n\nimport Url from \"lib/url-parser\";\nimport { isSuperApp, setCookie } from \"lib/utils\";\nimport { XNotification } from \"component/x-notification\";\nimport { IndexSelect } from \"../../IndexSelect\";\n\nexport const SearchProfiler = (props: any) => {\n  const physicsCluster: string = Url().search?.physicsCluster;\n  setCookie([{ key: \"kibanaPhyClusterName\", value: physicsCluster }]);\n\n  useEffect(() => {\n    const onHandleVisibleChange = () => {\n      if (!document.hidden) {\n        const physicsCluster: string = Url().search?.physicsCluster;\n        setCookie([{ key: \"kibanaPhyClusterName\", value: physicsCluster }]);\n      }\n    };\n    document.addEventListener(\"visibilitychange\", onHandleVisibleChange);\n\n    return () => {\n      document.removeEventListener(\"visibilitychange\", onHandleVisibleChange);\n    };\n  }, []);\n\n  return (\n    <div className=\"sense-page\">\n      <DevToolsPage\n        noNeedTab={true}\n        activeId={\"searchprofiler\"}\n        currentCluster={{ id: physicsCluster }}\n        notifications={XNotification}\n        IndexSelect={IndexSelect}\n        isSuperApp={!!isSuperApp()}\n      />\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics-detail/sense.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { DevToolsPage } from \"@knowdesign/kbn-sense\";\nimport Url from \"lib/url-parser\";\nimport { setCookie, getCookie, getCurrentProject, isSuperApp } from \"lib/utils\";\nimport { XNotification } from \"component/x-notification\";\nimport { IndexSelect } from \"../../IndexSelect\";\nimport { getSenseOperate, setSenseOperate } from \"api/cluster-api\";\n\nexport const Sense = (props: any) => {\n  const physicsCluster: string = Url().search?.physicsCluster;\n  setCookie([{ key: \"kibanaPhyClusterName\", value: physicsCluster }]);\n  const clusterId = Number(Url().search?.physicsClusterId);\n\n  const [content, setContent] = useState(\"\");\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    _getSenseOperate();\n    const onHandleVisibleChange = () => {\n      if (!document.hidden) {\n        const physicsCluster: string = Url().search?.physicsCluster;\n        setCookie([{ key: \"kibanaPhyClusterName\", value: physicsCluster }]);\n      }\n    };\n    document.addEventListener(\"visibilitychange\", onHandleVisibleChange);\n\n    return () => {\n      document.removeEventListener(\"visibilitychange\", onHandleVisibleChange);\n    };\n  }, []);\n\n  const _getSenseOperate = async () => {\n    let params = { userName: getCookie(\"userName\") || \"\", content: \"\", projectId: getCurrentProject()?.id || \"\" };\n    let data = await getSenseOperate(params);\n    let content = \"\";\n    (data || []).forEach((item) => {\n      content += `${item}\\n`;\n    });\n    setContent(content);\n    setLoading(false);\n  };\n\n  const onInputEditorChange = (content) => {\n    let contentArr = content?.split(\"\\n\");\n    if (contentArr?.length > 1000) {\n      content = contentArr?.slice(0, 1000)?.join(\"\\n\");\n    }\n    let params = { userName: getCookie(\"userName\") || \"\", content, projectId: getCurrentProject()?.id || \"\" };\n    setSenseOperate(params);\n  };\n\n  return (\n    <div className=\"sense-page\">\n      {loading ? null : (\n        <DevToolsPage\n          consoleEditorValue={content}\n          onInputEditorChange={onInputEditorChange}\n          noNeedTab={true}\n          currentCluster={{ id: physicsCluster }}\n          notifications={XNotification}\n          IndexSelect={IndexSelect}\n          isSuperApp={!!isSuperApp()}\n        />\n      )}\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/cluster/physics.tsx",
    "content": "import React, { useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getPhysicsColumns, getPhyClusterQueryXForm } from \"./config\";\nimport {\n  getOpPhysicsClusterList,\n  getNodeSpecification,\n  IClusterList,\n  getPackageList,\n  getZeusUrl,\n  getSuperPhyClusterList,\n  getSuperLogiClusterList,\n} from \"api/cluster-api\";\nimport { DTable, ITableBtn } from \"component/dantd/dtable\";\nimport { INodeListObjet } from \"container/modal/physics-cluster/apply-cluster\";\nimport { IVersions } from \"typesPath/cluster/physics-type\";\nimport { Button, Tag } from \"knowdesign\";\nimport { RenderTitle } from \"component/render-title\";\nimport { isOpenUp } from \"constants/common\";\nimport \"./index.less\";\nimport { PhyClusterPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { XNotification } from \"component/x-notification\";\nimport { ProTable } from \"knowdesign\";\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params, cb)),\n});\n\nconst PhysicsClusterBox = (props) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject]: any = useState({\n    current: 1,\n    size: 10,\n  });\n  const [data, setData] = useState([]);\n  const [total, setTotal] = useState(0);\n  const [url, setUrl] = useState(\"\");\n  const [packageHostList, setPackageHostList] = useState([]);\n  const [packageDockerList, setPackageDockerList] = useState([]);\n  const [phyClusterList, setPhyClusterList] = useState([]);\n  const [logiClusterList, setLogiClusterList] = useState([]);\n  const [form, setForm] = useState<any>();\n\n  React.useEffect(() => {\n    _getPackageList();\n    getPhyClusterList();\n    getLogiClusterList();\n  }, []);\n\n  React.useEffect(() => {\n    reloadData();\n  }, [department, queryFormObject]);\n\n  const reloadData = () => {\n    const app = JSON.parse(localStorage.getItem(\"current-project\"));\n    if (!app?.name) {\n      return;\n    }\n    setloading(true);\n    const Params: IClusterList = {\n      page: queryFormObject.current,\n      size: queryFormObject.size,\n      authType: queryFormObject.currentAppAuth,\n      health: queryFormObject.health,\n      cluster: queryFormObject.cluster,\n      esVersion: queryFormObject.esVersion,\n      sortTerm: queryFormObject.sortTerm,\n      orderByDesc: queryFormObject.orderByDesc,\n      id: queryFormObject.id !== undefined ? +queryFormObject.id : undefined,\n      desc: queryFormObject.desc,\n      logicClusterName: queryFormObject.logicClusterName,\n    };\n    getOpPhysicsClusterList(Params)\n      .then((res) => {\n        if (res) {\n          setData(\n            res?.bizData?.map((item) => ({\n              ...item,\n              diskInfo: {\n                diskTotal: item.diskTotal,\n                diskUsage: item.diskUsage,\n                diskUsagePercent: item.diskUsagePercent,\n              },\n            }))\n          );\n          setTotal(res?.pagination?.total);\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n    getZeusUrl().then((res) => {\n      setUrl(res);\n    });\n  };\n\n  const _getPackageList = async () => {\n    let data = await getPackageList();\n    const packageList = data.map((ele, index) => {\n      return {\n        ...ele,\n        key: ele.id,\n        value: ele.esVersion,\n        title: ele.esVersion,\n      };\n    });\n    let dockerList = packageList.filter((ele) => ele.manifest === 3);\n    let hostList = packageList.filter((ele) => ele.manifest === 4);\n    setPackageHostList(hostList);\n    setPackageDockerList(dockerList);\n  };\n\n  const getPhyClusterList = () => {\n    getSuperPhyClusterList().then((res = []) => {\n      const list = res.map((item) => ({ title: item, value: item }));\n      setPhyClusterList(list);\n    });\n  };\n\n  const getLogiClusterList = (phyClusterName?: string) => {\n    getSuperLogiClusterList(phyClusterName).then((res = []) => {\n      const list = res.map((item) => ({ title: item, value: item }));\n      setLogiClusterList(list);\n    });\n  };\n\n  const onPhyClusterChange = (val) => {\n    form.setFieldsValue({ logicClusterName: undefined });\n    getLogiClusterList(val);\n  };\n\n  const renderTitleContent = () => {\n    return {\n      title: \"物理集群\",\n      content: null,\n    };\n  };\n\n  const handleReset = () => {\n    // 重置重新请求逻辑集群接口\n    getLogiClusterList();\n    setqueryFormObject({ size: queryFormObject.size, current: 1 });\n  };\n\n  const handleSubmit = (result) => {\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject({ ...result, size: queryFormObject.size, current: 1 });\n  };\n\n  const getModalData = () => {\n    const nodeList = {} as INodeListObjet;\n    let machineList = [] as { value: string }[];\n\n    getNodeSpecification()\n      .then((data) => {\n        machineList = data.map((item) => {\n          return {\n            value: item,\n          };\n        });\n        props.setModalId(\n          \"applyPhyCluster\",\n          { loading: false, nodeList, packageDockerList, packageHostList, machineList, history: props.history },\n          reloadData\n        );\n      })\n      .catch((err) => {\n        XNotification({ type: \"error\", message: \"网络错误！\" });\n        props.setModalId(\"\");\n      });\n  };\n\n  const getOpBtns = (): ITableBtn[] => {\n    return [\n      hasOpPermission(PhyClusterPermissions.PAGE, PhyClusterPermissions.ACCESS) && {\n        label: \"接入集群\",\n        type: \"default\",\n        clickFunc: () => props.setModalId(\"accessCluster\", {}, reloadData),\n      },\n      {\n        type: \"primary\",\n        label: \"新建集群\",\n        isOpenUp: isOpenUp,\n        clickFunc: () => getModalData(),\n      },\n    ].filter(Boolean);\n  };\n  const handleChange = (pagination, filters, sorter) => {\n    // 条件过滤请求在这里处理\n    const sorterObject: { [key: string]: any } = {};\n    if (sorter.columnKey && sorter.order) {\n      switch (sorter.columnKey) {\n        case \"diskInfo\":\n          sorterObject.sortTerm = \"disk_usage_percent\";\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n        case \"activeShardNum\":\n          sorterObject.sortTerm = \"active_shard_num\";\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n        default:\n          break;\n      }\n    }\n    setqueryFormObject((state) => {\n      if (!sorter.order) {\n        delete state.sortTerm;\n        delete state.orderByDesc;\n      }\n\n      return {\n        ...state,\n        ...sorterObject,\n        current: pagination.current,\n        size: pagination.pageSize,\n      };\n    });\n  };\n\n  const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n  return (\n    <div className=\"table-layout-style\">\n      <ProTable\n        showQueryForm={true}\n        queryFormProps={{\n          // layout: \"inline\", //没有label的查询条件\n          // colMode: \"style\", //col默认设计样式\n          totalNumber: total, //传入总条数\n          defaultCollapse: true,\n          columns: getPhyClusterQueryXForm(data, packageHostList, phyClusterList, logiClusterList, onPhyClusterChange),\n          // onChange={() => null}\n          onReset: handleReset,\n          onSearch: handleSubmit,\n          initialValues: queryFormObject,\n          isResetClearAll: true,\n          getFormInstance: (form) => setForm(form),\n        }}\n        tableProps={{\n          tableId: \"physics_cluster_list\", //开启表格自定义列\n          key: JSON.stringify({\n            authType: queryFormObject.authType,\n            health: queryFormObject.health,\n            cluster: queryFormObject.cluster,\n            esVersion: queryFormObject.esVersion,\n          }),\n          isCustomPg: false,\n          loading,\n          rowKey: \"id\",\n          dataSource: data,\n          columns: getPhysicsColumns(props.setModalId, props.setDrawerId, reloadData, props),\n          reloadData,\n          getOpBtns: getOpBtns,\n          customRenderSearch: () => (\n            <div className=\"zeus-url\">\n              <RenderTitle {...renderTitleContent()} />{\" \"}\n              {url && (\n                <Tag className=\"zeus-url-tag\" onClick={() => (window.open(\"about:blank\").location.href = url)}>\n                  Zeus管控\n                </Tag>\n              )}\n            </div>\n          ),\n          paginationProps: {\n            position: \"bottomRight\",\n            showQuickJumper: true,\n            total: total,\n            showSizeChanger: true,\n            pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n            showTotal: (total) => `共 ${total} 条`,\n            current: queryFormObject.current,\n          },\n          attrs: {\n            onChange: handleChange,\n            scroll: { x: \"max-content\" },\n          },\n          ...props,\n        }}\n      />\n    </div>\n  );\n};\nexport const PhysicsCluster = connect(null, mapDispatchToProps)(PhysicsClusterBox);\n"
  },
  {
    "path": "arius-console/src/container/custom-component.tsx",
    "content": "import React from \"react\";\nimport \"styles/custom-component.less\";\nimport \"styles/table-filter.less\";\nimport { QuestionCircleOutlined } from \"@ant-design/icons\";\nimport { Tooltip, Modal, Button, Popconfirm, Dropdown, Spin, Menu, Tag, Popover, Progress } from \"antd\";\nimport { withRouter, Link } from \"react-router-dom\";\nimport { ITableBtn } from \"component/dantd/dtable\";\nimport { openSourceTip } from \"constants/status-map\";\nimport { refreshByCacheKey } from \"react-router-cache-route\";\nimport { bytesUnitFormatter } from \"../lib/utils\";\nimport { TooltipPlacement } from \"antd/es/tooltip\";\n\ninterface INavRouterLinkProps {\n  element: JSX.Element | string;\n  href: string;\n  needToolTip?: boolean;\n  onClick?: any;\n  removeCacheKey?: any;\n  maxShowLength?: number;\n  style?: any;\n}\n\nconst hiddenTooltipElement = (className: string) => {\n  const navLinkTooltips = document.getElementsByClassName(className);\n  for (let i = 0; i < navLinkTooltips.length; i++) {\n    (navLinkTooltips[i] as any).style = \"top: -1000px; left: -1000px\";\n  }\n};\n\nexport const NavRouterLink = withRouter<any, any>((props: INavRouterLinkProps) => {\n  const overlayClassName = \"nav-link-tooltip\";\n  // 限制展示固定字符\n  const renderElement = () => {\n    if (props.maxShowLength && typeof props.element === \"string\") {\n      if (props.element.length <= props.maxShowLength) {\n        return props.element;\n      }\n      return props.element.slice(0, props.maxShowLength) + \"...\";\n    } else {\n      return props.element;\n    }\n  };\n  return (\n    <Link\n      onClick={() => {\n        props.onClick && props.onClick();\n        props.needToolTip && hiddenTooltipElement(overlayClassName);\n        props.removeCacheKey && refreshByCacheKey(props.removeCacheKey);\n      }}\n      to={props.href}\n      style={props?.style}\n    >\n      {props.needToolTip ? (\n        <Tooltip overlayClassName={overlayClassName} placement=\"bottomLeft\" title={props.element}>\n          {renderElement()}\n        </Tooltip>\n      ) : (\n        renderElement()\n      )}\n    </Link>\n  );\n});\n\nexport const showSubmitOrderSuccessModal = (params: { title: string; id: number; onOk?: any; width?: number }, history?: any) => {\n  Modal.success({\n    onOk: params.onOk && params.onOk,\n    okText: \"确定\",\n    title: \"提交成功！\",\n    width: params.width,\n    content: (\n      <>\n        <div className=\"order-success\">\n          <span>{params.title}已提交！可至“工单任务” &gt; “我的申请”中查看工单详情</span>\n          <br />\n          <span>\n            工单标题（ID）：\n            <Button\n              type=\"link\"\n              style={{ padding: 0 }}\n              onClick={() => {\n                Modal.destroyAll();\n                history.push(`/work-order/my-application/detail?orderId=${params.id}`);\n              }}\n            >\n              {params.title}（{params.id}）\n            </Button>\n          </span>\n        </div>\n      </>\n    ),\n  });\n};\n\nexport const showSubmitTaskSuccessModal = (\n  params: {\n    title: string;\n    id: number;\n    onOk?: any;\n    businessKey: string;\n    taskType: number;\n    status: string;\n    expandData: string;\n  },\n  history?: any\n) => {\n  Modal.success({\n    onOk: params.onOk && params.onOk,\n    okText: \"确定\",\n    title: \"提交成功！\",\n    content: (\n      <>\n        <div className=\"order-success\">\n          <span>{params.title}已提交！可至“任务中心”查看任务详情</span>\n          <br />\n          <span>\n            任务标题（ID）：\n            <Button\n              type=\"link\"\n              style={{ padding: 0 }}\n              onClick={() => {\n                Modal.destroyAll();\n                history.push(\n                  `/work-order/task/detail?title=${params.title}&taskid=${params.id}&id=${Number(params.businessKey)}&type=${\n                    params.taskType\n                  }&status=${params.status}&dcdr_info=${encodeURI(`${params.expandData}`)}`\n                );\n              }}\n            >\n              {params.title}（{params.id}）\n            </Button>\n          </span>\n        </div>\n      </>\n    ),\n  });\n};\n\nexport const CancelActionModal = (props: { routeHref: string; history?: any; cb?: Function }) => {\n  const onHandleCancel = (routeHref: string, history?: any, cb?: Function) => {\n    Modal.confirm({\n      title: \"确定取消？\",\n      content: \"取消后当前填写内容将失效，请谨慎操作\",\n      okText: \"确定\",\n      cancelText: \"取消\",\n      icon: <QuestionCircleOutlined className=\"question-icon\" />,\n      onOk: () => {\n        const url = window?.location?.pathname;\n        setTimeout(() => {\n          if (history) {\n            history.push(routeHref.replace(\"/es\", \"\"));\n          } else {\n            window.location.href = routeHref;\n          }\n          if (cb) {\n            cb(url);\n          }\n        }, 500);\n      },\n    });\n  };\n\n  return <Button onClick={() => onHandleCancel(props.routeHref, props.history, props.cb)}>取消</Button>;\n};\n\nexport const renderOperationBtns = (btns: ITableBtn[], record: any, limit = 4) => {\n  btns = btns.filter((item) => !item.invisible);\n  const freeBtns = btns.length < limit ? btns : [].concat(btns).splice(0, 2);\n  const leftBtns = [].concat(btns).splice(2);\n\n  if (!freeBtns.length) {\n    return <>-</>;\n  }\n\n  return (\n    <>\n      <span className=\"table-operation\">\n        {freeBtns.map((item, index) => {\n          if (item.isOpenUp)\n            return (\n              <Tooltip key={index} title={item.tip || openSourceTip}>\n                <a key={index} style={{ color: \"#bfbfbf\" }}>\n                  {item.label}\n                </a>\n              </Tooltip>\n            );\n\n          if (item.isRouterNav) {\n            return <span key={index}>{item.label}</span>;\n          }\n\n          if (item.needConfirm) {\n            return (\n              <Popconfirm\n                key={index}\n                title={`确认${item.confirmText}?`}\n                onConfirm={() => item.clickFunc(record)}\n                okText={item.confirmText}\n                cancelText=\"取消\"\n              >\n                <a type=\"javascript;\">{item.label}</a>\n              </Popconfirm>\n            );\n          }\n\n          if (item.clickFunc) {\n            return (\n              <a type=\"javascript;\" key={index} onClick={() => item.clickFunc(record)}>\n                {item.label}\n              </a>\n            );\n          }\n          return (\n            <span key={index}>\n              <a>{item.label}</a>\n            </span>\n          );\n        })}\n        {btns.length >= limit ? <MoreBtns btns={leftBtns} data={record} /> : null}\n      </span>\n    </>\n  );\n};\n\nexport const renderMoreBtns = (btns: ITableBtn[], record: any) => {\n  const freeBtns = btns.length < 3 ? btns : [].concat(btns).splice(0, 3);\n  const leftBtns = [].concat(btns).splice(3);\n\n  return (\n    <>\n      <span className=\"table-header-operation\">\n        {freeBtns.map((item, index) => {\n          if (item.invisible) return null;\n          if (item.isOpenUp)\n            return (\n              <Tooltip key={index} title={openSourceTip}>\n                <Button type={item.type || \"primary\"} key={index} disabled={true} onClick={item.clickFunc}>\n                  {item.label}\n                </Button>\n              </Tooltip>\n            );\n\n          if (item.isRouterNav) {\n            return (\n              <Button type={item.type || \"primary\"} key={index}>\n                {item.label}\n              </Button>\n            );\n          }\n\n          if (item.clickFunc) {\n            return (\n              <Button type={item.type || \"primary\"} key={index} onClick={item.clickFunc}>\n                {item.label}\n              </Button>\n            );\n          }\n        })}\n        {btns.length > 3 ? <DetailMoreBtns btns={leftBtns} data={record} /> : null}\n      </span>\n    </>\n  );\n};\n\ninterface IMoreBtnsProps {\n  btns: ITableBtn[];\n  data: object;\n}\n\nexport const MoreBtns = (props: IMoreBtnsProps) => {\n  const { btns, data } = props;\n\n  // 当下拉框中选项都禁用时，将 更多 文字置灰\n  const flag = btns.length === btns.filter((item) => item.isOpenUp).length;\n\n  const btnsMenu = (\n    <ul className=\"dropdown-menu\">\n      {btns.map((v, index) => {\n        if (v.invisible) return null;\n\n        if (v.isOpenUp)\n          return (\n            <li key={index} className=\"es-open-theme\">\n              <Tooltip title={v.tip || openSourceTip}>\n                <a style={{ color: \"#bfbfbf\" }}> {v.label} </a>\n              </Tooltip>\n            </li>\n          );\n\n        if (v.isRouterNav) {\n          return (\n            <li key={index} className=\"es-open-theme\">\n              {v.label}\n            </li>\n          );\n        }\n        if (v.clickFunc) {\n          return (\n            <li key={index} onClick={() => v.clickFunc(data)} className=\"es-open-theme\">\n              <a>{v.label}</a>\n            </li>\n          );\n        }\n        return (\n          <li key={index} className=\"es-open-theme\">\n            <a>{v.label}</a>\n          </li>\n        );\n      })}\n    </ul>\n  );\n  return (\n    <Dropdown key=\"2\" overlay={btnsMenu} trigger={[\"hover\"]} placement=\"bottomLeft\">\n      <span className=\"es-open-theme ml-10\">\n        <a style={{ color: flag ? \"#bfbfbf\" : \"none\" }}>更多</a>\n      </span>\n    </Dropdown>\n  );\n};\n\nexport const DetailMoreBtns = (props: IMoreBtnsProps) => {\n  const { btns, data } = props;\n\n  // 当下拉框中选项都禁用时，将 更多 文字置灰\n  const flag = btns.length === btns.filter((item) => item.isOpenUp).length;\n\n  const btnsMenu = (\n    <Menu>\n      {btns.map((v, index) => {\n        if (v.invisible) return null;\n\n        if (v.isOpenUp) {\n          return (\n            <Menu.Item key={index}>\n              <Tooltip title={openSourceTip}>\n                <a style={{ color: \"#bfbfbf\" }}> {v.label} </a>\n              </Tooltip>\n            </Menu.Item>\n          );\n        }\n\n        if (v.clickFunc) {\n          return (\n            <Menu.Item key={index}>\n              <a style={{ color: \"#526ecc\" }} onClick={() => v.clickFunc()}>\n                {v.label}\n              </a>\n            </Menu.Item>\n          );\n        }\n        return (\n          <Menu.Item key={index}>\n            <a>{v.label}</a>\n          </Menu.Item>\n        );\n      })}\n    </Menu>\n  );\n  return (\n    <Dropdown key=\"2\" overlay={btnsMenu} trigger={[\"click\", \"hover\"]} placement=\"bottomLeft\">\n      <Button className={flag ? \"disabled-button\" : \"\"}>更多</Button>\n    </Dropdown>\n  );\n};\n\nexport const LoadingBlock = (props: { loading: boolean; height?: number }) => {\n  return <Spin style={{ height: props.height, lineHeight: props.height }} spinning={props.loading} className=\"loading-content\" />;\n};\n\nexport const renderAttributes = (params: {\n  data: any;\n  type?: string;\n  limit?: number;\n  splitType?: string;\n  placement?: TooltipPlacement;\n}) => {\n  const { data, type = \",\", limit = 2, splitType = \"；\", placement } = params;\n  let attrArray = data;\n  if (!Array.isArray(data) && data) {\n    attrArray = data.split(type);\n  }\n  const showItems = attrArray.slice(0, limit) || [];\n  const hideItems = attrArray.slice(limit, attrArray.length) || [];\n  let content = hideItems.map((item, index) => (\n    <Tag key={index} className=\"tag-blue\">\n      {item}\n    </Tag>\n  ));\n\n  return (\n    <div className=\"attribute-content\">\n      {showItems.length > 0 ? showItems.join(splitType) : \"-\"}\n      {hideItems.length > 0 && (\n        <Popover placement={placement || \"bottomRight\"} content={content} overlayClassName=\"attribute-tag\">\n          <Tag className=\"tag-blue tag-num\">共{attrArray.length}个</Tag>\n        </Popover>\n      )}\n    </div>\n  );\n};\n\nexport const renderDiskRate = (diskInfo: { diskUsagePercent: number; diskUsage: number; diskTotal: number }) => {\n  const num = Number((diskInfo.diskUsagePercent * 100).toFixed(2));\n  let strokeColor: string;\n  let yellow = \"#F4A838\";\n  let red = \"#df6d62\";\n  if (num > 90) {\n    strokeColor = red;\n  } else if (num > 70) {\n    strokeColor = yellow;\n  } else {\n    strokeColor = \"#1473FF\";\n  }\n\n  return (\n    <div style={{ position: \"relative\" }} className=\"process-box\">\n      <Progress className=\"process-box-\" percent={num} size=\"small\" strokeColor={strokeColor} style={{ width: \"100%\" }} showInfo={false} />\n      <div className=\"process-box-foot\">\n        <span className=\"process-box-foot-byte\">\n          {bytesUnitFormatter(diskInfo.diskUsage || 0)}/{bytesUnitFormatter(diskInfo.diskTotal || 0)}\n        </span>\n        <span className=\"process-box-foot-per\">{num + \"%\"}</span>\n      </div>\n    </div>\n  );\n};\n\nexport const renderMoreText = (text, maxShowLength) => {\n  if (text?.length <= maxShowLength) {\n    return text || \"-\";\n  } else {\n    return <Tooltip title={text}>{text?.slice(0, maxShowLength) + \"...\"}</Tooltip>;\n  }\n};\n"
  },
  {
    "path": "arius-console/src/container/custom-form/add-role-table.tsx",
    "content": "import { MinusOutlined, PlusOutlined } from \"@ant-design/icons\";\nimport { Button, Checkbox, Tooltip } from \"antd\";\nimport React from \"react\";\nimport \"./index.less\";\nimport { TableFormAddRow } from \"./tpl-table-add-row/TableFormAddRow\";\n\nexport const nodeTypeList = [\"masternode\", \"clientnode\", \"datanode\", \"Cold属性节点\"];\n\nexport const AddRoleTable = (props) => {\n  const [isShow, setIsShow] = React.useState(true);\n  const [isCold, setIsCold] = React.useState(false);\n\n  const addNodeTypeList = [nodeTypeList[1], nodeTypeList[2]];\n  const coldNodeTypeList = [nodeTypeList[3]];\n\n  const handleChange = (params) => {\n    const { onChange } = props;\n    onChange && onChange(params);\n  };\n\n  const renderItem = (item) => {\n    return (\n      <div key={item}>\n        <div className=\"add-role-table-header\">\n          <div className=\"role-table-text\">\n            <span>{item}</span>\n          </div>\n          <TableFormAddRow type={item} onChange={handleChange} machineList={props.machineList} />\n        </div>\n      </div>\n    );\n  };\n\n  return (\n    <>\n      <TableFormAddRow type={nodeTypeList[0]} onChange={handleChange} machineList={props.machineList} />\n      <div className=\"add-role-button\">\n        {isShow ? (\n          <Button\n            className=\"add-node\"\n            type=\"link\"\n            size=\"small\"\n            onClick={() => {\n              setIsShow((b) => !b);\n            }}\n          >\n            <PlusOutlined />\n            添加节点类型\n          </Button>\n        ) : (\n          <Button\n            className=\"delete-node\"\n            type=\"link\"\n            size=\"small\"\n            onClick={() => {\n              setIsShow((b) => !b);\n            }}\n          >\n            <MinusOutlined />\n            删除节点类型\n          </Button>\n        )}\n      </div>\n      {!isShow ? addNodeTypeList.map((item) => renderItem(item)) : null}\n      {!isShow && isCold ? coldNodeTypeList.map((item) => renderItem(item)) : null}\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/custom-form/base.tsx",
    "content": "import { INode, IOpClusterRoles } from \"typesPath/cluster/cluster-types\";\nimport { ArrowDownOutlined, ArrowUpOutlined, MinusCircleOutlined, PlusOutlined } from \"@ant-design/icons\";\nimport { Button, Form, InputNumber, Select, Space, Table, Tooltip, Input } from \"antd\";\nimport { getAccessClusterNodeSpecification, getPhysicClusterRoles, getNodeCount } from \"api/cluster-api\";\nimport React, { forwardRef, useState, useEffect } from \"react\";\nimport \"./index.less\";\nimport { INodeListObjet } from \"container/modal/physics-cluster/apply-cluster\";\nimport { regNonnegativeNumber, regOddNumber, regIp } from \"constants/reg\";\nimport { filterOption, uuid } from \"lib/utils\";\n\nconst { TextArea } = Input;\n\ninterface Props {\n  onChange?: (result: any) => any;\n  value?: any;\n  style?: any;\n  id?: any;\n  host?: string;\n  nodeList?: INodeListObjet;\n  isHidden?: boolean;\n}\n\nexport const Demo: React.FC<Props> = (props) => {\n  const [tableData, setTableData] = React.useState([]);\n\n  React.useEffect(() => {}, []);\n\n  return <></>;\n};\n\n// 只渲染\nexport const RenderText = (props: any, ref) => {\n  return <span>{props.value || props.text}</span>;\n};\n\n// Datanode 选择\nexport const DataNode: React.FC<Props> = forwardRef((props, ref) => {\n  const [dataNode, setDataNode] = React.useState([]);\n  const [dataNodeSpec, setDataNodeSpec] = React.useState(\"\");\n  const [dataNodeNu, setDataNodeNu] = React.useState(2);\n  const [nodeCount, setNodeCount] = useState([]);\n\n  useEffect(() => {\n    _getNodeSpecification();\n  }, []);\n\n  const _getNodeSpecification = async () => {\n    let res = await getAccessClusterNodeSpecification();\n    let list = (res || []).map((item) => {\n      return { value: item };\n    });\n    let count = await getNodeCount();\n    let nodeCount = (count || []).map((item) => {\n      return { value: item };\n    });\n    setDataNode(list);\n    setNodeCount(nodeCount);\n  };\n\n  const handleChangeSpecification = (value) => {\n    setDataNodeSpec(value);\n    const { onChange } = props;\n    onChange && onChange({ dataNodeSpec: value, dataNodeNu });\n  };\n\n  const handleChangeNuber = (value) => {\n    const _value = value.length ? +value[value.length - 1] : (null as any);\n    setDataNodeNu(_value);\n    const { onChange } = props;\n    onChange && onChange({ dataNodeSpec, dataNodeNu: _value });\n  };\n\n  return (\n    <div className=\"datanode-select\">\n      <Select\n        showSearch\n        placeholder=\"请输入节点规格\"\n        onChange={handleChangeSpecification}\n        filterOption={filterOption}\n        style={{ width: 218, marginRight: 16 }}\n      >\n        {dataNode.map((v) => (\n          <Select.Option value={v.value} key={v.value}>\n            {(v.value + \"\")?.length > 35 ? (\n              <Tooltip placement=\"bottomLeft\" title={v.value}>\n                {v.value}\n              </Tooltip>\n            ) : (\n              v.value\n            )}\n          </Select.Option>\n        ))}\n      </Select>\n      <Select\n        placeholder=\"请输入节点个数\"\n        onChange={handleChangeNuber}\n        mode=\"tags\"\n        value={(props.value?.dataNodeNu && props.value?.dataNodeNu + \"\") || []}\n        maxTagCount={1}\n        style={{ width: 218 }}\n      >\n        {nodeCount.map((v) => (\n          <Select.Option value={v.value} key={v.value}>\n            {(v.value + \"\")?.length > 35 ? (\n              <Tooltip placement=\"bottomLeft\" title={v.value}>\n                {v.value}\n              </Tooltip>\n            ) : (\n              v.value\n            )}\n          </Select.Option>\n        ))}\n      </Select>\n    </div>\n  );\n});\n\n// Masternode 选择\nexport const Masternode: React.FC<Props> = forwardRef((props, ref) => {\n  const [options, setOption] = React.useState([]);\n  const [type, setType] = React.useState(\"\");\n  const [form] = Form.useForm();\n\n  React.useEffect(() => {}, []);\n\n  const specificationsNode = [{ value: \"datanode\" }, { value: \"clientnode\" }];\n\n  const onSubmit = (fields: any[], fn: any) => {\n    form!\n      .validateFields()\n      .then((values) => {\n        if (fields.length <= 1) {\n          fn();\n        }\n      })\n      .catch((err) => {});\n  };\n\n  const nodeNumberValidator = (rule, value) => {\n    if (!new RegExp(regNonnegativeNumber).test(value) || value <= 1) {\n      return Promise.reject();\n    }\n    return Promise.resolve();\n  };\n\n  const childNodeNumberValidator = (rule, value) => {\n    if (!new RegExp(regOddNumber).test(value) || value < 1) {\n      return Promise.reject();\n    }\n    return Promise.resolve();\n  };\n\n  const specValidator = (rule, value) => {\n    const { nodeList } = props;\n    if (value === \"datanode\") {\n      setOption(nodeList.datanode);\n    } else if (value === \"clientnode\") {\n      setOption(nodeList.clientnode);\n    } else {\n      setOption([]);\n    }\n    setType(value);\n    return Promise.resolve();\n  };\n\n  const onValuesChange = (changedValues, allValues) => {\n    const { onChange } = props;\n    onChange && onChange(allValues);\n  };\n\n  const { nodeList } = props;\n\n  // Form不能含Form TODO:\n\n  return (\n    <>\n      <Form layout=\"inline\" form={form} name=\"control-hooks3\" onValuesChange={onValuesChange}>\n        {/* <Form.Item\n          key=\"masterSpec\"\n          name=\"masterSpec\"\n          rules={[{ required: true, message: \"请选择节点规格\" }]}\n        >\n          <Select\n            placeholder=\"请选择节点规格\"\n            style={{ width: 300, marginRight: 8 }}\n          >\n            {nodeList.masternode?.map((v) => (\n              <Select.Option value={v.value} key={v.value}>\n                {(v.value + \"\")?.length > 35 ? (\n                  <Tooltip placement=\"bottomLeft\" title={v.value}>\n                    {v.value}\n                  </Tooltip>\n                ) : (\n                  v.value\n                )}\n              </Select.Option>\n            ))}\n          </Select>\n        </Form.Item> */}\n        <Form.Item\n          key=\"masterNodeNu\"\n          name=\"masterNodeNu\"\n          rules={[\n            {\n              required: true,\n              message: \"节点个数必须大于等于1，且必须为奇数。\",\n              validator: childNodeNumberValidator,\n            },\n          ]}\n        >\n          <InputNumber style={{ width: 250, marginTop: 10 }} placeholder=\"请输入节点个数\"></InputNumber>\n        </Form.Item>\n        <Form.List name=\"nodeList\">\n          {(fields, { add, remove }) => (\n            <>\n              {fields.map((field) => (\n                <Space\n                  key={field.key}\n                  align=\"baseline\"\n                  style={{\n                    display: \"flex\",\n                    alignItems: \"center\",\n                    paddingTop: 10,\n                  }}\n                >\n                  <Form.Item\n                    noStyle\n                    shouldUpdate={(prevValues, curValues) => prevValues.area !== curValues.area || prevValues.sights !== curValues.sights}\n                  >\n                    <Form.Item\n                      {...field}\n                      name={[field.name, \"node\"]}\n                      fieldKey={[field.fieldKey, \"node\"]}\n                      rules={[\n                        {\n                          required: true,\n                          message: \"请选择节点类型\",\n                          validator: specValidator,\n                        },\n                      ]}\n                    >\n                      <Select showSearch filterOption={filterOption} style={{ width: 138 }} placeholder=\"请选择节点类型\">\n                        {specificationsNode.map((v) => (\n                          <Select.Option value={v.value} key={v.value} disabled={field.name === 1 && type === v.value}>\n                            {(v.value + \"\")?.length > 35 ? (\n                              <Tooltip placement=\"bottomLeft\" title={v.value}>\n                                {v.value}\n                              </Tooltip>\n                            ) : (\n                              v.value\n                            )}\n                          </Select.Option>\n                        ))}\n                      </Select>\n                    </Form.Item>\n                  </Form.Item>\n\n                  {/* <Form.Item\n                    {...field}\n                    name={[field.name, \"spec\"]}\n                    fieldKey={[field.fieldKey, \"spec\"]}\n                    rules={[{ required: true, message: \"请选择节点规格\" }]}\n                  >\n                    <Select style={{ width: 138 }} placeholder=\"请选择节点规格\">\n                      {options.map((v) => (\n                        <Select.Option value={v.value} key={v.value}>\n                          {(v.value + \"\")?.length > 35 ? (\n                            <Tooltip placement=\"bottomLeft\" title={v.value}>\n                              {v.value}\n                            </Tooltip>\n                          ) : (\n                            v.value\n                          )}\n                        </Select.Option>\n                      ))}\n                    </Select>\n                  </Form.Item> */}\n\n                  <Form.Item\n                    {...field}\n                    name={[field.name, \"nodeNu\"]}\n                    fieldKey={[field.fieldKey, \"nodeNu\"]}\n                    rules={[\n                      {\n                        required: true,\n                        message: \"节点个数必须大于等于1。\",\n                        validator: nodeNumberValidator,\n                      },\n                    ]}\n                  >\n                    <InputNumber style={{ width: 250 }} placeholder=\"请输入节点个数\"></InputNumber>\n                  </Form.Item>\n\n                  <MinusCircleOutlined onClick={() => remove(field.name)} />\n                </Space>\n              ))}\n              <Form.Item>\n                <Button\n                  style={{ width: 122, height: 30, margin: \"10px 0 0 10px\" }}\n                  type=\"primary\"\n                  onClick={() => onSubmit(fields, add)}\n                  block\n                  icon={<PlusOutlined />}\n                  disabled={fields.length > 1}\n                >\n                  添加节点类型\n                </Button>\n              </Form.Item>\n            </>\n          )}\n        </Form.List>\n      </Form>\n    </>\n  );\n});\n\n// 升序、降序\nexport const OrderNode = (props: Props) => {\n  const [dataSource, setDataSource] = React.useState([] as IOpClusterRoles[]);\n\n  const handleOrder = (index1, index2) => {\n    setDataSource(swapArr(index1, index2));\n    props?.onChange(swapArr(index1, index2));\n  };\n\n  React.useEffect(() => {\n    if (!props.id) return;\n    getPhysicClusterRoles(props.id).then((data: IOpClusterRoles[]) => {\n      data =\n        data.map((ele, index) => {\n          return {\n            ...ele,\n            label: ele.roleClusterName,\n            value: ele.roleClusterName,\n            key: index,\n          };\n        }) || [];\n      setDataSource(data);\n      props?.onChange(data);\n    });\n  }, []);\n\n  const swapArr = (index1, index2) => {\n    /*数组两个元素位置互换*/\n    const array = [...dataSource];\n    array.splice(index2, 1, ...array.splice(index1, 1, array[index2]));\n    return array;\n  };\n\n  const columns = [\n    {\n      title: \"排序\",\n      dataIndex: \"id\",\n      key: \"id\",\n      width: \"20%\",\n    },\n    {\n      title: \"节点名称\",\n      dataIndex: \"roleClusterName\",\n      key: \"roleClusterName\",\n      width: \"60%\",\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      key: \"operation\",\n      render: (id: number, record, index) => {\n        const ascendingOrder = (\n          <a onClick={() => handleOrder(index, index - 1)}>\n            <ArrowUpOutlined />\n            升序\n          </a>\n        );\n        const descendingOrder = (\n          <a onClick={() => handleOrder(index, index + 1)}>\n            <ArrowDownOutlined />\n            降序\n          </a>\n        );\n        const allOrder = (\n          <div className=\"operation-box\">\n            <a onClick={() => handleOrder(index, index - 1)}>\n              <ArrowUpOutlined />\n              升序\n            </a>{\" \"}\n            <span className=\"line-between\"></span>{\" \"}\n            <a onClick={() => handleOrder(index, index + 1)}>\n              <ArrowDownOutlined />\n              降序\n            </a>\n          </div>\n        );\n        let operation: any = \"-\";\n        if (dataSource?.length <= 1) {\n          return <>{operation}</>;\n        }\n        if (index === 0) {\n          operation = descendingOrder;\n        } else if (index === dataSource.length - 1) {\n          operation = ascendingOrder;\n        } else {\n          operation = allOrder;\n        }\n        return <>{operation}</>;\n      },\n    },\n  ];\n\n  return <Table dataSource={dataSource} columns={columns} rowKey={\"id\"} pagination={false} scroll={{ y: 150 }} />;\n};\n\n// 扩缩容节点列表\nexport const ExpandShrinkNodeList = (props: Props) => {\n  const onChange = (e) => {\n    props.onChange(e.target.value);\n  };\n\n  const hostList = props.host?.split(\"\\n\") || [];\n  return (\n    <>\n      {hostList.map((item) => {\n        return item ? (\n          <>\n            <span>{item}</span>\n            <br />\n          </>\n        ) : null;\n      })}\n      {!props.isHidden ? <TextArea allowClear rows={4} onChange={onChange} placeholder={\"请输入主机列表，多个主机换行\"} /> : \"\"}\n    </>\n  );\n};\n\nexport const DockerExpectDataNodeNu = (props) => {\n  const [InputValue, setValue] = React.useState(0);\n  const [isExpect, setIsExpect] = React.useState(true);\n\n  React.useEffect(() => {\n    setValue(props.value);\n  }, []);\n\n  const onChange = (value) => {\n    setValue(value);\n    setIsExpect(props.value - value <= 0);\n    const { onChange } = props;\n    onChange && onChange(value);\n  };\n\n  const { style } = props;\n\n  return (\n    <>\n      <InputNumber style={style} value={InputValue} onChange={onChange} />\n      <span style={{ paddingLeft: 10 }}>{`${isExpect ? \"增加\" : \"减少\"} ${Math.abs(props.podNumber - InputValue)}节点，${\n        isExpect ? \"扩容\" : \"缩容\"\n      }至 ${InputValue}`}</span>\n    </>\n  );\n};\n\n// 扩缩容节点列表\nexport const ExpandShrinkList = (props: any) => {\n  const { data, type, isExpand, options, onShrink, onExpand, form } = props;\n  const [dataSource, setDataSource] = useState([]);\n  const [shrinkNode, setShrinkNode] = useState([]);\n  const [expandNode, setExpandNode] = useState({});\n  const [orginData, setOrginData] = useState([]);\n\n  useEffect(() => {\n    getDataSource();\n    setShrinkNode([]);\n  }, [isExpand]);\n\n  useEffect(() => {\n    shrinkNode.length && onShrink(shrinkNode);\n  }, [shrinkNode]);\n\n  useEffect(() => {\n    typeof onExpand === \"function\" && onExpand(expandNode);\n  }, [expandNode]);\n\n  const getDataSource = () => {\n    let list = (data || []).filter((item) => item?.role === type);\n    let esClusterRoleHostVO = list[0]?.esClusterRoleHostVO;\n    if (isExpand && type !== \"masternode\") {\n      esClusterRoleHostVO = [...(esClusterRoleHostVO || []), addData()];\n    }\n    setOrginData(esClusterRoleHostVO);\n    setDataSource(esClusterRoleHostVO);\n  };\n\n  const addData = () => {\n    let id = uuid();\n    let node = { id, role: type, hostname: \"\", machineSpec: \"\" };\n    setExpandNode(node);\n    return {\n      ip: (\n        <Form.Item\n          className=\"expand-shrink-ip\"\n          name={`ip&${type}&${id}`}\n          key={`ip&${type}&${id}`}\n          rules={[\n            {\n              validator: (rule: any, value: string) => {\n                if (!value) return Promise.resolve();\n                if (!new RegExp(regIp).test(value)) {\n                  return Promise.reject(\"请正确输入IP，例如：127.1.1.1\");\n                }\n                for (let i = 0; i < dataSource?.length; i++) {\n                  if (dataSource[i]?.ip === value) {\n                    return Promise.reject(\"IP不能重复\");\n                  }\n                }\n                return Promise.resolve();\n              },\n            },\n          ]}\n        >\n          <Input\n            placeholder=\"请输入\"\n            onChange={(e) => {\n              let val = e.target.value;\n            }}\n          ></Input>\n        </Form.Item>\n      ),\n      machineSpec: (\n        <Form.Item\n          className=\"expand-shrink-machine\"\n          name={`machineSpec&${type}&${id}`}\n          key={`machineSpec&${type}&${id}`}\n          rules={[\n            {\n              validator: (rule: any, value: string) => {\n                return Promise.resolve();\n              },\n            },\n          ]}\n        >\n          <Select placeholder=\"请选择\" options={options}></Select>\n        </Form.Item>\n      ),\n      type: \"expand\",\n      id,\n    };\n  };\n\n  const columns = [\n    {\n      title: \"IP\",\n      dataIndex: \"ip\",\n      key: \"ip\",\n      width: 300,\n    },\n    {\n      title: \"机型\",\n      dataIndex: \"machineSpec\",\n      key: \"machineSpec\",\n      width: 200,\n    },\n    {\n      title: \"操作\",\n      key: \"action\",\n      width: 100,\n      render: (_, record) => {\n        if (type === \"masternode\") return;\n        if (!isExpand)\n          return (\n            <svg\n              onClick={() => {\n                let data = dataSource.filter((item) => item?.id !== record?.id);\n                setDataSource(data);\n                setShrinkNode([...shrinkNode, record]);\n              }}\n              className=\"icon svg-icon delete-row\"\n              aria-hidden=\"true\"\n            >\n              <use xlinkHref=\"#iconjianshao\"></use>\n            </svg>\n          );\n        return record?.type === \"expand\" ? (\n          <div>\n            <svg\n              onClick={() => {\n                let data = [...dataSource, addData()];\n                setDataSource(data);\n              }}\n              className=\"icon svg-icon add-row\"\n              aria-hidden=\"true\"\n            >\n              <use xlinkHref=\"#iconzengjia\"></use>\n            </svg>\n            {dataSource.length === orginData.length ? null : (\n              <svg\n                onClick={() => {\n                  let data = dataSource.filter((item) => item?.id !== record?.id);\n                  setDataSource(data);\n                }}\n                className=\"icon svg-icon delete-row\"\n                aria-hidden=\"true\"\n              >\n                <use xlinkHref=\"#iconjianshao\"></use>\n              </svg>\n            )}\n          </div>\n        ) : null;\n      },\n    },\n  ];\n  return (\n    <>\n      <Table columns={columns} dataSource={dataSource} rowKey=\"id\" pagination={false}></Table>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/custom-form/cost.tsx",
    "content": "import React from \"react\";\nimport { InputNumber } from \"antd\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\n\nconst mapDispatchToProps = (dispatch) => ({\n  setClusterCost: (n: number) => dispatch(actions.setClusterCost(n)),\n});\n// 成本计算\nconst ExpectInput: React.FC<any> = (props) => {\n  const [InputValue, setValue] = React.useState(0);\n  const [isExpect, setIsExpect] = React.useState(true);\n\n  React.useEffect(() => {\n    setValue(props.podNumber || 0);\n  }, []);\n\n  const onChange = (value) => {\n    value = Number(value);\n    if (!value || isNaN(value) || value < 0) {\n      value = 0;\n    }\n    setValue(value);\n    setIsExpect(props.podNumber - value <= 0);\n    const { onChange } = props;\n    onChange && onChange(value);\n    // 判断是否是正整数\n    if (!regNonnegativeInteger.test(value) || value <= 1) {\n      return false;\n    }\n  };\n\n  return (\n    <>\n      <InputNumber min={props.min} value={InputValue} onInput={onChange} onStep={onChange} />\n      <span style={{ paddingLeft: 10 }}>\n        {`${isExpect ? \"增加\" : \"减少\"}${Math.abs(props.podNumber - InputValue)}节点，集群${\n          isExpect ? \"扩容\" : \"缩容\"\n        }至${InputValue}个节点`}\n      </span>\n    </>\n  );\n};\nexport const ExpectDataNodeNu = connect(null, mapDispatchToProps)(ExpectInput);\n\nconst mapStateToProps = (state: any) => ({\n  cost: state.clusterBase.cost,\n});\n// 成本展示\nconst ShowCostComponent: React.FC<any> = (props: any) => {\n  return <span>{props.cost}</span>;\n};\nexport const ShowCost = connect(mapStateToProps)(ShowCostComponent);\n"
  },
  {
    "path": "arius-console/src/container/custom-form/index.less",
    "content": ".add-role-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding-bottom: 10px;\n  font-weight: 500;\n  margin-top: 10px;\n}\n\n.add-role-table-header {\n  padding-bottom: 10px;\n  .role-table-text {\n    padding-bottom: 5px;\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n  }\n}\n.master-item {\n  margin-top: 10px;\n}\n.operation-box {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n}\n\n.line-between {\n  width: 1px;\n  height: 12px;\n  display: block;\n  background: #e8e8e8;\n}\n\n.region-transfer {\n  height: 323px;\n  .ant-transfer-list-body-customize-wrapper {\n    overflow: auto;\n  }\n  .ant-transfer-list {\n    width: 310px;\n  }\n  .region-transfer-table {\n    width: 496px;\n    height: 323px;\n    .ant-spin-nested-loading,\n    .ant-spin-container,\n    .ant-table-empty {\n      height: 100%;\n\n      .ant-table-container,\n      .ant-table-content,\n      table {\n        height: 100%;\n      }\n    }\n  }\n}\n\n.attribute-content {\n  .tag-blue {\n    padding: 0 2px;\n    background: rgba(42, 143, 255, 0.06);\n    border: 0.5px solid #2a8fff;\n    border-radius: 1px;\n    margin-left: 2px;\n    font-family: PingFangSC-Medium;\n    font-size: 10px;\n    color: #2a8fff;\n    line-height: 15px;\n    cursor: default;\n  }\n\n  .tag-num {\n    font-family: PingFangSC-Medium;\n    text-align: right;\n    line-height: 13px;\n    margin-left: 6px;\n    transform: scale(0.8333);\n  }\n}\n\n.attribute-tag {\n  .ant-popover-inner-content {\n    padding: 12px;\n    max-width: 480px;\n  }\n\n  .ant-popover-arrow {\n    display: none;\n  }\n\n  .ant-popover-placement-bottom,\n  .ant-popover-placement-bottomLeft,\n  .ant-popover-placement-bottomRight {\n    top: 23px !important;\n    border-radius: 2px;\n  }\n\n  .tag-blue {\n    font-family: PingFangSC-Regular;\n    color: #2f81f9;\n    border: 1px solid #eaeef5;\n    height: 24px;\n    line-height: 24px;\n    padding: 0 4px;\n    margin: 3px;\n    height: 24px;\n    background: #f8fafd;\n  }\n}\n\n.add-role-content {\n  .ant-form-item,\n  .add-role {\n    margin-bottom: 0;\n  }\n}\n\n.datanode-select {\n  display: flex;\n}\n\n.add-role-button {\n  margin-top: 10px;\n  .add-node,\n  .delete-node {\n    border: 1px solid #2f81f9;\n    border-radius: 4px;\n    height: 30px;\n    padding: 0 10px;\n  }\n  .delete-node {\n    margin-bottom: 10px;\n  }\n}\n\n.add-row,\n.delete-row {\n  font-size: 30px;\n}\n\n.add-row {\n  margin-right: 5px;\n}\n\n.expand-shrink-ip,\n.expand-shrink-machine {\n  margin-bottom: 0;\n}\n\n.relevance-region {\n  .select-cluster {\n    width: 300px;\n    margin-right: 16px;\n  }\n  .select-region {\n    width: 300px;\n  }\n  .ant-form-inline .ant-form-item-with-help {\n    margin-bottom: 0px;\n  }\n  .ant-form-item {\n    margin-right: 0;\n  }\n  .nodelist {\n    width: 100%;\n    margin-top: 16px;\n  }\n}\n\n.dcloud-drawer .dcloud-drawer-body {\n  .ant-form-item.no-margin-bottom {\n    margin-bottom: 0 !important;\n    width: 50%;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/custom-form/index.ts",
    "content": "export * from \"./base\";\nexport * from \"./relevance-region\";\nexport * from \"./cost\";\n"
  },
  {
    "path": "arius-console/src/container/custom-form/logic-cluser-select.tsx",
    "content": "import { getClusterLogicNames } from \"api/cluster-api\";\nimport { Form, Select, Spin } from \"antd\";\nimport { RESOURCE_TYPE_LIST } from \"constants/common\";\nimport { filterOption } from \"lib/utils\";\nimport React from \"react\";\nimport \"./index.less\";\n\nexport const LogicCluserSelect: React.FC<any> = (props: {\n  value: any;\n  isModifyPage: boolean;\n  $form: any;\n  onChange?: (result: any) => any;\n}) => {\n  const { value } = props;\n  const [logicClusterList, setLogicClusterList] = React.useState([]);\n  const [clusterType, setType] = React.useState(value?.clusterType || null);\n  const [cluster, setCluster] = React.useState(value?.cluster || null);\n  const [fetching, setFetching] = React.useState(false);\n\n  React.useEffect(() => {\n    if (clusterType) {\n      setFetching(true);\n      getClusterLogicNames(clusterType)\n        .then((res) => {\n          if (res) {\n            res = res.map((item) => {\n              return {\n                label: item.name,\n                value: item.id,\n                type: item.type,\n                level: item.level,\n                dataCenter: item.dataCenter,\n              };\n            });\n            setLogicClusterList(res);\n          }\n        })\n        .finally(() => {\n          setFetching(false);\n        });\n    }\n  }, [clusterType]);\n\n  const onSubmit = (valus: any, type: string) => {\n    const obj = {\n      cluster,\n      clusterType,\n      clusterName: \"\",\n      level: null,\n      dataCenter: null,\n    };\n    if (type === \"type\") {\n      obj.clusterType = valus;\n      setType(valus);\n      if (cluster) {\n        setCluster(null);\n        obj.cluster = null;\n        props.$form?.current.setFieldsValue({ clusterName: null });\n      }\n    }\n    if (type === \"name\") {\n      const clusterInfo = logicClusterList.filter((item) => item.value === valus);\n      obj.cluster = valus;\n      obj.clusterName = clusterInfo[0]?.label;\n      obj.level = clusterInfo[0]?.level;\n      obj.dataCenter = clusterInfo[0]?.dataCenter;\n      setCluster(valus);\n    }\n    const { onChange } = props;\n    onChange && onChange(obj);\n  };\n\n  return (\n    <div style={{ display: \"flex\" }}>\n      <Form.Item\n        name=\"type\"\n        initialValue={clusterType}\n        rules={[{ required: false }]}\n        className=\"no-margin-bottom\"\n        style={{ paddingRight: 20 }}\n      >\n        <Select\n          showSearch\n          disabled={props.isModifyPage}\n          placeholder=\"请选择集群类型\"\n          options={RESOURCE_TYPE_LIST}\n          onChange={(e) => onSubmit(e, \"type\")}\n          filterOption={filterOption}\n        />\n      </Form.Item>\n      <Form.Item name=\"clusterName\" initialValue={cluster} rules={[{ required: false }]} className=\"no-margin-bottom\">\n        <Select\n          showSearch\n          placeholder=\"请选择集群\"\n          disabled={props.isModifyPage}\n          options={logicClusterList.map((item) => ({ label: item.label, value: item.value }))}\n          onChange={(e) => onSubmit(e, \"name\")}\n          notFoundContent={fetching ? <Spin size=\"small\" /> : null}\n          filterOption={filterOption}\n        />\n      </Form.Item>\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/custom-form/region-transfer.tsx",
    "content": "import { Table, Transfer, Tag, Popover, Tooltip } from \"antd\";\nimport difference from \"lodash/difference\";\nimport React, { useEffect, useState } from \"react\";\nimport { renderAttributes } from \"../../container/custom-component\";\nimport \"./index.less\";\n\ninterface IRegionTransferProps {\n  targetKeys?: number[];\n  dataSource: any[];\n  selectKeys: (keys: number[]) => void;\n  listStyle?: object;\n  style?: object;\n  isExpand?: boolean;\n}\n\nconst TableTransfer = ({ leftColumns, rightColumns, isExpand, ...restProps }) => (\n  <Transfer {...restProps}>\n    {({ direction, filteredItems, onItemSelectAll, onItemSelect, selectedKeys: listSelectedKeys }) => {\n      const columns = direction === \"left\" ? leftColumns : rightColumns;\n      const rowSelection = {\n        onSelectAll(selected, selectedRows) {\n          const treeSelectedKeys = selectedRows.filter((item) => !item.disabled).map(({ key }) => key);\n          const diffKeys = selected ? difference(treeSelectedKeys, listSelectedKeys) : difference(listSelectedKeys, treeSelectedKeys);\n          onItemSelectAll(diffKeys, selected);\n        },\n        onSelect({ key }, selected) {\n          onItemSelect(key, selected);\n        },\n        selectedRowKeys: listSelectedKeys,\n        renderCell(checked, record, index, node) {\n          if (record?.disabled) {\n            return <Tooltip title={`${isExpand ? \"扩容\" : \"缩容\"}工单，不允许${isExpand ? \"缩容\" : \"扩容\"}节点`}>{node}</Tooltip>;\n          }\n          return node;\n        },\n        getCheckboxProps: (item) => ({\n          disabled: item.disabled,\n        }),\n      };\n\n      return (\n        <Table\n          className=\"region-transfer-table\"\n          rowSelection={rowSelection}\n          columns={columns}\n          dataSource={filteredItems}\n          size=\"small\"\n          pagination={false}\n          onRow={({ key, disabled: itemDisabled }) => ({\n            onClick: () => {\n              if (itemDisabled) return;\n              onItemSelect(key, !listSelectedKeys.includes(key));\n            },\n          })}\n        />\n      );\n    }}\n  </Transfer>\n);\n\nconst tableColumns = [\n  {\n    dataIndex: \"nodeSet\",\n    title: \"节点名称\",\n    width: 90,\n    ellipsis: true,\n    render: (val: string) => {\n      return (\n        <Tooltip title={val} placement=\"topLeft\">\n          <span>{val}</span>\n        </Tooltip>\n      );\n    },\n  },\n  {\n    dataIndex: \"ip\",\n    title: \"ip\",\n    width: 120,\n  },\n  {\n    dataIndex: \"attributes\",\n    title: \"attribute\",\n    render: (val: string) => {\n      if (!val) return \"-\";\n      let attrArray = val.split(\",\");\n      let limit = 1;\n      if (attrArray?.length === 2 && attrArray[0]?.length + attrArray[1]?.length <= 35) {\n        limit = 2;\n      } else if (attrArray?.length === 3 && attrArray[0]?.length + attrArray[1]?.length + attrArray[2]?.length <= 35) {\n        limit = 3;\n      }\n      return renderAttributes({ data: val, limit });\n    },\n  },\n];\n\nconst RegionTransfer = (props: IRegionTransferProps) => {\n  const [targetKeys, setTargetKeys] = useState(props?.targetKeys || []);\n\n  const { dataSource, selectKeys, isExpand } = props;\n\n  const onChange = (targetKeys: []) => {\n    setTargetKeys(targetKeys);\n    selectKeys(targetKeys);\n  };\n\n  useEffect(() => {\n    setTargetKeys(props?.targetKeys || []);\n  }, [dataSource]);\n\n  //解决父组件挂在完成之前props?.targetKeys为空值\n  useEffect(() => {\n    setTargetKeys(props?.targetKeys);\n  }, [props?.targetKeys]);\n\n  return (\n    <>\n      <TableTransfer\n        listStyle={props.listStyle || {}}\n        className=\"region-transfer\"\n        dataSource={dataSource}\n        targetKeys={targetKeys}\n        showSearch={true}\n        onChange={onChange}\n        filterOption={(inputValue: string, item: any) => {\n          let nodeSet = item.nodeSet.indexOf(inputValue) !== -1;\n          let ipPort = item.ip.indexOf(inputValue) !== -1;\n          let attributes = item.attributes.indexOf(inputValue) !== -1;\n          return nodeSet || ipPort || attributes;\n        }}\n        leftColumns={tableColumns}\n        rightColumns={tableColumns}\n        style={props?.style}\n        isExpand={isExpand}\n      />\n    </>\n  );\n};\n\nexport default RegionTransfer;\n"
  },
  {
    "path": "arius-console/src/container/custom-form/relevance-region.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Form, Select, Table } from \"antd\";\nimport { getPhyClusterRegionList, logicClusterNodesList } from \"api/op-cluster-region-api\";\nimport { filterOption } from \"lib/utils\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state: any) => ({\n  clusterList: state.region.phyClusterList,\n  type: state.region.type,\n});\n\n// 永不重名的key\nlet count = 0;\n\nexport const RelevanceRegion: React.FC<any> = connect(mapStateToProps)(\n  (props: { dataInfo: any; onChange?: (result: any) => any; type: string; clusterList: { value: string; label: string }[] }) => {\n    const { dataInfo } = props;\n    const [tableData, setTableData] = useState([]);\n    const [regionList, setRegionList] = useState([]);\n    const [regionId, setRegionId] = useState(null);\n    const [nodeList, setNodeList] = useState([]);\n\n    const [form] = Form.useForm();\n\n    const onFormChange = (changedValues, allValues) => {\n      if (changedValues.name) {\n        //name变化时候清空regionlist，清空region值\n        setRegionList([]);\n        setRegionId(null);\n        form.setFieldsValue({ region: undefined });\n        //name表单变化时候调用接口\n        getPhyClusterRegionList(changedValues.name, props.type, { hostNum: dataInfo.dataNodeNu, machineSpec: dataInfo?.dataNodeSpec }).then(\n          (res) => {\n            let resArray = [];\n            res.forEach((item) => {\n              let cold = false;\n              if (item?.config) {\n                let config = JSON.parse(item?.config);\n                cold = config?.cold;\n              }\n              if (!cold) {\n                resArray.push({\n                  label: `${item.name}`,\n                  value: JSON.stringify({\n                    config: item.config,\n                    logicClusterIds: item.logicClusterIds,\n                    phyClusterName: item.clusterName,\n                    id: item.id,\n                    name: item.name,\n                  }),\n                });\n              }\n            });\n            setRegionList([...resArray]);\n          }\n        );\n      }\n\n      //处理表单数据并通过onchange将数据透传给父组件表单\n      if (!allValues.name || !allValues.region) return;\n      if (Array.isArray(allValues.region)) {\n        allValues.regionObject = allValues.region?.map((item) => JSON.parse(item));\n      } else if (allValues.region.constructor === String) {\n        const transObj = JSON.parse(allValues.region);\n        allValues.regionObject = [{ ...transObj }];\n      }\n      let dataSource = [...tableData];\n      allValues.regionObject.forEach((element) => {\n        allValues.racks = element.racks;\n        allValues.regionId = element.id;\n        element.phyClusterName = allValues.name;\n        dataSource.push({ key: count++, ...{ ...allValues, region: [JSON.stringify(element)] } });\n      });\n      const { onChange } = props;\n      onChange && onChange(dataSource);\n    };\n\n    return (\n      <>\n        <Form className=\"relevance-region\" layout=\"inline\" form={form} name=\"control-hooks1\" onValuesChange={onFormChange}>\n          <Form.Item name=\"name\" rules={[{ required: true, message: \"请选择物理集群\" }]}>\n            <Select\n              showSearch\n              className=\"select-cluster\"\n              placeholder=\"请选择物理集群\"\n              options={props.clusterList}\n              disabled={tableData && tableData.length ? true : false}\n              filterOption={filterOption}\n            />\n          </Form.Item>\n          <Form.Item name=\"region\" rules={[{ required: true, message: \"请选择region\" }]}>\n            <Select\n              showSearch\n              className=\"select-region\"\n              filterOption={filterOption}\n              placeholder=\"请选择region\"\n              options={regionList}\n              onSelect={async (val: string) => {\n                let id = JSON.parse(val)?.id;\n                let data = await logicClusterNodesList(id);\n                setRegionId(id);\n                setNodeList(data);\n              }}\n            ></Select>\n          </Form.Item>\n          {regionId && (\n            <Form.Item className=\"nodelist\">\n              <Table\n                rowKey=\"id\"\n                columns={[\n                  {\n                    title: \"主机IP\",\n                    dataIndex: \"ip\",\n                  },\n                  {\n                    title: \"节点规格\",\n                    dataIndex: \"machineSpec\",\n                  },\n                ]}\n                dataSource={nodeList}\n                pagination={false}\n              ></Table>\n            </Form.Item>\n          )}\n        </Form>\n      </>\n    );\n  }\n);\n"
  },
  {
    "path": "arius-console/src/container/custom-form/step-select.tsx",
    "content": "import * as React from 'react';\nimport { Select, Tooltip } from 'antd';\nimport { connect } from \"react-redux\";\nimport * as actions from 'actions';\n\n\nconst mapStateToProps = (state) => ({\n  phyClusterConfig: state.configInfo,\n});\nconst connects: Function = connect\n\n@connects(mapStateToProps)\nexport class StepSelect extends React.Component<any> {\n\n  public render() {\n    const  { disabled, value, phyClusterConfig } = this.props;\n\n    return (\n      <>\n        <Select\n            placeholder=\"请依次点击节点角色，设置操作的执行顺序。\"\n            showSearch={true}\n            disabled={disabled}\n            value={value}\n            mode=\"multiple\"\n            onChange={(e: any) => this.handleChange(e)}\n        >\n            { phyClusterConfig?.clusterRolesList.map((v, index) => (\n              <Select.Option\n                key={v.value || v.key || index}\n                value={v.value}\n              >\n                {(v.label?.length > 35 || (v.value + '')?.length > 35) ? <Tooltip placement=\"bottomLeft\" title={v.label || v.value}>\n                  {v.label || v.value}\n                </Tooltip> : (v.label || v.value)}\n              </Select.Option>\n            ))}\n        </Select>\n      </>\n    );\n  }\n\n  public setSeptPhysicClusterRoles(data: string[]) {\n    const arr = this.props.phyClusterConfig.clusterRolesList.map(item => {\n        item.label = item.value;\n        return item;\n    });\n    const arrStr =  arr.map(item => {\n      return item.value;\n    });\n    let num = null;\n    data.forEach((item, index) => {\n      num = arrStr.indexOf(item);\n      if (num !== -1) {\n        arr[num].label = arr[num].label + ' ' + `(步骤${index + 1})`;\n      }\n    });\n    this.props.dispatch(actions.setPhyClusterConfigRoles(arr));\n  }\n\n  public handleChange(params: any) {\n    const { onChange } = this.props;\n    this.setSeptPhysicClusterRoles(params);\n    // tslint:disable-next-line:no-unused-expression\n    onChange && onChange(params);\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/custom-form/tpl-table-add-row/TableFormAddRow.tsx",
    "content": "import React from \"react\";\nimport { Row, Col } from \"antd\";\nimport EditTable from \"./editTable\";\nimport \"./index.less\";\nimport { cloneDeep } from \"lodash\";\n\nconst basicClass = \"tpl-table-form\";\n\ninterface ITableFormAddRowProps {\n  type: string;\n  onChange?: (result: string[]) => any;\n  value?: any;\n  machineList?: [];\n}\n\nexport interface IState {\n  dataSource: any[];\n  type: string;\n}\n\nexport const XFormContext = React.createContext({});\n\nexport const TableFormAddRow = (props: ITableFormAddRowProps) => {\n  const reducer = (state: any, action: any) => {\n    state = cloneDeep(state);\n    const { dataSource } = state;\n    switch (action.key) {\n      case \"rowData\": // 给表格添加一行数据\n        dataSource.push(action.data || {});\n        break;\n      case \"deleteRow\": // 删除一行数据\n        dataSource?.splice(action.data.index, 1);\n        break;\n      default:\n        break;\n    }\n    return state;\n  };\n\n  const [state, dispatch] = React.useReducer(reducer, {\n    dataSource: [{}],\n    type: props.type,\n  } as IState);\n\n  React.useEffect(() => {\n    const { onChange } = props;\n    onChange && onChange(state.dataSource);\n  }, [state.dataSource]);\n\n  return (\n    <XFormContext.Provider value={{ state, dispatch }}>\n      <div className={basicClass}>\n        <Row>\n          <Col span={24}>\n            <EditTable machineList={props.machineList} />\n          </Col>\n        </Row>\n      </div>\n    </XFormContext.Provider>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/custom-form/tpl-table-add-row/editTable.tsx",
    "content": "import React, { useState } from \"react\";\nimport Table from \"antd/lib/table\";\nimport \"./index.less\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { cloneDeep } from \"lodash\";\nimport { Form } from \"antd\";\nimport { FormItemType, IFormItem, renderFormItem } from \"component/x-form\";\nimport { IState, XFormContext } from \"./TableFormAddRow\";\nimport { regIp } from \"constants/reg\";\n\nconst basicClass = \"tpl-table-form-edittable\";\n\nconst cpuOptions = [\n  {\n    value: \"4核\",\n  },\n  {\n    value: \"8核\",\n  },\n  {\n    value: \"16核\",\n  },\n  {\n    value: \"24核\",\n  },\n];\n\nconst memoryOptions = [\n  {\n    value: \"16G\",\n  },\n  {\n    value: \"32G\",\n  },\n  {\n    value: \"64G\",\n  },\n];\n\nconst diskTypeOptions = [\n  {\n    value: \"S2D\",\n  },\n  {\n    value: \"VHD\",\n  },\n];\n\nconst diskSizeOptions = [\n  {\n    value: \"512g\",\n  },\n  {\n    value: \"768g\",\n  },\n  {\n    value: \"1024g\",\n  },\n  {\n    value: \"1536g\",\n  },\n  {\n    value: \"2048g\",\n  },\n  {\n    value: \"2560g\",\n  },\n  {\n    value: \"3072g\",\n  },\n];\n\nexport const addRoleformMap: IFormItem[] = [\n  {\n    key: \"host\",\n    label: \"IP: 端口号\",\n    type: FormItemType.input,\n    rules: [\n      {\n        required: true,\n        validator: (rule: any, value: string) => {\n          if ((rule.field.indexOf(\"datanode\") !== -1 || rule.field.indexOf(\"clientnode\") !== -1) && !value) {\n            return Promise.resolve();\n          }\n          if (!value) {\n            return Promise.reject(\"请输入IP:端口号，例如：127.1.1.1:8888\");\n          }\n          const allValues = (window as any).formData?.allValues || {};\n          const ipArr = [];\n          const key = rule.field;\n          Object.keys(allValues).forEach((item) => {\n            const analysisKey = key?.split(\"&\");\n            if (analysisKey.length !== 3 || item === key) return;\n            if (item.indexOf(`${analysisKey[0]}&${analysisKey[1]}`) > -1) {\n              ipArr.push(allValues[item]);\n            }\n          });\n          const isPostArr = value?.split(\":\");\n          let judgeIp = false;\n          ipArr.length &&\n            ipArr.forEach((ipPort) => {\n              const ip = ipPort?.split(\":\")[0];\n              if (ip === isPostArr[0]) {\n                judgeIp = true;\n              }\n            });\n          if (judgeIp) {\n            return Promise.reject(\"ip不能相同\");\n          }\n          if (!new RegExp(regIp).test(isPostArr[0])) {\n            return Promise.reject(\"请输入正确端ip，例：127.1.1.1:8888\");\n          }\n          if (!isPostArr[1] && isPostArr[0]) {\n            return Promise.reject(\"格式错误:号后面没有端口。\");\n          }\n          return Promise.resolve();\n        },\n      },\n    ],\n    attrs: {\n      placeholder: \"请输入\",\n    },\n  },\n  {\n    key: \"cpu\",\n    label: \"CPU核数\",\n    type: FormItemType.select,\n    rules: [\n      {\n        required: true,\n        message: \"请选择\",\n        validator: (rule: any, value: string) => {\n          if ((rule.field.indexOf(\"datanode\") !== -1 || rule.field.indexOf(\"clientnode\") !== -1) && !value) {\n            return Promise.resolve();\n          }\n          if (!value) {\n            return Promise.reject();\n          }\n          return Promise.resolve();\n        },\n      },\n    ],\n    options: cpuOptions,\n  },\n  {\n    key: \"memory\",\n    label: \"内存大小\",\n    type: FormItemType.select,\n    rules: [\n      {\n        required: true,\n        message: \"请选择\",\n        validator: (rule: any, value: string) => {\n          if ((rule.field.indexOf(\"datanode\") !== -1 || rule.field.indexOf(\"clientnode\") !== -1) && !value) {\n            return Promise.resolve();\n          }\n          if (!value) {\n            return Promise.reject();\n          }\n          return Promise.resolve();\n        },\n      },\n    ],\n    options: memoryOptions,\n  },\n  {\n    key: \"diskType\",\n    label: \"磁盘类型\",\n    type: FormItemType.select,\n    rules: [\n      {\n        required: true,\n        message: \"请选择\",\n        validator: (rule: any, value: string) => {\n          if ((rule.field.indexOf(\"datanode\") !== -1 || rule.field.indexOf(\"clientnode\") !== -1) && !value) {\n            return Promise.resolve();\n          }\n          if (!value) {\n            return Promise.reject();\n          }\n          return Promise.resolve();\n        },\n      },\n    ],\n    options: diskTypeOptions,\n  },\n  {\n    key: \"diskSize\",\n    label: \"磁盘大小\",\n    type: FormItemType.select,\n    rules: [\n      {\n        required: true,\n        message: \"请选择\",\n        validator: (rule: any, value: string) => {\n          if ((rule.field.indexOf(\"datanode\") !== -1 || rule.field.indexOf(\"clientnode\") !== -1) && !value) {\n            return Promise.resolve();\n          }\n          if (!value) {\n            return Promise.reject();\n          }\n          return Promise.resolve();\n        },\n      },\n    ],\n    options: diskSizeOptions,\n  },\n];\n\nexport const EditTable = (props) => {\n  const { state, dispatch } = React.useContext(XFormContext) as { state: IState; dispatch: any };\n  const { type } = state;\n\n  const [machineSpec, setMachineSpec] = useState(\"\");\n\n  const applyFormMap = [\n    {\n      key: \"host\",\n      label: \"IP: 端口号\",\n      type: FormItemType.input,\n      rules: [\n        {\n          required: true,\n          validator: (rule: any, value: string) => {\n            if ((rule.field.indexOf(\"datanode\") !== -1 || rule.field.indexOf(\"clientnode\") !== -1) && !value) {\n              return Promise.resolve();\n            }\n            if (!value) {\n              return Promise.reject(\"请输入IP:端口号，例如：127.1.1.1:8888\");\n            }\n            const allValues = (window as any).formData?.allValues || {};\n            const ipArr = [];\n            const key = rule.field;\n            Object.keys(allValues).forEach((item) => {\n              const analysisKey = key?.split(\"&\");\n              if (analysisKey.length !== 3 || item === key) return;\n              if (item.indexOf(`${analysisKey[0]}&${analysisKey[1]}`) > -1) {\n                ipArr.push(allValues[item]);\n              }\n            });\n            const isPostArr = value?.split(\":\");\n            let judgeIp = false;\n            ipArr.length &&\n              ipArr.forEach((ipPort) => {\n                const ip = ipPort?.split(\":\")[0];\n                if (ip === isPostArr[0]) {\n                  judgeIp = true;\n                }\n              });\n            if (judgeIp) {\n              return Promise.reject(\"ip不能相同\");\n            }\n            if (!new RegExp(regIp).test(isPostArr[0])) {\n              return Promise.reject(\"请输入IP:端口号，例如：127.1.1.1:8888\");\n            }\n            if (!isPostArr[1] && isPostArr[0]) {\n              return Promise.reject('格式错误\":\"号后面没有端口');\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n      attrs: {\n        placeholder: \"请输入\",\n      },\n    },\n    {\n      key: \"machineSpec\",\n      label: \"机型\",\n      type: FormItemType.select,\n      rules: [\n        {\n          required: true,\n          message: \"请选择\",\n          validator: (rule: any, value: string) => {\n            if ((rule.field.indexOf(\"datanode\") !== -1 || rule.field.indexOf(\"clientnode\") !== -1) && !value) {\n              return Promise.resolve();\n            }\n            if (!value) {\n              return Promise.reject();\n            }\n            setMachineSpec(value);\n            return Promise.resolve();\n          },\n        },\n      ],\n      options: props.machineList,\n    },\n  ];\n\n  const formMap = applyFormMap;\n\n  const getColumns = () => {\n    let length = state.dataSource.length;\n    return [\n      {\n        dataIndex: formMap[0].key,\n        title: formMap[0].label,\n        width: 350,\n        render: (text, record, index) => {\n          const formItem = cloneDeep(formMap[0]);\n          formItem.key = `${type}&${formItem.key}&${index}`;\n          return (\n            <div>\n              <Form.Item\n                className={`${basicClass}-table-formitem`}\n                name={formItem.key}\n                key={formItem.key}\n                rules={\n                  formItem.rules || [\n                    {\n                      required: false,\n                      message: \"\",\n                    },\n                  ]\n                }\n              >\n                {renderFormItem(formItem)}\n              </Form.Item>\n            </div>\n          );\n        },\n      },\n      {\n        dataIndex: formMap[1].key,\n        title: formMap[1].label,\n        width: 300,\n        render: (text, record, index) => {\n          const formItem = cloneDeep(formMap[1]);\n          formItem.key = `${type}&${formItem.key}&${index}`;\n          return (\n            <div>\n              <Form.Item\n                className={`${basicClass}-table-formitem`}\n                name={formItem.key}\n                key={formItem.key}\n                initialValue={state.dataSource[length - 1]?.machineSpec}\n                rules={\n                  formItem.rules || [\n                    {\n                      required: false,\n                      message: \"\",\n                    },\n                  ]\n                }\n              >\n                {renderFormItem(formItem)}\n              </Form.Item>\n            </div>\n          );\n        },\n      },\n      {\n        dataIndex: \"option\",\n        title: \"操作\",\n        width: 150,\n        render: (_, record, index: number) => {\n          return (\n            <div>\n              <svg\n                onClick={() => {\n                  dispatch({ key: \"rowData\", data: { machineSpec: machineSpec ? machineSpec : undefined } });\n                }}\n                className=\"icon svg-icon add-row\"\n                aria-hidden=\"true\"\n              >\n                <use xlinkHref=\"#iconzengjia\"></use>\n              </svg>\n              {state?.dataSource.length === 1 ? null : (\n                <svg\n                  onClick={() => {\n                    dispatch({ key: \"deleteRow\", data: { index } });\n                  }}\n                  className=\"icon svg-icon delete-row\"\n                  aria-hidden=\"true\"\n                >\n                  <use xlinkHref=\"#iconjianshao\"></use>\n                </svg>\n              )}\n            </div>\n          );\n        },\n      },\n    ];\n  };\n\n  return (\n    <div className={basicClass}>\n      <Table pagination={false} rowKey={() => uuidv4()} dataSource={state?.dataSource || []} columns={getColumns()} />\n    </div>\n  );\n};\n\nexport default EditTable;\n"
  },
  {
    "path": "arius-console/src/container/custom-form/tpl-table-add-row/index.less",
    "content": ".tpl-table-form {\n  &-readonlyText {\n    margin-top: 12px;\n  }\n  &-formitem {\n    margin-top: 20px;\n    margin-bottom: 0px !important;\n  }\n  &-table-formitem {\n    margin-top: 0px;\n    margin-bottom: 0px !important;\n  }\n  &-Tag {\n    width: 44px;\n    height: 24px;\n    background: rgba(47, 129, 249, 0.06);\n    border: 1px solid @primary-color;\n    border-radius: 1px;\n    &-content {\n      font-family: PingFangSC-Medium;\n      font-size: 12px;\n      color: @primary-color;\n      text-align: center;\n      line-height: 20px;\n    }\n  }\n  &-titleicon {\n    font-size: 10px;\n    color: #666;\n    margin-left: 4px;\n  }\n  .ant-input-number-handler-wrap {\n    opacity: 1 !important;\n  }\n}\n.tpl-table-form-edittable {\n  &-formitem {\n    margin-top: 20px;\n    margin-bottom: 0px !important;\n  }\n  &-table-formitem {\n    margin-top: 0px;\n    margin-bottom: 0px !important;\n  }\n  .add-row,\n  .delete-row {\n    font-size: 30px;\n  }\n  .add-row {\n    margin-right: 5px;\n  }\n}\n.ant-typography-disabled {\n  color: #00000040;\n  cursor: not-allowed;\n}\n"
  },
  {
    "path": "arius-console/src/container/custom-form/upload-file.tsx",
    "content": "import React from 'react';\nimport  { Upload } from 'antd';\nimport { UploadOutlined } from '@ant-design/icons';\n\nconst { Dragger } = Upload;\n\nexport interface IUploadFileProps {\n  name?: string;\n  multiple?: boolean;\n  action?: string;\n  accept?: string;\n  msg?: string;\n  url?: any;\n  onChange?: (result: any) => any;\n}\nexport const UploadFile = (props: IUploadFileProps) => {\n\n  const handleChange = (e: any) => {\n    const { onChange } = props;\n    onChange && onChange(e);\n  }\n\n  const {multiple, action, accept, msg, url} = props;\n\n  const defaultFileList = [] as any;\n    if (url) {\n      defaultFileList[0] = {\n          uid: 1,\n          name: url,\n          status: 'done',\n      }\n    }\n  return (\n    <>\n        <Dragger\n          beforeUpload={(file: any) => false}\n          multiple={multiple}\n          accept={accept}\n          action={action}\n          onChange={(e) => handleChange(e)}\n          defaultFileList={defaultFileList}\n          style={{width: '50%'}}\n        >\n          <p>\n            <UploadOutlined style={{fontSize: 20, color: '#1473FF'}}/>\n          </p>\n          <p>{msg ? msg : <p>单击或拖动文件到此区域以上传, 支持单、多个文件<br/>且为.gz格式文件。</p>}</p>\n        </Dragger>\n    </>);\n}"
  },
  {
    "path": "arius-console/src/container/dashboard/Operation.tsx",
    "content": "import { dashboardIndex } from \"api/dashboard\";\nimport React, { useEffect, useState, createContext } from \"react\";\nimport { HashMenu } from \"knowdesign\";\nimport { operationTabs, OPERATION_MENU_MAP } from \"./config\";\nimport { useDispatch } from \"react-redux\";\nimport { setDashBoardDymanicMetrics } from \"actions/dashBoard\";\nimport \"./index.less\";\nimport { getDictionary } from \"api/dashboard\";\n\nexport const DashboardContext = createContext(null);\n\nconst OperationPage = () => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const dispatch = useDispatch();\n\n  const [dictionary, setDictionary] = useState({});\n\n  useEffect(() => {\n    dashboardIndex().then((res) => {\n      dispatch(\n        setDashBoardDymanicMetrics({\n          dymanicConfigMetrics: res || [],\n        })\n      );\n    });\n    _getDictionary();\n  }, []);\n\n  const _getDictionary = async () => {\n    let params = {\n      model: \"Dashboard\",\n    };\n    let res = await getDictionary(params);\n    let clusterData = {};\n    let nodeData = {};\n    let indexData = {};\n    (res || []).forEach((item: any) => {\n      if (item?.metricType) {\n        switch (item?.type) {\n          case \"集群\":\n            clusterData[item?.metricType] = item;\n            break;\n          case \"节点\":\n            nodeData[item?.metricType] = item;\n            break;\n          case \"索引\":\n            indexData[item?.metricType] = item;\n            break;\n          default:\n            break;\n        }\n      }\n    });\n    setDictionary({ clusterData, nodeData, indexData });\n  };\n\n  return (\n    <DashboardContext.Provider value={dictionary}>\n      <HashMenu TAB_LIST={operationTabs} MENU_MAP={OPERATION_MENU_MAP} defaultHash=\"cluster\" prefix=\"dashboard\" key={department} />\n    </DashboardContext.Provider>\n  );\n};\n\nexport default OperationPage;\n"
  },
  {
    "path": "arius-console/src/container/dashboard/cluster.tsx",
    "content": "import React, { useState, useEffect, useRef, useContext } from \"react\";\nimport { SyncOutlined } from \"@ant-design/icons\";\nimport { MetricsConfig } from \"./components/metricsConfig\";\nimport { clusterMetrics, getOption } from \"./config\";\nimport { PieCharts } from \"./components/pieCharts\";\nimport \"./index.less\";\nimport { ILineParams, clusterLine, setCheckedList, getCheckedList, clusterList, clusterThreadPoolQueue } from \"api/dashboard\";\nimport { Line } from \"./components/line\";\nimport { cloneDeep } from \"lodash\";\nimport DragGroup from \"../../d1-packages/drag-group/DragGroup\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport { withRouter } from \"react-router-dom\";\nimport TableCard from \"./components/table\";\nimport { connect } from \"react-redux\";\nimport { CustomTimeRangePicker } from \"component/TimeRangePicker\";\nimport { DashboardContext } from \"./Operation\";\n\nconst ONE_HOUR = 1000 * 60 * 60;\n\nconst mapStateToProps = (state) => ({\n  dashboard: state.dashBoard,\n});\n\nconst Cluster = withRouter((props: any) => {\n  const dictionary = useContext(DashboardContext);\n\n  const currentTime = new Date().getTime();\n  const [rangeTime, setRangeTime] = useState([currentTime - ONE_HOUR, currentTime]);\n  const [loading, setLoading] = useState([]);\n  const [metricsLoading, setMetricsLoading] = useState(true);\n  const [isLoading, setIsLoading] = useState(false);\n  const [metrics, setMetrics] = useState([\"health\", ...Object.keys(clusterMetrics).filter((item) => item != \"health\")]);\n  const [data, setData] = useState({});\n  const ref: any = useRef();\n  const topN = useRef({});\n  const customTimeRef = useRef(null);\n\n  const handleTimeChange = (times: number[], isCustomTime = false) => {\n    setRangeTime(times);\n  };\n\n  const setIndexConfigCheckedData = (checkvalue) => {\n    setMetrics([\"health\", ...checkvalue.filter((item) => item != \"health\")]);\n    setCheckedList(\"cluster\", [\"health\", ...checkvalue.filter((item) => item != \"health\")]);\n  };\n\n  const reload = () => {\n    if (metricsLoading) return;\n    ref.current?.getData();\n    getLineData();\n  };\n\n  const sortMetrics = () => {\n    const left = metrics.map((item) => ({ name: clusterMetrics[item]?.name, value: item, fixed: clusterMetrics[item]?.fixed || false }));\n    const right = [];\n    Object.keys(clusterMetrics).forEach((item) => {\n      if (!metrics.includes(item)) {\n        right.push({ name: clusterMetrics[item]?.name, value: item, fixed: clusterMetrics[item]?.fixed || false });\n      }\n    });\n    return [...left, ...right];\n  };\n\n  // 增加点击刷新按钮先计算时间差 保持用户选择的事件范围\n  const handleReload = () => {\n    customTimeRef?.current?.refresh();\n  };\n\n  const renderConfig = () => {\n    return (\n      <div className=\"dashboard-config\">\n        <SyncOutlined spin={isLoading} className=\"dashboard-config-icon\" onClick={() => handleReload()} />\n        <span className=\"dashboard-config-line\"></span>\n        <CustomTimeRangePicker ref={customTimeRef} onChange={handleTimeChange} />\n        <MetricsConfig title=\"集群\" value={metrics} optionList={sortMetrics()} cb={setIndexConfigCheckedData} defaultCheckedData={[]} />\n      </div>\n    );\n  };\n\n  const getLineData = async (topNu?: number, metricsTypes?: string[]) => {\n    const filterLine = [\"health\", \"clusterElapsedTimeGte5Min\", \"shardNum\"];\n    const filterTable = [\"clusterElapsedTimeGte5Min\", \"shardNum\"];\n    const whiteList: string[] = [\"refresh\", \"merge\", \"write\", \"management\", \"search\", \"flush\"];\n    const lineMetrics = metrics.filter((item: any) => !filterLine.includes(item) && !whiteList.includes(item));\n    const tableMetrics = metrics.filter((item: any) => filterTable.includes(item));\n    const whiteMetrics = metrics.filter((item: any) => whiteList.includes(item));\n    setIsLoading(true);\n    setLoading(metricsTypes || metrics);\n    const params: ILineParams = {\n      metricsTypes: metricsTypes || lineMetrics,\n      // 目前固定为avg\n      aggType: \"avg\",\n      startTime: rangeTime[0],\n      endTime: rangeTime[1],\n      topNu: topNu || 5,\n    };\n    try {\n      let metricsList = [];\n      if (params.metricsTypes.length) {\n        metricsList = await clusterLine(params);\n      }\n      if (metrics.includes(\"clusterElapsedTimeGte5Min\") || metrics.includes(\"shardNum\")) {\n        const list = await getListData(tableMetrics);\n        metricsList.push(...list);\n      }\n      if (whiteMetrics.length) {\n        params.metricsTypes = whiteMetrics;\n        const list = await clusterThreadPoolQueue(params);\n        metricsList.push(...list);\n      }\n      if (!metricsList || metricsList.length === 0 || metricsList[0]?.metricsContents?.length === 0) {\n        setData({});\n        setIsLoading(false);\n        setLoading([]);\n        return;\n      }\n      if (metricsTypes) {\n        // 如果传入指标就不初始化data直接在这里return\n        const cloneData = cloneDeep(data);\n        metricsList.forEach((item) => {\n          // 针对Gateway, clusterElapsedTimeGte5Min 做特殊处理\n          if (item.type == \"gatewaySucPer\" || item.type == \"gatewayFailedPer\") {\n            cloneData[item.type] = getOption({ metrics: item, configData: clusterMetrics, isGatewayLink: true });\n          } else if (item.type === \"clusterElapsedTimeGte5Min\" || item.type === \"shardNum\") {\n            cloneData[item.type] = item;\n          } else if (whiteList.includes(item.type)) {\n            cloneData[item.type] = getOption({ metrics: item, configData: clusterMetrics });\n          } else {\n            cloneData[item.type] = getOption({ metrics: item, configData: clusterMetrics, isClusterLink: true });\n          }\n        });\n        setData(cloneData);\n        return;\n      }\n      const datas = {};\n\n      metricsList.forEach((item) => {\n        // 针对Gateway, clusterElapsedTimeGte5Min 做特殊处理\n        if (item.type == \"gatewaySucPer\" || item.type == \"gatewayFailedPer\") {\n          datas[item.type] = getOption({ metrics: item, configData: clusterMetrics, isGatewayLink: true });\n        } else if (item.type === \"clusterElapsedTimeGte5Min\" || item.type === \"shardNum\") {\n          datas[item.type] = item;\n        } else if (whiteList.includes(item.type)) {\n          datas[item.type] = getOption({ metrics: item, configData: clusterMetrics });\n        } else {\n          datas[item.type] = getOption({ metrics: item, configData: clusterMetrics, isClusterLink: true });\n        }\n      });\n      setData(datas);\n    } catch (error) {\n      setIsLoading(false);\n      setLoading([]);\n      console.log(\"render line\", error);\n    } finally {\n      setIsLoading(false);\n      setLoading([]);\n    }\n  };\n\n  const getListData = async (metricsTypes) => {\n    let listParams = {\n      metricsTypes,\n      aggType: \"avg\",\n      orderByDesc: true,\n    };\n    let list = await clusterList(listParams);\n    return list;\n  };\n\n  const sortEnd = ({ oldIndex, newIndex }) => {\n    if (metrics[newIndex] === \"health\") {\n      return;\n    }\n    const listsNew = arrayMoveImmutable(metrics, oldIndex, newIndex);\n    setCheckedList(\"cluster\", listsNew);\n    setMetrics(listsNew);\n  };\n\n  const renderContent = () => {\n    return (\n      <DragGroup\n        dragContainerProps={{\n          onSortEnd: (args) => sortEnd({ ...args }),\n          axis: \"xy\",\n          distance: 100,\n        }}\n        containerProps={{\n          grid: 8,\n          gutter: [10, 10],\n        }}\n      >\n        {metrics.map((item: any, i) => {\n          if (item === \"health\") return <PieCharts ref={ref} key={\"health\"} dictionary={dictionary?.clusterData} />;\n          if (item === \"clusterElapsedTimeGte5Min\" || item === \"shardNum\") {\n            let list = data[item]?.metricListContents;\n            let dataSource = (list || []).map((item) => {\n              return {\n                ...item,\n                key: item.clusterPhyName,\n              };\n            });\n            return (\n              <TableCard\n                columns={clusterMetrics[item]?.columns}\n                dataSource={dataSource}\n                title={clusterMetrics[item]?.name}\n                dictionary={dictionary?.clusterData?.[item]}\n                isLoading={loading.includes(item)}\n                key={item}\n              />\n            );\n          }\n          return (\n            <Line\n              title={data?.[item]?.title?.text || clusterMetrics[item]?.title()}\n              index={item}\n              key={item}\n              option={data[item] || {}}\n              isLoading={loading.includes(item)}\n              cb={getLineData}\n              dictionary={dictionary?.clusterData?.[item]}\n              topN={topN}\n            />\n          );\n        })}\n      </DragGroup>\n    );\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(\"cluster\");\n      setMetricsLoading(false);\n      if (!checkedList || checkedList.length === 0) {\n        ref.current?.getData();\n        getLineData();\n      } else {\n        // 以下需暂时过滤掉\n        const filterList = [\n          \"reqUprushNum\",\n          \"httpNum\",\n          \"gatewaySucPer\",\n          \"write\",\n          \"search\",\n          \"refresh\",\n          \"flush\",\n          \"management\",\n          \"merge\",\n          \"clusterElapsedTime\",\n          \"indexReqNum\",\n          \"docUprushNum\",\n        ];\n        setMetrics([...(new Set(checkedList.filter((item) => filterList.indexOf(item) === -1)) as any)]);\n      }\n    } catch (error) {\n      setMetricsLoading(false);\n      setMetrics(metrics);\n      console.log(\"cluster-kanban node-view 获取配置下项失败\", error);\n    }\n  };\n\n  const linkToClusterPage = (cluster: string) => {\n    props.history.push(`/indicators/cluster?cluster=${cluster}`);\n  };\n\n  const linkToNodePage = (node: string, cluster: string) => {\n    props.history.push(`/indicators/cluster?cluster=${cluster}&node=${node}&#node`);\n  };\n\n  const linkToGatewayPage = () => {\n    props.history.push(`/indicators/gateway`);\n  };\n\n  useEffect(() => {\n    window[\"clusterlink\"] = (cluster: string) => {\n      linkToClusterPage(cluster);\n    };\n    window[\"gatewaylink\"] = () => {\n      linkToGatewayPage();\n    };\n    window[\"nodelink\"] = (node: string, cluster: string) => {\n      linkToNodePage(node, cluster);\n    };\n  }, []);\n\n  const setDymanicMetrics = () => {\n    if (props.dashboard?.dymanicConfigMetrics?.length) {\n      const res = props.dashboard?.dymanicConfigMetrics;\n      res.forEach((item) => {\n        try {\n          const itemValue = JSON.parse(item?.value);\n          switch (item.valueName) {\n            case \"cluster.shard.num_threshold\":\n              clusterMetrics.shardNum.name = `shard个数大于${itemValue.value ?? \"\"}集群列表`;\n              break;\n            case \"cluster.metric.collector.delayed_threshold \":\n              //指标采集延时大于5分钟集群列表\n              clusterMetrics.clusterElapsedTimeGte5Min.name = `指标采集延时大于${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}集群列表`;\n              break;\n            default:\n              break;\n          }\n        } catch (error) {\n          console.log(error, `JSON.parse解析${item?.valueName}错误，请检查动态配置中配置项书写格式`);\n        }\n      });\n    }\n  };\n\n  // 加载选中配置\n  useEffect(() => {\n    getAsyncCheckedList();\n  }, []);\n\n  useEffect(() => {\n    setDymanicMetrics();\n  }, [props.dashboard?.dymanicConfigMetrics]);\n\n  useEffect(() => {\n    reload();\n  }, [rangeTime, metrics]);\n\n  return (\n    <div className=\"dashboard-index-view\">\n      {renderConfig()}\n      {renderContent()}\n    </div>\n  );\n});\n\nexport default connect(mapStateToProps, null)(Cluster);\n"
  },
  {
    "path": "arius-console/src/container/dashboard/components/echarts/index.less",
    "content": ".no-data-info {\n  text-align: center;\n}"
  },
  {
    "path": "arius-console/src/container/dashboard/components/echarts/index.tsx",
    "content": "import React from \"react\";\nimport { EChartOption } from \"echarts/lib/echarts\";\nimport * as echart from \"echarts/lib/echarts\";\n// import 'echarts/lib/chart/pie';\n// import 'echarts/lib/chart/bar';\n// import 'echarts/lib/chart/line';\n// import 'echarts/lib/component/legend';\n// import 'echarts/lib/component/tooltip';\n// import 'echarts/lib/component/title';\n// import 'echarts/lib/component/axis';\nimport \"./index.less\";\nimport { throttle } from \"lodash\";\n\nexport interface IEchartsProps {\n  width?: number;\n  height?: number;\n  options?: EChartOption;\n  isResize?: boolean;\n  onClick?: (key: string) => void;\n}\n\nexport const hasData = (options: EChartOption) => {\n  if (options?.series?.length) return true;\n  return false;\n};\n\nexport default class Echarts extends React.Component<IEchartsProps> {\n  public id = null as HTMLDivElement;\n\n  public myChart = null as unknown as echart.ECharts;\n\n  public componentDidMount() {\n    const { options } = this.props;\n    this.myChart = echart.init(this.id);\n    this.myChart.setOption(options as EChartOption);\n    this.props.onClick &&\n      this.myChart.on(\"click\", (params) => {\n        this.props.onClick(params?.data?.key);\n      });\n\n    const resize = throttle(() => {\n      // 表示该dom未进入可视区\n      if (!this.id?.getBoundingClientRect().width) {\n        return;\n      }\n      this.resize();\n    }, 300);\n    window.addEventListener(\"resize\", resize);\n  }\n\n  public componentWillUnmount() {\n    window.removeEventListener(\"resize\", this.resize);\n  }\n\n  public componentDidUpdate() {\n    this.refresh();\n  }\n\n  public refresh = () => {\n    const { options } = this.props;\n    this.myChart.setOption(options as EChartOption);\n  };\n\n  public resize = () => {\n    this.props.isResize ? console.log(\"已设置不执行resize\") : this.myChart.resize();\n  };\n\n  public render() {\n    const { height, width } = this.props;\n    return <div ref={(id: HTMLDivElement) => (this.id = id)} style={{ width: `${width}px`, height: `${height}px` }} />;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/dashboard/components/line.tsx",
    "content": "import React, { memo, useEffect, useRef, useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as echarts from \"echarts/core\";\nimport { Spin, Empty, Tooltip, Modal, Dropdown, Menu } from \"antd\";\nimport _, { cloneDeep } from \"lodash\";\nimport {\n  BarChart,\n  // 系列类型的定义后缀都为 SeriesOption\n  BarSeriesOption,\n  LineChart,\n  LineSeriesOption,\n} from \"echarts/charts\";\nimport {\n  TitleComponent,\n  // 组件类型的定义后缀都为 ComponentOption\n  TitleComponentOption,\n  TooltipComponent,\n  TooltipComponentOption,\n  GridComponent,\n  GridComponentOption,\n  LegendComponent,\n  LegendComponentOption,\n  MarkLineComponent,\n  MarkLineComponentOption,\n} from \"echarts/components\";\nimport { CanvasRenderer } from \"echarts/renderers\";\nimport * as actions from \"actions\";\nimport { useMouseoutOutSide } from \"../../indicators-kanban//hooks/useMouseoutOutSide\";\nimport \"../index\";\nimport { DownOutlined } from \"@ant-design/icons\";\nimport InfoTooltip from \"component/infoTooltip\";\n\nconst imgSrc = require(\"./../../../assets/empty.png\");\n\n// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型\nexport type ECOption = echarts.ComposeOption<\n  | BarSeriesOption\n  | LineSeriesOption\n  | TitleComponentOption\n  | TooltipComponentOption\n  | GridComponentOption\n  | LegendComponentOption\n  | MarkLineComponentOption\n>;\n\n// 注册必须的组件\necharts.use([TitleComponent, LegendComponent, TooltipComponent, GridComponent, BarChart, LineChart, CanvasRenderer, MarkLineComponent]);\n\n/*\n *@ 教程 https://echarts.apache.org/zh/index.html\n *@ 配置按需引入\n */\n\nexport const overviewClassPrefix = \"dashboard\";\n\nexport interface ILine {\n  index: string;\n  option: ECOption;\n  setModalId?: (modalId: string, params?: any, cb?: Function) => any;\n  bigPicture?: boolean;\n  width?: number | string;\n  height?: number | string;\n  isLoading?: boolean;\n  title?: string;\n  tipSync?: boolean;\n  cb?: Function;\n  tooltip?: string;\n  topN?: any;\n  dictionary?: any;\n}\n\nexport const DrawLine = ({ index, option, setModalId, bigPicture, width, height, tipSync, cb, title, topN, dictionary }: ILine) => {\n  const chartBox = useRef(null);\n  const myChart = useRef(null);\n  const flag = useRef(true);\n  const [isShowLegend, setIsShowLegend] = useState(false);\n  const topNMap = {\n    5: \"top 5\",\n    10: \"top 10\",\n    20: \"top 20\",\n    50: \"top 50\",\n  };\n  const handleMenuClick = (result) => {\n    topN.current[index] = result.key;\n    cb(result.key, [index]);\n  };\n  const getMenu = () => (\n    <Menu onClick={handleMenuClick} selectedKeys={[topN.current[index] || \"5\"]}>\n      {Object.keys(topNMap).map((item) => (\n        <Menu.Item key={item}>{topNMap[item]}</Menu.Item>\n      ))}\n    </Menu>\n  );\n\n  const renderCheckTop = (topN) => {\n    return (\n      <div className={`dashboard-overview-content-line-enlarge`}>\n        <Dropdown overlay={getMenu()} trigger={[\"click\"]}>\n          <div>\n            {topNMap[topN.current && topN.current[index]] || topNMap[5]} <DownOutlined style={{ color: \"#74788D\", marginLeft: 6 }} />\n          </div>\n        </Dropdown>\n      </div>\n    );\n  };\n\n  const showTip = (params) => {\n    const { offsetX: x, offsetY: y } = params;\n    if (tipSync) {\n      if (x !== -999 || y !== -999) {\n        (window as any).lineX = x;\n        (window as any).lineY = y;\n        (window as any).lineTag = index;\n      } else if ((window as any).lineTag === index) {\n        (window as any).lineX = x;\n        (window as any).lineY = y;\n      }\n      myChart.current.dispatchAction({\n        type: \"showTip\",\n        x: x === -999 ? (window as any).lineX : x,\n        y: y === -999 ? (window as any).lineY : y,\n      });\n    } else {\n      myChart.current.dispatchAction({\n        type: \"showTip\",\n        x: x,\n        y: y,\n      });\n    }\n  };\n\n  const hideTip = () => {\n    // 设置无效的 x, y 隐藏点击显示的 toolTip 和 线\n    showTip({ offsetX: -999, offsetY: -999 });\n\n    // 重新监听鼠标移动显示 toolTip\n    chartMousemove();\n\n    flag.current = true;\n  };\n\n  const chartMousemove = () => {\n    myChart.current.getZr().on(\"mousemove\", showTip);\n  };\n\n  useMouseoutOutSide(\"mousemove\", chartBox, hideTip);\n\n  useEffect(() => {\n    if (myChart.current) {\n      myChart.current?.dispose();\n    }\n\n    myChart.current = echarts.init(document.getElementById(index) as HTMLElement);\n\n    // 监听点击事件\n    myChart.current.getZr().on(\"click\", function (params) {\n      if (flag.current) {\n        myChart.current.getZr().off(\"mousemove\");\n\n        flag.current = false;\n      } else {\n        hideTip();\n      }\n    });\n\n    // 监听鼠标移动显示 toolTip\n    chartMousemove();\n\n    const resize = _.throttle(() => {\n      const el: HTMLElement = document.getElementById(index);\n      // 表示该dom未进入可视区\n      if (!el.getBoundingClientRect().width) {\n        return;\n      }\n      myChart.current?.resize();\n    }, 300);\n\n    window.addEventListener(\"resize\", resize);\n\n    return () => {\n      window.removeEventListener(\"resize\", resize);\n    };\n  }, []);\n\n  useEffect(() => {\n    // 增加true不合并数据\n    if (isShowLegend) {\n      const copyOption = cloneDeep(option);\n      (copyOption.legend as any) = null;\n      (copyOption.grid as any).right = \"20\";\n      copyOption && myChart.current?.setOption(copyOption, true);\n    } else {\n      option && myChart.current?.setOption(option, true);\n    }\n  }, [option, isShowLegend]);\n\n  return (\n    <>\n      <div ref={chartBox} style={{ position: \"relative\" }} className={`${overviewClassPrefix}-overview-content-line-container`}>\n        <div\n          className={`${overviewClassPrefix}-overview-content-line-item`}\n          id={index}\n          key={index}\n          style={{\n            width: width ? width : \"none\",\n            height: height ? height : \"none\",\n          }}\n        ></div>\n        <div\n          className=\"center-center-empty-box-title\"\n          style={{\n            position: \"absolute\",\n            top: 13,\n            left: 16,\n            height: 22,\n            lineHeight: \"22px\",\n            fontSize: \"14px\",\n            color: \"#212529\",\n            fontFamily: \"HelveticaNeue-Medium\",\n            letterSpacing: \"0.5px\",\n          }}\n        >\n          {title}\n          {(dictionary?.price || dictionary?.currentCalLogic || dictionary?.threshold) && (\n            <InfoTooltip\n              price={dictionary?.price}\n              currentCalLogic={dictionary?.currentCalLogic}\n              threshold={dictionary?.threshold}\n            ></InfoTooltip>\n          )}\n        </div>\n        {renderCheckTop(topN)}\n      </div>\n    </>\n  );\n};\n\nexport const Line: React.FC<ILine> = ({\n  index,\n  option,\n  isLoading = false,\n  width,\n  height,\n  title,\n  tipSync,\n  cb,\n  tooltip,\n  topN,\n  dictionary,\n}) => {\n  const renderLoading = () => {\n    return (\n      <div\n        className={`common-loading-container indicators-kanban-loading-container ${overviewClassPrefix}-overview-content-line-container`}\n        style={{ border: \"none\" }}\n      >\n        <div className=\"center-center-loading\">\n          <Spin />\n        </div>\n      </div>\n    );\n  };\n  const renderEmpty = () => {\n    const { price, currentCalLogic, threshold } = dictionary || {};\n    return (\n      <div\n        className={`common-loading-container indicators-kanban-loading-container ${overviewClassPrefix}-overview-content-line-container`}\n        style={{ border: \"none\" }}\n      >\n        {title ? (\n          <div\n            className=\"center-center-empty-box-title\"\n            style={{\n              position: \"relative\",\n              top: 13,\n              left: 16,\n              height: 22,\n              lineHeight: \"22px\",\n              fontSize: \"14px\",\n              color: \"#212529\",\n              fontFamily: \"HelveticaNeue-Medium\",\n              letterSpacing: \"0.5px\",\n              marginBottom: 100,\n            }}\n          >\n            {title}\n            {(price || currentCalLogic || threshold) && (\n              <InfoTooltip price={price} currentCalLogic={currentCalLogic} threshold={threshold}></InfoTooltip>\n            )}\n          </div>\n        ) : (\n          \"\"\n        )}\n        <div className={\"dashboard-line-container-empty\"}>\n          <div>\n            <img src={imgSrc} />\n          </div>\n          <div>\n            <span>数据为空</span>\n          </div>\n        </div>\n      </div>\n    );\n  };\n  const renderLine = () => {\n    return (\n      <DrawLine\n        width={width}\n        height={height}\n        option={option}\n        index={index}\n        tipSync={tipSync}\n        cb={cb}\n        title={title}\n        tooltip={tooltip}\n        topN={topN}\n        dictionary={dictionary}\n      />\n    );\n  };\n  return <>{isLoading ? renderLoading() : !option || Object.keys(option).length == 0 ? renderEmpty() : renderLine()}</>;\n};\n"
  },
  {
    "path": "arius-console/src/container/dashboard/components/metricsConfig.tsx",
    "content": "import React, { memo, useState, useEffect } from \"react\";\nimport { Button, Modal, Checkbox, Divider, Form, Row, Col, Popover } from \"antd\";\nconst CheckboxGroup = Checkbox.Group;\nimport { SettingOutlined } from \"@ant-design/icons\";\nimport \"./../index.less\";\nimport Tooltip from \"antd/es/tooltip\";\nimport { getPopupContainer } from \"lib/utils\";\n\nexport const MetricsConfig = memo((props: any) => {\n  const { title, optionList, defaultCheckedData, cb: callback } = props;\n  const [selectedData, setSelectedData] = useState(defaultCheckedData || []);\n  const [disabled, setDisabled] = useState(false);\n  const [visible, setVisible] = React.useState(false);\n\n  const showPopconfirm = (visible) => {\n    setSelectedData(props.value);\n    setVisible(visible);\n  };\n\n  useEffect(() => {\n    setDisabled(selectedData.length >= 1 ? false : true);\n  }, [selectedData, props.value]);\n\n  useEffect(() => {\n    setSelectedData(props.value);\n  }, [props.value]);\n\n  const handleCancel = () => {\n    setSelectedData(props.value);\n    setVisible(false);\n  };\n  const renderFooter = () => {\n    return (\n      <div style={{ overflow: \"hidden\", marginTop: 20 }}>\n        <Button\n          type=\"primary\"\n          key=\"ok\"\n          onClick={() => {\n            setVisible(false);\n            callback(selectedData);\n            setVisible(false);\n          }}\n          style={{ float: \"right\", marginLeft: 8 }}\n          disabled={disabled}\n        >\n          确认\n        </Button>\n        <Button key=\"cancel\" onClick={() => handleCancel()} style={{ float: \"right\" }}>\n          取消\n        </Button>\n      </div>\n    );\n  };\n\n  const handleChange = (val: string[]) => {\n    setSelectedData(val);\n  };\n\n  const renderContent = () => {\n    return (\n      <div style={{ width: 420 }}>\n        <div style={{ fontSize: 14, color: \"#212529\", marginBottom: 20 }}>{`${title}指标配置`}</div>\n        <Checkbox.Group value={selectedData} style={{ width: \"100%\" }} onChange={handleChange}>\n          <Row gutter={38}>\n            {optionList.map((item) =>\n              item.fixed ? null : (\n                <Col span={12} key={item.value}>\n                  <Checkbox value={item.value}>{item.name?.split(\"（\")[0]}</Checkbox>\n                </Col>\n              )\n            )}\n          </Row>\n        </Checkbox.Group>\n        {renderFooter()}\n      </div>\n    );\n  };\n  return (\n    <>\n      <Tooltip title=\"指标配置\">\n        <Popover\n          title={null}\n          visible={visible}\n          trigger={[\"click\"]}\n          placement=\"bottomLeft\"\n          content={renderContent()}\n          onVisibleChange={showPopconfirm}\n          getPopupContainer={getPopupContainer}\n        >\n          <SettingOutlined className=\"dashboard-config-setting\" />\n        </Popover>\n      </Tooltip>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/dashboard/components/pieCharts/constants.ts",
    "content": "export const createOption = (data: any, key: string) => {\n  let text = {\n    green: \"健康率\",\n    yellow: \"预警率\",\n    red: \"故障率\",\n    unknown: \"未知率\",\n  };\n  let subtext = (data || []).filter((item) => item.key === key);\n\n  const options = {\n    title: {\n      text: text[key] || \"故障率\",\n      subtext: parseInt(subtext[0]?.prrcent || \"0\") + \"%\",\n      textAlign: \"center\",\n      textVerticalAlign: \"center\",\n      textStyle: {\n        fontSize: 12,\n        color: \"#74788D\",\n        fontFamily: \"PingFangSC-Regular\",\n      },\n      subtextStyle: {\n        fontSize: 20,\n        color: \"rgba(0,0,0,0.85)\",\n        fontFamily: \"PingFangSC-Medium\",\n      },\n      left: \"47%\",\n      top: \"40%\",\n    },\n    tooltip: {\n      trigger: \"item\",\n      position: (pos, params, dom, rect, size) => {\n        const [x, y] = pos;\n        const [width, height] = size.viewSize;\n        const domWidth = (dom as any).offsetWidth || 390;\n        const obj = { top: y - 80 };\n        const chartPosition = width / 2 + 20;\n        if (x > chartPosition) {\n          // 在鼠标左侧展示\n          obj[\"left\"] = x - domWidth - 10;\n        } else {\n          // 在鼠标右侧展示\n          obj[\"left\"] = x + 10;\n        }\n        return obj;\n      },\n      formatter: (params: any) => {\n        let tip =\n          params.marker +\n          params.name +\n          \": \" +\n          params?.data?.value +\n          '个<br /> <span style=\"display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color: #fff;\"> </span>占比: ' +\n          params?.data?.prrcent +\n          \"%\";\n        return tip;\n      },\n    },\n    color: [\"#6BD9C5\", \"#F9CC7E\", \"#FA8787\", \"#A8ADBD\"],\n    grid: {\n      left: 10,\n      top: 0,\n    },\n    series: [\n      {\n        type: \"pie\",\n        radius: [\"100%\", \"60%\"],\n        avoidLabelOverlap: false,\n        hoverAnimation: false,\n        label: {\n          show: false,\n          position: \"center\",\n        },\n        animation: false,\n        labelLine: {\n          show: false,\n        },\n        data: data,\n      },\n    ],\n  };\n  return options;\n};\n"
  },
  {
    "path": "arius-console/src/container/dashboard/components/pieCharts/index.less",
    "content": ".piedashboardbox {\n  width: 100%;\n  display: flex;\n  width: 100%;\n  border: 1px solid #dae0e4;\n  border-radius: 8px;\n}\n\n.dashboard-piechart {\n  height: 262px;\n  padding: 13px 0px 0px 16px;\n  background: #fff;\n  border-radius: 8px;\n  // box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.01), 0 3px 6px 3px rgba(0, 0, 0, 0.01), 0 2px 6px 0 rgba(0, 0, 0, 0.03);\n  width: 100%;\n  cursor: default;\n\n  &-header {\n    width: 100%;\n\n    &-title {\n      font-size: 14px;\n      line-height: 20px;\n      font-family: PingFangSC-Regular;\n      color: #303a51;\n      .health-tooltip {\n        position: absolute;\n      }\n    }\n  }\n\n  &-faulttask {\n    margin: 17px 15px 0 0px;\n    width: 100%;\n    height: 190px;\n    background: #f8f9fa;\n    border-radius: 8px;\n    padding: 12px 10px 10px 10px;\n    overflow: hidden;\n\n    &-icon {\n      width: 100%;\n      line-height: 16px;\n      &-item {\n        width: 20px;\n        height: 20px;\n        margin-right: 4px;\n        display: inline-block;\n        vertical-align: middle;\n      }\n\n      &-title {\n        font-size: 14px;\n        color: rgba(0, 0, 0, 0.85);\n        letter-spacing: 0;\n        text-align: justify;\n        line-height: 22px;\n        vertical-align: middle;\n      }\n    }\n\n    &-content {\n      height: 90%;\n      overflow-y: scroll;\n      overflow-x: hidden;\n      margin-top: 4px;\n      margin-left: 19px;\n\n      &-empty {\n        margin-top: 48px;\n        text-align: center;\n        margin-left: -19px;\n\n        img {\n          margin-left: 8px;\n          width: 60px;\n          height: 40px;\n          margin-bottom: 8px;\n        }\n\n        span {\n          font-family: PingFangSC-Regular;\n          font-size: 12px;\n          color: #919aac;\n          text-align: center;\n          line-height: 20px;\n          margin-left: -1px;\n        }\n      }\n\n      &-li {\n        font-size: 12px;\n        color: rgba(0, 0, 0, 0.65);\n        letter-spacing: 0;\n        text-align: justify;\n        line-height: 20px;\n        margin-bottom: 4px;\n      }\n    }\n  }\n}\n\n::-webkit-scrollbar-track {\n  background-color: transparent;\n}\n\n::-webkit-scrollbar-thumb {\n  border-radius: 10px;\n  transition: all 1s;\n  background-color: #c7c7c7;\n  border: 1px solid transparent;\n}\n\n::-webkit-scrollbar {\n  -webkit-appearance: none;\n  width: 8px;\n  height: 3px;\n}\n\n::-webkit-scrollbar-button {\n  display: none;\n}\n\n::-webkit-scrollbar-corner {\n  display: none;\n}\n"
  },
  {
    "path": "arius-console/src/container/dashboard/components/pieCharts/index.tsx",
    "content": "import React from \"react\";\nimport { PieChart } from \"./pieChart\";\nimport { Spin } from \"antd\";\nimport { dashboardHealth } from \"api/dashboard\";\n\ninterface Istate {\n  dataSource: any;\n  loading: boolean;\n}\n\nexport class PieCharts extends React.Component<any, Istate> {\n  public constructor(props) {\n    super(props);\n  }\n\n  public state: Istate = {\n    dataSource: {},\n    loading: true,\n  };\n\n  public getData = () => {\n    // const { startTime, endTime } = this.props;\n    this.setState({ dataSource: {}, loading: true });\n    dashboardHealth()\n      .then((res) => {\n        this.setState({ dataSource: res, loading: false });\n      })\n      .catch((err) => {\n        this.setState({ loading: false });\n      });\n  };\n\n  public render() {\n    const { dataSource, loading } = this.state;\n    return (\n      <Spin spinning={loading}>\n        <div className=\"piedashboardbox\">\n          <PieChart type=\"dashboard\" dataSource={dataSource} loading={loading} dictionary={this.props?.dictionary?.health} />\n        </div>\n      </Spin>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/dashboard/components/pieCharts/pieChart.tsx",
    "content": "import React from \"react\";\nimport LineChart from \"../echarts\";\nimport { NavRouterLink } from \"container/custom-component\";\nimport { createOption } from \"./constants\";\nimport InfoTooltip from \"component/infoTooltip\";\nimport \"./index.less\";\n\ninterface IProps {\n  type: string;\n  dataSource: {\n    greenNum: number;\n    greenPercent: number;\n    greenClusterList: string[];\n    redClusterList: string[];\n    redNum: number;\n    redPercent: number;\n    timestamp: number;\n    totalNum: number;\n    unknownClusterList: string[];\n    unknownNum: number;\n    unknownPercent: number;\n    yellowClusterList: string[];\n    yellowNum: number;\n    yellowPercent: number;\n  };\n  loading?: boolean;\n  dictionary?: any;\n}\n\nconst imgSrc = require(\"./../../../../assets/empty.png\");\n\nexport class PieChart extends React.Component<IProps> {\n  className: string;\n  textStyle: any;\n  public constructor(props: IProps) {\n    super(props);\n    this.className = `${this.props.type}-piechart`;\n    this.textStyle = {\n      fontFamily: \"PingFangSC-Regular\",\n      fontSize: 12,\n      color: \"#495057\",\n      letterSpacing: 0,\n      textAlign: \"justify\",\n      lineHeight: \"20px\",\n    };\n  }\n\n  public state = {\n    chartKey: \"red\",\n  };\n\n  public clickChart = (key: string) => {\n    this.setState({ chartKey: key });\n  };\n\n  public renderChart = () => {\n    const { dataSource } = this.props;\n    let data = [\n      { value: dataSource?.greenNum || 0, name: \"健康集群\", prrcent: dataSource?.greenPercent, key: \"green\" },\n      { value: dataSource?.yellowNum || 0, name: \"预警集群\", prrcent: dataSource?.yellowPercent, key: \"yellow\" },\n      { value: dataSource?.redNum || 0, name: \"故障集群\", prrcent: dataSource?.redPercent, key: \"red\" },\n      { value: dataSource?.unknownNum || 0, name: \"未知集群\", prrcent: dataSource?.unknownPercent, key: \"unknown\" },\n    ];\n    const options = createOption(data, this.state.chartKey);\n    return (\n      <div style={{ margin: \"31px 30px 0 0\", float: \"left\" }}>\n        <LineChart isResize={true} width={162} height={162} options={options} key=\"chart\" onClick={this.clickChart} />\n      </div>\n    );\n  };\n\n  public renderContent = (list: any) => {\n    let empty =\n      list.length === 0 ? (\n        <div className={`${this.className}-faulttask-content-empty`}>\n          <div className=\"img\">\n            <img src={imgSrc} />\n          </div>\n          <div>\n            <span>数据为空</span>\n          </div>\n        </div>\n      ) : null;\n    let content = (\n      <ul>\n        {(list || []).map((item: any, index: any) => {\n          return (\n            <li className={`${this.className}-faulttask-content-li`} key={index}>\n              <NavRouterLink\n                maxShowLength={28}\n                needToolTip\n                style={this.textStyle}\n                element={item}\n                href={`/indicators/cluster?cluster=${item}#overview`}\n              />\n            </li>\n          );\n        })}\n      </ul>\n    );\n    return (\n      <>\n        {!this.props.loading && empty}\n        {content}\n      </>\n    );\n  };\n\n  public renderGreenClusterList = () => {\n    const { dataSource } = this.props;\n    const list = dataSource?.greenClusterList || [];\n    return (\n      <div className={`${this.className}-faulttask`}>\n        <div className={`${this.className}-faulttask-icon`}>\n          <span className=\"icon iconfont icon-lv\" style={{ margin: \"0px 4px 0px 0px\", color: \"#34c28f\" }}></span>\n          <span className={`${this.className}-faulttask-icon-title`}>健康集群</span>\n        </div>\n        <div className={`${this.className}-faulttask-content`}>{this.renderContent(list)}</div>\n      </div>\n    );\n  };\n\n  public renderRedClusterList = () => {\n    const { dataSource } = this.props;\n    const list = dataSource?.redClusterList || [];\n    return (\n      <div className={`${this.className}-faulttask`}>\n        <div className={`${this.className}-faulttask-icon`}>\n          <svg className={`d1-layout-left-menus-icon`} style={{ margin: \"0px 4px 0px 0px\" }} aria-hidden=\"true\">\n            <use xlinkHref=\"#iconyijigaojing\"></use>\n          </svg>\n          <span className={`${this.className}-faulttask-icon-title`}>故障集群</span>\n        </div>\n        <div className={`${this.className}-faulttask-content`}>{this.renderContent(list)}</div>\n      </div>\n    );\n  };\n\n  public renderYellowClusterList = () => {\n    const { dataSource } = this.props;\n    const list = dataSource?.yellowClusterList || [];\n    return (\n      <div className={`${this.className}-faulttask`}>\n        <div className={`${this.className}-faulttask-icon`}>\n          <svg className={`d1-layout-left-menus-icon`} style={{ margin: \"0px 4px 0px 0px\" }} aria-hidden=\"true\">\n            <use xlinkHref=\"#iconerjigaojing\"></use>\n          </svg>\n          <span className={`${this.className}-faulttask-icon-title`}>预警集群</span>\n        </div>\n        <div className={`${this.className}-faulttask-content`}>{this.renderContent(list)}</div>\n      </div>\n    );\n  };\n\n  public renderUnknownClusterList = () => {\n    const { dataSource } = this.props;\n    const list = dataSource?.unknownClusterList || [];\n    return (\n      <div className={`${this.className}-faulttask`}>\n        <div className={`${this.className}-faulttask-icon`}>\n          <svg className={`d1-layout-left-menus-icon`} style={{ margin: \"0px 4px 0px 0px\" }} aria-hidden=\"true\">\n            <use xlinkHref=\"#iconweizhi\"></use>\n          </svg>\n          <span className={`${this.className}-faulttask-icon-title`}>未知集群</span>\n        </div>\n        <div className={`${this.className}-faulttask-content`}>{this.renderContent(list)}</div>\n      </div>\n    );\n  };\n\n  public renderList = () => {\n    let { chartKey } = this.state;\n    if (chartKey === \"unknown\") {\n      return this.renderUnknownClusterList();\n    } else if (chartKey === \"green\") {\n      return this.renderGreenClusterList();\n    } else if (chartKey === \"yellow\") {\n      return this.renderYellowClusterList();\n    }\n    return this.renderRedClusterList();\n  };\n\n  public renderTooltip = () => {\n    let { price, currentCalLogic, threshold } = this.props?.dictionary || {};\n    return <InfoTooltip className=\"health-tooltip\" price={price} currentCalLogic={currentCalLogic} threshold={threshold}></InfoTooltip>;\n  };\n\n  public render() {\n    return (\n      <div className={this.className}>\n        <div className={`${this.className}-header`}>\n          <div className={`${this.className}-header-title`}>集群健康状态{this.renderTooltip()}</div>\n        </div>\n        <div className={`${this.className}-header-content`} style={{ display: \"flex\" }}>\n          {this.renderChart()}\n          {this.renderList()}\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/dashboard/components/table/index.less",
    "content": ".dashboard-table-container {\n  height: 262px;\n  background: #fff;\n  // box-shadow: 0 2px 4px 0 rgba(0,0,0,0.01), 0 3px 6px 3px rgba(0,0,0,0.01), 0 2px 6px 0 rgba(0,0,0,0.03);\n  border-radius: 8px;\n  padding: 12px 16px 0px 16px;\n  position: relative;\n  .ant-spin-nested-loading {\n    height: 100%;\n    .ant-spin-container {\n      height: 100%;\n    }\n  }\n  .dashboard-table-title {\n    position: relative;\n    height: 22px;\n    line-height: 22px;\n    margin-bottom: 12px;\n    font-family: HelveticaNeue-Medium;\n    letter-spacing: 0.5px;\n    font-size: 14px;\n    color: #212529;\n    height: 22px;\n    line-height: 22px;\n\n    span {\n      font-size: 12px;\n      color: #495057;\n      letter-spacing: 0.43px;\n      margin: 0 3px;\n    }\n  }\n\n  .ant-table {\n    overflow-x: scroll;\n    overflow-y: hidden;\n    height: 193px;\n\n    .ant-table-thead > tr > th,\n    .ant-table-tbody > tr > td {\n      padding: 0px;\n      padding-left: 10px;\n    }\n\n    .ant-table-thead > tr > th {\n      height: 27px;\n      line-height: 27px;\n      background: #ebedef;\n    }\n\n    td {\n      color: #495057;\n    }\n  }\n\n  .ant-table-empty {\n    .ant-table-thead {\n      display: none !important;\n    }\n\n    .ant-table-tbody > tr > td {\n      border: none !important;\n    }\n  }\n\n  .ant-table-pagination.ant-pagination {\n    margin: 5px 0 0;\n    position: absolute;\n    bottom: -18px;\n    right: -12px;\n\n    .ant-pagination-prev {\n      height: 16px;\n      line-height: 16px;\n      margin-right: 0px;\n\n      .ant-pagination-item-link {\n        height: 16px;\n\n        svg {\n          width: 7px;\n        }\n      }\n    }\n\n    .ant-pagination-simple {\n      .ant-pagination-prev,\n      .ant-pagination-next,\n      .ant-pagination-jump-prev,\n      .ant-pagination-jump-next {\n        min-width: 24px;\n      }\n    }\n\n    .ant-pagination-simple-pager {\n      display: inline-block;\n      height: 16px;\n      margin-top: -2px;\n      margin-right: 0px;\n      color: #495057;\n\n      input {\n        width: 40px;\n        height: 14px;\n        border: 1px solid #ced4da;\n        margin-right: 7px;\n      }\n\n      .ant-pagination-slash {\n        margin: 0 7px 0 0;\n      }\n    }\n\n    .ant-pagination-next {\n      height: 16px;\n      line-height: 16px;\n      vertical-align: top;\n\n      .ant-pagination-item-link {\n        height: 16px;\n\n        svg {\n          width: 7px;\n        }\n      }\n    }\n  }\n\n  &-empty {\n    margin-top: 100px;\n    text-align: center;\n\n    img {\n      width: 60px;\n      height: 40px;\n      margin-bottom: 8px;\n    }\n\n    span {\n      font-family: PingFangSC-Regular;\n      font-size: 12px;\n      color: #919aac;\n      text-align: center;\n      line-height: 20px;\n      margin-left: -10px;\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/dashboard/components/table/index.tsx",
    "content": "import React from \"react\";\nimport { Spin, Table, Tooltip } from \"antd\";\nimport InfoTooltip from \"component/infoTooltip\";\nimport \"./index.less\";\n\ninterface ITableProps {\n  columns: any[];\n  dataSource: any[];\n  title: string;\n  isLoading: boolean;\n  tooltip?: JSX.Element | string;\n  unit?: string;\n  dictionary?: any;\n  metricType?: string;\n}\n\nconst imgSrc = require(\"./../../../../assets/empty.png\");\n\nconst TableCard = (props: ITableProps) => {\n  const { columns, dataSource = [], title, tooltip, unit, isLoading, dictionary } = props;\n\n  const renderTitle = () => {\n    let { price, currentCalLogic, threshold } = dictionary || {};\n    return (\n      <div className=\"dashboard-table-title\">\n        {title}\n        {unit && <span>{`(${dataSource.length}${unit})`}</span>}\n        {(price || currentCalLogic || threshold) && (\n          <InfoTooltip price={price} currentCalLogic={currentCalLogic} threshold={threshold}></InfoTooltip>\n        )}\n      </div>\n    );\n  };\n\n  return (\n    <div className=\"dashboard-table-container\">\n      <Spin spinning={isLoading || false}>\n        {renderTitle()}\n        {!isLoading &&\n          (dataSource.length ? (\n            <Table\n              columns={columns}\n              dataSource={dataSource}\n              rowClassName={(record, index) => {\n                return index & 1 ? \"even-row\" : \"\";\n              }}\n              pagination={\n                dataSource.length <= 6\n                  ? false\n                  : {\n                      simple: true,\n                      total: dataSource.length,\n                      pageSize: 6,\n                    }\n              }\n            />\n          ) : (\n            <div className={\"dashboard-table-container-empty\"}>\n              <div>\n                <img src={imgSrc} />\n              </div>\n              <div>\n                <span>数据为空</span>\n              </div>\n            </div>\n          ))}\n      </Spin>\n    </div>\n  );\n};\n\nexport default TableCard;\n"
  },
  {
    "path": "arius-console/src/container/dashboard/config.tsx",
    "content": "import React from \"react\";\nimport Cluster from \"./cluster\";\nimport Node from \"./node\";\nimport IndexView from \"./index-view\";\nimport { IMenuItem } from \"typesPath/base-types\";\nimport { unitMap, addChartTitle, colorList } from \"../indicators-kanban/config\";\nimport moment from \"moment\";\nimport { toFixedNum, bytesUnitFormatter, formatTime, formatDecimalPoint } from \"lib/utils\";\nimport { ECOption } from \"../indicators-kanban/components/line\";\nimport { NavRouterLink } from \"container/custom-component\";\nimport { Tooltip } from \"antd\";\n\nexport enum TAB_LIST_KEY {\n  Operation = \"operation\",\n  operate = \"operate\",\n}\n\nexport enum OPERATION_TAB_LIST_KEY {\n  cluster = \"cluster\",\n  index = \"index\",\n  node = \"node\",\n}\n\ninterface seriesType {\n  name: string;\n  data: number[] | { timestamp: number; value: number }[];\n}\nexport interface metricsContentsType {\n  metricsContentCells: { timeStamp: number; value: number }[];\n  name: string;\n  cluster?: string;\n}\n\nexport interface metricsType {\n  metricsContents: metricsContentsType[];\n  type: string;\n}\n\nexport const operationTabs = [\n  {\n    name: \"集群\",\n    key: OPERATION_TAB_LIST_KEY.cluster,\n    content: () => <Cluster />,\n  },\n  {\n    name: \"节点\",\n    key: OPERATION_TAB_LIST_KEY.node,\n    content: () => <Node />,\n  },\n  {\n    name: \"索引\",\n    key: OPERATION_TAB_LIST_KEY.index,\n    content: () => <IndexView />,\n  },\n];\n\nconst menuMap = new Map<string, IMenuItem>();\n\noperationTabs.forEach((d) => {\n  menuMap.set(d.key, d);\n});\n\nexport const OPERATION_MENU_MAP = menuMap;\n\ninterface lineOptionType {\n  title: string;\n  xAxisData: number[];\n  series: seriesType[];\n  unitMap?: { [key: string]: any };\n  isMoreDay?: boolean;\n  isMarkLine?: boolean;\n  color?: string[];\n  // isShowTooltipModal?: boolean,\n  // isShowTaskTooltipModal?: boolean,\n  isClusterLink?: boolean;\n  isNodeLink?: boolean;\n  isGatewayLink?: boolean;\n  metricsType?: string;\n  showLegend?: boolean;\n  clusterPhyName?: string[];\n  tooltip?: string;\n  linkWithSeriesName?: boolean;\n  cluster?: string;\n}\n\ninterface OptionType {\n  metrics: metricsType;\n  configData: any;\n  isMoreDay?: boolean;\n  isMarkLine?: boolean;\n  isClusterLink?: boolean;\n  showLegend?: boolean;\n  isGatewayLink?: boolean;\n  clusterPhyName?: string[];\n  linkWithSeriesName?: boolean;\n  isNodeLink?: boolean;\n}\n\n// 判断 ms 是否需要转换成 s，只判断峰值\nconst isConversion = (series) => {\n  return series.some((item) => {\n    return item.data.some((item) => {\n      if (typeof item == \"object\") {\n        if (item.value > 1000) {\n          return true;\n        }\n      }\n      return item > 1000;\n    });\n  });\n};\n\n// 图表 tooltip 展示位置\nconst tooltipPosition = (pos, params, dom, rect, size, showLegend) => {\n  const [x, y] = pos;\n  const [width, height] = size.viewSize;\n\n  let domHeight = (dom as any).offsetHeight;\n\n  if (domHeight > 350) {\n    domHeight = 250;\n  }\n\n  const domWidth = (dom as any).offsetWidth || 390;\n\n  const obj = { top: y - domHeight - 10 };\n\n  // showLegend 是否展示左侧 legend\n  const chartPosition = showLegend ? width - 40 : width / 2 - 20;\n  if (x > chartPosition) {\n    // 在鼠标左侧展示\n    obj[\"left\"] = x - domWidth - 10;\n  } else if (x + domWidth > width) {\n    // 右侧超出，设置固定位置\n    obj[\"right\"] = -50;\n  } else {\n    // 在鼠标右侧展示\n    obj[\"left\"] = x + 10;\n  }\n  return obj;\n};\n\n// 图表 tooltip 展示的样式\nconst tooltipFormatter = (params) => {\n  let { date, arr, unit, isClusterLink, metricsType, isGatewayLink, clusterPhyName, linkWithSeriesName, isNodeLink, cluster } = params;\n  // 新增从大到小排序\n  arr = arr.sort((a, b) => b.value - a.value);\n  const str = arr\n    .map((item: any, idx: number) => {\n      return `<div style=\"margin: 3px 0;line-height:1;\">\n        <div style=\"margin: 0px 0 0;line-height:1;\">\n        ${item.marker}\n        <span style=\"font-size:14px;color:#666;pointer-events: auto;font-weight:400;margin-left:2px;${\n          isClusterLink || isGatewayLink || isNodeLink ? \"cursor: pointer\" : \"\"\n        }\" \n          ${isClusterLink ? `onclick=\"window.clusterlink('${linkWithSeriesName ? item.seriesName : \"\"}','${item?.data?.cluster}')\"` : \"\"}\n          ${isNodeLink ? `onclick=\"window.nodelink('${linkWithSeriesName ? item.seriesName : \"\"}','${cluster}')\"` : \"\"}\n          ${isGatewayLink ? `onclick=\"window.gatewaylink('${linkWithSeriesName ? item.seriesName : \"\"}')\"}` : \"\"}>\n          <span title=所属集群：${item?.data?.cluster}>${item.seriesName}</span>\n          </span>\n          <span style=\"float:right;margin-left:20px;font-size:14px;color:#666;font-weight:900\">\n            ${item.value > 10000 ? toFixedNum(item.value / 10000, 2) + \"W\" : item.value} ${unit || \"\"}\n          </span>\n          <div style=\"clear:both\"></div>\n        </div>\n        <div style=\"clear:both\"></div>\n      </div>\n    <div style=\"clear:both\"></div>`;\n    })\n    .join(\"\");\n\n  return `<div style=\"margin: 0px 0 0;line-height:1; position: relative; z-index: 99;\">\n    <div style=\"margin: 0px 0 0;line-height:1;\">\n      <div style=\"font-size:14px;color:#666;font-weight:400;line-height:1;\">\n        ${date}\n      </div>\n      <div style=\"margin: 10px 0 0;line-height:1;max-height: 252px; overflow: scroll\">\n        ${str}\n      </div>\n      <div style=\"clear:both\"></div>\n    </div>\n  </div>`;\n};\n\nexport const getLineOption = ({\n  title,\n  xAxisData,\n  series,\n  // 单位名称，单位格式化\n  unitMap,\n  // 是否大于一天\n  isMoreDay = false,\n  // 是否展示警戒线\n  isMarkLine = false,\n  color = colorList,\n  // 是否跳转到集群看板\n  isClusterLink = false,\n  // 是否跳转到节点视图\n  isNodeLink = false,\n  // 是否跳转到网关看板\n  isGatewayLink = false,\n  // 后端图表指标名称，帮助弹窗获取数据\n  metricsType,\n  // 是否显示左侧 legend\n  showLegend = true,\n  clusterPhyName = [],\n  // 跳转是否需要精确到具体维度，比如节点/索引\n  linkWithSeriesName,\n  cluster,\n}: lineOptionType) => {\n  let seriesData;\n  let unitFormatter = unitMap?.formatter;\n  let unitName = unitMap?.name;\n\n  if (unitFormatter) {\n    // 根据数值大小判断单位是否需要进行转换\n    if (unitName === \"ms\" && isConversion(series)) {\n      unitFormatter = (num) => {\n        let val = Number(num);\n        return toFixedNum(val / 1000, 3);\n      };\n      unitName = \"s\";\n      title = title.replace(\"ms\", \"s\");\n    }\n    seriesData = series.map((item: any) => ({\n      name: item?.name || \"\",\n      data: item?.data.map((el) => {\n        if (typeof el == \"object\") {\n          return {\n            timestamp: el.timestamp,\n            value: unitFormatter(el.value),\n            cluster: el?.cluster || \"\",\n          };\n        }\n        return unitFormatter(el);\n      }),\n      type: \"line\",\n      // markLine: isMarkLine ? markLine() : {},\n      showSymbol: false,\n    }));\n  } else {\n    seriesData = series.map((item) => ({\n      ...item,\n      type: \"line\",\n      // markLine: isMarkLine ? markLine() : {},\n      showSymbol: false,\n    }));\n  }\n  return {\n    color: color,\n    title: {\n      text: title,\n      show: false,\n    },\n    tooltip: {\n      trigger: \"axis\",\n      enterable: true,\n      position: (pos, params, dom, rect, size) => {\n        return tooltipPosition(pos, params, dom, rect, size, showLegend);\n      },\n      extraCssText: \"z-index: 101\",\n      formatter: (params: any) => {\n        let res = \"\";\n        if (params != null && params.length > 0) {\n          let formatterParams = {\n            date: moment(Number(params[0].name)).format(\"YYYY-MM-DD HH:mm\"),\n            arr: params,\n            unit: unitName,\n            isClusterLink,\n            metricsType,\n            isGatewayLink,\n            clusterPhyName,\n            linkWithSeriesName,\n            isNodeLink,\n            cluster,\n          };\n          res += tooltipFormatter(formatterParams);\n        }\n        return res;\n      },\n    },\n    legend: showLegend\n      ? {\n          type: \"scroll\",\n          left: \"45\",\n          bottom: \"5\",\n          icon: \"rect\",\n          itemHeight: 2,\n          itemWidth: 14,\n          textStyle: {\n            width: 85,\n            overflow: \"truncate\",\n            ellipsis: \"...\",\n            fontSize: 11,\n            color: \"#74788D\",\n          },\n          padding: [\n            8, // 上\n            20, // 右\n            6, // 下\n            5, // 左\n          ],\n          pageIcons: {\n            horizontal: [\n              \"path://M474.496 512l151.616 151.616a9.6 9.6 0 0 1 0 13.568l-31.68 31.68a9.6 9.6 0 0 1-13.568 0l-190.08-190.08a9.6 9.6 0 0 1 0-13.568l190.08-190.08a9.6 9.6 0 0 1 13.568 0l31.68 31.68a9.6 9.6 0 0 1 0 13.568L474.496 512z\",\n              \"path://M549.504 512L397.888 360.384a9.6 9.6 0 0 1 0-13.568l31.68-31.68a9.6 9.6 0 0 1 13.568 0l190.08 190.08a9.6 9.6 0 0 1 0 13.568l-190.08 190.08a9.6 9.6 0 0 1-13.568 0l-31.68-31.68a9.6 9.6 0 0 1 0-13.568L549.504 512z\",\n            ],\n            pageIconColor: \"#495057\",\n            pageIconInactiveColor: \"#ADB5BC\",\n          },\n          pageTextStyle: {\n            width: 8,\n            color: \"#495057\",\n            fontSize: 11,\n          },\n          pageIconSize: [4, 7],\n          pageButtonItemGap: 10,\n          pageFormatter: \"{current} / {total}\",\n          tooltip: {\n            show: true,\n          },\n        }\n      : null,\n    grid: {\n      left: 16,\n      right: 16,\n      bottom: showLegend ? 37 : 10,\n      containLabel: true,\n    },\n    xAxis: {\n      type: \"category\",\n      boundaryGap: true,\n      data: [...xAxisData],\n      axisTick: {\n        alignWithLabel: true,\n        lineStyle: {\n          color: \"#e9e9ea\",\n        },\n      },\n      axisLine: {\n        lineStyle: {\n          color: \"#e9e9ea\",\n        },\n      },\n      fontFamily: \"HelveticaNeue\",\n      axisLabel: {\n        color: \"#495057\",\n        formatter: (value: number) => {\n          value = Number(value);\n          return \"{a|\" + moment(value).format(\"MM-DD\") + \"}\\n\" + \"{b|\" + moment(value).format(\"HH:mm\") + \"}\";\n        },\n        rich: {\n          a: {\n            lineHeight: 16,\n            color: \"#495057\",\n          },\n          b: {\n            color: \"#ADB5BC\",\n          },\n        },\n      },\n    },\n    yAxis: {\n      type: \"value\",\n      splitLine: {\n        lineStyle: {\n          type: \"dashed\",\n          color: \"#e9e9ea\",\n        },\n      },\n      axisLabel: {\n        showMaxLabel: true,\n        formatter: function (value) {\n          if (value < 10000) {\n            return value;\n          }\n          return (value / 10000).toFixed(1) + \"W\";\n        },\n      },\n    },\n    series: [...seriesData],\n    animation: false,\n  } as ECOption;\n};\n\nexport const getOption = ({\n  metrics,\n  configData,\n  isMoreDay = false,\n  isMarkLine = false,\n  isClusterLink = false,\n  showLegend = true,\n  isGatewayLink = false,\n  clusterPhyName = [],\n  linkWithSeriesName = true,\n  isNodeLink = false,\n}: OptionType) => {\n  if (!metrics || !metrics.type) {\n    return {};\n  }\n\n  const title = (configData[metrics.type] && configData[metrics.type].title()) || metrics.type;\n\n  const xAxisData = [];\n  const series = metrics.metricsContents.map((content, index) => ({\n    name: content.name,\n    data: content.metricsContentCells\n      .sort((a, b) => a.timeStamp - b.timeStamp)\n      .map((item) => {\n        if (index === 0) {\n          xAxisData.push(item.timeStamp);\n        }\n        return {\n          value: item.value,\n          timestamp: item.timeStamp,\n          cluster: content?.cluster || \"\",\n        };\n      }),\n  }));\n  return getLineOption({\n    title,\n    xAxisData,\n    series,\n    unitMap: configData[metrics.type]?.unit,\n    isMoreDay,\n    isMarkLine,\n    isClusterLink,\n    metricsType: metrics.type,\n    showLegend,\n    clusterPhyName,\n    isGatewayLink,\n    linkWithSeriesName,\n    isNodeLink,\n    cluster: metrics?.metricsContents[0]?.cluster,\n  });\n};\n\nexport const clusterMetrics = {\n  health: {\n    name: \"集群健康状态\",\n    unit: unitMap.none,\n    type: \"pie\",\n    fixed: true,\n  },\n  searchLatency: {\n    name: \"查询耗时\",\n    unit: unitMap.ms,\n  },\n  indexingLatency: {\n    name: \"写入耗时\",\n    unit: unitMap.ms,\n  },\n  shardNum: {\n    name: \"shard个数大于10000集群列表\",\n    width: \"33%\",\n    columns: [\n      {\n        title: \"集群名称\",\n        dataIndex: \"clusterPhyName\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              <NavRouterLink\n                needToolTip\n                style={{\n                  fontFamily: \"PingFangSC-Regular\",\n                  fontSize: 12,\n                  color: \"#495057\",\n                  letterSpacing: 0,\n                  textAlign: \"justify\",\n                  lineHeight: \"20px\",\n                }}\n                element={text}\n                href={`/indicators/cluster?cluster=${record.clusterPhyName}&overview=${text}&#overview`}\n              />\n            </div>\n          );\n        },\n      },\n      {\n        title: \"shard个数\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (val: number) => val || \"-\",\n      },\n      {\n        title: \"索引个数\",\n        dataIndex: \"indexCount\",\n        width: \"33%\",\n        render: (val: number) => val || \"-\",\n      },\n    ],\n  },\n  pendingTaskNum: {\n    name: \"集群pending task数\",\n    unit: unitMap.count,\n  },\n  gatewayFailedPer: {\n    name: \"网关失败率\",\n    unit: unitMap.percent,\n  },\n  nodeElapsedTime: {\n    name: \"nodes_stats 接口平均采集耗时\",\n    unit: unitMap.s,\n  },\n  clusterElapsedTimeGte5Min: {\n    name: \"指标采集延时大于5分钟集群列表\",\n    unit: unitMap.none,\n    columns: [\n      {\n        title: \"集群名称\",\n        dataIndex: \"clusterPhyName\",\n        width: \"50%\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              <NavRouterLink\n                needToolTip\n                style={{\n                  fontFamily: \"PingFangSC-Regular\",\n                  fontSize: 12,\n                  color: \"#495057\",\n                  letterSpacing: 0,\n                  textAlign: \"justify\",\n                  lineHeight: \"20px\",\n                }}\n                element={text}\n                href={`/indicators/cluster?cluster=${record.clusterPhyName}&overview=${text}&#overview`}\n              />\n            </div>\n          );\n        },\n      },\n      {\n        title: \"采集延时\",\n        dataIndex: \"value\",\n        width: \"50%\",\n        render: (val: number) => formatTime(val) || \"-\",\n      },\n    ],\n  },\n};\n\naddChartTitle(clusterMetrics);\n\nconst typeMap = {\n  index: \"索引\",\n  node: \"节点\",\n  template: \"索引模板\",\n};\nexport const columns = (width, type: string = \"index\", disabled: boolean = false) => [\n  {\n    title: `${typeMap[type]}名称`,\n    dataIndex: \"name\",\n    key: \"clusterPhynameName\",\n    ellipsis: true,\n    width,\n    render: (text, record) => {\n      return (\n        <div\n          style={{\n            whiteSpace: \"nowrap\",\n            overflow: \"hidden\",\n            textOverflow: \"ellipsis\",\n            height: 26,\n            lineHeight: \"26px\",\n            width: \"90%\",\n          }}\n        >\n          {disabled ? (\n            text\n          ) : (\n            <NavRouterLink\n              // maxShowLength={20}\n              needToolTip\n              style={{\n                fontFamily: \"PingFangSC-Regular\",\n                fontSize: 12,\n                color: \"#495057\",\n                letterSpacing: 0,\n                textAlign: \"justify\",\n                lineHeight: \"20px\",\n              }}\n              element={text}\n              href={`/indicators/cluster?cluster=${record.clusterPhyName}&${type}=${text}&#${type}`}\n            />\n          )}\n        </div>\n      );\n    },\n  },\n  {\n    title: \"所属集群\",\n    dataIndex: \"clusterPhyName\",\n    key: \"clusterPhyName\",\n    ellipsis: true,\n    width,\n    render: (text, record) => {\n      return (\n        <div\n          style={{\n            whiteSpace: \"nowrap\",\n            overflow: \"hidden\",\n            textOverflow: \"ellipsis\",\n            height: 26,\n            lineHeight: \"26px\",\n            width: \"90%\",\n          }}\n        >\n          <Tooltip title={typeof text == \"number\" ? text.toFixed(2) : text} placement=\"bottomLeft\">\n            {typeof text == \"number\" ? text.toFixed(2) : text}\n          </Tooltip>\n        </div>\n      );\n    },\n  },\n];\n\nexport const indexViewMetrics = {\n  segmentNum: {\n    name: \"索引Segments个数\",\n    //tooltip: \"索引Segments个数超过阀值100才显示\",\n    unit: unitMap.ms,\n    columns: [\n      ...columns(\"33%\"),\n      {\n        title: \"Segments个数\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              {text}\n            </div>\n          );\n        },\n      },\n    ],\n  },\n  tplSegmentMemSize: {\n    name: \"索引模板Segments内存大小（MB）\",\n    //tooltip: \"索引模版Segments内存大小超过阀值才显示\",\n    unit: unitMap.ms,\n    as: \"segmentMemSize\",\n    columns: [\n      ...columns(\"33%\", \"template\"),\n      {\n        title: \"内存大小\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              {bytesUnitFormatter(text) || \"\"}\n            </div>\n          );\n        },\n      },\n    ],\n  },\n  unassignedShard: {\n    name: \"未分配shard索引列表\",\n    unit: unitMap.ms,\n    columns: columns(\"50%\"),\n  },\n  tplSegmentNum: {\n    name: \"索引模板Segments个数\",\n    //tooltip: \"索引模版Segments个数超过阀值1000才显示\",\n    unit: unitMap.ms,\n    as: \"segmentNum\",\n    columns: [\n      ...columns(\"33%\", \"template\"),\n      {\n        title: \"Segments个数\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              {text}\n            </div>\n          );\n        },\n      },\n    ],\n  },\n  mappingNum: {\n    name: \"索引Mapping字段个数\",\n    //tooltip: \"索引Mapping个数超过100再显示\",\n    unit: unitMap.ms,\n    columns: [\n      ...columns(\"33%\"),\n      {\n        title: \"Mapping字段个数\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              {text}\n            </div>\n          );\n        },\n      },\n    ],\n  },\n  bigShard: {\n    name: \"单个shard大于50G索引列表\",\n    unit: unitMap.ms,\n    //tooltip: \"大于50G为大shard\",\n    columns: [\n      ...columns(\"33%\"),\n      {\n        title: \"索引存储大小\",\n        dataIndex: \"value\",\n        key: \"value\",\n        width: \"33%\",\n        render: (val) => {\n          return bytesUnitFormatter(val);\n        },\n      },\n    ],\n  },\n  smallShard: {\n    name: \"单个shard小于500MB索引列表\",\n    //name: \"小shard索引列表\",\n    unit: unitMap.ms,\n    // tooltip: \"小shard索引列表，shard个数大于1才显示\",\n    columns: [\n      ...columns(\"33%\"),\n      {\n        title: \"索引存储大小\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (val) => {\n          return bytesUnitFormatter(val);\n        },\n      },\n    ],\n  },\n  segmentMemSize: {\n    name: \"索引Segments内存大小（MB）\",\n    // tooltip: \"索引Segments内存大小超过阀值才显示\",\n    unit: unitMap.ms,\n    columns: [\n      ...columns(\"33%\"),\n      {\n        title: \"内存大小\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              {bytesUnitFormatter(text)}\n            </div>\n          );\n        },\n      },\n    ],\n  },\n  singReplicate: {\n    name: \"无副本索引列表\",\n    unit: unitMap.ms,\n    columns: columns(\"50%\"),\n  },\n  red: {\n    name: \"RED索引列表\",\n    unit: unitMap.none,\n    columns: columns(\"50%\"),\n  },\n};\n\naddChartTitle(indexViewMetrics);\n\nexport const nodeMetrics = {\n  taskConsuming: {\n    name: \"节点执行任务耗时\",\n    unit: unitMap.s,\n    as: \"taskConsuming\",\n  },\n  shardNum: {\n    name: \"节点分片个数列表\",\n    //tooltip: \"节点分片个数>500才显示\",\n    unit: unitMap.ms,\n    columns: [\n      ...columns(\"33%\", \"node\"),\n      {\n        title: \"分片个数\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              {text}\n            </div>\n          );\n        },\n      },\n    ],\n  },\n  largeDiskUsage: {\n    name: \"磁盘利用率超红线节点列表\",\n    unit: unitMap.ms,\n    tooltip: \"磁盘利用率超85%为超红线\",\n    columns: [\n      ...columns(\"33%\", \"node\"),\n      {\n        title: \"磁盘利用率\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              {formatDecimalPoint(text)}%\n            </div>\n          );\n        },\n      },\n    ],\n  },\n  largeHead: {\n    name: \"堆内存利用率超红线节点列表\",\n    unit: unitMap.ms,\n    tooltip: \"堆内存利用率超80%且持续5min为超红线\",\n    columns: [\n      ...columns(\"33%\", \"node\"),\n      {\n        title: \"堆内存利用率\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              {formatDecimalPoint(text)}%\n            </div>\n          );\n        },\n      },\n    ],\n  },\n  writeRejectedNum: {\n    name: \"WriteRejected节点列表\",\n    unit: unitMap.ms,\n    columns: columns(\"50%\", \"node\"),\n  },\n  searchRejectedNum: {\n    name: \"SearchRejected节点列表\",\n    unit: unitMap.ms,\n    columns: columns(\"50%\", \"node\"),\n  },\n  largeCpuUsage: {\n    name: \"CPU利用率超红线节点列表\",\n    unit: unitMap.ms,\n    tooltip: \"CPU利用率超80%且持续30min为超红线\",\n    columns: [\n      ...columns(\"33%\", \"node\"),\n      {\n        title: \"CPU利用率\",\n        dataIndex: \"value\",\n        width: \"33%\",\n        render: (text, record) => {\n          return (\n            <div\n              style={{\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"ellipsis\",\n                height: 26,\n                lineHeight: \"26px\",\n                width: \"90%\",\n              }}\n            >\n              {formatDecimalPoint(text)}%\n            </div>\n          );\n        },\n      },\n    ],\n  },\n};\n\naddChartTitle(nodeMetrics);\n"
  },
  {
    "path": "arius-console/src/container/dashboard/index-view.tsx",
    "content": "import React, { useState, useEffect, useRef, useContext } from \"react\";\nimport { SyncOutlined } from \"@ant-design/icons\";\nimport { MetricsConfig } from \"./components/metricsConfig\";\nimport { getOption, indexViewMetrics } from \"./config\";\nimport { ILineParams, indexLine, indexList, setCheckedList, getCheckedList, templatelist } from \"api/dashboard\";\nimport TableCard from \"./components/table\";\nimport \"./index.less\";\nimport { cloneDeep } from \"lodash\";\nimport DragGroup from \"../../d1-packages/drag-group/DragGroup\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport { Line } from \"./components/line\";\nimport { withRouter } from \"react-router-dom\";\nimport { connect } from \"react-redux\";\nimport { CustomTimeRangePicker } from \"component/TimeRangePicker\";\nimport { DashboardContext } from \"./Operation\";\n\nconst ONE_HOUR = 1000 * 60 * 60;\n\nconst mapStateToProps = (state) => ({\n  dashboard: state.dashBoard,\n});\n\nconst IndexView = withRouter((props: any) => {\n  const dictionary = useContext(DashboardContext);\n\n  const currentTime = new Date().getTime();\n  const [rangeTime, setRangeTime] = useState([currentTime - ONE_HOUR, currentTime]);\n\n  const [loading, setLoading] = useState(Object.keys(indexViewMetrics));\n  const [metrics, setMetrics] = useState(Object.keys(indexViewMetrics));\n  const [data, setData] = useState({});\n  const [listData, setListData] = useState({});\n  const [isLoading, setIsLoading] = useState(false);\n  const [metricsLoading, setMetricsLoading] = useState(false);\n  const [indexViewInfo, setIndexViewInfo] = useState(null);\n  const topN = useRef({});\n  const customTimeRef = useRef(null);\n\n  const handleTimeChange = (times: number[], isCustomTime = false) => {\n    setRangeTime(times);\n  };\n\n  const reload = () => {\n    if (metricsLoading) return;\n\n    getLineData();\n    getListData();\n    getTplListData();\n  };\n\n  const setIndexConfigCheckedData = (checkvalue) => {\n    setMetrics(checkvalue);\n    setCheckedList(\"index\", checkvalue);\n  };\n\n  const sortMetrics = () => {\n    const left = metrics.map((item) => ({ name: indexViewMetrics[item]?.name, value: item }));\n    const right = [];\n    Object.keys(indexViewMetrics).forEach((item) => {\n      if (!metrics.includes(item)) {\n        right.push({ name: indexViewMetrics[item]?.name, value: item });\n      }\n    });\n    return [...left, ...right];\n  };\n\n  // 增加点击刷新按钮先计算时间差 保持用户选择的事件范围\n  const handleReload = () => {\n    customTimeRef?.current?.refresh();\n  };\n\n  const renderConfig = () => {\n    return (\n      <div className=\"dashboard-config\">\n        <SyncOutlined spin={isLoading} className=\"dashboard-config-icon\" onClick={() => handleReload()} />\n        <span className=\"dashboard-config-line\"></span>\n        <CustomTimeRangePicker ref={customTimeRef} onChange={handleTimeChange} />\n        <MetricsConfig title=\"索引\" value={metrics} optionList={sortMetrics()} defaultCheckedData={[]} cb={setIndexConfigCheckedData} />\n      </div>\n    );\n  };\n\n  const getLineData = async (topNu?: number, metricsTypes?: string[]) => {\n    //获取线性图标数据，通过columns，有columns代表是表格\n    const lineMetrics = [];\n    metrics.forEach((item) => {\n      if (indexViewMetrics && indexViewMetrics[item].columns) {\n        return;\n      }\n      lineMetrics.push(item);\n    });\n    const params: ILineParams = {\n      metricsTypes: metricsTypes || lineMetrics,\n      // 目前固定为avg\n      aggType: \"avg\",\n      startTime: rangeTime[0],\n      endTime: rangeTime[1],\n      topNu: topNu || 5,\n    };\n    if (!params.metricsTypes.length) {\n      return;\n    }\n    try {\n      setIsLoading(true);\n      setLoading((state) => [...state, ...(metricsTypes || lineMetrics)]);\n      const metricsList = await indexLine(params);\n      if (!metricsList || metricsList.length === 0) {\n        setData({});\n        return;\n      }\n      if (metricsTypes) {\n        // 如果传入指标就不初始化data直接在这里return\n        const cloneData = cloneDeep(data);\n        metricsList.forEach((item) => {\n          cloneData[item.type] = getOption({\n            metrics: item,\n            configData: indexViewMetrics,\n            isClusterLink: true,\n            clusterPhyName: (item.metricsContents || []).map((v) => v.cluster),\n          });\n        });\n        setIsLoading(false);\n        setLoading((state) => state.filter((item) => !(metricsTypes || lineMetrics).includes(item)));\n        setData(cloneData);\n        return;\n      }\n      const datas = {};\n      metricsList.forEach((item) => {\n        datas[item.type] = getOption({\n          metrics: item,\n          configData: indexViewMetrics,\n          isClusterLink: true,\n          clusterPhyName: (item.metricsContents || []).map((v) => v.cluster),\n        });\n      });\n      setIsLoading(false);\n      setLoading((state) => state.filter((item) => !(metricsTypes || lineMetrics).includes(item)));\n      setData(datas);\n    } catch (error) {\n      setIsLoading(false);\n      setLoading([]);\n      console.log(\"render line\", error);\n    } finally {\n      // setIsLoading(false);\n    }\n  };\n\n  const getTplListData = async () => {\n    setIsLoading(true);\n    const datas = {};\n    const TplListMetrics = [];\n    const loadingList = [];\n    metrics.forEach((item) => {\n      if (indexViewMetrics && indexViewMetrics[item].columns) {\n        if (indexViewMetrics[item].as) {\n          TplListMetrics.push(indexViewMetrics[item].as);\n          loadingList.push(item);\n        }\n      }\n    });\n    if (TplListMetrics && TplListMetrics.length === 0) {\n      return;\n    }\n    setLoading((state) => [...state, ...loadingList]);\n    const TplParams: any = {\n      metricsTypes: TplListMetrics,\n      aggType: \"avg\",\n      orderByDesc: true,\n    };\n    try {\n      const tplMetricsList = await templatelist(TplParams);\n      if (!tplMetricsList || tplMetricsList.length === 0) {\n        // setListData({});\n        setLoading((state) => state.filter((item) => !loadingList.includes(item)));\n        return;\n      }\n      metrics.forEach((item) => {\n        tplMetricsList.forEach((v) => {\n          if (indexViewMetrics[item].as === v.type) {\n            datas[item] = v;\n          }\n        });\n      });\n      setListData((state) => ({ ...state, ...datas }));\n      setIsLoading(false);\n      setLoading((state) => state.filter((item) => !loadingList.includes(item)));\n    } catch (err) {\n      console.log(err);\n    }\n  };\n\n  const getListData = async () => {\n    const ListMetrics = [];\n    metrics.forEach((item) => {\n      if (indexViewMetrics && indexViewMetrics[item].columns) {\n        if (!indexViewMetrics[item].as) {\n          if (item != \"smallShard\") {\n            ListMetrics.push(item);\n          }\n        }\n      }\n    });\n    if (ListMetrics && ListMetrics.length === 0) {\n      return;\n    }\n    const params: any = {\n      metricsTypes: ListMetrics,\n      aggType: \"avg\",\n      orderByDesc: true,\n    };\n    const smallShardParams: any = {\n      metricsTypes: [\"smallShard\"],\n      aggType: \"avg\",\n      orderByDesc: false,\n    };\n\n    try {\n      setIsLoading(true);\n      setLoading((state) => [...state, ...ListMetrics]);\n      const datas = {};\n      const metricsList = await indexList(params);\n      if (metrics.includes(\"smallShard\")) {\n        const smallShardMetricsList = await indexList(smallShardParams);\n        metricsList.push(...smallShardMetricsList);\n        ListMetrics.push(\"smallShard\");\n      }\n      if (!metricsList || metricsList.length === 0) {\n        // setListData({});\n        setLoading((state) => state.filter((item) => !ListMetrics.includes(item)));\n        return;\n      }\n      metricsList.forEach((item) => {\n        datas[item.type] = item;\n      });\n      setListData((state) => ({ ...state, ...datas }));\n      setIsLoading(false);\n      setLoading((state) => state.filter((item) => !ListMetrics.includes(item)));\n    } catch (error) {\n      setIsLoading(false);\n      setLoading([]);\n      console.log(\"render line\", error);\n    } finally {\n      // setIsLoading(false);\n    }\n  };\n\n  const sortEnd = ({ oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(metrics, oldIndex, newIndex);\n    setCheckedList(\"index\", listsNew);\n    setMetrics(listsNew);\n  };\n\n  const renderContent = () => {\n    return (\n      <DragGroup\n        dragContainerProps={{\n          onSortEnd: (args) => sortEnd({ ...args }),\n          axis: \"xy\",\n          distance: 100,\n        }}\n        containerProps={{\n          grid: 8,\n          gutter: [12, 12],\n        }}\n      >\n        {metrics.map((item: any, i) => {\n          // console.log(\"--dictionary?.indexData?.[item]\", dictionary?.indexData, item);\n          if (indexViewMetrics[item]?.columns) {\n            let list = listData[item]?.metricListContents;\n            let dataSource = (list || []).map((item) => {\n              return {\n                ...item,\n                key: `${item.clusterPhyName}-${item.name}`,\n              };\n            });\n            return (\n              <TableCard\n                columns={indexViewMetrics[item]?.columns}\n                dataSource={dataSource}\n                title={indexViewMetrics[item]?.name}\n                // unit={item.unit}\n                isLoading={loading.includes(item)}\n                key={item}\n                dictionary={dictionary?.indexData?.[item]}\n              />\n            );\n          }\n          return (\n            <Line\n              title={data[item]?.title?.text || indexViewMetrics[item]?.title()}\n              index={item}\n              key={item}\n              option={data[item] || {}}\n              isLoading={loading.includes(item)}\n              cb={getLineData}\n              topN={topN}\n              dictionary={dictionary?.indexData?.[item]}\n            />\n          );\n        })}\n      </DragGroup>\n    );\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      setMetricsLoading(true);\n      const checkedList = await getCheckedList(\"index\");\n      if (!checkedList || checkedList.length === 0) {\n        setMetrics(metrics);\n      } else {\n        // 以下需暂时过滤掉\n        const filterList = [\"reqUprushNum\", \"docUprushNum\"];\n        setMetrics(checkedList.filter((item) => filterList.indexOf(item) === -1));\n      }\n    } catch (error) {\n      setMetrics(metrics);\n      console.log(\"cluster-kanban node-view 获取配置下项失败\", error);\n    } finally {\n      setMetricsLoading(false);\n    }\n  };\n\n  const linkToClusterPage = () => {\n    window[\"clusterlink\"] = (index: string, clusterName: string) => {\n      props.history.push(`/indicators/cluster?cluster=${clusterName}&index=${index}#index`);\n    };\n  };\n\n  const setDymanicMetrics = () => {\n    if (props.dashboard?.dymanicConfigMetrics?.length) {\n      const res = props.dashboard?.dymanicConfigMetrics;\n      res.forEach((item) => {\n        try {\n          const itemValue = JSON.parse(item.value);\n          switch (item.valueName) {\n            case \"index.segment.num_threshold\":\n              //name: \"索引Segments个数\",\n              indexViewMetrics.segmentNum.name = `segments个数大于${itemValue.value ?? \"\"}索引列表`;\n              break;\n            case \"index.mapping.num_threshold\":\n              //name: \"索引Mapping字段个数\",\n              indexViewMetrics.mappingNum.name = `mapping字段个数大于${itemValue.value ?? \"\"}索引列表`;\n              break;\n            case \"index.template.segment_num_threshold\":\n              //name: \"索引模板Segments个数\",\n              indexViewMetrics.tplSegmentNum.name = `segments个数大于${itemValue.value ?? \"\"}索引模版列表`;\n              break;\n            case \"index.segment.memory_size_threshold\":\n              //name: \"索引Segments内存大小（MB）\",\n              indexViewMetrics.segmentMemSize.name = `segments内存大于${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}索引列表`;\n              break;\n            case \"index.template.segment_memory_size_threshold\":\n              //name: \"索引模板Segments内存大小（MB）\",\n              indexViewMetrics.tplSegmentMemSize.name = `segments内存大于${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}索引模版列表`;\n              break;\n            case \"index.shard.small_threshold\":\n              //小Shard列表阈值定义\n              indexViewMetrics.smallShard.name = `单个shard小于${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}索引列表`;\n              break;\n            case \"index.shard.big_threshold\":\n              //index.shard.big_threshold\n              indexViewMetrics.bigShard.name = `单个shard大于${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}索引列表`;\n            default:\n              break;\n          }\n        } catch (error) {\n          console.log(error, `JSON.parse解析${item?.valueName}错误，请检查动态配置中配置项书写格式`);\n        }\n      });\n    }\n  };\n  // 加载选中配置\n  useEffect(() => {\n    linkToClusterPage();\n    getAsyncCheckedList();\n    setDymanicMetrics();\n    setIndexViewInfo(indexViewMetrics);\n  }, []);\n\n  useEffect(() => {\n    setDymanicMetrics();\n  }, [props.dashboard?.dymanicConfigMetrics]);\n\n  useEffect(() => {\n    reload();\n  }, [rangeTime, metrics]);\n\n  return (\n    <div className=\"dashboard-index-view\">\n      {renderConfig()}\n      {renderContent()}\n    </div>\n  );\n});\n\nexport default connect(mapStateToProps, null)(IndexView);\n"
  },
  {
    "path": "arius-console/src/container/dashboard/index.less",
    "content": ".dashboard {\n  position: relative;\n  background-image: linear-gradient(180deg, #f5f7fa 2%, #f5f7fa 86%);\n  padding: 16px 10px 16px 20px;\n  border-radius: 8px;\n  min-width: 1210px;\n\n  &-changepage {\n    position: absolute;\n    top: 24px;\n    right: 20px;\n    height: 27px;\n    width: 82px;\n    border-radius: 4px;\n    padding: 4px 0px 4px 8px;\n    user-select: none;\n    cursor: pointer;\n\n    &-text {\n      font-family: PingFangSC-Regular;\n      font-size: 13px;\n      color: #ffffff;\n      text-align: left;\n      line-height: 20px;\n    }\n\n    &-icon {\n      font-size: 12px;\n      color: #ffffff;\n    }\n  }\n\n  .ant-spin-blur {\n    opacity: 1;\n  }\n  .hash-menu {\n    background: transparent;\n  }\n}\n\n.dashboard-config {\n  height: 27px;\n  position: absolute;\n  margin-bottom: 12px;\n  top: -45px;\n  right: 0px;\n  width: 420px;\n  &-icon {\n    width: 17px;\n    height: 17px;\n    font-size: 17px;\n    color: #74788d;\n    margin-right: 9px;\n  }\n\n  &-line {\n    width: 1px;\n    height: 20px;\n    border: 1px solid #ced4da;\n    margin-right: 7px;\n  }\n\n  &-setting {\n    position: absolute;\n    /* margin-top: -16px; */\n    top: 6px;\n    right: 12px;\n    font-size: 17px;\n  }\n\n  #d-range-time .d-range-time-input input {\n    font-family: PingFangSC-Regular;\n    font-size: 13px;\n    color: #495057;\n    text-align: left;\n    line-height: 20px;\n  }\n}\n\n.dashboard-table-content {\n  background: none;\n  padding: 0px;\n\n  ul {\n    color: #212529;\n    background: none;\n    line-height: 36px;\n    border-bottom: none;\n    margin-bottom: 8px;\n    .ant-menu-item {\n      font-size: 18px !important;\n      margin: -1px 24px 0px 0px !important;\n      font-family: PingFangSC-Regular;\n      color: #303a51;\n      &.ant-menu-item-selected {\n        font-family: PingFangSC-Medium;\n      }\n    }\n  }\n}\n\n.dashboard-detail-wrapper {\n  background: none;\n  padding: 8px 0px 20px 0px !important;\n  .d1-col-8 {\n    height: 262px;\n  }\n}\n\n.dashboard-overview-content {\n  &-line {\n    width: 100%;\n    display: flex;\n    justify-content: space-between;\n    flex-wrap: wrap;\n    margin-top: 20px;\n\n    &-container {\n      height: 262px;\n      background: #ffffff;\n      // box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.01), 0 3px 6px 3px rgba(0, 0, 0, 0.01), 0 2px 6px 0 rgba(0, 0, 0, 0.03);\n      border-radius: 8px;\n    }\n\n    &-item {\n      width: 100%;\n      height: 262px;\n\n      // 覆盖 echarts tooltip 的 z-index\n      div {\n        // z-index: 100!important;\n      }\n\n      &-header {\n        display: flex;\n        justify-content: space-between;\n        align-items: center;\n        margin-bottom: 20px;\n\n        &-title {\n          font-family: PingFangSC-Medium;\n          font-size: 16px;\n          color: #101724;\n          line-height: 24px;\n        }\n\n        &-time {\n          font-family: PingFangSC-Medium;\n          font-size: 12px;\n          color: #303a51;\n          line-height: 20px;\n        }\n      }\n    }\n\n    &-enlarge {\n      position: absolute;\n      cursor: pointer;\n      top: 16px;\n      right: 16px;\n      width: 60px;\n      height: 15px;\n      z-index: 100;\n\n      ::selection {\n        color: none;\n        background: none;\n      }\n\n      img {\n        width: 100%;\n        height: 100%;\n      }\n    }\n\n    &-legend {\n      position: absolute;\n      cursor: pointer;\n      top: 16.5px;\n      right: 45px;\n      width: 20px;\n      height: 20px;\n      z-index: 100;\n      font-size: 18px;\n      color: rgb(180, 180, 180);\n    }\n  }\n}\n\n// 索引\n.dashboard-index-view {\n  position: relative;\n  .index-content-item {\n    padding: 12px 16px;\n    height: 282px;\n    background: #ffffff;\n    box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.01), 0 3px 6px 3px rgba(0, 0, 0, 0.01), 0 2px 6px 0 rgba(0, 0, 0, 0.03);\n    border-radius: 8px;\n    margin-bottom: 12px;\n  }\n}\n\n.dashboard-line-container-empty {\n  text-align: center;\n\n  img {\n    width: 60px;\n    height: 40px;\n    margin-bottom: 8px;\n  }\n\n  span {\n    font-family: PingFangSC-Regular;\n    font-size: 12px;\n    color: #919aac;\n    text-align: center;\n    line-height: 20px;\n    margin-left: -10px;\n  }\n}\n\n.dashborad-popover {\n  background: #ffffff;\n  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.01), 0 3px 6px 3px rgba(0, 0, 0, 0.01), 0 2px 6px 0 rgba(0, 0, 0, 0.03);\n  border-radius: 4px;\n  padding-top: 4px;\n\n  .ant-popover-arrow {\n    opacity: 0;\n  }\n\n  .ant-popover-inner-content {\n    padding: 16px 24px;\n  }\n\n  .ant-picker-range {\n    background: rgba(33, 37, 41, 0.04);\n    border-radius: 8px;\n\n    .ant-picker-input > input {\n      font-family: PingFangSC-Regular;\n      font-size: 13px;\n      color: #74788d;\n    }\n  }\n\n  .ant-radio-button-wrapper {\n    border: none !important;\n    height: 18px;\n    line-height: 18px;\n    padding: 0px;\n    font-family: PingFangSC-Medium;\n    font-size: 13px;\n    color: #495057;\n    letter-spacing: 0;\n    transition: none;\n\n    &.ant-radio-button-wrapper-checked {\n      color: #556ee6;\n    }\n  }\n\n  .dd-time-range-module .flx_con .time_title {\n    font-family: PingFangSC-Medium;\n    font-size: 14px;\n    color: #212529;\n    letter-spacing: 0;\n  }\n\n  .dd-time-range-module .flx_con .flx_l {\n    width: 144px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/dashboard/index.tsx",
    "content": "import React, { memo, useState, useEffect, useRef } from \"react\";\nimport { useSelector, useDispatch } from \"react-redux\";\nimport { TAB_LIST_KEY } from \"./config\";\nimport Operation from \"./Operation\";\nimport Url from \"lib/url-parser\";\nimport { setDashBoard } from \"../../actions/dashBoard\";\nimport { Dropdown, Button, Menu } from \"antd\";\nimport { DownOutlined } from \"@ant-design/icons\";\n\nimport \"./index.less\";\nimport \"./../indicators-kanban/style\";\n\nexport const DashBoard = () => {\n  // const dispatch = useDispatch();\n  // useEffect(() => {\n  //   const url = Url().search;\n  //   if (url && url.tabs) {\n  //     dispatch(\n  //       setDashBoard({\n  //         tabs: url.tabs,\n  //       })\n  //     );\n  //   }\n  // }, [])\n  // const { tabs } = useSelector(\n  //   (state) => ({\n  //     tabs: (state as any).dashBoard.tabs,\n  //   }),\n  // );\n\n  const handleMenuClick = (target) => {\n    // window.location.search = `tabs=${key}`\n    // dispatch(\n    //   setDashBoard({\n    //     tabs: target.key,\n    //   })\n    // );\n  };\n\n  const menu = (\n    <Menu onClick={handleMenuClick}>\n      <Menu.Item key={TAB_LIST_KEY.Operation}>运维视角</Menu.Item>\n      <Menu.Item key={TAB_LIST_KEY.operate}>运营视角</Menu.Item>\n    </Menu>\n  );\n  return (\n    <div className=\"hash-menu-container dashboard\">\n      {/* <Dropdown overlay={menu} disabled={true}>\n        <div className=\"dashboard-changepage ant-btn-primary\">\n          <div className=\"dashboard-changepage-text\">运维视角 <DownOutlined className=\"dashboard-changepage-icon\" /></div>\n        </div>\n      </Dropdown> */}\n      <Operation />\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/dashboard/node.tsx",
    "content": "import React, { useState, useEffect, useRef, useContext } from \"react\";\nimport { SyncOutlined } from \"@ant-design/icons\";\nimport { MetricsConfig } from \"./components/metricsConfig\";\nimport { getOption, nodeMetrics } from \"./config\";\nimport { ILineParams, nodeLine, nodeList, setCheckedList, getCheckedList } from \"api/dashboard\";\nimport TableCard from \"./components/table\";\nimport \"./index.less\";\nimport { cloneDeep } from \"lodash\";\nimport DragGroup from \"../../d1-packages/drag-group/DragGroup\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport { Line } from \"./components/line\";\nimport { withRouter } from \"react-router-dom\";\nimport { connect } from \"react-redux\";\nimport { CustomTimeRangePicker } from \"component/TimeRangePicker\";\nimport { DashboardContext } from \"./Operation\";\n\nconst ONE_HOUR = 1000 * 60 * 60;\n\nconst mapStateToProps = (state) => ({\n  dashboard: state.dashBoard,\n});\n\nconst Node = withRouter((props: any) => {\n  const dictionary = useContext(DashboardContext);\n\n  const currentTime = new Date().getTime();\n  const [rangeTime, setRangeTime] = useState([currentTime - ONE_HOUR, currentTime]);\n  const [loading, setLoading] = useState([]);\n  const [metrics, setMetrics] = useState(Object.keys(nodeMetrics));\n  const [data, setData] = useState({});\n  const [listdata, setListData] = useState({});\n  const [isLoading, setIsLoading] = useState(false);\n  const [metricsLoading, setMetricsLoading] = useState(false);\n  const [nodeInfo, setNodeInfo] = useState(null);\n  const topN = useRef({});\n  const customTimeRef = useRef(null);\n\n  const handleTimeChange = (times, isCustomTime) => {\n    setRangeTime(times);\n  };\n\n  const reload = () => {\n    if (metricsLoading) return;\n\n    getLineData();\n    getListData();\n    // getTplListData();\n  };\n\n  const setIndexConfigCheckedData = (checkvalue) => {\n    setMetrics(checkvalue);\n    setCheckedList(\"node\", checkvalue);\n  };\n\n  const sortMetrics = () => {\n    const left = metrics.map((item) => ({ name: nodeMetrics[item]?.name, value: item }));\n    const right = [];\n    Object.keys(nodeMetrics).forEach((item) => {\n      if (!metrics.includes(item)) {\n        right.push({ name: nodeMetrics[item]?.name, value: item });\n      }\n    });\n    return [...left, ...right];\n  };\n\n  const handleReload = () => {\n    customTimeRef?.current?.refresh();\n  };\n\n  const renderConfig = () => {\n    return (\n      <div className=\"dashboard-config\">\n        <SyncOutlined spin={isLoading} className=\"dashboard-config-icon\" onClick={() => handleReload()} />\n        <span className=\"dashboard-config-line\"></span>\n        <CustomTimeRangePicker ref={customTimeRef} onChange={handleTimeChange} />\n        <MetricsConfig title=\"节点\" value={metrics} optionList={sortMetrics()} defaultCheckedData={[]} cb={setIndexConfigCheckedData} />\n      </div>\n    );\n  };\n\n  const injectOptions = (row: any) => {\n    // 不需要注入clusterPhyName白名单\n    const whiteList: string[] = [\"refresh\", \"merge\", \"write\", \"management\", \"search\", \"flush\"];\n    let options: any = {\n      clusterPhyName: (row.metricsContents || []).map((v) => v.cluster),\n    };\n    if (whiteList.includes(row.type)) options.linkWithSeriesName = false;\n    return options;\n  };\n\n  const getLineData = async (topNu?: number, metricsTypes?: string[]) => {\n    const lineMetrics = [];\n    const asLineMetrics = [];\n    metrics.forEach((item) => {\n      if (nodeMetrics && nodeMetrics[item].columns) {\n        return;\n      }\n      if (nodeMetrics && nodeMetrics[item].as) {\n        asLineMetrics.push(item);\n        return;\n      }\n      lineMetrics.push(item);\n    });\n    const params: ILineParams = {\n      metricsTypes: metricsTypes || lineMetrics,\n      // 目前固定为avg\n      aggType: \"avg\",\n      startTime: rangeTime[0],\n      endTime: rangeTime[1],\n      topNu: topNu || 5,\n    };\n    const asParams = {\n      metricsTypes: metricsTypes || asLineMetrics,\n      // 目前固定为avg\n      aggType: \"avg\",\n      startTime: rangeTime[0],\n      endTime: rangeTime[1],\n      topNu: topNu || 5,\n    };\n    if (!params.metricsTypes.length && !asParams.metricsTypes.length) {\n      return;\n    }\n    try {\n      setIsLoading(true);\n      setLoading((state) => [...state, ...(metricsTypes || lineMetrics), ...asLineMetrics]);\n      const metricsList = JSON.stringify(metricsTypes) === JSON.stringify(asLineMetrics) ? await nodeLine(asParams) : [];\n      let asList = [];\n      if (asLineMetrics.length && !metricsTypes) {\n        asList = await nodeLine(asParams);\n      }\n      setIsLoading(false);\n      setLoading((state) => state.filter((item) => !(metricsTypes || lineMetrics).includes(item)));\n      if (metricsTypes) {\n        // 如果传入指标就不初始化data直接在这里return\n        const cloneData = cloneDeep(data);\n        metricsList.forEach((item) => {\n          cloneData[item.type] = getOption({ metrics: item, configData: nodeMetrics, isClusterLink: true, ...injectOptions(item) });\n        });\n        setData(cloneData);\n        return;\n      }\n      const datas = {};\n      metricsList.forEach((item) => {\n        datas[item.type] = getOption({ metrics: item, configData: nodeMetrics, isClusterLink: true, ...injectOptions(item) });\n      });\n      asList.forEach((item) => {\n        datas[item.type] = getOption({ metrics: item, configData: nodeMetrics, isClusterLink: true, ...injectOptions(item) });\n      });\n      setData(datas);\n    } catch (error) {\n      setIsLoading(false);\n      setLoading([]);\n      console.log(\"render line\", error);\n    } finally {\n      setLoading([]);\n    }\n  };\n\n  const getListData = async () => {\n    const ListMetrics = [];\n    metrics.forEach((item) => {\n      if (nodeMetrics && nodeMetrics[item].columns) {\n        ListMetrics.push(item);\n      }\n    });\n    if (!ListMetrics.length) return;\n    const params: any = {\n      metricsTypes: ListMetrics,\n      aggType: \"avg\",\n      orderByDesc: true,\n    };\n\n    try {\n      setIsLoading(true);\n      setLoading((state) => [...state, ...ListMetrics]);\n      const datas = {};\n      const metricsList = await nodeList(params);\n      if (!metricsList || metricsList.length === 0 || metricsList[0]?.metricsContents?.length === 0) {\n        ListMetrics.forEach((item) => {\n          data[item];\n        });\n        setListData({});\n        return;\n      }\n      metricsList.forEach((item) => {\n        datas[item.type] = item;\n      });\n      setListData(datas);\n      setIsLoading(false);\n      setLoading((state) => state.filter((item) => !ListMetrics.includes(item)));\n    } catch (error) {\n      setIsLoading(false);\n      setLoading([]);\n      console.log(\"render line\", error);\n    } finally {\n      // setIsLoading(false);\n    }\n  };\n\n  const sortEnd = ({ oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(metrics, oldIndex, newIndex);\n    setCheckedList(\"node\", listsNew);\n    setMetrics(listsNew);\n  };\n\n  const renderContent = () => {\n    return (\n      <DragGroup\n        dragContainerProps={{\n          onSortEnd: (args) => sortEnd({ ...args }),\n          axis: \"xy\",\n          distance: 100,\n        }}\n        containerProps={{\n          grid: 8,\n          gutter: [12, 12],\n        }}\n      >\n        {metrics.map((item: any, i) => {\n          if (nodeMetrics[item]?.columns) {\n            let list = listdata[item]?.metricListContents;\n            let dataSource = (list || []).map((item) => {\n              return {\n                ...item,\n                key: `${item.clusterPhyName}-${item.name}`,\n              };\n            });\n            return (\n              <TableCard\n                columns={nodeMetrics[item]?.columns}\n                dataSource={dataSource}\n                title={nodeMetrics[item]?.name}\n                // unit={item.unit}\n                isLoading={loading.includes(item)}\n                key={item}\n                dictionary={dictionary?.nodeData?.[item]}\n              />\n            );\n          }\n          return (\n            <Line\n              title={data[item]?.title?.text || nodeMetrics[item]?.title()}\n              index={item}\n              key={item}\n              option={data[item] || {}}\n              isLoading={loading.includes(item)}\n              cb={getLineData}\n              topN={topN}\n              dictionary={dictionary?.nodeData?.[item]}\n            />\n          );\n        })}\n      </DragGroup>\n    );\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      setMetricsLoading(true);\n      const checkedList = await getCheckedList(\"node\");\n      if (!checkedList || checkedList.length === 0) {\n        setMetrics(metrics);\n      } else {\n        // 以下需暂时过滤掉\n        const filterList = [\"dead\"];\n        setMetrics(checkedList.filter((item) => filterList.indexOf(item) === -1));\n      }\n    } catch (error) {\n      setMetrics(metrics);\n      console.log(\"cluster-kanban node-view 获取配置下项失败\", error);\n    } finally {\n      setMetricsLoading(false);\n    }\n  };\n  const linkToClusterPage = () => {\n    window[\"clusterlink\"] = (node: string, clusterName: string) => {\n      if (node) {\n        props.history.push(`/indicators/cluster?cluster=${clusterName}&node=${node}#node`);\n      } else {\n        props.history.push(`/indicators/cluster?cluster=${clusterName}#node`);\n      }\n    };\n  };\n\n  const setDymanicMetrics = () => {\n    if (props.dashboard?.dymanicConfigMetrics?.length) {\n      const res = props.dashboard?.dymanicConfigMetrics;\n      res.forEach((item) => {\n        try {\n          const itemValue = JSON.parse(item.value);\n          switch (item.valueName) {\n            case \"node.disk.used_percent_threshold\":\n              nodeMetrics.largeDiskUsage.name = `磁盘利用率超${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}节点列表`;\n              if (dictionary?.nodeData?.largeDiskUsage) {\n                dictionary.nodeData.largeDiskUsage.threshold = `磁盘利用率超${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}为超红线`;\n              }\n              break;\n            case \"node.jvm.heap.used_percent_threshold\":\n              // ex\n              const target = res.find((row) => row.valueName === \"node.jvm.heap.used_percent_time_duration_threshold\") || {};\n              const timeValue = target.value ? JSON.parse(target.value) : {};\n              nodeMetrics.largeHead.name = `堆内存利用率超${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}节点列表`;\n              if (dictionary?.nodeData?.largeHead) {\n                dictionary.nodeData.largeHead.threshold = `堆内存利用率超${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}且持续${\n                  timeValue?.value ?? \"\"\n                }${timeValue?.unit ?? \"\"}为超红线`;\n              }\n              break;\n            case \"node.cpu.used_percent_threshold\":\n              // ex\n              const target1 = res.find((row) => row.valueName === \"node.cpu.used_percent_threshold_time_duration_threshold\") || {};\n              const time1Value = target1.value ? JSON.parse(target1.value) : {};\n              nodeMetrics.largeCpuUsage.name = `CPU利用率超${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}节点列表`;\n              if (dictionary?.nodeData?.largeCpuUsage) {\n                dictionary.nodeData.largeCpuUsage.threshold = `CPU利用率超${itemValue.value ?? \"\"}${itemValue.unit ?? \"\"}且持续${\n                  time1Value?.value ?? \"\"\n                }${time1Value?.unit ?? \"\"}为超红线`;\n              }\n              break;\n            case \"node.shard.num_threshold\":\n              nodeMetrics.shardNum.name = `节点分片个数大于${itemValue.value ?? \"\"}节点列表`;\n              break;\n            default:\n              break;\n          }\n        } catch (error) {\n          console.log(error, `JSON.parse解析${item?.valueName}错误，请检查动态配置中配置项书写格式`);\n        }\n      });\n    }\n  };\n\n  // 加载选中配置\n  useEffect(() => {\n    linkToClusterPage();\n    getAsyncCheckedList();\n    setNodeInfo(nodeMetrics);\n  }, []);\n\n  useEffect(() => {\n    setDymanicMetrics();\n  }, [props.dashboard?.dymanicConfigMetrics, dictionary]);\n\n  useEffect(() => {\n    reload();\n  }, [rangeTime, metrics]);\n\n  return (\n    <div className=\"dashboard-index-view\">\n      {renderConfig()}\n      {renderContent()}\n    </div>\n  );\n});\n\nexport default connect(mapStateToProps, null)(Node);\n"
  },
  {
    "path": "arius-console/src/container/drawer/config-detail.tsx",
    "content": "import { Drawer } from 'antd';\nimport React from 'react';\nimport { connect } from \"react-redux\";\nimport * as actions from 'actions';\n\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n});\nclass ConfigDetail extends React.Component<any> {\n\n  public render() {\n    const { dispatch } = this.props\n    return (\n      <Drawer\n        title={'配置内容'}\n        visible={true}\n        onClose={() => dispatch(actions.setDrawerId(''))}\n        width={600}\n        maskClosable={true}\n      >\n        <pre>{this.props.params}</pre>  \n      </Drawer>\n    );\n  }\n}\nexport default connect(mapStateToProps)(ConfigDetail);\n\n\n"
  },
  {
    "path": "arius-console/src/container/drawer/config.tsx",
    "content": "import React from 'react';\nimport  { Modal } from 'antd';\nimport { IRegionTaskItem } from 'typesPath/cluster/physics-type';\nimport { renderOperationBtns } from 'container/custom-component';\nimport { TaskItemModal } from 'container/cluster/physics-detail/region-task-item-modal';\n\n\nexport const getPhysicsRegionTaskItemColumns = () => {\n  const operationList = [\n    {\n      label: 'detail',\n      clickFunc: (record: IRegionTaskItem) => {\n        Modal.confirm({\n          title: '详情',\n          icon: 'none',\n          content: <TaskItemModal {...record} />,\n          width: 800,\n          okText: '确认',\n          cancelText: '取消',\n          onOk() {\n            return;\n          },\n        });\n      },\n    }];\n  const columns = [\n    {\n      title: 'ID',\n      dataIndex: 'id',\n      key: 'id',\n      sorter: (a: IRegionTaskItem, b: IRegionTaskItem) => a.id - b.id,\n    }, {\n      title: '物理模板ID',\n      dataIndex: 'physicalId',\n      key: 'physicalId',\n    }, {\n      title: '模板名字',\n      dataIndex: 'templateName',\n      key: 'templateName',\n    }, {\n      title: 'Quota',\n      dataIndex: 'quota',\n      key: 'quota',\n    }, {\n      title: '磁盘消耗（G）',\n      dataIndex: 'sumIndexSizeG',\n      key: 'sumIndexSizeG',\n    }, {\n      title: 'cpu消耗',\n      dataIndex: 'combinedCpuCount',\n      key: 'combinedCpuCount',\n    }, {\n      title: 'tps峰值(w/s)',\n      dataIndex: 'maxTps',\n      key: 'maxTps',\n    }, {\n      title: '操作',\n      dataIndex: 'operation',\n      key: 'operation',\n      width: '15%',\n      render: (text: number, record: IRegionTaskItem) => {\n        const btns = operationList;\n        return renderOperationBtns(btns as any, record);\n      },\n    },\n  ];\n  return columns;\n};"
  },
  {
    "path": "arius-console/src/container/drawer/dsl-detail.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { Descriptions, Button, Tooltip, message, Modal } from \"antd\";\nimport { Drawer, Divider } from \"knowdesign\";\nimport { CopyOutlined } from \"@ant-design/icons\";\nimport { copyString, transTimeFormat, formatDecimalPoint } from \"lib/utils\";\nimport { changeStatus, getDslDetail } from \"api/search-query\";\nimport EditLimit from \"../search-query/components/editLimit\";\nimport store from \"store\";\n\nconst confirm = Modal.confirm;\nconst DescriptionsItem = Descriptions.Item;\n\nconst appInfo = {\n  app: store.getState().app.appInfo,\n  user: store.getState().user.getName,\n};\ninterface IProps {\n  visible: boolean;\n  detailData: any;\n  onCancel: () => void;\n  cb: () => void;\n  showEditLimit: (detailData: any) => void;\n  history?: any;\n}\n\nconst DslDetail: React.FC<IProps> = (props: IProps) => {\n  const { detailData } = props;\n  const [data, setData]: any = useState({});\n  const [records, setRecords]: any = useState([]);\n  const [editVisible, setEditVisible] = useState(false);\n\n  const getWidth = () => {\n    return 600;\n  };\n\n  const getDetail = () => {\n    getDslDetail(detailData.dslTemplateMd5, detailData.projectId).then((res = {}) => {\n      setData(res);\n      setRecords([res]);\n    });\n  };\n\n  const editCancel = () => {\n    setEditVisible(false);\n  };\n\n  const showEditLimit = () => {\n    setEditVisible(true);\n  };\n\n  useEffect(() => {\n    if (props.visible) {\n      getDetail();\n    }\n    return () => {\n      setData({});\n      setRecords([]);\n    };\n  }, [props.visible, detailData, detailData.dslTemplateMd5]);\n\n  const typeMap = [\n    {\n      type: \"查询索引示例\",\n      value: (\n        <div className=\"dsl-drawer-box\" title={data?.indiceSample}>\n          <span className=\"icon iconfont iconfuzhi dsl-drawer-icon\" onClick={() => copyString(data?.indiceSample)}></span>\n          {data?.indiceSample}\n        </div>\n      ),\n    },\n    {\n      type: \"所属应用\",\n      value: `${detailData?.projectName}(${detailData?.projectId})`,\n    },\n    {\n      type: \"查询模板\",\n      value: (\n        <div className=\"dsl-drawer-box\" title={data?.dslTemplate}>\n          <span className=\"icon iconfont iconfuzhi dsl-drawer-icon\" onClick={() => copyString(data?.dslTemplate)}></span>\n          {data?.dslTemplate}\n        </div>\n      ),\n    },\n    {\n      type: \"查询语句示例\",\n      value: (\n        <div className=\"dsl-drawer-box\" title={data?.dsl}>\n          <span\n            className=\"icon iconfont iconfuzhi dsl-drawer-icon\"\n            onClick={() => copyString(`GET ${data?.indices}/_search\\n${data?.dsl}`)}\n          ></span>\n          {data?.dsl}\n        </div>\n      ),\n    },\n    {\n      type: \"创建时间\",\n      value: transTimeFormat(data?.ariusCreateTime),\n    },\n    {\n      type: \"修改时间\",\n      value: transTimeFormat(data?.ariusModifyTime),\n    },\n    {\n      type: \"最近使用时间\",\n      value: transTimeFormat(data?.flinkTime),\n    },\n    {\n      type: \"MD5信息\",\n      value: (\n        <div className=\"dsl-drawer-box\" title={data?.dslTemplateMd5}>\n          {data?.dslTemplateMd5}\n        </div>\n      ),\n    },\n  ];\n  const detailMap = [\n    {\n      type: \"请求数\",\n      value: data?.searchCount,\n    },\n    {\n      type: \"查询语句长度\",\n      value: formatDecimalPoint(data?.dslLenAvg),\n    },\n    {\n      type: \"单次响应长度\",\n      value: formatDecimalPoint(data?.responseLenAvg),\n    },\n    {\n      type: \"耗时(ms)\",\n      value: formatDecimalPoint(data?.totalCostAvg),\n    },\n    {\n      type: \"es响应时间(ms)\",\n      value: formatDecimalPoint(data?.esCostAvg),\n    },\n    {\n      type: \"预处理时间(ms)\",\n      value: formatDecimalPoint(data?.beforeCostAvg),\n    },\n    {\n      type: \"总Shard个数\",\n      value: formatDecimalPoint(data?.totalShardsAvg),\n    },\n    {\n      type: \"失败Shard个数\",\n      value: formatDecimalPoint(data?.failedShardsAvg),\n    },\n    {\n      type: \"单次命中数\",\n      value: formatDecimalPoint(data?.totalHitsAvg),\n    },\n    {\n      type: \"查询限流值\",\n      value: formatDecimalPoint(data?.queryLimit),\n    },\n    {\n      type: \"语句类型\",\n      value: data?.dslType,\n    },\n    {\n      type: \"请求方式\",\n      value: data?.requestType,\n    },\n    {\n      type: \"查询方式\",\n      value: data?.searchType,\n    },\n  ];\n\n  const handleChangeStatus = () => {\n    confirm({\n      title: \"提示\",\n      content: `确定${data?.enable || data?.enable === null ? \"禁用\" : \"启用\"}查询模板${data?.dslTemplateMd5}？`,\n      width: 500,\n      okText: \"确认\",\n      cancelText: \"取消\",\n      onOk() {\n        changeStatus(data?.dslTemplateMd5, data?.projectId).then((res) => {\n          getDetail();\n          props.cb();\n          message.success(\"操作成功\");\n        });\n      },\n    });\n  };\n\n  const renderFooter = () => {\n    return (\n      <div>\n        <Button onClick={handleChangeStatus} className={\"dsl-mr-20\"}>\n          {data?.enable || data?.enable === null ? \"禁用\" : \"启用\"}\n        </Button>\n        <Button type=\"primary\" onClick={showEditLimit}>\n          修改限流值\n        </Button>\n        <Divider\n          type=\"vertical\"\n          style={{\n            height: \"16px\",\n            margin: \"0 16px\",\n          }}\n        ></Divider>\n      </div>\n    );\n  };\n\n  const title = (text) => {\n    return (\n      <div className=\"dsl-drawer-title\">\n        <Divider\n          type=\"vertical\"\n          style={{\n            width: \"3px\",\n            height: \"12px\",\n            margin: \"0 4px 0 -2px\",\n            background: \"#1473FF\",\n          }}\n        ></Divider>{\" \"}\n        {text}\n      </div>\n    );\n  };\n\n  const contentStyle: any = {\n    whiteSpace: \"nowrap\",\n    overflow: \"hidden\",\n    textOverflow: \"ellipsis\",\n    color: \"rgba(0,0,0,0.87)\",\n    alignItems: \"center\",\n    fontSize: \"14px\",\n  };\n  const labelStyle: any = { width: \"127px\", justifyContent: \"flex-end\", fontSize: \"14px\", color: \"rgba(0,0,0,0.6)\" };\n\n  return (\n    <Drawer\n      title={\"查询模板详情\"}\n      visible={props.visible}\n      width={getWidth()}\n      maskClosable={true}\n      extra={renderFooter()}\n      onClose={props.onCancel}\n      bodyStyle={{ padding: \"0px\" }}\n    >\n      <div className=\"dsl-drawer\">\n        <EditLimit history={props?.history} appInfo={appInfo} visible={editVisible} record={records} cancel={editCancel} cb={getDetail} />\n        {title(\"基本信息\")}\n        <Descriptions column={1} labelStyle={labelStyle} contentStyle={contentStyle} style={{ paddingLeft: 24 }}>\n          {typeMap.map((item, index) => (\n            <DescriptionsItem key={index} label={item.type}>\n              {item.value}\n            </DescriptionsItem>\n          ))}\n        </Descriptions>\n      </div>\n      <div className=\"dsl-drawer\">\n        {title(\"业务信息\")}\n        <Descriptions column={1} labelStyle={labelStyle} contentStyle={contentStyle} style={{ paddingLeft: 24 }}>\n          {detailMap.map((item, index) => (\n            <DescriptionsItem key={index} label={item.type}>\n              <Tooltip title={item.value}>{item.value}</Tooltip>\n            </DescriptionsItem>\n          ))}\n        </Descriptions>\n      </div>\n    </Drawer>\n  );\n};\nexport default DslDetail;\n"
  },
  {
    "path": "arius-console/src/container/drawer/index-create.tsx",
    "content": "import { Button, Steps, Drawer, message } from \"antd\";\nimport React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"../../actions\";\nimport { Dispatch } from \"redux\";\nimport { FormItemType, IFormItem, XForm as XFormComponent } from \"component/x-form\";\nimport { addIndexAdmin } from \"api/index-admin\";\nimport { AppState } from \"store/type\";\nimport { SetMapping, SetSetting } from \"../index-admin/component\";\nimport { getClusterLogicNames } from \"api/cluster-api\";\nimport { checkIndexName, getPhyClusterPerType } from \"api/cluster-index-api\";\nimport { RESOURCE_TYPE_LIST } from \"constants/common\";\nimport { formatJsonStr, isSuperApp, getFormatJsonStr } from \"lib/utils\";\n\nconst { Step } = Steps;\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params, cb)),\n});\n\nconst mapStateToProps = (state) => ({\n  app: state.app,\n  cb: state.modal.cb,\n});\n\nclass CreateIndex extends React.Component<{\n  app: AppState;\n  cb: Function;\n  setDrawerId: Function;\n}> {\n  state = {\n    loading: false,\n    visible: false,\n    current: 0,\n    baseInfoData: {} as any,\n    mapping: \"\",\n    setting: getFormatJsonStr({\n      index: {\n        \"translog.durability\": \"async\",\n        \"translog.sync_interval\": \"15s\",\n        refresh_interval: \"1s\",\n        // codec: \"default\",\n      },\n    }),\n    clusterList: [],\n  };\n\n  $formRef: any = React.createRef();\n  $mappingRef: any = React.createRef();\n  $settingRef: any = React.createRef();\n\n  steps = [\n    {\n      title: \"基础信息\",\n      content: \"baseInfo\",\n    },\n    {\n      title: \"Mapping设置\",\n      content: \"Mapping\",\n    },\n    {\n      title: \"Setting设置\",\n      content: \"Setting\",\n    },\n  ];\n\n  formMap = () => {\n    return [\n      {\n        key: \"name\",\n        label: \"索引名称\",\n        attrs: {\n          placeholder: \"请填写索引名称，支持小写字母、数字、-、_4-128位字符\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: string) => {\n              value = value?.trim();\n              const reg = /^[.a-z0-9_-]{1,}$/g;\n              if (!value) {\n                return Promise.reject(\"请填写索引名称\");\n              }\n              if (!reg.test(value) || value.length > 128 || value.length < 4) {\n                return Promise.reject(\"请正确填写索引名称，支持小写字母、数字、-、_4-128位字符\");\n              }\n              const cluster = this.$formRef?.current.getFieldValue([\"cluster\"]);\n              if (value && cluster) {\n                try {\n                  const res = await checkIndexName(cluster, value);\n                  if (res?.data) {\n                    return Promise.reject(\"索引名称已存在\");\n                  }\n                  if (res.code !== 0 && res.code !== 200) {\n                    return Promise.reject(res.message);\n                  }\n                } catch (err) {\n                  return Promise.reject(\"索引名称校验失败\");\n                }\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"clusterType\",\n        label: \"集群类型\",\n        type: FormItemType.select,\n        options: RESOURCE_TYPE_LIST,\n        attrs: {\n          onChange: (value) => {\n            // 超级应用展示物理集群，其他应用展示逻辑集群\n            const superApp = isSuperApp();\n            const clusterFn = superApp ? getPhyClusterPerType : getClusterLogicNames;\n            clusterFn(value).then((res = []) => {\n              this.$formRef?.current.setFieldsValue({ cluster: undefined });\n              this.setState({ clusterList: superApp ? res : res.map((item) => item.name) });\n            });\n          },\n        },\n        rules: [\n          {\n            required: true,\n            message: \"请选择集群类型\",\n          },\n        ],\n      },\n      {\n        key: \"cluster\",\n        label: \"集群名称\",\n        type: FormItemType.select,\n        options: this.state.clusterList.map((item) => ({\n          label: item,\n          value: item,\n        })),\n        attrs: {\n          onChange: (value) => {\n            const name = this.$formRef?.current.getFieldValue([\"name\"]);\n            if (value && name) {\n              this.$formRef?.current.validateFields([\"name\"]);\n            }\n          },\n        },\n        rules: [\n          {\n            required: true,\n            message: \"请选择集群名称\",\n          },\n        ],\n      },\n    ] as IFormItem[];\n  };\n\n  handleCancel = () => {\n    this.props.setDrawerId(\"\");\n  };\n\n  prev = () => {\n    const { current } = this.state;\n    if (current === 1) {\n      this.$mappingRef.handlePre();\n    } else if (current === 2) {\n      this.$settingRef.handlePre();\n    }\n  };\n\n  next = () => {\n    const { current } = this.state;\n    if (current === 0) {\n      this.$formRef\n        ?.current!.validateFields()\n        .then((values) => {\n          this.setState({\n            current: 1,\n            baseInfoData: values,\n          });\n        })\n        .catch((errs) => {});\n    } else if (current === 1) {\n      this.$mappingRef.handleSubmit();\n    } else if (current === 2) {\n      this.$settingRef.handleSubmit(this.onSubmit);\n    }\n  };\n\n  onSubmit = (value) => {\n    const { baseInfoData, mapping } = this.state;\n    const params = {\n      index: baseInfoData.name,\n      cluster: baseInfoData.cluster,\n      mapping: formatJsonStr(mapping),\n      setting: formatJsonStr(value),\n    };\n    this.setState({\n      loading: true,\n    });\n    addIndexAdmin(params)\n      .then((res) => {\n        message.success(res?.message || \"索引创建成功\");\n        this.props.setDrawerId(\"\");\n        this.props.cb();\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n  };\n\n  renderBtn = () => {\n    const { current } = this.state;\n    return [\n      current < 2 ? (\n        <Button key=\"submit3\" type=\"primary\" style={{ marginRight: \"10px\" }} onClick={this.next}>\n          下一步\n        </Button>\n      ) : (\n        \"\"\n      ),\n      current === 2 ? (\n        <Button loading={this.state.loading} key=\"submit4\" type=\"primary\" style={{ marginRight: \"10px\" }} onClick={this.next}>\n          完成\n        </Button>\n      ) : (\n        \"\"\n      ),\n      current > 0 ? (\n        <Button key=\"back2\" style={{ marginRight: \"10px\" }} onClick={this.prev}>\n          上一步\n        </Button>\n      ) : (\n        \"\"\n      ),\n      <Button key=\"back1\" onClick={this.handleCancel}>\n        取消\n      </Button>,\n    ];\n  };\n\n  updateState = (keyValue, cb?: any) => {\n    this.setState(keyValue, cb && cb());\n  };\n\n  renderContent = () => {\n    const { current, baseInfoData, mapping, setting } = this.state;\n    if (this.steps[current].content === \"baseInfo\") {\n      return <XFormComponent formData={baseInfoData} formMap={this.formMap()} wrappedComponentRef={this.$formRef} />;\n    } else if (this.steps[current].content === \"Mapping\") {\n      return (\n        <div style={{ marginTop: 20 }}>\n          <SetMapping childEvevnt={(child) => (this.$mappingRef = child)} updateState={this.updateState} data={mapping} />\n        </div>\n      );\n    } else if (this.steps[current].content === \"Setting\") {\n      return (\n        <div style={{ marginTop: 20 }}>\n          <SetSetting childEvevnt={(child) => (this.$settingRef = child)} updateState={this.updateState} data={setting} />\n        </div>\n      );\n    } else {\n      return this.steps[current].content;\n    }\n  };\n\n  componentWillUnmount() {\n    // 这是一段比较恶心的代码 xform的值无法传下去 但是内部需要接收到\n    (window as any).masternodeErr = false;\n    delete (window as any).masternodeErr;\n  }\n\n  render() {\n    const { current } = this.state;\n    return (\n      <div>\n        <Drawer visible={true} title=\"新建索引\" width={728} onClose={this.handleCancel} footer={this.renderBtn()} maskClosable={false}>\n          <Steps current={current} style={{ margin: \"24px 0 24px 0\" }}>\n            {this.steps.map((item) => (\n              <Step key={item.title} title={item.title} />\n            ))}\n          </Steps>\n          <div className=\"steps-content\">{this.renderContent()}</div>\n        </Drawer>\n      </div>\n    );\n  }\n}\n\nexport default connect(mapStateToProps, mapDispatchToProps)(CreateIndex);\n"
  },
  {
    "path": "arius-console/src/container/drawer/index-mapping-edit.tsx",
    "content": "import * as React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { Drawer, Button } from \"antd\";\nimport { SetMapping } from \"../index-admin/component\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nconst connects: any = connect;\n\n@connects(mapStateToProps)\nexport class EditIndexMapping extends React.Component<any, any> {\n  public state = {\n    btnLoading: false,\n    disabled: false,\n    mapping: \"\",\n  };\n\n  $mappingRef: any = React.createRef();\n\n  public updateState = (keyValue) => {\n    this.setState(keyValue);\n  };\n\n  setValid = (valid: boolean) => {\n    this.setState({\n      disabled: !valid,\n    });\n  };\n\n  public handleSubmit = () => {\n    this.$mappingRef.handleSave(() => {\n      this.props.dispatch(actions.setDrawerId(\"\"));\n      this.props.cb && this.props.cb(); // 重新获取数据列表\n    });\n  };\n\n  public handleCancel = () => {\n    this.props.dispatch(actions.setDrawerId(\"\"));\n  };\n\n  public render() {\n    const { btnLoading, mapping } = this.state;\n\n    return (\n      <>\n        <Drawer\n          title=\"编辑Mapping\"\n          visible={true}\n          width={600}\n          closable={true}\n          maskClosable={false}\n          destroyOnClose={true}\n          onClose={this.handleCancel}\n          footer={\n            <div className=\"footer-btn\">\n              <Button disabled={this.state.disabled} className=\"mr-10\" type=\"primary\" loading={btnLoading} onClick={this.handleSubmit}>\n                确定\n              </Button>\n              <Button onClick={this.handleCancel}>取消</Button>\n            </div>\n          }\n        >\n          <div className=\"warning-container\" style={{ margin: \"0 -24px 16px\" }}>\n            <span className=\"icon iconfont iconbiaogejieshi\"></span>\n            <span>索引Mapping只允许新增，不允许清空或变更原有字段</span>\n          </div>\n          <SetMapping\n            childEvevnt={(child) => (this.$mappingRef = child)}\n            setValid={this.setValid}\n            updateState={this.updateState}\n            data={mapping}\n          />\n        </Drawer>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/drawer/index-setting-edit.tsx",
    "content": "import * as React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { Drawer, Button } from \"antd\";\nimport { SetSetting } from \"../index-admin/component\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nconst connects: any = connect;\n\n@connects(mapStateToProps)\nexport class EditIndexSetting extends React.Component<any, any> {\n  public state = {\n    btnLoading: false,\n    disabled: false,\n    setting: \"\",\n  };\n\n  $settingRef: any = React.createRef();\n\n  public updateState = (keyValue) => {\n    this.setState(keyValue);\n  };\n\n  setValid = (valid: boolean) => {\n    this.setState({\n      disabled: !valid,\n    });\n  };\n\n  public handleSubmit = () => {\n    this.$settingRef.handleSave(() => {\n      this.props.dispatch(actions.setDrawerId(\"\"));\n      this.props.cb && this.props.cb(); // 重新获取数据列表\n    });\n  };\n\n  public handleCancel = () => {\n    this.props.dispatch(actions.setDrawerId(\"\"));\n  };\n\n  public render() {\n    const { btnLoading, setting } = this.state;\n\n    return (\n      <>\n        <Drawer\n          title=\"编辑Setting\"\n          visible={true}\n          width={600}\n          closable={true}\n          maskClosable={false}\n          destroyOnClose={true}\n          onClose={this.handleCancel}\n          footer={\n            <div className=\"footer-btn\">\n              <Button disabled={this.state.disabled} className=\"mr-10\" type=\"primary\" loading={btnLoading} onClick={this.handleSubmit}>\n                确定\n              </Button>\n              <Button onClick={this.handleCancel}>取消</Button>\n            </div>\n          }\n        >\n          <div style={{ marginBottom: \"20px\" }}></div>\n          <SetSetting\n            childEvevnt={(child) => (this.$settingRef = child)}\n            setValid={this.setValid}\n            updateState={this.updateState}\n            data={setting}\n          />\n        </Drawer>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/drawer/index-srv-forceMerge.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { message, Tooltip } from \"antd\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { executeForceMerge } from \"api/index-admin\";\nimport { XNotification } from \"component/x-notification\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const IndexSrvForceMerge = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const [onlyExpungeDeletes, setOnlyExpungeDeletes] = React.useState(false);\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"onlyExpungeDeletes\",\n        label: (\n          <div className=\"cluster-label\">\n            only_expunge_deletes\n            <Tooltip title=\"是否只合并包含删除文档的segment\">\n              <span className=\"icon iconfont iconinfo\"></span>\n            </Tooltip>\n          </div>\n        ),\n\n        type: FormItemType.select,\n        attrs: {\n          placeholder: \"请选择\",\n          onChange: (value) => {\n            setOnlyExpungeDeletes(value);\n          },\n        },\n        rules: [\n          {\n            required: true,\n            message: \"请选择only_expunge_deletes\",\n          },\n        ],\n        options: [\n          {\n            label: \"true\",\n            value: true,\n          },\n          {\n            label: \"false\",\n            value: false,\n          },\n        ],\n      },\n      {\n        key: \"maxNumSegments\",\n        label: (\n          <div className=\"cluster-label\">\n            max_num_segments\n            <Tooltip title=\"最大segment数\">\n              <span className=\"icon iconfont iconinfo\"></span>\n            </Tooltip>\n          </div>\n        ),\n        type: FormItemType.inputNumber,\n        invisible: onlyExpungeDeletes,\n        attrs: {\n          placeholder: \"请输入max_num_segments\",\n          style: {\n            width: \"100%\",\n          },\n        },\n        rules: [\n          {\n            required: true,\n            message: `请输入max_num_segments（正整数）`,\n            validator: (rule: any, value: any) => {\n              if (new RegExp(regNonnegativeInteger).test(value)) return Promise.resolve();\n              return Promise.reject();\n            },\n          },\n        ],\n      },\n      {\n        key: \"indexs\",\n        label: \"操作对象\",\n        type: FormItemType.custom,\n        customFormItem: (\n          <div className=\"btn-labels-box\">\n            {props.params.length ? props.params.map((item) => <div className=\"btn-labels\">{item.index}</div>) : \"-\"}\n          </div>\n        ),\n      },\n    ] as IFormItem[],\n    type: \"drawer\",\n    visible: true,\n    title: (\n      <>\n        执行ForceMerge\n        <a\n          href=\"https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-forcemerge.html\"\n          rel=\"noreferrer\"\n          target=\"_blank\"\n          className=\"link-button\"\n        >\n          官方指导\n        </a>\n      </>\n    ),\n    formData: { onlyExpungeDeletes: false, maxNumSegments: 5 },\n    isWaitting: true,\n    width: 500,\n    needSuccessMessage: false,\n    onCancel: () => {\n      props.dispatch(actions.setDrawerId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      const params = {\n        indices: props.params.map((item) => ({\n          cluster: item.cluster,\n          index: item.index,\n        })),\n        ...result,\n      };\n      return executeForceMerge(params).then(() => {\n        message.success(`操作提交成功，任务异步执行`);\n        props.dispatch(actions.setDrawerId(\"\"));\n        props.cb && props.cb(); // 重新获取数据列表\n      });\n      // .catch((err) => {\n      //   XNotification({ type: \"error\", message: \"错误\", description: err.tips });\n      // });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/drawer/index-srv-rollover.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { message } from \"antd\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { executeRollover } from \"api/index-admin\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const IndexSrvRollover = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const rolloverIndexs = props.params.filter((item) => !item.templateId && item.aliases?.length);\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"max_age\",\n        label: \"max_age\",\n        type: FormItemType.input,\n        attrs: {\n          placeholder: \"请输入max_age，单位参考，天：d、小时：h\",\n        },\n        rules: [\n          {\n            required: false,\n            message: `请输入max_age`,\n          },\n        ],\n      },\n      {\n        key: \"max_docs\",\n        label: \"max_docs\",\n        type: FormItemType.inputNumber,\n        attrs: {\n          placeholder: \"请输入max_docs\",\n          style: {\n            width: \"100%\",\n          },\n        },\n        rules: [\n          {\n            required: false,\n            message: `请输入max_docs（正整数）`,\n            validator: (rule: any, value: any) => {\n              if (value === undefined || value === null) return Promise.resolve();\n              if (new RegExp(regNonnegativeInteger).test(value)) return Promise.resolve();\n              return Promise.reject();\n            },\n          },\n        ],\n      },\n      {\n        key: \"max_size\",\n        label: \"max_size\",\n        type: FormItemType.input,\n        attrs: {\n          placeholder: \"请输入max_size，单位参考：gb\",\n        },\n        rules: [\n          {\n            required: false,\n            message: `请输入max_size`,\n          },\n        ],\n      },\n      {\n        key: \"indexs\",\n        label: \"操作对象\",\n        type: FormItemType.custom,\n        customFormItem: (\n          <div className=\"btn-labels-box\">\n            {rolloverIndexs.length ? rolloverIndexs.map((item) => <div className=\"btn-labels\">{item.index}</div>) : \"-\"}\n          </div>\n        ),\n      },\n    ] as IFormItem[],\n    type: \"drawer\",\n    visible: true,\n    title: (\n      <>\n        执行Rollover\n        <a\n          href=\"https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-rollover-index.html\"\n          rel=\"noreferrer\"\n          target=\"_blank\"\n          className=\"link-button\"\n        >\n          官方指导\n        </a>\n      </>\n    ),\n    needBtnLoading: true,\n    width: 500,\n    onCancel: () => {\n      props.dispatch(actions.setDrawerId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      if (!rolloverIndexs.length) {\n        props.dispatch(actions.setDrawerId(\"\"));\n        return;\n      }\n      const params = {\n        indices: rolloverIndexs.map((item) => ({\n          cluster: item.cluster,\n          index: item.index,\n        })),\n        content: JSON.stringify({ conditions: result }),\n      };\n      return executeRollover(params).then(() => {\n        message.success(`操作成功`);\n        props.dispatch(actions.setDrawerId(\"\"));\n        props.cb && props.cb(); // 重新获取数据列表\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/drawer/index-srv-shrinkSplit.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { message } from \"antd\";\nimport { executeShrink, executeSplit } from \"api/index-admin\";\nimport { formatJsonStr, copyString } from \"lib/utils\";\nimport { CopyOutlined } from \"@ant-design/icons\";\nimport { JsonEditorWrapper } from \"component/jsonEditorWrapper\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const IndexSrvShrinkSplit = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const { type, indexs } = props.params;\n  const [activeInstance, setActiveInstance] = React.useState(null);\n  const shrinkExample = `{\n    \"settings\": {\n        \"index.number_of_replicas\": 1,\n        \"index.number_of_shards\": 1,\n        \"index.codec\": \"best_compression\"\n    },\n    \"aliases\": {\n        \"my_search_indices\": {}\n    }\n}`;\n  const splitExample = `{\n    \"settings\": {\n        \"index.number_of_shards\": 5\n    },\n    \"aliases\": {\n        \"my_search_indices\": {}\n    }\n}`;\n  const documentHref =\n    type === \"shrink\"\n      ? \"https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-shrink-index.html\"\n      : \"https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-split-index.html\";\n\n  const exampleElement = () => {\n    const exampleText = type === \"shrink\" ? shrinkExample : splitExample;\n    return (\n      <>\n        <div>\n          {type === \"shrink\" ? \"执行shrink样例：\" : \"执行split样例：\"}\n          <CopyOutlined onClick={() => copyString(exampleText)} />\n        </div>\n        <pre>{exampleText}</pre>\n      </>\n    );\n  };\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"tips\",\n        label: \"\",\n        type: FormItemType.custom,\n        formAttrs: {\n          className: \"warning-container\",\n          style: {\n            margin: \"0 -24px\",\n            padding: \"2px 24px\",\n          },\n        },\n        customFormItem: (\n          <>\n            <span className=\"icon iconfont iconbiaogejieshi\"></span>\n            <span>需要提前禁写索引，请谨慎操作</span>\n          </>\n        ),\n      },\n      {\n        key: \"targetIndex\",\n        label: \"目标索引\",\n        type: FormItemType.input,\n        attrs: {\n          placeholder: \"请填写目标索引，支持小写字母、数字、-、_4-128位字符\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: string) => {\n              value = value?.trim();\n              const reg = /^[.a-z0-9_-]{1,}$/g;\n              if (!value) {\n                return Promise.reject(\"请填写目标索引\");\n              }\n              if (!reg.test(value) || value.length > 128 || value.length < 4) {\n                return Promise.reject(\"请正确填写目标索引，支持小写字母、数字、-、_4-128位字符\");\n              }\n              if (value && value === indexs.index) {\n                return Promise.reject(\"目标索引不能与原有索引重复\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n        options: [{ label: \"index\", value: 1 }],\n      },\n      {\n        key: \"extra\",\n        label: \"\",\n        type: FormItemType.custom,\n        customFormItem: (\n          <>\n            <JsonEditorWrapper\n              data={\"\"}\n              isNeedAutoIndent={true}\n              title={\"编辑器\"}\n              loading={false}\n              docType=\"mapping\"\n              setEditorInstance={(editor) => {\n                setActiveInstance(editor);\n              }}\n              docUrl={documentHref}\n              exampleElement={exampleElement()}\n              jsonClassName={\"index-edit-json\"}\n            />\n          </>\n        ),\n      },\n    ] as IFormItem[],\n    type: \"drawer\",\n    visible: true,\n    title: type === \"shrink\" ? \"执行shrink\" : \"执行split\",\n    needBtnLoading: true,\n    width: 500,\n    needSuccessMessage: false,\n    onCancel: () => {\n      props.dispatch(actions.setDrawerId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      try {\n        const value = activeInstance ? activeInstance.getValue() : \"\";\n        if (type === \"split\" && (!value || value === \"{}\")) {\n          message.error(\"JSON不能为空\");\n          return new Promise((resolve) => {\n            resolve(\"\");\n          });\n        }\n        let jsonValue = {};\n        if (value) {\n          jsonValue = JSON.parse(value || \"null\");\n        }\n        const params = {\n          cluster: indexs.cluster,\n          index: indexs.index,\n          targetIndex: result.targetIndex,\n          extra: formatJsonStr(value),\n        };\n        const submitFn = type === \"shrink\" ? executeShrink : executeSplit;\n        return submitFn(params).then(() => {\n          message.success(`操作提交成功，任务异步执行`);\n          props.dispatch(actions.setDrawerId(\"\"));\n          props.cb && props.cb(); // 重新获取数据列表\n        });\n      } catch {\n        message.error(\"JSON格式有误\");\n        return new Promise((resolve) => {\n          resolve(\"\");\n        });\n      }\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/drawer/index.less",
    "content": ".tasklist-detail,\n.scheduling-log {\n  margin-top: 16px;\n\n  .ant-descriptions-item-label,\n  .ant-descriptions-item-content {\n    line-height: 1;\n  }\n}\n\n.scheduling-detail {\n  margin-top: 16px;\n}\n\n.index-edit-json {\n  height: calc(100vh - 285px);\n}\n\n.steps-content {\n  padding: 0 26px;\n  .ant-form {\n    padding: 0 48px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/drawer/mapping-diff.less",
    "content": ".mapping-diff {\n  &-mapping {\n    padding: 24px;\n\n    &-header {\n      height: 36px;\n      width: 100%;\n      font-family: PingFangSC-Regular;\n      font-size: 14px;\n      color: #303a51;\n\n\n      &-before {\n        float: left;\n        width: 504px;\n        height: 36px;\n        padding: 7px 0px 7px 20px;\n        background: #FFFFFF;\n        border: 1px solid #EBEDEF;\n        border-bottom: 0px;\n        border-radius: 4px 4px 0 0;\n      }\n\n      &-after {\n        float: right;\n        width: 504px;\n        height: 36px;\n        padding: 7px 0px 7px 20px;\n        background: #FFFFFF;\n        border: 1px solid #EBEDEF;\n        border-bottom: 0px;\n        border-radius: 4px 4px 0 0;\n      }\n    }\n  }\n\n  .react-diff-code-view {\n    .CodeMirror {\n      height: calc(100vh - 160px);\n      background: #F5F7FA;\n      font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;\n      color: #343741;\n    }\n\n    .cm-s-default .cm-string {\n      color: #00739d;\n    }\n\n    .CodeMirror-line {\n      span {\n        .cm-string:last-of-type {\n          color: #007c1e;\n        }\n\n        .cm-number:last-of-type {\n          color: #007c1e;\n        }\n\n        .cm-string:first-of-type {\n          color: #00739d;\n        }\n      }\n\n      .cm-string {\n        :first-child {\n          color: #00739d;\n        }\n\n        :last-child {\n          color: #007c1e;\n        }\n      }\n    }\n\n    .CodeMirror-gutters {\n      background-color: #fff;\n      color: #69707D;\n    }\n\n    .CodeMirror-linenumber {\n      color: #69707D;\n    }\n\n    .CodeMirror-merge {\n      height: calc(100vh - 160px);\n      border: none;\n    }\n\n    .CodeMirror-merge-editor {\n      position: absolute;\n      right: 0px;\n      border: 1px solid #ebedef;\n      width: 504px;\n    }\n\n    .CodeMirror-merge-pane-rightmost {\n      position: absolute;\n      left: 0px;\n      border: 1px solid #ebedef;\n      width: 504px;\n    }\n\n    .CodeMirror-merge-r-deleted {\n      background-image: none;\n    }\n\n    .CodeMirror-merge-r-inserted {\n      background-image: none;\n    }\n  }\n\n  .react-diff-dynamic-code-view {\n    .CodeMirror {\n      height: calc(100vh - 160px);\n    }\n\n    .CodeMirror-merge {\n      height: calc(100vh - 160px);\n      border: none;\n    }\n\n    .CodeMirror-merge-editor {\n      position: absolute;\n      right: 0px;\n      border: 1px solid #ebedef;\n      width: 504px;\n    }\n\n    .CodeMirror-merge-pane-rightmost {\n      position: absolute;\n      left: 0px;\n      border: 1px solid #ebedef;\n      width: 504px;\n    }\n\n    .CodeMirror-merge-r-deleted {\n      background-image: none;\n    }\n\n    .CodeMirror-merge-r-inserted {\n      background-image: none;\n    }\n  }\n}"
  },
  {
    "path": "arius-console/src/container/drawer/mapping-diff.tsx",
    "content": "import { Drawer, Tag } from \"antd\";\nimport React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { getFormatJsonStr } from \"lib/utils\";\nimport \"./mapping-diff.less\";\n\nimport CodeMirror from \"codemirror\"; //引入codeMirror\nimport \"codemirror/addon/merge/merge.css\"; //引入codeMirror样式\nimport \"codemirror/addon/merge/merge.css\";\nimport \"codemirror/addon/merge/merge.js\";\nimport \"codemirror/mode/javascript/javascript\";\nimport \"codemirror/mode/xml/xml\";\nimport \"codemirror/mode/python/python\";\nimport \"codemirror/mode/markdown/markdown\";\nimport \"codemirror/addon/fold/foldgutter.css\";\nimport \"codemirror/addon/fold/foldcode\";\nimport \"codemirror/addon/fold/brace-fold\"; //折叠js\nimport \"codemirror/addon/fold/xml-fold\"; //折叠xml和html\nimport \"codemirror/addon/fold/markdown-fold\"; //折叠md\nimport \"codemirror/addon/fold/comment-fold\"; //折叠注释，但是测试一下只能折叠html的注释；\nimport \"codemirror/addon/selection/active-line\";\nimport DiffMatchPatch from \"diff-match-patch\";\n(window as any).diff_match_patch = DiffMatchPatch;\n(window as any).DIFF_DELETE = -1;\n(window as any).DIFF_INSERT = 1;\n(window as any).DIFF_EQUAL = 0;\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n});\nclass MappingSettingDiff extends React.Component<any> {\n  public constructor(props) {\n    super(props);\n  }\n\n  public componentDidMount() {\n    this.initUI(this.props.params?.data);\n  }\n\n  public componentWillReceiveProps(nextProps) {\n    this.initUI(nextProps.params?.data);\n  }\n\n  public initUI(data) {\n    let operate = this.props.params?.operate;\n    const target = document.querySelector(\".react-diff-code-view\"); // 获取dom元素\n    const oldData = data?.source;\n    const newData = data?.target;\n    // target.innerHTML = \"\"; // 每次dom元素的内容清空\n    CodeMirror.MergeView(\n      target,\n      Object.assign(\n        {},\n        {\n          readOnly: true, // 只读\n          lineNumbers: true, // 显示行号\n          // theme: 'eclipse', // 设置主题\n          value: operate === \"配置文件\" ? newData || \"\" : getFormatJsonStr(newData), // 右边的内容（新内容）\n          orig: operate === \"配置文件\" ? oldData || \"\" : getFormatJsonStr(oldData), // 左边的内容（旧内容）\n          mode: \"javascript\", // 代码模式为js模式，这里还可以是xml，python，java，等等，会根据不同代码模式实现代码高亮\n          highlightDifferences: \"highlight\", // 有差异的地方是否高亮\n          connect: null,\n          revertButtons: false, // revert按钮设置为true可以回滚\n          // styleActiveLine: true, // 光标所在的位置代码高亮\n          lineWrap: true, // 文字过长时，是换行(wrap)还是滚动(scroll),默认是滚动\n          smartIndent: true, // 智能缩进\n          matchBrackets: true, // 括号匹配\n          foldGutter: true, // 代码折叠\n          gutters: [\"CodeMirror-linenumbers\", \"CodeMirror-foldgutter\"],\n        }\n      )\n    );\n    setTimeout(() => {\n      const scrolllocks = document.querySelectorAll(\".CodeMirror-merge-scrolllock\");\n      const gaps = document.querySelectorAll(\".CodeMirror-merge-gap\");\n      if (scrolllocks && scrolllocks.length) {\n        scrolllocks.forEach((item: any) => {\n          item.click();\n        });\n      }\n      if (gaps && gaps.length) {\n        gaps.forEach((item: any) => {\n          item?.setAttribute(\"style\", `visibility: hidden `);\n        });\n      }\n    }, 300);\n  }\n\n  public render() {\n    const { dispatch, params } = this.props;\n    const operate = params?.operate;\n    return (\n      <Drawer\n        title={`${operate}对比`}\n        visible={true}\n        onClose={() => dispatch(actions.setDrawerId(\"\"))}\n        width={1080}\n        maskClosable={true}\n        bodyStyle={{ padding: \"0px\" }}\n      >\n        <div className=\"mapping-diff\">\n          <div className=\"mapping-diff-mapping\">\n            <div className=\"mapping-diff-mapping-header\">\n              <div className=\"mapping-diff-mapping-header-before\">\n                {`${operate}${operate === \"配置文件\" ? \"\" : \"编辑器\"}`}\n                <Tag style={{ color: \"#5B6675\", marginLeft: 10 }}>{operate === \"配置文件\" ? \"变更前\" : \"编辑前\"}</Tag>\n              </div>\n              <div className=\"mapping-diff-mapping-header-after\">\n                {`${operate}${operate === \"配置文件\" ? \"\" : \"编辑器\"}`}\n                <Tag color=\"green\" style={{ marginLeft: 10 }}>\n                  {operate === \"配置文件\" ? \"变更后\" : \"编辑后\"}\n                </Tag>\n              </div>\n            </div>\n            <div className=\"react-diff-code-view\"></div>\n          </div>\n        </div>\n      </Drawer>\n    );\n  }\n}\nexport default connect(mapStateToProps)(MappingSettingDiff);\n"
  },
  {
    "path": "arius-console/src/container/drawer/node-monitor.tsx",
    "content": "import { Drawer }  from 'antd';\nimport React from 'react';\nimport { connect } from \"react-redux\";\nimport * as actions from 'actions';\nimport { PageIFrameContainer } from 'container/iframe-page';\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n});\nclass NodeMonitorDrawer extends React.Component<any> {\n\n\n  public render() {\n    const { dispatch } = this.props\n     const str = `/console/arius/kibana7/app/kibana#/dashboard/17d17640-5a32-11eb-af34-ad99b4265825?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:Arius%E8%8A%82%E7%82%B9%E7%9A%84%E7%9B%91%E6%8E%A7%E6%8C%87%E6%A0%87,filters:!(),fullScreenMode:!f,options:(hidePanelTitles:!f,useMargins:!t),panels:!((embeddableConfig:(),gridData:(h:15,i:a4f4c258-36d1-4a51-b2bb-fb1158d053d8,w:24,x:0,y:0),id:d5c80080-5a2b-11eb-af34-ad99b4265825,panelIndex:a4f4c258-36d1-4a51-b2bb-fb1158d053d8,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:c60cb2ad-6713-4da2-a335-8d4a1d7071ca,w:24,x:24,y:0),id:'55633270-5a2b-11eb-af34-ad99b4265825',panelIndex:c60cb2ad-6713-4da2-a335-8d4a1d7071ca,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:c350f4e6-23c6-4df8-9b8a-73075225de46,w:24,x:0,y:15),id:'9a3d8a30-5a2b-11eb-af34-ad99b4265825',panelIndex:c350f4e6-23c6-4df8-9b8a-73075225de46,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:e0141327-2671-45e1-8b9b-bda621977a22,w:24,x:24,y:15),id:'1cd26cc0-5a2e-11eb-af34-ad99b4265825',panelIndex:e0141327-2671-45e1-8b9b-bda621977a22,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:'8922c138-37ac-4976-9ae5-83c3dca54416',w:24,x:0,y:30),id:'278d76f0-5a2e-11eb-af34-ad99b4265825',panelIndex:'8922c138-37ac-4976-9ae5-83c3dca54416',type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:bf137eb1-b906-46e3-967a-a06687967065,w:24,x:24,y:30),id:'9519d0d0-5a2c-11eb-af34-ad99b4265825',panelIndex:bf137eb1-b906-46e3-967a-a06687967065,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:'1e3b73d1-5235-4160-8e00-4a03f203a5dc',w:24,x:0,y:45),id:'707954c0-5a2d-11eb-af34-ad99b4265825',panelIndex:'1e3b73d1-5235-4160-8e00-4a03f203a5dc',type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:'78fb0a32-3ea8-4657-a21b-0dad044f087a',w:24,x:24,y:45),id:d2e620d0-5a2c-11eb-af34-ad99b4265825,panelIndex:'78fb0a32-3ea8-4657-a21b-0dad044f087a',type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:e704b854-1cc7-4e87-a27e-7fdd2a5f200d,w:24,x:0,y:60),id:'21ec8930-5a2d-11eb-af34-ad99b4265825',panelIndex:e704b854-1cc7-4e87-a27e-7fdd2a5f200d,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:b988c487-eef5-4665-8da1-1ed2584195af,w:24,x:24,y:60),id:'1b240b60-5a2c-11eb-af34-ad99b4265825',panelIndex:b988c487-eef5-4665-8da1-1ed2584195af,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:'684a51e5-b145-4dc4-8bd3-9384002dbc7c',w:24,x:0,y:75),id:'536ceb40-5a2c-11eb-af34-ad99b4265825',panelIndex:'684a51e5-b145-4dc4-8bd3-9384002dbc7c',type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:'924bdd72-8936-4366-9ec1-92f8c245b2fb',w:24,x:24,y:75),id:c3554440-5a2f-11eb-af34-ad99b4265825,panelIndex:'924bdd72-8936-4366-9ec1-92f8c245b2fb',type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:'397d936d-6f73-439d-9f13-595298024449',w:24,x:0,y:90),id:'2f5f9c90-5a2f-11eb-af34-ad99b4265825',panelIndex:'397d936d-6f73-439d-9f13-595298024449',type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:ca9241be-9d5c-4333-8c28-5f97a06ec6d8,w:24,x:24,y:90),id:'5fc3e040-5a2e-11eb-af34-ad99b4265825',panelIndex:ca9241be-9d5c-4333-8c28-5f97a06ec6d8,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:'785f9ff6-79b8-4da0-88f7-203d8c1be7a7',w:24,x:0,y:105),id:'986b81f0-5a2e-11eb-af34-ad99b4265825',panelIndex:'785f9ff6-79b8-4da0-88f7-203d8c1be7a7',type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:a40d3e46-f4f3-43d8-9c60-d87369cd89f3,w:24,x:24,y:105),id:fcb03060-5a2f-11eb-af34-ad99b4265825,panelIndex:a40d3e46-f4f3-43d8-9c60-d87369cd89f3,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:d9d56a54-0dbc-4537-a840-7bf3ccfeb81f,w:24,x:0,y:120),id:'56ca7150-5a30-11eb-af34-ad99b4265825',panelIndex:d9d56a54-0dbc-4537-a840-7bf3ccfeb81f,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:'50520d14-ff37-483c-a7d7-3c5dc0fec975',w:24,x:24,y:120),id:'2cdcd760-5a31-11eb-af34-ad99b4265825',panelIndex:'50520d14-ff37-483c-a7d7-3c5dc0fec975',type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:a6a26f96-c93d-468f-a31b-8d4eceea060a,w:24,x:0,y:135),id:e92cced0-5a30-11eb-af34-ad99b4265825,panelIndex:a6a26f96-c93d-468f-a31b-8d4eceea060a,type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:'25f879e6-b74f-4720-9fa4-1eac812ac5b1',w:24,x:24,y:135),id:'76fe3280-5a31-11eb-af34-ad99b4265825',panelIndex:'25f879e6-b74f-4720-9fa4-1eac812ac5b1',type:visualization,version:'7.6.0-SNAPSHOT'),(embeddableConfig:(),gridData:(h:15,i:'87545db1-d8ee-4800-9977-0f949077e177',w:24,x:0,y:150),id:b3e68b20-5a31-11eb-af34-ad99b4265825,panelIndex:'87545db1-d8ee-4800-9977-0f949077e177',type:visualization,version:'7.6.0-SNAPSHOT')),query:(language:kuery,query:'node:${this.props.params.node}'),timeRestore:!f,title:arius_node_monitor,viewMode:view)`;\n    return (\n      <Drawer\n        title={'节点监控'}\n        visible={true}\n        onClose={() => dispatch(actions.setDrawerId(''))}\n        width={1000}\n        maskClosable={true}\n      >\n        <PageIFrameContainer src={str} />\n      </Drawer>\n    );\n  }\n}\nexport default connect(mapStateToProps)(NodeMonitorDrawer);\n\n\n"
  },
  {
    "path": "arius-console/src/container/drawer/scheduling-detail.tsx",
    "content": "import { Drawer, Card, Descriptions } from \"antd\";\nimport React from \"react\";\nimport \"./index.less\";\n\nconst DescriptionsItem = Descriptions.Item;\n\ninterface IProps {\n  visible: boolean;\n  record: any;\n  onCancel: () => void;\n}\n\nconst SchDulingDetail: React.FC<IProps> = (props: IProps) => {\n  const { record } = props;\n  const renderDetail = () => {\n    return (\n      <Card title=\"基本信息\" key=\"1\" type=\"inner\" className=\"scheduling-detail\">\n        <Descriptions column={1}>\n          <DescriptionsItem label=\"地址列表\">{record?.allWorkerIps?.join(\"，\")}</DescriptionsItem>\n        </Descriptions>\n      </Card>\n    );\n  };\n\n  const renderHandleSchduling = () => {\n    const rusult = JSON.parse(record?.result || \"{}\");\n    return (\n      <Card title=\"触发调度\" key=\"2\" type=\"inner\" style={{ marginTop: 20 }}>\n        <Descriptions column={1}>\n          <DescriptionsItem label=\"address\">{record?.workerIp}</DescriptionsItem>\n          <DescriptionsItem label=\"code\">{rusult?.code}</DescriptionsItem>\n          <DescriptionsItem label=\"message\">{rusult?.message}</DescriptionsItem>\n        </Descriptions>\n      </Card>\n    );\n  };\n  return (\n    <Drawer title={\"调度详情\"} visible={props.visible} width={600} maskClosable={true} onClose={props.onCancel}>\n      {renderDetail()}\n      {renderHandleSchduling()}\n    </Drawer>\n  );\n};\nexport default SchDulingDetail;\n"
  },
  {
    "path": "arius-console/src/container/drawer/scheduling-log.tsx",
    "content": "import React from \"react\";\nimport { Drawer, Descriptions } from \"antd\";\nimport { ReloadOutlined } from \"@ant-design/icons\";\nimport \"./index.less\";\n\nconst DescriptionsItem = Descriptions.Item;\n\ninterface IProps {\n  visible: boolean;\n  error: string;\n  onCancel: () => void;\n}\n\nconst SchDulingLog: React.FC<IProps> = (props: IProps) => {\n  const getWidth = () => {\n    return document.querySelector(\"#d1-layout-main\")?.clientWidth || 600;\n  };\n  return (\n    <Drawer title={\"执行日志\"} visible={props.visible} width={getWidth()} maskClosable={true} onClose={props.onCancel}>\n      {/* <ReloadOutlined onClick={() => console.log(1)} style={reloadstyle} /> */}\n      <div>\n        <Descriptions column={1} className=\"scheduling-log\">\n          {JSON.parse(props?.error || \"{}\")\n            ?.message?.split(\"\\n\")\n            ?.map((item, index) => (\n              <DescriptionsItem key={index}>{item}</DescriptionsItem>\n            ))}\n        </Descriptions>\n        [Load Log Finish]\n      </div>\n    </Drawer>\n  );\n};\nexport default SchDulingLog;\n"
  },
  {
    "path": "arius-console/src/container/drawer/shard-list/config.tsx",
    "content": "import { Tooltip } from \"antd\";\nimport { bytesUnitFormatter } from \"lib/utils\";\nimport React from \"react\";\n\n\nexport const queryFormText: { searchText: string, resetText: string } = {\n  searchText: '查询',\n  resetText: '重置'\n};\n\n\nexport const formColumns = [\n  {\n    type: 'input',\n    title: '主机名称',\n    dataIndex: 'ip',\n    placeholder: \"请输入\",\n  }\n];\n\n\nexport const renderText = (text) => {\n  return (\n    <div className=\"dsl-overflow-auto\">\n      {text}\n    </div>\n  )\n}\nconst columnsRender = (item: string, width: string = \"none\") => {\n  return <div className=\"two-row-ellipsis pointer\" style={{\n    width: width\n  }}>\n    <Tooltip placement=\"right\" title={renderText(item)}>{item}</Tooltip>\n  </div>;\n};\n\nexport const getColumns = (setModalId?: any,\n  setDrawerId?: any,\n  reloadDataFn?: any) => {\n  return [\n    {\n      title: \"主机名称\",\n      dataIndex: \"ip\",\n      render: (item, row) =>  {\n        return {\n          children: columnsRender(item),\n          props: {\n            rowSpan: row.rowSpan\n          },\n        };\n      }\n    },\n    {\n      title: \"Shard个数\",\n      dataIndex: \"shardCount\",\n      render: (item, row) =>  {\n        return {\n          children: columnsRender(item),\n          props: {\n            rowSpan: row.rowSpan\n          },\n        };\n      }\n    },\n    {\n      title: \"文档总个数\",\n      dataIndex: \"totalDocs\",\n      render: (item, row) =>  {\n        return {\n          children: columnsRender(item),\n          props: {\n            rowSpan: row.rowSpan\n          },\n        };\n      }\n    },\n    {\n      title: \"总存储大小\",\n      dataIndex: \"totalStore\",\n      render: (item, row) =>  {\n        return {\n          children: bytesUnitFormatter(item, \"float\"),\n          props: {\n            rowSpan: row.rowSpan\n          },\n        };\n      }\n    },\n    {\n      title: \"shard序号\",\n      dataIndex: \"shard\",\n      render: (item) => columnsRender(item),\n    },\n    {\n      title: \"进程名称\",\n      dataIndex: \"node\",\n      render: (item) => columnsRender(item),\n    },\n    {\n      title: \"文档个数\",\n      dataIndex: \"docs\",\n      render: (item) => columnsRender(item),\n    },\n    {\n      title: \"存储大小\",\n      dataIndex: \"storeInByte\",\n      render: (item) => bytesUnitFormatter(item, \"float\"),\n    },\n  ].map(item => ({\n    ...item,\n    align: 'center'\n  }))\n};\n\n"
  },
  {
    "path": "arius-console/src/container/drawer/shard-list/index.less",
    "content": ".shard-list-header {\n  .ant-col-offset-8 {\n    margin-left: 0;\n  }\n}\n\n.dsl-overflow-auto {\n  overflow: auto;\n  max-height: 300px;\n}\n\n.two-row-ellipsis {\n  text-overflow: -o-ellipsis-lastline;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-line-clamp: 2;\n  line-clamp: 2;\n  -webkit-box-orient: vertical;\n}"
  },
  {
    "path": "arius-console/src/container/drawer/shard-list/index.tsx",
    "content": "import { Drawer } from \"antd\";\nimport React, { memo, useEffect, useState } from \"react\";\nimport { useDispatch, useSelector, shallowEqual } from \"react-redux\";\nimport { formColumns, getColumns, queryFormText } from \"./config\";\nimport QueryForm from \"component/dantd/query-form\";\nimport { DTable } from \"component/dantd/dtable\";\nimport * as actions from \"actions\";\nimport { getShardDetail } from \"api/index-admin\";\nimport \"./index.less\";\n\nexport const ShardList = memo((props) => {\n  const dispatch = useDispatch();\n  const { modal } = useSelector((state) => ({ modal: (state as any).modal }), shallowEqual);\n  const { params = {} } = modal;\n  const clusterName = params.cluster || \"\";\n  const indexName = params.index || \"\";\n\n  const [isLoading, setIsLoading] = useState(false);\n  const [data, setData] = useState([]);\n  const [queryFormObject, setQueryFormObject] = useState({});\n  const [pageSize, setPageSize] = useState(10);\n\n  const handleSubmit = (result) => {\n    for (let key in result) {\n      result[key] = result[key] || \"\";\n    }\n    setQueryFormObject(result);\n  };\n\n  const mergeCell = (data) => {\n    let start = 0;\n    let end = 0;\n    // 用来判断元素是否在一页数据中重复出现\n    let obj = {};\n    const newData = data.map((item, index) => {\n      // 根据 pageSize 大小判断合并单元格数，避免出现，分页多合并单元格的情况\n      // 每达到一页数据，更新初始值\n      if (index % pageSize === 0) {\n        start = end;\n        end += pageSize;\n        obj = {};\n      }\n      // 截取这一页的数据\n      const pageData = data.slice(start, end);\n\n      const newItem = {\n        // 判断是否是当前页第一次出现，合并相同单元格，否则不展示\n        rowSpan: !obj[item.node] ? pageData?.filter((i) => item.node === i.node).length : 0,\n        ...item,\n      };\n      // 记录已经出现过的单元格\n      obj[item.node] = true;\n\n      return newItem;\n    });\n\n    return newData;\n  };\n\n  const getData = () => {\n    // 查询项的key 要与 数据源的key  对应\n    const keys = Object.keys(queryFormObject);\n\n    if (!queryFormObject || !keys.length) return mergeCell(data);\n\n    const filterData = data.filter((d) => {\n      let flag = true;\n      keys.forEach((item) => {\n        if (queryFormObject[item] && d[item] && !d[item].includes(queryFormObject[item])) {\n          flag = false;\n        }\n      });\n      return flag;\n    });\n    return mergeCell(filterData);\n  };\n\n  const getAsyncData = async () => {\n    setIsLoading(true);\n    try {\n      const res = await getShardDetail(clusterName, indexName);\n      if (!res) {\n        return;\n      }\n      // 对数组中相同 ip 的元素进行聚合，相加\n      for (let i = 0; i < res.length; i++) {\n        let temp = res[i];\n        temp.totalDocs = temp.docs || 0;\n        temp.totalStore = temp.storeInByte || 0;\n        temp.shardCount = 1;\n        temp.shardCells = [\n          {\n            node: temp.node,\n            shard: temp.shard,\n            docs: temp.docs,\n            storeInByte: temp.storeInByte,\n          },\n        ];\n        for (let j = i + 1; j < res.length; j++) {\n          if (temp.ip === res[j].ip) {\n            temp.totalDocs += res[j].docs || 0;\n            temp.totalStore += res[j].storeInByte || 0;\n            temp.shardCount++;\n            temp.shardCells.push({\n              node: res[j].node,\n              shard: res[j].shard,\n              docs: res[j].docs,\n              storeInByte: res[j].storeInByte,\n            });\n            res.splice(j, 1);\n            j--;\n          }\n        }\n      }\n      const data = [];\n      let i = 0;\n      res.forEach((item) => {\n        data.push(...item.shardCells.map((cell) => ({ ...item, ...cell, key: i++ })));\n      });\n      setData(data);\n    } catch (error) {\n      console.log(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const reloadData = () => {\n    getAsyncData();\n  };\n\n  const pageChange = (pagination) => {\n    if (pagination.pageSize === pageSize) {\n      return;\n    }\n    setPageSize(pagination.pageSize);\n  };\n\n  useEffect(() => {\n    getAsyncData();\n  }, []);\n\n  return (\n    <Drawer\n      title=\"Shard 列表\"\n      placement=\"right\"\n      className=\"index-container\"\n      width={`calc(100% - 190px)`}\n      visible={true}\n      onClose={() => {\n        dispatch(actions.setDrawerId(\"\"));\n      }}\n    >\n      <div className=\"shard-list-header\">\n        <QueryForm\n          onReset={handleSubmit}\n          onSearch={handleSubmit}\n          onChange={() => {}}\n          columns={formColumns}\n          initialValues={{}}\n          isResetClearAll\n          {...queryFormText}\n          defaultCollapse\n          showCollapseButton={false}\n        />\n      </div>\n      <div className=\"table-content\">\n        <DTable\n          loading={isLoading}\n          rowKey=\"key\"\n          dataSource={getData()}\n          attrs={{\n            bordered: true,\n            onChange: pageChange,\n          }}\n          paginationProps={{\n            position: \"bottomRight\",\n            showQuickJumper: true,\n            showSizeChanger: true,\n            pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n            showTotal: (total) => `共 ${total} 条`,\n          }}\n          reloadData={reloadData}\n          columns={getColumns()}\n        />\n      </div>\n    </Drawer>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/drawer/tasklist-detail.tsx",
    "content": "import React from \"react\";\nimport { Drawer, Descriptions } from \"antd\";\nimport \"./index.less\";\n\nconst DescriptionsItem = Descriptions.Item;\n\ninterface IProps {\n  visible: boolean;\n  detailData: any;\n  onCancel: () => void;\n}\n\nconst SchDulingLog: React.FC<IProps> = (props: IProps) => {\n  const { detailData } = props;\n  const typeMap = [\n    {\n      type: \"任务名称\",\n      value: detailData?.taskDesc || \"-\",\n    },\n    {\n      type: \"路由策略\",\n      value: detailData?.routing || \"-\",\n    },\n    {\n      type: \"Cron\",\n      value: detailData?.cron || \"-\",\n    },\n    {\n      type: \"运行模式\",\n      value: detailData?.runningType || \"-\",\n    },\n    {\n      type: \"JobHandler\",\n      value: detailData?.className || \"-\",\n    },\n    {\n      type: \"运行参数\",\n      value: detailData?.params || \"-\",\n    },\n    {\n      type: \"阻塞处理策略\",\n      value: detailData?.blockPolicy || \"-\",\n    },\n    {\n      type: \"责任人\",\n      value: detailData?.owner || \"-\",\n    },\n  ];\n  return (\n    <Drawer title={\"任务详情\"} visible={props.visible} width={600} maskClosable={true} onClose={props.onCancel}>\n      <div>\n        <Descriptions className=\"tasklist-detail\" column={1} labelStyle={{ justifyContent: \"flex-end\", minWidth: 100 }}>\n          {typeMap.map((item, index) => (\n            <DescriptionsItem key={index} label={item.type}>\n              {item.value}\n            </DescriptionsItem>\n          ))}\n        </Descriptions>\n      </div>\n    </Drawer>\n  );\n};\nexport default SchDulingLog;\n"
  },
  {
    "path": "arius-console/src/container/drawer/template-create.tsx",
    "content": "import { message } from \"antd\";\nimport { Button, Steps, Drawer } from \"knowdesign\";\nimport React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { Dispatch } from \"redux\";\nimport { FormItemType, IFormItem, XForm as XFormComponent } from \"component/x-form\";\nimport { AppState } from \"store/type\";\nimport { SetMapping, SetSetting, Preview } from \"../index-tpl-management/component\";\nimport { createIndex, getNameCheck, getClusterCheck, getTimeFormat } from \"api/cluster-index-api\";\nimport { LEVEL_MAP } from \"constants/common\";\nimport { KEEP_LIVE_LIST } from \"constants/time\";\nimport { CYCLICAL_ROLL_TYPE_LIST } from \"container/index-tpl-management/create/constant\";\nimport { formatJsonStr, getFormatJsonStr } from \"lib/utils\";\nimport { LogicCluserSelect } from \"container/custom-form/logic-cluser-select\";\nimport { nounPartitionCreate } from \"container/tooltip\";\n\nconst { Step } = Steps;\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params, cb)),\n});\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  app: state.app,\n  cb: state.modal.cb,\n});\n\nclass CreateTemplate extends React.Component<{\n  app: AppState;\n  cb: Function;\n  setDrawerId: Function;\n  params: any;\n}> {\n  state = {\n    loading: false,\n    visible: false,\n    current: 0,\n    isCyclicalRoll: false,\n    dataCenter: null,\n    baseInfoData: {} as any,\n    mapping: \"\",\n    setting: getFormatJsonStr({\n      index: {\n        \"translog.durability\": \"async\",\n        \"translog.sync_interval\": \"15s\",\n        refresh_interval: \"1s\",\n        // codec: \"default\",\n      },\n    }),\n    timeFormatList: [],\n  };\n\n  $formRef: any = React.createRef();\n  $mappingRef: any = React.createRef();\n  $settingRef: any = React.createRef();\n  $previewRef: any = React.createRef();\n\n  steps = [\n    {\n      title: \"基础信息\",\n      content: \"baseInfo\",\n    },\n    {\n      title: \"Mapping设置\",\n      content: \"Mapping\",\n    },\n    {\n      title: \"Setting设置\",\n      content: \"Setting\",\n    },\n    {\n      title: \"设置完成\",\n      content: \"Review\",\n    },\n  ];\n\n  formMap = (): IFormItem[] => {\n    const { isCyclicalRoll, timeFormatList } = this.state;\n    return [\n      {\n        key: \"name\",\n        label: \"索引模板名称\",\n        attrs: {\n          placeholder: \"请填写索引模板名称，支持小写字母、数字、-、_4-128位字符\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: string) => {\n              value = value?.trim();\n              const reg = /^[.a-z0-9_-]{1,}$/g;\n              if (!value) {\n                return Promise.reject(\"请填写索引模板名称\");\n              }\n              if (!reg.test(value) || value.length > 128 || value.length < 4) {\n                return Promise.reject(\"请正确填写索引模板名称，支持小写字母、数字、-、_4-128位字符\");\n              }\n              if (value) {\n                try {\n                  const res = await getNameCheck(value);\n                  if (res.code !== 0 && res.code !== 200) {\n                    return Promise.reject(res.message);\n                  }\n                } catch (err) {\n                  return Promise.reject(\"索引模板名称校验失败\");\n                }\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"clusterInfo\",\n        label: \"所属集群\",\n        type: FormItemType.custom,\n        customFormItem: <LogicCluserSelect isModifyPage={false} $form={this.$formRef} onChange={this.onClusterInfoChange} />,\n        rules: [\n          {\n            required: true,\n            message: \"请填写完整\",\n            validator: async (rule: any, value: any) => {\n              if (!value) return Promise.reject();\n              if (value.cluster) {\n                try {\n                  const res = await getClusterCheck(value.cluster);\n                  if (res.code !== 0 && res.code !== 200) {\n                    return Promise.reject(res.message);\n                  }\n                } catch (err) {\n                  return Promise.reject(\"所属集群校验失败\");\n                }\n                return Promise.resolve();\n              }\n              return Promise.reject();\n            },\n          },\n        ],\n      },\n      {\n        key: \"level\",\n        label: \"业务等级\",\n        type: FormItemType.select,\n        rules: [\n          {\n            required: true,\n            message: \"请选择业务等级\",\n          },\n        ],\n        attrs: {\n          placeholder: \"请选择业务等级\",\n        },\n        options: LEVEL_MAP,\n      },\n      {\n        key: \"cyclicalRoll\",\n        label: \"是否分区\",\n        type: FormItemType.select,\n        rules: [{ required: true, message: \"请选择是否分区\" }],\n        attrs: {\n          placeholder: \"请选择是否分区\",\n          onChange: (value) => {\n            this.setState({ isCyclicalRoll: value === \"more\" });\n          },\n        },\n        options: CYCLICAL_ROLL_TYPE_LIST,\n        extraElement: <>{nounPartitionCreate}</>,\n      },\n      {\n        key: \"dateField\",\n        label: \"分区字段\",\n        invisible: !isCyclicalRoll,\n        attrs: {\n          placeholder: \"请输入分区字段\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: string) => {\n              value = value?.trim();\n              if (!value || value.length > 20) {\n                return Promise.reject(\"请输入分区字段，不超过20位字符\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      [\n        {\n          key: \"dateFieldFormat\",\n          label: \"时间格式\",\n          invisible: !isCyclicalRoll,\n          type: FormItemType.select,\n          rules: [{ required: true, message: \"请选择时间格式\" }],\n          options: timeFormatList.map((item) => ({\n            label: item,\n            value: item,\n          })),\n          attrs: {\n            placeholder: \"请选择时间格式\",\n          },\n        },\n        {\n          key: \"expireTime\",\n          label: \"保存周期(天)\",\n          invisible: !isCyclicalRoll,\n          type: FormItemType.select,\n          defaultValue: KEEP_LIVE_LIST[0],\n          rules: [{ required: true, message: \"请选择保存周期\" }],\n          options: KEEP_LIVE_LIST.map((item) => {\n            return {\n              label: item === -1 ? \"永不过期\" : item,\n              value: item,\n            };\n          }),\n        },\n      ],\n      [\n        {\n          key: \"diskSize\",\n          label: \"索引模板数据大小(GB)\",\n          formAttrs: {\n            dependencies: [\"clusterInfo\"],\n          },\n          defaultValue: 30,\n          type: FormItemType.inputNumber,\n          rules: [\n            {\n              required: true,\n              validator: (rule: any, value: number) => {\n                if (typeof value !== \"number\") {\n                  return Promise.reject(\"请输入数据大小(GB)，最小3G, 最大3072G\");\n                }\n                if (value === Infinity || value < 0) {\n                  return Promise.reject(\"请输入数据大小(GB)，最小3G, 最大3072G\");\n                }\n\n                if (value < 3 || value > 3072) {\n                  return Promise.reject(\"请输入数据大小(GB)，最小3G, 最大3072G\");\n                }\n                return Promise.resolve();\n              },\n            },\n          ],\n          attrs: {\n            placeholder: \"请输入\",\n            style: {\n              width: \"100%\",\n            },\n          },\n        },\n        {\n          key: \"dataType\",\n          label: \"业务类型\",\n          type: FormItemType.select,\n          rules: [{ required: true, message: \"请选择业务类型\" }],\n          options: this.props.params.dataTypeList,\n          attrs: {\n            placeholder: \"请选择业务类型\",\n          },\n        },\n      ],\n      {\n        key: \"desc\",\n        label: \"模板描述\",\n        type: FormItemType.textArea,\n        attrs: {\n          placeholder: \"请输入0-1000字模板描述\",\n        },\n        rules: [\n          {\n            validator: (rule: any, value: string) => {\n              value = value?.trim();\n              if (!value) {\n                return Promise.resolve();\n              } else if (value.length > 1000) {\n                return Promise.reject(\"请输入0-1000字模板描述\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n    ] as IFormItem[];\n  };\n\n  onClusterInfoChange = (value: any) => {\n    this.$formRef?.current.setFieldsValue({ level: value?.level }); // 选择集群后给level初始值\n    this.setState({\n      dataCenter: value?.dataCenter,\n    });\n  };\n\n  getTimeFormatList = () => {\n    getTimeFormat().then((res = []) => {\n      this.setState({\n        timeFormatList: res,\n      });\n    });\n  };\n\n  handleCancel = () => {\n    this.props.setDrawerId(\"\");\n  };\n\n  prev = () => {\n    const { current } = this.state;\n    if (current === 1) {\n      this.$mappingRef.handlePre();\n    } else if (current === 2) {\n      this.$settingRef.handlePre();\n    } else if (current === 3) {\n      this.$previewRef.handlePre();\n    }\n  };\n\n  next = () => {\n    const { current } = this.state;\n    if (current === 0) {\n      this.$formRef\n        ?.current!.validateFields()\n        .then((values) => {\n          this.setState({\n            current: 1,\n            baseInfoData: values,\n          });\n        })\n        .catch((errs) => {});\n    } else if (current === 1) {\n      this.$mappingRef.handleNext();\n    } else if (current === 2) {\n      this.$settingRef.handleNext();\n    } else if (current === 3) {\n      this.$previewRef.handleSubmit(this.onSubmit);\n    }\n  };\n\n  onSubmit = () => {\n    const { dataCenter, baseInfoData, mapping, setting } = this.state;\n    const params = {\n      dataCenter,\n      name: `${baseInfoData.name}`,\n      resourceId: baseInfoData.clusterInfo?.cluster,\n      level: baseInfoData.level,\n      cyclicalRoll: baseInfoData.cyclicalRoll === \"more\" ? 1 : 0,\n      expireTime: baseInfoData.expireTime,\n      dateField: baseInfoData.dateField,\n      dateFieldFormat: baseInfoData.dateFieldFormat,\n      diskSize: Number(baseInfoData.diskSize),\n      dataType: baseInfoData.dataType,\n      desc: baseInfoData.desc,\n      mapping: formatJsonStr(mapping),\n      setting: formatJsonStr(setting),\n    };\n    this.setState({\n      loading: true,\n    });\n    createIndex(params)\n      .then(() => {\n        message.success(\"模板创建成功\");\n        this.props.setDrawerId(\"\");\n        this.props.cb();\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n  };\n\n  renderBtn = () => {\n    const { current } = this.state;\n    return [\n      current < 3 ? (\n        <Button key=\"submit3\" type=\"primary\" style={{ marginRight: \"10px\" }} onClick={this.next}>\n          下一步\n        </Button>\n      ) : (\n        \"\"\n      ),\n      current === 3 ? (\n        <Button loading={this.state.loading} key=\"submit4\" type=\"primary\" style={{ marginRight: \"10px\" }} onClick={this.next}>\n          完成\n        </Button>\n      ) : (\n        \"\"\n      ),\n      current > 0 ? (\n        <Button key=\"back2\" style={{ marginRight: \"10px\" }} onClick={this.prev}>\n          上一步\n        </Button>\n      ) : (\n        \"\"\n      ),\n      <Button key=\"back1\" onClick={this.handleCancel}>\n        取消\n      </Button>,\n    ];\n  };\n\n  updateState = (keyValue, cb?: any) => {\n    this.setState(keyValue, cb && cb());\n  };\n\n  renderContent = () => {\n    const { current, isCyclicalRoll, dataCenter, baseInfoData, mapping, setting } = this.state;\n    if (this.steps[current].content === \"baseInfo\") {\n      return <XFormComponent layout=\"vertical\" formData={baseInfoData} formMap={this.formMap()} wrappedComponentRef={this.$formRef} />;\n    } else if (this.steps[current].content === \"Mapping\") {\n      return (\n        <div style={{ marginTop: 20 }}>\n          <SetMapping childEvevnt={(child) => (this.$mappingRef = child)} updateState={this.updateState} data={mapping} />\n        </div>\n      );\n    } else if (this.steps[current].content === \"Setting\") {\n      return (\n        <div style={{ marginTop: 20 }}>\n          <SetSetting childEvevnt={(child) => (this.$settingRef = child)} updateState={this.updateState} data={setting} />\n        </div>\n      );\n    } else if (this.steps[current].content === \"Review\") {\n      return (\n        <Preview\n          childEvevnt={(child) => (this.$previewRef = child)}\n          updateState={this.updateState}\n          data={{ isCyclicalRoll, dataCenter, baseInfoData, mapping, setting }}\n        />\n      );\n    } else {\n      return this.steps[current].content;\n    }\n  };\n\n  componentDidMount() {\n    this.getTimeFormatList();\n  }\n\n  componentWillUnmount() {\n    // 这是一段比较恶心的代码 xform的值无法传下去 但是内部需要接收到\n    (window as any).masternodeErr = false;\n    delete (window as any).masternodeErr;\n  }\n\n  render() {\n    const { current } = this.state;\n    return (\n      <div>\n        <Drawer visible={true} title=\"新建模板\" width={750} onClose={this.handleCancel} footer={this.renderBtn()} maskClosable={false}>\n          <Steps current={current} style={{ margin: \"0 0 30px 0\", padding: \"0 26px\" }}>\n            {this.steps.map((item) => (\n              <Step key={item.title} title={item.title} />\n            ))}\n          </Steps>\n          <div className=\"steps-content\">{this.renderContent()}</div>\n        </Drawer>\n      </div>\n    );\n  }\n}\n\nexport default connect(mapStateToProps, mapDispatchToProps)(CreateTemplate);\n"
  },
  {
    "path": "arius-console/src/container/drawer/template-edit.tsx",
    "content": "import { message } from \"antd\";\nimport { Spin, Drawer, Space, Button, Divider } from \"knowdesign\";\nimport React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { Dispatch } from \"redux\";\nimport { FormItemType, IFormItem, XForm as XFormComponent } from \"component/x-form\";\nimport { AppState } from \"store/type\";\nimport { getIndexBaseInfo, updateIndexInfo, getTimeFormat } from \"api/cluster-index-api\";\nimport { LEVEL_MAP } from \"constants/common\";\nimport { KEEP_LIVE_LIST } from \"constants/time\";\nimport { CYCLICAL_ROLL_TYPE_LIST } from \"container/index-tpl-management/create/constant\";\nimport { LogicCluserSelect } from \"container/custom-form/logic-cluser-select\";\nimport { nounPartitionCreate } from \"container/tooltip\";\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params, cb)),\n});\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  app: state.app,\n  cb: state.modal.cb,\n});\n\nclass EditTemplate extends React.Component<{\n  app: AppState;\n  cb: Function;\n  setDrawerId: Function;\n  params: any;\n}> {\n  state = {\n    loading: false,\n    visible: false,\n    isCyclicalRoll: false,\n    dataCenter: null,\n    baseInfoData: {} as any,\n    timeFormatList: [],\n  };\n\n  $formRef: any = React.createRef();\n  id: number = null;\n\n  constructor(props: any) {\n    super(props);\n    this.id = this.props.params.record?.id;\n  }\n\n  formMap = (): IFormItem[] => {\n    const { isCyclicalRoll, timeFormatList } = this.state;\n    return [\n      {\n        key: \"name\",\n        label: \"索引模板名称\",\n        attrs: {\n          disabled: true,\n          placeholder: \"请填写索引模板名称，支持小写字母、数字、-、_4-128位字符\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: string) => {\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"clusterInfo\",\n        label: \"所属集群\",\n        type: FormItemType.custom,\n        customFormItem: <LogicCluserSelect isModifyPage={true} $form={this.$formRef} onChange={this.onClusterInfoChange} />,\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: any) => {\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"level\",\n        label: \"业务等级\",\n        type: FormItemType.select,\n        rules: [\n          {\n            required: true,\n            message: \"请选择业务等级\",\n          },\n        ],\n        attrs: {\n          disabled: true,\n          placeholder: \"请选择业务等级\",\n        },\n        options: LEVEL_MAP,\n      },\n      {\n        key: \"cyclicalRoll\",\n        label: \"是否分区\",\n        type: FormItemType.select,\n        rules: [{ required: true, message: \"请选择是否分区\" }],\n        attrs: {\n          disabled: true,\n          placeholder: \"请选择是否分区\",\n          onChange: (value) => {\n            this.setState({ isCyclicalRoll: value === \"more\" });\n          },\n        },\n        options: CYCLICAL_ROLL_TYPE_LIST,\n        extraElement: <>{nounPartitionCreate}</>,\n      },\n      {\n        key: \"dateField\",\n        label: \"分区字段\",\n        invisible: !isCyclicalRoll,\n        attrs: {\n          disabled: true,\n          placeholder: \"请输入分区字段\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: string) => {\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      [\n        {\n          key: \"dateFieldFormat\",\n          label: \"时间格式\",\n          invisible: !isCyclicalRoll,\n          type: FormItemType.select,\n          rules: [{ required: true, message: \"请选择时间格式\" }],\n          options: timeFormatList.map((item) => ({\n            label: item,\n            value: item,\n          })),\n          attrs: {\n            disabled: true,\n            placeholder: \"请选择时间格式\",\n          },\n        },\n        {\n          key: \"expireTime\",\n          label: \"保存周期(天)\",\n          invisible: !isCyclicalRoll,\n          type: FormItemType.select,\n          defaultValue: KEEP_LIVE_LIST[0],\n          rules: [{ required: true, message: \"请选择保存周期\" }],\n          options: KEEP_LIVE_LIST.map((item) => {\n            return {\n              label: item === -1 ? \"永不过期\" : item,\n              value: item,\n            };\n          }),\n        },\n      ],\n      [\n        {\n          key: \"diskSize\",\n          label: \"索引模板数据大小(GB)\",\n          formAttrs: {\n            dependencies: [\"clusterInfo\"],\n          },\n          defaultValue: 30,\n          type: FormItemType.inputNumber,\n          rules: [\n            {\n              required: true,\n              validator: (rule: any, value: number) => {\n                return Promise.resolve();\n              },\n            },\n          ],\n          attrs: {\n            disabled: true,\n            placeholder: \"请输入\",\n            style: {\n              width: \"100%\",\n            },\n          },\n        },\n        {\n          key: \"dataType\",\n          label: \"业务类型\",\n          type: FormItemType.select,\n          rules: [{ required: true, message: \"请选择业务类型\" }],\n          options: this.props.params.dataTypeList,\n          attrs: {\n            placeholder: \"请选择业务类型\",\n          },\n        },\n      ],\n      {\n        key: \"desc\",\n        label: \"模板描述\",\n        type: FormItemType.textArea,\n        attrs: {\n          placeholder: \"请输入0-1000字模板描述\",\n        },\n        rules: [\n          {\n            validator: (rule: any, value: string) => {\n              value = value?.trim();\n              if (!value) {\n                return Promise.resolve();\n              } else if (value.length > 1000) {\n                return Promise.reject(\"请输入0-1000字模板描述\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n    ] as IFormItem[];\n  };\n\n  onClusterInfoChange = (value: any) => {\n    this.$formRef?.current.setFieldsValue({ level: value?.level }); // 选择集群后给level初始值\n    this.setState({\n      dataCenter: value?.dataCenter,\n    });\n  };\n\n  getBaseInfo = () => {\n    this.setState({\n      loading: true,\n    });\n    getIndexBaseInfo(this.id)\n      .then((data = {}) => {\n        data.cyclicalRoll = data.cyclicalRoll ? \"more\" : \"one\";\n        data.clusterInfo = {\n          cluster: data.cluster,\n          clusterName: data.cluster,\n          clusterType: data.clusterType,\n        };\n        data.type = data.clusterType;\n        data.clusterName = data.cluster;\n        this.setState({\n          baseInfoData: data,\n          isCyclicalRoll: data.cyclicalRoll === \"more\",\n        });\n        this.$formRef?.current.setFieldsValue(data);\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n  };\n\n  getTimeFormatList = () => {\n    getTimeFormat().then((res = []) => {\n      this.setState({\n        timeFormatList: res,\n      });\n    });\n  };\n\n  handleCancel = () => {\n    this.props.setDrawerId(\"\");\n  };\n\n  handleSubmit = () => {\n    this.$formRef?.current.validateFields().then((result) => {\n      const formData = {\n        id: this.id,\n        desc: result.desc,\n        dataType: result.dataType,\n        expireTime: result.expireTime,\n      };\n      updateIndexInfo(formData).then(() => {\n        message.success(\"更新成功\");\n        this.props.setDrawerId(\"\");\n        this.props.cb();\n      });\n    });\n  };\n\n  componentDidMount() {\n    this.getBaseInfo();\n    this.getTimeFormatList();\n  }\n\n  componentWillUnmount() {\n    // 这是一段比较恶心的代码 xform的值无法传下去 但是内部需要接收到\n    (window as any).masternodeErr = false;\n    delete (window as any).masternodeErr;\n  }\n\n  render() {\n    const { loading, baseInfoData } = this.state;\n    return (\n      <Drawer\n        visible={true}\n        title=\"编辑模板\"\n        width={600}\n        onClose={this.handleCancel}\n        maskClosable={false}\n        extra={\n          <Space>\n            <Button onClick={this.handleCancel}>取消</Button>\n            <Button type=\"primary\" onClick={this.handleSubmit}>\n              确定\n            </Button>\n            <Divider type=\"vertical\" />\n          </Space>\n        }\n      >\n        <Spin spinning={loading}>\n          <XFormComponent layout=\"vertical\" formData={baseInfoData} formMap={this.formMap()} wrappedComponentRef={this.$formRef} />\n        </Spin>\n      </Drawer>\n    );\n  }\n}\n\nexport default connect(mapStateToProps, mapDispatchToProps)(EditTemplate);\n"
  },
  {
    "path": "arius-console/src/container/full-screen/index.less",
    "content": ".full-screen-mark {\n  position: fixed;\n  left: 0;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  background-color: rgba(0, 0, 0, 0.5);\n  z-index: 1050;\n  .full-screen-content {\n    width: 80%;\n    box-shadow: 0 4px 12px 0;\n    border-radius: 4px;\n    margin: 10% auto;\n    background-color: #fff;\n    padding: 20px;\n    overflow: hidden;\n  }\n}"
  },
  {
    "path": "arius-console/src/container/full-screen/index.tsx",
    "content": "import React from 'react';\nimport './index.less';\nimport { connect } from \"react-redux\";\nimport * as actions from '../../actions';\n\nconst mapStateToProps = (state: any) => ({\n  content: state.fullScreen?.content,\n});\n\nconst mapDispatchToProps = dispatch => ({\n  close: (content: any) => dispatch(actions.setFullScreenContent(content))\n});\n\ntype Props = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;\n\nclass FullScreen extends React.Component<Props> {\n\n  public handleClose = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {\n    if ((event.target as any).nodeName === 'SECTION') {\n      this.props.close(null)\n    };\n  }\n\n  public render() {\n    if (!this.props.content) return null;\n    return (\n      <section className=\"full-screen-mark\" onClick={this.handleClose}>\n        <div className=\"full-screen-content\">\n          {this.props.content}\n        </div>\n      </section>\n    );\n  }\n}\n\nexport default connect(mapStateToProps, mapDispatchToProps)(FullScreen)\n"
  },
  {
    "path": "arius-console/src/container/iframe-page.tsx",
    "content": "import React from 'react';\n\n\ninterface IProps {\n  src?: string;\n  className?: string;\n}\nexport const PageIFrameContainer = (props: IProps) => {\n\n  const [loading, setLoading] = React.useState(false);\n\n  return (\n    <iframe style={{ display: loading ? 'none' : '' }} className={`iframe-page ${props.className}`} src={props.src} />\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/index-admin/component/index.less",
    "content": ".tip-example {\n  line-height: 16px;\n  max-width: 360px;\n  max-height: 500px;\n  overflow: scroll;\n}\n\n.edit-mapping {\n  height: calc(100vh - 280px);\n\n  &.modify {\n    height: calc(100vh - 180px);\n  }\n\n  &.info {\n    height: calc(100vh - 220px);\n  }\n}\n\n.mapping-detail {\n  height: calc(100vh - 350px);\n}\n"
  },
  {
    "path": "arius-console/src/container/index-admin/component/index.tsx",
    "content": "export * from \"./mapping\";\nexport * from \"./setting\";\nexport * from \"./mapping-index\";\nexport * from \"./setting-index\";\n"
  },
  {
    "path": "arius-console/src/container/index-admin/component/mapping-index.tsx",
    "content": "import * as React from \"react\";\nimport Url from \"lib/url-parser\";\nimport { message } from \"antd\";\nimport { connect } from \"react-redux\";\nimport { getMapping, updateMapping } from \"api/index-admin\";\nimport { getFormatJsonStr } from \"lib/utils\";\nimport \"./index.less\";\nimport { JsonEditorWrapper } from \"component/jsonEditorWrapper\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\nconst connects: Function = connect;\n@connects(mapStateToProps)\nexport class SetMapping extends React.Component<any> {\n  private indexName: string = null;\n  private isDetailPage: boolean = false;\n  private isModifyPage: boolean = false;\n  static defaultProps: { isShowPlaceholder: boolean } = { isShowPlaceholder: true };\n\n  public state = {\n    loading: false,\n    activeInstance: null,\n  };\n\n  constructor(props: any) {\n    super(props);\n    this.indexName = Url().search.index || this.props.params.index;\n    this.isDetailPage = window.location.pathname.includes(\"/detail\");\n    this.isModifyPage = !this.isDetailPage && this.indexName ? true : false;\n  }\n\n  public componentDidMount() {\n    this.props.childEvevnt(this);\n    if (this.isModifyPage || this.isDetailPage) {\n      this.setState({\n        loading: true,\n      });\n      getMapping(this.props.params.cluster, this.indexName)\n        .then((res) => {\n          this.props.updateState({\n            mapping: getFormatJsonStr(JSON.parse(res?.mappings)),\n          });\n        })\n        .finally(() => {\n          this.setState({\n            loading: false,\n          });\n        });\n    }\n  }\n\n  public componentWillUnmount() {\n    if (this.isModifyPage || this.isDetailPage) {\n      this.props.updateState({\n        mapping: \"\",\n      });\n    }\n  }\n\n  public handlePre = () => {\n    const editor = this.state.activeInstance;\n    const value = editor ? editor.getValue() : \"\";\n    this.props.updateState({\n      current: 0,\n      mapping: value,\n    });\n  };\n\n  public handleSubmit = () => {\n    try {\n      const editor = this.state.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      this.props.updateState({\n        current: 2,\n        mapping: value,\n      });\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public handleSave = (cb) => {\n    try {\n      const editor = this.state.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      const params = {\n        cluster: this.props.params.cluster,\n        index: this.indexName,\n        mapping: JSON.stringify(jsonValue),\n      };\n      this.props.updateState({\n        btnLoading: true,\n      });\n      updateMapping(params)\n        .then(() => {\n          message.success(\"编辑成功\");\n          cb && cb();\n        })\n        .finally(() => {\n          this.props.updateState({\n            btnLoading: false,\n          });\n        });\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public render() {\n    const { data: value, setValid } = this.props;\n    const { loading } = this.state;\n\n    return (\n      <>\n        <JsonEditorWrapper\n          data={value}\n          title={\"Mapping编辑器\"}\n          loading={loading}\n          docType=\"mapping\"\n          isNeedAutoIndent={!this.isDetailPage}\n          setEditorInstance={(editor) => {\n            this.setState({\n              activeInstance: editor,\n            });\n          }}\n          setValid={setValid}\n          jsonClassName={this.isModifyPage ? \"edit-mapping info\" : \"edit-mapping\"}\n          readOnly={this.isDetailPage}\n        />\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-admin/component/mapping.tsx",
    "content": "import { getMapping } from \"api/index-admin\";\nimport React, { FC, memo, useEffect, useState } from \"react\";\nimport urlParser from \"lib/url-parser\";\nimport { getFormatJsonStr } from \"lib/utils\";\nimport { Spin } from \"antd\";\nimport { ACEJsonEditor } from \"@knowdesign/kbn-sense/lib/packages/kbn-ace/src/ace/json_editor\";\nimport \"./index.less\";\n\ninterface propsType {\n  data: any;\n}\n\nexport const Mapping: FC<propsType> = memo(({ data }) => {\n  const { search } = urlParser();\n  const clusterName = data.cluster || search.cluster;\n  const indexName = data.index || search.index;\n\n  const [mappingData, setMappingData] = useState(\"\");\n  const [isLoading, setIsLoading] = useState(false);\n\n  const getAsyncMapping = async () => {\n    setIsLoading(true);\n    try {\n      const res = await getMapping(clusterName, indexName);\n      setMappingData(getFormatJsonStr(JSON.parse(res?.mappings)));\n    } catch (error) {\n      console.log(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    getAsyncMapping();\n  }, []);\n\n  return (\n    <div className=\"json-editor-wrapper\">\n      <Spin spinning={isLoading}>{!isLoading && <ACEJsonEditor className={\"mapping-detail\"} readOnly={true} data={mappingData} />}</Spin>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/index-admin/component/setting-index.tsx",
    "content": "import * as React from \"react\";\nimport Url from \"lib/url-parser\";\nimport { message } from \"antd\";\nimport { connect } from \"react-redux\";\nimport { getSetting, updateSetting } from \"api/index-admin\";\nimport { getFormatJsonStr, formatJsonStr } from \"lib/utils\";\nimport \"./index.less\";\nimport { JsonEditorWrapper } from \"component/jsonEditorWrapper\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\nconst connects: Function = connect;\n@connects(mapStateToProps)\nexport class SetSetting extends React.Component<any> {\n  private indexName: string = null;\n  private isDetailPage: boolean = false;\n  private isModifyPage: boolean = false;\n  static defaultProps: { isShowPlaceholder: boolean } = { isShowPlaceholder: true };\n\n  public state = {\n    loading: false,\n    activeInstance: null,\n  };\n\n  constructor(props: any) {\n    super(props);\n    this.indexName = Url().search.index || this.props.params.index;\n    this.isDetailPage = window.location.pathname.includes(\"/detail\");\n    this.isModifyPage = !this.isDetailPage && this.indexName ? true : false;\n  }\n\n  public componentDidMount() {\n    this.props.childEvevnt(this);\n    if (this.isModifyPage || this.isDetailPage) {\n      this.setState({\n        loading: true,\n      });\n      getSetting(this.props.params.cluster, this.indexName)\n        .then((res) => {\n          this.props.updateState({\n            setting: getFormatJsonStr(res?.properties),\n          });\n        })\n        .finally(() => {\n          this.setState({\n            loading: false,\n          });\n        });\n    }\n  }\n\n  public componentWillUnmount() {\n    if (this.isModifyPage || this.isDetailPage) {\n      this.props.updateState({\n        setting: \"\",\n      });\n    }\n  }\n\n  public handlePre = () => {\n    const editor = this.state.activeInstance;\n    const value = editor ? editor.getValue() : \"\";\n    this.props.updateState({\n      current: 1,\n      setting: value,\n    });\n  };\n\n  public handleSubmit = (cb) => {\n    try {\n      const editor = this.state.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      this.props.updateState({ setting: value }, () => cb && cb(value));\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public handleSave = (cb) => {\n    try {\n      const editor = this.state.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      const params = {\n        cluster: this.props.params.cluster,\n        index: this.indexName,\n        setting: formatJsonStr(value),\n      };\n      this.props.updateState({\n        btnLoading: true,\n      });\n      updateSetting(params)\n        .then(() => {\n          message.success(\"编辑成功\");\n          cb && cb();\n        })\n        .finally(() => {\n          this.props.updateState({\n            btnLoading: false,\n          });\n        });\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public render() {\n    const { data: value, setValid } = this.props;\n    const { loading } = this.state;\n\n    return (\n      <>\n        <JsonEditorWrapper\n          data={value}\n          title={\"Setting编辑器\"}\n          loading={loading}\n          isNeedAutoIndent={!this.isDetailPage}\n          docType=\"setting\"\n          setEditorInstance={(editor) => {\n            this.setState({\n              activeInstance: editor,\n            });\n          }}\n          setValid={setValid}\n          isShowMappingTip={false}\n          jsonClassName={this.isModifyPage ? \"edit-mapping modify\" : \"edit-mapping\"}\n          readOnly={this.isDetailPage}\n        />\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-admin/component/setting.tsx",
    "content": "import React, { FC, memo, useEffect, useState } from \"react\";\nimport { getSetting } from \"api/index-admin\";\nimport urlParser from \"lib/url-parser\";\nimport { getFormatJsonStr } from \"lib/utils\";\nimport { Spin } from \"antd\";\nimport { ACEJsonEditor } from \"@knowdesign/kbn-sense/lib/packages/kbn-ace/src/ace/json_editor\";\nimport \"./index.less\";\n\ninterface propsType {\n  data: any;\n}\n\nexport const Setting: FC<propsType> = memo(({ data }) => {\n  const { search } = urlParser();\n  const clusterName = data.cluster || search.cluster;\n  const indexName = data.index || search.index;\n\n  const [settingData, setSettingData] = useState(\"\");\n  const [isLoading, setIsLoading] = useState(false);\n\n  const getAsyncSetting = async () => {\n    setIsLoading(true);\n    try {\n      const res = await getSetting(clusterName, indexName);\n      setSettingData(getFormatJsonStr(res?.properties));\n    } catch (error) {\n      console.log(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    getAsyncSetting();\n  }, []);\n\n  return (\n    <div className=\"json-editor-wrapper\">\n      <Spin spinning={isLoading}>{!isLoading && <ACEJsonEditor className={\"mapping-detail\"} readOnly={true} data={settingData} />}</Spin>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/index-admin/detail.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { withRouter } from \"react-router-dom\";\nimport { Menu, Spin, Divider } from \"knowdesign\";\nimport { TAB_LIST, MENU_MAP } from \"./management/config\";\nimport { getIndexDetail } from \"api/index-admin\";\nimport urlParser from \"lib/url-parser\";\nimport { isSuperApp } from \"lib/utils\";\n\nexport const IndexAdminDetail = withRouter((props) => {\n  const [indexBaseInfo, setIndexBaseInfo] = useState({} as any);\n  const [isLoading, setIsLoading] = useState(false);\n  const [menu, setMenu] = useState(window.location.hash.replace(\"#\", \"\") || \"baseInfo\");\n\n  useEffect(() => {\n    getData();\n    window.addEventListener(\"hashchange\", () => {\n      updateMenu();\n    });\n    return () => {\n      window.removeEventListener(\"hashchange\", () => {\n        updateMenu();\n      });\n    };\n  }, []);\n\n  const getData = async () => {\n    const { search } = urlParser();\n    setIsLoading(true);\n    try {\n      const data = (await getIndexDetail(search.cluster, search.index)) || {};\n      data.cluster = isSuperApp() ? data.cluster : data.clusterLogic;\n      setIndexBaseInfo(data);\n    } catch (error) {\n      console.error(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const updateMenu = () => {\n    setMenu(window.location.hash.replace(\"#\", \"\") || \"info\");\n  };\n\n  const renderContent = () => {\n    return MENU_MAP.get(menu)?.content({\n      indexBaseInfo: indexBaseInfo,\n      reloadData: getData,\n      loading: isLoading,\n    });\n  };\n\n  const changeMenu = (e) => {\n    window.location.hash = e.key;\n  };\n\n  const renderPageHeader = () => {\n    const { search } = urlParser();\n    return (\n      <div className=\"detail-header\">\n        <div className=\"left-content\">\n          <span className=\"icon iconfont iconarrow-left\" onClick={() => props.history.push(\"/index-admin/management\")}></span>\n          <Divider type=\"vertical\"></Divider>\n          <div className=\"title\">\n            <span className=\"text\">{indexBaseInfo?.index || search?.index || \"\"}</span>\n          </div>\n        </div>\n        <div className=\"right-content\">\n          <span className=\"detail\">\n            <span className=\"label\">所属集群：</span>\n            <span className=\"value\">{indexBaseInfo?.cluster || search?.cluster || \"-\"}</span>\n          </span>\n          <div className=\"reload-icon\" onClick={getData}>\n            <span className=\"icon iconfont iconshuaxin2\"></span>\n          </div>\n        </div>\n      </div>\n    );\n  };\n\n  return (\n    <div className=\"index-detail detail-container\">\n      <Spin spinning={isLoading}>\n        {renderPageHeader()}\n        <div className=\"content\">\n          <div className=\"menu-container\">\n            <Menu className=\"menu\" selectedKeys={[menu]} mode=\"horizontal\" onClick={changeMenu}>\n              {TAB_LIST.map((d) => (\n                <Menu.Item key={d.key}>{d.name}</Menu.Item>\n              ))}\n            </Menu>\n          </div>\n          <div className=\"detail-wrapper\">{renderContent()}</div>\n        </div>\n      </Spin>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/index-admin/index.tsx",
    "content": "export * from \"./management\";\nexport * from \"./service\";\n"
  },
  {
    "path": "arius-console/src/container/index-admin/management/config.tsx",
    "content": "import React from \"react\";\nimport { Tag, Tooltip } from \"antd\";\nimport { BaseDetail } from \"component/dantd/base-detail\";\nimport { renderOperationBtns, NavRouterLink } from \"container/custom-component\";\nimport { IndexPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { Mapping, Setting } from \"../component\";\nimport { OperatingRecord } from \"container/index-tpl-management/detail/record\";\nimport { ShardList } from \"container/index-tpl-management/detail/shard\";\nimport { formatDecimalPoint } from \"lib/utils\";\n\nconst renderText = (text) => {\n  return <div className=\"dsl-overflow-auto\">{text}</div>;\n};\n\nexport const columnsRender = (item: string) => {\n  return (\n    <Tooltip placement=\"right\" title={renderText(item)}>\n      <div\n        className=\"row-ellipsis pointer\"\n        style={{\n          maxWidth: \"100%\",\n          display: \"inline-block\",\n        }}\n      >\n        {item || \"-\"}\n      </div>\n    </Tooltip>\n  );\n};\n\nexport const queryFormText: { searchText: string; resetText: string } = {\n  searchText: \"查询\",\n  resetText: \"重置\",\n};\n\nexport const getQueryFormConfig = (cluster: any) => {\n  return [\n    {\n      type: \"input\",\n      title: \"索引名称:\",\n      dataIndex: \"index\",\n      placeholder: \"请输入索引名称\",\n      rules: [\n        {\n          required: false,\n          validator: async (rule: any, value: string) => {\n            if (value && value.length > 128) {\n              return Promise.reject(\"最大限制128字符\");\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      type: \"select\",\n      title: \"所属集群:\",\n      dataIndex: \"cluster\",\n      options: cluster.map((item) => ({\n        title: item,\n        value: item,\n      })),\n      placeholder: \"请选择\",\n    },\n    {\n      type: \"select\",\n      title: \"健康状态:\",\n      dataIndex: \"health\",\n      options: [\n        {\n          title: \"green\",\n          value: \"green\",\n        },\n        {\n          title: \"yellow\",\n          value: \"yellow\",\n        },\n        {\n          title: \"red\",\n          value: \"red\",\n        },\n      ],\n      placeholder: \"请选择\",\n    },\n  ];\n};\n\nexport const getBtnList = (record, setModalId?: any, setDrawerId?: any, reloadDataFn?: (del?: boolean) => void) => {\n  const isOpenUp = false;\n  const clusterName = record.cluster;\n  const indexName = record.index;\n\n  let btn = [\n    {\n      label: \"编辑Mapping\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      invisible: !hasOpPermission(IndexPermissions.PAGE, IndexPermissions.EDIT_MAPPING),\n      clickFunc: () => {\n        setDrawerId(\"editIndexMapping\", record, reloadDataFn);\n      },\n    },\n    {\n      label: \"编辑Setting\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      invisible: !hasOpPermission(IndexPermissions.PAGE, IndexPermissions.EDIT_SETTING),\n      clickFunc: () => {\n        setDrawerId(\"editIndexSetting\", record, reloadDataFn);\n      },\n    },\n    {\n      label: \"设置别名\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      invisible: !hasOpPermission(IndexPermissions.PAGE, IndexPermissions.SET_ALIAS),\n      clickFunc: () => {\n        setModalId(\"setAlias\", record, reloadDataFn);\n      },\n    },\n    {\n      label: \"删除别名\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      invisible: !hasOpPermission(IndexPermissions.PAGE, IndexPermissions.DELETE_ALIAS) || !record.aliases?.length,\n      clickFunc: () => {\n        setModalId(\"deleteAlias\", record, reloadDataFn);\n      },\n    },\n    {\n      label: \"下线\",\n      type: \"primary\",\n      invisible: !hasOpPermission(IndexPermissions.PAGE, IndexPermissions.OFFLINE),\n      clickFunc: () => {\n        setModalId(\n          \"deleteIndex\",\n          {\n            delList: [\n              {\n                cluster: clusterName,\n                index: indexName,\n              },\n            ],\n            title: `确定下线索引 ${indexName} ?`,\n          },\n          () => {\n            reloadDataFn && reloadDataFn(true);\n          }\n        );\n      },\n    },\n  ];\n  return btn;\n};\n\nconst statusTag = (item) => {\n  switch (item) {\n    case \"red\":\n      return <Tag color=\"error\">red</Tag>;\n    case \"yellow\":\n      return <Tag color=\"warning\">yellow</Tag>;\n    case \"green\":\n      return <Tag color=\"success\">green</Tag>;\n    default:\n      return \"-\";\n  }\n};\n\nexport const cherryList = [\"rep\", \"docsCount\", \"docsDeleted\", \"priStoreSize\", \"storeSize\"];\n\nexport const getColumns = (setModalId?: any, setDrawerId?: any, reloadDataFn?: any) => {\n  return [\n    {\n      title: \"索引名称\",\n      dataIndex: \"index\",\n      fixed: \"left\",\n      width: 180,\n      render: (item, record) => {\n        return (\n          <div className=\"two-row-ellipsis pointer index-name-cell\">\n            <NavRouterLink\n              needToolTip\n              maxShowLength={50}\n              element={item}\n              href={`/index-admin/management/detail?index=${record.index}&cluster=${record.cluster}`}\n            />\n          </div>\n        );\n      },\n    },\n    {\n      title: \"所属集群\",\n      dataIndex: \"cluster\",\n      width: 150,\n      render: (item) => columnsRender(item),\n    },\n    {\n      title: \"健康状态\",\n      dataIndex: \"health\",\n      width: 80,\n      render: (item) => <div style={{ width: \"2vw\" }}>{statusTag(item)}</div>,\n    },\n    // {\n    //   title: \"索引状态\",\n    //   dataIndex: \"status\",\n    //   render: (text) => {\n    //     return text == 'open' ? '开启' : '关闭'\n    //   },\n    // },\n    {\n      title: \"Shard个数\",\n      dataIndex: \"pri\",\n      width: 110,\n      sorter: true,\n    },\n    {\n      title: \"副本个数\",\n      dataIndex: \"rep\",\n      width: 100,\n      sorter: true,\n    },\n    {\n      title: \"文档个数\",\n      dataIndex: \"docsCount\",\n      width: 100,\n      sorter: true,\n    },\n    {\n      title: \"删除文档个数\",\n      dataIndex: \"docsDeleted\",\n      width: 130,\n      sorter: true,\n    },\n    {\n      title: \"主分片存储大小\",\n      dataIndex: \"priStoreSize\",\n      width: 130,\n      sorter: true,\n      render: (item) => columnsRender(formatDecimalPoint(item) + \"\"),\n    },\n    {\n      title: \"存储大小\",\n      dataIndex: \"storeSize\",\n      width: 80,\n      sorter: true,\n      render: (item) => columnsRender(formatDecimalPoint(item) + \"\"),\n    },\n    {\n      title: \"索引别名\",\n      dataIndex: \"aliases\",\n      width: 120,\n      render: (item) => columnsRender(item?.join()),\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      fixed: \"right\",\n      width: 250,\n      render: (index: number, record) => {\n        const btns = getBtnList(record, setModalId, setDrawerId, reloadDataFn);\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n};\n\nexport enum TAB_LIST_KEY {\n  baseInfo = \"baseInfo\",\n  mapping = \"mapping\",\n  setting = \"setting\",\n  shard = \"shard\",\n  record = \"record\",\n}\n\nconst baseInfo: any = [\n  {\n    label: \"Shard个数\",\n    key: \"pri\",\n  },\n  {\n    label: \"副本个数\",\n    key: \"rep\",\n  },\n  {\n    label: \"文档个数\",\n    key: \"docsCount\",\n  },\n  {\n    label: \"删除文档个数\",\n    key: \"docsDeleted\",\n  },\n  {\n    label: \"主分片存储大小\",\n    key: \"priStoreSize\",\n    render: (text: string) => formatDecimalPoint(text) + \"\",\n  },\n  {\n    label: \"存储大小\",\n    key: \"storeSize\",\n    render: (text: string) => formatDecimalPoint(text) + \"\",\n  },\n];\n\nexport const TAB_LIST = [\n  {\n    name: \"基本信息\",\n    key: TAB_LIST_KEY.baseInfo,\n    content: (data) => (\n      <div className=\"base-info\">\n        <BaseDetail columns={baseInfo} baseDetail={data?.indexBaseInfo || {}} />\n      </div>\n    ),\n  },\n  {\n    name: \"Mapping\",\n    key: TAB_LIST_KEY.mapping,\n    content: (data) => <Mapping data={data} />,\n  },\n  {\n    name: \"Setting\",\n    key: TAB_LIST_KEY.setting,\n    content: (data) => <Setting data={data} />,\n  },\n  {\n    name: \"Shard\",\n    key: TAB_LIST_KEY.shard,\n    content: (data) => <ShardList dataInfo={data} />,\n  },\n  {\n    name: \"操作记录\",\n    key: TAB_LIST_KEY.record,\n    content: (data) => <OperatingRecord recordType=\"indexName\" />,\n  },\n];\n\nconst menuMap = new Map();\n\nTAB_LIST.forEach((d) => {\n  return menuMap.set(d.key, d);\n});\n\nexport const MENU_MAP = menuMap;\n"
  },
  {
    "path": "arius-console/src/container/index-admin/management/index.less",
    "content": ".dsl-overflow-auto {\n  overflow: auto;\n  max-height: 300px;\n}\n\n.two-row-ellipsis {\n  text-overflow: -o-ellipsis-lastline;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-line-clamp: 2;\n  line-clamp: 2;\n  -webkit-box-orient: vertical;\n}\n\n.row-ellipsis {\n  overflow: hidden;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n}\n\n.pointer {\n  cursor: pointer;\n}\n\n.index-name-cell {\n  color: @primary-color;\n  word-break: break-all;\n}\n\n.index-detail {\n  .detail-wrapper {\n    height: calc(100vh - 320px);\n    .CodeMirror {\n      max-height: calc(100vh - 360px);\n    }\n  }\n  .table-content {\n    padding: 0;\n    padding-bottom: 20px;\n  }\n  .base-info-box {\n    margin-top: 0;\n  }\n  .hash-menu {\n    min-height: calc(100vh - 160px);\n  }\n}\n.index-spin-name {\n  margin-left: 0%;\n  margin-top: 30%;\n}\n"
  },
  {
    "path": "arius-console/src/container/index-admin/management/index.tsx",
    "content": "import React, { memo, useCallback, useEffect, useState } from \"react\";\nimport { useDispatch } from \"react-redux\";\nimport { withRouter } from \"react-router-dom\";\nimport { Tooltip, Button, Spin } from \"antd\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { RenderTitle } from \"component/render-title\";\nimport { getColumns, getQueryFormConfig, queryFormText } from \"./config\";\nimport QueryForm from \"component/dantd/query-form\";\nimport * as actions from \"actions\";\nimport \"./index.less\";\nimport { getIndexAdminData } from \"api/index-admin\";\nimport { getClusterPerApp, getPhyClusterPerApp } from \"api/cluster-index-api\";\nimport { initPaginationProps } from \"constants/table\";\nimport { isSuperApp } from \"lib/utils\";\nimport { IndexPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { RenderEmpty } from \"component/LogClusterEmpty\";\nimport { ProTable } from \"knowdesign\";\n\nexport const IndexAdmin = withRouter((props: { history: any }) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  // 超级应用展示物理集群，其他应用展示逻辑集群\n  const superApp = isSuperApp();\n  const totalLimit = 10000;\n  const dispatch = useDispatch();\n  const setModalId = (modalId: string, params?: any, cb?: Function) => {\n    dispatch(actions.setModalId(modalId, params, cb));\n  };\n  const setDrawerId = (drawerId: string, params?: any, cb?: Function) => {\n    dispatch(actions.setDrawerId(drawerId, params, cb));\n  };\n\n  const [data, setData] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const [paginationProps, setPaginationProps] = useState(initPaginationProps());\n  const [realTotal, setRealTotal] = useState(0);\n  const [selectedRowKeys, setSelectedRowKeys] = useState([]);\n  const [selectedRows, setSelectedRows] = useState([]);\n  const [cluster, setCluster] = useState([]);\n  const [queryData, setQueryData]: any = useState({\n    page: 1,\n    size: 10,\n  });\n  const [pageLoad, setPageLoad] = useState(false);\n\n  const getAsyncData = async () => {\n    setIsLoading(true);\n    const Params: any = {\n      page: queryData.page,\n      size: queryData.size,\n      index: queryData.index,\n      cluster: queryData.cluster,\n      health: queryData.health,\n      sortTerm: queryData.sortTerm,\n      orderByDesc: queryData.orderByDesc,\n    };\n    getIndexAdminData(Params)\n      .then((res) => {\n        if (res) {\n          let data = (res?.bizData || []).map((item) => {\n            return {\n              ...item,\n              cluster: superApp ? item.cluster : item.clusterLogic,\n              rowKey: item.key,\n            };\n          });\n          setData(data);\n          clearSelect();\n          const { pageNo = 1, pageSize = 10, total = 0 } = res?.pagination;\n          setPaginationProps({\n            ...paginationProps,\n            total: total > totalLimit ? totalLimit : total,\n            current: pageNo,\n            pageSize: pageSize,\n            showTotal: (total) => `共 ${res?.pagination?.total} 条`,\n          });\n          setRealTotal(res?.pagination?.total);\n        }\n      })\n      .finally(() => {\n        setIsLoading(false);\n      });\n  };\n\n  const clearSelect = () => {\n    setSelectedRowKeys([]);\n    setSelectedRows([]);\n  };\n\n  const getAsyncClusterName = async () => {\n    setPageLoad(true);\n    try {\n      const clusterNameList = superApp ? await getPhyClusterPerApp() : await getClusterPerApp();\n      setPageLoad(false);\n      setCluster(superApp ? clusterNameList || [] : clusterNameList.map((item) => item.v2));\n    } catch (error) {\n      console.log(error, \"error\");\n      setPageLoad(false);\n    }\n  };\n\n  const handleSubmit = (result) => {\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setQueryData({ ...result, page: 1, size: paginationProps.pageSize });\n  };\n\n  const pageChange = (pagination, filters, sorter) => {\n    // 条件过滤请求在这里处理\n    const sorterObject: { [key: string]: any } = {};\n    // 排序\n    if (sorter.field && sorter.order) {\n      sorterObject.sortTerm = sorter.field;\n      sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n    }\n    setQueryData((state) => {\n      if (!sorter.order) {\n        delete state.sortTerm;\n        delete state.orderByDesc;\n      }\n      return {\n        ...state,\n        ...sorterObject,\n        page: pagination.current,\n        size: pagination.pageSize,\n      };\n    });\n  };\n\n  const modalReloadData = function (del?: boolean) {\n    // 下线操作，\n    if (del) {\n      setQueryData({\n        ...queryData,\n        page: 1,\n        size: paginationProps.pageSize,\n      });\n      return;\n    }\n    setQueryData((state) => ({ ...state }));\n  };\n\n  useEffect(() => {\n    getAsyncClusterName();\n  }, [department]);\n\n  useEffect(() => {\n    getAsyncData();\n  }, [queryData, department]);\n\n  const renderTitleContent = () => {\n    return {\n      title: \"索引管理\",\n      content: null,\n    };\n  };\n\n  const getOpBtns = useCallback(() => {\n    return (\n      <>\n        <Button type=\"primary\" onClick={() => setDrawerId(\"createIndex\", {}, modalReloadData)}>\n          新建索引\n        </Button>\n\n        {hasOpPermission(IndexPermissions.PAGE, IndexPermissions.BAT_DELETE) ? (\n          selectedRows && selectedRows.length > 0 ? (\n            <Tooltip title={selectedRows && selectedRows.length ? \"\" : \"需要选中后批量下线\"}>\n              <Button\n                onClick={() => {\n                  setModalId(\n                    \"deleteIndex\",\n                    {\n                      delList: selectedRows.map((item) => ({\n                        cluster: item.cluster,\n                        index: item.index,\n                      })),\n                      title: `确定批量下线所选索引吗?`,\n                    },\n                    modalReloadData\n                  );\n                }}\n                style={{ marginRight: 0 }}\n                type={\"primary\"}\n                disabled={selectedRows && selectedRows.length ? false : true}\n              >\n                批量下线\n              </Button>\n            </Tooltip>\n          ) : (\n            \"\"\n          )\n        ) : (\n          \"\"\n        )}\n      </>\n    );\n  }, [selectedRows]);\n\n  const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n\n  const renderNode = () => {\n    return (\n      <div className=\"table-layout-style\">\n        <ProTable\n          showQueryForm={true}\n          queryFormProps={{\n            defaultCollapse: true,\n            columns: getQueryFormConfig(cluster),\n            // onChange={() => null}\n            onReset: handleSubmit,\n            onSearch: handleSubmit,\n            // initialValues={{}}\n            isResetClearAll: true,\n          }}\n          tableProps={{\n            tableId: \"index_admin_manage_list\", //开启表格自定义列\n            isCustomPg: false,\n            loading: isLoading,\n            rowKey: \"rowKey\",\n            dataSource: data,\n            columns: getColumns(setModalId, setDrawerId, modalReloadData),\n            reloadData: () => modalReloadData(),\n            getJsxElement: getOpBtns,\n            customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n            paginationProps: {\n              ...paginationProps,\n              itemRender: (page, type: \"page\" | \"prev\" | \"next\", originalElement) => {\n                const lastPage = totalLimit / paginationProps?.pageSize;\n                if (type === \"page\") {\n                  if (realTotal > totalLimit && page === lastPage) {\n                    return <Tooltip title={`考虑到性能问题，只展示${totalLimit}条数据`}>{page}</Tooltip>;\n                  } else {\n                    return page;\n                  }\n                } else {\n                  return originalElement;\n                }\n              },\n            },\n            attrs: {\n              onChange: pageChange,\n              rowSelection: {\n                selectedRowKeys,\n                onChange: (selectedRowKeys, selectedRows) => {\n                  setSelectedRowKeys(selectedRowKeys);\n                  setSelectedRows(selectedRows);\n                },\n              },\n              border: true,\n              scroll: {\n                x: \"max-content\",\n              },\n            },\n          }}\n        />\n      </div>\n    );\n  };\n\n  return (\n    <div>\n      <Spin spinning={pageLoad} className=\"index-spin-name\">\n        {superApp\n          ? renderNode()\n          : cluster.length\n          ? !pageLoad && renderNode()\n          : !pageLoad && (\n              <div>\n                <RenderEmpty {...props} />\n              </div>\n            )}\n      </Spin>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/index-admin/service/config.tsx",
    "content": "import { Modal, message, Tooltip } from \"antd\";\nimport { NavRouterLink, renderOperationBtns } from \"container/custom-component\";\nimport React from \"react\";\nimport { columnsRender } from \"../management/config\";\nimport { QuestionCircleOutlined } from \"@ant-design/icons\";\nimport { openOrCloseReadOrWrite, indicesOpen, indicesClose } from \"api/index-admin\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { IndexServicePermissions } from \"constants/permission\";\n\nexport const queryFormText: { searchText: string; resetText: string } = {\n  searchText: \"查询\",\n  resetText: \"重置\",\n};\n\nexport const getQueryFormConfig = (cluster: any) => {\n  return [\n    {\n      type: \"input\",\n      title: \"索引名称:\",\n      dataIndex: \"index\",\n      placeholder: \"请输入索引名称\",\n      rules: [\n        {\n          required: false,\n          validator: async (rule: any, value: string) => {\n            if (value && value.length > 128) {\n              return Promise.reject(\"最大限制128字符\");\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      type: \"select\",\n      title: \"所属集群:\",\n      dataIndex: \"cluster\",\n      options: cluster.map((item) => ({\n        title: item,\n        value: item,\n      })),\n      placeholder: \"请选择\",\n    },\n  ];\n};\n\nconst statusText = (item) => {\n  let status = item ? \"禁用\" : \"启用\";\n  return <div style={{ width: \"2vw\" }}>{status}</div>;\n};\n\nexport const getBtnList = (record, setModalId?: any, setDrawerId?: any, reloadDataFn?: (del?: boolean) => void) => {\n  const isOpenUp = false;\n  const isRead = !record.readFlag; //  record.readFlag 为 true 禁用，false 启用\n  const isWrite = !record.writeFlag;\n  const clusterName = record.cluster;\n  const indexName = record.index;\n\n  const clickReadOrWrite = (props: { clusterName: string; indexName: string; type: \"write\" | \"read\"; value: boolean }) => {\n    const { clusterName, indexName, type, value } = props;\n    const info = type === \"write\" ? \"写\" : \"读\";\n    const operate = value ? \"禁用\" : \"启用\";\n\n    Modal.confirm({\n      title: \"提示\",\n      icon: <QuestionCircleOutlined />,\n      content: `确定${operate}索引 ${indexName} 的${info}操作？`,\n      okText: \"确认\",\n      cancelText: \"取消\",\n      onOk: async () => {\n        try {\n          const res = await openOrCloseReadOrWrite([\n            {\n              cluster: clusterName,\n              index: indexName,\n              type: type,\n              value: value,\n            },\n          ]);\n          res ? message.success(`${operate}${info}成功`) : message.error(`${operate}${info}失败`);\n          reloadDataFn && reloadDataFn();\n        } catch (error) {\n          message.error(`${operate}${info}失败`);\n        }\n      },\n    });\n  };\n\n  const clickOpenOrClose = (props: { clusterName: string; indexName: string; type: \"open\" | \"close\" | any }) => {\n    const { clusterName, indexName, type } = props;\n    const operate = type == \"open\" ? \"关闭\" : \"开启\";\n\n    Modal.confirm({\n      title: \"提示\",\n      icon: <QuestionCircleOutlined />,\n      content: `确定${operate}索引 ${indexName} 吗？`,\n      okText: \"确认\",\n      cancelText: \"取消\",\n      onOk: async () => {\n        try {\n          const params = [\n            {\n              cluster: clusterName,\n              index: indexName,\n            },\n          ];\n          const res = type == \"open\" ? await indicesClose(params) : await indicesOpen(params);\n          res ? message.success(`${operate}成功`) : message.error(`${operate}失败`);\n          reloadDataFn && reloadDataFn();\n        } catch (error) {\n          message.error(`${operate}失败`);\n        }\n      },\n    });\n  };\n\n  let btn = [\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.DISABLE_READ) && {\n      label: isRead ? \"禁用读\" : \"启用读\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        clickReadOrWrite({\n          clusterName: clusterName,\n          indexName: indexName,\n          type: \"read\",\n          value: isRead,\n        });\n      },\n    },\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.DISABLE_WRITE) && {\n      label: isWrite ? \"禁用写\" : \"启用写\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        clickReadOrWrite({\n          clusterName: clusterName,\n          indexName: indexName,\n          type: \"write\",\n          value: isWrite,\n        });\n      },\n    },\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.CLOSE_INDEX) && {\n      label: record.status == \"open\" ? \"关闭索引\" : \"开启索引\",\n      type: \"primary\",\n      isOpenUp: isOpenUp,\n      clickFunc: () => {\n        clickOpenOrClose({\n          clusterName: clusterName,\n          indexName: indexName,\n          type: record.status,\n        });\n      },\n    },\n  ].filter(Boolean);\n  return btn;\n};\n\nexport const getColumns = (setModalId?: any, setDrawerId?: any, reloadDataFn?: any) => {\n  return [\n    {\n      title: \"索引名称\",\n      dataIndex: \"index\",\n      fixed: \"left\",\n      width: 180,\n      render: (item, record) => {\n        return (\n          <div className=\"two-row-ellipsis pointer index-name-cell\">\n            <NavRouterLink\n              needToolTip\n              maxShowLength={50}\n              element={item}\n              href={`/index-admin/management/detail?index=${record.index}&cluster=${record.cluster}`}\n            />\n          </div>\n        );\n      },\n    },\n    // {\n    //   title: \"是否关联模板\",\n    //   dataIndex: \"templateId\",\n    //   width: 100,\n    //   render: (item) => (item ? \"是\" : \"否\"),\n    // },\n    {\n      title: \"所属集群\",\n      dataIndex: \"cluster\",\n      width: 150,\n      render: (item) => columnsRender(item),\n    },\n    {\n      title: \"Shard数\",\n      dataIndex: \"pri\",\n      width: 120,\n      sorter: true,\n    },\n    {\n      title: \"Segment数\",\n      dataIndex: \"totalSegmentCount\",\n      width: 120,\n      sorter: true,\n    },\n    {\n      title: \"读\",\n      width: 60,\n      dataIndex: \"readFlag\",\n      render: (item) => statusText(item),\n    },\n    {\n      title: \"写\",\n      width: 60,\n      dataIndex: \"writeFlag\",\n      render: (item) => statusText(item),\n    },\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.ROLLOVER) && {\n      title: \"Rollover\",\n      dataIndex: \"rollover\",\n      width: 80,\n      render: (item, record) =>\n        record.templateId ? (\n          <Tooltip title=\"该索引具备模板，无法进行索引Rollover\">\n            <a style={{ color: \"#bfbfbf\" }}>执行</a>\n          </Tooltip>\n        ) : (\n          <a\n            onClick={() => {\n              if (record.aliases?.length) {\n                setDrawerId(\"indexSrvRollover\", [record], reloadDataFn);\n              } else {\n                Modal.confirm({\n                  title: \"提示\",\n                  content: (\n                    <>\n                      <div style={{ marginBottom: \"10px\" }}>以下索引未设置别名，无法进行Rollover操作！</div>\n                      <div className=\"btn-labels-box\">\n                        <div className=\"btn-labels\">{record.index}</div>\n                      </div>\n                    </>\n                  ),\n                  okText: \"确认\",\n                  cancelText: \"取消\",\n                });\n              }\n            }}\n          >\n            执行\n          </a>\n        ),\n    },\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.SHRINK) && {\n      title: \"Shrink\",\n      dataIndex: \"shrink\",\n      width: 70,\n      render: (item, record) =>\n        record.templateId ? (\n          <Tooltip title=\"该索引具备模板，无法进行索引shrink\">\n            <a style={{ color: \"#bfbfbf\" }}>执行</a>\n          </Tooltip>\n        ) : (\n          <a onClick={() => setDrawerId(\"indexSrvShrinkSplit\", { type: \"shrink\", indexs: record }, reloadDataFn)}>执行</a>\n        ),\n    },\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.SPLIT) && {\n      title: \"Split\",\n      dataIndex: \"split\",\n      width: 70,\n      render: (item, record) =>\n        record.templateId ? (\n          <Tooltip title=\"该索引具备模板，无法进行索引split\">\n            <a style={{ color: \"#bfbfbf\" }}>执行</a>\n          </Tooltip>\n        ) : (\n          <a onClick={() => setDrawerId(\"indexSrvShrinkSplit\", { type: \"split\", indexs: record }, reloadDataFn)}>执行</a>\n        ),\n    },\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.ForceMerge) && {\n      title: \"ForceMerge\",\n      dataIndex: \"ForceMerge\",\n      width: 100,\n      render: (item, record) => <a onClick={() => setDrawerId(\"indexSrvForceMerge\", [record], reloadDataFn)}>执行</a>,\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      fixed: \"right\",\n      width: 200,\n      render: (index: number, record) => {\n        const btns = getBtnList(record, setModalId, setDrawerId, reloadDataFn);\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ].filter(Boolean);\n};\n\nexport const getBatchBtnService = (setModalId, setDrawerId, selectedRows, reloadData) => {\n  return [\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.ROLLOVER) && {\n      label: \"Rollover\",\n      onClick: () => setDrawerId(\"indexSrvRollover\", selectedRows, reloadData),\n    },\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.ForceMerge) && {\n      label: \"ForceMerge\",\n      onClick: () => setDrawerId(\"indexSrvForceMerge\", selectedRows, reloadData),\n    },\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.DISABLE_READ) && {\n      label: \"启用/禁用读\",\n      onClick: () => setModalId(\"batchExecute\", { type: \"read\", datas: selectedRows }, reloadData),\n    },\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.DISABLE_WRITE) && {\n      label: \"启用/禁用写\",\n      onClick: () => setModalId(\"batchExecute\", { type: \"write\", datas: selectedRows }, reloadData),\n    },\n    hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.CLOSE_INDEX) && {\n      label: \"开启/关闭索引\",\n      onClick: () => setModalId(\"batchExecute\", { type: \"status\", datas: selectedRows }, reloadData),\n    },\n  ].filter(Boolean);\n};\n"
  },
  {
    "path": "arius-console/src/container/index-admin/service/index.less",
    "content": ".dsl-overflow-auto {\n  overflow: auto;\n  max-height: 300px;\n}\n\n.two-row-ellipsis {\n  text-overflow: -o-ellipsis-lastline;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-line-clamp: 2;\n  line-clamp: 2;\n  -webkit-box-orient: vertical;\n}\n\n.row-ellipsis {\n  overflow: hidden;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n}\n\n.pointer {\n  cursor: pointer;\n}\n\n.index-name-cell {\n  color: @primary-color;\n  word-break: break-all;\n}\n"
  },
  {
    "path": "arius-console/src/container/index-admin/service/index.tsx",
    "content": "import React, { useCallback, useEffect, useState } from \"react\";\nimport { useDispatch } from \"react-redux\";\nimport { withRouter } from \"react-router-dom\";\nimport { Menu, Dropdown, Tooltip, Button, Tag } from \"antd\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { RenderTitle } from \"component/render-title\";\nimport { getColumns, getQueryFormConfig, queryFormText, getBatchBtnService } from \"./config\";\nimport QueryForm from \"component/dantd/query-form\";\nimport * as actions from \"actions\";\nimport \"./index.less\";\nimport { getIndexAdminData } from \"api/index-admin\";\nimport { getPhyClusterPerApp } from \"api/cluster-index-api\";\nimport { initPaginationProps } from \"constants/table\";\nimport { isSuperApp } from \"lib/utils\";\nimport { ProTable } from \"knowdesign\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { IndexServicePermissions } from \"constants/permission\";\n\nexport const IndexService = withRouter((props: { history: any }) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  // 超级应用展示物理集群，其他应用展示逻辑集群\n  const superApp = isSuperApp();\n  const totalLimit = 10000;\n  const dispatch = useDispatch();\n  const setModalId = (modalId: string, params?: any, cb?: Function) => {\n    dispatch(actions.setModalId(modalId, params, cb));\n  };\n  const setDrawerId = (drawerId: string, params?: any, cb?: Function) => {\n    dispatch(actions.setDrawerId(drawerId, params, cb));\n  };\n\n  const [data, setData] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const [selectedRowKeys, setSelectedRowKeys] = useState([]);\n  const [selectedRows, setSelectedRows] = useState([]);\n  const [cluster, setCluster] = useState([]);\n  const [queryData, setQueryData]: any = useState({\n    page: 1,\n    size: 10,\n  });\n  const [paginationProps, setPaginationProps] = useState(initPaginationProps());\n  const [realTotal, setRealTotal] = useState(0);\n\n  const getAsyncData = async () => {\n    setIsLoading(true);\n    const Params: any = {\n      page: queryData.page,\n      size: queryData.size,\n      index: queryData.index,\n      cluster: queryData.cluster,\n      sortTerm: queryData.sortTerm,\n      orderByDesc: queryData.orderByDesc,\n    };\n    getIndexAdminData(Params)\n      .then((res) => {\n        if (res) {\n          res?.bizData.forEach((item) => {\n            item.cluster = superApp ? item.cluster : item.clusterLogic;\n            item.rowKey = `${item.cluster}${item.index}`;\n          });\n          setData(res?.bizData);\n          clearSelect();\n          const { pageNo = 1, pageSize = 10, total = 0 } = res?.pagination;\n          setPaginationProps({\n            ...paginationProps,\n            total: total > totalLimit ? totalLimit : total,\n            current: pageNo,\n            pageSize: pageSize,\n            showTotal: (total) => `共 ${res?.pagination?.total} 条`,\n          });\n          setRealTotal(res?.pagination?.total);\n        }\n      })\n      .finally(() => {\n        setIsLoading(false);\n      });\n  };\n\n  const clearSelect = () => {\n    setSelectedRowKeys([]);\n    setSelectedRows([]);\n  };\n\n  const handleSubmit = (result) => {\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setQueryData({ ...result, page: 1, size: paginationProps.pageSize });\n  };\n\n  const pageChange = (pagination, filters, sorter) => {\n    // 条件过滤请求在这里处理\n    const sorterObject: { [key: string]: any } = {};\n    // 排序\n    if (sorter.field && sorter.order) {\n      sorterObject.sortTerm = sorter.field;\n      sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n    }\n    setQueryData((state) => {\n      if (!sorter.order) {\n        delete state.sortTerm;\n        delete state.orderByDesc;\n      }\n      return {\n        ...state,\n        ...sorterObject,\n        page: pagination.current,\n        size: pagination.pageSize,\n      };\n    });\n  };\n\n  useEffect(() => {\n    getPhyClusterPerApp().then((res = []) => {\n      setCluster(res);\n    });\n  }, [department]);\n\n  useEffect(() => {\n    getAsyncData();\n  }, [queryData, department]);\n\n  const renderTitleContent = () => {\n    return {\n      title: \"索引服务\",\n      content: null,\n    };\n  };\n\n  const getOpBtns = useCallback(() => {\n    if ((selectedRows && selectedRows.length < 1) || !hasOpPermission(IndexServicePermissions.PAGE, IndexServicePermissions.BAT)) {\n      return null;\n    }\n    const menu = (\n      <Menu>\n        {getBatchBtnService(setModalId, setDrawerId, selectedRows, getAsyncData).map((item) => (\n          <Menu.Item disabled={selectedRows && selectedRows.length === 0} key={item.label} onClick={() => item.onClick()}>\n            {selectedRows && selectedRows.length === 0 ? <Tooltip title=\"需选定索引后批量执行\">{item.label}</Tooltip> : item.label}\n          </Menu.Item>\n        ))}\n      </Menu>\n    );\n    return (\n      <>\n        {selectedRows && selectedRows.length > 0 ? (\n          <Dropdown overlay={menu} placement=\"bottomCenter\">\n            <Button type=\"primary\">批量执行</Button>\n          </Dropdown>\n        ) : (\n          \"\"\n        )}\n      </>\n    );\n  }, [selectedRows]);\n\n  const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n\n  return (\n    <div className=\"table-layout-style\">\n      <ProTable\n        showQueryForm={true}\n        queryFormProps={{\n          defaultCollapse: true,\n          columns: getQueryFormConfig(cluster),\n          onReset: handleSubmit,\n          onSearch: handleSubmit,\n          isResetClearAll: true,\n        }}\n        tableProps={{\n          tableId: \"index_admin_service_list\",\n          isCustomPg: false,\n          loading: isLoading,\n          rowKey: \"rowKey\",\n          dataSource: data,\n          columns: getColumns(setModalId, setDrawerId, getAsyncData),\n          reloadData: () => getAsyncData(),\n          isDividerHide: selectedRows?.length > 0,\n          getJsxElement: getOpBtns,\n          customRenderSearch: () => (\n            <div className=\"zeus-url\">\n              <RenderTitle {...renderTitleContent()} />{\" \"}\n              <Tag\n                className=\"zeus-url-tag\"\n                onClick={() =>\n                  (window.open(\"about:blank\").location.href = \"https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices.html\")\n                }\n              >\n                指导文档\n              </Tag>\n            </div>\n          ),\n          paginationProps: {\n            ...paginationProps,\n            itemRender: (page, type: \"page\" | \"prev\" | \"next\", originalElement) => {\n              const lastPage = totalLimit / paginationProps?.pageSize;\n              if (type === \"page\") {\n                if (realTotal > totalLimit && page === lastPage) {\n                  return <Tooltip title={`考虑到性能问题，只展示${totalLimit}条数据`}>{page}</Tooltip>;\n                } else {\n                  return page;\n                }\n              } else {\n                return originalElement;\n              }\n            },\n          },\n          attrs: {\n            onChange: pageChange,\n            rowSelection: {\n              selectedRowKeys,\n              onChange: (selectedRowKeys, selectedRows) => {\n                setSelectedRowKeys(selectedRowKeys);\n                setSelectedRows(selectedRows);\n              },\n            },\n            border: true,\n            scroll: {\n              x: \"max-content\",\n            },\n          },\n          ...props,\n        }}\n      />\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/component/index.less",
    "content": ".tip-example {\n  line-height: 16px;\n  max-width: 360px;\n  max-height: 500px;\n  overflow: scroll;\n}\n\n.edit-mapping {\n  height: calc(100vh - 280px);\n\n  &.modify {\n    height: calc(100vh - 180px);\n  }\n\n  &.info {\n    height: calc(100vh - 220px);\n  }\n}\n\n.mapping-detail {\n  height: calc(100vh - 350px);\n}\n\n.tab-content .dcloud-tabs-nav {\n  .dcloud-tabs-nav-list {\n    padding: 2px;\n    background: rgba(116, 120, 141, 0.1);\n    border-radius: 4px;\n  }\n  .dcloud-tabs-tab {\n    border: none;\n    padding: 2px 9px;\n    background: rgba(116, 120, 141, 0);\n  }\n  .dcloud-tabs-tab-active {\n    background: #ffffff;\n    border-radius: 4px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/component/index.tsx",
    "content": "export * from \"./mapping\";\nexport * from \"./setting\";\nexport * from \"./preview-tpl\";\nexport * from \"./mapping-tpl\";\nexport * from \"./setting-tpl\";\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/component/mapping-tpl.tsx",
    "content": "import * as React from \"react\";\nimport Url from \"lib/url-parser\";\nimport { message } from \"antd\";\nimport { connect } from \"react-redux\";\nimport { getMapping, updateMapping } from \"api/index-admin\";\nimport { getFormatJsonStr } from \"lib/utils\";\nimport \"./index.less\";\nimport { JsonEditorWrapper } from \"component/jsonEditorWrapper\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\nconst connects: Function = connect;\n@connects(mapStateToProps)\nexport class SetMapping extends React.Component<any> {\n  private indexName: string = null;\n  private isDetailPage: boolean = false;\n  private isModifyPage: boolean = false;\n  static defaultProps: { isShowPlaceholder: boolean } = { isShowPlaceholder: true };\n\n  public state = {\n    loading: false,\n    activeInstance: null,\n  };\n\n  constructor(props: any) {\n    super(props);\n    this.indexName = Url().search.index || this.props.params.index;\n    this.isDetailPage = window.location.pathname.includes(\"/detail\");\n    this.isModifyPage = !this.isDetailPage && this.indexName ? true : false;\n  }\n\n  public componentDidMount() {\n    this.props.childEvevnt(this);\n    if (this.isModifyPage || this.isDetailPage) {\n      this.setState({\n        loading: true,\n      });\n      getMapping(this.props.params.cluster, this.indexName)\n        .then((res) => {\n          this.props.updateState({\n            mapping: getFormatJsonStr(JSON.parse(res?.mappings)),\n          });\n        })\n        .finally(() => {\n          this.setState({\n            loading: false,\n          });\n        });\n    }\n  }\n\n  public componentWillUnmount() {\n    if (this.isModifyPage || this.isDetailPage) {\n      this.props.updateState({\n        mapping: \"\",\n      });\n    }\n  }\n\n  public handlePre = () => {\n    const editor = this.state.activeInstance;\n    const value = editor ? editor.getValue() : \"\";\n    this.props.updateState({\n      current: 0,\n      mapping: value,\n    });\n  };\n\n  public handleNext = () => {\n    try {\n      const editor = this.state.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      this.props.updateState({\n        current: 2,\n        mapping: value,\n      });\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public handleSave = (cb) => {\n    try {\n      const editor = this.state.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      const params = {\n        cluster: this.props.params.cluster,\n        index: this.indexName,\n        mapping: JSON.stringify(jsonValue),\n      };\n      this.props.updateState({\n        btnLoading: true,\n      });\n      updateMapping(params)\n        .then(() => {\n          message.success(\"编辑成功\");\n          cb && cb();\n        })\n        .finally(() => {\n          this.props.updateState({\n            btnLoading: false,\n          });\n        });\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public render() {\n    const { data: value, setValid } = this.props;\n    const { loading } = this.state;\n\n    return (\n      <>\n        <JsonEditorWrapper\n          data={value}\n          title={\"Mapping编辑器\"}\n          loading={loading}\n          docType=\"mapping\"\n          isNeedAutoIndent={!this.isDetailPage}\n          setEditorInstance={(editor) => {\n            this.setState({\n              activeInstance: editor,\n            });\n          }}\n          setValid={setValid}\n          jsonClassName={this.isModifyPage ? \"edit-mapping info\" : \"edit-mapping\"}\n          readOnly={this.isDetailPage}\n        />\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/component/mapping.tsx",
    "content": "import { getMapping } from \"api/index-admin\";\nimport React, { FC, memo, useEffect, useState } from \"react\";\nimport urlParser from \"lib/url-parser\";\nimport { getFormatJsonStr } from \"lib/utils\";\nimport { Spin } from \"antd\";\nimport { ACEJsonEditor } from \"@knowdesign/kbn-sense/lib/packages/kbn-ace/src/ace/json_editor\";\nimport \"./index.less\";\n\ninterface propsType {\n  data: any;\n}\n\nexport const Mapping: FC<propsType> = memo(({ data }) => {\n  const { search } = urlParser();\n  const clusterName = data.cluster || search.cluster;\n  const indexName = data.index || search.index;\n\n  const [mappingData, setMappingData] = useState(\"\");\n  const [isLoading, setIsLoading] = useState(false);\n\n  const getAsyncMapping = async () => {\n    setIsLoading(true);\n    try {\n      const res = await getMapping(clusterName, indexName);\n      setMappingData(getFormatJsonStr(JSON.parse(res?.mappings)));\n    } catch (error) {\n      console.log(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    getAsyncMapping();\n  }, []);\n\n  return (\n    <div className=\"json-editor-wrapper\">\n      <Spin spinning={isLoading}>{!isLoading && <ACEJsonEditor className={\"mapping-detail\"} readOnly={true} data={mappingData} />}</Spin>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/component/preview-tpl.tsx",
    "content": "import * as React from \"react\";\nimport { BasicInfoPreview } from \"container/index-tpl-management/create/basicInfo-preview\";\nimport { Tabs } from \"knowdesign\";\nimport * as actions from \"actions\";\nimport { connect } from \"react-redux\";\nimport { getFormatJsonStr, formatJsonStr } from \"lib/utils\";\nimport { ACEJsonEditor } from \"@knowdesign/kbn-sense/lib/packages/kbn-ace/src/ace/json_editor\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\nconst connects: Function = connect;\n\n@connects(mapStateToProps)\nexport class Preview extends React.Component<any> {\n  constructor(props: any) {\n    super(props);\n  }\n\n  public componentDidMount() {\n    this.props.childEvevnt(this);\n  }\n\n  public handlePre = () => {\n    this.props.updateState({\n      current: 2,\n    });\n  };\n\n  public handleSubmit = (cb) => {\n    cb && cb();\n  };\n\n  public render() {\n    const { isCyclicalRoll, dataCenter, baseInfoData, mapping, setting } = this.props.data;\n    const { dataTypeList } = this.props.params;\n\n    return (\n      <>\n        <Tabs type=\"card\" className=\"tab-content mt-20 \">\n          <Tabs.TabPane tab=\"基本信息\" key=\"1\">\n            <BasicInfoPreview baseInfo={{ isCyclicalRoll, dataCenter, ...baseInfoData }} dataTypeList={dataTypeList} />\n          </Tabs.TabPane>\n          <Tabs.TabPane tab=\"Mapping\" key=\"2\">\n            <div className=\"json-editor-wrapper\">\n              <ACEJsonEditor className={\"mapping-detail\"} readOnly={true} data={getFormatJsonStr(JSON.parse(mapping || \"{}\"))} />\n            </div>\n          </Tabs.TabPane>\n          <Tabs.TabPane tab=\"Setting\" key=\"3\">\n            <div className=\"json-editor-wrapper\">\n              <ACEJsonEditor className={\"mapping-detail\"} readOnly={true} data={getFormatJsonStr(JSON.parse(setting || \"{}\"))} />\n            </div>\n          </Tabs.TabPane>\n        </Tabs>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/component/setting-tpl.tsx",
    "content": "import * as React from \"react\";\nimport Url from \"lib/url-parser\";\nimport { message } from \"antd\";\nimport { connect } from \"react-redux\";\nimport { getSetting, updateSetting } from \"api/index-admin\";\nimport { getFormatJsonStr, formatJsonStr } from \"lib/utils\";\nimport \"./index.less\";\nimport { JsonEditorWrapper } from \"component/jsonEditorWrapper\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\nconst connects: Function = connect;\n@connects(mapStateToProps)\nexport class SetSetting extends React.Component<any> {\n  private indexName: string = null;\n  private isDetailPage: boolean = false;\n  private isModifyPage: boolean = false;\n  static defaultProps: { isShowPlaceholder: boolean } = { isShowPlaceholder: true };\n\n  public state = {\n    loading: false,\n    activeInstance: null,\n  };\n\n  constructor(props: any) {\n    super(props);\n    this.indexName = Url().search.index || this.props.params.index;\n    this.isDetailPage = window.location.pathname.includes(\"/detail\");\n    this.isModifyPage = !this.isDetailPage && this.indexName ? true : false;\n  }\n\n  public componentDidMount() {\n    this.props.childEvevnt(this);\n    if (this.isModifyPage || this.isDetailPage) {\n      this.setState({\n        loading: true,\n      });\n      getSetting(this.props.params.cluster, this.indexName)\n        .then((res) => {\n          this.props.updateState({\n            setting: getFormatJsonStr(res?.properties),\n          });\n        })\n        .finally(() => {\n          this.setState({\n            loading: false,\n          });\n        });\n    }\n  }\n\n  public componentWillUnmount() {\n    if (this.isModifyPage || this.isDetailPage) {\n      this.props.updateState({\n        setting: \"\",\n      });\n    }\n  }\n\n  public handlePre = () => {\n    const editor = this.state.activeInstance;\n    const value = editor ? editor.getValue() : \"\";\n    this.props.updateState({\n      current: 1,\n      setting: value,\n    });\n  };\n\n  public handleNext = () => {\n    try {\n      const editor = this.state.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      this.props.updateState({\n        current: 3,\n        setting: value,\n      });\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public handleSave = (cb) => {\n    try {\n      const editor = this.state.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      const params = {\n        cluster: this.props.params.cluster,\n        index: this.indexName,\n        setting: formatJsonStr(value),\n      };\n      this.props.updateState({\n        btnLoading: true,\n      });\n      updateSetting(params)\n        .then(() => {\n          message.success(\"编辑成功\");\n          cb && cb();\n        })\n        .finally(() => {\n          this.props.updateState({\n            btnLoading: false,\n          });\n        });\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public render() {\n    const { data: value, setValid } = this.props;\n    const { loading } = this.state;\n\n    return (\n      <>\n        <JsonEditorWrapper\n          data={value}\n          title={\"Setting编辑器\"}\n          loading={loading}\n          isNeedAutoIndent={!this.isDetailPage}\n          docType=\"setting\"\n          setEditorInstance={(editor) => {\n            this.setState({\n              activeInstance: editor,\n            });\n          }}\n          setValid={setValid}\n          isShowMappingTip={false}\n          jsonClassName={this.isModifyPage ? \"edit-mapping modify\" : \"edit-mapping\"}\n          readOnly={this.isDetailPage}\n        />\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/component/setting.tsx",
    "content": "import React, { FC, memo, useEffect, useState } from \"react\";\nimport { getSetting } from \"api/index-admin\";\nimport urlParser from \"lib/url-parser\";\nimport { getFormatJsonStr } from \"lib/utils\";\nimport { Spin } from \"antd\";\nimport { ACEJsonEditor } from \"@knowdesign/kbn-sense/lib/packages/kbn-ace/src/ace/json_editor\";\nimport \"./index.less\";\n\ninterface propsType {\n  data: any;\n}\n\nexport const Setting: FC<propsType> = memo(({ data }) => {\n  const { search } = urlParser();\n  const clusterName = data.cluster || search.cluster;\n  const indexName = data.index || search.index;\n\n  const [settingData, setSettingData] = useState(\"\");\n  const [isLoading, setIsLoading] = useState(false);\n\n  const getAsyncSetting = async () => {\n    setIsLoading(true);\n    try {\n      const res = await getSetting(clusterName, indexName);\n      setSettingData(getFormatJsonStr(res?.properties));\n    } catch (error) {\n      console.log(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    getAsyncSetting();\n  }, []);\n\n  return (\n    <div className=\"json-editor-wrapper\">\n      <Spin spinning={isLoading}>{!isLoading && <ACEJsonEditor className={\"mapping-detail\"} readOnly={true} data={settingData} />}</Spin>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/create/basicInfo-preview.tsx",
    "content": "import * as React from \"react\";\nimport { getMappingPreviewInfo } from \"./config\";\nimport { IBaseInfo } from \"typesPath/base-types\";\nimport { Descriptions } from \"knowdesign\";\nimport \"./index.less\";\n\nexport class BasicInfoPreview extends React.Component<any> {\n  public render() {\n    const { baseInfo, dataTypeList } = this.props;\n\n    return (\n      <>\n        <Descriptions className=\"base-info\" size=\"middle\" column={3} layout=\"vertical\">\n          {getMappingPreviewInfo(baseInfo?.isCyclicalRoll, dataTypeList).map((item: IBaseInfo, index: number) => (\n            <Descriptions.Item key={index} label={item.label}>\n              {item.render ? item.render(baseInfo) : `${baseInfo?.[item.key] || \"-\"}${item.unit || \"\"}`}\n            </Descriptions.Item>\n          ))}\n        </Descriptions>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/create/basicInfo.tsx",
    "content": "import * as React from \"react\";\nimport { XForm as XFormComponent, IFormItem } from \"component/x-form\";\nimport { getStepOneFormMap } from \"./config\";\nimport { TEMP_FORM_MAP_KEY } from \"./constant\";\nimport Url from \"lib/url-parser\";\nimport { CancelActionModal } from \"container/custom-component\";\nimport { Button, Spin } from \"antd\";\nimport { getTimeFormat } from \"api/cluster-index-api\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { dropByCacheKey } from \"react-router-cache-route\";\n\nconst mapStateToProps = (state) => ({\n  createIndex: state.createIndex,\n});\n\nconst connects: Function = connect;\n@connects(mapStateToProps)\nexport class BasicInfo extends React.Component<any> {\n  public state = {\n    cyclicalRoll: \"\",\n    formData: null as any,\n    loading: false,\n    timeFormatList: [],\n  };\n  private $formRef: any = null;\n  private id: number = null;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.id = Number(url.search.id);\n  }\n\n  public async componentDidMount() {\n    getTimeFormat().then((res = []) => {\n      this.setState({\n        timeFormatList: res,\n      });\n    });\n  }\n\n  public componentWillUnmount() {\n    this.$formRef = null;\n  }\n\n  public onHandleValuesChange = (value: any, allValues: object) => {\n    Object.keys(value).forEach((key) => {\n      switch (key) {\n        case \"cyclicalRoll\":\n          this.setState({\n            cyclicalRoll: value[key],\n          });\n          break;\n        case \"clusterInfo\":\n          this.$formRef.setFieldsValue({ level: value?.clusterInfo?.level }); // 选择集群后给level初始值\n          this.props.dispatch(actions.setCreateIndex({ dataCenter: value?.clusterInfo?.dataCenter }));\n          this.setState({ ...this.state });\n          break;\n        default:\n          break;\n      }\n    });\n  };\n\n  public onSubmit = () => {\n    this.$formRef.validateFields().then((result) => {\n      this.props.dispatch(actions.setTemporaryFormMap(TEMP_FORM_MAP_KEY.firstStepFormData, result));\n      this.props.dispatch(actions.setTemporaryFormMap(TEMP_FORM_MAP_KEY.isCyclicalRoll, result.cyclicalRoll === \"more\"));\n      this.props.dispatch(actions.setCurrentStep(1));\n    });\n  };\n\n  public getFormMap = (formData: any): IFormItem[] => {\n    const { cyclicalRoll: cyclicalRollFromStore, timeFormatList } = this.state;\n    const cyclicalRoll = cyclicalRollFromStore || formData.cyclicalRoll;\n    return getStepOneFormMap(cyclicalRoll, false, this.$formRef, timeFormatList, this.props.dataTypeList);\n  };\n\n  public clearStore = (str) => {\n    this.props?.setRemovePaths([str]);\n    dropByCacheKey(\"menu.es.index-tpl.management.create\");\n    this.props.dispatch(actions.setClearCreateIndex());\n  };\n\n  public render() {\n    const formData = this.state.formData || this.props.createIndex.temporaryFormMap.get(TEMP_FORM_MAP_KEY.firstStepFormData) || {};\n\n    return (\n      <>\n        <Spin spinning={this.state.loading}>\n          <div className=\"step\">\n            <XFormComponent\n              wrappedComponentRef={(formRef) => (this.$formRef = formRef)}\n              formData={formData}\n              formMap={this.getFormMap(formData)}\n              onHandleValuesChange={this.onHandleValuesChange}\n            />\n            <div className=\"op-btn-group\">\n              <Button type=\"primary\" onClick={this.onSubmit}>\n                下一步\n              </Button>\n              <CancelActionModal routeHref={\"/index-tpl/management\"} history={this.props?.history} cb={this.clearStore} />\n            </div>\n          </div>\n        </Spin>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/create/config.tsx",
    "content": "import { IFormItem, FormItemType } from \"component/x-form\";\nimport { LEVEL_MAP } from \"constants/common\";\nimport { CYCLICAL_ROLL_TYPE_LIST } from \"./constant\";\nimport { KEEP_LIVE_LIST } from \"constants/time\";\nimport React from \"react\";\n// import { StaffSelect } from \"container/staff-select\";\n// import { staffRuleProps } from \"constants/table\";\nimport { nounPartitionCreate } from \"container/tooltip\";\nimport { LogicCluserSelect } from \"container/custom-form/logic-cluser-select\";\nimport store from \"store\";\nimport { AppState } from \"store/type\";\nimport { getNameCheck, getClusterCheck } from \"api/cluster-index-api\";\nimport { CopyOutlined } from \"@ant-design/icons\";\nimport { copyString } from \"lib/utils\";\n\nconst app = {\n  app: store.getState().app as AppState,\n};\n\nexport const getStepOneFormMap = (\n  cyclicalRoll: string,\n  isModifyPage: boolean,\n  form: any,\n  timeFormatList = [],\n  dataTypeList = []\n): IFormItem[] => {\n  const mapList = [\n    {\n      key: \"name\",\n      label: \"索引模板名称\",\n      attrs: {\n        disabled: isModifyPage,\n        placeholder: \"请填写索引模板名称，支持小写字母、数字、-、_4-128位字符\",\n      },\n      rules: [\n        {\n          required: isModifyPage ? false : true,\n          validator: async (rule: any, value: string) => {\n            if (isModifyPage) return Promise.resolve();\n            value = value?.trim();\n            const reg = /^[.a-z0-9_-]{1,}$/g;\n            if (!value) {\n              return Promise.reject(\"请填写索引模板名称\");\n            }\n            if (!reg.test(value) || value.length > 128 || value.length < 4) {\n              return Promise.reject(\"请正确填写索引模板名称，支持小写字母、数字、-、_4-128位字符\");\n            }\n            if (value) {\n              try {\n                const res = await getNameCheck(value);\n                if (res.code !== 0 && res.code !== 200) {\n                  return Promise.reject(res.message);\n                }\n              } catch (err) {\n                return Promise.reject(\"索引模板名称校验失败\");\n              }\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      key: \"clusterInfo\",\n      label: \"所属集群\",\n      type: FormItemType.custom,\n      customFormItem: <LogicCluserSelect isModifyPage={isModifyPage} $form={form} />,\n      rules: [\n        {\n          required: isModifyPage ? false : true,\n          message: \"请填写完整\",\n          validator: async (rule: any, value: any) => {\n            if (isModifyPage) return Promise.resolve();\n            if (!value) return Promise.reject();\n            if (value.cluster) {\n              try {\n                const res = await getClusterCheck(value.cluster);\n                if (res.code !== 0 && res.code !== 200) {\n                  return Promise.reject(res.message);\n                }\n              } catch (err) {\n                return Promise.reject(\"所属集群校验失败\");\n              }\n              return Promise.resolve();\n            }\n            return Promise.reject();\n          },\n        },\n      ],\n    },\n    {\n      key: \"level\",\n      label: \"业务等级\",\n      type: FormItemType.select,\n      rules: [\n        {\n          required: isModifyPage ? false : true,\n          message: \"请选择业务等级\",\n        },\n      ],\n      attrs: {\n        disabled: isModifyPage,\n        placeholder: \"请选择业务等级\",\n      },\n      options: LEVEL_MAP,\n    },\n    {\n      key: \"cyclicalRoll\",\n      label: \"是否分区\",\n      type: FormItemType.select,\n      rules: [{ required: isModifyPage ? false : true, message: \"请选择是否分区\" }],\n      attrs: {\n        disabled: isModifyPage,\n        placeholder: \"请选择是否分区\",\n      },\n      options: CYCLICAL_ROLL_TYPE_LIST,\n      extraElement: <>{nounPartitionCreate}</>,\n    },\n    {\n      key: \"dateField\",\n      label: \"分区字段\",\n      invisible: cyclicalRoll !== \"more\",\n      attrs: {\n        disabled: isModifyPage,\n        placeholder: \"请输入分区字段\",\n      },\n      rules: [\n        {\n          required: isModifyPage ? false : true,\n          validator: async (rule: any, value: string) => {\n            if (isModifyPage) return Promise.resolve();\n            value = value?.trim();\n            if (!value || value.length > 20) {\n              return Promise.reject(\"请输入分区字段，不超过20位字符\");\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      key: \"dateFieldFormat\",\n      label: \"时间格式\",\n      invisible: cyclicalRoll !== \"more\",\n      type: FormItemType.select,\n      rules: [{ required: isModifyPage ? false : true, message: \"请选择时间格式\" }],\n      options: timeFormatList.map((item) => ({\n        label: item,\n        value: item,\n      })),\n      attrs: {\n        disabled: isModifyPage,\n        placeholder: \"请选择时间格式\",\n      },\n    },\n    {\n      key: \"diskSize\",\n      label: \"索引模板数据大小(GB)\",\n      formAttrs: {\n        dependencies: [\"clusterInfo\"],\n      },\n      defaultValue: 30,\n      type: FormItemType.inputNumber,\n      rules: [\n        {\n          required: true,\n          validator: (rule: any, value: number) => {\n            if (isModifyPage) return Promise.resolve();\n            if (typeof value !== \"number\") {\n              return Promise.reject(\"请输入数据大小(GB)，最小3G, 最大3072G\");\n            }\n            if (value === Infinity || value < 0) {\n              return Promise.reject(\"请输入数据大小(GB)，最小3G, 最大3072G\");\n            }\n\n            if (value < 3 || value > 3072) {\n              return Promise.reject(\"请输入数据大小(GB)，最小3G, 最大3072G\");\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n      attrs: {\n        disabled: isModifyPage,\n        placeholder: \"请输入\",\n      },\n    },\n    {\n      key: \"expireTime\",\n      label: \"保存周期(天)\",\n      invisible: cyclicalRoll !== \"more\",\n      type: FormItemType.select,\n      defaultValue: KEEP_LIVE_LIST[0],\n      rules: [{ required: true, message: \"请选择保存周期\" }],\n      options: KEEP_LIVE_LIST.map((item) => {\n        return {\n          label: item === -1 ? \"永不过期\" : item,\n          value: item,\n        };\n      }),\n    },\n    {\n      key: \"dataType\",\n      label: \"业务类型\",\n      type: FormItemType.select,\n      rules: [{ required: true, message: \"请选择业务类型\" }],\n      options: dataTypeList,\n      attrs: {\n        placeholder: \"请选择业务类型\",\n      },\n    },\n    {\n      key: \"desc\",\n      label: \"模板描述\",\n      type: FormItemType.textArea,\n      attrs: {\n        placeholder: \"请输入0-1000字模板描述\",\n      },\n      rules: [\n        {\n          validator: (rule: any, value: string) => {\n            value = value?.trim();\n            if (!value) {\n              return Promise.resolve();\n            } else if (value.length > 1000) {\n              return Promise.reject(\"请输入0-1000字模板描述\");\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n  ] as IFormItem[];\n  return mapList;\n};\n\nexport const getMappingPreviewInfo = (isCyclicalRoll: boolean, dataTypeList = []) => {\n  if (isCyclicalRoll) {\n    return mappingPreviewInfo(dataTypeList);\n  }\n  return mappingPreviewInfo(dataTypeList).filter(\n    (item) => item.key !== \"expireTime\" && item.key !== \"dateField\" && item.key !== \"dateFieldFormat\"\n  );\n};\n\nexport const mappingPreviewInfo = (dataTypeList) => {\n  return [\n    {\n      label: \"模板名称\",\n      key: \"name\",\n      render: (value: any) => <span>{`${value?.name || \"-\"}`}</span>,\n    },\n    {\n      label: \"所属应用\",\n      key: \"app\",\n      render: (value: any) => <span>{`${app.app.appInfo()?.name || \"-\"}(${app.app.appInfo()?.id || \"-\"})`}</span>,\n    },\n    {\n      label: \"数据中心\",\n      key: \"dataCenter\",\n    },\n    {\n      label: \"所属集群\",\n      key: \"clusterInfo\",\n      render: (value: any) => <span>{value.clusterInfo?.clusterName || \"-\"}</span>,\n    },\n    {\n      label: \"业务等级\",\n      key: \"level\",\n      render: (value: any) => <span>{LEVEL_MAP[Number(value?.level) - 1]?.label || \"-\"}</span>,\n    },\n    {\n      label: \"是否分区\",\n      key: \"cyclicalRoll\",\n      render: (value: any) => (\n        <span>{CYCLICAL_ROLL_TYPE_LIST.filter((item) => item.value === value?.cyclicalRoll)?.[0]?.label || \"-\"}</span>\n      ),\n    },\n    {\n      label: \"保存周期\",\n      key: \"expireTime\",\n      render: (value: any) => <span>{value.expireTime === -1 ? \"永不过期\" : `${value.expireTime}天`}</span>,\n    },\n    {\n      label: \"分区字段\",\n      key: \"dateField\",\n    },\n    {\n      label: \"时间格式\",\n      key: \"dateFieldFormat\",\n    },\n    {\n      label: \"数据大小\",\n      key: \"diskSize\",\n      unit: \"GB\",\n    },\n    {\n      label: \"业务类型\",\n      key: \"dataType\",\n      render: (value: any) => <span>{dataTypeList.filter((item) => item.value === value?.dataType)?.[0]?.label || \"-\"}</span>,\n    },\n    {\n      label: \"描述\",\n      key: \"desc\",\n    },\n  ];\n};\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/create/constant.ts",
    "content": "export const CYCLICAL_ROLL_TYPE_LIST = [\n  {\n    label: \"是\",\n    value: \"more\",\n  },\n  {\n    label: \"否\",\n    value: \"one\",\n  },\n];\n\nexport const TEMP_FORM_MAP_KEY = {\n  firstStepFormData: \"first-step-form-data\",\n  isCyclicalRoll: \"isCyclicalRoll\",\n  jsonMappingValue: \"json-mapping-value\",\n};\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/create/index.less",
    "content": ".content-wrapper {\n  background: white;\n  padding: 20px;\n\n  &.edit {\n    padding-top: 30px;\n  }\n\n  .step {\n    padding-top: 20px;\n  }\n\n  .short-input {\n    width: 50%;\n  }\n}\n\n.op-btns-group {\n  text-align: center;\n  padding: 12px 0px 12px 120px;\n  left: 0px;\n  position: fixed;\n  bottom: 0px;\n  right: 0px;\n  background: transparent;\n  z-index: 10;\n\n  :first-child {\n    margin-left: -16px;\n    margin-right: 8px;\n  }\n\n  :last-child {\n    margin-left: 8px;\n  }\n}\n\n.tab-content {\n  &.no-nav {\n    .ant-tabs-nav {\n      display: none;\n    }\n  }\n\n  &.no-margin {\n    margin-top: 0px;\n  }\n\n  .base-info {\n    padding: 24px 24px 10px 24px;\n    overflow: auto;\n    background: #f8f9fa;\n    border-radius: 4px;\n    .dcloud-descriptions-item {\n      padding-bottom: 6px;\n    }\n    .dcloud-descriptions-item-label {\n      color: rgba(0, 0, 0, 0.6);\n    }\n    .dcloud-descriptions-item-content {\n      margin-bottom: 10px;\n      color: rgba(0, 0, 0, 0.87);\n    }\n\n    .ant-descriptions-row > td {\n      padding-bottom: 40px;\n    }\n  }\n\n  .add-btn {\n    left: 96%;\n    top: -53px;\n    position: relative;\n  }\n\n  .table-mapping-form {\n    max-height: 700px;\n    overflow: scroll;\n\n    &.detail-page {\n      max-height: 610px;\n    }\n\n    .custom-tree-node {\n      display: inline-block;\n      width: 100%;\n\n      .first-level {\n        width: 100%;\n\n        .name-box {\n          width: 14.5%;\n        }\n      }\n\n      .second-level {\n        width: 100%;\n\n        .name-box {\n          width: 13.5%;\n        }\n      }\n\n      .third-level {\n        width: 100%;\n\n        .name-box {\n          width: 13%;\n        }\n      }\n\n      .ant-tree li .ant-tree-node-content-wrapper.ant-tree-node-selected {\n        background-color: #fffdfb;\n      }\n    }\n\n    .ant-tree li .ant-tree-node-content-wrapper {\n      width: 100%;\n    }\n\n    .ant-tree li .ant-tree-node-content-wrapper {\n      height: auto;\n    }\n\n    .first-row {\n      box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);\n      height: 46px;\n    }\n\n    .form-col {\n      margin-right: 15px;\n\n      &.center {\n        text-align: center;\n      }\n    }\n\n    .extra-element {\n      .ant-cascader-picker {\n        width: 80%;\n        margin-right: 10px;\n      }\n    }\n\n    .ant-collapse > .ant-collapse-item:last-child,\n    .ant-collapse > .ant-collapse-item:last-child > .ant-collapse-header {\n      border-bottom: none;\n    }\n\n    .ant-collapse > .ant-collapse-item > .ant-collapse-header {\n      padding: 0px 10px 0px 40px;\n    }\n\n    .ant-collapse-borderless > .ant-collapse-item {\n      border-bottom: none;\n    }\n\n    .ant-collapse-content > .ant-collapse-content-box {\n      padding: 0px;\n      padding-left: 12px;\n      padding-right: 3px;\n    }\n  }\n\n  .json-editor-wrapper {\n    background: #ffffff;\n    border-radius: 4px;\n\n    .CodeMirror {\n      height: calc(100vh - 330px);\n    }\n\n    &.detail {\n      .CodeMirror {\n        height: calc(100vh - 380px);\n      }\n    }\n  }\n\n  .time-select {\n    width: 210px;\n  }\n\n  .json-content-wrapper {\n    padding: 0px 0px 10px 0px;\n    height: calc(100vh - 340px);\n  }\n}\n\n.table-mapping-setting-row {\n  display: flex;\n  align-items: center;\n  height: 80px;\n\n  .ant-form-item {\n    margin-bottom: 0;\n  }\n}\n\n.ant-tree .ant-tree-node-content-wrapper {\n  width: 100%;\n}\n\n.ant-tree-show-line .ant-tree-switcher {\n  display: flex;\n  align-items: center;\n}\n\n.extra-element {\n  .ant-form-item-control-input-content {\n    display: flex;\n    align-items: center;\n  }\n}\n\n.setingcheck-disabled {\n  span {\n    color: black;\n    position: relative;\n    top: 4px;\n  }\n\n  // .ant-checkbox-checked .ant-checkbox-inner {\n  //   background-color: #526ecc;\n  //   border-color: #526ecc;\n  // }\n  // .ant-checkbox-disabled.ant-checkbox-checked .ant-checkbox-inner::after{\n  //   border-color: #fff;\n  // }\n}\n\n.setting-check {\n  height: 52px;\n  // margin-top: 24px;\n  background: #ffffff;\n  border: 1px solid #ebedef;\n\n  .left-box {\n    width: 180px;\n    height: 50px;\n    background: #f9f9fa;\n    border-radius: 4px 0 0 4px;\n    display: inline-block;\n    padding: 18px 0px 0px 24px;\n  }\n\n  .right-box {\n    display: inline-block;\n    padding: 18px 0px 0px 24px;\n    position: relative;\n  }\n}\n\n.detail-tabs {\n  width: 177px;\n  height: 32px;\n  background: #f4f4f6;\n  border-radius: 4px;\n  margin-bottom: 16px;\n  display: flex;\n  padding: 4px;\n  justify-content: space-between;\n\n  &-item {\n    width: 72px;\n    height: 24px;\n    border-radius: 4px;\n    font-family: PingFangSC-Medium;\n    font-size: 14px;\n    color: #5b6675;\n    line-height: 20px;\n    text-align: center;\n    cursor: pointer;\n    user-select: text;\n    padding: 2px 8px 2px 8px;\n  }\n\n  &-item-json {\n    width: 82px;\n    height: 24px;\n    border-radius: 4px;\n    font-family: PingFangSC-Medium;\n    font-size: 14px;\n    color: #5b6675;\n    line-height: 20px;\n    text-align: center;\n    cursor: pointer;\n    user-select: text;\n    padding: 2px 8px 2px 8px;\n  }\n\n  .check {\n    background: #ffffff;\n    color: @primary-color;\n  }\n}\n\n.ant-page-header-content {\n  padding-top: 0;\n}\n\n.tpl-edit-mapping {\n  height: calc(100vh - 345px);\n}\n\n.tpl-detail-mapping {\n  height: calc(100vh - 345px);\n}\n\n.tpl-create-mapping {\n  height: calc(100vh - 320px);\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/create/index.tsx",
    "content": "import * as React from \"react\";\nimport { BasicInfo } from \"./basicInfo\";\nimport { Mapping } from \"./mapping\";\nimport \"./index.less\";\nimport { LastStep } from \"./last-step\";\nimport { Setting } from \"./setting\";\nimport Url from \"lib/url-parser\";\nimport { Steps } from \"antd\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { getFormatJsonStr } from \"lib/utils\";\nimport { getIndexDataType } from \"api/cluster-index-api\";\n\nconst { Step } = Steps;\n\nconst mapStateToProps = (state) => ({\n  createIndex: state.createIndex,\n});\nconst connects: Function = connect;\n\n@connects(mapStateToProps)\nexport class CreateIndexTpl extends React.Component<any> {\n  state = {\n    dataTypeList: [],\n  };\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.props.dispatch(\n      actions.setCreateIndex({\n        customerAnalysisValue: getFormatJsonStr({\n          index: {\n            \"translog.durability\": \"async\",\n            \"translog.sync_interval\": \"15s\",\n            refresh_interval: \"1s\",\n            // codec: \"default\",\n          },\n        }),\n      })\n    );\n  }\n\n  public componentDidMount() {\n    getIndexDataType().then((res = {}) => {\n      const dataTypeList = Object.keys(res).map((key) => {\n        return {\n          title: res[key],\n          label: res[key],\n          value: Number(key),\n        };\n      });\n      this.setState({ dataTypeList });\n    });\n  }\n\n  public renderContent = () => {\n    const componentMap = {\n      0: <BasicInfo {...this.props} dataTypeList={this.state.dataTypeList} />,\n      1: <Mapping />,\n      2: <Setting />,\n      3: <LastStep {...this.props} dataTypeList={this.state.dataTypeList} />,\n    } as {\n      [key: number]: JSX.Element;\n    };\n    return componentMap[this.props.createIndex.currentStep];\n  };\n\n  public render() {\n    return (\n      <>\n        <div className=\"content-wrapper\">\n          <Steps current={this.props.createIndex.currentStep}>\n            <Step title=\"基础信息\" />\n            <Step title=\"Mapping设置\" />\n            <Step title=\"Setting设置\" />\n            <Step title=\"设置完成\" />\n          </Steps>\n          {this.renderContent()}\n        </div>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/create/last-step.tsx",
    "content": "import * as React from \"react\";\nimport \"./index.less\";\nimport { BasicInfoPreview } from \"./basicInfo-preview\";\nimport { TEMP_FORM_MAP_KEY } from \"./constant\";\nimport { CancelActionModal } from \"container/custom-component\";\nimport { Tabs, Button, message } from \"antd\";\nimport * as actions from \"actions\";\nimport { connect } from \"react-redux\";\nimport { createIndex } from \"api/cluster-index-api\";\nimport { getFormatJsonStr, formatJsonStr } from \"lib/utils\";\nimport { dropByCacheKey, refreshByCacheKey } from \"react-router-cache-route\";\nimport { ACEJsonEditor } from \"@knowdesign/kbn-sense/lib/packages/kbn-ace/src/ace/json_editor\";\n\nconst mapStateToProps = (state) => ({\n  createIndex: state.createIndex,\n});\nconst connects: Function = connect;\n\n@connects(mapStateToProps)\nexport class LastStep extends React.Component<any> {\n  public extraInfo = {};\n\n  constructor(props: any) {\n    super(props);\n    this.getExtraInfo();\n  }\n\n  public getExtraInfo = () => {\n    const firstStepFormData = this.props.createIndex.temporaryFormMap.get(TEMP_FORM_MAP_KEY.firstStepFormData) || {};\n    this.props.dispatch(actions.setTemporaryFormMap(TEMP_FORM_MAP_KEY.firstStepFormData, firstStepFormData));\n  };\n\n  public clearStore = () => {\n    dropByCacheKey(\"menu.es.index-tpl.management.create\");\n    this.props?.setRemovePaths([\"/es/index-tpl/management/create\"]);\n    this.props.dispatch(actions.setClearCreateIndex());\n    refreshByCacheKey(`menu.es.index-tpl.management`);\n  };\n\n  public onSubmit = () => {\n    const mappingData = this.props.createIndex.temporaryFormMap.get(TEMP_FORM_MAP_KEY.jsonMappingValue) || \"\";\n    const formData = this.props.createIndex.temporaryFormMap.get(TEMP_FORM_MAP_KEY.firstStepFormData);\n    const { customerAnalysisValue, dataCenter } = this.props.createIndex;\n    const postData = {\n      dataCenter,\n      name: `${formData.name}`,\n      resourceId: formData.clusterInfo?.cluster,\n      level: formData.level,\n      cyclicalRoll: formData.cyclicalRoll === \"more\" ? 1 : 0,\n      expireTime: formData.expireTime,\n      dateField: formData.dateField,\n      dateFieldFormat: formData.dateFieldFormat,\n      diskSize: Number(formData.diskSize),\n      dataType: formData.dataType,\n      desc: formData.desc,\n      mapping: formatJsonStr(mappingData),\n      setting: formatJsonStr(customerAnalysisValue),\n    };\n    const backUrl = \"/index-tpl/management\";\n\n    this.props.dispatch(actions.setLoadingMap(\"create-loading\", true));\n    createIndex(postData)\n      .then(() => {\n        message.success(\"模板创建成功\");\n        this.clearStore();\n        this.props?.history?.push(backUrl);\n      })\n      .finally(() => {\n        this.props.dispatch(actions.setLoadingMap(\"create-loading\", false));\n        this.props.dispatch(\n          actions.setCreateIndex({\n            customerAnalysisValue: getFormatJsonStr({\n              index: {\n                \"translog.durability\": \"async\",\n                \"translog.sync_interval\": \"15s\",\n                refresh_interval: \"1s\",\n              },\n            }),\n          })\n        );\n      });\n  };\n\n  public render() {\n    const mapping = this.props.createIndex.temporaryFormMap.get(TEMP_FORM_MAP_KEY.jsonMappingValue) || \"{}\";\n    const setting = this.props.createIndex.customerAnalysisValue || \"{}\";\n\n    return (\n      <>\n        <Tabs type=\"card\" className=\"tab-content mt-20 \">\n          <Tabs.TabPane tab=\"基本信息\" key=\"1\">\n            <BasicInfoPreview dataTypeList={this.props.dataTypeList} />\n          </Tabs.TabPane>\n          <Tabs.TabPane tab=\"Mapping\" key=\"2\">\n            <div className=\"json-content-wrapper\">\n              <ACEJsonEditor className={\"mapping-detail\"} readOnly={true} data={getFormatJsonStr(JSON.parse(mapping))} />\n            </div>\n          </Tabs.TabPane>\n          <Tabs.TabPane tab=\"Setting\" key=\"3\">\n            <div className=\"json-content-wrapper\">\n              <ACEJsonEditor className={\"mapping-detail\"} readOnly={true} data={getFormatJsonStr(JSON.parse(setting))} />\n            </div>\n          </Tabs.TabPane>\n        </Tabs>\n        <div className=\"op-btn-group\">\n          <Button onClick={() => this.props.dispatch(actions.setCurrentStep(2))}>上一步</Button>\n          <Button type=\"primary\" loading={this.props.createIndex.loadingMap[\"create-loading\"]} onClick={this.onSubmit}>\n            确定\n          </Button>\n          <CancelActionModal routeHref={\"/index-tpl/management\"} history={this.props?.history} cb={this.clearStore} />\n        </div>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/create/mapping.tsx",
    "content": "import * as React from \"react\";\nimport { TEMP_FORM_MAP_KEY } from \"./constant\";\nimport { Button, message } from \"antd\";\nimport * as actions from \"actions\";\nimport { connect } from \"react-redux\";\nimport \"./index.less\";\nimport { JsonEditorWrapper } from \"component/jsonEditorWrapper\";\n\nconst mapStateToProps = (state) => ({\n  createIndex: state.createIndex,\n});\n\nconst connects: Function = connect;\n@connects(mapStateToProps)\nexport class Mapping extends React.Component<any> {\n  // private isCyclicalRoll: boolean = false;\n  static defaultProps: { isShowPlaceholder: boolean } = { isShowPlaceholder: true };\n\n  constructor(props: any) {\n    super(props);\n    // this.isCyclicalRoll = !!props.createIndex.temporaryFormMap.get(TEMP_FORM_MAP_KEY.isCyclicalRoll);\n    this.props.dispatch(actions.setLoadingMap(\"mapping-loading\", false));\n  }\n\n  public state = {\n    disabled: false,\n  };\n\n  public componentDidMount() {\n    //\n  }\n\n  public setValid = (valid: boolean) => {\n    this.setState({\n      disabled: !valid,\n    });\n  };\n\n  public onHandlePrevStep = async () => {\n    const editor = this.props.createIndex.activeInstance;\n    const value = editor ? editor.getValue() : \"\";\n    this.props.dispatch(actions.setTemporaryFormMap(TEMP_FORM_MAP_KEY.jsonMappingValue, value));\n    this.props.dispatch(actions.setCurrentStep(0));\n  };\n\n  public onHandleNextStep = async () => {\n    try {\n      const editor = this.props.createIndex.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      this.props.dispatch(actions.setTemporaryFormMap(TEMP_FORM_MAP_KEY.jsonMappingValue, value));\n      this.props.dispatch(actions.setCurrentStep(2));\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public render() {\n    const value = this.props.createIndex.temporaryFormMap.get(TEMP_FORM_MAP_KEY.jsonMappingValue) || \"\";\n    const loading = this.props.createIndex.loadingMap[\"mapping-loading\"];\n\n    return (\n      <div id=\"mappingName\" className={\"tab-content\"}>\n        <JsonEditorWrapper\n          data={value}\n          isNeedAutoIndent={true}\n          title={\"Mapping编辑器\"}\n          loading={loading}\n          docType=\"mapping\"\n          setEditorInstance={(editor) => {\n            this.props.dispatch(actions.setEditorInstance(editor));\n          }}\n          setValid={this.setValid}\n          jsonClassName={\"tpl-create-mapping\"}\n        />\n        <div className={`op-btns-group`}>\n          <Button onClick={this.onHandlePrevStep}>上一步</Button>\n          <Button type=\"primary\" onClick={this.onHandleNextStep}>\n            下一步\n          </Button>\n          {/* {!this.isCyclicalRoll && <Button onClick={() => this.skip()}>跳过</Button>} */}\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/create/setting.tsx",
    "content": "import * as React from \"react\";\n// import { TEMP_FORM_MAP_KEY } from \"./constant\";\nimport { Button, message } from \"antd\";\nimport * as actions from \"actions\";\nimport { connect } from \"react-redux\";\nimport \"./index.less\";\nimport { JsonEditorWrapper } from \"component/jsonEditorWrapper\";\n\nconst mapStateToProps = (state) => ({\n  createIndex: state.createIndex,\n});\n\nconst connects: any = connect;\n@connects(mapStateToProps)\nexport class Setting extends React.Component<any> {\n  // private isCyclicalRoll: boolean = false;\n  static defaultProps: { isShowPlaceholder: boolean } = { isShowPlaceholder: true };\n\n  constructor(props: any) {\n    super(props);\n    // this.isCyclicalRoll = !!props.createIndex.temporaryFormMap.get(TEMP_FORM_MAP_KEY.isCyclicalRoll);\n    this.props.dispatch(actions.setLoadingMap(\"setting-loading\", false));\n  }\n\n  public state = {\n    disabled: false,\n  };\n\n  public componentDidMount() {}\n\n  // public skip = () => {\n  //   const customerAnalysisJsonEditor = this.props.createIndex.customerAnalysisJson;\n  //   const customerAnalysisValue = customerAnalysisJsonEditor ? customerAnalysisJsonEditor.getValue() : \"\";\n  //   this.props.dispatch(actions.setCreateIndex({ customerAnalysisValue }));\n  //   this.props.dispatch(actions.setCurrentStep(3));\n  // };\n\n  public onHandlePrevStep = () => {\n    const customerAnalysisJsonEditor = this.props.createIndex.customerAnalysisJson;\n    const customerAnalysisValue = customerAnalysisJsonEditor ? customerAnalysisJsonEditor.getValue() : \"\";\n    this.props.dispatch(actions.setCreateIndex({ customerAnalysisValue }));\n    this.props.dispatch(actions.setCurrentStep(1));\n  };\n\n  public onHandleNextStep = () => {\n    try {\n      const customerAnalysisJsonEditor = this.props.createIndex.customerAnalysisJson;\n      const customerAnalysisValue = customerAnalysisJsonEditor ? customerAnalysisJsonEditor.getValue() : \"\";\n      let jsonValue = {};\n\n      if (customerAnalysisValue) {\n        jsonValue = JSON.parse(customerAnalysisValue || \"null\");\n      }\n      this.props.dispatch(actions.setCreateIndex({ customerAnalysisValue }));\n      this.props.dispatch(actions.setCurrentStep(3));\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public setValid = (valid: boolean) => {\n    this.setState({\n      disabled: !valid,\n    });\n  };\n\n  public render() {\n    const loading = this.props.createIndex.loadingMap[\"setting-loading\"];\n    const { customerAnalysisValue } = this.props.createIndex;\n\n    return (\n      <div id=\"settingName\" className={\"tab-content\"}>\n        <JsonEditorWrapper\n          data={customerAnalysisValue}\n          title={\"Setting编辑器\"}\n          isNeedAutoIndent={true}\n          loading={loading}\n          docType=\"setting\"\n          setEditorInstance={(editor) => {\n            this.props.dispatch(actions.setCreateIndex({ customerAnalysisJson: editor }));\n          }}\n          setValid={this.setValid}\n          isShowMappingTip={false}\n          jsonClassName={\"tpl-create-mapping\"}\n        />\n        <div className=\"op-btns-group\">\n          <Button onClick={this.onHandlePrevStep}>上一步</Button>\n          <Button type=\"primary\" onClick={this.onHandleNextStep}>\n            下一步\n          </Button>\n          {/* {!this.isCyclicalRoll && <Button onClick={() => this.skip()}>跳过</Button>} */}\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/detail/base-info.tsx",
    "content": "import React from \"react\";\nimport { baseInfo } from \"./config\";\nimport { BaseDetail } from \"component/dantd/base-detail\";\nimport \"./index.less\";\n\nexport interface ITemplateSrv {\n  esVersion: string;\n  serviceId: number;\n  serviceName: string;\n}\nexport class BaseInfo extends React.Component<{ data: any }> {\n  constructor(props: any) {\n    super(props);\n  }\n\n  public render() {\n    const { data } = this.props;\n    return (\n      <div className=\"base-info\">\n        <BaseDetail columns={baseInfo} baseDetail={data} />\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/detail/config.tsx",
    "content": "import React from \"react\";\nimport { Tag, Tooltip } from \"antd\";\nimport { BaseInfo } from \"./base-info\";\nimport { cellStyle } from \"constants/table\";\nimport { IPartition } from \"typesPath/index-types\";\nimport { IndexPartition } from \"./partition\";\nimport { IOpRecord, ITemplateLogic } from \"typesPath/cluster/physics-type\";\nimport { OperatingRecord } from \"./record\";\nimport { JsonMapping } from \"../edit/jsonMapping\";\nimport { JsonSetting } from \"../edit/jsonSetting\";\nimport { LEVEL_MAP } from \"constants/common\";\nimport { transTimeFormat, bytesUnitFormatter, formatDecimalPoint } from \"lib/utils\";\nimport { columnsRender } from \"../management/config\";\nexport const formColumns = [\n  {\n    type: \"input\",\n    title: \"主机名称\",\n    dataIndex: \"ip\",\n    placeholder: \"请输入\",\n  },\n];\nexport const queryFormText: { searchText: string; resetText: string } = {\n  searchText: \"查询\",\n  resetText: \"重置\",\n};\nexport const getColumns = (setModalId?: any, setDrawerId?: any, reloadDataFn?: any) => {\n  return [\n    {\n      title: \"主机名称\",\n      dataIndex: \"ip\",\n      render: (item, row) => {\n        return {\n          children: columnsRender(item),\n          props: {\n            rowSpan: row.rowSpan,\n          },\n        };\n      },\n    },\n    {\n      title: \"Shard个数\",\n      dataIndex: \"shardCount\",\n      render: (item, row) => {\n        return {\n          children: columnsRender(item),\n          props: {\n            rowSpan: row.rowSpan,\n          },\n        };\n      },\n    },\n    {\n      title: \"文档总个数\",\n      dataIndex: \"totalDocs\",\n      render: (item, row) => {\n        return {\n          children: columnsRender(item),\n          props: {\n            rowSpan: row.rowSpan,\n          },\n        };\n      },\n    },\n    {\n      title: \"总存储大小\",\n      dataIndex: \"totalStore\",\n      render: (item, row) => {\n        return {\n          children: bytesUnitFormatter(item, \"float\"),\n          props: {\n            rowSpan: row.rowSpan,\n          },\n        };\n      },\n    },\n    {\n      title: \"Shard状态\",\n      dataIndex: \"state\",\n      render: (item, row) => columnsRender(item),\n    },\n    {\n      title: \"shard序号\",\n      dataIndex: \"shard\",\n      render: (item) => columnsRender(item),\n    },\n    {\n      title: \"进程名称\",\n      dataIndex: \"node\",\n      render: (item) => columnsRender(item),\n    },\n    {\n      title: \"文档个数\",\n      dataIndex: \"docs\",\n      render: (item) => columnsRender(item),\n    },\n    {\n      title: \"存储大小\",\n      dataIndex: \"storeInByte\",\n      render: (item) => bytesUnitFormatter(item, \"float\"),\n    },\n  ].map((item) => ({\n    ...item,\n    align: \"center\",\n  }));\n};\nexport const DESC_LIST = [\n  {\n    label: \"所属集群\",\n    key: \"cluster\",\n    width: 250,\n    render: (cluster: string) => cluster || \"-\",\n  },\n  {\n    label: \"业务等级\",\n    key: \"level\",\n    render: (value: any) => <span>{LEVEL_MAP[value - 1]?.label || \"-\"}</span>,\n  },\n];\n\nexport enum TAB_LIST_KEY {\n  info = \"info\",\n  mapping = \"mapping\",\n  setting = \"setting\",\n  partition = \"partition\",\n  record = \"record\",\n}\n\nexport const INDEX_TAB_LIST = [\n  {\n    name: \"基本信息\",\n    key: TAB_LIST_KEY.info,\n    content: (data) => <BaseInfo data={data} />,\n  },\n  {\n    name: \"Mapping\",\n    key: TAB_LIST_KEY.mapping,\n    content: (data) => <JsonMapping isShowPlaceholder={false} />,\n  },\n  {\n    name: \"Setting\",\n    key: TAB_LIST_KEY.setting,\n    content: (data) => <JsonSetting isShowPlaceholder={false} />,\n  },\n  {\n    name: \"分区详情\",\n    key: TAB_LIST_KEY.partition,\n    content: (data) => <IndexPartition />,\n  },\n  {\n    name: \"操作记录\",\n    key: TAB_LIST_KEY.record,\n    content: (data) => <OperatingRecord recordType=\"bizId\" />,\n  },\n];\n\nconst menuMap = new Map();\nINDEX_TAB_LIST.forEach((d) => {\n  menuMap.set(d.key, d);\n});\nexport const DETAIL_MENU_MAP = menuMap;\n\nexport const baseInfo: any = [\n  {\n    key: \"dateFormat\",\n    label: \"滚动格式\",\n    render: (text) => {\n      return text || \"-\";\n    },\n  },\n  {\n    key: \"dateField\",\n    label: \"分区字段\",\n    render: (text) => {\n      return text || \"-\";\n    },\n  },\n  {\n    key: \"dateFieldFormat\",\n    label: \"时间格式\",\n    render: (text) => {\n      return text || \"-\";\n    },\n  },\n  {\n    key: \"expireTime\",\n    label: \"生命周期\",\n    render: (text) => {\n      return text || \"-\";\n    },\n  },\n  {\n    key: \"quota\",\n    label: \"数据大小(GB)\",\n    render: (text: number) => (\n      <>\n        <span className=\"text-value\">{text || \"-\"}</span>\n        {/* <a\n            href=\"http://wiki.intra.xiaojukeji.com/pages/viewpage.action?pageId=235801075\"\n            target=\"_blank\"\n          >\n            Arius Quota说明\n          </a> */}\n      </>\n    ),\n  },\n  {\n    key: \"first\",\n    label: \"最早分区\",\n    render: (text) => {\n      return text || \"-\";\n    },\n  },\n  {\n    key: \"createTime\",\n    label: \"创建时间\",\n    render: (value: string) => transTimeFormat(value),\n  },\n  {\n    key: \"desc\",\n    label: \"描述\",\n    render: (desc: string) => (\n      <>\n        <Tooltip placement=\"bottomLeft\" title={desc}>\n          {desc?.length > 20 ? desc.slice(0, 20) + \"...\" : desc || \"-\"}\n        </Tooltip>\n      </>\n    ),\n  },\n  {\n    key: \"disableIndexRollover\",\n    label: \"Rollover\",\n    render: (value: string) => <>{value === null || value === undefined ? \"-\" : value ? \"否\" : \"是\"}</>,\n  },\n];\n\nexport const getIndexPartitionColumns = () => {\n  const cols = [\n    {\n      title: \"分区名称\",\n      dataIndex: \"index\",\n      key: \"index\",\n      width: \"12%\",\n      onCell: () => ({\n        style: cellStyle,\n      }),\n      render: (text: string, record: IPartition) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={text}>\n            {text}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"分区状态\",\n      dataIndex: \"status\",\n      key: \"status\",\n      width: \"10%\",\n    },\n    {\n      title: \"健康状态\",\n      dataIndex: \"health\",\n      key: \"health\",\n      width: \"8%\",\n      render: (text: string) => {\n        return <Tag color={text}>{text}</Tag>;\n      },\n    },\n    {\n      title: \"shard个数\",\n      dataIndex: \"pri\",\n      key: \"pri\",\n      width: \"10%\",\n      sorter: (a: IPartition, b: IPartition) => a.pri - b.pri,\n    },\n    {\n      title: \"副本个数\",\n      dataIndex: \"rep\",\n      key: \"rep\",\n      width: \"10%\",\n      sorter: (a: IPartition, b: IPartition) => a.rep - b.rep,\n    },\n    {\n      title: \"文档个数\",\n      dataIndex: \"docsCount\",\n      key: \"docsCount\",\n      width: \"10%\",\n      sorter: (a: IPartition, b: IPartition) => a.docsCount - b.docsCount,\n    },\n    {\n      title: \"删除文档个数\",\n      dataIndex: \"docsDeleted\",\n      key: \"docsDeleted\",\n      width: \"12%\",\n      sorter: (a: IPartition, b: IPartition) => a.docsDeleted - b.docsDeleted,\n    },\n    {\n      title: \"主分片存储大小\",\n      dataIndex: \"priStoreSize\",\n      key: \"priStoreSize\",\n      width: \"10%\",\n      render: (text: string) => formatDecimalPoint(text),\n    },\n    {\n      title: \"存储大小\",\n      dataIndex: \"storeSize\",\n      key: \"storeSize\",\n      width: \"10%\",\n      render: (text: string) => formatDecimalPoint(text),\n    },\n  ];\n  return cols;\n};\n\nexport const getOperationColumns = (setDrawerId) => {\n  let cols = [\n    {\n      title: \"业务ID\",\n      dataIndex: \"id\",\n      sorter: true,\n      width: 100,\n    },\n    {\n      title: \"操作时间\",\n      dataIndex: \"operateTime\",\n      sorter: true,\n      width: 160,\n      render: (t) => transTimeFormat(t),\n    },\n    {\n      title: \"模块\",\n      dataIndex: \"module\",\n      width: 100,\n    },\n    {\n      title: \"操作内容\",\n      dataIndex: \"content\",\n      width: 360,\n      render: (text: string, record: any) => {\n        let diffArr = [\"编辑MAPPING\", \"编辑SETTING\", \"配置文件变更\"];\n        if (diffArr.includes(record.operate)) {\n          try {\n            const data = text ? JSON.parse(text) : {};\n            let operate: string;\n            if (record.operate === \"编辑MAPPING\") {\n              operate = \"Mapping\";\n            } else if (record.operate === \"编辑SETTING\") {\n              operate = \"Setting\";\n            } else if (record.operate === \"配置文件变更\") {\n              operate = \"配置文件\";\n            }\n            return (\n              <>\n                <span style={{ marginRight: \"5px\" }}>{record.operate}</span>\n                <a href=\"JavaScript:;\" onClick={() => setDrawerId(\"mappingSettingDiff\", { operate, data })}>\n                  查看\n                </a>\n              </>\n            );\n          } catch (err) {\n            console.log(err);\n          }\n        } else {\n          return columnsRender(text) || \"-\";\n        }\n      },\n    },\n    {\n      title: \"行为\",\n      dataIndex: \"operate\",\n      width: 160,\n    },\n    {\n      title: \"操作人\",\n      dataIndex: \"userOperation\",\n      width: 100,\n    },\n  ];\n  return cols;\n};\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/detail/index.less",
    "content": "@import \"../../../styles/base.less\";\n\n.base-index-box {\n  &-tag {\n    padding-top: 20px;\n    display: flex;\n    flex-wrap: wrap;\n\n    &-item {\n      display: flex;\n      padding-right: 30px;\n      align-items: center;\n\n      &-title {\n        .min-title();\n        padding-right: 4px;\n        cursor: pointer;\n      }\n\n      &-title:hover {\n        color: #2a8fff;\n      }\n    }\n  }\n}\n\n.base-info-title {\n  .middle-title();\n  border-bottom: 1px solid #dbe0e4;\n  padding-bottom: 8px;\n}\n\n.clear-info {\n  background: white;\n  padding: 20px;\n  display: flex;\n  justify-content: space-around;\n\n  .option-panel {\n    flex: 1;\n    max-width: 600px;\n    padding-left: 30px;\n\n    .op-btn {\n      margin-bottom: 10px;\n    }\n\n    .tip {\n      color: red;\n      padding: 10px 0px;\n\n      &.more-padding {\n        padding-bottom: 20px;\n        padding-top: 20px;\n      }\n    }\n\n    .sql-content {\n      margin: 15px 0px;\n      padding: 10px 0px;\n      height: 250px;\n      border: 1px solid #e8e8e8;\n    }\n  }\n\n  .table-wrapper {\n    flex: 1;\n  }\n}\n\n.tpl-dcdr {\n  position: relative;\n\n  &-btnbox {\n    position: absolute;\n    top: -78px;\n    right: 0;\n  }\n}\n\n.detail-wrapper.index-tpl-detail {\n  height: calc(100vh - 244px);\n  margin: 0;\n  border-radius: 0 0 8px 8px;\n\n  &.service {\n    height: calc(100vh - 265px);\n    padding-top: 20px;\n\n    .tpl-detail-mapping {\n      height: calc(100vh - 335px);\n    }\n  }\n\n  .base-info-box,\n  .json-editor-wrapper {\n    margin-top: 0;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/detail/index.tsx",
    "content": "import * as React from \"react\";\nimport { Menu, Spin, Divider } from \"knowdesign\";\nimport \"styles/detail.less\";\nimport { DESC_LIST, DETAIL_MENU_MAP, INDEX_TAB_LIST } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { connect } from \"react-redux\";\nimport { getIndexBaseInfo } from \"api/cluster-index-api\";\nimport { IUNSpecificInfo } from \"typesPath/base-types\";\nimport { ITemplateLogic } from \"typesPath/cluster/physics-type\";\nimport { AppState } from \"store/type\";\n\nexport interface IBaseButton {\n  label: string;\n  type: \"primary\" | \"dashed\";\n  clickFunc: () => any;\n  attr?: any;\n}\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nconst mapStateToProps = (state) => ({\n  app: state.app,\n});\n\nconst connects: Function = connect;\n@connects(mapStateToProps, mapDispatchToProps)\nexport class IndexTplDetail extends React.Component<{ setModalId: Function; app: AppState; history: any }> {\n  public id: number;\n  public authType: number;\n  private isServiceDetailPage: boolean = false;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.id = Number(url.search.id);\n    this.authType = Number(url.search.authType);\n    this.isServiceDetailPage = window.location.pathname.includes(\"/service\");\n\n    window.addEventListener(\"hashchange\", () => {\n      this.updateLogicMenu();\n    });\n  }\n\n  public state = {\n    menu: window.location.hash.replace(\"#\", \"\") || \"info\",\n    indexBaseInfo: {} as ITemplateLogic,\n    loading: false,\n  };\n\n  public updateLogicMenu() {\n    this.setState({\n      menu: window.location.hash.replace(\"#\", \"\") || \"info\",\n    });\n  }\n\n  public componentDidMount() {\n    this.reloadData();\n  }\n\n  public componentWillUnmount() {\n    this.setState = () => false;\n  }\n\n  public reloadData = () => {\n    this.setState({\n      loading: true,\n    });\n    getIndexBaseInfo(this.id)\n      .then((baseInfo: IUNSpecificInfo) => {\n        const info = baseInfo || ({} as IUNSpecificInfo);\n        info.first = info.indices?.[0];\n        info.last = info.indices?.pop();\n        info.authType = this.authType;\n        info.expireTime = info.expireTime === -1 ? \"永久\" : `${info.expireTime}天`;\n        this.setState({\n          indexBaseInfo: info,\n        });\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n  };\n\n  public renderPageHeader() {\n    const { indexBaseInfo } = this.state;\n    return (\n      <div className=\"detail-header\">\n        <div className=\"left-content\">\n          <span className=\"icon iconfont iconarrow-left\" onClick={() => this.props.history.push(\"/index-tpl/service\")}></span>\n          <Divider type=\"vertical\"></Divider>\n          <div className=\"title\">\n            <span className=\"text\">{indexBaseInfo?.name || \"\"}</span>\n          </div>\n        </div>\n        <div className=\"right-content\">\n          {DESC_LIST.map((row, index) => {\n            return (\n              <span className=\"detail\" key={index}>\n                <span className=\"label\">{row.label}：</span>\n                <span className=\"value\">{row.render(indexBaseInfo?.[row.key])}</span>\n              </span>\n            );\n          })}\n          <div className=\"reload-icon\" onClick={this.reloadData}>\n            <span className=\"icon iconfont iconshuaxin2\"></span>\n          </div>\n        </div>\n      </div>\n    );\n  }\n\n  public renderContent = () => {\n    return DETAIL_MENU_MAP.get(this.state.menu)?.content(this.state.indexBaseInfo);\n  };\n\n  public changeMenu = (e) => {\n    window.location.hash = e.key;\n  };\n\n  public render() {\n    return (\n      <div className=\"detail-container\">\n        <Spin spinning={this.state.loading}>\n          {this.renderPageHeader()}\n          <div className=\"menu-container\">\n            <Menu className=\"menu\" selectedKeys={[this.state.menu]} mode=\"horizontal\" onClick={this.changeMenu}>\n              {INDEX_TAB_LIST.map((d) => (\n                <Menu.Item key={d.key}>{d.name}</Menu.Item>\n              ))}\n            </Menu>\n          </div>\n\n          <div className={`detail-wrapper ${this.isServiceDetailPage ? \"index-tpl-detail service\" : \"index-tpl-detail\"}`}>\n            {this.renderContent()}\n          </div>\n        </Spin>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/detail/partition.tsx",
    "content": "import * as React from \"react\";\nimport \"styles/search-filter.less\";\nimport { getIndexPartitionColumns } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { getIndexPartitionList } from \"api/cluster-index-api\";\nimport { DTable } from \"component/dantd/dtable\";\n\nexport class IndexPartition extends React.Component {\n  public state = {\n    searchKey: \"\",\n    indexList: [],\n    loading: false,\n  };\n\n  public id: number;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.id = Number(url.search.id);\n  }\n\n  public getData = (origin?: any[]) => {\n    let { searchKey } = this.state;\n    searchKey = (searchKey + \"\").trim().toLowerCase();\n    const data = searchKey ? origin.filter((d) => d.index && d.index.toLowerCase().includes(searchKey as string)) : origin;\n    return data;\n  };\n\n  public componentDidMount() {\n    this.reloadData();\n  }\n\n  public reloadData = () => {\n    this.setState({\n      loading: true,\n    });\n\n    getIndexPartitionList(this.id)\n      .then((res) => {\n        this.setState({\n          indexList: (res || []).sort((a, b) => a.id - b.id) || [],\n        });\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n  };\n\n  public handleSubmit = (value) => {\n    this.setState({\n      searchKey: value,\n    });\n  };\n\n  public render() {\n    const { indexList, loading } = this.state;\n    const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n    return (\n      <>\n        <DTable\n          loading={loading}\n          rowKey=\"id\"\n          dataSource={this.getData(indexList)}\n          columns={getIndexPartitionColumns()}\n          reloadData={this.reloadData}\n          tableHeaderSearchInput={{ submit: this.handleSubmit }}\n          attrs={{\n            scroll: {\n              y: clientHeight > 500 ? clientHeight - 200 : 300,\n            },\n          }}\n        />\n      </>\n    );\n  }\n\n  public defineTableWrapperClassNames = () => {\n    return \"no-padding\";\n  };\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/detail/record.tsx",
    "content": "import * as React from \"react\";\nimport \"styles/search-filter.less\";\nimport { getOperationColumns } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { getUserRecordList } from \"api/cluster-api\";\nimport { IOperaRecordt } from \"typesPath/cluster/cluster-types\";\nimport { connect } from \"react-redux\";\nimport { initPaginationProps } from \"constants/table\";\nimport * as actions from \"actions\";\n\nconst mapDispatchToProps = (dispatch: any) => ({\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params, cb)),\n});\n\nconst connects: Function = connect;\n@connects(null, mapDispatchToProps)\nexport class OperatingRecord extends React.Component<any> {\n  public state = {\n    tableData: [] as IOperaRecordt[],\n    loading: false,\n    queryObject: {\n      content: \"\",\n      page: 1,\n      size: 10,\n    },\n    paginationProps: initPaginationProps(),\n  };\n\n  public id: number | string;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.id = props?.recordType === \"bizId\" ? Number(url.search.id) : url.search.index;\n  }\n\n  public componentDidMount() {\n    this.reloadData();\n  }\n\n  public reloadData = () => {\n    this.setState({\n      loading: true,\n    });\n    const { queryObject, paginationProps } = this.state;\n    getUserRecordList({ bizId: this.id, ...queryObject })\n      .then((res) => {\n        const { pageNo = 1, pageSize = 10, total = 0 } = res?.pagination;\n        this.setState({\n          tableData: res?.bizData || [],\n          paginationProps: {\n            ...paginationProps,\n            total: total,\n            current: pageNo,\n            pageSize: pageSize,\n          },\n        });\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n  };\n\n  public handleSubmit = (value) => {\n    value = value?.trim();\n    if (value === this.state.queryObject.content) return;\n    this.setState(\n      {\n        queryObject: {\n          ...this.state.queryObject,\n          page: 1,\n          content: value,\n        },\n      },\n      this.reloadData\n    );\n  };\n\n  public handleChange = (pagination, filters, sorter) => {\n    // 条件过滤请求在这里处理\n    const sorterObject: { [key: string]: any } = {};\n    // 排序\n    if (sorter.field && sorter.order) {\n      sorterObject.sortTerm = sorter.field;\n      sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n    }\n    if (!sorter.order) {\n      delete sorterObject.sortTerm;\n      delete sorterObject.orderByDesc;\n    }\n    this.setState(\n      {\n        queryObject: {\n          ...sorterObject,\n          content: this.state.queryObject.content,\n          page: pagination.current,\n          size: pagination.pageSize,\n        },\n      },\n      this.reloadData\n    );\n  };\n\n  public render() {\n    const { tableData, loading, paginationProps } = this.state;\n    const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n    return (\n      <>\n        <DTable\n          loading={loading}\n          rowKey=\"id\"\n          dataSource={tableData}\n          columns={getOperationColumns((this.props as any)?.setDrawerId)}\n          reloadData={this.reloadData}\n          tableHeaderSearchInput={{ submit: this.handleSubmit, placeholder: \"请输入操作内容\" }}\n          attrs={{\n            onChange: this.handleChange,\n            scroll: {\n              y: clientHeight > 500 ? clientHeight - 200 : 300,\n            },\n          }}\n          paginationProps={paginationProps}\n        />\n      </>\n    );\n  }\n\n  public defineTableWrapperClassNames = () => {\n    return \"no-padding\";\n  };\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/detail/shard.tsx",
    "content": "import React, { FC, memo, useEffect, useState } from \"react\";\nimport { getColumns } from \"./config\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { getShardDetail } from \"api/index-admin\";\nimport urlParser from \"lib/url-parser\";\nimport \"./index.less\";\ninterface propsType {\n  dataInfo: any;\n}\n\nexport const ShardList: FC<propsType> = memo(({ dataInfo }) => {\n  const { search } = urlParser();\n  const clusterName = dataInfo?.cluster || search?.cluster || \"\";\n  const indexName = dataInfo?.index || search?.index || \"\";\n  const [isLoading, setIsLoading] = useState(false);\n  const [data, setData] = useState([]);\n  const [pageSize, setPageSize] = useState(10);\n  const [tableSearch, setTableSearch] = useState(null);\n\n  const mergeCell = (data) => {\n    let start = 0;\n    let end = 0;\n    // 用来判断元素是否在一页数据中重复出现\n    let obj = {};\n    const newData = data.map((item, index) => {\n      // 根据 pageSize 大小判断合并单元格数，避免出现，分页多合并单元格的情况\n      // 每达到一页数据，更新初始值\n      if (index % pageSize === 0) {\n        start = end;\n        end += pageSize;\n        obj = {};\n      }\n      // 截取这一页的数据\n      const pageData = data.slice(start, end);\n      const newItem = {\n        // 判断是否是当前页第一次出现，合并相同单元格，否则不展示\n        rowSpan: !obj[item.node] ? pageData?.filter((i) => item.node === i.node).length : 0,\n        ...item,\n      };\n      // 记录已经出现过的单元格\n      obj[item.node] = true;\n      return newItem;\n    });\n    return newData;\n  };\n\n  const getData = () => {\n    // 查询项的key 要与 数据源的key  对应\n    const filterData = tableSearch\n      ? data.filter((d) => {\n          let flag = false;\n          Object.keys(d).forEach((item) => {\n            if (typeof item === \"string\" || typeof item === \"number\") {\n              if ((d[item] + \"\").toLowerCase().includes((tableSearch + \"\") as string)) {\n                flag = true;\n                return;\n              }\n            }\n          });\n          return flag;\n        })\n      : data;\n    return mergeCell(filterData);\n  };\n\n  const getAsyncData = async () => {\n    setIsLoading(true);\n    try {\n      const res = await getShardDetail(clusterName, indexName);\n      if (!res) {\n        return;\n      }\n      // 对数组中相同 ip 的元素进行聚合，相加\n      for (let i = 0; i < res.length; i++) {\n        let temp = res[i];\n        temp.totalDocs = temp.docs || 0;\n        temp.totalStore = temp.storeInByte || 0;\n        temp.shardCount = 1;\n        temp.shardCells = [\n          {\n            node: temp.node,\n            shard: temp.shard,\n            docs: temp.docs,\n            storeInByte: temp.storeInByte,\n          },\n        ];\n        for (let j = i + 1; j < res.length; j++) {\n          if (temp.ip === res[j].ip) {\n            temp.totalDocs += res[j].docs || 0;\n            temp.totalStore += res[j].storeInByte || 0;\n            temp.shardCount++;\n            temp.shardCells.push({\n              node: res[j].node,\n              shard: res[j].shard,\n              docs: res[j].docs,\n              storeInByte: res[j].storeInByte,\n            });\n            res.splice(j, 1);\n            j--;\n          }\n        }\n      }\n      const data = [];\n      let i = 0;\n      res.forEach((item) => {\n        data.push(...item.shardCells.map((cell) => ({ ...item, ...cell, key: i++ })));\n      });\n      setData(data);\n    } catch (error) {\n      console.log(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const reloadData = () => {\n    getAsyncData();\n  };\n\n  const pageChange = (pagination) => {\n    if (pagination.pageSize === pageSize) {\n      return;\n    }\n    setPageSize(pagination.pageSize);\n  };\n  const tableSubmit = (value) => {\n    value = (value + \"\")?.trim().toLowerCase();\n    setTableSearch(value);\n    // if (value === this.state.queryObject.content) return;\n    // this.setState(\n    //   {\n    //     queryObject: {\n    //       ...this.state.queryObject,\n    //       page: 1,\n    //       content: value,\n    //     },\n    //   },\n    //   reloadData\n    // );\n  };\n\n  useEffect(() => {\n    getAsyncData();\n  }, []);\n\n  return (\n    <>\n      <div className=\"table-content\">\n        <DTable\n          loading={isLoading}\n          rowKey=\"key\"\n          dataSource={getData()}\n          attrs={{\n            bordered: true,\n            onChange: pageChange,\n          }}\n          tableHeaderSearchInput={{ submit: tableSubmit }}\n          paginationProps={{\n            position: \"bottomRight\",\n            showQuickJumper: true,\n            showSizeChanger: true,\n            pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n            showTotal: (total) => `共 ${total} 条`,\n          }}\n          reloadData={reloadData}\n          columns={getColumns()}\n        />\n      </div>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/edit/baseInfo.tsx",
    "content": "import * as React from \"react\";\nimport { XForm as XFormComponent, IFormItem } from \"component/x-form\";\nimport { getStepOneFormMap } from \"../create/config\";\nimport Url from \"lib/url-parser\";\nimport { CancelActionModal } from \"container/custom-component\";\nimport { Button, Spin } from \"antd\";\nimport { getIndexBaseInfo, updateIndexInfo, getTimeFormat, getIndexDataType } from \"api/cluster-index-api\";\nimport { dropByCacheKey } from \"react-router-cache-route\";\nimport { XNotification } from \"component/x-notification\";\n\nexport class EditBaseInfo extends React.Component<any> {\n  public state = {\n    formData: {} as any,\n    loading: false,\n    timeFormatList: [],\n    dataTypeList: [],\n  };\n  private $formRef: any = null;\n  private id: number = null;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.id = Number(url.search.id);\n  }\n\n  public componentDidMount() {\n    this.setState({\n      loading: true,\n    });\n    getIndexBaseInfo(this.id)\n      .then((data = {}) => {\n        data.cyclicalRoll = data.cyclicalRoll ? \"more\" : \"one\";\n        data.clusterInfo = {\n          cluster: data.cluster,\n          clusterName: data.cluster,\n          clusterType: data.clusterType,\n        };\n        data.type = data.clusterType;\n        data.clusterName = data.cluster;\n        this.setState({\n          formData: data,\n        });\n        this.$formRef.setFieldsValue(data);\n      })\n      .finally(() => {\n        this.setState({\n          loading: false,\n        });\n      });\n    getTimeFormat().then((res = []) => {\n      this.setState({\n        timeFormatList: res,\n      });\n    });\n    getIndexDataType().then((res = {}) => {\n      const dataTypeList = Object.keys(res).map((key) => {\n        return {\n          title: res[key],\n          label: res[key],\n          value: Number(key),\n        };\n      });\n      this.setState({ dataTypeList });\n    });\n  }\n\n  public componentWillUnmount() {\n    this.$formRef = null;\n  }\n\n  public onSave = () => {\n    this.$formRef.validateFields().then((result) => {\n      const formData = {\n        id: this.id,\n        desc: result.desc,\n        dataType: result.dataType,\n        expireTime: result.expireTime,\n      };\n      updateIndexInfo(formData).then(() => {\n        XNotification({ type: \"success\", message: \"更新成功\" });\n        dropByCacheKey(\"menu.es.index-tpl.management\");\n        this.clearStore([\"/es/index-tpl/management/modify\"]);\n        this.props?.history.push(\"/index-tpl/management\");\n      });\n    });\n  };\n\n  public getFormMap = (): IFormItem[] => {\n    const { formData, timeFormatList, dataTypeList } = this.state;\n    const cyclicalRoll = formData.cyclicalRoll;\n    return getStepOneFormMap(cyclicalRoll, true, this.$formRef, timeFormatList, dataTypeList);\n  };\n\n  public clearStore = (str) => {\n    this.props?.setRemovePaths([str]);\n    // 修改已不在缓存列，取消缓存\n    // dropByCacheKey(\"menu.es.index-tpl.modify\");\n  };\n\n  public render() {\n    const { loading, formData } = this.state;\n    return (\n      <>\n        <Spin spinning={loading}>\n          <div className=\"content-wrapper edit\">\n            <XFormComponent wrappedComponentRef={(formRef) => (this.$formRef = formRef)} formData={formData} formMap={this.getFormMap()} />\n            <div className=\"op-btn-group\">\n              <Button type=\"primary\" onClick={this.onSave}>\n                确定\n              </Button>\n              <CancelActionModal routeHref={\"/index-tpl/management\"} history={this.props?.history} cb={this.clearStore} />\n            </div>\n          </div>\n        </Spin>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/edit/jsonMapping.tsx",
    "content": "import * as React from \"react\";\nimport { mappingFormatJsonStr } from \"lib/utils\";\nimport Url from \"lib/url-parser\";\nimport { getIndexBaseInfo, updateIndexMappingInfo, getIndexMappingInfo } from \"api/cluster-index-api\";\nimport { PageHeader, Button, message } from \"antd\";\nimport { CancelActionModal } from \"container/custom-component\";\nimport { InfoItem } from \"component/info-item\";\nimport \"../create/index.less\";\nimport { JsonEditorWrapper } from \"component/jsonEditorWrapper\";\n\nexport class JsonMapping extends React.Component<any> {\n  private isModifyPage: boolean = true;\n  private isDetailPage: boolean = false;\n  private indexId: number = null;\n  private history: string = null;\n  static defaultProps: { isShowPlaceholder: boolean } = { isShowPlaceholder: true };\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.indexId = Number(url.search.id);\n    this.history = unescape(url.search.history);\n    this.isModifyPage = window.location.pathname.includes(\"modify/mapping\");\n    this.isDetailPage = window.location.pathname.includes(\"/detail\");\n  }\n\n  public state = {\n    pageLoading: true,\n    btnLoading: false,\n    disabled: false,\n    indexBaseInfo: {} as any,\n    activeInstance: null,\n    mapping: \"\",\n  };\n\n  public componentDidMount() {\n    getIndexMappingInfo(this.indexId)\n      .then((res) => {\n        const data = res?.typeProperties?.[0];\n        this.setState({ mapping: mappingFormatJsonStr(data?.properties, data?.[\"dynamic_templates\"]) });\n      })\n      .finally(() => {\n        this.setState({ pageLoading: false });\n      });\n    if (this.isModifyPage) {\n      getIndexBaseInfo(this.indexId).then((info = {}) => {\n        this.setState({\n          indexBaseInfo: info,\n        });\n      });\n    }\n  }\n\n  public componentWillUnmount() {\n    this.setState = () => {\n      return;\n    };\n  }\n\n  public onSave = () => {\n    try {\n      const editor = this.state.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      const params = {\n        logicId: this.indexId,\n        typeProperties: [\n          {\n            properties: jsonValue,\n          },\n        ],\n      };\n      this.updataBtnLoading(true);\n      updateIndexMappingInfo(params)\n        .then(() => {\n          message.success(\"编辑成功\");\n          this.clearStore([\"/es/index-tpl/management/modify/mapping\"]);\n          setTimeout(() => {\n            this.props?.history?.push(this.history.replace(\"/es\", \"\"));\n          }, 100);\n        })\n        .finally(() => {\n          this.updataBtnLoading(false);\n        });\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public updataBtnLoading = (b: boolean) => {\n    this.setState({\n      btnLoading: b,\n    });\n  };\n\n  // 关闭页面跳转\n  public clearStore = (str) => {\n    this.props?.setRemovePaths([str]);\n  };\n\n  setValid = (valid: boolean) => {\n    this.setState({\n      disabled: !valid,\n    });\n  };\n\n  public render() {\n    const { pageLoading, mapping } = this.state;\n\n    return (\n      <div id=\"mappingName\">\n        {this.isModifyPage ? (\n          <PageHeader className=\"detail-header\" backIcon={false}>\n            {[\n              {\n                label: \"模板名称\",\n                key: \"name\",\n              },\n              {\n                label: \"所属集群\",\n                key: \"cluster\",\n              },\n            ].map((row, index) => (\n              <InfoItem key={index} label={row.label} value={`${this.state.indexBaseInfo?.[row.key] || \"-\"}`} width={250} />\n            ))}\n          </PageHeader>\n        ) : null}\n\n        <div className={this.isModifyPage ? \"content-wrapper\" : \"\"}>\n          <JsonEditorWrapper\n            isNeedAutoIndent={!this.isDetailPage}\n            wrapperClassName={this.isDetailPage ? \"detail\" : \"\"}\n            data={mapping}\n            title={\"Mapping编辑器\"}\n            loading={pageLoading}\n            docType=\"mapping\"\n            isNeedHeader={!this.isDetailPage}\n            setEditorInstance={(editor) => {\n              this.setState({\n                activeInstance: editor,\n              });\n            }}\n            setValid={this.setValid}\n            jsonClassName={this.isDetailPage ? \"tpl-detail-mapping\" : \"tpl-edit-mapping\"}\n            readOnly={this.isDetailPage}\n          />\n          {this.isModifyPage && (\n            <div className=\"op-btns-group\">\n              <Button disabled={this.state.disabled} loading={this.state.btnLoading} type=\"primary\" onClick={this.onSave}>\n                确定\n              </Button>\n              <CancelActionModal routeHref={this.history} history={this.props.history} cb={this.clearStore} />\n            </div>\n          )}\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/edit/jsonSetting.tsx",
    "content": "import * as React from \"react\";\nimport Url from \"lib/url-parser\";\nimport { Button, PageHeader, message } from \"antd\";\nimport { getIndexBaseInfo, getSetting, updateIndexSettingInfo } from \"api/cluster-index-api\";\nimport { CancelActionModal } from \"container/custom-component\";\nimport { InfoItem } from \"component/info-item\";\nimport { getFormatJsonStr } from \"lib/utils\";\nimport \"../create/index.less\";\nimport { JsonEditorWrapper } from \"component/jsonEditorWrapper\";\n\nexport class JsonSetting extends React.Component<any> {\n  private isModifyPage: boolean = true;\n  private isDetailPage: boolean = false;\n  private indexId: number = null;\n  private history: string = null;\n  static defaultProps: { isShowPlaceholder: boolean } = { isShowPlaceholder: true };\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.indexId = Number(url.search.id);\n    this.history = unescape(url.search.history);\n    this.isModifyPage = window.location.pathname.includes(\"modify/setting\");\n    this.isDetailPage = window.location.pathname.includes(\"/detail\");\n  }\n\n  public state = {\n    pageLoading: true,\n    btnLoading: false,\n    disabled: false,\n    indexBaseInfo: {} as any,\n    activeInstance: null,\n    setting: \"\",\n  };\n\n  public componentDidMount() {\n    getSetting(this.indexId)\n      .then((res) => {\n        this.setState({ setting: getFormatJsonStr(res?.settings) });\n      })\n      .finally(() => {\n        this.setState({ pageLoading: false });\n      });\n    if (this.isModifyPage) {\n      getIndexBaseInfo(this.indexId).then((info = {}) => {\n        this.setState({\n          indexBaseInfo: info,\n        });\n      });\n    }\n  }\n\n  public componentWillUnmount() {\n    this.setState = () => {\n      return;\n    };\n  }\n\n  public onSave = () => {\n    try {\n      const editor = this.state.activeInstance;\n      const value = editor ? editor.getValue() : \"\";\n      let jsonValue = {};\n      if (value) {\n        jsonValue = JSON.parse(value || \"null\");\n      }\n      const params = {\n        logicId: this.indexId,\n        params: value ? JSON.parse(value) : {},\n      };\n      this.updataBtnLoading(true);\n      updateIndexSettingInfo(params)\n        .then(() => {\n          message.success(\"编辑成功\");\n          this.clearStore(\"/es/index-tpl/management/modify/setting\");\n          setTimeout(() => {\n            this.props?.history?.push(this.history.replace(\"/es\", \"\"));\n          }, 100);\n        })\n        .finally(() => {\n          this.updataBtnLoading(false);\n        });\n    } catch {\n      message.error(\"JSON格式有误\");\n    }\n  };\n\n  public updataBtnLoading = (b: boolean) => {\n    this.setState({\n      btnLoading: b,\n    });\n  };\n\n  // 关闭页面跳转\n  public clearStore = (str) => {\n    this.props?.setRemovePaths([str]);\n  };\n\n  setValid = (valid: boolean) => {\n    this.setState({\n      disabled: !valid,\n    });\n  };\n\n  public render() {\n    const { pageLoading, setting } = this.state;\n\n    return (\n      <div id=\"settingName\">\n        {this.isModifyPage ? (\n          <PageHeader className=\"detail-header\" backIcon={false}>\n            {[\n              {\n                label: \"模板名称\",\n                key: \"name\",\n              },\n              {\n                label: \"所属集群\",\n                key: \"cluster\",\n              },\n            ].map((row, index) => (\n              <InfoItem key={index} label={row.label} value={`${this.state.indexBaseInfo?.[row.key] || \"-\"}`} width={250} />\n            ))}\n          </PageHeader>\n        ) : null}\n\n        <div className={this.isModifyPage ? \"content-wrapper\" : \"\"}>\n          <JsonEditorWrapper\n            wrapperClassName={this.isDetailPage ? \"detail\" : \"\"}\n            data={setting}\n            isNeedAutoIndent={!this.isDetailPage}\n            title={\"Setting编辑器\"}\n            loading={pageLoading}\n            docType=\"setting\"\n            isNeedHeader={!this.isDetailPage}\n            setEditorInstance={(editor) => {\n              this.setState({\n                activeInstance: editor,\n              });\n            }}\n            isShowMappingTip={false}\n            setValid={this.setValid}\n            jsonClassName={this.isDetailPage ? \"tpl-detail-mapping\" : \"tpl-edit-mapping\"}\n            readOnly={this.isDetailPage}\n          />\n          {this.isModifyPage && (\n            <div className=\"op-btns-group\">\n              <Button loading={this.state.btnLoading} disabled={this.state.disabled} type=\"primary\" onClick={this.onSave}>\n                确定\n              </Button>\n              <CancelActionModal routeHref={this.history} history={this.props.history} cb={this.clearStore} />\n            </div>\n          )}\n        </div>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/index.tsx",
    "content": "export * from \"./management\";\nexport * from \"./service\";\nexport * from \"./detail\";\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/management/config.tsx",
    "content": "import { IColumnsType } from \"component/dantd/query-form/QueryForm\";\nimport { ITemplateLogic } from \"typesPath/cluster/physics-type\";\nimport { IIndex } from \"typesPath/index-types\";\nimport { deleteIndexInfo } from \"api/cluster-index-api\";\nimport { Modal, Tooltip, message } from \"antd\";\nimport { ITableBtn } from \"component/dantd/dtable\";\nimport { FormItemType } from \"component/x-form\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { NavRouterLink, renderOperationBtns } from \"container/custom-component\";\nimport React from \"react\";\nimport { isOpenUp, LEVEL_MAP } from \"constants/common\";\nimport { transTimeFormat } from \"lib/utils\";\nimport { TempletPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { XNotification } from \"component/x-notification\";\nimport { QuestionCircleOutlined } from \"@ant-design/icons\";\nimport { IWorkOrder } from \"@types/params-types\";\nimport { submitWorkOrder } from \"api/common-api\";\nimport store from \"store\";\n\nconst appInfo = {\n  app: store.getState().app.appInfo,\n  user: store.getState().user.getName,\n};\n\nconst renderText = (text) => {\n  return <div className=\"dsl-overflow-auto\">{text}</div>;\n};\n\nexport const columnsRender = (item: string) => {\n  return (\n    <Tooltip placement=\"right\" title={renderText(item)}>\n      <div\n        className=\"row-ellipsis pointer\"\n        style={{\n          maxWidth: \"100%\",\n          display: \"inline-block\",\n        }}\n      >\n        {item || (typeof item === \"number\" ? item : \"-\")}\n      </div>\n    </Tooltip>\n  );\n};\n\nexport const getQueryFormConfig = (cluster: any, dataTypeList = []) => {\n  return [\n    {\n      dataIndex: \"id\",\n      title: \"模板ID\",\n      type: \"input\",\n      placeholder: \"请输入模板ID\",\n      componentProps: {\n        autoComplete: \"off\",\n      },\n      rules: [\n        {\n          required: false,\n          validator: (rule: any, value: string) => {\n            if (value && !new RegExp(regNonnegativeInteger).test(value)) {\n              return Promise.reject(\"请输入数字\");\n            }\n            if (value?.length > 16) {\n              return Promise.reject(new Error(\"请输入正确ID，0-16位字符\"));\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      dataIndex: \"name\",\n      title: \"模板名称\",\n      type: \"input\",\n      placeholder: \"请输入模板名称\",\n      rules: [\n        {\n          required: false,\n          validator: async (rule: any, value: string) => {\n            if (value && value.length > 128) {\n              return Promise.reject(\"最大限制128字符\");\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      dataIndex: \"dataType\",\n      title: \"模板类型\",\n      type: FormItemType.select,\n      options: dataTypeList,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"cluster\",\n      title: \"所属集群\",\n      type: FormItemType.select,\n      options: cluster.map((item) => ({\n        title: item.v2,\n        value: item.v1,\n      })),\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"desc\",\n      title: \"模板描述\",\n      type: \"input\",\n      placeholder: \"请输入模板描述\",\n      componentProps: {\n        autoComplete: \"off\",\n      },\n    },\n  ] as IColumnsType[];\n};\n\nexport const getLogicIndexColumns = (\n  dataTypeList = [],\n  setDrawerId: any,\n  reloadData: any,\n  pushHistory?: (url: string) => void,\n  history?: any\n) => {\n  return [\n    {\n      title: \"模板ID\",\n      dataIndex: \"id\",\n      width: 80,\n      fixed: \"left\",\n    },\n    {\n      title: \"模板名称\",\n      dataIndex: \"name\",\n      width: 180,\n      lineClampOne: true,\n      render: (text: string, record: IIndex) => {\n        const href = `/index-tpl/management/detail?index=${text}&id=${record.id}&authType=${record.authType}`;\n        return <NavRouterLink needToolTip={true} element={text} href={href} />;\n      },\n    },\n    {\n      title: \"业务等级\",\n      dataIndex: \"level\",\n      width: 120,\n      sorter: true,\n      render: (text) => LEVEL_MAP[Number(text) - 1]?.label || \"-\",\n    },\n    {\n      title: \"模板类型\",\n      dataIndex: \"dataType\",\n      width: 140,\n      render: (val: number) => dataTypeList.find((item) => item.value === val)?.label || \"未知\",\n    },\n    {\n      title: \"所属集群\",\n      dataIndex: \"cluster\",\n      width: 180,\n      render: (item) => columnsRender(item),\n    },\n    {\n      title: \"模板描述\",\n      dataIndex: \"desc\",\n      width: 160,\n      render: (item) => columnsRender(item),\n    },\n    {\n      title: \"创建时间\",\n      dataIndex: \"createTime\",\n      width: 160,\n      render: (time) => transTimeFormat(time),\n    },\n    {\n      title: \"读\",\n      width: 60,\n      dataIndex: \"blockRead\",\n      sorter: true,\n      render: (item) => (item ? \"禁用\" : \"启用\"),\n    },\n    {\n      title: \"写\",\n      width: 60,\n      dataIndex: \"blockWrite\",\n      sorter: true,\n      render: (item) => (item ? \"禁用\" : \"启用\"),\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      width: 220,\n      fixed: \"right\",\n      render: (text: number, record: ITemplateLogic) => {\n        const btns = getBtnLogicIndexList(record, setDrawerId, reloadData, pushHistory, history, dataTypeList);\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n};\n\nexport const getBtnLogicIndexList = (\n  record: ITemplateLogic,\n  setDrawerId,\n  reloadData,\n  pushHistory: (url: string) => void,\n  history,\n  dataTypeList\n): ITableBtn[] => {\n  // 是否为系统数据\n  const isSystemData = record.dataType === 0;\n  const currentIsOpenUp = isSystemData && isOpenUp;\n\n  const btns: any[] = [\n    {\n      label: \"编辑\",\n      isOpenUp: currentIsOpenUp,\n      tip: isSystemData ? \"预置系统数据，不支持操作\" : \"\",\n      invisible: !hasOpPermission(TempletPermissions.PAGE, TempletPermissions.EDIT),\n      clickFunc: () => {\n        setDrawerId(\"editTemplate\", { record, dataTypeList }, reloadData);\n      },\n    },\n    {\n      label: \"编辑Mapping\",\n      isOpenUp: currentIsOpenUp || !record.isPartition,\n      tip: currentIsOpenUp ? \"预置系统数据，不支持操作\" : !record.isPartition ? \"非分区模板禁止编辑Mapping\" : \"\",\n      invisible: !hasOpPermission(TempletPermissions.PAGE, TempletPermissions.EDIT_MAPPING),\n      clickFunc: () => {\n        const href = `/index-tpl/management/modify/mapping?id=${record.id}&history=${\"/index-tpl/management\"}`;\n        pushHistory(href);\n      },\n    },\n    {\n      label: \"编辑Setting\",\n      isOpenUp: currentIsOpenUp,\n      tip: isSystemData ? \"预置系统数据，不支持操作\" : \"\",\n      invisible: !hasOpPermission(TempletPermissions.PAGE, TempletPermissions.EDIT_SETTING),\n      clickFunc: () => {\n        const href = `/index-tpl/management/modify/setting?id=${record.id}&history=${\"/index-tpl/management\"}`;\n        pushHistory(href);\n      },\n    },\n    {\n      label: !record.blockRead ? \"禁用读\" : \"启用读\",\n      isOpenUp: currentIsOpenUp,\n      clickFunc: () => {\n        Modal.confirm({\n          icon: <QuestionCircleOutlined />,\n          content: `确定${record.blockRead ? \"启用\" : \"禁用\"}模版 ${record.name} 的读操作？`,\n          okText: \"确认\",\n          cancelText: \"取消\",\n          onOk: async () => {\n            const contentObj = {\n              templateId: record.id,\n              name: record.name,\n              status: Number(!record.blockRead),\n              operator: appInfo.user(\"userName\") || \"\",\n              projectId: appInfo.app()?.id,\n            };\n            const params: IWorkOrder = {\n              contentObj,\n              submitorProjectId: appInfo.app()?.id,\n              submitor: appInfo.user(\"userName\") || \"\",\n              description: \"\",\n              type: \"templateLogicBlockRead\",\n            };\n            return submitWorkOrder(params, history, reloadData);\n          },\n        });\n      },\n    },\n    {\n      label: !record.blockWrite ? \"禁用写\" : \"启用写\",\n      isOpenUp: currentIsOpenUp,\n      clickFunc: () => {\n        Modal.confirm({\n          icon: <QuestionCircleOutlined />,\n          content: `确定${record.blockWrite ? \"启用\" : \"禁用\"}模版 ${record.name} 的写操作？`,\n          okText: \"确认\",\n          cancelText: \"取消\",\n          onOk: async () => {\n            const contentObj = {\n              templateId: record.id,\n              name: record.name,\n              status: Number(!record.blockWrite),\n              operator: appInfo.user(\"userName\") || \"\",\n              projectId: appInfo.app()?.id,\n            };\n            const params: IWorkOrder = {\n              contentObj,\n              submitorProjectId: appInfo.app()?.id,\n              submitor: appInfo.user(\"userName\") || \"\",\n              description: \"\",\n              type: \"templateLogicBlockWrite\",\n            };\n            return submitWorkOrder(params, history, reloadData);\n          },\n        });\n      },\n    },\n    {\n      label: \"下线\",\n      isOpenUp: currentIsOpenUp,\n      tip: isSystemData ? \"预置系统数据，不支持操作\" : \"\",\n      invisible: !hasOpPermission(TempletPermissions.PAGE, TempletPermissions.OFFLINE),\n      clickFunc: () => {\n        Modal.confirm({\n          title: \"提示\",\n          content: `索引模板 ${record.name}（${record.id}）下线后数据无法恢复，请确认影响后继续`,\n          width: 500,\n          okText: \"确定\",\n          cancelText: \"取消\",\n          onOk() {\n            deleteIndexInfo(record.id).then((res) => {\n              XNotification({ type: \"success\", message: `下线模板${record.name}（${record.id}）成功` });\n              reloadData();\n            });\n          },\n        });\n      },\n    },\n  ];\n\n  return btns;\n};\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/management/constants.ts",
    "content": "export const LOGIC_INDEX_TITLE = {\n  title: \"模板管理\",\n  content: \"\",\n};\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/management/index.less",
    "content": ".template-name-cell {\n  color: @primary-color;\n  word-break: break-all;\n}\n.temp-spin-name{\n  margin-top: 30%;\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/management/index.tsx",
    "content": "import { getAllIndexList, IAllIndexList, getClusterPerApp, getIndexDataType } from \"api/cluster-index-api\";\nimport { RenderTitle } from \"component/render-title\";\nimport React, { useState } from \"react\";\nimport { getLogicIndexColumns, getQueryFormConfig } from \"./config\";\nimport { LOGIC_INDEX_TITLE } from \"./constants\";\nimport { connect } from \"react-redux\";\nimport { NavRouterLink } from \"container/custom-component\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { ProTable, Button, Spin } from \"knowdesign\";\nimport { initPaginationProps } from \"constants/table\";\nimport { TempletPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { RenderEmpty } from \"component/LogClusterEmpty\";\nimport \"./index.less\";\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n  setDrawerId: (drawerId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(drawerId, params, cb)),\n});\n\nexport const IndexTplManagement = connect(\n  null,\n  mapDispatchToProps\n)((props: { setModalId: Function; setDrawerId: Function; history: any }) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject]: any = useState({\n    page: 1,\n    size: 10,\n  });\n  const [tableData, setTableData] = useState([]);\n  const [paginationProps, setPaginationProps] = useState(initPaginationProps());\n  const [cluster, setCluster] = useState([]);\n  const [dataTypeList, setDataTypeList] = useState([]);\n  const [pageLoad, setPageLoad] = useState(false);\n  const [sorter, setSorter] = useState({});\n\n  React.useEffect(() => {\n    reloadData();\n  }, [department, queryFormObject]);\n\n  React.useEffect(() => {\n    // 逻辑集群\n    setPageLoad(true);\n    getClusterPerApp()\n      .then((res = []) => {\n        setCluster(res);\n      })\n      .finally(() => {\n        setPageLoad(false);\n      });\n  }, [department]);\n\n  React.useEffect(() => {\n    getIndexDataType().then((res = {}) => {\n      const dataTypeList = Object.keys(res).map((key) => {\n        return {\n          title: res[key],\n          label: res[key],\n          value: Number(key),\n        };\n      });\n      setDataTypeList(dataTypeList);\n    });\n  }, []);\n\n  const handleSubmit = (result) => {\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject({ ...result, ...sorter, page: 1, size: paginationProps.pageSize });\n  };\n\n  const reloadData = () => {\n    setloading(true);\n    const Params: IAllIndexList = {\n      page: queryFormObject.page,\n      size: queryFormObject.size,\n      id: queryFormObject.id !== undefined ? +queryFormObject.id : undefined,\n      name: queryFormObject.name,\n      dataType: queryFormObject.dataType,\n      desc: queryFormObject.desc,\n      resourceId: queryFormObject.cluster,\n      sortTerm: queryFormObject.sortTerm,\n      orderByDesc: queryFormObject.orderByDesc,\n    };\n    getAllIndexList(Params)\n      .then((res) => {\n        if (res) {\n          setTableData(res?.bizData);\n          const { pageNo = 1, pageSize = 10 } = res.pagination;\n          setPaginationProps({\n            ...paginationProps,\n            total: res?.pagination?.total,\n            current: pageNo,\n            pageSize: pageSize,\n          });\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const getOpBtns = () => {\n    return (\n      <>\n        {hasOpPermission(TempletPermissions.PAGE, TempletPermissions.APPLY) ? (\n          <Button type=\"primary\" onClick={() => props.setDrawerId(\"createTemplate\", { dataTypeList }, reloadData)}>\n            新建模板\n          </Button>\n        ) : (\n          \"\"\n        )}\n      </>\n    );\n  };\n\n  const pushHistory = (url) => {\n    props.history.push(url);\n  };\n\n  const handleChange = (pagination, filters, sorter) => {\n    // 条件过滤请求在这里处理\n    const sorterObject: { [key: string]: any } = {};\n    // 排序\n    if (sorter.field && sorter.order) {\n      switch (sorter.field) {\n        case \"blockRead\":\n          sorterObject.sortTerm = \"block_read\";\n          break;\n        case \"blockWrite\":\n          sorterObject.sortTerm = \"block_write\";\n          break;\n        default:\n          sorterObject.sortTerm = sorter.field;\n          break;\n      }\n      sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n    }\n    setSorter(sorterObject);\n    setqueryFormObject((state) => {\n      if (!sorter.order) {\n        delete state.sortTerm;\n        delete state.orderByDesc;\n      }\n      return {\n        ...state,\n        ...sorterObject,\n        page: pagination.current,\n        size: pagination.pageSize,\n      };\n    });\n  };\n\n  const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n  const renderNode = () => {\n    return (\n      <>\n        <div className=\"table-layout-style\">\n          <ProTable\n            showQueryForm={true}\n            queryFormProps={{\n              // layout: \"inline\",\n              // colMode: \"style\",\n              totalNumber: paginationProps?.total,\n              defaultCollapse: true,\n              columns: getQueryFormConfig(cluster, dataTypeList),\n              onReset: handleSubmit,\n              onSearch: handleSubmit,\n              isResetClearAll: true,\n            }}\n            tableProps={{\n              tableId: \"template_manage_list\",\n              isCustomPg: false,\n              loading,\n              rowKey: \"id\",\n              dataSource: tableData,\n              columns: getLogicIndexColumns(dataTypeList, props.setDrawerId, reloadData, pushHistory, props.history),\n              reloadData,\n              getJsxElement: getOpBtns,\n              customRenderSearch: () => <RenderTitle {...LOGIC_INDEX_TITLE} />,\n              paginationProps,\n              attrs: {\n                onChange: handleChange,\n                scroll: {\n                  x: \"max-content\",\n                },\n              },\n            }}\n          />\n        </div>\n      </>\n    );\n  };\n\n  return (\n    <Spin className=\"temp-spin-name\" spinning={pageLoad}>\n      {cluster.length\n        ? !pageLoad && renderNode()\n        : !pageLoad && (\n            <div>\n              <RenderEmpty {...props} />\n            </div>\n          )}\n    </Spin>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/service/config.tsx",
    "content": "import { IColumnsType } from \"component/dantd/query-form/QueryForm\";\nimport { ITemplateLogic } from \"typesPath/cluster/physics-type\";\nimport { IIndex } from \"typesPath/index-types\";\nimport { message } from \"antd\";\nimport { Modal, Tooltip, Switch, Tag } from \"knowdesign\";\nimport { ITableBtn } from \"component/dantd/dtable\";\nimport { FormItemType } from \"component/x-form\";\nimport { CodeType, isOpenUp, CONFIRM_BUTTON_TEXT } from \"constants/common\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { NavRouterLink, renderOperationBtns } from \"container/custom-component\";\nimport React from \"react\";\nimport { disableRead, disableWrite, updateTemplateSrv, updateVision } from \"api/cluster-index-api\";\nimport { columnsRender } from \"../management/config\";\nimport { XNotification } from \"component/x-notification\";\nimport { FilterModal } from \"./filterModal\";\nimport { InfoCircleFilled } from \"@ant-design/icons\";\n\nconst statusTag = (item) => {\n  switch (item) {\n    case 2:\n      return <Tag color=\"error\">Red</Tag>;\n    case 1:\n      return <Tag color=\"warning\">Yellow</Tag>;\n    case 0:\n      return <Tag color=\"success\">Green</Tag>;\n    case -1:\n      return <Tag className=\"ant-tag-dark\">Unknown</Tag>;\n    default:\n      return \"-\";\n  }\n};\n\nconst healthList = [\n  {\n    title: \"green\",\n    value: \"0\",\n  },\n  {\n    title: \"yellow\",\n    value: \"1\",\n  },\n  {\n    title: \"red\",\n    value: \"2\",\n  },\n  {\n    title: \"unknown\",\n    value: \"-1\",\n  },\n];\n\nexport const getQueryFormConfig = (cluster: any, projectList: any) => {\n  return [\n    {\n      dataIndex: \"id\",\n      title: \"模板ID:\",\n      type: \"input\",\n      placeholder: \"请输入模板ID\",\n      componentProps: {\n        autoComplete: \"off\",\n      },\n      rules: [\n        {\n          required: false,\n          validator: (rule: any, value: string) => {\n            if (value && !new RegExp(regNonnegativeInteger).test(value)) {\n              return Promise.reject(\"请输入数字\");\n            }\n            if (value?.length > 16) {\n              return Promise.reject(new Error(\"请输入正确ID，0-16位字符\"));\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      dataIndex: \"name\",\n      title: \"模板名称:\",\n      type: \"input\",\n      placeholder: \"请输入模板名称\",\n      rules: [\n        {\n          required: false,\n          validator: async (rule: any, value: string) => {\n            if (value && value.length > 128) {\n              return Promise.reject(\"最大限制128字符\");\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      type: \"select\",\n      title: \"健康状态:\",\n      dataIndex: \"health\",\n      options: healthList,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"projectId\",\n      title: \"所属应用:\",\n      type: FormItemType.select,\n      options: projectList.map((item) => ({\n        title: item.projectName,\n        value: item.id,\n      })),\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"cluster\",\n      title: \"所属集群:\",\n      type: FormItemType.select,\n      options: cluster.map((item) => ({\n        title: item,\n        value: item,\n      })),\n      placeholder: \"请选择\",\n    },\n  ] as IColumnsType[];\n};\n\nexport const getServiceColumns = (setModalId: any, setDrawerId: any, reloadData: any, pushHistory?: (url: string) => void) => {\n  return [\n    {\n      title: \"模板ID\",\n      dataIndex: \"id\",\n      key: \"id\",\n      width: 80,\n      fixed: \"left\",\n    },\n    {\n      title: \"模板名称\",\n      dataIndex: \"name\",\n      key: \"name\",\n      width: 180,\n      lineClampOne: true,\n      render: (text: string, record: IIndex) => {\n        const href = `/index-tpl/service/detail?name=${text}&id=${record.id}&authType=${record.authType}`;\n        return <NavRouterLink needToolTip={true} element={text} href={href} />;\n      },\n    },\n    {\n      title: \"健康状态\",\n      dataIndex: \"health\",\n      key: \"health\",\n      width: 100,\n      sorter: true,\n      render: (item) => <div>{statusTag(item)}</div>,\n    },\n    {\n      title: \"所属应用\",\n      dataIndex: \"projectName\",\n      key: \"projectName\",\n      width: 150,\n      render: (text) => columnsRender(text),\n    },\n    {\n      title: \"所属集群\",\n      dataIndex: \"cluster\",\n      key: \"cluster\",\n      width: 180,\n      render: (text) => columnsRender(text?.join(\",\")),\n    },\n    {\n      title: \"预创建\",\n      dataIndex: \"preCreateFlags\",\n      key: \"preCreateFlags\",\n      width: 80,\n      render: (text, record) => renderSwitch(CodeType.PreCreate, record, reloadData, setModalId),\n    },\n    {\n      title: \"过期删除\",\n      dataIndex: \"overdueDelete\",\n      key: \"overdueDelete\",\n      width: 80,\n      render: (text, record) => renderSwitch(CodeType.Delete, record, reloadData, setModalId),\n    },\n    {\n      title: \"冷热分离\",\n      dataIndex: \"separate\",\n      key: \"separate\",\n      width: 140,\n      render: (text, record) => {\n        const expireTime = record.expireTime !== -1 ? `${record.expireTime || \"-\"}天` : \"永久\";\n        const hotTime =\n          record.hotTime !== -1 ? `${record.hotTime || \"-\"}` : record.expireTime !== -1 ? `${record.expireTime || \"-\"}` : \"永久\";\n        return (\n          <>\n            {renderSwitch(CodeType.Separate, record, reloadData, setModalId)}\n            <span style={{ marginLeft: \"3px\" }}>\n              {hotTime}/{expireTime}\n            </span>\n          </>\n        );\n      },\n    },\n    {\n      title: \"Pipeline\",\n      dataIndex: \"pipeline\",\n      key: \"pipeline\",\n      width: 80,\n      render: (text, record) => renderSwitch(CodeType.Pipeline, record, reloadData, setModalId),\n    },\n    {\n      title: \"Rollover\",\n      dataIndex: \"rollover\",\n      key: \"rollover\",\n      width: 80,\n      render: (text, record) => renderSwitch(CodeType.Rollover, record, reloadData, setModalId),\n    },\n    {\n      title: \"DCDR\",\n      dataIndex: \"hasDCDR\",\n      key: \"hasDCDR\",\n      filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => {\n        return <FilterModal setSelectedKeys={setSelectedKeys} selectedKeys={selectedKeys} confirm={confirm} clearFilters={clearFilters} />;\n      },\n      width: 90,\n      render: (text, record) => renderSwitch(CodeType.DCDR, record, reloadData, setModalId, setDrawerId),\n    },\n\n    {\n      title: \"主从位点差\",\n      dataIndex: \"checkPointDiff\",\n      key: \"checkPointDiff\",\n      width: 110,\n      sorter: true,\n      render: (text) => {\n        return <>{typeof text == \"number\" ? (text < 0 ? \"-\" : text) : text || \"-\"}</>;\n      },\n    },\n    {\n      title: \"读\",\n      width: 60,\n      dataIndex: \"blockRead\",\n      sorter: true,\n      render: (item) => (item ? \"禁用\" : \"启用\"),\n    },\n    {\n      title: \"写\",\n      width: 60,\n      dataIndex: \"blockWrite\",\n      sorter: true,\n      render: (item) => (item ? \"禁用\" : \"启用\"),\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      key: \"operation\",\n      width: 180,\n      fixed: \"right\",\n      render: (text: number, record: ITemplateLogic) => {\n        const btns = getBtnServiceList(record, setModalId, setDrawerId, reloadData, pushHistory);\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n};\n\nconst onClick = (code: number, status: boolean, record, reloadData, setModalId, setDrawerId?: any) => {\n  let title = null;\n  let content = null;\n  switch (code) {\n    case CodeType.PreCreate:\n      title = `确定${status ? \"关闭\" : \"开启\"}预创建能力？`;\n      break;\n    case CodeType.Delete:\n      title = `确定${status ? \"关闭\" : \"开启\"}过期删除能力？`;\n      break;\n    case CodeType.Separate:\n      title = `确定${status ? \"关闭\" : \"开启\"}冷热分离能力？`;\n      break;\n    case CodeType.Pipeline:\n      title = `确定${status ? \"关闭\" : \"开启\"}pipeline能力？`;\n      break;\n    case CodeType.Rollover:\n      title = `确定${status ? \"关闭\" : \"开启\"}Rollover能力？`;\n      if (!status) {\n        content = (\n          <>\n            <div>开启后会影响索引Update和Delete能力以及指定id写入、更新、删除</div>\n            <div>默认主分片到达50G后进行升版本，如需修改，请前往【平台配置】修改 index.rollover.threshold 值</div>\n          </>\n        );\n      }\n      break;\n    default:\n      break;\n  }\n  if (code === CodeType.Separate && !status) {\n    setModalId(\"openSeparate\", { id: record.id, expireTime: record.expireTime }, reloadData);\n    return;\n  }\n  if (code === CodeType.DCDR && !status) {\n    setModalId(\"createDCDR\", record.id, reloadData);\n    return;\n  }\n  if (code === CodeType.DCDR && status) {\n    setDrawerId(\"dcdrDetail\", record.id, reloadData);\n    return;\n  }\n  Modal.confirm({\n    ...CONFIRM_BUTTON_TEXT,\n    title,\n    content,\n    icon: <InfoCircleFilled className=\"confirm-icon\" />,\n    onOk: () => {\n      const params = {\n        srvCode: code,\n        templateIdList: [record.id],\n      };\n      updateTemplateSrv(params, status ? \"DELETE\" : \"PUT\").then(() => {\n        message.success(`操作成功`);\n        reloadData();\n      });\n    },\n  });\n};\n\nexport const renderSwitch = (code: number, record, reloadData, setModalId, setDrawerId?: any) => {\n  const unavailableInfo = record?.unavailableSrv?.find((item) => item.srvCode === code);\n  const openInfo = record?.openSrv?.find((item) => item.srvCode === code);\n  const status = openInfo ? true : false;\n  const hasDCDR = record?.hasDCDR;\n  if (unavailableInfo) {\n    return (\n      <Tooltip title={unavailableInfo.unavailableReason}>\n        {code === CodeType.DCDR ? <a style={{ color: \"#bfbfbf\" }}>创建链路</a> : <Switch size=\"small\" disabled={true} checked={false} />}\n      </Tooltip>\n    );\n  } else {\n    return code === CodeType.DCDR ? (\n      <a onClick={() => onClick(code, hasDCDR, record, reloadData, setModalId, setDrawerId)}>{hasDCDR ? \"查看链路\" : \"创建链路\"}</a>\n    ) : (\n      <Switch size=\"small\" checked={status} onClick={() => onClick(code, status, record, reloadData, setModalId)} />\n    );\n  }\n};\n\nexport const getBtnServiceList = (\n  record: ITemplateLogic,\n  setModalId,\n  setDrawerId,\n  reloadData,\n  pushHistory: (url: string) => void\n): ITableBtn[] => {\n  // 是否为系统数据\n  const isSystemData = record.dataType === 0;\n  const currentIsOpenUp = isSystemData && isOpenUp;\n\n  const btns: any[] = [\n    {\n      label: \"清理\",\n      isOpenUp: currentIsOpenUp,\n      tip: isSystemData ? \"预置系统数据，不支持操作\" : \"\",\n      clickFunc: () => {\n        setDrawerId(\"clearModal\", record.id, reloadData);\n      },\n    },\n    {\n      label: \"扩缩容\",\n      isOpenUp: currentIsOpenUp,\n      tip: isSystemData ? \"预置系统数据，不支持操作\" : \"\",\n      clickFunc: () => {\n        let errorCluster = [];\n        let errorDesc;\n        if (record?.clusterConnectionStatus) {\n          record?.clusterConnectionStatus.forEach((element) => {\n            if (element.status === \"DISCONNECTED\") {\n              errorCluster.push(element.cluster);\n              errorDesc = element.desc;\n            }\n          });\n          errorCluster.length\n            ? XNotification({\n                type: \"error\",\n                message: \"集群故障\",\n                description: `${errorCluster.join(\",\")}集群故障，请检查集群状态后重试`,\n                duration: 1000,\n              })\n            : null;\n        }\n        if (!errorCluster.length) {\n          setModalId(\"expandShrinkCapacity\", record, reloadData);\n        }\n      },\n    },\n    {\n      label: \"升版本\",\n      isOpenUp: currentIsOpenUp,\n      tip: isSystemData ? \"预置系统数据，不支持操作\" : \"\",\n      clickFunc: () => {\n        Modal.confirm({\n          ...CONFIRM_BUTTON_TEXT,\n          title: \"确定进行升版本操作？\",\n          icon: <InfoCircleFilled className=\"confirm-icon\" />,\n          content: (\n            <>\n              <div>升级后版本号自动+1。</div>\n              {record.partition ? null : <div>会影响当前模板指定id的写入、更新、删除。</div>}\n            </>\n          ),\n          onOk: () => {\n            updateVision(record.id).then(() => {\n              message.success(`升版本成功`);\n              reloadData();\n            });\n          },\n        });\n      },\n    },\n    {\n      label: !record.blockRead ? \"禁用读\" : \"启用读\",\n      isOpenUp: currentIsOpenUp,\n      clickFunc: () => {\n        Modal.confirm({\n          ...CONFIRM_BUTTON_TEXT,\n          title: `确定${record.blockRead ? \"启用\" : \"禁用\"}模版 ${record.name} 的读操作？`,\n          icon: <InfoCircleFilled className=\"confirm-icon\" />,\n          onOk: async () => {\n            disableRead(record.id, Number(!record.blockRead))\n              .then(() => {\n                message.success(\"操作成功\");\n              })\n              .catch((error) => {\n                message.error(`${record.blockRead ? \"启用\" : \"禁用\"}读失败`);\n              })\n              .finally(() => {\n                reloadData();\n              });\n          },\n        });\n      },\n    },\n    {\n      label: !record.blockWrite ? \"禁用写\" : \"启用写\",\n      isOpenUp: currentIsOpenUp,\n      clickFunc: () => {\n        Modal.confirm({\n          ...CONFIRM_BUTTON_TEXT,\n          title: `确定${record.blockWrite ? \"启用\" : \"禁用\"}模版 ${record.name} 的写操作？`,\n          icon: <InfoCircleFilled className=\"confirm-icon\" />,\n          onOk: async () => {\n            disableWrite(record.id, Number(!record.blockWrite))\n              .then(() => {\n                message.success(\"操作成功\");\n              })\n              .catch((error) => {\n                message.error(`${record.blockWrite ? \"启用\" : \"禁用\"}写失败`);\n              })\n              .finally(() => {\n                reloadData();\n              });\n          },\n        });\n      },\n    },\n  ];\n\n  return btns;\n};\n\nexport const getBatchBtnService = (setModalId, reloadData, selectedRows, switchDCDR) => {\n  return [\n    {\n      label: \"预创建\",\n      onClick: () => setModalId(\"batchUpdate\", { code: CodeType.PreCreate, datas: selectedRows }, reloadData),\n    },\n    {\n      label: \"过期删除\",\n      onClick: () => setModalId(\"batchUpdate\", { code: CodeType.Delete, datas: selectedRows }, reloadData),\n    },\n    {\n      label: \"冷热分离\",\n      onClick: () => setModalId(\"batchUpdate\", { code: CodeType.Separate, datas: selectedRows }, reloadData),\n    },\n    {\n      label: \"pipeline\",\n      onClick: () => setModalId(\"batchUpdate\", { code: CodeType.Pipeline, datas: selectedRows }, reloadData),\n    },\n    {\n      label: \"Rollover\",\n      onClick: () => setModalId(\"batchUpdate\", { code: CodeType.Rollover, datas: selectedRows }, reloadData),\n    },\n    {\n      label: \"DCDR-平滑切换\",\n      onClick: () => switchDCDR(1),\n    },\n    {\n      label: \"DCDR-强制切换\",\n      onClick: () => switchDCDR(2),\n    },\n  ];\n};\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/service/constants.ts",
    "content": "export const LOGIC_INDEX_TITLE = {\n  title: \"模板服务\",\n  content: \"\",\n};\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/service/filterModal.tsx",
    "content": "import React, { useState, useRef } from \"react\";\nimport { Button, Space, Checkbox, Col, Row } from \"antd\";\nimport \"./index.less\";\nconst filterOption = [\n  {\n    text: \"未创建\",\n    value: false,\n    key: \"openSrv\",\n  },\n  {\n    text: \"已创建\",\n    value: true,\n    key: \"hasDCDR\",\n  },\n];\nexport const FilterModal = ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => {\n  const handleSearch = (selectedKeys, confirm) => {\n    confirm();\n  };\n  const handleReset = (clearFilters) => {\n    clearFilters();\n  };\n  return (\n    <div\n      style={{\n        padding: 8,\n      }}\n    >\n      <div>DCDR链路创建情况</div>\n      <Checkbox.Group\n        style={{\n          marginBottom: 8,\n          display: \"block\",\n          width: \"100%\",\n        }}\n        value={selectedKeys}\n        onChange={(e) => {\n          setSelectedKeys(e ? e : []);\n        }}\n      >\n        {filterOption.map((item) => (\n          <div key={item.key}>\n            <Checkbox value={item.value}>{item.text}</Checkbox>\n          </div>\n        ))}\n      </Checkbox.Group>\n      <Space>\n        <Button\n          type=\"primary\"\n          onClick={() => handleSearch(selectedKeys, confirm)}\n          size=\"small\"\n          style={{\n            width: 90,\n          }}\n        >\n          确定\n        </Button>\n        <Button\n          onClick={() => clearFilters && handleReset(clearFilters)}\n          size=\"small\"\n          style={{\n            width: 90,\n          }}\n        >\n          重置\n        </Button>\n      </Space>\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/service/index.less",
    "content": ".template-name-cell {\n  color: @primary-color;\n  word-break: break-all;\n}\n\n.btn-labels-box {\n  display: flex;\n  flex-wrap: wrap;\n  justify-content: space-between;\n\n  .btn-labels {\n    display: inline-block;\n    margin-bottom: 12px;\n    margin-right: 12px;\n    padding: 2px 8px;\n    background: #ececf6;\n    border-radius: 4px;\n  }\n}\n.cluster-label {\n  .iconinfo {\n    font-size: 12px;\n    margin-left: 5px;\n    color: rgb(140, 140, 140);\n    position: relative;\n    bottom: 1px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/index-tpl-management/service/index.tsx",
    "content": "import { getServiceList, IAllIndexList, switchMasterSlave, getPhyClusterPerApp } from \"api/cluster-index-api\";\nimport { getProjectListByUserId } from \"api/app-api\";\nimport { getCookie } from \"lib/utils\";\nimport { RenderTitle } from \"component/render-title\";\nimport React, { useState } from \"react\";\nimport { getServiceColumns, getQueryFormConfig, getBatchBtnService } from \"./config\";\nimport { LOGIC_INDEX_TITLE } from \"./constants\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { AppState } from \"store/type\";\nimport { ProTable, Menu, Dropdown, Button, Modal, Tooltip } from \"knowdesign\";\nimport { InfoCircleFilled } from \"@ant-design/icons\";\nimport { isOpenUp, CodeType, CONFIRM_BUTTON_TEXT } from \"constants/common\";\nimport { initPaginationProps } from \"constants/table\";\nimport store from \"store\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state) => ({\n  app: state.app,\n});\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n  setDrawerId: (drawerId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(drawerId, params, cb)),\n});\n\nexport const IndexTplService = connect(\n  mapStateToProps,\n  mapDispatchToProps\n)((props: { setModalId: Function; setDrawerId: Function; app: AppState; history: any }) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject]: any = useState({\n    page: 1,\n    size: 10,\n  });\n  const [tableData, setTableData] = useState([]);\n  const [paginationProps, setPaginationProps] = useState(initPaginationProps());\n  const [selectedRowKeys, setSelectedRowKeys] = useState([]);\n  const [selectedRows, setSelectedRows] = useState([]);\n  const [cluster, setCluster] = useState([]);\n  const [projectList, setProjectList] = useState([]);\n  const [sorter, setSorter] = useState({});\n\n  React.useEffect(() => {\n    reloadData();\n  }, [department, queryFormObject]);\n\n  React.useEffect(() => {\n    getPhyClusterPerApp().then((res = []) => {\n      setCluster(res);\n    });\n  }, [department]);\n\n  React.useEffect(() => {\n    const projectList = props.app.projectList;\n    if (!projectList?.length) {\n      const userId = getCookie(\"userId\");\n      getProjectListByUserId(+userId).then((res = []) => {\n        setProjectList(res);\n        store.dispatch(actions.setProjectList(res));\n      });\n    } else {\n      setProjectList(projectList);\n    }\n  }, []);\n\n  const handleSubmit = (result) => {\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject({ ...result, ...sorter, page: 1, size: paginationProps.pageSize });\n  };\n\n  const reloadData = () => {\n    setloading(true);\n    const params: IAllIndexList = {\n      page: queryFormObject.page,\n      size: queryFormObject.size,\n      id: queryFormObject.id !== undefined ? +queryFormObject.id : undefined,\n      name: queryFormObject.name,\n      health: queryFormObject.health,\n      projectId: queryFormObject.projectId,\n      cluster: queryFormObject.cluster,\n      sortTerm: queryFormObject.sortTerm,\n      orderByDesc: queryFormObject.orderByDesc,\n      hasDCDR: queryFormObject.hasDCDR,\n      openSrv: queryFormObject.openSrv,\n    };\n    getServiceList(params)\n      .then((res) => {\n        if (res) {\n          setTableData(res?.bizData);\n          clearSelect();\n          const { pageNo = 1, pageSize = 10 } = res.pagination;\n          setPaginationProps({\n            ...paginationProps,\n            total: res?.pagination?.total,\n            current: pageNo,\n            pageSize: pageSize,\n          });\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const clearSelect = () => {\n    setSelectedRowKeys([]);\n    setSelectedRows([]);\n  };\n\n  const switchDCDR = (type) => {\n    const unavailableSrv = [];\n    const opend = [];\n    const closed = [];\n    selectedRows.forEach((item) => {\n      if (item.unavailableSrv?.find((srv) => srv.srvCode === CodeType.DCDR)) {\n        unavailableSrv.push({\n          name: item.name,\n          id: item.id,\n        });\n      } else if (item.hasDCDR) {\n        opend.push({\n          name: item.name,\n          id: item.id,\n        });\n      } else {\n        closed.push({\n          name: item.name,\n          id: item.id,\n        });\n      }\n    });\n    if (unavailableSrv.length === selectedRows.length) {\n      Modal.confirm({\n        ...CONFIRM_BUTTON_TEXT,\n        icon: <InfoCircleFilled className=\"confirm-icon\" />,\n        title: \"提示\",\n        content: `索引模板${\n          unavailableSrv.length > 1 ? `${unavailableSrv[0].name}等` : unavailableSrv[0].name\n        }不具备DCDR主从切换条件，无法切换。`,\n      });\n    } else if (closed.length) {\n      Modal.confirm({\n        ...CONFIRM_BUTTON_TEXT,\n        icon: <InfoCircleFilled className=\"confirm-icon\" />,\n        title: \"提示\",\n        content: (\n          <>\n            <div>{`索引模板${closed.length > 1 ? `${closed[0].name}等` : closed[0].name}未建立DCDR链路，无法进行主从切换。`}</div>\n            <div>请点击“创建链路”进行链路的创建。</div>\n          </>\n        ),\n      });\n    } else {\n      if (!opend.length) return;\n      if (type === 2) {\n        Modal.confirm({\n          ...CONFIRM_BUTTON_TEXT,\n          icon: <InfoCircleFilled className=\"confirm-icon\" />,\n          title: \"提示\",\n          content: `强制切换后，无法确保数据一致，待切换前主集群正常后会自动清理链路，且不会反向构建新链路，底层数据不会删除。`,\n          onOk: () => {\n            confirmSwitch(type, opend);\n          },\n        });\n      } else {\n        props.setModalId(\"dcdrTimeout\", { onSubmit: confirmSwitch, type, opend });\n      }\n    }\n  };\n\n  const confirmSwitch = (type, ids, timeout?: number) => {\n    switchMasterSlave({\n      type,\n      templateIds: ids.map((item) => item.id),\n      timeout,\n    }).then((res) => {\n      Modal.success({\n        ...CONFIRM_BUTTON_TEXT,\n        onOk: () => reloadData(),\n        title: \"提交成功！\",\n        content: (\n          <>\n            <div className=\"order-success\">\n              <span>{res.title}已提交！可至“任务中心”查看任务详情</span>\n              <br />\n              <span>\n                任务标题（ID）：\n                <Button\n                  type=\"link\"\n                  style={{ padding: 0 }}\n                  onClick={() => {\n                    Modal.destroyAll();\n                    props.history.push(`/work-order/task/dcdrdetail?taskid=${res.id}&title=${res.title}`);\n                  }}\n                >\n                  {res.title}（{res.id}）\n                </Button>\n              </span>\n            </div>\n          </>\n        ),\n      });\n    });\n  };\n\n  const getOpBtns = React.useCallback(() => {\n    const menu = (\n      <Menu>\n        {getBatchBtnService(props.setModalId, reloadData, selectedRows, switchDCDR).map((item) => (\n          <Menu.Item disabled={(selectedRows && selectedRows.length === 0) || isOpenUp} key={item.label} onClick={() => item.onClick()}>\n            {selectedRows && selectedRows.length === 0 ? (\n              <Tooltip title={isOpenUp ? \"该功能仅面向商业版客户开放\" : \"需选定索引模板\"}>{item.label}</Tooltip>\n            ) : (\n              item.label\n            )}\n          </Menu.Item>\n        ))}\n      </Menu>\n    );\n    return (\n      <>\n        <Dropdown overlay={menu} placement=\"bottomCenter\">\n          <Tooltip title={isOpenUp ? \"该功能仅面向商业版客户开放\" : \"\"}>\n            {selectedRows && selectedRows.length <= 0 ? (\n              \"\"\n            ) : (\n              <Button type=\"primary\" disabled={isOpenUp}>\n                批量操作\n              </Button>\n            )}\n          </Tooltip>\n        </Dropdown>\n      </>\n    );\n  }, [selectedRows]);\n\n  const pushHistory = (url) => {\n    props.history.push(url);\n  };\n\n  const handleChange = (pagination, filters, sorter) => {\n    // 条件过滤请求在这里处理\n    const sorterObject: { [key: string]: any } = {};\n    // 排序\n    if (sorter.field && sorter.order) {\n      switch (sorter.columnKey) {\n        case \"checkPointDiff\":\n          sorterObject.sortTerm = \"check_point_diff\";\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n        default:\n          sorterObject.sortTerm = sorter.field;\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n      }\n    }\n    let filterArr = filters.hasDCDR;\n    let filterObj = {} as { openSrv: number; hasDCDR: boolean };\n    (filterArr || []).forEach((item) => {\n      item ? (filterObj[\"hasDCDR\"] = true) : (filterObj[\"openSrv\"] = 10);\n    });\n\n    setSorter({ ...sorterObject, ...filterObj });\n    setqueryFormObject((state) => {\n      if (!sorter.order) {\n        delete state.sortTerm;\n        delete state.orderByDesc;\n      }\n      if (!filterObj.hasDCDR) {\n        delete state.hasDCDR;\n      }\n      if (!filterObj.openSrv) {\n        delete state.openSrv;\n      }\n      return {\n        ...state,\n        ...sorterObject,\n        ...filterObj,\n        page: pagination.current,\n        size: pagination.pageSize,\n      };\n    });\n  };\n\n  const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n  return (\n    <div className=\"table-layout-style\">\n      <ProTable\n        showQueryForm={true}\n        queryFormProps={{\n          // layout: \"inline\",\n          // colMode: \"style\",\n          totalNumber: paginationProps?.total,\n          defaultCollapse: true,\n          columns: getQueryFormConfig(cluster, projectList),\n          onReset: handleSubmit,\n          onSearch: handleSubmit,\n          isResetClearAll: true,\n        }}\n        tableProps={{\n          tableId: \"template_service_list\",\n          isCustomPg: false,\n          loading,\n          rowKey: \"id\",\n          dataSource: tableData,\n          columns: getServiceColumns(props.setModalId, props.setDrawerId, reloadData, pushHistory),\n          reloadData,\n          // isDividerHide: selectedRows?.length > 0,\n          getJsxElement: getOpBtns,\n          customRenderSearch: () => <RenderTitle {...LOGIC_INDEX_TITLE} />,\n          paginationProps,\n          attrs: {\n            onChange: handleChange,\n            rowSelection: {\n              selectedRowKeys,\n              onChange: (selectedRowKeys, selectedRows) => {\n                setSelectedRowKeys(selectedRowKeys);\n                setSelectedRows(selectedRows);\n              },\n            },\n            scroll: {\n              x: \"max-content\",\n            },\n          },\n        }}\n      />\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/cluster-kanban.tsx",
    "content": "import React, { memo, useState, useEffect, useRef } from \"react\";\nimport { useSelector, useDispatch, shallowEqual } from \"react-redux\";\nimport { setClusterForm } from \"../../../actions/cluster-kanban\";\nimport { RenderTitle } from \"component/render-title\";\nimport { oneDayMillims } from \"../../../constants/common\";\nimport { getLogicClusterNames } from \"../../../api/cluster-kanban\";\nimport { TAB_LIST, MENU_MAP, CLUSTER_KANBAN_MENU } from \"./config\";\nimport { KanbanForm, RefreshTime } from \"../components\";\nimport { HashMenu } from \"knowdesign\";\nimport Url from \"lib/url-parser\";\nimport { Spin } from \"knowdesign\";\nimport \"../style\";\nimport { isSuperApp } from \"lib/utils\";\nimport { getPhyClusterPerApp } from \"api/cluster-index-api\";\nimport { RenderEmpty } from \"component/LogClusterEmpty\";\nconst ONE_HOUR = 1000 * 60 * 60;\n\nexport const ClusterKanban = (props) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const { clusterKanban } = useSelector(\n    (state) => ({\n      clusterKanban: (state as any).clusterKanban,\n    }),\n    shallowEqual\n  );\n\n  const dispatch = useDispatch();\n\n  const currentTime = new Date().getTime();\n  const [startTime, setStartTime] = useState(currentTime - ONE_HOUR);\n  const [endTime, setEndTime] = useState(currentTime - 120000);\n  const [clusterName, setClusterName] = useState(clusterKanban.clusterName);\n  const [clusterNameList, setClusterNameList] = useState([]);\n  const [refreshTime, setRefreshTime] = useState(0);\n  const [pageLoad, setPageLoad] = useState(false);\n  const superApp = isSuperApp();\n\n  const updateCluster = (props) => {\n    const { startTime, endTime, clusterName, timeRadioKey } = props;\n    // if (!clusterName) {\n    //   return;\n    // }\n    const timeMinus = endTime - startTime;\n    dispatch(\n      setClusterForm({\n        startTime,\n        endTime,\n        clusterName,\n        isMoreDay: timeMinus > oneDayMillims,\n        timeRadioKey,\n      })\n    );\n  };\n\n  const onTimeStampChange = (startTime, endTime, timeRadioKey) => {\n    updateCluster({\n      startTime,\n      endTime,\n      clusterName,\n      timeRadioKey,\n    });\n    setStartTime(startTime);\n    setEndTime(endTime);\n  };\n\n  const setSelectClusterName = async () => {\n    const superApp = isSuperApp();\n    setPageLoad(true);\n    try {\n      const clusterNames = await (superApp ? getPhyClusterPerApp() : getLogicClusterNames());\n      setPageLoad(false);\n      if (clusterNames && clusterNames.length > 0) {\n        setClusterNameList(clusterNames.map((item) => ({ text: item, value: item })));\n        setClusterName(Url().search.cluster || clusterNames[0]);\n      }\n    } catch (error) {\n      console.log(error, \"错误\");\n      setPageLoad(false);\n    }\n  };\n\n  useEffect(() => {\n    setClusterName(Url().search.cluster);\n  }, [Url().search.cluster]);\n\n  useEffect(() => {\n    setSelectClusterName();\n  }, []);\n\n  useEffect(() => {\n    updateCluster({\n      startTime,\n      endTime,\n      clusterName,\n      timeRadioKey: clusterKanban.timeRadioKey,\n    });\n    return () => {\n      updateCluster({\n        startTime,\n        endTime,\n        clusterName: \"\",\n      });\n    };\n  }, [clusterName]);\n\n  const renderTitleContent = () => {\n    return {\n      title: \"集群看板\",\n      content: null,\n    };\n  };\n  const renderNode = () => {\n    return (\n      <>\n        {/* <div className=\"indicators-header\">\n          <div className=\"kanban-header-box\">\n            <RenderTitle {...renderTitleContent()} />\n          </div>\n          <KanbanForm\n            clusterName={clusterName}\n            clusterNameList={clusterNameList}\n            onTimeStampChange={onTimeStampChange}\n            onClusterNameChange={(val) => {\n              setClusterName(val);\n            }}\n            refreshTime={refreshTime}\n          />\n        </div> */}\n        <div className=\"hash-menu-container cluster\">\n          <HashMenu\n            TAB_LIST={CLUSTER_KANBAN_MENU()}\n            MENU_MAP={MENU_MAP}\n            defaultHash={isSuperApp() ? \"overview\" : \"index\"}\n            // 监听页面权限的变化\n            key={department + JSON.stringify(Url().search)}\n          />\n          <div className=\"kanban-form\">\n            <KanbanForm\n              clusterName={clusterName}\n              clusterNameList={clusterNameList}\n              onTimeStampChange={onTimeStampChange}\n              onClusterNameChange={(val) => {\n                setClusterName(val);\n              }}\n              refreshTime={refreshTime}\n            />\n          </div>\n\n          <div className=\"refresh-time\">\n            <RefreshTime changeRefreshTime={setRefreshTime} />\n          </div>\n        </div>\n      </>\n    );\n  };\n\n  return (\n    <div>\n      <Spin className=\"index-spin-name\" spinning={pageLoad}>\n        {superApp\n          ? renderNode()\n          : clusterNameList.length\n          ? !pageLoad && renderNode()\n          : !pageLoad && (\n              <div>\n                <RenderEmpty {...props} />\n              </div>\n            )}\n      </Spin>\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/config.tsx",
    "content": "export * from \"../config\";\n\nimport React from \"react\";\nimport { IMenuItem } from \"typesPath/base-types\";\nimport { OverviewView } from \"./overview-view\";\nimport { IndexView } from \"./index-view\";\nimport { NodeView } from \"./node-view\";\nimport { IndexTemplateView } from \"./index-template-view\";\nimport moment from \"moment\";\nimport { isSuperApp } from \"lib/utils\";\n\nexport enum TAB_LIST_KEY {\n  overview = \"overview\",\n  node = \"node\",\n  index = \"index\",\n  template = \"template\",\n}\n\n\nexport const CLUSTER_KANBAN_MENU = () => {\n  //普通侧和运维测tab需要更改\n  const superApp = isSuperApp();\n  if (!superApp) {\n    return [\n      {\n        name: \"索引\",\n        key: TAB_LIST_KEY.index,\n      },\n      {\n        name: \"索引模板\",\n        key: TAB_LIST_KEY.template,\n      },\n      {\n        name: \"总览\",\n        key: TAB_LIST_KEY.overview,\n      },\n      {\n        name: \"节点\",\n        key: TAB_LIST_KEY.node,\n      },\n    ];\n  }\n  return [\n    {\n      name: \"总览\",\n      key: TAB_LIST_KEY.overview,\n    },\n    {\n      name: \"节点\",\n      key: TAB_LIST_KEY.node,\n    },\n    {\n      name: \"索引\",\n      key: TAB_LIST_KEY.index,\n    },\n    {\n      name: \"索引模板\",\n      key: TAB_LIST_KEY.template,\n    },\n  ];\n};\nexport const TAB_LIST = [\n  {\n    name: \"总览\",\n    key: TAB_LIST_KEY.overview,\n    content: () => <OverviewView />,\n  },\n  {\n    name: \"节点\",\n    key: TAB_LIST_KEY.node,\n    content: () => <NodeView />,\n  },\n  {\n    name: \"索引\",\n    key: TAB_LIST_KEY.index,\n    content: () => <IndexView />,\n  },\n  {\n    name: \"索引模板\",\n    key: TAB_LIST_KEY.template,\n    content: () => <IndexTemplateView />,\n  },\n];\nconst menuMap = new Map<string, IMenuItem>();\n\nTAB_LIST.forEach((d) => {\n  menuMap.set(d.key, d);\n});\n\nexport const MENU_MAP = menuMap;\n\n// 总览视图饼图\nexport const getContrastChartProps = (\n  name,\n  eChartsData,\n  subtext,\n  colors = [\"#21CAB8\", \"#D3DAE7\"]\n) => {\n  return {\n    name: `${name}对比图`,\n    eChartsData: eChartsData,\n    colors: colors,\n    text: name,\n    subtext: subtext,\n  };\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/index-template-view-config.tsx",
    "content": "import { unitMap, addChartTitle } from \"../config\";\n\nexport const indexConfigClassifyList: string[] = [\"索引模板基础指标\", \"索引模板性能指标\", \"索引模板内存指标\"];\n\n// 匹配计算方式\nexport const aggTypeMap = {\n  索引模板基础指标: \"sum\",\n  索引模板性能指标: \"max\",\n  索引模板内存指标: \"sum\",\n};\n\nexport const indexConfigData = {\n  shardNu: {\n    name: \"索引Shard数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[0],\n    indicatorType: [1],\n  },\n  \"store-size_in_bytes\": {\n    name: \"索引存储大小\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[0],\n    indicatorType: [],\n  },\n  \"docs-count\": {\n    name: \"文档总数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[0],\n    indicatorType: [1],\n  },\n  \"indexing-index_total_rate\": {\n    name: \"写入TPS\",\n    unit: unitMap.countS,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 3],\n  },\n  \"indices-indexing-index_time_per_doc\": {\n    name: \"写入耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  \"search-query_total_rate\": {\n    name: \"查询Query QPS\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 3],\n  },\n  \"cost-query_time_in_millis\": {\n    name: \"查询Query耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  \"search-fetch_total_rate\": {\n    name: \"查询Fetch QPS\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"cost-fetch_time_in_millis\": {\n    name: \"查询Fetch耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  \"search-scroll_total_rate\": {\n    name: \"查询Scroll量\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"cost-scroll_time_in_millis\": {\n    name: \"查询Scroll耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  \"merges-total_rate\": {\n    name: \"Merge次数\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"cost-merges-total_time_in_millis\": {\n    name: \"Merge耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  // \"merges_avg_time\": {\n  //   name: \"模板merge操作单次耗时\",\n  //   unit: unitMap.ms,\n  //   classify: indexConfigClassifyList[1],\n  // },\n  \"refresh-total_rate\": {\n    name: \"Refresh次数\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"cost-refresh-total_time_in_millis\": {\n    name: \"Refresh耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  // refresh_avg_time: {\n  //   name: \"模板refresh操作单次耗时\",\n  //   unit: unitMap.ms,\n  //   classify: indexConfigClassifyList[1],\n  // },\n  \"flush-total_rate\": {\n    name: \"Flush次数\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"cost-flush-total_time_in_millis\": {\n    name: \"Flush耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  // flush_avg_time: {\n  //   name: \"模板flush操作单次耗时\",\n  //   unit: unitMap.ms,\n  //   classify: indexConfigClassifyList[1],\n  // },\n  // \"indexing-time_per_doc\": {\n  //   name: \"单个模板操作耗时\",\n  //   unit: unitMap.ms,\n  //   classify: indexConfigClassifyList[1],\n  // },\n  \"query_cache-memory_size_in_bytes\": {\n    name: \"Query Cache内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [1, 4],\n  },\n  \"segments-memory_in_bytes\": {\n    name: \"Segments大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [1, 4],\n  },\n  \"segments-term_vectors_memory_in_bytes\": {\n    name: \"Terms内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"segments-points_memory_in_bytes\": {\n    name: \"Points内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"segments-doc_values_memory_in_bytes\": {\n    name: \"Doc Values内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"segments-index_writer_memory_in_bytes\": {\n    name: \"Index Writer内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"translog-size_in_bytes\": {\n    name: \"未提交的Translog大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"segments-stored_fields_memory_in_bytes\": {\n    name: \"Stored Fields大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"segments-norms_memory_in_bytes\": {\n    name: \"Norms内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"segments-version_map_memory_in_bytes\": {\n    name: \"Version Map内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"segments-fixed_bit_set_memory_in_bytes\": {\n    name: \"Fixed Bitset内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"fielddata-memory_size_in_bytes\": {\n    name: \"Fielddata内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"request_cache-memory_size_in_bytes\": {\n    name: \"Request Cache内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n};\n// 给指标配置项添加标题\naddChartTitle(indexConfigData);\n\nexport const getCheckedData = (checkedList) => {\n  const defaultClassifyData = {};\n  indexConfigClassifyList.forEach((item) => {\n    defaultClassifyData[item] = [];\n  });\n  checkedList.forEach((item) => {\n    if (indexConfigData[item]) {\n      defaultClassifyData[indexConfigData[item].classify].push(item);\n    }\n  });\n  return defaultClassifyData;\n};\n\nexport const allCheckedData = getCheckedData(Object.keys(indexConfigData));\n\ninterface defaultIndexConfigItemPropsType {\n  title: string;\n  plainOptions: { label: string; value: string }[];\n}\n\nexport const defaultIndexConfigList: defaultIndexConfigItemPropsType[] = indexConfigClassifyList.map((item) => ({\n  title: item,\n  plainOptions: allCheckedData[item].map((item) => ({\n    label: indexConfigData[item].name,\n    value: item,\n    indicatorType: indexConfigData[item].indicatorType,\n  })),\n}));\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/index-template-view.tsx",
    "content": "import React, { memo, useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport { Collapse } from \"antd\";\nimport _ from \"lodash\";\nimport { IndexConfig, SelectRadio } from \"../components\";\nimport {\n  defaultIndexConfigList,\n  allCheckedData,\n  getCheckedData,\n  indexConfigData,\n  indexConfigClassifyList,\n  aggTypeMap,\n} from \"./index-template-view-config\";\nimport { formatterTimeYMDHMS, objFlat } from \"../config\";\nimport { TOP_MAP, TOP_TIME_RANGE, TOP_TYPE } from \"constants/status-map\";\nimport { RenderLine } from \"../components/render-line\";\nimport {\n  getCheckedList,\n  setCheckedList,\n  getTemplateViewData,\n  getLogicListTemplates,\n  getPhyListTemplates,\n  getDictionary,\n} from \"../../../api/cluster-kanban\";\nimport { asyncMicroTasks, isSuperApp, resize } from \"../../../lib/utils\";\nimport { setIsUpdate } from \"actions/cluster-kanban\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport Url from \"lib/url-parser\";\nimport { OperationPanel } from \"../components/operation-panel\";\n\nexport const classPrefix = \"monitor\";\nconst { Panel } = Collapse;\nconst TEMPLATE = \"template\";\nexport const IndexTemplateView = memo(() => {\n  const [indexTemplateList, setIndexTemplateList] = useState([]);\n  const [checkedData, setCheckedData] = useState(getCheckedData([]));\n  const [update, setUpdate] = useState(false);\n  const [dictionary, setDictionary] = useState({});\n\n  // 用于判断是否第一次进入页面\n  const [flag, setFlag] = useState(true);\n\n  const dispatch = useDispatch();\n  const selectRadioValue = useRef({\n    topNum: TOP_MAP[0].value,\n    topTimeStep: TOP_TIME_RANGE[0].value,\n    topMethod: TOP_TYPE[0].value,\n    content: [],\n  });\n\n  const sortEnd = (item, { oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(checkedData[item], oldIndex, newIndex);\n    checkedData[item] = listsNew;\n    const checkedList = objFlat(checkedData);\n    setCheckedList(TEMPLATE, checkedList);\n    setCheckedData({ ...checkedData });\n  };\n\n  const { clusterName, startTime, endTime, isMoreDay, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      clusterName: (state as any).clusterKanban.clusterName,\n      startTime: (state as any).clusterKanban.startTime,\n      endTime: (state as any).clusterKanban.endTime,\n      isMoreDay: (state as any).clusterKanban.isMoreDay,\n      isUpdate: (state as any).clusterKanban.isUpdate,\n      timeRadioKey: (state as any).clusterKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n\n  const reloadPage = () => {\n    dispatch(setIsUpdate(!isUpdate));\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(TEMPLATE);\n      if (!checkedList || checkedList.length === 0) {\n        setCheckedData(allCheckedData);\n      } else {\n        setCheckedData(getCheckedData(checkedList));\n      }\n    } catch (error) {\n      setCheckedData(allCheckedData);\n      console.log(\"cluster-kanban node-view 获取配置下项失败\", error);\n    }\n  };\n\n  const setIndexConfigCheckedData = (changeCheckedData) => {\n    const checkedList = objFlat(changeCheckedData);\n    setCheckedData(changeCheckedData);\n    setCheckedList(TEMPLATE, checkedList);\n    reloadPage();\n  };\n\n  const getAsyncViewData = useCallback(\n    async (metricsTypes, aggType?: string) => {\n      const logicTemplateIds = selectRadioValue.current.content;\n      // 从dashboard跳转至索引模板视图，没有logicTemplateId时不调接口\n      if (flag && Url().search?.template && !logicTemplateIds.length) return;\n      setFlag(false);\n      let data = await getTemplateViewData(\n        metricsTypes,\n        clusterName,\n        startTime,\n        endTime,\n        selectRadioValue.current.topNum,\n        logicTemplateIds,\n        aggType,\n        selectRadioValue.current.topMethod,\n        selectRadioValue.current.topTimeStep\n      );\n      return data;\n    },\n    [clusterName, startTime, endTime, timeRadioKey, update, selectRadioValue.current.content]\n  );\n\n  const getAsyncIndexTemplateList = async () => {\n    if (clusterName) {\n      try {\n        selectRadioValue.current.content = [];\n        setUpdate(!update);\n        const superApp = isSuperApp();\n        const data = await (superApp ? getPhyListTemplates(clusterName) : getLogicListTemplates(clusterName));\n        const indexTemplateList = data.map((item) => ({ name: item.name, value: item.id }));\n        const id =\n          Url().search?.cluster === clusterName ? indexTemplateList.find((v) => v.name === Url().search?.template)?.value : undefined;\n        selectRadioValue.current.content = id ? [id] : [];\n        setIndexTemplateList(indexTemplateList);\n      } catch (error) {\n        console.log(error);\n      }\n    }\n  };\n\n  const _getDictionary = async () => {\n    let params = {\n      model: \"Index_template\",\n    };\n    let res = await getDictionary(params);\n    let data = {} as any;\n    (res || []).forEach((item) => {\n      if (item?.metricType) {\n        data[item?.metricType] = item;\n      }\n    });\n    setDictionary(data);\n  };\n\n  useEffect(() => {\n    getAsyncCheckedList();\n    _getDictionary();\n  }, []);\n\n  useEffect(() => {\n    getAsyncIndexTemplateList();\n  }, [clusterName]);\n\n  const onSelectRadioChange = (values, needReload) => {\n    selectRadioValue.current = values;\n    if (needReload) {\n      reloadPage();\n    }\n  };\n\n  const renderTopWhat = () => {\n    return (\n      <SelectRadio\n        onValueChange={onSelectRadioChange}\n        content={selectRadioValue.current.content || []}\n        contentList={indexTemplateList}\n        placeholder=\"请选择索引模板\"\n        allowClear={true}\n        type=\"node\"\n      />\n    );\n  };\n\n  const renderConfig = () => {\n    return (\n      <IndexConfig\n        title=\"索引模板指标配置\"\n        optionList={defaultIndexConfigList}\n        checkedData={checkedData}\n        setCheckedData={setIndexConfigCheckedData}\n        needShortcut={true}\n      />\n    );\n  };\n\n  const renderFilter = () => {\n    return (\n      <>\n        {renderTopWhat()}\n        {renderConfig()}\n      </>\n    );\n  };\n\n  const RenderContent = useMemo(\n    () => (\n      <div className={`${classPrefix}-overview-content`}>\n        {indexConfigClassifyList.map((item, index) => {\n          if (checkedData[item] && checkedData[item].length > 0) {\n            return (\n              <Collapse\n                defaultActiveKey={[index]}\n                onChange={() => {\n                  asyncMicroTasks(resize);\n                }}\n                style={{ marginTop: 20 }}\n                key={item + index}\n              >\n                <Panel header={item} key={index}>\n                  <div className={`${classPrefix}-overview-content-line  content-margin-top-20`}>\n                    {checkedData[item] && checkedData[item].length ? (\n                      <RenderLine\n                        metricsTypes={checkedData[item]}\n                        key={item + index + selectRadioValue.current.topNum + clusterName}\n                        configData={indexConfigData}\n                        isMoreDay={isMoreDay}\n                        getAsyncViewData={getAsyncViewData}\n                        startTime={startTime}\n                        endTime={endTime}\n                        sortEnd={sortEnd}\n                        item={item}\n                        aggType={aggTypeMap[item]}\n                        dictionary={dictionary}\n                        content={selectRadioValue.current.content}\n                      />\n                    ) : (\n                      \"\"\n                    )}\n                  </div>\n                </Panel>\n              </Collapse>\n            );\n          }\n        })}\n      </div>\n    ),\n    [startTime, endTime, timeRadioKey, checkedData, indexConfigClassifyList, update, dictionary]\n  );\n\n  return (\n    <>\n      <OperationPanel classPrefix={classPrefix} reloadPage={reloadPage} endTime={endTime} renderFilter={renderFilter} />\n      {RenderContent}\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/index-view-config.tsx",
    "content": "import { unitMap, addChartTitle } from \"../config\";\n\nexport const indexConfigClassifyList: string[] = [\"索引基础指标\", \"索引性能指标\", \"索引内存指标\"];\n\nexport const indexConfigData = {\n  shardNu: {\n    name: \"索引Shard数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[0],\n    indicatorType: [1],\n  },\n  \"store-size_in_bytes\": {\n    name: \"索引存储大小\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[0],\n    indicatorType: [],\n  },\n  \"docs-count\": {\n    name: \"文档总数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[0],\n    indicatorType: [1],\n  },\n  \"indexing-index_total_rate\": {\n    name: \"写入TPS\",\n    unit: unitMap.countS,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 3],\n  },\n  \"indices-indexing-index_time_per_doc\": {\n    name: \"写入耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  \"search-query_total_rate\": {\n    name: \"查询Query QPS\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 3],\n  },\n  \"cost-query_time_in_millis\": {\n    name: \"查询Query耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  \"search-fetch_total_rate\": {\n    name: \"查询Fetch QPS\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"cost-fetch_time_in_millis\": {\n    name: \"查询Fetch耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  \"search-scroll_total_rate\": {\n    name: \"查询Scroll量\",\n    unit: unitMap.countS,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"cost-scroll_time_in_millis\": {\n    name: \"查询Scroll耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  \"merges-total_rate\": {\n    name: \"Merge次数\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"cost-merges-total_time_in_millis\": {\n    name: \"Merge耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  // merges_avg_time: {\n  //   name: \"索引merge操作单次耗时\",\n  //   unit: unitMap.ms,\n  //   classify: indexConfigClassifyList[1],\n  // },\n  \"refresh-total_rate\": {\n    name: \"Refresh次数\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"cost-refresh-total_time_in_millis\": {\n    name: \"Refresh耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  // refresh_avg_time: {\n  //   name: \"索引refresh操作单次耗时\",\n  //   unit: unitMap.ms,\n  //   classify: indexConfigClassifyList[1],\n  // },\n  \"flush-total_rate\": {\n    name: \"Flush次数\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"cost-flush-total_time_in_millis\": {\n    name: \"Flush耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  // flush_avg_time: {\n  //   name: \"索引flush操作单次耗时\",\n  //   unit: unitMap.ms,\n  //   classify: indexConfigClassifyList[1],\n  // },\n  // \"indexing-time_per_doc\": {\n  //   name: \"单个索引操作耗时\",\n  //   unit: unitMap.ms,\n  //   classify: indexConfigClassifyList[1],\n  // },\n  \"query_cache-memory_size_in_bytes\": {\n    name: \"Query Cache内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"segments-memory_in_bytes\": {\n    name: \"Segments大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [1, 4],\n  },\n  \"segments-term_vectors_memory_in_bytes\": {\n    name: \"Terms内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"segments-points_memory_in_bytes\": {\n    name: \"Points内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"segments-doc_values_memory_in_bytes\": {\n    name: \"Doc Values内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"segments-index_writer_memory_in_bytes\": {\n    name: \"Index Writer内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"translog-size_in_bytes\": {\n    name: \"未提交的Translog大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"segments-stored_fields_memory_in_bytes\": {\n    name: \"Stored Fields大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"segments-norms_memory_in_bytes\": {\n    name: \"Norms内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"segments-version_map_memory_in_bytes\": {\n    name: \"Version Map内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"segments-fixed_bit_set_memory_in_bytes\": {\n    name: \"Fixed Bitset内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"fielddata-memory_size_in_bytes\": {\n    name: \"Fielddata内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n  \"request_cache-memory_size_in_bytes\": {\n    name: \"Request Cache内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [4],\n  },\n};\n// 给指标配置项添加标题\naddChartTitle(indexConfigData);\n\nexport const getCheckedData = (checkedList) => {\n  const defaultClassifyData = {};\n  indexConfigClassifyList.forEach((item) => {\n    defaultClassifyData[item] = [];\n  });\n  checkedList.forEach((item) => {\n    if (indexConfigData[item]) {\n      defaultClassifyData[indexConfigData[item].classify].push(item);\n    }\n  });\n  return defaultClassifyData;\n};\n\nexport const allCheckedData = getCheckedData(Object.keys(indexConfigData));\n\ninterface defaultIndexConfigItemPropsType {\n  title: string;\n  plainOptions: { label: string; value: string }[];\n}\n\nexport const defaultIndexConfigList: defaultIndexConfigItemPropsType[] = indexConfigClassifyList.map((item) => ({\n  title: item,\n  plainOptions: allCheckedData[item].map((item) => ({\n    label: indexConfigData[item].name,\n    value: item,\n    indicatorType: indexConfigData[item].indicatorType,\n  })),\n}));\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/index-view.tsx",
    "content": "import React, { memo, useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport { Collapse } from \"antd\";\nimport _ from \"lodash\";\nimport { IndexConfig, SelectRadio } from \"../components\";\nimport { defaultIndexConfigList, allCheckedData, getCheckedData, indexConfigData, indexConfigClassifyList } from \"./index-view-config\";\nimport { objFlat } from \"../config\";\nimport { TOP_MAP, TOP_TIME_RANGE, TOP_TYPE } from \"constants/status-map\";\nimport { RenderLine } from \"../components/render-line\";\nimport {\n  getCheckedList,\n  setCheckedList,\n  getIndexViewData,\n  getPhyIndexNameList,\n  getLogicIndexNameList,\n  getDictionary,\n} from \"../../../api/cluster-kanban\";\nimport { asyncMicroTasks, isSuperApp, resize } from \"../../../lib/utils\";\nimport { setIsUpdate } from \"actions/cluster-kanban\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport Url from \"lib/url-parser\";\nimport { OperationPanel } from \"../components/operation-panel\";\n\nexport const classPrefix = \"monitor\";\nconst { Panel } = Collapse;\nconst INDEX = \"index\";\nexport const IndexView = memo(() => {\n  const [indexNameList, setIndexNameList] = useState([]);\n  const [update, setUpdate] = useState(false);\n  const [checkedData, setCheckedData] = useState(getCheckedData([]));\n  const [dictionary, setDictionary] = useState({});\n\n  // 用于判断是否第一次进入页面\n  const [flag, setFlag] = useState(true);\n\n  const dispatch = useDispatch();\n\n  const selectRadioValue = useRef({\n    topNum: TOP_MAP[0].value,\n    topTimeStep: TOP_TIME_RANGE[0].value,\n    topMethod: TOP_TYPE[0].value,\n    content: Url().search?.index ? [Url().search?.index] : [],\n  });\n\n  const sortEnd = (item, { oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(checkedData[item], oldIndex, newIndex);\n    checkedData[item] = listsNew;\n    const checkedList = objFlat(checkedData);\n    setCheckedList(INDEX, checkedList);\n    setCheckedData({ ...checkedData });\n  };\n\n  const { clusterName, startTime, endTime, isMoreDay, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      clusterName: (state as any).clusterKanban.clusterName,\n      startTime: (state as any).clusterKanban.startTime,\n      endTime: (state as any).clusterKanban.endTime,\n      isMoreDay: (state as any).clusterKanban.isMoreDay,\n      isUpdate: (state as any).clusterKanban.isUpdate,\n      timeRadioKey: (state as any).clusterKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n\n  const reloadPage = () => {\n    dispatch(setIsUpdate(!isUpdate));\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(INDEX);\n      if (!checkedList || checkedList.length === 0) {\n        setCheckedData(allCheckedData);\n      } else {\n        setCheckedData(getCheckedData(checkedList));\n      }\n    } catch (error) {\n      setCheckedData(allCheckedData);\n      console.log(\"cluster-kanban node-view 获取配置下项失败\", error);\n    }\n  };\n\n  const setIndexConfigCheckedData = (changeCheckedData) => {\n    const checkedList = objFlat(changeCheckedData);\n    setCheckedData(changeCheckedData);\n    setCheckedList(INDEX, checkedList);\n    reloadPage();\n  };\n  const getAsyncViewData = useCallback(\n    async (metricsTypes) => {\n      // 从dashboard跳转至索引视图，selectRadioValue.current.content未赋值时不调接口\n      // if (flag && !selectRadioValue.current.content?.length && Url().search?.index) return;\n      // setFlag(false);\n      return await getIndexViewData(\n        metricsTypes,\n        clusterName,\n        startTime,\n        endTime,\n        selectRadioValue.current.topNum,\n        selectRadioValue.current.content,\n        selectRadioValue.current.topMethod,\n        selectRadioValue.current.topTimeStep\n      );\n    },\n    [clusterName, startTime, endTime, timeRadioKey, selectRadioValue.current.content]\n  );\n\n  const getAsyncIndexNameList = async () => {\n    if (clusterName) {\n      try {\n        selectRadioValue.current.content = [];\n        setUpdate(!update);\n        const superApp = isSuperApp();\n        const indexNameList = await (superApp ? getPhyIndexNameList(clusterName) : getLogicIndexNameList(clusterName));\n        selectRadioValue.current.content = Url().search?.cluster === clusterName && Url().search?.index ? [Url().search?.index] : [];\n        setIndexNameList(indexNameList);\n      } catch (error) {\n        console.log(error);\n      }\n    }\n  };\n\n  const _getDictionary = async () => {\n    let params = {\n      model: \"Index\",\n    };\n    let res = await getDictionary(params);\n    let data = {} as any;\n    (res || []).forEach((item) => {\n      if (item?.metricType) {\n        data[item?.metricType] = item;\n      }\n    });\n    setDictionary(data);\n  };\n\n  useEffect(() => {\n    getAsyncCheckedList();\n    _getDictionary();\n  }, []);\n\n  useEffect(() => {\n    getAsyncIndexNameList();\n  }, [clusterName]);\n\n  const onSelectRadioChange = (values, needReload) => {\n    selectRadioValue.current = values;\n    if (needReload) {\n      reloadPage();\n    }\n  };\n\n  const renderTopWhat = () => {\n    return (\n      <SelectRadio\n        onValueChange={onSelectRadioChange}\n        content={selectRadioValue.current.content || []}\n        contentList={indexNameList}\n        placeholder=\"请选择索引\"\n        style={{ width: '100%' }}\n        type=\"node\"\n        allowClear={true}\n      />\n    );\n  };\n\n  const renderConfig = () => {\n    return (\n      <IndexConfig\n        title=\"索引指标配置\"\n        optionList={defaultIndexConfigList}\n        checkedData={checkedData}\n        setCheckedData={setIndexConfigCheckedData}\n        needShortcut={true}\n      />\n    );\n  };\n\n  const renderFilter = () => {\n    return (\n      <>\n        {renderTopWhat()}\n        {renderConfig()}\n      </>\n    );\n  };\n\n  const RenderContent = useMemo(() => {\n    return (\n      <div className={`${classPrefix}-overview-content`}>\n        {indexConfigClassifyList.map((item, index) => {\n          if (checkedData[item] && checkedData[item].length > 0) {\n            return (\n              <Collapse\n                defaultActiveKey={[index]}\n                onChange={() => {\n                  asyncMicroTasks(resize);\n                }}\n                style={{ marginTop: 20 }}\n                key={item + index}\n              >\n                <Panel header={item} key={index}>\n                  <div className={`${classPrefix}-overview-content-line  content-margin-top-20`}>\n                    {checkedData[item] && checkedData[item].length ? (\n                      <RenderLine\n                        metricsTypes={checkedData[item]}\n                        key={item + index + selectRadioValue.current.topNum + clusterName}\n                        configData={indexConfigData}\n                        isMoreDay={isMoreDay}\n                        getAsyncViewData={getAsyncViewData}\n                        startTime={startTime}\n                        endTime={endTime}\n                        sortEnd={sortEnd}\n                        item={item}\n                        dictionary={dictionary}\n                        content={selectRadioValue.current.content}\n                      />\n                    ) : (\n                      \"\"\n                    )}\n                  </div>\n                </Panel>\n              </Collapse>\n            );\n          }\n        })}\n      </div>\n    );\n  }, [startTime, endTime, checkedData, timeRadioKey, indexConfigClassifyList, update, dictionary]);\n\n  return (\n    <>\n      <OperationPanel classPrefix={classPrefix} reloadPage={reloadPage} endTime={endTime} renderFilter={renderFilter} />\n      {RenderContent}\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/node-view-config.tsx",
    "content": "import { unitMap, addChartTitle } from \"../config\";\n\n// 指标分类\nexport const indexConfigClassifyList: string[] = [\"系统指标\", \"基本性能指标\", \"高级性能指标\", \"JVM指标\", \"Breaker指标\", \"内存大小指标\"];\n\n// 所有指标项\nexport const indexConfigData = {\n  \"os-cpu-percent\": {\n    // 指标配置选项，中文映射\n    name: \"CPU利用率\",\n    // 单位名称和单位数据格式化函数\n    unit: unitMap.percent,\n    // 分类\n    classify: indexConfigClassifyList[0],\n    indicatorType: [1, 2, 3],\n  },\n  \"os-cpu-load_average-1m\": {\n    name: \"CPU近1分钟负载\",\n    unit: unitMap.none,\n    classify: indexConfigClassifyList[0],\n    indicatorType: [2, 3],\n  },\n  \"fs-total-disk_free_percent\": {\n    name: \"磁盘空闲率\",\n    unit: unitMap.percent,\n    classify: indexConfigClassifyList[0],\n    indicatorType: [1, 3],\n  },\n  \"transport-tx_size_in_bytes_rate\": {\n    name: \"网络发送流量\",\n    unit: unitMap.mbS,\n    classify: indexConfigClassifyList[0],\n    indicatorType: [3],\n  },\n  \"transport-rx_size_in_bytes_rate\": {\n    name: \"网络接收流量\",\n    unit: unitMap.mbS,\n    classify: indexConfigClassifyList[0],\n    indicatorType: [3],\n  },\n  \"indices-indexing-index_total_rate\": {\n    name: \"写入TPS\",\n    unit: unitMap.countS,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 3],\n  },\n  \"indices-indexing-index_time_per_doc\": {\n    name: \"写入耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  \"thread_pool-bulk-rejected\": {\n    name: \"Write Rejected\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  \"thread_pool-bulk-queue\": {\n    name: \"Write Queue\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  \"indices-search-query_total_rate\": {\n    name: \"Query QPS\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 3],\n  },\n  \"indices-search-fetch_total_rate\": {\n    name: \"Fetch QPS\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [3],\n  },\n  \"indices-search-query_time_per_query\": {\n    name: \"Query耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  \"indices-search-fetch_time_per_fetch\": {\n    name: \"Fetch耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  \"thread_pool-search-queue\": {\n    name: \"Search Queue\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  \"thread_pool-search-rejected\": {\n    name: \"Search Rejected\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  \"indices-search-scroll_current\": {\n    name: \"Scroll当下请求量\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"indices-search-scroll_avg_time\": {\n    name: \"Scroll请求耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  \"indices-merges_avg_time\": {\n    name: \"Merge操作耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  \"indices-merges-total\": {\n    name: \"Merge次数\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"indices-refresh_avg_time\": {\n    name: \"Refresh操作耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  \"indices-refresh-total\": {\n    name: \"Refresh次数\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"indices-flush_avg_time\": {\n    name: \"Flush操作耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  \"indices-flush-total\": {\n    name: \"Flush次数\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"indices-query_cache-hit_rate\": {\n    name: \"Query Cache内存命中率\",\n    unit: unitMap.percent,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [2],\n  },\n  \"indices-request_cache-hit_rate\": {\n    name: \"Request Cache内存命中率\",\n    unit: unitMap.percent,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"indices-query_cache-evictions\": {\n    name: \"Query Cache evictions\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"indices-request_cache-evictions\": {\n    name: \"Request Cache eviction\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[1],\n    indicatorType: [],\n  },\n  \"http-current_open\": {\n    name: \"Http活跃连接数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [1, 3],\n  },\n  \"indices-segments-count\": {\n    name: \"Segment数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [3, 4],\n  },\n  \"indices-docs-count\": {\n    name: \"文档总数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [3],\n  },\n  \"indices-store-size_in_bytes\": {\n    name: \"总存储大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"indices-translog-uncommitted_size_in_bytes\": {\n    name: \"未提交的Translog大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  runningTime: {\n    name: \"执行任务耗时\",\n    unit: unitMap.s,\n    classify: indexConfigClassifyList[2],\n    newquota: \"avg\",\n    indicatorType: [1, 2],\n  },\n  taskId: {\n    name: \"执行任务数量\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[2],\n    newquota: \"cardinality\",\n    indicatorType: [1, 2],\n  },\n  \"thread_pool-write-queue\": {\n    name: \"写入线程池queue数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [2],\n  },\n  \"thread_pool-refresh-queue\": {\n    name: \"刷新线程池queue数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"thread_pool-rollup_indexing-queue\": {\n    name: \"落盘线程池queue数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"thread_pool-management-queue\": {\n    name: \"管理线程池queue数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"thread_pool-force_merge-queue\": {\n    name: \"合并线程池queue数\",\n    unit: unitMap.count,\n    classify: indexConfigClassifyList[2],\n    indicatorType: [],\n  },\n  \"jvm-gc-young-collection_count_rate\": {\n    name: \"Young GC次数\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[3],\n    indicatorType: [1, 2],\n  },\n  \"jvm-gc-old-collection_count_rate\": {\n    name: \"Old GC次数\",\n    unit: unitMap.ss,\n    classify: indexConfigClassifyList[3],\n    indicatorType: [1, 2],\n  },\n  \"jvm-gc-young-collection_avg_time\": {\n    name: \"Young GC耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[3],\n    indicatorType: [],\n  },\n  \"jvm-gc-old-collection_avg_time\": {\n    name: \"Old GC耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[3],\n    indicatorType: [],\n  },\n  \"jvm-mem-heap_used_in_bytes\": {\n    name: \"JVM堆内存使用量\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[3],\n    indicatorType: [],\n  },\n  \"jvm-mem-non_heap_used_in_bytes\": {\n    name: \"JVM堆外存使用量\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[3],\n    indicatorType: [],\n  },\n  \"jvm-mem-heap_used_percent\": {\n    name: \"JVM堆使用率\",\n    unit: unitMap.percent,\n    classify: indexConfigClassifyList[3],\n    indicatorType: [1, 2],\n  },\n  \"jvm-mem-pools-young-used_in_bytes\": {\n    name: \"堆内存young区使用空间\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[3],\n    indicatorType: [],\n  },\n  \"jvm-mem-pools-old-used_in_bytes\": {\n    name: \"堆内存old区使用空间\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[3],\n    indicatorType: [],\n  },\n  \"breakers-fielddata-limit_size_in_bytes\": {\n    name: \"Field data circuit breaker 内存占用\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[4],\n    indicatorType: [],\n  },\n  \"breakers-request-limit_size_in_bytes\": {\n    name: \"Request circuit breaker 内存占用\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[4],\n    indicatorType: [],\n  },\n  \"breakers-in_flight_requests-limit_size_in_bytes\": {\n    name: \"Inflight requests circuit breaker 内存占用\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[4],\n    indicatorType: [1, 4],\n  },\n  \"breakers-in_flight_http_requests-limit_size_in_bytes\": {\n    name: \"Inflight http requests circuit breaker 内存占用\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[4],\n    indicatorType: [1, 4],\n  },\n  \"breakers-accounting-limit_size_in_bytes\": {\n    name: \"Accounting requests circuit breaker 内存占用\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[4],\n    indicatorType: [],\n  },\n  // \"script-compilations\": {\n  //   name: \"Script compilation circuit breaker 编译次数\",\n  //   unit: unitMap.mins,\n  //   classify: indexConfigClassifyList[4],\n  //   indicatorType: [],\n  // },\n  \"breakers-parent-limit_size_in_bytes\": {\n    name: \"Parent circuit breaker JVM真实内存占用\",\n    unit: unitMap.GB,\n    classify: indexConfigClassifyList[4],\n    indicatorType: [1, 4],\n  },\n  \"indices-segments-memory_in_bytes\": {\n    name: \"Segment内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [1, 4],\n  },\n  \"indices-segments-term_vectors_memory_in_bytes\": {\n    name: \"Terms内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [4],\n  },\n  \"indices-segments-points_memory_in_bytes\": {\n    name: \"Points内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [],\n  },\n  \"indices-segments-doc_values_memory_in_bytes\": {\n    name: \"Doc Values内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [4],\n  },\n  \"indices-segments-index_writer_memory_in_bytes\": {\n    name: \"Index Writer内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [4],\n  },\n  \"indices-query_cache-memory_size_in_bytes\": {\n    name: \"Query Cache内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [4],\n  },\n  \"indices-request_cache-memory_size_in_bytes\": {\n    name: \"Request Cache内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [4],\n  },\n  \"indices-segments-stored_fields_memory_in_bytes\": {\n    name: \"Stored Fields大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [4],\n  },\n  \"indices-segments-norms_memory_in_bytes\": {\n    name: \"Norms内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [],\n  },\n  \"indices-segments-version_map_memory_in_bytes\": {\n    name: \"Version Map内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [],\n  },\n  \"indices-segments-fixed_bit_set_memory_in_bytes\": {\n    name: \"Fixed Bitset内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [],\n  },\n  \"breakers-fielddata-estimated_size_in_bytes\": {\n    name: \"Fielddata内存大小\",\n    unit: unitMap.MB,\n    classify: indexConfigClassifyList[5],\n    indicatorType: [4],\n  },\n};\n\naddChartTitle(indexConfigData);\n\nexport const getCheckedData = (checkedList) => {\n  const defaultClassifyData = {};\n\n  indexConfigClassifyList.forEach((item) => {\n    defaultClassifyData[item] = [];\n  });\n\n  checkedList.forEach((item) => {\n    if (indexConfigData[item]) {\n      defaultClassifyData[indexConfigData[item].classify].push(item);\n    }\n  });\n\n  return defaultClassifyData;\n};\n\n//\nexport const allCheckedData = getCheckedData(Object.keys(indexConfigData));\n\ninterface defaultIndexConfigItemPropsType {\n  title: string;\n  plainOptions: { label: string; value: string }[];\n}\n\nexport const defaultIndexConfigList: defaultIndexConfigItemPropsType[] = indexConfigClassifyList.map((item) => ({\n  title: item,\n  plainOptions: allCheckedData[item].map((item) => ({\n    label: indexConfigData[item].name,\n    value: item,\n    indicatorType: indexConfigData[item].indicatorType,\n  })),\n}));\n\nexport const parseLineParams = (data) => {\n  const title = data.nodeMetricsType;\n  const xAxis = data.nodesSubMetrics[0].nodeMetricsContentCells.map((item) => item.timeStamp);\n  const series = data.nodesSubMetrics.map((item) => {\n    return {\n      name: item.nodeIp,\n      data: item.nodeMetricsContentCells.map((item) => ({\n        value: item.nodeMetricsValue,\n        timeStamp: item.timeStamp,\n      })),\n    };\n  });\n  return { title, xAxis, series };\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/node-view.tsx",
    "content": "import { TOP_MAP, TOP_TIME_RANGE, TOP_TYPE } from \"constants/status-map\";\nimport React, { memo, useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport { Collapse, TreeSelect } from \"antd\";\nimport _ from \"lodash\";\nimport { RenderLine, IndexConfig, SelectRadio } from \"../components\";\nimport { getCheckedList, setCheckedList, getNodeViewData, getNodeInfoList, getDictionary } from \"../../../api/cluster-kanban\";\nimport { objFlat } from \"../config\";\nimport { indexConfigClassifyList, defaultIndexConfigList, allCheckedData, getCheckedData, indexConfigData } from \"./node-view-config\";\nimport { asyncMicroTasks, resize, uuid } from \"../../../lib/utils\";\nimport { setIsUpdate } from \"actions/cluster-kanban\";\nimport * as actions from \"../../../actions\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport Url from \"lib/url-parser\";\nimport { OperationPanel } from \"../components/operation-panel\";\nimport \"../style/index\";\n\nconst { Panel } = Collapse;\nconst { SHOW_CHILD } = TreeSelect;\n\nexport const classPrefix = \"monitor\";\n\nconst NODE = \"node\";\n\nconst NODE_TYPE = {\n  1: \"data\",\n  2: \"client\",\n  3: \"master\",\n  4: \"tribe\",\n};\n\nexport const NodeView = memo(() => {\n  const { clusterName, startTime, endTime, isMoreDay, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      clusterName: (state as any).clusterKanban.clusterName,\n      startTime: (state as any).clusterKanban.startTime,\n      endTime: (state as any).clusterKanban.endTime,\n      isMoreDay: (state as any).clusterKanban.isMoreDay,\n      isUpdate: (state as any).clusterKanban.isUpdate,\n      timeRadioKey: (state as any).clusterKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n  const [nodeIpList, setNodeIpList] = useState([]);\n  const [update, setUpdate] = useState(false);\n  const [checkedData, setCheckedData] = useState(getCheckedData([]));\n  // 用于判断是否第一次进入页面\n  const [flag, setFlag] = useState(true);\n  const [dictionary, setDictionary] = useState({});\n\n  const selectRadioValue = useRef({\n    topNum: TOP_MAP[0].value,\n    topTimeStep: TOP_TIME_RANGE[0].value,\n    topMethod: TOP_TYPE[0].value,\n    content: [],\n  });\n\n  useEffect(() => {\n    getAsyncCheckedList();\n    _getDictionary();\n  }, []);\n\n  useEffect(() => {\n    if (Url().search?.node) {\n      selectRadioValue.current.content = [Url().search?.node];\n    }\n  }, [Url().search?.node]);\n\n  useEffect(() => {\n    getAsyncNodeViewIpList();\n  }, [clusterName]);\n\n  const sortEnd = (item, { oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(checkedData[item], oldIndex, newIndex);\n    checkedData[item] = listsNew;\n    const checkedList = objFlat(checkedData);\n    setCheckedList(NODE, checkedList);\n    setCheckedData({ ...checkedData });\n  };\n\n  const dispatch = useDispatch();\n\n  const reloadPage = () => {\n    dispatch(setIsUpdate(!isUpdate));\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(NODE);\n      if (!checkedList || checkedList.length === 0) {\n        setCheckedData(allCheckedData);\n      } else {\n        setCheckedData(getCheckedData(checkedList));\n      }\n    } catch (error) {\n      setCheckedData(allCheckedData);\n      console.log(\"cluster-kanban node-view 获取配置下项失败\", error);\n    }\n  };\n\n  const getAsyncNodeViewIpList = () => {\n    if (clusterName) {\n      try {\n        selectRadioValue.current.content = [];\n        setUpdate(!update);\n        getNodeInfoList(clusterName).then((list) => {\n          setNodeIpList(\n            list.map((item, index) => ({\n              ...item,\n              name: item.nodeName,\n              value: item.nodeName,\n              tips: NODE_TYPE[item.nodeType],\n            }))\n          );\n        });\n        selectRadioValue.current.content = Url().search?.cluster === clusterName && Url().search?.node ? [Url().search?.node] : [];\n      } catch (error) {\n        console.error(error);\n      }\n    }\n  };\n\n  const _getDictionary = async () => {\n    let params = {\n      model: \"Node\",\n    };\n    let res = await getDictionary(params);\n    let data = {} as any;\n    (res || []).forEach((item) => {\n      if (item?.metricType) {\n        data[item?.metricType] = item;\n      }\n    });\n    setDictionary(data);\n  };\n\n  const setIndexConfigCheckedData = (changeCheckedData) => {\n    const checkedList = objFlat(changeCheckedData);\n    setCheckedList(NODE, checkedList);\n    setCheckedData(changeCheckedData);\n    reloadPage();\n  };\n\n  const getAsyncNodeViewData = useCallback(\n    async (metricsTypes) => {\n      const values = (selectRadioValue.current.content || []).map((item) => {\n        return item.split(\"_\")?.[1];\n      });\n      let content = flag && Url().search?.node ? [Url().search?.node] : values;\n\n      setFlag(false);\n      return await getNodeViewData(\n        metricsTypes,\n        clusterName,\n        startTime,\n        endTime,\n        selectRadioValue.current.topNum,\n        content,\n        selectRadioValue.current.topMethod,\n        selectRadioValue.current.topTimeStep\n      );\n    },\n    [clusterName, startTime, endTime, timeRadioKey]\n  );\n\n  const onSelectRadioChange = (values, needReload) => {\n    selectRadioValue.current = values;\n    if (needReload) {\n      reloadPage();\n    }\n  };\n\n  const renderTopWhat = () => {\n    const options = [];\n    for (let item of nodeIpList) {\n      const index = options.findIndex((row) => row.value === item.nodeType);\n      if (index < 0) {\n        options.push({\n          title: <span className=\"parent\">{item.tips}</span>,\n          value: item.nodeType,\n          key: uuid(),\n          children: [\n            {\n              title: <span className=\"child\">{item.nodeName}</span>,\n              value: item.nodeType + \"_\" + item.nodeName,\n            },\n          ],\n        });\n      } else {\n        options[index].children.push({\n          title: <span className=\"child\">{item.nodeName}</span>,\n          value: item.nodeType + \"_\" + item.nodeName,\n          key: uuid(),\n        });\n      }\n    }\n    return (\n      <SelectRadio\n        onValueChange={onSelectRadioChange}\n        content={selectRadioValue.current.content || []}\n        contentList={options}\n        placeholder=\"请选择节点名称\"\n        type=\"treeSelect\"\n      />\n    );\n  };\n\n  const renderConfig = () => {\n    return (\n      <IndexConfig\n        title=\"节点指标配置\"\n        optionList={defaultIndexConfigList}\n        checkedData={checkedData}\n        setCheckedData={setIndexConfigCheckedData}\n        needShortcut={true}\n      />\n    );\n  };\n\n  const renderFilter = () => {\n    return (\n      <>\n        {renderTopWhat()}\n        {renderConfig()}\n      </>\n    );\n  };\n\n  const ShowTaskTooltipModal = (clusterPhyName, node, time) => {\n    dispatch(\n      actions.setModalId(\"chartTableModal\", {\n        clusterPhyName,\n        node,\n        time,\n      })\n    );\n  };\n\n  useEffect(() => {\n    window[\"showTaskTooltipModal\"] = (clusterPhyName, node, time) => {\n      ShowTaskTooltipModal(clusterPhyName, node, time);\n    };\n  }, []);\n\n  const RenderContent = useMemo(\n    () => (\n      <div className={`${classPrefix}-overview-content`}>\n        {indexConfigClassifyList.map((item, index) => {\n          if (checkedData[item] && checkedData[item].length > 0) {\n            return (\n              <Collapse\n                defaultActiveKey={[index]}\n                onChange={() => {\n                  asyncMicroTasks(resize);\n                }}\n                style={{ marginTop: 20 }}\n                key={item + index}\n              >\n                <Panel header={item} key={index}>\n                  <div className={`${classPrefix}-overview-content-line content-margin-top-20`}>\n                    {checkedData[item] && checkedData[item].length ? (\n                      <RenderLine\n                        dictionary={dictionary}\n                        metricsTypes={checkedData[item]}\n                        key={item + index + selectRadioValue.current.topNum + clusterName}\n                        configData={indexConfigData}\n                        isMoreDay={isMoreDay}\n                        getAsyncViewData={getAsyncNodeViewData}\n                        startTime={startTime}\n                        endTime={endTime}\n                        clusterPhyName={clusterName}\n                        sortEnd={sortEnd}\n                        item={item}\n                      />\n                    ) : (\n                      \"\"\n                    )}\n                  </div>\n                </Panel>\n              </Collapse>\n            );\n          }\n        })}\n      </div>\n    ),\n    [startTime, endTime, timeRadioKey, checkedData, indexConfigClassifyList, update, dictionary]\n  );\n\n  return (\n    <>\n      <OperationPanel classPrefix={classPrefix} reloadPage={reloadPage} endTime={endTime} renderFilter={renderFilter} />\n      {RenderContent}\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/overview-line-shard.tsx",
    "content": "import React, { memo, useEffect, useState, useRef } from \"react\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport { Spin } from \"antd\";\nimport { Line, Shard } from \"../components\";\nimport { getOverviewOption } from \"./overview-view-config\";\nimport { LINE, SHARD, metricsDataType, indexConfigData } from \"./overview-view-config\";\nimport { getOverviewData } from \"../../../api/cluster-kanban\";\nimport _, { forEach } from \"lodash\";\nimport DragGroup from \"../../../d1-packages/drag-group/DragGroup\";\nimport { setIsUpdate, setClusterKanban } from \"actions/cluster-kanban\";\nimport InfoTooltip from \"component/infoTooltip\";\n\ninterface propsType {\n  metricsTypes: string[];\n  sortEnd?: any;\n  item?: string;\n  dictionary?: any;\n}\n\nexport const LineShard: React.FC<propsType> = memo(({ metricsTypes, sortEnd, item, dictionary }) => {\n  const { clusterName, startTime, endTime, isMoreDay, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      clusterName: (state as any).clusterKanban.clusterName,\n      startTime: (state as any).clusterKanban.startTime,\n      endTime: (state as any).clusterKanban.endTime,\n      isMoreDay: (state as any).clusterKanban.isMoreDay,\n      isUpdate: (state as any).clusterKanban.isUpdate,\n      timeRadioKey: (state as any).clusterKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n\n  const [data, setData] = useState({});\n  // const metricsTypes = [metricsType, \"searchLatency\"];\n  const [currentTime, setCurrentTime] = useState(\"\");\n  const [isLoading, setIsLoading] = useState(true);\n  const isFirst = useRef(true);\n  const timeDiff = useRef(0);\n  const oldClusterName = useRef(clusterName);\n  const dispatch = useDispatch();\n  const getLineOption = (lineConfig, data) => {\n    if (!data) {\n      return;\n    }\n    return getOverviewOption(lineConfig.info.title, data, lineConfig.info.data, lineConfig.info.list, lineConfig.unit, isMoreDay);\n  };\n\n  const getShardOption = (shardConfig, data) => {\n    if (!data) {\n      return;\n    }\n    return data.map(shardConfig.mapFn);\n  };\n\n  const getOption = (LineShardData, metricsType) => {\n    const metricsConfig = _.cloneDeep(metricsDataType[metricsType]);\n    // 针对合并数据做特殊处理\n    let data = [];\n    if (indexConfigData[metricsType] && indexConfigData[metricsType].types) {\n      indexConfigData[metricsType].types.forEach((type) => {\n        data.push(...LineShardData[type]);\n      });\n    } else {\n      data = LineShardData[metricsType];\n    }\n    // 判断是折线图还是表格\n    if (metricsConfig.type === LINE) {\n      return data && data.length ? getLineOption(metricsConfig, data) : {};\n    } else {\n      return data && data.length ? getShardOption(metricsConfig, LineShardData[metricsType]) : [];\n    }\n  };\n\n  const getOverviewLineShardData = async () => {\n    if (!clusterName) {\n      setIsLoading(false);\n      return;\n    }\n    setIsLoading(true);\n    try {\n      // 针对合并数据做特殊处理\n      let newMetricsTypes = [];\n      metricsTypes.forEach((item) => {\n        if (indexConfigData[item] && indexConfigData[item].types) {\n          newMetricsTypes.push(...indexConfigData[item].types);\n        } else {\n          newMetricsTypes.push(item);\n        }\n      });\n      const LineShardData = await getOverviewData(newMetricsTypes, clusterName, startTime, endTime);\n      const data = {};\n      //保存配置化标题的值bigShardThreshold\n      dispatch(\n        setClusterKanban({\n          bigShardThreshold: LineShardData?.bigShardThreshold,\n        })\n      );\n      metricsTypes.forEach((item) => {\n        data[item] = getOption(LineShardData, item);\n      });\n      setData(data);\n      setCurrentTime(LineShardData[\"currentTime\"] || 0);\n    } catch (error) {\n      console.log(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    if (isFirst.current || timeDiff.current !== endTime - startTime || oldClusterName.current !== clusterName) {\n      timeDiff.current = endTime - startTime;\n      isFirst.current = false;\n      oldClusterName.current = clusterName;\n    }\n    getOverviewLineShardData();\n  }, [isMoreDay, metricsTypes, clusterName, startTime, endTime, timeRadioKey, getOverviewData]);\n\n  const renderLineShard = (metricsType) => {\n    const metricsConfig = metricsDataType[metricsType];\n    if (!metricsConfig) {\n      return \"\";\n    }\n    let dict = dictionary[metricsType];\n    let tooltip =\n      dict?.currentCalLogic || dict?.price || dict?.threshold ? (\n        <InfoTooltip\n          className=\"indicators-info\"\n          currentCalLogic={dict?.currentCalLogic}\n          price={dict?.price}\n          threshold={dict?.threshold}\n        ></InfoTooltip>\n      ) : null;\n    if (metricsConfig.type === LINE) {\n      return (\n        <Line\n          title={metricsConfig?.info?.title || \"\"}\n          tooltip={tooltip}\n          key={metricsType}\n          index={\"overview-view-line-ele-id\" + metricsType}\n          isLoading={isLoading}\n          option={data[metricsType]}\n          connectGroupName={\"cluster-overview\"}\n        />\n      );\n    }\n    //table\n    return (\n      <Shard\n        currentTime={currentTime}\n        title={metricsConfig.title || \"\"}\n        tooltip={tooltip}\n        key={metricsType}\n        dataSource={data[metricsType]}\n        shardColumns={metricsConfig.shardColumn}\n        isLoading={isLoading}\n      />\n    );\n  };\n\n  return (\n    <>\n      <DragGroup\n        dragContainerProps={{\n          onSortEnd: (args) => sortEnd(item, { ...args }),\n          axis: \"xy\",\n          distance: 100,\n        }}\n        containerProps={{\n          grid: 12,\n          gutter: [10, 10],\n        }}\n      >\n        {metricsTypes.map((item) => renderLineShard(item))}\n      </DragGroup>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/overview-view-basic.tsx",
    "content": "import React, { memo, useEffect, useState } from \"react\";\nimport { useSelector, shallowEqual } from \"react-redux\";\nimport { Skeleton } from \"antd\";\nimport { StateConfig, ContrastFigure } from \"../components\";\n\nimport { getContrastChartProps } from \"./config\";\nimport { getOverviewData } from \"../../../api/cluster-kanban\";\nimport { toFixedNum } from \"../../../lib/utils\";\ninterface propsType {\n  reload?: boolean;\n}\ninterface basicPropsType {\n  // memFreePercent?: number; // 空闲内存百分比\n  heapFreeUsage?: number; // 堆空闲内存百分比\n  // memUsedPercent?: number; // 已用内存百分比\n  heapUsage?: number; // 堆已用内存百分比\n  storeUsage?: number; // 已用磁盘百分比\n  storeFreeUsage?: number; // 空闲磁盘百分比\n  activeNodeNu?: number; // 活跃节点数\n  clusterName?: string; // 物理集群名称\n  freeStoreSize?: number; // 空闲磁盘\n  invalidNodeNu?: number; // 死亡节点\n  heapMemFree?: number; // 堆空闲内存\n  // memFree?: number; // 空闲内存\n  heapMemTotal?: number; // 堆内存总量\n  // memTotal?: number; // 内存总量\n  heapMemUsed?: number; // 堆已用内存\n  // memUsed?: number; // 已用内存\n  numberClientNodes?: number; // Clientnode节点数\n  numberDataNodes?: number; // Datanode节点数\n  numberIngestNode?: number; // IngestNode节点数\n  numberMasterNodes?: number; // Masternode节点数\n  numberNodes?: number; //节点总数\n  physicCluster?: number; //是否是物理集群\n  shardNu?: number; // Shard数量\n  status?: string; // 集群状态 number gree 1 yellow 2 red\n  storeSize?: number; // 磁盘已使用容量\n  totalDocNu?: number; //文档总数\n  totalIndicesNu?: number; // 索引数目\n  totalStoreSize?: number; // 磁盘总容量\n  totalTemplateNu?: number; // 索引模板数目\n  [key: string]: any;\n}\n\nexport const overviewClassPrefix = \"monitor\";\n\nexport const OverviewViewBasic: React.FC<propsType> = memo(({ reload }) => {\n  const { clusterName, startTime, endTime, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      clusterName: (state as any).clusterKanban.clusterName,\n      startTime: (state as any).clusterKanban.startTime,\n      endTime: (state as any).clusterKanban.endTime,\n      isMoreDay: (state as any).clusterKanban.isMoreDay,\n      isUpdate: (state as any).clusterKanban.isUpdate,\n      timeRadioKey: (state as any).clusterKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n  const [basic, setBasic] = useState<basicPropsType>({});\n  const [isLoading, setIsLoading] = useState(true);\n\n  const getOverviewBasicData = async () => {\n    if (!clusterName) {\n      setIsLoading(false);\n      return;\n    }\n\n    setIsLoading(true);\n    try {\n      const { basic } = await getOverviewData([\"basic\"], clusterName, startTime, endTime);\n      setBasic(basic);\n    } catch (error) {\n      setBasic({});\n      console.log(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const bytesToGB = (num: number) => {\n    if (!num) {\n      return 0;\n    }\n    return Number((num / 1024 / 1024 / 1024).toFixed(2));\n  };\n\n  useEffect(() => {\n    getOverviewBasicData();\n  }, [clusterName, reload, startTime, endTime, timeRadioKey]);\n\n  // 总揽视图列表\n  const stateConfigurationList = [\n    {\n      id: 1,\n      name: \"集群状态\",\n      state: basic.status || \"red\",\n    },\n    {\n      id: 2,\n      name: \"Shard总数\",\n      count: basic.shardNu || 0,\n      unit: \"个\",\n    },\n    {\n      id: 3,\n      name: \"未分配Shard数\",\n      count: basic.unassignedShardNum || 0,\n      unit: \"个\",\n    },\n    {\n      id: 4,\n      name: \"索引模板数\",\n      count: basic.totalTemplateNu || 0,\n      unit: \"个\",\n    },\n    {\n      id: 5,\n      name: \"文档总数\",\n      count: basic.totalDocNu || 0,\n      unit: \"个\",\n    },\n    {\n      id: 6,\n      name: \"索引数\",\n      count: basic.totalIndicesNu || 0,\n      unit: \"个\",\n    },\n    {\n      id: 7,\n      name: \"集群索引存储量\",\n      count: bytesToGB(basic.indicesStoreSize) || 0,\n      unit: \"GB\",\n    },\n  ];\n\n  const nodeDistributionList = [\n    {\n      id: 1,\n      name: \"Masternode\",\n      count: basic.numberMasterNodes || 0,\n      unit: \"个\",\n    },\n    {\n      id: 2,\n      name: \"Datatnode\",\n      count: basic.numberDataNodes || 0,\n      unit: \"个\",\n    },\n    {\n      id: 3,\n      name: \"Clientnode\",\n      count: basic.numberClientNodes || 0,\n      unit: \"个\",\n    },\n  ];\n\n  const decimalToPercent = (val) => {\n    if (!val) {\n      return 0;\n    }\n    val = val * 100;\n    if (parseInt(val) != val) {\n      return toFixedNum(Number(val), 2);\n    }\n    return val;\n  };\n\n  // const memUsed = bytesToGB(basic.memUsed) || 0;\n  const heapMemUsed = bytesToGB(basic?.heapMemUsed) || 0;\n  // const memFree = bytesToGB(basic.memFree) || 0;\n  const heapMemFree = bytesToGB(basic?.heapMemFree) || 0;\n  // const memTotal = toFixedNum(memUsed + memFree) || 0;\n  const heapMemTotal = toFixedNum(heapMemUsed + heapMemFree) || 0;\n  // const memUsedPercent = toFixedNum(basic.memUsedPercent) || 0;\n  const heapUsage = toFixedNum(basic?.heapUsage) || 0;\n  // decimalToPercent(memUsed / memTotal) || 0;\n  // const memFreePercent = toFixedNum(basic.memFreePercent) || 0;\n  const heapFreeUsage = toFixedNum(basic?.heapFreeUsage) || 0;\n  // toFixedNum(100 - memUsedPercent) || 0;\n\n  const storeSize = bytesToGB(basic.storeSize) || 0;\n  const freeStoreSize = bytesToGB(basic.freeStoreSize) || 0;\n  const diskTotal = toFixedNum(storeSize + freeStoreSize) || 0;\n  const diskStoreUsage = toFixedNum(basic.storeUsage) || 0;\n  // decimalToPercent(storeSize / diskTotal) || 0;\n  const diskFreeUsage = toFixedNum(basic.storeFreeUsage) || 0;\n  // toFixedNum(100 - diskStoreUsage) || 0;\n\n  const activeNodeNu = basic.activeNodeNu || 0;\n  const invalidNodeNu = basic.invalidNodeNu || 0;\n  const nodeNuTotal = toFixedNum(activeNodeNu + invalidNodeNu) || 0;\n  const activeNodeNuPercent = decimalToPercent(activeNodeNu / nodeNuTotal) || 0;\n  const invalidNodeNuPercent = invalidNodeNu ? toFixedNum(100 - activeNodeNuPercent) || 0 : 0;\n\n  const memLegendVal = {\n    堆已用内存: {\n      value: heapMemUsed + \"GB\",\n      percent: heapUsage,\n    },\n    堆空闲内存: {\n      value: heapMemFree + \"GB\",\n      percent: heapFreeUsage,\n    },\n  };\n\n  const memoryContrastEChartsData = [\n    {\n      value: heapMemUsed,\n      name: \"堆已用内存\",\n    },\n    {\n      value: heapMemFree,\n      name: \"堆空闲内存\",\n    },\n  ];\n\n  const memoryContrastSubtext = heapMemTotal;\n\n  const diskLegendVal = {\n    已用磁盘: {\n      value: storeSize + \"GB\",\n      percent: diskStoreUsage,\n    },\n    空闲磁盘: {\n      value: freeStoreSize + \"GB\",\n      percent: diskFreeUsage,\n    },\n  };\n\n  const diskContrastEChartsData = [\n    {\n      value: storeSize,\n      name: \"已用磁盘\",\n    },\n    {\n      value: freeStoreSize,\n      name: \"空闲磁盘\",\n    },\n  ];\n  const diskContrastSubtext = diskTotal;\n\n  const nodeLegendVal = {\n    活跃节点数: {\n      value: activeNodeNu + \"个\",\n      percent: activeNodeNuPercent,\n    },\n    死亡节点数: {\n      value: invalidNodeNu + \"个\",\n      percent: invalidNodeNuPercent,\n    },\n  };\n\n  const nodeContrastEChartsData = [\n    {\n      value: activeNodeNu,\n      name: \"活跃节点数\",\n    },\n    {\n      value: invalidNodeNu,\n      name: \"死亡节点数\",\n    },\n  ];\n  const nodeContrastSubtext = nodeNuTotal || 0;\n\n  return (\n    <>\n      {isLoading ? (\n        <>\n          <Skeleton active />\n          <Skeleton active />\n          <Skeleton active paragraph={{ rows: 2 }} />\n        </>\n      ) : (\n        <>\n          <div className={`${overviewClassPrefix}-overview-content-config-box-view`}>\n            <div className={`${overviewClassPrefix}-overview-content-config-box-view-state-config`}>\n              <StateConfig className=\"status-overview\" list={stateConfigurationList} title=\"状态概览\" />\n            </div>\n            <div className={`${overviewClassPrefix}-overview-content-config-box-view-memory-map`}>\n              <div className={`${overviewClassPrefix}-overview-content-config-box-view-memory-map-view`}>\n                <ContrastFigure\n                  id=\"memory-view\"\n                  legendVal={memLegendVal}\n                  unit=\"GB\"\n                  {...getContrastChartProps(\"堆内存\", memoryContrastEChartsData, memoryContrastSubtext)}\n                />\n              </div>\n              <div className=\"vertical-line\"></div>\n              <div className={`${overviewClassPrefix}-overview-content-config-box-view-memory-map-view`}>\n                <ContrastFigure\n                  id=\"disk-view\"\n                  legendVal={diskLegendVal}\n                  unit=\"GB\"\n                  {...getContrastChartProps(\"磁盘\", diskContrastEChartsData, diskContrastSubtext)}\n                />\n              </div>\n            </div>\n          </div>\n          <div className={`${overviewClassPrefix}-overview-content-config-box-node-distribution`}>\n            <StateConfig list={nodeDistributionList} title=\"节点分配\" />\n            <div className=\"cross-line\"></div>\n            <ContrastFigure\n              id=\"node-view\"\n              legendVal={nodeLegendVal}\n              unit=\"个\"\n              tooltipDirection=\"left\"\n              {...getContrastChartProps(\"节点\", nodeContrastEChartsData, nodeContrastSubtext, [\"#1473FF\", \"#D3DAE7\"])}\n            />\n          </div>\n        </>\n      )}\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/overview-view-config.tsx",
    "content": "import React from \"react\";\nimport { Tag, Popover, Button, Tooltip } from \"antd\";\nimport { getLineOption, unitMap } from \"./config\";\nimport { formatDecimalPoint } from \"lib/utils\";\nimport _ from \"lodash\";\n\n// 指标配置 start\nexport const indexConfigClassifyList: string[] = [\"系统指标\", \"性能指标\", \"状态指标\"];\n\nexport const indexConfigData = {\n  cpuUsage: {\n    name: \"CPU使用率\",\n    classify: indexConfigClassifyList[0],\n    indicatorType: [1, 2, 3],\n  },\n  cpuLoad1M: {\n    name: \"CPU 1分钟负载\",\n    classify: indexConfigClassifyList[0],\n    indicatorType: [2, 3],\n  },\n  diskUsage: {\n    name: \"磁盘使用率\",\n    classify: indexConfigClassifyList[0],\n    indicatorType: [1, 4],\n  },\n  diskInfo: {\n    name: \"磁盘使用情况\",\n    classify: indexConfigClassifyList[0],\n    indicatorType: [],\n  },\n  // 特殊的指标前端做合并\n  networkFlow: {\n    name: \"网络流量\",\n    types: [\"recvTransSize\", \"sendTransSize\"],\n    classify: indexConfigClassifyList[0],\n    indicatorType: [],\n  },\n  // recvTransSize: {\n  //   name: \"网络入口流量\",\n  //   classify: indexConfigClassifyList[0],\n  //   indicatorType: [],\n  // },\n  // sendTransSize: {\n  //   name: \"网络出口流量\",\n  //   classify: indexConfigClassifyList[0],\n  //   indicatorType: [],\n  // },\n  readTps: {\n    name: \"查询QPS\",\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1],\n  },\n  writeTps: {\n    name: \"写入TPS\",\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1],\n  },\n  searchLatency: {\n    name: \"查询耗时\",\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  indexingLatency: {\n    name: \"写入耗时\",\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2],\n  },\n  taskCost: {\n    name: \"执行任务耗时\",\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2, 3, 4],\n  },\n  taskCount: {\n    name: \"执行任务数量\",\n    classify: indexConfigClassifyList[1],\n    indicatorType: [1, 2, 3, 4],\n  },\n  movingShards: {\n    name: \"迁移中shard列表\",\n    classify: indexConfigClassifyList[2],\n    indicatorType: [1, 2, 3, 4],\n  },\n  unAssignShards: {\n    name: \"未分配Shard列表\",\n    classify: indexConfigClassifyList[2],\n    indicatorType: [1, 2, 3, 4],\n  },\n  invalidNodes: {\n    name: \"Dead节点列表\",\n    classify: indexConfigClassifyList[2],\n    indicatorType: [1, 2, 3, 4],\n  },\n  pendingTasks: {\n    name: \"PendingTask列表\",\n    classify: indexConfigClassifyList[2],\n    indicatorType: [1, 2, 3, 4],\n  },\n  // elapsedTime: {\n  //   name: \"_cluster_stats 接口平均采集耗时\",\n  //   classify: indexConfigClassifyList[1],\n  // }\n};\n\nexport const getCheckedData = (checkedList) => {\n  const defaultClassifyData = {};\n  indexConfigClassifyList.forEach((item) => {\n    defaultClassifyData[item] = [];\n  });\n  checkedList.forEach((item) => {\n    if (indexConfigData[item]) {\n      defaultClassifyData[indexConfigData[item].classify].push(item);\n    }\n  });\n  return defaultClassifyData;\n};\n\nexport const allCheckedData = getCheckedData(Object.keys(indexConfigData));\n\ninterface defaultIndexConfigItemPropsType {\n  title: string;\n  plainOptions: { label: string; value: string }[];\n}\n\nexport const defaultIndexConfigList: defaultIndexConfigItemPropsType[] = indexConfigClassifyList.map((item) => ({\n  title: item,\n  plainOptions: allCheckedData[item].map((item) => ({\n    label: indexConfigData[item].name,\n    value: item,\n    indicatorType: indexConfigData[item].indicatorType,\n  })),\n}));\n// 指标配置 end\n\n// 折线图\ninterface dataType {\n  [key: string]: number;\n}\ninterface lineDataType {\n  [key: string]: {\n    name: string;\n    data: number[];\n  };\n}\n\nexport const getOverviewOption = (\n  title: string,\n  data: dataType[],\n  lineData: lineDataType,\n  lineSeriesKeys: string[],\n  unitMap: {},\n  isMoreDay: boolean = false,\n  isMarkLine: boolean = false\n) => {\n  data.sort((a, b) => a.timeStamp - b.timeStamp);\n\n  data.forEach((item) => {\n    for (let key in item) {\n      if (lineData[key]) {\n        lineData[key].data.push(item[key]);\n      }\n    }\n  });\n\n  const xAxisData = [...new Set(lineData.timeStamp.data)];\n\n  const series = lineSeriesKeys.map((item) => lineData[item]);\n\n  return getLineOption({ title, xAxisData, series, unitMap, isMoreDay, isMarkLine });\n};\n\nconst legendInfo = {\n  aggType: {\n    name: \"平均分位值\",\n    data: [],\n  },\n  st99: {\n    name: \"99分位值\",\n    data: [],\n  },\n  st95: {\n    name: \"95分位值\",\n    data: [],\n  },\n  st75: {\n    name: \"75分位值\",\n    data: [],\n  },\n  st55: {\n    name: \"55分位值\",\n    data: [],\n  },\n  timeStamp: {\n    name: \"时间戳\",\n    data: [],\n  },\n};\n\nconst getObjKeys = (obj) => {\n  return Object.keys(obj).filter((item) => item !== \"timeStamp\");\n};\n\n// cpu 使用率\nexport const cpuUsageData: lineDataType = _.cloneDeep(legendInfo);\n\nexport const cpuUsageList = getObjKeys(cpuUsageData);\n\nexport const cpuUsageObj = {\n  title: \"CPU 使用率(%)\",\n  data: cpuUsageData,\n  list: cpuUsageList,\n};\n\n// cpu 1分钟负载\nconst cpuLoad1MData = _.cloneDeep(legendInfo);\n\nconst cpuLoad1MList = getObjKeys(cpuLoad1MData);\n\nconst cpuLoad1MObj = {\n  title: \"CPU 1分钟负载\",\n  data: cpuLoad1MData,\n  list: cpuLoad1MList,\n};\n\n// 磁盘使用率\nexport const diskUsageData: lineDataType = _.cloneDeep(legendInfo);\n\nexport const diskUsageList = getObjKeys(diskUsageData);\n\nexport const diskUsageObj = {\n  title: \"磁盘使用率(%)\",\n  data: diskUsageData,\n  list: diskUsageList,\n};\n\n// 磁盘使用情况(GB)\nexport const diskInfoData: lineDataType = {\n  freeStoreSize: {\n    name: \"磁盘空闲量\",\n    data: [],\n  },\n  storeSize: {\n    name: \"磁盘使用量\",\n    data: [],\n  },\n  totalStoreSize: {\n    name: \"磁盘总量\",\n    data: [],\n  },\n  timeStamp: {\n    name: \"时间戳\",\n    data: [],\n  },\n};\n\nexport const diskInfoList = getObjKeys(diskInfoData);\n\nexport const diskInfoObj = {\n  title: \"磁盘使用情况(GB)\",\n  data: diskInfoData,\n  list: diskInfoList,\n};\n\n// 写入TPS\nexport const writeTpsData: lineDataType = {\n  writeTps: {\n    name: \"写入TPS\",\n    data: [],\n  },\n  timeStamp: {\n    name: \"时间戳\",\n    data: [],\n  },\n};\n\nexport const writeTpsList = getObjKeys(writeTpsData);\n\nexport const writeTpsObj = {\n  title: \"写入TPS(个/S)\",\n  data: writeTpsData,\n  list: writeTpsList,\n};\n\n// 网络出口流量\nexport const networkFlowData = {\n  recvTransSize: {\n    name: \"网络入口流量\",\n    data: [],\n  },\n  sendTransSize: {\n    name: \"网络出口流量\",\n    data: [],\n  },\n  timeStamp: {\n    name: \"时间戳\",\n    data: [],\n  },\n};\n\nexport const networkFlowList = getObjKeys(networkFlowData);\n\nexport const networkFlowObj = {\n  title: \"网络流量(MB/S)\",\n  data: networkFlowData,\n  list: networkFlowList,\n};\n\n// // 网络入口流量\n// export const recvTransSizeData = {\n//   recvTransSize: {\n//     name: \"网络入口流量\",\n//     data: [],\n//   },\n//   timeStamp: {\n//     name: \"时间戳\",\n//     data: [],\n//   },\n// };\n\n// export const recvTransSizeList = getObjKeys(recvTransSizeData);\n\n// export const recvTransSizeObj = {\n//   title: \"网络入口流量(MB/s)\",\n//   data: recvTransSizeData,\n//   list: recvTransSizeList,\n// };\n\n// 查询耗时\nexport const searchLatencyData = _.cloneDeep(legendInfo);\n\nexport const searchLatencyList = getObjKeys(searchLatencyData);\n\nexport const searchLatencyObj = {\n  title: \"查询耗时(MS)\",\n  data: searchLatencyData,\n  list: searchLatencyList,\n};\n\n// task 耗时taskCost\nexport const taskCostData = _.cloneDeep(legendInfo);\n\nexport const taskCostList = getObjKeys(taskCostData);\n\nexport const taskCostObj = {\n  title: \"执行任务耗时(S)\",\n  data: taskCostData,\n  list: taskCostList,\n};\n\n// 查询QPS\nexport const readTpsData = {\n  readTps: {\n    name: \"查询QPS\",\n    data: [],\n  },\n  timeStamp: {\n    name: \"时间戳\",\n    data: [],\n  },\n};\n\nexport const readTpsList = getObjKeys(readTpsData);\n\nexport const readTpsObj = {\n  title: \"查询QPS(次/S)\",\n  data: readTpsData,\n  list: readTpsList,\n};\n\n// taskCount task数量趋势\nexport const taskCountData = {\n  taskCount: {\n    name: \"执行任务数量\",\n    data: [],\n  },\n  timeStamp: {\n    name: \"时间戳\",\n    data: [],\n  },\n};\n\nexport const taskCountList = getObjKeys(taskCountData);\n\nexport const taskCountObj = {\n  title: \"执行任务数量(个/S)\",\n  data: taskCountData,\n  list: taskCountList,\n};\n\n// export const elapsedTimeData: lineDataType = {\n//   elapsedTime: {\n//     name: \"采集耗时\",\n//     data: [],\n//   },\n//   timeStamp: {\n//     name: \"时间戳\",\n//     data: [],\n//   },\n// };\n\n// export const elapsedTimeList = getObjKeys(elapsedTimeData);\n\n// export const elapsedTimeObj = {\n//   title: \"_cluster_stats 接口平均采集耗时(ms)\",\n//   data: elapsedTimeData,\n//   list: elapsedTimeList,\n// };\n\n// 写入耗时\nexport const indexingLatencyData = _.cloneDeep(legendInfo);\n\nexport const indexingLatencyList = getObjKeys(indexingLatencyData);\n\nexport const indexingLatencyObj = {\n  title: \"写入耗时(MS)\",\n  data: indexingLatencyData,\n  list: indexingLatencyList,\n};\n\n// shard\nexport const movingShardColumns = [\n  {\n    title: \"承载索引\",\n    dataIndex: \"i\",\n    key: \"i\",\n  },\n  {\n    title: \"源节点IP\",\n    dataIndex: \"shost\",\n    key: \"shost\",\n  },\n  {\n    title: \"目标节点IP\",\n    dataIndex: \"thost\",\n    key: \"thost\",\n  },\n  {\n    title: \"恢复的字节数\",\n    dataIndex: \"br\",\n    key: \"br\",\n  },\n  {\n    title: \"字节数占比\",\n    dataIndex: \"bp\",\n    key: \"bp\",\n  },\n  {\n    title: \"转换日志操作占比\",\n    dataIndex: \"top\",\n    key: \"top\",\n  },\n];\n\nexport const unassignShardColumns = [\n  {\n    title: \"归属索引\",\n    dataIndex: \"index\",\n    key: \"index\",\n  },\n  {\n    title: \"shard标识\",\n    dataIndex: \"shard\",\n    key: \"shard\",\n  },\n  {\n    title: \"主/备\",\n    dataIndex: \"prirep\",\n    key: \"prirep\",\n  },\n  {\n    title: \"状态\",\n    dataIndex: \"state\",\n    key: \"state\",\n  },\n];\n\nexport const bigShardColumns = [\n  {\n    title: \"Shard序号\",\n    dataIndex: \"shard\",\n    key: \"shard\",\n  },\n  {\n    title: \"承载索引\",\n    dataIndex: \"index\",\n    key: \"index\",\n  },\n  {\n    title: \"主/备\",\n    dataIndex: \"prirep\",\n    key: \"prirep\",\n  },\n  {\n    title: \"所属节点\",\n    dataIndex: \"node\",\n    key: \"node\",\n  },\n  {\n    title: \"所属Ip\",\n    dataIndex: \"ip\",\n    key: \"ip\",\n  },\n  {\n    title: \"容量\",\n    dataIndex: \"store\",\n    key: \"store\",\n    render: (text) => formatDecimalPoint(text),\n  },\n];\n\nexport const invalidNodesColumns = [\n  {\n    title: \"节点IP\",\n    dataIndex: \"ip\",\n    key: \"ip\",\n    render: (_, record) => {\n      return record?.deadNode?.ip || \"-\";\n    },\n  },\n  {\n    title: \"主机名\",\n    dataIndex: \"hostname\",\n    key: \"hostname\",\n    render: (_, record) => {\n      return record?.deadNode?.hostname || \"-\";\n    },\n  },\n  {\n    title: \"实例名\",\n    dataIndex: \"cluster\",\n    key: \"cluster\",\n    render: (_, record) => {\n      return record?.deadNode?.cluster || \"-\";\n    },\n  },\n];\n\nexport const pendingTasksColumns = [\n  {\n    title: \"插入顺序\",\n    dataIndex: \"insertOrder\",\n    key: \"insertOrder\",\n  },\n  {\n    title: \"优先级\",\n    dataIndex: \"priority\",\n    key: \"priority\",\n  },\n  {\n    title: \"任务来源说明\",\n    dataIndex: \"source\",\n    key: \"source\",\n  },\n  {\n    title: \"执行任务前等待时间\",\n    dataIndex: \"timeInQueue\",\n    key: \"timeInQueue\",\n  },\n];\n\nexport const LINE = \"line\";\nexport const SHARD = \"shard\";\ninterface metricsDataType {\n  [key: string]: {\n    type: string;\n    info?: any;\n    title?: string;\n    shardColumn?: any;\n    mapFn?: any;\n    unit?: any;\n  };\n}\n\nconst ellipsis = (str: string | number, num: number = 10) => {\n  return String(str).length > num ? (\n    <Tooltip placement=\"top\" title={str}>\n      {String(str).substring(0, num) + \"...\"}\n    </Tooltip>\n  ) : (\n    str\n  );\n};\n\nconst shardColumnEllipsis = (map, num = 10) => {\n  for (let key in map) {\n    if (key !== \"key\") {\n      map[key] = ellipsis(map[key], num);\n    }\n  }\n  return map;\n};\n\nexport const metricsDataType: metricsDataType = {\n  cpuUsage: {\n    type: LINE,\n    info: cpuUsageObj,\n    unit: unitMap.none,\n  },\n  cpuLoad1M: {\n    type: LINE,\n    info: cpuLoad1MObj,\n    unit: unitMap.none,\n  },\n  diskUsage: {\n    type: LINE,\n    info: diskUsageObj,\n    unit: unitMap.percent,\n  },\n  diskInfo: {\n    type: LINE,\n    info: diskInfoObj,\n    unit: unitMap.GB,\n  },\n  writeTps: {\n    type: LINE,\n    info: writeTpsObj,\n    unit: unitMap.countS,\n  },\n  // sendTransSize: {\n  //   type: LINE,\n  //   info: sendTransSizeObj,\n  //   unit: unitMap.mbS,\n  // },\n  searchLatency: {\n    type: LINE,\n    info: searchLatencyObj,\n    unit: unitMap.ms,\n  },\n  taskCost: {\n    type: LINE,\n    info: taskCostObj,\n    unit: unitMap.s,\n  },\n  // elapsedTime: {\n  //   type: LINE,\n  //   info: elapsedTimeObj,\n  //   unit: unitMap.ms,\n  // },\n  networkFlow: {\n    type: LINE,\n    info: networkFlowObj,\n    unit: unitMap.mbS,\n  },\n  // recvTransSize: {\n  //   type: LINE,\n  //   info: recvTransSizeObj,\n  //   unit: unitMap.mbS,\n  // },\n  readTps: {\n    type: LINE,\n    info: readTpsObj,\n    unit: unitMap.countS,\n  },\n  taskCount: {\n    type: LINE,\n    info: taskCountObj,\n    unit: unitMap.countS,\n  },\n  indexingLatency: {\n    type: LINE,\n    info: indexingLatencyObj,\n    unit: unitMap.ms,\n  },\n  movingShards: {\n    type: SHARD,\n    title: \"迁移中shard列表\",\n    shardColumn: movingShardColumns,\n    mapFn: (item, index) =>\n      shardColumnEllipsis(\n        {\n          key: index + \"\" + item.i + item.shost + item.thost,\n          i: item.i,\n          shost: item.shost,\n          thost: item.thost,\n          br: item.br,\n          bp: item.bp,\n          top: item.top,\n        },\n        6\n      ),\n  },\n  unAssignShards: {\n    type: SHARD,\n    title: \"未分配Shard列表\",\n    shardColumn: unassignShardColumns,\n    mapFn: (item, index) =>\n      shardColumnEllipsis(\n        {\n          key: index + \"\" + item.shard + item.prirep + item.state,\n          index: item.index,\n          prirep: item.prirep,\n          shard: item.shard,\n          state: item.state,\n        },\n        20\n      ),\n  },\n  invalidNodes: {\n    type: SHARD,\n    title: \"Dead节点列表\",\n    shardColumn: invalidNodesColumns,\n    mapFn: (item, index) =>\n      shardColumnEllipsis(\n        {\n          key: index,\n          deadNode: item,\n        },\n        97\n      ),\n  },\n  pendingTasks: {\n    type: SHARD,\n    title: \"PendingTask列表\",\n    shardColumn: pendingTasksColumns,\n    mapFn: (item, index) =>\n      shardColumnEllipsis(\n        {\n          key: index,\n          insertOrder: item.insertOrder,\n          priority: item.priority,\n          source: item.source,\n          timeInQueue: item.timeInQueue,\n        },\n        20\n      ),\n  },\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/cluster-kanban/overview-view.tsx",
    "content": "import { SyncOutlined } from \"@ant-design/icons\";\nimport { Collapse } from \"antd\";\nimport { TOP_MAP } from \"constants/status-map\";\nimport React, { memo, useState, useEffect, useRef } from \"react\";\nimport { IndexConfig, Line } from \"../components\";\nimport { OverviewViewBasic } from \"./overview-view-basic\";\nimport { formatterTimeYMDHMS, objFlat } from \"./config\";\nimport { defaultIndexConfigList, allCheckedData, getCheckedData, indexConfigClassifyList } from \"./overview-view-config\";\nimport { LineShard } from \"./overview-line-shard\";\nimport { asyncMicroTasks, resize } from \"../../../lib/utils\";\nimport { getCheckedList, setCheckedList, getDictionary } from \"../../../api/cluster-kanban\";\nconst { Panel } = Collapse;\nimport \"../style/index\";\nimport { shallowEqual, useDispatch, useSelector } from \"react-redux\";\nimport { setIsUpdate } from \"actions/cluster-kanban\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport { Divider } from \"knowdesign\";\n\nconst OVERVIEW = \"overview\";\n\nexport const classPrefix = \"monitor\";\n\nexport const OverviewView = memo(() => {\n  const [checkedData, setCheckedData] = useState(getCheckedData([]));\n  const [dictionary, setDictionary] = useState({});\n\n  const dispatch = useDispatch();\n  const { isUpdate, endTime } = useSelector(\n    (state) => ({\n      isUpdate: (state as any).clusterKanban.isUpdate,\n      endTime: (state as any).clusterKanban.endTime,\n    }),\n    shallowEqual\n  );\n\n  useEffect(() => {\n    getAsyncCheckedList();\n    _getDictionary();\n  }, []);\n\n  const reloadPage = () => {\n    dispatch(setIsUpdate(!isUpdate));\n  };\n\n  const sortEnd = (item, { oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(checkedData[item], oldIndex, newIndex);\n    checkedData[item] = listsNew;\n    const checkedList = objFlat(checkedData);\n    setCheckedList(OVERVIEW, checkedList);\n    setCheckedData({ ...checkedData });\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(OVERVIEW);\n      if (!checkedList || checkedList.length === 0) {\n        setCheckedData(allCheckedData);\n      } else {\n        setCheckedData(getCheckedData(checkedList));\n      }\n    } catch (error) {\n      setCheckedData(allCheckedData);\n      console.log(\"cluster-kanban node-view 获取配置下项失败\", error);\n    }\n  };\n\n  const _getDictionary = async () => {\n    let params = {\n      model: \"OverView\",\n    };\n    let res = await getDictionary(params);\n    let data = {} as any;\n    (res || []).forEach((item) => {\n      if (item?.metricType) {\n        data[item?.metricType] = item;\n      }\n      if (item?.metricType === \"sendTransSize\" || item?.metricType === \"recvTransSize\") {\n        data[\"networkFlow\"] = item;\n      }\n    });\n    setDictionary(data);\n  };\n\n  const setIndexConfigCheckedData = (changeCheckedData) => {\n    const checkedList = objFlat(changeCheckedData);\n    setCheckedList(OVERVIEW, checkedList);\n    setCheckedData(changeCheckedData);\n    reloadPage();\n  };\n\n  const renderConfig = () => {\n    return (\n      <IndexConfig\n        title=\"总览指标配置\"\n        optionList={defaultIndexConfigList}\n        checkedData={checkedData}\n        setCheckedData={setIndexConfigCheckedData}\n        needShortcut={true}\n      />\n    );\n  };\n\n  return (\n    <>\n      <div className={`${classPrefix}-overview-search`}>\n        <div className={`${classPrefix}-overview-search-reload`}>\n          <SyncOutlined className=\"dashboard-config-icon\" onClick={reloadPage} />\n        </div>\n        <div className={`${classPrefix}-overview-search-filter`}>{renderConfig()}</div>\n      </div>\n      <div className={`${classPrefix}-overview-content`}>\n        <div className={`${classPrefix}-overview-content-config`}>\n          <div className={`${classPrefix}-overview-content-config-box`}>\n            <OverviewViewBasic />\n          </div>\n        </div>\n      </div>\n      <div className={`${classPrefix}-overview-content`}>\n        {indexConfigClassifyList.map((item, index) => {\n          if (checkedData[item] && checkedData[item].length > 0) {\n            return (\n              <Collapse\n                defaultActiveKey={[index]}\n                onChange={() => {\n                  asyncMicroTasks(resize);\n                }}\n                style={{ marginBottom: 20 }}\n                key={item + index}\n              >\n                <Panel header={item} key={index}>\n                  <div className={`${classPrefix}-overview-content-line content-margin-top-20`}>\n                    {checkedData[item] && checkedData[item].length ? (\n                      <LineShard\n                        sortEnd={sortEnd}\n                        item={item}\n                        metricsTypes={checkedData[item]}\n                        key={`${item}_${index}`}\n                        dictionary={dictionary}\n                      />\n                    ) : (\n                      \"\"\n                    )}\n                  </div>\n                </Panel>\n              </Collapse>\n            );\n          }\n        })}\n      </div>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/contrast-figure-config.ts",
    "content": "\nimport { ContrastFigurePropsType  } from './contrast-figure';\n\nexport const getPieOption = ({\n  name,\n  text,\n  eChartsData,\n  colors,\n  legendVal,\n  unit,\n  tooltipDirection = 'right'\n}: ContrastFigurePropsType) => {\n  return {\n    legend: {\n      orient: \"vertical\",\n      top: \"center\",\n      align: \"left\",\n      right: 0,\n      icon: \"circle\",\n      itemGap: 20,\n      itemWidth: 12,\n      itemHeight: 12,\n      textStyle: {\n        fontFamily: \"PingFangSC-Regular\",\n        fontSize: 12,\n        color: \"#303A51\",\n        letterSpacing: 0,\n        textAlign: \"justify\",\n        width: 100,\n        overflow: \"break\",\n        lineHeight: 18,\n        // ellipsis: \"...\",\n      },\n      formatter: (name) => {\n        return (\n          name +\n          \":\\n\" +\n          legendVal[name]?.value +\n          \"  |  \" +\n          legendVal[name]?.percent +\n          \"%\"\n        );\n      },\n    },\n    tooltip: {\n      show: true,\n      trigger: \"item\",\n      // formatter: `{b} : {c} ${unit ? unit : \"\"} ({d}%)`,\n      formatter: ({name, value}) => {\n        return `${name} : ${value} ${unit ? unit : \"\"} (${legendVal[name]?.percent}%)`\n      },\n      position: (pos, params, dom, rect, size) => {\n        const [x, y] = pos;\n\n        let domHeight = (dom as any).offsetHeight;\n\n        if (domHeight > 350) {\n          domHeight = 250;\n        }\n\n        const domWidth = (dom as any).offsetWidth || 390;\n\n        const obj = { top: y - domHeight - 10 };\n\n        if (tooltipDirection === 'left') {\n          // 在鼠标左侧展示\n          obj[\"left\"] = x - domWidth - 10;\n        } else {\n          // 在鼠标右侧展示\n          obj[\"left\"] = x + 10;\n        }\n\n        return obj;\n      }\n    },\n    title: {\n      show: true,\n      text: text,\n      left: \"34%\",\n      top: \"45%\",\n      // subtext: subtext,\n      textAlign: \"center\",\n      textVerticalAlign: \"center\",\n      textStyle: {\n        fontFamily: \"PingFangSC-Regular\",\n        color: \"#505568\",\n        fontSize: 14,\n      },\n      subtextStyle: {\n        fontFamily: \"PingFangSC-Medium\",\n        color: \"#303A51\",\n        fontSize: 19,\n        width: 100,\n        overflow: \"truncate\",\n        ellipsis: \"...\",\n      },\n    },\n    color: colors,\n    animation: false,\n    series: [\n      {\n        name: name,\n        type: \"pie\",\n        radius: [\"60%\", \"90%\"],\n        center: [\"35%\", \"53%\"],\n        hoverAnimation: true,\n        itemStyle: {\n          borderColor: \"#fff\",\n          borderWidth: 1,\n        },\n        label: {\n          show: false,\n        },\n        data: eChartsData,\n      },\n    ],\n  };\n}"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/contrast-figure.tsx",
    "content": "import React, { memo, useEffect } from \"react\";\nimport _ from \"lodash\";\n// 引入 ECharts 主模块\nimport * as echarts from \"echarts/core\";\nimport {\n  PieChart,\n  // 系列类型的定义后缀都为 SeriesOption\n} from \"echarts/charts\";\n// 引入提示框，标题，直角坐标系组件，组件后缀都为 Component\nimport {\n  TitleComponent,\n  TooltipComponent,\n  LegendComponent,\n} from \"echarts/components\";\n// 引入 Canvas 渲染器，注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步\nimport { CanvasRenderer } from \"echarts/renderers\";\nimport { ellipsis } from \"../config\";\nimport { getPieOption } from './contrast-figure-config';\n\n// 注册必须的组件\necharts.use([\n  TitleComponent,\n  TooltipComponent,\n  PieChart,\n  LegendComponent,\n  CanvasRenderer,\n]);\nimport \"../style\";\n\nconst classPrefix = \"contrast-figure\";\n\nexport interface ContrastFigurePropsType {\n  id: string | number;\n  name: string;\n  text: string;\n  subtext: string;\n  eChartsData: { value: number; name: string }[];\n  colors: string[];\n  legendVal: { [key: string]: { value: number | string; percent: number } };\n  unit?: string;\n  tooltipDirection?: 'left' | 'right';\n}\n\nexport const ContrastFigure: React.FC<ContrastFigurePropsType> = memo((props) => {\n  const { id, name, subtext, unit } = props;\n\n  useEffect(() => {\n    // 基于准备好的dom，初始化echarts实例\n    const myChart = echarts.init(\n      document.getElementById(`${classPrefix}-box-content-${id}`)\n    );\n\n    // 指定图表的配置项和数据\n    const option = getPieOption(props);\n\n    // 使用刚指定的配置项和数据显示图表。\n    myChart.setOption(option);\n\n    const resize = _.throttle(() => {\n      const el: HTMLElement = document.getElementById(`${classPrefix}-box-content-${id}`);\n      // 表示该dom未进入可视区\n      if (!el.getBoundingClientRect().width) {\n        return;\n      }\n      myChart.resize();\n    }, 300);\n\n    window.addEventListener(\"resize\", resize);\n\n    return () => {\n      window.removeEventListener(\"resize\", resize);\n    };\n  }, [props]);\n\n  return (\n    <div className={`${classPrefix}-box`}>\n      <h4 className={`${classPrefix}-box-title`}>{name}</h4>\n      <div className={`${classPrefix}-box-container`}>\n        <span className={`${classPrefix}-box-subtext`}>\n          {ellipsis(subtext, 6, unit)}\n        </span>\n        <div\n          className={`${classPrefix}-box-content`}\n          id={`${classPrefix}-box-content-${id}`}\n        ></div>\n      </div>\n    </div>\n  );\n}\n);\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/custom-time-picker.tsx",
    "content": "import React, { useEffect, useRef } from \"react\";\nimport { useSelector, shallowEqual } from \"react-redux\";\nimport { CustomTimeRangePicker } from \"component/TimeRangePicker\";\n\ninterface CustomPickTimeProps {\n  onTimeStampChange?: (startTime, endTime, radioCheckedKey?: string) => void;\n  refreshTime?: number;\n}\n\nexport const CustomPickTime: React.FC<CustomPickTimeProps> = ({ onTimeStampChange, refreshTime = 0 }) => {\n  const { isClusterKanbanUpdate } = useSelector(\n    (state) => ({\n      isClusterKanbanUpdate: (state as any).clusterKanban.isUpdate,\n    }),\n    shallowEqual\n  );\n  const { isGatewayKanbanUpdate } = useSelector(\n    (state) => ({\n      isGatewayKanbanUpdate: (state as any).gatewayKanban.isUpdate,\n    }),\n    shallowEqual\n  );\n  const timer = useRef(null);\n  const rangeTimeRef = useRef(null);\n  const currentUpdateKey = useRef(\"\");\n\n  const updateTimeStamp = (dates = null, isCustomTime = false) => {\n    const _dates = dates || rangeTimeRef.current.rangeTime;\n    if (!_dates) return;\n    // 记录时间差用于刷新生效\n    if (isCustomTime) {\n      currentUpdateKey.current = `${new Date().getTime()}-${_dates[1].valueOf() - _dates[0].valueOf()}`;\n    }\n\n    onTimeStampChange && onTimeStampChange(_dates[0].valueOf(), _dates[1].valueOf(), isCustomTime ? currentUpdateKey.current : undefined);\n  };\n\n  const setTimer = () => {\n    if (!refreshTime || typeof refreshTime !== \"number\" || refreshTime <= 0) {\n      return;\n    }\n    timer.current && clearInterval(timer.current);\n    timer.current = setInterval(() => {\n      rangeTimeRef.current.refresh();\n    }, refreshTime);\n  };\n\n  useEffect(() => {\n    setTimer();\n    return () => {\n      clearInterval(timer.current);\n    };\n  }, [refreshTime]);\n\n  useEffect(() => {\n    rangeTimeRef.current.refresh();\n  }, [isClusterKanbanUpdate, isGatewayKanbanUpdate]);\n\n  return (\n    <>\n      <CustomTimeRangePicker ref={rangeTimeRef} onChange={(dates, isCustomTime) => updateTimeStamp(dates, isCustomTime)} />\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/index.tsx",
    "content": "export * from \"./kanban-form\";\nexport * from \"./select-time\";\nexport * from \"./state-config\";\nexport * from \"./contrast-figure\";\nexport * from \"./indicator-config\";\nexport * from \"./select-radio\";\nexport * from \"./line\";\nexport * from \"./shard\";\nexport * from \"./render-line\";\nexport * from \"./refresh-time\";\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/indicator-config.tsx",
    "content": "import React, { memo, useState } from \"react\";\nimport { useDispatch, useSelector, shallowEqual } from \"react-redux\";\nimport { SettingOutlined } from \"@ant-design/icons\";\nimport { Button, Modal } from \"antd\";\nimport * as actions from \"actions\";\n\ninterface optionListType {\n  title: string;\n  plainOptions: { label: string; value: string | number }[];\n}\ninterface propsType {\n  title: string;\n  optionList: optionListType[];\n  checkedData?: object;\n  setCheckedData: (defaultCheckedList) => void;\n  needShortcut?: boolean;\n}\n\nexport const IndexConfig: React.FC<propsType> = memo(({ title, optionList, checkedData, setCheckedData, needShortcut }) => {\n  const { btnTitle } = {\n    btnTitle: \"指标配置\",\n  };\n  const dispatch = useDispatch();\n  const modalId = \"IndexConfig\";\n  const { clusterKanban } = useSelector(\n    (state) => ({\n      clusterKanban: (state as any).clusterKanban,\n    }),\n    shallowEqual\n  );\n\n  const openWindow = () => {\n    for (const key in checkedData) {\n      optionList.forEach((item) => {\n        if (item.title === key) {\n          const before = [];\n          const after = [];\n          item.plainOptions.forEach((option) => {\n            const index = checkedData[key].indexOf(option.value);\n            if (index !== -1) {\n              before[index] = option;\n            } else {\n              after.push(option);\n            }\n          });\n          item.plainOptions = [...before, ...after];\n        }\n      });\n    }\n    const params = {\n      title: title,\n      optionList: optionList,\n      defaultCheckedData: checkedData || {},\n      needShortcut,\n    };\n    dispatch(actions.setModalId(modalId, params, setCheckedData));\n  };\n\n  return (\n    <Button\n      icon={<SettingOutlined />}\n      type=\"primary\"\n      ghost\n      onClick={() => {\n        openWindow();\n      }}\n    >\n      {btnTitle}\n    </Button>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/kanban-form.tsx",
    "content": "import React, { memo, useEffect, useState } from \"react\";\nimport { Form, Select } from \"antd\";\nimport \"../style\";\nimport { CustomPickTime } from \"./custom-time-picker\";\nconst { Option } = Select;\n\ninterface propsType {\n  clusterName: string;\n  clusterNameList: { text: string; value: string }[];\n  onTimeStampChange: (startTime: number, endTime: number, radioCheckedKey?: string) => void;\n  onClusterNameChange: (val: string) => void;\n  refreshTime?: number;\n}\n\nexport const KanbanForm: React.FC<propsType> = memo(\n  ({ onTimeStampChange, onClusterNameChange, clusterName, clusterNameList, refreshTime = 0 }) => {\n    const [form] = Form.useForm();\n\n    useEffect(() => {\n      form.setFieldsValue({ clusterName: clusterName || (clusterNameList[0] && clusterNameList[0].value) });\n    }, [clusterName]);\n\n    return (\n      <Form form={form}>\n        <div className=\"kanban-from-box\">\n          <div className=\"kanban-from-box-item\">\n            <Form.Item name=\"clusterName\" label=\"\" colon={false} initialValue={clusterName}>\n              <Select\n                placeholder=\"请选择\"\n                style={{ width: 200 }}\n                onChange={onClusterNameChange}\n                value={clusterNameList[0] && clusterNameList[0].value}\n                showSearch\n              >\n                {clusterNameList.map((item, index) => (\n                  <Option value={item.value} key={index + item.value}>\n                    {item.text}\n                  </Option>\n                ))}\n              </Select>\n            </Form.Item>\n          </div>\n          <CustomPickTime onTimeStampChange={onTimeStampChange} refreshTime={refreshTime} />\n        </div>\n      </Form>\n    );\n  }\n);\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/line.tsx",
    "content": "import React, { memo, useEffect, useRef, useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as echarts from \"echarts/core\";\nimport { Spin, Empty, Tooltip, Modal } from \"antd\";\nimport { throttle, cloneDeep } from \"lodash\";\nimport {\n  BarChart,\n  // 系列类型的定义后缀都为 SeriesOption\n  BarSeriesOption,\n  LineChart,\n  LineSeriesOption,\n} from \"echarts/charts\";\nimport {\n  TitleComponent,\n  // 组件类型的定义后缀都为 ComponentOption\n  TitleComponentOption,\n  TooltipComponent,\n  TooltipComponentOption,\n  GridComponent,\n  GridComponentOption,\n  LegendComponent,\n  LegendComponentOption,\n  MarkLineComponent,\n  MarkLineComponentOption,\n} from \"echarts/components\";\nimport { CanvasRenderer } from \"echarts/renderers\";\nimport * as actions from \"actions\";\nimport { useMouseoutOutSide } from \"../hooks/useMouseoutOutSide\";\nimport \"../style/index\";\nimport { MenuUnfoldOutlined, MenuFoldOutlined } from \"@ant-design/icons\";\nimport \"./style.less\";\n\nconst iconSrc = require(\"../img/full-screen.png\");\n\n// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型\nexport type ECOption = echarts.ComposeOption<\n  | BarSeriesOption\n  | LineSeriesOption\n  | TitleComponentOption\n  | TooltipComponentOption\n  | GridComponentOption\n  | LegendComponentOption\n  | MarkLineComponentOption\n>;\n\n// 注册必须的组件\necharts.use([TitleComponent, LegendComponent, TooltipComponent, GridComponent, BarChart, LineChart, CanvasRenderer, MarkLineComponent]);\n\n/*\n *@ 教程 https://echarts.apache.org/zh/index.html\n *@ 配置按需引入\n */\n\nexport const overviewClassPrefix = \"monitor\";\n\nexport interface ILine {\n  index: string;\n  option: ECOption;\n  setModalId?: (modalId: string, params?: any, cb?: Function) => any;\n  bigPicture?: boolean;\n  width?: number | string;\n  height?: number | string;\n  isLoading?: boolean;\n  title?: string | React.ReactNode;\n  tipSync?: boolean;\n  cb?: Function;\n  connectGroupName?: string;\n  tooltip?: React.ReactNode;\n}\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\nexport const DrawLine = connect(\n  null,\n  mapDispatchToProps\n)(\n  memo(({ index, option, setModalId, bigPicture, width, height, tipSync, cb, connectGroupName, title, tooltip }: ILine) => {\n    const chartBox = useRef(null);\n    const myChart = useRef(null);\n    const flag = useRef(true);\n    const [isShowLegend, setIsShowLegend] = useState(false);\n\n    const onRegisterConnect = ({ chartInstance }) => {\n      // 关联图表\n      chartInstance.group = connectGroupName;\n      echarts.connect(connectGroupName);\n    };\n\n    useEffect(() => {\n      if (myChart.current) {\n        myChart.current?.dispose();\n      }\n\n      myChart.current = echarts.init(document.getElementById(index) as HTMLElement);\n      connectGroupName &&\n        onRegisterConnect({\n          chartInstance: myChart.current,\n        });\n\n      // 监听点击事件\n      myChart.current.getZr().on(\"click\", function (params) {\n        if (flag.current) {\n          myChart.current.getZr().off(\"mousemove\");\n          flag.current = false;\n        } else {\n          hideTip();\n        }\n      });\n\n      const resize = throttle(() => {\n        const el: HTMLElement = document.getElementById(index);\n        // 表示该dom未进入可视区\n        if (!el?.getBoundingClientRect().width) {\n          return;\n        }\n        myChart.current?.resize();\n      }, 300);\n\n      window.addEventListener(\"resize\", resize);\n\n      return () => {\n        window.removeEventListener(\"resize\", resize);\n      };\n    }, []);\n\n    useEffect(() => {\n      // 增加true不合并数据\n      if (isShowLegend) {\n        const copyOption = cloneDeep(option);\n        (copyOption.legend as any) = null;\n        (copyOption.grid as any).right = \"20\";\n        copyOption && myChart.current?.setOption(copyOption, true);\n      } else {\n        option && myChart.current?.setOption(option, true);\n      }\n    }, [option, isShowLegend]);\n\n    const showTip = (params) => {\n      const { offsetX: x, offsetY: y } = params;\n      if (tipSync) {\n        if (x !== -999 || y !== -999) {\n          (window as any).lineX = x;\n          (window as any).lineY = y;\n          (window as any).lineTag = index;\n        } else if ((window as any).lineTag === index) {\n          (window as any).lineX = x;\n          (window as any).lineY = y;\n        }\n        myChart.current.dispatchAction({\n          type: \"showTip\",\n          x: x === -999 ? (window as any).lineX : x,\n          y: y === -999 ? (window as any).lineY : y,\n        });\n      } else {\n        myChart.current.dispatchAction({\n          type: \"showTip\",\n          x: x,\n          y: y,\n        });\n      }\n    };\n\n    const hideTip = () => {\n      // 设置无效的 x, y 隐藏点击显示的 toolTip 和 线\n      showTip({ offsetX: -999, offsetY: -999 });\n\n      // 重新监听鼠标移动显示 toolTip\n      chartMousemove();\n\n      flag.current = true;\n    };\n\n    const chartMousemove = () => {\n      myChart.current.getZr().on(\"mousemove\", showTip);\n    };\n\n    const getBigPictureOption = (option: ECOption): ECOption => {\n      option = _.cloneDeep(option);\n      (option.title as any).show = false;\n      (option.title as any).top = \"0\";\n      (option.legend as any).right = \"2%\";\n      (option.legend as any).itemWidth = 20;\n      ((option.legend as any).textStyle = {\n        width: 120,\n        overflow: \"truncate\",\n        ellipsis: \"...\",\n      }),\n        ((option.grid as any).right = \"20%\");\n      (option.grid as any).top = \"5\";\n      return option;\n    };\n\n    return (\n      <>\n        <div\n          ref={chartBox}\n          style={{ position: \"relative\" }}\n          className={bigPicture ? \"\" : `${overviewClassPrefix}-overview-content-line-container`}\n        >\n          <div\n            className={\n              bigPicture ? `${overviewClassPrefix}-overview-content-line-bigPicture` : `${overviewClassPrefix}-overview-content-line-item`\n            }\n            id={index}\n            key={index}\n            style={{\n              width: width ? width : \"none\",\n              height: height ? height : \"none\",\n            }}\n          ></div>\n          {cb ? (\n            cb()\n          ) : (\n            <>\n              <div className=\"line-title\">\n                {title}\n                {tooltip}\n              </div>\n              <div\n                style={bigPicture ? { display: \"none\" } : null}\n                className={`${overviewClassPrefix}-overview-content-line-legend`}\n                onClick={() => setIsShowLegend(!isShowLegend)}\n              >\n                <Tooltip title={isShowLegend ? \"展开legend\" : \"收起legend\"}>\n                  {isShowLegend ? <MenuFoldOutlined /> : <MenuUnfoldOutlined />}\n                </Tooltip>\n              </div>\n              <Tooltip title=\"查看大图\">\n                <div\n                  style={bigPicture ? { display: \"none\" } : null}\n                  onClick={(e) => {\n                    setModalId(\"bigPicture\", { ...getBigPictureOption(option), titleText: title });\n                  }}\n                  className={`${overviewClassPrefix}-overview-content-line-enlarge`}\n                >\n                  <img src={iconSrc} alt=\"全屏\" />\n                </div>\n              </Tooltip>\n            </>\n          )}\n        </div>\n      </>\n    );\n  })\n);\n\nexport const Line: React.FC<ILine> = ({ index, option, isLoading = false, width, height, title, tooltip, connectGroupName, cb }) => {\n  const renderLoading = () => {\n    return (\n      <div\n        className={`common-loading-container indicators-kanban-loading-container ${overviewClassPrefix}-overview-content-line-container`}\n      >\n        <div className=\"center-center-loading\">\n          <Spin />\n        </div>\n      </div>\n    );\n  };\n  const renderEmpty = () => {\n    return (\n      <div\n        className={`common-loading-container indicators-kanban-loading-container ${overviewClassPrefix}-overview-content-line-container`}\n      >\n        <div className=\"line-title\">\n          {title}\n          {tooltip}\n        </div>\n        <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} className=\"center-center-empty-box-content\" />\n      </div>\n    );\n  };\n  const renderLine = () => {\n    return (\n      <DrawLine\n        width={width}\n        height={height}\n        option={option}\n        index={index}\n        connectGroupName={connectGroupName}\n        cb={cb}\n        title={title}\n        tooltip={tooltip}\n      />\n    );\n  };\n  return <>{isLoading ? renderLoading() : !option || Object.keys(option).length == 0 ? renderEmpty() : renderLine()}</>;\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/operation-panel.tsx",
    "content": "import { SyncOutlined } from \"@ant-design/icons\";\nimport React from \"react\";\nimport { formatterTimeYMDHMS } from \"../config\";\n\nexport const OperationPanel = (props) => {\n  const { classPrefix, reloadPage, endTime, renderFilter } = props;\n\n  return (\n    <div className={`${classPrefix}-overview-search`}>\n      <div className={`${classPrefix}-overview-search-reload`}>\n        <SyncOutlined className=\"dashboard-config-icon\" onClick={reloadPage} />\n      </div>\n      <div className={`${classPrefix}-overview-search-filter`}>{renderFilter()}</div>\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/refresh-time.tsx",
    "content": "import React, { memo, useEffect, useState } from \"react\";\nimport { Select } from \"knowdesign\";\nimport \"../style/refresh-time.less\";\n\nconst { Option } = Select;\n\ninterface propsType {\n  changeRefreshTime: (val) => void;\n}\n\nconst seconds = 1000;\nconst minutes = 60 * seconds;\nexport const RefreshTime: React.FC<propsType> = memo(({ changeRefreshTime }) => {\n  const [isRotate, setIsRotate] = useState(false);\n  const [awaitTime, setAwaitTime] = useState(0);\n  const refreshConfig = [\n    {\n      value: 1 * minutes,\n      name: \"自动刷新：1分钟\",\n    },\n    {\n      value: 3 * minutes,\n      name: \"自动刷新：3分钟\",\n    },\n    {\n      value: 5 * minutes,\n      name: \"自动刷新：5分钟\",\n    },\n    {\n      value: 10 * minutes,\n      name: \"自动刷新：10分钟\",\n    },\n    {\n      value: 0,\n      name: \"关闭\",\n    },\n  ];\n\n  const onSelectChange = (val) => {\n    changeRefreshTime(val);\n    setAwaitTime(val);\n  };\n\n  useEffect(() => {\n    if (!awaitTime) {\n      return;\n    }\n\n    let interval, timeout;\n\n    timeout && clearTimeout(timeout);\n    interval && clearInterval(interval);\n\n    setInterval(() => {\n      setIsRotate(true);\n\n      setTimeout(() => {\n        setIsRotate(false);\n      }, 300);\n    }, awaitTime);\n\n    return () => {\n      clearTimeout(timeout);\n      clearInterval(interval);\n    };\n  }, [awaitTime]);\n\n  return (\n    <div className=\"refresh-time-container\">\n      {/* <span className=\"refresh-time-desc\">自动刷新</span> */}\n      <div className={`refresh-select ${awaitTime ? \"refresh-icon-container\" : \"\"}`}>\n        <Select onChange={onSelectChange} defaultValue={0}>\n          {refreshConfig.map((item) => (\n            <Option value={item.value} key={item.name + item.value}>\n              {item.name}\n            </Option>\n          ))}\n        </Select>\n      </div>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/render-line.tsx",
    "content": "import React, { memo, useEffect, useRef, useState } from \"react\";\nimport { Line } from \"./line\";\nimport { getOption, metricsType } from \"../config\";\nimport { indexConfigData } from \"container/indicators-kanban/cluster-kanban/node-view-config\";\nimport DragGroup from \"../../../d1-packages/drag-group/DragGroup\";\nimport { copyString } from \"lib/utils\";\nimport InfoTooltip from \"component/infoTooltip\";\nimport { unitMap } from \"../config\";\nimport \"./style.less\";\n\ninterface propsType {\n  metricsTypes: string[];\n  width?: number | string;\n  height?: number | string;\n  configData?: {\n    [key: string]: any;\n  };\n  isMoreDay?: boolean;\n  getAsyncViewData: (metricsType: string[], aggType?: string) => any;\n  reload?: boolean;\n  endTime?: number;\n  startTime?: number;\n  clusterPhyName?: string;\n  sortEnd?: any;\n  item?: string;\n  aggType?: string;\n  dictionary?: any;\n  content?: string | string[];\n}\n\nexport const RenderLine: React.FC<propsType> = memo(\n  ({\n    metricsTypes,\n    width,\n    height,\n    configData,\n    isMoreDay,\n    getAsyncViewData,\n    reload,\n    startTime,\n    endTime,\n    clusterPhyName,\n    sortEnd,\n    item,\n    aggType,\n    dictionary,\n    content,\n  }) => {\n    const [option, setOption] = useState({});\n    const [isLoading, setIsLoading] = useState(true);\n    const isFirst = useRef(true);\n    const timeDiff = useRef(0);\n\n    const getData = async () => {\n      if (!getAsyncViewData) {\n        setIsLoading(false);\n        return;\n      }\n      setIsLoading(true);\n      try {\n        const metricsList = await getAsyncViewData(metricsTypes, aggType);\n        if (!metricsList || metricsList.length === 0 || metricsList[0]?.metricsContents?.length === 0) {\n          setOption({});\n          return;\n        }\n        const data = {};\n        metricsList.forEach((item) => {\n          if (item?.type === \"indices-store-size_in_bytes\") {\n            let series = item?.metricsContents;\n            let unit = \"MB\";\n            (series || []).forEach((ele) => {\n              let number = ele?.metricsContentCells?.[0]?.value;\n              if (number > 1024 * 1024 * 1024 * 1024) {\n                unit = \"TB\";\n              } else if (number > 1024 * 1024 * 1024) {\n                unit = \"GB\";\n              }\n            });\n            if (configData[item?.type]) {\n              configData[item?.type].unit = unitMap[unit];\n            }\n          }\n          let breakLimit = [\n            \"breakers-fielddata-limit_size_in_bytes\",\n            \"breakers-accounting-limit_size_in_bytes\",\n            \"breakers-parent-limit_size_in_bytes\",\n            \"breakers-in_flight_requests-limit_size_in_bytes\",\n            \"breakers-request-limit_size_in_bytes\",\n            \"breakers-in_flight_http_requests-limit_size_in_bytes\",\n          ];\n          // breaker指标需增加阈值线展示\n          if (breakLimit.includes(item?.type)) {\n            addLimit(item, metricsList);\n          }\n          data[item.type] = getOption({\n            metrics: item,\n            configData,\n            isMoreDay,\n            isShowTooltipModal: true,\n            isShowTaskTooltipModal: !!indexConfigData[item.type]?.newquota,\n            clusterPhyName,\n            limit: item?.limit,\n          });\n        });\n        setOption(data);\n      } catch (error) {\n        console.log(\"render line\", error);\n      } finally {\n        setIsLoading(false);\n      }\n    };\n\n    const addLimit = (metrics, metricsList) => {\n      let length = metrics?.metricsContents?.[0]?.metricsContentCells?.length;\n      let limit = metrics?.metricsContents?.[0]?.metricsContentCells[length - 1].value;\n      // breaker指标返回的数据为阈值，需替换为真实数据\n      switch (metrics?.type) {\n        case \"breakers-fielddata-limit_size_in_bytes\":\n          let fielddataEstimated = (metricsList || []).filter((item) => item?.type === \"breakers-fielddata-estimated_size_in_bytes\")?.[0];\n          metrics.limit = limit;\n          metrics.metricsContents = [...fielddataEstimated?.metricsContents];\n          break;\n        case \"breakers-accounting-limit_size_in_bytes\":\n          let accountingEstimated = (metricsList || []).filter((item) => item?.type === \"breakers-accounting-estimated_size_in_bytes\")?.[0];\n          metrics.limit = limit;\n          metrics.metricsContents = [...accountingEstimated?.metricsContents];\n          break;\n        case \"breakers-parent-limit_size_in_bytes\":\n          let parentEstimated = (metricsList || []).filter((item) => item?.type === \"breakers-parent-estimated_size_in_bytes\")?.[0];\n          metrics.limit = limit;\n          metrics.metricsContents = [...parentEstimated?.metricsContents];\n          break;\n        case \"breakers-in_flight_requests-limit_size_in_bytes\":\n          let flightEstimated = (metricsList || []).filter(\n            (item) => item?.type === \"breakers-in_flight_requests-estimated_size_in_bytes\"\n          )?.[0];\n          metrics.limit = limit;\n          metrics.metricsContents = [...flightEstimated?.metricsContents];\n          break;\n        case \"breakers-request-limit_size_in_bytes\":\n          let requestEstimated = (metricsList || []).filter((item) => item?.type === \"breakers-request-estimated_size_in_bytes\")?.[0];\n          metrics.limit = limit;\n          metrics.metricsContents = [...requestEstimated?.metricsContents];\n          break;\n        case \"breakers-in_flight_http_requests-limit_size_in_bytes\":\n          let flightHttpEstimated = (metricsList || []).filter(\n            (item) => item?.type === \"breakers-in_flight_http_requests-estimated_size_in_bytes\"\n          )?.[0];\n          metrics.limit = limit;\n          metrics.metricsContents = [...flightHttpEstimated?.metricsContents];\n          break;\n        default:\n          break;\n      }\n    };\n\n    useEffect(() => {\n      if (endTime && startTime) {\n        if (isFirst.current || timeDiff.current !== endTime - startTime) {\n          setIsLoading(true);\n          timeDiff.current = endTime - startTime;\n          isFirst.current = false;\n        }\n      } else {\n        setIsLoading(true);\n      }\n      getData();\n    }, [metricsTypes, configData, isMoreDay, getAsyncViewData, reload, content]);\n\n    const showTooltipModal = (md5, metricsType) => {\n      copyString(md5);\n    };\n\n    useEffect(() => {\n      window[\"showTooltipModal\"] = (md5, metricsType) => {\n        showTooltipModal(md5, metricsType);\n      };\n    }, []);\n\n    return (\n      <>\n        <DragGroup\n          dragContainerProps={{\n            onSortEnd: (args) => sortEnd(item, { ...args }),\n            axis: \"xy\",\n            distance: 100,\n          }}\n          containerProps={{\n            grid: 12,\n            gutter: [10, 10],\n          }}\n        >\n          {metricsTypes.map((item, i) => {\n            let dict = dictionary?.[item] || {};\n            let title = configData[item]?.title() || \"\";\n            let tooltip =\n              dict?.currentCalLogic || dict?.price || dict?.threshold ? (\n                <InfoTooltip\n                  className=\"indicators-info\"\n                  currentCalLogic={dict?.currentCalLogic}\n                  price={dict?.price}\n                  threshold={dict?.threshold}\n                ></InfoTooltip>\n              ) : null;\n            return (\n              <Line\n                title={title}\n                index={item}\n                key={item}\n                option={option[item] || {}}\n                isLoading={isLoading}\n                width={width}\n                height={height}\n                tooltip={tooltip}\n              />\n            );\n          })}\n        </DragGroup>\n      </>\n    );\n  }\n);\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/select-radio.tsx",
    "content": "import React, { memo, useEffect, useRef, useState } from \"react\";\nimport { Button, Dropdown, Popover, Radio, Select, Space, Tooltip, Tag, TreeSelect } from \"antd\";\nimport { TOP_MAP, TOP_TIME_RANGE, TOP_TYPE } from \"../../../constants/status-map\";\nimport { DownOutlined, SettingOutlined } from \"@ant-design/icons\";\nimport Url from \"lib/url-parser\";\nimport \"./style.less\";\nimport { getPopupContainer } from \"lib/utils\";\nconst classPrefix = \"monitor\";\nconst { SHOW_CHILD } = TreeSelect;\n\ninterface propsType {\n  topNu?: number;\n  setTopNu?: (val: number) => void;\n  content: string | string[];\n  setContent?: (val: string | any) => void;\n  contentList: string[] | { name: string; value: string }[] | any;\n  placeholder?: string;\n  type?: string;\n  allowClear?: boolean;\n  style?: object;\n  onValueChange?: any;\n  secondSelectValue?: any;\n  secondSelectList?: any;\n  onSecondSelectChange?: any;\n  secondSelectPlaceholder?: string;\n}\n\nexport const SelectRadio = memo((props: propsType) => {\n  const {\n    content,\n    setContent,\n    topNu,\n    contentList,\n    placeholder,\n    allowClear,\n    type,\n    style,\n    onValueChange,\n    secondSelectPlaceholder,\n    secondSelectValue,\n    secondSelectList,\n    onSecondSelectChange,\n  } = props;\n\n  const [topNum, setTopNum] = useState(topNu ?? TOP_MAP[0].value);\n  const [visible, setVisible] = useState(false);\n  const [topTimeStep, setTopRange] = useState(TOP_TIME_RANGE[0].value);\n  const [topMethod, setTopType] = useState(TOP_TYPE[0].value);\n\n  const lastStatus = useRef({\n    topTimeStep: TOP_TIME_RANGE[0].value,\n    topMethod: TOP_TYPE[0].value,\n  });\n\n  useEffect(() => {\n    if (Url().search?.node || Url().search?.template || Url().search?.index) {\n      setTopNum(null);\n    }\n  }, []);\n\n  const onTypeValueChange = (type, value) => {\n    if (type === \"topTimeStep\") {\n      lastStatus.current.topTimeStep = topTimeStep;\n      setTopRange(value);\n    }\n    if (type === \"topMethod\") {\n      lastStatus.current.topMethod = topMethod;\n      setTopType(value);\n    }\n  };\n\n  const handleValueChange = (params) => {\n    const { topNum, topTimeStep, topMethod, content, needReload = true } = params;\n    onValueChange && onValueChange({ topNum, topTimeStep, topMethod, content }, needReload);\n  };\n\n  const setValues = (params) => {\n    const { topNum, topTimeStep, topMethod, content, needReload = true } = params;\n    setTopNum(topNum);\n    // TopN计算规则默认1分钟、最大值\n    const timeStep = topTimeStep || TOP_TIME_RANGE[0].value;\n    const method = topMethod || TOP_TYPE[0].value;\n    onTypeValueChange(\"topTimeStep\", timeStep);\n    onTypeValueChange(\"topMethod\", method);\n    handleValueChange({ topNum, topTimeStep: timeStep, topMethod: method, content, needReload });\n  };\n\n  const onSubmit = () => {\n    handleValueChange({ topNum, topTimeStep, topMethod, content });\n    lastStatus.current.topTimeStep = topTimeStep;\n    lastStatus.current.topMethod = topMethod;\n\n    setVisible(false);\n  };\n\n  const onCancel = () => {\n    setTopRange(lastStatus.current.topTimeStep);\n    setTopType(lastStatus.current.topMethod);\n    setVisible(false);\n  };\n\n  const popoverContent = () => {\n    return (\n      <div className=\"top-popover\">\n        <div className=\"top-radio\">\n          <div className=\"range\">\n            <div className=\"title\">Top计算时间步长</div>\n            <Radio.Group\n              className=\"time-radio-group\"\n              onChange={(e) => onTypeValueChange(\"topTimeStep\", e.target.value)}\n              value={topTimeStep}\n            >\n              <Space direction=\"vertical\" size={16}>\n                {TOP_TIME_RANGE.map((item, index) => (\n                  <Radio.Button value={item.value} key={index}>\n                    {item.label}\n                  </Radio.Button>\n                ))}\n              </Space>\n            </Radio.Group>\n          </div>\n          <div>\n            <div className=\"title\">Top计算方式</div>\n            <Radio.Group className=\"time-radio-group\" onChange={(e) => onTypeValueChange(\"topMethod\", e.target.value)} value={topMethod}>\n              <Space direction=\"vertical\" size={16}>\n                {TOP_TYPE.map((item, index) => (\n                  <Radio.Button value={item.value} key={index}>\n                    {item.label}\n                  </Radio.Button>\n                ))}\n              </Space>\n            </Radio.Group>\n          </div>\n        </div>\n        <div className=\"btns\">\n          <Button size=\"small\" onClick={onCancel}>\n            取消\n          </Button>\n          <Button size=\"small\" type=\"primary\" onClick={onSubmit}>\n            应用\n          </Button>\n        </div>\n      </div>\n    );\n  };\n\n  return (\n    <>\n      <Tooltip overlayClassName=\"top-n-tips\" placement=\"topLeft\" title=\"TopN计算规则配置，只作用于Top5-Top20算法\">\n        <Popover placement=\"bottomLeft\" visible={visible} onVisibleChange={setVisible} content={popoverContent} trigger=\"click\">\n          <Button className=\"setting-btn\" icon={<SettingOutlined />}>\n            <DownOutlined />\n          </Button>\n        </Popover>\n      </Tooltip>\n\n      <Radio.Group\n        className={`${classPrefix}-overview-search-filter-item`}\n        value={topNum}\n        onChange={(e) => {\n          setValues({\n            topNum: e.target.value,\n            topTimeStep: topTimeStep || TOP_TIME_RANGE[0].value,\n            topMethod: topMethod || TOP_TYPE[0].value,\n            content: type !== \"secondSelect\" ? (type == \"node\" ? [] : undefined) : content,\n          });\n        }}\n      >\n        {TOP_MAP.map((item) => (\n          <Radio.Button key={item.value} value={item.value}>\n            {item.label}\n          </Radio.Button>\n        ))}\n      </Radio.Group>\n      {type == \"treeSelect\" ? (\n        <div className=\"tree-select-node\">\n          <TreeSelect\n            getPopupContainer={getPopupContainer}\n            treeData={contentList}\n            value={content || undefined}\n            onChange={(val) => {\n              setValues({\n                topNum: 0,\n                topTimeStep: undefined,\n                topMethod: undefined,\n                content: val,\n              });\n            }}\n            treeCheckable\n            showCheckedStrategy={SHOW_CHILD}\n            placeholder={placeholder}\n            style={{ width: \"100%\", ...style }}\n          />\n        </div>\n      ) : (\n        <div className=\"overview-select-mode\">\n          <Select\n            mode={type == \"node\" ? \"multiple\" : null}\n            showArrow\n            maxTagCount=\"responsive\"\n            placeholder={placeholder}\n            style={{ width: \"100%\", ...style }}\n            value={content || undefined}\n            onChange={(val) => {\n              if (!val || (typeof val === \"object\" && !val.length)) {\n                setValues({\n                  topNum: TOP_MAP[0].value,\n                  topTimeStep: TOP_TIME_RANGE[0].value,\n                  topMethod: TOP_TYPE[0].value,\n                  content: val,\n                });\n                return;\n              }\n              const isSecondSelect = type === \"secondSelect\";\n              setValues({\n                topNum: isSecondSelect ? topNum || TOP_MAP[0].value : 0,\n                topTimeStep: isSecondSelect ? topTimeStep || TOP_TIME_RANGE[0].value : undefined,\n                topMethod: isSecondSelect ? topMethod || TOP_TYPE[0].value : undefined,\n                content: val,\n              });\n            }}\n            allowClear={allowClear || false}\n            showSearch\n            filterOption={(val, option: any) => {\n              if (type === \"node\" && typeof option.children !== \"string\") {\n                return option.key.toLowerCase().indexOf(val.toLowerCase()) >= 0;\n              } else {\n                return option.children.includes(val.trim());\n              }\n            }}\n            className={`${classPrefix}-overview-search-filter-item`}\n          >\n            {contentList.map((item, index) => {\n              if (typeof item === \"string\") {\n                return (\n                  <Select.Option value={item} key={item + index}>\n                    {item}\n                  </Select.Option>\n                );\n              } else {\n                return (\n                  <Select.Option value={item.value} key={JSON.stringify(item) + index}>\n                    {type === \"node\" ? (\n                      <div className=\"node-select-item\">\n                        <span>{item.name}</span>\n                        <Tag color=\"blue\">{item.tips}</Tag>\n                      </div>\n                    ) : (\n                      item.name\n                    )}\n                  </Select.Option>\n                );\n              }\n            })}\n          </Select>\n        </div>\n      )}\n\n      {type === \"secondSelect\" ? (\n        <Select\n          className=\"second-select\"\n          placeholder={secondSelectPlaceholder}\n          onChange={(e: string) => {\n            setValues({\n              topNum: e ? 0 : TOP_MAP[0].value,\n              topTimeStep: e ? undefined : TOP_TIME_RANGE[0].value,\n              topMethod: e ? undefined : TOP_TYPE[0].value,\n              content,\n              needReload: false,\n            });\n            onSecondSelectChange(e || \"\");\n          }}\n          value={secondSelectValue || null}\n          showSearch\n          filterOption={(val, option) => {\n            return option.children.includes(val.trim());\n          }}\n          allowClear\n        >\n          {secondSelectList.map((item, index) => {\n            if (typeof item === \"string\") {\n              return (\n                <Select.Option value={item} key={item + index}>\n                  {item}\n                </Select.Option>\n              );\n            } else {\n              return (\n                <Select.Option value={item.value} key={item.value + index}>\n                  {item.name}\n                </Select.Option>\n              );\n            }\n          })}\n        </Select>\n      ) : null}\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/select-time.tsx",
    "content": "import React, { useEffect, useRef, useState } from \"react\";\nimport { useSelector, shallowEqual } from \"react-redux\";\nimport { Radio, DatePicker } from \"antd\";\nimport moment from \"moment\";\nimport { PERIOD_RADIO, PERIOD_RADIO_MAP } from \"../config\";\nimport { AlertTwoTone } from \"@ant-design/icons\";\nconst { RangePicker } = DatePicker;\n\ninterface SelectTimePropsType {\n  onTimeStampChange?: (startTime, endTime, radioCheckedKey) => void;\n  refreshTime?: number;\n}\n\nexport const SelectTime: React.FC<SelectTimePropsType> = ({ onTimeStampChange, refreshTime = 0 }) => {\n  const { isClusterKanbanUpdate } = useSelector(\n    (state) => ({\n      isClusterKanbanUpdate: (state as any).clusterKanban.isUpdate,\n    }),\n    shallowEqual\n  );\n  const { isGatewayKanbanUpdate } = useSelector(\n    (state) => ({\n      isGatewayKanbanUpdate: (state as any).gatewayKanban.isUpdate,\n    }),\n    shallowEqual\n  );\n  const [time, setTime] = useState(\"oneHour\");\n  const [hackValue, setHackValue] = useState(null);\n  const [dates, setDates] = useState([undefined, undefined]);\n  const [calendarDates, setCalendarDates] = useState([]);\n  const didMount = useRef(false);\n  const timer = useRef(null);\n  const currentRadioKey = useRef(\"\");\n\n  const disabledDate = (current) => {\n    if (!calendarDates || calendarDates.length === 0) {\n      return current > moment().endOf(\"day\");\n    }\n    const tooLate = (calendarDates[0] && current.diff(calendarDates[0], \"days\") > 13) || current > moment().endOf(\"day\");\n    const tooEarly = calendarDates[1] && calendarDates[1].diff(current, \"days\") > 13;\n    return tooLate || tooEarly;\n  };\n\n  const updateTimeStamp = (key: string, isUpdate = false) => {\n    const _dates = PERIOD_RADIO_MAP.get(key)?.dateRange || dates;\n    if (!_dates) return;\n    setDates(_dates);\n    // 记录时间差用于判断刷新是否生效\n    if (isUpdate) {\n      currentRadioKey.current = `${new Date().getTime()}-${_dates[1].valueOf() - _dates[0].valueOf()}`;\n    }\n    onTimeStampChange && onTimeStampChange(_dates[0].valueOf(), _dates[1].valueOf(), isUpdate ? currentRadioKey.current : undefined);\n  };\n\n  const onRadioChange = (e) => {\n    const { value } = e.target;\n    setTime && setTime(value);\n    updateTimeStamp(value);\n  };\n\n  const onRangeChange = (dates) => {\n    setTime && setTime(\"\");\n    setDates(dates);\n    onTimeStampChange && onTimeStampChange(dates[0].valueOf(), dates[1].valueOf(), currentRadioKey.current);\n  };\n\n  const onOpenChange = (open) => {\n    if (open) {\n      setHackValue([]);\n      setCalendarDates([]);\n    } else {\n      setHackValue(undefined);\n    }\n  };\n\n  const setTimer = () => {\n    if (!refreshTime || typeof refreshTime !== \"number\" || refreshTime <= 0) {\n      return;\n    }\n    timer.current && clearInterval(timer.current);\n    timer.current = setInterval(() => {\n      updateTimeStamp(time);\n    }, refreshTime);\n  };\n\n  useEffect(() => {\n    setTimer();\n    return () => {\n      clearInterval(timer.current);\n    };\n  }, [refreshTime, time]);\n\n  useEffect(() => {\n    if (!didMount.current) {\n      didMount.current = true;\n      return;\n    }\n    updateTimeStamp(time, true);\n    setTimer();\n  }, [isClusterKanbanUpdate, isGatewayKanbanUpdate]);\n\n  useEffect(() => {\n    const dates = PERIOD_RADIO_MAP.get(time).dateRange;\n    setDates(dates);\n  }, []);\n\n  return (\n    <div>\n      <Radio.Group style={{ margin: \"0 15px 10px 0\" }} value={time} onChange={onRadioChange}>\n        {PERIOD_RADIO.map((p) => (\n          <Radio.Button key={p.key} value={p.key}>\n            {p.label}\n          </Radio.Button>\n        ))}\n      </Radio.Group>\n      <RangePicker\n        disabledDate={disabledDate}\n        onCalendarChange={(val) => setCalendarDates(val)}\n        format=\"YYYY-MM-DD HH:mm\"\n        allowClear={false}\n        value={(hackValue || dates) as [moment.Moment, moment.Moment]}\n        onChange={onRangeChange}\n        onOpenChange={onOpenChange}\n        showTime={{ format: \"HH:mm\", defaultValue: [moment(\"00:00:00\", \"HH:mm\"), moment(\"23:59:59\", \"HH:mm\")] }}\n      />\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/shard.tsx",
    "content": "import { Table } from \"antd\";\nimport React, { memo } from \"react\";\nimport moment from \"moment\";\nimport \"../style/index\";\nimport \"./style.less\";\n\ninterface propsType {\n  dataSource: any[];\n  shardColumns: any[];\n  title: string | React.ReactNode;\n  currentTime: string;\n  isLoading?: boolean;\n  tooltip?: React.ReactNode;\n}\n\nexport const Shard: React.FC<propsType> = memo(({ title, tooltip, shardColumns, dataSource, currentTime, isLoading = false }) => {\n  const date = moment(Date.parse(currentTime)).format(\"yyyy-MM-DD HH:mm\");\n  return (\n    <div className=\"shard-container\">\n      <div className=\"shard-title\">\n        <div className=\"title-content\">\n          <span className=\"title-text\">{title}</span>\n          {tooltip}\n        </div>\n        <div className=\"title-time\">{`时间： ${date}`}</div>\n      </div>\n      <div className=\"shard-table\">\n        <Table\n          loading={isLoading}\n          rowKey={\"key\"}\n          dataSource={dataSource}\n          columns={shardColumns}\n          pagination={{\n            // simple: true,\n            showSizeChanger: false,\n            showQuickJumper: true,\n            size: \"small\",\n            position: [\"bottomRight\"],\n            pageSize: 5,\n            total: dataSource?.length,\n            showTotal: (total) => `共 ${total} 条`,\n          }}\n        />\n      </div>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/state-config.tsx",
    "content": "import React, { memo } from \"react\";\nimport { Tooltip } from \"antd\";\nimport \"../style\";\nimport \"./style.less\";\n\nconst classPrefix = \"state-config\";\n\ninterface ListType {\n  name: string;\n  count?: number;\n  state?: string;\n  id?: number;\n}\n\ninterface StateConfigPropsType {\n  list: ListType[];\n  title: String;\n  className?: string;\n}\n\nconst RenderModule = (props) => {\n  let status = \"\";\n  if (props.state != null) {\n    if (props.state === \"green\") {\n      status = \"Green\";\n    } else if (props.state === \"yellow\") {\n      status = \"Yellow\";\n    } else if (props.state === \"unknown\") {\n      status = \"Unknown\";\n    } else [(status = \"Red\")];\n  }\n\n  const ellipsis = (str: string | number, num: number, unit: string = \"\") => {\n    return String(str).length > num ? (\n      <Tooltip placement=\"top\" title={`${str}${unit || \"\"}`}>\n        {String(str).substring(0, num) + \"...\"}\n      </Tooltip>\n    ) : (\n      str\n    );\n  };\n\n  return (\n    <div className={`${classPrefix}-box-content-module`} key={props.name}>\n      <p className={`${classPrefix}-box-config-info`}>{props.name}</p>\n      {status ? (\n        <p className={`${classPrefix}-box-config-state ${classPrefix}-box-config-state-${status}`}>\n          <span>{status}</span>\n        </p>\n      ) : (\n        <p className={`${classPrefix}-box-config-content`}>\n          {ellipsis(props.count, 4, props.unit)}\n          <span className={`${classPrefix}-box-config-content-sub`}>{props.unit || \"\"}</span>\n        </p>\n      )}\n    </div>\n  );\n};\nexport const StateConfig: React.FC<StateConfigPropsType> = memo(({ list, title, className }) => {\n  return (\n    <div className={`${classPrefix}-box ${className ? className : \"\"}`}>\n      <h4 className={`${classPrefix}-box-title`}>{title}</h4>\n      <div className={`${classPrefix}-box-content`}>\n        {list.map((item, index) => (\n          <RenderModule {...item} key={item.id} />\n        ))}\n      </div>\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/components/style.less",
    "content": "@antd-prefix: ant;\n\n.top-popover {\n  min-width: 260px;\n  .top-radio {\n    display: flex;\n\n    .title {\n      font-family: PingFangSC-Medium;\n      font-size: 14px;\n      color: #212529;\n      letter-spacing: 0;\n      margin-bottom: 16px;\n    }\n\n    .range {\n      margin-right: 30px;\n    }\n\n    .@{antd-prefix}-radio-button-wrapper {\n      border: none;\n      padding: 0;\n      height: 18px;\n      line-height: 18px;\n    }\n\n    .@{antd-prefix}-radio-button-wrapper-checked:not(.@{antd-prefix}-radio-button-wrapper-disabled):focus-within {\n      box-shadow: none;\n    }\n  }\n\n  .btns {\n    text-align: right;\n    margin-top: 16px;\n\n    Button {\n      border-radius: 4px;\n    }\n\n    Button + Button {\n      margin-left: 8px;\n    }\n  }\n}\n\n.setting-btn {\n  line-height: 17px;\n}\n\n.top-n-tips.ant-tooltip {\n  max-width: 300px;\n}\n\n.status-overview {\n  .state-config-box-content {\n    .state-config-box-content-module {\n      flex: none;\n      width: 14%;\n    }\n    .state-config-box-content-module:nth-child(3) {\n      width: 18%;\n    }\n    .state-config-box-content-module:nth-child(6) {\n      width: 13%;\n    }\n  }\n}\n\n.monitor-overview-content-line-item-header {\n  position: relative;\n}\n\n.line-title,\n.title-content {\n  position: absolute;\n  top: 14.5px;\n  left: 20px;\n  font-family: PingFangSC-Medium;\n  font-size: 16px;\n  color: #303a51;\n  line-height: 24px;\n}\n\n.shard-container {\n  min-width: 518px;\n  padding: 20px;\n  position: relative;\n  border: 1px solid #dcdfe6;\n  border-radius: 2px;\n  margin: 0 0 20px;\n  height: 305px;\n  .title-time {\n    position: absolute;\n    right: 20px;\n    top: 14.5px;\n  }\n  .shard-table {\n    margin-top: 30px;\n    .ant-table-cell {\n      padding: 5px 0px 5px 6px;\n      height: 33px;\n    }\n    .ant-table-empty {\n      .ant-empty-normal {\n        margin: 65px 0;\n      }\n    }\n  }\n}\n\n.tree-select-node {\n  display: inline-block;\n\n  .ant-select-tree .ant-select-tree-node-content-wrapper {\n    padding: 0 1px;\n  }\n\n  .ant-tree-select-dropdown .ant-select-tree-list-holder-inner .ant-select-tree-treenode {\n    padding-bottom: 12px;\n  }\n\n  .ant-select-tree-checkbox-indeterminate .ant-select-tree-checkbox-inner::after {\n    background-color: #fff;\n    height: 2px;\n  }\n\n  .ant-select-tree-checkbox-indeterminate .ant-select-tree-checkbox-inner {\n    background-color: @primary-color;\n  }\n\n  .ant-select-tree-checkbox-checked .ant-select-tree-checkbox-inner::after {\n    transition: none;\n  }\n\n  .ant-select-tree-title {\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: rgba(0, 0, 0, 0.87);\n    letter-spacing: 0;\n    line-height: 22px;\n    font-weight: 400;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/config.tsx",
    "content": "import { ECOption } from \"./components/line\";\nimport React from \"react\";\nimport { Tooltip } from \"antd\";\nimport moment from \"moment\";\nimport { toFixedNum } from \"lib/utils\";\n\n// 图表单位映射\nexport const unitMap = {\n  none: {\n    // 图表单位名称\n    name: \"\",\n    // 图表数据格式化\n    formatter: toFixedNum,\n  },\n  percent: {\n    name: \"%\",\n    formatter: toFixedNum,\n  },\n  count: {\n    name: \"个\",\n    formatter: toFixedNum,\n  },\n  TB: {\n    name: \"TB\",\n    formatter: (num) => {\n      return toFixedNum(num / 1024 / 1024 / 1024 / 1024, 3);\n    },\n  },\n  GB: {\n    name: \"GB\",\n    formatter: (num) => {\n      return toFixedNum(num / 1024 / 1024 / 1024, 3);\n    },\n  },\n  MB: {\n    name: \"MB\",\n    formatter: (num) => {\n      return toFixedNum(num / 1024 / 1024, 3);\n    },\n  },\n  ms: {\n    name: \"MS\",\n    formatter: toFixedNum,\n  },\n  countS: {\n    name: \"个/S\",\n    formatter: (num) => {\n      return toFixedNum(num, 1);\n    },\n  },\n  mbS: {\n    name: \"MB/S\",\n    formatter: (num) => {\n      return toFixedNum(num / 1024 / 1024, 3);\n    },\n  },\n  s: {\n    name: \"S\",\n    formatter: (num) => {\n      return toFixedNum(num / 1000, 3);\n    },\n  },\n  numS: {\n    name: \"次\",\n    formatter: toFixedNum,\n  },\n  ss: {\n    name: \"次/S\",\n    formatter: (num) => {\n      return toFixedNum(num, 3);\n    },\n  },\n  mins: {\n    name: \"次/MIN\",\n    formatter: toFixedNum,\n  },\n  item: {\n    name: \"条\",\n    formatter: toFixedNum,\n  },\n  itemMin: {\n    name: \"条/MIN\",\n    formatter: toFixedNum,\n  },\n  byte: {\n    name: \"Bytes\",\n    formatter: toFixedNum,\n  },\n  countM: {\n    name: \"个/MIN\",\n    formatter: toFixedNum,\n  },\n  characterMin: {\n    name: \"字符/MIN\",\n    formatter: toFixedNum,\n  },\n};\n\n// 图表标题\nconst title = function () {\n  const unit = this.unit?.name ? `(${this.unit?.name})` : \"\";\n  return this.name + unit;\n};\n\n// 给图标的指标项添加标题\nexport const addChartTitle = (data: { [key: string]: any }) => {\n  for (let key in data) {\n    data[key].title = title;\n  }\n};\n\nexport const colorList = [\n  \"#5B73F0\",\n  \"#5998FF\",\n  \"#3DDCDC\",\n  \"#21CAB8\",\n  \"#89D9CA\",\n  \"#BCE2E8\",\n  \"#CBE681\",\n  \"#FFEE8F\",\n  \"#F3D930\",\n  \"#F0BC18\",\n  \"#F7B977\",\n  \"#FF9C6E\",\n  \"#FF8686\",\n  \"#FF7043\",\n  \"#E17B34\",\n  \"#EB767F\",\n  \"#FF85C0\",\n  \"#B88EFA\",\n  \"#B37FEB\",\n  \"#7779FF\",\n  \"#7F6DE7\",\n  \"#A5A0EE\",\n  \"#9DABF6\",\n  \"#C4CCF9\",\n  \"#A0BDEE\",\n  \"#89C3EB\",\n  \"#85CFF3\",\n  \"#C2E8FA\",\n  \"#EAEEFA\",\n];\n\nexport interface metricsContentsType {\n  metricsContentCells: { timeStamp: number; value: number }[];\n  name: string;\n  cluster: string;\n}\nexport interface metricsType {\n  metricsContents: metricsContentsType[];\n  type: string;\n}\n\ninterface seriesType {\n  name: string;\n  data: number[] | { timestamp: number; value: number }[];\n}\n\nconst markLine = (val1 = 50000, val2 = 100000) => ({\n  data: [\n    {\n      name: \"预警线5W\",\n      yAxis: val1,\n      label: {\n        formatter: \"{b}\",\n        position: \"insideStartTop\",\n      },\n      lineStyle: {\n        color: \"#F39419\",\n      },\n    },\n    {\n      name: \"预警线10w\",\n      yAxis: val2,\n      label: {\n        formatter: \"{b}\",\n        position: \"insideStartTop\",\n      },\n      lineStyle: {\n        color: \"#F11919\",\n      },\n    },\n  ],\n});\n\nconst markLimitLine = (val: number, unitMap) => {\n  return {\n    data: [\n      {\n        name: `阈值${unitMap.formatter(val)}${unitMap.name}`,\n        yAxis: unitMap.formatter(val),\n        label: {\n          formatter: \"{b}\",\n          position: \"insideStartTop\",\n        },\n        lineStyle: {\n          color: \"#F11919\",\n        },\n      },\n    ],\n  };\n};\n\n// 图表 tooltip 展示的样式\nconst tooltipFormatter = (date, arr, unit, isShowTooltipModal, metricsType, isShowTaskTooltipModal, clusterPhyName) => {\n  // 新增从大到小排序\n  arr = arr.sort((a, b) => b.value - a.value);\n  const str = arr\n    .map(\n      (item) => `<div style=\"margin: 3px 0;line-height:1;\">\n          <div style=\"margin: 0px 0 0;line-height:1;\">\n          ${item.marker}\n          <span style=\"font-size:14px;color:#666;pointer-events: auto;font-weight:400;margin-left:2px;${\n            isShowTooltipModal ? \"cursor: pointer\" : \"\"\n          }\" \n          ${\n            isShowTaskTooltipModal\n              ? `onclick=\"window.showTaskTooltipModal('${clusterPhyName}', '${item.seriesName}', '${item.name}')\"}`\n              : \"\"\n          }\n            ${isShowTooltipModal ? `onclick=\"window.showTooltipModal('${item.seriesName}', '${metricsType}')\"}` : \"\"}\n           >\n              ${item.seriesName}\n            </span>\n            <span style=\"float:right;margin-left:20px;font-size:14px;color:#666;font-weight:900\">\n              ${item.value > 10000 ? toFixedNum(item.value / 10000, 2) + \"W\" : item.value} ${unit || \"\"}\n            </span>\n            <div style=\"clear:both\"></div>\n          </div>\n          <div style=\"clear:both\"></div>\n        </div>\n      <div style=\"clear:both\"></div>`\n    )\n    .join(\"\");\n\n  return `<div style=\"margin: 0px 0 0;line-height:1; position: relative; z-index: 99;\">\n    <div style=\"margin: 0px 0 0;line-height:1;\">\n      <div style=\"font-size:14px;color:#666;font-weight:400;line-height:1;\">\n        ${date}\n      </div>\n      <div style=\"margin: 10px 0 0;line-height:1;\">\n        ${str}\n      </div>\n      <div style=\"clear:both\"></div>\n    </div>\n  </div>`;\n};\n\n// 图表 tooltip 展示位置\nconst tooltipPosition = (pos, params, dom, rect, size, showLegend) => {\n  const [x, y] = pos;\n  const [width, height] = size.viewSize;\n\n  let domHeight = (dom as any).offsetHeight;\n\n  if (domHeight > 350) {\n    domHeight = 250;\n  }\n\n  const domWidth = (dom as any).offsetWidth || 390;\n  const obj = { top: y - domHeight - 10 };\n\n  // showLegend 是否展示左侧 legend\n  const chartPosition = showLegend ? width - 40 : width / 2 - 20;\n  if (x > chartPosition) {\n    // 在鼠标左侧展示\n    obj[\"left\"] = x - domWidth - 10;\n  } else if (x + domWidth > width) {\n    // 右侧超出，设置固定位置\n    obj[\"right\"] = -50;\n  } else {\n    // 在鼠标右侧展示\n    obj[\"left\"] = x + 10;\n  }\n  return obj;\n};\n\n// 判断 ms 是否需要转换成 s，只判断峰值\nconst isConversion = (series) => {\n  return series.some((item) => {\n    return item.data.some((item) => {\n      if (typeof item == \"object\") {\n        if (item.value > 1000) {\n          return true;\n        }\n      }\n      return item > 1000;\n    });\n  });\n};\ninterface lineOptionType {\n  title: string;\n  xAxisData: number[];\n  series: seriesType[];\n  unitMap?: { [key: string]: any };\n  isMoreDay?: boolean;\n  isMarkLine?: boolean;\n  color?: string[];\n  isShowTooltipModal?: boolean;\n  isShowTaskTooltipModal?: boolean;\n  metricsType?: string;\n  showLegend?: boolean;\n  clusterPhyName?: string;\n  limit?: number;\n}\n\nexport const getLineOption = ({\n  title,\n  xAxisData,\n  series,\n  // 单位名称，单位格式化\n  unitMap,\n  // 是否大于一天\n  isMoreDay = false,\n  // 是否展示警戒线\n  isMarkLine = false,\n  color = colorList,\n  // 是否展示可以点击 Tooltip 并展示弹窗\n  isShowTooltipModal = false,\n  // 是否展示可以点击 Tooltip 并展示task弹窗\n  isShowTaskTooltipModal = false,\n  // 后端图表指标名称，帮助弹窗获取数据\n  metricsType,\n  // 是否显示左侧 legend\n  showLegend = true,\n  clusterPhyName = \"\",\n  // 阈值线阈值\n  limit,\n}: lineOptionType) => {\n  let seriesData;\n  let unitFormatter = unitMap?.formatter;\n  let unitName = unitMap?.name;\n  if (unitFormatter) {\n    // 根据数值大小判断单位是否需要进行转换\n    if (unitName === \"ms\" && isConversion(series)) {\n      unitFormatter = (num) => {\n        let val = Number(num);\n        return toFixedNum(val / 1000, 3);\n      };\n      unitName = \"s\";\n      title = title.replace(\"ms\", \"s\");\n    }\n    seriesData = series.map((item: any) => ({\n      name: item?.name || \"\",\n      data: item?.data.map((el) => {\n        if (typeof el == \"object\") {\n          return {\n            timestamp: el.timestamp,\n            value: unitFormatter(el.value),\n          };\n        }\n        return unitFormatter(el);\n      }),\n      type: \"line\",\n      markLine: isMarkLine ? markLine() : limit || limit === 0 ? markLimitLine(limit, unitMap) : {},\n      showSymbol: false,\n    }));\n  } else {\n    seriesData = series.map((item) => ({\n      ...item,\n      type: \"line\",\n      markLine: isMarkLine ? markLine() : limit || limit === 0 ? markLimitLine(limit, unitMap) : {},\n      showSymbol: false,\n    }));\n  }\n\n  return {\n    color: color,\n    title: {\n      // text: title,\n      top: showLegend ? \"20\" : 0,\n      left: showLegend ? \"20\" : 0,\n    },\n    tooltip: {\n      trigger: \"axis\",\n      position: (pos, params, dom, rect, size) => {\n        return tooltipPosition(pos, params, dom, rect, size, showLegend);\n      },\n      extraCssText: \"z-index: 101\",\n      formatter: (params: any) => {\n        let res = \"\";\n        if (params != null && params.length > 0) {\n          res += tooltipFormatter(\n            moment(Number(params[0].name)).format(\"YYYY-MM-DD HH:mm\"),\n            params,\n            unitName,\n            isShowTooltipModal,\n            metricsType,\n            isShowTaskTooltipModal,\n            clusterPhyName\n          );\n        }\n        return res;\n      },\n    },\n    legend: showLegend\n      ? {\n          type: \"scroll\",\n          orient: \"vertical\",\n          right: \"10\",\n          top: \"16%\",\n          bottom: \"20%\",\n          icon: \"rect\",\n          itemHeight: 2,\n          itemWidth: 14,\n          textStyle: {\n            width: 135,\n            overflow: \"truncate\",\n            ellipsis: \"...\",\n          },\n          tooltip: {\n            show: true,\n          },\n        }\n      : null,\n    grid: {\n      left: showLegend ? \"20\" : 0,\n      right: showLegend ? \"200\" : 20,\n      bottom: showLegend ? \"3%\" : 0,\n      containLabel: true,\n    },\n    xAxis: {\n      type: \"category\",\n      boundaryGap: false,\n      data: [...xAxisData],\n      axisLabel: {\n        formatter: (value: number) => {\n          value = Number(value);\n          if (!isMoreDay) {\n            return moment(value).format(\"HH:mm\");\n          } else {\n            return moment(value).format(\"HH:mm\") + \"\\n\" + moment(value).format(\"MM/DD\");\n          }\n        },\n      },\n    },\n    yAxis: {\n      type: \"value\",\n      max: (value) => {\n        let max;\n        if (limit && unitMap.formatter(limit) > value.max) {\n          max = unitMap.formatter(limit);\n        }\n        return max;\n      },\n      axisLabel: {\n        showMaxLabel: true,\n        formatter: function (value) {\n          if (value < 10000) {\n            return value;\n          }\n          return (value / 10000).toFixed(1) + \"W\";\n        },\n      },\n    },\n    series: [...seriesData],\n    animation: false,\n  } as ECOption;\n};\n\nexport const getOption = ({\n  metrics,\n  configData,\n  isMoreDay = false,\n  isMarkLine = false,\n  isShowTooltipModal = false,\n  showLegend = true,\n  isShowTaskTooltipModal = false,\n  clusterPhyName = \"\",\n  needShowClusterName = false,\n  limit,\n}) => {\n  if (!metrics || !metrics.type) {\n    return {};\n  }\n\n  const title = (configData[metrics.type] && configData[metrics.type].title()) || metrics.type;\n  const xAxisData = [];\n  const series = metrics.metricsContents.map((item, index) => ({\n    name: needShowClusterName ? `${item.cluster || \"\"}_${item.name}` : item.name,\n    data: item.metricsContentCells\n      .sort((a, b) => a.timeStamp - b.timeStamp)\n      .map((item) => {\n        if (index === 0) {\n          xAxisData.push(item.timeStamp);\n        }\n        return {\n          value: item.value,\n          timestamp: item.timeStamp,\n        };\n      }),\n  }));\n\n  return getLineOption({\n    title,\n    xAxisData,\n    series,\n    unitMap: configData[metrics.type]?.unit,\n    isMoreDay,\n    isMarkLine,\n    isShowTooltipModal,\n    metricsType: metrics.type,\n    showLegend,\n    clusterPhyName,\n    isShowTaskTooltipModal,\n    limit,\n  });\n};\n\nexport const objFlat = (data: { [key: string]: any[] }) => {\n  const arr = [];\n\n  for (let key in data) {\n    arr.push(...data[key]);\n  }\n\n  return arr;\n};\n\nexport const ellipsis = (str: string | number, num: number, unit: string = \"\") => {\n  return String(str).length > num ? (\n    <Tooltip placement=\"top\" title={`${str}${unit || \"\"}`}>\n      {String(str).substring(0, num) + \"...\"}\n      {unit}\n    </Tooltip>\n  ) : (\n    str + unit\n  );\n};\n\nexport interface IPeriod {\n  label: string;\n  key: string;\n  dateRange: [number, moment.Moment];\n}\n\nconst oneHour = 1000 * 60 * 60;\nconst oneDay = 24 * oneHour;\n\nexport const PERIOD_RADIO = [\n  {\n    label: \"近1小时\",\n    key: \"oneHour\",\n    get dateRange() {\n      const timestamp = new Date().getTime();\n      return [moment(timestamp - oneHour), moment(timestamp)];\n    },\n  },\n  {\n    label: \"近1天\",\n    key: \"oneDay\",\n    get dateRange() {\n      const timestamp = new Date().getTime();\n      return [moment(timestamp - oneDay), moment(timestamp)];\n    },\n  },\n  {\n    label: \"近3天\",\n    key: \"threeDay\",\n    get dateRange() {\n      const timestamp = new Date().getTime();\n      return [moment(timestamp - oneDay * 3), moment(timestamp)];\n    },\n  },\n  {\n    label: \"近7天\",\n    key: \"sevenDay\",\n    get dateRange() {\n      const timestamp = new Date().getTime();\n      return [moment(timestamp - oneDay * 7), moment(timestamp)];\n    },\n  },\n] as IPeriod[];\n\nconst periodRadioMap = new Map<string, IPeriod>();\n\nPERIOD_RADIO.forEach((p) => {\n  periodRadioMap.set(p.key, p);\n});\n\nexport const PERIOD_RADIO_MAP = periodRadioMap;\n\nexport const formatterTimeYMDHMS = (timestamp) => {\n  return moment(timestamp).format(\"YYYY-MM-DD HH:mm:ss\");\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/clientnode-config.tsx",
    "content": "import { addChartTitle, unitMap } from \"../config\";\nexport const indexConfigClassifyList: string[] = [\"ClientNode性能指标\"];\n\nexport const indexConfigData = {\n  queryClientNode: {\n    name: \"clientNode查询\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角ES ClientNode查询请求速率\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为true时相应节点对于clientNode字段的指定时间间隔的查询次数/指定时间间隔min\",\n  },\n  writeClientNode: {\n    name: \"clientNode写入请求量\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角ES ClientNode写入请求速率\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为false时相应节点对于clientNode字段的指定时间间隔的写入次数/指定时间间隔min\",\n  },\n  dslLen: {\n    name: \"clientNode写入吞吐量\",\n    unit: unitMap.characterMin,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角ES ClientNode写入吞吐量\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为false时相应节点对于clientNode字段的指定时间间隔的dslLen的平均长度\",\n  },\n};\n\n// 给指标配置项添加标题\naddChartTitle(indexConfigData);\n\nexport const getCheckedData = (checkedList) => {\n  const defaultClassifyData = {};\n  indexConfigClassifyList.forEach((item) => {\n    defaultClassifyData[item] = [];\n  });\n  checkedList.forEach((item) => {\n    if (indexConfigData[item]) {\n      defaultClassifyData[indexConfigData[item].classify].push(item);\n    }\n  });\n  return defaultClassifyData;\n};\n\nexport const allCheckedData = getCheckedData(Object.keys(indexConfigData));\n\ninterface defaultIndexConfigItemPropsType {\n  title: string;\n  plainOptions: { label: string; value: string }[];\n}\n\nexport const defaultIndexConfigList: defaultIndexConfigItemPropsType[] = indexConfigClassifyList.map((item) => ({\n  title: item,\n  plainOptions: allCheckedData[item].map((item) => ({\n    label: indexConfigData[item].name,\n    value: item,\n  })),\n}));\n\nexport const parseLineParams = (data) => {\n  const title = data.nodeMetricsType;\n  const xAxis = data.nodesSubMetrics[0].nodeMetricsContentCells.map((item) => item.timeStamp);\n  const series = data.nodesSubMetrics.map((item) => {\n    return {\n      name: item.nodeIp,\n      data: item.nodeMetricsContentCells.map((item) => ({\n        value: item.nodeMetricsValue,\n        timeStamp: item.timeStamp,\n      })),\n    };\n  });\n  return { title, xAxis, series };\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/clientnode-view.tsx",
    "content": "import { TOP_MAP, TOP_TIME_RANGE, TOP_TYPE } from \"constants/status-map\";\nimport React, { memo, useState, useEffect, useCallback, useRef } from \"react\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport _ from \"lodash\";\nimport { defaultIndexConfigList, allCheckedData, getCheckedData } from \"./clientnode-config\";\nimport { objFlat, getOption } from \"../config\";\nimport { getRenderToolTip } from \"./config\";\nimport { indexConfigData } from \"./clientnode-config\";\nimport { IndexConfig, SelectRadio, Line } from \"../components\";\nimport { getCheckedList, setCheckedList, getNodeIpList, getClientNodeViewData, getClientNodeList } from \"../../../api/gateway-kanban\";\nimport \"../style/index\";\nimport { setIsUpdate } from \"actions/gateway-kanban\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport DragGroup from \"../../../d1-packages/drag-group/DragGroup\";\nimport { OperationPanel } from \"../components/operation-panel\";\nimport { copyString } from \"lib/utils\";\n\nexport const classPrefix = \"monitor\";\n\nconst CLINETNODE = \"clientNode\";\n\nexport const ClientNodeView = memo(() => {\n  const { startTime, endTime, isMoreDay, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      startTime: (state as any).gatewayKanban.startTime,\n      endTime: (state as any).gatewayKanban.endTime,\n      isMoreDay: (state as any).gatewayKanban.isMoreDay,\n      isUpdate: (state as any).gatewayKanban.isUpdate,\n      timeRadioKey: (state as any).gatewayKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n  const dispatch = useDispatch();\n\n  const selectRadioValue = useRef({\n    topNum: TOP_MAP[0].value,\n    topTimeStep: TOP_TIME_RANGE[0].value,\n    topMethod: TOP_TYPE[0].value,\n    content: undefined,\n    secondValue: \"\",\n  });\n\n  const reloadPage = () => {\n    dispatch(setIsUpdate(!isUpdate));\n  };\n\n  const [clientNodeIp, setClientNodeIp] = useState(\"\");\n  const [nodeIpList, setNodeIpList] = useState([]);\n  const [clientNodeList, setclientNodeList] = useState([]);\n  const [checkedData, setCheckedData] = useState(getCheckedData([]));\n  const [metricsTypes, setMetricsTypes] = useState([]);\n  const [viewData, setViewData] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const [clientNodeLoading, setClientNodeLoading] = useState(false);\n\n  const isFirst = useRef(true);\n  const timeDiff = useRef(0);\n  const prevTopNu = useRef(TOP_MAP[0].value);\n\n  const sortEnd = ({ oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(checkedData[\"ClientNode性能指标\"], oldIndex, newIndex);\n    checkedData[\"ClientNode性能指标\"] = listsNew;\n    const checkedList = objFlat(checkedData);\n    setCheckedList(CLINETNODE, checkedList);\n    setMetricsTypes([...listsNew]);\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(CLINETNODE);\n      if (!checkedList || checkedList.length === 0) {\n        setCheckedData(allCheckedData);\n      } else {\n        setCheckedData(getCheckedData(checkedList));\n      }\n    } catch (error) {\n      setCheckedData(allCheckedData);\n      console.log(error);\n    }\n  };\n\n  const getAsyncNodeViewIpList = async () => {\n    try {\n      const ipList = await getNodeIpList();\n      setNodeIpList(ipList);\n    } catch (error) {\n      console.log(error);\n    }\n  };\n\n  const getAsyncClientNodeViewList = async () => {\n    setClientNodeLoading(true);\n    try {\n      const clientNodeList = await getClientNodeList(selectRadioValue.current.content, startTime, endTime);\n      const newClientNodeList = clientNodeList.map((item) => {\n        return {\n          name: `${item.v1}_${item.v2}`,\n          value: item.v2,\n        };\n      });\n\n      selectRadioValue.current.secondValue = newClientNodeList?.[0]?.value || \"\";\n      selectRadioValue.current.topNum = newClientNodeList.length ? 0 : selectRadioValue.current.topNum;\n\n      setClientNodeLoading(false);\n      setclientNodeList(newClientNodeList);\n    } catch (error) {\n      console.log(error);\n      setClientNodeLoading(false);\n    }\n  };\n\n  const setIndexConfigCheckedData = (changeCheckedData) => {\n    const checkedList = objFlat(changeCheckedData);\n    setCheckedList(CLINETNODE, checkedList);\n    setCheckedData(changeCheckedData);\n    reloadPage();\n  };\n\n  const getAsyncViewData = async (metricsTypes) => {\n    return await getClientNodeViewData(\n      metricsTypes,\n      startTime,\n      endTime,\n      selectRadioValue.current.topNum,\n      selectRadioValue.current.content,\n      selectRadioValue.current.secondValue,\n      selectRadioValue.current.topMethod,\n      selectRadioValue.current.topTimeStep\n    );\n  };\n\n  const getAllAsyncViewData = async (metricsTypes) => {\n    if (clientNodeLoading) return;\n    try {\n      setIsLoading(true);\n      let res = await getAsyncViewData(metricsTypes);\n      // 去空\n      res = res.filter((item) => {\n        return item.metricsContents && item.metricsContents.length;\n      });\n      setViewData(\n        res.map((item) =>\n          getOption({\n            metrics: item,\n            configData: indexConfigData,\n            isMoreDay,\n            isShowTooltipModal: true,\n            needShowClusterName: true,\n          })\n        )\n      );\n    } catch (error) {\n      setViewData([]);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const showTooltipModal = (md5, metricsType) => {\n    copyString(md5);\n  };\n\n  useEffect(() => {\n    window[\"showTooltipModal\"] = (md5, metricsType) => {\n      showTooltipModal(md5, metricsType);\n    };\n  }, []);\n\n  useEffect(() => {\n    getAsyncCheckedList();\n  }, []);\n\n  useEffect(() => {\n    getAsyncNodeViewIpList();\n  }, []);\n\n  useEffect(() => {\n    getAsyncClientNodeViewList();\n  }, [startTime, endTime, timeRadioKey]);\n\n  useEffect(() => {\n    if (selectRadioValue.current.topNum !== 0 && selectRadioValue.current.secondValue) {\n      setClientNodeIp(\"\");\n      selectRadioValue.current.secondValue = \"\";\n    }\n  }, [selectRadioValue.current.topNum]);\n\n  useEffect(() => {\n    setMetricsTypes(objFlat(checkedData));\n  }, [checkedData]);\n\n  useEffect(() => {\n    if (isFirst.current || timeDiff.current !== endTime - startTime || prevTopNu.current !== selectRadioValue.current.topNum) {\n      // setIsLoading(true);\n      timeDiff.current = endTime - startTime;\n      isFirst.current = false;\n      prevTopNu.current = selectRadioValue.current.topNum;\n    }\n    if (!metricsTypes || metricsTypes.length === 0) {\n      return;\n    }\n    getAllAsyncViewData(metricsTypes);\n  }, [metricsTypes, clientNodeLoading, clientNodeIp]);\n\n  const onSecondSelectChange = (value) => {\n    setClientNodeIp(value);\n    selectRadioValue.current.secondValue = value;\n  };\n\n  const onSelectRadioChange = (values, needReload) => {\n    selectRadioValue.current = values;\n    if (needReload) {\n      reloadPage();\n    }\n  };\n\n  const renderTopWhat = () => {\n    return (\n      <SelectRadio\n        onValueChange={onSelectRadioChange}\n        content={selectRadioValue.current.content}\n        contentList={nodeIpList}\n        placeholder=\"请选择Gateway节点\"\n        allowClear={true}\n        type=\"secondSelect\"\n        topNu={selectRadioValue.current.topNum}\n        secondSelectList={clientNodeList}\n        secondSelectValue={clientNodeIp}\n        secondSelectPlaceholder={\"请选择ESClient节点\"}\n        onSecondSelectChange={onSecondSelectChange}\n      />\n    );\n  };\n\n  const renderConfig = () => {\n    return (\n      <IndexConfig\n        title=\"ClientNode指标配置\"\n        optionList={defaultIndexConfigList}\n        checkedData={checkedData}\n        setCheckedData={setIndexConfigCheckedData}\n      />\n    );\n  };\n\n  const renderFilter = () => {\n    return (\n      <>\n        {clientNodeLoading ? null : renderTopWhat()}\n        {renderConfig()}\n      </>\n    );\n  };\n\n  return (\n    <>\n      <OperationPanel classPrefix={classPrefix} reloadPage={reloadPage} endTime={endTime} renderFilter={renderFilter} />\n      <div className={`${classPrefix}-overview-content-line`}>\n        <DragGroup\n          dragContainerProps={{\n            onSortEnd: sortEnd,\n            axis: \"xy\",\n            distance: 100,\n          }}\n          containerProps={{\n            grid: 12,\n            gutter: [10, 10],\n          }}\n        >\n          {metricsTypes.map((item, index) => (\n            <Line\n              key={`${item}`}\n              title={indexConfigData[item]?.title()}\n              tooltip={getRenderToolTip(indexConfigData[item])}\n              index={`${item}_${index}`}\n              option={viewData[index] || {}}\n              isLoading={isLoading}\n            />\n          ))}\n        </DragGroup>\n      </div>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/config.tsx",
    "content": "import React from \"react\";\nexport * from \"../config\";\nimport { IMenuItem } from \"typesPath/base-types\";\nimport { OverviewView } from \"./overview-view\";\nimport { IndexView } from \"./index-view\";\nimport { NodeView } from \"./node-view\";\nimport { ClientNodeView } from \"./clientnode-view\";\nimport { ProjectView } from \"./project-view\";\nimport { QueryTemplate } from \"./query-template\";\nimport InfoTooltip from \"component/infoTooltip\";\n\nexport enum TAB_LIST_KEY {\n  overview = \"overview\",\n  node = \"node\",\n  clientNode = \"clientNode\",\n  index = \"index\",\n  project = \"project\",\n  queryTemplate = \"queryTemplate\",\n}\n\nexport const TAB_LIST = [\n  {\n    name: \"节点\",\n    key: TAB_LIST_KEY.node,\n    content: () => <NodeView />,\n  },\n  {\n    name: \"ClientNode\",\n    key: TAB_LIST_KEY.clientNode,\n    content: () => <ClientNodeView />,\n  },\n  {\n    name: \"索引\",\n    key: TAB_LIST_KEY.index,\n    content: () => <IndexView />,\n  },\n  {\n    name: \"应用\",\n    key: TAB_LIST_KEY.project,\n    content: () => <ProjectView />,\n  },\n  {\n    name: \"查询模板\",\n    key: TAB_LIST_KEY.queryTemplate,\n    content: () => <QueryTemplate />,\n  },\n  {\n    name: \"总览\",\n    key: TAB_LIST_KEY.overview,\n    content: () => <OverviewView />,\n  },\n];\nconst menuMap = new Map<string, IMenuItem>();\n\nTAB_LIST.forEach((d) => {\n  menuMap.set(d.key, d);\n});\n\nexport const MENU_MAP = menuMap;\n\nexport const getRenderToolTip = (item) => {\n  return item?.currentCalLogic || item?.price || item?.threshold ? (\n    <InfoTooltip\n      className=\"indicators-info\"\n      currentCalLogic={item?.currentCalLogic}\n      price={item?.price}\n      threshold={item?.threshold}\n    ></InfoTooltip>\n  ) : null;\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/gateway-kanban.tsx",
    "content": "import React, { memo, useEffect, useState } from \"react\";\nimport { useDispatch } from \"react-redux\";\nimport { setGatewayForm } from \"../../../actions/gateway-kanban\";\nimport { oneDayMillims } from \"../../../constants/common\";\nimport { TAB_LIST, MENU_MAP } from \"./config\";\nimport { HashMenu } from \"knowdesign\";\nimport \"../style\";\n\nimport { RefreshTime } from \"../components\";\nimport { CustomPickTime } from \"../components/custom-time-picker\";\n\nexport const GatewayKanban = () => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const dispatch = useDispatch();\n  const [refreshTime, setRefreshTime] = useState(0);\n\n  const onTimeStampChange = (startTime: number, endTime: number, timeRadioKey?: string) => {\n    const timeMinus = endTime - startTime;\n    dispatch(\n      setGatewayForm({\n        startTime,\n        endTime,\n        isMoreDay: timeMinus > oneDayMillims,\n        timeRadioKey,\n      })\n    );\n  };\n\n  useEffect(() => {\n    const ONE_HOUR = 1000 * 60 * 60;\n    const currentTime = new Date().getTime();\n    dispatch(\n      setGatewayForm({\n        startTime: currentTime - ONE_HOUR,\n        endTime: currentTime - 120000,\n        isMoreDay: false,\n        timeRadioKey: \"oneHour\",\n      })\n    );\n  }, [department]);\n\n  return (\n    <>\n      <div className=\"hash-menu-container gateway\">\n        <HashMenu\n          prefix=\"gateway-kanban-content\"\n          TAB_LIST={TAB_LIST}\n          MENU_MAP={MENU_MAP}\n          defaultHash=\"node\"\n          // 监听页面权限的变化\n          key={department}\n        />\n        <CustomPickTime onTimeStampChange={onTimeStampChange} refreshTime={refreshTime} />\n        <div className=\"refresh-time gateway-refresh\">\n          <RefreshTime changeRefreshTime={setRefreshTime} />\n        </div>\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/index-view-config.tsx",
    "content": "import { addChartTitle, unitMap } from \"../config\";\n\n// 指标分类\nconst indexConfigClassifyList: string[] = [\"索引性能指标\"];\n\n// 指标项\nexport const indexConfigData = {\n  writeIndexCount: {\n    name: \"gateway对索引写入量\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角索引级写入请求速率\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为false时相应索引对于destTemplateName字段的指定时间间隔的写入次数/指定时间间隔min\",\n  },\n  writeIndexTotalCost: {\n    name: \"gateway对索引写入耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角索引级写入请求平均耗时\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为false时相应索引对于destTemplateName字段的指定时间间隔的totalCost的总和/指定时间间隔min\",\n  },\n  searchIndexCount: {\n    name: \"索引查询量分布\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角索引级查询请求速率\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为true时相应索引对于destTemplateName字段的指定时间间隔的查询次数/指定时间间隔min\",\n  },\n  searchIndexTotalCost: {\n    name: \"索引平均查询耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角索引级查询请求平均耗时\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为true时相应索引对于destTemplateName字段的指定时间间隔的totalCost的总和/指定时间间隔min\",\n  },\n};\n\n// 给指标配置项添加标题\naddChartTitle(indexConfigData);\n\nexport const getCheckedData = (checkedList) => {\n  const defaultClassifyData = {};\n\n  indexConfigClassifyList.forEach((item) => {\n    defaultClassifyData[item] = [];\n  });\n\n  checkedList.forEach((item) => {\n    if (indexConfigData[item]) {\n      defaultClassifyData[indexConfigData[item].classify].push(item);\n    }\n  });\n\n  return defaultClassifyData;\n};\n\nexport const allCheckedData = getCheckedData(Object.keys(indexConfigData));\n\ninterface defaultIndexConfigItemPropsType {\n  title: string;\n  plainOptions: { label: string; value: string }[];\n}\n\nexport const defaultIndexConfigList: defaultIndexConfigItemPropsType[] = indexConfigClassifyList.map((item) => ({\n  title: item,\n  plainOptions: allCheckedData[item].map((item) => ({\n    label: indexConfigData[item].name,\n    value: item,\n  })),\n}));\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/index-view.tsx",
    "content": "import React, { memo, useState, useEffect, useCallback, useRef } from \"react\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport _ from \"lodash\";\nimport { IndexConfig, Line, SelectRadio } from \"../components\";\nimport { defaultIndexConfigList, allCheckedData, getCheckedData, indexConfigData } from \"./index-view-config\";\nimport { getOption, objFlat } from \"../config\";\nimport { getRenderToolTip } from \"./config\";\nimport { TOP_MAP, TOP_TIME_RANGE, TOP_TYPE } from \"constants/status-map\";\nimport { getCheckedList, setCheckedList, getIndexViewData, getIndexNameList } from \"../../../api/gateway-kanban\";\nimport { setIsUpdate } from \"actions/gateway-kanban\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport DragGroup from \"../../../d1-packages/drag-group/DragGroup\";\nimport { OperationPanel } from \"../components/operation-panel\";\nimport { copyString } from \"lib/utils\";\n\nexport const classPrefix = \"monitor\";\n\nconst INDEX = \"index\";\n\nexport const IndexView = memo(() => {\n  const [indexNameList, setIndexNameList] = useState([]);\n  const [checkedData, setCheckedData] = useState(getCheckedData([]));\n  const [metricsTypes, setMetricsTypes] = useState([]);\n  const [viewData, setViewData] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const [indexLoading, setIndexLoading] = useState(false);\n  const { startTime, endTime, isMoreDay, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      startTime: (state as any).gatewayKanban.startTime,\n      endTime: (state as any).gatewayKanban.endTime,\n      isMoreDay: (state as any).gatewayKanban.isMoreDay,\n      isUpdate: (state as any).gatewayKanban.isUpdate,\n      timeRadioKey: (state as any).gatewayKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n  const selectRadioValue = useRef({\n    topNum: TOP_MAP[0].value,\n    topTimeStep: TOP_TIME_RANGE[0].value,\n    topMethod: TOP_TYPE[0].value,\n    content: undefined,\n  });\n\n  const dispatch = useDispatch();\n  const isFirst = useRef(true);\n  const timeDiff = useRef(0);\n  const prevTopNu = useRef(TOP_MAP[0].value);\n\n  const sortEnd = ({ oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(checkedData[\"索引性能指标\"], oldIndex, newIndex);\n    checkedData[\"索引性能指标\"] = listsNew;\n    const checkedList = objFlat(checkedData);\n    setCheckedList(INDEX, checkedList);\n    setMetricsTypes([...listsNew]);\n  };\n\n  const reloadPage = () => {\n    dispatch(setIsUpdate(!isUpdate));\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(INDEX);\n      if (!checkedList || checkedList.length === 0) {\n        setCheckedData(allCheckedData);\n      } else {\n        setCheckedData(getCheckedData(checkedList));\n      }\n    } catch (error) {\n      setCheckedData(allCheckedData);\n      console.log(error);\n    }\n  };\n\n  const setIndexConfigCheckedData = (changeCheckedData) => {\n    const checkedList = objFlat(changeCheckedData);\n    setCheckedList(INDEX, checkedList);\n    setCheckedData(changeCheckedData);\n    reloadPage();\n  };\n\n  const getAsyncViewData = useCallback(\n    async (metricsTypes) => {\n      return await getIndexViewData(\n        metricsTypes,\n        startTime,\n        endTime,\n        selectRadioValue.current.topNum,\n        selectRadioValue.current.content,\n        selectRadioValue.current.topMethod,\n        selectRadioValue.current.topTimeStep\n      );\n    },\n    [startTime, endTime, timeRadioKey, indexLoading]\n  );\n  const getAllAsyncViewData = async (metricsTypes) => {\n    try {\n      setIsLoading(true);\n      const res = await getAsyncViewData(metricsTypes);\n      setViewData(\n        res.map((item) =>\n          getOption({\n            metrics: item,\n            configData: indexConfigData,\n            isMoreDay,\n            isShowTooltipModal: true,\n          })\n        )\n      );\n    } catch (error) {\n      setViewData([]);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const getAsyncIndexNameList = async () => {\n    setIndexLoading(true);\n    try {\n      const indexNameList = await getIndexNameList();\n      // if (indexNameList.length) {\n      //   selectRadioValue.current.content = indexNameList[0];\n      //   selectRadioValue.current.topNum = 0;\n      // }\n      await setIndexLoading(false);\n      setIndexNameList(indexNameList);\n    } catch (error) {\n      console.log(error);\n      setIndexLoading(false);\n    }\n  };\n\n  const showTooltipModal = (md5, metricsType) => {\n    copyString(md5);\n  };\n\n  useEffect(() => {\n    window[\"showTooltipModal\"] = (md5, metricsType) => {\n      showTooltipModal(md5, metricsType);\n    };\n  }, []);\n\n  useEffect(() => {\n    getAsyncCheckedList();\n  }, []);\n\n  useEffect(() => {\n    setMetricsTypes(objFlat(checkedData));\n  }, [checkedData]);\n\n  useEffect(() => {\n    getAsyncIndexNameList();\n  }, []);\n\n  useEffect(() => {\n    if (isFirst.current || timeDiff.current !== endTime - startTime || prevTopNu.current !== selectRadioValue.current.topNum) {\n      setIsLoading(true);\n      timeDiff.current = endTime - startTime;\n      isFirst.current = false;\n      prevTopNu.current = selectRadioValue.current.topNum;\n    }\n    if (!metricsTypes || metricsTypes.length === 0) {\n      return;\n    }\n    if (indexLoading) return;\n\n    getAllAsyncViewData(metricsTypes);\n  }, [metricsTypes, getAsyncViewData]);\n\n  const onSelectRadioChange = (values, needReload) => {\n    selectRadioValue.current = values;\n    if (needReload) {\n      reloadPage();\n    }\n  };\n\n  const renderTopWhat = () => {\n    return (\n      <SelectRadio\n        onValueChange={onSelectRadioChange}\n        topNu={selectRadioValue.current.topNum}\n        content={selectRadioValue.current.content}\n        contentList={indexNameList}\n        placeholder=\"请选择索引\"\n        style={{ width: '100%' }}\n      />\n    );\n  };\n\n  const renderConfig = () => {\n    return (\n      <IndexConfig\n        title=\"索引指标配置\"\n        optionList={defaultIndexConfigList}\n        checkedData={checkedData}\n        setCheckedData={setIndexConfigCheckedData}\n      />\n    );\n  };\n\n  const renderFilter = () => {\n    return (\n      <>\n        {indexLoading ? null : renderTopWhat()}\n        {renderConfig()}\n      </>\n    );\n  };\n\n  return (\n    <>\n      <OperationPanel classPrefix={classPrefix} reloadPage={reloadPage} endTime={endTime} renderFilter={renderFilter} />\n      <div className={`${classPrefix}-overview-content-line`}>\n        <DragGroup\n          dragContainerProps={{\n            onSortEnd: sortEnd,\n            axis: \"xy\",\n            distance: 100,\n          }}\n          containerProps={{\n            grid: 12,\n            gutter: [10, 10],\n          }}\n        >\n          {metricsTypes.map((item, index) => (\n            <Line\n              key={`${item}`}\n              title={indexConfigData[item]?.title()}\n              tooltip={getRenderToolTip(indexConfigData[item])}\n              index={`${item}_${index}`}\n              option={viewData[index] || {}}\n              isLoading={isLoading}\n            />\n          ))}\n        </DragGroup>\n      </div>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/node-view-config.tsx",
    "content": "import { addChartTitle, unitMap } from \"../config\";\nexport const indexConfigClassifyList: string[] = [\"节点性能指标\"];\n\nexport const indexConfigData = {\n  writeGatewayNode: {\n    name: \"gatewayNode写入请求量\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway节点级写入请求速率\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为false时相应节点对于gatewayNode字段的指定时间间隔的写入次数/指定时间间隔min\",\n  },\n  dslLen: {\n    name: \"gatewayNode写入吞吐量\",\n    unit: unitMap.characterMin,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway节点级写入请求吞吐量\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为false时相应节点对于gatewayNode字段的指定时间间隔的dslLen的平均长度\",\n  },\n  queryGatewayNode: {\n    name: \"gatewayNode查询\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway节点级查询请求速率\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为true时相应节点对于gatewayNode字段的指定时间间隔的查询次数/指定时间隔间min\",\n  },\n  // queryClientNode: {\n  //   name: \"gateway各clientnode查询分布\",\n  //   unit: unitMap.numS,\n  //   classify: indexConfigClassifyList[0],\n  // },\n  // writeClientNode: {\n  //   name: \"gateway各clientnode写入分布\",\n  //   unit: unitMap.itemMin,\n  //   classify: indexConfigClassifyList[0],\n  // },\n};\n\n// 给指标配置项添加标题\naddChartTitle(indexConfigData);\n\nexport const getCheckedData = (checkedList) => {\n  const defaultClassifyData = {};\n  indexConfigClassifyList.forEach((item) => {\n    defaultClassifyData[item] = [];\n  });\n  checkedList.forEach((item) => {\n    if (indexConfigData[item]) {\n      defaultClassifyData[indexConfigData[item].classify].push(item);\n    }\n  });\n  return defaultClassifyData;\n};\n\nexport const allCheckedData = getCheckedData(Object.keys(indexConfigData));\n\ninterface defaultIndexConfigItemPropsType {\n  title: string;\n  plainOptions: { label: string; value: string }[];\n}\n\nexport const defaultIndexConfigList: defaultIndexConfigItemPropsType[] = indexConfigClassifyList.map((item) => ({\n  title: item,\n  plainOptions: allCheckedData[item].map((item) => ({\n    label: indexConfigData[item].name,\n    value: item,\n  })),\n}));\n\nexport const parseLineParams = (data) => {\n  const title = data.nodeMetricsType;\n  const xAxis = data.nodesSubMetrics[0].nodeMetricsContentCells.map((item) => item.timeStamp);\n  const series = data.nodesSubMetrics.map((item) => {\n    return {\n      name: item.nodeIp,\n      data: item.nodeMetricsContentCells.map((item) => ({\n        value: item.nodeMetricsValue,\n        timeStamp: item.timeStamp,\n      })),\n    };\n  });\n  return { title, xAxis, series };\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/node-view.tsx",
    "content": "import { TOP_MAP, TOP_TIME_RANGE, TOP_TYPE } from \"constants/status-map\";\nimport React, { memo, useState, useEffect, useCallback, useRef } from \"react\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport _ from \"lodash\";\nimport { defaultIndexConfigList, allCheckedData, getCheckedData } from \"./node-view-config\";\nimport { objFlat, getOption } from \"../config\";\nimport { getRenderToolTip } from \"./config\";\nimport { indexConfigData } from \"./node-view-config\";\nimport { IndexConfig, SelectRadio, Line } from \"../components\";\nimport { getCheckedList, setCheckedList, getNodeViewData, getNodeIpList } from \"../../../api/gateway-kanban\";\nimport \"../style/index\";\nimport { setIsUpdate } from \"actions/gateway-kanban\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport DragGroup from \"../../../d1-packages/drag-group/DragGroup\";\nimport { OperationPanel } from \"../components/operation-panel\";\nimport { copyString } from \"lib/utils\";\n\nexport const classPrefix = \"monitor\";\n\nconst NODE = \"node\";\n\nexport const NodeView = memo(() => {\n  const { startTime, endTime, isMoreDay, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      startTime: (state as any).gatewayKanban.startTime,\n      endTime: (state as any).gatewayKanban.endTime,\n      isMoreDay: (state as any).gatewayKanban.isMoreDay,\n      isUpdate: (state as any).gatewayKanban.isUpdate,\n      timeRadioKey: (state as any).gatewayKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n  const dispatch = useDispatch();\n\n  const reloadPage = () => {\n    dispatch(setIsUpdate(!isUpdate));\n  };\n\n  const [nodeIpList, setNodeIpList] = useState([]);\n  const [checkedData, setCheckedData] = useState(getCheckedData([]));\n  const [metricsTypes, setMetricsTypes] = useState([]);\n  const [viewData, setViewData] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const isFirst = useRef(true);\n  const timeDiff = useRef(0);\n  const prevTopNu = useRef(TOP_MAP[0].value);\n  const selectRadioValue = useRef({\n    topNum: TOP_MAP[0].value,\n    topTimeStep: TOP_TIME_RANGE[0].value,\n    topMethod: TOP_TYPE[0].value,\n    content: [],\n  });\n\n  const sortEnd = ({ oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(checkedData[\"节点性能指标\"], oldIndex, newIndex);\n    checkedData[\"节点性能指标\"] = listsNew;\n    const checkedList = objFlat(checkedData);\n    setCheckedList(NODE, checkedList);\n    setMetricsTypes([...listsNew]);\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(NODE);\n      if (!checkedList || checkedList.length === 0) {\n        setCheckedData(allCheckedData);\n      } else {\n        setCheckedData(getCheckedData(checkedList));\n      }\n    } catch (error) {\n      setCheckedData(allCheckedData);\n      console.log(error);\n    }\n  };\n\n  const getAsyncNodeViewIpList = async () => {\n    try {\n      const ipList = await getNodeIpList();\n      setNodeIpList(ipList);\n    } catch (error) {\n      console.log(error);\n    }\n  };\n\n  const setIndexConfigCheckedData = (changeCheckedData) => {\n    const checkedList = objFlat(changeCheckedData);\n    setCheckedList(NODE, checkedList);\n    setCheckedData(changeCheckedData);\n    reloadPage();\n  };\n\n  const getAsyncViewData = useCallback(\n    async (metricsTypes) => {\n      return await getNodeViewData(\n        metricsTypes,\n        startTime,\n        endTime,\n        selectRadioValue.current.topNum,\n        selectRadioValue.current.content,\n        selectRadioValue.current.topMethod,\n        selectRadioValue.current.topTimeStep\n      );\n    },\n    [startTime, endTime, timeRadioKey]\n  );\n\n  const getAllAsyncViewData = async (metricsTypes) => {\n    try {\n      setIsLoading(true);\n      const res = await getAsyncViewData(metricsTypes);\n      setViewData(\n        res.map((item) =>\n          getOption({\n            metrics: item,\n            configData: indexConfigData,\n            isMoreDay,\n            isShowTooltipModal: true,\n          })\n        )\n      );\n    } catch (error) {\n      setViewData([]);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const showTooltipModal = (md5, metricsType) => {\n    copyString(md5);\n  };\n\n  useEffect(() => {\n    window[\"showTooltipModal\"] = (md5, metricsType) => {\n      showTooltipModal(md5, metricsType);\n    };\n  }, []);\n\n  useEffect(() => {\n    getAsyncCheckedList();\n  }, []);\n\n  useEffect(() => {\n    getAsyncNodeViewIpList();\n  }, []);\n\n  useEffect(() => {\n    setMetricsTypes(objFlat(checkedData));\n  }, [checkedData]);\n\n  useEffect(() => {\n    if (isFirst.current || timeDiff.current !== endTime - startTime || prevTopNu.current !== selectRadioValue.current.topNum) {\n      setIsLoading(true);\n      timeDiff.current = endTime - startTime;\n      isFirst.current = false;\n      prevTopNu.current = selectRadioValue.current.topNum;\n    }\n    if (!metricsTypes || metricsTypes.length === 0) {\n      return;\n    }\n    getAllAsyncViewData(metricsTypes);\n  }, [metricsTypes, getAsyncViewData]);\n\n  const onSelectRadioChange = (values, needReload) => {\n    selectRadioValue.current = values;\n    if (needReload) {\n      reloadPage();\n    }\n  };\n\n  const renderTopWhat = () => {\n    return (\n      <SelectRadio\n        onValueChange={onSelectRadioChange}\n        content={selectRadioValue.current.content}\n        contentList={nodeIpList}\n        placeholder=\"请选择节点名称\"\n        type=\"node\"\n      />\n    );\n  };\n\n  const renderConfig = () => {\n    return (\n      <IndexConfig\n        title=\"节点指标配置\"\n        optionList={defaultIndexConfigList}\n        checkedData={checkedData}\n        setCheckedData={setIndexConfigCheckedData}\n      />\n    );\n  };\n\n  const renderFilter = () => {\n    return (\n      <>\n        {renderTopWhat()}\n        {renderConfig()}\n      </>\n    );\n  };\n\n  return (\n    <>\n      <OperationPanel classPrefix={classPrefix} reloadPage={reloadPage} endTime={endTime} renderFilter={renderFilter} />\n      <div className={`${classPrefix}-overview-content-line`}>\n        <DragGroup\n          dragContainerProps={{\n            onSortEnd: sortEnd,\n            axis: \"xy\",\n            distance: 100,\n          }}\n          containerProps={{\n            grid: 12,\n            gutter: [10, 10],\n          }}\n        >\n          {metricsTypes.map((item, index) => (\n            <Line\n              key={`${item}`}\n              title={indexConfigData[item]?.title()}\n              tooltip={getRenderToolTip(indexConfigData[item])}\n              index={`${item}_${index}`}\n              option={viewData[index] || {}}\n              isLoading={isLoading}\n            />\n          ))}\n        </DragGroup>\n      </div>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/overview-view-config.tsx",
    "content": "import { getLineOption } from \"./config\";\nimport { unitMap, addChartTitle } from \"../config\";\n\n// 指标配置 start\nexport const indexConfigClassifyList: string[] = [\"总览性能指标\"];\n\nexport const indexConfigData = {\n  writeDocCount: {\n    name: \"写入请求量\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway集群写入请求速率\",\n    currentCalLogic: \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为false时指定时间间隔的写入次数/指定时间min\",\n  },\n  writeTotalCost: {\n    name: \"写入平均耗时\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway集群写入请求平均耗时\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为false时指定时间间隔的totalCost的总和/指定时间间隔min\",\n  },\n  writeResponseLen: {\n    name: \"写入响应长度平均值\",\n    unit: unitMap.byte,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway集群写入请求响应体平均大小\",\n    currentCalLogic: \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为false时指定时间间隔的responseLen的平均长度\",\n  },\n  queryTotalHitsAvgCount: {\n    name: \"查询平均命中量\",\n    unit: unitMap.itemMin,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway集群查询请求TotalHits平均值\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为true时指定时间间隔的totalHits的总和/指定时间间隔min\",\n  },\n  readDocCount: {\n    name: \"查询量\",\n    unit: unitMap.mins,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway集群查询请求速率\",\n    currentCalLogic: \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为true时指定时间间隔的查询次数/指定时间min\",\n  },\n  queryCostAvg: {\n    name: \"查询平均响应时间\",\n    unit: unitMap.ms,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway集群查询请求平均响应时间\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为true时指定时间间隔的totalCost的总和/指定时间间隔min\",\n  },\n  queryTotalShardsAvg: {\n    name: \"查询shard平均数\",\n    unit: unitMap.countM,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway集群查询请求平均命中Shard数\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为true时指定时间间隔的totalShards的总和/指定时间间隔min\",\n  },\n  dslLen: {\n    name: \"写入吞吐量\",\n    unit: unitMap.characterMin,\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway集群写入请求吞吐量\",\n    currentCalLogic: \"[平均值] 聚合查询arius_gateway_join索引获取指定时间queryRequest字段为false时指定时间间隔的dslLen的平均长度\",\n  },\n};\n\n// 给指标配置项添加标题\naddChartTitle(indexConfigData);\n\nexport const getCheckedData = (checkedList) => {\n  const defaultClassifyData = {};\n  indexConfigClassifyList.forEach((item) => {\n    defaultClassifyData[item] = [];\n  });\n  checkedList.forEach((item) => {\n    if (indexConfigData[item]) {\n      defaultClassifyData[indexConfigData[item].classify].push(item);\n    }\n  });\n  return defaultClassifyData;\n};\n\nexport const allCheckedData = getCheckedData(Object.keys(indexConfigData));\n\ninterface defaultIndexConfigItemPropsType {\n  title: string;\n  plainOptions: { label: string; value: string }[];\n}\n\n// 指标配置项\nexport const defaultIndexConfigList: defaultIndexConfigItemPropsType[] = indexConfigClassifyList.map((item) => ({\n  title: item,\n  plainOptions: allCheckedData[item].map((item) => ({\n    label: indexConfigData[item].name,\n    value: item,\n  })),\n}));\n\nexport interface metricsType {\n  metrics: { timeStamp: number; value: number }[];\n  type: string;\n}\n\nexport const getOverviewOption = (metrics: metricsType, configData, isMoreDay: boolean = false, isMarkLine: boolean = false) => {\n  if (!metrics || !metrics.type || !configData[metrics.type]) {\n    return {};\n  }\n  const title = (configData[metrics.type] && configData[metrics.type].title()) || metrics.type;\n  const xAxisData = [];\n  const series = [\n    {\n      name: configData[metrics.type].name || metrics.type,\n      data: metrics.metrics.map((item) => {\n        if (!xAxisData.includes(item.timeStamp)) {\n          xAxisData.push(item.timeStamp);\n        }\n        return {\n          value: item.value,\n          timestamp: item.timeStamp,\n        };\n      }),\n    },\n  ];\n\n  xAxisData.sort((a, b) => a - b);\n\n  return getLineOption({\n    title,\n    xAxisData,\n    series,\n    unitMap: configData[metrics.type]?.unit || {},\n    isMoreDay,\n    isMarkLine,\n  });\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/overview-view.tsx",
    "content": "import { SyncOutlined } from \"@ant-design/icons\";\nimport { Skeleton } from \"antd\";\nimport React, { memo, useState, useEffect, useCallback, useRef } from \"react\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport _ from \"lodash\";\nimport { IndexConfig, Line } from \"../components\";\nimport { formatterTimeYMDHMS, objFlat, getRenderToolTip } from \"./config\";\nimport { defaultIndexConfigList, allCheckedData, getCheckedData, indexConfigData, getOverviewOption } from \"./overview-view-config\";\nimport { getCheckedList, setCheckedList, getOverviewData } from \"../../../api/gateway-kanban\";\n\nimport \"../style/index\";\nimport { setIsUpdate } from \"actions/gateway-kanban\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport DragGroup from \"../../../d1-packages/drag-group/DragGroup\";\n\nconst OVERVIEW = \"overview\";\n\nexport const classPrefix = \"monitor\";\n\nexport const OverviewView = memo(() => {\n  const { startTime, endTime, isMoreDay, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      startTime: (state as any).gatewayKanban.startTime,\n      endTime: (state as any).gatewayKanban.endTime,\n      isMoreDay: (state as any).gatewayKanban.isMoreDay,\n      isUpdate: (state as any).gatewayKanban.isUpdate,\n      timeRadioKey: (state as any).gatewayKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n  const dispatch = useDispatch();\n\n  const reloadPage = () => {\n    dispatch(setIsUpdate(!isUpdate));\n  };\n\n  const [checkedData, setCheckedData] = useState(getCheckedData([]));\n  const [metricsTypes, setMetricsTypes] = useState([]);\n  const [viewData, setViewData] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const isFirst = useRef(true);\n  const timeDiff = useRef(0);\n\n  const sortEnd = ({ oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(checkedData[\"总览性能指标\"], oldIndex, newIndex);\n    checkedData[\"总览性能指标\"] = listsNew;\n    const checkedList = objFlat(checkedData);\n    setCheckedList(OVERVIEW, checkedList);\n    setMetricsTypes([...listsNew]);\n  };\n\n  const getAsyncOverviewData = useCallback(\n    async (metricsTypes) => {\n      return await getOverviewData(metricsTypes, startTime, endTime);\n    },\n    [startTime, endTime, timeRadioKey]\n  );\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(OVERVIEW);\n      if (!checkedList || checkedList.length === 0) {\n        setCheckedData(allCheckedData);\n      } else {\n        setCheckedData(getCheckedData(checkedList));\n      }\n    } catch (error) {\n      setCheckedData(allCheckedData);\n      console.log(error);\n    }\n  };\n\n  const setIndexConfigCheckedData = (changeCheckedData) => {\n    const checkedList = objFlat(changeCheckedData);\n    setCheckedList(OVERVIEW, checkedList);\n    setCheckedData(changeCheckedData);\n    reloadPage();\n  };\n\n  const getAllAsyncOverviewData = async (metricsTypes) => {\n    try {\n      setIsLoading(true);\n      const res = await getAsyncOverviewData(metricsTypes);\n      setViewData(res.map((item) => getOverviewOption(item, indexConfigData, isMoreDay)));\n    } catch (error) {\n      setViewData([]);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    getAsyncCheckedList();\n  }, []);\n\n  useEffect(() => {\n    setMetricsTypes(objFlat(checkedData));\n  }, [checkedData]);\n\n  useEffect(() => {\n    if (isFirst.current || timeDiff.current !== endTime - startTime) {\n      setIsLoading(true);\n      timeDiff.current = endTime - startTime;\n      isFirst.current = false;\n    }\n    if (!metricsTypes || metricsTypes.length === 0) {\n      return;\n    }\n    getAllAsyncOverviewData(metricsTypes);\n  }, [metricsTypes, getAsyncOverviewData]);\n\n  const renderConfig = () => {\n    return (\n      <IndexConfig\n        title=\"总览指标配置\"\n        optionList={defaultIndexConfigList}\n        checkedData={checkedData}\n        setCheckedData={setIndexConfigCheckedData}\n      />\n    );\n  };\n\n  return (\n    <>\n      <div className={`${classPrefix}-overview-search`}>\n        <div className={`${classPrefix}-overview-search-reload`}>\n          <SyncOutlined className=\"dashboard-config-icon\" onClick={reloadPage} />\n        </div>\n        <div className={`${classPrefix}-overview-search-filter`}>{renderConfig()}</div>\n      </div>\n      <div className={`${classPrefix}-overview-content-line`}>\n        <DragGroup\n          dragContainerProps={{\n            onSortEnd: sortEnd,\n            axis: \"xy\",\n            distance: 100,\n          }}\n          containerProps={{\n            grid: 12,\n            gutter: [10, 10],\n          }}\n        >\n          {metricsTypes.map((item, index) => (\n            <Line\n              key={`${item}`}\n              title={indexConfigData[item]?.title()}\n              tooltip={getRenderToolTip(indexConfigData[item])}\n              index={`${item}_${index}`}\n              option={viewData[index] || {}}\n              isLoading={isLoading}\n            />\n          ))}\n        </DragGroup>\n      </div>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/project-view-config.tsx",
    "content": "import { addChartTitle, unitMap } from \"../config\";\n\nconst indexConfigClassifyList: string[] = [\"应用性能指标\"];\n\nexport const indexConfigData = {\n  queryAppTotalCost: {\n    name: \"应用查询耗时平均值\",\n    unit: unitMap.ms,\n    title: function () {\n      return this.name + \"(ms)\";\n    },\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角应用级查询请求平均耗时\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间相应应用对于projectId字段的指定时间间隔的searchCost的总和/指定时间间隔min\",\n  },\n  queryAppCount: {\n    name: \"gateway各应用查询量\",\n    unit: unitMap.mins,\n    title: function () {\n      return this.name + \"(次/min)\";\n    },\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角应用级查询请求速率\",\n    currentCalLogic: \"[平均值] 聚合查询arius_gateway_join索引获取指定时间相应应用对于projectId字段的指定时间间隔的查询次数/指定时间间隔min\",\n  },\n};\n\n// 给指标配置项添加标题\naddChartTitle(indexConfigData);\n\nexport const getCheckedData = (checkedList) => {\n  const defaultClassifyData = {};\n  indexConfigClassifyList.forEach((item) => {\n    defaultClassifyData[item] = [];\n  });\n  checkedList.forEach((item) => {\n    if (indexConfigData[item]) {\n      defaultClassifyData[indexConfigData[item].classify].push(item);\n    }\n  });\n  return defaultClassifyData;\n};\n\nexport const allCheckedData = getCheckedData(Object.keys(indexConfigData));\n\ninterface defaultIndexConfigItemPropsType {\n  title: string;\n  plainOptions: { label: string; value: string }[];\n}\n\nexport const defaultIndexConfigList: defaultIndexConfigItemPropsType[] = indexConfigClassifyList.map((item) => ({\n  title: item,\n  plainOptions: allCheckedData[item].map((item) => ({\n    label: indexConfigData[item].name,\n    value: item,\n  })),\n}));\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/project-view.tsx",
    "content": "import React, { memo, useState, useEffect, useCallback, useRef } from \"react\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport _ from \"lodash\";\nimport { IndexConfig, Line, SelectRadio } from \"../components\";\nimport { defaultIndexConfigList, allCheckedData, getCheckedData, indexConfigData } from \"./project-view-config\";\nimport { getOption, objFlat } from \"../config\";\nimport { getRenderToolTip } from \"./config\";\nimport { TOP_MAP, TOP_TIME_RANGE, TOP_TYPE } from \"constants/status-map\";\nimport { getCheckedList, setCheckedList, getProjectViewData, getProjectIdList } from \"../../../api/gateway-kanban\";\nimport { setIsUpdate } from \"actions/gateway-kanban\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport DragGroup from \"../../../d1-packages/drag-group/DragGroup\";\nimport { OperationPanel } from \"../components/operation-panel\";\nimport { copyString } from \"lib/utils\";\n\nexport const classPrefix = \"monitor\";\n\nconst secondUserConfigType = \"app\";\n\nexport const ProjectView = memo(() => {\n  const [projectIdList, setProjectIdList] = useState([]);\n  const [checkedData, setCheckedData] = useState(getCheckedData([]));\n  const [metricsTypes, setMetricsTypes] = useState([]);\n  const [projectIdMap, setProjectIdMap] = useState({});\n  const [viewData, setViewData] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const [isGetProjectIdEnd, setIsGetProjectIdEnd] = useState(false);\n\n  const sortEnd = ({ oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(checkedData[\"应用性能指标\"], oldIndex, newIndex);\n    checkedData[\"应用性能指标\"] = listsNew;\n    const checkedList = objFlat(checkedData);\n    setCheckedList(secondUserConfigType, checkedList);\n    setMetricsTypes([...listsNew]);\n  };\n\n  const dispatch = useDispatch();\n  const { startTime, endTime, isMoreDay, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      startTime: (state as any).gatewayKanban.startTime,\n      endTime: (state as any).gatewayKanban.endTime,\n      isMoreDay: (state as any).gatewayKanban.isMoreDay,\n      isUpdate: (state as any).gatewayKanban.isUpdate,\n      timeRadioKey: (state as any).gatewayKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n\n  const selectRadioValue = useRef({\n    topNum: TOP_MAP[0].value,\n    topTimeStep: TOP_TIME_RANGE[0].value,\n    topMethod: TOP_TYPE[0].value,\n    content: undefined,\n  });\n\n  const isFirst = useRef(true);\n  const timeDiff = useRef(0);\n  const prevTopNu = useRef(TOP_MAP[0].value);\n\n  const reloadPage = () => {\n    dispatch(setIsUpdate(!isUpdate));\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(secondUserConfigType);\n      if (!checkedList || checkedList.length === 0) {\n        setCheckedData(allCheckedData);\n      } else {\n        setCheckedData(getCheckedData(checkedList));\n      }\n    } catch (error) {\n      setCheckedData(allCheckedData);\n      console.log(error);\n    }\n  };\n  const setIndexConfigCheckedData = (changeCheckedData) => {\n    const checkedList = objFlat(changeCheckedData);\n    setCheckedList(secondUserConfigType, checkedList);\n    setCheckedData(changeCheckedData);\n    reloadPage();\n  };\n\n  const getAsyncIndexNameList = async () => {\n    try {\n      const projectIdList = await getProjectIdList();\n      const projectIdMap = {};\n      const newProjectIdList = projectIdList.map((item) => {\n        projectIdMap[item.id] = item.projectName;\n        return { value: item.id, name: item.projectName };\n      });\n      // if (newProjectIdList.length) {\n      //   selectRadioValue.current.content = newProjectIdList[0].value;\n      //   selectRadioValue.current.topNum = 0;\n      // }\n      setProjectIdList(newProjectIdList);\n      setProjectIdMap(projectIdMap);\n    } catch (error) {\n      console.log(error);\n    } finally {\n      setIsGetProjectIdEnd(true);\n    }\n  };\n\n  const getAsyncViewData = useCallback(\n    async (metricsTypes) => {\n      if (isGetProjectIdEnd) {\n        const projectViewData = await getProjectViewData(\n          metricsTypes,\n          startTime,\n          endTime,\n          selectRadioValue.current.topNum,\n          selectRadioValue.current.content,\n          selectRadioValue.current.topMethod,\n          selectRadioValue.current.topTimeStep\n        );\n        return projectViewData.map((item) => ({\n          type: item.type,\n          metricsContents: item.metricsContents.map((cell) => ({\n            name: projectIdMap[cell.name] || cell.name,\n            metricsContentCells: cell.metricsContentCells,\n          })),\n        }));\n      }\n    },\n    [isGetProjectIdEnd, startTime, endTime, timeRadioKey]\n  );\n\n  const getAllAsyncViewData = async (metricsTypes) => {\n    try {\n      setIsLoading(true);\n      const res = await getAsyncViewData(metricsTypes);\n      setViewData(\n        res.map((item) =>\n          getOption({\n            metrics: item,\n            configData: indexConfigData,\n            isMoreDay,\n            isShowTooltipModal: true,\n          })\n        )\n      );\n    } catch (error) {\n      setViewData([]);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const showTooltipModal = (md5, metricsType) => {\n    copyString(md5);\n  };\n\n  useEffect(() => {\n    window[\"showTooltipModal\"] = (md5, metricsType) => {\n      showTooltipModal(md5, metricsType);\n    };\n  }, []);\n\n  useEffect(() => {\n    setMetricsTypes(objFlat(checkedData));\n  }, [checkedData]);\n\n  useEffect(() => {\n    getAsyncCheckedList();\n    getAsyncIndexNameList();\n  }, []);\n\n  useEffect(() => {\n    if (isFirst.current || timeDiff.current !== endTime - startTime || prevTopNu.current !== selectRadioValue.current.topNum) {\n      setIsLoading(true);\n      timeDiff.current = endTime - startTime;\n      isFirst.current = false;\n      prevTopNu.current = selectRadioValue.current.topNum;\n    }\n    if (!isGetProjectIdEnd || !metricsTypes || metricsTypes.length === 0) {\n      return;\n    }\n    getAllAsyncViewData(metricsTypes);\n  }, [metricsTypes, getAsyncViewData, isGetProjectIdEnd]);\n\n  const onSelectRadioChange = (values, needReload) => {\n    selectRadioValue.current = values;\n    if (needReload) {\n      reloadPage();\n    }\n  };\n\n  const renderTopWhat = () => {\n    return (\n      <SelectRadio\n        onValueChange={onSelectRadioChange}\n        topNu={selectRadioValue.current.topNum}\n        content={selectRadioValue.current.content}\n        contentList={projectIdList}\n        placeholder=\"请选择应用\"\n      />\n    );\n  };\n\n  const renderConfig = () => {\n    return (\n      <IndexConfig\n        title=\"应用指标配置\"\n        optionList={defaultIndexConfigList}\n        checkedData={checkedData}\n        setCheckedData={setIndexConfigCheckedData}\n      />\n    );\n  };\n\n  const renderFilter = () => {\n    return (\n      <>\n        {isGetProjectIdEnd ? renderTopWhat() : null}\n        {renderConfig()}\n      </>\n    );\n  };\n\n  return (\n    <>\n      <OperationPanel classPrefix={classPrefix} reloadPage={reloadPage} endTime={endTime} renderFilter={renderFilter} />\n      <div className={`${classPrefix}-overview-content-line`}>\n        <DragGroup\n          dragContainerProps={{\n            onSortEnd: sortEnd,\n            axis: \"xy\",\n            distance: 100,\n          }}\n          containerProps={{\n            grid: 12,\n            gutter: [10, 10],\n          }}\n        >\n          {metricsTypes.map((item, index) => (\n            <Line\n              key={`${item}_${index}`}\n              title={indexConfigData[item]?.title()}\n              tooltip={getRenderToolTip(indexConfigData[item])}\n              index={`${item}_${index}`}\n              option={viewData[index] || {}}\n              isLoading={isLoading}\n            />\n          ))}\n        </DragGroup>\n      </div>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/query-template-config.tsx",
    "content": "import { addChartTitle, unitMap } from \"../config\";\n\nconst indexConfigClassifyList: string[] = [\"查询模板性能配置\"];\n\nexport const indexConfigData = {\n  queryDslCount: {\n    name: \"查询模板访问量\",\n    unit: unitMap.mins,\n    title: function () {\n      return this.name + \"(次/min)\";\n    },\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角查询模板级请求速率\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间相应应用对于dslTemplateMd5字段的指定时间间隔的查询次数/指定时间间隔min\",\n  },\n  queryDslTotalCost: {\n    name: \"查询模板访问耗时\",\n    unit: unitMap.ms,\n    title: function () {\n      return this.name + \"(ms)\";\n    },\n    classify: indexConfigClassifyList[0],\n    price: \"Gateway视角查询模板级请求平均耗时\",\n    currentCalLogic:\n      \"[平均值] 聚合查询arius_gateway_join索引获取指定时间相应应用对于dslTemplateMd5字段的指定时间间隔的totalCost的总和/指定时间间隔min\",\n  },\n};\n\n// 给指标配置项添加标题\naddChartTitle(indexConfigData);\n\nexport const getCheckedData = (checkedList) => {\n  const defaultClassifyData = {};\n  indexConfigClassifyList.forEach((item) => {\n    defaultClassifyData[item] = [];\n  });\n  checkedList.forEach((item) => {\n    if (indexConfigData[item]) {\n      defaultClassifyData[indexConfigData[item].classify].push(item);\n    }\n  });\n  return defaultClassifyData;\n};\n\nexport const allCheckedData = getCheckedData(Object.keys(indexConfigData));\n\ninterface defaultIndexConfigItemPropsType {\n  title: string;\n  plainOptions: { label: string; value: string }[];\n}\n\nexport const defaultIndexConfigList: defaultIndexConfigItemPropsType[] = indexConfigClassifyList.map((item) => ({\n  title: item,\n  plainOptions: allCheckedData[item].map((item) => ({\n    label: indexConfigData[item].name,\n    value: item,\n  })),\n}));\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/gateway-kanban/query-template.tsx",
    "content": "import React, { memo, useState, useEffect, useCallback, useRef } from \"react\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport _ from \"lodash\";\nimport { IndexConfig, Line, SelectRadio } from \"../components\";\nimport { defaultIndexConfigList, allCheckedData, getCheckedData, indexConfigData } from \"./query-template-config\";\nimport { getOption, objFlat } from \"../config\";\nimport { getRenderToolTip } from \"./config\";\nimport { TOP_MAP, TOP_TIME_RANGE, TOP_TYPE } from \"constants/status-map\";\nimport { getCheckedList, setCheckedList, getQueryTemplateData, getDslMd5List } from \"../../../api/gateway-kanban\";\nimport { setIsUpdate } from \"actions/gateway-kanban\";\nimport { arrayMoveImmutable } from \"array-move\";\nimport DragGroup from \"../../../d1-packages/drag-group/DragGroup\";\nimport { copyString } from \"lib/utils\";\nimport { OperationPanel } from \"../components/operation-panel\";\n\nexport const classPrefix = \"monitor\";\n\nconst secondUserConfigType = \"dsl\";\n\nexport const QueryTemplate = memo(() => {\n  const [dslMd5List, setDslMd5List] = useState([]);\n  const [checkedData, setCheckedData] = useState(getCheckedData([]));\n  const [metricsTypes, setMetricsTypes] = useState([]);\n  const [viewData, setViewData] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n\n  const selectRadioValue = useRef({\n    topNum: TOP_MAP[0].value,\n    topTimeStep: TOP_TIME_RANGE[0].value,\n    topMethod: TOP_TYPE[0].value,\n    content: undefined,\n  });\n\n  const sortEnd = ({ oldIndex, newIndex }) => {\n    const listsNew = arrayMoveImmutable(checkedData[\"查询模板性能配置\"], oldIndex, newIndex);\n    checkedData[\"查询模板性能配置\"] = listsNew;\n    const checkedList = objFlat(checkedData);\n    setCheckedList(secondUserConfigType, checkedList);\n    setMetricsTypes([...listsNew]);\n  };\n\n  const { startTime, endTime, isMoreDay, isUpdate, timeRadioKey } = useSelector(\n    (state) => ({\n      startTime: (state as any).gatewayKanban.startTime,\n      endTime: (state as any).gatewayKanban.endTime,\n      isMoreDay: (state as any).gatewayKanban.isMoreDay,\n      isUpdate: (state as any).gatewayKanban.isUpdate,\n      timeRadioKey: (state as any).gatewayKanban.timeRadioKey,\n    }),\n    shallowEqual\n  );\n  const dispatch = useDispatch();\n\n  const isFirst = useRef(true);\n  const timeDiff = useRef(0);\n  const prevTopNu = useRef(TOP_MAP[0].value);\n\n  const showTooltipModal = (md5, metricsType) => {\n    copyString(md5);\n  };\n\n  useEffect(() => {\n    window[\"showTooltipModal\"] = (md5, metricsType) => {\n      showTooltipModal(md5, metricsType);\n    };\n  }, []);\n\n  const reloadPage = () => {\n    dispatch(setIsUpdate(!isUpdate));\n  };\n\n  const getAsyncCheckedList = async () => {\n    try {\n      const checkedList = await getCheckedList(secondUserConfigType);\n      if (!checkedList || checkedList.length === 0) {\n        setCheckedData(allCheckedData);\n      } else {\n        setCheckedData(getCheckedData(checkedList));\n      }\n    } catch (error) {\n      setCheckedData(allCheckedData);\n      console.log(error);\n    }\n  };\n  const setIndexConfigCheckedData = (changeCheckedData) => {\n    const checkedList = objFlat(changeCheckedData);\n    setCheckedList(secondUserConfigType, checkedList);\n    setCheckedData(changeCheckedData);\n    reloadPage();\n  };\n\n  const getAsyncViewData = useCallback(\n    async (metricsTypes) => {\n      return await getQueryTemplateData(\n        metricsTypes,\n        startTime,\n        endTime,\n        selectRadioValue.current.topNum,\n        selectRadioValue.current.content,\n        selectRadioValue.current.topMethod,\n        selectRadioValue.current.topTimeStep\n      );\n    },\n    [startTime, endTime, timeRadioKey]\n  );\n\n  const getAsyncDslMd5List = async () => {\n    try {\n      const dslMd5List = await getDslMd5List(startTime, endTime);\n\n      setDslMd5List(dslMd5List);\n    } catch (error) {\n      console.log(error);\n    }\n  };\n\n  const getAllAsyncViewData = async (metricsTypes) => {\n    try {\n      setIsLoading(true);\n      const res = await getAsyncViewData(metricsTypes);\n      setViewData(\n        res.map((item) =>\n          getOption({\n            metrics: item,\n            configData: indexConfigData,\n            isMoreDay,\n            isShowTooltipModal: true,\n          })\n        )\n      );\n    } catch (error) {\n      setViewData([]);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    getAsyncCheckedList();\n    getAsyncDslMd5List();\n  }, []);\n\n  useEffect(() => {\n    setMetricsTypes(objFlat(checkedData));\n  }, [checkedData]);\n\n  useEffect(() => {\n    if (isFirst.current || timeDiff.current !== endTime - startTime || prevTopNu.current !== selectRadioValue.current.topNum) {\n      setIsLoading(true);\n      timeDiff.current = endTime - startTime;\n      isFirst.current = false;\n      prevTopNu.current = selectRadioValue.current.topNum;\n    }\n    if (!metricsTypes || metricsTypes.length === 0) {\n      return;\n    }\n    getAllAsyncViewData(metricsTypes);\n  }, [metricsTypes, getAsyncViewData]);\n\n  const onSelectRadioChange = (values, needReload) => {\n    selectRadioValue.current = values;\n    if (needReload) {\n      reloadPage();\n    }\n  };\n\n  const renderTopWhat = () => {\n    return (\n      <SelectRadio\n        onValueChange={onSelectRadioChange}\n        content={selectRadioValue.current.content}\n        contentList={dslMd5List}\n        placeholder=\"请选择dslMd5\"\n      />\n    );\n  };\n\n  const renderConfig = () => {\n    return (\n      <IndexConfig\n        title=\"查询模板指标配置\"\n        optionList={defaultIndexConfigList}\n        checkedData={checkedData}\n        setCheckedData={setIndexConfigCheckedData}\n      />\n    );\n  };\n\n  const renderFilter = () => {\n    return (\n      <>\n        {renderTopWhat()}\n        {renderConfig()}\n      </>\n    );\n  };\n\n  return (\n    <>\n      <OperationPanel classPrefix={classPrefix} reloadPage={reloadPage} endTime={endTime} renderFilter={renderFilter} />\n      <div className={`${classPrefix}-overview-content-line`}>\n        <DragGroup\n          dragContainerProps={{\n            onSortEnd: sortEnd,\n            axis: \"xy\",\n            distance: 100,\n          }}\n          containerProps={{\n            grid: 12,\n            gutter: [10, 10],\n          }}\n        >\n          {metricsTypes.map((item, index) => (\n            <Line\n              key={`${item}`}\n              title={indexConfigData[item]?.title()}\n              tooltip={getRenderToolTip(indexConfigData[item])}\n              index={`${item}_${index}`}\n              option={viewData[index] || {}}\n              isLoading={isLoading}\n            />\n          ))}\n        </DragGroup>\n      </div>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/hooks/useMouseoutOutSide.tsx",
    "content": "import { RefObject } from \"react\";\n\nimport { useEffect } from \"react\";\n\nexport const useMouseoutOutSide = (\n  eventName: string,\n  ref: RefObject<HTMLElement>,\n  handler: Function\n) => {\n  useEffect(() => {\n    const listener = (event: MouseEvent) => {\n      if (!ref.current || ref.current.contains(event.target as HTMLElement)) {\n        return;\n      }\n      handler(event);\n    };\n    document.addEventListener(eventName, listener);\n    return () => {\n      document.removeEventListener(eventName, listener);\n    };\n  }, [eventName, ref, handler]);\n};\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/index.tsx",
    "content": "export * from \"./cluster-kanban/cluster-kanban\";\nexport * from \"./gateway-kanban/gateway-kanban\";\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/style/cluster-kanban.less",
    "content": ".kanban-header-box {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-end;\n  &-content {\n    padding-right: 20px;\n    color: #6a9ef4;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/style/contrast-figure.less",
    "content": ".contrast-figure-box {\n  padding: 20px;\n  p {\n    margin: 0;\n  }\n  &-title {\n    font-family: PingFangSC-Medium;\n    font-size: 16px;\n    color: #303a51;\n    line-height: 24px;\n  }\n  &-container {\n    position: relative;\n  }\n  &-subtext {\n    position: absolute;\n    top: 53%;\n    width: 31%;\n    left: 20%;\n    text-align: center;\n    font-family: \"PingFangSC-Medium\";\n    color: \"#303A51\";\n    font-size: 19px;\n    z-index: 10;\n    cursor: pointer;\n  }\n\n  &-content {\n    // display: flex;\n    // justify-content: space-around;\n    // align-items: center;\n    // width: ;\n    height: 190px;\n    &-figure {\n      width: 160px;\n      height: 160px;\n      margin: 20px;\n      border-radius: 50%;\n    }\n    &-info {\n      margin: 0 15px;\n      &-content:first-child {\n        margin-bottom: 15px;\n      }\n      &-content {\n        p {\n          position: relative;\n          padding-left: 10px;\n        }\n        p:first-child::before {\n          content: \"\";\n          position: absolute;\n          top: 50%;\n          transform: translateY(-50%);\n          left: 0;\n          width: 8px;\n          height: 8px;\n          background: #21cab8;\n          border-radius: 4px;\n        }\n      }\n      &-content:last-child p:first-child::before {\n        background: #d3dae7;\n      }\n      p {\n        font-family: PingFangSC-Regular;\n        font-size: 12px;\n        color: #303a51;\n        letter-spacing: 0;\n        text-align: justify;\n        line-height: 20px;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/style/gateway-kanban.less",
    "content": ".gateway-kanban-header-box {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  h3 {\n    font-family: PingFangSC-Medium;\n    font-size: 18px;\n    font-weight: 400;\n    color: #101724;\n    margin: 0;\n    padding: 0 0 0 20px;\n  }\n  &-select {\n    display: flex;\n    align-items: center;\n    height: 70px;\n    padding-right: 20px;\n  }\n  &-content {\n    padding: 0 15px;\n    color: #6a9ef4;\n  }\n}\n\n.gateway-kanban-content-table-content {\n  padding: 20px 20px 10px 0;\n  .ant-menu-item {\n    margin: 0 40px 0 0;\n  }\n}\n\n.gateway-kanban-content-detail-wrapper {\n  margin-top: 20px;\n  height: 100%;\n  background: #fff;\n  border-radius: 8px;\n  padding: 20px 20px 0 20px;\n  .d1-row {\n    width: 101%;\n  }\n}\n.gateway .hash-menu {\n  min-height: calc(100vh - 124px);\n}\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/style/index.less",
    "content": "@import \"../../../styles/base.less\";\n\n@prefix: dcloud;\n\n.hash-menu-container {\n  position: relative;\n\n  .kanban-form {\n    position: absolute;\n    top: -3px;\n    right: 0px;\n  }\n\n  .hash-detail-wrapper {\n    background-color: transparent;\n  }\n\n  .@{prefix}-menu {\n    background-color: transparent;\n  }\n\n  .@{prefix}-menu-horizontal {\n    line-height: 31px;\n    font-family: PingFangSC-Semibold;\n    font-size: 18px;\n    color: rgba(0, 0, 0, 0.6);\n    letter-spacing: 0;\n    font-weight: 600;\n    border-bottom: 0px;\n    width: 100%;\n  }\n\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-item:hover,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-submenu:hover,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-item-active,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-submenu-active,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-item-open,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-submenu-open,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-item-selected,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-submenu-selected {\n    color: rgba(0, 0, 0, 0.87);\n  }\n\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-item:hover::after,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-submenu:hover::after,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-item-active::after,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-submenu-active::after,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-item-open::after,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-submenu-open::after,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-item-selected::after,\n  .@{prefix}-menu-horizontal:not(.@{prefix}-menu-dark) > .@{prefix}-menu-submenu-selected::after {\n    border-bottom: 4px solid @primary-color;\n    bottom: -5px;\n    border-radius: 8px;\n  }\n\n  .hash-menu {\n    background-color: transparent;\n\n    .hash-table-content {\n      padding: 16px 20px 24px;\n\n      .@{prefix}-menu-item {\n        margin: 0 24px 0 0;\n        padding: 0px;\n      }\n    }\n  }\n\n  .hash-detail-wrapper {\n    background-color: #fff;\n    border-radius: 8px;\n    margin: 0px 20px;\n    padding: 16px 20px;\n  }\n\n  .refresh-time {\n    position: absolute;\n    top: 0;\n    right: 20px;\n  }\n  .gateway-refresh {\n    top: 98px;\n    left: 40px;\n    display: inline-block;\n    width: 140px;\n  }\n}\n.cluster .refresh-time {\n  top: 87px;\n  left: 40px;\n  right: auto;\n}\n\n.monitor-overview-search {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n\n  &-reload {\n    .dcloud-divider-vertical {\n      border-left: 1px solid #ced4da;\n    }\n\n    .divider {\n      margin: 0px 16px 0px 156px;\n      width: 1px;\n      height: 20px;\n    }\n\n    .reload {\n      line-height: 30px;\n      // width: 16px;\n      // height: 16px;\n      margin-right: 6px;\n      color: rgba(0, 0, 0, 0.6);\n    }\n\n    .text {\n      font-family: PingFangSC-Regular;\n      font-size: 14px;\n      color: rgba(0, 0, 0, 0.6);\n      line-height: 22px;\n      font-weight: 400;\n    }\n\n    .reload:hover {\n      color: @primary-color;\n    }\n  }\n\n  &-filter {\n    &-item {\n      margin-right: 8px;\n    }\n  }\n}\n\n.monitor-overview-content {\n  .ant-collapse-content > .ant-collapse-content-box {\n    padding: 0 20px !important;\n  }\n\n  &-config {\n    width: 100%;\n    overflow-x: auto;\n    margin: 20px 0 20px 0;\n\n    &-box {\n      min-width: 1024px;\n      display: flex;\n      flex-wrap: wrap;\n      justify-content: space-between;\n      height: 437px;\n\n      &-view {\n        display: flex;\n        flex-direction: column;\n        justify-content: space-between;\n        width: 68%;\n        min-width: 777px;\n\n        &-state-config {\n          border: 1px solid #dcdfe6;\n          margin-bottom: 20px;\n        }\n\n        &-memory-map {\n          display: flex;\n          justify-content: space-between;\n          align-items: center;\n          height: 268px;\n          border: 1px solid #dcdfe6;\n\n          .vertical-line {\n            width: 1px;\n            height: 228px;\n            background: #d8d8d8;\n          }\n\n          &-view {\n            flex: 1;\n          }\n        }\n      }\n\n      &-node-distribution {\n        display: flex;\n        flex-direction: column;\n        width: calc(32% - 20px);\n        min-width: 360px;\n        height: 437px;\n        border: 1px solid #dcdfe6;\n\n        .cross-line {\n          width: 100%;\n          height: 1px;\n          background: #dcdfe6;\n          align-self: center;\n          margin: 0 0 15px 0;\n        }\n      }\n    }\n  }\n\n  &-line {\n    width: 100%;\n    display: flex;\n    justify-content: space-between;\n    flex-wrap: wrap;\n    margin-top: 20px;\n\n    &-container {\n      // width: calc(50% - 10px);\n      margin: 0 0 20px 0;\n      height: 305px;\n      border: 1px solid #dcdfe6;\n      border-radius: 2px;\n      background: #fff;\n    }\n\n    &-item {\n      width: 100%;\n      height: 305px;\n\n      // 覆盖 echarts tooltip 的 z-index\n      div {\n        // z-index: 100!important;\n      }\n\n      &-header {\n        display: flex;\n        justify-content: space-between;\n        align-items: center;\n        margin-bottom: 20px;\n\n        &-title {\n          .max-title();\n        }\n\n        &-time {\n          .min-title();\n        }\n      }\n    }\n\n    &-bigPicture {\n      width: 100%;\n      height: 50vh;\n    }\n\n    &-enlarge {\n      position: absolute;\n      cursor: pointer;\n      top: 17.5px;\n      right: 20px;\n      width: 15px;\n      height: 15px;\n      z-index: 100;\n\n      ::selection {\n        color: none;\n        background: none;\n      }\n\n      img {\n        width: 100%;\n        height: 100%;\n      }\n    }\n\n    &-legend {\n      position: absolute;\n      cursor: pointer;\n      top: 14.5px;\n      right: 45px;\n      width: 20px;\n      height: 20px;\n      line-height: 22px;\n      z-index: 100;\n      font-size: 18px;\n      color: rgb(180, 180, 180);\n    }\n  }\n\n  &-shard {\n    .ant-table-thead > tr > th,\n    .ant-table-tbody > tr > td,\n    .ant-table tfoot > tr > th,\n    .ant-table tfoot > tr > td {\n      padding: 0;\n    }\n\n    .ant-table-thead > tr > th,\n    .ant-table-tbody > tr > td {\n      padding: 6px;\n    }\n  }\n}\n\n.index-view-line-container {\n  margin-top: 20px;\n}\n\n.content-margin-top-20 {\n  margin-top: 20px;\n}\n\n.indicators-kanban-loading-container {\n  border: 1px solid #dcdfe6;\n  border-radius: 2px;\n  margin: 0 0 20px 0;\n}\n\n.common-loading-container {\n  position: relative;\n\n  .center-center-loading {\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n  }\n\n  .center-center-empty-box-title {\n    position: absolute;\n    top: 20px;\n    left: 20px;\n    font-family: PingFangSC-Medium;\n    font-size: 16px;\n    color: #303a51;\n    line-height: 24px;\n  }\n\n  .center-center-empty-box-content {\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n  }\n}\n\n@media screen and (max-width: 1000px) {\n  .monitor-overview-content-line-container {\n    width: 100%;\n  }\n}\n\n.indicators-header {\n  min-width: 800px;\n  border-radius: 4px 4px 0 0;\n}\n"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/style/index.ts",
    "content": "import './index.less'\nimport './kanban-form.less'\nimport './cluster-kanban.less'\nimport './state-config.less'\nimport './contrast-figure.less'\nimport './gateway-kanban.less'\nimport './node-view.less'\nimport './select-time.less'"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/style/kanban-form.less",
    "content": ".kanban-from-box {\n  display: flex;\n  justify-content: space-between;\n  flex-wrap: wrap;\n  padding: 20px 20px 0;\n\n  &-item {\n    display: flex;\n    flex-wrap: wrap;\n    margin-right: 12px;\n  }\n\n  .ant-form-item {\n    margin-bottom: 5px;\n  }\n}"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/style/node-view.less",
    "content": ""
  },
  {
    "path": "arius-console/src/container/indicators-kanban/style/refresh-time.less",
    "content": "@keyframes rotate {\n  from {\n    transform: translate(0, -50%) rotate(0deg);\n  }\n\n  to {\n    transform: translate(0, -50%) rotate(360deg);\n  }\n}\n\n@prefix: dcloud;\n\n.refresh-time-container {\n  display: flex;\n  align-items: center;\n\n  .@{prefix}-select {\n    width: 140px;\n  }\n\n  .@{prefix}-select-selection-item {\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: rgba(0, 0, 0, 0.60);\n    text-align: left;\n    line-height: 22px;\n    font-weight: 400;\n  }\n\n  .refresh-icon-container .@{prefix}-select-single:not(.@{prefix}-select-customize-input) .@{prefix}-select-selector {\n    padding: 0 8px;\n  }\n\n  .refresh-select {\n    position: relative;\n\n\n    .dcloud-select.dcloud-select-single .dcloud-select-selector {\n      height: 30px;\n    }\n\n    .dcloud-select-single .dcloud-select-selector .dcloud-select-selection-item {\n      line-height: 30px;\n    }\n\n    .refresh-icon {\n      position: absolute;\n      top: 50%;\n      left: 9px;\n      transform: translate(0, -50%);\n      z-index: 1;\n    }\n\n    .refresh-icon-animation {\n      animation: rotate 0.8s linear infinite;\n      color: @primary-color;\n    }\n  }\n\n  .refresh-time-desc {\n    font-family: PingFangSC-Regular;\n    font-size: 12px;\n    color: #303a51;\n    padding-right: 8px;\n  }\n}"
  },
  {
    "path": "arius-console/src/container/indicators-kanban/style/select-time.less",
    "content": ""
  },
  {
    "path": "arius-console/src/container/indicators-kanban/style/state-config.less",
    "content": ".state-config-box {\n  padding: 20px;\n\n  p {\n    margin-bottom: 0;\n  }\n\n  &-title {\n    font-family: PingFangSC-Medium;\n    font-size: 16px;\n    color: #303a51;\n  }\n\n  &-content {\n    display: flex;\n\n    &-module {\n      flex: 1;\n    }\n  }\n\n  &-config-info {\n    margin-top: 15px;\n    padding-bottom: 5px;\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: #505568;\n    letter-spacing: 0;\n    text-align: justify;\n    line-height: 22px;\n  }\n\n  &-config-state {\n    width: 73px;\n    height: 28px;\n    border-radius: 4px;\n    text-align: center;\n\n    &-Green {\n      background: rgba(70, 214, 119, 0.1);\n      border: 1px solid #46d677;\n\n      span {\n        color: #46d677;\n      }\n    }\n\n    &-Yellow {\n      background: rgba(244, 168, 56, 0.1);\n      border: 1px solid #f4a838;\n\n      span {\n        color: #f4a838;\n      }\n    }\n\n    &-Unknown {\n      background: #f5f5f5;\n      border: 1px solid #d9d9d9;\n      width: 93px;\n\n      span {\n        color: rgba(0, 0, 0, 0.25);\n      }\n    }\n\n    &-Red {\n      background: rgba(239, 100, 92, 0.1);\n      border: 1px solid #ef645c;\n\n      span {\n        color: #ef645c;\n      }\n    }\n\n    span {\n      font-family: PingFangSC-Medium;\n      font-size: 20px;\n      line-height: 28px;\n    }\n  }\n\n  &-config-content {\n    font-family: PingFangSC-Medium;\n    font-size: 24px;\n    color: #303a51;\n    line-height: 32px;\n    cursor: pointer;\n\n    &-sub {\n      font-family: PingFangSC-Regular;\n      font-size: 12px;\n      color: #a8adbd;\n      line-height: 20px;\n      padding-left: 5px;\n    }\n  }\n}"
  },
  {
    "path": "arius-console/src/container/modal/edition-cluster/add-package.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { UploadFile } from \"container/custom-form/upload-file\";\nimport { computeChecksumMd5, getCookie } from \"lib/utils\";\nimport { IOpPackageParams } from \"typesPath/params-types\";\nimport { getClusterVersion, addPackage, updatePackage } from \"api/cluster-api\";\nimport { UserState } from \"store/type\";\nimport { AutoComplete } from \"antd\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  user: state.user,\n});\n\nconst AddPackageModal = (props: { dispatch: any; cb: Function; user: UserState; params: any }) => {\n  const [versionlist, setVersionlist] = useState([]);\n\n  useEffect(() => {\n    _getClusterVersion();\n  }, []);\n\n  const _getClusterVersion = async () => {\n    let res = await getClusterVersion();\n    let list = res.map((item) => {\n      return { value: item };\n    });\n    setVersionlist(list);\n  };\n\n  const { params } = props;\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"url\",\n        label: \"URL\",\n        rules: [{ required: true, message: \"请输入\" }],\n        attrs: {\n          placeholder: \"请输入\",\n        },\n      },\n      {\n        key: \"esVersion\",\n        label: \"版本名称\",\n        type: FormItemType.custom,\n        customFormItem: <AutoComplete options={versionlist} placeholder=\"请输入4位数字组成的版本号，如：7.6.0.12\"></AutoComplete>,\n        rules: [\n          {\n            required: true,\n            validator: (rule: any, value: string) => {\n              const reg = /^([1-9]\\d|[1-9])(.([1-9]\\d|\\d)){2}(.(\\d|[1-9]\\d|[1-9]\\d\\d|[1-9]\\d\\d\\d))$/;\n              if (!value || !reg.test(value)) {\n                return Promise.reject(\"必须是4位，x.x.x.x的形式, 每位x的范围分别为1-99,0-99,0-99,0-9999\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"desc\",\n        label: \"描述\",\n        type: FormItemType.textArea,\n        rules: [\n          {\n            required: false,\n            whitespace: true,\n            validator: (rule: any, value: string) => {\n              if (!value || value?.trim().length <= 100) {\n                return Promise.resolve();\n              } else {\n                return Promise.reject(\"请输入0-100字描述\");\n              }\n            },\n          },\n        ],\n        attrs: {\n          placeholder: \"请输入0-100字描述\",\n        },\n      },\n    ] as IFormItem[],\n    type: \"drawer\",\n    visible: true,\n    title: params && !params.addPackage ? \"编辑版本\" : \"新增版本\",\n    formData: params || {},\n    isWaitting: true,\n    width: 660,\n    onCancel: () => {\n      props.dispatch(actions.setDrawerId(\"\"));\n    },\n    actionAfterSubmit: () => {\n      props.dispatch(actions.setDrawerId(\"\"));\n      props.cb && props.cb();\n    },\n    onSubmit: async (result: IOpPackageParams) => {\n      result.manifest = result.manifest || 4;\n      result.creator = getCookie(\"userName\") || \"\";\n      if (result.manifest === 4 && result.uploadFile?.fileList) {\n        const file = result.uploadFile?.fileList[0].originFileObj;\n        result.fileName = result.uploadFile.fileList[0].name;\n        const md5 = await computeChecksumMd5(file);\n        result.md5 = md5 as string;\n        result.uploadFile = file;\n      } else {\n        result.uploadFile = null;\n      }\n      // 判断是新增版本还是编辑版本\n      if (params && !params.addPackage) {\n        result.id = params.id;\n        result.url = result.uploadFile ? result.url : params?.url;\n        return updatePackage(result).catch(() => {\n          throw new Error(\"编辑失败\");\n        });\n      }\n      return addPackage(result).catch((req: any) => {\n        throw new Error(\"上传失败\");\n      });\n    },\n  };\n\n  const updateFormModal = (type) => {\n    const dockerForm = {\n      key: \"url\",\n      label: \"URL\",\n      rules: [{ required: true, message: \"请输入\" }],\n      attrs: {\n        placeholder: \"请输入\",\n      },\n    } as IFormItem;\n    const hostForm = {\n      key: \"uploadFile\",\n      label: \"上传文件\",\n      type: FormItemType.custom,\n      customFormItem: <UploadFile url={params?.url} accept=\".gz\" msg=\"单击或拖动文件到此区域以上传, 只能上传1个文件，且为.gz格式文件\" />,\n      rules: [\n        {\n          required: true,\n          validator: async (rule: any, value: any) => {\n            if (params?.url && value == null) {\n              return Promise.resolve();\n            }\n            if (!value) {\n              return Promise.reject(\"请上传文件,仅支持上传单个文件且文件小于 500 MB\");\n            }\n            const { fileList } = value;\n            const flag = fileList?.some((item) => item.size / 1024 / 1024 >= 500);\n            if (!fileList || fileList.length !== 1 || flag) {\n              return Promise.reject(\"请上传文件,仅支持上传单个文件且文件小于 500 MB\");\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    } as any;\n    if (type === 1) {\n      xFormModalConfig.formMap[0] = dockerForm;\n    } else {\n      xFormModalConfig.formMap[0] = hostForm;\n    }\n  };\n\n  if (params?.manifest === 4) {\n    updateFormModal(2);\n  }\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(AddPackageModal);\n"
  },
  {
    "path": "arius-console/src/container/modal/index-admin/batch-execute.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { message } from \"antd\";\nimport { openOrCloseReadOrWrite, indicesOpen, indicesClose } from \"api/index-admin\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const BatchExecute = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const { type, datas } = props.params;\n  let label = \"\";\n\n  switch (type) {\n    case \"read\":\n      label = `索引读`;\n      break;\n    case \"write\":\n      label = `索引写`;\n      break;\n    case \"status\":\n      label = `索引状态`;\n      break;\n    default:\n      break;\n  }\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"status\",\n        label: label,\n        type: FormItemType._switch,\n        formAttrs: {\n          style: {\n            marginTop: 0,\n          },\n        },\n      },\n      {\n        key: \"ids\",\n        label: \"操作对象\",\n        type: FormItemType.custom,\n        customFormItem: (\n          <div className=\"btn-labels-box\">{datas.length ? datas.map((item) => <div className=\"btn-labels\">{item.index}</div>) : \"-\"}</div>\n        ),\n      },\n    ] as IFormItem[],\n    formData: {\n      status: true,\n    },\n    visible: true,\n    title: \"批量操作\",\n    needBtnLoading: true,\n    width: 500,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      if (!datas.length) {\n        props.dispatch(actions.setModalId(\"\"));\n        return;\n      }\n      const thenFn = () => {\n        message.success(`操作成功`);\n        props.dispatch(actions.setModalId(\"\"));\n        props.cb && props.cb(); // 重新获取数据列表\n      };\n      if (type === \"read\" || type === \"write\") {\n        const params = datas?.map((item) => ({\n          cluster: item.cluster,\n          index: item.index,\n          type: type,\n          value: !result.status,\n        }));\n        return openOrCloseReadOrWrite(params).then(() => {\n          thenFn();\n        });\n      } else if (type === \"status\") {\n        const params = datas?.map((item) => ({\n          cluster: item.cluster,\n          index: item.index,\n        }));\n        const submitFn = result.status ? indicesOpen : indicesClose;\n        return submitFn(params).then(() => {\n          thenFn();\n        });\n      }\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/index-admin/delete-alias.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { message } from \"antd\";\nimport { deleteAlias } from \"api/index-admin\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const DeleteAlias = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"alias\",\n        label: \"请选择需要删除的别名\",\n        type: FormItemType.checkBox,\n        options: props.params.aliases || [],\n        rules: [\n          {\n            required: true,\n            message: \"请选择需要删除的别名\",\n            validator: (rule: any, value: any) => {\n              if (value === undefined || !value.length) {\n                return Promise.reject();\n              } else {\n                return Promise.resolve();\n              }\n            },\n          },\n        ],\n        formAttrs: {\n          style: {\n            marginTop: 0,\n          },\n        },\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"删除别名\",\n    needBtnLoading: true,\n    width: 500,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      const params = {\n        cluster: props.params.cluster,\n        index: props.params.index,\n        aliases: result.alias,\n      };\n      return deleteAlias(params).then(() => {\n        message.success(`操作成功`);\n        props.dispatch(actions.setModalId(\"\"));\n        props.cb && props.cb(); // 重新获取数据列表\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/index-admin/delete-index.tsx",
    "content": "import { DeleteOutlined } from \"@ant-design/icons\";\nimport { Button, Checkbox, Drawer, message, Modal } from \"antd\";\nimport { use } from \"echarts\";\nimport React, { memo, useEffect, useState } from \"react\";\nimport { useSelector, useDispatch, shallowEqual } from \"react-redux\";\nimport \"./index.less\";\nimport * as actions from \"../../../actions\";\nimport { delIndexAdminData } from \"api/index-admin\";\n\nexport const DeleteIndex = memo((props) => {\n  const dispatch = useDispatch();\n  const [isDisabled, setIsDisabled] = useState(true);\n  const { params, cb } = useSelector((state) => ({ params: (state as any).modal.params, cb: (state as any).modal.cb }), shallowEqual);\n\n  const { delList, title, type = \"下线\" } = params;\n\n  const [loading, setIsLoading] = useState(false);\n\n  const del = async () => {\n    setIsLoading(true);\n    try {\n      const res = await delIndexAdminData(delList);\n      res ? message.success(`${type}成功`) : message.error(`${type}失败!`);\n    } catch (error) {\n      message.error(`${type}失败!`);\n    } finally {\n      setIsLoading(false);\n      dispatch(actions.setModalId(\"\"));\n      // 刷新数据\n      cb(true);\n    }\n  };\n\n  return (\n    <Modal\n      visible={true}\n      maskClosable={false}\n      onOk={() => {\n        setIsDisabled(true);\n        dispatch(actions.setModalId(\"\"));\n      }}\n      onCancel={() => {\n        setIsDisabled(true);\n        dispatch(actions.setModalId(\"\"));\n      }}\n      className={\"delete-index-container\"}\n      footer={[]}\n    >\n      <div className=\"ant-modal-confirm-title\">\n        <DeleteOutlined style={{ color: \"red\" }} />\n        <p>{title}</p>\n      </div>\n      <p>\n        <Checkbox\n          onChange={() => {\n            setIsDisabled(!isDisabled);\n          }}\n          style={{ margin: \"0 15px\" }}\n        />\n        <span>{`索引${type}后数据无法恢复，请确认影响后继续${type}操作`}</span>\n      </p>\n      <div className=\"delete-index-container-button\">\n        <Button key=\"cancel\" onClick={() => dispatch(actions.setModalId(\"\"))}>\n          取消\n        </Button>\n        <Button\n          type=\"primary\"\n          key=\"ok\"\n          disabled={isDisabled}\n          loading={loading}\n          onClick={() => {\n            del();\n          }}\n          style={{ marginLeft: 8 }}\n        >\n          确认\n        </Button>\n      </div>\n    </Modal>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/index-admin/index.less",
    "content": ".delete-index-container {\n  .ant-modal-body {\n    padding: 32px 32px 24px;\n  }\n  .ant-modal-confirm-title {\n    display: flex;\n    overflow: hidden;\n    color: rgba(0, 0, 0, 0.85);\n    font-weight: 500;\n    font-size: 14px;\n    line-height: 1.4;\n    .anticon-delete {\n      font-size: 22px;\n      margin: 0 10px;\n    }\n  }\n  p {\n    margin-bottom: 1em;\n  }\n\n  .delete-index-container-button {\n    display: flex;\n    justify-content: flex-end;\n    margin-top: 20px;\n  }\n  .ant-modal-close,\n  .ant-modal-footer {\n    display: none;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/index-admin/set-alias.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { message } from \"antd\";\nimport { setAlias } from \"api/index-admin\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const SetAlias = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"alias\",\n        label: \"别名\",\n        type: FormItemType.input,\n        attrs: {\n          placeholder: \"请输入别名，多个用','分割\",\n        },\n        formAttrs: {\n          style: {\n            marginTop: 0,\n          },\n        },\n        rules: [\n          {\n            required: true,\n            message: \"请输入别名，1-30字符\",\n            validator: (rule: any, value: any) => {\n              value = value?.trim();\n              if (value === undefined || !value.length || value.length > 30) {\n                return Promise.reject();\n              } else {\n                return Promise.resolve();\n              }\n            },\n          },\n        ],\n      },\n      {\n        key: \"aliases\",\n        label: \"已有别名\",\n        type: FormItemType.custom,\n        customFormItem: (\n          <div className=\"btn-labels-box\">\n            {props.params?.aliases?.length ? props.params?.aliases?.map((item) => <div className=\"btn-labels\">{item}</div>) : \"-\"}\n          </div>\n        ),\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"设置别名\",\n    needBtnLoading: true,\n    width: 500,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      const params = {\n        cluster: props.params.cluster,\n        index: props.params.index,\n        aliases: result.alias.split(\",\"),\n      };\n      return setAlias(params).then(() => {\n        message.success(`设置别名成功`);\n        props.dispatch(actions.setModalId(\"\"));\n        props.cb && props.cb(); // 重新获取数据列表\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/indicators/big-picture.tsx",
    "content": "import { Button, Modal } from \"antd\";\nimport React, { useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"../../../actions\";\nimport { Dispatch } from \"redux\";\nimport { DrawLine } from \"container/indicators-kanban/components/line\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const BigPicture = connect(mapStateToProps)((props: { dispatch: Dispatch; params: any; cb: Function }) => {\n  return (\n    <>\n      <Modal\n        visible={true}\n        title={props.params?.titleText}\n        width={\"calc(70vw)\"}\n        onCancel={() => props.dispatch(actions.setModalId(\"\"))}\n        footer={[\n          <Button key=\"back1\" onClick={() => props.dispatch(actions.setModalId(\"\"))}>\n            取消\n          </Button>,\n        ]}\n      >\n        <DrawLine index={\"ele-id\" + \"modal\"} option={props.params} bigPicture={true} />\n      </Modal>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/indicators/chart-modal.less",
    "content": ".qsl-template-box {\n  width: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  .qsl-template-box-chart {\n    .monitor-overview-content-line-container {\n      width: 450px;\n      height: 261px;\n      border: none;\n      .monitor-overview-content-line-enlarge {\n        display: none;\n      }\n    }\n  }\n  .qsl-template-box-description {\n    .ant-descriptions-item-content {\n      display: inline-block;\n      width: 100%;\n      .description-cell {\n        white-space: nowrap;\n        overflow: hidden;\n        text-overflow: ellipsis;\n        display: inline-block;\n        max-width: 100%;\n      }\n    }\n  }\n\n  .dsl-drawer-box {\n    width: 100%;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/indicators/chart-tablemodal.tsx",
    "content": "import React, { memo, useEffect, useState } from \"react\";\nimport { Table, Modal, Spin, Tooltip, TimePicker, message, Input } from \"antd\";\nimport \"./chart-modal.less\";\nimport * as actions from \"../../../actions\";\nimport { useSelector, useDispatch, shallowEqual } from \"react-redux\";\nimport { getChartTableList } from \"api/cluster-kanban\";\nimport moment from \"moment\";\nimport { transTimeFormat } from \"lib/utils\";\n\nexport const ChartTableModal = memo((props) => {\n  const dispatch = useDispatch();\n  const { params, cb } = useSelector(\n    (state) => ({\n      params: (state as any).modal.params,\n      cb: (state as any).modal.cb,\n    }),\n    shallowEqual\n  );\n\n  const { clusterPhyName, node, time } = params;\n  const [data, setData] = useState<any>([]);\n  const [listData, setListData] = useState<any>([]);\n  const [dataLoading, setDataLoading] = useState(false);\n  const columns = [\n    {\n      title: \"操作类型\",\n      dataIndex: \"action\",\n      width: 200,\n      render: (text) => {\n        return (\n          <div style={{ overflow: \"hidden\", textOverflow: \"ellipsis\" }}>\n            <Tooltip title={text}>{text || \"-\"}</Tooltip>\n          </div>\n        );\n      },\n    },\n    {\n      title: \"开始时间\",\n      dataIndex: \"startTime\",\n      render: (text) => {\n        return transTimeFormat(text);\n      },\n    },\n    {\n      title: \"运行时间\",\n      dataIndex: \"runningTimeString\",\n      render: (text) => {\n        return text || \"-\";\n      },\n    },\n    {\n      title: \"描述\",\n      dataIndex: \"description\",\n      width: 200,\n      render: (text) => {\n        return (\n          <div style={{ overflow: \"hidden\", textOverflow: \"ellipsis\" }}>\n            <Tooltip title={text}>{text || \"-\"}</Tooltip>\n          </div>\n        );\n      },\n    },\n  ];\n\n  const onInputIndexChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const searchKey = e.target.value.trim();\n    setListData(searchKey ? data.filter((row) => row.action.includes(searchKey)) : data);\n  };\n\n  const getData = async (times?: any) => {\n    if (times && times[1] - times[0] > 60 * 1000 * 60) {\n      message.info(\"时间范围仅支持一小时\");\n      return;\n    }\n    setDataLoading(true);\n    let t = times ? times : [time, time];\n    try {\n      const res = await getChartTableList(clusterPhyName, node, t);\n      if (res && res.length) {\n        setData(res);\n        setListData(res);\n      }\n    } catch (error) {\n      console.error(error);\n      setData([]);\n      setListData([]);\n    } finally {\n      setDataLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    getData();\n  }, []);\n\n  return (\n    <Modal\n      visible={true}\n      maskClosable={false}\n      width={750}\n      onOk={() => {\n        dispatch(actions.setModalId(\"\"));\n      }}\n      onCancel={() => {\n        dispatch(actions.setModalId(\"\"));\n      }}\n      title=\"查询Task详情\"\n      footer={null}\n      bodyStyle={{\n        display: \"block\",\n        padding: \"20px\",\n      }}\n    >\n      <Spin spinning={dataLoading}>\n        <div style={{ overflow: \"hidden\" }}>\n          <TimePicker.RangePicker\n            format=\"HH:mm:ss\"\n            style={{ float: \"right\", marginBottom: 10, marginLeft: 20 }}\n            onChange={(e) => getData([moment(e[0]).valueOf(), moment(e[1]).valueOf()])}\n            defaultValue={[moment(Number(time)), moment(Number(time))]}\n          />\n          <Input\n            allowClear\n            onChange={onInputIndexChange}\n            placeholder=\"请输入操作类型关键字\"\n            style={{ float: \"right\", marginBottom: 10, width: 200 }}\n          />\n        </div>\n        <Table pagination={false} dataSource={listData} rowKey=\"taskId\" columns={columns} style={{ width: \"100%\" }} scroll={{ y: 500 }} />\n      </Spin>\n    </Modal>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/indicators/index-config.less",
    "content": ".index-config {\n  .checkboxGroup .ant-checkbox-group-item {\n    padding-top: 14px;\n  }\n  .checkboxGroup .dcloud-checkbox-group-item {\n    padding-top: 14px;\n  }\n}\n.indicators {\n  .dcloud-btn:hover,\n  .dcloud-btn:focus, \n  .dcloud-btn:active {\n    color: #353a40;\n    border-color: #ced4da;\n  }\n  .dcloud-btn.activ, .dcloud-btn.active:hover{\n    color: #3d91ff;\n    border-color: #3d91ff;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/indicators/index-config.tsx",
    "content": "import React, { memo, useState, useEffect } from \"react\";\nimport { useDispatch, useSelector, shallowEqual } from \"react-redux\";\nimport * as actions from \"../../../actions\";\nimport { Button, Modal, Checkbox, Divider, Form } from \"knowdesign\";\nconst CheckboxGroup = Checkbox.Group;\nimport \"./index-config.less\";\n\ninterface selectPropsType {\n  title: string;\n  plainOptions: any[];\n  defaultCheckedList: any[];\n  value?: [];\n  onChange?: (value) => void;\n}\n\nconst SelectCheckBox: React.FC<selectPropsType> = memo(({ title, defaultCheckedList, plainOptions, onChange }) => {\n  const [checkedList, setCheckedList] = useState(defaultCheckedList || []);\n  const [indeterminate, setIndeterminate] = useState(true);\n  const [checkAll, setCheckAll] = useState(false);\n\n  useEffect(() => {\n    if (checkedList.length === plainOptions.length) {\n      setIndeterminate(false);\n      setCheckAll(true);\n    }\n    onChange(checkedList);\n  }, [checkedList]);\n\n  const onCheckboxGroupChange = (list) => {\n    setCheckedList(list);\n    setIndeterminate(!!list.length && list.length < plainOptions.length);\n    setCheckAll(list.length === plainOptions.length);\n  };\n\n  const onCheckAllChange = (e) => {\n    setCheckedList(e.target.checked ? plainOptions.map((item) => item.value) : []);\n    setIndeterminate(false);\n    setCheckAll(e.target.checked);\n  };\n\n  return (\n    <>\n      <Checkbox indeterminate={indeterminate} onChange={onCheckAllChange} checked={checkAll}>\n        {title}\n      </Checkbox>\n      <br />\n      <CheckboxGroup\n        className=\"checkboxGroup\"\n        options={plainOptions.map((item) => ({\n          ...item,\n          value: item.value,\n        }))}\n        value={checkedList}\n        onChange={onCheckboxGroupChange}\n      />\n    </>\n  );\n});\n\nexport const IndexConfig = memo(() => {\n  const {\n    params: { title, optionList, defaultCheckedData, needShortcut = false },\n    cb: callback,\n  } = useSelector(\n    (state: any) => ({\n      params: state.modal.params,\n      cb: state.modal.cb,\n    }),\n    shallowEqual\n  );\n  const indicatorsConfig = {\n    gold: {},\n    performance: {},\n    hot: {},\n    memory: {},\n  };\n  if (needShortcut) {\n    optionList.forEach((item) => {\n      indicatorsConfig.gold[item.title] = [];\n      indicatorsConfig.performance[item.title] = [];\n      indicatorsConfig.hot[item.title] = [];\n      indicatorsConfig.memory[item.title] = [];\n      item.plainOptions.forEach((indicator) => {\n        // 黄金指标1、性能指标2、热点指标3、内存指标4\n        if (indicator.indicatorType?.indexOf(1) > -1) indicatorsConfig.gold[item.title].push(indicator.value);\n        if (indicator.indicatorType?.indexOf(2) > -1) indicatorsConfig.performance[item.title].push(indicator.value);\n        if (indicator.indicatorType?.indexOf(3) > -1) indicatorsConfig.hot[item.title].push(indicator.value);\n        if (indicator.indicatorType?.indexOf(4) > -1) indicatorsConfig.memory[item.title].push(indicator.value);\n      });\n    });\n  }\n\n  const dispatch = useDispatch();\n  const [isDisabled, setIsDisabled] = useState(true);\n  const [check, setCheck] = useState(false);\n  const [count, setCount] = useState(0);\n  const [selectedData, setSelectedData] = useState(defaultCheckedData || indicatorsConfig.gold || {});\n  const [indicatorConfig, setIndicatorConfig] = useState({});\n  const [goldActive, setGoldActive] = useState(defaultCheckedData ? false: true);\n  const [performanceActive, setPerformanceActive] = useState(false);\n  const [hotActive, setHotActive] = useState(false);\n  const [memoryActive, setMemoryActive] = useState(false);\n\n  const filterIndicators = (type) => {\n    switch (type) {\n      case 'gold':\n        setGoldActive((state) => {\n          return !state\n        });\n        break;\n      case 'performance':\n        setPerformanceActive((state) => {\n          return !state\n        });\n        break;\n      case 'hot':\n        setHotActive((state) => {\n          return !state\n        });\n        break;\n      case 'memory':\n        setMemoryActive((state) => {\n          return !state\n        });\n        break;\n      default:\n        break;\n    }\n  };\n\n  useEffect(() => {\n    const newConfig = Object.keys(indicatorsConfig.gold).reduce((obj:any, item:string) => {\n      obj[item] = [\n        ...new Set([\n          ...goldActive ? indicatorsConfig.gold[item] : [],\n          ...performanceActive ? indicatorsConfig.performance[item] : [],\n          ...hotActive ? indicatorsConfig.hot[item] : [],\n          ...memoryActive ? indicatorsConfig.memory[item] : []\n        ])\n      ];\n      return obj\n    },{})\n    setIndicatorConfig(newConfig);\n    setCheck(true);\n    setCount((state) => state + 1);\n  }, [goldActive,performanceActive,hotActive,memoryActive]);\n\n  const renderFooter = () => {\n    return (\n      <div style={{ overflow: \"hidden\" }} className=\"indicators\">\n        {needShortcut ? (\n          <>\n            <Button key=\"gold\" className={ goldActive ? 'activ': '' } onClick={() => filterIndicators(\"gold\")} style={{ float: \"left\" }}>\n              黄金指标\n            </Button>\n            <Button key=\"performance\" className={ performanceActive ? 'activ': '' } onClick={() => filterIndicators(\"performance\")} style={{ float: \"left\" }}>\n              性能指标\n            </Button>\n            <Button key=\"hot\" className={ hotActive ? 'activ' : '' } onClick={() => filterIndicators(\"hot\")} style={{ float: \"left\" }}>\n              热点指标\n            </Button>\n            <Button key=\"memory\" className={ memoryActive ? 'activ' : '' } onClick={() => filterIndicators(\"memory\")} style={{ float: \"left\" }}>\n              内存指标\n            </Button>\n          </>\n        ) : null}\n        <Button\n          type=\"primary\"\n          key=\"ok\"\n          disabled={isDisabled}\n          onClick={() => {\n            dispatch(actions.setModalId(\"\"));\n            callback(selectedData);\n          }}\n          style={{ float: \"right\", marginLeft: 8 }}\n        >\n          确认\n        </Button>\n        <Button key=\"cancel\" onClick={() => dispatch(actions.setModalId(\"\"))} style={{ float: \"right\" }}>\n          取消\n        </Button>\n      </div>\n    );\n  };\n\n  useEffect(() => {\n    if (JSON.stringify(selectedData) !== JSON.stringify(indicatorConfig)) {\n      setCheck(false);\n    }\n  }, [selectedData]);\n\n  return (\n    <>\n      <Modal\n        title={title}\n        centered\n        visible={true}\n        onCancel={() => dispatch(actions.setModalId(\"\"))}\n        width={660}\n        footer={renderFooter()}\n        maskClosable={false}\n        className=\"index-config\"\n      >\n        <Form\n          onValuesChange={(changedValues, allValues) => {\n            if (!allValues) {\n              setIsDisabled(true);\n              return;\n            }\n            let flag = true;\n            for (let key in allValues) {\n              if (!allValues[key] || allValues[key].length > 0) {\n                flag = false;\n                break;\n              }\n            }\n            setSelectedData(allValues);\n            setIsDisabled(flag);\n          }}\n        >\n          {optionList.map((item, index) => (\n            <div key={item.title + index}>\n              <Form.Item name={item.title}>\n                <SelectCheckBox\n                  title={item.title}\n                  key={count}\n                  defaultCheckedList={check ? indicatorConfig[item.title] : selectedData[item.title]}\n                  plainOptions={item.plainOptions}\n                />\n              </Form.Item>\n              {index < optionList.length - 1 ? <Divider /> : null}\n            </div>\n          ))}\n        </Form>\n      </Modal>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/logic-cluster/apply-authority.tsx",
    "content": "import * as React from 'react';\nimport { XFormWrapper } from 'component/x-form-wrapper';\nimport { connect } from \"react-redux\";\nimport * as actions from 'actions';\nimport { FormItemType, IFormItem } from 'component/x-form';\nimport { StaffSelect } from 'container/staff-select';\nimport { RenderText } from 'container/custom-form';\nimport { IWorkOrder } from 'typesPath/params-types';\nimport { submitWorkOrder } from 'api/common-api';\nimport { nounAuthority } from 'container/tooltip';\nimport { AppState, UserState } from 'store/type';\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst ApplyAauthorityModal = (props: { dispatch: any, cb: Function, app: AppState, params: any, user: UserState }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: 'name',\n        label: '集群名称',\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.name} />,\n      }, {\n        key: 'project',\n        label: '申请者所在项目',\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.app.appInfo()?.name} />,\n      }, {\n        key: 'powerType',\n        label: <span>{nounAuthority} 集群状态: </span>,\n        type: FormItemType.text,\n        customFormItem: <RenderText text={'访问'} />,\n      }, {\n        key: 'description',\n        type: FormItemType.textArea,\n        label: '申请原因',\n        rules: [{\n          required: true,\n          validator: (rule: any, value: string) => {\n            if (!value || value?.trim().length > 100) {\n              return Promise.reject('请输入1-100字申请原因');\n            } else {\n              return Promise.resolve();\n            }\n          },\n        }],\n        attrs: {\n          placeholder: '请输入1-100字申请原因',\n        },\n      }\n    ] as IFormItem[],\n    visible: true,\n    title: '申请权限',\n    formData: props.params || {},\n    width: 660,\n    okText: '提交',\n    onCancel: () => {\n      props.dispatch(actions.setModalId(''));\n    },\n    onSubmit: (result: any) => {\n      const params: IWorkOrder = {\n        contentObj: {\n          logicClusterId: props.params.id,\n          logicClusterName: props.params.name,\n          authCode: 2,\n          memo: result.description,\n        },\n        submitorProjectId: props.app.appInfo()?.id,\n        submitor: props.user.getName('userName'),\n        description: result.description,\n        type: 'logicClusterAuth',\n      };\n      return submitWorkOrder(params);\n    }\n  };\n\n  return (\n    <>\n      <XFormWrapper\n        visible={true}\n        {...xFormModalConfig}\n      />\n    </>\n  )\n};\n\nexport default connect(mapStateToProps)(ApplyAauthorityModal);\n\n"
  },
  {
    "path": "arius-console/src/container/modal/logic-cluster/apply-cluster.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { StaffSelect } from \"container/staff-select\";\nimport { getPackageList } from \"api/cluster-api\";\nimport { DataNode, RenderText } from \"container/custom-form\";\nimport { AppState, UserState } from \"store/type\";\nimport { IWorkOrder } from \"typesPath/params-types\";\nimport { submitWorkOrder } from \"api/common-api\";\nimport { RESOURCE_TYPE_LIST, LEVEL_MAP } from \"constants/common\";\nimport { staffRuleProps } from \"constants/table\";\nimport { Tooltip } from \"antd\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst ApplyClusterModal = (props: { dispatch: any; cb: Function; app: AppState; user: UserState; params: any }) => {\n  const [versionList, setVersionList] = useState([]);\n\n  useEffect(() => {\n    getVersionList();\n  }, []);\n\n  const getVersionList = async () => {\n    let ret = await getPackageList();\n    let list = ret.map((item) => {\n      return {\n        ...item,\n        value: item.esVersion,\n      };\n    });\n    setVersionList(list);\n  };\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"name\",\n        label: \"集群名称\",\n        attrs: {\n          placeholder: \"请填写集群名称，支持大、小写字母、数字、-、_，1-32位字符\",\n        },\n        rules: [\n          {\n            required: true,\n            message: \"请填写集群名称，支持大、小写字母、数字、-、_，1-32位字符\",\n            validator: async (rule: any, value: string) => {\n              const reg = /^[a-zA-Z0-9_-]{1,}$/g;\n              if (!reg.test(value) || value?.length > 32 || !value) {\n                return Promise.reject(\"请填写集群名称，支持大、小写字母、数字、-、_，1-32位字符\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"esVersion\",\n        label: \"集群版本\",\n        type: FormItemType.select,\n        options: versionList || [],\n        rules: [\n          {\n            required: true,\n            message: \"请选择\",\n          },\n        ],\n        attrs: {\n          placeholder: \"请选择版本\",\n        },\n      },\n      {\n        key: \"type\",\n        label: (\n          <div className=\"cluster-label\">\n            集群类型\n            <Tooltip\n              title={\n                <>\n                  <div>独立集群：支持集群层面的数据隔离</div>\n                  <div>独享集群：支持数据节点层面的隔离</div>\n                  <div>共享集群：数据共享</div>\n                </>\n              }\n            >\n              <span className=\"icon iconfont iconinfo\"></span>\n            </Tooltip>\n          </div>\n        ),\n        type: FormItemType.select,\n        options: RESOURCE_TYPE_LIST,\n        rules: [\n          {\n            required: true,\n            message: \"请选择\",\n          },\n        ],\n      },\n      {\n        key: \"level\",\n        label: (\n          <div className=\"cluster-label\">\n            业务等级\n            <Tooltip title=\"请根据集群实际业务等级进行选择，这里按照业务等级高低细分为核心、重要、一般\">\n              <span className=\"icon iconfont iconinfo\"></span>\n            </Tooltip>\n          </div>\n        ),\n        type: FormItemType.select,\n        options: LEVEL_MAP,\n        rules: [\n          {\n            required: true,\n            message: \"请选择\",\n          },\n        ],\n      },\n      {\n        key: \"datanode\",\n        label: \"Datanode\",\n        type: FormItemType.custom,\n        customFormItem: <DataNode />,\n        rules: [\n          {\n            required: true,\n            whitespace: true,\n            validator: async (rule: any, value: { dataNodeNu: number; dataNodeSpec: string }) => {\n              if (!value) {\n                return Promise.reject(\"请输入节点规格\");\n              }\n              if (value?.dataNodeSpec.length == 0 || value?.dataNodeNu == 0) {\n                return Promise.reject(\"请输入节点个数\");\n              } else {\n                return Promise.resolve();\n              }\n            },\n          },\n        ],\n      },\n      {\n        key: \"memo\",\n        type: FormItemType.textArea,\n        label: \"集群描述\",\n        attrs: {\n          placeholder: \"请输入0-100字集群描述\",\n        },\n        rules: [\n          {\n            required: false,\n            validator: async (rule: any, value: string) => {\n              if (value && value.length > 100) {\n                return Promise.reject(\"请输入0-100字集群描述\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"description\",\n        type: FormItemType.textArea,\n        label: \"申请原因\",\n        attrs: {\n          placeholder: \"请输入1-100字申请原因\",\n        },\n        rules: [\n          {\n            required: true,\n            whitespace: true,\n            validator: async (rule: any, value: string) => {\n              if (value?.trim().length > 0 && value?.trim().length < 100) {\n                return Promise.resolve();\n              } else {\n                return Promise.reject(\"请输入1-100字申请原因\");\n              }\n            },\n          },\n        ],\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"申请集群\",\n    formData: { type: RESOURCE_TYPE_LIST[1].value, ...props.params },\n    isWaitting: true,\n    width: 480,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      const params: IWorkOrder = {\n        contentObj: {\n          name: result.name,\n          dataNodeSpec: result.datanode.dataNodeSpec,\n          dataNodeNu: result.datanode.dataNodeNu,\n          memo: result.memo,\n          type: result.type,\n          level: result.level,\n        },\n        submitorProjectId: props.app.appInfo()?.id,\n        submitor: props.user.getName(\"userName\"),\n        description: result.description || \"\",\n        type: \"logicClusterCreate\",\n      };\n      return submitWorkOrder(params, props.params?.history, () => {\n        props.dispatch(actions.setModalId(\"\"));\n      });\n    },\n    type: \"drawer\",\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(ApplyClusterModal);\n"
  },
  {
    "path": "arius-console/src/container/modal/logic-cluster/deleteStyle.less",
    "content": ".delete-modal-content {\n  overflow: hidden;\n}\n.delete-modal-content-left2 {\n  float: left;\n  margin-right: 5px;\n  &-icon {\n    width: 14px;\n    height: 14px;\n    color: #f4a838;\n  }\n}\n\n.delete-modal-content-right2 {\n  float: left;\n  width: 400px;\n  &-p1 {\n    font-family: PingFangSC-Medium;\n    font-size: 12px;\n    color: #303a51;\n    line-height: 20px;\n  }\n  &-p2 {\n    font-family: PingFangSC-Regular;\n    font-size: 12px;\n    color: #303a51;\n    line-height: 20px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/logic-cluster/edit-cluster.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { XNotification } from \"component/x-notification\";\nimport { StaffSelect } from \"container/staff-select\";\nimport { opEditLogicCluster } from \"api/cluster-api\";\nimport { RenderText } from \"container/custom-form\";\nimport { AppState } from \"store/type\";\nimport { staffRuleProps } from \"constants/table\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n});\n\nconst EditClusterModal = (props: { dispatch: any; app: AppState; cb: Function; params: any }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"name\",\n        label: \"集群名称\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.name} />,\n      },\n      {\n        key: \"memo\",\n        type: FormItemType.textArea,\n        label: \"集群描述\",\n        rules: [\n          {\n            required: false,\n            whitespace: true,\n            validator: (rule: any, value: string) => {\n              if (!value) {\n                return Promise.resolve();\n              }\n              if (value?.trim().length >= 0 && value?.trim().length < 100) {\n                return Promise.resolve();\n              } else {\n                return Promise.reject(\"0-100个字符\");\n              }\n            },\n          },\n        ],\n        attrs: {\n          placeholder: \"请输入该集群描述，0-100字\",\n        },\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"编辑集群\",\n    formData: props.params || {},\n    isWaitting: true,\n    width: 660,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      const req = props.params;\n      req.memo = result.memo;\n      return opEditLogicCluster(req)\n        .then((res) => {\n          props.dispatch(actions.setModalId(\"\"));\n        })\n        .finally(() => {\n          props.cb && props.cb(); // 重新获取数据列表\n        });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper visible={true} {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(EditClusterModal);\n"
  },
  {
    "path": "arius-console/src/container/modal/logic-cluster/expand-shrink-cluster.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { ExpectDataNodeNu, RenderText, ShowCost } from \"container/custom-form\";\nimport { IWorkOrder } from \"typesPath/params-types\";\nimport { getDiskSize } from \"api/cluster-api\";\nimport { submitWorkOrder } from \"api/common-api\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { ICluster } from \"typesPath/cluster/cluster-types\";\nimport { AppState, UserState } from \"store/type\";\nimport { bytesUnitFormatter } from \"lib/utils\";\nimport { getRegionNodeSpec } from \"api/op-cluster-region-api\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst ExpandShrinkModal = (props: { dispatch: any; cb: Function; params: any; app: AppState; user: UserState }) => {\n  const [count, setCount] = useState(props.params?.dataNodeNum || 0);\n  const [diskSize, setDiskSize] = useState(\"\" as string | number);\n  const [dataNodeSpec, setDataNodeSpec] = useState(\"-\");\n  useEffect(() => {\n    _getDiskSize();\n  }, [count]);\n\n  const _getDiskSize = async () => {\n    let res = await getDiskSize(props.params.id, count);\n    let size = res === -1 ? \"-\" : bytesUnitFormatter(res);\n    setDiskSize(size);\n  };\n\n  useEffect(() => {\n    getRegionNodeSpec(props.params.id).then((res) => {\n      setDataNodeSpec(res || \"-\");\n    });\n  }, []);\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"name\",\n        label: \"集群名称\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.name} />,\n      },\n      {\n        key: \"oldDataNodeNu\",\n        label: \"现有节点数\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params?.dataNodeNum || 0} />,\n      },\n      {\n        key: \"dataNodeNum\",\n        label: \"期望节点数\",\n        type: FormItemType.custom,\n        isCustomStyle: true,\n        CustomStyle: { marginBottom: 0 },\n        customFormItem: <ExpectDataNodeNu min={0} podNumber={props.params?.dataNodeNum || 0} />,\n        rules: [\n          {\n            required: true,\n            validator: (rule: any, value: any) => {\n              if (props.params?.dataNodeNum === value) {\n                return Promise.reject(\"不能与原来一样\");\n              }\n              if (value < 1) {\n                return Promise.reject(\"请输入节点个数，大于等于1的正整数\");\n              } else {\n                setCount(value);\n                return Promise.resolve();\n              }\n            },\n          },\n        ],\n      },\n      {\n        key: \"dataNodeSpec\",\n        label: \"节点规格\",\n        type: FormItemType.text,\n        isCustomStyle: true,\n        CustomStyle: { marginTop: 16 },\n        customFormItem: <RenderText text={dataNodeSpec || \"-\"} />,\n      },\n      {\n        key: \"diskSize\",\n        label: \"磁盘大小预估\",\n        type: FormItemType.text,\n        isCustomStyle: true,\n        CustomStyle: { marginTop: 16 },\n        customFormItem: <RenderText text={diskSize || \"-\"} />,\n      },\n      // {\n      //   key: 'clusterCost',\n      //   label: '集群成本',\n      //   type: FormItemType.text,\n      //   customFormItem: <ShowCost />,\n      // },\n      {\n        key: \"description\",\n        label: \"申请原因\",\n        type: FormItemType.textArea,\n        rules: [\n          {\n            required: true,\n            whitespace: true,\n            validator: (rule: any, value: string) => {\n              if (!value || value?.trim().length >= 100) {\n                return Promise.reject(\"请输入1-100字申请原因\");\n              } else {\n                return Promise.resolve();\n              }\n            },\n          },\n        ],\n        attrs: {\n          placeholder: \"请输入1-100字申请原因\",\n        },\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"集群扩缩容\",\n    formData: props.params || {},\n    needBtnLoading: true,\n    width: 660,\n    okText: \"提交\",\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: async (result: any) => {\n      const params: IWorkOrder = {\n        contentObj: {\n          logicClusterId: props.params.id,\n          logicClusterName: props.params.name,\n          dataNodeSpec,\n          dataNodeNu: result.dataNodeNum,\n          memo: result.memo,\n        },\n        submitorProjectId: props.app.appInfo()?.id,\n        submitor: props.user.getName(\"userName\"),\n        description: result.description,\n        type: \"logicClusterIndecrease\",\n      };\n      await submitWorkOrder(params, props.params?.history, () => {\n        props.dispatch(actions.setModalId(\"\"));\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper visible={true} {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(ExpandShrinkModal);\n"
  },
  {
    "path": "arius-console/src/container/modal/logic-cluster/index.less",
    "content": ".cluster-label {\n  .iconinfo {\n    font-size: 14px;\n    margin-left: 5px;\n    color: rgb(140, 140, 140);\n    position: relative;\n    bottom: 1px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/logic-cluster/offlineLogicCluster.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { Modal } from \"antd\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { InfoCircleOutlined } from \"@ant-design/icons\";\nimport { deleteLogic } from \"api/cluster-api\";\nimport { XNotification } from \"component/x-notification\";\nimport \"./deleteStyle.less\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const OfflineCluster = connect(mapStateToProps)((props: { dispatch: any; params: any; cb: any }) => {\n  const { params, dispatch, cb } = props;\n  const [loading, setLoading] = useState(false);\n\n  return (\n    <>\n      <Modal\n        visible={true}\n        title={\"逻辑集群下线\"}\n        centered\n        maskClosable={false}\n        width={480}\n        okButtonProps={{ loading: loading }}\n        onCancel={() => {\n          dispatch(actions.setModalId(\"\"));\n        }}\n        onOk={async () => {\n          setLoading(true);\n          deleteLogic(params.id)\n            .then(() => {\n              XNotification({ type: \"success\", message: `逻辑集群${params.name}下线成功` });\n              cb();\n              dispatch(actions.setModalId(\"\"));\n            })\n            .finally(() => {\n              setLoading(false);\n            });\n        }}\n      >\n        <div>\n          <div className=\"delete-modal-content\">\n            <div className=\"delete-modal-content-left2\">\n              <InfoCircleOutlined className=\"delete-modal-content-left-icon\" />\n            </div>\n            <div className=\"delete-modal-content-right2\">\n              <p className=\"delete-modal-content-right-p1\">是否确定删除逻辑集群{params.name}？</p>\n            </div>\n          </div>\n        </div>\n      </Modal>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/access-cluster.tsx",
    "content": "import React, { useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"../../../actions\";\nimport { Dispatch } from \"redux\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport \"./index.less\";\nimport { clusterJoin } from \"api/cluster-api\";\nimport { INPUT_RULE_MAP } from \"constants/status-map\";\nimport Senior from \"./senior\";\nimport { regIp, regPort } from \"constants/reg\";\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nconst mapStateToProps = (state) => ({\n  app: state.app,\n  cb: state.modal.cb,\n});\n\nconst AccessCluster = ({ app, cb, setModalId }) => {\n  const [seniorValue, setSeniorValue] = useState({} as any);\n  const [isFullType, setIsFullType] = useState(false);\n\n  const getRoleClusterHosts = async (baseInfoData) => {\n    let arrRoleClusterHosts = [];\n    let nodeList = [\n      { fullnodes: baseInfoData?.fullnodes },\n      { masternode: baseInfoData?.masternode },\n      { clientnode: baseInfoData?.clientnode },\n      { datanode: baseInfoData?.datanode },\n    ];\n    nodeList.forEach((item) => {\n      let key = Object.keys(item)[0];\n      const arr = item[key]?.split(\"\\n\")?.filter((ele: string) => ele !== \"\");\n      (arr || []).forEach((item) => {\n        const ipPostArr = item.split(\":\");\n        const arrRoleClusterHost: any = {\n          cluster: baseInfoData.name,\n          id: 0,\n          ip: ipPostArr[0],\n          nodeSet: \"\",\n          port: ipPostArr[1],\n          role: key === \"datanode\" ? 1 : key === \"clientnode\" ? 2 : 3, //角色 1data   2client    3master\n          roleClusterId: 0,\n          status: 0,\n        };\n        arrRoleClusterHosts.push(arrRoleClusterHost);\n      });\n    });\n    return arrRoleClusterHosts;\n  };\n\n  const checkText = (value, type) => {\n    // 非master不做空判断\n    if (!value && type == \"masternode\") {\n      return \"请按照 IP:端口号的形式填写，例如：127.1.1.1:8888 ，不同IP用换行符分隔。\";\n    }\n    const values = value?.split(\"\\n\").filter((ele: string) => ele !== \"\") || [];\n    const IP_TIP = \"请输入IP:端口号，例如：127.1.1.1:8888。多个IP用换行分割\";\n\n    let flat = false;\n    let flatPost = false;\n    let flatLength = false;\n    let flatIp = false;\n    const ipArr = [];\n\n    values.forEach((element) => {\n      if (element.indexOf(\":\") === -1) {\n        flat = true;\n      } else {\n        const isPostArr = element.split(\":\");\n        ipArr.push(isPostArr[0]);\n        if (!new RegExp(regIp).test(isPostArr[0])) {\n          flatIp = true;\n        }\n        if ((!isPostArr[1] && flatIp === false) || !new RegExp(regPort).test(isPostArr[1])) {\n          flatPost = true;\n        }\n        if (isPostArr[1] && flatIp === false) {\n          if (+isPostArr[1] > 25535) {\n            flatLength = true;\n          }\n        }\n      }\n    });\n    // 多个相同 ip\n    if (new Set(ipArr).size != ipArr.length) {\n      return `${IP_TIP}且 ip 不能相同`;\n    } else if (flat || flatIp || flatPost) {\n      // 格式错误，ip不符合规范, 没有:号, :号后面没有端口\n      return IP_TIP;\n    } else if (flatLength) {\n      // 格式错误，:号端口格式不正确, 多个请换行。\n      return `${IP_TIP}，输入端口号超最大值25535`;\n    }\n  };\n\n  const xFormModalConfig = () => {\n    let formMap = [\n      {\n        key: \"name\",\n        label: \"集群名称\",\n        attrs: {\n          placeholder: \"请填写集群名称，支持大、小写字母、数字、-、_，1-32位字符\",\n          style: { width: 432 },\n        },\n        rules: [\n          {\n            required: true,\n            message: \"请填写集群名称，支持大、小写字母、数字、-、_，1-32位字符\",\n            validator: async (rule: any, value: string) => {\n              const reg = /^[a-zA-Z0-9_-]{1,}$/g;\n              if (!reg.test(value) || value.length > 32 || !value) {\n                return Promise.reject(\"请填写集群名称，支持大、小写字母、数字、-、_，1-32位字符\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"importRule\",\n        label: \"录入规则\",\n        type: FormItemType.radioGroup,\n        defaultValue: \"0\",\n        className: \"import-rule\",\n        attrs: {\n          onChange: (e) => {\n            if (e && e.target) {\n              let bool = e.target.value === \"1\";\n              setIsFullType(bool);\n            }\n          },\n        },\n        options: Object.keys(INPUT_RULE_MAP).map((item) => {\n          return {\n            label: INPUT_RULE_MAP[item],\n            value: item,\n          };\n        }),\n        rules: [{ required: true, message: \"请选择录入规则\" }],\n      },\n      {\n        key: \"fullnodes\",\n        label: \"集群节点\",\n        type: FormItemType.textArea,\n        className: \"access-add-role\",\n        attrs: {\n          placeholder:\n            \"请添加可接入节点，masternode、clientnode、datanode均可，需按照IP：端口号的形式填写，例如：127.1.1.1:8888 ，不同IP用换行符分隔。\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: { type: string; value: string; check?: boolean }[]) => {\n              let errormsg = checkText(value, \"masternode\");\n              if (errormsg) {\n                return Promise.reject(errormsg);\n              }\n              return Promise.resolve(\"\");\n            },\n          },\n        ],\n      },\n      {\n        key: \"senior\",\n        className: \"access-senior\",\n        type: FormItemType.custom,\n        customFormItem: <Senior seniorChange={(val) => setSeniorValue(val)} seniorValue={seniorValue} />,\n      },\n    ] as IFormItem[];\n    if (isFullType) {\n      let fullnode = [\n        {\n          key: \"masternode\",\n          label: \"Masternode\",\n          type: FormItemType.textArea,\n          className: \"access-add-role\",\n          attrs: {\n            placeholder: \"请按照 IP:端口号的形式填写，例如：127.1.1.1:8888 ，不同IP用换行符分隔。\",\n          },\n          rules: [\n            {\n              required: true,\n              validator: async (rule: any, value: { type: string; value: string; check?: boolean }[]) => {\n                let errormsg = checkText(value, \"masternode\");\n                if (errormsg) {\n                  return Promise.reject(errormsg);\n                }\n                return Promise.resolve(\"\");\n              },\n            },\n          ],\n        },\n        {\n          key: \"clientnode\",\n          label: \"Clientnode\",\n          type: FormItemType.textArea,\n          className: \"access-add-role\",\n          attrs: {\n            placeholder: \"请按照 IP:端口号的形式填写，例如：127.1.1.1:8888 ，不同IP用换行符分隔。\",\n          },\n          rules: [\n            {\n              validator: async (rule: any, value: { type: string; value: string; check?: boolean }[]) => {\n                let errormsg = checkText(value, \"clientnode\");\n                if (errormsg) {\n                  return Promise.reject(errormsg);\n                }\n                return Promise.resolve(\"\");\n              },\n            },\n          ],\n        },\n        {\n          key: \"datanode\",\n          label: \"Datanode\",\n          type: FormItemType.textArea,\n          className: \"access-add-role\",\n          attrs: {\n            placeholder: \"请按照 IP:端口号的形式填写，例如：127.1.1.1:8888 ，不同IP用换行符分隔。\",\n          },\n          rules: [\n            {\n              validator: async (rule: any, value: { type: string; value: string; check?: boolean }[]) => {\n                let errormsg = checkText(value, \"datanode\");\n                if (errormsg) {\n                  return Promise.reject(errormsg);\n                }\n                return Promise.resolve(\"\");\n              },\n            },\n          ],\n        },\n      ];\n      formMap.splice(2, 1, ...fullnode);\n    }\n    return {\n      formMap,\n      title: \"接入集群\",\n      width: 480,\n      visible: true,\n      formData: {},\n      needBtnLoading: true,\n      onCancel: () => setModalId(\"\"),\n      onSubmit: async (result) => {\n        const roleClusterHosts = await getRoleClusterHosts(result);\n        let password = seniorValue.usename && seniorValue.password ? `${seniorValue.usename}:${seniorValue.password}` : \"\";\n        const params = {\n          type: 4,\n          resourceType: Number(seniorValue.clusterType) || 2, // 集群类型默认为独立集群\n          dataCenter: seniorValue.dataCenter || \"\",\n          platformType: seniorValue.platformType || \"\",\n          tags: JSON.stringify({\n            createSource: 0, // 0接入1新建\n          }),\n          proxyAddress: seniorValue.proxyAddress,\n          kibanaAddress: seniorValue.kibanaAddress,\n          cerebroAddress: seniorValue.cerebroAddress,\n          importRule: result.importRule,\n          projectId: app.appInfo()?.id,\n          cluster: result.name,\n          divide: true,\n          logicCluster: result?.logicCluster,\n          phyClusterDesc: result.desc || \"\",\n          singular: result.singular,\n          roleClusterHosts,\n          password,\n        };\n        await clusterJoin(params);\n        setModalId(\"\");\n        cb();\n      },\n    };\n  };\n\n  return <XFormWrapper type={\"drawer\"} {...xFormModalConfig()} />;\n};\n\nexport default connect(mapStateToProps, mapDispatchToProps)(AccessCluster);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/apply-cluster.tsx",
    "content": "import React, { useState } from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { regClusterName } from \"constants/reg\";\nimport { INode } from \"typesPath/cluster/cluster-types\";\nimport { AppState, UserState } from \"store/type\";\nimport { creatCluster } from \"api/cluster-api\";\nimport { Masternode } from \"container/custom-form\";\nimport { AddRoleTable, nodeTypeList } from \"container/custom-form/add-role-table\";\nimport { addRoleformMap } from \"container/custom-form/tpl-table-add-row/editTable\";\nimport { RESOURCE_TYPE_LIST } from \"constants/common\";\nimport Senior from \"./senior\";\nimport { showSubmitTaskSuccessModal } from \"container/custom-component\";\nimport { Tooltip } from \"antd\";\n\nexport interface INodeListObjet {\n  masternode: INode[];\n  clientnode: INode[];\n  datanode: INode[];\n  datanodeceph: INode[];\n}\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst ApplyPhyClusterModal = (props: { dispatch: any; cb: Function; app: AppState; user: UserState; params: any }) => {\n  const [seniorValue, setSeniorValue] = useState({} as any);\n\n  const getRoleClusterHosts = (result) => {\n    // 聚合成接口请求的格式\n    const masternodeRoleArr = [];\n    const masternodeRoleArrKey = [];\n    const clientnodeRoleArr = [];\n    const clientnodeRoleArrKey = [];\n    const datanodeRoleArr = [];\n    const datanodeRoleArrKey = [];\n    const coldRoleArr = [];\n    const coldRoleArrKey = [];\n\n    Object.keys(result).map((item) => {\n      if (item.indexOf(nodeTypeList[0]) > -1) {\n        const analysisKey = item.split(\"&\");\n        if (analysisKey.length !== 3) return;\n        masternodeRoleArr.push({ role: analysisKey[0], [analysisKey[1]]: result[item], key: analysisKey[2], beCold: false });\n        masternodeRoleArrKey.push(analysisKey[2]);\n      }\n      if (item.indexOf(nodeTypeList[1]) > -1) {\n        const analysisKey = item.split(\"&\");\n        if (analysisKey.length !== 3) return;\n        clientnodeRoleArr.push({ role: analysisKey[0], [analysisKey[1]]: result[item], key: analysisKey[2], beCold: false });\n        clientnodeRoleArrKey.push(analysisKey[2]);\n      }\n      if (item.indexOf(nodeTypeList[2]) > -1) {\n        const analysisKey = item.split(\"&\");\n        if (analysisKey.length !== 3) return;\n        datanodeRoleArr.push({ role: analysisKey[0], [analysisKey[1]]: result[item], key: analysisKey[2], beCold: false });\n        datanodeRoleArrKey.push(analysisKey[2]);\n      }\n      if (item.indexOf(nodeTypeList[3]) > -1) {\n        const analysisKey = item.split(\"&\");\n        if (analysisKey.length !== 3) return;\n        // 此处role使用datanode\n        coldRoleArr.push({ role: nodeTypeList[2], [analysisKey[1]]: result[item], key: analysisKey[2], beCold: true });\n        coldRoleArrKey.push(analysisKey[2]);\n      }\n    });\n    const masternodeHosts = getRole(masternodeRoleArrKey, masternodeRoleArr);\n    const clientnodeHosts = getRole(clientnodeRoleArrKey, clientnodeRoleArr);\n    const datanodeHosts = getRole(datanodeRoleArrKey, datanodeRoleArr);\n    const coldHosts = getRole(coldRoleArrKey, coldRoleArr);\n    const roleClusterHosts = [...masternodeHosts, ...clientnodeHosts, ...datanodeHosts, ...coldHosts];\n    return roleClusterHosts;\n  };\n\n  const getRole = (arrKey, RoleArr) => {\n    const arr = [];\n    new Set([...arrKey]).forEach((item) => {\n      let obj: { [key: string]: any } = {};\n      RoleArr.forEach((ele) => {\n        if (item === ele.key) {\n          obj = { ...obj, ...ele };\n        }\n      });\n      const realDataStructure = {\n        role: obj.role,\n        address: obj[addRoleformMap[0].key],\n        beCold: obj.beCold,\n        machineSpec: obj.machineSpec,\n      };\n      if (\n        obj[addRoleformMap[0].key] ||\n        obj[addRoleformMap[1].key] ||\n        obj[addRoleformMap[2].key] ||\n        obj[addRoleformMap[3].key] ||\n        obj[addRoleformMap[4].key]\n      ) {\n        arr.push(realDataStructure);\n      }\n    });\n    return arr;\n  };\n\n  const xFormModalConfig = {\n    formMap: [\n      [\n        {\n          key: \"phyClusterName\",\n          label: \"集群名称\",\n          attrs: {\n            placeholder: \"请填写集群名称，支持大、小写字母、数字、-、_，1-32位字符\",\n          },\n          isCustomStyle: true,\n          CustomStyle: { marginBottom: 0 },\n          rules: [\n            {\n              required: true,\n              message: \"请填写集群名称，支持大、小写字母、数字、-、_，1-32位字符\",\n              validator: async (rule: any, value: string) => {\n                const reg = /^[a-zA-Z0-9_-]{1,}$/g;\n                if (!reg.test(value) || value?.length > 32 || !value) {\n                  return Promise.reject(\"请填写集群名称，支持大、小写字母、数字、-、_，1-32位字符\");\n                }\n                return Promise.resolve();\n              },\n            },\n          ],\n        },\n        {\n          key: \"esVersion\",\n          label: \"集群版本\",\n          type: FormItemType.select,\n          options: props.params?.packageHostList || [],\n          isCustomStyle: true,\n          CustomStyle: { marginBottom: 0 },\n          rules: [\n            {\n              required: true,\n              message: \"请选择集群版本\",\n            },\n          ],\n          attrs: {\n            placeholder: \"请选择版本\",\n          },\n        },\n      ],\n      {\n        key: \"nsTree\",\n        label: \"机器节点\",\n        rules: [\n          {\n            required: true,\n            message: \"请输入机器节点\",\n          },\n        ],\n        attrs: {\n          placeholder: \"请输入例如：arius-es-test.data-online.fd.es.com\",\n        },\n      },\n      // {\n      //   key: \"masternode\",\n      //   label: \"Masternode\",\n      //   type: FormItemType.custom,\n      //   customFormItem: <Masternode nodeList={props.params?.nodeList || []} />,\n      //   rules: [\n      //     {\n      //       required: true,\n      //       whitespace: true,\n      //       validator: async (rule: any, value) => {\n      //         if (value) {\n      //           return Promise.resolve();\n      //         }\n      //         return Promise.reject();\n      //       },\n      //     },\n      //   ],\n      // },\n      {\n        key: \"desc\",\n        type: FormItemType.textArea,\n        label: \"集群描述\",\n        rules: [\n          {\n            required: false,\n            message: \"请输入0-100个字描述信息\",\n            validator: async (rule: any, value: string) => {\n              if (!value || value?.trim().length <= 100) {\n                return Promise.resolve();\n              } else {\n                return Promise.reject();\n              }\n            },\n          },\n        ],\n        attrs: {\n          placeholder: \"请输入集群描述\",\n        },\n      },\n      {\n        key: \"senior\",\n        className: \"apply-senior\",\n        type: FormItemType.custom,\n        customFormItem: <Senior seniorChange={(val) => setSeniorValue(val)} type=\"apply\" seniorValue={seniorValue} />,\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"新建集群\",\n    formData: { resourceType: RESOURCE_TYPE_LIST[1].value },\n    width: 850,\n    needBtnLoading: true,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: async (result: { [key: string]: any }) => {\n      let clusterRoleHosts = getRoleClusterHosts(result);\n      let password = seniorValue.usename && seniorValue.password ? `${seniorValue.usename}:${seniorValue.password}` : \"\";\n      let params = {\n        type: 4,\n        clusterRoleHosts,\n        esVersion: result.esVersion,\n        phyClusterName: result.phyClusterName,\n        desc: result.desc,\n        tags: JSON.stringify({\n          createSource: 1, // 0接入1新建\n        }),\n        dataCenter: seniorValue.dataCenter || \"\",\n        resourceType: Number(seniorValue.clusterType) || 2, // 集群类型默认为独立集群\n        proxyAddress: seniorValue.proxyAddress,\n        kibanaAddress: seniorValue.kibanaAddress,\n        cerebroAddress: seniorValue.cerebroAddress,\n        password,\n      };\n      let expandData = JSON.stringify(params);\n      let ret = await creatCluster({ expandData });\n      props.dispatch(actions.setModalId(\"\"));\n      showSubmitTaskSuccessModal(ret, props.params?.history);\n    },\n  };\n\n  const hostItem = [\n    {\n      key: \"masternode\",\n      label: \"Masternode\",\n      type: FormItemType.custom,\n      customFormItem: <AddRoleTable machineList={props.params?.machineList || []} />,\n      rules: [\n        {\n          required: true,\n          validator: (rule: any, value: any) => {\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n  ] as IFormItem[];\n\n  const esVersionHost = {\n    key: \"esVersion\",\n    label: \"集群版本\",\n    type: FormItemType.select,\n    options: props.params?.packageHostList || [],\n    rules: [\n      {\n        required: true,\n        message: \"请选择\",\n      },\n    ],\n    attrs: {\n      placeholder: \"请选择版本\",\n    },\n  } as IFormItem;\n\n  // 默认选中 host，更新选中 host 后的配置项\n  // xFormModalConfig.formMap.splice(5, 2, ...hostItem);\n  // xFormModalConfig.formMap.splice(4, 1, esVersionHost);\n  // 物理集群-新建集群，责任人暂时注释，剪切下标需要减一\n  xFormModalConfig.formMap.splice(1, 1, ...hostItem);\n  // (xFormModalConfig.formMap[1] as any).splice(1, 1, esVersionHost);\n\n  // 这是一段比较恶心的代码 xform的值无法传下去 但是内部需要接收到\n  React.useEffect(() => {\n    return () => {\n      (window as any).masternodeErr = false;\n      delete (window as any).masternodeErr;\n      delete (window as any).formData;\n    };\n  }, []);\n\n  const { loading } = props.params;\n\n  const onHandleValuesChange = (value: any, allValues: object) => {\n    (window as any).formData = {\n      value,\n      allValues,\n    };\n  };\n\n  return (\n    <>\n      {!loading ? (\n        <XFormWrapper onHandleValuesChange={onHandleValuesChange} type={\"drawer\"} visible={true} {...xFormModalConfig} />\n      ) : (\n        <span>loading...</span>\n      )}\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(ApplyPhyClusterModal);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/bind-gateway.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { bindGateway } from \"api/cluster-api\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { AppState, UserState } from \"store/type\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { Modal, Button } from \"antd\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst BindGateway = (props: { dispatch: any; cb: Function; app: AppState; user: UserState; params: any }) => {\n  const [options, setOptions] = useState(null);\n  const handleFormData = () => {\n    if (props.params?.gatewayUrl) {\n      const gatewayUrl = props.params?.gatewayUrl.split(\",\");\n      return gatewayUrl;\n    }\n  };\n  // useEffect(() => {\n  //获取getWayList\n  //   getGateway().then((res)=>{\n  //     const options=res.list;\n  //     setOptions(options)\n  //   })\n  // }, [])\n  //gataway还没有开发完成，option状态只是测试数据\n  useEffect(() => {\n    setOptions([\n      {\n        label: \"gold\",\n        value: \"gold\",\n      },\n      {\n        label: \"lime\",\n        value: \"lime\",\n      },\n      {\n        label: \"green\",\n        value: \"green\",\n      },\n      {\n        label: \"cyan\",\n        value: \"cyan\",\n      },\n    ]);\n  }, []);\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"gateway\",\n        label: \"Gateway名称\",\n        type: FormItemType.select,\n        isCustomStyle: true,\n        CustomStyle: { margin: 0 },\n        attrs: {\n          mode: \"multiple\",\n          //options: options,\n          placeholder: \"请选择\",\n        },\n        rules: [{ required: true }],\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"绑定Gateway\",\n    //formData: { 'gateway': props.params?.gateway || '' },\n    formData: { gateway: handleFormData() },\n    //isWaitting: true,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (res) => {\n      const req = JSON.parse(JSON.stringify(res));\n      const gatewayUrl = res.gateway.join(\",\");\n      req[\"gatewayUrl\"] = gatewayUrl;\n      req[\"id\"] = props.params.id;\n      return bindGateway(req)\n        .then(() => {\n          Modal.warning({\n            title: \"提示\",\n            okText: \"确定\",\n            content: (\n              <>\n                <div>\n                  <span>绑定成功!</span>\n                  <br />\n                  <span>\n                    如需变更查询模式，请前往\n                    <a href=\"\" onClick={() => props.params.history.push(\"/system/users\")}>\n                      应用管理\n                    </a>\n                    进行访问设置，创建不同的查询模式\n                  </span>\n                </div>\n              </>\n            ),\n          });\n        })\n        .finally(() => {\n          props.cb && props.cb();\n          props.dispatch(actions.setModalId(\"\"));\n        });\n    },\n    width: 480,\n    bodyStyle: { height: 300 },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(BindGateway);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/deleteCluster.tsx",
    "content": "import React from \"react\";\n//import { Modal, Form, Input, message } from 'antd';\nimport { Modal, message } from \"knowdesign\";\nconst { confirm } = Modal;\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { IconFont } from \"@knowdesign/icons\";\n//import { submitWorkOrder } from \"api/common-api\";\nimport { clusterDelete } from \"api/cluster-api\";\nimport store from \"store\";\nimport \"./deleteStyle.less\";\n\nconst loginInfo = {\n  userName: store.getState().user?.getName,\n  app: store.getState().app,\n};\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const DeleteCluster = connect(mapStateToProps)((props: { dispatch: any; params: any; cb: any }) => {\n  const { params, dispatch, cb } = props;\n  confirm({\n    title: `确定要删除物理集群${params.cluster}？`,\n    icon: <IconFont type=\"icon-shibai\" />,\n    content: `集群删除后，集群所有相关数据也将被删除，请谨慎操作！`,\n    okText: \"确定\",\n    cancelText: \"取消\",\n    onOk: async () => {\n      const param: any = {\n        regionId: params.id,\n      };\n      clusterDelete(param).then(() => {\n        message.success(\"下线成功\");\n        cb();\n        dispatch(actions.setModalId(\"\"));\n      });\n    },\n    onCancel: () => {\n      dispatch(actions.setModalId(\"\"));\n    },\n  });\n  return (\n    <>\n      {/* <Modal\n        visible={true}\n        title={\"集群下线\"}\n        centered\n        maskClosable={false}\n        width={480}\n        onCancel={() => {\n          dispatch(actions.setModalId(\"\"));\n        }}\n        onOk={async () => {\n          const param: any = {\n            regionId: params.id,\n          };\n          clusterDelete(param).then(() => {\n            message.success(\"下线成功\");\n            cb();\n            dispatch(actions.setModalId(\"\"));\n          });\n        }}\n      >\n        <div>\n          <div className=\"delete-modal-content\">\n            <div className=\"delete-modal-content-left\">\n              <InfoCircleOutlined className=\"delete-modal-content-left-icon\" />\n            </div>\n            <div className=\"delete-modal-content-right\">\n              <p className=\"delete-modal-content-right-p1\">是否确定删除物理集群{params.cluster}？</p>\n              <p className=\"delete-modal-content-right-p2\">集群删除后，集群所有相关数据也将被删除，请谨慎操作！</p>\n            </div>\n          </div>\n        </div>\n      </Modal> */}\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/deleteStyle.less",
    "content": ".delete-modal-content {\n  overflow: hidden;\n}\n.delete-modal-content-left {\n  float: left;\n  margin-right: 5px;\n  &-icon {\n    width: 14px;\n    height: 14px;\n    color: #F4A838;\n  }\n}\n\n.delete-modal-content-right {\n  float: left;\n  &-p1 {\n    font-family: PingFangSC-Medium;\n    font-size: 12px;\n    color: #303A51;\n    line-height: 20px;\n  }\n  &-p2 {\n    font-family: PingFangSC-Regular;\n    font-size: 12px;\n    color: #303A51;\n    line-height: 20px;\n  }\n}"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/docker-expand-shrink-cluster.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { RenderText } from \"container/custom-form\";\nimport { DockerExpectDataNodeNu } from \"container/custom-form\";\nimport { VERSION_MAINFEST_TYPE } from \"constants/status-map\";\nimport { IOpPhysicsClusterDetail } from \"typesPath/cluster/cluster-types\";\nimport { IWorkOrder } from \"typesPath/params-types\";\nimport { submitWorkOrder } from \"api/common-api\";\nimport { AppState, UserState } from \"store/type\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst DockerExpandShrinkCluster = (props: {\n  dispatch: any;\n  cb: Function;\n  app: AppState;\n  user: UserState;\n  params: IOpPhysicsClusterDetail;\n}) => {\n  const dataData = props.params?.esRoleClusterVOS?.filter((ele) => ele.role === \"datanode\");\n  const masternode = props.params?.esRoleClusterVOS?.filter((ele) => ele.role === \"masternode\");\n  const clientnode = props.params?.esRoleClusterVOS?.filter((ele) => ele.role === \"clientnode\");\n  const dataObj = dataData[0];\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"cluster\",\n        label: \"集群名称\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.cluster} />,\n      },\n      {\n        key: \"project\",\n        label: \"所属应用\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={\"es\"} />,\n      },\n      {\n        key: \"type\",\n        label: \"集群类型\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={VERSION_MAINFEST_TYPE[props.params.type]} />,\n      },\n      {\n        key: \"esVersion\",\n        label: \"ES版本\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.esVersion} />,\n      },\n      {\n        key: \"machineSpec\",\n        label: \"Datanode规格\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={dataObj.machineSpec} />,\n      },\n      {\n        key: \"dataNodeNu\",\n        label: \"现有Datanode节点数\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={dataObj.podNumber} />,\n      },\n      {\n        key: \"podNumber\",\n        label: \"期望Datanode节点数\",\n        type: FormItemType.custom,\n        customFormItem: <DockerExpectDataNodeNu podNumber={dataObj.podNumber} style={{ width: \"60%\" }} />,\n        rules: [\n          {\n            required: true,\n            validator: (rule: any, value: number) => {\n              if (dataObj.podNumber === value) {\n                return Promise.reject(\"不能与原来一样\");\n              }\n              if (value && value > 1) {\n                return Promise.resolve();\n              }\n              return Promise.reject(\"大于1\");\n            },\n          },\n        ],\n      },\n      {\n        key: \"description\",\n        type: FormItemType.textArea,\n        label: \"申请原因\",\n        rules: [\n          {\n            required: true,\n            whitespace: true,\n            validator: (rule: any, value: string) => {\n              if (value?.trim().length > 0 && value?.trim().length < 100) {\n                return Promise.resolve();\n              } else {\n                return Promise.reject(\"请输入1-100个字符\");\n              }\n            },\n          },\n        ],\n        attrs: {\n          placeholder: \"请输入该项目描述，0-50字\",\n        },\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"扩缩容\",\n    formData: dataObj || {},\n    isWaitting: true,\n    width: 660,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      const roleClusters = [];\n      if (dataObj?.podNumber !== result?.dataNodeNu) {\n        const datanodeObj = {\n          role: \"datanode\",\n          originPodNumber: dataObj?.podNumber,\n          podNumber: result?.podNumber,\n          pidCount: \"\",\n          machineSpec: dataObj?.machineSpec,\n        };\n        const masternodeObj = {\n          role: \"masternode\",\n          originPodNumber: masternode[0]?.podNumber,\n          podNumber: masternode[0]?.podNumber,\n          pidCount: \"\",\n          machineSpec: masternode[0]?.machineSpec,\n        };\n        const clientnodeObj = {\n          role: \"clientnode\",\n          originPodNumber: clientnode[0]?.podNumber,\n          podNumber: clientnode[0]?.podNumber,\n          pidCount: \"\",\n          machineSpec: clientnode[0]?.machineSpec,\n        };\n        roleClusters.push(datanodeObj, masternodeObj, clientnodeObj);\n      }\n      const contentObj = {\n        type: 3,\n        operationType: dataObj.podNumber - result?.podNumber >= 0 ? 3 : 2, //  2:扩容 3:缩容\n        phyClusterId: props.params.id,\n        phyClusterName: props.params.cluster,\n        roleClusters,\n      };\n      const params: IWorkOrder = {\n        contentObj,\n        submitorProjectId: props.app.appInfo()?.id,\n        submitor: props.user.getName(\"userName\"),\n        description: result.description || \"\",\n        type: \"clusterOpIndecrease\",\n      };\n\n      return submitWorkOrder(params, props.params?.history, () => {\n        props.dispatch(actions.setModalId(\"\"));\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper visible={true} {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(DockerExpandShrinkCluster);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/edit-cluster.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { RenderText } from \"container/custom-form\";\nimport { VERSION_MAINFEST_TYPE } from \"constants/status-map\";\nimport { IOpPhysicsClusterDetail } from \"typesPath/cluster/cluster-types\";\nimport { improveOpEditCluster } from \"api/cluster-api\";\nimport { XNotification } from \"component/x-notification\";\nimport { regIp, regPort } from \"constants/reg\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nconst EditPhyCluster = (props: { dispatch: any; cb: Function; params: IOpPhysicsClusterDetail }) => {\n  let { password, proxyAddress, kibanaAddress, cerebroAddress } = props.params;\n  const checkText = (value) => {\n    const values = value?.split(\",\").filter((ele: string) => ele !== \"\") || [];\n    const IP_TIP = \"请输入IP:端口号，例如：127.1.1.1:8888。多个IP用逗号分割\";\n\n    let flat = false;\n    let flatPost = false;\n    let flatLength = false;\n    let flatIp = false;\n    const ipArr = [];\n\n    values.forEach((element) => {\n      if (element.indexOf(\":\") === -1) {\n        flat = true;\n      } else {\n        const isPostArr = element.split(\":\");\n        ipArr.push(isPostArr[0]);\n        if (!new RegExp(regIp).test(isPostArr[0])) {\n          flatIp = true;\n        }\n        if ((!isPostArr[1] && flatIp === false) || !new RegExp(regPort).test(isPostArr[1])) {\n          flatPost = true;\n        }\n        if (isPostArr[1] && flatIp === false) {\n          if (+isPostArr[1] > 25535) {\n            flatLength = true;\n          }\n        }\n      }\n    });\n    // 多个相同 ip\n    if (new Set(ipArr).size != ipArr.length) {\n      return `${IP_TIP}且 ip 不能相同`;\n    } else if (flat || flatIp || flatPost) {\n      // 格式错误，ip不符合规范, 没有:号, :号后面没有端口\n      return IP_TIP;\n    } else if (flatLength) {\n      // 格式错误，:号端口格式不正确, 多个请换行。\n      return `${IP_TIP}，输入端口号超最大值25535`;\n    }\n  };\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"name\",\n        label: \"集群名称\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.cluster} />,\n      },\n      {\n        key: \"usename\",\n        label: \"账户名\",\n        attrs: {\n          placeholder: \"请输入账户名\",\n        },\n        invisible: !password,\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: string) => {\n              if (value.length > 32 || value.includes(\"：\") || value.includes(\":\") || !value) {\n                return Promise.reject(\"请填写账户名，1-32位字符，不支持：号\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"password\",\n        label: \"密码\",\n        invisible: !password,\n        attrs: {\n          placeholder: \"请输入密码\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: string) => {\n              if (value.length < 6 || value.length > 32 || /[\\u4e00-\\u9fa5\\:：.]/.test(value)) {\n                return Promise.reject(\"请填写正确密码，6-32位字符，不支持.、:、中文\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"proxyAddress\",\n        label: \"代理地址\",\n        type: FormItemType.input,\n        invisible: !proxyAddress,\n        attrs: {\n          placeholder: \"请输入代理地址\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: (_, value) => {\n              if (value?.length > 128 || !value) return Promise.reject(\"请输入代理地址，1-128位字符\");\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"httpAddress\",\n        label: \"读地址\",\n        type: FormItemType.input,\n        invisible: proxyAddress,\n        attrs: {\n          placeholder: \"请输入\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: string) => {\n              if (!value) return Promise.reject(\"请输入读地址\");\n              let errormsg = checkText(value);\n              if (errormsg) {\n                return Promise.reject(errormsg);\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"httpWriteAddress\",\n        label: \"写地址\",\n        type: FormItemType.input,\n        invisible: proxyAddress,\n        attrs: { placeholder: \"请输入\" },\n        rules: [\n          {\n            required: true,\n            validator: async (rule: any, value: string) => {\n              if (!value) return Promise.reject(\"请输入写地址\");\n              let errormsg = checkText(value);\n              if (errormsg) {\n                return Promise.reject(errormsg);\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"kibanaAddress\",\n        label: \"kibana外链地址\",\n        attrs: {\n          placeholder: \"请输入kibana外链地址\",\n        },\n        // invisible: !kibanaAddress,\n        isCustomStyle: true,\n        CustomStyle: { marginTop: 0 },\n        rules: [\n          {\n            validator: async (rule: any, value: string) => {\n              if (!value || (value && value.length <= 512 && /[\\u4e00-\\u9fa5-_、/.a-zA-Z0-9_]{1,512}$/.test(value))) {\n                return Promise.resolve();\n              }\n              return Promise.reject(\"清输入正确的kibana外链地址，支持中英文、数字、-、_、、/、.，0-512位字符\");\n            },\n          },\n        ],\n      },\n      {\n        key: \"cerebroAddress\",\n        label: \"cerebro外链地址\",\n        // invisible: !cerebroAddress,\n        attrs: {\n          placeholder: \"请输入cerebro外链地址\",\n        },\n        isCustomStyle: true,\n        CustomStyle: { marginTop: 0 },\n        rules: [\n          {\n            validator: async (rule: any, value: string) => {\n              if (!value || (value && value.length <= 512 && /[\\u4e00-\\u9fa5-_、/.a-zA-Z0-9_]{1,512}$/.test(value))) {\n                return Promise.resolve();\n              }\n              return Promise.reject(\"清输入正确的cerebro外链地址，支持中英文、数字、-、_、、/、.，0-512位字符\");\n            },\n          },\n        ],\n      },\n      {\n        key: \"desc\",\n        type: FormItemType.textArea,\n        label: \"集群描述\",\n        rules: [\n          {\n            validator: (rule: any, value: string) => {\n              if (!value || value?.trim().length < 100) {\n                return Promise.resolve();\n              } else {\n                return Promise.reject(\"请输入0-100字描述信息\");\n              }\n            },\n          },\n        ],\n        attrs: {\n          placeholder: \"请输入0-100字集群描述\",\n        },\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"编辑集群\",\n    formData: props.params || {},\n    isWaitting: true,\n    width: 660,\n    needSuccessMessage: false,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      const { desc, cerebroAddress, httpAddress, httpWriteAddress, kibanaAddress, proxyAddress } = result;\n      const req = {\n        id: props.params?.id,\n        desc,\n        cerebroAddress,\n        httpAddress,\n        httpWriteAddress,\n        kibanaAddress,\n        proxyAddress,\n      } as any;\n      return improveOpEditCluster(req)\n        .then(() => {\n          XNotification({ type: \"success\", message: \"编辑成功\" });\n        })\n        .finally(() => {\n          props.cb && props.cb();\n          props.dispatch(actions.setModalId(\"\"));\n        });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper visible={true} {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(EditPhyCluster);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/edit-config.tsx",
    "content": "import * as React from 'react';\nimport { XFormWrapper } from 'component/x-form-wrapper';\nimport { connect } from \"react-redux\";\nimport * as actions from 'actions';\nimport { FormItemType, IFormItem } from 'component/x-form';\nimport { AppState, UserState } from 'store/type';\nimport { IPhyConfig } from 'typesPath/cluster/physics-type';\nimport { IWorkOrder } from 'typesPath/params-types';\nimport Url from \"lib/url-parser\";\nimport { submitWorkOrder } from 'api/common-api';\nimport { getPhysicClusterRoles } from 'api/cluster-api';\n\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst EditConfig = (props: { dispatch: any, cb: Function, app: AppState, user: UserState, params: IPhyConfig }) => {\n  const [clusterRolesList, setClusterRolesList] = React.useState([]);\n\n  React.useEffect(() => {\n    getPhysicClusterRoles(Number(Url().search.physicsClusterId)).then((res) => {\n      res =\n        res?.map((ele, index) => {\n          return {\n            ...ele,\n            label: ele.roleClusterName,\n            value: ele.roleClusterName,\n            key: index,\n          };\n        }) || [];\n      setClusterRolesList(res);\n    });\n  }, [])\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: 'configData',\n        type: FormItemType.textArea,\n        label: '配置内容',\n        rules: [{\n          required: true,\n          validator: (rule: any, value: string) => {\n            if (props.params?.configData === value) {\n              return Promise.reject('不可与原来一致。');\n            }\n            return Promise.resolve();\n          },\n        }]\n      }, {\n        key: 'description',\n        type: FormItemType.textArea,\n        label: '申请原因',\n        rules: [{\n          required: true,\n          validator: (rule: any, value: string) => {\n            if (!value || value?.trim().length > 100) {\n              return Promise.reject('请输入1-100字申请原因');\n            } else {\n              return Promise.resolve();\n            }\n          },\n        }],\n        attrs: {\n          placeholder: '请输入1-100字申请原因',\n        },\n      }] as IFormItem[],\n    visible: true,\n    title: '编辑配置内容',\n    formData: props.params || {},\n    isWaitting: true,\n    width: 660,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(''));\n    },\n    onSubmit: (result: any) => {\n      const url = Url();\n      const esConfigs = { ...props.params };\n      esConfigs.configData = result.configData;\n      const roleOrder = [];\n      clusterRolesList.forEach((item) => {\n        if (item?.roleClusterName.indexOf(props.params?.enginName) > -1) {\n          roleOrder.push(item.roleClusterName);\n        }\n      });\n      const workOrderParams: IWorkOrder = {\n        contentObj: {\n          phyClusterId: Number(url.search.physicsClusterId),\n          phyClusterName: url.search.physicsCluster,\n          roleOrder: roleOrder,\n          type: Number(url.search.type),\n          actionType: props.params?.enginName ? 2 : 1,\n          newEsConfigs: [esConfigs],\n          originalConfigs: props.params.enginName ? [props.params] : [],\n        },\n        submitorProjectId: props.app.appInfo()?.id,\n        submitor: props.user.getName('userName'),\n        description: result.description || \"\",\n        type: \"clusterOpConfigRestart\",\n      };\n      return submitWorkOrder(workOrderParams).finally(() => {\n        props.dispatch(actions.setModalId(\"\"));\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper\n        visible={true}\n        {...xFormModalConfig}\n      />\n    </>\n  )\n};\n\nexport default connect(mapStateToProps)(EditConfig);\n\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/edit-gateway-url.tsx",
    "content": "import React, { useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { AppState, UserState } from \"store/type\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { bindGateway } from \"api/cluster-api\";\nimport { regIp, regPort } from \"constants/reg\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst EditGatewayUrl = (props: { dispatch: any; cb: Function; app: AppState; user: UserState; params: any }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"gatewayUrl\",\n        label: \"Gateway地址\",\n        type: FormItemType.input,\n        attrs: {\n          placeholder: \"请输入Gateway地址\",\n        },\n        isCustomStyle: true,\n        CustomStyle: { margin: 0 },\n        rules: [\n          {\n            required: true,\n            validator: (_, value: string) => {\n              if (!value) {\n                return Promise.reject(\"请输入Gateway地址 ，不同地址用逗号分隔。\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"编辑Gateway地址\",\n    formData: { gatewayUrl: props.params.gatewayUrl },\n    isWaitting: true,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: async (result: any) => {\n      let { gatewayUrl } = result;\n      while (gatewayUrl.includes(\"，\")) {\n        gatewayUrl = gatewayUrl.replace(\"，\", \",\");\n      }\n      let params = {\n        id: props.params.id,\n        gatewayUrl,\n      };\n      await bindGateway(params);\n      props.dispatch(actions.setModalId(\"\"));\n      props.cb();\n    },\n    width: 480,\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(EditGatewayUrl);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/edit-plugin-desc.tsx",
    "content": "import React, { useState } from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { useSelector, shallowEqual, useDispatch } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { XNotification } from \"component/x-notification\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { editPlug } from \"api/plug-api\";\n\nconst EditPluginDesc = () => {\n  const dispatch = useDispatch();\n  const { params, cb } = useSelector((state) => ({ params: (state as any).modal.params, cb: (state as any).modal.cb }), shallowEqual);\n  const { record } = params;\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"desc\",\n        type: FormItemType.textArea,\n        label: \"插件描述\",\n        formAttrs: {\n          style: { margin: 0 },\n        },\n        attrs: {\n          placeholder: \"请输入插件描述，0-100字\",\n        },\n        rules: [\n          {\n            validator: (rule: any, value: string) => {\n              if (record.desc === value) {\n                return Promise.reject(\"请编辑描述，不可与原本一致。\");\n              }\n              if (!value || value?.trim().length < 100) {\n                return Promise.resolve();\n              } else {\n                return Promise.reject(\"请输入0-100字描述信息\");\n              }\n            },\n          },\n        ],\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"编辑插件描述\",\n    formData:\n      {\n        desc: record.desc,\n      } || {},\n    isWaitting: true,\n    width: 660,\n    needSuccessMessage: false,\n    onCancel: () => {\n      dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      const { desc } = result;\n      return editPlug(record.id, desc)\n        .then(() => {\n          XNotification({ type: \"success\", message: \"编辑成功\" });\n        })\n        .finally(() => {\n          cb && cb();\n          dispatch(actions.setModalId(\"\"));\n        });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper visible={true} {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default EditPluginDesc;\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/expand-shrink-cluster.tsx",
    "content": "import React, { useEffect, useRef, useState } from \"react\";\nimport { Drawer, Button } from \"antd\";\nimport { connect } from \"react-redux\";\nimport { FormItemType, IFormItem, XForm as XFormComponent } from \"component/x-form\";\nimport { ExpandShrinkList } from \"container/custom-form\";\nimport \"./index.less\";\nimport * as actions from \"actions\";\nimport { CLUSTER_INDECREASE_TYPE } from \"constants/status-map\";\nimport { clusterExpand, clusterShrink, getNodeSpecification } from \"api/cluster-api\";\nimport { showSubmitTaskSuccessModal } from \"container/custom-component\";\nimport { Dispatch } from \"redux\";\nimport { XNotification } from \"component/x-notification\";\n\nconst labelList = [\n  {\n    label: \"集群名称：\",\n    key: \"cluster\",\n  },\n  {\n    label: \"现有ES版本：\",\n    key: \"esVersion\",\n  },\n];\n\ninterface IExpandShrinkParams {\n  title: string;\n  id: number;\n  businessKey: string;\n  taskType: number;\n  status: string;\n  expandData: string;\n}\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst ExpandShrinkCluster = (props) => {\n  const [clientNodes, setClientNodes] = useState([]);\n  const [dataNodes, setDataNodes] = useState([]);\n  const [confirmLoading, setConfirmLoading] = useState(false);\n  const [options, setOptions] = useState([]);\n  const [formMap, setFormMap] = useState([] as IFormItem[]);\n  const [isExpand, setIsExpand] = useState(false);\n\n  const formRef = useRef(null);\n\n  useEffect(() => {\n    _getNodeSpecification();\n  }, []);\n\n  useEffect(() => {\n    getFormMap();\n  }, [isExpand]);\n\n  const _getNodeSpecification = async () => {\n    let list = await getNodeSpecification();\n    let options = (list || []).map((item) => ({ label: item, value: item }));\n    setOptions(options);\n  };\n\n  const filterExpandData = (result) => {\n    let res = [];\n    let keys = Object.keys(result);\n    let filterKeys = keys.filter((item) => result[item] && (item.startsWith(\"ip\") || item.startsWith(\"machineSpec\")));\n    if (!filterKeys.length) {\n      XNotification({ type: \"error\", message: \"请对数据进行更改后再提交\" });\n      setConfirmLoading(false);\n      return;\n    }\n    filterKeys.forEach((item) => {\n      let arr = item.split(\"&\");\n      let data = {\n        id: arr[2],\n        role: arr[1],\n      };\n      arr[0] === \"ip\" ? (data[\"hostname\"] = result[item]) : (data[\"machineSpec\"] = result[item]);\n      let index = -1;\n      for (let i = 0; i < res.length; i++) {\n        if (res[i].id === data.id) {\n          res[i] = { ...res[i], ...data };\n          index = i;\n          break;\n        }\n      }\n      index === -1 && res.push(data);\n    });\n    for (let i = 0; i < res.length; i++) {\n      if (!res[i].hostname || !res[i].machineSpec) {\n        XNotification({ type: \"error\", message: \"请填写完整\" });\n        setConfirmLoading(false);\n        return;\n      }\n      for (let j = i + 1; j < res.length; j++) {\n        if (res[i].hostname === res[j].hostname && res[i].role === res[j].role) {\n          XNotification({ type: \"error\", message: \"存在重复IP，请修改后再提交\" });\n          setConfirmLoading(false);\n          return;\n        }\n      }\n    }\n    return res;\n  };\n\n  const handleOk = () => {\n    setConfirmLoading(true);\n    formRef.current!.validateFields().then(async (result) => {\n      const { id, cluster, esClusterRoleVOS } = props.params;\n      let clusterRoleHosts = [];\n      if (result?.type === 2) {\n        // 扩容\n        clusterRoleHosts = filterExpandData(result);\n        if (!clusterRoleHosts) {\n          setConfirmLoading(false);\n          return;\n        }\n        clusterRoleHosts.forEach((item) => {\n          delete item.id;\n        });\n      } else {\n        // 缩容\n        if (!clientNodes.length && !dataNodes.length) {\n          XNotification({ type: \"error\", message: \"请对数据进行更改后再提交\" });\n          setConfirmLoading(false);\n          return;\n        }\n        dataNodes.forEach((item) => {\n          clusterRoleHosts.push({\n            role: \"datanode\",\n            hostname: item.hostname,\n            machineSpec: item.machineSpec,\n          });\n        });\n        clientNodes.forEach((item) => {\n          clusterRoleHosts.push({\n            role: \"clientnode\",\n            hostname: item.hostname,\n            machineSpec: item.machineSpec,\n          });\n        });\n      }\n\n      let filterNode = (esClusterRoleVOS || []).filter((item) => item.role !== \"masternode\");\n      let node = [];\n      filterNode.forEach((item) => {\n        let list = item.esClusterRoleHostVO.map((ele) => ({ ...ele, role: item.role }));\n        node = [...node, ...list];\n      });\n      let originClusterRoleHosts = node.map((item) => {\n        return { role: item.role, hostname: item.hostname, machineSpec: item.machineSpec };\n      });\n\n      const contentObj = {\n        type: 4,\n        operationType: result?.type,\n        phyClusterId: id,\n        phyClusterName: cluster,\n        clusterRoleHosts,\n        originClusterRoleHosts,\n      };\n      let expandData = JSON.stringify(contentObj);\n      let ret = {} as IExpandShrinkParams;\n      try {\n        if (result?.type === 2) {\n          ret = await clusterExpand({ expandData });\n        } else {\n          ret = await clusterShrink({ expandData });\n        }\n        props.setModalId(\"\");\n        showSubmitTaskSuccessModal(ret, props.params?.history);\n      } finally {\n        setConfirmLoading(false);\n      }\n    });\n  };\n\n  const handleCancel = () => {\n    props.setModalId(\"\");\n  };\n\n  const getFormMap = () => {\n    const { esClusterRoleVOS = [] } = props.params;\n    const expandShrinkArr = [\n      {\n        key: \"type\",\n        label: \"扩缩容\",\n        type: FormItemType.select,\n        defaultValue: 3,\n        rules: [\n          {\n            required: true,\n            validator: (rule: any, value: any) => {\n              if (value === 2) {\n                setIsExpand(true);\n              } else {\n                setIsExpand(false);\n              }\n              setClientNodes([]);\n              setDataNodes([]);\n              return Promise.resolve();\n            },\n          },\n        ],\n        options: CLUSTER_INDECREASE_TYPE,\n        attrs: {\n          style: { width: \"50%\" },\n        },\n      },\n      {\n        key: \"masternode\",\n        label: \"master列表\",\n        type: FormItemType.custom,\n        customFormItem: <ExpandShrinkList type=\"masternode\" data={esClusterRoleVOS} isExpand={isExpand} />,\n      },\n      {\n        key: \"clientnode\",\n        label: \"client列表\",\n        type: FormItemType.custom,\n        customFormItem: (\n          <ExpandShrinkList\n            type=\"clientnode\"\n            form={formRef?.current}\n            data={esClusterRoleVOS}\n            isExpand={isExpand}\n            options={options}\n            clientNodes={clientNodes}\n            onShrink={(val) => {\n              setClientNodes(val);\n            }}\n          />\n        ),\n      },\n      {\n        key: \"datanode\",\n        label: \"data列表\",\n        type: FormItemType.custom,\n        customFormItem: (\n          <ExpandShrinkList\n            type=\"datanode\"\n            form={formRef?.current}\n            data={esClusterRoleVOS}\n            isExpand={isExpand}\n            options={options}\n            dataNodes={dataNodes}\n            onShrink={(val) => {\n              setDataNodes(val);\n            }}\n          />\n        ),\n      },\n    ] as IFormItem[];\n    setFormMap(expandShrinkArr);\n  };\n\n  return (\n    <>\n      <Drawer\n        closable={true}\n        className=\"expand-shrink\"\n        visible={true}\n        title=\"集群扩缩容\"\n        width={660}\n        destroyOnClose={true}\n        onClose={handleCancel}\n        maskClosable={false}\n        footer={\n          <div className=\"footer-btn\">\n            <Button style={{ marginRight: 10 }} loading={confirmLoading} type=\"primary\" onClick={handleOk}>\n              确定\n            </Button>\n            <Button onClick={handleCancel}>取消</Button>\n          </div>\n        }\n      >\n        <div className=\"upgrade-cluster-box\">\n          {labelList.map((item, index) => (\n            <div key={item.label + index} className=\"upgrade-cluster-box-item\">\n              <span className=\"label\">{item.label}</span>\n              <span>{props.params[item.key]}</span>\n            </div>\n          ))}\n        </div>\n        <div>\n          <XFormComponent formData={{}} formMap={formMap} wrappedComponentRef={formRef} layout={\"vertical\"} />\n        </div>\n      </Drawer>\n    </>\n  );\n};\n\nexport default connect(mapStateToProps, mapDispatchToProps)(ExpandShrinkCluster);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/index.less",
    "content": "@import \"../../../styles/base.less\";\n.create-region-box {\n  width: 688px;\n  background: #ffffff;\n  box-shadow: 0 0 12px 0 rgba(31, 50, 82, 0.18);\n  margin-top: 20px;\n  &-transfer {\n    padding: 19px 19px 19px 19px;\n  }\n  .ant-transfer-list {\n    width: 40%;\n  }\n}\n.create-region-table-box {\n  margin-top: 10px;\n  width: 688px;\n  background: #ffffff;\n  box-shadow: 0 0 12px 0 rgba(31, 50, 82, 0.18);\n  margin-top: 20px;\n}\n.relation-region-box {\n  width: 688px;\n  height: 99px;\n  background: #ffffff;\n  box-shadow: 0 0 12px 0 rgba(31, 50, 82, 0.12);\n  &-form {\n    display: flex;\n    justify-content: space-around;\n    height: 100%;\n    align-items: center;\n    &-item {\n      width: 42%;\n      margin-bottom: 0;\n    }\n  }\n}\n\n.upgrade-cluster-box {\n  display: flex;\n  flex-wrap: wrap;\n  flex-direction: column;\n  margin-top: 16px;\n  margin-bottom: -10px;\n  &-item {\n    width: 50%;\n    margin-bottom: 10px;\n    .label {\n      color: #697687;\n      font-size: 12px;\n      font-weight: 500;\n    }\n  }\n}\n\n.config-dividing-line {\n  height: 1px;\n  border: 1px solid #dcdfe6;\n  margin-top: 20px;\n}\n.nodelist {\n  margin-bottom: 32px;\n}\n.defined {\n  margin-top: 32px;\n}\n.region-title {\n  font-family: PingFangSC-Medium;\n  color: #1d2330;\n  font-weight: 500;\n  width: 1075px;\n  height: 40px;\n  background: #f9f9fa;\n  display: inline-block;\n  position: relative;\n  left: -25px;\n  margin-bottom: 23px;\n  padding-left: 23px;\n  line-height: 40px;\n  overflow: hidden;\n}\n.define-region {\n  margin: 0 0 32px 0;\n  display: flex;\n  .cold-region {\n    flex: 1;\n    min-width: 270px;\n    &-title {\n      font-family: PingFangSC-Medium;\n      font-size: 12px;\n      color: #303a51;\n      font-weight: 500;\n      margin-bottom: 12px;\n    }\n  }\n\n  .region-input {\n    width: 580px;\n    .region-name-title {\n      font-family: PingFangSC-Medium;\n      font-size: 12px;\n      color: #303a51;\n      font-weight: 500;\n      width: 70px;\n      margin-bottom: 8px;\n    }\n    .region-name-input {\n      width: 350px;\n      height: 30px;\n      margin-right: 10px;\n    }\n    .region-name-input-error:focus {\n      border-color: #ff4d4f;\n      box-shadow: 0 0 0 2px rgb(255 20 51 / 20%);\n    }\n    .region-name-add {\n      height: 30px;\n      margin-right: 10px;\n    }\n    .region-name-error {\n      color: red;\n      position: relative;\n    }\n  }\n}\n\n.cold-region-tag {\n  height: 26px;\n  line-height: 26px;\n  .tag-bule {\n    margin: 0 0 0 5px;\n    padding: 0;\n    width: 54px;\n    background: rgba(20, 115, 255, 0.1);\n    border-radius: 4px;\n    border: none;\n    line-height: 24px;\n    text-align: center;\n    color: #1473ff;\n    cursor: default;\n    &:hover {\n      border: 1px solid #1473ff;\n    }\n  }\n}\n\n.access-cluster-senior {\n  .ant-form-horizontal .ant-form-item-control {\n    flex: auto;\n  }\n  .down {\n    transform: rotate(90deg);\n    margin-left: 5px;\n  }\n  .up {\n    transform: rotate(-90deg);\n  }\n  .ant-btn > .anticon + span,\n  .ant-btn > span + .anticon {\n    margin-left: 5px;\n  }\n  .cluster-label {\n    width: 100px;\n    height: 18px;\n  }\n  .ant-col {\n    max-width: 100%;\n  }\n  .ant-col-12 {\n    max-width: 50%;\n  }\n  .iconinfo {\n    font-size: 14px;\n    margin-left: 5px;\n    color: rgb(140, 140, 140);\n    position: relative;\n    bottom: 2px;\n  }\n  .ant-form-item-explain-error {\n    width: 220px;\n  }\n  button {\n    padding: 0;\n    line-height: 18px;\n    height: 18px;\n  }\n}\n\n.expand-shrink {\n  .ant-form-item-control-input {\n    min-height: 12px;\n  }\n  .ant-form-item-label {\n    font-weight: 500;\n  }\n}\n\n.upgrade-cluster-form {\n  .ant-form-item-label {\n    font-weight: 500;\n  }\n}\n\n.regin-contain {\n  .ant-drawer-header > .ant-drawer-title {\n    color: rgb(0, 0, 0);\n  }\n}\n\n.new-config-content {\n  margin-top: 16px;\n  .ant-form-item {\n    margin-bottom: 16px;\n    .ant-input {\n      margin-bottom: 0;\n    }\n  }\n  .ant-form-item-label {\n    font-weight: 500;\n  }\n}\n\n.base-info-form {\n  .ant-form-item-label {\n    font-weight: 500;\n  }\n}\n\n.add-new-config {\n  width: 122px;\n  height: 30px;\n  margin: 4px 0 16px 0;\n}\n\n.import-rule {\n  .ant-form-item-control-input {\n    min-height: 20px;\n  }\n  .ant-radio-inner {\n    width: 12px;\n    height: 12px;\n    &::after {\n      top: 1.5px;\n      left: 1.5px;\n      width: 7px;\n      height: 7px;\n    }\n  }\n}\n\n.access-senior,\n.apply-senior {\n  margin-top: -4px !important;\n  .ant-form-item-control-input {\n    min-height: 32px;\n  }\n}\n\n.senior-form {\n  margin-top: -4px;\n}\n\n.access-add-role {\n  .ant-form-item-explain {\n    min-height: 0;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/install.tsx",
    "content": "import React from \"react\";\nimport { Modal, Form, Input, message } from \"antd\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { InfoCircleOutlined } from \"@ant-design/icons\";\nimport { submitWorkOrder } from \"api/common-api\";\nimport store from \"store\";\nimport \"./deleteStyle.less\";\n\nconst appInfo = {\n  app: store.getState().app,\n  user: store.getState().user,\n};\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const InstallPlugin = connect(mapStateToProps)((props: { dispatch: any; params: any; cb: any }) => {\n  const { params, dispatch, cb } = props;\n  const [form] = Form.useForm();\n  return (\n    <>\n      <Modal\n        visible={true}\n        title={\"安装插件\"}\n        width={480}\n        onCancel={() => {\n          dispatch(actions.setModalId(\"\"));\n        }}\n        onOk={async () => {\n          const values = await form.validateFields();\n          if (values && values?.desc) {\n            const contentObj = {\n              operationType: 3,\n              logicClusterId: params.id,\n              logicClusterName: params.name,\n              plugIds: params.id,\n              plugName: params.name,\n              pluginId: params.id,\n              pluginFileName: params.name,\n              url: params.url,\n              plugDesc: params.plugDesc,\n              type: \"6\",\n            };\n            const param = {\n              contentObj,\n              submitorProjectId: appInfo.app.appInfo()?.id,\n              submitor: appInfo.user.getName(\"userName\"),\n              description: values?.desc,\n              type: \"clusterOpPluginRestart\",\n            };\n            return submitWorkOrder(param, () => {\n              dispatch(actions.setModalId(\"\"));\n              cb();\n            });\n          }\n        }}\n      >\n        <div>\n          <div className=\"delete-modal-content\">\n            <div className=\"delete-modal-content-left\">\n              <InfoCircleOutlined className=\"delete-modal-content-left-icon\" />\n            </div>\n            <div className=\"delete-modal-content-right\">\n              <p className=\"delete-modal-content-right-p1\">是否确定安装该{params.name}插件？</p>\n              <p className=\"delete-modal-content-right-p2\">插件卸载、安装需要重启集群，点击确认后，将自动提交工单。</p>\n            </div>\n          </div>\n\n          <div style={{ marginTop: 10 }}>\n            <Form form={form} layout=\"vertical\">\n              <Form.Item\n                label=\"申请理由\"\n                style={{ marginBottom: 0 }}\n                rules={[\n                  {\n                    required: true,\n                    validator: (rule: any, value: string) => {\n                      if (!value || value?.trim().length > 100) {\n                        return Promise.reject(\"请输入1-100字申请原因\");\n                      } else {\n                        return Promise.resolve();\n                      }\n                    },\n                  },\n                ]}\n                name={\"desc\"}\n              >\n                <Input.TextArea allowClear rows={4} placeholder=\"请输入申请原因1-100个字符\" />\n              </Form.Item>\n            </Form>\n          </div>\n        </div>\n      </Modal>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/new-config.tsx",
    "content": "import * as React from \"react\";\nimport { Modal, Form, Row, Col, Button, Select, Tooltip, Drawer } from \"antd\";\nimport \"./index.less\";\nimport { IFormItem, FormItemType, renderFormItem, handleFormItem } from \"component/x-form\";\nimport Url from \"lib/url-parser\";\nimport { connect } from \"react-redux\";\nimport { getClusterTemplateCentent } from \"api/op-cluster-config-api\";\nimport * as actions from \"actions\";\nimport { StepSelect } from \"container/custom-form/step-select\";\nimport { PlusOutlined } from \"@ant-design/icons\";\nimport { getPhysicClusterRoles } from \"api/cluster-api\";\nimport { clusterConfigAdd } from \"api/cluster-api\";\nimport { showSubmitTaskSuccessModal } from \"container/custom-component\";\n\nconst mapStateToProps = (state) => ({\n  phyClusterConfig: state.configInfo,\n  app: state.app,\n  user: state.user,\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\nconst connects: Function = connect;\n@connects(mapStateToProps)\nexport class NewConfigModal extends React.Component<any> {\n  public state = {\n    addFormArr: [0],\n    roleList: [] as string[],\n    configRoleList: [],\n    clusterOpRolesList: [],\n    confirmLoading: false,\n  };\n\n  public physicsClusterId: number;\n  public physicsCluster: string;\n  public type: number;\n\n  private $formRef: any[] = [];\n  private $TwoFormRef: any = null;\n\n  public componentDidMount() {\n    const url = Url();\n    this.physicsClusterId = Number(this.props.params.id);\n    this.type = Number(url.search.type);\n    this.physicsCluster = url.search.physicsCluster || this.props.params.cluster;\n    if (this.physicsClusterId) {\n      // 原节点角色列表接口，缺少判断字段，与下面接口数据冲突\n      // getConfigRole(this.physicsClusterId).then((res) => {\n      //   res = res?.map((item: string) => {\n      //     return {\n      //       label: item,\n      //       value: item,\n      //     };\n      //   });\n      //   this.setState({\n      //     configRoleList: res,\n      //   });\n      // });\n      getPhysicClusterRoles(this.physicsClusterId).then((res) => {\n        res =\n          res?.map((ele, index) => {\n            return {\n              ...ele,\n              label: ele.roleClusterName,\n              value: ele.roleClusterName,\n              key: index,\n            };\n          }) || [];\n        const configRoleList = res\n          ?.map((ele, index) => ({\n            ...ele,\n            label: ele.role,\n            value: ele.role,\n          }))\n          .filter((item) => item.podNumber);\n        // 排序master>client>data\n        let sortConfigRoleList = [];\n        if (configRoleList.filter((item) => item.role === \"masternode\").length) {\n          sortConfigRoleList.push(...configRoleList.filter((item) => item.role === \"masternode\"));\n        }\n        if (configRoleList.filter((item) => item.role === \"clientnode\").length) {\n          sortConfigRoleList.push(...configRoleList.filter((item) => item.role === \"clientnode\"));\n        }\n        if (configRoleList.filter((item) => item.role === \"datanode\").length) {\n          sortConfigRoleList.push(...configRoleList.filter((item) => item.role === \"datanode\"));\n        }\n        this.props.dispatch(actions.setPhyClusterConfigRoles(res));\n        this.setState({\n          clusterOpRolesList: res,\n          configRoleList: sortConfigRoleList,\n          //configRoleList: configRoleList,\n        });\n      });\n    }\n  }\n\n  public handleCancel = () => {\n    this.resetForm();\n  };\n\n  public handleSubmit = () => {\n    this.setState({ confirmLoading: true });\n    const esConfigs = [] as any[];\n    this.$formRef.map((item) => {\n      item\n        .validateFields()\n        .then(async (result) => {\n          const esConfigItem = {\n            clusterId: this.physicsClusterId,\n            enginName: result.enginName,\n            typeName: result.typeName,\n            configData: result.configData,\n            desc: result.desc,\n          };\n          esConfigs.push(esConfigItem);\n          await this.twoFormRefHandleSubmit(esConfigs);\n          this.setState({ confirmLoading: false });\n        })\n        .catch((errs) => {\n          this.setState({ confirmLoading: false });\n          return;\n        });\n    });\n  };\n\n  public twoFormRefHandleSubmit = async (esConfigs?: any) => {\n    if (esConfigs) {\n      await this.$TwoFormRef.validateFields().then(async (resultR) => {\n        const roleOrder = [] as string[];\n        const { phyClusterConfig, params } = this.props;\n        phyClusterConfig?.clusterRolesList.forEach((item) => {\n          if (item.roleClusterName.indexOf(params?.enginName) > -1) {\n            roleOrder.push(item.roleClusterName);\n          }\n        });\n        let expandData = {\n          phyClusterId: this.physicsClusterId,\n          phyClusterName: this.physicsCluster,\n          roleOrder: params?.enginName ? roleOrder : resultR.roleOrder,\n          type: this.type,\n          actionType: params?.enginName ? 2 : 1,\n          newEsConfigs: esConfigs,\n          originalConfigs: params?.enginName ? [params] : [],\n        } as any;\n        expandData = JSON.stringify(expandData);\n        let ret = await clusterConfigAdd({ expandData });\n        this.props.dispatch(actions.setDrawerId(\"\"));\n        showSubmitTaskSuccessModal(ret, this.props.params?.history);\n      });\n    } else {\n      await this.$TwoFormRef.validateFields().then(async (resultR) => {\n        const roleOrder = [] as string[];\n        const { phyClusterConfig, params } = this.props;\n        phyClusterConfig?.clusterRolesList.forEach((item) => {\n          if (item.roleClusterName.indexOf(params?.enginName) > -1) {\n            roleOrder.push(item.roleClusterName);\n          }\n        });\n        let expandData = {\n          phyClusterId: this.physicsClusterId,\n          phyClusterName: this.physicsCluster,\n          roleOrder,\n          type: this.type,\n          actionType: 3,\n          newEsConfigs: [params],\n          originalConfigs: [params],\n        } as any;\n        expandData = JSON.stringify(expandData);\n        let ret = await clusterConfigAdd({ expandData });\n        this.props.dispatch(actions.setDrawerId(\"\"));\n        showSubmitTaskSuccessModal(ret, this.props.params?.history);\n      });\n    }\n  };\n\n  public resetForm = (resetFields?: string[]) => {\n    this.$formRef.map((item) => {\n      item.resetFields(resetFields || \"\");\n    });\n    this.props.dispatch(actions.setDrawerId(\"\"));\n  };\n\n  public bindForm = (formRef: any, index: number) => {\n    if (!formRef) return;\n\n    if (this.$formRef.length === index) {\n      this.$formRef.push(formRef);\n    } else {\n      this.$formRef[index] = formRef;\n    }\n  };\n\n  public resetBindForm = (formRef: any) => {\n    if (!formRef) return;\n\n    this.$TwoFormRef = formRef;\n  };\n\n  public bindNodeRole = () => {\n    const configArr = this.props.phyClusterConfig.typeNameList || [];\n    let arr = [] as string[];\n    configArr.map((itemP) => {\n      this.state.clusterOpRolesList.map((item) => {\n        if (item.roleClusterName.indexOf(itemP.role) > -1) {\n          arr.push(item.roleClusterName);\n        }\n      });\n    });\n    arr = [...new Set(arr)];\n    const setArr = Array.apply(\"\", { length: arr.length });\n    arr.map((item) => {\n      if (item.indexOf(\"master\") > -1) {\n        setArr[0] = item;\n      } else if (item.indexOf(\"clien\") > -1) {\n        if (arr.length === 1) setArr[0] = item;\n        if (arr.length > 1) setArr[1] = item;\n      } else if (item.indexOf(\"data\") > -1) {\n        setArr[arr.length - 1] = item;\n      }\n    });\n    this.setSeptPhysicClusterRoles(setArr);\n    this.$TwoFormRef.setFieldsValue({\n      roleOrder: setArr,\n    });\n  };\n\n  public setSeptPhysicClusterRoles(data: string[]) {\n    const arr = this.props.phyClusterConfig?.clusterRolesList.map((item) => {\n      item.label = item.value;\n      return item;\n    });\n    const arrStr = arr.map((item) => {\n      return item.value;\n    });\n    let num = null;\n    data.forEach((item, index) => {\n      num = arrStr.indexOf(item);\n      if (num !== -1) {\n        arr[num].label = arr[num].label + \" \" + `(步骤${index + 1})`;\n      }\n    });\n    this.props.dispatch(actions.setPhyClusterConfigRoles(arr));\n  }\n\n  public computeTypeNameList(role: string, index: number) {\n    const { typeNameList, configList } = this.props.phyClusterConfig;\n    if (typeNameList[index]?.role === role) return;\n    const allItem = [\n      {\n        label: \"elasticsearch.yml\",\n        value: \"elasticsearch.yml\",\n      },\n      {\n        label: \"jvm.options\",\n        value: \"jvm.options\",\n      },\n      {\n        label: \"filebeat.yml\",\n        value: \"filebeat.yml\",\n      },\n    ];\n    const arr = [] as string[];\n    configList.forEach((i) => {\n      if (i.enginName === role) {\n        arr.push(i.typeName);\n      }\n    });\n\n    typeNameList?.forEach((i) => {\n      if (i.role === role) {\n        arr.push(i.typeName);\n      }\n    });\n\n    const arrCp = allItem.map((item) => {\n      if (arr.join(\"\").indexOf(item.label) > -1) {\n        return { ...item, disabled: true };\n      } else {\n        return item;\n      }\n    });\n    if (typeNameList.length === index) {\n      typeNameList.push({\n        role,\n        typeName: \"\",\n        typeList: arrCp,\n      });\n      this.props.dispatch(actions.setPhyClusterConfigType(typeNameList));\n    } else {\n      typeNameList[index] = {\n        role,\n        typeName: \"\",\n        typeList: arrCp,\n      };\n      this.props.dispatch(actions.setPhyClusterConfigType(typeNameList));\n    }\n  }\n\n  public setOptionConfigData(value: string, index: number) {\n    const { typeNameList } = this.props.phyClusterConfig;\n    if (typeNameList.length > index) {\n      const initValue = typeNameList[index].typeName;\n      typeNameList[index].typeName = value;\n      typeNameList.map((item, i) => {\n        if (typeNameList[index].role === item.role) {\n          const arr = item.typeList.map((itemC) => {\n            if (value.indexOf(itemC.label) > -1) {\n              return { ...itemC, disabled: true };\n            } else {\n              if (initValue === itemC.label) {\n                return { ...itemC, disabled: false };\n              }\n              return itemC;\n            }\n          });\n          typeNameList[i].typeList = arr;\n          this.props.dispatch(actions.setPhyClusterConfigType(typeNameList));\n        }\n      });\n    }\n  }\n\n  public getFormMap = (index: number) => {\n    return [\n      [\n        {\n          key: \"enginName\",\n          label: \"节点角色\",\n          type: FormItemType.select,\n          options: this.state.configRoleList,\n          attrs: {\n            disabled: this.props.params?.enginName ? true : false,\n            placeholder: \"请选择节点角色\",\n          },\n          rules: [\n            {\n              required: true,\n              message: \"请选择节点角色\",\n              validator: (rule: any, value: string) => {\n                this.computeTypeNameList(value, index);\n                this.bindNodeRole();\n                if (value) {\n                  return Promise.resolve();\n                } else {\n                  return Promise.reject();\n                }\n              },\n            },\n          ],\n        },\n        {\n          key: \"typeName\",\n          label: \"配置类别\",\n          type: FormItemType.custom,\n          customFormItem: <ConfigNameSelect index={index} disabled={this.props.params?.enginName ? true : false} />,\n          rules: [\n            {\n              required: true,\n              message: \"请选择配置类别\",\n              validator: async (rule: any, value: string) => {\n                this.setOptionConfigData(value, index);\n                if (value) {\n                  return Promise.resolve();\n                } else {\n                  return Promise.reject();\n                }\n              },\n            },\n          ],\n        },\n      ],\n      [\n        {\n          key: \"desc\",\n          label: \"描述信息\",\n          type: FormItemType.textArea,\n          rules: [\n            {\n              required: false,\n              validator: async (rule: any, value: string) => {\n                if (value && value.length > 50) {\n                  return Promise.reject(\"请输入0-50字符\");\n                }\n                return Promise.resolve();\n              },\n            },\n          ],\n          attrs: {\n            disabled: false,\n            rows: 2,\n            placeholder: \"请输入描述\",\n          },\n        },\n      ],\n      [\n        {\n          key: \"configData\",\n          label: \"配置内容\",\n          type: FormItemType.textArea,\n          rules: [\n            {\n              required: true,\n            },\n          ],\n          attrs: {\n            disabled: false,\n            rows: 3,\n            placeholder: \"请输入配置内容\",\n          },\n        },\n      ],\n    ] as unknown as IFormItem[];\n  };\n\n  public getRolMap = () => {\n    return [\n      [\n        {\n          key: \"roleOrder\",\n          label: \"重启节点顺序\",\n          type: FormItemType.custom,\n          customFormItem: <StepSelect disabled={this.props.params?.enginName ? true : false} />,\n          rules: [\n            {\n              required: true,\n              message: \"请选择角色顺序\",\n              validator: (rule: any, value: any) => {\n                if (value?.length > 0) {\n                  return Promise.resolve();\n                } else {\n                  return Promise.reject();\n                }\n              },\n            },\n          ],\n        },\n      ],\n    ];\n  };\n\n  public onDel = (index: number) => {\n    if (index === 0) return;\n    const { addFormArr } = this.state;\n    addFormArr.splice(index, 1);\n    // phyClusterConfig.delEsConfigs(index);\n    this.setState({\n      addFormArr,\n    });\n  };\n\n  public addConfigItem = async () => {\n    this.$formRef.map((item, index) => {\n      if (this.$formRef.length - 1 === index) {\n        item\n          .validateFields()\n          .then((result) => {\n            const { addFormArr } = this.state;\n            const index = addFormArr.length - 1;\n            addFormArr.push(this.state.addFormArr.length);\n            this.setState({\n              addFormArr,\n            });\n          })\n          .catch((errs) => {\n            //\n          });\n      }\n    });\n  };\n\n  public render() {\n    const formDataRole = {\n      roleOrder: this.props.params?.enginName,\n    };\n    return (\n      <>\n        <Drawer\n          visible={true}\n          closable={true}\n          onClose={this.handleCancel}\n          title={this.props.params?.enginName ? \"编辑配置\" : \"新增配置\"}\n          maskClosable={false}\n          destroyOnClose={true}\n          width={728}\n          footer={\n            <div className=\"footer-btn\">\n              <Button style={{ marginRight: 10 }} loading={this.state.confirmLoading} type=\"primary\" onClick={this.handleSubmit}>\n                确定\n              </Button>\n              <Button onClick={this.handleCancel}>取消</Button>\n            </div>\n          }\n        >\n          {this.state.addFormArr.map((item, index) => {\n            return (\n              <div key={item} style={index > 0 ? { marginTop: 10 } : null} className=\"new-config-content\">\n                {item > 0 ? (\n                  <div className=\"new-config-content-del\">\n                    <a>{null}</a>\n                    <a onClick={() => this.onDel(index)}>删除</a>\n                  </div>\n                ) : null}\n                <XFormComponent\n                  key={item}\n                  wrappedComponentRef={(form: any) => {\n                    this.bindForm(form, index);\n                  }}\n                  formData={this.props.params || {}}\n                  formMapList={this.getFormMap(index)}\n                />\n              </div>\n            );\n          })}\n\n          {this.props.params?.enginName ? null : (\n            <Button className=\"add-new-config\" type=\"primary\" onClick={this.addConfigItem} block icon={<PlusOutlined />}>\n              添加新配置\n            </Button>\n          )}\n          <XFormComponent wrappedComponentRef={this.resetBindForm} formData={formDataRole} formMapList={this.getRolMap()} />\n        </Drawer>\n      </>\n    );\n  }\n}\n\ninterface IFormProps {\n  wrappedComponentRef?: any;\n  formData?: any;\n  formMapList: any;\n}\n\nconst XFormComponent = (props: IFormProps) => {\n  const [form] = Form.useForm();\n\n  const onValuesChange = (values) => {\n    Object.keys(values).map((key) => {\n      if (key === \"typeName\") {\n        getClusterTemplateCentent(values.typeName).then((res) => {\n          form.setFieldsValue({\n            configData: res?.configData,\n          });\n        });\n      }\n      if (key === \"enginName\") {\n        form.resetFields([\"typeName\", \"configData\"]);\n      }\n    });\n  };\n\n  const { formData, formMapList, wrappedComponentRef } = props;\n  return (\n    <Form ref={wrappedComponentRef} form={form} onValuesChange={onValuesChange} layout={\"vertical\"} className=\"base-info-form\">\n      {formMapList.map((row: IFormItem[], index: number) => {\n        return (\n          <Row key={index}>\n            {row[0] && (\n              <Col span={row.length === 1 ? 24 : 10} key={\"col-1\" + index} style={{ paddingRight: 20 }}>\n                {!row[0].invisible ? (\n                  <Form.Item\n                    key={row[0].key}\n                    label={row[0].label}\n                    name={row[0].key}\n                    rules={row[0].rules || [{ required: false, message: \"\" }]}\n                    initialValue={handleFormItem(row[0], formData).initialValue}\n                    valuePropName={handleFormItem(row[0], formData).valuePropName}\n                    className=\"from-confing-item\"\n                  >\n                    {renderFormItem(row[0])}\n                  </Form.Item>\n                ) : (\n                  <Form.Item key={row[0].key}>-</Form.Item>\n                )}\n              </Col>\n            )}\n            {row[1] && (\n              <Col span={10} key={\"col-2\" + index}>\n                {!row[1].invisible ? (\n                  <Form.Item\n                    key={row[1].key}\n                    label={row[1].label}\n                    name={row[1].key}\n                    rules={row[1].rules || [{ required: false, message: \"\" }]}\n                    initialValue={handleFormItem(row[1], formData).initialValue}\n                    valuePropName={handleFormItem(row[1], formData).valuePropName}\n                    className=\"from-confing-item\"\n                  >\n                    {renderFormItem(row[1])}\n                  </Form.Item>\n                ) : (\n                  <Form.Item key={row[1].key}>-</Form.Item>\n                )}\n              </Col>\n            )}\n          </Row>\n        );\n      })}\n    </Form>\n  );\n};\n\nconst ConfigNameSelect = connect(mapStateToProps)((props: any) => {\n  const { disabled, value, index } = props;\n  const opList = props.phyClusterConfig?.typeNameList[index]?.typeList || [];\n\n  const handleChange = (params: any) => {\n    const { onChange } = props;\n    onChange && onChange(params);\n  };\n\n  const content = (val) => {\n    if (val.disabled) {\n      return (\n        <Tooltip placement=\"right\" title={\"该配置已存在，不可重复添加\"}>\n          {val.label || val.value}\n        </Tooltip>\n      );\n    }\n    return val.label?.length > 35 || (val.value + \"\")?.length > 35 ? (\n      <Tooltip placement=\"bottomLeft\" title={val.label || val.value}>\n        {val.label || val.value}\n      </Tooltip>\n    ) : (\n      val.label || val.value\n    );\n  };\n  return (\n    <>\n      <Select placeholder=\"请选择配置类别\" showSearch={true} disabled={disabled} value={value} onChange={(e: any) => handleChange(e)}>\n        {opList.map((v) => (\n          <Select.Option key={v.value || v.label} value={v.value} disabled={v.disabled ? true : false}>\n            {content(v)}\n          </Select.Option>\n        ))}\n      </Select>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/physicsClusterTask/codeMirror.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { Spin } from \"antd\";\nimport { ACEJsonEditor } from \"@knowdesign/kbn-sense/lib/packages/kbn-ace/src/ace/json_editor\";\n\nexport const HotTask = (props) => {\n  const [data, setData] = useState(\"\");\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    props\n      .network(props.params.cluster)\n      .then((res) => {\n        setData(res || \"\");\n      })\n      .catch(() => {\n        setData(\"网络请求错误\");\n      })\n      .finally(() => {\n        setLoading(false);\n      });\n  }, []);\n\n  return (\n    <>\n      <div className=\"hot-task\">\n        <Spin spinning={loading} className=\"hot-task-spin\">\n          {!loading && <ACEJsonEditor options={{ useWorker: false }} className={\"mapping-detail\"} readOnly={true} data={data} />}\n        </Spin>\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/physicsClusterTask/config.tsx",
    "content": "import { toBytesFun, transTimeFormat, formatDecimalPoint } from \"lib/utils\";\nimport { bytesUnitFormatter } from \"lib/utils\";\n\nexport const node_state = () => {\n  const columns = [\n    {\n      title: \"node_name\",\n      dataIndex: \"nodeName\",\n      key: \"nodeName\",\n      width: 120,\n      sorter: (a, b) => {\n        const aa = a.nodeName || \"0\";\n        const bb = b.nodeName || \"0\";\n        return aa.localeCompare(bb);\n      },\n    },\n    {\n      title: \"segments_memory\",\n      dataIndex: \"segmentsMemory\",\n      key: \"segmentsMemory\",\n      width: 170,\n      sorter: (a, b) => {\n        const aa = a.segmentsMemory || -1;\n        const bb = b.segmentsMemory || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"os_cpu\",\n      dataIndex: \"osCpu\",\n      key: \"osCpu\",\n      width: 100,\n      sorter: (a, b) => {\n        const aa = a.osCpu || -1;\n        const bb = b.osCpu || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"os.load_average\",\n      dataIndex: \"loadAverage5m\",\n      key: \"loadAverage5m\",\n      sorter: (a, b) => {\n        const aa = a.loadAverage5m || -1;\n        const bb = b.loadAverage5m || -1;\n        return aa - bb;\n      },\n      width: 150,\n    },\n    {\n      title: \"jvm_heap_used_percent\",\n      dataIndex: \"jvmHeapUsedPercent\",\n      width: 200,\n      key: \"jvmHeapUsedPercent\",\n      sorter: (a, b) => {\n        const aa = a.jvmHeapUsedPercent || -1;\n        const bb = b.jvmHeapUsedPercent || -1;\n        return aa - bb;\n      },\n      render: (text: number) => (text + \"\" && text + \"%\") || \"-\",\n    },\n    {\n      title: \"thread.count\",\n      dataIndex: \"threadsCount\",\n      width: 140,\n      key: \"threadsCount\",\n      sorter: (a, b) => {\n        const aa = a.threadsCount || -1;\n        const bb = b.threadsCount || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"http_current_open\",\n      dataIndex: \"currentOpen\",\n      key: \"currentOpen\",\n      width: 160,\n      sorter: (a, b) => {\n        const aa = a.currentOpen || -1;\n        const bb = b.currentOpen || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"thread_pool_write_active\",\n      dataIndex: \"threadPoolWriteActive\",\n      width: 200,\n      sorter: (a, b) => {\n        const aa = a.threadPoolWriteActive || -1;\n        const bb = b.threadPoolWriteActive || -1;\n        return aa - bb;\n      },\n      key: \"threadPoolWriteActive\",\n    },\n    {\n      title: \"thread_pool_write_queue\",\n      dataIndex: \"threadPoolWriteQueue\",\n      key: \"threadPoolWriteQueue\",\n      width: 200,\n      sorter: (a, b) => {\n        const aa = a.threadPoolWriteQueue || -1;\n        const bb = b.threadPoolWriteQueue || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"thread_pool_write_reject\",\n      dataIndex: \"threadPoolWriteReject\",\n      key: \"threadPoolWriteReject\",\n      sorter: (a, b) => {\n        const aa = a.threadPoolWriteReject || -1;\n        const bb = b.threadPoolWriteReject || -1;\n        return aa - bb;\n      },\n      width: 200,\n    },\n    {\n      title: \"thread_pool_search_active\",\n      dataIndex: \"threadPoolSearchActive\",\n      key: \"threadPoolSearchActive\",\n      width: 210,\n      sorter: (a, b) => {\n        const aa = a.threadPoolSearchActive || -1;\n        const bb = b.threadPoolSearchActive || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"thread_pool_search_queue\",\n      dataIndex: \"threadPoolSearchQueue\",\n      key: \"threadPoolSearchQueue\",\n      sorter: (a, b) => {\n        const aa = a.threadPoolSearchQueue || -1;\n        const bb = b.threadPoolSearchQueue || -1;\n        return aa - bb;\n      },\n      width: 210,\n    },\n    {\n      title: \"thread_pool_search_reject\",\n      dataIndex: \"threadPoolSearchReject\",\n      key: \"threadPoolSearchReject\",\n      sorter: (a, b) => {\n        const aa = a.threadPoolSearchReject || -1;\n        const bb = b.threadPoolSearchReject || -1;\n        return aa - bb;\n      },\n      width: 210,\n    },\n    {\n      title: \"thread_pool_management_active\",\n      dataIndex: \"threadPoolManagementActive\",\n      key: \"threadPoolManagementActive\",\n      sorter: (a, b) => {\n        const aa = a.threadPoolManagementActive || -1;\n        const bb = b.threadPoolManagementActive || -1;\n        return aa - bb;\n      },\n      width: 250,\n    },\n    {\n      title: \"thread_pool_management_queue\",\n      dataIndex: \"threadPoolManagementQueue\",\n      key: \"threadPoolManagementQueue\",\n      sorter: (a, b) => {\n        const aa = a.threadPoolManagementQueue || -1;\n        const bb = b.threadPoolManagementQueue || -1;\n        return aa - bb;\n      },\n      width: 255,\n    },\n    {\n      title: \"thread_pool_management_reject\",\n      dataIndex: \"threadPoolManagementReject\",\n      key: \"threadPoolManagementReject\",\n      sorter: (a, b) => {\n        const aa = a.threadPoolManagementReject || -1;\n        const bb = b.threadPoolManagementReject || -1;\n        return aa - bb;\n      },\n      width: 250,\n    },\n  ];\n  return columns;\n};\n\nexport const getPhysicsColumns = () => {\n  const columns = [\n    {\n      title: \"health\",\n      dataIndex: \"health\",\n      key: \"health\",\n      width: 100,\n      sorter: (a, b) => {\n        const aa = a.health || \"0\";\n        const bb = b.health || \"0\";\n        return aa.localeCompare(bb);\n      },\n    },\n    {\n      title: \"status\",\n      dataIndex: \"status\",\n      key: \"status\",\n      width: 100,\n      sorter: (a, b) => {\n        const aa = a.status || \"0\";\n        const bb = b.status || \"0\";\n        return aa.localeCompare(bb);\n      },\n    },\n    {\n      title: \"index\",\n      dataIndex: \"index\",\n      width: 115,\n      key: \"index\",\n    },\n    {\n      title: \"pri\",\n      dataIndex: \"pri\",\n      key: \"pri\",\n      width: 80,\n      sorter: (a, b) => {\n        const aa = a.pri || -1;\n        const bb = b.pri || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"rep\",\n      dataIndex: \"rep\",\n      key: \"rep\",\n      width: 80,\n      sorter: (a, b) => {\n        const aa = a.rep || -1;\n        const bb = b.rep || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"docs.Deleted\",\n      dataIndex: \"docsDeleted\",\n      key: \"docsDeleted\",\n      width: 120,\n      sorter: (a, b) => {\n        const aa = a.docsDeleted || -1;\n        const bb = b.docsDeleted || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"store.size\",\n      dataIndex: \"storeSize\",\n      key: \"storeSize\",\n      width: 100,\n      sorter: (a, b) => {\n        const aa = a.storeSize || -1;\n        const bb = b.storeSize || -1;\n        return aa - bb;\n      },\n      render: (val: number) => bytesUnitFormatter(val),\n    },\n    {\n      title: \"pri.store.size\",\n      dataIndex: \"priStoreSize\",\n      key: \"priStoreSize\",\n      width: 120,\n      sorter: (a, b) => {\n        const aa = a.priStoreSize || -1;\n        const bb = b.priStoreSize || -1;\n        return aa - bb;\n      },\n      render: (val: number) => bytesUnitFormatter(val),\n    },\n  ];\n  return columns;\n};\n\nexport const shard_distribution = () => {\n  const columns = [\n    {\n      title: \"index\",\n      dataIndex: \"index\",\n      key: \"index\",\n      width: 200,\n      sorter: (a, b) => {\n        const aa = a.index || \"0\";\n        const bb = b.index || \"0\";\n        return aa.localeCompare(bb);\n      },\n    },\n    {\n      title: \"shard\",\n      dataIndex: \"shard\",\n      key: \"shard\",\n      width: 100,\n      sorter: (a, b) => {\n        const aa = a.shard || -1;\n        const bb = b.shard || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"p/r\",\n      dataIndex: \"prirep\",\n      key: \"prirep\",\n      width: 80,\n      sorter: (a, b) => {\n        const aa = a.prirep || \"0\";\n        const bb = b.prirep || \"0\";\n        return aa.localeCompare(bb);\n      },\n    },\n    {\n      title: \"state\",\n      dataIndex: \"state\",\n      key: \"state\",\n      width: 108,\n      sorter: (a, b) => {\n        const aa = a.state || \"0\";\n        const bb = b.state || \"0\";\n        return aa.localeCompare(bb);\n      },\n    },\n    {\n      title: \"docs\",\n      dataIndex: \"docs\",\n      key: \"docs\",\n      width: 113,\n      sorter: (a, b) => {\n        const aa = a.docs || -1;\n        const bb = b.docs || -1;\n        return aa - bb;\n      },\n    },\n    {\n      title: \"store\",\n      dataIndex: \"store\",\n      key: \"store\",\n      width: 109,\n      sorter: (a, b) => {\n        const aa = a.store || -1;\n        const bb = b.store || -1;\n        return aa - bb;\n      },\n      render: (val: number) => bytesUnitFormatter(val),\n    },\n    {\n      title: \"ip\",\n      dataIndex: \"ip\",\n      key: \"ip\",\n      width: 120,\n      sorter: (a, b) => {\n        const aa = a.state || \"0\";\n        const bb = b.state || \"0\";\n        return aa.localeCompare(bb);\n      },\n    },\n    {\n      title: \"node\",\n      dataIndex: \"node\",\n      key: \"node\",\n      width: 100,\n      sorter: (a, b) => {\n        const aa = a.node || \"0\";\n        const bb = b.node || \"0\";\n        return aa.localeCompare(bb);\n      },\n    },\n  ];\n  return columns;\n};\n\nexport const pending_TaskAnalysis = () => {\n  const columns = [\n    {\n      title: \"insert_order\",\n      dataIndex: \"insertOrder\",\n      key: \"insertOrder\",\n      width: 200,\n    },\n    {\n      title: \"priority\",\n      dataIndex: \"priority\",\n      key: \"priority\",\n      width: 200,\n    },\n    {\n      title: \"source\",\n      dataIndex: \"source\",\n      key: \"source\",\n      width: 200,\n    },\n    {\n      title: \"time_in_queue_millis\",\n      dataIndex: \"timeInQueueMillis\",\n      key: \"timeInQueueMillis\",\n      width: 200,\n      sorter: (a, b) => {\n        return a.timeInQueueMillis - b.timeInQueueMillis;\n      },\n    },\n    {\n      title: \"time_in_queue\",\n      dataIndex: \"timeInQueue\",\n      key: \"timeInQueue\",\n      width: 200,\n      sorter: (a, b) => {\n        return toBytesFun(a.timeInQueue) - toBytesFun(b.timeInQueue);\n      },\n      render: (text: string) => formatDecimalPoint(text),\n    },\n  ];\n  return columns;\n};\n\nexport const task_Analysis = () => {\n  const columns = [\n    {\n      title: \"nodeName\",\n      dataIndex: \"node\",\n      key: \"node\",\n      width: 210,\n    },\n    {\n      title: \"action\",\n      dataIndex: \"action\",\n      key: \"action\",\n      width: 190,\n    },\n    {\n      title: \"description\",\n      dataIndex: \"description\",\n      key: \"description\",\n      width: 150,\n    },\n    {\n      title: \"start_time_in_millis\",\n      dataIndex: \"startTimeInMillis\",\n      key: \"startTimeInMillis\",\n      width: 200,\n      sorter: (a, b) => {\n        const aa = a.startTimeInMillis || -1;\n        const bb = b.startTimeInMillis || -1;\n        return parseFloat(aa) - parseFloat(bb);\n      },\n      render: (text: number) => transTimeFormat(text),\n    },\n    {\n      title: \"running_time_in_nanos\",\n      dataIndex: \"runningTimeInNanos\",\n      key: \"runningTimeInNanos\",\n      sorter: (a, b) => {\n        const aa = a.runningTimeInNanos || -1;\n        const bb = b.runningTimeInNanos || -1;\n        return parseFloat(aa) - parseFloat(bb);\n      },\n      render: (text: string) => formatDecimalPoint(text),\n    },\n  ];\n  return columns;\n};\n\nexport const shard_DistributionExplain = () => {\n  const columns = [\n    {\n      title: \"index\",\n      dataIndex: \"index\",\n      key: \"index\",\n      width: 122,\n    },\n    {\n      title: \"shard\",\n      dataIndex: \"shard\",\n      key: \"shard\",\n      width: 112,\n    },\n    {\n      title: \"primary\",\n      dataIndex: \"primary\",\n      key: \"primary\",\n      width: 120,\n    },\n    {\n      title: \"current_state\",\n      dataIndex: \"currentState\",\n      key: \"currentState\",\n      width: 148,\n    },\n    {\n      title: \"node_name\",\n      dataIndex: \"nodeName\",\n      key: \"nodeName\",\n      width: 170,\n    },\n    {\n      title: \"nodeDecide\",\n      dataIndex: \"nodeDecide\",\n      key: \"nodeDecide\",\n      width: 138,\n    },\n    {\n      title: \"explanation\",\n      dataIndex: \"explanation\",\n      key: \"explanation\",\n    },\n  ];\n  return columns;\n};\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/physicsClusterTask/index.less",
    "content": ".ant-drawer-body {\n  padding: 0 24px;\n\n  .ant-tabs-nav {\n    margin-bottom: 8px;\n  }\n}\n\n.CodeMirror {\n  height: calc(100vh - 345px);\n}\n\n.error-container {\n  margin-top: 120px;\n\n  .error-gif {\n    text-align: center;\n  }\n\n  .error-desc {\n    text-align: center;\n    margin-top: 32px;\n    font-size: 20px;\n    font-family: PingFangSC-Regular;\n    color: #101724;\n  }\n}\n\n.retry-button {\n  display: flex;\n  justify-content: center;\n  margin-top: 20px;\n}\n\n.button-container {\n  background-color: #eff8ff;\n  height: 36px;\n  line-height: 36px;\n\n  .test-container {\n    height: 22px;\n    line-height: 22px;\n\n    .iconinfo {\n      font-size: 16px;\n      margin-right: 6px;\n      margin-left: 12px;\n      color: #2f81f9;\n      position: relative;\n      bottom: 1px;\n    }\n\n    span {\n      font-size: 14px;\n    }\n  }\n}\n\n.button-style {\n  width: 88px;\n  height: 28px;\n  margin-left: 16px;\n  line-height: 14px;\n\n  span {\n    height: 12px;\n    line-height: 12px;\n  }\n}\n\n.button-style2 {\n  width: 88px;\n  height: 28px;\n  line-height: 14px;\n\n  span {\n    height: 12px;\n    line-height: 12px;\n  }\n}\n\n.tab-empty {\n  text-align: center;\n  font-size: 20px !important;\n\n  img {\n    width: 200px;\n    height: 200px;\n  }\n\n  .tab-desc {\n    text-align: center !important;\n    color: #101724 !important;\n    font-family: PingFangSC-Regular !important;\n  }\n}\n\n.quick-commands {\n  height: 100%;\n  .ant-tabs {\n    height: 100%;\n    width: 100%;\n    display: inline-block;\n    overflow: auto;\n    &::-webkit-scrollbar {\n      display: none;\n    }\n  }\n  .ant-tabs-nav-list {\n    padding-top: 16px;\n    overflow-x: auto;\n    &::-webkit-scrollbar {\n      display: none;\n    }\n  }\n  .ant-tabs-tab {\n    font-size: 14px;\n    padding: 8px 0;\n    line-height: 36px;\n    height: 36px;\n  }\n  .ant-tabs-tab-active {\n    font-family: PingFangSC-Medium;\n  }\n  .ant-tabs-nav .ant-tabs-nav-operations .ant-tabs-nav-more {\n    padding: 20px 10px 0 10px;\n  }\n  .ant-spin-nested-loading {\n    .hot-task-spin {\n      height: 300px;\n    }\n  }\n  .tab-empty {\n    position: absolute;\n    top: 300px;\n    left: 400px;\n  }\n}\n\n.hot-task {\n  .mapping-detail {\n    height: calc(100vh - 170px);\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/physicsClusterTask/index.tsx",
    "content": "import React, { useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { AppState, UserState } from \"store/type\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { IFormItem } from \"component/x-form\";\nimport { Tabs, Spin, Button } from \"antd\";\nimport {\n  abnormalShardRetry,\n  clearFieldDataMemory,\n  nodeState,\n  indicesDistribute,\n  shardDistribute,\n  task_mission_analysis,\n  pendTaskAnalysis,\n  hotThreadAnalysis,\n  shardAssignDescription,\n} from \"api/cluster-api\";\nimport {\n  getPhysicsColumns,\n  node_state,\n  shard_distribution,\n  pending_TaskAnalysis,\n  task_Analysis,\n  shard_DistributionExplain,\n} from \"./config\";\nimport { HotTask } from \"./codeMirror\";\nimport { PhysicsClusterTable } from \"./table\";\nimport { ShardTables } from \"./shardTable\";\nimport { IndicesTables } from \"./indicesTable\";\nimport { ShardDistributeTabs } from \"./shardDistributeTable\";\nimport \"./index.less\";\nimport { ErrorSvg, OkSvg } from \"./svg\";\nconst { TabPane } = Tabs;\n\nconst TabButton = (props) => {\n  const [isShow, setIsShow] = useState(true);\n  const [isLoading, setIsLoading] = useState(false);\n  const [Retry, setRetry] = useState(\"\");\n\n  return (\n    <div>\n      {isShow && (\n        <div className=\"button-container\">\n          <span className=\"test-container\">\n            <span className=\"icon iconfont iconinfo\"></span>\n            <span>{props.tabKey === \"8\" ? \"POST/_cluster/reroute?retry_failed=true\" : \"POST _cache/clear?fielddata=true\"}</span>\n          </span>\n          <Button\n            type=\"primary\"\n            loading={isLoading}\n            className=\"button-style\"\n            onClick={() => {\n              setIsLoading(true);\n              props\n                .network(props.props.params.cluster)\n                .then((res) => {\n                  res && res.message === \"操作失败\" ? setRetry(\"执行失败\") : setRetry(\"执行成功\");\n                  setIsShow(false);\n                })\n                .catch((rej) => {\n                  setRetry(\"执行失败\");\n                })\n                .finally(() => {\n                  setIsLoading(false);\n                  setIsShow(false);\n                });\n            }}\n          >\n            执行\n          </Button>\n        </div>\n      )}\n      {!isShow && (\n        <Spin spinning={isLoading} tip=\"Loading...\">\n          <div className=\"error-container\">\n            <div className=\"error-gif\">{Retry === \"执行成功\" ? <OkSvg /> : <ErrorSvg />}</div>\n            <div className=\"error-desc\">\n              <span>{Retry === \"执行成功\" ? Retry : `${Retry}请重试`}</span>\n            </div>\n            {Retry === \"执行成功\" ? (\n              \"\"\n            ) : (\n              <div className=\"retry-button\">\n                <Button\n                  type=\"primary\"\n                  loading={isLoading}\n                  className=\"button-style2\"\n                  onClick={() => {\n                    setIsLoading(true);\n                    props\n                      .network(props.props.params.cluster)\n                      .then((res) => {\n                        res && res.message === \"操作失败\" ? setRetry(\"执行失败\") : setRetry(\"执行成功\");\n                        setIsShow(false);\n                      })\n                      .catch((rej) => {\n                        setRetry(\"执行失败\");\n                      })\n                      .finally(() => {\n                        setIsLoading(false);\n                        setIsShow(false);\n                      });\n                  }}\n                >\n                  执行\n                </Button>\n              </div>\n            )}\n          </div>\n        </Spin>\n      )}\n    </div>\n  );\n};\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst PhysicsClusterTask = (props: { dispatch: any; cb: Function; app: AppState; user: UserState; params: any }) => {\n  const [currentTabKey, setCurrentTabKey] = useState(\"\");\n  //tab点击请求接口\n  const changeTabs = (activeKey) => {\n    setCurrentTabKey(activeKey);\n  };\n  const customRenderElementFun = () => {\n    return (\n      <div className=\"quick-commands\">\n        <Tabs activeKey={currentTabKey} onChange={changeTabs} destroyInactiveTabPane>\n          <TabPane tab=\"node_state分析\" key=\"1\">\n            <PhysicsClusterTable\n              {...props}\n              network={nodeState}\n              columns={node_state}\n              hasSearch\n              placeholder=\"请输入关键字，支持node_name\"\n              keyword=\"nodeName\"\n            />\n          </TabPane>\n          <TabPane tab=\"indices分布\" key=\"2\">\n            <IndicesTables {...props} network={indicesDistribute} columns={getPhysicsColumns} />\n          </TabPane>\n          <TabPane tab=\"shard分布\" key=\"3\">\n            <ShardDistributeTabs {...props} network={shardDistribute} columns={shard_distribution} />\n          </TabPane>\n          <TabPane tab=\"pending task分析\" key=\"4\">\n            <PhysicsClusterTable {...props} network={pendTaskAnalysis} columns={pending_TaskAnalysis} />\n          </TabPane>\n          <TabPane tab=\"task任务分析\" key=\"5\">\n            <PhysicsClusterTable\n              {...props}\n              network={task_mission_analysis}\n              columns={task_Analysis}\n              hasSearch\n              placeholder=\"请输入关键字，支持nodeName\"\n              keyword=\"node\"\n            />\n          </TabPane>\n          <TabPane tab=\"热点线程分析\" key=\"6\">\n            <HotTask {...props} network={hotThreadAnalysis} />\n          </TabPane>\n          {/* <TabPane tab=\"shard分配说明\" key=\"7\">\n            <ShardTables {...props} network={shardAssignDescription} columns={shard_DistributionExplain} />\n          </TabPane>\n          <TabPane tab=\"异常shard分配重试\" key=\"8\">\n            <TabButton props={props} network={abnormalShardRetry} tabKey={currentTabKey} />\n          </TabPane>\n          <TabPane tab=\"清除fielddata内存\" key=\"9\">\n            <TabButton props={props} network={clearFieldDataMemory} tabKey={currentTabKey} />\n          </TabPane> */}\n        </Tabs>\n        {!currentTabKey && (\n          <div className=\"tab-empty\">\n            <img src={require(\"../../../../assets/yellow-receipts@2x.png\")} alt=\"\" />\n            <div className=\"tab-desc\">请点击执行快捷命令</div>\n          </div>\n        )}\n      </div>\n    );\n  };\n  const xFormModalConfig = {\n    formMap: [] as IFormItem[],\n    visible: true,\n    title: \"快捷命令\",\n    bodyStyle: { Padding: 0 },\n    formData: { gatewayUrl: props.params.gatewayUrl },\n    onCancel: () => {\n      props.dispatch(actions.setDrawerId(\"\"));\n    },\n    onSubmit: async () => {},\n    width: 1080,\n    customRenderElement: customRenderElementFun(),\n    noform: true,\n    type: \"drawer\",\n    nofooter: true,\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(PhysicsClusterTask);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/physicsClusterTask/indicesTable.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { ErrorSvg } from \"./svg\";\nimport { useResize } from \"../../../../lib/utils\";\n\nconst IndicesTable = (props) => {\n  const [loading, setLoading] = useState(false);\n  const [data, setData] = useState([]);\n  const [orginData, setOrginData] = useState([]);\n  const [isResolve, setIsResolve] = useState(true);\n  const clientSize = useResize(\"ant-drawer-body\");\n\n  useEffect(() => {\n    reloadData();\n  }, []);\n\n  const reloadData = async () => {\n    setLoading(true);\n    const requestData = props.network;\n    const params = {\n      cluster: props.params.cluster,\n    };\n    try {\n      let res = await requestData(params);\n      setIsResolve(true);\n      setData(res);\n      setOrginData(res);\n    } catch {\n      setIsResolve(false);\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  const handleSubmit = (val) => {\n    let data = orginData.filter((item) => item?.index?.includes(val));\n    setData(data);\n  };\n\n  return (\n    <>\n      <div>\n        {isResolve ? (\n          <DTable\n            loading={loading}\n            rowKey=\"index\"\n            dataSource={data}\n            reloadData={reloadData}\n            attrs={{\n              scroll: { x: \"max-content\", y: clientSize.height - 220 },\n            }}\n            tableHeaderSearchInput={{\n              submit: handleSubmit,\n              style: { width: 220, paddingBottom: 10 },\n              placeholder: \"请输入关键字，支持index\",\n            }}\n            columns={props.columns()}\n            paginationProps={{\n              showSizeChanger: true,\n              pageSizeOptions: [\"5\", \"10\", \"20\", \"50\", \"100\", \"200\"],\n              position: \"bottomRight\",\n              showQuickJumper: true,\n              showTotal: (total) => `共 ${total} 条`,\n            }}\n          />\n        ) : (\n          <div className=\"error-container\">\n            <div className=\"error-gif\">\n              <ErrorSvg />\n            </div>\n            <div className=\"error-desc\">\n              <span>执行失败</span>\n            </div>\n          </div>\n        )}\n      </div>\n    </>\n  );\n};\nexport const IndicesTables = IndicesTable;\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/physicsClusterTask/shardDistributeTable.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { ErrorSvg } from \"./svg\";\nimport { useResize, uuid } from \"../../../../lib/utils\";\n\nconst ShardDistributeTab = (props) => {\n  const [loading, setLoading] = useState(false);\n  const [data, setData] = useState([]);\n  const [originData, setOriginData] = useState([]);\n  const [isResolve, setIsResolve] = useState(true);\n\n  const clientSize = useResize(\"ant-drawer-body\");\n\n  useEffect(() => {\n    reloadData();\n  }, []);\n\n  const reloadData = () => {\n    setLoading(true);\n    const requestData = props.network;\n    const params = {\n      cluster: props.params.cluster,\n    };\n    requestData(params)\n      .then((res) => {\n        if (res) {\n          let data = res.map((item) => ({ ...item, id: uuid() }));\n          setIsResolve(true);\n          setData(data);\n          setOriginData(data);\n        }\n      })\n      .catch(() => {\n        setIsResolve(false);\n      })\n      .finally(() => {\n        setLoading(false);\n      });\n  };\n\n  const handleSubmit = (val) => {\n    let data = originData.filter((item) => item?.index?.includes(val) || item?.ip?.includes(val) || item?.node?.includes(val));\n    setData(data);\n  };\n\n  return (\n    <>\n      <div>\n        {isResolve ? (\n          <DTable\n            loading={loading}\n            rowKey=\"id\"\n            dataSource={data}\n            reloadData={reloadData}\n            attrs={{\n              scroll: { y: clientSize.height - 220 },\n            }}\n            tableHeaderSearchInput={{\n              submit: handleSubmit,\n              style: { width: 300, paddingBottom: 10 },\n              placeholder: \"请输入关键字，支持index、ip、node\",\n            }}\n            columns={props.columns()}\n            paginationProps={{\n              showSizeChanger: true,\n              pageSizeOptions: [\"5\", \"10\", \"20\", \"50\", \"100\", \"200\"],\n              position: \"bottomRight\",\n              showQuickJumper: true,\n              showTotal: (total) => `共 ${total} 条`,\n            }}\n          />\n        ) : (\n          <div className=\"error-container\">\n            <div className=\"error-gif\">\n              <ErrorSvg />\n            </div>\n            <div className=\"error-desc\">\n              <span>执行失败</span>\n            </div>\n          </div>\n        )}\n      </div>\n    </>\n  );\n};\nexport const ShardDistributeTabs = ShardDistributeTab;\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/physicsClusterTask/shardTable.tsx",
    "content": "import React, { useState, useEffect, useRef } from \"react\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { ErrorSvg } from \"./svg\"\nimport { useResize } from \"../../../../lib/utils\";\nconst ShardTable = (props) => {\n  const [loading, setLoading] = useState(false);\n  const [queryFormObject, setqueryFormObject]: any = useState({\n    current: 1,\n    size: 10,\n  });\n  const [data, setData] = useState([]);\n  const [total, setTotal] = useState(0);\n  const [isResolve, setIsResolve] = useState(true);\n  const saveData = useRef(null);\n  const clientSize = useResize(\"ant-drawer-body\");\n  useEffect(() => {\n    reloadData();\n  }, []);\n\n  // useEffect(() => {\n  //   const start = queryFormObject.size * (queryFormObject.current - 1);\n  //   const end = queryFormObject.current * queryFormObject.size;\n  //   if (saveData.current) {\n  //     const formatRes = saveData.current?.decisions.slice(start, end).map((item, index) => {\n  //       return {\n  //         ...saveData.current,\n  //         ...item,\n  //       };\n  //     });\n  //     setData(formatRes);\n  //   }\n  // }, [queryFormObject]);\n\n  const reloadData = () => {\n    setLoading(true);\n    const requestData = props.network;\n    requestData(props.params.cluster)\n      .then((res) => {\n        if (res) {\n          setIsResolve(true);\n          const formatRes = res?.decisions.map((item, index) => {\n            return {\n              ...res,\n              ...item,\n            };\n          });\n          saveData.current = res;\n          setData(formatRes);\n        }\n      }).catch((rej) => {\n        setIsResolve(false);\n      })\n      .finally(() => {\n        setLoading(false);\n      });\n  };\n\n  const handleChange = (pagination, filters, sorter) => {\n    // 条件过滤请求在这里处理\n    const sorterObject: { [key: string]: any } = {};\n    if (sorter.columnKey && sorter.order) {\n      // switch (sorter.columnKey) {\n      //   case \"diskInfo\":\n      //     sorterObject.sortTerm = \"disk_usage_percent\";\n      //     sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n      //     break;\n      //   case \"activeShardNum\":\n      //     sorterObject.sortTerm = \"active_shard_num\";\n      //     sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n      //     break;\n      //   default:\n      //     break;\n      // }\n    }\n    setqueryFormObject((state) => {\n      if (!sorter.order) {\n        delete state.sortTerm;\n        delete state.orderByDesc;\n      }\n      return {\n        ...state,\n        // ...sorterObject,\n        current: pagination.current,\n        size: pagination.pageSize,\n      };\n    });\n  };\n\n  return (\n    <>\n      <div>\n        {isResolve ? <DTable\n          loading={loading}\n          rowKey=\"id\"\n          dataSource={data}\n          attrs={{\n            //pagination: false,\n            onChange: handleChange,\n            scroll: { x: \"max-content\", y: clientSize.height - 190 },\n            //bordered: true\n          }}\n          columns={props.columns()}\n        /> : (<div className=\"error-container\">\n          <div className=\"error-gif\">\n            <ErrorSvg />\n          </div>\n          <div className=\"error-desc\">\n            <span>执行失败</span>\n          </div>\n        </div>)\n        }\n      </div>\n    </>\n  );\n};\nexport const ShardTables = ShardTable;\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/physicsClusterTask/svg.tsx",
    "content": "import React from \"react\";\nexport const ErrorSvg = () => {\n  return (\n    <>\n      <svg width=\"72px\" height=\"72px\" viewBox=\"0 0 72 72\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlnsXlink=\"http://www.w3.org/1999/xlink\">\n        <title>形状</title>\n        <g id=\"0.3版本迭代0512\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n          <g id=\"【ES】--其他\" transform=\"translate(-2224.000000, -2187.000000)\" fill=\"#FB4E57\" fill-rule=\"nonzero\">\n            <g id=\"编组-13\" transform=\"translate(1720.000000, 1981.000000)\">\n              <g id=\"编组-12\" transform=\"translate(500.000000, 206.000000)\">\n                <path d=\"M40,0 C20.02,0 4,16.02 4,36 C4,55.98 20.02,72 40,72 C59.9755,72 76,55.98 76,36 C76,16.02 59.9755,0 40,0 L40,0 Z M58,48.96 L52.9555,54 L40,41.04 L27.0355,54 L22,48.96 L34.9555,36 L22,23.04 L27.0355,18 L40,30.96 L52.9555,18 L58,23.04 L45.0355,36 L58,48.96 L58,48.96 Z\" id=\"形状\"></path>\n              </g>\n            </g>\n          </g>\n        </g>\n      </svg>\n    </>\n  );\n};\n\nexport const OkSvg = () => {\n  return (\n    <>\n      <svg width=\"72px\" height=\"72px\" viewBox=\"0 0 72 72\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlnsXlink=\"http://www.w3.org/1999/xlink\">\n        <title>形状</title>\n        <g id=\"0.3版本迭代0512\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n          <g id=\"【ES】--其他\" transform=\"translate(-1991.000000, -2498.000000)\" fill=\"#00B365\" fill-rule=\"nonzero\">\n            <path d=\"M2052.45624,2559.45624 C2038.39788,2573.51459 2015.60212,2573.51459 2001.54376,2559.45624 C1987.48541,2545.39788 1987.48541,2522.60212 2001.54376,2508.54376 C2015.60212,2494.48541 2038.39788,2494.48541 2052.45624,2508.54376 C2066.51459,2522.60212 2066.51459,2545.39788 2052.45624,2559.45624 Z M2022.47289,2538.69272 L2012.29003,2528.50986 L2007.1995,2533.60039 L2022.47289,2548.87377 L2046.65649,2524.69017 L2041.56596,2519.59964 L2022.47289,2538.69272 Z\" id=\"形状\"></path>\n          </g>\n        </g>\n      </svg>\n    </>\n  );\n};\n\n\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/physicsClusterTask/table.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { ErrorSvg } from \"./svg\";\nimport { useResize, uuid } from \"../../../../lib/utils\";\n// import { ProTable, DTable } from \"knowdesign\";\n\nconst PhysicsClusterTask = (props) => {\n  const [loading, setLoading] = useState(false);\n  const [data, setData] = useState([]);\n  const [orginData, setOrginData] = useState([]);\n  const [isResolve, setIsResolve] = useState(true);\n  const clientSize = useResize(\"ant-drawer-body\");\n\n  const { network, params, hasSearch, placeholder, columns, keyword, rowKey } = props;\n\n  useEffect(() => {\n    reloadData();\n  }, []);\n\n  const reloadData = () => {\n    setLoading(true);\n    network(params.cluster)\n      .then((res) => {\n        if (res) {\n          let data = (res || []).map((item) => {\n            return {\n              ...item,\n              id: uuid(),\n            };\n          });\n          setIsResolve(true);\n          setData(data);\n          setOrginData(data);\n        }\n      })\n      .catch(() => {\n        setIsResolve(false);\n      })\n      .finally(() => {\n        setLoading(false);\n      });\n  };\n\n  const handleSubmit = (val) => {\n    let data = (orginData || []).filter((item) => item[keyword].includes(val));\n    setData(data);\n  };\n\n  return (\n    <>\n      <div>\n        {isResolve ? (\n          <DTable\n            loading={loading}\n            rowKey=\"id\"\n            dataSource={data}\n            attrs={{\n              scroll: { x: \"max-content\", y: clientSize.height - 190 },\n            }}\n            tableHeaderSearchInput={\n              hasSearch\n                ? {\n                    submit: handleSubmit,\n                    style: { width: 250, paddingBottom: 10 },\n                    placeholder,\n                  }\n                : null\n            }\n            columns={columns()}\n          />\n        ) : (\n          // <ProTable\n          //   tableProps={{\n          //     tableId: \"physics_cluster_task_table\",\n          //     loading,\n          //     rowKey: \"key\",\n          //     dataSource: data,\n          //     columns: columns(),\n          //     attrs: {\n          //       scroll: { x: \"max-content\", y: clientSize.height - 190 },\n          //     },\n          //   }}\n          // />\n          <div className=\"error-container\">\n            <div className=\"error-gif\">\n              <ErrorSvg />\n            </div>\n            <div className=\"error-desc\">\n              <span>执行失败</span>\n            </div>\n          </div>\n        )}\n      </div>\n    </>\n  );\n};\nexport const PhysicsClusterTable = PhysicsClusterTask;\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/region-admin.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport RegionTransfer from \"container/custom-form/region-transfer\";\nimport { getRegionNode, getRegionList, editRegion, deleteRegion } from \"api/cluster-api\";\nimport { Button, Drawer, Tag, Tooltip } from \"antd\";\nimport { INodeDivide } from \"typesPath/index-types\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { renderOperationBtns, renderMoreText } from \"container/custom-component\";\nimport { XNotification } from \"component/x-notification\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nconst RegionAdmin = (props: {\n  dispatch: any;\n  cb: Function;\n  params: {\n    cluster: string;\n    nodeDivideList: INodeDivide[];\n    record?: INodeDivide;\n    id: number;\n  };\n}) => {\n  const [nodeList, setNodeList] = useState([]);\n  const [transferList, setTransferList] = useState([]);\n  const [selectKeys, setSelectKeys] = useState([]);\n  const [tableList, setTableList] = useState([]);\n  const [currentRegion, setCurrentRegion] = useState({} as any);\n  const [loading, setLoading] = useState(false);\n  const [transferVisible, setTransferVisible] = useState(false);\n  const [editList, setEditList] = useState([]);\n\n  useEffect(() => {\n    _getRegionNode();\n  }, []);\n\n  const _getRegionNode = async () => {\n    let clusterId = props.params.id;\n    setLoading(true);\n    let res = await getRegionNode(clusterId);\n    let tableData = await getTableList(res);\n    let nodeList = (res || []).map((item) => {\n      return {\n        ...item,\n        key: item.id,\n        selected: item.regionName ? true : false,\n      };\n    });\n    setNodeList(nodeList);\n    setTableList(tableData);\n    setLoading(false);\n    return nodeList;\n  };\n\n  const getTransferList = (data, keys) => {\n    let list = data.filter((item) => !item.selected || keys?.includes(item.id));\n    let res = list.map((item) => {\n      return {\n        ...item,\n      };\n    });\n    return res;\n  };\n\n  const getTableList = async (data) => {\n    let cluster = props.params.cluster;\n    // 获取region列表\n    let res = await getRegionList(cluster);\n    // 过滤掉未绑定的节点\n    let list = (data || []).filter((item) => item.regionId !== -1);\n    let tableList = [];\n    // 通过name判断data中是否有对应的数据\n    const hasNode = (data: any, name: string, key: string) => {\n      let index = -1;\n      for (let i = 0; i < data?.length; i++) {\n        if (data[i]?.[key] === name) {\n          index = i;\n          break;\n        }\n      }\n      return index;\n    };\n    list.forEach((item) => {\n      let name = item.regionName;\n      let index = hasNode(tableList, name, \"regionName\");\n      let regionIndex = hasNode(res, name, \"name\");\n      // 将region列表数据和节点数据进行合并\n      if (index !== -1) {\n        tableList[index].nodeSet = tableList[index].nodeSet + \", \" + item.nodeSet;\n        tableList[index].key.push(item.id);\n      } else if (regionIndex !== -1) {\n        let data = {\n          ...item,\n          key: [item.id],\n          ...res[regionIndex],\n        };\n        tableList.push(data);\n      } else {\n        let data = {\n          ...item,\n          key: [item.id],\n        };\n        tableList.push(data);\n      }\n    });\n    // 若接口返回列表长度和拼接region后的列表长度不一致，说明有region为空\n    if (res?.length !== tableList?.length) {\n      let nameList = (tableList || []).map((item) => item.name);\n      let emptyNodeList = (res || []).filter((item) => {\n        return !nameList.includes(item.name);\n      });\n      emptyNodeList = emptyNodeList.map((item) => {\n        return {\n          ...item,\n          regionName: item.name,\n          regionId: item.id,\n        };\n      });\n      tableList = [...tableList, ...emptyNodeList];\n    }\n    return tableList;\n  };\n\n  const _editRegion = async () => {\n    // 未进行操作，点击确定直接关闭弹窗\n    if (!editList.length && !currentRegion.regionId) {\n      props.dispatch(actions.setModalId(\"\"));\n      return;\n    }\n    if (!selectKeys.length) {\n      XNotification({ type: \"error\", message: \"region不能为空\" });\n      return;\n    }\n    let params = editList;\n    let unBindingNodeIds = [];\n    (currentRegion?.key || []).forEach((item) => {\n      if (!selectKeys.includes(item)) {\n        unBindingNodeIds.push(item);\n      }\n    });\n    let lastRegion = {\n      bindingNodeIds: selectKeys,\n      id: currentRegion.regionId,\n      logicClusterIds: props.params.id,\n      name: currentRegion.regionName,\n      phyClusterName: props.params.cluster,\n      unBindingNodeIds,\n    };\n    params.push(lastRegion);\n    await editRegion(params);\n    XNotification({ type: \"success\", message: \"编辑成功\" });\n    props.dispatch(actions.setModalId(\"\"));\n  };\n\n  const clickEdit = (record, list?: any) => {\n    setCurrentRegion(record);\n    if (transferVisible) {\n      let unBindingNodeIds = [];\n      (currentRegion?.key || []).forEach((item) => {\n        if (!selectKeys.includes(item)) {\n          unBindingNodeIds.push(item);\n        }\n      });\n      let region = {\n        bindingNodeIds: selectKeys,\n        id: currentRegion.regionId,\n        logicClusterIds: props.params.id,\n        name: currentRegion.regionName,\n        phyClusterName: props.params.cluster,\n        unBindingNodeIds,\n      };\n      setEditList([...editList, region]);\n    } else {\n      setTransferVisible(true);\n    }\n    let transferData = getTransferList(list || nodeList, record.key);\n    setTransferList(transferData);\n    setSelectKeys(record.key);\n    setCurrentRegion(record);\n  };\n\n  const getColumns = () => {\n    return [\n      {\n        title: \"Region名称\",\n        dataIndex: \"regionName\",\n        key: \"regionName\",\n        width: 264,\n        render: (val: string, record: any) => {\n          let cold = false;\n          if (record?.config) {\n            let config = JSON.parse(record?.config);\n            cold = config?.cold;\n          }\n          return cold ? (\n            <div className=\"cold-region-tag\">\n              {renderMoreText(val, 36)}\n              <Tooltip title=\"该Region只用于冷热分离，不可用于划分逻辑集群\" overlayStyle={{ maxWidth: 1080 }}>\n                <Tag color=\"blue\" className=\"tag-bule\">\n                  cold\n                </Tag>\n              </Tooltip>\n            </div>\n          ) : (\n            renderMoreText(val, 36)\n          );\n        },\n      },\n      {\n        title: \"实例名称\",\n        dataIndex: \"nodeSet\",\n        key: \"nodeSet\",\n      },\n      {\n        title: \"操作\",\n        dataIndex: \"actions\",\n        key: \"actions\",\n        render: (val, record) => {\n          let btn = [\n            {\n              label: \"编辑\",\n              type: \"primary\",\n              clickFunc: (record) => {\n                clickEdit(record);\n              },\n            },\n            {\n              label: \"删除\",\n              type: \"primary\",\n              needConfirm: true,\n              confirmText: `删除`,\n              clickFunc: async (record) => {\n                await deleteRegion(record.regionId);\n                XNotification({ type: \"success\", message: \"删除成功\" });\n                let list = await _getRegionNode();\n                if (currentRegion?.regionId === record.regionId) {\n                  setCurrentRegion({});\n                  setTransferVisible(false);\n                  setEditList([]);\n                } else {\n                  transferVisible && clickEdit(currentRegion, list);\n                }\n              },\n            },\n          ];\n          return renderOperationBtns(btn, record);\n        },\n      },\n    ];\n  };\n\n  const renderTransfer = () => {\n    return (\n      <>\n        <div className=\"region-title\">节点列表</div>\n        <RegionTransfer\n          dataSource={transferList}\n          selectKeys={(keys) => {\n            setSelectKeys(keys);\n            let list = nodeList.map((item) => {\n              return {\n                ...item,\n                selected: keys.includes(item.key) || (item?.id !== currentRegion.id && item.selected),\n              };\n            });\n            setNodeList(list);\n          }}\n          targetKeys={selectKeys}\n        />\n      </>\n    );\n  };\n\n  const xFormModalConfig = {\n    width: 1080,\n    title: \"Region管理\",\n    type: \"drawer\",\n    onClose: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    footer: (\n      <div>\n        <Button type=\"primary\" style={{ marginRight: 10 }} onClick={_editRegion}>\n          确定\n        </Button>\n        <Button onClick={() => props.dispatch(actions.setModalId(\"\"))}>取消</Button>\n      </div>\n    ),\n  };\n\n  return (\n    <>\n      <Drawer visible={true} {...xFormModalConfig}>\n        <div>\n          <div className=\"region-title\">Region列表</div>\n          <DTable\n            loading={loading}\n            rowKey=\"id\"\n            dataSource={tableList}\n            columns={getColumns()}\n            attrs={{ size: \"small\", style: { marginTop: -15 } }}\n          />\n        </div>\n        {transferVisible && renderTransfer()}\n      </Drawer>\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(RegionAdmin);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/region-divide.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport RegionTransfer from \"container/custom-form/region-transfer\";\nimport { getRegionNode, divideRegionCheck, divideRegion, getRegionList } from \"api/cluster-api\";\nimport { Input, Button, Drawer, Radio, Tag, Tooltip } from \"antd\";\nimport { INodeDivide } from \"typesPath/index-types\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { renderMoreText } from \"container/custom-component\";\nimport { regRegionName } from \"../../../constants/reg\";\nimport { XNotification } from \"component/x-notification\";\nimport { uuid } from \"lib/utils\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nconst RegionDivide = (props: {\n  dispatch: any;\n  cb: Function;\n  params: {\n    cluster: string;\n    nodeDivideList: INodeDivide[];\n    record?: INodeDivide;\n    id: number;\n  };\n}) => {\n  const [transferList, setTransferList] = useState([]);\n  const [selectKeys, setSelectKeys] = useState([]);\n  const [tableList, setTableList] = useState([]);\n  const [loading, setLoading] = useState(false);\n  const [name, setName] = useState(\"\");\n  const [error, setError] = useState(false);\n  const [value, setValue] = useState(false);\n  const [divideList, setDivideList] = useState([]);\n\n  useEffect(() => {\n    _getRegionNode();\n  }, []);\n\n  const _getRegionNode = async () => {\n    let clusterId = props.params.id;\n    setLoading(true);\n    let res = await getRegionNode(clusterId);\n    let tableData = await _getRegionList();\n    let transferData = getTransferList(res);\n    setTransferList(transferData);\n    setTableList(tableData);\n    setLoading(false);\n  };\n\n  const onChange = (e) => {\n    setValue(e.target.value);\n  };\n\n  const _getRegionList = async () => {\n    let cluster = props.params.cluster;\n    let res = await getRegionList(cluster);\n    let data = (res || []).map((item) => {\n      return {\n        ...item,\n        regionName: item.name,\n        nodeSet: item.nodeNames || \"-\",\n      };\n    });\n    return data;\n  };\n\n  const getTransferList = (data) => {\n    let list = data.filter((item) => item.regionId === -1);\n    let res = list.map((item) => {\n      return {\n        ...item,\n        key: item.id,\n      };\n    });\n    return res;\n  };\n\n  const addRegion = async () => {\n    if (error) {\n      XNotification({ type: \"error\", message: \"请输入正确输入Region名称\" });\n      return;\n    }\n    if (!name) {\n      XNotification({ type: \"error\", message: \"请输入Region名称\" });\n      return;\n    }\n    if (!selectKeys.length) {\n      XNotification({ type: \"error\", message: \"请选择加入Region的节点\" });\n      return;\n    }\n    let config = { cold: value };\n    let params = [\n      {\n        bindingNodeIds: selectKeys,\n        logicClusterIds: props.params.id,\n        name,\n        phyClusterName: props.params.cluster,\n        config: JSON.stringify(config),\n      },\n    ] as any;\n    if (!value) {\n      delete params[0].config;\n    }\n    // 校验region名称是否重复\n    await divideRegionCheck(params);\n    setName(\"\");\n    setDivideList([...divideList, ...params]);\n    // transfer 数据中过滤掉已选中的节点\n    let transferData = transferList?.filter((item) => !selectKeys.includes(item?.id));\n    setTransferList(transferData);\n    // table 展示添加的节点\n    let selectList = transferList?.filter((item) => selectKeys.includes(item?.id));\n    let nodeSet = selectList.map((item) => item.nodeSet).join(\",\");\n    setTableList([...tableList, { regionName: name, nodeSet, config: JSON.stringify(config), id: uuid() }]);\n    setSelectKeys([]);\n  };\n\n  const getColumns = () => {\n    return [\n      {\n        title: \"Region名称\",\n        dataIndex: \"regionName\",\n        key: \"regionName\",\n        width: 264,\n        render: (val: string, record: any) => {\n          let cold = false;\n          if (record?.config) {\n            let config = JSON.parse(record?.config);\n            cold = config?.cold;\n          }\n          return cold ? (\n            <div className=\"cold-region-tag\">\n              {renderMoreText(val, 36)}\n              <Tooltip title=\"该Region只用于冷热分离，不可用于划分逻辑集群\" overlayStyle={{ maxWidth: 1080 }}>\n                <Tag color=\"blue\" className=\"tag-bule\">\n                  cold\n                </Tag>\n              </Tooltip>\n            </div>\n          ) : (\n            renderMoreText(val, 36)\n          );\n        },\n      },\n      {\n        title: \"节点名称\",\n        dataIndex: \"nodeSet\",\n        key: \"nodeSet\",\n      },\n    ];\n  };\n\n  const xFormModalConfig = {\n    visible: true,\n    width: 1080,\n    title: \"Region划分\",\n    className: \"regin-contain\",\n    onClose: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    footer: (\n      <div>\n        <Button\n          type=\"primary\"\n          style={{ marginRight: 10 }}\n          onClick={async () => {\n            if (divideList.length) {\n              await divideRegion(divideList);\n              XNotification({ type: \"success\", message: \"添加成功\" });\n            }\n            props.dispatch(actions.setModalId(\"\"));\n          }}\n        >\n          确定\n        </Button>\n        <Button onClick={() => props.dispatch(actions.setModalId(\"\"))}>取消</Button>\n      </div>\n    ),\n  };\n\n  const renderDefineRegion = () => {\n    return (\n      <div>\n        <div className=\"region-title defined\">Region定义</div>\n        <div className=\"define-region\">\n          <div className=\"region-input\">\n            <div className=\"region-name-title\">Region名称</div>\n            <Input\n              allowClear\n              value={name}\n              className={`region-name-input ${error && \"region-name-input-error\"}`}\n              placeholder=\"请输入Region名称\"\n              onChange={(e) => {\n                let value = e.target.value;\n                if (regRegionName.test(value) && value.length <= 32) {\n                  setError(false);\n                } else {\n                  setError(true);\n                }\n                setName(value);\n              }}\n            />\n            <Button className=\"region-name-add\" type=\"primary\" onClick={addRegion}>\n              添加\n            </Button>\n            {error && <div className=\"region-name-error\">支持文字，字母，数字，下划线，中划线，32字以内</div>}\n          </div>\n          <div className=\"cold-region\">\n            <div className=\"cold-region-title\">是否定义为cold属性Region？</div>\n            <Radio.Group className=\"cold-group\" onChange={onChange} value={value}>\n              <Radio value={true}>是</Radio>\n              <Radio value={false}>否</Radio>\n            </Radio.Group>\n          </div>\n        </div>\n      </div>\n    );\n  };\n\n  return (\n    <>\n      <Drawer {...xFormModalConfig}>\n        <div className=\"node-list\">\n          <div className=\"region-title\">节点列表</div>\n          <RegionTransfer\n            dataSource={transferList}\n            selectKeys={(keys) => {\n              setSelectKeys(keys);\n            }}\n            style={{ marginTop: -6 }}\n          />\n        </div>\n        {renderDefineRegion()}\n        <div className=\"region-title nodelist\">Region列表</div>\n        <DTable\n          loading={loading}\n          rowKey=\"id\"\n          dataSource={tableList}\n          columns={getColumns()}\n          attrs={{ size: \"small\", style: { marginTop: -15 } }}\n        />\n      </Drawer>\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(RegionDivide);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/restart-cluster.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { OrderNode, RenderText } from \"container/custom-form\";\nimport { IOpPhysicsClusterDetail } from \"typesPath/cluster/cluster-types\";\nimport { AppState, UserState } from \"store/type\";\nimport { clusterRestart } from \"api/cluster-api\";\nimport { showSubmitTaskSuccessModal } from \"container/custom-component\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  user: state.user,\n  app: state.app,\n});\n\nconst RestartClusterModal = (props: { dispatch: any; cb: Function; app: AppState; user: UserState; params: IOpPhysicsClusterDetail }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"name\",\n        label: \"集群名称\",\n        type: FormItemType.text,\n        isCustomStyle: true,\n        CustomStyle: { marginTop: 24 },\n        customFormItem: <RenderText text={props.params.cluster} />,\n      },\n      {\n        key: \"roleOrder\",\n        label: \"重启节点顺序\",\n        type: FormItemType.custom,\n        customFormItem: <OrderNode id={props.params.id} />,\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"集群重启\",\n    formData: props.params || {},\n    isWaitting: true,\n    type: \"drawer\",\n    width: 660,\n    onCancel: () => {\n      props.dispatch(actions.setDrawerId(\"\"));\n    },\n    onSubmit: async (result: any) => {\n      result.roleOrder = result.roleOrder.map((item) => item.roleClusterName);\n      let params = {\n        phyClusterId: props.params.id,\n        phyClusterName: props.params.cluster,\n        roleOrder: result.roleOrder,\n      };\n      let expandData = JSON.stringify(params);\n      let ret = await clusterRestart({ expandData });\n      props.dispatch(actions.setDrawerId(\"\"));\n      showSubmitTaskSuccessModal(ret, props.params?.history);\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(RestartClusterModal);\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/senior.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { Button, Tooltip } from \"antd\";\nimport { getDataCenter, getResourceType } from \"api/cluster-api\";\nimport { DoubleRightOutlined } from \"@ant-design/icons\";\nimport { FormItemType, IFormItem, XForm as XFormComponent } from \"component/x-form\";\nimport { RESOURCE_TYPE_LIST } from \"constants/common\";\nimport \"./index.less\";\n\nexport default function Senior(props) {\n  const [fold, setFold] = useState(false);\n  const [dataCenter, setDataCenter] = useState([]);\n  const [resourceType, setResourceType] = useState([]);\n\n  useEffect(() => {\n    _getDataCenter();\n    _getResourceType();\n  }, []);\n\n  const _getDataCenter = async () => {\n    let res = await getDataCenter();\n    let data = (res || []).map((item: string) => {\n      return { value: item, label: item };\n    });\n    setDataCenter(data);\n  };\n\n  const _getResourceType = async () => {\n    let res = await getResourceType();\n    let data = (res || []).map((item: string) => {\n      return { value: item, label: item };\n    });\n    setResourceType(data);\n  };\n\n  const onHandleValuesChange = (val, allVal) => {\n    props.seniorChange(allVal);\n  };\n\n  const accessFormMap = [\n    props?.type === \"apply\"\n      ? {\n          key: \"proxyAddress\",\n          label: (\n            <div className=\"cluster-label\">\n              代理地址\n              <Tooltip title=\"请填写代理地址，填写后，上方填写的部署地址无效，以代理地址为准。\">\n                <span className=\"icon iconfont iconinfo\"></span>\n              </Tooltip>\n            </div>\n          ),\n          isCustomStyle: true,\n          CustomStyle: { marginTop: 0 },\n          attrs: {\n            placeholder: \"请输入\",\n          },\n          rules: [\n            {\n              validator: (_, value) => {\n                if (value?.length > 128) return Promise.reject(\"请输入代理地址，0-128位字符\");\n                return Promise.resolve();\n              },\n            },\n          ],\n        }\n      : [\n          {\n            key: \"platformType\",\n            label: \"IaaS平台类型\",\n            type: FormItemType.select,\n            options: resourceType,\n            attrs: {\n              placeholder: \"请选择\",\n            },\n            isCustomStyle: true,\n            CustomStyle: { marginTop: 0 },\n          },\n          {\n            key: \"proxyAddress\",\n            label: (\n              <div className=\"cluster-label\">\n                代理地址\n                <Tooltip title=\"请填写代理地址，填写后，上方填写的部署地址无效，以代理地址为准。\">\n                  <span className=\"icon iconfont iconinfo\"></span>\n                </Tooltip>\n              </div>\n            ),\n            isCustomStyle: true,\n            CustomStyle: { marginTop: 0 },\n            attrs: {\n              placeholder: \"请输入\",\n            },\n            rules: [\n              {\n                validator: (_, value) => {\n                  if (value?.length > 128) return Promise.reject(\"请输入代理地址，0-128位字符\");\n                  return Promise.resolve();\n                },\n              },\n            ],\n          },\n        ],\n    [\n      {\n        key: \"usename\",\n        label: (\n          <div className=\"cluster-label\">\n            账户名\n            <Tooltip title=\"集群具备账号和密码的用户请自定义添加，不具备请忽略，否则可能导致集群接入失败。\">\n              <span className=\"icon iconfont iconinfo\"></span>\n            </Tooltip>\n          </div>\n        ),\n        attrs: {\n          placeholder: \"请输入账户名\",\n        },\n        isCustomStyle: true,\n        CustomStyle: { marginTop: 0 },\n        rules: [\n          {\n            validator: async (_rule: any, value: string) => {\n              if (value.length > 32 || value.includes(\"：\") || value.includes(\":\")) {\n                return Promise.reject(\"请填写账户名，1-32位字符，不支持：号\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"password\",\n        label: <div className=\"cluster-label\">密码</div>,\n        attrs: {\n          placeholder: \"请输入密码\",\n        },\n        isCustomStyle: true,\n        CustomStyle: { marginTop: 0 },\n        rules: [\n          {\n            validator: async (rule: any, value: string) => {\n              if (!value) return Promise.resolve();\n              if (\n                value.length < 6 ||\n                value.length > 32 ||\n                value.includes(\".\") ||\n                /[\\u4e00-\\u9fa5]/.test(value) ||\n                value.includes(\":\") ||\n                value.includes(\"：\")\n              ) {\n                return Promise.reject(\"请填写正确密码，6-32位字符，不支持.、:、中文\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n    ],\n    [\n      {\n        key: \"kibanaAddress\",\n        label: \"kibana外链地址\",\n        attrs: {\n          placeholder: \"请输入kibana外链地址\",\n        },\n        isCustomStyle: true,\n        CustomStyle: { marginTop: 0 },\n        rules: [\n          {\n            validator: async (rule: any, value: string) => {\n              if (!value || (value && value.length <= 512 && /[\\u4e00-\\u9fa5-_、/.a-zA-Z0-9_]{1,512}$/.test(value))) {\n                return Promise.resolve();\n              }\n              return Promise.reject(\"清输入正确的kibana外链地址，支持中英文、数字、-、_、、/、.，0-512位字符\");\n            },\n          },\n        ],\n      },\n      {\n        key: \"cerebroAddress\",\n        label: \"cerebro外链地址\",\n        attrs: {\n          placeholder: \"请输入cerebro外链地址\",\n        },\n        isCustomStyle: true,\n        CustomStyle: { marginTop: 0 },\n        rules: [\n          {\n            validator: async (rule: any, value: string) => {\n              if (!value || (value && value.length <= 512 && /[\\u4e00-\\u9fa5-_、/.a-zA-Z0-9_]{1,512}$/.test(value))) {\n                return Promise.resolve();\n              }\n              return Promise.reject(\"清输入正确的cerebro外链地址，支持中英文、数字、-、_、、/、.，0-512位字符\");\n            },\n          },\n        ],\n      },\n    ],\n  ] as unknown as IFormItem[];\n\n  const basicFormMap = [\n    [\n      {\n        key: \"clusterType\",\n        label: (\n          <div className=\"cluster-label\">\n            <span className=\"title\">集群类型</span>\n            <Tooltip\n              title={\n                <>\n                  <div>独立集群：支持集群层面的数据隔离</div>\n                  <div>独享集群：支持数据节点层面的隔离</div>\n                  <div>共享集群：数据共享</div>\n                </>\n              }\n            >\n              <span className=\"icon iconfont iconinfo\"></span>\n            </Tooltip>\n          </div>\n        ),\n        type: FormItemType.select,\n        options: RESOURCE_TYPE_LIST,\n        rules: [\n          {\n            required: true,\n          },\n        ],\n        attrs: {\n          placeholder: \"请选择\",\n        },\n      },\n      {\n        key: \"dataCenter\",\n        label: \"数据中心\",\n        type: FormItemType.select,\n        options: dataCenter,\n        attrs: {\n          placeholder: \"请选择\",\n        },\n      },\n    ],\n  ];\n\n  const renderContent = () => {\n    let formMap = [].concat(basicFormMap).concat(accessFormMap);\n\n    let seniorValue = props?.seniorValue || {};\n    return (\n      <XFormComponent\n        className=\"senior-form\"\n        //@ts-ignore\n        formMap={formMap}\n        formData={{ clusterType: RESOURCE_TYPE_LIST[1].value, ...seniorValue }}\n        onHandleValuesChange={onHandleValuesChange}\n      ></XFormComponent>\n    );\n  };\n\n  return (\n    <div className=\"access-cluster-senior\">\n      <Button type=\"link\" style={{ paddingLeft: 0, marginBottom: \"16px\" }} onClick={() => setFold(!fold)}>\n        高级\n        <DoubleRightOutlined className={fold ? \"up\" : \"down\"} />\n      </Button>\n      {fold && renderContent()}\n    </div>\n  );\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/unintallPlugn.tsx",
    "content": "import React from \"react\";\nimport { Modal, Form, Input, message } from \"antd\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { InfoCircleOutlined } from \"@ant-design/icons\";\nimport { submitWorkOrder } from \"api/common-api\";\nimport store from \"store\";\nimport \"./deleteStyle.less\";\n\nconst appInfo = {\n  app: store.getState().app,\n  user: store.getState().user,\n};\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const UninstallPlugin = connect(mapStateToProps)((props: { dispatch: any; params: any; cb: any }) => {\n  const { params, dispatch, cb } = props;\n  const [form] = Form.useForm();\n  return (\n    <>\n      <Modal\n        visible={true}\n        title={\"卸载插件\"}\n        width={480}\n        onCancel={() => {\n          dispatch(actions.setModalId(\"\"));\n        }}\n        onOk={async () => {\n          const values = await form.validateFields();\n          if (values && values?.desc) {\n            const contentObj = {\n              operationType: 4,\n              logicClusterId: params.id,\n              logicClusterName: params.name,\n              plugIds: params.id,\n              plugName: params.name,\n              pluginId: params.id,\n              pluginFileName: params.name,\n              url: params.url,\n              plugDesc: params.plugDesc,\n              type: \"6\",\n            };\n            const param = {\n              contentObj,\n              submitorProjectId: appInfo.app.appInfo()?.id,\n              submitor: appInfo.user.getName(\"userName\"),\n              description: values?.desc,\n              type: \"clusterOpPluginRestart\",\n            };\n            return submitWorkOrder(param, () => {\n              dispatch(actions.setModalId(\"\"));\n              cb();\n            });\n          }\n        }}\n      >\n        <div>\n          <div className=\"delete-modal-content\">\n            <div className=\"delete-modal-content-left\">\n              <InfoCircleOutlined className=\"delete-modal-content-left-icon\" />\n            </div>\n            <div className=\"delete-modal-content-right\">\n              <p className=\"delete-modal-content-right-p1\">是否确定卸载该{params.name}插件？</p>\n              <p className=\"delete-modal-content-right-p2\">插件卸载、安装需要重启集群，点击确认后，将自动提交工单。</p>\n            </div>\n          </div>\n\n          <div style={{ marginTop: 10 }}>\n            <Form form={form} layout=\"vertical\">\n              <Form.Item\n                label=\"申请理由\"\n                style={{ marginBottom: 0 }}\n                rules={[\n                  {\n                    required: true,\n                    validator: (rule: any, value: string) => {\n                      if (!value || value?.trim().length > 100) {\n                        return Promise.reject(\"请输入1-100字申请原因\");\n                      } else {\n                        return Promise.resolve();\n                      }\n                    },\n                  },\n                ]}\n                name={\"desc\"}\n              >\n                <Input.TextArea allowClear rows={4} placeholder=\"请输入申请原因1-100个字符\" />\n              </Form.Item>\n            </Form>\n          </div>\n        </div>\n      </Modal>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/upgrade-cluster.tsx",
    "content": "import { Drawer, Button } from \"antd\";\nimport React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"../../../actions\";\nimport { Dispatch } from \"redux\";\nimport { FormItemType, IFormItem, XForm as XFormComponent } from \"component/x-form\";\nimport { OrderNode } from \"container/custom-form\";\nimport \"./index.less\";\nimport { VERSION_MAINFEST_TYPE } from \"constants/status-map\";\nimport { IVersions } from \"typesPath/cluster/physics-type\";\nimport { getPackageList } from \"api/cluster-api\";\nimport { clusterUpgrade } from \"api/cluster-api\";\nimport { showSubmitTaskSuccessModal } from \"container/custom-component\";\n\nconst labelList = [\n  {\n    label: \"集群名称：\",\n    key: \"cluster\",\n    content: \"\",\n  },\n  {\n    label: \"现有ES版本：\",\n    key: \"esVersion\",\n    content: \"\",\n  },\n];\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params, cb)),\n});\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  user: state.user,\n  app: state.app,\n});\n\nconst connects: Function = connect;\n\n@connects(mapStateToProps, mapDispatchToProps)\nexport class UpgradeCluster extends React.Component<any> {\n  state = {\n    formMapItem: [\n      {\n        key: \"esVersion\",\n        label: \"升级至ES版本\",\n        type: FormItemType.select,\n        options: [],\n        rules: [\n          {\n            required: true,\n          },\n        ],\n        attrs: {\n          style: { width: \"50%\" },\n        },\n      },\n      {\n        key: \"roleOrder\",\n        label: \"重启节点顺序\",\n        type: FormItemType.custom,\n        customFormItem: <OrderNode id={this.props.params?.id} />,\n      },\n    ] as IFormItem[],\n    confirmLoading: false,\n  };\n  formRef: any = React.createRef();\n\n  public componentDidMount() {\n    const { params } = this.props;\n    let packageDockerList = [] as IVersions[];\n    let packageHostList = [] as IVersions[];\n    getPackageList().then((data: IVersions[]) => {\n      const list = data.filter((data, indx, self) => {\n        return self.findIndex((ele) => ele.esVersion === data.esVersion) === indx;\n      });\n      const packageList = list.map((ele, index) => {\n        return {\n          ...ele,\n          key: index,\n          value: ele.esVersion,\n        };\n      });\n      packageDockerList = packageList.filter((ele) => ele.manifest === 3);\n      packageHostList = packageList.filter((ele) => ele.manifest === 4);\n      const formMapItem = this.state.formMapItem;\n      if (params.type === 3) {\n        formMapItem[0].options = packageDockerList;\n        this.setState({\n          formMapItem,\n        });\n      } else {\n        formMapItem[0].options = packageHostList;\n        this.setState({\n          formMapItem,\n        });\n      }\n    });\n  }\n\n  public handleOk = () => {\n    this.setState({ confirmLoading: true });\n    this.formRef.current!.validateFields().then(async (result) => {\n      result.roleOrder = result.roleOrder.map((item) => item.roleClusterName);\n      let roleClusterHosts = [];\n      if (this.props.params && this.props.params.esRoleClusterVOS) {\n        this.props.params.esRoleClusterVOS?.forEach((item) => {\n          item?.esRoleClusterHostVO?.forEach((obj) => {\n            const param: any = { role: item.role, hostname: obj.hostname };\n            if (obj.rack == \"cold\") {\n              param.beCold = true;\n            } else {\n              param.beCold = false;\n            }\n            roleClusterHosts.push(param);\n          });\n        });\n      }\n      let params = {\n        phyClusterId: this.props.params.id,\n        phyClusterName: this.props.params.cluster,\n        esVersion: result.esVersion,\n        roleOrder: result.roleOrder,\n        roleClusterHosts,\n      };\n      let expandData = JSON.stringify(params);\n      try {\n        let ret = await clusterUpgrade({ expandData });\n        this.props.setDrawerId(\"\");\n        showSubmitTaskSuccessModal(ret, this.props.params?.history);\n      } finally {\n        this.setState({ confirmLoading: false });\n      }\n    });\n  };\n\n  public handleCancel = () => {\n    this.props.setDrawerId(\"\");\n  };\n\n  public getLabelList = () => {\n    const { params, user } = this.props;\n    return labelList.map((item) => {\n      item.content = params[item.key];\n      if (item.key === \"user\") {\n        item.content = user.getName(\"userName\");\n      }\n      if (item.key === \"type\") {\n        item.content = VERSION_MAINFEST_TYPE[params[item.key]];\n      }\n      if (item.key === \"user\") {\n        item.content = this.props.user.getName(\"userName\");\n      }\n      return item;\n    });\n  };\n\n  render() {\n    return (\n      <div>\n        <Drawer\n          destroyOnClose={true}\n          onClose={this.handleCancel}\n          maskClosable={false}\n          closable={true}\n          visible={true}\n          title=\"集群升级\"\n          width={660}\n          footer={\n            <div className=\"footer-btn\">\n              <Button style={{ marginRight: 10 }} loading={this.state.confirmLoading} type=\"primary\" onClick={this.handleOk}>\n                确定\n              </Button>\n              <Button onClick={this.handleCancel}>取消</Button>\n            </div>\n          }\n        >\n          <div className=\"upgrade-cluster-box\">\n            {this.getLabelList().map((item, index) => (\n              <div key={item.label + index} className=\"upgrade-cluster-box-item\">\n                <span className=\"label\">{item.label}</span>\n                <span>{item.content}</span>\n              </div>\n            ))}\n          </div>\n          <div className=\"upgrade-cluster-form\">\n            <XFormComponent formData={{}} formMap={this.state.formMapItem} wrappedComponentRef={this.formRef} layout={\"vertical\"} />\n          </div>\n        </Drawer>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/physics-cluster/userPassword.tsx",
    "content": "import React from \"react\";\nimport { Button, Tooltip, Input, Form } from \"antd\";\nimport { MinusOutlined, PlusOutlined, QuestionCircleOutlined } from \"@ant-design/icons\";\n\nexport class RulePassword extends React.Component<any> {\n  state = {\n    isShow: false,\n    addNodeTypeList: [\n      {\n        value: \"user\",\n        text: \"账户名\",\n        tip: \"请输入账户\",\n        index: 0,\n      },\n      {\n        value: \"password\",\n        text: \"密码\",\n        tip: \"请输入密码\",\n        index: 1,\n      },\n    ],\n    text: \"\",\n    check: {\n      user: {\n        tipText: \"\",\n        isTip: false,\n      },\n      password: {\n        tipText: \"\",\n        isTip: false,\n      },\n    } as { [key: string]: { tipText: string; isTip: boolean } },\n  };\n\n  addFrom = () => {\n    this.setState(\n      {\n        isShow: !this.state.isShow,\n      },\n      () => {\n        this.handleTextArea();\n      }\n    );\n  };\n\n  del() {\n    this.setState(\n      {\n        isShow: !this.state.isShow,\n        text: \"\",\n        check: {\n          user: {\n            tipText: \"\",\n            isTip: false,\n          },\n          password: {\n            tipText: \"\",\n            isTip: false,\n          },\n        },\n      },\n      () => this.handleChange(\"\")\n    );\n  }\n\n  handleTextArea(e?: string, type?) {\n    const { check, text } = this.state;\n    const textSplit = text.split(\":\");\n    // 因为根据；号隔开\n    e?.replace(\":\", \"\");\n    if (type === \"user\") {\n      if (!e || e?.length > 32 || e?.indexOf(\":\") !== -1) {\n        check[type] = {\n          tipText: \"填写账户名，1-32位字符，不支持：号\",\n          isTip: true,\n        };\n      } else {\n        check[type] = {\n          tipText: \"\",\n          isTip: false,\n        };\n      }\n      textSplit[0] = e;\n    } else if (type === \"password\") {\n      if (!e || e?.length < 6 || e?.length > 32) {\n        check[type] = {\n          tipText: \"请填写密码，6-32位字符，不支持:号\",\n          isTip: true,\n        };\n      } else {\n        check[type] = {\n          tipText: \"\",\n          isTip: false,\n        };\n      }\n      textSplit[1] = e;\n    }\n    if ((textSplit[0] && !textSplit[0]?.length) || !textSplit[0]) {\n      check.user = {\n        tipText: \"填写账户名，1-32位字符，不支持：号\",\n        isTip: true,\n      };\n    }\n    if ((textSplit[1] && !textSplit[1]?.length) || !textSplit[1]) {\n      check.password = {\n        tipText: \"请填写密码，6-32位字符，不支持:号\",\n        isTip: true,\n      };\n    }\n    this.setState({\n      text: textSplit.join(\":\"),\n      check,\n    });\n    this.handleChange(textSplit.join(\":\"));\n  }\n\n  handleChange(param) {\n    const { onChange } = this.props;\n    const { check } = this.state;\n    let flag = false;\n    for (const key in check) {\n      if (check[key].isTip) {\n        flag = true;\n      }\n    }\n    onChange && onChange({ value: param, check: flag });\n  }\n\n  componentDidMount() {\n    const { value } = this.props;\n    if (value && value?.value) {\n      this.setState({\n        text: value.value,\n        isShow: true,\n      });\n    }\n  }\n\n  renderItem = (item, key: number) => {\n    const { text, check } = this.state;\n    return (\n      <div key={key}>\n        <div className=\"add-role-header\" style={{ marginTop: item.index == \"1\" ? 10 : 0 }}>\n          <div>\n            <span>{item.text}</span>\n          </div>\n        </div>\n        <Input\n          allowClear\n          value={text.split(\":\")[item.index]}\n          onChange={(e) => this.handleTextArea(e.target.value, item.value)}\n          placeholder={item?.tip}\n        />\n        {check[item.value]?.isTip ? <p style={{ color: \"#ff4d4f\" }}>{check[item.value]?.tipText}</p> : null}\n      </div>\n    );\n  };\n\n  render() {\n    let { addNodeTypeList, isShow } = this.state;\n    return (\n      <>\n        <div style={{ marginTop: 10 }}>\n          {!isShow ? (\n            <Button type=\"primary\" size=\"small\" onClick={this.addFrom}>\n              <PlusOutlined /> 添加账户密码\n            </Button>\n          ) : (\n            <Button\n              type=\"primary\"\n              size=\"small\"\n              onClick={() => {\n                this.del();\n              }}\n              style={{ marginBottom: 10 }}\n            >\n              <MinusOutlined /> 删除账户密码\n            </Button>\n          )}\n          <Tooltip title=\"集群具备账号和密码的用户请自定义添加，不具备请忽略，否则可能导致集群接入失败。\">\n            <QuestionCircleOutlined\n              style={{\n                fontSize: 14,\n                // verticalAlign: 'middle',\n                marginLeft: 10,\n                color: \"rgb(197, 197, 197)\",\n              }}\n            />\n          </Tooltip>\n        </div>\n        {isShow ? addNodeTypeList.map((item, index) => this.renderItem(item, index)) : null}\n      </>\n    );\n  }\n}\n\nexport default RulePassword;\n"
  },
  {
    "path": "arius-console/src/container/modal/plugn/custom-plugn.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { UploadFile } from \"container/custom-form/upload-file\";\nimport { addPlug } from \"api/plug-api\";\nimport { UserState } from \"store/type\";\nimport urlParser from \"lib/url-parser\";\nimport { pDefaultMap } from \"container/cluster/logic-detail/config\";\nimport { computeChecksumMd5, getCookie } from \"lib/utils\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  user: state.user,\n});\n\nconst CustomPlugnModal = (props: { dispatch: any; cb: Function; user: UserState; params: any }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"uploadFile\",\n        label: \"上传文件\",\n        type: FormItemType.custom,\n        customFormItem: <UploadFile multiple={true} />,\n        formAttrs: {\n          style: { margin: 0 },\n        },\n        rules: [\n          {\n            required: true,\n            message: \"请上传的单个文件小于 100 MB\",\n            validator: async (rule: any, value: any) => {\n              const { fileList } = value;\n              const flag = fileList.some((item) => item.size / 1024 / 1024 >= 100);\n              if (flag) {\n                return Promise.reject();\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n        attrs: {\n          accept: \".gz\",\n        },\n      },\n      {\n        key: \"pDefault\",\n        label: \"插件类型\",\n        type: FormItemType.select,\n        isCustomStyle: true,\n        CustomStyle: { margin: \"-16px 0 0\" },\n        options: Object.keys({\n          1: \"ES能力\",\n          2: \"平台能力\",\n        }).map((item) => {\n          return {\n            label: pDefaultMap[Number(item)],\n            value: item,\n          };\n        }),\n        rules: [\n          {\n            required: true,\n            message: \"请选择插件类型\",\n          },\n        ],\n        attrs: {\n          placeholder: \"请选择插件类型\",\n        },\n      },\n      {\n        key: \"desc\",\n        label: \"描述\",\n        type: FormItemType.textArea,\n        rules: [\n          {\n            required: false,\n            validator: async (rule: any, value: any) => {\n              if (value?.length > 100) {\n                return Promise.reject(\"请输入0-100个字符\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n        attrs: {\n          placeholder: \"请输入备注\",\n        },\n      },\n      // {\n      //   key: 'affirm',\n      //   label: '我已阅读',\n      //   type: FormItemType.checkBox,\n      //   options: [{\n      //     label: '插件安装需要重启集群，点击\"确认\"后，将自动提交申请工单，为保障集群稳定性，请务必保证插件本身的安全性和可用性。',\n      //     value: '1',\n      //   }],\n      //   rules: [{ required: true, message: '请确认阅读' }],\n      // },\n    ] as IFormItem[],\n    visible: true,\n    title: \"上传插件\",\n    formData: {},\n    isWaitting: true,\n    width: 660,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: async (result: any) => {\n      const { physicsClusterId } = urlParser().search;\n\n      const params = {\n        creator: getCookie(\"userName\") || \"\",\n        desc: result.desc,\n        name: result.name,\n        version: result.version,\n        pDefault: result.pDefault,\n        logicClusterId: props.params?.id || 0,\n        physicsClusterId: physicsClusterId,\n      };\n\n      const files = await Promise.all(\n        result.uploadFile.fileList.map(async (item) => ({\n          ...params,\n          fileName: item.name,\n          uploadFile: item.originFileObj,\n          md5: await computeChecksumMd5(item.originFileObj),\n        }))\n      );\n\n      await Promise.all(files.map((item) => addPlug(item)))\n        .then((res) => {\n          props.cb && props.cb(); // 重新获取数据列表\n        })\n        .finally(() => {\n          props.dispatch(actions.setModalId(\"\"));\n        });\n\n      // result.file = result.uploadFile.fileList[0].originFileObj;\n      // const md5 = await computeChecksumMd5(result.file);\n      // const params = {\n      //   creator: props.user.getName(\"userName\"),\n      //   desc: result.desc,\n      //   md5: md5 as string,\n      //   fileName: result.uploadFile.fileList[0].name,\n      //   name: result.name,\n      //   version: result.version,\n      //   uploadFile: result.file,\n      //   pDefault: props.params?.pDefault ? true : false,\n      //   logicClusterId: 0,\n      //   physicsClusterId: physicsClusterId,\n      // };\n      // if (props.params?.id) params.logicClusterId = props.params.id;\n      // addPlug(params)\n      //   .then((res) => {\n      //     props.dispatch(actions.setModalId(\"\"));\n      //     props.cb && props.cb(); // 重新获取数据列表\n      //   })\n      //   .finally(() => {\n      //     props.dispatch(actions.setModalId(\"\"));\n      //   });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper visible={true} {...xFormModalConfig} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(CustomPlugnModal);\n"
  },
  {
    "path": "arius-console/src/container/modal/project/access-setting.tsx",
    "content": "/* eslint-disable react/display-name */\nimport * as React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"../../../actions\";\nimport { Button, Drawer, message, Modal, Select, Table, Tooltip, Input, Form, Switch } from \"antd\";\nimport { SEARCH_TYPE_MAP } from \"container/ProjectManager/config\";\nimport { createAppByProjectId, deleteOneAppByProjectId, getAppByProjectId, updateAppByProjectId } from \"api\";\nimport { getEsUserPrimitiveList, getEsUserList, setDefaultDisplay } from \"api/cluster-api\";\nimport { renderOperationBtns } from \"container/custom-component\";\nimport { filterOption } from \"lib/utils\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { cellStyle } from \"constants/table\";\nimport { XNotification } from \"component/x-notification\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nconst searchTypeOptions = [\n  { value: 0, label: \"集群模式\" },\n  { value: 1, label: \"索引模式\" },\n  { value: 2, label: \"原生模式\" },\n];\n\nconst AccessSetting = (props: { dispatch: any; cb: any; params: any }) => {\n  const { params = {} } = props;\n  const [list, setList] = React.useState([]);\n  const [modalVisible, setModalVisible] = React.useState(false);\n  const [primitiveList, setPrimitiveList] = React.useState([]);\n  const [clusterList, setClusterList] = React.useState([]);\n  const [searchType, setSearchType] = React.useState(1);\n  const opType = React.useRef(\"add\");\n  const currentRecord = React.useRef({} as any);\n  const [form] = Form.useForm();\n\n  React.useEffect(() => {\n    getData();\n    getClusterList();\n  }, []);\n\n  const getData = () => {\n    getAppByProjectId(params.id).then((res) => {\n      setList(res);\n    });\n  };\n\n  const getClusterList = async () => {\n    let primitive = await getEsUserPrimitiveList(params.id);\n    let cluster = await getEsUserList(params.id);\n    let clusterList = (cluster || []).map((item) => ({ value: item, label: item }));\n    let primitiveList = (primitive || []).map((item) => ({ value: item, label: item }));\n    setClusterList(clusterList);\n    setPrimitiveList(primitiveList);\n  };\n\n  const getColumns: any = (list) => {\n    return [\n      {\n        title: \"ES_User\",\n        dataIndex: \"id\",\n        key: \"id\",\n        width: 90,\n      },\n      {\n        title: \"检验码\",\n        dataIndex: \"verifyCode\",\n        key: \"verifyCode\",\n        width: 150,\n      },\n      {\n        title: \"访问模式\",\n        dataIndex: \"searchType\",\n        key: \"searchType\",\n        width: 90,\n        render: (text: number) => {\n          return <>{SEARCH_TYPE_MAP[text]}</>;\n        },\n      },\n      {\n        title: \"访问集群\",\n        dataIndex: \"cluster\",\n        key: \"cluster\",\n        width: 150,\n        onCell: () => ({\n          style: { ...cellStyle, maxWidth: 150 },\n        }),\n        render: (val: string) => <Tooltip title={val || \"-\"}>{val || \"-\"}</Tooltip>,\n      },\n      {\n        title: \"应用默认的ES_User\",\n        dataIndex: \"defaultDisplay\",\n        key: \"defaultDisplay\",\n        width: 130,\n        render: (val: boolean, record) => {\n          return (\n            <div className=\"project-default-display\">\n              <Switch\n                size=\"small\"\n                checked={val}\n                disabled={val}\n                onClick={() =>\n                  Modal.confirm({\n                    title: `确认应用${record.id}为默认的ES_User？`,\n                    onOk: async () => {\n                      await setDefaultDisplay(params.id, record.id);\n                      message.success(\"操作成功\");\n                      getData();\n                    },\n                  })\n                }\n              />\n            </div>\n          );\n        },\n      },\n      {\n        title: \"操作\",\n        dataIndex: \"operation\",\n        filterTitle: true,\n        key: \"operation\",\n        width: 120,\n        render: (text: string, record: any) => {\n          const btns = [\n            {\n              clickFunc: async () => {\n                onClickAddOrEdit(\"edit\", record);\n              },\n              label: \"编辑\",\n            },\n            {\n              clickFunc: () => {\n                if (list.length === 1) {\n                  return;\n                }\n                Modal.confirm({\n                  title: `确认删除ES_User ${record.id}？`,\n                  content: <span style={{ color: \"red\" }}>请确认影响后再进行删除操作！</span>,\n                  onOk: () => {\n                    deleteOneAppByProjectId(params.id, record.id).then((res) => {\n                      message.success(\"删除成功\");\n                      getData();\n                    });\n                  },\n                });\n              },\n              label:\n                list.length === 1 ? (\n                  <Tooltip title=\"至少保留一条ES_User\">\n                    <span style={{ color: \"gray\", cursor: \"not-allowed\" }}>删除</span>\n                  </Tooltip>\n                ) : (\n                  <span>删除</span>\n                ),\n            },\n          ];\n          return renderOperationBtns(btns, record);\n        },\n      },\n    ];\n  };\n\n  const onCancel = () => {\n    props.dispatch(actions.setDrawerId(\"\"));\n  };\n\n  const onSearchTypeChange = (searchType: number) => {\n    setSearchType(searchType);\n    if (searchType === 0 && !clusterList.length) {\n      form.setFieldsValue({ selectCluster: undefined });\n      XNotification({ type: \"error\", message: `该应用下无可用集群，无法新增集群模式的ES_User` });\n      return;\n    } else if (searchType === 2 && !primitiveList.length) {\n      form.setFieldsValue({ selectCluster: undefined });\n      XNotification({ type: \"error\", message: `该应用下无独立类型集群，无法新增原生模式的ES_User` });\n      return;\n    }\n    opType.current === \"add\"\n      ? form.setFieldsValue({ selectCluster: searchType === 0 ? clusterList?.[0]?.value : primitiveList?.[0]?.value || undefined })\n      : form.setFieldsValue({ selectCluster: currentRecord?.current?.cluster || undefined });\n  };\n\n  const onClickAddOrEdit = (type: string, record?: any) => {\n    opType.current = type;\n    currentRecord.current = record || {};\n    if (type === \"edit\") {\n      form.setFieldsValue({\n        searchType: record?.searchType,\n        selectCluster: record?.cluster || clusterList?.[0]?.value || undefined,\n        queryThreshold: record?.queryThreshold || undefined,\n      });\n      setSearchType(record?.searchType);\n    } else {\n      form.setFieldsValue({\n        searchType: 1,\n        queryThreshold: \"100\",\n      });\n      setSearchType(1);\n    }\n    setModalVisible(!modalVisible);\n  };\n\n  const onModalSubmit = (result) => {\n    if (opType.current === \"edit\") {\n      updateAppByProjectId({\n        projectId: params.id,\n        id: currentRecord.current.id,\n        searchType: result.searchType,\n        queryThreshold: result.queryThreshold,\n        cluster: searchType !== 1 ? result.selectCluster : undefined,\n      }).then((res) => {\n        getData();\n      });\n    } else {\n      createAppByProjectId(params.id, {\n        searchType: result.searchType,\n        queryThreshold: result.queryThreshold,\n        cluster: searchType !== 1 ? result.selectCluster : undefined,\n      }).then(() => {\n        getData();\n      });\n    }\n    setModalVisible(!modalVisible);\n  };\n\n  return (\n    <>\n      <Drawer onClose={onCancel} width={800} visible={true} title=\"访问设置\">\n        <div className=\"add-esuser\">\n          <Button onClick={() => onClickAddOrEdit(\"add\")} type=\"primary\">\n            新建ES_User\n          </Button>\n        </div>\n        <Table rowKey=\"id\" columns={getColumns(list)} dataSource={list} scroll={{ x: \"max-content\" }} />\n      </Drawer>\n      {modalVisible && (\n        <Modal\n          title={opType.current === \"edit\" ? \"编辑ES_User\" : \"新建ES_User\"}\n          visible={modalVisible}\n          className=\"esuser-modal\"\n          footer=\"\"\n          onCancel={() => setModalVisible(!modalVisible)}\n          destroyOnClose\n        >\n          <Form labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} form={form} onFinish={onModalSubmit}>\n            <Form.Item name=\"searchType\" label=\"访问模式\">\n              <Select\n                showSearch\n                filterOption={filterOption}\n                placeholder=\"请选择\"\n                options={searchTypeOptions}\n                onChange={onSearchTypeChange}\n              ></Select>\n            </Form.Item>\n            {searchType !== 1 && (\n              <Form.Item name=\"selectCluster\" label=\"访问集群\">\n                <Select\n                  showSearch\n                  filterOption={filterOption}\n                  placeholder=\"请选择\"\n                  options={searchType === 0 ? clusterList : primitiveList}\n                ></Select>\n              </Form.Item>\n            )}\n            <div className=\"query-threshold\">\n              <Form.Item\n                name=\"queryThreshold\"\n                label=\"查询限流值\"\n                rules={[\n                  { required: true, message: \"请输入查询限流值，支持1-16个数字字符\" },\n                  {\n                    validator: (rule: any, value: string) => {\n                      if ((value && !new RegExp(regNonnegativeInteger).test(value)) || value?.length > 16) {\n                        return Promise.reject(new Error(\"请输入查询限流值，支持1-16个数字字符\"));\n                      }\n                      return Promise.resolve();\n                    },\n                  },\n                ]}\n              >\n                <Input placeholder=\"请输入\" />\n              </Form.Item>\n              <span className=\"unit\">次/s</span>\n            </div>\n            <div className=\"footer\">\n              <Form.Item>\n                <Button className=\"cancel\" onClick={() => setModalVisible(!modalVisible)}>\n                  取消\n                </Button>\n                <Button type=\"primary\" htmlType=\"submit\">\n                  确定\n                </Button>\n              </Form.Item>\n            </div>\n          </Form>\n        </Modal>\n      )}\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(AccessSetting);\n"
  },
  {
    "path": "arius-console/src/container/modal/project/add-project.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"../../../actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { Transfer } from \"antd\";\nimport { useGlobalLoginStatus } from \"store\";\nimport { getUserList } from \"api/logi-security\";\nimport { createProject, getUnassignedUsers, updateProject, updateOwner, updateUser } from \"api/app-api\";\nimport { UserSelect } from \"component/UserSelect\";\nimport { getCookie } from \"lib/utils\";\nimport \"./index.less\";\nimport Tooltip from \"antd/es/tooltip\";\n\ninterface ITaskValue {\n  taskName: string;\n  sinkType: string;\n  sourceType: string;\n  taskDesc: string;\n  owners: string[];\n  quota: number;\n}\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nconst UserTransfer = (props: any) => {\n  const { value, list, isNew, onChange, userListWithAdminRole } = props;\n\n  const [targetKeys, setTargetKeys] = React.useState(value || []);\n  const [dataSource, setDataSource] = React.useState(list || []);\n  const filterOption = (inputValue: any, option: any) => option?.text?.indexOf(inputValue) > -1;\n\n  React.useEffect(() => {\n    if (isNew) {\n      let adminIdList = (userListWithAdminRole || []).map((item) => item?.id);\n      let initList = [+getCookie(\"userId\")];\n      if (getCookie(\"isAdminUser\") === \"yes\") {\n        initList = [...initList, ...adminIdList];\n      }\n      setTargetKeys(initList);\n      onChange(initList);\n      getDataSource();\n    }\n  }, [userListWithAdminRole]);\n\n  React.useEffect(() => {\n    getDataSource();\n  }, [list, targetKeys]);\n\n  const getDataSource = () => {\n    let dataSource = (list || []).map((item) => {\n      if (targetKeys.includes(item?.key)) {\n        let adminIdList = (userListWithAdminRole || []).map((item) => item?.id);\n        if (adminIdList.includes(item?.key)) {\n          return {\n            ...item,\n            disabled: true,\n            label: <Tooltip title=\"管理员角色用户，不可删除！\">{item.label}</Tooltip>,\n            text: item.label,\n          };\n        } else {\n          return { ...item, text: item.label };\n        }\n      } else {\n        return { ...item, text: item.label };\n      }\n    });\n    setDataSource(dataSource);\n  };\n\n  const handleChange = (targetKeys: any) => {\n    setTargetKeys(targetKeys);\n    // tslint:disable-next-line:no-unused-expression\n    onChange && onChange(targetKeys);\n  };\n\n  return (\n    <Transfer\n      dataSource={dataSource}\n      showSearch={true}\n      filterOption={filterOption}\n      titles={[\"未分配用户\", \"已分配用户\"]}\n      targetKeys={targetKeys}\n      onChange={handleChange}\n      render={(item) => item.label}\n      listStyle={{ width: 290 }}\n    />\n  );\n};\n\nconst AddOrEditProjectModal = (props: { dispatch: any; cb: any; params: any }) => {\n  const { params = {}, cb } = props;\n  const { type, callback, ownersList, usersList } = params || {};\n  const [loginStatus, setLoginStatus] = useGlobalLoginStatus();\n  const [list, setList] = useState(usersList);\n  const [targetKeys, setTargetKeys] = useState(params?.userIdList || []);\n  const [ownerIdList, setOwnerIdList] = useState([]);\n  const [userListWithAdminRole, setUserListWithAdminRole] = useState([]);\n\n  const fetchOptions = (value, size = 100) => {\n    let params = {\n      userName: value,\n      page: 1,\n      size,\n    } as any;\n    let isAdmin = getCookie(\"isAdminUser\") === \"yes\";\n    if (!isAdmin) {\n      params.containsAdminRole = false;\n    }\n    return getUserList(params)\n      .then((res) => {\n        return res?.bizData || [];\n      })\n      .catch((err) => {\n        return [];\n      });\n  };\n\n  const getInitUserList = () => {\n    if (!params || type === \"create\") {\n      // 如果是新建项目调用全量用户接口\n      fetchOptions(\"\", type === \"create\" ? 100 : 1000).then((res) => {\n        const data = (res || []).map((item) => ({\n          label: item.userName,\n          value: item.id,\n          title: item.id,\n          key: item.id,\n        }));\n        setList(data);\n        setUserListWithAdminRole(res?.[0]?.userListWithAdminRole || []);\n      });\n    } else {\n      // 如果是编辑项目调用未分配用户接口\n      getUnassignedUsers(params.id).then((res) => {\n        res = (res || []).map((item) => {\n          return {\n            label: item.userName,\n            title: item.id,\n            key: item.id,\n          };\n        });\n        setList([...list, ...res]);\n      });\n    }\n  };\n\n  useEffect(() => {\n    getInitUserList();\n  }, []);\n\n  const addProject = async (values) => {\n    return createProject({\n      project: {\n        deptId: 0, // TODO: 后端接口待确认\n        ...values,\n        userIdList: values?.userIdList || [],\n      },\n      config: {\n        memo: values.description,\n        slowQueryTimes: +values.slowQueryTimes,\n      },\n    });\n  };\n\n  const editProject = async (values) => {\n    let adminIdList = (params?.userListWithAdminRole || []).map((item) => item.id);\n    let userList = (targetKeys || []).filter((item) => !adminIdList.includes(item));\n\n    let project = {\n      deptId: 0,\n      id: params.id,\n      description: values.description,\n      projectName: values.projectName,\n      slowQueryTimes: values.slowQueryTimes,\n    };\n\n    await updateOwner(params?.id, ownerIdList);\n    await updateUser(params?.id, userList);\n    return updateProject({\n      project,\n      config: {\n        memo: values.description,\n        slowQueryTimes: +values.slowQueryTimes,\n      },\n    });\n  };\n\n  const renderFormMap = () => {\n    let formMap = [\n      {\n        key: \"tips\",\n        type: FormItemType.custom,\n        customFormItem: (\n          <div className=\"project-tips\">\n            <svg className=\"icon svg-icon svg-style\" aria-hidden=\"true\">\n              <use xlinkHref=\"#iconinfo-circle\"></use>\n            </svg>\n            SuperApp无需分配用户，管理员角色的用户默认加入到SuperApp中\n          </div>\n        ),\n      },\n      {\n        key: \"projectName\",\n        label: \"应用名称\",\n        attrs: {\n          placeholder: \"请输入应用名称\",\n        },\n        rules: [\n          {\n            required: true,\n            whitespace: true,\n            validator: (rule: any, value: string) => {\n              const reg = /^[a-zA-Z0-9\\u4e00-\\u9fa5][a-zA-Z0-9_\\-\\u4e00-\\u9fa5]+$/;\n\n              if (!value) {\n                return Promise.reject(\"请输入应用名称\");\n              }\n              if (value && (value.length > 30 || value.length < 8)) {\n                return Promise.reject(\"请输入8-30字符\");\n              }\n              if (!reg.test(value)) {\n                return Promise.reject(\"应用名称不能以_、-为前缀， 支持中文、英文、数字、-、_，8-30位字符\");\n              } else {\n                return Promise.resolve();\n              }\n            },\n          },\n        ],\n      },\n      {\n        key: \"ownerIdList\",\n        label: \"责任人\",\n        type: FormItemType.custom,\n        defaultValue: [+getCookie(\"userId\")],\n        customFormItem: (\n          <UserSelect\n            targetKeys={targetKeys}\n            list={list}\n            ownersList={ownersList}\n            isNew={!params || type === \"create\"}\n            fetchOptions={fetchOptions}\n            setOwnerIdList={setOwnerIdList}\n            mode=\"multiple\"\n            placeholder=\"请选择责任人\"\n          />\n        ),\n        rules: [\n          {\n            required: true,\n            message: \"请选择责任人\",\n            validator: (rule: any, value: any) => {\n             if (!ownerIdList.length) return Promise.reject('请选择责任人')\n             return Promise.resolve()\n            },\n          },\n        ],\n      },\n      {\n        key: \"userIdList\",\n        type: FormItemType.custom,\n        label: \"用户分配\",\n        invisible: type === \"create\",\n        customFormItem: (\n          <UserTransfer\n            list={list}\n            isNew={!params || type === \"create\"}\n            userListWithAdminRole={params?.userListWithAdminRole || userListWithAdminRole}\n            fetchOptions={(value) => fetchOptions(value, 2000)}\n            onChange={(key) => {\n              setTargetKeys(key);\n            }}\n          />\n        ),\n      },\n      {\n        key: \"slowQueryTimes\",\n        type: FormItemType.input,\n        label: \"慢查询耗时\",\n        rules: [\n          {\n            required: true,\n            whitespace: true,\n            validator: (rule: any, value: string) => {\n              const reg = /^[1-9]\\d*$/;\n              if (!reg.test(value)) {\n                return Promise.reject(\"请输入非0正整数\");\n              } else if (+value > 1000000) {\n                return Promise.reject(\"请输入小于1000000的正整数\");\n              } else {\n                return Promise.resolve();\n              }\n            },\n          },\n        ],\n        attrs: {\n          placeholder: \"请输入慢查询耗时\",\n          suffix: <span> ms</span>,\n        },\n      },\n      {\n        key: \"description\",\n        type: FormItemType.textArea,\n        label: \"备注\",\n        rules: [\n          {\n            required: true,\n            whitespace: true,\n            validator: (rule: any, value: string) => {\n              if (!value) {\n                return Promise.reject(\"请输入1-100字备注\");\n              }\n              if (value && value.length > 100) {\n                return Promise.reject(\"请输入1-100字备注\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n        attrs: {\n          placeholder: \"请输入1-100字备注\",\n        },\n      },\n    ] as IFormItem[];\n    if (params?.projectName === \"SuperApp\") {\n      formMap.splice(3, 1);\n    } else {\n      formMap = formMap.slice(1);\n    }\n    return { formMap };\n  };\n\n  const xFormModalConfig = {\n    visible: true,\n    title: type === \"create\" ? \"创建应用\" : props.params ? \"编辑应用\" : \"新建应用\",\n    formData: { slowQueryTimes: 1000, ...props.params } || { slowQueryTimes: 1000 },\n    isWaitting: true,\n    width: 660,\n    onChangeVisible: () => {\n      props.dispatch(actions.setDrawerId(\"\"));\n    },\n    onCancel: () => {\n      if (type === \"create\") {\n        callback();\n      }\n    },\n    onSubmit: (value: ITaskValue) => {\n      if (!params || type === \"create\") {\n        return addProject(value);\n      }\n      if (params) {\n        return editProject(value);\n      }\n    },\n    actionAfterSubmit: () => {\n      if (type === \"create\") {\n        return setLoginStatus(!loginStatus);\n      }\n      cb && cb();\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper visible={true} type=\"drawer\" {...xFormModalConfig} {...renderFormMap()} />\n    </>\n  );\n};\n\nexport default connect(mapStateToProps)(AddOrEditProjectModal);\n"
  },
  {
    "path": "arius-console/src/container/modal/project/delete-project.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { Modal, message } from \"antd\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { InfoCircleOutlined } from \"@ant-design/icons\";\nimport { checkResources, deleteProject } from \"api\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const DeleteProject = connect(mapStateToProps)((props: { dispatch: any; params: any; cb: any }) => {\n  const { params, dispatch, cb } = props;\n  const [loading, setLoading] = useState(false);\n  const [visible, setVisible] = useState(false);\n\n  useEffect(() => {\n    _checkResources();\n  }, []);\n\n  const _checkResources = async () => {\n    try {\n      await checkResources(params?.id);\n      setVisible(true);\n    } catch (err) {\n      dispatch(actions.setModalId(\"\"));\n    }\n  };\n\n  return (\n    <>\n      <Modal\n        visible={visible}\n        title={\"删除应用\"}\n        centered\n        maskClosable={false}\n        width={480}\n        okButtonProps={{ loading: loading }}\n        onCancel={() => {\n          dispatch(actions.setModalId(\"\"));\n        }}\n        onOk={async () => {\n          setLoading(true);\n          let { current, pageSize, total } = params?.pagination || {};\n          deleteProject(params.id)\n            .then(() => {\n              message.success(\"删除成功\");\n              let pagination = {\n                pageNo: current,\n                pageSize,\n              };\n              if (current * pageSize - (total - 1) >= 10) {\n                pagination.pageNo = current - 1;\n              }\n              cb(pagination);\n              dispatch(actions.setModalId(\"\"));\n            })\n            .finally(() => {\n              setLoading(false);\n            });\n        }}\n      >\n        <div>\n          <div className=\"delete-modal-content\">\n            <div className=\"delete-modal-content-left2\">\n              <InfoCircleOutlined className=\"delete-modal-content-left-icon\" />\n            </div>\n            <div className=\"delete-modal-content-right2\">\n              <p className=\"delete-modal-content-right-p1\">确认删除应用{params.projectName}？</p>\n              <p>删除后会同步下线掉关联的全部ES_User，请确认影响后再进行删除操作!</p>\n            </div>\n          </div>\n        </div>\n      </Modal>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/project/index.less",
    "content": ".add-esuser {\n  text-align: right;\n  margin: 20px 0;\n}\n\n.project-tips {\n  height: 32px;\n  background: #eff4ff;\n  border-radius: 4px;\n  padding: 6px;\n  color: #041d66;\n  .icon {\n    font-size: 14px;\n    margin-right: 5px;\n  }\n}\n\n.esuser-modal {\n  .query-threshold {\n    position: relative;\n    .unit {\n      position: absolute;\n      top: 6px;\n      right: 45px;\n    }\n  }\n  .footer {\n    width: 520px;\n    height: 46px;\n    position: relative;\n    left: -24px;\n    padding: 19px 24px 0 24px;\n    border-top: 1px solid #f0f0f0;\n    background: #fff;\n    .ant-form-item {\n      margin-bottom: 0;\n      .ant-form-item-control-input {\n        width: 472px;\n        .ant-form-item-control-input-content {\n          position: absolute;\n          right: 0;\n          .ant-btn {\n            font-size: 14px;\n            line-height: 18px;\n          }\n          .cancel {\n            margin-right: 8px;\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/project/resources-associated.tsx",
    "content": "import * as React from 'react';\nimport { XFormWrapper } from 'component/x-form-wrapper';\nimport { connect } from \"react-redux\";\nimport * as actions from '../../../actions';\nimport { FormItemType, IFormItem } from 'component/x-form';\nimport { Cascader } from 'antd';\n\ninterface ITaskValue {\n  taskName: string;\n  sinkType: string;\n  sourceType: string;\n  taskDesc: string;\n  owners: string[];\n  quota: number;\n}\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\ninterface IProps {\n  onChange?: (e: any) => any;\n  value?: string[];\n}\n\nexport class CustomCascader extends React.Component<IProps> {\n  public state = {\n    data: [\n      {\n        value: 'zhejiang',\n        label: 'Zhejiang',\n        children: [\n          {\n            value: 'hangzhou',\n            label: 'Hangzhou',\n            children: [\n              {\n                value: 'xihu',\n                label: 'West Lake',\n              },\n            ],\n          },\n        ],\n      },\n      {\n        value: 'jiangsu',\n        label: 'Jiangsu',\n        children: [\n          {\n            value: 'nanjing',\n            label: 'Nanjing',\n            children: [\n              {\n                value: 'zhonghuamen',\n                label: 'Zhong Hua Men',\n              },\n            ],\n          },\n        ],\n      },\n    ]\n  };\n\n  public handleChange = (targetKeys: any) => {\n    this.setState({ targetKeys });\n    const { onChange } = this.props;\n    // tslint:disable-next-line:no-unused-expression\n    onChange && onChange(targetKeys);\n  }\n\n  public render() {\n    return (\n      <Cascader options={this.state.data} onChange={this.handleChange} placeholder=\"请选择细分权限\" />\n    );\n  }\n}\n\n\n\nconst ResourcesAssociated = (props: { dispatch: any, cb: Function, params: any }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: 'type',\n        label: '资源类型',\n        type: FormItemType.select,\n        options: [{\n          label: '爸爸1',\n          value: 1,\n        }],\n        rules: [{\n          required: true,\n          message: '请选择',\n        }],\n        attrs: {\n          disabled: props.params,\n          placeholder: '请选择新增的资源类型',\n        }\n      }, {\n        key: 'name',\n        label: '资源名称',\n        type: FormItemType.select,\n        options: [{\n          label: '爸爸1',\n          value: 1,\n        }],\n        rules: [{\n          required: true,\n          message: '请选择',\n        }],\n        attrs: {\n          mode: 'multiple',\n          disabled: props.params,\n          placeholder: '请选择资源所属的项目',\n        }\n      }, {\n        key: 'member',\n        type: FormItemType.custom,\n        label: '细分权限',\n        customFormItem: <CustomCascader />,\n      }\n    ] as IFormItem[],\n    visible: true,\n    title: '关联资源',\n    formData: props.params || {},\n    isWaitting: true,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(''));\n    },\n    onSubmit: (value: ITaskValue) => {\n      props.dispatch(actions.setModalId(''));\n    },\n  };\n  return (\n    <>\n      <XFormWrapper\n        visible={true}\n        {...xFormModalConfig}\n      />\n    </>\n  )\n};\n\nexport default connect(mapStateToProps)(ResourcesAssociated);\n\n"
  },
  {
    "path": "arius-console/src/container/modal/project/transfer-of-resources.tsx",
    "content": "import * as React from 'react';\nimport { XFormWrapper } from 'component/x-form-wrapper';\nimport { connect } from \"react-redux\";\nimport * as actions from '../../../actions';\nimport { FormItemType, IFormItem } from 'component/x-form';\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\ninterface IProps {\n  onChange?: (e: any) => any;\n  value?: string[];\n}\n\n\nconst TransferOfResources = (props: { dispatch: any, cb: Function, params: any }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: 'principal',\n        label: '转让项目名称',\n        type: FormItemType.select,\n        options: [{\n          label: '爸爸1',\n          value: 1,\n        }],\n        rules: [{\n          required: true,\n          message: '请选择转让项目名称',\n        }],\n        attrs: {\n          mode: 'multiple'\n        }\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: '转让资源',\n    formData: {},\n    isWaitting: true,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(''));\n    },\n    onSubmit: (value: any) => {\n      props.dispatch(actions.setModalId(''));\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper\n        visible={true}\n        {...xFormModalConfig}\n      />\n    </>\n  )\n};\n\nexport default connect(mapStateToProps)(TransferOfResources);\n\n"
  },
  {
    "path": "arius-console/src/container/modal/role/add-or-edit-role.tsx",
    "content": "import * as React from 'react';\nimport { XFormWrapper } from 'component/x-form-wrapper';\nimport { connect } from \"react-redux\";\nimport * as actions from '../../../actions';\nimport { FormItemType, IFormItem } from 'component/x-form';\nimport { Transfer } from 'antd';\n\ninterface ITaskValue {\n  taskName: string;\n  sinkType: string;\n  sourceType: string;\n  taskDesc: string;\n  owners: string[];\n  quota: number;\n}\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\ninterface IProps {\n  onChange?: (e: any) => any;\n  value?: string[];\n}\n\nexport class MemberTransfer extends React.Component<IProps> {\n  public state = {\n    mockData: [] as any,\n    targetKeys: [] as any,\n    data: [\n      {\n        key: '1',\n        disabled: false,\n        title: 'yoyo',\n        description: 'ct0',\n      },\n      {\n        key: '2',\n        disabled: false,\n        title: 'yoyo1',\n        description: 'ct2',\n      }\n    ]\n  };\n\n  public filterOption = (inputValue: any, option: any) => option.description.indexOf(inputValue) > -1;\n\n  public handleChange = (targetKeys: any) => {\n    this.setState({ targetKeys });\n    const { onChange } = this.props;\n    // tslint:disable-next-line:no-unused-expression\n    onChange && onChange(targetKeys);\n  }\n\n  public render() {\n    return (\n      <Transfer\n        dataSource={this.state.data}\n        showSearch={true}\n        filterOption={this.filterOption}\n        targetKeys={this.state.targetKeys}\n        onChange={this.handleChange}\n        render={item => item.title}\n      />\n    );\n  }\n}\n\n\n\nconst AddOrEditRole = (props: { dispatch: any, cb: Function, params: any }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: 'role',\n        label: '角色名',\n        attrs: {\n          placeholder: '请输入角色名',\n        },\n        rules: [{\n          required: true,\n          whitespace: true,\n          validator: (rule: any, value: string) => {\n            const reg = /^[a-zA-Z0-9_\\u4e00-\\u9fa5]+$/;\n            if (!reg.test(value)) {\n              return Promise.reject('请输入正确格式');\n            } else {\n              return Promise.resolve();\n            }\n          },\n        }],\n      }, {\n        key: 'description',\n        type: FormItemType.textArea,\n        label: '角色描述',\n        rules: [{\n          whitespace: true,\n          validator: (rule: any, value: string) => {\n            if (value?.trim().length > 0 && value?.trim().length < 50) {\n              return Promise.reject('0-50个字符');\n            } else {\n              return Promise.resolve();\n            }\n          },\n        }],\n        attrs: {\n          placeholder: '请输入该角色描述，0-50字',\n          rows: 2,\n        },\n      }, {\n        key: 'member',\n        type: FormItemType.custom,\n        label: '权限点',\n        customFormItem: <MemberTransfer />,\n      }\n    ] as IFormItem[],\n    visible: true,\n    title: props.params ? '编辑角色' : '新增角色',\n    formData: props.params || {},\n    isWaitting: true,\n    width: 660,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(''));\n    },\n    onSubmit: (value: ITaskValue) => {\n      props.dispatch(actions.setModalId(''));\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper\n        visible={true}\n        {...xFormModalConfig}\n      />\n    </>\n  )\n};\n\nexport default connect(mapStateToProps)(AddOrEditRole);\n\n"
  },
  {
    "path": "arius-console/src/container/modal/sql-query/mapping.tsx",
    "content": "import React, { useState } from \"react\";\nimport { Modal, Form, Select, Spin, Table } from \"knowdesign\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"../../../actions\";\nimport { Dispatch } from \"redux\";\n\nconst FormItem = Form.Item;\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const Mapping = connect(mapStateToProps)((props: { dispatch: Dispatch; params: any; cb: Function }) => {\n  const [originSelectMapJson] = useState(props.params.selectMapJson || []);\n  const [selectMapJson, setSelectMapJson] = useState(props.params.selectMapJson || []);\n  const [mappingJson, setMappingJson] = useState(props.params.mappingJson || []);\n  const [originMappingJson] = useState(props.params.mappingJson || []);\n  const mappingHandleSearch = (value) => {\n    console.log(\"originSelectMapJson\", originSelectMapJson, value);\n    setSelectMapJson(originSelectMapJson.filter((row) => row.value.includes(value)));\n  };\n  const onMappingChange = (value) => {\n    console.log(\"originMappingJson\", originMappingJson, value);\n    setMappingJson(value ? originMappingJson.filter((row) => row.value.includes(value)) : originMappingJson);\n  };\n\n  return (\n    <>\n      <Modal\n        visible={true}\n        title={props.params?.title}\n        width={600}\n        height={440}\n        onCancel={() => props.dispatch(actions.setModalId(\"\"))}\n        footer={null}\n      >\n        <Form>\n          <FormItem key=\"mapping\" name=\"mapping\" label=\"\" className=\"mapping-input\">\n            <Select\n              style={{ width: \"321px\" }}\n              showSearch\n              options={selectMapJson}\n              allowClear\n              placeholder=\"Mapping\"\n              defaultActiveFirstOption={false}\n              filterOption={false}\n              onSearch={mappingHandleSearch}\n              onChange={onMappingChange}\n            />\n          </FormItem>\n        </Form>\n        <div className=\"mapping-tab\">\n          <Spin spinning={props.params.tableLoading}>\n            <Table\n              rowKey=\"name\"\n              dataSource={mappingJson}\n              columns={props.params.columns}\n              scroll={{ y: 225 }}\n              pagination={{\n                simple: true,\n                pageSize: 5,\n                size: \"small\",\n              }}\n            />\n          </Spin>\n        </div>\n      </Modal>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/system/cluster-config.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { XNotification } from \"component/x-notification\";\nimport { IDeploy } from \"typesPath/cluster/physics-type\";\nimport { newDeploy, updateDeploy } from \"api/cluster-api\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const ClusterConfigModal = connect(mapStateToProps)((props: { dispatch: any; params: IDeploy; cb: any }) => {\n  const isEdit = props.params?.id ? true : false;\n  const title = isEdit ? \"编辑\" : \"新增\";\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"valueGroup\",\n        label: \"配置组 \",\n        attrs: {\n          placeholder: \"请填写配置组名称\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: (rule: any, value: string) => {\n              let flat_1_128 = value && value.length > 0 && value.length <= 128;\n              if (!value) {\n                return Promise.reject(\"配置组不能为空\");\n              }\n              if (flat_1_128) {\n                return Promise.resolve();\n              } else {\n                return Promise.reject(\"请输入1-128字符\");\n              }\n            },\n          },\n        ],\n      },\n      {\n        key: \"valueName\",\n        label: \"名称\",\n        attrs: {\n          placeholder: \"请填写名称\",\n        },\n        rules: [\n          {\n            required: true,\n            validator: (rule: any, value: string) => {\n              let flat_1_50 = value && value.length > 0 && value.length <= 100;\n              if (!value) {\n                return Promise.reject(\"名称不能为空\");\n              }\n              if (flat_1_50) {\n                return Promise.resolve();\n              } else {\n                return Promise.reject(\"请输入1-100字符\");\n              }\n            },\n          },\n        ],\n      },\n      {\n        key: \"value\",\n        label: \"值\",\n        type: FormItemType.textArea,\n        rules: [\n          {\n            required: false,\n            validator: (rule: any, value: string) => {\n              if (!value) {\n                return Promise.resolve();\n              }\n              let flat_0_100 = value.length >= 0 && value.length <= 1000;\n              if (flat_0_100) {\n                return Promise.resolve();\n              } else {\n                return Promise.reject(\"请输入0-1000个字符\");\n              }\n            },\n          },\n        ],\n        attrs: {\n          placeholder: `请填写值`,\n          rows: 4,\n        },\n      },\n      {\n        key: \"memo\",\n        label: \"描述\",\n        type: FormItemType.textArea,\n        rules: [\n          {\n            required: false,\n            validator: (rule: any, value: string) => {\n              if (!value) {\n                return Promise.resolve();\n              } else if (value?.trim().length > 100) {\n                return Promise.reject(\"请输入0-100个字符\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n        attrs: {\n          placeholder: `请输入描述信息`,\n          rows: 4,\n        },\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: `${title}配置`,\n    formData: props.params || {},\n    needBtnLoading: true,\n    width: 660,\n    className: \"cluster-config\",\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      if (isEdit) {\n        result.id = props.params?.id;\n        result.status = props.params?.status;\n      } else {\n        result.status = 1;\n      }\n      const submitFn = isEdit ? updateDeploy : newDeploy;\n      return submitFn(result).then(() => {\n        XNotification({ type: \"success\", message: `${title}配置成功` });\n        props.dispatch(actions.setModalId(\"\"));\n        props.cb && props.cb();\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper visible={true} {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/system/index.less",
    "content": ".cluster-config {\n  &.dcloud-modal {\n    top: 120px;\n  }\n  .ant-modal-body {\n    padding: 0 24px 24px 24px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/template/DCDR-detail.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { message, Button, Modal } from \"knowdesign\";\nimport { getDCDRDetail, deleteDCDR } from \"api/cluster-index-api\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const DCDRDetail = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: number }) => {\n  const [detail, setDetail] = React.useState({} as any);\n\n  React.useEffect(() => {\n    getDCDRDetail(props.params)\n      .then((res = {}) => {\n        setDetail(res?.data || {});\n      })\n      .catch((res = {}) => {\n        setDetail(res?.data || {});\n      });\n  }, []);\n\n  const goDeleteDCDR = () => {\n    Modal.confirm({\n      title: \"提示\",\n      content: \"确定删除DCDR链路吗?\",\n      onOk: () => {\n        deleteDCDR(props.params).then(() => {\n          message.success(`操作成功`);\n          props.dispatch(actions.setDrawerId(\"\"));\n          props.cb && props.cb(); // 重新获取数据列表\n        });\n      },\n    });\n  };\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"masterClusterName\",\n        label: \"集群\",\n        type: FormItemType.custom,\n        customFormItem: detail.masterClusterName || \"-\",\n      },\n      {\n        key: \"slaveClusterName\",\n        label: \"从集群\",\n        type: FormItemType.custom,\n        customFormItem: detail.slaveClusterName || \"-\",\n      },\n      {\n        key: \"templateCheckPointDiff\",\n        label: \"主从位点差\",\n        type: FormItemType.custom,\n        customFormItem: detail.templateCheckPointDiff || detail.templateCheckPointDiff === 0 ? detail.templateCheckPointDiff : \"-\",\n      },\n      {\n        key: \"deleteDCDR\",\n        label: \"\",\n        type: FormItemType.custom,\n        customFormItem: (\n          <Button danger onClick={goDeleteDCDR}>\n            删除链路\n          </Button>\n        ),\n        formAttrs: {\n          style: {\n            position: \"absolute\",\n            bottom: \"-6px\",\n            left: \"170px\",\n          },\n        },\n      },\n    ] as IFormItem[],\n    type: \"drawer\",\n    visible: true,\n    title: \"DCDR链路\",\n    width: 500,\n    layout: \"horizontal\",\n    onCancel: () => {\n      props.dispatch(actions.setDrawerId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      props.dispatch(actions.setDrawerId(\"\"));\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/template/batch-update.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { message, Tooltip } from \"antd\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { updateTemplateSrv } from \"api/cluster-index-api\";\nimport { CodeType } from \"constants/common\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const BatchUpdate = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const { code, datas } = props.params;\n  const [status, setStatus] = React.useState(true);\n  const ids = [];\n  let label: string | React.ReactNode;\n\n  datas.forEach((item) => {\n    const unavailableSrv = item.unavailableSrv?.find((srv) => srv.srvCode === code);\n    if (!unavailableSrv) {\n      ids.push({\n        name: item.name,\n        id: item.id,\n        expireTime: item.expireTime,\n      });\n    }\n  });\n  const expireTimes = ids.map((item) => (item.expireTime !== -1 ? item.expireTime : null)).sort();\n\n  switch (code) {\n    case CodeType.PreCreate:\n      label = `预创建`;\n      break;\n    case CodeType.Delete:\n      label = `过期删除`;\n      break;\n    case CodeType.Separate:\n      label = `冷热分离`;\n      break;\n    case CodeType.Pipeline:\n      label = `pipeline`;\n      break;\n    case CodeType.Rollover:\n      label = (\n        <div className=\"rollover-title\">\n          <span className=\"title\">Rollover</span>\n          <Tooltip title={\"开启后会影响索引Update和Delete能力以及指定id写入、更新、删除\"}>\n            <span className=\"icon iconfont iconinfo\"></span>\n          </Tooltip>\n        </div>\n      );\n      break;\n    default:\n      break;\n  }\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"status\",\n        label: label,\n        type: FormItemType._switch,\n        attrs: {\n          onChange: (value) => {\n            setStatus(value);\n          },\n        },\n        formAttrs: {\n          style: {\n            marginTop: 0,\n          },\n        },\n      },\n      {\n        key: \"ids\",\n        label: \"操作对象\",\n        type: FormItemType.custom,\n        customFormItem: (\n          <div className=\"btn-labels-box\">\n            {ids.length\n              ? ids.map((item) => (\n                  <div className=\"btn-labels\" key={item.id}>\n                    {item.name}\n                  </div>\n                ))\n              : \"-\"}\n          </div>\n        ),\n      },\n      {\n        key: \"coldSaveDays\",\n        label: \"热节点保存天数\",\n        type: FormItemType.inputNumber,\n        invisible: !(code === CodeType.Separate && status),\n        attrs: {\n          placeholder: \"请输入热节点保存天数\",\n          style: {\n            width: \"100%\",\n          },\n        },\n        rules: [\n          {\n            required: true,\n            message: `请输入热节点保存天数（${expireTimes[0] ? \"1-\" + expireTimes[0] : \"1或以上\"}的正整数）`,\n            validator: (rule: any, value: any) => {\n              if (expireTimes[0]) {\n                if (new RegExp(regNonnegativeInteger).test(value) && value > 0 && value <= expireTimes[0]) return Promise.resolve();\n              } else {\n                if (new RegExp(regNonnegativeInteger).test(value) && value > 0) return Promise.resolve();\n              }\n              return Promise.reject();\n            },\n          },\n        ],\n      },\n    ] as IFormItem[],\n    formData: {\n      status: status,\n    },\n    visible: true,\n    title: \"批量操作\",\n    needBtnLoading: true,\n    width: 500,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      if (!ids.length) {\n        props.dispatch(actions.setModalId(\"\"));\n        return;\n      }\n      const params = {\n        srvCode: code,\n        templateIdList: ids.map((item) => item.id),\n      } as any;\n      if (code === CodeType.Separate && result.status) {\n        params.params = {};\n        params.params.coldSaveDays = result.coldSaveDays;\n      }\n      return updateTemplateSrv(params, result.status ? \"PUT\" : \"DELETE\").then(() => {\n        message.success(`操作成功`);\n        props.dispatch(actions.setModalId(\"\"));\n        props.cb && props.cb(); // 重新获取数据列表\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/template/clear.tsx",
    "content": "import * as React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport Url from \"lib/url-parser\";\nimport { IUNSpecificInfo } from \"typesPath/base-types\";\nimport { message } from \"antd\";\nimport { Drawer, Table, Space, Divider, Modal, Button } from \"knowdesign\";\nimport { CloseCircleFilled } from \"@ant-design/icons\";\nimport { getClearInfo, clearIndex } from \"api/cluster-index-api\";\nimport { CONFIRM_BUTTON_TEXT } from \"constants/common\";\n\nconst { confirm } = Modal;\n\nconst mapStateToProps = (state: any) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nconst connects: any = connect;\n\n@connects(mapStateToProps)\nexport class ClearModal extends React.Component<any, any> {\n  public state = {\n    searchKey: \"\",\n    clearInfo: {} as IUNSpecificInfo,\n    login: false,\n    clearInfoSelectedRowKeys: [] as string[],\n  };\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n  }\n\n  public componentDidMount() {\n    this.reloadData();\n  }\n\n  public reloadData = () => {\n    this.setState({ loading: true });\n    getClearInfo(this.props.params)\n      .then((value = {}) => {\n        this.setState({\n          clearInfo: value,\n        });\n      })\n      .finally(() => {\n        this.setState({ loading: false });\n      });\n  };\n\n  public getData = (origin?: IUNSpecificInfo[]) => {\n    origin = (origin || []).map((item) => {\n      return {\n        name: item,\n      };\n    });\n    let { searchKey } = this.state;\n    searchKey = (searchKey + \"\").trim().toLowerCase();\n    const data = searchKey ? origin.filter((d) => d.name?.toLowerCase().includes(searchKey as string)) : origin;\n    return data;\n  };\n\n  public getColumns = () => {\n    const cols = [\n      {\n        title: \"索引列表\",\n        dataIndex: \"index\",\n      },\n      {\n        title: \"存储大小\",\n        dataIndex: \"priStoreSize\",\n        width: \"100px\",\n      },\n    ];\n    return cols;\n  };\n\n  public handleSubmit = () => {\n    if (!this.state.clearInfoSelectedRowKeys?.length) {\n      message.warning(\"请先选择需清理的索引\");\n      return;\n    }\n    confirm({\n      ...CONFIRM_BUTTON_TEXT,\n      title: `索引数据清理后数据无法恢复，确认要清理吗？`,\n      icon: <CloseCircleFilled className=\"confirm-delete-icon\" />,\n      onOk: () => {\n        clearIndex(this.props.params, this.state.clearInfoSelectedRowKeys).then(() => {\n          message.success(\"清理成功\");\n          this.props.dispatch(actions.setDrawerId(\"\"));\n          this.props.cb && this.props.cb(); // 重新获取数据列表\n        });\n      },\n    });\n  };\n\n  public handleCancel = () => {\n    this.setState({\n      relatedAppList: [],\n    });\n    this.props.dispatch(actions.setDrawerId(\"\"));\n  };\n\n  public onSelectChange = (selectedRowKeys: string[]) => {\n    this.setState({\n      clearInfoSelectedRowKeys: selectedRowKeys,\n    });\n  };\n\n  public renderTable = () => {\n    const rowSelection = {\n      selectedRowKeys: this.state.clearInfoSelectedRowKeys,\n      onChange: this.onSelectChange,\n    };\n    return (\n      <Table\n        scroll={{ x: \"max-content\", y: 300 }}\n        loading={this.state.login}\n        rowKey=\"index\"\n        dataSource={this.state.clearInfo.indices}\n        columns={this.getColumns()}\n        pagination={false}\n        rowSelection={rowSelection}\n      />\n    );\n  };\n\n  public render() {\n    return (\n      <>\n        <Drawer\n          title=\"清理\"\n          visible={true}\n          width={480}\n          closable={true}\n          maskClosable={false}\n          destroyOnClose={true}\n          onClose={this.handleCancel}\n          extra={\n            <Space>\n              <Button onClick={this.handleCancel}>取消</Button>\n              <Button type=\"primary\" onClick={this.handleSubmit}>\n                清理\n              </Button>\n              <Divider type=\"vertical\" />\n            </Space>\n          }\n        >\n          {this.renderTable()}\n        </Drawer>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/template/create-DCDR.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { message } from \"antd\";\nimport { getDCDRCluster, getDCDRRegion, createDCDR } from \"api/cluster-index-api\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const CreateDCDR = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const [clusterList, setClusterList] = React.useState([]);\n  const [regionList, setRegionList] = React.useState([]);\n  const $ref: any = React.createRef();\n\n  React.useEffect(() => {\n    getDCDRCluster(props.params).then((res) => {\n      setClusterList(\n        res?.map((item) => ({\n          label: item,\n          value: item,\n        }))\n      );\n    });\n  }, []);\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"targetCluster\",\n        label: \"从集群\",\n        type: FormItemType.select,\n        attrs: {\n          placeholder: \"请选择\",\n          onChange: (value) => {\n            getDCDRRegion(value).then((res) => {\n              $ref?.current?.form.setFieldsValue({ regionId: undefined });\n              setRegionList(\n                res?.map((item) => ({\n                  label: item.name,\n                  value: item.id,\n                }))\n              );\n            });\n          },\n        },\n        rules: [\n          {\n            required: true,\n            message: \"请选择集群\",\n          },\n        ],\n        options: clusterList,\n      },\n      {\n        key: \"regionId\",\n        label: \"Region\",\n        type: FormItemType.select,\n        attrs: {\n          placeholder: \"请选择\",\n        },\n        rules: [\n          {\n            required: true,\n            message: \"请选择Region\",\n          },\n        ],\n        options: regionList,\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"创建DCDR链路\",\n    needBtnLoading: true,\n    width: 500,\n    needSuccessMessage: false,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      const params = {\n        templateId: props.params,\n        ...result,\n      };\n      return createDCDR(params).then(() => {\n        message.success(`链路创建操作提交成功，任务异步执行`);\n        props.dispatch(actions.setModalId(\"\"));\n        props.cb && props.cb(); // 重新获取数据列表\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper ref={$ref} {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/template/dcdr-timeout.tsx",
    "content": "import * as React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { Modal, Form, Input, Button, Tooltip } from \"antd\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const DcdrTimeout = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const { onSubmit, type, opend } = props.params;\n  const [form] = Form.useForm();\n\n  const onModalSubmit = async (result) => {\n    await onSubmit(type, opend, +result.timeout);\n    props.dispatch(actions.setModalId(\"\"));\n  };\n\n  return (\n    <Modal\n      visible={true}\n      className=\"timeout-modal\"\n      footer=\"\"\n      onCancel={() => props.dispatch(actions.setModalId(\"\"))}\n      width={400}\n      destroyOnClose\n    >\n      <Form labelCol={{ span: 8 }} wrapperCol={{ span: 15 }} form={form} onFinish={onModalSubmit}>\n        <div className=\"timeout-container\">\n          <Form.Item\n            name=\"timeout\"\n            label={\n              <div className=\"timeout-title\">\n                <Tooltip title={\"数据一致性校验超时时间\"}>\n                  <span className=\"icon iconfont iconinfo\"></span>\n                </Tooltip>\n                <span className=\"title\">切换超时时间</span>\n              </div>\n            }\n            initialValue=\"100\"\n            rules={[\n              { required: true, message: \"请输入切换超时时间，限制数字类型，1-32位字符\" },\n              {\n                validator: (rule: any, value: string) => {\n                  if ((value && !new RegExp(regNonnegativeInteger).test(value)) || value?.length > 32) {\n                    return Promise.reject(new Error(\"请输入切换超时时间，限制数字类型，1-32位字符\"));\n                  }\n                  return Promise.resolve();\n                },\n              },\n            ]}\n          >\n            <Input placeholder=\"请输入切换超时时间，限制数字类型，1-32位字符\" />\n          </Form.Item>\n          <span className=\"unit\">s</span>\n        </div>\n        <div className=\"footer\">\n          <Form.Item>\n            <Button className=\"cancel\" onClick={() => props.dispatch(actions.setModalId(\"\"))}>\n              取消\n            </Button>\n            <Button type=\"primary\" htmlType=\"submit\">\n              确定\n            </Button>\n          </Form.Item>\n        </div>\n      </Form>\n    </Modal>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/template/expand-shrink-capacity.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { getTemplateIndexDetail, updateShard } from \"api/cluster-index-api\";\nimport { IOpTemplateIndexDetail } from \"typesPath/index-types\";\nimport { XNotification } from \"component/x-notification\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const ExpandShrinkCapacity = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const [formData, setFormData]: any = React.useState({});\n\n  React.useEffect(() => {\n    getTemplateIndexDetail(props.params.id).then((data: IOpTemplateIndexDetail[]) => {\n      setFormData({ shard: data[0]?.shard });\n    });\n  }, []);\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"shard\",\n        label: \"shard个数\",\n        type: FormItemType.inputNumber,\n        attrs: {\n          placeholder: \"请输入shard个数\",\n          style: {\n            width: \"100%\",\n          },\n        },\n        rules: [\n          {\n            required: true,\n            message: \"请输入shard个数（正整数）\",\n            validator: (rule: any, value: any) => {\n              if (new RegExp(regNonnegativeInteger).test(value) && value > 0) return Promise.resolve();\n              return Promise.reject();\n            },\n          },\n        ],\n        formAttrs: {\n          style: {\n            marginTop: 0,\n          },\n        },\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"扩缩容\",\n    needBtnLoading: true,\n    width: 400,\n    formData: formData,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      return updateShard(props.params.id, result.shard).then(() => {\n        XNotification({ type: \"success\", message: `扩缩容成功` });\n        props.dispatch(actions.setModalId(\"\"));\n        props.cb && props.cb(); // 重新获取数据列表\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/template/index.less",
    "content": ".rollover-title {\n  .iconinfo {\n    font-size: 14px;\n    margin-left: 5px;\n    color: #8c8c8c;\n    position: relative;\n    bottom: 1px;\n  }\n}\n\n.timeout-modal {\n  .timeout-container {\n    position: relative;\n    padding-top: 20px;\n    .unit {\n      position: absolute;\n      right: 5px;\n      top: 25px;\n    }\n    .timeout-title {\n      .iconinfo {\n        font-size: 14px;\n        margin-right: 5px;\n        color: rgb(140, 140, 140);\n        position: relative;\n        bottom: 1px;\n      }\n    }\n  }\n  .footer {\n    width: 400px;\n    position: relative;\n    left: -24px;\n    padding: 0 24px 0 24px;\n    background: #fff;\n    height: 35px;\n    .ant-form-item {\n      width: 350px;\n      display: inline-block;\n      position: relative;\n      .ant-form-item-control {\n        display: inline-block;\n        position: absolute;\n        right: 0;\n        .ant-btn {\n          font-size: 14px;\n          line-height: 18px;\n        }\n        .cancel {\n          margin-right: 8px;\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/template/open-separate.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType, IFormItem } from \"component/x-form\";\nimport { message } from \"antd\";\nimport { regNonnegativeInteger } from \"constants/reg\";\nimport { updateTemplateSrv } from \"api/cluster-index-api\";\nimport { CodeType } from \"constants/common\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const OpenSeparate = connect(mapStateToProps)((props: { dispatch: any; cb: Function; params: any }) => {\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"tips\",\n        label: \"\",\n        type: FormItemType.custom,\n        customFormItem: <>确定开启冷热分离能力？请完善热节点保存天数</>,\n        formAttrs: {\n          style: {\n            marginTop: 0,\n          },\n        },\n      },\n      {\n        key: \"coldSaveDays\",\n        label: \"热节点保存天数\",\n        type: FormItemType.inputNumber,\n        attrs: {\n          placeholder: \"请输入热节点保存天数\",\n          style: {\n            width: \"150px\",\n          },\n        },\n        rules: [\n          {\n            required: true,\n            message: `请输入热节点保存天数（${props.params.expireTime !== -1 ? \"1-\" + props.params.expireTime : \"1或以上\"}的正整数）`,\n            validator: (rule: any, value: any) => {\n              if (props.params.expireTime !== -1) {\n                if (new RegExp(regNonnegativeInteger).test(value) && value > 0 && value <= props.params.expireTime)\n                  return Promise.resolve();\n              } else {\n                if (new RegExp(regNonnegativeInteger).test(value) && value > 0) return Promise.resolve();\n              }\n              return Promise.reject();\n            },\n          },\n        ],\n      },\n    ] as IFormItem[],\n    visible: true,\n    title: \"提示\",\n    needBtnLoading: true,\n    width: 500,\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (result: any) => {\n      const params = {\n        srvCode: CodeType.Separate,\n        templateIdList: [props.params.id],\n        params: {\n          coldSaveDays: result.coldSaveDays,\n        },\n      };\n      return updateTemplateSrv(params).then(() => {\n        message.success(`操作成功`);\n        props.dispatch(actions.setModalId(\"\"));\n        props.cb && props.cb(); // 重新获取数据列表\n      });\n    },\n  };\n\n  return (\n    <>\n      <XFormWrapper {...xFormModalConfig} />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/modal/work-order/approval-drawer.tsx",
    "content": "import React, { useState, useEffect, useRef } from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType } from \"component/x-form\";\nimport { approvalOrder } from \"api/order-api\";\nimport { IApprovalOrder, IOrderInfo } from \"typesPath/cluster/order-types\";\nimport { AppState, UserState } from \"store/type\";\nimport { XNotification } from \"component/x-notification\";\nimport { RenderText } from \"container/custom-form\";\nimport RegionTransfer from \"container/custom-form/region-transfer\";\nimport { getRegionNode, getOpPhysicsClusterList, IClusterList } from \"api/cluster-api\";\nimport { logicClusterRegionList } from \"api/op-cluster-region-api\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nexport const ShowApprovalDrawer = connect(mapStateToProps)(\n  (props: { params: IOrderInfo; dispatch: Function; app: AppState; cb: Function; user: UserState }) => {\n    const { id, type, detailInfo, outcome } = props.params;\n\n    const [transferList, setTransferList] = useState([]);\n    const [targetKeys, setTargetKeys] = useState([]); //数据源改变时要进行设置\n    const [leftTargetKeys, setLeftTargetKeys] = useState([]);\n    const [logicRegionList, setLogicRegionList] = useState([]);\n    const [selectKeys, setSelectKeys] = useState([]);\n    const [regionName, setRegionName] = useState(\"\");\n    const selectData = useRef([]);\n    const allData = useRef([]);\n    const $ref: any = useRef();\n\n    useEffect(() => {\n      if (type === \"logicClusterIndecrease\") {\n        //通过逻辑集群id获取逻辑集群下的region列表\n        logicClusterRegionList(detailInfo.logicClusterId)\n          .then((res) => {\n            if (res && res.length) {\n              res = res.map((item) => {\n                return {\n                  ...item,\n                  value: JSON.stringify(item),\n                  label: item.name || item.id,\n                };\n              });\n              setLogicRegionList(res);\n              $ref?.current?.form.setFieldsValue({ RegionList: res[0].value });\n              //通过region里面的物理集群名称获取对应物理集群信息\n              const params: IClusterList = {\n                page: 1,\n                size: 10,\n                cluster: res[0].clusterName,\n              };\n              return getOpPhysicsClusterList(params);\n            }\n          })\n          .then((res) => {\n            if (res && res.bizData.length) {\n              //通过上个接口返回的物理集群id获取物理集群下的ip节点\n              return getRegionNode(res?.bizData[0].id);\n            }\n          })\n          .then((res) => {\n            if (res && res.length) {\n              let arr = [];\n              res = res.map((item) => {\n                return {\n                  ...item,\n                  key: item.id,\n                };\n              });\n              allData.current = JSON.parse(JSON.stringify(res)); //保存穿梭框初始值数据源(静态)\n              const currentSelectObj = $ref?.current?.form && JSON.parse($ref?.current?.form.getFieldsValue().RegionList);\n              //transferList指代ip节点列表\n              res.map((item) => {\n                //过滤出相等的regionid和未分配的region\n                if (item.regionId == currentSelectObj.id) {\n                  arr.push({ ...item });\n                  setRegionName(item.regionName);\n                } else if (item.regionId === -1) {\n                  arr.push({ ...item });\n                }\n              });\n              getTransferData(arr);\n            }\n          });\n      }\n    }, []);\n\n    const getTransferData = (arr) => {\n      let copyArr = JSON.parse(JSON.stringify(arr));\n      let targetTransKey = getTargetTransferList(copyArr);\n      setTargetKeys(targetTransKey);\n      if (detailInfo?.dataNodeNu > detailInfo?.oldDataNodeNu) {\n        // 期望节点数大于原始节点数，扩容，不允许操作右侧原始节点，置灰\n        copyArr = (copyArr || []).map((item) => {\n          if (targetTransKey?.includes(item?.id)) {\n            return {\n              ...item,\n              disabled: true,\n            };\n          }\n          return item;\n        });\n      } else {\n        // 期望节点数小于原始节点数，缩容，不允许操作左侧原始节点，置灰\n        copyArr = (copyArr || []).map((item) => {\n          if (!targetTransKey?.includes(item?.id)) {\n            return {\n              ...item,\n              disabled: true,\n            };\n          }\n          return item;\n        });\n      }\n      setTransferList(copyArr); //change变化的时候需要设置一下数据源（动态）\n      selectData.current = copyArr; //保存当前下拉选中时的数据\n    };\n\n    const getTargetTransferList = (data) => {\n      //过滤出被分配过的ip节点\n      let list = data.filter((item) => item.regionId > -1);\n      let res = list.map((t) => t.key);\n      return res;\n    };\n\n    const xFormModalConfigFun = () => {\n      const formtTemplateIndecreaseMap = [\n        {\n          key: \"clusterName\",\n          label: \"集群名称\",\n          type: FormItemType.text,\n          customFormItem: <RenderText text={props.params.detailInfo.logicClusterName || \"-\"} />,\n        },\n        {\n          key: \"BelongApplication\",\n          label: \"所属应用\",\n          type: FormItemType.text,\n          customFormItem: <RenderText text={props.params.applicantAppName} />,\n        },\n        {\n          key: \"oldDataNodeNu\",\n          label: \"data节点数\",\n          type: FormItemType.text,\n          customFormItem: <RenderText text={props.params.detailInfo?.oldDataNodeNu || \"-\"} />,\n        },\n        {\n          key: \"dataNodeNu\",\n          label: \"期望节点数\",\n          type: FormItemType.text,\n          customFormItem: <RenderText text={props.params.detailInfo?.dataNodeNu || \"-\"} />,\n        },\n        {\n          key: \"dataNodeSpec\",\n          label: \"节点规格\",\n          type: FormItemType.text,\n          customFormItem: <RenderText text={props.params.detailInfo?.dataNodeSpec || \"-\"} />,\n        },\n        {\n          key: \"RegionList\",\n          label: \"Region\",\n          type: FormItemType.select,\n          options: logicRegionList,\n          rules: [{ required: true, message: \"请选择Region\" }],\n          attrs: {\n            onChange: (e) => {\n              const eventValueObj = JSON.parse(e);\n              $ref?.current?.form.validateFields([\"regionObj\"]);\n              //下拉框值变化时，对数据源进行处理，同时也要对targetKey进行处理\n              ///根据逻辑集群rejon过滤出与之对应的节点\n              let arr = [];\n              //transferList指代ip节点列表\n              if (transferList.length && allData.current.length) {\n                allData.current.map((item) => {\n                  //过滤出相等的regionid和未分配的region\n                  if (item.regionId == eventValueObj.id) {\n                    arr.push({ ...item });\n                    setRegionName(item.regionName);\n                  } else if (item.regionId === -1) {\n                    arr.push({ ...item });\n                  }\n                });\n                getTransferData(arr);\n              }\n            },\n          },\n        },\n        {\n          key: \"regionObj\",\n          type: FormItemType.custom,\n          label: \"节点列表\",\n          customFormItem: (\n            <RegionTransfer\n              dataSource={transferList}\n              selectKeys={(keys) => {\n                //在进行穿梭框之前要对上面下拉框进行验证操作\n                $ref?.current?.form.validateFields([\"RegionList\", \"regionObj\"]).then(\n                  (res) => {},\n                  (rej) => {\n                    console.log(rej);\n                  }\n                );\n                //本属性会在onchange里面调用\n                //leftKey,未分配的节点\n                let leftKey = [];\n                if (!keys.length) {\n                  selectData.current.map((i) => {\n                    leftKey.push(i.id);\n                  });\n                } else if (keys.length == selectData.current.length) {\n                  leftKey = [];\n                } else {\n                  let allKey = [];\n                  selectData.current.length &&\n                    selectData.current.map((item) => {\n                      allKey.push(item.id);\n                    });\n                  const left = allKey.concat(keys).filter((v, i, arr) => {\n                    return arr.indexOf(v) === arr.lastIndexOf(v);\n                  });\n                  leftKey.push(...left);\n                }\n                setLeftTargetKeys(leftKey); //左侧的key\n                setSelectKeys(keys); //相当于targetKey\n              }}\n              targetKeys={targetKeys}\n              isExpand={detailInfo?.dataNodeNu > detailInfo?.oldDataNodeNu}\n            />\n          ),\n          rules: [\n            {\n              required: true,\n              whitespace: true,\n              validator: async (rule: any, value: any) => {\n                if (!leftTargetKeys.length && !selectKeys.length) {\n                  return Promise.reject(\"请选择region节点列表！\");\n                }\n                return Promise.resolve();\n              },\n            },\n          ],\n        },\n      ] as any;\n\n      const xFormModalConfig = {\n        formMap: [\n          {\n            key: \"id\",\n            label: \"工单ID\",\n            type: FormItemType.text,\n            className: \"approval-id\",\n            customFormItem: <RenderText text={id} />,\n          },\n          {\n            key: \"opinion\",\n            label: \"审批意见\",\n            type: FormItemType.textArea,\n            attrs: {\n              placeholder: \"请输入1-100字审核意见\",\n            },\n            rules: [\n              {\n                required: true,\n                whitespace: true,\n                validator: async (rule: any, value: any) => {\n                  if (!value) {\n                    return Promise.reject(\"请输入1-100字审核意见!\");\n                  }\n                  if (value && value.length > 100) {\n                    return Promise.reject(\"请输入1-100字审核意见!\");\n                  }\n                  return Promise.resolve();\n                },\n              },\n            ],\n          },\n        ],\n        width: 1080,\n        okText: outcome === \"agree\" ? \"通过\" : \"驳回\",\n        visible: true,\n        title: \"审批\",\n        type: \"drawer\",\n        needBtnLoading: true,\n        //formData: { RegionList: logicRegionList && logicRegionList[0] ? logicRegionList[0].value : '' },\n        onCancel: () => {\n          props.dispatch(actions.setDrawerId(\"\"));\n        },\n        onSubmit: (value: any) => {\n          let contentObj = {} as any;\n          if (outcome === \"agree\") {\n            if (type === \"logicClusterIndecrease\") {\n              const regionValue = JSON.parse(value.RegionList);\n              contentObj = {\n                regionWithNodeInfo: [\n                  {\n                    id: regionValue.id || \"\",\n                    name: regionName || \"\",\n                    phyClusterName: regionValue.clusterName || \"\",\n                    logicClusterIds: detailInfo.logicClusterId || \"\",\n                    config: regionValue.config || \"\",\n                    bindingNodeIds: selectKeys,\n                    unBindingNodeIds: leftTargetKeys,\n                  },\n                ],\n              };\n            }\n          }\n\n          const orderParams = {\n            assignee: props.user.getName(\"userName\"),\n            checkAuthority: false,\n            comment: value.opinion ? value.opinion.trim() : \"\",\n            orderId: id + \"\",\n            outcome,\n            assigneeProjectId: props.app.appInfo()?.id,\n            contentObj,\n          } as unknown as IApprovalOrder;\n          return approvalOrder(orderParams).then((res) => {\n            let msg = outcome === \"agree\" ? \"通过成功\" : \"驳回成功\";\n            if (res?.message) {\n              msg = res?.description;\n            }\n            XNotification({ type: \"success\", message: msg });\n            props.dispatch(actions.setDrawerId(\"\"));\n            props.cb();\n          });\n        },\n      };\n\n      if (outcome === \"agree\") {\n        if (type === \"logicClusterIndecrease\") {\n          xFormModalConfig.formMap.splice(1, 0, ...formtTemplateIndecreaseMap);\n        }\n      }\n      return xFormModalConfig;\n    };\n\n    return (\n      <>\n        <XFormWrapper ref={$ref} visible={true} {...xFormModalConfigFun()} />\n      </>\n    );\n  }\n);\n"
  },
  {
    "path": "arius-console/src/container/modal/work-order/approval-modal.tsx",
    "content": "import * as React from \"react\";\nimport { XFormWrapper } from \"component/x-form-wrapper\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { FormItemType } from \"component/x-form\";\nimport { Tooltip } from \"antd\";\nimport { approvalOrder } from \"api/order-api\";\nimport { IApprovalOrder, IOrderInfo } from \"typesPath/cluster/order-types\";\nimport { AppState, UserState } from \"store/type\";\nimport { XNotification } from \"component/x-notification\";\nimport { RenderText, RelevanceRegion } from \"container/custom-form\";\nimport { getPhysicsClusterList } from \"api/cluster-api\";\nimport { LEVEL_MAP } from \"constants/common\";\nimport { useDispatch } from \"react-redux\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n  app: state.app,\n  user: state.user,\n});\n\nconst ShowApprovalModal = (props: { params: IOrderInfo; dispatch: Function; app: AppState; cb: Function; user: UserState }) => {\n  const {\n    id,\n    type,\n    detailInfo: { clusterPhyNameList = [], clusterLogicName, diskQuota },\n  } = props.params;\n  const dispatch = useDispatch();\n  //获取物理集群列表数据\n  const getPhyClusterList = (type: number) => {\n    getPhysicsClusterList(type).then((res) => {\n      if (res) {\n        res = res.map((item) => {\n          return {\n            value: item,\n            label: item,\n          };\n        });\n\n        dispatch(actions.setPhyClusterList(res, type + \"\"));\n      }\n    });\n  };\n  React.useEffect(() => {\n    if (props.params.type === \"logicClusterCreate\") {\n      getPhyClusterList(props.params.detailInfo.type);\n    }\n  }, []);\n\n  const filterClusterType = (value: number) => {\n    if (value) {\n      const RESOURCE_TYPE_LIST = [\n        { value: -1, label: \"未知集群\" },\n        { value: 1, label: \"共享集群\" },\n        { value: 2, label: \"独立集群\" },\n        { value: 3, label: \"独享集群\" },\n      ];\n      for (var item of RESOURCE_TYPE_LIST) {\n        if (value === item.value) {\n          return item.label;\n        }\n      }\n    }\n  };\n  const formtTemplateCreateMapFun = () => {\n    const formtTemplateCreateMap = [\n      {\n        key: \"clusterName\",\n        label: \"集群名称\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.detailInfo.name || \"-\"} />,\n      },\n      {\n        key: \"BelongApplication\",\n        label: \"所属应用\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.applicantAppName} />,\n      },\n      {\n        key: \"type\",\n        label: \"集群类型\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={filterClusterType(props.params.detailInfo.type) || \"-\"} />,\n      },\n      {\n        key: \"level\",\n        label: \"业务等级\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={LEVEL_MAP[Number(props.params.detailInfo?.level) - 1]?.label || \"-\"} />,\n      },\n      {\n        key: \"nodeSize\",\n        label: \"节点规格\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.detailInfo?.dataNodeSpec || \"-\"} />,\n      },\n      {\n        key: \"dataNodeSize\",\n        label: \"data节点数\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.detailInfo?.dataNodeNu || \"-\"} />,\n      },\n      {\n        key: \"regionObj\",\n        type: FormItemType.custom,\n        label: (\n          <div className=\"cluster-label\">\n            关联region\n            <Tooltip title=\"所选集群需满足集群类型一致，Region需要满足节点规格严格一致，节点数可大于等于用户选择节点数\">\n              <span className=\"icon iconfont iconinfo\"></span>\n            </Tooltip>\n          </div>\n        ),\n        customFormItem: <RelevanceRegion dataInfo={props.params.detailInfo || {}} />,\n        rules: [\n          {\n            required: true,\n            whitespace: true,\n            validator: async (rule: any, value: any) => {\n              if (!value) {\n                return Promise.reject(\"请关联region，并点击添加完成操作！\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n      {\n        key: \"description\",\n        label: \"集群描述\",\n        type: FormItemType.textArea,\n        attrs: {\n          placeholder: \"请输入审批意见1-200字符\",\n          readOnly: true,\n        },\n      },\n    ] as any;\n    return formtTemplateCreateMap;\n  };\n\n  const dslTemplateStatusMap = () => {\n    const { params } = props;\n    const formMap = [\n      {\n        key: \"BelongApplication\",\n        label: \"所属应用\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={params.applicantAppName} />,\n      },\n      {\n        key: \"desc\",\n        label: \"工单内容\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={params.title} />,\n      },\n    ] as any;\n    return formMap;\n  };\n  const dslTemplateQueryLimitMap = () => {\n    const { params } = props;\n    const formMap = [\n      {\n        key: \"BelongApplication\",\n        label: \"所属应用\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={params.applicantAppName} />,\n      },\n      {\n        key: \"title\",\n        label: \"查询模版MD5\",\n        type: FormItemType.text,\n        customFormItem: (\n          <>\n            {(params.detailInfo?.dslQueryLimitDTOList || []).map((item) => {\n              return <div>{item.dslTemplateMd5 || \"\"}</div>;\n            })}\n          </>\n        ),\n      },\n      params.detailInfo?.dslQueryLimitDTOList?.length === 1 && {\n        key: \"queryLimitBefore\",\n        label: \"原限流值\",\n        type: FormItemType.text,\n        customFormItem: (\n          <>\n            {(params.detailInfo?.dslQueryLimitDTOList || []).map((item) => {\n              return <div>{item.queryLimitBefore || \"\"}</div>;\n            })}\n          </>\n        ),\n      },\n      {\n        key: \"queryLimit\",\n        label: \"修改后限流值\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={params.detailInfo?.dslQueryLimitDTOList?.[0]?.queryLimit || \"-\"} />,\n      },\n    ].filter(Boolean) as any;\n    return formMap;\n  };\n\n  const templateLogicBlockMap = (type) => {\n    const { params } = props;\n    const formMap = [\n      {\n        key: \"BelongApplication\",\n        label: \"所属应用\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={params.applicantAppName} />,\n      },\n      {\n        key: \"name\",\n        label: \"索引模版\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={params.detailInfo?.name || \"-\"} />,\n      },\n      {\n        key: \"op\",\n        label: \"操作\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={params.detailInfo?.status ? `禁用${type}` : `启用${type}`} />,\n      },\n    ] as any;\n    return formMap;\n  };\n\n  const xFormModalConfig = {\n    formMap: [\n      {\n        key: \"id\",\n        label: \"工单ID\",\n        type: FormItemType.text,\n        customFormItem: <RenderText text={props.params.id} />,\n      },\n      {\n        key: \"opinion\",\n        label: \"审批意见\",\n        type: FormItemType.textArea,\n        attrs: {\n          placeholder: \"请输入1-100字审批意见\",\n        },\n        rules: [\n          {\n            required: true,\n            whitespace: true,\n            validator: async (rule: any, value: any) => {\n              if (!value) {\n                return Promise.reject(\"请输入1-100字审核意见!\");\n              }\n              if (value && value.length > 100) {\n                return Promise.reject(\"请输入1-100字审核意见!\");\n              }\n              return Promise.resolve();\n            },\n          },\n        ],\n      },\n    ],\n    width: 668,\n    formData: { description: props.params.description },\n    okText: props.params.outcome === \"agree\" ? \"通过\" : \"驳回\",\n    visible: true,\n    title: \"审批\",\n    needBtnLoading: true,\n    className: \"approval-modal\",\n    onCancel: () => {\n      props.dispatch(actions.setModalId(\"\"));\n    },\n    onSubmit: (value: any) => {\n      let contentObj = {} as any;\n      if (props.params.outcome === \"agree\") {\n        if (type === \"logicClusterCreate\") {\n          contentObj = {\n            clusterRegionDTOS: Array.isArray(value.regionObj)\n              ? value.regionObj.map((item) => {\n                  const regionJson = JSON.parse(item.region[\"0\"]);\n                  return {\n                    id: regionJson.id,\n                    name: regionJson.name,\n                    phyClusterName: regionJson.phyClusterName,\n                    logicClusterIds: regionJson.logicClusterIds,\n                    config: regionJson.config,\n                  };\n                })\n              : [],\n          };\n        }\n      }\n\n      const orderParams = {\n        assignee: props.user.getName(\"userName\"),\n        checkAuthority: false,\n        comment: value.opinion ? value.opinion.trim() : \"\",\n        orderId: id + \"\",\n        outcome: props.params.outcome,\n        assigneeProjectId: props.app.appInfo()?.id,\n        contentObj,\n      } as unknown as IApprovalOrder;\n\n      return approvalOrder(orderParams).then((res) => {\n        let msg = props.params.outcome === \"agree\" ? \"通过成功\" : \"驳回成功\";\n        if (res?.message) {\n          msg = res?.description;\n        }\n        XNotification({ type: \"success\", message: msg });\n        props.dispatch(actions.setModalId(\"\"));\n        props.cb();\n      });\n    },\n  };\n\n  if (props.params.outcome === \"agree\") {\n    if (type === \"logicClusterCreate\") {\n      const formtTemplateCreateMap = formtTemplateCreateMapFun();\n      xFormModalConfig.formMap.splice(1, 0, ...formtTemplateCreateMap);\n    }\n    if (type === \"templateLogicBlockRead\" || type === \"templateLogicBlockWrite\") {\n      const formtTemplateCreateMap = templateLogicBlockMap(type === \"templateLogicBlockRead\" ? \"读\" : \"写\");\n      xFormModalConfig.formMap.splice(1, 0, ...formtTemplateCreateMap);\n    }\n    if (type === \"dslTemplateStatusChange\") {\n      const formtTemplateCreateMap = dslTemplateStatusMap();\n      xFormModalConfig.formMap.splice(1, 0, ...formtTemplateCreateMap);\n    }\n    if (type === \"dslTemplateQueryLimit\") {\n      const formtTemplateCreateMap = dslTemplateQueryLimitMap();\n      xFormModalConfig.formMap.splice(1, 0, ...formtTemplateCreateMap);\n    }\n  }\n  return (\n    <>\n      <XFormWrapper visible={true} {...xFormModalConfig} />\n    </>\n  );\n};\nexport default connect(mapStateToProps)(ShowApprovalModal);\n"
  },
  {
    "path": "arius-console/src/container/modal/work-order/index.less",
    "content": ".approval-id {\n  margin-top: 16px;\n}\n\n.approval-modal {\n  .ant-modal-body {\n    padding: 16px 24px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/modal/work-order/task-log.tsx",
    "content": "import * as React from \"react\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { Modal, Spin, Tabs } from \"antd\";\nimport { getTaskLog } from \"api/task-api\";\nimport { ITaskLog } from \"typesPath/task-types\";\n\nconst { TabPane } = Tabs;\n\nconst mapStateToProps = (state) => ({\n  params: state.modal.params,\n  cb: state.modal.cb,\n});\n\nexport const TaskLogModal = connect(mapStateToProps)(\n  (props: { dispatch: any; params: any }) => {\n    const [loading, setLoading] = React.useState(false);\n    const [taskLog, setTaskLog] = React.useState({} as ITaskLog);\n\n    React.useEffect(() => {\n      reloadData();\n    }, []);\n\n    const reloadData = () => {\n      setLoading(true);\n      getTaskLog(props.params)\n        .then((res) => {\n          setTaskLog(res);\n        })\n        .finally(() => {\n          setLoading(false);\n        });\n    };\n\n    return (\n      <>\n        <Modal\n          visible={true}\n          title=\"日志详情\"\n          width={700}\n          onOk={() => props.dispatch(actions.setModalId(\"\"))}\n          onCancel={() => props.dispatch(actions.setModalId(\"\"))}\n          okText={\"确定\"}\n          cancelText={\"取消\"}\n        >\n          <Spin spinning={loading}>\n            <div>\n              <Tabs defaultActiveKey=\"1\">\n                <TabPane tab=\"详情列表\" key=\"1\">\n                  <div className=\"line-break\">{taskLog.agent || '任务未执行完成，请稍后再查看日志。'}</div>\n                </TabPane>\n                <TabPane tab=\"部署日志\" key=\"2\">\n                  <div className=\"line-break\">{taskLog.user || '任务未执行完成，请稍后再查看日志。'}</div>\n                </TabPane>\n              </Tabs>\n            </div>\n          </Spin>\n        </Modal>\n      </>\n    );\n  }\n);\n"
  },
  {
    "path": "arius-console/src/container/search-query/components/editLimit.less",
    "content": ".dsl-editlimit-input {\n  width: 100%;\n  margin-top: 10px;\n}\n\n.dsl-editlimit-tags {\n  margin-bottom: 5px;\n  margin-top: -10px;\n  display: flex;\n  justify-content: space-between;\n  flex-wrap: wrap;\n}\n\n.dsl-editlimit-tag{\n  display: block;\n  margin-bottom: 5px;\n  margin-right: 0px;\n}\n\n.dsl-editlimit-tag-r {\n  flex: 1;\n  padding-left: 3px;\n}\n\n.dsl-editlimit-tag-l {\n  flex: 1;\n  padding-right: 3px;\n}"
  },
  {
    "path": "arius-console/src/container/search-query/components/editLimit.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { Modal, InputNumber, message, Tag } from \"antd\";\nimport { queryLimit } from \"api/search-query\";\nimport \"./editLimit.less\";\nimport { isSuperApp } from \"lib/utils\";\nimport { IWorkOrder } from \"@types/params-types\";\nimport { submitWorkOrder } from \"api/common-api\";\n\ninterface IProps {\n  record: any;\n  visible: boolean;\n  cb: () => void;\n  cancel: () => void;\n  history?: any;\n  appInfo: any;\n}\n\nconst EditLimit: React.FC<IProps> = (props: IProps) => {\n  const [value, setValue] = useState(\"\" as any);\n\n  const handleOk = async () => {\n    if (value < 0) {\n      message.warning(\"限流值不能小于0\");\n      return;\n    }\n    if (isSuperApp()) {\n      const params = props?.record?.map((item) => ({\n        dslTemplateMd5: item.dslTemplateMd5,\n        queryLimit: value,\n        projectId: item.projectId,\n      }));\n      return queryLimit(params).then(() => {\n        props.cancel();\n        props.cb();\n        message.success(\"修改成功\");\n      });\n    }\n    const params: IWorkOrder = {\n      contentObj: {\n        dslQueryLimitDTOList: props?.record?.map((item) => ({\n          dslTemplateMd5: item.dslTemplateMd5,\n          queryLimit: value,\n          queryLimitBefore: item.queryLimit,\n          projectId: item.projectId,\n        })),\n        operator: props?.appInfo.user(\"userName\") || \"\",\n        projectId: props?.appInfo.app()?.id,\n      },\n      submitorProjectId: props?.appInfo.app()?.id,\n      submitor: props?.appInfo.user(\"userName\") || \"\",\n      description: \"\",\n      type: \"dslTemplateQueryLimit\",\n    };\n    await submitWorkOrder(\n      params,\n      props?.history,\n      () => {\n        props.cancel();\n        props.cb();\n      },\n      500\n    );\n  };\n\n  const renderTags = () => {\n    const left = [];\n    const right = [];\n    props.record?.map((item, index) => {\n      if (index % 2 !== 0) {\n        right.push(\n          <Tag key={item.dslTemplateMd5} className=\"dsl-editlimit-tag\">\n            {item.dslTemplateMd5}\n          </Tag>\n        );\n      } else {\n        left.push(\n          <Tag key={item.dslTemplateMd5} className=\"dsl-editlimit-tag\">\n            {item.dslTemplateMd5}\n          </Tag>\n        );\n      }\n    });\n    return (\n      <>\n        <div className=\"dsl-editlimit-tag-l\">{left}</div>\n        <div className=\"dsl-editlimit-tag-r\">{right}</div>\n      </>\n    );\n  };\n\n  useEffect(() => {\n    if (props?.record && props?.record?.length === 1) {\n      setValue(props?.record[0]?.queryLimit);\n    }\n    return () => {\n      setValue(\"\");\n    };\n  }, [props?.record[0]?.queryLimit]);\n\n  return (\n    <Modal\n      visible={props.visible}\n      onOk={handleOk}\n      onCancel={props.cancel}\n      width={650}\n      title={props.record?.length >= 2 ? \"批量修改限流值\" : \"修改限流值\"}\n    >\n      <div>\n        <div className=\"dsl-editlimit-tags\">{renderTags()}</div>\n        <div>\n          <label>查询限流值：</label>\n          <InputNumber value={value} onChange={(e) => setValue(e)} className=\"dsl-editlimit-input\" />\n        </div>\n      </div>\n    </Modal>\n  );\n};\n\nexport default EditLimit;\n"
  },
  {
    "path": "arius-console/src/container/search-query/components/index.tsx",
    "content": "export * from \"./select-time\";\nexport * from \"./search-query-form\";\n"
  },
  {
    "path": "arius-console/src/container/search-query/components/search-query-form.less",
    "content": ".search-query-from-box {\n  display: flex;\n  // justify-content: flex-end;\n  flex-wrap: wrap;\n  &-item {\n    display: flex;\n    flex-wrap: wrap;\n    margin-left: 20px;\n  }\n  .ant-form-item {\n    margin-bottom: 5px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/search-query/components/search-query-form.tsx",
    "content": "import React, { memo, useEffect, useRef, useState } from \"react\";\nimport \"./search-query-form.less\";\nimport store from \"store\";\nimport { isSuperApp, filterOption } from \"lib/utils\";\nimport DRangeTime from \"../../../d1-packages/d-range-time\";\nimport { QueryForm } from \"knowdesign\";\nimport moment from \"moment\";\nimport { IColumnsType } from \"../../../d1-packages/ProForm/QueryForm\";\nimport { regNonnegativeInteger } from \"constants/reg\";\n\ninterface SearchQueryFormPropsType {\n  setSearchQuery: (params) => void;\n  reload?: boolean;\n  isSlow?: boolean;\n  value?: any;\n}\nconst CN = \"dsl-query-tpl\";\nconst customTimeOptions = [\n  {\n    label: \"最近 2 小时\",\n    value: 2 * 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 1 天\",\n    value: 24 * 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 7 天\",\n    value: 7 * 24 * 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 1 月\",\n    value: 30 * 24 * 60 * 60 * 1000,\n  },\n];\n\nconst getQueryFormConfig = (data = [], handleTimeChange, filterOption, superApp, isShow, error) => {\n  //export const getEditionQueryXForm = (data, handleTimeChange, resetAllValue: Function) => {\n  const customTimeOptions = [\n    {\n      label: \"最近 2 小时\",\n      value: 2 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 1 天\",\n      value: 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 7 天\",\n      value: 7 * 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 1 月\",\n      value: 30 * 24 * 60 * 60 * 1000,\n    },\n  ];\n  const formMap = [\n    {\n      dataIndex: \"queryIndex\",\n      title: \"查询索引:\",\n      type: \"input\",\n      placeholder: \"请输入\",\n      rules: [\n        {\n          required: false,\n          validator: (rule, value) => {\n            if (value?.length > 128) {\n              error.current = true;\n              return Promise.reject(\"上限128字符\");\n            }\n            error.current = false;\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      dataIndex: \"queryIndexSearch\",\n      title: \"查询时间:\",\n      type: \"custom\",\n      //component: <RangePicker showTime={{ format: \"HH:mm\" }} format=\"YYYY-MM-DD HH:mm\" />,\n      component: (\n        <DRangeTime\n          timeChange={handleTimeChange}\n          popoverClassName=\"dashborad-popover\"\n          //resetAllValue={resetAllValue}\n          customTimeOptions={customTimeOptions}\n          defaultRangeKey={0}\n        />\n      ),\n    },\n  ] as IColumnsType[];\n\n  isShow &&\n    formMap.unshift({\n      dataIndex: \"totalCost\",\n      title: \"总耗时:\",\n      type: \"input\",\n      placeholder: \"请输入\",\n      rules: [\n        {\n          required: false,\n          validator: (rule: any, value: string) => {\n            if (value && !new RegExp(regNonnegativeInteger).test(value)) {\n              return Promise.reject(new Error(\"请输入正确格式\"));\n            }\n            if (value?.length > 6) {\n              return Promise.reject(\"上限6字符\");\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    });\n\n  superApp &&\n    formMap.unshift({\n      dataIndex: \"clusterName\",\n      title: \"所属集群:\",\n      type: \"input\",\n      placeholder: \"请输入\",\n      rules: [\n        {\n          required: false,\n          validator: (rule, value) => {\n            if (value?.length > 128) {\n              error.current = true;\n              return Promise.reject(\"上限128字符\");\n            }\n            error.current = false;\n            return Promise.resolve();\n          },\n        },\n      ],\n    });\n\n  superApp &&\n    formMap.unshift({\n      dataIndex: \"projectId\",\n      title: \"所属应用:\",\n      type: \"select\",\n      options: data?.map((item) => ({\n        title: `${item.projectName}(${item.id})`,\n        value: item.id,\n      })),\n      componentProps: {\n        showSearch: true,\n        filterOption: filterOption,\n      },\n      placeholder: \"请选择\",\n    });\n\n  return formMap;\n};\n\nexport const SearchQueryForm: React.FC<SearchQueryFormPropsType> = memo(({ setSearchQuery, reload, isSlow = false, value }) => {\n  // 默认近2小时\n  const defaultRangeKey = 0;\n\n  const queryParams = useRef({\n    startTime: moment(new Date().getTime() - customTimeOptions[defaultRangeKey]?.value).valueOf(),\n    endTime: moment().valueOf(),\n    projectId: undefined,\n    queryIndex: undefined,\n    totalCost: undefined,\n    clusterName: undefined,\n  });\n  const [form, setForm] = useState<any>();\n  const buttonTime = useRef(null);\n  const error = useRef(false);\n  const superApp = isSuperApp();\n\n  const onSearch = (result) => {\n    // 校验不通过时不发送请求\n    if (error.current) {\n      return;\n    }\n    const { projectId = undefined, queryIndex, totalCost, queryIndexSearch, clusterName } = result || {};\n    const { rangeTime } = queryIndexSearch || {};\n    const time = rangeTime?.[1]?.valueOf() - rangeTime?.[0]?.valueOf();\n    const currentTime = new Date().getTime();\n    let _queryParams = {\n      projectId,\n      queryIndex,\n      clusterName,\n      startTime: queryIndexSearch ? (buttonTime.current ? currentTime - time : rangeTime?.[0].valueOf()) : undefined,\n      endTime: queryIndexSearch ? (buttonTime.current ? currentTime : rangeTime?.[1].valueOf()) : undefined,\n      totalCost,\n    };\n    queryParams.current = _queryParams;\n    setSearchQuery && setSearchQuery(_queryParams);\n  };\n\n  const onReset = (result) => {\n    queryParams.current = {} as any;\n    setSearchQuery && setSearchQuery({});\n  };\n\n  useEffect(() => {\n    sessionStorage.setItem(value, JSON.stringify(queryParams.current));\n  }, [queryParams.current]);\n\n  useEffect(() => {\n    let params: any = sessionStorage.getItem(value);\n    let _queryParams = queryParams.current;\n    if (params) {\n      params = JSON.parse(params);\n      _queryParams = params;\n      queryParams.current = _queryParams;\n    }\n    if (form) {\n      form.setFieldsValue(_queryParams);\n      setSearchQuery && setSearchQuery(_queryParams);\n    }\n  }, [form]);\n\n  const handleTimeChange = (times: number[], periodOrPicker: boolean) => {\n    if (times) {\n      buttonTime.current = periodOrPicker;\n    }\n  };\n\n  return (\n    <>\n      <QueryForm\n        defaultCollapse\n        columns={getQueryFormConfig(store.getState().app?.projectList, handleTimeChange, filterOption, superApp, isSlow, error)}\n        onChange={() => null}\n        getFormInstance={(form) => setForm(form)}\n        onReset={onReset}\n        onSearch={onSearch}\n        isResetClearAll\n      />\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/search-query/components/select-time.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { Radio, DatePicker } from \"antd\";\nimport moment from \"moment\";\nimport { IPeriod } from \"../config\";\nconst { RangePicker } = DatePicker;\n\ninterface SelectTimePropsType {\n  onTimeStampChange?: (startTime, endTime) => void;\n  periodRadio: IPeriod[];\n  periodRadioMap: Map<string, IPeriod>;\n  reload?: boolean;\n  value?: any;\n}\n\nexport const SelectTime: React.FC<SelectTimePropsType> = ({ onTimeStampChange, periodRadio, periodRadioMap, reload, value }) => {\n  const [time, setTime] = useState(\"oneDay\");\n  const [dates, setDates] = useState([undefined, undefined]);\n  const disabledDate = (current) => {\n    if (!dates || dates.length === 0) {\n      return false;\n    }\n    const tooLate = dates[0] && current.diff(dates[0], \"days\") > 13;\n    const tooEarly = dates[1] && dates[1].diff(current, \"days\") > 13;\n    return current > moment().endOf(\"day\");\n  };\n\n  const onRadioChange = (e) => {\n    const { value } = e.target;\n    setTime && setTime(value);\n    const dates = periodRadioMap.get(value).dateRange;\n    onTimeStampChange && onTimeStampChange(dates[0].valueOf(), dates[1].valueOf());\n  };\n\n  const onRangeChange = (dates) => {\n    setTime && setTime(\"\");\n    onTimeStampChange && onTimeStampChange(dates[0].valueOf(), dates[1].valueOf());\n  };\n\n  useEffect(() => {\n    if (value) {\n      setTime && setTime(\"\");\n      setDates([moment(value[0]), moment(value[1])]);\n    }\n  }, [value]);\n\n  useEffect(() => {\n    if (typeof reload !== \"boolean\" || !time) {\n      return;\n    }\n    const dates = periodRadioMap.get(time).dateRange;\n    onTimeStampChange && onTimeStampChange(dates[0].valueOf(), dates[1].valueOf());\n  }, [reload]);\n\n  return (\n    <div>\n      <Radio.Group style={{ margin: \"0 20px 10px 0\" }} value={time} onChange={onRadioChange}>\n        {periodRadio.map((p) => (\n          <Radio.Button key={p.key} value={p.key}>\n            {p.label}\n          </Radio.Button>\n        ))}\n      </Radio.Group>\n      <RangePicker\n        // disabledDate={disabledDate}\n        onCalendarChange={(val) => setDates(val)}\n        format=\"YYYY-MM-DD HH:mm\"\n        allowClear={false}\n        value={dates as [moment.Moment, moment.Moment]}\n        onChange={onRangeChange}\n        showTime\n      />\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/search-query/config.tsx",
    "content": "import React from \"react\";\nimport { Tooltip, message, Modal } from \"antd\";\nimport { IMenuItem } from \"typesPath/base-types\";\nimport { renderOperationBtns } from \"container/custom-component\";\nimport moment from \"moment\";\nimport { changeStatus } from \"api/search-query\";\nimport { SearchQueryPermissions, SearchTemplatePermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { ErrorQuery } from \"./error-query\";\nimport { SlowQuery } from \"./slow-query\";\nimport { copyString, transTimeFormat, formatDecimalPoint, getFormatJsonStr, isSuperApp } from \"lib/utils\";\nimport store from \"store\";\nimport { copyContentFn } from \"knowdesign/lib/utils/tools\";\nimport DRangeTime from \"../../d1-packages/d-range-time\";\nimport { IColumnsType } from \"d1-packages/ProForm/QueryForm\";\nimport { IconFont } from \"@knowdesign/icons\";\nimport { IWorkOrder } from \"@types/params-types\";\nimport { submitWorkOrder } from \"api/common-api\";\n\nexport enum TAB_LIST_KEY {\n  queryTpl = \"query-tpl\",\n  errorQuery = \"error-query\",\n  slowQuery = \"slow-query\",\n}\nconst appInfo = {\n  app: store.getState().app.appInfo,\n  user: store.getState().user.getName,\n};\n\nconst { confirm } = Modal;\n\nexport const getTabList = (setReload?: any) => {\n  return [\n    {\n      name: \"慢查询列表\",\n      key: TAB_LIST_KEY.slowQuery,\n      visible: hasOpPermission(SearchQueryPermissions.PAGE, SearchQueryPermissions.SLOW_LIST),\n      content: (menu) => <SlowQuery menu={menu} />,\n      renderCustomElement: (menu) => {\n        return (\n          <div className=\"search-query-reload\" onClick={() => setReload(menu)}>\n            <IconFont type=\"icon-shuaxin1\" />{\" \"}\n          </div>\n        );\n      },\n      renderCustomElementClick: setReload,\n    },\n    {\n      name: \"异常查询列表\",\n      key: TAB_LIST_KEY.errorQuery,\n      visible: hasOpPermission(SearchQueryPermissions.PAGE, SearchQueryPermissions.ERROR_LIST),\n      content: (menu) => <ErrorQuery menu={menu} />,\n      renderCustomElement: (menu) => {\n        return (\n          <div className=\"search-query-reload\" onClick={() => setReload(menu)}>\n            <IconFont type=\"icon-shuaxin1\" />{\" \"}\n          </div>\n        );\n      },\n      renderCustomElementClick: setReload,\n    },\n  ];\n};\n\nexport const menuMap = new Map<string, IMenuItem>();\n\ngetTabList().forEach((d) => {\n  menuMap.set(d.key, d);\n});\n\nexport const MENU_MAP = menuMap;\n\nexport const renderText = (text) => {\n  return <div className=\"dsl-overflow-auto\">{text}</div>;\n};\n\nexport const filterColumnsList = [\n  \"searchCount\",\n  \"totalCostAvg\",\n  \"totalShardsAvg\",\n  \"totalHitsAvg\",\n  \"responseLenAvg\",\n  \"ariusCreateTime\",\n  \"timeStamp\",\n];\n\nconst formatProject = (id: number) => {\n  const projectList = store.getState().app?.projectList;\n  const projectInfo = projectList.find((item) => item.id === id);\n  return projectInfo?.projectName || id;\n};\n\nexport const customTimeOptions = [\n  {\n    label: \"最近 2 小时\",\n    value: 2 * 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 1 天\",\n    value: 24 * 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 7 天\",\n    value: 7 * 24 * 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 1 月\",\n    value: 30 * 24 * 60 * 60 * 1000,\n  },\n];\n\nexport const getQueryTplColumns = (\n  reloadData: Function,\n  showDrawer: Function,\n  showEditLimit: Function,\n  superApp: boolean,\n  setVisible,\n  props\n) => {\n  const getCongigBtnList = (reloadData: Function, record: any, showEditLimit: Function) => {\n    return [\n      {\n        label: `${record.enable || record.enable === null ? \"禁用\" : \"启用\"}`,\n        invisible: !hasOpPermission(SearchTemplatePermissions.PAGE, SearchTemplatePermissions.DISABLE),\n        clickFunc: () => {\n          confirm({\n            title: \"提示\",\n            content: `确定${record.enable || record.enable === null ? \"禁用\" : \"启用\"}查询模板${record.dslTemplateMd5}？`,\n            width: 500,\n            okText: \"确认\",\n            cancelText: \"取消\",\n            onOk: async () => {\n              if (superApp) {\n                return changeStatus(record.dslTemplateMd5, record.projectId).then((res) => {\n                  reloadData();\n                  message.success(\"操作成功\");\n                });\n              }\n              const params: IWorkOrder = {\n                contentObj: {\n                  name: record.dslTemplate,\n                  projectId: record.projectId,\n                  operator: appInfo.user(\"userName\") || \"\",\n                  dslTemplateMd5: record.dslTemplateMd5,\n                },\n                submitorProjectId: appInfo.app()?.id,\n                submitor: appInfo.user(\"userName\") || \"\",\n                description: \"\",\n                type: \"dslTemplateStatusChange\",\n              };\n              await submitWorkOrder(params, props?.history, () => reloadData(), 500);\n            },\n          });\n        },\n      },\n      {\n        label: \"修改限流值\",\n        invisible: !hasOpPermission(SearchTemplatePermissions.PAGE, SearchTemplatePermissions.MODIFY_LIMIT),\n        clickFunc: () => {\n          showEditLimit(record);\n        },\n      },\n    ];\n  };\n  const orderColumns = [\n    {\n      title: \"查询模板\",\n      dataIndex: \"dslTemplate\",\n      fixed: \"left\",\n      width: 100,\n      render: (text: any, record: any) => {\n        const btns: any = [\n          {\n            label: (\n              <Tooltip placement=\"right\" title={renderText(text)}>\n                <div className=\"two-row-ellipsis dsl-vw-5\">{text}</div>\n              </Tooltip>\n            ),\n            clickFunc: () => {\n              showDrawer({ ...record, projectName: formatProject(record.projectId) });\n            },\n          },\n        ];\n        return renderOperationBtns(btns, record);\n      },\n    },\n    {\n      title: \"所属应用\",\n      dataIndex: \"projectId\",\n      invisible: !superApp,\n      width: 100,\n      render: (text) => {\n        const projectName = formatProject(text);\n        return (\n          <Tooltip placement=\"right\" title={renderText(projectName)}>\n            <div className=\"two-row-ellipsis dsl-vw-5\">{projectName}</div>\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"所属查询索引\",\n      dataIndex: \"indices\",\n      width: 130,\n      render: (text) => (\n        <Tooltip placement=\"right\" title={renderText(text)}>\n          <div className=\"two-row-ellipsis dsl-vw-5\">{text}</div>\n        </Tooltip>\n      ),\n    },\n    {\n      title: \"查询模板MD5\",\n      dataIndex: \"dslTemplateMd5\",\n      width: 150,\n      render: (text) => (\n        <Tooltip placement=\"right\" title={renderText(text)}>\n          <div className=\"two-row-ellipsis dsl-vw-5\">{text}</div>\n        </Tooltip>\n      ),\n    },\n    {\n      title: \"请求数(次/分钟)\",\n      dataIndex: \"searchCount\",\n      width: 140,\n      sorter: true,\n    },\n    {\n      title: \"耗时(ms)\",\n      dataIndex: \"totalCostAvg\",\n      sorter: true,\n      width: 100,\n      render: (text) => formatDecimalPoint(text),\n    },\n    {\n      title: \"总shard数\",\n      dataIndex: \"totalShardsAvg\",\n      width: 100,\n      sorter: true,\n    },\n    {\n      title: \"单次命中数\",\n      dataIndex: \"totalHitsAvg\",\n      sorter: true,\n      width: 130,\n      render: (text) => formatDecimalPoint(text),\n    },\n    {\n      title: \"单次响应长度\",\n      dataIndex: \"responseLenAvg\",\n      sorter: true,\n      width: 130,\n      render: (text) => formatDecimalPoint(text),\n    },\n    {\n      title: \"创建时间\",\n      dataIndex: \"ariusCreateTime\",\n      sorter: true,\n      width: 150,\n      render: (text) => transTimeFormat(text),\n    },\n    {\n      title: \"最近使用时间\",\n      dataIndex: \"timeStamp\",\n      sorter: true,\n      width: 150,\n      render: (text) => transTimeFormat(text),\n    },\n    {\n      title: \"限流值(s)\",\n      dataIndex: \"queryLimit\",\n      sorter: true,\n      width: 100,\n      render: (text) => formatDecimalPoint(text),\n    },\n    {\n      title: \"状态\",\n      dataIndex: \"enable\",\n      sorter: true,\n      width: 100,\n      render: (text) => {\n        if (text === null || text) {\n          return \"启用\";\n        } else {\n          return \"禁用\";\n        }\n      },\n    },\n    {\n      title: (\n        <div className=\"option-filter-columns\">\n          <span>操作</span>\n        </div>\n      ),\n      dataIndex: \"operation\",\n      filterTitle: true,\n      width: 180,\n      key: \"operation\",\n      fixed: \"right\",\n      render: (text: any, record: any) => {\n        const btns: any = getCongigBtnList(reloadData, record, showEditLimit);\n        return <div>{renderOperationBtns(btns, record)}</div>;\n      },\n    },\n  ];\n  return orderColumns.filter((item) => !item.invisible);\n};\nexport interface IPeriod {\n  label: string;\n  key: string;\n  dateRange: [moment.Moment, moment.Moment];\n}\n\nexport const PERIOD_RADIO = [\n  {\n    label: \"近1天\",\n    key: \"oneDay\",\n    get dateRange() {\n      return [moment().subtract(1, \"day\"), moment()];\n    },\n  },\n  {\n    label: \"近7天\",\n    key: \"sevenDay\",\n    get dateRange() {\n      return [moment().subtract(1, \"week\"), moment()];\n    },\n  },\n  {\n    label: \"近1月\",\n    key: \"thirtyDay\",\n    get dateRange() {\n      return [moment().subtract(1, \"month\"), moment()];\n    },\n  },\n] as IPeriod[];\n\nconst periodRadioMap = new Map<string, IPeriod>();\n\nPERIOD_RADIO.forEach((p) => {\n  periodRadioMap.set(p.key, p);\n});\n\nexport const PERIOD_RADIO_MAP = periodRadioMap;\n\nconst errorQueryColumnsRender = (item) => {\n  return (\n    <Tooltip placement=\"right\" title={renderText(item)}>\n      <div className=\"error-query-container-table-cell two-row-ellipsis\"> {item || \"-\"}</div>\n    </Tooltip>\n  );\n};\n\nexport const errorQueryColumns = (superApp: boolean) => {\n  const columns = [\n    {\n      title: \"请求URL\",\n      dataIndex: \"uri\",\n      render: (item) => errorQueryColumnsRender(item),\n      fixed: \"left\",\n    },\n    {\n      title: \"查询语句\",\n      dataIndex: \"dsl\",\n      render: (item) => errorQueryColumnsRender(item),\n    },\n    {\n      title: \"所属应用\",\n      dataIndex: \"projectId\",\n      invisible: !superApp,\n      render: (text) => errorQueryColumnsRender(formatProject(text)),\n    },\n    {\n      title: \"所属集群\",\n      dataIndex: \"clusterName\",\n      invisible: !superApp,\n      render: (text) => errorQueryColumnsRender(text),\n    },\n    {\n      title: \"所属查询索引\",\n      dataIndex: \"indices\",\n      render: (item) => errorQueryColumnsRender(item),\n    },\n    {\n      title: \"查询时间\",\n      dataIndex: \"timeStamp\",\n      render: (text) => {\n        const content = transTimeFormat(text);\n        return (\n          <div className=\"error-query-container-table-cell two-row-ellipsis\">\n            <Tooltip placement=\"right\" title={renderText(content)}>\n              {content}\n            </Tooltip>\n          </div>\n        );\n      },\n    },\n    {\n      title: \"错误信息\",\n      dataIndex: \"exceptionName\",\n      render: (item) => errorQueryColumnsRender(item),\n    },\n  ];\n  return columns.filter((item) => !item.invisible);\n};\n\nexport const slowQueryColumns = (superApp: boolean) => {\n  const columns = [\n    {\n      title: \"查询语句\",\n      dataIndex: \"dsl\",\n      render: (text, data) => (\n        <Tooltip placement=\"right\" title={renderText(text)}>\n          <div\n            className=\"two-row-ellipsis slow-query-container-table-cell\"\n            onClick={() => {\n              copyString(`GET ${data?.indices}/_search\\n${data?.dsl}`);\n            }}\n          >\n            <a href=\"javascript:;\">{text}</a>\n          </div>\n        </Tooltip>\n      ),\n      fixed: \"left\",\n    },\n    {\n      title: \"所属应用\",\n      dataIndex: \"projectId\",\n      invisible: !superApp,\n      render: (text) => {\n        const projectName = formatProject(text);\n        return (\n          <Tooltip placement=\"right\" title={renderText(projectName)}>\n            <div className=\"two-row-ellipsis slow-query-container-table-cell\">{projectName}</div>\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"所属集群\",\n      dataIndex: \"clusterName\",\n      invisible: !superApp,\n      render: (text) => errorQueryColumnsRender(text),\n    },\n    {\n      title: \"所属查询索引\",\n      dataIndex: \"indices\",\n      render: (text) => (\n        <Tooltip placement=\"right\" title={renderText(text)}>\n          <div className=\"two-row-ellipsis slow-query-container-table-cell\">{text || \"-\"}</div>\n        </Tooltip>\n      ),\n    },\n    {\n      title: \"响应时间(ms)\",\n      dataIndex: \"esCost\",\n      sorter: (a, b) => a.esCost - b.esCost,\n      render: (text) => formatDecimalPoint(text),\n    },\n    {\n      title: \"总耗时(ms)\",\n      dataIndex: \"totalCost\",\n      sorter: (a, b) => a.totalCost - b.totalCost,\n      render: (text) => formatDecimalPoint(text),\n    },\n    {\n      title: \"单次命中数\",\n      dataIndex: \"totalHits\",\n      sorter: (a, b) => a.totalHits - b.totalHits,\n      render: (text) => formatDecimalPoint(text),\n    },\n    {\n      title: \"单次响应长度\",\n      dataIndex: \"responseLen\",\n      sorter: (a, b) => a.responseLen - b.responseLen,\n      render: (text) => formatDecimalPoint(text),\n    },\n    {\n      title: \"查询时间\",\n      dataIndex: \"timeStamp\",\n      render: (text) => {\n        return transTimeFormat(text);\n      },\n    },\n    {\n      title: \"是否超时\",\n      dataIndex: \"isTimedOut\",\n    },\n  ];\n  return columns.filter((item) => !item.invisible);\n};\n\nexport const getIndexColumns = () => {\n  return [\n    {\n      title: \"字段名\",\n      dataIndex: \"name\",\n      key: \"name\",\n      width: 70,\n      render: (value) => {\n        return (\n          <>\n            <Tooltip title={value}>\n              <div\n                className=\"mapping-name\"\n                onClick={() => {\n                  copyContentFn(value);\n                }}\n              >\n                {value || \"-\"}\n              </div>\n            </Tooltip>\n          </>\n        );\n      },\n    },\n    {\n      title: \"类型\",\n      dataIndex: \"type\",\n      key: \"type\",\n      width: 65,\n    },\n    {\n      title: \"是否排序/聚合\",\n      dataIndex: \"doc_value\",\n      key: \"doc_value\",\n      width: 95,\n      render: (value) => {\n        return (\n          <>\n            <span>{value ? \"是\" : \"否\"}</span>\n          </>\n        );\n      },\n    },\n    {\n      title: \"检索方式\",\n      dataIndex: \"search\",\n      key: \"search\",\n      width: 65,\n    },\n  ];\n};\nexport const TAB_JSON = [\n  {\n    label: \"TABLE\",\n    key: \"TABLE\",\n  },\n  {\n    label: \"JSON\",\n    key: \"JSON\",\n  },\n];\n\nexport const getResTableColumns = (checkedList: any[] = []) => {\n  const arr = [];\n  for (const key of checkedList) {\n    if (key) {\n      arr.push({\n        title: key,\n        dataIndex: key,\n        width: 150,\n        key,\n        render: (text) => {\n          if (typeof text === \"object\") {\n            let str = \"-\";\n            try {\n              str = getFormatJsonStr(text);\n            } catch (err) {\n              console.log(err);\n            }\n            return (\n              <>\n                <Tooltip\n                  title={\n                    <div className=\"tooltip-title\">\n                      <pre>{str}</pre>\n                    </div>\n                  }\n                >\n                  <div className=\"text-oh\">{str}</div>\n                </Tooltip>\n              </>\n            );\n          }\n          return (\n            <>\n              <Tooltip title={text}>\n                <div className=\"text-oh\">{text}</div>\n              </Tooltip>\n            </>\n          );\n        },\n      });\n    }\n  }\n  return arr;\n};\n\nexport type selectDt = {\n  value: string;\n  label: string;\n};\n\nexport const getQueryFormConfig = (data = [], handleTimeChange, filterOption, superApp, error) => {\n  //export const getEditionQueryXForm = (data, handleTimeChange, resetAllValue: Function) => {\n  const customTimeOptions = [\n    {\n      label: \"最近 2 小时\",\n      value: 2 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 1 天\",\n      value: 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 7 天\",\n      value: 7 * 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 1 月\",\n      value: 30 * 24 * 60 * 60 * 1000,\n    },\n  ];\n  const formMap = [\n    {\n      dataIndex: \"MD5\",\n      title: \"查询模板MD5:\",\n      type: \"input\",\n      placeholder: \"请输入\",\n      rules: [\n        {\n          required: false,\n          validator: (rule, value) => {\n            if (value?.length > 128) {\n              error.current = true;\n              return Promise.reject(\"上限128字符\");\n            }\n            error.current = false;\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      dataIndex: \"queryIndex\",\n      title: \"查询索引:\",\n      type: \"input\",\n      placeholder: \"请输入\",\n      rules: [\n        {\n          required: false,\n          validator: (rule, value) => {\n            if (value?.length > 128) {\n              error.current = true;\n              return Promise.reject(\"上限128字符\");\n            }\n            error.current = false;\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      dataIndex: \"queryIndexTime\",\n      title: \"最近使用时间:\",\n      type: \"custom\",\n      //component: <RangePicker showTime={{ format: \"HH:mm\" }} format=\"YYYY-MM-DD HH:mm\" />,\n      component: (\n        <DRangeTime\n          timeChange={handleTimeChange}\n          popoverClassName=\"dashborad-popover\"\n          //resetAllValue={resetAllValue}\n          customTimeOptions={customTimeOptions}\n          defaultRangeKey={0}\n        />\n      ),\n    },\n  ] as IColumnsType[];\n\n  superApp &&\n    formMap.unshift({\n      dataIndex: \"projectId\",\n      title: \"所属应用:\",\n      type: \"select\",\n      options: data?.map((item) => ({\n        title: `${item.projectName}(${item.id})`,\n        value: item.id,\n      })),\n      componentProps: {\n        showSearch: true,\n        filterOption: filterOption,\n      },\n      placeholder: \"请选择\",\n    });\n\n  return formMap;\n};\n"
  },
  {
    "path": "arius-console/src/container/search-query/dsl-page.tsx",
    "content": "import React, { useState, useEffect, useRef } from \"react\";\nimport { DevToolsPage } from \"@knowdesign/kbn-sense\";\nimport { clearSubscriptions } from \"@knowdesign/kbn-sense/lib/plugin/console/public/lib/mappings/mappings\";\nimport { useDidCache, useDidRecover } from \"react-router-cache-route\";\nimport { getCookie, setCookie, getCurrentProject, uuid, isSuperApp } from \"lib/utils\";\nimport { XNotification } from \"component/x-notification\";\nimport { Select } from \"knowdesign\";\nimport { newClusterList, getSenseOperate, setSenseOperate } from \"api/cluster-api\";\nimport Url from \"lib/url-parser\";\nimport { IndexSelect } from \"../IndexSelect\";\n\nconst Option = Select.Option;\n\nexport const DslPage = () => {\n  const [id, setId] = useState(null);\n  const [list, setList] = useState([]);\n  const [content, setContent] = useState(\"\");\n  const [loading, setLoading] = useState(true);\n  const [listLoading, setListLoading] = useState(true);\n  const currentClusterInfoRef = useRef({});\n\n  useEffect(() => {\n    _getSenseOperate();\n    newClusterList()\n      .then((res) => {\n        setList(res);\n        if (res && res.length) {\n          setCookiePhyClusterName(res[0]);\n          setId(res[0]?.v1);\n          currentClusterInfoRef.current = res[0];\n          changeUrl(res[0]);\n        } else {\n          setCookiePhyClusterName(null);\n        }\n        setListLoading(false);\n      })\n      .catch(() => {\n        setCookiePhyClusterName(null);\n        setListLoading(false);\n      });\n    document.addEventListener(\"visibilitychange\", onHandleVisibleChange);\n    return () => {\n      currentClusterInfoRef.current = {};\n      document.removeEventListener(\"visibilitychange\", onHandleVisibleChange);\n    };\n  }, []);\n\n  const _getSenseOperate = async () => {\n    let params = { userName: getCookie(\"userName\") || \"\", content: \"\", projectId: getCurrentProject()?.id || \"\" };\n    let data = await getSenseOperate(params);\n    let content = \"\";\n    (data || []).forEach((item) => {\n      content += `${item}\\n`;\n    });\n    setContent(content);\n    setLoading(false);\n  };\n\n  const setCookiePhyClusterName = (clusterInfo) => {\n    //cookie设置是为了和DSL和kibana进行通信\n    const value = clusterInfo?.v2?.cluster || \"no bind phyCluster\";\n    setCookie([{ key: \"kibanaPhyClusterName\", value }]);\n  };\n\n  const changeUrl = (item) => {\n    const href = window.location.href;\n    let search = window.location.search;\n    let url = href.split(\"?\")?.[0];\n    if (!href.split(\"?\")?.[1]) {\n      return;\n    }\n    url = url.split(\"#\")[0];\n    let hash = window.location.hash.split(\"#\");\n    const urlParams = Url();\n    search = `?clusterId=${item.v2.id}&type=${item.v2.type}&currLeftMenu=${urlParams.search.currLeftMenu || \"kibana\"}`;\n    url = url + search + \"#\" + hash[hash.length - 1];\n\n    window.history.pushState(\n      {\n        url,\n      },\n      \"\",\n      url\n    );\n  };\n\n  const onHandleVisibleChange = () => {\n    if (!document.hidden) {\n      setCookiePhyClusterName(currentClusterInfoRef.current);\n    }\n  };\n\n  const onChange = (e) => {\n    const data = (list || []).filter((item) => item.v1 === e);\n    if (data && data.length) {\n      setCookiePhyClusterName(data[0]);\n      setId(e);\n      currentClusterInfoRef.current = data[0];\n      changeUrl(data[0]);\n    }\n  };\n\n  const onInputEditorChange = (content) => {\n    let contentArr = content?.split(\"\\n\");\n    if (contentArr?.length > 1000) {\n      content = contentArr?.slice(0, 1000)?.join(\"\\n\");\n    }\n    let params = { userName: getCookie(\"userName\") || \"\", content, projectId: getCurrentProject()?.id || \"\" };\n    setSenseOperate(params);\n  };\n\n  useDidCache(() => {\n    // 只有 keepalive 才会有路由跳转事件\n    clearSubscriptions();\n  });\n\n  useDidRecover(() => {\n    // TODO: 恢复定时器\n  });\n\n  const showNoClusterTip = () => {\n    XNotification({ type: \"error\", message: `执行错误，无集群信息。` });\n  };\n\n  return (\n    <>\n      <div className=\"common-page\">\n        {/* <div className=\"title\">DSL</div> */}\n        <div className=\"query-panel dsl\">\n          <span className=\"label\"></span>\n          <Select className=\"select\" placeholder=\"我的集群\" value={id} onChange={onChange} showSearch optionFilterProp=\"children\">\n            {list?.map((item) => (\n              <Option value={item.v1} key={uuid()}>\n                {item.v1}\n              </Option>\n            ))}\n          </Select>\n        </div>\n        <div className=\"content dsl\">\n          {!loading && !listLoading ? (\n            <DevToolsPage\n              consoleEditorValue={content}\n              onInputEditorChange={onInputEditorChange}\n              currentCluster={{ id, noInfoAction: showNoClusterTip }}\n              prefix={`${getCookie(\"userName\") || \"\"}-${getCurrentProject()?.id || \"\"}`}\n              notifications={XNotification}\n              IndexSelect={IndexSelect}\n              isSuperApp={!!isSuperApp()}\n            />\n          ) : null}\n        </div>\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/search-query/dsl-tpl.tsx",
    "content": "import React from \"react\";\nimport { connect } from \"react-redux\";\nimport { HashMenu } from \"knowdesign\";\nimport { getTabList, menuMap, MENU_MAP } from \"./config\";\nimport store from \"store\";\nimport { AppState } from \"store/type\";\nimport * as actions from \"actions\";\nimport { getCookie } from \"lib/utils\";\nimport { getProjectListByUserId } from \"api/app-api\";\nimport { IMenuItem } from \"typesPath/base-types\";\nimport \"./index.less\";\n\nconst mapStateToProps = (state) => ({\n  app: state.app,\n});\n\nexport const DslTpl = connect(mapStateToProps)((props: { app: AppState }) => {\n  const [reloadPage, setReloadPage] = React.useState<string>(\"\");\n  let FILTER_TAB_LIST = getTabList(setReloadPage).filter((item) => {\n    if (item.visible) {\n      return true;\n    }\n    return false;\n  });\n\n  const menuMap = new Map<string, IMenuItem>();\n\n  getTabList(setReloadPage).forEach((d) => {\n    menuMap.set(d.key, d);\n  });\n\n  const MENU_MAP = menuMap;\n\n  React.useEffect(() => {\n    const projectList = props.app.projectList;\n    if (!projectList?.length) {\n      const userId = getCookie(\"userId\");\n      getProjectListByUserId(+userId).then((res = []) => {\n        store.dispatch(actions.setProjectList(res));\n      });\n    }\n  }, []);\n\n  return (\n    <div className=\"hash-menu-container dsl-tpl\">\n      <HashMenu prefix=\"dsl-tpl\" TAB_LIST={FILTER_TAB_LIST} MENU_MAP={MENU_MAP} defaultHash={FILTER_TAB_LIST[0].key} data={reloadPage} />\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/search-query/error-query.tsx",
    "content": "import React, { memo, useEffect, useRef, useState } from \"react\";\nimport _ from \"lodash\";\nimport { SearchQueryForm } from \"./components\";\nimport { Tooltip } from \"antd\";\nimport { PERIOD_RADIO_MAP, errorQueryColumns } from \"./config\";\nimport { getErrorQueryList as getQueryList } from \"api/search-query\";\nimport { isSuperApp } from \"lib/utils\";\nimport { ProTable } from \"knowdesign\";\nimport \"./index.less\";\n\nconst classPrefix = \"error-query-container\";\n\nexport const ErrorQuery = (props: any) => {\n  const [queryParams, setQueryParams] = useState({\n    queryIndex: undefined,\n    startTime: undefined,\n    endTime: undefined,\n  });\n  const [dataSource, setDataSource] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const [page, setPage] = useState({\n    page: 1,\n    size: 10,\n  });\n  const [total, setTotal] = useState(0);\n\n  const isFirst = useRef(true);\n  const totalLimit = 10000;\n\n  const changeQueryParams = (params) => {\n    setQueryParams({ ...params });\n    page.page !== 1 && setPage({ ...page, page: 1 });\n  };\n\n  const getAsyncDataSource = async () => {\n    try {\n      setIsLoading(true);\n      let params = {\n        ...page,\n        ...queryParams,\n      };\n      const res = await getQueryList(params as any);\n      let dataSource = res?.bizData;\n      if (!dataSource) {\n        setDataSource([]);\n        return;\n      }\n      dataSource?.forEach((item, index) => {\n        item.key = index;\n      });\n      setDataSource(dataSource);\n      setTotal(res?.pagination.total);\n    } catch (error) {\n      setDataSource([]);\n      console.log(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const handleChange = (pagination) => {\n    setPage({\n      page: pagination.current,\n      size: pagination.pageSize,\n    });\n  };\n  useEffect(() => {\n    if (isFirst.current && !queryParams.startTime) {\n      isFirst.current = false;\n      return;\n    }\n    getAsyncDataSource();\n  }, [queryParams, page]);\n\n  useEffect(() => {\n    props?.menu === \"error-query\" && getAsyncDataSource();\n  }, [props?.menu]);\n\n  return (\n    <div className={classPrefix}>\n      <div className={`${classPrefix}-query`}>\n        <SearchQueryForm setSearchQuery={changeQueryParams} value={\"error-query\"} />\n      </div>\n\n      <div className={`${classPrefix}-table`}>\n        <ProTable\n          showQueryForm={false}\n          tableProps={{\n            tableId: \"error_search_query_table\",\n            isCustomPg: false,\n            showHeader: false,\n            loading: isLoading,\n            rowKey: \"key\",\n            dataSource: dataSource,\n            columns: errorQueryColumns(isSuperApp()),\n            paginationProps: {\n              total: total > totalLimit ? totalLimit : total,\n              current: page.page,\n              pageSize: page.size,\n              pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n              showTotal: (total) => `共 ${total} 条`,\n              itemRender: (pagination, type: \"page\" | \"prev\" | \"next\", originalElement) => {\n                const lastPage = totalLimit / page.size;\n                if (type === \"page\") {\n                  if (total > totalLimit && pagination === lastPage) {\n                    return <Tooltip title={`考虑到性能问题，只展示${totalLimit}条数据`}>{pagination}</Tooltip>;\n                  } else {\n                    return pagination;\n                  }\n                } else {\n                  return originalElement;\n                }\n              },\n            },\n            attrs: {\n              scroll: { x: \"max-content\" },\n              onChange: handleChange,\n            },\n          }}\n        />\n      </div>\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/search-query/index.less",
    "content": ".dsl-pb-20 {\n  padding-bottom: 20px;\n}\n\n.dsl-mr-20 {\n  margin-right: 20px;\n}\n.dcloud-drawer-title {\n  font-size: 18px;\n}\n.dcloud-drawer-header {\n  border: none;\n}\n.ant-btn {\n  border-radius: 4px;\n}\n\n.dsl-drawer {\n  margin-bottom: 20px;\n\n  &-title {\n    width: 100%;\n    height: 40px;\n    // background: #f9f9fa;\n    font-family: PingFangSC-Medium;\n    font-size: 16px;\n    color: #1d2330;\n    text-align: left;\n    line-height: 40px;\n    margin-bottom: 24px;\n    padding-left: 24px;\n  }\n\n  &-box {\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    width: 90%;\n    position: relative;\n    padding-left: 20px;\n    font-size: 14px;\n    .ant-descriptions-item-content {\n      font-size: 14px;\n    }\n  }\n\n  &-icon {\n    cursor: pointer;\n    position: absolute;\n    line-height: 16px;\n    left: 0px;\n    top: 4px;\n  }\n\n  &-icon:hover {\n    position: absolute;\n  }\n}\n\n.two-row-ellipsis {\n  text-overflow: -o-ellipsis-lastline;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-line-clamp: 2;\n  line-clamp: 2;\n  -webkit-box-orient: vertical;\n}\n\n.dsl-overflow-auto {\n  overflow: auto;\n  max-height: 300px;\n}\n\n.dsl-vw-5 {\n  max-width: 6vw;\n}\n\n.dsl-float-right {\n  float: right;\n}\n\n.dsl-query-tpl {\n  &-search {\n    padding-bottom: 10px;\n    &-reset {\n      margin-right: 10px;\n      float: right;\n    }\n    &-submit {\n      margin-right: 10px;\n      float: right;\n    }\n    .table-header-box-title {\n      font-size: 18px;\n      font-weight: 500;\n    }\n  }\n}\n\n.error-query-container {\n  &-query {\n    margin-bottom: 12px;\n  }\n  .error-query-container-table {\n    .error-query-container-table-cell {\n      width: 12vw;\n    }\n  }\n}\n\n.slow-query-container {\n  &-query {\n    margin-bottom: 12px;\n  }\n  .slow-query-container-table {\n    .slow-query-container-table-cell {\n      width: 10vw;\n    }\n  }\n}\n\n.iframe-search {\n  min-height: 800px !important;\n}\n\n.hiddenMenuHeader {\n  .select-contain {\n    position: absolute;\n    right: 24px;\n    top: 16px;\n    z-index: 100;\n\n    .cluster-label {\n      font-family: PingFangSC-Medium;\n      font-size: 12px;\n      color: #303a51;\n      font-weight: 500;\n    }\n\n    .select-cluster {\n      width: 242px;\n      height: 30px;\n      border-radius: 2px;\n      background-color: #ffffff;\n      border-color: #dcdfe6;\n    }\n  }\n\n  .ant-menu {\n    display: none;\n  }\n\n  background: #fff;\n  position: relative;\n  overflow: hidden;\n\n  .detail-tabs {\n    height: 32px;\n    background: #f4f4f6;\n    border-radius: 4px;\n    margin-bottom: 16px;\n    margin-top: 16px;\n    margin-left: 20px;\n    display: flex;\n    padding: 4px;\n    justify-content: space-between;\n\n    &-item {\n      // width: 72px;\n      height: 24px;\n      border-radius: 4px;\n      font-family: PingFangSC-Medium;\n      font-size: 14px;\n      color: #5b6675;\n      line-height: 20px;\n      text-align: center;\n      cursor: pointer;\n      user-select: text;\n      padding: 2px 8px 2px 8px;\n    }\n\n    .check {\n      background: #ffffff;\n      color: @primary-color;\n    }\n  }\n}\n\n.search-query-table-content {\n  min-width: 800px;\n  padding: 12px 20px;\n  background: #fff;\n\n  ul {\n    line-height: 28px;\n  }\n\n  .ant-menu-item {\n    margin: 0 40px 0 0 !important;\n  }\n}\n\n.search-query-detail-wrapper {\n  min-width: 800px;\n  background-color: #fff;\n  padding: 18px;\n}\n\n.search-template-table {\n  padding: 0 20px 40px 20px;\n  background: #fff;\n}\n\n.dsl-query-tpl-search {\n  background: #fff;\n  padding: 20px;\n}\n\n.search-template-form {\n  padding-top: 20px;\n\n  .search-template-button {\n    display: flex;\n    align-items: center;\n\n    .ant-btn-primary {\n      margin: 10px;\n    }\n  }\n}\n\n.common-page {\n  background-color: transparent;\n  padding: 16px 20px;\n  border-radius: 4px;\n  position: relative;\n  .devApp__container {\n    background: #fff;\n  }\n\n  .title {\n    font-family: PingFangSC-Medium;\n    font-size: 18px;\n    color: rgba(0, 0, 0, 0.87);\n    line-height: 28px;\n    font-weight: 500;\n  }\n\n  .query-panel {\n    position: absolute;\n    right: 20px;\n    top: 16px;\n\n    &.dsl {\n      top: 18px;\n      z-index: 9;\n    }\n\n    .label {\n      font-family: PingFangSC-Regular;\n      font-size: 14px;\n      color: rgba(0, 0, 0, 0.6);\n      text-align: right;\n      line-height: 20px;\n      font-weight: 400;\n    }\n\n    .select {\n      width: 300px;\n      height: 32px;\n      background: #ffffff;\n      border-radius: 4px;\n\n      .dcloud-select-selector {\n        border-radius: 4px;\n        border: 1px solid rgba(0, 0, 0, 0.13);\n      }\n    }\n    .dcloud-select.dcloud-select-single .dcloud-select-selector {\n      height: 32px;\n    }\n    .dcloud-select-single .dcloud-select-selector .dcloud-select-selection-item {\n      line-height: 32px;\n      color: rgba(0, 0, 0, 0.6);\n    }\n  }\n\n  .content {\n    margin-top: 36px;\n    overflow-y: overlay;\n\n    &.kibana {\n      height: calc(100vh - 188px);\n    }\n\n    &.sql {\n      height: calc(100vh - 140px);\n      margin-top: 16px;\n      background: #fff;\n      border-radius: 8px;\n      padding: 0 20px 0 20px;\n    }\n\n    &.dsl {\n      margin-top: 0px;\n      height: calc(100vh - 96px);\n      border-radius: 8px;\n\n      .application {\n        z-index: inherit;\n        .euiTabs {\n          overflow: visible;\n          .euiToolTipAnchor {\n            font-family: PingFangSC-Regular;\n            font-size: 18px;\n            .euiTab__content {\n              font-size: 16px;\n            }\n            .euiTab-isSelected {\n              font-family: PingFangSC-Semibold;\n              color: rgba(0, 0, 0, 0.87);\n            }\n          }\n        }\n        .euiTabs {\n          &::before {\n            background: transparent;\n          }\n        }\n        .euiTextColor--subdued {\n          h1 {\n            margin: 30px 0 2px 0;\n            font-size: 14px;\n          }\n        }\n      }\n    }\n\n    &.kibana {\n      margin-top: 16px;\n    }\n\n    .euiTabs {\n      height: 38px;\n      line-height: 38px;\n      margin-bottom: 16px;\n    }\n\n    .euiTab {\n      padding: 0px 0px 8px;\n      font-size: 14px;\n      font-weight: 600;\n      margin-right: 24px;\n      color: rgba(0, 0, 0, 0.6);\n      font-family: PingfangSC-Semibold;\n    }\n\n    .euiTab.euiTab-isSelected {\n      color: @primary-color;\n    }\n\n    .euiTab.euiTab-isSelected::after {\n      background-color: @primary-color;\n      height: 4px;\n      border-radius: 8px;\n    }\n\n    .euiTabs:not(.euiTabs--condensed)::before {\n      background-color: #dbe0e4;\n    }\n\n    .euiTab:focus {\n      background-color: #fff;\n      text-decoration: none;\n    }\n\n    .euiTab:hover:not(.euiTab-isSelected) {\n      text-decoration: none;\n    }\n\n    .search-profiler-page {\n      .appRoot {\n        height: calc(100vh - 150px);\n      }\n\n      .euiTabs {\n        height: 32px;\n        line-height: 32px;\n      }\n\n      .euiTab {\n        padding: 0px;\n        margin-right: 0px;\n        padding: 6px 9px;\n      }\n\n      .euiTab.euiTab-isSelected {\n        height: 28px;\n      }\n    }\n  }\n}\n\n.search-query-reload {\n  font-size: 20px;\n  color: #74788d;\n  cursor: pointer;\n  position: absolute;\n  right: 24px;\n}\n\n.dsl-tpl-table-content {\n  padding: 16px;\n  .ant-menu-horizontal {\n    border: none;\n    line-height: 38px;\n    .ant-menu-item {\n      font-family: PingFangSC-Regular;\n      font-size: 18px;\n      line-height: 22px;\n      font-weight: 400;\n      padding-bottom: 8px;\n    }\n  }\n}\n\n.dsl-tpl-detail-wrapper {\n  margin: 0 24px 0 24px;\n  padding-top: 16px;\n  background-color: #fff;\n  height: calc(100vh - 138px);\n  border-radius: 8px;\n}\n\n.option-filter-columns {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  &-icon {\n    margin-left: 10px;\n  }\n}\n//补充样式\n.common-page .devApp__container {\n  border-radius: 8px;\n}\n#consoleRoot {\n  background: #fff;\n  border-radius: 8px;\n}\n.euiTab:focus {\n  background-color: #f5f7fa;\n}\n.search-profiler-page .appRoot {\n  height: calc(100vh - 172px);\n}\n.search-profiler-page .euiPage {\n  padding: 20px;\n  padding-top: 16px;\n}\n.euiFormRow__labelWrapper {\n  display: none;\n}\n.application .ace-tm .ace_gutter {\n  background: #f5f7fa;\n}\n.application .ace-tm .ace_gutter-active-line {\n  background: rgba(0, 0, 0, 0.04);\n}\n.common-page .content .search-profiler-page .euiTab.euiTab-isSelected::after {\n  height: 0;\n}\n.search-profiler-page .prfDevTool__main {\n  margin-top: 48px;\n}\n.search-profiler-page .euiTabs {\n  position: absolute;\n  right: 30px;\n}\n.conApp__resizer:focus,\n.conApp__resizer.active {\n  background-color: #fff;\n}\n.euiFlyout {\n  top: 118px;\n  height: 79%;\n}\n.search-profiler-page .prfDevTool__main {\n  border-left: none;\n  border-radius: 0 4px 4px 0;\n}\n.prfDevTool__page__bodyGroup .prfDevTool__sense {\n  margin: 4px 4px 4px 0;\n}\n.search-profiler-page .prfDevTool__main {\n  margin-top: 52px;\n  margin-bottom: 4px;\n  margin-left: -12px;\n}\n.search-profiler-page .prfDevTool__sense .ace_editor {\n  border-radius: 4px 0 0 4px;\n}\n.prfDevTool__sense .ace_editor {\n  outline: none;\n  border: solid 1px #d3dae6;\n  border-right: none;\n}\n.search-profiler-page {\n  .prfDevTool__profileTree__shardDetails {\n    .spacer {\n      width: 4px;\n      height: 12px;\n      margin-right: 8px;\n    }\n    .title {\n      font-size: 16px;\n    }\n  }\n  .prfDevTool__percentBadge__progress--time {\n    background-image: linear-gradient(\n      to left,\n      #1473ff 0%,\n      #1473ff var(--prfDevToolProgressPercentage, auto),\n      #f7f7f9 var(--prfDevToolProgressPercentage, auto),\n      #f7f7f9 100%\n    );\n    border-radius: 4px;\n  }\n  .prfDevTool__profileTree__cell .euiIcon--medium {\n    zoom: 0.4;\n  }\n  .ace_editor.ace-tm {\n    font-size: 14px;\n  }\n}\n.dsl-tpl {\n  .hash-menu {\n    background: transparent;\n    height: calc(100vh - 72px);\n    .dcloud-menu {\n      border-radius: 8px 8px 0 0;\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/search-query/kibana-page.tsx",
    "content": "import React, { useState, useEffect, useRef } from \"react\";\nimport { setCookie, uuid } from \"lib/utils\";\nimport { XNotification } from \"component/x-notification\";\nimport { Select } from \"antd\";\nimport { newClusterList } from \"api/cluster-api\";\nimport Url from \"lib/url-parser\";\nimport { PageIFrameContainer } from \"container/iframe-page\";\n\nconst Option = Select.Option;\n\nexport const KibanaPage = () => {\n  const [id, setId] = useState(null);\n  const [list, setList] = useState([]);\n  const currentClusterInfoRef = useRef({});\n\n  useEffect(() => {\n    newClusterList()\n      .then((res) => {\n        setList(res);\n        if (res && res.length) {\n          setCookiePhyClusterName(res[0]);\n          setId(res[0]?.v1);\n          currentClusterInfoRef.current = res[0];\n          changeUrl(res[0]);\n        } else {\n          setCookiePhyClusterName(null);\n        }\n      })\n      .catch(() => {\n        setCookiePhyClusterName(null);\n      });\n    document.addEventListener(\"visibilitychange\", onHandleVisibleChange);\n    return () => {\n      currentClusterInfoRef.current = {};\n      document.removeEventListener(\"visibilitychange\", onHandleVisibleChange);\n    };\n  }, []);\n\n  const setCookiePhyClusterName = (clusterInfo) => {\n    //cookie设置是为了和DSL和kibana进行通信\n    const value = clusterInfo?.v2?.cluster || \"no bind phyCluster\";\n    setCookie([{ key: \"kibanaPhyClusterName\", value }]);\n  };\n\n  const changeUrl = (item) => {\n    const href = window.location.href;\n    let search = window.location.search;\n    let url = href.split(\"?\")?.[0];\n    if (!href.split(\"?\")?.[1]) {\n      return;\n    }\n    url = url.split(\"#\")[0];\n    let hash = window.location.hash.split(\"#\");\n    const urlParams = Url();\n    search = `?clusterId=${item.v2.id}&type=${item.v2.type}&currLeftMenu=${urlParams.search.currLeftMenu || \"kibana\"}`;\n    url = url + search + \"#\" + hash[hash.length - 1];\n\n    window.history.pushState(\n      {\n        url,\n      },\n      \"\",\n      url\n    );\n  };\n\n  const onHandleVisibleChange = () => {\n    if (!document.hidden) {\n      setCookiePhyClusterName(currentClusterInfoRef.current);\n    }\n  };\n\n  const onChange = (e) => {\n    const data = (list || []).filter((item) => item.v1 === e);\n    if (data && data.length) {\n      setCookiePhyClusterName(data[0]);\n      setId(e);\n      currentClusterInfoRef.current = data[0];\n      changeUrl(data[0]);\n    }\n  };\n\n  return (\n    <>\n      <div className=\"common-page\">\n        <div className=\"title\">Kibana</div>\n        <div className=\"query-panel\">\n          <span className=\"label\">我的集群: </span>\n          <Select className=\"select\" value={id} onChange={onChange} showSearch optionFilterProp=\"children\">\n            {list?.map((item) => (\n              <Option value={item.v1} key={uuid()}>\n                {item.v1}\n              </Option>\n            ))}\n          </Select>\n        </div>\n        <div className=\"content kibana\">\n          <PageIFrameContainer className=\"iframe-search\" src={`/console/arius/kibana7/app/kibana#/discover?_g=()`} />\n        </div>\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/search-query/query-tpl.tsx",
    "content": "import React, { useState, useCallback, useRef, useEffect } from \"react\";\nimport { Row, Col, Form, Input, Select, Button, Tooltip } from \"antd\";\nimport moment from \"moment\";\nimport { connect } from \"react-redux\";\nimport { getQueryTplColumns, filterColumnsList, customTimeOptions } from \"./config\";\nimport { getDslList, getCheckedList, setCheckedList } from \"api/search-query\";\nimport { DTable } from \"component/dantd/dtable\";\nimport DslDetail from \"../drawer/dsl-detail\";\nimport EditLimit from \"./components/editLimit\";\nimport FilterColumns from \"component/filterColumns\";\nimport { SearchTemplatePermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { AppState } from \"store/type\";\nimport { isSuperApp, filterOption, getCookie, getCurrentProject } from \"lib/utils\";\nimport { ProTable } from \"knowdesign\";\nimport { RenderTitle } from \"component/render-title\";\nimport { getQueryFormConfig } from \"./config\";\nimport \"./index.less\";\nimport store from \"store\";\n\nconst appInfo = {\n  app: store.getState().app.appInfo,\n  user: store.getState().user.getName,\n};\n\nconst mapStateToProps = (state) => ({\n  app: state.app,\n});\n\nexport const QueryTpl = connect(mapStateToProps)((props: { app: AppState }) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const defaultRangeKey = 0;\n  const [loading, setloading] = useState(false);\n  const [data, setData] = useState([] as any[]);\n  const [queryForm, setQueryForm] = useState({ MD5: \"\", projectId: null, queryIndex: \"\" });\n  const [startTime, setStartTime] = useState(moment(new Date().getTime() - customTimeOptions[defaultRangeKey]?.value) as any); // 默认近2小时\n  const [endTime, setEndTime] = useState(moment() as any);\n  const [visible, setVisible] = useState(false);\n  const [selectedRowKeys, setSelectedRowKeys] = useState([]);\n  const [records, setRecords] = useState([]);\n  const [selectItem, setSelectItem] = useState([]);\n  const [editVisible, setEditVisible] = useState(false);\n  const [record, setRecord] = useState({});\n  const [columns, setColumns] = useState([]);\n  const [filterColumnsVisible, setFilterColumnsVisible] = useState(false);\n  const buttonTime = useRef(null);\n  const error = useRef(false);\n  const superApp = isSuperApp();\n\n  const [pagination, setPagination] = useState({\n    position: \"bottomRight\",\n    showQuickJumper: true,\n    total: 0,\n    showSizeChanger: true,\n    pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n    showTotal: (total) => `共 ${total} 条`,\n    current: 1,\n    pageSize: 10,\n  });\n  const [page, setPage] = useState({\n    page: 1,\n    size: 10,\n    sortInfo: \"\",\n    orderByDesc: true,\n  });\n\n  useEffect(() => {\n    reloadData();\n  }, [department, page, queryForm]);\n\n  const onSelectChange = (selectedRowKeys, records) => {\n    setSelectItem(records);\n    setSelectedRowKeys(selectedRowKeys);\n  };\n\n  const rowSelection = {\n    selectedRowKeys,\n    onChange: onSelectChange,\n  };\n\n  const reloadData = () => {\n    // 校验不通过时不发送请求\n    if (error.current) {\n      return;\n    }\n    setloading(true);\n    const currentTime = new Date().getTime();\n    const params = {\n      ...page,\n      startTime: startTime ? (buttonTime.current ? currentTime - (endTime?.valueOf() - startTime?.valueOf()) : startTime?.valueOf()) : \"\",\n      endTime: endTime ? (buttonTime.current ? currentTime : endTime?.valueOf()) : \"\",\n      projectId: superApp ? queryForm.projectId : null,\n      dslTemplateMd5: queryForm.MD5,\n      queryIndex: queryForm.queryIndex,\n    };\n    getDslList(params)\n      .then((res: any) => {\n        if (res) {\n          res?.bizData.forEach((item, index) => {\n            item.key = `${item.projectId}${index}`;\n          });\n          setData(res?.bizData);\n          const { pageNo = 1, pageSize = 10 } = res.pagination;\n          setPagination({\n            ...pagination,\n            total: res?.pagination?.total,\n            current: pageNo,\n            pageSize: pageSize,\n          });\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const handleChange = (pagination, _, tableParams) => {\n    setPage({\n      page: pagination.current,\n      size: pagination.pageSize,\n      sortInfo: tableParams.order === \"ascend\" || tableParams.order === \"descend\" ? tableParams.field : null,\n      orderByDesc: tableParams.order === \"ascend\" || tableParams.order === \"descend\" ? tableParams.order !== \"ascend\" : null,\n    });\n  };\n\n  const onCancel = () => {\n    setVisible(false);\n  };\n\n  const showDrawer = (record: any) => {\n    setRecord(record);\n    setVisible(true);\n  };\n\n  const onSearch = (result) => {\n    const { MD5, projectId, queryIndex } = result;\n    setQueryForm({ MD5, projectId, queryIndex });\n    setPage({\n      ...page,\n      page: 1,\n      size: page.size,\n    });\n  };\n\n  const onReset = () => {\n    setStartTime(\"\");\n    setEndTime(\"\");\n    setQueryForm({ MD5: \"\", projectId: null, queryIndex: \"\" });\n  };\n\n  const handleTimeChange = (times: number[], periodOrPicker: boolean) => {\n    if (times) {\n      setStartTime(moment(Number(times[0])));\n      setEndTime(moment(Number(times[1])));\n      buttonTime.current = periodOrPicker;\n    }\n  };\n\n  const getCheckList = async () => {\n    const checkList = await getCheckedList();\n    return checkList;\n  };\n\n  const saveCheckFn = async (list: string[]) => {\n    await setCheckedList(list);\n  };\n\n  const getOpBtns = useCallback(() => {\n    return (\n      <>\n        {hasOpPermission(SearchTemplatePermissions.PAGE, SearchTemplatePermissions.BAT_MODIFY) &&\n          (selectItem && selectItem.length >= 1 ? (\n            <Tooltip title={selectItem && selectItem.length ? \"\" : \"需要选中后批量修改\"}>\n              <Button\n                onClick={() => showEditLimit()}\n                type=\"primary\"\n                style={{ marginRight: 0 }}\n                disabled={selectItem && selectItem.length ? false : true}\n              >\n                批量修改限流值\n              </Button>\n            </Tooltip>\n          ) : (\n            \"\"\n          ))}\n      </>\n    );\n  }, [selectItem]);\n\n  const editCancel = () => {\n    setEditVisible(false);\n    setRecords([]);\n  };\n\n  const showEditLimit = (record?: any) => {\n    if (record) {\n      setRecords([record]);\n    } else {\n      setRecords(selectItem);\n    }\n    setEditVisible(true);\n  };\n\n  const renderTitleContent = () => {\n    return {\n      title: \"查询模板\",\n      content: null,\n    };\n  };\n\n  return (\n    <div className=\"table-layout-style\">\n      <ProTable\n        showQueryForm={true}\n        queryFormProps={{\n          defaultCollapse: true,\n          columns: getQueryFormConfig(props.app.projectList, handleTimeChange, filterOption, superApp, error),\n          onReset: onReset,\n          onSearch: onSearch,\n          isResetClearAll: true,\n        }}\n        tableProps={{\n          tableId: \"query_tpl_table\",\n          isCustomPg: false,\n          loading,\n          rowKey: \"key\",\n          dataSource: data,\n          columns: columns,\n          reloadData,\n          isDividerHide: selectItem.length > 0,\n          getJsxElement: getOpBtns,\n          customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n          paginationProps: pagination,\n          attrs: {\n            onChange: handleChange,\n            scroll: { x: \"max-content\" },\n            rowSelection: rowSelection,\n          },\n        }}\n      />\n      <DslDetail\n        history={(props as any).history}\n        visible={visible}\n        detailData={record}\n        onCancel={onCancel}\n        cb={reloadData}\n        showEditLimit={showEditLimit}\n      />\n      <EditLimit\n        history={(props as any).history}\n        appInfo={appInfo}\n        visible={editVisible}\n        record={records}\n        cancel={editCancel}\n        cb={reloadData}\n      />\n      <FilterColumns\n        columns={getQueryTplColumns(reloadData, showDrawer, showEditLimit, superApp, setFilterColumnsVisible, props)}\n        setColumns={setColumns}\n        checkArr={filterColumnsList}\n        getCheckFn={getCheckList}\n        saveCheckFn={saveCheckFn}\n        filterColumnsVisible={filterColumnsVisible}\n        setFilterColumnsVisible={setFilterColumnsVisible}\n        sortObj={page}\n      />\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/search-query/slow-query.tsx",
    "content": "import React, { memo, useEffect, useRef, useState } from \"react\";\nimport _ from \"lodash\";\nimport { SearchQueryForm } from \"./components\";\nimport { Tooltip } from \"antd\";\nimport { PERIOD_RADIO_MAP, slowQueryColumns } from \"./config\";\nimport { getSlowQueryList as getQueryList } from \"api/search-query\";\nimport { isSuperApp } from \"lib/utils\";\nimport { ProTable } from \"knowdesign\";\nimport \"./index.less\";\n\nconst classPrefix = \"slow-query-container\";\n\nexport const SlowQuery = (props: any) => {\n  const [queryParams, setQueryParams] = useState({\n    queryIndex: undefined,\n    startTime: undefined,\n    endTime: undefined,\n    totalCost: undefined,\n  });\n  const [dataSource, setDataSource] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const [page, setPage] = useState({\n    page: 1,\n    size: 10,\n    sortTerm: \"\",\n    orderByDesc: true,\n  });\n  const [total, setTotal] = useState(0);\n\n  const isFirst = useRef(true);\n  const totalLimit = 10000;\n\n  const changeQueryParams = (params) => {\n    setQueryParams({ ...params });\n    page.page !== 1 && setPage({ ...page, page: 1 });\n  };\n\n  const getAsyncDataSource = async () => {\n    try {\n      setIsLoading(true);\n      let params = {\n        ...page,\n        ...queryParams,\n      };\n      const res: any = await getQueryList(params as any);\n      let dataSource = res?.bizData;\n      if (!dataSource) {\n        setDataSource([]);\n        return;\n      }\n      dataSource?.forEach((item, index) => {\n        item.key = index;\n      });\n      setDataSource(dataSource);\n      setTotal(res?.pagination.total);\n    } catch (error) {\n      setDataSource([]);\n      console.log(error);\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const handleChange = (pagination, _, tableParams) => {\n    setPage({\n      page: pagination.current,\n      size: pagination.pageSize,\n      sortTerm: tableParams.order === \"ascend\" || tableParams.order === \"descend\" ? tableParams.field : null,\n      orderByDesc: tableParams.order === \"ascend\" || tableParams.order === \"descend\" ? tableParams.order !== \"ascend\" : null,\n    });\n  };\n\n  useEffect(() => {\n    if (isFirst.current && !queryParams.startTime) {\n      isFirst.current = false;\n      return;\n    }\n    getAsyncDataSource();\n  }, [queryParams, page]);\n\n  useEffect(() => {\n    props?.menu === \"slow-query\" && getAsyncDataSource();\n  }, [props?.menu]);\n\n  return (\n    <div className={classPrefix}>\n      <div className={`${classPrefix}-query`}>\n        <SearchQueryForm setSearchQuery={changeQueryParams} isSlow value={\"slow-query\"} />\n      </div>\n      <div className={`${classPrefix}-table`}>\n        <ProTable\n          showQueryForm={false}\n          // queryFormProps={{\n          //   defaultCollapse: true,\n          //   columns: slowQueryColumns(isSuperApp()),\n          //   isResetClearAll: true,\n          // }}\n          tableProps={{\n            tableId: \"slow_query_table\",\n            isCustomPg: false,\n            showHeader: false,\n            loading: isLoading,\n            rowKey: \"key\",\n            dataSource: dataSource,\n            columns: slowQueryColumns(isSuperApp()),\n            paginationProps: {\n              total: total > totalLimit ? totalLimit : total,\n              current: page.page,\n              pageSize: page.size,\n              pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n              showTotal: (total) => `共 ${total} 条`,\n              itemRender: (pagination, type: \"page\" | \"prev\" | \"next\", originalElement) => {\n                const lastPage = totalLimit / page.size;\n                if (type === \"page\") {\n                  if (total > totalLimit && pagination === lastPage) {\n                    return <Tooltip title={`考虑到性能问题，只展示${totalLimit}条数据`}>{pagination}</Tooltip>;\n                  } else {\n                    return pagination;\n                  }\n                } else {\n                  return originalElement;\n                }\n              },\n            },\n            attrs: {\n              scroll: { x: \"max-content\" },\n              onChange: handleChange,\n            },\n          }}\n        />\n      </div>\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/search-query/sql-index.less",
    "content": ".text-oh {\n  white-space: nowrap;\n  max-width: 150px;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n\n.sql-query-page {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  .ant-form-vertical .ant-form-item-label,\n  .ant-col-24.ant-form-item-label,\n  .ant-col-xl-24.ant-form-item-label {\n    padding: 0px 0px 2px;\n  }\n  .title-prefix {\n    display: inline-block;\n    height: 12px;\n    width: 3px;\n    background: #1473ff;\n    border-radius: 1px;\n    margin-right: 6px;\n  }\n\n  .CodeMirror {\n    height: auto;\n    min-height: 200px;\n    height: 100%;\n    background: #f5f7fa;\n    padding-top: 12px;\n    border-radius: 4px;\n    font: 12px / normal \"Monaco\", \"Menlo\", \"Ubuntu Mono\", \"Consolas\", \"source-code-pro\", monospace;\n  }\n\n  .CodeMirror-lines {\n    padding: 0px;\n  }\n\n  .CodeMirror-line {\n    padding-right: 140px !important;\n    min-height: 20px !important;\n    color: #05a !important;\n  }\n\n  .cm-s-default .cm-keyword {\n    color: #c80a68 !important;\n  }\n\n  .cm-s-default .cm-operator {\n    color: #303a51 !important;\n  }\n\n  .CodeMirror-activeline-gutter,\n  .CodeMirror-activeline-background {\n    background-color: rgba(0, 0, 0, 0.04);\n  }\n\n  .CodeMirror-line-container {\n    min-height: 20px;\n    font-size: 14px;\n    .query {\n      font-size: 12px;\n    }\n  }\n\n  .CodeMirror-code {\n    max-width: 1000px;\n  }\n\n  .top-console-open {\n    display: flex;\n    flex: 1;\n    transition: all 1s;\n    max-height: 500px;\n    padding: 8px 0px;\n    padding-right: 0px;\n    overflow: auto;\n    overflow-y: hidden;\n\n    .codemirror-contain {\n      flex: 1;\n      //max-width: 600px;\n      min-width: 860px;\n      height: 100%;\n\n      .CodeMirror-scroll {\n        background-color: #f8f9fa;\n      }\n\n      .CodeMirror-gutters {\n        border-right: none;\n        background-color: #f8f9fa;\n        color: #69707d;\n      }\n\n      .codemirror-title {\n        display: flex;\n        align-items: center;\n        width: 100%;\n        height: 36px;\n        background: #fff;\n        border-bottom: hidden;\n        border-radius: 4px 4px 0 0;\n        font-size: 14px;\n        color: rgba(0, 0, 0, 0.87);\n        line-height: 36px;\n        font-weight: 500;\n      }\n\n      .codemirror {\n        min-height: 200px;\n        height: calc(100% - 36px);\n        border-radius: 0 0 4px 4px;\n      }\n    }\n\n    .tip-content {\n      flex: 1;\n\n      .text-link {\n        color: @primary-color;\n      }\n\n      .index-ul {\n        height: 250px;\n        overflow: auto;\n\n        li:hover {\n          cursor: pointer;\n          background-color: #d2d9e6;\n        }\n      }\n    }\n\n    .arrow-right {\n      margin-top: 20%;\n      margin-left: 10px;\n      margin-right: 10px;\n      border: 1px dashed #ccc;\n    }\n\n    .expand-btn {\n      width: 40px;\n      position: relative;\n    }\n\n    &-open {\n      min-height: 420px;\n      padding: 8px 0px;\n    }\n\n    .field-box {\n      transition: all 1s;\n      width: 0%;\n      display: flex;\n      flex-wrap: wrap;\n      padding: 0px 0px;\n      overflow: hidden;\n\n      &-open {\n        width: 50%;\n      }\n    }\n  }\n\n  .bottom-console {\n    position: relative;\n    padding-top: 8px;\n    min-height: 200px;\n    height: 100%;\n    flex: 1;\n\n    .ant-table.ant-table-bordered > .ant-table-container {\n      border: 1px solid #ebedef;\n    }\n\n    .data-table {\n      overflow-x: scroll;\n      border-top: 0;\n      margin-top: 8px;\n    }\n  }\n\n  .index-temp {\n    margin-left: 16px;\n    border-radius: 4px;\n    height: 100%;\n  }\n\n  .indextemp-input {\n    width: 100%;\n    margin-bottom: 8px;\n  }\n\n  .mapping-input {\n    margin: 16px 0px 0px 26px;\n    width: calc(45%);\n  }\n\n  .tooltip-title {\n    overflow: scroll;\n    max-height: 500px;\n  }\n\n  .detail-tabs {\n    position: absolute;\n    width: auto;\n    height: 28px;\n    right: 0;\n    top: 0;\n    margin-top: 0;\n    margin-bottom: 0;\n\n    &-item {\n      height: auto;\n      padding: 0px 8px;\n      width: auto;\n    }\n  }\n\n  .iam-box {\n    //width: 100%\n    height: 100%;\n    min-width: 278px;\n    background: #f8f9fa;\n    border-radius: 4px;\n    display: flex;\n    flex-direction: column;\n    overflow: hidden;\n    &-title {\n      display: flex;\n      align-items: center;\n      line-height: 36px;\n      background-color: #fff;\n      font-size: 14px;\n      font-weight: 500;\n    }\n\n    .ant-form {\n      margin: 16px 20px 0 20px;\n    }\n\n    .ant-form-item-label > label {\n      font-family: PingFangSC-Regular;\n      color: rgba(0, 0, 0, 0.87);\n      font-weight: 400;\n    }\n\n    .index-container {\n      display: flex;\n      height: 300px;\n\n      .index-tabs-contain {\n        flex: 1;\n        display: flex;\n        flex-direction: column;\n\n        .iam-head-tip {\n          //position: absolute;\n          //top: 0;\n          //width: 48.5%;\n          height: 36px;\n          padding: 7px 0px 7px 15px;\n          border-radius: 4px 4px 0 0;\n          background: #f9f9fa;\n\n          .color-text {\n            display: inline-block;\n            width: 2px;\n            height: 10px;\n            margin-right: 4px;\n            background: #2f81f9;\n            border-radius: 1px;\n          }\n\n          span {\n            font-family: PingFangSC-Medium;\n            font-size: 12px;\n            color: #303a51;\n            line-height: 22px;\n            font-weight: 500;\n          }\n        }\n\n        .index-tabs {\n          flex: 1;\n          white-space: nowrap;\n          overflow: auto;\n          border-radius: 0 0 4px 4px;\n          background: #f9f9fa;\n\n          .index-tabs-item {\n            height: 40px;\n            padding: 0 0 0 20px;\n            line-height: 40px;\n            background: #f9f9fa;\n\n            &-content {\n              display: flex;\n              align-items: center;\n              justify-content: space-between;\n            }\n          }\n\n          .index-tabs-item:hover {\n            cursor: pointer;\n            background-color: rgba(0, 0, 0, 0.04);\n          }\n\n          .check {\n            background: #f1f7ff;\n            color: #1473ff;\n          }\n        }\n      }\n\n      .mapping-tab {\n        width: 57%;\n        padding-left: 10px;\n\n        .ant-table-placeholder {\n          height: 215px;\n        }\n\n        .ant-table-cell {\n          padding: 8px 0 8px 10px;\n        }\n\n        .ant-table-thead .ant-table-cell {\n          font-weight: 400 !important;\n        }\n\n        .mapping-title {\n          height: 36px;\n          padding: 7px 0px 7px 0;\n          border-radius: 4px 4px 0 0;\n\n          .color-text {\n            display: inline-block;\n            width: 2px;\n            height: 10px;\n            margin-right: 4px;\n            background: #2f81f9;\n            border-radius: 1px;\n          }\n\n          span {\n            font-family: PingFangSC-Medium;\n            font-size: 12px;\n            color: #303a51;\n            line-height: 22px;\n            font-weight: 500;\n          }\n        }\n      }\n    }\n\n    li {\n      list-style: none;\n    }\n\n    ul {\n      padding-left: 16px;\n      margin-top: 5px;\n    }\n\n    &-icon {\n      width: 12px;\n      height: 12px;\n      opacity: 0.6;\n      color: #666666;\n    }\n  }\n\n  .query {\n    position: absolute;\n    right: 20px;\n    top: 0;\n    z-index: 10;\n    cursor: pointer;\n    display: flex;\n    justify-content: space-around;\n\n    i {\n      color: #20a0ff;\n    }\n\n    .dsl_icon {\n      border: 1px solid #20a0ff;\n      display: inline-block;\n      border-radius: 6px;\n      padding: 0px 6px;\n      height: 18px;\n      line-height: 16px;\n      margin-right: 5px;\n      font-style: italic;\n      color: #20a0ff;\n      cursor: pointer;\n\n      &:hover {\n        background-color: #20a0ff;\n        color: #fff;\n\n        i {\n          color: #fff;\n        }\n      }\n    }\n\n    .explain_icons {\n      border: 1px solid #20a0ff;\n      display: inline-block;\n      border-radius: 6px;\n      padding: 0px 6px;\n      height: 18px;\n      line-height: 16px;\n      margin-right: 5px;\n      font-style: italic;\n      color: #20a0ff;\n      cursor: pointer;\n\n      &:hover {\n        background-color: #20a0ff;\n        color: #fff;\n\n        i {\n          color: #fff;\n        }\n      }\n    }\n  }\n\n  .box-right {\n    border: 1px solid #ebedef;\n    border-radius: 4px 4px 4px 4px;\n    flex-grow: 1;\n    min-height: 100px;\n    padding-left: 0px;\n    margin-top: 8px;\n\n    .ace_editor {\n      height: calc(50vh - 160px);\n      min-height: 160px;\n      background-color: #f8f9fa;\n    }\n  }\n\n  .title-text {\n    font-family: PingFangSC-Medium;\n    font-size: 14px;\n    color: #303a51;\n    line-height: 22px;\n    font-weight: 500;\n  }\n\n  .empty-contain {\n    background: #f8f9fa;\n    margin: 0px;\n    border-radius: 4px;\n    padding: 80px;\n  }\n\n  .empty-title {\n    text-align: left;\n    height: 28px;\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: #303a51;\n  }\n\n  .select-column {\n    position: absolute;\n    right: 180px;\n    width: 230px;\n    height: 30px;\n  }\n\n  .json-button {\n    position: absolute;\n    right: 0px;\n    width: 80px;\n    height: 30px;\n  }\n\n  .sql-title {\n    position: relative;\n    height: 32px;\n    line-height: 32px;\n    &-wrap {\n      display: flex;\n      align-items: center;\n      margin: 24px 0 12px 0;\n    }\n    .title-text {\n      font-size: 14px;\n      color: #303a51;\n      line-height: 22px;\n      font-weight: 500;\n    }\n\n    .line {\n      margin: 0 10px;\n      display: inline-block;\n    }\n\n    .text {\n      display: inline-block;\n      font-family: PingFangSC-Medium;\n      font-size: 12px;\n      color: #2e3a53;\n      line-height: 16px;\n      margin-right: 40px;\n    }\n  }\n}\n\n.mapping-name {\n  word-wrap: break-word;\n  word-break: break-word;\n  cursor: pointer;\n}\n.mapping-tab {\n  min-height: 280px;\n  .dcloud-table-wrapper {\n    padding: 0;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/search-query/sql-page.tsx",
    "content": "import React, { useState, useEffect, useRef } from \"react\";\nimport { setCookie, uuid } from \"lib/utils\";\nimport { XNotification } from \"component/x-notification\";\nimport { Select } from \"antd\";\nimport { newClusterList } from \"api/cluster-api\";\nimport Url from \"lib/url-parser\";\nimport { SQLQuery } from \"./sql-query\";\n\nconst Option = Select.Option;\n\nexport const SqlPage = () => {\n  const [id, setId] = useState(null);\n  const [list, setList] = useState([]);\n  const currentClusterInfoRef = useRef({});\n\n  const [phyClusterName, setPhyClusterName] = useState(null);\n  const [actPhyCluster, setActPhyCluster] = useState(null);\n\n  useEffect(() => {\n    newClusterList()\n      .then((res) => {\n        setList(res);\n        if (res && res.length) {\n          setCookiePhyClusterName(res[0]);\n          setId(res[0]?.v1);\n          currentClusterInfoRef.current = res[0];\n          changeUrl(res[0]);\n        } else {\n          setCookiePhyClusterName(null);\n        }\n      })\n      .catch(() => {\n        setCookiePhyClusterName(null);\n      });\n    document.addEventListener(\"visibilitychange\", onHandleVisibleChange);\n    return () => {\n      currentClusterInfoRef.current = {};\n      document.removeEventListener(\"visibilitychange\", onHandleVisibleChange);\n    };\n  }, []);\n\n  const setCookiePhyClusterName = (clusterInfo) => {\n    //cookie设置是为了和DSL和kibana进行通信\n    const value = clusterInfo?.v2?.cluster || \"no bind phyCluster\";\n    setCookie([{ key: \"kibanaPhyClusterName\", value }]);\n  };\n\n  const changeUrl = (item) => {\n    // 集群健康状态为-1 需要弹框提示\n    if (item?.v2 && item?.v2?.health === -1) {\n      XNotification({ type: \"error\", message: `${item?.v1 || \"\"}集群异常，无法获取mapping信息` });\n    }\n    // v2是真实物理集群\n    setPhyClusterName(item.v1 || null);\n    setActPhyCluster(item.v2?.cluster || null);\n    const href = window.location.href;\n    let search = window.location.search;\n    let url = href.split(\"?\")?.[0];\n    if (!href.split(\"?\")?.[1]) {\n      return;\n    }\n    url = url.split(\"#\")[0];\n    let hash = window.location.hash.split(\"#\");\n    const urlParams = Url();\n    search = `?clusterId=${item.v2.id}&type=${item.v2.type}&currLeftMenu=${urlParams.search.currLeftMenu || \"kibana\"}`;\n    url = url + search + \"#\" + hash[hash.length - 1];\n\n    window.history.pushState(\n      {\n        url,\n      },\n      \"\",\n      url\n    );\n  };\n\n  const onHandleVisibleChange = () => {\n    if (!document.hidden) {\n      setCookiePhyClusterName(currentClusterInfoRef.current);\n    }\n  };\n\n  const onChange = (e) => {\n    const data = (list || []).filter((item) => item.v1 === e);\n    if (data && data.length) {\n      setCookiePhyClusterName(data[0]);\n      setId(e);\n      currentClusterInfoRef.current = data[0];\n      changeUrl(data[0]);\n    }\n  };\n\n  return (\n    <>\n      <div className=\"common-page\">\n        <div className=\"title\">SQL查询</div>\n        <div className=\"query-panel\">\n          <span className=\"label\"></span>\n          <Select className=\"select\" value={id} onChange={onChange} showSearch optionFilterProp=\"children\">\n            {list?.map((item) => (\n              <Option value={item.v1} key={uuid()}>\n                {item.v1}\n              </Option>\n            ))}\n          </Select>\n        </div>\n        <div className=\"content sql\">\n          <SQLQuery currentClusterInfo={currentClusterInfoRef.current} phyClusterName={phyClusterName} actPhyCluster={actPhyCluster} />\n        </div>\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/search-query/sql-query.tsx",
    "content": "import CodeMirror from \"codemirror/lib/codemirror\";\nimport \"codemirror/lib/codemirror.css\";\nimport \"codemirror/mode/sql/sql\";\nimport \"codemirror/mode/javascript/javascript\";\nimport \"codemirror/addon/hint/show-hint.js\";\nimport \"codemirror/addon/hint/sql-hint.js\";\nimport \"codemirror/addon/hint/show-hint.css\";\nimport * as React from \"react\";\nimport { explainSql, toDsl } from \"api/cluster-index-api\";\nimport { Empty, Table, Tooltip, Spin, Form, Select, Row } from \"antd\";\nimport \"./sql-index.less\";\nimport store from \"store\";\nimport { isArray, isEmpty } from \"lodash\";\nimport { isSuperApp } from \"lib/utils\";\nimport { getLogicListTemplates, getPhyListTemplates } from \"../../api/cluster-kanban\";\nimport { getIndexMappingInfo } from \"api/cluster-index-api\";\nimport { getIndexColumns, TAB_JSON, getResTableColumns, selectDt } from \"./config\";\nimport { XNotification } from \"component/x-notification\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { ACEJsonEditor } from \"@knowdesign/kbn-sense/lib/packages/kbn-ace/src/ace/json_editor\";\nconst imgSrc = require(\"./../../assets/empty-icon.png\");\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\n\nconst FormItem = Form.Item;\nconst app = {\n  currentAppInfo: {\n    app: store.getState().app,\n  },\n};\nconst user = {\n  currentUser: store.getState().user,\n};\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\nclass SQLQueryCom extends React.Component<any> {\n  public state = {\n    checkedList: [] as string[],\n    indexStore: [],\n    selectDataSource: [] as selectDt[],\n    tableLoading: false,\n    indexList: [],\n    sqlData: {} as any,\n    tableShow: false,\n    tableReady: false,\n    indeterminate: true,\n    tableInfo: {} as any,\n    tableData: [] as any,\n    plainOptions: [] as string[],\n    tableHeader: {} as any,\n    jsonData: {} as any,\n    phyClusterName: null,\n    loading: false,\n    activeKey: \"\",\n    mappingJson: [],\n    selectMapJson: [],\n    activeInstance: null,\n    lineSign: 0,\n    showButton: true,\n    jsonKey: \"TABLE\",\n    isError: false,\n    resultLoading: false,\n  };\n  $selectRef: any = React.createRef();\n  $clickRef: any = React.createRef();\n  $mappingJsonRef: any = React.createRef();\n  $formRef: any = React.createRef();\n\n  public getMapFun = (cluster, indexName) => {\n    const templeteId = this.$selectRef.current.filter((row) => row.label === indexName);\n    this.setState({\n      tableLoading: true,\n      mappingJson: [],\n      selectMapJson: [],\n    });\n    getIndexMappingInfo(templeteId[0].value)\n      .then((res) => {\n        const data = res?.fields;\n        if (!data.length) return;\n        const copyData = JSON.parse(JSON.stringify(data));\n        copyData.forEach((item) => {\n          ///添加检索方式,fields.keyword里面有这个字段的配置\n          item[\"value\"] = item[\"name\"];\n          item[\"label\"] = item[\"name\"];\n          if (!item.hasOwnProperty(\"search\")) {\n            if (item[\"type\"] === \"text\") {\n              item.search = \"fuzzy\";\n            } else {\n              item.search = \"Accurate\";\n            }\n          }\n          if (!item.hasOwnProperty(\"doc_value\")) {\n            item[\"doc_value\"] = true;\n          }\n        });\n        this.setState({\n          mappingJson: copyData,\n          selectMapJson: copyData,\n        });\n        this.$formRef.current.setFieldsValue({ mapping: null });\n        this.$mappingJsonRef.current = copyData || [];\n      })\n      .catch(() => {\n        this.setState({\n          mappingJson: [],\n          selectMapJson: [],\n        });\n        this.$formRef.current.setFieldsValue({ mapping: null });\n        this.$mappingJsonRef.current = [];\n      })\n      .finally(() => {\n        this.$formRef.current.setFieldsValue({ mapping: null });\n        this.setState({\n          tableLoading: false,\n        });\n      });\n  };\n\n  public clusterOrLogic = async (name: string) => {\n    return isSuperApp() ? getPhyListTemplates(name) : getLogicListTemplates(name);\n  };\n\n  public dataSelectFun = (name: string, currentClusterInfo: any) => {\n    if (currentClusterInfo && currentClusterInfo?.v2?.health === -1) {\n      this.setState({\n        indexList: [],\n        indexStore: [],\n        phyClusterName: name || \"\",\n        selectDataSource: [],\n        mappingJson: [],\n        selectMapJson: [],\n      });\n      return;\n    }\n    this.setState({ loading: true });\n    this.clusterOrLogic(name)\n      .then((data) => {\n        let nameList = [];\n        if (isArray(data)) {\n          let selectData = data.map((i) => {\n            nameList.push(i?.name);\n            return {\n              label: i?.name,\n              value: i?.id,\n            };\n          });\n          this.$selectRef.current = selectData;\n          this.setState({\n            indexList: nameList || [],\n            indexStore: nameList || [],\n            phyClusterName: name || \"\",\n            selectDataSource: selectData || [],\n            mappingJson: [],\n            selectMapJson: [],\n          });\n        }\n      })\n      .finally(() => {\n        this.setState({ loading: false });\n      });\n  };\n\n  public componentWillReceiveProps(nextProps) {\n    if (this.state.phyClusterName !== nextProps.phyClusterName) {\n      this.dataSelectFun(nextProps.phyClusterName, nextProps.currentClusterInfo);\n      // 在这里进行异步操作或者更新状态，切换集群时清除sql记录，忽略最初的集群赋值\n      if (this.state.phyClusterName !== null) {\n        const cacheKey = `${user.currentUser.getName(\"userName\")}_${app.currentAppInfo.app.appInfo()?.id}_sql_cookie`;\n        localStorage.removeItem(cacheKey);\n        this.state.activeInstance.setValue(\"\");\n      }\n      this.$formRef.current.setFieldsValue({ mapping: null, index: null });\n      this.setState({\n        tableShow: false,\n        tableInfo: {},\n        tableData: [],\n        jsonData: \"\",\n      });\n    }\n    if (this.state.activeInstance) {\n      const value = this.state.activeInstance.getValue();\n      setTimeout(() => {\n        this.state.activeInstance.setValue(value);\n      }, 0);\n    }\n  }\n\n  public eventBox = (e: any) => {\n    const dom = e.target;\n    if (!this.props.phyClusterName) {\n      XNotification({ type: \"error\", message: \"执行错误，无集群信息\" });\n      return;\n    }\n    if (dom.classList[0] === \"dsl_icon\") {\n      const pdom = dom.parentNode;\n      const sign = pdom.getAttribute(\"data-sign\");\n      const data = this.state.sqlData[sign];\n      this.sqlToDsl(data);\n    } else if (dom.classList[0] === \"explain_icons\") {\n      const pdom = dom.parentNode;\n      const sign = pdom.getAttribute(\"data-sign\");\n      const data = this.state.sqlData[sign];\n      this.sqlExplain(data);\n    }\n  };\n\n  public sqlExplain = (info: any) => {\n    if (this.$clickRef.current) {\n      return;\n    }\n    this.$clickRef.current = true;\n    this.setState({\n      isError: false,\n      resultLoading: true,\n    });\n    const { value } = info;\n    explainSql(value, this.props.actPhyCluster)\n      .then((data) => {\n        data = JSON.parse(data);\n        this.setState({\n          jsonData: data,\n        });\n        if (data.hits) {\n          const tableInfo = {} as any;\n          tableInfo.took = data.took;\n          tableInfo.timed_out = data.timed_out;\n          tableInfo[\"_shards.total\"] = data._shards.total;\n          tableInfo[\"_shards.failed\"] = data._shards.failed;\n          tableInfo[\"hits.total\"] = data.hits.total;\n          const tmpHits = data.hits.hits;\n          const tmpData = [] as any;\n          const tmpHeader = {} as any;\n          tmpHits.forEach((node: any) => {\n            if (node._source) {\n              for (const key in node._source) {\n                if (!tmpHeader[key]) {\n                  tmpHeader[key] = true;\n                }\n              }\n              tmpData.push(node._source);\n            }\n          });\n          this.setState({\n            tableInfo,\n            tableShow: !!tmpHits.length,\n            showButton: true,\n            tableReady: true,\n            tableHeader: tmpHeader,\n            checkedList: this.getCurrentCheckList(tmpHeader),\n            plainOptions: this.getCurrentCheckList(tmpHeader),\n            tableData: tmpData,\n            jsonKey: tmpHits.length ? \"TABLE\" : \"JSON\",\n          });\n        } else {\n          this.setState({\n            tableShow: false,\n            tableReady: false,\n            tableInfo: {},\n            showButton: false,\n            isError: true,\n          });\n        }\n      })\n      .catch(() => {\n        this.setState({\n          jsonData: \"\",\n        });\n      })\n      .finally(() => {\n        this.$clickRef.current = false;\n        this.setState({\n          resultLoading: false,\n        });\n      });\n  };\n\n  public sqlToDsl = (info: any) => {\n    if (this.$clickRef.current) {\n      return;\n    }\n    const { value } = info;\n    this.$clickRef.current = true;\n    this.setState({\n      resultLoading: true,\n    });\n    toDsl(this.props.actPhyCluster, value)\n      .then((data) => {\n        data = JSON.parse(data);\n        this.setState({\n          tableShow: false,\n          showButton: false,\n          tableReady: false,\n          jsonData: data,\n        });\n      })\n      .catch(() => {\n        this.setState({\n          jsonData: \"\",\n        });\n      })\n      .finally(() => {\n        this.$clickRef.current = false;\n\n        this.setState({\n          resultLoading: false,\n        });\n      });\n  };\n\n  public customAnchor = (anchorName: string) => {\n    const anchorElement = document.querySelector(anchorName);\n    window.setTimeout(() => {\n      if (anchorElement) {\n        anchorElement.scrollIntoView();\n      }\n    }, 0);\n  };\n\n  public componentDidMount() {\n    this.props.phyClusterName && this.dataSelectFun(this.props.phyClusterName, this.props.currentClusterInfo);\n    const code = document.querySelector(\".codemirror\");\n    code.innerHTML = \"\";\n    const editor = CodeMirror(document.querySelector(\".codemirror\"), {\n      mode: \"text/x-sql\",\n      lineNumbers: true,\n      styleActiveLine: true,\n      lineWrapping: true,\n      completeSingle: false,\n    });\n\n    editor.on(\"keyup\", (cm: any, event: any) => {\n      if (!cm.state.completionActive && ![13, 8, 9, 32, 27].includes(event.keyCode)) {\n        const tables = {} as any;\n        this.state.indexStore.forEach((node: any) => {\n          tables[node] = [];\n        });\n        // this.state.mappingStore.forEach((node: any) => {\n        //   tables[node.field] = [];\n        // });\n        CodeMirror.commands.autocomplete(cm, null, {\n          completeSingle: false,\n          tables,\n        });\n      }\n    });\n    editor.on(\"changes\", (a: any) => {\n      const data = a.getValue().split(\"\\n\");\n      let status = \"false\";\n      const sqlData = {} as any;\n      let tmp = \"\";\n      let array = [] as any;\n      let tmpkey = 0;\n      data.forEach((node: any, i: number) => {\n        if (node) {\n          if (status === \"false\") {\n            tmpkey = i;\n          }\n          array.push(i);\n          tmp = `${tmp + node}\\n`;\n          sqlData[tmpkey] = {\n            value: tmp,\n            line: array,\n          };\n          status = \"start\";\n        } else {\n          if (status === \"start\") {\n            status = \"false\";\n            tmpkey = 0;\n            tmp = \"\";\n            array = [];\n          }\n        }\n      });\n      const lineDoms = document.querySelectorAll(\".codemirror .CodeMirror-code>div\");\n      lineDoms.forEach((lineDom) => {\n        lineDom.className = \"CodeMirror-line-container\";\n        if (lineDom.querySelector(\".query\")) {\n          lineDom.removeChild(lineDom.querySelector(\".query\"));\n        }\n      });\n      for (const key in sqlData) {\n        if (sqlData[key]) {\n          const line = parseInt(key, 10);\n          const lineDom = lineDoms[line];\n          // tslint:disable-next-line:no-unused-expression bcui-icon-treenode-arrow\n          lineDom &&\n            lineDom.insertAdjacentHTML(\n              \"beforeend\",\n              `<span class=\"query\" data-sign=\"${line}\"><span class=\"dsl_icon\">toDSL</span><span class=\"explain_icons\">执行</span></span>`\n            );\n        }\n      }\n      this.setState({\n        sqlData,\n      });\n      const eventDom = document.querySelector(\".codemirror\");\n      eventDom.addEventListener(\"click\", this.eventBox);\n    });\n    this.setState({\n      activeInstance: editor,\n    });\n    const cacheKey = `${user.currentUser.getName(\"userName\")}_${app.currentAppInfo.app.appInfo()?.id}_sql_cookie`;\n    if (localStorage.getItem(cacheKey)) {\n      editor.setValue(localStorage.getItem(cacheKey));\n    }\n    editor.on(\"blur\", (a: any) => {\n      this.setState({ lineSign: a.getCursor().line });\n      const data = a.getValue();\n      localStorage.setItem(cacheKey, data);\n    });\n  }\n\n  public onIndexChange = (value, option) => {\n    this.setState({\n      indexStore: value ? this.state.indexList.filter((row) => row === option.label) : this.state.indexList,\n    });\n  };\n\n  public onMappingChange = (value) => {\n    this.setState({\n      mappingJson: value ? this.$mappingJsonRef.current.filter((row) => row.value === value) : this.$mappingJsonRef.current,\n    });\n  };\n\n  public indexHandleSearch = (value) => {\n    this.setState({\n      selectDataSource: value ? this.$selectRef.current.filter((row) => row.label.includes(value)) : this.$selectRef.current,\n    });\n  };\n\n  public mappingHandleSearch = (value) => {\n    this.setState({\n      selectMapJson: value ? this.$mappingJsonRef.current.filter((row) => row.value.includes(value)) : this.$mappingJsonRef.current,\n    });\n  };\n\n  public changeMenu = (e) => {\n    this.getMapFun(this.state.phyClusterName, e);\n    const cacheKey = `${user.currentUser.getName(\"userName\")}_${app.currentAppInfo.app.appInfo()?.id}_sql_cookie`;\n    if (localStorage.getItem(cacheKey)) {\n      const curentValue = localStorage.getItem(cacheKey);\n      const array = curentValue.split(\"\\n\");\n      const index = this.state.lineSign;\n      array[index] = array[index] + e;\n      localStorage.setItem(cacheKey, array.join(\"\\n\"));\n      this.state.activeInstance.setValue(localStorage.getItem(cacheKey));\n      this.state.activeInstance.setCursor({ line: index, ch: array[index].length }); //设置聚焦，默认聚焦为最后一个字节\n    } else {\n      localStorage.setItem(cacheKey, e);\n      this.state.activeInstance.setValue(e);\n    }\n    this.setState({\n      activeKey: e,\n    });\n  };\n\n  public renderIndexTable = () => {\n    return (\n      <div className=\"index-temp\">\n        <div className=\"iam-box\">\n          <div className=\"iam-box-title\">\n            <span className=\"title-prefix\"></span>索引模版\n          </div>\n          <Form ref={this.$formRef} layout=\"vertical\">\n            <Row>\n              <FormItem key=\"index\" name=\"index\" label=\"\" className=\"indextemp-input\">\n                <Select\n                  showSearch\n                  options={this.state.selectDataSource}\n                  allowClear\n                  placeholder=\"索引模版\"\n                  defaultActiveFirstOption={false}\n                  filterOption={false}\n                  onSearch={this.indexHandleSearch}\n                  onChange={this.onIndexChange}\n                />\n              </FormItem>\n            </Row>\n          </Form>\n          {this.state.indexStore.length ? (\n            <Spin spinning={this.state.loading}>\n              <div className=\"index-container\">\n                <div className=\"index-tabs-contain\">\n                  <div className=\"index-tabs\">\n                    {(this.state.indexStore || []).map((m, index) => {\n                      return (\n                        <div\n                          key={index}\n                          onClick={() => {\n                            this.changeMenu(m);\n                          }}\n                          className={this.state.activeKey === m ? \"index-tabs-item check\" : \"index-tabs-item\"}\n                        >\n                          <Tooltip title={m}>\n                            <div className=\"index-tabs-item-content\">\n                              <span>{m || \"\"}</span>\n                              <span\n                                style={{\n                                  display: this.state.activeKey == m ? \"inline-block\" : \"none\",\n                                }}\n                                className=\"iconfont iconrenwuzhongxin1\"\n                                onClick={(e) => {\n                                  e.stopPropagation();\n                                  this.props.setModalId(\"mapping\", {\n                                    title: \"Mapping\",\n                                    selectMapJson: this.state.selectMapJson,\n                                    mappingHandleSearch: this.mappingHandleSearch,\n                                    onMappingChange: this.onMappingChange,\n                                    tableLoading: this.state.tableLoading,\n                                    columns: getIndexColumns(),\n                                    mappingJson: this.state.mappingJson,\n                                  });\n                                  console.log(\"click \");\n                                }}\n                              ></span>\n                            </div>\n                          </Tooltip>\n                        </div>\n                      );\n                    })}\n                  </div>\n                </div>\n              </div>\n            </Spin>\n          ) : (\n            <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />\n          )}\n        </div>\n      </div>\n    );\n  };\n\n  public getCurrentCheckList = (tableHeader: any) => {\n    const plainOptions = [] as string[];\n    for (const key in tableHeader) {\n      if (tableHeader[key]) {\n        plainOptions.push(key);\n      }\n    }\n    return plainOptions;\n  };\n\n  public handleChange = (value: any) => {\n    this.setState({\n      checkedList: value,\n      indeterminate: !!value.length && value.length < this.state.plainOptions.length,\n    });\n  };\n\n  public changeResTab = (e) => {\n    this.setState({\n      jsonKey: e.key,\n      tableShow: e.key === \"TABLE\",\n    });\n  };\n\n  public renderResTable = () => {\n    const { tableData } = this.state;\n    const height = document.body.clientHeight - 725;\n    return (\n      <>\n        {tableData.length ? (\n          <Table\n            dataSource={tableData}\n            rowKey={() => uuidv4()}\n            bordered\n            className=\"data-table\"\n            columns={getResTableColumns(this.state.checkedList)}\n            scroll={{ x: \"max-content\", y: \"max-content\" }}\n          />\n        ) : (\n          <div className=\"empty-contain\">\n            <Empty\n              image={\n                <>\n                  <img src={imgSrc} />\n                </>\n              }\n              description=\"您的执行结果为空~\"\n              className=\"empty-component\"\n            />\n          </div>\n        )}\n      </>\n    );\n  };\n\n  public renderJsonRes = () => {\n    return (\n      <>\n        {this.state.tableShow ? null : (\n          <div className=\"box-right\">\n            <ACEJsonEditor readOnly={true} data={JSON.stringify(this.state.jsonData, null, 4)} />\n          </div>\n        )}\n      </>\n    );\n  };\n\n  public renderResultContent = () => {\n    const { tableInfo, tableShow, jsonData, isError, showButton } = this.state;\n    const selectObj = this.state.plainOptions.map((i) => ({\n      label: i,\n      value: i,\n    }));\n\n    if ((tableShow && isEmpty(tableInfo)) || isEmpty(jsonData)) {\n      return (\n        <div className=\"sql-title\">\n          <div className=\"sql-title-wrap\">\n            <span className=\"title-prefix\"></span>\n            <span className=\"title-text\">执行结果</span>\n          </div>\n          <div className=\"empty-contain\">\n            <Empty\n              image={\n                <>\n                  <img src={imgSrc} />\n                </>\n              }\n              description=\"您的执行结果为空~\"\n              className=\"empty-component\"\n            />\n          </div>\n        </div>\n      );\n    }\n\n    return (\n      <>\n        <div className=\"sql-title\">\n          <div className=\"sql-title-wrap\">\n            <span className=\"title-prefix\"></span>\n            <span className=\"title-text\">执行结果</span>\n            {isError ? null : (\n              <>\n                {showButton && (\n                  <span>\n                    <span className=\"line\"> | </span>\n                    <span>\n                      响应时间: <span className=\"text\">{tableInfo.took} ms </span>\n                      超时: <span className=\"text\">{tableInfo.timed_out ? \"是\" : \"否\"}</span>\n                      总shard数: <span className=\"text\">{tableInfo[\"_shards.total\"]}</span>\n                      失败shard数: <span className=\"text\">{tableInfo[\"_shards.failed\"]}</span>\n                      总条数: <span className=\"text\">{tableInfo[\"hits.total\"]}</span>\n                    </span>\n                    {this.state.tableData.length > 0 && this.state.jsonKey === \"TABLE\" && (\n                      <Select\n                        mode=\"tags\"\n                        className=\"select-column\"\n                        value={this.state.checkedList}\n                        onChange={this.handleChange}\n                        tokenSeparators={[\",\"]}\n                        maxTagCount={\"responsive\"}\n                      >\n                        {selectObj.map((i) => {\n                          return (\n                            <Select.Option key={i.label} value={i.value}>\n                              {i.value}\n                            </Select.Option>\n                          );\n                        })}\n                      </Select>\n                    )}\n                    <div className=\"detail-tabs\">\n                      {(TAB_JSON || []).map((m) => {\n                        return (\n                          <div\n                            key={m.key}\n                            onClick={() => this.changeResTab(m)}\n                            className={this.state.jsonKey == m.key ? \"detail-tabs-item check\" : \"detail-tabs-item\"}\n                          >\n                            {m.label}\n                          </div>\n                        );\n                      })}\n                    </div>\n                  </span>\n                )}\n              </>\n            )}\n          </div>\n        </div>\n        <Spin spinning={this.state.resultLoading}>\n          {this.state.tableShow && this.renderResTable()}\n          {this.renderJsonRes()}\n        </Spin>\n      </>\n    );\n  };\n\n  public render() {\n    return (\n      <div className=\"sql-query-page\">\n        <div className=\"top-console-open\">\n          <div className=\"codemirror-contain\">\n            <div className=\"codemirror-title\">\n              <span className=\"title-prefix\"></span>\n              SQL编辑器\n            </div>\n            <div className=\"codemirror\" />\n          </div>\n          <div className=\"tip-content\">{this.renderIndexTable()}</div>\n        </div>\n        <div className=\"bottom-console\">{this.renderResultContent()}</div>\n      </div>\n    );\n  }\n}\nexport const SQLQuery = connect(null, mapDispatchToProps)(SQLQueryCom);\n"
  },
  {
    "path": "arius-console/src/container/staff-select.tsx",
    "content": "import { Select } from \"antd\";\nimport * as React from \"react\";\nimport { getAllUserList } from \"api/common-api\";\nimport { IUser, NewIUser } from \"typesPath/user-types\";\nimport { isArray } from \"lodash\";\nimport { filterOption } from \"lib/utils\";\n\nconst Option = Select.Option;\n\ninterface IUserSelectProps {\n  onChange?: (result: string[]) => any;\n  value?: string[];\n  disabled?: boolean;\n  placeholder?: string;\n  style?: any;\n}\n\nexport class StaffSelect extends React.Component<IUserSelectProps> {\n  public state = {\n    staffList: [] as IUser[],\n  };\n\n  constructor(props: IUserSelectProps) {\n    super(props);\n  }\n\n  public componentDidMount() {\n    this.getStaffList();\n  }\n\n  public getStaffList = () => {\n    getAllUserList().then((res) => {\n      const list = (res || []).map((item) => ({\n        ...item,\n        label: item.userName,\n        value: item.userName,\n      }));\n      this.setState({\n        staffList: list,\n      });\n    });\n  };\n\n  public render() {\n    const { disabled, placeholder, style } = this.props;\n    let { value } = this.props;\n    if (value && typeof value === \"string\") {\n      value = (value as string)?.split(\",\");\n    }\n    // 打印出value为空时 值为 [''],导致编辑时出现空标签\n    if (value && isArray(value)) {\n      value = value?.filter((item) => {\n        return item !== \"\";\n      });\n    }\n    return (\n      <Select\n        mode=\"multiple\"\n        showSearch={true}\n        optionFilterProp=\"children\"\n        placeholder={placeholder ? placeholder : \"请输入负责人查询\"}\n        defaultValue={value || []}\n        value={value || []}\n        onChange={(e: string[]) => this.handleChange(e)}\n        disabled={disabled}\n        tokenSeparators={[\",\"]}\n        style={style}\n        className=\"ant-form-item-custom\"\n        filterOption={filterOption}\n      >\n        {this.state.staffList.map((d: NewIUser) => (\n          <Option value={d.userName} key={d.userName}>\n            {d.userName}\n          </Option>\n        ))}\n      </Select>\n    );\n  }\n\n  public handleChange(params: string[]) {\n    const { onChange } = this.props;\n    // tslint:disable-next-line:no-unused-expression\n    onChange && onChange(params);\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/system/cluster-config.tsx",
    "content": "import React, { useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getClusterCongigQueryXForm, getClusterCongigColumns } from \"./config\";\nimport { getDeployList } from \"api/cluster-api\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { RenderTitle } from \"component/render-title\";\nimport QueryForm from \"component/dantd/query-form\";\nimport { queryFormText } from \"constants/status-map\";\nimport { Button, Tag } from \"antd\";\nimport { RiseOutlined } from \"@ant-design/icons\";\nimport { PlatformPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { ProTable } from \"knowdesign\";\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nexport const ClusterConfig = connect(\n  null,\n  mapDispatchToProps\n)((props: any) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject] = useState(null);\n  const [data, setData] = useState([]);\n\n  React.useEffect(() => {\n    reloadData();\n  }, [department]);\n\n  const getData = () => {\n    // 查询项的key 要与 数据源的key  对应\n    if (!queryFormObject) return data;\n    const keys = Object.keys(queryFormObject);\n    const filterData = data.filter((d) => {\n      let b = true;\n      keys.forEach((k: string) => {\n        (d[k] + \"\").includes(queryFormObject[k]) ? \"\" : (b = false);\n      });\n      return b;\n    });\n    return filterData;\n  };\n\n  const reloadData = () => {\n    setloading(true);\n    getDeployList()\n      .then((res) => {\n        if (res) {\n          setData(res);\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const renderTitleContent = () => {\n    return {\n      title: \"平台配置\",\n      content: null,\n    };\n  };\n\n  const handleSubmit = (result) => {\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject(result);\n  };\n\n  const getOpBtns = () => {\n    return (\n      <>\n        {hasOpPermission(PlatformPermissions.PAGE, PlatformPermissions.ADD) && (\n          <Button type=\"primary\" className=\"ant-btn-primary\" onClick={() => props.setModalId(\"clusterConfigModal\", {}, reloadData)}>\n            新增配置\n          </Button>\n        )}\n        {/* <div\n          style={{\n            display: \"inline-block\",\n            fontSize: 14,\n            color: \"#1473FF\",\n            letterSpacing: 0,\n            textAlign: \"right\",\n            marginLeft: 4,\n            cursor: \"pointer\",\n          }}\n          onClick={() =>\n            window.open(\n              \"https://github.com/didi/LogiEM/blob/master/doc/LogiEM%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97.md#38-%E5%B9%B3%E5%8F%B0%E9%85%8D%E7%BD%AE\"\n            )\n          }\n        >\n          指导文档\n          <RiseOutlined />\n        </div> */}\n      </>\n    );\n  };\n\n  const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n\n  return (\n    <>\n      <div className=\"table-layout-style\">\n        <ProTable\n          showQueryForm={true}\n          queryFormProps={{\n            defaultCollapse: true,\n            columns: getClusterCongigQueryXForm(),\n            onReset: handleSubmit,\n            onSearch: handleSubmit,\n            initialValues: queryFormObject,\n            isResetClearAll: true,\n          }}\n          tableProps={{\n            tableId: \"cluster_config_table\",\n            isCustomPg: false,\n            loading,\n            rowKey: \"id\",\n            dataSource: getData(),\n            columns: getClusterCongigColumns(data, props.setModalId, reloadData),\n            reloadData,\n            getJsxElement: getOpBtns,\n            customRenderSearch: () => (\n              <div className=\"zeus-url\">\n                <RenderTitle {...renderTitleContent()} />{\" \"}\n                <Tag\n                  className=\"zeus-url-tag\"\n                  onClick={() =>\n                    (window.open(\"about:blank\").location.href =\n                      \"https://github.com/didi/LogiEM/blob/master/doc/LogiEM%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97.md#38-%E5%B9%B3%E5%8F%B0%E9%85%8D%E7%BD%AE\")\n                  }\n                >\n                  指导文档\n                </Tag>\n              </div>\n            ),\n            attrs: {\n              scroll: { x: \"max-content\" },\n            },\n          }}\n        />\n      </div>\n      {/* <div className=\"table-header\">\n        <RenderTitle {...renderTitleContent()} />\n\n        <QueryForm\n          {...queryFormText}\n          showCollapseButton={false}\n          defaultCollapse\n          columns={getClusterCongigQueryXForm()}\n          onChange={() => null}\n          onReset={handleSubmit}\n          onSearch={handleSubmit}\n          initialValues={{}}\n          isResetClearAll\n        />\n      </div>\n      <div>\n        <div className=\"table-content\">\n          <DTable\n            loading={loading}\n            rowKey=\"id\"\n            dataSource={getData()}\n            attrs={{\n              scroll: {\n                x: 1700 - (13 - 6) * 120,\n                y: clientHeight > 500 ? clientHeight - 200 : 300,\n              },\n            }}\n            columns={getClusterCongigColumns(data, props.setModalId, reloadData)}\n            reloadData={reloadData}\n            renderInnerOperation={getOpBtns}\n          />\n        </div>\n      </div> */}\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/system/config.tsx",
    "content": "import React from \"react\";\nimport { IDeploy, IOpRecord } from \"typesPath/cluster/physics-type\";\nimport { Tooltip, Modal, DatePicker, Button } from \"antd\";\nimport { cellStyle } from \"constants/table\";\nimport { deployStatus } from \"constants/status-map\";\nimport { renderOperationBtns } from \"container/custom-component\";\nimport { QuestionCircleOutlined } from \"@ant-design/icons\";\nimport { deleteDeploy, switchDeploy } from \"api/cluster-api\";\nimport { PlatformPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { transTimeFormat } from \"lib/utils\";\nimport { XNotification } from \"component/x-notification\";\nimport DRangeTime from \"../../d1-packages/d-range-time\";\nconst { confirm } = Modal;\nconst { RangePicker } = DatePicker;\n\nexport const getClusterCongigQueryXForm = () => {\n  const formMap = [\n    {\n      dataIndex: \"valueGroup\",\n      title: \"配置组\",\n      type: \"input\",\n      placeholder: \"请输入配置组\",\n    },\n    {\n      dataIndex: \"valueName\",\n      title: \"名称\",\n      type: \"input\",\n      placeholder: \"请输入名称\",\n    },\n    {\n      dataIndex: \"memo\",\n      title: \"描述\",\n      type: \"input\",\n      placeholder: \"请输入描述\",\n    },\n  ];\n  return formMap;\n};\n\nexport const getOperatingListQueryXForm = (params, handleTimeChange) => {\n  const customTimeOptions = [\n    {\n      label: \"最近 1 天\",\n      value: 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 7 天\",\n      value: 7 * 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 1 月\",\n      value: 30 * 24 * 60 * 60 * 1000,\n    },\n  ];\n  const formMap = [\n    {\n      dataIndex: \"projectName\",\n      title: \"应用\",\n      type: \"input\",\n      placeholder: \"请输入\",\n    },\n    {\n      dataIndex: \"moduleId\",\n      title: \"模块\",\n      type: \"select\",\n      options: params.modules,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"operateId\",\n      title: \"操作类型\",\n      type: \"select\",\n      options: params.operationType,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"userOperation\",\n      title: \"操作人\",\n      type: \"input\",\n      placeholder: \"请输入\",\n    },\n    {\n      dataIndex: \"triggerWayId\",\n      title: \"触发方式\",\n      type: \"select\",\n      options: params.triggerWay,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"operateTime\",\n      title: \"操作时间\",\n      type: \"custom\",\n      component: <DRangeTime timeChange={handleTimeChange} popoverClassName=\"dashborad-popover\" customTimeOptions={customTimeOptions} />,\n    },\n    {\n      dataIndex: \"content\",\n      title: \"操作内容\",\n      type: \"input\",\n      placeholder: \"请输入\",\n    },\n  ];\n  return formMap;\n};\n\nexport const getClusterCongigColumns = (data: IDeploy[], fn: any, reloadDataFn: any) => {\n  const getClusterCongigBtnList = (record: IDeploy, fn: any, reloadDataFn: any) => {\n    const title = record.status === 1 ? \"禁用\" : \"开启\";\n    return [\n      // {\n      //   label: title,\n      //   invisible: !hasOpPermission(PlatformPermissions.PAGE, PlatformPermissions.DISABLE),\n      //   clickFunc: () => {\n      //     const { id, status } = record;\n      //     confirm({\n      //       title: \"提示\",\n      //       icon: <QuestionCircleOutlined style={{ color: \"red\" }} />,\n      //       content: `确定${title}配置${id}？`,\n      //       width: 500,\n      //       okText: \"确认\",\n      //       cancelText: \"取消\",\n      //       onOk() {\n      //         switchDeploy({ id, status: status === 1 ? 2 : 1 }).then((data) => {\n      //           XNotification({ type: \"success\", message: `${title}配置成功` });\n      //           reloadDataFn();\n      //         });\n      //       },\n      //     });\n      //   },\n      // },\n      {\n        label: \"编辑\",\n        invisible: !hasOpPermission(PlatformPermissions.PAGE, PlatformPermissions.EDIT),\n        clickFunc: () => {\n          fn(\"clusterConfigModal\", record, reloadDataFn);\n        },\n      },\n      {\n        label: \"删除\",\n        invisible: !hasOpPermission(PlatformPermissions.PAGE, PlatformPermissions.DELETE),\n        clickFunc: (record: IDeploy) => {\n          const { id } = record;\n          confirm({\n            title: \"提示\",\n            icon: <QuestionCircleOutlined style={{ color: \"red\" }} />,\n            content: `确定删除配置${id}？`,\n            width: 500,\n            okText: \"确认\",\n            cancelText: \"取消\",\n            onOk() {\n              deleteDeploy(id).then((data) => {\n                XNotification({ type: \"success\", message: \"删除成功\" });\n                reloadDataFn();\n              });\n            },\n          });\n          return;\n        },\n      },\n    ];\n  };\n  const columns = [\n    {\n      title: \"ID\",\n      dataIndex: \"id\",\n      width: 80,\n      sorter: (a: IDeploy, b: IDeploy) => a.id - b.id,\n    },\n    {\n      title: \"配置组\",\n      dataIndex: \"valueGroup\",\n      width: 150,\n      onCell: () => ({\n        style: {\n          maxWidth: 250,\n          ...cellStyle,\n        },\n      }),\n      lineClampTwo: true,\n      needTooltip: true,\n      render: (value: string) => {\n        return value || \"-\";\n      },\n    },\n    {\n      title: \"名称\",\n      dataIndex: \"valueName\",\n      width: 200,\n      onCell: () => ({\n        style: {\n          maxWidth: 200,\n          ...cellStyle,\n        },\n      }),\n      lineClampTwo: true,\n      needTooltip: true,\n      render: (value: string) => {\n        return value || \"-\";\n      },\n    },\n    {\n      title: \"值\",\n      dataIndex: \"value\",\n      width: 180,\n      onCell: () => ({\n        style: {\n          maxWidth: 250,\n          ...cellStyle,\n        },\n      }),\n      lineClampTwo: true,\n      needTooltip: true,\n      render: (value: string) => {\n        return value || \"-\";\n      },\n    },\n    {\n      title: \"描述\",\n      dataIndex: \"memo\",\n      width: 200,\n      onCell: () => ({\n        style: {\n          maxWidth: 250,\n          ...cellStyle,\n        },\n      }),\n      lineClampTwo: true,\n      needTooltip: true,\n      render: (value: string) => {\n        return value || \"-\";\n      },\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      width: 120,\n      render: (id: number, record: IDeploy) => {\n        const btns = getClusterCongigBtnList(record, fn, reloadDataFn);\n        return renderOperationBtns(btns as any, record);\n      },\n    },\n  ];\n  return columns;\n};\n\nexport const getOperationColumns = (setDrawerId) => {\n  let cols = [\n    {\n      title: \"应用\",\n      dataIndex: \"projectName\",\n      key: \"projectName\",\n      width: \"10%\",\n      render: (val: string) => val || \"-\",\n    },\n    {\n      title: \"模块\",\n      dataIndex: \"module\",\n      key: \"module\",\n      width: \"10%\",\n      render: (val: string) => val || \"-\",\n    },\n    {\n      title: \"操作类型\",\n      dataIndex: \"operate\",\n      key: \"operate\",\n      width: \"15%\",\n      render: (val: string) => val || \"-\",\n    },\n    {\n      title: \"操作人\",\n      dataIndex: \"userOperation\",\n      key: \"userOperation\",\n      width: \"10%\",\n      render: (val: string) => val || \"-\",\n    },\n    {\n      title: \"操作时间\",\n      dataIndex: \"operateTime\",\n      key: \"operateTime\",\n      width: 200,\n      render: (t: number) => transTimeFormat(t),\n    },\n    {\n      title: \"触发方式\",\n      dataIndex: \"triggerWay\",\n      key: \"triggerWay\",\n      width: \"10%\",\n      render: (val: string) => val || \"-\",\n    },\n    {\n      title: \"操作内容\",\n      dataIndex: \"content\",\n      key: \"content\",\n      width: 260,\n      ellipsis: true,\n      render: (val: string, record) => {\n        let diffArr = [\"编辑MAPPING\", \"编辑SETTING\", \"配置文件变更\"];\n        if (diffArr.includes(record.operate)) {\n          const data = val ? JSON.parse(val) : {};\n          let operate: string;\n          if (record.operate === \"编辑MAPPING\") {\n            operate = \"Mapping\";\n          } else if (record.operate === \"编辑SETTING\") {\n            operate = \"Setting\";\n          } else if (record.operate === \"配置文件变更\") {\n            operate = \"配置文件\";\n          }\n          return (\n            <>\n              <span style={{ marginRight: \"5px\" }}>{record.operate}</span>\n              <Button\n                type=\"link\"\n                style={{ height: 20, padding: \"0 15px\" }}\n                onClick={() => setDrawerId(\"mappingSettingDiff\", { operate, data })}\n              >\n                查看\n              </Button>\n            </>\n          );\n        }\n        return (\n          <Tooltip title={val || \"-\"} placement=\"topLeft\">\n            <span>{val || \"-\"}</span>\n          </Tooltip>\n        );\n      },\n    },\n  ];\n  return cols;\n};\n"
  },
  {
    "path": "arius-console/src/container/system/operating-list.tsx",
    "content": "import React, { useState, useEffect, useRef } from \"react\";\nimport { getOperatingListQueryXForm, getOperationColumns } from \"./config\";\nimport { getlistModules, getUserRecordList, getTriggerWay, getOperationType } from \"api/cluster-api\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { RenderTitle } from \"component/render-title\";\nimport QueryForm from \"component/dantd/query-form\";\nimport { queryFormText } from \"constants/status-map\";\nimport moment from \"moment\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { connect } from \"react-redux\";\nimport { ProTable } from \"knowdesign\";\ninterface IOpRecord {\n  value: number | string;\n  title: string | number;\n}\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params)),\n});\n\nconst Operating = (props) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [modules, setModules] = useState([] as IOpRecord[]);\n  const [triggerWay, setTriggerWay] = useState([] as IOpRecord[]);\n  const [operationType, setOperationType] = useState([] as IOpRecord[]);\n  const [data, setData] = useState([]);\n  const [queryFormObject, setQueryFormObject] = useState({ page: 1, size: 10 } as any);\n  const [total, setTotal] = useState(0);\n  const [moduleId, setModuleId] = useState();\n  const [form, setForm] = useState<any>();\n  const [startAndEnd, setStartAndEnd] = useState([]);\n  //const [resetValue, setResetValue] = useState(null);//\n  const buttonTime = useRef(null);\n\n  useEffect(() => {\n    reloadData();\n    getModules();\n    _getTriggerWay();\n    _getOperationType();\n  }, [department]);\n\n  useEffect(() => {\n    reloadData();\n  }, [queryFormObject]);\n\n  const getModules = () => {\n    getlistModules().then((res) => {\n      let keys = Object.keys(res || {});\n      let modules = keys.map((item) => {\n        return {\n          title: item,\n          value: res[item],\n        };\n      });\n      setModules(modules);\n    });\n  };\n\n  const _getTriggerWay = async () => {\n    let res = await getTriggerWay();\n    let keys = Object.keys(res || {});\n    let triggerWay = keys.map((item) => {\n      return {\n        title: item,\n        value: res[item],\n      };\n    });\n    setTriggerWay(triggerWay);\n  };\n\n  const _getOperationType = async (code?: number) => {\n    let res = await getOperationType(code);\n    let keys = Object.keys(res || {});\n    let operationType = keys.map((item) => {\n      return {\n        title: res[item],\n        value: Number(item),\n      };\n    });\n    setOperationType(operationType);\n  };\n\n  const reloadData = () => {\n    setloading(true);\n    getUserRecordList({\n      ...queryFormObject,\n      beginTime: queryFormObject?.operateTime?.length ? queryFormObject?.operateTime[0]?.valueOf() : \"\",\n      endTime: queryFormObject?.operateTime?.length ? queryFormObject?.operateTime[1]?.valueOf() : \"\",\n    })\n      .then((res) => {\n        if (res?.bizData) {\n          setData(res.bizData);\n        }\n        setTotal(res?.pagination?.total);\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const renderTitleContent = () => {\n    return {\n      title: \"操作记录\",\n      content: null,\n    };\n  };\n\n  const handleSubmit = (result) => {\n    const copyResult = JSON.parse(JSON.stringify(result));\n    // 增加点击刷新按钮先计算时间差 保持用户选择的事件范围\n    //判断此时是否是自定义时间情况，如果是则不需要实时更新时间戳，反之不需要。\n    const time = startAndEnd[1] - startAndEnd[0];\n    const currentTime = new Date().getTime();\n    const isCustomTime = buttonTime.current ? [currentTime - time, currentTime] : startAndEnd;\n    copyResult.operateTime = isCustomTime;\n    for (var key in copyResult) {\n      if (copyResult[key] === \"\" || copyResult[key] === undefined) {\n        delete copyResult[key];\n      }\n    }\n    setQueryFormObject({ ...copyResult, page: 1, size: queryFormObject.size });\n  };\n  const resetSubmit = (result) => {\n    buttonTime.current = false;\n    setStartAndEnd([]);\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setQueryFormObject({ ...result, page: 1, size: queryFormObject.size });\n  };\n\n  const handleTimeChange = (times: number[], periodOrPicker: boolean) => {\n    //periodOrPicker为true表示此时时间选择器选的是period，false表示Picker\n    if (times) {\n      setStartAndEnd(times);\n      buttonTime.current = periodOrPicker;\n    }\n  };\n  // const resetAllValue = (obj = {}) => {\n  //   setResetValue({ ...obj })\n  // }\n\n  const handleChange = (pagination) => {\n    setQueryFormObject({ ...queryFormObject, page: pagination.current, size: pagination.pageSize });\n  };\n\n  const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n\n  return (\n    <>\n      <div className=\"table-layout-style\">\n        <ProTable\n          showQueryForm={true}\n          queryFormProps={{\n            defaultCollapse: true,\n            columns: getOperatingListQueryXForm({ modules, triggerWay, operationType }, handleTimeChange),\n            onChange: (data) => {\n              if (data?.[1]?.value !== moduleId) {\n                _getOperationType(data?.[1]?.value);\n                setModuleId(data?.[1]?.value);\n                form.setFieldsValue({ operateId: undefined });\n              }\n            },\n            onReset: resetSubmit,\n            onSearch: handleSubmit,\n            // initialValues={{}}\n            isResetClearAll: true,\n            showCollapseButton: false,\n            getFormInstance: (form) => setForm(form),\n          }}\n          tableProps={{\n            tableId: \"operation_list_table\",\n            isCustomPg: false,\n            loading,\n            rowKey: \"id\",\n            dataSource: data,\n            columns: getOperationColumns(props.setDrawerId),\n            reloadData,\n            isDividerHide: false,\n            customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n            paginationProps: {\n              position: \"bottomRight\",\n              showQuickJumper: true,\n              total: total,\n              showSizeChanger: true,\n              pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n              showTotal: (total) => `共 ${total} 条`,\n              current: queryFormObject.page,\n              pageSize: queryFormObject.size,\n            },\n            attrs: {\n              onChange: handleChange,\n              scroll: {\n                x: \"max-content\",\n              },\n            },\n          }}\n        />\n      </div>\n    </>\n  );\n};\n\nexport const OperatingList = connect(null, mapDispatchToProps)(Operating);\n"
  },
  {
    "path": "arius-console/src/container/tooltip.tsx",
    "content": "import React from 'react';\nimport { InfoCircleOutlined } from '@ant-design/icons';\nimport { Tooltip } from 'antd';\n\n// 集群类型\nexport const nounClusterType =\n(\n  <>\n      <Tooltip title={<><p>公共集群：Arius团队维护的大集群，成本低，隔离性较弱;</p><p>独享集群、独立集群：隔离性好但成本高；</p></>}>\n        <InfoCircleOutlined className=\"ml-10 mr-5\" />\n      </Tooltip>\n  </>\n);\n\n// 集群状=\nconst clusterTypeEle =\n(\n  <>\n    <p>green: 集群主副分片均正常;</p>\n    <p>yellow：集群主分片均正常，存在异常副分片;</p>\n    <p>red：集群存在异常主分片;</p>\n  </>\n);\nexport const nounClusterStatus =\n(\n  <>\n      <Tooltip title={clusterTypeEle}>\n        <InfoCircleOutlined className=\"ml-10 mr-5\" />\n      </Tooltip>\n  </>\n);\n\n// 分区创建\nexport const nounPartitionCreate  =\n(\n  <>\n      <Tooltip title={<>分区创建：按照时间每天/每月创建物理索引，在性能、稳定性、扩容上更有优势;<br/> 不分区创建：只创建一个物理索引</>}>\n          <InfoCircleOutlined className=\"ml-10 mr-10\" />\n      </Tooltip>\n  </>\n);\n\n// 集群权限\nexport const nounClusterAuthority  =\n(\n  <>\n      <Tooltip title={<>访问权限： 在集群上进行创建索引、查看数据、查询索引等操作；<br/>配置管理：除访问权限外，可修改集群配置，申请扩缩容</>}>\n          <InfoCircleOutlined className=\"ml-10 mr-10\" />\n      </Tooltip>\n  </>\n);\n\n// 索引服务\nexport const nounIndexServer  =\n(\n  <>\n      <Tooltip title={<>xxxx</>}>\n          <InfoCircleOutlined className=\"ml-10 mr-10\" />\n      </Tooltip>\n  </>\n);\n\n// 索引权限\nconst indexAuthorityEle =\n(\n  <>\n    <p>读权限：可实现对索引的查看、查询操作；</p>\n    <p>读写权限：在读权限基础上，可向索引中写入数据；</p>\n    <p>管理权限：在读写权限基础上，还具备修改索引的配置（如mapping结构）、清理索引、下线索引的能力。</p>\n  </>\n);\nexport const nounIndexAuthority  =\n(\n  <>\n      <Tooltip title={indexAuthorityEle}>\n          <InfoCircleOutlined className=\"ml-10 mr-10\" />\n      </Tooltip>\n  </>\n);\nexport const nounAuthority =\n(\n  <>\n      <Tooltip title='访问权限表示您所在的项目可以查看该集群，并在其上申请逻辑索引'>\n        <InfoCircleOutlined style={{ color: 'green' }} />\n      </Tooltip>\n  </>\n);\n\nexport const renderTip = (t: string, color?: string) => (\n  <>\n      <Tooltip title={t}>\n        <InfoCircleOutlined style={{ color: color ? color : 'green' }} />\n      </Tooltip>\n  </>\n);\n"
  },
  {
    "path": "arius-console/src/container/work-order/base-info.tsx",
    "content": "import * as React from 'react';\nimport { BASE_INFO, ORDER_INFO } from './config';\nimport Url from 'lib/url-parser';\nimport { Descriptions, Spin, Divider } from 'antd';\nimport { IBaseInfo } from 'typesPath/base-types';\nimport { connect } from \"react-redux\";\nimport { TaskState } from 'store/type';\n\nconst mapStateToProps = state => ({\n  task: state.task\n});\n\nconst connects: Function = connect;\n@connects(mapStateToProps)\nexport class BaseInfo extends React.Component<{ task: TaskState }> {\n  public id: number = null;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.id = Number(url.search.id);\n  }\n\n  public render() {\n    const { task } = this.props;\n    return (\n      <Spin spinning={task.loading}>\n        <Descriptions title=\"基础信息\" className=\"base-info\" size=\"middle\" column={3}>\n          {BASE_INFO.map((item: IBaseInfo, index: number) => (\n            <Descriptions.Item key={index} label={item.label}>\n              {item.render ? item.render(task.taskBaseInfo?.[item.key]) : task.taskBaseInfo?.[item.key]}\n            </Descriptions.Item>\n          ))}\n        </Descriptions>\n        <Divider />\n        {/* <Descriptions title=\"关联工单\" className=\"base-info\" size=\"middle\" column={3}>\n          {ORDER_INFO(task).map((item: IBaseInfo, index: number) => (\n            <Descriptions.Item key={index} label={item.label}>\n              {item.render ? item.render(task.taskBaseInfo?.[item.key]) : task.taskBaseInfo?.[item.key]}\n            </Descriptions.Item>\n          ))}\n        </Descriptions> */}\n      </Spin>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/work-order/config.tsx",
    "content": "import React from \"react\";\nimport { renderOperationBtns, NavRouterLink } from \"container/custom-component\";\nimport { transTimeFormat, transTimeStamp } from \"lib/utils\";\nimport moment from \"moment\";\nimport { cellStyle } from \"constants/table\";\nimport { Tooltip, DatePicker, Popconfirm, Modal, message } from \"antd\";\nimport { IColumnsType } from \"component/dantd/query-form/QueryForm\";\nimport { IBaseOrder, IOrderInfo, ITypeEnums } from \"typesPath/cluster/order-types\";\nimport {\n  orderStatusMap,\n  STAUS_TYPE_MAP,\n  TASK_STATUS_TYPE_MAP,\n  TASK_TYPE_MAP,\n  TASK_TYPE_MAP_LIST,\n  VERSION_MAINFEST_TYPE,\n} from \"constants/status-map\";\nimport { ILabelValue, IMenuItem, IStringMap } from \"interface/common\";\nimport { LEVEL_MAP } from \"constants/common\";\nimport { INodeTask, ITask } from \"typesPath/task-types\";\nimport { IBaseInfo } from \"typesPath/base-types\";\nimport { BaseInfo } from \"./base-info\";\nimport { PlanSpeed } from \"./plan-speed\";\nimport { cancalTask, createTask, pauseTask, restartTask, retryTask, scaleTask, upgradeTask } from \"api/task-api\";\nimport { cancelDcdr } from \"api/dcdr-api\";\nimport DRangeTime from \"../../d1-packages/d-range-time\";\nconst { RangePicker } = DatePicker;\nexport const authCodeMap = {\n  0: \"超管\",\n  1: \"配置管理\",\n  2: \"访问\",\n  \"-1\": \"无权限\",\n};\n\nexport const getMyApplicationColumns = (typeEnums: IStringMap, type?: string) => {\n  const orderColumns = [\n    {\n      title: \"工单ID\",\n      dataIndex: \"id\",\n      width: 100,\n    },\n    {\n      title: \"工单标题\",\n      dataIndex: \"title\",\n      width: 200,\n      render: (text: string, record: IBaseOrder) => {\n        let href = `/work-order/my-application/detail?title=${text}&orderId=${record.id}`;\n        if (type) {\n          href = `/work-order/my-approval/detail?title=${text}&orderId=${record.id}`;\n        }\n        return (\n          <div className=\"two-row-ellipsis pointer\">\n            <NavRouterLink needToolTip={true} maxShowLength={50} element={text} href={href} />\n          </div>\n        );\n      },\n    },\n    {\n      title: \"工单状态\",\n      dataIndex: \"status\",\n      width: 100,\n      render: (t: any) => (\n        <>\n          <span className={t === 1 ? \"success\" : t === 2 ? \"fail\" : \"\"}>{orderStatusMap[t] || \"\"}</span>\n        </>\n      ),\n    },\n    {\n      title: \"申请时间\",\n      dataIndex: \"createTime\",\n      width: 160,\n      // sorter: (a: IBaseOrder, b: IBaseOrder) => transTimeStamp(b.createTime) - transTimeStamp(a.createTime),\n      render: (t: string) => transTimeFormat(t),\n    },\n    {\n      title: \"工单类型\",\n      dataIndex: \"type\",\n      width: 120,\n      render: (t: string, record: IBaseOrder) => <>{typeEnums[t] || \"-\"}</>,\n    },\n    {\n      title: \"申请原因\",\n      dataIndex: \"description\",\n      width: 200,\n      onCell: () => ({\n        style: {\n          maxWidth: 200,\n          ...cellStyle,\n        },\n      }),\n      render: (text: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={text}>\n            {\" \"}\n            {text || \"_\"}{\" \"}\n          </Tooltip>\n        );\n      },\n    },\n  ];\n  return orderColumns;\n};\n\nexport const getMyApplicationQueryXForm = (typeList: ITypeEnums[], handleTimeChange) => {\n  const customTimeOptions = [\n    {\n      label: \"最近 1 天\",\n      value: 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 7 天\",\n      value: 7 * 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 1 月\",\n      value: 30 * 24 * 60 * 60 * 1000,\n    },\n  ];\n  const formMap = [\n    {\n      dataIndex: \"status\",\n      title: \"工单状态:\",\n      type: \"select\",\n      options: Object.keys(orderStatusMap).map((key) => ({\n        value: key,\n        title: orderStatusMap[key],\n      })),\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"title\",\n      title: \"工单标题:\",\n      type: \"input\",\n      placeholder: \"请输入工单标题\",\n    },\n    {\n      dataIndex: \"type\",\n      title: \"工单类型:\",\n      type: \"select\",\n      options: typeList,\n      placeholder: \"请选择\",\n    },\n    {\n      dataIndex: \"createTime\",\n      title: \"申请时间:\",\n      type: \"custom\",\n      component: <DRangeTime timeChange={handleTimeChange} popoverClassName=\"dashborad-popover\" customTimeOptions={customTimeOptions} />,\n    },\n  ] as IColumnsType[];\n  return formMap;\n};\n\nexport const getTaskQueryXForm = (handleTimeChange) => {\n  const customTimeOptions = [\n    {\n      label: \"最近 1 天\",\n      value: 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 7 天\",\n      value: 7 * 24 * 60 * 60 * 1000,\n    },\n    {\n      label: \"最近 1 月\",\n      value: 30 * 24 * 60 * 60 * 1000,\n    },\n  ];\n  const formMap = [\n    {\n      dataIndex: \"title\",\n      title: \"任务标题:\",\n      type: \"input\",\n      placeholder: \"请输入\",\n    },\n    {\n      dataIndex: \"createTime\",\n      title: \"创建时间:\",\n      type: \"custom\",\n      component: (\n        <DRangeTime\n          timeChange={handleTimeChange}\n          popoverClassName=\"dashborad-popover\"\n          ///resetAllValue={resetAllValue}\n          customTimeOptions={customTimeOptions}\n        />\n      ),\n    },\n  ] as IColumnsType[];\n  return formMap;\n};\n\nexport const getTaskColumns = (reloadData: Function) => {\n  const orderColumns = [\n    {\n      title: \"任务ID\",\n      dataIndex: \"id\",\n      key: \"id\",\n    },\n    {\n      title: \"任务标题\",\n      dataIndex: \"title\",\n      key: \"title\",\n      render: (text: string, record: ITask) => {\n        const str = encodeURI(record.expandData);\n        let href = `/work-order/task/detail?title=${text}&taskid=${record.id}&id=${record.businessKey}&type=${record?.taskType}&status=${record?.status}&dcdr_info=${str}`;\n        if (record.taskType === 10) {\n          href = `/work-order/task/dcdrdetail?title=${text}&taskid=${record.id}&title=${record.title}`;\n        }\n        return <NavRouterLink needToolTip={true} element={text} href={href} />;\n      },\n    },\n    {\n      title: \"任务类型\",\n      dataIndex: \"taskType\",\n      key: \"taskType\",\n      render: (t: any) => <>{TASK_TYPE_MAP[t] || \"_\"}</>,\n    },\n    {\n      title: \"任务状态\",\n      dataIndex: \"status\",\n      key: \"status\",\n      render: (t: any) => <>{TASK_STATUS_TYPE_MAP[t] || \"_\"}</>,\n    },\n    {\n      title: \"创建人\",\n      dataIndex: \"creator\",\n      key: \"creator\",\n      render: (text: string) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={text}>\n            {text}\n          </Tooltip>\n        );\n      },\n    },\n    {\n      title: \"创建时间\",\n      dataIndex: \"createTime\",\n      key: \"createTime\",\n      width: \"10%\",\n      sorter: true,\n      render: (t: string) => transTimeFormat(t),\n    },\n    {\n      title: \"更新时间\",\n      dataIndex: \"updateTime\",\n      key: \"updateTime\",\n      width: \"10%\",\n      sorter: true,\n      render: (t: string) => transTimeFormat(t),\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      key: \"operation\",\n      render: (text: any, record: ITask) => {\n        const btns = getTaskBtns(record, reloadData);\n        return renderOperationBtns(btns, record);\n      },\n    },\n  ];\n  return orderColumns;\n};\n\nconst confirmFn = (text: string, taskId: number, id: number, fn: Function, reloadDataFn: Function) => {\n  Modal.confirm({\n    title: `确定${text}任务${taskId}?`,\n    // icon: <DeleteOutlined style={{ color: \"red\" }} />,\n    width: 500,\n    okText: \"确定\",\n    cancelText: \"取消\",\n    onOk() {\n      fn(id).then(() => {\n        reloadDataFn();\n      });\n    },\n  });\n};\n\nconst getTaskBtns = (record: ITask, reloadData: Function) => {\n  let href = `/work-order/task/detail?title=${record.title}&taskid=${record.id}&id=${record.businessKey}#plan`;\n  if (record.taskType === 10) {\n    href = `/work-order/task/dcdrdetail?title=${record.title}&taskid=${record.id}&title=${record.title}`;\n  }\n  let taskBtns = [\n    {\n      isRouterNav: true,\n      label: <NavRouterLink element={\"查看进度\"} href={href} />,\n    },\n  ];\n  const carryBtn = {\n    label: (\n      <span\n        onClick={() => {\n          // 后端字段修改： record.orderType -> record.taskType\n          return carryTask(record.businessKey, record.taskType, reloadData, record.id);\n        }}\n      >\n        执行\n      </span>\n    ),\n  } as any;\n  const pauseBtn = {\n    label: <span onClick={() => TaskApi.pauseTask(record.businessKey, reloadData, record.id)}>暂停</span>,\n  } as any;\n  const restartBtn = {\n    label: <span onClick={() => TaskApi.retryTask(record.businessKey, reloadData, record.id)}>重试</span>,\n  } as any;\n  const cancalBtn = {\n    label: <span onClick={() => TaskApi.cancalTask(record.businessKey, reloadData, record.id)}>取消</span>,\n  } as any;\n  if (record.taskType === 10) {\n    if (record.status == \"running\") {\n      taskBtns.push({\n        isRouterNav: false,\n        label: (\n          <span\n            onClick={() => {\n              Modal.confirm({\n                title: `提示`,\n                content: `确定取消任务${record.title}?`,\n                // icon: <DeleteOutlined style={{ color: \"red\" }} />,\n                // width: 500,\n                okText: \"确定\",\n                cancelText: \"取消\",\n                onOk() {\n                  cancelDcdr(record.id).then(() => {\n                    reloadData();\n                    message.success(\"操作成功\");\n                  });\n                },\n              });\n            }}\n          >\n            取消\n          </span>\n        ),\n      });\n    }\n    return taskBtns;\n  }\n  switch (record.status) {\n    case \"waiting\":\n      taskBtns = taskBtns.concat(carryBtn, cancalBtn);\n      break;\n    case \"running\":\n      taskBtns = taskBtns.concat(pauseBtn, cancalBtn);\n      break;\n    case \"failed\":\n      taskBtns = taskBtns.concat(restartBtn, cancalBtn);\n      break;\n    case \"pause\":\n      taskBtns = taskBtns.concat(carryBtn, cancalBtn);\n      break;\n  }\n  return taskBtns;\n};\n\nexport const carryTask = (id: number, orderType: number, reloadData: Function, taskId?: number) => {\n  // 1 集群启动create 2 集群扩容scale 3 集群缩容scale 4 集群重启restart 5 集群升级upgrade\n  switch (orderType) {\n    case 1:\n      TaskApi.createTask(id, reloadData, taskId);\n      break;\n    case 2:\n    case 3:\n      TaskApi.scaleTask(id, reloadData, taskId);\n      break;\n    case 4:\n      TaskApi.restartTask(id, reloadData, taskId);\n      break;\n    default:\n      TaskApi.upgradeTask(id, reloadData, taskId);\n  }\n};\n\nconst TaskApi = {\n  createTask: (id: number, reloadData: Function, taskId: number) => {\n    // return createTask(id).then(() => reloadData()); // this.getTaskList()\n    return confirmFn(\"执行\", taskId, id, createTask, reloadData);\n  },\n  scaleTask: (id: number, reloadData: Function, taskId: number) => {\n    // return scaleTask(id).then(() => reloadData());\n    return confirmFn(\"执行\", taskId, id, scaleTask, reloadData);\n  },\n  restartTask: (id: number, reloadData: Function, taskId: number) => {\n    // return restartTask(id).then(() => reloadData());\n    return confirmFn(\"执行\", taskId, id, restartTask, reloadData);\n  },\n  retryTask: (id: number, reloadData: Function, taskId: number) => {\n    // return retryTask(id).then(() => reloadData());\n    return confirmFn(\"重试\", taskId, id, retryTask, reloadData);\n  },\n  upgradeTask: (id: number, reloadData: Function, taskId: number) => {\n    // return upgradeTask(id).then(() => reloadData());\n    return confirmFn(\"执行\", taskId, id, upgradeTask, reloadData);\n  },\n  pauseTask: (id: number, reloadData: Function, taskId: number) => {\n    return confirmFn(\"暂停\", taskId, id, pauseTask, reloadData);\n  },\n  cancalTask: (id: number, reloadData: Function, taskId: number) => {\n    return confirmFn(\"取消\", taskId, id, cancalTask, reloadData);\n  },\n};\n\nexport const DESC_LIST = [\n  {\n    label: \"逻辑索引模板\",\n    key: \"logicTemplateName\",\n    render: (value: string) => (\n      <>\n        <span>{value || \"-\"}</span>\n      </>\n    ),\n  },\n  {\n    label: \"所属逻辑集群\",\n    key: \"logicClusterName\",\n    render: (value: string) => (\n      <>\n        <span>{value || \"-\"}</span>\n      </>\n    ),\n  },\n  {\n    label: \"物理索引模板（主）\",\n    key: \"masterPhysicalTemplateName\",\n    render: (value: string) => (\n      <>\n        <span>{value || \"-\"}</span>\n      </>\n    ),\n  },\n  {\n    label: \"所属物理集群（主）\",\n    key: \"masterPhysicalClusterName\",\n    render: (value: string) => (\n      <>\n        <span>{value || \"-\"}</span>\n      </>\n    ),\n  },\n  {\n    label: \"物理索引模板（从）\",\n    key: \"vicePhysicalTemplateName\",\n    render: (value: string) => (\n      <>\n        <span>{value || \"-\"}</span>\n      </>\n    ),\n  },\n  {\n    label: \"所属物理集群（从）\",\n    key: \"vicePhysicalClusterName\",\n    render: (value: string) => (\n      <>\n        <span>{value || \"-\"}</span>\n      </>\n    ),\n  },\n  {\n    label: \"开始时间\",\n    key: \"createTime\",\n    render: (value: string) => (\n      <>\n        <span>{transTimeFormat(value)}</span>\n      </>\n    ),\n  },\n];\n\nexport enum TAB_LIST_KEY {\n  base = \"base\",\n  plan = \"plan\",\n  dcdrPlan = \"dcdrPlan\",\n}\n\nexport const BASE_INFO: IBaseInfo[] = [\n  {\n    key: \"title\",\n    label: \"任务名称\",\n  },\n  {\n    key: \"status\",\n    label: \"任务状态\",\n    render: (text: string) => {\n      let type = \"\";\n      STAUS_TYPE_MAP.forEach((ele: ILabelValue) => {\n        if (ele.value === text) {\n          type = ele.text;\n        }\n      });\n      return <>{type}</>;\n    },\n  },\n  {\n    key: \"clusterNodeRole\",\n    label: \"节点角色\",\n    render: (text: string) => {\n      return <>{text}</>;\n    },\n  },\n  {\n    key: \"createTime\",\n    label: \"创建时间\",\n    render: (t: string) => transTimeFormat(t),\n  },\n  {\n    key: \"updateTime\",\n    label: \"更新时间\",\n    render: (t: string) => transTimeFormat(t),\n  },\n  {\n    key: \"clusterName\",\n    label: \"生效集群\",\n  },\n  {\n    key: \"orderType\",\n    label: \"集群类型\",\n    render: (t: number) => {\n      let type = \"\";\n      TASK_TYPE_MAP_LIST.forEach((ele: ILabelValue) => {\n        if (ele.value === t) {\n          type = ele.text;\n        }\n      });\n      return <>{type}</>;\n    },\n  },\n  {\n    key: \"desc\",\n    label: \"集群描述\",\n    render: (t) => {\n      return t || \"-\";\n    },\n  },\n  {\n    key: \"esVersion\",\n    label: \"ES 版本\",\n  },\n];\n\nexport const ORDER_INFO = (task) => {\n  return [\n    {\n      key: \"title\",\n      label: \"工单标题\",\n      render: (text: number) => (\n        <>\n          <div style={{ float: \"left\" }}>\n            <span className=\"text-value\">\n              {text}（{task.taskBaseInfo?.workOrderId}）\n            </span>\n          </div>\n          <div style={{ float: \"left\" }}>\n            <NavRouterLink element=\"查看\" href={`/work-order/my-approval/detail?title=${text}&orderId=${task.taskBaseInfo?.workOrderId}`} />\n          </div>\n        </>\n      ),\n    },\n    {\n      key: \"creator\",\n      label: \"申请人\",\n    },\n  ];\n};\n\nexport const getPlanSpeedColumns = (setModalId: Function) => {\n  const cols = [\n    {\n      title: \"ID\",\n      dataIndex: \"id\",\n      key: \"id\",\n    },\n    {\n      title: \"节点名称\",\n      dataIndex: \"hostname\",\n      key: \"hostname\",\n    },\n    {\n      title: \"分组\",\n      dataIndex: \"grp\",\n      key: \"grp\",\n    },\n    {\n      title: \"更新时间\",\n      dataIndex: \"updateTime\",\n      key: \"updateTime\",\n      sorter: (a: INodeTask, b: INodeTask) => transTimeStamp(b.updateTime) - transTimeStamp(a.updateTime),\n      render: (t: string) => transTimeFormat(t),\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      key: \"operation\",\n      width: \"15%\",\n      render: (text: number, record: INodeTask) => {\n        const btns = getPlanBtns(record, setModalId);\n        return renderOperationBtns(btns as any, record);\n      },\n    },\n  ];\n  return cols;\n};\n\nconst getPlanBtns = (record: INodeTask, setModalId) => {\n  const taskBtns = [\n    {\n      label: \"查看日志\",\n      clickFunc: (record: INodeTask) => {\n        // viewTaskLog(record.id);\n        setModalId(\"taskLogModal\", record.id);\n      },\n    },\n    {\n      label: (\n        <Popconfirm title=\"确定重试？\" onConfirm={() => null}>\n          <a>重试</a>\n        </Popconfirm>\n      ),\n    },\n    {\n      label: (\n        <Popconfirm title=\"确定忽略？\" onConfirm={() => null}>\n          <a>忽略</a>\n        </Popconfirm>\n      ),\n    },\n  ];\n  if (record.status === \"failed\") {\n    return taskBtns;\n  }\n  return taskBtns.slice(0, 1);\n};\nexport const TASK_TAB_LIST = [\n  {\n    name: \"基础信息\",\n    key: TAB_LIST_KEY.base,\n    content: <BaseInfo task={{} as any} />,\n  },\n  {\n    name: \"执行进度\",\n    key: TAB_LIST_KEY.plan,\n    content: <PlanSpeed task={{} as any} />,\n  },\n];\nconst menuMap = new Map<string, IMenuItem>();\nTASK_TAB_LIST.forEach((d) => {\n  menuMap.set(d.key, d);\n});\n\nexport const TASK_MENU_MAP = menuMap;\n\nexport const DCDR_STEPS = [\n  {\n    title: \"创建dcdr\",\n    description: \"\",\n    key: 0,\n  },\n  {\n    title: \"停止向主索引写入数据\",\n    description: \"\",\n    key: 1,\n  },\n  {\n    title: \"确保主从索引数据同步\",\n    description: \"\",\n    key: 2,\n  },\n  {\n    title: \"删除源dcdr模板和索引链路\",\n    description: \"\",\n    key: 3,\n  },\n  {\n    title: \"拷贝主模板的mapping信息到从模板\",\n    description: \"\",\n    key: 4,\n  },\n  {\n    title: \"关闭从索引dcdr索引开关，并打开主索引dcdr索引开关\",\n    description: \"\",\n    key: 5,\n  },\n  {\n    title: \"停止从索引写入\",\n    description: \"\",\n    key: 6,\n  },\n  {\n    title: \"创建新的dcdr链路\",\n    description: \"\",\n    key: 7,\n  },\n  {\n    title: \"恢复主从索引实时写入\",\n    description: \"\",\n    key: 8,\n  },\n  {\n    title: \"主从模板角色切换\",\n    description: \"\",\n    key: 9,\n  },\n];\n\nexport const getInfoRenderItem = (orderInfo: IOrderInfo) => {\n  const { type, detailInfo, description } = orderInfo;\n  const logicClusterIndecreaseList: ILabelValue[] = [\n    {\n      label: \"集群名称\",\n      value: detailInfo?.logicClusterName,\n    },\n    {\n      label: \"data节点数\",\n      value: detailInfo?.oldDataNodeNu,\n    },\n    {\n      label: \"期望节点数\",\n      value: detailInfo?.dataNodeNu,\n    },\n    {\n      label: \"节点规格\",\n      value: detailInfo?.dataNodeSpec,\n    },\n    {\n      label: \"申请原因\",\n      value: description,\n    },\n  ];\n\n  const logicClusterCreateList: ILabelValue[] = [\n    {\n      label: \"集群名称\",\n      value: detailInfo?.name,\n    },\n    {\n      label: \"业务等级\",\n      value: LEVEL_MAP[Number(detailInfo?.level) - 1]?.label,\n    },\n    {\n      label: \"节点规格\",\n      value: detailInfo?.dataNodeSpec,\n    },\n    {\n      label: \"data节点数\",\n      value: detailInfo?.dataNodeNu,\n    },\n    {\n      label: \"申请原因\",\n      value: description,\n    },\n  ];\n\n  if (type === \"logicClusterIndecrease\") {\n    return logicClusterIndecreaseList;\n  } else if (type === \"logicClusterCreate\") {\n    return logicClusterCreateList;\n  } else if (type === \"dslTemplateStatusChange\") {\n    return [\n      {\n        label: \"查询模版\",\n        value: detailInfo?.dslTemplateMd5,\n      },\n    ];\n  } else if (type === \"dslTemplateQueryLimit\") {\n    const { dslQueryLimitDTOList } = detailInfo;\n    const dslTemplateQueryLimit: ILabelValue[] = [];\n    for (let item of dslQueryLimitDTOList) {\n      dslTemplateQueryLimit.push(\n        ...[\n          {\n            label: \"查询模版\",\n            value: item?.dslTemplateMd5,\n          },\n          {\n            label: \"原限流值\",\n            value: item?.queryLimitBefore,\n          },\n          {\n            label: \"修改后限流值\",\n            value: item?.queryLimit,\n          },\n        ]\n      );\n    }\n    return dslTemplateQueryLimit;\n  } else if (type === \"templateLogicBlockWrite\" || type === \"templateLogicBlockRead\") {\n    return [\n      {\n        label: \"索引模版\",\n        value: detailInfo?.name,\n      },\n    ];\n  } else {\n    return [] as ILabelValue[];\n  }\n};\n\nexport const getAddConfigInfoColumns = (type: string, setDrawerId: Function): any => {\n  const columns = [\n    {\n      title: \"节点角色\",\n      dataIndex: \"enginName\",\n      key: \"enginName\",\n    },\n    {\n      title: \"配置类别\",\n      dataIndex: \"typeName\",\n      key: \"typeName\",\n      render: (value: string) => <span>{value || \"-\"}</span>,\n    },\n    {\n      title: \"配置内容\",\n      dataIndex: \"configData\",\n      key: \"configData\",\n      onCell: () => ({\n        style: cellStyle,\n      }),\n      render: (text: string) => {\n        return (\n          <a\n            onClick={() => {\n              setDrawerId(\"configDetail\", text);\n            }}\n          >\n            {text}\n          </a>\n        );\n      },\n    },\n  ];\n  const columnsItem = {\n    title: \"原配置内容\",\n    dataIndex: \"originalConfigData\",\n    key: \"originalConfigData\",\n    onCell: () => ({\n      style: cellStyle,\n    }),\n    render: (text: string) => {\n      return (\n        <a\n          onClick={() => {\n            setDrawerId(\"configDetail\", text);\n          }}\n        >\n          {text}\n        </a>\n      );\n    },\n  };\n  const columnsItemUpdata = {\n    title: \"编辑后内容\",\n    dataIndex: \"configData\",\n    key: \"configData\",\n    onCell: () => ({\n      style: cellStyle,\n    }),\n    render: (text: string) => {\n      return (\n        <a\n          onClick={() => {\n            setDrawerId(\"configDetail\", text);\n          }}\n        >\n          {text}\n        </a>\n      );\n    },\n  };\n  if (type.indexOf(\"编辑\") > -1) {\n    columns.splice(2, 1, columnsItem, columnsItemUpdata);\n  }\n  return columns;\n};\n"
  },
  {
    "path": "arius-console/src/container/work-order/dcdr-detail.tsx",
    "content": "import React, { useState, useEffect, useRef } from \"react\";\nimport { SPIT_STYLE_MAP, DCDR_STATE_MAP } from \"constants/status-map\";\nimport { cancelDcdr, getDcdrDetail, canceltemplateDcdr } from \"api/dcdr-api\";\nimport \"./dcdr.less\";\nimport \"./index.less\";\nimport { Button, Progress, Popconfirm, Tooltip, Collapse, Modal, message } from \"antd\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { DcdrDrawer } from \"./dcdr-drawer\";\nimport Url from \"lib/url-parser\";\nimport moment from \"moment\";\nimport { transTimeFormat } from \"lib/utils\";\n\nexport const DcdrTaskList: React.FC = () => {\n  const [data, setData]: any = useState({});\n  // 依赖data 利用ref避过effect依赖监测\n  const ref: any = useRef();\n  const [visible, setVisible] = useState(false);\n  const [params, setParams] = useState({\n    taskId: 0,\n    templateId: 0,\n  });\n  const urlParam: any = Url().search;\n\n  const reloadData = () => {\n    getDcdrDetail(urlParam.taskid).then((res) => {\n      ref.current = res;\n      setData(res);\n    });\n  };\n\n  // 开启定时器定时刷新\n  React.useEffect(() => {\n    reloadData();\n    const time = setInterval(() => {\n      if (ref.current && ref.current?.state !== 0 && ref.current?.state !== 3 && ref.current?.state !== 1) {\n        reloadData();\n      }\n    }, 10 * 1000);\n    return () => clearInterval(time);\n  }, [urlParam.taskid, ref]);\n\n  let pattern = null as any;\n  SPIT_STYLE_MAP.forEach((ele, index) => {\n    if (ele.type === DCDR_STATE_MAP[data?.state]) {\n      pattern = ele;\n    }\n  });\n\n  const getColumns = (reloadData: Function) => {\n    return [\n      {\n        title: \"任务标题\",\n        dataIndex: \"taskTitle\",\n        key: \"taskTitle\",\n      },\n      {\n        title: \"任务状态\",\n        dataIndex: \"taskStatus\",\n        key: \"taskStatus\",\n        render: (text, record) => {\n          let pattern = null as any;\n          SPIT_STYLE_MAP.forEach((ele, index) => {\n            if (ele.type === DCDR_STATE_MAP[text]) {\n              pattern = ele;\n            }\n          });\n          const colorMap = {\n            0: \"#bfbfbf\",\n            1: \"#10c038\",\n            2: \"#ff931d\",\n            3: \"#f04134\",\n            4: \"#bfbfbf\",\n          };\n          const spotStyle = {\n            width: 6,\n            height: 6,\n            borderRadius: \"50%\",\n            background: colorMap[text],\n            display: \"inline-block\",\n            marginRight: 4,\n          };\n          return (\n            <span>\n              <div style={spotStyle} />\n              {pattern.text}\n            </span>\n          );\n        },\n      },\n      {\n        title: \"任务类型\",\n        dataIndex: \"switchType\",\n        key: \"switchType\",\n        render: (text) => {\n          return text == 1 ? \"平滑切换\" : \"强制切换\";\n        },\n        sorter: (a, b) => {\n          return a?.switchType - b?.switchType;\n        },\n      },\n      {\n        title: \"创建时间\",\n        dataIndex: \"createTime\",\n        key: \"createTime\",\n        render: (text) => transTimeFormat(text),\n        sorter: (a, b) => {\n          return moment(a?.createTime).valueOf() - moment(b?.createTime).valueOf();\n        },\n      },\n      {\n        title: \"更新时间\",\n        dataIndex: \"updateTime\",\n        key: \"updateTime\",\n        render: (text) => transTimeFormat(text),\n        sorter: (a, b) => {\n          return moment(a?.updateTime).valueOf() - moment(b?.updateTime).valueOf();\n        },\n      },\n      {\n        title: \"操作\",\n        dataIndex: \"operation\",\n        filterTitle: true,\n        key: \"operation\",\n        render: (text: any, record: any) => {\n          return (\n            <>\n              <a\n                href=\"javaScript:;\"\n                onClick={() => {\n                  setVisible(true);\n                  setParams({\n                    taskId: urlParam.taskid,\n                    templateId: record.templateId,\n                  });\n                }}\n              >\n                查看详情\n              </a>\n              {record.taskStatus === 2 || record.taskStatus === 4 ? (\n                <a\n                  href=\"javaScript:;\"\n                  style={{ marginLeft: 20 }}\n                  onClick={() => {\n                    Modal.confirm({\n                      title: `提示`,\n                      content: `确定取消任务${decodeURI(record?.taskTitle)}?`,\n                      // icon: <DeleteOutlined style={{ color: \"red\" }} />,\n                      // width: 500,\n                      okText: \"确定\",\n                      cancelText: \"取消\",\n                      onOk() {\n                        canceltemplateDcdr(urlParam?.taskid, record?.templateId).then(() => {\n                          message.success(\"操作成功\");\n                          reloadData();\n                        });\n                      },\n                    });\n                  }}\n                >\n                  取消\n                </a>\n              ) : null}\n            </>\n          );\n        },\n      },\n    ];\n  };\n\n  // 关闭抽屉\n  const onCancel = () => {\n    setVisible(false);\n    setParams({\n      taskId: 0,\n      templateId: 0,\n    });\n  };\n  return (\n    <div className=\"dcdr-taskdetail\">\n      <div className=\"dcdr-taskdetail-header\">任务详情</div>\n      <div className=\"plan-speed-head\" style={{ borderBottom: \"solid 1px #DBE0E4\" }}>\n        <div className=\"speed-head-left\">\n          <span className=\"head-left-top\">\n            <Progress percent={data?.percent} strokeColor={pattern?.color.replace(\"333\", \"BFBFBF\")} className=\"left-top-pro\" />\n            <i className={`left-top-text ${pattern?.back}`}>{pattern?.text}</i>\n          </span>\n          <ul className=\"head-left-ul\">\n            <li>\n              <span>\n                <div className=\"spot running\" />\n                总数：{data?.total}\n              </span>\n              <span>\n                <div className=\"spot success\" />\n                成功：{data?.successNum}\n              </span>\n              <span>\n                <div className=\"spot failed\" />\n                失败：{data?.failedNum}\n              </span>\n              <span>\n                <div className=\"spot creating\" />\n                执行中：{data?.runningNum}\n              </span>\n              <span>\n                <div className=\"spot waiting\" />\n                待执行：{data?.waitNum}\n              </span>\n              <span>\n                <div className=\"spot waiting\" />\n                已取消：{data?.cancelNum}\n              </span>\n            </li>\n          </ul>\n        </div>\n        <div>\n          <Button\n            className=\"cancel-all\"\n            type=\"primary\"\n            disabled={ref.current?.state !== 2}\n            onClick={() => {\n              Modal.confirm({\n                title: `提示`,\n                content: `确定取消任务${decodeURI(urlParam?.title)}?`,\n                // icon: <DeleteOutlined style={{ color: \"red\" }} />,\n                // width: 500,\n                okText: \"确定\",\n                cancelText: \"取消\",\n                onOk() {\n                  cancelDcdr(urlParam?.taskid).then(() => {\n                    reloadData();\n                  });\n                },\n              });\n            }}\n          >\n            全部取消\n          </Button>\n        </div>\n      </div>\n      <DTable\n        columns={getColumns(reloadData)}\n        rowKey=\"templateId\"\n        dataSource={data?.dcdrSingleTemplateMasterSlaveSwitchDetailList || []}\n        reloadData={reloadData}\n      />\n      <DcdrDrawer visible={visible} onCancel={onCancel} {...params} parentReload={reloadData} />\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/work-order/dcdr-drawer.tsx",
    "content": "import React, { useState, useEffect, useRef } from \"react\";\nimport { Drawer, Descriptions, Timeline, Button, Modal, message, Tooltip } from \"antd\";\nimport \"./dcdr.less\";\nimport { CheckOutlined, SyncOutlined, CloseOutlined } from \"@ant-design/icons\";\nimport { getTemplateDcdrDetail, dcdrForceSwitch, dcdrRefresh } from \"api/dcdr-api\";\nimport { transTimeFormat } from \"lib/utils\";\n\ninterface IDcdrDrawer {\n  taskId: number;\n  templateId: number;\n  visible: boolean;\n  onCancel: () => void;\n  parentReload: () => void;\n}\n\nexport const DescList = [\n  {\n    title: \"所属集群(主):\",\n    dataIndex: \"masterCluster\",\n    render: (value) => value || \"-\",\n  },\n  {\n    title: \"所属集群(从):\",\n    dataIndex: \"slaveCluster\",\n    render: (value) => value || \"-\",\n  },\n  {\n    title: \"创建时间:\",\n    dataIndex: \"createTime\",\n    render: (value) => transTimeFormat(value),\n  },\n  {\n    title: \"完成时间:\",\n    dataIndex: \"updateTime\",\n    render: (value) => transTimeFormat(value),\n  },\n  {\n    title: \"任务类型:\",\n    dataIndex: \"switchType\",\n    render: (value) => (value == 1 ? \"平滑切换\" : \"强制切换\"),\n  },\n];\n\nexport const DcdrDrawer: React.FC<IDcdrDrawer> = (props: IDcdrDrawer) => {\n  const [data, setData]: any = useState({});\n  // 依赖data 利用ref避过effect依赖监测\n  const ref: any = useRef();\n\n  const renderTitle = (text) => {\n    return <div className=\"dcdr-drawer-title\">{text}</div>;\n  };\n\n  const reloadData = () => {\n    if (props.visible) {\n      getTemplateDcdrDetail(props.taskId, props.templateId).then((res) => {\n        ref.current = res;\n        setData(res);\n      });\n    }\n  };\n\n  useEffect(() => {\n    reloadData();\n    const time = setInterval(() => {\n      if (ref.current && ref.current?.taskStatus !== 0 && ref.current?.taskStatus !== 3 && ref.current?.taskStatus !== 1) {\n        reloadData();\n      }\n    }, 10 * 1000);\n    return () => {\n      clearInterval(time);\n    };\n  }, [props.visible, props.taskId, props.templateId, ref]);\n\n  const renderDesc = () => {\n    return (\n      <div>\n        {renderTitle(\"基本信息\")}\n        <div style={{ padding: 24, marginBottom: 8 }}>\n          <Descriptions column={2} bordered>\n            {DescList.map((item) => (\n              <Descriptions.Item label={item.title} key={item.title}>\n                {item && item.render ? item.render(data[item?.dataIndex]) : data[item?.dataIndex]}\n              </Descriptions.Item>\n            ))}\n          </Descriptions>\n        </div>\n      </div>\n    );\n  };\n\n  const renderStep = () => {\n    let todo = false;\n    let fail = false;\n    return (\n      <div>\n        {renderTitle(\"执行进度\")}\n        <div style={{ padding: 24 }}>\n          <Timeline>\n            {data?.taskProgressList?.map((item, index) => {\n              const values = item.split(\"@@@\");\n              let icon = (\n                <div className=\"dcdr-drawer-step-icon\">\n                  <div className=\"dcdr-drawer-step-icon-text\">{index + 1}</div>\n                </div>\n              );\n              if (values && values[1] === \"DONE\") {\n                icon = (\n                  <div className=\"dcdr-drawer-step-icon-done\">\n                    <CheckOutlined style={{ marginTop: 4 }} />\n                  </div>\n                );\n              }\n              if (values && values[1] === \"TODO\" && !todo && !fail) {\n                todo = true;\n                icon = (\n                  <div className=\"dcdr-drawer-step-icon-todo\">\n                    <SyncOutlined style={{ marginTop: 4 }} />\n                  </div>\n                );\n              }\n              if (values && values[1] === \"FAIL\" && !fail) {\n                fail = true;\n                icon = (\n                  <div className=\"dcdr-drawer-step-icon-fail\">\n                    <CloseOutlined style={{ marginTop: 4 }} />\n                  </div>\n                );\n              }\n              return (\n                <Timeline.Item dot={icon} key={index}>\n                  <div>\n                    <div className=\"dcdr-drawer-step-title\">{values[0]}</div>\n                    <div className=\"dcdr-drawer-step-text\">{values[2]}</div>\n                  </div>\n                </Timeline.Item>\n              );\n            })}\n          </Timeline>\n        </div>\n      </div>\n    );\n  };\n\n  const handleDcdrForceSwitch = () => {\n    Modal.confirm({\n      title: `提示`,\n      content: `确定进行强制切换吗？`,\n      // icon: <DeleteOutlined style={{ color: \"red\" }} />,\n      // width: 500,\n      okText: \"确定\",\n      cancelText: \"取消\",\n      onOk() {\n        dcdrForceSwitch(props.taskId, props.templateId).then((res) => {\n          message.success(\"操作成功\");\n          reloadData();\n          props.parentReload();\n        });\n      },\n    });\n  };\n\n  const handleDcdrRefresh = () => {\n    Modal.confirm({\n      title: `提示`,\n      content: `确定重试该任务吗？`,\n      // icon: <DeleteOutlined style={{ color: \"red\" }} />,\n      // width: 500,\n      okText: \"确定\",\n      cancelText: \"取消\",\n      onOk() {\n        dcdrRefresh(props.taskId, props.templateId).then((res) => {\n          message.success(\"操作成功\");\n          reloadData();\n          props.parentReload();\n        });\n      },\n    });\n  };\n\n  const renderFooter = () => {\n    return (\n      <div>\n        <Button\n          className=\"dcdr-drawer-footer-button\"\n          type=\"primary\"\n          disabled={!(data && data.taskStatus === 3)}\n          onClick={handleDcdrRefresh}\n        >\n          重试\n        </Button>\n        {(data && data.switchType === 2) || data.taskStatus === 1 || data.taskStatus === 0 ? null : (\n          <Button className=\"dcdr-drawer-footer-button\" type=\"primary\" onClick={handleDcdrForceSwitch}>\n            强制切换\n          </Button>\n        )}\n        <Button onClick={props?.onCancel}>返回</Button>\n      </div>\n    );\n  };\n\n  return (\n    <Drawer\n      title={\n        <div style={{ fontSize: 14, color: \"#1D2330\" }}>\n          <Tooltip title={data?.taskTitle || \"任务详情\"}>\n            {(data?.taskTitle && data?.taskTitle.length > 20 ? `${data?.taskTitle.substring(0, 20)}...` : data?.taskTitle) || \"任务详情\"}\n          </Tooltip>\n        </div>\n      }\n      visible={props?.visible}\n      onClose={props?.onCancel}\n      width={700}\n      maskClosable={true}\n      bodyStyle={{ padding: 0 }}\n      footer={renderFooter()}\n    >\n      {renderDesc()}\n      {renderStep()}\n    </Drawer>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/container/work-order/dcdr-plan-speed.tsx",
    "content": "import * as React from 'react';\nimport Url from 'lib/url-parser';\nimport './index.less';\nimport { DCDR_STEPS } from './config';\nimport { DCDR_TASK_STATUS_TYPE_MAP } from 'constants/status-map';\nimport  { Divider, PageHeader, Steps }  from 'antd';\n\nconst task = {} as any;\nconst { Step } = Steps;\n\nexport class DcdrPlanSpeed extends React.Component {\n  public id: number = null;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.id = Number(url.search.id);\n  }\n\n  public render() {\n    let status = task.dcdrStepDetail.status ===  DCDR_TASK_STATUS_TYPE_MAP[1] ? 'error' : 'process' as any;\n    if ((DCDR_STEPS.length - 1) === task.dcdrStepDetail.taskProgress) status = 'finish';\n    return (\n      <>\n      <PageHeader\n        className=\"detail-header\"\n        backIcon={false}\n        title={'执行进度'}\n      >\n        <Steps\n          direction=\"vertical\"\n          current={task.dcdrStepDetail.taskProgress}\n          status={status}\n        >\n            {\n              DCDR_STEPS.map((item, index) => {\n                return <Step\n                  key={index}\n                  title={item.title}\n                  description={status === index ? task.dcdrStepDetail?.comment : item.description}\n                  icon={(task.dcdrStepDetail.status === DCDR_TASK_STATUS_TYPE_MAP[1] && task.dcdrStepDetail.taskProgress === index)\n                  ? 'loading...'\n                  : ''}\n                />;\n              })\n            }\n        </Steps>\n        <Divider />\n      </PageHeader>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/work-order/dcdr.less",
    "content": ".dcdr-taskdetail {\n  background-color: #ffffff;\n  width: 100%;\n  border-radius: 4px;\n  padding: 20px;\n  min-height: 800px;\n  &-header {\n    font-size: 16px;\n    color: #101724;\n    line-height: 24px;\n    height: 24px;\n    margin-bottom: 16px;\n  }\n  .cancel-all {\n    position: relative;\n    bottom: 5px;\n  }\n}\n\n.dcdr-drawer {\n  &-title {\n    width: 100%;\n    height: 40px;\n    background: #f9f9fa;\n    font-family: PingFangSC-Medium;\n    font-size: 12px;\n    color: #1d2330;\n    text-align: left;\n    line-height: 40px;\n    padding-left: 24px;\n  }\n  &-step-title {\n    font-family: PingFangSC-Regular;\n    font-size: 13px;\n    color: #374053;\n    line-height: 18px;\n    margin-bottom: 4px;\n  }\n  &-step-text {\n    font-family: PingFangSC-Regular;\n    font-size: 12px;\n    color: #919aac;\n    line-height: 18px;\n  }\n  &-step-icon {\n    width: 22px;\n    height: 22px;\n    border-radius: 22px;\n    border: solid #d7dae0 1px;\n  }\n  &-step-icon-text {\n    font-family: PingFangSC-Regular;\n    font-size: 12px;\n    color: #a9afbc;\n    text-align: center;\n    line-height: 18px;\n  }\n  &-step-icon-done {\n    color: #1473ff;\n    width: 22px;\n    height: 22px;\n    border-radius: 22px;\n    border: solid #1473ff 1px;\n  }\n  &-step-icon-todo {\n    color: #faad14;\n    width: 22px;\n    height: 22px;\n    border-radius: 22px;\n    border: solid #faad14 1px;\n  }\n  &-step-icon-fail {\n    color: #ff4d4f;\n    width: 22px;\n    height: 22px;\n    border-radius: 22px;\n    border: solid #ff4d4f 1px;\n  }\n  &-footer {\n    &-button {\n      margin-right: 8px;\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/work-order/index.less",
    "content": ".k-collect {\n  width: 250px;\n  position: relative;\n\n  .bat-op {\n    margin-bottom: 12px;\n  }\n\n  .ant-alert-close-icon {\n    top: 7px;\n  }\n\n  .k-coll-btn {\n    position: absolute;\n    top: 9px;\n    right: 15px;\n\n    .btn-right {\n      margin-right: 5px;\n    }\n  }\n}\n\n.container {\n  position: relative;\n\n  .operation-panel {\n    position: absolute;\n    top: 0px;\n    right: 23px;\n  }\n}\n\n.order-detail {\n  .detail-top {\n    width: calc(100% - 190px);\n    position: fixed;\n    top: 55px;\n    z-index: 999;\n  }\n\n  .btn-groups {\n    background: white;\n    width: 100%;\n    margin-top: -5px;\n    box-shadow: 0px 12px 8px -14px #c5c2c2;\n  }\n\n  .detail-btn {\n    margin-right: 10px;\n  }\n\n  .work-detail-box {\n    background: #fff;\n    padding: 20px 30px 60px;\n    margin: 85px 0 50px;\n  }\n\n  .step {\n    margin-top: 60px;\n    margin-bottom: 40px;\n  }\n}\n\n.chart-box {\n  background-color: white;\n  padding: 0px 20px 10px 20px;\n}\n\n.op-panel {\n  position: absolute;\n  top: 0px;\n  right: 0px;\n\n  span:first-child {\n    margin-right: 8px;\n  }\n}\n\n.plan-speed-head {\n  display: flex;\n  justify-content: space-between;\n  margin-bottom: 20px;\n  font-size: 12px;\n  line-height: 30px;\n  width: 100%;\n  padding-top: 24px;\n\n  .speed-head-left {\n    width: 84%;\n    display: flex;\n    justify-content: left;\n\n    .head-left-top {\n      width: 40%;\n\n      .left-top-pro {\n        width: 75%;\n        margin-top: 4px;\n        margin-right: 20px;\n      }\n\n      .left-top-text {\n        width: 25%;\n        padding: 3px 10px;\n        border-radius: 2px;\n        font-style: normal;\n        margin-left: 10px;\n      }\n    }\n\n    .head-left-ul {\n      width: 60%;\n      margin-left: 20px;\n      display: flex;\n      justify-self: start;\n\n      span {\n        float: left;\n        display: flex;\n        justify-self: start;\n        margin-right: 10px;\n\n        .spot {\n          width: 6px;\n          height: 6px;\n          border-radius: 50%;\n          margin: 11px 5px;\n        }\n      }\n    }\n  }\n\n  .success {\n    background: #10c038;\n  }\n\n  .failed {\n    background: #f04134;\n  }\n\n  .creating {\n    background: #ff931d;\n  }\n\n  .running {\n    background: #337dff;\n  }\n\n  .waiting {\n    background: #bfbfbf;\n  }\n\n  .ignore {\n    background: #333;\n  }\n\n  .success-back {\n    background: #edf8e8;\n    color: #10c038;\n    border: 1px solid #10c038;\n  }\n\n  .failed-back {\n    background: #fff2f1;\n    color: #f04134;\n    border: 1px solid #f04134;\n  }\n\n  .pause-back {\n    background: #fef9ed;\n    color: #ff931d;\n    border: 1px solid #ff931d;\n  }\n\n  .running-back {\n    background: rgb(202, 217, 241);\n    color: #337dff;\n    border: 1px solid #337dff;\n  }\n\n  .waiting-back {\n    background: #e6f4ff;\n    color: #1473ff;\n    border: 1px solid #8fc7ff;\n  }\n\n  .cancel-back {\n    background: #d7d7d7;\n    color: #555555;\n    border: 1px solid #555555;\n  }\n}\n\n.ant-steps-vertical .ant-steps-item-content {\n  min-height: 80px;\n}\n.button-styles {\n  height: 30px;\n  font-size: 12px;\n}\n.task-detail-wrapper {\n  height: calc(100% - 118px);\n  overflow-y: auto;\n  padding-top: 20px;\n  margin: 20px 0;\n}\n.menu-container.task-detail {\n  background-color: transparent;\n  padding: 20px 0;\n}\n"
  },
  {
    "path": "arius-console/src/container/work-order/my-application.tsx",
    "content": "import React, { useState, useRef } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getMyApplicationQueryXForm, getMyApplicationColumns } from \"./config\";\nimport moment from \"moment\";\nimport QueryForm from \"component/dantd/query-form\";\nimport { getApplyOrderList, getTypeEnums } from \"api/order-api\";\nimport { ITypeEnums } from \"typesPath/cluster/order-types\";\nimport { IStringMap } from \"interface/common\";\nimport { queryFormText } from \"constants/status-map\";\nimport { DTable } from \"component/dantd/dtable\";\nimport { ProTable } from \"knowdesign\";\nimport { RenderTitle } from \"component/render-title\";\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nexport const MyApplication = connect(\n  null,\n  mapDispatchToProps\n)((props) => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject] = useState(null);\n  const [data, setData] = useState([]);\n  const [typeList, setTypeList] = useState([] as ITypeEnums[]);\n  const [typeEnums, setTypeEnums] = useState({} as IStringMap);\n  const [startAndEnd, setStartAndEnd] = useState([]);\n  //const [resetValue, setResetValue] = useState(null);\n  const buttonTime = useRef(null);\n  React.useEffect(() => {\n    reloadData();\n  }, [department]);\n\n  React.useEffect(() => {\n    getTypeEnumsFn();\n  }, []);\n  // React.useEffect(() => {\n  //   //setResetValue初始化只会执行一次\n  //   if (resetValue) {\n  //     for (var i in resetValue) {\n  //       resetValue[i](undefined)\n  //     }\n  //   }\n  // }, [resetValue]);\n\n  const getTypeEnumsFn = () => {\n    getTypeEnums().then((res) => {\n      const arr = res.map((ele, index) => {\n        return {\n          ...ele,\n          value: ele.type,\n          title: ele.message,\n          key: index + 1,\n        };\n      });\n      const obj = {} as IStringMap;\n      arr.map((e: ITypeEnums) => {\n        obj[e.type] = e.message;\n      });\n      setTypeEnums(obj);\n      setTypeList(arr);\n    });\n  };\n\n  const getData = () => {\n    // 查询项的key 要与 数据源的key  对应\n    if (!queryFormObject) return data;\n    const keys = Object.keys(queryFormObject);\n    const filterData = data.filter((d) => {\n      let b = true;\n      keys.forEach((k: string) => {\n        if (k === \"createTime\") {\n          const time = moment(d[k]).unix() * 1000;\n          if (queryFormObject[k][0] > time || time > queryFormObject[k][1]) {\n            b = false;\n          }\n        } else if (k === \"type\") {\n          d[k] === queryFormObject[k] ? \"\" : (b = false);\n        } else {\n          (d[k] + \"\")?.includes(queryFormObject[k]) ? \"\" : (b = false);\n        }\n      });\n      return b;\n    });\n    return filterData;\n  };\n\n  const reloadData = () => {\n    setloading(true);\n    getApplyOrderList(1)\n      .then((res) => {\n        if (res) {\n          let list = res.sort((a, b) => new Date(b.createTime).getTime() - new Date(a.createTime).getTime());\n          setData(list);\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const handleSubmit = (result) => {\n    const copyResult = JSON.parse(JSON.stringify(result));\n    // 增加点击刷新按钮先计算时间差 保持用户选择的事件范围\n    //判断此时是否是自定义时间情况，如果是则不需要实时更新时间戳，反之不需要。\n    const time = startAndEnd[1] - startAndEnd[0];\n    const currentTime = new Date().getTime();\n    const isCustomTime = buttonTime.current ? [currentTime - time, currentTime] : startAndEnd;\n    copyResult.createTime = isCustomTime;\n    for (var key in copyResult) {\n      if (copyResult[key] === \"\" || copyResult[key] === undefined) {\n        delete copyResult[key];\n      }\n    }\n    setqueryFormObject(copyResult);\n  };\n  const handleTimeChange = (times: number[], periodOrPicker: boolean) => {\n    //periodOrPicker为true表示此时时间选择器选的是period，false表示Picker\n    if (times) {\n      setStartAndEnd(times);\n      buttonTime.current = periodOrPicker;\n    }\n  };\n  // const resetAllValue = (obj = {}) => {\n  //   setResetValue({ ...obj })\n  // }\n  const resetSubmit = (result) => {\n    setStartAndEnd([]);\n    buttonTime.current = false;\n    // if (resetValue) {\n    //   for (var i in resetValue) {\n    //     resetValue[i](undefined)\n    //   }\n    // }\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject(result);\n  };\n\n  const clientHeight = document.querySelector(\"#d1-layout-main\")?.clientHeight;\n\n  const renderTitleContent = () => {\n    return {\n      title: \"我的申请\",\n      content: null,\n    };\n  };\n\n  return (\n    <>\n      <div className=\"table-layout-style\">\n        <ProTable\n          showQueryForm={true}\n          queryFormProps={{\n            defaultCollapse: true,\n            columns: getMyApplicationQueryXForm(typeList, handleTimeChange),\n            onReset: resetSubmit,\n            onSearch: handleSubmit,\n            isResetClearAll: true,\n          }}\n          tableProps={{\n            tableId: \"my_application_table\",\n            isCustomPg: false,\n            loading,\n            rowKey: \"id\",\n            dataSource: getData(),\n            columns: getMyApplicationColumns(typeEnums),\n            customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n            reloadData,\n            isDividerHide: false,\n            attrs: {\n              scroll: {\n                x: \"max-content\",\n              },\n            },\n          }}\n        />\n      </div>\n    </>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/work-order/my-approval.tsx",
    "content": "import React, { useState, useRef } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getMyApplicationQueryXForm, getMyApplicationColumns } from \"./config\";\nimport QueryForm from \"component/dantd/query-form\";\nimport { getApprovalOrderList, getTypeEnums } from \"api/order-api\";\nimport { ITypeEnums } from \"typesPath/cluster/order-types\";\nimport { IStringMap } from \"interface/common\";\nimport { queryFormText } from \"constants/status-map\";\nimport { DTable } from \"component/dantd/dtable\";\nimport moment from \"moment\";\nimport { ProTable } from \"knowdesign\";\nimport { RenderTitle } from \"component/render-title\";\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nexport const MyApproval = connect(\n  null,\n  mapDispatchToProps\n)(() => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [queryFormObject, setqueryFormObject] = useState({ status: \"0\" });\n  const [data, setData] = useState([]);\n  const [typeList, setTypeList] = useState([] as ITypeEnums[]);\n  const [typeEnums, setTypeEnums] = useState({} as IStringMap);\n  const [startAndEnd, setStartAndEnd] = useState([]);\n  //const [resetValue, setResetValue] = useState(null);\n  const buttonTime = useRef(null);\n  React.useEffect(() => {\n    reloadData();\n  }, [department]);\n  // React.useEffect(() => {\n  //   //setResetValue初始化只会执行一次\n  //   if (resetValue) {\n  //     for (var i in resetValue) {\n  //       resetValue[i](undefined)\n  //     }\n  //   }\n  // }, [resetValue]);\n  React.useEffect(() => {\n    getTypeEnumsFn();\n  }, []);\n\n  const getTypeEnumsFn = () => {\n    getTypeEnums().then((res) => {\n      const arr = res.map((ele, index) => {\n        return {\n          ...ele,\n          value: ele.type,\n          title: ele.message,\n          key: index + 1,\n        };\n      });\n      const obj = {} as IStringMap;\n      arr.map((e: ITypeEnums) => {\n        obj[e.type] = e.message;\n      });\n      setTypeEnums(obj);\n      setTypeList(arr);\n    });\n  };\n\n  const getData = () => {\n    // 查询项的key 要与 数据源的key  对应\n    if (!queryFormObject) return data;\n    const keys = Object.keys(queryFormObject);\n    const filterData = data.filter((d) => {\n      let b = true;\n      keys.forEach((k: string) => {\n        if (k === \"createTime\") {\n          const time = moment(d[k]).unix() * 1000;\n          if (queryFormObject[k][0] > time || time > queryFormObject[k][1]) {\n            b = false;\n          }\n        } else if (k === \"type\") {\n          d[k] === queryFormObject[k] ? \"\" : (b = false);\n        } else {\n          (d[k] + \"\")?.includes(queryFormObject[k]) ? \"\" : (b = false);\n        }\n      });\n      return b;\n    });\n    return filterData;\n  };\n\n  const reloadData = () => {\n    setloading(true);\n    getApprovalOrderList(1)\n      .then((res) => {\n        if (res) {\n          setData(res);\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const handleSubmit = (result) => {\n    const copyResult = JSON.parse(JSON.stringify(result));\n    // 增加点击刷新按钮先计算时间差 保持用户选择的事件范围\n    //判断此时是否是自定义时间情况，如果是则不需要实时更新时间戳，反之不需要。\n    const time = startAndEnd[1] - startAndEnd[0];\n    const currentTime = new Date().getTime();\n    const isCustomTime = buttonTime.current ? [currentTime - time, currentTime] : startAndEnd;\n    copyResult.createTime = isCustomTime;\n    for (var key in copyResult) {\n      if (copyResult[key] === \"\" || copyResult[key] === undefined) {\n        delete copyResult[key];\n      }\n    }\n    setqueryFormObject(copyResult);\n  };\n\n  const handleTimeChange = (times: number[], periodOrPicker: boolean) => {\n    //periodOrPicker为true表示此时时间选择器选的是period，false表示Picker\n    if (times) {\n      setStartAndEnd(times);\n      buttonTime.current = periodOrPicker;\n    }\n  };\n  // const resetAllValue = (obj = {}) => {\n  //   setResetValue({ ...obj })\n  // }\n  const resetSubmit = (result) => {\n    setStartAndEnd([]);\n    buttonTime.current = false;\n    // if (resetValue) {\n    //   for (var i in resetValue) {\n    //     resetValue[i](undefined)\n    //   }\n    // }\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject(result);\n  };\n\n  const initialValues = {\n    status: [\"0\"], // 默认审批\n  };\n  const renderTitleContent = () => {\n    return {\n      title: \"我的审批\",\n      content: null,\n    };\n  };\n\n  return (\n    <div className=\"table-layout-style\">\n      <ProTable\n        showQueryForm={true}\n        queryFormProps={{\n          defaultCollapse: true,\n          columns: getMyApplicationQueryXForm(typeList, handleTimeChange),\n          // onChange={() => null}\n          onReset: resetSubmit,\n          onSearch: handleSubmit,\n          initialValues: initialValues,\n          isResetClearAll: true,\n        }}\n        tableProps={{\n          tableId: \"my_approval_table\",\n          isCustomPg: false,\n          loading,\n          rowKey: \"id\",\n          dataSource: getData(),\n          columns: getMyApplicationColumns(typeEnums, \"approval\"),\n          customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n          reloadData,\n          isDividerHide: false,\n        }}\n      />\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/container/work-order/order-detail.tsx",
    "content": "import * as React from \"react\";\nimport { getInfoRenderItem } from \"./config\";\nimport { transTimeFormat } from \"lib/utils\";\nimport Url from \"lib/url-parser\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport \"./index.less\";\nimport { PageHeader, Button, Descriptions, Steps, Divider, Tooltip, Spin, message } from \"antd\";\nimport { IOrderInfo, ITypeEnums } from \"typesPath/cluster/order-types\";\nimport { IUser } from \"typesPath/user-types\";\nimport { cancelOrder, getOrderDetail, getTypeEnums } from \"api/order-api\";\nimport { IStringMap } from \"interface/common\";\nimport { MyApprovalPermissions, MyApplyPermissions } from \"constants/permission\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { getRegionNodeSpec } from \"api/op-cluster-region-api\";\nconst { Step } = Steps;\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n  setDrawerId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setDrawerId(modalId, params, cb)),\n});\nconst connects: any = connect;\n@connects(null, mapDispatchToProps)\nexport class OrderDetail extends React.Component<{\n  setModalId: Function;\n  setDrawerId: Function;\n}> {\n  public result: boolean;\n  public orderId: number;\n\n  public state = {\n    showUnfold: false,\n    loading: false,\n    typeEnums: {} as IStringMap,\n    orderInfo: {} as IOrderInfo,\n  };\n\n  constructor(props) {\n    super(props);\n    const url = Url();\n    this.orderId = Number(url.search.orderId);\n  }\n\n  public dealInfo(info: IOrderInfo) {\n    info = JSON.parse(JSON.stringify(info));\n    const { detail = \"\", approverList = [], status } = info;\n\n    info.detailInfo = detail ? JSON.parse(detail) : {};\n    info.approvers = approverList.filter((item) => item.userName).map((item) => item.userName);\n    info.applicant = info.applicant || ({} as IUser);\n    info.currentStep = status === 0 ? 1 : status === 1 || status === 2 ? 2 : 0; // 0待审批 1已通过 2已驳回 3已撤回\n    return info;\n  }\n\n  public renderApplicant() {\n    const { applicant, createTime, applicantAppName } = this.state.orderInfo;\n    const infoList = [\n      {\n        label: \"申请人\",\n        value: applicant?.userName,\n      },\n      {\n        label: \"申请时间\",\n        value: this.formatTime(createTime),\n      },\n      {\n        label: \"应用名称\",\n        value: applicantAppName,\n      },\n    ];\n\n    return (\n      <>\n        <Divider />\n        <Descriptions title=\"申请人信息\" column={3}>\n          {infoList.map((item, key) => (\n            <Descriptions.Item key={key} label={item.label}>\n              <Tooltip placement=\"bottomLeft\" title={item.value}>\n                <span>{item.value || \"-\"}</span>\n              </Tooltip>\n            </Descriptions.Item>\n          ))}\n        </Descriptions>\n      </>\n    );\n  }\n\n  public renderDetail() {\n    const { type } = this.state.orderInfo;\n    const infoList = getInfoRenderItem(this.state.orderInfo);\n\n    return (\n      <>\n        <Divider />\n        <Descriptions title={`申请内容-${this.state.typeEnums[type] || \"\"}`} column={3}>\n          {infoList.map((item, key) => (\n            <Descriptions.Item key={key} label={item.label}>\n              <Tooltip placement=\"bottomLeft\" title={item.value}>\n                <span>{item.value || \"-\"}</span>\n              </Tooltip>\n            </Descriptions.Item>\n          ))}\n        </Descriptions>\n      </>\n    );\n  }\n\n  public formatTime(time) {\n    return <>{transTimeFormat(time)}</>;\n  }\n\n  public componentDidMount() {\n    this.getOrderDetail();\n    this.getTypeEnumsFn();\n  }\n\n  public getOrderDetail = () => {\n    this.setState({ loading: true });\n    getOrderDetail(this.orderId).then(async (data = {}) => {\n      const { type, detail } = data;\n      if (type && type === \"logicClusterIndecrease\" && detail) {\n        const details = JSON.parse(detail);\n        await getRegionNodeSpec(details.logicClusterId).then((res) => {\n          details.dataNodeSpec = res;\n          data.detail = JSON.stringify(details);\n        });\n      }\n      this.setState({\n        orderInfo: this.dealInfo(data),\n        loading: false,\n      });\n    });\n  };\n\n  public getTypeEnumsFn = () => {\n    getTypeEnums().then((res) => {\n      const obj = {} as IStringMap;\n      res.forEach((item: ITypeEnums) => {\n        obj[item.type] = item.message;\n      });\n      this.setState({\n        typeEnums: obj,\n      });\n    });\n  };\n\n  public cancelOrder(orderId: number) {\n    cancelOrder(orderId).then(() => {\n      message.success(\"撤回成功\");\n      this.getOrderDetail();\n    });\n  }\n\n  public handerUnfold = () => {\n    this.setState({\n      showUnfold: !this.state.showUnfold,\n    });\n  };\n\n  public formatApprovers = (approvers: string[], approverArr = []) => {\n    if (approvers.length > 3) {\n      approverArr.push(approvers.splice(0, 3));\n      if (approvers.length) this.formatApprovers(approvers, approverArr);\n    } else {\n      approverArr.push(approvers);\n    }\n    return approverArr;\n  };\n\n  public renderApprovers = (approvers: string[]) => {\n    const arrApprovers = this.formatApprovers([...approvers]);\n    let unfoldList = [];\n    if (arrApprovers.length > 2) unfoldList = arrApprovers.splice(2);\n\n    return (\n      <div>\n        {arrApprovers.map((item, index) => (\n          <div key={index}>{item?.join(\", \")}</div>\n        ))}\n        {this.state.showUnfold ? unfoldList.map((item, index) => <div key={index}>{item?.join(\", \")}</div>) : null}\n        {unfoldList.length ? <a onClick={this.handerUnfold}>{this.state.showUnfold ? \"收起\" : \"展开\"}</a> : \"\"}\n      </div>\n    );\n  };\n\n  public render() {\n    const isOrder = window.location.href.includes(\"my-application\");\n    const info = this.state.orderInfo;\n    this.result = info.approverList?.some((item) => item.userName === info.applicant?.userName);\n\n    return (\n      <div className=\"order-detail\">\n        <Spin spinning={this.state.loading}>\n          <div className=\"detail-top\">\n            <PageHeader\n              className=\"btn-groups\"\n              title={`${info.title}${info.id ? `（${info.id}）` : \"\"}`}\n              extra={\n                info.currentStep === 1 || this.result ? (\n                  <>\n                    {isOrder && info.status === 0 ? (\n                      <span key=\"4\">\n                        {hasOpPermission(MyApplyPermissions.PAGE, MyApplyPermissions.CALLBACK) && (\n                          <Button key=\"5\" type=\"primary\" onClick={() => this.cancelOrder(info.id)}>\n                            撤回\n                          </Button>\n                        )}\n                      </span>\n                    ) : info.status === 1 || info.status === 2 || info.status === 3 ? null : (\n                      <span key=\"3\">\n                        {hasOpPermission(MyApprovalPermissions.PAGE, MyApprovalPermissions.DNOE) && (\n                          <Button\n                            key=\"1\"\n                            type=\"primary\"\n                            className=\"detail-btn\"\n                            onClick={() => {\n                              if (info.type === \"logicClusterIndecrease\") {\n                                this.props.setDrawerId(\"showApprovalDrawer\", { ...info, outcome: \"agree\" }, this.getOrderDetail);\n                              } else {\n                                this.props.setModalId(\"showApprovalModal\", { ...info, outcome: \"agree\" }, this.getOrderDetail);\n                              }\n                            }}\n                          >\n                            通过\n                          </Button>\n                        )}\n                        {hasOpPermission(MyApprovalPermissions.PAGE, MyApprovalPermissions.CALLBACK) && (\n                          <Button\n                            key=\"2\"\n                            onClick={() =>\n                              this.props.setModalId(\"showApprovalModal\", { ...info, outcome: \"disagree\" }, this.getOrderDetail)\n                            }\n                          >\n                            驳回\n                          </Button>\n                        )}\n                      </span>\n                    )}\n                  </>\n                ) : null\n              }\n            />\n          </div>\n\n          <div className=\"work-detail-box\">\n            <Steps\n              className=\"step\"\n              current={info.currentStep}\n              status={info.currentStep === 2 && info.status === 2 ? \"error\" : \"process\"}\n              progressDot={true}\n            >\n              <Step\n                title={`${this.state.typeEnums[info.type] || \"\"}${info.status === 3 ? \"（已撤回）\" : \"\"}`}\n                subTitle={info.applicant?.userName}\n                description={this.formatTime(info.createTime)}\n              />\n              <Step title=\"待审批\" description={info.status === 0 ? this.renderApprovers(info.approvers) : null} />\n              <Step\n                title={info.status === 1 ? \"已通过\" : info.status === 2 ? \"已拒绝\" : \"完成\"}\n                // subTitle={info.currentStep === 2 ? this.renderApprovers(info.approvers) : null}\n                description={info.currentStep === 2 ? this.formatTime(info.finishTime) : null}\n              />\n            </Steps>\n\n            {this.renderApplicant()}\n\n            {info.detail ? this.renderDetail() : null}\n\n            {info.status === 1 || info.status === 2 ? (\n              <>\n                <Divider />\n                <Descriptions title=\"审批信息\" column={1}>\n                  <Descriptions.Item label=\"审批意见\">{info.opinion}</Descriptions.Item>\n                </Descriptions>\n              </>\n            ) : null}\n          </div>\n        </Spin>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/work-order/plan-speed.tsx",
    "content": "import * as React from 'react';\nimport { carryTask, getPlanSpeedColumns } from './config';\nimport { SPIT_STYLE_MAP, TASK_STATUS_TYPE_MAP } from 'constants/status-map';\nimport { tableFilter } from 'lib/utils';\nimport Url from 'lib/url-parser';\nimport './index.less';\nimport { Table, Button, Progress, Popconfirm, Tooltip, Collapse, Modal } from 'antd';\nimport { INodeTask, ITask, ITaskDetail, ITaskNodes } from 'typesPath/task-types';\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { TaskState } from \"store/type\";\nimport { cancalTask, continueTask, getTaskDetail, pauseTask } from \"api/task-api\";\nimport { Dispatch } from \"redux\";\n\nconst { Panel } = Collapse;\n\nconst mapStateToProps = (state) => ({\n  task: state.task,\n});\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nconst connects: Function = connect;\n@connects(mapStateToProps, mapDispatchToProps)\nexport class PlanSpeed extends React.Component<{ task: TaskState; setModalId?: Function }> {\n  public timer = null as any;\n\n  public state = {\n    searchKey: \"\",\n    taskDetail: null as ITaskDetail,\n    loading: false,\n    taskNodes: [] as ITaskNodes[],\n  };\n  public id: number = null;\n  public taskId: number = null;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.id = Number(url.search.id);\n    this.taskId = Number(url.search.taskid);\n  }\n\n  public getData = (origin?: any[]) => {\n    let { searchKey } = this.state;\n    searchKey = (searchKey + \"\").trim().toLowerCase();\n    const data = searchKey\n      ? origin.filter(\n        (d) => (d.id + \"\").toLowerCase().includes(searchKey as string) || d.hostname?.toLowerCase().includes(searchKey as string)\n      )\n      : origin;\n\n    return data;\n  };\n\n  public componentDidMount() {\n    this.reloadData();\n  }\n\n  public reloadData = () => {\n    this.refreshData(this.id);\n  };\n\n  public refreshData(id: number) {\n    this.getTaskDetail(id)\n      .then((data: { taskDetail: ITaskDetail; taskNodes: ITaskNodes[] }) => {\n        this.setState({\n          taskDetail: data.taskDetail,\n          taskNodes: data.taskNodes,\n          loading: false,\n        });\n      })\n      .catch(() => {\n        clearInterval(this.timer);\n      });\n    setTimeout(() => this.iTimer(id), 0);\n  }\n\n  public iTimer = (id: number) => {\n    this.timer = setInterval(() => {\n      if (this.state.taskDetail && (this.state.taskDetail?.status === 'running' || this.state.taskDetail?.status === 'unknown')) {\n        this.getTaskDetail(id, 'update').then((data: { taskDetail: ITaskDetail, taskNodes: ITaskNodes[] }) => {\n          this.setState({\n            taskDetail: data.taskDetail,\n            taskNodes: data.taskNodes,\n            loading: false\n          });\n        }).catch(() => { clearInterval(this.timer); });\n      } else { clearInterval(this.timer); }\n    }, 5 * 1 * 1000);\n  }\n\n  public getTaskDetail = (id: number, text?: string) => {\n    if (text) {\n      this.setState({ loading: false });\n    } else {\n      this.setState({ loading: true });\n    }\n    return getTaskDetail(id).then(this.setTaskDetail);\n  };\n\n  public setTaskDetail(data: ITaskDetail) {\n    const obj = data.roleNameTaskDetailMap;\n    const nodes = Object.keys(obj)\n      .sort()\n      .map((key) => key);\n    const arr = nodes.map((ele) => {\n      if (ele === \"masternode\") {\n        return {\n          header: \"master-node\",\n          data: obj?.masternode || [],\n          key: \"master\",\n        };\n      } else if (ele === \"clientnode\") {\n        return {\n          header: \"client-node\",\n          data: obj?.clientnode || [],\n          key: \"client\",\n        };\n      } else if (ele === \"datanode\") {\n        return {\n          header: \"data-node\",\n          data: obj?.datanode || [],\n          key: \"data\",\n        };\n      } else if (ele === \"coldnode\") {\n        return {\n          header: \"cold-node\",\n          data: obj?.coldnode || [],\n          key: \"cold\",\n        };\n      }\n    });\n    return {\n      taskDetail: data,\n      taskNodes: arr,\n      key: \"data\",\n    };\n  }\n\n  public getOpBtns = () => {\n    return null;\n  };\n\n  // 组件清除时清除定时器\n  public componentWillUnmount() {\n    clearInterval(this.timer);\n  }\n\n  public confirmFn = (text: string, taskId: number, id: number, fn: Function) => {\n    Modal.confirm({\n      title: `确定${text}任务${taskId}?`,\n      // icon: <DeleteOutlined style={{ color: \"red\" }} />,\n      width: 500,\n      okText: \"确定\",\n      cancelText: \"取消\",\n      onOk() {\n        fn(id)\n      },\n    });\n  }\n\n  public pauseTask = (id: number) => {\n    pauseTask(id).then(() => this.refreshData(id));\n  };\n\n  public continueTask = (id: number) => {\n    continueTask(id).then(() => this.refreshData(id));\n  };\n\n  public cancalTask = (id: number) => {\n    cancalTask(id).then(() => this.refreshData(id));\n  };\n\n  public renderInnerOperation = (): JSX.Element => {\n    return <></>;\n  };\n\n  public renderOperationPanel = (): JSX.Element => {\n    const taskObj = this.state.taskDetail;\n    let pattern = null as any;\n    SPIT_STYLE_MAP.forEach((ele, index) => {\n      if (ele.type === taskObj?.status) {\n        pattern = ele;\n      }\n    });\n    return (\n      <>\n        <div className=\"plan-speed-head\">\n          <div className=\"speed-head-left\">\n            <span className=\"head-left-top\">\n              <Progress percent={taskObj?.percent / 100} strokeColor={pattern?.color} className=\"left-top-pro\" />\n              <i className={`left-top-text ${pattern?.back}`}>{pattern?.text}</i>\n            </span>\n            <ul className=\"head-left-ul\">\n              <li>\n                <span>\n                  <div className=\"spot running\" />\n                  总数：{taskObj?.sum}\n                </span>\n                <span>\n                  <div className=\"spot success\" />\n                  成功：{taskObj?.success}\n                </span>\n                <span>\n                  <div className=\"spot failed\" />\n                  失败：{taskObj?.failed}\n                </span>\n                <span>\n                  <div className=\"spot creating\" />\n                  执行中：{taskObj?.creating}\n                </span>\n                {taskObj?.status === \"cancel\" ? (\n                  <span>\n                    <div className=\"spot waiting\" />\n                    已取消：{taskObj?.cancel}\n                  </span>\n                ) : (\n                  <span>\n                    <div className=\"spot waiting\" />\n                    待执行：{taskObj?.waiting}\n                  </span>\n                )}\n                <span>\n                  <div className=\"spot ignore\" />\n                  已忽略：{taskObj?.ignore}\n                </span>\n              </li>\n            </ul>\n          </div>\n          <div>\n            {taskObj?.status === 'waiting' &&\n              <Button type=\"primary\" className=\"mr-10 button-styles\" onClick={() => carryTask(this.id, taskObj?.orderType, this.reloadData, this.taskId)}>执行</Button>\n            }\n            {taskObj?.status === 'running' &&\n              <Button type=\"primary\" className=\"mr-10 button-styles\" onClick={() => this.confirmFn('暂停', this.taskId, this.id, this.pauseTask)}>暂停</Button>\n            }\n            {taskObj?.status === 'pause' &&\n              <Button type=\"primary\" className=\"mr-10 button-styles\" onClick={() => this.confirmFn('继续', this.taskId, this.id, this.continueTask)}>继续</Button>\n            }\n            {(taskObj?.status === 'waiting' || taskObj?.status === 'running' || taskObj?.status === 'pause' || taskObj?.status === 'failed') &&\n              <Button type=\"primary\" className=\"mr-10 button-styles\" onClick={() => this.confirmFn('取消', this.taskId, this.id, this.cancalTask)}>取消</Button>\n            }\n          </div>\n        </div>\n      </>\n    );\n  };\n\n  public getColumns(data: INodeTask[], type: string) {\n    const columns = getPlanSpeedColumns(this.props.setModalId);\n\n    const statusType = Object.assign({\n      title: \"节点状态\",\n      dataIndex: \"status\",\n      key: \"status\",\n      width: \"10%\",\n      onFilter: (value: string, record: ITask) => record.status === value,\n      filters: tableFilter<INodeTask>(data, \"status\", TASK_STATUS_TYPE_MAP),\n      render: (text: any) => {\n        return (\n          <Tooltip placement=\"bottomLeft\" title={TASK_STATUS_TYPE_MAP[text]}>\n            {TASK_STATUS_TYPE_MAP[text]}\n          </Tooltip>\n        );\n      },\n    });\n\n    columns.splice(3, 0, statusType);\n    return columns;\n  }\n\n  public renderNodeTable = (data: INodeTask[], type: string) => {\n    return (\n      <>\n        <Table rowKey=\"id\" loading={this.state.loading} dataSource={this.getData(data)} columns={this.getColumns(data, type)} />\n      </>\n    );\n  };\n\n  public renderTable = () => {\n    return (\n      <>\n        <Collapse bordered={false} defaultActiveKey={this.state.taskNodes?.map((row) => row.key)}>\n          {this.state.taskNodes?.map((item) => {\n            return (\n              <Panel header={item.header} key={item.key}>\n                {this.renderNodeTable(item.data, item.key)}\n              </Panel>\n            );\n          })}\n        </Collapse>\n      </>\n    );\n  };\n\n  public render() {\n    return (\n      <>\n        {this.renderOperationPanel()}\n        <div className=\"table-wrapper no-padding\">{this.state.taskNodes?.length ? this.renderTable() : \"\"}</div>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/work-order/task-detail.tsx",
    "content": "import * as React from \"react\";\nimport { InfoItem } from \"component/info-item\";\nimport { TASK_MENU_MAP, TASK_TAB_LIST, DESC_LIST } from \"./config\";\nimport Url from \"lib/url-parser\";\nimport { DcdrPlanSpeed } from \"./dcdr-plan-speed\";\nimport \"./index.less\";\nimport { PageHeader, Tag } from \"antd\";\nimport { Menu } from \"knowdesign\";\nimport { IDcdrStepDetailInfo } from \"typesPath/task-types\";\nimport { DCDR_TASK_STATUS_TYPE_MAP } from \"constants/status-map\";\nimport { connect } from \"react-redux\";\nimport * as actions from \"actions\";\nimport { TaskState } from \"store/type\";\nimport { getTaskBaseInfo } from \"api/task-api\";\n\nconst mapStateToProps = (state) => ({\n  task: state.task,\n});\n\nconst connects: Function = connect;\n@connects(mapStateToProps)\nexport class TaskDetail extends React.Component<{\n  dispatch: any;\n  task: TaskState;\n}> {\n  public id: number;\n  public taskType: number;\n  public index: number;\n  public dcdrInfo: IDcdrStepDetailInfo;\n  public status: string;\n\n  constructor(props: any) {\n    super(props);\n    const url = Url();\n    this.id = Number(url.search.id);\n    this.taskType = Number(url.search.type);\n    this.status = url.search.status;\n    if (this.taskType === 10) {\n      const str = decodeURI(url.search?.dcdr_info);\n      this.dcdrInfo = JSON.parse(str || \"{}\") as IDcdrStepDetailInfo;\n      this.props.dispatch(actions.setDcdrStepDetail(this.dcdrInfo));\n    } else {\n      this.props.dispatch(actions.setTaskBaseLoading(true));\n      getTaskBaseInfo(this.id).then((res) => {\n        this.props.dispatch(actions.setTaskBaseInfo(res));\n        this.props.dispatch(actions.setTaskBaseLoading(false));\n      });\n    }\n    this.judgeHashValue();\n    window.addEventListener(\"hashchange\", () => {\n      this.props.dispatch(actions.setTaskMenu());\n    });\n  }\n\n  public componentDidMount() {\n    //\n  }\n\n  public judgeHashValue = () => {\n    const { task } = this.props;\n    const menu = task.menu;\n    const currHash = window.location.hash;\n\n    if (currHash !== menu) {\n      this.props.dispatch(actions.setTaskMenu());\n    }\n  };\n\n  public renderContent = () => {\n    const { task } = this.props;\n    const currentHash = window.location.hash.replace(\"#\", \"\") || \"base\";\n    const menu = task.menu !== currentHash ? currentHash : task.menu;\n    return TASK_MENU_MAP.get(menu)?.content;\n  };\n\n  public renderPageHeader() {\n    // 1：执行中 2：执行成功 3：执行失败\n    const tagArr = [\n      {\n        color: \"blue\",\n        text: \"执行中\",\n      },\n      {\n        color: \"green\",\n        text: \"成功\",\n      },\n      {\n        color: \"red\",\n        text: \"失败\",\n      },\n    ];\n    let status = 0;\n    switch (this.status) {\n      case DCDR_TASK_STATUS_TYPE_MAP[0]:\n        status = 1;\n        break;\n      case DCDR_TASK_STATUS_TYPE_MAP[1]:\n        status = 3;\n        break;\n      case DCDR_TASK_STATUS_TYPE_MAP[2]:\n        status = 0;\n        break;\n      default:\n        return;\n    }\n    const { task } = this.props;\n    return (\n      <PageHeader\n        className=\"detail-header\"\n        backIcon={false}\n        tags={<Tag color={tagArr[status].color}>{tagArr[status].text}</Tag>}\n        title={task.dcdrStepDetail.logicTemplateName + \"主从切换\"}\n      >\n        {DESC_LIST.map((row, index) => (\n          <InfoItem\n            key={index}\n            label={row.label}\n            value={row.render ? row.render(task.dcdrStepDetail?.[row.key]) : `${task.dcdrStepDetail?.[row.key] || \"\"}`}\n            width={250}\n          />\n        ))}\n      </PageHeader>\n    );\n  }\n\n  public render() {\n    const { task } = this.props;\n    return (\n      <>\n        {this.taskType !== 10 ? (\n          <div className=\"hash-menu-container menu-container task-detail\">\n            <Menu selectedKeys={[task.menu]} mode=\"horizontal\" onClick={(e: any) => (window.location.hash = e.key)}>\n              {TASK_TAB_LIST.map((d) => (\n                <Menu.Item key={d.key}>{d.name}</Menu.Item>\n              ))}\n            </Menu>\n          </div>\n        ) : (\n          this.renderPageHeader()\n        )}\n        <div className=\"detail-wrapper task-detail-wrapper\">{this.taskType !== 10 ? this.renderContent() : <DcdrPlanSpeed />}</div>\n      </>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/container/work-order/task.tsx",
    "content": "import React, { useEffect, useState, useRef } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Dispatch } from \"redux\";\nimport * as actions from \"actions\";\nimport { getTaskQueryXForm, getTaskColumns } from \"./config\";\nimport QueryForm from \"component/dantd/query-form\";\nimport { getTaskList } from \"api/task-api\";\nimport { ITask } from \"typesPath/task-types\";\nimport moment from \"moment\";\nimport { ProTable } from \"knowdesign\";\nimport { RenderTitle } from \"component/render-title\";\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n  setModalId: (modalId: string, params?: any, cb?: Function) => dispatch(actions.setModalId(modalId, params, cb)),\n});\n\nexport const TaskList = connect(\n  null,\n  mapDispatchToProps\n)(() => {\n  const department: string = localStorage.getItem(\"current-project\");\n  const [loading, setloading] = useState(false);\n  const [data, setData] = useState([] as ITask[]);\n  const [startAndEnd, setStartAndEnd] = useState([]);\n  const [queryFormObject, setqueryFormObject]: any = useState({ current: 1, size: 10 });\n  const [total, setTotal] = useState(0);\n  const buttonTime = useRef(null);\n\n  useEffect(() => {\n    reloadData();\n  }, [department, queryFormObject]);\n\n  const reloadData = () => {\n    setloading(true);\n    const params = {\n      page: queryFormObject.current,\n      size: queryFormObject.size,\n      startTime: startAndEnd.length ? startAndEnd[0] : undefined,\n      endTime: startAndEnd.length ? startAndEnd[1] : undefined,\n      title: queryFormObject.title,\n      sortTerm: queryFormObject.sortTerm,\n      orderByDesc: queryFormObject.orderByDesc,\n    };\n    getTaskList(params)\n      .then((res) => {\n        if (res) {\n          res.bizData =\n            (res?.bizData || []).map((ele, index) => {\n              return {\n                ...ele,\n                key: index,\n              };\n            }) || [];\n          setData(res?.bizData);\n          setTotal(res?.pagination?.total);\n        }\n      })\n      .finally(() => {\n        setloading(false);\n      });\n  };\n\n  const handleSubmit = (result) => {\n    const copyResult = JSON.parse(JSON.stringify(result));\n    // 增加点击刷新按钮先计算时间差 保持用户选择的事件范围\n    // 判断此时是否是自定义时间情况，如果是则不需要实时更新时间戳，反之不需要。\n    const time = startAndEnd[1] - startAndEnd[0];\n    const currentTime = new Date().getTime();\n    const isCustomTime = buttonTime.current ? [currentTime - time, currentTime] : startAndEnd;\n    copyResult.createTime = isCustomTime;\n    for (var key in copyResult) {\n      if (copyResult[key] === \"\" || copyResult[key] == undefined) {\n        delete copyResult[key];\n      }\n    }\n    setqueryFormObject({ ...copyResult, size: queryFormObject.size, current: 1 });\n  };\n\n  const resetSubmit = (result) => {\n    setStartAndEnd([]);\n    buttonTime.current = false;\n    for (var key in result) {\n      if (result[key] === \"\" || result[key] === undefined) {\n        delete result[key];\n      }\n    }\n    setqueryFormObject(result);\n  };\n  const handleTimeChange = (times: number[], periodOrPicker: boolean) => {\n    //periodOrPicker为true表示此时时间选择器选的是period，false表示Picker\n    if (times) {\n      setStartAndEnd(times);\n      buttonTime.current = periodOrPicker;\n    }\n  };\n\n  const handleChange = (pagination, filters, sorter) => {\n    const sorterObject: { [key: string]: any } = {};\n    // 排序\n    if (sorter.columnKey && sorter.order) {\n      switch (sorter.columnKey) {\n        case \"createTime\":\n          sorterObject.sortTerm = \"create_time\";\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n        case \"updateTime\":\n          sorterObject.sortTerm = \"update_time\";\n          sorterObject.orderByDesc = sorter.order === \"ascend\" ? false : true;\n          break;\n        default:\n          break;\n      }\n    }\n    setqueryFormObject((state) => {\n      if (!sorter.order) {\n        delete state.sortTerm;\n        delete state.orderByDesc;\n      }\n      return {\n        ...state,\n        ...sorterObject,\n        current: pagination.current,\n        size: pagination.pageSize,\n      };\n    });\n  };\n\n  const renderTitleContent = () => {\n    return {\n      title: \"任务中心\",\n      content: null,\n    };\n  };\n\n  return (\n    <div className=\"table-layout-style\">\n      <ProTable\n        showQueryForm={true}\n        queryFormProps={{\n          defaultCollapse: true,\n          columns: getTaskQueryXForm(handleTimeChange),\n          // onChange={() => null}\n          onReset: resetSubmit,\n          onSearch: handleSubmit,\n          // initialValues={{}}\n          isResetClearAll: true,\n        }}\n        tableProps={{\n          tableId: \"work_order_table\",\n          isCustomPg: false,\n          loading,\n          rowKey: \"id\",\n          dataSource: data,\n          columns: getTaskColumns(reloadData),\n          reloadData,\n          isDividerHide: false,\n          customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n          paginationProps: {\n            position: \"bottomRight\",\n            showQuickJumper: true,\n            total: total,\n            showSizeChanger: true,\n            pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n            showTotal: (total: number) => `共 ${total} 条`,\n            current: queryFormObject.current,\n          },\n          attrs: {\n            onChange: handleChange,\n            scroll: {\n              x: \"max-content\",\n            },\n          },\n        }}\n      />\n    </div>\n  );\n});\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonComponents/ProgressBar/NProgress.js",
    "content": "function clamp(n, min, max) {\n  if (n < min) return min;\n  if (n > max) return max;\n  return n;\n}\n\nfunction toBarPerc(n) {\n  return (-1 + n) * 100;\n}\n\nlet queue = (function () {\n  let pending = [];\n\n  function next() {\n    let fn = pending.shift();\n    if (fn) {\n      fn(next);\n    }\n  }\n\n  return function (fn) {\n    pending.push(fn);\n    if (pending.length == 1) next();\n  };\n})();\n\nlet css = (function () {\n  let cssPrefixes = [\"Webkit\", \"O\", \"Moz\", \"ms\"],\n    cssProps = {};\n\n  function camelCase(string) {\n    return string.replace(/^-ms-/, \"ms-\").replace(/-([\\da-z])/gi, function (match, letter) {\n      return letter.toUpperCase();\n    });\n  }\n\n  function getVendorProp(name) {\n    let style = document.body.style;\n    if (name in style) return name;\n\n    let i = cssPrefixes.length,\n      capName = name.charAt(0).toUpperCase() + name.slice(1),\n      vendorName;\n    while (i--) {\n      vendorName = cssPrefixes[i] + capName;\n      if (vendorName in style) return vendorName;\n    }\n\n    return name\n  }\n\n  function getStyleProp(name) {\n    name = camelCase(name);\n    return cssProps[name] || (cssProps[name] = getVendorProp(name));\n  }\n\n  function applyCss(element, prop, value) {\n    prop = getStyleProp(prop);\n    element.style[prop] = value;\n  }\n\n  return function (element, properties) {\n    let args = arguments,\n      prop,\n      value;\n\n    if (args.length == 2) {\n      for (prop in properties) {\n        value = properties[prop];\n        if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);\n      }\n    } else {\n      applyCss(element, args[1], args[2]);\n    }\n  };\n})();\n\nfunction hasClass(element, name) {\n  let list = typeof element == \"string\" ? element : classList(element);\n  return list.indexOf(\" \" + name + \" \") >= 0;\n}\n\nfunction addClass(element, name) {\n  let oldList = classList(element),\n    newList = oldList + name;\n\n  if (hasClass(oldList, name)) return;\n\n  // Trim the opening space.\n  element.className = newList.substring(1);\n}\n\nfunction removeClass(element, name) {\n  let oldList = classList(element),\n    newList;\n\n  if (!hasClass(element, name)) return;\n\n  // Replace the class name.\n  newList = oldList.replace(\" \" + name + \" \", \" \");\n\n  // Trim the opening and closing spaces.\n  element.className = newList.substring(1, newList.length - 1);\n}\n\nfunction classList(element) {\n  return (\" \" + (element.className || \"\") + \" \").replace(/\\s+/gi, \" \");\n}\n\nfunction removeElement(element) {\n  element && element.parentNode && element.parentNode.removeChild(element);\n}\n\nclass NProgress {\n  constructor(settings) {\n    this.status = null;\n    this.settings = settings || {\n      minimum: 0.08,\n      easing: \"ease\",\n      positionUsing: \"\",\n      speed: 200,\n      trickle: true,\n      trickleRate: 0.02,\n      trickleSpeed: 800,\n      showSpinner: true,\n      barSelector: '[role=\"bar\"]',\n      spinnerSelector: '[role=\"spinner\"]',\n      parent: \"body\",\n      template:\n        '<div class=\"bar\" role=\"bar\"><div class=\"peg\"></div></div><div class=\"spinner\" role=\"spinner\"><div class=\"spinner-icon\"></div></div>',\n    };\n  }\n\n  configure(options) {\n    let key, value;\n    for (key in options) {\n      value = options[key];\n      if (value !== undefined && options.hasOwnProperty(key)) this.settings[key] = value;\n    }\n\n    return this;\n  }\n  set(n) {\n    let started = this.isStarted();\n\n    n = clamp(n, this.settings.minimum, 1);\n    this.status = n === 1 ? null : n;\n\n    let progress = this.render(!started),\n      bar = progress.querySelector(this.settings.barSelector),\n      speed = this.settings.speed,\n      ease = this.settings.easing;\n    progress.offsetWidth;\n    let self = this;\n    queue(function (next) {\n      // this.set positionUsing if it hasn't already been this.set\n      if (self.settings.positionUsing === \"\") self.settings.positionUsing = self.getPositioningCSS();\n\n      // Add transition\n      css(bar, self.barPositionCSS(n, speed, ease));\n\n      if (n === 1) {\n        // Fade out\n        css(progress, {\n          transition: \"none\",\n          opacity: 1,\n        });\n        progress.offsetWidth; /* Repaint */\n\n        setTimeout(function () {\n          css(progress, {\n            transition: \"all \" + speed + \"ms linear\",\n            opacity: 0,\n          });\n          setTimeout(function () {\n            self.remove();\n            next();\n          }, speed);\n        }, speed);\n      } else {\n        setTimeout(next, speed);\n      }\n    });\n\n    return this;\n  }\n\n  isStarted() {\n    return typeof this.status === \"number\";\n  }\n\n  start() {\n    let self = this;\n    if (!self.status) self.set(0);\n\n    let work = function () {\n      setTimeout(function () {\n        if (!self.status) return;\n        self.trickle();\n        work();\n      }, self.settings.trickleSpeed);\n    };\n\n    if (self.settings.trickle) work();\n\n    return self;\n  }\n\n  done(force) {\n    if (!force && !this.status) return this;\n\n    return this.inc(0.3 + 0.5 * Math.random()).set(1);\n  }\n\n  inc(amount) {\n    let n = this.status;\n\n    if (!n) {\n      return this.start();\n    } else {\n      if (typeof amount !== \"number\") {\n        amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);\n      }\n\n      n = clamp(n + amount, 0, 0.994);\n      return this.set(n);\n    }\n  }\n\n  trickle() {\n    return this.inc(Math.random() * this.settings.trickleRate);\n  }\n\n  render(fromStart) {\n    if (this.isRendered()) return document.getElementById(\"nprogress\");\n\n    addClass(document.documentElement, \"this-busy\");\n\n    let progress = document.createElement(\"div\");\n    progress.id = \"nprogress\";\n    progress.innerHTML = this.settings.template;\n\n    let bar = progress.querySelector(this.settings.barSelector),\n      perc = fromStart ? \"-100\" : toBarPerc(this.status || 0),\n      parent = document.querySelector(this.settings.parent),\n      spinner;\n\n    css(bar, {\n      transition: \"all 0 linear\",\n      transform: \"translate3d(\" + perc + \"%,0,0)\",\n    });\n\n    if (!this.settings.showSpinner) {\n      spinner = progress.querySelector(this.settings.spinnerSelector);\n      spinner && removeElement(spinner);\n    }\n\n    if (parent != document.body) {\n      addClass(parent, \"this-custom-parent\");\n    }\n\n    parent.appendChild(progress);\n    return progress;\n  }\n\n  remove() {\n    removeClass(document.documentElement, \"this-busy\");\n    removeClass(document.querySelector(this.settings.parent), \"this-custom-parent\");\n    let progress = document.getElementById(\"nprogress\");\n    progress && removeElement(progress);\n  }\n  isRendered() {\n    return !!document.getElementById(\"nprogress\");\n  }\n  getPositioningCSS() {\n    // Sniff on document.body.style\n    let bodyStyle = document.body.style;\n\n    // Sniff prefixes\n    let vendorPrefix =\n      \"WebkitTransform\" in bodyStyle\n        ? \"Webkit\"\n        : \"MozTransform\" in bodyStyle\n        ? \"Moz\"\n        : \"msTransform\" in bodyStyle\n        ? \"ms\"\n        : \"OTransform\" in bodyStyle\n        ? \"O\"\n        : \"\";\n\n    if (vendorPrefix + \"Perspective\" in bodyStyle) {\n      // Modern browsers with 3D support, e.g. Webkit, IE10\n      return \"translate3d\";\n    } else if (vendorPrefix + \"Transform\" in bodyStyle) {\n      // Browsers without 3D support, e.g. IE9\n      return \"translate\";\n    } else {\n      // Browsers without translate() support, e.g. IE7-8\n      return \"margin\";\n    }\n  }\n  barPositionCSS(n, speed, ease) {\n    let barCSS;\n    if (this.settings.positionUsing === \"translate3d\") {\n      barCSS = { transform: \"translate3d(\" + toBarPerc(n) + \"%,0,0)\" };\n    } else if (this.settings.positionUsing === \"translate\") {\n      barCSS = { transform: \"translate(\" + toBarPerc(n) + \"%,0)\" };\n    } else {\n      barCSS = { \"margin-left\": toBarPerc(n) + \"%\" };\n    }\n\n    barCSS.transition = \"all \" + speed + \"ms \" + ease;\n\n    return barCSS;\n  }\n}\n\nexport default NProgress;\n "
  },
  {
    "path": "arius-console/src/d1-packages/CommonComponents/ProgressBar/index.less",
    "content": "/* Make clicks pass-through */\n#nprogress {\n  pointer-events: none;\n}\n\n#nprogress .bar {\n  background: #fff;\n\n  position: fixed;\n  z-index: 1031;\n  top: 0;\n  left: 0;\n\n  width: 100%;\n  height: 2px;\n}\n\n/* Fancy blur effect */\n#nprogress .peg {\n  display: block;\n  position: absolute;\n  right: 0px;\n  width: 100px;\n  height: 100%;\n  box-shadow: 0 0 10px #29d, 0 0 5px #29d;\n  opacity: 1;\n\n  -webkit-transform: rotate(3deg) translate(0px, -4px);\n  -ms-transform: rotate(3deg) translate(0px, -4px);\n  transform: rotate(3deg) translate(0px, -4px);\n}\n\n/* Remove these to get rid of the spinner */\n#nprogress .spinner {\n  display: none;\n  position: fixed;\n  z-index: 1031;\n  top: 15px;\n  right: 15px;\n}\n\n#nprogress .spinner-icon {\n  width: 18px;\n  height: 18px;\n  box-sizing: border-box;\n\n  border: solid 2px transparent;\n  border-top-color: #29d;\n  border-left-color: #29d;\n  border-radius: 50%;\n\n  -webkit-animation: nprogress-spinner 400ms linear infinite;\n  animation: nprogress-spinner 400ms linear infinite;\n}\n\n.nprogress-custom-parent {\n  overflow: hidden;\n  position: relative;\n}\n\n.nprogress-custom-parent #nprogress .spinner,\n.nprogress-custom-parent #nprogress .bar {\n  position: absolute;\n}\n\n@-webkit-keyframes nprogress-spinner {\n  0% {\n    -webkit-transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(360deg);\n  }\n}\n@keyframes nprogress-spinner {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonComponents/ProgressBar/index.ts",
    "content": "import NProgress from \"./NProgress\";\nimport \"./index.less\";\nconst SingleWrapper = (fn: any) => {\n  let instance: any;\n  return function (config: any) {\n    if (!instance) {\n      instance = new fn(config);\n    }\n    return instance;\n  };\n};\nconst singleProgress = SingleWrapper(NProgress);\nconst Progress =(function ProgressBar(props?: any) {\n  return singleProgress(props);\n})()\n\nexport default Progress;\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Exception/Page401/index.tsx",
    "content": "import React from 'react';\nimport '../style.less';\n\nconst Page401 = () => {\n  return (\n    <div className=\"response-tpl-page\">\n      <div className=\"response-tpl-page-content p-401\">\n        <div className=\"response-tpl-page-content-operate\">\n          <h3 className=\"response-tpl-page-content-operate-message-sorry\">很抱歉，您暂时没有权限访问该页面～</h3>\n          <div className=\"response-tpl-page-content-operate-message-tip\">请联系管理员开通权限进行访问</div>\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default Page401;\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Exception/Page403/index.tsx",
    "content": "import React from 'react';\nimport { RouteComponentProps } from 'react-router-dom';\nimport '../style.less';\n\nconst Page403 = (props) => {\n  return (\n    <div className=\"response-tpl-page\">\n      <div className=\"response-tpl-page-content p-403\">\n        <div className=\"response-tpl-page-content-operate\">\n          <h3 className=\"response-tpl-page-content-operate-message-sorry\">\n            抱歉，您没有权限访问该页面\n          </h3>\n          {/* <div\n            className=\"response-tpl-page-content-operate-message-btn\"\n            onClick={() => {\n              props.history.push({\n                pathname: \"/\",\n              });\n            }}\n          >\n            返回首页\n          </div> */}\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default Page403;\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Exception/Page404/index.tsx",
    "content": "import React from 'react';\nimport { RouteComponentProps } from 'react-router-dom';\nimport '../style.less';\n\nconst Page404: React.FC<RouteComponentProps> = (props) => {\n  const { history } = props;\n  return (\n    <div className=\"response-tpl-page\">\n      <div className=\"response-tpl-page-content p-404\">\n        <div className=\"response-tpl-page-content-operate\">\n          <h3 className=\"response-tpl-page-content-operate-message-sorry\">很抱歉，页面走丢了～</h3>\n          <div className=\"response-tpl-page-content-operate-message-tip\">\n            请检查页面地址是否正确，或刷新页面\n            {/* <div\n              className=\"response-tpl-page-content-operate-message-btn\"\n              onClick={() => {\n                history.push({\n                  pathname: \"/\",\n                });\n              }}\n            >\n              返回首页\n            </div> */}\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default Page404;\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Exception/Page500/index.tsx",
    "content": "import React from 'react';\nimport '../style.less';\n\nconst Page500 = () => {\n  return (\n    <div className=\"response-tpl-page\">\n      <div className=\"response-tpl-page-content p-500\">\n        <div className=\"response-tpl-page-content-operate\">\n          <h3 className=\"response-tpl-page-content-operate-message-sorry\">抱歉，服务器开小差儿了～</h3>\n          <div className=\"response-tpl-page-content-operate-message-tip\">请刷新页面或稍后进行重试</div>\n        </div>\n      </div>\n    </div>\n  );\n};\n\nexport default Page500;\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Exception/index.tsx",
    "content": "import Page500 from './Page500/index';\nimport Page404 from './Page404/index';\nimport Page403 from './Page403/index';\nimport Page401 from './Page401/index';\n\nexport {\n  Page500,\n  Page404,\n  Page403,\n  Page401\n}"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Exception/style.less",
    "content": ".response-tpl-page {\n  &-content {\n    // background: url('./assets/@{status}.png') no-repeat center;\n    width: 100%;\n    height: calc(75vh);\n\n    &.p-403 {\n      background: url('./assets/403.png') no-repeat center;\n    }\n\n    &.p-401 {\n      background: url('./assets/401.png') no-repeat center;\n    }\n\n    &.p-404 {\n      background: url('./assets/404.png') no-repeat center;\n    }\n\n    &.p-500 {\n      background: url('./assets/500.png') no-repeat center;\n    }\n\n    &-operate {\n      position: relative;\n      top: calc(65%);\n\n      &-message-sorry {\n        font-size: 20px;\n        color: #505568;\n        text-align: center;\n        // > span {\n        //   color: #526ecc;\n        //   text-decoration: underline;\n        //   cursor: pointer;\n        // }\n      }\n\n      &-message-tip {\n        font-size: 16px;\n        color: #A8ADBD;\n        text-align: center;\n      }\n\n      &-message-btn {\n        color: #526ecc;\n        text-decoration: underline;\n        cursor: pointer;\n        text-align: center;\n      }\n    }\n  }\n}"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Login/LoginForm.tsx",
    "content": "import React from \"react\";\nimport { Form, Button, Row, message } from \"knowdesign\";\nimport { FormMap, renderFormItem } from \"./config\";\nimport { userLogin } from \"api/logi-security\";\nimport { encryptAES } from \"./crypto\";\nimport { Utils } from \"knowdesign\";\nconst setCookie = Utils.setCookie;\nimport { useGlobalLoginStatus } from \"../../../store\";\nimport { judgeAdminUser } from \"api/user-api\";\n\nexport const LoginForm: React.FC<any> = (props: any) => {\n  const [form] = Form.useForm();\n  const [loginStatus, setLoginStatus] = useGlobalLoginStatus();\n\n  const handleSubmit = async (e: { userName: string; password: string }) => {\n    try {\n      const res = await userLogin({\n        pw: encryptAES(e.password),\n        userName: e.userName,\n      });\n      localStorage.setItem(\"current-project\", JSON.stringify({})); //清空原有项目数据\n      setCookie([\n        { key: \"userName\", value: res.userName },\n        { key: \"userId\", value: res.id },\n      ]);\n      message.success(\"登录成功\");\n\n      judgeAdminUser()\n        .then((res) => {\n          setCookie([{ key: \"isAdminUser\", value: res.code === 0 ? \"yes\" : \"no\" }]);\n          props.fn(res.code === 0);\n        })\n        .finally(() => {\n          setLoginStatus(!loginStatus);\n        });\n    } catch (err) {\n      // do nothing\n    }\n  };\n\n  return (\n    <>\n      <Form name=\"normal_login\" form={form} className=\"login-form\" onFinish={handleSubmit} layout={\"vertical\"}>\n        {FormMap.map((formItem) => {\n          return (\n            <Row key={formItem.key}>\n              <Form.Item key={formItem.key} name={formItem.key} label={formItem.label} rules={formItem.rules} style={{ width: \"100%\" }}>\n                {renderFormItem(formItem)}\n              </Form.Item>\n            </Row>\n          );\n        })}\n        <Form.Item key={\"submit\"}>\n          <Row>\n            <Button style={{ width: \"100%\", height: 56 }} type=\"primary\" htmlType=\"submit\">\n              登录\n            </Button>\n          </Row>\n        </Form.Item>\n      </Form>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Login/RegisterForm.tsx",
    "content": "import React from \"react\";\nimport { Form, Button, Input, Row, Tooltip, message } from \"knowdesign\";\nimport { RegisterFormMap, renderFormItem } from \"./config\";\nimport { CheckCircleOutlined, CloseCircleOutlined } from \"@ant-design/icons\";\nimport { userRegister } from \"api/logi-security\";\nimport { encryptAES } from \"./crypto\";\n\nconst redTip = \"#EF645C\";\nconst greenTip = \"#46D677\";\nconst grayTip = \"#A8ADBD\";\n\nexport const RegisterForm: React.FC<any> = (props: { fn: (t: string) => any }) => {\n  const [userNameCheckColorlength, setUserNameCheckColorlength] = React.useState(grayTip);\n  const [userNameCheckColorReg, setUserNameCheckColorReg] = React.useState(grayTip);\n  const [userNameCheckRepeat, setUserNameCheckRepeat] = React.useState(grayTip);\n  const [passwordCheckColorlength, setPasswordCheckColorlength] = React.useState(grayTip);\n  const [passwordCheckColorReg, setPCheckColorReg] = React.useState(grayTip);\n  const [form] = Form.useForm();\n\n  React.useEffect(() => {\n    //\n  }, []);\n\n  const handleSubmit = async (e: any) => {\n    const userName = typeof e.userName === \"object\" ? e.userName.value : e.userName;\n    const email = typeof e.mailbox === \"object\" ? e.mailbox.value : e.mailbox;\n    const phone = typeof e.phone === \"object\" ? e.phone.value : e.phone;\n    const req = {\n      userName,\n      pw: e.password,\n      realName: e.realName,\n      email,\n      phone,\n    };\n    userRegister(req)\n      .then(() => {\n        message.success(\"注册成功\");\n        props.fn(\"login\");\n      })\n      .catch(() => {\n        message.error(\"注册失败\");\n      });\n  };\n\n  const renderTip = (key: string) => {\n    let ele = null;\n    if (key === \"userName\") {\n      ele = (\n        <>\n          <div>\n            {userNameCheckColorlength !== redTip ? (\n              <CheckCircleOutlined style={{ color: userNameCheckColorlength }} />\n            ) : (\n              <CloseCircleOutlined style={{ color: userNameCheckColorlength }} />\n            )}\n            &nbsp;长度为5-50个字符\n          </div>\n          <div>\n            {userNameCheckColorReg !== redTip ? (\n              <CheckCircleOutlined style={{ color: userNameCheckColorReg }} />\n            ) : (\n              <CloseCircleOutlined style={{ color: userNameCheckColorReg }} />\n            )}\n            &nbsp;支持英文字母、数字、下划线\n          </div>\n          <div>\n            {userNameCheckRepeat !== redTip ? (\n              <CheckCircleOutlined style={{ color: userNameCheckRepeat }} />\n            ) : (\n              <CloseCircleOutlined style={{ color: userNameCheckRepeat }} />\n            )}\n            &nbsp;账号不可重复\n          </div>\n        </>\n      );\n    } else {\n      ele = (\n        <>\n          <div>\n            {passwordCheckColorlength !== redTip ? (\n              <CheckCircleOutlined style={{ color: passwordCheckColorlength }} />\n            ) : (\n              <CloseCircleOutlined style={{ color: passwordCheckColorlength }} />\n            )}\n            &nbsp;6-20个字符\n          </div>\n          <div>\n            {passwordCheckColorReg !== redTip ? (\n              <CheckCircleOutlined style={{ color: passwordCheckColorReg }} />\n            ) : (\n              <CloseCircleOutlined style={{ color: passwordCheckColorReg }} />\n            )}\n            &nbsp;英文字母、数字、标点符号（除空格）\n          </div>\n        </>\n      );\n    }\n    return ele;\n  };\n\n  const onValuesChange = (value, allValue) => {\n    Object.keys(value).forEach((key) => {\n      switch (key) {\n        case \"userName\":\n          checkUserName(value[key]);\n          break;\n        case \"password\":\n          checkUserPassword(value[key]);\n          break;\n        default:\n          break;\n      }\n    });\n  };\n\n  const checkUserName = (value) => {\n    if (!value) {\n      setUserNameCheckColorlength(redTip);\n      setUserNameCheckColorReg(redTip);\n      setUserNameCheckRepeat(redTip);\n      return;\n    }\n    const isRed = typeof value === \"string\" || value === \"-9999\";\n    const _value = typeof value === \"string\" ? value : value.value;\n\n    const flat_5_50 = _value && _value.length > 4 && _value.length <= 50;\n    const reg = /^[0-9a-zA-Z_]{1,}$/;\n    const flat = reg.test(_value);\n    setUserNameCheckColorlength(flat_5_50 ? greenTip : redTip);\n    setUserNameCheckColorReg(flat ? greenTip : redTip);\n    setUserNameCheckRepeat(isRed ? redTip : greenTip);\n  };\n\n  const checkUserPassword = (value) => {\n    if (!value) return;\n    const flat_6_20 = value && value.length > 5 && value.length <= 20;\n    const reg = /^[a-zA-Z0-9\\_-]*$/;\n    const flat = reg.test(value);\n    if (flat_6_20 && passwordCheckColorlength !== greenTip) {\n      setPasswordCheckColorlength(greenTip);\n    } else if (!flat_6_20 && passwordCheckColorlength !== redTip) {\n      setPasswordCheckColorlength(redTip);\n    }\n    if (flat && passwordCheckColorReg !== greenTip) {\n      setPCheckColorReg(greenTip);\n    } else if (!flat && passwordCheckColorReg !== redTip) {\n      setPCheckColorReg(redTip);\n    }\n  };\n\n  return (\n    <>\n      <Form\n        name=\"normal_login\"\n        form={form}\n        className=\"login-form\"\n        onFinish={handleSubmit}\n        layout={\"vertical\"}\n        onValuesChange={onValuesChange}\n      >\n        {RegisterFormMap.map((formItem) => {\n          return formItem.key === \"userName\" || formItem.key === \"password\" ? (\n            <Tooltip\n              key={formItem.key}\n              color=\"#fff\"\n              overlayClassName=\"custom-login-style\"\n              placement=\"right\"\n              title={renderTip(formItem.key)}\n            >\n              <Row key={formItem.key}>\n                <Form.Item key={formItem.key} name={formItem.key} label={formItem.label} rules={formItem.rules} style={{ width: \"100%\" }}>\n                  {renderFormItem(formItem)}\n                </Form.Item>\n              </Row>\n            </Tooltip>\n          ) : (\n            <Row key={formItem.key}>\n              <Form.Item key={formItem.key} name={formItem.key} label={formItem.label} rules={formItem.rules} style={{ width: \"100%\" }}>\n                {renderFormItem(formItem)}\n              </Form.Item>\n            </Row>\n          );\n        })}\n        <Form.Item key={\"submit\"}>\n          <Row>\n            <Button className=\"submit-btn\" type=\"primary\" htmlType=\"submit\">\n              立即注册\n            </Button>\n          </Row>\n        </Form.Item>\n      </Form>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Login/config.tsx",
    "content": "import { IMenuItem } from \"interface/common\";\nimport { LoginForm } from \"./LoginForm\";\nimport React from \"react\";\nimport { CloseCircleFilled, LockOutlined, UserOutlined } from \"@ant-design/icons\";\nimport { RegisterForm } from \"./RegisterForm\";\nimport { Input, InputNumber } from \"knowdesign\";\nimport { checkRegisterUser } from \"api/logi-security\";\nimport { regUserPassword } from \"constants/reg\";\n\nconst CHECK_TYPE = {\n  user: 1,\n  phone: 2,\n  email: 3,\n};\n\nexport enum LOGIN_TAB_KEY {\n  login = \"login\",\n  register = \"register\",\n}\n\nexport const LOGIN_MENU = [\n  {\n    label: \"账号密码登录\",\n    key: LOGIN_TAB_KEY.login,\n    render: (fn) => <LoginForm fn={fn} />,\n  },\n  {\n    label: \"账号注册\",\n    key: LOGIN_TAB_KEY.register,\n    render: (fn) => <RegisterForm fn={fn} />,\n  },\n] as IMenuItem[];\n\nconst menuMap = new Map<string, IMenuItem>();\nLOGIN_MENU.forEach((d) => {\n  menuMap.set(d.key, d);\n});\n\nexport const LOGIN_MENU_MAP = menuMap;\n\nexport enum FormItemType {\n  input = \"input\",\n  inputPassword = \"inputPassword\",\n  inputNumber = \"inputNumber\",\n  custom = \"custom\",\n}\nexport interface IFormItem {\n  key: string;\n  type: FormItemType;\n  attrs?: any;\n  rules?: any[];\n  invisible?: boolean;\n  customFormItem?: any;\n}\n\nexport const renderFormItem = (item: IFormItem) => {\n  switch (item.type) {\n    default:\n    case FormItemType.input:\n      return <Input allowClear key={item.key} {...item.attrs} />;\n    case FormItemType.inputPassword:\n      return <Input.Password allowClear key={item.key} {...item.attrs} />;\n    case FormItemType.inputNumber:\n      return <InputNumber key={item.key} {...item.attrs} />;\n    case FormItemType.custom:\n      return (item as IFormItem).customFormItem;\n  }\n};\n\nexport const FormMap = [\n  {\n    key: \"userName\",\n    label: \"账号\",\n    type: FormItemType.input,\n    rules: [\n      {\n        required: true,\n        message: (\n          <>\n            <CloseCircleFilled />\n            请输入用户账号\n          </>\n        ),\n      },\n    ],\n    attrs: {\n      placeholder: \"请输入账号\",\n      prefix: <UserOutlined style={{ color: \"rgba(0,0,0,.25)\" }} />,\n    },\n  },\n  {\n    key: \"password\",\n    type: FormItemType.inputPassword,\n    label: \"密码\",\n    rules: [\n      {\n        required: true,\n        message: (\n          <>\n            <CloseCircleFilled />\n            请输入密码\n          </>\n        ),\n      },\n    ],\n    attrs: {\n      placeholder: \"请输入密码\",\n      prefix: <LockOutlined style={{ color: \"rgba(0,0,0,.25)\" }} />,\n    },\n  },\n];\n\n// 用户校验\nconst UserInfoCheck = (props) => {\n  const onChange = (e) => {\n    props?.onChange(e.target.value);\n  };\n\n  const onBlur = (e) => {\n    const value = e.target.value;\n    if (props.checkFn && !props.checkFn(value)) {\n      return;\n    }\n\n    checkRegisterUser(props.type, value)\n      .then(() => {\n        props?.onChange({ checked: true, value });\n      })\n      .catch(() => {\n        props?.onChange(\"-9999\");\n      });\n  };\n\n  return (\n    <Input size=\"large\" allowClear key={props.type + \"user\"} placeholder={props.placeholder || \"\"} onChange={onChange} onBlur={onBlur} />\n  );\n};\n\nconst userNameCheck = (value) => {\n  let flat_5_50 = value && value.length > 4 && value.length <= 50;\n  const reg = /^[0-9a-zA-Z_]{1,}$/;\n\n  return flat_5_50 && reg.test(value);\n};\n\nconst userPhoneCheck = (value) => {\n  const reg = /^[1][3-9][0-9]{9}$/;\n\n  return reg.test(value);\n};\n\nconst userEmailCheck = (value) => {\n  const reg = /^[\\w.\\-]+@(?:[a-z0-9]+(?:-[a-z0-9]+)*\\.)+[a-z]{2,3}$/;\n\n  return reg.test(value);\n};\n\nexport const RegisterFormMap = [\n  {\n    key: \"userName\",\n    label: \"用户账号\",\n    type: FormItemType.custom,\n    customFormItem: <UserInfoCheck checkFn={userNameCheck} placeholder=\"请输入用户账号\" type={CHECK_TYPE.user} />,\n    rules: [\n      {\n        required: true,\n        validator: (rule: any, value: string) => {\n          if (value === \"-9999\") {\n            return Promise.reject(\"账号已存在，请重新填写\");\n          }\n          if (value === \"-1\" || !value) {\n            return Promise.reject(\"请输入用户账号\");\n          }\n\n          if (typeof value === \"object\") {\n            return Promise.resolve();\n          }\n\n          if (!userNameCheck(value)) {\n            return Promise.reject(\"账号设置不符合要求\");\n          }\n          return Promise.resolve();\n        },\n      },\n    ],\n  },\n  {\n    key: \"password\",\n    type: FormItemType.inputPassword,\n    label: \"密码\",\n    rules: [\n      {\n        required: true,\n        message: \"密码设置不符合要求\",\n        validator: (rule: any, value: string) => {\n          if (!value) return Promise.reject(\"请输入密码\");\n          let flat_6_20 = value && value.length > 5 && value.length <= 20;\n          if (flat_6_20 && regUserPassword.test(value)) {\n            return Promise.resolve();\n          } else {\n            return Promise.reject();\n          }\n        },\n      },\n    ],\n    attrs: {\n      placeholder: \"请输入密码\",\n    },\n  },\n  {\n    key: \"confirm\",\n    type: FormItemType.inputPassword,\n    label: \"确认密码\",\n    rules: [\n      {\n        required: true,\n        message: \"两次密码不统一\",\n      },\n      ({ getFieldValue }) => ({\n        validator(_, value) {\n          if (!value || getFieldValue(\"password\") === value) {\n            return Promise.resolve();\n          }\n          return Promise.reject(\"两次密码不统一\");\n        },\n      }),\n    ],\n    attrs: {\n      placeholder: \"请再次输入密码\",\n    },\n  },\n  {\n    key: \"realName\",\n    label: \"用户实名\",\n    type: FormItemType.input,\n    rules: [\n      {\n        required: true,\n        validator: (rule: any, value: string) => {\n          if (!value) {\n            return Promise.reject(\"请输入用户实名\");\n          }\n          let flat_1_50 = value && value.length > 0 && value.length <= 50;\n          const reg = /^[a-zA-Z\\u4e00-\\u9fa5]+$/;\n          if (!reg.test(value)) {\n            return Promise.reject(\"请输入中文或英文\");\n          } else if (!flat_1_50) {\n            return Promise.reject(\"1-50字符\");\n          } else {\n            return Promise.resolve();\n          }\n        },\n      },\n    ],\n    attrs: {\n      placeholder: \"请输入用户实名\",\n    },\n  },\n  {\n    key: \"phone\",\n    label: \"手机号\",\n    type: FormItemType.custom,\n    customFormItem: <UserInfoCheck checkFn={userPhoneCheck} placeholder=\"请输入手机号码\" type={CHECK_TYPE.phone} />,\n    rules: [\n      {\n        required: false,\n        validator: (rule: any, value: string) => {\n          if (!value) {\n            return Promise.resolve();\n          }\n          if (value === \"-9999\") {\n            return Promise.reject(\"该手机号已存在，请重新输入\");\n          }\n          if (typeof value === \"object\") {\n            return Promise.resolve();\n          }\n          if (!userPhoneCheck(value)) {\n            return Promise.reject(\"请输入正确手机号码\");\n          } else {\n            return Promise.resolve();\n          }\n        },\n      },\n    ],\n  },\n  {\n    key: \"mailbox\",\n    label: \"邮箱\",\n    type: FormItemType.custom,\n    customFormItem: <UserInfoCheck checkFn={userEmailCheck} placeholder=\"请输入邮箱地址\" type={CHECK_TYPE.email} />,\n    rules: [\n      {\n        required: false,\n        validator: (rule: any, value: string) => {\n          if (!value) {\n            return Promise.resolve();\n          }\n          if (value === \"-9999\") {\n            return Promise.reject(\"该邮箱地址已存在，请重新输入\");\n          }\n          if (typeof value === \"object\") {\n            return Promise.resolve();\n          }\n          if (!userEmailCheck(value)) {\n            return Promise.reject(\"请输入完整的邮件格式\");\n          } else {\n            return Promise.resolve();\n          }\n        },\n      },\n    ],\n  },\n];\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Login/crypto.ts",
    "content": "import CryptoJS from 'crypto-js';\n\nconst AES_KEY = 'Szjx2022@666666$'; // 密钥, AES-128 需16个字符, AES-256 需要32个字符\nconst key = CryptoJS.enc.Utf8.parse(AES_KEY);\n\nexport function encryptAES(str: string) {\n  const srcs = CryptoJS.enc.Utf8.parse(str);\n  const encrypted = CryptoJS.AES.encrypt(srcs, key, {\n    mode: CryptoJS.mode.ECB,\n    padding: CryptoJS.pad.Pkcs7,\n  });\n  return encrypted.toString();\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Login/index.less",
    "content": ".login-box {\n  width: 100%;\n  height: 100vh;\n  display: flex;\n  align-items: center;\n  justify-content: space-around;\n  background: #f4f9ff;\n\n  &-left {\n    flex: 1;\n    height: 100%;\n    background-image: radial-gradient(circle at 50% 50%, #7ca4ff 0%, #ffffff 47%, #ffffff 47%);\n    background-repeat: no-repeat;\n    background-size: 120% auto;\n    &-img {\n      height: 100%;\n      background-color: #f4f9ff;\n      background-image: url(\"./img/background.png\");\n      background-repeat: no-repeat;\n      background-size: 115%;\n    }\n\n    &-title {\n      font-family: PingFangSC-Semibold;\n      font-size: 28px;\n      color: #ffffff;\n      text-align: center;\n      line-height: 40px;\n    }\n\n    &-conter {\n      font-family: PingFangSC-Regular;\n      font-size: 20px;\n      color: #ffffff;\n      text-align: center;\n      line-height: 30px;\n    }\n  }\n\n  &-form {\n    width: 500px;\n    height: 100%;\n    background-repeat: no-repeat;\n    background-size: 100% 435px;\n    background-color: rgba(255, 255, 255, 0.74);\n    display: flex;\n    align-items: center;\n    justify-content: center;\n\n    &-center {\n      position: relative;\n\n      &-header {\n        width: 100%;\n        display: flex;\n        justify-content: center;\n        align-items: center;\n\n        &-left {\n          display: flex;\n          font-size: 18px;\n          color: @primary-color;\n          margin-left: 20px;\n          padding-bottom: 40px;\n\n          &-log {\n            width: 29px;\n            height: 29px;\n            background: url(\"./img/es-logo.png\");\n            background-repeat: no-repeat;\n            background-size: 100% 100%;\n            margin-right: 10px;\n          }\n        }\n        &-logo {\n          width: 240px;\n          height: 41px;\n          margin: 0 auto;\n          background: url(\"./img/logo.png\");\n          background-size: contain;\n        }\n        &-desc {\n          font-family: PingFangSC-Regular;\n          font-size: 16px;\n          color: rgba(14, 16, 51, 0.84);\n          text-align: center;\n          line-height: 30px;\n          margin-top: 10px;\n          padding-bottom: 70px;\n        }\n        &-reg {\n          display: flex;\n          align-items: center;\n          justify-content: space-between;\n          width: 100%;\n          padding-bottom: 50px;\n          &-desc {\n            font-family: PingFangSC-Medium;\n            font-size: 20px;\n            color: rgba(0, 0, 0, 0.84);\n            letter-spacing: 0;\n            line-height: 28px;\n            font-weight: 500;\n          }\n        }\n\n        &-right {\n          font-size: 12px;\n          color: #303a51;\n          text-align: center;\n          line-height: 20px;\n          margin-right: 40px;\n          cursor: pointer;\n          width: 65px;\n          cursor: pointer;\n          display: flex;\n          align-items: center;\n          justify-content: space-between;\n        }\n\n        &-right:hover {\n          color: @primary-color;\n        }\n      }\n\n      &-title {\n        width: 340px;\n        margin: 0 auto;\n        display: flex;\n        align-items: center;\n        justify-content: space-between;\n\n        &-left {\n          font-size: 24px;\n          color: #303a51;\n          text-align: center;\n        }\n\n        &-right {\n          font-size: 12px;\n          color: #999999;\n          text-align: center;\n          margin: 0 auto;\n        }\n      }\n\n      &-content {\n        width: 340px;\n        margin: 0 auto;\n      }\n\n      &-bottom {\n        position: absolute;\n        bottom: 0;\n        width: 100%;\n        height: 50px;\n\n        p {\n          font-size: 12px;\n          color: #999999;\n          letter-spacing: 0;\n          text-align: center;\n          line-height: 18px;\n        }\n      }\n    }\n  }\n\n  .ant-form-vertical .ant-form-item-control {\n    position: relative;\n  }\n\n  .ant-form-item-has-error {\n    margin-bottom: 24px;\n  }\n  .ant-form-item-label > label {\n    font-size: 14px;\n  }\n  .ant-form-item {\n    margin-bottom: 20px;\n  }\n\n  .ant-form-item-explain.ant-form-item-explain-error {\n    color: #ff4d4f;\n    position: absolute;\n    width: 120px;\n    top: 5px;\n    right: -133px;\n\n    span {\n      padding-right: 5px;\n    }\n  }\n\n  .submit-btn {\n    margin-top: 20px;\n    width: 100%;\n    height: 56px;\n  }\n}\n\n.ant-form-item-custom {\n  .ant-form-item-control {\n    height: 32px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/Login/index.tsx",
    "content": "import React, { useState } from \"react\";\nimport { debounce } from \"lodash\";\nimport \"./index.less\";\nimport { LoginForm } from \"./LoginForm\";\nimport { RegisterForm } from \"./RegisterForm\";\n\nexport const LoginOrRegister: React.FC<any> = (props) => {\n  const { type } = props;\n  const defaultKey = window.location.hash.replace(\"#\", \"\") || type || \"login\";\n  const [currentKey, setCurrentKey] = useState(defaultKey);\n  const [critical, setCritical] = useState(window.innerWidth < 1366);\n\n  React.useEffect(() => {\n    window.addEventListener(\"resize\", handleResize); //监听窗口大小改变\n    return () => window.removeEventListener(\"resize\", debounce(handleResize, 500));\n  }, []);\n\n  const handleResize = (e) => {\n    if (e.target.innerWidth < 1366) {\n      setCritical(true);\n    } else {\n      setCritical(false);\n    }\n  };\n\n  const renderContent = () => {\n    return currentKey === \"register\" ? (\n      <RegisterForm fn={handleMenuClick} />\n    ) : (\n      <LoginForm fn={(isAdminUser: boolean) => props.history.push(isAdminUser ? \"/dashboard\" : \"/cluster/logic\")} />\n    );\n  };\n\n  const handleMenuClick = (e: string) => {\n    setCurrentKey(e);\n    window.location.hash = e;\n  };\n\n  /*\n   *屏幕宽度大于等于1366\n   *@ 图片宽度占页面宽度比三分之一，等比缩放\n   *@ 表单区域占比三分之二，区域内水平居中\n   *屏幕宽度小于1366\n   *@ 不展示图片\n   *@ 水平居中\n   */\n\n  const renderHeader = () => {\n    return (\n      <>\n        {critical === true ? (\n          <div className=\"login-box-form-center-header-left\">\n            <div className=\"login-box-form-center-header-logo\"></div>\n          </div>\n        ) : isLogin ? (\n          <div>\n            <div className=\"login-box-form-center-header-logo\"></div>\n            <div className=\"login-box-form-center-header-desc\">零侵入、零门槛 Elasticsearch GUI管控平台</div>\n          </div>\n        ) : (\n          <div className=\"login-box-form-center-header-reg\">\n            <div className=\"login-box-form-center-header-reg-desc\">账号注册</div>\n            <div>\n              已有账号，<a onClick={() => handleMenuClick(\"login\")}>直接登录</a>\n            </div>\n          </div>\n        )}\n        {/* <div className='login-box-form-center-header-right'>\n          <CopyOutlined />\n          说明文档\n        </div> */}\n      </>\n    );\n  };\n\n  const isLogin = currentKey === \"login\";\n\n  return (\n    <div className=\"login-box\">\n      <div className=\"login-box-left\" style={{ display: critical ? \"none\" : null }}>\n        <div className=\"login-box-left-img\"></div>\n      </div>\n      <div className=\"login-box-form\">\n        <div className=\"login-box-form-center\">\n          <div className=\"login-box-form-center-header\">{renderHeader()}</div>\n          <div className=\"login-box-form-center-content\">{renderContent()}</div>\n          <div className=\"login-box-form-center-title\" style={isLogin ? { marginTop: \"5%\" } : null}>\n            <div className=\"login-box-form-center-title-right\">\n              {currentKey === \"register\" ? null : (\n                <div>\n                  {\" \"}\n                  还没账号，<a onClick={() => handleMenuClick(\"register\")}>立即注册</a>\n                </div>\n              )}\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RenderTitle/index.less",
    "content": ".table-header {\n  background-color: #fff;\n  border-radius: 4px 4px 0 0;\n  border-bottom: 1px solid #dcdfe6;\n  &-box {\n    padding: 20px 20px 0;\n    &-title {\n      font-family: PingFangSC-Medium;\n      font-size: 16px;\n      color: #101724;\n      line-height: 24px;\n    }\n    &-content {\n      font-family: PingFangSC-Regular;\n      font-size: 14px;\n      color: #505568;\n      line-height: 22px;\n    }\n  }\n}\n.table-content {\n  padding: 20px;\n  background: white;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RenderTitle/index.tsx",
    "content": "import \"./index.less\";\nimport React, { useState } from \"react\";\n\ninterface ITitle {\n  title: string;\n  content: string;\n}\nexport const RenderTitle = (header: ITitle) => {\n  return (\n    <div className=\"table-header-box\">\n      <span className=\"table-header-box-title\">{header.title}</span>\n      {header.content ? (\n        <>\n          <span> / </span>\n          <span className=\"table-header-box-content\">{header.content}</span>\n        </>\n      ) : null}\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RoleManage/BindUser.tsx",
    "content": "import { Button, Col, Form, Modal, Row, Select, Table } from \"antd\";\nimport { renderOperationBtns } from \"container/custom-component\";\nimport React from \"react\";\nimport { queryAssignedUserByRole } from \"./service\";\n\nconst BindUser = (props) => {\n  const [list, setList] = React.useState([]);\n  const [data, setData] = React.useState([]);\n\n  const fetchUserList = async () => {\n    const res: [] = await queryAssignedUserByRole(props.roleId);\n    const initVal = res.filter((item: any) => item.has);\n    const initList = res\n      .filter((item: any) => !item.has)\n      .map((item: any) => ({\n        label: item.name,\n        value: item.id,\n      }));\n    setList(initList);\n    setData(initVal);\n  };\n\n  React.useEffect(() => {\n    fetchUserList();\n  }, []);\n\n  const addUser = (values) => {\n    const { user = {} } = values;\n    const _data =\n      data.findIndex((row) => row.id === user.value) < 0\n        ? [\n            ...data,\n            {\n              id: user.value,\n              name: user.label,\n            },\n          ]\n        : data;\n    setData(_data);\n    props.onUserChange(\n      _data.length,\n      _data.map((item) => item.id)\n    );\n  };\n\n  const getColumns = () => {\n    return [\n      {\n        title: \"序号\",\n        dataIndex: \"id\",\n        key: \"id\",\n        width: 250,\n      },\n      {\n        title: \"用户账号\",\n        dataIndex: \"name\",\n        key: \"name\",\n      },\n      {\n        title: \"操作\",\n        dataIndex: \"operation\",\n        filterTitle: true,\n        key: \"operation\",\n        width: 100,\n        render: (text: string, record: any) => {\n          const btns = !record.has\n            ? [\n                {\n                  clickFunc: () => {\n                    Modal.confirm({\n                      title: `确认删除用户 ${record.name}？`,\n                      content: \"\",\n                      onOk: () => {\n                        const _data = data.filter((item) => item.id !== record.id);\n                        setData(_data);\n                        props.onUserChange(\n                          _data.length,\n                          _data.map((item) => item.id)\n                        );\n                      },\n                    });\n                  },\n                  label: \"删除\",\n                },\n              ]\n            : [];\n          return renderOperationBtns(btns, record);\n        },\n      },\n    ];\n  };\n\n  return (\n    <>\n      <div>\n        <Form onFinish={addUser}>\n          <Row>\n            <Col span={10}>\n              <Form.Item label=\"\" name=\"user\" rules={[{ required: true, message: \"请选择用户\" }]}>\n                <Select\n                  showSearch\n                  labelInValue\n                  optionFilterProp=\"children\"\n                  options={list}\n                  placeholder={\"请选择用户\"}\n                  filterOption={(input, option) => (option!.label as unknown as string).toLowerCase().includes(input.toLowerCase())}\n                />\n              </Form.Item>\n            </Col>\n            <Col span={4}>\n              <Form.Item>\n                <Button style={{ marginLeft: 16 }} type=\"primary\" htmlType=\"submit\">\n                  添加\n                </Button>\n              </Form.Item>\n            </Col>\n          </Row>\n        </Form>\n      </div>\n      <Table rowKey=\"id\" scroll={{ y: 500 }} columns={getColumns()} dataSource={data} pagination={false} />\n    </>\n  );\n};\n\nexport default BindUser;\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RoleManage/PermissionTree.tsx",
    "content": "import { Checkbox, Form } from \"antd\";\nimport React, { useRef, useState } from \"react\";\nimport { Tooltip } from \"antd\";\n\nconst getCheckItems = (options) => {\n  const _checkList = [];\n  for (let item of options) {\n    _checkList.push(item.id);\n  }\n  return _checkList;\n};\n\nconst SinglePermission = (props) => {\n  const { data, isEdit } = props;\n  const allOptions = (data.childList || []).map((item) => ({\n    ...item,\n    label: (\n      <Tooltip key={item.id} title={item.permissionName}>\n        {item.permissionName}\n      </Tooltip>\n    ),\n    value: item.id,\n  }));\n\n  const checkItems = getCheckItems((data.childList || []).filter((item) => item.has));\n  const [checkedList, setCheckedList] = useState(checkItems || []);\n  const [indeterminate, setIndeterminate] = useState(checkItems.length !== allOptions.length && !!checkItems.length);\n  const [checkAll, setCheckAll] = useState(checkItems.length === allOptions.length);\n\n  const onChange = (list) => {\n    setCheckedList(list);\n    setIndeterminate(!!list.length && list.length < allOptions.length);\n    setCheckAll(list.length === allOptions.length);\n    props.onChange?.(list, list.length === 0);\n  };\n\n  const onCheckAllChange = (e) => {\n    const checkItems = e.target.checked ? getCheckItems(allOptions) : [];\n    setCheckedList(checkItems);\n    setIndeterminate(false);\n    setCheckAll(e.target.checked);\n    props.onChange?.(checkItems, !e.target.checked);\n  };\n\n  return (\n    <>\n      <div className=\"check-item\" key={data.id}>\n        <div className=\"label\">\n          {isEdit ? (\n            <Checkbox indeterminate={indeterminate} onChange={onCheckAllChange} checked={checkAll}>\n              {data.permissionName}\n            </Checkbox>\n          ) : (\n            <span>{data.permissionName}</span>\n          )}\n        </div>\n        <div className=\"content\">\n          <Checkbox.Group disabled={!isEdit} options={allOptions} value={checkedList} onChange={onChange} />\n        </div>\n      </div>\n    </>\n  );\n};\n\nconst PermissionTree = React.forwardRef((props: any, ref) => {\n  const { isUpdate, permissionData } = props;\n\n  const initPermissionIdList = () => {\n    const checkedItems = {};\n    if (isUpdate) {\n      const checkedData = permissionData.filter((item) => item.has);\n      for (let item of checkedData) {\n        checkedItems[item.id] = [item.id];\n        for (let row of item.childList || []) {\n          if (item.has) {\n            checkedItems[item.id].push(row.id);\n          }\n        }\n      }\n    }\n    return checkedItems;\n  };\n\n  const permissionIdMap = useRef({});\n\n  React.useEffect(() => {\n    permissionIdMap.current = initPermissionIdList();\n    return () => {\n      permissionIdMap.current = null;\n    };\n  }, [permissionData]);\n\n  const onChange = (parentId: number, subIds: number[], isNone: boolean) => {\n    // isNone 表示该权限项无任何权限点\n    permissionIdMap.current[parentId] = isNone ? [] : [parentId, ...subIds];\n  };\n\n  const getPermissionIdList = () => {\n    const permissionIdList = [];\n    for (let key of Object.keys(permissionIdMap.current)) {\n      permissionIdList.push(...permissionIdMap.current[key]);\n    }\n    return permissionIdList;\n  };\n\n  React.useImperativeHandle(ref, () => ({\n    getPermissionIdList,\n  }));\n\n  return (\n    <>\n      <div className=\"role-tree-panel\">\n        {permissionData.map((item, index) => (\n          <SinglePermission\n            onChange={(values, isNone) => onChange(item.id, values, isNone)}\n            isEdit={props.isEdit}\n            data={item}\n            key={item.id}\n          />\n        ))}\n      </div>\n    </>\n  );\n});\n\nexport default PermissionTree;\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RoleManage/RecycleUser.tsx",
    "content": "import { Button, Col, Form, Input, message, Modal, Row, Table } from \"antd\";\nimport { renderOperationBtns } from \"container/custom-component\";\nimport React, { useRef } from \"react\";\nimport { deleteUserByRoleId, queryAssignedUserByRole } from \"./service\";\nimport { XNotification } from \"component/x-notification\";\n\nconst RecylceUser = (props) => {\n  const [data, setData] = React.useState([]);\n  const primaryData = useRef([]);\n  const [form] = Form.useForm();\n\n  const fetchUserList = async () => {\n    const res: [] = await queryAssignedUserByRole(props.roleId);\n    const initVal = res.filter((item: any) => item.has);\n    primaryData.current = initVal;\n    setData(initVal);\n  };\n\n  React.useEffect(() => {\n    fetchUserList();\n    return () => {\n      primaryData.current = null;\n    };\n  }, []);\n\n  const searchUser = (values) => {\n    if (!values?.user) {\n      setData(primaryData.current);\n      return;\n    }\n    const _data = data.filter((item) => item.name.includes(values.user));\n    setData(_data);\n  };\n\n  const onReset = () => {\n    form.setFieldsValue({ user: \"\" });\n    setData(primaryData.current);\n  };\n\n  const getColumns = () => {\n    return [\n      {\n        title: \"序号\",\n        dataIndex: \"id\",\n        key: \"id\",\n        width: 250,\n      },\n      {\n        title: \"用户账号\",\n        dataIndex: \"name\",\n        key: \"name\",\n      },\n      {\n        title: \"操作\",\n        dataIndex: \"operation\",\n        filterTitle: true,\n        key: \"operation\",\n        width: 100,\n        render: (text: string, record: any) => {\n          const btns = [\n            {\n              clickFunc: () => {\n                if (props.roleName === \"管理员\" && primaryData?.current?.length === 1) {\n                  XNotification({ type: \"error\", message: \"管理员角色用户数不能为0\" });\n                  return;\n                }\n                Modal.confirm({\n                  title: `确认回收用户 ${record.name}？`,\n                  content: <span style={{ color: \"red\" }}>请确认影响后再进行删除操作！</span>,\n                  onOk: () => {\n                    deleteUserByRoleId(props.roleId, record.id).then((res) => {\n                      message.success(\"删除成功\");\n                      fetchUserList();\n                      props.submitCb && props.submitCb(false);\n                    });\n                  },\n                });\n              },\n              label: \"删除\",\n            },\n          ];\n          return renderOperationBtns(btns, record);\n        },\n      },\n    ];\n  };\n\n  return (\n    <>\n      <div>\n        <Form form={form} onFinish={searchUser}>\n          <Row>\n            <Col span={10}>\n              <Form.Item label=\"\" name=\"user\" rules={[{ required: true, message: \"请输入用户账号\" }]}>\n                <Input allowClear placeholder={\"请输入用户账号\"} />\n              </Form.Item>\n            </Col>\n            <Col span={6}>\n              <Form.Item>\n                <Button style={{ marginLeft: 16, marginRight: 16 }} type=\"primary\" htmlType=\"submit\">\n                  查询\n                </Button>\n                <Button htmlType=\"button\" onClick={onReset}>\n                  重置\n                </Button>\n              </Form.Item>\n            </Col>\n          </Row>\n        </Form>\n      </div>\n      <Table rowKey=\"id\" scroll={{ y: 250 }} columns={getColumns()} dataSource={data} pagination={false} />\n    </>\n  );\n};\n\nexport default RecylceUser;\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RoleManage/config.tsx",
    "content": "import React from \"react\";\nimport { Utils } from \"knowdesign\";\nconst formatDate = Utils.formatDate;\nimport { regNonnegativeInteger } from \"constants/reg\";\n\nexport interface ITableBtn {\n  clickFunc?: () => void;\n  type?: string;\n  customFormItem?: string | JSX.Element;\n  isRouterNav?: boolean;\n  label: string | JSX.Element;\n  className?: string;\n  needConfirm?: boolean;\n  aHref?: string;\n  confirmText?: string;\n  noRefresh?: boolean;\n  loading?: boolean;\n  disabled?: boolean;\n  invisible?: boolean; // 不可见\n}\n\nexport const getFormText: { searchText: string; resetText: string } = {\n  searchText: \"查询\",\n  resetText: \"重置\",\n};\n\nexport const getFormCol = () => {\n  return [\n    {\n      type: \"input\",\n      title: \"角色ID:\",\n      dataIndex: \"id\",\n      placeholder: \"请输入角色ID\",\n      componentProps: {\n        maxLength: 128,\n      },\n      rules: [\n        {\n          required: false,\n          validator: (rule: any, value: string) => {\n            if (value && !new RegExp(regNonnegativeInteger).test(value)) {\n              return Promise.reject(new Error(\"请输入正确格式\"));\n            }\n            if (value && value?.length > 16) {\n              return Promise.reject(new Error(\"请输入正确ID，0-16位字符\"));\n            }\n            return Promise.resolve();\n          },\n        },\n      ],\n    },\n    {\n      type: \"input\",\n      title: \"角色名称:\",\n      dataIndex: \"roleName\",\n      placeholder: \"请输入角色名称\",\n      componentProps: {\n        maxLength: 128,\n      },\n    },\n    {\n      type: \"input\",\n      title: \"描述:\",\n      dataIndex: \"description\",\n      placeholder: \"请输入描述\",\n      componentProps: {\n        maxLength: 128,\n      },\n    },\n  ];\n};\n\nexport const getTableCol = (renderIndex, renderRoleDetail, renderUserNum, renderOptCol) => {\n  const columns = [\n    {\n      title: \"序号\",\n      dataIndex: \"index\",\n      render: renderIndex,\n    },\n    {\n      title: \"角色ID\",\n      dataIndex: \"id\",\n      key: \"id\",\n      render: renderRoleDetail,\n    },\n    {\n      title: \"角色名称\",\n      dataIndex: \"roleName\",\n      key: \"roleName\",\n      render: renderRoleDetail,\n    },\n    {\n      title: \"角色描述\",\n      dataIndex: \"description\",\n      key: \"description\",\n      width: \"200px\",\n      lineClampTwo: true,\n      needTooltip: true,\n      render: (text: string) => text || \"-\",\n    },\n    {\n      title: \"绑定用户数\",\n      dataIndex: \"authedUserCnt\",\n      key: \"authedUserCnt\",\n      render: renderUserNum,\n    },\n    {\n      title: \"最后修改人\",\n      dataIndex: \"lastReviser\",\n      key: \"lastReviser\",\n      render: (text: string) => text || \"-\",\n    },\n    {\n      title: \"最后更新时间\",\n      dataIndex: \"updateTime\",\n      key: \"updateTime\",\n      render: (_value: string | number): any => {\n        return formatDate(_value, \"YYYY-MM-DD HH:mm:ss\");\n      },\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      width: 180,\n      key: \"operation\",\n      render: renderOptCol,\n    },\n  ];\n  return columns;\n};\n\nexport const readableForm = [\n  {\n    label: \"角色名称\",\n    prop: \"roleName\",\n    readText: \"\",\n    render: null,\n  },\n  {\n    label: \"描述\",\n    prop: \"description\",\n    readText: \"\",\n    render: null,\n  },\n];\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RoleManage/detail.less",
    "content": "@ant-prefix: ant;\n\n.role-manage-detail {\n  .read-lable {\n    font-family: PingFangSC-Regular;\n    text-align: right;\n    line-height: 20px;\n    display: inline-block;\n    width: 70px;\n    text-align: right;\n  }\n\n  .read-content {\n    font-family: PingFangSC-Regular;\n    line-height: 20px;\n    display: inline-block;\n  }\n\n  .role-tpl-form {\n    padding: 20px;\n\n    &-formitem {\n      margin-top: 20px !important;\n      margin-bottom: 0px !important;\n    }\n\n    &-first-formitem {\n      margin-bottom: 0px !important;\n    }\n  }\n\n  .ant-transfer {\n    height: 100%;\n  }\n\n  .ant-transfer-list {\n    width: 100%;\n    height: 100%;\n    border-radius: 4px;\n  }\n\n  .ant-transfer-list-header-title {\n    font-weight: bolder;\n  }\n\n  .bind-row-item {\n    height: 24px;\n    margin-right: 7px;\n    padding: 0 3px;\n    background: #f8fafd;\n    color: #303a51;\n    border: 1px solid #eaeef5;\n    border-radius: 1px;\n  }\n\n  .bind-role-title {\n    margin-top: 26px;\n    margin-bottom: 12px;\n    font-size: 14px;\n    font-weight: bolder;\n    color: #303a51;\n  }\n\n  .bind-role-table {\n    width: 100%;\n    border: 1px solid #dcdfe6;\n    border-radius: 4px;\n    border-collapse: collapse;\n    display: table;\n    border-style: hidden;\n    box-shadow: 0 0 0 1px #dcdfe6;\n\n    .tr {\n      display: table-row;\n\n      .td {\n        display: table-cell;\n        line-height: 40px;\n        padding: 0 20px;\n        vertical-align: top;\n        border: 1px solid #dcdfe6;\n        position: relative;\n        text-align: left;\n      }\n    }\n\n    .tHead {\n      font-weight: bold;\n      height: 40px;\n      line-height: 40px;\n      color: #303a51;\n      background: #f5f7fa;\n\n      > div:first-child {\n        width: 157px;\n        border-top-left-radius: 4px;\n      }\n\n      > div:last-child {\n        // width: 482px;\n        border-top-right-radius: 4px;\n      }\n    }\n\n    .tBody {\n      .col-permission {\n        display: flex;\n\n        .permission-all {\n        }\n\n        .permission-content {\n          flex: 1;\n          display: flex;\n          flex-wrap: wrap;\n          padding-top: 10px;\n\n          .content-item {\n            margin-top: -10px;\n            padding-left: 16px;\n          }\n        }\n      }\n    }\n\n    .empty-item {\n      position: relative;\n      display: table-row;\n      height: 80px;\n      line-height: 80px;\n\n      span {\n        position: absolute;\n        top: 50%;\n        left: 50%;\n        transform: translate(-50%, -50%);\n      }\n    }\n  }\n}\n\n.role-tree-panel {\n  padding-bottom: 24px;\n  .check-item:last-child {\n    margin-bottom: 0px;\n  }\n\n  .check-item {\n    display: flex;\n    background: #ffffff;\n    border: 1px solid #ebedef;\n    border-radius: 4px;\n    margin-bottom: 11px;\n\n    .label {\n      font-family: PingFangSC-Regular;\n      font-size: 12px;\n      color: #374053;\n      line-height: 20px;\n      width: 120px;\n      background: #f9f9fa;\n      border-radius: 4px 0 0 4px;\n      display: flex;\n      align-items: center;\n      padding-left: 16px;\n    }\n\n    .content {\n      padding: 16px 24px 5px;\n      width: calc(100% - 120px);\n\n      .ant-checkbox-group-item {\n        width: 128px;\n        margin-bottom: 11px;\n        height: 20px;\n      }\n    }\n\n    .@{ant-prefix}-checkbox-disabled .@{ant-prefix}-checkbox-inner {\n      background-color: #f4f4f6;\n      border: 0.77px solid #d7dae0;\n      border-radius: 1.53px;\n    }\n\n    .@{ant-prefix}-checkbox-disabled.@{ant-prefix}-checkbox-checked .@{ant-prefix}-checkbox-inner::after {\n      border-color: #a9afbc;\n    }\n\n    .@{ant-prefix}-checkbox-disabled + span {\n      color: #374053;\n    }\n\n    .@{ant-prefix}-checkbox-inner {\n      height: 14px;\n      width: 14px;\n    }\n\n    .@{ant-prefix}-checkbox-indeterminate {\n      .@{ant-prefix}-checkbox-inner::after {\n        width: 8px;\n        height: 8px;\n      }\n    }\n\n    .@{ant-prefix}-checkbox-inner::after {\n      width: 4.9px;\n      height: 6.99px;\n    }\n\n    .@{ant-prefix}-checkbox + span {\n      padding-right: 8px;\n      padding-left: 8px;\n      text-overflow: ellipsis;\n      max-width: 105px;\n      white-space: nowrap;\n      overflow: hidden;\n    }\n  }\n}\n\n.edit-table {\n  margin-top: 20px;\n\n  .@{ant-prefix}-select-selector {\n    width: 320px;\n    text-align: left;\n  }\n}\n\n.bind-admin-tips {\n  height: 32px;\n  background: #eff4ff;\n  border-radius: 4px;\n  padding: 6px;\n  color: #041d66;\n  .icon {\n    font-size: 14px;\n    margin-right: 5px;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RoleManage/detail.tsx",
    "content": "import React, { useState, useEffect, FC, useRef } from \"react\";\nimport { Button, message, Drawer, Form, Input, Row, Col, Transfer, Checkbox, Descriptions } from \"antd\";\nimport { readableForm } from \"./config\";\nimport { queryRoleDetail, createOrUpdateRole, assignRole, queryPermissionTree, getRolePermission } from \"./service\";\nimport \"./detail.less\";\nimport PermissionTree from \"./PermissionTree\";\nimport BindUser from \"./BindUser\";\nimport RecylceUser from \"./RecycleUser\";\n\nconst { TextArea } = Input;\n\nenum Eflag {\n  detail = \"角色详情\",\n  create = \"新建角色\",\n  update = \"编辑角色\",\n  assign = \"绑定用户\",\n  recycle = \"回收用户\",\n}\nexport default function Detail(props: any) {\n  const { detailVisible, setDetailVisible, flag, submitCb, roleId, width, roleName } = props;\n\n  const [form] = Form.useForm();\n  const [submitDisabled, setSubmitDisabled] = useState(flag === \"assign\");\n  const [submitLoading, setSubmitLoading] = useState(false);\n  const [detailData, setDetailData] = useState({\n    // userVoList: [],\n    // permissionVo: {},\n  });\n  const [permissionVo, setPermissionVo] = useState([]);\n  const [loading, setLoading] = useState(true);\n\n  const permissionRef: any = React.createRef();\n  const currentSelectUser = useRef([]);\n\n  const onSubmit = () => {\n    if (flag === \"assign\") {\n      handleAssign();\n    } else {\n      handleCreateOrUpdate();\n    }\n  };\n\n  const getIdList = (permissionVo) => {\n    return permissionVo.reduce((res, curr) => {\n      if (curr.has && !res.includes(curr.id)) {\n        res.push(curr.id);\n      }\n      return res.concat(curr.childList && curr.childList.length > 0 ? getIdList(curr.childList) : []);\n    }, []);\n  };\n\n  const handleAssign = () => {\n    const params = {\n      id: roleId,\n      flag: false, // true：N个角色分配给1个用户、false：1个角色分配给N个用户\n      idList: currentSelectUser.current,\n    };\n    setSubmitLoading(true);\n    assignRole(params)\n      .then(() => {\n        message.success(\"提交成功\");\n        setSubmitLoading(false);\n        submitCb();\n      })\n      .catch(() => {\n        setSubmitLoading(false);\n      });\n  };\n\n  const handleCreateOrUpdate = () => {\n    form\n      .validateFields()\n      .then((values) => {\n        const permissionIdList = permissionRef.current.getPermissionIdList();\n\n        if (permissionIdList.length < 1) {\n          message.warning(\"请勾选权限项\");\n          return;\n        }\n        const isCreate = flag === \"create\";\n        const params = isCreate\n          ? {\n              ...values,\n              permissionIdList,\n            }\n          : {\n              ...values,\n              id: roleId,\n              permissionIdList,\n            };\n\n        setSubmitLoading(true);\n        createOrUpdateRole(isCreate, params)\n          .then(() => {\n            message.success(\"提交成功\");\n            submitCb();\n          })\n          .finally(() => {\n            setSubmitLoading(false);\n          });\n      })\n      .catch((err) => {\n        console.log(err);\n      });\n  };\n\n  const onClose = () => {\n    setDetailVisible(false);\n  };\n\n  const filterPermission = (permissionData: any[]) => {\n    let _permissionData = Array.from(permissionData).filter((item) => item.has);\n    for (let permission of _permissionData) {\n      permission.childList = (permission.childList || []).filter((item) => item.has);\n    }\n    return _permissionData;\n  };\n\n  const fetchDetail = async (roleId) => {\n    setLoading(true);\n    try {\n      const res: any = await queryRoleDetail(roleId);\n      let permissionVoData =\n        res.permissionTreeVO &&\n        res.permissionTreeVO.childList.map((item) => {\n          if (res.roleName !== \"管理员\" && item.permissionName === \"应用管理\") {\n            // 非管理员无访问设置权限\n            item.childList = (item?.childList || []).filter((child) => child.permissionName !== \"访问设置\");\n          }\n          if (res.roleName === \"管理员\" && item.permissionName === \"物理集群\") {\n            // 0.3版本隐藏绑定Gateway功能\n            item.childList = (item?.childList || []).filter((child) => child.has);\n          }\n          return {\n            ...item,\n            isCheckAll: item.childList.every((subItem) => subItem.has),\n          };\n        });\n\n      if (flag !== \"update\") {\n        setDetailData(res);\n      } else {\n        form.setFieldsValue(res);\n        // 编辑权限点时展示所有权限点\n        const roleList: any = await getRolePermission();\n\n        // roleList?.childList 中has表示该角色是否能展示权限点\n        const renderRoleList = (roleList?.childList || []).filter((item) => item.has);\n\n        for (let item of renderRoleList) {\n          // permissionVoData中has表示该权限点是否生效\n          item.childList = (item.childList || []).filter((row) => row.has);\n        }\n\n        for (let parent of renderRoleList) {\n          // permissionVoData中has表示该权限点是否生效\n          parent.has = !!permissionVoData.find((row) => row.id === parent.id)?.has;\n          const childList = parent.childList || [];\n          for (let child of childList) {\n            // permissionVoData中has表示该权限点是否生效\n            const pChildList = permissionVoData.find((row) => row.id === parent.id)?.childList || [];\n            child.has = !!pChildList.find((row) => row.id === child.id)?.has;\n          }\n          parent.childList = childList;\n        }\n        permissionVoData = renderRoleList;\n      }\n      setPermissionVo(permissionVoData);\n      setLoading(false);\n    } catch (err) {\n      setLoading(false);\n    }\n  };\n\n  const fetchPermissionTree = async () => {\n    const res: any = await getRolePermission();\n    let permissionVoData = (res.childList || []).map((item) => {\n      if (item.permissionName === \"应用管理\") {\n        // 新建角色无访问设置权限\n        item.childList = (item?.childList || []).filter((child) => child.permissionName !== \"访问设置\");\n      }\n      return {\n        ...item,\n      };\n    });\n    setPermissionVo(permissionVoData);\n  };\n\n  const renderReadOnlyCol = () => {\n    let titleForm = readableForm.map((item, i) => {\n      return (\n        <Col key={i} span={24} className=\"mb-10\">\n          <div className=\"read-lable\">{item.label}：</div>\n          <div className=\"read-content\">{detailData[item.prop]}</div>\n        </Col>\n      );\n    });\n    let bindAdminTips = (\n      <Col key={\"tips\"} span={24} className=\"mb-10\">\n        <div className=\"bind-admin-tips\">\n          <svg className=\"icon svg-icon svg-style\" aria-hidden=\"true\">\n            <use xlinkHref=\"#iconinfo-circle\"></use>\n          </svg>\n          管理员角色用户会拥有全部应用的管理权限，包括SuperApp，请谨慎分配！\n        </div>\n      </Col>\n    );\n    return (\n      <>\n        {roleName === \"管理员\" && flag === \"assign\" && bindAdminTips}\n        {titleForm}\n      </>\n    );\n  };\n\n  const renderEditableCol = () => {\n    return (\n      <Form layout=\"vertical\" form={form}>\n        <Row>\n          <Col span={24}>\n            <Form.Item\n              label=\"角色名称\"\n              name=\"roleName\"\n              rules={[\n                {\n                  required: true,\n                  //message: \"请输入角色名称\",\n                  validator: async (rule: any, value: string) => {\n                    let flat_1_50 = value && value.length >= 3 && value.length <= 20;\n                    if (!value) {\n                      return Promise.reject(\"请输入角色名称，支持3-20个字符\");\n                    }\n                    if (flat_1_50) {\n                      return Promise.resolve();\n                    } else {\n                      return Promise.reject(\"请输入角色名称，支持3-20个字符\");\n                    }\n                  },\n                },\n              ]}\n            >\n              <Input allowClear style={{ width: \"60%\" }} placeholder=\"请输入角色名称\" />\n            </Form.Item>\n          </Col>\n          <Col span={24}>\n            <Form.Item\n              label=\"描述\"\n              name=\"description\"\n              rules={[\n                {\n                  required: true,\n                  validator: async (rule: any, value: string) => {\n                    if (!value) {\n                      return Promise.reject(\"请输入描述，支持1-100个字符\");\n                    }\n                    if (value && value.length > 100) {\n                      return Promise.reject(\"请输入描述，支持1-100个字符\");\n                    }\n\n                    return Promise.resolve();\n                  },\n                },\n              ]}\n            >\n              <TextArea allowClear style={{ width: \"60%\" }} placeholder=\"请输入描述，支持1-100个字符\" />\n            </Form.Item>\n          </Col>\n        </Row>\n      </Form>\n    );\n  };\n\n  const renderEmpty = () => {\n    return (\n      <div className=\"empty-item\">\n        <span>暂无权限项</span>\n      </div>\n    );\n  };\n\n  const renderContent = () => {\n    // 编辑权限点不做过滤，查看详情和新建角色过滤掉不可展示的权限点\n    const permissionData = flag === \"detail\" || flag === \"create\" ? filterPermission(permissionVo) : permissionVo;\n    return (\n      <PermissionTree\n        ref={permissionRef}\n        isUpdate={flag === \"update\" || flag === \"create\"}\n        isEdit={flag !== \"detail\"}\n        permissionData={permissionData}\n      />\n    );\n  };\n\n  const renderRolePermission = () => {\n    return (\n      <>\n        {flag === \"detail\" ? <h4 className=\"bind-role-title\"></h4> : null}\n        {flag === \"detail\" && !loading && permissionVo.every((item) => !item.has) ? renderEmpty() : renderContent()}\n      </>\n    );\n  };\n\n  const renderFooter = () => {\n    return (\n      <div\n        style={{\n          textAlign: \"left\",\n        }}\n      >\n        {flag === \"detail\" || flag === \"recycle\" ? (\n          <Button onClick={onClose} type=\"primary\">\n            关闭\n          </Button>\n        ) : (\n          <Button disabled={submitDisabled} loading={submitLoading} onClick={onSubmit} type=\"primary\">\n            保存\n          </Button>\n        )}\n      </div>\n    );\n  };\n\n  const onUserChange = (canSubmit: Boolean, userList: number[]) => {\n    setSubmitDisabled(!canSubmit);\n    currentSelectUser.current = userList;\n  };\n\n  const renderOpTable = () => {\n    return (\n      <div className=\"edit-table\">\n        {flag === \"assign\" ? (\n          <BindUser roleId={props.roleId} onUserChange={onUserChange} />\n        ) : (\n          <RecylceUser submitCb={submitCb} roleId={props.roleId} roleName={roleName} />\n        )}\n      </div>\n    );\n  };\n\n  useEffect(() => {\n    flag === \"create\" ? fetchPermissionTree() : fetchDetail(roleId);\n    return () => {\n      permissionRef.current = null;\n      currentSelectUser.current = null;\n    };\n  }, []);\n\n  return (\n    <Drawer\n      className=\"role-manage-detail\"\n      width={width || 800}\n      title={Eflag[flag] || \"\"}\n      onClose={onClose}\n      visible={detailVisible}\n      footer={renderFooter()}\n    >\n      <div style={{ paddingTop: 16 }}>\n        {(flag === \"detail\" || flag === \"assign\" || flag === \"recycle\") && renderReadOnlyCol()}\n        {(flag === \"create\" || flag === \"update\") && renderEditableCol()}\n        {flag === \"assign\" || flag === \"recycle\" ? renderOpTable() : renderRolePermission()}\n      </div>\n    </Drawer>\n  );\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RoleManage/index.less",
    "content": ".mb-10 {\n  margin-bottom: 10px;\n}\n\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RoleManage/index.tsx",
    "content": "import { Modal, message } from \"antd\";\nimport React, { useState, useEffect } from \"react\";\nimport { getFormCol, getTableCol, getFormText } from \"./config\";\nimport { DTable, ITableBtn } from \"../../dantd/DTable\";\nimport { RenderTitle } from \"../RenderTitle\";\nimport QueryForm from \"../../ProForm/QueryForm\";\nimport { queryRoleList, queryRoleStatus, deleteRole } from \"./service\";\nimport { renderTableOpts } from \"../../ProTable/RenderTableOpts\";\nimport { ExclamationCircleOutlined } from \"@ant-design/icons\";\nimport Detail from \"./detail\";\nimport \"./index.less\";\nimport Progress from \"../../CommonComponents/ProgressBar\";\nimport { getCookie } from \"lib/utils\";\nimport { getUser } from \"api/logi-security\";\nimport { PERMISSION_TREE } from \"constants/common\";\nimport store from \"../../../store\";\nimport * as actions from \"actions\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { RolePermissions } from \"constants/permission\";\nimport { ProTable } from \"knowdesign\";\n\nexport const RoleManage = () => {\n  const [flag, setFlag] = useState(\"\");\n  const [detailVisible, setDetailVisible] = useState(false);\n  const [loading, setloading] = useState(false);\n  const [formData, setFormData] = useState({} as any);\n  const [pagination, setPagination] = useState({\n    current: 1,\n    pageSize: 10,\n    position: \"bottomRight\",\n    showQuickJumper: true,\n    showSizeChanger: true,\n    pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n    showTotal: (total: number) => `共 ${total} 条`,\n  });\n  const [roleId, setRoleId] = useState();\n  const [data, setData] = useState([]);\n  const [roleName, setRoleName] = useState(\"\");\n\n  const renderTitleContent = () => {\n    return {\n      title: \"角色管理\",\n      content: null,\n    };\n  };\n\n  const getOpBtns = (): ITableBtn[] => {\n    return [\n      hasOpPermission(RolePermissions.PAGE, RolePermissions.ADD) && {\n        label: \"新建角色\",\n        className: \"ant-btn-primary\",\n        clickFunc: () => handleAdd(),\n      },\n    ].filter(Boolean);\n  };\n\n  const getOperationList = (row: any) => {\n    return [\n      {\n        label: \"编辑\",\n        invisible: row.isDefaultRole || !hasOpPermission(RolePermissions.PAGE, RolePermissions.EDIT),\n        clickFunc: () => handleDetail(row, \"update\"),\n      },\n      {\n        invisible: !hasOpPermission(RolePermissions.PAGE, RolePermissions.BIND),\n        label: \"绑定用户\",\n        clickFunc: () => handleDetail(row, \"assign\"),\n      },\n      {\n        label: \"删除\",\n        invisible: row.isDefaultRole || !hasOpPermission(RolePermissions.PAGE, RolePermissions.DELETE),\n        clickFunc: () => onDelete(row),\n      },\n      {\n        label: \"回收用户\",\n        invisible: !hasOpPermission(RolePermissions.PAGE, RolePermissions.RECYCLE),\n        clickFunc: () => handleDetail(row, \"recycle\"),\n      },\n    ];\n  };\n\n  const handleAdd = () => {\n    setFlag(\"create\");\n    setDetailVisible(true);\n  };\n\n  const onDelete = (row: any) => {\n    if (row.authedUserCnt) {\n      const content = (\n        <>\n          <div className=\"mb-20\">要删除角色{row.roleName}吗？</div>\n          <div className=\"mb-20\">角色{row.roleName}已分配给用户，不允许删除，请先解除分配的用户再试！</div>\n        </>\n      );\n      Modal.info({\n        title: \"删除提示\",\n        icon: <ExclamationCircleOutlined />,\n        content,\n        okText: \"确认\",\n        closable: true,\n        width: 500,\n      });\n    } else {\n      Modal.confirm({\n        title: \"删除提示\",\n        icon: <ExclamationCircleOutlined />,\n        content: `要删除角色${row.roleName}吗？`,\n        okText: \"确认\",\n        cancelText: \"取消\",\n        closable: true,\n        onOk: async () => {\n          await deleteRole(row.id);\n          message.success(\"删除成功\");\n          fetchRoleList();\n        },\n      });\n    }\n  };\n\n  const handleDetail = (row, type) => {\n    setFlag(type || \"detail\");\n    setRoleId(row.id);\n    setDetailVisible(true);\n    setRoleName(row.roleName);\n  };\n\n  const closeDetail = () => {\n    setDetailVisible(false);\n  };\n\n  const handleSubmit = (data) => {\n    const formData = {\n      ...data,\n    };\n    for (const key in formData) {\n      if (!formData[key]) {\n        formData[key] = \"\";\n      } else {\n        formData[key] = formData[key].trim();\n      }\n    }\n    setFormData(formData);\n  };\n\n  const onChangePagination = (current: any, pageSize: any) => {\n    fetchRoleList({\n      current,\n      pageSize,\n    });\n  };\n\n  const fetchRoleList = (customPagination: any = {}) => {\n    const { current, pageSize } = pagination;\n    const params = {\n      ...formData,\n      id: formData?.id ? Number(formData?.id) : undefined,\n      page: customPagination.current ?? current,\n      size: customPagination.pageSize ?? pageSize,\n    };\n    setloading(true);\n    Progress.start();\n    queryRoleList(params)\n      .then((res: any) => {\n        Progress.done();\n        setloading(false);\n        setData(res.bizData);\n        setPagination((origin) => {\n          return {\n            ...origin,\n            current: res.pagination.pageNo,\n            pageSize: res.pagination.pageSize,\n            total: res.pagination.total,\n          };\n        });\n      })\n      .finally(() => {\n        Progress.done();\n        setloading(false);\n      });\n  };\n\n  const updateUserPermission = () => {\n    if (flag !== \"update\") return;\n    const userId = getCookie(\"userId\");\n    const userName = getCookie(\"userName\");\n    // 如果当前登录用户属于该角色，需要同步更新权限点\n\n    if (data.find((item) => item.id === roleId)?.authedUsers?.includes(userName)) {\n      getUser(+userId).then((res) => {\n        window.localStorage.setItem(PERMISSION_TREE, JSON.stringify(res.permissionTreeVO?.childList || []));\n        store.dispatch(actions.setUserPermissionTree(res.permissionTreeVO?.childList || []));\n      });\n    }\n  };\n\n  const submitCb = (needClose = true) => {\n    if (needClose) {\n      closeDetail();\n    }\n    fetchRoleList();\n    updateUserPermission();\n  };\n\n  const renderIndex = (value, row, index) => {\n    return `${(pagination.current - 1) * pagination.pageSize + (index + 1)}`;\n  };\n\n  const renderRoleDetail = (value, row) => {\n    return (\n      <a\n        type=\"javascript;\"\n        onClick={() => {\n          handleDetail(row, \"detail\");\n        }}\n      >\n        {value}\n      </a>\n    );\n  };\n\n  const renderUserNum = (value, row) => {\n    return (\n      <div className=\"user-num\">\n        <span className=\"num\">{value}</span>\n      </div>\n    );\n  };\n\n  const renderOptCol = (value: any, row: any) => {\n    const btns = getOperationList(row);\n    return renderTableOpts(btns, row);\n  };\n\n  useEffect(() => {\n    fetchRoleList({ current: 1, pageSize: pagination.pageSize });\n  }, [formData]);\n\n  return (\n    <div className=\"table-layout-style\">\n      <ProTable\n        showQueryForm={true}\n        queryFormProps={{\n          defaultCollapse: true,\n          columns: getFormCol(),\n          // onChange={() => null}\n          onReset: handleSubmit,\n          onSearch: handleSubmit,\n          isResetClearAll: true,\n          initialValues: formData,\n        }}\n        tableProps={{\n          tableId: \"role_manager_table\",\n          isCustomPg: false,\n          loading,\n          rowKey: \"id\",\n          dataSource: data,\n          getOpBtns: getOpBtns,\n          columns: getTableCol(renderIndex, renderRoleDetail, renderUserNum, renderOptCol),\n          paginationProps: { ...pagination, onChange: onChangePagination },\n          customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n          reloadData: fetchRoleList,\n        }}\n      />\n      {detailVisible ? (\n        <Detail\n          flag={flag}\n          detailVisible={detailVisible}\n          setDetailVisible={setDetailVisible}\n          closeDetail={closeDetail}\n          roleId={roleId}\n          submitCb={submitCb}\n          roleName={roleName}\n        />\n      ) : null}\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/RoleManage/service.ts",
    "content": "import { getCookie, getCurrentProject } from \"lib/utils\";\nimport { request, post, put, delete as deleteMethod } from \"knowdesign/lib/utils/request\";\nconst esPrefix = \"/api/es/admin\";\nconst logiPrefix = \"/v3/security\";\nconst rolePrefix = \"/role\";\nconst prefix = `${esPrefix}${logiPrefix}${rolePrefix}`;\n\nconst getHeaders = () => {\n  return {\n    \"X-SSO-USER\": getCookie(\"userName\") || \"\",\n    \"X-SSO-USER-ID\": getCookie(\"userId\") || \"\",\n    \"X-LOGI-SECURITY-PROJECT-ID\": getCurrentProject()?.id || \"\",\n  };\n};\n\n// 分页查询角色列表\nexport const queryRoleList = (params): any => {\n  return post(`${prefix}/page`, params, { headers: getHeaders() });\n};\n\n// 获取角色详情\nexport const queryRoleDetail = (id: any): any => {\n  return request(`${prefix}/${id}`, { headers: getHeaders() });\n};\n\n// 创建角色&&更新角色信息\nexport const createOrUpdateRole = (isCreate: boolean, params: any) => {\n  const reqMethod = isCreate ? post : put;\n  return reqMethod(`${prefix}`, params, { headers: getHeaders() });\n};\n\n// 删除角色\nexport const deleteRole = (id: any) => {\n  return deleteMethod(`${prefix}/${id}`, { headers: getHeaders() });\n};\n\n// 分配角色\nexport const assignRole = (params: any) => {\n  return post(`${prefix}/assign`, params, { headers: getHeaders() });\n};\n\nexport const queryRoleStatus = (id: any): any => {\n  return deleteMethod(`${prefix}/delete/check/${id}`, { headers: getHeaders() });\n};\n\n// 角色管理/分配用户/列表\nexport const queryAssignedUserByRole = (roleId): any => {\n  return request(`${prefix}/assign/${roleId}`, { headers: getHeaders() });\n};\n\nexport const queryPermissionTree = () => {\n  return request(`${esPrefix}${logiPrefix}/permission/tree`, { headers: getHeaders() });\n};\n\n// 获取资源own角色权限树\nexport const getRolePermission = (): any => {\n  return request(`${esPrefix}${logiPrefix}/permission/resource-owner`, { headers: getHeaders() });\n};\n\n// 从角色中删除该角色下的用户\nexport const deleteUserByRoleId = (id: number, userId: number) => {\n  return deleteMethod(`${prefix}/${id}/user/${userId}`, { headers: getHeaders() });\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/UserManage/config.tsx",
    "content": "import * as React from \"react\";\nimport { formatDate } from \"knowdesign/lib/utils/tools\";\nimport { renderAttributes } from \"container/custom-component\";\nimport { Tooltip } from \"antd\";\nexport interface ITableBtn {\n  clickFunc?: () => void;\n  type?: string;\n  customFormItem?: string | JSX.Element;\n  isRouterNav?: boolean;\n  label: string | JSX.Element;\n  className?: string;\n  needConfirm?: boolean;\n  aHref?: string;\n  confirmText?: string;\n  noRefresh?: boolean;\n  loading?: boolean;\n  disabled?: boolean;\n  invisible?: boolean; // 不可见\n}\n\nexport const getFormCol = (deptItem, roleItem) => {\n  return [\n    {\n      type: \"input\",\n      title: \"用户账号:\",\n      dataIndex: \"userName\",\n      placeholder: \"请输入用户账号\",\n      componentProps: {\n        maxLength: 128,\n      },\n    },\n    {\n      type: \"input\",\n      title: \"用户实名:\",\n      dataIndex: \"realName\",\n      placeholder: \"请输入用户实名\",\n      componentProps: {\n        maxLength: 128,\n      },\n    },\n  ];\n};\n\nexport const getFormText: { searchText: string; resetText: string } = {\n  searchText: \"查询\",\n  resetText: \"重置\",\n};\n\nexport const getTableCol = (renderIndex, renderUserNameCol, renderOptCol) => {\n  const columns = [\n    {\n      title: \"序号\",\n      dataIndex: \"index\",\n      key: \"index\",\n      render: renderIndex,\n    },\n    {\n      title: \"用户账号\",\n      dataIndex: \"userName\",\n      key: \"userName\",\n      render: renderUserNameCol,\n    },\n    {\n      title: \"用户实名\",\n      dataIndex: \"realName\",\n      key: \"realName\",\n      render: renderUserNameCol,\n    },\n    {\n      title: \"所属应用\",\n      dataIndex: \"projectList\",\n      key: \"projectList\",\n      render: (list) =>\n        renderAttributes({ data: list?.map((item: any) => item && item.projectName) || [], limit: 2, placement: \"bottomLeft\" }),\n    },\n    {\n      title: \"电话\",\n      dataIndex: \"phone\",\n      key: \"phone\",\n      render: (text: string) => {\n        return <>{text || \"-\"}</>;\n      },\n    },\n    {\n      title: \"邮箱\",\n      dataIndex: \"email\",\n      key: \"email\",\n      render: (text: string) => {\n        return <>{text || \"-\"}</>;\n      },\n    },\n    {\n      title: \"分配角色\",\n      dataIndex: \"roleList\",\n      key: \"roleList\",\n      render: (value: any) =>\n        renderAttributes({ data: value?.map((item: any) => item && item.roleName) || [], limit: 2, placement: \"bottomLeft\" }),\n    },\n    {\n      title: \"最后更新时间\",\n      dataIndex: \"updateTime\",\n      key: \"updateTime\",\n      render: (value) => {\n        return formatDate(value, \"YYYY-MM-DD HH:mm:ss\");\n      },\n    },\n    {\n      title: \"操作\",\n      dataIndex: \"operation\",\n      filterTitle: true,\n      key: \"operation\",\n      width: 150,\n      render: renderOptCol,\n    },\n  ];\n  return columns;\n};\n\nconst columnsRender = (item: string, maxWidth) => {\n  return (\n    <Tooltip placement=\"right\" title={item}>\n      <div\n        className=\"row-ellipsis\"\n        style={{\n          maxWidth,\n          display: \"inline-block\",\n        }}\n      >\n        {item || (typeof item === \"number\" ? item : \"-\")}\n      </div>\n    </Tooltip>\n  );\n};\n\nexport const readableForm = [\n  {\n    flag: [\"detail\", \"update\"],\n    label: \"已选用户\",\n    prop: [\"userName\", \"realName\"],\n    readText: \"\",\n  },\n  {\n    flag: [\"detail\"],\n    label: \"密码\",\n    prop: \"password\",\n    readText: \"\",\n    render: (text) => text || \"-\",\n  },\n  {\n    flag: [\"detail\", \"update\"],\n    label: \"所属应用\",\n    prop: \"projectList\",\n    readText: \"\",\n    render: (list) => {\n      return columnsRender(list?.map((item: any) => item && item.projectName)?.join(\"；\") || \"-\", \"180px\");\n      // return renderAttributes({ data: list?.map((item: any) => item && item.projectName) || [], limit: 2, placement: \"bottomLeft\" });\n    },\n  },\n  {\n    flag: [\"detail\"],\n    label: \"绑定角色\",\n    prop: \"roleList\",\n    readText: \"\",\n    render: (list) => {\n      return columnsRender(list?.map((item: any) => item && item.roleName)?.join(\"；\") || \"-\", \"210px\");\n      // return renderAttributes({ data: list?.map((item: any) => item && item.roleName) || [], limit: 6, placement: \"bottomLeft\" });\n    },\n  },\n];\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/UserManage/detail.less",
    "content": ".user-manage-detail {\n  .user-tpl-form {\n    padding: 20px;\n\n    &-readonlyText {\n      display: flex;\n      margin-top: 12px;\n\n      .read-lable {\n        flex-shrink: 0;\n      }\n    }\n\n    &-formitem {\n      margin-top: 20px !important;\n      margin-bottom: 0px !important;\n    }\n\n    &-first-formitem {\n      margin-bottom: 0px !important;\n    }\n  }\n\n  .ant-transfer {\n    height: 100%;\n  }\n\n  .ant-transfer-list {\n    width: 100%;\n    height: 100%;\n    border-radius: 4px;\n  }\n\n  .ant-transfer-list-header-title {\n    font-weight: bolder;\n  }\n\n  .bind-row-item {\n    height: 24px;\n    margin-right: 7px;\n    padding: 0 3px;\n    background: #f8fafd;\n    color: #303a51;\n    border: 1px solid #eaeef5;\n    border-radius: 1px;\n  }\n\n  .bind-role-title {\n    margin-top: 16px;\n    margin-bottom: 12px;\n    font-size: 14px;\n    font-weight: bolder;\n    color: #303a51;\n  }\n\n  .bind-role-table {\n    width: 100%;\n    border: 1px solid #dcdfe6;\n    border-radius: 4px;\n    border-collapse: collapse;\n    display: table;\n    border-style: hidden;\n    box-shadow: 0 0 0 1px #dcdfe6;\n\n    .tr {\n      display: table-row;\n\n      .td {\n        display: table-cell;\n        line-height: 40px;\n        padding: 0 20px;\n        vertical-align: top;\n        border: 1px solid #dcdfe6;\n        position: relative;\n        text-align: left;\n      }\n    }\n\n    .tHead {\n      font-weight: bold;\n      height: 40px;\n      line-height: 40px;\n      color: #303a51;\n      background: #f5f7fa;\n\n      >div:first-child {\n        width: 157px;\n        border-top-left-radius: 4px;\n      }\n\n      >div:last-child {\n        // width: 482px;\n        border-top-right-radius: 4px;\n      }\n    }\n\n    .tBody {\n      .col-permission {\n        display: flex;\n\n        .permission-all {}\n\n        .permission-content {\n          flex: 1;\n          display: flex;\n          flex-wrap: wrap;\n          padding-top: 10px;\n\n          .content-item {\n            margin-top: -10px;\n            padding-left: 16px;\n          }\n        }\n      }\n    }\n\n    .empty-item {\n      position: relative;\n      display: table-row;\n      height: 80px;\n      line-height: 80px;\n\n      span {\n        position: absolute;\n        top: 50%;\n        left: 50%;\n        transform: translate(-50%, -50%);\n      }\n    }\n  }\n}\n\n.custom-desc {\n  &.no-alert {\n    margin-top: 20px;\n  }\n}\n\n.detail-alert {\n  border: none;\n  position: absolute;\n  top: 55px;\n  width: 100%;\n  transform: translate(-24px, 0px);\n\n  .ant-alert-message {\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: #374053;\n    line-height: 20px;\n  }\n\n  .ant-alert-icon {\n    font-size: 17px;\n  }\n}"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/UserManage/detail.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { Button, message, Drawer, Col, Transfer, Descriptions, Alert } from \"antd\";\nimport { readableForm } from \"./config\";\nimport { queryUserDetail, queryAssignedRoleByUser, assignRoleToUser } from \"./service\";\n\nimport \"./detail.less\";\nimport PermissionTree from \"../RoleManage/PermissionTree\";\nenum Eflag {\n  detail = \"用户详情\",\n  update = \"分配角色\",\n}\nexport default function Detail(props: any) {\n  const { detailVisible, flag, setDetailVisible, submitCb, userId } = props;\n  const [curretFlag, setCurretFlag] = useState(flag);\n\n  const [visible, setVisible] = useState(detailVisible);\n  const [roleList, setRoleList] = useState([]);\n  const [submitLoading, setSubmitLoading] = useState(false);\n  const [submitDisabled, setSubmitDisabled] = useState(true);\n  const [initialTargetKeys, setInitialTargetKeys] = useState([]);\n  const [targetKeys, setTargetKeys] = useState(initialTargetKeys);\n  const [selectedKeys, setSelectedKeys] = useState([]);\n  const [permissionVo, setPermissionVo] = useState([]);\n  const [loading, setLoading] = useState(true);\n  const [formModel, setFormModel] = useState({\n    deptList: [],\n    roleList: [],\n  });\n\n  useEffect(() => {\n    setCurretFlag(curretFlag);\n  }, [flag]);\n\n  const onSubmit = () => {\n    const params = {\n      id: userId,\n      flag: true, // true：N个角色分配给1个用户、false：1个角色分配给N个用户\n      idList: targetKeys,\n    };\n    setSubmitLoading(true);\n    assignRoleToUser(params)\n      .then(() => {\n        message.success(\"提交成功\");\n        submitCb();\n      })\n      .finally(() => {\n        setSubmitLoading(false);\n      });\n  };\n\n  const onClose = () => {\n    setDetailVisible(false);\n  };\n\n  const fetchDetail = async (userId) => {\n    setLoading(true);\n    try {\n      const data = await queryUserDetail(userId);\n      const { permissionTreeVO } = data;\n      const permissionVoData = permissionTreeVO.childList.map((item) => {\n        return {\n          ...item,\n          isCheckAll: item.childList.every((subItem) => subItem.has),\n        };\n      });\n      setPermissionVo(permissionVoData);\n      setFormModel(data);\n      setLoading(false);\n    } catch (err) {\n      setLoading(false);\n    }\n  };\n\n  const fetchRoleList = async (name?: string) => {\n    const res: any = await queryAssignedRoleByUser(userId, name);\n    const assignedRoles = res.filter((item) => item.has).map((item) => item.id);\n    setInitialTargetKeys(assignedRoles);\n    setRoleList(res);\n  };\n\n  const renderReadCol = () => {\n    const data = {\n      ...formModel,\n    };\n    const formCol = readableForm.filter((item) => item.flag.includes(curretFlag));\n    const hasAlert = curretFlag === \"detail\" && !loading && permissionVo.every((item) => !item.has);\n    return (\n      <Descriptions className={`custom-desc ${hasAlert ? \"\" : \"no-alert\"}`} title=\"\" column={2}>\n        {formCol.map((row, index) => (\n          <Descriptions.Item className=\"read-lable\" label={row.label} key={index}>\n            <span className=\"read-content\">\n              {Array.isArray(row.prop)\n                ? row.prop.length > 0 && row.prop.map((k) => data[k]).join(\"/\")\n                : row.render\n                ? row.render(data?.[row.prop])\n                : data[row.prop]}\n            </span>\n          </Descriptions.Item>\n        ))}\n      </Descriptions>\n    );\n  };\n\n  const renderAlert = () => {\n    return curretFlag === \"detail\" && !loading && permissionVo.every((item) => !item.has) ? (\n      <>\n        <Alert\n          className=\"detail-alert\"\n          showIcon\n          message={\n            <span>\n              当前用户未分配角色，无任何权限，如需分配，请点击：{\" \"}\n              <a type=\"javascript;\" onClick={() => setCurretFlag(\"update\")}>\n                分配角色\n              </a>\n            </span>\n          }\n          type=\"info\"\n        />\n        <div style={{ height: 40 }}></div>\n      </>\n    ) : null;\n  };\n\n  const renderContent = () => {\n    const permissionData = permissionVo.filter((item) => item.has);\n    return <PermissionTree isEdit={false} permissionData={permissionData} />;\n  };\n\n  const renderPermission = () => {\n    return (\n      <>\n        {curretFlag === \"detail\" ? <h4 className=\"bind-role-title\"></h4> : null}\n        {curretFlag === \"detail\" && permissionVo.every((item) => !item.has) ? null : renderContent()}\n      </>\n    );\n  };\n\n  const renderFooter = () => {\n    return (\n      <div\n        style={{\n          textAlign: \"left\",\n        }}\n      >\n        {curretFlag === \"detail\" ? (\n          <Button onClick={onClose} type=\"primary\">\n            关闭\n          </Button>\n        ) : (\n          <Button disabled={submitDisabled} loading={submitLoading} onClick={onSubmit} type=\"primary\">\n            保存\n          </Button>\n        )}\n      </div>\n    );\n  };\n\n  const isEqualArray = (originArr, updateArr) => {\n    return originArr.length === updateArr.length && originArr.every((item) => updateArr.includes(item));\n  };\n\n  const onChange = (nextTargetKeys, direction, moveKeys) => {\n    setSubmitDisabled(isEqualArray(nextTargetKeys, initialTargetKeys) || nextTargetKeys.length < 1);\n    setTargetKeys(nextTargetKeys);\n  };\n\n  const onSelectChange = (sourceSelectedKeys, targetSelectedKeys) => {\n    setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);\n  };\n\n  const onSearch = (dir, value) => {\n    console.log(dir, value);\n  };\n\n  const renderTransfer = () => {\n    return (\n      <div style={{ width: \"100%\", height: \"600px\", marginTop: \"24px\" }}>\n        <Transfer\n          dataSource={roleList}\n          titles={[\"未分配角色\", \"已分配角色\"]}\n          targetKeys={targetKeys}\n          selectedKeys={selectedKeys}\n          showSearch={true}\n          onChange={onChange}\n          onSearch={onSearch}\n          onSelectChange={onSelectChange}\n          rowKey={(record) => record.id}\n          render={(record) => record.name}\n        />\n      </div>\n    );\n  };\n\n  useEffect(() => {\n    setVisible(detailVisible);\n  }, [detailVisible]);\n\n  useEffect(() => {\n    fetchDetail(userId);\n    fetchRoleList();\n  }, []);\n\n  useEffect(() => {\n    setTargetKeys(initialTargetKeys);\n  }, [initialTargetKeys]);\n\n  return (\n    <Drawer\n      className=\"user-manage-detail\"\n      width=\"640\"\n      title={Eflag[curretFlag] || \"\"}\n      onClose={onClose}\n      visible={visible}\n      footer={renderFooter()}\n    >\n      {renderAlert()}\n      {renderReadCol()}\n      {curretFlag === \"detail\" ? renderPermission() : renderTransfer()}\n    </Drawer>\n  );\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/UserManage/index.less",
    "content": ".user-manage {\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/UserManage/index.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { getTableCol, getFormCol, getFormText } from \"./config\";\nimport { DTable } from \"../../dantd/DTable\";\nimport { RenderTitle } from \"../RenderTitle\";\nimport QueryForm from \"../../ProForm/QueryForm\";\nimport { queryUserList, queryDeptTreeData, queryRoleListByName, deleteUser } from \"./service\";\nimport { Modal, TreeSelect, message } from \"antd\";\nimport { renderTableOpts } from \"../../ProTable/RenderTableOpts\";\nimport Detail from \"./detail\";\nconst { TreeNode } = TreeSelect;\nimport Progress from \"../../CommonComponents/ProgressBar\";\nimport { hasOpPermission } from \"lib/permission\";\nimport { UserPermissions } from \"constants/permission\";\nimport { ProTable } from \"knowdesign\";\n\nexport const UserManage = () => {\n  const [flag, setFlag] = useState(\"\");\n  const [detailVisible, setDetailVisible] = useState(false);\n  const [loading, setloading] = useState(false);\n  const [deptList, setDeptList] = useState([]);\n  const [roleList, setRoleList] = useState([]);\n  const [formData, setFormData] = useState({});\n\n  const [pagination, setPagination] = useState({\n    current: 1,\n    pageSize: 10,\n    position: \"bottomRight\",\n    showQuickJumper: true,\n    showSizeChanger: true,\n    pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n    showTotal: (total: number) => `共 ${total} 条`,\n  });\n\n  const [userId, setUserId] = useState();\n  const [data, setData] = useState([]);\n  const getOperationList = (row: any) => {\n    return [\n      {\n        invisible: !hasOpPermission(UserPermissions.PAGE, UserPermissions.ASSGIN),\n        label: \"分配角色\",\n        clickFunc: () => {\n          handleAssignRole(row);\n        },\n      },\n      {\n        invisible: !hasOpPermission(UserPermissions.PAGE, UserPermissions.ASSGIN),\n        label: \"删除\",\n        clickFunc: () => {\n          if (row.singleOwnerOfProjects?.length) {\n            return Modal.info({\n              title: \"提示\",\n              content: (\n                <>\n                  <div>此用户是以下应用的唯一责任人，删除用户前需下线应用：</div>\n                  <div>{row.singleOwnerOfProjects.join(\"、\")}</div>\n                </>\n              ),\n            });\n          }\n          Modal.confirm({\n            title: \"提示\",\n            content: row.ownProjects?.length ? (\n              <>\n                <div>用户是以下应用的责任人，是否确定删除？</div>\n                <div>{row.ownProjects.join(\"、\")}</div>\n              </>\n            ) : (\n              `确认删除${row.userName || \"\"}`\n            ),\n            onOk: () => {\n              deleteUser(row.id).then(() => {\n                message.success(\"删除成功\");\n                fetchUserList();\n              });\n            },\n          });\n        },\n      },\n    ];\n  };\n\n  const renderIndex = (value, row, index) => {\n    return `${(pagination.current - 1) * pagination.pageSize + (index + 1)}`;\n  };\n\n  const renderUserNameCol = (value, row) => {\n    if (!value) return \"-\";\n    return (\n      <a\n        type=\"javascript;\"\n        onClick={() => {\n          handleDetail(row);\n        }}\n      >\n        {value}\n      </a>\n    );\n  };\n\n  const renderOptCol = (value: any, row: any) => {\n    const btns = getOperationList(row);\n    return renderTableOpts(btns, row);\n  };\n\n  const handleAssignRole = (row) => {\n    setFlag(\"update\");\n    setDetailVisible(true);\n    setUserId(row.id);\n  };\n\n  const fetchUserList = (customPagination: any = {}) => {\n    const { current, pageSize } = pagination;\n    const params = {\n      ...formData,\n      page: customPagination.current ?? current,\n      size: customPagination.pageSize ?? pageSize,\n    };\n    Progress.start();\n    setloading(true);\n    queryUserList(params)\n      .then((res: any) => {\n        if (res) {\n          Progress.done();\n          setData(res.bizData);\n          setPagination((origin) => {\n            return {\n              ...origin,\n              current: res.pagination.pageNo,\n              pageSize: res.pagination.pageSize,\n              total: res.pagination.total,\n            };\n          });\n        }\n      })\n      .finally(() => {\n        Progress.done();\n        setloading(false);\n      });\n  };\n\n  const fetchDeptList = async (val?) => {\n    const res = await queryDeptTreeData(val);\n    setDeptList(res.childList);\n  };\n\n  const fetchRoleList = async (val?) => {\n    const res: any = await queryRoleListByName(val);\n    const roleList = res.map((item) => ({ value: item.id, title: item.roleName }));\n    setRoleList(roleList);\n  };\n\n  const renderRoleItem = () => {\n    const roleItem = {\n      options: roleList,\n      componentProps: {\n        // onSearch: debounce(fetchRoleList, 1000),\n      },\n    };\n    return roleItem;\n  };\n\n  const renderDeptTree = (list) => {\n    return (\n      list.length > 0 &&\n      list.map((item: any) => (\n        <TreeNode key={item.id} value={item.id} title={item.deptName}>\n          {item.childList && item.childList.length > 0 && renderDeptTree(item.childList)}\n        </TreeNode>\n      ))\n    );\n  };\n\n  const renderDeptItem = () => {\n    const deptItem = {\n      component: (\n        <TreeSelect\n          showSearch\n          style={{ width: \"100%\" }}\n          treeNodeFilterProp=\"title\"\n          dropdownStyle={{ maxHeight: 400, overflow: \"auto\" }}\n          placeholder=\"请选择使用部门\"\n          allowClear\n        >\n          {renderDeptTree(deptList)}\n        </TreeSelect>\n      ),\n    };\n    return deptItem;\n  };\n\n  useEffect(() => {\n    renderRoleItem();\n  }, [roleList]);\n\n  useEffect(() => {\n    renderDeptItem();\n  }, [deptList]);\n\n  const renderTitleContent = () => {\n    return {\n      title: \"用户管理\",\n      content: null,\n    };\n  };\n\n  const handleDetail = (row) => {\n    setFlag(\"detail\");\n    setUserId(row.id);\n    setDetailVisible(true);\n  };\n\n  const closeDetail = () => {\n    setDetailVisible(false);\n  };\n\n  const handleSubmit = (data) => {\n    const formData = {\n      ...data,\n    };\n    for (const key in formData) {\n      if (!formData[key]) {\n        formData[key] = undefined;\n      } else {\n        formData[key] = formData[key].trim();\n      }\n    }\n    setFormData(formData);\n  };\n\n  const onChangePagination = (current: any, pageSize: any) => {\n    fetchUserList({\n      current,\n      pageSize,\n    });\n  };\n\n  const submitCb = () => {\n    closeDetail();\n    fetchUserList();\n  };\n\n  React.useEffect(() => {\n    fetchUserList({ current: 1, pageSize: pagination.pageSize });\n  }, [formData]);\n\n  return (\n    <div className=\"table-layout-style\">\n      <ProTable\n        showQueryForm={true}\n        queryFormProps={{\n          defaultCollapse: true,\n          columns: getFormCol(renderDeptItem(), renderRoleItem()),\n          // onChange={() => null}\n          onReset: handleSubmit,\n          onSearch: handleSubmit,\n          isResetClearAll: true,\n          initialValues: formData,\n        }}\n        tableProps={{\n          tableId: \"user_manager_table\",\n          isCustomPg: false,\n          loading,\n          rowKey: \"id\",\n          dataSource: data,\n          columns: getTableCol(renderIndex, renderUserNameCol, renderOptCol),\n          paginationProps: { ...pagination, onChange: onChangePagination },\n          customRenderSearch: () => <RenderTitle {...renderTitleContent()} />,\n        }}\n      />\n      {detailVisible ? (\n        <Detail\n          flag={flag}\n          detailVisible={detailVisible}\n          closeDetail={closeDetail}\n          setDetailVisible={setDetailVisible}\n          userId={userId}\n          submitCb={submitCb}\n        />\n      ) : null}\n    </div>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/CommonPages/UserManage/service.ts",
    "content": "import { getCookie } from \"knowdesign/lib/utils/tools\";\nimport { request, post } from \"knowdesign/lib/utils/request\";\nimport { getCurrentProject } from \"../../../lib/utils\";\nconst prefix = `/api/es/admin/v3/security`;\n\nconst getHeaders = () => {\n  return {\n    \"X-SSO-USER\": getCookie(\"userName\") || \"\",\n    \"X-SSO-USER-ID\": getCookie(\"userId\") || \"\",\n    \"X-LOGI-SECURITY-PROJECT-ID\": getCurrentProject()?.id || \"\",\n  };\n};\n\nexport const queryUserList = (params): any => {\n  return post(`${prefix}/user/page`, params, { headers: getHeaders() });\n};\n\nexport const queryRoleListByName = (roleName = \"\") => {\n  return request(`${prefix}/role/list/${roleName ? \"?roleName=\" + roleName : \"\"}`, { headers: getHeaders() });\n};\n\nexport const queryAssignedRoleByUser = (userId: number, roleName = \"\"): any => {\n  return request(`${prefix}/user/assign/${userId}/${roleName}`, { headers: getHeaders() });\n};\n\nexport const queryUserDetail = (id): any => {\n  return request(`${prefix}/user/${id}`, { headers: getHeaders() });\n};\n\nexport const assignRoleToUser = (params: any): any => {\n  console.log();\n  return post(`${prefix}/role/assign`, params, { headers: getHeaders() });\n};\n\nexport const queryDeptTreeData = (val): any => {\n  return request(`${prefix}/dept/tree`, { headers: getHeaders() });\n};\n\nexport const deleteUser = (id): any => {\n  return request(`${prefix}/user/${id}`, { headers: getHeaders(), method: \"DELETE\" });\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/GlobalStore.js",
    "content": "import { createContext } from \"react\";\r\nconst GlobalStore = createContext({});\r\nexport default GlobalStore;\r\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/CustomProjectSelect/index.less",
    "content": "@header-text-color: rgba(0, 0, 0, 0.87);\n.dropdown-text {\n  color: @header-text-color;\n\n  &:hover {\n    color: rgba(0, 0, 0, 1);\n  }\n  .text {\n    margin-left: 5px;\n    font-size: 14px;\n  }\n  .select-icon {\n    top: 0;\n  }\n  .icon {\n    font-size: 20px;\n  }\n}\n\n.app-wrapper {\n  top: 30px !important;\n  .ant-dropdown-arrow {\n    top: 8px !important;\n  }\n  .project-select {\n    width: 216px;\n    height: 246px;\n    background: #fff;\n    border-radius: 5px;\n    box-shadow: 0 -2px 4px 0 rgb(0 0 0 / 2%), 0 2px 6px 6px rgb(0 0 0 / 2%), 0 2px 6px 0 rgb(0 0 0 / 6%);\n    .ant-input-affix-wrapper {\n      position: relative;\n      border-radius: 4px;\n      width: 200px;\n      height: 30px;\n      margin: 8px;\n      .ant-input-prefix {\n        position: absolute;\n        right: 7px;\n        top: 9px;\n      }\n      .ant-input {\n        margin-right: 20px;\n      }\n    }\n    .hasclear {\n      .ant-input-prefix {\n        right: 27px;\n      }\n    }\n    .project-list {\n      margin-top: 4px;\n      height: 195px;\n      overflow: auto;\n      li {\n        text-align: left;\n        height: 32px;\n        line-height: 32px;\n        padding-left: 16px;\n        font-family: PingFangSC-Regular;\n        font-size: 12px;\n        letter-spacing: 0;\n        color: #303a51;\n        cursor: pointer;\n        &:hover {\n          background: rgba(0, 0, 0, 0.04);\n        }\n      }\n      .active {\n        background: #f1f7ff !important;\n        color: #1473ff;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/CustomProjectSelect/index.tsx",
    "content": "import { Dropdown, Input, Tooltip } from \"antd\";\nimport React, { useState } from \"react\";\nimport \"./index.less\";\n\nexport interface IProject {\n  id: number;\n  memo: string;\n  name: string;\n}\n\ninterface IProjectDropDown {\n  list: IProject[];\n  currentProject: IProject;\n  onChange: (newProject: IProject) => void;\n  setVisible?: (visible: boolean) => void;\n}\n\nexport const CustomAppDropDown = (props: {\n  currentProject: IProject;\n  projectList: IProject[];\n  setCurrentProject: (newProject: IProject) => void;\n}) => {\n  const [visible, setVisible] = useState(false);\n\n  const { currentProject, projectList = [], setCurrentProject } = props;\n\n  const handleVisibleChange = (newVisible: boolean) => {\n    setVisible(newVisible);\n  };\n\n  return (\n    <>\n      {currentProject?.name ? (\n        <>\n          <Dropdown\n            visible={visible}\n            key=\"2\"\n            arrow\n            overlayClassName=\"app-wrapper\"\n            onVisibleChange={handleVisibleChange}\n            overlay={\n              <ProjectSelect\n                onChange={(val) => {\n                  setCurrentProject(val);\n                  setVisible(false);\n                }}\n                list={projectList}\n                currentProject={currentProject}\n              />\n            }\n            trigger={[\"click\"]}\n            placement=\"bottomCenter\"\n          >\n            <span className=\"dropdown-content\">\n              <a className=\"dropdown-text\">\n                <span className={`icon iconfont iconyingyong`}></span>\n                <span className=\"text\">\n                  {currentProject?.name?.length > 20 ? (\n                    <Tooltip title={currentProject?.name}>{currentProject?.name?.slice(0, 18) + \"...\"}</Tooltip>\n                  ) : (\n                    currentProject?.name\n                  )}\n                </span>\n                <div className={`select-icon`}>\n                  <span className={`icon iconfont iconRight`}></span>\n                </div>\n              </a>\n            </span>\n          </Dropdown>\n        </>\n      ) : (\n        \"\"\n      )}\n    </>\n  );\n};\n\nclass ProjectSelect extends React.Component<IProjectDropDown> {\n  public state = {\n    list: this.props.list || ([] as IProject[]),\n    isSearch: false,\n  };\n\n  public onHandleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n    const { value } = e.target;\n    const originList = this.props.list || [];\n    const list = value?.trim()\n      ? originList.filter((item) => item.name.includes(value?.trim()) || (item.id + \"\").includes(value?.trim()))\n      : originList;\n    this.setState({\n      list,\n      isSearch: value ? true : false,\n    });\n  };\n\n  public switchProjectId = (item: IProject) => {\n    this.props.onChange && this.props.onChange(item);\n  };\n\n  public render() {\n    const { list, isSearch } = this.state;\n    const { currentProject } = this.props;\n    return (\n      <div className=\"project-select\">\n        <Input\n          className={isSearch ? \"hasclear\" : \"\"}\n          allowClear\n          onChange={this.onHandleInputChange}\n          placeholder=\"请输入应用名称或应用ID\"\n          prefix={\n            <svg className=\"icon svg-icon\" aria-hidden=\"true\">\n              <use xlinkHref=\"#icontubiao-sousuo\"></use>\n            </svg>\n          }\n        />\n        <ul className=\"project-list\">\n          {isSearch && !list.length ? <li>无匹配结果</li> : null}\n          {!isSearch && !list.length ? <li>无应用</li> : null}\n          {list.map((item, index) => (\n            <li key={index} className={currentProject?.id === item.id ? \"active\" : \"\"} onClick={() => this.switchProjectId(item)}>\n              <span>\n                {item.name}({item.id})\n              </span>\n            </li>\n          ))}\n        </ul>\n      </div>\n    );\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/HeaderConditionComponent.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { Dropdown, Menu, Divider, Popover, Drawer, Select, Input } from \"knowdesign\";\nimport _ from \"lodash\";\nimport { FormattedMessage } from \"react-intl\";\nimport { prefixCls } from \"./config\";\nimport { MsgPanel } from \"./MsgPanel\";\nimport ProjectSelect from \"./ProjectSelect\";\nimport { CustomAppDropDown } from \"./CustomProjectSelect\";\nimport UseCenter from \"./UseCenter\";\nimport { isSuperApp, getCookie } from \"lib/utils\";\nimport { getUser } from \"api/logi-security\";\nimport \"./index.less\";\n\nconst HeaderConditionComponent = (params: any, index: number, props: any) => {\n  const cPrefixCls = `${prefixCls}-layout`;\n  const { setLeftIndex, leftIndex, setHeaderClick, history } = props;\n\n  const [visible, setVisible] = useState(false);\n  const [fullScreen, setFullScreen] = useState(false);\n  const [userInfo, setUserInfo] = React.useState({} as any);\n  const [trigger, setTrigger] = React.useState([\"click\"] as Array<\"click\" | \"hover\" | \"contextMenu\">);\n\n  React.useEffect(() => {\n    params.scene === \"user\" && getData();\n  }, []);\n\n  React.useEffect(() => {\n    visible && getData();\n  }, [visible]);\n\n  const getData = () => {\n    if (!getCookie(\"userId\")) return;\n    getUser(+getCookie(\"userId\")).then((res) => {\n      setUserInfo(res || {});\n    });\n  };\n\n  const toggleFullscreen = () => {\n    const docu = document as any;\n    if (!docu.fullscreenElement && /* alternative standard method */ !docu.mozFullScreenElement && !docu.webkitFullscreenElement) {\n      if (docu.documentElement.requestFullscreen) {\n        docu.documentElement.requestFullscreen();\n      } else if (docu.documentElement.mozRequestFullScreen) {\n        docu.documentElement.mozRequestFullScreen();\n      } else if (docu.documentElement.webkitRequestFullscreen) {\n        docu.documentElement.webkitRequestFullscreen((Element as any).ALLOW_KEYBOARD_INPUT);\n      }\n    } else {\n      if (docu.cancelFullScreen) {\n        docu.cancelFullScreen();\n      } else if (docu.mozCancelFullScreen) {\n        docu.mozCancelFullScreen();\n      } else if (docu.webkitCancelFullScreen) {\n        docu.webkitCancelFullScreen();\n      }\n    }\n  };\n  function escFullScreen() {\n    setFullScreen((fullScreen) => !fullScreen);\n  }\n  useEffect(() => {\n    // 监听退出全屏事件 --- chrome 用 esc 退出全屏并不会触发 keyup 事件\n    document.addEventListener(\"webkitfullscreenchange\", escFullScreen); /* Chrome, Safari and Opera */\n    document.addEventListener(\"mozfullscreenchange\", escFullScreen); /* Firefox */\n    document.addEventListener(\"fullscreenchange\", escFullScreen); /* Standard syntax */\n    document.addEventListener(\"msfullscreenchange\", escFullScreen); /* IE / Edge */\n    return () => {\n      //销毁时清除监听\n      document.removeEventListener(\"webkitfullscreenchange\", escFullScreen);\n      document.removeEventListener(\"mozfullscreenchange\", escFullScreen);\n      document.removeEventListener(\"fullscreenchange\", escFullScreen);\n      document.removeEventListener(\"MSFullscreenChange\", escFullScreen);\n    };\n  }, []);\n\n  // 消息通知\n  const componentMsg = (item) => {\n    return (\n      <Dropdown placement=\"bottomRight\" overlay={<MsgPanel />} trigger={[\"hover\"]} key={index}>\n        <svg className={`${prefixCls}-layout-menus-icon`} aria-hidden=\"true\">\n          <use xlinkHref={item.icon}></use>\n        </svg>\n      </Dropdown>\n    );\n  };\n\n  // 项目下拉\n  const componentProjectSelect = () => {\n    return (\n      <ProjectSelect key={index} value={props.currentProject} onProjectChange={(value)=> props.setCurrentProject(value, { history })} projectList={props.projectList} />\n    );\n  };\n\n  //项目drop\n  const componentProjectDrop = () => {\n    return (\n      <CustomAppDropDown\n        key={index}\n        setCurrentProject={(value)=>props.setCurrentProject(value, { history })}\n        projectList={props.projectList}\n        currentProject={props.currentProject}\n      />\n    );\n  };\n\n  // 全屏显示\n  const componentFullscreen = () => {\n    return (\n      <span key={index} className={`icon iconfont ${fullScreen ? \"icon-tuichuquanju\" : \"icon-quanju1\"}`} onClick={toggleFullscreen}></span>\n    );\n  };\n\n  // 个人信息\n  const componentUserCenter = () => {\n    const handleVisibleChange = (newVisible: boolean) => {\n      setVisible(newVisible);\n    };\n    const close = () => {\n      setVisible(false);\n    };\n\n    return (\n      <span className={`${cPrefixCls}-username`} key={index}>\n        <Dropdown\n          visible={visible}\n          onVisibleChange={handleVisibleChange}\n          arrow\n          placement=\"bottomRight\"\n          overlay={<UseCenter userInfo={userInfo} getData={getData} logout={props.logout} close={close} />}\n          trigger={trigger}\n          overlayClassName=\"user-wrapper dcloud-dropdown dcloud-dropdown-show-arrow dcloud-dropdown-placement-bottomRight\"\n        >\n          <div className=\"user-trigger\">\n            <div className=\"user-icon\">\n              <span className={`icon iconfont icontouxiang`}></span>\n            </div>\n            <span>Hi,{userInfo?.userName || \"-\"}</span>\n          </div>\n        </Dropdown>\n      </span>\n    );\n  };\n\n  const renderInput = () => {\n    return <Input allowClear key={index} {...params.componentProps} />;\n  };\n\n  const renderDivider = () => {\n    return <Divider key={index} className={`${cPrefixCls}-header-right-divider`} type=\"vertical\" />;\n  };\n\n  const renderDropdown = () => {\n    if (params.scene === \"user\") {\n      return componentUserCenter();\n    }\n    if (params.scene === \"project\") {\n      return componentProjectDrop();\n    }\n    if (params.scene === \"admin\") {\n      return renderAdmin();\n    }\n    return (\n      <Dropdown placement=\"bottomRight\" overlay={params.overlay} key=\"other\">\n        {params.content}\n      </Dropdown>\n    );\n  };\n\n  const renderSelect = () => {\n    if (params.scene === \"project\") {\n      return componentProjectSelect;\n    }\n    return (\n      <Select allowClear={true} placeholder=\"请选择\" key={index}>\n        {params.options.map((item, index) => {\n          return (\n            <Select.Option key={item.value} value={item.value}>\n              {item.name}\n            </Select.Option>\n          );\n        })}\n      </Select>\n    );\n  };\n\n  const renderLink = () => {\n    return (\n      <div className={`${cPrefixCls}-header-right-links`} key={index}>\n        {params.options.map((item: { icon: string | undefined; href: string; text: string }, index: number) => {\n          return item.icon ? (\n            <a href={item.href} key={index}>\n              <Popover content={item.text}>\n                <svg className={`${cPrefixCls}-header-menus-icon`} aria-hidden=\"true\">\n                  <use xlinkHref={item.icon}></use>\n                </svg>\n              </Popover>\n            </a>\n          ) : (\n            <a href={item.href} key={index}>\n              {item.text}\n            </a>\n          );\n        })}\n      </div>\n    );\n  };\n\n  const renderIcon = () => {\n    if (params.scene === \"fullscreen\") {\n      return componentFullscreen();\n    }\n    return (\n      <div className={`${cPrefixCls}-header-right-icons`} key={index}>\n        {params.options?.map((item: { icon: string; scene: string }, index: number) => {\n          return item.scene == \"msg\" ? (\n            componentMsg(item)\n          ) : (\n            <svg className={`${prefixCls}-layout-menus-icon`} aria-hidden=\"true\" key={index}>\n              <use xlinkHref={item.icon}></use>\n            </svg>\n          );\n        })}\n      </div>\n    );\n  };\n\n  const renderAdmin = () => {\n    // if (!isSuperApp()) return;\n    let menu = (\n      <ul className=\"admin-select\">\n        {params?.children.map((item, index) => (\n          <li\n            key={index}\n            className={item.key === leftIndex ? \"active\" : \"\"}\n            onClick={() => {\n              setLeftIndex(item.key);\n              setHeaderClick(item.key, { history });\n            }}\n          >\n            <span className={`icon iconfont ${item.icon}`}></span>\n            <span>{item.label}</span>\n          </li>\n        ))}\n      </ul>\n    );\n    return (\n      <Dropdown key=\"admin-dropdown\" arrow placement=\"bottomCenter\" overlay={menu} trigger={[\"click\"]} overlayClassName=\"admin-wrapper\">\n        <div className=\"admin-container\">\n          <span className={`icon iconfont ${params?.children?.[leftIndex]?.icon}`}></span>\n          <span>{params?.children?.[leftIndex]?.label}</span>\n          <div className={`select-icon`}>\n            <span className={`icon iconfont iconRight`}></span>\n          </div>\n        </div>\n      </Dropdown>\n    );\n  };\n\n  const headerConditionMap = {\n    input: renderInput,\n    select: renderSelect,\n    dropdown: renderDropdown,\n    link: renderLink,\n    icon: renderIcon,\n    divider: renderDivider,\n  };\n\n  return headerConditionMap[params.type]();\n};\n\nexport default HeaderConditionComponent;\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/LeftMenu.tsx",
    "content": "import React from \"react\";\nimport { withRouter, RouteComponentProps } from \"react-router-dom\";\nimport { Layout } from \"knowdesign\";\nimport classNames from \"classnames\";\nimport _ from \"lodash\";\nimport { prefixCls } from \"./config\";\nimport MeunContent from \"./MenuContent\";\nimport \"./assets/iconfont-logi/iconfont.css\";\nimport \"./assets/iconfont-logi/iconfont.js\";\nimport \"./style.less\";\nimport { IntlProvider } from \"react-intl\";\nimport { getCookie, setCookie } from \"knowdesign/lib/utils/tools\";\nimport { asyncMicroTasks, resize } from \"../../lib/utils\";\n\ninterface Props {\n  noBackground?: boolean;\n  menus: any;\n  treeVisible?: boolean;\n  systemName: string;\n  systemNameChn: string;\n  children?: React.ReactNode;\n  siderMenuVisible?: boolean; // 是否需要菜单\n  onSiderMenuChange?: (value: boolean) => any;\n  intlMessages?: any;\n  locale?: string;\n  permissionPoints?: any[];\n  getPermission?: any;\n  redirectPath?: (permissionPoints: any, history: any) => string;\n}\n\nconst defaultCollapsed = getCookie(\"siderMenuCollapsed\") === \"true\";\nconst { Content, Sider } = Layout;\n\nconst MenuLayout = (props: Props & RouteComponentProps) => {\n  const [menuCollapsed, setMenuCollapsed] = React.useState(defaultCollapsed);\n  const { systemName, menus, systemNameChn, siderMenuVisible } = props;\n  const currentSystemMenuConf = _.get(menus, \"children\");\n  const cPrefixCls = `${prefixCls}-layout`;\n\n  const renderContent = () => {\n    const { noBackground = false } = props;\n    const cPrefixCls = `${prefixCls}-layout`;\n\n    return (\n      <Layout\n        className={classNames({\n          [`${cPrefixCls}-container`]: true,\n        })}\n        style={{ height: \"100%\" }}\n      >\n        <Content className={`${cPrefixCls}-content`} style={{ position: \"relative\" }}>\n          <div\n            className={classNames({\n              [`${cPrefixCls}-main`]: true,\n              [`${cPrefixCls}-main-noBg`]: noBackground,\n            })}\n            id={`${cPrefixCls}-main`}\n          >\n            {props.children}\n          </div>\n        </Content>\n      </Layout>\n    );\n  };\n  return (\n    <>\n      <Layout className={cPrefixCls}>\n        {siderMenuVisible && (\n          <Sider\n            theme=\"light\"\n            width={190}\n            collapsedWidth={56}\n            className={classNames({\n              [`${cPrefixCls}-sider-nav`]: true,\n            })}\n            trigger={null}\n            collapsible\n            collapsed={menuCollapsed}\n          >\n            <IntlProvider locale={props.locale} messages={props.intlMessages}>\n              <MeunContent\n                systemName={systemName}\n                systemNameChn={systemNameChn}\n                menuConf={currentSystemMenuConf}\n                className={`${cPrefixCls}-menu`}\n                collapsed={menuCollapsed}\n                permissionPoints={props.permissionPoints}\n                getPermission={props.getPermission}\n                redirectPath={props.redirectPath}\n              />\n            </IntlProvider>\n            <div className={`${prefixCls}-layout-sider-nav-bottom-divider`}></div>\n            <div\n              className={`${prefixCls}-layout-sider-nav-bottom`}\n              onClick={() => {\n                setMenuCollapsed(!menuCollapsed);\n                props.onSiderMenuChange && props.onSiderMenuChange(!menuCollapsed);\n                asyncMicroTasks(resize);\n                setCookie([\n                  {\n                    key: \"siderMenuCollapsed\",\n                    value: String(!menuCollapsed),\n                  },\n                ]);\n              }}\n            >\n              <svg className={`${prefixCls}-layout-left-menus-icon`} aria-hidden=\"true\">\n                <use xlinkHref={menuCollapsed ? \"#icon-zhankaiicon\" : \"#icon-shouqiicon\"} />\n              </svg>\n            </div>\n          </Sider>\n        )}\n        <Content\n          style={{\n            marginLeft: siderMenuVisible ? (menuCollapsed ? 56 : 190) : 0,\n            // overflow: 'hidden',\n          }}\n        >\n          {renderContent()}\n        </Content>\n      </Layout>\n    </>\n  );\n};\n\nexport default withRouter(MenuLayout);\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/MenuContent.tsx",
    "content": "import React, { Component } from \"react\";\nimport { Link, matchPath, withRouter, RouteComponentProps } from \"react-router-dom\";\nimport { FormattedMessage, injectIntl, WrappedComponentProps } from \"react-intl\";\nimport queryString from \"query-string\";\nimport { Menu } from \"knowdesign\";\nimport _ from \"lodash\";\nimport * as utils from \"./utils\";\nimport { prefixCls } from \"./config\";\nimport { MenuConfItem } from \"./interface\";\nimport { isSuperApp } from \"lib/utils\";\n\ninterface Props {\n  systemName: string;\n  systemNameChn: string;\n  isroot?: boolean;\n  className?: string;\n  menuMode?: \"vertical\" | \"vertical-left\" | \"vertical-right\" | \"horizontal\" | \"inline\" | undefined;\n  menuTheme?: \"dark\" | \"light\" | undefined;\n  menuStyle?: React.CSSProperties | any;\n  menuConf?: MenuConfItem[];\n  collapsed: boolean;\n  permissionPoints: any;\n  getPermission: any;\n  redirectPath?: (permissionPoints: any, history: any) => string;\n}\n\nconst { Item: MenuItem, Divider: MenuDivider, SubMenu, ItemGroup } = Menu;\n\nclass LayoutMenu extends Component<Props & RouteComponentProps & WrappedComponentProps> {\n  static defaultProps: any = {\n    menuMode: \"inline\",\n    menuTheme: \"light\",\n    menuStyle: undefined,\n    menuConf: [], // TODO\n  };\n\n  defaultOpenKeys: string[] = [];\n\n  selectedKeys: string[] = [];\n\n  componentWillReceiveProps() {\n    this.selectedKeys = [];\n  }\n\n  getNavMenuItems(navs: MenuConfItem[], prefix: string) {\n    const { location, collapsed, permissionPoints, getPermission } = this.props;\n    const permissionedNavs = _.filter(navs, (nav) => {\n      if (nav.visible !== undefined && nav.visible === false) {\n        return false;\n      }\n      if (!this.props.isroot && nav.rootVisible) {\n        return false;\n      }\n\n      if (nav.permissionPoint && typeof getPermission === \"function\") {\n        return !!getPermission(nav.permissionPoint, permissionPoints);\n      }\n      if (nav.permissionPoint && !permissionPoints[nav.permissionPoint]) {\n        return false;\n      }\n      return true;\n    });\n    if (location?.pathname === \"/\") {\n      const { redirectPath, permissionPoints, history } = this.props;\n      redirectPath(permissionPoints, history);\n    }\n    return _.map(permissionedNavs, (nav, index) => {\n      if (nav.divider) {\n        return <MenuDivider key={index} />;\n      }\n\n      const icon = nav.icon ? (\n        <svg className={`${prefixCls}-layout-left-menus-icon`} aria-hidden=\"true\">\n          <use xlinkHref={nav.icon}></use>\n        </svg>\n      ) : null;\n\n      const linkProps = {} as { target: string; href: string; to: { pathname?: string; search?: string } };\n      let link;\n\n      if (_.isArray(nav.children) && utils.hasRealChildren(nav.children)) {\n        const menuKey = nav.name;\n        if (this.isActive(nav.to)) {\n          this.defaultOpenKeys = _.union(this.defaultOpenKeys, [menuKey]) as any;\n        }\n\n        if (nav.type === \"group\") {\n          return (\n            <ItemGroup key={menuKey as any} title={collapsed ? \"/\" : this.props.intl.formatMessage({ id: `${prefix}.${nav.name}` })}>\n              {this.getNavMenuItems(nav.children, `${prefix}.${nav.name}`)}\n            </ItemGroup>\n          );\n        }\n\n        const childList = this.getNavMenuItems(nav.children, `${prefix}.${nav.name}`);\n\n        if (!childList.length) return null;\n\n        return (\n          <SubMenu\n            key={menuKey as any}\n            title={\n              <>\n                {icon}\n                <span className=\"menu-name\">{<FormattedMessage id={`${prefix}.${nav.name}`} />}</span>\n              </>\n            }\n          >\n            {childList}\n          </SubMenu>\n        );\n      }\n\n      if (nav.target) {\n        linkProps.target = nav.target;\n      }\n\n      if (nav.to && (utils.isAbsolutePath(nav.to) || nav.isAbsolutePath)) {\n        linkProps.href = nav.to;\n        link = (\n          <a {...linkProps}>\n            {icon}\n            <span className=\"menu-name\">{<FormattedMessage id={`${prefix}.${nav.name}`} />}</span>\n          </a>\n        );\n      } else {\n        if (nav.to && this.isActive(nav.to)) this.selectedKeys = [nav.to];\n\n        linkProps.to = {\n          pathname: nav.to,\n        };\n\n        if (_.isFunction(nav.getQuery)) {\n          const query = nav.getQuery(queryString.parse(location.search));\n          linkProps.to.search = queryString.stringify(query);\n        }\n\n        link = (\n          <Link to={linkProps.to}>\n            {icon}\n            <span className=\"menu-name\">{<FormattedMessage id={`${prefix}.${nav.name}`} />}</span>\n          </Link>\n        );\n      }\n      return <MenuItem key={nav.to}>{link}</MenuItem>;\n    });\n  }\n\n  isActive(path?: string) {\n    const { location } = this.props;\n    return !!matchPath(location.pathname, { path });\n  }\n\n  render() {\n    const { menuMode, menuTheme, menuStyle, location } = this.props;\n    const { menuConf, className, systemName, collapsed } = this.props;\n    const realMenuConf = _.isFunction(menuConf) ? menuConf(location) : menuConf;\n    const normalizedMenuConf = utils.normalizeMenuConf(realMenuConf);\n    const menus = this.getNavMenuItems(normalizedMenuConf, `menu.${systemName}`);\n\n    return (\n      <Menu\n        defaultOpenKeys={collapsed ? [] : this.defaultOpenKeys}\n        selectedKeys={this.selectedKeys}\n        theme={menuTheme}\n        mode={menuMode}\n        style={menuStyle}\n        className={className}\n      >\n        {menus}\n      </Menu>\n    );\n  }\n}\n\nexport default injectIntl(withRouter(LayoutMenu));\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/MsgPanel/index.less",
    "content": ".msg-panel {\n  width: 440px;\n  height: 400px;\n  background: #FFFFFF;\n  box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.15);\n  border-radius: 4px;\n\n  .tabs {\n    padding: 0px 16px;\n  }\n\n  .right-btn {\n    line-height: 46px;\n    position: absolute;\n    top: 0px;\n    right: 16px;\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: @primary-color;\n  }\n\n  .ant-tabs-tab-btn {\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: #303A51;\n    line-height: 22px;\n  }\n\n  .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: @primary-color;\n    line-height: 22px;\n  }\n\n  .ant-tabs-top>.ant-tabs-nav,\n  .ant-tabs-bottom>.ant-tabs-nav,\n  .ant-tabs-top>div>.ant-tabs-nav,\n  .ant-tabs-bottom>div>.ant-tabs-nav {\n    margin: 0px;\n  }\n\n  .list {\n    height: 352px;\n    overflow: scroll;\n\n    .ant-list-item-meta-title {\n      font-family: PingFangSC-Medium;\n      font-size: 16px;\n      color: #303A51;\n      line-height: 24px;\n      text-overflow: ellipsis;\n      overflow: hidden;\n      max-width: 270px;\n\n      .read {\n        opacity: 0.8;\n      }\n    }\n\n    .ant-list-item-meta-description {\n      font-family: PingFangSC-Regular;\n      font-size: 12px;\n      color: #505568;\n      line-height: 20px;\n      text-overflow: ellipsis;\n      overflow: hidden;\n      max-width: 274px;\n\n      .read {\n        opacity: 0.8;\n      }\n    }\n\n    .right-text {\n      font-family: PingFangSC-Regular;\n      font-size: 12px;\n      color: #A8ADBD;\n      text-align: right;\n      line-height: 20px;\n    }\n  }\n\n  .ant-empty-image {\n    margin-bottom: 12px;\n    height: 76px;\n    margin-top: 121px;\n  }\n\n  .ant-empty-description {\n    height: 22px;\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: #505568;\n    line-height: 22px;\n    font-weight: 400;\n  }\n}"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/MsgPanel/index.tsx",
    "content": "import * as React from \"react\";\nimport { Empty, List, Spin, Tabs } from \"antd\";\nimport WindowScroller, { WindowScrollerChildProps } from \"react-virtualized/dist/commonjs/WindowScroller\";\nimport AutoSizer from \"react-virtualized/dist/commonjs/AutoSizer\";\nimport VList, { ListProps } from \"react-virtualized/dist/commonjs/List\";\nimport InfiniteLoader from \"react-virtualized/dist/commonjs/InfiniteLoader\";\nimport \"./index.less\";\n\nimport utils from \"knowdesign/lib/utils\";\n\nconst emptyImg = require(\"./assets/empty.png\");\n\ninterface IMsg {\n  title: string;\n  content: string;\n  timestamp: string;\n  createTime: string;\n}\nconst { TabPane } = Tabs;\n\nexport const MsgPanel: React.FC = () => {\n  const [data, setData] = React.useState<IMsg[]>([]);\n  const [msgCount, setMsgCount] = React.useState(0);\n  const [status, setStatus] = React.useState(\"unread\");\n  const [loading, setLoading] = React.useState(false);\n  const loadedRowsMap = {} as {\n    [key: number]: number;\n  };\n  const queryProjectList = (params): any => {\n    // return Promise.resolve([\n    //   {\n    //     content: \"ejqwkjdkqwdksajdjkasdksjajdksajdksajhdjkhsajkdhkjsahdkjshdkjsahdwuyeuahdmasbmndbamsbdmnsabdnsa\",\n    //     createTime: \"00:00:00\",\n    //     id: 0,\n    //     isRead: true,\n    //     title: \"操作消息说就是看电视卡等级\",\n    //     timestamp: \"22312312312\",\n    //   },\n    // ]);\n    return utils.request(`/v1/message/list`, params);\n  };\n  const getData = async (params = \"\") => {\n    setLoading(true);\n    const fakeData: any = await queryProjectList(params);\n    console.log(fakeData);\n    setData(fakeData);\n    setMsgCount(0);\n    setLoading(false);\n  };\n\n  const onHandleAllMsg = () => {\n    //\n  };\n\n  React.useEffect(() => {\n    getData();\n  }, []);\n\n  const handleInfiniteOnLoad = ({ startIndex, stopIndex }: { startIndex: number; stopIndex: number }): any => {\n    setLoading(true);\n    for (let i = startIndex; i <= stopIndex; i++) {\n      // 1 means loading\n      loadedRowsMap[i] = 1;\n    }\n    if (data.length > 10) {\n      setLoading(false);\n      return;\n    }\n    getData();\n    return;\n  };\n\n  const isRowLoaded = ({ index }: { index: number }) => !!loadedRowsMap[index];\n\n  const renderItem = ({ index, key, style }: { index: number; key: string; style: React.CSSProperties | any }) => {\n    const item = data[index] || ({} as IMsg);\n    return (\n      <List.Item key={key} style={style}>\n        <List.Item.Meta title={<span className={status}>{item.title}</span>} description={<span className={status}>{item.content}</span>} />\n        <div className=\"right-text\">{item.createTime}</div>\n      </List.Item>\n    );\n  };\n\n  const vlist = ({ height, isScrolling, onChildScroll, scrollTop, onRowsRendered, width }: ListProps) => (\n    <VList\n      autoHeight\n      height={height}\n      isScrolling={isScrolling}\n      onScroll={onChildScroll}\n      overscanRowCount={2}\n      rowCount={data.length}\n      rowHeight={78}\n      rowRenderer={renderItem}\n      onRowsRendered={onRowsRendered}\n      scrollTop={scrollTop}\n      width={width}\n      style={{ paddingLeft: 16, paddingRight: 16 }}\n    />\n  );\n  const autoSize = ({ height, isScrolling, onChildScroll, scrollTop, onRowsRendered }: ListProps) => (\n    <AutoSizer disableHeight>\n      {({ width }: { width: number }) =>\n        vlist({\n          height,\n          isScrolling,\n          onChildScroll,\n          scrollTop,\n          onRowsRendered,\n          width,\n        } as unknown as ListProps)\n      }\n    </AutoSizer>\n  );\n  const infiniteLoader = ({ height, isScrolling, onChildScroll, scrollTop }: WindowScrollerChildProps) => (\n    <InfiniteLoader isRowLoaded={isRowLoaded} loadMoreRows={handleInfiniteOnLoad} rowCount={data.length}>\n      {({ onRowsRendered }: any) =>\n        autoSize({\n          height,\n          isScrolling,\n          onChildScroll,\n          scrollTop,\n          onRowsRendered,\n        } as unknown as ListProps)\n      }\n    </InfiniteLoader>\n  );\n\n  return (\n    <>\n      <div className=\"msg-panel\">\n        <>\n          <Tabs className=\"tabs\" defaultActiveKey={status} onChange={setStatus}>\n            <TabPane tab={`未读(${msgCount})`} key=\"unread\"></TabPane>\n            <TabPane tab=\"已读\" key=\"read\"></TabPane>\n          </Tabs>\n          <a className=\"right-btn\" onClick={onHandleAllMsg}>\n            全部消息\n          </a>\n        </>\n        {data.length === 0 && !loading && <Empty image={emptyImg} />}\n        {data.length > 0 && (\n          <List className=\"list\">\n            {<WindowScroller>{infiniteLoader}</WindowScroller>}\n            {loading && <Spin className=\"loading\" />}\n          </List>\n        )}\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/ProjectSelect/index.tsx",
    "content": "import React, { useState } from 'react';\nimport { Select } from 'antd';\nimport _ from 'lodash';\ninterface IProps {\n  style?: object;\n  value?: any;\n  projectList?: IProject[];\n  onProjectChange?: (newValue: any) => void;\n}\n\nexport interface IProject {\n  id?: number;\n  ident?: string;\n  name?: string;\n}\n\nexport default function ProjectSelect(props: IProps) {\n  const [data, setData] = useState<IProject[]>(props.projectList || []);\n  React.useEffect(() => {\n    setData(props.projectList || []);\n  }, [props.projectList])\n  \n  const onChange = (value: number) => {\n    props.onProjectChange && props.onProjectChange(data.filter(item => item.id === value)?.[0]);\n  }\n\n  return (\n    <Select\n      allowClear={true}\n      placeholder=\"请选择\"\n      onChange={onChange}\n      defaultValue={props.value || data?.[0]?.id}\n    >\n      {\n        _.map(data, (item, index) => {\n          return (\n            <Select.Option key={item.ident + index} value={item.id}>\n              {item.name}({item.id})\n            </Select.Option>\n          );\n        })\n      }\n    </Select>\n  )\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/UseCenter/config.ts",
    "content": "export enum FormItemType {\n  input = \"input\",\n  inputPassword = \"inputPassword\",\n  inputNumber = \"inputNumber\",\n}\n\nexport interface IFormItem {\n  key: string;\n  type: FormItemType;\n  attrs?: any;\n  rules?: any[];\n  invisible?: boolean;\n}\n\nexport const FormMap = [\n  {\n    key: \"password\",\n    type: FormItemType.inputPassword,\n    label: \"当前密码\",\n    rules: [\n      {\n        required: true,\n      },\n    ],\n    attrs: {\n      placeholder: \"请输入当前密码\",\n    },\n  },\n  {\n    key: \"newPassword\",\n    type: FormItemType.inputPassword,\n    label: \"新密码\",\n    rules: [\n      {\n        required: true,\n        validator: (rule: any, value: string) => {\n          if (!value) return Promise.reject(\"请输入新密码\");\n          let flat_6_20 = value && value.length > 5 && value.length <= 20;\n          const reg = /^[a-zA-Z0-9`~!@#$%^&*()_\\-+=<>?:\"{}|,.\\/;'\\\\[\\]·~！@#￥%……&*（）——\\-+={}|《》？：“”【】、；‘'，。、]*$/;\n          if (flat_6_20 && reg.test(value)) {\n            return Promise.resolve();\n          } else {\n            return Promise.reject(\"6-20个字符，支持英文字母、数字、标点符号（除空格）\");\n          }\n        },\n      },\n      ({ getFieldValue }) => ({\n        validator(_, value) {\n          if (getFieldValue(\"password\") === value) {\n            return Promise.reject(\"新密码不能与当前密码相同\");\n          }\n          return Promise.resolve();\n        },\n      }),\n    ],\n    attrs: {\n      placeholder: \"请输入新密码\",\n    },\n  },\n  {\n    key: \"confirm\",\n    type: FormItemType.inputPassword,\n    label: \"确认密码\",\n    rules: [\n      {\n        required: true,\n        message: \"请再次输入密码\",\n      },\n      ({ getFieldValue }) => ({\n        validator(_, value) {\n          let flat_6_20 = value && value.length > 5 && value.length <= 20;\n          const reg = /^[a-zA-Z0-9`~!@#$%^&*()_\\-+=<>?:\"{}|,.\\/;'\\\\[\\]·~！@#￥%……&*（）——\\-+={}|《》？：“”【】、；‘'，。、]*$/;\n          if (value && (!flat_6_20 || !reg.test(value))) {\n            return Promise.reject(\"6-20个字符，支持英文字母、数字、标点符号（除空格）\");\n          }\n          if (!value || getFieldValue(\"newPassword\") === value) {\n            return Promise.resolve();\n          }\n          return Promise.reject(\"两次密码不统一\");\n        },\n      }),\n    ],\n    attrs: {\n      placeholder: \"请再次输入密码\",\n    },\n  },\n];\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/UseCenter/index.less",
    "content": ".user-container {\n  position: relative;\n  .user-title {\n    width: 100%;\n    height: 48px;\n    border-bottom: 1px solid #eceef0;\n    padding: 10px 22px 12px 22px;\n    font-family: PingFangSC-Medium;\n    img {\n      width: 18px;\n      margin-right: 4px;\n      position: relative;\n      top: 3px;\n    }\n    span {\n      font-size: 14px;\n      color: #1d2330;\n      line-height: 24px;\n      font-weight: 500;\n    }\n    .anticon-close {\n      color: #929aac;\n      position: absolute;\n      right: 20px;\n      top: 12px;\n    }\n  }\n  .user-content {\n    height: 320px;\n    overflow: auto;\n    padding: 24px 0 0 20px;\n    .ant-descriptions-item-label {\n      font-weight: 500;\n      font-family: PingFangSC-Medium;\n    }\n    .ant-descriptions-item-content {\n      font-family: PingFangSC-Regular;\n    }\n    .edit-content {\n      width: 100%;\n      position: relative;\n      .anticon-edit {\n        position: absolute;\n        right: 10px;\n      }\n      .edit-input {\n        width: 150px;\n        margin-right: 10px;\n      }\n      .button {\n        display: inline-block;\n        .ant-btn-link {\n          margin-right: 5px;\n          padding: 0;\n        }\n      }\n      .error-input {\n        border-color: #ff4d4f;\n        &:focus {\n          border-color: #ff7875;\n          box-shadow: 0 0 0 2px rgb(255 77 79 / 20%);\n        }\n      }\n      .error {\n        color: #ff4d4f;\n      }\n    }\n    .edit {\n      height: 30px;\n      position: relative;\n      top: -6px;\n    }\n    .password {\n      .ant-descriptions-item-container {\n        display: inline-block;\n        .change_password_form {\n          width: 272px;\n          margin-top: 8px;\n          padding: 12px 10px 0px 12px;\n          background: #f9f9fa;\n          border: 1px solid #f9f9fa;\n          border-radius: 4px;\n          .ant-input-password {\n            width: 249px;\n            height: 26px;\n            background: #ffffff;\n            border-radius: 2px;\n          }\n          .ant-form-item {\n            margin-bottom: 10px;\n          }\n          .ant-btn {\n            height: 24px;\n            line-height: 13px;\n          }\n        }\n      }\n    }\n  }\n\n  .user-logout {\n    width: 100%;\n    height: 56px;\n    border-top: 1px solid #eceef0;\n    position: absolute;\n    bottom: 0;\n    padding: 18px 24px;\n    font-size: 14px;\n    cursor: pointer;\n    font-family: PingFangSC-Regular;\n    background: #fff;\n    .icontuichudenglu {\n      position: relative;\n      top: -1px;\n      padding-right: 4px;\n      &:hover {\n        color: #000;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/UseCenter/index.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { Descriptions, Input, Form, Row, Button } from \"antd\";\nimport moment from \"moment\";\nimport { updateUserInfo } from \"api/logi-security\";\nimport { EditOutlined, CloseOutlined } from \"@ant-design/icons\";\nimport { deleteCookie } from \"lib/utils\";\nimport { FormItemType, FormMap, IFormItem } from \"./config\";\nimport { XNotification } from \"component/x-notification\";\nimport \"./index.less\";\nimport { renderAttributes } from \"container/custom-component\";\n\nconst imgSrc = require(\"../../../assets/emjio@3x.png\");\n\nexport default function UseCenter(props: any) {\n  const { userInfo, getData, logout, close } = props;\n\n  const [isSwitch, setSwitch] = useState(false);\n  const [name, setName] = useState(\"\");\n  const [nameSwitch, setNameSwitch] = useState(false);\n  const [nameError, setNameError] = useState(\"\");\n  const [phone, setPhone] = useState(\"\");\n  const [phoneSwitch, setPhoneSwitch] = useState(false);\n  const [phoneError, setPhoneError] = useState(\"\");\n  const [email, setEmail] = useState(\"\");\n  const [emailSwitch, setEmailSwitch] = useState(false);\n  const [emailError, setEmailError] = useState(\"\");\n\n  const [form] = Form.useForm();\n\n  useEffect(() => {\n    setEditValue();\n  }, [userInfo]);\n\n  const setEditValue = () => {\n    setName(userInfo?.realName);\n    setPhone(userInfo?.phone);\n    setEmail(userInfo?.email);\n  };\n\n  const editUser = async (value: string, type: string) => {\n    let req = {} as any;\n    if (type === \"realName\") {\n      req = { realName: value };\n    } else if (type === \"phone\") {\n      req = { phone: value };\n    } else if (type === \"email\") {\n      req = { email: value };\n    }\n    req.userName = userInfo.userName;\n    await updateUserInfo(req).then(() => {\n      XNotification({ type: \"success\", message: \"更新成功\", duration: 1.5 });\n      getData();\n      if (type === \"realName\") {\n        setNameSwitch(!nameSwitch);\n      } else if (type === \"phone\") {\n        setPhoneSwitch(!phoneSwitch);\n      } else if (type === \"email\") {\n        setEmailSwitch(!emailSwitch);\n      }\n    });\n  };\n\n  const getNameInput = (type: string) => {\n    let ele = (\n      <Input\n        className={`edit-input ${nameError ? \"error-input\" : \"\"}`}\n        placeholder=\"请输入用户实名\"\n        defaultValue={name}\n        onChange={(e) => {\n          let value = e.target.value;\n          setName(value);\n          if (!value) {\n            setNameError(\"请输入用户实名\");\n          }\n          let flat_1_50 = value && value.length > 0 && value.length <= 50;\n          const reg = /^[a-zA-Z\\u4e00-\\u9fa5]+$/;\n          if (!reg.test(value)) {\n            setNameError(\"请输入中文或英文\");\n          } else if (!flat_1_50) {\n            setNameError(\"1-50字符\");\n          } else {\n            setNameError(\"\");\n          }\n        }}\n      />\n    );\n    return (\n      <div className={`edit-content ${nameSwitch ? \"edit\" : \"\"}`}>\n        {nameSwitch ? ele : <span>{userInfo?.realName || \"-\"}</span>}\n        {nameSwitch ? (\n          <div className=\"button\">\n            <Button\n              type=\"link\"\n              onClick={async () => {\n                if (nameError || name === userInfo?.realName) {\n                  setNameSwitch(!nameSwitch);\n                  return;\n                }\n                await editUser(name, type);\n                setNameSwitch(!nameSwitch);\n              }}\n            >\n              确认\n            </Button>\n            <Button\n              type=\"link\"\n              onClick={async () => {\n                setNameSwitch(!nameSwitch);\n                setNameError(\"\");\n                setName(userInfo?.realName);\n              }}\n            >\n              取消\n            </Button>\n          </div>\n        ) : (\n          <EditOutlined onClick={() => setNameSwitch(!nameSwitch)} />\n        )}\n        <div className=\"error\">{nameError}</div>\n      </div>\n    );\n  };\n\n  const getMobileInput = (type: string, value: string) => {\n    let ele = (\n      <Input\n        className={`edit-input ${phoneError ? \"error-input\" : \"\"}`}\n        placeholder=\"请输入手机号码\"\n        defaultValue={phone}\n        onChange={(e) => {\n          let value = e.target.value;\n          setPhone(value);\n          const reg = /^[1][3-9][0-9]{9}$/;\n          if (value && !reg.test(value)) {\n            setPhoneError(\"请输入正确手机号码\");\n          } else {\n            setPhoneError(\"\");\n          }\n        }}\n      />\n    );\n    return (\n      <div className=\"edit-content\">\n        {phoneSwitch ? ele : <span>{value || \"-\"}</span>}\n        {phoneSwitch ? (\n          <div className=\"button\">\n            <Button\n              type=\"link\"\n              onClick={async () => {\n                if (phoneError || phone === userInfo?.phone) {\n                  setPhoneSwitch(!phoneSwitch);\n                  return;\n                }\n                await editUser(phone, type);\n                setPhoneSwitch(!phoneSwitch);\n              }}\n            >\n              确认\n            </Button>\n            <Button\n              type=\"link\"\n              onClick={async () => {\n                setPhoneSwitch(!phoneSwitch);\n                setPhoneError(\"\");\n                setPhone(userInfo?.phone);\n              }}\n            >\n              取消\n            </Button>\n          </div>\n        ) : (\n          <EditOutlined onClick={() => setPhoneSwitch(!phoneSwitch)} />\n        )}\n        <div className=\"error\">{phoneError}</div>\n      </div>\n    );\n  };\n\n  const getEmailInput = (type: string, value: string) => {\n    let ele = (\n      <Input\n        className={`edit-input ${emailError ? \"error-input\" : \"\"}`}\n        defaultValue={email}\n        placeholder=\"请输入邮箱地址\"\n        onChange={(e) => {\n          let value = e.target.value;\n          setEmail(value);\n          const reg = /^[\\w.\\-]+@(?:[a-z0-9]+(?:-[a-z0-9]+)*\\.)+[a-z]{2,3}$/;\n          if (value && !reg.test(value)) {\n            setEmailError(\"请输入正确邮箱地址\");\n          } else {\n            setEmailError(\"\");\n          }\n        }}\n      />\n    );\n    return (\n      <div className=\"edit-content\">\n        {emailSwitch ? ele : <span>{value || \"-\"}</span>}\n        {emailSwitch ? (\n          <div className=\"button\">\n            <Button\n              type=\"link\"\n              onClick={async () => {\n                if (emailError || email === userInfo?.email) {\n                  setEmailSwitch(!emailSwitch);\n                  return;\n                }\n                await editUser(email, type);\n                setEmailSwitch(!emailSwitch);\n              }}\n            >\n              确认\n            </Button>\n            <Button\n              type=\"link\"\n              onClick={async () => {\n                setEmailSwitch(!emailSwitch);\n                setEmailError(\"\");\n                setEmail(userInfo?.email);\n              }}\n            >\n              取消\n            </Button>\n          </div>\n        ) : (\n          <EditOutlined onClick={() => setEmailSwitch(!emailSwitch)} />\n        )}\n        <div className=\"error\">{emailError}</div>\n      </div>\n    );\n  };\n\n  const handleSubmit = (e: { password: string; newPassword: string }) => {\n    updateUserInfo({ oldPw: e.password, pw: e.newPassword, userName: userInfo.userName }).then(() => {\n      XNotification({ type: \"success\", message: \"修改密码成功！\", duration: 1.5 });\n      deleteCookie([\"userId\", \"userName\"]);\n      window.location.href = \"/login\";\n    });\n  };\n\n  const renderFormItem = (item: IFormItem) => {\n    switch (item.type) {\n      default:\n      case FormItemType.input:\n        return <Input key={item.key} {...item.attrs} />;\n      case FormItemType.inputPassword:\n        return <Input.Password key={item.key} {...item.attrs} />;\n    }\n  };\n\n  const changePassword = () => {\n    return (\n      <div className=\"change_password_form\">\n        <Form name=\"change_password\" form={form} onFinish={handleSubmit} layout={\"vertical\"}>\n          {FormMap.map((formItem) => {\n            return (\n              <Row key={formItem.key}>\n                <Form.Item key={formItem.key} name={formItem.key} label={formItem.label} rules={formItem.rules} style={{ width: \"100%\" }}>\n                  {renderFormItem(formItem)}\n                </Form.Item>\n              </Row>\n            );\n          })}\n          <Form.Item key={\"submit\"}>\n            <Row>\n              <Button type=\"primary\" htmlType=\"submit\">\n                确定\n              </Button>\n              <Button style={{ marginLeft: 10 }} onClick={() => setSwitch(!isSwitch)}>\n                取消\n              </Button>\n            </Row>\n          </Form.Item>\n        </Form>\n      </div>\n    );\n  };\n\n  const renderProject = () => {\n    let list = userInfo?.projectList || [];\n    let data = list.map((item: any) => item && item.projectName);\n    return renderAttributes({ data, limit: 10, placement: \"bottomLeft\" });\n  };\n\n  const renderContent = () => {\n    return (\n      <Descriptions>\n        <Descriptions.Item span={24} label=\"用户账号\" key=\"userName\">\n          {userInfo.userName}\n        </Descriptions.Item>\n        <Descriptions.Item span={24} label=\"注册时间\" key=\"createTime\">\n          {moment(userInfo.createTime).format(\"YYYY-MM-DD\")}\n        </Descriptions.Item>\n        <Descriptions.Item span={24} label=\"用户实名\" key=\"realName\">\n          {getNameInput(\"realName\")}\n        </Descriptions.Item>\n        <Descriptions.Item span={24} label=\"手机号码\" key=\"phone\">\n          {getMobileInput(\"phone\", userInfo.phone)}\n        </Descriptions.Item>\n        <Descriptions.Item span={24} label=\"邮箱地址\" key=\"email\">\n          {getEmailInput(\"email\", userInfo.email)}\n        </Descriptions.Item>\n        <Descriptions.Item span={24} label=\"登录密码\" className=\"password\" key=\"password\">\n          {isSwitch ? (\n            changePassword()\n          ) : (\n            <span>\n              ………\n              <a className=\"ml-10\" onClick={() => setSwitch(!isSwitch)}>\n                修改密码\n              </a>\n            </span>\n          )}\n        </Descriptions.Item>\n        <Descriptions.Item span={24} label=\"所属应用\" key=\"project\">\n          <div className=\"project\">{renderProject()}</div>\n        </Descriptions.Item>\n      </Descriptions>\n    );\n  };\n\n  return (\n    <div className=\"user-container\">\n      <div className=\"user-title\">\n        <img src={imgSrc}></img>\n        <span>嗨，你好，{userInfo?.userName || \"-\"}</span>\n        <CloseOutlined onClick={close} />\n      </div>\n      <div className=\"user-content\">{renderContent()}</div>\n      <div className=\"user-logout\" onClick={() => logout()}>\n        <span className={`icon iconfont icontuichudenglu`}></span>\n        <span>退出登录</span>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/iconfont-es/demo.css",
    "content": "/* Logo 字体 */\n@font-face {\n  font-family: \"iconfont logo\";\n  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');\n  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),\n    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),\n    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),\n    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');\n}\n\n.logo {\n  font-family: \"iconfont logo\";\n  font-size: 160px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n/* tabs */\n.nav-tabs {\n  position: relative;\n}\n\n.nav-tabs .nav-more {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  height: 42px;\n  line-height: 42px;\n  color: #666;\n}\n\n#tabs {\n  border-bottom: 1px solid #eee;\n}\n\n#tabs li {\n  cursor: pointer;\n  width: 100px;\n  height: 40px;\n  line-height: 40px;\n  text-align: center;\n  font-size: 16px;\n  border-bottom: 2px solid transparent;\n  position: relative;\n  z-index: 1;\n  margin-bottom: -1px;\n  color: #666;\n}\n\n\n#tabs .active {\n  border-bottom-color: #f00;\n  color: #222;\n}\n\n.tab-container .content {\n  display: none;\n}\n\n/* 页面布局 */\n.main {\n  padding: 30px 100px;\n  width: 960px;\n  margin: 0 auto;\n}\n\n.main .logo {\n  color: #333;\n  text-align: left;\n  margin-bottom: 30px;\n  line-height: 1;\n  height: 110px;\n  margin-top: -50px;\n  overflow: hidden;\n  *zoom: 1;\n}\n\n.main .logo a {\n  font-size: 160px;\n  color: #333;\n}\n\n.helps {\n  margin-top: 40px;\n}\n\n.helps pre {\n  padding: 20px;\n  margin: 10px 0;\n  border: solid 1px #e7e1cd;\n  background-color: #fffdef;\n  overflow: auto;\n}\n\n.icon_lists {\n  width: 100% !important;\n  overflow: hidden;\n  *zoom: 1;\n}\n\n.icon_lists li {\n  width: 100px;\n  margin-bottom: 10px;\n  margin-right: 20px;\n  text-align: center;\n  list-style: none !important;\n  cursor: default;\n}\n\n.icon_lists li .code-name {\n  line-height: 1.2;\n}\n\n.icon_lists .icon {\n  display: block;\n  height: 100px;\n  line-height: 100px;\n  font-size: 42px;\n  margin: 10px auto;\n  color: #333;\n  -webkit-transition: font-size 0.25s linear, width 0.25s linear;\n  -moz-transition: font-size 0.25s linear, width 0.25s linear;\n  transition: font-size 0.25s linear, width 0.25s linear;\n}\n\n.icon_lists .icon:hover {\n  font-size: 100px;\n}\n\n.icon_lists .svg-icon {\n  /* 通过设置 font-size 来改变图标大小 */\n  width: 1em;\n  /* 图标和文字相邻时，垂直对齐 */\n  vertical-align: -0.15em;\n  /* 通过设置 color 来改变 SVG 的颜色/fill */\n  fill: currentColor;\n  /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示\n      normalize.css 中也包含这行 */\n  overflow: hidden;\n}\n\n.icon_lists li .name,\n.icon_lists li .code-name {\n  color: #666;\n}\n\n/* markdown 样式 */\n.markdown {\n  color: #666;\n  font-size: 14px;\n  line-height: 1.8;\n}\n\n.highlight {\n  line-height: 1.5;\n}\n\n.markdown img {\n  vertical-align: middle;\n  max-width: 100%;\n}\n\n.markdown h1 {\n  color: #404040;\n  font-weight: 500;\n  line-height: 40px;\n  margin-bottom: 24px;\n}\n\n.markdown h2,\n.markdown h3,\n.markdown h4,\n.markdown h5,\n.markdown h6 {\n  color: #404040;\n  margin: 1.6em 0 0.6em 0;\n  font-weight: 500;\n  clear: both;\n}\n\n.markdown h1 {\n  font-size: 28px;\n}\n\n.markdown h2 {\n  font-size: 22px;\n}\n\n.markdown h3 {\n  font-size: 16px;\n}\n\n.markdown h4 {\n  font-size: 14px;\n}\n\n.markdown h5 {\n  font-size: 12px;\n}\n\n.markdown h6 {\n  font-size: 12px;\n}\n\n.markdown hr {\n  height: 1px;\n  border: 0;\n  background: #e9e9e9;\n  margin: 16px 0;\n  clear: both;\n}\n\n.markdown p {\n  margin: 1em 0;\n}\n\n.markdown>p,\n.markdown>blockquote,\n.markdown>.highlight,\n.markdown>ol,\n.markdown>ul {\n  width: 80%;\n}\n\n.markdown ul>li {\n  list-style: circle;\n}\n\n.markdown>ul li,\n.markdown blockquote ul>li {\n  margin-left: 20px;\n  padding-left: 4px;\n}\n\n.markdown>ul li p,\n.markdown>ol li p {\n  margin: 0.6em 0;\n}\n\n.markdown ol>li {\n  list-style: decimal;\n}\n\n.markdown>ol li,\n.markdown blockquote ol>li {\n  margin-left: 20px;\n  padding-left: 4px;\n}\n\n.markdown code {\n  margin: 0 3px;\n  padding: 0 5px;\n  background: #eee;\n  border-radius: 3px;\n}\n\n.markdown strong,\n.markdown b {\n  font-weight: 600;\n}\n\n.markdown>table {\n  border-collapse: collapse;\n  border-spacing: 0px;\n  empty-cells: show;\n  border: 1px solid #e9e9e9;\n  width: 95%;\n  margin-bottom: 24px;\n}\n\n.markdown>table th {\n  white-space: nowrap;\n  color: #333;\n  font-weight: 600;\n}\n\n.markdown>table th,\n.markdown>table td {\n  border: 1px solid #e9e9e9;\n  padding: 8px 16px;\n  text-align: left;\n}\n\n.markdown>table th {\n  background: #F7F7F7;\n}\n\n.markdown blockquote {\n  font-size: 90%;\n  color: #999;\n  border-left: 4px solid #e9e9e9;\n  padding-left: 0.8em;\n  margin: 1em 0;\n}\n\n.markdown blockquote p {\n  margin: 0;\n}\n\n.markdown .anchor {\n  opacity: 0;\n  transition: opacity 0.3s ease;\n  margin-left: 8px;\n}\n\n.markdown .waiting {\n  color: #ccc;\n}\n\n.markdown h1:hover .anchor,\n.markdown h2:hover .anchor,\n.markdown h3:hover .anchor,\n.markdown h4:hover .anchor,\n.markdown h5:hover .anchor,\n.markdown h6:hover .anchor {\n  opacity: 1;\n  display: inline-block;\n}\n\n.markdown>br,\n.markdown>p>br {\n  clear: both;\n}\n\n\n.hljs {\n  display: block;\n  background: white;\n  padding: 0.5em;\n  color: #333333;\n  overflow-x: auto;\n}\n\n.hljs-comment,\n.hljs-meta {\n  color: #969896;\n}\n\n.hljs-string,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-strong,\n.hljs-emphasis,\n.hljs-quote {\n  color: #df5000;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-type {\n  color: #a71d5d;\n}\n\n.hljs-literal,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-attribute {\n  color: #0086b3;\n}\n\n.hljs-section,\n.hljs-name {\n  color: #63a35c;\n}\n\n.hljs-tag {\n  color: #333333;\n}\n\n.hljs-title,\n.hljs-attr,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n  color: #795da3;\n}\n\n.hljs-addition {\n  color: #55a532;\n  background-color: #eaffea;\n}\n\n.hljs-deletion {\n  color: #bd2c00;\n  background-color: #ffecec;\n}\n\n.hljs-link {\n  text-decoration: underline;\n}\n\n/* 代码高亮 */\n/* PrismJS 1.15.0\nhttps://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */\n/**\n * prism.js default theme for JavaScript, CSS and HTML\n * Based on dabblet (http://dabblet.com)\n * @author Lea Verou\n */\ncode[class*=\"language-\"],\npre[class*=\"language-\"] {\n  color: black;\n  background: none;\n  text-shadow: 0 1px white;\n  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;\n  text-align: left;\n  white-space: pre;\n  word-spacing: normal;\n  word-break: normal;\n  word-wrap: normal;\n  line-height: 1.5;\n\n  -moz-tab-size: 4;\n  -o-tab-size: 4;\n  tab-size: 4;\n\n  -webkit-hyphens: none;\n  -moz-hyphens: none;\n  -ms-hyphens: none;\n  hyphens: none;\n}\n\npre[class*=\"language-\"]::-moz-selection,\npre[class*=\"language-\"] ::-moz-selection,\ncode[class*=\"language-\"]::-moz-selection,\ncode[class*=\"language-\"] ::-moz-selection {\n  text-shadow: none;\n  background: #b3d4fc;\n}\n\npre[class*=\"language-\"]::selection,\npre[class*=\"language-\"] ::selection,\ncode[class*=\"language-\"]::selection,\ncode[class*=\"language-\"] ::selection {\n  text-shadow: none;\n  background: #b3d4fc;\n}\n\n@media print {\n\n  code[class*=\"language-\"],\n  pre[class*=\"language-\"] {\n    text-shadow: none;\n  }\n}\n\n/* Code blocks */\npre[class*=\"language-\"] {\n  padding: 1em;\n  margin: .5em 0;\n  overflow: auto;\n}\n\n:not(pre)>code[class*=\"language-\"],\npre[class*=\"language-\"] {\n  background: #f5f2f0;\n}\n\n/* Inline code */\n:not(pre)>code[class*=\"language-\"] {\n  padding: .1em;\n  border-radius: .3em;\n  white-space: normal;\n}\n\n.token.comment,\n.token.prolog,\n.token.doctype,\n.token.cdata {\n  color: slategray;\n}\n\n.token.punctuation {\n  color: #999;\n}\n\n.namespace {\n  opacity: .7;\n}\n\n.token.property,\n.token.tag,\n.token.boolean,\n.token.number,\n.token.constant,\n.token.symbol,\n.token.deleted {\n  color: #905;\n}\n\n.token.selector,\n.token.attr-name,\n.token.string,\n.token.char,\n.token.builtin,\n.token.inserted {\n  color: #690;\n}\n\n.token.operator,\n.token.entity,\n.token.url,\n.language-css .token.string,\n.style .token.string {\n  color: #9a6e3a;\n  background: hsla(0, 0%, 100%, .5);\n}\n\n.token.atrule,\n.token.attr-value,\n.token.keyword {\n  color: #07a;\n}\n\n.token.function,\n.token.class-name {\n  color: #DD4A68;\n}\n\n.token.regex,\n.token.important,\n.token.variable {\n  color: #e90;\n}\n\n.token.important,\n.token.bold {\n  font-weight: bold;\n}\n\n.token.italic {\n  font-style: italic;\n}\n\n.token.entity {\n  cursor: help;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/iconfont-es/demo_index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\"/>\n  <title>IconFont Demo</title>\n  <link rel=\"shortcut icon\" href=\"//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico\" type=\"image/x-icon\"/>\n  <link rel=\"icon\" type=\"image/svg+xml\" href=\"//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.svg\"/>\n  <link rel=\"stylesheet\" href=\"https://g.alicdn.com/thx/cube/1.3.2/cube.min.css\">\n  <link rel=\"stylesheet\" href=\"demo.css\">\n  <link rel=\"stylesheet\" href=\"iconfont.css\">\n  <script src=\"iconfont.js\"></script>\n  <!-- jQuery -->\n  <script src=\"https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js\"></script>\n  <!-- 代码高亮 -->\n  <script src=\"https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js\"></script>\n</head>\n<body>\n  <div class=\"main\">\n    <h1 class=\"logo\"><a href=\"https://www.iconfont.cn/\" title=\"iconfont 首页\" target=\"_blank\">&#xe86b;</a></h1>\n    <div class=\"nav-tabs\">\n      <ul id=\"tabs\" class=\"dib-box\">\n        <li class=\"dib active\"><span>Unicode</span></li>\n        <li class=\"dib\"><span>Font class</span></li>\n        <li class=\"dib\"><span>Symbol</span></li>\n      </ul>\n      \n      <a href=\"https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2457502\" target=\"_blank\" class=\"nav-more\">查看项目</a>\n      \n    </div>\n    <div class=\"tab-container\">\n      <div class=\"content unicode\" style=\"display: block;\">\n          <ul class=\"icon_lists dib-box\">\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe62f;</span>\n                <div class=\"name\">表格解释</div>\n                <div class=\"code-name\">&amp;#xe62f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe630;</span>\n                <div class=\"name\">步骤完成</div>\n                <div class=\"code-name\">&amp;#xe630;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe631;</span>\n                <div class=\"name\">弹框删除</div>\n                <div class=\"code-name\">&amp;#xe631;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe632;</span>\n                <div class=\"name\">表格排序</div>\n                <div class=\"code-name\">&amp;#xe632;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe633;</span>\n                <div class=\"name\">顶部导航展开</div>\n                <div class=\"code-name\">&amp;#xe633;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe634;</span>\n                <div class=\"name\">多选已选状态</div>\n                <div class=\"code-name\">&amp;#xe634;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe635;</span>\n                <div class=\"name\">多选不可选状态</div>\n                <div class=\"code-name\">&amp;#xe635;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe636;</span>\n                <div class=\"name\">多选未选状态</div>\n                <div class=\"code-name\">&amp;#xe636;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe637;</span>\n                <div class=\"name\">更多操作收起</div>\n                <div class=\"code-name\">&amp;#xe637;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe638;</span>\n                <div class=\"name\">告警ICON</div>\n                <div class=\"code-name\">&amp;#xe638;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe639;</span>\n                <div class=\"name\">顶部导航收起</div>\n                <div class=\"code-name\">&amp;#xe639;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63a;</span>\n                <div class=\"name\">关</div>\n                <div class=\"code-name\">&amp;#xe63a;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63b;</span>\n                <div class=\"name\">链接</div>\n                <div class=\"code-name\">&amp;#xe63b;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63c;</span>\n                <div class=\"name\">开</div>\n                <div class=\"code-name\">&amp;#xe63c;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63d;</span>\n                <div class=\"name\">更多操作缩起</div>\n                <div class=\"code-name\">&amp;#xe63d;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63e;</span>\n                <div class=\"name\">面包屑关闭</div>\n                <div class=\"code-name\">&amp;#xe63e;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe63f;</span>\n                <div class=\"name\">默认开不可点</div>\n                <div class=\"code-name\">&amp;#xe63f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe640;</span>\n                <div class=\"name\">面包屑删除</div>\n                <div class=\"code-name\">&amp;#xe640;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe641;</span>\n                <div class=\"name\">默认关不可点</div>\n                <div class=\"code-name\">&amp;#xe641;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe642;</span>\n                <div class=\"name\">上传中</div>\n                <div class=\"code-name\">&amp;#xe642;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe643;</span>\n                <div class=\"name\">日期</div>\n                <div class=\"code-name\">&amp;#xe643;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe644;</span>\n                <div class=\"name\">图标-info</div>\n                <div class=\"code-name\">&amp;#xe644;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe645;</span>\n                <div class=\"name\">刷新</div>\n                <div class=\"code-name\">&amp;#xe645;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe646;</span>\n                <div class=\"name\">日期悬浮</div>\n                <div class=\"code-name\">&amp;#xe646;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe647;</span>\n                <div class=\"name\">上传失败链接</div>\n                <div class=\"code-name\">&amp;#xe647;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe648;</span>\n                <div class=\"name\">图标-搜索</div>\n                <div class=\"code-name\">&amp;#xe648;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe649;</span>\n                <div class=\"name\">文件上传</div>\n                <div class=\"code-name\">&amp;#xe649;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64a;</span>\n                <div class=\"name\">悬浮文件上传</div>\n                <div class=\"code-name\">&amp;#xe64a;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64b;</span>\n                <div class=\"name\">文件删除</div>\n                <div class=\"code-name\">&amp;#xe64b;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64c;</span>\n                <div class=\"name\">左侧导航栏收起</div>\n                <div class=\"code-name\">&amp;#xe64c;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64d;</span>\n                <div class=\"name\">选择框收起</div>\n                <div class=\"code-name\">&amp;#xe64d;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64e;</span>\n                <div class=\"name\">选择框展开</div>\n                <div class=\"code-name\">&amp;#xe64e;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe64f;</span>\n                <div class=\"name\">左侧导航收起</div>\n                <div class=\"code-name\">&amp;#xe64f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe650;</span>\n                <div class=\"name\">左侧导航栏展开</div>\n                <div class=\"code-name\">&amp;#xe650;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe651;</span>\n                <div class=\"name\">左侧导航了收</div>\n                <div class=\"code-name\">&amp;#xe651;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe652;</span>\n                <div class=\"name\">左侧导航栏缩</div>\n                <div class=\"code-name\">&amp;#xe652;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe653;</span>\n                <div class=\"name\">左侧导航缩起</div>\n                <div class=\"code-name\">&amp;#xe653;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe654;</span>\n                <div class=\"name\">es logo</div>\n                <div class=\"code-name\">&amp;#xe654;</div>\n              </li>\n          \n          </ul>\n          <div class=\"article markdown\">\n          <h2 id=\"unicode-\">Unicode 引用</h2>\n          <hr>\n\n          <p>Unicode 是字体在网页端最原始的应用方式，特点是：</p>\n          <ul>\n            <li>兼容性最好，支持 IE6+，及所有现代浏览器。</li>\n            <li>支持按字体的方式去动态调整图标大小，颜色等等。</li>\n            <li>但是因为是字体，所以不支持多色。只能使用平台里单色的图标，就算项目里有多色图标也会自动去色。</li>\n          </ul>\n          <blockquote>\n            <p>注意：新版 iconfont 支持多色图标，这些多色图标在 Unicode 模式下将不能使用，如果有需求建议使用symbol 的引用方式</p>\n          </blockquote>\n          <p>Unicode 使用步骤如下：</p>\n          <h3 id=\"-font-face\">第一步：拷贝项目下面生成的 <code>@font-face</code></h3>\n<pre><code class=\"language-css\"\n>@font-face {\n  font-family: 'iconfont';\n  src: url('iconfont.eot');\n  src: url('iconfont.eot?#iefix') format('embedded-opentype'),\n      url('iconfont.woff2') format('woff2'),\n      url('iconfont.woff') format('woff'),\n      url('iconfont.ttf') format('truetype'),\n      url('iconfont.svg#iconfont') format('svg');\n}\n</code></pre>\n          <h3 id=\"-iconfont-\">第二步：定义使用 iconfont 的样式</h3>\n<pre><code class=\"language-css\"\n>.iconfont {\n  font-family: \"iconfont\" !important;\n  font-size: 16px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n</code></pre>\n          <h3 id=\"-\">第三步：挑选相应图标并获取字体编码，应用于页面</h3>\n<pre>\n<code class=\"language-html\"\n>&lt;span class=\"iconfont\"&gt;&amp;#x33;&lt;/span&gt;\n</code></pre>\n          <blockquote>\n            <p>\"iconfont\" 是你项目下的 font-family。可以通过编辑项目查看，默认是 \"iconfont\"。</p>\n          </blockquote>\n          </div>\n      </div>\n      <div class=\"content font-class\">\n        <ul class=\"icon_lists dib-box\">\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconbiaogejieshi\"></span>\n            <div class=\"name\">\n              表格解释\n            </div>\n            <div class=\"code-name\">.iconbiaogejieshi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconbuzhouwancheng\"></span>\n            <div class=\"name\">\n              步骤完成\n            </div>\n            <div class=\"code-name\">.iconbuzhouwancheng\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icondankuangshanchu\"></span>\n            <div class=\"name\">\n              弹框删除\n            </div>\n            <div class=\"code-name\">.icondankuangshanchu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconbiaogepaixu\"></span>\n            <div class=\"name\">\n              表格排序\n            </div>\n            <div class=\"code-name\">.iconbiaogepaixu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icondingbudaohangzhankai\"></span>\n            <div class=\"name\">\n              顶部导航展开\n            </div>\n            <div class=\"code-name\">.icondingbudaohangzhankai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconduoxuanyixuanzhuangtai\"></span>\n            <div class=\"name\">\n              多选已选状态\n            </div>\n            <div class=\"code-name\">.iconduoxuanyixuanzhuangtai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconduoxuanbukexuanzhuangtai\"></span>\n            <div class=\"name\">\n              多选不可选状态\n            </div>\n            <div class=\"code-name\">.iconduoxuanbukexuanzhuangtai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconduoxuanweixuanzhuangtai\"></span>\n            <div class=\"name\">\n              多选未选状态\n            </div>\n            <div class=\"code-name\">.iconduoxuanweixuanzhuangtai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icongengduocaozuoshouqi\"></span>\n            <div class=\"name\">\n              更多操作收起\n            </div>\n            <div class=\"code-name\">.icongengduocaozuoshouqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icongaojingICON\"></span>\n            <div class=\"name\">\n              告警ICON\n            </div>\n            <div class=\"code-name\">.icongaojingICON\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icondingbudaohangshouqi\"></span>\n            <div class=\"name\">\n              顶部导航收起\n            </div>\n            <div class=\"code-name\">.icondingbudaohangshouqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconguan\"></span>\n            <div class=\"name\">\n              关\n            </div>\n            <div class=\"code-name\">.iconguan\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconlianjie\"></span>\n            <div class=\"name\">\n              链接\n            </div>\n            <div class=\"code-name\">.iconlianjie\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconkai\"></span>\n            <div class=\"name\">\n              开\n            </div>\n            <div class=\"code-name\">.iconkai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icongengduocaozuosuoqi\"></span>\n            <div class=\"name\">\n              更多操作缩起\n            </div>\n            <div class=\"code-name\">.icongengduocaozuosuoqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconmianbaoxieguanbi\"></span>\n            <div class=\"name\">\n              面包屑关闭\n            </div>\n            <div class=\"code-name\">.iconmianbaoxieguanbi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconmorenkaibukedian\"></span>\n            <div class=\"name\">\n              默认开不可点\n            </div>\n            <div class=\"code-name\">.iconmorenkaibukedian\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconmianbaoxieshanchu\"></span>\n            <div class=\"name\">\n              面包屑删除\n            </div>\n            <div class=\"code-name\">.iconmianbaoxieshanchu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconmorenguanbukedian\"></span>\n            <div class=\"name\">\n              默认关不可点\n            </div>\n            <div class=\"code-name\">.iconmorenguanbukedian\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconshangchuanzhong\"></span>\n            <div class=\"name\">\n              上传中\n            </div>\n            <div class=\"code-name\">.iconshangchuanzhong\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconriqi\"></span>\n            <div class=\"name\">\n              日期\n            </div>\n            <div class=\"code-name\">.iconriqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontubiao-info\"></span>\n            <div class=\"name\">\n              图标-info\n            </div>\n            <div class=\"code-name\">.icontubiao-info\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconshuaxin\"></span>\n            <div class=\"name\">\n              刷新\n            </div>\n            <div class=\"code-name\">.iconshuaxin\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconriqixuanfu\"></span>\n            <div class=\"name\">\n              日期悬浮\n            </div>\n            <div class=\"code-name\">.iconriqixuanfu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconshangchuanshibailianjie\"></span>\n            <div class=\"name\">\n              上传失败链接\n            </div>\n            <div class=\"code-name\">.iconshangchuanshibailianjie\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icontubiao-sousuo\"></span>\n            <div class=\"name\">\n              图标-搜索\n            </div>\n            <div class=\"code-name\">.icontubiao-sousuo\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconwenjianshangchuan\"></span>\n            <div class=\"name\">\n              文件上传\n            </div>\n            <div class=\"code-name\">.iconwenjianshangchuan\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxuanfuwenjianshangchuan\"></span>\n            <div class=\"name\">\n              悬浮文件上传\n            </div>\n            <div class=\"code-name\">.iconxuanfuwenjianshangchuan\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconwenjianshanchu\"></span>\n            <div class=\"name\">\n              文件删除\n            </div>\n            <div class=\"code-name\">.iconwenjianshanchu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohanglanshouqi\"></span>\n            <div class=\"name\">\n              左侧导航栏收起\n            </div>\n            <div class=\"code-name\">.iconzuocedaohanglanshouqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxuanzekuangshouqi\"></span>\n            <div class=\"name\">\n              选择框收起\n            </div>\n            <div class=\"code-name\">.iconxuanzekuangshouqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconxuanzekuangzhankai\"></span>\n            <div class=\"name\">\n              选择框展开\n            </div>\n            <div class=\"code-name\">.iconxuanzekuangzhankai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohangshouqi\"></span>\n            <div class=\"name\">\n              左侧导航收起\n            </div>\n            <div class=\"code-name\">.iconzuocedaohangshouqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohanglanzhankai\"></span>\n            <div class=\"name\">\n              左侧导航栏展开\n            </div>\n            <div class=\"code-name\">.iconzuocedaohanglanzhankai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohangleshou\"></span>\n            <div class=\"name\">\n              左侧导航了收\n            </div>\n            <div class=\"code-name\">.iconzuocedaohangleshou\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohanglansuo\"></span>\n            <div class=\"name\">\n              左侧导航栏缩\n            </div>\n            <div class=\"code-name\">.iconzuocedaohanglansuo\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconzuocedaohangsuoqi\"></span>\n            <div class=\"name\">\n              左侧导航缩起\n            </div>\n            <div class=\"code-name\">.iconzuocedaohangsuoqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont iconeslogo\"></span>\n            <div class=\"name\">\n              es logo\n            </div>\n            <div class=\"code-name\">.iconeslogo\n            </div>\n          </li>\n          \n        </ul>\n        <div class=\"article markdown\">\n        <h2 id=\"font-class-\">font-class 引用</h2>\n        <hr>\n\n        <p>font-class 是 Unicode 使用方式的一种变种，主要是解决 Unicode 书写不直观，语意不明确的问题。</p>\n        <p>与 Unicode 使用方式相比，具有如下特点：</p>\n        <ul>\n          <li>兼容性良好，支持 IE8+，及所有现代浏览器。</li>\n          <li>相比于 Unicode 语意明确，书写更直观。可以很容易分辨这个 icon 是什么。</li>\n          <li>因为使用 class 来定义图标，所以当要替换图标时，只需要修改 class 里面的 Unicode 引用。</li>\n          <li>不过因为本质上还是使用的字体，所以多色图标还是不支持的。</li>\n        </ul>\n        <p>使用步骤如下：</p>\n        <h3 id=\"-fontclass-\">第一步：引入项目下面生成的 fontclass 代码：</h3>\n<pre><code class=\"language-html\">&lt;link rel=\"stylesheet\" href=\"./iconfont.css\"&gt;\n</code></pre>\n        <h3 id=\"-\">第二步：挑选相应图标并获取类名，应用于页面：</h3>\n<pre><code class=\"language-html\">&lt;span class=\"iconfont iconxxx\"&gt;&lt;/span&gt;\n</code></pre>\n        <blockquote>\n          <p>\"\n            iconfont\" 是你项目下的 font-family。可以通过编辑项目查看，默认是 \"iconfont\"。</p>\n        </blockquote>\n      </div>\n      </div>\n      <div class=\"content symbol\">\n          <ul class=\"icon_lists dib-box\">\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconbiaogejieshi\"></use>\n                </svg>\n                <div class=\"name\">表格解释</div>\n                <div class=\"code-name\">#iconbiaogejieshi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconbuzhouwancheng\"></use>\n                </svg>\n                <div class=\"name\">步骤完成</div>\n                <div class=\"code-name\">#iconbuzhouwancheng</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icondankuangshanchu\"></use>\n                </svg>\n                <div class=\"name\">弹框删除</div>\n                <div class=\"code-name\">#icondankuangshanchu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconbiaogepaixu\"></use>\n                </svg>\n                <div class=\"name\">表格排序</div>\n                <div class=\"code-name\">#iconbiaogepaixu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icondingbudaohangzhankai\"></use>\n                </svg>\n                <div class=\"name\">顶部导航展开</div>\n                <div class=\"code-name\">#icondingbudaohangzhankai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconduoxuanyixuanzhuangtai\"></use>\n                </svg>\n                <div class=\"name\">多选已选状态</div>\n                <div class=\"code-name\">#iconduoxuanyixuanzhuangtai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconduoxuanbukexuanzhuangtai\"></use>\n                </svg>\n                <div class=\"name\">多选不可选状态</div>\n                <div class=\"code-name\">#iconduoxuanbukexuanzhuangtai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconduoxuanweixuanzhuangtai\"></use>\n                </svg>\n                <div class=\"name\">多选未选状态</div>\n                <div class=\"code-name\">#iconduoxuanweixuanzhuangtai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icongengduocaozuoshouqi\"></use>\n                </svg>\n                <div class=\"name\">更多操作收起</div>\n                <div class=\"code-name\">#icongengduocaozuoshouqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icongaojingICON\"></use>\n                </svg>\n                <div class=\"name\">告警ICON</div>\n                <div class=\"code-name\">#icongaojingICON</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icondingbudaohangshouqi\"></use>\n                </svg>\n                <div class=\"name\">顶部导航收起</div>\n                <div class=\"code-name\">#icondingbudaohangshouqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconguan\"></use>\n                </svg>\n                <div class=\"name\">关</div>\n                <div class=\"code-name\">#iconguan</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconlianjie\"></use>\n                </svg>\n                <div class=\"name\">链接</div>\n                <div class=\"code-name\">#iconlianjie</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconkai\"></use>\n                </svg>\n                <div class=\"name\">开</div>\n                <div class=\"code-name\">#iconkai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icongengduocaozuosuoqi\"></use>\n                </svg>\n                <div class=\"name\">更多操作缩起</div>\n                <div class=\"code-name\">#icongengduocaozuosuoqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconmianbaoxieguanbi\"></use>\n                </svg>\n                <div class=\"name\">面包屑关闭</div>\n                <div class=\"code-name\">#iconmianbaoxieguanbi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconmorenkaibukedian\"></use>\n                </svg>\n                <div class=\"name\">默认开不可点</div>\n                <div class=\"code-name\">#iconmorenkaibukedian</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconmianbaoxieshanchu\"></use>\n                </svg>\n                <div class=\"name\">面包屑删除</div>\n                <div class=\"code-name\">#iconmianbaoxieshanchu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconmorenguanbukedian\"></use>\n                </svg>\n                <div class=\"name\">默认关不可点</div>\n                <div class=\"code-name\">#iconmorenguanbukedian</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconshangchuanzhong\"></use>\n                </svg>\n                <div class=\"name\">上传中</div>\n                <div class=\"code-name\">#iconshangchuanzhong</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconriqi\"></use>\n                </svg>\n                <div class=\"name\">日期</div>\n                <div class=\"code-name\">#iconriqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontubiao-info\"></use>\n                </svg>\n                <div class=\"name\">图标-info</div>\n                <div class=\"code-name\">#icontubiao-info</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconshuaxin\"></use>\n                </svg>\n                <div class=\"name\">刷新</div>\n                <div class=\"code-name\">#iconshuaxin</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconriqixuanfu\"></use>\n                </svg>\n                <div class=\"name\">日期悬浮</div>\n                <div class=\"code-name\">#iconriqixuanfu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconshangchuanshibailianjie\"></use>\n                </svg>\n                <div class=\"name\">上传失败链接</div>\n                <div class=\"code-name\">#iconshangchuanshibailianjie</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icontubiao-sousuo\"></use>\n                </svg>\n                <div class=\"name\">图标-搜索</div>\n                <div class=\"code-name\">#icontubiao-sousuo</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconwenjianshangchuan\"></use>\n                </svg>\n                <div class=\"name\">文件上传</div>\n                <div class=\"code-name\">#iconwenjianshangchuan</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxuanfuwenjianshangchuan\"></use>\n                </svg>\n                <div class=\"name\">悬浮文件上传</div>\n                <div class=\"code-name\">#iconxuanfuwenjianshangchuan</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconwenjianshanchu\"></use>\n                </svg>\n                <div class=\"name\">文件删除</div>\n                <div class=\"code-name\">#iconwenjianshanchu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohanglanshouqi\"></use>\n                </svg>\n                <div class=\"name\">左侧导航栏收起</div>\n                <div class=\"code-name\">#iconzuocedaohanglanshouqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxuanzekuangshouqi\"></use>\n                </svg>\n                <div class=\"name\">选择框收起</div>\n                <div class=\"code-name\">#iconxuanzekuangshouqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconxuanzekuangzhankai\"></use>\n                </svg>\n                <div class=\"name\">选择框展开</div>\n                <div class=\"code-name\">#iconxuanzekuangzhankai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohangshouqi\"></use>\n                </svg>\n                <div class=\"name\">左侧导航收起</div>\n                <div class=\"code-name\">#iconzuocedaohangshouqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohanglanzhankai\"></use>\n                </svg>\n                <div class=\"name\">左侧导航栏展开</div>\n                <div class=\"code-name\">#iconzuocedaohanglanzhankai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohangleshou\"></use>\n                </svg>\n                <div class=\"name\">左侧导航了收</div>\n                <div class=\"code-name\">#iconzuocedaohangleshou</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohanglansuo\"></use>\n                </svg>\n                <div class=\"name\">左侧导航栏缩</div>\n                <div class=\"code-name\">#iconzuocedaohanglansuo</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconzuocedaohangsuoqi\"></use>\n                </svg>\n                <div class=\"name\">左侧导航缩起</div>\n                <div class=\"code-name\">#iconzuocedaohangsuoqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#iconeslogo\"></use>\n                </svg>\n                <div class=\"name\">es logo</div>\n                <div class=\"code-name\">#iconeslogo</div>\n            </li>\n          \n          </ul>\n          <div class=\"article markdown\">\n          <h2 id=\"symbol-\">Symbol 引用</h2>\n          <hr>\n\n          <p>这是一种全新的使用方式，应该说这才是未来的主流，也是平台目前推荐的用法。相关介绍可以参考这篇<a href=\"\">文章</a>\n            这种用法其实是做了一个 SVG 的集合，与另外两种相比具有如下特点：</p>\n          <ul>\n            <li>支持多色图标了，不再受单色限制。</li>\n            <li>通过一些技巧，支持像字体那样，通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>\n            <li>兼容性较差，支持 IE9+，及现代浏览器。</li>\n            <li>浏览器渲染 SVG 的性能一般，还不如 png。</li>\n          </ul>\n          <p>使用步骤如下：</p>\n          <h3 id=\"-symbol-\">第一步：引入项目下面生成的 symbol 代码：</h3>\n<pre><code class=\"language-html\">&lt;script src=\"./iconfont.js\"&gt;&lt;/script&gt;\n</code></pre>\n          <h3 id=\"-css-\">第二步：加入通用 CSS 代码（引入一次就行）：</h3>\n<pre><code class=\"language-html\">&lt;style&gt;\n.icon {\n  width: 1em;\n  height: 1em;\n  vertical-align: -0.15em;\n  fill: currentColor;\n  overflow: hidden;\n}\n&lt;/style&gt;\n</code></pre>\n          <h3 id=\"-\">第三步：挑选相应图标并获取类名，应用于页面：</h3>\n<pre><code class=\"language-html\">&lt;svg class=\"icon\" aria-hidden=\"true\"&gt;\n  &lt;use xlink:href=\"#icon-xxx\"&gt;&lt;/use&gt;\n&lt;/svg&gt;\n</code></pre>\n          </div>\n      </div>\n\n    </div>\n  </div>\n  <script>\n  $(document).ready(function () {\n      $('.tab-container .content:first').show()\n\n      $('#tabs li').click(function (e) {\n        var tabContent = $('.tab-container .content')\n        var index = $(this).index()\n\n        if ($(this).hasClass('active')) {\n          return\n        } else {\n          $('#tabs li').removeClass('active')\n          $(this).addClass('active')\n\n          tabContent.hide().eq(index).fadeIn()\n        }\n      })\n    })\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/iconfont-es/iconfont.css",
    "content": "@font-face {font-family: \"iconfont\";\n  src: url('iconfont.eot?t=1619350462649'); /* IE9 */\n  src: url('iconfont.eot?t=1619350462649#iefix') format('embedded-opentype'), /* IE6-IE8 */\n  url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAzMAAsAAAAAGSQAAAx7AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCGdgqbcJYtATYCJAOBEAtKAAQgBYRtB4UcG00VM6PCxgEgUA+S/dcJ9JirdugY+35xAAHRMoXYZHYKWup0uWElaim1wMr3c72dTYWTCbLlmaGUPjyd+i7/B8WQgkoKXyorHZsMADIYN9975eTOk81WQamtwKBCcPT8ZPqZef1b6M5tFxUQFJ9cpqsTkR8ZltPxV7c9pQFSITXODJrb7tWnyDyTqbQGQbJsc7V8L3mlkSiB0niNJ9kAGKZ3ngGaUAEE/DX9Zv9eo3R3g6rXnzthaAqp0n/e7gZuQ93rPZ+aq00dKOYcrhWhkk9LKKUpJINCg3AMRhzGatycAccjhh4tC9nGjTBqUv3MF2bn84EBoA4zuICJiErIgAgUkjI4pqG2uhSiwl5QxToGot0C4r70GDMJfIh4o3nnAEyMfj/zBl6MCOCBTyBfKKUqsgLsc/fnGUTBKVBAlFDqkwCcBwEEgAsACjALyIpZIAm6RIx6S1UwP2qao09MjgsQ6FurwZvK5IrJk1RqjVanNxhNZvxn3qK3XK0328Fufziezpfr7f54viRlJ4/uIfkTnR8BPCAhIJASCMgIDOQEAQqCAiXBgIrgQE0IoCEk0BIK6AgN9IQBBsICI+GAifDALIKu5hHAQiRdH88AlqIAK1GBtWjARnRgK4a+LXwBsBMrsBebcADfIRzBDwgn8BPCGfyCcAG/IVzBHwg38BfCHfyD8AD/ITzBJ/p5wTu4x5fv7L/4ldZNqd97bYlU0mNpxPKK8XxwsntNM51M6ZSOxsNi7ks1vWPCyTo4AT9RnoRpF35lzXlT9R1m13zPsDX5Xmm5jpm2+I8yjWCU4fManUIvgqzBVAcj+4/o/JW8/4r7r8U6G8eJczRJmykFEhpJLU1K4/z7qibqqmzoioZCMVYNWrweTgjlWijK+sNxwYiQ1rabT6eiLAm0ph8jug8B1IR+i8rHlZIqK1L54xEtJkBgwv4WVYhR1gukuwezDU2Z3qnZFwGu0fBtyhPJ9p/agzBXIo96H1r3zQeo7frjzpGsRD5F/RjqZqN/FOP9R1/sXaptybyLlS350JDJqqnB553lXHrCHW+lkbiELz68C58vU1PmAzJV+W1u20vCF3GnYGTfkTetaWdqtnco39SQ6g6kX00Vmpv5sMWKcvh6kpPEoMlxISIoUgKzmJeVCFZc17JrqeksJZ4Huw1fXRwjKaFZG2K5iM9Yk1U9s9kioK1VBrh0z9bie4Sn6EYWo61vgzdcucBDmIUhEuJGMxSO0HQiABvUAYEZPEYYtlVCq6+r7A+YPkGTL2fAgRRhs6bwIseRbFvsLNLzDlspM30rizMHrF2PxfPYtBARqM6piXs0uREIxcCsycHbLJtK3YZgEkB1iBqWcNqpwj1BuEThFR9Rrhbz2hjqKZF4/GxfH6sblfWguL2rAXYKJPw5oV32k1E6EbjsegqRw1hYGSFHHOfQxbmy+0vxfh+zT0nOacXL/8Fua/9cOqdfLq1ry+Q89XxxRe/JELDA5PnzIUVTx32UOZCjngs9Qj+B4oMv17bp6g7UGopF+2DbhS4TArpuFcpE/GwxvC8a41pDpFkuyo4kxBvFRYkCxAWKfNLYoerbEChRTpkIAlUt9LyKs+uPH8vNqY5sS8THkxbKigEX9lJ4DvPCGQNuQsvexy/jbnnkzVWSQOFM1/Fc5gpQdA33xV3lmrfTkZiyq+6Kdx59eO9x34YJs8le9tattVz38qraSB3vpewg3jePOkEJWzgH91nVXtdlr4OHldLnM+LWp1EdD0fnmj/yxOi8H1ZG9ZPZazK9M/w9e8Mto1sNvfXOuZwzmVV1vgo5UxVdXX7po/sPWj/hI4AoiosXyjGDQEgfGX3cPiaxWa4nT8eY7R9LCk1nXk0sBhxSyFtwWG9M4NZZQwPbzTRz7ECG5s7vWrDAxfl4zgNv09PmDbt1Ij1jaD/wv3gusF8w32G+cRXwtmZmAp8BqU9MZsrolbalL8ac/Hzqa+6Yo5MWK1dHlILr+UCv6OldiU05j17JWkXVOhvb9EDr9cbpggy/dL9yDNiqkJds0PL2oMAxejBpj356iAI0aw8BI3PB8Ak7RpnhWuPHh7NblBseGr6ld1JSl+5/XfkuNvlFd+0yqXTk389l2uETJ3w09DBkFumjr1LJeIg9IGPlulyTszLzbJhzcvWDUw7puh3xGqkPTeQR9MherN+6aHNrjCpHPNtk9urVq1bfzZ1+Hrg6b5U7VxtHGM+xew+bExO9O/FCb5g0KXH3BWVHFXq9yXsvW7yFvQcNXBy2ZVEY7TCSsMSix1kchpClVZLM0MoBA/r3rwzdG5qFfgMGZLKZks7gapGu4HvB2QO+dFYwLEj5eSoW0/ORZNPr15sIu4m+fkU2RdLzYvF5Cr2plcJRQlGOv2iW0C95Gl9mnbBbUCaUC9cJRgrLBN3C7/X+vKUG898IZwt9Jxvf3DRI0Jy50QuABWH3079/6QMro/rJ7Lvd1qO9135fyRmHs+RHnt5DXrL6JKlHGJ+6BR2Zbqz/jrf3oH6fhjkus0eL/eLyiyZp66op/CxSBQLD46/b9pje7/7pH/9aExGH3yM9PbbhoXwIVNTKgn9bil5HRRcy/1eHTAm0fRzTZhYn6b46fii2k48fyFYoiNlOWnGwPrC4sQH64eyOSe9gb1CJV4RZKJALzJ2KiD6pT3WeqZp0PGVks0dwfIsq6kd15mLvceDlMX//AYmmdHa4Zvj+/VJNyZrvdSPjk5P8r/jdnjP7lt8V/6TkzsG8iK6BA7simBFbC8vQa8sKEVZQxvwrKC0t/A+cEJutvwkOgV3I9R6eO3yYzwoOH7mLQOoEV2uDMZeiqltwr9qoS2OOXnzu9Dzy6aLIRZe8qKhF6y7qReqB6+EuuZ1b4idzg2ypoVe7XU3EMBPNikPQNBkWUVO8mDVmkC2qbc17dXk6Ovj0W3GF+G37tpDV4CGHqgOXeFSnUSzyYxHL8rDDRjU5JrZEjMqULO4SZkOuirtUC+2cbGOP1r6d/J/p3ydT2WMVrUkuJceoifStEpQRrsOFbIOJ7drguuhYcBJn/ZTy35ci1HI1o616lOkX1KIlD2fmFrRFJElqRibSmOC6NY4NhuwQ3K6IzBYX2PtvGmGbHphXVpydu9TaK882Kso2r9ImLzrqefvCIs8mKrqoNEYhwtUxzmy2WZwjk9XensVYGZfJyr5CnLmj1HVIbIK9QVySMvWQ5mXPZfwUS5k51f6PPv847iPkIuV6SD1RcN84hUiDKABuJXlFcgHuAjlCvABuDblBsri/3Gn+XhIAcJPIR1LDDd8laCMxAECm835wyIkyX45tPRREKSoUlIk2ziLPSQWZQ6rKDhEzVsUSdVhFTZDyjofkErGIMjelvUWWEEMAoOBxN24VJhIbvAuSWK7gdeuwVLrY6r0BdZvkNPKWY3zq3gxmQlVccZ+gbyL6r7n57tqOA5G6f6TnWCUAEXhf0MavrhBBobYY8U1tyr02dG1VgCDSPI05kxab+Tu4v9RKQe1qwZqTOI6nezOnmA6LpF4DO6Z7OW7rNttgMNTaeADU580AB1mjhfv7sEf3P0EyEBUMJ48HIUzzCESwITTbJY8PDUjzBBAhNE8dzoh+sAa00QYChqoBcMJwI49BX2zM46E3DiKhss8jRfa9PD708M4WYBVD8tSRxWg/pgbsbvnfuckQCvSFdxYk2ao+UHTiY79RuwgyYVm3+8csJ7Zit97Ouh/QYqYjJj/ofVEooTKOxb0RgVHEIsk4QFmsDbqS681G9WPXkuNSByVDKIKivuCdS5NkqxYuOpVf/43aRZApxhyX/scsp+sXdta2DPLALGvMbfHnB71XCKmENzjjWLgXEqN5BwsJfaMAZbFmWrQl1zZiLsVl6/U78S3EuotvXPkUVwIKBg4BCQWNT+gf2cEjICLNy7rtD8fT+fLx+fV9vd0fz9dbr4yANQaEuaGB5y6G3RGsNGj10AcbOrA6N5V9rsuLS4BObuaT1Z7zgWmpL2bsBVr4jk8Lu2cK3Itp11QAXdWd6bkQe9nLUxxxYTHVa1bpXhL44hh+dil1NXCwvnOfbj7ep0NDJWp6ybZmRGD3A6sbMsekA4/jlEZxU4oHfCJknubRuGTuHx1GqG1tUzxsdS2j9bqF223viqziZk7Xn8h2+toWVynXb5I5u1XI8RFXPw9sJ3y5yNjUzMFMtXC+ifsl7hCNhDZj46Pi4DnQKltPzIM+a7Kc0Z9roWlclhthb64JtO0frUs7bH0bmEesuVQCAAAA') format('woff2'),\n  url('iconfont.woff?t=1619350462649') format('woff'),\n  url('iconfont.ttf?t=1619350462649') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */\n  url('iconfont.svg?t=1619350462649#iconfont') format('svg'); /* iOS 4.1- */\n}\n\n.iconfont {\n  font-family: \"iconfont\" !important;\n  font-size: 16px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n.iconbiaogejieshi:before {\n  content: \"\\e62f\";\n}\n\n.iconbuzhouwancheng:before {\n  content: \"\\e630\";\n}\n\n.icondankuangshanchu:before {\n  content: \"\\e631\";\n}\n\n.iconbiaogepaixu:before {\n  content: \"\\e632\";\n}\n\n.icondingbudaohangzhankai:before {\n  content: \"\\e633\";\n}\n\n.iconduoxuanyixuanzhuangtai:before {\n  content: \"\\e634\";\n}\n\n.iconduoxuanbukexuanzhuangtai:before {\n  content: \"\\e635\";\n}\n\n.iconduoxuanweixuanzhuangtai:before {\n  content: \"\\e636\";\n}\n\n.icongengduocaozuoshouqi:before {\n  content: \"\\e637\";\n}\n\n.icongaojingICON:before {\n  content: \"\\e638\";\n}\n\n.icondingbudaohangshouqi:before {\n  content: \"\\e639\";\n}\n\n.iconguan:before {\n  content: \"\\e63a\";\n}\n\n.iconlianjie:before {\n  content: \"\\e63b\";\n}\n\n.iconkai:before {\n  content: \"\\e63c\";\n}\n\n.icongengduocaozuosuoqi:before {\n  content: \"\\e63d\";\n}\n\n.iconmianbaoxieguanbi:before {\n  content: \"\\e63e\";\n}\n\n.iconmorenkaibukedian:before {\n  content: \"\\e63f\";\n}\n\n.iconmianbaoxieshanchu:before {\n  content: \"\\e640\";\n}\n\n.iconmorenguanbukedian:before {\n  content: \"\\e641\";\n}\n\n.iconshangchuanzhong:before {\n  content: \"\\e642\";\n}\n\n.iconriqi:before {\n  content: \"\\e643\";\n}\n\n.icontubiao-info:before {\n  content: \"\\e644\";\n}\n\n.iconshuaxin:before {\n  content: \"\\e645\";\n}\n\n.iconriqixuanfu:before {\n  content: \"\\e646\";\n}\n\n.iconshangchuanshibailianjie:before {\n  content: \"\\e647\";\n}\n\n.icontubiao-sousuo:before {\n  content: \"\\e648\";\n}\n\n.iconwenjianshangchuan:before {\n  content: \"\\e649\";\n}\n\n.iconxuanfuwenjianshangchuan:before {\n  content: \"\\e64a\";\n}\n\n.iconwenjianshanchu:before {\n  content: \"\\e64b\";\n}\n\n.iconzuocedaohanglanshouqi:before {\n  content: \"\\e64c\";\n}\n\n.iconxuanzekuangshouqi:before {\n  content: \"\\e64d\";\n}\n\n.iconxuanzekuangzhankai:before {\n  content: \"\\e64e\";\n}\n\n.iconzuocedaohangshouqi:before {\n  content: \"\\e64f\";\n}\n\n.iconzuocedaohanglanzhankai:before {\n  content: \"\\e650\";\n}\n\n.iconzuocedaohangleshou:before {\n  content: \"\\e651\";\n}\n\n.iconzuocedaohanglansuo:before {\n  content: \"\\e652\";\n}\n\n.iconzuocedaohangsuoqi:before {\n  content: \"\\e653\";\n}\n\n.iconeslogo:before {\n  content: \"\\e654\";\n}\n\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/iconfont-es/iconfont.js",
    "content": "!function(a){var l,i,o,h,t,n,e='<svg><symbol id=\"iconbiaogejieshi\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 0 0 1024A512 512 0 0 0 512 0z\" fill=\"#515A6F\" ></path><path d=\"M512 819.2a51.2 51.2 0 1 1 0-102.4 51.2 51.2 0 0 1 0 102.4zM563.2 665.6H460.8V204.8h102.4z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconbuzhouwancheng\" viewBox=\"0 0 1536 1024\"><path d=\"M1417.045333 0L1536 119.466667 635.136 1024 0 386.218667l118.954667-119.466667 516.181333 518.229333z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"icondankuangshanchu\" viewBox=\"0 0 1024 1024\"><path d=\"M928.256 0L1024 95.744 607.6416 511.8976 1024 928.256 928.256 1024 512 607.6416 95.744 1024 0 928.256 416.256 512 0 95.744 95.744 0 512 416.256 928.256 0z\" fill=\"#8C8C8C\" ></path></symbol><symbol id=\"iconbiaogepaixu\" viewBox=\"0 0 1024 1024\"><path d=\"M846.326305 614.397542c20.069818 0 31.231094 20.069818 18.841053 33.791021L530.841054 1016.101093a26.418434 26.418434 0 0 1-37.682108 0L158.832642 648.188563C146.442601 634.46736 157.603877 614.397542 177.673695 614.397542zM530.841054 7.899931L865.167358 375.812461c12.390041 13.721202 1.228764 33.79102-18.841053 33.79102H177.673695C157.603877 409.603481 146.442601 389.533664 158.730245 375.812461L493.158946 7.899931a26.418434 26.418434 0 0 1 37.682108 0z\" fill=\"#A8ADBD\" ></path></symbol><symbol id=\"icondingbudaohangzhankai\" viewBox=\"0 0 2048 1024\"><path d=\"M1979.59424 1024H68.81024c-57.344 0-89.344-50.176-53.76-84.48L970.44224 19.712a83.2 83.2 0 0 1 107.52 0L2033.35424 939.52c35.584 34.304 3.584 84.48-53.76 84.48z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconduoxuanyixuanzhuangtai\" viewBox=\"0 0 1024 1024\"><path d=\"M55.768615 39.384615m157.538462 0l630.153846 0q157.538462 0 157.538462 157.538462l0 630.153846q0 157.538462-157.538462 157.538462l-630.153846 0q-157.538462 0-157.538462-157.538462l0-630.153846q0-157.538462 157.538462-157.538462Z\" fill=\"#2F81F9\" ></path><path d=\"M758.705231 275.692308L843.460923 359.424 430.08 748.307692 213.307077 548.785231l83.810461-84.598154L429.134769 585.806769z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconduoxuanbukexuanzhuangtai\" viewBox=\"0 0 1024 1024\"><path d=\"M95.153231 78.769231m157.538461 0l551.384616 0q157.538462 0 157.538461 157.538461l0 551.384616q0 157.538462-157.538461 157.538461l-551.384616 0q-157.538462 0-157.538461-157.538461l0-551.384616q0-157.538462 157.538461-157.538461Z\" fill=\"#D7DAE5\" fill-opacity=\".12\" ></path></symbol><symbol id=\"iconduoxuanweixuanzhuangtai\" viewBox=\"0 0 1024 1024\"><path d=\"M42.666667 42.666667m85.333333 0l768 0q85.333333 0 85.333333 85.333333l0 768q0 85.333333-85.333333 85.333333l-768 0q-85.333333 0-85.333333-85.333333l0-768q0-85.333333 85.333333-85.333333Z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"icongengduocaozuoshouqi\" viewBox=\"0 0 1462 1024\"><path d=\"M1310.016366 100.205714a95.817143 95.817143 0 0 1 121.709714-9.801143c32.621714 23.405714 40.228571 63.341714 20.041143 94.354286l-8.777143 11.117714L731.456366 950.857143 18.167223 193.828571C-11.08992 160.914286-4.360777 114.102857 33.527223 88.795429a96.841143 96.841143 0 0 1 110.592 3.510857l10.678857 9.801143 581.339429 609.426285L1310.016366 100.059429z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"icongaojingICON\" viewBox=\"0 0 1024 1024\"><path d=\"M512 512m-495.483871 0a495.483871 495.483871 0 1 0 990.967742 0 495.483871 495.483871 0 1 0-990.967742 0Z\" fill=\"#F4A838\" ></path><path d=\"M543.149419 661.20671l21.239742-432.326194h-114.688l21.239742 432.326194h72.208516z m-36.533677 174.146064c18.696258 0 33.990194-5.945806 47.566452-17.837419 11.891613-11.891613 18.696258-28.044387 18.696258-46.740645a62.76129 62.76129 0 0 0-18.696258-45.848775c-12.750452-11.891613-28.870194-17.837419-47.566452-17.837419s-33.957161 5.945806-45.848774 17.837419c-13.60929 11.891613-19.555097 27.185548-19.555097 45.848775 0 18.696258 5.945806 33.990194 19.555097 45.881806a62.76129 62.76129 0 0 0 45.848774 18.696258z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"icondingbudaohangshouqi\" viewBox=\"0 0 2048 1024\"><path d=\"M1979.392 0H68.608C11.264 0-20.48 50.176 14.848 84.48L970.24 1004.288a83.2 83.2 0 0 0 107.52 0L2033.152 84.48C2068.48 50.176 2036.736 0 1979.392 0z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"iconguan\" viewBox=\"0 0 1649 1024\"><path d=\"M455.111111 56.888889h739.555556a455.111111 455.111111 0 1 1 0 910.222222H455.111111A455.111111 455.111111 0 1 1 455.111111 56.888889z\" fill=\"#D7DAE5\" ></path></symbol><symbol id=\"iconlianjie\" viewBox=\"0 0 1024 1024\"><path d=\"M868.205714 188.269714c64.512 66.413714 62.610286 172.763429-2.925714 238.226286l-343.917714 343.844571h-0.073143l-54.125714 54.125715a223.012571 223.012571 0 0 1-314.514286 0l-4.242286-4.242286a223.012571 223.012571 0 0 1 0-314.441143L483.035429 171.154286a26.038857 26.038857 0 0 1 36.864 36.864L185.197714 542.646857a168.228571 168.228571 0 0 0-37.156571 56.100572 171.52 171.52 0 0 0 37.156571 184.685714l4.242286 4.242286a168.228571 168.228571 0 0 0 56.100571 37.229714 171.52 171.52 0 0 0 184.685715-37.229714l353.133714-353.060572 46.153143-46.08c21.942857-21.942857 34.157714-51.346286 34.157714-82.724571a116.150857 116.150857 0 0 0-116.882286-116.809143c-31.451429 0-60.708571 12.068571-82.724571 34.084571L277.577143 609.499429a58.148571 58.148571 0 0 0-16.969143 41.398857 58.148571 58.148571 0 0 0 58.441143 58.514285 58.148571 58.148571 0 0 0 41.398857-17.042285l321.828571-321.828572a26.038857 26.038857 0 0 1 36.864 36.790857L398.262857 728.502857a111.542857 111.542857 0 0 1-156.598857 1.609143 110.957714 110.957714 0 0 1-0.731429-157.257143l386.413715-386.413714a168.594286 168.594286 0 0 1 119.515428-49.298286 168.155429 168.155429 0 0 1 121.417143 51.2z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconkai\" viewBox=\"0 0 1706 1024\"><path d=\"\"  ></path></symbol><symbol id=\"icongengduocaozuosuoqi\" viewBox=\"0 0 1462 1024\"><path d=\"M1309.988571 923.794286c30.427429 31.890286 84.845714 36.132571 121.709715 9.801143 32.621714-23.405714 40.228571-63.341714 20.041143-94.354286l-8.777143-11.117714L731.428571 73.142857 18.139429 830.171429c-29.257143 32.768-22.381714 79.725714 15.36 105.033142 33.645714 22.528 80.164571 20.187429 110.592-3.510857l10.678857-9.801143 581.339428-609.426285 573.878857 611.474285z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconmianbaoxieguanbi\" viewBox=\"0 0 1024 1024\"><path d=\"M730.823196 294.729286l-1.599835-1.599835a34.236469 34.236469 0 0 0-48.379011 0L511.325831 462.83995l-169.582511-169.582512a34.172476 34.172476 0 1 0-48.443005 48.443004l169.582512 169.582512-169.646505 169.582512a34.172476 34.172476 0 0 0 0 48.379011l1.599835 1.599835c13.310627 13.374621 35.00439 13.374621 48.443004 0l169.582512-169.582512 169.582512 169.582512a34.236469 34.236469 0 1 0 48.379011-48.506998l-169.582512-169.582512 169.582512-169.582512a34.236469 34.236469 0 0 0 0-48.443004\" fill=\"#505568\" ></path><path d=\"M873.91244 149.976214a511.819219 511.819219 0 0 0-723.957342 0 511.947205 511.947205 0 0 0 0 724.021335 511.755225 511.755225 0 0 0 723.957342 0 511.755225 511.755225 0 0 0 0-724.021335M198.206122 825.746525a443.53826 443.53826 0 0 1 0-627.455294 443.53826 443.53826 0 0 1 627.455294 0 443.602254 443.602254 0 0 1 0 627.3913 443.602254 443.602254 0 0 1-627.455294 0z\" fill=\"#505568\" ></path></symbol><symbol id=\"iconmorenkaibukedian\" viewBox=\"0 0 1706 1024\"><path d=\"\"  ></path></symbol><symbol id=\"iconmianbaoxieshanchu\" viewBox=\"0 0 1024 1024\"><path d=\"M1001.654601 26.021424L998.198731 22.437559a76.54113 76.54113 0 0 0-108.283939 0L510.409023 402.071322 131.03125 22.693549a76.54113 76.54113 0 0 0-108.28394 0 76.285139 76.285139 0 0 0 0 108.283939l379.505769 379.505769L22.49132 889.86103a76.413135 76.413135 0 0 0 0 108.28394l3.711861 3.45587a76.669125 76.669125 0 0 0 108.283939 0L513.864894 622.095071l379.377773 379.377774a76.54113 76.54113 0 1 0 108.411934-108.411935L622.148833 513.811132 1001.654601 134.433359a76.669125 76.669125 0 0 0 0-108.411935\" fill=\"#505568\" ></path></symbol><symbol id=\"iconmorenguanbukedian\" viewBox=\"0 0 1649 1024\"><path d=\"M455.111111 56.888889h739.555556a455.111111 455.111111 0 1 1 0 910.222222H455.111111A455.111111 455.111111 0 1 1 455.111111 56.888889z\" fill=\"#D7DAE5\" ></path></symbol><symbol id=\"iconshangchuanzhong\" viewBox=\"0 0 1024 1024\"><path d=\"M512 28.672a485.632 485.632 0 0 1 485.376 485.290667h-69.376A416.085333 416.085333 0 0 0 512 97.962667V28.672z m0 901.290667a416.085333 416.085333 0 0 1-416-416H26.624A485.632 485.632 0 0 0 512 999.338667v-69.376z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconriqi\" viewBox=\"0 0 1024 1024\"><path d=\"M360.533333 26.709333c9.386667 0 17.066667 7.594667 17.066667 17.066667v55.466667l-0.256 2.048 343.893333 0.085333a17.237333 17.237333 0 0 1-0.170666-2.133333v-55.466667c0-9.472 7.68-17.066667 17.066666-17.066667h55.466667c9.386667 0 17.066667 7.594667 17.066667 17.066667v55.466667l-0.341334 2.048h172.032c8.277333 0 14.933333 6.741333 14.933334 14.933333v866.133333a14.933333 14.933333 0 0 1-14.933334 14.933334H41.728a14.933333 14.933333 0 0 1-14.933333-14.933334V116.224c0-8.192 6.656-14.933333 14.933333-14.933333l246.528 0.085333a17.237333 17.237333 0 0 1-0.170667-2.133333v-55.466667c0-9.472 7.68-17.066667 17.066667-17.066667h55.466667z m547.157334 164.181334H116.394667L116.053333 347.648l490.837334 0.085333c9.386667 0 17.066667 7.68 17.066666 17.066667v55.466667a17.066667 17.066667 0 0 1-17.066666 17.066666H116.053333l0.085334 470.357334h791.466666v-716.8z m-76.8 448c9.472 0 17.066667 7.68 17.066666 17.066666v174.933334a17.066667 17.066667 0 0 1-17.066666 17.066666h-174.933334a17.066667 17.066667 0 0 1-17.066666-17.066666v-174.933334c0-9.386667 7.68-17.066667 17.066666-17.066666h174.933334z\" fill=\"#505568\" ></path></symbol><symbol id=\"icontubiao-info\" viewBox=\"0 0 1024 1024\"><path d=\"M512 64a448 448 0 1 1 0 896A448 448 0 0 1 512 64z m-8.533333 645.461333a44.629333 44.629333 0 0 0-33.792 13.653334 43.264 43.264 0 0 0-13.312 33.536 46.165333 46.165333 0 0 0 47.104 47.957333 47.786667 47.786667 0 0 0 33.792-13.653333 44.373333 44.373333 0 0 0 14.165333-34.304 46.165333 46.165333 0 0 0-47.957333-47.189334zM519.082667 204.8c-60.245333 0-107.093333 18.432-140.544 55.296-31.317333 32.853333-47.274667 75.946667-49.152 129.28 0 6.485333 4.778667 11.349333 10.752 11.349333h51.882666l3.754667-0.853333a9.813333 9.813333 0 0 0 5.973333-8.789333l0.170667-4.266667c1.706667-31.488 9.557333-56.405333 23.381333-75.434667 17.237333-25.6 45.738667-41.216 81.664-41.216 30.208 0 65.536 6.656 87.04 32.682667 15.786667 17.066667 24.405333 35.669333 24.405334 66.730667 0 21.76-9.984 41.813333-24.405334 61.184-11.264 13.568-43.093333 37.973333-54.613333 50.432l-9.813333 9.642666c-24.490667 24.405333-34.986667 38.656-42.752 54.272l-5.632 12.117334c-8.618667 19.370667-16.554667 41.216-16.554667 66.901333v21.333333c0 5.888 4.778667 10.581333 10.666667 10.581334h55.637333l3.498667-0.682667a9.130667 9.130667 0 0 0 5.632-8.448v-10.069333l0.597333-13.312c1.621333-17.322667 6.570667-33.109333 15.274667-47.786667a172.373333 172.373333 0 0 1 39.253333-46.08l11.776-10.496c22.442667-20.138667 38.570667-35.413333 48.384-45.568l7.68-8.448c20.906667-27.562667 31.829333-60.245333 31.829333-97.962667 0-50.176-15.872-89.6-46.933333-118.016-32.597333-30.122667-75.264-44.373333-128.853333-44.373333z\" fill=\"#2A8FFF\" ></path></symbol><symbol id=\"iconshuaxin\" viewBox=\"0 0 1170 1024\"><path d=\"M1100.2125 402.284852V146.285401l-84.114106 83.528964A516.53375 516.53375 0 0 0 585.87303 0C301.055355 0 70.070707 229.229223 70.070707 511.998903s230.984648 511.998903 515.875466 511.998903a515.875466 515.875466 0 0 0 478.06069-319.414173 43.593049 43.593049 0 0 0-6.070844-43.446764 44.397619 44.397619 0 0 0-75.848981 10.459406A427.592227 427.592227 0 0 1 585.946173 936.226565c-236.104637 0-427.445941-189.951593-427.445941-424.227662s191.341304-424.227662 427.445941-424.227663a427.884797 427.884797 0 0 1 366.152358 205.530989L842.311338 402.284852h257.901162z\" fill=\"#505568\" ></path></symbol><symbol id=\"iconriqixuanfu\" viewBox=\"0 0 1024 1024\"><path d=\"M372.184615 64.039385c8.664615 0 15.753846 7.010462 15.753847 15.753846v51.2l-0.236308 1.890461 317.44 0.07877a15.911385 15.911385 0 0 1-0.157539-1.969231v-51.2c0-8.743385 7.089231-15.753846 15.753847-15.753846h51.2c8.664615 0 15.753846 7.010462 15.753846 15.753846v51.2l-0.315077 1.890461h158.798769c7.640615 0 13.784615 6.222769 13.784615 13.784616v799.507692a13.784615 13.784615 0 0 1-13.784615 13.784615H77.902769a13.784615 13.784615 0 0 1-13.784615-13.784615V146.668308c0-7.561846 6.144-13.784615 13.784615-13.784616l227.564308 0.07877a15.911385 15.911385 0 0 1-0.157539-1.969231v-51.2c0-8.743385 7.089231-15.753846 15.753847-15.753846h51.2z m505.068308 151.552H146.825846L146.510769 360.290462l453.080616 0.078769c8.664615 0 15.753846 7.089231 15.753846 15.753846v51.2a15.753846 15.753846 0 0 1-15.753846 15.753846H146.510769l0.078769 434.176h730.584616v-661.661538z m-70.892308 413.538461c8.743385 0 15.753846 7.089231 15.753847 15.753846v161.476923a15.753846 15.753846 0 0 1-15.753847 15.753847h-161.476923a15.753846 15.753846 0 0 1-15.753846-15.753847v-161.476923c0-8.664615 7.089231-15.753846 15.753846-15.753846h161.476923z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconshangchuanshibailianjie\" viewBox=\"0 0 1024 1024\"><path d=\"M868.205714 188.269714c64.512 66.413714 62.610286 172.763429-2.925714 238.226286l-343.917714 343.844571h-0.073143l-54.125714 54.125715a223.012571 223.012571 0 0 1-314.514286 0l-4.242286-4.242286a223.012571 223.012571 0 0 1 0-314.441143L483.035429 171.154286a26.038857 26.038857 0 0 1 36.864 36.864L185.197714 542.646857a168.228571 168.228571 0 0 0-37.156571 56.100572 171.52 171.52 0 0 0 37.156571 184.685714l4.242286 4.242286a168.228571 168.228571 0 0 0 56.100571 37.229714 171.52 171.52 0 0 0 184.685715-37.229714l353.133714-353.060572 46.153143-46.08c21.942857-21.942857 34.157714-51.346286 34.157714-82.724571a116.150857 116.150857 0 0 0-116.882286-116.809143c-31.451429 0-60.708571 12.068571-82.724571 34.084571L277.577143 609.499429a58.148571 58.148571 0 0 0-16.969143 41.398857 58.148571 58.148571 0 0 0 58.441143 58.514285 58.148571 58.148571 0 0 0 41.398857-17.042285l321.828571-321.828572a26.038857 26.038857 0 0 1 36.864 36.790857L398.262857 728.502857a111.542857 111.542857 0 0 1-156.598857 1.609143 110.957714 110.957714 0 0 1-0.731429-157.257143l386.413715-386.413714a168.594286 168.594286 0 0 1 119.515428-49.298286 168.155429 168.155429 0 0 1 121.417143 51.2z\" fill=\"#EF645C\" ></path></symbol><symbol id=\"icontubiao-sousuo\" viewBox=\"0 0 1024 1024\"><path d=\"M802.730667 739.498667l190.122666 190.037333a14.933333 14.933333 0 0 1 0 21.162667l-42.24 42.154666a14.933333 14.933333 0 0 1-21.162666 0L739.413333 802.816a14.933333 14.933333 0 0 1 0-21.077333l42.24-42.24a14.933333 14.933333 0 0 1 21.077334 0z m-75.008-592.469334a410.709333 410.709333 0 1 1-580.778667 580.778667 410.709333 410.709333 0 0 1 580.778667-580.778667z m-517.376 63.317334a321.024 321.024 0 1 0 453.973333 454.058666 321.024 321.024 0 0 0-453.973333-453.973333z\" fill=\"#A8ADBD\" ></path></symbol><symbol id=\"iconwenjianshangchuan\" viewBox=\"0 0 1088 1024\"><path d=\"M976 928h-832v-320h64v256h704v-256h64v320z m-416.192-832l271.488 271.552-45.248 45.248L592 218.688V736h-64V218.304L333.504 412.8l-45.248-45.248L559.808 96z\" fill=\"#505568\" ></path></symbol><symbol id=\"iconxuanfuwenjianshangchuan\" viewBox=\"0 0 1088 1024\"><path d=\"M944 928h-832v-320h64v256h704v-256h64v320z m-416.192-832l271.488 271.552-45.248 45.248L560 218.688V736h-64V218.304L301.504 412.8l-45.248-45.248L527.808 96z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"iconwenjianshanchu\" viewBox=\"0 0 1024 1024\"><path d=\"M721.92 103.594667v138.581333l208.042667 0.085333v69.376H826.88v623.957334H203.093333V311.552H97.962667V242.346667h207.957333V103.509333H721.92z m35.754667 208.042666H272.213333v554.666667H757.76v-554.666667z m-69.376 69.290667V797.013333h-69.290667V380.928h69.290667z m-277.333334 0V797.013333h-69.290666V380.928h69.290666z m138.666667 0V797.013333H480.426667V380.928h69.290666z m102.997333-207.957333h-277.333333v69.290666h277.333333v-69.290666z\" fill=\"#A8ADBD\" opacity=\".8\" ></path></symbol><symbol id=\"iconzuocedaohanglanshouqi\" viewBox=\"0 0 1024 1024\"><path d=\"M512 256l512 465.408-51.2 46.592L512 348.9792 51.2 768 0 721.408l460.8-418.816L512 256z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconxuanzekuangshouqi\" viewBox=\"0 0 2048 1024\"><path d=\"M1050.4192 103.2192L1856.512 909.312a37.2736 37.2736 0 0 1-26.4192 63.488H217.9072a37.2736 37.2736 0 0 1-26.4192-63.488L997.5808 103.2192a37.2736 37.2736 0 0 1 52.8384 0z\" fill=\"#505568\" ></path></symbol><symbol id=\"iconxuanzekuangzhankai\" viewBox=\"0 0 2048 1024\"><path d=\"M1050.4192 920.7808L1856.512 114.688a37.2736 37.2736 0 0 0-26.4192-63.488H217.9072a37.2736 37.2736 0 0 0-26.4192 63.488l806.0928 806.0928a37.2736 37.2736 0 0 0 52.8384 0z\" fill=\"#ffffff\" ></path></symbol><symbol id=\"iconzuocedaohangshouqi\" viewBox=\"0 0 1024 1024\"><path d=\"M602.88 150.254933L392.533333 0v1024l210.346667-150.254933A68.266667 68.266667 0 0 0 631.466667 818.210133V205.789867a68.266667 68.266667 0 0 0-28.586667-55.534934z\" fill=\"#FAFAFC\" ></path><path d=\"M500.053333 341.333333l62.702934 170.0352 0.443733 0.085334-0.221867 0.546133 0.221867 0.546133-0.443733 0.068267L500.0704 682.666667 460.8 675.0208 520.9088 512 460.8 348.9792 500.053333 341.333333z\" fill=\"#A8ADBD\" ></path></symbol><symbol id=\"iconzuocedaohanglanzhankai\" viewBox=\"0 0 1024 1024\"><path d=\"M512 768l512-465.408-51.2-46.592L512 675.0208 51.2 256l-51.2 46.592 460.8 418.816 51.2 46.592z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconzuocedaohangleshou\" viewBox=\"0 0 1024 1024\"><path d=\"M1024 804.544v73.152H0v-73.152h1024z m0-512v438.912L731.456 512 1024 292.544zM585.152 585.152v73.152H0V585.152h585.152z m0-219.456v73.152H0V365.696h585.152zM1024 146.304v73.152H0V146.304h1024z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconzuocedaohanglansuo\" viewBox=\"0 0 1024 1024\"><path d=\"M1024 804.544v73.152H0v-73.152h1024z m-292.544-512L1024 512l-292.544 219.456V292.48zM585.152 585.152v73.152H0V585.152h585.152z m0-219.456v73.152H0V365.696h585.152zM1024 146.304v73.152H0V146.304h1024z\" fill=\"#303A51\" ></path></symbol><symbol id=\"iconzuocedaohangsuoqi\" viewBox=\"0 0 1024 1024\"><path d=\"M602.88 150.254933L392.533333 0v1024l210.346667-150.254933A68.266667 68.266667 0 0 0 631.466667 818.210133V205.789867a68.266667 68.266667 0 0 0-28.586667-55.534934z\" fill=\"#FAFAFC\" ></path><path d=\"M523.946667 341.333333l-62.702934 170.0352-0.443733 0.085334 0.221867 0.546133-0.221867 0.546133 0.443733 0.068267L523.9296 682.666667 563.2 675.0208 503.0912 512 563.2 348.9792 523.946667 341.333333z\" fill=\"#A8ADBD\" ></path></symbol><symbol id=\"iconeslogo\" viewBox=\"0 0 1024 1024\"><path d=\"M510.464 591.872h-85.248c11.52-45.984 17.28-86.208 17.28-132.16 0-45.984-5.76-91.936-17.28-132.16h258.592c80.448 0 143.68 57.44 143.68 132.16 0 2.656-0.096 5.312-0.256 7.936a299.744 299.744 0 0 0-68.704-7.936 298.528 298.528 0 0 0-248.064 132.16z m-3.84 327.488l-6.72 0.064c-86.176 0-155.136-23.008-224.064-51.744 57.44-57.44 97.664-132.16 126.4-206.848l74.24-1.28a298.368 298.368 0 0 0-16.768 98.976 297.44 297.44 0 0 0 46.944 160.896v-0.064zM0 453.952c0-45.952 5.76-86.176 17.248-126.4h344.768c11.52 40.224 17.248 86.176 17.248 132.16 0 45.952-5.76 86.176-17.248 132.16H22.976C5.76 551.648 0 499.936 0 453.952zM51.712 264.32C86.208 189.632 149.44 126.4 224.096 80.448 270.08 132.16 310.304 195.36 344.768 264.32H51.712z m683.84 0L402.24 258.56c-28.736-74.688-68.96-149.376-126.4-206.848C344.736 17.28 413.76 0 499.904 0c172.384 0 327.52 74.688 419.488 189.632-45.984 45.984-109.184 74.688-183.904 74.688zM45.92 655.072h293.088c-28.736 68.96-68.96 132.16-120.672 178.144a467.232 467.232 0 0 1-172.384-178.144z\" fill=\"#FFFFFF\" ></path><path d=\"M752.32 1003.008a250.72 250.72 0 0 1-250.816-250.656 250.72 250.72 0 0 1 250.56-250.88h0.224a250.72 250.72 0 0 1 250.72 250.784 250.72 250.72 0 0 1-250.72 250.752z m0-45.6a205.12 205.12 0 0 0 205.12-205.152 205.12 205.12 0 1 0-205.12 205.12z\" fill=\"#FFFFFF\" ></path><path d=\"M740.128 666.944h-40.864v-51.456h45.216c73.472 0.928 131.456 63.04 133.056 135.904-0.48 74.016-58.88 136.608-133.12 137.6h-81.248c-8.288 0.096-13.664-5.12-13.568-13.056v-208.96h49.6l0.064 163.84c0 4.224 2.656 6.72 6.944 6.72h33.12c48.16-0.544 87.648-38.336 88.128-86.144-1.536-46.784-39.808-83.872-87.36-84.448z\" fill=\"#FFFFFF\" ></path></symbol></svg>',c=(c=document.getElementsByTagName(\"script\"))[c.length-1].getAttribute(\"data-injectcss\");if(c&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write(\"<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>\")}catch(a){console&&console.log(a)}}function d(){t||(t=!0,o())}l=function(){var a,l,i,o;(o=document.createElement(\"div\")).innerHTML=e,e=null,(i=o.getElementsByTagName(\"svg\")[0])&&(i.setAttribute(\"aria-hidden\",\"true\"),i.style.position=\"absolute\",i.style.width=0,i.style.height=0,i.style.overflow=\"hidden\",a=i,(l=document.body).firstChild?(o=a,(i=l.firstChild).parentNode.insertBefore(o,i)):l.appendChild(a))},document.addEventListener?~[\"complete\",\"loaded\",\"interactive\"].indexOf(document.readyState)?setTimeout(l,0):(i=function(){document.removeEventListener(\"DOMContentLoaded\",i,!1),l()},document.addEventListener(\"DOMContentLoaded\",i,!1)):document.attachEvent&&(o=l,h=a.document,t=!1,(n=function(){try{h.documentElement.doScroll(\"left\")}catch(a){return void setTimeout(n,50)}d()})(),h.onreadystatechange=function(){\"complete\"==h.readyState&&(h.onreadystatechange=null,d())})}(window);"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/iconfont-es/iconfont.json",
    "content": "{\n  \"id\": \"2457502\",\n  \"name\": \"Logi-ES icon\",\n  \"font_family\": \"iconfont\",\n  \"css_prefix_text\": \"icon\",\n  \"description\": \"\",\n  \"glyphs\": [\n    {\n      \"icon_id\": \"20760350\",\n      \"name\": \"表格解释\",\n      \"font_class\": \"biaogejieshi\",\n      \"unicode\": \"e62f\",\n      \"unicode_decimal\": 58927\n    },\n    {\n      \"icon_id\": \"20760351\",\n      \"name\": \"步骤完成\",\n      \"font_class\": \"buzhouwancheng\",\n      \"unicode\": \"e630\",\n      \"unicode_decimal\": 58928\n    },\n    {\n      \"icon_id\": \"20760352\",\n      \"name\": \"弹框删除\",\n      \"font_class\": \"dankuangshanchu\",\n      \"unicode\": \"e631\",\n      \"unicode_decimal\": 58929\n    },\n    {\n      \"icon_id\": \"20760353\",\n      \"name\": \"表格排序\",\n      \"font_class\": \"biaogepaixu\",\n      \"unicode\": \"e632\",\n      \"unicode_decimal\": 58930\n    },\n    {\n      \"icon_id\": \"20760354\",\n      \"name\": \"顶部导航展开\",\n      \"font_class\": \"dingbudaohangzhankai\",\n      \"unicode\": \"e633\",\n      \"unicode_decimal\": 58931\n    },\n    {\n      \"icon_id\": \"20760355\",\n      \"name\": \"多选已选状态\",\n      \"font_class\": \"duoxuanyixuanzhuangtai\",\n      \"unicode\": \"e634\",\n      \"unicode_decimal\": 58932\n    },\n    {\n      \"icon_id\": \"20760356\",\n      \"name\": \"多选不可选状态\",\n      \"font_class\": \"duoxuanbukexuanzhuangtai\",\n      \"unicode\": \"e635\",\n      \"unicode_decimal\": 58933\n    },\n    {\n      \"icon_id\": \"20760357\",\n      \"name\": \"多选未选状态\",\n      \"font_class\": \"duoxuanweixuanzhuangtai\",\n      \"unicode\": \"e636\",\n      \"unicode_decimal\": 58934\n    },\n    {\n      \"icon_id\": \"20760358\",\n      \"name\": \"更多操作收起\",\n      \"font_class\": \"gengduocaozuoshouqi\",\n      \"unicode\": \"e637\",\n      \"unicode_decimal\": 58935\n    },\n    {\n      \"icon_id\": \"20760359\",\n      \"name\": \"告警ICON\",\n      \"font_class\": \"gaojingICON\",\n      \"unicode\": \"e638\",\n      \"unicode_decimal\": 58936\n    },\n    {\n      \"icon_id\": \"20760360\",\n      \"name\": \"顶部导航收起\",\n      \"font_class\": \"dingbudaohangshouqi\",\n      \"unicode\": \"e639\",\n      \"unicode_decimal\": 58937\n    },\n    {\n      \"icon_id\": \"20760361\",\n      \"name\": \"关\",\n      \"font_class\": \"guan\",\n      \"unicode\": \"e63a\",\n      \"unicode_decimal\": 58938\n    },\n    {\n      \"icon_id\": \"20760362\",\n      \"name\": \"链接\",\n      \"font_class\": \"lianjie\",\n      \"unicode\": \"e63b\",\n      \"unicode_decimal\": 58939\n    },\n    {\n      \"icon_id\": \"20760363\",\n      \"name\": \"开\",\n      \"font_class\": \"kai\",\n      \"unicode\": \"e63c\",\n      \"unicode_decimal\": 58940\n    },\n    {\n      \"icon_id\": \"20760364\",\n      \"name\": \"更多操作缩起\",\n      \"font_class\": \"gengduocaozuosuoqi\",\n      \"unicode\": \"e63d\",\n      \"unicode_decimal\": 58941\n    },\n    {\n      \"icon_id\": \"20760365\",\n      \"name\": \"面包屑关闭\",\n      \"font_class\": \"mianbaoxieguanbi\",\n      \"unicode\": \"e63e\",\n      \"unicode_decimal\": 58942\n    },\n    {\n      \"icon_id\": \"20760366\",\n      \"name\": \"默认开不可点\",\n      \"font_class\": \"morenkaibukedian\",\n      \"unicode\": \"e63f\",\n      \"unicode_decimal\": 58943\n    },\n    {\n      \"icon_id\": \"20760367\",\n      \"name\": \"面包屑删除\",\n      \"font_class\": \"mianbaoxieshanchu\",\n      \"unicode\": \"e640\",\n      \"unicode_decimal\": 58944\n    },\n    {\n      \"icon_id\": \"20760368\",\n      \"name\": \"默认关不可点\",\n      \"font_class\": \"morenguanbukedian\",\n      \"unicode\": \"e641\",\n      \"unicode_decimal\": 58945\n    },\n    {\n      \"icon_id\": \"20760369\",\n      \"name\": \"上传中\",\n      \"font_class\": \"shangchuanzhong\",\n      \"unicode\": \"e642\",\n      \"unicode_decimal\": 58946\n    },\n    {\n      \"icon_id\": \"20760370\",\n      \"name\": \"日期\",\n      \"font_class\": \"riqi\",\n      \"unicode\": \"e643\",\n      \"unicode_decimal\": 58947\n    },\n    {\n      \"icon_id\": \"20760371\",\n      \"name\": \"图标-info\",\n      \"font_class\": \"tubiao-info\",\n      \"unicode\": \"e644\",\n      \"unicode_decimal\": 58948\n    },\n    {\n      \"icon_id\": \"20760372\",\n      \"name\": \"刷新\",\n      \"font_class\": \"shuaxin\",\n      \"unicode\": \"e645\",\n      \"unicode_decimal\": 58949\n    },\n    {\n      \"icon_id\": \"20760373\",\n      \"name\": \"日期悬浮\",\n      \"font_class\": \"riqixuanfu\",\n      \"unicode\": \"e646\",\n      \"unicode_decimal\": 58950\n    },\n    {\n      \"icon_id\": \"20760374\",\n      \"name\": \"上传失败链接\",\n      \"font_class\": \"shangchuanshibailianjie\",\n      \"unicode\": \"e647\",\n      \"unicode_decimal\": 58951\n    },\n    {\n      \"icon_id\": \"20760375\",\n      \"name\": \"图标-搜索\",\n      \"font_class\": \"tubiao-sousuo\",\n      \"unicode\": \"e648\",\n      \"unicode_decimal\": 58952\n    },\n    {\n      \"icon_id\": \"20760376\",\n      \"name\": \"文件上传\",\n      \"font_class\": \"wenjianshangchuan\",\n      \"unicode\": \"e649\",\n      \"unicode_decimal\": 58953\n    },\n    {\n      \"icon_id\": \"20760377\",\n      \"name\": \"悬浮文件上传\",\n      \"font_class\": \"xuanfuwenjianshangchuan\",\n      \"unicode\": \"e64a\",\n      \"unicode_decimal\": 58954\n    },\n    {\n      \"icon_id\": \"20760378\",\n      \"name\": \"文件删除\",\n      \"font_class\": \"wenjianshanchu\",\n      \"unicode\": \"e64b\",\n      \"unicode_decimal\": 58955\n    },\n    {\n      \"icon_id\": \"20760379\",\n      \"name\": \"左侧导航栏收起\",\n      \"font_class\": \"zuocedaohanglanshouqi\",\n      \"unicode\": \"e64c\",\n      \"unicode_decimal\": 58956\n    },\n    {\n      \"icon_id\": \"20760380\",\n      \"name\": \"选择框收起\",\n      \"font_class\": \"xuanzekuangshouqi\",\n      \"unicode\": \"e64d\",\n      \"unicode_decimal\": 58957\n    },\n    {\n      \"icon_id\": \"20760381\",\n      \"name\": \"选择框展开\",\n      \"font_class\": \"xuanzekuangzhankai\",\n      \"unicode\": \"e64e\",\n      \"unicode_decimal\": 58958\n    },\n    {\n      \"icon_id\": \"20760382\",\n      \"name\": \"左侧导航收起\",\n      \"font_class\": \"zuocedaohangshouqi\",\n      \"unicode\": \"e64f\",\n      \"unicode_decimal\": 58959\n    },\n    {\n      \"icon_id\": \"20760383\",\n      \"name\": \"左侧导航栏展开\",\n      \"font_class\": \"zuocedaohanglanzhankai\",\n      \"unicode\": \"e650\",\n      \"unicode_decimal\": 58960\n    },\n    {\n      \"icon_id\": \"20760384\",\n      \"name\": \"左侧导航了收\",\n      \"font_class\": \"zuocedaohangleshou\",\n      \"unicode\": \"e651\",\n      \"unicode_decimal\": 58961\n    },\n    {\n      \"icon_id\": \"20760385\",\n      \"name\": \"左侧导航栏缩\",\n      \"font_class\": \"zuocedaohanglansuo\",\n      \"unicode\": \"e652\",\n      \"unicode_decimal\": 58962\n    },\n    {\n      \"icon_id\": \"20760386\",\n      \"name\": \"左侧导航缩起\",\n      \"font_class\": \"zuocedaohangsuoqi\",\n      \"unicode\": \"e653\",\n      \"unicode_decimal\": 58963\n    },\n    {\n      \"icon_id\": \"20760387\",\n      \"name\": \"es logo\",\n      \"font_class\": \"eslogo\",\n      \"unicode\": \"e654\",\n      \"unicode_decimal\": 58964\n    }\n  ]\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/iconfont-logi/demo.css",
    "content": "/* Logo 字体 */\n@font-face {\n  font-family: \"iconfont logo\";\n  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');\n  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),\n    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),\n    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),\n    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');\n}\n\n.logo {\n  font-family: \"iconfont logo\";\n  font-size: 160px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n/* tabs */\n.nav-tabs {\n  position: relative;\n}\n\n.nav-tabs .nav-more {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  height: 42px;\n  line-height: 42px;\n  color: #666;\n}\n\n#tabs {\n  border-bottom: 1px solid #eee;\n}\n\n#tabs li {\n  cursor: pointer;\n  width: 100px;\n  height: 40px;\n  line-height: 40px;\n  text-align: center;\n  font-size: 16px;\n  border-bottom: 2px solid transparent;\n  position: relative;\n  z-index: 1;\n  margin-bottom: -1px;\n  color: #666;\n}\n\n\n#tabs .active {\n  border-bottom-color: #f00;\n  color: #222;\n}\n\n.tab-container .content {\n  display: none;\n}\n\n/* 页面布局 */\n.main {\n  padding: 30px 100px;\n  width: 960px;\n  margin: 0 auto;\n}\n\n.main .logo {\n  color: #333;\n  text-align: left;\n  margin-bottom: 30px;\n  line-height: 1;\n  height: 110px;\n  margin-top: -50px;\n  overflow: hidden;\n  *zoom: 1;\n}\n\n.main .logo a {\n  font-size: 160px;\n  color: #333;\n}\n\n.helps {\n  margin-top: 40px;\n}\n\n.helps pre {\n  padding: 20px;\n  margin: 10px 0;\n  border: solid 1px #e7e1cd;\n  background-color: #fffdef;\n  overflow: auto;\n}\n\n.icon_lists {\n  width: 100% !important;\n  overflow: hidden;\n  *zoom: 1;\n}\n\n.icon_lists li {\n  width: 100px;\n  margin-bottom: 10px;\n  margin-right: 20px;\n  text-align: center;\n  list-style: none !important;\n  cursor: default;\n}\n\n.icon_lists li .code-name {\n  line-height: 1.2;\n}\n\n.icon_lists .icon {\n  display: block;\n  height: 100px;\n  line-height: 100px;\n  font-size: 42px;\n  margin: 10px auto;\n  color: #333;\n  -webkit-transition: font-size 0.25s linear, width 0.25s linear;\n  -moz-transition: font-size 0.25s linear, width 0.25s linear;\n  transition: font-size 0.25s linear, width 0.25s linear;\n}\n\n.icon_lists .icon:hover {\n  font-size: 100px;\n}\n\n.icon_lists .svg-icon {\n  /* 通过设置 font-size 来改变图标大小 */\n  width: 1em;\n  /* 图标和文字相邻时，垂直对齐 */\n  vertical-align: -0.15em;\n  /* 通过设置 color 来改变 SVG 的颜色/fill */\n  fill: currentColor;\n  /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示\n      normalize.css 中也包含这行 */\n  overflow: hidden;\n}\n\n.icon_lists li .name,\n.icon_lists li .code-name {\n  color: #666;\n}\n\n/* markdown 样式 */\n.markdown {\n  color: #666;\n  font-size: 14px;\n  line-height: 1.8;\n}\n\n.highlight {\n  line-height: 1.5;\n}\n\n.markdown img {\n  vertical-align: middle;\n  max-width: 100%;\n}\n\n.markdown h1 {\n  color: #404040;\n  font-weight: 500;\n  line-height: 40px;\n  margin-bottom: 24px;\n}\n\n.markdown h2,\n.markdown h3,\n.markdown h4,\n.markdown h5,\n.markdown h6 {\n  color: #404040;\n  margin: 1.6em 0 0.6em 0;\n  font-weight: 500;\n  clear: both;\n}\n\n.markdown h1 {\n  font-size: 28px;\n}\n\n.markdown h2 {\n  font-size: 22px;\n}\n\n.markdown h3 {\n  font-size: 16px;\n}\n\n.markdown h4 {\n  font-size: 14px;\n}\n\n.markdown h5 {\n  font-size: 12px;\n}\n\n.markdown h6 {\n  font-size: 12px;\n}\n\n.markdown hr {\n  height: 1px;\n  border: 0;\n  background: #e9e9e9;\n  margin: 16px 0;\n  clear: both;\n}\n\n.markdown p {\n  margin: 1em 0;\n}\n\n.markdown>p,\n.markdown>blockquote,\n.markdown>.highlight,\n.markdown>ol,\n.markdown>ul {\n  width: 80%;\n}\n\n.markdown ul>li {\n  list-style: circle;\n}\n\n.markdown>ul li,\n.markdown blockquote ul>li {\n  margin-left: 20px;\n  padding-left: 4px;\n}\n\n.markdown>ul li p,\n.markdown>ol li p {\n  margin: 0.6em 0;\n}\n\n.markdown ol>li {\n  list-style: decimal;\n}\n\n.markdown>ol li,\n.markdown blockquote ol>li {\n  margin-left: 20px;\n  padding-left: 4px;\n}\n\n.markdown code {\n  margin: 0 3px;\n  padding: 0 5px;\n  background: #eee;\n  border-radius: 3px;\n}\n\n.markdown strong,\n.markdown b {\n  font-weight: 600;\n}\n\n.markdown>table {\n  border-collapse: collapse;\n  border-spacing: 0px;\n  empty-cells: show;\n  border: 1px solid #e9e9e9;\n  width: 95%;\n  margin-bottom: 24px;\n}\n\n.markdown>table th {\n  white-space: nowrap;\n  color: #333;\n  font-weight: 600;\n}\n\n.markdown>table th,\n.markdown>table td {\n  border: 1px solid #e9e9e9;\n  padding: 8px 16px;\n  text-align: left;\n}\n\n.markdown>table th {\n  background: #F7F7F7;\n}\n\n.markdown blockquote {\n  font-size: 90%;\n  color: #999;\n  border-left: 4px solid #e9e9e9;\n  padding-left: 0.8em;\n  margin: 1em 0;\n}\n\n.markdown blockquote p {\n  margin: 0;\n}\n\n.markdown .anchor {\n  opacity: 0;\n  transition: opacity 0.3s ease;\n  margin-left: 8px;\n}\n\n.markdown .waiting {\n  color: #ccc;\n}\n\n.markdown h1:hover .anchor,\n.markdown h2:hover .anchor,\n.markdown h3:hover .anchor,\n.markdown h4:hover .anchor,\n.markdown h5:hover .anchor,\n.markdown h6:hover .anchor {\n  opacity: 1;\n  display: inline-block;\n}\n\n.markdown>br,\n.markdown>p>br {\n  clear: both;\n}\n\n\n.hljs {\n  display: block;\n  background: white;\n  padding: 0.5em;\n  color: #333333;\n  overflow-x: auto;\n}\n\n.hljs-comment,\n.hljs-meta {\n  color: #969896;\n}\n\n.hljs-string,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-strong,\n.hljs-emphasis,\n.hljs-quote {\n  color: #df5000;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-type {\n  color: #a71d5d;\n}\n\n.hljs-literal,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-attribute {\n  color: #0086b3;\n}\n\n.hljs-section,\n.hljs-name {\n  color: #63a35c;\n}\n\n.hljs-tag {\n  color: #333333;\n}\n\n.hljs-title,\n.hljs-attr,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n  color: #795da3;\n}\n\n.hljs-addition {\n  color: #55a532;\n  background-color: #eaffea;\n}\n\n.hljs-deletion {\n  color: #bd2c00;\n  background-color: #ffecec;\n}\n\n.hljs-link {\n  text-decoration: underline;\n}\n\n/* 代码高亮 */\n/* PrismJS 1.15.0\nhttps://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */\n/**\n * prism.js default theme for JavaScript, CSS and HTML\n * Based on dabblet (http://dabblet.com)\n * @author Lea Verou\n */\ncode[class*=\"language-\"],\npre[class*=\"language-\"] {\n  color: black;\n  background: none;\n  text-shadow: 0 1px white;\n  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;\n  text-align: left;\n  white-space: pre;\n  word-spacing: normal;\n  word-break: normal;\n  word-wrap: normal;\n  line-height: 1.5;\n\n  -moz-tab-size: 4;\n  -o-tab-size: 4;\n  tab-size: 4;\n\n  -webkit-hyphens: none;\n  -moz-hyphens: none;\n  -ms-hyphens: none;\n  hyphens: none;\n}\n\npre[class*=\"language-\"]::-moz-selection,\npre[class*=\"language-\"] ::-moz-selection,\ncode[class*=\"language-\"]::-moz-selection,\ncode[class*=\"language-\"] ::-moz-selection {\n  text-shadow: none;\n  background: #b3d4fc;\n}\n\npre[class*=\"language-\"]::selection,\npre[class*=\"language-\"] ::selection,\ncode[class*=\"language-\"]::selection,\ncode[class*=\"language-\"] ::selection {\n  text-shadow: none;\n  background: #b3d4fc;\n}\n\n@media print {\n\n  code[class*=\"language-\"],\n  pre[class*=\"language-\"] {\n    text-shadow: none;\n  }\n}\n\n/* Code blocks */\npre[class*=\"language-\"] {\n  padding: 1em;\n  margin: .5em 0;\n  overflow: auto;\n}\n\n:not(pre)>code[class*=\"language-\"],\npre[class*=\"language-\"] {\n  background: #f5f2f0;\n}\n\n/* Inline code */\n:not(pre)>code[class*=\"language-\"] {\n  padding: .1em;\n  border-radius: .3em;\n  white-space: normal;\n}\n\n.token.comment,\n.token.prolog,\n.token.doctype,\n.token.cdata {\n  color: slategray;\n}\n\n.token.punctuation {\n  color: #999;\n}\n\n.namespace {\n  opacity: .7;\n}\n\n.token.property,\n.token.tag,\n.token.boolean,\n.token.number,\n.token.constant,\n.token.symbol,\n.token.deleted {\n  color: #905;\n}\n\n.token.selector,\n.token.attr-name,\n.token.string,\n.token.char,\n.token.builtin,\n.token.inserted {\n  color: #690;\n}\n\n.token.operator,\n.token.entity,\n.token.url,\n.language-css .token.string,\n.style .token.string {\n  color: #9a6e3a;\n  background: hsla(0, 0%, 100%, .5);\n}\n\n.token.atrule,\n.token.attr-value,\n.token.keyword {\n  color: #07a;\n}\n\n.token.function,\n.token.class-name {\n  color: #DD4A68;\n}\n\n.token.regex,\n.token.important,\n.token.variable {\n  color: #e90;\n}\n\n.token.important,\n.token.bold {\n  font-weight: bold;\n}\n\n.token.italic {\n  font-style: italic;\n}\n\n.token.entity {\n  cursor: help;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/iconfont-logi/demo_index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\"/>\n  <title>iconfont Demo</title>\n  <link rel=\"shortcut icon\" href=\"//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico\" type=\"image/x-icon\"/>\n  <link rel=\"icon\" type=\"image/svg+xml\" href=\"//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.svg\"/>\n  <link rel=\"stylesheet\" href=\"https://g.alicdn.com/thx/cube/1.3.2/cube.min.css\">\n  <link rel=\"stylesheet\" href=\"demo.css\">\n  <link rel=\"stylesheet\" href=\"iconfont.css\">\n  <script src=\"iconfont.js\"></script>\n  <!-- jQuery -->\n  <script src=\"https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js\"></script>\n  <!-- 代码高亮 -->\n  <script src=\"https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js\"></script>\n  <style>\n    .main .logo {\n      margin-top: 0;\n      height: auto;\n    }\n\n    .main .logo a {\n      display: flex;\n      align-items: center;\n    }\n\n    .main .logo .sub-title {\n      margin-left: 0.5em;\n      font-size: 22px;\n      color: #fff;\n      background: linear-gradient(-45deg, #3967FF, #B500FE);\n      -webkit-background-clip: text;\n      -webkit-text-fill-color: transparent;\n    }\n  </style>\n</head>\n<body>\n  <div class=\"main\">\n    <h1 class=\"logo\"><a href=\"https://www.iconfont.cn/\" title=\"iconfont 首页\" target=\"_blank\">\n      <img width=\"200\" src=\"https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg\">\n      \n    </a></h1>\n    <div class=\"nav-tabs\">\n      <ul id=\"tabs\" class=\"dib-box\">\n        <li class=\"dib active\"><span>Unicode</span></li>\n        <li class=\"dib\"><span>Font class</span></li>\n        <li class=\"dib\"><span>Symbol</span></li>\n      </ul>\n      \n      <a href=\"https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2679570\" target=\"_blank\" class=\"nav-more\">查看项目</a>\n      \n    </div>\n    <div class=\"tab-container\">\n      <div class=\"content unicode\" style=\"display: block;\">\n          <ul class=\"icon_lists dib-box\">\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe68e;</span>\n                <div class=\"name\">展开icon</div>\n                <div class=\"code-name\">&amp;#xe68e;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe68f;</span>\n                <div class=\"name\">收起icon</div>\n                <div class=\"code-name\">&amp;#xe68f;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe691;</span>\n                <div class=\"name\">我的消息icon</div>\n                <div class=\"code-name\">&amp;#xe691;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe789;</span>\n                <div class=\"name\">reload time</div>\n                <div class=\"code-name\">&amp;#xe789;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9e1;</span>\n                <div class=\"name\">公告</div>\n                <div class=\"code-name\">&amp;#xe9e1;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d2;</span>\n                <div class=\"name\">公告</div>\n                <div class=\"code-name\">&amp;#xe9d2;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d3;</span>\n                <div class=\"name\">DC采集器管理</div>\n                <div class=\"code-name\">&amp;#xe9d3;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d4;</span>\n                <div class=\"name\">kafka</div>\n                <div class=\"code-name\">&amp;#xe9d4;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d5;</span>\n                <div class=\"name\">日志审计</div>\n                <div class=\"code-name\">&amp;#xe9d5;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d6;</span>\n                <div class=\"name\">逻辑集群管理</div>\n                <div class=\"code-name\">&amp;#xe9d6;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d7;</span>\n                <div class=\"name\">权限</div>\n                <div class=\"code-name\">&amp;#xe9d7;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d8;</span>\n                <div class=\"name\">es集群</div>\n                <div class=\"code-name\">&amp;#xe9d8;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d9;</span>\n                <div class=\"name\">快速诊断</div>\n                <div class=\"code-name\">&amp;#xe9d9;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9da;</span>\n                <div class=\"name\">dashboard</div>\n                <div class=\"code-name\">&amp;#xe9da;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9db;</span>\n                <div class=\"name\">自助服务</div>\n                <div class=\"code-name\">&amp;#xe9db;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9dc;</span>\n                <div class=\"name\">topic迁移</div>\n                <div class=\"code-name\">&amp;#xe9dc;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9dd;</span>\n                <div class=\"name\">集群详情</div>\n                <div class=\"code-name\">&amp;#xe9dd;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9df;</span>\n                <div class=\"name\">connect管理</div>\n                <div class=\"code-name\">&amp;#xe9df;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9e0;</span>\n                <div class=\"name\">配置管理</div>\n                <div class=\"code-name\">&amp;#xe9e0;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d0;</span>\n                <div class=\"name\">成功</div>\n                <div class=\"code-name\">&amp;#xe9d0;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9d1;</span>\n                <div class=\"name\">筛选</div>\n                <div class=\"code-name\">&amp;#xe9d1;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9cf;</span>\n                <div class=\"name\">失败</div>\n                <div class=\"code-name\">&amp;#xe9cf;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9c3;</span>\n                <div class=\"name\">折叠</div>\n                <div class=\"code-name\">&amp;#xe9c3;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9c4;</span>\n                <div class=\"name\">删除</div>\n                <div class=\"code-name\">&amp;#xe9c4;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9c5;</span>\n                <div class=\"name\">添加</div>\n                <div class=\"code-name\">&amp;#xe9c5;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9c6;</span>\n                <div class=\"name\">日期</div>\n                <div class=\"code-name\">&amp;#xe9c6;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9c7;</span>\n                <div class=\"name\">刷新</div>\n                <div class=\"code-name\">&amp;#xe9c7;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9c8;</span>\n                <div class=\"name\">搜索</div>\n                <div class=\"code-name\">&amp;#xe9c8;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9c9;</span>\n                <div class=\"name\">leader</div>\n                <div class=\"code-name\">&amp;#xe9c9;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9ca;</span>\n                <div class=\"name\">info</div>\n                <div class=\"code-name\">&amp;#xe9ca;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9cb;</span>\n                <div class=\"name\">复制</div>\n                <div class=\"code-name\">&amp;#xe9cb;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9cc;</span>\n                <div class=\"name\">编辑</div>\n                <div class=\"code-name\">&amp;#xe9cc;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9cd;</span>\n                <div class=\"name\">下载</div>\n                <div class=\"code-name\">&amp;#xe9cd;</div>\n              </li>\n          \n            <li class=\"dib\">\n              <span class=\"icon iconfont\">&#xe9ce;</span>\n                <div class=\"name\">全屏</div>\n                <div class=\"code-name\">&amp;#xe9ce;</div>\n              </li>\n          \n          </ul>\n          <div class=\"article markdown\">\n          <h2 id=\"unicode-\">Unicode 引用</h2>\n          <hr>\n\n          <p>Unicode 是字体在网页端最原始的应用方式，特点是：</p>\n          <ul>\n            <li>支持按字体的方式去动态调整图标大小，颜色等等。</li>\n            <li>默认情况下不支持多色，直接添加多色图标会自动去色。</li>\n          </ul>\n          <blockquote>\n            <p>注意：新版 iconfont 支持两种方式引用多色图标：SVG symbol 引用方式和彩色字体图标模式。（使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。）</p>\n          </blockquote>\n          <p>Unicode 使用步骤如下：</p>\n          <h3 id=\"-font-face\">第一步：拷贝项目下面生成的 <code>@font-face</code></h3>\n<pre><code class=\"language-css\"\n>@font-face {\n  font-family: 'iconfont';\n  src: url('iconfont.woff2?t=1627354481710') format('woff2'),\n       url('iconfont.woff?t=1627354481710') format('woff'),\n       url('iconfont.ttf?t=1627354481710') format('truetype');\n}\n</code></pre>\n          <h3 id=\"-iconfont-\">第二步：定义使用 iconfont 的样式</h3>\n<pre><code class=\"language-css\"\n>.iconfont {\n  font-family: \"iconfont\" !important;\n  font-size: 16px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n</code></pre>\n          <h3 id=\"-\">第三步：挑选相应图标并获取字体编码，应用于页面</h3>\n<pre>\n<code class=\"language-html\"\n>&lt;span class=\"iconfont\"&gt;&amp;#x33;&lt;/span&gt;\n</code></pre>\n          <blockquote>\n            <p>\"iconfont\" 是你项目下的 font-family。可以通过编辑项目查看，默认是 \"iconfont\"。</p>\n          </blockquote>\n          </div>\n      </div>\n      <div class=\"content font-class\">\n        <ul class=\"icon_lists dib-box\">\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-zhankaiicon\"></span>\n            <div class=\"name\">\n              展开icon\n            </div>\n            <div class=\"code-name\">.icon-zhankaiicon\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-shouqiicon\"></span>\n            <div class=\"name\">\n              收起icon\n            </div>\n            <div class=\"code-name\">.icon-shouqiicon\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-wodexiaoxiicon\"></span>\n            <div class=\"name\">\n              我的消息icon\n            </div>\n            <div class=\"code-name\">.icon-wodexiaoxiicon\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-reloadtime\"></span>\n            <div class=\"name\">\n              reload time\n            </div>\n            <div class=\"code-name\">.icon-reloadtime\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-gonggao-copy\"></span>\n            <div class=\"name\">\n              公告\n            </div>\n            <div class=\"code-name\">.icon-gonggao-copy\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-gonggao\"></span>\n            <div class=\"name\">\n              公告\n            </div>\n            <div class=\"code-name\">.icon-gonggao\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-DCcaijiqiguanli\"></span>\n            <div class=\"name\">\n              DC采集器管理\n            </div>\n            <div class=\"code-name\">.icon-DCcaijiqiguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-kafka\"></span>\n            <div class=\"name\">\n              kafka\n            </div>\n            <div class=\"code-name\">.icon-kafka\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-rizhishenji\"></span>\n            <div class=\"name\">\n              日志审计\n            </div>\n            <div class=\"code-name\">.icon-rizhishenji\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-luojijiqunguanli\"></span>\n            <div class=\"name\">\n              逻辑集群管理\n            </div>\n            <div class=\"code-name\">.icon-luojijiqunguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-quanxian\"></span>\n            <div class=\"name\">\n              权限\n            </div>\n            <div class=\"code-name\">.icon-quanxian\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-esjiqun\"></span>\n            <div class=\"name\">\n              es集群\n            </div>\n            <div class=\"code-name\">.icon-esjiqun\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-kuaisuzhenduan\"></span>\n            <div class=\"name\">\n              快速诊断\n            </div>\n            <div class=\"code-name\">.icon-kuaisuzhenduan\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-dashboard\"></span>\n            <div class=\"name\">\n              dashboard\n            </div>\n            <div class=\"code-name\">.icon-dashboard\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-zizhufuwu\"></span>\n            <div class=\"name\">\n              自助服务\n            </div>\n            <div class=\"code-name\">.icon-zizhufuwu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-topicqianyi\"></span>\n            <div class=\"name\">\n              topic迁移\n            </div>\n            <div class=\"code-name\">.icon-topicqianyi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-jiqunxiangqing\"></span>\n            <div class=\"name\">\n              集群详情\n            </div>\n            <div class=\"code-name\">.icon-jiqunxiangqing\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-connectguanli\"></span>\n            <div class=\"name\">\n              connect管理\n            </div>\n            <div class=\"code-name\">.icon-connectguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-peizhiguanli\"></span>\n            <div class=\"name\">\n              配置管理\n            </div>\n            <div class=\"code-name\">.icon-peizhiguanli\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-chenggong\"></span>\n            <div class=\"name\">\n              成功\n            </div>\n            <div class=\"code-name\">.icon-chenggong\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-shaixuan\"></span>\n            <div class=\"name\">\n              筛选\n            </div>\n            <div class=\"code-name\">.icon-shaixuan\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-shibai\"></span>\n            <div class=\"name\">\n              失败\n            </div>\n            <div class=\"code-name\">.icon-shibai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-zhedie\"></span>\n            <div class=\"name\">\n              折叠\n            </div>\n            <div class=\"code-name\">.icon-zhedie\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-shanchu\"></span>\n            <div class=\"name\">\n              删除\n            </div>\n            <div class=\"code-name\">.icon-shanchu\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-tianjia\"></span>\n            <div class=\"name\">\n              添加\n            </div>\n            <div class=\"code-name\">.icon-tianjia\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-riqi\"></span>\n            <div class=\"name\">\n              日期\n            </div>\n            <div class=\"code-name\">.icon-riqi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-shuaxin\"></span>\n            <div class=\"name\">\n              刷新\n            </div>\n            <div class=\"code-name\">.icon-shuaxin\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-sousuo\"></span>\n            <div class=\"name\">\n              搜索\n            </div>\n            <div class=\"code-name\">.icon-sousuo\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-leader\"></span>\n            <div class=\"name\">\n              leader\n            </div>\n            <div class=\"code-name\">.icon-leader\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-info\"></span>\n            <div class=\"name\">\n              info\n            </div>\n            <div class=\"code-name\">.icon-info\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-fuzhi\"></span>\n            <div class=\"name\">\n              复制\n            </div>\n            <div class=\"code-name\">.icon-fuzhi\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-bianji\"></span>\n            <div class=\"name\">\n              编辑\n            </div>\n            <div class=\"code-name\">.icon-bianji\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-xiazai\"></span>\n            <div class=\"name\">\n              下载\n            </div>\n            <div class=\"code-name\">.icon-xiazai\n            </div>\n          </li>\n          \n          <li class=\"dib\">\n            <span class=\"icon iconfont icon-quanping\"></span>\n            <div class=\"name\">\n              全屏\n            </div>\n            <div class=\"code-name\">.icon-quanping\n            </div>\n          </li>\n          \n        </ul>\n        <div class=\"article markdown\">\n        <h2 id=\"font-class-\">font-class 引用</h2>\n        <hr>\n\n        <p>font-class 是 Unicode 使用方式的一种变种，主要是解决 Unicode 书写不直观，语意不明确的问题。</p>\n        <p>与 Unicode 使用方式相比，具有如下特点：</p>\n        <ul>\n          <li>相比于 Unicode 语意明确，书写更直观。可以很容易分辨这个 icon 是什么。</li>\n          <li>因为使用 class 来定义图标，所以当要替换图标时，只需要修改 class 里面的 Unicode 引用。</li>\n        </ul>\n        <p>使用步骤如下：</p>\n        <h3 id=\"-fontclass-\">第一步：引入项目下面生成的 fontclass 代码：</h3>\n<pre><code class=\"language-html\">&lt;link rel=\"stylesheet\" href=\"./iconfont.css\"&gt;\n</code></pre>\n        <h3 id=\"-\">第二步：挑选相应图标并获取类名，应用于页面：</h3>\n<pre><code class=\"language-html\">&lt;span class=\"iconfont icon-xxx\"&gt;&lt;/span&gt;\n</code></pre>\n        <blockquote>\n          <p>\"\n            iconfont\" 是你项目下的 font-family。可以通过编辑项目查看，默认是 \"iconfont\"。</p>\n        </blockquote>\n      </div>\n      </div>\n      <div class=\"content symbol\">\n          <ul class=\"icon_lists dib-box\">\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-zhankaiicon\"></use>\n                </svg>\n                <div class=\"name\">展开icon</div>\n                <div class=\"code-name\">#icon-zhankaiicon</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-shouqiicon\"></use>\n                </svg>\n                <div class=\"name\">收起icon</div>\n                <div class=\"code-name\">#icon-shouqiicon</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-wodexiaoxiicon\"></use>\n                </svg>\n                <div class=\"name\">我的消息icon</div>\n                <div class=\"code-name\">#icon-wodexiaoxiicon</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-reloadtime\"></use>\n                </svg>\n                <div class=\"name\">reload time</div>\n                <div class=\"code-name\">#icon-reloadtime</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-gonggao-copy\"></use>\n                </svg>\n                <div class=\"name\">公告</div>\n                <div class=\"code-name\">#icon-gonggao-copy</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-gonggao\"></use>\n                </svg>\n                <div class=\"name\">公告</div>\n                <div class=\"code-name\">#icon-gonggao</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-DCcaijiqiguanli\"></use>\n                </svg>\n                <div class=\"name\">DC采集器管理</div>\n                <div class=\"code-name\">#icon-DCcaijiqiguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-kafka\"></use>\n                </svg>\n                <div class=\"name\">kafka</div>\n                <div class=\"code-name\">#icon-kafka</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-rizhishenji\"></use>\n                </svg>\n                <div class=\"name\">日志审计</div>\n                <div class=\"code-name\">#icon-rizhishenji</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-luojijiqunguanli\"></use>\n                </svg>\n                <div class=\"name\">逻辑集群管理</div>\n                <div class=\"code-name\">#icon-luojijiqunguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-quanxian\"></use>\n                </svg>\n                <div class=\"name\">权限</div>\n                <div class=\"code-name\">#icon-quanxian</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-esjiqun\"></use>\n                </svg>\n                <div class=\"name\">es集群</div>\n                <div class=\"code-name\">#icon-esjiqun</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-kuaisuzhenduan\"></use>\n                </svg>\n                <div class=\"name\">快速诊断</div>\n                <div class=\"code-name\">#icon-kuaisuzhenduan</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-dashboard\"></use>\n                </svg>\n                <div class=\"name\">dashboard</div>\n                <div class=\"code-name\">#icon-dashboard</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-zizhufuwu\"></use>\n                </svg>\n                <div class=\"name\">自助服务</div>\n                <div class=\"code-name\">#icon-zizhufuwu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-topicqianyi\"></use>\n                </svg>\n                <div class=\"name\">topic迁移</div>\n                <div class=\"code-name\">#icon-topicqianyi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-jiqunxiangqing\"></use>\n                </svg>\n                <div class=\"name\">集群详情</div>\n                <div class=\"code-name\">#icon-jiqunxiangqing</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-connectguanli\"></use>\n                </svg>\n                <div class=\"name\">connect管理</div>\n                <div class=\"code-name\">#icon-connectguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-peizhiguanli\"></use>\n                </svg>\n                <div class=\"name\">配置管理</div>\n                <div class=\"code-name\">#icon-peizhiguanli</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-chenggong\"></use>\n                </svg>\n                <div class=\"name\">成功</div>\n                <div class=\"code-name\">#icon-chenggong</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-shaixuan\"></use>\n                </svg>\n                <div class=\"name\">筛选</div>\n                <div class=\"code-name\">#icon-shaixuan</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-shibai\"></use>\n                </svg>\n                <div class=\"name\">失败</div>\n                <div class=\"code-name\">#icon-shibai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-zhedie\"></use>\n                </svg>\n                <div class=\"name\">折叠</div>\n                <div class=\"code-name\">#icon-zhedie</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-shanchu\"></use>\n                </svg>\n                <div class=\"name\">删除</div>\n                <div class=\"code-name\">#icon-shanchu</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-tianjia\"></use>\n                </svg>\n                <div class=\"name\">添加</div>\n                <div class=\"code-name\">#icon-tianjia</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-riqi\"></use>\n                </svg>\n                <div class=\"name\">日期</div>\n                <div class=\"code-name\">#icon-riqi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-shuaxin\"></use>\n                </svg>\n                <div class=\"name\">刷新</div>\n                <div class=\"code-name\">#icon-shuaxin</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-sousuo\"></use>\n                </svg>\n                <div class=\"name\">搜索</div>\n                <div class=\"code-name\">#icon-sousuo</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-leader\"></use>\n                </svg>\n                <div class=\"name\">leader</div>\n                <div class=\"code-name\">#icon-leader</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-info\"></use>\n                </svg>\n                <div class=\"name\">info</div>\n                <div class=\"code-name\">#icon-info</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-fuzhi\"></use>\n                </svg>\n                <div class=\"name\">复制</div>\n                <div class=\"code-name\">#icon-fuzhi</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-bianji\"></use>\n                </svg>\n                <div class=\"name\">编辑</div>\n                <div class=\"code-name\">#icon-bianji</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-xiazai\"></use>\n                </svg>\n                <div class=\"name\">下载</div>\n                <div class=\"code-name\">#icon-xiazai</div>\n            </li>\n          \n            <li class=\"dib\">\n                <svg class=\"icon svg-icon\" aria-hidden=\"true\">\n                  <use xlink:href=\"#icon-quanping\"></use>\n                </svg>\n                <div class=\"name\">全屏</div>\n                <div class=\"code-name\">#icon-quanping</div>\n            </li>\n          \n          </ul>\n          <div class=\"article markdown\">\n          <h2 id=\"symbol-\">Symbol 引用</h2>\n          <hr>\n\n          <p>这是一种全新的使用方式，应该说这才是未来的主流，也是平台目前推荐的用法。相关介绍可以参考这篇<a href=\"\">文章</a>\n            这种用法其实是做了一个 SVG 的集合，与另外两种相比具有如下特点：</p>\n          <ul>\n            <li>支持多色图标了，不再受单色限制。</li>\n            <li>通过一些技巧，支持像字体那样，通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>\n            <li>兼容性较差，支持 IE9+，及现代浏览器。</li>\n            <li>浏览器渲染 SVG 的性能一般，还不如 png。</li>\n          </ul>\n          <p>使用步骤如下：</p>\n          <h3 id=\"-symbol-\">第一步：引入项目下面生成的 symbol 代码：</h3>\n<pre><code class=\"language-html\">&lt;script src=\"./iconfont.js\"&gt;&lt;/script&gt;\n</code></pre>\n          <h3 id=\"-css-\">第二步：加入通用 CSS 代码（引入一次就行）：</h3>\n<pre><code class=\"language-html\">&lt;style&gt;\n.icon {\n  width: 1em;\n  height: 1em;\n  vertical-align: -0.15em;\n  fill: currentColor;\n  overflow: hidden;\n}\n&lt;/style&gt;\n</code></pre>\n          <h3 id=\"-\">第三步：挑选相应图标并获取类名，应用于页面：</h3>\n<pre><code class=\"language-html\">&lt;svg class=\"icon\" aria-hidden=\"true\"&gt;\n  &lt;use xlink:href=\"#icon-xxx\"&gt;&lt;/use&gt;\n&lt;/svg&gt;\n</code></pre>\n          </div>\n      </div>\n\n    </div>\n  </div>\n  <script>\n  $(document).ready(function () {\n      $('.tab-container .content:first').show()\n\n      $('#tabs li').click(function (e) {\n        var tabContent = $('.tab-container .content')\n        var index = $(this).index()\n\n        if ($(this).hasClass('active')) {\n          return\n        } else {\n          $('#tabs li').removeClass('active')\n          $(this).addClass('active')\n\n          tabContent.hide().eq(index).fadeIn()\n        }\n      })\n    })\n  </script>\n</body>\n</html>\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/iconfont-logi/iconfont.css",
    "content": "@font-face {\n  font-family: \"iconfont\"; /* Project id 2679570 */\n  src: url('iconfont.woff2?t=1627354481710') format('woff2'),\n       url('iconfont.woff?t=1627354481710') format('woff'),\n       url('iconfont.ttf?t=1627354481710') format('truetype');\n}\n\n.iconfont {\n  font-family: \"iconfont\" !important;\n  font-size: 16px;\n  font-style: normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n.icon-zhankaiicon:before {\n  content: \"\\e68e\";\n}\n\n.icon-shouqiicon:before {\n  content: \"\\e68f\";\n}\n\n.icon-wodexiaoxiicon:before {\n  content: \"\\e691\";\n}\n\n.icon-reloadtime:before {\n  content: \"\\e789\";\n}\n\n.icon-gonggao-copy:before {\n  content: \"\\e9e1\";\n}\n\n.icon-gonggao:before {\n  content: \"\\e9d2\";\n}\n\n.icon-DCcaijiqiguanli:before {\n  content: \"\\e9d3\";\n}\n\n.icon-kafka:before {\n  content: \"\\e9d4\";\n}\n\n.icon-rizhishenji:before {\n  content: \"\\e9d5\";\n}\n\n.icon-luojijiqunguanli:before {\n  content: \"\\e9d6\";\n}\n\n.icon-quanxian:before {\n  content: \"\\e9d7\";\n}\n\n.icon-esjiqun:before {\n  content: \"\\e9d8\";\n}\n\n.icon-kuaisuzhenduan:before {\n  content: \"\\e9d9\";\n}\n\n.icon-dashboard:before {\n  content: \"\\e9da\";\n}\n\n.icon-zizhufuwu:before {\n  content: \"\\e9db\";\n}\n\n.icon-topicqianyi:before {\n  content: \"\\e9dc\";\n}\n\n.icon-jiqunxiangqing:before {\n  content: \"\\e9dd\";\n}\n\n.icon-connectguanli:before {\n  content: \"\\e9df\";\n}\n\n.icon-peizhiguanli:before {\n  content: \"\\e9e0\";\n}\n\n.icon-chenggong:before {\n  content: \"\\e9d0\";\n}\n\n.icon-shaixuan:before {\n  content: \"\\e9d1\";\n}\n\n.icon-shibai:before {\n  content: \"\\e9cf\";\n}\n\n.icon-zhedie:before {\n  content: \"\\e9c3\";\n}\n\n.icon-shanchu:before {\n  content: \"\\e9c4\";\n}\n\n.icon-tianjia:before {\n  content: \"\\e9c5\";\n}\n\n.icon-riqi:before {\n  content: \"\\e9c6\";\n}\n\n.icon-shuaxin:before {\n  content: \"\\e9c7\";\n}\n\n.icon-sousuo:before {\n  content: \"\\e9c8\";\n}\n\n.icon-leader:before {\n  content: \"\\e9c9\";\n}\n\n.icon-info:before {\n  content: \"\\e9ca\";\n}\n\n.icon-fuzhi:before {\n  content: \"\\e9cb\";\n}\n\n.icon-bianji:before {\n  content: \"\\e9cc\";\n}\n\n.icon-xiazai:before {\n  content: \"\\e9cd\";\n}\n\n.icon-quanping:before {\n  content: \"\\e9ce\";\n}\n\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/iconfont-logi/iconfont.js",
    "content": "!function (a) { var l, h, c, i, v, o, t = '<svg><symbol id=\"iconyingyong\" viewBox=\"0 0 1024 1024\"><path d=\"M469.333333 192v213.333333c0 35.328-28.672 64-64 64h-213.333333A64 64 0 0 1 128 405.333333v-213.333333c0-35.328 28.672-64 64-64h213.333333c35.328 0 64 28.672 64 64z m-85.333333 0h-170.666667a21.333333 21.333333 0 0 0-21.333333 21.333333v170.666667c0 11.776 9.557333 21.333333 21.333333 21.333333h170.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-170.666667a21.333333 21.333333 0 0 0-21.333333-21.333333z m512 0v213.333333c0 35.328-28.672 64-64 64h-213.333333A64 64 0 0 1 554.666667 405.333333v-213.333333c0-35.328 28.672-64 64-64h213.333333c35.328 0 64 28.672 64 64z m-85.333333 0h-170.666667a21.333333 21.333333 0 0 0-21.333333 21.333333v170.666667c0 11.776 9.557333 21.333333 21.333333 21.333333h170.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-170.666667a21.333333 21.333333 0 0 0-21.333333-21.333333z m-341.333334 426.666667v213.333333c0 35.328-28.672 64-64 64h-213.333333a64 64 0 0 1-64-64v-213.333333c0-35.328 28.672-64 64-64h213.333333c35.328 0 64 28.672 64 64z m-85.333333 0h-170.666667a21.333333 21.333333 0 0 0-21.333333 21.333333v170.666667c0 11.776 9.557333 21.333333 21.333333 21.333333h170.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-170.666667a21.333333 21.333333 0 0 0-21.333333-21.333333z m512 0v213.333333c0 35.328-28.672 64-64 64h-213.333333a64 64 0 0 1-64-64v-213.333333c0-35.328 28.672-64 64-64h213.333333c35.328 0 64 28.672 64 64z m-85.333333 0h-170.666667a21.333333 21.333333 0 0 0-21.333333 21.333333v170.666667c0 11.776 9.557333 21.333333 21.333333 21.333333h170.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-170.666667a21.333333 21.333333 0 0 0-21.333333-21.333333z\"  ></path></symbol><symbol id=\"iconwarning-circle\" viewBox=\"0 0 1024 1024\"><path d=\"M512 938.6496a426.6496 426.6496 0 1 1 0-853.2992 426.6496 426.6496 0 1 1 0 853.2992z m-42.6496-277.2992v85.2992h85.2992v-85.2992H469.3504z m0-384v320h85.2992v-320H469.3504z\" fill=\"#FFC300\" ></path></symbol><symbol id=\"iconinfo-circle\" viewBox=\"0 0 1024 1024\"><path d=\"M512 85.3504a426.6496 426.6496 0 1 1 0 853.2992 426.6496 426.6496 0 1 1 0-853.2992z m42.6496 277.2992V277.3504H469.3504v85.2992h85.2992z m0 384v-320H469.3504v320h85.2992z\" fill=\"#1473FF\" ></path></symbol><symbol id=\"iconerror-circle\" viewBox=\"0 0 1024 1024\"><path d=\"M512 938.6496a426.6496 426.6496 0 1 1 0-853.2992 426.6496 426.6496 0 1 1 0 853.2992z m0-366.336l135.7824 135.7824 60.3136-60.3136L572.3136 512l135.7824-135.7824-60.3136-60.3136L512 451.6864 376.2176 315.904 315.904 376.2176 451.6864 512 315.904 647.7824l60.3136 60.3136L512 572.3136z\" fill=\"#F5483B\" ></path></symbol><symbol id=\"iconsuccess-circle\" viewBox=\"0 0 1024 1024\"><path d=\"M813.7216 813.7216A426.7008 426.7008 0 1 1 210.2784 210.2784a426.7008 426.7008 0 0 1 603.392 603.392z m-355.328-246.1184L337.6128 446.976 277.3504 507.2896l180.992 180.992 286.6176-286.6176-60.3136-60.3136-226.304 226.304z\" fill=\"#00B365\" ></path></symbol><symbol id=\"icona-knowsearch\" viewBox=\"0 0 5440 1024\"><path d=\"M510.464 591.872h-85.248c11.52-45.984 17.28-86.208 17.28-132.16 0-45.984-5.76-91.936-17.28-132.16h258.592c80.448 0 143.68 57.44 143.68 132.16 0 2.656-0.096 5.312-0.256 7.936a299.744 299.744 0 0 0-68.704-7.936 298.528 298.528 0 0 0-248.064 132.16z m-3.84 327.488l-6.72 0.064c-86.176 0-155.136-23.008-224.064-51.744 57.44-57.44 97.664-132.16 126.4-206.848l74.24-1.28a298.368 298.368 0 0 0-16.768 98.976 297.44 297.44 0 0 0 46.944 160.896v-0.064zM0 453.952c0-45.952 5.76-86.176 17.248-126.4h344.768c11.52 40.224 17.248 86.176 17.248 132.16 0 45.952-5.76 86.176-17.248 132.16H22.976C5.76 551.648 0 499.936 0 453.952zM51.712 264.32C86.208 189.632 149.44 126.4 224.096 80.448 270.08 132.16 310.304 195.36 344.768 264.32H51.712z m683.84 0L402.24 258.56c-28.736-74.688-68.96-149.376-126.4-206.848C344.736 17.28 413.76 0 499.904 0c172.384 0 327.52 74.688 419.488 189.632-45.984 45.984-109.184 74.688-183.904 74.688zM45.92 655.072h293.088c-28.736 68.96-68.96 132.16-120.672 178.144a467.232 467.232 0 0 1-172.384-178.144z\" fill=\"#FFFFFF\" ></path><path d=\"M752.32 1003.008a250.72 250.72 0 0 1-250.816-250.656 250.72 250.72 0 0 1 250.56-250.88h0.224a250.72 250.72 0 0 1 250.72 250.784 250.72 250.72 0 0 1-250.72 250.752z m0-45.6a205.12 205.12 0 0 0 205.12-205.152 205.12 205.12 0 1 0-205.12 205.12z\" fill=\"#FFFFFF\" ></path><path d=\"M740.128 666.944h-40.864v-51.456h45.216c73.472 0.928 131.456 63.04 133.056 135.904-0.48 74.016-58.88 136.608-133.12 137.6h-81.248c-8.288 0.096-13.664-5.12-13.568-13.056v-208.96h49.6l0.064 163.84c0 4.224 2.656 6.72 6.944 6.72h33.12c48.16-0.544 87.648-38.336 88.128-86.144-1.536-46.784-39.808-83.872-87.36-84.448z\" fill=\"#FFFFFF\" ></path><path d=\"M1414.4 309.12V736h-90.88V309.12h90.88z m3.2 211.2l163.2-211.2h119.68l-178.56 211.2L1692.16 736h-119.68l-154.88-215.68zM1743.36 424.32h165.12c24.736 0 43.616 1.824 56.64 5.44 13.024 3.616 24.864 10.144 35.52 19.52 21.76 20.064 32.64 51.616 32.64 94.72v192h-85.76v-201.6c0-15.36-3.424-26.464-10.24-33.28-6.816-6.816-18.144-10.24-33.92-10.24h-74.24V736h-85.76v-311.68zM2257.28 419.84c57.6 0 100.064 16.64 127.36 49.92 25.184 30.304 37.76 68.48 37.76 114.56 0 48.64-15.776 87.456-47.36 116.48-29.024 26.464-68.704 39.68-119.04 39.68-52.064 0-92.8-14.944-122.24-44.8-27.296-26.88-40.96-66.144-40.96-117.76 0-43.52 13.024-79.776 39.04-108.8 29.024-32.416 70.816-48.864 125.44-49.28z m0.64 65.28c-51.616 0-77.44 32-77.44 96 0 26.016 4.256 45.856 12.8 59.52 14.08 23.04 35.84 34.56 65.28 34.56 50.784 0 76.16-31.776 76.16-95.36 0-62.304-25.6-93.856-76.8-94.72zM2664.32 669.44v-245.12h85.76v245.12h92.16v-245.12h85.12V736h-314.88c-28.576 0-50.336-2.144-65.28-6.4a78.624 78.624 0 0 1-37.12-22.4c-18.784-20.48-28.16-48.64-28.16-84.48v-198.4h85.12v184.96c0 14.944 0.736 25.376 2.24 31.36 1.504 5.984 4.384 11.296 8.64 16 8.96 8.544 22.4 12.8 40.32 12.8h46.08zM3331.84 736v-76.16h195.2c31.136 0 51.84-2.976 62.08-8.96 14.944-8.96 22.4-22.4 22.4-40.32 0-20.896-8.736-36.064-26.24-45.44-9.824-5.536-25.6-8.32-47.36-8.32h-79.36c-48.224 0-82.976-8.736-104.32-26.24a114.656 114.656 0 0 1-31.04-41.6 129.792 129.792 0 0 1-11.2-53.76c0-29.856 8.736-57.184 26.24-81.92 17.056-23.904 44.384-37.984 81.92-42.24 12.8-1.28 31.776-1.92 56.96-1.92h211.84v76.16h-191.36c-28.576 0.416-47.584 1.696-56.96 3.84-19.2 4.704-28.8 19.2-28.8 43.52 0 20.48 8.096 34.144 24.32 40.96 10.656 5.12 28.576 7.68 53.76 7.68h68.48c34.976 0 61.024 2.976 78.08 8.96 30.304 10.24 51.2 28.16 62.72 53.76 8.96 20.48 13.44 42.464 13.44 65.92 0 26.016-5.984 49.28-17.92 69.76-16.64 29.024-41.6 46.496-74.88 52.48-16.224 2.56-40.736 3.84-73.6 3.84h-214.4zM4031.36 546.56v66.56h-180.48c1.696 20.48 8.32 34.976 19.84 43.52 11.52 8.544 30.304 12.8 56.32 12.8h104.32V736h-113.92c-24.736 0-44.896-2.24-60.48-6.72a134.784 134.784 0 0 1-43.84-22.08c-37.984-29.44-56.96-73.184-56.96-131.2 0-37.536 10.016-70.4 30.08-98.56 13.664-19.2 30.08-32.864 49.28-40.96 19.2-8.096 44.384-12.16 75.52-12.16h120.32v66.56h-113.92c-23.456 0-39.904 3.936-49.28 11.84-9.376 7.904-15.136 22.496-17.28 43.84h180.48zM4316.16 546.56c0-21.76-4.384-36.48-13.12-44.16-8.736-7.68-26.144-11.52-52.16-11.52h-144.64v-66.56h144.64c26.016 0 43.936 0.544 53.76 1.6 9.824 1.056 19.84 3.104 30.08 6.08 47.36 17.92 69.76 60.8 67.2 128.64V736h-180.48c-32.416 0-54.816-0.96-67.2-2.88a84.032 84.032 0 0 1-32.64-11.84c-25.184-17.056-37.76-42.88-37.76-77.44 0-20.896 5.024-39.584 15.04-56 10.016-16.416 23.36-27.616 40-33.6 14.496-5.12 38.624-7.68 72.32-7.68h104.96z m0 66.56h-113.28c-9.824 0-17.6 2.56-23.36 7.68-5.76 5.12-8.64 12.16-8.64 21.12 0 9.824 3.52 16.864 10.56 21.12 7.04 4.256 19.104 6.4 36.16 6.4h98.56v-56.32zM4481.92 424.32h126.72c26.016 0 46.176 1.824 60.48 5.44 14.304 3.616 26.144 9.696 35.52 18.24 9.376 8.544 16 19.2 19.84 32s5.76 31.136 5.76 55.04v30.08h-82.56v-16.64c0-22.176-3.84-37.344-11.52-45.44-7.68-8.096-22.4-12.16-44.16-12.16h-24.32V736h-85.76v-311.68zM5041.92 424.32v66.56h-102.4c-34.56 0-58.464 7.68-71.68 23.04-12.8 14.496-19.2 36.704-19.2 66.56 0 33.28 10.464 57.6 31.36 72.96 8.544 5.984 17.824 10.144 27.84 12.48 10.016 2.336 24 3.52 41.92 3.52h92.16V736h-117.12c-31.584 0-56.544-3.2-74.88-9.6a115.84 115.84 0 0 1-48.64-33.28c-26.88-29.856-40.32-67.84-40.32-113.92 0-55.456 16-96.864 48-124.16 12.8-11.104 28.16-18.976 46.08-23.68 17.92-4.704 41.184-7.04 69.76-7.04h117.12zM5192.96 309.12v115.2h87.68c26.016 0 46.4 2.016 61.12 6.08 14.72 4.064 27.2 11.2 37.44 21.44 19.616 17.92 29.44 48 29.44 90.24V736h-85.76v-177.28c0-16.64-0.736-28.48-2.24-35.52a38.208 38.208 0 0 0-9.28-18.24c-8.544-8.96-24.736-13.664-48.64-14.08h-69.76V736h-85.76V309.12h85.76z\" fill=\"#FFFFFF\" ></path></symbol><symbol id=\"icontouxiang\" viewBox=\"0 0 1024 1024\"><path d=\"M512 448a128 128 0 1 0 0-256 128 128 0 0 0 0 256zM512 512a192 192 0 1 1 0-384 192 192 0 0 1 0 384z m162.304 64H349.696a215.7568 215.7568 0 0 0-200.6016 136.4992l-14.8992 37.632A106.6496 106.6496 0 0 0 233.4208 896H790.528a106.6496 106.6496 0 0 0 99.2256-145.8688l-14.848-37.632a215.7568 215.7568 0 0 0-200.704-136.4992z m0 64c62.2592 0 118.2208 38.0416 141.1072 96l14.848 37.632a42.6496 42.6496 0 0 1-39.68 58.368H233.472a42.6496 42.6496 0 0 1-39.68-58.368l14.848-37.632A151.7568 151.7568 0 0 1 349.7472 640h324.5056z\"  ></path></symbol><symbol id=\"icontuichudenglu\" viewBox=\"0 0 1024 1024\"><path d=\"M660.1216 554.6496H436.1216a32 32 0 1 1 0-64h224V432.3328a21.3504 21.3504 0 0 1 32.3072-18.2784l150.528 90.3168a21.3504 21.3504 0 0 1 0 36.608l-150.528 90.3168a21.3504 21.3504 0 0 1-32.256-18.3296v-58.3168z m-335.9744-448c-79.7696 0-144.0256 66.0992-144.0256 147.2v537.6c0 81.1008 64.256 147.2 144.0256 147.2h373.2992c79.7696 0 144.0256-66.048 144.0256-147.2v-65.024a32 32 0 0 0-64 0v65.024c0 46.1824-36.0448 83.2-80.0256 83.2H324.1472c-44.032 0-80.0256-37.0176-80.0256-83.2v-537.6c0-46.1312 36.0448-83.2 80.0256-83.2h373.2992c44.032 0 80.0256 37.0688 80.0256 83.2v24.7296a32 32 0 1 0 64 0v-24.7296c0-81.1008-64.256-147.2-144.0256-147.2H324.1472z\"  ></path></symbol><symbol id=\"icon-zhankaiicon\" viewBox=\"0 0 1024 1024\"><path d=\"M1024 804.544v73.152H0v-73.152h1024z m-292.544-512L1024 512l-292.544 219.456V292.48zM585.152 585.152v73.152H0V585.152h585.152z m0-219.456v73.152H0V365.696h585.152zM1024 146.304v73.152H0V146.304h1024z\"  ></path></symbol><symbol id=\"icon-shouqiicon\" viewBox=\"0 0 1024 1024\"><path d=\"M1024 804.544v73.152H0v-73.152h1024z m0-512v438.912L731.456 512 1024 292.544zM585.152 585.152v73.152H0V585.152h585.152z m0-219.456v73.152H0V365.696h585.152zM1024 146.304v73.152H0V146.304h1024z\"  ></path></symbol><symbol id=\"icon-wodexiaoxiicon\" viewBox=\"0 0 1024 1024\"><path d=\"M436.906667 896c2.474667 0.256 4.949333 1.024 6.997333 2.389333l0.853333-1.194666c4.010667 1.28 7.424 3.754667 8.533334 7.509333 5.290667 26.197333 30.549333 45.397333 60.416 46.08 29.866667-0.682667 55.125333-19.968 60.416-46.08a10.581333 10.581333 0 0 1 5.632-6.314667l2.901333-1.194666 0.853333 1.194666 3.328-1.536 3.754667-0.853333h60.757333c6.314667 0.426667 10.922667 4.522667 11.946667 9.728-5.546667 62.72-63.146667 112.981333-135.68 117.845333L515.84 1024h-4.437333c-77.994667 0-141.482667-52.309333-147.285334-118.272a11.946667 11.946667 0 0 1 8.362667-9.045333l3.584-0.597334h60.672V896zM512.426667 0C561.92 0 602.453333 32.426667 607.573333 73.898667l0.426667 8.362666v2.389334c153.514667 35.84 277.845333 153.258667 285.952 282.794666l0.426667 13.482667v277.333333c0 104.704 85.162667 139.776 105.130666 146.602667a38.4 38.4 0 0 1 24.490667 34.304c-0.256 19.2-16.128 35.328-37.461333 38.144l-7.338667 0.512H44.8a47.274667 47.274667 0 0 1-31.402667-11.093333A37.290667 37.290667 0 0 1 0 839.168a38.4 38.4 0 0 1 24.490667-34.304l6.997333-2.56c26.453333-10.666667 91.477333-45.312 97.706667-130.730667l0.426666-13.226666v-277.333334c0-130.389333 119.210667-251.050667 270.592-292.437333l15.786667-3.925333V82.346667c0-42.666667 37.717333-77.653333 85.674667-81.92L512.512 0z m0 64L508.842667 64a22.357333 22.357333 0 0 0-20.309334 14.506667l-0.512 3.669333v50.602667l-66.56 16.896c-121.6 33.28-212.565333 126.122667-219.392 219.989333l-0.426666 11.264v279.381333l-0.597334 15.36c-4.096 56.576-25.941333 100.096-56.661333 131.84l-6.4 6.144 750.933333 0.256-2.133333-2.048a204.288 204.288 0 0 1-64-138.069333l-0.426667-15.616V382.805333l-0.341333-11.776C816.128 276.565333 724.48 183.637333 604.245333 150.186667l-14.506666-3.669334-53.76-12.544 0.170666-48.384L535.893333 80.64C535.04 72.96 527.616 66.218667 517.717333 64.426667L512.512 64z\"  ></path></symbol><symbol id=\"icon-reloadtime\" viewBox=\"0 0 1024 1024\"><path d=\"M536.1 273H488c-4.4 0-8 3.6-8 8v275.3c0 2.6 1.2 5 3.3 6.5l165.3 120.7c3.6 2.6 8.6 1.9 11.2-1.7l28.6-39c2.7-3.7 1.9-8.7-1.7-11.2L544.1 528.5V281c0-4.4-3.6-8-8-8zM755.9 348.2l156.8 38.3c5 1.2 9.9-2.6 9.9-7.7l0.8-161.5c0-6.7-7.7-10.5-12.9-6.3L752.9 334.1c-5.3 4.2-3.5 12.5 3 14.1z\"  ></path><path d=\"M923.6 649.3l-56.7-19.5c-4.1-1.4-8.6 0.7-10.1 4.8-1.9 5.1-3.9 10.1-6 15.1-17.8 42.1-43.3 80-75.9 112.5-32.5 32.5-70.4 58.1-112.5 75.9-43.6 18.4-89.9 27.8-137.7 27.8-47.8 0-94.1-9.3-137.7-27.8-42.1-17.8-80-43.4-112.5-75.9-32.5-32.5-58-70.4-75.9-112.5C180.3 606.2 171 559.8 171 512c0-47.8 9.3-94.2 27.8-137.8 17.8-42.1 43.3-80 75.9-112.5 32.5-32.5 70.4-58.1 112.5-75.9C430.6 167.3 477 158 524.8 158s94.1 9.3 137.7 27.8c42.1 17.8 80 43.4 112.5 75.9 10.2 10.3 19.8 21 28.6 32.3l59.8-46.8C784.7 146.6 662.2 81.9 524.6 82 285 82.1 92.6 276.7 95 516.4 97.4 751.9 288.9 942 524.8 942c185.5 0 343.5-117.6 403.7-282.3 1.5-4.2-0.7-8.9-4.9-10.4z\"  ></path></symbol><symbol id=\"icon-gonggao-copy\" viewBox=\"0 0 1024 1024\"><path d=\"M768 518.4a8.533333 8.533333 0 0 1-8.533333 8.533333H264.533333a8.533333 8.533333 0 0 1-8.533333-8.533333v-55.04c0-4.693333 3.84-8.533333 8.533333-8.533333h494.933334c4.693333 0 8.533333 3.84 8.533333 8.533333v55.04zM631.466667 697.6a8.533333 8.533333 0 0 0 8.533333-8.533333v-55.04a8.533333 8.533333 0 0 0-8.533333-8.533334H264.533333a8.533333 8.533333 0 0 0-8.533333 8.533334v55.04c0 4.693333 3.84 8.533333 8.533333 8.533333h366.933334z\" fill=\"#ffffff\" ></path><path d=\"M541.312 83.584a48.853333 48.853333 0 0 0-58.624 0L252.8 256H117.333333a32 32 0 0 0-32 32v576c0 17.664 14.336 32 32 32h789.333334a32 32 0 0 0 32-32V288a32 32 0 0 0-32-32h-135.466667l-229.888-172.416zM651.008 256H372.992L512 151.722667 651.008 256zM157.44 823.893333V328.106667h709.12v495.786666H157.44z\" fill=\"#ffffff\" ></path></symbol><symbol id=\"icon-gonggao\" viewBox=\"0 0 1024 1024\"><path d=\"M768 518.4a8.533333 8.533333 0 0 1-8.533333 8.533333H264.533333a8.533333 8.533333 0 0 1-8.533333-8.533333v-55.04c0-4.693333 3.84-8.533333 8.533333-8.533333h494.933334c4.693333 0 8.533333 3.84 8.533333 8.533333v55.04zM631.466667 697.6a8.533333 8.533333 0 0 0 8.533333-8.533333v-55.04a8.533333 8.533333 0 0 0-8.533333-8.533334H264.533333a8.533333 8.533333 0 0 0-8.533333 8.533334v55.04c0 4.693333 3.84 8.533333 8.533333 8.533333h366.933334z\"  ></path><path d=\"M541.312 83.584a48.853333 48.853333 0 0 0-58.624 0L252.8 256H117.333333a32 32 0 0 0-32 32v576c0 17.664 14.336 32 32 32h789.333334a32 32 0 0 0 32-32V288a32 32 0 0 0-32-32h-135.466667l-229.888-172.416zM651.008 256H372.992L512 151.722667 651.008 256zM157.44 823.893333V328.106667h709.12v495.786666H157.44z\"  ></path></symbol><symbol id=\"icon-DCcaijiqiguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M744 272h-80a8 8 0 0 0-8 8v464c0 4.416 3.584 8 8 8h80a8 8 0 0 0 8-8v-464a8 8 0 0 0-8-8z m-192 280h-80a8 8 0 0 0-8 8v184c0 4.416 3.584 8 8 8h80a8 8 0 0 0 8-8V560a8 8 0 0 0-8-8z m-192-72h-80a8 8 0 0 0-8 8v256c0 4.416 3.584 8 8 8h80a8 8 0 0 0 8-8v-256a8 8 0 0 0-8-8zM144 912h736a32 32 0 0 0 32-32V144a32 32 0 0 0-32-32H144a32 32 0 0 0-32 32v736a32 32 0 0 0 32 32z m40-728h656v656H184V184z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-kafka\" viewBox=\"0 0 1024 1024\"><path d=\"M469.312427 128.00896a127.99872 127.99872 0 0 1-93.119069 123.198768v92.99107a170.878291 170.878291 0 0 1 111.550885 79.359206l110.846891-63.99936a127.99872 127.99872 0 1 1 30.143699 65.855342L511.104009 493.253307a172.222278 172.222278 0 0 1-0.127999 37.247628l117.886821 68.095319a127.99872 127.99872 0 1 1-30.143698 65.855341L487.04025 600.132239A170.878291 170.878291 0 0 1 376.193358 678.403456v94.399056a127.99872 127.99872 0 1 1-72.063279 0.639994v-95.551045a170.750292 170.750292 0 0 1 0-333.180668V250.503735A127.99872 127.99872 0 1 1 469.312427 128.00896z m-127.99872 55.871441a55.871441 55.871441 0 1 0 0-111.742882 55.871441 55.871441 0 0 0 0 111.742882z m0 425.97974a98.559014 98.559014 0 1 0 0-197.118028 98.559014 98.559014 0 0 0 0 197.118028z m439.931601-268.541314a55.871441 55.871441 0 1 0-111.806882 0 55.871441 55.871441 0 0 0 111.806882 0z m-55.935441 397.244027a55.871441 55.871441 0 1 0 0-111.806882 55.871441 55.871441 0 0 0 0 111.806882zM397.249148 896.00128a55.871441 55.871441 0 1 0-111.806882 0 55.871441 55.871441 0 0 0 111.806882 0z\" fill=\"#2F81F9\" ></path></symbol><symbol id=\"icon-rizhishenji\" viewBox=\"0 0 1024 1024\"><path d=\"M296 249.984a8 8 0 0 0-8 8v48c0 4.416 3.584 8 8 8h384a8 8 0 0 0 8-8v-48a8 8 0 0 0-8-8h-384zM480 393.984H296a8 8 0 0 0-8 8v48c0 4.416 3.584 8 8 8H480a8 8 0 0 0 8-8v-48a8 8 0 0 0-8-8z m-48 458.048h-224v-704H768v320c0 4.352 3.584 8 8 8H832a8 8 0 0 0 8-8V108.032a32 32 0 0 0-32-32h-640a32 32 0 0 0-32 32v784a32 32 0 0 0 32 32H432a8 8 0 0 0 8-8.064v-55.936a8 8 0 0 0-8-8.064z m440-88.064h-144v-36.544a112 112 0 1 0-64 0v36.608h-144a16 16 0 0 0-16 16v151.936c0 8.832 7.168 16 16 16h352a16 16 0 0 0 16-16v-151.936a16 16 0 0 0-16-16z m-225.984-144a50.048 50.048 0 1 1 100.032 0.064 50.048 50.048 0 0 1-100.032 0z m179.968 266.048H566.016v-60.032h259.968v60.032z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-luojijiqunguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M888 680h-54.016V539.968h-288V448h238.016a16 16 0 0 0 16-16V168a16 16 0 0 0-16-16h-544a16 16 0 0 0-16 16V432c0 8.832 7.168 16 16 16h238.016v92.032h-288v139.968h-54.016A8 8 0 0 0 128 688v176c0 4.416 3.584 8 8 8h176A8 8 0 0 0 320 864v-176a8 8 0 0 0-8-8h-54.016V608H478.08v72h-54.016a8 8 0 0 0-8 8v176c0 4.416 3.584 8 8 8h176A8 8 0 0 0 608 864v-176a8 8 0 0 0-8-8h-54.016V608h220.032v72h-54.016a8 8 0 0 0-8 8v176c0 4.416 3.584 8 8 8h176A8 8 0 0 0 896 864v-176a8 8 0 0 0-8-8zM256 805.312a2.688 2.688 0 0 1-2.688 2.688H194.56a2.688 2.688 0 0 1-2.752-2.688v-58.688c0-1.536 1.28-2.752 2.752-2.752h58.688c1.472 0 2.688 1.28 2.688 2.752v58.688z m288 0a2.688 2.688 0 0 1-2.688 2.688H482.56a2.688 2.688 0 0 1-2.752-2.688v-58.688c0-1.536 1.28-2.752 2.752-2.752h58.688c1.472 0 2.688 1.28 2.688 2.752v58.688zM288 384V216h448V384h-448z m544 421.312a2.688 2.688 0 0 1-2.688 2.688h-58.688a2.688 2.688 0 0 1-2.752-2.688v-58.688c0-1.536 1.28-2.752 2.752-2.752h58.688c1.472 0 2.688 1.28 2.688 2.752v58.688zM360 299.968a40 40 0 1 0 80 0 40 40 0 0 0-80 0z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-quanxian\" viewBox=\"0 0 1088 1024\"><path d=\"M533.312 52.032c5.504 0 11.008 0.64 15.104 2.048l339.84 115.84c8.32 2.88 15.104 12.352 14.912 21.12v482.432c0 8.96-5.76 20.48-12.608 25.92l-344.704 268.608a20.48 20.48 0 0 1-12.608 4.096 20.672 20.672 0 0 1-12.608-4.096l-344.704-268.608a37.568 37.568 0 0 1-12.608-25.92V191.104c0-8.832 6.784-18.432 15.104-21.184l339.84-115.84a49.152 49.152 0 0 1 15.04-2.048z m0 73.088L235.328 226.688v427.584l297.984 232.256 298.048-232.256v-427.52L533.312 125.056z m32 611.008a8 8 0 0 1-8.064 7.936h-48a8 8 0 0 1-8.064-7.936V541.184a144.128 144.128 0 1 1 64.064 0v50.688h66.944c4.416 0 8 3.584 8 8v48a8 8 0 0 1-8 8.064H565.248zM533.184 320.64a80 80 0 1 0 0 160.064 80 80 0 1 0 0-160.064z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-esjiqun\" viewBox=\"0 0 1024 1024\"><path d=\"M96.768 413.44A427.861333 427.861333 0 0 0 85.333333 512a427.861333 427.861333 0 0 0 19.541334 128h643.584c31.061333 0 59.52-11.093333 81.664-29.44A127.744 127.744 0 0 0 876.458667 512c0-39.68-18.005333-75.093333-46.336-98.56A127.488 127.488 0 0 0 748.458667 384H104.874667a423.466667 423.466667 0 0 0-8.106667 29.44z m65.024 42.666667h586.666667a55.893333 55.893333 0 1 1 0 111.786666H161.792a357.717333 357.717333 0 0 1 0-111.786666zM120.832 341.333333a424.704 424.704 0 0 1 40.277333-72.106666A426.197333 426.197333 0 0 1 512 85.333333a426.197333 426.197333 0 0 1 379.989333 232.448 16.298667 16.298667 0 0 1-14.933333 23.552H120.874667z m649.6-72.106666A353.578667 353.578667 0 0 0 512 157.44a353.621333 353.621333 0 0 0-258.432 111.786667h516.864zM120.832 682.666667a424.917333 424.917333 0 0 0 40.277333 72.106666A426.197333 426.197333 0 0 0 512 938.666667a426.197333 426.197333 0 0 0 350.890667-183.893334l1.152-1.621333a427.776 427.776 0 0 0 27.946666-46.933333 16.298667 16.298667 0 0 0-14.933333-23.552H120.874667z m649.6 72.106666A353.578667 353.578667 0 0 1 512 866.56a353.621333 353.621333 0 0 1-258.432-111.786667h516.864z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-kuaisuzhenduan\" viewBox=\"0 0 1024 1024\"><path d=\"M839.232 278.08A32 32 0 0 0 808.768 256H736V144a32 32 0 0 0-32-32H320a32 32 0 0 0-32 32V256H215.168a31.936 31.936 0 0 0-30.336 22.08L112 502.016v377.984a32 32 0 0 0 32 32h736a32 32 0 0 0 32-32V502.016l-72.768-223.936z m-479.232-94.08h304V256h-304V184z m480 656H184V513.408l60.288-185.408h535.424l60.288 185.408v326.592z m-188.032-268.032H544V464a8 8 0 0 0-8-8h-48a8 8 0 0 0-8 8v108.032H371.968a8 8 0 0 0-8 7.936v48c0 4.48 3.648 8.064 8 8.064H480v107.968c0 4.416 3.584 8 8 8h48a8 8 0 0 0 8-8V635.968h108.032a8 8 0 0 0 7.936-7.936v-48a8 8 0 0 0-7.936-8.064z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-dashboard\" viewBox=\"0 0 1024 1024\"><path d=\"M750.912 853.312c9.472 0 17.088 7.68 17.088 17.088v37.952c0 9.472-7.68 17.088-17.088 17.088H273.088A17.088 17.088 0 0 1 256 908.352V870.4c0-9.408 7.68-17.088 17.088-17.088zM906.688 128a32 32 0 0 1 32 32v576a32 32 0 0 1-32 32H117.312a32 32 0 0 1-32-32v-576a32 32 0 0 1 32-32z m-40.128 72.128H157.44v495.744h709.12V200.128z m-112 106.304l26.88 26.88a17.088 17.088 0 0 1 0 24.128L566.72 572.16a17.088 17.088 0 0 1-24.128 0L426.688 456.192l-133.12 133.12a17.088 17.088 0 0 1-24.128 0l-26.88-26.88a17.088 17.088 0 0 1 0-24.128l172.032-172.032a17.088 17.088 0 0 1 24.128 0l115.968 115.968 175.744-175.808a17.088 17.088 0 0 1 24.128 0z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-zizhufuwu\" viewBox=\"0 0 1024 1024\"><path d=\"M688 312v-48A8 8 0 0 0 680 256h-384a8 8 0 0 0-8 8v48c0 4.416 3.584 8 8 8h384a8 8 0 0 0 8-8zM296 400a8 8 0 0 0-8 8v48c0 4.416 3.584 8 8 8H480a8 8 0 0 0 8-8v-48A8 8 0 0 0 480 400H296zM672 516.032a216 216 0 1 0 0 432 216 216 0 0 0 0-432z m107.52 323.456a151.04 151.04 0 0 1-107.52 44.48 151.04 151.04 0 0 1-107.52-44.48 151.04 151.04 0 0 1-44.48-107.52c0-40.576 15.808-78.72 44.48-107.52a151.04 151.04 0 0 1 107.52-44.416 151.04 151.04 0 0 1 107.52 44.48 151.04 151.04 0 0 1 44.48 107.52 151.04 151.04 0 0 1-44.48 107.52z m-18.56-183.488h-44.288a7.936 7.936 0 0 0-6.464 3.328l-63.488 87.744-23.104-31.872a7.936 7.936 0 0 0-6.528-3.328h-44.096a8 8 0 0 0-6.464 12.736l73.792 102.08c3.2 4.416 9.664 4.416 12.864 0l114.24-158.016a7.936 7.936 0 0 0-6.4-12.672z m-320.96 196.032H208v-704H768v343.936c0 4.48 3.584 8 8 8H832a8 8 0 0 0 8-8v-384a32 32 0 0 0-32-32h-640a32 32 0 0 0-32 32v784a32 32 0 0 0 32 32h272A8 8 0 0 0 448 916.032v-56.064a8 8 0 0 0-8-7.936z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-topicqianyi\" viewBox=\"0 0 1024 1024\"><path d=\"M868.032 732.032h-70.336a15.744 15.744 0 0 0-12.288 5.76 353.856 353.856 0 0 1-273.024 128.192 352.768 352.768 0 0 1-250.56-103.68 353.28 353.28 0 0 1-76.032-112.512A350.528 350.528 0 0 1 158.08 512 352.32 352.32 0 0 1 261.76 261.76a353.856 353.856 0 0 1 250.56-103.744 353.856 353.856 0 0 1 273.024 128.192c3.008 3.712 7.616 5.76 12.288 5.76h70.272c6.336 0 10.24-6.976 6.72-12.288A430.208 430.208 0 0 0 511.36 81.984 429.504 429.504 0 0 0 81.984 516.48a430.272 430.272 0 0 0 430.4 425.6 430.272 430.272 0 0 0 362.304-197.76 8 8 0 0 0-6.656-12.224z m88.896-226.304l-141.952-112a8 8 0 0 0-12.992 6.272v76.032H488a8 8 0 0 0-8 8v56c0 4.352 3.584 7.936 8 7.936h313.984V624c0 6.72 7.808 10.496 12.992 6.272l141.952-112a8 8 0 0 0 0-12.544z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-jiqunxiangqing\" viewBox=\"0 0 1024 1024\"><path d=\"M832 64H192a32 32 0 0 0-32 32v832a32 32 0 0 0 32 32h640a32 32 0 0 0 32-32v-832A32 32 0 0 0 832 64zM232 136h560v208h-560v-208z m560 480h-560v-208h560v208z m0 272h-560v-208h560v208zM496 208H312a8 8 0 0 0-8 8v48c0 4.416 3.584 8 8 8H496a8 8 0 0 0 8-8v-48a8 8 0 0 0-8-8zM312 544H496a8 8 0 0 0 8-8v-48A8 8 0 0 0 496 480H312a8 8 0 0 0-8 8v48c0 4.416 3.584 8 8 8zM640 788.032a40 40 0 1 0 80 0 40 40 0 0 0-80 0z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-connectguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M574.016 665.408a8 8 0 0 0-11.328 0l-116.16 116.224c-53.824 53.76-144.64 59.52-204.032 0a143.616 143.616 0 0 1 0-204.032l116.224-116.224a8 8 0 0 0 0-11.264l-39.808-39.808a8 8 0 0 0-11.328 0L191.424 526.528a216.192 216.192 0 0 0 0 305.92 216.32 216.32 0 0 0 305.92 0l116.288-116.16a8 8 0 0 0 0-11.264l-39.68-39.68z m258.56-473.984a216.192 216.192 0 0 0-305.92 0L410.24 307.584a8 8 0 0 0 0 11.328l39.68 39.68a8 8 0 0 0 11.328 0l116.16-116.16c53.824-53.824 144.64-59.52 204.032 0 59.52 59.52 53.76 150.144 0 203.968l-116.224 116.224a8 8 0 0 0 0 11.264l39.808 39.808a8 8 0 0 0 11.328 0l116.16-116.224a216.512 216.512 0 0 0 0-306.048zM610.112 372.288a8 8 0 0 0-11.328 0L372.288 598.72a8 8 0 0 0 0 11.264l39.616 39.616a8 8 0 0 0 11.264 0l226.432-226.432a8 8 0 0 0 0-11.264l-39.488-39.616z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-peizhiguanli\" viewBox=\"0 0 1024 1024\"><path d=\"M880 112H144a32 32 0 0 0-32 32v736a32 32 0 0 0 32 32h736a32 32 0 0 0 32-32V144a32 32 0 0 0-32-32z m-40 728H184V184h656v656z m-500.032-156.992v76.992c0 4.416 3.648 8 8 8h48a8 8 0 0 0 8-8v-76.992a105.6 105.6 0 0 1-64 0z m64-198.016V264A8 8 0 0 0 396.032 256h-48a8 8 0 0 0-8 8v220.992a105.6 105.6 0 0 1 64 0z m-64 198.016a105.6 105.6 0 0 0 64 0 104 104 0 1 0-64 0z m0.128-115.712l1.024-1.792v-0.128l1.152-1.792c0.128-0.192 0.256-0.256 0.32-0.512l1.024-1.344 0.256-0.448 1.408-1.6 0.32-0.256 1.216-1.28 0.384-0.32 1.6-1.408a19.2 19.2 0 0 1 1.728-1.28l0.448-0.32 1.408-1.024 0.384-0.32c0.64-0.384 1.28-0.64 1.92-1.088 0.128-0.064 0.32-0.064 0.384-0.192 0.512-0.32 1.024-0.512 1.6-0.768l0.64-0.32c0.64-0.32 1.28-0.64 1.984-0.832a17.28 17.28 0 0 1 2.112-0.64l0.64-0.256a10.432 10.432 0 0 1 1.664-0.384l0.512-0.064c0.64-0.256 1.472-0.32 2.176-0.448l0.512-0.064 1.792-0.192h0.64l2.24-0.128c0.832 0 1.536 0 2.304 0.128h0.64a11.008 11.008 0 0 1 2.24 0.256c0.704 0.128 1.536 0.192 2.24 0.448l0.512 0.064 1.664 0.384 0.64 0.256a17.28 17.28 0 0 1 2.048 0.64l2.048 0.832 0.64 0.32a11.968 11.968 0 0 1 1.536 0.768l0.384 0.192 1.92 1.088 0.384 0.32c0.512 0.32 1.024 0.64 1.408 1.024l0.512 0.256 1.664 1.28a20.032 20.032 0 0 1 1.664 1.472l0.384 0.384 1.216 1.216 0.256 0.256a20.032 20.032 0 0 1 1.408 1.6l0.32 0.448a7.04 7.04 0 0 1 0.96 1.344l0.32 0.512 1.216 1.792 0.064 0.128c0.448 0.64 0.704 1.216 1.024 1.792a36.16 36.16 0 0 1 0 33.408l-1.024 1.792-0.064 0.128-1.216 1.792-0.32 0.512-0.96 1.344-0.32 0.448-1.408 1.6-0.256 0.256-1.28 1.28-0.32 0.32-1.664 1.408a19.2 19.2 0 0 1-1.664 1.28l-0.512 0.32-1.408 1.024-0.384 0.32-1.92 1.088-0.384 0.192c-0.512 0.32-1.024 0.512-1.6 0.768l-0.64 0.32a17.28 17.28 0 0 1-4.096 1.472c-0.128 0.128-0.384 0.128-0.576 0.256a10.432 10.432 0 0 1-1.664 0.384l-0.512 0.064c-0.704 0.256-1.536 0.32-2.176 0.448l-0.512 0.064-1.792 0.192h-0.64l-2.304 0.128c-0.768 0-1.472 0-2.304-0.128h-0.64a11.008 11.008 0 0 1-1.728-0.192l-0.512-0.064c-0.64-0.128-1.472-0.192-2.176-0.448l-0.512-0.064-1.728-0.384-0.64-0.256a17.28 17.28 0 0 1-2.048-0.64l-1.984-0.832-0.64-0.32a11.968 11.968 0 0 1-1.6-0.768c-0.064-0.128-0.256-0.128-0.384-0.192a18.56 18.56 0 0 1-1.92-1.088l-0.384-0.32-1.408-1.024-0.448-0.256-1.728-1.28a20.032 20.032 0 0 1-1.6-1.472l-0.384-0.384L345.6 608.64l-0.32-0.256a20.032 20.032 0 0 1-1.408-1.6l-0.256-0.448a7.04 7.04 0 0 1-1.024-1.344c-0.064-0.256-0.192-0.32-0.32-0.512l-1.152-1.792v-0.128a36.16 36.16 0 0 1-1.024-35.2z m279.872-28.288v220.992c0 4.416 3.648 8 8.064 8h48a8 8 0 0 0 7.936-8V539.008a105.6 105.6 0 0 1-64 0z m64-198.016V264A8 8 0 0 0 676.032 256h-48a8 8 0 0 0-8.064 8v76.992a105.6 105.6 0 0 1 64 0z m-64 198.016a105.6 105.6 0 0 0 64 0 104 104 0 1 0-64 0z m0.128-115.712l1.024-1.792v-0.128l1.152-1.792c0.128-0.192 0.256-0.256 0.32-0.512l1.024-1.344 0.256-0.448 1.408-1.6 0.32-0.256 1.216-1.28 0.384-0.32 1.6-1.408a19.2 19.2 0 0 1 1.728-1.28l0.448-0.32 1.408-1.024 0.384-0.32c0.64-0.384 1.28-0.64 1.92-1.088 0.128-0.064 0.32-0.064 0.384-0.192 0.512-0.32 1.024-0.512 1.6-0.768l0.64-0.32c0.64-0.32 1.28-0.64 1.984-0.832l2.112-0.64 0.64-0.256a10.432 10.432 0 0 1 1.664-0.384l0.512-0.064c0.64-0.256 1.472-0.32 2.176-0.448l0.512-0.064 1.792-0.192h0.64l2.24-0.128c0.832 0 1.536 0 2.304 0.128h0.64l1.792 0.192 0.448 0.064c0.704 0.128 1.536 0.192 2.24 0.448l0.512 0.064 1.664 0.384 0.64 0.256a17.28 17.28 0 0 1 2.048 0.64l2.048 0.832 0.64 0.32a11.968 11.968 0 0 1 1.536 0.768l0.384 0.192 1.92 1.088 0.384 0.32c0.512 0.32 1.024 0.64 1.408 1.024l0.512 0.256 1.728 1.28a20.032 20.032 0 0 1 1.536 1.472l0.448 0.384 1.152 1.216 0.32 0.256a20.032 20.032 0 0 1 1.408 1.6l0.32 0.448c0.384 0.384 0.64 0.896 0.96 1.344l0.32 0.512 1.216 1.792v0.128l0.96 1.792a36.16 36.16 0 0 1 0 33.408c-0.256 0.64-0.64 1.216-0.96 1.792v0.128l-1.216 1.792-0.32 0.512-0.96 1.344-0.32 0.448-1.408 1.6-0.32 0.256-1.152 1.28-0.448 0.32c-0.448 0.512-0.96 0.896-1.536 1.408a19.2 19.2 0 0 1-1.728 1.28l-0.512 0.32-1.408 1.024-0.384 0.32-1.92 1.088-0.384 0.192c-0.512 0.32-1.024 0.512-1.6 0.768l-0.64 0.32a17.28 17.28 0 0 1-4.096 1.472c-0.128 0.128-0.384 0.128-0.576 0.256a10.432 10.432 0 0 1-1.664 0.384l-0.512 0.064c-0.704 0.256-1.536 0.32-2.24 0.448l-0.448 0.064-1.792 0.192h-0.64l-2.304 0.128c-0.768 0-1.472 0-2.304-0.128h-0.64l-1.728-0.192-0.512-0.064c-0.64-0.128-1.472-0.192-2.176-0.448l-0.512-0.064-1.728-0.384-0.64-0.256-2.048-0.64-1.984-0.832-0.64-0.32a11.968 11.968 0 0 1-1.6-0.768c-0.064-0.128-0.256-0.128-0.384-0.192a18.56 18.56 0 0 1-1.92-1.088l-0.384-0.32-1.408-1.024-0.448-0.256-1.728-1.28a20.032 20.032 0 0 1-1.6-1.472l-0.384-0.384-1.216-1.216-0.32-0.256a20.032 20.032 0 0 1-1.408-1.6l-0.256-0.448a7.04 7.04 0 0 1-1.024-1.344c-0.064-0.256-0.192-0.32-0.32-0.512l-1.152-1.792v-0.128a36.16 36.16 0 0 1-1.024-35.2z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-chenggong\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m176.896 340.821333L458.581333 568.32l-115.2-113.749333-57.514666 56.917333 172.714666 170.666667 287.829334-284.416-57.514667-56.917334z\"  ></path></symbol><symbol id=\"icon-shaixuan\" viewBox=\"0 0 1024 1024\"><path d=\"M794.56 193.92a51.2 51.2 0 0 1 41.472 81.28l-5.248 6.144L620.48 491.52v285.44h-64V465.088l207.168-207.232H270.272l207.232 207.232v425.856h-64v-399.36L203.264 281.344a51.2 51.2 0 0 1-4.992-66.688l4.992-5.76a51.2 51.2 0 0 1 28.16-14.336l8.064-0.64h555.072z\"  ></path></symbol><symbol id=\"icon-shibai\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m121.941333 341.333333L512 463.274667 390.058667 341.333333 341.333333 390.058667 463.189333 512 341.333333 633.941333 390.058667 682.666667 512 560.725333 633.941333 682.666667 682.666667 633.941333 560.725333 512 682.666667 390.058667 633.941333 341.333333z\"  ></path></symbol><symbol id=\"icon-zhedie\" viewBox=\"0 0 2048 1024\"><path d=\"M1050.4192 920.7808L1856.512 114.688a37.2736 37.2736 0 0 0-26.4192-63.488H217.9072a37.2736 37.2736 0 0 0-26.4192 63.488l806.0928 806.0928a37.2736 37.2736 0 0 0 52.8384 0z\"  ></path></symbol><symbol id=\"icon-shanchu\" viewBox=\"0 0 1024 1024\"><path d=\"M621.714286 0a146.285714 146.285714 0 0 1 146.285714 146.285714h219.428571a36.571429 36.571429 0 1 1 0 73.142857H950.857143v585.142858a219.428571 219.428571 0 0 1-219.428572 219.428571H292.571429a219.428571 219.428571 0 0 1-219.428572-219.428571V219.428571H36.571429a36.571429 36.571429 0 0 1 0-73.142857h219.428571a146.285714 146.285714 0 0 1 146.285714-146.285714h219.428572zM877.714286 219.428571H146.285714v585.142858a146.285714 146.285714 0 0 0 135.314286 145.92L292.571429 950.857143h438.857142a146.285714 146.285714 0 0 0 145.92-135.314286L877.714286 804.571429V219.428571zM512 365.714286a36.571429 36.571429 0 0 1 36.571429 36.571428v365.714286a36.571429 36.571429 0 1 1-73.142858 0v-365.714286A36.571429 36.571429 0 0 1 512 365.714286zM329.142857 365.714286a36.571429 36.571429 0 0 1 36.571429 36.571428v365.714286a36.571429 36.571429 0 1 1-73.142857 0v-365.714286a36.571429 36.571429 0 0 1 36.571428-36.571428z m365.714286 0a36.571429 36.571429 0 0 1 36.571428 36.571428v365.714286a36.571429 36.571429 0 1 1-73.142857 0v-365.714286a36.571429 36.571429 0 0 1 36.571429-36.571428z m-73.142857-292.571429h-219.428572a73.142857 73.142857 0 0 0-72.630857 64.585143L329.142857 146.285714h365.714286a73.142857 73.142857 0 0 0-64.585143-72.630857L621.714286 73.142857z\"  ></path></symbol><symbol id=\"icon-tianjia\" viewBox=\"0 0 1024 1024\"><path d=\"M824 480H544V200A8 8 0 0 0 536 192h-48a8 8 0 0 0-8 8V480H200A8 8 0 0 0 192 488v48c0 4.416 3.584 8 8 8H480v280c0 4.416 3.584 8 8 8h48a8 8 0 0 0 8-8V544h280A8 8 0 0 0 832 536v-48a8 8 0 0 0-8-8z\" fill=\"#303A51\" ></path></symbol><symbol id=\"icon-riqi\" viewBox=\"0 0 1024 1024\"><path d=\"M360.533333 26.709333c9.386667 0 17.066667 7.594667 17.066667 17.066667v55.466667l-0.256 2.048 343.893333 0.085333a17.237333 17.237333 0 0 1-0.170666-2.133333v-55.466667c0-9.472 7.68-17.066667 17.066666-17.066667h55.466667c9.386667 0 17.066667 7.594667 17.066667 17.066667v55.466667l-0.341334 2.048h172.032c8.277333 0 14.933333 6.741333 14.933334 14.933333v866.133333a14.933333 14.933333 0 0 1-14.933334 14.933334H41.728a14.933333 14.933333 0 0 1-14.933333-14.933334V116.224c0-8.192 6.656-14.933333 14.933333-14.933333l246.528 0.085333a17.237333 17.237333 0 0 1-0.170667-2.133333v-55.466667c0-9.472 7.68-17.066667 17.066667-17.066667h55.466667z m547.157334 164.181334H116.394667L116.053333 347.648l490.837334 0.085333c9.386667 0 17.066667 7.68 17.066666 17.066667v55.466667a17.066667 17.066667 0 0 1-17.066666 17.066666H116.053333l0.085334 470.357334h791.466666v-716.8z m-76.8 448c9.472 0 17.066667 7.68 17.066666 17.066666v174.933334a17.066667 17.066667 0 0 1-17.066666 17.066666h-174.933334a17.066667 17.066667 0 0 1-17.066666-17.066666v-174.933334c0-9.386667 7.68-17.066667 17.066666-17.066666h174.933334z\"  ></path></symbol><symbol id=\"icon-shuaxin\" viewBox=\"0 0 1024 1024\"><path d=\"M511.960506 0a511.814231 511.814231 0 0 1 427.706434 230.382228L1023.921012 146.27443v255.980253h-256.345939l119.067386-118.921112a438.823291 438.823291 0 1 0 29.620572 399.475469 36.568608 36.568608 0 0 1 67.359375 28.523514A512.033643 512.033643 0 1 1 511.960506 0z\"  ></path></symbol><symbol id=\"icon-sousuo\" viewBox=\"0 0 1024 1024\"><path d=\"M802.730667 739.498667l190.122666 190.037333a14.933333 14.933333 0 0 1 0 21.162667l-42.24 42.154666a14.933333 14.933333 0 0 1-21.162666 0L739.413333 802.816a14.933333 14.933333 0 0 1 0-21.077333l42.24-42.24a14.933333 14.933333 0 0 1 21.077334 0z m-75.008-592.469334a410.709333 410.709333 0 1 1-580.778667 580.778667 410.709333 410.709333 0 0 1 580.778667-580.778667z m-517.376 63.317334a321.024 321.024 0 1 0 453.973333 454.058666 321.024 321.024 0 0 0-453.973333-453.973333z\"  ></path></symbol><symbol id=\"icon-leader\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 85.333333a426.666667 426.666667 0 1 0 0 853.333334A426.666667 426.666667 0 0 0 512 85.333333z\"  ></path><path d=\"M512 213.333333a213.333333 213.333333 0 1 0 0 426.666667 213.333333 213.333333 0 0 0 0-426.666667z m0 85.333334a128 128 0 1 1 0 256 128 128 0 0 1 0-256z\"  ></path><path d=\"M512 554.666667a384.170667 384.170667 0 0 1 375.893333 304.981333 513.877333 513.877333 0 0 1-77.397333 68.437333A298.666667 298.666667 0 0 0 213.333333 938.666667l0.170667-10.581334a514.901333 514.901333 0 0 1-77.312-68.266666A384 384 0 0 1 512 554.666667z\"  ></path></symbol><symbol id=\"icon-info\" viewBox=\"0 0 1024 1024\"><path d=\"M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m28.233143 406.454857c-15.36 4.534857-29.184 9.069714-41.472 13.604572-12.361143 4.534857-24.137143 9.069714-35.547429 13.604571-11.264 4.534857-22.820571 9.289143-34.450285 14.116571-11.702857 4.900571-24.868571 10.24-39.497143 16.091429l8.996571 27.209143c8.630857-1.974857 15.140571-3.072 19.456-3.437714a26.112 26.112 0 0 1 11.556572 1.462857c4.608 1.316571 8.118857 4.388571 10.459428 9.289143a61.001143 61.001143 0 0 1 5.046857 15.506285c0.950857 5.558857 1.462857 10.605714 1.462857 15.140572v6.802285c0 3.218286-0.146286 7.606857-0.512 13.165715l-0.950857 14.774857-1.024 15.36-4.022857 61.293714c-1.682286 26.258286-4.169143 61.44-7.460571 105.545143 0 18.139429 1.170286 33.572571 3.437714 46.153143 2.340571 12.653714 6.217143 23.844571 11.556571 33.645714 3.291429 3.218286 6.144 5.12 8.484572 5.851429a36.864 36.864 0 0 0 9.508571 0.877714 605.622857 605.622857 0 0 0 84.992-38.4c29.330286-15.872 60.708571-34.230857 93.988572-54.930286l1.024-28.233143c-14.043429 5.12-24.502857 8.923429-31.451429 11.190858-7.094857 2.194286-13.165714 4.022857-18.578286 5.339428a136.777143 136.777143 0 0 1-20.48 3.437714 205.531429 205.531429 0 0 1-19.529142 1.462858c-8.045714 0.585143-12.434286-5.193143-13.458286-17.554286a628.150857 628.150857 0 0 1-1.462857-48.64v-7.753143c0-3.291429 0.292571-9.142857 0.950857-17.554286 0.658286-8.411429 1.462857-20.918857 2.486857-37.449143 1.024-16.530286 2.486857-39.424 4.534857-68.608 1.974857-26.550857 3.657143-50.541714 4.973714-71.972571 1.316571-21.357714 1.974857-35.035429 1.974858-40.813714a16.822857 16.822857 0 0 0-4.973715-12.653715c-3.364571-3.291429-6.656-4.242286-10.020571-2.925714z m-16.969143-205.385143a64 64 0 1 0 0 128 64 64 0 0 0 0-128z\"  ></path></symbol><symbol id=\"icon-fuzhi\" viewBox=\"0 0 1024 1024\"><path d=\"M672 288a64 64 0 0 1 64 64v448a64 64 0 0 1-64 64h-448a64 64 0 0 1-64-64v-448a64 64 0 0 1 64-64h448z m0 64h-448v448h448v-448z\"  ></path><path d=\"M800 128a96 96 0 0 1 95.552 86.784L896 224v384a96 96 0 0 1-86.784 95.552L800 704h-61.248v-64h61.248a32 32 0 0 0 31.488-26.24L832 608v-384a32 32 0 0 0-26.24-31.488L800 192h-384a32 32 0 0 0-31.488 26.24L384 224v63.68H320V224a96 96 0 0 1 86.784-95.552L416 128h384z\"  ></path></symbol><symbol id=\"icon-bianji\" viewBox=\"0 0 1024 1024\"><path d=\"M865.28 256.64l-137.984-138.112a96 96 0 0 0-135.808 0L258.368 451.712a96 96 0 0 0-27.264 55.232l-26.688 200.64a64 64 0 0 0 71.872 71.872l200.64-26.688a96 96 0 0 0 55.232-27.264l333.184-333.12a96 96 0 0 0 0-135.808z m-183.232-92.8l138.048 137.984a32 32 0 0 1 0 45.312l-333.184 333.12a32 32 0 0 1-18.368 9.088l-200.704 26.688 26.688-200.64a32 32 0 0 1 9.088-18.432l333.12-333.184a32 32 0 0 1 45.312 0z\"  ></path><path d=\"M308.032 457.6l228.544 228.544-45.248 45.312-228.544-228.608z\"  ></path><path d=\"M192 832h704v64H192z\"  ></path></symbol><symbol id=\"icon-xiazai\" viewBox=\"0 0 1024 1024\"><path d=\"M955.538286 702.171429a36.571429 36.571429 0 0 1 35.986285 29.988571l0.585143 6.582857v206.774857a36.571429 36.571429 0 0 1-29.988571 35.986286l-6.582857 0.585143H74.459429a36.571429 36.571429 0 0 1-35.986286-29.988572l-0.585143-6.582857v-206.848a36.571429 36.571429 0 0 1 72.557714-6.582857l0.585143 6.582857v170.203429h807.936v-170.203429a36.571429 36.571429 0 0 1 29.988572-35.986285l6.582857-0.585143zM514.998857 36.571429a36.571429 36.571429 0 0 1 35.986286 29.988571l0.585143 6.582857v661.357714l241.152-241.005714a36.571429 36.571429 0 0 1 46.665143-4.242286l5.12 4.242286a36.571429 36.571429 0 0 1 4.169142 46.665143l-4.242285 5.12-302.811429 302.811429a36.571429 36.571429 0 0 1-46.665143 4.242285l-5.12-4.242285-310.272-310.345143a36.571429 36.571429 0 0 1 46.665143-55.954286l5.046857 4.242286 247.149715 247.222857V73.142857a36.571429 36.571429 0 0 1 36.571428-36.571428z\"  ></path></symbol><symbol id=\"icon-quanping\" viewBox=\"0 0 1024 1024\"><path d=\"M341.049126 0a42.631141 42.631141 0 0 1 7.673605 84.580183L341.049126 85.262281H145.37219l267.894088 268.576187a42.631141 42.631141 0 0 1-54.56786 65.225645l-5.797835-4.945212L85.262281 145.798501V341.049126a42.631141 42.631141 0 0 1-34.957535 41.949042L42.631141 383.680266a42.631141 42.631141 0 0 1-41.949043-34.957535L0 341.049126V41.778518C0 39.902748 0.170525 38.026978 0.511574 36.151207L0 42.631141A42.801665 42.801665 0 0 1 12.533555 12.448293L13.81249 11.254621A42.886928 42.886928 0 0 1 17.052456 8.440966L12.533555 12.448293A42.801665 42.801665 0 0 1 34.957535 0.682098L36.406994 0.426311A42.886928 42.886928 0 0 1 41.778518 0H341.049126zM341.049126 1023.147377a42.631141 42.631141 0 0 0 7.673605-84.580183L341.049126 937.885096H145.37219l267.894088-268.576187a42.631141 42.631141 0 0 0-54.56786-65.225645l-5.797835 4.945212L85.262281 877.348876V682.098251a42.631141 42.631141 0 0 0-34.957535-41.949042L42.631141 639.467111a42.631141 42.631141 0 0 0-41.949043 34.957535L0 682.098251v299.270608c0 1.87577 0.170525 3.75154 0.511574 5.627311L0 980.516236a42.801665 42.801665 0 0 0 12.533555 30.182848l1.278935 1.193672a42.886928 42.886928 0 0 0 3.325229 2.813655l-4.604164-4.007327a42.801665 42.801665 0 0 0 22.42398 11.766195l1.449459 0.255787c1.705246 0.255787 3.495754 0.341049 5.286262 0.426311H341.049126zM682.098251 0a42.631141 42.631141 0 0 0-7.673605 84.580183L682.098251 85.262281h195.676936L609.881099 353.838468a42.631141 42.631141 0 0 0 54.56786 65.225645l5.797835-4.945212L937.885096 145.798501V341.049126a42.631141 42.631141 0 0 0 34.957535 41.949042l7.673605 0.682098a42.631141 42.631141 0 0 0 41.949043-34.957535L1023.147377 341.049126V41.778518a42.886928 42.886928 0 0 0-0.511574-5.627311L1023.147377 42.631141a42.801665 42.801665 0 0 0-12.533555-30.182848l-1.278934-1.193672A42.886928 42.886928 0 0 0 1006.094921 8.440966l4.604163 4.007327a42.801665 42.801665 0 0 0-22.42398-11.766195l-1.449459-0.255787A42.886928 42.886928 0 0 0 981.368859 0H682.098251zM682.098251 1023.147377a42.631141 42.631141 0 0 1-7.673605-84.580183L682.098251 937.885096h195.676936L609.881099 669.308909a42.631141 42.631141 0 0 1 54.56786-65.225645l5.797835 4.945212L937.885096 877.348876V682.098251a42.631141 42.631141 0 0 1 34.957535-41.949042l7.673605-0.682098a42.631141 42.631141 0 0 1 41.949043 34.957535L1023.147377 682.098251v299.270608a42.886928 42.886928 0 0 1-0.511574 5.627311L1023.147377 980.516236a42.801665 42.801665 0 0 1-12.533555 30.182848l-1.278934 1.193672a42.886928 42.886928 0 0 1-3.325229 2.813655l4.604163-4.007327a42.801665 42.801665 0 0 1-22.42398 11.766195l-1.449459 0.255787a42.886928 42.886928 0 0 1-5.286261 0.426311H682.098251z\"  ></path></symbol></svg>', m = (m = document.getElementsByTagName(\"script\"))[m.length - 1].getAttribute(\"data-injectcss\"); if (m && !a.__iconfont__svg__cssinject__) { a.__iconfont__svg__cssinject__ = !0; try { document.write(\"<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>\") } catch (a) { console && console.log(a) } } function e() { v || (v = !0, c()) } l = function () { var a, l, h; (h = document.createElement(\"div\")).innerHTML = t, t = null, (l = h.getElementsByTagName(\"svg\")[0]) && (l.setAttribute(\"aria-hidden\", \"true\"), l.style.position = \"absolute\", l.style.width = 0, l.style.height = 0, l.style.overflow = \"hidden\", a = l, (h = document.body).firstChild ? (l = h.firstChild).parentNode.insertBefore(a, l) : h.appendChild(a)) }, document.addEventListener ? ~[\"complete\", \"loaded\", \"interactive\"].indexOf(document.readyState) ? setTimeout(l, 0) : (h = function () { document.removeEventListener(\"DOMContentLoaded\", h, !1), l() }, document.addEventListener(\"DOMContentLoaded\", h, !1)) : document.attachEvent && (c = l, i = a.document, v = !1, (o = function () { try { i.documentElement.doScroll(\"left\") } catch (a) { return void setTimeout(o, 50) } e() })(), i.onreadystatechange = function () { \"complete\" == i.readyState && (i.onreadystatechange = null, e()) }) }(window);"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/iconfont-logi/iconfont.json",
    "content": "{\n  \"id\": \"2679570\",\n  \"name\": \"日志分析等方向\",\n  \"font_family\": \"iconfont\",\n  \"css_prefix_text\": \"icon-\",\n  \"description\": \"\",\n  \"glyphs\": [\n    {\n      \"icon_id\": \"16810871\",\n      \"name\": \"展开icon\",\n      \"font_class\": \"zhankaiicon\",\n      \"unicode\": \"e68e\",\n      \"unicode_decimal\": 59022\n    },\n    {\n      \"icon_id\": \"16810872\",\n      \"name\": \"收起icon\",\n      \"font_class\": \"shouqiicon\",\n      \"unicode\": \"e68f\",\n      \"unicode_decimal\": 59023\n    },\n    {\n      \"icon_id\": \"16827520\",\n      \"name\": \"我的消息icon\",\n      \"font_class\": \"wodexiaoxiicon\",\n      \"unicode\": \"e691\",\n      \"unicode_decimal\": 59025\n    },\n    {\n      \"icon_id\": \"4765853\",\n      \"name\": \"reload time\",\n      \"font_class\": \"reloadtime\",\n      \"unicode\": \"e789\",\n      \"unicode_decimal\": 59273\n    },\n    {\n      \"icon_id\": \"23116030\",\n      \"name\": \"公告\",\n      \"font_class\": \"gonggao-copy\",\n      \"unicode\": \"e9e1\",\n      \"unicode_decimal\": 59873\n    },\n    {\n      \"icon_id\": \"23106454\",\n      \"name\": \"公告\",\n      \"font_class\": \"gonggao\",\n      \"unicode\": \"e9d2\",\n      \"unicode_decimal\": 59858\n    },\n    {\n      \"icon_id\": \"23106455\",\n      \"name\": \"DC采集器管理\",\n      \"font_class\": \"DCcaijiqiguanli\",\n      \"unicode\": \"e9d3\",\n      \"unicode_decimal\": 59859\n    },\n    {\n      \"icon_id\": \"23106456\",\n      \"name\": \"kafka\",\n      \"font_class\": \"kafka\",\n      \"unicode\": \"e9d4\",\n      \"unicode_decimal\": 59860\n    },\n    {\n      \"icon_id\": \"23106457\",\n      \"name\": \"日志审计\",\n      \"font_class\": \"rizhishenji\",\n      \"unicode\": \"e9d5\",\n      \"unicode_decimal\": 59861\n    },\n    {\n      \"icon_id\": \"23106458\",\n      \"name\": \"逻辑集群管理\",\n      \"font_class\": \"luojijiqunguanli\",\n      \"unicode\": \"e9d6\",\n      \"unicode_decimal\": 59862\n    },\n    {\n      \"icon_id\": \"23106459\",\n      \"name\": \"权限\",\n      \"font_class\": \"quanxian\",\n      \"unicode\": \"e9d7\",\n      \"unicode_decimal\": 59863\n    },\n    {\n      \"icon_id\": \"23106460\",\n      \"name\": \"es集群\",\n      \"font_class\": \"esjiqun\",\n      \"unicode\": \"e9d8\",\n      \"unicode_decimal\": 59864\n    },\n    {\n      \"icon_id\": \"23106461\",\n      \"name\": \"快速诊断\",\n      \"font_class\": \"kuaisuzhenduan\",\n      \"unicode\": \"e9d9\",\n      \"unicode_decimal\": 59865\n    },\n    {\n      \"icon_id\": \"23106462\",\n      \"name\": \"dashboard\",\n      \"font_class\": \"dashboard\",\n      \"unicode\": \"e9da\",\n      \"unicode_decimal\": 59866\n    },\n    {\n      \"icon_id\": \"23106463\",\n      \"name\": \"自助服务\",\n      \"font_class\": \"zizhufuwu\",\n      \"unicode\": \"e9db\",\n      \"unicode_decimal\": 59867\n    },\n    {\n      \"icon_id\": \"23106464\",\n      \"name\": \"topic迁移\",\n      \"font_class\": \"topicqianyi\",\n      \"unicode\": \"e9dc\",\n      \"unicode_decimal\": 59868\n    },\n    {\n      \"icon_id\": \"23106465\",\n      \"name\": \"集群详情\",\n      \"font_class\": \"jiqunxiangqing\",\n      \"unicode\": \"e9dd\",\n      \"unicode_decimal\": 59869\n    },\n    {\n      \"icon_id\": \"23106467\",\n      \"name\": \"connect管理\",\n      \"font_class\": \"connectguanli\",\n      \"unicode\": \"e9df\",\n      \"unicode_decimal\": 59871\n    },\n    {\n      \"icon_id\": \"23106468\",\n      \"name\": \"配置管理\",\n      \"font_class\": \"peizhiguanli\",\n      \"unicode\": \"e9e0\",\n      \"unicode_decimal\": 59872\n    },\n    {\n      \"icon_id\": \"22953587\",\n      \"name\": \"成功\",\n      \"font_class\": \"chenggong\",\n      \"unicode\": \"e9d0\",\n      \"unicode_decimal\": 59856\n    },\n    {\n      \"icon_id\": \"22953588\",\n      \"name\": \"筛选\",\n      \"font_class\": \"shaixuan\",\n      \"unicode\": \"e9d1\",\n      \"unicode_decimal\": 59857\n    },\n    {\n      \"icon_id\": \"22953586\",\n      \"name\": \"失败\",\n      \"font_class\": \"shibai\",\n      \"unicode\": \"e9cf\",\n      \"unicode_decimal\": 59855\n    },\n    {\n      \"icon_id\": \"22953571\",\n      \"name\": \"折叠\",\n      \"font_class\": \"zhedie\",\n      \"unicode\": \"e9c3\",\n      \"unicode_decimal\": 59843\n    },\n    {\n      \"icon_id\": \"22953572\",\n      \"name\": \"删除\",\n      \"font_class\": \"shanchu\",\n      \"unicode\": \"e9c4\",\n      \"unicode_decimal\": 59844\n    },\n    {\n      \"icon_id\": \"22953573\",\n      \"name\": \"添加\",\n      \"font_class\": \"tianjia\",\n      \"unicode\": \"e9c5\",\n      \"unicode_decimal\": 59845\n    },\n    {\n      \"icon_id\": \"22953574\",\n      \"name\": \"日期\",\n      \"font_class\": \"riqi\",\n      \"unicode\": \"e9c6\",\n      \"unicode_decimal\": 59846\n    },\n    {\n      \"icon_id\": \"22953575\",\n      \"name\": \"刷新\",\n      \"font_class\": \"shuaxin\",\n      \"unicode\": \"e9c7\",\n      \"unicode_decimal\": 59847\n    },\n    {\n      \"icon_id\": \"22953577\",\n      \"name\": \"搜索\",\n      \"font_class\": \"sousuo\",\n      \"unicode\": \"e9c8\",\n      \"unicode_decimal\": 59848\n    },\n    {\n      \"icon_id\": \"22953580\",\n      \"name\": \"leader\",\n      \"font_class\": \"leader\",\n      \"unicode\": \"e9c9\",\n      \"unicode_decimal\": 59849\n    },\n    {\n      \"icon_id\": \"22953581\",\n      \"name\": \"info\",\n      \"font_class\": \"info\",\n      \"unicode\": \"e9ca\",\n      \"unicode_decimal\": 59850\n    },\n    {\n      \"icon_id\": \"22953582\",\n      \"name\": \"复制\",\n      \"font_class\": \"fuzhi\",\n      \"unicode\": \"e9cb\",\n      \"unicode_decimal\": 59851\n    },\n    {\n      \"icon_id\": \"22953583\",\n      \"name\": \"编辑\",\n      \"font_class\": \"bianji\",\n      \"unicode\": \"e9cc\",\n      \"unicode_decimal\": 59852\n    },\n    {\n      \"icon_id\": \"22953584\",\n      \"name\": \"下载\",\n      \"font_class\": \"xiazai\",\n      \"unicode\": \"e9cd\",\n      \"unicode_decimal\": 59853\n    },\n    {\n      \"icon_id\": \"22953585\",\n      \"name\": \"全屏\",\n      \"font_class\": \"quanping\",\n      \"unicode\": \"e9ce\",\n      \"unicode_decimal\": 59854\n    }\n  ]\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/assets/style.less",
    "content": "ul {\n  padding: 0;\n}\n\n// reset antd style\n.ant-form-vertical .ant-form-item {\n  padding-bottom: 0;\n}\n.rc-notification-notice {\n  padding: 0;\n}\n.ant-card-compact {\n  .ant-card-head {\n    padding: 0 16px;\n    min-height: unset;\n  }\n  .ant-card-head-title {\n    padding: 10px 0;\n  }\n  .ant-card-extra {\n    padding: 10px 0;\n  }\n  .ant-card-body {\n    padding: 10px 16px;\n  }\n}\n.ant-table-scroll {\n  .ant-table-body { padding-bottom: 10px; }\n}\n.ant-table-scroll table .ant-table-fixed-columns-in-body {\n  visibility: unset;\n}\n.ant-table-thead > tr > th.textAlignCenter {\n  text-align: center;\n}\n\n// global style\nbody { background: #f0f2f5; }\n.mt10 { margin-top: 10px; }\n.mr10 { margin-right: 10px; }\n.mb10 { margin-bottom: 10px; }\n.ml10 { margin-left: 10px; }\n.textAlignLeft { text-align: left; }\n.textAlignCenter { text-align: center; }\n.textAlignRight { text-align: right; }\n.pointer { cursor: pointer; }\n.fc50 { color: #f50 }\n.success-btn {\n  background: #87d068;\n  color: #fff;\n  border: 0 none;\n  &:hover,&:active,&:focus {\n    background: #449d44;\n    color: #fff;\n  }\n}\n.warning-btn {\n  background: #f0ad4e;\n  color: #fff;\n  border: 0 none;\n  &:hover,&:active,&:focus {\n    background: #ec971f;\n    color: #fff;\n  }\n}\n.danger-btn {\n  background: #d9534f;\n  color: #fff;\n  border: 0 none;\n  &:hover,&:active,&:focus {\n    background: #c9302c;\n    color: #fff;\n  }\n}\n// Functions\n.single-page-wrap(@width) {\n  width: @width;\n  margin-left: auto;\n  margin-right: auto;\n  overflow: hidden;\n}\n.single-page-main(@height) {\n  height: @height;\n  margin-top: calc(~\"50vh - @{height} / 2\");\n}\n.danger-link {\n  color: #d9534f;\n  &:hover,&:active,&:focus {\n    color: #c9302c;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/config.tsx",
    "content": "export interface MenuChild {\n  name: string;\n  nameEn: string;\n  path: string;\n  icon: string;\n}\nexport interface Menu {\n  name: string;\n  nameEn: string;\n  type: 'group';\n  children: MenuChild[];\n}\n\nexport const prefixCls = 'd1';\n\nexport enum FormItemType {\n  input = 'input',\n  inputPassword = 'inputPassword',\n  inputNumber = 'inputNumber'\n}\n\nexport interface IFormItem {\n  key: string;\n  type: FormItemType;\n  attrs?: any;\n  rules?: any[];\n  invisible?: boolean;\n}\n\n\nexport const FormMap = [\n  {\n    key: 'password',\n    type: FormItemType.inputPassword,\n    label: '当前密码',\n    rules: [{\n      required: true,\n    }],\n    attrs: {\n      placeholder: '当前密码',\n    }\n  },\n  {\n    key: 'newPassword',\n    type: FormItemType.inputPassword,\n    label: '新密码',\n    rules: [{\n      required: true,\n      message: '密码设置不符合要求',\n      validator: (rule: any, value: string) => {\n        let flat_6_20 = (value && value.length > 5 && value.length < 20);\n        const reg = /^[a-zA-Z0-9\\_-]*$/;\n        if (flat_6_20 && reg.test(value)) {\n          return Promise.resolve();\n        } else {\n          return Promise.reject();\n        }\n      },\n    }],\n    attrs: {\n      placeholder: '6-20个字符，支持英文字母、数字、标点符号（除空格）',\n    }\n  },\n  {\n    key: 'confirm',\n    type: FormItemType.inputPassword,\n    label: '确认密码',\n    rules: [{\n      required: true,\n      message: '两次密码不统一',\n    },\n    ({ getFieldValue }) => ({\n      validator(_, value) {\n        if (!value || getFieldValue('newPassword') === value) {\n          return Promise.resolve();\n        }\n        return Promise.reject('两次密码不统一');\n      },\n    }),],\n    attrs: {\n      placeholder: '请再次输入密码',\n    }\n  },\n]"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/index.less",
    "content": "@header-text-color: rgba(0, 0, 0, 0.87);\n@primary-color: #1473ff;\n\n.cluster-admin,\n.system-admin {\n  display: inline-block;\n  color: @header-text-color;\n  cursor: pointer;\n  margin-right: 15px;\n  position: relative;\n  top: 1px;\n  height: 24px;\n  text-align: center;\n  div {\n    line-height: 24px;\n  }\n  .iconfont {\n    margin-right: 2px;\n  }\n}\n\n.admin-container {\n  display: inline-block;\n  cursor: pointer;\n  margin-right: 20px;\n  color: @header-text-color;\n  font-size: 14px;\n  .icon {\n    margin-right: 5px;\n    font-size: 20px;\n  }\n}\n\n.icon-tuichuquanju,\n.icon-quanju1 {\n  color: #fff;\n  margin-right: 15px;\n  font-size: 20px !important;\n}\n\n.knowsearch-icon {\n  margin: 9px 4px 0px 0px;\n  width: 170px;\n  height: 32px;\n  color: #333;\n}\n\n.select-icon {\n  display: inline-block;\n  transform: rotate(90deg);\n  margin-left: 5px;\n  position: relative;\n  top: 3px;\n  .iconfont {\n    font-size: 20px;\n  }\n}\n\n.admin-wrapper {\n  top: 30px !important;\n  .ant-dropdown-arrow {\n    top: 8px !important;\n  }\n  .admin-select {\n    width: 140px;\n    height: 80px;\n    background: #fff;\n    padding: 8px 0;\n    border-radius: 5px;\n    box-shadow: 0 -2px 4px 0 rgb(0 0 0 / 2%), 0 2px 6px 6px rgb(0 0 0 / 2%), 0 2px 6px 0 rgb(0 0 0 / 6%);\n    li {\n      height: 32px;\n      padding-left: 16px;\n      cursor: pointer;\n      .icon {\n        margin-right: 5px;\n      }\n      &:hover {\n        background: rgba(0, 0, 0, 0.04);\n      }\n    }\n    .active {\n      background: #f1f7ff !important;\n      color: #1473ff;\n    }\n  }\n}\n\n.user-trigger {\n  font-size: 14px;\n}\n\n.user-icon {\n  display: inline-block;\n  width: 26px;\n  height: 26px;\n  border-radius: 50%;\n  text-align: center;\n  background: @primary-color;\n  line-height: 50px;\n  top: 12px;\n  position: relative;\n  margin: 0 10px 0 8px;\n  span {\n    position: relative;\n    top: -12px;\n    &:hover {\n      color: @primary-color;\n    }\n  }\n  .icon.iconfont.icontouxiang {\n    color: #fff;\n    font-size: 20px;\n  }\n}\n\n.user-wrapper {\n  top: 33px !important;\n  width: 320px;\n  height: 433px;\n  z-index: 1000;\n  .ant-dropdown-arrow {\n    top: 8px !important;\n    right: 25px;\n  }\n  .user-container {\n    width: 100%;\n    height: 100%;\n    background: #fff;\n    border-radius: 5px;\n    box-shadow: 0 -2px 4px 0 rgb(0 0 0 / 2%), 0 2px 6px 6px rgb(0 0 0 / 2%), 0 2px 6px 0 rgb(0 0 0 / 6%);\n  }\n}\n\n.admin-container,\n.dropdown-content,\n.d1-layout-username {\n  font-family: PingFangSC-Regular;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/index.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport _ from \"lodash\";\nimport { prefixCls } from \"./config\";\nimport \"./style.less\";\nimport { Layout } from \"knowdesign\";\nimport { IProject } from \"./ProjectSelect\";\nimport HeaderConditionComponent from \"./HeaderConditionComponent\";\nimport { withRouter } from \"react-router-dom\";\nimport { isSuperApp } from \"lib/utils\";\n\ninterface Props {\n  children: React.ReactNode;\n  language?: string;\n  onLanguageChange?: (language: string) => void;\n  setCurrentProject?: any;\n  projectList?: IProject[];\n  projectLoding?: boolean;\n  currentProject?: IProject;\n  onMount?: () => void;\n  feConf: any;\n  logout: (params?: any) => any;\n  setLeftIndex?: (index: number) => void;\n  leftIndex?: number;\n  setHeaderClick?: (bool: boolean) => void;\n}\n\nconst { Header } = Layout;\nconst normalizeTenantProjectData = (data: any[], tenantIdent?: string, tenantId?: number, tenantName?: string): any => {\n  return _.map(data, (item) => {\n    if (item.children) {\n      return {\n        ...item,\n        tenantIdent: tenantIdent || item.ident,\n        tenantId: tenantId || item.id,\n        tenantName: tenantName || item.name,\n        children: normalizeTenantProjectData(item.children, tenantIdent || item.ident, tenantId || item.id, tenantName || item.name),\n      };\n    }\n    return {\n      ...item,\n      tenantIdent,\n      tenantId,\n      tenantName,\n    };\n  });\n};\nconst index = withRouter((props: any) => {\n  const cPrefixCls = `${prefixCls}-layout`;\n  const [feConf] = useState(props.feConf || {});\n\n  return (\n    <Layout className={cPrefixCls}>\n      <Header className={`${cPrefixCls}-header ${_.get(feConf, \"header.theme\")}`}>\n        <div\n          className={`${cPrefixCls}-header-left`}\n          onClick={() => {\n            isSuperApp() ? props.history.push(_.get(feConf, \"header.logohref\") || \"/\") : props.history.push('/cluster/logic');\n            props.setLeftIndex(0);\n          }}\n        >\n          <div className={`${cPrefixCls}-header-left-logo`}></div>\n        </div>\n        <div className={`${cPrefixCls}-header-right`}>\n          {_.get(feConf, \"header.rightEle\").map((item, index) => HeaderConditionComponent(item, index, props))}\n        </div>\n      </Header>\n      <div\n        style={{\n          overflow: \"hidden\",\n          position: \"relative\",\n        }}\n      >\n        <div className={`${cPrefixCls}-main`}>{props.children}</div>\n      </div>\n    </Layout>\n  );\n});\nexport default index;\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/interface.tsx",
    "content": "import React from 'react';\n\nexport interface MenuConfItem {\n  key?: string,\n  name?: string | React.ReactNode,\n  path?: string,\n  icon?: string,\n  type?: 'group',\n  component?: React.ReactNode,\n  children?: MenuConfItem[],\n  visible?: boolean,\n  rootVisible?: boolean,\n  networkopsVisible?: boolean,\n  to?: string,\n  divider?: boolean,\n  target?: string,\n  getQuery?: (query: any) => any,\n  permissionPoint?: string,\n  isAbsolutePath?: boolean,\n}\n\nexport interface TreeNode {\n  id: number,\n  pid: number,\n  ident: string,\n  name: string,\n  path: string,\n  type: number,\n  leaf: number,\n  cate?: string,\n  note?: string,\n  children?: TreeNode[],\n  icon_color: string,\n  icon_char: string,\n  selectable?: boolean,\n}\n\nexport interface ResponseDat {\n  list: any[],\n  total: number,\n}\n\nexport interface Response {\n  err: string,\n  dat: any | ResponseDat,\n}\n\nexport interface UserProfile {\n  id: number,\n  username: string,\n  dispname: string,\n  email: string,\n  phone: string,\n  im: string,\n  isroot: boolean,\n}\n\nexport interface Tenant {\n  id: number,\n  ident: string,\n  name: string,\n  note: string,\n}\n\nexport interface IRouterTab {\n  key: string,\n  label: string,\n  href: string,\n  show: boolean,\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/style.less",
    "content": "@import \"~antd/lib/style/themes/default.less\";\n\n@layout-prefix-cls: d1-layout;\n@layout-content-padding: @layout-header-padding;\n@layout-breadcrumb-height: 40px;\n@layout-footer-height: 10px;\n@layout-border-color: #efefef;\n@dark-gray: #2c333c;\n@layout-header-height: 48px;\n@layout-header-bg: #1f3252; // #282b33;\n@layout-header-bg-light: #ffffff;\n@layout-header-color: rgba(0, 0, 0, 0.87);\n@layout-left-menu-color: #303a51;\n@primary-color: #1473ff;\n@header-text-color: rgba(0, 0, 0, 0.87);\n@layout-background-color: #f4f9ff;\n\nbody {\n  height: 100%;\n  overflow: hidden;\n}\n\n.@{layout-prefix-cls} {\n  > .@{layout-prefix-cls}-container {\n    width: 100%;\n  }\n\n  .@{layout-prefix-cls}-sider-nav {\n    position: absolute;\n    z-index: 1000;\n    height: calc(~\"100vh - @{layout-header-height}\");\n    overflow: hidden;\n    // background: @layout-background-color;\n    background-image: linear-gradient(180deg, #f5f7fa 2%, #f5f7fa 86%);\n\n    .ant-menu {\n      font-size: 12px;\n    }\n\n    .@{layout-prefix-cls}-sider-nav-systemName {\n      height: 50px;\n      line-height: 50px;\n      font-weight: 800;\n      border-bottom: 1px solid #dbe0e4;\n    }\n\n    .@{layout-prefix-cls}-sider-nav-bottom {\n      height: 32px;\n      line-height: 32px;\n      text-align: center;\n      opacity: 0.6;\n      background: #f5f7fa;\n      cursor: pointer;\n      position: relative;\n      bottom: 0;\n      &-divider {\n        width: 80%;\n        height: 1px;\n        margin: 0 auto;\n        opacity: 0.2;\n        background-image: linear-gradient(180deg, #74788d 0%, #f4f4f8 100%);\n        border-radius: 1px;\n      }\n      &:hover {\n        opacity: 1;\n      }\n    }\n\n    .@{layout-prefix-cls}-menu {\n      font-size: 14px;\n      padding-top: 10px;\n      height: calc(~\"100vh - 82px\");\n      overflow-x: hidden;\n      overflow-y: auto;\n\n      &::-webkit-scrollbar {\n        width: 2px;\n        height: 2px;\n      }\n\n      &::-webkit-scrollbar-thumb {\n        border-radius: 8px;\n        box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);\n        background: #bbb;\n      }\n\n      &::-webkit-scrollbar-track {\n        background: #fff;\n      }\n    }\n\n    .sider-menu-icon {\n      width: 1.2em;\n      height: 1.2em;\n      vertical-align: -0.15em;\n      fill: currentColor;\n      overflow: hidden;\n      margin-right: 0.5em;\n\n      &:before {\n        color: @primary-color;\n      }\n    }\n\n    .ant-menu-inline {\n      border: 0 none;\n\n      .ant-menu-item-selected::after {\n        opacity: 0;\n      }\n    }\n\n    .ant-menu-inline.ant-menu-sub {\n      box-shadow: none;\n      position: relative;\n      background-color: #fff;\n\n      &:before {\n        content: \"\";\n        z-index: 10;\n        position: absolute;\n        top: 0;\n        bottom: 0;\n        height: 100%;\n        left: 30px;\n        width: 2px;\n        background-color: #ccc;\n      }\n    }\n\n    .ant-menu-item-active > a,\n    .ant-menu-item-active > a:hover {\n      fill: @primary-color;\n    }\n\n    .ant-menu-item-active {\n      &:before {\n        width: 188px;\n        height: 30px;\n        position: absolute;\n        top: 0;\n        bottom: 0;\n        content: \"\";\n        transform: scaleY(1);\n        opacity: 1;\n        transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);\n      }\n    }\n\n    .ant-menu-item-selected {\n      &:before {\n        fill: @primary-color;\n        position: absolute;\n        top: 0;\n        bottom: 0;\n        left: 5px;\n        content: \"\";\n        transform: scaleY(1);\n        opacity: 1;\n        transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);\n      }\n    }\n\n    .ant-menu-submenu-selected {\n      color: @primary-color;\n      fill: @primary-color;\n\n      .anticon {\n        color: @primary-color;\n        fill: @primary-color;\n      }\n\n      .ant-menu-submenu-title {\n        &:before {\n          fill: @primary-color;\n          position: absolute;\n          top: 0;\n          left: 5px;\n          bottom: 0;\n          content: \"\";\n          transform: scaleY(1);\n          opacity: 1;\n          transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);\n        }\n      }\n\n      .ant-menu-item-selected:before {\n        fill: @primary-color;\n        border: 0 none;\n        content: \"\";\n        position: absolute;\n        top: 0;\n        left: 30px;\n        bottom: 0;\n        z-index: 10;\n        height: 100%;\n        width: 2px;\n        background-color: @primary-color;\n      }\n    }\n\n    .ant-layout-sider-trigger {\n      background: @dark-gray;\n    }\n\n    .ant-menu-inline-collapsed {\n      width: auto;\n\n      .ant-menu-submenu > .ant-menu-submenu-title {\n        padding: 0 20px !important;\n      }\n\n      .ant-menu-item {\n        padding: 0 20px !important;\n      }\n\n      .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-item {\n        padding: 0 20px !important;\n      }\n\n      .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-submenu > .ant-menu-submenu-title {\n        padding: 0 20px !important;\n      }\n\n      .ant-menu-item-group-title {\n        text-indent: 20px;\n        fill: @primary-color;\n      }\n\n      .menu-name {\n        opacity: 0;\n      }\n    }\n\n    .ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title {\n      height: 30px !important;\n      line-height: 30px !important;\n    }\n\n    .ant-menu-item {\n      height: 30px !important;\n      line-height: 30px !important;\n    }\n\n    .ant-menu-vertical > .ant-menu-submenu > .ant-menu-submenu-title {\n      height: 30px !important;\n      line-height: 30px !important;\n    }\n\n    .ant-menu-vertical > .ant-menu-submenu > .ant-menu-submenu-title:hover {\n      fill: @primary-color;\n    }\n\n    .ant-menu-inline .ant-menu-item,\n    .ant-menu-inline .ant-menu-submenu-title {\n      width: auto !important;\n    }\n\n    .ant-menu-item-selected > a,\n    .ant-menu-item-selected > a:hover {\n      font-weight: 600;\n      fill: @primary-color;\n    }\n  }\n\n  .ant-menu-submenu-active:hover {\n    fill: @primary-color;\n  }\n\n  .@{layout-prefix-cls}-sider-nav-collapsed {\n    .ant-menu-inline .ant-menu-submenu-title {\n      padding-right: 0;\n    }\n\n    .menu-name {\n      display: none;\n    }\n\n    .ant-menu-inline.ant-menu-sub {\n      &:before {\n        fill: @primary-color;\n        position: absolute;\n        z-index: 1;\n        top: 0;\n        left: 30px;\n        bottom: 0;\n        border-left: 1px solid #e3edff;\n        content: \"\";\n      }\n    }\n  }\n\n  .@{layout-prefix-cls}-header {\n    padding: 0;\n    height: @layout-header-height;\n    line-height: @layout-header-height;\n    background: @layout-header-bg;\n    box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.01), 0 3px 6px 3px rgba(0, 0, 0, 0.01), 0 2px 6px 0 rgba(0, 0, 0, 0.03);\n    position: relative;\n    z-index: 11;\n\n    &.light {\n      background: @layout-header-bg-light;\n    }\n\n    > .@{layout-prefix-cls}-header-left {\n      float: left;\n      cursor: pointer;\n      > .@{layout-prefix-cls}-header-left-logo {\n        height: 28px;\n        background: url(../CommonPages/Login/img/logo.png) no-repeat;\n        width: 200px;\n        background-size: contain;\n        background-position: center;\n        display: inline-block;\n        vertical-align: middle;\n      }\n\n      > .@{layout-prefix-cls}-header-menu {\n        width: 50px;\n        display: inline-block;\n        color: #fff;\n        text-align: center;\n        font-size: 20px;\n        cursor: pointer;\n      }\n\n      > .@{layout-prefix-cls}-header-menu-active {\n        background: #3e3f46;\n\n        &.light {\n          background: #2468cc;\n        }\n      }\n\n      > .@{layout-prefix-cls}-logo {\n        font-family: PingFangSC-Medium;\n        font-size: 16px;\n        color: #fff;\n        letter-spacing: 0;\n        margin-left: 20px;\n\n        img {\n          margin-right: 8px;\n          margin-top: -3px;\n        }\n      }\n    }\n\n    > .@{layout-prefix-cls}-header-right {\n      float: right;\n      color: @header-text-color;\n      .icon {\n        color: @header-text-color;\n      }\n\n      .ant-select {\n        color: @layout-header-color;\n        width: 240px;\n        background: rgba(255, 255, 255, 0.1);\n        border-radius: 4px;\n        text-align: left;\n\n        .ant-select-selector {\n          opacity: 0.5;\n          font-family: PingFangSC-Regular;\n          font-size: 12px;\n          color: #ffffff;\n          line-height: 20px;\n          background: none;\n          border: none;\n\n          .ant-select-selection-placeholder {\n            color: @layout-header-color;\n          }\n        }\n      }\n\n      .ant-select-selection {\n        background-color: #464c59;\n        border: none;\n      }\n\n      .ant-select-selection__clear {\n        color: inherit;\n        background: none;\n      }\n\n      .ant-select-arrow {\n        color: @layout-header-color;\n      }\n\n      > .@{layout-prefix-cls}-username {\n        color: @layout-header-color;\n        display: inline-block;\n        padding-right: 20px;\n        cursor: pointer;\n\n        &:hover {\n          background: rgba(0, 0, 0, 0.025);\n        }\n\n        img {\n          width: 30px;\n          vertical-align: middle;\n          margin-right: 6px;\n        }\n      }\n\n      > .@{layout-prefix-cls}-doc {\n        color: @layout-header-color;\n        display: inline-block;\n        padding: 0 20px;\n        cursor: pointer;\n\n        &:hover {\n          background: rgba(0, 0, 0, 0.025);\n        }\n\n        img {\n          width: 30px;\n          vertical-align: middle;\n          margin-right: 8px;\n        }\n      }\n\n      > .@{layout-prefix-cls}-header-right-links {\n        font-size: 14px;\n        display: inline-block;\n        padding: 0 20px;\n\n        a {\n          margin: 0 10px;\n          color: @layout-header-color;\n        }\n      }\n\n      > .@{layout-prefix-cls}-header-right-icons {\n        display: inline-block;\n        padding: 0 20px;\n\n        a {\n          margin: 0 10px;\n          color: @layout-header-color;\n        }\n\n        img {\n          width: 20px;\n        }\n      }\n\n      .@{layout-prefix-cls}-header-right-divider {\n        height: 16px;\n        background: @header-text-color;\n        margin: 0 15px;\n      }\n    }\n\n    // > .@{layout-prefix-cls}-menu {\n    //   font-size: 13px;\n    //   font-weight: 500;\n    //   height: @layout-menu-height;\n    //   line-height: @layout-menu-lineHeight;\n    //   display: inline-block;\n    // }\n  }\n\n  .@{layout-prefix-cls}-subSystems {\n    display: inline-block;\n    font-weight: 900;\n\n    a {\n      color: #fff;\n      padding: 0 20px;\n      display: inline-block;\n      height: 60px;\n    }\n\n    a.active {\n      background: @primary-7;\n    }\n  }\n\n  .@{layout-prefix-cls}-subSystems-icon {\n    height: 20px;\n    position: relative;\n    top: -2px;\n    margin-right: 7px;\n  }\n\n  > .@{layout-prefix-cls}-breadcrumb-container {\n    height: @layout-breadcrumb-height;\n    line-height: @layout-breadcrumb-height;\n\n    > .@{layout-prefix-cls}-breadcrumb {\n      float: left;\n    }\n\n    > .@{layout-prefix-cls}-breadcrumb-right {\n      float: right;\n    }\n\n    .ant-breadcrumb {\n      line-height: unset;\n    }\n  }\n\n  .ant-layout.ant-layout-has-sider > .ant-layout,\n  .ant-layout.ant-layout-has-sider > .ant-layout-content {\n    height: 100%;\n  }\n\n  .@{layout-prefix-cls}-main {\n    border: 0 none;\n    height: calc(~\"100vh - @{layout-header-height}\");\n    overflow-y: auto;\n    // background: @layout-background-color;\n    background-image: linear-gradient(180deg, #f5f7fa 2%, #f5f7fa 86%);\n  }\n\n  .ant-layout {\n    .@{layout-prefix-cls}-has-sider {\n      .@{layout-prefix-cls}-sider-nstree {\n        display: block;\n      }\n    }\n\n    > .@{layout-prefix-cls}-sider-nstree {\n      display: none;\n      background: #fff;\n\n      .@{layout-prefix-cls}-nsTree {\n        height: 100%;\n\n        .ant-spin-nested-loading {\n          height: calc(~\"100% - 52px\");\n          overflow: auto;\n\n          .ant-spin-container {\n            height: 100%;\n          }\n        }\n      }\n\n      .@{layout-prefix-cls}-nsTree-header {\n        padding: 10px;\n      }\n\n      .@{layout-prefix-cls}-nsTree-content-container {\n        height: 100%;\n      }\n\n      .@{layout-prefix-cls}-nsTree-content {\n        padding: 5px 10px;\n      }\n    }\n\n    > .@{layout-prefix-cls}-content {\n      > .@{layout-prefix-cls}-main {\n        border: 0 none;\n        margin-top: 46px;\n        padding: 20px;\n        height: calc(~\"100vh - @{layout-header-height} - 50px\");\n        overflow-y: visible;\n        min-width: calc(1440px - 190px);\n      }\n\n      > .@{layout-prefix-cls}-main-noBg {\n        background: none;\n        padding: 0;\n      }\n    }\n\n    .@{layout-prefix-cls}-sider-nstree-arrow {\n      position: absolute;\n      top: 50%;\n      left: -4px;\n      width: 15px;\n      height: 40px;\n      background: #f0f2f5;\n      border-top: 3px solid #f0f2f5;\n      border-bottom: 3px solid #f0f2f5;\n      border-left: 7px solid #f0f2f5;\n      border-right: 7px solid #fff;\n      cursor: pointer;\n\n      img {\n        height: 15px;\n        position: relative;\n        top: 7px;\n        left: 3px;\n      }\n    }\n\n    .@{layout-prefix-cls}-sider-nstree-arrow-right {\n      img {\n        transform: rotateY(180deg);\n      }\n    }\n  }\n\n  .@{layout-prefix-cls}-has-sider {\n    > .@{layout-prefix-cls}-sider-nstree {\n      margin-top: 10px;\n      margin-left: 10px;\n      margin-bottom: 10px;\n      border-radius: 3px;\n      height: calc(~\"100vh - @{layout-header-height} - 20px\");\n    }\n\n    > .@{layout-prefix-cls}-content {\n      > .@{layout-prefix-cls}-main {\n        border-radius: 3px;\n      }\n    }\n  }\n\n  > .@{layout-prefix-cls}-footer {\n    text-align: center;\n    margin-top: 10px;\n    margin-bottom: 10px;\n  }\n}\n\n.ecmc-errNotify-progress {\n  .ant-progress-inner {\n    vertical-align: bottom;\n  }\n\n  .ant-progress-bg {\n    border-radius: 0 !important;\n  }\n}\n\n.@{layout-prefix-cls}-menus {\n  overflow: hidden;\n\n  .@{layout-prefix-cls}-menus-allBtn {\n    position: relative;\n    height: 40px;\n    line-height: 40px;\n    padding-left: 20px;\n    cursor: pointer;\n    background: #fff;\n    border-bottom: 1px solid #dbe0e4;\n\n    &:hover {\n      background: #f5f7fa;\n    }\n  }\n\n  .@{layout-prefix-cls}-menus-allBtn-left {\n    font-size: 14px;\n    font-weight: 500;\n    margin-right: 10px;\n  }\n\n  .@{layout-prefix-cls}-menus-allBtn-right {\n    position: absolute;\n    right: 20px;\n    top: 13px;\n  }\n\n  .@{layout-prefix-cls}-menus-content {\n    height: calc(~\"100vh - 60px\") !important;\n    padding: 40px;\n    position: relative;\n    // overflow: hidden;\n  }\n\n  .@{layout-prefix-cls}-menus-content-search {\n    border-bottom: 1px solid #dbe0e4;\n    width: 95%;\n    padding-left: 10px;\n  }\n\n  .@{layout-prefix-cls}-menus-content-search-icon {\n    color: #666666;\n    font-size: 14px;\n  }\n\n  .@{layout-prefix-cls}-menus-content-search-icons {\n    color: #3370ff;\n    font-size: 14px;\n  }\n\n  .@{layout-prefix-cls}-menus-content-search-input {\n    width: 95%;\n    border: 0 none;\n    background: none;\n\n    &:focus {\n      box-shadow: none;\n    }\n  }\n\n  .@{layout-prefix-cls}-menus-content-menus-history {\n    margin-top: 40px;\n  }\n\n  .@{layout-prefix-cls}-menus-content-menus {\n    margin-top: 40px;\n    display: flex;\n    flex-direction: column;\n    flex-wrap: wrap;\n    height: 400px;\n  }\n\n  .@{layout-prefix-cls}-menus-content-menu-group {\n    width: 250px;\n    margin-bottom: 50px;\n\n    .@{layout-prefix-cls}-menus-content-menu-group-title {\n      font-weight: 800;\n      margin-bottom: 20px;\n      color: #333;\n    }\n\n    .@{layout-prefix-cls}-menus-content-menu {\n      line-height: 30px;\n      margin-right: 30px;\n      width: 270px !important;\n      position: relative;\n\n      a {\n        color: #333;\n      }\n\n      &:hover {\n        background: #edf0f2;\n        border-bottom: 1px solid @primary-color;\n\n        a {\n          color: @primary-color;\n        }\n\n        .@{layout-prefix-cls}-menus-content-menu-star {\n          display: block;\n          cursor: pointer;\n        }\n      }\n    }\n\n    .@{layout-prefix-cls}-menus-content-starMenu {\n      .@{layout-prefix-cls}-menus-content-menu-star {\n        display: block;\n      }\n    }\n\n    .@{layout-prefix-cls}-menus-content-menu-star {\n      position: absolute;\n      right: 10px;\n      top: 7px;\n      color: @primary-color;\n      display: none;\n    }\n  }\n\n  .@{layout-prefix-cls}-menus-content-menu-group-history {\n    width: 100%;\n    margin-right: 20px;\n    margin-bottom: 50px;\n\n    .@{layout-prefix-cls}-menus-content-menu {\n      display: inline-block;\n      width: 270px;\n    }\n  }\n\n  .@{layout-prefix-cls}-menus-close {\n    position: absolute;\n    top: 40px;\n    right: 40px;\n    font-size: 18px;\n    cursor: pointer;\n  }\n\n  .iconwrap {\n    vertical-align: text-top;\n    margin-right: 10px;\n  }\n\n  .ant-layout-sider {\n    box-shadow: 4px 0 6px 0 rgba(0, 0, 0, 0.06);\n  }\n\n  .ant-menu-item > a {\n    display: inline-block;\n  }\n}\n\n.@{layout-prefix-cls}-menus-sider-menus {\n  height: calc(~\"100vh - 100px\");\n  border-right: 0 none;\n  overflow-y: auto;\n  user-select: none;\n}\n\n.@{layout-prefix-cls}-menus-sider-menus-item {\n  height: 40px;\n  line-height: 40px;\n  position: relative;\n  z-index: 10000;\n  list-style: none;\n  padding-left: 20px;\n  padding-right: 40px;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  display: block;\n  white-space: nowrap;\n\n  a {\n    color: #333;\n  }\n\n  &:hover {\n    background: #f5f7fa;\n\n    .@{layout-prefix-cls}-menus-icon {\n      fill: @primary-color;\n    }\n\n    .@{layout-prefix-cls}-menus-sider-menus-item-link {\n      color: @primary-color;\n    }\n\n    .@{layout-prefix-cls}-menus-sider-menus-item-right {\n      position: absolute;\n      right: 7px;\n      display: inline;\n    }\n  }\n}\n\n.@{layout-prefix-cls}-menus-sider-menus-item-right {\n  position: absolute;\n  right: 7px;\n  display: none;\n}\n\n.@{layout-prefix-cls}-menus-icon,\n.@{layout-prefix-cls}-left-menus-icon {\n  width: 20px;\n  height: 20px;\n  vertical-align: text-top;\n  margin-right: 6px;\n  fill: @layout-header-color;\n\n  & .small {\n    width: 12px;\n    height: 12px;\n  }\n}\n\n.@{layout-prefix-cls}-left-menus-icon {\n  fill: @layout-left-menu-color;\n}\n\n.@{layout-prefix-cls}-header-menus-icon {\n  width: 14px;\n  height: 14px;\n  vertical-align: text-top;\n  margin-right: 8px;\n  fill: #adb0b8;\n}\n\n.ant-tooltip-placement-right {\n  .@{layout-prefix-cls}-menus-icon {\n    fill: #fff;\n  }\n}\n\n.ant-badge-dot {\n  box-shadow: 0 0 0 1px #464c59 !important;\n}\n\n.text {\n  display: inline-block;\n  position: relative !important;\n}\n\n.badge {\n  position: absolute !important;\n  transform: scale(0.5, 0.5);\n  right: -7px;\n  top: 8px;\n}\n\n.icontuozhuai {\n  width: 10px;\n  height: 10px;\n}\n\n.ant-badge-count {\n  box-shadow: 0 0 0 1px #464c59 !important;\n}\n\n.valueColor {\n  color: #f50;\n}\n\n.iconfont:hover {\n  color: white;\n}\n\n.NsTreeModal-button {\n  margin-left: 20px;\n}\n\n.user-center-drawer {\n  margin-top: 50px;\n}\n\n.ant-layout {\n  display: flex;\n  flex: auto;\n  flex-direction: column;\n  min-height: 0;\n  background: #f0f2f5;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/Layout/utils.tsx",
    "content": "import React from \"react\";\nimport _ from \"lodash\";\nimport { MenuConfItem, TreeNode } from \"./interface\";\n\nexport function isAbsolutePath(url: string) {\n  return /^https?:\\/\\//.test(url);\n}\n\nexport function hasRealChildren(children: { visible?: boolean }[]) {\n  if (_.isArray(children)) {\n    return !_.every(children, (item) => item.visible === false);\n  }\n  return false;\n}\n\nexport function normalizeMenuConf(children: MenuConfItem[], parentNav?: MenuConfItem) {\n  const navs: MenuConfItem[] = [];\n\n  _.each(children, (nav) => {\n    if (nav.visible === undefined || nav.visible === true) {\n      const navCopy = _.cloneDeep(nav);\n\n      if (isAbsolutePath(nav.path) || _.indexOf(nav.path, \"/\") === 0) {\n        navCopy.to = nav.path;\n      } else if (parentNav) {\n        if (parentNav.path) {\n          const parentPath = parentNav.to ? parentNav.to : `/${parentNav.path}`;\n          if (nav.path) {\n            navCopy.to = `${parentPath}/${nav.path}`;\n          } else {\n            navCopy.to = parentPath;\n          }\n        } else if (nav.path) {\n          navCopy.to = `/${nav.path}`;\n        }\n      } else if (nav.path) {\n        navCopy.to = `/${nav.path}`;\n      }\n\n      if (_.isArray(nav.children) && nav.children.length && hasRealChildren(nav.children)) {\n        navCopy.children = normalizeMenuConf(nav.children, navCopy);\n      } else {\n        delete navCopy.children;\n      }\n\n      navs.push(navCopy);\n    }\n  });\n  return navs;\n}\n\nexport function findNode(nodes: TreeNode[], node: TreeNode) {\n  let findedNode: TreeNode | undefined;\n  function findNodeReal(nodes: TreeNode[], node: TreeNode) {\n    for (let i = 0; i < nodes.length; i++) {\n      const item = nodes[i];\n      if (item.id === node.pid) {\n        findedNode = item;\n        break;\n      } else if (Array.isArray(item.children)) {\n        findNodeReal(item.children, node);\n      }\n    }\n  }\n  findNodeReal(nodes, node);\n  return findedNode;\n}\n\nexport function normalizeTreeData(data: TreeNode[]) {\n  const treeData: TreeNode[] = [];\n  let tag = 0;\n\n  function fn(_cache?: TreeNode[]) {\n    const cache: TreeNode[] = [];\n    _.each(data, (node) => {\n      node = _.cloneDeep(node);\n      if (node.pid === 0) {\n        if (tag === 0) {\n          treeData.splice(_.sortedIndexBy(treeData, node, \"name\"), 0, node);\n        }\n      } else {\n        const findedNode = findNode(treeData, node); // find parent node\n        if (!findedNode) {\n          cache.push(node);\n          return;\n        }\n        if (_.isArray(findedNode.children)) {\n          if (!_.find(findedNode.children, { id: node.id })) {\n            findedNode.children.splice(_.sortedIndexBy(findedNode.children, node, \"name\"), 0, node);\n          }\n        } else {\n          findedNode.children = [node];\n        }\n      }\n    });\n    tag += 1;\n    if (cache.length && !_.isEqual(_cache, cache)) {\n      fn(cache);\n    }\n  }\n  fn();\n  return treeData;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/DrawerForm/README.md",
    "content": "### DrawerForm\n\nDrawerForm 组合了Drawer和XForm 抽屉式的表单 内置了相关提交重置的方法\n\n> 使用默认的submit或者调用form.submit()提交数据，需要传递onFinish方法\n\n| 参数 | 说明 | 类型 | 默认值 |\n| --- | --- | --- | --- |\n| trigger | 用于触发 Modal 打开的 dom，一般是 button | `ReactNode` | - |\n| visible | 是否打开 | `boolean` | - |\n| onVisibleChange | visible 改变时触发 | `(visible:boolean)=>void` | - |\n| drawerProps | Drawer 的 props，使用方式与 [antd](https://ant.design/components/drawer-cn/) 相同。注意：不支持 'visible'，请使用全局的 visible, 自定义footer, 请使用submitter进行配置| [props](https://ant.design/components/drawer-cn/#API) | - |\n| title | 抽屉的标题 | `ReactNode` | - |\n| width | 抽屉的宽度 | `Number` | `size['small']` |\n| size | 抽屉的尺寸 包含 `small (595px)\\| middle (728px) \\| large (1080px)` | `String` | `small` |\n| onFinish | 使用默认的submit或者调用form.submit()提交数据校验通过后触发，需要如果返回一个 true 才会关掉抽屉, | `async (values)=>boolean` | - |\n| submitter | footer操作按钮相关配置, 设为false时不显示操作区域 | `Submitter \\| false` | - |\n| submitterPosition | footer操作按钮的位置, 支持居左和居右 | string | right |\n| XFormProps | XForm的属性|  |  |\n\n\n### Submitter\n\n底部操作区域配置\n| 参数 | 说明 | 类型 | 默认值 |\n| --- | --- | --- | --- |\n| buttonConfig | 提交重置的按钮文字 | `{submitText, resetText}` | submitText: '确定' resetText: '取消'   |\n| submitButtonProps | 提交按钮的 props，preventDefault为true为将不执行默认的form.submit  | `preventDefault` && [ButtonProps](https://ant.design/components/button-cn/) | - |\n| resetButtonProps | 重置按钮的 props，preventDefault为true为将不执行默认的form.reset方法 | `preventDefault` &&  [ButtonProps](https://ant.design/components/button-cn/) | - |\n| render | 自定义操作的渲染 | `false`\\|`(props: { form, submit, reset }, dom:JSX[])=>ReactNode[]`   | - |\n\n> resetButtonProps 默认会关闭modal或drawer, 定义了onClick时会覆盖上述行为\n\n> render 第一个参数props包含form实例、 form的submit和reset方法， 第二个参数是默认的 dom 数组，第一个是重置按钮，第二个是提交按钮。"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/DrawerForm/index.tsx",
    "content": "import React, { useEffect, useState } from 'react';\nimport type { DrawerProps, FormInstance } from 'antd';\nimport { Drawer } from 'antd';\nimport useMergedState from 'rc-util/lib/hooks/useMergedState';\nimport { XForm, renderFormContent, IXFormProps } from '../XForm';\nimport { SubmitterProps } from '../Submitter';\n\ninterface IDrawerProps {\n  /**\n   * 接受返回一个boolean，返回 true 会关掉这个抽屉\n   * @name 表单结束后调用\n   */\n  onFinish?: (formData) => Promise<boolean | void>;\n\n  /** @name 用于触发抽屉打开的 dom */\n  trigger?: JSX.Element;\n\n  /** @name 受控的打开关闭 */\n  visible?: DrawerProps['visible'];\n\n  /** @name 打开关闭的事件 */\n  onVisibleChange?: (visible: boolean) => void;\n\n  /** @name 抽屉的标题 */\n  title?: DrawerProps['title'];\n\n  /** @name 抽屉的宽度 */\n  width?: DrawerProps['width'];\n\n  /** @name 抽屉的预设的几种size */\n  size?: 'small' | 'middle' | 'large';\n\n  /** @name 底部操作区域 */\n  submitter?: SubmitterProps<{ form?: FormInstance<any> }> | false;\n\n  /** @name 底部操作按钮的位置 */\n  submitterPosition?: 'left' | 'right';\n\n  /**\n   * 不支持 'visible'，请使用全局的 visible\n   *\n   * @name 抽屉的属性\n   */\n  drawerProps?: Omit<DrawerProps, 'visible' | 'getContainer' | 'footer' | 'footerStyle'>;\n\n  /**\n   *\n   * @name XForm 表单的配置\n   */\n  XFormProps: IXFormProps;\n}\n\nconst DrawerForm = ({ trigger, title, width, size = 'middle', drawerProps, XFormProps, onFinish, onVisibleChange, ...rest }: IDrawerProps) => {\n  const sizeMap = {\n    small: 595,\n    middle: 728\n  }\n  const [visible, setVisible] = useMergedState<boolean>(!!rest.visible,  {\n    value: rest.visible,  \n    onChange: onVisibleChange,\n  });  \n  useEffect(() => {\n    if (visible && rest.visible) {\n      onVisibleChange?.(true);\n    }\n  }, [visible]);\n\n  const renderFormDom = () => {\n    return (\n      <XForm\n        formData={XFormProps.formData}\n        formMap={XFormProps.formMap}\n        form={XFormProps.form}\n        submitter={\n          rest.submitter === false\n            ? false\n            : {\n                ...rest.submitter,\n                buttonConfig: {\n                  submitText: '确认',\n                  resetText: '取消',\n                  ...rest.submitter?.buttonConfig,\n                },\n                resetButtonProps: {\n                  onClick: (e: any) => {\n                    setVisible(false);\n                    drawerProps?.onClose?.(e);\n                  },\n                  ...rest.submitter?.resetButtonProps,\n                },\n              }\n        }\n        contentRender={(submitter) => {\n          return (\n            <Drawer\n              title={title}\n              width={width || sizeMap[size]}\n              {...drawerProps}\n              getContainer={false}\n              visible={visible}\n              onClose={(e) => {\n                setVisible(false);\n                XFormProps.form?.resetFields();\n                drawerProps?.onClose?.(e);\n              }}\n              footer={\n                !!submitter && (\n                  <div\n                    style={{\n                      display: 'flex',\n                      justifyContent: rest.submitterPosition === 'left' ? 'flex-start' : 'flex-end',\n                    }}\n                  >\n                    {submitter}\n                  </div>\n                )\n              }\n            >\n              {renderFormContent({ ...XFormProps })}\n            </Drawer>\n          );\n        }}\n        onFinish={async (values) => {\n          if (!onFinish) {\n            return;\n          }\n          const success = await onFinish(values);\n          if (success) {\n            setVisible(false);\n            XFormProps.form?.resetFields();\n          }\n        }}\n      ></XForm>\n    );\n  };\n  return (\n    <>\n      {renderFormDom()}\n      {trigger &&\n        React.cloneElement(trigger, {\n          ...trigger.props,\n          onClick: (e: any) => {\n            setVisible(!visible);\n            trigger.props?.onClick?.(e);\n          },\n        })}\n    </>\n  );\n};\n\nexport default DrawerForm;\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/ModalForm/README.md",
    "content": "### ModalForm\n\nModalForm 组合了 Modal和XForm Modal式的表单 默认内置了提交和重置的方法\n\n> 使用默认的submit或者调用form.submit()提交数据，需要传递onFinish方法\n\n| 参数 | 说明 | 类型 | 默认值 |\n| --- | --- | --- | --- |\n| trigger | 用于触发 Modal 打开的 dom，一般是 button | `ReactNode` | - |\n| visible | Modal是否打开 | `boolean` | - |\n| onVisibleChange | visible 改变时触发 | `(visible:boolean)=>void` | - |\n| XFormProps | XForm的相关配置| XFormProps | - |\n| modalProps | Modal 的 props，使用方式与 [antd](https://ant.design/components/modal-cn/) 相同。注意：不支持 'visible'，请使用全局的 visible, 自定义footer, 请使用submitter进行配置 | [props](https://ant.design/components/modal-cn/#API) | - |\n| title | 弹框的标题 | `ReactNode` | - |\n| width | 弹框的宽度 | `Number` | 500 |\n| onFinish | 使用默认的submit或者调用form.submit()提交数据校验通过后触发，需要如果返回一个 true 才会关掉弹窗 | `async (values)=>boolean` | - |\n| submitter | footer操作按钮相关配置, 设为false | SubmitterProps | false | - |\n| submitterPosition | footer操作按钮的位置, 支持居左和居右 | string | right |\n\n#### SubmitterProps\n\n底部操作区域配置\n| 参数 | 说明 | 类型 | 默认值 |\n| --- | --- | --- | --- |\n| buttonConfig | 提交重置的按钮文字 | `{submitText, resetText}` | submitText: '确定' resetText: '取消'   |\n| submitButtonProps | 提交按钮的 props，preventDefault为true为将不执行默认的form.submit  | `preventDefault` && [ButtonProps](https://ant.design/components/button-cn/) | - |\n| resetButtonProps | 重置按钮的 props，preventDefault为true为将不执行默认的form.reset方法 | `preventDefault` &&  [ButtonProps](https://ant.design/components/button-cn/) | - |\n| render | 自定义操作的渲染 | `false`\\|`(props: { form, submit, reset }, dom:JSX[])=>ReactNode[]`   | - |\n\n> resetButtonProps 默认会关闭modal或drawer, 定义了onClick时会覆盖上述行为\n\n> render 第一个参数props包含form实例、 form的submit和reset方法， 第二个参数是默认的 dom 数组，第一个是重置按钮，第二个是提交按钮。"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/ModalForm/index.tsx",
    "content": "import React, { useEffect } from 'react';\nimport type { ModalProps, FormInstance } from 'antd';\nimport { Modal } from 'antd';\nimport useMergedState from 'rc-util/lib/hooks/useMergedState';\nimport { XForm, renderFormContent, IXFormProps } from '../XForm';\nimport { SubmitterProps } from '../Submitter';\n\ninterface IModalProps {\n  /**\n   * 接受返回一个boolean，返回 true 会关掉这个Modal\n   * @name 表单结束后调用\n   */\n  onFinish?: (formData) => Promise<boolean | void>;\n\n  /** @name 用于触发Modal打开的 dom */\n  trigger?: JSX.Element;\n\n  /** @name 受控的打开关闭 */\n  visible?: ModalProps['visible'];\n\n  /** @name 打开关闭的事件 */\n  onVisibleChange?: (visible: boolean) => void;\n\n  /** @name Modal的标题 */\n  title?: ModalProps['title'];\n\n  /** @name Modal的宽度 */\n  width?: ModalProps['width'];\n\n  /** @name 底部操作区域 */\n  submitter?: SubmitterProps<{ form?: FormInstance<any> }> | false;\n\n    /** @name 底部操作区域位置 */\n  submitterPosition?: 'left' | 'right';\n\n  /**\n   * 不支持 'visible'，请使用全局的 visible\n   *\n   * @name Modal的属性\n   */\n  modalProps?: Omit<ModalProps, 'visible' | 'footer'>;\n\n  /**\n   * @name 表单的配置\n   */\n  XFormProps: IXFormProps;\n}\n\nconst ModalForm = ({\n  trigger,\n  title,\n  width,\n  modalProps,\n  XFormProps,\n  onFinish,\n  onVisibleChange,\n  ...rest\n}: IModalProps) => {\n  \n  const [visible, setVisible] = useMergedState<boolean>(!!rest.visible, {\n    value: rest.visible,\n    onChange: onVisibleChange,\n  });\n\n  useEffect(() => {\n    if (visible && rest.visible) {\n      onVisibleChange?.(true);\n    }\n  }, [visible]);\n\n  const renderFormDom = () => {\n    return (\n      <XForm\n        formData={XFormProps.formData}\n        formMap={XFormProps.formMap}\n        form={XFormProps.form}\n        submitter={\n          rest.submitter === false\n            ? false\n            : {\n                ...rest.submitter,\n                buttonConfig: {\n                  submitText: modalProps?.okText || '确认',\n                  resetText: modalProps?.cancelText || '取消',\n                  ...rest.submitter?.buttonConfig,\n                },\n                submitButtonProps: {\n                  type: (modalProps?.okType as 'text') || 'primary',\n                  ...rest.submitter?.submitButtonProps,\n                },\n                resetButtonProps: {\n                  onClick: (e: React.MouseEvent<HTMLButtonElement>) => {\n                    modalProps?.onCancel?.(e);\n                    setVisible(false);\n                  },\n                  ...rest.submitter?.resetButtonProps,\n                },\n              }\n        }\n        contentRender={(submitter) => {\n          return (\n            <Modal\n              title={title}\n              width={width || 500}\n              {...modalProps}\n              afterClose={() => {\n                XFormProps.form?.resetFields();\n                modalProps?.afterClose?.();\n              }}\n              getContainer={false}\n              visible={visible}\n              onCancel={(e) => {\n                setVisible(false);\n                modalProps?.onCancel?.(e);\n              }}\n              footer={\n                !!submitter && (\n                  <div\n                    style={{\n                      display: 'flex',\n                      justifyContent:\n                        rest.submitterPosition === 'left'\n                          ? 'flex-start'\n                          : 'flex-end',\n                    }}\n                  >\n                    {submitter}\n                  </div>\n                )\n              }\n            >\n              {renderFormContent({ ...XFormProps })}\n            </Modal>\n          );\n        }}\n        onFinish={async (values) => {\n          if (!onFinish) {\n            return;\n          }\n          const success = await onFinish(values);\n          if (success) {\n            setVisible(false);\n            XFormProps.form?.resetFields();\n          }\n        }}\n      ></XForm>\n    );\n  };\n  return (\n    <>\n      {renderFormDom()}\n      {trigger &&\n        React.cloneElement(trigger, {\n          ...trigger.props,\n          onClick: (e: any) => {\n            setVisible(!visible);\n            trigger.props?.onClick?.(e);\n          },\n        })}\n    </>\n  );\n};\n\nexport default ModalForm;\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/QueryForm/QueryForm.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport classNames from \"classnames\";\nimport { ConfigProviderProps } from \"antd/es/config-provider\";\nimport useAntdMediaQuery from \"./use-media-antd-query\";\nimport { Button, Input, Form, Row, Col, Select, ConfigProvider } from \"antd\";\nimport { DownOutlined } from \"@ant-design/icons\";\n\nimport { useContext } from \"react\";\nimport IntlContext from \"./context\";\n\nfunction useIntl(): any {\n  const i18n = useContext(IntlContext);\n  return i18n;\n}\n\ndeclare const ItemSizes: [\"large\", \"default\", \"small\", string];\nexport declare type ItemSize = typeof ItemSizes[number];\n\ndeclare const ColumnTypes: [\"select\", \"input\", \"custom\", string];\nexport declare type ColumnType = typeof ColumnTypes[number];\n\ndeclare const ModeTypes: [\"full\", \"align\", string];\nexport declare type ModeType = typeof ModeTypes[number];\n\ndeclare const ColTypes: [\"grid\", \"style\", string];\nexport declare type ColType = typeof ColTypes[number];\n\nconst FormItem = Form.Item;\nconst { Option } = Select;\n\nexport interface IColumnsType {\n  type: ColumnType;\n  dataIndex: string;\n  title: string | React.ReactNode;\n  placeholder?: string;\n  valuePropName?: string;\n  required?: boolean;\n  colStyle?: React.CSSProperties;\n  isInputPressEnterCallSearch?: boolean;\n  size?: ItemSize;\n  rules?: any[]; // 校验规则\n  component?: React.ReactNode;\n  componentProps?: any; // 需要传给组件的其他属性\n  selectMode?: string; // 单选或者多选\n  options?: {\n    title: string;\n    value: string | number;\n  }[];\n  formItemLayout?: any;\n}\nexport interface FieldData {\n  name?: string;\n  level?: string;\n  status?: string[];\n  number?: Number;\n}\n\nexport interface IQueryFormProps {\n  prefixCls?: string;\n  className?: string;\n  style?: React.CSSProperties | any;\n  mode?: ModeType;\n  colMode?: ColType;\n  defaultColStyle?: React.CSSProperties;\n  columnStyleHideNumber?: number;\n  columns: IColumnsType[];\n  searchText?: string | React.ReactNode;\n  resetText?: string | React.ReactNode;\n  showOptionBtns?: boolean;\n  showCollapseButton?: boolean;\n  onChange?: (data: any) => any;\n  initialValues: any;\n  onSearch?: (data: any) => any;\n  onReset?: (data: any) => any;\n  getFormInstance?: (form: any) => any;\n  isResetClearAll: boolean;\n  antConfig?: ConfigProviderProps;\n  defaultCollapse?: boolean;\n  colConfig?:\n    | {\n        lg: number;\n        md: number;\n        xxl: number;\n        xl: number;\n        sm: number;\n        xs: number;\n      }\n    | undefined;\n}\n\nconst defaultColConfig = {\n  xs: 24,\n  sm: 24,\n  md: 12,\n  lg: 12,\n  xl: 8,\n  xxl: 6,\n};\n\nconst defaultFormItemLayout = {\n  labelCol: {\n    xs: { span: 5 },\n    sm: { span: 5 },\n    md: { span: 7 },\n    lg: { span: 7 },\n    xl: { span: 8 },\n    xxl: { span: 8 },\n  },\n  wrapperCol: {\n    xs: { span: 19 },\n    sm: { span: 19 },\n    md: { span: 17 },\n    lg: { span: 17 },\n    xl: { span: 16 },\n    xxl: { span: 16 },\n  },\n};\n\n/**\n * 合并用户和默认的配置\n * @param span\n * @param size\n */\nconst getSpanConfig = (span: number | typeof defaultColConfig, size: keyof typeof defaultColConfig): number => {\n  if (typeof span === \"number\") {\n    return span;\n  }\n  const config = {\n    ...defaultColConfig,\n    ...span,\n  };\n  return config[size];\n};\n\n/**\n * 获取最后一行的 offset，保证在最后一列\n * @param length\n * @param span\n */\nconst getOffset = (length: number, span: number = 8) => {\n  const cols = 24 / span;\n  return (cols - 1 - (length % cols)) * span;\n};\n\nconst getCollapseHideNum = (size: number) => {\n  const maps = {\n    6: 3,\n    8: 2,\n    12: 1,\n    24: 1,\n  } as { [key: number]: number };\n\n  return maps[size] || 1;\n};\n\nconst QueryForm = (props: IQueryFormProps) => {\n  const prefixCls = `${props.prefixCls || \"dantd\"}-query-form`;\n  const { t } = useIntl();\n  const {\n    className,\n    style,\n    colConfig,\n    searchText,\n    resetText,\n    showOptionBtns = true,\n    showCollapseButton = true,\n    defaultCollapse = false,\n    isResetClearAll = false,\n    onChange,\n    onSearch,\n    onReset,\n    getFormInstance,\n    columns = [] as IColumnsType[],\n    mode = \"full\",\n    colMode = \"grid\",\n    columnStyleHideNumber = 1,\n    defaultColStyle = {\n      width: \"300px\",\n    },\n    initialValues,\n    // valueType = 'object',\n  } = props;\n  const [form] = Form.useForm();\n  const wrapperClassName = classNames(prefixCls, className);\n  const formItemCls = classNames({\n    [`${prefixCls}-formitem`]: true,\n    [`${prefixCls}-formitem-full`]: mode === \"full\",\n  });\n  const windowSize = useAntdMediaQuery();\n  const itemColConfig = colConfig || defaultColConfig;\n  const [colSize, setColSize] = useState(getSpanConfig(itemColConfig || 8, windowSize));\n  const { validateFields, getFieldsValue, resetFields, setFieldsValue } = form;\n\n  const [collapsed, setCollapse] = useState(defaultCollapse);\n\n  useEffect(() => {\n    setColSize(getSpanConfig(itemColConfig || 8, windowSize));\n  }, [windowSize]);\n\n  useEffect(() => {\n    if (getFormInstance) {\n      getFormInstance(form);\n    }\n  }, []);\n\n  const collapseHideNum = getCollapseHideNum(getSpanConfig(itemColConfig || 8, windowSize));\n\n  const handleSearch = () => {\n    validateFields()\n      .then((values) => {\n        if (onSearch) {\n          onSearch(values);\n        }\n      })\n      .catch(() => {\n        //\n      });\n  };\n\n  const handleReset = () => {\n    if (isResetClearAll) {\n      const resetFieldsObj = columns.reduce((acc, cur: IColumnsType) => {\n        return {\n          ...acc,\n          [cur.dataIndex]: undefined,\n        };\n      }, {});\n      setFieldsValue(resetFieldsObj);\n      (onChange as any)(initialValues);\n    } else {\n      resetFields();\n      (onChange as any)({});\n    }\n\n    setTimeout(() => {\n      if (onReset) {\n        onReset(getFieldsValue());\n      }\n    });\n  };\n\n  const handlePressEnter = () => {\n    handleSearch();\n  };\n\n  const renderInputItem = (colItem: any) => {\n    const {\n      dataIndex,\n      title,\n      required,\n      componentProps = {},\n      placeholder,\n      isInputPressEnterCallSearch = true,\n      formItemLayout,\n      rules,\n      size = \"default\",\n    } = colItem;\n\n    const itemPlaceholder = placeholder ? placeholder : t(\"form.placeholder.prefix\");\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n    return (\n      <FormItem\n        shouldUpdate={true}\n        key=\"input\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        <Input\n          data-testid=\"field-input\"\n          size={size}\n          placeholder={itemPlaceholder}\n          onPressEnter={isInputPressEnterCallSearch ? handlePressEnter : () => {}}\n          allowClear\n          {...componentProps}\n        />\n      </FormItem>\n    );\n  };\n\n  const renderSelectItem = (colItem: any) => {\n    const {\n      dataIndex,\n      title,\n      required,\n      placeholder,\n      selectMode = \"single\",\n      rules,\n      formItemLayout,\n      options = [],\n      componentProps = {},\n      size = \"default\",\n    } = colItem;\n    const itemPlaceholder = placeholder ? (\n      placeholder\n    ) : (\n      <>\n        {t(\"form.selectplaceholder.prefix\")}\n        &nbsp;\n        {title}\n      </>\n    );\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n\n    return (\n      <FormItem\n        key=\"select\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        <Select\n          data-testid=\"select\"\n          mode={selectMode}\n          size={size}\n          allowClear\n          placeholder={itemPlaceholder}\n          showSearch={true}\n          optionFilterProp=\"children\"\n          style={{ width: \"100%\" }}\n          {...componentProps}\n        >\n          {options.map((option: any) => {\n            return (\n              <Option data-testid=\"select-option\" value={option.value} key={option.value}>\n                {option.title}\n              </Option>\n            );\n          })}\n        </Select>\n      </FormItem>\n    );\n  };\n\n  const renderCustomItem = (colItem: any) => {\n    const { formItemLayout, dataIndex, title, required, placeholder, rules, valuePropName = \"value\", component } = colItem;\n\n    const itemPlaceholder = placeholder ? (\n      placeholder\n    ) : (\n      <>\n        {t(\"form.placeholder.prefix\")}\n        &nbsp;\n        {title}\n      </>\n    );\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n\n    return (\n      <FormItem\n        key=\"custom\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        valuePropName={valuePropName}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        {component}\n      </FormItem>\n    );\n  };\n\n  const renderOptionBtns = () => {\n    const offsetVal = collapsed\n      ? columns.length <= collapseHideNum\n        ? getOffset(columns.length, colSize)\n        : getOffset(collapseHideNum, colSize)\n      : getOffset(columns.length, colSize);\n    let optionStyle = {};\n    if (colMode === \"style\") {\n      optionStyle = {\n        position: \"absolute\",\n        width: 280,\n        bottom: 0,\n        right: 0,\n        marginLeft: 0,\n      };\n    }\n    return (\n      <Col\n        {...itemColConfig}\n        offset={offsetVal}\n        key=\"option\"\n        className={`${prefixCls}-option`}\n        style={{\n          ...optionStyle,\n        }}\n      >\n        <Form.Item key=\"option\">\n          <span>\n            <Button onClick={handleReset}>{resetText || t(\"queryform.reset\")}</Button>\n            <Button onClick={handleSearch} style={{ marginLeft: 10 }} type=\"primary\" htmlType=\"submit\">\n              {searchText || t(\"queryform.search\")}\n            </Button>\n            {showCollapseButton && (\n              <a\n                style={{\n                  marginLeft: 10,\n                  display: \"inline-block\",\n                }}\n                onClick={() => {\n                  setCollapse(!collapsed);\n                }}\n              >\n                {collapsed ? \"展开\" : \"收起\"}\n                <DownOutlined\n                  style={{\n                    marginLeft: \"0.5em\",\n                    transition: \"0.3s all\",\n                    transform: `rotate(${collapsed ? 0 : 0.5}turn)`,\n                  }}\n                />\n              </a>\n            )}\n          </span>\n        </Form.Item>\n      </Col>\n    );\n  };\n\n  return (\n    <ConfigProvider {...props.antConfig}>\n      <div className={wrapperClassName} style={style}>\n        <Row gutter={16} justify=\"start\">\n          {columns.map((colItem, colIndex) => {\n            let itemHide = collapsed && collapseHideNum <= colIndex;\n            let colItemStyle = {};\n            if (colMode === \"style\") {\n              colItemStyle = colItem.colStyle || defaultColStyle;\n              if (collapsed && colIndex >= columnStyleHideNumber) {\n                itemHide = true;\n              }\n            }\n            colItemStyle = {\n              ...colItemStyle,\n              display: itemHide ? \"none\" : \"block\",\n            };\n            return (\n              <Col style={colItemStyle} key={`query-form-col-${colItem.dataIndex}-${colIndex}`} {...itemColConfig}>\n                <Form\n                  form={form}\n                  onFieldsChange={(_changedFields, allFields) => {\n                    (onChange as any)(allFields);\n                  }}\n                  initialValues={initialValues}\n                >\n                  {colItem.type === \"input\" && renderInputItem(colItem)}\n                  {colItem.type === \"select\" && renderSelectItem(colItem)}\n                  {colItem.type === \"custom\" && renderCustomItem(colItem)}\n                </Form>\n              </Col>\n            );\n          })}\n          {showOptionBtns && renderOptionBtns()}\n        </Row>\n      </div>\n    </ConfigProvider>\n  );\n};\n\nexport default QueryForm;\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/QueryForm/context.tsx",
    "content": "import { createContext } from 'react';\n\ninterface IContextProps {\n  t: (key: any) => any;\n}\n\n\nconst IntlContext = createContext<IContextProps>({\n  t: () => '展开',\n});\n\nexport default IntlContext;\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/QueryForm/index.tsx",
    "content": "import './style/index.less';\nimport QueryForm from './QueryForm';\nimport { IColumnsType, IQueryFormProps } from './QueryForm'\nexport type {\n    IColumnsType,\n    IQueryFormProps\n}\nexport default QueryForm;\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/QueryForm/readme.md",
    "content": "# query-form\n\n## 何时使用\n\n需要一个数据查询组件时使用，组件会自己管理状态并返回查询的数据。\n\n## API\n\n\n### QueryForm\n\n| 参数       | 说明           | 类型                | 默认值 |\n| :--------- | :------------- | :------------------ | :----- |\n| columns | 表单列的配置描述，具体项见下表（必填） | ColumnProps | []     |\n| initialValues | 表单默认值，只有初始化时生效 | object | -     |\n| searchText | 搜索按钮的文案 | string \\| React.ReactNode | 查询     |\n| resetText | 重置按钮的文案 | string \\| React.ReactNode | 重置     |\n| mode      | `FormItem` 的标题展示模式，`full`是占满整行，左对齐； `align` 会根据标题右对齐 | `['full', 'align']`              | `'full'`     |\n| colMode      | `FormItem` 的展示模式，`grid`是等分的栅格布局； `style` 会根据会对每个 `Col` 增加固定 `300px` 的宽度，也可以通过 `Column.colStyle` 自定义宽度等样式 | `['grid', 'style']`              | `'grid'`     |\n| showOptionBtns | 是否展示右下角的「查询」「重置」按钮，以及「展开」「收起」 | boolean | true      |\n| showCollapseButton | 是否展示右下角的「展开」「收起」 | boolean | true     |\n| onChange | 表单的值改变时触发的回调 | Function(values, form) | - |\n| onSearch | 点击查询按钮的回调 | Function(values, form) | - |\n| onReset | 点击重置按钮的回调 | Function(form) | - |\n| isResetClearAll | 点击重置时，是清空form里面的值，还是根据 `initialValue` 重置 | boolean | false     |\n| getFormInstance | 只用来获取Form实例的回调 | Function(form) | - |\n| defaultCollapse | 是否默认「展开」 | boolean | true     |\n| colConfig | Col 布局配置 | `{lg:number;md:number;xxl:number;xl:number;sm:number;xs:number}` | `{xs:24,sm:24,md:12,lg:12,xl:8,xxl:6}` |\n| antConfig | 使用 `Antd ConfigProvider` 进行的全局配置，需要通过这个属性传进来 | [ConfigProviderProps](https://github.com/ant-design/ant-design/blob/master/components/config-provider/index.tsx) | - |\n\n### Columns\n\n表单列的配置描述，目前支持 `['input', 'select', 'custom']` 这三种。\n\n| 参数       | 说明           | 类型                | 默认值 |\n| :--------- | :------------- | :------------------ | :----- |\n| type      | 动态表单组件的类型，内置 `input`, `select`；也可以自定义  | `['input', 'select', 'custom']`              | -      |\n| title      | 标题    | string              |  -      |\n| dataIndex      | form表单的唯一标识，不可以重复   | string              |  -      |\n| placeholder | 占位文案，默认会根据 `title` 自动生成 | string | -     |\n| isInputPressEnterCallSearch | 输入框按回车的时候，触发搜索 | boolean | -     |\n| valuePropName | 子节点的值的属性，如 Switch 的是 'checked' | string | 'value'    |\n| required | 是否对参数进行必填校验 | boolean | true      |\n| colStyle | `colMode='style'` 时，可以设置单个 `Column` 的样式| `React.CSSProperties` | -      |\n| columnStyleHideNumber | `colMode='style'` 时，收起时默认只展示一项，可以设置展示多项| number | 1      |\n| formItemLayout | 表单的Layout | `{labelCol:{xs:{span:number},sm:{span:number},md:{span:number},lg:{span:number},xl:{span:number},xxl:{span:number}},wrapperCol:{xs:{span:number},sm:{span:number},md:{span:number},lg:{span:number},xl:{span:number},xxl:{span:number}}}` | `{labelCol:{xs:{span:5},sm:{span:5},md:{span:7},lg:{span:7},xl:{span:8},xxl:{span:8},},wrapperCol:{xs:{span:19},sm:{span:19},md:{span:17},lg:{span:17},xl:{span:16},xxl:{span:16},},}`     |\n| rules | 自定义表单项的校验规则 | `object[]` | -      |\n| size | 表单项的 `size` 属性 | `large` \\| `default` \\| `small` | `default`   |\n| componentProps | `type=\"input|select\"` 时，可以通过该属性 ant 组件的Props | any | -      |\n| component | `type=\"custom\"` 时，可以通过该属性传递 `React.ReactNode` |  React.ReactNode | -      |\n| selectMode | `type=\"select\"` 时的 `mode` 属性 | `default` \\| `multiple` | `default`      |\n| options | `type=\"select\"` 时，通过该属性设置下拉选项 | {title: string;value: string;}[] | []      |\n\n## Demo\n\n```js\nimport { useState } from 'react';\nimport { QueryForm, InputNumber, Card, Button, Modal } from 'antd-advanced';\n\n\nconst columns = [\n  {\n    type: 'input',\n    title: '实例名称',\n    dataIndex: 'name',\n  },\n  {\n    type: 'select',\n    title: '报警等级',\n    dataIndex: 'level',\n    options: [\n      {\n        title: '全部',\n        value: 'all',\n      },\n      {\n        title: 'P0',\n        value: 'p0',\n      },\n      {\n        title: 'P1',\n        value: 'p1',\n      },\n      {\n        title: 'P2',\n        value: 'p2',\n      },\n    ],\n  },\n  {\n    type: 'select',\n    title: '任务状态',\n    dataIndex: 'status',\n    selectMode: 'multiple',\n    options: [\n      {\n        title: '进行中',\n        value: 'processing',\n      },\n      {\n        title: '成功',\n        value: 'success',\n      },\n      {\n        title: '失败',\n        value: 'fail',\n      },\n    ],\n  },\n  {\n    type: 'custom',\n    title: '机器数量',\n    dataIndex: 'number',\n    component: (\n      <InputNumber\n        placeholder=\"请输入机器数量\"\n        style={{ marginTop: 4, width: '100%' }}\n        min={0}\n        precision={0}\n      />\n    ),\n  },\n];\n\nconst Demo: React.FC = () => {\n  const initialValues = {\n    name: 'test',\n    level: 'p1',\n  }\n  const [result, setResult] = useState(initialValues);\n  const [isModalVisible, setIsModalVisible] = useState(false);\n\n  const showModal = () => {\n    setIsModalVisible(true);\n  };\n\n  const handleOk = () => {\n    setIsModalVisible(false);\n  };\n\n  const handleCancel = () => {\n    setIsModalVisible(false);\n  };\n  const handleChange = queryValue => {\n    setResult(queryValue);\n  };\n  return (\n    <div>\n      <QueryForm \n        onChange={handleChange} \n        onSearch={handleChange}\n        columns={columns} \n        initialValues={initialValues}\n      />\n      <h3>结果：</h3>\n      <div>{JSON.stringify(result)}</div>\n\n      <Card>\n        <Button type=\"primary\" onClick={showModal}>\n          Open Modal\n        </Button>\n        <Modal title=\"Basic Modal\" visible={isModalVisible} onOk={handleOk} onCancel={handleCancel}>\n          <p>Some contents...</p>\n          <p>Some contents...</p>\n          <p>Some contents...</p>\n        </Modal>\n      </Card>\n    </div>\n  );\n}\n\nReactDOM.render(\n  <div>\n    <Demo />\n  </div>,\n  mountNode,\n);\n```"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/QueryForm/style/index.less",
    "content": ".dantd-query-form {\n  padding: 20px 20px 0 20px;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/QueryForm/style/index.tsx",
    "content": "import './index.less';\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/QueryForm/use-media-antd-query.ts",
    "content": "import { useState, useEffect } from 'react';\nimport useMediaQuery from './use-media';\n\nexport const MediaQueryEnum = {\n  xs: '(max-width: 575px)',\n  sm: '(min-width: 576px) and (max-width: 767px)',\n  md: '(min-width: 768px) and (max-width: 991px)',\n  lg: '(min-width: 992px) and (max-width: 1199px)',\n  xl: '(min-width: 1200px) and (max-width: 1599px)',\n  xxl: '(min-width: 1600px)',\n};\n\nexport type MediaQueryKey = keyof typeof MediaQueryEnum;\n\n/**\n * loop query screen className\n * Array.find will throw a error\n * `Rendered more hooks than during the previous render.`\n * So should use Array.forEach\n */\nexport const getScreenClassName = () => {\n  let className: MediaQueryKey = 'md';\n  // support ssr\n  if (typeof window === 'undefined') {\n    return className;\n  }\n  const mediaQueryKey = (Object.keys(MediaQueryEnum) as MediaQueryKey[]).find((key) => {\n    const matchMedia = MediaQueryEnum[key];\n    if (window.matchMedia(matchMedia).matches) {\n      return true;\n    }\n    return false;\n  });\n  className = (mediaQueryKey as unknown) as MediaQueryKey;\n  return className;\n};\n\nconst useMedia = () => {\n  const isMd = useMediaQuery(MediaQueryEnum.md);\n  const isLg = useMediaQuery(MediaQueryEnum.lg);\n  const isXxl = useMediaQuery(MediaQueryEnum.xxl);\n  const isXl = useMediaQuery(MediaQueryEnum.xl);\n  const isSm = useMediaQuery(MediaQueryEnum.sm);\n  const isXs = useMediaQuery(MediaQueryEnum.xs);\n  const [colSpan, setColSpan] = useState<keyof typeof MediaQueryEnum>(getScreenClassName());\n\n  useEffect(() => {\n    if (isXxl) {\n      setColSpan('xxl');\n      return;\n    }\n    if (isXl) {\n      setColSpan('xl');\n      return;\n    }\n    if (isLg) {\n      setColSpan('lg');\n      return;\n    }\n    if (isMd) {\n      setColSpan('md');\n      return;\n    }\n    if (isSm) {\n      setColSpan('sm');\n      return;\n    }\n    if (isXs) {\n      setColSpan('xs');\n      return;\n    }\n    setColSpan('md');\n  }, [isMd, isLg, isXxl, isXl, isSm, isXs]);\n\n  return colSpan;\n};\n\nexport default useMedia;\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/QueryForm/use-media.ts",
    "content": "import { useEffect, useState } from 'react';\n\nexport const isClient = typeof window === 'object';\n\nconst useMedia = (query: string, defaultState: boolean = false) => {\n  const [state, setState] = useState(\n    isClient ? () => window.matchMedia(query).matches : defaultState,\n  );\n\n  useEffect(() => {\n    let mounted = true;\n    const mql = window.matchMedia(query);\n    const onChange = () => {\n      if (!mounted) {\n        return;\n      }\n      setState(!!mql.matches);\n    };\n\n    mql.addListener(onChange);\n    setState(mql.matches);\n\n    return () => {\n      mounted = false;\n      mql.removeListener(onChange);\n    };\n  }, [query]);\n\n  return state;\n};\n\nexport default useMedia;\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/StepForm/index.tsx",
    "content": "import React from \"react\";\n\nconst StepForm = () => {\n    return <div>StepForm</div>\n}\n\nexport default StepForm"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/Submitter/index.tsx",
    "content": "import React from \"react\";\nimport type { FormInstance, ButtonProps } from \"antd\";\nimport { Button, Space } from \"antd\";\n// import omit from \"omit.js\";\n\n/** @name 用于配置操作栏 */\nexport type ButtonConfig = {\n  /** @name 重置按钮的文本 */\n  resetText?: React.ReactNode;\n  /** @name 提交按钮的文本 */\n  submitText?: React.ReactNode;\n};\n\nexport type SubmitterProps<T = {}> = {\n  /** @name  按钮文本的配置*/\n  buttonConfig?: ButtonConfig;\n  /** @name 提交按钮的 props */\n  submitButtonProps?: false | (ButtonProps & { preventDefault?: boolean });\n  /** @name 重置按钮的 props */\n  resetButtonProps?: false | (ButtonProps & { preventDefault?: boolean });\n  /** @name 自定义操作的渲染 */\n  render?:\n    | ((\n        props: SubmitterProps &\n          T & {\n            submit: () => void;\n            reset: () => void;\n          },\n        dom: JSX.Element[]\n      ) => React.ReactNode[] | React.ReactNode | false)\n    | false;\n};\n\n/**\n * FormFooter组件\n  */\n\nconst Submitter: React.FC<SubmitterProps & { form: FormInstance }> = (\n  props\n) => {\n  if (props.render === false) {\n    return null;\n  }\n\n  const {\n    form,\n    render,\n    buttonConfig = {},\n    submitButtonProps,\n    resetButtonProps = {},\n  } = props;\n  const submit = () => {\n    form.submit();\n  };\n\n  const reset = () => {\n    form.resetFields();\n  };\n\n  const { submitText = \"提交\", resetText = \"重置\" } = buttonConfig;\n  /** 默认的操作的逻辑 */\n  const dom = [];\n\n  if (resetButtonProps !== false) {\n    dom.push(\n      <Button\n        // {...omit(resetButtonProps, [\"preventDefault\"])}\n        key=\"rest\"\n        onClick={(e) => {\n          if (!resetButtonProps?.preventDefault) reset();\n          resetButtonProps?.onClick?.(e);\n        }}\n      >\n        {resetText}\n      </Button>\n    );\n  }\n  if (submitButtonProps !== false) {\n    dom.push(\n      <Button\n        type=\"primary\"\n        // {...omit(submitButtonProps || {}, [\"preventDefault\"])}\n        key=\"submit\"\n        onClick={(e) => {\n          if (!submitButtonProps?.preventDefault) submit();\n          submitButtonProps?.onClick?.(e);\n        }}\n      >\n        {submitText}\n      </Button>\n    );\n  }\n\n  const renderDom = render ? render({ ...props, submit, reset }, dom) : dom;\n  if (!renderDom) {\n    return null;\n  }\n  if (Array.isArray(renderDom)) {\n    if (renderDom?.length < 1) {\n      return null;\n    }\n    if (renderDom?.length === 1) {\n      return renderDom[0] as JSX.Element;\n    }\n    return <Space>{renderDom}</Space>;\n  }\n  return renderDom as JSX.Element;\n};\n\nexport default Submitter;\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/XForm/index.less",
    "content": ".ant-input-number {\n  width: 314px\n}\n\n.footer-btn {\n  float: right;\n  text-align: right;\n  padding: 40px;\n  Button:first-child {\n    margin-right: 16px;\n  }\n}\n.ant-modal-body {\n  padding: 20px;\n}\n.ant-modal-header {\n  padding: 10px 20px;\n}\n.ant-form-item{\n  margin-bottom: 0;\n}"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/XForm/index.tsx",
    "content": "import * as React from \"react\";\nimport {\n  Button,\n  Checkbox,\n  DatePicker,\n  Form,\n  Input,\n  InputNumber,\n  Radio,\n  Select,\n  Switch,\n  Upload,\n  Cascader,\n  Row,\n  Col,\n  TimePicker,\n  AutoComplete,\n  TreeSelect,\n} from \"antd\";\nimport { UploadOutlined } from \"@ant-design/icons\";\nimport { useMemo, useState } from \"react\";\nimport Submitter, { SubmitterProps } from \"../Submitter\";\nimport { filterOption } from \"lib/utils\";\n\nconst TextArea = Input.TextArea;\nconst { RangePicker } = DatePicker;\n\nexport enum FormItemType {\n  input = \"input\",\n  inputNumber = \"input_number\",\n  textArea = \"text_area\",\n  select = \"select\",\n  _switch = \"_switch\",\n  custom = \"custom\",\n  checkBox = \"check_box\",\n  datePicker = \"date_picker\",\n  rangePicker = \"range_picker\",\n  radioGroup = \"radio_group\",\n  upload = \"upload\",\n  text = \"text\",\n  cascader = \"cascader\",\n  autoComplete = \"autoComplete\",\n  timePicker = \"timePicker\",\n  treeSelect = \"treeSelect\",\n}\n\nexport interface IFormItem {\n  key: string;\n  label: string;\n  type?: FormItemType;\n  value?: string;\n  options?: any[];\n  // 内部组件属性注入\n  attrs?: any;\n  // form属性注入\n  formAttrs?: any;\n  defaultValue?: string | number | any[];\n  rules?: any[];\n  invisible?: boolean;\n  extraElement?: JSX.Element;\n  colSpan?: any;\n  customClassName?: any;\n  radioType?: boolean;\n  isCustomStyle?: boolean;\n  customFormItem?: any;\n  treeData?: any[];\n}\n\nexport interface IFormSelect extends IFormItem {\n  options: Array<{\n    key?: string | number;\n    value: string | number;\n    label: string;\n    radioType?: boolean;\n    disabled?: boolean;\n  }>;\n}\n\ninterface IFormCustom extends IFormItem {\n  customFormItem: React.Component;\n}\nexport interface IXFormProps {\n  formMap: IFormItem[];\n  formData: any;\n  form?: any;\n  wrappedComponentRef?: any;\n  onFinish?: any;\n  formLayout?: any;\n  layout?: \"inline\" | \"horizontal\" | \"vertical\";\n  onHandleValuesChange?: (value: any, allValues: object) => any;\n  formItemColSpan?: number;\n  contentRender?: any;\n  submitter?: any;\n}\n\nexport const renderFormItem = (item: IFormItem) => {\n  switch (item.type) {\n    default:\n    case FormItemType.input:\n      return <Input allowClear key={item.key} {...item.attrs} />;\n    case FormItemType.inputNumber:\n      return <InputNumber {...item.attrs} />;\n    case FormItemType.textArea:\n      return <TextArea allowClear rows={2} {...item.attrs} />;\n    case FormItemType.autoComplete:\n      return (\n        <AutoComplete\n          key={item.key}\n          options={item.options}\n          allowClear={item.attrs?.allowClear || true}\n          placeholder={item.attrs?.placeholder || \"请输入\"}\n          filterOption={(inputValue, option) => option!.value.indexOf(inputValue) !== -1}\n          {...item.attrs}\n        />\n      );\n    case FormItemType.select:\n      return (\n        <Select showSearch filterOption={filterOption} key={item.key} placeholder={item.attrs?.placeholder || \"请选择\"} {...item.attrs}>\n          {(item as IFormSelect).options &&\n            (item as IFormSelect).options.map((v, index) => (\n              <Select.Option key={v.value || v.key || index} value={v.value} disabled={v.disabled}>\n                {v.label || v.value}\n              </Select.Option>\n            ))}\n        </Select>\n      );\n    case FormItemType._switch:\n      return <Switch {...item.attrs} />;\n    case FormItemType.custom:\n      return (item as IFormCustom).customFormItem;\n    case FormItemType.checkBox:\n      return <Checkbox.Group options={(item as IFormSelect).options} {...item.attrs} />;\n    case FormItemType.datePicker:\n      return <DatePicker key={item.key} {...item.attrs} />;\n    case FormItemType.rangePicker:\n      return <RangePicker key={item.key} {...item.attrs} />;\n    case FormItemType.timePicker:\n      return <TimePicker key={item.key} {...item.attrs} />;\n    case FormItemType.autoComplete:\n      return (\n        <AutoComplete\n          key={item.key}\n          options={item.options}\n          allowClear={item.attrs?.allowClear || true}\n          placeholder={item.attrs?.placeholder || \"请输入\"}\n          filterOption={\n            item.attrs?.filterOption ? item.attrs?.filterOption : (inputValue: any, option) => option!.value.indexOf(inputValue) !== -1\n          }\n          {...item.attrs}\n        />\n      );\n    case FormItemType.treeSelect:\n      return <TreeSelect key={item.key} treeData={item.treeData} placeholder={item.attrs?.placeholder || \"请选择\"} {...item.attrs} />;\n    case FormItemType.radioGroup:\n      return (\n        <Radio.Group key={item.key} {...item.attrs}>\n          {(item as IFormSelect).options.map((v, index) => {\n            if (v.radioType) {\n              return (\n                <Radio.Button key={v.value || v.key || index} value={v.value}>\n                  {v.label}\n                </Radio.Button>\n              );\n            }\n            return (\n              <Radio key={v.value || v.key || index} value={v.value}>\n                {v.label}\n              </Radio>\n            );\n          })}\n        </Radio.Group>\n      );\n    case FormItemType.upload:\n      return (\n        <Upload beforeUpload={false} {...item.attrs}>\n          <Button>\n            <UploadOutlined />\n            上传\n          </Button>\n        </Upload>\n      );\n    case FormItemType.cascader:\n      return <Cascader key={item.key} options={(item as IFormSelect).options} {...item.attrs} />;\n  }\n};\n\nexport const handleFormItem = (formItem: any, formData: any) => {\n  let initialValue = formData[formItem.key] || formItem.defaultValue || undefined;\n  let valuePropName = \"value\";\n\n  if (formItem.type === FormItemType.datePicker) {\n    initialValue = initialValue || null;\n  }\n\n  if (formItem.type === FormItemType._switch) {\n    initialValue = formData[formItem.key] ? true : false;\n  }\n\n  if (formItem.type === FormItemType._switch) {\n    valuePropName = \"checked\";\n  }\n\n  if (formItem.type === FormItemType.upload) {\n    valuePropName = \"fileList\";\n  }\n  return { initialValue, valuePropName };\n};\n\nconst onUploadFileChange = (e: any) => {\n  if (Array.isArray(e)) {\n    return e;\n  }\n  return e && e.fileList;\n};\n\nexport const renderFormContent = ({ formMap, formData, layout, formLayout, formItemColSpan = 24 }: any) => {\n  return formMap.map((formItem) => {\n    const { initialValue = undefined, valuePropName } = handleFormItem(formItem, formData);\n    if (formItem.type === FormItemType.text)\n      return (\n        !formItem.invisible && (\n          <Col key={formItem.key} span={formItem.colSpan || formItemColSpan}>\n            {layout === \"vertical\" ? (\n              <>\n                <span style={{ padding: \"0 0 5px\", display: \"block\", color: \"#919AAC\", fontSize: \"12px\" }}>{formItem.label}</span>\n                <span style={{ fontSize: \"14px\", padding: \"0 0 16px\", display: \"block\" }}>{(formItem as IFormCustom).customFormItem}</span>\n              </>\n            ) : (\n              <Row style={{ padding: \"6px 0 10px\" }}>\n                <Col span={formLayout?.labelCol.span || 4} style={{ textAlign: \"right\" }}>\n                  <span style={{ padding: \"0 10px 0 0\", display: \"inline-block\" }}>{formItem.label}:</span>\n                </Col>\n                <Col span={formLayout?.wrapperCol.span || 20}>\n                  <span>{(formItem as IFormCustom).customFormItem}</span>\n                </Col>\n              </Row>\n            )}\n          </Col>\n        )\n      );\n    return (\n      !formItem.invisible && (\n        <Col key={formItem.key} span={formItem.colSpan || formItemColSpan}>\n          <Form.Item\n            name={formItem.key}\n            key={formItem.key}\n            label={formItem.label}\n            rules={formItem.rules || [{ required: false, message: \"\" }]}\n            initialValue={initialValue}\n            valuePropName={valuePropName}\n            className={formItem.isCustomStyle ? \"ant-form-item-custom\" : null} // 兼容负责人选择后表单样式变大\n            style={formItem.isCustomStyle ? { marginBottom: 24 } : null}\n            getValueFromEvent={formItem.type === FormItemType.upload ? onUploadFileChange : null}\n            {...formItem.formAttrs}\n          >\n            {renderFormItem(formItem)}\n          </Form.Item>\n        </Col>\n      )\n    );\n  });\n};\n\nexport const XForm: React.FC<IXFormProps> = (props: IXFormProps) => {\n  const { layout, formLayout, formData, formMap, form, wrappedComponentRef, onHandleValuesChange, contentRender, submitter, ...rest } =\n    props;\n\n  const defaultLayout =\n    layout === \"vertical\"\n      ? null\n      : formLayout\n      ? formLayout\n      : {\n          labelCol: { span: 4 },\n          wrapperCol: { span: 20 },\n        };\n\n  const submitterProps: SubmitterProps = useMemo(() => (typeof submitter === \"boolean\" || !submitter ? {} : submitter), [submitter]);\n\n  const [loading, setLoading] = useState<boolean>(false);\n\n  const submitterNode = (() => {\n    if (submitter === false) return undefined;\n    return (\n      <Submitter\n        key=\"submitter\"\n        {...submitterProps}\n        form={form}\n        submitButtonProps={{\n          loading,\n          ...submitterProps.submitButtonProps,\n        }}\n      />\n    );\n  })();\n\n  const content = useMemo(() => {\n    if (contentRender) {\n      return contentRender(submitterNode);\n    }\n    return null;\n  }, [contentRender, submitterNode]);\n\n  return (\n    <>\n      <Form\n        ref={wrappedComponentRef}\n        form={form}\n        {...defaultLayout}\n        layout={layout || \"horizontal\"}\n        onValuesChange={onHandleValuesChange}\n        onFinish={async () => {\n          if (!rest.onFinish) return;\n          if (loading) return;\n          setLoading(true);\n          try {\n            const finalValues = form.getFieldsValue();\n            await rest.onFinish(finalValues);\n            setLoading(false);\n          } catch (error) {\n            setLoading(false);\n          }\n        }}\n      >\n        <Row gutter={10}>{content ? content : renderFormContent({ ...props })}</Row>\n      </Form>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProForm/index.ts",
    "content": "import { XForm } from \"./XForm\";\nimport DrawerForm from \"./DrawerForm\";\nimport ModalForm from \"./ModalForm\";\nimport QueryForm from \"./QueryForm\";\n\nexport {\n    DrawerForm,\n    ModalForm,\n    QueryForm\n}\nexport default XForm;\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProTable/DTable/filterTableColumns.less",
    "content": "@ant-prefix: 'dcloud';\n@checkbox-prefix-cls: ~'@{ant-prefix}-checkbox';\n\n.dcloud-checkbox-table-columns {\n  flex-wrap: wrap-reverse;\n  max-height: 186px;\n  overflow: auto;\n\n  .@{checkbox-prefix-cls}-wrapper {\n    width: 126px;\n    max-width: 50%;\n    padding-bottom: 10px;\n  }\n\n  .@{checkbox-prefix-cls} {\n    border-radius: 4px;\n  }\n}\n\n.dcloud-filter-modal{\n  .@{ant-prefix}-modal-footer{\n    .@{ant-prefix}-btn-sm{\n      padding-left: 16px;\n      padding-right: 16px;\n    }\n  }\n}\n\n// 去除自定义列默认的内填充\n.dcloud-checkbox-table-serch {\n  width: 100%;\n  padding: 16px 0;\n  border-radius: 4px;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProTable/DTable/filterTableColumns.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { Modal, Checkbox, Input, Button, Utils } from \"knowdesign\";\nimport { IconFont } from \"@knowdesign/icons\";\nexport default (props) => {\n  const { columns, setFilterColumns, visible = false, setVisible, tableId, title = \"自定义列\", modalSize } = props;\n  const [checkBoxOption, setCheckBoxOption] = useState([]);\n  const [searchCheckBox, setSearchCheckBox] = useState(null);\n  const [checked, setChecked] = useState([]);\n  const [searchValue, setSearchValue] = useState(\"\");\n\n  const setCheckBoxColumnsOption = () => {\n    if (!Array.isArray(columns)) return;\n    if (columns.length < 1) return;\n    // 根据表格Id获取本地存储的不展示的数据项\n    const checkedCol = tableId ? Utils.getLocalStorage(tableId) : null;\n    // 依据columns遍历出新的checkBox的options\n    const newcheckBoxOption = columns\n      .filter((item) => !item.filterTitle)\n      .map((item) => {\n        return {\n          ...item,\n          label: item.title,\n          value: item.key || item.dataIndex,\n        };\n      });\n\n    // 设置新的checkBox的options\n    setCheckBoxOption(newcheckBoxOption);\n    if (checkedCol?.length > 0) {\n      // 根据本地存储的不展示项筛选出需勾选项数组\n      const changeChecked = newcheckBoxOption\n        .filter((item) => !checkedCol?.includes(item.value))\n        .map((item) => {\n          return item.value;\n        });\n\n      setChecked(changeChecked);\n      return;\n    }\n    // 根据item.invisible获取新的勾选项数组\n    const newChecked = newcheckBoxOption\n      .filter((item) => !item.invisible)\n      .map((item) => {\n        return item.value;\n      });\n    setChecked(newChecked);\n  };\n\n  const checkBoxChange = (e) => {\n    // 每次change都筛选更新勾选项数组\n    const searchChecked = checkBoxOption\n      .filter((item) => {\n        if (!searchCheckBox) return;\n        return checked.includes(item.value) && !searchCheckBox.map((item) => item.value).includes(item.value);\n      })\n      .map((item) => item.value);\n\n    setChecked([...searchChecked, ...e]);\n  };\n\n  // 确认按钮\n  const onOk = () => {\n    // 如果localstarage没有存储不展示项，table渲染会用这个新的columns\n    const newColumns = columns.map((item) => {\n      return {\n        ...item,\n        invisible: !item.filterTitle && !checked.includes(item.dataIndex || item.key),\n      };\n    });\n    // 向localstarage存入数据\n    const filterChecked = checkBoxOption\n      .filter((item) => !item.filterTitle && !checked?.includes(item.value))\n      .map((item) => {\n        return item.value;\n      });\n    tableId && Utils.setLocalStorage(tableId, filterChecked);\n    // 调用DTable传入设置columns的方法\n    setFilterColumns(newColumns);\n    // 关闭弹窗\n    setVisible(false);\n    // 清空搜索结果\n    setSearchCheckBox(null);\n    // 清空Search框\n    setSearchValue(\"\");\n  };\n\n  // 取消按钮\n  const onCancel = () => {\n    const checkedCol = tableId ? Utils.getLocalStorage(tableId) : null;\n    if (checkedCol?.length > 0) {\n      const changeChecked = checkBoxOption\n        .filter((item) => !checkedCol?.includes(item.value))\n        .map((item) => {\n          return item.value;\n        });\n      setChecked(changeChecked);\n    } else {\n      const newChecked = checkBoxOption\n        .filter((item) => !item.invisible)\n        .map((item) => {\n          return item.value;\n        });\n      setChecked(newChecked);\n    }\n    setSearchCheckBox(null);\n    setSearchValue(\"\");\n    setVisible(false);\n  };\n\n  // 搜索\n  const searchChange = (e) => {\n    const value = e.target.value || \"\";\n    setSearchValue(value);\n    const newCheckBoxOption = checkBoxOption.filter((item) => {\n      return item.title.includes(value);\n    });\n    setSearchCheckBox(newCheckBoxOption);\n  };\n\n  // 恢复系统默认\n  const restoringDefaults = () => {\n    const newChecked = checkBoxOption.map((item) => {\n      return item.value;\n    });\n    setChecked(newChecked);\n    // 清空搜索结果\n    setSearchCheckBox(null);\n    // 清空Search框\n    setSearchValue(\"\");\n  };\n\n  useEffect(() => {\n    setCheckBoxColumnsOption();\n  }, [props.columns, props.visible]);\n\n  return (\n    <Modal\n      className=\"dcloud-filter-modal\"\n      title={title}\n      visible={visible}\n      onOk={onOk}\n      onCancel={onCancel}\n      width={340}\n      bodyStyle={{\n        padding: \"0 24px\",\n      }}\n      footer={\n        <div style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}>\n          <div>\n            <Button size={modalSize} onClick={restoringDefaults}>\n              恢复系统默认\n            </Button>\n          </div>\n          <div style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}>\n            <Button size={modalSize} onClick={onCancel} type=\"default\">\n              取消\n            </Button>\n            <Button size={modalSize} onClick={onOk} type=\"primary\">\n              确定\n            </Button>\n          </div>\n        </div>\n      }\n    >\n      <div className={\"dcloud-checkbox-table-serch\"}>\n        <Input\n          size={modalSize}\n          value={searchValue}\n          onChange={searchChange}\n          suffix={<IconFont type=\"icon-fangdajing\" />}\n          placeholder=\"搜索字段\"\n        />\n      </div>\n      <Checkbox.Group\n        className={\"dcloud-checkbox-table-columns\"}\n        options={searchCheckBox || checkBoxOption}\n        value={checked}\n        onChange={checkBoxChange}\n      />\n    </Modal>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProTable/DTable/index.less",
    "content": "@ant-prefix: ant;\n\n.d-table {\n  &-box {\n    // padding: 20px 0px; // 去除padding改由外部控制\n\n    &-header {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      padding: 12px 0;\n\n      &-search {\n        display: flex;\n        align-items: center;\n        justify-content: space-between;\n\n        &-custom {\n          padding-left: 12px;\n        }\n      }\n\n      &-btn {\n        display: flex;\n        align-items: center;\n        // button {\n        //   margin-right: 10px;\n        // }\n\n        &-reload {\n          font-size: 20px;\n          color: #74788d;\n          cursor: pointer;\n        }\n\n        &-divider {\n          height: 20px;\n          top: 0;\n        }\n\n        // .reload {\n        //   width: 30px;\n        //   height: 30px;\n        //   margin-right: 10px;\n        //   line-height: 30px;\n        //   border: 1px solid #dbe0e4;\n        //   border-radius: 2px;\n        // }\n\n        .reload:hover {\n          color: #2f81f9;\n        }\n      }\n    }\n\n    &-query {\n      box-sizing: border-box;\n      padding-bottom: 14px;\n      overflow: auto;\n      background-color: #f8f9fa;\n      transition: all 0.3s linear;\n    }\n\n    .line-custom-title {\n      display: flex;\n      align-items: center;\n      &-left {\n        display: flex;\n        align-items: center;\n        width: 100%;\n        &-text {\n          white-space: nowrap;\n          font-size: 13px;\n          font-weight: 500;\n        }\n        &-line {\n          width: 100%;\n          height: 1px;\n          background-color: #f6f6f6;\n          margin-left: 10px;\n        }\n      }\n    }\n  }\n\n  .@{ant-prefix}-table-title {\n    margin-bottom: 16px;\n    padding: 0;\n  }\n\n  .@{ant-prefix}-thead {\n    tr th {\n      white-space: nowrap;\n    }\n  }\n\n  .@{ant-prefix}-filter-column {\n    line-height: 100%;\n\n    .@{ant-prefix}-filter-column-title {\n      flex-grow: 0;\n      padding-right: 5px;\n    }\n\n    .@{ant-prefix}-filter-trigger-container {\n      position: relative;\n    }\n  }\n}\n\n.pro-table-container {\n  .container-query {\n    width: 100%;\n    // background: #fff;\n    // .dantd-query-form-option {\n    //   .@{ant-prefix}-form-item-control-input-content {\n    //     text-align: right;\n    //   }\n    // }\n  }\n\n  .container-table {\n    .@{ant-prefix}-table-thead {\n      tr th {\n        white-space: nowrap;\n      }\n    }\n\n    .@{ant-prefix}-table-filter-column {\n      line-height: 100%;\n\n      .@{ant-prefix}-table-filter-column-title {\n        flex-grow: 0;\n        padding-right: 5px;\n      }\n\n      .@{ant-prefix}-table-filter-trigger-container {\n        position: relative;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProTable/DTable/index.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { Input, Button, Table, ConfigProvider, Tooltip, Divider } from \"knowdesign\";\nimport { DSearchInput, Utils } from \"knowdesign\";\n\nimport { IconFont } from \"@knowdesign/icons\";\nimport { ReloadOutlined, SearchOutlined } from \"@ant-design/icons\";\nimport QueryForm, { IQueryFormProps } from \"../../QueryForm\";\n\nimport FilterTableColumns from \"./filterTableColumns\";\nimport \"./filterTableColumns.less\";\n// 表格国际化无效问题手动加\nimport antdZhCN from \"antd/es/locale/zh_CN\";\nimport \"./index.less\";\nexport const DTablerefix = \"d-table\";\n\nexport const pagination = {\n  position: [\"bottomRight\"],\n  // showQuickJumper: true,\n  showSizeChanger: true,\n  pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n  // showTotal: (total: number) => `共 ${total} 个条目`,\n  // hideOnSinglePage: true,\n  // total: 500,\n};\n\nexport interface ITableColumnsType {\n  title: string | JSX.Element;\n  key?: string;\n  dataIndex: string;\n  render?: (text?: any, record?: any) => any;\n  invisible?: boolean;\n  lineClampOne?: boolean; // 文本展示1行且超出隐藏，如果是自定义render，内容Tooltip需要自行处理\n  lineClampTwo?: boolean; // 文本展示2行且超出隐藏，如果是自定义render，内容Tooltip需要自行处理\n  filterTitle?: boolean; // 开启表头自定义列\n  titleIconType?: string; // 表头自定义列的Icon\n  needTooltip?: boolean; // 是否需要提供Tooltip展示\n  tooltipPlace?: any;\n  tooltipNode?: JSX.Element;\n  [name: string]: any;\n}\n\nexport interface ITableBtn {\n  clickFunc?: () => void;\n  type?: \"primary\" | \"ghost\" | \"dashed\" | \"link\" | \"text\" | \"default\" | \"custom\";\n  customFormItem?: string | JSX.Element;\n  // isRouterNav?: boolean;\n  label: string | JSX.Element;\n  className?: string;\n  // needConfirm?: boolean;\n  // aHref?: string;\n  // confirmText?: string;\n  noRefresh?: boolean;\n  loading?: boolean;\n  disabled?: boolean;\n  // invisible?: boolean; // 不可见\n}\n\nexport interface ISearchInput {\n  placeholder?: string;\n  submit: (params?: any) => any;\n  width?: string;\n  searchTrigger?: string;\n  searchInputType?: string;\n  searchAttr?: any;\n}\n\nexport interface IDTableProps {\n  showHeader?: boolean;\n  paginationProps?: any;\n  noPagination?: boolean;\n  rowKey: string;\n  columns: ITableColumnsType[];\n  dataSource: any[];\n  loading?: boolean;\n  reloadData?: (params?: any) => any;\n  isDividerHide?: boolean; // 刷新按钮右侧有按钮时，控制Divider的显示隐藏，默认为true\n  getOpBtns?: (params?: any) => ITableBtn[];\n  getJsxElement?: (params?: any) => JSX.Element;\n  tableHeaderSearchInput?: ISearchInput;\n  attrs?: any;\n  searchInputRightBtns?: ITableBtn[];\n  showQueryForm?: boolean;\n  queryFormProps?: IQueryFormProps;\n  tableId?: string;\n  customLocale?: any;\n  tableScreen?: boolean; // 控制queryForm显示隐藏的按钮\n  tableCustomColumns?: boolean; // 表格自定义列\n  filterModalSize?: \"small\" | \"middle\" | \"large\";\n  tableHeaderTitle?: boolean; // 展示表格自定义标题\n  tableHeaderTitleText?: string; // 自定义标题文本内容\n  tableHeaderCustomColumns?: boolean; // 表格Header右侧自定义列\n  lineFillColor?: boolean; // 表格是否隔行变色\n  needHeaderLine?: boolean; // 是否展示默认Header\n  emptyTextStyle?: any; // 默认的替换空状态的样式\n  customRenderSearch?: (params?: any) => JSX.Element;\n}\n\nexport const DTable = (props: IDTableProps) => {\n  const [queryFormShow, setQueryFormShow] = useState(true);\n  const [filterColumns, setFilterColumns] = useState([]);\n  const [filterColumnsVisible, setFilterColumnsVisible] = useState(false);\n\n  const clickFunc = () => {\n    setQueryFormShow(!queryFormShow);\n  };\n\n  const filterTableColumns = (columns) => {\n    setFilterColumnsVisible(true);\n  };\n\n  const renderSearch = () => {\n    // if (!props?.tableHeaderSearchInput) return;\n    const { searchInputRightBtns = [], tableScreen = false, tableCustomColumns = false, showQueryForm = false } = props;\n    const {\n      placeholder = null,\n      submit,\n      width,\n      searchTrigger = \"change\",\n      searchInputType,\n      searchAttr,\n    } = props?.tableHeaderSearchInput || {};\n    return (\n      <div className={`${DTablerefix}-box-header-search`}>\n        {props?.tableHeaderSearchInput && (\n          <div>\n            {searchInputType === \"search\" ? (\n              <DSearchInput onSearch={submit} attrs={searchAttr} />\n            ) : (\n              <Input\n                placeholder={placeholder || \"请输入关键字\"}\n                style={{ width: width || 200 }}\n                onChange={(e) => searchTrigger === \"change\" && submit(e.target.value)}\n                onPressEnter={(e: any) => searchTrigger === \"enter\" && submit(e.target.value)}\n                onBlur={(e: any) => searchTrigger === \"blur\" && submit(e.target.value)}\n                suffix={<SearchOutlined style={{ color: \"#ccc\" }} />}\n              />\n            )}\n          </div>\n        )}\n        {searchInputRightBtns.length > 0 && (\n          <div className={`${DTablerefix}-box-header-search-custom`}>\n            {searchInputRightBtns.map((item, index) => {\n              if (item?.type === \"custom\") {\n                return (\n                  <span style={{ marginLeft: 10 }} className={item.className} key={index}>\n                    {item?.customFormItem || item.label}\n                  </span>\n                );\n              }\n              return item.noRefresh ? (\n                <Button type={item.type} className={item.className} key={index}>\n                  {item.label}\n                </Button>\n              ) : (\n                <Button\n                  type={item.type}\n                  disabled={item.disabled}\n                  loading={item.loading}\n                  key={index}\n                  className={item.className}\n                  onClick={item.clickFunc}\n                >\n                  {\" \"}\n                  {item.label}{\" \"}\n                </Button>\n              );\n            })}\n          </div>\n        )}\n        {showQueryForm && tableScreen && <Button style={{ marginLeft: 8 }} onClick={clickFunc} icon={<IconFont type=\"icon-shaixuan\" />} />}\n        {tableCustomColumns && (\n          <Button style={{ marginLeft: 8 }} onClick={() => filterTableColumns(columns)} icon={<IconFont type=\"icon-zidingyibiaotou\" />} />\n        )}\n      </div>\n    );\n  };\n\n  const renderTableInnerOp = (reloadFunc: any, btns?: ITableBtn[], element?: JSX.Element) => {\n    return (\n      <div className={`${DTablerefix}-box-header-btn`}>\n        {/* {reloadFunc && <ReloadOutlined className=\"reload\" onClick={reloadFunc} />} */}\n        {reloadFunc && (\n          <>\n            <div className={`${DTablerefix}-box-header-btn-reload`} onClick={reloadFunc}>\n              <IconFont className={`${DTablerefix}-box-header-btn-reload-icon`} type=\"icon-shuaxin1\" />\n            </div>\n            <span onClick={reloadFunc} style={{ margin: \"0 5px\" }}>\n              刷新列表\n            </span>\n          </>\n        )}\n        {reloadFunc && (btns?.length > 0 || element) ? (\n          isDividerHide ? (\n            <Divider type=\"vertical\" className={`${DTablerefix}-box-header-btn-divider`} />\n          ) : null\n        ) : null}\n        {btns?.map((item, index) => {\n          if (item?.type === \"custom\") {\n            return (\n              <span style={{ marginLeft: 10 }} className={item.className} key={index}>\n                {item?.customFormItem || item.label}\n              </span>\n            );\n          }\n          return item.noRefresh ? (\n            <Button className={item.className} key={index}>\n              {item.label}\n            </Button>\n          ) : (\n            <Button\n              style={{ marginLeft: 8 }}\n              type={item.type || \"primary\"}\n              disabled={item.disabled}\n              loading={item.loading}\n              key={index}\n              className={item.className}\n              onClick={item.clickFunc}\n            >\n              {\" \"}\n              {item.label}{\" \"}\n            </Button>\n          );\n        })}\n        {element}\n      </div>\n    );\n  };\n\n  const renderTitle = (title, type = \"icon-shezhi1\", size = \"16px\") => {\n    return (\n      <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\" }}>\n        {title}\n        <IconFont style={{ fontSize: size }} onClick={filterTableColumns} type={type} />\n      </div>\n    );\n  };\n\n  const renderColumns = (columns: ITableColumnsType[]) => {\n    return columns\n      .filter((item) => !item.invisible)\n      .map((currentItem: ITableColumnsType) => {\n        const newClassName = currentItem.lineClampTwo\n          ? currentItem.className\n            ? `line_clamp_two ${currentItem.className}`\n            : \"line_clamp_two\"\n          : currentItem.lineClampOne\n          ? currentItem.className\n            ? `line_clamp_one ${currentItem.className}`\n            : \"line_clamp_one\"\n          : \"\";\n        return {\n          ...currentItem,\n          title: currentItem?.filterTitle && tableId ? renderTitle(currentItem?.title, currentItem?.titleIconType) : currentItem?.title,\n          className: newClassName,\n          showSorterTooltip: false,\n          onCell: () => {\n            return {\n              style: {\n                maxWidth: currentItem.width,\n              },\n            };\n          },\n          render: (...args) => {\n            const value = args[0];\n            const renderData = currentItem.render ? (\n              <span>{currentItem.render(...args)}</span>\n            ) : value === \"\" || value === null || value === undefined ? (\n              \"-\"\n            ) : (\n              <span>{value}</span>\n            );\n            return currentItem.needTooltip ? (\n              <Tooltip placement={currentItem.tooltipPlace || \"bottomLeft\"} title={currentItem.tooltipNode || renderData}>\n                <span>{renderData}</span>\n              </Tooltip>\n            ) : (\n              renderData\n            );\n          },\n        };\n      });\n  };\n\n  const {\n    rowKey,\n    loading,\n    dataSource,\n    columns,\n    paginationProps = pagination,\n    noPagination,\n    reloadData,\n    isDividerHide = true,\n    getOpBtns = () => [],\n    customRenderSearch,\n    getJsxElement = () => <></>,\n    attrs,\n    showHeader = true,\n    showQueryForm,\n    queryFormProps,\n    tableId = null,\n    customLocale,\n    tableHeaderTitle = false,\n    tableHeaderTitleText = \"\",\n    tableHeaderCustomColumns = true,\n    filterModalSize = \"small\",\n    lineFillColor = true,\n    needHeaderLine = true,\n    emptyTextStyle = { height: \"300px\" },\n  } = props;\n\n  // const newTableId = `${rowKey}-${tableId}`;\n\n  useEffect(() => {\n    if (tableId && Utils.getLocalStorage(tableId)) {\n      const invisibleColumns = Utils.getLocalStorage(tableId);\n\n      const newFilterColumns = columns.map((item) => {\n        return {\n          ...item,\n          invisible: invisibleColumns.includes(item.dataIndex || item.key),\n        };\n      });\n\n      setFilterColumns(newFilterColumns);\n    } else {\n      setFilterColumns(columns);\n    }\n  }, [columns]);\n\n  const renderCustomTitle = () => {\n    return (\n      <div className=\"line-custom-title\">\n        <div className=\"line-custom-title-left\">\n          <div className=\"line-custom-title-left-text\">{tableHeaderTitleText || \"基础配置信息\"}</div>\n          {needHeaderLine && <div className=\"line-custom-title-left-line\"></div>}\n        </div>\n        {tableHeaderCustomColumns && (\n          <div className=\"line-custom-title-right\">\n            <Button style={{ marginLeft: 8 }} onClick={() => filterTableColumns(columns)} icon={<IconFont type=\"icon-zidingyibiaotou\" />} />\n          </div>\n        )}\n      </div>\n    );\n  };\n\n  const rowLineFillColor = (r, i) => {\n    // 自定义行类名\n    return i % 2 === 0 ? \"\" : \"line-fill-color\";\n  };\n\n  return (\n    <>\n      <ConfigProvider locale={antdZhCN as any}>\n        <div className={`${DTablerefix}`}>\n          <div className={`${DTablerefix}-box`}>\n            {showHeader && (\n              <div className={`${DTablerefix}-box-header`}>\n                {renderTableInnerOp(reloadData, getOpBtns(), getJsxElement())}\n                {customRenderSearch ? customRenderSearch() : renderSearch()}\n              </div>\n            )}\n            {showQueryForm && (\n              <div className={`${DTablerefix}-box-query`}>\n                <QueryForm onCollapse={() => setQueryFormShow(false)} {...queryFormProps} />\n              </div>\n            )}\n            <Table\n              locale={{\n                emptyText: loading ? <div style={{ ...emptyTextStyle }}></div> : null,\n                ...attrs?.locale,\n              }}\n              loading={loading}\n              rowKey={rowKey}\n              dataSource={dataSource}\n              columns={renderColumns(filterColumns)}\n              pagination={!noPagination ? { ...pagination, ...paginationProps } : false}\n              {...{\n                title: tableHeaderTitle && renderCustomTitle,\n                rowClassName: lineFillColor && rowLineFillColor,\n                ...attrs,\n              }}\n            />\n            {columns.length > 0 && (\n              <FilterTableColumns\n                {...{\n                  columns: filterColumns,\n                  setFilterColumns,\n                  visible: filterColumnsVisible,\n                  setVisible: setFilterColumnsVisible,\n                  tableId,\n                  modalSize: filterModalSize,\n                }}\n              />\n            )}\n          </div>\n        </div>\n      </ConfigProvider>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProTable/DTable/readme.md",
    "content": "# dtable\n\n## 何时使用 \n\n- 当有大量结构化的数据需要展现时；\n- 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。  \n\n## API\n\n| 参数                   | 说明                                                         | 类型                                                         | 默认值     |\n| ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ---------- |\n| paginationProps        | 分页器，参考[配置项](https://ant.design/components/table-cn/#pagination)或 [pagination](https://ant.design/components/pagination-cn/) 文档，设为 false 时不展示和进行分页 | object                                                       |            |\n| rowKey                 | 表格行 key 的取值，可以是字符串或一个函数(必填)              | string \\|function(record): string                            | key        |\n| columns                | 表格列的配置描述，具体项见下表(必填)                         | [ColumnsType](https://ant.design/components/table-cn/#Column)[] |            |\n| dataSource             | 数据数组(必填)                                               | object[]                                                     |            |\n| loading                | 页面是否加载中                                               | boolean \\| [Spin Props](https://ant.design/components/spin-cn/#API) | false      |\n| attrs                  | Table 其他的的一些扩展属性，参考 [Table API](https://ant.design/components/table-cn/#API) | object                                                       |            |\n| reloadData             | 点击刷新图标后执行的函数                               | (params?: object) => any                                     |            |\n| getOpBtns              | 需要显示的功能按钮                                           | (params?: object) => ITableBtn[];                            | () => null |\n| renderInnerOperation   | 自定义的 JSX 元素                                            | (params?: object) => JSX.Element                             | () => null |\n| tableHeaderSearchInput | 如果存在显示搜索框                                           | ISearchInput                     |            |\n\n## paginationProps\n\n分页的配置项\n\n| 参数     | 说明                                                         | 类型  | 默认值          |\n| -------- | ------------------------------------------------------------ | ----- | --------------- |\n| position | 指定分页显示的位置， 取值为指定分页显示的位置， 取值为`topLeft` |`topCenter` |`topRight` |`bottomLeft` |`bottomCenter` |`bottomRight` | Array | [`bottomRight`] |\n\n## ITableBtn\n\n| 参数       | 说明                                                      | 类型                 | 默认值 |\n| ---------- | --------------------------------------------------------- | -------------------- | ------ |\n| label      | 按钮中显示的文字                                          | string \\|JSX.Element |        |\n| isOpenUp   | 如果为 true 直接返回带有文字提示的禁用按钮                | boolean              |        |\n| className  | 如果 isOpenUp 为 false 是按钮的类名                       | string               |        |\n| noRefresh  | 如果为 false 返回带有点击事件、loading 和 disabled 的按钮 | boolean              |        |\n| disabled   | 如果 noRefresh 为 false 时生效，是否禁用按钮              | boolean              |        |\n| loading    | 如果 noRefresh 为 false 时生效，是否开启loading效果       | boolean              |        |\n| iclickFunc | 如果 noRefresh 为 false 时生效，是否开启loading效果       | () =>void            |        |\n\n## ISearchInput\n\n| 参数        | 说明                                               | 类型                     | 默认值       |\n| ----------- | -------------------------------------------------- | ------------------------ | ------------ |\n| submit      | 点击搜索图标、清除图标，或按下回车键时的回调(必填) | (params?: any) => any |              |\n| text        | 搜索框描述                                         | string                   |              |\n| placeholder | 属性提供可描述输入字段预期值的提示信息             | string                   | 请输入关键字 |\n\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProTable/RenderTableOpts/index.less",
    "content": ".table-operation {\n  width: 240px;\n  > span {\n      cursor: pointer;\n  }\n  > span + span {\n    margin-left: 16px;\n  }\n}\n.table-dropdown-btns {\n  background-color: #fff;\n  font-size: 14px;\n  border: 1px solid #ebedef;\n  box-shadow: 0 0 2px 0 rgba(12, 25, 52, 0.02), 0 0 8px 0 rgba(104, 126, 154, 0.12);\n  border-radius: 2px;\n\n  li {\n    width: 94px;\n    height: 32px;\n    line-height: 32px;\n    box-sizing: border-box;\n    padding-left: 12px;\n    padding-right: 20px;\n    text-align: left;\n    font-size: 12px;\n    color: #374053;\n    cursor: pointer;\n    &:hover {\n      background: #f1f7ff;\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProTable/RenderTableOpts/index.tsx",
    "content": "import React from \"react\";\nimport { Popconfirm, Divider, Dropdown } from \"antd\";\nimport { EllipsisOutlined } from '@ant-design/icons'\nimport './index.less'\nexport interface ITableBtn {\n  clickFunc?: (params?: any) => void;\n  type?: string;\n  customFormItem?: string | JSX.Element;\n  isRouterNav?: boolean;\n  label: string | JSX.Element;\n  className?: string;\n  needConfirm?: boolean;\n  aHref?: string;\n  confirmText?: string;\n  noRefresh?: boolean;\n  loading?: boolean;\n  disabled?: boolean;\n  invisible?: boolean;\n}\n\ninterface IMoreBtnsProps {\n  btns: ITableBtn[];\n  data: object;\n}\n\nexport const MoreBtns = (props: IMoreBtnsProps) => {\n  const { btns, data } = props;\n  const btnsMenu = (\n    <ul className=\"table-dropdown-btns\">\n      {btns.map((v, index) => {\n        if (v.invisible) return null;\n\n        if (v.isRouterNav) {\n          return (\n            <li key={index} className=\"epri-theme\">\n              {v.label}\n            </li>\n          );\n        }\n\n        // if (v.needTooltip) {\n        //   return (\n        //     <Tooltip placement=\"topLeft\" title={v.tooltipText ? v.tooltipText : '更多功能请关注商业版'}>\n        //       <span key={index}><a style={{ color: '#00000040' }}>{v.label}</a></span>\n        //     </Tooltip>\n        //   )\n        // }\n\n        if (v.clickFunc) {\n          return (\n            <li key={index} onClick={() => v.clickFunc(data)} className=\"epri-theme\">\n              <a>{v.label}</a>\n            </li>\n          );\n        }\n        return (\n          <li key={index} className=\"epri-theme\">\n            <a>{v.label}</a>\n          </li>\n        );\n      })}\n    </ul>\n  );\n  return (\n    <Dropdown\n      overlay={btnsMenu}\n      trigger={['click', 'hover']}\n      placement=\"bottomLeft\"\n    >\n      <span>\n        <a >更多</a>\n        {/* <EllipsisOutlined style={{ color: '#1473FF' }} /> */}\n      </span>\n    </Dropdown>\n  );\n};\n\n\nexport const renderTableOpts = (btns: ITableBtn[], record: any) => {\n  btns = btns.filter(item => !item.invisible)\n  const freeBtns = btns.length <= 3 ? btns : [].concat(btns).splice(0, 2);\n  const moreBtns = [].concat(btns).splice(2);\n\n  if (!freeBtns.length) {\n    return <>-</>;\n  }\n\n  return (\n    <>\n      <span className={`table-operation`}>\n        {freeBtns.map((item, index) => {\n          const getVerticalLine = () => {\n            if (index < 1) return;\n            return <></>\n            // return <Divider type=\"vertical\" style={{ height: \"12px\", background: \"#DCDFE6\", margin: \"0 10px\" }} />;\n          };\n\n          if (item.isRouterNav) {\n            return (\n              <span key={index}>\n                {getVerticalLine()}\n                <span>{item.label}</span>\n              </span>\n            );\n          }\n\n          if (item.needConfirm) {\n            return (\n              <Popconfirm\n                disabled={item.disabled}\n                key={index}\n                title={`确认${item.confirmText}?`}\n                onConfirm={() => (item as { clickFunc: (record: any) => void }).clickFunc(record)}\n                okText=\"确认\"\n                cancelText=\"取消\"\n              >\n                {getVerticalLine()}\n                <a type=\"javascript;\">{item.label}</a>\n              </Popconfirm>\n            );\n          }\n\n          if (item.clickFunc) {\n            return (\n              <span key={index}>\n                {getVerticalLine()}\n                <a type=\"javascript;\" key={index} onClick={() => (item as { clickFunc: (record: any) => void }).clickFunc(record)}>\n                  {item.label}\n                </a>\n              </span>\n            );\n          }\n\n          return (\n            <span key={index}>\n              {getVerticalLine()}\n              <a>{item.label}</a>\n            </span>\n          );\n        })}\n\n\n        {btns.length > 3 ? <MoreBtns btns={moreBtns} data={record} /> : null}\n      </span>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProTable/XTable/index.less",
    "content": ".pro-table-container {\n  .container-query {\n    width: 100%;\n    // background: #fff;\n    // .dantd-query-form-option {\n    //   .ant-form-item-control-input-content {\n    //     text-align: right;\n    //   }\n    // }\n  }\n  .container-table {\n    .ant-table-thead {\n      tr th {\n        white-space: nowrap;\n      }\n    }\n    .ant-table-filter-column {\n      line-height: 100%;\n      .ant-table-filter-column-title {\n        flex-grow: 0;\n        padding-right: 5px;\n      }\n      .ant-table-filter-trigger-container {\n        position: relative;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProTable/XTable/index.tsx",
    "content": "import React from \"react\";\nimport { IQueryFormProps } from \"../../QueryForm\";\nimport { IDTableProps, DTable } from \"../DTable\";\nimport { Select } from \"knowdesign\";\nimport { IconFont } from \"@knowdesign/icons\";\n\ninterface MiniSelectInterface extends React.FC<any> {\n  Option: typeof Select.Option;\n}\n\ninterface ITableExtendProps extends IDTableProps {\n  isCustomPg?: boolean; // 是否展示自定义分页器样式 -- true\n  pgSelectComponentText?: string; // 分页下拉左侧展示文案\n  pgCustomSelectComponent?: () => any; // 展示自定义分页下拉框\n  selectComponentIcon?: string; // 自定义分页下拉框Icon -- 'icon-xiala'\n}\n\nexport default function ProTable<T>(props: { showQueryForm?: boolean; queryFormProps?: IQueryFormProps; tableProps: ITableExtendProps }) {\n  const { showQueryForm = false, queryFormProps, tableProps } = props;\n  const { pgSelectComponentText = \"\", pgCustomSelectComponent, selectComponentIcon = \"icon-xiala\", isCustomPg = true } = tableProps;\n  const SelectComponent: MiniSelectInterface = (props) => {\n    return (\n      <>\n        <span>{pgSelectComponentText || \"\"}</span>\n        <Select bordered={false} suffixIcon={<IconFont type={selectComponentIcon} />} {...props} />\n      </>\n    );\n  };\n\n  SelectComponent.Option = Select.Option;\n\n  const customPg = isCustomPg\n    ? {\n        locale: {\n          items_per_page: \"/页\",\n        },\n        selectComponentClass: SelectComponent,\n        className: \"pro-table-pagination-custom\",\n      }\n    : null;\n\n  const pagination = {\n    ...customPg,\n    ...tableProps.paginationProps,\n    // className: `${isCustomPg ? customPg.className : \"\"}${\n    //   tableProps?.paginationProps?.className ? \" \" + tableProps?.paginationProps?.className : \"\"\n    // }`,\n  };\n\n  return (\n    <div className=\"pro-table-container\">\n      {/* {showQueryForm && (\n        <div className=\"container-query\">\n          <QueryForm {...queryFormProps} />\n        </div>\n      )} */}\n      <div className=\"container-table\">\n        <DTable {...{ ...tableProps, paginationProps: pagination }} showQueryForm={showQueryForm} queryFormProps={queryFormProps} />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/ProTable/index.tsx",
    "content": "import XTable from \"./XTable\";\nimport { DTable } from \"./DTable\";\nexport { DTable };\nexport default XTable;\n"
  },
  {
    "path": "arius-console/src/d1-packages/QueryForm/QueryForm.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport classNames from \"classnames\";\nimport { ConfigProviderProps } from \"antd/es/config-provider\";\nimport useAntdMediaQuery from \"./use-media-antd-query\";\nimport { Button, Input, Form, Row, Col, Select, ConfigProvider, DatePicker, TimePicker } from \"knowdesign\";\nimport { IconFont } from \"@knowdesign/icons\";\n\nimport { useContext } from \"react\";\nimport IntlContext from \"./context\";\n\nconst { RangePicker: DateRangePicker } = DatePicker;\nconst { RangePicker: TimeRangePicker } = TimePicker;\n\nfunction useIntl(): any {\n  const i18n = useContext(IntlContext);\n  return i18n;\n}\n\ndeclare const ItemSizes: [\"large\", \"default\", \"small\", string];\nexport declare type ItemSize = typeof ItemSizes[number];\n\ndeclare const ColumnTypes: [\"select\", \"input\", \"datePicker\", \"dateRangePicker\", \"timePicker\", \"timeRangePicker\", \"custom\", string];\nexport declare type ColumnType = typeof ColumnTypes[number];\n\ndeclare const ModeTypes: [\"full\", \"align\", string];\nexport declare type ModeType = typeof ModeTypes[number];\n\ndeclare const ColTypes: [\"grid\", \"style\", string];\nexport declare type ColType = typeof ColTypes[number];\n\nconst FormItem = Form.Item;\nconst { Option } = Select;\n\nexport interface IColumnsType {\n  type: ColumnType;\n  dataIndex: string;\n  title: string | React.ReactNode;\n  placeholder?: string | string[];\n  valuePropName?: string;\n  required?: boolean;\n  colStyle?: React.CSSProperties;\n  isInputPressEnterCallSearch?: boolean;\n  size?: ItemSize;\n  rules?: any[]; // 校验规则\n  component?: React.ReactNode;\n  componentProps?: any; // 需要传给组件的其他属性\n  selectMode?: string; // 单选或者多选\n  options?: {\n    title: string;\n    value: string | number;\n  }[];\n  formItemLayout?: any;\n}\nexport interface FieldData {\n  name?: string;\n  level?: string;\n  status?: string[];\n  number?: Number;\n}\n\nexport interface IQueryFormProps {\n  layout?: \"vertical\" | \"horizontal\" | \"inline\";\n  totalNumber?: number;\n  onCollapse?: () => void | false;\n  prefixCls?: string;\n  className?: string;\n  style?: React.CSSProperties | any;\n  mode?: ModeType;\n  colMode?: ColType;\n  defaultColStyle?: React.CSSProperties;\n  columnStyleHideNumber?: number;\n  columns: IColumnsType[];\n  searchText?: string | React.ReactNode;\n  resetText?: string | React.ReactNode;\n  showOptionBtns?: boolean;\n  showCollapseButton?: boolean;\n  onChange?: (data: any) => any;\n  initialValues?: any;\n  onSearch?: (data: any) => any;\n  onReset?: (data: any) => any;\n  getFormInstance?: (form: any) => any;\n  isResetClearAll?: boolean;\n  isTrimOnSearch?: boolean;\n  antConfig?: ConfigProviderProps;\n  defaultCollapse?: boolean;\n  colConfig?:\n    | {\n        lg?: number;\n        md?: number;\n        xxl?: number;\n        xl?: number;\n        sm?: number;\n        xs?: number;\n      }\n    | undefined;\n}\n\nconst defaultColConfig = {\n  xs: 6,\n  sm: 6,\n  md: 6,\n  lg: 6,\n  xl: 6,\n  xxl: 6,\n};\n\nconst defaultFormItemLayout = {\n  labelCol: {\n    xs: { span: 5 },\n    sm: { span: 5 },\n    md: { span: 7 },\n    lg: { span: 7 },\n    xl: { span: 8 },\n    xxl: { span: 8 },\n  },\n  wrapperCol: {\n    xs: { span: 19 },\n    sm: { span: 19 },\n    md: { span: 17 },\n    lg: { span: 17 },\n    xl: { span: 16 },\n    xxl: { span: 16 },\n  },\n};\n\n/**\n * 合并用户和默认的配置\n *\n * @param span\n * @param size\n */\nconst getSpanConfig = (span: number | typeof defaultColConfig, size: keyof typeof defaultColConfig): number => {\n  if (typeof span === \"number\") {\n    return span;\n  }\n  const config = {\n    ...defaultColConfig,\n    ...span,\n  };\n  return config[size];\n};\n\n/**\n * 获取最后一行的 offset，保证在最后一列\n *\n * @param length\n * @param span\n */\nconst getOffset = (length: number, span: number = 8) => {\n  const cols = 24 / span;\n  return (cols - (length % cols)) * span;\n};\n\nconst getCollapseHideNum = (size: number) => {\n  const maps = {\n    6: 6,\n    8: 6,\n    12: 6,\n    24: 6,\n  } as { [key: number]: number };\n\n  return maps[size] || 1;\n};\n\nconst QueryForm = (props: IQueryFormProps) => {\n  const prefixCls = `${props.prefixCls || \"dantd\"}-query-form`;\n  const { t } = useIntl();\n  const {\n    layout = \"vertical\",\n    onCollapse,\n    className,\n    style,\n    colConfig,\n    searchText = \"查询\",\n    resetText = \"清空\",\n    showOptionBtns = true,\n    showCollapseButton = true,\n    defaultCollapse = false,\n    isResetClearAll = false,\n    isTrimOnSearch = true,\n    onChange,\n    onSearch,\n    onReset,\n    getFormInstance,\n    columns = [] as IColumnsType[],\n    mode = \"full\",\n    colMode = \"grid\",\n    columnStyleHideNumber = 1,\n    defaultColStyle = {\n      width: \"130px\",\n    },\n    initialValues,\n    totalNumber,\n  } = props;\n  const [form] = Form.useForm();\n  const wrapperClassName = classNames(prefixCls, className);\n  const formItemCls = classNames({\n    [`${prefixCls}-formitem`]: true,\n    [`${prefixCls}-formitem-full`]: mode === \"full\",\n  });\n  const windowSize = useAntdMediaQuery();\n  const itemColConfig = { ...defaultColConfig, ...colConfig } || defaultColConfig;\n  const [colSize, setColSize] = useState(getSpanConfig(itemColConfig || 8, windowSize));\n  const { validateFields, getFieldsValue, resetFields, setFieldsValue } = form;\n\n  const [collapsed, setCollapse] = useState(defaultCollapse);\n  const [isShowCollapseButton, setIsShowCollapseButton] = useState(true);\n\n  useEffect(() => {\n    setColSize(getSpanConfig(itemColConfig || 8, windowSize));\n    if (columns.length <= getCollapseHideNum(getSpanConfig(itemColConfig || 8, windowSize))) {\n      setIsShowCollapseButton(false);\n    } else {\n      setIsShowCollapseButton(true);\n    }\n  }, [windowSize]);\n\n  useEffect(() => {\n    if (getFormInstance) {\n      getFormInstance(form);\n    }\n  }, []);\n\n  const collapseHideNum = getCollapseHideNum(getSpanConfig(itemColConfig || 8, windowSize));\n\n  const handleSearch = () => {\n    validateFields()\n      .then((values) => {\n        if (onSearch) {\n          isTrimOnSearch ? handleTrimSearch(values) : onSearch(values);\n        }\n      })\n      .catch(() => {\n        //\n      });\n  };\n\n  const handleTrimSearch = (values = {}) => {\n    const data = {};\n    Object.keys(values).forEach((key) => {\n      if (typeof values[key] === \"string\") {\n        data[key] = values[key].trim();\n      } else {\n        data[key] = values[key];\n      }\n    });\n    onSearch(data);\n  };\n\n  const handleReset = () => {\n    if (isResetClearAll) {\n      const resetFieldsObj = columns.reduce((acc, cur: IColumnsType) => {\n        return {\n          ...acc,\n          [cur.dataIndex]: undefined,\n        };\n      }, {});\n      setFieldsValue(resetFieldsObj);\n      (onChange as any)?.(initialValues);\n    } else {\n      resetFields();\n      (onChange as any)?.({});\n    }\n\n    setTimeout(() => {\n      if (onReset) {\n        onReset(getFieldsValue());\n      }\n    });\n  };\n\n  const handlePressEnter = () => {\n    handleSearch();\n  };\n\n  const renderInputItem = (colItem: any) => {\n    const {\n      dataIndex,\n      title,\n      required,\n      componentProps = {},\n      placeholder,\n      isInputPressEnterCallSearch = true,\n      formItemLayout,\n      rules,\n      size = \"default\",\n    } = colItem;\n\n    const itemPlaceholder = placeholder ? placeholder : t(\"form.placeholder.prefix\");\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n    return (\n      <FormItem\n        shouldUpdate={true}\n        key=\"input\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={layout == \"inline\" ? \"\" : title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        <Input\n          data-testid=\"field-input\"\n          size={size}\n          placeholder={layout == \"inline\" ? title.split(\":\")[0] : itemPlaceholder}\n          onPressEnter={isInputPressEnterCallSearch ? handlePressEnter : () => {}}\n          {...componentProps}\n        />\n      </FormItem>\n    );\n  };\n\n  const renderSelectItem = (colItem: any) => {\n    const {\n      dataIndex,\n      title,\n      required,\n      placeholder,\n      selectMode = \"single\",\n      rules,\n      formItemLayout,\n      options = [],\n      componentProps = {},\n      size = \"default\",\n      isSelectPressEnterCallSearch = true,\n    } = colItem;\n    const itemPlaceholder = placeholder ? (\n      placeholder\n    ) : (\n      <>\n        {t(\"form.selectplaceholder.prefix\")}\n        &nbsp;\n        {title}\n      </>\n    );\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n    const handlePressEnter = (e) => {\n      if (e.keyCode === 13) {\n        handleSearch();\n      }\n    };\n    return (\n      <FormItem\n        key=\"select\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={layout == \"inline\" ? \"\" : title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        <Select\n          suffixIcon={<IconFont style={{ pointerEvents: \"none\" }} type=\"icon-xia\" />}\n          data-testid=\"select\"\n          mode={selectMode}\n          size={size}\n          allowClear\n          placeholder={layout == \"inline\" ? title.split(\":\")[0] : itemPlaceholder}\n          showSearch={true}\n          optionFilterProp=\"children\"\n          style={{ width: \"100%\" }}\n          onInputKeyDown={isSelectPressEnterCallSearch ? handlePressEnter : () => {}}\n          onSelect={handleSearch}\n          onClear={handleSearch}\n          filterOption={(val, option) => {\n            return option.children.includes(val.trim());\n          }}\n          {...componentProps}\n        >\n          {options.map((option: any) => {\n            return (\n              <Option data-testid=\"select-option\" value={option.value} key={option.value}>\n                {option.title}\n              </Option>\n            );\n          })}\n        </Select>\n      </FormItem>\n    );\n  };\n\n  const renderDateItem = (colItem: any) => {\n    const { dataIndex, title, required, componentProps = {}, placeholder, formItemLayout, rules, size = \"default\", type } = colItem;\n\n    const itemPlaceholder = placeholder ? placeholder : t(\"form.placeholder.prefix\");\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n    return (\n      <FormItem\n        shouldUpdate={true}\n        key=\"date\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={layout == \"inline\" ? \"\" : title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        {type === \"dateRangePicker\" ? (\n          <DateRangePicker\n            data-testid=\"dateRangePicker\"\n            size={size}\n            allowClear\n            showTime\n            placeholder={layout == \"inline\" ? title.split(\":\")[0] : itemPlaceholder}\n            // style={{ width: '100%' }}\n            suffixIcon={<IconFont type=\"icon-riqi\" style={{ color: \"#74788D\" }} />}\n            {...componentProps}\n          />\n        ) : (\n          <DatePicker\n            data-testid=\"datePicker\"\n            size={size}\n            allowClear\n            placeholder={itemPlaceholder}\n            style={{ width: \"100%\" }}\n            {...componentProps}\n          ></DatePicker>\n        )}\n      </FormItem>\n    );\n  };\n\n  const renderTimeItem = (colItem: any) => {\n    const { dataIndex, title, required, componentProps = {}, placeholder, formItemLayout, rules, size = \"default\", type } = colItem;\n\n    const itemPlaceholder = placeholder ? placeholder : t(\"form.placeholder.prefix\");\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n    return (\n      <FormItem\n        shouldUpdate={true}\n        key=\"date\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={layout == \"inline\" ? \"\" : title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        {type === \"timeRangePicker\" ? (\n          <TimeRangePicker\n            data-testid=\"timerRangePicker\"\n            size={size}\n            allowClear\n            showTime\n            placeholder={layout == \"inline\" ? title.split(\":\")[0] : itemPlaceholder}\n            style={{ width: \"100%\" }}\n            {...componentProps}\n          />\n        ) : (\n          <TimePicker\n            data-testid=\"timePicker\"\n            size={size}\n            allowClear\n            placeholder={layout == \"inline\" ? title.split(\":\")[0] : itemPlaceholder}\n            style={{ width: \"100%\" }}\n            {...componentProps}\n          ></TimePicker>\n        )}\n      </FormItem>\n    );\n  };\n\n  const renderCustomItem = (colItem: any) => {\n    const { formItemLayout, dataIndex, title, required, placeholder, rules, valuePropName = \"value\", component } = colItem;\n\n    const itemPlaceholder = placeholder ? (\n      placeholder\n    ) : (\n      <>\n        {t(\"form.placeholder.prefix\")}\n        &nbsp;\n        {title}\n      </>\n    );\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n\n    return (\n      <FormItem\n        key=\"custom\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={layout == \"inline\" ? \"\" : title}\n        valuePropName={valuePropName}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        {component}\n      </FormItem>\n    );\n  };\n\n  const renderOptionBtns = () => {\n    const offsetVal = collapsed\n      ? columns.length <= collapseHideNum\n        ? getOffset(columns.length, colSize)\n        : getOffset(collapseHideNum, colSize)\n      : getOffset(columns.length, colSize);\n    let optionStyle = {};\n    let isEmptyStyle = columns.length < 4 ? {} : { justifyContent: \"flex-end\" };\n\n    if (colMode === \"style\") {\n      optionStyle = defaultColStyle;\n    }\n    if (layout == \"inline\") {\n      return null;\n    }\n    return (\n      <Col\n        // {...colConfig}\n        offset={offsetVal}\n        span={offsetVal}\n        key=\"option\"\n        className={`${prefixCls}-option`}\n        style={{\n          display: \"flex\",\n          alignItems: \"flex-end\",\n          marginLeft: 0,\n          flex: 1,\n          ...isEmptyStyle,\n          ...optionStyle,\n        }}\n      >\n        <Form.Item key=\"option\">\n          <span>\n            {columns.length >= 4 && <a onClick={handleReset}>{resetText || t(\"queryform.reset\")}</a>}\n            <Button ghost onClick={handleSearch} style={{ marginLeft: 10, width: 80 }} type=\"primary\" htmlType=\"submit\">\n              {searchText || t(\"queryform.search\")}\n            </Button>\n            {isShowCollapseButton && showCollapseButton && (\n              <a\n                style={{\n                  marginLeft: 10,\n                  display: \"inline-block\",\n                }}\n                onClick={() => {\n                  onCollapse ? onCollapse() : setCollapse(!collapsed);\n                }}\n              >\n                {collapsed ? \"展开\" : \"收起\"}\n                {/* TODO  接入组件库后替换  */}\n                <IconFont\n                  type=\"icon-a-xialaIcon\"\n                  style={{\n                    marginLeft: 8,\n                    transform: collapsed ? \"rotate(180deg)\" : \"none\",\n                    transition: \"transform 0.3s\",\n                  }}\n                />\n              </a>\n            )}\n          </span>\n        </Form.Item>\n      </Col>\n    );\n  };\n\n  return (\n    <ConfigProvider {...props.antConfig}>\n      <div className={wrapperClassName} style={style}>\n        <Row gutter={10} justify=\"start\">\n          {columns.map((colItem, colIndex) => {\n            // 操作记录有7个筛选\n            let itemHide = collapsed && collapseHideNum < colIndex;\n            let colItemStyle = {};\n            let colConfig = colMode !== \"style\" ? itemColConfig : {};\n            if (colMode === \"style\") {\n              colItemStyle = colItem.colStyle || defaultColStyle;\n              // if (collapsed && colIndex >= columnStyleHideNumber) {\n              //   itemHide = true;\n              // }\n            }\n            colItemStyle = {\n              ...colItemStyle,\n              display: itemHide ? \"none\" : \"block\",\n            };\n            return (\n              <Col style={colItemStyle} key={`query-form-col-${colItem.dataIndex}-${colIndex}`} {...colConfig}>\n                <Form\n                  form={form}\n                  onFieldsChange={(_changedFields, allFields) => {\n                    (onChange as any)?.(allFields);\n                  }}\n                  initialValues={initialValues}\n                  layout={layout}\n                >\n                  {colItem.type === \"input\" && renderInputItem(colItem)}\n                  {colItem.type === \"select\" && renderSelectItem(colItem)}\n                  {colItem.type === \"datePicker\" && renderDateItem(colItem)}\n                  {colItem.type === \"dateRangePicker\" && renderDateItem(colItem)}\n                  {colItem.type === \"timePicker\" && renderTimeItem(colItem)}\n                  {colItem.type === \"timeRangePicker\" && renderTimeItem(colItem)}\n                  {colItem.type === \"custom\" && renderCustomItem(colItem)}\n                </Form>\n              </Col>\n            );\n          })}\n          {showOptionBtns && renderOptionBtns()}\n        </Row>\n        {layout == \"inline\" && totalNumber ? <div className={`${prefixCls}-result`}>共&nbsp;{totalNumber}&nbsp;条结果</div> : null}\n      </div>\n    </ConfigProvider>\n  );\n};\n\nexport default QueryForm;\n"
  },
  {
    "path": "arius-console/src/d1-packages/QueryForm/context.tsx",
    "content": "import { createContext } from 'react';\n\ninterface IContextProps {\n  t: (key: any) => any;\n}\n\n\nconst IntlContext = createContext<IContextProps>({\n  t: (key) => '展开',\n});\n\nexport default IntlContext;\n"
  },
  {
    "path": "arius-console/src/d1-packages/QueryForm/index.tsx",
    "content": "import \"./style/index.less\";\nimport QueryForm, { IQueryFormProps } from \"./QueryForm\";\nexport { IQueryFormProps };\nexport default QueryForm;\n"
  },
  {
    "path": "arius-console/src/d1-packages/QueryForm/readme.md",
    "content": "# query-form\n\n## 何时使用\n\n需要一个数据查询组件时使用，组件会自己管理状态并返回查询的数据。\n\n## API\n\n\n### QueryForm\n\n| 参数       | 说明           | 类型                | 默认值 |\n| :--------- | :------------- | :------------------ | :----- |\n| columns | 表单列的配置描述，具体项见下表（必填） | ColumnProps | []     |\n| initialValues | 表单默认值，只有初始化时生效 | object | -     |\n| searchText | 搜索按钮的文案 | string \\| React.ReactNode | 查询     |\n| resetText | 重置按钮的文案 | string \\| React.ReactNode | 重置     |\n| mode      | `FormItem` 的标题展示模式，`full`是占满整行，左对齐； `align` 会根据标题右对齐 | `['full', 'align']`              | `'full'`     |\n| colMode      | `FormItem` 的展示模式，`grid`是等分的栅格布局； `style` 会根据会对每个 `Col` 增加固定 `300px` 的宽度，也可以通过 `Column.colStyle` 自定义宽度等样式 | `['grid', 'style']`              | `'grid'`     |\n| showOptionBtns | 是否展示右下角的「查询」「重置」按钮，以及「展开」「收起」 | boolean | true      |\n| showCollapseButton | 是否展示右下角的「展开」「收起」 | boolean | true     |\n| onChange | 表单的值改变时触发的回调 | Function(values, form) | - |\n| onSearch | 点击查询按钮的回调 | Function(values, form) | - |\n| onReset | 点击重置按钮的回调 | Function(form) | - |\n| isResetClearAll | 点击重置时，是清空form里面的值，还是根据 `initialValue` 重置 | boolean | false     |\n| getFormInstance | 只用来获取Form实例的回调 | Function(form) | - |\n| defaultCollapse | 是否默认「展开」 | boolean | true     |\n| colConfig | Col 布局配置 | `{lg:number;md:number;xxl:number;xl:number;sm:number;xs:number}` | `{xs:24,sm:24,md:12,lg:12,xl:8,xxl:6}` |\n| antConfig | 使用 `Antd ConfigProvider` 进行的全局配置，需要通过这个属性传进来 | [ConfigProviderProps](https://github.com/ant-design/ant-design/blob/master/components/config-provider/index.tsx) | - |\n\n### Columns\n\n表单列的配置描述，目前支持 `['input', 'select', 'custom']` 这三种。\n\n| 参数       | 说明           | 类型                | 默认值 |\n| :--------- | :------------- | :------------------ | :----- |\n| type      | 动态表单组件的类型，内置 `input`, `select`；也可以自定义  | `['input', 'select', 'custom']`              | -      |\n| title      | 标题    | string              |  -      |\n| dataIndex      | form表单的唯一标识，不可以重复   | string              |  -      |\n| placeholder | 占位文案，默认会根据 `title` 自动生成 | string | -     |\n| isInputPressEnterCallSearch | 输入框按回车的时候，触发搜索 | boolean | -     |\n| valuePropName | 子节点的值的属性，如 Switch 的是 'checked' | string | 'value'    |\n| required | 是否对参数进行必填校验 | boolean | true      |\n| colStyle | `colMode='style'` 时，可以设置单个 `Column` 的样式| `React.CSSProperties` | -      |\n| columnStyleHideNumber | `colMode='style'` 时，收起时默认只展示一项，可以设置展示多项| number | 1      |\n| formItemLayout | 表单的Layout | `{labelCol:{xs:{span:number},sm:{span:number},md:{span:number},lg:{span:number},xl:{span:number},xxl:{span:number}},wrapperCol:{xs:{span:number},sm:{span:number},md:{span:number},lg:{span:number},xl:{span:number},xxl:{span:number}}}` | `{labelCol:{xs:{span:5},sm:{span:5},md:{span:7},lg:{span:7},xl:{span:8},xxl:{span:8},},wrapperCol:{xs:{span:19},sm:{span:19},md:{span:17},lg:{span:17},xl:{span:16},xxl:{span:16},},}`     |\n| rules | 自定义表单项的校验规则 | `object[]` | -      |\n| size | 表单项的 `size` 属性 | `large` \\| `default` \\| `small` | `default`   |\n| componentProps | `type=\"input|select\"` 时，可以通过该属性 ant 组件的Props | any | -      |\n| component | `type=\"custom\"` 时，可以通过该属性传递 `React.ReactNode` |  React.ReactNode | -      |\n| selectMode | `type=\"select\"` 时的 `mode` 属性 | `default` \\| `multiple` | `default`      |\n| options | `type=\"select\"` 时，通过该属性设置下拉选项 | {title: string;value: string;}[] | []      |\n\n## Demo\n\n```js\nimport { useState } from 'react';\nimport { QueryForm, InputNumber, Card, Button, Modal } from 'antd-advanced';\n\n\nconst columns = [\n  {\n    type: 'input',\n    title: '实例名称',\n    dataIndex: 'name',\n  },\n  {\n    type: 'select',\n    title: '报警等级',\n    dataIndex: 'level',\n    options: [\n      {\n        title: '全部',\n        value: 'all',\n      },\n      {\n        title: 'P0',\n        value: 'p0',\n      },\n      {\n        title: 'P1',\n        value: 'p1',\n      },\n      {\n        title: 'P2',\n        value: 'p2',\n      },\n    ],\n  },\n  {\n    type: 'select',\n    title: '任务状态',\n    dataIndex: 'status',\n    selectMode: 'multiple',\n    options: [\n      {\n        title: '进行中',\n        value: 'processing',\n      },\n      {\n        title: '成功',\n        value: 'success',\n      },\n      {\n        title: '失败',\n        value: 'fail',\n      },\n    ],\n  },\n  {\n    type: 'custom',\n    title: '机器数量',\n    dataIndex: 'number',\n    component: (\n      <InputNumber\n        placeholder=\"请输入机器数量\"\n        style={{ marginTop: 4, width: '100%' }}\n        min={0}\n        precision={0}\n      />\n    ),\n  },\n];\n\nconst Demo: React.FC = () => {\n  const initialValues = {\n    name: 'test',\n    level: 'p1',\n  }\n  const [result, setResult] = useState(initialValues);\n  const [isModalVisible, setIsModalVisible] = useState(false);\n\n  const showModal = () => {\n    setIsModalVisible(true);\n  };\n\n  const handleOk = () => {\n    setIsModalVisible(false);\n  };\n\n  const handleCancel = () => {\n    setIsModalVisible(false);\n  };\n  const handleChange = queryValue => {\n    setResult(queryValue);\n  };\n  return (\n    <div>\n      <QueryForm \n        onChange={handleChange} \n        onSearch={handleChange}\n        columns={columns} \n        initialValues={initialValues}\n      />\n      <h3>结果：</h3>\n      <div>{JSON.stringify(result)}</div>\n\n      <Card>\n        <Button type=\"primary\" onClick={showModal}>\n          Open Modal\n        </Button>\n        <Modal title=\"Basic Modal\" visible={isModalVisible} onOk={handleOk} onCancel={handleCancel}>\n          <p>Some contents...</p>\n          <p>Some contents...</p>\n          <p>Some contents...</p>\n        </Modal>\n      </Card>\n    </div>\n  );\n}\n\nReactDOM.render(\n  <div>\n    <Demo />\n  </div>,\n  mountNode,\n);\n```"
  },
  {
    "path": "arius-console/src/d1-packages/QueryForm/style/index.less",
    "content": ""
  },
  {
    "path": "arius-console/src/d1-packages/QueryForm/style/index.tsx",
    "content": "import './index.less';\n"
  },
  {
    "path": "arius-console/src/d1-packages/QueryForm/use-media-antd-query.ts",
    "content": "import { useState, useEffect } from 'react';\nimport useMediaQuery from './use-media';\n\nexport const MediaQueryEnum = {\n  xs: '(max-width: 575px)',\n  sm: '(min-width: 576px) and (max-width: 767px)',\n  md: '(min-width: 768px) and (max-width: 991px)',\n  lg: '(min-width: 992px) and (max-width: 1439px)',\n  xl: '(min-width: 1440px) and (max-width: 1919px)',\n  xxl: '(min-width: 1920px)',\n};\n\nexport type MediaQueryKey = keyof typeof MediaQueryEnum;\n\n/**\n * loop query screen className\n * Array.find will throw a error\n * `Rendered more hooks than during the previous render.`\n * So should use Array.forEach\n */\nexport const getScreenClassName = () => {\n  let className: MediaQueryKey = 'md';\n  // support ssr\n  if (typeof window === 'undefined') {\n    return className;\n  }\n  const mediaQueryKey = (Object.keys(MediaQueryEnum) as MediaQueryKey[]).find((key) => {\n    const matchMedia = MediaQueryEnum[key];\n    if (window.matchMedia(matchMedia).matches) {\n      return true;\n    }\n    return false;\n  });\n  className = (mediaQueryKey as unknown) as MediaQueryKey;\n  return className;\n};\n\nconst useMedia = () => {\n  const isMd = useMediaQuery(MediaQueryEnum.md);\n  const isLg = useMediaQuery(MediaQueryEnum.lg);\n  const isXxl = useMediaQuery(MediaQueryEnum.xxl);\n  const isXl = useMediaQuery(MediaQueryEnum.xl);\n  const isSm = useMediaQuery(MediaQueryEnum.sm);\n  const isXs = useMediaQuery(MediaQueryEnum.xs);\n  const [colSpan, setColSpan] = useState<keyof typeof MediaQueryEnum>(getScreenClassName());\n\n  useEffect(() => {\n    if (isXxl) {\n      setColSpan('xxl');\n      return;\n    }\n    if (isXl) {\n      setColSpan('xl');\n      return;\n    }\n    if (isLg) {\n      setColSpan('lg');\n      return;\n    }\n    if (isMd) {\n      setColSpan('md');\n      return;\n    }\n    if (isSm) {\n      setColSpan('sm');\n      return;\n    }\n    if (isXs) {\n      setColSpan('xs');\n      return;\n    }\n    setColSpan('md');\n  }, [isMd, isLg, isXxl, isXl, isSm, isXs]);\n\n  return colSpan;\n};\n\nexport default useMedia;\n"
  },
  {
    "path": "arius-console/src/d1-packages/QueryForm/use-media.ts",
    "content": "import { useEffect, useState } from 'react';\n\nexport const isClient = typeof window === 'object';\n\nconst useMedia = (query: string, defaultState: boolean = false) => {\n  const [state, setState] = useState(\n    isClient ? () => window.matchMedia(query).matches : defaultState,\n  );\n\n  useEffect(() => {\n    let mounted = true;\n    const mql = window.matchMedia(query);\n    const onChange = () => {\n      if (!mounted) {\n        return;\n      }\n      setState(!!mql.matches);\n    };\n\n    mql.addListener(onChange);\n    setState(mql.matches);\n\n    return () => {\n      mounted = false;\n      mql.removeListener(onChange);\n    };\n  }, [query]);\n\n  return state;\n};\n\nexport default useMedia;\n"
  },
  {
    "path": "arius-console/src/d1-packages/RouterGuard/README.md",
    "content": "## RouteGuard\n\n####  何时使用\n\n路由守卫，在路由切换时提供一些回调和处理方法，提供原声路由和缓存路由两种\n\n#### API\n\n| 属性               | 说明                                          | 类型                                 | 默认值   |\n| -----------       | --------------------------------------------- | ----------------------------------- | ------- |\n| routeList         | 渲染路由的数据                                  | routeItemType[]                     |         |\n| beforeEach        | 进入页面的回调                                  | (props: any) => Promise<Boolean>, props 组件的参数, 返回 true 执行重定向， 重定向到当前元素中 redirect 中路径 |         |\n| switchCacheRouter | 路由切换的毁掉，只有 routerType 为 cache 时 生效  | (props: any) => {}, props 组件的参数   |        |\n| afterEmit         | 定时器调用时间                                  | (props: any) => {}, props 组件的参数   |        |\n| routeType         | 路由的类型                                     |  routeType                            |        |\n\n**routeItemType**\n\n| 属性         | 说明                                        | 类型       |\n| ----------- | ------------------------------------------  | --------- |\n| path        | 路由路径                                      | string    |\n| component   | 对应路由路径展示的组件                          | ComponentType   |\n| cacheKey   | 缓存路由的 key 值，routeType 为 cache 时使用     | string   |\n| redirect   | beforeEach 返回 true 重定向到的地址             | string   |\n\n**routeType**\n\n| 属性         | 说明           | 类型       |\n| ----------- | -------------- | --------- |\n| cache       | 使用 keep-alive | string    |\n| default     | 使用默认路由     | string   |\n\n\n\n\n\n"
  },
  {
    "path": "arius-console/src/d1-packages/RouterGuard/index.tsx",
    "content": "export * from './route-guard';\nexport * from './route-guard-wrap';"
  },
  {
    "path": "arius-console/src/d1-packages/RouterGuard/route-guard-wrap.tsx",
    "content": "import React, { ComponentType, useEffect, useState } from \"react\";\nimport { withRouter } from \"react-router-dom\";\nimport { dropByCacheKey, useDidCache, useDidRecover } from \"react-router-cache-route\";\nimport { Page403 } from \"../CommonPages/Exception\";\n\nexport interface routeGuardWrapPropsType {\n  Component: ComponentType;\n  cacheKey?: string;\n  beforeEach?: (props: any) => Promise<Boolean>;\n  switchCacheRouter?: (props: any) => void;\n  afterEmit?: (props: any) => void;\n  redirect?: string;\n  needCache?: boolean;\n  attr?: any;\n  permissionPoint?: string;\n  path?: string;\n}\n\nexport const routeGuardWrap = ({\n  Component,\n  cacheKey,\n  needCache,\n  beforeEach,\n  switchCacheRouter,\n  afterEmit,\n  redirect,\n  attr,\n  path,\n  permissionPoint,\n}: routeGuardWrapPropsType) => {\n  const RouteGuardWrap = withRouter((props) => {\n    const { history } = props;\n    const [pagePermission, setPagePermission] = useState<Boolean>(true);\n    const [loading, setLoading] = useState<Boolean>(true);\n\n    const before = async () => {\n      if (!beforeEach) {\n        setLoading(false);\n        return;\n      }\n      try {\n        const res = await beforeEach({ path, permissionPoint, ...props });\n        // history.push(redirect || \"\");\n        // 卸载组件\n        if (needCache) {\n          cacheKey && dropByCacheKey(cacheKey);\n        }\n        setLoading(false);\n      } catch (err) {\n        setPagePermission(false);\n        setLoading(false);\n      }\n    };\n\n    useEffect(() => {\n      before();\n\n      return () => {\n        afterEmit && afterEmit(props);\n      };\n    }, []);\n\n    // 监听组件是否被缓存\n    useDidCache(() => {\n      // 只有 keepalive 才会有路由跳转事件\n      if (needCache) {\n        switchCacheRouter && switchCacheRouter(props);\n      }\n    });\n\n    useDidRecover(() => {\n      // 页面移回可视区\n    });\n\n    return loading ? null : pagePermission ? <Component {...props} {...attr} /> : <Page403 />;\n  });\n\n  return RouteGuardWrap;\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/RouterGuard/route-guard.tsx",
    "content": "import React, { ComponentType, FC, useMemo } from \"react\";\nimport { Route, Switch } from \"react-router-dom\";\nimport CacheRoute, { CacheSwitch } from \"react-router-cache-route\";\nimport { routeGuardWrap } from \"./route-guard-wrap\";\n\nexport interface routeItemType {\n  path: string;\n  component: ComponentType;\n  cacheKey?: string;\n  needCache?: boolean;\n  redirect?: string;\n  permissionPoint?: string;\n}\n\nexport interface routePropsType {\n  routeList: routeItemType[];\n  beforeEach?: (props: any) => Promise<Boolean>;\n  switchCacheRouter?: (props: any) => void;\n  afterEmit?: (props: any) => void;\n  attr?: any;\n  mulityPage: object;\n}\n\nexport const RouteGuard: FC<routePropsType> = ({ routeList, beforeEach, switchCacheRouter, afterEmit, attr = {}, mulityPage }) => {\n  const AppSwitch = routeList.filter((item) => item.needCache)?.length ? CacheSwitch : Switch;\n\n  const renderRoute = ({ path, component, cacheKey, needCache, redirect, permissionPoint }: routeItemType, key: number) => {\n    if (Object.keys(mulityPage).indexOf(path) > -1) {\n      cacheKey = window.location.search;\n    }\n    const PathRoute: any = needCache ? CacheRoute : Route;\n\n    return (\n      <PathRoute\n        path={path}\n        exact={true}\n        component={useMemo(\n          () =>\n            routeGuardWrap({\n              needCache,\n              Component: component,\n              cacheKey,\n              beforeEach,\n              switchCacheRouter,\n              afterEmit,\n              redirect,\n              attr,\n              path,\n              permissionPoint,\n            }),\n          [needCache, component, cacheKey, beforeEach, switchCacheRouter, afterEmit, redirect, attr]\n        )}\n        when=\"always\"\n        cacheKey={cacheKey}\n        key={key}\n      />\n    );\n  };\n\n  return <AppSwitch>{routeList.map((item, index) => renderRoute(item, index))}</AppSwitch>;\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/api.tsx",
    "content": "function getApi(sys: string, path: string) {\n  const prefix = \"/api/\";\n  return `${prefix}${sys}${path}`;\n}\n\nconst getCompleteApi = (path: string) => path;\n\nconst api = {\n  publicKey: \"/v3/thirdpart/sso/publicKey\",\n  opensourceLogin: \"/v3/thirdpart/sso/login\",\n  opensourceRegister: \"/v3/thirdpart/sso/register\",\n  completeUrl: getCompleteApi,\n};\n\nexport default api;\n"
  },
  {
    "path": "arius-console/src/d1-packages/config.js",
    "content": "module.exports = {\n  primaryColor: '#526ecc',\n  theme: {\n    'primary-color': '#526ecc',\n    'border-radius-base': '2px',\n    'border-radius-sm': '2px',\n    'font-size-base': '12px',\n    'font-family': 'verdana,Microsoft YaHei,Consolas,Deja Vu Sans Mono,Bitstream Vera Sans Mono',\n  },\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/Grid/RowContext.tsx",
    "content": "import { createContext, Context } from 'react';\n\nexport interface RowContextState {\n  gutter?: [number, number];\n  wrap?: boolean;\n  supportFlexGap?: boolean;\n}\n\nconst RowContext: Context<RowContextState> = createContext({});\n\nexport default RowContext;\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/Grid/_util/responsiveObserve.ts",
    "content": "export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';\nexport type BreakpointMap = Record<Breakpoint, string>;\nexport type ScreenMap = Partial<Record<Breakpoint, boolean>>;\nexport type ScreenSizeMap = Partial<Record<Breakpoint, number>>;\n\nexport const responsiveArray: Breakpoint[] = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];\n\nexport const responsiveMap: BreakpointMap = {\n  xs: '(max-width: 575px)',\n  sm: '(min-width: 576px)',\n  md: '(min-width: 768px)',\n  lg: '(min-width: 992px)',\n  xl: '(min-width: 1200px)',\n  xxl: '(min-width: 1600px)',\n};\n\ntype SubscribeFunc = (screens: ScreenMap) => void;\nconst subscribers = new Map<Number, SubscribeFunc>();\nlet subUid = -1;\nlet screens = {};\n\nconst responsiveObserve = {\n  matchHandlers: {} as {\n    [prop: string]: {\n      mql: MediaQueryList;\n      listener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | null;\n    };\n  },\n  dispatch(pointMap: ScreenMap) {\n    screens = pointMap;\n    subscribers.forEach(func => func(screens));\n    return subscribers.size >= 1;\n  },\n  subscribe(func: SubscribeFunc): number {\n    if (!subscribers.size) this.register();\n    subUid += 1;\n    subscribers.set(subUid, func);\n    func(screens);\n    return subUid;\n  },\n  unsubscribe(token: number) {\n    subscribers.delete(token);\n    if (!subscribers.size) this.unregister();\n  },\n  unregister() {\n    Object.keys(responsiveMap).forEach((screen) => {\n      const matchMediaQuery = responsiveMap[screen as Breakpoint];\n      const handler = this.matchHandlers[matchMediaQuery];\n      handler?.mql.removeListener(handler?.listener);\n    });\n    subscribers.clear();\n  },\n  register() {\n    Object.keys(responsiveMap).forEach((screen) => {\n      const matchMediaQuery = responsiveMap[screen as Breakpoint];\n      const listener = ({ matches }: { matches: boolean }) => {\n        this.dispatch({\n          ...screens,\n          [screen]: matches,\n        });\n      };\n      const mql = window.matchMedia(matchMediaQuery);\n      mql.addListener(listener);\n      this.matchHandlers[matchMediaQuery] = {\n        mql,\n        listener,\n      };\n\n      listener(mql);\n    });\n  },\n};\n\nexport default responsiveObserve;\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/Grid/col.tsx",
    "content": "import * as React from 'react';\nimport classNames from 'classnames';\nimport RowContext from './RowContext';\n\ntype ColSpanType = number | string;\n\ntype FlexType = number | 'none' | 'auto' | string;\n\nexport interface ColSize {\n  flex?: FlexType;\n  span?: ColSpanType;\n  order?: ColSpanType;\n  offset?: ColSpanType;\n  push?: ColSpanType;\n  pull?: ColSpanType;\n}\n\nexport interface ColProps extends React.HTMLAttributes<HTMLDivElement> {\n  flex?: FlexType;\n  span?: ColSpanType;\n  order?: ColSpanType;\n  offset?: ColSpanType;\n  push?: ColSpanType;\n  pull?: ColSpanType;\n  xs?: ColSpanType | ColSize;\n  sm?: ColSpanType | ColSize;\n  md?: ColSpanType | ColSize;\n  lg?: ColSpanType | ColSize;\n  xl?: ColSpanType | ColSize;\n  xxl?: ColSpanType | ColSize;\n  prefixCls?: string;\n}\n\nfunction parseFlex(flex: FlexType): string {\n  if (typeof flex === 'number') {\n    return `${flex} ${flex} auto`;\n  }\n\n  if (/^\\d+(\\.\\d+)?(px|em|rem|%)$/.test(flex)) {\n    return `0 0 ${flex}`;\n  }\n\n  return flex;\n}\nconst sizes = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'] as const;\nconst Col = React.forwardRef<HTMLDivElement, ColProps>((props, ref) => {\n  const { gutter, wrap, supportFlexGap } = React.useContext(RowContext);\n\n  const {\n    prefixCls: customizePrefixCls,\n    span,\n    order,\n    offset,\n    push,\n    pull,\n    className,\n    children,\n    flex,\n    style,\n    ...others\n  } = props;\n\n  const prefixCls = customizePrefixCls || `d1-col`;\n\n  let sizeClassObj = {};\n  sizes.forEach(size => {\n    let sizeProps: ColSize = {};\n    const propSize = props[size];\n    if (typeof propSize === 'number') {\n      sizeProps.span = propSize;\n    } else if (typeof propSize === 'object') {\n      sizeProps = propSize || {};\n    }\n\n    delete others[size];\n\n    sizeClassObj = {\n      ...sizeClassObj,\n      [`${prefixCls}-${size}-${sizeProps.span}`]: sizeProps.span !== undefined,\n      [`${prefixCls}-${size}-order-${sizeProps.order}`]: sizeProps.order || sizeProps.order === 0,\n      [`${prefixCls}-${size}-offset-${sizeProps.offset}`]:\n        sizeProps.offset || sizeProps.offset === 0,\n      [`${prefixCls}-${size}-push-${sizeProps.push}`]: sizeProps.push || sizeProps.push === 0,\n      [`${prefixCls}-${size}-pull-${sizeProps.pull}`]: sizeProps.pull || sizeProps.pull === 0,\n      [`${prefixCls}-rtl`]: false,\n    };\n  });\n\n  const classes = classNames(\n    prefixCls,\n    {\n      [`${prefixCls}-${span}`]: span !== undefined,\n      [`${prefixCls}-order-${order}`]: order,\n      [`${prefixCls}-offset-${offset}`]: offset,\n      [`${prefixCls}-push-${push}`]: push,\n      [`${prefixCls}-pull-${pull}`]: pull,\n    },\n    className,\n    sizeClassObj,\n  );\n\n  const mergedStyle: React.CSSProperties = {};\n  // Horizontal gutter use padding\n  if (gutter && gutter[0] > 0) {\n    const horizontalGutter = gutter[0] / 2;\n    mergedStyle.paddingLeft = horizontalGutter;\n    mergedStyle.paddingRight = horizontalGutter;\n  }\n\n  // Vertical gutter use padding when gap not support\n  if (gutter && gutter[1] > 0 && !supportFlexGap) {\n    const verticalGutter = gutter[1] / 2;\n    mergedStyle.paddingTop = verticalGutter;\n    mergedStyle.paddingBottom = verticalGutter;\n  }\n\n  if (flex) {\n    mergedStyle.flex = parseFlex(flex);\n\n    // Hack for Firefox to avoid size issue\n    // https://github.com/ant-design/ant-design/pull/20023#issuecomment-564389553\n    if (wrap === false && !mergedStyle.minWidth) {\n      mergedStyle.minWidth = 0;\n    }\n  }\n\n  return (\n    <div {...others} style={{ ...mergedStyle, ...style }} className={classes} ref={ref}>\n      {children}\n    </div>\n  );\n});\n\nCol.displayName = 'Col';\n\nexport default Col;\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/Grid/index.tsx",
    "content": "import Row from './row';\nimport Col from './col';\nimport './style/index';\n\nexport type { RowProps } from './row';\n\nexport type { ColProps, ColSize } from './col';\n\nexport { Row, Col };\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/Grid/row.tsx",
    "content": "import * as React from 'react';\nimport classNames from 'classnames';\nimport RowContext from './RowContext';\nimport ResponsiveObserve, {\n  Breakpoint,\n  ScreenMap,\n  responsiveArray,\n} from './_util/responsiveObserve';\n\nconst RowAligns = ['top', 'middle', 'bottom', 'stretch'] as const;\nconst RowJustify = ['start', 'end', 'center', 'space-around', 'space-between'] as const;\n\nexport type Gutter = number | Partial<Record<Breakpoint, number>>;\nexport interface RowProps extends React.HTMLAttributes<HTMLDivElement> {\n  gutter?: Gutter | [Gutter, Gutter];\n  align?: typeof RowAligns[number];\n  justify?: typeof RowJustify[number];\n  prefixCls?: string;\n  wrap?: boolean;\n}\n\nconst Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {\n  const {\n    prefixCls: customizePrefixCls,\n    justify,\n    align,\n    className,\n    style,\n    children,\n    gutter = 0,\n    wrap,\n    ...others\n  } = props;\n\n  const [screens, setScreens] = React.useState<ScreenMap>({\n    xs: true,\n    sm: true,\n    md: true,\n    lg: true,\n    xl: true,\n    xxl: true,\n  });\n\n  const supportFlexGap = true;\n\n  const gutterRef = React.useRef<Gutter | [Gutter, Gutter]>(gutter);\n\n  // ================================== Effect ==================================\n  React.useEffect(() => {\n    const token = ResponsiveObserve.subscribe(screen => {\n      const currentGutter = gutterRef.current || 0;\n      if (\n        (!Array.isArray(currentGutter) && typeof currentGutter === 'object') ||\n        (Array.isArray(currentGutter) &&\n          (typeof currentGutter[0] === 'object' || typeof currentGutter[1] === 'object'))\n      ) {\n        setScreens(screen);\n      }\n    });\n    return () => ResponsiveObserve.unsubscribe(token);\n  }, []);\n\n  // ================================== Render ==================================\n  const getGutter = (): [number, number] => {\n    const results: [number, number] = [0, 0];\n    const normalizedGutter = Array.isArray(gutter) ? gutter : [gutter, 0];\n    normalizedGutter.forEach((g, index) => {\n      if (typeof g === 'object') {\n        for (let i = 0; i < responsiveArray.length; i++) {\n          const breakpoint: Breakpoint = responsiveArray[i];\n          if (screens[breakpoint] && g[breakpoint] !== undefined) {\n            results[index] = g[breakpoint] as number;\n            break;\n          }\n        }\n      } else {\n        results[index] = g || 0;\n      }\n    });\n    return results;\n  };\n\n  const prefixCls = customizePrefixCls || `d1-row`;\n  const gutters = getGutter();\n  const classes = classNames(\n    prefixCls,\n    {\n      [`${prefixCls}-no-wrap`]: wrap === false,\n      [`${prefixCls}-${justify}`]: justify,\n      [`${prefixCls}-${align}`]: align,\n      [`${prefixCls}-rtl`]: false,\n    },\n    className,\n  );\n\n  // Add gutter related style\n  const rowStyle: React.CSSProperties = {};\n  const horizontalGutter = gutters[0] > 0 ? gutters[0] / -2 : undefined;\n  const verticalGutter = gutters[1] > 0 ? gutters[1] / -2 : undefined;\n\n  if (horizontalGutter) {\n    rowStyle.marginLeft = horizontalGutter;\n    rowStyle.marginRight = horizontalGutter;\n  }\n\n  if (supportFlexGap) {\n    // Set gap direct if flex gap support\n    [, rowStyle.rowGap] = gutters;\n  } else if (verticalGutter) {\n    rowStyle.marginTop = verticalGutter;\n    rowStyle.marginBottom = verticalGutter;\n  }\n\n  const rowContext = React.useMemo(() => ({ gutter: gutters, wrap, supportFlexGap }), [\n    gutters,\n    wrap,\n    supportFlexGap,\n  ]);\n\n  return (\n    <RowContext.Provider value={rowContext}>\n      <div {...others} className={classes} style={{ ...rowStyle, ...style }} ref={ref}>\n        {children}\n      </div>\n    </RowContext.Provider>\n  );\n});\n\nRow.displayName = 'Row';\n\nexport default Row;\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/Grid/style/index.less",
    "content": "@import './mixin';\n\n@d1-prefix: d1;\n// Media queries breakpoints\n// @screen-xs and @screen-xs-min is not used in Grid\n// smallest break point is @screen-md\n@screen-xs: 480px;\n@screen-xs-min: @screen-xs;\n// 👆 Extra small screen / phone\n\n// 👇 Small screen / tablet\n@screen-sm: 576px;\n@screen-sm-min: @screen-sm;\n\n// Medium screen / desktop\n@screen-md: 768px;\n@screen-md-min: @screen-md;\n\n// Large screen / wide desktop\n@screen-lg: 992px;\n@screen-lg-min: @screen-lg;\n\n// Extra large screen / full hd\n@screen-xl: 1440px;\n@screen-xl-min: @screen-xl;\n\n// Extra extra large screen / large desktop\n@screen-xxl: 1920px;\n@screen-xxl-min: @screen-xxl;\n\n// provide a maximum\n@screen-xs-max: (@screen-sm-min - 1px);\n@screen-sm-max: (@screen-md-min - 1px);\n@screen-md-max: (@screen-lg-min - 1px);\n@screen-lg-max: (@screen-xl-min - 1px);\n@screen-xl-max: (@screen-xxl-min - 1px);\n// Grid system\n@grid-columns: 24;\n\n// Grid system\n.@{d1-prefix}-row {\n  display: flex;\n  flex-flow: row wrap;\n  width: 100%;\n\n  &::before,\n  &::after {\n    display: flex;\n  }\n\n  // No wrap of flex\n  &-no-wrap {\n    flex-wrap: nowrap;\n  }\n}\n\n// x轴原点\n.@{d1-prefix}-row-start {\n  justify-content: flex-start;\n}\n\n// x轴居中\n.@{d1-prefix}-row-center {\n  justify-content: center;\n}\n\n// x轴反方向\n.@{d1-prefix}-row-end {\n  justify-content: flex-end;\n}\n\n// x轴平分\n.@{d1-prefix}-row-space-between {\n  justify-content: space-between;\n}\n\n// x轴有间隔地平分\n.@{d1-prefix}-row-space-around {\n  justify-content: space-around;\n}\n\n// 顶部对齐\n.@{d1-prefix}-row-top {\n  align-items: flex-start;\n}\n\n// 居中对齐\n.@{d1-prefix}-row-middle {\n  align-items: center;\n}\n\n// 底部对齐\n.@{d1-prefix}-row-bottom {\n  align-items: flex-end;\n}\n\n.@{d1-prefix}-col {\n  position: relative;\n  max-width: 100%;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n}\n\n.make-grid();\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(-xl);\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n  .make-grid(-xl);\n  // html{\n  //   font-size:  @screen-sm-min/1440*100px;\n  // }\n}\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n  .make-grid(-xl);\n  // html{\n  //   font-size:  @screen-md-min/1440*100px;\n  // }\n}\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n  .make-grid(-xl);\n  // html{\n  //   font-size:  @screen-lg-min/1440*100px;\n  // }\n}\n\n// Extra Large grid\n//\n// Columns, offsets, pushes, and pulls for the full hd device range.\n\n@media (min-width: @screen-xl-min) {\n  .make-grid(-xl);\n  // html{\n  //   font-size: 100px;\n  // }\n}\n\n// Extra Extra Large grid\n//\n// Columns, offsets, pushes, and pulls for the full hd device range.\n\n@media (min-width: @screen-xxl-min) {\n  .make-grid(-xxl);\n  // html{\n  //   font-size:  @screen-xxl-min/1440*100px;\n  // }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/Grid/style/index.tsx",
    "content": "import './index.less';\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/Grid/style/mixin.less",
    "content": "@d1-prefix: d1;\n// mixins for grid system\n// ------------------------\n\n.loop-grid-columns(@index, @class) when (@index > 0) {\n  .@{d1-prefix}-col@{class}-@{index} {\n    display: block;\n    flex: 0 0 percentage((@index / @grid-columns));\n    max-width: percentage((@index / @grid-columns));\n  }\n  .@{d1-prefix}-col@{class}-push-@{index} {\n    left: percentage((@index / @grid-columns));\n  }\n  .@{d1-prefix}-col@{class}-pull-@{index} {\n    right: percentage((@index / @grid-columns));\n  }\n  .@{d1-prefix}-col@{class}-offset-@{index} {\n    margin-left: percentage((@index / @grid-columns));\n  }\n  .@{d1-prefix}-col@{class}-order-@{index} {\n    order: @index;\n  }\n  .loop-grid-columns((@index - 1), @class);\n}\n\n.loop-grid-columns(@index, @class) when (@index = 0) {\n  .@{d1-prefix}-col@{class}-@{index} {\n    display: none;\n  }\n  .@{d1-prefix}-col-push-@{index} {\n    left: auto;\n  }\n  .@{d1-prefix}-col-pull-@{index} {\n    right: auto;\n  }\n  .@{d1-prefix}-col@{class}-push-@{index} {\n    left: auto;\n  }\n  .@{d1-prefix}-col@{class}-pull-@{index} {\n    right: auto;\n  }\n  .@{d1-prefix}-col@{class}-offset-@{index} {\n    margin-left: 0;\n  }\n  .@{d1-prefix}-col@{class}-order-@{index} {\n    order: 0;\n  }\n}\n\n.make-grid(@class: ~'') {\n  .loop-grid-columns(@grid-columns, @class);\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/demo/base.md",
    "content": "---\norder: 0\ntitle: 基本\n---\n\nContainer示例\n\n``` tsx\nimport * as React from 'react';\nimport '../example/grid.less';\nimport Container from '../index.tsx';\nconst Containers = (): JSX.Element => {\n    return (\n        <>\n            <div>栅格布局 共24格 {`grid={6}`}</div>\n            <Container gutter={10} grid={6}>\n                <div className=\"grid-demo-div\">栅格布局 6格</div>\n                <div className=\"grid-demo-div\">栅格布局 6格</div>\n                <div className=\"grid-demo-div\">栅格布局 6格</div>\n                <div className=\"grid-demo-div\">栅格布局 6格</div>\n            </Container>\n            <div>栅格布局 共24格 {`grid={[4, 4, 8, 8]}`}</div>\n            <Container gutter={10} grid={[4, 4, 8, 8]}>\n                <div className=\"grid-demo-div\">栅格布局 4格</div>\n                <div className=\"grid-demo-div\">栅格布局 4格</div>\n                <div className=\"grid-demo-div\">栅格布局 8格</div>\n                <div className=\"grid-demo-div\">栅格布局 8格</div>\n            </Container>\n            <div>流式布局 {`fluid={300}`}</div>\n            <Container gutter={10} fluid={300}>\n                <div className=\"grid-demo-div\">流式布局 300px</div>\n                <div className=\"grid-demo-div\">流式布局 300px</div>\n                <div className=\"grid-demo-div\">流式布局 300px</div>\n                <div className=\"grid-demo-div\">流式布局 300px</div>\n            </Container>\n            <div>flex auto布局 {`flex={'auto'}`}</div>\n            <Container gutter={10} flex={'auto'}>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n            </Container>\n            <div>flex 部分定宽布局 {`flex={['200px', 'auto']}`}</div>\n            <Container gutter={10} flex={['200px', 'auto']}>\n                <div className=\"grid-demo-div\">flex布局 200px</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n            </Container>\n            <div>自适应 断点1440和1920{`awd={true} `}</div>\n            <Container gutter={10} awd={true}>\n                <div className=\"grid-demo-div\">自适应布局</div>\n                <div className=\"grid-demo-div\">自适应布局</div>\n                <div className=\"grid-demo-div\">自适应布局</div>\n            </Container>\n            <div>响应式 {`rwd={true}`} 须使用rem为单位</div>\n            <Container gutter={10} rwd={true}>\n                <div className=\"grid-demo-div1\">响应式布局</div>\n                <div className=\"grid-demo-div1\">响应式布局</div>\n                <div className=\"grid-demo-div1\">响应式布局</div>\n                <div className=\"grid-demo-div1\">响应式布局</div>\n            </Container>\n            <div>组合使用1</div>\n            <Container gutter={10} awd={true} xl={[8, 8, 8, 24]} xxl={6}>\n                <Container fluid={400}><div className=\"grid-demo-div\">饼图1</div></Container>\n                <Container fluid={400}><div className=\"grid-demo-div\">饼图2</div></Container>\n                <Container fluid={400}>\n                    <div className=\"grid-demo-div\">summary</div>\n                    <div className=\"grid-demo-div\">Volume</div>\n                </Container>\n                <Container awd xl={8} xxl={24}>\n                    <Container fluid={400}><div className=\"grid-demo-div\">peak</div></Container>\n                    <Container fluid={400}><div className=\"grid-demo-div\">latest</div></Container>\n                </Container>\n            </Container>\n            <div>组合使用2 默认自适应+流式+flex+自定义自适应</div>\n            <Container gutter={10} awd={true} xl={[12, 12, 24]}>\n                <div className=\"grid-demo-div\">\n                    <Container gutter={10} fluid={100}>\n                        <div className=\"grid-demo-div grid-demo-div3\">流式布局 100px</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">流式布局 100px</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">流式布局 100px</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">流式布局 100px</div>\n                    </Container>\n                </div>\n                <div className=\"grid-demo-div\">\n                    <Container gutter={10} flex={['200px', 'auto']}>\n                        <div className=\"grid-demo-div grid-demo-div3\">flex布局 200px</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">flex布局 auto</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">flex布局 auto</div>\n                    </Container>\n                </div>\n                <div className=\"grid-demo-div\">\n                    <Container gutter={10} awd={true} xl={12} xxl={24}>\n                        <div className=\"grid-demo-div grid-demo-div3\">自适应布局</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">自适应布局</div>\n                    </Container>\n                </div>\n            </Container>\n\n        </>\n    )\n}\n\nReactDOM.render(\n  <div>\n    <Containers />\n  </div>,\n  mountNode,\n);\n```"
  },
  {
    "path": "arius-console/src/d1-packages/container/example/grid.less",
    "content": ".grid-demo-div{\n    color: #fff;\n    min-height: 50px;\n    background-color: #0092ff;\n    margin: 10px 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n}\n.grid-demo-div1{\n    color: #fff;\n    min-height: 0.5rem;\n    background-color: #0092ff;\n    margin: 10px 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n\n}\n\n.grid-demo-div3{\n    min-height: 50px;\n    background-color: #00d2ff;\n}"
  },
  {
    "path": "arius-console/src/d1-packages/container/example/grid.tsx",
    "content": "import * as React from 'react';\nimport './grid.less';\n\nimport Container from '../index';\n\nconst Containers = (): JSX.Element => {\n    return (\n        <>\n            <div>栅格布局 共24格 {`grid={6}`}</div>\n            <Container gutter={10} grid={6}>\n                <div className=\"grid-demo-div\">栅格布局 6格</div>\n                <div className=\"grid-demo-div\">栅格布局 6格</div>\n                <div className=\"grid-demo-div\">栅格布局 6格</div>\n                <div className=\"grid-demo-div\">栅格布局 6格</div>\n            </Container>\n            <div>栅格布局 共24格 {`grid={[4, 4, 8, 8]}`}</div>\n            <Container gutter={10} grid={[4, 4, 8, 8]}>\n                <div className=\"grid-demo-div\">栅格布局 4格</div>\n                <div className=\"grid-demo-div\">栅格布局 4格</div>\n                <div className=\"grid-demo-div\">栅格布局 8格</div>\n                <div className=\"grid-demo-div\">栅格布局 8格</div>\n            </Container>\n            <div>流式布局 {`fluid={300}`}</div>\n            <Container gutter={10} fluid={300}>\n                <div className=\"grid-demo-div\">流式布局 300px</div>\n                <div className=\"grid-demo-div\">流式布局 300px</div>\n                <div className=\"grid-demo-div\">流式布局 300px</div>\n                <div className=\"grid-demo-div\">流式布局 300px</div>\n            </Container>\n            <div>flex auto布局 {`flex={'auto'}`}</div>\n            <Container gutter={10} flex={'auto'}>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n            </Container>\n            <div>flex 部分定宽布局 {`flex={['200px', 'auto']}`}</div>\n            <Container gutter={10} flex={['200px', 'auto']}>\n                <div className=\"grid-demo-div\">flex布局 200px</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n                <div className=\"grid-demo-div\">flex布局 auto</div>\n            </Container>\n            <div>自适应 断点1440和1920{`awd={true} `}</div>\n            <Container gutter={10} awd={true}>\n                <div className=\"grid-demo-div\">自适应布局</div>\n                <div className=\"grid-demo-div\">自适应布局</div>\n                <div className=\"grid-demo-div\">自适应布局</div>\n            </Container>\n            <div>响应式 {`rwd={true}`} 须使用rem为单位</div>\n            <Container gutter={10} rwd={true}>\n                <div className=\"grid-demo-div1\">响应式布局</div>\n                <div className=\"grid-demo-div1\">响应式布局</div>\n                <div className=\"grid-demo-div1\">响应式布局</div>\n                <div className=\"grid-demo-div1\">响应式布局</div>\n            </Container>\n            <div>组合使用1</div>\n            <Container gutter={10} awd={true} xl={[8, 8, 8, 24]} xxl={6}>\n                <Container fluid={400}><div className=\"grid-demo-div\">饼图1</div></Container>\n                <Container fluid={400}><div className=\"grid-demo-div\">饼图2</div></Container>\n                <Container fluid={400}>\n                    <div className=\"grid-demo-div\">summary</div>\n                    <div className=\"grid-demo-div\">Volume</div>\n                </Container>\n                <Container awd xl={8} xxl={24}>\n                    <Container fluid={400}><div className=\"grid-demo-div\">peak</div></Container>\n                    <Container fluid={400}><div className=\"grid-demo-div\">latest</div></Container>\n                </Container>\n            </Container>\n            <div>组合使用2 默认自适应+流式+flex+自定义自适应</div>\n            <Container gutter={10} awd={true} xl={[12, 12, 24]}>\n                <div className=\"grid-demo-div\">\n                    <Container gutter={10} fluid={100}>\n                        <div className=\"grid-demo-div grid-demo-div3\">流式布局 100px</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">流式布局 100px</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">流式布局 100px</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">流式布局 100px</div>\n                    </Container>\n                </div>\n                <div className=\"grid-demo-div\">\n                    <Container gutter={10} flex={['200px', 'auto']}>\n                        <div className=\"grid-demo-div grid-demo-div3\">flex布局 200px</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">flex布局 auto</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">flex布局 auto</div>\n                    </Container>\n                </div>\n                <div className=\"grid-demo-div\">\n                    <Container gutter={10} awd={true} xl={12} xxl={24}>\n                        <div className=\"grid-demo-div grid-demo-div3\">自适应布局</div>\n                        <div className=\"grid-demo-div grid-demo-div3\">自适应布局</div>\n                    </Container>\n                </div>\n            </Container>\n\n        </>\n    )\n}\n\nexport default Containers;\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/index.md",
    "content": "---\ncategory: 组件\ntype: 布局\ncols: 1\ntitle: Container\nsubtitle: 布局组件\n---\n\n\n## 何时使用\n用于快速生成响应式、栅格、自适应等页面布局\n"
  },
  {
    "path": "arius-console/src/d1-packages/container/index.tsx",
    "content": "import React from \"react\";\nimport \"./Grid/style/index\";\nimport { Col, Row } from \"knowdesign\";\nimport { Gutter } from \"./Grid/row\";\n\ninterface OptionsProps {\n  [propertys: string]: any;\n}\n\ninterface LayoutProps {\n  [propertys: string]: any;\n}\n\ninterface LayoutState {\n  [propertys: string]: any;\n}\n\nexport function withContainer(Cmp: React.ComponentType, options: OptionsProps) {\n  return class FusionLayout extends React.Component<LayoutProps, LayoutState> {\n    constructor(props: LayoutProps) {\n      super(props);\n      this.state = {\n        ...options,\n      };\n    }\n    render() {\n      return (\n        <Container>\n          <Cmp {...this.state} {...this.props}></Cmp>\n        </Container>\n      );\n    }\n  };\n}\nexport function withContainers(options: OptionsProps) {\n  return (Cmp: React.ComponentType) => withContainer(Cmp, options);\n}\n\ntype ColSpanType = number | string;\n\ntype FlexType = number | \"none\" | \"auto\" | string;\n\ninterface ColSize {\n  flex?: FlexType;\n  span?: ColSpanType;\n  order?: ColSpanType;\n  offset?: ColSpanType;\n  push?: ColSpanType;\n  pull?: ColSpanType;\n}\n\nexport interface propsType extends React.HTMLAttributes<HTMLDivElement> {\n  children?: React.ReactNode;\n  grid?: ColSpanType | ColSpanType[];\n  fluid?: ColSpanType;\n  flex?: FlexType | FlexType[];\n  awd?: boolean | number[];\n  rwd?: boolean;\n  xl?: ColSpanType | ColSize | ColSpanType[] | ColSize[];\n  xxl?: ColSpanType | ColSize | ColSpanType[] | ColSize[];\n  wrap?: boolean;\n  gutter?: Gutter | [Gutter, Gutter];\n}\nconst Container: React.FC<propsType> = (props) => {\n  const { children, className, gutter, wrap = true, grid, fluid, flex, awd, rwd, xl = 12, xxl = 8 } = props;\n\n  const items = React.Children.toArray(children);\n  const itemNumber = items.length || 0;\n\n  const getGrid = () => {\n    if (!grid) return null;\n    const span = typeof grid === \"number\" ? Array(itemNumber).fill(grid || Math.round(24 / itemNumber)) : grid;\n\n    return items.map((child: React.ReactNode, index: number) => {\n      return (\n        <Col span={span[index]} key={index}>\n          {child}\n        </Col>\n      );\n    });\n  };\n\n  const getFluid = () => {\n    if (!fluid) return null;\n    return items.map((child: React.ReactNode, index: number) => (\n      <Col flex={`0 0 ${fluid}px`} key={index}>\n        {child}\n      </Col>\n    ));\n  };\n\n  const getFlex = () => {\n    if (!flex) return null;\n    let flexList: ColSpanType[] = Array(itemNumber);\n    if (Array.isArray(flex)) {\n      // @ts-ignore\n      flexList = flexList.fill(\"\").map((f, i) => flex[i] || \"auto\");\n    } else {\n      flexList.fill(flex);\n    }\n    return items.map((child: React.ReactNode, index: number) => (\n      <Col flex={flexList[index]} key={index}>\n        {child}\n      </Col>\n    ));\n  };\n\n  const getAWD = () => {\n    if (!awd) return null;\n    let xlList: (ColSpanType | ColSize)[] = Array(itemNumber);\n    if (Array.isArray(xl)) {\n      // @ts-ignore\n      xlList = xlList.fill(\"\").map((f, i) => xl[i] || 12);\n    } else {\n      xlList.fill(xl);\n    }\n    let xxlList: (ColSpanType | ColSize)[] = Array(itemNumber);\n    if (Array.isArray(xxl)) {\n      // @ts-ignore\n      xxlList = xxlList.fill(\"\").map((f, i) => xl[i] || 12);\n    } else {\n      xxlList.fill(xxl);\n    }\n    return items.map((child: React.ReactNode, index: number) => (\n      <Col xl={xlList[index]} xxl={xxlList[index]} key={index}>\n        {child}\n      </Col>\n    ));\n  };\n\n  const getRWD = () => {\n    if (!rwd) return null;\n    return items.map((child: React.ReactNode, index: number) => (\n      <Col flex=\"auto\" key={index}>\n        {child}\n      </Col>\n    ));\n  };\n\n  return (\n    <Row gutter={gutter} className={className} wrap={wrap} justify={fluid ? \"space-between\" : \"start\"}>\n      {getGrid() || getFluid() || getFlex() || getAWD() || getRWD()}\n    </Row>\n  );\n};\nexport default Container;\n"
  },
  {
    "path": "arius-console/src/d1-packages/d-range-time/demo/custom.md",
    "content": "---\norder: 0\ntitle: 基础用法\n---\n\nDRangeTime示例   \n\n``` tsx\nimport React, { useState, useEffect } from 'react';\nimport DRangeTime from '../index';\n\nconst Containers = (): JSX.Element => {\n  const [isGroup, setIsgroup] = useState(false); \n  const handleTimeChange = (times) => {\n    console.log(times)\n  }\n  return (\n      <>\n        <DRangeTime timeChange={handleTimeChange}/>         \n      </>\n  )\n}\n\nReactDOM.render(\n  <div>\n    <Containers />\n  </div>,\n  mountNode,\n);\n```\n\n```css\n.drag-sort-item {\n  /* background: #4482D4; */\n  box-shadow: 0 2px 4px 0 rgba(0,0,0,0.01), 0 3px 6px 3px rgba(0,0,0,0.01), 0 2px 6px 0 rgba(0,0,0,0.03);\n  border-radius: 4px; \n  color: #fff;\n}\n\n```\n"
  },
  {
    "path": "arius-console/src/d1-packages/d-range-time/index.md",
    "content": "---\ncategory: 组件\ntype: 布局\ncols: 1\ntitle: DRangeTime\nsubtitle: 时间段选择组件\n---\n\n\n## 何时使用\n时间段选择组件新UI\n"
  },
  {
    "path": "arius-console/src/d1-packages/d-range-time/index.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { Radio, DatePicker, Input, Popover, Space } from \"antd\";\nimport { IconFont } from \"@knowdesign/icons\";\nconst { RangePicker } = DatePicker;\nimport moment, { Moment } from \"moment\";\nimport { getPopupContainer } from \"lib/utils\";\nimport \"./style/index.less\";\n\ntype objectItem = {\n  value: number;\n  label: string;\n};\ninterface propsType extends React.HTMLAttributes<HTMLDivElement> {\n  timeChange: Function;\n  rangeTimeArr?: number[];\n  popoverClassName?: string;\n  // resetAllValue?: any;\n  customTimeOptions?: objectItem[];\n  value?: any;\n  onChange?: any;\n  customDisabledDate?: any;\n  defaultRangeKey?: number; // 默认选中第几个时间项\n}\n\nconst TimeOptionsDefault = [\n  {\n    label: \"最近 15 分钟\",\n    value: 15 * 60 * 1000,\n  },\n  {\n    label: \"最近 1 小时\",\n    value: 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 6 小时\",\n    value: 6 * 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 12 小时\",\n    value: 12 * 60 * 60 * 1000,\n  },\n  {\n    label: \"最近 1 天\",\n    value: 24 * 60 * 60 * 1000,\n  },\n];\n\n//const TimeModule: React.FC<propsType> = ({ timeChange, rangeTimeArr, popoverClassName, resetAllValue, customTimeOptions, value = {}, onChange }) => {\nconst TimeModule: React.FC<propsType> = ({\n  timeChange,\n  rangeTimeArr,\n  popoverClassName,\n  customTimeOptions,\n  value = {},\n  onChange,\n  defaultRangeKey,\n  customDisabledDate,\n}) => {\n  const [time, setTime] = useState<number>(60 * 60 * 1000);\n  const [rangeTime, setrangeTime] = useState<[Moment, Moment]>([moment(new Date().getTime() - time), moment(new Date().getTime())]);\n  const [isRelative, setIsRelative] = useState(true);\n  const [visible, setVisible] = useState(false);\n  const [dates, setDates] = useState([]);\n  const [TimeOptions, setfirst] = useState(customTimeOptions || TimeOptionsDefault);\n  const [inputValue, setInputValue] = useState<string>(null);\n  const [hackValue, setHackValue] = useState<any>(null); //RangePicker打开面板后值设置为空\n\n  useEffect(() => {\n    if (rangeTimeArr?.length > 0) {\n      setrangeTime([moment(rangeTimeArr[0]), moment(rangeTimeArr[1])]);\n      const rangeTimeLen = rangeTimeArr[1] - rangeTimeArr[0];\n      setTime(Math.floor(rangeTimeLen / 1000) * 1000);\n    }\n  }, [rangeTimeArr]);\n\n  useEffect(() => {\n    if (!!time) {\n      const timeOption = TimeOptions.find((item) => item.value === time);\n      timeOption ? setIsRelative(true) : setIsRelative(false);\n      timeOption && setInputValue(timeOption?.label);\n    }\n  }, [time]);\n  // const resetFun = () => {\n  //   resetAllValue && resetAllValue({ setInputValue, setrangeTime, setTime })\n  // }\n  // useEffect(() => {\n  //   resetFun()\n  // }, []);\n  useEffect(() => {\n    if (defaultRangeKey !== undefined) {\n      // 赋值初始默认起始时间\n      periodtimeChange({ target: { value: TimeOptions[defaultRangeKey]?.value } });\n    } else {\n      onChange && triggerChange({ time: null, rangeTime: null, inputValue: null }); //初始化清空所有数据\n    }\n  }, []);\n\n  const triggerChange = (changedValue) => {\n    onChange?.({ time, rangeTime, inputValue, ...value, ...changedValue });\n  };\n\n  const periodtimeChange = (e) => {\n    const periodtime = e.target.value;\n    const timeOption = TimeOptions.find((item) => item.value === periodtime);\n    onChange &&\n      triggerChange({\n        time: periodtime,\n        rangeTime: [moment(new Date().getTime() - periodtime), moment(new Date().getTime())],\n        inputValue: timeOption?.label,\n      });\n    setTime(periodtime);\n    setrangeTime([moment(new Date().getTime() - periodtime), moment(new Date().getTime())]);\n    timeChange([new Date().getTime() - periodtime, new Date().getTime()], true);\n    setIsRelative(true);\n    setVisible(false);\n  };\n\n  const rangeTimeChange = (dates, dateStrings) => {\n    setrangeTime(dates);\n    setTime(null);\n    dateStrings[0] && setInputValue(`${dateStrings[0]} ~ ${dateStrings[1]}`);\n    onChange && triggerChange({ time: null, rangeTime: dates, inputValue: dates ? `${dateStrings[0]} ~ ${dateStrings[1]}` : undefined });\n    timeChange([moment(dateStrings[0]).valueOf(), moment(dateStrings[1]).valueOf()], false); // 毫秒数\n    setIsRelative(false);\n    setVisible(false);\n  };\n  const onOpenChange = (open) => {\n    if (open) {\n      setHackValue([]);\n      setDates([]);\n    } else {\n      setHackValue(undefined);\n    }\n  };\n  const disabledDate = (current) => {\n    if (customDisabledDate) {\n      return customDisabledDate(current, dates);\n    }\n    if (current && current > moment().endOf(\"day\")) {\n      return true;\n    }\n    if (!dates || dates.length === 0) {\n      return false;\n    }\n    return false;\n  };\n\n  const handleVisibleChange = (visible) => {\n    setVisible(visible);\n  };\n\n  const clickContent = (\n    <div className=\"dd-time-range-module\">\n      {/* <span>时间：</span> */}\n      <div className=\"flx_con\">\n        <div className=\"flx_l\">\n          <h6 className=\"time_title\">选择时间范围</h6>\n          <Radio.Group\n            // optionType=\"button\"\n            // buttonStyle=\"solid\"\n            // options={TimeOptions}\n            className=\"time-radio-group\"\n            onChange={periodtimeChange}\n            value={onChange ? value?.time : time}\n            //value={time}\n          >\n            <Space direction=\"vertical\" size={16}>\n              {TimeOptions.map((item, index) => (\n                <Radio.Button value={item.value} key={index}>\n                  {item.label}\n                </Radio.Button>\n              ))}\n            </Space>\n          </Radio.Group>\n        </div>\n        <div className=\"flx_r\">\n          <h6 className=\"time_title\">自定义时间范围</h6>\n          <RangePicker\n            showTime={{\n              format: \"HH:mm\",\n            }}\n            format=\"YYYY-MM-DD HH:mm\"\n            separator=\"~\"\n            onCalendarChange={(val) => setDates(val)}\n            disabledDate={disabledDate}\n            suffixIcon={<IconFont type=\"icon-riqi\" style={{ color: \"#74788D\" }}></IconFont>}\n            //value={hackValue || rangeTime}\n            value={hackValue || (onChange ? value?.rangeTime : rangeTime)}\n            onChange={rangeTimeChange}\n            onOpenChange={onOpenChange}\n          />\n        </div>\n      </div>\n    </div>\n  );\n  return (\n    <>\n      <div id=\"d-range-time\">\n        <Popover\n          trigger={[\"click\"]}\n          visible={visible}\n          onVisibleChange={handleVisibleChange}\n          content={clickContent}\n          placement=\"bottomRight\"\n          overlayClassName={`d-range-time-popover ${popoverClassName ?? \"\"}`}\n          getPopupContainer={getPopupContainer}\n        >\n          <span className=\"input-span\">\n            <Input\n              className={isRelative ? \"relativeTime d-range-time-input\" : \"absoluteTime d-range-time-input\"}\n              value={onChange ? value?.inputValue : inputValue}\n              //value={inputValue}\n              readOnly={true}\n              bordered={false}\n              placeholder=\"请选择时间范围\"\n              suffix={<IconFont type=\"icon-jiantou1\" rotate={90} style={{ color: \"#74788D\" }}></IconFont>}\n            />\n          </span>\n        </Popover>\n      </div>\n    </>\n  );\n};\n\nexport default TimeModule;\n"
  },
  {
    "path": "arius-console/src/d1-packages/d-range-time/style/index.less",
    "content": "// @import '../style/index.less';\n#d-range-time {\n  position: relative;\n  display: inline-block;\n  width: 100%;\n  .input-span {\n    cursor: pointer;\n  }\n  .d-range-time-input {\n    height: 32px;\n    background: #fff;\n    border: 1px solid #ced4da;\n    border-radius: 4px;\n    &.relativeTime {\n      width: 100%;\n    }\n    &.absoluteTime {\n      width: 100%;\n    }\n    input {\n      cursor: pointer;\n    }\n    .dcloud-input {\n      background: transparent;\n    }\n    .dcloud-input-suffix {\n      font-size: 18px;\n      color: #74788d;\n    }\n  }\n}\n.d-range-time-popover {\n  border-radius: 12px;\n  .dcloud-popover-inner-content {\n    padding: 16px 24px;\n    width: 479px;\n    box-sizing: border-box;\n  }\n  &.dcloud-popover-placement-bottomRight {\n    padding-top: 0;\n  }\n}\n.dd-time-range-module {\n  .flx_con {\n    display: flex;\n    .time_title {\n      font-size: 14px;\n      color: #212529;\n      margin-bottom: 16px;\n    }\n    .flx_l {\n      width: 184px;\n      .dcloud-radio {\n        display: none;\n        & + * {\n          padding: 0;\n        }\n      }\n      .dcloud-radio-wrapper-checked {\n        color: #556ee6;\n      }\n    }\n    .flx_r {\n      flex: 1;\n    }\n    .ant-picker-range {\n      min-width: 320px;\n    }\n  }\n  .time-radio-group {\n    .dcloud-radio-wrapper {\n      line-height: 18px;\n    }\n  }\n  .dcloud-picker {\n    border: 0;\n    background: rgba(33, 37, 41, 0.04);\n  }\n  .dcloud-picker-range {\n    width: 300px;\n    .dcloud-picker-clear {\n      font-size: 14px;\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/DTable/index.less",
    "content": "// .d-table {\n//   // background: white;\n\n//   &-box {\n//     padding: 20px 0px;\n\n//     &-header {\n//       display: flex;\n//       justify-content: space-between;\n//       align-items: center;\n//       padding: 20px 0 20px 0;\n\n//       &-search {\n//         display: flex;\n//         justify-content: space-between;\n//         align-items: center;\n\n//         &-custom {\n//           padding-right: 20px;\n//         }\n//       }\n\n//       &-btn {\n//         button {\n//           margin-right: 10px;\n//         }\n\n//         .reload {\n//           width: 30px;\n//           height: 30px;\n//           line-height: 30px;\n//           border: 1px solid #dbe0e4;\n//           border-radius: 2px;\n//           margin-right: 10px;\n//         }\n\n//         .reload:hover {\n//           color: @primary-color;\n//         }\n//       }\n//     }\n//   }\n// }\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/DTable/index.tsx",
    "content": "import React from \"react\";\nimport { Input, Button, Table } from \"antd\";\nimport { ReloadOutlined, SearchOutlined } from \"@ant-design/icons\";\nimport \"./index.less\";\n\nexport const DTablerefix = \"d-table\";\n\nexport const pagination = {\n  // position: 'bottomRight',\n  showQuickJumper: true,\n  showSizeChanger: true,\n  pageSizeOptions: [\"10\", \"20\", \"50\", \"100\", \"200\", \"500\"],\n  showTotal: (total: number) => `共 ${total} 条`,\n  // hideOnSinglePage: true,\n};\n\nexport interface ITableBtn {\n  clickFunc?: () => void;\n  type?: string;\n  customFormItem?: string | JSX.Element;\n  isRouterNav?: boolean;\n  label: string | JSX.Element;\n  className?: string;\n  needConfirm?: boolean;\n  aHref?: string;\n  confirmText?: string;\n  noRefresh?: boolean;\n  loading?: boolean;\n  disabled?: boolean;\n  invisible?: boolean; // 不可见\n}\n\nexport interface ISearchInput {\n  placeholder?: string;\n  submit: (params?: any) => any;\n  width?: string;\n}\n\nexport interface IDTableProps {\n  paginationProps?: object;\n  noPagination?: boolean;\n  rowKey: string;\n  columns: object[];\n  dataSource: object[];\n  loading?: boolean;\n  reloadData?: (params?: object) => any;\n  getOpBtns?: (params?: object) => ITableBtn[];\n  getJsxElement?: (params?: object) => JSX.Element;\n  tableHeaderSearchInput?: ISearchInput;\n  attrs?: object;\n  searchInputRightBtns?: ITableBtn[];\n}\n\nexport const DTable = (props: IDTableProps) => {\n  const renderSearch = () => {\n    if (!props?.tableHeaderSearchInput) return;\n    const { searchInputRightBtns = [] } = props;\n    const { placeholder = null, submit, width } = props?.tableHeaderSearchInput;\n    return (\n      <div className={`${DTablerefix}-box-header-search`}>\n        <div className={`${DTablerefix}-box-header-search-custom`}>\n          {searchInputRightBtns.map((item, index) => {\n            if (item?.type === \"custom\") {\n              return (\n                <span style={{ marginLeft: 10 }} className={item.className} key={index}>\n                  {item?.customFormItem}\n                </span>\n              );\n            }\n            return item.noRefresh ? (\n              <Button className={item.className} key={index}>\n                {item.label}\n              </Button>\n            ) : (\n              <Button disabled={item.disabled} loading={item.loading} key={index} className={item.className} onClick={item.clickFunc}>\n                {\" \"}\n                {item.label}{\" \"}\n              </Button>\n            );\n          })}\n        </div>\n        <div>\n          <Input\n            allowClear\n            placeholder={placeholder || \"请输入关键字\"}\n            style={{ width: width || 200 }}\n            onChange={(e) => {\n              console.log(e, 111);\n              submit(e.target.value);\n            }}\n            suffix={<SearchOutlined style={{ color: \"#ccc\" }} />}\n          />\n        </div>\n      </div>\n    );\n  };\n\n  const renderTableInnerOp = (reloadFunc: any, btns?: ITableBtn[], element?: JSX.Element) => {\n    return (\n      <div className={`${DTablerefix}-box-header-btn`}>\n        {reloadFunc && <ReloadOutlined className=\"reload\" onClick={reloadFunc} />}\n        {btns?.map((item, index) => {\n          return item.noRefresh ? (\n            <Button className={item.className} key={index}>\n              {item.label}\n            </Button>\n          ) : (\n            <Button disabled={item.disabled} loading={item.loading} key={index} className={item.className} onClick={item.clickFunc}>\n              {\" \"}\n              {item.label}{\" \"}\n            </Button>\n          );\n        })}\n        {element}\n      </div>\n    );\n  };\n\n  const {\n    rowKey,\n    loading,\n    dataSource,\n    columns,\n    paginationProps = pagination,\n    noPagination,\n    reloadData,\n    getOpBtns = () => [],\n    getJsxElement = () => <></>,\n    attrs,\n  } = props;\n\n  return (\n    <>\n      <div className={`${DTablerefix}`}>\n        <div className={`${DTablerefix}-box`}>\n          <div className={`${DTablerefix}-box-header`}>\n            {renderTableInnerOp(reloadData, getOpBtns(), getJsxElement())}\n            {renderSearch()}\n          </div>\n          <Table\n            loading={loading}\n            rowKey={rowKey}\n            dataSource={dataSource}\n            columns={columns}\n            pagination={!noPagination ? { ...pagination, ...paginationProps } : false}\n            {...attrs}\n          />\n        </div>\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/DTable/readme.md",
    "content": "# dtable\n\n## 何时使用 \n\n- 当有大量结构化的数据需要展现时；\n- 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。  \n\n## API\n\n| 参数                   | 说明                                                         | 类型                                                         | 默认值     |\n| ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ---------- |\n| paginationProps        | 分页器，参考[配置项](https://ant.design/components/table-cn/#pagination)或 [pagination](https://ant.design/components/pagination-cn/) 文档，设为 false 时不展示和进行分页 | object                                                       |            |\n| rowKey                 | 表格行 key 的取值，可以是字符串或一个函数(必填)              | string \\|function(record): string                            | key        |\n| columns                | 表格列的配置描述，具体项见下表(必填)                         | [ColumnsType](https://ant.design/components/table-cn/#Column)[] |            |\n| dataSource             | 数据数组(必填)                                               | object[]                                                     |            |\n| loading                | 页面是否加载中                                               | boolean \\| [Spin Props](https://ant.design/components/spin-cn/#API) | false      |\n| attrs                  | Table 其他的的一些扩展属性，参考 [Table API](https://ant.design/components/table-cn/#API) | object                                                       |            |\n| reloadData             | 点击刷新图标后执行的函数                               | (params?: object) => any                                     |            |\n| getOpBtns              | 需要显示的功能按钮                                           | (params?: object) => ITableBtn[];                            | () => null |\n| renderInnerOperation   | 自定义的 JSX 元素                                            | (params?: object) => JSX.Element                             | () => null |\n| tableHeaderSearchInput | 如果存在显示搜索框                                           | ISearchInput                     |            |\n\n## paginationProps\n\n分页的配置项\n\n| 参数     | 说明                                                         | 类型  | 默认值          |\n| -------- | ------------------------------------------------------------ | ----- | --------------- |\n| position | 指定分页显示的位置， 取值为指定分页显示的位置， 取值为`topLeft` |`topCenter` |`topRight` |`bottomLeft` |`bottomCenter` |`bottomRight` | Array | [`bottomRight`] |\n\n## ITableBtn\n\n| 参数       | 说明                                                      | 类型                 | 默认值 |\n| ---------- | --------------------------------------------------------- | -------------------- | ------ |\n| label      | 按钮中显示的文字                                          | string \\|JSX.Element |        |\n| isOpenUp   | 如果为 true 直接返回带有文字提示的禁用按钮                | boolean              |        |\n| className  | 如果 isOpenUp 为 false 是按钮的类名                       | string               |        |\n| noRefresh  | 如果为 false 返回带有点击事件、loading 和 disabled 的按钮 | boolean              |        |\n| disabled   | 如果 noRefresh 为 false 时生效，是否禁用按钮              | boolean              |        |\n| loading    | 如果 noRefresh 为 false 时生效，是否开启loading效果       | boolean              |        |\n| iclickFunc | 如果 noRefresh 为 false 时生效，是否开启loading效果       | () =>void            |        |\n\n## ISearchInput\n\n| 参数        | 说明                                               | 类型                     | 默认值       |\n| ----------- | -------------------------------------------------- | ------------------------ | ------------ |\n| submit      | 点击搜索图标、清除图标，或按下回车键时的回调(必填) | (params?: any) => any |              |\n| text        | 搜索框描述                                         | string                   |              |\n| placeholder | 属性提供可描述输入字段预期值的提示信息             | string                   | 请输入关键字 |\n\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/QueryForm/QueryForm.tsx",
    "content": "import React, { useState, useEffect } from \"react\";\nimport classNames from \"classnames\";\nimport { ConfigProviderProps } from \"antd/es/config-provider\";\nimport useAntdMediaQuery from \"./use-media-antd-query\";\nimport { Button, Input, Form, Row, Col, Select, ConfigProvider } from \"antd\";\nimport { DownOutlined } from \"@ant-design/icons\";\n\nimport { useContext } from \"react\";\nimport IntlContext from \"./context\";\n\nfunction useIntl(): any {\n  const i18n = useContext(IntlContext);\n  return i18n;\n}\n\ndeclare const ItemSizes: [\"large\", \"default\", \"small\", string];\nexport declare type ItemSize = typeof ItemSizes[number];\n\ndeclare const ColumnTypes: [\"select\", \"input\", \"custom\", string];\nexport declare type ColumnType = typeof ColumnTypes[number];\n\ndeclare const ModeTypes: [\"full\", \"align\", string];\nexport declare type ModeType = typeof ModeTypes[number];\n\ndeclare const ColTypes: [\"grid\", \"style\", string];\nexport declare type ColType = typeof ColTypes[number];\n\nconst FormItem = Form.Item;\nconst { Option } = Select;\n\nexport interface IColumnsType {\n  type: ColumnType;\n  dataIndex: string;\n  title: string | React.ReactNode;\n  placeholder?: string;\n  valuePropName?: string;\n  required?: boolean;\n  colStyle?: React.CSSProperties;\n  isInputPressEnterCallSearch?: boolean;\n  size?: ItemSize;\n  rules?: any[]; // 校验规则\n  component?: React.ReactNode;\n  componentProps?: any; // 需要传给组件的其他属性\n  selectMode?: string; // 单选或者多选\n  options?: {\n    title: string;\n    value: string | number;\n  }[];\n  formItemLayout?: any;\n}\nexport interface FieldData {\n  name?: string;\n  level?: string;\n  status?: string[];\n  number?: Number;\n}\n\nexport interface IQueryFormProps {\n  prefixCls?: string;\n  className?: string;\n  style?: React.CSSProperties | any;\n  mode?: ModeType;\n  colMode?: ColType;\n  defaultColStyle?: React.CSSProperties;\n  columnStyleHideNumber?: number;\n  columns: IColumnsType[];\n  searchText?: string | React.ReactNode;\n  resetText?: string | React.ReactNode;\n  showOptionBtns?: boolean;\n  showCollapseButton?: boolean;\n  onChange?: (data: any) => any;\n  initialValues: any;\n  onSearch?: (data: any) => any;\n  onReset?: (data: any) => any;\n  getFormInstance?: (form: any) => any;\n  isResetClearAll: boolean;\n  antConfig?: ConfigProviderProps;\n  defaultCollapse?: boolean;\n  colConfig?:\n    | {\n        lg: number;\n        md: number;\n        xxl: number;\n        xl: number;\n        sm: number;\n        xs: number;\n      }\n    | undefined;\n}\n\nconst defaultColConfig = {\n  xs: 24,\n  sm: 24,\n  md: 12,\n  lg: 12,\n  xl: 8,\n  xxl: 6,\n};\n\nconst defaultFormItemLayout = {\n  labelCol: {\n    xs: { span: 5 },\n    sm: { span: 5 },\n    md: { span: 7 },\n    lg: { span: 7 },\n    xl: { span: 8 },\n    xxl: { span: 8 },\n  },\n  wrapperCol: {\n    xs: { span: 19 },\n    sm: { span: 19 },\n    md: { span: 17 },\n    lg: { span: 17 },\n    xl: { span: 16 },\n    xxl: { span: 16 },\n  },\n};\n\n/**\n * 合并用户和默认的配置\n * @param span\n * @param size\n */\nconst getSpanConfig = (span: number | typeof defaultColConfig, size: keyof typeof defaultColConfig): number => {\n  if (typeof span === \"number\") {\n    return span;\n  }\n  const config = {\n    ...defaultColConfig,\n    ...span,\n  };\n  return config[size];\n};\n\n/**\n * 获取最后一行的 offset，保证在最后一列\n * @param length\n * @param span\n */\nconst getOffset = (length: number, span: number = 8) => {\n  const cols = 24 / span;\n  return (cols - 1 - (length % cols)) * span;\n};\n\nconst getCollapseHideNum = (size: number) => {\n  const maps = {\n    6: 3,\n    8: 2,\n    12: 1,\n    24: 1,\n  } as { [key: number]: number };\n\n  return maps[size] || 1;\n};\n\nconst QueryForm = (props: IQueryFormProps) => {\n  const prefixCls = `${props.prefixCls || \"dantd\"}-query-form`;\n  const { t } = useIntl();\n  const {\n    className,\n    style,\n    colConfig,\n    searchText,\n    resetText,\n    showOptionBtns = true,\n    showCollapseButton = true,\n    defaultCollapse = false,\n    isResetClearAll = false,\n    onChange,\n    onSearch,\n    onReset,\n    getFormInstance,\n    columns = [] as IColumnsType[],\n    mode = \"full\",\n    colMode = \"grid\",\n    columnStyleHideNumber = 1,\n    defaultColStyle = {\n      width: \"300px\",\n    },\n    initialValues,\n    // valueType = 'object',\n  } = props;\n  const [form] = Form.useForm();\n  const wrapperClassName = classNames(prefixCls, className);\n  const formItemCls = classNames({\n    [`${prefixCls}-formitem`]: true,\n    [`${prefixCls}-formitem-full`]: mode === \"full\",\n  });\n  const windowSize = useAntdMediaQuery();\n  const itemColConfig = colConfig || defaultColConfig;\n  const [colSize, setColSize] = useState(getSpanConfig(itemColConfig || 8, windowSize));\n  const { validateFields, getFieldsValue, resetFields, setFieldsValue } = form;\n\n  const [collapsed, setCollapse] = useState(defaultCollapse);\n\n  useEffect(() => {\n    setColSize(getSpanConfig(itemColConfig || 8, windowSize));\n  }, [windowSize]);\n\n  useEffect(() => {\n    if (getFormInstance) {\n      getFormInstance(form);\n    }\n  }, []);\n\n  const collapseHideNum = getCollapseHideNum(getSpanConfig(itemColConfig || 8, windowSize));\n\n  const handleSearch = () => {\n    validateFields()\n      .then((values) => {\n        if (onSearch) {\n          onSearch(values);\n        }\n      })\n      .catch(() => {\n        //\n      });\n  };\n\n  const handleReset = () => {\n    if (isResetClearAll) {\n      const resetFieldsObj = columns.reduce((acc, cur: IColumnsType) => {\n        return {\n          ...acc,\n          [cur.dataIndex]: undefined,\n        };\n      }, {});\n      setFieldsValue(resetFieldsObj);\n      (onChange as any)(initialValues);\n    } else {\n      resetFields();\n      (onChange as any)({});\n    }\n\n    setTimeout(() => {\n      if (onReset) {\n        onReset(getFieldsValue());\n      }\n    });\n  };\n\n  const handlePressEnter = () => {\n    handleSearch();\n  };\n\n  const renderInputItem = (colItem: any) => {\n    const {\n      dataIndex,\n      title,\n      required,\n      componentProps = {},\n      placeholder,\n      isInputPressEnterCallSearch,\n      formItemLayout,\n      rules,\n      size = \"default\",\n    } = colItem;\n\n    const itemPlaceholder = placeholder ? placeholder : t(\"form.placeholder.prefix\");\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n    return (\n      <FormItem\n        shouldUpdate={true}\n        key=\"input\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        <Input\n          data-testid=\"field-input\"\n          size={size}\n          placeholder={itemPlaceholder}\n          onPressEnter={isInputPressEnterCallSearch ? handlePressEnter : () => {}}\n          allowClear\n          {...componentProps}\n        />\n      </FormItem>\n    );\n  };\n\n  const renderSelectItem = (colItem: any) => {\n    const {\n      dataIndex,\n      title,\n      required,\n      placeholder,\n      selectMode = \"single\",\n      rules,\n      formItemLayout,\n      options = [],\n      componentProps = {},\n      size = \"default\",\n    } = colItem;\n    const itemPlaceholder = placeholder ? (\n      placeholder\n    ) : (\n      <>\n        {t(\"form.selectplaceholder.prefix\")}\n        &nbsp;\n        {title}\n      </>\n    );\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n\n    return (\n      <FormItem\n        key=\"select\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        <Select\n          data-testid=\"select\"\n          mode={selectMode}\n          size={size}\n          allowClear\n          placeholder={itemPlaceholder}\n          showSearch={true}\n          optionFilterProp=\"children\"\n          style={{ width: \"100%\" }}\n          {...componentProps}\n        >\n          {options.map((option: any) => {\n            return (\n              <Option data-testid=\"select-option\" value={option.value} key={option.value}>\n                {option.title}\n              </Option>\n            );\n          })}\n        </Select>\n      </FormItem>\n    );\n  };\n\n  const renderCustomItem = (colItem: any) => {\n    const { formItemLayout, dataIndex, title, required, placeholder, rules, valuePropName = \"value\", component } = colItem;\n\n    const itemPlaceholder = placeholder ? (\n      placeholder\n    ) : (\n      <>\n        {t(\"form.placeholder.prefix\")}\n        &nbsp;\n        {title}\n      </>\n    );\n\n    let itemRules: any[] = [];\n    if (required) {\n      itemRules = [\n        {\n          required: true,\n          message: itemPlaceholder,\n        },\n      ];\n    }\n\n    const itemFormItemLayout = formItemLayout || mode === \"align\" ? defaultFormItemLayout : {};\n\n    return (\n      <FormItem\n        key=\"custom\"\n        name={dataIndex as string}\n        rules={rules || itemRules}\n        label={title}\n        valuePropName={valuePropName}\n        className={formItemCls}\n        {...itemFormItemLayout}\n      >\n        {component}\n      </FormItem>\n    );\n  };\n\n  const renderOptionBtns = () => {\n    const offsetVal = collapsed\n      ? columns.length <= collapseHideNum\n        ? getOffset(columns.length, colSize)\n        : getOffset(collapseHideNum, colSize)\n      : getOffset(columns.length, colSize);\n    let optionStyle = {};\n    if (colMode === \"style\") {\n      optionStyle = {\n        position: \"absolute\",\n        width: 280,\n        bottom: 0,\n        right: 0,\n        marginLeft: 0,\n      };\n    }\n    return (\n      <Col\n        {...itemColConfig}\n        offset={offsetVal}\n        key=\"option\"\n        className={`${prefixCls}-option`}\n        style={{\n          ...optionStyle,\n        }}\n      >\n        <Form.Item key=\"option\">\n          <span>\n            <Button onClick={handleReset}>{resetText || t(\"queryform.reset\")}</Button>\n            <Button onClick={handleSearch} style={{ marginLeft: 10 }} type=\"primary\" htmlType=\"submit\">\n              {searchText || t(\"queryform.search\")}\n            </Button>\n            {showCollapseButton && (\n              <a\n                style={{\n                  marginLeft: 10,\n                  display: \"inline-block\",\n                }}\n                onClick={() => {\n                  setCollapse(!collapsed);\n                }}\n              >\n                {collapsed ? \"展开\" : \"收起\"}\n                <DownOutlined\n                  style={{\n                    marginLeft: \"0.5em\",\n                    transition: \"0.3s all\",\n                    transform: `rotate(${collapsed ? 0 : 0.5}turn)`,\n                  }}\n                />\n              </a>\n            )}\n          </span>\n        </Form.Item>\n      </Col>\n    );\n  };\n\n  return (\n    <ConfigProvider {...props.antConfig}>\n      <div className={wrapperClassName} style={style}>\n        <Row gutter={16} justify=\"start\">\n          {columns.map((colItem, colIndex) => {\n            let itemHide = collapsed && collapseHideNum <= colIndex;\n            let colItemStyle = {};\n            if (colMode === \"style\") {\n              colItemStyle = colItem.colStyle || defaultColStyle;\n              if (collapsed && colIndex >= columnStyleHideNumber) {\n                itemHide = true;\n              }\n            }\n            colItemStyle = {\n              ...colItemStyle,\n              display: itemHide ? \"none\" : \"block\",\n            };\n            return (\n              <Col style={colItemStyle} key={`query-form-col-${colItem.dataIndex}-${colIndex}`} {...itemColConfig}>\n                <Form\n                  form={form}\n                  onFieldsChange={(_changedFields, allFields) => {\n                    (onChange as any)(allFields);\n                  }}\n                  initialValues={initialValues}\n                >\n                  {colItem.type === \"input\" && renderInputItem(colItem)}\n                  {colItem.type === \"select\" && renderSelectItem(colItem)}\n                  {colItem.type === \"custom\" && renderCustomItem(colItem)}\n                </Form>\n              </Col>\n            );\n          })}\n          {showOptionBtns && renderOptionBtns()}\n        </Row>\n      </div>\n    </ConfigProvider>\n  );\n};\n\nexport default QueryForm;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/QueryForm/context.tsx",
    "content": "import { createContext } from 'react';\n\ninterface IContextProps {\n  t: (key: any) => any;\n}\n\n\nconst IntlContext = createContext<IContextProps>({\n  t: () => '展开',\n});\n\nexport default IntlContext;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/QueryForm/index.tsx",
    "content": "import './style/index.less';\nimport QueryForm from './QueryForm';\nexport default QueryForm;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/QueryForm/readme.md",
    "content": "# query-form\n\n## 何时使用\n\n需要一个数据查询组件时使用，组件会自己管理状态并返回查询的数据。\n\n## API\n\n\n### QueryForm\n\n| 参数       | 说明           | 类型                | 默认值 |\n| :--------- | :------------- | :------------------ | :----- |\n| columns | 表单列的配置描述，具体项见下表（必填） | ColumnProps | []     |\n| initialValues | 表单默认值，只有初始化时生效 | object | -     |\n| searchText | 搜索按钮的文案 | string \\| React.ReactNode | 查询     |\n| resetText | 重置按钮的文案 | string \\| React.ReactNode | 重置     |\n| mode      | `FormItem` 的标题展示模式，`full`是占满整行，左对齐； `align` 会根据标题右对齐 | `['full', 'align']`              | `'full'`     |\n| colMode      | `FormItem` 的展示模式，`grid`是等分的栅格布局； `style` 会根据会对每个 `Col` 增加固定 `300px` 的宽度，也可以通过 `Column.colStyle` 自定义宽度等样式 | `['grid', 'style']`              | `'grid'`     |\n| showOptionBtns | 是否展示右下角的「查询」「重置」按钮，以及「展开」「收起」 | boolean | true      |\n| showCollapseButton | 是否展示右下角的「展开」「收起」 | boolean | true     |\n| onChange | 表单的值改变时触发的回调 | Function(values, form) | - |\n| onSearch | 点击查询按钮的回调 | Function(values, form) | - |\n| onReset | 点击重置按钮的回调 | Function(form) | - |\n| isResetClearAll | 点击重置时，是清空form里面的值，还是根据 `initialValue` 重置 | boolean | false     |\n| getFormInstance | 只用来获取Form实例的回调 | Function(form) | - |\n| defaultCollapse | 是否默认「展开」 | boolean | true     |\n| colConfig | Col 布局配置 | `{lg:number;md:number;xxl:number;xl:number;sm:number;xs:number}` | `{xs:24,sm:24,md:12,lg:12,xl:8,xxl:6}` |\n| antConfig | 使用 `Antd ConfigProvider` 进行的全局配置，需要通过这个属性传进来 | [ConfigProviderProps](https://github.com/ant-design/ant-design/blob/master/components/config-provider/index.tsx) | - |\n\n### Columns\n\n表单列的配置描述，目前支持 `['input', 'select', 'custom']` 这三种。\n\n| 参数       | 说明           | 类型                | 默认值 |\n| :--------- | :------------- | :------------------ | :----- |\n| type      | 动态表单组件的类型，内置 `input`, `select`；也可以自定义  | `['input', 'select', 'custom']`              | -      |\n| title      | 标题    | string              |  -      |\n| dataIndex      | form表单的唯一标识，不可以重复   | string              |  -      |\n| placeholder | 占位文案，默认会根据 `title` 自动生成 | string | -     |\n| isInputPressEnterCallSearch | 输入框按回车的时候，触发搜索 | boolean | -     |\n| valuePropName | 子节点的值的属性，如 Switch 的是 'checked' | string | 'value'    |\n| required | 是否对参数进行必填校验 | boolean | true      |\n| colStyle | `colMode='style'` 时，可以设置单个 `Column` 的样式| `React.CSSProperties` | -      |\n| columnStyleHideNumber | `colMode='style'` 时，收起时默认只展示一项，可以设置展示多项| number | 1      |\n| formItemLayout | 表单的Layout | `{labelCol:{xs:{span:number},sm:{span:number},md:{span:number},lg:{span:number},xl:{span:number},xxl:{span:number}},wrapperCol:{xs:{span:number},sm:{span:number},md:{span:number},lg:{span:number},xl:{span:number},xxl:{span:number}}}` | `{labelCol:{xs:{span:5},sm:{span:5},md:{span:7},lg:{span:7},xl:{span:8},xxl:{span:8},},wrapperCol:{xs:{span:19},sm:{span:19},md:{span:17},lg:{span:17},xl:{span:16},xxl:{span:16},},}`     |\n| rules | 自定义表单项的校验规则 | `object[]` | -      |\n| size | 表单项的 `size` 属性 | `large` \\| `default` \\| `small` | `default`   |\n| componentProps | `type=\"input|select\"` 时，可以通过该属性 ant 组件的Props | any | -      |\n| component | `type=\"custom\"` 时，可以通过该属性传递 `React.ReactNode` |  React.ReactNode | -      |\n| selectMode | `type=\"select\"` 时的 `mode` 属性 | `default` \\| `multiple` | `default`      |\n| options | `type=\"select\"` 时，通过该属性设置下拉选项 | {title: string;value: string;}[] | []      |\n\n## Demo\n\n```js\nimport { useState } from 'react';\nimport { QueryForm, InputNumber, Card, Button, Modal } from 'antd-advanced';\n\n\nconst columns = [\n  {\n    type: 'input',\n    title: '实例名称',\n    dataIndex: 'name',\n  },\n  {\n    type: 'select',\n    title: '报警等级',\n    dataIndex: 'level',\n    options: [\n      {\n        title: '全部',\n        value: 'all',\n      },\n      {\n        title: 'P0',\n        value: 'p0',\n      },\n      {\n        title: 'P1',\n        value: 'p1',\n      },\n      {\n        title: 'P2',\n        value: 'p2',\n      },\n    ],\n  },\n  {\n    type: 'select',\n    title: '任务状态',\n    dataIndex: 'status',\n    selectMode: 'multiple',\n    options: [\n      {\n        title: '进行中',\n        value: 'processing',\n      },\n      {\n        title: '成功',\n        value: 'success',\n      },\n      {\n        title: '失败',\n        value: 'fail',\n      },\n    ],\n  },\n  {\n    type: 'custom',\n    title: '机器数量',\n    dataIndex: 'number',\n    component: (\n      <InputNumber\n        placeholder=\"请输入机器数量\"\n        style={{ marginTop: 4, width: '100%' }}\n        min={0}\n        precision={0}\n      />\n    ),\n  },\n];\n\nconst Demo: React.FC = () => {\n  const initialValues = {\n    name: 'test',\n    level: 'p1',\n  }\n  const [result, setResult] = useState(initialValues);\n  const [isModalVisible, setIsModalVisible] = useState(false);\n\n  const showModal = () => {\n    setIsModalVisible(true);\n  };\n\n  const handleOk = () => {\n    setIsModalVisible(false);\n  };\n\n  const handleCancel = () => {\n    setIsModalVisible(false);\n  };\n  const handleChange = queryValue => {\n    setResult(queryValue);\n  };\n  return (\n    <div>\n      <QueryForm \n        onChange={handleChange} \n        onSearch={handleChange}\n        columns={columns} \n        initialValues={initialValues}\n      />\n      <h3>结果：</h3>\n      <div>{JSON.stringify(result)}</div>\n\n      <Card>\n        <Button type=\"primary\" onClick={showModal}>\n          Open Modal\n        </Button>\n        <Modal title=\"Basic Modal\" visible={isModalVisible} onOk={handleOk} onCancel={handleCancel}>\n          <p>Some contents...</p>\n          <p>Some contents...</p>\n          <p>Some contents...</p>\n        </Modal>\n      </Card>\n    </div>\n  );\n}\n\nReactDOM.render(\n  <div>\n    <Demo />\n  </div>,\n  mountNode,\n);\n```"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/QueryForm/style/index.less",
    "content": ".dantd-query-form {\n  padding: 20px 20px 0 20px;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/QueryForm/style/index.tsx",
    "content": "import './index.less';\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/QueryForm/use-media-antd-query.ts",
    "content": "import { useState, useEffect } from 'react';\nimport useMediaQuery from './use-media';\n\nexport const MediaQueryEnum = {\n  xs: '(max-width: 575px)',\n  sm: '(min-width: 576px) and (max-width: 767px)',\n  md: '(min-width: 768px) and (max-width: 991px)',\n  lg: '(min-width: 992px) and (max-width: 1199px)',\n  xl: '(min-width: 1200px) and (max-width: 1599px)',\n  xxl: '(min-width: 1600px)',\n};\n\nexport type MediaQueryKey = keyof typeof MediaQueryEnum;\n\n/**\n * loop query screen className\n * Array.find will throw a error\n * `Rendered more hooks than during the previous render.`\n * So should use Array.forEach\n */\nexport const getScreenClassName = () => {\n  let className: MediaQueryKey = 'md';\n  // support ssr\n  if (typeof window === 'undefined') {\n    return className;\n  }\n  const mediaQueryKey = (Object.keys(MediaQueryEnum) as MediaQueryKey[]).find((key) => {\n    const matchMedia = MediaQueryEnum[key];\n    if (window.matchMedia(matchMedia).matches) {\n      return true;\n    }\n    return false;\n  });\n  className = (mediaQueryKey as unknown) as MediaQueryKey;\n  return className;\n};\n\nconst useMedia = () => {\n  const isMd = useMediaQuery(MediaQueryEnum.md);\n  const isLg = useMediaQuery(MediaQueryEnum.lg);\n  const isXxl = useMediaQuery(MediaQueryEnum.xxl);\n  const isXl = useMediaQuery(MediaQueryEnum.xl);\n  const isSm = useMediaQuery(MediaQueryEnum.sm);\n  const isXs = useMediaQuery(MediaQueryEnum.xs);\n  const [colSpan, setColSpan] = useState<keyof typeof MediaQueryEnum>(getScreenClassName());\n\n  useEffect(() => {\n    if (isXxl) {\n      setColSpan('xxl');\n      return;\n    }\n    if (isXl) {\n      setColSpan('xl');\n      return;\n    }\n    if (isLg) {\n      setColSpan('lg');\n      return;\n    }\n    if (isMd) {\n      setColSpan('md');\n      return;\n    }\n    if (isSm) {\n      setColSpan('sm');\n      return;\n    }\n    if (isXs) {\n      setColSpan('xs');\n      return;\n    }\n    setColSpan('md');\n  }, [isMd, isLg, isXxl, isXl, isSm, isXs]);\n\n  return colSpan;\n};\n\nexport default useMedia;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/QueryForm/use-media.ts",
    "content": "import { useEffect, useState } from 'react';\n\nexport const isClient = typeof window === 'object';\n\nconst useMedia = (query: string, defaultState: boolean = false) => {\n  const [state, setState] = useState(\n    isClient ? () => window.matchMedia(query).matches : defaultState,\n  );\n\n  useEffect(() => {\n    let mounted = true;\n    const mql = window.matchMedia(query);\n    const onChange = () => {\n      if (!mounted) {\n        return;\n      }\n      setState(!!mql.matches);\n    };\n\n    mql.addListener(onChange);\n    setState(mql.matches);\n\n    return () => {\n      mounted = false;\n      mql.removeListener(onChange);\n    };\n  }, [query]);\n\n  return state;\n};\n\nexport default useMedia;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/config-provider/demo/direction.md",
    "content": "---\norder: 2\ntitle:\n  zh-CN: 方向\n  en-US: Direction\n---\n\n## zh-CN\n\n这里列出了支持 `rtl` 方向的组件，您可以在演示中切换方向。\n\n## en-US\n\nComponents which support rtl direction are listed here, you can toggle the direction in the demo.\n\n```jsx\nimport {\n  Row, \n  Col, \n  TreeSelect,\n  Input,\n  Select,\n  InputNumber,\n  ConfigProvider,\n  Cascader,\n  Radio,\n  Switch,\n  Tree,\n  Modal,\n  Button,\n  Pagination,\n  Steps,\n  Rate,\n  Badge,\n  Divider\n} from 'antd-advanced';\n\nimport {\n  SearchOutlined as SearchIcon,\n  SmileOutlined,\n  DownloadOutlined,\n  LeftOutlined,\n  RightOutlined,\n  MinusOutlined,\n  PlusOutlined,\n} from '@ant-design/icons';\n\nconst InputGroup = Input.Group;\nconst ButtonGroup = Button.Group;\nconst { Option } = Select;\nconst { TreeNode } = Tree;\nconst { Search } = Input;\nconst { Step } = Steps;\n\nconst cascaderOptions = [\n  {\n    value: 'tehran',\n    label: 'تهران',\n    children: [\n      {\n        value: 'tehran-c',\n        label: 'تهران',\n        children: [\n          {\n            value: 'saadat-abad',\n            label: 'سعادت آیاد',\n          },\n        ],\n      },\n    ],\n  },\n  {\n    value: 'ardabil',\n    label: 'اردبیل',\n    children: [\n      {\n        value: 'ardabil-c',\n        label: 'اردبیل',\n        children: [\n          {\n            value: 'primadar',\n            label: 'پیرمادر',\n          },\n        ],\n      },\n    ],\n  },\n  {\n    value: 'gilan',\n    label: 'گیلان',\n    children: [\n      {\n        value: 'rasht',\n        label: 'رشت',\n        children: [\n          {\n            value: 'district-3',\n            label: 'منطقه ۳',\n          },\n        ],\n      },\n    ],\n  },\n];\n\nclass Page extends React.Component {\n  state = {\n    currentStep: 0,\n    modalVisible: false,\n\n    badgeCount: 5,\n    showBadge: true,\n  };\n\n  selectBefore = (\n    <Select defaultValue=\"Http://\" style={{ width: 90 }}>\n      <Option value=\"Http://\">Http://</Option>\n      <Option value=\"Https://\">Https://</Option>\n    </Select>\n  );\n\n  selectAfter = (\n    <Select defaultValue=\".com\" style={{ width: 80 }}>\n      <Option value=\".com\">.com</Option>\n      <Option value=\".jp\">.jp</Option>\n      <Option value=\".cn\">.cn</Option>\n      <Option value=\".org\">.org</Option>\n    </Select>\n  );\n\n  // ==== Cascader ====\n  cascaderFilter = (inputValue, path) =>\n    path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);\n\n  onCascaderChange = value => {\n    console.log(value);\n  };\n  // ==== End Cascader ====\n\n  // ==== Modal ====\n  showModal = () => {\n    this.setState({\n      modalVisible: true,\n    });\n  };\n\n  handleOk = e => {\n    console.log(e);\n    this.setState({\n      modalVisible: false,\n    });\n  };\n\n  handleCancel = e => {\n    console.log(e);\n    this.setState({\n      modalVisible: false,\n    });\n  };\n  // ==== End Modal ====\n\n  onStepsChange = currentStep => {\n    console.log('onChange:', currentStep);\n    this.setState({ currentStep });\n  };\n\n  // ==== Badge ====\n\n  increaseBadge = () => {\n    const badgeCount = this.state.badgeCount + 1;\n    this.setState({ badgeCount });\n  };\n\n  declineBadge = () => {\n    let badgeCount = this.state.badgeCount - 1;\n    if (badgeCount < 0) {\n      badgeCount = 0;\n    }\n    this.setState({ badgeCount });\n  };\n\n  onChangeBadge = showBadge => {\n    this.setState({ showBadge });\n  };\n  // ==== End Badge ====\n\n  render() {\n    const { currentStep } = this.state;\n    return (\n      <div className=\"direction-components\">\n        <Row>\n          <Col span={24}>\n            <Divider orientation=\"left\">Cascader example</Divider>\n            <Cascader\n              suffixIcon={<SearchIcon />}\n              options={cascaderOptions}\n              onChange={this.onCascaderChange}\n              placeholder=\"یک مورد انتخاب کنید\"\n              popupPlacement={this.props.popupPlacement}\n            />\n            &nbsp;&nbsp;&nbsp;&nbsp; With search:\n            <Cascader\n              suffixIcon={<SmileOutlined />}\n              options={cascaderOptions}\n              onChange={this.onCascaderChange}\n              placeholder=\"Select an item\"\n              popupPlacement={this.props.popupPlacement}\n              showSearch={this.cascaderFilter}\n            />\n          </Col>\n        </Row>\n        <br />\n        <Row>\n          <Col span={12}>\n            <Divider orientation=\"left\">Switch example</Divider>\n            &nbsp;&nbsp;\n            <Switch defaultChecked />\n            &nbsp;&nbsp;\n            <Switch loading defaultChecked />\n            &nbsp;&nbsp;\n            <Switch size=\"small\" loading />\n          </Col>\n          <Col span={12}>\n            <Divider orientation=\"left\">Radio Group example</Divider>\n\n            <Radio.Group defaultValue=\"c\" buttonStyle=\"solid\">\n              <Radio.Button value=\"a\">تهران</Radio.Button>\n              <Radio.Button value=\"b\" disabled>\n                اصفهان\n              </Radio.Button>\n              <Radio.Button value=\"c\">فارس</Radio.Button>\n              <Radio.Button value=\"d\">خوزستان</Radio.Button>\n            </Radio.Group>\n          </Col>\n        </Row>\n        <br />\n        <Row>\n          <Col span={12}>\n            <Divider orientation=\"left\">Button example</Divider>\n            <div className=\"button-demo\">\n              <Button type=\"primary\" icon={<DownloadOutlined />} />\n              <Button type=\"primary\" shape=\"circle\" icon={<DownloadOutlined />} />\n              <Button type=\"primary\" shape=\"round\" icon={<DownloadOutlined />} />\n              <Button type=\"primary\" shape=\"round\" icon={<DownloadOutlined />}>\n                Download\n              </Button>\n              <Button type=\"primary\" icon={<DownloadOutlined />}>\n                Download\n              </Button>\n              <br />\n              <Button.Group>\n                <Button type=\"primary\">\n                  <LeftOutlined />\n                  Backward\n                </Button>\n                <Button type=\"primary\">\n                  Forward\n                  <RightOutlined />\n                </Button>\n              </Button.Group>\n              <Button type=\"primary\" loading>\n                Loading\n              </Button>\n              <Button type=\"primary\" size=\"small\" loading>\n                Loading\n              </Button>\n            </div>\n          </Col>\n          <Col span={12}>\n            <Divider orientation=\"left\">Tree example</Divider>\n            <Tree\n              showLine\n              checkable\n              defaultExpandedKeys={['0-0-0', '0-0-1']}\n              defaultSelectedKeys={['0-0-0', '0-0-1']}\n              defaultCheckedKeys={['0-0-0', '0-0-1']}\n            >\n              <TreeNode title=\"parent 1\" key=\"0-0\">\n                <TreeNode title=\"parent 1-0\" key=\"0-0-0\" disabled>\n                  <TreeNode title=\"leaf\" key=\"0-0-0-0\" disableCheckbox />\n                  <TreeNode title=\"leaf\" key=\"0-0-0-1\" />\n                </TreeNode>\n                <TreeNode title=\"parent 1-1\" key=\"0-0-1\">\n                  <TreeNode title={<span style={{ color: '#1890ff' }}>sss</span>} key=\"0-0-1-0\" />\n                </TreeNode>\n              </TreeNode>\n            </Tree>\n          </Col>\n        </Row>\n        <br />\n        <Row>\n          <Col span={24}>\n            <Divider orientation=\"left\">Input (Input Group) example</Divider>\n            <InputGroup size=\"large\">\n              <Row gutter={8}>\n                <Col span={5}>\n                  <Input defaultValue=\"0571\" />\n                </Col>\n                <Col span={8}>\n                  <Input defaultValue=\"26888888\" />\n                </Col>\n              </Row>\n            </InputGroup>\n            <br />\n            <InputGroup compact>\n              <Input style={{ width: '20%' }} defaultValue=\"0571\" />\n              <Input style={{ width: '30%' }} defaultValue=\"26888888\" />\n            </InputGroup>\n            <br />\n            <InputGroup compact>\n              <Select defaultValue=\"Option1\">\n                <Option value=\"Option1\">Option1</Option>\n                <Option value=\"Option2\">Option2</Option>\n              </Select>\n              <Input style={{ width: '50%' }} defaultValue=\"input content\" />\n              <InputNumber />\n            </InputGroup>\n            <br />\n            <Search placeholder=\"input search text\" enterButton=\"Search\" size=\"large\" />\n            <br />\n            <br />\n            <div style={{ marginBottom: 16 }}>\n              <Input\n                addonBefore={this.selectBefore}\n                addonAfter={this.selectAfter}\n                defaultValue=\"mysite\"\n              />\n            </div>\n            <br />\n            <Row>\n              <Col span={12}>\n                <Divider orientation=\"left\">Select example</Divider>\n                <Select mode=\"multiple\" defaultValue=\"مورچه\" style={{ width: 120 }}>\n                  <Option value=\"jack\">Jack</Option>\n                  <Option value=\"مورچه\">مورچه</Option>\n                  <Option value=\"disabled\" disabled>\n                    Disabled\n                  </Option>\n                  <Option value=\"Yiminghe\">yiminghe</Option>\n                </Select>\n                <Select defaultValue=\"مورچه\" style={{ width: 120 }} disabled>\n                  <Option value=\"مورچه\">مورچه</Option>\n                </Select>\n                <Select defaultValue=\"مورچه\" style={{ width: 120 }} loading>\n                  <Option value=\"مورچه\">مورچه</Option>\n                </Select>\n                <Select\n                  showSearch\n                  style={{ width: 200 }}\n                  placeholder=\"Select a person\"\n                  optionFilterProp=\"children\"\n                  filterOption={(input, option) =>\n                    option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0\n                  }\n                >\n                  <Option value=\"jack\">Jack</Option>\n                  <Option value=\"سعید\">سعید</Option>\n                  <Option value=\"tom\">Tom</Option>\n                </Select>\n              </Col>\n              <Col span={12}>\n                <Divider orientation=\"left\">TreeSelect example</Divider>\n                <div>\n                  <TreeSelect\n                    showSearch\n                    style={{ width: '100%' }}\n                    dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}\n                    placeholder=\"Please select\"\n                    allowClear\n                    treeDefaultExpandAll\n                  >\n                    <TreeNode value=\"parent 1\" title=\"parent 1\" key=\"0-1\">\n                      <TreeNode value=\"parent 1-0\" title=\"parent 1-0\" key=\"0-1-1\">\n                        <TreeNode value=\"leaf1\" title=\"my leaf\" key=\"random\" />\n                        <TreeNode value=\"leaf2\" title=\"your leaf\" key=\"random1\" />\n                      </TreeNode>\n                      <TreeNode value=\"parent 1-1\" title=\"parent 1-1\" key=\"random2\">\n                        <TreeNode\n                          value=\"sss\"\n                          title={<b style={{ color: '#08c' }}>sss</b>}\n                          key=\"random3\"\n                        />\n                      </TreeNode>\n                    </TreeNode>\n                  </TreeSelect>\n                </div>\n              </Col>\n            </Row>\n            <br />\n            <Row>\n              <Col span={24}>\n                <Divider orientation=\"left\">Modal example</Divider>\n                <div>\n                  <Button type=\"primary\" onClick={this.showModal}>\n                    Open Modal\n                  </Button>\n                  <Modal\n                    title=\"پنچره ساده\"\n                    visible={this.state.modalVisible}\n                    onOk={this.handleOk}\n                    onCancel={this.handleCancel}\n                  >\n                    <p>نگاشته‌های خود را اینجا قراردهید</p>\n                    <p>نگاشته‌های خود را اینجا قراردهید</p>\n                    <p>نگاشته‌های خود را اینجا قراردهید</p>\n                  </Modal>\n                </div>\n              </Col>\n            </Row>\n            <br />\n            <Row>\n              <Col span={24}>\n                <Divider orientation=\"left\">Steps example</Divider>\n                <div>\n                  <Steps progressDot current={currentStep}>\n                    <Step title=\"Finished\" description=\"This is a description.\" />\n                    <Step title=\"In Progress\" description=\"This is a description.\" />\n                    <Step title=\"Waiting\" description=\"This is a description.\" />\n                  </Steps>\n                  <br />\n                  <Steps current={currentStep} onChange={this.onStepsChange}>\n                    <Step title=\"Step 1\" description=\"This is a description.\" />\n                    <Step title=\"Step 2\" description=\"This is a description.\" />\n                    <Step title=\"Step 3\" description=\"This is a description.\" />\n                  </Steps>\n                </div>\n              </Col>\n            </Row>\n            <br />\n            <Row>\n              <Col span={12}>\n                <Divider orientation=\"left\">Rate example</Divider>\n                <div>\n                  <Rate defaultValue={2.5} />\n                  <br />\n                  <strong>* Note:</strong> Half star not implemented in RTL direction, it will be\n                  supported after <a href=\"https://github.com/react-component/rate\">rc-rate</a>{' '}\n                  implement rtl support.\n                </div>\n              </Col>\n              <Col span={12}>\n                <Divider orientation=\"left\">Badge example</Divider>\n                <div>\n                  <div>\n                    <Badge count={this.state.badgeCount}>\n                      <a href=\"#\" className=\"head-example\" />\n                    </Badge>\n                    <ButtonGroup>\n                      <Button onClick={this.declineBadge}>\n                        <MinusOutlined />\n                      </Button>\n                      <Button onClick={this.increaseBadge}>\n                        <PlusOutlined />\n                      </Button>\n                    </ButtonGroup>\n                  </div>\n                  <div style={{ marginTop: 10 }}>\n                    <Badge dot={this.state.showBadge}>\n                      <a href=\"#\" className=\"head-example\" />\n                    </Badge>\n                    <Switch onChange={this.onChangeBadge} checked={this.state.showBadge} />\n                  </div>\n                </div>\n              </Col>\n            </Row>\n          </Col>\n        </Row>\n\n        <br />\n        <br />\n        <Row>\n          <Col span={24}>\n            <Divider orientation=\"left\">Pagination example</Divider>\n            <Pagination showSizeChanger defaultCurrent={3} total={500} />\n          </Col>\n        </Row>\n        <br />\n        <Row>\n          <Col span={24}>\n            <Divider orientation=\"left\">Grid System example</Divider>\n            <div className=\"grid-demo\">\n              <div className=\"code-box-demo\">\n                <p>\n                  <strong>* Note:</strong> Every calculation in RTL grid system is from right side\n                  (offset, push, etc.)\n                </p>\n                <Row>\n                  <Col span={8}>col-8</Col>\n                  <Col span={8} offset={8}>\n                    col-8\n                  </Col>\n                </Row>\n                <Row>\n                  <Col span={6} offset={6}>\n                    col-6 col-offset-6\n                  </Col>\n                  <Col span={6} offset={6}>\n                    col-6 col-offset-6\n                  </Col>\n                </Row>\n                <Row>\n                  <Col span={12} offset={6}>\n                    col-12 col-offset-6\n                  </Col>\n                </Row>\n                <Row>\n                  <Col span={18} push={6}>\n                    col-18 col-push-6\n                  </Col>\n                  <Col span={6} pull={18}>\n                    col-6 col-pull-18\n                  </Col>\n                </Row>\n              </div>\n            </div>\n          </Col>\n        </Row>\n      </div>\n    );\n  }\n}\n\nclass App extends React.Component {\n  state = {\n    direction: 'ltr',\n    popupPlacement: 'bottomLeft',\n  };\n\n  changeDirection = e => {\n    const directionValue = e.target.value;\n    this.setState({ direction: directionValue });\n    if (directionValue === 'rtl') {\n      this.setState({ popupPlacement: 'bottomRight' });\n    } else {\n      this.setState({ popupPlacement: 'bottomLeft' });\n    }\n  };\n\n  render() {\n    const { direction, popupPlacement } = this.state;\n    return (\n      <>\n        <div style={{ marginBottom: 16 }}>\n          <span style={{ marginRight: 16 }}>Change direction of components: </span>\n          <Radio.Group defaultValue=\"ltr\" onChange={this.changeDirection}>\n            <Radio.Button key=\"ltr\" value=\"ltr\">\n              LTR\n            </Radio.Button>\n            <Radio.Button key=\"rtl\" value=\"rtl\">\n              RTL\n            </Radio.Button>\n          </Radio.Group>\n        </div>\n        <ConfigProvider direction={direction}>\n          <Page className={direction} popupPlacement={popupPlacement} />\n        </ConfigProvider>\n      </>\n    );\n  }\n}\n\nReactDOM.render(<App />, mountNode);\n```\n\n```css\n.button-demo .ant-btn,\n.button-demo .ant-btn-group {\n  margin-right: 8px;\n  margin-bottom: 12px;\n}\n.button-demo .ant-btn-group > .ant-btn,\n.button-demo .ant-btn-group > span > .ant-btn {\n  margin-right: 0;\n  margin-left: 0;\n}\n\n.head-example {\n  display: inline-block;\n  width: 42px;\n  height: 42px;\n  vertical-align: middle;\n  background: #eee;\n  border-radius: 4px;\n}\n\n.ant-badge:not(.ant-badge-not-a-wrapper) {\n  margin-right: 20px;\n}\n.ant-badge-rtl:not(.ant-badge-not-a-wrapper) {\n  margin-right: 0;\n  margin-left: 20px;\n}\n```\n\n<style>\n[data-theme=\"dark\"] .head-example {\n  background: rgba(255,255,255,.12);\n}\n</style>\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/config-provider/demo/locale.md",
    "content": "---\norder: 1\ntitle:\n  zh-CN: 国际化\n  en-US: Locale\n---\n\n## zh-CN\n\n此处列出 Ant Design 中需要国际化支持的组件，你可以在演示里切换语言。\n\n## en-US\n\nComponents which need localization support are listed here, you can toggle the language in the demo.\n\n```jsx\nimport {\n  ConfigProvider,\n  Pagination,\n  DatePicker,\n  TimePicker,\n  Calendar,\n  Popconfirm,\n  Table,\n  Modal,\n  Button,\n  Select,\n  Transfer,\n  Radio,\n} from 'antd-advanced';\n\nimport enUS from 'antd-advanced/locale/en_US';\nimport zhCN from 'antd-advanced/locale/zh_CN';\n\nimport moment from 'moment';\nimport 'moment/locale/zh-cn';\n\nmoment.locale('en');\n\nconst { Option } = Select;\nconst { RangePicker } = DatePicker;\n\nconst columns = [\n  {\n    title: 'Name',\n    dataIndex: 'name',\n    filters: [\n      {\n        text: 'filter1',\n        value: 'filter1',\n      },\n    ],\n  },\n  {\n    title: 'Age',\n    dataIndex: 'age',\n  },\n];\n\nclass Page extends React.Component {\n  state = {\n    visible: false,\n  };\n\n  showModal = () => {\n    this.setState({ visible: true });\n  };\n\n  hideModal = () => {\n    this.setState({ visible: false });\n  };\n\n  render() {\n    const info = () => {\n      Modal.info({\n        title: 'some info',\n        content: 'some info',\n      });\n    };\n    const confirm = () => {\n      Modal.confirm({\n        title: 'some info',\n        content: 'some info',\n      });\n    };\n    return (\n      <div className=\"locale-components\">\n        <div className=\"example\">\n          <Pagination defaultCurrent={1} total={50} showSizeChanger />\n        </div>\n        <div className=\"example\">\n          <Select showSearch style={{ width: 200 }}>\n            <Option value=\"jack\">jack</Option>\n            <Option value=\"lucy\">lucy</Option>\n          </Select>\n          <DatePicker />\n          <TimePicker />\n          <RangePicker style={{ width: 200 }} />\n        </div>\n        <div className=\"example\">\n          <Button type=\"primary\" onClick={this.showModal}>\n            Show Modal\n          </Button>\n          <Button onClick={info}>Show info</Button>\n          <Button onClick={confirm}>Show confirm</Button>\n          <Popconfirm title=\"Question?\">\n            <a href=\"#\">Click to confirm</a>\n          </Popconfirm>\n        </div>\n        <div className=\"example\">\n          <Transfer dataSource={[]} showSearch targetKeys={[]} render={item => item.title} />\n        </div>\n        <div className=\"site-config-provider-calendar-wrapper\">\n          <Calendar fullscreen={false} value={moment()} />\n        </div>\n        <div className=\"example\">\n          <Table dataSource={[]} columns={columns} />\n        </div>\n        <Modal title=\"Locale Modal\" visible={this.state.visible} onCancel={this.hideModal}>\n          <p>Locale Modal</p>\n        </Modal>\n      </div>\n    );\n  }\n}\n\nclass App extends React.Component {\n  constructor() {\n    super();\n    this.state = {\n      locale: enUS,\n    };\n  }\n\n  changeLocale = e => {\n    const localeValue = e.target.value;\n    this.setState({ locale: localeValue });\n    if (!localeValue) {\n      moment.locale('en');\n    } else {\n      moment.locale('zh-cn');\n    }\n  };\n\n  render() {\n    const { locale } = this.state;\n    return (\n      <div>\n        <div className=\"change-locale\">\n          <span style={{ marginRight: 16 }}>Change locale of components: </span>\n          <Radio.Group value={locale} onChange={this.changeLocale}>\n            <Radio.Button key=\"en\" value={enUS}>\n              English\n            </Radio.Button>\n            <Radio.Button key=\"cn\" value={zhCN}>\n              中文\n            </Radio.Button>\n          </Radio.Group>\n        </div>\n        <ConfigProvider locale={locale}>\n          <Page\n            key={locale ? locale.locale : 'en' /* Have to refresh for production environment */}\n          />\n        </ConfigProvider>\n      </div>\n    );\n  }\n}\n\nReactDOM.render(<App />, mountNode);\n```\n\n```css\n.site-config-provider-calendar-wrapper {\n  width: 319px;\n  border: 1px solid #d9d9d9;\n  border-radius: 2px;\n}\n\n.locale-components {\n  padding-top: 16px;\n  border-top: 1px solid #d9d9d9;\n}\n\n.code-box-demo .example {\n  margin: 16px 0;\n}\n\n.code-box-demo .example > * {\n  margin-right: 8px;\n}\n\n.change-locale {\n  margin-bottom: 16px;\n}\n```\n\n<style>\n[data-theme=\"dark\"] .locale-components {\n  border-top: 1px solid #303030;\n}\n[data-theme=\"dark\"] .site-config-provider-calendar-wrapper {\n  border: 1px solid #303030;\n}\n</style>\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/config-provider/demo/prefixCls.md",
    "content": "---\norder: 99\ntitle:\n  zh-CN: 前缀\n  en-US: prefixCls\ndebug: true\n---\n\n## zh-CN\n\n修改组件和图标前缀。\n\n## en-US\n\nConfig component and icon prefixCls.\n\n```jsx\nimport { ConfigProvider, Select } from 'antd-advanced';\nimport { SmileOutlined } from '@ant-design/icons';\n\n// Ant Design site use `es` module for view\n// but do not replace related lib `lib` with `es`\n// which do not show correct in site.\n// We may need do convert in site also.\nconst FormSizeDemo = () => (\n  <ConfigProvider prefixCls=\"light\" iconPrefixCls=\"bamboo\">\n    <SmileOutlined />\n    <Select />\n  </ConfigProvider>\n);\nReactDOM.render(<FormSizeDemo />, mountNode);\n```\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/config-provider/demo/size.md",
    "content": "---\norder: 2\ntitle:\n  zh-CN: 组件尺寸\n  en-US: Component size\n---\n\n## zh-CN\n\n修改默认组件尺寸。\n\n## en-US\n\nConfig component default size.\n\n```jsx\nimport React, { useState } from 'react';\nimport {\n  ConfigProvider,\n  Radio,\n  Input,\n  Button,\n  Select,\n  DatePicker,\n  Divider,\n  Table,\n  Card,\n  Tabs,\n} from 'antd-advanced';\n\nconst { TabPane } = Tabs;\n\nconst FormSizeDemo = () => {\n  const [componentSize, setComponentSize] = useState('small');\n  return (\n    <div>\n      <Radio.Group\n        value={componentSize}\n        onChange={e => {\n          setComponentSize(e.target.value);\n        }}\n      >\n        <Radio.Button value=\"small\">Small</Radio.Button>\n        <Radio.Button value=\"middle\">Middle</Radio.Button>\n        <Radio.Button value=\"large\">Large</Radio.Button>\n      </Radio.Group>\n      <Divider />\n      <ConfigProvider componentSize={componentSize}>\n        <div className=\"example\">\n          <Input />\n        </div>\n        <div className=\"example\">\n          <Tabs defaultActiveKey=\"1\">\n            <TabPane tab=\"Tab 1\" key=\"1\">\n              Content of Tab Pane 1\n            </TabPane>\n            <TabPane tab=\"Tab 2\" key=\"2\">\n              Content of Tab Pane 2\n            </TabPane>\n            <TabPane tab=\"Tab 3\" key=\"3\">\n              Content of Tab Pane 3\n            </TabPane>\n          </Tabs>\n        </div>\n        <div className=\"example\">\n          <Input.Search allowClear />\n        </div>\n        <div className=\"example\">\n          <Input.TextArea allowClear />\n        </div>\n        <div className=\"example\">\n          <Select defaultValue=\"demo\" options={[{ value: 'demo' }]} />\n        </div>\n        <div className=\"example\">\n          <DatePicker />\n        </div>\n        <div className=\"example\">\n          <DatePicker.RangePicker />\n        </div>\n        <div className=\"example\">\n          <Button>Button</Button>\n        </div>\n        <div className=\"example\">\n          <Card title=\"Card\">\n            <Table\n              columns={[\n                { title: 'Name', dataIndex: 'name' },\n                { title: 'Age', dataIndex: 'age' },\n              ]}\n              dataSource={[\n                {\n                  key: '1',\n                  name: 'John Brown',\n                  age: 32,\n                },\n                {\n                  key: '2',\n                  name: 'Jim Green',\n                  age: 42,\n                },\n                {\n                  key: '3',\n                  name: 'Joe Black',\n                  age: 32,\n                },\n              ]}\n            />\n          </Card>\n        </div>\n      </ConfigProvider>\n    </div>\n  );\n};\nReactDOM.render(<FormSizeDemo />, mountNode);\n```\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/config-provider/index.en-US.md",
    "content": "---\ncategory: Components\ntype: Other\ncols: 1\ntitle: ConfigProvider\ncover: https://gw.alipayobjects.com/zos/alicdn/kegYxl1wj/ConfigProvider.svg\n---\n\n`ConfigProvider` provides a uniform configuration support for components.\n\n## Usage\n\nThis component provides a configuration to all React components underneath itself via the [context API](https://facebook.github.io/react/docs/context.html). In the render tree all components will have access to the provided config.\n\n```jsx\nimport { ConfigProvider } from 'antd';\n\n// ...\n\nexport default () => (\n  <ConfigProvider direction=\"rtl\">\n    <App />\n  </ConfigProvider>\n);\n```\n\n### Content Security Policy\n\nSome components use dynamic style to support wave effect. You can config `csp` prop if Content Security Policy (CSP) is enabled:\n\n```jsx\n<ConfigProvider csp={{ nonce: 'YourNonceCode' }}>\n  <Button>My Button</Button>\n</ConfigProvider>\n```\n\n## API\n\n| Property | Description | Type | Default | Version |\n| --- | --- | --- | --- | --- |\n| autoInsertSpaceInButton | Set false to remove space between 2 chinese characters on Button | boolean | true |  |\n| componentSize | Config antd component size | `small` \\| `middle` \\| `large` | - |  |\n| csp | Set [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) config | { nonce: string } | - |  |\n| direction | Set direction of layout. See [demo](#components-config-provider-demo-direction) | `ltr` \\| `rtl` | `ltr` |  |\n| dropdownMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. Will ignore when value less than select width. `false` will disable virtual scroll | boolean \\| number | - | 4.3.0 |\n| form | Set Form common props | { validateMessages?: [ValidateMessages](/components/form/#validateMessages), requiredMark?: boolean \\| `optional` } | - | requiredMark: 4.8.0 |\n| getPopupContainer | To set the container of the popup element. The default is to create a `div` element in `body` | function(triggerNode) | () => document.body |  |\n| getTargetContainer | Config Affix, Anchor scroll target container | () => HTMLElement | () => window | 4.2.0 |\n| iconPrefixCls | Set icon prefix className (cooperated with [@iconfont-css-prefix](https://github.com/ant-design/ant-design/blob/d943b85a523bdf181dabc12c928226f3b4b893de/components/style/themes/default.less#L106)) | string | `anticon` | 4.11.0 |\n| input | Set Input common props | { autoComplete?: string } | - | 4.2.0 |\n| locale | Language package setting, you can find the packages in [antd/lib/locale](http://unpkg.com/antd/lib/locale/) | object | - |  |\n| pageHeader | Unify the ghost of PageHeader, ref [PageHeader](/components/page-header) | { ghost: boolean } | true |  |\n| prefixCls | Set prefix className (cooperated with [@ant-prefix](https://github.com/ant-design/ant-design/blob/2c6c789e3a9356f96c47aea0083f5a15538315cf/components/style/themes/default.less#L7)) | string | `ant` |  |\n| renderEmpty | Set empty content of components. Ref [Empty](/components/empty/) | function(componentName: string): ReactNode | - |  |\n| space | Set Space `size`, ref [Space](/components/space) | { size: `small` \\| `middle` \\| `large` \\| `number` } | - | 4.1.0 |\n| virtual | Disable virtual scroll when set to `false` | boolean | - | 4.3.0 |\n\n### ConfigProvider.config() `4.13.0+`\n\nSetting `Modal`、`Message`、`Notification` rootPrefixCls.\n\n```jsx\nConfigProvider.config({\n  prefixCls: 'ant',\n});\n```\n\n## FAQ\n\n#### How to contribute a new language?\n\nSee [<Adding new language>](/docs/react/i18n#Adding-newplanguage).\n\n#### Does the locale problem still exist in DatePicker even if ConfigProvider `locale` is used?\n\nPlease make sure you set moment locale or that you don't have two different versions of moment.\n\n```js\nimport 'moment/locale/zh-cn';\nmoment.locale('zh-cn');\n```\n\n#### Modal throw error when setting `getPopupContainer`?\n\nRelated issue: <https://github.com/ant-design/ant-design/issues/19974>\n\nWhen you config `getPopupContainer` to parentNode globally, Modal will throw error of `triggerNode is undefined` because it did not have a triggerNode. You can try the [fix](https://github.com/afc163/feedback-antd/commit/3e4d1ad1bc1a38460dc3bf3c56517f737fe7d44a) below.\n\n```diff\n <ConfigProvider\n-  getPopupContainer={triggerNode => triggerNode.parentNode}\n+  getPopupContainer={node => {\n+    if (node) {\n+      return node.parentNode;\n+    }\n+    return document.body;\n+  }}\n >\n   <App />\n </ConfigProvider>\n```\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/config-provider/index.md",
    "content": "---\ncategory: 组件\nsubtitle: 全局化配置\ncols: 1\ntype: 其他\ntitle: ConfigProvider\ncover: https://gw.alipayobjects.com/zos/alicdn/kegYxl1wj/ConfigProvider.svg\n---\n\n为组件提供统一的全局化配置。\n\n## 使用\n\nConfigProvider 使用 React 的 [context](https://facebook.github.io/react/docs/context.html) 特性，只需在应用外围包裹一次即可全局生效。\n\n```jsx\nimport { ConfigProvider } from 'antd';\n\n// ...\n\nexport default () => (\n  <ConfigProvider direction=\"rtl\">\n    <App />\n  </ConfigProvider>\n);\n```\n\n### Content Security Policy\n\n部分组件为了支持波纹效果，使用了动态样式。如果开启了 Content Security Policy (CSP)，你可以通过 `csp` 属性来进行配置：\n\n```jsx\n<ConfigProvider csp={{ nonce: 'YourNonceCode' }}>\n  <Button>My Button</Button>\n</ConfigProvider>\n```\n\n## API\n\n| 参数 | 说明 | 类型 | 默认值 | 版本 |\n| --- | --- | --- | --- | --- |\n| autoInsertSpaceInButton | 设置为 `false` 时，移除按钮中 2 个汉字之间的空格 | boolean | true |  |\n| componentSize | 设置 antd 组件大小 | `small` \\| `middle` \\| `large` | - |  |\n| csp | 设置 [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) 配置 | { nonce: string } | - |  |\n| direction | 设置文本展示方向。 [示例](#components-config-provider-demo-direction) | `ltr` \\| `rtl` | `ltr` |  |\n| dropdownMatchSelectWidth | 下拉菜单和选择器同宽。默认将设置 `min-width`，当值小于选择框宽度时会被忽略。`false` 时会关闭虚拟滚动 | boolean \\| number | - | 4.3.0 |\n| form | 设置 Form 组件的通用属性 | { validateMessages?: [ValidateMessages](/components/form/#validateMessages), requiredMark?: boolean \\| `optional` } | - | requiredMark: 4.8.0 |\n| getPopupContainer | 弹出框（Select, Tooltip, Menu 等等）渲染父节点，默认渲染到 body 上。 | function(triggerNode) | () => document.body |  |\n| getTargetContainer | 配置 Affix、Anchor 滚动监听容器。 | () => HTMLElement | () => window | 4.2.0 |\n| iconPrefixCls | 设置图标统一样式前缀。注意：需要配合 `less` 变量 [@iconfont-css-prefix](https://github.com/ant-design/ant-design/blob/d943b85a523bdf181dabc12c928226f3b4b893de/components/style/themes/default.less#L106) 使用 | string | `anticon` | 4.11.0 |\n| input | 设置 Input 组件的通用属性 | { autoComplete?: string } | - | 4.2.0 |\n| locale | 语言包配置，语言包可到 [antd/lib/locale](http://unpkg.com/antd/lib/locale/) 目录下寻找 | object | - |  |\n| pageHeader | 统一设置 PageHeader 的 ghost，参考 [PageHeader](/components/page-header) | { ghost: boolean } | true |  |\n| prefixCls | 设置统一样式前缀。注意：需要配合 `less` 变量 [@ant-prefix](https://github.com/ant-design/ant-design/blob/2c6c789e3a9356f96c47aea0083f5a15538315cf/components/style/themes/default.less#L7) 使用 | string | `ant` |  |\n| renderEmpty | 自定义组件空状态。参考 [空状态](/components/empty/) | function(componentName: string): ReactNode | - |  |\n| space | 设置 Space 的 `size`，参考 [Space](/components/space) | { size: `small` \\| `middle` \\| `large` \\| `number` } | - | 4.1.0 |\n| virtual | 设置 `false` 时关闭虚拟滚动 | boolean | - | 4.3.0 |\n\n### ConfigProvider.config() `4.13.0+`\n\n设置 `Modal`、`Message`、`Notification` rootPrefixCls。\n\n```jsx\nConfigProvider.config({\n  prefixCls: 'ant',\n});\n```\n\n## FAQ\n\n#### 如何增加一个新的语言包？\n\n参考[《增加语言包》](/docs/react/i18n#%E5%A2%9E%E5%8A%A0%E8%AF%AD%E8%A8%80%E5%8C%85)。\n\n#### 为什么我使用了 ConfigProvider `locale`，时间类组件的国际化还有问题？\n\n请检查是否正确设置了 moment 语言包，或者是否有两个版本的 moment 共存。\n\n```js\nimport 'moment/locale/zh-cn';\nmoment.locale('zh-cn');\n```\n\n#### 配置 `getPopupContainer` 导致 Modal 报错？\n\n相关 issue：<https://github.com/ant-design/ant-design/issues/19974>\n\n当如下全局设置 `getPopupContainer` 为触发节点的 parentNode 时，由于 Modal 的用法不存在 `triggerNode`，这样会导致 `triggerNode is undefined` 的报错，需要增加一个[判断条件](https://github.com/afc163/feedback-antd/commit/3e4d1ad1bc1a38460dc3bf3c56517f737fe7d44a)。\n\n```diff\n <ConfigProvider\n-  getPopupContainer={triggerNode => triggerNode.parentNode}\n+  getPopupContainer={node => {\n+    if (node) {\n+      return node.parentNode;\n+    }\n+    return document.body;\n+  }}\n >\n   <App />\n </ConfigProvider>\n```\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/config-provider/index.tsx",
    "content": "import { ConfigProvider } from 'antd';\nexport default ConfigProvider;"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/create-global-state/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: 工厂\ntitle: createGlobalState\nsubtitle: 全局状态工厂\n---\n\n## 何时使用\n\n一个创造全局共享状态的 React Hook，可以理解为一个全局的 `useState`。\n\n`createGlobalState` 工厂会返回一个自定义hook，这个自定义hook的使用方式和 `useState` 是一样的，\n返回一个 `state`，以及更新 `state` 的函数\n\n> 与 class 组件中的 setState 方法不同，useState 不会自动合并更新对象。你可以用函数式的 setState 结合展开运算符来达到合并更新对象的效果。\n\n```jsx\nsetState(prevState => {\n  // 也可以使用 Object.assign\n  return {...prevState, ...updatedValues};\n});\n```\n\n唯一不同的地方，是初始值的设置。因为是全局共享，所以自定义hook不支持传参设置初始值，\n只能调用返回值的第二个参数，来设置状态的改变。\n\n### Demo\n\n```jsx\nimport { createGlobalState } from 'antd-advanced';\n\nconst useGlobalValue = createGlobalState<number>(0);\n\nconst CompA: FC = () => {\n  const [value, setValue] = useGlobalValue();\n\n  return <button onClick={() => setValue(value + 1)}>+</button>;\n};\n\nconst CompB: FC = () => {\n  const [value, setValue] = useGlobalValue();\n\n  return <button onClick={() => setValue(value - 1)}>-</button>;\n};\n\nconst Demo: FC = () => {\n  const [value] = useGlobalValue();\n  return (\n    <div>\n      <p>{value}</p>\n      <CompA />\n      <CompB />\n    </div>\n  );\n};\n```\n\ncopy 自 [react-use](https://github.com/streamich/react-use/blob/master/docs/createGlobalState.md)\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/create-global-state/index.ts",
    "content": "/* eslint-disable */\nimport { useState } from 'react';\nimport useEffectOnce from './useEffectOnce';\nimport useIsomorphicLayoutEffect from './useIsomorphicLayoutEffect';\n\nexport function createGlobalState<S = any>(initialState?: S) {\n  const store: { state: S | undefined; setState: (state: S | ((preState: S) => S)) => void; setters: any[] } = {\n    state: initialState,\n    setState(state: S | ((preState: S) => S)) {\n      if (Object.prototype.toString.call(state) === '[object Function]') {\n        const stateFunc = state as Function;\n        store.state = stateFunc(store.state);\n      } else {\n        store.state = state as S;\n      }\n      store.setters.forEach(setter => setter(store.state));\n    },\n    setters: [],\n  };\n\n  return (): [S | undefined, (state: S | ((preState: S) => S)) => void] => {\n    const [globalState, stateSetter] = useState<S | undefined>(store.state);\n\n    useEffectOnce(() => () => {\n      store.setters = store.setters.filter(setter => setter !== stateSetter);\n    });\n\n    useIsomorphicLayoutEffect(() => {\n      if (!store.setters.includes(stateSetter)) {\n        store.setters.push(stateSetter);\n      }\n    });\n\n    return [globalState, store.setState];\n  };\n}\n\nexport default createGlobalState;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/create-global-state/useEffectOnce.ts",
    "content": "import { EffectCallback, useEffect } from 'react';\n\nconst useEffectOnce = (effect: EffectCallback) => {\n  useEffect(effect, []);\n};\n\nexport default useEffectOnce;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/create-global-state/useIsomorphicLayoutEffect.ts",
    "content": "import { useEffect, useLayoutEffect } from 'react';\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\nexport default useIsomorphicLayoutEffect;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/create-reducer-context/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: 工厂\ntitle: createReducerContext\nsubtitle: 全局Reducer工厂\n---\n\n## 何时使用\n\nreact上下文 hook 的工厂，除了状态将在提供者中的所有组件之间共享之外，它的行为与react的useReducer一样。\n\n这允许您拥有任何组件都可以轻松更新的共享状态。\n\n\n```jsx\nimport { createReducerContext } from 'antd-advanced';\n\ntype Action = 'increment' | 'decrement';\n\nconst reducer = (state: number, action: Action) => {\n  switch (action) {\n    case 'increment':\n      return state + 1;\n    case 'decrement':\n      return state - 1;\n    default:\n      throw new Error();\n  }\n};\n\nconst [useSharedCounter, SharedCounterProvider] = createReducerContext(reducer, 0);\n\nconst ComponentA = () => {\n  const [count, dispatch] = useSharedCounter();\n  return (\n    <p>\n      Component A &nbsp;\n      <button type=\"button\" onClick={() => dispatch('decrement')}>\n        -\n      </button>\n      &nbsp;{count}&nbsp;\n      <button type=\"button\" onClick={() => dispatch('increment')}>\n        +\n      </button>\n    </p>\n  );\n};\n\nconst ComponentB = () => {\n  const [count, dispatch] = useSharedCounter();\n  return (\n    <p>\n      Component B &nbsp;\n      <button type=\"button\" onClick={() => dispatch('decrement')}>\n        -\n      </button>\n      &nbsp;{count}&nbsp;\n      <button type=\"button\" onClick={() => dispatch('increment')}>\n        +\n      </button>\n    </p>\n  );\n};\n\nconst Demo = () => {\n  return (\n    <SharedCounterProvider>\n      <p>Those two counters share the same value.</p>\n      <ComponentA />\n      <ComponentB />\n    </SharedCounterProvider>\n  );\n};\n```\n\n```jsx\n\nconst [useSharedState, SharedStateProvider] = createReducerContext(reducer, initialState);\n\n// In wrapper\nconst Wrapper = ({ children }) => (\n  // You can override the initial state for each Provider\n  <SharedStateProvider initialState={overrideInitialState}>\n    { children }\n  </SharedStateProvider>\n)\n\n// In a component\nconst Component = () => {\n  const [sharedState, dispatch] = useSharedState();\n\n  // ...\n}\n```\n\ncopy 自 [react-use](https://github.com/streamich/react-use/blob/master/docs/createReducerContext.md)\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/create-reducer-context/index.ts",
    "content": "import { createElement, createContext, useContext, useReducer } from 'react';\n\nconst createReducerContext = <R extends React.Reducer<any, any>>(\n  reducer: R,\n  defaultInitialState: React.ReducerState<R>,\n) => {\n  const context = createContext<\n    [React.ReducerState<R>, React.Dispatch<React.ReducerAction<R>>] | undefined\n  >(undefined);\n  const providerFactory = (props, children) => createElement(context.Provider, props, children);\n\n  const ReducerProvider: React.FC<{ initialState?: React.ReducerState<R> }> = ({\n    children,\n    initialState,\n  }) => {\n    const state = useReducer<R>(\n      reducer,\n      initialState !== undefined ? initialState : defaultInitialState,\n    );\n    return providerFactory({ value: state }, children);\n  };\n\n  const useReducerContext = () => {\n    const state = useContext(context);\n    if (state == null) {\n      throw new Error(`useReducerContext must be used inside a ReducerProvider.`);\n    }\n    return state;\n  };\n\n  return [useReducerContext, ReducerProvider, context] as const;\n};\n\nexport default createReducerContext;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/create-state-context/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: 工厂\ntitle: createStateContext\nsubtitle: 全局State工厂\n---\n\n## 何时使用\n\nreact上下文 hook 的工厂，除了状态将在提供者中的所有组件之间共享之外，它的行为就像react的useState。\n\n这允许您拥有任何组件都可以轻松更新的共享状态。\n\n\n```jsx\nimport { createStateContext } from 'antd-advanced';\n\nconst [useSharedText, SharedTextProvider] = createStateContext('');\n\nconst ComponentA = () => {\n  const [text, setText] = useSharedText();\n  return (\n    <p>\n      Component A:\n      <br />\n      <input type=\"text\" value={text} onInput={ev => setText(ev.target.value)} />\n    </p>\n  );\n};\n\nconst ComponentB = () => {\n  const [text, setText] = useSharedText();\n  return (\n    <p>\n      Component B:\n      <br />\n      <input type=\"text\" value={text} onInput={ev => setText(ev.target.value)} />\n    </p>\n  );\n};\n\nconst Demo = () => {\n  return (\n    <SharedTextProvider>\n      <p>Those two fields share the same value.</p>\n      <ComponentA />\n      <ComponentB />\n    </SharedTextProvider>\n  );\n};\n```\n\n\ncopy 自 [react-use](https://github.com/streamich/react-use/blob/master/docs/createStateContext.md)\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/create-state-context/index.ts",
    "content": "import { createElement, createContext, useContext, useState } from 'react';\n\nconst createStateContext = <T>(defaultInitialValue: T) => {\n  const context = createContext<[T, React.Dispatch<React.SetStateAction<T>>] | undefined>(\n    undefined,\n  );\n  const providerFactory = (props, children) => createElement(context.Provider, props, children);\n\n  const StateProvider: React.FC<{ initialValue?: T }> = ({ children, initialValue }) => {\n    const state = useState<T>(initialValue !== undefined ? initialValue : defaultInitialValue);\n    return providerFactory({ value: state }, children);\n  };\n\n  const useStateContext = () => {\n    const state = useContext(context);\n    if (state == null) {\n      throw new Error(`useStateContext must be used inside a StateProvider.`);\n    }\n    return state;\n  };\n\n  return [useStateContext, StateProvider, context] as const;\n};\n\nexport default createStateContext;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-async/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: hook\ntitle: useAsync\nsubtitle: 请求\n---\n\n## 何时使用\n\n接收一个 async 函数或返回 promise 的函数，返回状态，数据形状与 `useAsync` 相同。\n\n\n```jsx\nimport { useAsyncFn } from 'antd-advanced';\n\nconst fn = () => new Promise((resolve) => {\n  setTimeout(() => {\n    resolve('RESOLVED');\n  }, 1000);\n});\n\nconst Demo = () => {\n  const state = useAsync(fn);\n\n  return (\n    <div>\n      {state.loading?\n        <div>Loading...</div>\n        : state.error?\n        <div>Error...</div>\n        : <div>Value: {state.value}</div>\n      }\n    </div>\n  );\n};\n\nReactDOM.render(\n  <div>\n    <Demo />\n  </div>,\n  mountNode,\n);\n```\n\n\ncopy 自 [react-use](https://github.com/streamich/react-use/blob/master/docs/useAsyncFn.md)\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-async/index.ts",
    "content": "import { DependencyList, useEffect } from 'react';\nimport useAsyncFn from '../use-async-fn';\n\nexport default function useAsync<Result = any, Args extends any[] = any[]>(\n  fn: (...args: Args | []) => Promise<Result>,\n  deps: DependencyList = [],\n) {\n  const [state, callback] = useAsyncFn<Result, Args>(fn, deps, {\n    loading: true,\n  });\n\n  useEffect(() => {\n    callback();\n  }, [callback]);\n\n  return state;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-async-fn/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: hook\ntitle: useAsyncFn\nsubtitle: 函数请求\n---\n\n## 何时使用\n\n这个 `Hook` 用于解析 async 函数或返回 promise 的函数。\n\n\n```jsx\nimport { useAsyncFn } from 'antd-advanced';\n\nconst Demo = (url) => {\n  const [state, fetch] = useAsyncFn(async () => {\n    const response = await fetch(url);\n    const result = await response.text();\n    return result\n  }, [url]);\n\n  return (\n    <div>\n      {state.loading\n        ? <div>Loading...</div>\n        : state.error\n          ? <div>Error: {state.error.message}</div>\n          : state.value && <div>Value: {state.value}</div>\n      }\n      <button onClick={() => fetch()}>Start loading</button>\n    </div>\n  );\n};\n\nReactDOM.render(\n  <div>\n    <Demo />\n  </div>,\n  mountNode,\n);\n```\n\ncopy 自 [react-use](https://github.com/streamich/react-use/blob/master/docs/useAsync.md)\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-async-fn/index.ts",
    "content": "/* eslint-disable */\nimport { DependencyList, useCallback, useState, useRef } from 'react';\nimport useMountedState from '../use-mounted-state';\n\nexport type AsyncState<T> =\n  | {\n      loading: boolean;\n      error?: undefined;\n      value?: undefined;\n    }\n  | {\n      loading: false;\n      error: Error;\n      value?: undefined;\n    }\n  | {\n      loading: false;\n      error?: undefined;\n      value: T;\n    };\n\nexport type AsyncFn<Result = any, Args extends any[] = any[]> = [\n  AsyncState<Result>,\n  (...args: Args | []) => Promise<Result>\n];\n\nexport default function useAsyncFn<Result = any, Args extends any[] = any[]>(\n  fn: (...args: Args | []) => Promise<Result>,\n  deps: DependencyList = [],\n  initialState: AsyncState<Result> = { loading: false }\n): AsyncFn<Result, Args> {\n  const lastCallId = useRef(0);\n  const [state, set] = useState<AsyncState<Result>>(initialState);\n  \n  const isMounted = useMountedState();\n\n  const callback = useCallback((...args: Args | []) => {\n    const callId = ++lastCallId.current;\n    set({ loading: true });\n\n    return fn(...args).then(\n      value => {\n        isMounted() && callId === lastCallId.current && set({ value, loading: false });\n\n        return value;\n      },\n      error => {\n        isMounted() && callId === lastCallId.current && set({ error, loading: false });\n\n        return error;\n      }\n    );\n  }, deps);\n\n  return [state, callback];\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-async-retry/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: hook\ntitle: useAsyncRetry\nsubtitle: retry请求\n---\n\n## 何时使用\n\n使用 `useAsync` 和一个额外的retry方法来轻松重试/刷新异步函数;\n\n\n```jsx\nimport { useAsyncRetry } from 'antd-advanced';\n\n// Returns a Promise that resolves after one second.\nconst fn = () => new Promise((resolve, reject) => {\n  setTimeout(() => {\n    if (Math.random() > 0.5) {\n      reject(new Error('Random error!'));\n    } else {\n      resolve('RESOLVED');\n    }\n  }, 1000);\n});\n\nconst Demo = () => {\n  const state = useAsyncRetry(fn);\n\n  return (\n    <div>\n      {state.loading?\n        <div>Loading...</div>\n        : state.error?\n        <div>Error...</div>\n        : <div>Value: {state.value}</div>\n      }\n      {!state.loading?\n        <a href='javascript:void 0' onClick={() => state.retry()}>Retry</a>\n        : null\n      }\n    </div>\n  );\n};\n\nReactDOM.render(\n  <div>\n    <Demo />\n  </div>,\n  mountNode,\n);\n```\n\ncopy 自 [react-use](https://github.com/streamich/react-use/blob/master/docs/useAsyncRetry.md)\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-async-retry/index.ts",
    "content": "/* eslint-disable */\nimport { DependencyList, useCallback, useState } from 'react';\nimport {AsyncState} from '../use-async-fn';\nimport useAsync from '../use-async';\n\nexport type AsyncStateRetry<T> = AsyncState<T> & {\n  retry(): void;\n};\n\nconst useAsyncRetry = <T>(fn: () => Promise<T>, deps: DependencyList = []) => {\n  const [attempt, setAttempt] = useState<number>(0);\n  const state = useAsync(fn, [...deps, attempt]);\n\n  const stateLoading = state.loading;\n  const retry = useCallback(() => {\n    if (stateLoading) {\n      if (process.env.NODE_ENV === 'development') {\n        console.log('You are calling useAsyncRetry hook retry() method while loading in progress, this is a no-op.');\n      }\n\n      return;\n    }\n\n    setAttempt(currentAttempt => currentAttempt + 1);\n  }, [...deps, stateLoading]);\n\n  return { ...state, retry };\n};\n\nexport default useAsyncRetry;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-debounce/demo/useDebounce.md",
    "content": "---\ncategory: 组件\ncols: 1\ntype: hook\ntitle: useDebounce\nsubtitle: 防抖\n---\n\n配合 `useEffect` ，监听 `input` 输入值的变化。\n\n```jsx\nimport { useDebounce, Table, Input, Icon, Row, Col, Button } from 'antd-advanced';\nconst listUrl = 'http://api-test-sls.intra.xiaojukeji.com/op-odin-dantd-serverless-test/dataTableList';\nconst columns = [\n  {\n    title: '标题',\n    dataIndex: 'title',\n    commonSearch: true,\n  },\n  {\n    title: '缩略图',\n    dataIndex: 'image',\n    render: (text, record, index) => (\n      <div>\n        {record.thumbnail_pic_s ? (\n          <img style={{ maxHeight: 40 }} src={record.thumbnail_pic_s} alt={record.title} />\n        ) : (\n          '暂无图片'\n        )}\n      </div>\n    ),\n  },\n  {\n    title: '分类',\n    dataIndex: 'category',\n    commonFilter: true,\n  },\n  {\n    title: '作者',\n    dataIndex: 'author_name',\n    commonFilter: true,\n  },\n  {\n    title: '发布日期',\n    dataIndex: 'date',\n    commonSorter: true,\n  },\n];\n\nconst BasicExample: React.FC = () => {\n    const [dataSource, setDataSource] = React.useState([]);\n    const [loading, setLoading] = React.useState(false);\n    const [searchQuery, setSearchQuery] = React.useState();\n    const debouncedSearchQuery = useDebounce(searchQuery, 500);\n\n    React.useEffect(() => {\n      fetchData();\n    }, [])\n\n    React.useEffect(() => {\n        const fetchParams = {\n            title: debouncedSearchQuery\n        }\n\n        fetchData(fetchParams);\n        // eslint-disable-next-line react-hooks/exhaustive-deps\n    }, [debouncedSearchQuery]);\n\n    async function fetchData(fetchParams = {}) {\n        let url = new URL(listUrl) as any;\n        url.search = new URLSearchParams(fetchParams);\n        setLoading(true);\n        const res = await fetch(url);\n        res\n        .json()\n        .then(res => {\n            setDataSource(res.data);\n            setLoading(false);\n        })\n        .catch(() => {\n            setLoading(false);\n        });\n    }\n\n    const handleSearchChange = e => {\n        const query = e.target.value;\n        setSearchQuery(query);\n    };\n\n    return (\n        <div>\n            <Input\n                style={{width: '100%', marginBottom: 10}}\n                allowClear={true}\n                value={searchQuery}\n                onChange={handleSearchChange}\n                placeholder=\"模糊搜索表格内容(多个关键词请用空格分隔。如：key1 key2)\"\n            />\n            <Table\n                columns={columns}\n                dataSource={dataSource}\n            />\n        </div>\n    );\n}\n\nReactDOM.render(\n  <div>\n    <BasicExample />\n  </div>,\n  mountNode,\n);\n```\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-debounce/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: hook\ntitle: useDebounce\nsubtitle: 防抖\n---\n\n## 何时使用\n\n这个 `Hook` 可以用防抖动的方式来处理改变过快的值。当 `useDebounce` 在指定的时间段内没有被调用时，`hook` 仅返回最新的值。当与 `useEffect` 一起使用时，就像我们在下面的示例中所做的那样，您可以轻松地确保昂贵的操作(如API调用)不会执行得太频繁。\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-debounce/index.tsx",
    "content": "// https://usehooks.com/useDebounce/\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport React, { useState, useEffect } from 'react';\n\nexport default function useDebounce(value, delay) {\n  // State and setters for debounced value\n  const [debouncedValue, setDebouncedValue] = useState(value);\n\n  useEffect(\n    () => {\n      // Update debounced value after delay\n      const handler = setTimeout(() => {\n        setDebouncedValue(value);\n      }, delay);\n\n      // Cancel the timeout if value changes (also on delay change or unmount)\n      // This is how we prevent debounced value from updating if value is changed ...\n      // .. within the delay period. Timeout gets cleared and restarted.\n      return () => {\n        clearTimeout(handler);\n      };\n    },\n    [value, delay], // Only re-call effect if value or delay changes\n  );\n\n  return debouncedValue;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-deep-compare-effect/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: hook\ntitle: useDeepCompareEffect\nsubtitle: 深比较Effect\n---\n\n## 何时使用\n\n需要深比较依赖，触发Effect的时候\n\n\n```jsx\nimport { useState } from 'react';\nimport { useDeepCompareEffect } from 'antd-advanced';\n\nconst Demo = () => {\n  const [count, setCount] = useState(0);\n  const options = { step: 2 };\n\n  useDeepCompareEffect(() => {\n    setCount(count + options.step);\n  }, [options]);\n\n  return (\n    <div>\n      <p>useDeepCompareEffect: {count}</p>\n    </div>\n  );\n};\n```\n\n\ncopy 自 [react-use](https://github.com/streamich/react-use/blob/master/docs/useAsyncFn.md)\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-deep-compare-effect/index.ts",
    "content": "import { DependencyList, EffectCallback } from 'react';\nimport isDeepEqualReact from 'react-fast-compare';\nimport useCustomCompareEffect from './useCustomCompareEffect';\n\nconst isDeepEqual: (a: any, b: any) => boolean = isDeepEqualReact;\nconst isPrimitive = (val: any) => val !== Object(val);\n\nconst useDeepCompareEffect = (effect: EffectCallback, deps: DependencyList) => {\n  if (process.env.NODE_ENV !== 'production') {\n    if (!(deps instanceof Array) || !deps.length) {\n      console.warn(\n        '`useDeepCompareEffect` should not be used with no dependencies. Use React.useEffect instead.',\n      );\n    }\n\n    if (deps.every(isPrimitive)) {\n      console.warn(\n        '`useDeepCompareEffect` should not be used with dependencies that are all primitive values. Use React.useEffect instead.',\n      );\n    }\n  }\n\n  useCustomCompareEffect(effect, deps, isDeepEqual);\n};\n\nexport default useDeepCompareEffect;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-deep-compare-effect/useCustomCompareEffect.ts",
    "content": "import { DependencyList, EffectCallback, useEffect, useRef } from 'react';\n\nconst isPrimitive = (val: any) => val !== Object(val);\n\ntype DepsEqualFnType<TDeps extends DependencyList> = (prevDeps: TDeps, nextDeps: TDeps) => boolean;\n\nconst useCustomCompareEffect = <TDeps extends DependencyList>(\n  effect: EffectCallback,\n  deps: TDeps,\n  depsEqual: DepsEqualFnType<TDeps>,\n) => {\n  if (process.env.NODE_ENV !== 'production') {\n    if (!(deps instanceof Array) || !deps.length) {\n      console.warn(\n        '`useCustomCompareEffect` should not be used with no dependencies. Use React.useEffect instead.',\n      );\n    }\n\n    if (deps.every(isPrimitive)) {\n      console.warn(\n        '`useCustomCompareEffect` should not be used with dependencies that are all primitive values. Use React.useEffect instead.',\n      );\n    }\n\n    if (typeof depsEqual !== 'function') {\n      console.warn(\n        '`useCustomCompareEffect` should be used with depsEqual callback for comparing deps list',\n      );\n    }\n  }\n\n  const ref = useRef<TDeps | undefined>(undefined);\n\n  if (!ref.current || !depsEqual(deps, ref.current)) {\n    ref.current = deps;\n  }\n\n  useEffect(effect, ref.current);\n};\n\nexport default useCustomCompareEffect;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-dynamic-list/demo/basic.md",
    "content": "---\norder: 0\ntitle: 基本\n---\n\n这是一个基础的动态表单。\n\n```jsx\nimport React, { useState } from 'react';\nimport { MinusCircleOutlined } from '@ant-design/icons';\nimport { PlusCircleOutlined } from '@ant-design/icons';\nimport { useDynamicList, Form, Button, Input } from 'antd-advanced';\n\nconst Demo = props => {\n  const { list, remove, getKey, push } = useDynamicList(['David', 'Jack']);\n  const [form] = Form.useForm();\n  const { validateFields } = form;\n  const [result, setResult] = useState('');\n  const Row = (index, item) => (\n    <Form.Item \n      key={getKey(index)} \n      rules={[{required: true, message: 'required'}]}>\n      <Form.Item \n          noStyle\n          name={`names[${getKey(index)}]`} \n          rules={[{required: true, message: 'required'}]}\n      >\n        <Input style={{ width: 300 }} placeholder=\"Please enter your name\" />\n      </Form.Item >\n      {list.length > 1 && (\n        <MinusCircleOutlined \n         style={{ marginLeft: 8 }}\n          onClick={() => {\n            remove(index);\n          }}\n        />\n      )}\n      <PlusCircleOutlined\n       style={{ marginLeft: 8 }}\n        onClick={() => {\n          push('');\n        }}\n      />\n    </Form.Item>\n  );\n\n  const listValue = (list) => {\n    const obj = {}\n    list.map((ele, index) => {\n      obj[`names[${index}]`] = ele;\n    })\n    return obj;\n  }\n  return (\n    <>\n      <Form initialValues={listValue(list)} form={form}>\n        {list.map((ele, index) => Row(index, ele))}\n      </Form>\n      <Button\n        style={{ marginTop: 8 }}\n        type=\"primary\"\n        onClick={() =>\n          validateFields().then(val => setResult(JSON.stringify(Object.values(val))))\n        }\n      >\n        Submit\n      </Button>\n      <div>{result}</div>\n    </>\n  );\n}\n\nReactDOM.render(<Demo />, mountNode);\n```\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-dynamic-list/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: hook\ntitle: useDynamicList\nsubtitle: 动态表单\n---\n\n> 下面文档出自 [umi hook useDynamicList v1.9.2](https://hooks.umijs.org/zh-CN/ui/use-dynamic-list)\n\n> 已经在使用 `@umijs/hooks` 的项目推荐使用原版的 `useDynamicList`。\n\n# 何时使用\n\n一个帮助你管理列表状态，并能生成唯一 key 的 Hook。\n\n## API\n\n```typescript\nconst result: Result = useDynamicList(initialValue: T[]);\n```\n\n### Result\n\n| 参数         | 说明         | 类型                 |  备注            |\n|--------------|--------------|----------------------|---------------|\n| list      | 当前的列表 | T[]              | - |\n| resetList  | 重新设置 list 的值     | (list: T[]) => void;          | - |\n| insert        | 在指定位置插入元素 | (index: number, obj: T) => void                | - |\n| merge         | 在指定位置插入多个元素 | (index: number, obj: T) => void | - |\n| replace          | 替换指定元素         | (index: number, obj: T) => void          | - |\n| remove   | 删除指定元素     | (index: number) => void;          | - |\n| move | 移动元素     | (oldIndex: number, newIndex: number) => void;          | - |\n| getKey  | 获得某个元素的 uuid     | (index: number) => number;           | - |\n| getIndex  | 获得某个key的 index     | (key: number) => number;           | - |\n| sortForm  | 根据表单结果自动排序     | (list: unknown[]) => unknown[];           | 使用方法详见[`动态表格(可拖拽)`](#动态表格可拖拽) |\n| push  | 在列表末尾添加元素     | (obj: T) => void;          | - |\n| pop  | 移除末尾元素     | () => void;          | - |\n| unshift  | 在列表起始位置添加元素    | (obj: T) => void;          | - |\n| shift  | 移除起始位置元素     | () => void;          | - |\n\n### 参数\n\n| 参数         | 说明         | 类型                 |   |\n|--------------|--------------|----------------------|---|\n| initialValue      | 列表的初始值 | T[]              |   |\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-dynamic-list/index.tsx",
    "content": "import { useState, useRef, useCallback } from 'react';\n\nexport default function useDynamicList<T>(initialValue: T[]) {\n  const counterRef = useRef(-1);\n  // key 存储器\n  const keyList = useRef<number[]>([]);\n\n  // 内部方法\n  const setKey = useCallback((index: number) => {\n    counterRef.current += 1;\n    keyList.current.splice(index, 0, counterRef.current);\n  }, []);\n\n  const [list, setList] = useState(() => {\n    (initialValue || []).forEach((_, index) => {\n      setKey(index);\n    });\n    return initialValue || [];\n  });\n\n  const resetList = (newList: T[] = []) => {\n    keyList.current = [];\n    counterRef.current = -1;\n    setList(() => {\n      (newList || []).forEach((_, index) => {\n        setKey(index);\n      });\n      return newList || [];\n    });\n  };\n\n  const insert = (index: number, obj: T) => {\n    setList(l => {\n      const temp = [...l];\n      temp.splice(index, 0, obj);\n      setKey(index);\n      return temp;\n    });\n  };\n\n  const getKey = (index: number) => keyList.current[index];\n  const getIndex = (index: number) => keyList.current.findIndex(ele => ele === index);\n\n  const merge = (index: number, obj: T[]) => {\n    setList(l => {\n      const temp = [...l];\n      obj.forEach((_, i) => {\n        setKey(index + i);\n      });\n      temp.splice(index, 0, ...obj);\n      return temp;\n    });\n  };\n\n  const replace = (index: number, obj: T) => {\n    setList(l => {\n      const temp = [...l];\n      temp[index] = obj;\n      return temp;\n    });\n  };\n\n  const remove = (index: number) => {\n    setList(l => {\n      const temp = [...l];\n      temp.splice(index, 1);\n\n      // remove keys if necessary\n      try {\n        keyList.current.splice(index, 1);\n      } catch (e) {\n        console.error(e);\n      }\n      return temp;\n    });\n    setTimeout(() => {\n      setList(list.filter((lItem, lIdx) => lIdx !== index));\n    });\n  };\n\n  const move = (oldIndex: number, newIndex: number) => {\n    if (oldIndex === newIndex) {\n      return;\n    }\n    setList(l => {\n      const newList = [...l];\n      const temp = newList.filter((_: {}, index: number) => index !== oldIndex);\n      temp.splice(newIndex, 0, newList[oldIndex]);\n\n      // move keys if necessary\n      try {\n        const keyTemp = keyList.current.filter((_: {}, index: number) => index !== oldIndex);\n        keyTemp.splice(newIndex, 0, keyList.current[oldIndex]);\n        keyList.current = keyTemp;\n      } catch (e) {\n        console.error(e);\n      }\n\n      return temp;\n    });\n  };\n\n  const push = (obj: T) => {\n    setList(l => {\n      setKey(l.length);\n      return l.concat([obj]);\n    });\n  };\n\n  const pop = () => {\n    // remove keys if necessary\n    try {\n      keyList.current = keyList.current.slice(0, keyList.current.length - 1);\n    } catch (e) {\n      console.error(e);\n    }\n\n    setList(l => l.slice(0, l.length - 1));\n  };\n\n  const unshift = (obj: T) => {\n    setList(l => {\n      setKey(0);\n      return [obj].concat(l);\n    });\n  };\n\n  const sortForm = (result: unknown[]) =>\n    result\n      .map((item, index) => ({ key: index, item })) // add index into obj\n      .sort((a, b) => getIndex(a.key) - getIndex(b.key)) // sort based on the index of table\n      .filter(item => !!item.item) // remove undefined(s)\n      .map(item => item.item); // retrive the data\n\n  const shift = () => {\n    // remove keys if necessary\n    try {\n      keyList.current = keyList.current.slice(1, keyList.current.length);\n    } catch (e) {\n      console.error(e);\n    }\n    setList(l => l.slice(1, l.length));\n  };\n\n  return {\n    list,\n    insert,\n    merge,\n    replace,\n    remove,\n    getKey,\n    getIndex,\n    move,\n    push,\n    pop,\n    unshift,\n    shift,\n    sortForm,\n    resetList,\n  };\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-interval/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: hook\ntitle: useInterval\nsubtitle: 定时器\n---\n\n## 何时使用\n\n一个定时器的hook，基于[Josh的文章](https://joshwcomeau.com/snippets/react-hooks/use-interval)。\n可以通过将延迟设置为null来暂停时间间隔。\n当组件卸载的时候，会自动清除定时器。\n也可以通过 `window.clearInterval` 来强行停止定制器。\n\n### 关于 Antd 的 Tab 组件\n\n但是一般不推荐这么做，比如 `Antdv3` 的 [Tab](https://ant-design-3x.gitee.io/components/tabs-cn/) 组件，\n可以添加 [destroyInactiveTabPane](https://github.com/ant-design/ant-design/issues/15102) 属性，当切换Tab时，自动卸载Tab里面的东西即可。\n\n```jsx\nimport { useInterval, Button } from 'antd-advanced';\n\nconst IntervalDemo = () => {\n  const [status, setStatus] = React.useState('running');\n  const [timeElapsed, setTimeElapsed] = React.useState(0);\n  const instance = useInterval(\n    () => {\n      setTimeElapsed(timeElapsed => timeElapsed + 1);\n    },\n    status === 'running' ? 1000 : null,\n  );\n  const toggle = () => {\n    setTimeElapsed(0);\n    setStatus(status => (status === 'running' ? 'idle' : 'running'));\n  };\n\n  const stop = () => {\n    window.clearInterval(instance);\n  };\n  return (\n    <>\n      Time Elapsed: {timeElapsed} second(s) <br />\n      <Button onClick={toggle}>{status === 'running' ? 'Stop' : 'Start'}</Button>\n      <Button onClick={stop}>强行停止</Button>\n    </>\n  );\n};\n```\n\n\ncopy 自 [useInterval](https://joshwcomeau.com/snippets/react-hooks/use-interval)\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-interval/index.ts",
    "content": "import { useEffect, useRef } from 'react';\n\nconst useInterval = (callback: Function, delay?: number | null) => {\n  const intervalId = useRef(null);\n  const savedCallback = useRef<Function>(() => {});\n\n  useEffect(() => {\n    savedCallback.current = callback;\n  });\n\n  useEffect(() => {\n    const tick = () => savedCallback.current();\n    if (typeof delay === 'number') {\n      intervalId.current = window.setInterval(tick, delay);\n      return () => window.clearInterval(intervalId.current);\n    }\n  }, [delay]);\n\n  return intervalId.current;\n};\n\nexport default useInterval;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-mounted-state/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: hook\ntitle: useMountedState\nsubtitle: Mounted\n---\n\n## 何时使用\n\n生命周期钩子提供检查组件的挂载状态的能力。\n\n给出一个函数，如果组件被挂载，该函数将返回true，否则返回false。\n\n\n```jsx\nimport { useMountedState } from 'antd-advanced';\n\n\nconst Demo = () => {\n  const isMounted = useMountedState();\n\n  React.useEffect(() => {\n    setTimeout(() => {\n      if (isMounted()) {\n        // ...\n      } else {\n        // ...\n      }\n    }, 1000);\n  });\n};\n\nReactDOM.render(\n  <div>\n    <Demo />\n  </div>,\n  mountNode,\n);\n```\n\n\ncopy 自 [react-use](https://github.com/streamich/react-use/blob/master/docs/useMountedState.md)\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-mounted-state/index.ts",
    "content": "import { useCallback, useEffect, useRef } from 'react';\n\nexport default function useMountedState(): () => boolean {\n  const mountedRef = useRef<boolean>(false);\n  const get = useCallback(() => mountedRef.current, []);\n\n  useEffect(() => {\n    mountedRef.current = true;\n\n    return () => {\n      mountedRef.current = false;\n    };\n  });\n\n  return get;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-timeout/index.md",
    "content": "---\ncategory: 自定义Hook\ncols: 1\ntype: hook\ntitle: useTimeout\nsubtitle: 间隔\n---\n\n## 何时使用\n\n在指定的毫秒数后重新渲染组件。 提供取消或重置超时的调用方式。\n\n\n```jsx\nimport { useTimeout } from 'antd-advanced';\n\nfunction TestComponent(props: { ms?: number } = {}) {\n  const ms = props.ms || 5000;\n  const [isReady, cancel] = useTimeout(ms);\n\n  return (\n    <div>\n      { isReady() ? 'I\\'m reloaded after timeout' : `I will be reloaded after ${ ms / 1000 }s` }\n      { isReady() === false ? <button onClick={ cancel }>Cancel</button> : '' }\n    </div>\n  );\n}\n\nconst Demo = () => {\n  return (\n    <div>\n      <TestComponent />\n      <TestComponent ms={ 10000 } />\n    </div>\n  );\n};\n```\n\n\ncopy 自 [react-use](https://github.com/streamich/react-use/blob/master/docs/useTimeout.md)\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-timeout/index.ts",
    "content": "import useTimeoutFn from './useTimeoutFn';\nimport useUpdate from './useUpdate';\n\nexport type UseTimeoutReturn = [() => boolean | null, () => void, () => void];\n\nexport default function useTimeout(ms: number = 0): UseTimeoutReturn {\n  const update = useUpdate();\n\n  return useTimeoutFn(update, ms);\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-timeout/useTimeoutFn.ts",
    "content": "/* eslint-disable */\nimport { useCallback, useEffect, useRef } from 'react';\n\nexport type UseTimeoutFnReturn = [() => boolean | null, () => void, () => void];\n\nexport default function useTimeoutFn(fn: Function, ms: number = 0): UseTimeoutFnReturn {\n  const ready = useRef<boolean | null>(false);\n  const timeout = useRef<ReturnType<typeof setTimeout>>();\n  const callback = useRef(fn);\n\n  const isReady = useCallback(() => ready.current, []);\n\n  const set = useCallback(() => {\n    ready.current = false;\n    timeout.current && clearTimeout(timeout.current);\n\n    timeout.current = setTimeout(() => {\n      ready.current = true;\n      callback.current();\n    }, ms);\n  }, [ms]);\n\n  const clear = useCallback(() => {\n    ready.current = null;\n    timeout.current && clearTimeout(timeout.current);\n  }, []);\n\n  // update ref when function changes\n  useEffect(() => {\n    callback.current = fn;\n  }, [fn]);\n\n  // set on mount, clear on unmount\n  useEffect(() => {\n    set();\n\n    return clear;\n  }, [ms]);\n\n  return [isReady, clear, set];\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/hook/use-timeout/useUpdate.ts",
    "content": "import { useReducer } from 'react';\n\nconst updateReducer = (num: number): number => (num + 1) % 1_000_000;\n\nconst useUpdate = () => {\n  const [, update] = useReducer(updateReducer, 0);\n  return update as () => void;\n};\n\nexport default useUpdate;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/locale/en_US.tsx",
    "content": "import antdEnUS from 'antd/lib/locale/en_US';\nimport { Locale } from 'antd/lib/locale-provider';\nimport { DLocale } from './index';\n\nconst localeValues: Locale & DLocale = {\n  ...antdEnUS,\n  back: 'Back',\n  'table.search.placeholder':\n    'Fuzzy search table content (multiple keywords separated by Spaces. Such as: key1 key2)',\n  'table.sort.ascend': 'Ascend',\n  'table.sort.descend': 'Descend',\n  'table.total.prefix': 'Total',\n  'table.total.suffix': 'Items',\n  'table.select.num': 'Selected: ',\n  'table.filter.search.placeholder': 'Please enter keywords',\n  'table.filter.search.btn.ok': 'Search',\n  'table.filter.search.btn.cancel': 'Clear',\n  'table.filter.header.title': 'Filtration Conditions:',\n  'table.filter.header.search': ': Search',\n  'table.filter.header.filter': ': Filter',\n  'table.filter.header.btn.clear': 'Clear',\n  'form.item.key.title': 'Custom Key',\n  'form.item.value.title': 'Custom Value',\n  'form.detail.nodata': 'No Data',\n  'form.item.key.placeholder': 'Please enter key',\n  'form.item.value.placeholder': 'Please enter value',\n  'form.item.add': 'Add Custom Parameters',\n  'form.placeholder.prefix': 'Please enter',\n  'form.selectplaceholder.prefix': 'Please select',\n  'dqueryform.reset': 'Clear',\n  'dqueryform.search': 'Search',\n  'dqueryform.collapsed': 'Collapsed',\n  'dqueryform.expand': 'Expand',\n  'color.placeholder': 'Please select color',\n};\n\nexport default localeValues;"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/locale/index.tsx",
    "content": "import zh_CN from './zh_CN';\nimport en_US from './en_US';\n\nexport interface DLocale {\n  back: string;\n  // [key: string]: string,\n  'table.search.placeholder': string;\n  'table.sort.ascend': string;\n  'table.sort.descend': string;\n  'table.total.prefix': string;\n  'table.total.suffix': string;\n  'table.select.num': string;\n  'table.filter.search.placeholder': string;\n  'table.filter.search.btn.ok': string;\n  'table.filter.search.btn.cancel': string;\n  'table.filter.header.title': string;\n  'table.filter.header.search': string;\n  'table.filter.header.filter': string;\n  'table.filter.header.btn.clear': string;\n  'form.item.key.title': string;\n  'form.item.value.title': string;\n  'form.detail.nodata': string;\n  'form.item.key.placeholder': string;\n  'form.item.value.placeholder': string;\n  'form.item.add': string;\n  'form.placeholder.prefix': string;\n  'form.selectplaceholder.prefix': string;\n  'dqueryform.reset': string;\n  'dqueryform.search': string;\n  'dqueryform.collapsed': string;\n  'dqueryform.expand': string;\n  'color.placeholder': string;\n}\n\nexport default {\n  'zh-CN': zh_CN,\n  'en-US': en_US,\n};\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/locale/zh_CN.tsx",
    "content": "\nimport antdZhCN from 'antd/lib/locale/zh_CN';\nimport { Locale } from 'antd/lib/locale-provider';\nimport { DLocale } from './index';\n\nconst localeValues: Locale & DLocale = {\n  ...antdZhCN,\n  'back': '返回',\n  'table.search.placeholder': '模糊搜索表格内容(多个关键词请用空格分隔。如：key1 key2)',\n  'table.sort.ascend': '升序',\n  'table.sort.descend': '降序',\n  'table.total.prefix': '共',\n  'table.total.suffix': '条',\n  'table.select.num': '已选择: ',\n  'table.filter.search.placeholder': '请输入要搜索的内容',\n  'table.filter.search.btn.ok': '搜索',\n  'table.filter.search.btn.cancel': '清空',\n  'table.filter.header.title': '过滤条件:',\n  'table.filter.header.search': ':搜索',\n  'table.filter.header.filter': ':过滤',\n  'table.filter.header.btn.clear': '清空',\n  'form.item.key.title': '自定义Key',\n  'form.item.value.title': '自定义Value',\n  'form.detail.nodata': '暂无数据',\n  'form.item.key.placeholder': '请输入Key',\n  'form.item.value.placeholder': '请输入Value',\n  'form.item.add': '增加自定义参数',\n  'form.placeholder.prefix': '请输入',\n  'form.selectplaceholder.prefix': '请选择',\n  'dqueryform.reset': '重置',\n  'dqueryform.search': '查询',\n  'dqueryform.collapsed': '收起',\n  'dqueryform.expand': '展开',\n  'color.placeholder': '请选择颜色',\n};\nexport default localeValues;"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/locale-provider/context.tsx",
    "content": "import { createContext } from 'react';\nimport TRANSLATIONS from '../locale';\n\ninterface IContextProps {\n  t: (key: any) => any;\n}\n\nconst locale = 'zh-CN';\n\nconst IntlContext = createContext<IContextProps>({\n  t: (key) => TRANSLATIONS[locale][key],\n});\n\nexport default IntlContext;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/locale-provider/index.tsx",
    "content": "import IntlProvider from './provider';\n// import { Locale } from 'antd/lib/locale-provider';\n\nexport { default as IntlProvider } from './provider';\nexport { default as useIntl } from './useIntl';\nexport { default as withIntl } from './withIntl';\n\nexport default IntlProvider;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/locale-provider/provider.tsx",
    "content": "import React from 'react';\nimport IntlContext from './context';\nimport TRANSLATIONS from '../locale';\n\ninterface IIntlProps {\n  locale: 'zh-CN' | 'en-US' | string;\n  children: React.ReactNode;\n}\n\nconst IntlProvider = (props: IIntlProps) => {\n  const locale = props.locale || 'en-US';\n  const i18n = {\n    t: (key) => TRANSLATIONS[locale][key],\n  };\n  return (\n    <IntlContext.Provider \n      value={i18n} \n    >\n      {props.children}\n    </IntlContext.Provider>\n  );\n};\n\nexport default IntlProvider;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/locale-provider/useIntl.tsx",
    "content": "import { useContext } from 'react';\nimport IntlContext from './context';\n\nfunction useIntl(): any {\n  const i18n = useContext(IntlContext);\n  return i18n;\n}\n\nexport default useIntl;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/locale-provider/withIntl.tsx",
    "content": "import React from 'react';\nimport IntlContext from './context';\n\nexport const withIntl = () => {\n  return (WrappedComponent) => {\n    const ComponentWithIntl = (props) => (\n      <IntlContext.Consumer>\n        {(i18n) => <WrappedComponent {...i18n} {...props} />}\n      </IntlContext.Consumer>\n    );\n    return ComponentWithIntl;\n  };\n};\n\nexport default withIntl;\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/components/utils/index.tsx",
    "content": "import queryString from 'query-string';\n\nexport function uuidv4() {\n  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n    const r = (Math.random() * 16) | 0,\n      v = c === 'x' ? r : (r & 0x3) | 0x8;\n    return v.toString(16);\n  });\n}\n\nexport function prefixFieldKey(name, prefix = '') {\n  if (!prefix) {\n    return name;\n  } else {\n    name = name.replace(name[0], name[0].toUpperCase());\n    return `${prefix}${name}`;\n  }\n}\n\n// export function processBasicFormItemsData(values) {\n//   const result = {};\n//   Object.entries(values).forEach(([formKey, formValue]) => {\n//     if (Array.isArray(formValue)) {\n//       formValue = formValue.filter((e) => !!e);\n//     }\n//     result[formKey] = formValue;\n//   });\n//   return result;\n// }\n\nexport function processBasicFormItemsData(values) {\n  const arr = [];\n  const result = [];\n  let defaultName;\n  const resultList = {};\n  let MaxLength;\n  const arrLength = [];\n  for (const i in values) {\n    const obj = {};\n    obj[i] = values[i];\n    arr.push(obj);\n  }\n\n  arr.map((item, index) => {\n    defaultName = Object.keys(item)[0].split('[');\n    arrLength.push(defaultName[2].split(']')[0]);\n    MaxLength = arrLength[0];\n    for (let i = 1; i < arrLength.length; i++) {\n      MaxLength = Math.max(MaxLength, arrLength[i]);\n    }\n    result.push(Object.values(item)[0]);\n    return result;\n  });\n  resultList[defaultName[0]] = chunk(result, MaxLength + 1);\n  return resultList;\n}\n\nconst chunk = (array, size) => {\n  const length = array.length;\n  let index = 0;\n  let resIndex = 0;\n  const result = new Array(Math.ceil(length / size));\n  while (index < length) {\n    result[resIndex++] = array.slice(index, (index += size));\n  }\n  return result;\n};\n\nexport const isClient = typeof window === 'object';\n\n/**\n * formatUrl 处理Url\n * @export\n * @param {*} url 需要处理的url，比如 /deploy/order/:id\n * @param {*} params 需要处理的参数 ，比如 {id: 123}\n * @param {*} query 需要处理的参数 ，比如 {id: 123}\n * @returns\n */\nexport function formatUrl(url: string): string;\nexport function formatUrl(url: string, params?: object): string;\nexport function formatUrl(url: string, params?: object, query?: object): string;\nexport function formatUrl(url: string, params?: object, query?: object): string {\n  if (params) {\n    Object.entries(params).forEach(([paramKey, paramValue]) => {\n      const regex = new RegExp(`:${paramKey}`, 'i');\n      url = url.replace(regex, paramValue);\n    });\n  }\n\n  if (query) {\n    url = `${url}?${queryString.stringify(query)}`;\n  }\n\n  return url;\n}\n\nexport function hexToRgb(hex) {\n  const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n  return result\n    ? {\n        r: parseInt(result[1], 16),\n        g: parseInt(result[2], 16),\n        b: parseInt(result[3], 16),\n      }\n    : null;\n}\n"
  },
  {
    "path": "arius-console/src/d1-packages/dantd/readme.md",
    "content": "## 看不懂？点击 wiki 链接查看应用项目及项目 demo\n\n- wiki: http://wiki.intra.xiaojukeji.com/pages/viewpage.action?pageId=635293796\n\n## 组件简单介绍\n\n| 组件       | 说明             | 使用                |\n| ---------- | ---------------- | ------------------- |\n| BaseDetail | 基础详情展示     | 对应文件下的 readme |\n| DTable     | 增强版 Table     | 对应文件下的 readme |\n| QueryForm  | 收集查询数据     | 对应文件下的 readme |\n| RouterTabs | 顶部历史菜单切换 | 对应文件下的 readme |\n"
  },
  {
    "path": "arius-console/src/d1-packages/drag-group/DragGroup.tsx",
    "content": "import React from \"react\";\nimport { SortableContainerProps } from 'react-sortable-hoc';\n\nimport { propsType as IcontainerProps } from '../container';\nimport DragableContainer from './DragableContainer';\nimport DragableItem from './DragableItem';\n\ninterface ISortableElement1 {\n  collection?: string | number;\n  disabled?: boolean;\n}\n\ninterface propsType extends React.HTMLAttributes<HTMLDivElement> {\n  children: React.ReactNode;\n  dragContainerProps?: SortableContainerProps;\n  containerProps?: IcontainerProps;\n  dragItemProps?: ISortableElement1;\n}\n\n\nconst DragGroup: React.FC<propsType> = ({ children, containerProps, dragContainerProps, dragItemProps }) => {\n\n  return (\n    <DragableContainer\n      dragContainerProps={{\n        axis: \"xy\",\n        ...dragContainerProps\n      }}\n      containerProps={{\n        grid: 8,\n        gutter: [10, 10],\n        ...containerProps\n      }}\n    >\n      {\n        React.Children.map(children, (child: any, index) => {\n          return (\n            <DragableItem\n              dragItemProps={{\n                index: index,\n                disabled: child.key?.indexOf('health') !== -1,\n                ...dragItemProps\n              }}\n              key={index}>\n              {React.cloneElement(child, { key: index })}\n            </DragableItem>\n          )\n        })\n      }\n    </DragableContainer>\n  )\n\n};\n\nexport default DragGroup;"
  },
  {
    "path": "arius-console/src/d1-packages/drag-group/DragableContainer.tsx",
    "content": "import React from \"react\";\nimport Container from '../container/index';\nimport { SortableContainer, SortableContainerProps } from 'react-sortable-hoc';\nimport { propsType as IcontainerProps } from '../container';\n\ninterface propsType extends React.HTMLAttributes<HTMLDivElement> {\n  children: React.ReactNode;\n  dragContainerProps?: SortableContainerProps;\n  containerProps?: IcontainerProps;\n}\n\nconst SortableCon = SortableContainer(({ children, containerProps }) => (\n  <Container\n    {...containerProps}\n  >\n    {children}\n  </Container>\n))\n\nconst DragableContainer: React.FC<propsType> = ({ children, dragContainerProps, containerProps }) => {\n\n  return (\n    <SortableCon\n      {...dragContainerProps}\n      containerProps={containerProps}\n    >\n      {children}\n    </SortableCon>\n  )\n\n};\n\nexport default DragableContainer;"
  },
  {
    "path": "arius-console/src/d1-packages/drag-group/DragableItem.tsx",
    "content": "import React from \"react\";\nimport { SortableContainer, SortableElement } from 'react-sortable-hoc';\n\nexport interface ISortableElement {\n  index: number;\n  collection?: string | number;\n  disabled?: boolean;\n}\n\ninterface propsType {\n  children: React.ReactNode;\n  dragItemProps: ISortableElement;\n}\n\nconst SortableItem = SortableElement(({ children }) => (\n  <div\n    className=\"drag-sort-item\"\n    style={{\n      cursor: 'move'\n    }}\n  >\n    {children}\n  </div>\n))\n\nconst DragableItem: React.FC<propsType> = ({ children, dragItemProps }) => {\n\n  return (\n    <SortableItem\n      {...dragItemProps}\n    >\n      {children}\n    </SortableItem>\n  )\n\n};\n\nexport default DragableItem;"
  },
  {
    "path": "arius-console/src/d1-packages/drag-group/demo/card.md",
    "content": "---\norder: 1\ntitle: card拖拽\n---\n\ncard拖拽示例\n\n``` tsx\nimport React, { useState } from 'react';\nimport DragGroup from '../DragGroup';\nimport { arrayMoveImmutable } from 'array-move';\nimport Card from '../../../basic/card';\nlet datas = [\n  {\n    id: 1,\n    name: 'item1'\n  },\n  {\n    id: 2,\n    name: 'item2'\n  },\n  {\n    id: 3,\n    name: 'item3'\n  },\n  {\n  id: 4,\n  name: 'item4'\n  },\n  {\n    id: 5,\n    name: 'item5'\n  }\n]    \nconst Containerskk = (): JSX.Element => {\n  const [lists, setlists] = useState(JSON.parse(JSON.stringify(datas)));\n  const sortEnd = ({ oldIndex, newIndex, collection }) => {\n    const listsNew = arrayMoveImmutable(lists, oldIndex, newIndex)\n    setlists(listsNew);\n  };       \n  return (\n    <>\n      <DragGroup\n        dragContainerProps={{\n          onSortEnd: sortEnd,\n          axis: \"xy\"\n        }}\n      >\n        {lists.map((item, index) => (\n          <Card title={item.name} key={index}>\n            <p>Card content</p>\n            <p>Card content</p>\n            <p>Card content</p>\n          </Card>\n        ))}\n      </DragGroup>           \n    </>\n  )\n}\n\nReactDOM.render(\n  <div>\n    <Containerskk />\n  </div>,\n  mountNode,\n);\n```\n\n```css\n.drag-sort-item {\n  \n}\n\n```"
  },
  {
    "path": "arius-console/src/d1-packages/drag-group/demo/custom.md",
    "content": "---\norder: 0\ntitle: 自定义拖拽项&拖拽分组\n---\n\nDragGroup示例\n\n``` tsx\nimport React, { useState } from 'react';\nimport DragGroup from '../DragGroup';\nimport { arrayMoveImmutable } from 'array-move';\n\nlet datas = [\n  {\n    id: 1,\n    name: 'item1'\n  },\n  {\n    id: 2,\n    name: 'item2'\n  },\n  {\n    id: 3,\n    name: 'item3'\n  },\n  {\n    id: 4,\n    name: 'item4'\n  },\n  {\n    id: 5,\n    name: 'item5'\n  },\n  {\n    id: 6,\n    name: 'item6'\n  }\n]\nlet datas2 = [\n  {\n    id: 1,\n    name: 'item1-2'\n  },\n  {\n    id: 2,\n    name: 'item2-2'\n  },\n  {\n    id: 3,\n    name: 'item3-2'\n  },\n  {\n    id: 4,\n    name: 'item4-2'\n  },\n  {\n    id: 5,\n    name: 'item5-2'\n  },\n  {\n    id: 6,\n    name: 'item6-2'\n  }\n]\n\nconst DragItem = (props) => {\n  return (\n    <div>{props.name}</div>\n  )\n}\n\nconst Containers = (): JSX.Element => {\n    \n  const [lists, setlists] = useState(JSON.parse(JSON.stringify(datas)));\n  const [lists2, setlists2] = useState(JSON.parse(JSON.stringify(datas2)));\n\n  const sortEnd = ({ oldIndex, newIndex, collection }) => {\n    let datas = [];\n    let setData;\n    switch (collection) {\n      case 'group1':\n        datas = lists;\n        setData = setlists;\n        break;\n      case 'group2':\n        datas = lists2;\n        setData = setlists2;\n        break;\n      default:\n        break;\n    }\n    const listsNew = arrayMoveImmutable(datas, oldIndex, newIndex)\n    setData(listsNew);\n  };\n  return (\n      <>\n        <h4>拖拽组1</h4>\n        <DragGroup \n          dragContainerProps={{\n            onSortEnd: sortEnd,\n            axis: \"xy\"\n          }}\n          dragItemProps={{\n            collection: 'group1'\n          }}\n        >\n          {lists.map((item, index) => (\n            <DragItem key={index} name={item.name} id={item.id}/>\n          ))}\n          \n        </DragGroup> \n        <br/>\n\n        <h4>拖拽组2</h4>\n        <DragGroup \n          dragContainerProps={{\n            onSortEnd: sortEnd,\n            axis: \"xy\"\n          }}\n          dragItemProps={{\n            collection: 'group2'\n          }}\n        >\n          {lists2.map((item, index) => (\n            <DragItem key={index} name={item.name} id={item.id}/>\n          ))} \n        </DragGroup>             \n      </>\n  )\n}\n\nReactDOM.render(\n  <div>\n    <Containers />\n  </div>,\n  mountNode,\n);\n```\n\n```css\n.drag-sort-item {\n  background: #4482D4;\n  border: 1px solid #50A5F1;\n  color: #fff;\n}\n\n```"
  },
  {
    "path": "arius-console/src/d1-packages/drag-group/index.md",
    "content": "---\ncategory: 组件\ntype: 布局\ncols: 1\ntitle: DragGroup\nsubtitle: 可拖拽组件\n---\n\n\n## 何时使用\n用于快速实现可拖拽排序的列表\n\n## API \n\n#### props\n\n| 参数                          | 类型                                                      | 默认值                                                                                                        | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                            |\n| :-------------------------------- | :-------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| dragContainerProps                  | object                                | -                        | [dragContainerProps](#dragContainerProps)            |\n| dragItemProps                       | object                                | -                        | [dragItemProps](#dragItemProps)  |\n| containerProps                      | object                                | -                        | [containerProps](#containerProps)  |\n\n#### dragContainerProps\n\n| 参数                          | 类型                                                      | 默认值                                                                                                        | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                            |\n| :-------------------------------- | :-------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| axis                              | String                                                    | `xy`                                                                                                            | 可以水平、垂直或在网格中排序。可能的值:' x '， ' y '或' xy '                                                                                                                                                                                                                                                           |\n| lockAxis                          | String                                                    |                                                                                                                | 可以在排序时将移动锁定到一个轴上。这在HTML5的拖放中是不可能实现的。可选值:' x '或' y '。                                                                                                                                                                                                                              |\n| helperClass                       | String                                                    |                                                                                                                | 自定义类名                                                                                                                                                                                                                                                                                                     |\n| transitionDuration                | Number                                                    | `300`                                                                                                          | 元素移动位置时的转换持续时间。如果你想禁用过渡，将它设置为“0”                                                                                                                                                                                                                                                                                       |\n| keyboardSortingTransitionDuration | Number                                                    | `transitionDuration`                                                                                           | 在键盘排序期间，助手被转移时的转换持续时间。如果你想禁用键盘排序助手的过渡，请将此设置为“0”。如果未定义，默认为' transitionDuration '的值                                                                                                                                                                              |\n| keyCodes                           | Array<Number>                                             | `{`<br/>&nbsp;&nbsp;`lift: [32],`<br/>&nbsp;&nbsp;`drop: [32],`<br/>&nbsp;&nbsp;`cancel: [27],`<br/>&nbsp;&nbsp;`up: [38, 37],`<br/>&nbsp;&nbsp;`down: [40, 39]`<br/>`}`                                                                                                                        | 包含每个键盘可访问操作的键码数组的对象。                                                                                                                                                                                                      |\n| pressDelay                        | Number                                                    | `0`                                                                                                            | 如果您希望元素在被按下一段时间后才变得可排序，请更改此属性。移动设备的一个合理的默认值是‘200’。不能与“distance”一起使用。                                                                                                                                 |\n| pressThreshold                    | Number                                                    | `5`                                                                                                            | 在忽略a press event之前，可以容忍的移动像素数                                                                                                                                                                                                                                                                                                                                    |\n| distance                          | Number                                                    | `0`                                                                                                            | 设置拖动一定数量的像素后才变得可排序。不能与' pressDelay '道具一起使用。                                                                                                                                                                                                                                                       |\n| shouldCancelStart                 | Function                                                  | [Function](https://github.com/clauderic/react-sortable-hoc/blob/master/src/SortableContainer/index.js#L48)     | 这个函数在排序开始之前被调用，并且可以用于在排序开始之前以编程方式取消排序。默认情况下，如果事件目标是' input '， ' textarea '， ' select '， ' option '或' button '，它将取消排序。                                                                                                                                                                                                         |\n| updateBeforeSortStart             | Function                                                  |                                                                                                                | 这个函数在排序开始之前被调用。它可以返回一个promise，允许你在排序开始之前运行异步更新(比如' setState ')。' function({node, index, collection, isKeySorting}， event) '                                                                                                                                                                                                     |\n| onSortStart                       | Function                                                  |                                                                                                                | 当排序开始时调用的回调。' function({node, index, collection, isKeySorting}， event) '                                                                                                                                                                                                                                                                               |\n| onSortMove                        | Function                                                  |                                                                                                                | 当光标移动时，排序期间调用的回调 `function(event)`                                                                                                                                                                                                                                                                                                                                                                                         |\n| onSortOver                        | Function                                                  |                                                                                                                | 当移动到一个项目时调用的回调。 `function({index, oldIndex, newIndex, collection, isKeySorting}, e)`                                                                                                                                                                                                                                                                                                                                                |\n| onSortEnd                         | Function                                                  |                                                                                                                | 排序结束时调用的回调。 `function({oldIndex, newIndex, collection, isKeySorting}, e)`                                                                                                                                                                                                                                                                                                                                                              |\n| useDragHandle                     | Boolean                                                   | `false`                                                                                                        | 如果你使用的是\" SortableHandle \" HOC，将其设为\" true \"                                                                                                                                                                                                                                                                                                                                              |\n| useWindowAsScrollContainer        | Boolean                                                   | `false`                                                                                                        | 可以将window设置为滚动容器                                                                                                                                                                                                                                                                                                                                 |\n| hideSortableGhost                 | Boolean                                                   | `true`                                                                                                         | 是否自动隐藏重影元素。默认情况下，为了方便起见，React Sortable List会自动隐藏当前正在排序的元素。如果您想应用自己的样式，则将此设置为false。                                                                                                                                                                       |\n| lockToContainerEdges              | Boolean                                                   | `false`                                                                                                        | 您可以将可排序元素的移动锁定到它的父元素 `SortableContainer`                                                                                                                                                                                                                                                                                                                                                                                       |\n| lockOffset                        | `OffsetValue`\\* &#124; [`OffsetValue`\\*, `OffsetValue`\\*] | `\"50%\"`                                                                                                        | 当' locktocontaineredges '被设置为' true '时，这将控制sortable helper和它的父类' sortableccontainer '的顶部/底部边缘之间的偏移距离。百分比值相对于当前排序的项目的高度。如果你想指定不同的行为锁定到容器的_top_和_bottom_，你也可以传入一个数组(例如:' [\"0%\"，\"100%\"]').                                             |\n| getContainer                      | Function                                                  |                                                                                                                | 返回可滚动容器元素的可选函数。该属性默认为“SortableContainer”元素本身，或者(如果“useWindowAsScrollContainer”为true)窗口。使用此函数指定一个自定义容器对象(例如，这对于与某些第三方组件(如' FlexTable ')集成很有用)。这个函数被传递了一个参数(' wrappedInstance ' React元素)，它将返回一个DOM元素。|\n| getHelperDimensions               | Function                                                  | [Function](https://github.com/clauderic/react-sortable-hoc/blob/master/src/SortableContainer/index.js#L74-L77) | 可选的' function({node, index, collection}) '，应该返回SortableHelper的计算维度。详情请参阅[default implementation](https://github.com/clauderic/react-sortable-hoc/blob/master/src/SortableContainer/defaultGetHelperDimensions.js)                                                                                                                                                                                                    |\n| helperContainer                   | HTMLElement &#124; Function                               | `document.body`                                                                                                | 默认情况下，克隆的可排序助手被追加到文档主体。使用此道具指定要追加的可排序克隆的不同容器。接受' HTMLElement '或返回' HTMLElement '的函数，该函数将在排序开始之前被调用                                                                                                                                            |\n| disableAutoscroll                 | Boolean                                                   | `false`                                                                                                        | 在拖动时禁用自动滚动  \n\n#### dragItemProps\n\n| 参数   | 类型            | 默认值 | Required | 说明                                                                                                                                                                                                                               |\n| :--------- | :--------------- | :------ | :-------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| collection | Number or String | `0`     |           | 元素所在的集合。如果你有多组可排序的元素在同一个' sortableccontainer '。可以用来区分不同的拖拽集合[例子](http://clauderic.github.io/react-sortable-hoc/#/basic-configuration/multiple-lists) |\n| disabled   | Boolean          | `false` |           | 元素是否可拖拽排序的                                                                                                                                                            |"
  },
  {
    "path": "arius-console/src/d1-packages/drag-group/index.tsx",
    "content": "import DragGroup from \"./DragGroup\";\n\nexport default DragGroup;"
  },
  {
    "path": "arius-console/src/d1-packages/index.tsx",
    "content": "import { Page500, Page404, Page403, Page401 } from \"./CommonPages/Exception/index\";\nimport { RoleManage } from \"./CommonPages/RoleManage\";\nimport { UserManage } from \"./CommonPages/UserManage\";\nimport ProgressBar from \"./CommonComponents/ProgressBar\";\nimport LayoutHeaderNav from \"./Layout/index\";\nimport LeftMenu from \"./Layout/LeftMenu\";\nimport ProTable from \"./ProTable\";\nimport ProForm, { DrawerForm, ModalForm, QueryForm } from \"./ProForm\";\n\nexport {\n  Page500,\n  Page404,\n  Page403,\n  Page401,\n  RoleManage,\n  UserManage,\n  ProgressBar,\n  LayoutHeaderNav,\n  LeftMenu,\n  ProTable,\n  ProForm,\n  DrawerForm,\n  ModalForm,\n  QueryForm,\n};\n"
  },
  {
    "path": "arius-console/src/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <meta  name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\" />\n  <meta name=\"description\" content=\"KnowSearch：一站式 Elasticsearch 集群指标监控与运维管控平台。\"/>\n  <title>KnowSearch</title>\n  <link rel=\"icon\" href=\"/favicon.ico\" />\n  <script src='/static/promise-polyfill.min.js'></script>\n\n</head>\n<body>\n  <div id=\"core-container\"></div>\n  <!-- <script defer src=\"/console/arius/kibana7/36136/bundles/kbn-ui-shared-deps/kbn-ui-shared-deps.js\" ></script> -->\n</body>\n</html>\n"
  },
  {
    "path": "arius-console/src/index.less",
    "content": "// @root-entry-name: \"default\";\n// @import \"~knowdesign/es/style/index.less\";\n// @import \"~knowdesign/es/style/components.less\";\n@import \"./style-addtion.less\";\n"
  },
  {
    "path": "arius-console/src/index.tsx",
    "content": "import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport App from \"./app\";\nimport \"./index.less\";\n\nReactDOM.render(<App />, document.getElementById(\"core-container\"));\n"
  },
  {
    "path": "arius-console/src/interface/common.ts",
    "content": "export interface IStringMap {\n  [index: string]: string;\n}\n\nexport interface ICookie {\n  key: string;\n  value?: string;\n  time?: number;\n}\n\nexport interface IMenuItem {\n  name?: string;\n  key: string;\n  show?: boolean;\n  type?: number;\n  label?: string;\n  content?: JSX.Element | string;\n  render?: (params: any) => JSX.Element;\n}\n\nexport interface IFilter {\n  text: string;\n  value: string;\n}\n\nexport interface IStatusMap {\n  [key: number]: string;\n}\n\nexport interface ILableKey<T> {\n  label: string;\n  key: string;\n  render?: (text: any, record?: T) => any;\n}\nexport interface ILeftMenuItem {\n  href: string;\n  i?: string;\n  title: string;\n}\n\nexport interface IRes extends Response {\n  code: number;\n  status: number;\n  message: string;\n  data: any;\n  pagination?: IPagination;\n}\n\nexport interface IFileType {\n  value: number;\n  parser?: \"Presto\" | \"Hive\" | \"Spark\";\n  title: string;\n  language?: string;\n  decomment?: boolean;\n  type?: number[];\n  timer?: boolean;\n}\n\nexport interface ITag {\n  tagId: string;\n  tag: string;\n  offset: IOffset;\n}\n\nexport interface IOffset {\n  year?: string;\n  month?: string;\n  week?: string;\n  day?: string;\n  hour?: string;\n  minute?: string;\n}\n\nexport interface IPreviewRow {\n  [key: number]: string;\n  key?: string | number;\n}\n\nexport interface ILabelValue {\n  value: string | number;\n  label?: string;\n  name?: string;\n  key?: number;\n  text?: string;\n}\n\nexport interface IXFormWrapper {\n  className?: string;\n  type?: string;\n  title: string;\n  onSubmit: (result: any) => any;\n  onCancel?: () => any;\n  visible: boolean;\n  onChangeVisible?: (visible: boolean) => any;\n  formMap?: any[];\n  formData?: any;\n  width?: number;\n  formLayout?: any;\n  okText?: string;\n  cancelText?: string;\n  customRenderElement?: React.ReactNode;\n  noform?: boolean;\n  nofooter?: boolean;\n  isWaitting?: boolean;\n  needBtnLoading?: boolean;\n  needSuccessMessage?: boolean;\n  layout?: \"inline\" | \"horizontal\" | \"vertical\";\n  actionAfterFailedSubmit?: () => any;\n  actionAfterSubmit?: (res: any) => any;\n  onHandleValuesChange?: (value: any, allValues: object) => any;\n}\n/*\n *@needSuccessMessage:控制成功之后的提示信息\n */\nexport interface IAction {\n  type: string;\n  payload: any;\n}\n\nexport interface IPagination {\n  pageNo: number;\n  pageSize: number;\n  total: number;\n}\n\nexport interface IClusterKanBanAction {\n  type: string;\n  clusterForm: {\n    clusterName?: string;\n    startTime?: number;\n    endTime?: number;\n    isMoreDay?: boolean;\n    isUpdate?: boolean;\n    bigShardThreshold?: number;\n  };\n}\nexport interface IGatewayKanbanAction {\n  type: string;\n  gatewayForm: {\n    startTime: number;\n    endTime: number;\n    isMoreDay: boolean;\n  };\n}\n\nexport interface IDashBoardAction {\n  type: string;\n  payload: {\n    startTime: number;\n    endTime: number;\n    isOperation: boolean;\n  };\n}\n"
  },
  {
    "path": "arius-console/src/interface/project.ts",
    "content": "export interface IProject {\n  dataCenter: string;\n  id: number;\n  memo: string;\n  name: string;\n  queryThreshold: number;\n  verifyCode: string;\n  projectCode: string;\n  projectName: string;\n  isAdmin: boolean;\n}\n"
  },
  {
    "path": "arius-console/src/lib/api-cache.ts",
    "content": "class ApiCache {\n  public apiCacheMap = new Map();\n\n  public setCacheMap = (key: string, data: any, timeout: number = 1 * 60 * 60 * 1000) => {\n    this.apiCacheMap.set(key, {\n      data,\n      timeout,\n      startTime: (new Date()).getTime(),\n    });\n  }\n\n  public getDataFromCache = (key: string) => {\n    const cacheData = this.apiCacheMap.get(key);\n\n    if (!cacheData) return null;\n\n    const { data, timeout, startTime } = cacheData;\n    const currentTime = (new Date()).getTime();\n\n    if ((currentTime - startTime) > timeout) {\n      this.deleteDataFromCache(key);\n      return null;\n    }\n    return data;\n  }\n\n  public deleteDataFromCache = (key: string) => {\n    return this.apiCacheMap.delete(key);\n  }\n}\n\nexport const apiCache = new ApiCache();\n"
  },
  {
    "path": "arius-console/src/lib/fetch.ts",
    "content": "import { notification, message } from \"antd\";\nimport store from \"store\";\nimport { csrfTokenMethod } from \"../constants/api\";\nimport { getCookie, getCurrentProject } from \"./utils\";\nimport { XNotification } from \"component/x-notification\";\n\nconst window = self.window;\nexport interface IRes {\n  code: number;\n  message: string;\n  data: any;\n  tip: string;\n}\n\nconst checkStatus = (res: Response) => {\n  if (res.status === 401) {\n    window.location.href = \"/login\";\n    // notification.error({ message: '无权限访问' });\n  }\n\n  // 关闭跳转403\n  // if (res.status === 405 || res.status === 403) {\n  //   location.href = '/403';\n  // }\n\n  if (res.status === 404) {\n    XNotification({ type: \"error\", message: \"接口不存在\" });\n  }\n\n  return res;\n};\n\nconst filter = (init: IInit) => (res: IRes) => {\n  if (res.code !== 0 && res.code !== 200) {\n    if (!init.errorNoTips) {\n      XNotification({ type: \"error\", message: \"错误\", description: res.message || \"服务错误，请重试！\" });\n      throw res;\n    }\n  }\n  if (res && res?.tip) {\n    message.info(res?.tip || \"\");\n  }\n  if (init.returnRes) {\n    return res;\n  }\n  return res.data;\n};\n\ninterface IInit extends RequestInit {\n  errorNoTips?: boolean;\n  body?: BodyInit | null | any;\n  prefix?: \"admin\" | \"ams\" | \"sql\" | \"mock\";\n  returnRes?: boolean;\n}\n\nconst uPrefix = {\n  admin: \"/api/es/admin\",\n  sql: \"\",\n  mock: \"/api/mock\",\n};\nconst addCustomHeader = (init?: IInit) => {\n  init.headers = Object.assign(init.headers || {}, {\n    \"X-SSO-USER\": getCookie(\"userName\") || \"\",\n    \"X-SSO-USER-ID\": getCookie(\"userId\") || \"\",\n    \"X-LOGI-SECURITY-PROJECT-ID\": getCurrentProject()?.id || \"\",\n  });\n  return init;\n};\n\nexport default function fetch(url: string, init?: IInit) {\n  if (!init) init = {};\n  const prefix = uPrefix[init.prefix] || uPrefix.admin;\n\n  const userId = getCookie(\"userId\");\n\n  if (!userId && !url.includes(\"/account/login\") && !url.includes(\"/security/user\") && !url.includes(\"/role/is-admin\")) {\n    window.location.href = \"/login\";\n  }\n  if (store.getState().user.userInfo?.id && userId !== store.getState().user.userInfo?.id) {\n    window.location.reload();\n  }\n\n  if (!init.credentials) init.credentials = \"include\";\n  if (init.body && typeof init.body === \"object\") init.body = JSON.stringify(init.body);\n  if (init.body && !init.method) init.method = \"POST\";\n  if (init.method) init.method = init.method.toUpperCase();\n\n  if (csrfTokenMethod.includes(init.method)) {\n    init.headers = Object.assign(\n      {},\n      init.headers || {\n        \"Content-Type\": \"application/json\",\n      }\n    );\n  }\n\n  init = addCustomHeader(init);\n  const realUrl = `${prefix}${url}`;\n\n  // 自动取消配置， 延迟2秒自动取消\n  // let controller = new AbortController();\n  // setTimeout(() => controller.abort(), 2000);\n\n  // init = { ...init, signal: controller.signal }\n  return window\n    .fetch(realUrl, init)\n    .then((res) => checkStatus(res))\n    .then((res) => res.json())\n    .then(filter(init));\n}\n\nexport function formFetch(url: string, init?: IInit) {\n  if (!init) init = {};\n  const prefix = uPrefix[init.prefix] || uPrefix.admin;\n\n  url = url.indexOf(\"?\") > 0 ? `${url}&dataCenter=${\"cn\"}` : `${url}?dataCenter=${\"cn\"}`; // :TODO\n\n  if (!/^http(s)?:\\/\\//.test(url)) {\n    url = `${prefix}${url}`;\n  }\n\n  init = addCustomHeader(init);\n  return window\n    .fetch(url, init)\n    .then((res) => checkStatus(res))\n    .then((res) => res.json())\n    .then(filter(init));\n}\n"
  },
  {
    "path": "arius-console/src/lib/permission.ts",
    "content": "import { IPermission } from \"store/type\";\nimport store from \"store\";\n\nexport const getPermissionTree = () => {\n  let permissionTree = [] as IPermission[];\n  try {\n    permissionTree = store.getState().user.permissionTree || [];\n  } catch (err) {\n    //\n  }\n  return permissionTree;\n}\n\nexport const hasOpPermission = (parentName: string, permissionName: string) => {\n  let permissionTree = getPermissionTree();\n  const target = permissionTree.find(item => item.permissionName === parentName)?.childList || [];\n\n  return target.find(row => row.permissionName === permissionName)?.has;\n};\n\nexport const getPagePermission = (permissionName: string, permissionTree: IPermission[]) => {\n  return permissionTree.find(item => item.permissionName === permissionName)?.has;\n};"
  },
  {
    "path": "arius-console/src/lib/url-parser.ts",
    "content": "interface IMap {\n  [key: string]: string;\n}\n\nexport default () => {\n  const Url = {\n    hash: {} as IMap,\n    search: {} as IMap,\n  } as {\n    hash: IMap;\n    search: IMap;\n    [key: string]: IMap;\n  };\n\n  window.location.hash.slice(1).split('&').map(str => {\n    const kv = str.split('=');\n    Url.hash[kv[0]] = kv[1];\n  });\n\n  window.location.search.slice(1).split('&').map(str => {\n    const kv = str.split('=');\n    Url.search[kv[0]] = kv[1];\n  });\n\n  return Url;\n};\n"
  },
  {
    "path": "arius-console/src/lib/utils.ts",
    "content": "import React, { useState, useEffect } from \"react\";\nimport { message } from \"antd\";\nimport { CURRENT_PROJECT_KEY, oneDayMillims } from \"constants/common\";\nimport { ICookie, IStringMap } from \"interface/common\";\nimport intlZhCN from \"../locales/zh\";\nimport * as SparkMD5 from \"spark-md5\";\nimport { systemKey, urlPrefix, leftMenus } from \"constants/menu\";\nimport moment, { Moment } from \"moment\";\nimport { timeFormat } from \"constants/time\";\nimport { IProject } from \"interface/project\";\n\nexport interface IStatusMap {\n  [key: number]: string;\n}\nexport interface IFilter {\n  text: string;\n  value: string;\n}\n\nexport const getCookie = (key: string): string => {\n  const map: IStringMap = {};\n  document.cookie.split(\";\").map((kv) => {\n    const d = kv.trim().split(\"=\");\n    map[d[0]] = d[1];\n    return null;\n  });\n  return map[key];\n};\n\nexport const setCookie = (cData: ICookie[]) => {\n  const date = new Date();\n  cData.forEach((ele) => {\n    date.setTime(date.getTime() + ele.time * oneDayMillims);\n    const expires = \"expires=\" + date.toUTCString();\n    document.cookie = ele.key + \"=\" + ele.value + \"; \" + expires + \"; path=/\";\n  });\n};\n\nexport const deleteCookie = (cData: string[]) => {\n  setCookie(cData.map((i) => ({ key: i, value: \"\", time: -1 })));\n};\n\nexport const copyString = (url: any) => {\n  const input = document.createElement(\"textarea\");\n  input.value = url;\n  document.body.appendChild(input);\n  input.select();\n  if (document.execCommand(\"copy\")) {\n    message.success(\"复制成功\");\n  }\n  input.remove();\n};\n\nexport const tableFilter = <T>(data: T[], name: keyof T, nameMap: IStatusMap = null): IFilter[] => {\n  if (!data) return [];\n  const obj: any = {};\n  return data?.reduce((cur, pre) => {\n    if (!obj[pre[name]] && pre[name]) {\n      obj[pre[name]] = true;\n      cur.push({\n        text: pre[name] !== undefined && nameMap ? nameMap[pre[name] as any] : pre[name],\n        value: pre[name],\n      });\n    }\n    return cur;\n  }, []);\n};\n\nexport const dealPathname = (pathname: string) => {\n  if ([\"/\", \"/es\"].indexOf(pathname) > -1) {\n    pathname = getCookie(\"isAdminUser\") === \"yes\" && isSuperApp() ? \"/es/dashboard\" : \"/es/cluster/logic\";\n  }\n  if ([\"/es/cluster\"].indexOf(pathname) > -1) {\n    pathname = \"/es/cluster/physics\";\n  }\n  return pathname;\n};\n\nexport const currentLeftIndex = (isSuperApp: boolean) => {\n  let path = window.location.pathname;\n  let systemList = [\n    \"/es/scheduling\",\n    \"/es/scheduling/task\",\n    \"/es/system/config\",\n    \"/es/system/operation\",\n    \"/es/scheduling/log\",\n    \"/es/scheduling/log/detail\",\n    \"/es/work-order/task\",\n    \"/es/work-order/my-approval\",\n    \"/es/system/project\",\n    \"/es/system/user\",\n    \"/es/system/role\",\n  ];\n  if (systemList.includes(path)) return 1;\n  return 0;\n};\n\nexport const redirectPath = (permissionPoints, history?: any, menuIndex?: number, changeProject?: boolean) => {\n  let path = window.location.pathname.slice(3);\n  let index = menuIndex || 0;\n  let permission = (permissionPoints || []).filter((item) => item.has);\n  let permissionNameList = (permission || []).map((item) => item.permissionName);\n  let menus = leftMenus[index]?.children || [];\n  let key = `menu.${systemKey}${path?.split(\"/\")?.join(\".\")}`;\n  let label = intlZhCN[key];\n  // 若有当前路由的权限，或为详情页，且不是点击切换多集群管理/系统管理，且不是切换应用，则不做跳转\n  let hasPermission = (permissionNameList.includes(label) || path.includes(\"detail\")) && menuIndex === undefined;\n  if (hasPermission && !changeProject) {\n    return path;\n  }\n  for (let i = 0; i < menus.length; i++) {\n    if (!menus[i].children && (permissionNameList.includes(menus[i]?.permissionPoint) || permissionNameList.includes(menus[i]?.path))) {\n      path = \"/\" + menus[i]?.path;\n      history && history.push(path);\n      return path;\n    } else {\n      let children = menus[i].children || [];\n      for (let j = 0; j < children.length; j++) {\n        let child = children[j];\n        if (permissionNameList.includes(child.permissionPoint)) {\n          path = \"/\" + menus[i].path + \"/\" + child.path;\n          history && history.push(path);\n          return path;\n        }\n      }\n    }\n  }\n};\n\nexport const setRouterPath = (pathname: string, search: string) => {\n  if (!(window as any).currentOpenRouterList) {\n    (window as any).currentOpenRouterList = [];\n  }\n  const routerList = [].concat((window as any).currentOpenRouterList);\n  pathname = dealPathname(pathname);\n\n  const key = `menu${pathname.split(\"/\")?.join(\".\")}`;\n  const index = routerList.findIndex((item) => item.key === key);\n  const href = search ? pathname.replace(`/${systemKey}`, \"\") + search : pathname.replace(`/${systemKey}`, \"\");\n\n  if (index < 0 && intlZhCN[key]) {\n    routerList.push({\n      key,\n      label: intlZhCN[key],\n      href,\n      show: true,\n    });\n  }\n  (window as any).currentOpenRouterList = routerList;\n};\n\nexport const computeChecksumMd5 = (file: File) => {\n  return new Promise((resolve, reject) => {\n    const chunkSize = 2097152; // Read in chunks of 2MB\n    const spark = new SparkMD5.ArrayBuffer();\n    const fileReader = new FileReader();\n\n    let cursor = 0; // current cursor in file\n\n    fileReader.onerror = () => {\n      reject(\"MD5 computation failed - error reading the file\");\n    };\n\n    function processChunk(chunkStart: number) {\n      const chunkEnd = Math.min(file.size, chunkStart + chunkSize);\n      fileReader.readAsArrayBuffer(file.slice(chunkStart, chunkEnd));\n    }\n\n    fileReader.onload = (e: any) => {\n      spark.append(e.target.result); // Accumulate chunk to md5 computation\n      cursor += chunkSize; // Move past this chunk\n\n      if (cursor < file.size) {\n        processChunk(cursor);\n      } else {\n        // Computation ended, last chunk has been processed. Return as Promise value.\n        // This returns the base64 encoded md5 hash, which is what\n        // Rails ActiveStorage or cloud services expect\n        // resolve(btoa(spark.end(true)));\n\n        // If you prefer the hexdigest form (looking like\n        // '7cf530335b8547945f1a48880bc421b2'), replace the above line with:\n        // resolve(spark.end());\n        resolve(spark.end());\n      }\n    };\n\n    processChunk(0);\n  });\n};\n\nexport const getFormatJsonStr = (obj: object = {}) => {\n  return Object.keys(obj).length > 0 ? JSON.stringify(obj, null, 4) : \"\";\n};\nexport const mappingFormatJsonStr = (obj: object = {}, dynamicTemplates: any[] = []) => {\n  const propertiesObj = obj && Object.keys(obj).length ? { properties: obj } : null;\n  const dynamicTemplatesObj = dynamicTemplates && dynamicTemplates.length ? { dynamic_templates: dynamicTemplates } : null;\n  return JSON.stringify({ ...propertiesObj, ...dynamicTemplatesObj }, null, 4);\n};\n\nexport const formatJsonStr = (json: string = \"\") => {\n  return json ? JSON.stringify(JSON.parse(json)) : \"\";\n};\n\nexport const goToTargetPage = (url: string) => {\n  window.location.href = `${urlPrefix}${url}`;\n};\n\nexport const getPercent = (numerator: number, denominator: number) => {\n  let percent = 0;\n  if (denominator === 0 && numerator === 0) {\n    percent = 0;\n  } else if (denominator === 0) {\n    percent = 100;\n  } else {\n    percent = ((numerator / denominator) * 100) | 0;\n    percent = percent > 100 ? 100 : percent;\n  }\n  return percent;\n};\n\nexport const transTimeStamp = (value: string) => {\n  return new Date(value).getTime();\n};\n\nexport const transTimeFormat = (value: string | number | Moment) => {\n  return value ? moment(value).format(timeFormat) : \"-\";\n};\n\nexport const getCurrentProject = () => {\n  let project = {} as IProject;\n  try {\n    project = JSON.parse(window.localStorage.getItem(CURRENT_PROJECT_KEY));\n  } catch (err) {\n    //\n  }\n  return project || ({} as IProject);\n};\n\nexport const isSuperApp = () => {\n  let project = getCurrentProject();\n  return project?.isAdmin;\n};\n\nexport const toFixedNum = (value, num: number = 2) => {\n  if (!value) {\n    return 0;\n  }\n  if (num === 0) {\n    return parseInt(value);\n  }\n  if (parseInt(value) === value) {\n    return value;\n  }\n  let val = Number(value);\n  return val.toFixed(num);\n};\n\nconst KB = 1024;\nconst unitFormatter = [\n  {\n    name: \"B\",\n    value: 1,\n  },\n  {\n    name: \"KB\",\n    value: KB,\n  },\n  {\n    name: \"MB\",\n    value: Math.pow(KB, 2),\n  },\n  {\n    name: \"GB\",\n    value: Math.pow(KB, 3),\n  },\n  {\n    name: \"TB\",\n    value: Math.pow(KB, 4),\n  },\n  {\n    name: \"PB\",\n    value: Math.pow(KB, 5),\n  },\n];\n\nexport const bytesUnitFormatter = (bytes: number, type?: string) => {\n  if (!bytes) {\n    return 0;\n  }\n  for (let i = unitFormatter.length - 1; i >= 0; i--) {\n    if (bytes >= unitFormatter[i].value) {\n      if (type === \"float\") {\n        return formatNum(bytes / unitFormatter[i].value) + unitFormatter[i].name;\n      }\n      return parseInt(bytes / unitFormatter[i].value + \"\") + unitFormatter[i].name;\n    }\n  }\n};\n\nexport const resize = () => {\n  if (!document.createEvent) {\n    return;\n  }\n  let event = document.createEvent(\"HTMLEvents\");\n  event.initEvent(\"resize\", true, true);\n  window.dispatchEvent(event);\n};\n\nexport const asyncMicroTasks = (callback: () => void) => {\n  new Promise((res, rej) => res(0)).then(() => {\n    callback();\n  });\n};\n\n/**\n * JS对象转URL字符串参数\n * @param {Object} obj - 待转换的对象\n * @returns {string} - 转换成的请求字符串\n */\nexport const objTransUrlParams = (obj) => {\n  const params = [];\n  Object.keys(obj).forEach((key) => {\n    let value = obj[key];\n    // 如果值为undefined我们将其置空\n    if (typeof value === \"undefined\") {\n      value = \"\";\n    }\n    // 对于需要编码的文本（比如说中文）我们要进行编码\n    params.push([key, encodeURIComponent(value)].join(\"=\"));\n  });\n  return params.join(\"&\");\n};\n\n/*\n *流量单位转bytes\n */\nexport const toBytesFun = (data: any) => {\n  if (data === \"null\" || data === null || data === undefined || data === \"0\" || data === \"0b\" || data === \"\") return 0;\n  const originNum = parseFloat(data);\n  const sizes = [\"b\", \"kb\", \"mb\", \"gb\", \"tb\", \"pb\", \"eb\", \"zb\", \"yb\"];\n  const reg = /[a-z]/g;\n  const end = data.match(reg).join(\"\");\n  const powerNum = sizes.indexOf(end);\n  const toBytes = Math.pow(1024, powerNum) * originNum;\n  return toBytes;\n};\n\n/* 生成唯一key */\nexport const uuid = () => {\n  var d = new Date().getTime();\n  if (window.performance && typeof window.performance.now === \"function\") {\n    d += performance.now(); //use high-precision timer if available\n  }\n  var uuid = \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function (c) {\n    var r = (d + Math.random() * 16) % 16 | 0; // d是随机种子\n    d = Math.floor(d / 16);\n    return (c == \"x\" ? r : (r & 0x3) | 0x8).toString(16);\n  });\n  return uuid;\n};\n\n/* 拍平schema为标准路径 */\n/*\n *{\n * a.b.c.d:{type:\"string\"}\n * b:{type:\"number\"}\n *}\n */\nexport const transformSchema = (jsonObj) => {\n  // 整理数据 去掉 properties 层的数据\n  if (jsonObj) {\n    //jsonObj不能是空\n    // const transFormJson = JSON.parse(jsonObj);\n    const arrayKey = Object.keys(jsonObj);\n    if (!arrayKey.length) return;\n    const filterProperties = (obj) => {\n      let result = {};\n      if (!obj) return {};\n      const bb = (sou, tar) => {\n        const keys = Object.keys(sou);\n        for (const key of keys) {\n          if (key === \"properties\") {\n            bb(sou[key], tar);\n          } else if (sou[key].hasOwnProperty(\"properties\")) {\n            if (!tar[key]) {\n              tar[key] = {};\n            }\n            bb(sou[key].properties, tar[key]);\n          } else {\n            tar[key] = sou[key];\n          }\n        }\n        return tar;\n      };\n      return bb(obj, result);\n    };\n\n    const flat = (obj) => {\n      let newObj = {};\n      function format(o, pre) {\n        for (let key in o) {\n          if (typeof o[key] === \"object\") {\n            if (!pre) {\n              format(o[key], key);\n            } else {\n              if (Array.isArray(o)) {\n                format(o[key], pre + \"[\" + key + \"]\");\n              } else {\n                format(o[key], pre + \".\" + key);\n              }\n            }\n          } else {\n            if (!pre) {\n              newObj[key] = o;\n            } else {\n              if (Array.isArray(o)) {\n                newObj[pre + \"[\" + key + \"]\"] = o; //es不考虑数组情况\n              } else {\n                newObj[pre] = o;\n              }\n            }\n          }\n        }\n      }\n      format(obj, null);\n      return newObj;\n    };\n\n    let json = filterProperties(jsonObj);\n    return flat(json);\n  }\n};\n\nexport const getPopupContainer = (triggerNode) => {\n  // 带搜索框的穿梭框的全选反选弹出层会被搜索框遮挡\n  const isTransfer = triggerNode?.className?.indexOf(\"ant-transfer-list-header-dropdown\") !== -1;\n  return triggerNode && !isTransfer ? triggerNode : document.body;\n};\n\nexport const formatTime = (msTime: number) => {\n  //将毫秒转化成具体的时分秒；\n  let time = msTime / 1000;\n  let hour;\n  hour = Math.floor(time / 60 / 60);\n  let minute;\n  minute = Math.floor(time / 60) % 60;\n  let second;\n  second = Math.floor(time) % 60;\n  return `${hour ? hour + \"小时\" : \"\"}${minute ? minute + \"分\" : \"\"}${second}秒`;\n};\n\nexport const filterOption = (input, option) => JSON.stringify(option).toLowerCase().indexOf(input.toLowerCase()) >= 0;\n\nexport const useResize = (className: string) => {\n  const [size, setSize] = useState({\n    height: document.querySelector(`.${className}`)?.clientHeight,\n  });\n\n  useEffect(() => {\n    const onResize = () => {\n      setSize({\n        height: document.querySelector(`.${className}`)?.clientHeight,\n      });\n    };\n    window.addEventListener(\"resize\", onResize);\n    return () => {\n      window.removeEventListener(\"resize\", onResize);\n    };\n  }, []);\n  return size;\n};\n\n// 四舍五入不补全\nexport const formatNum = (val, num: number = 2) => Math.round(val.toFixed(num) * Math.pow(10, num)) / Math.pow(10, num);\n\n// 保留两位小数(列表数据)\nexport const formatDecimalPoint = (value, num: number = 2) => {\n  if (value === null || value === undefined || value === \"null\" || value === \"\") {\n    return \"-\";\n  } else if (typeof value === \"string\") {\n    // 有可能带单位\n    const valNum = parseFloat(value);\n    const unit = value.match(/[A-Za-z]/g).join(\"\");\n    return formatNum(valNum, num) + unit;\n  } else {\n    return formatNum(value, num);\n  }\n};\n"
  },
  {
    "path": "arius-console/src/locales/en.tsx",
    "content": "import { en } from '../d1-packages';\nexport default {\n    ...en\n};\n"
  },
  {
    "path": "arius-console/src/locales/zh.tsx",
    "content": "import { zh } from \"../d1-packages\";\nimport { systemKey } from \"../constants/menu\";\n\nexport const permissions = {\n  [`menu.${systemKey}.cluster.physics.detail`]: \"/cluster/physics\",\n  [`menu.${systemKey}.cluster.logic.detail`]: \"/cluster/logic\",\n  [`menu.${systemKey}.index-tpl.management.detail`]: \"/index-tpl/management\",\n  [`menu.${systemKey}.index-tpl.service.detail`]: \"/index-tpl/management\",\n  [`menu.${systemKey}.index-tpl.management.modify`]: \"/index-tpl/management\",\n  [`menu.${systemKey}.index-tpl.management.modify.mapping`]: \"/index-tpl/management\",\n  [`menu.${systemKey}.index-admin.detail`]: \"/index-admin\",\n  [`menu.${systemKey}.work-order.my-application.detail`]: \"/work-order/my-application\",\n  [`menu.${systemKey}.work-order.my-approval.detail`]: \"/work-order/my-approval\",\n  [`menu.${systemKey}.scheduling.log.detail`]: \"/scheduling/log\",\n  [`menu.${systemKey}.scheduling.task.dcdrdetail`]: \"/work-order/task\",\n};\n\nexport default {\n  ...zh,\n  [`menu`]: \"物理集群\",\n  [`menu.${systemKey}`]: \"物理集群\",\n  [`menu.${systemKey}.cluster`]: \"集群管理\",\n  [`menu.${systemKey}.cluster.physics`]: \"物理集群\",\n  [`menu.${systemKey}.cluster.logic`]: \"我的集群\",\n  [`menu.${systemKey}.cluster.physics.detail`]: \"集群详情\",\n  [`menu.${systemKey}.cluster.logic.detail`]: \"集群详情\",\n  [`menu.${systemKey}.cluster.edition`]: \"集群版本\",\n  [`menu.${systemKey}.indicators`]: \"指标看板\",\n  [`menu.${systemKey}.indicators.cluster`]: \"集群看板\",\n  [`menu.${systemKey}.indicators.gateway`]: \"网关看板\",\n  [`menu.${systemKey}.system`]: \"租户管理\",\n  [`menu.${systemKey}.system.config`]: \"平台配置\",\n  [`menu.${systemKey}.system.operation`]: \"操作记录\",\n  // [`menu.${systemKey}.user`]: '用户管理',\n  [`menu.${systemKey}.system.users`]: \"用户管理\",\n  [`menu.${systemKey}.system.role`]: \"角色管理\",\n  [`menu.${systemKey}.system.project`]: \"应用管理\",\n  [`menu.${systemKey}.system.project.detail`]: \"应用详情\",\n  [`menu.${systemKey}.work-order`]: \"工单任务\",\n  [`menu.${systemKey}.work-order.my-application`]: \"我的申请\",\n  [`menu.${systemKey}.work-order.my-application.detail`]: \"我的申请详情\",\n  [`menu.${systemKey}.work-order.my-approval`]: \"我的审批\",\n  [`menu.${systemKey}.work-order.my-approval.detail`]: \"工单详情\",\n  [`menu.${systemKey}.work-order.task`]: \"任务中心\",\n  [`menu.${systemKey}.work-order.task.detail`]: \"任务详情\",\n  [`menu.${systemKey}.work-order.task.dcdrdetail`]: \"任务详情\",\n  [`menu.${systemKey}.scheduling`]: \"调度任务\",\n  [`menu.${systemKey}.scheduling.task`]: \"任务列表\",\n  [`menu.${systemKey}.scheduling.log`]: \"调度日志\",\n  [`menu.${systemKey}.scheduling.log.detail`]: \"调度日志详情\",\n  [`menu.${systemKey}.search-query`]: \"检索查询\",\n  [`menu.${systemKey}.search-query.dsl`]: \"DSL查询\",\n  [`menu.${systemKey}.search-query.sql`]: \"SQL查询\",\n  [`menu.${systemKey}.search-query.kibana`]: \"Kibana\",\n  [`menu.${systemKey}.search-query.dsl-tpl`]: \"查询诊断\",\n  [`menu.${systemKey}.search-query.search-template`]: \"查询模板\",\n  [`menu.${systemKey}.index-admin`]: \"索引管理\",\n  [`menu.${systemKey}.index-admin.management`]: \"索引管理\",\n  [`menu.${systemKey}.index-admin.management.detail`]: \"索引详情\",\n  [`menu.${systemKey}.index-admin.service`]: \"索引服务\",\n  [`menu.${systemKey}.index-tpl`]: \"模板管理\",\n  [`menu.${systemKey}.index-tpl.management`]: \"模板管理\",\n  [`menu.${systemKey}.index-tpl.detail`]: \"模板详情\",\n  [`menu.${systemKey}.index-tpl.management.detail`]: \"模板管理详情\",\n  [`menu.${systemKey}.index-tpl.service.detail`]: \"索引模板详情\",\n  [`menu.${systemKey}.index-tpl.management.create`]: \"新建模板\",\n  [`menu.${systemKey}.index-tpl.management.modify`]: \"编辑模板\",\n  [`menu.${systemKey}.index-tpl.management.modify.mapping`]: \"编辑Mapping\",\n  [`menu.${systemKey}.index-tpl.management.modify.setting`]: \"编辑Setting\",\n  [`menu.${systemKey}.index-tpl.service`]: \"模板服务\",\n  [`menu.${systemKey}.dashboard`]: \"Dashboard\",\n  [`menu.${systemKey}.grafana`]: \"Grafana大盘\",\n};\n"
  },
  {
    "path": "arius-console/src/pages/cachePage.tsx",
    "content": "export const cachePage = [\n  \"/cluster/physics\",\n  \"/cluster/logic\",\n  \"/cluster/edition\",\n  \"/index-tpl/management\",\n  \"/index-tpl/create\",\n  \"/index-tpl/service\",\n  \"/index-admin/management\",\n  \"/index-admin/service\",\n  \"/search-query/index-search\",\n  \"/search-query/dsl-tpl\",\n  \"/indicators/cluster\",\n  \"/indicators/gateway\",\n  \"/work-order/my-application\",\n  \"/work-order/my-approval\",\n  \"/work-order/task\",\n  \"/scheduling/task\",\n  \"/scheduling/log\",\n  \"/system/config\",\n  \"/system/operation\",\n];\nexport const mulityPage = {\n  \"/cluster/logic/detail\": (lan: string) => decodeURIComponent(window.location.search.slice(1).split(\"&\")[0].split(\"=\")[1]) + lan,\n  \"/cluster/physics/detail\": (lan: string) => decodeURIComponent(window.location.search.slice(1).split(\"&\")[0].split(\"=\")[1]) + lan,\n  \"/index-tpl/service/detail\": (lan: string) => decodeURIComponent(window.location.search.slice(1).split(\"&\")[0].split(\"=\")[1]) + lan,\n  \"/index-admin/management/detail\": (lan: string) => decodeURIComponent(window.location.search.slice(1).split(\"&\")[0].split(\"=\")[1]) + lan,\n  \"/index-tpl/management/detail\": (lan: string) => decodeURIComponent(window.location.search.slice(1).split(\"&\")[0].split(\"=\")[1]) + lan,\n  \"/work-order/my-approval/detail\": (lan: string) => decodeURIComponent(window.location.search.slice(1).split(\"&\")[0].split(\"=\")[1]) + lan,\n  \"/work-order/my-application/detail\": (lan: string) =>\n    decodeURIComponent(window.location.search.slice(1).split(\"&\")[0].split(\"=\")[1]) + lan,\n  \"/work-order/task/detail\": (lan: string) => decodeURIComponent(window.location.search.slice(1).split(\"&\")[0].split(\"=\")[1]) + lan,\n  \"/work-order/task/dcdrdetail\": (lan: string) => decodeURIComponent(window.location.search.slice(1).split(\"&\")[0].split(\"=\")[1]) + lan,\n};\n"
  },
  {
    "path": "arius-console/src/pages/cluster-admin.tsx",
    "content": "import * as React from \"react\";\nimport { PhysicsCluster } from \"../container/cluster\";\nimport { LogicCluster } from \"../container/cluster\";\nimport { LogicClusterDetail } from \"container/cluster/logic-detail/detail\";\nimport { PhyClusterDetail } from \"container/cluster/physics-detail/detail\";\nimport { EditionCluster } from \"container/cluster/cluster-edition\";\nimport { DashBoard } from \"../container/dashboard/index\";\nimport { getCookie } from \"knowdesign/lib/utils/tools\";\nimport { ClusterVersionPermissions, MyClusterPermissions, PhyClusterPermissions } from \"constants/permission\";\nimport { isSuperApp } from \"lib/utils\";\n\nexport const ClusterAdminPageRoutes = [\n  {\n    path: \"/\",\n    exact: true,\n    component: isSuperApp() ? DashBoard : LogicCluster,\n  },\n  {\n    path: \"/cluster\",\n    exact: true,\n    component: PhysicsCluster,\n    permissionPoint: PhyClusterPermissions.PAGE,\n  },\n  {\n    path: \"/cluster/physics\",\n    exact: true,\n    component: PhysicsCluster,\n    needCache: true,\n    permissionPoint: PhyClusterPermissions.PAGE,\n  },\n  {\n    path: \"/cluster/logic\",\n    exact: true,\n    component: LogicCluster,\n    needCache: true,\n    permissionPoint: MyClusterPermissions.PAGE,\n  },\n  {\n    path: \"/cluster/edition\",\n    exact: true,\n    component: EditionCluster,\n    needCache: true,\n    permissionPoint: ClusterVersionPermissions.PAGE,\n  },\n  {\n    path: \"/cluster/logic/detail\",\n    exact: true,\n    component: LogicClusterDetail,\n    permissionPoint: MyClusterPermissions.PAGE,\n  },\n  {\n    path: \"/cluster/physics/detail\",\n    exact: true,\n    component: PhyClusterDetail,\n    permissionPoint: PhyClusterPermissions.PAGE,\n  },\n];\n"
  },
  {
    "path": "arius-console/src/pages/cluster-system.tsx",
    "content": "import * as React from \"react\";\nimport { ClusterConfig } from \"container/system/cluster-config\";\nimport { OperatingList } from \"container/system/operating-list\";\nimport { OPRecordPermissions, PlatformPermissions } from \"constants/permission\";\n\nexport const ClusterSystemPageRoutes = [\n  {\n    path: \"/\",\n    exact: true,\n    component: ClusterConfig,\n    permissionPoint: PlatformPermissions.PAGE,\n  },\n  {\n    path: \"/system\",\n    exact: true,\n    component: ClusterConfig,\n    permissionPoint: PlatformPermissions.PAGE,\n  },\n  {\n    path: \"/system/config\",\n    exact: true,\n    component: ClusterConfig,\n    needCache: true,\n    permissionPoint: PlatformPermissions.PAGE,\n  },\n  {\n    path: \"/system/operation\",\n    exact: true,\n    component: OperatingList,\n    needCache: true,\n    permissionPoint: OPRecordPermissions.PAGE,\n  },\n];\n"
  },
  {
    "path": "arius-console/src/pages/dashboard.tsx",
    "content": "import { DashBoard } from '../container/dashboard/index';\n\nexport const DashBoardPageRoutes = [\n  {\n    path: '/dashboard',\n    exact: true,\n    component: DashBoard,\n  },\n];\n\n"
  },
  {
    "path": "arius-console/src/pages/index-admin.tsx",
    "content": "import { IndexPermissions, IndexServicePermissions } from \"constants/permission\";\nimport * as React from \"react\";\nimport { IndexAdmin, IndexService } from \"../container/index-admin\";\nimport { IndexAdminDetail } from \"../container/index-admin/detail\";\n\nexport const IndexAdminPagePageRoutes = [\n  {\n    path: \"/index-admin\",\n    exact: true,\n    component: IndexAdmin,\n    permissionPoint: IndexPermissions.PAGE,\n  },\n  {\n    path: \"/index-admin/management\",\n    exact: true,\n    component: IndexAdmin,\n    needCache: true,\n    permissionPoint: IndexPermissions.PAGE,\n  },\n  {\n    path: \"/index-admin/management/detail\",\n    exact: true,\n    component: IndexAdminDetail,\n    permissionPoint: IndexPermissions.PAGE,\n  },\n  {\n    path: \"/index-admin/service\",\n    exact: true,\n    needCache: true,\n    component: IndexService,\n    permissionPoint: IndexServicePermissions.PAGE,\n  },\n];\n"
  },
  {
    "path": "arius-console/src/pages/index-tpl-management.tsx",
    "content": "import * as React from \"react\";\nimport { IndexTplManagement, IndexTplService, IndexTplDetail } from \"container/index-tpl-management\";\nimport { CreateIndexTpl } from \"container/index-tpl-management/create\";\nimport { EditBaseInfo } from \"container/index-tpl-management/edit/baseInfo\";\nimport { JsonMapping } from \"container/index-tpl-management/edit/jsonMapping\";\nimport { JsonSetting } from \"container/index-tpl-management/edit/jsonSetting\";\nimport { TempletPermissions, TempletServicePermissions } from \"constants/permission\";\n\nexport const IndexTplManagementPageRoutes = [\n  {\n    path: \"/index-tpl\",\n    exact: true,\n    component: IndexTplManagement,\n    permissionPoint: TempletPermissions.PAGE,\n  },\n  {\n    path: \"/index-tpl/management\",\n    exact: true,\n    component: IndexTplManagement,\n    needCache: true,\n    permissionPoint: TempletPermissions.PAGE,\n  },\n  {\n    path: \"/index-tpl/management/detail\",\n    exact: true,\n    component: IndexTplDetail,\n  },\n  // {\n  //   path: \"/index-tpl/management/create\",\n  //   exact: true,\n  //   component: CreateIndexTpl,\n  //   needCache: true,\n  // },\n  // {\n  //   path: \"/index-tpl/management/modify\",\n  //   exact: true,\n  //   component: EditBaseInfo,\n  // },\n  {\n    path: \"/index-tpl/management/modify/mapping\",\n    exact: true,\n    component: JsonMapping,\n  },\n  {\n    path: \"/index-tpl/management/modify/setting\",\n    exact: true,\n    component: JsonSetting,\n  },\n  {\n    path: \"/index-tpl/service\",\n    exact: true,\n    component: IndexTplService,\n    needCache: true,\n    permissionPoint: TempletServicePermissions.PAGE,\n  },\n  {\n    path: \"/index-tpl/service/detail\",\n    exact: true,\n    component: IndexTplDetail,\n  },\n];\n"
  },
  {
    "path": "arius-console/src/pages/index.less",
    "content": "* {\n  padding: 0;\n  margin: 0;\n  -webkit-font-smoothing: antialiased;\n}\n\n.hide {\n  display: none;\n}\n\nli {\n  list-style-type: none;\n}\n\nhtml,\nbody,\n.router-nav {\n  width: 100%;\n  height: 100%;\n  font-family: PingFangSC-Regular;\n}\n\n[class*=\"k-icon-\"] {\n  font-family: kafka-manager;\n  font-style: normal;\n  font-weight: 400;\n  text-transform: none;\n  line-height: 1;\n  vertical-align: baseline;\n  display: inline-block;\n  -webkit-font-smoothing: antialiased;\n  font-variant: normal normal;\n}\n\n#root {\n  width: 100%;\n  position: fixed;\n  top: 0;\n  bottom: 0;\n  font-size: 14px;\n}\n\n.core-spin {\n  &.ant-spin-nested-loading {\n    position: unset;\n\n    .ant-spin-container {\n      position: unset;\n    }\n  }\n}\n\n.core-container {\n  display: flex;\n  flex-flow: row nowrap;\n  bottom: 0;\n  top: 65px;\n  position: absolute;\n  width: 100%;\n}\n\n.content-container {\n  flex: 1;\n  padding: 16px;\n  background: rgba(243, 244, 245, 1);\n  overflow: auto;\n}\n\n.head-tip {\n  height: 30px;\n  line-height: 30px;\n  margin-bottom: 10px;\n}\n\n.head-tip:before {\n  border-left: 4px solid @primary-color;\n  margin-right: 6px;\n  content: \"\";\n}\n\n.op-btn-group {\n  text-align: center;\n  border-top: 1px solid #e8e8e8;\n  padding-top: 15px;\n\n  &.no-border {\n    border-top: none;\n  }\n\n  Button {\n    margin-right: 15px;\n  }\n}\n\n.bread-crumb {\n  padding: 0px 0px 15px 0px !important;\n}\n\n.es-open-theme {\n  color: @primary-color;\n}\n\n.mt-24 {\n  margin-top: 24px;\n}\n\n.mb-24 {\n  margin-bottom: 24px;\n}\n\n.success {\n  color: #2fc25b;\n}\n\n.fail {\n  color: #f5222d;\n}\n\n.ant-table-thead > tr > th,\n.ant-table-tbody > tr > td {\n  padding: 13px;\n}\n\n.ant-table-tbody > tr > td {\n  background: #fff;\n}\n\n.ant-select-dropdown-menu-item-active,\n.ant-select-dropdown-menu-item:hover {\n  background: #f3f3f3;\n}\n\n.question-icon {\n  color: @primary-color !important;\n  margin-left: 10px;\n}\n\n.loading-content {\n  text-align: center;\n  width: 100%;\n  height: 200px;\n  line-height: 200px !important;\n}\n\n.ml-5 {\n  margin-left: 5px;\n}\n\n.ml-10 {\n  margin-left: 10px;\n}\n\n.ml-15 {\n  margin-left: 15px;\n}\n\n.mr-5 {\n  margin-right: 5px;\n}\n\n.mr-10 {\n  margin-right: 10px;\n}\n\n.mr-15 {\n  margin-right: 15px;\n}\n\n.mb-20 {\n  margin-bottom: 20px;\n}\n\n.mb-0 {\n  margin-bottom: 0px;\n}\n\n.mt-20 {\n  margin-top: 20px;\n}\n\n.fr {\n  float: right;\n}\n\n.iframe-page {\n  height: -webkit-fill-available;\n  border: none;\n  width: 100%;\n\n  &.fix-height {\n    height: 800px;\n  }\n}\n\n.line-break {\n  white-space: pre-line;\n  height: 50vh;\n  overflow-y: scroll;\n  padding: 10px;\n}\n\nhtml,\nbody,\ndiv,\nspan,\napplet,\nobject,\niframe,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\np,\nblockquote,\npre,\na,\nabbr,\nacronym,\naddress,\nbig,\ncite,\ncode,\ndel,\ndfn,\nem,\nimg,\nins,\nkbd,\nq,\ns,\nsamp,\nsmall,\nstrike,\nstrong,\nsub,\nsup,\ntt,\nvar,\nb,\nu,\ni,\ncenter,\ndl,\ndt,\ndd,\nol,\nul,\nli,\nfieldset,\nform,\nlabel,\nlegend,\ntable,\ncaption,\ntbody,\ntfoot,\nthead,\ntr,\nth,\ntd,\narticle,\naside,\ncanvas,\ndetails,\nembed,\nfigure,\nfigcaption,\nfooter,\nheader,\nhgroup,\nmenu,\nnav,\noutput,\nruby,\nsection,\nsummary,\ntime,\nmark,\naudio,\nvideo {\n  margin: 0;\n  padding: 0;\n  border: none;\n  vertical-align: revert;\n}\n\nbody {\n  margin: 0;\n  color: rgba(0, 0, 0, 0.85);\n  font-size: 12px;\n  font-family: \"Helvetica Neue, Helvetica, Arial, PingFang SC, Heiti SC, Hiragino Sans GB, Microsoft YaHei, sans-serif\";\n  line-height: 1.5715;\n  background-color: #fff;\n  font-feature-settings: \"tnum\";\n}\n\ncode,\npre,\nkbd,\nsamp {\n  font-family: inherit;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\np {\n  font-family: inherit;\n  font-weight: inherit;\n  font-size: inherit;\n}\n\ninput,\ntextarea,\nselect,\nbutton {\n  font-family: inherit;\n}\n\nem {\n  font-style: inherit;\n}\n\nstrong {\n  font-weight: inherit;\n}\n\n/* HTML5 display-role reset for older browsers */\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmenu,\nnav,\nsection {\n  display: block;\n}\n\nhtml {\n  font-weight: inherit;\n  letter-spacing: inherit;\n  -webkit-text-size-adjust: 100%;\n  -ms-text-size-adjust: 100%;\n  -webkit-font-kerning: inherit;\n  font-kerning: inherit;\n  font-size: inherit;\n  color: inherit;\n  background-color: inherit;\n}\n\na {\n  text-decoration: none;\n  color: @primary-color;\n}\n"
  },
  {
    "path": "arius-console/src/pages/index.tsx",
    "content": "import { ClusterAdminPageRoutes } from \"./cluster-admin\";\nimport { ClusterSystemPageRoutes } from \"./cluster-system\";\nimport { IndexAdminPagePageRoutes } from \"./index-admin\";\nimport { IndexTplManagementPageRoutes } from \"./index-tpl-management\";\nimport { IndicatorsKanbanPageRoutes } from \"./indicators-kanban\";\nimport { SchedulingPageRoutes } from \"./scheduling\";\nimport { SearchQueryPageRoutes } from \"./search-query\";\nimport { systemPageRoutes } from \"./system-page\";\nimport { workOrderPageRouter } from \"./work-order\";\nimport { DashBoardPageRoutes } from \"./dashboard\";\nimport \"../styles/common.less\";\nimport \"./index.less\";\nimport { routeItemType } from \"../d1-packages/RouterGuard\";\n\nexport const PageRoutes = [\n  ...ClusterAdminPageRoutes,\n  ...ClusterSystemPageRoutes,\n  ...IndexAdminPagePageRoutes,\n  ...IndexTplManagementPageRoutes,\n  ...IndicatorsKanbanPageRoutes,\n  ...SchedulingPageRoutes,\n  ...SearchQueryPageRoutes,\n  ...systemPageRoutes,\n  ...workOrderPageRouter,\n  ...DashBoardPageRoutes,\n] as routeItemType[];\n"
  },
  {
    "path": "arius-console/src/pages/indicators-kanban.tsx",
    "content": "import { ClusterPanelPermissions, GatewayPanelPermissions } from \"constants/permission\";\nimport * as React from \"react\";\nimport { ClusterKanban, GatewayKanban } from \"../container/indicators-kanban\";\n\nexport const IndicatorsKanbanPageRoutes = [\n  {\n    path: \"/indicators\",\n    exact: true,\n    component: ClusterKanban,\n    permissionPoint: ClusterPanelPermissions.PAGE,\n  },\n  {\n    path: \"/indicators/cluster\",\n    exact: true,\n    component: ClusterKanban,\n    permissionPoint: ClusterPanelPermissions.PAGE,\n  },\n  {\n    path: \"/indicators/gateway\",\n    exact: true,\n    needCache: true,\n    component: GatewayKanban,\n    permissionPoint: GatewayPanelPermissions.PAGE,\n  },\n];\n"
  },
  {
    "path": "arius-console/src/pages/scheduling.tsx",
    "content": "import * as React from \"react\";\nimport { Schedulinglog } from \"container/Scheduling/schedulinglog\";\nimport { TaskList } from \"container/Scheduling/taskList\";\nimport { ShceduleLogPermissions, ShceduleTaskPermissions } from \"constants/permission\";\n\nexport const SchedulingPageRoutes = [\n  {\n    path: \"/scheduling\",\n    exact: true,\n    component: TaskList,\n    permissionPoint: ShceduleTaskPermissions.PAGE,\n  },\n  {\n    path: \"/scheduling/task\",\n    exact: true,\n    component: TaskList,\n    needCache: true,\n    permissionPoint: ShceduleTaskPermissions.PAGE,\n  },\n  {\n    path: \"/scheduling/log\",\n    exact: true,\n    component: Schedulinglog,\n    needCache: true,\n    permissionPoint: ShceduleLogPermissions.PAGE,\n  },\n  {\n    path: \"/scheduling/log/detail\",\n    exact: true,\n    component: Schedulinglog,\n    permissionPoint: ShceduleLogPermissions.PAGE,\n  },\n];\n"
  },
  {
    "path": "arius-console/src/pages/search-query.tsx",
    "content": "import { DslTpl } from \"container/search-query/dsl-tpl\";\nimport { DslPage } from \"container/search-query/dsl-page\";\nimport { SqlPage } from \"container/search-query/sql-page\";\nimport { KibanaPage } from \"container/search-query/kibana-page\";\nimport { QueryTpl } from \"container/search-query/query-tpl\";\nimport { DslPermissions, SqlPermissions, KibanaPermissions, SearchQueryPermissions, SearchTemplatePermissions } from \"constants/permission\";\n\nexport const SearchQueryPageRoutes = [\n  {\n    path: \"/search-query/dsl-tpl\",\n    exact: true,\n    component: DslTpl,\n    needCache: true,\n    permissionPoint: SearchQueryPermissions.PAGE,\n  },\n  {\n    path: \"/search-query/search-template\",\n    exact: true,\n    component: QueryTpl,\n    permissionPoint: SearchTemplatePermissions.PAGE,\n  },\n  {\n    path: \"/search-query/dsl\",\n    exact: true,\n    component: DslPage,\n    permissionPoint: DslPermissions.PAGE,\n  },\n  {\n    path: \"/search-query/sql\",\n    exact: true,\n    component: SqlPage,\n    needCache: true,\n    permissionPoint: SqlPermissions.PAGE,\n  },\n  {\n    path: \"/search-query/kibana\",\n    exact: true,\n    component: KibanaPage,\n    needCache: true,\n    permissionPoint: KibanaPermissions.PAGE,\n  },\n];\n"
  },
  {
    "path": "arius-console/src/pages/system-page.tsx",
    "content": "import { ProjectList } from \"container/ProjectManager\";\nimport { ProjectDetail } from \"container/ProjectManager/detail\";\nimport { RoleManage } from \"../d1-packages/CommonPages/RoleManage\";\nimport { RoleDetail } from \"container/RoleManager/detail\";\nimport { UserManage } from \"../d1-packages/CommonPages/UserManage\";\nimport * as React from \"react\";\nimport { ProjectPermissions, RolePermissions, UserPermissions } from \"constants/permission\";\n\nexport const systemPageRoutes = [\n  {\n    path: \"/\",\n    exact: true,\n    component: UserManage,\n    permissionPoint: UserPermissions.PAGE,\n  },\n  {\n    path: \"/system/users\",\n    exact: true,\n    component: UserManage,\n    permissionPoint: UserPermissions.PAGE,\n  },\n  {\n    path: \"/system/project\",\n    exact: true,\n    component: ProjectList,\n    permissionPoint: ProjectPermissions.PAGE,\n  },\n  {\n    path: \"/system/project/detail\",\n    exact: true,\n    component: ProjectDetail,\n    permissionPoint: ProjectPermissions.PAGE,\n  },\n  {\n    path: \"/system/role\",\n    exact: true,\n    component: RoleManage,\n    permissionPoint: RolePermissions.PAGE,\n  },\n  {\n    path: \"/system/role/detail\",\n    exact: true,\n    component: RoleDetail,\n    permissionPoint: RolePermissions.PAGE,\n  },\n];\n"
  },
  {
    "path": "arius-console/src/pages/work-order.tsx",
    "content": "import * as React from \"react\";\nimport { MyApplication } from \"container/work-order/my-application\";\nimport { OrderDetail } from \"container/work-order/order-detail\";\nimport { MyApproval } from \"container/work-order/my-approval\";\nimport { TaskList } from \"container/work-order/task\";\nimport { TaskDetail } from \"container/work-order/task-detail\";\nimport { DcdrTaskList } from \"container/work-order/dcdr-detail\";\nimport { MyApplyPermissions, MyApprovalPermissions, TaskPermissions } from \"constants/permission\";\n\nexport const workOrderPageRouter = [\n  {\n    path: \"/work-order\",\n    exact: true,\n    component: MyApplication,\n    permissionPoint: MyApplyPermissions.PAGE,\n  },\n  {\n    path: \"/work-order/my-application\",\n    exact: true,\n    component: MyApplication,\n    needCache: true,\n    permissionPoint: MyApplyPermissions.PAGE,\n  },\n  {\n    path: \"/work-order/my-application/detail\",\n    exact: true,\n    component: OrderDetail,\n    permissionPoint: MyApplyPermissions.PAGE,\n  },\n  {\n    path: \"/work-order/my-approval\",\n    exact: true,\n    component: MyApproval,\n    needCache: true,\n    permissionPoint: MyApprovalPermissions.PAGE,\n  },\n  {\n    path: \"/work-order/my-approval/detail\",\n    exact: true,\n    component: OrderDetail,\n    permissionPoint: MyApprovalPermissions.PAGE,\n  },\n  {\n    path: \"/work-order/task\",\n    exact: true,\n    needCache: true,\n    component: TaskList,\n    permissionPoint: TaskPermissions.PAGE,\n  },\n  {\n    path: \"/work-order/task/detail\",\n    exact: true,\n    component: TaskDetail,\n    permissionPoint: TaskPermissions.PAGE,\n  },\n  {\n    path: \"/work-order/task/dcdrdetail\",\n    exact: true,\n    component: DcdrTaskList,\n    permissionPoint: TaskPermissions.PAGE,\n  },\n];\n"
  },
  {
    "path": "arius-console/src/reducers/app.ts",
    "content": "import { IAction } from \"interface/common\";\nimport { getCurrentProject } from \"lib/utils\";\nimport { AppState } from \"store/type\";\nimport actionTypes from \"../actions/actionTypes\";\n\nexport const initialState: AppState = {\n  appInfo: getCurrentProject,\n  projectList: [],\n};\n\nexport default (state = initialState, action: IAction) => {\n  switch (action.type) {\n    case actionTypes.SET_APP_LIST: {\n      const { projectList } = action.payload;\n      return { ...state, projectList };\n    }\n  }\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/cluster-base.ts",
    "content": "import { IAction } from \"interface/common\";\nimport { ClustrtData, INodeListObjet } from \"store/type\";\nimport actionTypes from \"../actions/actionTypes\"\n\nexport const initialState: ClustrtData = {\n  cost: 0,\n  nodeList: {} as INodeListObjet,\n  packageList: { docker: [], host: [] },\n};\n\nexport default (state = initialState, action: IAction) => {\n  switch (action.type) {\n    case actionTypes.SET_CLUSTER_COST: {\n      const { cost } = action.payload;\n      return { ...state, cost };\n    }\n    case actionTypes.SET_CLUSTER_NODE_LIST: {\n      const { nodeList } = action.payload;\n      return { ...state, nodeList };\n    }\n    case actionTypes.SET_CLUSTER_PACKEAGE: {\n      const { packageList } = action.payload;\n      return { ...state, packageList };\n    }\n  }\n\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/cluster-kanban.ts",
    "content": "import { IClusterKanBanAction } from \"interface/common\";\nimport { ClusterState } from \"store/type\";\nimport actionTypes from \"../actions/actionTypes\"\n\nconst ONE_HOUR = 1000 * 60 * 60;\nconst currentTime = new Date().getTime();\n\nexport const initialState: ClusterState = {\n  clusterName: \"\",\n  startTime: currentTime - ONE_HOUR,\n  endTime: currentTime,\n  isMoreDay: false,\n  timeRadioKey: 'oneHour',\n  isUpdate: true,\n};\n\nexport default (state = initialState, action: IClusterKanBanAction) => {\n  switch (action.type) {\n    case actionTypes.SET_CLUSTER_NAME_TIME: {\n      return { ...state, ...action.clusterForm };\n    }\n    case actionTypes.SET_CLUSTER_IS_UPDATE: {\n      return { ...state, ...action.clusterForm };\n    }\n    case actionTypes.SET_KAN_BAN: {\n      return { ...state, ...action.clusterForm };\n    }\n  }\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/create-index.ts",
    "content": "import { IUNSpecificInfo } from \"typesPath/base-types\";\nimport { IAction, IStringMap } from \"interface/common\";\nimport actionTypes from \"../actions/actionTypes\";\n\nexport const initialState: any = {\n  currentStep: 0,\n  secondChildMap: new Map(),\n  thirdChildMap: new Map(),\n  temporaryFormMap: new Map(),\n  fieldTypeMap: {} as IStringMap,\n  activeInstance: null,\n  loadingMap: {\n    list: false,\n    zoomInfo: false,\n  } as {\n    [key: string]: boolean;\n  },\n  cancelCopy: false,\n  asyncTranslog: false,\n  customerAnalysisJson: null,\n  customerAnalysisValue: \"\",\n  settingCount: 0,\n  dataCenter: null,\n};\n\nexport default (state = initialState, action: IAction) => {\n  switch (action.type) {\n    case actionTypes.SET_INDEX_CREATE_TEMPORAYFORMMAP: {\n      const { key, result } = action.payload;\n      state.temporaryFormMap.set(key, result);\n      return { ...state };\n    }\n    case actionTypes.SET_INDEX_CREATE_SECOND_CHILD_MAP: {\n      const { key, result } = action.payload;\n      state.secondChildMap.set(key, result);\n      return { ...state };\n    }\n    case actionTypes.SET_INDEX_CREATE_LOADING_MAP: {\n      const { key, result } = action.payload;\n      state.loadingMap[key] = result;\n      return { ...state };\n    }\n    case actionTypes.SET_THIRD_CHILD_MAP: {\n      const { key, result } = action.payload;\n      if (result) {\n        state.thirdChildMap.set(key, result);\n      } else {\n        state.thirdChildMap.delete(key);\n      }\n      return { ...state };\n    }\n    case actionTypes.SET_CURRENT_STEP: {\n      const { currentStep } = action.payload;\n      return { ...state, currentStep };\n    }\n    case actionTypes.SET_FIELD_TYPE_MAP: {\n      const { fieldTypeMap } = action.payload;\n      return { ...state, fieldTypeMap };\n    }\n    case actionTypes.SET_EDITOR_INSTANCE: {\n      const { activeInstance } = action.payload;\n      return { ...state, activeInstance };\n    }\n    case actionTypes.SET_CLEAR_CREATE_INDEX: {\n      return {\n        currentStep: 0,\n        secondChildMap: new Map(),\n        thirdChildMap: new Map(),\n        temporaryFormMap: new Map(),\n        fieldTypeMap: {} as IStringMap,\n        activeInstance: null,\n        loadingMap: {\n          list: false,\n          zoomInfo: false,\n        } as {\n          [key: string]: boolean;\n        },\n        cancelCopy: false,\n        asyncTranslog: false,\n        customerAnalysisJson: null,\n        customerAnalysisValue: \"\",\n      };\n    }\n    case actionTypes.SET_CREATE_INDEX: {\n      return { ...state, ...action.payload };\n    }\n  }\n\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/dashboard.ts",
    "content": "import { IDashBoardAction } from \"interface/common\";\nimport { DashboardState } from \"store/type\";\nimport actionTypes from \"../actions/actionTypes\";\n\nconst ONE_HOUR = 1000 * 60 * 60;\nconst currentTime = new Date().getTime();\n\nexport const initialState: DashboardState = {\n  startTime: currentTime - ONE_HOUR,\n  endTime: currentTime,\n  tabs: \"operation\",\n  dymanicConfigMetrics: [],\n};\n\nexport default (state = initialState, action: IDashBoardAction) => {\n  switch (action.type) {\n    case actionTypes.SET_DASHBOARD: {\n      return { ...state, ...action.payload };\n    }\n    case actionTypes.SET_DASHBOARD_DYMANIC: {\n      return { ...state, ...action.payload };\n    }\n  }\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/gateway-kanban.ts",
    "content": "import { IGatewayKanbanAction } from \"interface/common\";\nimport { GatewayState } from \"store/type\";\nimport actionTypes from \"../actions/actionTypes\"\n\nconst ONE_HOUR = 1000 * 60 * 60;\nconst currentTime = new Date().getTime();\n\nexport const initialState: GatewayState = {\n  startTime: currentTime - ONE_HOUR,\n  endTime: currentTime,\n  isMoreDay: false,\n  isUpdate: true,\n};\n\nexport default (state = initialState, action: IGatewayKanbanAction) => {\n  switch (action.type) {\n    case actionTypes.SET_GATEWAY_TIME: {\n      return { ...state, ...action.gatewayForm };\n    }\n    case actionTypes.SET_GATEWAY_IS_UPDATE: {\n      return { ...state, ...action.gatewayForm };\n    }\n  }\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/index.ts",
    "content": "import { combineReducers } from \"redux\";\nimport modal from \"./modal\";\nimport sliderMenu from \"./sliderMenu\";\nimport clusterBase from \"./cluster-base\";\nimport app from \"./app\";\nimport user from \"./user\";\nimport region from \"./region\";\nimport configInfo from \"./phy-cluster-config\";\nimport createIndex from \"./create-index\";\nimport task from \"./task\";\nimport clusterKanban from \"./cluster-kanban\";\nimport gatewayKanban from \"./gateway-kanban\";\nimport dashBoard from \"./dashboard\";\n\nexport default combineReducers({\n  modal,\n  sliderMenu,\n  clusterBase,\n  app,\n  user,\n  region,\n  configInfo,\n  createIndex,\n  task,\n  clusterKanban,\n  gatewayKanban,\n  dashBoard,\n});\n"
  },
  {
    "path": "arius-console/src/reducers/modal.ts",
    "content": "import { IAction } from \"interface/common\";\nimport { ModalState } from \"store/type\";\nimport actionTypes from \"../actions/actionTypes\";\n\nexport const initialState: ModalState = {\n  loading: false,\n  modalId: \"\",\n  drawerId: \"\",\n  params: null,\n  cb: null,\n};\n\nexport default (state = initialState, action: IAction) => {\n  switch (action.type) {\n    case actionTypes.SET_MODAL_ID: {\n      const { modalId, params, cb } = action.payload;\n      return { ...state, modalId, params, cb };\n    }\n    case actionTypes.SET_DRAWER_ID: {\n      const { drawerId, params, cb } = action.payload;\n      return { ...state, drawerId, params, cb };\n    }\n    case actionTypes.SET_LOADING: {\n      const { loading } = action.payload;\n      return { ...state, loading };\n    }\n  }\n\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/phy-cluster-config.ts",
    "content": "import { IAction } from \"interface/common\";\nimport { RegionState } from \"store/type\";\nimport actionTypes from \"../actions/actionTypes\"\n\nexport const initialState = {\n  typeNameList: [],\n  configList: [],\n  clusterRolesList: [],\n};\n\nexport default (state = initialState, action: IAction) => {\n  switch (action.type) {\n    case actionTypes.SET_PHY_CLUSTER_CONFIG: {\n      const { typeNameList } = action.payload;\n      return { ...state, typeNameList };\n    }\n    case actionTypes.SET_PHY_CLUSTER_CONFIG_LIST: {\n      const { configList } = action.payload;\n      return { ...state, configList };\n    }\n    case actionTypes.SET_PHY_CLUSTER_CONFIG_ROLES: {\n      const { clusterRolesList } = action.payload;\n      return { ...state, clusterRolesList };\n    }\n  }\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/region.ts",
    "content": "import { IAction } from \"interface/common\";\nimport { RegionState } from \"store/type\";\nimport actionTypes from \"../actions/actionTypes\"\n\nexport const initialState: RegionState = {\n  phyClusterList: [],\n  region: [],\n  racks: '',\n  racksArr: [],\n  type: \"\",\n  tableData: [],\n};\n\nexport default (state = initialState, action: IAction) => {\n  switch (action.type) {\n    case actionTypes.SET_PHY_CLUSTER_LIST: {\n      const { phyClusterList, type, tableData} = action.payload;\n      return { ...state, phyClusterList, type, tableData };\n    }\n    case actionTypes.SET_REGION_LIST: {\n      const { region } = action.payload;\n      return { ...state, region };\n    }\n    case actionTypes.SET_RACKS: {\n      const { racks } = action.payload;\n      return { ...state, racks };\n    }\n    case actionTypes.SET_RACKS_ARR: {\n      const { racksArr } = action.payload;\n      return { ...state, racksArr };\n    }\n  }\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/sliderMenu.ts",
    "content": "import { IAction } from \"interface/common\";\nimport actionTypes from \"../actions/actionTypes\"\n\nexport const initialState = {\n  sliderMenuCollapsed: false\n};\n\nexport default (state = initialState, action: IAction) => {\n  switch (action.type) {\n    case actionTypes.SET_SLIDER_MENU: {\n      const { sliderMenuCollapsed } = action.payload;\n      return { ...state, sliderMenuCollapsed };\n    }\n  }\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/task.ts",
    "content": "import { IAction } from \"interface/common\";\nimport { TaskState } from \"store/type\";\nimport actionTypes from \"../actions/actionTypes\"\n\nexport const initialState: TaskState = {\n  dcdrStepDetail: null,\n  taskBaseInfo: null,\n  menu: window.location.hash.replace('#', '') || 'base',\n  loading: false,\n};\n\nexport default (state = initialState, action: IAction) => {\n  switch (action.type) {\n    case actionTypes.SET_TASK_BASE_INFO: {\n      const { taskBaseInfo } = action.payload;\n      return { ...state, taskBaseInfo };\n    }\n    case actionTypes.SET_DCDR_STEP_DEL: {\n      const { dcdrStepDetail } = action.payload;\n      return { ...state, dcdrStepDetail };\n    }\n    case actionTypes.SET_TASK_MENU: {\n      const { menu } = action.payload;\n      return { ...state, menu };\n    }\n    case actionTypes.SET_TASK_BASE_LOADING: {\n      const { loading } = action.payload;\n      return { ...state, loading };\n    }\n  }\n\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/reducers/user.ts",
    "content": "import actionTypes from \"actions/actionTypes\";\nimport { getCookie } from \"knowdesign/lib/utils/tools\";\nimport { IAction } from \"interface/common\";\nimport { IUser, UserState } from \"store/type\";\n\nexport const initialState: UserState = {\n  getName: getCookie,\n  isAdminUser: getCookie(\"isAdminUser\") === \"yes\",\n  permissionTree: [],\n  userInfo: {} as IUser,\n};\n\nexport default (state = initialState, action: IAction) => {\n  switch (action.type) {\n    case actionTypes.SET_USER_TYPE: {\n      const { isAdminUser } = action.payload;\n      return { ...state, isAdminUser };\n    }\n    case actionTypes.SET_USER: {\n      const { userInfo } = action.payload;\n      return { ...state, userInfo };\n    }\n    case actionTypes.SET_USER_PERMISSION: {\n      const { permissionTree } = action.payload;\n      return { ...state, permissionTree };\n    }\n  }\n  return state;\n};\n"
  },
  {
    "path": "arius-console/src/store/index.ts",
    "content": "import { applyMiddleware, createStore } from \"redux\";\nimport thunk from \"redux-thunk\";\nimport reducer from \"../reducers\";\nimport { createGlobalState } from \"./../d1-packages/dantd/components/hook/create-global-state/index\";\n\nconst initialState = {};\n\nconst middleware = applyMiddleware(thunk);\n\nexport default createStore(reducer, initialState, middleware);\n\n// 切换routerTab时记录状态，用作监听\nexport const useGlobalPathStatus = createGlobalState([\"\"]);\nexport const useGlobalLoginStatus = createGlobalState(false);\nexport const useGlobalPermissionTree = createGlobalState([]);\n"
  },
  {
    "path": "arius-console/src/store/type.d.ts",
    "content": "import { IProject } from \"interface/project\";\nimport { ILabelValue } from \"typesPath/base-types\";\nimport { IVersions } from \"typesPath/cluster/physics-type\";\nimport { INode } from \"typesPath/index-types\";\nimport { IDcdrStepDetailInfo, ITaskBaseInfo } from \"typesPath/task-types\";\n\nexport interface IPermission {\n  has: boolean;\n  id: number;\n  leaf: boolean;\n  parentId: number;\n  permissionName: string;\n  childList: IPermission[];\n}\n\nexport interface IUser {\n  userName: string;\n  id: number;\n  email: string;\n  phone: string;\n}\n\ntype UserState = {\n  getName: (params: string) => any;\n  isAdminUser: boolean;\n  permissionTree: IPermission[];\n  userInfo: IUser;\n};\n\nexport interface ModalState {\n  loading: boolean;\n  modalId: string;\n  drawerId: string;\n  params: any;\n  cb?: any;\n}\n\nexport interface ClustrtData {\n  cost: number | string;\n  nodeList: INodeListObjet;\n  packageList: { docker: IVersions[]; host: IVersions[] };\n}\n\nexport interface INodeListObjet {\n  masternode: INode[];\n  clientnode: INode[];\n  datanode: INode[];\n  datanodeceph: INode[];\n}\n\ntype AppState = {\n  appInfo: () => IProject;\n  projectList: any[];\n};\n\nexport interface RegionState {\n  phyClusterList: ILabelValue[];\n  region: any[];\n  racks: string;\n  racksArr: ILabelValue[];\n  type?: string;\n  tableData?: any[];\n}\n\nexport interface TaskState {\n  dcdrStepDetail: IDcdrStepDetailInfo;\n  taskBaseInfo: ITaskBaseInfo;\n  menu: string;\n  loading: boolean;\n}\n\n// 集群看板\nexport interface ClusterState {\n  clusterName: string;\n  startTime: number;\n  endTime: number;\n  isMoreDay: boolean;\n  timeRadioKey?: string;\n  isUpdate?: boolean;\n}\n// gateway 看板\nexport interface GatewayState {\n  startTime?: number;\n  endTime?: number;\n  isMoreDay?: boolean;\n  isUpdate?: boolean;\n  timeRadioKey?: string;\n}\n// dashboard\nexport interface DashboardState {\n  startTime: number;\n  endTime: number;\n  tabs: string;\n  dymanicConfigMetrics: any[];\n}\n"
  },
  {
    "path": "arius-console/src/style-addtion.less",
    "content": "//定制组件库样式\n@primary-color: #1473ff;\n@layout-background-color: #f4f9ff;\n@bg-primary-color: #f8f9fa;\n@import \"~knowdesign/lib/query-form/style/index.less\";\n//登录页面样式补充\n.login-box {\n  .dcloud-form-item-label > label {\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    line-height: 20px;\n  }\n  .dcloud-input-affix-wrapper {\n    height: 44px;\n    background: rgba(33, 37, 41, 0.06);\n    border-radius: 10px;\n    & > input.dcloud-input {\n      background: transparent;\n    }\n  }\n  .dcloud-btn-primary {\n    border-radius: 8px;\n    font-size: 18px;\n    font-weight: 500;\n  }\n  .dcloud-input {\n    font-size: 14px;\n  }\n}\n.custom-login-style {\n  .dcloud-tooltip-inner {\n    font-size: 12px;\n    color: #303a51;\n    line-height: 20px;\n  }\n}\n//导航菜单样式补充\n.dcloud-layout-sider-children > .dcloud-menu {\n  background: transparent;\n}\n.table-layout-style {\n  padding: 0 20px;\n  background-image: linear-gradient(180deg, #f5f7fa 2%, #f5f7fa 86%);\n  border-radius: 4px;\n  height: calc(100vh - 80px);\n  overflow: auto;\n}\n.dcloud-menu-inline,\n.dcloud-menu-vertical,\n.dcloud-menu-vertical-left {\n  border-right: none;\n}\n.dcloud-menu {\n  font-size: 14px;\n  width: 100%;\n}\n.dcloud-menu-sub.dcloud-menu-inline > .dcloud-menu-item {\n  height: 32px;\n  line-height: 32px;\n  padding-left: 28px !important;\n}\n.dcloud-layout-sider-children > .dcloud-menu:not(.dcloud-menu-vertical) .dcloud-menu-item-selected {\n  background-color: @primary-color;\n  border-radius: 4px;\n}\n.dcloud-menu-sub.dcloud-menu-inline {\n  padding: 0 10px;\n}\n\n.dcloud-menu:not(.dcloud-menu-vertical) {\n  .dcloud-menu-item-selected a,\n  .dcloud-menu-item-selected a:hover {\n    color: #fff;\n  }\n}\n.dcloud-menu-sub.dcloud-menu-vertical {\n  .dcloud-menu-item-selected a,\n  .dcloud-menu-item-selected a:hover {\n    color: @primary-color;\n  }\n}\n\n.dcloud-menu-submenu,\n.dcloud-menu-submenu-inline {\n  transition: none;\n}\n.dcloud-menu-inline .dcloud-menu-item {\n  width: 100%;\n}\n.dcloud-menu-sub.dcloud-menu-inline {\n  background: transparent;\n}\n.dcloud-menu.dcloud-menu-inline-collapsed > .dcloud-menu-item,\n.dcloud-menu.dcloud-menu-inline-collapsed > .dcloud-menu-submenu > .dcloud-menu-submenu-title {\n  margin: 0 calc(50% - 16px / 2);\n  padding: 0;\n}\n.dcloud-spin-container {\n  overflow: auto;\n}\n.dcloud-menu-horizontal:not(.dcloud-menu-dark) > .dcloud-menu-item {\n  padding: 0 16px;\n}\n//列表样式补充\n.pro-table-container,\n.container-table,\n.d-table,\n.d-table-box {\n  height: 100%;\n}\n.dantd-query-form {\n  background-color: @bg-primary-color;\n  border-radius: 4px 4px 0 0;\n}\n.pro-table-container .d-table-box-query {\n  background-color: #fff;\n  border-radius: 8px 8px 0 0;\n}\n.d-table-box {\n  display: flex;\n  flex-direction: column;\n  .ant-table-wrapper {\n    flex: 1;\n    // padding: 0 20px;\n    background: #fff;\n    border-radius: 0 0 8px 8px;\n    overflow: auto;\n  }\n}\n.dcloud-menu-submenu-open.dcloud-menu-submenu-selected {\n  color: inherit;\n  & > .dcloud-menu-submenu-title {\n    font-family: PingFangSC-Medium;\n    color: rgba(0, 0, 0, 0.87);\n  }\n}\n.dcloud-menu:not(.dcloud-menu-vertical) .dcloud-menu-item-selected {\n  .d1-layout-left-menus-icon {\n    fill: #fff;\n  }\n}\n.dcloud-menu:not(.dcloud-menu-horizontal) .dcloud-menu-item-selected {\n  background-color: transparent;\n}\n.dcloud-menu-vertical {\n  .dcloud-menu-submenu-selected,\n  .dcloud-menu-item-selected {\n    .d1-layout-left-menus-icon {\n      fill: @primary-color;\n    }\n  }\n}\n.dcloud-menu-inline-collapsed-tooltip .d1-layout-left-menus-icon {\n  fill: #fff;\n}\n.dcloud-menu-submenu.dcloud-menu-submenu-popup.dcloud-menu.dcloud-menu-light.dcloud-menu-submenu-placement-rightTop {\n  width: 150px;\n}\n\n.dcloud-menu-submenu.dcloud-menu-submenu-inline.dcloud-menu-submenu-selected {\n  & > .dcloud-menu-submenu-title {\n    font-family: PingFangSC-Medium;\n    color: rgba(0, 0, 0, 0.87);\n  }\n}\n.dcloud-table-wrapper {\n  flex: auto;\n  padding: 0 16px;\n  background: #fff;\n  border-radius: 0 0 8px 8px;\n}\n//查询条件样式补充\n\n//table\n.dcloud-pagination-total-text {\n  display: none;\n}\n.ant-table .ant-table-tbody .ant-table-cell {\n  vertical-align: top;\n}\n.d-table-box-query {\n  max-height: 240px !important;\n}\n.dcloud-table .dcloud-table-cell {\n  font-size: 14px;\n}\n.dcloud-table-pagination.dcloud-pagination {\n  margin-right: 2px;\n}\n.dcloud-table-wrapper .dcloud-table-selection-column {\n  width: 1%;\n  padding: 0;\n}\n\n// Drawer 样式补充\n.dcloud-drawer {\n  .dcloud-drawer-header {\n    border-bottom: none;\n    padding: 16px 24px;\n    .dcloud-drawer-title {\n      font-family: PingFangSC-Medium;\n      font-size: 18px;\n      color: rgba(0, 0, 0, 0.84);\n      letter-spacing: 0;\n      line-height: 28px;\n      font-weight: 500;\n    }\n    .dcloud-btn {\n      height: 32px;\n      padding: 4px 16px;\n    }\n    .dcloud-space-horizontal {\n      gap: 12px !important;\n    }\n    .dcloud-divider-vertical {\n      margin-left: 4px;\n      margin-right: 32px;\n      height: 16px;\n      background: rgba(0, 0, 0, 0.12);\n    }\n    .dcloud-drawer-close {\n      margin-right: 24px;\n      font-size: 18px;\n      color: #495057;\n    }\n  }\n\n  .dcloud-drawer-body {\n    padding: 16px 24px;\n    .dcloud-table-wrapper {\n      padding: 0;\n      .dcloud-table-selection-column {\n        padding-right: 0;\n      }\n    }\n    .ant-form-item {\n      margin: 0 0 16px 0 !important;\n    }\n  }\n}\n\n// Modal 样式补充\n.dcloud-modal {\n  top: 180px;\n  .dcloud-modal-header {\n    padding: 16px 24px 8px 24px;\n    border-bottom: none;\n    .dcloud-modal-title {\n      font-size: 18px;\n    }\n  }\n\n  .dcloud-modal-body {\n    padding: 16px 24px;\n    .ant-form-item {\n      margin: 0 0 16px 0 !important;\n    }\n    .dcloud-table-wrapper {\n      padding: 0;\n    }\n    .anticon-close-circle.confirm-delete-icon {\n      margin-right: 10px;\n      font-size: 20px;\n      color: #f5483b;\n    }\n    .anticon-info-circle.confirm-icon {\n      margin-right: 10px;\n      font-size: 20px;\n      color: #0a70f5;\n    }\n  }\n\n  .dcloud-modal-footer {\n    padding: 8px 24px 16px 24px;\n    border-top: none;\n  }\n  .dcloud-btn {\n    height: 32px;\n    padding: 4px 16px;\n  }\n}\n\n// Tag 样式补充\n.dcloud-tag {\n  width: 64px;\n  height: 24px;\n  padding: 0;\n  line-height: 24px;\n  text-align: center;\n  font-size: 14px;\n}\n\n// Step 样式补充\n.dcloud-steps {\n  .dcloud-steps-item-icon {\n    width: 28px;\n    height: 28px;\n    .dcloud-steps-icon {\n      top: -2.5px;\n    }\n  }\n  .dcloud-steps-item-title {\n    height: 28px;\n    line-height: 28px;\n    font-size: 14px;\n  }\n}\n//Select样式补充\n.dantd-query-form .dcloud-select-single:not(.dcloud-select-customize-input) .dcloud-select-selector {\n  padding: 0 12px;\n}\n\n//弹窗样式补\n.dcloud-modal-content {\n  .dcloud-btn {\n    line-height: 1;\n    height: 32px;\n  }\n}\n.dcloud-modal-confirm .dcloud-modal-body {\n  padding: 32px 32px 16px;\n}\n.dcloud-modal-confirm-warning .dcloud-modal-confirm-body > .anticon,\n.dcloud-modal-confirm-confirm .dcloud-modal-confirm-body > .anticon {\n  color: #f5483b;\n  margin-right: 10px;\n}\n.dcloud-modal-confirm-body > .anticon + .dcloud-modal-confirm-title + .dcloud-modal-confirm-content {\n  margin-left: 32px;\n}\n.cluster {\n  .monitor-overview-search {\n    padding-left: 148px;\n    &-filter {\n      padding-left: 8px;\n      flex: 1 1 auto;\n      display: flex;\n      justify-content: flex-end;\n    }\n    .tree-select-node,\n    .overview-select-mode {\n      max-width: 400px;\n      flex: 1 1 auto;\n      padding-right: 8px;\n    }\n  }\n}\n.gateway {\n  padding: 0 20px;\n  .monitor-overview-search-filter {\n    padding-left: 8px;\n    flex: 1 1 auto;\n    display: flex;\n    justify-content: flex-end;\n  }\n  .tree-select-node,\n  .overview-select-mode,\n  .second-select {\n    padding-right: 8px;\n    width: 250px;\n  }\n  .monitor-overview-search {\n    margin-left: 145px;\n  }\n  .custom-ranger-picker {\n    position: absolute;\n    top: 17px;\n    right: 18px;\n  }\n}\n//kbn-sense样式补充\n.euiToolTipAnchor {\n  line-height: 16px;\n  vertical-align: top;\n}\n//SQL查询\n.CodeMirror-wrap pre.CodeMirror-line,\n.CodeMirror-wrap pre.CodeMirror-line-like {\n  font-size: 14px;\n}\n.application .ace_editor {\n  font-size: 14px;\n}\n//hash-menu\n.dashboard,\n.gateway {\n  .hash-menu .hash-menu-border {\n    margin-left: -15px;\n  }\n}\n.dcloud-row-start {\n  width: 100%;\n}\n.cluster,\n.index-detail {\n  .dcloud-menu-horizontal > .dcloud-menu-item::after,\n  .dcloud-menu-horizontal > .dcloud-menu-submenu::after {\n    left: 0;\n    right: 0;\n  }\n}\n.index-detail {\n  .hash-detail-wrapper {\n    min-height: calc(100vh - 260px);\n  }\n}\n//message\n.dcloud-message-custom-content {\n  & > .anticon {\n    vertical-align: bottom;\n  }\n}\n\n.anticon.ant-input-clear-icon {\n  color: rgba(0, 0, 0, 0.25);\n}\n\n.ant-descriptions-row > td:not(:last-child) {\n  padding-right: 36px;\n}\n"
  },
  {
    "path": "arius-console/src/styles/base.less",
    "content": "@table-prefix-cls: ~'ant-table';\n@table-background-color: #ffffff;\n@table-color: #333333;\n@table-line-fill-color: #fcfdfd;\n@table-thead-cell-bgcolor: #f7f7f7;\n\n.max-title {\n  font-family: PingFangSC-Medium;\n  font-size: 16px;\n  color: #101724;\n  line-height: 24px;\n}\n\n.middle-title {\n  font-family: PingFangSC-Medium;\n  font-size: 14px;\n  color: #101724;\n  line-height: 24px;\n}\n\n.min-title {\n  font-family: PingFangSC-Medium;\n  font-size: 12px;\n  color: #303a51;\n  line-height: 20px;\n}\n\n.text-content {\n  font-family: PingFangSC-Regular;\n  font-size: 12px;\n  color: #303a51;\n  line-height: 20px;\n}\n\n.middle-content {\n  font-family: PingFangSC-Regular;\n  font-size: 14px;\n  color: #505568;\n  line-height: 22px;\n}\n\n.table-popover-content {\n  max-width: 560px;\n  max-height: 200px;\n  overflow: scroll;\n  .ant-tag {\n    margin: 5px;\n  }\n}\n\n.process-box {\n  top: -7px;\n  position: relative;\n  // padding-right: 20px;\n  &-foot{\n    position: absolute;\n    font-size: 12px;\n    margin-top: -2px;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    width: 100%;\n    &-byte{\n      transform: scale(0.83);\n      margin-left: -4px;\n    }\n    &-per{\n      transform: scale(0.83);\n      margin-right: -4px;\n    }\n  }\n  .ant-progress-show-info .ant-progress-outer {\n    margin-right: calc(-3em - 8px);\n    padding-right: calc(3em + 8px);\n  }\n\n}\n.pro-table-container {\n  .d-table {\n    &-box {\n      &-header {\n        display: block;\n        overflow: visible;\n        padding: 16px 0 !important;\n        &-btn {\n          float: right;\n          .ant-btn {\n            padding-top: 0;\n            padding-bottom: 0;\n            border-radius: 4px;\n            font-size: 14px;\n            margin-left: 12px;\n          }\n          .ant-divider {\n            margin: 0 0 0 10px;\n          }\n        }\n        .table-header-box {\n          float: left;\n          height: 32px;\n          line-height: 32px;\n          display: flex;\n          align-items: center;\n          padding: 0;\n          &-title {\n            font-family: PingFangSC-Medium;\n            font-size: 18px;\n            color: #101724;\n            line-height: 24px;\n          }\n          &-content {\n            font-family: PingFangSC-Regular;\n            font-size: 14px;\n            color: #505568;\n            line-height: 22px;\n          }\n          .ant-btn {\n            margin-left: 0 !important;\n            margin-right: 8px;\n          }\n        }\n      }\n      &-query {\n        background: #f7f7f7;\n        border-radius: 4px;\n        overflow: unset;\n      }\n      .ant-table {\n        font-size: 14px;\n      }\n    }\n  }\n}\n\n// HashMenu 控制最小高度为一屏\n.hash-menu {\n  min-height: calc(100vh - 116px);\n}\n\n.ant-pagination {\n  // display: flow-root; // 对float进行修正\n  // text-align: right;\n  // vertical-align: middle;\n  font-size: 14px;\n\n  .ant-pagination-prev .ant-pagination-item-link,\n  .ant-pagination-next .ant-pagination-item-link {\n    line-height: normal;\n  }\n  .ant-pagination-prev .ant-pagination-item-link,\n  .ant-pagination-next .ant-pagination-item-link,\n  .ant-pagination-item {\n    border-radius: 4px;\n  }\n  .ant-pagination-total-text {\n    line-height: 32px;\n  }\n  .ant-pagination-options {\n    margin-left: 8px;\n    .ant-select {\n      font-size: 14px;\n      .ant-select-selector {\n        border-radius: 4px;\n      }\n    }\n    .ant-pagination-options-quick-jumper {\n      line-height: normal;\n      input {\n        border-radius: 4px;\n      }\n    }\n  }\n}\n\n\n\n.@{table-prefix-cls},\n.@{table-prefix-cls}-small {\n\n  \n  .@{table-prefix-cls}-thead > tr > th:not(:last-child):not(.@{table-prefix-cls}-selection-column):not(.@{table-prefix-cls}-row-expand-icon-cell):not([colspan])::before{\n    content:'' !important;\n    width: 0 !important;\n  }\n\n  .@{table-prefix-cls}-content{\n    border-radius: 4px 4px 0 0;\n  }\n\n  .@{table-prefix-cls}-cell {\n    line-height: 20px;\n    padding: 11px 16px 11px;\n    font-size: 14px;\n\n    .@{table-prefix-cls}-column-sorters {\n      display: flex;\n      flex: auto;\n      align-items: center;\n      justify-content: flex-start;\n\n      .@{table-prefix-cls}-column-title{\n        flex: initial;\n      }\n    }\n\n    .@{table-prefix-cls}-column-sorter{\n      color: #74788D;\n    }\n  }\n\n  .line_clamp_two {\n    cursor: pointer;\n\n    &>* {\n      overflow: hidden;\n      text-overflow: ellipsis;\n      display: -webkit-box;\n      -webkit-line-clamp: 2;\n      -webkit-box-orient: vertical;\n      display: -moz-box;\n      -moz-line-clamp: 2;\n      -moz-box-orient: vertical;\n      word-wrap: break-word;\n      word-break: break-all;\n      white-space: normal;\n    }\n  }\n\n  .line_clamp_one {\n    cursor: pointer;\n\n    &>* {\n      display: block;\n      overflow: hidden;\n      text-overflow: ellipsis;\n      white-space: nowrap;\n    }\n  }\n\n  .@{table-prefix-cls}-thead {\n    // &>tr:nth-child(1){\n    //   .@{table-prefix-cls}-cell:nth-child(1) {\n    //     padding-left: 24px;\n    //   }\n    // }\n\n    // .@{table-prefix-cls}-cell:nth-last-child(1) {\n    //   padding-right: 24px;\n    // }\n\n    .@{table-prefix-cls}-cell {\n      background-color:@table-thead-cell-bgcolor;\n      border-bottom: 1px solid #DCDFE6;\n      font-weight: 500;\n    }\n  }\n\n  .@{table-prefix-cls}-tbody {\n    // .@{table-prefix-cls}-cell:nth-child(1) {\n    //   padding-left: 24px;\n    // }\n\n    // .@{table-prefix-cls}-cell:nth-last-child(1) {\n    //   padding-right: 24px;\n    // }\n    \n    .@{table-prefix-cls}-cell {\n      // line-height: 20px;\n      background-color: @table-background-color;\n      color: @table-color;\n    }\n  }\n\n  // 设置默认行背景色-(隔行变色)\n  // .line-fill-color {\n  //   .@{table-prefix-cls}-cell {\n  //     background-color: @table-line-fill-color;\n  //   }\n  // }\n\n  // .@{table-prefix-cls}-cell::before {\n  //   width: 0 !important;\n  //   background-color: transparent;\n  // }\n\n  .table-small-bgcolor{\n    .@{table-prefix-cls}-cell {\n      background-color: @table-thead-cell-bgcolor !important;\n      border-bottom: 1px solid #EFF2F7;\n    }\n  }\n}\n\n.@{table-prefix-cls}-small {\n  .@{table-prefix-cls}-cell {\n    padding: 0 8px !important;\n    height: 30px !important;\n    line-height: 30px;\n    font-size: 13px !important;\n  }\n}\n\n// 鼠标滑过行背景色设置\n.@{table-prefix-cls}-cell-row-hover {\n  background-color: #F8F9FA;\n}\n\n// 纯无边框Table\n.frameless-table {\n  .@{table-prefix-cls}-cell {\n    border: none !important;\n  }\n\n  .@{table-prefix-cls}-container {\n    border: none !important;\n  }\n\n  .@{table-prefix-cls}-content {\n    &>table {\n      border: none !important;\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/src/styles/common.less",
    "content": "@import \"./base.less\";\n@import \"./sense_overrides.less\";\n\n.ecmc-layout .ant-layout > .ecmc-layout-content > .ecmc-layout-main {\n  padding: 20px;\n  margin: 0;\n  background-color: inherit;\n  overflow-y: visible;\n  overflow-x: visible;\n}\n\n.dantd-modal .ant-modal-content {\n  max-height: 9999px;\n}\n\n.dantd-modal .ant-modal-content .ant-modal-body {\n  max-height: 9999px;\n}\n\n.icon {\n  width: 1em;\n  height: 1em;\n  vertical-align: -0.15em;\n  fill: currentColor;\n  overflow: hidden;\n}\n\n.disabled-button {\n  color: rgba(0, 0, 0, 0.25);\n  background: #f5f5f5;\n  border-color: #d9d9d9;\n}\n\n.disabled-button:hover {\n  color: rgba(0, 0, 0, 0.25);\n  background: #f5f5f5;\n  border-color: #d9d9d9;\n}\n\n.ant-table-thead .ant-table-cell {\n  background: #f7f7f7 !important;\n  font-weight: 500 !important;\n  color: rgba(0, 0, 0, 0.6);\n}\n\n.ant-drawer-footer,\n.ant-modal-footer {\n  padding: 12px 24px;\n\n  .ant-btn {\n    font-size: 14px;\n    line-height: 18px;\n  }\n}\n\n.ant-table-thead tr th:first-child,\n.ant-table-tbody tr td:first-child {\n  padding-left: 20px;\n\n  &.ant-table-selection-column {\n    padding-left: 16px;\n  }\n\n  .ant-table-column-sorters {\n    padding-left: 0;\n  }\n}\n\n// .ant-table .ant-table-selection-col {\n//   width: 40px;\n// }\n\n.ant-dropdown-menu-item:hover,\n.ant-dropdown-menu-submenu-title:hover,\n.ant-select-item-option-active:not(.ant-select-item-option-disabled) {\n  background: rgba(0, 0, 0, 0.04);\n}\n\n.ant-select-item-option-selected:not(.ant-select-item-option-disabled) {\n  color: #2f81f9;\n  font-weight: 500;\n  background: #f1f7ff;\n}\n\n.ant-drawer-header,\n.ant-modal-header {\n  padding: 12px 24px;\n\n  .ant-drawer-title,\n  .ant-modal-title {\n    font-weight: 700;\n    color: #1d2330;\n  }\n}\n\n.ant-drawer-close {\n  padding: 12px 21px;\n}\n\n.ant-modal-close-x {\n  line-height: 48px;\n}\n\n.ant-page-header {\n  .ant-page-header-heading-title {\n    font-size: 16px;\n  }\n\n  .ant-page-header-content {\n    margin-top: 3px;\n\n    .info-item-wrapper label {\n      font-weight: 700;\n    }\n  }\n}\n\n.warning-container {\n  padding: 6px 24px;\n  font-size: 14px;\n  background: #fffae0;\n  color: #592d00;\n\n  .iconbiaogejieshi {\n    margin-right: 8px;\n    font-size: 16px;\n    color: #ffc300;\n    vertical-align: middle;\n  }\n}\n\n.link-button {\n  padding: 1px 7px;\n  margin-left: 10px;\n  font-size: 12px;\n  font-weight: 500;\n  color: #1473ff;\n  border: 1px solid #1473ff;\n  border-radius: 2px;\n}\n\n.ant-switch {\n  background-color: #a9afbc;\n}\n\n.ant-switch-checked {\n  background-color: #1473ff;\n}\n\n.ant-switch-disabled {\n  background-color: #eaebef;\n}\n\n.spin-name {\n  margin-left: 50%;\n  margin-top: 30%;\n}\n\n.ant-layout-content {\n  .ant-menu {\n    line-height: 36px;\n\n    .ant-menu-item-only-child {\n      font-size: 14px;\n      color: #303a51;\n      text-align: center;\n      margin: 0 40px 0 0;\n    }\n\n    .ant-menu-item.ant-menu-item-selected {\n      color: #2f81f9;\n      font-family: PingFangSC-Medium;\n    }\n  }\n}\n\n.menu-container {\n  background: #fff;\n}\n\n.ant-transfer-list-header-title {\n  font-weight: bolder;\n}\n\n.consoleContainer {\n  padding: 16px;\n}"
  },
  {
    "path": "arius-console/src/styles/custom-component.less",
    "content": ".principal-with-dchat {\n  \n  .d-chat-wrap {\n    display: inline-block;\n    vertical-align: middle;\n    margin-right: 10px;\n    white-space: nowrap;\n    text-decoration: none;\n  }\n\n  .d-chat-wrap__logo {\n    width: 16px;\n    height: 16px;\n    display: inline-block;\n    vertical-align: middle;\n    margin-right: 5px;\n  }\n\n  .d-chat-wrap__text {\n    display: inline-block;\n    vertical-align: middle;\n  }\n}\n\n.order-success {\n  line-height: 26px;\n  padding: 8px 0px;\n}\n\n.not-bind-app {\n  height: 400px;\n  width: 100%;\n  line-height: 30px;\n  text-align: center;\n  vertical-align: middle;\n  padding-top: 120px;\n\n  .icon {\n    font-size: 40px;\n  }\n}\n.dropdown-menu {\n  background-color: #fff;\n  box-shadow: 0px 0px 4px 0px #D9D9D9;\n  border-radius: 4px;\n  font-size: 13px;\n\n  &.fix-height {\n    height: 200px;\n    overflow: scroll;\n  }\n\n  li {\n    text-align: center;\n    height: 32px;\n    line-height: 32px;\n    padding: 0px 20px;\n\n    &:hover {\n      background: rgba(236, 111, 38, 0.1);\n    }\n  }\n}"
  },
  {
    "path": "arius-console/src/styles/detail.less",
    "content": ".tag-name{\n   width: 64px;\n   text-align: center;\n}\n.detail-wrapper {\n  height: calc(100% - 224px);\n  min-width: 800px;\n  background-color: white;\n  padding: 0 20px;\n  border-radius: 8px;\n\n  .editor-wrapper {\n    height: 300px;\n  }\n\n  .ant-descriptions-middle .ant-descriptions-row > td {\n    padding-bottom: 30px;\n  }\n\n  .detail-content {\n    padding: 24px;\n    height: calc(100% - 48px);\n  }\n\n  .ant-table-placeholder {\n    border-bottom: none !important;\n  }\n}\n"
  },
  {
    "path": "arius-console/src/styles/search-filter.less",
    "content": ".table-operation-panel {\n  margin-bottom: 20px;\n  font-size: 12px;\n  min-height: 70px;\n  line-height: 70px;\n  background: white;\n  border-radius: 6px;\n  padding: 0px 15px;\n\n  &.not-white {\n    border-radius: 0px;\n    background: #f3f4f5;\n  }\n\n  li {\n    display: inline-block;\n    vertical-align: middle;\n    margin-right: 15px;\n\n    .ant-select {\n      width: 150px;\n    }\n\n    .ant-input-search {\n      width: 200px;\n    }\n\n    &.right-btn-1 {\n      float: right;\n\n      Button {\n        margin-left: 10px;\n      }\n    }\n  }\n\n  li:last-child {\n    margin-right: 0px;\n  }\n}\n\n.ant-table-thead>tr>th .ant-table-filter-icon {\n  right: initial;\n}\n\n.table-wrapper {\n  padding: 10px 15px 20px 15px;\n  background: white;\n  border-radius: 6px;\n  overflow-x: scroll;\n\n  &.no-padding {\n    padding: 5px 0px 0px 0px\n  }\n  \n  .table-op-btn {\n    background: white;\n    padding: 0px 0px 10px 0px;\n    \n    Button {\n      margin-right: 10px;\n    }\n  \n    // a {\n    //   color: white\n    // }\n  \n    .reload {\n      width: 30px;\n      height: 30px;\n      line-height: 30px;\n      border: 1px solid #DBE0E4;\n      border-radius: 2px;\n      margin-right: 10px;\n    }\n  }\n\n  .ant-table-wrapper {\n    background: white;\n    border: 1px solid #DBE0E4;\n    padding: 20px 15px;\n  }\n\n  .table-inner-operation {\n    float: right;\n\n    li {\n      display: inline-block;\n      vertical-align: middle;\n\n      .ant-select {\n        width: 150px;\n      }\n\n      .ant-input-search {\n        width: 200px;\n      }\n    }\n\n    li:last-child {\n      margin-right: 0px;\n    }\n  }\n}"
  },
  {
    "path": "arius-console/src/styles/sense_overrides.less",
    "content": "#consoleRoot {\n\n  .conApp__editorContent {\n    border-bottom: 1px solid #ebedef;\n    border-right: 1px solid #ebedef;\n    border-top: 1px solid #ebedef;\n    border-radius: 4px 0px 0px 4px;\n  }\n\n  .conApp__output {\n    border-bottom: 1px solid #ebedef;\n    border-right: 1px solid #ebedef;\n    border-top: 1px solid #ebedef;\n    border-radius: 0px 4px 4px 0px;\n  }\n\n  .conApp__resizer {\n    border-bottom: 1px solid #ebedef;\n    border-top: 1px solid #ebedef;\n  }\n}\n\n.search-profiler-page {\n  .appRoot {\n    height: calc(100vh - 360px);\n    overflow-y: scroll;\n    min-height: 130px;\n  }\n\n  .euiFormRow {\n    max-width: 100%;\n  }\n\n  .euiTabs {\n    height: 32px;\n    line-height: 32px;\n    width: 204px;\n    background: rgba(116, 120, 141, 0.1);\n    border-radius: 4px;\n\n    .euiTab {\n      padding: 0px;\n      margin-right: 0px;\n      padding: 6px 9px;\n    }\n  }\n\n  .euiTab.euiTab-isSelected::after {\n    height: 0px;\n  }\n\n  .euiTab.euiTab-isSelected {\n    background: #ffffff;\n    border-radius: 4px;\n    height: 26px;\n    margin: 2px;\n    line-height: 16px;\n  }\n\n  .euiTabs:not(.euiTabs--condensed)::before {\n    height: 0px;\n  }\n\n  .prfDevTool__sense .ace_editor {\n    border-radius: 4px;\n    margin-bottom: 0px;\n    min-height: 0px;\n  }\n\n  .prfDevTool__main {\n    box-shadow: none;\n    padding: 26px 22px 0px;\n  }\n\n  .prfDevTool__profileTree__shardDetails {\n    .title {\n      font-family: PingFangSC-Medium;\n      font-size: 12px;\n      color: #303a51;\n      line-height: 22px;\n      font-weight: 500;\n    }\n\n    .spacer {\n      width: 2px;\n      height: 10px;\n      background: @primary-color;\n      display: inline-block;\n      margin-right: 3px;\n    }\n  }\n\n  .prfDevTool__profileTree__shardDetails--dim small {\n    font-family: PingFangSC-Medium;\n    font-size: 12px;\n    color: #303a51;\n    line-height: 22px;\n    font-weight: 500;\n  }\n\n  .prfDevTool__profileTree__shardDetails--dim {\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: #374053;\n    line-height: 20px;\n    font-weight: 400;\n  }\n\n  .prfDevTool__detail {\n    font-family: PingFangSC-Regular;\n    font-size: 12px;\n    font-weight: 400;\n  }\n\n  .prfDevTool__details {\n    z-index: 99;\n\n    .euiBadge--iconLeft {\n      border-radius: 4px;\n      color: #374053 !important;\n    }\n\n    .column-time {\n      background: rgba(7, 13, 56, 0.03) !important;\n    }\n  }\n\n  .prfDevTool__percentBadge__progress--time {\n    background-image: linear-gradient(\n      to left,\n      #fa8787 0%,\n      #fa8787 var(--prfDevToolProgressPercentage, auto),\n      #f7f7f9 var(--prfDevToolProgressPercentage, auto),\n      #f7f7f9 100%\n    );\n    border-radius: 4px;\n    color: #374053 !important;\n\n    &.percent-100 {\n      color: #fff !important;\n    }\n  }\n\n  .prfDevTool__percentBadge__progress--percent {\n    background-image: linear-gradient(\n      270deg,\n      #1473ff 0,\n      #1473ff var(--prfDevToolProgressPercentage, auto),\n      #f7f7f9 var(--prfDevToolProgressPercentage, auto),\n      #f7f7f9\n    );\n    border-radius: 4px;\n    color: #374053 !important;\n\n    &.percent-100 {\n      color: #1473ff !important;\n      background-color: #fff !important;\n      border: 1px solid #1473ff;\n      background-image: none;\n    }\n  }\n\n  .prfDevTool__profileTree__badge {\n    background-color: #fff !important;\n    border-radius: 4px;\n    color: rgba(0, 0, 0, 0.84) !important;\n    border: 1px solid rgba(0, 0, 0, 0.13);\n    border-radius: 4px;\n  }\n\n  .prfDevTool__profileTree__panel {\n    border-bottom: none;\n  }\n\n  .euiText--small {\n    font-family: PingFangSC-Regular;\n    font-size: 12px;\n    color: #495057;\n    line-height: 22px;\n    font-weight: 400;\n    padding: 0 4px;\n  }\n\n  .euiIcon--medium {\n    zoom: 1;\n    margin-right: 6px;\n  }\n\n  .euiPage {\n    padding: 0;\n    background: #fff;\n  }\n\n  .euiFormRow__fieldWrapper {\n    .ant-select {\n      width: calc(100% - 96px);\n    }\n  }\n\n  .euiPanel {\n    box-shadow: none;\n    border: none;\n    border-radius: 0px;\n  }\n\n  .euiPanel--paddingLarge {\n    padding: 0px;\n  }\n\n  .euiFormControlLayout {\n    height: 32px;\n    width: calc(100% - 96px);\n    display: inline-block;\n\n    .euiFieldText {\n      height: 32px;\n    }\n  }\n\n  .euiButton--primary.euiButton--fill {\n    background-color: @primary-color;\n    height: 32px;\n    line-height: 32px;\n    min-width: 80px;\n    float: right;\n\n    .euiText {\n      font-family: PingFangSC-Regular;\n      font-size: 14px;\n      color: #ffffff;\n      letter-spacing: 0;\n      line-height: 22px;\n      font-weight: 400;\n    }\n  }\n\n  .euiButton:hover:not(:disabled),\n  .euiButton:focus {\n    text-decoration: none;\n  }\n\n  .euiButton--primary:enabled:hover,\n  .euiButton--primary:enabled:focus {\n    box-shadow: none;\n    background-color: @primary-color !important;\n    border-color: @primary-color !important;\n  }\n\n  .euiFlexGroup {\n    .profile-query-editor {\n      flex-grow: 1.2;\n    }\n  }\n\n  .euiFormLabel {\n    font-family: PingFangSC-Regular;\n    font-size: 14px;\n    color: #303a51;\n    line-height: 20px;\n    font-weight: 400;\n  }\n}\n\n.euiLink.euiLink--primary {\n  color: @primary-color !important;\n}\n\n.euiLink:hover {\n  text-decoration: none !important;\n}\n\n.euiLink:focus {\n  text-decoration: none !important;\n  background: none !important;\n}\n\n.euiLink.euiLink--primary:focus {\n  outline: none !important;\n}\n.prfDevTool__page__pageBodyContentBody {\n  font-size: 14px;\n}\n"
  },
  {
    "path": "arius-console/src/styles/table-filter.less",
    "content": ".table-operation {\n  a {\n    color: @primary-color;\n  }\n\n  a + a {\n    margin-left: 10px;\n  }\n\n  span + span {\n    margin-left: 10px;\n  }\n  a + span {\n    margin-left: 10px;\n  }\n  span + a {\n    margin-left: 10px;\n  }\n}\n\n.table-header-operation {\n  .ant-btn-primary {\n    margin-right: 20px;\n  }\n}\n\n.float-content {\n  position: absolute;\n  top: 26px;\n  right: 24px;\n}\n\n.icon:hover {\n  position: relative;\n\n  .ant-checkbox-disabled {\n    &::after {\n      content: \"\";\n      color: #fff;\n      background-color: rgba(0, 0, 0, 0.65);\n      position: absolute;\n      padding: 8px 0px;\n      width: 60px;\n      border-radius: 4px;\n      top: -30px;\n      left: 1px;\n    }\n  }\n}\n"
  },
  {
    "path": "arius-console/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"*\": [\n        \"src/*\"\n      ],\n      \"typesPath/*\": [\n        \"src/@types/*\"\n      ],\n      \"store\": [\n        \"src/store\"\n      ],\n      \"interface\": [\n        \"src/interface\"\n      ],\n      \"container\": [\n        \"src/container\"\n      ]\n    },\n    \"outDir\": \"./dist/\",\n    \"sourceMap\": true,\n    \"noImplicitAny\": false,\n    \"esModuleInterop\": true,\n    \"experimentalDecorators\": true,\n    \"allowJs\": true,\n    \"moduleResolution\": \"node\",\n    \"module\": \"es2015\",\n    \"target\": \"es2015\",\n    \"downlevelIteration\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"jsx\": \"react\",\n  },\n  \"include\": [\n    \"src/**/*\"\n  ],\n  \"exclude\": [\n    \"node_modules\",\n    \"dist/*\",\n  ],\n}"
  },
  {
    "path": "arius-console/webpack.config.js",
    "content": "/* eslint-disable */\nconst path = require('path');\nconst isProd = process.env.NODE_ENV === 'production';\nconst pre_build = process.env.PRE_BUILD;\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\nconst webpack = require('webpack');\nconst merge = require('webpack-merge');\nconst pkgJson = require('./package');\nconst getWebpackCommonConfig = require('./config/d1-webpack.base');\nconst jsFileName = isProd ? '[name]-[chunkhash].js' : '[name].js';\n\nlet publicPath = '/';\n\nif (isProd) {\n\n  if (!publicPath.endsWith(\"/\")) {\n    publicPath = publicPath + \"/\";\n  }\n  publicPath = pre_build ? publicPath : `/${pkgJson.systemName}/`\n}\n\nmodule.exports = merge(getWebpackCommonConfig(), {\n  mode: isProd ? 'production' : 'development',\n  entry: {\n    [pkgJson.systemName]: ['./src/index.tsx'],\n  },\n  plugins: [\n    new webpack.DefinePlugin({\n      'process.env': {\n        NODE_ENV: JSON.stringify(process.env.NODE_ENV),\n        PRE_BUILD: JSON.stringify(process.env.PRE_BUILD),\n      },\n    }),\n    new HtmlWebpackPlugin({\n      template: './src/index.html',\n      favicon: './favicon.ico',\n    }),\n  ],\n  output: {\n    path: path.resolve(__dirname, pre_build ? `./dist` : `./pub/${pkgJson.systemName}`),\n    publicPath,\n    filename: jsFileName,\n    chunkFilename: jsFileName,\n  },\n  devtool: isProd ? 'none' : 'cheap-module-eval-source-map',\n  devServer: {\n    host: '127.0.0.1',\n    port: pkgJson.port,\n    hot: true,\n    open: false,\n    disableHostCheck: true,\n    proxy: {\n      \"/api/es/admin\": {\n        // target: \"https://api-kylin-xg02.intra.xiaojukeji.com/bigdata_commercial_es_admin_master\",\n        // target: \"http://api-kylin-xg02.intra.xiaojukeji.com/bigdata_commercial_es_admin_zh_0.3\",\n        target: \"http://116.85.7.53:8015\",\n        changeOrigin: true,\n        pathRewrite: {\n          \"^/api/es/admin\": \"/admin/api\",\n        },\n      },\n      \"/api/es/gateway\": {\n        target: \"http://10.96.75.13:18278\",\n        // target: \"http://127.0.0.1:9200\",\n        changeOrigin: true,\n        // headers: {\n        //   'Authorization': \"Basic MTphekFXaUpoeGtobzMzYWM=\",\n        //   'CLUSTER-ID': \"Zh_test2_cluster_7-6-0-1400\",\n        // },\n        pathRewrite: {\n          \"^/api/es/gateway\": \"\",\n        },\n      },\n    },\n    historyApiFallback: true,\n    headers: {\n      \"Access-Control-Allow-Origin\": \"*\",\n    },\n  },\n});"
  },
  {
    "path": "arius-gateway/README.md",
    "content": "# 1.项目背景\n\n> arius-gateway-v2, 提供了100%适配原生 ES RestClient 的接口功能，零侵入、插件化的进行了ES特性增强：查询/写入限流、权限校验、跨集群访问、DSL分析与管控。\n\n# 2.模块划分\n\n >arius-gateway-common     存放公共常量, 公用方法, 异常类, 普通java bean等。\n> \n >arius-gateway-core       提供核心方法, 主要业务逻辑实现。\n> \n>arius-gateway-remote     依赖第三方的接口。\n>   \n> arius-gateway-rest       提供rest和Tcp方式接口。\n>   \n> arius-gateway-task       执行程序定时任务。\n\n# 3.如何使用\n\n> arius-gateway-v2 作为网关层，需配合 arius-admin-v2 使用。\n> \n1. 配置\n   \n   ```java\n   配置环境文件：application-xxx.properties\n   arius.gateway.adminUrl=arius.gateway.adminUrl=http://{host}:{port}/admin/api\n   ```\n2. 打包 \n   \n   ```java\n   mvn clean package -Dmaven.test.skip=true\n   ```\n   \n3. 运行\n\n   ```java\n   java -jar arius-gateway-rest-0.0.1-SNAPSHOT.jar --spring.profiles.active=test\n   ```\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.didi</groupId>\n        <artifactId>arius-gateway-v2</artifactId>\n        <version>0.0.1-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>arius-gateway-common</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.google.code.gson</groupId>\n            <artifactId>gson</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>javax.servlet</groupId>\n            <artifactId>javax.servlet-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-io</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.dropwizard.metrics</groupId>\n            <artifactId>metrics-core</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>commons-beanutils</groupId>\n            <artifactId>commons-beanutils</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>commons-collections</groupId>\n            <artifactId>commons-collections</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-lang3</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>net.sf.ehcache</groupId>\n            <artifactId>ehcache</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>fastjson</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>javax.annotation:=</groupId>\n                    <artifactId>javax.annotation-api</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2.external</groupId>\n                    <artifactId>javax.inject</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-utils</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>osgi-resource-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.openjdk.jol</groupId>\n                    <artifactId>jol-core</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>hk2-utils</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.hk2</groupId>\n                    <artifactId>osgi-resource-locator</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jersey.bundles.repackaged</groupId>\n                    <artifactId>jersey-guava</artifactId>\n                </exclusion>\n                <exclusion>\n                    <groupId>org.glassfish.jersey.core</groupId>\n                    <artifactId>jersey-common</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.httpcomponents</groupId>\n            <artifactId>httpclient</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>commons-codec</groupId>\n            <artifactId>commons-codec</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-metrices</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.elasticsearch</groupId>\n            <artifactId>elasticsearch</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.elasticsearch.client</groupId>\n            <artifactId>elasticsearch-rest-client</artifactId>\n        </dependency>\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/consts/QueryConsts.java",
    "content": "package com.didi.arius.gateway.common.consts;\n\npublic class QueryConsts {\n\n\tprivate QueryConsts(){}\n\n\tpublic static final String HEAD_AUTHORIZATION = \"Authorization\";\n\tpublic static final String HEAD_SEARCH_ID = \"SEARCH_ID\";\n\tpublic static final String HEAD_USER = \"username\";\n\tpublic static final String HEAD_CLUSTER_ID = \"CLUSTER-ID\";\n\tpublic static final String HEAD_USERNAME = \"x-username\";\n\tpublic static final String HEAD_SSO_USERNAME = \"X-SSO-USER\";\n\tpublic static final String HEAD_CLIENT_VERSION = \"ES-Client-Version\";\n\tpublic static final String HEAD_KIBANA_VERSION = \"kbn-version\";\n\tpublic static final String NEW_KIBANA_VERSION_START = \"7\";\n\tpublic static final String COOKIE_USERNAME = \"_sso_username\";\n\tpublic static final String GET_CLUSTER_ID = \"cluster_id\";\n\n\tpublic static final String TRACE_ID = \"traceid\";\n\t\n\tpublic static final String SPAN_ID = \"cspanid\";\n\t\n\tpublic static final String TOTAL_SEARCH_ID = \"all\";\n\tpublic static final int TOTAL_APPID_ID = -1;\n\t\n\tpublic static final String HTTP_ATTR_QUERY_CONTEXT = \"queryContext\";\n\t\n\tpublic static final String DLFLAG_PREFIX = \"_arius_\";\n\tpublic static final String STAT_LOGGER = \"queryStats\";\n\tpublic static final String TRACE_LOGGER = \"traceLog\";\n\tpublic static final String AUDIT_LOGGER = \"auditLog\";\n\tpublic static final String BOOT_LOGGER = \"bootLog\";\n\t\n\tpublic static final int RETRY_COUNT = 3;\n\tpublic static final int RETRY_SLEEP_MILLIS = 100;\n\t\n\tpublic static final String DEFAULT_TRIB_CLUSTER = \"elasticsearch\";\n\t\n\tpublic static final long DEFAULT_SCROLL_MILLIS = 600000;\n\tpublic static final long DEFAULT_SCROLL_TIMEOUT = 5000;\n\t\n\tpublic static final int DEFAULT_HTTP_TIMEOUT = 30000;\n\t\n\tpublic static final String MESSAGE_FIELD = \"message\";\n\tpublic static final String TOPIC_FIELD = \"kTopic\";\n\tpublic static final String PARTITION_FIELD = \"kPartition\";\n\tpublic static final String OFFSET_FIELD = \"kOffset\";\n\tpublic static final String UNIQUE_KEY_FIELD = \"uniqueKey\";\n\t\n\tpublic static final String CHECK_MODE_BLACK = \"black\";\n\tpublic static final int QUERY_DSL_LIMIT_WAIT = 50;\n\tpublic static final int AGGS_BUCKET_MEM_UNIT = 0;\n\tpublic static final int AGGS_DEFAULT_SHARD_NUMBER = 50;\n\tpublic static final int QUERY_DSL_MODIFY_TIME_EARLY = 600000;\n\t\n\tpublic static final int DATE_HISTOGRAM_DEFAUL_RANGE = 3600000;\n\t\n\tpublic static final int MIN_APPID_NUMBER = 1;\n\tpublic static final int MIN_TEMPLATE_NUMBER = 5;\n\n\tpublic static final int SLOW_REQUEST_COST = 30000;\n\n\tpublic static final String DEFAULT_ES_VERSION = \"2.3.3\";\n\tpublic static final String ES_VERSION_2_PREFIX = \"2\";\n\tpublic static final String ES_VERSION_6_PREFIX = \"6\";\n\tpublic static final String ES_VERSION_7_PREFIX = \"7\";\n\n\tpublic static final String DETAIL_LOG_FLAG = \"detail.log.flag\";\n\t// 动态配置项，可以跳过多type索引启用映射查询的appid列表\n\tpublic static final String MAPPING_INDEXNAME_WHITE_APPIDS = \"mapping.indexname.white.appids\";\n\n\tpublic static final long DAY_MILLIS = 24 * 60 * 60 * 1000L;\n\tpublic static final long DEFALUT_INDEX_DAY = 93;\n\tpublic static final long MAX_INDEX_COUNT = 100;\n\n\tpublic static final int MAX_SOCKET_TIMEOUT = 120000;\n\n\tpublic static final String GATEWAY_GET_APP_TICKET      = \"xTc59aY72\";\n\tpublic static final String GATEWAY_GET_APP_TICKET_NAME = \"X-ARIUS-GATEWAY-TICKET\";\n\n\tpublic static final String GATEWAY_WRITE_MODE = \"write\";\n\n\tpublic static final String SEARCH_IGNORE_THROTTLED = \"ignore_throttled\";\n\n\tpublic static final String GATEWAY_GROUP = \"Normal\";\n\n\t// 动态配置项，通过gateway的索引setting设置接口设置setting时被禁止的setting项\n\tpublic static final String FORBIDDEN_SETTING_PATH = \"gateway.forbidden.settings.path\";\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/consts/RestConsts.java",
    "content": "package com.didi.arius.gateway.common.consts;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n* @author weizijun\n* @date：2016年8月26日\n* \n*/\npublic class RestConsts {\n\n\tprivate RestConsts(){}\n\n\tpublic static final String ATTR_REQUEST_PARAMS = \"requestParams\";\n\tpublic static final String SEARCH_DATE_FROM_PARAMS = \"time_from\";\n\tpublic static final String SEARCH_DATE_TO_PARAMS = \"time_to\";\n\tpublic static final String SOCKET_TIMEOUT_PARAMS = \"socket_timeout\";\n\tpublic static final String DSL_MD5_PARAMS = \"dslMd5\";\n\n\tpublic static final String GATEWAY_VERSION = \"2.5.6\";\n\n\tpublic static final String INDEX = \"index\";\n\tpublic static final String STRING_NAME = \"string\";\n\n\tpublic static final String SCROLL_SPLIT = \"!\";\n\n\tpublic static final String FIELDS = \"fields\";\n\n\tpublic static final String SCROLL = \"scroll\";\n\n\tpublic static final Set<String> DEFAULT_WRITE_ACTION = new HashSet<String>(){{\n\t\tadd(\"RestBulkAction\");\n\t\tadd(\"RestDeleteAction\");\n\t\tadd(\"RestIndexAction\");\n\t\tadd(\"RestUpdateAction\");\n\t}};\n\n\tpublic static final String NULL_ACTION = \"null\";\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/enums/AggsTypeEnum.java",
    "content": "package com.didi.arius.gateway.common.enums;\n\npublic enum AggsTypeEnum {\n\tBUCKET, METRICS;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/enums/ClusterType.java",
    "content": "package com.didi.arius.gateway.common.enums;\n\n/**\n * @deprecated (when, why, refactoring advice...)\n */\n@Deprecated\npublic enum ClusterType {\n\n    INDEX(0),\n    SOURCE(1);\n\n    int type;\n\n    private ClusterType(int type) {\n        this.type = type;\n    }\n\n    public static ClusterType integerToType(int code) {\n        for (ClusterType type : ClusterType.values()) {\n            if (type.type == code) {\n                return type;\n            }\n        }\n        return INDEX;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/enums/FlowStatus.java",
    "content": "package com.didi.arius.gateway.common.enums;\n/**\n* @author weizijun\n* @date：2016年8月22日\n* \n*/\npublic enum FlowStatus {\n\t/**\n\t * 低于下限\n\t */\n\tDOWN,\n\t/**\n\t * 位于流控值的上限和下限之间\n\t */\n\tKEEP,\n\t/**\n\t * 高于上限\n\t */\n\tUP;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/enums/FlowType.java",
    "content": "package com.didi.arius.gateway.common.enums;\n/**\n* @author weizijun\n* @date：2016年8月22日\n* \n*/\n/**\n * @deprecated (when, why, refactoring advice...)\n */\n@Deprecated\npublic enum FlowType {\n\tIN, OUT, OPS;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/enums/RunModeEnum.java",
    "content": "package com.didi.arius.gateway.common.enums;\n\npublic enum RunModeEnum {\n    READ_WRITE_SHARE(0),\n    READ_WRITE_SPLIT(1);\n    int runMode;\n\n    RunModeEnum(int runMode) {\n        this.runMode = runMode;\n    }\n\n    public int getRunMode() {\n        return runMode;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/enums/SearchType.java",
    "content": "package com.didi.arius.gateway.common.enums;\n/**\n* @author weizijun\n* @date：2016年8月18日\n* \n*/\n/**\n * @deprecated (when, why, refactoring advice...)\n */\n@Deprecated\npublic \tenum SearchType {\n\tDSL, SQL;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/enums/TemplateBlockTypeEnum.java",
    "content": "package com.didi.arius.gateway.common.enums;\n\npublic enum TemplateBlockTypeEnum {\n    READ_BLOCK_TYPE(0),\n    WRITE_WRITE_TYPE(1);\n    int blockType;\n\n    TemplateBlockTypeEnum(int blockType) {\n        this.blockType = blockType;\n    }\n\n    public int getBlockType() {\n        return blockType;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/event/ActionPostResponseEvent.java",
    "content": "package com.didi.arius.gateway.common.event;\n\nimport com.didi.arius.gateway.common.metadata.ActionContext;\n\npublic class ActionPostResponseEvent extends PostResponseEvent {\n\n    private ActionContext actionContext;\n\n    public ActionPostResponseEvent(Object source, ActionContext actionContext) {\n        super( source );\n        this.actionContext = actionContext;\n    }\n\n    public ActionContext getActionContext(){\n        return actionContext;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/event/PostResponseEvent.java",
    "content": "package com.didi.arius.gateway.common.event;\n\nimport org.springframework.context.ApplicationEvent;\n\npublic abstract class PostResponseEvent extends ApplicationEvent {\n\n    protected PostResponseEvent(Object source) {\n        super( source );\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/event/QueryPostResponseEvent.java",
    "content": "package com.didi.arius.gateway.common.event;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\n\npublic class QueryPostResponseEvent extends PostResponseEvent {\n\n    private QueryContext queryContext;\n\n    public QueryPostResponseEvent(Object source, QueryContext queryContext) {\n        super( source );\n        this.queryContext = queryContext;\n    }\n\n    public QueryContext getQueryContext(){\n        return queryContext;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/AccessForbiddenException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年8月28日\n* \n*/\npublic class AccessForbiddenException extends QueryException {\n\n    public AccessForbiddenException(String msg) {\n        super(msg);\n    }\n\n    public AccessForbiddenException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public AccessForbiddenException(StreamInput in) throws IOException{\n        super(in);\n    }\n    \n    @Override\n    public RestStatus status() {\n        return RestStatus.FORBIDDEN;\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/AggsParseException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\npublic class AggsParseException extends QueryException {\n\n    public AggsParseException(String msg) {\n        super(msg);\n    }\n\n    public AggsParseException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public AggsParseException(StreamInput in) throws IOException{\n        super(in);\n    }\n    \n    @Override\n    public RestStatus status() {\n        return RestStatus.BAD_REQUEST;\n    }\n\n}\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/ClusterNotFoundException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n * author weizijun\n * date：2019-06-26\n */\npublic class ClusterNotFoundException extends QueryException {\n    public ClusterNotFoundException(String msg) {\n        super(msg);\n    }\n\n    public ClusterNotFoundException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public ClusterNotFoundException(StreamInput in) throws IOException {\n        super(in);\n    }\n\n    @Override\n    public RestStatus status() {\n        return RestStatus.NOT_FOUND;\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/DslForbiddenException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\npublic class DslForbiddenException extends QueryException {\n\n    public DslForbiddenException(String msg) {\n        super(msg);\n    }\n\n    public DslForbiddenException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public DslForbiddenException(StreamInput in) throws IOException{\n        super(in);\n    }\n    \n    @Override\n    public RestStatus status() {\n        return RestStatus.FORBIDDEN;\n    }\n\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/DslRateLimitException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\n\nimport java.io.IOException;\n\npublic class DslRateLimitException extends QueryException {\n    public DslRateLimitException(String msg) {\n        super(msg);\n    }\n\n    public DslRateLimitException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public DslRateLimitException(StreamInput in) throws IOException{\n        super(in);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/FlowLimitException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年8月24日\n* \n*/\npublic class FlowLimitException extends QueryException {\n    public FlowLimitException(String msg) {\n        super(msg);\n    }\n\n    public FlowLimitException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public FlowLimitException(StreamInput in) throws IOException{\n        super(in);\n    }\n\n    @Override\n    public RestStatus status() {\n        return RestStatus.SERVICE_UNAVAILABLE;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/IndexDateFieldException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\n\nimport java.io.IOException;\n\npublic class IndexDateFieldException extends QueryException {\n    public IndexDateFieldException(String msg) {\n        super(msg);\n    }\n\n    public IndexDateFieldException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public IndexDateFieldException(StreamInput in) throws IOException {\n        super(in);\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/IndexNotFoundException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.ElasticsearchException;\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n * @author didi\n * @date 2022-03-23 10:35 上午\n */\npublic class IndexNotFoundException extends ElasticsearchException {\n\n    public IndexNotFoundException(String msg) {\n        super(msg);\n    }\n\n    public IndexNotFoundException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public IndexNotFoundException(StreamInput in) throws IOException {\n        super(in);\n    }\n\n    @Override\n    public RestStatus status() {\n        return RestStatus.NOT_FOUND;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/IndexNotPermittedException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年8月22日\n* \n*/\npublic class IndexNotPermittedException extends QueryException {\n    public IndexNotPermittedException(String msg) {\n        super(msg);\n    }\n\n    public IndexNotPermittedException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public IndexNotPermittedException(StreamInput in) throws IOException{\n        super(in);\n    }\n    \n    @Override\n    public RestStatus status() {\n        return RestStatus.FORBIDDEN;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/IndexRateLimitException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\npublic class IndexRateLimitException extends QueryException {\n    public IndexRateLimitException(String msg) {\n        super(msg);\n    }\n\n    public IndexRateLimitException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public IndexRateLimitException(StreamInput in) throws IOException {\n        super(in);\n    }\n\n    @Override\n    public RestStatus status() {\n        return RestStatus.SERVICE_UNAVAILABLE;\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/InvalidAppInfoException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年8月22日\n* \n*/\npublic class InvalidAppInfoException extends QueryException {\n    public InvalidAppInfoException(String msg) {\n        super(msg);\n    }\n\n    public InvalidAppInfoException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public InvalidAppInfoException(StreamInput in) throws IOException{\n        super(in);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/InvalidParameterException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年8月22日\n* \n*/\npublic class InvalidParameterException extends QueryException {\n    public InvalidParameterException(String msg) {\n        super(msg);\n    }\n\n    public InvalidParameterException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public InvalidParameterException(StreamInput in) throws IOException{\n        super(in);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/QueryDslLengthException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\n\nimport java.io.IOException;\n\npublic class QueryDslLengthException extends QueryException {\n\n    public QueryDslLengthException(String msg) {\n        super(msg);\n    }\n\n    public QueryDslLengthException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public QueryDslLengthException(StreamInput in) throws IOException{\n        super(in);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/QueryException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.ElasticsearchException;\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\npublic class QueryException extends ElasticsearchException {\n\n    public QueryException(String msg) {\n        super(msg);\n    }\n\n    public QueryException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public QueryException(StreamInput in) throws IOException{\n        super(in);\n    }\n    \n    @Override\n    public RestStatus status() {\n        return RestStatus.BAD_REQUEST;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/ResponseTooLargeException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\n\nimport java.io.IOException;\n\npublic class ResponseTooLargeException extends QueryException {\n\n    public ResponseTooLargeException(String msg) {\n        super(msg);\n    }\n\n    public ResponseTooLargeException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public ResponseTooLargeException(StreamInput in) throws IOException{\n        super(in);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/SQLNotPermittedException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年8月22日\n* \n*/\npublic class SQLNotPermittedException extends QueryException {\n    public SQLNotPermittedException(String msg) {\n        super(msg);\n    }\n\n    public SQLNotPermittedException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public SQLNotPermittedException(StreamInput in) throws IOException{\n        super(in);\n    }\n    \n    @Override\n    public RestStatus status() {\n        return RestStatus.FORBIDDEN;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/ServerBusyException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\npublic class ServerBusyException extends QueryException {\n    public ServerBusyException(String msg) {\n        super(msg);\n    }\n\n    public ServerBusyException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public ServerBusyException(StreamInput in) throws IOException{\n        super(in);\n    }\n\n    @Override\n    public RestStatus status() {\n        return RestStatus.SERVICE_UNAVAILABLE;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/ServerException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年8月22日\n* \n*/\npublic class ServerException extends QueryException {\n    public ServerException(String msg) {\n        super(msg);\n    }\n\n    public ServerException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public ServerException(StreamInput in) throws IOException{\n        super(in);\n    }\n    \n    @Override\n    public RestStatus status() {\n        return RestStatus.INTERNAL_SERVER_ERROR;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/SettingsForbiddenException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.ElasticsearchException;\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\npublic class SettingsForbiddenException extends ElasticsearchException {\n    public SettingsForbiddenException(Throwable cause) {\n        super( cause );\n    }\n\n    public SettingsForbiddenException(String msg) {\n        super(msg);\n    }\n\n    public SettingsForbiddenException(StreamInput in) throws IOException {\n        super(in);\n    }\n\n    @Override\n    public RestStatus status() {\n        return RestStatus.FORBIDDEN;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/TemplateBlockException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.ElasticsearchException;\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n * @author didi\n * @date 2021-11-11 3:25 下午\n */\npublic class TemplateBlockException extends ElasticsearchException {\n\n    public TemplateBlockException(String msg) {\n        super(msg);\n    }\n\n    public TemplateBlockException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public TemplateBlockException(StreamInput in) throws IOException {\n        super(in);\n    }\n\n    @Override\n    public RestStatus status() {\n        return RestStatus.FORBIDDEN;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/TooManyIndexException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\n\nimport java.io.IOException;\n\npublic class TooManyIndexException extends QueryException {\n    public TooManyIndexException(String msg) {\n        super(msg);\n    }\n\n    public TooManyIndexException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public TooManyIndexException(StreamInput in) throws IOException {\n        super(in);\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/UnauthorizedException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年9月6日\n* \n*/\npublic class UnauthorizedException extends QueryException {\n    public UnauthorizedException(String msg) {\n        super(msg);\n        addHeader(\"WWW-authenticate\", \"Basic realm=need the correct appid and password\");\n    }\n\n    public UnauthorizedException(String msg, Throwable cause) {\n        super(msg, cause);\n        addHeader(\"WWW-authenticate\", \"Basic realm=need the correct appid and password\");\n    }\n\n    public UnauthorizedException(StreamInput in) throws IOException{\n        super(in);\n        addHeader(\"WWW-authenticate\", \"Basic realm=need the correct appid and password\");\n    }\n    \n    @Override\n    public RestStatus status() {\n        return RestStatus.UNAUTHORIZED;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/exception/UriNotFoundException.java",
    "content": "package com.didi.arius.gateway.common.exception;\n\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年8月22日\n* \n*/\npublic class UriNotFoundException extends QueryException {\n    public UriNotFoundException(String msg) {\n        super(msg);\n    }\n\n    public UriNotFoundException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    public UriNotFoundException(StreamInput in) throws IOException{\n        super(in);\n    }\n    \n    @Override\n    public RestStatus status() {\n        return RestStatus.NOT_FOUND;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/flowcontrol/AreaFlow.java",
    "content": "package com.didi.arius.gateway.common.flowcontrol;\n\nimport com.didi.arius.gateway.common.enums.FlowStatus;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author weizijun \n * @date：2016年8月22日\n * \n */\n@Data\n@NoArgsConstructor\npublic class AreaFlow {\n\tprivate Flow in;\n\n\tprivate Flow out;\n\n\tprivate Flow ops;\n\n\tprivate FlowStatus status;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/flowcontrol/AreaFlowCache.java",
    "content": "package com.didi.arius.gateway.common.flowcontrol;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n* @author weizijun\n* @date：2016年8月23日\n* \n*/\npublic class AreaFlowCache {\n\tprivate ConcurrentMap<String, AreaFlow> areaFlowMap = new ConcurrentHashMap<>();\n\t\n\tpublic static AreaFlowCache getInstance() {\n\t\treturn instance;\n\t}\n\n\tprivate static final AreaFlowCache instance = new AreaFlowCache();\n\t\n\tpublic AreaFlow getAreaFlow(String areaId) {\n\t\treturn areaFlowMap.get(areaId);\n\t}\n\t\n\tpublic void setAreaFlow(String areaId, AreaFlow areaFlow) {\n\t\tareaFlowMap.put(areaId, areaFlow);\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/flowcontrol/Flow.java",
    "content": "package com.didi.arius.gateway.common.flowcontrol;\n\nimport com.didi.arius.gateway.common.enums.FlowStatus;\n\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n* @author weizijun\n* @date：2016年8月22日\n* \n*/\npublic class Flow {\n\t/**\n\t * 当前大小\n\t */\n\tprivate AtomicInteger curtQuantity = new AtomicInteger(0);\n\n\t/**\n\t * 每秒钟的流控值，通过后台线程计算所得\n\t */\n\tprivate AtomicInteger lastPerSecond = new AtomicInteger(0);\n\n\t/**\n\t * 上一次计算流控值的时间\n\t */\n\tprivate AtomicLong lastCalTime = new AtomicLong(0);\n\n\t/**\n\t * 上限\n\t */\n\tprivate AtomicInteger lowerBound = new AtomicInteger(0);\n\n\t/**\n\t * 下限\n\t */\n\tprivate AtomicInteger upperBound = new AtomicInteger(0);\n\n\t/**\n\t * 当前状态\n\t */\n\tprivate FlowStatus status = FlowStatus.DOWN;\n\t\n\tpublic int getCurtQuantity() {\n\t\treturn curtQuantity.get();\n\t}\n\t\n\tpublic int addCurtQuantity(int size) {\n\t\treturn this.curtQuantity.addAndGet(size);\n\t}\n\t\n\tpublic int subCurtQuantity(int size) {\n\t\treturn this.curtQuantity.addAndGet(-size);\n\t}\n\t\n\tpublic int getLastPerSecond() {\n\t\treturn lastPerSecond.get();\n\t}\n\t\n\tpublic void setLastPerSecond(int lastPerSecond) {\n\t\tthis.lastPerSecond.set(lastPerSecond);\n\t}\n\n\tpublic long getLastCalTime() {\n\t\treturn lastCalTime.get();\n\t}\n\t\n\tpublic void setLastCalTime(long lastCalTime) {\n\t\tthis.lastCalTime.set(lastCalTime);\n\t}\n\n\tpublic int getLowerBound() {\n\t\treturn lowerBound.get();\n\t}\n\n\tpublic void setLowerBound(int lowerBound) {\n\t\tthis.lowerBound.set(lowerBound);\n\t}\n\n\tpublic int getUpperBound() {\n\t\treturn upperBound.get();\n\t}\n\n\tpublic void setUpperBound(int upperBound) {\n\t\tthis.upperBound.set(upperBound);\n\t}\n\n\tpublic FlowStatus getStatus() {\n\t\treturn status;\n\t}\n\n\tpublic void setStatus(FlowStatus status) {\n\t\tthis.status = status;\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/flowcontrol/FlowController.java",
    "content": "package com.didi.arius.gateway.common.flowcontrol;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.enums.FlowStatus;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n* @author weizijun\n* @date：2016年8月22日\n* \n*/\npublic class FlowController {\n\tprivate static final ILog logger = LogFactory.getLog(FlowController.class);\n\t\n\tprivate int appid;\n\n\t/**\n\t * 计算流控的时间间隔\n\t */\n\tprivate int calIntervalSecond;\n\n\tConcurrentMap<String, AreaFlow> flowLimitMap = new ConcurrentHashMap<>();\n\t\n\tpublic FlowController(int appid, int calIntervalSecond) {\n\t\tthis.appid = appid;\n\t\tthis.calIntervalSecond = calIntervalSecond;\n\t}\n\t\n\tpublic boolean addUpFlow(Flow flow, int size) {\n\t\tif (flow.getCurtQuantity() + size < 0) {\n\t\t\tflow.setStatus(FlowStatus.UP);\n\t\t} else {\n\t\t\tint curt = flow.addCurtQuantity(size);\n\t\t\tif (curt < 0) {\n\t\t\t\tflow.subCurtQuantity(size);\n\t\t\t\tflow.setStatus(FlowStatus.UP);\n\t\t\t} else if ((curt / calIntervalSecond) >= flow.getUpperBound()) {\n\t\t\t\tflow.setStatus(FlowStatus.UP);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn flow.getStatus() == FlowStatus.DOWN;\n\t}\n\t\n\tpublic boolean addUpIn(String searchId, int in) {\n\t\tboolean isRelaxed = false;\n\t\tif (!searchId.equals(QueryConsts.TOTAL_SEARCH_ID)) {\n\t\t\tisRelaxed = addUpIn(QueryConsts.TOTAL_SEARCH_ID, in);\n\t\t}\n\t\t\n\t\tAreaFlow areaFlow = getAreaFlow(searchId);\n\t\tif (areaFlow == null) {\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tboolean limit = false;\n\t\tlimit = !addUpFlow(areaFlow.getIn(), in) || limit;\n\t\tlimit = !addUpFlow(areaFlow.getOps(), 1) || limit;\n\t\tif (limit) {\n\t\t\tareaFlow.setStatus(FlowStatus.UP);\n\t\t\tlogger.info(\"appid={} Add up request: search_id={}, in={}, status={}\",\n\t\t\t\t\tappid, searchId, in, areaFlow.getStatus());\n\t\t}\n\t\t\n\t\treturn isRelaxed && areaFlow.getStatus() == FlowStatus.DOWN;\n\t}\n\t\n\tpublic boolean addUpOut(String searchId, int out) {\n\t\tboolean isRelaxed = false;\n\t\tif (!searchId.equals(QueryConsts.TOTAL_SEARCH_ID)) {\n\t\t\tisRelaxed = addUpOut(QueryConsts.TOTAL_SEARCH_ID, out);\n\t\t}\n\t\t\n\t\tAreaFlow areaFlow = getAreaFlow(searchId);\n\t\tif (areaFlow == null) {\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\tboolean limit = false;\n\t\tlimit = !addUpFlow(areaFlow.getOut(), out) || limit;\n\t\tif (limit) {\n\t\t\tareaFlow.setStatus(FlowStatus.UP);\n\t\t\tlogger.info(\"appid={} Add up response: search_id={}, out={}, status={}\",\n\t\t\t\t\tappid, searchId, out, areaFlow.getStatus());\n\t\t}\n\t\t\n\t\treturn isRelaxed && areaFlow.getStatus() == FlowStatus.DOWN;\n\t}\n\t\n\tpublic void backgroundCalFlows() {\n\t\tfor (Map.Entry<String, AreaFlow> entry : flowLimitMap.entrySet()) {\n\t\t\tAreaFlow areaFlow = entry.getValue();\n\t\t\tFlowStatus statusIn = calCurrentFlow(areaFlow.getIn());\n\t\t\tif (statusIn != FlowStatus.DOWN) {\n\t\t\t\tlogger.info(\"Flow IN Limit: appid={}, searchId={}, status={}, value={}\", appid, entry.getKey(), statusIn, areaFlow.getIn().getLastPerSecond());\n\t\t\t}\n\t\t\t\n\t\t\tFlowStatus statusOut = calCurrentFlow(areaFlow.getOut());\n\t\t\tif (statusOut != FlowStatus.DOWN) {\n\t\t\t\tlogger.info(\"Flow OUT Limit: appid={}, searchId={}, status={}, value={}\", appid, entry.getKey(), statusOut, areaFlow.getOut().getLastPerSecond());\n\t\t\t}\n\t\t\t\n\t\t\tFlowStatus statusOps = calCurrentFlow(areaFlow.getOps());\n\t\t\tif (statusOps != FlowStatus.DOWN) {\n\t\t\t\tlogger.info(\"Flow OPS Limit: appid={}, searchId={}, status={}, value={}\", appid, entry.getKey(), statusOps, areaFlow.getOps().getLastPerSecond());\n\t\t\t}\n\t\t\t\n\t\t\tif (logger.isDebugEnabled()) {\n\t\t\t\tlogger.debug(\"Flow rate: appid={}, searchId={}, in={} {}, out={} {}, ops={} {}\",\n\t\t\t\t\t\t appid,entry.getKey(), areaFlow.getIn().getLastPerSecond(), statusIn,\n\t\t\t\t\t\tareaFlow.getOut().getLastPerSecond(), statusOut,\n\t\t\t\t\t\tareaFlow.getOps().getLastPerSecond(), statusOps);\n\t\t\t}\n\t\t\t\n\t\t\tif (statusIn == FlowStatus.UP\n\t\t\t\t\t|| statusOut == FlowStatus.UP\n\t\t\t\t\t|| statusOps == FlowStatus.UP) {\n\t\t\t\tareaFlow.setStatus(FlowStatus.UP);\n\t\t\t} else if (statusIn == FlowStatus.KEEP\n\t\t\t\t\t|| statusOut == FlowStatus.KEEP\n\t\t\t\t\t|| statusOps == FlowStatus.KEEP) {\n\t\t\t\tareaFlow.setStatus(FlowStatus.KEEP);\n\t\t\t} else {\n\t\t\t\tareaFlow.setStatus(FlowStatus.DOWN);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tprivate FlowStatus calCurrentFlow(Flow flow) {\n\t\tlong now = System.currentTimeMillis();\n\t\tint quantity = flow.getCurtQuantity();\n\t\tlong lastCalTime = flow.getLastCalTime();\n\t\tint spend = (int) (lastCalTime > 0 ? now - lastCalTime : calIntervalSecond * 1000);\n\t\tint lastPerSecond = spend <  1000.0001 ? quantity : (int) ((double) quantity / spend * 1000);\n\t\tflow.setLastPerSecond(lastPerSecond);\n\t\t\n\t\tflow.setLastCalTime(now);\n\t\t\n\t\tflow.subCurtQuantity(quantity);\n\t\t\n\t\tif (lastPerSecond > flow.getUpperBound()) {\n\t\t\tflow.setStatus(FlowStatus.UP);\n\t\t} else if (flow.getStatus() == FlowStatus.UP && lastPerSecond > flow.getLowerBound()) {\n\t\t\tflow.setStatus(FlowStatus.KEEP);\n\t\t} else {\n\t\t\tflow.setStatus(FlowStatus.DOWN);\n\t\t}\n\t\t\n\t\treturn flow.getStatus();\n\t}\n\t\n\tprivate AreaFlow getAreaFlow(String searchId) {\n\t\tif (!flowLimitMap.containsKey(searchId)) {\n\t\t\tsynchronized (flowLimitMap) {\n\t\t\t\tif (!flowLimitMap.containsKey(searchId)) {\n\t\t\t\t\tString areaId = formAreaId(appid, searchId);\n\t\t\t\t\tAreaFlow areaFlow = AreaFlowCache.getInstance().getAreaFlow(areaId);\n\t\t\t\t\tif (areaFlow == null) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tflowLimitMap.put(searchId, areaFlow);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn flowLimitMap.get(searchId);\n\t}\n\t\n\tpublic static String formAreaId(int appid, String searchId) {\n\t\tStringBuilder buffer = new StringBuilder(String.valueOf(appid));\n\t\tbuffer.append(\"_\");\n\t\tbuffer.append(searchId);\n\t\treturn buffer.toString();\n\t}\n\t\n\tpublic int getAppid() {\n\t\treturn appid;\n\t}\n\t\n\tpublic Map<String, AreaFlow> getFlowLimitMap() {\n\t\treturn flowLimitMap;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/flowcontrol/FlowLimit.java",
    "content": "package com.didi.arius.gateway.common.flowcontrol;\n\nimport com.didi.arius.gateway.common.enums.FlowStatus;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport java.util.Random;\n\n/**\n* @author weizijun\n* @date：2016年8月25日\n* \n*/\npublic class FlowLimit {\n\tprivate ILog log = LogFactory.getLog(FlowLimit.class);\n\n\t/**\n\t * //阀值，如果flowRandom产生的随机数超过该阀值，则判断为over flow，否则即判断down\n\t */\n\tprivate int threshold;\n\n\t/**\n\t * //阀值，如果flowRandom产生的随机数超过该阀值，则判断为over flow，否则即判断down\n\t */\n\tprivate static final double UP_FACTOR = 0.3;\n\n\t/**\n\t * //threshold down减少因子\n\t */\n\tprivate static final double DOWN_FACTOR = 0.5;\n\n\tprivate static final int MAX_THRESHOLD = 2000;\n\tprivate static final Random flowRandom = new Random();\n\n\tprivate String areaId;\n\n\tpublic FlowLimit(String areaId) {\n\t\tthreshold = 0;\n\t\tthis.areaId = areaId;\n\t}\n\t\n\tpublic int getThreshold() {\n\t\treturn threshold;\n\t}\n\t\n\tpublic boolean isOverflow() {\n\t\t\n\t\tif (threshold == 0)\n\t\t\treturn false;\n\t\telse if (threshold >= MAX_THRESHOLD) {\n\t\t\tlog.warn(\"Threshold {} larger than max {}\", threshold, MAX_THRESHOLD);\n\t\t\treturn true;\n\t\t}\n\t\t \n\t\telse\n\t\t{\n\t\t\t//这么做的好处是一旦被判定为over flow，不会限制所有的该namespace的request\n\t\t\t//而是以一定的概率限制request\n\t\t\treturn flowRandom.nextInt(MAX_THRESHOLD) < threshold;\n\t\t}\n\t\t \n\t}\n\t\n\tpublic void limitLevelTouch(FlowStatus status) {\n\t\tswitch (status) {\n\t\tcase KEEP :\n\t\t\tlimitLevelKeep();\n\t\t\tbreak;\n\t\tcase UP :\n\t\t\tlimitLevelUp();\n\t\t\tbreak;\n\t\tcase DOWN :\n\t\t\tlimitLevelDown();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tpublic void limitLevelUp() {\n\t\t//逐步提高被判断为over flow的概率\n\t\tif (threshold < MAX_THRESHOLD - 10) {\n\t\t\tthreshold = (int)(threshold + UP_FACTOR * (MAX_THRESHOLD - threshold));\n\t\t}\n\t\t\n\t\tlog.warn(\"flow limit up areaId {} curt {}\", areaId, threshold);\n\t}\n\t\n\tpublic void limitLevelKeep() {\n\t\t// Do nothing\n\t}\n\t\n\tpublic void limitLevelDown() {\n\t\tif (threshold == 0) {\n\t\t\treturn ;\n\t\t}\n\t\t\n\t\t//这样做的好处是一旦前期被限流，不会因为一个down而导致全被解流，它是一个逐步解流的过程\n\t\t//一旦threshold阀值低于50，则全解流\n\t\tthreshold = (int)(threshold - DOWN_FACTOR * threshold);\n\t\tif (threshold < 50) {\n\t\t\tthreshold = 0;\n\t\t}\n\t\t\n\t\tlog.warn(\"flow limit down areaId {} curt {}\", areaId, threshold);\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/ActionContext.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.elasticsearch.transport.TransportChannel;\nimport org.elasticsearch.transport.TransportRequest;\n\n/**\n * @author weizijun\n * @date：2016年9月20日\n * 记录tcp请求的上下文信息\n */\n@Data\n@NoArgsConstructor\npublic class ActionContext extends BaseContext {\n    /**\n     * tcp request\n     */\n    private TransportRequest request;\n\n    /**\n     * tcp channal\n     */\n    private TransportChannel channel;\n\n    /**\n     * 请求接口名称\n     */\n    private String actionName;\n\n    /**\n     * 请求内容长度\n     */\n    private int requestLength;\n\n    /**\n     * 响应内容长度\n     */\n    private int responseLength;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/AggsAnalyzerContext.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * aggs请求的上下文类\n */\n@Data\n@NoArgsConstructor\npublic class AggsAnalyzerContext {\n\n\t/**\n\t * aggs的层数\n\t */\n\tprivate int maxLevel;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/AggsBukcetInfo.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.enums.AggsTypeEnum;\nimport lombok.Data;\n\n/**\n * 聚合查询bucket信息\n */\n@Data\npublic class AggsBukcetInfo {\n\n\t/**\n\t * bucket的数量\n\t */\n\tprivate int bucketNumber;\n\n\t/**\n\t * bucket作为最后一层的bucket数量\n\t */\n\tprivate int lastBucketNumber;\n\n\t/**\n\t * bucket使用的内存数量\n\t */\n\tprivate long memUsed;\n\n\t/**\n\t * 是否是最后一层\n\t */\n\tprivate boolean isLastBucket;\n\n\t/**\n\t * aggs类型\n\t */\n\tprivate AggsTypeEnum bucketType;\n\t\n\tpublic AggsBukcetInfo() {\n\t\tisLastBucket = true;\n\t\tbucketType = AggsTypeEnum.BUCKET;\n\t}\n\t\n\tpublic static AggsBukcetInfo createSingleBucket() {\n\t\tAggsBukcetInfo aggsBukcetInfo = new AggsBukcetInfo();\n\t\taggsBukcetInfo.setBucketNumber(1);\n\t\taggsBukcetInfo.setLastBucketNumber(1);\n\t\taggsBukcetInfo.setMemUsed(QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\taggsBukcetInfo.setLastBucket(true);\n\t\taggsBukcetInfo.setBucketType(AggsTypeEnum.BUCKET);\n\t\t\n\t\treturn aggsBukcetInfo;\n\t}\n\t\n\tpublic static AggsBukcetInfo createSingleMetrics() {\n\t\tAggsBukcetInfo aggsBukcetInfo = new AggsBukcetInfo();\n\t\taggsBukcetInfo.setBucketNumber(1);\n\t\taggsBukcetInfo.setLastBucketNumber(1);\n\t\taggsBukcetInfo.setMemUsed(QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\taggsBukcetInfo.setLastBucket(true);\n\t\taggsBukcetInfo.setBucketType(AggsTypeEnum.METRICS);\n\t\t\n\t\treturn aggsBukcetInfo;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"bucketNumber=\" + bucketNumber + \"||lastBucketNumber=\" + lastBucketNumber + \"||memUsed=\" + memUsed;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/AggsPath.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n@Data\n@NoArgsConstructor\npublic class AggsPath {\n\n    private String aggsName;\n\n    private String aggsTypedKey;\n\n    private Map<String, AggsPath> items = new HashMap<>();\n\n    public void addItems(String key, AggsPath item) {\n        items.put(key, item);\n    }\n\n    public AggsPath getItem(String key) {\n        return items.get(key);\n    }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/AppDetail.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n * @author weizijun\n * @date：2016年8月18日\n */\n@Data\n@NoArgsConstructor\npublic class AppDetail {\n    private int id;\n    private Integer projectId;\n\n    /**\n     * appid授权的索引列表\n     */\n    private List<String> indexExp;\n\n    /**\n     * appid授权写权限的索引列表\n     */\n    private List<String> windexExp;\n\n    /**\n     * appid校验码\n     */\n    private String verifyCode;\n\n    /**\n     * appid配置的白名单列表\n     */\n    private List<String> ip;\n\n    /**\n     * appid对应的集群名称\n     */\n    private String cluster;\n\n    /**\n     * appid限流值\n     */\n    private int queryThreshold;\n\n    /**\n     * 是否生效DSL分析查询限流值\n     */\n    private boolean dslAnalyzeEnable;\n\n    /**\n     * 是否生效聚合查询分析\n     */\n    private boolean aggrAnalyzeEnable;\n\n    /**\n     * 是否生效记录响应结果的索引列表\n     */\n    private boolean analyzeResponseEnable;\n\n    private RequestType searchType;\n\n    private Integer isRoot;\n\n    public enum RequestType {\n        CLUSTER(0),\n        INDEX(1),\n        ORIGIN_CLUSTER(2);\n\n        int type;\n\n        public int getType() {\n            return type;\n        }\n\n        private RequestType(int type) {\n            this.type = type;\n        }\n\n        public static RequestType integerToType(int code) {\n            for (RequestType type : RequestType.values()) {\n                if (type.type == code) {\n                    return type;\n                }\n            }\n            return CLUSTER;\n        }\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/AuthRequest.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n* @author weizijun\n* @date：2016年8月18日\n* \n*/\n@Data\n@NoArgsConstructor\npublic class AuthRequest {\n\tprivate int appid;\n\tprivate String appsecret;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/BaseContext.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport lombok.AccessLevel;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestRequest.Method;\n\nimport java.io.Serializable;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.concurrent.Semaphore;\n\n/**\n * @author weizijun\n * @date：2016年9月20日\n * 上下文信息基类\n */\n@Data\n@NoArgsConstructor\npublic abstract class BaseContext implements Serializable {\n    /**\n     * 上下文请求id\n     */\n    private String requestId;\n\n    /**\n     * http请求的方法\n     */\n    private Method method;\n\n    /**\n     * Deprecated\n     * 一个查询模板对应的searchId\n     */\n    private String searchId;\n\n    /**\n     * 用户从header中传递的集群名称\n     */\n    private String clusterId;\n\n    /**\n     * 用户在header中传递的用户名\n     */\n    private String user;\n\n    /**\n     * url请求的请求参数,问好之后的内容\n     */\n    private String queryString;\n\n    /**\n     * http请求的消息体\n     */\n    private String postBody;\n\n    /**\n     * 请求客户端ip\n     */\n    private String remoteAddr;\n\n    /**\n     * 认证信息\n     */\n    private String authentication;\n\n    /**\n     * appid\n     */\n    private int appid;\n\n    /**\n     * appid对应的详细信息\n     */\n    private AppDetail appDetail;\n\n    /**\n     * 请求时刻的时间戳\n     */\n    private long requestTime;\n\n    /**\n     * 响应时刻的时间戳\n     */\n    private long responseTime;\n\n    /**\n     * 请求整体耗时\n     */\n    @Setter(AccessLevel.NONE)\n    private long costTime;\n\n    /**\n     * 用户传递的traceid\n     */\n    private String traceid;\n\n    /**\n     * 用户传递的spanid\n     */\n    private String spanid;\n\n    /**\n     * 查询对应的dsl模板\n     */\n    private String dslTemplateKey;\n\n    /**\n     * 控制并发的信号量\n     */\n    private Semaphore semaphore;\n\n    /**\n     * 用作索引存储分离获取，记录请求访问的fields信息\n     */\n    private FetchFields fetchFields;\n\n    /**\n     * 是否要记录详细log\n     *\n     * 非写入的Action会记录log\n     * 如果admin配置了开启，则所有请求都会记录日志\n     */\n    private boolean detailLog;\n\n    /**\n     * 是否需要使用typedKeys功能\n     */\n    private boolean typedKeys;\n\n    /**\n     * 请求的索引模板信息\n     */\n    private IndexTemplate indexTemplate;\n\n    /**\n     * 请求ES集群名称\n     */\n    private String clusterName;\n\n    /**\n     * 本次查询的type名称\n     */\n    private String typeNames;\n    /**\n     * 慢查询阈值时间\n     */\n    private long requestSlowlogThresholdMills;\n    /**\n     * httpResponse最大长度参考\n     */\n    private int maxHttpResponseLength;\n\n    /**\n     * 日志上下文\n     */\n    private JoinLogContext joinLogContext;\n\n    /**\n     * 查询模式\n     */\n    private Integer searchType;\n    /**\n     * 项目id\n     */\n    private Integer projectId;\n\n    public void setAppDetail(AppDetail appDetail) {\n        this.appDetail = appDetail;\n        this.searchType = appDetail.getSearchType().type;\n        this.appid = appDetail.getId();\n        this.projectId=appDetail.getProjectId();\n    }\n\n\n    public void setResponseTime(long responseTime) {\n        this.responseTime = responseTime;\n        this.costTime = this.responseTime - this.requestTime;\n    }\n\n    /**\n     * 从应用配置的集群名称，在集群模式下有效，在索引模式下访问的集群名称需要根据主索引所在集群\n     *\n     * @return\n     */\n    public String getCluster() {\n        if (appDetail != null && appDetail.getCluster() != null) {\n            return appDetail.getCluster();\n        } else {\n            return QueryConsts.DEFAULT_TRIB_CLUSTER;\n        }\n    }\n\n    public String getTypeNames() {\n        return typeNames;\n    }\n\n    public void setTypeNames(String typeNames) {\n        this.typeNames = typeNames;\n    }\n\n    public void setTypeNames(String[] typeNames) {\n        if (Objects.nonNull(typeNames)) {\n            this.typeNames = StringUtils.join(typeNames, \",\");\n        }\n    }\n\n    public void setTypeNames(Set<String> typeNames) {\n        if (Objects.nonNull(typeNames)) {\n            this.typeNames = StringUtils.join(typeNames, \",\");\n        }\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/DSLTemplate.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport com.google.common.util.concurrent.RateLimiter;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class DSLTemplate {\n\t/**\n\t * dsl模板限流类\n\t */\n\tprivate RateLimiter rateLimiter = null;\n\n\t/**\n\t * dsl模板总的限流值\n\t */\n\tprivate double totalQueryLimit;\n\n\t/**\n\t * 当前节点的dsl模板限流值\n\t */\n\tprivate double queryLimit;\n\n\t/**\n\t * 是否禁止查询\n\t */\n\tprivate boolean queryForbidden;\n\n\t/**\n\t * dsl模板es查询开销\n\t */\n\tprivate double esCostAvg;\n\n\t/**\n\t * dsl模板平均命中数量\n\t */\n\tprivate double totalHitsAvg;\n\n\t/**\n\t * dsl模板查询平均total_shards数\n\t */\n\tprivate double totalShardsAvg;\n\t\n\tpublic DSLTemplate(double totalQueryLimit, double queryLimit, boolean queryForbidden) {\n\t\tthis.totalQueryLimit = totalQueryLimit;\n\t\tthis.queryLimit = queryLimit;\n\t\tthis.queryForbidden = queryForbidden;\n\t\trateLimiter = RateLimiter.create(queryLimit);\n\t}\n\n\tpublic void updateRateLimiter(double queryLimit) {\n\t\trateLimiter.setRate(queryLimit);\n\t}\n\t\n\tpublic String toString() {\n\t\treturn \"queryForbidden=\" + queryForbidden + \"||queryLimit=\" + queryLimit + \"||qps=\" + rateLimiter.getRate();\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/ESCluster.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.elasticsearch.client.Client;\n\nimport java.util.Set;\n\n\n/**\n* @author weizijun\n* @date：2016年10月31日\n* 集群信息\n*/\n@Data\n@NoArgsConstructor\npublic class ESCluster {\n\t/**\n\t * 集群名称\n\t */\n\tprivate String cluster;\n\n\t/**\n\t * 读请求tcp地址\n\t */\n\tprivate String readAddress;\n\n\t/**\n\t * http请求地址\n\t */\n\tprivate String httpAddress;\n\n\t/**\n\t * httpWriteAddress\n\t */\n\tprivate String httpWriteAddress;\n\n\t/**\n\t * tcp client\n\t */\n\tprivate Client client;\n\n\t/**\n\t * http 读client\n\t */\n\tprivate ESClient esClient;\n\n\t/**\n\t * http 写client\n\t */\n\tprivate ESClient esWriteClient;\n\n\t/**\n\t * 集群类型，INDEX or TRIB\n\t */\n\tprivate Type type;\n\n\t/**\n\t * 数据中心\n\t */\n\tprivate String dataCenter;\n\n\t/**\n\t * es集群版本号\n\t */\n\tprivate String esVersion;\n\n\t/**\n\t * 集群认证信息\n\t */\n\tprivate String password;\n\n\t/**\n\t * 读写模式\n\t */\n\tprivate int runMode;\n\n\t/**\n\t * 读写分离，指定得action需要用写的action\n\t */\n\tprivate Set<String> writeAction;\n\n\tpublic enum Type {\n\t\tINDEX(0),\n\t\tSOURCE(1);\n\t\t\n\t\tint clusterType;\n\t\t\n\t\tprivate Type(int clusterType) {\n\t\t\tthis.clusterType = clusterType;\n\t\t}\n\n\t\tpublic static Type integerToType(int code) {\n\t\t\tfor (Type type : Type.values()) {\n\t\t\t\tif (type.clusterType == code) {\n\t\t\t\t\treturn type;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn INDEX;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/FetchFields.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.elasticsearch.search.fetch.source.FetchSourceContext;\n\n/**\n* @author weizijun\n* @date：2017年2月28日\n* \n*/\n@Data\n@NoArgsConstructor\npublic class FetchFields {\n\t/**\n\t * _source信息\n\t */\n\tprivate FetchSourceContext fetchSourceContext;\n\n\t/**\n\t * fileds信息\n\t */\n\tprivate String[] fields;\n\n\t/**\n\t * 是否包含message字段\n\t */\n\tprivate boolean hasMessageField;\n\t\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/FieldInfo.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class FieldInfo {\n\t/**\n\t * 字段类型\n\t */\n\tprivate String type;\n\n\t/**\n\t * 字段基数\n\t */\n\tprivate int cardinality;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/FlowThreshold.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n* @author weizijun\n* @date：2016年8月23日\n* \n*/\n@Data\n@NoArgsConstructor\npublic class FlowThreshold {\n\n\t/**\n\t * 30MB/s\n\t */\n\tprivate static final int SEARCHID_FLOW_LIMIT_IN_UPPER = 30 * 1024 * 1024;\n\t/**\n\t * 15MB/s\n\t */\n\tprivate static final int SEARCHID_FLOW_LIMIT_IN_LOWER = 15 * 1024 * 1024;\n\t/**\n\t * 100MB/s\n\t */\n\tprivate static final int SEARCHID_FLOW_LIMIT_OUT_UPPER = 100 * 1024 * 1024;\n\t/**\n\t * 80MB/s\n\t */\n\tprivate static final int SEARCHID_FLOW_LIMIT_OUT_LOWER = 80 * 1024 * 1024;\n\t\n\t/**\n\t * 触发ops限流的值\n\t */\n\tint opsUpper;\n\n\t/**\n\t * 解除ops限流的值\n\t */\n\tint opsLower;\n\n\t/**\n\t * 触发request流量限流的值\n\t */\n\tint inUpper = SEARCHID_FLOW_LIMIT_IN_UPPER;\n\n\t/**\n\t * 解除request流量限流的值\n\t */\n\tint inLower = SEARCHID_FLOW_LIMIT_IN_LOWER;\n\n\t/**\n\t * 触发response流量限流的值\n\t */\n\tint outUpper = SEARCHID_FLOW_LIMIT_OUT_UPPER;\n\n\t/**\n\t * 解除response流量限流的值\n\t */\n\tint outLower = SEARCHID_FLOW_LIMIT_OUT_LOWER;\n\t\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/IndexTemplate.java",
    "content": "\npackage com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\npublic class IndexTemplate {\n\n    /**\n     * 逻辑模板ID\n     */\n    private Integer id;\n\n    /**\n     * 模板名称\n     */\n    private String name;\n\n    /**\n     * 时间字段\n     */\n    private String dateField;\n\n    /**\n     * 时间格式\n     */\n    private String dateFormat;\n\n    /**\n     * 过期天数，-1为不过期\n     */\n    private long expireTime;\n\n    /**\n     * 索引表达式\n     */\n    private String expression;\n\n    /**\n     * 是否用默认路由\n     */\n    private Boolean isDefaultRouting;\n\n    /**\n     * 索引模板版本号\n     */\n    private int version;\n\n    /**\n     * 索引主从类型\n     */\n    private DeployStatus deployStatus;\n\n    /**\n     * 别名列表\n     */\n    private List<String> aliases;\n\n    /**\n     * 是否禁读\n     */\n    private Boolean blockRead;\n\n    /**\n     * 是否禁写\n     */\n    private Boolean blockWrite;\n\n    /**\n     * master模板信息\n     */\n    private TemplateClusterInfo masterInfo;\n\n    /**\n     * slave模板信息\n     */\n    private List<TemplateClusterInfo> slaveInfos;\n\n    private boolean internal = false;\n\n    private String ingestPipeline;\n\n    public enum DeployStatus {\n        MASTER_AND_SLAVE(1),\n        NONE(2),\n        MASTER_ONLY(3);\n\n        int type;\n\n        private DeployStatus(int type) {\n            this.type = type;\n        }\n\n        public static DeployStatus integerToStatus(int code) {\n            for (DeployStatus status : DeployStatus.values()) {\n                if (status.type == code) {\n                    return status;\n                }\n            }\n            return MASTER_AND_SLAVE;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/JoinLogContext.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metrics.log.DslMetricHelper;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport lombok.Data;\nimport org.elasticsearch.rest.RestRequest;\n\nimport java.util.Set;\n\nimport static com.didi.arius.gateway.elasticsearch.client.utils.LogUtils.KIBANA_LOG;\n\n@Data\npublic class JoinLogContext {\n    private Boolean queryRequest = true;\n    private String idc;\n    private String exceptionName;\n    private String stack;\n    private int appid;\n    private int projectId;\n    private String ariusType;\n    private String traceid;\n    private String requestId;\n    private AppDetail.RequestType requestType;\n    private RestRequest.Method method;\n    private String group;\n    private String gatewayNode;\n    private String clusterId;\n    private String user;\n    private String xUserName;\n    private String clientVersion;\n    private String clientNode;\n    private String uri;\n    private String queryString;\n    private String remoteAddr;\n    private int dslLen;\n    private String dsl;\n    private Set<String> dslTag;\n    private int responseLen;\n    private int status;\n    private String scrollId;\n    private long esCost;\n    private int totalShards;\n    private int failedShards;\n    private long totalHits;\n    private Boolean isTimedOut;\n    private String sourceIndexNames;\n    private String destIndexName;\n    private String sourceTemplateName;\n    private String destTemplateName;\n    private String dslTemplate;\n    private String searchType;\n    private String dslType;\n    private String dslTemplateMd5;\n    private String selectFields;\n    private String whereFields;\n    private String groupByFields;\n    private String sortByFields;\n    private int aggsLevel;\n    private String index;\n    private String indices;\n    private String typeName;\n    private String clusterName;\n    private int logicId;\n    private long beforeCost;\n    private long paramCost;\n    private long indexTemplateCost;\n    private long getClientCost;\n    private long preProcessCost;\n    private long searchCost;\n    private long totalCost;\n    private long internalCost;\n    private long timeStamp;\n    private long sinkTime;\n\n    public JoinLogContext() {\n        this.gatewayNode = Convert.getHostName();\n    }\n\n    @Override\n    public String toString() {\n        if (uri != null && (uri.startsWith(\"/.\"))) {\n            return KIBANA_LOG;\n        }\n        String res = JSON.toJSONString(this);\n        DslMetricHelper.putDslLog(res);\n        return res;\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/MappingIndexNameWhiteAppIds.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport com.google.common.collect.Sets;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Objects;\nimport java.util.Set;\n\n/**\n *\n * @desc 可以跳过多type索引启用映射查询的appid列表\n */\n@Data\n@NoArgsConstructor\npublic class MappingIndexNameWhiteAppIds {\n\n    /**\n     * appid列表\n     */\n    private Set<Integer> appids = Sets.newHashSet();\n\n    /**\n     * 该appid是否为白名单\n     *\n     * @param appid\n     * @return\n     */\n    public boolean isWhiteAppid(int appid){\n        return this.appids.contains(appid);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        MappingIndexNameWhiteAppIds that = (MappingIndexNameWhiteAppIds) o;\n        return Objects.equals(appids, that.appids);\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(appids);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/MetaVersion.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class MetaVersion {\n\t/**\n\t * 大基数字段的version\n\t */\n\tprivate String largeFieldVersion = \"-1\"; \n\t\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/QueryContext.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestResponse;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\npublic class QueryContext extends BaseContext {\n    /**\n     * http request\n     */\n    private RestRequest request;\n\n    /**\n     * http channel\n     */\n    private RestChannel channel;\n\n    /**\n     * http response\n     */\n    private RestResponse response;\n\n    /**\n     * 本次查询的索引列表\n     */\n    private List<String> indices;\n\n    /**\n     * 用户名\n     */\n    private String xUserName;\n\n    /**\n     * rest请求的名称\n     */\n    private String restName;\n\n    /**\n     * gateway请求的cluster\n     */\n    private ESClient client;\n\n    /**\n     * 请求的client版本号\n     */\n    private String clientVersion;\n\n    /**\n     * 是否来自于kibana\n     */\n    private boolean isFromKibana;\n\n    /**\n     * 是否来着于新版本\n     */\n    private boolean isNewKibana;\n\n    /**\n     * 请求ES前的时间点\n     */\n    private long preQueryEsTime;\n\n    public String getUri() {\n        return request.rawPath();\n    }\n\n\n    public void addIndex(String index) {\n        this.indices.add(index);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/RateLimitDetail.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class RateLimitDetail {\n\tprivate int appid;\n\n\t/**\n\t * dsl md5值\n\t */\n\tprivate String dslMd5;\n\n\t/**\n\t * 限流值\n\t */\n\tprivate double queryLimit;\n\n\t/**\n\t * 是否禁止\n\t */\n\tprivate boolean queryForbidden;\n\n\t/**\n\t * es查询开销\n\t */\n\tprivate double esCostAvg;\n\n\t/**\n\t * 查询命中数\n\t */\n\tprivate double totalHitsAvg;\n\n\t/**\n\t * 查询totalShards\n\t */\n\tprivate double totalShardsAvg;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/RateLimitStat.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class RateLimitStat {\n\t/**\n\t * dsl模板数量\n\t */\n\tprivate Integer dslCount = 0;\n\n\t/**\n\t * 禁止的dsl模板数量\n\t */\n\tprivate Integer dslForbiddenCount = 0;\n\n\t/**\n\t * 新产生的dsl模板数量\n\t */\n\tprivate Integer newDslCount = 0;\n\n\t/**\n\t * 新产生的禁止的dsl模板数量\n\t */\n\tprivate Integer newDslForbiddenCount = 0;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/TemplateAlias.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\npublic class TemplateAlias {\n\n    private Integer logicId;\n\n    private String  name;\n\n    public Integer getLogicId() {\n        return logicId;\n    }\n\n    public void setLogicId(Integer logicId) {\n        this.logicId = logicId;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/TemplateClusterInfo.java",
    "content": "\npackage com.didi.arius.gateway.common.metadata;\n\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\nimport java.util.Set;\n\n@Data\n@NoArgsConstructor\npublic class TemplateClusterInfo {\n\n    /**\n     * 允许访问的appid列表\n     */\n    private Set<Integer> accessApps;\n\n    /**\n     * 索引模板对应的集群名称\n     */\n    private String cluster;\n\n    /**\n     * 索引模板对应的topic名称\n     */\n    private String topic;\n\n    /**\n     * 用于索引多type改造   是否启用索引名称映射 0 禁用 1 启用\n     */\n    private Boolean mappingIndexNameEnable;\n\n    /**\n     * 多type索引type名称到单type索引模板名称的映射\n     */\n    private Map<String/*typeName*/,String/*templateName*/> typeIndexMapping;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/TemplateInfo.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n@Data\n@NoArgsConstructor\npublic class TemplateInfo {\n\t/**\n\t * 是否需要message\n\t */\n\tprivate boolean needSource;\n\n\t/**\n\t * 索引模板版本号\n\t */\n\tprivate int version = 0;\n\n\t/**\n\t * 索引模板mapping列表\n\t */\n\tprivate Map<String, FieldInfo> mappings = new HashMap<>();\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metadata/WrapESGetResponse.java",
    "content": "package com.didi.arius.gateway.common.metadata;\n\n\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESGetResponse;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class WrapESGetResponse {\n    private ESGetResponse esGetResponse;\n\n    private ResultType resultType;\n\n    public enum ResultType {\n        ALL,\n        SOURCE,\n        HEAD\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metrics/ActionMetric.java",
    "content": "package com.didi.arius.gateway.common.metrics;\n\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n* @author weizijun\n* @date：2016年8月28日\n* \n*/\npublic class ActionMetric {\n\tprivate String actionName;\n\n\tpublic ActionMetric(String actionName) {\n\t\tthis.actionName = actionName;\n\t}\n\t\n\tprivate ConcurrentMap<Integer, StatusMetric> appMetrisMap = new ConcurrentHashMap<>();\n\t\n\tpublic void incr(int appid, RestStatus restStatus, long cost) {\n\t\tStatusMetric statusMetric = appMetrisMap.get(appid);\n\t\tif (statusMetric == null) {\n\t\t\tsynchronized (appMetrisMap) {\n\t\t\t\tstatusMetric = new StatusMetric();\n\t\t\t\tappMetrisMap.putIfAbsent(appid, statusMetric);\n\t\t\t}\n\t\t}\n\t\t\n\t\tstatusMetric.incr(restStatus, cost);\n\t}\n\n\tpublic String getActionName() {\n\t\treturn actionName;\n\t}\n\n\tpublic ConcurrentMap<Integer, StatusMetric> getAppMetrisMap() {\n\t\treturn appMetrisMap;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metrics/AppMetric.java",
    "content": "package com.didi.arius.gateway.common.metrics;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n* @author weizijun\n* @date：2016年8月28日\n* \n*/\npublic class AppMetric {\n\tprivate int appid;\n\t\n\tpublic AppMetric(int appid) {\n\t\tthis.appid = appid;\n\t}\n\t\n\tprivate ConcurrentMap<String, SearchMetric> searchsMetricMap = new ConcurrentHashMap<>();\n\t\n\tpublic void incr(String searchId, String actionName, RestStatus restStatus, long cost) {\n\t\tif (!searchId.equals(QueryConsts.TOTAL_SEARCH_ID)) {\n\t\t\tincr(QueryConsts.TOTAL_SEARCH_ID, actionName, restStatus, cost);\n\t\t}\n\t\t\n\t\tSearchMetric searchMetric = searchsMetricMap.get(searchId);\n\t\tif (searchMetric == null) {\n\t\t\tsynchronized (searchsMetricMap) {\n\t\t\t\tsearchMetric = new SearchMetric(searchId);\n\t\t\t\tsearchsMetricMap.putIfAbsent(searchId, searchMetric);\n\t\t\t}\n\t\t}\n\t\t\n\t\tsearchMetric.incr(actionName, restStatus, cost);\n\t}\n\n\tpublic int getAppid() {\n\t\treturn appid;\n\t}\n\n\tpublic ConcurrentMap<String, SearchMetric> getSearchsMetricMap() {\n\t\treturn searchsMetricMap;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metrics/IndexMetrics.java",
    "content": "package com.didi.arius.gateway.common.metrics;\n\nimport com.didi.arius.gateway.common.utils.MetricUtil;\nimport com.didiglobal.knowframework.metrics.MetricsBuilder;\nimport com.didiglobal.knowframework.metrics.MetricsSource;\nimport com.didiglobal.knowframework.metrics.lib.MetricMutablePeriodGaugeLong;\nimport com.didiglobal.knowframework.metrics.lib.MetricMutableStat;\nimport com.didiglobal.knowframework.metrics.lib.MetricsRegistry;\n\n/**\n * author weizijun\n * date：2019-08-28\n */\npublic class IndexMetrics implements MetricsSource {\n    private MetricsRegistry metricsRegistry;\n\n    private static final String INDEX_COUNT_NAME = \"index.count\";\n    private static final String INDEX_COST_NAME = \"index.cost\";\n    private static final String INDEX_REQUEST_AVG_LENGTH_NAME = \"index.request.avg.length\";\n    private static final String INDEX_RESPONSE_AVG_LENGTH_NAME = \"index.response.avg.length\";\n\n    private static final String INDEX_REQUEST_LENGTH_NAME = \"index.request.length\";\n    private static final String INDEX_RESPONSE_LENGTH_NAME = \"index.response.length\";\n    private static final String COUNT_NAME = \"] count\";\n\n    private MetricMutablePeriodGaugeLong countMetric;\n\n    private MetricMutableStat costMetric;\n\n    private MetricMutableStat requestAvgLengthMetric;\n    private MetricMutableStat responseAvgLengthMetric;\n\n    private MetricMutablePeriodGaugeLong requestLengthMetric;\n    private MetricMutablePeriodGaugeLong responseLengthMetric;\n\n    public IndexMetrics(String index, String operation) {\n        super();\n        String name = \"index_\" + index + \"_\" + operation;\n        metricsRegistry = new MetricsRegistry(\"index\");\n        metricsRegistry.tag(\"template\", \"\", index);\n        metricsRegistry.tag(\"operation\", \"\", operation);\n\n        countMetric = metricsRegistry.newPeriodGauge(INDEX_COUNT_NAME, \"[\"\n                + name + COUNT_NAME, 0L);\n\n        costMetric = metricsRegistry.newStat(INDEX_COST_NAME,\n                \"[\"\n                        + name + \"] cost\", \"ops\", \"time\", true);\n\n        requestAvgLengthMetric = metricsRegistry.newStat(INDEX_REQUEST_AVG_LENGTH_NAME,\n                \"[\" + name + \"] request length\", \"ops\", \"length\", true);\n\n        responseAvgLengthMetric = metricsRegistry.newStat(INDEX_RESPONSE_AVG_LENGTH_NAME,\n                \"[\" + name + \"] response length\", \"ops\", \"length\", true);\n\n        requestLengthMetric = metricsRegistry.newPeriodGauge(INDEX_REQUEST_LENGTH_NAME, \"[\"\n                + name + COUNT_NAME, 0L);\n\n        responseLengthMetric = metricsRegistry.newPeriodGauge(INDEX_RESPONSE_LENGTH_NAME, \"[\"\n                + name + COUNT_NAME, 0L);\n\n        MetricUtil.register(\"gateway_\"+name, \"arius-gateway index metrics\", this);\n    }\n\n    @Override\n    public void getMetrics(MetricsBuilder builder, boolean all) {\n        metricsRegistry.snapshot(builder.addRecord(metricsRegistry.name()),\n                true);\n    }\n\n    public void incrCost(long cost) {\n        countMetric.incr();\n        costMetric.add(cost);\n    }\n\n    public void incrReqeustLength(long length) {\n        requestLengthMetric.incr(length);\n        requestAvgLengthMetric.add(length);\n    }\n\n    public void incrResponseLength(long length) {\n        responseLengthMetric.incr(length);\n        responseAvgLengthMetric.add(length);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metrics/LoggerMetric.java",
    "content": "package com.didi.arius.gateway.common.metrics;\n\nimport com.alibaba.fastjson.JSONObject;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.metrics.Metric;\nimport com.didiglobal.knowframework.metrics.MetricsRecord;\nimport com.didiglobal.knowframework.metrics.MetricsTag;\nimport com.didiglobal.knowframework.metrics.sink.mq.AbstractMetricSink;\n\npublic class LoggerMetric extends AbstractMetricSink {\n\tprotected static final ILog logger = LogFactory.getLog(\"metrics\");\n\n\t@Override\n\tpublic void putMetrics(MetricsRecord record) {\n\t\tIterable<Metric> metrics = record.metrics();\n\t\tif (null == metrics || !metrics.iterator().hasNext()) {\n\t\t\treturn;\n\t\t}\n\n\t\tJSONObject message = new JSONObject();\n\t\tmessage.put(\"timestamp\", record.timestamp());\n\t\tfor (MetricsTag loopTag : record.tags()) {\n\t\t\tmessage.put(loopTag.name().replace('.', '_'), loopTag.value());\n\t\t}\n\n\t\tmessage.put(\"type\", record.name());\n\n\t\t//append all the metrics with one record\n\t\tfor (Metric loopMetric : record.metrics()) {\n\t\t\tmessage.put(loopMetric.name().replace('.', '_'), loopMetric.value());\n\t\t}\n\n\t\tlogger.info(message.toJSONString());\n\t}\n\n\t@Override\n\tpublic void sendMetrics(String content) {\n\t\t// pass\n\t}\n\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metrics/QueryMetrics.java",
    "content": "package com.didi.arius.gateway.common.metrics;\n\nimport com.didi.arius.gateway.common.utils.MetricUtil;\nimport com.didiglobal.knowframework.metrics.MetricsBuilder;\nimport com.didiglobal.knowframework.metrics.MetricsSource;\nimport com.didiglobal.knowframework.metrics.lib.MetricMutablePeriodGaugeLong;\nimport com.didiglobal.knowframework.metrics.lib.MetricMutableStat;\nimport com.didiglobal.knowframework.metrics.lib.MetricsRegistry;\n\npublic class QueryMetrics implements MetricsSource {\n\tprivate MetricsRegistry metricsRegistry;\n\t\n\tprivate static final String APPID_COUNT_NAME = \"query.count\";\t\n\tprivate static final String APPID_COST_NAME = \"query.cost\";\t\n\t\n\tprivate static final String APPID_SLOWLOG_COUNT_NAME = \"slowlog.count\";\n\tprivate static final String APPID_SLOWLOG_COST_NAME = \"slowlog.cost\";\n\t\n\tprivate static final String APPID_QUERY_REQUEST_LENGTH_NAME = \"query.request.length\";\n\tprivate static final String APPID_QUERY_RESPONSE_LENGTH_NAME = \"query.response.length\";\n\tprivate static final String APPID_QUERY_TOOK_NAME = \"query.tookInMillis\";\n\tprivate static final String APPID_QUERY_HITS_NAME = \"query.totalHits\";\n\tprivate static final String APPID_QUERY_TOTAL_SHARDS_NAME = \"query.totalShards\";\n\tprivate static final String APPID_QUERY_FAILED_SHARDS_NAME = \"query.failedShards\";\n\t\n\tprivate static final String APPID_AGGS_COUNT_NAME = \"query.aggs.count\";\n\tprivate static final String APPID_NAME = \"appid [\";\n\tprivate static final String COUNT_NAME = \"count\";\n\t\n\t\n\tprivate MetricMutablePeriodGaugeLong countMetric;\n\t\n\tprivate MetricMutableStat costMetric;\n\t\n\tprivate MetricMutablePeriodGaugeLong slowlogCountMetric;\n\t\n\tprivate MetricMutableStat slowlogCostMetric;\n\t\n\tprivate MetricMutableStat requestLengthMetric;\n\tprivate MetricMutableStat responseLengthMetric;\n\tprivate MetricMutableStat tookInMillisMetric;\n\tprivate MetricMutableStat totalHitsMetric;\n\tprivate MetricMutableStat totalShardsMetric;\n\tprivate MetricMutableStat failedShardsMetric;\n\t\n\tprivate MetricMutablePeriodGaugeLong aggsCountMetric;\n\n\tpublic QueryMetrics(int appid) {\n\t\tsuper();\n\t\tmetricsRegistry = new MetricsRegistry(\"query\");\n\t\tmetricsRegistry.tag(\"appid\", \"\", String.valueOf(appid));\n\t\t\n\t\tcountMetric = metricsRegistry.newPeriodGauge(APPID_COUNT_NAME, APPID_NAME\n\t\t\t\t+ appid + \"] query count\", 0L);\n\t\t\n\t\tcostMetric = metricsRegistry.newStat(APPID_COST_NAME,\n\t\t\t\tAPPID_NAME\n\t\t\t\t+ appid + \"] query cost\", \"ops\", \"time\", true);\t\t\n\t\t\n\t\tslowlogCountMetric = metricsRegistry.newPeriodGauge(APPID_SLOWLOG_COUNT_NAME, APPID_NAME\n\t\t\t\t+ appid + \"] slowlog count\", 0L);\n\t\t\n\t\tslowlogCostMetric = metricsRegistry.newStat(APPID_SLOWLOG_COST_NAME,\n\t\t\t\tAPPID_NAME\n\t\t\t\t+ appid + \"] slowlog cost\", \"ops\", \"time\", true);\n\t\t\n\t\trequestLengthMetric = metricsRegistry.newStat(APPID_QUERY_REQUEST_LENGTH_NAME,\n\t\t\t\tAPPID_NAME + appid + \"] request length\", \"ops\", \"length\");\n\t\t\n\t\tresponseLengthMetric = metricsRegistry.newStat(APPID_QUERY_RESPONSE_LENGTH_NAME,\n\t\t\t\tAPPID_NAME + appid + \"] response length\", \"ops\", \"length\");\n\t\t\n\t\ttookInMillisMetric = metricsRegistry.newStat(APPID_QUERY_TOOK_NAME,\n\t\t\t\tAPPID_NAME + appid + \"] tookInMillis\", \"ops\", \"millis\");\n\t\t\n\t\ttotalHitsMetric = metricsRegistry.newStat(APPID_QUERY_HITS_NAME,\n\t\t\t\tAPPID_NAME + appid + \"] totalHits\", \"ops\", COUNT_NAME);\n\t\t\n\t\ttotalShardsMetric = metricsRegistry.newStat(APPID_QUERY_TOTAL_SHARDS_NAME,\n\t\t\t\tAPPID_NAME + appid + \"] totalShards\", \"ops\", COUNT_NAME);\n\t\t\n\t\tfailedShardsMetric = metricsRegistry.newStat(APPID_QUERY_FAILED_SHARDS_NAME,\n\t\t\t\tAPPID_NAME + appid + \"] failedShards\", \"ops\", COUNT_NAME);\n\t\t\n\t\taggsCountMetric = metricsRegistry.newPeriodGauge(APPID_AGGS_COUNT_NAME, APPID_NAME\n\t\t\t\t+ appid + \"] query count\", 0L);\n\t\t\n\t\tMetricUtil.register(\"gateway_\"+appid, \"arius-gateway metrics\", this);\n\t}\n\t\n\t@Override\n\tpublic void getMetrics(MetricsBuilder builder, boolean all) {\n\t\tmetricsRegistry.snapshot(builder.addRecord(metricsRegistry.name()),\n\t\t\t\ttrue);\n\t}\n\t\n\tpublic void incrCost(long cost) {\n\t\tcountMetric.incr();\n\t\tcostMetric.add(cost);\n\t}\n\t\n\tpublic void incrSlowlogCost(long cost) {\n\t\tslowlogCountMetric.incr();\n\t\tslowlogCostMetric.add(cost);\n\t}\n\t\n\tpublic void incrReqeustLength(long length) {\n\t\trequestLengthMetric.add(length);\n\t}\n\t\n\tpublic void incrResponseLength(long length) {\n\t\tresponseLengthMetric.add(length);\n\t}\n\t\n\tpublic void incrSearchResponseMetrics(long tookInMillis, long totalHits, int totalShards, int failedShards) {\n\t\ttookInMillisMetric.add(tookInMillis);\n\t\ttotalHitsMetric.add(totalHits);\n\t\ttotalShardsMetric.add(totalShards);\n\t\tfailedShardsMetric.add(failedShards);\n\t}\n\t\n\tpublic void incrAggs() {\n\t\taggsCountMetric.incr();\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metrics/SearchMetric.java",
    "content": "package com.didi.arius.gateway.common.metrics;\n\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n* @author weizijun\n* @date：2016年8月28日\n* \n*/\npublic class SearchMetric {\n\tprivate String searchId;\n\t\n\tpublic SearchMetric(String searchId) {\n\t\tthis.searchId = searchId;\n\t}\n\t\n\tprivate ConcurrentMap<String, StatusMetric> actionMetricMap = new ConcurrentHashMap<>();\n\t\n\tpublic void incr(String actionName, RestStatus restStatus, long cost) {\n\t\tStatusMetric statusMetric = actionMetricMap.get(actionName);\n\t\tif (statusMetric == null) {\n\t\t\tsynchronized (actionMetricMap) {\n\t\t\t\tstatusMetric = new StatusMetric();\n\t\t\t\tactionMetricMap.putIfAbsent(actionName, statusMetric);\n\t\t\t}\n\t\t}\n\t\t\n\t\tstatusMetric.incr(restStatus, cost);\n\t}\n\n\tpublic String getSearchId() {\n\t\treturn searchId;\n\t}\n\n\tpublic ConcurrentMap<String, StatusMetric> getActionMetricMap() {\n\t\treturn actionMetricMap;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metrics/StatusMetric.java",
    "content": "package com.didi.arius.gateway.common.metrics;\n\nimport org.elasticsearch.common.metrics.MeanMetric;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n* @author weizijun\n* @date：2016年8月28日\n* \n*/\npublic class StatusMetric {\n\tprivate ConcurrentMap<RestStatus, MeanMetric> statusMetricMap = new ConcurrentHashMap<>();\n\n\tpublic void incr(RestStatus restStatus, long cost) {\n\t\tMeanMetric meanMetric = statusMetricMap.get(restStatus);\n\t\tif (meanMetric == null) {\n\t\t\tsynchronized (statusMetricMap) {\n\t\t\t\tmeanMetric = new MeanMetric();\n\t\t\t\tstatusMetricMap.putIfAbsent(restStatus, meanMetric);\n\t\t\t}\n\t\t}\n\t\t\n\t\tmeanMetric.inc(cost);\n\t}\n\n\tpublic ConcurrentMap<RestStatus, MeanMetric> getStatusMetricMap() {\n\t\treturn statusMetricMap;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metrics/log/DslLogEntity.java",
    "content": "package com.didi.arius.gateway.common.metrics.log;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author didi\n * @date 2021-09-16 10:46 下午\n */\n@Data\n@NoArgsConstructor\npublic class DslLogEntity {\n    private int dslLen;\n    private int responseLen;\n    private long beforeCost;\n    private long esCost;\n    private long totalCost;\n    private int successfulShards;\n    private int totalShards;\n    private int failedShards;\n    private long totalHits;\n    private int appid;\n    private int projectId;\n    private String dslTemplate;\n    private String dslTemplateMd5;\n    private String appidDslTemplateMd5;\n    private String projectIdDslTemplateMd5;\n    private long timeStamp;\n    private String dsl;\n    private String indices;\n    private String indiceSample;\n    private String requestType;\n    private String searchType;\n    private String dslType;\n    private boolean isFromUserConsole;\n    private String version;\n    private String dslLevel;\n    private String dslTag;\n    private long searchCount = 1;\n    private String ariusType;\n    private String gatewayNode;\n    private boolean queryRequest;\n\n    //平均值\n    private double dslLenAvg;\n    private double responseLenAvg;\n    private double beforeCostAvg;\n    private double esCostAvg;\n    private double totalCostAvg;\n    private double successfulShardsAvg;\n    private double totalShardsAvg;\n    private double failedShardsAvg;\n    private double totalHitsAvg;\n\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/metrics/log/DslMetricHelper.java",
    "content": "package com.didi.arius.gateway.common.metrics.log;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport java.util.Map;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.locks.ReentrantLock;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.observability.Observability;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.util.concurrent.ConcurrentCollections;\n\n/**\n * @author didi\n * @date 2021-09-16 10:44 下午\n */\npublic class DslMetricHelper {\n\n    private DslMetricHelper() {\n    }\n\n    private static final ConcurrentMap<String, KeyLock> map = ConcurrentCollections.newConcurrentMapWithAggressiveConcurrency();\n\n    protected static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n\n    //这个限制是个大概值，map大小在指定值左右值默认1000\n    private static int dslMapSize;\n    private static int threadSize;\n    private static int queueSize;\n\n    private static final String ERROR = \"error\";\n\n    private static Map<String, DslLogEntity> dslLogMap = new ConcurrentHashMap<>();\n    private static ExecutorService es;\n\n    public static void init(int dslMapSize, int threadSize, int queueSize) {\n        DslMetricHelper.dslMapSize = dslMapSize;\n        DslMetricHelper.threadSize = threadSize;\n        DslMetricHelper.queueSize = queueSize;\n        es = newFixedThreadPool();\n    }\n\n    public static void putDslLog(String logString) {\n        DslLogEntity dslLogEntity = JSON.parseObject(logString, DslLogEntity.class);\n        if (!filter(dslLogEntity)) {\n            es.submit(() -> {\n                String key = String.format(\"%d_%s\", dslLogEntity.getProjectId(), dslLogEntity.getDslTemplateMd5());\n                dslLogEntity.setProjectIdDslTemplateMd5(key);\n\n                //这里由于涉及到累加所以得加锁，但是全局加锁会导致性能低，所以这里采用对单个key加锁，不同key互不影响\n                try {\n                    KeyLock lock;\n                    while (true) {\n                        KeyLock perNodeLock = map.get(key);\n                        if (perNodeLock == null) {\n                            KeyLock newLock = new KeyLock(false);\n                            newLock.lock();\n                            KeyLock keyLock = map.putIfAbsent(key, newLock);\n                            if (keyLock == null) {\n                                lock = newLock;\n                                break;\n                            }\n                        } else {\n                            assert perNodeLock != null;\n                            int i = perNodeLock.count.get();\n                            if (i > 0 && perNodeLock.count.compareAndSet(i, i + 1)) {\n                                perNodeLock.lock();\n                                lock = perNodeLock;\n                                break;\n                            }\n                        }\n                    }\n\n                    DslLogEntity value = dslLogMap.get(key);\n                    if (null == value) {\n                        value = dslLogEntity;\n                        dslLogMap.put(key, value);\n                    } else {\n                        calculateTotal(dslLogEntity, value);\n                    }\n\n                    //释放锁\n                    int decrementAndGet = lock.count.decrementAndGet();\n                    lock.unlock();\n                    if (decrementAndGet == 0) {\n                        map.remove(key, lock);\n                    }\n                } catch (Exception e) {\n                    bootLogger.warn(\"deal dsl log error\", e);\n                }\n            });\n\n        }\n    }\n\n    private static boolean filter(DslLogEntity dslLogEntity) {\n        //空模板过滤\n        if (Strings.isEmpty(dslLogEntity.getDslTemplateMd5()) ||\n                Strings.isEmpty(dslLogEntity.getDslTemplate())) {\n            return true;\n        }\n\n        if (!dslLogEntity.isQueryRequest()) {\n            return true;\n        }\n\n        //error日志过滤\n        if (!Strings.isEmpty(dslLogEntity.getAriusType()) && dslLogEntity.getAriusType().equals(ERROR)) {\n            return true;\n        }\n\n        if (!dslLogMap.containsKey(String.format(\"%d_%s\",\n                dslLogEntity.getProjectId(), dslLogEntity.getDslTemplateMd5())) &&\n                dslLogMap.size() >= dslMapSize) {\n            return true;\n        }\n\n        return false;\n    }\n\n\n    private static ExecutorService newFixedThreadPool() {\n        return Observability.wrap(new ThreadPoolExecutor(threadSize, threadSize, 0L, TimeUnit.MILLISECONDS,\n                new ArrayBlockingQueue<>(queueSize), (runnable, threadPoolExecutor) ->\n                //拒绝了就直接丢弃\n                bootLogger.warn(\"deal log busy so discard log\")));\n    }\n\n    public static void resetMap() {\n        dslLogMap = new ConcurrentHashMap<>();\n    }\n\n    public static Map<String, DslLogEntity> getDslLogMap() {\n        return dslLogMap;\n    }\n\n    private static void calculateTotal(DslLogEntity dslLogEntity, DslLogEntity value) {\n        value.setSearchCount(value.getSearchCount() + dslLogEntity.getSearchCount());\n        value.setDslLen(value.getDslLen() + dslLogEntity.getDslLen());\n        value.setResponseLen(value.getResponseLen() + dslLogEntity.getResponseLen());\n        value.setBeforeCost(value.getBeforeCost() + dslLogEntity.getBeforeCost());\n        value.setEsCost(value.getEsCost() + dslLogEntity.getEsCost());\n        value.setTotalCost(value.getTotalCost() + dslLogEntity.getTotalCost());\n        value.setTotalShards(value.getTotalShards() + dslLogEntity.getTotalShards());\n        value.setTotalHits(value.getTotalHits() + dslLogEntity.getTotalHits());\n        value.setFailedShards(value.getFailedShards() + value.getFailedShards());\n    }\n\n    private static final class KeyLock extends ReentrantLock {\n        KeyLock(boolean fair) {\n            super(fair);\n        }\n\n        private final AtomicInteger count = new AtomicInteger(1);\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/utils/AppUtil.java",
    "content": "package com.didi.arius.gateway.common.utils;\n\nimport com.didi.arius.gateway.common.metadata.AppDetail;\n\npublic class AppUtil {\n\n    private AppUtil(){}\n\n    public static boolean isAdminAppid(AppDetail appDetail) {\n        return (appDetail != null) && appDetail.getIsRoot() == 1;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/utils/CommonUtil.java",
    "content": "package com.didi.arius.gateway.common.utils;\n\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.util.List;\n\npublic class CommonUtil {\n\n    private CommonUtil(){}\n\n    public static boolean isIndexType(QueryContext queryContext) {\n        boolean res = false;\n        if (!queryContext.isFromKibana() && queryContext.getAppDetail().getSearchType() == AppDetail.RequestType.INDEX) {\n            res = true;\n        }\n        return res;\n    }\n\n    public static boolean isIndexType(QueryContext queryContext, List<String> indices) {\n        boolean res = false;\n        if (!isSearchKibana(queryContext.getUri(), indices) && queryContext.getAppDetail().getSearchType() == AppDetail.RequestType.INDEX) {\n            res = true;\n        }\n        return res;\n    }\n\n    public static boolean isSearchKibana(String uri, List<String> indices) {\n        if (uri != null && (uri.startsWith(\"/.\"))) {\n            return true;\n        } else if (indices != null && !indices.isEmpty()) {\n            for (String index : indices) {\n                if (index.startsWith(\".\")) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public static RestStatus fromCode(int code){\n       for(RestStatus restStatus : RestStatus.values()){\n           if(code == restStatus.getStatus()){\n               return restStatus;\n           }\n       }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/utils/Convert.java",
    "content": "package com.didi.arius.gateway.common.utils;\n\n\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.net.InetAddress;\nimport java.net.InetSocketAddress;\nimport java.net.UnknownHostException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.regex.Pattern;\n\nimport javax.servlet.http.HttpServletRequest;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.action.search.SearchRequest;\nimport org.elasticsearch.common.Base64;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.search.fetch.source.FetchSourceContext;\nimport com.didi.arius.gateway.common.metadata.AuthRequest;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchRequest;\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport com.google.gson.JsonPrimitive;\n\n/**\n* @author weizijun\n* @date：2016年9月6日\n* \n*/\npublic class Convert {\n\n\tprivate Convert(){}\n\n\tprotected static final ILog logger = LogFactory.getLog(Convert.class);\n\tprivate static String pattern = \".*\\\\d\\\\d-*\\\\d\\\\d\";\n\tprivate static Pattern r = Pattern.compile(pattern);\n\tprivate static final String BASIC = \"Basic \";\n\tprivate static final String UN_KNOW = \"unknown\";\n\t\n\tpublic static AuthRequest parseAuth(String authentication) {\n\t\tAuthRequest auth = new AuthRequest();\n\t\tif (!authentication.startsWith(BASIC)) {\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\tif (authentication.length() == BASIC.length()) {\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\tString userPasswd;\n\t\ttry {\n\t\t\tuserPasswd = new String(Base64.decode(authentication.substring(BASIC.length()).trim()));\n\t\t} catch (Exception e) {\n\t\t\treturn null;\n\t\t}\n\t\tint pos = userPasswd.indexOf(\":\");\n\t\tif (pos < 0 || pos > userPasswd.length() - 1) {\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\tString user = userPasswd.substring(0, pos);\n\t\tString pass = userPasswd.substring(pos+1, userPasswd.length());\n\t\t\n\t\ttry {\n\t\t\tint appid = Integer.parseInt(user);\n\t\t\tauth.setAppid(appid);\n\t\t} catch (Exception e) {\n\t\t\treturn null;\n\t\t}\n\t\t\n\t\tauth.setAppsecret(pass);\n\t\t\n\t\treturn auth;\n\t}\n\n\tpublic static String listToString(List<String> list, String conjunction)\n\t{\n\t   StringBuilder sb = new StringBuilder();\n\t   boolean first = true;\n\t   for (String item : list)\n\t   {\n\t      if (first)\n\t         first = false;\n\t      else\n\t         sb.append(conjunction);\n\t      sb.append(item);\n\t   }\n\t   return sb.toString();\n\t}\n\t\n\tpublic static FetchSourceContext parseFetchSourceContext(JsonElement sourceContext) {\n\t\ttry {\n\t\t\tList<String> includes = new ArrayList<>(2);\n\t\t\tList<String> excludes = new ArrayList<>(2);\n\t\t\tif (sourceContext.isJsonPrimitive()) {\n\t\t\t\tJsonPrimitive sourceContextPost = sourceContext.getAsJsonPrimitive();\n\t\t\t\tFetchSourceContext fetchContext = getFetchSourceContext(sourceContextPost);\n\t\t\t\tif (fetchContext != null) return fetchContext;\n\t\t\t} else if (sourceContext.isJsonArray()) {\n\t\t\t\tincludes = new ArrayList<>();\n\t\t\t\taddInclude(sourceContext, includes);\n\t\t\t} else if (sourceContext.isJsonObject()) {\n\t\t\t\taddIncludesAndExcludes(sourceContext, includes, excludes);\n\t\t\t}\n\n\t\t\treturn new FetchSourceContext(includes.toArray(new String[includes.size()]),\n\t\t\t        excludes.toArray(new String[excludes.size()]));\n\t\t} catch (Exception e) {\n\t\t\treturn new FetchSourceContext(true);\n\t\t}\n\t}\n\n\tprivate static void addIncludesAndExcludes(JsonElement sourceContext, List<String> includes, List<String> excludes) {\n\t\tJsonObject sourceContextPost = sourceContext.getAsJsonObject();\n\t\tJsonElement includesJson = sourceContextPost.get(\"includes\");\n\t\tif (includesJson == null) {\n\t\t\tincludesJson = sourceContextPost.get(\"include\");\n\t\t}\n\n\t\tif (includesJson != null) {\n\t\t\tdealJson(includes, includesJson);\n\t\t}\n\n\t\tJsonElement excludesJson = sourceContextPost.get(\"excludes\");\n\t\tif (excludesJson == null) {\n\t\t\texcludesJson = sourceContextPost.get(\"exclude\");\n\t\t}\n\n\t\tif (excludesJson != null) {\n\t\t\tdealJson(excludes, excludesJson);\n\t\t}\n\t}\n\n\tprivate static void dealJson(List<String> includesOrExcludes, JsonElement includesOrExcludesJson) {\n\t\tif (includesOrExcludesJson.isJsonArray()) {\n\t\t\tfor (int i = 0; i < includesOrExcludesJson.getAsJsonArray().size(); ++i) {\n\t\t\t\tincludesOrExcludes.add(includesOrExcludesJson.getAsJsonArray().get(i).getAsString());\n\t\t\t}\n\t\t} else if (includesOrExcludesJson.isJsonPrimitive()) {\n\t\t\tincludesOrExcludes.add(includesOrExcludesJson.getAsString());\n\t\t}\n\t}\n\n\tprivate static void addInclude(JsonElement sourceContext, List<String> includes) {\n\t\tJsonArray sourceContextPost = sourceContext.getAsJsonArray();\n\t\tfor (int i = 0; i < sourceContextPost.size(); ++i) {\n\t\t\tincludes.add(sourceContextPost.get(i).getAsString());\n\t\t}\n\t}\n\n\tprivate static FetchSourceContext getFetchSourceContext(JsonPrimitive sourceContextPost) {\n\t\tif (sourceContextPost.isBoolean()) {\n\t\t\treturn new FetchSourceContext(sourceContextPost.getAsBoolean());\n\t\t} else if (sourceContextPost.isString()) {\n\t\t\treturn new FetchSourceContext(sourceContextPost.getAsString());\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic static String[] parseFields(JsonElement fields) {\n\t\tif (fields.isJsonArray()) {\n\t\t\tJsonArray fieldsPost = fields.getAsJsonArray();\n\t\t\tString[] strFields = new String[fieldsPost.size()];\n\t\t\tfor (int i = 0 ; i < fieldsPost.size(); ++i) {\n\t\t\t\tstrFields[i] = fieldsPost.get(i).getAsString();\n\t\t\t}\n\t\t\t\n\t\t\treturn strFields;\n\t\t} else if (fields.isJsonPrimitive()) {\n\t\t\tJsonPrimitive fieldsPost = fields.getAsJsonPrimitive();\n\t\t\tif (fieldsPost.isString()) {\n\t\t\t\treturn new String[]{fieldsPost.getAsString()};\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn new String[]{};\n\t}\n\t\n\tpublic static String getPrefix(String str) {\n\t\treturn str.length() > 4096 ? str.substring(0, 4095) + \"...\" : str;\n\t}\n\t\n    /** \n     *  \n     * @功能说明:在日志文件中，打印异常堆栈 \n     * @return:String\n     */  \n    public static String logExceptionStack(Throwable e) {  \n        StringWriter errorsWriter = new StringWriter();  \n        e.printStackTrace(new PrintWriter(errorsWriter));  \n        return getPrefix(errorsWriter.toString());\n    }  \t\n\t\n\tpublic static String getClientIP(HttpServletRequest request) {\n\t\t// kibana不能用X-Forwarded-For，而是直接用kibana部署的服务器ip\n\t\tif (request.getHeader(\"kbn-version\") != null) {\n\t\t\treturn request.getRemoteAddr();\n\t\t} else {\n\t\t\tString ip = request.getHeader(\"X-Real-IP\");\n\t\t    \n\t\t    if (ipExist(ip)) {\n\t\t    \tip = request.getHeader(\"X-Forwarded-For\");\n\t\t    }\n\t\t    \n\t\t    if (ipExist(ip)) {\n\t\t    \tip = request.getRemoteAddr();\n\t\t    }\n\n\t\t    return ip;\n\t\t}\n\t}\n\n\tprivate static boolean ipExist(String ip) {\n\t\treturn ip == null || ip.length() == 0 || UN_KNOW.equalsIgnoreCase(ip);\n\t}\n\n\tpublic static String getClientIP(RestRequest request) {\n\t\t// kibana不能用X-Forwarded-For，而是直接用kibana部署的服务器ip\n\t\tif (request.header(\"kbn-version\") != null) {\n\t\t\tInetSocketAddress address = (InetSocketAddress) request.getRemoteAddress();\n\t\t\treturn address.getAddress().getHostAddress();\n\t\t} else {\n\t\t\tString ip = request.header(\"X-Real-IP\");\n\n\t\t\tif (ipExist(ip)) {\n\t\t\t\tip = request.header(\"X-Forwarded-For\");\n\t\t\t}\n\n\t\t\tif (ipExist(ip)) {\n\t\t\t\tInetSocketAddress address = (InetSocketAddress) request.getRemoteAddress();\n\t\t\t\tip = address.getAddress().getHostAddress();\n\t\t\t}\n\n\t\t\treturn ip;\n\t\t}\n\t}\n\t\n\tpublic static void convertIndices(SearchRequest searchRequest) {\n    \tsearchRequest.indices(convertIndices(searchRequest.indices()));\n\t}\n\n\tpublic static void convertIndices(ESSearchRequest esSearchRequest) {\n    \tesSearchRequest.indices(convertIndices(esSearchRequest.indices()));\n\t}\n\n\t/**\n\t * 将具体索引带上*，支持访问带版本索引数据\n\t *\n\t * @param indices 索引\n\t * @return {@link String[]}\n\t */\n\tpublic static String[] convertIndices(String[] indices) {\n\t\tif (indices == null) {\n\t\t\treturn indices;\n\t\t}\n\n\t\tboolean changed = false;\n\t\tString[] newIndices = new String[indices.length];\n\n\t\tfor (int i = 0; i < indices.length; ++i) {\n\t\t\tString index = indices[i];\n            if (StringUtils.isNotBlank(index) && !index.endsWith(\"*\")) {\n\t\t\t\tString newIndex = index + \"*\";\n\t\t\t\tnewIndices[i] = newIndex;\n\t\t\t\tchanged = true;\n\t\t\t} else {\n\t\t\t\tnewIndices[i] = index;\n\t\t\t}\n\t\t}\n\n\t\tif (changed) {\n\t\t\tif (logger.isDebugEnabled()) {\n\t\t\t\tlogger.debug(\"convertIndices||newIndices={}\", StringUtils.join(newIndices, \",\"));\n\t\t\t}\n\t\t\treturn newIndices;\n\t\t} else {\n\t\t\treturn indices;\n\t\t}\n\t}\n\t\n\tpublic static FieldInfo fieldInfoMerge(FieldInfo oldFieldInfo, FieldInfo newFieldInfo) {\n\t\tif (newFieldInfo.getCardinality() > oldFieldInfo.getCardinality()) {\n\t\t\treturn newFieldInfo;\n\t\t} else {\n\t\t\treturn oldFieldInfo;\n\t\t}\n\t}\n\t\n\tpublic static String getHostName() {\n\t\tInetAddress addr = null;\n\t\ttry {\n\t\t\taddr = InetAddress.getLocalHost();\n\t\t} catch (UnknownHostException e) {\n\t\t\treturn \"localhost\";\n\t\t}\n\t\tString hostName = addr.getHostName();\n        if (hostName != null) {\n            hostName = hostName.replace(\".diditaxi.com\", \"\");\n        } else {\n            hostName = \"localhost\";\n        }\n        \n        return hostName;  \n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/utils/DateUtil.java",
    "content": "package com.didi.arius.gateway.common.utils;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.cache.CacheLoader;\nimport com.google.common.cache.LoadingCache;\nimport org.apache.commons.lang3.StringUtils;\nimport org.joda.time.DateTime;\nimport org.joda.time.format.DateTimeFormat;\n\nimport java.time.Instant;\nimport java.time.LocalDateTime;\nimport java.time.ZoneId;\nimport java.time.format.DateTimeFormatter;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\n\npublic class DateUtil {\n\n    private DateUtil(){}\n\n    protected static final List<String> timePatterns = Arrays.asList( \"yyyy-MM-dd\", \"yyyy-MM-dd HH:mm:ss\", \"yyyy-MM-dd HH:mm:ss.SSS Z\", \"yyyy-MM-dd'T'HH:mm:ssZ\");\n\n    private static final long MILLIS_ZONE_OFFSET = LocalDateTime.of(1970, 1, 1, 0, 0, 0,\n            0).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();\n    private static LoadingCache<Long, Map<String, String>> dayFormatCache = CacheBuilder.newBuilder().concurrencyLevel(20).expireAfterWrite(5,\n            TimeUnit.MINUTES).initialCapacity(60).maximumSize(100).recordStats().build(new CacheLoader<Long, Map<String, String>>() {\n\n        @Override\n        public Map<String, String> load(Long key) {\n            return new ConcurrentHashMap<>();\n        }\n    });\n\n    public static long transformToMillis(String date) throws InvalidParameterException {\n        long messageTime = 0;\n\n        if (StringUtils.isNumeric(date)) {\n            if (date.length() == 13) {\n                messageTime = Long.parseLong(date);\n            } else if (date.length() == 10) {\n                messageTime = Long.parseLong(date);\n                messageTime = messageTime * 1000;\n            }\n        } else if (!StringUtils.isEmpty(date)) {\n            for (String timePattern : timePatterns) {\n                try {\n                    messageTime = DateTime.parse(date, DateTimeFormat.forPattern(timePattern)).getMillis();\n                    break;\n                } catch (Exception e) {\n                    //pass\n                }\n            }\n        }\n\n        if (messageTime == 0) {\n            throw new InvalidParameterException(\"date format error, date=\" + date);\n        }\n\n        return messageTime;\n    }\n\n    public static String transformToDateFormat(long time, String dateFormat) {\n        // 需要校准时区之差对应的时间\n        long key = (time - MILLIS_ZONE_OFFSET) / QueryConsts.DAY_MILLIS;\n        String dateFormatTime = null;\n        dateFormat = dateFormat.replace('Y', 'y');\n\n        try {\n            // 从缓存中获取\n            Map<String, String> format2DayValueMap = dayFormatCache.get(key);\n\n            // 如果该时间在缓存中找不到，则计算, 这里不会执行到，因为在构建dayFormatCache设置了load回调来放入新的key\n            if (null == format2DayValueMap) {\n\n                format2DayValueMap = new ConcurrentHashMap<>();\n                // 不包含该日期转换格式则计算，然后放入map中\n\n                Instant instant = Instant.ofEpochMilli(time);\n                LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());\n                dateFormatTime = DateTimeFormatter.ofPattern(dateFormat).format(dateTime);\n\n                format2DayValueMap.put(dateFormat, dateFormatTime);\n                // 放入缓存中\n                dayFormatCache.put(key, format2DayValueMap);\n            } else {\n                // 如果包含了该日期转换格式\n                if (format2DayValueMap.containsKey(dateFormat)) {\n                    dateFormatTime = format2DayValueMap.get(dateFormat);\n                } else {\n                    // 不包含该日期转换格式则计算，然后放入map中\n                    Instant instant = Instant.ofEpochMilli(time);\n                    LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());\n\n                    dateFormatTime = DateTimeFormatter.ofPattern(dateFormat).format(dateTime);\n\n                    // 有效的才放入map中\n                    format2DayValueMap.put(dateFormat, dateFormatTime);\n                }\n            }\n        } catch (Exception e) {\n            //pass\n        }\n\n        return dateFormatTime;\n    }\n\n    public static List<String> getDateFormatSuffix(long start, long end, String dateFormat) {\n        List<String> suffixes = new ArrayList<>();\n\n        if (start > end) {\n            return suffixes;\n        }\n\n        DateTime startDate = new DateTime(start);\n        DateTime endDate = new DateTime(end);\n\n        String startSuffix = startDate.toString(dateFormat);\n        String endSuffix = endDate.toString(dateFormat);\n\n        suffixes.add(startSuffix);\n\n        String lastSuffix = startSuffix;\n        if (dateFormat.endsWith(\"dd\")) {\n            while (startDate.plusDays(1).getMillis() < endDate.getMillis()) {\n                startDate = startDate.plusDays(1);\n\n                String suffix = startDate.toString(dateFormat);\n                suffixes.add(suffix);\n\n                lastSuffix = suffix;\n            }\n        } else if (dateFormat.endsWith(\"MM\")) {\n            while (startDate.plusMonths(1).getMillis() < endDate.getMillis()) {\n                startDate = startDate.plusMonths(1);\n\n                String suffix = startDate.toString(dateFormat);\n                suffixes.add(suffix);\n\n                lastSuffix = suffix;\n            }\n        } else if (dateFormat.toLowerCase().endsWith(\"yy\")) {\n            while (startDate.plusYears(1).getMillis() < endDate.getMillis()) {\n                startDate = startDate.plusYears(1);\n\n                String suffix = startDate.toString(dateFormat);\n                suffixes.add(suffix);\n\n                lastSuffix = suffix;\n            }\n        }\n\n        if (!endSuffix.equals(lastSuffix)) {\n            suffixes.add(endSuffix);\n        }\n\n        return suffixes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/utils/HttpClient.java",
    "content": "package com.didi.arius.gateway.common.utils;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.*;\nimport org.apache.http.entity.StringEntity;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.util.EntityUtils;\nimport org.elasticsearch.ElasticsearchException;\nimport java.io.IOException;\nimport java.util.Map;\n\n/**\n * http 客户端\n * \n * @author moyunfeng\n *\n */\npublic final class HttpClient {\n\n\tprivate static ILog LOG = LogFactory.getLog(\"thirdReq\");\n\tprivate static CloseableHttpClient HTTPCLIENT = HttpClients.createDefault();\n\n\tprivate HttpClient() {\n\n\t}\n\n\tpublic static <T> T forward(String url, String method, String bodyform,\n\t\t\tMap<String, String> headerParams,\n\t\t\tMap<String, String[]> requestParams, Class<T> clazz)\n\t\t\tthrows ElasticsearchException {\n\t\tLOG.info(\"请求地址：\" + url);\n\t\tLOG.info(\"请求method:\" + method);\n\t\tLOG.info(\"请求参数:\" + requestParams);\n\t\tLOG.info(\"请求头部参数:\" + headerParams);\n\t\tLOG.info(\"请求body:\" + bodyform);\n\n\t\tT result = null;\n\t\tString content;\n\t\ttry {\n\t\t\tcontent = forward(url, method, bodyform, headerParams,\n\t\t\t\t\trequestParams);\n\t\t} catch (Exception e) {\n\t\t\tLOG.error(\"调用错误\", e);\n//\t\t\tthrow new ElasticsearchException(\"调用地址：\" + url + \"发生错误，请求参数：\"\n//\t\t\t\t\t+ requestParams, e);\n\t\t\tcontent = String.format(\"{\\\"code\\\":-1,\\\"message\\\":\\\"请求失败, url=%s, params=%s, header=%s\\\"}\", url, JSON.toJSONString(requestParams), JSON.toJSONString(headerParams));\n\t\t}\n\t\tLOG.info(\"请求结果：\" + content);\n\t\ttry {\n\t\t\tif (content != null && !content.isEmpty()) {\n\t\t\t\tresult = JSON.parseObject(content, clazz);\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tresult = JSON.parseObject(\"{\\\"code\\\":-1,\\\"message\\\":\\\"请求失败\\\"}\", clazz);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tpublic static String forward(String url, String method, String bodyform,\n\t\t\tMap<String, String> headerParams,\n\t\t\tMap<String, String[]> requestParams) throws IOException {\n\t\tif (requestParams != null && requestParams.size() > 0) {\n\t\t\turl += \"?\";\n\t\t\tfor (Map.Entry<String, String[]> e : requestParams.entrySet()) {\n\t\t\t\turl += (e.getKey() + \"=\" + e.getValue()[0] + \"&\");\n\t\t\t}\n\t\t\turl = url.substring(0, url.length() - 1);\n\t\t}\n\n\t\tHttpRequestBase request = null;\n\t\tswitch (method.toUpperCase()) {\n\t\tcase \"GET\":\n\t\t\trequest = new HttpGet(url);\n\t\t\tbreak;\n\t\tcase \"DELETE\":\n\t\t\trequest = new HttpDelete(url);\n\t\t\tbreak;\n\t\tcase \"POST\":\n\t\t\trequest = new HttpPost(url);\n\t\t\tbreak;\n\t\tcase \"PUT\":\n\t\t\trequest = new HttpPut(url);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tLOG.error(\"错误的请求method： \" + method);\n\t\t\treturn null;\n\t\t}\n\n\t\trequest.addHeader(\"content-type\", \"application/json;charset=UTF-8\");\n\t\tif (bodyform != null) {\n\t\t\tif (request instanceof HttpEntityEnclosingRequestBase) {\n\t\t\t\t((HttpEntityEnclosingRequestBase) request)\n\t\t\t\t\t\t.setEntity(new StringEntity(bodyform, \"UTF-8\"));\n\t\t\t}\n\t\t}\n\n\t\tif (headerParams != null && headerParams.size() > 0) {\n\t\t\tfor (Map.Entry<String, String> e : headerParams.entrySet()) {\n\t\t\t\trequest.setHeader(e.getKey(), e.getValue());\n\t\t\t}\n\t\t}\n\n\t\tString repons = null;\n\t\ttry {\n\t\t\tRequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(QueryConsts.DEFAULT_HTTP_TIMEOUT).setConnectTimeout(QueryConsts.DEFAULT_HTTP_TIMEOUT).build();//设置请求和\n\t\t\trequest.setConfig(requestConfig);\n\t\t\t\n\t\t\tHttpResponse httpResponse = HTTPCLIENT.execute(request);\n\t\t\tHttpEntity httpEntity = httpResponse.getEntity();\n\t\t\trepons = EntityUtils.toString(httpEntity);// 取出应答字符串\n\t\t} catch (IOException e) {\n\t\t\tLOG.error(\"转发请求失败\", e);\n\t\t\tthrow e;\n\t\t}\n\n\t\treturn repons;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/utils/IndexTire.java",
    "content": "package com.didi.arius.gateway.common.utils;\n\nimport com.didi.arius.gateway.common.exception.TooManyIndexException;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport org.apache.commons.lang3.StringUtils;\nimport org.joda.time.DateTime;\nimport org.joda.time.format.DateTimeFormat;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class IndexTire {\n    private Node root;\n\n    public IndexTire() {\n        root = new Node(new Char(' ', 0));\n    }\n\n    public Node getRoot() {\n        return root;\n    }\n\n    public static class Node {\n        private Char content; // the character in the node\n\n        private boolean isEnd; // whether the end of the words\n\n        private LinkedList<Node> childList; // the child list\n\n        private IndexTemplate indexTemplate;\n\n        public Node(Char c) {\n            childList = new LinkedList<>();\n            isEnd = false;\n            content = c;\n        }\n\n        public Node subNode(char c) {\n            if (childList != null) {\n                for (Node eachChild : childList) {\n                    if (equalsChar(c, eachChild.content)) {\n                        return eachChild;\n                    }\n                }\n            }\n            return null;\n        }\n\n        public Node subNode(Char c) {\n            if (childList != null) {\n                for (Node eachChild : childList) {\n                    if (equalsChar(c, eachChild.content)) {\n                        return eachChild;\n                    }\n                }\n            }\n            return null;\n        }\n\n        public void addSubNode(Node child) {\n            childList.add(child);\n        }\n\n        public List<Node> subNodes() {\n            return childList;\n        }\n\n        public boolean isEnd() {\n            return isEnd;\n        }\n\n        public void setEnd(boolean end) {\n            this.isEnd = end;\n        }\n\n        public IndexTemplate getIndexTemplate() {\n            return indexTemplate;\n        }\n\n        public void setIndexTemplate(IndexTemplate indexTemplate) {\n            this.indexTemplate = indexTemplate;\n        }\n    }\n\n    public void insert(List<Char> chars, IndexTemplate indexTemplate) {\n        Node current = root;\n        int i = 0;\n        for ( ; i < chars.size(); ++i) {\n            Node child = current.subNode(chars.get(i));\n            if (child == null) {\n                current.setEnd(false);\n                break;\n            } else {\n                current = child;\n            }\n        }\n\n        for ( ; i < chars.size(); ++i) {\n            Node child = new Node(chars.get(i));\n            current.addSubNode(child);\n            current = child;\n        }\n\n        if (current.getIndexTemplate() == null) {\n            current.setIndexTemplate(indexTemplate);\n            if (current.subNodes() == null || current.subNodes().isEmpty()) {\n                current.setEnd(true);\n            }\n        }\n    }\n\n    public IndexTemplate search(String index){\n        Node current = root;\n        int pos = 0;\n\n        // 从根节点开始遍历字符\n        return searchSubNode(current, index, pos);\n    }\n\n    private IndexTemplate scanNodes(Node current, String index) {\n        // 遍历子节点，找到对应的模板，如果匹配到超过2个模板，则直接返回错误。\n        IndexTemplate indexTemplate = null;\n\n        if (current.getIndexTemplate() != null\n            && checkIndexMatchTemplate(index, current.getIndexTemplate())) {\n            indexTemplate = current.getIndexTemplate();\n        }\n\n        for (Node child : current.subNodes()) {\n\n            IndexTemplate subTemplate = scanNodes(child, index);\n\n            if (indexTemplate != null && subTemplate != null && !indexTemplate.equals(subTemplate)) {\n                throw new TooManyIndexException(String.format(\"search query match more then one index template, index=%s, template 1=%s, template 2=%s\", index, indexTemplate.getExpression(), subTemplate.getExpression()));\n            }\n\n            if (indexTemplate == null && subTemplate != null) {\n                indexTemplate = subTemplate;\n            }\n        }\n\n        return indexTemplate;\n    }\n\n    private IndexTemplate searchSubNode(Node current, String index, int pos) {\n        if (current.isEnd()) {\n            // 已经遍历到模板的末尾\n            boolean result = checkIndexMatchTemplate(index, current.getIndexTemplate());\n            IndexTemplate indexTemplate = null;\n            if (result) {\n                indexTemplate = current.getIndexTemplate();\n            }\n            return indexTemplate;\n        }\n\n        // 判断是否有带*号的查询，有的话，顺序过滤多个*号，到下一个字符\n        boolean wildcard = false;\n        while (pos < index.length() && index.charAt(pos) == '*') {\n            pos ++;\n            wildcard = true;\n            break;\n        }\n\n        if (wildcard) {\n            // 前缀有带*号的case，则遍历剩下全部节点，找到符合的模板\n            return scanNodes(current, index);\n        }\n\n        // 前缀没有带*号，则一直往下遍历\n        if (pos < index.length()) {\n            current = current.subNode(index.charAt(pos));\n            if (current == null) {\n                // 没找到对应的模板\n                return null;\n            } else {\n                return searchSubNode(current, index, pos + 1);\n            }\n        } else if (current.getIndexTemplate() != null) {\n            // index已经遍历完，且当前节点包含索引模板\n            boolean result = checkIndexMatchTemplate(index, current.getIndexTemplate());\n            if (result) {\n                return current.getIndexTemplate();\n            } else {\n                return null;\n            }\n        } else {\n            // index已经遍历完，但没命中到查询模板\n            return null;\n        }\n    }\n\n    public static class Char {\n        char c;\n        int type;\n\n        Char(char c, int type) {\n            this.c = c;\n            this.type = type;\n        }\n    }\n\n    public static boolean checkIndexMatchTemplate(String index, IndexTemplate indexTemplate) {\n        String expression = indexTemplate.getExpression();\n        expression = expression.replace(\"*\", \"\");\n\n        //如果索引匹配上索引模板，则直接返回true\n        if (index.equals(indexTemplate.getName())) {\n            return true;\n        }\n\n        //如果索引匹配上别名，这直接返回true\n        if (indexTemplate.getAliases() != null) {\n            for (String alias : indexTemplate.getAliases()) {\n                if (alias.equals(index)) {\n                    return true;\n                }\n            }\n        }\n\n        if (index.contains(\"*\")) {\n            return matchTemplateByStar(index, indexTemplate, expression);\n        } else {\n            return matchTemplateByOther(index, indexTemplate, expression);\n        }\n    }\n\n    private static boolean matchTemplateByOther(String index, IndexTemplate indexTemplate, String expression) {\n        if (StringUtils.isEmpty(indexTemplate.getDateFormat())) {\n            // 不是时间后缀的索引，直接比较\n            return index.equals(expression);\n        } else {\n            int pos = index.indexOf(expression);\n            if (pos < 0) {\n                return false;\n            }\n\n            pos += expression.length();\n\n            String format = index.substring(pos);\n\n            int end = format.indexOf(\"_v\");\n\n            if (end > 0) {\n                format = format.substring(0, end);\n            }\n\n            try {\n                DateTime.parse(format, DateTimeFormat.forPattern(indexTemplate.getDateFormat()));\n                return true;\n            } catch (Exception e) {\n                return false;\n            }\n        }\n    }\n\n    private static boolean matchTemplateByStar(String index, IndexTemplate indexTemplate, String expression) {\n        // 按*号，将index分成多个token\n        Tokens tokens = formTokens(index);\n\n        List<Char> expCharList = IndexTireBuilder.getIndexChars(expression, indexTemplate.getDateFormat());\n\n        Iterator<String> tokenIter = tokens.tokenList.iterator();\n        String token = tokenIter.next();\n\n        int tokenPos = 0;\n        if (!tokens.indexStarStart) {\n            boolean startResult = startWithToken(expCharList, token);\n            if (!startResult) {\n                return false;\n            }\n\n            tokenPos = token.length();\n        } else {\n            tokenPos = indexOfToken(expCharList, tokenPos, token);\n            if (tokenPos < 0) {\n                return false;\n            }\n        }\n\n        while (tokenIter.hasNext()) {\n            token = tokenIter.next();\n            tokenPos = indexOfToken(expCharList, tokenPos, token);\n            if (tokenPos < 0) {\n                return false;\n            }\n        }\n\n        boolean res = false;\n        if (tokenPos == expCharList.size() || tokens.indexStarEnd) {\n            res = true;\n        }\n        return res;\n    }\n\n    private static boolean startWithToken(List<Char> expCharList, String token) {\n        int pos = 0;\n        int tokenPos = 0;\n        boolean missed = false;\n        while (tokenPos < token.length()) {\n            if (pos >= expCharList.size()) {\n                return false;\n            }\n\n            char tokenC = token.charAt(tokenPos);\n            Char expC = expCharList.get(pos);\n            if (!equalsChar(tokenC, expC)) {\n                missed = true;\n                break;\n            }\n\n            tokenPos++;\n            pos++;\n        }\n\n        return !missed;\n    }\n\n    private static int indexOfToken(List<Char> expCharList, int pos, String token) {\n        char tokenFirst = token.charAt(0);\n        while (pos < expCharList.size()) {\n            Integer tokenIndex = getToken(expCharList, pos, token, tokenFirst);\n            if (tokenIndex != null) return tokenIndex;\n\n            pos ++;\n        }\n\n        // token没命中exp\n        return -1;\n    }\n\n    private static Integer getToken(List<Char> expCharList, int pos, String token, char tokenFirst) {\n        Char expC = expCharList.get(pos);\n        if (equalsChar(tokenFirst, expC)) {\n            int tokenPos = 0;\n            int expPos = pos;\n            boolean missed = false;\n            while (tokenPos < token.length()) {\n                if (expPos >= expCharList.size()) {\n                    // token没命中exp\n                    return -1;\n                }\n\n                char tokenC = token.charAt(tokenPos);\n                expC = expCharList.get(expPos);\n                if (!equalsChar(tokenC, expC)) {\n                    missed = true;\n                    break;\n                }\n\n                tokenPos++;\n                expPos++;\n            }\n\n            if (!missed) {\n                return expPos;\n            }\n        }\n        return null;\n    }\n\n    private static boolean equalsChar(char a, Char b) {\n        boolean res = false;\n        if ((b.type == 0 && a == b.c)\n                || (b.type == 1 && a >= '0' && a <= '9')) {\n            res = true;\n        }\n        return res;\n    }\n\n    private static boolean equalsChar(Char a, Char b) {\n        boolean res = false;\n        if ((b.type == 0 && a.type == 0 && a.c == b.c)\n                || (b.type == 1 && a.type == 1)) {\n            res = true;\n        }\n        return res;\n    }\n\n    public static class Tokens {\n        List<String> tokenList;\n        boolean indexStarEnd;\n        boolean indexStarStart;\n\n        public Tokens(List<String> tokenList, boolean indexStarEnd, boolean indexStarStart) {\n            this.tokenList = tokenList;\n            this.indexStarEnd = indexStarEnd;\n            this.indexStarStart = indexStarStart;\n        }\n    }\n\n    public static Tokens formTokens(String index) {\n        List<String> tokens = new ArrayList<>();\n\n        int tokenStart = 0;\n        int indexPointer = 0;\n\n        boolean indexStarEnd = false;\n        boolean indexStarStart = false;\n        if (index.charAt(0) == '*') {\n            indexStarStart = true;\n            for (; indexPointer < index.length(); indexPointer++) {\n                if (index.charAt(indexPointer) != '*') {\n                    tokenStart = indexPointer;\n                    break;\n                }\n            }\n        }\n\n        if (index.charAt(index.length() - 1) == '*') {\n            indexStarEnd = true;\n        }\n\n        while (indexPointer < index.length()) {\n            char indexC = index.charAt(indexPointer);\n            if (indexC == '*') {\n                if (indexPointer != 0) {\n                    tokens.add(index.substring(tokenStart, indexPointer));\n                }\n\n\n                for (; indexPointer < index.length(); indexPointer++) {\n                    if (index.charAt(indexPointer) != '*') {\n                        tokenStart = indexPointer;\n                        break;\n                    }\n                }\n            } else {\n                indexPointer++;\n            }\n        }\n\n        if (!indexStarEnd) {\n            tokens.add(index.substring(tokenStart, indexPointer));\n        }\n\n\n        return new Tokens(tokens, indexStarEnd, indexStarStart);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/utils/IndexTireBuilder.java",
    "content": "package com.didi.arius.gateway.common.utils;\n\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\npublic class IndexTireBuilder {\n    private Map<String, IndexTemplate> templateMap;\n\n    public IndexTireBuilder(Map<String, IndexTemplate> templateMap) {\n        this.templateMap = templateMap;\n    }\n\n    public IndexTire build() {\n        IndexTire indexTire = new IndexTire();\n        for (Map.Entry<String, IndexTemplate> entry : templateMap.entrySet()) {\n            String expression = entry.getKey();\n            IndexTemplate indexTemplate = entry.getValue();\n\n            List<IndexTire.Char> chars = getIndexChars(expression, indexTemplate.getDateFormat());\n            indexTire.insert(chars, indexTemplate);\n\n            if (!StringUtils.isEmpty(indexTemplate.getDateFormat())) {\n                List<IndexTire.Char> expChars = getIndexChars(expression, null);\n                indexTire.insert(expChars, indexTemplate);\n            }\n\n            if (indexTemplate.getAliases() != null) {\n                for (String alias : indexTemplate.getAliases()) {\n                    List<IndexTire.Char> aliasChars = getIndexChars(alias, null);\n                    indexTire.insert(aliasChars, indexTemplate);\n                }\n            }\n        }\n\n        return indexTire;\n    }\n\n\n    public static List<IndexTire.Char> getIndexChars(String expression, String dateFormat) {\n        List<IndexTire.Char> chars = new ArrayList<>();\n        for (int i = 0 ; i < expression.length(); ++i) {\n            chars.add(new IndexTire.Char(expression.charAt(i), 0));\n        }\n\n        if (!StringUtils.isEmpty(dateFormat)) {\n            for (int i = 0 ; i < dateFormat.length(); ++i) {\n                char c = dateFormat.charAt(i);\n                switch (c) {\n                    case 'Y':\n                    case 'y':\n                    case 'M':\n                    case 'm':\n                    case 'D':\n                    case 'd':\n                        chars.add(new IndexTire.Char(c, 1));\n                        break;\n                    default:\n                        chars.add(new IndexTire.Char(c, 0));\n                        break;\n                }\n\n            }\n        }\n\n        return chars;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/utils/MetricUtil.java",
    "content": "package com.didi.arius.gateway.common.utils;\n\nimport com.didiglobal.knowframework.metrics.MetricsSource;\nimport com.didiglobal.knowframework.metrics.MetricsSystem;\nimport com.didiglobal.knowframework.metrics.lib.DefaultMetricsSystem;\n\npublic class MetricUtil {\n\n\tprivate MetricUtil(){}\n\n\tprivate static final String METRIC_PREFIX = \"arius\";\n\n\tprivate static MetricsSystem metricsSystem;\n\n\t/**\n\t * 获取系统级别的指标系统\n\t * \n\t * @return\n\t */\n\tprivate static synchronized MetricsSystem getMetricsSystem() {\n\t\tif (null == metricsSystem) {\n\t\t\tmetricsSystem = DefaultMetricsSystem.initialize(METRIC_PREFIX);\n\t\t}\n\n\t\treturn metricsSystem;\n\t}\n\n\t/**\n\t * 注册source\n\t * \n\t * @param metricSetName\n\t *            指标集名称\n\t * @param desc\n\t *            描述信息\n\t * @param metricSource\n\t *            指标数据源\n\t */\n\tpublic static <T extends MetricsSource> T register(String metricSetName,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   String desc, T metricSource) {\n\t\treturn getMetricsSystem().register(metricSetName, desc, metricSource);\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/utils/PathTrie.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.common.utils;\n\nimport java.util.*;\nimport java.util.function.BiFunction;\nimport java.util.function.Supplier;\n\nimport static java.util.Collections.emptyMap;\nimport static java.util.Collections.unmodifiableMap;\n\npublic class PathTrie<T> {\n\n    enum TrieMatchingMode {\n        /*\n         * Retrieve only explicitly mapped nodes, no wildcards are\n         * matched.\n         */\n        EXPLICIT_NODES_ONLY,\n        /*\n         * Retrieve only explicitly mapped nodes, with wildcards\n         * allowed as root nodes.\n         */\n        WILDCARD_ROOT_NODES_ALLOWED,\n        /*\n         * Retrieve only explicitly mapped nodes, with wildcards\n         * allowed as leaf nodes.\n         */\n        WILDCARD_LEAF_NODES_ALLOWED,\n        /*\n         * Retrieve both explicitly mapped and wildcard nodes.\n         */\n        WILDCARD_NODES_ALLOWED\n    }\n\n    private static final EnumSet<TrieMatchingMode> EXPLICIT_OR_ROOT_WILDCARD =\n            EnumSet.of(TrieMatchingMode.EXPLICIT_NODES_ONLY, TrieMatchingMode.WILDCARD_ROOT_NODES_ALLOWED);\n\n    public interface Decoder {\n        String decode(String value);\n    }\n\n    private final Decoder decoder;\n    private final TrieNode root;\n    private T rootValue;\n\n    private static final String SEPARATOR = \"/\";\n    private static final String WILDCARD = \"*\";\n\n    public PathTrie(Decoder decoder) {\n        this.decoder = decoder;\n        root = new TrieNode(SEPARATOR, null, WILDCARD);\n    }\n\n    public class TrieNode {\n        private transient String key;\n        private transient T value;\n        private final String wildcard;\n\n        private transient String namedWildcard;\n\n        private Map<String, TrieNode> children;\n\n        private TrieNode(String key, T value, String wildcard) {\n            this.key = key;\n            this.wildcard = wildcard;\n            this.value = value;\n            this.children = emptyMap();\n            if (isNamedWildcard(key)) {\n                namedWildcard = key.substring(key.indexOf('{') + 1, key.indexOf('}'));\n            } else {\n                namedWildcard = null;\n            }\n        }\n\n        private void updateKeyWithNamedWildcard(String key) {\n            this.key = key;\n            String newNamedWildcard = key.substring(key.indexOf('{') + 1, key.indexOf('}'));\n            if (namedWildcard != null && !newNamedWildcard.equals(namedWildcard)) {\n                throw new IllegalArgumentException(\"Trying to use conflicting wildcard names for same path: \"\n                    + namedWildcard + \" and \" + newNamedWildcard);\n            }\n            namedWildcard = newNamedWildcard;\n        }\n\n        private void addInnerChild(String key, TrieNode child) {\n            Map<String, TrieNode> newChildren = new HashMap<>(children);\n            newChildren.put(key, child);\n            children = unmodifiableMap(newChildren);\n        }\n\n        private synchronized void insert(String[] path, int index, T value) {\n            TrieNode node = getTrieNode(path, index, value, (x, y) -> {throw new IllegalArgumentException(\"Path [\" + String.join(\"/\", path)+ \"] already has a value\");});\n            if (node == null) return;\n\n            node.insert(path, index + 1, value);\n        }\n\n        private synchronized void insertOrUpdate(String[] path, int index, T value, BiFunction<T, T, T> updater) {\n            TrieNode node = getTrieNode(path, index, value, updater);\n            if (node == null) return;\n\n            node.insertOrUpdate(path, index + 1, value, updater);\n        }\n\n        private TrieNode getTrieNode(String[] path, int index, T value, BiFunction<T, T, T> updater) {\n            if (index >= path.length)\n                return null;\n\n            String token = path[index];\n            String key = token;\n            if (isNamedWildcard(token)) {\n                key = wildcard;\n            }\n            TrieNode node = children.get(key);\n            if (node == null) {\n                T nodeValue = index == path.length - 1 ? value : null;\n                node = new TrieNode(token, nodeValue, wildcard);\n                addInnerChild(key, node);\n            } else {\n                if (isNamedWildcard(token)) {\n                    node.updateKeyWithNamedWildcard(token);\n                }\n                /*\n                 * If the target node already exists, but is without a value,\n                 *  then the value should be updated.\n                 */\n                if (index == (path.length - 1)) {\n                    if (node.value != null) {\n                        node.value = updater.apply(node.value, value);\n                    } else {\n                        node.value = value;\n                    }\n                }\n            }\n            return node;\n        }\n\n        private boolean isNamedWildcard(String key) {\n            return key.indexOf('{') != -1 && key.indexOf('}') != -1;\n        }\n\n        private String namedWildcard() {\n            return namedWildcard;\n        }\n\n        private boolean isNamedWildcard() {\n            return namedWildcard != null;\n        }\n\n        public T retrieve(String[] path, int index, Map<String, String> params, TrieMatchingMode trieMatchingMode) {\n            if (index >= path.length)\n                return null;\n\n            String token = path[index];\n            TrieNode node = children.get(token);\n            boolean usedWildcard;\n\n            if (node == null) {\n                if (isMatch(path, index, trieMatchingMode)\n                ) {\n                    node = children.get(wildcard);\n                    if (node == null) {\n                        return null;\n                    }\n                    usedWildcard = true;\n                } else {\n                    return null;\n                }\n            } else {\n                usedWildcard = token.equals(wildcard);\n                if (isMatch(path, index, trieMatchingMode, node)) {\n                    /*\n                     * If we are at the end of the path, the current node does not have a value but\n                     * there is a child wildcard node, use the child wildcard node.\n                     */\n                    node = children.get(wildcard);\n                    usedWildcard = true;\n                }\n            }\n\n            put(params, node, token);\n\n            if (index == (path.length - 1)) {\n                return node.value;\n            }\n\n            T nodeValue = node.retrieve(path, index + 1, params, trieMatchingMode);\n            if (isMatch(trieMatchingMode, usedWildcard, nodeValue)) {\n                node = children.get(wildcard);\n                if (node != null) {\n                    put(params, node, token);\n                    nodeValue = node.retrieve(path, index + 1, params, trieMatchingMode);\n                }\n            }\n\n            return nodeValue;\n        }\n\n        private boolean isMatch(TrieMatchingMode trieMatchingMode, boolean usedWildcard, T nodeValue) {\n            return nodeValue == null && !usedWildcard && trieMatchingMode != TrieMatchingMode.EXPLICIT_NODES_ONLY;\n        }\n\n        private boolean isMatch(String[] path, int index, TrieMatchingMode trieMatchingMode, TrieNode node) {\n            return (index + 1 == path.length && node.value == null && children.get(wildcard) != null\n                    && !EXPLICIT_OR_ROOT_WILDCARD.contains(trieMatchingMode)) ||\n                    (index == 1 && node.value == null && children.get(wildcard) != null\n                            && trieMatchingMode == TrieMatchingMode.WILDCARD_ROOT_NODES_ALLOWED);\n        }\n\n        private boolean isMatch(String[] path, int index, TrieMatchingMode trieMatchingMode) {\n            return trieMatchingMode == TrieMatchingMode.WILDCARD_NODES_ALLOWED ||\n                    (trieMatchingMode == TrieMatchingMode.WILDCARD_ROOT_NODES_ALLOWED && index == 1) ||\n                    (trieMatchingMode == TrieMatchingMode.WILDCARD_LEAF_NODES_ALLOWED && index + 1 == path.length);\n        }\n\n        private void put(Map<String, String> params, TrieNode node, String value) {\n            if (params != null && node.isNamedWildcard()) {\n                params.put(node.namedWildcard(), decoder.decode(value));\n            }\n        }\n\n        @Override\n        public String toString() {\n            return key;\n        }\n    }\n\n    public void insert(String path, T value) {\n        String[] strings = path.split(SEPARATOR);\n        if (strings.length == 0) {\n            if (rootValue != null) {\n                throw new IllegalArgumentException(\"Path [/] already has a value [\" + rootValue + \"]\");\n            }\n            rootValue = value;\n            return;\n        }\n        int index = 0;\n        // Supports initial delimiter.\n        if (strings[0].isEmpty()) {\n            index = 1;\n        }\n        root.insert(strings, index, value);\n    }\n\n    /**\n     * Insert a value for the given path. If the path already exists, replace the value with:\n     * <pre>\n     * value = updater.apply(oldValue, newValue);\n     * </pre>\n     * allowing the value to be updated if desired.\n     */\n    public void insertOrUpdate(String path, T value, BiFunction<T, T, T> updater) {\n        String[] strings = path.split(SEPARATOR);\n        if (strings.length == 0) {\n            if (rootValue != null) {\n                rootValue = updater.apply(rootValue, value);\n            } else {\n                rootValue = value;\n            }\n            return;\n        }\n        int index = 0;\n        // Supports initial delimiter.\n        if (strings[0].isEmpty()) {\n            index = 1;\n        }\n        root.insertOrUpdate(strings, index, value, updater);\n    }\n\n    public T retrieve(String path) {\n        return retrieve(path, null, TrieMatchingMode.WILDCARD_NODES_ALLOWED);\n    }\n\n    public T retrieve(String path, Map<String, String> params) {\n        return retrieve(path, params, TrieMatchingMode.WILDCARD_NODES_ALLOWED);\n    }\n\n    public T retrieve(String path, Map<String, String> params, TrieMatchingMode trieMatchingMode) {\n        if (path.length() == 0) {\n            return rootValue;\n        }\n        String[] strings = path.split(SEPARATOR);\n        if (strings.length == 0) {\n            return rootValue;\n        }\n        int index = 0;\n\n        // Supports initial delimiter.\n        if (strings[0].isEmpty()) {\n            index = 1;\n        }\n\n        return root.retrieve(strings, index, params, trieMatchingMode);\n    }\n\n    /**\n     * Returns an iterator of the objects stored in the {@code PathTrie}, using\n     * all possible {@code TrieMatchingMode} modes. The {@code paramSupplier}\n     * is called between each invocation of {@code next()} to supply a new map\n     * of parameters.\n     */\n    public Iterator<T> retrieveAll(String path, Supplier<Map<String, String>> paramSupplier) {\n        return new Iterator<T>() {\n\n            private int mode;\n\n            @Override\n            public boolean hasNext() {\n                return mode < TrieMatchingMode.values().length;\n            }\n\n            @Override\n            public T next() {\n                if (!hasNext()) {\n                    throw new NoSuchElementException(\"called next() without validating hasNext()! no more modes available\");\n                }\n                return retrieve(path, paramSupplier.get(), TrieMatchingMode.values()[mode++]);\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/common/utils/Regex.java",
    "content": "package com.didi.arius.gateway.common.utils;\n\n/**\n* @author weizijun\n* @date：2016年8月18日\n* \n*/\npublic class Regex {\n\n\tprivate Regex(){}\n\t\n\tpublic static boolean indexContainExp(String index, String exp) {\n\t\tif (isEmpty(index, exp)) return false;\n\n\t\tint indexPointer = 0;\n\t\tint expPointer = 0;\n\n\t\t// compare prefix\n\t\tboolean hasStar = false;\n\t\twhile (indexPointer < index.length() && expPointer < exp.length()) {\n\t\t\tchar indexC = index.charAt(indexPointer);\n\t\t\tchar expC = exp.charAt(expPointer);\n\t\t\t\n\t\t\tif (indexC == '*' || expC == '*') {\n\t\t\t\thasStar = true;\n\t\t\t\tbreak;\n\t\t\t} else if (indexC != expC) {\n\t\t\t\t// not the same, failed\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t\n\t\t\tindexPointer++;\n\t\t\texpPointer++;\n\t\t}\n\t\t\n\t\tif (!hasStar) {\n\t\t\treturn starDeal(index, exp, indexPointer, expPointer);\n\t\t}\n\t\t\n\t\t// no *\n\t\t\n\t\tindexPointer = index.length() -1;\n\t\texpPointer = exp.length() - 1;\n\t\t\n\t\t// compare suffix\n\t\twhile ( indexPointer >= 0 && expPointer >= 0) {\n\t\t\tchar indexC = index.charAt(indexPointer);\n\t\t\tchar expC = exp.charAt(expPointer);\n\t\t\t\n\t\t\tif (indexC == '*' || expC == '*') {\n\t\t\t\tbreak;\n\t\t\t} else if (indexC != expC) {\n\t\t\t\t// not the same, failed\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t\n\t\t\tindexPointer--;\n\t\t\texpPointer--;\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n\n\tprivate static boolean isEmpty(String index, String exp) {\n\t\tif (index == null || index.length() == 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (exp == null || exp.length() == 0) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate static boolean starDeal(String index, String exp, int indexPointer, int expPointer) {\n\t\twhile (indexPointer < index.length()) {\n\t\t\tchar indexC = index.charAt(indexPointer);\n\t\t\tif (indexC != '*') {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tindexPointer++;\n\t\t}\n\n\t\twhile (expPointer < exp.length()) {\n\t\t\tchar expC = exp.charAt(expPointer);\n\t\t\tif (expC != '*') {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\texpPointer++;\n\t\t}\n\n\t\t// both end or either end with *\n\t\treturn true;\n\t}\n\n\tpublic static boolean expContainIndex(String index, String exp) {\n\t\tif (isEmpty(index, exp)) return false;\n\n\t\tint indexPointer = 0;\n\t\tint expPointer = 0;\n\n\t\t\n\t\twhile (expPointer < exp.length()) {\n\t\t\tchar expC = exp.charAt(expPointer);\n\t\t\t\n\t\t\tif (expC == '*') {\n\t\t\t\texpPointer++;\n\t\t\t\tboolean expPointerEnd = true;\n\n\t\t\t\twhile (expPointer < exp.length()) {\n\t\t\t\t\texpC = exp.charAt(expPointer);\n\t\t\t\t\tif (expC != '*') {\n\t\t\t\t\t\texpPointerEnd = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\texpPointer++;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// * is the last char in exp\n\t\t\t\tif (expPointerEnd) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tint nextStar = exp.indexOf('*', expPointer);\n\t\t\t\tString expInter = null;\n\t\t\t\tif (nextStar < 0) {\n\t\t\t\t\texpInter = exp.substring(expPointer);\n\t\t\t\t} else {\n\t\t\t\t\texpInter = exp.substring(expPointer, nextStar);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tint indexPos = index.indexOf(expInter, indexPointer);\n\t\t\t\tif (indexPos <= 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\texpPointer = expPointer + expInter.length();\n\t\t\t\tindexPointer = indexPos + expInter.length();\n\t\t\t} else if (indexPointer < index.length()) {\n\t\t\t\tchar indexC = index.charAt(indexPointer);\n\t\t\t\tif (indexC != expC) {\n\t\t\t\t\t// not the same, failed\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tindexPointer++;\n\t\t\t\texpPointer++;\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tboolean res = true;\n\t\tif (indexPointer < index.length()) {\n\t\t\t// index has chars left\n\t\t\tres = false;\n\t\t}\n\t\treturn res;\n\t}\t\t\n\t\n\tpublic static boolean ipMaskMatch(String ip, String mask) {\n\t\tif (mask.endsWith(\"*\")) {\n\t\t\tString prefix = mask.substring(0, mask.length()-1);\n\t\t\tboolean res = false;\n\t\t\tif (ip.startsWith(prefix)) {\n\t\t\t\tres = true;\n\t\t\t}\n\t\t\treturn res;\n\t\t} else {\n\t\t\treturn ip.equals(mask);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/ESClient.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client;\n\n\nimport com.didi.arius.gateway.elasticsearch.client.model.*;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.http.Header;\nimport org.apache.http.HttpHost;\nimport org.apache.http.impl.nio.client.CloseableHttpAsyncClient;\nimport org.apache.http.message.BasicHeader;\nimport org.elasticsearch.action.*;\nimport org.elasticsearch.client.ResponseException;\nimport org.elasticsearch.client.ResponseListener;\nimport org.elasticsearch.client.RestClient;\nimport org.elasticsearch.common.transport.TransportAddress;\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.nio.charset.StandardCharsets;\nimport java.util.ArrayList;\nimport java.util.Base64;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicReference;\n\npublic class ESClient extends ESAbstractClient {\n    protected static final ILog logger = LogFactory.getLog(ESClient.class);\n\n    private List<TransportAddress> tas = new ArrayList<>();\n    private List<HttpHost> nodes = new ArrayList<>();\n\n    private RestClient restClient;\n    private List<Header> headers = new ArrayList<>();\n    private String uriPrefix = null;\n\n    public static final String DEFAULT_ES_VERSION = \"2.3.3\";\n\n    private String esVersion = DEFAULT_ES_VERSION;\n\n    private String clusterName;\n\n    public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 1000;\n    public static final int DEFAULT_SOCKET_TIMEOUT_MILLIS = 30000;\n    public static final int DEFAULT_MAX_RETRY_TIMEOUT_MILLIS = DEFAULT_SOCKET_TIMEOUT_MILLIS;\n    public static final int DEFAULT_MAX_RETRY_COUNT = 3;\n    public static final int DEFAULT_MAX_CONN_PER_ROUTE = 10;\n    public static final int DEFAULT_MAX_CONN_TOTAL = 30;\n\n    private int maxRetryTimeout = DEFAULT_MAX_RETRY_TIMEOUT_MILLIS;\n\n    private int max_conn_per_router = DEFAULT_MAX_CONN_PER_ROUTE;\n    private int max_conn_total = DEFAULT_MAX_CONN_TOTAL;\n\n    private int connect_timeout_millis = DEFAULT_CONNECT_TIMEOUT_MILLIS;\n    private int socket_timeout_millis = DEFAULT_SOCKET_TIMEOUT_MILLIS;\n\n    private final AtomicReference<Boolean> running;\n\n    public ESClient(String clusterName, String version) {\n        this();\n        this.clusterName = clusterName;\n        this.esVersion = version;\n    }\n\n    public ESClient() {\n        running = new AtomicReference<>(false);\n\n    }\n\n    public ESClient addTransportAddress(TransportAddress transportAddress) {\n        tas.add(transportAddress);\n        return this;\n    }\n\n    public ESClient addTransportAddresses(TransportAddress... transportAddress) {\n        for(TransportAddress ta : transportAddress) {\n            addTransportAddress(ta);\n        }\n        return this;\n    }\n\n    public ESClient addHttpHost(String host, int port) {\n        nodes.add(new HttpHost(host, port));\n        return this;\n    }\n\n    @Deprecated\n    public ESClient setHeader(Header header) {\n        return addHeader(header);\n    }\n\n    public ESClient addHeader(Header header) {\n        this.headers.add(header);\n        return this;\n    }\n\n    public ESClient setHeaders(List<Header> headers) {\n        this.headers = headers;\n        return this;\n    }\n\n    public ESClient setUriPrefix(String prefix) {\n        this.uriPrefix = prefix;\n        return this;\n    }\n\n    /**\n     * 设置认证信息\n     * @param password 校验码\n     * @return ESClient\n     */\n    public ESClient setBasicAuth(String password) {\n        String encode = Base64.getEncoder().encodeToString(String.format(\"%s\", password).getBytes(StandardCharsets.UTF_8));\n        Header header = new BasicHeader(\"Authorization\", \"Basic \" + encode);\n        this.headers.add(header);\n        return this;\n    }\n\n    public void start() {\n        reset();\n    }\n\n    private void reset() {\n        logger.info(String.format(\"reset client, cluster=%s\", clusterName));\n\n        for (TransportAddress ta : tas) {\n            nodes.add(new HttpHost(ta.getAddress(), ta.getPort()));\n        }\n\n        HttpHost[] hostArr = new HttpHost[nodes.size()];\n\n        restClient = RestClient.builder(nodes.toArray(hostArr))\n                .setRequestConfigCallback((requestConfigBuilder) -> {\n                    requestConfigBuilder.setSocketTimeout(socket_timeout_millis);\n                    requestConfigBuilder.setConnectTimeout(connect_timeout_millis);\n                    return requestConfigBuilder;\n                })\n                .setHttpClientConfigCallback((httpClientBuilder) -> {\n                    httpClientBuilder.setMaxConnPerRoute(max_conn_per_router);\n                    httpClientBuilder.setMaxConnTotal(max_conn_total);\n\n                    return httpClientBuilder;\n                })\n                .setMaxRetryTimeoutMillis(maxRetryTimeout)\n                .build();\n\n        running.set(true);\n    }\n\n    @Override\n    protected <Request extends ActionRequest,\n               Response extends ActionResponse,\n               RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>>\n    void doExecute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) {\n\n        try {\n            if (running.get().equals(false)) {\n                throw new IllegalStateException(\"client not running\");\n            }\n\n            ESActionRequest req = (ESActionRequest) request;\n            RestRequest rr = req.buildRequest(headers);\n            rr.addEndpointPrefix(uriPrefix);\n\n            restClient.performRequestAsync(rr.buildRequest(), new ResponseListener() {\n                @Override\n                public void onSuccess(org.elasticsearch.client.Response response) {\n                    try {\n                        if (req.checkResponse(response)) {\n                            RestResponse restResponse = new RestResponse(response);\n                            ESActionResponse tr = req.buildResponse(restResponse);\n\n                            listener.onResponse((Response) tr);\n                        } else {\n                            throw new ResponseException(response);\n                        }\n                    } catch (Exception e) {\n                        listener.onFailure(e);\n                    }\n\n                }\n\n                @Override\n                public void onFailure(Exception e) {\n                    listener.onFailure(e);\n                }\n            });\n        } catch (Exception t) {\n            listener.onFailure(t);\n            //todo：zqr\n            /*if (restClient != null && !restClient.isRunning()) {\n                if (running.compareAndSet(true, false)) {\n                    try {\n                        restClient.close();\n                        reset();\n                    } catch (IOException e) {\n                        // pass\n                        logger.error(\"restClient stop error\", e);\n                    }\n                }\n            }*/\n        }\n    }\n\n\n    @Override\n    public void close() {\n        try {\n            restClient.close();\n            running.set(false);\n        } catch (IOException e) {\n            logger.error(\"restClient close error\", e);\n        }\n    }\n\n    public String getEsVersion() {\n        return esVersion;\n    }\n\n    public void setEsVersion(String esVersion) {\n        this.esVersion = esVersion;\n    }\n\n    public String getClusterName() {\n        return clusterName;\n    }\n\n    public void setClusterName(String clusterName) {\n        this.clusterName = clusterName;\n    }\n\n    public void setMax_conn_per_router(int max_conn_per_router) {\n        this.max_conn_per_router = max_conn_per_router;\n    }\n\n    public void setMax_conn_total(int max_conn_total) {\n        this.max_conn_total = max_conn_total;\n    }\n\n    public void setConnect_timeout_millis(int connect_timeout_millis) {\n        this.connect_timeout_millis = connect_timeout_millis;\n    }\n\n    public void setSocket_timeout_millis(int socket_timeout_millis) {\n        this.socket_timeout_millis = socket_timeout_millis;\n    }\n\n    public List<HttpHost> getNodes() {\n        return nodes;\n    }\n\n    public boolean isActualRunning() {\n        try {\n            Field field = restClient.getClass().getDeclaredField(\"client\");\n            field.setAccessible(true);\n            CloseableHttpAsyncClient httpAsyncClient = (CloseableHttpAsyncClient) field.get(restClient);\n            return httpAsyncClient.isRunning();\n        } catch (Exception e) {\n            logger.warn(\"get running status error.\", e);\n            return true;\n        }\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/direct/DirectAction.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.direct;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class DirectAction extends Action<DirectRequest, DirectResponse, DirectRequestBuilder> {\n    public static final DirectAction INSTANCE = new DirectAction();\n    public static final String NAME = \"rest:direct/action\";\n\n    private DirectAction() {\n        super(NAME);\n    }\n\n    @Override\n    public DirectResponse newResponse() {\n        return new DirectResponse();\n    }\n\n    @Override\n    public DirectRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new DirectRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/direct/DirectRequest.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.direct;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class DirectRequest extends ESActionRequest<DirectRequest> {\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    private String method;\n\n    private String uri;\n\n    private String postContent;\n\n    private Map<String, String> params = new HashMap<>();\n\n    public DirectRequest() {\n\n    }\n\n    public DirectRequest(String method, String uri) {\n        this.method = method;\n        this.uri = uri;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        RestRequest rr = new RestRequest(method, uri);\n        rr.setParams(params);\n        rr.setBody(postContent);\n        return rr;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return new DirectResponse(respStr);\n    }\n\n    public void setParams(Map<String, String> params) {\n        this.params = params;\n    }\n\n    public void setPostContent(String postContent) {\n        this.postContent = postContent;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/direct/DirectRequestBuilder.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.direct;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class DirectRequestBuilder extends ActionRequestBuilder<DirectRequest, DirectResponse, DirectRequestBuilder> {\n    protected DirectRequestBuilder(ElasticsearchClient client, Action<DirectRequest, DirectResponse, DirectRequestBuilder> action, DirectRequest request) {\n        super(client, action, request);\n    }\n\n    public DirectRequestBuilder(ElasticsearchClient client, DirectAction directAction) {\n        super(client, directAction, new DirectRequest());\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/direct/DirectResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.direct;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\npublic class DirectResponse extends ESActionResponse {\n    public String getResponseContent() {\n        return responseContent;\n    }\n\n    public void setResponseContent(String responseContent) {\n        this.responseContent = responseContent;\n    }\n\n    private String responseContent;\n\n    public DirectResponse() {\n        // pass\n    }\n\n    public DirectResponse(String responseContent) {\n        this.responseContent = responseContent;\n    }\n\n    @Override\n    public String toString() {\n        return responseContent;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/DocWriteResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentParser;\n\nimport java.io.IOException;\nimport java.util.Locale;\nimport java.util.Map;\n\npublic class DocWriteResponse extends ESActionResponse {\n    private static final String SHARDS = \"_shards\";\n    private static final String INDEX = \"_index\";\n    private static final String TYPE = \"_type\";\n    private static final String ID = \"_id\";\n    private static final String VERSION = \"_version\";\n    private static final String SEQ_NO = \"_seq_no\";\n    private static final String PRIMARY_TERM = \"_primary_term\";\n    private static final String RESULT = \"result\";\n    private static final String FORCED_REFRESH = \"forced_refresh\";\n\n    protected static final String FOUND = \"found\";\n    protected static final String CREATED = \"created\";\n\n    /**\n     * An enum that represents the results of CRUD operations, primarily used to communicate the type of\n     * operation that occurred.\n     */\n    public enum Result {\n        CREATED(0),\n        UPDATED(1),\n        DELETED(2),\n        NOT_FOUND(3),\n        NOOP(4);\n\n        private final byte op;\n        private final String lowercase;\n\n        Result(int op) {\n            this.op = (byte) op;\n            this.lowercase = this.name().toLowerCase(Locale.ROOT);\n        }\n\n        public byte getOp() {\n            return op;\n        }\n\n        public String getLowercase() {\n            return lowercase;\n        }\n    }\n\n    private String index;\n    private String id;\n    private String type;\n    private long version;\n    private long seqNo;\n    private long primaryTerm;\n    private boolean forcedRefresh;\n\n    protected Result result;\n\n    protected Map<String, Object> shards;\n\n    protected boolean found;\n    protected boolean created;\n\n    public DocWriteResponse() {\n\n    }\n\n    public DocWriteResponse(String index, String type, String id, long seqNo, long primaryTerm, long version, Result result, boolean found, boolean created) {\n        this.index = index;\n        this.type = type;\n        this.id = id;\n        this.seqNo = seqNo;\n        this.primaryTerm = primaryTerm;\n        this.version = version;\n        this.result = result;\n        this.found = found;\n        this.created = created;\n    }\n\n    /**\n     * The change that occurred to the document.\n     */\n    public Result getResult() {\n        return result;\n    }\n\n    public void setResult(Result result) {\n        this.result = result;\n    }\n\n    /**\n     * The index the document was changed in.\n     */\n    public String getIndex() {\n        return index;\n    }\n\n    /**\n     * The type of the document changed.\n     */\n    public String getType() {\n        return this.type;\n    }\n\n    /**\n     * The id of the document changed.\n     */\n    public String getId() {\n        return this.id;\n    }\n\n    /**\n     * Returns the current version of the doc.\n     */\n    public long getVersion() {\n        return this.version;\n    }\n\n    public long getSeqNo() {\n        return seqNo;\n    }\n\n    /**\n     * The primary term for this change.\n     *\n     * @return the primary term\n     */\n    public long getPrimaryTerm() {\n        return primaryTerm;\n    }\n\n\n    public boolean forcedRefresh() {\n        return forcedRefresh;\n    }\n\n    public void setForcedRefresh(boolean forcedRefresh) {\n        this.forcedRefresh = forcedRefresh;\n    }\n\n    public Map<String, Object> getShards() {\n        return shards;\n    }\n\n    public void setShards(Map<String, Object> shards) {\n        this.shards = shards;\n    }\n\n    protected XContentBuilder interToXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {\n        builder.field(INDEX, index);\n        builder.field(TYPE, type);\n        builder.field(ID, id);\n        builder.field(VERSION, version);\n\n        if (shards != null && !shards.isEmpty()) {\n            builder.field(SHARDS, shards);\n        }\n        builder.field(RESULT, result.getLowercase());\n        if (forcedRefresh) {\n            builder.field(FORCED_REFRESH, true);\n        }\n\n        if (getSeqNo() >= 0) {\n            builder.field(SEQ_NO, getSeqNo());\n            builder.field(PRIMARY_TERM, getPrimaryTerm());\n        }\n\n        return builder;\n    }\n\n    protected static void parseInnerToXContent(XContentParser parser, Builder context) throws IOException {\n        XContentParser.Token token = parser.currentToken();\n        XContentParserUtils.ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);\n\n        String currentFieldName = parser.currentName();\n        token = parser.nextToken();\n\n        if (token.isValue()) {\n            if (INDEX.equals(currentFieldName)) {\n                // index uuid and shard id are unknown and can't be parsed back for now.\n                context.setIndex(parser.text());\n            } else if (TYPE.equals(currentFieldName)) {\n                context.setType(parser.text());\n            } else if (ID.equals(currentFieldName)) {\n                context.setId(parser.text());\n            } else if (VERSION.equals(currentFieldName)) {\n                context.setVersion(parser.longValue());\n            } else if (RESULT.equals(currentFieldName)) {\n                resultDeal(parser, context);\n            } else if (FORCED_REFRESH.equals(currentFieldName)) {\n                context.setForcedRefresh(parser.booleanValue());\n            } else if (SEQ_NO.equals(currentFieldName)) {\n                context.setSeqNo(parser.longValue());\n            } else if (PRIMARY_TERM.equals(currentFieldName)) {\n                context.setPrimaryTerm(parser.longValue());\n            } else if (FOUND.equals(currentFieldName)) {\n                context.setFound(parser.booleanValue());\n            } else if (CREATED.equals(currentFieldName)) {\n                context.setCreated(parser.booleanValue());\n            }\n        } else if (token == XContentParser.Token.START_OBJECT) {\n            startObjDeal(parser, context, currentFieldName);\n        } else if (token == XContentParser.Token.START_ARRAY) {\n            parser.skipChildren(); // skip potential inner arrays for forward compatibility\n        }\n    }\n\n    private static void startObjDeal(XContentParser parser, Builder context, String currentFieldName) throws IOException {\n        if (SHARDS.equals(currentFieldName)) {\n            context.setShards(parser.map());\n        } else {\n            parser.skipChildren(); // skip potential inner objects for forward compatibility\n        }\n    }\n\n    private static void resultDeal(XContentParser parser, Builder context) throws IOException {\n        String result = parser.text();\n        for (Result r :  Result.values()) {\n            if (r.getLowercase().equals(result)) {\n                context.setResult(r);\n                break;\n            }\n        }\n    }\n\n    public abstract static class Builder {\n        protected String index = null;\n        protected String type = null;\n        protected String id = null;\n        protected Long version = null;\n        protected Result result = null;\n        protected boolean forcedRefresh;\n        protected Long seqNo = 0L;\n        protected Long primaryTerm = 0L;\n\n        protected boolean found;\n        protected boolean created;\n\n        protected Map<String, Object> shards = null;\n\n        public String getIndex() {\n            return index;\n        }\n\n        public void setIndex(String index) {\n            this.index = index;\n        }\n\n        public String getId() {\n            return id;\n        }\n\n        public void setId(String id) {\n            this.id = id;\n        }\n\n        public String getType() {\n            return type;\n        }\n\n        public void setType(String type) {\n            this.type = type;\n        }\n\n        public void setVersion(Long version) {\n            this.version = version;\n        }\n\n        public void setResult(Result result) {\n            this.result = result;\n        }\n\n        public void setForcedRefresh(boolean forcedRefresh) {\n            this.forcedRefresh = forcedRefresh;\n        }\n\n        public void setSeqNo(Long seqNo) {\n            this.seqNo = seqNo;\n        }\n\n        public void setPrimaryTerm(Long primaryTerm) {\n            this.primaryTerm = primaryTerm;\n        }\n\n        public Map<String, Object> getShards() {\n            return shards;\n        }\n\n        public void setShards(Map<String, Object> shards) {\n            this.shards = shards;\n        }\n\n        public boolean getFound() {\n            return found;\n        }\n\n        public void setFound(boolean found) {\n            this.found = found;\n        }\n\n        public boolean getCreated() {\n            return created;\n        }\n\n        public void setCreated(boolean created) {\n            this.created = created;\n        }\n\n        public abstract DocWriteResponse build();\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESBaseReplicationRequest.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport org.elasticsearch.common.unit.TimeValue;\n\npublic abstract class ESBaseReplicationRequest<T extends ESBaseReplicationRequest<T>> extends ESActionRequest<T> {\n    protected TimeValue timeout;\n\n    protected String index;\n\n    protected String waitForActiveShards;\n\n    protected String consistencyLevel;\n\n    protected String refresh;\n\n    /**\n     * A timeout to wait if the index operation can't be performed immediately. Defaults to <tt>1m</tt>.\n     */\n    @SuppressWarnings(\"unchecked\")\n    public final T timeout(TimeValue timeout) {\n        this.timeout = timeout;\n        return (T) this;\n    }\n\n    /**\n     * A timeout to wait if the index operation can't be performed immediately. Defaults to <tt>1m</tt>.\n     */\n    public final T timeout(String timeout) {\n        return timeout(TimeValue.parseTimeValue(timeout, null, getClass().getSimpleName() + \".timeout\"));\n    }\n\n    public TimeValue timeout() {\n        return timeout;\n    }\n\n    public String index() {\n        return this.index;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public final T index(String index) {\n        this.index = index;\n        return (T) this;\n    }\n\n    public String getIndex() {\n        return index;\n    }\n\n    public void setIndex(String index) {\n        this.index = index;\n    }\n\n    public String getWaitForActiveShards() {\n        return waitForActiveShards;\n    }\n\n    public void setWaitForActiveShards(String waitForActiveShards) {\n        this.waitForActiveShards = waitForActiveShards;\n    }\n\n    public String getConsistencyLevel() {\n        return consistencyLevel;\n    }\n\n    public void setConsistencyLevel(String consistencyLevel) {\n        this.consistencyLevel = consistencyLevel;\n    }\n\n    public String getRefresh() {\n        return refresh;\n    }\n\n    public void setRefresh(String refresh) {\n        this.refresh = refresh;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESDeleteAction.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESDeleteAction extends Action<ESDeleteRequest, ESDeleteResponse, ESDeleteRequestBuilder> {\n    public static final ESDeleteAction INSTANCE = new ESDeleteAction();\n    public static final String NAME = \"indices:data/write/delete\";\n\n    private ESDeleteAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESDeleteResponse newResponse() {\n        return new ESDeleteResponse();\n    }\n\n    @Override\n    public ESDeleteRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESDeleteRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESDeleteRequest.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.RequestConverters;\nimport org.apache.http.client.methods.HttpDelete;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.common.lucene.uid.Versions;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\nimport org.elasticsearch.index.VersionType;\n\npublic class ESDeleteRequest extends ESBaseReplicationRequest<ESDeleteRequest> {\n    private String type;\n    private String id;\n    @Nullable\n    private String routing;\n    @Nullable\n    private String parent;\n    private long version = Versions.MATCH_ANY;\n    private VersionType versionType = VersionType.INTERNAL;\n\n    public ESDeleteRequest() {\n        // pass\n    }\n\n    /**\n     * The type of the document to delete.\n     */\n    public String type() {\n        return type;\n    }\n\n    /**\n     * Sets the type of the document to delete.\n     */\n    public ESDeleteRequest type(String type) {\n        this.type = type;\n        return this;\n    }\n\n    /**\n     * The id of the document to delete.\n     */\n    public String id() {\n        return id;\n    }\n\n    /**\n     * Sets the id of the document to delete.\n     */\n    public ESDeleteRequest id(String id) {\n        this.id = id;\n        return this;\n    }\n\n    /**\n     * @return The parent for this request.\n     */\n    public String parent() {\n        return parent;\n    }\n\n    /**\n     * Sets the parent id of this document.\n     */\n    public ESDeleteRequest parent(String parent) {\n        this.parent = parent;\n        return this;\n    }\n\n    /**\n     * Controls the shard routing of the request. Using this value to hash the shard\n     * and not the id.\n     */\n    public ESDeleteRequest routing(String routing) {\n        if (routing != null && routing.length() == 0) {\n            this.routing = null;\n        } else {\n            this.routing = routing;\n        }\n        return this;\n    }\n\n    /**\n     * Controls the shard routing of the delete request. Using this value to hash the shard\n     * and not the id.\n     */\n    public String routing() {\n        return this.routing;\n    }\n\n    public ESDeleteRequest version(long version) {\n        this.version = version;\n        return this;\n    }\n\n    public long version() {\n        return this.version;\n    }\n\n    public ESDeleteRequest versionType(VersionType versionType) {\n        this.versionType = versionType;\n        return this;\n    }\n\n    public VersionType versionType() {\n        return this.versionType;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = RequestConverters.endpoint(index(), type(), id());\n        RestRequest request = new RestRequest(HttpDelete.METHOD_NAME, endpoint);\n\n        RequestConverters.Params parameters = new RequestConverters.Params(request);\n        parameters.withRouting(routing());\n        parameters.withParent(parent());\n        parameters.withTimeout(timeout());\n        parameters.withVersion(version());\n        parameters.withVersionType(versionType());\n        parameters.withWaitForActiveShards(getWaitForActiveShards());\n        return request;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        XContentParser parser = JsonXContent.jsonXContent.createParser(response.getResponseContent());\n        return ESDeleteResponse.fromXContent(parser);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESDeleteRequestBuilder.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESDeleteRequestBuilder extends ActionRequestBuilder<ESDeleteRequest, ESDeleteResponse, ESDeleteRequestBuilder> {\n    public ESDeleteRequestBuilder(ElasticsearchClient client, ESDeleteAction action) {\n        super(client, action, new ESDeleteRequest());\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESDeleteResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentParser;\n\nimport java.io.IOException;\n\npublic class ESDeleteResponse extends DocWriteResponse implements ToXContent {\n    public static ESDeleteResponse fromXContent(XContentParser parser) throws IOException {\n        XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);\n\n        Builder context = new Builder();\n        while (parser.nextToken() != XContentParser.Token.END_OBJECT) {\n            parseInnerToXContent(parser, context);\n        }\n        return context.build();\n    }\n\n    public ESDeleteResponse() {\n    }\n\n    private ESDeleteResponse(String index, String type, String id, long seqNo, long primaryTerm, long version, Result result, boolean found, boolean created) {\n        super(index, type, id, seqNo, primaryTerm, version, result, found, created);\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.startObject();\n        interToXContent(builder, params);\n        boolean res = false;\n        if (result == Result.DELETED) {\n            res = true;\n        }\n        builder.field(FOUND, res);\n        builder.endObject();\n        return builder;\n    }\n\n    public static class Builder extends DocWriteResponse.Builder {\n\n        @Override\n        public ESDeleteResponse build() {\n            ESDeleteResponse esDeleteResponse = new ESDeleteResponse(index, type, id, seqNo, primaryTerm, version, result, found, created);\n            esDeleteResponse.setForcedRefresh(forcedRefresh);\n            if (shards != null) {\n                esDeleteResponse.setShards(shards);\n            }\n\n            if (result == null) {\n                if (found) {\n                    result = Result.DELETED;\n                } else {\n                    result = Result.NOT_FOUND;\n                }\n\n                esDeleteResponse.setResult(result);\n            }\n\n            return esDeleteResponse;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESGetAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n\npublic class ESGetAction extends Action<ESGetRequest, ESGetResponse, ESGetRequestBuilder> {\n\n    public static final ESGetAction INSTANCE = new ESGetAction();\n    public static final String NAME = \"indices:data/read/get\";\n\n    private ESGetAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESGetResponse newResponse() {\n        return new ESGetResponse();\n    }\n\n    @Override\n    public ESGetRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESGetRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESGetRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.RequestConverters;\nimport org.apache.http.client.methods.HttpGet;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.common.lucene.uid.Versions;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\nimport org.elasticsearch.index.VersionType;\nimport org.elasticsearch.search.fetch.source.FetchSourceContext;\n\npublic class ESGetRequest extends ESActionRequest<ESGetRequest> {\n\n    private String index;\n    private String type;\n    private String id;\n    private String routing;\n    private String preference;\n\n    private String[] fields;\n\n    private FetchSourceContext fetchSourceContext;\n\n    private String refresh;\n\n    Boolean realtime;\n\n    private VersionType versionType = VersionType.INTERNAL;\n    private long version = Versions.MATCH_ANY;\n    private boolean ignoreErrorsOnGeneratedFields;\n\n    private String parent;\n\n    private String[] storedFields;\n\n    public ESGetRequest() {\n        type = \"_all\";\n    }\n\n    /**\n     * Copy constructor that creates a new get request that is a copy of the one provided as an argument.\n     * The new request will inherit though headers and context from the original request that caused it.\n     */\n    public ESGetRequest(ESGetRequest getRequest) {\n        this.index = getRequest.index;\n        this.type = getRequest.type;\n        this.id = getRequest.id;\n        this.routing = getRequest.routing;\n        this.preference = getRequest.preference;\n        this.fields = getRequest.fields;\n        this.fetchSourceContext = getRequest.fetchSourceContext;\n        this.refresh = getRequest.refresh;\n        this.realtime = getRequest.realtime;\n        this.version = getRequest.version;\n        this.versionType = getRequest.versionType;\n        this.ignoreErrorsOnGeneratedFields = getRequest.ignoreErrorsOnGeneratedFields;\n    }\n\n    /**\n     * Constructs a new get request against the specified index. The {@link #type(String)} and {@link #id(String)}\n     * must be set.\n     */\n    public ESGetRequest(String index) {\n        this.index = index;\n        this.type = \"_all\";\n    }\n\n    /**\n     * Constructs a new get request against the specified index with the type and id.\n     *\n     * @param index The index to get the document from\n     * @param type  The type of the document\n     * @param id    The id of the document\n     */\n    public ESGetRequest(String index, String type, String id) {\n        this.index = index;\n        this.type = type;\n        this.id = id;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        RestRequest request = new RestRequest(HttpGet.METHOD_NAME, RequestConverters.endpoint(this.index(), this.type(), this.id()));\n\n        RequestConverters.Params parameters = new RequestConverters.Params(request);\n        parameters.withPreference(this.preference());\n        parameters.withRouting(this.routing());\n        parameters.withParent(this.parent());\n        parameters.withRefresh(this.refresh());\n        parameters.withRealtime(this.realtime());\n        parameters.withStoredFields(this.storedFields());\n        parameters.withVersion(this.version());\n        parameters.withVersionType(this.versionType());\n        parameters.withFetchSourceContext(this.fetchSourceContext());\n        parameters.withFields(this.fields());\n\n        return request;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        XContentParser parser = JsonXContent.jsonXContent.createParser(response.getResponseStream());\n        return ESGetResponse.fromXContent(parser);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    public String index() {\n        return index;\n    }\n\n    public ESGetRequest index(String index) {\n        this.index = index;\n        return this;\n    }\n\n    /**\n     * Sets the type of the document to fetch.\n     */\n    public ESGetRequest type(@Nullable String type) {\n        if (type == null) {\n            type = \"_all\";\n        }\n        this.type = type;\n        return this;\n    }\n\n    /**\n     * Sets the id of the document to fetch.\n     */\n    public ESGetRequest id(String id) {\n        this.id = id;\n        return this;\n    }\n\n    /**\n     * Controls the shard routing of the request. Using this value to hash the shard\n     * and not the id.\n     */\n    public ESGetRequest routing(String routing) {\n        this.routing = routing;\n        return this;\n    }\n\n    /**\n     * Sets the preference to execute the search. Defaults to randomize across shards. Can be set to\n     * <tt>_local</tt> to prefer local shards, <tt>_primary</tt> to execute only on primary shards, or\n     * a custom value, which guarantees that the same order will be used across different requests.\n     */\n    public ESGetRequest preference(String preference) {\n        this.preference = preference;\n        return this;\n    }\n\n    public String type() {\n        return type;\n    }\n\n    public String id() {\n        return id;\n    }\n\n    public String routing() {\n        return this.routing;\n    }\n\n    public String preference() {\n        return this.preference;\n    }\n\n    /**\n     * Allows setting the {@link FetchSourceContext} for this request, controlling if and how _source should be returned.\n     */\n    public ESGetRequest fetchSourceContext(FetchSourceContext context) {\n        this.fetchSourceContext = context;\n        return this;\n    }\n\n    public FetchSourceContext fetchSourceContext() {\n        return fetchSourceContext;\n    }\n\n    /**\n     * Explicitly specify the fields that will be returned. By default, the <tt>_source</tt>\n     * field will be returned.\n     */\n    public ESGetRequest fields(String... fields) {\n        this.fields = fields;\n        return this;\n    }\n\n    /**\n     * Explicitly specify the fields that will be returned. By default, the <tt>_source</tt>\n     * field will be returned.\n     */\n    public String[] fields() {\n        return this.fields;\n    }\n\n    public ESGetRequest refresh(String refresh) {\n        this.refresh = refresh;\n        return this;\n    }\n\n    public String refresh() {\n        return this.refresh;\n    }\n\n    public boolean realtime() {\n        return this.realtime == null || this.realtime;\n    }\n\n    public ESGetRequest realtime(Boolean realtime) {\n        this.realtime = realtime;\n        return this;\n    }\n\n    /**\n     * Sets the version, which will cause the get operation to only be performed if a matching\n     * version exists and no changes happened on the doc since then.\n     */\n    public long version() {\n        return version;\n    }\n\n    public ESGetRequest version(long version) {\n        this.version = version;\n        return this;\n    }\n\n    /**\n     * Sets the versioning type. Defaults to {@link VersionType#INTERNAL}.\n     */\n    public ESGetRequest versionType(VersionType versionType) {\n        this.versionType = versionType;\n        return this;\n    }\n\n    public ESGetRequest ignoreErrorsOnGeneratedFields(boolean ignoreErrorsOnGeneratedFields) {\n        this.ignoreErrorsOnGeneratedFields = ignoreErrorsOnGeneratedFields;\n        return this;\n    }\n\n    public VersionType versionType() {\n        return this.versionType;\n    }\n\n    public boolean ignoreErrorsOnGeneratedFields() {\n        return ignoreErrorsOnGeneratedFields;\n    }\n\n    /**\n     * @return The parent for this request.\n     */\n    public String parent() {\n        return parent;\n    }\n\n    /**\n     * Sets the parent id of this document.\n     */\n    public ESGetRequest parent(String parent) {\n        this.parent = parent;\n        return this;\n    }\n\n    /**\n     * Explicitly specify the stored fields that will be returned. By default, the {@code _source}\n     * field will be returned.\n     */\n    public ESGetRequest storedFields(String... fields) {\n        this.storedFields = fields;\n        return this;\n    }\n\n    /**\n     * Explicitly specify the stored fields that will be returned. By default, the {@code _source}\n     * field will be returned.\n     */\n    public String[] storedFields() {\n        return this.storedFields;\n    }\n\n    @Override\n    public String toString() {\n        return \"get [\" + index + \"][\" + type + \"][\" + id + \"]: routing [\" + routing + \"]\";\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESGetRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n * A get request request builder.\n */\npublic class ESGetRequestBuilder extends ActionRequestBuilder<ESGetRequest, ESGetResponse, ESGetRequestBuilder> {\n\n    public ESGetRequestBuilder(ElasticsearchClient client, ESGetAction action) {\n        super(client, action, new ESGetRequest());\n    }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESGetResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.xcontent.*;\nimport org.elasticsearch.index.mapper.internal.SourceFieldMapper;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestResponse;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class ESGetResponse extends ESActionResponse implements ToXContent {\n    /**\n     * 索引名称\n     */\n    private String index;\n    /**\n     * type名称\n     */\n    private String type;\n\n    /**\n     * 主键id\n     */\n    private String id;\n\n    /**\n     * 版本\n     */\n    private long version = -1;\n    /**\n     * 得分\n     */\n    private boolean exists;\n    /**\n     * source\n     */\n    private Map<String, Object> source;\n\n    private Map<String, List<Object>> fields;\n\n    private Map<String, Object> otherFields = new HashMap<>();\n\n    public ESGetResponse() {\n        // pass\n    }\n\n    public String getIndex() {\n        return index;\n    }\n\n    public void setIndex(String index) {\n        this.index = index;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public Map<String, List<Object>> getFields() {\n        return fields;\n    }\n\n    public void setFields(Map<String, List<Object>> fields) {\n        this.fields = fields;\n    }\n\n\n    /**\n     * Does the document exists.\n     */\n    public boolean isExists() {\n        return exists;\n    }\n\n    public void setExists(boolean exists) {\n        this.exists = exists;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public void setId(String id) {\n        this.id = id;\n    }\n\n    public long getVersion() {\n        return version;\n    }\n\n    public void setVersion(long version) {\n        this.version = version;\n    }\n\n    public static ESGetResponse fromXContent(XContentParser parser) throws IOException {\n        XContentParser.Token token = parser.nextToken();\n        XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation);\n\n        return fromXContentEmbedded(parser);\n    }\n\n    public static ESGetResponse fromXContentEmbedded(XContentParser parser) throws IOException {\n        XContentParser.Token token = parser.nextToken();\n        XContentParserUtils.ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);\n        return fromXContentEmbedded(parser, null, null, null);\n    }\n\n    public static ESGetResponse fromXContentEmbedded(XContentParser parser, String index, String type, String id) throws IOException {\n        XContentParser.Token token = parser.currentToken();\n        XContentParserUtils.ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);\n\n        ESGetResponse esGetResponse = new ESGetResponse();\n        esGetResponse.index = index;\n        esGetResponse.type = type;\n        esGetResponse.id = id;\n        String currentFieldName = parser.currentName();\n        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n            if (token == XContentParser.Token.FIELD_NAME) {\n                currentFieldName = parser.currentName();\n            } else if (token.isValue()) {\n                if (INDEX.equals(currentFieldName)) {\n                    esGetResponse.index = parser.text();\n                } else if (TYPE.equals(currentFieldName)) {\n                    esGetResponse.type = parser.text();\n                } else if (ID.equals(currentFieldName)) {\n                    esGetResponse.id = parser.text();\n                }  else if (VERSION.equals(currentFieldName)) {\n                    esGetResponse.version = parser.longValue();\n                } else if (FOUND.equals(currentFieldName)) {\n                    esGetResponse.exists = parser.booleanValue();\n                } else {\n                    esGetResponse.otherFields.put(currentFieldName, parser.objectText());\n                }\n            } else if (token == XContentParser.Token.START_OBJECT) {\n                startObjDeal(parser, esGetResponse, currentFieldName);\n            } else if (token == XContentParser.Token.START_ARRAY) {\n                esGetResponse.otherFields.put(currentFieldName, parser.list());\n            }\n        }\n\n        return esGetResponse;\n    }\n\n    private static void startObjDeal(XContentParser parser, ESGetResponse esGetResponse, String currentFieldName) throws IOException {\n        XContentParser.Token token;\n        if (SourceFieldMapper.NAME.equals(currentFieldName)) {\n            esGetResponse.source = parser.map();\n        } else if (FIELDS.equals(currentFieldName)) {\n            esGetResponse.fields = new HashMap<>();\n            while(parser.nextToken() != XContentParser.Token.END_OBJECT) {\n                String key = parser.currentName();\n                token = parser.nextToken();\n                XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_ARRAY, token, parser::getTokenLocation);\n                esGetResponse.fields.put(key, parser.list());\n            }\n        } else {\n            esGetResponse.otherFields.put(currentFieldName, parser.map());\n        }\n    }\n\n    public Map<String, Object> getSource() {\n        return source;\n    }\n\n    public void setSource(Map<String, Object> source) {\n        this.source = source;\n    }\n\n    public static final String INDEX = \"_index\";\n    public static final String TYPE = \"_type\";\n    public static final String ID = \"_id\";\n    private static final String VERSION = \"_version\";\n    private static final String FOUND = \"found\";\n    private static final String FIELDS = \"fields\";\n    private static final String SOURCE = \"_source\";\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.startObject();\n        builder.field(INDEX, index);\n        builder.field(TYPE, type);\n        builder.field(ID, id);\n        if (isExists()) {\n            if (version != -1) {\n                builder.field(VERSION, version);\n            }\n            toXContentEmbedded(builder, params);\n        } else {\n            builder.field(FOUND, false);\n        }\n        builder.endObject();\n        return builder;\n    }\n\n    public XContentBuilder toXContentEmbedded(XContentBuilder builder, Params params) throws IOException {\n        builder.field(FOUND, exists);\n\n        if (fields != null && !fields.isEmpty()) {\n            builder.field(FIELDS, fields);\n        }\n\n        if (source != null) {\n            builder.field(SOURCE, source);\n        }\n\n        for (Map.Entry<String, Object> entry : otherFields.entrySet()) {\n            builder.field(entry.getKey(), entry.getValue());\n        }\n\n        return builder;\n    }\n\n    @Override\n    public RestResponse buildRestResponse(RestChannel channel) {\n        try {\n            XContentBuilder xContentBuilder = channel.newBuilder();\n            toXContent(xContentBuilder, channel.request());\n            return new BytesRestResponse(getRestStatus(), xContentBuilder);\n        } catch (IOException e) {\n            return new BytesRestResponse(getRestStatus(), XContentType.JSON.restContentType(), toString());\n        }\n    }\n\n    @Override\n    public String toString() {\n        try {\n            XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().prettyPrint();\n            toXContent(xContentBuilder, EMPTY_PARAMS);\n            return xContentBuilder.string();\n        } catch (IOException e) {\n            return \"{ \\\"error\\\" : \\\"\" + e.getMessage() + \"\\\"}\";\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESIndexAction.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndexAction extends Action<ESIndexRequest, ESIndexResponse, ESIndexRequestBuilder> {\n    public static final ESIndexAction INSTANCE = new ESIndexAction();\n    public static final String NAME = \"indices:data/write/index\";\n\n    private ESIndexAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndexResponse newResponse() {\n        return new ESIndexResponse();\n    }\n\n    @Override\n    public ESIndexRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndexRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESIndexRequest.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.RequestConverters;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.client.methods.HttpPut;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.action.index.IndexRequest.OpType;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.lucene.uid.Versions;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\nimport org.elasticsearch.index.VersionType;\n\nimport java.util.Locale;\n\npublic class ESIndexRequest extends ESBaseReplicationRequest<ESIndexRequest> {\n    private String type;\n    private String id;\n    @Nullable\n    private String routing;\n    @Nullable\n    private String parent;\n\n    private BytesReference source;\n\n    private OpType opType = OpType.INDEX;\n\n    private long version = Versions.MATCH_ANY;\n    private VersionType versionType = VersionType.INTERNAL;\n\n    private String pipeline;\n\n    public ESIndexRequest() {\n        // pass\n    }\n\n    public String index() {\n        return index;\n    }\n\n    /**\n     * The type of the indexed document.\n     */\n    public String type() {\n        return type;\n    }\n\n    /**\n     * Sets the type of the indexed document.\n     */\n    public ESIndexRequest type(String type) {\n        this.type = type;\n        return this;\n    }\n\n    /**\n     * The id of the indexed document. If not set, will be automatically generated.\n     */\n    public String id() {\n        return id;\n    }\n\n    /**\n     * Sets the id of the indexed document. If not set, will be automatically generated.\n     */\n    public ESIndexRequest id(String id) {\n        this.id = id;\n        return this;\n    }\n\n    /**\n     * Controls the shard routing of the request. Using this value to hash the shard\n     * and not the id.\n     */\n    public ESIndexRequest routing(String routing) {\n        if (routing != null && routing.length() == 0) {\n            this.routing = null;\n        } else {\n            this.routing = routing;\n        }\n        return this;\n    }\n\n    /**\n     * Controls the shard routing of the request. Using this value to hash the shard\n     * and not the id.\n     */\n    public String routing() {\n        return this.routing;\n    }\n\n    /**\n     * Sets the parent id of this document.\n     */\n    public ESIndexRequest parent(String parent) {\n        this.parent = parent;\n        return this;\n    }\n\n    public String parent() {\n        return this.parent;\n    }\n\n    /**\n     * The source of the document to index, recopied to a new array if it is unsafe.\n     */\n    public BytesReference source() {\n        return source;\n    }\n\n    public ESIndexRequest source(String source) {\n        this.source = new BytesArray(source);\n        return this;\n    }\n\n    public ESIndexRequest source(BytesReference source) {\n        this.source = source;\n        return this;\n    }\n\n    /**\n     * Sets the type of operation to perform.\n     */\n    public ESIndexRequest opType(OpType opType) {\n        if (opType != OpType.CREATE && opType != OpType.INDEX) {\n            throw new IllegalArgumentException(\"opType must be 'create' or 'index', found: [\" + opType + \"]\");\n        }\n        this.opType = opType;\n        return this;\n    }\n\n    /**\n     * Sets a string representation of the {@link #opType(OpType)}. Can\n     * be either \"index\" or \"create\".\n     */\n    public ESIndexRequest opType(String opType) {\n        String op = opType.toLowerCase(Locale.ROOT);\n        if (op.equals(\"create\")) {\n            opType(OpType.CREATE);\n        } else if (op.equals(\"index\")) {\n            opType(OpType.INDEX);\n        } else {\n            throw new IllegalArgumentException(\"opType must be 'create' or 'index', found: [\" + opType + \"]\");\n        }\n        return this;\n    }\n\n\n    /**\n     * Set to {@code true} to force this index to use {@link OpType#CREATE}.\n     */\n    public ESIndexRequest create(boolean create) {\n        if (create) {\n            return opType(OpType.CREATE);\n        } else {\n            return opType(OpType.INDEX);\n        }\n    }\n\n    public OpType opType() {\n        return this.opType;\n    }\n\n    public ESIndexRequest version(long version) {\n        this.version = version;\n        return this;\n    }\n\n    /**\n     * Returns stored version. If currently stored version is {@link Versions#MATCH_ANY} and\n     * opType is {@link OpType#CREATE}, returns {@link Versions#MATCH_ANY}.\n     */\n    public long version() {\n        return resolveVersionDefaults();\n    }\n\n    /**\n     * Resolves the version based on operation type {@link #opType()}.\n     */\n    private long resolveVersionDefaults() {\n        if (opType == OpType.CREATE && version == Versions.MATCH_ANY) {\n            return Versions.MATCH_ANY;\n        } else {\n            return version;\n        }\n    }\n\n    public ESIndexRequest versionType(VersionType versionType) {\n        this.versionType = versionType;\n        return this;\n    }\n\n    public VersionType versionType() {\n        return this.versionType;\n    }\n\n    public RestRequest toRequest() throws Exception {\n        String method = Strings.hasLength(id()) ? HttpPut.METHOD_NAME : HttpPost.METHOD_NAME;\n        boolean isCreate = (opType() == OpType.CREATE);\n        String endpoint = RequestConverters.endpoint(index(), type(), id(), isCreate ? \"_create\" : null);\n        RestRequest request = new RestRequest(method, endpoint);\n\n        RequestConverters.Params parameters = new RequestConverters.Params(request);\n        parameters.withRouting(routing());\n        parameters.withParent(parent());\n        parameters.withTimeout(timeout());\n        parameters.withVersion(version());\n        parameters.withVersionType(versionType());\n        parameters.withWaitForActiveShards(getWaitForActiveShards());\n        parameters.withConsistency(getConsistencyLevel());\n        parameters.withPipeline(getPipeline());\n        parameters.withRefresh(getRefresh());\n\n        request.setBody(source());\n\n        return request;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        XContentParser parser = JsonXContent.jsonXContent.createParser(response.getResponseContent());\n        return ESIndexResponse.fromXContent(parser);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    public String getPipeline() {\n        return pipeline;\n    }\n\n    public void setPipeline(String pipeline) {\n        this.pipeline = pipeline;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESIndexRequestBuilder.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndexRequestBuilder  extends ActionRequestBuilder<ESIndexRequest, ESIndexResponse, ESIndexRequestBuilder> {\n    public ESIndexRequestBuilder(ElasticsearchClient client, ESIndexAction action) {\n        super(client, action, new ESIndexRequest());\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESIndexResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentParser;\n\nimport java.io.IOException;\n\npublic class ESIndexResponse extends DocWriteResponse implements ToXContent {\n\n    public ESIndexResponse() {}\n\n    private ESIndexResponse(String index, String type, String id, long seqNo, long primaryTerm, long version, Result result, boolean found, boolean created) {\n        super(index, type, id, seqNo, primaryTerm, version, result, found, created);\n    }\n\n    public static ESIndexResponse fromXContent(XContentParser parser) throws IOException {\n        XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);\n\n        Builder context = new Builder();\n        while (parser.nextToken() != XContentParser.Token.END_OBJECT) {\n            parseInnerToXContent(parser, context);\n        }\n        return context.build();\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.startObject();\n        interToXContent(builder, params);\n        boolean res = false;\n        if (result == Result.CREATED) {\n            res = true;\n        }\n        builder.field(CREATED, res);\n        builder.endObject();\n        return builder;\n    }\n\n    public static class Builder extends DocWriteResponse.Builder {\n        @Override\n        public ESIndexResponse build() {\n            ESIndexResponse indexResponse = new ESIndexResponse(index, type, id, seqNo, primaryTerm, version, result, found, created);\n            indexResponse.setForcedRefresh(forcedRefresh);\n            if (shards != null) {\n                indexResponse.setShards(shards);\n            }\n\n            if (result == null) {\n                if (created) {\n                    result = Result.CREATED;\n                } else {\n                    result = Result.UPDATED;\n                }\n\n                indexResponse.setResult(result);\n            }\n\n            return indexResponse;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESMultiGetAction.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESMultiGetAction extends Action<ESMultiGetRequest, ESMultiGetResponse, ESMultiGetBuilder> {\n    public static final ESMultiGetAction INSTANCE = new ESMultiGetAction();\n    public static final String NAME = \"indices:data/internal/mget\";\n\n    private ESMultiGetAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESMultiGetResponse newResponse() {\n        return new ESMultiGetResponse();\n    }\n\n    @Override\n    public ESMultiGetBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESMultiGetBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESMultiGetBuilder.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESMultiGetBuilder extends ActionRequestBuilder<ESMultiGetRequest, ESMultiGetResponse, ESMultiGetBuilder> {\n\n    public ESMultiGetBuilder(ElasticsearchClient client, ESMultiGetAction action) {\n        super(client, action, new ESMultiGetRequest());\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESMultiGetRequest.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.RequestConverters;\nimport org.apache.http.client.methods.HttpPost;\nimport org.elasticsearch.ElasticsearchParseException;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.action.ValidateActions;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.lucene.uid.Versions;\nimport org.elasticsearch.common.xcontent.XContentFactory;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\nimport org.elasticsearch.index.VersionType;\nimport org.elasticsearch.search.fetch.source.FetchSourceContext;\n\nimport java.io.IOException;\nimport java.util.*;\n\npublic class ESMultiGetRequest extends ESActionRequest<ESMultiGetRequest> {\n    private Map<String, String> params = new HashMap<>();\n    private static final String FIELDS = \"fields\";\n    private static final String STORED_FIELDS = \"stored_fields\";\n    private static final String SOURCE = \"_source\";\n\n    /**\n     * A single get item.\n     */\n    public static class Item {\n        private String index;\n        private String type;\n        private String id;\n        private String routing;\n        private String[] fields;\n        private String[] storedFields;\n        private long version = Versions.MATCH_ANY;\n        private VersionType versionType = VersionType.INTERNAL;\n        private FetchSourceContext fetchSourceContext;\n\n        public Item() {\n\n        }\n\n        /**\n         * Constructs a single get item.\n         *\n         * @param index The index name\n         * @param type  The type (can be null)\n         * @param id    The id\n         */\n        public Item(String index, @Nullable String type, String id) {\n            this.index = index;\n            this.type = type;\n            this.id = id;\n        }\n\n        public String index() {\n            return this.index;\n        }\n\n        public Item index(String index) {\n            this.index = index;\n            return this;\n        }\n\n        public String type() {\n            return this.type;\n        }\n\n        public Item type(String type) {\n            this.type = type;\n            return this;\n        }\n\n        public String id() {\n            return this.id;\n        }\n\n        /**\n         * The routing associated with this document.\n         */\n        public Item routing(String routing) {\n            this.routing = routing;\n            return this;\n        }\n\n        public String routing() {\n            return this.routing;\n        }\n\n        public Item parent(String parent) {\n            if (routing == null) {\n                this.routing = parent;\n            }\n            return this;\n        }\n\n        public Item fields(String... fields) {\n            this.fields = fields;\n            return this;\n        }\n\n        public String[] fields() {\n            return this.fields;\n        }\n\n        public Item storedFields(String... storedFields) {\n            this.storedFields = storedFields;\n            return this;\n        }\n\n        public String[] storedFields() {\n            return this.storedFields;\n        }\n\n        public long version() {\n            return version;\n        }\n\n        public Item version(long version) {\n            this.version = version;\n            return this;\n        }\n\n        public VersionType versionType() {\n            return versionType;\n        }\n\n        public Item versionType(VersionType versionType) {\n            this.versionType = versionType;\n            return this;\n        }\n\n        public FetchSourceContext fetchSourceContext() {\n            return this.fetchSourceContext;\n        }\n\n        /**\n         * Allows setting the {@link FetchSourceContext} for this request, controlling if and how _source should be returned.\n         */\n        public Item fetchSourceContext(FetchSourceContext fetchSourceContext) {\n            this.fetchSourceContext = fetchSourceContext;\n            return this;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (!(o instanceof Item)) return false;\n\n            Item item = (Item) o;\n\n            if (version != item.version) return false;\n            if (fetchSourceContext != null ? !fetchSourceContext.equals(item.fetchSourceContext) : item.fetchSourceContext != null)\n                return false;\n            if (!Arrays.equals(fields, item.fields)) return false;\n            if (!id.equals(item.id)) return false;\n            if (!index.equals(item.index)) return false;\n            if (routing != null ? !routing.equals(item.routing) : item.routing != null) return false;\n            if (type != null ? !type.equals(item.type) : item.type != null) return false;\n            if (versionType != item.versionType) return false;\n\n            return true;\n        }\n\n        @Override\n        public int hashCode() {\n            int result = index.hashCode();\n            result = 31 * result + (type != null ? type.hashCode() : 0);\n            result = 31 * result + id.hashCode();\n            result = 31 * result + (routing != null ? routing.hashCode() : 0);\n            result = 31 * result + (fields != null ? Arrays.hashCode(fields) : 0);\n            result = 31 * result + (int) (version ^ (version >>> 32));\n            result = 31 * result + versionType.hashCode();\n            result = 31 * result + (fetchSourceContext != null ? fetchSourceContext.hashCode() : 0);\n            return result;\n        }\n    }\n\n    String preference;\n    Boolean realtime;\n    String refresh;\n    private boolean ignoreErrorsOnGeneratedFields = false;\n\n    List<Item> items = new ArrayList<>();\n\n    public ESMultiGetRequest() {\n        // pass\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        RestRequest request = new RestRequest(HttpPost.METHOD_NAME, \"/_mget\");\n        request.setParams(params);\n\n        RequestConverters.Params parameters = new RequestConverters.Params(request);\n        parameters.withPreference(this.preference());\n        parameters.withRealtime(this.realtime());\n        parameters.withRefresh(this.refresh());\n\n        JSONArray jsonArray = new JSONArray();\n        for (Item item : items) {\n            JSONObject itemJson = new JSONObject();\n            itemJson.put(\"_index\", item.index);\n            itemJson.put(\"_type\", item.type);\n            itemJson.put(\"_id\", item.id);\n\n            if (item.routing != null) {\n                itemJson.put(\"routing\", item.routing);\n            }\n\n            if (item.version != Versions.MATCH_ANY) {\n                itemJson.put(\"version\", item.version);\n            }\n\n            if (item.versionType != null) {\n                itemJson.put(\"version_type\", item.versionType.name().toLowerCase(Locale.ROOT));\n            }\n\n            if (item.fields != null) {\n                itemJson.put(FIELDS, item.fields);\n            }\n\n            if (item.storedFields != null) {\n                itemJson.put(STORED_FIELDS, item.storedFields);\n            }\n\n            if (item.fetchSourceContext != null) {\n                fetchSource(item, itemJson);\n            }\n\n            jsonArray.add(itemJson);\n        }\n\n        JSONObject jsonObject = new JSONObject();\n        jsonObject.put(\"docs\", jsonArray);\n        request.setBody(jsonObject.toJSONString());\n\n        return request;\n    }\n\n    private void fetchSource(Item item, JSONObject itemJson) {\n        if (!item.fetchSourceContext.fetchSource()) {\n            itemJson.put(SOURCE, Boolean.FALSE.toString());\n        } else {\n            JSONObject sourceObj = new JSONObject();\n            if (item.fetchSourceContext.includes() != null && item.fetchSourceContext.includes().length > 0) {\n                JSONArray includes = new JSONArray();\n                for (String include : item.fetchSourceContext.includes()) {\n                    includes.add(include);\n                }\n                sourceObj.put(\"includes\", includes);\n            }\n\n            if (item.fetchSourceContext.excludes() != null && item.fetchSourceContext.excludes().length > 0) {\n                JSONArray excludes = new JSONArray();\n                for (String exclude : item.fetchSourceContext.excludes()) {\n                    excludes.add(exclude);\n                }\n                sourceObj.put(\"excludes\", excludes);\n            }\n\n            itemJson.put(SOURCE, sourceObj);\n        }\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        XContentParser parser = JsonXContent.jsonXContent.createParser(response.getResponseStream());\n        return ESMultiGetResponse.fromXContent(parser);\n    }\n\n    public List<Item> getItems() {\n        return this.items;\n    }\n\n    public ESMultiGetRequest add(Item item) {\n        items.add(item);\n        return this;\n    }\n\n    public ESMultiGetRequest add(String index, @Nullable String type, String id) {\n        items.add(new Item(index, type, id));\n        return this;\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        ActionRequestValidationException validationException = null;\n        if (items.isEmpty()) {\n            validationException = ValidateActions.addValidationError(\"no documents to get\", validationException);\n        } else {\n            for (int i = 0; i < items.size(); i++) {\n                Item item = items.get(i);\n                if (item.index() == null) {\n                    validationException = ValidateActions.addValidationError(\"index is missing for doc \" + i, validationException);\n                }\n                if (item.id() == null) {\n                    validationException = ValidateActions.addValidationError(\"id is missing for doc \" + i, validationException);\n                }\n            }\n        }\n        return validationException;\n    }\n\n    /**\n     * Sets the preference to execute the search. Defaults to randomize across shards. Can be set to\n     * <tt>_local</tt> to prefer local shards, <tt>_primary</tt> to execute only on primary shards, or\n     * a custom value, which guarantees that the same order will be used across different requests.\n     */\n    public ESMultiGetRequest preference(String preference) {\n        this.preference = preference;\n        return this;\n    }\n\n    public String preference() {\n        return this.preference;\n    }\n\n    public boolean realtime() {\n        return this.realtime == null || this.realtime;\n    }\n\n    public ESMultiGetRequest realtime(Boolean realtime) {\n        this.realtime = realtime;\n        return this;\n    }\n\n    public String refresh() {\n        return this.refresh;\n    }\n\n    public ESMultiGetRequest refresh(String refresh) {\n        this.refresh = refresh;\n        return this;\n    }\n\n\n    public ESMultiGetRequest ignoreErrorsOnGeneratedFields(boolean ignoreErrorsOnGeneratedFields) {\n        this.ignoreErrorsOnGeneratedFields = ignoreErrorsOnGeneratedFields;\n        return this;\n    }\n\n    public ESMultiGetRequest add(@Nullable String defaultIndex, @Nullable String defaultType, @Nullable String[] defaultFields, @Nullable FetchSourceContext defaultFetchSource, byte[] data, int from, int length) throws Exception {\n        return add(defaultIndex, defaultType, defaultFields, defaultFetchSource, new BytesArray(data, from, length), true);\n    }\n\n    public ESMultiGetRequest add(@Nullable String defaultIndex, @Nullable String defaultType, @Nullable String[] defaultFields, @Nullable FetchSourceContext defaultFetchSource, BytesReference data) throws Exception {\n        return add(defaultIndex, defaultType, defaultFields, defaultFetchSource, data, true);\n    }\n\n    public ESMultiGetRequest add(@Nullable String defaultIndex, @Nullable String defaultType, @Nullable String[] defaultFields, @Nullable FetchSourceContext defaultFetchSource, BytesReference data, boolean allowExplicitIndex) throws Exception {\n        return add(defaultIndex, defaultType, defaultFields, defaultFetchSource, null, data, allowExplicitIndex);\n    }\n\n    public ESMultiGetRequest add(@Nullable String defaultIndex, @Nullable String defaultType, @Nullable String[] defaultFields, @Nullable FetchSourceContext defaultFetchSource, @Nullable String defaultRouting, BytesReference data, boolean allowExplicitIndex) throws IOException {\n        try (XContentParser parser = XContentFactory.xContent(data).createParser(data)) {\n            XContentParser.Token token;\n            String currentFieldName = null;\n            while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n                if (token == XContentParser.Token.FIELD_NAME) {\n                    currentFieldName = parser.currentName();\n                } else if (token == XContentParser.Token.START_ARRAY) {\n                    if (\"docs\".equals(currentFieldName)) {\n                        parseDocuments(parser, this.items, defaultIndex, defaultType, defaultFields, defaultFetchSource, defaultRouting, allowExplicitIndex);\n                    } else if (\"ids\".equals(currentFieldName)) {\n                        parseIds(parser, this.items, defaultIndex, defaultType, defaultFields, defaultFetchSource, defaultRouting);\n                    }\n                }\n            }\n        }\n        return this;\n    }\n\n    public static void parseDocuments(XContentParser parser, List<Item> items, @Nullable String defaultIndex, @Nullable String defaultType, @Nullable String[] defaultFields, @Nullable FetchSourceContext defaultFetchSource, @Nullable String defaultRouting, boolean allowExplicitIndex) throws IOException {\n        String currentFieldName = null;\n        XContentParser.Token token;\n        while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {\n            if (token != XContentParser.Token.START_OBJECT) {\n                throw new IllegalArgumentException(\"docs array element should include an object\");\n            }\n            String index = defaultIndex;\n            String type = defaultType;\n            String id = null;\n            String routing = defaultRouting;\n            String parent = null;\n            List<String> fields = null;\n            List<String> storedFields = null;\n            long version = Versions.MATCH_ANY;\n            VersionType versionType = VersionType.INTERNAL;\n\n            FetchSourceContext fetchSourceContext = null;\n\n            while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n                if (token == XContentParser.Token.FIELD_NAME) {\n                    currentFieldName = parser.currentName();\n                } else if (token.isValue()) {\n                    if (\"_index\".equals(currentFieldName)) {\n                        if (!allowExplicitIndex) {\n                            throw new IllegalArgumentException(\"explicit index in multi get is not allowed\");\n                        }\n                        index = parser.text();\n                    } else if (\"_type\".equals(currentFieldName)) {\n                        type = parser.text();\n                    } else if (\"_id\".equals(currentFieldName)) {\n                        id = parser.text();\n                    } else if (\"_routing\".equals(currentFieldName) || \"routing\".equals(currentFieldName)) {\n                        routing = parser.text();\n                    } else if (\"_parent\".equals(currentFieldName) || \"parent\".equals(currentFieldName)) {\n                        parent = parser.text();\n                    } else if (FIELDS.equals(currentFieldName)) {\n                        fields = new ArrayList<>();\n                        fields.add(parser.text());\n                    } else if (STORED_FIELDS.equals(currentFieldName)) {\n                        storedFields = new ArrayList<>();\n                        storedFields.add(parser.text());\n                    } else if (\"_version\".equals(currentFieldName) || \"version\".equals(currentFieldName)) {\n                        version = parser.longValue();\n                    } else if (\"_version_type\".equals(currentFieldName) || \"_versionType\".equals(currentFieldName) || \"version_type\".equals(currentFieldName) || \"versionType\".equals(currentFieldName)) {\n                        versionType = VersionType.fromString(parser.text());\n                    } else if (SOURCE.equals(currentFieldName)) {\n                        if (parser.isBooleanValue()) {\n                            fetchSourceContext = new FetchSourceContext(parser.booleanValue());\n                        } else if (token == XContentParser.Token.VALUE_STRING) {\n                            fetchSourceContext = new FetchSourceContext(new String[]{parser.text()});\n                        } else {\n                            throw new ElasticsearchParseException(\"illegal type for _source: [{}]\", token);\n                        }\n                    }\n                } else if (token == XContentParser.Token.START_ARRAY) {\n                    if (FIELDS.equals(currentFieldName)) {\n                        fields = new ArrayList<>();\n                        while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {\n                            fields.add(parser.text());\n                        }\n                    } else if (STORED_FIELDS.equals(currentFieldName)) {\n                        storedFields = new ArrayList<>();\n                        while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {\n                            storedFields.add(parser.text());\n                        }\n                    } else if (SOURCE.equals(currentFieldName)) {\n                        ArrayList<String> includes = new ArrayList<>();\n                        while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {\n                            includes.add(parser.text());\n                        }\n                        fetchSourceContext = new FetchSourceContext(includes.toArray(Strings.EMPTY_ARRAY));\n                    }\n\n                } else if (token == XContentParser.Token.START_OBJECT && SOURCE.equals(currentFieldName)) {\n                    List<String> currentList = new ArrayList<>(), includes = null, excludes = null;\n\n                    while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n                        if (token == XContentParser.Token.FIELD_NAME) {\n                            currentFieldName = parser.currentName();\n                            if (\"includes\".equals(currentFieldName) || \"include\".equals(currentFieldName)) {\n                                currentList = includes != null ? includes : (includes = new ArrayList<>(2));\n                            } else if (\"excludes\".equals(currentFieldName) || \"exclude\".equals(currentFieldName)) {\n                                currentList = excludes != null ? excludes : (excludes = new ArrayList<>(2));\n                            } else {\n                                throw new ElasticsearchParseException(\"source definition may not contain [{}]\", parser.text());\n                            }\n                        } else if (token == XContentParser.Token.START_ARRAY) {\n                            while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {\n                                currentList.add(parser.text());\n                            }\n                        } else if (token.isValue()) {\n                            currentList.add(parser.text());\n                        } else {\n                            throw new ElasticsearchParseException(\"unexpected token while parsing source settings\");\n                        }\n                    }\n\n                    fetchSourceContext = new FetchSourceContext(\n                            includes == null ? Strings.EMPTY_ARRAY : includes.toArray(new String[includes.size()]),\n                            excludes == null ? Strings.EMPTY_ARRAY : excludes.toArray(new String[excludes.size()]));\n                }\n            }\n            String[] aFields;\n            if (fields != null) {\n                aFields = fields.toArray(new String[fields.size()]);\n            } else {\n                aFields = defaultFields;\n            }\n\n            String[] aStoredFields = null;\n            if (storedFields != null) {\n                aStoredFields = storedFields.toArray(new String[storedFields.size()]);\n            }\n\n            items.add(new Item(index, type, id).routing(routing).fields(aFields).storedFields(aStoredFields).parent(parent).version(version).versionType(versionType)\n                    .fetchSourceContext(fetchSourceContext == null ? defaultFetchSource : fetchSourceContext));\n        }\n    }\n\n    public static void parseDocuments(XContentParser parser, List<Item> items) throws IOException {\n        parseDocuments(parser, items, null, null, null, null, null, true);\n    }\n\n    public static void parseIds(XContentParser parser, List<Item> items, @Nullable String defaultIndex, @Nullable String defaultType, @Nullable String[] defaultFields, @Nullable FetchSourceContext defaultFetchSource, @Nullable String defaultRouting) throws IOException {\n        XContentParser.Token token;\n        while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {\n            if (!token.isValue()) {\n                throw new IllegalArgumentException(\"ids array element should only contain ids\");\n            }\n            items.add(new Item(defaultIndex, defaultType, parser.text()).fields(defaultFields).fetchSourceContext(defaultFetchSource).routing(defaultRouting));\n        }\n    }\n\n    public static void parseIds(XContentParser parser, List<Item> items) throws IOException {\n        parseIds(parser, items, null, null, null, null, null);\n    }\n\n    public Map<String, String> getParams() {\n        return params;\n    }\n\n    public void setParams(Map<String, String> params) {\n        this.params = params;\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESMultiGetResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.common.ParseField;\nimport org.elasticsearch.common.xcontent.*;\nimport org.elasticsearch.common.xcontent.XContentParser.Token;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\npublic class ESMultiGetResponse extends ESActionResponse implements ToXContent {\n\n    private static final ParseField INDEX = new ParseField(\"_index\");\n    private static final ParseField TYPE = new ParseField(\"_type\");\n    private static final ParseField ID = new ParseField(\"_id\");\n    private static final ParseField ERROR = new ParseField(\"error\");\n    private static final ParseField DOCS = new ParseField(\"docs\");\n\n    private List<Item> responses;\n\n    public ESMultiGetResponse() {\n        // pass\n    }\n\n    public List<Item> getResponses() {\n        return responses;\n    }\n\n    public void setResponses(List<Item> responses) {\n        this.responses = responses;\n    }\n\n    public static class Failure implements ToXContent {\n\n        private String index;\n        private String type;\n        private String id;\n        private Map<String, Object> exception;\n\n        Failure() {\n        }\n\n        public Failure(String index, String type, String id, Map<String, Object> exception) {\n            this.index = index;\n            this.type = type;\n            this.id = id;\n            this.exception = exception;\n        }\n\n        /**\n         * The index name of the action.\n         */\n        public String getIndex() {\n            return this.index;\n        }\n\n        /**\n         * The type of the action.\n         */\n        public String getType() {\n            return type;\n        }\n\n        /**\n         * The id of the action.\n         */\n        public String getId() {\n            return id;\n        }\n\n        @Override\n        public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n            builder.startObject();\n            builder.field(INDEX.getPreferredName(), index);\n            builder.field(TYPE.getPreferredName(), type);\n            builder.field(ID.getPreferredName(), id);\n            builder.field(ERROR.getPreferredName(), exception);\n            builder.endObject();\n            return builder;\n        }\n\n        public Map<String, Object> getFailure() {\n            return exception;\n        }\n    }\n\n    public static class Item {\n        private ESGetResponse response;\n        private Failure failure;\n\n        Item() {\n\n        }\n\n        public Item(ESGetResponse response, Failure failure) {\n            this.response = response;\n            this.failure = failure;\n        }\n\n        /**\n         * Is it a failed search?\n         */\n        public boolean isFailure() {\n            return failure != null;\n        }\n\n        @Nullable\n        public ESGetResponse getResponse() {\n            return this.response;\n        }\n\n        public Failure getFailure() {\n            return failure;\n        }\n\n        /**\n         * The index name of the document.\n         */\n        public String getIndex() {\n            if (failure != null) {\n                return failure.getIndex();\n            }\n            return response.getIndex();\n        }\n\n        /**\n         * The type of the document.\n         */\n        public String getType() {\n            if (failure != null) {\n                return failure.getType();\n            }\n            return response.getType();\n        }\n\n        /**\n         * The id of the document.\n         */\n        public String getId() {\n            if (failure != null) {\n                return failure.getId();\n            }\n            return response.getId();\n        }\n    }\n\n    public static ESMultiGetResponse fromXContent(XContentParser parser) throws IOException {\n        String currentFieldName = null;\n        List<Item> items = new ArrayList<>();\n        for (Token token = parser.nextToken(); token != Token.END_OBJECT; token = parser.nextToken()) {\n            switch (token) {\n                case FIELD_NAME:\n                    currentFieldName = parser.currentName();\n                    break;\n                case START_ARRAY:\n                    if (DOCS.getPreferredName().equals(currentFieldName)) {\n                        for (token = parser.nextToken(); token != Token.END_ARRAY; token = parser.nextToken()) {\n                            if (token == Token.START_OBJECT) {\n                                items.add(parseItem(parser));\n                            }\n                        }\n                    }\n                    break;\n                default:\n                    // If unknown tokens are encounter then these should be ignored, because\n                    // this is parsing logic on the client side.\n                    break;\n            }\n        }\n        ESMultiGetResponse esMultiGetResponse = new ESMultiGetResponse();\n        esMultiGetResponse.responses = items;\n        return esMultiGetResponse;\n    }\n\n    private static Item parseItem(XContentParser parser) throws IOException {\n        String currentFieldName = null;\n        String index = null;\n        String type = null;\n        String id = null;\n        Map<String, Object> exception = null;\n        ESGetResponse esGetResponse = null;\n        for (Token token = parser.nextToken(); token != Token.END_OBJECT; token = parser.nextToken()) {\n            switch (token) {\n                case FIELD_NAME:\n                    currentFieldName = parser.currentName();\n                    esGetResponse = getEsGetResponse(parser, currentFieldName, index, type, id, esGetResponse);\n                    break;\n                case VALUE_STRING:\n                    if (INDEX.getPreferredName().equals(currentFieldName)) {\n                        index = parser.text();\n                    } else if (TYPE.getPreferredName().equals(currentFieldName)) {\n                        type = parser.text();\n                    } else if (ID.getPreferredName().equals(currentFieldName)) {\n                        id = parser.text();\n                    }\n                    break;\n                case START_OBJECT:\n                    if (ERROR.getPreferredName().equals(currentFieldName)) {\n                        exception = parser.map();\n                    }\n                    break;\n                default:\n                    // If unknown tokens are encounter then these should be ignored, because\n                    // this is parsing logic on the client side.\n                    break;\n            }\n            if (esGetResponse != null) {\n                break;\n            }\n        }\n\n        if (exception != null) {\n            return new Item(null, new Failure(index, type, id, exception));\n        } else {\n            return new Item(esGetResponse, null);\n        }\n    }\n\n    private static ESGetResponse getEsGetResponse(XContentParser parser, String currentFieldName, String index, String type, String id, ESGetResponse esGetResponse) throws IOException {\n        if (!INDEX.getPreferredName().equals(currentFieldName)\n                && !TYPE.getPreferredName().equals(currentFieldName)\n                && !ID.getPreferredName().equals(currentFieldName)\n                && !ERROR.getPreferredName().equals(currentFieldName)) {\n            esGetResponse = ESGetResponse.fromXContentEmbedded(parser, index, type, id);\n        }\n        return esGetResponse;\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.startObject();\n        builder.startArray(DOCS.getPreferredName());\n        for (Item response : responses) {\n            if (response.isFailure()) {\n                Failure failure = response.getFailure();\n                failure.toXContent(builder, params);\n            } else {\n                ESGetResponse getResponse = response.getResponse();\n                getResponse.toXContent(builder, params);\n            }\n        }\n        builder.endArray();\n        builder.endObject();\n        return builder;\n    }\n\n    @Override\n    public org.elasticsearch.rest.RestResponse buildRestResponse(RestChannel channel) {\n        try {\n            XContentBuilder contentBuilder = channel.newBuilder();\n            toXContent(contentBuilder, channel.request());\n            return new BytesRestResponse(getRestStatus(), contentBuilder);\n        } catch (IOException e) {\n            return new BytesRestResponse(getRestStatus(), XContentType.JSON.restContentType(), toString());\n        }\n    }\n\n    @Override\n    public String toString() {\n        try {\n            XContentBuilder contentBuilder = XContentFactory.jsonBuilder().prettyPrint();\n            toXContent(contentBuilder, EMPTY_PARAMS);\n            return contentBuilder.string();\n        } catch (IOException e) {\n            return \"{ \\\"error\\\" : \\\"\" + e.getMessage() + \"\\\"}\";\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESUpdateAction.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESUpdateAction extends Action<ESUpdateRequest, ESUpdateResponse, ESUpdateRequestBuilder> {\n    public static final ESUpdateAction INSTANCE = new ESUpdateAction();\n    public static final String NAME = \"indices:data/write/update\";\n\n    private ESUpdateAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESUpdateResponse newResponse() {\n        return new ESUpdateResponse();\n    }\n\n    @Override\n    public ESUpdateRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESUpdateRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESUpdateRequest.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.RequestConverters;\nimport org.apache.http.client.methods.HttpPost;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.lucene.uid.Versions;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\nimport org.elasticsearch.index.VersionType;\nimport org.elasticsearch.search.fetch.source.FetchSourceContext;\n\npublic class ESUpdateRequest extends ESBaseReplicationRequest<ESUpdateRequest> {\n\n    private String type;\n    private String id;\n    @Nullable\n    private String routing;\n\n    @Nullable\n    private String parent;\n\n    private BytesReference source;\n\n    private String[] fields;\n    private FetchSourceContext fetchSourceContext;\n\n    private long version = Versions.MATCH_ANY;\n    private VersionType versionType = VersionType.INTERNAL;\n    private int retryOnConflict = 0;\n\n    private ESIndexRequest upsertRequest;\n    private String pipeline;\n\n    private boolean scriptedUpsert = false;\n    private boolean docAsUpsert = false;\n    private boolean detectNoop = true;\n\n    public ESUpdateRequest() {\n        // pass\n    }\n\n    /**\n     * The type of the indexed document.\n     */\n    public String type() {\n        return type;\n    }\n\n    /**\n     * Sets the type of the indexed document.\n     */\n    public ESUpdateRequest type(String type) {\n        this.type = type;\n        return this;\n    }\n\n    /**\n     * The id of the indexed document.\n     */\n    public String id() {\n        return id;\n    }\n\n    /**\n     * Sets the id of the indexed document.\n     */\n    public ESUpdateRequest id(String id) {\n        this.id = id;\n        return this;\n    }\n\n    /**\n     * Controls the shard routing of the request. Using this value to hash the shard\n     * and not the id.\n     */\n    public ESUpdateRequest routing(String routing) {\n        if (routing != null && routing.length() == 0) {\n            this.routing = null;\n        } else {\n            this.routing = routing;\n        }\n        return this;\n    }\n\n    /**\n     * Controls the shard routing of the request. Using this value to hash the shard\n     * and not the id.\n     */\n    public String routing() {\n        return this.routing;\n    }\n\n    /**\n     * The parent id is used for the upsert request and also implicitely sets the routing if not already set.\n     */\n    public ESUpdateRequest parent(String parent) {\n        this.parent = parent;\n        if (routing == null) {\n            routing = parent;\n        }\n        return this;\n    }\n\n    public String parent() {\n        return parent;\n    }\n\n    /**\n     * The source of the document to index, recopied to a new array if it is unsafe.\n     */\n    public BytesReference source() {\n        return source;\n    }\n\n    public ESUpdateRequest source(String source) {\n        this.source = new BytesArray(source);\n        return this;\n    }\n\n    public ESUpdateRequest source(BytesReference source) {\n        this.source = source;\n        return this;\n    }\n\n    /**\n     * Indicate that _source should be returned with every hit, with an\n     * \"include\" and/or \"exclude\" set which can include simple wildcard\n     * elements.\n     *\n     * @param include An optional include (optionally wildcarded) pattern to filter\n     *                the returned _source\n     * @param exclude An optional exclude (optionally wildcarded) pattern to filter\n     *                the returned _source\n     */\n    public ESUpdateRequest fetchSource(@Nullable String include, @Nullable String exclude) {\n        FetchSourceContext context = this.fetchSourceContext == null ? FetchSourceContext.FETCH_SOURCE : this.fetchSourceContext;\n        this.fetchSourceContext = new FetchSourceContext(context.fetchSource(), new String[]{include}, new String[]{exclude}, false);\n        return this;\n    }\n\n    /**\n     * Indicate that _source should be returned, with an\n     * \"include\" and/or \"exclude\" set which can include simple wildcard\n     * elements.\n     *\n     * @param includes An optional list of include (optionally wildcarded) pattern to\n     *                 filter the returned _source\n     * @param excludes An optional list of exclude (optionally wildcarded) pattern to\n     *                 filter the returned _source\n     */\n    public ESUpdateRequest fetchSource(@Nullable String[] includes, @Nullable String[] excludes) {\n        FetchSourceContext context = this.fetchSourceContext == null ? FetchSourceContext.FETCH_SOURCE : this.fetchSourceContext;\n        this.fetchSourceContext = new FetchSourceContext(context.fetchSource(), includes, excludes, false);\n        return this;\n    }\n\n    /**\n     * Indicates whether the response should contain the updated _source.\n     */\n    public ESUpdateRequest fetchSource(boolean fetchSource) {\n        FetchSourceContext context = this.fetchSourceContext == null ? FetchSourceContext.FETCH_SOURCE : this.fetchSourceContext;\n        this.fetchSourceContext = new FetchSourceContext(fetchSource, context.includes(), context.excludes(), false);\n        return this;\n    }\n\n    /**\n     * Explicitly set the fetch source context for this request\n     */\n    public ESUpdateRequest fetchSource(FetchSourceContext context) {\n        this.fetchSourceContext = context;\n        return this;\n    }\n\n\n    /**\n     * Get the fields to be returned.\n     *\n     * @deprecated Use {@link ESUpdateRequest#fetchSource()} instead\n     */\n    @Deprecated\n    public String[] fields() {\n        return fields;\n    }\n\n    /**\n     * Gets the {@link FetchSourceContext} which defines how the _source should\n     * be fetched.\n     */\n    public FetchSourceContext fetchSource() {\n        return fetchSourceContext;\n    }\n\n    /**\n     * Sets the number of retries of a version conflict occurs because the document was updated between\n     * getting it and updating it. Defaults to 0.\n     */\n    public ESUpdateRequest retryOnConflict(int retryOnConflict) {\n        this.retryOnConflict = retryOnConflict;\n        return this;\n    }\n\n    public int retryOnConflict() {\n        return this.retryOnConflict;\n    }\n\n    public ESUpdateRequest version(long version) {\n        this.version = version;\n        return this;\n    }\n\n    public long version() {\n        return this.version;\n    }\n\n    public ESUpdateRequest versionType(VersionType versionType) {\n        this.versionType = versionType;\n        return this;\n    }\n\n    public VersionType versionType() {\n        return this.versionType;\n    }\n\n    public boolean docAsUpsert() {\n        return this.docAsUpsert;\n    }\n\n    public ESUpdateRequest docAsUpsert(boolean shouldUpsertDoc) {\n        this.docAsUpsert = shouldUpsertDoc;\n        return this;\n    }\n\n    public boolean scriptedUpsert() {\n        return this.scriptedUpsert;\n    }\n\n    public ESUpdateRequest scriptedUpsert(boolean scriptedUpsert) {\n        this.scriptedUpsert = scriptedUpsert;\n        return this;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint;\n        if (type() == null) {\n            endpoint = RequestConverters.endpoint(index(), \"_update\", id());\n        } else {\n            endpoint = RequestConverters.endpoint(index(), type(), id(), \"_update\");\n        }\n\n        RestRequest request = new RestRequest(HttpPost.METHOD_NAME, endpoint);\n\n        RequestConverters.Params parameters = new RequestConverters.Params(request);\n        parameters.withRouting(routing());\n        parameters.withParent(parent());\n        parameters.withTimeout(timeout());\n        parameters.withWaitForActiveShards(getWaitForActiveShards());\n        parameters.withDocAsUpsert(docAsUpsert());\n        parameters.withFetchSourceContext(fetchSource());\n        parameters.withRetryOnConflict(retryOnConflict());\n        parameters.withVersion(version());\n        parameters.withVersionType(versionType());\n        parameters.withPipeline(getPipeline());\n\n        request.setBody(source);\n        return request;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        XContentParser parser = JsonXContent.jsonXContent.createParser(response.getResponseContent());\n        return ESUpdateResponse.fromXContent(parser);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    public String getPipeline() {\n        return pipeline;\n    }\n\n    public void setPipeline(String pipeline) {\n        this.pipeline = pipeline;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESUpdateRequestBuilder.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESUpdateRequestBuilder extends ActionRequestBuilder<ESUpdateRequest, ESUpdateResponse, ESUpdateRequestBuilder> {\n    public ESUpdateRequestBuilder(ElasticsearchClient client, ESUpdateAction action) {\n        super(client, action, new ESUpdateRequest());\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/document/ESUpdateResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.document;\n\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentParser;\n\nimport java.io.IOException;\n\npublic class ESUpdateResponse extends DocWriteResponse implements ToXContent {\n\n    private static final String GET = \"get\";\n\n    private ESGetResponse esGetResponse;\n\n    public ESUpdateResponse() {}\n\n    private ESUpdateResponse(String index, String type, String id, long seqNo, long primaryTerm, long version, Result result, boolean found, boolean created) {\n        super(index, type, id, seqNo, primaryTerm, version, result, found, created);\n    }\n\n    public ESGetResponse getEsGetResponse() {\n        return esGetResponse;\n    }\n\n    public void setEsGetResponse(ESGetResponse esGetResponse) {\n        this.esGetResponse = esGetResponse;\n    }\n\n    public static ESUpdateResponse fromXContent(XContentParser parser) throws IOException {\n        XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);\n\n        Builder context = new Builder();\n        while (parser.nextToken() != XContentParser.Token.END_OBJECT) {\n            parseXContentFields(parser, context);\n        }\n        return context.build();\n    }\n\n    /**\n     * Parse the current token and update the parsing context appropriately.\n     */\n    public static void parseXContentFields(XContentParser parser, Builder context) throws IOException {\n        XContentParser.Token token = parser.currentToken();\n        String currentFieldName = parser.currentName();\n\n        if (GET.equals(currentFieldName)) {\n            if (token == XContentParser.Token.START_OBJECT) {\n                context.setEsGetResponse(ESGetResponse.fromXContentEmbedded(parser));\n            }\n        } else {\n            parseInnerToXContent(parser, context);\n        }\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.startObject();\n        interToXContent(builder, params);\n        if (esGetResponse != null) {\n            builder.startObject(GET);\n            esGetResponse.toXContentEmbedded(builder, params);\n            builder.endObject();\n        }\n        builder.endObject();\n        return builder;\n    }\n\n    public static class Builder extends DocWriteResponse.Builder {\n\n        private ESGetResponse esGetResponse = null;\n\n        @Override\n        public ESUpdateResponse build() {\n            ESUpdateResponse response = new ESUpdateResponse(index, type, id, seqNo, primaryTerm, version, result, found, created);\n            response.setForcedRefresh(forcedRefresh);\n            response.setEsGetResponse(esGetResponse);\n            if (shards != null) {\n                response.setShards(shards);\n            }\n\n            if (result == null) {\n                response.setResult(Result.UPDATED);\n            }\n            return response;\n        }\n\n        public void setEsGetResponse(ESGetResponse esGetResponse) {\n            this.esGetResponse = esGetResponse;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESClearScrollAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESClearScrollAction extends Action<ESClearScrollRequest, ESClearScrollResponse, ESClearScrollRequestBuilder> {\n\n    public static final ESClearScrollAction INSTANCE = new ESClearScrollAction();\n    public static final String NAME = \"indices:data/read/scroll/clear\";\n\n    private ESClearScrollAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESClearScrollResponse newResponse() {\n        return new ESClearScrollResponse();\n    }\n\n    @Override\n    public ESClearScrollRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESClearScrollRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESClearScrollRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ESClearScrollRequest extends ESActionRequest<ESClearScrollRequest> {\n\n    private List<String> scrollIds = new ArrayList<>();\n\n    public ESClearScrollRequest() {\n        // pass\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endPoint = \"/_search/scroll\";\n\n        JSONObject scrollJs = new JSONObject();\n        scrollJs.put(\"scroll_id\", scrollIds);\n\n\n        RestRequest restRequest = new RestRequest(\"DELETE\", endPoint, null);\n        restRequest.setBody(scrollJs.toJSONString());\n\n        return restRequest;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        XContentParser parser = JsonXContent.jsonXContent.createParser(response.getResponseStream());\n        return ESClearScrollResponse.fromXContent(parser);\n    }\n\n    public List<String> getScrollIds() {\n        return scrollIds;\n    }\n\n    public void setScrollIds(List<String> scrollIds) {\n        this.scrollIds = scrollIds;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESClearScrollRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n * A search request request builder.\n */\npublic class ESClearScrollRequestBuilder extends ActionRequestBuilder<ESClearScrollRequest, ESClearScrollResponse, ESClearScrollRequestBuilder> {\n\n    public ESClearScrollRequestBuilder(ElasticsearchClient client, ESClearScrollAction action) {\n        super(client, action, new ESClearScrollRequest());\n    }\n\n    @Override\n    public ESClearScrollRequest request() {\n        return request;\n    }\n\n    @Override\n    protected ESClearScrollRequest beforeExecute(ESClearScrollRequest request) {\n        return request;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESClearScrollResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.action.search.ClearScrollResponse;\nimport org.elasticsearch.common.ParseField;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentFactory;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.XContentParser.Token;\n\nimport java.io.IOException;\n\npublic class ESClearScrollResponse extends ESActionResponse implements ToXContent {\n    private static final ParseField SUCCEEDED = new ParseField(\"succeeded\");\n    private static final ParseField NUMFREED = new ParseField(\"num_freed\");\n\n    private boolean succeeded;\n    private int numFreed;\n\n    public ESClearScrollResponse() {\n        // pass\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.startObject();\n        builder.field(SUCCEEDED.getPreferredName(), succeeded);\n        builder.field(NUMFREED.getPreferredName(), numFreed);\n        builder.endObject();\n        return builder;\n    }\n\n    /**\n     * Parse the clear scroll response body into a new {@link ClearScrollResponse} object\n     */\n    public static ESClearScrollResponse fromXContent(XContentParser parser) throws IOException {\n        XContentParserUtils.ensureExpectedToken(Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);\n        String currentFieldName = parser.currentName();\n\n        ESClearScrollResponse esClearScrollResponse = new ESClearScrollResponse();\n        for (Token token = parser.nextToken(); token != Token.END_OBJECT; token = parser.nextToken()) {\n            if (token == Token.FIELD_NAME) {\n                currentFieldName = parser.currentName();\n            } else if (token.isValue()) {\n                if (SUCCEEDED.getPreferredName().equals(currentFieldName)) {\n                    esClearScrollResponse.succeeded = parser.booleanValue();\n                } else if (NUMFREED.getPreferredName().equals(currentFieldName)) {\n                    esClearScrollResponse.numFreed = parser.intValue();\n                } else {\n                    parser.skipChildren();\n                }\n            } else if (token == Token.START_OBJECT) {\n                parser.skipChildren();\n            }\n        }\n\n        return  esClearScrollResponse;\n    }\n\n    @Override\n    public String toString() {\n        try {\n            XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();\n            toXContent(builder, EMPTY_PARAMS);\n            return builder.string();\n        } catch (IOException e) {\n            return \"{ \\\"error\\\" : \\\"\" + e.getMessage() + \"\\\"}\";\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESMultiSearchAction.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESMultiSearchAction extends Action<ESMultiSearchRequest, ESMultiSearchResponse, ESMultiSearchBuilder> {\n    public static final ESMultiSearchAction INSTANCE = new ESMultiSearchAction();\n    public static final String NAME = \"indices:data/internal/msearch\";\n\n    private ESMultiSearchAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESMultiSearchResponse newResponse() {\n        return new ESMultiSearchResponse();\n    }\n\n    @Override\n    public ESMultiSearchBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESMultiSearchBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESMultiSearchBuilder.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESMultiSearchBuilder extends ActionRequestBuilder<ESMultiSearchRequest, ESMultiSearchResponse, ESMultiSearchBuilder> {\n    protected ESMultiSearchBuilder(ElasticsearchClient client, Action<ESMultiSearchRequest, ESMultiSearchResponse, ESMultiSearchBuilder> action, ESMultiSearchRequest request) {\n        super(client, action, request);\n    }\n\n    public ESMultiSearchBuilder(ElasticsearchClient client, ESMultiSearchAction action) {\n        super(client, action, new ESMultiSearchRequest());\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESMultiSearchRequest.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.action.support.IndicesOptions;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.xcontent.XContent;\nimport org.elasticsearch.common.xcontent.XContentFactory;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\nimport org.jboss.netty.handler.codec.http.HttpMethod;\n\nimport java.io.IOException;\nimport java.util.*;\n\nimport static org.elasticsearch.common.xcontent.support.XContentMapValues.*;\n\npublic class ESMultiSearchRequest extends ESActionRequest<ESMultiSearchRequest> {\n\n    private Map<String, String> params = new HashMap<>();\n\n    private List<ESSearchRequest> requests = new ArrayList<>();\n\n    private boolean isTemplateRequest;\n\n    private final String endpoint;\n\n    public ESMultiSearchRequest() {\n        this.endpoint = \"/_msearch\";\n    }\n\n    public ESMultiSearchRequest(String endpoint) {\n        this.endpoint = endpoint;\n    }\n\n    private static final String SEARCH_TYPE = \"search_type\";\n\n    private static final String REQUEST_CACHE = \"request_cache\";\n\n    private static final String PREFERENCE = \"preference\";\n\n    private static final String ROUTING = \"routing\";\n\n\n    /**\n     * Add a search request to execute. Note, the order is important, the search response will be returned in the\n     * same order as the search requests.\n     */\n    public ESMultiSearchRequest add(ESSearchRequest request) {\n        requests.add(request);\n        return this;\n    }\n\n    public ESMultiSearchRequest add(BytesReference data, boolean isTemplateRequest, @Nullable String[] indices, @Nullable String[] types, @Nullable String searchType, @Nullable String routing, IndicesOptions indicesOptions, boolean allowExplicitIndex) throws IOException {\n        XContent xContent = XContentFactory.xContent(data);\n        int from = 0;\n        int length = data.length();\n        byte marker = xContent.streamSeparator();\n        while (true) {\n            int nextMarker = findNextMarker(marker, from, data, length);\n            if (nextMarker == -1) {\n                break;\n            }\n            // support first line with \\n\n            if (nextMarker == 0) {\n                from = nextMarker + 1;\n                continue;\n            }\n\n            ESSearchRequest esSearchRequest = new ESSearchRequest();\n            setValue(indices, types, searchType, routing, indicesOptions, esSearchRequest);\n\n            IndicesOptions defaultOptions = IndicesOptions.strictExpandOpenAndForbidClosed();\n\n\n            // now parse the action\n            if (nextMarker - from > 0) {\n                try (XContentParser parser = xContent.createParser(data.slice(from, nextMarker - from))) {\n                    Map<String, Object> source = parser.map();\n                    sourceParser(allowExplicitIndex, esSearchRequest, source);\n                    defaultOptions = IndicesOptions.fromMap(source, defaultOptions);\n                }\n            }\n            esSearchRequest.indicesOptions(defaultOptions);\n\n            // move pointers\n            from = nextMarker + 1;\n            // now for the body\n            nextMarker = findNextMarker(marker, from, data, length);\n            if (nextMarker == -1) {\n                break;\n            }\n\n            esSearchRequest.source(data.slice(from, nextMarker - from));\n\n            // move pointers\n            from = nextMarker + 1;\n\n            add(esSearchRequest);\n        }\n\n        return this;\n    }\n\n    private void setValue(String[] indices, String[] types, String searchType, String routing, IndicesOptions indicesOptions, ESSearchRequest esSearchRequest) {\n        if (indices != null) {\n            esSearchRequest.indices(indices);\n        }\n        if (indicesOptions != null) {\n            esSearchRequest.indicesOptions(indicesOptions);\n        }\n        if (types != null && types.length > 0) {\n            esSearchRequest.types(types);\n        }\n        if (routing != null) {\n            esSearchRequest.routing(routing);\n        }\n        if (searchType != null) {\n            esSearchRequest.searchType(searchType);\n        }\n    }\n\n    private void sourceParser(boolean allowExplicitIndex, ESSearchRequest esSearchRequest, Map<String, Object> source) {\n        for (Map.Entry<String, Object> entry : source.entrySet()) {\n            Object value = entry.getValue();\n            if (\"index\".equals(entry.getKey()) || \"indices\".equals(entry.getKey())) {\n                if (!allowExplicitIndex) {\n                    throw new IllegalArgumentException(\"explicit index in multi percolate is not allowed\");\n                }\n                esSearchRequest.indices(nodeStringArrayValue(value));\n            } else if (\"type\".equals(entry.getKey()) || \"types\".equals(entry.getKey())) {\n                esSearchRequest.types(nodeStringArrayValue(value));\n            } else if (SEARCH_TYPE.equals(entry.getKey()) || \"searchType\".equals(entry.getKey())) {\n                esSearchRequest.searchType(nodeStringValue(value, null));\n            } else if (REQUEST_CACHE.equals(entry.getKey()) || \"requestCache\".equals(entry.getKey())) {\n                esSearchRequest.requestCache(nodeBooleanValue(value));\n            } else if (PREFERENCE.equals(entry.getKey())) {\n                esSearchRequest.preference(nodeStringValue(value, null));\n            } else if (ROUTING.equals(entry.getKey())) {\n                esSearchRequest.routing(nodeStringValue(value, null));\n            }\n        }\n    }\n\n    private int findNextMarker(byte marker, int from, BytesReference data, int length) {\n        for (int i = from; i < length; i++) {\n            if (data.get(i) == marker) {\n                return i;\n            }\n        }\n        return -1;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = this.endpoint;\n        if (isTemplateRequest) {\n            endpoint += \"/template\";\n        }\n\n        RestRequest restRequest = new RestRequest(HttpMethod.POST.getName(), endpoint);\n        restRequest.setParams(params);\n\n        StringBuilder builder = new StringBuilder();\n        for (ESSearchRequest esSearchRequest : requests) {\n            JSONObject header = new JSONObject();\n            setIndexAndType(esSearchRequest, header);\n\n            if (esSearchRequest.getParams().containsKey(SEARCH_TYPE)) {\n                header.put(SEARCH_TYPE, esSearchRequest.getParams().get(SEARCH_TYPE));\n            }\n\n            if (esSearchRequest.getParams().containsKey(REQUEST_CACHE)) {\n                header.put(REQUEST_CACHE, esSearchRequest.getParams().get(REQUEST_CACHE));\n            }\n\n            if (esSearchRequest.getParams().containsKey(PREFERENCE)) {\n                header.put(PREFERENCE, esSearchRequest.getParams().get(PREFERENCE));\n            }\n\n            if (esSearchRequest.getParams().containsKey(ROUTING)) {\n                header.put(ROUTING, esSearchRequest.getParams().get(ROUTING));\n            }\n\n            if (esSearchRequest.indicesOptions() != null) {\n                headDeal(esSearchRequest, header);\n            }\n\n            builder.append(header.toJSONString());\n            builder.append(\"\\n\");\n            builder.append(esSearchRequest.source() == null ? \"{}\" : esSearchRequest.source().toUtf8());\n            builder.append(\"\\n\");\n        }\n\n        restRequest.setBody(builder.toString());\n\n        return restRequest;\n    }\n\n    private void setIndexAndType(ESSearchRequest esSearchRequest, JSONObject header) {\n        if (esSearchRequest.indices() != null && esSearchRequest.indices().length > 0) {\n            header.put(\"index\", Strings.arrayToCommaDelimitedString(esSearchRequest.indices()));\n        }\n\n        if (esSearchRequest.types() != null && esSearchRequest.types().length > 0) {\n            header.put(\"type\", Strings.arrayToCommaDelimitedString(esSearchRequest.types()));\n        }\n    }\n\n    private void headDeal(ESSearchRequest esSearchRequest, JSONObject header) {\n        header.put(\"ignore_unavailable\", Boolean.toString(esSearchRequest.indicesOptions().ignoreUnavailable()));\n        header.put(\"allow_no_indices\", Boolean.toString(esSearchRequest.indicesOptions().allowNoIndices()));\n        String expandWildcards;\n        if (!esSearchRequest.indicesOptions().expandWildcardsOpen() && !esSearchRequest.indicesOptions().expandWildcardsClosed()) {\n            expandWildcards = \"none\";\n        } else {\n            StringJoiner joiner = new StringJoiner(\",\");\n            if (esSearchRequest.indicesOptions().expandWildcardsOpen()) {\n                joiner.add(\"open\");\n            }\n            if (esSearchRequest.indicesOptions().expandWildcardsClosed()) {\n                joiner.add(\"closed\");\n            }\n            expandWildcards = joiner.toString();\n        }\n        header.put(\"expand_wildcards\", expandWildcards);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        XContentParser parser = JsonXContent.jsonXContent.createParser(response.getResponseStream());\n        return ESMultiSearchResponse.fromXContent(parser);\n    }\n\n    public Map<String, String> getParams() {\n        return params;\n    }\n\n    public void setParams(Map<String, String> params) {\n        this.params = params;\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    public List<ESSearchRequest> requests() {\n        return this.requests;\n    }\n\n    public List<ESSearchRequest> getRequests() {\n        return requests;\n    }\n\n    public void setRequests(List<ESSearchRequest> requests) {\n        this.requests = requests;\n    }\n\n    public void addRequest(ESSearchRequest request) {\n        requests.add(request);\n    }\n\n    public boolean isTemplateRequest() {\n        return isTemplateRequest;\n    }\n\n    public void setTemplateRequest(boolean templateRequest) {\n        isTemplateRequest = templateRequest;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESMultiSearchResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.common.xcontent.*;\nimport org.elasticsearch.common.xcontent.XContentParser.Token;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestResponse;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ESMultiSearchResponse extends ESActionResponse implements ToXContent {\n\n    static final class Fields {\n        private Fields() {\n\n        }\n        static final String RESPONSES = \"responses\";\n        static final String STATUS = \"status\";\n        static final String ERROR = \"error\";\n    }\n\n    @JSONField(name=\"responses\")\n    private List<Item> responses;\n\n    public ESMultiSearchResponse() {\n        // pass\n    }\n\n    public List<Item> getResponses() {\n        return responses;\n    }\n\n    public void setResponses(List<Item> responses) {\n        this.responses = responses;\n    }\n\n    /**\n     * A search response item, holding the actual search response, or an error message if it failed.\n     */\n    public static class Item {\n        private ESSearchResponse response;\n        private Object exception;\n\n        private int status;\n\n        Item() {\n\n        }\n\n        public Item(ESSearchResponse response, Object exception) {\n            this.response = response;\n            this.exception = exception;\n        }\n\n        /**\n         * Is it a failed search?\n         */\n        public boolean isFailure() {\n            return exception != null;\n        }\n\n        /**\n         * The actual search response, null if its a failure.\n         */\n        @Nullable\n        public ESSearchResponse getResponse() {\n            return this.response;\n        }\n\n        public Object getFailure() {\n            return exception;\n        }\n\n        public int getStatus() {\n            return status;\n        }\n\n        public void setStatus(int status) {\n            this.status = status;\n        }\n    }\n\n    public static ESMultiSearchResponse fromXContent(XContentParser parser) throws IOException {\n        XContentParserUtils.ensureExpectedToken(Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);\n        parser.nextToken();\n\n        XContentParserUtils.ensureExpectedToken(Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation);\n        String currentFieldName = parser.currentName();\n\n        ESMultiSearchResponse esMultiSearchResponse = new ESMultiSearchResponse();\n        for (Token token = parser.nextToken(); token != Token.END_OBJECT; token = parser.nextToken()) {\n            if (token == Token.FIELD_NAME) {\n                currentFieldName = parser.currentName();\n            } else if (token == Token.START_ARRAY) {\n                if (Fields.RESPONSES.equals(currentFieldName)) {\n                    esMultiSearchResponse.responses = new ArrayList<>();\n                    while ((token = parser.nextToken()) != Token.END_ARRAY) {\n                        esMultiSearchResponse.responses.add(itemFromXContent(parser));\n                    }\n                } else {\n                    parser.skipChildren();\n                }\n            } else {\n                parser.skipChildren();\n            }\n        }\n\n        return esMultiSearchResponse;\n    }\n\n    private static Item itemFromXContent(XContentParser parser) throws IOException {\n        // This parsing logic is a bit tricky here, because the multi search response itself is tricky:\n        // 1) The json objects inside the responses array are either a search response or a serialized exception\n        // 2) Each response json object gets a status field injected that ElasticsearchException.failureFromXContent(...) does not parse,\n        //    but SearchResponse.innerFromXContent(...) parses and then ignores. The status field is not needed to parse\n        //    the response item. However in both cases this method does need to parse the 'status' field otherwise the parsing of\n        //    the response item in the next json array element will fail due to parsing errors.\n\n        Item item = null;\n        String fieldName = null;\n\n        Token token = parser.nextToken();\n        assert token == Token.FIELD_NAME;\n\n        outer: for (; token != Token.END_OBJECT; token = parser.nextToken()) {\n            switch (token) {\n                case FIELD_NAME:\n                    fieldName = parser.currentName();\n                    if (Fields.ERROR.equals(fieldName)) {\n                        item = getItem(parser);\n                    } else if (Fields.STATUS.equals(fieldName)) {\n                        token = parser.nextToken();\n                        if (null != item) {\n                            item.status = parser.intValue();\n                        }\n                    } else {\n                        item = new Item(ESSearchResponse.innerFromXContent(parser), null);\n                        setItemStatus(item);\n                        break outer;\n                    }\n                    break;\n                default:\n            }\n        }\n        assert parser.currentToken() == Token.END_OBJECT;\n        return item;\n    }\n\n    private static void setItemStatus(Item item) {\n        if (item.getResponse().getStatus() != null) {\n            item.status = item.getResponse().getStatus();\n        }\n    }\n\n    private static Item getItem(XContentParser parser) throws IOException {\n        Item item;\n        Token token;\n        token = parser.nextToken();\n        Object err;\n        if (token == Token.START_OBJECT) {\n            err = parser.map();\n        } else {\n            err = parser.objectText();\n        }\n        item = new Item(null, err);\n        return item;\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.startObject();\n        builder.startArray(Fields.RESPONSES);\n\n\n        for (Item item : responses) {\n            builder.startObject();\n            if (item.getFailure() == null) {\n                item.getResponse().toXContent(builder, params);\n            } else {\n                builder.field(Fields.ERROR, item.exception);\n            }\n\n            if (item.status > 0) {\n                builder.field(Fields.STATUS, item.status);\n            }\n\n            builder.endObject();\n        }\n        builder.endArray();\n        builder.endObject();\n\n        return builder;\n    }\n\n    @Override\n    public RestResponse buildRestResponse(RestChannel channel) {\n        try {\n            XContentBuilder builder = channel.newBuilder();\n            toXContent(builder, channel.request());\n            return new BytesRestResponse(getRestStatus(), builder);\n        } catch (IOException e) {\n            return new BytesRestResponse(getRestStatus(), XContentType.JSON.restContentType(), toString());\n        }\n    }\n\n\n    @Override\n    public String toString() {\n        try {\n            XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();\n            toXContent(builder, EMPTY_PARAMS);\n            return builder.string();\n        } catch (IOException e) {\n            return \"{ \\\"error\\\" : \\\"\" + e.getMessage() + \"\\\"}\";\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESSearchAction.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESSearchAction extends Action<ESSearchRequest, ESSearchResponse, ESSearchRequestBuilder> {\n\n    public static final ESSearchAction INSTANCE = new ESSearchAction();\n    public static final String NAME = \"indices:data/read/search\";\n\n    private ESSearchAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESSearchResponse newResponse() {\n        return new ESSearchResponse();\n    }\n\n    @Override\n    public ESSearchRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESSearchRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESSearchRequest.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.ElasticsearchGenerationException;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.action.search.SearchType;\nimport org.elasticsearch.action.support.IndicesOptions;\nimport org.elasticsearch.client.Requests;\nimport org.elasticsearch.common.ParseFieldMatcher;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentFactory;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\nimport org.elasticsearch.search.builder.SearchSourceBuilder;\nimport org.jboss.netty.handler.codec.http.HttpMethod;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.StringJoiner;\n\npublic class ESSearchRequest extends ESActionRequest<ESSearchRequest> {\n    private String[] indices;\n\n    private String[] types = Strings.EMPTY_ARRAY;\n\n    private BytesReference source;\n\n    private BytesReference extraSource;\n\n    private boolean isTemplateRequest;\n\n    private final String endpoint;\n\n    private Map<String, String> params = new HashMap<>();\n\n    private static final String SEARCH_TYPE = \"search_type\";\n\n    private static final String ROUTING = \"routing\";\n\n    public ESSearchRequest() {\n        this.endpoint = \"/_search\";\n    }\n\n    public ESSearchRequest(String endpoint) {\n        this.endpoint = endpoint;\n    }\n\n    /**\n     * Sets the indices the search will be executed on.\n     */\n    public ESSearchRequest indices(String... indices) {\n        if (indices == null) {\n            throw new IllegalArgumentException(\"indices must not be null\");\n        } else {\n            for (int i = 0; i < indices.length; i++) {\n                if (indices[i] == null) {\n                    throw new IllegalArgumentException(\"indices[\" + i + \"] must not be null\");\n                }\n            }\n        }\n        this.indices = indices;\n        return this;\n    }\n\n    /**\n     * The indices\n     */\n    public String[] indices() {\n        return indices;\n    }\n\n    /**\n     * The document types to execute the search against. Defaults to be executed against\n     * all types.\n     */\n    public String[] types() {\n        return types;\n    }\n\n    /**\n     * The document types to execute the search against. Defaults to be executed against\n     * all types.\n     */\n    public ESSearchRequest types(String... types) {\n        this.types = types;\n        return this;\n    }\n\n    /**\n     * The source of the search request.\n     */\n    public ESSearchRequest source(SearchSourceBuilder sourceBuilder) {\n        this.source = sourceBuilder.buildAsBytes(Requests.CONTENT_TYPE);\n        return this;\n    }\n\n    /**\n     * The source of the search request. Consider using either {@link #source(byte[])} or\n     * {@link #source(SearchSourceBuilder)}.\n     */\n    public ESSearchRequest source(String source) {\n        this.source = new BytesArray(source);\n        return this;\n    }\n\n    /**\n     * The source of the search request in the form of a map.\n     */\n    public ESSearchRequest source(Map source) {\n        try {\n            XContentBuilder builder = XContentFactory.contentBuilder(Requests.CONTENT_TYPE);\n            builder.map(source);\n            return source(builder);\n        } catch (IOException e) {\n            throw new ElasticsearchGenerationException(\"Failed to generate [\" + source + \"]\", e);\n        }\n    }\n\n    public ESSearchRequest source(XContentBuilder builder) {\n        this.source = builder.bytes();\n        return this;\n    }\n\n    /**\n     * The search source to execute.\n     */\n    public ESSearchRequest source(byte[] source) {\n        return source(source, 0, source.length);\n    }\n\n\n    /**\n     * The search source to execute.\n     */\n    public ESSearchRequest source(byte[] source, int offset, int length) {\n        return source(new BytesArray(source, offset, length));\n    }\n\n    /**\n     * The search source to execute.\n     */\n    public ESSearchRequest source(BytesReference source) {\n        this.source = source;\n        return this;\n    }\n\n    /**\n     * The search source to execute.\n     */\n    public BytesReference source() {\n        return source;\n    }\n\n    /**\n     * Allows to provide additional source that will be used as well.\n     */\n    public ESSearchRequest extraSource(SearchSourceBuilder sourceBuilder) {\n        if (sourceBuilder == null) {\n            extraSource = null;\n            return this;\n        }\n        this.extraSource = sourceBuilder.buildAsBytes(Requests.CONTENT_TYPE);\n        return this;\n    }\n\n    public ESSearchRequest extraSource(Map extraSource) {\n        try {\n            XContentBuilder builder = XContentFactory.contentBuilder(Requests.CONTENT_TYPE);\n            builder.map(extraSource);\n            return extraSource(builder);\n        } catch (IOException e) {\n            throw new ElasticsearchGenerationException(\"Failed to generate [\" + extraSource + \"]\", e);\n        }\n    }\n\n    public ESSearchRequest extraSource(XContentBuilder builder) {\n        this.extraSource = builder.bytes();\n        return this;\n    }\n\n    /**\n     * Allows to provide additional source that will use used as well.\n     */\n    public ESSearchRequest extraSource(String source) {\n        this.extraSource = new BytesArray(source);\n        return this;\n    }\n\n    /**\n     * Allows to provide additional source that will be used as well.\n     */\n    public ESSearchRequest extraSource(byte[] source) {\n        return extraSource(source, 0, source.length);\n    }\n\n    /**\n     * Allows to provide additional source that will be used as well.\n     */\n    public ESSearchRequest extraSource(byte[] source, int offset, int length) {\n        return extraSource(new BytesArray(source, offset, length));\n    }\n\n    /**\n     * Allows to provide additional source that will be used as well.\n     */\n    public ESSearchRequest extraSource(BytesReference source) {\n        this.extraSource = source;\n        return this;\n    }\n\n    /**\n     * Additional search source to execute.\n     */\n    public BytesReference extraSource() {\n        return this.extraSource;\n    }\n\n    public boolean isTemplateRequest() {\n        return isTemplateRequest;\n    }\n\n    public void setTemplateRequest(boolean templateRequest) {\n        isTemplateRequest = templateRequest;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String index = StringUtils.join(indices, \",\");\n        String type = StringUtils.join(types, \",\");\n\n        String endpoint;\n        if (type == null || type.length() == 0) {\n            endpoint = String.format(\"/%s\", index);\n        } else {\n            endpoint = String.format(\"/%s/%s\", index, type);\n        }\n        endpoint += this.endpoint;\n\n        if (isTemplateRequest) {\n            endpoint += \"/template\";\n        }\n\n        RestRequest restRequest = new RestRequest(HttpMethod.POST.getName(), endpoint);\n        restRequest.setBody(source);\n\n        prepareDealSearchType();\n        restRequest.setParams(params);\n        return restRequest;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        XContentParser parser = JsonXContent.jsonXContent.createParser(response.getResponseStream());\n        return ESSearchResponse.fromXContent(parser);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    public Map<String, String> getParams() {\n        return params;\n    }\n\n    public void setParams(Map<String, String> params) {\n        this.params = params;\n    }\n\n    /**\n     * A comma separated list of routing values to control the shards the search will be executed on.\n     */\n    public String routing() {\n        return this.params.get(ROUTING);\n    }\n\n    /**\n     * A comma separated list of routing values to control the shards the search will be executed on.\n     */\n    public ESSearchRequest routing(String routing) {\n        putParam(ROUTING, routing);\n        return this;\n    }\n\n    /**\n     * The routing values to control the shards that the search will be executed on.\n     */\n    public ESSearchRequest routing(String... routings) {\n        putParam(ROUTING, Strings.arrayToCommaDelimitedString(routings));\n        return this;\n    }\n\n    /**\n     * Sets the preference to execute the search. Defaults to randomize across shards. Can be set to\n     * <tt>_local</tt> to prefer local shards, <tt>_primary</tt> to execute only on primary shards, or\n     * a custom value, which guarantees that the same order will be used across different requests.\n     */\n    public ESSearchRequest preference(String preference) {\n        putParam(\"preference\", preference);\n        return this;\n    }\n\n    public String preference() {\n        return params.get(\"preference\");\n    }\n\n    /**\n     * The tye of search to execute.\n     */\n    public SearchType searchType() {\n        return SearchType.fromString(params.get(SEARCH_TYPE), ParseFieldMatcher.EMPTY);\n    }\n\n    /**\n     * The search type to execute, defaults to {@link SearchType#DEFAULT}.\n     */\n    public ESSearchRequest searchType(SearchType searchType) {\n        if (searchType.equals(SearchType.COUNT)) {\n            return this;\n        }\n\n        putParam(SEARCH_TYPE, searchType.name().toLowerCase(Locale.ROOT));\n        return this;\n    }\n\n    /**\n     * The a string representation search type to execute, defaults to {@link SearchType#DEFAULT}. Can be\n     * one of \"dfs_query_then_fetch\"/\"dfsQueryThenFetch\", \"dfs_query_and_fetch\"/\"dfsQueryAndFetch\",\n     * \"query_then_fetch\"/\"queryThenFetch\", and \"query_and_fetch\"/\"queryAndFetch\".\n     */\n    public ESSearchRequest searchType(String searchType) {\n        if (searchType.equalsIgnoreCase(\"count\")) {\n            return this;\n        }\n\n        putParam(SEARCH_TYPE, searchType);\n        return this;\n    }\n\n    private void prepareDealSearchType() {\n        String searchType = params.get(SEARCH_TYPE);\n        if (searchType != null && (searchType.equalsIgnoreCase(\"count\"))) {\n            params.remove(SEARCH_TYPE);\n        }\n    }\n\n    public IndicesOptions indicesOptions() {\n        return IndicesOptions.fromParameters(\n                params.get(\"expand_wildcards\"),\n                params.get(\"ignore_unavailable\"),\n                params.get(\"allow_no_indices\"),\n                IndicesOptions.strictExpandOpenAndForbidClosed());\n    }\n\n    public ESSearchRequest indicesOptions(IndicesOptions indicesOptions) {\n        putParam(\"ignore_unavailable\", Boolean.toString(indicesOptions.ignoreUnavailable()));\n        putParam(\"allow_no_indices\", Boolean.toString(indicesOptions.allowNoIndices()));\n        String expandWildcards;\n        if (!indicesOptions.expandWildcardsOpen() && !indicesOptions.expandWildcardsClosed()) {\n            expandWildcards = \"none\";\n        } else {\n            StringJoiner stringJoiner = new StringJoiner(\",\");\n            if (indicesOptions.expandWildcardsOpen()) {\n                stringJoiner.add(\"open\");\n            }\n            if (indicesOptions.expandWildcardsClosed()) {\n                stringJoiner.add(\"closed\");\n            }\n            expandWildcards = stringJoiner.toString();\n        }\n        putParam(\"expand_wildcards\", expandWildcards);\n        return this;\n    }\n\n    /**\n     * Sets if this request should use the request cache or not, assuming that it can (for\n     * example, if \"now\" is used, it will never be cached). By default (not set, or null,\n     * will default to the index level setting if request cache is enabled or not).\n     */\n    public ESSearchRequest requestCache(Boolean requestCache) {\n        putParam(\"request_cache\", String.valueOf(requestCache));\n        return this;\n    }\n\n    public Boolean requestCache() {\n        return Boolean.valueOf(params.get(\"request_cache\"));\n    }\n\n    public void putParam(String name, String value) {\n        if (Strings.hasLength(value)) {\n            params.put(name, value);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESSearchRequestBuilder.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESSearchRequestBuilder extends ActionRequestBuilder<ESSearchRequest, ESSearchResponse, ESSearchRequestBuilder> {\n    protected ESSearchRequestBuilder(ElasticsearchClient client, Action<ESSearchRequest, ESSearchResponse, ESSearchRequestBuilder> action, ESSearchRequest request) {\n        super(client, action, request);\n    }\n\n    public ESSearchRequestBuilder(ElasticsearchClient client, ESSearchAction action) {\n        super(client, action, new ESSearchRequest());\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESSearchResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.response.Shards;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.response.src.Hits;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.xcontent.*;\nimport org.elasticsearch.common.xcontent.XContentParser.Token;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestResponse;\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.util.Map;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/8/31 下午4:27\n * @Modified By\n */\npublic class ESSearchResponse extends ESActionResponse implements ToXContent {\n\n    /**\n     * 查询耗时\n     */\n    private Long took;\n    /**\n     * 是否超时\n     */\n    private Boolean timeOut;\n    /**\n     * shard结果\n     */\n    private Shards shards;\n    /**\n     * 命中结果\n     */\n    private Hits hits;\n\n    /**\n     * 聚合结果\n     */\n    private Map<String, Object> aggregations;\n    /**\n     * 滚动id\n     */\n    private String scrollId;\n\n    private Map<String, Object> suggest;\n\n    private Map<String, Object> profile;\n\n    private Map<String, Object> clusters;\n\n    private Boolean terminatedEarly;\n\n    private int numReducePhases;\n\n    private Integer status;\n\n    public ESSearchResponse() {\n        // pass\n    }\n\n    public Long getTook() {\n        return took;\n    }\n\n    public void setTook(Long took) {\n        this.took = took;\n    }\n\n    public Boolean getTimeOut() {\n        return timeOut;\n    }\n\n    public void setTimeOut(Boolean timeOut) {\n        this.timeOut = timeOut;\n    }\n\n    public Shards getShards() {\n        return shards;\n    }\n\n    public void setShards(Shards shard) {\n        this.shards = shard;\n    }\n\n    public Hits getHits() {\n        return hits;\n    }\n\n    public void setHits(Hits hits) {\n        this.hits = hits;\n    }\n\n    public String getScrollId() {\n        return scrollId;\n    }\n\n    public void setScrollId(String scrollId) {\n        this.scrollId = scrollId;\n    }\n\n    public Boolean getTerminatedEarly() {\n        return terminatedEarly;\n    }\n\n    public void setTerminatedEarly(Boolean terminatedEarly) {\n        this.terminatedEarly = terminatedEarly;\n    }\n\n    public Integer getStatus() {\n        return status;\n    }\n\n    public void setStatus(Integer status) {\n        this.status = status;\n    }\n\n    public Map<String, Object> getAggregations() {\n        return aggregations;\n    }\n\n    static final class Fields {\n        static final String SCROLL_ID = \"_scroll_id\";\n        static final String TOOK = \"took\";\n        static final String TIMED_OUT = \"timed_out\";\n        static final String TERMINATED_EARLY = \"terminated_early\";\n        static final String NUM_REDUCE_PHASES = \"num_reduce_phases\";\n        static final String SUGGEST = \"suggest\";\n        static final String PROFILE = \"profile\";\n        static final String AGGREGATIONS = \"aggregations\";\n        static final String HITS = \"hits\";\n        static final String SHARDS = \"_shards\";\n        static final String CLUSTERS_FIELD = \"_clusters\";\n        static final String STATUS = \"status\";\n        private Fields () {\n\n        }\n    }\n\n    @Override\n    public String toString() {\n        try {\n            XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();\n            builder.startObject();\n            toXContent(builder, EMPTY_PARAMS);\n            builder.endObject();\n            return builder.string();\n        } catch (IOException e) {\n            return \"{ \\\"error\\\" : \\\"\" + e.getMessage() + \"\\\"}\";\n        }\n    }\n\n    public static ESSearchResponse innerFromXContent(XContentParser parser) throws IOException {\n        XContentParserUtils.ensureExpectedToken(Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation);\n        String currentFieldName = parser.currentName();\n\n        ESSearchResponse esSearchResponse = new ESSearchResponse();\n        for (Token token = parser.nextToken(); token != Token.END_OBJECT; token = parser.nextToken()) {\n            if (token == Token.FIELD_NAME) {\n                currentFieldName = parser.currentName();\n            } else if (token.isValue()) {\n                dealValue(parser, currentFieldName, esSearchResponse);\n            } else if (token == Token.START_OBJECT) {\n                if (Fields.HITS.equals(currentFieldName)) {\n                    esSearchResponse.hits = Hits.fromXContent(parser);\n                } else if (Fields.AGGREGATIONS.equals(currentFieldName)) {\n                    esSearchResponse.aggregations = parser.map();\n                } else if (Fields.SUGGEST.equals(currentFieldName)) {\n                    esSearchResponse.suggest = parser.map();\n                } else if (Fields.PROFILE.equals(currentFieldName)) {\n                    esSearchResponse.profile = parser.map();\n                } else if (Fields.SHARDS.equals(currentFieldName)) {\n                    esSearchResponse.shards = Shards.fromXContent(parser);\n                } else if (Fields.CLUSTERS_FIELD.equals(currentFieldName)) {\n                    esSearchResponse.clusters = parser.map();\n                } else {\n                    parser.skipChildren();\n                }\n            }\n        }\n\n        return esSearchResponse;\n    }\n\n    private static void dealValue(XContentParser parser, String currentFieldName, ESSearchResponse esSearchResponse) throws IOException {\n        if (Fields.SCROLL_ID.equals(currentFieldName)) {\n            esSearchResponse.scrollId = parser.text();\n        } else if (Fields.TOOK.equals(currentFieldName)) {\n            esSearchResponse.took = parser.longValue();\n        } else if (Fields.TIMED_OUT.equals(currentFieldName)) {\n            esSearchResponse.timeOut = parser.booleanValue();\n        } else if (Fields.TERMINATED_EARLY.equals(currentFieldName)) {\n            esSearchResponse.terminatedEarly = parser.booleanValue();\n        } else if (Fields.NUM_REDUCE_PHASES.equals(currentFieldName)) {\n            esSearchResponse.numReducePhases = parser.intValue();\n        } else if (Fields.STATUS.equals(currentFieldName)) {\n            esSearchResponse.status = parser.intValue();\n        } else {\n            parser.skipChildren();\n        }\n    }\n\n    public static ESSearchResponse fromXContent(XContentParser parser) throws IOException {\n        XContentParserUtils.ensureExpectedToken(Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);\n        parser.nextToken();\n        return innerFromXContent(parser);\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        if (scrollId != null) {\n            builder.field(Fields.SCROLL_ID, scrollId);\n        }\n\n        builder.field(Fields.TOOK, took);\n        builder.field(Fields.TIMED_OUT, timeOut);\n\n        if (terminatedEarly != null) {\n            builder.field(Fields.TERMINATED_EARLY, terminatedEarly);\n        }\n\n        shards.toXContent(builder, params);\n        hits.toXContent(builder, params);\n        if (aggregations != null && !aggregations.isEmpty()) {\n            builder.field(Fields.AGGREGATIONS, aggregations);\n        }\n\n        if (suggest != null) {\n            builder.field(Fields.SUGGEST, suggest);\n        }\n\n        if (profile != null) {\n            builder.field(Fields.PROFILE, profile);\n        }\n\n        return builder;\n    }\n\n    @Override\n    public RestResponse buildRestResponse(RestChannel channel) {\n        XContentBuilder builder = null;\n        try {\n            builder = channel.newBuilder();\n            builder.startObject();\n            toXContent(builder, channel.request());\n            builder.endObject();\n            return new BytesRestResponse(getRestStatus(), builder);\n        } catch (IOException e) {\n            return new BytesRestResponse(getRestStatus(), XContentType.JSON.restContentType(), toString());\n        } finally {\n            if (null != builder) {\n                builder.close();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESSearchScrollAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESSearchScrollAction extends Action<ESSearchScrollRequest, ESSearchResponse, ESSearchScrollRequestBuilder> {\n\n    public static final ESSearchScrollAction INSTANCE = new ESSearchScrollAction();\n    public static final String NAME = \"indices:data/read/scroll\";\n\n    private ESSearchScrollAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESSearchResponse newResponse() {\n        return new ESSearchResponse();\n    }\n\n    @Override\n    public ESSearchScrollRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESSearchScrollRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESSearchScrollRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.common.unit.TimeValue;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\n\npublic class ESSearchScrollRequest extends ESActionRequest<ESSearchScrollRequest> {\n\n    private String scrollId;\n    private TimeValue scrollTime;\n\n    public ESSearchScrollRequest() {\n        // pass\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    public String getScrollId() {\n        return scrollId;\n    }\n\n    public ESSearchScrollRequest setScrollId(String scrollId) {\n        this.scrollId = scrollId;\n        return this;\n    }\n\n    public ESSearchScrollRequest scroll(TimeValue keepAlive) {\n        this.scrollTime = keepAlive;\n        return this;\n    }\n\n    public ESSearchScrollRequest scroll(String keepAlive) {\n        return scroll( TimeValue.parseTimeValue(keepAlive, null,\"scroll\"));\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        if(scrollId == null) {\n            throw new Exception(\"scroll id is null\");\n        }\n\n        String endPoint = \"/_search/scroll\";\n\n        JSONObject scrollJson = new JSONObject();\n        if(scrollTime!=null) {\n            scrollJson.put(\"scroll\", scrollTime.getMillis() + \"ms\");\n        }\n        scrollJson.put(\"scroll_id\", scrollId);\n\n\n        RestRequest restRequest = new RestRequest(\"POST\", endPoint, null);\n        restRequest.setBody(scrollJson.toJSONString());\n\n        return restRequest;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        XContentParser parser = JsonXContent.jsonXContent.createParser(response.getResponseStream());\n        return ESSearchResponse.fromXContent(parser);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/ESSearchScrollRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.gateway.search;\n\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\nimport org.elasticsearch.common.unit.TimeValue;\n\n/**\n * A search request request builder.\n */\npublic class ESSearchScrollRequestBuilder extends ActionRequestBuilder<ESSearchScrollRequest, ESSearchResponse, ESSearchScrollRequestBuilder> {\n\n    public ESSearchScrollRequestBuilder(ElasticsearchClient client, ESSearchScrollAction action) {\n        super(client, action, new ESSearchScrollRequest());\n    }\n\n\n    public ESSearchScrollRequestBuilder setScrollId(String scrollId) {\n        request.setScrollId(scrollId);\n        return this;\n    }\n\n    public ESSearchScrollRequestBuilder setScroll(TimeValue keepAlive) {\n        request.scroll(keepAlive);\n        return this;\n    }\n\n    public ESSearchScrollRequestBuilder setScroll(String keepAlive) {\n        request.scroll(keepAlive);\n        return this;\n    }\n\n\n    @Override\n    public ESSearchScrollRequest request() {\n        return request;\n    }\n\n    @Override\n    protected ESSearchScrollRequest beforeExecute(ESSearchScrollRequest request) {\n        return request;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/response/FailReason.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search.response;\n\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentParser;\n\nimport java.io.IOException;\nimport java.util.Map;\n\npublic class FailReason implements ToXContent {\n    private static final String TYPE = \"type\";\n    private static final String REASON = \"reason\";\n    private static final String CAUSED_BY = \"caused_by\";\n\n    private String type;\n\n    private String reason;\n\n    private Map<String, Object> causedBy;\n\n    public FailReason() {\n        // pass\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public String getReason() {\n        return reason;\n    }\n\n    public void setReason(String reason) {\n        this.reason = reason;\n    }\n\n    public Map<String, Object> getCausedBy() {\n        return causedBy;\n    }\n\n    public void setCausedBy(Map<String, Object> causedBy) {\n        this.causedBy = causedBy;\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.field(TYPE, type);\n        builder.field(REASON, reason);\n        builder.field(CAUSED_BY, causedBy);\n        return builder;\n    }\n\n    public static FailReason fromXContent(XContentParser parser) throws IOException {\n        XContentParser.Token token = parser.currentToken();\n        XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation);\n\n        String type = null;\n        String reason = null;\n        Map<String, Object> causedBy = null;\n\n        String currentFieldName = null;\n        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n            if (token == XContentParser.Token.FIELD_NAME) {\n                currentFieldName = parser.currentName();\n            } else if (token.isValue()) {\n                if (TYPE.equals(currentFieldName)) {\n                    type = parser.text();\n                } else if (REASON.equals(currentFieldName)) {\n                    reason = parser.text();\n                } else {\n                    parser.skipChildren();\n                }\n            } else if (token == XContentParser.Token.START_OBJECT) {\n                if (CAUSED_BY.equals(currentFieldName)) {\n                    causedBy = parser.map();\n                } else {\n                    parser.skipChildren();\n                }\n            }\n        }\n        FailReason failReason = new FailReason();\n        failReason.setReason(reason);\n        failReason.setType(type);\n        failReason.setCausedBy(causedBy);\n\n        return failReason;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/response/Failure.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search.response;\n\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentParser;\n\nimport java.io.IOException;\n\npublic class Failure implements ToXContent {\n    private static final String REASON_FIELD = \"reason\";\n    private static final String NODE_FIELD = \"node\";\n    private static final String INDEX_FIELD = \"index\";\n    private static final String SHARD_FIELD = \"shard\";\n\n    private int shard;\n\n    private String index;\n\n    private String node;\n\n    private FailReason reason;\n\n    public Failure() {\n        // pass\n    }\n\n    public int getShard() {\n        return shard;\n    }\n\n    public void setShard(int shard) {\n        this.shard = shard;\n    }\n\n    public String getIndex() {\n        return index;\n    }\n\n    public void setIndex(String index) {\n        this.index = index;\n    }\n\n    public String getNode() {\n        return node;\n    }\n\n    public void setNode(String node) {\n        this.node = node;\n    }\n\n    public FailReason getReason() {\n        return reason;\n    }\n\n    public void setReason(FailReason reason) {\n        this.reason = reason;\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.field(SHARD_FIELD, shard);\n        builder.field(INDEX_FIELD, index);\n        if (node != null) {\n            builder.field(\"node\", node);\n        }\n\n        if (reason != null) {\n            builder.field(REASON_FIELD);\n            builder.startObject();\n            reason.toXContent(builder, params);\n            builder.endObject();\n        }\n        return builder;\n    }\n\n    public static Failure fromXContent(XContentParser parser) throws IOException {\n        XContentParser.Token token;\n        XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser::getTokenLocation);\n        String currentFieldName = null;\n        int shardId = -1;\n        String indexName = null;\n        String nodeId = null;\n        FailReason failReason = null;\n        while((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n            if (token == XContentParser.Token.FIELD_NAME) {\n                currentFieldName = parser.currentName();\n            } else if (token.isValue()) {\n                if (SHARD_FIELD.equals(currentFieldName)) {\n                    shardId  = parser.intValue();\n                } else if (INDEX_FIELD.equals(currentFieldName)) {\n                    indexName  = parser.text();\n                } else if (NODE_FIELD.equals(currentFieldName)) {\n                    nodeId  = parser.text();\n                } else {\n                    parser.skipChildren();\n                }\n            } else if (token == XContentParser.Token.START_OBJECT) {\n                failReason = getFailReason(parser, currentFieldName, failReason);\n            } else {\n                parser.skipChildren();\n            }\n        }\n\n        Failure failure = new Failure();\n        failure.setShard(shardId);\n        failure.setIndex(indexName);\n        failure.setReason(failReason);\n        failure.setNode(nodeId);\n\n        return failure;\n    }\n\n    private static FailReason getFailReason(XContentParser parser, String currentFieldName, FailReason failReason) throws IOException {\n        if (REASON_FIELD.equals(currentFieldName)) {\n            failReason = FailReason.fromXContent(parser);\n        } else {\n            parser.skipChildren();\n        }\n        return failReason;\n    }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/response/Shards.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search.response;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentParser;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/8/31 下午4:47\n * @Modified By\n */\npublic class Shards implements ToXContent {\n\n    static final class Fields {\n        public static final String _SHARDS = \"_shards\";\n        public static final String TOTAL = \"total\";\n        public static final String SUCCESSFUL = \"successful\";\n        public static final String FAILED = \"failed\";\n        public static final String FAILURES = \"failures\";\n        public static final String SKIPPED = \"skipped\";\n    }\n\n    /**\n     * 查询总shard总个数\n     */\n    private Integer totalShard;\n\n    /**\n     * 成功的shard个数\n     */\n    private Integer successfulShard;\n\n    /**\n     * 失败的shard个数\n     */\n    private Integer failedShard;\n\n    private Integer skippedShard;\n\n    private List<Failure> failures;\n\n    public Shards() {\n        // pass\n    }\n\n    public Integer getTotalShard() {\n        return totalShard;\n    }\n\n    public void setTotalShard(Integer totalShard) {\n        this.totalShard = totalShard;\n    }\n\n    public Integer getSuccessfulShard() {\n        return successfulShard;\n    }\n\n    public void setSuccessfulShard(Integer successfulShard) {\n        this.successfulShard = successfulShard;\n    }\n\n    public Integer getFailedShard() {\n        return failedShard;\n    }\n\n    public void setFailedShard(Integer failedShard) {\n        this.failedShard = failedShard;\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n    public List<Failure> getFailures() {\n        return failures;\n    }\n\n    public void setFailures(List<Failure> failures) {\n        this.failures = failures;\n    }\n\n    public Integer getSkippedShard() {\n        return skippedShard;\n    }\n\n    public void setSkippedShard(Integer skippedShard) {\n        this.skippedShard = skippedShard;\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.startObject(Fields._SHARDS);\n        builder.field(Fields.TOTAL, totalShard);\n        builder.field(Fields.SUCCESSFUL, successfulShard);\n        builder.field(Fields.FAILED, failedShard);\n        if (failures != null && failures.size() > 0) {\n            builder.startArray(Fields.FAILURES);\n            //final boolean group = params.paramAsBoolean(\"group_shard_failures\", true); // we group by default\n            for (Failure failure : failures) {\n                builder.startObject();\n                failure.toXContent(builder, params);\n                builder.endObject();\n            }\n            builder.endArray();\n        }\n        builder.endObject();\n\n        return builder;\n    }\n\n    public static Shards fromXContent(XContentParser parser) throws IOException {\n        XContentParser.Token token = parser.currentToken();\n        XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser::getTokenLocation);\n\n        int total = 0;\n        int successful = 0;\n        int failed = 0;\n        int skipped = 0;\n        List<Failure> failuresList = null;\n        String currentFieldName = null;\n        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n            if (token == XContentParser.Token.FIELD_NAME) {\n                currentFieldName = parser.currentName();\n            } else if (token.isValue()) {\n                if (Fields.TOTAL.equals(currentFieldName)) {\n                    total = parser.intValue();\n                } else if (Fields.SUCCESSFUL.equals(currentFieldName)) {\n                    successful = parser.intValue();\n                } else if (Fields.FAILED.equals(currentFieldName)){\n                    failed = parser.intValue();\n                } else if (Fields.SKIPPED.equals(currentFieldName)) {\n                    skipped = parser.intValue();\n                } else {\n                    parser.skipChildren();\n                }\n            } else if (token == XContentParser.Token.START_ARRAY) {\n                failuresList = getFailures(parser, failuresList, currentFieldName);\n            } else {\n                parser.skipChildren(); // skip potential inner arrays for forward compatibility\n            }\n        }\n\n        Shards shards = new Shards();\n        shards.setTotalShard(total);\n        shards.setSuccessfulShard(successful);\n        shards.setFailedShard(failed);\n        shards.setSkippedShard(skipped);\n        shards.setFailures(failuresList);\n\n        return shards;\n    }\n\n    private static List<Failure> getFailures(XContentParser parser, List<Failure> failuresList, String currentFieldName) throws IOException {\n        XContentParser.Token token;\n        if (Fields.FAILURES.equals(currentFieldName)) {\n            failuresList = new ArrayList<>();\n            while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {\n                failuresList.add(Failure.fromXContent(parser));\n            }\n        } else {\n            parser.skipChildren(); // skip potential inner arrays for forward compatibility\n        }\n        return failuresList;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/response/src/Hit.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search.response.src;\n\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.ElasticsearchParseException;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentFactory;\nimport org.elasticsearch.common.xcontent.XContentParser;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TreeMap;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/8/31 下午4:32\n * @Modified By\n */\npublic class Hit implements ToXContent {\n    public static class Fields {\n        static final String INDEX = \"_index\";\n        static final String SHARD = \"_shard\";\n        static final String NODE = \"_node\";\n        static final String TYPE = \"_type\";\n        static final String ID = \"_id\";\n        static final String VERSION = \"_version\";\n        static final String SCORE = \"_score\";\n        static final String FIELDS = \"fields\";\n        static final String HIGHLIGHT = \"highlight\";\n        static final String SORT = \"sort\";\n        static final String MATCHED_QUERIES = \"matched_queries\";\n        static final String EXPLANATION = \"_explanation\";\n        static final String INNER_HITS = \"inner_hits\";\n        static final String NESTED = \"_nested\";\n        static final String SOURCE = \"_source\";\n    }\n\n    /**\n     * 索引名称\n     */\n    private String index;\n    /**\n     * type名称\n     */\n    private String type;\n    /**\n     * 主键id\n     */\n    private String id;\n    /**\n     * 得分\n     */\n    private float score;\n    /**\n     * source\n     */\n    private Map<String, Object> source;\n\n    private String sourceAsString;\n\n    private Map<String, List<Object>> fields = new HashMap<>();\n\n    private Map<String, Object> otherFields;\n\n    public Hit() {\n        // pass\n    }\n\n    public String getIndex() {\n        return index;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public void setIndex(String index) {\n        this.index = index;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public void setId(String id) {\n        this.id = id;\n    }\n\n    public float getScore() {\n        return score;\n    }\n\n    public void setScore(float score) {\n        this.score = score;\n    }\n\n    public Map<String, Object> getSource() {\n        return source;\n    }\n\n    public void setSource(Map<String, Object> source) {\n        this.source = source;\n    }\n\n    public String sourceAsString() {\n        if (source == null) {\n            return null;\n        }\n\n        if (sourceAsString != null) {\n            return sourceAsString;\n        }\n\n        try {\n            XContentBuilder builder = XContentFactory.jsonBuilder();\n            builder.map(source);\n            sourceAsString = builder.string();\n            return sourceAsString;\n        } catch (IOException e) {\n            throw new ElasticsearchParseException(\"failed to convert source to a json string\");\n        }\n    }\n\n    public Map<String, List<Object>> getFields() {\n        return fields;\n    }\n\n    public void setFields(Map<String, List<Object>> fields) {\n        this.fields = fields;\n    }\n\n    public Map<String, Object> getOtherFields() {\n        return otherFields;\n    }\n\n    public void setOtherFields(Map<String, Object> otherFields) {\n        this.otherFields = otherFields;\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.startObject();\n\n        if (index != null) {\n            builder.field(Fields.INDEX, index);\n        }\n\n        builder.field(Fields.TYPE, type);\n        builder.field(Fields.ID, id);\n\n        if (Float.isNaN(score)) {\n            builder.field(Fields.SCORE, 0.0f);\n        } else {\n            builder.field(Fields.SCORE, score);\n        }\n\n        if (source != null) {\n            builder.field(Fields.SOURCE, source);\n        }\n\n        if (fields != null && fields.size() > 0) {\n            builder.field(Fields.FIELDS, fields);\n        }\n\n        if (otherFields != null) {\n            for (Map.Entry<String, Object> entry : otherFields.entrySet()) {\n                builder.field(entry.getKey(), entry.getValue());\n            }\n        }\n\n        builder.endObject();\n        return builder;\n    }\n\n    public static Hit fromXContent(XContentParser parser) throws  IOException {\n        if (parser.currentToken() != XContentParser.Token.START_OBJECT) {\n            parser.nextToken();\n            XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser::getTokenLocation);\n        }\n\n        XContentParser.Token token = parser.currentToken();\n        String currentFieldName = null;\n        Hit hit = new Hit();\n        hit.otherFields = new TreeMap<>();\n        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n            if (token == XContentParser.Token.FIELD_NAME) {\n                currentFieldName = parser.currentName();\n            } else if (token.isValue()) {\n                dealValue(parser, currentFieldName, hit);\n            } else if (token == XContentParser.Token.VALUE_NULL) {\n                if (Fields.SCORE.equals(currentFieldName)) {\n                    hit.score = 0.0f; // NaN gets rendered as null-field\n                } else {\n                    hit.otherFields.put(currentFieldName, null);\n                }\n            } else if (token == XContentParser.Token.START_OBJECT) {\n                dealStartObj(parser, currentFieldName, hit);\n            } else if (token == XContentParser.Token.START_ARRAY) {\n                hit.otherFields.put(currentFieldName, parser.list());\n            }\n        }\n\n        return hit;\n    }\n\n    private static void dealStartObj(XContentParser parser, String currentFieldName, Hit hit) throws IOException {\n        XContentParser.Token token;\n        if (Fields.SOURCE.equals(currentFieldName)) {\n            hit.source = parser.map();\n        } else if (Fields.FIELDS.equals(currentFieldName)) {\n            hit.fields = new HashMap<>();\n            while(parser.nextToken() != XContentParser.Token.END_OBJECT) {\n                String key = parser.currentName();\n                token = parser.nextToken();\n                XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_ARRAY, token, parser::getTokenLocation);\n                hit.fields.put(key, parser.list());\n            }\n        } else {\n            hit.otherFields.put(currentFieldName, parser.map());\n        }\n    }\n\n    private static void dealValue(XContentParser parser, String currentFieldName, Hit hit) throws IOException {\n        if (Fields.INDEX.equals(currentFieldName)) {\n            hit.index = parser.text();\n        } else if (Fields.TYPE.equals(currentFieldName)) {\n            hit.type = parser.text();\n        } else if (Fields.ID.equals(currentFieldName)) {\n            hit.id = parser.text();\n        } else if (Fields.SCORE.equals(currentFieldName)) {\n            hit.score = parser.floatValue();\n        } else {\n            hit.otherFields.put(currentFieldName, parser.objectText());\n        }\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/gateway/search/response/src/Hits.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.gateway.search.response.src;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.utils.XContentParserUtils;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentParser;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @Author: D10865\n * @Description:\n * @Date: Create on 2018/8/31 下午4:29\n * @Modified By\n */\npublic class Hits implements ToXContent {\n    static final class Fields {\n        private Fields() {\n\n        }\n        static final String HITS = \"hits\";\n        static final String TOTAL = \"total\";\n        static final String MAX_SCORE = \"max_score\";\n    }\n\n    /**\n     * 结果集\n     */\n    private List<Hit> hits;\n\n    /**\n     * 命中总条数\n     */\n    private long total;\n    /**\n     * 最大得分\n     */\n    private float maxScore;\n\n    public Hits() {\n        // pass\n    }\n\n    @JSONField(serialize=false)\n    public boolean isEmpty() {\n        boolean res = false;\n        if(hits==null || hits.isEmpty()) {\n            res = true;\n        }\n        return res;\n    }\n\n    public List<Hit> getHits() {\n        return hits;\n    }\n\n    public void setHits(List<Hit> hits) {\n        this.hits = hits;\n    }\n\n    public long getTotal() {\n        return total;\n    }\n\n    public void setTotal(long total) {\n        this.total = total;\n    }\n\n    public float getMaxScore() {\n        return maxScore;\n    }\n\n    public void setMaxScore(float maxScore) {\n        this.maxScore = maxScore;\n    }\n\n    @Override\n    public String toString() {\n        return JSON.toJSONString(this);\n    }\n\n    public static Hits fromXContent(XContentParser parser) throws IOException {\n        if (parser.currentToken() != XContentParser.Token.START_OBJECT) {\n            parser.nextToken();\n            XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser::getTokenLocation);\n        }\n        XContentParser.Token token = parser.currentToken();\n        String currentFieldName = null;\n\n        Hits hits = new Hits();\n        hits.hits = new ArrayList<>();\n        while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n            if (token == XContentParser.Token.FIELD_NAME) {\n                currentFieldName = parser.currentName();\n            } else if (token.isValue()) {\n                if (Fields.TOTAL.equals(currentFieldName)) {\n                    hits.total = parser.longValue();\n                } else if (Fields.MAX_SCORE.equals(currentFieldName)) {\n                    hits.maxScore = parser.floatValue();\n                }\n            } else if (token == XContentParser.Token.VALUE_NULL) {\n                if (Fields.MAX_SCORE.equals(currentFieldName)) {\n                    hits.maxScore = 0.0F; // NaN gets rendered as null-field\n                }\n            } else if (token == XContentParser.Token.START_ARRAY) {\n                dealStartArray(parser, currentFieldName, hits);\n            } else if (token == XContentParser.Token.START_OBJECT) {\n                parser.skipChildren();\n            }\n        }\n\n        return hits;\n    }\n\n    private static void dealStartArray(XContentParser parser, String currentFieldName, Hits hits) throws IOException {\n        XContentParser.Token token;\n        if (Fields.HITS.equals(currentFieldName)) {\n            while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {\n                hits.hits.add(Hit.fromXContent(parser));\n            }\n        } else {\n            parser.skipChildren();\n        }\n    }\n\n    @Override\n    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {\n        builder.startObject(Fields.HITS);\n        builder.field(Fields.TOTAL, total);\n        if (Float.isNaN(maxScore)) {\n            builder.field(Fields.MAX_SCORE, 0.0f);\n        } else {\n            builder.field(Fields.MAX_SCORE, maxScore);\n        }\n\n        builder.field(Fields.HITS);\n        builder.startArray();\n\n        for (Hit hit : hits) {\n            hit.toXContent(builder, params);\n        }\n        builder.endArray();\n        builder.endObject();\n        return builder;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/Client.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.model;\n\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.*;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.*;\nimport com.didi.arius.gateway.elasticsearch.client.model.admin.ESAdminClient;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.ESBatchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.ESBatchRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.cat.ESCatRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.cat.ESCatRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.query.ESQueryRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.query.ESQueryRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.scroll.ESQueryScrollRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.scroll.ESQueryScrollRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.sql.ESSQLRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.sql.ESSQLRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.ESBatchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cat.ESCatResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport org.elasticsearch.action.ActionFuture;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.client.ElasticsearchClient;\nimport org.elasticsearch.common.lease.Releasable;\n\n/**\n * A client provides a one stop interface for performing actions/operations against the cluster.\n * <p>\n * All operations performed are asynchronous by nature. Each request/operation has two flavors, the first\n * simply returns an {@link ActionFuture}, while the second accepts an\n * {@link ActionListener}.\n * <p>\n * A client can either be retrieved from a {@link org.elasticsearch.node.Node} started, or connected remotely\n * to one or more nodes using {@link org.elasticsearch.client.transport.TransportClient}.\n *\n * @see org.elasticsearch.node.Node#client()\n * @see org.elasticsearch.client.transport.TransportClient\n */\npublic interface Client extends ElasticsearchClient, Releasable {\n\n    /**\n     * The admin client that can be used to perform administrative operations.\n     */\n    ESAdminClient admin();\n\n\n    ActionFuture<ESQueryResponse> query(final ESQueryRequest request);\n\n    void query(final ESQueryRequest request, final ActionListener<ESQueryResponse> listener);\n\n    ESQueryRequestBuilder prepareQuery(String... indices);\n\n\n    ActionFuture<ESQueryResponse> execSQL(final ESSQLRequest request);\n\n    void execSQL(final ESSQLRequest request, final ActionListener<ESQueryResponse> listener);\n\n    ESSQLRequestBuilder prepareSQL(String sql);\n\n\n    ActionFuture<ESQueryResponse> queryScroll(final ESQueryScrollRequest request);\n\n    void queryScroll(final ESQueryScrollRequest request, final ActionListener<ESQueryResponse> listener);\n\n    ESQueryScrollRequestBuilder prepareQueryScroll(String scrollId);\n\n\n\n    public ActionFuture<ESCatResponse> cat(final ESCatRequest request);\n\n    public void cat(final ESCatRequest request, final ActionListener<ESCatResponse> listener);\n\n    public ESCatRequestBuilder prepareCat();\n\n\n\n\n    ActionFuture<ESBatchResponse> batch(final ESBatchRequest request);\n\n    void batch(final ESBatchRequest request, final ActionListener<ESBatchResponse> listener);\n\n    ESBatchRequestBuilder prepareBatch();\n\n    /**\n     * direct request where url and post content, reture direct response.\n     * <p>\n     * The id is optional, if it is not provided, one will be generated automatically.\n     *\n     * @param request The direct request\n     * @return The result future\n     */\n    ActionFuture<DirectResponse> direct(DirectRequest request);\n\n    /**\n     * direct request where url and post content, reture direct response.\n     * <p>\n     * The id is optional, if it is not provided, one will be generated automatically.\n     *\n     * @param request  The direct request\n     * @param listener A listener to be notified with a result\n     */\n    void direct(DirectRequest request, ActionListener<DirectResponse> listener);\n\n\n    ActionFuture<ESSearchResponse> search(ESSearchRequest request);\n\n    void search(ESSearchRequest request, ActionListener<ESSearchResponse> listener);\n\n    ActionFuture<ESClearScrollResponse> clearScroll(ESClearScrollRequest request);\n\n    void clearScroll(ESClearScrollRequest request, ActionListener<ESClearScrollResponse> listener);\n\n    ActionFuture<ESSearchResponse> searchScroll(final ESSearchScrollRequest request);\n\n    void searchScroll(final ESSearchScrollRequest request, final ActionListener<ESSearchResponse> listener);\n\n    ActionFuture<ESMultiSearchResponse> multiSearch(ESMultiSearchRequest request);\n\n    void multiSearch(ESMultiSearchRequest request, ActionListener<ESMultiSearchResponse> listener);\n\n    ActionFuture<ESGetResponse> get(ESGetRequest request);\n\n    void get(ESGetRequest request, ActionListener<ESGetResponse> listener);\n\n    ActionFuture<ESMultiGetResponse> multiGet(ESMultiGetRequest request);\n\n    void multiGet(ESMultiGetRequest request, ActionListener<ESMultiGetResponse> listener);\n\n    ActionFuture<ESIndexResponse> index(ESIndexRequest request);\n\n    void index(ESIndexRequest request, ActionListener<ESIndexResponse> listener);\n\n    ActionFuture<ESUpdateResponse> update(ESUpdateRequest request);\n\n    void update(ESUpdateRequest request, ActionListener<ESUpdateResponse> listener);\n\n    ActionFuture<ESDeleteResponse> delete(ESDeleteRequest request);\n\n    void delete(ESDeleteRequest request, ActionListener<ESDeleteResponse> listener);\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/ESAbstractClient.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.model;\n\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectAction;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.*;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.*;\nimport com.didi.arius.gateway.elasticsearch.client.model.admin.*;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.ESBatchAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.ESBatchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.ESBatchRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.cat.ESCatAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.cat.ESCatRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.cat.ESCatRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.query.ESQueryAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.query.ESQueryRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.query.ESQueryRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.scroll.ESQueryScrollAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.scroll.ESQueryScrollRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.scroll.ESQueryScrollRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.sql.ESSQLAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.sql.ESSQLRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.query.sql.ESSQLRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.ESBatchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cat.ESCatResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport org.elasticsearch.action.*;\nimport org.elasticsearch.action.support.PlainActionFuture;\nimport org.elasticsearch.client.ElasticsearchClient;\nimport org.elasticsearch.threadpool.ThreadPool;\n\npublic abstract class ESAbstractClient implements Client {\n\n    private Admin admin;\n\n    protected ESAbstractClient() {\n        this.admin = new Admin(this);\n    }\n\n    @Override\n    public final ThreadPool threadPool() {\n        return null;\n    }\n\n    @Override\n    public final ESAdminClient admin() {\n        return admin;\n    }\n\n    @Override\n    public final <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>>\n    RequestBuilder prepareExecute(final Action<Request, Response, RequestBuilder> action) {\n        return action.newRequestBuilder(this);\n    }\n\n    @Override\n    public final <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>>\n    ActionFuture<Response> execute(Action<Request, Response, RequestBuilder> action, Request request) {\n        PlainActionFuture<Response> actionFuture = PlainActionFuture.newFuture();\n        execute(action, request, actionFuture);\n        return actionFuture;\n    }\n\n    /**\n     * This is the single execution point of *all* clients.\n     * 核心接口\n     */\n    @Override\n    public final <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>>\n    void execute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) {\n        doExecute(action, request, listener);\n    }\n\n    // 子类继承\n    protected abstract <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>>\n        void doExecute(final Action<Request, Response, RequestBuilder> action, final Request request, ActionListener<Response> listener);\n\n\n    @Override\n    public ActionFuture<ESQueryResponse> query(final ESQueryRequest request) {\n        return execute( ESQueryAction.INSTANCE, request);\n    }\n\n    @Override\n    public void query(final ESQueryRequest request, final ActionListener<ESQueryResponse> listener) {\n        execute(ESQueryAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESQueryRequestBuilder prepareQuery(String... indices) {\n        return new ESQueryRequestBuilder(this, ESQueryAction.INSTANCE).setIndices(indices);\n    }\n\n    @Override\n    public ActionFuture<ESQueryResponse> execSQL(ESSQLRequest request) {\n        return execute( ESSQLAction.INSTANCE, request);\n    }\n\n    @Override\n    public void execSQL(ESSQLRequest request, ActionListener<ESQueryResponse> listener) {\n        execute(ESSQLAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESSQLRequestBuilder prepareSQL(String sql) {\n        return new ESSQLRequestBuilder(this, ESSQLAction.INSTANCE).setSQL(sql);\n    }\n\n    @Override\n    public ActionFuture<ESQueryResponse> queryScroll(final ESQueryScrollRequest request) {\n        return execute( ESQueryScrollAction.INSTANCE, request);\n    }\n\n    @Override\n    public void queryScroll(final ESQueryScrollRequest request, final ActionListener<ESQueryResponse> listener) {\n        execute(ESQueryScrollAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESQueryScrollRequestBuilder prepareQueryScroll(String scrollId) {\n        return new ESQueryScrollRequestBuilder(this, ESQueryScrollAction.INSTANCE).setScrollId(scrollId);\n    }\n\n\n\n    @Override\n    public ActionFuture<ESBatchResponse> batch(final ESBatchRequest request) {\n        return execute( ESBatchAction.INSTANCE, request);\n    }\n\n    @Override\n    public void batch(final ESBatchRequest request, final ActionListener<ESBatchResponse> listener) {\n        execute(ESBatchAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESBatchRequestBuilder prepareBatch() {\n        return new ESBatchRequestBuilder(this, ESBatchAction.INSTANCE);\n    }\n\n\n\n    @Override\n    public ActionFuture<ESCatResponse> cat(final ESCatRequest request) {\n        return execute( ESCatAction.INSTANCE, request);\n    }\n\n    @Override\n    public void cat(final ESCatRequest request, final ActionListener<ESCatResponse> listener) {\n        execute(ESCatAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESCatRequestBuilder prepareCat() {\n        return new ESCatRequestBuilder(this, ESCatAction.INSTANCE);\n    }\n\n\n\n\n\n                        /******** for gateway  ********/\n    @Override\n    public ActionFuture<DirectResponse> direct(DirectRequest request) {\n        return execute( DirectAction.INSTANCE, request);\n    }\n\n    @Override\n    public void direct(DirectRequest request, ActionListener<DirectResponse> listener) {\n        execute(DirectAction.INSTANCE, request, listener);\n    }\n\n\n\n    @Override\n    public ActionFuture<ESSearchResponse> search(ESSearchRequest request) {\n        return execute( ESSearchAction.INSTANCE, request);\n    }\n\n    @Override\n    public void search(ESSearchRequest request, ActionListener<ESSearchResponse> listener) {\n        execute(ESSearchAction.INSTANCE, request, listener);\n    }\n\n\n\n    @Override\n    public ActionFuture<ESClearScrollResponse> clearScroll(ESClearScrollRequest request) {\n        return execute(ESClearScrollAction.INSTANCE, request);\n    }\n\n    @Override\n    public void clearScroll(ESClearScrollRequest request, ActionListener<ESClearScrollResponse> listener) {\n        execute(ESClearScrollAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ActionFuture<ESSearchResponse> searchScroll(final ESSearchScrollRequest request) {\n        return execute(ESSearchScrollAction.INSTANCE, request);\n    }\n\n    @Override\n    public void searchScroll(final ESSearchScrollRequest request, final ActionListener<ESSearchResponse> listener) {\n        execute(ESSearchScrollAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ActionFuture<ESMultiSearchResponse> multiSearch(ESMultiSearchRequest request) {\n        return execute(ESMultiSearchAction.INSTANCE, request);\n    }\n\n    @Override\n    public void multiSearch(ESMultiSearchRequest request, ActionListener<ESMultiSearchResponse> listener) {\n        execute(ESMultiSearchAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ActionFuture<ESGetResponse> get(ESGetRequest request) {\n        return execute( ESGetAction.INSTANCE, request);\n    }\n\n    @Override\n    public void get(ESGetRequest request, ActionListener<ESGetResponse> listener) {\n        execute(ESGetAction.INSTANCE, request, listener);\n    }\n\n\n\n    @Override\n    public ActionFuture<ESMultiGetResponse> multiGet(ESMultiGetRequest request) {\n        return execute(ESMultiGetAction.INSTANCE, request);\n    }\n\n    @Override\n    public void multiGet(ESMultiGetRequest request, ActionListener<ESMultiGetResponse> listener) {\n        execute(ESMultiGetAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ActionFuture<ESIndexResponse> index(ESIndexRequest request) {\n        return execute(ESIndexAction.INSTANCE, request);\n    }\n\n    @Override\n    public void index(ESIndexRequest request, ActionListener<ESIndexResponse> listener){\n        execute(ESIndexAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ActionFuture<ESUpdateResponse> update(ESUpdateRequest request) {\n        return execute(ESUpdateAction.INSTANCE, request);\n    }\n\n    @Override\n    public void update(ESUpdateRequest request, ActionListener<ESUpdateResponse> listener){\n        execute(ESUpdateAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ActionFuture<ESDeleteResponse> delete(ESDeleteRequest request) {\n        return execute(ESDeleteAction.INSTANCE, request);\n    }\n\n    @Override\n    public void delete(ESDeleteRequest request, ActionListener<ESDeleteResponse> listener){\n        execute(ESDeleteAction.INSTANCE, request, listener);\n    }\n\n    static class Admin implements ESAdminClient {\n\n        private final ESClusterAdmin clusterAdmin;\n        private final ESIndicesAdmin indicesAdmin;\n\n        public Admin(ElasticsearchClient client) {\n            this.clusterAdmin = new ESClusterAdmin(client);\n            this.indicesAdmin = new ESIndicesAdmin(client);\n        }\n\n        @Override\n        public ESClusterAdminClient cluster() {\n            return clusterAdmin;\n        }\n\n        @Override\n        public ESIndicesAdminClient indices() {\n            return indicesAdmin;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/ESActionRequest.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.model;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.didi.arius.gateway.common.utils.CommonUtil;\nimport org.apache.http.Header;\nimport org.apache.http.message.BasicHeader;\nimport org.elasticsearch.action.ActionRequest;\n\npublic abstract class ESActionRequest<T extends ESActionRequest> extends ActionRequest {\n    protected ESActionRequest() {\n        super();\n    }\n\n    protected ESActionRequest(ESActionRequest request) {\n        super(request);\n    }\n\n    public abstract RestRequest toRequest() throws Exception;\n\n    private int socketTimeout;\n\n    public RestRequest buildRequest(List<Header> headers) throws Exception {\n        RestRequest restRequest = toRequest();\n        List<Header> newHeaders = new ArrayList<>();\n        newHeaders.addAll(headers);\n        if (this.headers != null) {\n            for (Map.Entry<String, Object> entry : this.headers.entrySet()) {\n                if(\"Authorization\".equals(entry.getKey())){\n                    //为了接入带认证es集群，这个判断会使action下传的Auth失效,直接使用client的Auth\n                    continue;\n                }\n                Header header = new BasicHeader(entry.getKey(), entry.getValue().toString());\n                newHeaders.add(header);\n            }\n        }\n\n        if (socketTimeout > 0) {\n            restRequest.setSocketTimeOut(socketTimeout);\n        }\n\n        restRequest.setHeaders(newHeaders);\n        return restRequest;\n    }\n\n    public abstract ESActionResponse toResponse(RestResponse response) throws Exception;\n\n    public boolean checkResponse(org.elasticsearch.client.Response response) {\n        int status = response.getStatusLine().getStatusCode();\n        boolean res = false;\n        if (status == 200 || status == 202 || status == 201) {\n            res = true;\n        }\n        return res;\n    }\n\n    public ESActionResponse buildResponse(RestResponse response) throws Exception {\n        ESActionResponse esActionResponse = toResponse(response);\n        esActionResponse.setRestStatus( CommonUtil.fromCode(response.getStatusCode()));\n        esActionResponse.setHost(response.getResponse().getHost());\n\n        return  esActionResponse;\n    }\n\n    public void setSocketTimeout(int socketTimeout) {\n        this.socketTimeout = socketTimeout;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/ESActionResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.model;\n\nimport org.apache.http.HttpHost;\nimport org.elasticsearch.action.ActionResponse;\nimport org.elasticsearch.common.xcontent.ToXContent;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic abstract class ESActionResponse extends ActionResponse {\n    private RestStatus restStatus;\n\n    private HttpHost host;\n\n    private Map<String, Object> otherFields = new HashMap<>();\n\n    public RestStatus getRestStatus() {\n        return restStatus;\n    }\n\n    public void setRestStatus(RestStatus restStatus) {\n        this.restStatus = restStatus;\n    }\n\n    public HttpHost getHost() {\n        return host;\n    }\n\n    public void setHost(HttpHost host) {\n        this.host = host;\n    }\n\n    public Map<String, Object> getOtherFields() {\n        return otherFields;\n    }\n\n    public void setOtherFields(Map<String, Object> otherFields) {\n        this.otherFields = otherFields;\n    }\n\n    public void putOtherFields(String key, Object value) {\n        otherFields.put(key, value);\n    }\n\n    public org.elasticsearch.rest.RestResponse buildRestResponse(RestChannel channel) {\n        if (this instanceof ToXContent) {\n            try {\n                XContentBuilder builder = channel.newBuilder();\n                ((ToXContent)this).toXContent(builder, channel.request());\n                return new BytesRestResponse(getRestStatus(), builder);\n            } catch (IOException e) {\n                return new BytesRestResponse(getRestStatus(), XContentType.JSON.restContentType(), toString());\n            }\n        } else {\n            return new BytesRestResponse(getRestStatus(), XContentType.JSON.restContentType(), toString());\n        }\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/RestRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.model;\n\nimport java.io.IOException;\nimport java.util.*;\n\nimport com.alibaba.fastjson.JSONObject;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.http.Header;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.entity.ByteArrayEntity;\nimport org.apache.http.entity.ContentType;\nimport org.elasticsearch.client.HttpAsyncResponseConsumerFactory;\nimport org.elasticsearch.client.Request;\nimport org.elasticsearch.client.RequestOptions;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.jboss.netty.handler.codec.http.HttpMethod;\n\npublic final class RestRequest {\n\n    //default buffer limit is 300MB\n    static final int DEFAULT_BUFFER_LIMIT = 300 * 1024 * 1024;\n\n    HttpAsyncResponseConsumerFactory DEFAULT_HTTP_RESPONSE_FACTORY = new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(DEFAULT_BUFFER_LIMIT);\n\n    private String method;\n    private String endpoint;\n    private HttpEntity entity;\n    private String dsl;\n    private Map<String, String> params = new HashMap<>();\n    private List<Header> headers = new ArrayList<>();\n    private int socketTimeOut = 0;\n\n    public RestRequest(String method, String endpoint) throws IOException {\n        this(method, endpoint, null);\n    }\n\n    public RestRequest(String method, String endpoint, BytesReference body) throws IOException {\n        this.method = Objects.requireNonNull(method, \"method cannot be null\");\n        this.endpoint = Objects.requireNonNull(endpoint, \"endpoint cannot be null\");\n\n        setBody(body);\n    }\n\n    public void setBody(String body) throws IOException {\n        BytesReference source = body == null ? null : new BytesArray(body);\n        setBody(source);\n    }\n\n    public void setBody(BytesReference body) throws IOException {\n        if(body != null && body.length() > 0) {\n            entity = new ByteArrayEntity(body.toBytes(), 0, body.length(), ContentType.APPLICATION_JSON);\n            dsl = XContentHelper.convertToJson(body, false);\n        } else {\n            dsl =  \"\";\n            entity = new ByteArrayEntity(dsl.getBytes(), 0, dsl.length());\n        }\n    }\n\n    public void setContent(String content) {\n        if (content != null) {\n            entity = new ByteArrayEntity(content.getBytes(), 0, content.length(), ContentType.APPLICATION_JSON);\n        }\n    }\n\n    public void addParam(String key, String value) {\n        params.put(key, value);\n    }\n\n    public String getMethod() {\n        return method;\n    }\n\n    public String getEndpoint() {\n        return endpoint;\n    }\n\n    public void addEndpointPrefix(String prefix) {\n        if(StringUtils.isBlank(prefix)) {\n            return;\n        }\n\n        if(prefix.startsWith(\"/\")) {\n            prefix = prefix.substring(1);\n        }\n\n        if(prefix.endsWith(\"/\")) {\n            prefix = prefix.substring(0, prefix.length()-1);\n        }\n\n        if(endpoint==null) {\n            endpoint = \"\";\n        }\n\n        if(StringUtils.isBlank(endpoint)) {\n            this.endpoint = \"/\" + prefix;\n        } else {\n            this.endpoint = \"/\" + prefix + \"/\" + this.endpoint;\n        }\n    }\n\n    public HttpEntity getEntity() {\n        return entity;\n    }\n\n    public void setParams(Map<String, String> params) {\n        this.params = params;\n    }\n\n    public Map<String, String> getParams() {\n        return params;\n    }\n\n\n    public JSONObject toJSON() {\n        JSONObject obj = new JSONObject();\n        obj.put(\"method\", method);\n        obj.put(\"endpoint\", endpoint);\n        if(dsl!=null) {\n            obj.put(\"dsl\", dsl);\n        }\n        return obj;\n    }\n\n    public Request buildRequest() {\n        String uri = endpoint;\n        if (StringUtils.isNotBlank(endpoint) && !endpoint.startsWith(\"/\")) {\n            uri = \"/\" + endpoint;\n        }\n        Request request = new Request(method, uri);\n        for (Map.Entry<String, String> entry : params.entrySet()) {\n            request.addParameter(entry.getKey(), entry.getValue());\n        }\n\n\n        if(!method.equalsIgnoreCase(HttpMethod.HEAD.getName())) {\n            request.setEntity(entity);\n        }\n\n        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();\n        if(headers!=null) {\n            for (Header header : headers) {\n                builder.addHeader(header.getName(), header.getValue());\n            }\n        }\n        builder.setHttpAsyncResponseConsumerFactory(DEFAULT_HTTP_RESPONSE_FACTORY);\n        RequestOptions options = builder.build();\n        request.setOptions(options);\n\n        return request;\n    }\n\n    @Override\n    public String toString() {\n        return toJSON().toJSONString();\n    }\n\n    public List<Header> getHeaders() {\n        return headers;\n    }\n\n    public void setHeaders(List<Header> headers) {\n        this.headers = headers;\n    }\n\n    public void setSocketTimeOut(int socketTimeOut) {\n        this.socketTimeOut = socketTimeOut;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/RestResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.model;\n\nimport org.apache.http.util.EntityUtils;\nimport org.elasticsearch.client.Response;\n\nimport java.io.IOException;\nimport java.io.InputStream;\n\npublic class RestResponse {\n    private Response response;\n\n    public RestResponse(Response response) {\n        this.response = response;\n    }\n\n    public Response getResponse() {\n        return response;\n    }\n\n    public String getResponseContent() {\n        String content = null;\n        try {\n            if (response.getEntity() == null) {\n                return null;\n            }\n\n            content = EntityUtils.toString(response.getEntity());\n        } catch (IOException e) {\n            content = \"{}\";\n        }\n\n        return content;\n    }\n\n    public InputStream getResponseStream() throws IOException {\n        return response.getEntity().getContent();\n    }\n\n    public int getStatusCode() {\n        return response.getStatusLine().getStatusCode();\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/admin/ESAdminClient.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.model.admin;\n\n/**\n * Administrative actions/operations against the cluster or the indices.\n *\n *\n * @see org.elasticsearch.client.Client#admin()\n */\npublic interface ESAdminClient {\n\n    /**\n     * A client allowing to perform actions/operations against the cluster.\n     */\n    ESClusterAdminClient cluster();\n\n    /**\n     * A client allowing to perform actions/operations against the indices.\n     */\n    ESIndicesAdminClient indices();\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/admin/ESClusterAdmin.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.model.admin;\n\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.health.ESClusterHealthAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.health.ESClusterHealthRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.health.ESClusterHealthRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.nodessetting.ESClusterNodesSettingAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.nodessetting.ESClusterNodesSettingRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.nodessetting.ESClusterNodesSettingRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.nodestats.ESClusterNodesStatsAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.nodestats.ESClusterNodesStatsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.nodestats.ESClusterNodesStatsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.updatesetting.ESClusterUpdateSettingsAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.updatesetting.ESClusterUpdateSettingsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.updatesetting.ESClusterUpdateSettingsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.nodessetting.ESClusterNodesSettingResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.nodesstats.ESClusterNodesStatsResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.updatesetting.ESClusterUpdateSettingsResponse;\nimport org.elasticsearch.action.*;\nimport org.elasticsearch.client.ElasticsearchClient;\nimport org.elasticsearch.threadpool.ThreadPool;\n\npublic class ESClusterAdmin implements ESClusterAdminClient {\n\n    private final ElasticsearchClient client;\n\n    public ESClusterAdmin(ElasticsearchClient client) {\n        this.client = client;\n    }\n\n    @Override\n    public <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>>\n    void execute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) {\n        client.execute(action, request, listener);\n    }\n\n    @Override\n    public <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>>\n    ActionFuture<Response> execute(Action<Request, Response, RequestBuilder> action, Request request) {\n        return client.execute(action, request);\n    }\n\n    @Override\n    public <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>>\n    RequestBuilder prepareExecute(Action<Request, Response, RequestBuilder> action) {\n        return client.prepareExecute(action);\n    }\n\n    @Override\n    public ThreadPool threadPool() {\n        return client.threadPool();\n    }\n\n\n\n    @Override\n    public ActionFuture<ESClusterHealthResponse> health(final ESClusterHealthRequest request) {\n        return execute( ESClusterHealthAction.INSTANCE, request);\n    }\n\n    @Override\n    public void health(final ESClusterHealthRequest request, final ActionListener<ESClusterHealthResponse> listener) {\n        execute(ESClusterHealthAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESClusterHealthRequestBuilder prepareHealth() {\n        return new ESClusterHealthRequestBuilder(this, ESClusterHealthAction.INSTANCE);\n    }\n\n\n\n\n    @Override\n    public ActionFuture<ESClusterNodesStatsResponse> nodeStats(final ESClusterNodesStatsRequest request) {\n        return execute( ESClusterNodesStatsAction.INSTANCE, request);\n    }\n\n    @Override\n    public void nodeStats(final ESClusterNodesStatsRequest request, final ActionListener<ESClusterNodesStatsResponse> listener) {\n        execute(ESClusterNodesStatsAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESClusterNodesStatsRequestBuilder prepareNodeStats() {\n        return new ESClusterNodesStatsRequestBuilder(this, ESClusterNodesStatsAction.INSTANCE);\n    }\n\n\n\n\n    @Override\n    public ActionFuture<ESClusterNodesSettingResponse> nodesSetting(final ESClusterNodesSettingRequest request) {\n        return execute( ESClusterNodesSettingAction.INSTANCE, request);\n    }\n\n    @Override\n    public void nodesSetting(final ESClusterNodesSettingRequest request, final ActionListener<ESClusterNodesSettingResponse> listener) {\n        execute(ESClusterNodesSettingAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESClusterNodesSettingRequestBuilder prepareNodesSetting() {\n        return new ESClusterNodesSettingRequestBuilder(this, ESClusterNodesSettingAction.INSTANCE);\n    }\n\n\n\n\n\n    @Override\n    public ActionFuture<ESClusterUpdateSettingsResponse> updateSetting(final ESClusterUpdateSettingsRequest request) {\n        return execute( ESClusterUpdateSettingsAction.INSTANCE, request);\n    }\n\n    @Override\n    public void updateSetting(final ESClusterUpdateSettingsRequest request, final ActionListener<ESClusterUpdateSettingsResponse> listener) {\n        execute(ESClusterUpdateSettingsAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESClusterUpdateSettingsRequestBuilder prepareUpdateSettings() {\n        return new ESClusterUpdateSettingsRequestBuilder(this, ESClusterUpdateSettingsAction.INSTANCE);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/admin/ESClusterAdminClient.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.model.admin;\n\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.health.ESClusterHealthRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.health.ESClusterHealthRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.nodessetting.ESClusterNodesSettingRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.nodessetting.ESClusterNodesSettingRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.nodestats.ESClusterNodesStatsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.nodestats.ESClusterNodesStatsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.updatesetting.ESClusterUpdateSettingsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.cluster.updatesetting.ESClusterUpdateSettingsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.nodessetting.ESClusterNodesSettingResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.nodesstats.ESClusterNodesStatsResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.updatesetting.ESClusterUpdateSettingsResponse;\nimport org.elasticsearch.action.ActionFuture;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.client.AdminClient;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n * Administrative actions/operations against indices.\n *\n * @see AdminClient#cluster()\n */\npublic interface ESClusterAdminClient extends ElasticsearchClient {\n\n    ActionFuture<ESClusterHealthResponse> health(ESClusterHealthRequest request);\n\n    void health(ESClusterHealthRequest request, ActionListener<ESClusterHealthResponse> listener);\n\n    ESClusterHealthRequestBuilder prepareHealth();\n\n\n\n    ActionFuture<ESClusterNodesStatsResponse> nodeStats(final ESClusterNodesStatsRequest request);\n\n    void nodeStats(final ESClusterNodesStatsRequest request, final ActionListener<ESClusterNodesStatsResponse> listener);\n\n    ESClusterNodesStatsRequestBuilder prepareNodeStats();\n\n\n\n    ActionFuture<ESClusterNodesSettingResponse> nodesSetting(final ESClusterNodesSettingRequest request);\n\n    void nodesSetting(final ESClusterNodesSettingRequest request, final ActionListener<ESClusterNodesSettingResponse> listener);\n\n    ESClusterNodesSettingRequestBuilder prepareNodesSetting();\n\n\n    ActionFuture<ESClusterUpdateSettingsResponse> updateSetting(final ESClusterUpdateSettingsRequest request);\n\n    void updateSetting(final ESClusterUpdateSettingsRequest request, final ActionListener<ESClusterUpdateSettingsResponse> listener);\n\n    ESClusterUpdateSettingsRequestBuilder prepareUpdateSettings();\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/admin/ESIndicesAdmin.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.model.admin;\n\nimport com.didi.arius.gateway.elasticsearch.client.request.index.deleteIndex.ESIndicesDeleteIndexAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.deleteIndex.ESIndicesDeleteIndexRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.deleteIndex.ESIndicesDeleteIndexRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.deletetemplate.ESIndicesDeleteTemplateAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.deletetemplate.ESIndicesDeleteTemplateRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.deletetemplate.ESIndicesDeleteTemplateRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.exists.ESIndicesExistsAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.exists.ESIndicesExistsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.exists.ESIndicesExistsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.getalias.ESIndicesGetAliasAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.getalias.ESIndicesGetAliasRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.getalias.ESIndicesGetAliasRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.getindex.ESIndicesGetIndexAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.getindex.ESIndicesGetIndexRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.getindex.ESIndicesGetIndexRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.gettemplate.ESIndicesGetTemplateAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.gettemplate.ESIndicesGetTemplateRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.gettemplate.ESIndicesGetTemplateRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.putalias.ESIndicesPutAliasAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.putalias.ESIndicesPutAliasRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.putalias.ESIndicesPutAliasRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.putindex.ESIndicesPutIndexAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.putindex.ESIndicesPutIndexRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.putindex.ESIndicesPutIndexRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.puttemplate.ESIndicesPutTemplateAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.puttemplate.ESIndicesPutTemplateRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.puttemplate.ESIndicesPutTemplateRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.refreshindex.ESIndicesRefreshIndexAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.refreshindex.ESIndicesRefreshIndexRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.refreshindex.ESIndicesRefreshIndexRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.searchshards.ESIndicesSearchShardsAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.searchshards.ESIndicesSearchShardsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.searchshards.ESIndicesSearchShardsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.stats.ESIndicesStatsAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.stats.ESIndicesStatsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.stats.ESIndicesStatsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.updatesettings.ESIndicesUpdateSettingsAction;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.updatesettings.ESIndicesUpdateSettingsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.updatesettings.ESIndicesUpdateSettingsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.deleteindex.ESIndicesDeleteIndexResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.deletetemplate.ESIndicesDeleteTemplateResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.exists.ESIndicesExistsResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.getalias.ESIndicesGetAliasResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.getindex.ESIndicesGetIndexResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.gettemplate.ESIndicesGetTemplateResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.putalias.ESIndicesPutAliasResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.putindex.ESIndicesPutIndexResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.puttemplate.ESIndicesPutTemplateResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.refreshindex.ESIndicesRefreshIndexResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.searchshards.ESIndicesSearchShardsResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.stats.ESIndicesStatsResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.updatesettings.ESIndicesUpdateSettingsResponse;\nimport org.elasticsearch.action.*;\nimport org.elasticsearch.client.ElasticsearchClient;\nimport org.elasticsearch.threadpool.ThreadPool;\n\n\npublic class ESIndicesAdmin implements ESIndicesAdminClient {\n    private final ElasticsearchClient client;\n\n    public ESIndicesAdmin(ElasticsearchClient client) {\n        this.client = client;\n    }\n\n    @Override\n    public <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> ActionFuture<Response> execute(Action<Request, Response, RequestBuilder> action, Request request) {\n        return client.execute(action, request);\n    }\n\n    @Override\n    public <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void execute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) {\n        client.execute(action, request, listener);\n    }\n\n    @Override\n    public <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> RequestBuilder prepareExecute(Action<Request, Response, RequestBuilder> action) {\n        return client.prepareExecute(action);\n    }\n\n\n    @Override\n    public ThreadPool threadPool() {\n        return client.threadPool();\n    }\n\n    @Override\n    public ActionFuture<ESIndicesStatsResponse> stats(final ESIndicesStatsRequest request) {\n        return execute( ESIndicesStatsAction.INSTANCE, request);\n    }\n\n    @Override\n    public void stats(final ESIndicesStatsRequest request, final ActionListener<ESIndicesStatsResponse> listener) {\n        execute(ESIndicesStatsAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesStatsRequestBuilder prepareStats(String... indices) {\n        return new ESIndicesStatsRequestBuilder(this, ESIndicesStatsAction.INSTANCE).setIndices(indices);\n    }\n\n    @Override\n    public ESIndicesStatsRequestBuilder prepareStats() {\n        return new ESIndicesStatsRequestBuilder(this, ESIndicesStatsAction.INSTANCE);\n    }\n\n\n\n\n    @Override\n    public ActionFuture<ESIndicesSearchShardsResponse> searchShards(ESIndicesSearchShardsRequest request) {\n        return execute( ESIndicesSearchShardsAction.INSTANCE, request);\n    }\n\n    @Override\n    public void searchShards(ESIndicesSearchShardsRequest request, ActionListener<ESIndicesSearchShardsResponse> listener) {\n        execute(ESIndicesSearchShardsAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesSearchShardsRequestBuilder prepareSearchShards(String... indices) {\n        return new ESIndicesSearchShardsRequestBuilder(this, ESIndicesSearchShardsAction.INSTANCE).setIndices(indices);\n    }\n\n    @Override\n    public ESIndicesSearchShardsRequestBuilder prepareSearchShards() {\n        return new ESIndicesSearchShardsRequestBuilder(this, ESIndicesSearchShardsAction.INSTANCE);\n    }\n\n\n\n\n\n    @Override\n    public ActionFuture<ESIndicesGetAliasResponse> alias(ESIndicesGetAliasRequest request) {\n        return execute( ESIndicesGetAliasAction.INSTANCE, request);\n    }\n\n    @Override\n    public void alias(ESIndicesGetAliasRequest request, ActionListener<ESIndicesGetAliasResponse> listener) {\n        execute(ESIndicesGetAliasAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesGetAliasRequestBuilder prepareAlias(String... indices) {\n        return new ESIndicesGetAliasRequestBuilder(this, ESIndicesGetAliasAction.INSTANCE).setIndices(indices);\n    }\n\n    @Override\n    public ESIndicesGetAliasRequestBuilder prepareAlias() {\n        return new ESIndicesGetAliasRequestBuilder(this, ESIndicesGetAliasAction.INSTANCE);\n    }\n\n\n\n    @Override\n    public ActionFuture<ESIndicesPutAliasResponse> putAlias(ESIndicesPutAliasRequest request) {\n        return execute( ESIndicesPutAliasAction.INSTANCE, request);\n    }\n\n    @Override\n    public void putAlias(ESIndicesPutAliasRequest request, ActionListener<ESIndicesPutAliasResponse> listener) {\n        execute(ESIndicesPutAliasAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesPutAliasRequestBuilder preparePutAlias() {\n        return new ESIndicesPutAliasRequestBuilder(this, ESIndicesPutAliasAction.INSTANCE);\n    }\n\n\n\n\n\n    @Override\n    public ActionFuture<ESIndicesGetIndexResponse> getIndex(final ESIndicesGetIndexRequest request) {\n        return execute( ESIndicesGetIndexAction.INSTANCE, request);\n    }\n\n    @Override\n    public void getIndex(ESIndicesGetIndexRequest request, ActionListener<ESIndicesGetIndexResponse> listener) {\n        execute(ESIndicesGetIndexAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesGetIndexRequestBuilder prepareGetIndex(String... indices) {\n        return new ESIndicesGetIndexRequestBuilder(this, ESIndicesGetIndexAction.INSTANCE).setIndices(indices);\n    }\n\n    @Override\n    public ESIndicesGetIndexRequestBuilder prepareGetIndex() {\n        return new ESIndicesGetIndexRequestBuilder(this, ESIndicesGetIndexAction.INSTANCE);\n    }\n\n\n\n\n    @Override\n    public ActionFuture<ESIndicesPutIndexResponse> putIndex(final ESIndicesPutIndexRequest request) {\n        return execute( ESIndicesPutIndexAction.INSTANCE, request);\n    }\n\n    @Override\n    public void putIndex(ESIndicesPutIndexRequest request, ActionListener<ESIndicesPutIndexResponse> listener) {\n        execute(ESIndicesPutIndexAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesPutIndexRequestBuilder preparePutIndex(String index) {\n        return new ESIndicesPutIndexRequestBuilder(this, ESIndicesPutIndexAction.INSTANCE).setIndex(index);\n    }\n\n\n\n\n\n    @Override\n    public ActionFuture<ESIndicesDeleteIndexResponse> deleteIndex(final ESIndicesDeleteIndexRequest request) {\n        return execute( ESIndicesDeleteIndexAction.INSTANCE, request);\n    }\n\n    @Override\n    public void deleteIndex(ESIndicesDeleteIndexRequest request, ActionListener<ESIndicesDeleteIndexResponse> listener) {\n        execute(ESIndicesDeleteIndexAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesDeleteIndexRequestBuilder prepareDeleteIndex(String index) {\n        return new ESIndicesDeleteIndexRequestBuilder(this, ESIndicesDeleteIndexAction.INSTANCE).setIndex(index);\n    }\n\n\n    @Override\n    public ActionFuture<ESIndicesRefreshIndexResponse> refreshIndex(final ESIndicesRefreshIndexRequest request) {\n        return execute( ESIndicesRefreshIndexAction.INSTANCE, request);\n    }\n\n    @Override\n    public void refreshIndex(ESIndicesRefreshIndexRequest request, ActionListener<ESIndicesRefreshIndexResponse> listener) {\n        execute(ESIndicesRefreshIndexAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesRefreshIndexRequestBuilder prepareRefreshIndex(String index) {\n        return new ESIndicesRefreshIndexRequestBuilder(this, ESIndicesRefreshIndexAction.INSTANCE).setIndex(index);\n    }\n\n    @Override\n    public ActionFuture<ESIndicesGetTemplateResponse> getTemplate(final ESIndicesGetTemplateRequest request) {\n        return execute( ESIndicesGetTemplateAction.INSTANCE, request);\n    }\n\n    @Override\n    public void getTemplate(ESIndicesGetTemplateRequest request, ActionListener<ESIndicesGetTemplateResponse> listener) {\n        execute(ESIndicesGetTemplateAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesGetTemplateRequestBuilder prepareGetTemplate(String... templates) {\n        return new ESIndicesGetTemplateRequestBuilder(this, ESIndicesGetTemplateAction.INSTANCE).setTemplate(templates);\n    }\n\n    @Override\n    public ESIndicesGetTemplateRequestBuilder prepareGetTemplate() {\n        return new ESIndicesGetTemplateRequestBuilder(this, ESIndicesGetTemplateAction.INSTANCE);\n    }\n\n\n\n    @Override\n    public ActionFuture<ESIndicesPutTemplateResponse> putTemplate(final ESIndicesPutTemplateRequest request) {\n        return execute( ESIndicesPutTemplateAction.INSTANCE, request);\n    }\n\n    @Override\n    public void putTemplate(ESIndicesPutTemplateRequest request, ActionListener<ESIndicesPutTemplateResponse> listener) {\n        execute(ESIndicesPutTemplateAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesPutTemplateRequestBuilder preparePutTemplate(String template) {\n        return new ESIndicesPutTemplateRequestBuilder(this, ESIndicesPutTemplateAction.INSTANCE).setTemplate(template);\n    }\n\n\n\n\n\n    @Override\n    public ActionFuture<ESIndicesDeleteTemplateResponse> deleteTemplate(final ESIndicesDeleteTemplateRequest request) {\n        return execute( ESIndicesDeleteTemplateAction.INSTANCE, request);\n    }\n\n    @Override\n    public void deleteTemplate(ESIndicesDeleteTemplateRequest request, ActionListener<ESIndicesDeleteTemplateResponse> listener) {\n        execute(ESIndicesDeleteTemplateAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesDeleteTemplateRequestBuilder prepareDeleteTemplate(String template) {\n        return new ESIndicesDeleteTemplateRequestBuilder(this, ESIndicesDeleteTemplateAction.INSTANCE).setTemplate(template);\n    }\n\n\n\n\n    @Override\n    public ActionFuture<ESIndicesUpdateSettingsResponse> updateSettings(final ESIndicesUpdateSettingsRequest request) {\n        return execute( ESIndicesUpdateSettingsAction.INSTANCE, request);\n    }\n\n    @Override\n    public void updateSettings(ESIndicesUpdateSettingsRequest request, ActionListener<ESIndicesUpdateSettingsResponse> listener) {\n        execute(ESIndicesUpdateSettingsAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesUpdateSettingsRequestBuilder prepareUpdateSettings(String index) {\n        return new ESIndicesUpdateSettingsRequestBuilder(this, ESIndicesUpdateSettingsAction.INSTANCE).setIndex(index);\n    }\n\n\n    @Override\n    public ActionFuture<ESIndicesExistsResponse> exists(final ESIndicesExistsRequest request) {\n        return execute( ESIndicesExistsAction.INSTANCE, request);\n    }\n\n    @Override\n    public void exists(ESIndicesExistsRequest request, ActionListener<ESIndicesExistsResponse> listener) {\n        execute(ESIndicesExistsAction.INSTANCE, request, listener);\n    }\n\n    @Override\n    public ESIndicesExistsRequestBuilder prepareExists(String index) {\n        return new ESIndicesExistsRequestBuilder(this, ESIndicesExistsAction.INSTANCE).setIndex(index);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/admin/ESIndicesAdminClient.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.model.admin;\n\nimport com.didi.arius.gateway.elasticsearch.client.request.index.deleteIndex.ESIndicesDeleteIndexRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.deleteIndex.ESIndicesDeleteIndexRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.deletetemplate.ESIndicesDeleteTemplateRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.deletetemplate.ESIndicesDeleteTemplateRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.exists.ESIndicesExistsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.exists.ESIndicesExistsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.getalias.ESIndicesGetAliasRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.getalias.ESIndicesGetAliasRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.getindex.ESIndicesGetIndexRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.getindex.ESIndicesGetIndexRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.gettemplate.ESIndicesGetTemplateRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.gettemplate.ESIndicesGetTemplateRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.putalias.ESIndicesPutAliasRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.putalias.ESIndicesPutAliasRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.putindex.ESIndicesPutIndexRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.putindex.ESIndicesPutIndexRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.puttemplate.ESIndicesPutTemplateRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.puttemplate.ESIndicesPutTemplateRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.refreshindex.ESIndicesRefreshIndexRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.refreshindex.ESIndicesRefreshIndexRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.searchshards.ESIndicesSearchShardsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.searchshards.ESIndicesSearchShardsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.stats.ESIndicesStatsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.stats.ESIndicesStatsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.updatesettings.ESIndicesUpdateSettingsRequest;\nimport com.didi.arius.gateway.elasticsearch.client.request.index.updatesettings.ESIndicesUpdateSettingsRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.deleteindex.ESIndicesDeleteIndexResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.deletetemplate.ESIndicesDeleteTemplateResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.exists.ESIndicesExistsResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.getalias.ESIndicesGetAliasResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.getindex.ESIndicesGetIndexResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.gettemplate.ESIndicesGetTemplateResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.putalias.ESIndicesPutAliasResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.putindex.ESIndicesPutIndexResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.puttemplate.ESIndicesPutTemplateResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.refreshindex.ESIndicesRefreshIndexResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.searchshards.ESIndicesSearchShardsResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.stats.ESIndicesStatsResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.updatesettings.ESIndicesUpdateSettingsResponse;\nimport org.elasticsearch.action.ActionFuture;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.client.AdminClient;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n * Administrative actions/operations against indices.\n *\n * @see AdminClient#indices()\n */\npublic interface ESIndicesAdminClient extends ElasticsearchClient {\n    ActionFuture<ESIndicesStatsResponse> stats(ESIndicesStatsRequest request);\n\n    void stats(ESIndicesStatsRequest request, ActionListener<ESIndicesStatsResponse> listener);\n\n    ESIndicesStatsRequestBuilder prepareStats(String... indices);\n\n    ESIndicesStatsRequestBuilder prepareStats();\n\n\n    ActionFuture<ESIndicesSearchShardsResponse> searchShards(ESIndicesSearchShardsRequest request);\n\n    void searchShards(ESIndicesSearchShardsRequest request, ActionListener<ESIndicesSearchShardsResponse> listener);\n\n    ESIndicesSearchShardsRequestBuilder prepareSearchShards(String... indices);\n\n    ESIndicesSearchShardsRequestBuilder prepareSearchShards();\n\n\n\n\n    ActionFuture<ESIndicesGetAliasResponse> alias(ESIndicesGetAliasRequest request);\n\n    void alias(ESIndicesGetAliasRequest request, ActionListener<ESIndicesGetAliasResponse> listener);\n\n    ESIndicesGetAliasRequestBuilder prepareAlias(String... indices);\n\n    ESIndicesGetAliasRequestBuilder prepareAlias();\n\n\n\n    ActionFuture<ESIndicesPutAliasResponse> putAlias(ESIndicesPutAliasRequest request);\n\n    void putAlias(ESIndicesPutAliasRequest request, ActionListener<ESIndicesPutAliasResponse> listener);\n\n    ESIndicesPutAliasRequestBuilder preparePutAlias();\n\n\n\n\n\n\n    ActionFuture<ESIndicesGetIndexResponse> getIndex(final ESIndicesGetIndexRequest request);\n\n    void getIndex(ESIndicesGetIndexRequest request, ActionListener<ESIndicesGetIndexResponse> listener);\n\n    ESIndicesGetIndexRequestBuilder prepareGetIndex(String... indices);\n\n    ESIndicesGetIndexRequestBuilder prepareGetIndex();\n\n\n    ActionFuture<ESIndicesPutIndexResponse> putIndex(final ESIndicesPutIndexRequest request);\n\n    void putIndex(ESIndicesPutIndexRequest request, ActionListener<ESIndicesPutIndexResponse> listener);\n\n    ESIndicesPutIndexRequestBuilder preparePutIndex(String index);\n\n\n    ActionFuture<ESIndicesDeleteIndexResponse> deleteIndex(final ESIndicesDeleteIndexRequest request);\n\n    void deleteIndex(ESIndicesDeleteIndexRequest request, ActionListener<ESIndicesDeleteIndexResponse> listener);\n\n    ESIndicesDeleteIndexRequestBuilder prepareDeleteIndex(String index);\n\n\n    ActionFuture<ESIndicesRefreshIndexResponse> refreshIndex(final ESIndicesRefreshIndexRequest request);\n\n    void refreshIndex(ESIndicesRefreshIndexRequest request, ActionListener<ESIndicesRefreshIndexResponse> listener);\n\n    ESIndicesRefreshIndexRequestBuilder prepareRefreshIndex(String index);\n\n\n\n\n    ActionFuture<ESIndicesGetTemplateResponse> getTemplate(final ESIndicesGetTemplateRequest request);\n\n    void getTemplate(ESIndicesGetTemplateRequest request, ActionListener<ESIndicesGetTemplateResponse> listener);\n\n    ESIndicesGetTemplateRequestBuilder prepareGetTemplate(String... templates);\n\n    ESIndicesGetTemplateRequestBuilder prepareGetTemplate();\n\n\n    public ActionFuture<ESIndicesPutTemplateResponse> putTemplate(final ESIndicesPutTemplateRequest request);\n\n    void putTemplate(ESIndicesPutTemplateRequest request, ActionListener<ESIndicesPutTemplateResponse> listener);\n\n    ESIndicesPutTemplateRequestBuilder preparePutTemplate(String template);\n\n\n    ActionFuture<ESIndicesDeleteTemplateResponse> deleteTemplate(final ESIndicesDeleteTemplateRequest request);\n\n    void deleteTemplate(ESIndicesDeleteTemplateRequest request, ActionListener<ESIndicesDeleteTemplateResponse> listener);\n\n    ESIndicesDeleteTemplateRequestBuilder prepareDeleteTemplate(String template);\n\n\n\n\n\n    ActionFuture<ESIndicesUpdateSettingsResponse> updateSettings(final ESIndicesUpdateSettingsRequest request);\n\n    void updateSettings(ESIndicesUpdateSettingsRequest request, ActionListener<ESIndicesUpdateSettingsResponse> listener);\n\n    ESIndicesUpdateSettingsRequestBuilder prepareUpdateSettings(String index);\n\n\n    public ActionFuture<ESIndicesExistsResponse> exists(final ESIndicesExistsRequest request);\n\n    public void exists(ESIndicesExistsRequest request, ActionListener<ESIndicesExistsResponse> listener);\n\n    public ESIndicesExistsRequestBuilder prepareExists(String index);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/exception/ESAlreadyExistsException.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.model.exception;\n\npublic class ESAlreadyExistsException extends RuntimeException {\n    private final Throwable t;\n\n    public ESAlreadyExistsException(Throwable t) {\n        this.t = t;\n    }\n\n    @Override\n    public String getMessage() {\n        return t.getMessage();\n    }\n\n    public static boolean check(Throwable t) {\n        String str = t.getMessage();\n        boolean res = false;\n        if(str!=null && (str.contains(\"index_already_exists_exception\") ||\n                         str.contains(\"resource_already_exists_exception\"))) {\n            res = true;\n        }\n        return res;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/exception/ESIndexNotFoundException.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.model.exception;\n\npublic class ESIndexNotFoundException extends RuntimeException {\n    private final Throwable t;\n\n    @Override\n    public String getMessage() {\n        return t.getMessage();\n    }\n\n    public ESIndexNotFoundException(Throwable t) {\n        this.t = t;\n    }\n\n    public static boolean check(Throwable t) {\n        String str = t.getMessage();\n        boolean res = false;\n        if(str!=null && str.contains(\"index_not_found_exception\")) {\n            res = true;\n        }\n        return res;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/exception/ESIndexTemplateMissingException.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.model.exception;\n\npublic class ESIndexTemplateMissingException extends RuntimeException {\n    private final Throwable t;\n\n    public ESIndexTemplateMissingException(Throwable t) {\n        this.t = t;\n    }\n\n    @Override\n    public String getMessage() {\n        return t.getMessage();\n    }\n\n    public static boolean check(Throwable t) {\n        String str = t.getMessage();\n        boolean res = false;\n        if(str!=null && str.contains(\"index_template_missing_exception\")) {\n            res = true;\n        }\n        return res;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/exception/ExceptionFactory.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.model.exception;\n\npublic class ExceptionFactory {\n\n    private ExceptionFactory() {\n\n    }\n\n    public static Throwable translate(Throwable t) {\n        if(ESIndexNotFoundException.check(t)) {\n            return new ESIndexNotFoundException(t);\n        }\n\n        if(ESIndexTemplateMissingException.check(t)) {\n            return new ESIndexTemplateMissingException(t);\n        }\n\n        if(ESAlreadyExistsException.check(t)) {\n            return new ESAlreadyExistsException(t);\n        }\n\n        return t;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/model/type/ESVersion.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.model.type;\n\npublic enum ESVersion {\n    ES233(\"es-version2.3.3\"),\n    ES651(\"es-version6.5.1\");\n\n    private String str;\n\n    private ESVersion(String str) {\n        this.str = str;\n    }\n\n    public String getStr() {\n        return str;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/batch/BatchNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.request.batch;\n\nimport com.alibaba.fastjson.JSONObject;\n\npublic class BatchNode {\n    private BatchType batchType;\n\n    private String index;\n    private String type;\n    private String id;\n    private String content;\n\n    private String routing;\n\n    private String parent;\n\n    public BatchNode(BatchType batchType, String index, String type, String id, String content) {\n        this.batchType = batchType;\n        this.index = index;\n        this.type = type;\n        this.id = id;\n        this.content = content;\n    }\n\n    private static final String HEADER_TYPE_ID = \"{\\\"%s\\\":{\\\"_index\\\":\\\"%s\\\",\\\"_type\\\":\\\"%s\\\",\\\"_id\\\":\\\"%s\\\"}}\\n\";\n    private static final String HEADER_ID = \"{\\\"%s\\\":{\\\"_index\\\":\\\"%s\\\",\\\"_id\\\":\\\"%s\\\"}}\\n\";\n    private static final String HEADER_TYPE = \"{\\\"%s\\\":{\\\"_index\\\":\\\"%s\\\",\\\"_type\\\":\\\"%s\\\"}}\\n\";\n    private static final String HEADER_NULL = \"{\\\"%s\\\":{\\\"_index\\\":\\\"%s\\\"}}\\n\";\n    public String toMessage() throws Exception {\n        String header = null;\n        if(index==null) {\n            throw new Exception(\"index is null\");\n        }\n\n        if(content==null) {\n            throw new Exception(\"content is null\");\n        }\n\n        if (routing != null || parent != null) {\n            JSONObject jsonObject = new JSONObject();\n            jsonObject.put(\"_index\", index);\n            jsonObject.put(\"_type\", type);\n            if (id != null) {\n                jsonObject.put(\"_id\", id);\n            }\n\n            if (routing != null) {\n                jsonObject.put(\"_routing\", routing);\n            }\n\n            if (parent != null) {\n                jsonObject.put(\"_parent\", parent);\n            }\n\n            JSONObject outter = new JSONObject();\n            outter.put(batchType.getStr(), jsonObject);\n            header = outter.toJSONString();\n            header += \"\\n\";\n        }\n\n        if (header == null) {\n            header = initialHeader();\n        }\n\n        switch (batchType) {\n            case INDEX:\n                return header + content.trim() + \"\\n\";\n\n            case CREATE:\n                return header + content.trim() + \"\\n\";\n\n            case DELETE:\n                return header;\n\n            case UPDATE:\n                return header + String.format(\"{\\\"doc\\\":%s,\\\"upsert\\\":%s}%n\", content, content);\n\n            default:\n                throw new Exception(\"unknow type, type:\" + batchType);\n        }\n\n    }\n\n    private String initialHeader() {\n        String header;\n        if(type==null) {\n            if(id==null) {\n                header = String.format(HEADER_NULL, batchType.getStr(), index);\n            } else {\n                header = String.format(HEADER_ID, batchType.getStr(), index, id);\n            }\n        } else {\n            if(id==null) {\n                header = String.format(HEADER_TYPE, batchType.getStr(), index, type);\n            } else {\n                header = String.format(HEADER_TYPE_ID, batchType.getStr(), index, type, id);\n            }\n        }\n        return header;\n    }\n\n\n    public BatchType getBatchType() {\n        return batchType;\n    }\n\n    public void setBatchType(BatchType batchType) {\n        this.batchType = batchType;\n    }\n\n    public String getIndex() {\n        return index;\n    }\n\n    public void setIndex(String index) {\n        this.index = index;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public void setId(String id) {\n        this.id = id;\n    }\n\n    public String getContent() {\n        return content;\n    }\n\n    public void setContent(String content) {\n        this.content = content;\n    }\n\n    public void setRouting(String routing) {\n        this.routing = routing;\n    }\n\n    public void setParent(String parent) {\n        this.parent = parent;\n    }\n\n    public String getRouting() {\n        return routing;\n    }\n\n    public String getParent() {\n        return parent;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/batch/BatchType.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.request.batch;\n\npublic enum BatchType {\n\n    CREATE(\"create\"),\n    INDEX(\"index\"),\n    UPDATE(\"update\"),\n    DELETE(\"delete\");\n\n    private String str;\n\n    private BatchType(String s) {\n        this.str = s;\n    }\n\n    public String getStr() {\n        return str;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/batch/ESBatchAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.batch;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.ESBatchResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESBatchAction extends Action<ESBatchRequest, ESBatchResponse, ESBatchRequestBuilder> {\n\n    public static final ESBatchAction INSTANCE = new ESBatchAction();\n    public static final String NAME = \"indices:data/write/bulk\";\n\n    private ESBatchAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESBatchResponse newResponse() {\n        return new ESBatchResponse();\n    }\n\n    @Override\n    public ESBatchRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESBatchRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/batch/ESBatchRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.batch;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.ESBatchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ESBatchRequest extends ESActionRequest<ESBatchRequest> {\n\n    private static final int REQUEST_OVERHEAD = 50;\n\n    private List<BatchNode>  batchNodes = new ArrayList<>();\n\n    private long sizeInBytes = 0;\n\n    private String pipeline;\n\n    public ESBatchRequest() {\n\n    }\n\n    public ESBatchRequest(ESActionRequest request) {\n        super(request);\n    }\n\n    public String getPipeline() {\n        return pipeline;\n    }\n\n    public void setPipeline(String pipeline) {\n        this.pipeline = pipeline;\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    public void addNode(BatchNode batchNode) {\n        batchNodes.add(batchNode);\n        sizeInBytes += (batchNode.getContent() != null ? batchNode.getContent().length() : 0) + REQUEST_OVERHEAD;\n    }\n\n\n    public void addNode(BatchType batchType, String index, String type, String content) {\n        addNode(batchType, index, type, null, content);\n    }\n    public void addNode(BatchType batchType, String index, String type, String id, String content) {\n        addNode(new BatchNode(batchType, index, type, id, content));\n    }\n\n    /**\n     * The number of actions in the bulk request.\n     */\n    public int numberOfActions() {\n        return batchNodes.size();\n    }\n\n    /**\n     * The estimated size in bytes of the bulk request.\n     */\n    public long estimatedSizeInBytes() {\n        return sizeInBytes;\n    }\n\n    /**\n     * The list of requests in this bulk request.\n     */\n    public List<BatchNode> requests() {\n        return this.batchNodes;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = \"/_bulk\";\n        if (null != pipeline) {\n            endpoint = String.format(\"%s?pipeline=%s\", endpoint, pipeline);\n        }\n\n        StringBuilder sb = new StringBuilder();\n\n        for(BatchNode node : batchNodes) {\n            sb.append(node.toMessage());\n        }\n\n        RestRequest rr = new RestRequest(\"POST\", endpoint, null);\n        rr.setBody(sb.toString());\n\n        return rr;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESBatchResponse.class);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/batch/ESBatchRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.batch;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.ESBatchResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/* TODO支持异步回调函数 */\npublic class ESBatchRequestBuilder extends ActionRequestBuilder<ESBatchRequest, ESBatchResponse, ESBatchRequestBuilder> {\n\n    public ESBatchRequestBuilder(ElasticsearchClient client, ESBatchAction action) {\n        super(client, action, new ESBatchRequest());\n    }\n\n    public ESBatchRequestBuilder addNode(BatchType batchType, String index, String type, String id, String content) {\n        request.addNode(batchType, index, type, id, content);\n        return this;\n    }\n\n\n    @Override\n    public ESBatchRequest request() {\n        return request;\n    }\n\n    @Override\n    protected ESBatchRequest beforeExecute(ESBatchRequest request) {\n        return request;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/broadcast/ESBroadcastOperationRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.broadcast;\n\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.action.ActionResponse;\nimport org.elasticsearch.action.support.IndicesOptions;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic abstract class ESBroadcastOperationRequestBuilder<Request extends ESBroadcastRequest<Request>, Response extends ActionResponse, RequestBuilder extends ESBroadcastOperationRequestBuilder<Request, Response, RequestBuilder>>\n        extends ActionRequestBuilder<Request, Response, RequestBuilder> {\n\n    protected ESBroadcastOperationRequestBuilder(ElasticsearchClient client, Action<Request, Response, RequestBuilder> action, Request request) {\n        super(client, action, request);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public final RequestBuilder setIndices(String... indices) {\n        request.indices(indices);\n        return (RequestBuilder) this;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public final RequestBuilder setIndicesOptions(IndicesOptions indicesOptions) {\n        request.indicesOptions(indicesOptions);\n        return (RequestBuilder) this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/broadcast/ESBroadcastRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.broadcast;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.action.IndicesRequest;\nimport org.elasticsearch.action.support.IndicesOptions;\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.common.io.stream.StreamOutput;\n\nimport java.io.IOException;\n\n/**\n *\n */\npublic abstract class ESBroadcastRequest<T extends ESBroadcastRequest> extends ESActionRequest<T> implements IndicesRequest.Replaceable {\n\n    protected String[] indices;\n    private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpenAndForbidClosed();\n\n    protected ESBroadcastRequest() {\n\n    }\n\n    protected ESBroadcastRequest(ESActionRequest originalRequest) {\n        super(originalRequest);\n    }\n\n\n    protected ESBroadcastRequest(String[] indices) {\n        this.indices = indices;\n    }\n\n    @Override\n    public String[] indices() {\n        return indices;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public final T indices(String... indices) {\n        this.indices = indices;\n        return (T) this;\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    @Override\n    public IndicesOptions indicesOptions() {\n        return indicesOptions;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public final T indicesOptions(IndicesOptions indicesOptions) {\n        this.indicesOptions = indicesOptions;\n        return (T) this;\n    }\n\n    @Override\n    public void writeTo(StreamOutput out) throws IOException {\n        super.writeTo(out);\n        out.writeStringArrayNullable(indices);\n        indicesOptions.writeIndicesOptions(out);\n    }\n\n    @Override\n    public void readFrom(StreamInput in) throws IOException {\n        super.readFrom(in);\n        indices = in.readStringArray();\n        indicesOptions = IndicesOptions.readIndicesOptions(in);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/bulk/BulkRequestHandler.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.request.bulk;\n\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.ESBatchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.ESBatchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.bulk.BackoffPolicy;\nimport org.elasticsearch.common.logging.ESLogger;\nimport org.elasticsearch.common.logging.Loggers;\n\nimport java.util.concurrent.Semaphore;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Abstracts the low-level details of bulk request handling\n */\nabstract class BulkRequestHandler {\n    protected final ESLogger logger;\n    protected final ESClient client;\n\n    private static final String RETRY_ON_THROWABLE = \"EsRejectedExecutionException\";\n\n    protected BulkRequestHandler(ESClient client) {\n        this.client = client;\n        this.logger = Loggers.getLogger(getClass());\n    }\n\n\n    public abstract void execute(ESBatchRequest bulkRequest, long executionId);\n\n    public abstract boolean awaitClose(long timeout, TimeUnit unit) throws InterruptedException;\n\n\n    public static BulkRequestHandler syncHandler(ESClient client, BackoffPolicy backoffPolicy, ESBulkProcessor.Listener listener) {\n        return new SyncBulkRequestHandler(client, backoffPolicy, listener);\n    }\n\n    public static BulkRequestHandler asyncHandler(ESClient client, BackoffPolicy backoffPolicy, ESBulkProcessor.Listener listener, int concurrentRequests) {\n        return new AsyncBulkRequestHandler(client, backoffPolicy, listener, concurrentRequests);\n    }\n\n    private static class SyncBulkRequestHandler extends BulkRequestHandler {\n        private final ESBulkProcessor.Listener listener;\n        private final BackoffPolicy backoffPolicy;\n\n        public SyncBulkRequestHandler(ESClient client, BackoffPolicy backoffPolicy, ESBulkProcessor.Listener listener) {\n            super(client);\n            this.backoffPolicy = backoffPolicy;\n            this.listener = listener;\n        }\n\n        @Override\n        public void execute(ESBatchRequest bulkRequest, long executionId) {\n            boolean afterCalled = false;\n            try {\n                listener.beforeBulk(executionId, bulkRequest);\n                ESBatchResponse bulkResponse = Retry\n                        .on(RETRY_ON_THROWABLE)\n                        .policy(backoffPolicy)\n                        .withSyncBackoff(client, bulkRequest);\n                afterCalled = true;\n                listener.afterBulk(executionId, bulkRequest, bulkResponse);\n            } catch (InterruptedException e) {\n                Thread.currentThread().interrupt();\n                logger.info(\"Bulk request {} has been cancelled.\", e, executionId);\n                if (!afterCalled) {\n                    listener.afterBulk(executionId, bulkRequest, e);\n                }\n            } catch (Exception t) {\n                logger.warn(\"Failed to execute bulk request {}.\", t, executionId);\n                if (!afterCalled) {\n                    listener.afterBulk(executionId, bulkRequest, t);\n                }\n            }\n        }\n\n        @Override\n        public boolean awaitClose(long timeout, TimeUnit unit) throws InterruptedException {\n            // we are \"closed\" immediately as there is no request in flight\n            return true;\n        }\n    }\n\n    private static class AsyncBulkRequestHandler extends BulkRequestHandler {\n        private final BackoffPolicy backoffPolicy;\n        private final ESBulkProcessor.Listener listener;\n        private final Semaphore semaphore;\n        private final int concurrentRequests;\n\n        private AsyncBulkRequestHandler(ESClient client, BackoffPolicy backoffPolicy, ESBulkProcessor.Listener listener, int concurrentRequests) {\n            super(client);\n            this.backoffPolicy = backoffPolicy;\n            assert concurrentRequests > 0;\n            this.listener = listener;\n            this.concurrentRequests = concurrentRequests;\n            this.semaphore = new Semaphore(concurrentRequests);\n        }\n\n        @Override\n        public void execute(final ESBatchRequest bulkRequest, final long executionId) {\n            boolean bulkRequestSetupSuccessful = false;\n            boolean acquired = false;\n            try {\n                listener.beforeBulk(executionId, bulkRequest);\n                semaphore.acquire();\n                acquired = true;\n                Retry.on(RETRY_ON_THROWABLE)\n                        .policy(backoffPolicy)\n                        .withAsyncBackoff(client, bulkRequest, new ActionListener<ESBatchResponse>() {\n                            @Override\n                            public void onResponse(ESBatchResponse response) {\n                                try {\n                                    listener.afterBulk(executionId, bulkRequest, response);\n                                } finally {\n                                    semaphore.release();\n                                }\n                            }\n\n                            @Override\n                            public void onFailure(Throwable e) {\n                                try {\n                                    listener.afterBulk(executionId, bulkRequest, e);\n                                } finally {\n                                    semaphore.release();\n                                }\n                            }\n                        });\n                bulkRequestSetupSuccessful = true;\n            } catch (InterruptedException e) {\n                Thread.currentThread().interrupt();\n                logger.info(\"Bulk request {} has been cancelled.\", e, executionId);\n                listener.afterBulk(executionId, bulkRequest, e);\n            } catch (Exception t) {\n                logger.warn(\"Failed to execute bulk request {}.\", t, executionId);\n                listener.afterBulk(executionId, bulkRequest, t);\n            } finally {\n                if (!bulkRequestSetupSuccessful && acquired) {  // if we fail on client.bulk() release the semaphore\n                    semaphore.release();\n                }\n            }\n        }\n\n        @Override\n        public boolean awaitClose(long timeout, TimeUnit unit) throws InterruptedException {\n            if (semaphore.tryAcquire(this.concurrentRequests, timeout, unit)) {\n                semaphore.release(this.concurrentRequests);\n                return true;\n            }\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/bulk/ESBulkProcessor.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.request.bulk;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.ESBatchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.BatchNode;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.BatchType;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.ESBatchRequest;\nimport org.elasticsearch.action.bulk.BackoffPolicy;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.common.settings.Settings;\nimport org.elasticsearch.common.unit.ByteSizeUnit;\nimport org.elasticsearch.common.unit.ByteSizeValue;\nimport org.elasticsearch.common.unit.TimeValue;\nimport org.elasticsearch.common.util.concurrent.EsExecutors;\nimport org.elasticsearch.common.util.concurrent.FutureUtils;\n\nimport java.io.Closeable;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * A bulk processor is a thread safe bulk processing class, allowing to easily set when to \"flush\" a new bulk request\n * (either based on number of actions, based on the size, or time), and to easily control the number of concurrent bulk\n * requests allowed to be executed in parallel.\n * <p>\n * In order to create a new bulk processor, use the {@link Builder}.\n */\npublic class ESBulkProcessor implements Closeable {\n\n    /**\n     * A listener for the execution.\n     */\n    public interface Listener {\n\n        /**\n         * Callback before the bulk is executed.\n         */\n        void beforeBulk(long executionId, ESBatchRequest request);\n\n        /**\n         * Callback after a successful execution of bulk request.\n         */\n        void afterBulk(long executionId, ESBatchRequest request, ESBatchResponse response);\n\n        /**\n         * Callback after a failed execution of bulk request.\n         *\n         * Note that in case an instance of <code>InterruptedException</code> is passed, which means that request processing has been\n         * cancelled externally, the thread's interruption status has been restored prior to calling this method.\n         */\n        void afterBulk(long executionId, ESBatchRequest request, Throwable failure);\n    }\n\n    /**\n     * A builder used to create a build an instance of a bulk processor.\n     */\n    public static class Builder {\n\n        private final ESClient client;\n        private final Listener listener;\n\n        private String name;\n        private int concurrentRequests = 1;\n        private int bulkActions = 1000;\n        private ByteSizeValue bulkSize = new ByteSizeValue(5, ByteSizeUnit.MB);\n        private TimeValue flushInterval = null;\n        private BackoffPolicy backoffPolicy = BackoffPolicy.exponentialBackoff();\n\n        /**\n         * Creates a builder of bulk processor with the client to use and the listener that will be used\n         * to be notified on the completion of bulk requests.\n         */\n        public Builder(ESClient client, Listener listener) {\n            this.client = client;\n            this.listener = listener;\n        }\n\n        /**\n         * Sets an optional name to identify this bulk processor.\n         */\n        public Builder setName(String name) {\n            this.name = name;\n            return this;\n        }\n\n        /**\n         * Sets the number of concurrent requests allowed to be executed. A value of 0 means that only a single\n         * request will be allowed to be executed. A value of 1 means 1 concurrent request is allowed to be executed\n         * while accumulating new bulk requests. Defaults to <tt>1</tt>.\n         */\n        public Builder setConcurrentRequests(int concurrentRequests) {\n            this.concurrentRequests = concurrentRequests;\n            return this;\n        }\n\n        /**\n         * Sets when to flush a new bulk request based on the number of actions currently added. Defaults to\n         * <tt>1000</tt>. Can be set to <tt>-1</tt> to disable it.\n         */\n        public Builder setBulkActions(int bulkActions) {\n            this.bulkActions = bulkActions;\n            return this;\n        }\n\n        /**\n         * Sets when to flush a new bulk request based on the size of actions currently added. Defaults to\n         * <tt>5mb</tt>. Can be set to <tt>-1</tt> to disable it.\n         */\n        public Builder setBulkSize(ByteSizeValue bulkSize) {\n            this.bulkSize = bulkSize;\n            return this;\n        }\n\n        /**\n         * Sets a flush interval flushing *any* bulk actions pending if the interval passes. Defaults to not set.\n         * <p>\n         * Note, both {@link #setBulkActions(int)} and {@link #setBulkSize(ByteSizeValue)}\n         * can be set to <tt>-1</tt> with the flush interval set allowing for complete async processing of bulk actions.\n         */\n        public Builder setFlushInterval(TimeValue flushInterval) {\n            this.flushInterval = flushInterval;\n            return this;\n        }\n\n        /**\n         * Sets a custom backoff policy. The backoff policy defines how the bulk processor should handle retries of bulk requests internally\n         * in case they have failed due to resource constraints (i.e. a thread pool was full).\n         *\n         * The default is to back off exponentially.\n         *\n         * @see BackoffPolicy#exponentialBackoff()\n         */\n        public Builder setBackoffPolicy(BackoffPolicy backoffPolicy) {\n            if (backoffPolicy == null) {\n                throw new NullPointerException(\"'backoffPolicy' must not be null. To disable backoff, pass BackoffPolicy.noBackoff()\");\n            }\n            this.backoffPolicy = backoffPolicy;\n            return this;\n        }\n\n        /**\n         * Builds a new bulk processor.\n         */\n        public ESBulkProcessor build() {\n            return new ESBulkProcessor(client, backoffPolicy, listener, name, concurrentRequests, bulkActions, bulkSize, flushInterval);\n        }\n    }\n\n    public static Builder builder(ESClient client, Listener listener) {\n        if (client == null) {\n            throw new NullPointerException(\"The client you specified while building a ESBulkProcessor is null\");\n        }\n\n        return new Builder(client, listener);\n    }\n\n    private final int bulkActions;\n    private final long bulkSize;\n\n\n    private final ScheduledThreadPoolExecutor scheduler;\n    private final ScheduledFuture scheduledFuture;\n\n    private final AtomicLong executionIdGen = new AtomicLong();\n\n    private ESBatchRequest bulkRequest;\n    private final BulkRequestHandler bulkRequestHandler;\n\n    private volatile boolean closed = false;\n\n    ESBulkProcessor(ESClient client, BackoffPolicy backoffPolicy, Listener listener, @Nullable String name, int concurrentRequests, int bulkActions, ByteSizeValue bulkSize, @Nullable TimeValue flushInterval) {\n        this.bulkActions = bulkActions;\n        this.bulkSize = bulkSize.bytes();\n\n        this.bulkRequest = new ESBatchRequest();\n        this.bulkRequestHandler = (concurrentRequests == 0) ? BulkRequestHandler.syncHandler(client, backoffPolicy, listener) : BulkRequestHandler.asyncHandler(client, backoffPolicy, listener, concurrentRequests);\n\n        if (flushInterval != null) {\n            this.scheduler = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1, EsExecutors.daemonThreadFactory(Settings.EMPTY, (name != null ? \"[\" + name + \"]\" : \"\") + \"bulk_processor\"));\n            this.scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);\n            this.scheduler.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);\n            this.scheduledFuture = this.scheduler.scheduleWithFixedDelay(new Flush(), flushInterval.millis(), flushInterval.millis(), TimeUnit.MILLISECONDS);\n        } else {\n            this.scheduler = null;\n            this.scheduledFuture = null;\n        }\n    }\n\n    /**\n     * Closes the processor. If flushing by time is enabled, then it's shutdown. Any remaining bulk actions are flushed.\n     */\n    @Override\n    public void close() {\n        try {\n            awaitClose(0, TimeUnit.NANOSECONDS);\n        } catch(InterruptedException exc) {\n            Thread.currentThread().interrupt();\n        }\n    }\n\n    /**\n     * Closes the processor. If flushing by time is enabled, then it's shutdown. Any remaining bulk actions are flushed.\n     *\n     * If concurrent requests are not enabled, returns {@code true} immediately.\n     * If concurrent requests are enabled, waits for up to the specified timeout for all bulk requests to complete then returns {@code true},\n     * If the specified waiting time elapses before all bulk requests complete, {@code false} is returned.\n     *\n     * @param timeout The maximum time to wait for the bulk requests to complete\n     * @param unit The time unit of the {@code timeout} argument\n     * @return {@code true} if all bulk requests completed and {@code false} if the waiting time elapsed before all the bulk requests completed\n     * @throws InterruptedException If the current thread is interrupted\n     */\n    public synchronized boolean awaitClose(long timeout, TimeUnit unit) throws InterruptedException {\n        if (closed) {\n            return true;\n        }\n        closed = true;\n        if (this.scheduledFuture != null) {\n            FutureUtils.cancel(this.scheduledFuture);\n            this.scheduler.shutdown();\n        }\n        if (bulkRequest.numberOfActions() > 0) {\n            execute();\n        }\n        return this.bulkRequestHandler.awaitClose(timeout, unit);\n    }\n\n    public ESBulkProcessor add(BatchType batchType, String index, String type, String content) {\n        return add(batchType, index, type, null, content);\n    }\n\n    public ESBulkProcessor add(BatchType batchType, String index, String type, String id, String content) {\n        internalAdd(new BatchNode(batchType, index, type, id, content));\n        return this;\n    }\n\n    public ESBulkProcessor add(BatchNode batchNode) {\n        internalAdd(batchNode);\n        return this;\n    }\n\n    boolean isOpen() {\n        return !closed;\n    }\n\n    protected void ensureOpen() {\n        if (closed) {\n            throw new IllegalStateException(\"bulk process already closed\");\n        }\n    }\n\n    private synchronized void internalAdd(BatchNode request) {\n        ensureOpen();\n        bulkRequest.addNode(request);\n        executeIfNeeded();\n    }\n\n    private void executeIfNeeded() {\n        ensureOpen();\n        if (!isOverTheLimit()) {\n            return;\n        }\n        execute();\n    }\n\n    // (currently) needs to be executed under a lock\n    private void execute() {\n        final ESBatchRequest bulkRequestTmp = this.bulkRequest;\n        final long executionId = executionIdGen.incrementAndGet();\n\n        this.bulkRequest = new ESBatchRequest();\n        this.bulkRequestHandler.execute(bulkRequestTmp, executionId);\n    }\n\n    private boolean isOverTheLimit() {\n        boolean res = false;\n        if (bulkActions != -1 && bulkRequest.numberOfActions() >= bulkActions) {\n            res = true;\n        }\n        if (bulkSize != -1 && bulkRequest.estimatedSizeInBytes() >= bulkSize) {\n            res = true;\n        }\n        return res;\n    }\n\n    /**\n     * Flush pending delete or index requests.\n     */\n    public synchronized void flush() {\n        ensureOpen();\n        if (bulkRequest.numberOfActions() > 0) {\n            execute();\n        }\n    }\n\n    class Flush implements Runnable {\n\n        @Override\n        public void run() {\n            synchronized (ESBulkProcessor.this) {\n                if (closed) {\n                    return;\n                }\n                if (bulkRequest.numberOfActions() == 0) {\n                    return;\n                }\n                execute();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/bulk/Retry.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.request.bulk;\n\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.ESBatchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.ESBatchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.IndexResultItemNode;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.action.ActionFuture;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.bulk.BackoffPolicy;\nimport org.elasticsearch.action.support.PlainActionFuture;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.logging.ESLogger;\nimport org.elasticsearch.common.logging.Loggers;\nimport org.elasticsearch.common.unit.TimeValue;\nimport org.elasticsearch.common.util.concurrent.FutureUtils;\nimport org.elasticsearch.threadpool.ThreadPool;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.ScheduledFuture;\n\n/**\n * Encapsulates synchronous and asynchronous retry logic. While this was designed for use with ESBulkProcessor it is public so it can be used\n * by other code. Specifically it is used by the reindex module.\n */\npublic class Retry {\n    private final String retryOnThrowable;\n\n    private BackoffPolicy backoffPolicy;\n\n    public static Retry on(String retryOnThrowable) {\n        return new Retry(retryOnThrowable);\n    }\n\n    /**\n     * @param backoffPolicy The backoff policy that defines how long and how often to wait for retries.\n     */\n    public Retry policy(BackoffPolicy backoffPolicy) {\n        this.backoffPolicy = backoffPolicy;\n        return this;\n    }\n\n    Retry(String retryOnThrowable) {\n        this.retryOnThrowable = retryOnThrowable;\n    }\n\n    /**\n     * Invokes #bulk(BulkRequest, ActionListener) on the provided client. Backs off on the provided exception and delegates results to the\n     * provided listener.\n     *\n     * @param client      Client invoking the bulk request.\n     * @param bulkRequest The bulk request that should be executed.\n     * @param listener    A listener that is invoked when the bulk request finishes or completes with an exception. The listener is not\n     */\n    public void withAsyncBackoff(ESClient client, ESBatchRequest bulkRequest, ActionListener<ESBatchResponse> listener) {\n        AsyncRetryHandler r = new AsyncRetryHandler(retryOnThrowable, backoffPolicy, client, listener);\n        r.execute(bulkRequest);\n\n    }\n\n    /**\n     * Invokes #bulk(BulkRequest) on the provided client. Backs off on the provided exception.\n     *\n     * @param client      Client invoking the bulk request.\n     * @param bulkRequest The bulk request that should be executed.\n     * @return the bulk response as returned by the client.\n     * @throws Exception Any exception thrown by the callable.\n     */\n    public ESBatchResponse withSyncBackoff(ESClient client, ESBatchRequest bulkRequest) throws Exception {\n        return SyncRetryHandler\n                .create(retryOnThrowable, backoffPolicy, client)\n                .executeBlocking(bulkRequest)\n                .actionGet();\n    }\n\n    static class AbstractRetryHandler implements ActionListener<ESBatchResponse> {\n        private final ESLogger logger;\n        private final ESClient client;\n        private final ActionListener<ESBatchResponse> listener;\n        private final Iterator<TimeValue> backoff;\n        private final String retryOnThrowable;\n        // Access only when holding a client-side lock, see also #addResponses()\n        private final List<IndexResultItemNode> responses = new ArrayList<>();\n        private final long startTimestampNanos;\n        // needed to construct the next bulk request based on the response to the previous one\n        // volatile as we're called from a scheduled thread\n        private volatile ESBatchRequest currentBulkRequest;\n        private volatile ScheduledFuture<?> scheduledRequestFuture;\n\n        public AbstractRetryHandler(String retryOnThrowable, BackoffPolicy backoffPolicy, ESClient client, ActionListener<ESBatchResponse> listener) {\n            this.retryOnThrowable = retryOnThrowable;\n            this.backoff = backoffPolicy.iterator();\n            this.client = client;\n            this.listener = listener;\n            this.logger = Loggers.getLogger(getClass());\n            // in contrast to System.currentTimeMillis(), nanoTime() uses a monotonic clock under the hood\n            this.startTimestampNanos = System.nanoTime();\n        }\n\n        @Override\n        public void onResponse(ESBatchResponse bulkItemResponses) {\n            if (!bulkItemResponses.hasFailures()) {\n                // we're done here, include all responses\n                addResponses(bulkItemResponses, TruePredicate.INSTANCE);\n                finishHim();\n            } else {\n                if (canRetry(bulkItemResponses)) {\n                    addResponses(bulkItemResponses, response -> !response.isFailed());\n                    retry(createBulkRequestForRetry(bulkItemResponses));\n                } else {\n                    addResponses(bulkItemResponses, TruePredicate.INSTANCE);\n                    finishHim();\n                }\n            }\n        }\n\n        @Override\n        public void onFailure(Throwable e) {\n            try {\n                listener.onFailure(e);\n            } finally {\n                FutureUtils.cancel(scheduledRequestFuture);\n            }\n        }\n\n        private void retry(final ESBatchRequest bulkRequestForRetry) {\n            assert backoff.hasNext();\n            TimeValue next = backoff.next();\n            logger.trace(\"Retry of bulk request scheduled in {} ms.\", next.millis());\n            scheduledRequestFuture = client.threadPool().schedule(next, ThreadPool.Names.SAME, () -> AbstractRetryHandler.this.execute(bulkRequestForRetry));\n        }\n        private ESBatchRequest createBulkRequestForRetry(ESBatchResponse bulkItemResponses) {\n            ESBatchRequest requestToReissue = new ESBatchRequest(currentBulkRequest);\n            int index = 0;\n            for (IndexResultItemNode bulkItemResponse : bulkItemResponses.getItems()) {\n                if (bulkItemResponse.isFailed()) {\n                    requestToReissue.addNode(currentBulkRequest.requests().get(index));\n                }\n                index++;\n            }\n            return requestToReissue;\n        }\n\n        private boolean canRetry(ESBatchResponse bulkItemResponses) {\n            if (!backoff.hasNext()) {\n                return false;\n            }\n            for (IndexResultItemNode bulkItemResponse : bulkItemResponses.getItems()) {\n                if (bulkItemResponse.isFailed()) {\n                    String type = bulkItemResponse.getIndex().getError().getType();\n                    if (!Strings.toCamelCase(type).equals(retryOnThrowable)) {\n                        return false;\n                    }\n                }\n            }\n            return true;\n        }\n\n        private void finishHim() {\n            try {\n                listener.onResponse(getAccumulatedResponse());\n            } finally {\n                FutureUtils.cancel(scheduledRequestFuture);\n            }\n        }\n\n        private void addResponses(ESBatchResponse response, BulkItemResponsePredicate filter) {\n            for (IndexResultItemNode bulkItemResponse : response.getItems()) {\n                if (filter.test(bulkItemResponse)) {\n                    // Use client-side lock here to avoid visibility issues. This method may be called multiple times\n                    // (based on how many retries we have to issue) and relying that the response handling code will be\n                    // scheduled on the same thread is fragile.\n                    synchronized (responses) {\n                        responses.add(bulkItemResponse);\n                    }\n                }\n            }\n        }\n\n        private ESBatchResponse getAccumulatedResponse() {\n            long stopTimestamp = System.nanoTime();\n            long totalLatencyMs = TimeValue.timeValueNanos(stopTimestamp - startTimestampNanos).millis();\n            return new ESBatchResponse(responses, totalLatencyMs);\n        }\n\n        public void execute(ESBatchRequest bulkRequest) {\n            this.currentBulkRequest = bulkRequest;\n            client.batch(bulkRequest, this);\n        }\n    }\n\n    static class AsyncRetryHandler extends AbstractRetryHandler {\n        public AsyncRetryHandler(String retryOnThrowable, BackoffPolicy backoffPolicy, ESClient client, ActionListener<ESBatchResponse> listener) {\n            super(retryOnThrowable, backoffPolicy, client, listener);\n        }\n    }\n\n    static class SyncRetryHandler extends AbstractRetryHandler {\n        private final PlainActionFuture<ESBatchResponse> actionFuture;\n\n        public static SyncRetryHandler create(String retryOnThrowable, BackoffPolicy backoffPolicy, ESClient client) {\n            PlainActionFuture<ESBatchResponse> actionFuture = PlainActionFuture.newFuture();\n            return new SyncRetryHandler(retryOnThrowable, backoffPolicy, client, actionFuture);\n        }\n\n        public SyncRetryHandler(String retryOnThrowable, BackoffPolicy backoffPolicy, ESClient client, PlainActionFuture<ESBatchResponse> actionFuture) {\n            super(retryOnThrowable, backoffPolicy, client, actionFuture);\n            this.actionFuture = actionFuture;\n        }\n\n        public ActionFuture<ESBatchResponse> executeBlocking(ESBatchRequest bulkRequest) {\n            super.execute(bulkRequest);\n            return actionFuture;\n        }\n    }\n\n    private interface BulkItemResponsePredicate {\n        boolean test(IndexResultItemNode response);\n    }\n\n    private static class TruePredicate implements BulkItemResponsePredicate {\n        private static final TruePredicate INSTANCE = new TruePredicate();\n\n        @Override\n        public boolean test(IndexResultItemNode response) {\n            return true;\n        }\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cat/ESCatAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cat;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cat.ESCatResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESCatAction extends Action<ESCatRequest, ESCatResponse, ESCatRequestBuilder> {\n\n    public static final ESCatAction INSTANCE = new ESCatAction();\n    public static final String NAME = \"cluster:health\";\n\n    private ESCatAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESCatResponse newResponse() {\n        return new ESCatResponse();\n    }\n\n    @Override\n    public ESCatRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESCatRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cat/ESCatRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cat;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cat.ESCatResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ESCatRequest extends ESActionRequest<ESCatRequest> {\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    private String uri;\n    private Map<String, String> param = new HashMap<>();\n    private Class clazz;\n\n    public ESCatRequest() {\n        // pass\n    }\n\n    public ESCatRequest setUri(String uri) {\n        this.uri = uri;\n        return this;\n    }\n\n    public ESCatRequest addParam(String key, String value) {\n        param.put(key, value);\n        return this;\n    }\n\n    public ESCatRequest removeParam(String key) {\n        param.remove(key);\n        return this;\n    }\n\n    public ESCatRequest setClazz(Class clazz) {\n        this.clazz = clazz;\n        return this;\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = buildEndPoint();\n        RestRequest req = new RestRequest(\"GET\", endpoint, null);\n\n        for(Map.Entry<String,String> entry : param.entrySet()) {\n            req.addParam(entry.getKey(), entry.getValue());\n        }\n\n        return req;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return new ESCatResponse(respStr, clazz);\n    }\n\n    private String buildEndPoint() {\n        if(uri.startsWith(\"/\")) {\n            uri = uri.substring(1);\n        }\n\n        return \"_cat/\" + uri;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cat/ESCatRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cat;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cat.ESCatResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESCatRequestBuilder extends ActionRequestBuilder<ESCatRequest, ESCatResponse, ESCatRequestBuilder> {\n    public ESCatRequestBuilder(ElasticsearchClient client, ESCatAction action) {\n        super(client, action, new ESCatRequest());\n    }\n\n    public ESCatRequestBuilder setUri(String uri) {\n        this.request.setUri(uri);\n        return this;\n    }\n\n    public ESCatRequestBuilder addParam(String key, String value) {\n        this.request.addParam(key, value);\n        return this;\n    }\n\n    public ESCatRequestBuilder removeParam(String key) {\n        this.request.removeParam(key);\n        return this;\n    }\n\n    public ESCatRequestBuilder setClazz(Class clazz) {\n        this.request.setClazz(clazz);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/health/ESClusterHealthAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.health;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESClusterHealthAction extends Action<ESClusterHealthRequest, ESClusterHealthResponse, ESClusterHealthRequestBuilder> {\n\n    public static final ESClusterHealthAction INSTANCE = new ESClusterHealthAction();\n    public static final String NAME = \"cluster:health\";\n\n    private ESClusterHealthAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESClusterHealthResponse newResponse() {\n        return new ESClusterHealthResponse();\n    }\n\n    @Override\n    public ESClusterHealthRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESClusterHealthRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/health/ESClusterHealthRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.health;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\npublic class ESClusterHealthRequest extends ESActionRequest<ESClusterHealthRequest> {\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = buildEndPoint();\n        return new RestRequest(\"GET\", endpoint, null);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n\n        return JSON.parseObject(respStr, ESClusterHealthResponse.class);\n    }\n\n    private String buildEndPoint() {\n        return \"_cluster/health\";\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/health/ESClusterHealthRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.health;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.ESClusterHealthResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESClusterHealthRequestBuilder extends ActionRequestBuilder<ESClusterHealthRequest, ESClusterHealthResponse, ESClusterHealthRequestBuilder> {\n    public ESClusterHealthRequestBuilder(ElasticsearchClient client, ESClusterHealthAction action) {\n        super(client, action, new ESClusterHealthRequest());\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/nodessetting/ESClusterNodesSettingAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.nodessetting;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.nodessetting.ESClusterNodesSettingResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESClusterNodesSettingAction extends\n        Action<ESClusterNodesSettingRequest, ESClusterNodesSettingResponse, ESClusterNodesSettingRequestBuilder> {\n\n    public static final ESClusterNodesSettingAction INSTANCE = new ESClusterNodesSettingAction();\n    public static final String NAME = \"cluster:nodes/setting\";\n\n    private ESClusterNodesSettingAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESClusterNodesSettingResponse newResponse() {\n        return new ESClusterNodesSettingResponse();\n    }\n\n    @Override\n    public ESClusterNodesSettingRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESClusterNodesSettingRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/nodessetting/ESClusterNodesSettingRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.nodessetting;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.nodessetting.ESClusterNodesSettingResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\n\npublic class ESClusterNodesSettingRequest extends ESActionRequest<ESClusterNodesSettingRequest> {\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        return new RestRequest(\"GET\", \"_nodes/settings\", null);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        // TODO 新版本ES增加了_nodes字段，和node在fastjson中会冲突, 先去除_nodes处理，后续兼容这种情况\n        String respStr = response.getResponseContent();\n        JSONObject obj = JSON.parseObject(respStr);\n        obj.remove(\"_nodes\");\n\n        return JSON.parseObject(obj.toJSONString(), ESClusterNodesSettingResponse.class);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/nodessetting/ESClusterNodesSettingRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.nodessetting;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.nodessetting.ESClusterNodesSettingResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n\npublic class ESClusterNodesSettingRequestBuilder extends ActionRequestBuilder<ESClusterNodesSettingRequest, ESClusterNodesSettingResponse, ESClusterNodesSettingRequestBuilder> {\n\n    public ESClusterNodesSettingRequestBuilder(ElasticsearchClient client, ESClusterNodesSettingAction action) {\n        super(client, action, new ESClusterNodesSettingRequest());\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/nodestats/ESClusterNodesStatsAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.nodestats;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.nodesstats.ESClusterNodesStatsResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESClusterNodesStatsAction extends\n        Action<ESClusterNodesStatsRequest, ESClusterNodesStatsResponse, ESClusterNodesStatsRequestBuilder> {\n\n    public static final ESClusterNodesStatsAction INSTANCE = new ESClusterNodesStatsAction();\n    public static final String NAME = \"cluster:nodes/stats\";\n\n    private ESClusterNodesStatsAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESClusterNodesStatsResponse newResponse() {\n        return new ESClusterNodesStatsResponse();\n    }\n\n    @Override\n    public ESClusterNodesStatsRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESClusterNodesStatsRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/nodestats/ESClusterNodesStatsRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.nodestats;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.nodesstats.ESClusterNodesStatsResponse;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class ESClusterNodesStatsRequest extends ESActionRequest<ESClusterNodesStatsRequest> {\n    public static final String INDICES = \"indices\";\n    public static final String OS = \"os\";\n    public static final String PROCESS = \"process\";\n    public static final String JVM = \"jvm\";\n    public static final String THREAD_POOL = \"thread_pool\";\n    public static final String FS = \"fs\";\n    public static final String TRANSPORT = \"transport\";\n    public static final String HTTP = \"http\";\n    public static final String BREAKERS = \"breakers\";\n    public static final String SCRIPT = \"script\";\n\n    private Set<String> flags = new HashSet<>();\n    private String[] nodesIds = null;\n    private String level = null;\n\n\n    public final ESClusterNodesStatsRequest  nodesIds(String... nodesIds) {\n        this.nodesIds = nodesIds;\n        return this;\n    }\n\n    public ESClusterNodesStatsRequest level(String level) {\n        this.level = level;\n        return this;\n    }\n\n    public ESClusterNodesStatsRequest all() {\n        flags.add(INDICES);\n        flags.add(OS);\n        flags.add(PROCESS);\n        flags.add(JVM);\n        flags.add(THREAD_POOL);\n        flags.add(FS);\n        flags.add(TRANSPORT);\n        flags.add(HTTP);\n        flags.add(BREAKERS);\n        flags.add(SCRIPT);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequest clear() {\n        flags.clear();\n        return this;\n    }\n\n\n    public ESClusterNodesStatsRequest flag(String name, boolean isSet) {\n        if(isSet) {\n            flags.add(name);\n        } else {\n            flags.remove(name);\n        }\n        return this;\n    }\n\n    public boolean isSet(String name) {\n        return flags.contains(name);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = buildEndPoint();\n        RestRequest restRequest = new RestRequest(\"GET\", endpoint, null);\n\n        if(level!=null) {\n            restRequest.getParams().put(\"level\", level);\n        }\n\n        return restRequest;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        // TODO 新版本ES增加了_nodes字段，和node在fastjson中会冲突, 先去除_nodes处理，后续兼容这种情况\n        String respStr = response.getResponseContent();\n        JSONObject obj = JSON.parseObject(respStr);\n        obj.remove(\"_nodes\");\n\n        return JSON.parseObject(obj.toJSONString(), ESClusterNodesStatsResponse.class);\n    }\n\n    private String buildEndPoint() {\n        String nodes = null;\n        if(nodesIds!=null) {\n            nodes = StringUtils.join(nodesIds, \",\");\n        }\n        if(nodes!=null && nodes.trim().length()==0) {\n            nodes = null;\n        }\n\n        String flagStr = null;\n        if(flags.size()<10) {\n            flagStr = StringUtils.join(flags, \",\");\n        }\n        if(flagStr!=null && flagStr.trim().length()==0) {\n            flagStr = null;\n        }\n\n\n        if(nodes==null) {\n           if(flagStr==null) {\n               return \"_nodes/stats\";\n           } else {\n               return \"_nodes/stats/\" + flagStr.trim();\n           }\n        } else {\n           if(flagStr==null) {\n               return \"_nodes/\" +nodes.trim()+ \"/stats\";\n           } else {\n               return \"_nodes/\" +nodes.trim()+ \"/stats/\" + flagStr.trim();\n           }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/nodestats/ESClusterNodesStatsRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.nodestats;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.nodesstats.ESClusterNodesStatsResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\nimport static com.didi.arius.gateway.elasticsearch.client.request.cluster.nodestats.ESClusterNodesStatsRequest.*;\n\n/**\n *\n */\npublic class ESClusterNodesStatsRequestBuilder extends ActionRequestBuilder<ESClusterNodesStatsRequest, ESClusterNodesStatsResponse, ESClusterNodesStatsRequestBuilder> {\n\n    public ESClusterNodesStatsRequestBuilder(ElasticsearchClient client, ESClusterNodesStatsAction action) {\n        super(client, action, new ESClusterNodesStatsRequest());\n    }\n\n    public final ESClusterNodesStatsRequestBuilder setNodesIds(String... nodesIds) {\n        request.nodesIds(nodesIds);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder all() {\n        request.all();\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder clear() {\n        request.clear();\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder level(String level) {\n        request.level(level);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder setIndices(boolean indices) {\n        request.flag(INDICES, indices);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder setBreaker(boolean breaker) {\n        request.flag(BREAKERS, breaker);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder setScript(boolean script) {\n        request.flag(SCRIPT, script);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder setOs(boolean os) {\n        request.flag(OS, os);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder setProcess(boolean process) {\n        request.flag(PROCESS, process);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder setJvm(boolean jvm) {\n        request.flag(JVM, jvm);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder setThreadPool(boolean threadPool) {\n        request.flag(THREAD_POOL, threadPool);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder setFs(boolean fs) {\n        request.flag(FS, fs);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder setTransport(boolean transport) {\n        request.flag(TRANSPORT, transport);\n        return this;\n    }\n\n    public ESClusterNodesStatsRequestBuilder setHttp(boolean http) {\n        request.flag(HTTP, http);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/updatesetting/ESClusterUpdateSettingsAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.updatesetting;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.updatesetting.ESClusterUpdateSettingsResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESClusterUpdateSettingsAction extends Action<ESClusterUpdateSettingsRequest, ESClusterUpdateSettingsResponse, ESClusterUpdateSettingsRequestBuilder> {\n\n    public static final ESClusterUpdateSettingsAction INSTANCE = new ESClusterUpdateSettingsAction();\n    public static final String NAME = \"cluster:settings/update\";\n\n    private ESClusterUpdateSettingsAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESClusterUpdateSettingsResponse newResponse() {\n        return new ESClusterUpdateSettingsResponse();\n    }\n\n    @Override\n    public ESClusterUpdateSettingsRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESClusterUpdateSettingsRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/updatesetting/ESClusterUpdateSettingsRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.updatesetting;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.updatesetting.ESClusterUpdateSettingsResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.common.unit.TimeValue;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Request for an update cluster settings action\n */\npublic class ESClusterUpdateSettingsRequest extends ESActionRequest<ESClusterUpdateSettingsRequest> {\n    private static final TimeValue DEFAULT_ACK_TIMEOUT =  new TimeValue(30 , TimeUnit.SECONDS);\n    private static final String PERSISTENT_STR = \"persistent\";\n    private static final String TRANSIENT_STR = \"transient\";\n\n\n    protected TimeValue timeout = DEFAULT_ACK_TIMEOUT;\n    private Map<String, String> transients = new HashMap<>();\n    private Map<String, String> persistents = new HashMap<>();\n\n    public ESClusterUpdateSettingsRequest() {\n        // pass\n    }\n\n    public ESClusterUpdateSettingsRequest timeout(String timeout) {\n        this.timeout = TimeValue.parseTimeValue(timeout, this.timeout, getClass().getSimpleName() + \".timeout\");\n        return this;\n    }\n\n    public ESClusterUpdateSettingsRequest timeout(TimeValue timeout) {\n        this.timeout = timeout;\n        return this;\n    }\n\n\n    public ESClusterUpdateSettingsRequest addTransient(String key, String value) {\n        transients.put(key, value);\n\n        return this;\n    }\n\n    public ESClusterUpdateSettingsRequest addPersistent(String key, String value) {\n        persistents.put(key, value);\n        return this;\n    }\n\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        JSONObject obj = new JSONObject();\n\n        addSetting(TRANSIENT_STR, transients, obj);\n        addSetting(PERSISTENT_STR, persistents, obj);\n\n        RestRequest rr = new RestRequest(\"PUT\", \"/_cluster/settings\", null);\n        rr.setBody(obj.toJSONString());\n\n        if (timeout != null) {\n            rr.addParam(\"timeout\", timeout.toString());\n        }\n        return rr;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESClusterUpdateSettingsResponse.class);\n    }\n\n    private void addSetting(String name, Map<String, String> m, JSONObject root) {\n        if (m.size() == 0) {\n            return;\n        }\n\n        JSONObject o = new JSONObject();\n        for (Map.Entry<String,String> entry : m.entrySet()) {\n            o.put(entry.getKey(), entry.getValue());\n        }\n        root.put(name, o);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/cluster/updatesetting/ESClusterUpdateSettingsRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.cluster.updatesetting;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.cluster.updatesetting.ESClusterUpdateSettingsResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\nimport org.elasticsearch.common.unit.TimeValue;\n\npublic class ESClusterUpdateSettingsRequestBuilder extends ActionRequestBuilder<ESClusterUpdateSettingsRequest, ESClusterUpdateSettingsResponse, ESClusterUpdateSettingsRequestBuilder> {\n\n    public ESClusterUpdateSettingsRequestBuilder(ElasticsearchClient client, ESClusterUpdateSettingsAction action) {\n        super(client, action, new ESClusterUpdateSettingsRequest());\n    }\n\n    public ESClusterUpdateSettingsRequestBuilder addTransient(String key, String value) {\n        request.addTransient(key, value);\n        return this;\n    }\n\n    public ESClusterUpdateSettingsRequestBuilder addPersistent(String key, String value) {\n        request.addPersistent(key, value);\n        return this;\n    }\n\n\n    public ESClusterUpdateSettingsRequestBuilder setTimeout(TimeValue timeout) {\n        request.timeout(timeout);\n        return this;\n    }\n\n    public ESClusterUpdateSettingsRequestBuilder setTimeout(String timeout) {\n        request.timeout(timeout);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/deleteIndex/ESIndicesDeleteIndexAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.deleteIndex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.deleteindex.ESIndicesDeleteIndexResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesDeleteIndexAction extends Action<ESIndicesDeleteIndexRequest, ESIndicesDeleteIndexResponse, ESIndicesDeleteIndexRequestBuilder> {\n\n    public static final ESIndicesDeleteIndexAction INSTANCE = new ESIndicesDeleteIndexAction();\n    public static final String NAME = \"indices:delete/index\";\n\n    private ESIndicesDeleteIndexAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesDeleteIndexResponse newResponse() {\n        return new ESIndicesDeleteIndexResponse();\n    }\n\n    @Override\n    public ESIndicesDeleteIndexRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesDeleteIndexRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/deleteIndex/ESIndicesDeleteIndexRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.deleteIndex;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.deleteindex.ESIndicesDeleteIndexResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\npublic class ESIndicesDeleteIndexRequest extends ESActionRequest<ESIndicesDeleteIndexRequest> {\n    private String index;\n\n    public ESIndicesDeleteIndexRequest() {\n        // pass\n    }\n\n    public ESIndicesDeleteIndexRequest setIndex(String index) {\n        this.index = index;\n        return this;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        if(index==null || index.length()==0) {\n            throw new Exception(\"template is null\");\n        }\n\n        String endPoint = index;\n        return new RestRequest(\"DELETE\", endPoint, null);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESIndicesDeleteIndexResponse.class);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/deleteIndex/ESIndicesDeleteIndexRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.deleteIndex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.deleteindex.ESIndicesDeleteIndexResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesDeleteIndexRequestBuilder extends ActionRequestBuilder<ESIndicesDeleteIndexRequest, ESIndicesDeleteIndexResponse, ESIndicesDeleteIndexRequestBuilder> {\n\n    public ESIndicesDeleteIndexRequestBuilder(ElasticsearchClient client, ESIndicesDeleteIndexAction action) {\n        super(client, action, new ESIndicesDeleteIndexRequest());\n    }\n\n    public ESIndicesDeleteIndexRequestBuilder setIndex(String index) {\n        request.setIndex(index);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/deletetemplate/ESIndicesDeleteTemplateAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.deletetemplate;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.deletetemplate.ESIndicesDeleteTemplateResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesDeleteTemplateAction extends Action<ESIndicesDeleteTemplateRequest, ESIndicesDeleteTemplateResponse, ESIndicesDeleteTemplateRequestBuilder> {\n\n    public static final ESIndicesDeleteTemplateAction INSTANCE = new ESIndicesDeleteTemplateAction();\n    public static final String NAME = \"indices:delete/template\";\n\n    private ESIndicesDeleteTemplateAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesDeleteTemplateResponse newResponse() {\n        return new ESIndicesDeleteTemplateResponse();\n    }\n\n    @Override\n    public ESIndicesDeleteTemplateRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesDeleteTemplateRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/deletetemplate/ESIndicesDeleteTemplateRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.deletetemplate;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.deletetemplate.ESIndicesDeleteTemplateResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\npublic class ESIndicesDeleteTemplateRequest extends ESActionRequest<ESIndicesDeleteTemplateRequest> {\n    private String template;\n\n    public ESIndicesDeleteTemplateRequest() {\n        // pass\n    }\n\n    public ESIndicesDeleteTemplateRequest setTemplate(String template) {\n        this.template = template;\n        return this;\n    }\n\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        if(template==null || template.length()==0) {\n            throw new Exception(\"template is null\");\n        }\n\n        String endPoint = \"/_template/\" + template;\n\n        return new RestRequest(\"DELETE\", endPoint, null);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESIndicesDeleteTemplateResponse.class);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/deletetemplate/ESIndicesDeleteTemplateRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.deletetemplate;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.deletetemplate.ESIndicesDeleteTemplateResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesDeleteTemplateRequestBuilder extends ActionRequestBuilder<ESIndicesDeleteTemplateRequest, ESIndicesDeleteTemplateResponse, ESIndicesDeleteTemplateRequestBuilder> {\n\n    public ESIndicesDeleteTemplateRequestBuilder(ElasticsearchClient client, ESIndicesDeleteTemplateAction action) {\n        super(client, action, new ESIndicesDeleteTemplateRequest());\n    }\n\n    public ESIndicesDeleteTemplateRequestBuilder setTemplate(String template) {\n        request.setTemplate(template);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/exists/ESIndicesExistsAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.exists;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.exists.ESIndicesExistsResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesExistsAction extends Action<ESIndicesExistsRequest, ESIndicesExistsResponse, ESIndicesExistsRequestBuilder> {\n\n    public static final ESIndicesExistsAction INSTANCE = new ESIndicesExistsAction();\n    public static final String NAME = \"indices:exists\";\n\n    private ESIndicesExistsAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesExistsResponse newResponse() {\n        return new ESIndicesExistsResponse();\n    }\n\n    @Override\n    public ESIndicesExistsRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesExistsRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/exists/ESIndicesExistsRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.exists;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.exists.ESIndicesExistsResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\npublic class ESIndicesExistsRequest extends ESActionRequest<ESIndicesExistsRequest> {\n    private String index;\n\n    public ESIndicesExistsRequest() {\n        // pass\n    }\n\n    public ESIndicesExistsRequest setIndex(String index) {\n        this.index = index;\n        return this;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        if(index==null || index.length()==0) {\n            throw new Exception(\"template is null\");\n        }\n\n        String endPoint = index;\n\n        return new RestRequest(\"HEAD\", endPoint, null);\n    }\n\n    @Override\n    public boolean checkResponse(org.elasticsearch.client.Response response) {\n        int status = response.getStatusLine().getStatusCode();\n        if(status==404) {\n            return true;\n        }\n\n        return super.checkResponse(response);\n    }\n\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        int code = response.getStatusCode();\n\n        ESIndicesExistsResponse indicesExistsResponse = new ESIndicesExistsResponse();\n        boolean res = true;\n        if(code == 404) {\n            res = false;\n        }\n        indicesExistsResponse.setExists(res);\n\n        return indicesExistsResponse;\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/exists/ESIndicesExistsRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.exists;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.exists.ESIndicesExistsResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesExistsRequestBuilder extends ActionRequestBuilder<ESIndicesExistsRequest, ESIndicesExistsResponse, ESIndicesExistsRequestBuilder> {\n\n    public ESIndicesExistsRequestBuilder(ElasticsearchClient client, ESIndicesExistsAction action) {\n        super(client, action, new ESIndicesExistsRequest());\n    }\n\n    public ESIndicesExistsRequestBuilder setIndex(String index) {\n        request.setIndex(index);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/getalias/ESIndicesGetAliasAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.getalias;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.getalias.ESIndicesGetAliasResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESIndicesGetAliasAction extends Action<ESIndicesGetAliasRequest, ESIndicesGetAliasResponse, ESIndicesGetAliasRequestBuilder> {\n\n    public static final ESIndicesGetAliasAction INSTANCE = new ESIndicesGetAliasAction();\n    public static final String NAME = \"indices:get/alias\";\n\n    private ESIndicesGetAliasAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesGetAliasResponse newResponse() {\n        return new ESIndicesGetAliasResponse();\n    }\n\n    @Override\n    public ESIndicesGetAliasRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesGetAliasRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/getalias/ESIndicesGetAliasRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.getalias;\n\nimport com.didi.arius.gateway.elasticsearch.client.request.broadcast.ESBroadcastRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.getalias.ESIndicesGetAliasResponse;\nimport org.apache.commons.lang3.StringUtils;\n\npublic class ESIndicesGetAliasRequest extends ESBroadcastRequest<ESIndicesGetAliasRequest> {\n    private String[] indices;\n\n    public ESIndicesGetAliasRequest() {\n        // pass\n    }\n\n    public ESIndicesGetAliasRequest setIndices(String... indices) {\n        this.indices = indices;\n\n        return this;\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String indicesStr = null;\n        if(indices!=null) {\n            indicesStr = StringUtils.join(indices, \",\");\n        }\n        if(indicesStr!=null && indicesStr.length()==0) {\n            indicesStr = null;\n        }\n\n        String endPoint;\n        if(indicesStr==null) {\n            endPoint = \"/_alias\";\n        } else {\n            endPoint = indicesStr.trim()+\"/_alias\";\n        }\n\n        return new RestRequest(\"GET\", endPoint, null);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        return ESIndicesGetAliasResponse.getResponse(response.getResponseContent());\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/getalias/ESIndicesGetAliasRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.getalias;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.getalias.ESIndicesGetAliasResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesGetAliasRequestBuilder extends ActionRequestBuilder<ESIndicesGetAliasRequest, ESIndicesGetAliasResponse, ESIndicesGetAliasRequestBuilder> {\n\n    public ESIndicesGetAliasRequestBuilder(ElasticsearchClient client, ESIndicesGetAliasAction action) {\n        super(client, action, new ESIndicesGetAliasRequest());\n    }\n\n    public ESIndicesGetAliasRequestBuilder setIndices(String... indices) {\n        request.setIndices(indices);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/getindex/ESIndicesGetIndexAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.getindex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.getindex.ESIndicesGetIndexResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESIndicesGetIndexAction extends Action<ESIndicesGetIndexRequest, ESIndicesGetIndexResponse, ESIndicesGetIndexRequestBuilder> {\n\n    public static final ESIndicesGetIndexAction INSTANCE = new ESIndicesGetIndexAction();\n    public static final String NAME = \"indices:get/index\";\n\n    private ESIndicesGetIndexAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesGetIndexResponse newResponse() {\n        return new ESIndicesGetIndexResponse();\n    }\n\n    @Override\n    public ESIndicesGetIndexRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesGetIndexRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/getindex/ESIndicesGetIndexRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.getindex;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.getindex.ESIndicesGetIndexResponse;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class ESIndicesGetIndexRequest extends ESActionRequest<ESIndicesGetIndexRequest> {\n    private static final String MAPPING_STR = \"_mapping\";\n    private static final String SETTINGS_STR = \"_settings\";\n    private static final String ALIAS_STR = \"_alias\";\n\n    private String[] indices;\n    private Set<String> flags = new HashSet<>();\n\n    public ESIndicesGetIndexRequest() {\n        // pass\n    }\n\n    public ESIndicesGetIndexRequest setIndices(String... indices) {\n        this.indices = indices;\n        return this;\n    }\n\n\n    public ESIndicesGetIndexRequest mapping(boolean enable) {\n        if (enable) {\n            flags.add(MAPPING_STR);\n        } else {\n            flags.remove(MAPPING_STR);\n        }\n        return this;\n    }\n\n\n    public ESIndicesGetIndexRequest settings(boolean enable) {\n        if (enable) {\n            flags.add(SETTINGS_STR);\n        } else {\n            flags.remove(SETTINGS_STR);\n        }\n        return this;\n    }\n\n\n    public ESIndicesGetIndexRequest alias(boolean enable) {\n        if (enable) {\n            flags.add(ALIAS_STR);\n        } else {\n            flags.remove(ALIAS_STR);\n        }\n        return this;\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String indicesStr = null;\n        if (indices != null) {\n            indicesStr = StringUtils.join(indices, \",\");\n        }\n        if (indicesStr != null && indicesStr.length() == 0) {\n            indicesStr = null;\n        }\n\n\n        String flagStr = StringUtils.join(flags, \",\");\n        if (flagStr != null && flagStr.trim().length() == 0) {\n            flagStr = null;\n        }\n\n        String endPoint;\n        if (indicesStr == null) {\n            if (flagStr == null) {\n                endPoint = \"*\";\n            } else {\n                endPoint = \"*/\" + flagStr.trim();\n            }\n        } else {\n            if (flagStr == null) {\n                endPoint = indicesStr.trim();\n            } else {\n                endPoint = indicesStr.trim() + \"/\" + flagStr.trim();\n            }\n        }\n\n        return new RestRequest(\"GET\", endPoint, null);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        return ESIndicesGetIndexResponse.getResponse(response.getResponseContent());\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/getindex/ESIndicesGetIndexRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.getindex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.getindex.ESIndicesGetIndexResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesGetIndexRequestBuilder extends ActionRequestBuilder<ESIndicesGetIndexRequest, ESIndicesGetIndexResponse, ESIndicesGetIndexRequestBuilder> {\n\n    public ESIndicesGetIndexRequestBuilder(ElasticsearchClient client, ESIndicesGetIndexAction action) {\n        super(client, action, new ESIndicesGetIndexRequest());\n    }\n\n    public ESIndicesGetIndexRequestBuilder setIndices(String... indices) {\n        request.setIndices(indices);\n        return this;\n    }\n\n\n    public ESIndicesGetIndexRequestBuilder mapping(boolean enable) {\n        request.mapping(enable);\n        return this;\n    }\n\n    public ESIndicesGetIndexRequestBuilder settings(boolean enable) {\n        request.settings(enable);\n        return this;\n    }\n\n    public ESIndicesGetIndexRequestBuilder alias(boolean enable) {\n        request.alias(enable);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/gettemplate/ESIndicesGetTemplateAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.gettemplate;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.gettemplate.ESIndicesGetTemplateResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESIndicesGetTemplateAction extends Action<ESIndicesGetTemplateRequest, ESIndicesGetTemplateResponse, ESIndicesGetTemplateRequestBuilder> {\n\n    public static final ESIndicesGetTemplateAction INSTANCE = new ESIndicesGetTemplateAction();\n    public static final String NAME = \"indices:get/template\";\n\n    private ESIndicesGetTemplateAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesGetTemplateResponse newResponse() {\n        return new ESIndicesGetTemplateResponse();\n    }\n\n    @Override\n    public ESIndicesGetTemplateRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesGetTemplateRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/gettemplate/ESIndicesGetTemplateRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.gettemplate;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.gettemplate.ESIndicesGetTemplateResponse;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\npublic class ESIndicesGetTemplateRequest extends ESActionRequest<ESIndicesGetTemplateRequest> {\n    private String[] templates;\n\n    public ESIndicesGetTemplateRequest() {\n        // pass\n    }\n\n    public ESIndicesGetTemplateRequest setTemplates(String... tempaltes) {\n        this.templates = tempaltes;\n        return this;\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String tempalteStr = null;\n        if(templates!=null) {\n            tempalteStr = StringUtils.join(templates, \",\");\n        }\n        if(tempalteStr!=null && tempalteStr.length()==0) {\n            tempalteStr= null;\n        }\n\n        String endPoint;\n        if(tempalteStr==null) {\n            endPoint = \"/_template\";\n        } else {\n            endPoint = \"/_template/\" + tempalteStr.trim();\n        }\n\n        return new RestRequest(\"GET\", endPoint, null);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        return ESIndicesGetTemplateResponse.getResponse(response.getResponseContent());\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/gettemplate/ESIndicesGetTemplateRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.gettemplate;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.gettemplate.ESIndicesGetTemplateResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesGetTemplateRequestBuilder extends ActionRequestBuilder<ESIndicesGetTemplateRequest, ESIndicesGetTemplateResponse, ESIndicesGetTemplateRequestBuilder> {\n\n    public ESIndicesGetTemplateRequestBuilder(ElasticsearchClient client, ESIndicesGetTemplateAction action) {\n        super(client, action, new ESIndicesGetTemplateRequest());\n    }\n\n    public ESIndicesGetTemplateRequestBuilder setTemplate(String... template) {\n        request.setTemplates(template);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/putalias/ESIndicesPutAliasAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.putalias;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.putalias.ESIndicesPutAliasResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesPutAliasAction extends Action<ESIndicesPutAliasRequest, ESIndicesPutAliasResponse, ESIndicesPutAliasRequestBuilder> {\n\n    public static final ESIndicesPutAliasAction INSTANCE = new ESIndicesPutAliasAction();\n    public static final String NAME = \"indices:put/alias\";\n\n    private ESIndicesPutAliasAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesPutAliasResponse newResponse() {\n        return new ESIndicesPutAliasResponse();\n    }\n\n    @Override\n    public ESIndicesPutAliasRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesPutAliasRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/putalias/ESIndicesPutAliasRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.putalias;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.putalias.ESIndicesPutAliasResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ESIndicesPutAliasRequest extends ESActionRequest<ESIndicesPutAliasRequest> {\n    private List<PutAliasNode> putAliasNodeList = new ArrayList<>();\n\n\n    public ESIndicesPutAliasRequest addPutAliasNode(PutAliasNode node) {\n        putAliasNodeList.add(node);\n        return this;\n    }\n\n    public ESIndicesPutAliasRequest addPutAliasNodes(List<PutAliasNode> nodes) {\n        putAliasNodeList.addAll(nodes);\n        return this;\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        RestRequest rr = new RestRequest(\"POST\", \"/_aliases\", null);\n        JSONObject obj = new JSONObject();\n        JSONArray array = new JSONArray();\n        for(PutAliasNode node : putAliasNodeList) {\n            array.add(node.toJson());\n        }\n\n        obj.put(\"actions\", array);\n        rr.setBody(obj.toJSONString());\n\n        return rr;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESIndicesPutAliasResponse.class);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/putalias/ESIndicesPutAliasRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.putalias;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.putalias.ESIndicesPutAliasResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\nimport java.util.List;\n\npublic class ESIndicesPutAliasRequestBuilder extends ActionRequestBuilder<ESIndicesPutAliasRequest, ESIndicesPutAliasResponse, ESIndicesPutAliasRequestBuilder> {\n\n    public ESIndicesPutAliasRequestBuilder(ElasticsearchClient client, ESIndicesPutAliasAction action) {\n        super(client, action, new ESIndicesPutAliasRequest());\n    }\n\n    public ESIndicesPutAliasRequestBuilder addPutAliasNode(PutAliasNode node) {\n        request.addPutAliasNode(node);\n        return this;\n    }\n\n    public ESIndicesPutAliasRequestBuilder addPutAliasNodes(List<PutAliasNode> nodes) {\n        request.addPutAliasNodes(nodes);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/putalias/PutAliasNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.request.index.putalias;\n\nimport com.alibaba.fastjson.JSONObject;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class PutAliasNode {\n    private static final String INDEX_STR = \"index\";\n    private static final String ALIAS_STR = \"alias\";\n\n    private PutAliasType type;\n    private String index;\n    private String alias;\n    private Map<String, Object> other = new HashMap<>();\n\n    public PutAliasNode() {\n        // pass\n    }\n\n    public PutAliasType getType() {\n        return type;\n    }\n\n    public void setType(PutAliasType type) {\n        this.type = type;\n    }\n\n    public String getIndex() {\n        return index;\n    }\n\n    public void setIndex(String index) {\n        this.index = index;\n    }\n\n    public String getAlias() {\n        return alias;\n    }\n\n    public void setAlias(String alias) {\n        this.alias = alias;\n    }\n\n    public void putOtherConfig(String key, JSONObject obj) {\n        other.put(key, obj);\n    }\n\n    public JSONObject toJson() throws Exception {\n        if(type==null || index==null || alias==null) {\n            throw new Exception(\"type, index, alias is null\");\n        }\n\n        JSONObject obj = new JSONObject();\n        obj.put(INDEX_STR, index);\n        obj.put(ALIAS_STR, alias);\n        for(Map.Entry<String,Object> entry : other.entrySet()) {\n            obj.put(entry.getKey(), entry.getValue());\n        }\n\n        JSONObject ret = new JSONObject();\n        ret.put(type.getStr(), obj);\n        return ret;\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/putalias/PutAliasType.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.request.index.putalias;\n\npublic enum PutAliasType {\n    REMOVE(\"remove\"),\n    ADD(\"add\");\n\n    private String str;\n\n    private PutAliasType(String str) {\n        this.str = str;\n    }\n\n    public String getStr() {\n        return str;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/putindex/ESIndicesPutIndexAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.putindex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.putindex.ESIndicesPutIndexResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesPutIndexAction extends Action<ESIndicesPutIndexRequest, ESIndicesPutIndexResponse, ESIndicesPutIndexRequestBuilder> {\n\n    public static final ESIndicesPutIndexAction INSTANCE = new ESIndicesPutIndexAction();\n    public static final String NAME = \"indices:put/index\";\n\n    private ESIndicesPutIndexAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesPutIndexResponse newResponse() {\n        return new ESIndicesPutIndexResponse();\n    }\n\n    @Override\n    public ESIndicesPutIndexRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesPutIndexRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/putindex/ESIndicesPutIndexRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.putindex;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.putindex.ESIndicesPutIndexResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.index.IndexConfig;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\npublic class ESIndicesPutIndexRequest extends ESActionRequest<ESIndicesPutIndexRequest> {\n    private String index;\n    private String indexConfig;\n\n    public ESIndicesPutIndexRequest() {\n        // pass\n    }\n\n    public ESIndicesPutIndexRequest setIndex(String index) {\n        this.index = index;\n        return this;\n    }\n\n\n    public ESIndicesPutIndexRequest setIndexConfig(String indexConfig) {\n        this.indexConfig = indexConfig;\n        return this;\n    }\n\n\n    public ESIndicesPutIndexRequest setIndexConfig(IndexConfig indexConfig) {\n        this.indexConfig = indexConfig.toJson().toJSONString();\n        return this;\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        if(index==null || index.length()==0) {\n            throw new Exception(\"index is null\");\n        }\n\n        String endPoint = index;\n        RestRequest rr = new RestRequest(\"PUT\", endPoint, null);\n        if(indexConfig!=null) {\n            rr.setBody(indexConfig);\n        }\n\n        return rr;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESIndicesPutIndexResponse.class);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/putindex/ESIndicesPutIndexRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.putindex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.putindex.ESIndicesPutIndexResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.index.IndexConfig;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesPutIndexRequestBuilder extends ActionRequestBuilder<ESIndicesPutIndexRequest, ESIndicesPutIndexResponse, ESIndicesPutIndexRequestBuilder> {\n\n    public ESIndicesPutIndexRequestBuilder(ElasticsearchClient client, ESIndicesPutIndexAction action) {\n        super(client, action, new ESIndicesPutIndexRequest());\n    }\n\n    public ESIndicesPutIndexRequestBuilder setIndex(String index) {\n        request.setIndex(index);\n        return this;\n    }\n\n    public ESIndicesPutIndexRequestBuilder setIndexConfig(String indexConfig) {\n        request.setIndexConfig(indexConfig);\n        return this;\n    }\n\n    public ESIndicesPutIndexRequestBuilder setIndexConfig(IndexConfig indexConfig) {\n        request.setIndexConfig(indexConfig);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/puttemplate/ESIndicesPutTemplateAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.puttemplate;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.puttemplate.ESIndicesPutTemplateResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESIndicesPutTemplateAction extends Action<ESIndicesPutTemplateRequest, ESIndicesPutTemplateResponse, ESIndicesPutTemplateRequestBuilder> {\n\n    public static final ESIndicesPutTemplateAction INSTANCE = new ESIndicesPutTemplateAction();\n    public static final String NAME = \"indices:put/template\";\n\n    private ESIndicesPutTemplateAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesPutTemplateResponse newResponse() {\n        return new ESIndicesPutTemplateResponse();\n    }\n\n    @Override\n    public ESIndicesPutTemplateRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesPutTemplateRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/puttemplate/ESIndicesPutTemplateRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.puttemplate;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.type.ESVersion;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.puttemplate.ESIndicesPutTemplateResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.template.TemplateConfig;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\npublic class ESIndicesPutTemplateRequest extends ESActionRequest<ESIndicesPutTemplateRequest> {\n    private String template;\n    private String templateConfig;\n    private ESVersion esVersion = ESVersion.ES233;\n\n    public ESIndicesPutTemplateRequest() {\n        // pass\n    }\n\n    public ESIndicesPutTemplateRequest setESVersion(ESVersion version) {\n        this.esVersion = version;\n        return this;\n    }\n\n    public ESIndicesPutTemplateRequest setTemplate(String template) {\n        this.template = template;\n        return this;\n    }\n\n\n    public ESIndicesPutTemplateRequest setTemplateConfig(String templateConfig) {\n        this.templateConfig = templateConfig;\n        return this;\n    }\n\n\n    public ESIndicesPutTemplateRequest setTemplateConfig(TemplateConfig templateConfig) {\n        this.templateConfig = templateConfig.toJson(esVersion).toJSONString();\n        return this;\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        if(template==null || template.length()==0) {\n            throw new Exception(\"template is null\");\n        }\n\n        if(templateConfig==null || templateConfig.length()==0) {\n            throw new Exception(\"template config is null\");\n        }\n\n        String endPoint = \"/_template/\" + template;\n\n        RestRequest rr = new RestRequest(\"PUT\", endPoint, null);\n        rr.setBody(templateConfig);\n        return rr;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESIndicesPutTemplateResponse.class);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/puttemplate/ESIndicesPutTemplateRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.puttemplate;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.type.ESVersion;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.puttemplate.ESIndicesPutTemplateResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.template.TemplateConfig;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesPutTemplateRequestBuilder extends ActionRequestBuilder<ESIndicesPutTemplateRequest, ESIndicesPutTemplateResponse, ESIndicesPutTemplateRequestBuilder> {\n\n    public ESIndicesPutTemplateRequestBuilder(ElasticsearchClient client, ESIndicesPutTemplateAction action) {\n        super(client, action, new ESIndicesPutTemplateRequest());\n    }\n\n    public ESIndicesPutTemplateRequestBuilder setVersion(ESVersion version) {\n        request.setESVersion(version);\n        return this;\n    }\n\n\n    public ESIndicesPutTemplateRequestBuilder setTemplate(String template) {\n        request.setTemplate(template);\n        return this;\n    }\n\n    public ESIndicesPutTemplateRequestBuilder setTemplateConfig(String templateConfig) {\n        request.setTemplateConfig(templateConfig);\n        return this;\n    }\n\n    public ESIndicesPutTemplateRequestBuilder setTemplateConfig(TemplateConfig templateConfig) {\n        request.setTemplateConfig(templateConfig);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/refreshindex/ESIndicesRefreshIndexAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.refreshindex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.refreshindex.ESIndicesRefreshIndexResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesRefreshIndexAction extends Action<ESIndicesRefreshIndexRequest, ESIndicesRefreshIndexResponse, ESIndicesRefreshIndexRequestBuilder> {\n\n    public static final ESIndicesRefreshIndexAction INSTANCE = new ESIndicesRefreshIndexAction();\n    public static final String NAME = \"indices:admin/refresh\";\n\n    private ESIndicesRefreshIndexAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesRefreshIndexResponse newResponse() {\n        return new ESIndicesRefreshIndexResponse();\n    }\n\n    @Override\n    public ESIndicesRefreshIndexRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesRefreshIndexRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/refreshindex/ESIndicesRefreshIndexRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.refreshindex;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.refreshindex.ESIndicesRefreshIndexResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\npublic class ESIndicesRefreshIndexRequest extends ESActionRequest<ESIndicesRefreshIndexRequest> {\n    private String index;\n\n    public ESIndicesRefreshIndexRequest() {\n        // pass\n    }\n\n    public ESIndicesRefreshIndexRequest setIndex(String index) {\n        this.index = index;\n        return this;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        if(index==null || index.length()==0) {\n            throw new Exception(\"index is null\");\n        }\n\n        String endPoint = index + \"/_refresh\";\n\n        return new RestRequest(\"POST\", endPoint, null);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESIndicesRefreshIndexResponse.class);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/refreshindex/ESIndicesRefreshIndexRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.refreshindex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.refreshindex.ESIndicesRefreshIndexResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesRefreshIndexRequestBuilder extends ActionRequestBuilder<ESIndicesRefreshIndexRequest, ESIndicesRefreshIndexResponse, ESIndicesRefreshIndexRequestBuilder> {\n\n    public ESIndicesRefreshIndexRequestBuilder(ElasticsearchClient client, ESIndicesRefreshIndexAction action) {\n        super(client, action, new ESIndicesRefreshIndexRequest());\n    }\n\n    public ESIndicesRefreshIndexRequestBuilder setIndex(String index) {\n        request.setIndex(index);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/searchshards/ESIndicesSearchShardsAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.searchshards;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.searchshards.ESIndicesSearchShardsResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESIndicesSearchShardsAction extends Action<ESIndicesSearchShardsRequest, ESIndicesSearchShardsResponse, ESIndicesSearchShardsRequestBuilder> {\n\n    public static final ESIndicesSearchShardsAction INSTANCE = new ESIndicesSearchShardsAction();\n    public static final String NAME = \"indices:search_shards\";\n\n    private ESIndicesSearchShardsAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesSearchShardsResponse newResponse() {\n        return new ESIndicesSearchShardsResponse();\n    }\n\n    @Override\n    public ESIndicesSearchShardsRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesSearchShardsRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/searchshards/ESIndicesSearchShardsRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.searchshards;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.elasticsearch.client.request.broadcast.ESBroadcastRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.searchshards.ESIndicesSearchShardsResponse;\nimport org.apache.commons.lang3.StringUtils;\n\n\npublic class ESIndicesSearchShardsRequest extends ESBroadcastRequest<ESIndicesSearchShardsRequest> {\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = buildEndPoint();\n        return new RestRequest(\"GET\", endpoint, null);\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n\n        return JSON.parseObject(respStr, ESIndicesSearchShardsResponse.class);\n    }\n\n    private String buildEndPoint() {\n        String index = null;\n        if (indices != null && indices.length > 0) {\n            index = StringUtils.join(indices, \",\");\n        }\n\n        if (index == null) {\n                return \"/_search_shards\";\n        } else {\n                return \"/\" + index.trim() + \"/_search_shards\";\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/searchshards/ESIndicesSearchShardsRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.searchshards;\n\nimport com.didi.arius.gateway.elasticsearch.client.request.broadcast.ESBroadcastOperationRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.searchshards.ESIndicesSearchShardsResponse;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n * A request to get indices level nodestats. Allow to enable different nodestats to be returned.\n * <p>\n * By default, the {@link #setDocs(boolean)}, {@link #setStore(boolean)}, {@link #setIndexing(boolean)}\n * are enabled. Other nodestats can be enabled as well.\n * <p>\n * All the nodestats to be returned can be cleared using {@link #clear()}, at which point, specific\n * nodestats can be enabled.\n */\npublic class ESIndicesSearchShardsRequestBuilder extends ESBroadcastOperationRequestBuilder<ESIndicesSearchShardsRequest, ESIndicesSearchShardsResponse, ESIndicesSearchShardsRequestBuilder> {\n\n    public ESIndicesSearchShardsRequestBuilder(ElasticsearchClient client, ESIndicesSearchShardsAction action) {\n        super(client, action, new ESIndicesSearchShardsRequest());\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/stats/ESIndicesStatsAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.stats;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.stats.ESIndicesStatsResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESIndicesStatsAction extends Action<ESIndicesStatsRequest, ESIndicesStatsResponse, ESIndicesStatsRequestBuilder> {\n\n    public static final ESIndicesStatsAction INSTANCE = new ESIndicesStatsAction();\n    public static final String NAME = \"indices:stats\";\n\n    private ESIndicesStatsAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesStatsResponse newResponse() {\n        return new ESIndicesStatsResponse();\n    }\n\n    @Override\n    public ESIndicesStatsRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesStatsRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/stats/ESIndicesStatsRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.stats;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.elasticsearch.client.request.broadcast.ESBroadcastRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.stats.ESIndicesStatsResponse;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * A request to get indices level nodestats. Allow to enable different nodestats to be returned.\n * <p>\n * By default, all statistics are enabled.\n * <p>\n * All the nodestats to be returned can be cleared using {@link #clear()}, at which point, specific\n * nodestats can be enabled.\n */\npublic class ESIndicesStatsRequest extends ESBroadcastRequest<ESIndicesStatsRequest> {\n    public static final String COMPLETION = \"completion\";\n    public static final String STORE = \"store\";\n    public static final String INDEXING = \"indexing\";\n    public static final String TRANSLOG = \"translog\";\n    public static final String REFRESH = \"refresh\";\n    public static final String SUGGEST = \"suggest\";\n    public static final String RECOVERY = \"recovery\";\n    public static final String WARMER = \"warmer\";\n    public static final String SEGMENTS = \"segments\";\n    public static final String SEARCH = \"search\";\n    public static final String QUERY_CACHE = \"query_cache\";\n    public static final String DOCS = \"docs\";\n    public static final String FLUSH = \"flush\";\n    public static final String FIELDDATA = \"fielddata\";\n    public static final String GET = \"get\";\n    public static final String MERGE = \"merge\";\n    public static final String REQUEST_CACHE = \"request_cache\";\n\n    private Set<String> flags = new HashSet<>();\n    private IndicesStatsLevel level = null;\n\n    /**\n     * Sets all flags to return all nodestats.\n     */\n    public ESIndicesStatsRequest all() {\n        flags.add(COMPLETION);\n        flags.add(INDEXING);\n        flags.add(TRANSLOG);\n        flags.add(REFRESH);\n        flags.add(SUGGEST);\n        flags.add(RECOVERY);\n        flags.add(WARMER);\n        flags.add(SEGMENTS);\n        flags.add(SEARCH);\n        flags.add(QUERY_CACHE);\n        flags.add(DOCS);\n        flags.add(FLUSH);\n        flags.add(FIELDDATA);\n        flags.add(GET);\n        flags.add(MERGE);\n        flags.add(REQUEST_CACHE);\n\n        return this;\n    }\n\n    /**\n     * Clears all nodestats.\n     */\n    public ESIndicesStatsRequest clear() {\n        flags.clear();\n        return this;\n    }\n\n    public ESIndicesStatsRequest types(String... types) {\n        for (String type : types) {\n            flags.add(type);\n        }\n        return this;\n    }\n\n\n    public ESIndicesStatsRequest flag(String type, boolean isSet) {\n        if (isSet) {\n            flags.add(type);\n        } else {\n            flags.remove(type);\n        }\n        return this;\n    }\n\n   public ESIndicesStatsRequest setLevel(IndicesStatsLevel level) {\n        this.level = level;\n\n        return this;\n    }\n\n    public boolean isSet(String type) {\n        return flags.contains(type);\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = buildEndPoint();\n        RestRequest rr = new RestRequest(\"GET\", endpoint, null);\n\n        if(level!=null) {\n            rr.addParam(\"level\", level.getStr());\n        }\n\n        return rr;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n\n\n        return JSON.parseObject(respStr, ESIndicesStatsResponse.class);\n    }\n\n    private String buildEndPoint() {\n        String type = null;\n        if (flags != null && !flags.isEmpty()) {\n            type = StringUtils.join(flags, \",\");\n        }\n        if (type != null && type.trim().length() == 0) {\n            type = null;\n        }\n\n        String index = null;\n        if (indices != null && indices.length > 0) {\n            index = StringUtils.join(indices, \",\");\n        }\n\n        if (index == null) {\n            if (type == null) {\n                return \"/_stats\";\n            } else {\n                return \"/_stats/\" + type.trim();\n            }\n        } else {\n            if (type == null) {\n                return \"/\" + index.trim() + \"/_stats\";\n            } else {\n                return \"/\" + index.trim() + \"/_stats/\" + type.trim();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/stats/ESIndicesStatsRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.stats;\n\nimport com.didi.arius.gateway.elasticsearch.client.request.broadcast.ESBroadcastOperationRequestBuilder;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.stats.ESIndicesStatsResponse;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n * A request to get indices level nodestats. Allow to enable different nodestats to be returned.\n * <p>\n * By default, the {@link #setDocs(boolean)}, {@link #setStore(boolean)}, {@link #setIndexing(boolean)}\n * are enabled. Other nodestats can be enabled as well.\n * <p>\n * All the nodestats to be returned can be cleared using {@link #clear()}, at which point, specific\n * nodestats can be enabled.\n */\npublic class ESIndicesStatsRequestBuilder extends ESBroadcastOperationRequestBuilder<ESIndicesStatsRequest, ESIndicesStatsResponse, ESIndicesStatsRequestBuilder> {\n\n    public ESIndicesStatsRequestBuilder(ElasticsearchClient client, ESIndicesStatsAction action) {\n        super(client, action, new ESIndicesStatsRequest());\n    }\n\n    /**\n     * Sets all flags to return all nodestats.\n     */\n    public ESIndicesStatsRequestBuilder all() {\n        request.all();\n        return this;\n    }\n\n    /**\n     * Clears all nodestats.\n     */\n    public ESIndicesStatsRequestBuilder clear() {\n        request.clear();\n        return this;\n    }\n\n    /**\n     * Document types to return nodestats for. Mainly affects {@link #setIndexing(boolean)} when\n     * enabled, returning specific indexing nodestats for those types.\n     */\n    public ESIndicesStatsRequestBuilder setTypes(String... types) {\n        request.types(types);\n        return this;\n    }\n\n\n    public ESIndicesStatsRequestBuilder setDocs(boolean docs) {\n        request.flag( ESIndicesStatsRequest.DOCS, docs);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setStore(boolean store) {\n        request.flag( ESIndicesStatsRequest.STORE, store);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setIndexing(boolean indexing) {\n        request.flag( ESIndicesStatsRequest.INDEXING, indexing);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setGet(boolean get) {\n        request.flag( ESIndicesStatsRequest.GET, get);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setSearch(boolean search) {\n        request.flag( ESIndicesStatsRequest.SEARCH, search);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setMerge(boolean merge) {\n        request.flag( ESIndicesStatsRequest.MERGE, merge);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setRefresh(boolean refresh) {\n        request.flag( ESIndicesStatsRequest.REFRESH, refresh);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setFlush(boolean flush) {\n        request.flag( ESIndicesStatsRequest.FLUSH, flush);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setWarmer(boolean warmer) {\n        request.flag( ESIndicesStatsRequest.WARMER, warmer);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setQueryCache(boolean queryCache) {\n        request.flag( ESIndicesStatsRequest.QUERY_CACHE, queryCache);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setFieldData(boolean fieldData) {\n        request.flag( ESIndicesStatsRequest.FIELDDATA, fieldData);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setSegments(boolean segments) {\n        request.flag( ESIndicesStatsRequest.SEGMENTS, segments);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setCompletion(boolean completion) {\n        request.flag( ESIndicesStatsRequest.COMPLETION, completion);\n        return this;\n    }\n\n\n    public ESIndicesStatsRequestBuilder setTranslog(boolean translog) {\n        request.flag( ESIndicesStatsRequest.TRANSLOG, translog);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setSuggest(boolean suggest) {\n        request.flag( ESIndicesStatsRequest.SUGGEST, suggest);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setRequestCache(boolean requestCache) {\n        request.flag( ESIndicesStatsRequest.REQUEST_CACHE, requestCache);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setRecovery(boolean recovery) {\n        request.flag( ESIndicesStatsRequest.RECOVERY, recovery);\n        return this;\n    }\n\n    public ESIndicesStatsRequestBuilder setLevel(IndicesStatsLevel level) {\n        request.setLevel(level);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/stats/IndicesStatsLevel.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.request.index.stats;\n\npublic enum IndicesStatsLevel {\n    CLUSTER(\"cluster\"),\n    INDICES(\"indices\"),\n    SHARDS(\"shards\");\n\n\n    private String str;\n\n    private IndicesStatsLevel(String str) {\n        this.str = str;\n    }\n\n    public String getStr() {\n        return str;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/updatesettings/ESIndicesUpdateSettingsAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.updatesettings;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.updatesettings.ESIndicesUpdateSettingsResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesUpdateSettingsAction extends Action<ESIndicesUpdateSettingsRequest, ESIndicesUpdateSettingsResponse, ESIndicesUpdateSettingsRequestBuilder> {\n\n    public static final ESIndicesUpdateSettingsAction INSTANCE = new ESIndicesUpdateSettingsAction();\n    public static final String NAME = \"indices:update/settings\";\n\n    private ESIndicesUpdateSettingsAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESIndicesUpdateSettingsResponse newResponse() {\n        return new ESIndicesUpdateSettingsResponse();\n    }\n\n    @Override\n    public ESIndicesUpdateSettingsRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESIndicesUpdateSettingsRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/updatesettings/ESIndicesUpdateSettingsRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.updatesettings;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.updatesettings.ESIndicesUpdateSettingsResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.JsonUtils;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ESIndicesUpdateSettingsRequest extends ESActionRequest<ESIndicesUpdateSettingsRequest> {\n    private String index;\n    private Map<String, String> settings = new HashMap<>();\n\n    public ESIndicesUpdateSettingsRequest() {\n        // pass\n    }\n\n    public ESIndicesUpdateSettingsRequest setIndex(String index) {\n        this.index = index;\n        return this;\n    }\n\n\n    public ESIndicesUpdateSettingsRequest addSettings(String key, String value) {\n        settings.put(key, value);\n        return this;\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        if(index==null || index.length()==0) {\n            throw new Exception(\"index is null\");\n        }\n\n        String endPoint = \"/\" + index.trim() + \"/_settings\";\n        RestRequest rr = new RestRequest(\"PUT\", endPoint, null);\n\n        JSONObject obj = new JSONObject();\n        obj.put(\"index\", JsonUtils.reFlat(settings));\n        rr.setBody(obj.toJSONString());\n        return rr;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESIndicesUpdateSettingsResponse.class);\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/index/updatesettings/ESIndicesUpdateSettingsRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.index.updatesettings;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.updatesettings.ESIndicesUpdateSettingsResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\npublic class ESIndicesUpdateSettingsRequestBuilder extends ActionRequestBuilder<ESIndicesUpdateSettingsRequest, ESIndicesUpdateSettingsResponse, ESIndicesUpdateSettingsRequestBuilder> {\n\n    public ESIndicesUpdateSettingsRequestBuilder(ElasticsearchClient client, ESIndicesUpdateSettingsAction action) {\n        super(client, action, new ESIndicesUpdateSettingsRequest());\n    }\n\n    public ESIndicesUpdateSettingsRequestBuilder setIndex(String index) {\n        request.setIndex(index);\n        return this;\n    }\n\n    public ESIndicesUpdateSettingsRequestBuilder addSettings(String key, String value) {\n        request.addSettings(key, value);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/clearScroll/ESQueryClearScrollAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.clearScroll;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.query.clearScroll.ESQueryClearScrollResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESQueryClearScrollAction extends Action<ESQueryClearScrollRequest, ESQueryClearScrollResponse, ESQueryClearScrollRequestBuilder> {\n\n    public static final ESQueryClearScrollAction INSTANCE = new ESQueryClearScrollAction();\n    public static final String NAME = \"query:clear/scroll\";\n\n    private ESQueryClearScrollAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESQueryClearScrollResponse newResponse() {\n        return new ESQueryClearScrollResponse();\n    }\n\n    @Override\n    public ESQueryClearScrollRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESQueryClearScrollRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/clearScroll/ESQueryClearScrollRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.clearScroll;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.response.query.clearScroll.ESQueryClearScrollResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ESQueryClearScrollRequest extends ESActionRequest<ESQueryClearScrollRequest> {\n\n    private List<String> scrollIds = new ArrayList<>();\n\n    public ESQueryClearScrollRequest() {\n        // pass\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endPoint = \"/_search/scroll\";\n        JSONObject scrollJson = new JSONObject();\n        scrollJson.put(\"scroll_id\", scrollIds);\n        RestRequest restRequest = new RestRequest(\"DELETE\", endPoint, null);\n        restRequest.setBody(scrollJson.toJSONString());\n        return restRequest;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        String respStr = response.getResponseContent();\n        return JSON.parseObject(respStr, ESQueryClearScrollResponse.class);\n    }\n\n    public List<String> getScrollIds() {\n        return scrollIds;\n    }\n\n    public void setScrollIds(List<String> scrollIds) {\n        this.scrollIds = scrollIds;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/clearScroll/ESQueryClearScrollRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.clearScroll;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.query.clearScroll.ESQueryClearScrollResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n * A search request request builder.\n */\npublic class ESQueryClearScrollRequestBuilder extends ActionRequestBuilder<ESQueryClearScrollRequest, ESQueryClearScrollResponse, ESQueryClearScrollRequestBuilder> {\n\n    public ESQueryClearScrollRequestBuilder(ElasticsearchClient client, ESQueryClearScrollAction action) {\n        super(client, action, new ESQueryClearScrollRequest());\n    }\n\n    @Override\n    public ESQueryClearScrollRequest request() {\n        return request;\n    }\n\n    @Override\n    protected ESQueryClearScrollRequest beforeExecute(ESQueryClearScrollRequest request) {\n        return request;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/query/ESQueryAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.query;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESQueryAction extends Action<ESQueryRequest, ESQueryResponse, ESQueryRequestBuilder> {\n\n    public static final ESQueryAction INSTANCE = new ESQueryAction();\n    public static final String NAME = \"query:query\";\n\n    private ESQueryAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESQueryResponse newResponse() {\n        return new ESQueryResponse();\n    }\n\n    @Override\n    public ESQueryRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESQueryRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/query/ESQueryRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.query;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.action.IndicesRequest;\nimport org.elasticsearch.action.search.SearchType;\nimport org.elasticsearch.action.support.IndicesOptions;\nimport org.elasticsearch.client.Requests;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.unit.TimeValue;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.search.builder.SearchSourceBuilder;\n\n/**\n * A request to execute search against one or more indices (or all). Best created using\n * {@link Requests#searchRequest(String...)}.\n * <p>\n * Note, the search {@link #source(SearchSourceBuilder)}\n * is required. The search source is the different search options, including aggregations and such.\n * <p>\n *\n * @see Requests#searchRequest(String...)\n */\npublic class ESQueryRequest extends ESActionRequest<ESQueryRequest> implements IndicesRequest.Replaceable {\n\n    private Class clazz = null;\n\n    private String[] indices;\n\n    private String routing;\n\n    private String preference;\n\n    private BytesReference source;\n\n    private TimeValue scrollTime;\n\n    private String[] types = Strings.EMPTY_ARRAY;\n\n\n    public ESQueryRequest() {\n    }\n\n\n    public ESQueryRequest(String... indices) {\n        indices(indices);\n    }\n\n    public ESQueryRequest(String[] indices, byte[] source) {\n        indices(indices);\n        source(source);\n    }\n\n    public ESQueryRequest clazz(Class clazz) {\n        this.clazz = clazz;\n        return this;\n    }\n\n    @Override\n    public ESQueryRequest indices(String... indices) {\n        if (indices == null) {\n            throw new IllegalArgumentException(\"indices must not be null\");\n        } else {\n            for (int i = 0; i < indices.length; i++) {\n                if (indices[i] == null) {\n                    throw new IllegalArgumentException(\"indices[\" + i + \"] must not be null\");\n                }\n            }\n        }\n        this.indices = indices;\n        return this;\n    }\n\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n\n    @Override\n    public String[] indices() {\n        return indices;\n    }\n\n    @Override\n    public IndicesOptions indicesOptions() {\n        throw new RuntimeException(\"not support\");\n    }\n\n\n\n                        /* type */\n    public String[] types() {\n        return types;\n    }\n\n    public ESQueryRequest types(String... types) {\n        this.types = types;\n        return this;\n    }\n\n                        /* preference */\n    public ESQueryRequest preference(String preference) {\n        this.preference = preference;\n        return this;\n    }\n\n                        /* routing */\n    public String routing() {\n        return this.routing;\n    }\n\n    public ESQueryRequest routing(String routing) {\n        this.routing = routing;\n        return this;\n    }\n\n    public ESQueryRequest routing(String... routings) {\n        this.routing = Strings.arrayToCommaDelimitedString(routings);\n        return this;\n    }\n\n\n    /* source */\n    public ESQueryRequest source(SearchSourceBuilder sourceBuilder) {\n        return source(sourceBuilder.buildAsBytes(Requests.CONTENT_TYPE));\n    }\n\n    public ESQueryRequest source(String source) {\n        return source(new BytesArray(source));\n    }\n\n    public ESQueryRequest source(XContentBuilder builder) {\n        return source(builder.bytes());\n    }\n\n    public ESQueryRequest source(byte[] source) {\n        return source(source, 0, source.length);\n    }\n\n    public ESQueryRequest source(byte[] source, int offset, int length) {\n        return source(new BytesArray(source, offset, length));\n    }\n\n    public ESQueryRequest source(BytesReference source) {\n        this.source = source;\n        return this;\n    }\n\n    public BytesReference source() {\n        return source;\n    }\n\n\n                        /* scroll */\n    public ESQueryRequest scroll(TimeValue keepAlive) {\n        this.scrollTime = keepAlive;\n        return this;\n    }\n\n    public ESQueryRequest scroll(String keepAlive) {\n        return scroll( TimeValue.parseTimeValue(keepAlive, null,null));\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String index = StringUtils.join(indices, \",\");\n        String type = StringUtils.join(types, \",\");\n\n        String endpoint;\n        if (type == null || type.length() == 0) {\n            endpoint = String.format(\"/%s/_search\", index);\n        } else {\n            endpoint = String.format(\"/%s/%s/_search\", index, type);\n        }\n\n        RestRequest restRequest = new RestRequest(\"GET\", endpoint, source);\n        if(scrollTime!=null) {\n            restRequest.addParam(\"scroll\", scrollTime.toString());\n        }\n\n        if(preference!=null) {\n            restRequest.addParam(\"preference\", preference);\n        }\n\n        if(routing!=null) {\n            restRequest.addParam(\"routing\", routing);\n        }\n\n        return restRequest;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        return ESQueryResponse.parserResponse(response.getResponseContent(), clazz);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/query/ESQueryRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.query;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport org.elasticsearch.ExceptionsHelper;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.unit.TimeValue;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.elasticsearch.index.query.QueryBuilder;\nimport org.elasticsearch.script.Script;\nimport org.elasticsearch.search.aggregations.AbstractAggregationBuilder;\nimport org.elasticsearch.search.builder.SearchSourceBuilder;\nimport org.elasticsearch.search.fetch.innerhits.InnerHitsBuilder;\nimport org.elasticsearch.search.highlight.HighlightBuilder;\nimport org.elasticsearch.search.rescore.RescoreBuilder;\nimport org.elasticsearch.search.sort.SortBuilder;\nimport org.elasticsearch.search.sort.SortOrder;\nimport org.elasticsearch.search.suggest.SuggestBuilder;\n\nimport java.util.Map;\n\n/**\n * A search request request builder.\n */\npublic class ESQueryRequestBuilder extends ActionRequestBuilder<ESQueryRequest, ESQueryResponse, ESQueryRequestBuilder> {\n\n    private SearchSourceBuilder sourceBuilder;\n\n    public ESQueryRequestBuilder(ElasticsearchClient client, ESQueryAction action) {\n        super(client, action, new ESQueryRequest());\n    }\n\n    public ESQueryRequestBuilder setClazz(Class clazz) {\n        request.clazz(clazz);\n        return this;\n    }\n    /**\n     * Sets the indices the search will be executed on.\n     */\n    public ESQueryRequestBuilder setIndices(String... indices) {\n        request.indices(indices);\n        return this;\n    }\n\n    /**\n     * The document types to execute the search against. Defaults to be executed against\n     * all types.\n     */\n    public ESQueryRequestBuilder setTypes(String... types) {\n        request.types(types);\n        return this;\n    }\n\n\n    /**\n     * If set, will enable scrolling of the search request for the specified timeout.\n     */\n    public ESQueryRequestBuilder setScroll(TimeValue keepAlive) {\n        request.scroll(keepAlive);\n        return this;\n    }\n\n    /**\n     * If set, will enable scrolling of the search request for the specified timeout.\n     */\n    public ESQueryRequestBuilder setScroll(String keepAlive) {\n        request.scroll(keepAlive);\n        return this;\n    }\n\n    public ESQueryRequestBuilder preference(String preference) {\n        request.preference(preference);\n        return this;\n    }\n\n    /**\n     * A comma separated list of routing values to control the shards the search will be executed on.\n     */\n    public ESQueryRequestBuilder setRouting(String routing) {\n        request.routing(routing);\n        return this;\n    }\n\n    /**\n     * The routing values to control the shards that the search will be executed on.\n     */\n    public ESQueryRequestBuilder setRouting(String... routing) {\n        request.routing(routing);\n        return this;\n    }\n\n    /**\n     * Sets the source of the request as a json string. Note, settings anything other\n     * than the search type will cause this source to be overridden, consider using\n     */\n    public ESQueryRequestBuilder setSource(String source) {\n        request.source(source);\n        return this;\n    }\n\n\n    /**\n     * Sets the source of the request as a json string. Note, settings anything other\n     * than the search type will cause this source to be overridden, consider using\n     */\n    public ESQueryRequestBuilder setSource(BytesReference source) {\n        request.source(source);\n        return this;\n    }\n\n    /**\n     * Sets the source of the request as a json string. Note, settings anything other\n     * than the search type will cause this source to be overridden, consider using\n     */\n    public ESQueryRequestBuilder setSource(byte[] source) {\n        request.source(source);\n        return this;\n    }\n\n    /**\n     * Sets the source of the request as a json string. Note, settings anything other\n     * than the search type will cause this source to be overridden, consider using\n     */\n    public ESQueryRequestBuilder setSource(byte[] source, int offset, int length) {\n        request.source(source, offset, length);\n        return this;\n    }\n\n    /**\n     * Sets the source of the request as a json string. Note, settings anything other\n     * than the search type will cause this source to be overridden, consider using\n     */\n    public ESQueryRequestBuilder setSource(XContentBuilder builder) {\n        request.source(builder);\n        return this;\n    }\n\n    /**\n     * Should the query be profiled. Defaults to <code>false</code>\n     */\n    public ESQueryRequestBuilder setProfile(boolean profile) {\n        sourceBuilder().profile(profile);\n        return this;\n    }\n\n    /**\n     * Sets the source builder to be used with this request. Note, any operations done\n     * on this require builder before are discarded as this internal builder replaces\n     * what has been built up until this point.\n     */\n    public ESQueryRequestBuilder internalBuilder(SearchSourceBuilder sourceBuilder) {\n        this.sourceBuilder = sourceBuilder;\n        return this;\n    }\n\n\n\n                            /* 构建dsl */\n\n    /**\n     * An optional timeout to control how long search is allowed to take.\n     */\n    public ESQueryRequestBuilder setTimeout(TimeValue timeout) {\n        sourceBuilder().timeout(timeout);\n        return this;\n    }\n\n    /**\n     * An optional timeout to control how long search is allowed to take.\n     */\n    public ESQueryRequestBuilder setTimeout(String timeout) {\n        sourceBuilder().timeout(timeout);\n        return this;\n    }\n\n    /**\n     * An optional document count, upon collecting which the search\n     * query will early terminate\n     */\n    public ESQueryRequestBuilder setTerminateAfter(int terminateAfter) {\n        sourceBuilder().terminateAfter(terminateAfter);\n        return this;\n    }\n\n    /**\n     * Constructs a new search source builder with a search query.\n     *\n     * @see org.elasticsearch.index.query.QueryBuilders\n     */\n    public ESQueryRequestBuilder setQuery(QueryBuilder queryBuilder) {\n        sourceBuilder().query(queryBuilder);\n        return this;\n    }\n\n    /**\n     * Constructs a new search source builder with a raw search query.\n     */\n    public ESQueryRequestBuilder setQuery(String query) {\n        sourceBuilder().query(query);\n        return this;\n    }\n\n    /**\n     * Constructs a new search source builder with a raw search query.\n     */\n    public ESQueryRequestBuilder setQuery(BytesReference queryBinary) {\n        sourceBuilder().query(queryBinary);\n        return this;\n    }\n\n    /**\n     * Constructs a new search source builder with a raw search query.\n     */\n    public ESQueryRequestBuilder setQuery(byte[] queryBinary) {\n        sourceBuilder().query(queryBinary);\n        return this;\n    }\n\n    /**\n     * Constructs a new search source builder with a raw search query.\n     */\n    public ESQueryRequestBuilder setQuery(byte[] queryBinary, int queryBinaryOffset, int queryBinaryLength) {\n        sourceBuilder().query(queryBinary, queryBinaryOffset, queryBinaryLength);\n        return this;\n    }\n\n    /**\n     * Constructs a new search source builder with a raw search query.\n     */\n    public ESQueryRequestBuilder setQuery(XContentBuilder query) {\n        sourceBuilder().query(query);\n        return this;\n    }\n\n    /**\n     * Constructs a new search source builder with a raw search query.\n     */\n    public ESQueryRequestBuilder setQuery(Map query) {\n        sourceBuilder().query(query);\n        return this;\n    }\n\n    /**\n     * Sets a filter that will be executed after the query has been executed and only has affect on the search hits\n     * (not aggregations). This filter is always executed as last filtering mechanism.\n     */\n    public ESQueryRequestBuilder setPostFilter(QueryBuilder postFilter) {\n        sourceBuilder().postFilter(postFilter);\n        return this;\n    }\n\n    /**\n     * Sets a filter on the query executed that only applies to the search query\n     * (and not aggs for example).\n     */\n    public ESQueryRequestBuilder setPostFilter(String postFilter) {\n        sourceBuilder().postFilter(postFilter);\n        return this;\n    }\n\n    /**\n     * Sets a filter on the query executed that only applies to the search query\n     * (and not aggs for example).\n     */\n    public ESQueryRequestBuilder setPostFilter(BytesReference postFilter) {\n        sourceBuilder().postFilter(postFilter);\n        return this;\n    }\n\n    /**\n     * Sets a filter on the query executed that only applies to the search query\n     * (and not aggs for example).\n     */\n    public ESQueryRequestBuilder setPostFilter(byte[] postFilter) {\n        sourceBuilder().postFilter(postFilter);\n        return this;\n    }\n\n    /**\n     * Sets a filter on the query executed that only applies to the search query\n     * (and not aggs for example).\n     */\n    public ESQueryRequestBuilder setPostFilter(byte[] postFilter, int postFilterOffset, int postFilterLength) {\n        sourceBuilder().postFilter(postFilter, postFilterOffset, postFilterLength);\n        return this;\n    }\n\n    /**\n     * Sets a filter on the query executed that only applies to the search query\n     * (and not aggs for example).\n     */\n    public ESQueryRequestBuilder setPostFilter(XContentBuilder postFilter) {\n        sourceBuilder().postFilter(postFilter);\n        return this;\n    }\n\n    /**\n     * Sets a filter on the query executed that only applies to the search query\n     * (and not aggs for example).\n     */\n    public ESQueryRequestBuilder setPostFilter(Map postFilter) {\n        sourceBuilder().postFilter(postFilter);\n        return this;\n    }\n\n    /**\n     * Sets the minimum score below which docs will be filtered out.\n     */\n    public ESQueryRequestBuilder setMinScore(float minScore) {\n        sourceBuilder().minScore(minScore);\n        return this;\n    }\n\n    /**\n     * From index to start the search from. Defaults to <tt>0</tt>.\n     */\n    public ESQueryRequestBuilder setFrom(int from) {\n        sourceBuilder().from(from);\n        return this;\n    }\n\n    /**\n     * The number of search hits to return. Defaults to <tt>10</tt>.\n     */\n    public ESQueryRequestBuilder setSize(int size) {\n        sourceBuilder().size(size);\n        return this;\n    }\n\n    /**\n     * Should each {@link org.elasticsearch.search.SearchHit} be returned with an\n     * explanation of the hit (ranking).\n     */\n    public ESQueryRequestBuilder setExplain(boolean explain) {\n        sourceBuilder().explain(explain);\n        return this;\n    }\n\n    /**\n     * Should each {@link org.elasticsearch.search.SearchHit} be returned with its\n     * version.\n     */\n    public ESQueryRequestBuilder setVersion(boolean version) {\n        sourceBuilder().version(version);\n        return this;\n    }\n\n    /**\n     * Sets the boost a specific index will receive when the query is executeed against it.\n     *\n     * @param index      The index to apply the boost against\n     * @param indexBoost The boost to apply to the index\n     */\n    public ESQueryRequestBuilder addIndexBoost(String index, float indexBoost) {\n        sourceBuilder().indexBoost(index, indexBoost);\n        return this;\n    }\n\n    /**\n     * The nodestats groups this request will be aggregated under.\n     */\n    public ESQueryRequestBuilder setStats(String... statsGroups) {\n        sourceBuilder().stats(statsGroups);\n        return this;\n    }\n\n    /**\n     * Sets no fields to be loaded, resulting in only id and type to be returned per field.\n     */\n    public ESQueryRequestBuilder setNoFields() {\n        sourceBuilder().noFields();\n        return this;\n    }\n\n    /**\n     * Indicates whether the response should contain the stored _source for every hit\n     */\n    public ESQueryRequestBuilder setFetchSource(boolean fetch) {\n        sourceBuilder().fetchSource(fetch);\n        return this;\n    }\n\n    /**\n     * Indicate that _source should be returned with every hit, with an \"include\" and/or \"exclude\" set which can include simple wildcard\n     * elements.\n     *\n     * @param include An optional include (optionally wildcarded) pattern to filter the returned _source\n     * @param exclude An optional exclude (optionally wildcarded) pattern to filter the returned _source\n     */\n    public ESQueryRequestBuilder setFetchSource(@Nullable String include, @Nullable String exclude) {\n        sourceBuilder().fetchSource(include, exclude);\n        return this;\n    }\n\n    /**\n     * Indicate that _source should be returned with every hit, with an \"include\" and/or \"exclude\" set which can include simple wildcard\n     * elements.\n     *\n     * @param includes An optional list of include (optionally wildcarded) pattern to filter the returned _source\n     * @param excludes An optional list of exclude (optionally wildcarded) pattern to filter the returned _source\n     */\n    public ESQueryRequestBuilder setFetchSource(@Nullable String[] includes, @Nullable String[] excludes) {\n        sourceBuilder().fetchSource(includes, excludes);\n        return this;\n    }\n\n\n    /**\n     * Adds a field to load and return (note, it must be stored) as part of the search request.\n     * If none are specified, the source of the document will be return.\n     */\n    public ESQueryRequestBuilder addField(String field) {\n        sourceBuilder().field(field);\n        return this;\n    }\n\n    /**\n     * Adds a field data based field to load and return. The field does not have to be stored,\n     * but its recommended to use non analyzed or numeric fields.\n     *\n     * @param name The field to get from the field data cache\n     */\n    public ESQueryRequestBuilder addFieldDataField(String name) {\n        sourceBuilder().fieldDataField(name);\n        return this;\n    }\n\n    /**\n     * Adds a script based field to load and return. The field does not have to be stored,\n     * but its recommended to use non analyzed or numeric fields.\n     *\n     * @param name   The name that will represent this value in the return hit\n     * @param script The script to use\n     */\n    public ESQueryRequestBuilder addScriptField(String name, Script script) {\n        sourceBuilder().scriptField(name, script);\n        return this;\n    }\n\n    /**\n     * Adds a sort against the given field name and the sort ordering.\n     *\n     * @param field The name of the field\n     * @param order The sort ordering\n     */\n    public ESQueryRequestBuilder addSort(String field, SortOrder order) {\n        sourceBuilder().sort(field, order);\n        return this;\n    }\n\n    /**\n     * Adds a generic sort builder.\n     *\n     * @see org.elasticsearch.search.sort.SortBuilders\n     */\n    public ESQueryRequestBuilder addSort(SortBuilder sort) {\n        sourceBuilder().sort(sort);\n        return this;\n    }\n\n    /**\n     * Applies when sorting, and controls if scores will be tracked as well. Defaults to\n     * <tt>false</tt>.\n     */\n    public ESQueryRequestBuilder setTrackScores(boolean trackScores) {\n        sourceBuilder().trackScores(trackScores);\n        return this;\n    }\n\n    /**\n     * Adds the fields to load and return as part of the search request. If none are specified,\n     * the source of the document will be returned.\n     */\n    public ESQueryRequestBuilder addFields(String... fields) {\n        sourceBuilder().fields(fields);\n        return this;\n    }\n\n    /**\n     * Adds an get to the search operation.\n     */\n    public ESQueryRequestBuilder addAggregation(AbstractAggregationBuilder aggregation) {\n        sourceBuilder().aggregation(aggregation);\n        return this;\n    }\n\n    /**\n     * Sets a raw (xcontent) binary representation of addAggregation to use.\n     */\n    public ESQueryRequestBuilder setAggregations(BytesReference aggregations) {\n        sourceBuilder().aggregations(aggregations);\n        return this;\n    }\n\n    /**\n     * Sets a raw (xcontent) binary representation of addAggregation to use.\n     */\n    public ESQueryRequestBuilder setAggregations(byte[] aggregations) {\n        sourceBuilder().aggregations(aggregations);\n        return this;\n    }\n\n    /**\n     * Sets a raw (xcontent) binary representation of addAggregation to use.\n     */\n    public ESQueryRequestBuilder setAggregations(byte[] aggregations, int aggregationsOffset, int aggregationsLength) {\n        sourceBuilder().aggregations(aggregations, aggregationsOffset, aggregationsLength);\n        return this;\n    }\n\n    /**\n     * Sets a raw (xcontent) binary representation of addAggregation to use.\n     */\n    public ESQueryRequestBuilder setAggregations(XContentBuilder aggregations) {\n        sourceBuilder().aggregations(aggregations);\n        return this;\n    }\n\n    /**\n     * Sets a raw (xcontent) binary representation of addAggregation to use.\n     */\n    public ESQueryRequestBuilder setAggregations(Map aggregations) {\n        sourceBuilder().aggregations(aggregations);\n        return this;\n    }\n\n    /**\n     * Adds a field to be highlighted with default fragment size of 100 characters, and\n     * default number of fragments of 5.\n     *\n     * @param name The field to highlight\n     */\n    public ESQueryRequestBuilder addHighlightedField(String name) {\n        highlightBuilder().field(name);\n        return this;\n    }\n\n\n    /**\n     * Adds a field to be highlighted with a provided fragment size (in characters), and\n     * default number of fragments of 5.\n     *\n     * @param name         The field to highlight\n     * @param fragmentSize The size of a fragment in characters\n     */\n    public ESQueryRequestBuilder addHighlightedField(String name, int fragmentSize) {\n        highlightBuilder().field(name, fragmentSize);\n        return this;\n    }\n\n    /**\n     * Adds a field to be highlighted with a provided fragment size (in characters), and\n     * a provided (maximum) number of fragments.\n     *\n     * @param name              The field to highlight\n     * @param fragmentSize      The size of a fragment in characters\n     * @param numberOfFragments The (maximum) number of fragments\n     */\n    public ESQueryRequestBuilder addHighlightedField(String name, int fragmentSize, int numberOfFragments) {\n        highlightBuilder().field(name, fragmentSize, numberOfFragments);\n        return this;\n    }\n\n    /**\n     * Adds a field to be highlighted with a provided fragment size (in characters),\n     * a provided (maximum) number of fragments and an offset for the highlight.\n     *\n     * @param name              The field to highlight\n     * @param fragmentSize      The size of a fragment in characters\n     * @param numberOfFragments The (maximum) number of fragments\n     */\n    public ESQueryRequestBuilder addHighlightedField(String name, int fragmentSize, int numberOfFragments,\n                                                     int fragmentOffset) {\n        highlightBuilder().field(name, fragmentSize, numberOfFragments, fragmentOffset);\n        return this;\n    }\n\n    /**\n     * Adds a highlighted field.\n     */\n    public ESQueryRequestBuilder addHighlightedField(HighlightBuilder.Field field) {\n        highlightBuilder().field(field);\n        return this;\n    }\n\n    /**\n     * Set a tag scheme that encapsulates a built in pre and post tags. The allows schemes\n     * are <tt>styled</tt> and <tt>default</tt>.\n     *\n     * @param schemaName The tag scheme name\n     */\n    public ESQueryRequestBuilder setHighlighterTagsSchema(String schemaName) {\n        highlightBuilder().tagsSchema(schemaName);\n        return this;\n    }\n\n    public ESQueryRequestBuilder setHighlighterFragmentSize(Integer fragmentSize) {\n        highlightBuilder().fragmentSize(fragmentSize);\n        return this;\n    }\n\n    public ESQueryRequestBuilder setHighlighterNumOfFragments(Integer numOfFragments) {\n        highlightBuilder().numOfFragments(numOfFragments);\n        return this;\n    }\n\n    public ESQueryRequestBuilder setHighlighterFilter(Boolean highlightFilter) {\n        highlightBuilder().highlightFilter(highlightFilter);\n        return this;\n    }\n\n    /**\n     * The encoder to set for highlighting\n     */\n    public ESQueryRequestBuilder setHighlighterEncoder(String encoder) {\n        highlightBuilder().encoder(encoder);\n        return this;\n    }\n\n    /**\n     * Explicitly set the pre tags that will be used for highlighting.\n     */\n    public ESQueryRequestBuilder setHighlighterPreTags(String... preTags) {\n        highlightBuilder().preTags(preTags);\n        return this;\n    }\n\n    /**\n     * Explicitly set the post tags that will be used for highlighting.\n     */\n    public ESQueryRequestBuilder setHighlighterPostTags(String... postTags) {\n        highlightBuilder().postTags(postTags);\n        return this;\n    }\n\n    /**\n     * The order of fragments per field. By default, ordered by the order in the\n     * highlighted text. Can be <tt>score</tt>, which then it will be ordered\n     * by score of the fragments.\n     */\n    public ESQueryRequestBuilder setHighlighterOrder(String order) {\n        highlightBuilder().order(order);\n        return this;\n    }\n\n    public ESQueryRequestBuilder setHighlighterRequireFieldMatch(boolean requireFieldMatch) {\n        highlightBuilder().requireFieldMatch(requireFieldMatch);\n        return this;\n    }\n\n    public ESQueryRequestBuilder setHighlighterBoundaryMaxScan(Integer boundaryMaxScan) {\n        highlightBuilder().boundaryMaxScan(boundaryMaxScan);\n        return this;\n    }\n\n    public ESQueryRequestBuilder setHighlighterBoundaryChars(char[] boundaryChars) {\n        highlightBuilder().boundaryChars(boundaryChars);\n        return this;\n    }\n\n    /**\n     * The highlighter type to use.\n     */\n    public ESQueryRequestBuilder setHighlighterType(String type) {\n        highlightBuilder().highlighterType(type);\n        return this;\n    }\n\n    public ESQueryRequestBuilder setHighlighterFragmenter(String fragmenter) {\n        highlightBuilder().fragmenter(fragmenter);\n        return this;\n    }\n\n    /**\n     * Sets a query to be used for highlighting all fields instead of the search query.\n     */\n    public ESQueryRequestBuilder setHighlighterQuery(QueryBuilder highlightQuery) {\n        highlightBuilder().highlightQuery(highlightQuery);\n        return this;\n    }\n\n    /**\n     * Sets the size of the fragment to return from the beginning of the field if there are no matches to\n     * highlight and the field doesn't also define noMatchSize.\n     *\n     * @param noMatchSize integer to set or null to leave out of request.  default is null.\n     * @return this builder for chaining\n     */\n    public ESQueryRequestBuilder setHighlighterNoMatchSize(Integer noMatchSize) {\n        highlightBuilder().noMatchSize(noMatchSize);\n        return this;\n    }\n\n    /**\n     * Sets the maximum number of phrases the fvh will consider if the field doesn't also define phraseLimit.\n     */\n    public ESQueryRequestBuilder setHighlighterPhraseLimit(Integer phraseLimit) {\n        highlightBuilder().phraseLimit(phraseLimit);\n        return this;\n    }\n\n    public ESQueryRequestBuilder setHighlighterOptions(Map<String, Object> options) {\n        highlightBuilder().options(options);\n        return this;\n    }\n\n    /**\n     * Forces to highlight fields based on the source even if fields are stored separately.\n     */\n    public ESQueryRequestBuilder setHighlighterForceSource(Boolean forceSource) {\n        highlightBuilder().forceSource(forceSource);\n        return this;\n    }\n\n    /**\n     * Send the fields to be highlighted using a syntax that is specific about the order in which they should be highlighted.\n     *\n     * @return this for chaining\n     */\n    public ESQueryRequestBuilder setHighlighterExplicitFieldOrder(boolean explicitFieldOrder) {\n        highlightBuilder().useExplicitFieldOrder(explicitFieldOrder);\n        return this;\n    }\n\n    public ESQueryRequestBuilder addInnerHit(String name, InnerHitsBuilder.InnerHit innerHit) {\n        innerHitsBuilder().addInnerHit(name, innerHit);\n        return this;\n    }\n\n    /**\n     * Delegates to {@link SuggestBuilder#setText(String)}.\n     */\n    public ESQueryRequestBuilder setSuggestText(String globalText) {\n        suggestBuilder().setText(globalText);\n        return this;\n    }\n\n    /**\n     * Delegates to {@link SuggestBuilder#addSuggestion(SuggestBuilder.SuggestionBuilder)}.\n     */\n    public ESQueryRequestBuilder addSuggestion(SuggestBuilder.SuggestionBuilder<?> suggestion) {\n        suggestBuilder().addSuggestion(suggestion);\n        return this;\n    }\n\n    /**\n     * Clears all rescorers on the builder and sets the first one.  To use multiple rescore windows use\n     * {@link #addRescorer(RescoreBuilder.Rescorer, int)}.\n     *\n     * @param rescorer rescorer configuration\n     * @return this for chaining\n     */\n    public ESQueryRequestBuilder setRescorer(RescoreBuilder.Rescorer rescorer) {\n        sourceBuilder().clearRescorers();\n        return addRescorer(rescorer);\n    }\n\n    /**\n     * Clears all rescorers on the builder and sets the first one.  To use multiple rescore windows use\n     * {@link #addRescorer(RescoreBuilder.Rescorer, int)}.\n     *\n     * @param rescorer rescorer configuration\n     * @param window   rescore window\n     * @return this for chaining\n     */\n    public ESQueryRequestBuilder setRescorer(RescoreBuilder.Rescorer rescorer, int window) {\n        sourceBuilder().clearRescorers();\n        return addRescorer(rescorer, window);\n    }\n\n    /**\n     * Adds a new rescorer.\n     *\n     * @param rescorer rescorer configuration\n     * @return this for chaining\n     */\n    public ESQueryRequestBuilder addRescorer(RescoreBuilder.Rescorer rescorer) {\n        sourceBuilder().addRescorer(new RescoreBuilder().rescorer(rescorer));\n        return this;\n    }\n\n    /**\n     * Adds a new rescorer.\n     *\n     * @param rescorer rescorer configuration\n     * @param window   rescore window\n     * @return this for chaining\n     */\n    public ESQueryRequestBuilder addRescorer(RescoreBuilder.Rescorer rescorer, int window) {\n        sourceBuilder().addRescorer(new RescoreBuilder().rescorer(rescorer).windowSize(window));\n        return this;\n    }\n\n    /**\n     * Clears all rescorers from the builder.\n     *\n     * @return this for chaining\n     */\n    public ESQueryRequestBuilder clearRescorers() {\n        sourceBuilder().clearRescorers();\n        return this;\n    }\n\n    /**\n     * Sets the rescore window for all rescorers that don't specify a window\n     * when added.\n     *\n     * @param window\n     *            rescore window\n     * @return this for chaining\n     *\n     * @deprecated use\n     *             {@link #addRescorer(RescoreBuilder.Rescorer, int)}\n     *             instead.\n     */\n    @Deprecated\n    public ESQueryRequestBuilder setRescoreWindow(int window) {\n        sourceBuilder().defaultRescoreWindowSize(window);\n        return this;\n    }\n\n\n    /**\n     * Returns the internal search source builder used to construct the request.\n     */\n    public SearchSourceBuilder internalBuilder() {\n        return sourceBuilder();\n    }\n\n    @Override\n    public String toString() {\n        if (sourceBuilder != null) {\n            return sourceBuilder.toString();\n        }\n        if (request.source() != null) {\n            try {\n                return XContentHelper.convertToJson(request.source().toBytesArray(), false, true);\n            } catch (Exception e) {\n                return \"{ \\\"error\\\" : \\\"\" + ExceptionsHelper.detailedMessage(e) + \"\\\"}\";\n            }\n        }\n        return new SearchSourceBuilder().toString();\n    }\n\n    @Override\n    public ESQueryRequest request() {\n        if (sourceBuilder != null) {\n            request.source(sourceBuilder());\n        }\n        return request;\n    }\n\n    @Override\n    protected ESQueryRequest beforeExecute(ESQueryRequest request) {\n        if (sourceBuilder != null) {\n            request.source(sourceBuilder());\n        }\n        return request;\n    }\n\n    private SearchSourceBuilder sourceBuilder() {\n        if (sourceBuilder == null) {\n            sourceBuilder = new SearchSourceBuilder();\n        }\n        return sourceBuilder;\n    }\n\n    private HighlightBuilder highlightBuilder() {\n        return sourceBuilder().highlighter();\n    }\n\n    private InnerHitsBuilder innerHitsBuilder() {\n        return sourceBuilder().innerHitsBuilder();\n    }\n\n    private SuggestBuilder suggestBuilder() {\n        return sourceBuilder().suggest();\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/scroll/ESQueryScrollAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.scroll;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESQueryScrollAction extends Action<ESQueryScrollRequest, ESQueryResponse, ESQueryScrollRequestBuilder> {\n\n    public static final ESQueryScrollAction INSTANCE = new ESQueryScrollAction();\n    public static final String NAME = \"query:scroll\";\n\n    private ESQueryScrollAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESQueryResponse newResponse() {\n        return new ESQueryResponse();\n    }\n\n    @Override\n    public ESQueryScrollRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESQueryScrollRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/scroll/ESQueryScrollRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.scroll;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\nimport org.elasticsearch.common.unit.TimeValue;\n\npublic class ESQueryScrollRequest extends ESActionRequest<ESQueryScrollRequest> {\n\n    private Class clazz;\n    private String scrollId;\n    private TimeValue scrollTime;\n\n    public ESQueryScrollRequest() {\n        // pass\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n\n    public ESQueryScrollRequest setScrollId(String scrollId) {\n        this.scrollId = scrollId;\n        return this;\n    }\n\n\n    public ESQueryScrollRequest clazz(Class clazz) {\n        this.clazz = clazz;\n        return this;\n    }\n\n    public ESQueryScrollRequest scroll(TimeValue keepAlive) {\n        this.scrollTime = keepAlive;\n        return this;\n    }\n\n    public ESQueryScrollRequest scroll(String keepAlive) {\n        return scroll( TimeValue.parseTimeValue(keepAlive, null,null));\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        if(scrollId == null) {\n            throw new Exception(\"scroll id is null\");\n        }\n\n        String endPoint = \"/_search/scroll\";\n\n        JSONObject scrollJson = new JSONObject();\n        if(scrollTime!=null) {\n            scrollJson.put(\"scroll\", scrollTime.toString());\n        }\n        scrollJson.put(\"scroll_id\", scrollId);\n\n\n        RestRequest restRequest = new RestRequest(\"POST\", endPoint, null);\n        restRequest.setBody(scrollJson.toJSONString());\n\n        return restRequest;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        return ESQueryResponse.parserResponse(response.getResponseContent(), clazz);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/scroll/ESQueryScrollRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.scroll;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\nimport org.elasticsearch.common.unit.TimeValue;\n\n/**\n * A search request request builder.\n */\npublic class ESQueryScrollRequestBuilder extends ActionRequestBuilder<ESQueryScrollRequest, ESQueryResponse, ESQueryScrollRequestBuilder> {\n\n    public ESQueryScrollRequestBuilder(ElasticsearchClient client, ESQueryScrollAction action) {\n        super(client, action, new ESQueryScrollRequest());\n    }\n\n    public ESQueryScrollRequestBuilder clazz(Class clazz) {\n        request.clazz(clazz);\n        return this;\n    }\n\n    public ESQueryScrollRequestBuilder setScrollId(String scrollId) {\n        request.setScrollId(scrollId);\n        return this;\n    }\n\n    public ESQueryScrollRequestBuilder setScroll(TimeValue keepAlive) {\n        request.scroll(keepAlive);\n        return this;\n    }\n\n    public ESQueryScrollRequestBuilder setScroll(String keepAlive) {\n        request.scroll(keepAlive);\n        return this;\n    }\n\n\n    @Override\n    public ESQueryScrollRequest request() {\n        return request;\n    }\n\n    @Override\n    protected ESQueryScrollRequest beforeExecute(ESQueryScrollRequest request) {\n        return request;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/sql/ESSQLAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.sql;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport org.elasticsearch.action.Action;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n */\npublic class ESSQLAction extends Action<ESSQLRequest, ESQueryResponse, ESSQLRequestBuilder> {\n\n    public static final ESSQLAction INSTANCE = new ESSQLAction();\n    public static final String NAME = \"indices:data/read/sql\";\n\n    private ESSQLAction() {\n        super(NAME);\n    }\n\n    @Override\n    public ESQueryResponse newResponse() {\n        return new ESQueryResponse();\n    }\n\n    @Override\n    public ESSQLRequestBuilder newRequestBuilder(ElasticsearchClient client) {\n        return new ESSQLRequestBuilder(client, this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/sql/ESSQLRequest.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.sql;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport com.didi.arius.gateway.elasticsearch.client.model.RestResponse;\nimport org.elasticsearch.action.ActionRequestValidationException;\n\npublic class ESSQLRequest extends ESActionRequest<ESSQLRequest> {\n    private String sql;\n\n    private Class clazz = null;\n\n    public ESSQLRequest() {\n    }\n\n\n    public ESSQLRequest(String sql) {\n        this.sql = sql;\n    }\n\n\n    public ESSQLRequest clazz(Class clazz) {\n        this.clazz = clazz;\n        return this;\n    }\n\n    @Override\n    public ActionRequestValidationException validate() {\n        return null;\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public void setSql(String sql) {\n        this.sql = sql;\n    }\n\n\n    @Override\n    public RestRequest toRequest() throws Exception {\n        String endpoint = \"/_sql\";\n        RestRequest restRequest = new RestRequest(\"POST\", endpoint);\n        restRequest.setContent(sql);\n        return restRequest;\n    }\n\n    @Override\n    public ESActionResponse toResponse(RestResponse response) throws Exception {\n        return ESQueryResponse.parserResponse(response.getResponseContent(), clazz);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/request/query/sql/ESSQLRequestBuilder.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.request.query.sql;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.ESQueryResponse;\nimport org.elasticsearch.action.ActionRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\n\n/**\n * A search request request builder.\n */\npublic class ESSQLRequestBuilder extends ActionRequestBuilder<ESSQLRequest, ESQueryResponse, ESSQLRequestBuilder> {\n\n    private String sql;\n\n    public ESSQLRequestBuilder(ElasticsearchClient client, ESSQLAction action) {\n        super(client, action, new ESSQLRequest());\n    }\n\n    public ESSQLRequestBuilder setClazz(Class clazz) {\n        request.clazz(clazz);\n        return this;\n    }\n\n    @Override\n    public String toString() {\n        return sql;\n    }\n\n    public ESSQLRequestBuilder SQL(String sql) {\n        request.setSql(sql);\n        return this;\n    }\n\n    public ESSQLRequestBuilder setSQL(String sql) {\n        request.setSql(sql);\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/ESAcknowledgedResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\npublic class ESAcknowledgedResponse extends ESActionResponse {\n    private Boolean acknowledged;\n\n    public ESAcknowledgedResponse() {\n        // pass\n    }\n\n    public Boolean getAcknowledged() {\n        return acknowledged;\n    }\n\n    public void setAcknowledged(Boolean acknowledged) {\n        this.acknowledged = acknowledged;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/batch/ESBatchResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.batch;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\nimport java.util.List;\n\npublic class ESBatchResponse extends ESActionResponse {\n    @JSONField(name = \"took\")\n    private Long took;\n\n    @JSONField(name = \"errors\")\n\tprivate Boolean errors;\n\n    @JSONField(name = \"items\")\n\tprivate List<IndexResultItemNode> items;\n\n    public ESBatchResponse() {\n\n    }\n\n    public ESBatchResponse(List<IndexResultItemNode> items, Long took) {\n        this.items = items;\n        this.took = took;\n    }\n\n    public Long getTook() {\n        return took;\n    }\n\n    public void setTook(Long took) {\n        this.took = took;\n    }\n\n    public Boolean getErrors() {\n        return errors;\n    }\n\n    public void setErrors(Boolean errors) {\n        this.errors = errors;\n    }\n\n    public List<IndexResultItemNode> getItems() {\n        return items;\n    }\n\n    public void setItems(List<IndexResultItemNode> items) {\n        this.items = items;\n    }\n\n    /**\n     * Has anything failed with the execution.\n     */\n    public boolean hasFailures() {\n        for (IndexResultItemNode response : items) {\n            if (response.isFailed()) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public String buildFailureMessage() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(\"failure in bulk execution:\");\n        for (int i = 0; i < items.size(); i++) {\n            IndexResultItemNode response = items.get(i);\n            if (response.isFailed()) {\n                IndexResultNode node = response.getIndex();\n                sb.append(\"\\n[\").append(i)\n                        .append(\"]: index [\").append(node.getIndex()).append(\"], type [\").append(node.getType()).append(\"], id [\").append(node.getId())\n                        .append(\"], message [\").append(node.getFailureMessage()).append(\"]\");\n            }\n        }\n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/batch/Error.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.batch;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\n/**\n * @author: D10865\n * @description:\n * @date: Create on 2019/2/18 下午2:29\n * @modified By D10865\n *\n\n\"error\": {\n\"type\": \"mapper_parsing_exception\",\n\"reason\": \"failed to parse [date]\",\n\"caused_by\": {\n\"type\": \"illegal_argument_exception\",\n\"reason\": \"Invalid format: \\\"exception_test\\\"\"\n}\n}\n\n */\npublic class Error {\n\n    @JSONField(name = \"type\")\n    private String type;\n\n    @JSONField(name = \"reason\")\n    private String reason;\n\n    @JSONField(name = \"caused_by\")\n    private Cause cause;\n\n    public Error() {\n        // pass\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public Error setType(String type) {\n        this.type = type;\n        return this;\n    }\n\n    public String getReason() {\n        return reason;\n    }\n\n    public Error setReason(String reason) {\n        this.reason = reason;\n        return this;\n    }\n\n    public Cause getCause() {\n        return cause;\n    }\n\n    public Error setCause(Cause cause) {\n        this.cause = cause;\n        return this;\n    }\n\n    class Cause {\n\n        private String type;\n\n        private String reason;\n\n        public Cause() {\n            // pass\n        }\n\n        public String getType() {\n            return type;\n        }\n\n        public Cause setType(String type) {\n            this.type = type;\n            return this;\n        }\n\n        public String getReason() {\n            return reason;\n        }\n\n        public Cause setReason(String reason) {\n            this.reason = reason;\n            return this;\n        }\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/batch/IndexResultItemNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.batch;\n\npublic class IndexResultItemNode {\n    private IndexResultNode index;\n\n    public IndexResultItemNode() {\n        // pass\n    }\n\n    public IndexResultNode getIndex() {\n        return index;\n    }\n\n    public void setIndex(IndexResultNode index) {\n        this.index = index;\n    }\n\n    /**\n     * Is this a failed execution of an operation.\n     */\n    public boolean isFailed() {\n        return index.getError() != null;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/batch/IndexResultNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.batch;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.response.Shards;\n\npublic class IndexResultNode {\n    @JSONField(name = \"_index\")\n    private String index;\n\n    @JSONField(name = \"_type\")\n    private String type;\n\n    @JSONField(name = \"_id\")\n    private String id;\n\n    @JSONField(name = \"_version\")\n    private Long version;\n\n    @JSONField(name = \"result\")\n    private String result;\n\n    @JSONField(name = \"_shards\")\n    private Shards shards;\n\n    @JSONField(name = \"_seq_no\")\n    private Long seqNo;\n\n    @JSONField(name = \"_primary_term\")\n    private Long primaryTerm;\n\n    @JSONField(name = \"status\")\n    private Long status;\n\n    @JSONField(name = \"error\")\n    private Error error;\n\n    public IndexResultNode() {\n        // pass\n    }\n\n    public String getIndex() {\n        return index;\n    }\n\n    public void setIndex(String index) {\n        this.index = index;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public void setId(String id) {\n        this.id = id;\n    }\n\n    public Long getVersion() {\n        return version;\n    }\n\n    public void setVersion(Long version) {\n        this.version = version;\n    }\n\n    public String getResult() {\n        return result;\n    }\n\n    public void setResult(String result) {\n        this.result = result;\n    }\n\n    public Shards getShards() {\n        return shards;\n    }\n\n    public void setShards(Shards shards) {\n        this.shards = shards;\n    }\n\n    public Long getSeqNo() {\n        return seqNo;\n    }\n\n    public void setSeqNo(Long seqNo) {\n        this.seqNo = seqNo;\n    }\n\n    public Long getPrimaryTerm() {\n        return primaryTerm;\n    }\n\n    public void setPrimaryTerm(Long primaryTerm) {\n        this.primaryTerm = primaryTerm;\n    }\n\n    public Long getStatus() {\n        return status;\n    }\n\n    public void setStatus(Long status) {\n        this.status = status;\n    }\n\n    /**\n     * The failure message, <tt>null</tt> if it did not fail.\n     */\n    public String getFailureMessage() {\n        if (error != null) {\n            return error.getReason();\n        }\n        return null;\n    }\n\n\n    public Error getError() {\n        return error;\n    }\n\n    public IndexResultNode setError(Error error) {\n        this.error = error;\n        return this;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/cat/ESCatResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.cat;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\npublic class ESCatResponse extends ESActionResponse {\n    private Object response;\n\n    public ESCatResponse() {}\n    public ESCatResponse(String response, Class clazz) {\n        if(clazz==null) {\n            this.response = response;\n            return;\n        }\n\n        this.response = JSON.parseArray(response, clazz);\n    }\n\n    public Object getResponse() {\n        return response;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        return (JSONObject) JSON.toJSON(this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/cluster/ESClusterHealthResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.cluster;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\npublic class ESClusterHealthResponse extends ESActionResponse {\n    @JSONField(name = \"cluster_name\")\n    private String clusterName;\n\n    @JSONField(name = \"status\")\n    private String status;\n\n    @JSONField(name = \"timed_out\")\n    private boolean timedOut;\n\n    @JSONField(name = \"number_of_nodes\")\n    private long numberOfNodes;\n\n    @JSONField(name = \"number_of_data_nodes\")\n    private long numberOfDataNodes;\n\n    @JSONField(name = \"active_primary_shards\")\n    private long activePrimaryShards;\n\n    @JSONField(name = \"active_shards\")\n    private long activeShards;\n\n    @JSONField(name = \"relocating_shards\")\n    private long relocatingShards;\n\n    @JSONField(name = \"initializing_shards\")\n    private long initializingShards;\n\n    @JSONField(name = \"unassigned_shards\")\n    private long unassignedShards;\n\n    @JSONField(name = \"delayed_unassigned_shards\")\n    private long delayedUnassignedShards;\n\n    @JSONField(name = \"number_of_pending_tasks\")\n    private long numberOfPendingTasks;\n\n    @JSONField(name = \"number_of_in_flight_fetch\")\n    private long numberOfInFlightFetch;\n\n    @JSONField(name = \"task_max_waiting_in_queue_millis\")\n    private long taskMaxWaitingInQueueMillis;\n\n    @JSONField(name = \"active_shards_percent_as_number\")\n    private long activeShardsPercentAsNumber;\n\n    public ESClusterHealthResponse() {\n        // pass\n    }\n\n    public String getClusterName() {\n        return clusterName;\n    }\n\n    public void setClusterName(String clusterName) {\n        this.clusterName = clusterName;\n    }\n\n    public String getStatus() {\n        return status;\n    }\n\n    public void setStatus(String status) {\n        this.status = status;\n    }\n\n    public boolean isTimedOut() {\n        return timedOut;\n    }\n\n    public void setTimedOut(boolean timedOut) {\n        this.timedOut = timedOut;\n    }\n\n    public long getNumberOfNodes() {\n        return numberOfNodes;\n    }\n\n    public void setNumberOfNodes(long numberOfNodes) {\n        this.numberOfNodes = numberOfNodes;\n    }\n\n    public long getNumberOfDataNodes() {\n        return numberOfDataNodes;\n    }\n\n    public void setNumberOfDataNodes(long numberOfDataNodes) {\n        this.numberOfDataNodes = numberOfDataNodes;\n    }\n\n    public long getActivePrimaryShards() {\n        return activePrimaryShards;\n    }\n\n    public void setActivePrimaryShards(long activePrimaryShards) {\n        this.activePrimaryShards = activePrimaryShards;\n    }\n\n    public long getActiveShards() {\n        return activeShards;\n    }\n\n    public void setActiveShards(long activeShards) {\n        this.activeShards = activeShards;\n    }\n\n    public long getRelocatingShards() {\n        return relocatingShards;\n    }\n\n    public void setRelocatingShards(long relocatingShards) {\n        this.relocatingShards = relocatingShards;\n    }\n\n    public long getInitializingShards() {\n        return initializingShards;\n    }\n\n    public void setInitializingShards(long initializingShards) {\n        this.initializingShards = initializingShards;\n    }\n\n    public long getUnassignedShards() {\n        return unassignedShards;\n    }\n\n    public void setUnassignedShards(long unassignedShards) {\n        this.unassignedShards = unassignedShards;\n    }\n\n    public long getDelayedUnassignedShards() {\n        return delayedUnassignedShards;\n    }\n\n    public void setDelayedUnassignedShards(long delayedUnassignedShards) {\n        this.delayedUnassignedShards = delayedUnassignedShards;\n    }\n\n    public long getNumberOfPendingTasks() {\n        return numberOfPendingTasks;\n    }\n\n    public void setNumberOfPendingTasks(long numberOfPendingTasks) {\n        this.numberOfPendingTasks = numberOfPendingTasks;\n    }\n\n    public long getNumberOfInFlightFetch() {\n        return numberOfInFlightFetch;\n    }\n\n    public void setNumberOfInFlightFetch(long numberOfInFlightFetch) {\n        this.numberOfInFlightFetch = numberOfInFlightFetch;\n    }\n\n    public long getTaskMaxWaitingInQueueMillis() {\n        return taskMaxWaitingInQueueMillis;\n    }\n\n    public void setTaskMaxWaitingInQueueMillis(long taskMaxWaitingInQueueMillis) {\n        this.taskMaxWaitingInQueueMillis = taskMaxWaitingInQueueMillis;\n    }\n\n    public long getActiveShardsPercentAsNumber() {\n        return activeShardsPercentAsNumber;\n    }\n\n    public void setActiveShardsPercentAsNumber(long activeShardsPercentAsNumber) {\n        this.activeShardsPercentAsNumber = activeShardsPercentAsNumber;\n    }\n\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        return (JSONObject) JSON.toJSON(this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/cluster/nodessetting/ClusterNodeSettings.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.cluster.nodessetting;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.node.NodeAttributes;\nimport com.didi.arius.gateway.elasticsearch.client.utils.JsonUtils;\n\nimport java.util.Map;\n\npublic class ClusterNodeSettings {\n    @JSONField(name = \"name\")\n    private String name;\n\n    @JSONField(name = \"transport_address\")\n    private String transportAddress;\n\n    @JSONField(name = \"host\")\n    private String host;\n\n    @JSONField(name = \"ip\")\n    private String ip;\n\n    @JSONField(name = \"version\")\n    private String version;\n\n    @JSONField(name = \"build\")\n    private String build;\n\n    @JSONField(name = \"http_address\")\n    private String httpAddress;\n\n    @JSONField(name = \"attributes\")\n    private NodeAttributes attributes;\n\n    @JSONField(name = \"settings\")\n    private JSONObject settings;\n\n    public ClusterNodeSettings() {\n        // pass\n    }\n\n    @JSONField(serialize = false)\n    public Map<String, String> getSettingsByFlat() {\n        return JsonUtils.flat(settings);\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public String getTransportAddress() {\n        return transportAddress;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public void setHost(String host) {\n        this.host = host;\n    }\n\n    public void setTransportAddress(String transportAddress) {\n        this.transportAddress = transportAddress;\n    }\n\n    public String getHost() {\n        return host;\n    }\n\n    public String getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public String getVersion() {\n        return version;\n    }\n\n    public void setVersion(String version) {\n        this.version = version;\n    }\n\n    public String getBuild() {\n        return build;\n    }\n\n    public void setBuild(String build) {\n        this.build = build;\n    }\n\n    public String getHttpAddress() {\n        return httpAddress;\n    }\n\n    public void setHttpAddress(String httpAddress) {\n        this.httpAddress = httpAddress;\n    }\n\n    public NodeAttributes getAttributes() {\n        return attributes;\n    }\n\n    public void setAttributes(NodeAttributes attributes) {\n        this.attributes = attributes;\n    }\n\n    public JSONObject getSettings() {\n        return settings;\n    }\n\n    public void setSettings(JSONObject settings) {\n        this.settings = settings;\n    }\n}\n\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/cluster/nodessetting/ESClusterNodesSettingResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.cluster.nodessetting;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\nimport java.util.Map;\n\npublic class ESClusterNodesSettingResponse extends ESActionResponse {\n    @JSONField(name = \"cluster_name\")\n    private String clusterName;\n\n    @JSONField(name = \"nodes\")\n    private Map<String, ClusterNodeSettings> nodes;\n\n    public ESClusterNodesSettingResponse() {\n        // pass\n    }\n\n    public String getClusterName() {\n        return clusterName;\n    }\n\n    public void setClusterName(String clusterName) {\n        this.clusterName = clusterName;\n    }\n\n    public Map<String, ClusterNodeSettings> getNodes() {\n        return nodes;\n    }\n\n    public void setNodes(Map<String, ClusterNodeSettings> nodes) {\n        this.nodes = nodes;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        return (JSONObject) JSON.toJSON(this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/cluster/nodesstats/ClusterNodeStats.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.cluster.nodesstats;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.breakers.Breakers;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.fs.FSNode;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.http.HttpNode;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.indices.CommonStat;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.jvm.JvmNode;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.node.NodeAttributes;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.os.OsNode;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.process.ProcessNode;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.script.ScriptNode;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.threadpool.ThreadPoolNodes;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.transport.TransportNode;\n\nimport java.util.List;\n\npublic class ClusterNodeStats {\n       @JSONField(name = \"timestamp\")\n       private long timestamp;\n\n       @JSONField(name = \"name\")\n       private String name;\n\n       @JSONField(name = \"transport_address\")\n       private String transportAddress;\n\n       @JSONField(name = \"host\")\n       private String host;\n\n       @JSONField(name = \"ip\")\n       private List<String> ip;\n\n       @JSONField(name = \"attributes\")\n       private NodeAttributes attributes;\n\n       @JSONField(name = \"indices\")\n       private CommonStat indices;\n\n       @JSONField(name = \"os\")\n       private OsNode os;\n\n       @JSONField(name = \"process\")\n       private ProcessNode process;\n\n       @JSONField(name = \"jvm\")\n       private JvmNode jvm;\n\n       @JSONField(name = \"thread_pool\")\n       private ThreadPoolNodes threadPool;\n\n       @JSONField(name = \"fs\")\n       private FSNode fs;\n\n       @JSONField(name = \"transport\")\n       private TransportNode transport;\n\n       @JSONField(name = \"http\")\n       private HttpNode http;\n\n       @JSONField(name = \"breakers\")\n       private Breakers breakers;\n\n       @JSONField(name = \"script\")\n       private ScriptNode script;\n\n       public ClusterNodeStats() {\n              // pass\n       }\n\n       public long getTimestamp() {\n              return timestamp;\n       }\n\n       public void setTimestamp(long timestamp) {\n              this.timestamp = timestamp;\n       }\n\n       public String getName() {\n              return name;\n       }\n\n       public void setName(String name) {\n              this.name = name;\n       }\n\n       public String getTransportAddress() {\n              return transportAddress;\n       }\n\n       public void setTransportAddress(String transportAddress) {\n              this.transportAddress = transportAddress;\n       }\n\n       public String getHost() {\n              return host;\n       }\n\n       public void setHost(String host) {\n              this.host = host;\n       }\n\n       public List<String> getIp() {\n              return ip;\n       }\n\n       public void setIp(List<String> ip) {\n              this.ip = ip;\n       }\n\n       public NodeAttributes getAttributes() {\n              return attributes;\n       }\n\n       public void setAttributes(NodeAttributes attributes) {\n              this.attributes = attributes;\n       }\n\n       public CommonStat getIndices() {\n              return indices;\n       }\n\n       public void setIndices(CommonStat indices) {\n              this.indices = indices;\n       }\n\n       public OsNode getOs() {\n              return os;\n       }\n\n       public void setOs(OsNode os) {\n              this.os = os;\n       }\n\n       public ProcessNode getProcess() {\n              return process;\n       }\n\n       public void setProcess(ProcessNode process) {\n              this.process = process;\n       }\n\n       public JvmNode getJvm() {\n              return jvm;\n       }\n\n       public void setJvm(JvmNode jvm) {\n              this.jvm = jvm;\n       }\n\n       public ThreadPoolNodes getThreadPool() {\n              return threadPool;\n       }\n\n       public void setThreadPool(ThreadPoolNodes threadPool) {\n              this.threadPool = threadPool;\n       }\n\n       public FSNode getFs() {\n              return fs;\n       }\n\n       public void setFs(FSNode fs) {\n              this.fs = fs;\n       }\n\n       public TransportNode getTransport() {\n              return transport;\n       }\n\n       public void setTransport(TransportNode transport) {\n              this.transport = transport;\n       }\n\n       public HttpNode getHttp() {\n              return http;\n       }\n\n       public void setHttp(HttpNode http) {\n              this.http = http;\n       }\n\n       public Breakers getBreakers() {\n              return breakers;\n       }\n\n       public void setBreakers(Breakers breakers) {\n              this.breakers = breakers;\n       }\n\n       public ScriptNode getScript() {\n              return script;\n       }\n\n       public void setScript(ScriptNode script) {\n              this.script = script;\n       }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/cluster/nodesstats/ESClusterNodesStatsResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.cluster.nodesstats;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\nimport java.util.Map;\n\npublic class ESClusterNodesStatsResponse extends ESActionResponse {\n    @JSONField(name = \"cluster_name\")\n    private String clusterName;\n\n    @JSONField(name = \"nodes\")\n    private Map<String, ClusterNodeStats> nodes;\n\n    public ESClusterNodesStatsResponse() {\n        // pass\n    }\n\n    public String getClusterName() {\n        return clusterName;\n    }\n\n    public void setClusterName(String clusterName) {\n        this.clusterName = clusterName;\n    }\n\n    public Map<String, ClusterNodeStats> getNodes() {\n        return nodes;\n    }\n\n    public void setNodes(Map<String, ClusterNodeStats> nodes) {\n        this.nodes = nodes;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        return (JSONObject) JSON.toJSON(this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/cluster/updatesetting/ESClusterUpdateSettingsResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.cluster.updatesetting;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.response.ESAcknowledgedResponse;\nimport com.didi.arius.gateway.elasticsearch.client.utils.JsonUtils;\n\nimport java.util.Map;\n\n/**\n * A response for a cluster update settings action.\n */\npublic class ESClusterUpdateSettingsResponse extends ESAcknowledgedResponse {\n    @JSONField(name = \"transient\")\n    private JSONObject transientObj;\n\n    @JSONField(name = \"persistent\")\n    private JSONObject persistentObj;\n\n    public ESClusterUpdateSettingsResponse() {\n        // pass\n    }\n\n    @JSONField(serialize=false)\n    public Map<String, String> getFlatTransient() {\n        return JsonUtils.flat(transientObj);\n    }\n\n    @JSONField(serialize=false)\n    public Map<String, String> getFlatPersistent() {\n        return JsonUtils.flat(persistentObj);\n    }\n\n\n\n    public JSONObject getTransientObj() {\n        return transientObj;\n    }\n\n    public void setTransientObj(JSONObject transientObj) {\n        this.transientObj = transientObj;\n    }\n\n    public JSONObject getPersistentObj() {\n        return persistentObj;\n    }\n\n    public void setPersistentObj(JSONObject persistentObj) {\n        this.persistentObj = persistentObj;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/deleteindex/ESIndicesDeleteIndexResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.deleteindex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.ESAcknowledgedResponse;\n\npublic class ESIndicesDeleteIndexResponse extends ESAcknowledgedResponse {\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/deletetemplate/ESIndicesDeleteTemplateResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.deletetemplate;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.ESAcknowledgedResponse;\n\npublic class ESIndicesDeleteTemplateResponse extends ESAcknowledgedResponse {\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/exists/ESIndicesExistsResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.exists;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\npublic class ESIndicesExistsResponse extends ESActionResponse {\n    @JSONField(name = \"isExists\")\n    private boolean isExists;\n\n    public ESIndicesExistsResponse() {\n        // pass\n    }\n\n    public boolean isExists() {\n        return isExists;\n    }\n\n    public void setExists(boolean exists) {\n        isExists = exists;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/getalias/AliasIndexNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.indices.getalias;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\n\nimport java.util.Map;\n\npublic class AliasIndexNode {\n    @JSONField(name = \"aliases\")\n    private Map<String, JSONObject> aliases;\n\n    public AliasIndexNode() {\n        // pass\n    }\n\n    public Map<String, JSONObject> getAliases() {\n        return aliases;\n    }\n\n    public void setAliases(Map<String, JSONObject> aliases) {\n        this.aliases = aliases;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/getalias/ESIndicesGetAliasResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.getalias;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ESIndicesGetAliasResponse extends ESActionResponse {\n    private Map<String, AliasIndexNode> m;\n\n    public ESIndicesGetAliasResponse() {\n        // pass\n    }\n\n    public Map<String, AliasIndexNode> getM() {\n        return m;\n    }\n\n    public void setM(Map<String, AliasIndexNode> m) {\n        this.m = m;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson()  {\n        return (JSONObject) JSON.toJSON(this);\n    }\n\n\n    public static ESIndicesGetAliasResponse getResponse(String str) {\n        Map<String, AliasIndexNode> m = new HashMap<>();\n\n        JSONObject obj = JSON.parseObject(str);\n        for(Map.Entry<String,Object> entry : obj.entrySet()) {\n            m.put(entry.getKey(), JSON.parseObject(entry.getValue().toString(), AliasIndexNode.class));\n        }\n\n        ESIndicesGetAliasResponse response = new ESIndicesGetAliasResponse();\n        response.setM(m);\n        return response;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/getindex/ESIndicesGetIndexResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.getindex;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.index.MultiIndexsConfig;\n\npublic class ESIndicesGetIndexResponse extends ESActionResponse {\n    private MultiIndexsConfig indexsMapping;\n\n    public ESIndicesGetIndexResponse() {\n        // pass\n    }\n\n    public MultiIndexsConfig getIndexsMapping() {\n        return indexsMapping;\n    }\n\n    public void setIndexsMapping(MultiIndexsConfig indexsMapping) {\n        this.indexsMapping = indexsMapping;\n    }\n\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson()  {\n        return (JSONObject) JSON.toJSON(this);\n    }\n\n\n    public static ESIndicesGetIndexResponse getResponse(String str) throws Exception {\n        ESIndicesGetIndexResponse response = new ESIndicesGetIndexResponse();\n        response.setIndexsMapping(new MultiIndexsConfig(JSON.parseObject(str)));\n        return response;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/gettemplate/ESIndicesGetTemplateResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.gettemplate;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.template.MultiTemplatesConfig;\n\npublic class ESIndicesGetTemplateResponse extends ESActionResponse {\n    private MultiTemplatesConfig multiTemplatesConfig;\n\n    public ESIndicesGetTemplateResponse() {\n        // pass\n    }\n\n    public MultiTemplatesConfig getMultiTemplatesConfig() {\n        return multiTemplatesConfig;\n    }\n\n    public void setMultiTemplatesConfig(MultiTemplatesConfig multiTemplatesConfig) {\n        this.multiTemplatesConfig = multiTemplatesConfig;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson()  {\n        return (JSONObject) JSON.toJSON(this);\n    }\n\n\n    public static ESIndicesGetTemplateResponse getResponse(String str) throws Exception {\n        ESIndicesGetTemplateResponse response = new ESIndicesGetTemplateResponse();\n        response.setMultiTemplatesConfig(new MultiTemplatesConfig(JSON.parseObject(str)));\n        return response;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/putalias/ESIndicesPutAliasResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.putalias;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.ESAcknowledgedResponse;\n\npublic class ESIndicesPutAliasResponse extends ESAcknowledgedResponse {\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/putindex/ESIndicesPutIndexResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.putindex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.ESAcknowledgedResponse;\n\npublic class ESIndicesPutIndexResponse extends ESAcknowledgedResponse {\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/puttemplate/ESIndicesPutTemplateResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.puttemplate;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.ESAcknowledgedResponse;\n\npublic class ESIndicesPutTemplateResponse extends ESAcknowledgedResponse {\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/refreshindex/ESIndicesRefreshIndexResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.refreshindex;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.ESAcknowledgedResponse;\n\npublic class ESIndicesRefreshIndexResponse extends ESAcknowledgedResponse {\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/searchshards/ESIndicesSearchShardsResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.searchshards;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.searchshards.item.ESNode;\nimport com.didi.arius.gateway.elasticsearch.client.response.indices.searchshards.item.ESShard;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n */\npublic class ESIndicesSearchShardsResponse extends ESActionResponse {\n    @JSONField(name = \"nodes\")\n    private Map<String, ESNode> nodes;\n\n    @JSONField(name = \"shards\")\n    private List<List<ESShard>> shards;\n\n    public ESIndicesSearchShardsResponse() {\n        // pass\n    }\n\n    public Map<String, ESNode> getNodes() {\n        return nodes;\n    }\n\n    public void setNodes(Map<String, ESNode> nodes) {\n        this.nodes = nodes;\n    }\n\n    public List<List<ESShard>> getShards() {\n        return shards;\n    }\n\n    public void setShards(List<List<ESShard>> shards) {\n        this.shards = shards;\n    }\n\n\n\n    @JSONField(serialize=false)\n    public Map<String, List<List<ESShard>>> getIndexMap() {\n        Map<String, List<List<ESShard>>> ret = new HashMap<>();\n\n        for(List<ESShard> les : shards) {\n            if(les==null || les.size()==0 || les.get(0)==null) {\n                continue;\n            }\n\n            String index = les.get(0).getIndex();\n            if(!ret.containsKey(index)) {\n                ret.put(index, new ArrayList<>());\n            }\n\n            ret.get(index).add(les);\n        }\n\n        return ret;\n    }\n\n\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson()  {\n        return (JSONObject) JSON.toJSON(this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/searchshards/item/ESNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.indices.searchshards.item;\n\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.node.NodeAttributes;\n\npublic class ESNode {\n    @JSONField(name = \"name\")\n    private String name;\n\n    @JSONField(name = \"transport_address\")\n    private String transportAddress;\n\n    @JSONField(name = \"attributes\")\n    private NodeAttributes attributes;\n\n    public ESNode() {\n        // pass\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getTransportAddress() {\n        return transportAddress;\n    }\n\n    public void setTransportAddress(String transportAddress) {\n        this.transportAddress = transportAddress;\n    }\n\n    public NodeAttributes getAttributes() {\n        return attributes;\n    }\n\n    public void setAttributes(NodeAttributes attributes) {\n        this.attributes = attributes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/searchshards/item/ESShard.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.indices.searchshards.item;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class ESShard {\n    @JSONField(name = \"state\")\n    private String state;\n\n    @JSONField(name = \"primary\")\n    private boolean primary;\n\n    @JSONField(name = \"node\")\n    private String node;\n\n    @JSONField(name = \"relocating_node\")\n    private String relocatingNode;\n\n    @JSONField(name = \"shard\")\n    private long shard;\n\n    @JSONField(name = \"index\")\n    private String index;\n\n    @JSONField(name = \"version\")\n    private String version;\n\n    @JSONField(name = \"allocation_id\")\n    private AllocatinID allocationId;\n\n    public ESShard() {\n        // pass\n    }\n\n    public String getState() {\n        return state;\n    }\n\n    public void setState(String state) {\n        this.state = state;\n    }\n\n    public boolean isPrimary() {\n        return primary;\n    }\n\n    public void setPrimary(boolean primary) {\n        this.primary = primary;\n    }\n\n    public String getNode() {\n        return node;\n    }\n\n    public void setNode(String node) {\n        this.node = node;\n    }\n\n    public String getRelocatingNode() {\n        return relocatingNode;\n    }\n\n    public void setRelocatingNode(String relocatingNode) {\n        this.relocatingNode = relocatingNode;\n    }\n\n    public long getShard() {\n        return shard;\n    }\n\n    public void setShard(long shard) {\n        this.shard = shard;\n    }\n\n    public String getIndex() {\n        return index;\n    }\n\n    public void setIndex(String index) {\n        this.index = index;\n    }\n\n    public String getVersion() {\n        return version;\n    }\n\n    public void setVersion(String version) {\n        this.version = version;\n    }\n\n    public AllocatinID getAllocationId() {\n        return allocationId;\n    }\n\n    public void setAllocationId(AllocatinID allocationId) {\n        this.allocationId = allocationId;\n    }\n\n\n    public static class AllocatinID {\n        @JSONField(name = \"id\")\n        private String id;\n\n        public String getId() {\n            return id;\n        }\n\n        public void setId(String id) {\n            this.id = id;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/stats/ESIndicesStatsResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.stats;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.response.Shards;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n */\npublic class ESIndicesStatsResponse extends ESActionResponse {\n\n    @JSONField(name = \"_shards\")\n    private Shards shards;\n\n    @JSONField(name = \"_all\")\n    private IndexNodes all;\n\n    @JSONField(name = \"indices\")\n    private Map<String, IndexNodes> indices = new HashMap<>();\n\n    public ESIndicesStatsResponse() {\n        // pass\n    }\n\n    public Shards getShards() {\n        return shards;\n    }\n\n    public void setShards(Shards shards) {\n        this.shards = shards;\n    }\n\n    public IndexNodes getAll() {\n        return all;\n    }\n\n    public void setAll(IndexNodes all) {\n        this.all = all;\n    }\n\n    public JSONObject getIndices() {\n        if (indices == null || indices.size() == 0) {\n            return null;\n        }\n\n        JSONObject ret = new JSONObject();\n        for (Map.Entry<String,IndexNodes> entry : indices.entrySet()) {\n            ret.put(entry.getKey(), JSON.toJSON(entry.getValue()));\n        }\n        return ret;\n    }\n\n    public void setIndices(JSONObject root) {\n        if (root == null) {\n            return;\n        }\n\n        for (String index : root.keySet()) {\n            String str = root.getString(index);\n            indices.put(index, JSON.parseObject(str, IndexNodes.class));\n        }\n    }\n\n\n    @JSONField(serialize = false)\n    public Map<String, IndexNodes> getIndicesMap() {\n        return indices;\n    }\n\n    @JSONField(serialize = false)\n    public void setIndicesMap(Map<String, IndexNodes> indicesMap) {\n        this.indices = indicesMap;\n    }\n\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        return (JSONObject) JSON.toJSON(this);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/stats/IndexNodes.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.indices.stats;\n\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.response.model.indices.CommonStat;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic class IndexNodes {\n    @JSONField(name = \"primaries\")\n    private CommonStat primaries;\n\n    @JSONField(name = \"total\")\n    private CommonStat total;\n\n    @JSONField(name = \"shards\")\n    private Map<String, List<CommonStat>> shards;\n\n    public IndexNodes() {\n        // pass\n    }\n\n    public CommonStat getPrimaries() {\n        return primaries;\n    }\n\n    public void setPrimaries(CommonStat primaries) {\n        this.primaries = primaries;\n    }\n\n    public CommonStat getTotal() {\n        return total;\n    }\n\n    public void setTotal(CommonStat total) {\n        this.total = total;\n    }\n\n    public Map<String, List<CommonStat>> getShards() {\n        return shards;\n    }\n\n    public void setShards(Map<String, List<CommonStat>> shards) {\n        this.shards = shards;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/indices/updatesettings/ESIndicesUpdateSettingsResponse.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.indices.updatesettings;\n\nimport com.didi.arius.gateway.elasticsearch.client.response.ESAcknowledgedResponse;\n\npublic class ESIndicesUpdateSettingsResponse extends ESAcknowledgedResponse {\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/breakers/BreakerNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.breakers;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class BreakerNode {\n    @JSONField(name = \"limit_size_in_bytes\")\n    private long limitSizeInBytes;\n\n    @JSONField(name = \"limit_size\")\n    private String limitSize;\n\n    @JSONField(name = \"estimated_size_in_bytes\")\n    private long estimatedSizeInBytes;\n\n    @JSONField(name = \"estimated_size\")\n    private String estimatedSize;\n\n    @JSONField(name = \"overhead\")\n    private long overhead;\n\n    @JSONField(name = \"tripped\")\n    private long tripped;\n\n    public BreakerNode() {\n        // pass\n    }\n\n    public long getLimitSizeInBytes() {\n        return limitSizeInBytes;\n    }\n\n    public void setLimitSizeInBytes(long limitSizeInBytes) {\n        this.limitSizeInBytes = limitSizeInBytes;\n    }\n\n    public String getLimitSize() {\n        return limitSize;\n    }\n\n    public void setLimitSize(String limitSize) {\n        this.limitSize = limitSize;\n    }\n\n    public long getEstimatedSizeInBytes() {\n        return estimatedSizeInBytes;\n    }\n\n    public void setEstimatedSizeInBytes(long estimatedSizeInBytes) {\n        this.estimatedSizeInBytes = estimatedSizeInBytes;\n    }\n\n    public String getEstimatedSize() {\n        return estimatedSize;\n    }\n\n    public void setEstimatedSize(String estimatedSize) {\n        this.estimatedSize = estimatedSize;\n    }\n\n    public long getOverhead() {\n        return overhead;\n    }\n\n    public void setOverhead(long overhead) {\n        this.overhead = overhead;\n    }\n\n    public long getTripped() {\n        return tripped;\n    }\n\n    public void setTripped(long tripped) {\n        this.tripped = tripped;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/breakers/Breakers.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.breakers;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Breakers {\n    @JSONField(name = \"request\")\n    private BreakerNode request;\n\n    @JSONField(name = \"fielddata\")\n    private BreakerNode fielddata;\n\n    @JSONField(name = \"parent\")\n    private BreakerNode parent;\n\n    public Breakers() {\n        // pass\n    }\n\n    public BreakerNode getRequest() {\n        return request;\n    }\n\n    public void setRequest(BreakerNode request) {\n        this.request = request;\n    }\n\n    public BreakerNode getFielddata() {\n        return fielddata;\n    }\n\n    public void setFielddata(BreakerNode fielddata) {\n        this.fielddata = fielddata;\n    }\n\n    public BreakerNode getParent() {\n        return parent;\n    }\n\n    public void setParent(BreakerNode parent) {\n        this.parent = parent;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/fs/FSDataNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.fs;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class FSDataNode {\n    @JSONField(name = \"path\")\n    private String path;\n\n    @JSONField(name = \"mount\")\n    private String mount;\n\n    @JSONField(name = \"type\")\n    private String type;\n\n    @JSONField(name = \"total_in_bytes\")\n    private long totalInBytes;\n\n    @JSONField(name = \"free_in_bytes\")\n    private long freeInBytes;\n\n    @JSONField(name = \"available_in_bytes\")\n    private long availableInBytes;\n\n    public FSDataNode() {\n        // pass\n    }\n\n    public String getPath() {\n        return path;\n    }\n\n    public void setPath(String path) {\n        this.path = path;\n    }\n\n    public String getMount() {\n        return mount;\n    }\n\n    public void setMount(String mount) {\n        this.mount = mount;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public long getTotalInBytes() {\n        return totalInBytes;\n    }\n\n    public void setTotalInBytes(long totalInBytes) {\n        this.totalInBytes = totalInBytes;\n    }\n\n    public void setFreeInBytes(long freeInBytes) {\n        this.freeInBytes = freeInBytes;\n    }\n\n    public long getAvailableInBytes() {\n        return availableInBytes;\n    }\n\n    public void setAvailableInBytes(long availableInBytes) {\n        this.availableInBytes = availableInBytes;\n    }\n\n    public long getFreeInBytes() {\n        return freeInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/fs/FSNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.fs;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\nimport java.util.List;\n\npublic class FSNode {\n    @JSONField(name = \"timestamp\")\n    private long timestamp;\n\n    @JSONField(name = \"total\")\n    private FSTotal total;\n\n    @JSONField(name = \"data\")\n    private List<FSDataNode> data;\n\n    public FSNode() {\n        // pass\n    }\n\n    public long getTimestamp() {\n        return timestamp;\n    }\n\n    public void setTimestamp(long timestamp) {\n        this.timestamp = timestamp;\n    }\n\n    public FSTotal getTotal() {\n        return total;\n    }\n\n    public void setTotal(FSTotal total) {\n        this.total = total;\n    }\n\n    public List<FSDataNode> getData() {\n        return data;\n    }\n\n    public void setData(List<FSDataNode> data) {\n        this.data = data;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/fs/FSTotal.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.fs;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class FSTotal {\n    @JSONField(name = \"total_in_bytes\")\n    private long totalInBytes;\n\n    @JSONField(name = \"free_in_bytes\")\n    private long freeInBytes;\n\n    @JSONField(name = \"available_in_bytes\")\n    private long availableInBytes;\n\n    public FSTotal() {\n        // pass\n    }\n\n    public long getTotalInBytes() {\n        return totalInBytes;\n    }\n\n    public void setTotalInBytes(long totalInBytes) {\n        this.totalInBytes = totalInBytes;\n    }\n\n    public long getFreeInBytes() {\n        return freeInBytes;\n    }\n\n    public void setFreeInBytes(long freeInBytes) {\n        this.freeInBytes = freeInBytes;\n    }\n\n    public long getAvailableInBytes() {\n        return availableInBytes;\n    }\n\n    public void setAvailableInBytes(long availableInBytes) {\n        this.availableInBytes = availableInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/http/HttpNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.http;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class HttpNode {\n    @JSONField(name = \"current_open\")\n    private long currentOpen;\n\n    @JSONField(name = \"total_opened\")\n    private long totalOpened;\n\n    public HttpNode() {\n        // pass\n    }\n\n    public long getCurrentOpen() {\n        return currentOpen;\n    }\n\n    public void setCurrentOpen(long currentOpen) {\n        this.currentOpen = currentOpen;\n    }\n\n    public long getTotalOpened() {\n        return totalOpened;\n    }\n\n    public void setTotalOpened(long totalOpened) {\n        this.totalOpened = totalOpened;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/CommonStat.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic class CommonStat {\n    @JSONField(name = \"routing\")\n    private Routing routing;\n\n    @JSONField(name = \"docs\")\n    private Docs docs;\n\n    @JSONField(name = \"store\")\n    private Store store;\n\n    @JSONField(name = \"indexing\")\n    private Indexing indexing;\n\n    @JSONField(name = \"get\")\n    private Get get;\n\n    @JSONField(name = \"search\")\n    private Search search;\n\n    @JSONField(name = \"merges\")\n    private Merges merges;\n\n    @JSONField(name = \"refresh\")\n    private Refresh refresh;\n\n    @JSONField(name = \"flush\")\n    private Flush flush;\n\n    @JSONField(name = \"warmer\")\n    private Warmer warmer;\n\n    @JSONField(name = \"query_cache\")\n    private QueryCache queryCache;\n\n    @JSONField(name = \"fielddata\")\n    private Fielddata fielddata;\n\n    @JSONField(name = \"percolate\")\n    private Percolate percolate;\n\n    @JSONField(name = \"completion\")\n    private Completion completion;\n\n    @JSONField(name = \"segments\")\n    private Segments segments;\n\n    @JSONField(name = \"translog\")\n    private Translog translog;\n\n    @JSONField(name = \"suggest\")\n    private Suggest suggest;\n\n    @JSONField(name = \"request_cache\")\n    private RequestCache requestCache;\n\n    @JSONField(name = \"recovery\")\n    private Recovery recovery;\n\n    @JSONField(name = \"shards\")\n    private Map<String, List<Map<String, CommonStat>>> shards;\n\n    @JSONField(name = \"indices\")\n    private Map<String, CommonStat> indices;\n\n    public CommonStat() {\n        // pass\n    }\n\n    public Routing getRouting() {\n        return routing;\n    }\n\n    public void setRouting(Routing routing) {\n        this.routing = routing;\n    }\n\n    public Docs getDocs() {\n        return docs;\n    }\n\n    public void setDocs(Docs docs) {\n        this.docs = docs;\n    }\n\n    public Store getStore() {\n        return store;\n    }\n\n    public void setStore(Store store) {\n        this.store = store;\n    }\n\n    public Indexing getIndexing() {\n        return indexing;\n    }\n\n    public void setIndexing(Indexing indexing) {\n        this.indexing = indexing;\n    }\n\n    public Get getGet() {\n        return get;\n    }\n\n    public void setGet(Get get) {\n        this.get = get;\n    }\n\n    public Search getSearch() {\n        return search;\n    }\n\n    public void setSearch(Search search) {\n        this.search = search;\n    }\n\n    public Merges getMerges() {\n        return merges;\n    }\n\n    public void setMerges(Merges merges) {\n        this.merges = merges;\n    }\n\n    public Refresh getRefresh() {\n        return refresh;\n    }\n\n    public void setRefresh(Refresh refresh) {\n        this.refresh = refresh;\n    }\n\n    public Flush getFlush() {\n        return flush;\n    }\n\n    public void setFlush(Flush flush) {\n        this.flush = flush;\n    }\n\n    public Warmer getWarmer() {\n        return warmer;\n    }\n\n    public void setWarmer(Warmer warmer) {\n        this.warmer = warmer;\n    }\n\n    public QueryCache getQueryCache() {\n        return queryCache;\n    }\n\n    public void setQueryCache(QueryCache queryCache) {\n        this.queryCache = queryCache;\n    }\n\n    public Fielddata getFielddata() {\n        return fielddata;\n    }\n\n    public void setFielddata(Fielddata fielddata) {\n        this.fielddata = fielddata;\n    }\n\n    public Percolate getPercolate() {\n        return percolate;\n    }\n\n    public void setPercolate(Percolate percolate) {\n        this.percolate = percolate;\n    }\n\n    public Completion getCompletion() {\n        return completion;\n    }\n\n    public void setCompletion(Completion completion) {\n        this.completion = completion;\n    }\n\n    public Segments getSegments() {\n        return segments;\n    }\n\n    public void setSegments(Segments segments) {\n        this.segments = segments;\n    }\n\n    public Translog getTranslog() {\n        return translog;\n    }\n\n    public void setTranslog(Translog translog) {\n        this.translog = translog;\n    }\n\n    public Suggest getSuggest() {\n        return suggest;\n    }\n\n    public void setSuggest(Suggest suggest) {\n        this.suggest = suggest;\n    }\n\n    public RequestCache getRequestCache() {\n        return requestCache;\n    }\n\n    public void setRequestCache(RequestCache requestCache) {\n        this.requestCache = requestCache;\n    }\n\n    public Recovery getRecovery() {\n        return recovery;\n    }\n\n    public void setRecovery(Recovery recovery) {\n        this.recovery = recovery;\n    }\n\n\n    public Map<String, List<Map<String, CommonStat>>> getShards() {\n        return shards;\n    }\n\n    public void setShards(Map<String, List<Map<String, CommonStat>>> shards) {\n        this.shards = shards;\n    }\n\n    public Map<String, CommonStat> getIndices() {\n        return indices;\n    }\n\n    public void setIndices(Map<String, CommonStat> indices) {\n        this.indices = indices;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Completion.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Completion {\n    @JSONField(name = \"size_in_bytes\")\n    private long sizeInBytes;\n\n    public Completion() {\n        // pass\n    }\n\n    public long getSizeInBytes() {\n        return sizeInBytes;\n    }\n\n    public void setSizeInBytes(long sizeInBytes) {\n        this.sizeInBytes = sizeInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Docs.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Docs {\n    @JSONField(name = \"count\")\n    private long count;\n\n    @JSONField(name = \"deleted\")\n    private long deleted;\n\n    public Docs() {\n        // pass\n    }\n\n    public long getCount() {\n        return count;\n    }\n\n    public void setCount(long count) {\n        this.count = count;\n    }\n\n    public long getDeleted() {\n        return deleted;\n    }\n\n    public void setDeleted(long deleted) {\n        this.deleted = deleted;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Fielddata.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Fielddata {\n    @JSONField(name = \"memory_size_in_bytes\")\n    private long memorySizeInBytes;\n\n    @JSONField(name = \"evictions\")\n    private long evictions;\n\n    public Fielddata() {\n        // pass\n    }\n\n    public long getMemorySizeInBytes() {\n        return memorySizeInBytes;\n    }\n\n    public void setMemorySizeInBytes(long memorySizeInBytes) {\n        this.memorySizeInBytes = memorySizeInBytes;\n    }\n\n    public long getEvictions() {\n        return evictions;\n    }\n\n    public void setEvictions(long evictions) {\n        this.evictions = evictions;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Flush.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Flush {\n    @JSONField(name = \"total\")\n    private long total;\n\n    @JSONField(name = \"total_time_in_millis\")\n    private long totalTimeInMillis;\n\n    public Flush() {\n        // pass\n    }\n\n    public long getTotal() {\n        return total;\n    }\n\n    public void setTotal(long total) {\n        this.total = total;\n    }\n\n    public long getTotalTimeInMillis() {\n        return totalTimeInMillis;\n    }\n\n    public void setTotalTimeInMillis(long totalTimeInMillis) {\n        this.totalTimeInMillis = totalTimeInMillis;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Get.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Get {\n    @JSONField(name = \"total\")\n    private long total;\n\n    @JSONField(name = \"time_in_millis\")\n    private long timeInMillis;\n\n    @JSONField(name = \"exists_total\")\n    private long existsTotal;\n\n    @JSONField(name = \"exists_time_in_millis\")\n    private long existsTimeInMillis;\n\n    @JSONField(name = \"missing_total\")\n    private long missingTotal;\n\n    @JSONField(name = \"missing_time_in_millis\")\n    private long missingTimeInMillis;\n\n    @JSONField(name = \"current\")\n    private long current;\n\n    public Get() {\n        // pass\n    }\n\n    public long getTotal() {\n        return total;\n    }\n\n    public void setTotal(long total) {\n        this.total = total;\n    }\n\n    public long getTimeInMillis() {\n        return timeInMillis;\n    }\n\n    public void setTimeInMillis(long timeInMillis) {\n        this.timeInMillis = timeInMillis;\n    }\n\n    public long getExistsTotal() {\n        return existsTotal;\n    }\n\n    public void setExistsTotal(long existsTotal) {\n        this.existsTotal = existsTotal;\n    }\n\n    public long getExistsTimeInMillis() {\n        return existsTimeInMillis;\n    }\n\n    public void setExistsTimeInMillis(long existsTimeInMillis) {\n        this.existsTimeInMillis = existsTimeInMillis;\n    }\n\n    public long getMissingTotal() {\n        return missingTotal;\n    }\n\n    public void setMissingTotal(long missingTotal) {\n        this.missingTotal = missingTotal;\n    }\n\n    public long getMissingTimeInMillis() {\n        return missingTimeInMillis;\n    }\n\n    public void setMissingTimeInMillis(long missingTimeInMillis) {\n        this.missingTimeInMillis = missingTimeInMillis;\n    }\n\n    public long getCurrent() {\n        return current;\n    }\n\n    public void setCurrent(long current) {\n        this.current = current;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Indexing.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Indexing {\n\n    @JSONField(name = \"index_total\")\n    private long indexTotal;\n\n    @JSONField(name = \"index_time_in_millis\")\n    private long indexTimeInMillis;\n\n    @JSONField(name = \"index_current\")\n    private long indexCurrent;\n\n    @JSONField(name = \"index_failed\")\n    private long indexFailed;\n\n    @JSONField(name = \"delete_total\")\n    private long deleteTotal;\n\n    @JSONField(name = \"delete_time_in_millis\")\n    private long deleteTimeInMillis;\n\n    @JSONField(name = \"delete_current\")\n    private long deleteCurrent;\n\n    @JSONField(name = \"noop_update_total\")\n    private long noopUpdateTotal;\n\n    @JSONField(name = \"is_throttled\")\n    private boolean isThrottled;\n\n    @JSONField(name = \"throttle_time_in_millis\")\n    private long throttleTimeInMillis;\n\n    public Indexing() {\n        // pass\n    }\n\n    public long getIndexTotal() {\n        return indexTotal;\n    }\n\n    public void setIndexTotal(long indexTotal) {\n        this.indexTotal = indexTotal;\n    }\n\n    public long getIndexTimeInMillis() {\n        return indexTimeInMillis;\n    }\n\n    public void setIndexTimeInMillis(long indexTimeInMillis) {\n        this.indexTimeInMillis = indexTimeInMillis;\n    }\n\n    public long getIndexCurrent() {\n        return indexCurrent;\n    }\n\n    public void setIndexCurrent(long indexCurrent) {\n        this.indexCurrent = indexCurrent;\n    }\n\n    public long getIndexFailed() {\n        return indexFailed;\n    }\n\n    public void setIndexFailed(long indexFailed) {\n        this.indexFailed = indexFailed;\n    }\n\n    public long getDeleteTotal() {\n        return deleteTotal;\n    }\n\n    public void setDeleteTotal(long deleteTotal) {\n        this.deleteTotal = deleteTotal;\n    }\n\n    public long getDeleteTimeInMillis() {\n        return deleteTimeInMillis;\n    }\n\n    public void setDeleteTimeInMillis(long deleteTimeInMillis) {\n        this.deleteTimeInMillis = deleteTimeInMillis;\n    }\n\n    public long getDeleteCurrent() {\n        return deleteCurrent;\n    }\n\n    public void setDeleteCurrent(long deleteCurrent) {\n        this.deleteCurrent = deleteCurrent;\n    }\n\n    public long getNoopUpdateTotal() {\n        return noopUpdateTotal;\n    }\n\n    public void setNoopUpdateTotal(long noopUpdateTotal) {\n        this.noopUpdateTotal = noopUpdateTotal;\n    }\n\n    public boolean getThrottled() {\n        return isThrottled;\n    }\n\n    public void setThrottled(boolean throttled) {\n        this.isThrottled = throttled;\n    }\n\n    public long getThrottleTimeInMillis() {\n        return throttleTimeInMillis;\n    }\n\n    public void setThrottleTimeInMillis(long throttleTimeInMillis) {\n        this.throttleTimeInMillis = throttleTimeInMillis;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Merges.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Merges {\n    @JSONField(name = \"current\")\n    private long current;\n\n    @JSONField(name = \"current_docs\")\n    private long currentDocs;\n\n    @JSONField(name = \"current_size_in_bytes\")\n    private long currentSizeInBytes;\n\n    @JSONField(name = \"total\")\n    private long total;\n\n    @JSONField(name = \"total_time_in_millis\")\n    private long totalTimeInMillis;\n\n    @JSONField(name = \"total_docs\")\n    private long totalDocs;\n\n    @JSONField(name = \"total_size_in_bytes\")\n    private long totalSizeInBytes;\n\n    @JSONField(name = \"total_stopped_time_in_millis\")\n    private long totalStoppedTimeInMillis;\n\n    @JSONField(name = \"total_throttled_time_in_millis\")\n    private long totalThrottledTimeInMillis;\n\n    @JSONField(name = \"total_auto_throttle_in_bytes\")\n    private long totalAutoThrottleInBytes;\n\n    public Merges() {\n        // pass\n    }\n\n    public long getCurrent() {\n        return current;\n    }\n\n    public void setCurrent(long current) {\n        this.current = current;\n    }\n\n    public long getCurrentDocs() {\n        return currentDocs;\n    }\n\n    public void setCurrentDocs(long currentDocs) {\n        this.currentDocs = currentDocs;\n    }\n\n    public long getCurrentSizeInBytes() {\n        return currentSizeInBytes;\n    }\n\n    public void setCurrentSizeInBytes(long currentSizeInBytes) {\n        this.currentSizeInBytes = currentSizeInBytes;\n    }\n\n    public long getTotal() {\n        return total;\n    }\n\n    public void setTotal(long total) {\n        this.total = total;\n    }\n\n    public long getTotalTimeInMillis() {\n        return totalTimeInMillis;\n    }\n\n    public void setTotalTimeInMillis(long totalTimeInMillis) {\n        this.totalTimeInMillis = totalTimeInMillis;\n    }\n\n    public long getTotalDocs() {\n        return totalDocs;\n    }\n\n    public void setTotalDocs(long totalDocs) {\n        this.totalDocs = totalDocs;\n    }\n\n    public long getTotalSizeInBytes() {\n        return totalSizeInBytes;\n    }\n\n    public void setTotalSizeInBytes(long totalSizeInBytes) {\n        this.totalSizeInBytes = totalSizeInBytes;\n    }\n\n    public long getTotalStoppedTimeInMillis() {\n        return totalStoppedTimeInMillis;\n    }\n\n    public void setTotalStoppedTimeInMillis(long totalStoppedTimeInMillis) {\n        this.totalStoppedTimeInMillis = totalStoppedTimeInMillis;\n    }\n\n    public long getTotalThrottledTimeInMillis() {\n        return totalThrottledTimeInMillis;\n    }\n\n    public void setTotalThrottledTimeInMillis(long totalThrottledTimeInMillis) {\n        this.totalThrottledTimeInMillis = totalThrottledTimeInMillis;\n    }\n\n    public long getTotalAutoThrottleInBytes() {\n        return totalAutoThrottleInBytes;\n    }\n\n    public void setTotalAutoThrottleInBytes(long totalAutoThrottleInBytes) {\n        this.totalAutoThrottleInBytes = totalAutoThrottleInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Percolate.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Percolate {\n    @JSONField(name = \"total\")\n    private long total;\n\n    @JSONField(name = \"time_in_millis\")\n    private long timeInMillis;\n\n    @JSONField(name = \"current\")\n    private long current;\n\n    @JSONField(name = \"memory_size_in_bytes\")\n    private long memorySizeInBytes;\n\n    @JSONField(name = \"memory_size\")\n    private String memorySize;\n\n    @JSONField(name = \"queries\")\n    private long queries;\n\n    public Percolate() {\n        // pass\n    }\n\n    public long getTotal() {\n        return total;\n    }\n\n    public long getTimeInMillis() {\n        return timeInMillis;\n    }\n\n    public void setTimeInMillis(long timeInMillis) {\n        this.timeInMillis = timeInMillis;\n    }\n\n    public long getCurrent() {\n        return current;\n    }\n\n    public void setTotal(long total) {\n        this.total = total;\n    }\n\n    public void setCurrent(long current) {\n        this.current = current;\n    }\n\n    public long getMemorySizeInBytes() {\n        return memorySizeInBytes;\n    }\n\n    public void setMemorySizeInBytes(long memorySizeInBytes) {\n        this.memorySizeInBytes = memorySizeInBytes;\n    }\n\n    public String getMemorySize() {\n        return memorySize;\n    }\n\n    public void setMemorySize(String memorySize) {\n        this.memorySize = memorySize;\n    }\n\n    public long getQueries() {\n        return queries;\n    }\n\n    public void setQueries(long queries) {\n        this.queries = queries;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/QueryCache.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class QueryCache {\n    @JSONField(name = \"memory_size_in_bytes\")\n    private long memorySizeInBytes;\n\n    @JSONField(name = \"total_count\")\n    private long totalCount;\n\n    @JSONField(name = \"hit_count\")\n    private long hitCount;\n\n    @JSONField(name = \"miss_count\")\n    private long missCount;\n\n    @JSONField(name = \"cache_size\")\n    private long cacheSize;\n\n    @JSONField(name = \"cache_count\")\n    private long cacheCount;\n\n    @JSONField(name = \"evictions\")\n    private long evictions;\n\n    public QueryCache() {\n        // pass\n    }\n\n    public long getMemorySizeInBytes() {\n        return memorySizeInBytes;\n    }\n\n    public void setMemorySizeInBytes(long memorySizeInBytes) {\n        this.memorySizeInBytes = memorySizeInBytes;\n    }\n\n    public long getTotalCount() {\n        return totalCount;\n    }\n\n    public void setTotalCount(long totalCount) {\n        this.totalCount = totalCount;\n    }\n\n    public long getHitCount() {\n        return hitCount;\n    }\n\n    public void setHitCount(long hitCount) {\n        this.hitCount = hitCount;\n    }\n\n    public long getMissCount() {\n        return missCount;\n    }\n\n    public void setMissCount(long missCount) {\n        this.missCount = missCount;\n    }\n\n    public long getCacheSize() {\n        return cacheSize;\n    }\n\n    public void setCacheSize(long cacheSize) {\n        this.cacheSize = cacheSize;\n    }\n\n    public long getCacheCount() {\n        return cacheCount;\n    }\n\n    public void setCacheCount(long cacheCount) {\n        this.cacheCount = cacheCount;\n    }\n\n    public long getEvictions() {\n        return evictions;\n    }\n\n    public void setEvictions(long evictions) {\n        this.evictions = evictions;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Recovery.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Recovery {\n    @JSONField(name = \"current_as_source\")\n    private long currentAsSource;\n\n    @JSONField(name = \"current_as_target\")\n    private long currentAsTarget;\n\n    @JSONField(name = \"throttle_time_in_millis\")\n    private long throttleTimeInMillis;\n\n    public Recovery() {\n        // pass\n    }\n\n    public long getCurrentAsSource() {\n        return currentAsSource;\n    }\n\n    public void setCurrentAsSource(long currentAsSource) {\n        this.currentAsSource = currentAsSource;\n    }\n\n    public long getCurrentAsTarget() {\n        return currentAsTarget;\n    }\n\n    public void setCurrentAsTarget(long currentAsTarget) {\n        this.currentAsTarget = currentAsTarget;\n    }\n\n    public long getThrottleTimeInMillis() {\n        return throttleTimeInMillis;\n    }\n\n    public void setThrottleTimeInMillis(long throttleTimeInMillis) {\n        this.throttleTimeInMillis = throttleTimeInMillis;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Refresh.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Refresh {\n    @JSONField(name = \"total\")\n    private long total;\n\n    @JSONField(name = \"total_time_in_millis\")\n    private long totalTimeInMillis;\n\n    public Refresh() {\n        // pass\n    }\n\n    public long getTotal() {\n        return total;\n    }\n\n    public void setTotal(long total) {\n        this.total = total;\n    }\n\n    public long getTotalTimeInMillis() {\n        return totalTimeInMillis;\n    }\n\n    public void setTotalTimeInMillis(long totalTimeInMillis) {\n        this.totalTimeInMillis = totalTimeInMillis;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/RequestCache.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class RequestCache {\n    @JSONField(name = \"memory_size_in_bytes\")\n    private long memorySizeInBytes;\n\n    @JSONField(name = \"evictions\")\n    private long evictions;\n\n    @JSONField(name = \"hit_count\")\n    private long hitCount;\n\n    @JSONField(name = \"miss_count\")\n    private long missCount;\n\n    public RequestCache() {\n        // pass\n    }\n\n    public long getMemorySizeInBytes() {\n        return memorySizeInBytes;\n    }\n\n    public void setMemorySizeInBytes(long memorySizeInBytes) {\n        this.memorySizeInBytes = memorySizeInBytes;\n    }\n\n    public long getEvictions() {\n        return evictions;\n    }\n\n    public void setEvictions(long evictions) {\n        this.evictions = evictions;\n    }\n\n    public long getHitCount() {\n        return hitCount;\n    }\n\n    public void setHitCount(long hitCount) {\n        this.hitCount = hitCount;\n    }\n\n    public long getMissCount() {\n        return missCount;\n    }\n\n    public void setMissCount(long missCount) {\n        this.missCount = missCount;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Routing.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Routing {\n    @JSONField(name = \"state\")\n    private String state;\n\n    @JSONField(name = \"primary\")\n    private boolean primary;\n\n    @JSONField(name = \"node\")\n    private String node;\n\n    @JSONField(name = \"relocating_node\")\n    private String relocatingNode;\n\n    public Routing() {\n        // pass\n    }\n\n    public String getState() {\n        return state;\n    }\n\n    public void setNode(String node) {\n        this.node = node;\n    }\n\n    public void setState(String state) {\n        this.state = state;\n    }\n\n    public boolean isPrimary() {\n        return primary;\n    }\n\n    public String getNode() {\n        return node;\n    }\n\n    public void setPrimary(boolean primary) {\n        this.primary = primary;\n    }\n\n    public String getRelocatingNode() {\n        return relocatingNode;\n    }\n\n    public void setRelocatingNode(String relocatingNode) {\n        this.relocatingNode = relocatingNode;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Search.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Search {\n    @JSONField(name = \"open_contexts\")\n    private long openContexts;\n\n    @JSONField(name = \"query_total\")\n    private long queryTotal;\n\n    @JSONField(name = \"query_time_in_millis\")\n    private long queryTimeInMillis;\n\n    @JSONField(name = \"query_current\")\n    private long queryCurrent;\n\n    @JSONField(name = \"fetch_total\")\n    private long fetchTotal;\n\n    @JSONField(name = \"fetch_time_in_millis\")\n    private long fetchTimeInMillis;\n\n    @JSONField(name = \"fetch_current\")\n    private long fetchCurrent;\n\n    @JSONField(name = \"scroll_total\")\n    private long scrollTotal;\n\n    @JSONField(name = \"scroll_time_in_millis\")\n    private long scrollTimeInMillis;\n\n    @JSONField(name = \"scroll_current\")\n    private long scrollCurrent;\n\n    public Search() {\n        // pass\n    }\n\n    public long getOpenContexts() {\n        return openContexts;\n    }\n\n    public void setOpenContexts(long openContexts) {\n        this.openContexts = openContexts;\n    }\n\n    public long getQueryTotal() {\n        return queryTotal;\n    }\n\n    public void setQueryTotal(long queryTotal) {\n        this.queryTotal = queryTotal;\n    }\n\n    public long getQueryTimeInMillis() {\n        return queryTimeInMillis;\n    }\n\n    public void setQueryTimeInMillis(long queryTimeInMillis) {\n        this.queryTimeInMillis = queryTimeInMillis;\n    }\n\n    public long getQueryCurrent() {\n        return queryCurrent;\n    }\n\n    public void setQueryCurrent(long queryCurrent) {\n        this.queryCurrent = queryCurrent;\n    }\n\n    public long getFetchTotal() {\n        return fetchTotal;\n    }\n\n    public void setFetchTotal(long fetchTotal) {\n        this.fetchTotal = fetchTotal;\n    }\n\n    public long getFetchTimeInMillis() {\n        return fetchTimeInMillis;\n    }\n\n    public void setFetchTimeInMillis(long fetchTimeInMillis) {\n        this.fetchTimeInMillis = fetchTimeInMillis;\n    }\n\n    public long getFetchCurrent() {\n        return fetchCurrent;\n    }\n\n    public void setFetchCurrent(long fetchCurrent) {\n        this.fetchCurrent = fetchCurrent;\n    }\n\n    public long getScrollTotal() {\n        return scrollTotal;\n    }\n\n    public void setScrollTotal(long scrollTotal) {\n        this.scrollTotal = scrollTotal;\n    }\n\n    public long getScrollTimeInMillis() {\n        return scrollTimeInMillis;\n    }\n\n    public void setScrollTimeInMillis(long scrollTimeInMillis) {\n        this.scrollTimeInMillis = scrollTimeInMillis;\n    }\n\n    public long getScrollCurrent() {\n        return scrollCurrent;\n    }\n\n    public void setScrollCurrent(long scrollCurrent) {\n        this.scrollCurrent = scrollCurrent;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Segments.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Segments {\n\n    @JSONField(name = \"count\")\n    private long count;\n\n    @JSONField(name = \"memory_in_bytes\")\n    private long memoryInBytes;\n\n    @JSONField(name = \"terms_memory_in_bytes\")\n    private long termsMemoryInBytes;\n\n    @JSONField(name = \"stored_fields_memory_in_bytes\")\n    private long storedFieldsMemoryInBytes;\n\n    @JSONField(name = \"term_vectors_memory_in_bytes\")\n    private long termVectorsMemoryInBytes;\n\n    @JSONField(name = \"norms_memory_in_bytes\")\n    private long normsMemoryInBytes;\n\n    @JSONField(name = \"doc_values_memory_in_bytes\")\n    private long docValuesMemoryInBytes;\n\n    @JSONField(name = \"index_writer_memory_in_bytes\")\n    private long indexWriterMemoryInBytes;\n\n    @JSONField(name = \"index_writer_max_memory_in_bytes\")\n    private long indexWriterMaxMemoryInBytes;\n\n    @JSONField(name = \"version_map_memory_in_bytes\")\n    private long versionMapMemoryInBytes;\n\n    @JSONField(name = \"fixed_bit_set_memory_in_bytes\")\n    private long fixedBitSetMemoryInBytes;\n\n    public Segments() {\n        // pass\n    }\n\n    public long getCount() {\n        return count;\n    }\n\n    public void setCount(long count) {\n        this.count = count;\n    }\n\n    public long getMemoryInBytes() {\n        return memoryInBytes;\n    }\n\n    public void setMemoryInBytes(long memoryInBytes) {\n        this.memoryInBytes = memoryInBytes;\n    }\n\n    public long getTermsMemoryInBytes() {\n        return termsMemoryInBytes;\n    }\n\n    public void setTermsMemoryInBytes(long termsMemoryInBytes) {\n        this.termsMemoryInBytes = termsMemoryInBytes;\n    }\n\n    public long getStoredFieldsMemoryInBytes() {\n        return storedFieldsMemoryInBytes;\n    }\n\n    public void setStoredFieldsMemoryInBytes(long storedFieldsMemoryInBytes) {\n        this.storedFieldsMemoryInBytes = storedFieldsMemoryInBytes;\n    }\n\n    public long getTermVectorsMemoryInBytes() {\n        return termVectorsMemoryInBytes;\n    }\n\n    public void setTermVectorsMemoryInBytes(long termVectorsMemoryInBytes) {\n        this.termVectorsMemoryInBytes = termVectorsMemoryInBytes;\n    }\n\n    public long getNormsMemoryInBytes() {\n        return normsMemoryInBytes;\n    }\n\n    public void setNormsMemoryInBytes(long normsMemoryInBytes) {\n        this.normsMemoryInBytes = normsMemoryInBytes;\n    }\n\n    public long getDocValuesMemoryInBytes() {\n        return docValuesMemoryInBytes;\n    }\n\n    public void setDocValuesMemoryInBytes(long docValuesMemoryInBytes) {\n        this.docValuesMemoryInBytes = docValuesMemoryInBytes;\n    }\n\n    public long getIndexWriterMemoryInBytes() {\n        return indexWriterMemoryInBytes;\n    }\n\n    public void setIndexWriterMemoryInBytes(long indexWriterMemoryInBytes) {\n        this.indexWriterMemoryInBytes = indexWriterMemoryInBytes;\n    }\n\n    public long getIndexWriterMaxMemoryInBytes() {\n        return indexWriterMaxMemoryInBytes;\n    }\n\n    public void setIndexWriterMaxMemoryInBytes(long indexWriterMaxMemoryInBytes) {\n        this.indexWriterMaxMemoryInBytes = indexWriterMaxMemoryInBytes;\n    }\n\n    public long getVersionMapMemoryInBytes() {\n        return versionMapMemoryInBytes;\n    }\n\n    public void setVersionMapMemoryInBytes(long versionMapMemoryInBytes) {\n        this.versionMapMemoryInBytes = versionMapMemoryInBytes;\n    }\n\n    public long getFixedBitSetMemoryInBytes() {\n        return fixedBitSetMemoryInBytes;\n    }\n\n    public void setFixedBitSetMemoryInBytes(long fixedBitSetMemoryInBytes) {\n        this.fixedBitSetMemoryInBytes = fixedBitSetMemoryInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Store.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Store {\n    @JSONField(name = \"size_in_bytes\")\n    private long sizeInBytes;\n\n    @JSONField(name = \"throttle_time_in_millis\")\n    private long throttleTimeInMillis;\n\n    public Store() {\n        // pass\n    }\n\n    public long getSizeInBytes() {\n        return sizeInBytes;\n    }\n\n    public void setSizeInBytes(long sizeInBytes) {\n        this.sizeInBytes = sizeInBytes;\n    }\n\n    public long getThrottleTimeInMillis() {\n        return throttleTimeInMillis;\n    }\n\n    public void setThrottleTimeInMillis(long throttleTimeInMillis) {\n        this.throttleTimeInMillis = throttleTimeInMillis;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Suggest.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Suggest {\n    @JSONField(name = \"total\")\n    private long total;\n\n    @JSONField(name = \"time_in_millis\")\n    private long timeInMillis;\n\n    @JSONField(name = \"current\")\n    private long current;\n\n    public Suggest() {\n        // pass\n    }\n\n    public long getTotal() {\n        return total;\n    }\n\n    public void setTotal(long total) {\n        this.total = total;\n    }\n\n    public long getTimeInMillis() {\n        return timeInMillis;\n    }\n\n    public void setTimeInMillis(long timeInMillis) {\n        this.timeInMillis = timeInMillis;\n    }\n\n    public long getCurrent() {\n        return current;\n    }\n\n    public void setCurrent(long current) {\n        this.current = current;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Translog.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Translog {\n    @JSONField(name = \"operations\")\n    private long operations;\n\n    @JSONField(name = \"size_in_bytes\")\n    private long sizeInBytes;\n\n    public Translog() {\n        // pass\n    }\n\n    public long getOperations() {\n        return operations;\n    }\n\n    public void setOperations(long operations) {\n        this.operations = operations;\n    }\n\n    public long getSizeInBytes() {\n        return sizeInBytes;\n    }\n\n    public void setSizeInBytes(long sizeInBytes) {\n        this.sizeInBytes = sizeInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/indices/Warmer.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.indices;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class Warmer {\n    @JSONField(name = \"current\")\n    private long current;\n\n    @JSONField(name = \"total\")\n    private long total;\n\n    @JSONField(name = \"total_time_in_millis\")\n    private long totalTimeInMillis;\n\n    public Warmer() {\n        // pass\n    }\n\n    public long getCurrent() {\n        return current;\n    }\n\n    public void setCurrent(long current) {\n        this.current = current;\n    }\n\n    public long getTotal() {\n        return total;\n    }\n\n    public void setTotal(long total) {\n        this.total = total;\n    }\n\n    public long getTotalTimeInMillis() {\n        return totalTimeInMillis;\n    }\n\n    public void setTotalTimeInMillis(long totalTimeInMillis) {\n        this.totalTimeInMillis = totalTimeInMillis;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/jvm/JvmBufferPoolsNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.jvm;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class JvmBufferPoolsNode {\n    @JSONField(name = \"count\")\n    private long count;\n\n    @JSONField(name = \"used_in_bytes\")\n    private long usedInBytes;\n\n    @JSONField(name = \"total_capacity_in_bytes\")\n    private long totalCapacityInBytes;\n\n    public JvmBufferPoolsNode() {\n        // pass\n    }\n\n    public long getCount() {\n        return count;\n    }\n\n    public void setCount(long count) {\n        this.count = count;\n    }\n\n    public long getUsedInBytes() {\n        return usedInBytes;\n    }\n\n    public void setUsedInBytes(long usedInBytes) {\n        this.usedInBytes = usedInBytes;\n    }\n\n    public long getTotalCapacityInBytes() {\n        return totalCapacityInBytes;\n    }\n\n    public void setTotalCapacityInBytes(long totalCapacityInBytes) {\n        this.totalCapacityInBytes = totalCapacityInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/jvm/JvmGCNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.jvm;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class JvmGCNode {\n    @JSONField(name = \"collection_count\")\n    private long collectionCount;\n\n    @JSONField(name = \"collection_time_in_millis\")\n    private long collectionTimeInMillis;\n\n    public JvmGCNode() {\n        // pass\n    }\n\n    public long getCollectionCount() {\n        return collectionCount;\n    }\n\n    public void setCollectionCount(long collectionCount) {\n        this.collectionCount = collectionCount;\n    }\n\n    public long getCollectionTimeInMillis() {\n        return collectionTimeInMillis;\n    }\n\n    public void setCollectionTimeInMillis(long collectionTimeInMillis) {\n        this.collectionTimeInMillis = collectionTimeInMillis;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/jvm/JvmMem.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.jvm;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\nimport java.util.Map;\n\npublic class JvmMem {\n\n    @JSONField(name = \"heap_used_in_bytes\")\n    private long heapUsedInBytes;\n\n    @JSONField(name = \"heap_used_percent\")\n    private long heapUsedPercent;\n\n    @JSONField(name = \"heap_committed_in_bytes\")\n    private long heapCommittedInBytes;\n\n    @JSONField(name = \"heap_max_in_bytes\")\n    private long heapMaxInBytes;\n\n    @JSONField(name = \"non_heap_used_in_bytes\")\n    private long nonHeapUsedInBytes;\n\n    @JSONField(name = \"non_heap_committed_in_bytes\")\n    private long nonHeapCommittedInBytes;\n\n    private Map<String, JvmMemPoolNode> pools;\n\n    public JvmMem() {\n        // pass\n    }\n\n    public long getHeapUsedInBytes() {\n        return heapUsedInBytes;\n    }\n\n    public void setHeapUsedInBytes(long heapUsedInBytes) {\n        this.heapUsedInBytes = heapUsedInBytes;\n    }\n\n    public long getHeapUsedPercent() {\n        return heapUsedPercent;\n    }\n\n    public void setHeapUsedPercent(long heapUsedPercent) {\n        this.heapUsedPercent = heapUsedPercent;\n    }\n\n    public long getHeapCommittedInBytes() {\n        return heapCommittedInBytes;\n    }\n\n    public void setHeapCommittedInBytes(long heapCommittedInBytes) {\n        this.heapCommittedInBytes = heapCommittedInBytes;\n    }\n\n    public long getHeapMaxInBytes() {\n        return heapMaxInBytes;\n    }\n\n    public void setHeapMaxInBytes(long heapMaxInBytes) {\n        this.heapMaxInBytes = heapMaxInBytes;\n    }\n\n    public long getNonHeapUsedInBytes() {\n        return nonHeapUsedInBytes;\n    }\n\n    public void setNonHeapUsedInBytes(long nonHeapUsedInBytes) {\n        this.nonHeapUsedInBytes = nonHeapUsedInBytes;\n    }\n\n    public long getNonHeapCommittedInBytes() {\n        return nonHeapCommittedInBytes;\n    }\n\n    public void setNonHeapCommittedInBytes(long nonHeapCommittedInBytes) {\n        this.nonHeapCommittedInBytes = nonHeapCommittedInBytes;\n    }\n\n    public Map<String, JvmMemPoolNode> getPools() {\n        return pools;\n    }\n\n    public void setPools(Map<String, JvmMemPoolNode> pools) {\n        this.pools = pools;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/jvm/JvmMemPoolNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.jvm;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class JvmMemPoolNode {\n    @JSONField(name = \"used_in_bytes\")\n    private long usedInBytes;\n\n    @JSONField(name = \"max_in_bytes\")\n    private long maxInBytes;\n\n    @JSONField(name = \"peak_used_in_bytes\")\n    private long peakUsedInBytes;\n\n    @JSONField(name = \"peak_max_in_bytes\")\n    private long peakMaxInBytes;\n\n    public JvmMemPoolNode() {\n        // pass\n    }\n\n    public long getUsedInBytes() {\n        return usedInBytes;\n    }\n\n    public void setUsedInBytes(long usedInBytes) {\n        this.usedInBytes = usedInBytes;\n    }\n\n    public long getMaxInBytes() {\n        return maxInBytes;\n    }\n\n    public void setMaxInBytes(long maxInBytes) {\n        this.maxInBytes = maxInBytes;\n    }\n\n    public long getPeakUsedInBytes() {\n        return peakUsedInBytes;\n    }\n\n    public void setPeakUsedInBytes(long peakUsedInBytes) {\n        this.peakUsedInBytes = peakUsedInBytes;\n    }\n\n    public long getPeakMaxInBytes() {\n        return peakMaxInBytes;\n    }\n\n    public void setPeakMaxInBytes(long peakMaxInBytes) {\n        this.peakMaxInBytes = peakMaxInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/jvm/JvmNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.jvm;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\nimport java.util.Map;\n\npublic class JvmNode {\n    @JSONField(name = \"timestamp\")\n    private long timestamp;\n    @JSONField(name = \"uptime_in_millis\")\n    private long uptimeInMillis;\n\n    @JSONField(name = \"mem\")\n    private JvmMem mem;\n    @JSONField(name = \"threads\")\n    private JvmThreads threads;\n    @JSONField(name = \"gc\")\n    private Map<String, Map<String, JvmGCNode>> gc;\n    @JSONField(name = \"buffer_pools\")\n    private Map<String, JvmBufferPoolsNode> bufferPools;\n\n    public JvmNode() {\n        // pass\n    }\n\n    public long getTimestamp() {\n        return timestamp;\n    }\n\n    public void setTimestamp(long timestamp) {\n        this.timestamp = timestamp;\n    }\n\n    public long getUptimeInMillis() {\n        return uptimeInMillis;\n    }\n\n    public void setUptimeInMillis(long uptimeInMillis) {\n        this.uptimeInMillis = uptimeInMillis;\n    }\n\n    public JvmMem getMem() {\n        return mem;\n    }\n\n    public void setMem(JvmMem mem) {\n        this.mem = mem;\n    }\n\n    public JvmThreads getThreads() {\n        return threads;\n    }\n\n    public void setThreads(JvmThreads threads) {\n        this.threads = threads;\n    }\n\n    public Map<String, Map<String, JvmGCNode>> getGc() {\n        return gc;\n    }\n\n    public void setGc(Map<String, Map<String, JvmGCNode>> gc) {\n        this.gc = gc;\n    }\n\n    public Map<String, JvmBufferPoolsNode> getBufferPools() {\n        return bufferPools;\n    }\n\n    public void setBufferPools(Map<String, JvmBufferPoolsNode> bufferPools) {\n        this.bufferPools = bufferPools;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/jvm/JvmThreads.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.jvm;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class JvmThreads {\n    @JSONField(name = \"count\")\n    private long count;\n\n    @JSONField(name = \"peak_count\")\n    private long peakCount;\n\n    public JvmThreads() {\n        // pass\n    }\n\n    public long getCount() {\n        return count;\n    }\n\n    public void setCount(long count) {\n        this.count = count;\n    }\n\n    public long getPeakCount() {\n        return peakCount;\n    }\n\n    public void setPeakCount(long peakCount) {\n        this.peakCount = peakCount;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/node/NodeAttributes.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.node;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class NodeAttributes {\n    @JSONField(name = \"set\")\n    private String set;\n    @JSONField(name = \"max_local_storage_nodes\")\n    private long maxLocalStorageNodes;\n    @JSONField(name = \"master\")\n    private boolean master;\n\n    public NodeAttributes() {\n        // pass\n    }\n\n    public String getSet() {\n        return set;\n    }\n\n    public void setSet(String set) {\n        this.set = set;\n    }\n\n    public long getMaxLocalStorageNodes() {\n        return maxLocalStorageNodes;\n    }\n\n    public void setMaxLocalStorageNodes(long maxLocalStorageNodes) {\n        this.maxLocalStorageNodes = maxLocalStorageNodes;\n    }\n\n    public boolean isMaster() {\n        return master;\n    }\n\n    public void setMaster(boolean master) {\n        this.master = master;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/os/OsMem.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.os;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class OsMem {\n\n    @JSONField(name = \"total_in_bytes\")\n    private long totalInBytes;\n    @JSONField(name = \"free_in_bytes\")\n    private long freeInBytes;\n    @JSONField(name = \"used_in_bytes\")\n    private long usedInBytes;\n    @JSONField(name = \"free_percent\")\n    private long freePercent;\n    @JSONField(name = \"used_percent\")\n    private long usedPercent;\n\n    public OsMem() {\n        // pass\n    }\n\n    public long getTotalInBytes() {\n        return totalInBytes;\n    }\n\n    public long getFreeInBytes() {\n        return freeInBytes;\n    }\n\n    public void setTotalInBytes(long totalInBytes) {\n        this.totalInBytes = totalInBytes;\n    }\n\n    public void setFreeInBytes(long freeInBytes) {\n        this.freeInBytes = freeInBytes;\n    }\n\n    public long getUsedInBytes() {\n        return usedInBytes;\n    }\n\n    public void setUsedInBytes(long usedInBytes) {\n        this.usedInBytes = usedInBytes;\n    }\n\n    public long getFreePercent() {\n        return freePercent;\n    }\n\n    public void setFreePercent(long freePercent) {\n        this.freePercent = freePercent;\n    }\n\n    public long getUsedPercent() {\n        return usedPercent;\n    }\n\n    public void setUsedPercent(long usedPercent) {\n        this.usedPercent = usedPercent;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/os/OsNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.os;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class OsNode {\n    @JSONField(name = \"timestamp\")\n    private long timestamp;\n    @JSONField(name = \"cpu_percent\")\n    private long cpuPercent;\n    @JSONField(name = \"load_average\")\n    private double loadAverage;\n    @JSONField(name = \"mem\")\n    private OsMem mem;\n    @JSONField(name = \"swap\")\n    private OsSwap swap;\n\n    public OsNode() {\n        // pass\n    }\n\n    public long getTimestamp() {\n        return timestamp;\n    }\n\n    public void setTimestamp(long timestamp) {\n        this.timestamp = timestamp;\n    }\n\n    public long getCpuPercent() {\n        return cpuPercent;\n    }\n\n    public void setCpuPercent(long cpuPercent) {\n        this.cpuPercent = cpuPercent;\n    }\n\n    public double getLoadAverage() {\n        return loadAverage;\n    }\n\n    public void setLoadAverage(double loadAverage) {\n        this.loadAverage = loadAverage;\n    }\n\n    public OsMem getMem() {\n        return mem;\n    }\n\n    public void setMem(OsMem mem) {\n        this.mem = mem;\n    }\n\n    public OsSwap getSwap() {\n        return swap;\n    }\n\n    public void setSwap(OsSwap swap) {\n        this.swap = swap;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/os/OsSwap.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.os;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class OsSwap {\n    @JSONField(name = \"total_in_bytes\")\n    private long totalInBytes;\n    @JSONField(name = \"free_in_bytes\")\n    private long freeInBytes;\n    @JSONField(name = \"used_in_bytes\")\n    private long usedInBytes;\n\n    public OsSwap() {\n        // pass\n    }\n\n    public long getTotalInBytes() {\n        return totalInBytes;\n    }\n\n    public void setTotalInBytes(long totalInBytes) {\n        this.totalInBytes = totalInBytes;\n    }\n\n    public long getFreeInBytes() {\n        return freeInBytes;\n    }\n\n    public void setFreeInBytes(long freeInBytes) {\n        this.freeInBytes = freeInBytes;\n    }\n\n    public long getUsedInBytes() {\n        return usedInBytes;\n    }\n\n    public void setUsedInBytes(long usedInBytes) {\n        this.usedInBytes = usedInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/process/ProcessCpu.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.process;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class ProcessCpu {\n    @JSONField(name = \"percent\")\n    private long percent;\n\n    @JSONField(name = \"total_in_millis\")\n    private long totalInMillis;\n\n    public ProcessCpu() {\n        // pass\n    }\n\n    public long getPercent() {\n        return percent;\n    }\n\n    public void setPercent(long percent) {\n        this.percent = percent;\n    }\n\n    public long getTotalInMillis() {\n        return totalInMillis;\n    }\n\n    public void setTotalInMillis(long totalInMillis) {\n        this.totalInMillis = totalInMillis;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/process/ProcessMem.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.process;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class ProcessMem {\n    @JSONField(name = \"total_virtual_in_bytes\")\n    private long totalVirtualInBytes;\n\n    public ProcessMem() {\n        // pass\n    }\n\n    public long getTotalVirtualInBytes() {\n        return totalVirtualInBytes;\n    }\n\n    public void setTotalVirtualInBytes(long totalVirtualInBytes) {\n        this.totalVirtualInBytes = totalVirtualInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/process/ProcessNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.process;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class ProcessNode {\n    @JSONField(name = \"timestamp\")\n    private long timestamp;\n\n    @JSONField(name = \"open_file_descriptors\")\n    private long openFileDescriptors;\n\n    @JSONField(name = \"max_file_descriptors\")\n    private long maxFileDescriptors;\n\n    @JSONField(name = \"cpu\")\n    private ProcessCpu cpu;\n\n    @JSONField(name = \"mem\")\n    private ProcessMem mem;\n\n    public ProcessNode() {\n        // pass\n    }\n\n    public long getTimestamp() {\n        return timestamp;\n    }\n\n    public void setTimestamp(long timestamp) {\n        this.timestamp = timestamp;\n    }\n\n    public long getOpenFileDescriptors() {\n        return openFileDescriptors;\n    }\n\n    public void setOpenFileDescriptors(long openFileDescriptors) {\n        this.openFileDescriptors = openFileDescriptors;\n    }\n\n    public long getMaxFileDescriptors() {\n        return maxFileDescriptors;\n    }\n\n    public void setMaxFileDescriptors(long maxFileDescriptors) {\n        this.maxFileDescriptors = maxFileDescriptors;\n    }\n\n    public ProcessCpu getCpu() {\n        return cpu;\n    }\n\n    public void setCpu(ProcessCpu cpu) {\n        this.cpu = cpu;\n    }\n\n    public ProcessMem getMem() {\n        return mem;\n    }\n\n    public void setMem(ProcessMem mem) {\n        this.mem = mem;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/script/ScriptNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.script;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class ScriptNode {\n    @JSONField(name = \"compilations\")\n    private long compilations;\n\n    @JSONField(name = \"cache_evictions\")\n    private long cacheEvictions;\n\n    public ScriptNode() {\n        // pass\n    }\n\n    public long getCompilations() {\n        return compilations;\n    }\n\n    public void setCompilations(long compilations) {\n        this.compilations = compilations;\n    }\n\n    public long getCacheEvictions() {\n        return cacheEvictions;\n    }\n\n    public void setCacheEvictions(long cacheEvictions) {\n        this.cacheEvictions = cacheEvictions;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/threadpool/ThreadPoolNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.threadpool;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class ThreadPoolNode {\n\n    @JSONField(name = \"threads\")\n    private long threads;\n\n    @JSONField(name = \"queue\")\n    private long queue;\n\n    @JSONField(name = \"active\")\n    private long active;\n\n    @JSONField(name = \"rejected\")\n    private long rejected;\n\n    @JSONField(name = \"largest\")\n    private long largest;\n\n    @JSONField(name = \"completed\")\n    private long completed;\n\n    public ThreadPoolNode() {\n        // pass\n    }\n\n    public long getThreads() {\n        return threads;\n    }\n\n    public void setThreads(long threads) {\n        this.threads = threads;\n    }\n\n    public long getQueue() {\n        return queue;\n    }\n\n    public void setQueue(long queue) {\n        this.queue = queue;\n    }\n\n    public long getActive() {\n        return active;\n    }\n\n    public void setActive(long active) {\n        this.active = active;\n    }\n\n    public long getRejected() {\n        return rejected;\n    }\n\n    public void setRejected(long rejected) {\n        this.rejected = rejected;\n    }\n\n    public long getLargest() {\n        return largest;\n    }\n\n    public void setLargest(long largest) {\n        this.largest = largest;\n    }\n\n    public long getCompleted() {\n        return completed;\n    }\n\n    public void setCompleted(long completed) {\n        this.completed = completed;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/threadpool/ThreadPoolNodes.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.threadpool;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class ThreadPoolNodes {\n       @JSONField(name = \"bulk\")\n       private ThreadPoolNode bulk;\n\n       @JSONField(name = \"fetch_shard_started\")\n       private ThreadPoolNode fetchShardStarted;\n\n       @JSONField(name = \"fetch_shard_store\")\n       private ThreadPoolNode fetchShardStore;\n\n       @JSONField(name = \"flush\")\n       private ThreadPoolNode flush;\n\n       @JSONField(name = \"force_merge\")\n       private ThreadPoolNode forceMerge;\n\n       @JSONField(name = \"generic\")\n       private ThreadPoolNode generic;\n\n       @JSONField(name = \"get\")\n       private ThreadPoolNode get;\n\n       @JSONField(name = \"index\")\n       private ThreadPoolNode index;\n\n       @JSONField(name = \"listener\")\n       private ThreadPoolNode listener;\n\n       @JSONField(name = \"management\")\n       private ThreadPoolNode management;\n\n       @JSONField(name = \"percolate\")\n       private ThreadPoolNode percolate;\n\n       @JSONField(name = \"refresh\")\n       private ThreadPoolNode refresh;\n\n       @JSONField(name = \"search\")\n       private ThreadPoolNode search;\n\n       @JSONField(name = \"snapshot\")\n       private ThreadPoolNode snapshot;\n\n       @JSONField(name = \"suggest\")\n       private ThreadPoolNode suggest;\n\n       @JSONField(name = \"warmer\")\n       private ThreadPoolNode warmer;\n\n       public ThreadPoolNodes() {\n              // pass\n       }\n\n       public ThreadPoolNode getBulk() {\n              return bulk;\n       }\n\n       public void setBulk(ThreadPoolNode bulk) {\n              this.bulk = bulk;\n       }\n\n       public ThreadPoolNode getFetchShardStarted() {\n              return fetchShardStarted;\n       }\n\n       public void setFetchShardStarted(ThreadPoolNode fetchShardStarted) {\n              this.fetchShardStarted = fetchShardStarted;\n       }\n\n       public ThreadPoolNode getFetchShardStore() {\n              return fetchShardStore;\n       }\n\n       public void setFetchShardStore(ThreadPoolNode fetchShardStore) {\n              this.fetchShardStore = fetchShardStore;\n       }\n\n       public ThreadPoolNode getFlush() {\n              return flush;\n       }\n\n       public void setFlush(ThreadPoolNode flush) {\n              this.flush = flush;\n       }\n\n       public ThreadPoolNode getForceMerge() {\n              return forceMerge;\n       }\n\n       public void setForceMerge(ThreadPoolNode forceMerge) {\n              this.forceMerge = forceMerge;\n       }\n\n       public ThreadPoolNode getGeneric() {\n              return generic;\n       }\n\n       public void setGeneric(ThreadPoolNode generic) {\n              this.generic = generic;\n       }\n\n       public ThreadPoolNode getGet() {\n              return get;\n       }\n\n       public void setGet(ThreadPoolNode get) {\n              this.get = get;\n       }\n\n       public ThreadPoolNode getIndex() {\n              return index;\n       }\n\n       public void setIndex(ThreadPoolNode index) {\n              this.index = index;\n       }\n\n       public ThreadPoolNode getListener() {\n              return listener;\n       }\n\n       public void setListener(ThreadPoolNode listener) {\n              this.listener = listener;\n       }\n\n       public ThreadPoolNode getManagement() {\n              return management;\n       }\n\n       public void setManagement(ThreadPoolNode management) {\n              this.management = management;\n       }\n\n       public ThreadPoolNode getPercolate() {\n              return percolate;\n       }\n\n       public void setPercolate(ThreadPoolNode percolate) {\n              this.percolate = percolate;\n       }\n\n       public ThreadPoolNode getRefresh() {\n              return refresh;\n       }\n\n       public void setRefresh(ThreadPoolNode refresh) {\n              this.refresh = refresh;\n       }\n\n       public ThreadPoolNode getSearch() {\n              return search;\n       }\n\n       public void setSearch(ThreadPoolNode search) {\n              this.search = search;\n       }\n\n       public ThreadPoolNode getSnapshot() {\n              return snapshot;\n       }\n\n       public void setSnapshot(ThreadPoolNode snapshot) {\n              this.snapshot = snapshot;\n       }\n\n       public ThreadPoolNode getSuggest() {\n              return suggest;\n       }\n\n       public void setSuggest(ThreadPoolNode suggest) {\n              this.suggest = suggest;\n       }\n\n       public ThreadPoolNode getWarmer() {\n              return warmer;\n       }\n\n       public void setWarmer(ThreadPoolNode warmer) {\n              this.warmer = warmer;\n       }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/model/transport/TransportNode.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.model.transport;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\npublic class TransportNode {\n    @JSONField(name = \"server_open\")\n    private long serverOpen;\n\n    @JSONField(name = \"rx_count\")\n    private long rxCount;\n\n    @JSONField(name = \"rx_size_in_bytes\")\n    private long rxSizeInBytes;\n\n    @JSONField(name = \"tx_count\")\n    private long txCount;\n\n    @JSONField(name = \"tx_size_in_bytes\")\n    private long txSizeInBytes;\n\n    public TransportNode() {\n        // pass\n    }\n\n    public long getServerOpen() {\n        return serverOpen;\n    }\n\n    public void setServerOpen(long serverOpen) {\n        this.serverOpen = serverOpen;\n    }\n\n    public long getRxCount() {\n        return rxCount;\n    }\n\n    public void setRxCount(long rxCount) {\n        this.rxCount = rxCount;\n    }\n\n    public long getRxSizeInBytes() {\n        return rxSizeInBytes;\n    }\n\n    public void setRxSizeInBytes(long rxSizeInBytes) {\n        this.rxSizeInBytes = rxSizeInBytes;\n    }\n\n    public long getTxCount() {\n        return txCount;\n    }\n\n    public void setTxCount(long txCount) {\n        this.txCount = txCount;\n    }\n\n    public long getTxSizeInBytes() {\n        return txSizeInBytes;\n    }\n\n    public void setTxSizeInBytes(long txSizeInBytes) {\n        this.txSizeInBytes = txSizeInBytes;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/query/clearScroll/ESQueryClearScrollResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.query.clearScroll;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\npublic class ESQueryClearScrollResponse extends ESActionResponse {\n    @Override\n    public String toString() {\n        return \"{}\";\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/query/query/ESQueryResponse.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.query.query;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.aggs.ESAggrMap;\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.hits.ESHit;\nimport com.didi.arius.gateway.elasticsearch.client.response.query.query.hits.ESHits;\n\nimport java.util.*;\n\npublic class ESQueryResponse extends ESActionResponse {\n    private static final String HITS_STR = \"hits\";\n    private static final String AGGREGATIONS_STR = \"aggregations\";\n\n    private Map<String, Object> unusedMap = new HashMap<>();\n\n    private ESHits hits;\n    private ESAggrMap aggs;\n\n\n    public ESQueryResponse() {}\n    public ESQueryResponse(JSONObject root, Class clazz) {\n        if(root==null) {\n            return;\n        }\n\n        for(Map.Entry<String,Object> entry : root.entrySet()) {\n            String key = entry.getKey();\n            if(HITS_STR.equalsIgnoreCase(key)) {\n                hits = new ESHits((JSONObject) root.get(key), clazz);\n\n            } else if(AGGREGATIONS_STR.equalsIgnoreCase(key)) {\n                aggs = new ESAggrMap((JSONObject) root.get(key));\n\n            } else {\n                unusedMap.put(key, root.get(key));\n            }\n        }\n    }\n\n\n\n    public Map<String, Object> getUnusedMap() {\n        return unusedMap;\n    }\n\n    public void setUnusedMap(Map<String, Object> unusedMap) {\n        this.unusedMap = unusedMap;\n    }\n\n\n    public ESHits getHits() {\n        return hits;\n    }\n\n    public void setHits(ESHits hits) {\n        this.hits = hits;\n    }\n\n    public ESAggrMap getAggs() {\n        return aggs;\n    }\n\n    public void setAggs(ESAggrMap aggs) {\n        this.aggs = aggs;\n    }\n\n\n    public boolean isEmptyHits() {\n        boolean res = false;\n        if (this.getHits() == null || this.getHits().isEmpty()) {\n            res = true;\n        }\n\n        return res;\n    }\n\n    public Object getFirstHit() {\n        if (isEmptyHits()) {\n            return null;\n        }\n        return hits.getHits().get(0).getSource();\n    }\n\n    public List<Object> getSourceList() {\n        if(isEmptyHits()) {\n            return Collections.emptyList();\n        }\n\n        List<Object> ret = new ArrayList<>();\n        for(ESHit hit : hits.getHits()) {\n            ret.add(hit.getSource());\n        }\n        return ret;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n\n        for(Map.Entry<String,Object> entry : unusedMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue());\n        }\n\n        if(hits!=null) {\n            root.put(HITS_STR, hits.toJson());\n        }\n\n        if(aggs!=null) {\n            root.put(AGGREGATIONS_STR, aggs.toJson());\n        }\n\n        return root;\n    }\n\n\n    public static ESQueryResponse parserResponse(String str, Class clazz) {\n        JSONObject root = JSON.parseObject(str);\n        return new ESQueryResponse(root, clazz);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/query/query/aggs/ESAggr.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.query.query.aggs;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class ESAggr {\n    private Map<String, Object> unusedMap = new HashMap<>();\n\n\n    private static final String BUCKETS_STR = \"buckets\";\n    private List<ESBucket> bucketList = null;\n\n    public ESAggr(JSONObject root) {\n        if(root==null) {\n           return;\n        }\n\n\n        for(Map.Entry<String,Object> entry : root.entrySet()) {\n            String key = entry.getKey();\n            if(BUCKETS_STR.equalsIgnoreCase(key)) {\n                bucketList = new ArrayList<>();\n\n                JSONArray array = root.getJSONArray(key);\n                for(Object obj : array) {\n                    JSONObject jsonObject = (JSONObject) obj;\n\n                    bucketList.add(new ESBucket(jsonObject));\n                }\n\n            } else {\n                unusedMap.put(key, root.get(key));\n            }\n        }\n    }\n\n\n    public Map<String, Object> getUnusedMap() {\n        return unusedMap;\n    }\n\n    public void setUnusedMap(Map<String, Object> unusedMap) {\n        this.unusedMap = unusedMap;\n    }\n\n    public List<ESBucket> getBucketList() {\n        return bucketList;\n    }\n\n    public void setBucketList(List<ESBucket> bucketList) {\n        this.bucketList = bucketList;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n\n        for(Map.Entry<String,Object> entry : unusedMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue());\n        }\n\n\n        if(bucketList!=null) {\n            JSONArray array = new JSONArray();\n            for(ESBucket bucket : bucketList) {\n                array.add(bucket.toJson());\n            }\n\n            root.put(BUCKETS_STR, array);\n        }\n\n        return root;\n    }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/query/query/aggs/ESAggrMap.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.query.query.aggs;\n\nimport com.alibaba.fastjson.JSONObject;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ESAggrMap {\n    private Map<String, ESAggr> esAggrMap = new HashMap<>();\n\n    public ESAggrMap(JSONObject root) {\n       if(root==null) {\n           return;\n       }\n\n        for(Map.Entry<String,Object> entry : root.entrySet()) {\n            String key = entry.getKey();\n           esAggrMap.put(key, new ESAggr((JSONObject) root.get(key)));\n        }\n    }\n\n\n    public Map<String, ESAggr> getEsAggrMap() {\n        return esAggrMap;\n    }\n\n    public void setEsAggrMap(Map<String, ESAggr> esAggrMap) {\n        this.esAggrMap = esAggrMap;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n\n        for(Map.Entry<String, ESAggr> entry : esAggrMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue().toJson());\n        }\n\n        return root;\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/query/query/aggs/ESBucket.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.query.query.aggs;\n\nimport com.alibaba.fastjson.JSONObject;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ESBucket {\n    private Map<String, Object> unusedMap = new HashMap<>();\n    private Map<String, ESAggr> aggrMap = new HashMap<>();\n\n\n    public ESBucket() {}\n    public ESBucket(JSONObject root) {\n        if(root==null) {\n            return;\n        }\n\n        for(Map.Entry<String,Object> entry : root.entrySet()) {\n            String key = entry.getKey();\n            Object obj = entry.getValue();\n\n            if(obj instanceof JSONObject) {\n                aggrMap.put(key, new ESAggr((JSONObject) obj));\n            } else {\n                unusedMap.put(key, obj);\n            }\n        }\n\n    }\n\n    public Map<String, Object> getUnusedMap() {\n        return unusedMap;\n    }\n\n    public void setUnusedMap(Map<String, Object> unusedMap) {\n        this.unusedMap = unusedMap;\n    }\n\n    public Map<String, ESAggr> getAggrMap() {\n        return aggrMap;\n    }\n\n    public void setAggrMap(Map<String, ESAggr> aggrMap) {\n        this.aggrMap = aggrMap;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n\n\n        for(Map.Entry<String,Object> entry : unusedMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue());\n        }\n\n\n        for(Map.Entry<String, ESAggr> entry : aggrMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue().toJson());\n        }\n\n        return root;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/query/query/hits/ESHit.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.query.query.hits;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ESHit {\n    private Map<String, Object> unusedMap = new HashMap<>();\n\n    private static final String SOURCE_STR = \"_source\";\n    private Object source;\n\n    public ESHit() { }\n    public ESHit(JSONObject root, Class clazz) {\n        if(root==null) {\n            return;\n        }\n\n        for(Map.Entry<String,Object> entry : root.entrySet()) {\n            String key = entry.getKey();\n            if(SOURCE_STR.equalsIgnoreCase(key)) {\n                if(clazz==null) {\n                    source = root.get(key);\n                } else {\n                    source = JSON.toJavaObject((JSON) root.get(key), clazz);\n                }\n            } else {\n                unusedMap.put(key, root.get(key));\n            }\n        }\n\n    }\n\n\n    public Map<String, Object> getUnusedMap() {\n        return unusedMap;\n    }\n\n    public void setUnusedMap(Map<String, Object> unusedMap) {\n        this.unusedMap = unusedMap;\n    }\n\n    public Object getSource() {\n        return source;\n    }\n\n    public void setSource(Object source) {\n        this.source = source;\n    }\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n        for(Map.Entry<String,Object> entry : unusedMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue());\n        }\n\n        if(source instanceof  JSON) {\n            root.put(SOURCE_STR, source);\n        } else {\n            root.put(SOURCE_STR, JSON.parseObject(JSON.toJSONString(source)));\n        }\n\n        return root;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/query/query/hits/ESHits.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.query.query.hits;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class ESHits {\n    private Map<String, Object> unusedMap = new HashMap<>();\n\n    private static final String HITS_STR = \"hits\";\n    private List<ESHit> hits;\n\n\n    public ESHits() { }\n    public ESHits(JSONObject root, Class clazz) {\n        if (root == null) {\n            return;\n        }\n\n        for (Map.Entry<String,Object> entry : root.entrySet()) {\n            String key = entry.getKey();\n            if (HITS_STR.equalsIgnoreCase(key)) {\n                JSONArray array = (JSONArray) root.get(HITS_STR);\n                hits= new ArrayList<>();\n\n                for(Object obj : array) {\n                    hits.add(new ESHit((JSONObject) obj, clazz));\n                }\n\n            } else {\n                unusedMap.put(key, root.get(key));\n            }\n        }\n    }\n\n\n    public Map<String, Object> getUnusedMap() {\n        return unusedMap;\n    }\n\n    public void setUnusedMap(Map<String, Object> unusedMap) {\n        this.unusedMap = unusedMap;\n    }\n\n    public List<ESHit> getHits() {\n        return hits;\n    }\n\n    public void setHits(List<ESHit> hits) {\n        this.hits = hits;\n    }\n\n    public boolean isEmpty() {\n        boolean res = false;\n        if (hits == null || hits.isEmpty()) {\n            res = true;\n        }\n        return res;\n    }\n\n\n    @Override\n    public String toString() {\n        return toJson().toJSONString();\n    }\n\n\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n        for(Map.Entry<String,Object> entry : unusedMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue());\n        }\n\n\n        if(hits!=null) {\n            JSONArray array = new JSONArray();\n            for(ESHit hit : hits) {\n                array.add(hit.toJson());\n            }\n            root.put(HITS_STR, array);\n        }\n\n        return root;\n    }\n}\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/setting/common/MappingConfig.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.setting.common;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.type.ESVersion;\n\nimport java.util.*;\n\npublic class MappingConfig {\n    private Map<String, TypeConfig> mapping = new HashMap<>();\n\n    public MappingConfig(JSONObject root) throws Exception {\n        if(root == null) {\n            throw new Exception(\"root is null\");\n        }\n\n        for(String key : root.keySet()) {\n            mapping.put(key, new TypeConfig(root.getJSONObject(key)));\n        }\n    }\n\n\n    public boolean isEmpty() {\n        boolean res = false;\n        if(mapping==null || mapping.size()==0) {\n            res = true;\n        }\n        return res;\n    }\n\n    public Map<String, TypeConfig> getMapping() {\n        return mapping;\n    }\n\n\n\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n\n        for (Map.Entry<String, TypeConfig> entry : mapping.entrySet()) {\n            root.put(entry.getKey(), entry.getValue().toJson());\n        }\n\n        return root;\n    }\n\n    public JSONObject toJson(ESVersion version) {\n        JSONObject root = new JSONObject();\n\n        for(Map.Entry<String,TypeConfig> entry : mapping.entrySet()) {\n            root.put(entry.getKey(), entry.getValue().toJson(version));\n        }\n\n        return root;\n    }\n\n\n\n    public void addField(String typeName, String field, TypeDefine typeDefine) {\n        if(!mapping.containsKey(typeName)) {\n            mapping.put(typeName, new TypeConfig());\n        }\n\n        mapping.get(typeName).addField(field, typeDefine);\n    }\n\n    public void deleteField(String typeName, String fieldName) {\n        if(!mapping.containsKey(typeName)) {\n            return;\n        }\n\n        mapping.get(typeName).deleteField(fieldName);\n    }\n\n    /**\n     * 判断字段是否存在\n     *\n     * @param fieldName\n     * @return\n     */\n    public boolean isFieldExist(String fieldName) {\n        for(Map.Entry<String,TypeConfig> entry : mapping.entrySet()) {\n            if (entry.getValue().isFieldExists(fieldName)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public void addType(String typeName, Map<String, Object> pro) {\n        if(!mapping.containsKey(typeName)) {\n            mapping.put(typeName, new TypeConfig());\n        }\n\n        mapping.get(typeName).addProperties(pro);\n    }\n\n\n\n    public Map<String/*typeName*/, Map<String/*field*/, TypeDefine>> getTypeDefines() {\n        Map<String, Map<String, TypeDefine>> ret = new HashMap<>();\n\n        for(Map.Entry<String,TypeConfig> entry : mapping.entrySet()) {\n            Map m = entry.getValue().getTypeDefine();\n            if(m.size()>0) {\n                ret.put(entry.getKey(), m);\n            }\n        }\n\n        return ret;\n    }\n\n\n    public Map<String/*field*/, List<TypeDefine>> getTypes() {\n        Map<String, List<TypeDefine>> ret = new HashMap<>();\n\n        for(Map.Entry<String,TypeConfig> entry : mapping.entrySet()) {\n            Map<String, TypeDefine> m = entry.getValue().getTypeDefine();\n\n            for(Map.Entry<String,TypeDefine> entry1 : m.entrySet()) {\n                String field = entry1.getKey();\n                if(!ret.containsKey(field)) {\n                    ret.put(field, new ArrayList<>());\n                }\n\n                ret.get(field).add(m.get(field));\n            }\n        }\n\n        return ret;\n    }\n\n    // 判断mapping只是否有字段在多处使用不同的定义\n    public Set<String> checkMapping() {\n        Map<String, List<TypeDefine>> m = getTypes();\n\n        Set<String> ret = new HashSet<>();\n        for(Map.Entry<String, List<TypeDefine>> entry : m.entrySet()) {\n            String field = entry.getKey();\n            List<TypeDefine> l = m.get(field);\n            if(l==null || l.size()<=1) {\n                continue;\n            }\n\n            TypeDefine typeDefine = l.get(0);\n            for(int i=1; i<l.size(); i++) {\n                if(!typeDefine.equals(l.get(i))) {\n                    ret.add(field);\n                    break;\n                }\n            }\n        }\n\n        return ret;\n    }\n\n    public Set<String> diffTypeDefine(MappingConfig mappings) {\n        Set<String> ret = new HashSet<>();\n        if (mappings == null) {\n            return ret;\n        }\n\n        Map<String, List<TypeDefine>> m1 = this.getTypes();\n        Map<String, List<TypeDefine>> m2 = mappings.getTypes();\n\n\n        for (Map.Entry<String, List<TypeDefine>> entry : m1.entrySet()) {\n            String field = entry.getKey();\n            if (!m2.containsKey(field)) {\n                continue;\n            }\n\n            List<TypeDefine> l1 = m1.get(field);\n            List<TypeDefine> l2 = m2.get(field);\n            for (TypeDefine td1 : l1) {\n                for (TypeDefine td2 : l2) {\n                    if (!td1.equals(td2)) {\n                        ret.add(field);\n                        break;\n                    }\n                }\n            }\n        }\n\n        return ret;\n    }\n\n    public MappingConfig deepCopy() throws Exception {\n        JSONObject jsonObject = this.toJson();\n        return new MappingConfig(jsonObject);\n    }\n\n    private static final String DEFAULT_TYPE_STR = \"_default_\";\n    public void mergeDefault(MappingConfig mappings) {\n        TypeConfig typeMapping = mappings.getMapping().get(DEFAULT_TYPE_STR);\n        if(typeMapping!=null) {\n            this.mapping.put(DEFAULT_TYPE_STR, typeMapping);\n        }\n    }\n\n    public boolean haveDefault() {\n        return mapping.containsKey(DEFAULT_TYPE_STR);\n    }\n\n    public void removeDefault() {\n        mapping.remove(DEFAULT_TYPE_STR);\n    }\n\n    public boolean isJustDefault() {\n        boolean res = false;\n        if(mapping.size()==0) {\n            res = true;\n        }\n\n        if(mapping.size()==1 && mapping.containsKey(DEFAULT_TYPE_STR)) {\n            res = true;\n        }\n\n        return res;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/setting/common/TypeConfig.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.setting.common;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.type.ESVersion;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class TypeConfig {\n    private Map<String, Object> notUsedMap = new HashMap<>();\n\n    private TypeProperties properties = null;\n\n\n    public TypeConfig() {}\n    public TypeConfig(JSONObject root) throws Exception {\n        if (root == null) {\n            throw new Exception(\"root is null\");\n        }\n\n        for (Map.Entry<String,Object> entry : root.entrySet()) {\n            String key = entry.getKey();\n            if (key.equalsIgnoreCase(TypeProperties.PROPERTIES_STR)) {\n                properties = new TypeProperties(root.getJSONObject(key));\n            } else {\n                notUsedMap.put(key, root.get(key));\n            }\n        }\n    }\n\n    public void addProperties(Map<String, Object> m) {\n        notUsedMap.putAll(m);\n    }\n\n    public void addField(String field, TypeDefine define) {\n        if(properties==null) {\n            properties = new TypeProperties();\n        }\n\n        properties.addField(field, define);\n    }\n\n    public void deleteField(String fieldName) {\n        if (properties != null) {\n            properties.deleteField(fieldName);\n        }\n    }\n\n    public boolean isFieldExists(String fieldName) {\n        if (properties != null) {\n            Map<String, TypeDefine> fieldNameMap = properties.getTypeDefine();\n            for (String field : fieldNameMap.keySet()) {\n                if (field.equals(fieldName)) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n\n        for (Map.Entry<String,Object> entry : notUsedMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue());\n        }\n\n        if (properties != null) {\n            root.put(TypeProperties.PROPERTIES_STR, properties.toJson());\n        }\n\n        return root;\n    }\n\n    public JSONObject toJson(ESVersion version) {\n        JSONObject root = new JSONObject();\n\n        for (Map.Entry<String,Object> entry : notUsedMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue());\n        }\n\n        if (properties != null) {\n            root.put(TypeProperties.PROPERTIES_STR, properties.toJson(version));\n        }\n\n        return root;\n    }\n\n\n    public Map<String, TypeDefine> getTypeDefine() {\n        if (properties != null) {\n            return properties.getTypeDefine();\n        } else {\n            return new HashMap<>();\n        }\n    }\n\n    public Map<String, Object> getNotUsedMap() {\n        return notUsedMap;\n    }\n\n    public void setNotUsedMap(Map<String, Object> notUsedMap) {\n        this.notUsedMap = notUsedMap;\n    }\n\n    public TypeProperties getProperties() {\n        return properties;\n    }\n\n    public void setProperties(TypeProperties properties) {\n        this.properties = properties;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/setting/common/TypeDefine.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.setting.common;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.type.ESVersion;\n\npublic class TypeDefine {\n    private JSONObject define;\n\n    public TypeDefine(JSONObject root) {\n        this.define = root;\n    }\n\n    public JSONObject toJson() {\n        return define;\n    }\n\n    public JSONObject toJson(ESVersion version) {\n        return TypeDefineOperator.toJson(define, version);\n    }\n\n    public void setDefine(JSONObject define) {\n        this.define = define;\n    }\n\n    public JSONObject getDefine() {\n        return define;\n    }\n\n    /**\n     * 是否需要忽略mapping优化\n     * @return\n     */\n    public boolean isNotOptimze() {\n        return TypeDefineOperator.isNotOptimze(define);\n    }\n\n    /**\n     * 获取类型\n     *\n     * @return\n     */\n    public String getType() {\n        return TypeDefineOperator.getType(define);\n    }\n\n    public boolean isIndexOff() {\n        return TypeDefineOperator.isIndexOff(define);\n    }\n\n    /**\n     * 设置成不检索\n     *\n     */\n    public void setIndexOff() {\n        TypeDefineOperator.setIndexOff(define);\n    }\n\n    /**\n     * 设置成检索\n     *\n     */\n    public void setIndexOn() {\n        TypeDefineOperator.setIndexOn(define);\n    }\n\n    public boolean isDocValuesOff() {\n        return TypeDefineOperator.isDocValuesOff(define);\n    }\n\n    /**\n     * 设置成不支持排序\n     */\n    public void setDocValuesOff() {\n        TypeDefineOperator.setDocValuesOff(define);\n    }\n\n    /**\n     * 设置成支持排序\n     */\n    public void setDocValuesOn() {\n        TypeDefineOperator.setDocValuesOn(define);\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        return TypeDefineOperator.isEquals(define, obj);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/setting/common/TypeDefineOperator.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.setting.common;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.type.ESVersion;\nimport org.apache.commons.lang3.StringUtils;\n\n/**\n * TypeDefine操作类\n *\n * 主要是完成高低版本兼容\n *\n * Created by d06679 on 2019/3/6.\n */\npublic class TypeDefineOperator {\n\n    private static final String TYPE_STR                       = \"type\";\n\n    private static final String NESTED_STR                     = \"nested\";\n\n    private static final String OBJECT_STR                     = \"object\";\n\n    private static final String FIELDS_STR                     = \"fields\";\n\n    private static final String RAW_STR                        = \"raw\";\n\n    private static final String INDEX_STR                      = \"index\";\n\n    private static final String DOC_VALUES_STR                 = \"doc_values\";\n\n    private static final String IGNORE_ABOVE_STR               = \"ignore_above\";\n\n    private static final String ES_HIGH_TYPE_TEXT_STR          = \"text\";\n\n    private static final String ES_HIGH_TYPE_KEYWORD_STR       = \"keyword\";\n\n    private static final String ES_LOW_TYPE_STRING_STR         = \"string\";\n\n    private static final String ES_LOW_STRING_NOT_ANALYZED_STR = \"not_analyzed\";\n\n    private static final String ES_LOW_STRING_FIELDDATA_STR    = \"fielddata\";\n\n    private static final String FALSE = \"false\";\n\n    private TypeDefineOperator() {\n\n    }\n\n    /**\n     * 是否需要忽略mapping优化\n     * @return\n     */\n    public static boolean isNotOptimze(JSONObject define) {\n        if (define.containsKey(TYPE_STR)) {\n            String v = define.getString(TYPE_STR);\n            if (NESTED_STR.equalsIgnoreCase(v) || OBJECT_STR.equalsIgnoreCase(v)) {\n                return true;\n            }\n        } else if (define.containsKey(FIELDS_STR)) {\n            //                    \\\"artifact\\\": {\\n\"\n            //                              \\\"type\\\": \\\"string\\\",\\n\"\n            //                              \\\"fields\\\": {\\n\"\n            //                                \\\"raw\\\": {\\n\"\n            //                                  \\\"ignore_above\\\": 1024,\\n\"\n            //                                  \\\"index\\\": \\\"not_analyzed\\\",\\n\"\n            //                                   \\\"type\\\": \\\"string\\\"\\n\"\n            //                                }\\n\"\n            //                              }\\n\"\n            if (define.get(FIELDS_STR) instanceof JSONObject) {\n                JSONObject fieldsObj = define.getJSONObject(FIELDS_STR);\n                if (fieldsObj.containsKey(RAW_STR)) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * 获取类型\n     *\n     * @return\n     */\n    public static String getType(JSONObject define) {\n        if (define != null && define.containsKey(TYPE_STR)) {\n            return define.getString(TYPE_STR);\n        }\n\n        return null;\n    }\n\n    public static boolean isHighVersionString(JSONObject define) {\n        String type = getType(define);\n        return !StringUtils.isBlank(type)\n               && (type.equals(ES_HIGH_TYPE_TEXT_STR) || type.equals(ES_HIGH_TYPE_KEYWORD_STR));\n    }\n\n    public static boolean isLowVersionString(JSONObject define) {\n        String type = getType(define);\n        return !StringUtils.isBlank(type) && type.equals(ES_LOW_TYPE_STRING_STR);\n    }\n\n    public static boolean isIndexOff(JSONObject define) {\n\n        if (isHighVersionString(define)) {\n            throw new RuntimeException(\"illegal operator\");\n        } else {\n            if (\"no\".equalsIgnoreCase(define.getString(INDEX_STR))\n                && \"true\".equalsIgnoreCase(define.getString(DOC_VALUES_STR))) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * 设置成不检索\n     *\n     */\n    public static void setIndexOff(JSONObject define) {\n        if (isHighVersionString(define)) {\n            define.put(INDEX_STR, FALSE);\n        } else {\n            define.put(INDEX_STR, \"no\");\n        }\n    }\n\n    /**\n     * 设置成检索\n     *\n     */\n    public static void setIndexOn(JSONObject define) {\n        if (isHighVersionString(define)) {\n            define.remove(INDEX_STR);\n            define.put(TYPE_STR, ES_HIGH_TYPE_KEYWORD_STR);\n        } else {\n            define.put(TYPE_STR, ES_LOW_STRING_NOT_ANALYZED_STR);\n        }\n    }\n\n    public static boolean isDocValuesOff(JSONObject define) {\n        if (isHighVersionString(define)) {\n            if (FALSE.equalsIgnoreCase(define.getString(INDEX_STR))\n                && !\"true\".equalsIgnoreCase(define.getString(DOC_VALUES_STR))) {\n                return true;\n            }\n            throw new RuntimeException(\"illegal operator\");\n        } else {\n            if (\"no\".equalsIgnoreCase(define.getString(INDEX_STR))\n                && !\"true\".equalsIgnoreCase(define.getString(DOC_VALUES_STR))) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * 设置成不支持排序\n     */\n    public static void setDocValuesOff(JSONObject define) {\n        define.put(DOC_VALUES_STR, false);\n    }\n\n    /**\n     * 设置成支持排序\n     */\n    public static void setDocValuesOn(JSONObject define) {\n        define.put(DOC_VALUES_STR, true);\n    }\n\n    public static boolean isEquals(JSONObject define, Object obj) {\n        if (!(obj instanceof TypeDefine)) {\n            return false;\n        }\n\n        TypeDefine t = (TypeDefine) obj;\n\n        JSONObject j1 = (JSONObject) define.clone();\n        JSONObject j2 = (JSONObject) t.getDefine().clone();\n\n        j1.remove(IGNORE_ABOVE_STR);\n        j2.remove(IGNORE_ABOVE_STR);\n\n        return j1.equals(j2);\n    }\n\n    public static JSONObject toJson(JSONObject define, ESVersion version) {\n\n        if (version == ESVersion.ES651) {\n\n            if (isLowVersionString(define)) {\n                // 处理String\n                if (define.containsKey(INDEX_STR)) {\n                    dealString(define);\n                } else {\n                    define.put(TYPE_STR, ES_HIGH_TYPE_TEXT_STR);\n                }\n            } else {\n                // 处理其他字段\n                if (define.containsKey(INDEX_STR) && \"no\".equals(define.get(INDEX_STR))) {\n                    define.put(INDEX_STR, FALSE);\n                }\n            }\n\n            // 处理fielddata配置\n            define.remove(ES_LOW_STRING_FIELDDATA_STR);\n\n        }\n\n        return define;\n    }\n\n    private static void dealString(JSONObject define) {\n        if (ES_LOW_STRING_NOT_ANALYZED_STR.equals(define.get(INDEX_STR))) {\n            // keyword\n            define.remove(INDEX_STR);\n            define.put(TYPE_STR, ES_HIGH_TYPE_KEYWORD_STR);\n        } else if (\"no\".equals(define.get(INDEX_STR))) {\n            // keyword and not index\n            define.put(INDEX_STR, FALSE);\n            define.put(TYPE_STR, ES_HIGH_TYPE_KEYWORD_STR);\n        } else {\n            define.remove(INDEX_STR);\n            define.put(TYPE_STR, ES_HIGH_TYPE_TEXT_STR);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/setting/common/TypeProperties.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.setting.common;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.type.ESVersion;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class TypeProperties {\n    public static final String PROPERTIES_STR = \"properties\";\n\n    private Map<String, TypeDefine> jsonMap = new HashMap<>();\n\n    private Map<String, TypeDefine> propertyTypeMap = new HashMap<>();\n    private Map<String, TypeProperties> propertyMap = new HashMap<>();\n\n    public TypeProperties() {}\n    public TypeProperties(JSONObject root) {\n        for(String key : root.keySet()) {\n            JSONObject obj = root.getJSONObject(key);\n\n            if(obj.containsKey(PROPERTIES_STR)) {\n                propertyMap.put(key, new TypeProperties(obj.getJSONObject(PROPERTIES_STR)));\n\n                // 处理nest本省有类型的情况\n                JSONObject o = JSON.parseObject(obj.toJSONString());\n                o.remove(PROPERTIES_STR);\n                if(o.size()>0) {\n                    propertyTypeMap.put(key, new TypeDefine(o));\n                }\n\n            } else {\n                jsonMap.put(key, new TypeDefine(obj));\n            }\n        }\n    }\n\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n\n        for(Map.Entry<String,TypeDefine> entry : jsonMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue().toJson());\n        }\n\n        for(Map.Entry<String,TypeProperties> entry : propertyMap.entrySet()) {\n            String key = entry.getKey();\n            JSONObject obj = new JSONObject();\n            obj.put(PROPERTIES_STR, propertyMap.get(key).toJson());\n            if(propertyTypeMap.containsKey(key)) {\n                obj.putAll(propertyTypeMap.get(key).toJson());\n            }\n\n            root.put(key, obj);\n        }\n\n        return root;\n    }\n\n    public JSONObject toJson(ESVersion version) {\n        JSONObject root = new JSONObject();\n\n        for (Map.Entry<String, TypeDefine> entry : jsonMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue().toJson(version));\n        }\n\n        for (Map.Entry<String,TypeProperties> entry : propertyMap.entrySet()) {\n            String key = entry.getKey();\n            JSONObject obj = new JSONObject();\n            obj.put(PROPERTIES_STR, propertyMap.get(key).toJson(version));\n            if (propertyTypeMap.containsKey(key)) {\n                obj.putAll(propertyTypeMap.get(key).toJson(version));\n            }\n\n            root.put(key, obj);\n        }\n\n        return root;\n    }\n\n\n    public Map<String, TypeDefine>  getTypeDefine() {\n        Map<String, TypeDefine> ret = new HashMap<>();\n\n        for(Map.Entry<String, TypeDefine> entry : jsonMap.entrySet()) {\n            ret.put(entry.getKey(), entry.getValue());\n        }\n\n        for(Map.Entry<String,TypeProperties> entry : propertyMap.entrySet()) {\n            String key = entry.getKey();\n            // 处理nest的情况\n            ret.put(key, new TypeDefine(new JSONObject()));\n\n            Map<String, TypeDefine> tmp = propertyMap.get(key).getTypeDefine();\n            for(Map.Entry<String, TypeDefine> entry1 : tmp.entrySet()) {\n                String k = entry1.getKey();\n                ret.put(key.trim()+\".\"+k.trim(), tmp.get(k));\n            }\n        }\n\n        return ret;\n    }\n\n\n    public void addField(String field, TypeDefine define) {\n        propertyMap.remove(field);\n        jsonMap.put(field, define);\n    }\n\n    public void deleteField(String fieldName) {\n        propertyMap.remove(fieldName);\n        jsonMap.remove(fieldName);\n    }\n\n    public Map<String, TypeDefine> getJsonMap() {\n        return jsonMap;\n    }\n\n    public void setJsonMap(Map<String, TypeDefine> jsonMap) {\n        this.jsonMap = jsonMap;\n    }\n\n    public Map<String, TypeProperties> getPropertyMap() {\n        return propertyMap;\n    }\n\n    public void setPropertyMap(Map<String, TypeProperties> propertyMap) {\n        this.propertyMap = propertyMap;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/setting/index/IndexConfig.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.setting.index;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didi.arius.gateway.elasticsearch.client.utils.JsonUtils;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class IndexConfig {\n    private static final String ALIASES_STR = \"aliases\";\n    private static final String MAPPINGS_STR = \"mappings\";\n    private static final String SETTINGS_STR = \"settings\";\n\n    private JSONObject aliases;\n    private MappingConfig mappings = null;\n    private JSONObject settings;\n    private Map<String, Object> notUsedMap = new HashMap<>();\n\n\n    public IndexConfig() {}\n\n    public IndexConfig(JSONObject root) throws Exception {\n        if(root==null) {\n            throw new Exception(\"root is null\");\n        }\n\n        for(Map.Entry<String,Object> entry : root.entrySet()) {\n            String key = entry.getKey();\n            if(key.equalsIgnoreCase(SETTINGS_STR)) {\n                settings = root.getJSONObject(key);\n\n            } else if(key.equalsIgnoreCase(ALIASES_STR)) {\n                aliases = root.getJSONObject(key);\n\n            } else if(key.equalsIgnoreCase(MAPPINGS_STR)) {\n                mappings = new MappingConfig(root.getJSONObject(key));\n\n            } else {\n                notUsedMap.put(key, root.get(key));\n            }\n        }\n    }\n\n\n    public JSONObject getAliases() {\n        return aliases;\n    }\n\n    public void setAliases(JSONObject aliases) {\n        this.aliases = aliases;\n    }\n\n    public MappingConfig getMappings() {\n        return mappings;\n    }\n\n    public void setMappings(MappingConfig mappings) {\n        this.mappings = mappings;\n    }\n\n    public Map<String, String> getSettings() {\n        return JsonUtils.flat(settings);\n    }\n\n    public void setSettings(Map<String, String> settings) {\n        this.settings = JsonUtils.reFlat(settings);\n    }\n\n    public Object getOther(String key) {\n        return notUsedMap.get(key);\n    }\n\n    public void setOther(String key, Object value) {\n        this.notUsedMap.put(key, value);\n    }\n\n\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n\n        if(settings!=null && settings.size()>0) {\n            root.put(SETTINGS_STR, settings);\n        }\n\n        if(aliases!=null && aliases.size()>0) {\n            root.put(ALIASES_STR, aliases);\n        }\n\n        if(mappings!=null && !mappings.isEmpty()) {\n            root.put(MAPPINGS_STR, mappings.toJson());\n        }\n\n        for(Map.Entry<String,Object> entry : notUsedMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue());\n        }\n\n        return root;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/setting/index/MultiIndexsConfig.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.setting.index;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.annotation.JSONField;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.common.MappingConfig;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class MultiIndexsConfig {\n    private Map<String, IndexConfig> indexConfigMap = new HashMap<>();\n\n    public MultiIndexsConfig(JSONObject root) throws Exception {\n        if(root==null) {\n            throw new Exception(\"root is null\");\n        }\n\n        for(String indexName: root.keySet()) {\n            indexConfigMap.put(indexName, new IndexConfig(root.getJSONObject(indexName)));\n        }\n    }\n\n    public JSONObject toJson() {\n        JSONObject root = new JSONObject();\n\n        for(Map.Entry<String, IndexConfig> entry : indexConfigMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue().toJson());\n        }\n\n        return root;\n    }\n\n    public Map<String, IndexConfig> getIndexConfigMap() {\n        return indexConfigMap;\n    }\n\n    public IndexConfig getIndexConfig(String index) {\n        return indexConfigMap.get(index);\n    }\n\n    @JSONField(serialize=false)\n    public MappingConfig getNewestMappings() {\n        String newestName= \"\";\n        for(String indexName : indexConfigMap.keySet()) {\n            if(newestName.compareTo(indexName)<0) {\n                newestName = indexName;\n            }\n        }\n\n        return indexConfigMap.get(newestName).getMappings();\n    }\n\n    @JSONField(serialize=false)\n    public boolean isEmpty() {\n        return indexConfigMap.isEmpty();\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/setting/template/MultiTemplatesConfig.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.setting.template;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.type.ESVersion;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.common.TypeDefine;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport java.util.*;\n\npublic class MultiTemplatesConfig {\n    private final ILog LOGGER = LogFactory.getLog(MultiTemplatesConfig.class);\n\n    private Map<String, TemplateConfig> templateConfigMap = new HashMap<>();\n\n    public MultiTemplatesConfig(JSONObject root) throws Exception {\n        if(root==null) {\n            throw new Exception(\"root is null\");\n        }\n\n        for(String key : root.keySet()) {\n            templateConfigMap.put(key, new TemplateConfig(root.getJSONObject(key)));\n        }\n    }\n\n    public JSONObject toJson(ESVersion version) {\n        JSONObject root = new JSONObject();\n\n        for(Map.Entry<String, TemplateConfig> entry : templateConfigMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue().toJson(version));\n        }\n\n        return root;\n    }\n\n    public Map<String, TemplateConfig> getTemplateConfigMap() {\n        return templateConfigMap;\n    }\n\n    public TemplateConfig getSingleConfig() {\n        for(Map.Entry<String, TemplateConfig> entry : templateConfigMap.entrySet()) {\n            return entry.getValue();\n        }\n\n        return null;\n    }\n\n    public void addTemplateConfig(String name, TemplateConfig config) {\n        templateConfigMap.put(name, config);\n    }\n\n    // 检测模版和base是否一直\n    private static final String BASE_STR = \"base\";\n    public static final String TESTMAPPINGS = \"testMappings\";\n    public Map<String, Set<String>> checkBaseConfig(String cluster, MappingConfig testMappings) throws Exception {\n        TemplateConfig baseConfig = templateConfigMap.get(BASE_STR);\n        if(baseConfig == null) {\n            LOGGER.error(\"not have baesConfig, clusterName:{}\", cluster);\n            return new HashMap<>();\n        }\n\n        MappingConfig baseMapping = baseConfig.getMappings();\n\n        Map<String, Set<String>> ret = new HashMap<>();\n        for(Map.Entry<String,TemplateConfig> entry : templateConfigMap.entrySet()) {\n            String template = entry.getKey();\n            if(template.equalsIgnoreCase(BASE_STR)) {\n                continue;\n            }\n\n            MappingConfig mappings = templateConfigMap.get(template).getMappings();\n\n            Set<String> diffField = baseMapping.diffTypeDefine(mappings);\n            if(diffField!=null && !diffField.isEmpty()) {\n                ret.put(template, diffField);\n            }\n        }\n\n        if(testMappings!=null) {\n            Set<String> diffField = baseMapping.diffTypeDefine(testMappings);\n            if (diffField != null && !diffField.isEmpty()) {\n                ret.put(TESTMAPPINGS, diffField);\n            }\n        }\n\n        return ret;\n    }\n\n    // 检测每一个模版的mapping中的字段的定义是否一致\n    public Map<String, Set<String>> checkMapping() {\n        Map<String, Set<String>> ret = new HashMap<>();\n\n        for(Map.Entry<String, TemplateConfig> entry : templateConfigMap.entrySet()) {\n            String template = entry.getKey();\n            Set<String> fields = templateConfigMap.get(template).getMappings().checkMapping();\n            if(fields!=null && !fields.isEmpty()) {\n                ret.put(template, fields);\n            }\n        }\n\n        return ret;\n    }\n\n\n    // 检测每一个模版的mapping中的字段的定义是否一致\n    public Map<String, Set<String>> xiaoyi() {\n        Map<String, Set<String>> ret = new HashMap<>();\n\n        for(Map.Entry<String, TemplateConfig> entry : templateConfigMap.entrySet()) {\n            String template = entry.getKey();\n            Map<String, List<TypeDefine>> m = templateConfigMap.get(template).getTypes();\n            Set<String> f = new HashSet<>();\n            for(Map.Entry<String, List<TypeDefine>> entry1 : m.entrySet()) {\n                String name = entry1.getKey();\n                if(name.startsWith(\"json\")) {\n                    Set<String> info = new HashSet<>();\n                    for(TypeDefine typeDefine : m.get(name)) {\n                        info.add(JSON.toJSONString(typeDefine));\n                    }\n\n                    f.add(name + \"_\" + JSON.toJSON(info));\n                }\n            }\n\n            if(!f.isEmpty()) {\n                ret.put(template, f);\n            }\n        }\n\n        return ret;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/response/setting/template/TemplateConfig.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.response.setting.template;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.elasticsearch.client.model.type.ESVersion;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.common.MappingConfig;\nimport com.didi.arius.gateway.elasticsearch.client.response.setting.common.TypeDefine;\nimport com.didi.arius.gateway.elasticsearch.client.utils.JsonUtils;\nimport com.google.common.collect.Sets;\n\nimport java.util.*;\n\npublic class TemplateConfig {\n    private static final String ORDER_STR = \"order\";\n    private static final String SETTINGS_STR = \"settings\";\n    private static final String ALIASES_STR = \"aliases\";\n    private static final String MAPPINGS_STR = \"mappings\";\n    private static final String TEMPLATE_STR = \"template\";\n    private static final String INDEX_PATTERNS_STR = \"index_patterns\";\n\n    private Set<String> template = new HashSet<>();\n    private Long order;\n    private JSONObject setttings;\n    private JSONObject aliases;\n    private MappingConfig mappings = null;\n    private Map<String, Object> notUsedMap = new HashMap<>();\n\n    public TemplateConfig() {}\n    public TemplateConfig(JSONObject root) throws Exception {\n        if(root==null) {\n            throw new Exception(\"root is null\");\n        }\n\n        for(Map.Entry<String,Object> entry : root.entrySet()) {\n            String key = entry.getKey();\n            if(key.equalsIgnoreCase(TEMPLATE_STR)) {\n                template.add((String) root.get(key));\n\n            } else if(key.equalsIgnoreCase(INDEX_PATTERNS_STR)) {\n                dealIndexPattern(root, key);\n\n            } else if(key.equalsIgnoreCase(ORDER_STR)) {\n                order = root.getLong(key);\n\n            } else if(key.equalsIgnoreCase(SETTINGS_STR)) {\n                setttings = root.getJSONObject(key);\n\n            } else if(key.equalsIgnoreCase(ALIASES_STR)) {\n                aliases = root.getJSONObject(key);\n\n            } else if(key.equalsIgnoreCase(MAPPINGS_STR)) {\n                mappings = new MappingConfig(root.getJSONObject(key));\n\n            } else {\n                notUsedMap.put(key, root.get(key));\n            }\n        }\n\n        if(mappings==null) {\n            throw new Exception(\"not have mapping, config:\" + root.toJSONString());\n        }\n    }\n\n    private void dealIndexPattern(JSONObject root, String key) {\n        Object obj = root.get(key);\n        if(obj instanceof JSONArray) {\n            for(Object o : (JSONArray)obj) {\n                template.add(o.toString());\n            }\n        } else {\n            template.add(obj.toString());\n        }\n    }\n\n    public String getTemplate() {\n        for(String k : template) {\n            return k;\n        }\n\n        return null;\n    }\n\n    public Set<String> getTemplates() {\n        return template;\n    }\n\n\n    public void setTemplate(String template) {\n        this.template.clear();\n        this.template.add(template);\n    }\n\n    public void addTemplate(String template) {\n        this.template.add(template);\n    }\n\n    public Long getOrder() {\n        return order;\n    }\n\n    public void setOrder(Long order) {\n        this.order = order;\n    }\n\n    public Map<String, String> getSetttings() {\n        return JsonUtils.flat(setttings);\n    }\n\n    public void setSetttings(Map<String, String> setttings) {\n        this.setttings = JsonUtils.reFlat(setttings);\n    }\n\n    public JSONObject getAliases() {\n        return aliases;\n    }\n\n    public void setAliases(JSONObject aliases) {\n        this.aliases = aliases;\n    }\n\n    public void setMappings(MappingConfig mappings) {\n        this.mappings = mappings;\n    }\n\n    public MappingConfig getMappings() {\n        return mappings;\n    }\n\n    public void addOther(String key, Object value) {\n        notUsedMap.put(key, value);\n    }\n\n    public void getOther(String key) {\n        notUsedMap.get(key);\n    }\n\n    public JSONObject toJson(ESVersion version) {\n        if(version==null) {\n            version=ESVersion.ES233;\n        }\n\n        JSONObject root = new JSONObject();\n\n        if(template!=null && !template.isEmpty()) {\n            root.put(TEMPLATE_STR, genTemplateByVersion(template, version));\n        }\n\n        if(order!=null) {\n            root.put(ORDER_STR, order);\n        }\n\n        if(setttings!=null) {\n            root.put(SETTINGS_STR, setttings);\n        }\n\n        if(aliases!=null) {\n            root.put(ALIASES_STR, aliases);\n        }\n\n        if(mappings!=null && !mappings.isEmpty()) {\n            root.put(MAPPINGS_STR, mappings.toJson(version));\n        }\n\n        for(Map.Entry<String,Object> entry : notUsedMap.entrySet()) {\n            root.put(entry.getKey(), entry.getValue());\n        }\n\n        return root;\n    }\n\n    private Object genTemplateByVersion(Set<String> template, ESVersion version) {\n        if (version == ESVersion.ES233) {\n            return getTemplate();\n        }\n\n        JSONArray array = new JSONArray();\n        for (String key : template) {\n            array.add(key);\n        }\n        return array;\n    }\n\n    public Map<String/*typeName*/, Map<String/*field*/, TypeDefine>> getTypeDefines() {\n        return mappings.getTypeDefines();\n    }\n\n    public Map<String, List<TypeDefine>> getTypes() {\n        Map<String, Map<String, TypeDefine>> tm = getTypeDefines();\n\n        Map<String, List<TypeDefine>> ret = new HashMap<>();\n        for(String key : tm.keySet()) {\n            for(String field : tm.get(key).keySet()) {\n                if(!ret.containsKey(field)) {\n                    ret.put(field, new ArrayList<>());\n                }\n\n                ret.get(field).add(tm.get(key).get(field));\n            }\n        }\n\n        return ret;\n    }\n\n    /**\n     * 获取mapping中所有字段名 fieldName,不包含type这层，由于不同type的类型必须一致\n     * @return\n     */\n    public Set<String> getFieldNames() {\n        Set<String> fieldNameSet = Sets.newLinkedHashSet();\n        Map<String/*typeName*/, Map<String/*field*/, TypeDefine>> typeFieldMap = mappings.getTypeDefines();\n        for (Map.Entry<String, Map<String, TypeDefine>> entry : typeFieldMap.entrySet()) {\n            for (Map.Entry<String, TypeDefine> typeDefineEntry : entry.getValue().entrySet()) {\n                fieldNameSet.add(typeDefineEntry.getKey());\n            }\n        }\n\n        return fieldNameSet;\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/utils/JsonUtils.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.utils;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONException;\nimport com.alibaba.fastjson.JSONObject;\nimport org.apache.commons.lang3.StringUtils;\n\npublic class JsonUtils {\n\n    public static Map<String, String> flat(JSONObject obj) {\n        Map<String, String> ret = new HashMap<>();\n\n        if(obj==null) {\n            return ret;\n        }\n\n        for(Map.Entry<String,Object> entry : obj.entrySet()) {\n            Object o = entry.getValue();\n            String key = entry.getKey();\n\n            if (o instanceof JSONObject) {\n                Map<String, String> m = flat((JSONObject) o);\n                for (Map.Entry<String,String> entry1 : m.entrySet()) {\n                    ret.put(key.replace(\".\", \"#\") + \".\" + entry1.getKey(), entry1.getValue());\n                }\n            } else {\n                ret.put(key.replace(\".\", \"#\"), o.toString());\n            }\n        }\n\n        return ret;\n    }\n\n    public static JSONObject reFlat(Map<String, String> m) {\n        JSONObject ret = new JSONObject();\n        for(Map.Entry<String,String> entry : m.entrySet()) {\n            String key = entry.getKey();\n            // 增加一个value\n            String[] subKeys = key.split(\"\\\\.\");\n            for(int i=0; i<subKeys.length; i++) {\n                subKeys[i] = subKeys[i].replace(\"#\", \".\");\n            }\n\n            JSONObject obj = ret;\n            int i;\n            for(i=0; i<subKeys.length-1; i++) {\n                String subKey = subKeys[i];\n\n                // 逐层增加\n                if(!obj.containsKey(subKey)) {\n                    obj.put(subKey, new JSONObject());\n                }\n\n                obj = obj.getJSONObject(subKey);\n            }\n\n            String value = m.get(key);\n            if(value!=null && value.startsWith(\"[\") && value.endsWith(\"]\")) {\n                // 看是否可以转化成jsonArray\n                //这里应该进行try catch否则会导致解析json中的正则失败\n                JSONArray array = null;\n                try {\n                    array = JSONArray.parseArray(value);\n                } catch (JSONException e) {\n                    //pass\n                }\n                obj.put(subKeys[i], array);\n                if(array==null) {\n                    obj.put(subKeys[i], value);\n                }\n\n            } else {\n                obj.put(subKeys[i], value);\n            }\n        }\n\n        return ret;\n    }\n\n\n    /**\n     * 将一维的kv对转化为嵌套的kv对\n     * 例如:\n     *  a.b.c:\"test\"\n     *\n     *  转化为:\n     *\n     *    {\n     *      \"a\": {\n     *          \"b\": {\n     *              \"c\": \"test\"\n     *              }\n     *          }\n     *    }\n     *\n     * @param map\n     * @return\n     */\n    public static Map<String, Object> formatMap(Map<String, Object> map) {\n        Map<String, Object> result = new HashMap<>();\n        for (Map.Entry<String,Object> entry : map.entrySet()) {\n            String longKey = entry.getKey();\n            if (longKey.contains(\".\")) {\n                String firstKey = StringUtils.substringBefore(longKey, \".\");\n                Map<String, Object> innerMap;\n                if (result.containsKey(firstKey)) {\n                    innerMap = (Map<String, Object>) result.get(firstKey);\n                } else {\n                    innerMap = new HashMap<>();\n                }\n                String lastKey = StringUtils.substringAfter(longKey, \".\");\n                innerMap.put(lastKey, map.get(longKey));\n                result.put(firstKey, formatMap(innerMap));\n            } else {\n                result.put(longKey, map.get(longKey));\n            }\n        }\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/utils/LogUtils.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.utils;\n\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\n\n/**\n * @author didi\n * @date 2021-09-26 3:31 下午\n */\npublic class LogUtils {\n\n    public static final String KIBANA_LOG = \"_arius_query or _arius_write is from kibana\";\n\n    public static void setWriteLog(QueryContext queryContext, IndexTemplate indexTemplate,\n                                     ESActionResponse response, long currentTime, boolean contentOpen) {\n        JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n        joinLogContext.setClientNode(response.getHost().getHostName() + \":\" + response.getHost().getPort());\n        joinLogContext.setTotalCost(currentTime - queryContext.getRequestTime());\n        joinLogContext.setInternalCost( joinLogContext.getTotalCost() - joinLogContext.getEsCost());\n        joinLogContext.setSinkTime(System.currentTimeMillis());\n        joinLogContext.setQueryRequest(false);\n        joinLogContext.setDestTemplateName(null != indexTemplate ? indexTemplate.getName() : \"none\");\n        if (!contentOpen) {\n            joinLogContext.setDsl(null);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/utils/ParsingException.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.utils;\n\nimport org.elasticsearch.ElasticsearchException;\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.common.io.stream.StreamOutput;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentLocation;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.io.IOException;\n\n/**\n * Exception that can be used when parsing queries with a given {@link\n * org.elasticsearch.common.xcontent.XContentParser}.\n * Can contain information about location of the error.\n */\npublic class ParsingException extends ElasticsearchException {\n\n    protected static final int UNKNOWN_POSITION = -1;\n    private final int lineNumber;\n    private final int columnNumber;\n\n    public ParsingException(XContentLocation contentLocation, String msg, Object... args) {\n        this(contentLocation, msg, null, args);\n    }\n\n    public ParsingException(XContentLocation contentLocation, String msg, Throwable cause, Object... args) {\n        super(msg, cause, args);\n        int lineNumber = UNKNOWN_POSITION;\n        int columnNumber = UNKNOWN_POSITION;\n        if (contentLocation != null) {\n            lineNumber = contentLocation.lineNumber;\n            columnNumber = contentLocation.columnNumber;\n        }\n        this.columnNumber = columnNumber;\n        this.lineNumber = lineNumber;\n    }\n\n    /**\n     * This constructor is provided for use in unit tests where a\n     * {@link org.elasticsearch.common.xcontent.XContentParser} may not be available\n     */\n    public ParsingException(int line, int col, String msg, Throwable cause) {\n        super(msg, cause);\n        this.lineNumber = line;\n        this.columnNumber = col;\n    }\n\n    public ParsingException(StreamInput in) throws IOException {\n        super(in);\n        lineNumber = in.readInt();\n        columnNumber = in.readInt();\n    }\n\n    /**\n     * Line number of the location of the error\n     *\n     * @return the line number or -1 if unknown\n     */\n    public int getLineNumber() {\n        return lineNumber;\n    }\n\n    /**\n     * Column number of the location of the error\n     *\n     * @return the column number or -1 if unknown\n     */\n    public int getColumnNumber() {\n        return columnNumber;\n    }\n\n    @Override\n    public RestStatus status() {\n        return RestStatus.BAD_REQUEST;\n    }\n\n    protected void metadataToXContent(XContentBuilder builder, Params params) throws IOException {\n        if (lineNumber != UNKNOWN_POSITION) {\n            builder.field(\"line\", lineNumber);\n            builder.field(\"col\", columnNumber);\n        }\n    }\n\n    @Override\n    public void writeTo(StreamOutput out) throws IOException {\n        super.writeTo(out);\n        out.writeInt(lineNumber);\n        out.writeInt(columnNumber);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/utils/RequestConverters.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.utils;\n\nimport com.didi.arius.gateway.elasticsearch.client.model.RestRequest;\nimport org.elasticsearch.action.support.IndicesOptions;\nimport org.elasticsearch.cluster.health.ClusterHealthStatus;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.lucene.uid.Versions;\nimport org.elasticsearch.common.unit.TimeValue;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.index.VersionType;\nimport org.elasticsearch.search.fetch.source.FetchSourceContext;\nimport org.elasticsearch.tasks.TaskId;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.util.Locale;\nimport java.util.StringJoiner;\n\npublic class RequestConverters {\n    static final XContentType REQUEST_BODY_CONTENT_TYPE = XContentType.JSON;\n\n    private RequestConverters() {\n        // Contains only status utility methods\n    }\n\n    public static String endpoint(String index, String type, String id) {\n        return new EndpointBuilder().addPathPart(index, type, id).build();\n    }\n\n    public static String endpoint(String index, String type, String id, String endpoint) {\n        return new EndpointBuilder().addPathPart(index, type, id).addPathPartAsIs(endpoint).build();\n    }\n\n    public static String endpoint(String[] indices) {\n        return new EndpointBuilder().addCommaSeparatedPathParts(indices).build();\n    }\n\n    public static String endpoint(String[] indices, String endpoint) {\n        return new EndpointBuilder().addCommaSeparatedPathParts(indices).addPathPartAsIs(endpoint).build();\n    }\n\n    public static String endpoint(String[] indices, String[] types, String endpoint) {\n        return new EndpointBuilder().addCommaSeparatedPathParts(indices).addCommaSeparatedPathParts(types)\n                .addPathPartAsIs(endpoint).build();\n    }\n\n    public static String endpoint(String[] indices, String endpoint, String[] suffixes) {\n        return new EndpointBuilder().addCommaSeparatedPathParts(indices).addPathPartAsIs(endpoint)\n                .addCommaSeparatedPathParts(suffixes).build();\n    }\n\n    public static String endpoint(String[] indices, String endpoint, String type) {\n        return new EndpointBuilder().addCommaSeparatedPathParts(indices).addPathPartAsIs(endpoint).addPathPart(type).build();\n    }\n\n    /**\n     * Utility class to help with common parameter names and patterns. Wraps\n     * a {@link RestRequest} and adds the parameters to it directly.\n     */\n    public static class Params {\n        private final RestRequest request;\n\n        public Params(RestRequest request) {\n            this.request = request;\n        }\n\n        public Params putParam(String name, String value) {\n            if (Strings.hasLength(value)) {\n                request.addParam(name, value);\n            }\n            return this;\n        }\n\n        public Params putParam(String key, TimeValue value) {\n            if (value != null) {\n                return putParam(key, value.toString());\n            }\n            return this;\n        }\n\n        public Params withDocAsUpsert(boolean docAsUpsert) {\n            if (docAsUpsert) {\n                return putParam(\"doc_as_upsert\", Boolean.TRUE.toString());\n            }\n            return this;\n        }\n\n        public Params withFetchSourceContext(FetchSourceContext fetchSourceContext) {\n            if (fetchSourceContext != null) {\n                if (!fetchSourceContext.fetchSource()) {\n                    putParam(\"_source\", Boolean.FALSE.toString());\n                }\n                if (fetchSourceContext.includes() != null && fetchSourceContext.includes().length > 0) {\n                    putParam(\"_source_include\", String.join(\",\", fetchSourceContext.includes()));\n                }\n                if (fetchSourceContext.excludes() != null && fetchSourceContext.excludes().length > 0) {\n                    putParam(\"_source_exclude\", String.join(\",\", fetchSourceContext.excludes()));\n                }\n            }\n            return this;\n        }\n\n        public Params withFields(String[] fields) {\n            if (fields != null && fields.length > 0) {\n                return putParam(\"fields\", String.join(\",\", fields));\n            }\n            return this;\n        }\n\n        public Params withMasterTimeout(TimeValue masterTimeout) {\n            return putParam(\"master_timeout\", masterTimeout);\n        }\n\n        public Params withParent(String parent) {\n            return putParam(\"parent\", parent);\n        }\n\n        public Params withPipeline(String pipeline) {\n            return putParam(\"pipeline\", pipeline);\n        }\n\n        public Params withPreference(String preference) {\n            return putParam(\"preference\", preference);\n        }\n\n        public Params withRealtime(boolean realtime) {\n            if (!realtime) {\n                return putParam(\"realtime\", Boolean.FALSE.toString());\n            }\n            return this;\n        }\n\n        public Params withRefresh(String refresh) {\n            return putParam(\"refresh\", refresh);\n        }\n\n        public Params withRetryOnConflict(int retryOnConflict) {\n            if (retryOnConflict > 0) {\n                return putParam(\"retry_on_conflict\", String.valueOf(retryOnConflict));\n            }\n            return this;\n        }\n\n        public Params withConsistency(String consistency) {\n            return putParam(\"consistency\", consistency);\n        }\n\n        public Params withWaitForActiveShards(String waitForActiveShards) {\n            return putParam(\"wait_for_active_shards\", waitForActiveShards);\n        }\n\n        public Params withRouting(String routing) {\n            return putParam(\"routing\", routing);\n        }\n\n        public Params withStoredFields(String[] storedFields) {\n            if (storedFields != null && storedFields.length > 0) {\n                return putParam(\"stored_fields\", String.join(\",\", storedFields));\n            }\n            return this;\n        }\n\n        public Params withTimeout(TimeValue timeout) {\n            return putParam(\"timeout\", timeout);\n        }\n\n        public Params withUpdateAllTypes(boolean updateAllTypes) {\n            if (updateAllTypes) {\n                return putParam(\"update_all_types\", Boolean.TRUE.toString());\n            }\n            return this;\n        }\n\n        public Params withVersion(long version) {\n            if (version != Versions.MATCH_ANY) {\n                return putParam(\"version\", Long.toString(version));\n            }\n            return this;\n        }\n\n        public Params withVersionType(VersionType versionType) {\n            if (versionType != VersionType.INTERNAL) {\n                return putParam(\"version_type\", versionType.name().toLowerCase(Locale.ROOT));\n            }\n            return this;\n        }\n\n        /*Params withWaitForActiveShards(ActiveShardCount currentActiveShardCount, ActiveShardCount defaultActiveShardCount) {\n            if (currentActiveShardCount != null && currentActiveShardCount != defaultActiveShardCount) {\n                return putParam(\"wait_for_active_shards\", currentActiveShardCount.toString().toLowerCase(Locale.ROOT));\n            }\n            return this;\n        }*/\n\n        public Params withIndicesOptions(IndicesOptions indicesOptions) {\n            withIgnoreUnavailable(indicesOptions.ignoreUnavailable());\n            putParam(\"allow_no_indices\", Boolean.toString(indicesOptions.allowNoIndices()));\n            String expandWildcards;\n            if (!indicesOptions.expandWildcardsOpen() && !indicesOptions.expandWildcardsClosed()) {\n                expandWildcards = \"none\";\n            } else {\n                StringJoiner joiner = new StringJoiner(\",\");\n                if (indicesOptions.expandWildcardsOpen()) {\n                    joiner.add(\"open\");\n                }\n                if (indicesOptions.expandWildcardsClosed()) {\n                    joiner.add(\"closed\");\n                }\n                expandWildcards = joiner.toString();\n            }\n            putParam(\"expand_wildcards\", expandWildcards);\n            return this;\n        }\n\n        public Params withIgnoreUnavailable(boolean ignoreUnavailable) {\n            // Always explicitly place the ignore_unavailable value.\n            putParam(\"ignore_unavailable\", Boolean.toString(ignoreUnavailable));\n            return this;\n        }\n\n        public Params withHuman(boolean human) {\n            if (human) {\n                putParam(\"human\", Boolean.toString(human));\n            }\n            return this;\n        }\n\n        public Params withLocal(boolean local) {\n            if (local) {\n                putParam(\"local\", Boolean.toString(local));\n            }\n            return this;\n        }\n\n        public Params withIncludeDefaults(boolean includeDefaults) {\n            if (includeDefaults) {\n                return putParam(\"include_defaults\", Boolean.TRUE.toString());\n            }\n            return this;\n        }\n\n        public Params withPreserveExisting(boolean preserveExisting) {\n            if (preserveExisting) {\n                return putParam(\"preserve_existing\", Boolean.TRUE.toString());\n            }\n            return this;\n        }\n\n        public Params withDetailed(boolean detailed) {\n            if (detailed) {\n                return putParam(\"detailed\", Boolean.TRUE.toString());\n            }\n            return this;\n        }\n\n        public Params withWaitForCompletion(boolean waitForCompletion) {\n            if (waitForCompletion) {\n                return putParam(\"wait_for_completion\", Boolean.TRUE.toString());\n            }\n            return this;\n        }\n\n        public Params withNodes(String[] nodes) {\n            if (nodes != null && nodes.length > 0) {\n                return putParam(\"nodes\", String.join(\",\", nodes));\n            }\n            return this;\n        }\n\n        public Params withActions(String[] actions) {\n            if (actions != null && actions.length > 0) {\n                return putParam(\"actions\", String.join(\",\", actions));\n            }\n            return this;\n        }\n\n        public Params withTaskId(TaskId taskId) {\n            if (taskId != null && taskId.isSet()) {\n                return putParam(\"task_id\", taskId.toString());\n            }\n            return this;\n        }\n\n        public Params withParentTaskId(TaskId parentTaskId) {\n            if (parentTaskId != null && parentTaskId.isSet()) {\n                return putParam(\"parent_task_id\", parentTaskId.toString());\n            }\n            return this;\n        }\n\n        public Params withVerify(boolean verify) {\n            if (verify) {\n                return putParam(\"verify\", Boolean.TRUE.toString());\n            }\n            return this;\n        }\n\n        public Params withWaitForStatus(ClusterHealthStatus status) {\n            if (status != null) {\n                return putParam(\"wait_for_status\", status.name().toLowerCase(Locale.ROOT));\n            }\n            return this;\n        }\n\n        public Params withWaitForNoRelocatingShards(boolean waitNoRelocatingShards) {\n            if (waitNoRelocatingShards) {\n                return putParam(\"wait_for_no_relocating_shards\", Boolean.TRUE.toString());\n            }\n            return this;\n        }\n\n        public Params withWaitForNoInitializingShards(boolean waitNoInitShards) {\n            if (waitNoInitShards) {\n                return putParam(\"wait_for_no_initializing_shards\", Boolean.TRUE.toString());\n            }\n            return this;\n        }\n\n        public Params withWaitForNodes(String waitForNodes) {\n            return putParam(\"wait_for_nodes\", waitForNodes);\n        }\n\n    }\n\n    /**\n     * Utility class to build request's endpoint given its parts as strings\n     */\n    static class EndpointBuilder {\n\n        private final StringJoiner joiner = new StringJoiner(\"/\", \"/\", \"\");\n\n        EndpointBuilder addPathPart(String... parts) {\n            for (String part : parts) {\n                if (Strings.hasLength(part)) {\n                    joiner.add(encodePart(part));\n                }\n            }\n            return this;\n        }\n\n        EndpointBuilder addCommaSeparatedPathParts(String[] parts) {\n            addPathPart(String.join(\",\", parts));\n            return this;\n        }\n\n        EndpointBuilder addPathPartAsIs(String... parts) {\n            for (String part : parts) {\n                if (Strings.hasLength(part)) {\n                    joiner.add(part);\n                }\n            }\n            return this;\n        }\n\n        String build() {\n            return joiner.toString();\n        }\n\n        private static String encodePart(String pathPart) {\n            try {\n                //encode each part (e.g. index, type and id) separately before merging them into the path\n                //we prepend \"/\" to the path part to make this path absolute, otherwise there can be issues with\n                //paths that start with `-` or contain `:`\n                URI uri = new URI(null, null, null, -1, \"/\" + pathPart, null, null);\n                //manually encode any slash that each part may contain\n                return uri.getRawPath().substring(1).replace(\"/\", \"%2F\");\n            } catch (URISyntaxException e) {\n                throw new IllegalArgumentException(\"Path part [\" + pathPart + \"] couldn't be encoded\", e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-common/src/main/java/com/didi/arius/gateway/elasticsearch/client/utils/XContentParserUtils.java",
    "content": "package com.didi.arius.gateway.elasticsearch.client.utils;\n\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.xcontent.XContentLocation;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.XContentParser.Token;\n\nimport java.io.IOException;\nimport java.util.Locale;\nimport java.util.function.Supplier;\n\n/**\n * A set of static methods to get {@link Token} from {@link XContentParser}\n * while checking for their types and throw {@link ParsingException} if needed.\n */\npublic final class XContentParserUtils {\n\n    private XContentParserUtils() {\n    }\n\n    /**\n     * Makes sure that current token is of type {@link Token#FIELD_NAME} and the field name is equal to the provided one\n     * @throws ParsingException if the token is not of type {@link Token#FIELD_NAME} or is not equal to the given field name\n     */\n    public static void ensureFieldName(XContentParser parser, Token token, String fieldName) throws IOException {\n        ensureExpectedToken(Token.FIELD_NAME, token, parser::getTokenLocation);\n        String currentName = parser.currentName();\n        if (!currentName.equals(fieldName)) {\n            String message = \"Failed to parse object: expecting field with name [%s] but found [%s]\";\n            throw new ParsingException(parser.getTokenLocation(), String.format(Locale.ROOT, message, fieldName, currentName));\n        }\n    }\n\n    /**\n     * @throws ParsingException with a \"unknown field found\" reason\n     */\n    public static void throwUnknownField(String field, XContentLocation location) {\n        String message = \"Failed to parse object: unknown field [%s] found\";\n        throw new ParsingException(location, String.format(Locale.ROOT, message, field));\n    }\n\n    /**\n     * @throws ParsingException with a \"unknown token found\" reason\n     */\n    public static void throwUnknownToken(Token token, XContentLocation location) {\n        String message = \"Failed to parse object: unexpected token [%s] found\";\n        throw new ParsingException(location, String.format(Locale.ROOT, message, token));\n    }\n\n    /**\n     * Makes sure that provided token is of the expected type\n     *\n     * @throws ParsingException if the token is not equal to the expected type\n     */\n    public static void ensureExpectedToken(Token expected, Token actual, Supplier<XContentLocation> location) {\n        if (actual != expected) {\n            String message = \"Failed to parse object: expecting token of type [%s] but found [%s]\";\n            throw new ParsingException(location.get(), String.format(Locale.ROOT, message, expected, actual));\n        }\n    }\n\n    /**\n     * Parse the current token depending on its token type. The following token types will be\n     * parsed by the corresponding parser methods:\n     * <ul>\n     *    <li>{@link Token#VALUE_STRING}: {@link XContentParser#text()}</li>\n     *    <li>{@link Token#VALUE_NUMBER}: {@link XContentParser#numberValue()} ()}</li>\n     *    <li>{@link Token#VALUE_BOOLEAN}: {@link XContentParser#booleanValue()} ()}</li>\n     *    <li>{@link Token#VALUE_EMBEDDED_OBJECT}: {@link XContentParser#binaryValue()} ()}</li>\n     *    <li>{@link Token#VALUE_NULL}: returns null</li>\n     *    <li>{@link Token#START_OBJECT}: {@link XContentParser#mapOrdered()} ()}</li>\n     *    <li>{@link Token#START_ARRAY}: {@link XContentParser#listOrderedMap()} ()}</li>\n     * </ul>\n     *\n     * @throws ParsingException if the token is none of the allowed values\n     */\n    public static Object parseFieldsValue(XContentParser parser) throws IOException {\n        Token token = parser.currentToken();\n        Object value = null;\n        if (token == Token.VALUE_STRING) {\n            //binary values will be parsed back and returned as base64 strings when reading from json and yaml\n            value = parser.text();\n        } else if (token == Token.VALUE_NUMBER) {\n            value = parser.numberValue();\n        } else if (token == Token.VALUE_BOOLEAN) {\n            value = parser.booleanValue();\n        } else if (token == Token.VALUE_EMBEDDED_OBJECT) {\n            //binary values will be parsed back and returned as BytesArray when reading from cbor and smile\n            value = new BytesArray(parser.binaryValue());\n        } else if (token == Token.VALUE_NULL) {\n            value = null;\n        } else if (token == Token.START_OBJECT) {\n            value = parser.mapOrdered();\n        } else if (token == Token.START_ARRAY) {\n            value = parser.listOrderedMap();\n        } else {\n            throwUnknownToken(token, parser.getTokenLocation());\n        }\n        return value;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.didi</groupId>\n        <artifactId>arius-gateway-v2</artifactId>\n        <version>0.0.1-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>arius-gateway-core</artifactId>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.didi</groupId>\n            <artifactId>arius-gateway-common</artifactId>\n            <version>${project.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.didi</groupId>\n            <artifactId>arius-gateway-remote</artifactId>\n            <version>${project.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-elasticsearch-sql</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-dsl-prase</artifactId>\n        </dependency>\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/component/QueryConfig.java",
    "content": "package com.didi.arius.gateway.core.component;\n\nimport com.didi.arius.gateway.common.metrics.log.DslMetricHelper;\nimport lombok.Getter;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Configuration;\n\nimport javax.annotation.PostConstruct;\nimport java.util.concurrent.Semaphore;\n\n/**\n* @author fitz\n* @date：2021年5月31日\n* \n*/\n@Configuration\n@Getter\npublic class QueryConfig {\n\n\t@Value(\"${gateway.queryConfig.searchSlowlogThresholdMills}\")\n\tprivate long searchSlowlogThresholdMills;\n\t\n\t@Value(\"${gateway.queryConfig.requestSlowlogThresholdMills}\")\n\tprivate long requestSlowlogThresholdMills;\n\t\n\t@Value(\"${gateway.queryConfig.dslMaxLength}\")\n\tprivate int dslMaxLength;\n\n\t@Value(\"${gateway.queryConfig.tcpQueryLimit}\")\n\tprivate int tcpQueryLimit;\n\n\t@Value(\"${gateway.queryConfig.httpQueryLimit}\")\n\tprivate int httpQueryLimit;\n\n\t@Value(\"${gateway.queryConfig.kibanaSearchUri}\")\n\tprivate String kibanaSearchUri;\n\n\t@Value(\"${gateway.queryConfig.maxAggsBuckets}\")\n\tprivate int maxAggsBuckets;\n\t\n\t@Value(\"${gateway.queryConfig.maxAggsMemUsed}\")\n\tprivate long maxAggsMemUsed;\n\n\t@Value(\"${gateway.queryConfig.connectESTime}\")\n\tprivate String connectESTime;\n\t\n\t@Value(\"${gateway.queryConfig.clientWorkerCount}\")\n\tprivate String clientWorkerCount;\n\n\t@Value(\"${gateway.queryConfig.fetchTimeout}\")\n\tprivate long fetchTimeout;\n\t\n\t@Value(\"${gateway.queryConfig.dslQPSLimit}\")\n\tprivate double dslQPSLimit;\n\t\n\t@Value(\"${gateway.queryConfig.maxHttpResponseLength}\")\n\tprivate int maxHttpResponseLength;\n\n\t@Value(\"${gateway.queryConfig.checkForbidden}\")\n\tprivate boolean checkForbidden;\n\n\t@Value(\"${gateway.queryConfig.esSocketTimeout}\")\n\tprivate int esSocketTimeout;\n\n\t@Value(\"${elasticsearch.admin.cluster.name}\")\n\tprivate String adminClusterName;\n\n\t@Value(\"${gateway.queryConfig.runMode}\")\n\tprivate String runMode;\n\n\t@Value(\"${gateway.queryConfig.maxByteIn}\")\n\tprivate long maxByteIn;\n\n\tprivate Semaphore httpSemaphore;\n\n\tprivate Semaphore tcpSemaphore;\n\n\t@Value(\"${gateway.dslLog.map.size:1000}\")\n\tprivate int dslMapSize;\n\n\t@Value(\"${gateway.dslLog.thread.size:4}\")\n\tprivate int threadSize;\n\n\t@Value(\"${gateway.dslLog.queue.size:1000}\")\n\tprivate int queueSize;\n\n\t@Value(\"${gateway.write.log.content.open:false}\")\n\tprivate boolean writeLogContentOpen;\n\n\tpublic QueryConfig() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\thttpSemaphore = new Semaphore(httpQueryLimit);\n\n\t\ttcpSemaphore = new Semaphore(tcpQueryLimit);\n\n\t\tDslMetricHelper.init(dslMapSize,threadSize, queueSize);\n\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/component/SpringTool.java",
    "content": "package com.didi.arius.gateway.core.component;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.DisposableBean;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.ApplicationEvent;\nimport org.springframework.context.annotation.Lazy;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Map;\n\n/**\n * @author huangyiminghappy@163.com\n * @date 2019-05-08\n */\n@Service(\"springTool\")\n@Lazy(false)\n@Order(value = 1)\npublic class SpringTool implements ApplicationContextAware, DisposableBean {\n    private static ApplicationContext applicationContext = null;\n\n    private static ILog logger             = LogFactory.getLog(SpringTool.class);\n\n    /**\n     * 去的存储在静态变量中的ApplicationContext\n     */\n    private static ApplicationContext getApplicationContext() {\n        return applicationContext;\n    }\n\n    /**\n     * 从静态变量applicationContext中去的Bean，自动转型为所复制对象的类型\n     */\n    public static <T> T getBean(String name) {\n        return (T) applicationContext.getBean(name);\n    }\n\n    public static <T> T getBean(String name, Class<T> clazz) {\n        return applicationContext.getBean(name, clazz);\n    }\n\n    public static <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {\n        return getApplicationContext().getBeansOfType(type);\n    }\n\n    /**\n     * 清除SpringContextHolder中的ApplicationContext为Null\n     */\n    public static void clearHolder() {\n        if (logger.isDebugEnabled()) {\n            logger.debug(String.format(\"清除SpringContextHolder中的ApplicationContext:%s\", applicationContext));\n        }\n        applicationContext = null;\n    }\n\n    /**\n     * 实现ApplicationContextAware接口，注入Context到静态变量\n     */\n    @Override\n    public void setApplicationContext(ApplicationContext context) throws BeansException {\n        SpringTool.applicationContext = context;\n    }\n\n    /**\n     * 实现DisposableBean接口，在Context关闭时清理静态变量\n     */\n    @Override\n    public void destroy() throws Exception {\n        SpringTool.clearHolder();\n    }\n\n    /**\n     * 发布一个事件\n     */\n    public static void publish(ApplicationEvent event) {\n        getApplicationContext().publishEvent(event);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/component/ThreadPool.java",
    "content": "package com.didi.arius.gateway.core.component;\n\nimport com.didiglobal.knowframework.observability.Observability;\nimport org.elasticsearch.common.util.concurrent.EsExecutors;\nimport org.jboss.netty.util.ThreadRenamingRunnable;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n@Component(\"threadPool\")\npublic class ThreadPool {\n\n\tprivate ScheduledExecutorService scheduleThreadPool;\n\tprivate int scheduleThreadNum = 16;\n\tprivate int searchSize = 100;\n\tprivate int searchQueueSize = 1000;\n\t\n\tprivate Executor searchExecutor;\n\n\tpublic ThreadPool() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\tscheduleThreadPool = Observability.wrap(Executors.newScheduledThreadPool(\n\t\t\t\tscheduleThreadNum, new DeamondThreadFactory(\n\t\t\t\t\t\t\"scheduleThreadPool\")));\n\t\t\n\t\tsearchExecutor = Observability.wrap(EsExecutors.newFixed(\"search\", searchSize, searchQueueSize, new DeamondThreadFactory(\n\t\t\t\t\"searchThreadPool\")));\n\t}\n\t\n\tpublic void submitScheduleAtFixTask(Runnable runnable, long initialDelay,\n\t\t\tlong period) {\n\t\tscheduleThreadPool.scheduleAtFixedRate(runnable, initialDelay, period,\n\t\t\t\tTimeUnit.SECONDS);\n\t}\n\t\n}\n\nclass DeamondThreadFactory implements ThreadFactory {\n\tstatic final AtomicInteger poolNumber = new AtomicInteger(1);\n\tfinal ThreadGroup group;\n\tfinal AtomicInteger threadNumber = new AtomicInteger(1);\n\tfinal String namePrefix;\n\n\tstatic {\n\t\tThreadRenamingRunnable\n\t\t\t\t.setThreadNameDeterminer( (currentThreadName, proposedThreadName) -> currentThreadName );\n\t}\n\n\t@Override\n\tpublic Thread newThread(Runnable r) {\n\t\tThread t = new Thread(group, r, namePrefix\n\t\t\t\t+ threadNumber.getAndIncrement(), 0);\n\t\tif (!t.isDaemon())\n\t\t\tt.setDaemon(true);\n\t\tif (t.getPriority() != Thread.NORM_PRIORITY)\n\t\t\tt.setPriority(Thread.NORM_PRIORITY);\n\t\treturn t;\n\t}\n\n\tpublic DeamondThreadFactory(String prefix) {\n\t\tSecurityManager s = System.getSecurityManager();\n\t\tgroup = (s != null) ? s.getThreadGroup() : Thread.currentThread()\n\t\t\t\t.getThreadGroup();\n\t\tnamePrefix = prefix + \"-pool-\" + poolNumber.getAndIncrement()\n\t\t\t\t+ \"-\";\n\t}\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/component/log/AbstractAggLogManager.java",
    "content": "package com.didi.arius.gateway.core.component.log;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.observability.Observability;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * @author didi\n * @date 2021-09-17 5:22 下午\n */\npublic abstract class AbstractAggLogManager {\n\n    protected static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n\n    protected ScheduledExecutorService scheduleThreadPool;\n\n    /**\n     * 定时线程池启动，以便后续其他日志聚合操作\n     *\n     * @param threadSize 池大小\n     * @param runnable   处理类\n     * @param interval   处理间隔\n     */\n    public void init(int threadSize, Runnable runnable, int interval) {\n        scheduleThreadPool = Observability.wrap(Executors.newScheduledThreadPool(threadSize));\n        scheduleThreadPool.scheduleWithFixedDelay(runnable, interval, interval, TimeUnit.MINUTES);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/component/log/DslLogManager.java",
    "content": "package com.didi.arius.gateway.core.component.log;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.metrics.log.DslLogEntity;\nimport com.didi.arius.gateway.common.metrics.log.DslMetricHelper;\nimport com.didi.arius.gateway.core.component.log.process.LogProcess;\nimport com.didi.arius.gateway.core.component.log.process.MetricLogProcess;\nimport com.didi.arius.gateway.core.component.log.process.TemplateLogProcess;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport javax.annotation.PostConstruct;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author didi\n * @date 2021-09-16 11:21 下午\n */\n@Component\npublic class DslLogManager extends AbstractAggLogManager {\n    public static final String LOG_TIME = \"logTime\";\n    public static final String FLINK_TIME = \"flinkTime\";\n    public static final String TIMESTAMP = \"timeStamp\";\n    public static final String VERSION = \"version\";\n    public static final String TIME_FORMAT = \"yyyy-MM-dd HH:mm:ss.SSS Z\";\n    public static final String[] OUTPUT_FIELD_NAME = new String[]{\n            \"appid\",\"projectId\", \"dslTemplate\", \"dslTemplateMd5\", \"timeStamp\", \"dsl\", \"indices\", \"indiceSample\",\n            \"requestType\", \"searchType\",\n            \"dslType\", \"isFromUserConsole\", \"version\", \"dslLenAvg\", \"responseLenAvg\", \"beforeCostAvg\", \"esCostAvg\",\n            \"totalCostAvg\", \"successfulShardsAvg\", \"totalShardsAvg\", \"failedShardsAvg\", \"totalHitsAvg\", \"searchCount\", \"gatewayNode\", \"appidDslTemplateMd5\",\"projectIdDslTemplateMd5\"\n    };\n    public static final int ONE = 1;\n    public static final int INTERVAL_MINUTES = 1;\n\n    @Autowired\n    private ESRestClientService esRestClientService;\n\n    @Autowired\n    protected IndexTemplateService indexTemplateService;\n\n    @PostConstruct\n    public void init() {\n        DslLogProcessDecorator logProcess = new DslLogProcessDecorator(\n                new MetricLogProcess(esRestClientService, indexTemplateService),\n                new TemplateLogProcess(esRestClientService, indexTemplateService)\n        );\n        super.init(ONE, logProcess, INTERVAL_MINUTES);\n    }\n\n    public class DslLogProcessDecorator implements Runnable {\n\n        List<LogProcess> logProcessList = new ArrayList<>();\n\n        public DslLogProcessDecorator(LogProcess... logProcesses) {\n            Arrays.stream(logProcesses).forEach(x -> logProcessList.add(x));\n        }\n\n        @Override\n        public void run() {\n            Collection<DslLogEntity> dslLogEntities = DslMetricHelper.getDslLogMap().values();\n            if (dslLogEntities.size() > 0) {\n                //这里清空，如果写失败也丢弃日志，等待下一批再写入\n                DslMetricHelper.resetMap();\n                List<JSONObject> records = dslLogEntities.stream().map(x -> dslLog(x)).collect(Collectors.toList());\n                logProcessList.stream().forEach(process -> process.dealLog(records));\n            }\n        }\n\n        private JSONObject dslLog(DslLogEntity dslLogEntity) {\n            calculateAvg(dslLogEntity);\n            if (null == dslLogEntity.getIndiceSample()) {\n                dslLogEntity.setIndiceSample(dslLogEntity.getIndices());\n            }\n            JSONObject mapResult = new JSONObject();\n            JSONObject dslJs = (JSONObject) JSON.toJSON(dslLogEntity);\n            SimpleDateFormat sd = new SimpleDateFormat(TIME_FORMAT);\n            Arrays.stream(OUTPUT_FIELD_NAME).forEach(field -> {\n                mapResult.put(field, dslJs.get(field));\n            });\n            mapResult.put(LOG_TIME, sd.format(new Date(dslJs.getLong(TIMESTAMP))));\n            mapResult.put(FLINK_TIME, sd.format(new Date()));\n            mapResult.put(VERSION, \"V2\");\n            return mapResult;\n        }\n\n\n        private void calculateAvg(DslLogEntity dslLogEntity) {\n            double searchCount = dslLogEntity.getSearchCount();\n            dslLogEntity.setDslLenAvg(dslLogEntity.getDslLen() / searchCount);\n            dslLogEntity.setResponseLenAvg(dslLogEntity.getResponseLen() / searchCount);\n            dslLogEntity.setBeforeCostAvg(dslLogEntity.getBeforeCost() / searchCount);\n            dslLogEntity.setEsCostAvg(dslLogEntity.getEsCost() / searchCount);\n            dslLogEntity.setTotalCostAvg(dslLogEntity.getTotalCost() / searchCount);\n            dslLogEntity.setTotalShardsAvg(dslLogEntity.getTotalShards() / searchCount);\n            dslLogEntity.setTotalHitsAvg(dslLogEntity.getTotalHits() / searchCount);\n            dslLogEntity.setFailedShardsAvg(dslLogEntity.getFailedShards() / searchCount);\n            dslLogEntity.setSuccessfulShardsAvg(dslLogEntity.getTotalShardsAvg() - dslLogEntity.getFailedShardsAvg());\n        }\n    }\n\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/component/log/process/AbstractDslLogProcess.java",
    "content": "package com.didi.arius.gateway.core.component.log.process;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\nimport java.util.List;\n\n/**\n * @author didi\n * @date 2021-09-23 3:41 下午\n */\npublic abstract class AbstractDslLogProcess implements LogProcess<List<JSONObject>> {\n\n    protected static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n\n    public static final String TYPE = \"_doc\";\n\n    protected ESRestClientService esRestClientService;\n\n    protected IndexTemplateService indexTemplateService;\n\n    protected AbstractDslLogProcess(ESRestClientService esRestClientService, IndexTemplateService indexTemplateService) {\n        this.esRestClientService = esRestClientService;\n        this.indexTemplateService = indexTemplateService;\n    }\n\n\n    public IndexTemplate getTemplate(String template) {\n        IndexTemplate indexTemplate = indexTemplateService.getIndexTemplate(template);\n        if (null == indexTemplate) {\n            bootLogger.warn(\"can not find template[{}]\", template);\n        }\n        return indexTemplate;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/component/log/process/LogProcess.java",
    "content": "package com.didi.arius.gateway.core.component.log.process;\n\npublic interface LogProcess<T> {\n    public void dealLog(T records);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/component/log/process/MetricLogProcess.java",
    "content": "package com.didi.arius.gateway.core.component.log.process;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.BatchNode;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.BatchType;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.ESBatchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.ESBatchResponse;\n\nimport java.util.List;\n\n/**\n * @author didi\n * @date 2021-09-23 3:32 下午\n */\npublic class MetricLogProcess extends AbstractDslLogProcess {\n\n    public static final String DSL_INDEX_NAME = \"arius.dsl.metrics\";\n\n    public MetricLogProcess(ESRestClientService esRestClientService, IndexTemplateService indexTemplateService) {\n        super(esRestClientService, indexTemplateService);\n    }\n\n    @Override\n    public void dealLog(List<JSONObject> records) {\n        try {\n            IndexTemplate indexTemplate = getTemplate(DSL_INDEX_NAME);\n            if (null != indexTemplate) {\n                ESClient esClient = esRestClientService.getClientStrict(indexTemplate.getMasterInfo().getCluster(), \"MetricLogProcess\");\n                ESBatchRequest esBatchRequest = new ESBatchRequest();\n                esBatchRequest.setPipeline(indexTemplate.getIngestPipeline());\n                records.stream().forEach(x ->\n                        esBatchRequest.addNode(new BatchNode(BatchType.INDEX, DSL_INDEX_NAME, TYPE, null, x.toJSONString())));\n                ESBatchResponse response = esClient.batch(esBatchRequest).get();\n                if (response.getErrors()) {\n                    bootLogger.warn(\"batch insert error [{}]\", response.buildFailureMessage());\n                }\n            }\n        } catch (Exception e) {\n            bootLogger.error(\"insert dsl template log error\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/component/log/process/TemplateLogProcess.java",
    "content": "package com.didi.arius.gateway.core.component.log.process;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.BatchNode;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.BatchType;\nimport com.didi.arius.gateway.elasticsearch.client.request.batch.ESBatchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.response.batch.ESBatchResponse;\nimport java.util.List;\n\n/**\n * @author didi\n * @date 2021-09-23 4:18 下午\n */\npublic class TemplateLogProcess extends AbstractDslLogProcess {\n\n    public static final String DSL_TEMPLATE_INDEX_NAME = \"arius.dsl.template\";\n\n    public static final String PROJECT_ID_TEMPLATE = \"projectIdDslTemplateMd5\";\n\n    public TemplateLogProcess(ESRestClientService esRestClientService, IndexTemplateService indexTemplateService) {\n        super(esRestClientService, indexTemplateService);\n    }\n\n    @Override\n    public void dealLog(List<JSONObject> records) {\n        try {\n            IndexTemplate indexTemplate = getTemplate(DSL_TEMPLATE_INDEX_NAME);\n            if (null != indexTemplate) {\n                ESClient esClient = esRestClientService.getClientStrict(indexTemplate.getMasterInfo().getCluster(), \"TemplateLogProcess\");\n                ESBatchRequest esBatchRequest = new ESBatchRequest();\n                esBatchRequest.setPipeline(indexTemplate.getIngestPipeline());\n                records.stream().forEach(x ->\n                        esBatchRequest.addNode(new BatchNode(BatchType.UPDATE, DSL_TEMPLATE_INDEX_NAME, TYPE,\n                                x.getString(PROJECT_ID_TEMPLATE), x.toJSONString())));\n                ESBatchResponse response = esClient.batch(esBatchRequest).get();\n                if (response.getErrors()) {\n                    bootLogger.warn(\"batch insert error [{}]\", response.buildFailureMessage());\n                }\n            }\n        } catch (Exception e) {\n            bootLogger.error(\"insert dsl metric log error\", e);\n        }\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/ESAction.java",
    "content": "package com.didi.arius.gateway.core.es.http;\n\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\n\npublic abstract class ESAction extends HttpRestHandler {\n\n\tprivate static final String PATH_DELIMITER = \"/\";\n\n\t@Override\n\tpublic void handleRequest(QueryContext queryContext) throws Exception {\n\t\tRestRequest request = queryContext.getRequest();\n\t\tRestChannel channel = queryContext.getChannel();\n\n\t\tString[]  indicesArr = Strings.splitStringByCommaToArray(request.param(\"index\"));\n\t\tList<String> indices = Lists.newArrayList(indicesArr);\n\t\tqueryContext.setIndices(indices);\n\t\tqueryContext.setTypeNames(request.param(\"type\"));\n\n\t\tif (queryContext.isDetailLog()) {\n\t\t\tJoinLogContext joinLogContext = queryContext.getJoinLogContext();\n\t\t\tjoinLogContext.setBeforeCost(System.currentTimeMillis() - queryContext.getRequestTime());\n\t\t\tjoinLogContext.setIndices(StringUtils.join(indices, \",\"));\n\t\t\tjoinLogContext.setTypeName(request.param(\"type\"));\n\t\t}\n\n\t\tcheckFlowLimit(queryContext);\n\n\t\tif (isOriginCluster(queryContext)) {\n\t\t\thandleOriginClusterRequest(queryContext);\n\t\t} else {\n\t\t\tif (isNeededCheckIndices()) {\n\t\t\t\tif (isNeededCheckTemplateSearchBlockAction()) {\n\t\t\t\t\tcheckIndicesAndTemplateBlockRead(queryContext);\n\t\t\t\t} else {\n\t\t\t\t\tcheckIndices(queryContext);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\thandleInterRequest(queryContext, request, channel);\n\t\t}\n\t}\n\n\tprotected abstract void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception;\n\n    protected void indexAction(QueryContext queryContext, String index) {\n        IndexTemplate indexTemplate = preIndexAction(queryContext, index);\n        ESClient client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n        directRequest(client, queryContext);\n    }\n\n    protected void indexAction(QueryContext queryContext, String index, String api) {\n        IndexTemplate indexTemplate = preIndexAction(queryContext, index);\n        List<String> indices = Lists.newArrayList();\n        //传入索引，且模版为分区模板或者不分区模板升了版本，则将传入索引加上'*'\n        if (StringUtils.isNotBlank(index) && null != indexTemplate\n            && (indexTemplate.getExpression().endsWith(\"*\") || indexTemplate.getVersion() > 0)) {\n            String[] indicesArr = Strings.splitStringByCommaToArray(index);\n            indices = Lists.newArrayList(Convert.convertIndices(indicesArr));\n            queryContext.setIndices(indices);\n        }\n        ESClient client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n        String path = queryContext.getUri();\n        String type = queryContext.getTypeNames();\n        if (CollectionUtils.isNotEmpty(indices)) {\n            StringBuilder pathBuilder = new StringBuilder();\n            pathBuilder.append(PATH_DELIMITER).append(indices.stream().distinct().collect(Collectors.joining(\",\")));\n            if (StringUtils.isNotBlank(type)) {\n                pathBuilder.append(PATH_DELIMITER).append(type);\n            }\n            if (null != api && api.trim().length() > 0 && !api.startsWith(PATH_DELIMITER)) {\n                pathBuilder.append(PATH_DELIMITER);\n            }\n            pathBuilder.append(api);\n            path = pathBuilder.toString();\n        }\n        DirectRequest directRequest = buildDirectRequest(queryContext, path);\n        directRequest(client, queryContext, directRequest);\n    }\n\n\tprotected IndexTemplate preIndexAction(QueryContext queryContext, String index) {\n\t\tString[] indicesArr = Strings.splitStringByCommaToArray(index);\n\t\tList<String> indices = Lists.newArrayList(indicesArr);\n\t\tqueryContext.setIndices(indices);\n\t\tcheckIndices(queryContext);\n\t\tIndexTemplate indexTemplate = null;\n\t\tif (!queryContext.isFromKibana()) {\n\t\t\t// kibana的请求就不需要搜索模版了\n\t\t\tindexTemplate = getTemplateByIndexTire(indices, queryContext);\n\t\t\tqueryContext.setIndexTemplate(indexTemplate);\n\t\t}\n\t\treturn indexTemplate;\n\t}\n\n\tprotected boolean isAliasGet(IndexTemplate indexTemplate, List<String> indexs){\n\t\tif(CollectionUtils.isEmpty(indexTemplate.getAliases())){\n\t\t\treturn false;\n\t\t}\n\n\t\tfor(String index : indexs){\n\t\t\tif(indexTemplate.getAliases().contains( index )){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\t\n\t/**\n\t * 如果存在 filter_path 参数，则将 take、timed_out、_shards 和 hits 添加到 filter_path\n\t *\n\t * @param params 要传递给 Elasticsearch API 的参数。\n\t */\n\tprotected void addFilterPathDefaultValue(Map<String, String> params) {\n\t\tif (params.containsKey(\"filter_path\")) {\n\t\t\tSet<String> filterPath = Sets.newHashSet(StringUtils.split(params.get(\"filter_path\"), \",\"));\n\t\t\tfilterPath.add(\"took\");\n\t\t\tfilterPath.add(\"timed_out\");\n\t\t\tfilterPath.add(\"_shards\");\n\t\t\tfilterPath.add(\"hits\");\n\t\t\tparams.put(\"filter_path\", String.join(\",\", filterPath));\n\t\t}\n\t}\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/ESBase.java",
    "content": "package com.didi.arius.gateway.core.es.http;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLQueryExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.exception.IndexNotFoundException;\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.didi.arius.gateway.common.exception.SQLNotPermittedException;\nimport com.didi.arius.gateway.common.exception.TooManyIndexException;\nimport com.didi.arius.gateway.common.metadata.*;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.common.utils.DateUtil;\nimport com.didi.arius.gateway.common.utils.IndexTire;\nimport com.didi.arius.gateway.core.service.arius.AppService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport com.didi.arius.gateway.core.service.dsl.DslAggsAnalyzerService;\nimport com.didi.arius.gateway.core.service.dsl.DslAuditService;\nimport com.didi.arius.gateway.core.service.dsl.DslRewriterService;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESGetResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESMultiGetRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESMultiGetResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.response.src.Hit;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport com.google.gson.JsonParser;\nimport org.elasticsearch.action.*;\nimport org.elasticsearch.action.get.GetRequest;\nimport org.elasticsearch.action.get.MultiGetRequest;\nimport org.elasticsearch.action.search.SearchAction;\nimport org.elasticsearch.action.search.SearchRequest;\nimport org.elasticsearch.action.search.SearchRequestBuilder;\nimport org.elasticsearch.client.ElasticsearchClient;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.elasticsearch.search.fetch.source.FetchSourceContext;\nimport org.elasticsearch.threadpool.ThreadPool;\nimport org.nlpcn.es4sql.domain.Select;\nimport org.nlpcn.es4sql.exception.SqlParseException;\nimport org.nlpcn.es4sql.parse.ElasticSqlExprParser;\nimport org.nlpcn.es4sql.parse.SqlParser;\nimport org.nlpcn.es4sql.query.AggregationQueryAction;\nimport org.nlpcn.es4sql.query.DefaultQueryAction;\nimport org.nlpcn.es4sql.query.QueryAction;\nimport org.nlpcn.es4sql.query.SqlElasticRequestBuilder;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport static com.didi.arius.gateway.common.consts.RestConsts.FIELDS;\nimport static com.didi.arius.gateway.common.consts.RestConsts.INDEX;\n\n/**\n* @author weizijun\n* @date：2017年2月13日\n* \n*/\npublic abstract class ESBase {\n\tprotected static final ILog logger = LogFactory.getLog(ESBase.class);\n\t\n\t@Autowired\n\tprotected DslAggsAnalyzerService dslAggsAnalyzerService;\n\t@Autowired\n\tprotected DslAuditService dslAuditService;\n\t@Autowired\n\tprotected DslRewriterService dslRewriterService;\n\n\t@Autowired\n\tprotected IndexTemplateService indexTemplateService;\n\n\tprotected String actionName = this.getClass().getSimpleName();\n\n\n\n\t@Autowired\n\tprotected AppService appService;\n\t\n\tprotected ESGetResponse getVersionResponse(int indexVersion, RestRequest request, ESClient client) {\n        ESMultiGetRequest multiGetRequest = new ESMultiGetRequest();\n        multiGetRequest.refresh(request.param(\"refresh\"));\n        multiGetRequest.preference(request.param(\"preference\"));\n        multiGetRequest.realtime(request.paramAsBoolean(\"realtime\", null));\n        multiGetRequest.ignoreErrorsOnGeneratedFields(request.paramAsBoolean(\"ignore_errors_on_generated_fields\", false));\n\n        String[] sFields = null;\n        String sField = request.param(FIELDS);\n        if (sField != null) {\n            sFields = Strings.splitStringByCommaToArray(sField);\n        }\n\n        FetchSourceContext defaultFetchSource = FetchSourceContext.parseFromRestRequest(request);\n        for (int i = indexVersion; i >= 0; i--) {\n        \tString index = request.param(INDEX);\n        \tif (i > 0) {\n        \t\tindex = request.param(INDEX)+\"_v\"+i;\n        \t}\n\t\t\tESMultiGetRequest.Item item = new ESMultiGetRequest.Item(index, request.param(\"type\"), request.param(\"id\"));\n        \titem.routing(request.param(\"routing\"));\n        \titem.parent(request.param(\"parent\"));\n        \titem.fields(sFields);\n        \titem.fetchSourceContext(defaultFetchSource);\n        \t\n        \tmultiGetRequest.add(item);\n        }\n\n\t\tESMultiGetResponse response = client.multiGet(multiGetRequest).actionGet();\n\n\t\tESGetResponse getResponse = null;\n        for (ESMultiGetResponse.Item item : response.getResponses()) {\n        \tESGetResponse inResponse = item.getResponse();\n        \tif (inResponse == null) {\n        \t\tcontinue;\n        \t}\n        \t\n        \tif (inResponse.isExists()) {\n        \t\tgetResponse = inResponse;\n        \t\tbreak;\n        \t}\n        \t\n        \tgetResponse = inResponse;\n        }\n\n        if (getResponse == null) {\n\t\t\tgetResponse = new ESGetResponse();\n\t\t\tgetResponse.setIndex(request.param(INDEX));\n\t\t\tgetResponse.setType(request.param(\"type\"));\n\t\t\tgetResponse.setId(request.param(\"id\"));\n\t\t\tgetResponse.setExists(false);\n        }\n\n        return getResponse;\n\t}\n\n\tprotected void getVersionResponse(QueryContext queryContext, int indexVersion, String indexName, final RestRequest request, ESClient client, final WrapESGetResponse.ResultType resultType) {\n\t\tESMultiGetRequest multiGetRequest = new ESMultiGetRequest();\n\t\tmultiGetRequest.refresh(request.param(\"refresh\"));\n\t\tmultiGetRequest.preference(request.param(\"preference\"));\n\t\tmultiGetRequest.realtime(request.paramAsBoolean(\"realtime\", null));\n\t\tmultiGetRequest.ignoreErrorsOnGeneratedFields(request.paramAsBoolean(\"ignore_errors_on_generated_fields\", false));\n\n\t\tmultiGetRequest.putHeader(\"requestId\", queryContext.getRequestId());\n\t\tmultiGetRequest.putHeader(\"Authorization\", queryContext.getRequest().getHeader(\"Authorization\"));\n\n\t\tString[] sFields = null;\n\t\tString sField = request.param(FIELDS);\n\t\tif (sField != null) {\n\t\t\tsFields = Strings.splitStringByCommaToArray(sField);\n\t\t}\n\n\t\tFetchSourceContext defaultFetchSource = FetchSourceContext.parseFromRestRequest(request);\n\t\tfor (int i = indexVersion; i >= 0; i--) {\n\t\t\tString index = indexName;\n\t\t\tif (i > 0) {\n\t\t\t\tindex = indexName + \"_v\" + i;\n\t\t\t}\n\t\t\tESMultiGetRequest.Item item = new ESMultiGetRequest.Item(index, request.param(\"type\") == null ? \"_doc\" : request.param(\"type\"), request.param(\"id\"));\n\t\t\titem.routing(request.param(\"routing\"));\n\t\t\titem.parent(request.param(\"parent\"));\n\t\t\titem.fields(sFields);\n\t\t\titem.fetchSourceContext(defaultFetchSource);\n\n\t\t\tmultiGetRequest.add(item);\n\t\t}\n\n\t\tActionListener<ESMultiGetResponse> listener = new RestActionListenerImpl<ESMultiGetResponse>(queryContext) {\n\t\t\t@Override\n\t\t\tpublic void onResponse(ESMultiGetResponse response) {\n\t\t\t\tESGetResponse getResponse = null;\n\t\t\t\tfor (ESMultiGetResponse.Item item : response.getResponses()) {\n\t\t\t\t\tESGetResponse inResponse = item.getResponse();\n\t\t\t\t\tif (inResponse == null) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (inResponse.isExists()) {\n\t\t\t\t\t\tgetResponse = inResponse;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tgetResponse = inResponse;\n\t\t\t\t}\n\n\t\t\t\tif (getResponse == null) {\n\t\t\t\t\tgetResponse = new ESGetResponse();\n\t\t\t\t\tgetResponse.setIndex(request.param(INDEX));\n\t\t\t\t\tgetResponse.setType(request.param(\"type\"));\n\t\t\t\t\tgetResponse.setId(request.param(\"id\"));\n\t\t\t\t\tgetResponse.setExists(false);\n\t\t\t\t}\n\n\t\t\t\tRestActionListenerImpl<ESGetResponse> innerListener = new RestActionListenerImpl<>(queryContext);\n\t\t\t\tswitch (resultType) {\n\t\t\t\t\tcase ALL:\n\t\t\t\t\t\tinnerListener.onResponse(getResponse);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase HEAD:\n\t\t\t\t\t\tif (getResponse.isExists()) {\n\t\t\t\t\t\t\tinnerListener.onResponse(new BytesRestResponse(RestStatus.OK));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinnerListener.onResponse(new BytesRestResponse(RestStatus.NOT_FOUND));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SOURCE:\n\t\t\t\t\t\tif (getResponse.isExists()) {\n\t\t\t\t\t\t\tinnerListener.onResponse(new BytesRestResponse(RestStatus.OK, XContentType.JSON.restContentType(), JSONObject.toJSONString(getResponse.getSource())));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinnerListener.onResponse(new BytesRestResponse(RestStatus.NOT_FOUND));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t}\n\n\t\t\t}\n\t\t};\n\n\t\tclient.multiGet(multiGetRequest, listener);\n\t}\n\n\tprotected MultiGetRequest getVersionRequest(int indexVersion, GetRequest request) {\n        MultiGetRequest multiGetRequest = new MultiGetRequest();\n        multiGetRequest.refresh(request.refresh());\n        multiGetRequest.preference(request.preference());\n        multiGetRequest.realtime(request.realtime());\n        multiGetRequest.ignoreErrorsOnGeneratedFields(request.ignoreErrorsOnGeneratedFields());\n\n        for (int i = indexVersion; i >= 0; i--) {\n        \tString index = request.index();\n        \tif (i > 0) {\n        \t\tindex = request.index()+\"_v\"+i;\n        \t}\n        \tMultiGetRequest.Item item = new MultiGetRequest.Item(index, request.type(), request.id());\n        \titem.routing(request.routing());\n        \titem.fields(request.fields());\n        \titem.fetchSourceContext(request.fetchSourceContext());\n        \t\n        \tmultiGetRequest.add(item);\n        }\n\n        return multiGetRequest;\n\t}\n\n\tprotected FetchFields formFetchFields(SearchRequest searchRequest) {\n\t\tFetchFields fetchFields = new FetchFields();\n\t\tformFetchFields(searchRequest.source(), fetchFields);\n\t\tformFetchFields(searchRequest.extraSource(), fetchFields);\n\t\treturn fetchFields;\n\t}\n\n\tprotected FetchFields formFetchFields(ESSearchRequest esSearchRequest) {\n\t\tFetchFields fetchFields = new FetchFields();\n\t\tformFetchFields(esSearchRequest.source(), fetchFields);\n\t\tformFetchFields(esSearchRequest.extraSource(), fetchFields);\n\n\t\treturn fetchFields;\n\t}\n\t\n\tprivate void formFetchFields(BytesReference source, FetchFields fetchFields) {\n\t\tif (source == null || source.length() == 0) {\n            return ;\n        }\n\t\t\n\t\ttry {\n\t\t\tString sourceStr = XContentHelper.convertToJson(source, true);\n\t\t\tformFetchFields(sourceStr, fetchFields);\n\t\t} catch (IOException e) {\n\t\t\tlogger.warn(\"source_convertToJson_error||source={}||exception={}\", source, Convert.logExceptionStack(e));\n\t\t}\n\t}\n\t\n\tprivate void formFetchFields(String source, FetchFields fetchFields) {\n\t\tif (source == null || source.length() == 0) {\n            return ;\n        }\n        \n    \tJsonParser jsonParser = new JsonParser();\n    \tJsonObject jsonObject = jsonParser.parse(source).getAsJsonObject();\n    \t\n    \tJsonElement sourceContext = jsonObject.get(\"_source\");\n    \t\n    \tif (sourceContext != null) {\n    \t\tFetchSourceContext fetchSourceContext = Convert.parseFetchSourceContext(sourceContext);\n    \t    fetchFields.setFetchSourceContext(fetchSourceContext);\t\n    \t}\n    \t\n    \t\n    \tJsonElement fields = jsonObject.get(FIELDS);\n    \tif (fields != null) {\n    \t\tString[] strFields = Convert.parseFields(fields);\n    \t\tfetchFields.setFields(strFields);\n    \t\t\n    \t\tfor (String field : strFields) {\n    \t\t\tif (field.equals(QueryConsts.MESSAGE_FIELD)) {\n    \t\t\t\tfetchFields.setHasMessageField(true);\n    \t\t\t\tbreak;\n    \t\t\t}\n    \t\t}\n    \t}\n    }\n\n\tprotected String buildSearchIndex(BaseContext context, ESSearchResponse queryResponse) {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tsb.append(QueryConsts.DLFLAG_PREFIX + \"response_index||requestId=\");\n\t\tsb.append(context.getRequestId());\n\n\t\tList<Hit> hits = queryResponse.getHits().getHits();\n\t\tMap<String, Integer> indexCount = new HashMap<>();\n\t\tif (hits != null) {\n\t\t\tfor (Hit hit : hits) {\n\t\t\t\tString index = hit.getIndex();\n\t\t\t\tif (indexCount.containsKey(index)) {\n\t\t\t\t\tindexCount.put(index, indexCount.get(index) + 1);\n\t\t\t\t} else {\n\t\t\t\t\tindexCount.put(index, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tJoinLogContext joinLogContext = context.getJoinLogContext();\n\t\tjoinLogContext.setIndex(JSON.toJSONString(indexCount));\n\n\t\tsb.append(\"||index=\");\n\t\tsb.append(JSON.toJSONString(indexCount));\n\t\treturn sb.toString();\n\t}\n\n\n\tprotected Select parseSql(String sql) throws SqlParseException {\n\t\tif (sql == null || sql.isEmpty()) {\n\t\t\tthrow new InvalidParameterException(\"no SQL content found\");\n\t\t}\n\n\t\tif (!sql.trim().toLowerCase().startsWith(\"select\")) {\n\t\t\tthrow new SQLNotPermittedException(\"gateway only support SELECT SQL\");\n\t\t}\n\n\t\tSQLQueryExpr sqlExpr = (SQLQueryExpr) toSqlExpr(sql);\n\t\tif(isJoin(sqlExpr,sql)){\n\t\t\tthrow new SQLNotPermittedException(\"join SQL not allow\");\n\t\t}\n\n\t\tSelect select = new SqlParser().parseSelect(sqlExpr);\n\t\tif (select.containsSubQueries()) {\n\t\t\tthrow new SQLNotPermittedException(\"subQueries SQL not allow\");\n\t\t}\n\n\t\treturn select;\n\t}\n\n\tprivate boolean isJoin(SQLQueryExpr sqlExpr, String sql) {\n\t\tMySqlSelectQueryBlock query = (MySqlSelectQueryBlock) sqlExpr.getSubQuery().getQuery();\n\t\treturn query.getFrom() instanceof SQLJoinTableSource && sql.toLowerCase().contains(\" join \");\n\t}\n\n\tprivate SQLExpr toSqlExpr(String sql) {\n\t\tSQLExprParser parser = new ElasticSqlExprParser(sql);\n\t\tSQLExpr expr = parser.expr();\n\n\t\tif (parser.getLexer().token() != Token.EOF) {\n\t\t\tthrow new ParserException(\"illegal sql expr : \" + sql);\n\t\t}\n\n\t\treturn expr;\n\t}\n\n\tprotected SqlElasticRequestBuilder buildRequest(String sql) throws SqlParseException {\n\t\tif (sql.endsWith(\";\")) {\n\t\t\tsql = sql.substring(0, sql.length() - 1);\n\t\t}\n\t\tSelect select = parseSql(sql);\n\n\t\tQueryAction queryAction;\n\t\tif (select.isAgg) {\n\t\t\tqueryAction = new AggregationQueryAction(select);\n\t\t} else {\n\t\t\tqueryAction = new DefaultQueryAction(select);\n\t\t}\n\n\t\treturn queryAction.explain(new SearchRequestBuilder(new ElasticsearchClient() {\n\t\t\t@Override\n\t\t\tpublic <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> ActionFuture<Response> execute(Action<Request, Response, RequestBuilder> action, Request request) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void execute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) {\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> RequestBuilder prepareExecute(Action<Request, Response, RequestBuilder> action) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic ThreadPool threadPool() {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}, SearchAction.INSTANCE));\n\t}\n\n\tprotected IndexTemplate getTemplateByIndex(List<String> indices, QueryContext queryContext) {\n        if (indices.size() != 1) {\n            throw new InvalidParameterException(\"index size overflow, you can only search one index, index size=\" + indices.size());\n        }\n\n        String index = indices.get(0);\n        if (index.endsWith(\"*\")) {\n            index = index.substring(0, index.length()-1);\n        }\n\n\t\tIndexTemplate indexTemplate = indexTemplateService.getIndexTemplate(index);\n        if (indexTemplate != null) {\n\t\t\tqueryContext.setIndexTemplate(indexTemplate);\n\t\t}\n\n        return indexTemplate;\n    }\n\n    protected IndexTemplate getTemplateByIndexTire(List<String> indices, QueryContext queryContext) throws IndexNotFoundException, TooManyIndexException{\n\t\tString index = indices.get(0);\n\t\tif(index.startsWith(\".\")) {\n\t\t\t// kibana 有一些请求，是把 .kibana_arius 索引放在请求体里面的，例如 /_mget\n\t\t\tqueryContext.setFromKibana(true);\n\t\t\tqueryContext.setSearchType(AppDetail.RequestType.ORIGIN_CLUSTER.getType());\n\t\t\treturn null;\n\t\t}\n\n        IndexTemplate indexTemplate = indexTemplateService.getIndexTemplateByTire(index);\n        if (indexTemplate == null) {\n        \tString alias = indexTemplateService.getIndexAlias(index);\n        \tif (alias != null) {\n\t\t\t\tindexTemplate = indexTemplateService.getIndexTemplateByTire(alias);\n\t\t\t}\n        }\n\n\t\tif (indexTemplate == null) {\n\t\t\tthrow new IndexNotFoundException(\"query can't find index template exception,index=\" + index);\n\t\t}\n\n        for (int i = 1; i < indices.size(); ++i) {\n            boolean check = IndexTire.checkIndexMatchTemplate(indices.get(i), indexTemplate);\n            if (!check) {\n\t\t\t\tString alias = indexTemplateService.getIndexAlias(indices.get(i));\n\t\t\t\tif (alias != null) {\n\t\t\t\t\tcheck = IndexTire.checkIndexMatchTemplate(alias, indexTemplate);\n\t\t\t\t}\n\t\t\t}\n\n            if (!check) {\n                throw new TooManyIndexException(String.format(\"search query indices don't have the same index template, index1=%s, index2=%s\", index, indices.get(i)));\n            }\n        }\n\n        queryContext.setIndexTemplate(indexTemplate);\n\n        return indexTemplate;\n    }\n\n    protected String[] getQueryIndices(IndexTemplate indexTemplate, String dateFrom, String dateTo) {\n        if (Strings.isEmpty(indexTemplate.getDateFormat()) ||\n\t\t\t\t(Strings.isEmpty(dateFrom) && Strings.isEmpty(dateTo))) {\n            return new String[]{indexTemplate.getExpression()};\n        } else {\n        \tlong end = System.currentTimeMillis();\n\n\t\t\tlong gap = QueryConsts.DAY_MILLIS * (indexTemplate.getExpireTime() <= 0 ? QueryConsts.DEFALUT_INDEX_DAY :  Math.min(indexTemplate.getExpireTime(), QueryConsts.DEFALUT_INDEX_DAY));\n\t\t\tlong start = end - gap;\n\n        \tif (!Strings.isEmpty(dateFrom)) {\n\t\t\t\tstart = DateUtil.transformToMillis(dateFrom);\n\t\t\t}\n\n\t\t\tif (!Strings.isEmpty(dateTo)) {\n\t\t\t\tend = DateUtil.transformToMillis(dateTo);\n\t\t\t}\n\n\t\t\tList<String> suffixes = DateUtil.getDateFormatSuffix(start, end, indexTemplate.getDateFormat());\n\t\t\tinvalidSuffixes(indexTemplate, dateFrom, dateTo, suffixes);\n\n\t\t\tString expression = indexTemplate.getExpression();\n\t\t\texpression = expression.replace(\"*\", \"\");\n\t\t\tString[] newIndices = new String[suffixes.size()];\n\t\t\tint i = 0;\n\t\t\tfor (String suffix : suffixes) {\n\t\t\t\tnewIndices[i] = expression + suffix;\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\treturn newIndices;\n        }\n    }\n\n\tprivate void invalidSuffixes(IndexTemplate indexTemplate, String dateFrom, String dateTo, List<String> suffixes) {\n\t\tif (suffixes.isEmpty()) {\n\t\t\tthrow new InvalidParameterException(String.format(\"time range error, from > end, from=%s, end=%s\", dateFrom, dateTo));\n\t\t}\n\n\t\tif (suffixes.size() > QueryConsts.MAX_INDEX_COUNT) {\n\t\t\tthrow new InvalidParameterException(String.format(\"time range error, get more then %d index, from=%s, end=%s, format=%s\", QueryConsts.MAX_INDEX_COUNT, dateFrom, dateTo, indexTemplate.getDateFormat()));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/HttpRestHandler.java",
    "content": "package com.didi.arius.gateway.core.es.http;\n\nimport static com.didi.arius.gateway.common.consts.RestConsts.SCROLL_SPLIT;\nimport static com.didi.arius.gateway.elasticsearch.client.utils.LogUtils.setWriteLog;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.collections.MapUtils;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.collect.Tuple;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\nimport org.elasticsearch.rest.RestResponse;\nimport org.elasticsearch.rest.support.RestUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.consts.RestConsts;\nimport com.didi.arius.gateway.common.enums.TemplateBlockTypeEnum;\nimport com.didi.arius.gateway.common.exception.FlowLimitException;\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.es.http.action.reindex.RestDeleteByQueryAction;\nimport com.didi.arius.gateway.core.es.http.action.reindex.RestUpdateByQueryAction;\nimport com.didi.arius.gateway.core.es.http.bulk.RestBulkAction;\nimport com.didi.arius.gateway.core.es.http.count.RestCountAction;\nimport com.didi.arius.gateway.core.es.http.document.RestBaseWriteAction;\nimport com.didi.arius.gateway.core.es.http.get.RestBaseGetAction;\nimport com.didi.arius.gateway.core.es.http.get.RestHeadAction;\nimport com.didi.arius.gateway.core.es.http.get.RestMultiGetAction;\nimport com.didi.arius.gateway.core.es.http.search.*;\nimport com.didi.arius.gateway.core.es.http.sql.SQLAction;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.core.service.MetricsService;\nimport com.didi.arius.gateway.core.service.RateLimitService;\nimport com.didi.arius.gateway.core.service.RequestStatsService;\nimport com.didi.arius.gateway.core.service.arius.AppService;\nimport com.didi.arius.gateway.core.service.arius.DynamicConfigService;\nimport com.didi.arius.gateway.core.service.arius.ESClusterService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.response.Failure;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.response.src.Hit;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.google.common.collect.Lists;\n\npublic abstract class HttpRestHandler extends ESBase {\n    protected static final ILog logger = LogFactory.getLog(HttpRestHandler.class);\n    protected static final Logger statLogger = LoggerFactory.getLogger(QueryConsts.STAT_LOGGER);\n\n    @Autowired\n    protected DynamicConfigService dynamicConfigService;\n\n    @Autowired\n    protected RequestStatsService requestStatsService;\n\n    @Autowired\n    protected ESClusterService    esClusterService;\n\n    @Autowired\n    protected ESRestClientService esRestClientService;\n\n    @Autowired\n    protected QueryConfig queryConfig;\n\n    @Autowired\n    protected RateLimitService rateLimitService;\n\n    @Autowired\n    protected MetricsService metricsService;\n\n    @Autowired\n    protected IndexTemplateService indexTemplateService;\n\n    @Autowired\n    protected AppService appService;\n\n    public abstract void handleRequest(QueryContext queryContext) throws Exception;\n\n    public abstract String name();\n\n    protected void checkFlowLimit(QueryContext queryContext) {\n        if (rateLimitService.isTrafficDataOverflow(queryContext.getAppDetail().getId(), queryContext.getSearchId())) {\n            throw new FlowLimitException(\"query flow limit, please try again!\");\n        }\n    }\n\n    protected void checkIndices(QueryContext queryContext) {\n        List<String> indices = queryContext.getIndices();\n        indexTemplateService.checkTemplateExist(indices);\n        appService.checkIndices(queryContext, indices);\n    }\n\n    protected void checkIndicesAndTemplateBlockRead(QueryContext queryContext) {\n        List<String> indices = queryContext.getIndices();\n        indexTemplateService.checkTemplateBlock(indices, queryContext.getAppDetail(), TemplateBlockTypeEnum.READ_BLOCK_TYPE);\n        appService.checkIndices(queryContext, indices);\n    }\n\n    protected boolean isOriginCluster(QueryContext queryContext){\n        return queryContext.getSearchType() == AppDetail.RequestType.ORIGIN_CLUSTER.getType();\n    }\n\n    protected void checkWriteIndicesAndTemplateBlockWrite(QueryContext queryContext) {\n        List<String> indices = queryContext.getIndices();\n        indexTemplateService.checkTemplateBlock(indices, queryContext.getAppDetail(), TemplateBlockTypeEnum.WRITE_WRITE_TYPE);\n        appService.checkWriteIndices(queryContext, indices);\n    }\n\n    protected void logSearchResponse(QueryContext queryContext, ESSearchResponse queryResponse) {\n        if (queryResponse == null) {\n            return ;\n        }\n\n        metricsService.addSearchResponseMetrics(queryContext.getAppid(), queryResponse.getTook(), queryResponse.getHits().getTotal(), queryResponse.getShards().getTotalShard(), queryResponse.getShards().getFailedShard());\n\n        if (queryResponse.getShards().getFailedShard() > 0) {\n            StringBuilder stringBuilder = new StringBuilder(\"search response has some failed,appid=\"+queryContext.getAppid()+\",requestId=\"+queryContext.getRequestId()+\",number=\"+queryResponse.getShards().getFailedShard()+\" reasons:\\n\");\n            int count = 0;\n            for (Failure failure : queryResponse.getShards().getFailures()) {\n                stringBuilder.append(Convert.getPrefix(failure.getReason().getReason()));\n                stringBuilder.append(\"\\n\");\n                count++;\n                if (count > 2) {\n                    stringBuilder.append(\"...\\n\");\n                    break;\n                }\n            }\n            logger.warn(stringBuilder.toString());\n        }\n\n        buildSearchResponseLog(queryContext, queryResponse);\n\n        if (queryResponse.getTook() > queryConfig.getSearchSlowlogThresholdMills()) {\n            buildSearchSlowlog(queryContext, queryResponse);\n        }\n\n        if (queryContext.getAppDetail().isAnalyzeResponseEnable()) {\n            buildSearchIndex(queryContext, queryResponse);\n        }\n\n        if (queryContext.isDetailLog()) {\n            JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n            joinLogContext.setAriusType(\"type\");\n            joinLogContext.setClusterName(queryContext.getClient().getClusterName());\n            joinLogContext.setClientVersion(queryContext.getClient().getEsVersion());\n            joinLogContext.setLogicId(queryContext.getIndexTemplate() != null ? queryContext.getIndexTemplate().getId() : -1);\n            joinLogContext.setTotalCost(System.currentTimeMillis() - queryContext.getRequestTime());\n            joinLogContext.setInternalCost( joinLogContext.getTotalCost() - joinLogContext.getEsCost());\n            joinLogContext.setSinkTime(System.currentTimeMillis());\n            joinLogContext.setSearchCost(System.currentTimeMillis() - queryContext.getPreQueryEsTime());\n            if (queryContext.getIndexTemplate() != null) {\n                joinLogContext.setDestTemplateName(queryContext.getIndexTemplate().getName());\n            }\n        }\n    }\n\n    protected RestActionListenerImpl<ESSearchResponse> newSearchListener(QueryContext queryContext) {\n        queryContext.setPreQueryEsTime(System.currentTimeMillis());\n        return new RestActionListenerImpl<ESSearchResponse>(queryContext) {\n            @Override\n            public void onResponse(ESSearchResponse queryResponse) {\n                statLogger.info(QueryConsts.DLFLAG_PREFIX + \"query_search_query||requestId={}||clusterName={}||logicId={}||cost={}\", queryContext.getRequestId(), queryContext.getClusterName(),\n                        queryContext.getIndexTemplate() != null ? queryContext.getIndexTemplate().getId() : -1, (System.currentTimeMillis()-queryContext.getRequestTime()));\n\n                logSearchResponse(queryContext, queryResponse);\n\n                queryResponse = dealKibanaResponse(queryContext, queryResponse);\n\n                if (!Strings.isEmpty(queryResponse.getScrollId())\n                        && queryContext.getClient() != null\n                        && queryContext.getAppDetail().getSearchType() == AppDetail.RequestType.INDEX) {\n                    String encode = Base64.getEncoder().encodeToString(queryContext.getClient().getClusterName().getBytes());\n                    queryResponse.setScrollId(encode + SCROLL_SPLIT + queryResponse.getScrollId());\n                }\n                super.onResponse(queryResponse);\n            }\n        };\n    }\n\n    protected RestActionListenerImpl<DirectResponse> newDirectSearchListener(QueryContext queryContext) {\n        return new RestActionListenerImpl<DirectResponse>(queryContext) {\n            @Override\n            public void onResponse(DirectResponse response) {\n                try {\n                    XContentParser parser = JsonXContent.jsonXContent.createParser(response.getResponseContent());\n                    ESSearchResponse queryResponse =  ESSearchResponse.fromXContent(parser);\n                    logSearchResponse(queryContext, queryResponse);\n                    queryResponse = dealKibanaResponse(queryContext, queryResponse);\n                    if (!Strings.isEmpty(queryResponse.getScrollId())\n                            && queryContext.getClient() != null\n                            && queryContext.getAppDetail().getSearchType() == AppDetail.RequestType.INDEX) {\n                        String encode = Base64.getEncoder().encodeToString(queryContext.getClient().getClusterName().getBytes());\n                        queryResponse.setScrollId(encode + SCROLL_SPLIT + queryResponse.getScrollId());\n                    }\n                    super.onResponse(response);\n                } catch (Exception e) {\n                    onFailure(e);\n                }\n            }\n        };\n    }\n\n    protected RestActionListenerImpl<DirectResponse> newDirectWriteListener(QueryContext queryContext) {\n        return new RestActionListenerImpl<DirectResponse>(queryContext) {\n            @Override\n            public void onResponse(DirectResponse response) {\n                long currentTime = System.currentTimeMillis();\n                setWriteLog(queryContext, null, response,\n                        currentTime, queryConfig.isWriteLogContentOpen());\n\n                metricsService.addIndexMetrics(null, name(), currentTime - queryContext.getRequestTime(), queryContext.getPostBody().length(), response.getResponseContent().length());\n\n                super.onResponse(response);\n            }\n        };\n    }\n\n    protected void directRequest(ESClient client, QueryContext queryContext) {\n        RestActionListenerImpl<DirectResponse> listener = new RestActionListenerImpl<>(queryContext);\n        if (this instanceof RestSearchAction) {\n            dslAuditService.auditDSL(queryContext, queryContext.getRequest().content(), queryContext.getIndices().toArray(new String[]{}));\n            listener = newDirectSearchListener(queryContext);\n        } else if (this instanceof RestBaseWriteAction) {\n            listener = newDirectWriteListener(queryContext);\n        }\n        directRequest(client, queryContext, listener);\n    }\n\n    protected void directRequest(ESClient client, QueryContext queryContext, DirectRequest directRequest) {\n        RestActionListenerImpl<DirectResponse> listener = new RestActionListenerImpl<>(queryContext);\n        if (this instanceof RestSearchAction) {\n            dslAuditService.auditDSL(queryContext, queryContext.getRequest().content(), queryContext.getIndices().toArray(new String[] {}));\n            listener = newDirectSearchListener(queryContext);\n        } else if (this instanceof RestBaseWriteAction) {\n            listener = newDirectWriteListener(queryContext);\n        }\n        client.direct(directRequest, listener);\n    }\n\n    protected void directRequest(ESClient client, QueryContext queryContext,\n                                 RestActionListenerImpl<DirectResponse> listener) {\n        DirectRequest directRequest = buildDirectRequest(queryContext, queryContext.getUri());\n        client.direct(directRequest, listener);\n    }\n\n    protected DirectRequest buildDirectRequest(QueryContext queryContext, String uri) {\n        String queryString = queryContext.getQueryString() == null ? \"\" : queryContext.getQueryString();\n\n        Map<String, String> paramsMap = new HashMap<>();\n        RestUtils.decodeQueryString(queryString, 0, paramsMap);\n\n        DirectRequest directRequest = new DirectRequest(queryContext.getMethod().toString(), uri);\n        setSocketTimeout(paramsMap, directRequest);\n        directRequest.setPostContent(queryContext.getPostBody());\n        directRequest.setParams(paramsMap);\n\n        directRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        directRequest.putHeader(\"Authorization\", queryContext.getRequest().getHeader(\"Authorization\"));\n        return directRequest;\n    }\n\n    protected void preSearchProcess(QueryContext queryContext, ESClient client, ESSearchRequest esSearchRequest) {\n        String dslTemplateMd5;\n        if (this instanceof SQLAction) {\n            dslTemplateMd5 = dslAuditService.auditSQL(queryContext, queryContext.getPostBody(), esSearchRequest.indices());\n        } else {\n            dslTemplateMd5 = dslAuditService.auditDSL(queryContext, esSearchRequest.source(), esSearchRequest.indices());\n        }\n\n        esSearchRequest.putHeader(RestConsts.DSL_MD5_PARAMS, dslTemplateMd5);\n\n        dslAggsAnalyzerService.analyzeAggs(queryContext, esSearchRequest.source(), esSearchRequest.indices());\n\n        BytesReference source = dslRewriterService.rewriteRequest(queryContext, client.getEsVersion(), esSearchRequest.source());\n        esSearchRequest.source(source);\n\n        setSocketTimeout(esSearchRequest.getParams(), esSearchRequest);\n    }\n\n    protected void sendDirectResponse(QueryContext queryContext, RestResponse restResponse) {\n        RestActionListenerImpl<ESSearchResponse> listener = new RestActionListenerImpl<>(queryContext);\n        listener.onResponse(restResponse);\n    }\n\n    protected ESSearchResponse dealKibanaResponse(QueryContext queryContext, ESSearchResponse queryResponse) {\n        if (queryContext.isNewKibana()) {\n            if (queryContext.getRequest().rawPath().equals(queryConfig.getKibanaSearchUri())) {\n                List<Hit> hitsList = new ArrayList<>();\n                List<Hit> hits = queryResponse.getHits().getHits();\n                for (Hit hit : hits) {\n                    ESSearchResponse queryResponse1 = getEsSearchResponse(queryContext, queryResponse, hitsList, hit);\n                    if (queryResponse1 != null) return queryResponse1;\n                }\n                queryResponse.getHits().setHits(hitsList);\n                return queryResponse;\n            } else {\n                return queryResponse;\n            }\n        } else {\n            return queryResponse;\n        }\n    }\n\n    private ESSearchResponse getEsSearchResponse(QueryContext queryContext, ESSearchResponse queryResponse, List<Hit> hitsList, Hit hit) {\n        try {\n            // kibana索引名称字段为title，过滤出有权限访问的索引\n            if (hit.getId().contains(\"index-pattern\")) {\n                Map<String, String> map = (Map<String, String>) hit.getSource().get(\"index-pattern\");\n                if (indexTemplateService.checkIndex(map.get(\"title\"), queryContext.getAppDetail().getIndexExp())) {\n                    hitsList.add(hit);\n                }\n            } else {\n                return queryResponse;\n            }\n        } catch (Exception e) {\n            return queryResponse;\n        }\n        return null;\n    }\n\n    protected boolean isNeededCheckIndices() {\n        return !isNotCheckAction();\n    }\n\n    private boolean isNotCheckAction() {\n        return this instanceof RestSearchScrollAction\n                || this instanceof RestClearScrollAction\n                || this instanceof RestMultiGetAction\n                || this instanceof RestMultiSearchAction\n                || this instanceof RestBulkAction\n                || this instanceof RestSpatialMultiSearchAction;\n    }\n\n    protected boolean isNeededCheckTemplateSearchBlockAction() {\n        return this instanceof RestBaseGetAction\n                || this instanceof RestCountAction\n                || this instanceof RestHeadAction\n                || this instanceof RestSearchAction\n                || this instanceof RestUpdateByQueryAction\n                || this instanceof RestDeleteByQueryAction;\n    }\n\n    /**\n     * 是否需要替换查询的索引名称\n     *\n     * @param queryContext\n     * @param indexTemplate\n     * @return\n     */\n    public boolean isNeedChangeIndexName(QueryContext queryContext, IndexTemplate indexTemplate) {\n\n        if (Objects.nonNull(indexTemplate) &&\n                Objects.nonNull(indexTemplate.getMasterInfo()) &&\n                MapUtils.isNotEmpty(indexTemplate.getMasterInfo().getTypeIndexMapping())) {\n\n            // 如果该索引启用type名称映射功能，或者该appid是在白名单中的，则需要替换查询的索引名称\n            if (indexTemplate.getMasterInfo().getMappingIndexNameEnable().booleanValue() ||\n                    dynamicConfigService.isWhiteAppid(queryContext.getAppid())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * 替换索引名称的具体实现\n     *\n     * @param queryContext\n     * @param indexTemplate\n     * @param sourceIndexNames\n     * @param types\n     * @return\n     */\n    public Tuple<IndexTemplate/*dest template*/, String[]/*dest indexNames*/> handleChangeIndexName(QueryContext queryContext, IndexTemplate indexTemplate, String[] sourceIndexNames, String[] types) {\n        String sourceTemplateName = indexTemplate.getName();\n        List<String> indexList = Lists.newArrayList();\n        String destTemplateName = null;\n        Map<String/*typeName*/,String/*templateName*/> typeIndexMapping = indexTemplate.getMasterInfo().getTypeIndexMapping();\n\n        // 用户不指定type方式查询时，gateway需要将该多type索引映射为多个单type索引，然后转发到es，数据聚合功能由es完成。例如 GET indexName/_search  改写为  GET type1@indexName,type2@indexName/_search\n        if (Objects.isNull(types) || types.length == 0) {\n            for (String name : typeIndexMapping.values()) {\n                destTemplateName = name;\n                for (String indexName : sourceIndexNames) {\n                    indexList.add(indexName.replaceAll(sourceTemplateName, destTemplateName));\n                }\n            }\n\n        } else {\n            // 用户指定type方式查询时，gateway需要将该多type索引和指定的type名称映射为对应的单type索引，然后转发到es。例如GET indexName/type1/_search   改写为 GET type1@indexName/type1/_search。\n            String typeName = types[0];\n            destTemplateName = typeIndexMapping.get(typeName);\n            if (StringUtils.isNoneBlank(destTemplateName)) {\n                String name = destTemplateName;\n                indexList = Arrays.asList(sourceIndexNames).stream().map(item -> item.replaceAll(sourceTemplateName, name)).collect(Collectors.toList());\n            } else {\n                // 找不到type对应的索引名称时，使用原索引\n                destTemplateName = sourceTemplateName;\n                indexList = Arrays.asList(sourceIndexNames);\n            }\n        }\n\n        // 替换查询语句中的索引名称\n        String[] destIndexName = indexList.toArray(new String[]{});\n        // 再替换索引模板对象\n        IndexTemplate destIndexTemplate = indexTemplateService.getIndexTemplate(destTemplateName);\n\n        if (queryContext.isDetailLog()) {\n            JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n            joinLogContext.setSourceIndexNames(StringUtils.join(sourceIndexNames, \",\"));\n            joinLogContext.setTypeName(StringUtils.join(types, \",\"));\n            joinLogContext.setDestIndexName(StringUtils.join(destIndexName, \",\"));\n            joinLogContext.setSourceTemplateName(sourceTemplateName);\n            joinLogContext.setDestTemplateName(destTemplateName);\n        }\n\n        return new Tuple<>(destIndexTemplate, destIndexName);\n    }\n\n    /************************************************************** private method **************************************************************/\n    protected void buildSearchSlowlog(QueryContext queryContext, ESSearchResponse queryResponse) {\n        JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n        joinLogContext.setEsCost(queryResponse.getTook());\n        joinLogContext.setScrollId(queryResponse.getScrollId());\n        joinLogContext.setTotalShards(queryResponse.getShards().getTotalShard());\n        joinLogContext.setFailedShards(queryResponse.getShards().getFailedShard());\n        joinLogContext.setIsTimedOut(queryResponse.getTimeOut());\n        joinLogContext.setTotalHits(queryResponse.getHits().getTotal());\n    }\n\n    protected void buildSearchResponseLog(QueryContext queryContext, ESSearchResponse queryResponse) {\n        JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n        joinLogContext.setEsCost(queryResponse.getTook());\n        joinLogContext.setScrollId(queryResponse.getScrollId());\n        joinLogContext.setTotalShards(queryResponse.getShards().getTotalShard());\n        joinLogContext.setFailedShards(queryResponse.getShards().getFailedShard());\n        joinLogContext.setIsTimedOut(queryResponse.getTimeOut());\n        joinLogContext.setTotalHits(queryResponse.getHits().getTotal());\n    }\n\n    private void setSocketTimeout(Map<String, String> params, ESActionRequest request) {\n        if (params.containsKey(RestConsts.SOCKET_TIMEOUT_PARAMS)) {\n            String strSocketTimeout = params.remove(RestConsts.SOCKET_TIMEOUT_PARAMS);\n            try {\n                int socketTimeout = Integer.parseInt(strSocketTimeout);\n                if (socketTimeout > 0 && socketTimeout <= QueryConsts.MAX_SOCKET_TIMEOUT) {\n                    request.setSocketTimeout(socketTimeout);\n                }\n            } catch (Exception e) {\n                // pass\n            }\n        }\n    }\n\n    protected void handleOriginClusterRequest(QueryContext queryContext){\n        logger.info(\"handleOriginClusterRequest||uri={}||indices={}\", queryContext.getUri(),queryContext.getIndices());\n\n        ESClient client = esClusterService.getClient(queryContext, actionName);\n        directRequest(client, queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/RestActionListenerImpl.java",
    "content": "package com.didi.arius.gateway.core.es.http;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.event.QueryPostResponseEvent;\nimport com.didi.arius.gateway.common.exception.ResponseTooLargeException;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.CommonUtil;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.component.SpringTool;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.log.LogGather;\nimport org.apache.http.util.EntityUtils;\nimport org.elasticsearch.ExceptionsHelper;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.client.Response;\nimport org.elasticsearch.client.ResponseException;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.common.xcontent.json.JsonXContent;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestResponse;\nimport org.elasticsearch.rest.RestStatus;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class RestActionListenerImpl<T extends ESActionResponse> implements ActionListener<T> {\n\tprotected static final ILog logger = LogFactory.getLog(RestActionListenerImpl.class);\n\tprotected static final Logger statLogger = LoggerFactory.getLogger(QueryConsts.STAT_LOGGER);\n\tprotected static final ILog traceLogger = LogFactory.getLog(QueryConsts.TRACE_LOGGER);\n\tprotected static final String ERROR = \"error\";\n\t\n\tprotected QueryContext queryContext;\n\t\n\tpublic RestActionListenerImpl(QueryContext queryContext) {\n\t\tthis.queryContext = queryContext;\n\t}\n\n\tpublic void onResponse(RestResponse restResponse) {\n\n\t\tif (queryContext.getRequest().method() == RestRequest.Method.HEAD) {\n\t\t\trestResponse = new BytesRestResponse(restResponse.status());\n\t\t}\n\n\t\tif (restResponse.content() != null && restResponse.content().length() > queryContext.getMaxHttpResponseLength()) {\n\t\t\tthrow new ResponseTooLargeException(String.format(\"response length(%d) > %d exception\", restResponse.content().length(), queryContext.getMaxHttpResponseLength()));\n\t\t}\n\n\t\tqueryContext.setResponse(restResponse);\n\t\tpostResponse(queryContext);\n\n\t\tqueryContext.getChannel().sendResponse(restResponse);\n\t}\n\t\n\t@Override\n\tpublic void onResponse(T response) {\n\n\t\tRestResponse restResponse;\n\t\tif(response.getHost() != null) {\n\t\t\tqueryContext.getJoinLogContext().setClientNode(response.getHost().getHostName() + \":\" + response.getHost().getPort());\n\t\t}\n\t\tif (queryContext.getRequest().method() == RestRequest.Method.HEAD) {\n\t\t\trestResponse = new BytesRestResponse(response.getRestStatus());\n\t\t} else {\n\t\t\trestResponse = response.buildRestResponse(queryContext.getChannel());\n\n\t\t\tif (restResponse.content() != null && restResponse.content().length() > queryContext.getMaxHttpResponseLength()) {\n\t\t\t\tthrow new ResponseTooLargeException(String.format(\"response length(%d) > %d exception\", restResponse.content().length(), queryContext.getMaxHttpResponseLength()));\n\t\t\t}\n\t\t}\n\n\t\tqueryContext.setResponse(restResponse);\n\t\tpostResponse(queryContext);\n\n\t\tqueryContext.getChannel().sendResponse(restResponse);\n\t}\n\n\t@Override\n\tpublic void onFailure(Throwable e) {\n\n\t\ttry {\n\t\t\tRestResponse restResponse;\n\t\t\tif (e instanceof ResponseException) {\n\t\t\t\tResponseException responseException = (ResponseException) e;\n\t\t\t\tResponse response = responseException.getResponse();\n\t\t\t\tint statusCode = response.getStatusLine().getStatusCode();\n\n\t\t\t\tif (queryContext.getRequest().method() == RestRequest.Method.HEAD) {\n\t\t\t\t\trestResponse = new BytesRestResponse( CommonUtil.fromCode(statusCode));\n\t\t\t\t} else {\n\t\t\t\t\tString responseBody = EntityUtils.toString(response.getEntity());\n\t\t\t\t\trestResponse = new BytesRestResponse(CommonUtil.fromCode(statusCode), XContentType.JSON.restContentType(), responseBody);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (queryContext.getRequest().method() == RestRequest.Method.HEAD) {\n\t\t\t\t\trestResponse = new BytesRestResponse(ExceptionsHelper.status(e));\n\t\t\t\t} else {\n\t\t\t\t\trestResponse = new BytesRestResponse(queryContext.getChannel(), e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpostResponse(queryContext, e);\n\n\t\t\tqueryContext.getChannel().sendResponse(restResponse);\n\t\t} catch (Exception ioe) {\n\t\t\tBytesRestResponse response = new BytesRestResponse(RestStatus.INTERNAL_SERVER_ERROR, XContentType.JSON.restContentType(), \"{\\\"error\\\":\\\"unknown\\\"}\");\n\t\t\tqueryContext.getChannel().sendResponse(response);\n\t\t}finally {\n\t\t\tif (queryContext.isDetailLog()) {\n\t\t\t\tJoinLogContext joinLogContext = queryContext.getJoinLogContext();\n\t\t\t\tjoinLogContext.setAriusType(ERROR);\n\t\t\t\tif (queryContext.getClient() != null) {\n\t\t\t\t\tjoinLogContext.setClusterName(queryContext.getClient().getClusterName());\n\t\t\t\t\tjoinLogContext.setClientVersion(queryContext.getClient().getEsVersion());\n\t\t\t\t}\n\t\t\t\tjoinLogContext.setLogicId(queryContext.getIndexTemplate() != null ? queryContext.getIndexTemplate().getId() : -1);\n\t\t\t\tjoinLogContext.setTotalCost(System.currentTimeMillis() - queryContext.getRequestTime());\n\t\t\t\tjoinLogContext.setInternalCost( joinLogContext.getTotalCost() - joinLogContext.getEsCost());\n\t\t\t\tjoinLogContext.setSinkTime(System.currentTimeMillis());\n\t\t\t\tString log = joinLogContext.toString();\n\n\t\t\t\tstatLogger.error(log);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void postResponse(QueryContext queryContext) {\n\n        SpringTool.publish(new QueryPostResponseEvent(this, queryContext));\n\n\t\tqueryContext.setResponseTime(System.currentTimeMillis());\n\n\t\tint responseBodyLen = queryContext.getResponse() != null ? queryContext.getResponse().content().length() : 0;\n\t\tint status = queryContext.getResponse() != null && queryContext.getResponse().status() != null ? queryContext.getResponse().status().getStatus() : -1;\n\n\t\tif (queryContext.isDetailLog()) {\n\t\t\tJoinLogContext joinLogContext = queryContext.getJoinLogContext();\n\t\t\tjoinLogContext.setStatus(status);\n\t\t\tjoinLogContext.setResponseLen(responseBodyLen);\n\t\t\tString log = joinLogContext.toString();\n\t\t\tstatLogger.info(log);\n\n\t\t\ttraceLogger.info(\"_com_request_out||traceid={}||spanid={}||type=http||appid={}||requestId={}||uri={}||responseLen={}||status={}||proc_time={}\",\n\t\t\t\t\tqueryContext.getTraceid(), queryContext.getSpanid(), queryContext.getAppid(), queryContext.getRequestId(), queryContext.getUri(), responseBodyLen, status, queryContext.getCostTime());\n\t\t} else {\n\t\t\tLogGather.recordInfoLog(QueryConsts.DLFLAG_PREFIX + \"query_response_\" + queryContext.getAppid() + \"_\" + queryContext.getRestName(), String.format(\n\t\t\t\t\t\"requestId=%s||uri=%s||cost=%d||status=%d||responseLen=%d\", queryContext.getRequestId(), queryContext.getUri(), queryContext.getCostTime(), status, responseBodyLen\n\t\t\t));\n\t\t}\n\n\t}\n\n\tprotected void postResponse(QueryContext queryContext, Throwable e) {\n        SpringTool.publish(new QueryPostResponseEvent(this, queryContext));\n\n\t\tif (queryContext.isDetailLog()) {\n\t\t\tJoinLogContext joinLogContext = queryContext.getJoinLogContext();\n\t\t\tjoinLogContext.setExceptionName(e.getClass().getName());\n\t\t\tjoinLogContext.setStack(Convert.logExceptionStack(e));\n\n\t\t\ttraceLogger.info(\"_com_request_out||traceid={}||spanid={}||type=http||appid={}||requestId={}||errname={}\",\n\t\t\t\t\tqueryContext.getTraceid(), queryContext.getSpanid(), queryContext.getAppid(), queryContext.getRequestId(), e.getClass().getName());\n\t\t} else {\n\t\t\tLogGather.recordErrorLog(e.getClass().getName() + \"_\" + queryContext.getAppid(), String.format(\"http_exception||requestId=%s||appid=%d||uri=%s||postBody=%s\",\n\t\t\t\t\tqueryContext.getRequestId(), queryContext.getAppid(), queryContext.getUri(), queryContext.getPostBody()), e);\n\t\t}\n\n\t}\n\n\tprotected String exceptionToJsonString(Throwable t) {\n\t\ttry {\n\t\t\tif (t instanceof ResponseException) {\n\t\t\t\tResponseException responseException = (ResponseException) t;\n\t\t\t\tResponse response = responseException.getResponse();\n\t\t\t\treturn EntityUtils.toString(response.getEntity());\n\t\t\t} else {\n\t\t\t\tXContentBuilder builder = JsonXContent.contentBuilder().startObject();\n\t\t\t\tif (t == null) {\n\t\t\t\t\tbuilder.field(ERROR, \"unknown\");\n\t\t\t\t} else {\n\t\t\t\t\tbuilder.field(ERROR, t.getMessage());\n\t\t\t\t}\n\t\t\t\tbuilder.field(\"status\", RestStatus.INTERNAL_SERVER_ERROR);\n\t\t\t\tbuilder.endObject();\n\n\t\t\t\treturn builder.bytes().toUtf8();\n\t\t\t}\n\t\t} catch (Exception ioe) {\n\t\t\treturn \"{\\\"error\\\":{}}\";\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/StatAction.java",
    "content": "package com.didi.arius.gateway.core.es.http;\n\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\n\nimport java.util.List;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n/**\n* @author weizijun\n* @date：2016年8月25日\n* \n*/\npublic abstract class StatAction extends HttpRestHandler {\n\n\t@Override\n\tpublic void handleRequest(QueryContext queryContext) throws Exception {\n\n\t\tESClient client = esClusterService.getClient(queryContext, actionName);\n\n\t\tif (isOriginCluster(queryContext)) {\n\t\t\thandleOriginClusterRequest(queryContext);\n\t\t} else {\n\t\t\tif (queryContext.getRequest().param(\"index\") != null) {\n\t\t\t\tString index = queryContext.getRequest().param(\"index\");\n\t\t\t\tString[] indicesArr = Strings.splitStringByCommaToArray(index);\n\t\t\t\tList<String> indicesList = Lists.newArrayList(indicesArr);\n\t\t\t\tqueryContext.setIndices(indicesList);\n\n\t\t\t\tcheckIndices(queryContext);\n\n\t\t\t\tif (isIndexType(queryContext)) {\n\t\t\t\t\tIndexTemplate indexTemplate = getTemplateByIndexTire(indicesList, queryContext);\n\n\t\t\t\t\tclient = esClusterService.getClient(queryContext, indexTemplate, actionName);\n\t\t\t\t}\n\t\t\t}\n\t\t\thandleInterRequest(queryContext, queryContext.getRequest(), queryContext.getChannel(), client);\n\t\t}\n\t}\n\n\tprotected abstract void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/action/RestCommonAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.action;\n\nimport java.util.List;\n\nimport com.didi.arius.gateway.common.exception.AccessForbiddenException;\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.AppUtil;\nimport com.didi.arius.gateway.core.es.http.HttpRestHandler;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.common.Strings;\nimport org.springframework.stereotype.Component;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n@Component(\"restCommonAction\")\npublic class RestCommonAction extends HttpRestHandler {\n\n    @Override\n    public String name() {\n        return \"common\";\n    }\n\n    @Override\n    public void handleRequest(QueryContext queryContext) throws Exception {\n        if (isOriginCluster(queryContext)) {\n            handleOriginClusterRequest(queryContext);\n        } else {\n            handleInterRequest(queryContext);\n        }\n    }\n\n    public void handleInterRequest(QueryContext queryContext) throws Exception {\n        String uri = queryContext.getUri();\n        String[] uriUnit = Strings.splitStringToArray(uri, '/');\n        if (uriUnit.length <= 0) {\n            throw new InvalidParameterException(\"uri(\" + uri + \") error\");\n        }\n\n        ESClient client = esClusterService.getClient(queryContext, actionName);\n\n        if (queryContext.getRequest().param(\"index\") != null) {\n            String index = queryContext.getRequest().param(\"index\");\n            String[] indicesArr = Strings.splitStringByCommaToArray(index);\n            List<String> indices = Lists.newArrayList(indicesArr);\n            queryContext.setIndices(indices);\n\n            checkIndices(queryContext);\n\n            if (isIndexType(queryContext)) {\n                IndexTemplate indexTemplate = getTemplateByIndexTire(indices, queryContext);\n\n                client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n            }\n        } else if (!AppUtil.isAdminAppid(queryContext.getAppDetail())\n                && !queryContext.isFromKibana()) {\n            throw new AccessForbiddenException(\"action(\" + queryContext.getUri() + \") forbidden\");\n        }\n\n        directRequest(client, queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/action/RestMainAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.action;\n\nimport com.didi.arius.gateway.common.consts.RestConsts;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.StatAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.Build;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\nimport static org.elasticsearch.rest.RestRequest.Method.HEAD;\n\n/**\n* @author weizijun\n* @date：2016年8月28日\n* \n*/\n@Component(\"restMainAction\")\npublic class RestMainAction extends StatAction {\n\n\t@Override\n\tpublic String name() {\n\t\treturn \"main\";\n\t}\n\n\t@Value(\"${gateway.cluster.name}\")\n\tprivate String gatewayClusterName;\n\n\tpublic RestMainAction() {\n\t\t// pass\n\t}\n\n\t@Override\n\tpublic void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n\t\t\n        RestStatus status = RestStatus.OK;\n\n\t\tif (request.method() == HEAD) {\n\t\t\tsendDirectResponse(queryContext, new BytesRestResponse(status));\n\t\t} else {\n\t\t\ttry (XContentBuilder builder = channel.newBuilder()) {\n\t\t\t\t// Default to pretty printing, but allow ?pretty=false to disable\n\t\t\t\tif (!request.hasParam(\"pretty\")) {\n\t\t\t\t\tbuilder.prettyPrint().lfAtEnd();\n\t\t\t\t}\n\n\t\t\t\tbuilder.startObject();\n\t\t\t\tbuilder.field(\"name\", \"elasticsearch gateway \" + RestConsts.GATEWAY_VERSION);\n\t\t\t\tbuilder.field(\"cluster_name\", null != client ? client.getClusterName() : gatewayClusterName);\n\t\t\t\tbuilder.startObject(\"version\")\n\t\t\t\t\t\t.field(\"number\", null != client ? client.getEsVersion() : \"6.6.1\")\n\t\t\t\t\t\t.field(\"build_hash\", Build.CURRENT.hash())\n\t\t\t\t\t\t.field(\"build_timestamp\", Build.CURRENT.timestamp())\n\t\t\t\t\t\t.field(\"build_snapshot\", false)\n\t\t\t\t\t\t.field(\"lucene_version\", \"7.6.0\")\n\t\t\t\t\t\t.endObject();\n\t\t\t\tbuilder.field(\"tagline\", \"You Know, for Search\");\n\t\t\t\tbuilder.endObject();\n\n\t\t\t\tsendDirectResponse(queryContext, new BytesRestResponse(status, builder));\n\t\t\t}\n\t\t}\n        \n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/action/admin/cluster/health/RestClusterHealthAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.action.admin.cluster.health;\n\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.StatAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n/**\n *\n */\n@Component\npublic class RestClusterHealthAction extends StatAction {\n\n    @Override\n    public String name() {\n        return \"restClusterHealth\";\n    }\n\n    public RestClusterHealthAction() {\n        // pass\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client)\n            throws Exception {\n        String index = request.param(\"index\");\n        if (index != null && isIndexType(queryContext)) {\n            // 如果查询指定索引的健康状态\n            String[] indicesArr = Strings.splitStringByCommaToArray(request.param(\"index\"));\n            List<String> indices = Lists.newArrayList(indicesArr);\n            IndexTemplate indexTemplate = getTemplateByIndexTire(indices, queryContext);\n            // 根据索引模版找到对应的集群client\n            client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n        }\n\n\n        if (client == null) {\n            // 找到根据appid关联的集群的client\n            client = esClusterService.getClient(queryContext, actionName);\n        }\n\n        if(client == null) {\n            // 使用默认的集群的client\n            client = esRestClientService.getAdminClient(actionName);\n        }\n\n        directRequest(client, queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/action/admin/cluster/node/info/RestNodesInfoAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.action.admin.cluster.node.info;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.core.es.http.StatAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectResponse;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Component;\n\n\n/**\n *\n */\n@Component(\"restNodesInfoAction\")\npublic class RestNodesInfoAction extends StatAction {\n\n\t@Override\n\tpublic String name() {\n\t\treturn \"restNodesInfo\";\n\t}\n\n\tprivate BytesRestResponse bytesRestResponse = null;\n\t\n\tprivate long cacheTime = 0;\n\t\n\tprivate static final long CACHE_MILLIS = 60000;\n\n\n    @Override\n\tprotected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client)\n\t\t\tthrows Exception {\n        // cache\n        if (request.rawPath().equals(\"/_nodes\")) {\n            if (queryContext.isFromKibana()) {\n                client = esRestClientService.getAdminClient(actionName);\n            }\n\n        \tlong now = System.currentTimeMillis();\n        \tif (now - cacheTime > CACHE_MILLIS) {\n                directRequest(client, queryContext, new RestActionListenerImpl<DirectResponse>(queryContext) {\n                    @Override\n                    public void onResponse(DirectResponse response) {\n                        bytesRestResponse = new BytesRestResponse(RestStatus.OK, XContentType.JSON.restContentType(), response.getResponseContent());\n                        super.onResponse(response);\n                        cacheTime = now;\n                    }\n                });\n        \t} else {\n                sendDirectResponse(queryContext, bytesRestResponse);\n        \t}\n        } else if (request.rawPath().equals(\"/_nodesclean\")) {\n            sendDirectResponse(queryContext, bytesRestResponse);\n\n            bytesRestResponse = null;\n        \tcacheTime = 0;\n        } else {\n        \tdirectRequest(client, queryContext);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/action/cat/RestIndicesAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.action.cat;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.StatAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Component;\n\n@Component(\"restIndicesAction\")\npublic class RestIndicesAction extends StatAction {\n\n\t@Override\n\tpublic String name() {\n\t\treturn \"restIndices\";\n\t}\n\t\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client)\n            throws Exception {\n        final String[] indices = Strings.splitStringByCommaToArray(request.param(\"index\"));\n        boolean allIndices = false;\n        if (indices.length == 0) {\n        \tallIndices = true;\n        }\n        \n        for (String index : indices) {\n        \tif (index.trim().equals(\"*\")) {\n        \t\tallIndices = true;\n        \t\tbreak;\n        \t}\n        }\n        \n        if (allIndices) {\n            sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, \"not support!\"));\n        } else if (request.hasParam(\"h\") && request.param(\"h\").equals(\"i\")){\n            // 用户控制台直接获取索引列表\n            StringBuilder builder = new StringBuilder();\n            for (String index : indices) {\n                builder.append(index);\n                builder.append(\"\\n\");\n            }\n\n            sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, builder.toString()));\n        } else {\n            directRequest(client, queryContext);\n        }\n\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/action/fieldstats/RestFieldStatsAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.action.fieldstats;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.CommonUtil;\nimport com.didi.arius.gateway.core.es.http.StatAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n */\n@Component\npublic class RestFieldStatsAction extends StatAction {\n\n    public static final String INDEX = \"index\";\n\n    @Override\n    public String name() {\n        return \"restFieldStats\";\n    }\n\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client)\n            throws Exception {\n        if (CommonUtil.isIndexType(queryContext)) {\n            String[]  indicesArr = Strings.splitStringByCommaToArray(request.param(INDEX));\n            List<String> indices = Lists.newArrayList(indicesArr);\n            IndexTemplate indexTemplate = getTemplateByIndexTire(indices, queryContext);\n\n            client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n        }\n\n        if (CommonUtil.isSearchKibana(queryContext.getUri(), queryContext.getIndices())) {\n            sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, XContentType.JSON.restContentType(), \"{\\\"_shards\\\":{\\\"total\\\":0,\\\"successful\\\":0,\\\"failed\\\":0},\\\"indices\\\":{}}\"));\n        } else if ( queryContext.isFromKibana()\n                && !queryContext.isNewKibana()\n                && !client.getEsVersion().startsWith(QueryConsts.ES_VERSION_2_PREFIX)\n                && request.param(INDEX) != null\n                && request.param(\"level\") != null && request.param(\"level\").equals(\"indices\")) {\n\n            // for kibana\n            String index = request.param(INDEX);\n\n            String timeStamp = \"\";\n            try {\n                JSONObject source = JSON.parseObject(queryContext.getPostBody());\n                JSONArray fields = source.getJSONArray(\"fields\");\n                timeStamp = fields.getString(0);\n            } catch (Exception e) {\n                logger.info(\"source parse error, souce={}\", queryContext.getPostBody());\n            }\n\n            String result = String.format(\"{\\n\" +\n                    \"  \\\"_shards\\\": {\\n\" +\n                    \"    \\\"total\\\": 1,\\n\" +\n                    \"    \\\"successful\\\": 1,\\n\" +\n                    \"    \\\"failed\\\": 0\\n\" +\n                    \"  },\\n\" +\n                    \"  \\\"indices\\\": {\\n\" +\n                    \"    \\\"%s\\\": {\\n\" +\n                    \"      \\\"fields\\\": {\\n\" +\n                    \"        \\\"%s\\\": {\\n\" +\n                    \"          \\\"max_doc\\\": 1,\\n\" +\n                    \"          \\\"doc_count\\\": 1,\\n\" +\n                    \"          \\\"density\\\": 1,\\n\" +\n                    \"          \\\"sum_doc_freq\\\": 1,\\n\" +\n                    \"          \\\"sum_total_term_freq\\\": -1,\\n\" +\n                    \"          \\\"min_value\\\": 1,\\n\" +\n                    \"          \\\"min_value_as_string\\\": \\\"1970-03-03 16:00:00 +0000\\\",\\n\" +\n                    \"          \\\"max_value\\\": 33108537600000,\\n\" +\n                    \"          \\\"max_value_as_string\\\": \\\"3019-03-04 00:00:00 +0000\\\"\\n\" +\n                    \"        }\\n\" +\n                    \"      }\\n\" +\n                    \"    }\\n\" +\n                    \"  }\\n\" +\n                    \"}\", index, timeStamp);\n\n            sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, XContentType.JSON.restContentType(), result));\n        } else {\n            directRequest(client, queryContext);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/action/reindex/RestDeleteByQueryAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.action.reindex;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restDeleteByQueryAction 给普通账号\n */\n@Component(\"restDeleteByQueryAction\")\npublic class RestDeleteByQueryAction extends ESAction {\n\n    @Override\n    public String name() {\n        return \"restDeleteByQueryAction\";\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String deleteQueryIndex = queryContext.getRequest().param(\"index\");\n\n        if (StringUtils.isNotBlank(deleteQueryIndex)) {\n            indexAction(queryContext, deleteQueryIndex, \"/_delete_by_query\");\n        } else {\n            throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/action/reindex/RestUpdateByQueryAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.action.reindex;\n\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restUpdateByQueryAction 给普通账号\n */\n@Component(\"restUpdateByQueryAction\")\npublic class RestUpdateByQueryAction extends ESAction {\n\n    @Override\n    public String name() {\n        return \"restUpdateByQueryAction\";\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String updateByQueryIndex = queryContext.getRequest().param(\"index\");\n\n        if (StringUtils.isNotBlank(updateByQueryIndex)) {\n            indexAction(queryContext, updateByQueryIndex, \"/_update_by_query\");\n        } else {\n            throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/RestAnalyzeAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restAnalyzeAction 给普通账号\n */\n@Component(\"restAnalyzeAction\")\npublic class RestAnalyzeAction extends ESAction {\n\n    @Override\n    public String name() {\n        return \"restAnalyzeAction\";\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String analyzeIndex = queryContext.getRequest().param(\"index\");\n\n        if (StringUtils.isNotBlank(analyzeIndex)) {\n            indexAction(queryContext, analyzeIndex);\n        } else {\n            throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/RestCheckMappingAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restCheckMappingAction 给普通账号\n */\n@Component(\"restCheckMappingAction\")\npublic class RestCheckMappingAction extends ESAction {\n\n    @Override\n    public String name() {\n        return \"restCheckMappingAction\";\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String checkMappingIndex = queryContext.getRequest().param(\"index\");\n\n        if (StringUtils.isNotBlank(checkMappingIndex)) {\n            indexAction(queryContext, checkMappingIndex);\n        } else {\n            throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/RestGetAliasesAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restGetAliasesAction 给普通账号\n */\n@Component(\"restGetAliasesAction\")\npublic class RestGetAliasesAction extends ESAction {\n\n    @Override\n    public String name() {\n        return \"restGetAliasesAction\";\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String checkAliasIndex = queryContext.getRequest().param(\"index\");\n\n        if (StringUtils.isNotBlank(checkAliasIndex)) {\n            indexAction(queryContext, checkAliasIndex);\n        } else {\n            throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/RestIndexDeleteAliasesAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restIndexDeleteAliasesAction 给普通账号\n */\n@Component(\"restIndexDeleteAliasesAction\")\npublic class RestIndexDeleteAliasesAction extends ESAction {\n\n\n    @Override\n    public String name() {\n        return \"restIndexDeleteAliasesAction\";\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String index = queryContext.getRequest().param(\"index\");\n        String name = queryContext.getRequest().param(\"name\");\n\n        if (StringUtils.isNotBlank(index)) {\n            String[] indicesArr = Strings.splitStringByCommaToArray(index);\n            List<String> deleteAliasIndices = Lists.newArrayList(indicesArr);\n            queryContext.setIndices(deleteAliasIndices);\n            checkIndices(queryContext);\n\n            IndexTemplate indexTemplate = getTemplateByIndexTire(deleteAliasIndices, queryContext);\n\n            if (!indexTemplateService.delTemplateAlias(queryContext.getAppid(), indexTemplate.getId(), indexTemplate.getName(), name)) {\n                throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n            }\n\n            ESClient client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n\n            directRequest(client, queryContext);\n        } else {\n            throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/RestIndexPutAliasAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restIndexPutAliasAction 给普通账号\n * 给索引设置别名的时候需要同步的给admin的索引模板也设置下别名，这样通过别名查询的时候就有权限了\n */\n@Component(\"restIndexPutAliasAction\")\npublic class RestIndexPutAliasAction extends ESAction {\n\n    @Override\n    public String name() {\n        return \"restIndexPutAliasAction\";\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String index = queryContext.getRequest().param(\"index\");\n        String name = queryContext.getRequest().param(\"name\");\n\n        if (StringUtils.isNotBlank(index)) {\n            String[] indicesArr = Strings.splitStringByCommaToArray(index);\n            List<String> aliasIndices = Lists.newArrayList(indicesArr);\n            queryContext.setIndices(aliasIndices);\n            checkIndices(queryContext);\n\n            IndexTemplate indexTemplate = getTemplateByIndexTire(aliasIndices, queryContext);\n\n            if (!indexTemplateService.addTemplateAlias(queryContext.getAppid(), indexTemplate.getId(), indexTemplate.getName(), name)) {\n                throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n            }\n\n            ESClient client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n\n            directRequest(client, queryContext);\n        } else {\n            throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/RestPutMappingAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restPutMappingAction 给普通账号\n */\n@Component(\"restPutMappingAction\")\npublic class RestPutMappingAction extends ESAction {\n\n    @Override\n    public String name() {\n        return \"restPutMappingAction\";\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String putMappingIndex = queryContext.getRequest().param(\"index\");\n\n        if (StringUtils.isNotBlank(putMappingIndex)) {\n            indexAction(queryContext, putMappingIndex);\n        } else {\n            throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/RestRefreshAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restRefreshAction 给普通账号\n */\n@Component(\"restRefreshAction\")\npublic class RestRefreshAction extends ESAction {\n\n    @Override\n    public String name() {\n        return \"restRefreshAction\";\n    }\n\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String refreshIndex = queryContext.getRequest().param(\"index\");\n\n        if (StringUtils.isNotBlank(refreshIndex)) {\n            indexAction(queryContext, refreshIndex);\n        } else {\n            throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/create/RestCreateIndexAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices.create;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n@Component(\"restCreateIndexAction\")\npublic class RestCreateIndexAction extends ESAction {\n\n    public static final String NAME = \"restCreateIndex\";\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String index = queryContext.getRequest().param(\"index\");\n        if (Strings.hasText(index) == false) {\n            throw new IllegalArgumentException(\"index must not be null\");\n        }\n\n        ESClient client;\n\n        String[] indicesArr = Strings.splitStringByCommaToArray(index);\n        List<String> createIndices = Lists.newArrayList(indicesArr);\n        queryContext.setIndices(createIndices);\n        checkIndices(queryContext);\n        if (isIndexType(queryContext)) {\n            IndexTemplate indexTemplate = getTemplateByIndexTire(createIndices, queryContext);\n            client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n        } else {\n            client = esClusterService.getClient(queryContext, actionName);\n        }\n\n        RestActionListenerImpl<DirectResponse> listener = new RestActionListenerImpl<DirectResponse>(queryContext) {\n            @Override\n            public void onResponse(DirectResponse response) {\n                if (response.getRestStatus() == RestStatus.OK) {\n                    JSONObject res = JSON.parseObject(response.getResponseContent());\n                    if (false == res.containsKey(\"index\")) {\n                        res.put(\"index\", index);\n                        res.put(\"shards_acknowledged\", true);\n                    }\n\n                    response.setResponseContent(res.toJSONString());\n                }\n\n                super.onResponse(response);\n            }\n        };\n\n        directRequest(client, queryContext, listener);\n    }\n\n    @Override\n    public String name() {\n        return NAME;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/delete/RestDeleteIndexAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices.delete;\n\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n@Component(\"restDeleteIndexAction\")\npublic class RestDeleteIndexAction extends ESAction {\n\n    public static final String NAME = \"restDeleteIndex\";\n\n    @Override\n    public String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String index = queryContext.getRequest().param(\"index\");\n        if (Strings.hasText(index) == false) {\n            throw new IllegalArgumentException(\"index must not be null\");\n        }\n\n        ESClient client;\n\n        String[] indicesArr = Strings.splitStringByCommaToArray(index);\n        List<String> indices = Lists.newArrayList(indicesArr);\n        queryContext.setIndices(indices);\n        checkIndices(queryContext);\n        if (isIndexType(queryContext)) {\n            IndexTemplate indexTemplate = getTemplateByIndexTire(indices, queryContext);\n            client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n        } else {\n            client = esClusterService.getClient(queryContext, actionName);\n        }\n\n        directRequest(client, queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/mapping/get/RestGetFieldMappingAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.admin.indices.mapping.get;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.core.es.http.StatAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Component;\n\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport static com.didi.arius.gateway.common.consts.RestConsts.*;\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n/**\n *\n */\n@Component\npublic class RestGetFieldMappingAction extends StatAction {\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client)\n            throws Exception {\n        String index = request.param(INDEX);\n        if (null == index) {\n            sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, XContentType.JSON.restContentType(), \"{}\"));\n            return;\n        }\n\n        if (isIndexType(queryContext)) {\n            String[] indicesArr = Strings.splitStringByCommaToArray(index);\n            List<String> indices = Lists.newArrayList(indicesArr);\n            IndexTemplate indexTemplate = getTemplateByIndexTire(indices, queryContext);\n\n            client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n        }\n\n        if (queryContext.isFromKibana() && !queryContext.isNewKibana() && !client.getEsVersion().startsWith(QueryConsts.ES_VERSION_2_PREFIX)) {\n            ESClient finalClient = client;\n            RestActionListenerImpl<DirectResponse> listener = new RestActionListenerImpl<DirectResponse>(queryContext) {\n                @Override\n                public void onResponse(DirectResponse response) {\n                    if (response.getRestStatus() == RestStatus.OK) {\n                        JSONObject jsonRes = JSON.parseObject(response.getResponseContent());\n\n                        // for kibana\n                        // 遍历索引\n                        for (Map.Entry<String, Object> entry : jsonRes.entrySet()) {\n                            JSONObject index = (JSONObject) entry.getValue();\n                            JSONObject mapping = index.getJSONObject(\"mappings\");\n\n                            if (mapping == null || mapping.size() == 0) {\n                                continue;\n                            }\n\n                            // 遍历mappings\n                            if (finalClient.getEsVersion().startsWith(QueryConsts.ES_VERSION_7_PREFIX)) {\n                                //7.x single type\n                                String text = mapping.toJSONString();\n                                Set<String> keySet = new HashSet<>(mapping.keySet());\n                                keySet.forEach(mapping::remove);\n                                mapping.put(\"_doc\", JSON.parseObject(text));\n                            }\n                            for (Map.Entry<String, Object> inEntry : mapping.entrySet()) {\n                                JSONObject type = (JSONObject) inEntry.getValue();\n\n                                //遍历type\n                                for (Map.Entry<String, Object> typeEntry : type.entrySet()) {\n                                    JSONObject field = (JSONObject) typeEntry.getValue();\n                                    handleMapping(field);\n                                }\n                            }\n                        }\n\n                        response.setResponseContent(jsonRes.toJSONString());\n                    }\n\n                    super.onResponse(response);\n                }\n            };\n\n            directRequest(client, queryContext, listener);\n        } else {\n            directRequest(client, queryContext);\n        }\n\n    }\n\n    private void handleMapping(JSONObject field) {\n        if (field.containsKey(\"mapping\")) {\n            JSONObject mapping = field.getJSONObject(\"mapping\");\n\n            //遍历field\n            for (Map.Entry<String, Object> mappingEntry : mapping.entrySet()) {\n                JSONObject fieldTypes = (JSONObject) mappingEntry.getValue();\n                dealType(fieldTypes);\n\n                //如果type包含fields，则继续处理fields\n                if (fieldTypes.containsKey(\"fields\")) {\n                    for (Map.Entry<String, Object> fieldsEntry : fieldTypes.getJSONObject(\"fields\").entrySet()) {\n                        JSONObject fields = (JSONObject) fieldsEntry.getValue();\n                        dealType(fields);\n                    }\n                }\n            }\n        }\n    }\n\n    private void dealType(JSONObject fieldTypes) {\n        if (fieldTypes.containsKey(\"type\")) {\n            String strType = fieldTypes.getString(\"type\");\n            String isIndex = fieldTypes.getString(INDEX);\n            if (strType.equalsIgnoreCase(\"text\")) {\n                fieldTypes.put(\"type\", STRING_NAME);\n                if (isIndex == null || isIndex.equals(\"true\")) {\n                    fieldTypes.put(INDEX, \"analyzed\");\n                }\n            } else if (strType.equalsIgnoreCase(\"keyword\")) {\n                fieldTypes.put(\"type\", STRING_NAME);\n                if (isIndex == null || isIndex.equals(\"true\")) {\n                    fieldTypes.put(INDEX, \"not_analyzed\");\n                }\n            }\n        }\n    }\n\n    @Override\n    public String name() {\n        return \"restGetFieldMapping\";\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/mapping/get/RestGetMappingAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.admin.indices.mapping.get;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.core.es.http.StatAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Component;\n\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport static com.didi.arius.gateway.common.consts.RestConsts.*;\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n/**\n *\n */\n@Component\npublic class RestGetMappingAction extends StatAction {\n\n    @Override\n    public String name() {\n        return \"restGetMapping\";\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client)\n            throws Exception {\n\n        String index = request.param(INDEX);\n        if (index == null) {\n            sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, XContentType.JSON.restContentType(), \"{}\"));\n            return;\n        }\n\n        if (isIndexType(queryContext)) {\n            String[] indicesArr = Strings.splitStringByCommaToArray(request.param(INDEX));\n            List<String> indices = Lists.newArrayList(indicesArr);\n            IndexTemplate indexTemplate = getTemplateByIndexTire(indices, queryContext);\n\n            client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n        }\n\n        if (queryContext.isFromKibana() && !queryContext.isNewKibana() && !client.getEsVersion().startsWith(QueryConsts.ES_VERSION_2_PREFIX)) {\n            ESClient finalClient = client;\n            RestActionListenerImpl<DirectResponse> listener = new RestActionListenerImpl<DirectResponse>(queryContext) {\n                @Override\n                public void onResponse(DirectResponse response) {\n                    if (response.getRestStatus() == RestStatus.OK) {\n                        JSONObject res = JSON.parseObject(response.getResponseContent());\n\n                        dealMapping(res, finalClient);\n\n                        response.setResponseContent(res.toJSONString());\n                    }\n\n                    super.onResponse(response);\n                }\n            };\n\n            directRequest(client, queryContext, listener);\n        } else {\n            directRequest(client, queryContext);\n        }\n    }\n\n    private void dealMapping(JSONObject res, ESClient finalClient) {\n        // for kibana\n        // 遍历索引\n        for (Map.Entry<String, Object> entry : res.entrySet()) {\n            JSONObject index = (JSONObject) entry.getValue();\n            JSONObject mappings = index.getJSONObject(\"mappings\");\n\n            if (mappings == null || mappings.size() == 0) {\n                continue;\n            }\n\n            if (finalClient.getEsVersion().startsWith(QueryConsts.ES_VERSION_7_PREFIX)) {\n                //7.x single type\n                String text = mappings.toJSONString();\n                Set<String> keySet = new HashSet<>(mappings.keySet());\n                keySet.forEach(mappings::remove);\n                mappings.put(\"_doc\", JSON.parseObject(text));\n            }\n\n            // 遍历mappings\n            for (Map.Entry<String, Object> inEntry : mappings.entrySet()) {\n                JSONObject type = (JSONObject) inEntry.getValue();\n                JSONObject properties = type.getJSONObject(\"properties\");\n\n                if (properties == null) {\n                    continue;\n                }\n\n                //遍历type的properties\n                for (Map.Entry<String, Object> typeEntry : properties.entrySet()) {\n                    JSONObject fieldType = (JSONObject) typeEntry.getValue();\n                    dealType(fieldType);\n\n                    //如果type包含fields，则继续处理fields\n                    dealFields(fieldType);\n                }\n            }\n        }\n    }\n\n    private void dealType(JSONObject fieldType) {\n        if (fieldType.containsKey(\"type\")) {\n            String strType = fieldType.getString(\"type\");\n            String isIndex = fieldType.getString(INDEX);\n            if (strType.equalsIgnoreCase(\"text\")) {\n                fieldType.put(\"type\", STRING_NAME);\n                if (isIndex == null || isIndex.equals(\"true\")) {\n                    fieldType.put(INDEX, \"analyzed\");\n                }\n            } else if (strType.equalsIgnoreCase(\"keyword\")) {\n                fieldType.put(\"type\", STRING_NAME);\n                if (isIndex == null || isIndex.equals(\"true\")) {\n                    fieldType.put(INDEX, \"not_analyzed\");\n                }\n            }\n        }\n    }\n\n    private void dealFields(JSONObject fieldType) {\n        if (fieldType.containsKey(\"fields\")) {\n            for (Map.Entry<String, Object> fieldsEntry : fieldType.getJSONObject(\"fields\").entrySet()) {\n                JSONObject fields = (JSONObject) fieldsEntry.getValue();\n                dealType(fields);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/settings/RestGetSettingsAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices.settings;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restGetSettingsAction 给普通账号\n */\n@Component(\"restGetSettingsAction\")\npublic class RestGetSettingsAction extends ESAction {\n\n    @Override\n    public String name() {\n        return \"restGetSettingsAction\";\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String getSettingIndex = queryContext.getRequest().param(\"index\");\n\n        if (StringUtils.isNotBlank(getSettingIndex)) {\n            indexAction(queryContext, getSettingIndex);\n        } else {\n            throw new IllegalArgumentException(\"index must not be null when arius gateway in index mode\");\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/admin/indices/settings/RestPutIndexSettingsAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.admin.indices.settings;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.JSONPath;\nimport com.didi.arius.gateway.common.exception.SettingsForbiddenException;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n@Component(\"restPutIndexSettingsAction\")\npublic class RestPutIndexSettingsAction extends ESAction {\n\n    public static final String NAME = \"restPutIndexSettings\";\n\n    @Override\n    public String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        String index = queryContext.getRequest().param(\"index\");\n        if (Strings.hasText(index) == false) {\n            throw new IllegalArgumentException(\"index must not be null\");\n        }\n\n        String settings = queryContext.getPostBody();\n        if (StringUtils.isBlank(settings)) {\n            throw new IllegalArgumentException(\"index settings must not be null\");\n        }\n\n        String forbiddenSettings = dynamicConfigService.getForbiddenSettings();\n        if (StringUtils.isNotBlank(forbiddenSettings)) {\n            String[] forbiddenSettingList = forbiddenSettings.split(\",\");\n\n            JSONObject settingJSONObj = JSON.parseObject(settings);\n\n            for (String strSetting : forbiddenSettingList) {\n                if (null != settingJSONObj.get(strSetting) || JSONPath.contains(settingJSONObj, strSetting)) {\n                    throw new SettingsForbiddenException(forbiddenSettings + \"be forbiddened setting by arius gateway interface!\");\n                }\n            }\n        }\n\n        ESClient client;\n\n        String[] indicesArr = Strings.splitStringByCommaToArray(index);\n        List<String> indicesList = Lists.newArrayList(indicesArr);\n        queryContext.setIndices(indicesList);\n        checkIndices(queryContext);\n        if (isIndexType(queryContext)) {\n            IndexTemplate indexTemplate = getTemplateByIndexTire(indicesList, queryContext);\n            client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n        } else {\n            client = esClusterService.getClient(queryContext, actionName);\n        }\n\n        directRequest(client, queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/bulk/RestBulkAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.bulk;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.core.es.http.document.RestBaseWriteAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectResponse;\n\nimport com.didiglobal.knowframework.log.LogGather;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.support.RestUtils;\nimport org.springframework.stereotype.Component;\n\nimport java.util.*;\n\nimport static com.didi.arius.gateway.elasticsearch.client.utils.LogUtils.setWriteLog;\n\n/**\n * <pre>\n * { \"index\" : { \"_index\" : \"test\", \"_type\" : \"type1\", \"_id\" : \"1\" }\n * { \"type1\" : { \"field1\" : \"value1\" } }\n * { \"delete\" : { \"_index\" : \"test\", \"_type\" : \"type1\", \"_id\" : \"2\" } }\n * { \"create\" : { \"_index\" : \"test\", \"_type\" : \"type1\", \"_id\" : \"1\" }\n * { \"type1\" : { \"field1\" : \"value1\" } }\n * </pre>\n */\n@Component\npublic class RestBulkAction extends RestBaseWriteAction {\n\n    @Override\n    public String name() {\n        return \"bulk\";\n    }\n\n    @Override\n    public void handleInterRequest(QueryContext queryContext, final RestRequest request, final RestChannel channel)\n            throws Exception {\n        String defaultIndex = request.param(\"index\");\n        if (defaultIndex == null) {\n            String bulkBody = queryContext.getPostBody();\n            String[] line = bulkBody.split(\"\\n\");\n            List<String> bulkItems = Arrays.asList(line);\n            Iterator<String> iter = bulkItems.iterator();\n            while (iter.hasNext()) {\n                String operate = iter.next();\n                if (operate.equals(\"\")) {\n                    continue;\n                }\n                JSONObject bulkJson = JSON.parseObject(operate);\n                if (bulkJson.keySet().size() != 1) {\n                    throw new InvalidParameterException(\"bulk operate error\");\n                }\n\n                String key = bulkJson.keySet().iterator().next();\n                JSONObject operateJson = bulkJson.getJSONObject(key);\n                String index = operateJson.getString(\"_index\");\n                if (index != null) {\n                    defaultIndex = index;\n                    break;\n                }\n            }\n        }\n\n        queryContext.setIndices(Arrays.asList(defaultIndex));\n        checkWriteIndicesAndTemplateBlockWrite(queryContext);\n\n        IndexTemplate indexTemplate = getAndCheckIndexTemplate(defaultIndex, queryContext);\n\n        // 获取写入的client\n        ESClient writeClient = esClusterService.getWriteClient(indexTemplate, actionName);\n\n        String uri = queryContext.getUri();\n        String queryString = queryContext.getQueryString() == null ? \"\" : queryContext.getQueryString();\n\n        Map<String, String> params = new HashMap<>();\n        RestUtils.decodeQueryString(queryString, 0, params);\n        if (!Strings.isEmpty(indexTemplate.getIngestPipeline())) {\n            params.put(\"pipeline\", indexTemplate.getIngestPipeline());\n        }\n\n        DirectRequest directRequest = new DirectRequest(queryContext.getMethod().toString(), uri);\n        directRequest.setPostContent(queryContext.getPostBody());\n        directRequest.setParams(params);\n        directRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        directRequest.putHeader(\"Authorization\", request.getHeader(\"Authorization\"));\n\n        LogGather.recordInfoLog( indexTemplate.getExpression() + \"_\" + OPER_BULK, String.format(\"%s write index\", indexTemplate.getExpression()));\n\n        // 生成listener\n        ActionListener<DirectResponse> listener = new RestActionListenerImpl<DirectResponse>(queryContext) {\n            @Override\n            public void onResponse(DirectResponse response) {\n                long currentTime = System.currentTimeMillis();\n                setWriteLog(queryContext, indexTemplate, response,\n                        currentTime, queryConfig.isWriteLogContentOpen());\n\n                metricsService.addIndexMetrics(indexTemplate.getExpression(), name(), currentTime - queryContext.getRequestTime(), queryContext.getPostBody().length(), response.getResponseContent().length());\n\n                super.onResponse(response);\n            }\n        };\n\n        writeClient.direct(directRequest, listener);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/count/RestCountAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.count;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.consts.RestConsts;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.collect.Tuple;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n/**\n *\n */\n@Component(\"restCountAction\")\npublic class RestCountAction extends ESAction {\n\n\t@Override\n\tpublic String name() {\n\t\treturn \"count\";\n\t}\n\t\n\n    @Override\n\tpublic void handleInterRequest(QueryContext queryContext, final RestRequest request, final RestChannel channel)\n\t\t\tthrows Exception {\n        ESSearchRequest esSearchRequest = new ESSearchRequest();\n        esSearchRequest.indices(Strings.splitStringByCommaToArray(request.param(\"index\")));\n        esSearchRequest.types(Strings.splitStringByCommaToArray(request.param(\"type\")));\n        esSearchRequest.setTemplateRequest(request.path().endsWith(\"/template\"));\n        esSearchRequest.source(RestActions.getRestContent(request));\n        Map<String, String> params = request.params();\n        params.remove(\"source\");\n        params.remove(\"index\");\n        params.remove(\"type\");\n        params.put(\"size\", \"0\");\n        esSearchRequest.setParams(params);\n\n        esSearchRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        esSearchRequest.putHeader(\"Authorization\", queryContext.getRequest().getHeader(\"Authorization\"));\n\n        IndexTemplate indexTemplate = null;\n        if (isIndexType(queryContext)) {\n            List<String> indices = queryContext.getIndices();\n            if (indices.size() == 1) {\n                indexTemplate = getTemplateByIndex(indices, queryContext);\n            }\n\n            if (indexTemplate != null) {\n                if(!isAliasGet(indexTemplate, indices)){\n                    String dateFrom = queryContext.getRequest().param(RestConsts.SEARCH_DATE_FROM_PARAMS);\n                    String dateTo = queryContext.getRequest().param(RestConsts.SEARCH_DATE_TO_PARAMS);\n\n                    String[] newIndicesArray = getQueryIndices(indexTemplate, dateFrom, dateTo);\n\n                    esSearchRequest.indices(newIndicesArray);\n                }\n            } else {\n                indexTemplate = getTemplateByIndexTire(indices, queryContext);\n            }\n\n            // 该索引模板需要根据type名称进行映射到对应的索引模板\n            if (isNeedChangeIndexName(queryContext, indexTemplate)) {\n\n                Tuple<IndexTemplate/*dest template*/, String[]/*dest indexNames*/> changeRes =\n                        handleChangeIndexName(queryContext, indexTemplate, esSearchRequest.indices(), esSearchRequest.types());\n\n                // 替换查询语句中的索引名称\n                esSearchRequest.indices(changeRes.v2());\n                // 再替换索引模板对象\n                indexTemplate = changeRes.v1();\n            }\n        }\n\n        // 日期索引加上*号后缀，支持异常索引修复方案\n        Convert.convertIndices(esSearchRequest);\n\n        ESClient readClient = esClusterService.getClient(queryContext, indexTemplate, actionName);\n\n        // pre process\n        preSearchProcess(queryContext, readClient, esSearchRequest);\n\n        RestActionListenerImpl<ESSearchResponse> listener = new RestActionListenerImpl<ESSearchResponse>(queryContext) {\n            @Override\n            public void onResponse(ESSearchResponse response) {\n\n                JSONObject jsonObject = new JSONObject();\n                jsonObject.put(name(), response.getHits().getTotal());\n                jsonObject.put(\"_shards\", response.getShards());\n\n                super.onResponse(new BytesRestResponse(RestStatus.OK, XContentType.JSON.restContentType(), jsonObject.toJSONString()));\n            }\n        };\n        readClient.search(esSearchRequest, listener);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/document/RestBaseWriteAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.document;\n\nimport java.time.Instant;\nimport java.time.LocalDateTime;\nimport java.time.ZoneId;\nimport java.time.format.DateTimeFormatter;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.exception.IndexDateFieldException;\nimport com.didi.arius.gateway.common.exception.IndexNotPermittedException;\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.didi.arius.gateway.common.exception.ServerBusyException;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.TemplateClusterInfo;\nimport com.didi.arius.gateway.common.utils.AppUtil;\nimport com.didi.arius.gateway.core.es.http.HttpRestHandler;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.log.LogGather;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.cache.CacheLoader;\nimport com.google.common.cache.LoadingCache;\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.joda.time.DateTime;\nimport org.joda.time.format.DateTimeFormat;\n\npublic abstract class RestBaseWriteAction extends HttpRestHandler {\n    protected static final ILog logger = LogFactory.getLog(RestBaseWriteAction.class);\n\n    protected static final int OPER_INDEX                   = 100001;\n    protected static final int OPER_UPDATE                  = 100002;\n    protected static final int OPER_APPEND                  = 100003;\n    protected static final int OPER_APPEND_LIST             = 100004;\n    protected static final int OPER_DELETE                  = 100005;\n    protected static final int OPER_BULK                    = 100000;\n    protected static final String WRITE_TIME_FIELD          = \"es_index_time\";\n    protected static final List<String> timePatterns = Arrays.asList(\"yyyy-MM-dd HH:mm:ss\", \"yyyy-MM-dd HH:mm:ss.SSS\",\n            \"yyyy-MM-dd HH:mm:ss.SSS Z\", \"yyyy-MM-dd'T'HH:mm:ss\", \"yyyy-MM-dd'T'HH:mm:ss.SSS\", \"yyyy-MM-dd'T'HH:mm:ssZ\",\n            \"yyyy-MM-dd'T'HH:mm:ss.SSSZ\", \"yyyy/MM/dd HH:mm:ss\", \"epoch_second\", \"epoch_millis\", \"yyyy-MM-dd\");\n\n    protected static final long MILLIS_ZONE_OFFSET = LocalDateTime.of(1970, 1, 1, 0, 0, 0,\n            0).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();\n    private LoadingCache<Long, Map<String, String>> dayFormatCache = CacheBuilder.newBuilder().concurrencyLevel(20).expireAfterWrite(5,\n            TimeUnit.MINUTES).initialCapacity(60).maximumSize(100).recordStats().build(new CacheLoader<Long, Map<String, String>>() {\n\n        @Override\n        public Map<String, String> load(Long key) {\n            return new ConcurrentHashMap<>();\n        }\n    });\n\n    @Override\n    public void handleRequest(QueryContext queryContext) throws Exception {\n        RestRequest request = queryContext.getRequest();\n        RestChannel channel = queryContext.getChannel();\n\n        String[]  indicesArr = Strings.splitStringByCommaToArray(request.param(\"index\"));\n        List<String> indices = Lists.newArrayList(indicesArr);\n        queryContext.setIndices(indices);\n\n        if (isOriginCluster(queryContext)) {\n            handleOriginClusterRequest(queryContext);\n        } else {\n            if (isNeededCheckIndices()) {\n                checkWriteIndicesAndTemplateBlockWrite(queryContext);\n            }\n\n            handleInterRequest(queryContext, request, channel);\n        }\n    }\n\n    protected abstract void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception;\n\n\n    public   String getIndexName(IndexTemplate indexTemplate, Map<String, Object> source) {\n        if (StringUtils.isBlank(indexTemplate.getDateFormat())) {\n            String indexExpression = indexTemplate.getExpression();\n            if (indexExpression.endsWith(\"*\")) {\n                indexExpression = indexExpression.substring(0, indexExpression.length()-1);\n            }\n\n            return getIndexVersionName(indexExpression, indexTemplate.getVersion());\n        }\n\n        Object timeObj = source != null ? source.get(indexTemplate.getDateField()) : null;\n        long messageTime = 0;\n\n        if (null != timeObj) {\n            String timeValue = String.valueOf(timeObj);\n            if (StringUtils.isNumeric(timeValue)) {\n                if (timeValue.length() == 13) {\n                    messageTime = Long.parseLong(timeValue);\n                } else if (timeValue.length() == 10) {\n                    timeObj = Long.parseLong(timeValue);\n                    messageTime = ((Long) timeObj) * 1000;\n                }\n            } else {\n                messageTime = getMessageTime(messageTime, timeValue);\n            }\n\n            if (messageTime == 0) {\n                throw new IndexDateFieldException(String.format(\"index time format error,index=%s, time field=%s, time=%s\", indexTemplate.getExpression(), indexTemplate.getDateField(), timeValue));\n            }\n        } else {\n            throw new InvalidParameterException(String.format(\"index time field missing,index=%s, time field=%s\", indexTemplate.getExpression(), indexTemplate.getDateField()));\n        }\n\n        return getIndexNameWithDate(indexTemplate, messageTime);\n    }\n\n    private long getMessageTime(long messageTime, String timeValue) {\n        for (String timePattern : timePatterns) {\n            try {\n                messageTime = DateTime.parse(timeValue, DateTimeFormat.forPattern(timePattern)).getMillis();\n                break;\n            } catch (Exception e) {\n                // pass\n            }\n        }\n        return messageTime;\n    }\n\n    protected String getIndexNameWithDate(IndexTemplate indexTemplate, long time) {\n        // 配置了过期时间字段，则需要判断是否过期，或者过于超前\n        if (indexTemplate.getExpireTime() > 0 &&\n                (time < System.currentTimeMillis() - indexTemplate.getExpireTime() * QueryConsts.DAY_MILLIS\n                    || time > System.currentTimeMillis() + 2 * QueryConsts.DAY_MILLIS)) {\n            throw new IndexDateFieldException(String.format(\"index time expire,index=%s, time=%d\", indexTemplate.getExpression(), time));\n        }\n\n        // 需要校准时区之差对应的时间\n        long key = (time - MILLIS_ZONE_OFFSET) / QueryConsts.DAY_MILLIS;\n        String indexExpression = indexTemplate.getExpression();\n        String indexNameDateTime = null;\n        String dateFormat = indexTemplate.getDateFormat().replace('Y', 'y');\n\n        try {\n            // 从缓存中获取\n            Map<String, String> format2DayValueMap = dayFormatCache.get(key);\n\n            // 如果该时间在缓存中找不到，则计算, 这里不会执行到，因为在构建dayFormatCache设置了load回调来放入新的key\n            if (null == format2DayValueMap) {\n\n                format2DayValueMap = new ConcurrentHashMap<>();\n                // 不包含该日期转换格式则计算，然后放入map中\n\n                Instant instant = Instant.ofEpochMilli(time);\n                LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());\n                indexNameDateTime = DateTimeFormatter.ofPattern(dateFormat).format(dateTime);\n\n                format2DayValueMap.put(dateFormat, indexNameDateTime);\n                // 放入缓存中\n                dayFormatCache.put(key, format2DayValueMap);\n            } else {\n                // 如果包含了该日期转换格式\n                if (format2DayValueMap.containsKey(dateFormat)) {\n                    indexNameDateTime = format2DayValueMap.get(dateFormat);\n\n                    if (logger.isDebugEnabled()) {\n                        logger.debug(\"getIndexNameWithDate||infoMsg=get time -> {}, key -> {} from cache, dateFormat -> {}, indexNameDateTime -> {}\",\n                                time, key, dateFormat, indexNameDateTime);\n                    }\n                } else {\n                    // 不包含该日期转换格式则计算，然后放入map中\n                    Instant instant = Instant.ofEpochMilli(time);\n                    LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());\n\n                    indexNameDateTime = DateTimeFormatter.ofPattern(dateFormat).format(dateTime);\n\n                    // 有效的才放入map中\n                    format2DayValueMap.put(dateFormat, indexNameDateTime);\n                }\n            }\n        } catch (Exception e) {\n            LogGather.recordErrorLog(\"LoadingCacheField_\" + indexExpression, \"Failed to get key \", e);\n        }\n\n        // 如果日期值为空，则默认为当天\n        if (StringUtils.isBlank(indexNameDateTime)) {\n            LocalDateTime dateTime = LocalDateTime.now();\n            // 根据时间格式转换为格式化后的时间字符串\n            indexNameDateTime = DateTimeFormatter.ofPattern(dateFormat).format(dateTime);\n        }\n\n        if (indexExpression.endsWith(\"*\")) {\n            indexExpression = indexExpression.substring(0, indexExpression.length()-1);\n        }\n\n        return getIndexVersionName(indexExpression.concat(indexNameDateTime), indexTemplate.getVersion());\n    }\n\n    protected String getIndexVersionName(String index, int version) {\n        if (version == 0) {\n            return index;\n        } else {\n            return String.format(\"%s_v%d\", index, version);\n        }\n    }\n\n    protected IndexTemplate getAndCheckIndexTemplate(String index, QueryContext queryContext) {\n        IndexTemplate indexTemplate = getTemplateByIndex(Arrays.asList(index), queryContext);\n        if (indexTemplate == null) {\n            if (queryContext.isFromKibana())  {\n                // kibana索引写入admin集群\n                indexTemplate = new IndexTemplate();\n                indexTemplate.setExpression(index);\n                indexTemplate.setExpireTime(-1);\n                indexTemplate.setDeployStatus(IndexTemplate.DeployStatus.MASTER_ONLY);\n                indexTemplate.setInternal(true);\n\n                TemplateClusterInfo templateClusterInfo = new TemplateClusterInfo();\n                templateClusterInfo.setCluster(esRestClientService.getAdminClient(actionName).getClusterName());\n                indexTemplate.setMasterInfo(templateClusterInfo);\n                return indexTemplate;\n            } else if (AppUtil.isAdminAppid(queryContext.getAppDetail())) {\n                indexTemplate = new IndexTemplate();\n                indexTemplate.setExpression(index);\n                indexTemplate.setExpireTime(-1);\n                indexTemplate.setDeployStatus(IndexTemplate.DeployStatus.MASTER_ONLY);\n                indexTemplate.setInternal(true);\n\n                TemplateClusterInfo templateClusterInfo = new TemplateClusterInfo();\n                templateClusterInfo.setCluster(queryContext.getAppDetail().getCluster());\n                indexTemplate.setMasterInfo(templateClusterInfo);\n                return indexTemplate;\n            }\n\n            indexTemplate = getTemplateByIndexTire(Lists.newArrayList(index), queryContext);\n            if (indexTemplate == null) {\n                throw new IndexNotPermittedException(\"appid=\" + queryContext.getAppDetail().getId() + \" don't have permission to write \" + index);\n            }\n        }\n\n        if (indexTemplate.getDeployStatus() == IndexTemplate.DeployStatus.NONE) {\n            throw new ServerBusyException(String.format(\"es internal write %s busy, please wait...\", indexTemplate.getName()));\n        }\n\n        return indexTemplate;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/document/RestDeleteAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.document;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.exception.AccessForbiddenException;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.AppUtil;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESDeleteRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESDeleteResponse;\nimport com.didiglobal.knowframework.log.LogGather;\nimport org.apache.commons.lang.StringUtils;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.support.replication.ReplicationRequest;\nimport org.elasticsearch.common.xcontent.XContentFactory;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.index.VersionType;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.springframework.stereotype.Component;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.didi.arius.gateway.elasticsearch.client.utils.LogUtils.setWriteLog;\n\n@Component(\"restDeleteAction\")\npublic class RestDeleteAction extends RestBaseWriteAction {\n\n    @Override\n    public String name() {\n        return \"delete\";\n    }\n\n\n    @Override\n    public void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel)\n            throws Exception {\n        String index = request.param(\"index\");\n        IndexTemplate indexTemplate = getAndCheckIndexTemplate(index, queryContext);\n\n        String indexName = index;\n        // delete 在索引不按时间分割的时候，可以支持不传递source\n        if (StringUtils.isBlank(indexTemplate.getDateFormat())) {\n            String indexExpression = indexTemplate.getExpression();\n            if (indexExpression.endsWith(\"*\")) {\n                indexExpression = indexExpression.substring(0, indexExpression.length()-1);\n            }\n            indexName = getIndexVersionName(indexExpression.toLowerCase(), indexTemplate.getVersion());\n        } else {\n            if(request.hasContent()) {\n                String strSource;\n                if (XContentType.JSON != XContentFactory.xContentType(request.content())) {\n                    strSource = XContentHelper.convertToJson(request.content(), false);\n                } else {\n                    strSource = request.content().toUtf8();\n                }\n                Map<String, Object> source = JSON.parseObject(strSource, HashMap.class);\n                indexName = getIndexName(indexTemplate, source);\n            }\n        }\n\n        if (indexName.startsWith(\".\") && !AppUtil.isAdminAppid(queryContext.getAppDetail())) {\n            throw new AccessForbiddenException(\"action(\" + queryContext.getUri() + \") forbidden\");\n        }\n\n        ESDeleteRequest deleteRequest = new ESDeleteRequest();\n        deleteRequest.index(indexName);\n        deleteRequest.type(request.param(\"type\") == null ? \"_doc\" : request.param(\"type\"));\n        deleteRequest.id(request.param(\"id\"));\n        deleteRequest.routing(request.param(\"routing\"));\n        deleteRequest.parent(request.param(\"parent\")); // order is important, set it after routing, so it will set the routing\n        deleteRequest.timeout(request.paramAsTime(\"timeout\", ReplicationRequest.DEFAULT_TIMEOUT));\n        deleteRequest.setRefresh(request.param(\"refresh\"));\n        deleteRequest.version(RestActions.parseVersion(request));\n        deleteRequest.versionType(VersionType.fromString(request.param(\"version_type\"), deleteRequest.versionType()));\n        deleteRequest.setConsistencyLevel(request.param(\"consistency\"));\n        deleteRequest.setWaitForActiveShards(request.param(\"wait_for_active_shards\"));\n\n        deleteRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        deleteRequest.putHeader(\"Authorization\", request.getHeader(\"Authorization\"));\n\n        ESClient writeClient = esClusterService.getWriteClient(indexTemplate, actionName);\n\n        if (logger.isDebugEnabled()) {\n            logger.debug(\"rest delete data:index={}, type={}, id={}\", deleteRequest.index(), deleteRequest.type(), deleteRequest.id());\n        }\n\n        LogGather.recordInfoLog( deleteRequest.index() + \"_\" + OPER_DELETE, String.format(\"%s delete index, type=%s, id=%s\", deleteRequest.index(), deleteRequest.type(), deleteRequest.id()));\n\n        ActionListener<ESDeleteResponse> listener = new RestActionListenerImpl<ESDeleteResponse>(queryContext) {\n            @Override\n            public void onResponse(ESDeleteResponse response) {\n                long currentTime = System.currentTimeMillis();\n\n                setWriteLog(queryContext, indexTemplate,\n                        response, currentTime, queryConfig.isWriteLogContentOpen());\n\n                metricsService.addIndexMetrics(indexTemplate.getExpression(), name(), currentTime - queryContext.getRequestTime(), queryContext.getPostBody().length(), 0);\n\n                super.onResponse(response);\n            }\n\n\n        };\n        writeClient.delete(deleteRequest, listener);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/document/RestIndexAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.document;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESIndexRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESIndexResponse;\nimport com.didiglobal.knowframework.log.LogGather;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.index.IndexRequest;\nimport org.elasticsearch.action.support.replication.ReplicationRequest;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.xcontent.XContentFactory;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.index.VersionType;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.springframework.stereotype.Component;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.didi.arius.gateway.elasticsearch.client.utils.LogUtils.setWriteLog;\n\n@Component(\"restIndexAction\")\npublic class RestIndexAction extends RestBaseWriteAction {\n    private static final String CREATE_NAME = \"_create\";\n\n    @Override\n    public String name() {\n        return \"index\";\n    }\n\n\n    @Override\n    public void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel)\n            throws Exception {\n        if (request.param(CREATE_NAME) != null) {\n            if (request.param(CREATE_NAME).equals(CREATE_NAME)) {\n                request.params().put(\"op_type\", \"create\");\n            } else {\n                throw new IllegalArgumentException(\"Can't handle [\" + request.method() + \"] for path [\" + request.rawPath() + \"]\");\n            }\n        }\n\n        if (!request.hasContent()) {\n            throw  new InvalidParameterException(\"no source to write\");\n        }\n\n        String index = request.param(name());\n        IndexTemplate indexTemplate = getAndCheckIndexTemplate(index, queryContext);\n\n        String strSource;\n        if (XContentType.JSON != XContentFactory.xContentType(request.content())) {\n            strSource = XContentHelper.convertToJson(request.content(), false);\n        } else {\n            strSource = request.content().toUtf8();\n        }\n\n        Map<String, Object> source = JSON.parseObject(strSource, HashMap.class);\n\n        if (!indexTemplate.isInternal()) {\n            source.put(WRITE_TIME_FIELD, System.currentTimeMillis());\n        }\n        ESIndexRequest indexRequest = new ESIndexRequest();\n        indexRequest.index(index);\n        indexRequest.type(request.param(\"type\") == null ? \"_doc\" : request.param(\"type\"));\n        indexRequest.id(request.param(\"id\"));\n        indexRequest.routing(request.param(\"routing\"));\n        indexRequest.parent(request.param(\"parent\")); // order is important, set it after routing, so it will set the routing\n        if (!Strings.isEmpty(indexTemplate.getIngestPipeline())) {\n            indexRequest.setPipeline(indexTemplate.getIngestPipeline());\n        }\n        indexRequest.source(JSON.toJSONString(source));\n        indexRequest.timeout(request.paramAsTime(\"timeout\", ReplicationRequest.DEFAULT_TIMEOUT));\n\n        indexRequest.version(RestActions.parseVersion(request));\n        indexRequest.versionType(VersionType.fromString(request.param(\"version_type\"), indexRequest.versionType()));\n        String sOpType = request.param(\"op_type\");\n        if (sOpType != null) {\n            indexRequest.opType(IndexRequest.OpType.fromString(sOpType));\n        }\n\n        indexRequest.setConsistencyLevel(request.param(\"consistency\"));\n        indexRequest.setWaitForActiveShards(request.param(\"wait_for_active_shards\"));\n        indexRequest.setRefresh(request.param(\"refresh\"));\n\n        indexRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        indexRequest.putHeader(\"Authorization\", request.getHeader(\"Authorization\"));\n\n        // 获取写入的client\n        ESClient writeClient = esClusterService.getWriteClient(indexTemplate, actionName);\n\n        if (logger.isDebugEnabled()) {\n            logger.debug(\"rest index data:index={}, type={}, id={}\", indexRequest.index(), indexRequest.type(), indexRequest.id());\n        }\n\n        LogGather.recordInfoLog( indexRequest.index() + \"_\" + OPER_INDEX, String.format(\"%s write index, type=%s, id=%s\", indexRequest.index(), indexRequest.type(), indexRequest.id()));\n\n        // 生成listener\n        ActionListener<ESIndexResponse> listener = new RestActionListenerImpl<ESIndexResponse>(queryContext) {\n            @Override\n            public void onResponse(ESIndexResponse response) {\n                long currentTime = System.currentTimeMillis();\n\n                setWriteLog(queryContext, indexTemplate, response,\n                        currentTime, queryConfig.isWriteLogContentOpen());\n\n                metricsService.addIndexMetrics(indexTemplate.getExpression(), name(), currentTime - queryContext.getRequestTime(), queryContext.getPostBody().length(), 0);\n\n                super.onResponse(response);\n            }\n        };\n\n        // 异步写入\n        writeClient.index(indexRequest, listener);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/document/RestUpdateAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.document;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESUpdateRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESUpdateResponse;\nimport com.didiglobal.knowframework.log.LogGather;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.common.xcontent.XContentFactory;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.index.VersionType;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.springframework.stereotype.Component;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.didi.arius.gateway.elasticsearch.client.utils.LogUtils.setWriteLog;\n\n@Component(\"restUpdateAction\")\npublic class RestUpdateAction extends RestBaseWriteAction {\n\n    @Override\n    public String name() {\n        return \"update\";\n    }\n\n\n    @Override\n    public void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel)\n            throws Exception {\n        if (!request.hasContent()) {\n            throw  new InvalidParameterException(\"no source to update\");\n        }\n\n        String index = request.param(\"index\");\n        IndexTemplate indexTemplate = getAndCheckIndexTemplate(index, queryContext);\n\n        String strSource;\n        if (XContentType.JSON != XContentFactory.xContentType(request.content())) {\n            strSource = XContentHelper.convertToJson(request.content(), false);\n        } else {\n            strSource = request.content().toUtf8();\n        }\n\n        Map<String, Object> source = JSON.parseObject(strSource, HashMap.class);\n        Map<String, Object> doc = (Map<String, Object>) source.get(\"doc\");\n        if (doc == null && indexTemplate.getDeployStatus() == IndexTemplate.DeployStatus.MASTER_AND_SLAVE) {\n            throw new InvalidParameterException(\"kakfa update only support doc update\");\n        }\n\n        if (doc != null && !indexTemplate.isInternal()) {\n            doc.put(WRITE_TIME_FIELD, System.currentTimeMillis());\n        }\n\n        String indexName = getIndexName(indexTemplate, doc);\n\n        ESUpdateRequest updateRequest = new ESUpdateRequest();\n        updateRequest.index(indexName);\n        updateRequest.type(request.param(\"type\"));\n        updateRequest.id(request.param(\"id\"));\n        updateRequest.routing(request.param(\"routing\"));\n        updateRequest.parent(request.param(\"parent\"));\n        updateRequest.timeout(request.paramAsTime(\"timeout\", updateRequest.timeout()));\n        updateRequest.setRefresh(request.param(\"refresh\"));\n        updateRequest.setConsistencyLevel(request.param(\"consistency\"));\n        updateRequest.setWaitForActiveShards(request.param(\"wait_for_active_shards\"));\n\n        updateRequest.docAsUpsert(request.paramAsBoolean(\"doc_as_upsert\", updateRequest.docAsUpsert()));\n\n        updateRequest.retryOnConflict(request.paramAsInt(\"retry_on_conflict\", updateRequest.retryOnConflict()));\n        updateRequest.version(RestActions.parseVersion(request));\n        updateRequest.versionType(VersionType.fromString(request.param(\"version_type\"), updateRequest.versionType()));\n        updateRequest.source(JSON.toJSONString(source));\n\n        updateRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        updateRequest.putHeader(\"Authorization\", request.getHeader(\"Authorization\"));\n\n        ESClient writeClient = esClusterService.getWriteClient(indexTemplate, actionName);\n\n        LogGather.recordInfoLog( updateRequest.index() + \"_\" + OPER_UPDATE, String.format(\"%s update index, type=%s, id=%s\", updateRequest.index(), updateRequest.type(), updateRequest.id()));\n\n        ActionListener<ESUpdateResponse> listener = new RestActionListenerImpl<ESUpdateResponse>(queryContext) {\n            @Override\n            public void onResponse(ESUpdateResponse response) {\n                long currentTime = System.currentTimeMillis();\n\n                setWriteLog(queryContext, indexTemplate, response,\n                        currentTime, queryConfig.isWriteLogContentOpen());\n\n                metricsService.addIndexMetrics(indexTemplate.getExpression(), name(), currentTime - queryContext.getRequestTime(), queryContext.getPostBody().length(), 0);\n\n                super.onResponse(response);\n            }\n        };\n        writeClient.update(updateRequest, listener);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/get/RestBaseGetAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.get;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.*;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESGetRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESGetResponse;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.index.VersionType;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.elasticsearch.search.fetch.source.FetchSourceContext;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\npublic abstract class RestBaseGetAction extends ESAction {\n    protected void handleInterGetRequest(QueryContext queryContext, RestRequest request, final WrapESGetResponse.ResultType resultType) {\n        IndexTemplate template = null;\n\n        String index = request.param(\"index\");\n\n        if (isIndexType(queryContext)) {\n            List<String> indices = queryContext.getIndices();\n            template = getTemplateByIndexTire(indices, queryContext);\n\n            // 该索引模板需要根据type名称进行映射到对应的索引模板\n            if (isNeedChangeIndexName(queryContext, template)) {\n                String sourceIndexName = index;\n                String sourceTemplateName = template.getName();\n                Map<String/*typeName*/,String/*templateName*/> typeIndexMapping = template.getMasterInfo().getTypeIndexMapping();\n\n                // 用户指定type方式查询时，gateway需要将该多type索引和指定的type名称映射为对应的单type索引，然后转发到es。例如GET indexName/type1/_search   改写为 GET type1@indexName/type1/_search。\n                String typeName = request.param(\"type\");\n                String destTemplateName = typeIndexMapping.get(typeName);\n                if (StringUtils.isNoneBlank(destTemplateName)) {\n                    // 替换索引名称\n                    index = index.replace(sourceTemplateName, destTemplateName);\n                    // 再替换索引模板对象\n                    template = indexTemplateService.getIndexTemplate(destTemplateName);\n                }\n\n                if (queryContext.isDetailLog()) {\n                    JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n                    joinLogContext.setSourceIndexNames(sourceIndexName);\n                    joinLogContext.setTypeName(typeName);\n                    joinLogContext.setDestIndexName(index);\n                    joinLogContext.setSourceTemplateName(sourceTemplateName);\n                    joinLogContext.setDestTemplateName(destTemplateName);\n                }\n            }\n        }\n\n        ESClient readClient = esClusterService.getClient(queryContext, template, actionName);\n\n        int indexVersion = indexTemplateService.getIndexVersion(index, queryContext.getCluster());\n\n        final FetchFields fetchFields = new FetchFields();\n        fetchFields.setFetchSourceContext(FetchSourceContext.parseFromRestRequest(request));\n        String sField = request.param(\"fields\");\n        if (sField != null) {\n            dealField(fetchFields, sField);\n        }\n\n        if (indexVersion > 0) {\n            getVersionResponse(queryContext, indexVersion, index, request, readClient, resultType);\n        } else {\n            final ESGetRequest getRequest = new ESGetRequest(index, request.param(\"type\") == null ? \"_doc\" : request.param(\"type\"), request.param(\"id\"));\n            getRequest.refresh(request.param(\"refresh\"));\n            getRequest.routing(request.param(\"routing\"));  // order is important, set it after routing, so it will set the routing\n            getRequest.parent(request.param(\"parent\"));\n            getRequest.preference(request.param(\"preference\"));\n            getRequest.realtime(request.paramAsBoolean(\"realtime\", null));\n            getRequest.ignoreErrorsOnGeneratedFields(request.paramAsBoolean(\"ignore_errors_on_generated_fields\", false));\n\n            setFieldValue(request, getRequest);\n\n            getRequest.putHeader(\"requestId\", queryContext.getRequestId());\n            getRequest.putHeader(\"Authorization\", queryContext.getRequest().getHeader(\"Authorization\"));\n\n            getRequest.version(RestActions.parseVersion(request));\n            getRequest.versionType(VersionType.fromString(request.param(\"version_type\"), getRequest.versionType()));\n\n            getRequest.fetchSourceContext(FetchSourceContext.parseFromRestRequest(request));\n\n            ActionListener<ESGetResponse> listener = getEsGetResponseActionListener(queryContext, resultType);\n            readClient.get(getRequest, listener);\n        }\n    }\n\n    private ActionListener<ESGetResponse> getEsGetResponseActionListener(QueryContext queryContext, WrapESGetResponse.ResultType resultType) {\n        return new RestActionListenerImpl<ESGetResponse>(queryContext) {\n            @Override\n            public void onResponse(ESGetResponse response) {\n                WrapESGetResponse wrapESGetResponse = new WrapESGetResponse();\n                wrapESGetResponse.setEsGetResponse(response);\n                wrapESGetResponse.setResultType(resultType);\n                switch (wrapESGetResponse.getResultType()) {\n                    case ALL:\n                        super.onResponse(response);\n                        break;\n                    case HEAD:\n                        if (response.isExists()) {\n                            super.onResponse(new BytesRestResponse(RestStatus.OK));\n                        } else {\n                            super.onResponse(new BytesRestResponse(RestStatus.NOT_FOUND));\n                        }\n                        break;\n                    case SOURCE:\n                        if (response.isExists()) {\n                            super.onResponse(new BytesRestResponse(RestStatus.OK, XContentType.JSON.restContentType(), JSON.toJSONString(response.getSource())));\n                        } else {\n                            super.onResponse(new BytesRestResponse(RestStatus.NOT_FOUND));\n                        }\n\n                        break;\n                    default:\n                }\n            }\n        };\n    }\n\n    private void setFieldValue(RestRequest request, ESGetRequest getRequest) {\n        String fieldStr = request.param(\"fields\");\n        if (fieldStr != null) {\n            String[] sFields = Strings.splitStringByCommaToArray(fieldStr);\n            if (sFields != null) {\n                getRequest.fields(sFields);\n            }\n        }\n\n        final String fieldsParam = request.param(\"stored_fields\");\n        if (fieldsParam != null) {\n            final String[] fields = Strings.splitStringByCommaToArray(fieldsParam);\n            if (fields != null) {\n                getRequest.storedFields(fields);\n            }\n        }\n    }\n\n    private void dealField(FetchFields fetchFields, String sField) {\n        String[] sFields = Strings.splitStringByCommaToArray(sField);\n        if (sFields != null) {\n            fetchFields.setFields(sFields);\n            for (String field : sFields) {\n                if (field.equals(QueryConsts.MESSAGE_FIELD)) {\n                    fetchFields.setHasMessageField(true);\n                    break;\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/get/RestGetAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.get;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.WrapESGetResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\n/**\n *\n */\n@Component(\"restGetAction\")\npublic class RestGetAction extends RestBaseGetAction {\n\n\t@Override\n\tpublic String name() {\n\t\treturn \"get\";\n\t}\n\t\n    @Override\n\tpublic void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel)\n\t\t\tthrows Exception {\n        handleInterGetRequest(queryContext, request, WrapESGetResponse.ResultType.ALL);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/get/RestGetSourceAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.get;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.WrapESGetResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Component;\n\n/**\n *\n */\n@Component(\"restGetSourceAction\")\npublic class RestGetSourceAction extends RestBaseGetAction {\n\n\t@Override\n\tpublic String name() {\n\t\treturn \"getSource\";\n\t}\n\n    @Override\n\tpublic void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel)\n\t\t\tthrows Exception {\n        handleInterGetRequest(queryContext, request, WrapESGetResponse.ResultType.SOURCE);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/get/RestHeadAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.get;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.WrapESGetResponse;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESGetRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESGetResponse;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Component;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n/**\n *\n */\n@Component(\"restHeadAction\")\npublic class RestHeadAction extends ESAction {\n\n\t@Override\n\tpublic String name() {\n\t\treturn \"head\";\n\t}\n\n    @Override\n\tpublic void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel)\n\t\t\tthrows Exception {\n        String index = request.param(\"index\");\n\n        IndexTemplate indexTemplate = null;\n        if (isIndexType(queryContext)) {\n            List<String> indices = queryContext.getIndices();\n            indexTemplate = getTemplateByIndexTire(indices, queryContext);\n\n            // 该索引模板需要根据type名称进行映射到对应的索引模板\n            if (isNeedChangeIndexName(queryContext, indexTemplate)) {\n                String sourceIndexName = index;\n                String sourceTemplateName = indexTemplate.getName();\n                Map<String/*typeName*/,String/*templateName*/> typeIndexMapping = indexTemplate.getMasterInfo().getTypeIndexMapping();\n\n                // 用户指定type方式查询时，gateway需要将该多type索引和指定的type名称映射为对应的单type索引，然后转发到es。例如GET indexName/type1/_search   改写为 GET type1@indexName/type1/_search。\n                String typeName = request.param(\"type\");\n                String destTemplateName = typeIndexMapping.get(typeName);\n                if (StringUtils.isNoneBlank(destTemplateName)) {\n                    // 替换索引名称\n                    index = index.replace(sourceTemplateName, destTemplateName);\n                    // 再替换索引模板对象\n                    indexTemplate = indexTemplateService.getIndexTemplate(destTemplateName);\n                }\n\n                if (queryContext.isDetailLog()) {\n                    JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n                    joinLogContext.setSourceIndexNames(sourceIndexName);\n                    joinLogContext.setTypeName(typeName);\n                    joinLogContext.setDestIndexName(index);\n                    joinLogContext.setSourceTemplateName(sourceTemplateName);\n                    joinLogContext.setDestTemplateName(destTemplateName);\n                }\n            }\n        }\n\n        ESClient readClient = esClusterService.getClient(queryContext, indexTemplate, actionName);\n\n    \tint indexVersion = indexTemplateService.getIndexVersion(index, queryContext.getCluster());\n\n    \tif (indexVersion > 0) {\n    \t\tgetVersionResponse(queryContext, indexVersion, index, request, readClient, WrapESGetResponse.ResultType.HEAD);\n    \t} else {\n            final ESGetRequest getRequest = new ESGetRequest(index, request.param(\"type\") == null ? \"_doc\" : request.param(\"type\"), request.param(\"id\"));\n            getRequest.refresh(request.param(\"refresh\"));\n            getRequest.routing(request.param(\"routing\"));  // order is important, set it after routing, so it will set the routing\n            getRequest.parent(request.param(\"parent\"));\n            getRequest.preference(request.param(\"preference\"));\n            getRequest.realtime(request.paramAsBoolean(\"realtime\", null));\n            // don't get any fields back...\n            getRequest.fields(Strings.EMPTY_ARRAY);\n\n            getRequest.putHeader(\"requestId\", queryContext.getRequestId());\n            getRequest.putHeader(\"Authorization\", request.getHeader(\"Authorization\"));\n\n\n            readClient.get(getRequest, new RestActionListenerImpl<ESGetResponse>(queryContext) {\n                @Override\n                public void onResponse(ESGetResponse response) {\n                    if (response.isExists()) {\n                        super.onResponse(new BytesRestResponse(RestStatus.OK));\n                    } else {\n                        super.onResponse(new BytesRestResponse(RestStatus.NOT_FOUND));\n                    }\n                }\n            });\n    \t}\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/get/RestMultiGetAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.get;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESMultiGetRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.document.ESMultiGetResponse;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Sets;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.elasticsearch.search.fetch.source.FetchSourceContext;\nimport org.springframework.stereotype.Component;\n\nimport java.util.*;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n@Component(\"restMultiGetAction\")\npublic class RestMultiGetAction extends ESAction {\n\n\tpublic static final String AUTHORIZATION = \"Authorization\";\n\t\n\t@Override\n\tpublic String name() {\n\t\treturn \"multiGet\";\n\t}\n\t\n    private static final boolean allowExplicitIndex = true;\n\n    @Override\n\tpublic void handleInterRequest(final QueryContext queryContext, RestRequest request, RestChannel channel)\n\t\t\tthrows Exception {\n\t\tESMultiGetRequest esMultiGetRequest = new ESMultiGetRequest();\n\n\t\tMap<String, String> params = request.params();\n\t\tesMultiGetRequest.setParams(params);\n\n\t\tesMultiGetRequest.refresh(request.param(\"refresh\"));\n\t\tesMultiGetRequest.preference(request.param(\"preference\"));\n\t\tesMultiGetRequest.realtime(request.paramAsBoolean(\"realtime\", null));\n\t\tesMultiGetRequest.ignoreErrorsOnGeneratedFields(request.paramAsBoolean(\"ignore_errors_on_generated_fields\", false));\n\n        FetchSourceContext defaultFetchSource = FetchSourceContext.parseFromRestRequest(request);\n\t\tesMultiGetRequest.add(request.param(\"index\"), request.param(\"type\"), null, defaultFetchSource, request.param(\"routing\"), RestActions.getRestContent(request), allowExplicitIndex);\n\n        // multi get body may contain index, so this will check indices again\n        addIndices(queryContext, esMultiGetRequest);\n        checkIndicesAndTemplateBlockRead(queryContext);\n\n\t\tList<String> indices = queryContext.getIndices();\n\t\tIndexTemplate indexTemplate = null;\n\t\tif (isIndexType(queryContext)) {\n\t\t\tindexTemplate = getTemplateByIndexTire(indices, queryContext);\n\n\t\t\t// 该索引模板需要根据type名称进行映射到对应的索引模板\n\t\t\tif (isNeedChangeIndexName(queryContext, indexTemplate)) {\n\n\t\t\t\tESMultiGetRequest resetMultiGetRequest = new ESMultiGetRequest();\n\t\t\t\tresetMultiGetRequest.setParams(params);\n\t\t\t\tresetMultiGetRequest.refresh(request.param(\"refresh\"));\n\t\t\t\tresetMultiGetRequest.preference(request.param(\"preference\"));\n\t\t\t\tresetMultiGetRequest.realtime(request.paramAsBoolean(\"realtime\", null));\n\t\t\t\tresetMultiGetRequest.ignoreErrorsOnGeneratedFields(request.paramAsBoolean(\"ignore_errors_on_generated_fields\", false));\n\n\t\t\t\tMap<String/*typeName*/,String/*templateName*/> typeIndexMapping = indexTemplate.getMasterInfo().getTypeIndexMapping();\n\t\t\t\tString sourceTemplateName = indexTemplate.getName();\n\t\t\t\tString destTemplateName = null;\n\n\t\t\t\tList<String> sourceIndexNameList = Lists.newArrayList();\n\t\t\t\tList<String> typeNameList = Lists.newArrayList();\n\t\t\t\tList<String> destIndexNameList = Lists.newArrayList();\n\n\t\t\t\t// 取出每一个get请求中的index和type信息\n\t\t\t\tfor (ESMultiGetRequest.Item item : esMultiGetRequest.getItems()) {\n\t\t\t\t\tString typeName = item.type();\n\t\t\t\t\tString sourceIndexName = item.index();\n\t\t\t\t\tString destIndexName = sourceIndexName;\n\t\t\t\t\tsourceIndexNameList.add(sourceIndexName);\n\t\t\t\t\ttypeNameList.add(typeName);\n\n\t\t\t\t\t// 用户指定type方式查询时，gateway需要将该多type索引和指定的type名称映射为对应的单type索引，然后转发到es。\n\t\t\t\t\tif (StringUtils.isNoneBlank(typeName)) {\n\t\t\t\t\t\tdestTemplateName = typeIndexMapping.get(typeName);\n\t\t\t\t\t\tif (StringUtils.isNoneBlank(destTemplateName)) {\n\t\t\t\t\t\t\tdestIndexName = sourceIndexName.replace(sourceTemplateName, destTemplateName);\n\t\t\t\t\t\t\tindexTemplate = indexTemplateService.getIndexTemplate(destTemplateName);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdestIndexNameList.add(destIndexName);\n\t\t\t\t\t\titem.index(destIndexName).type(typeName);\n\t\t\t\t\t\tresetMultiGetRequest.add(item);\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// 用户不指定type方式查询时，gateway需要将该多type索引映射为多个单type索引，然后转发到es，数据聚合功能由es完成。\n\t\t\t\t\t\tfor (String name : typeIndexMapping.values()) {\n\t\t\t\t\t\t\tdestTemplateName = name;\n\t\t\t\t\t\t\tdestIndexName = sourceIndexName.replace(sourceTemplateName, name);\n\t\t\t\t\t\t\tdestIndexNameList.add(destIndexName);\n\t\t\t\t\t\t\titem.index(destIndexName).type(typeName);\n\t\t\t\t\t\t\tresetMultiGetRequest.add(item);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tindexTemplate = indexTemplateService.getIndexTemplate(destTemplateName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// 替换mget请求\n\t\t\t\tesMultiGetRequest = resetMultiGetRequest;\n\t\t\t\tif (queryContext.isDetailLog()) {\n\t\t\t\t\tJoinLogContext joinLogContext = queryContext.getJoinLogContext();\n\t\t\t\t\tjoinLogContext.setSourceIndexNames(StringUtils.join(sourceIndexNameList, \",\"));\n\t\t\t\t\tjoinLogContext.setTypeName(StringUtils.join(typeNameList, \",\"));\n\t\t\t\t\tjoinLogContext.setDestIndexName(StringUtils.join(destIndexNameList, \",\"));\n\t\t\t\t\tjoinLogContext.setSourceTemplateName(sourceTemplateName);\n\t\t\t\t\tjoinLogContext.setDestTemplateName(destTemplateName);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tESClient readClient = esClusterService.getClient(queryContext, indexTemplate, actionName);\n\n\t\tfinal List<FetchFields> fetchFieldsList = new ArrayList<>(esMultiGetRequest.getItems().size());\n        for (ESMultiGetRequest.Item item : esMultiGetRequest.getItems()) {\n        \tFetchFields fetchFields = new FetchFields();\n\t\t\tfetchFields.setFields(item.fields());\n        \tfetchFields.setFetchSourceContext(item.fetchSourceContext());\n            if (fetchFields.getFields() != null) {\n                for (String field : fetchFields.getFields()) {\n        \t\t\tif (field.equals(QueryConsts.MESSAGE_FIELD)) {\n        \t\t\t\tfetchFields.setHasMessageField(true);\n        \t\t\t\tbreak;\n        \t\t\t}\n        \t\t}\n            }\n            \n            fetchFieldsList.add(fetchFields);\n        }\n        \n        boolean needGetVersion = false;\n\t\tESMultiGetRequest newMultiGetRequest = new ESMultiGetRequest();\n        final List<Integer> versionPos = new ArrayList<>();\n        final List<Integer> versionValue = new ArrayList<>();\n        int pos = 0;\n        for (ESMultiGetRequest.Item item : esMultiGetRequest.getItems()) {\n        \tString index = item.index();\n        \tint indexVersion = indexTemplateService.getIndexVersion(index, queryContext.getCluster());\n        \tif (indexVersion > 0) {\n        \t\tversionPos.add(pos);\n        \t\tversionValue.add(indexVersion);\n        \t\tneedGetVersion = true;\n        \t\tfor (int i = indexVersion; i >= 0; i--) {\n        \t\t\tString inIndex = item.index();\n                \tif (i > 0) {\n                \t\tinIndex = index+\"_v\"+i;\n                \t}\n\n\t\t\t\t\tESMultiGetRequest.Item newItem = new ESMultiGetRequest.Item(inIndex, item.type(), item.id());\n\n\t\t\t\t\tnewItem.fetchSourceContext(item.fetchSourceContext());\n        \t\t\tnewItem.version(item.version());\n\t\t\t\t\tnewItem.versionType(item.versionType());\n        \t\t\tnewItem.fields(item.fields());\n        \t\t\tnewItem.routing(item.routing());\n        \t\t\t\n        \t\t\tnewMultiGetRequest.add(newItem);\n        \t\t\t\n        \t\t\t++pos;\n        \t\t}\n        \t} else {\n        \t\tnewMultiGetRequest.add(item);\n        \t\t\n        \t\t++pos;\n        \t}\n        }\n        \n        if (needGetVersion) {\n\t\t\tActionListener<ESMultiGetResponse> listener = new RestActionListenerImpl<ESMultiGetResponse>(queryContext) {\n\t\t\t\t@Override\n\t\t\t\tpublic void onResponse(ESMultiGetResponse response) {\n\t\t\t\t\tList<ESMultiGetResponse.Item> itemList = new ArrayList<>();\n\t\t\t\t\tIterator<Integer> posIter = versionPos.iterator();\n\t\t\t\t\tIterator<Integer> versionIter = versionValue.iterator();\n\t\t\t\t\tint itemPos = 0;\n\t\t\t\t\tint currentVersion = 0;\n\t\t\t\t\tif (posIter.hasNext()) {\n\t\t\t\t\t\titemPos = posIter.next();\n\t\t\t\t\t\tcurrentVersion = versionIter.next();\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (int i = 0; i < response.getResponses().size(); ++i) {\n\t\t\t\t\t\tESMultiGetResponse.Item item = response.getResponses().get(i);\n\t\t\t\t\t\tif (i == itemPos) {\n\t\t\t\t\t\t\tESMultiGetResponse.Item newGetItemResponse = null;\n\t\t\t\t\t\t\tfor (int p = 0; p <= currentVersion; p++) {\n\t\t\t\t\t\t\t\tnewGetItemResponse = response.getResponses().get(i + p);\n\t\t\t\t\t\t\t\tif (newGetItemResponse.getResponse() != null && newGetItemResponse.getResponse().isExists()) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\titemList.add(newGetItemResponse);\n\n\t\t\t\t\t\t\tfor (int p = 1; p <= currentVersion; p++) {\n\t\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (posIter.hasNext()) {\n\t\t\t\t\t\t\t\titemPos = posIter.next();\n\t\t\t\t\t\t\t\tcurrentVersion = versionIter.next();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\titemList.add(item);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tESMultiGetResponse newResponse = new ESMultiGetResponse();\n\t\t\t\t\tnewResponse.setResponses(itemList);\n\t\t\t\t\tsuper.onResponse(newResponse);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tnewMultiGetRequest.putHeader(\"requestId\", queryContext.getRequestId());\n\t\t\tnewMultiGetRequest.putHeader(AUTHORIZATION, queryContext.getRequest().getHeader(AUTHORIZATION));\n\n\t\t\treadClient.multiGet(newMultiGetRequest, listener);\n        } else {\n\t\t\tActionListener<ESMultiGetResponse> listener = new RestActionListenerImpl<>(queryContext);\n\t\t\tesMultiGetRequest.putHeader(\"requestId\", queryContext.getRequestId());\n\t\t\tesMultiGetRequest.putHeader(AUTHORIZATION, queryContext.getRequest().getHeader(AUTHORIZATION));\n\t\t\treadClient.multiGet(esMultiGetRequest, listener);\n        }\n        \n    }\n    \n    private void addIndices(QueryContext queryContext, ESMultiGetRequest request) {\n    \tSet<String> typeNames = Sets.newHashSet();\n    \tfor (ESMultiGetRequest.Item item : request.getItems()) {\n    \t\tqueryContext.addIndex(item.index());\n\t\t\ttypeNames.add(item.type());\n    \t}\n\t\tqueryContext.setTypeNames(typeNames);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/search/RestClearScrollAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.search;\n\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESClearScrollRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESClearScrollResponse;\nimport org.elasticsearch.action.search.ClearScrollRequest;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.springframework.stereotype.Component;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Base64;\nimport java.util.List;\n\nimport static com.didi.arius.gateway.common.consts.RestConsts.SCROLL_SPLIT;\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n/**\n */\n@Component(\"restClearScrollAction\")\npublic class RestClearScrollAction extends ESAction {\n\n\t@Override\n\tpublic String name() {\n\t\treturn \"clearScroll\";\n\t}\n\t\n    @Override\n\tpublic void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel)\n\t\t\tthrows Exception {\n        String scrollIds = request.param(\"scroll_id\");\n\n        ClearScrollRequest clearRequest = new ClearScrollRequest();\n        clearRequest.setScrollIds(Arrays.asList(splitScrollIds(scrollIds)));\n        if (RestActions.hasBodyContent(request)) {\n            XContentType type = RestActions.guessBodyContentType(request);\n           if (type == null) {\n               scrollIds = RestActions.getRestContent(request).toUtf8();\n               clearRequest.setScrollIds(Arrays.asList(splitScrollIds(scrollIds)));\n           } else {\n               // NOTE: if rest request with xcontent body has request parameters, these parameters does not override xcontent value\n               clearRequest.setScrollIds(null);\n               buildFromContent(RestActions.getRestContent(request), clearRequest);\n           }\n        }\n\n        ESClient readClient;\n        List<String> scrolls;\n        if (isIndexType(queryContext)) {\n            String cluster = null;\n\n            scrolls = new ArrayList<>();\n            for (String scrollIdWrap : clearRequest.getScrollIds()) {\n                int pos = scrollIdWrap.indexOf(SCROLL_SPLIT);\n                if (pos <= 0) {\n                    throw new InvalidParameterException(\"scrollId format error, scrollId=\" +  scrollIdWrap);\n                }\n\n                String clusterEncode = scrollIdWrap.substring(0, pos);\n                byte[] bytes = Base64.getUrlDecoder().decode(clusterEncode);\n                String inCluster = new String(bytes);\n\n                if (cluster == null) {\n                    cluster = inCluster;\n                } else if (!cluster.equals(inCluster)) {\n                    throw new InvalidParameterException(\"scrollId cluster error, scrollId=\" +  scrollIdWrap);\n                }\n\n                String realScrollId = scrollIdWrap.substring(pos+1);\n                scrolls.add(realScrollId);\n            }\n\n            readClient = esClusterService.getClientFromCluster(queryContext, cluster, actionName);\n        } else {\n            readClient = esClusterService.getClient(queryContext, actionName);\n            scrolls = clearRequest.getScrollIds();\n        }\n\n        ESClearScrollRequest esClearScrollRequest = new ESClearScrollRequest();\n        esClearScrollRequest.setScrollIds(scrolls);\n\n        esClearScrollRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        esClearScrollRequest.putHeader(\"Authorization\", request.getHeader(\"Authorization\"));\n\n        RestActionListenerImpl<ESClearScrollResponse> listener = new RestActionListenerImpl<>(queryContext);\n        readClient.clearScroll(esClearScrollRequest, listener);\n    }\n\n    public static String[] splitScrollIds(String scrollIds) {\n        if (scrollIds == null) {\n            return Strings.EMPTY_ARRAY;\n        }\n        return Strings.splitStringByCommaToArray(scrollIds);\n    }\n\n    public static void buildFromContent(BytesReference content, ClearScrollRequest clearScrollRequest) {\n        try (XContentParser parser = XContentHelper.createParser(content)) {\n            if (parser.nextToken() != XContentParser.Token.START_OBJECT) {\n                throw new IllegalArgumentException(\"Malformed content, must start with an object\");\n            } else {\n                XContentParser.Token token;\n                String currentFieldName = null;\n                while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n                    if (token == XContentParser.Token.FIELD_NAME) {\n                        currentFieldName = parser.currentName();\n                    } else if (\"scroll_id\".equals(currentFieldName) && token == XContentParser.Token.START_ARRAY) {\n                        dealScroll(clearScrollRequest, parser);\n                    } else {\n                        throw new IllegalArgumentException(\"Unknown parameter [\" + currentFieldName + \"] in request body or parameter is of the wrong type[\" + token + \"] \");\n                    }\n                }\n            }\n        } catch (IOException e) {\n            throw new IllegalArgumentException(\"Failed to parse request body\", e);\n        }\n    }\n\n    private static void dealScroll(ClearScrollRequest clearScrollRequest, XContentParser parser) throws IOException {\n        XContentParser.Token token;\n        while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {\n            if (!token.isValue()) {\n                throw new IllegalArgumentException(\"scroll_id array element should only contain scroll_id\");\n            }\n            clearScrollRequest.addScrollId(parser.text());\n        }\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/search/RestMultiSearchAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.search;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.consts.RestConsts;\nimport com.didi.arius.gateway.common.metadata.*;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESMultiSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESMultiSearchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.support.IndicesOptions;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.collect.Tuple;\nimport org.elasticsearch.common.util.concurrent.AtomicArray;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.springframework.stereotype.Component;\n\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static com.didi.arius.gateway.common.consts.RestConsts.SCROLL_SPLIT;\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n\n/**\n *\n */\n@Component(\"restMultiSearchAction\")\npublic class RestMultiSearchAction extends ESAction {\n\n    private static final String TYPED_KEYS = \"typed_keys\";\n    private static final boolean ALLOW_EXPLICIT_INDEX = true;\n\n    @Override\n    public String name() {\n        return \"multiSearch\";\n    }\n\n    @Override\n    public void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        handle(queryContext, request, new ESMultiSearchRequest());\n    }\n\n    private void handle(QueryContext queryContext, RestRequest request, ESMultiSearchRequest esMultiSearchRequest) throws Exception {\n        long start = System.currentTimeMillis();\n\n        Map<String, String> params = new HashMap<>();\n        if (request.hasParam(TYPED_KEYS)) {\n            params.put(TYPED_KEYS, request.param(TYPED_KEYS));\n        }\n        params.put(QueryConsts.SEARCH_IGNORE_THROTTLED, \"false\");\n\n        String[] types = Strings.splitStringByCommaToArray(request.param(\"type\"));\n        String[] indices = Strings.splitStringByCommaToArray(request.param(\"index\"));\n        String path = request.path();\n        boolean isTemplateRequest = isTemplateRequest(path);\n        esMultiSearchRequest.setTemplateRequest(isTemplateRequest);\n\n        IndicesOptions indicesOptions = IndicesOptions.fromRequest(request, IndicesOptions.strictExpandOpenAndForbidClosed());\n        esMultiSearchRequest.add(RestActions.getRestContent(request), isTemplateRequest, indices, types, request.param(\"search_type\"), request.param(\"routing\"), indicesOptions, ALLOW_EXPLICIT_INDEX );\n\n        // multi search body may contain index, so this will check indices again\n        addIndices(queryContext, esMultiSearchRequest);\n        checkIndicesAndTemplateBlockRead(queryContext);\n\n        final List<FetchFields> fetchFieldsList = new ArrayList<>(esMultiSearchRequest.requests().size());\n\n        String dateFrom = queryContext.getRequest().param(RestConsts.SEARCH_DATE_FROM_PARAMS);\n        String dateTo = queryContext.getRequest().param(RestConsts.SEARCH_DATE_TO_PARAMS);\n\n        long paramTime = System.currentTimeMillis();\n\n        ActionListener<ESMultiSearchResponse> multiListener = new RestActionListenerImpl<ESMultiSearchResponse>(queryContext) {\n            @Override\n            public void onResponse(ESMultiSearchResponse esMultiSearchResponse) {\n\n                JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n                joinLogContext.setTotalCost(System.currentTimeMillis() - queryContext.getRequestTime());\n                for (ESMultiSearchResponse.Item item : esMultiSearchResponse.getResponses()) {\n                    ESSearchResponse esSearchResponse = item.getResponse();\n                    if (esSearchResponse == null) {\n                        continue;\n                    }\n                    logSearchResponse(queryContext, esSearchResponse);\n                }\n                super.onResponse(esMultiSearchResponse);\n            }\n        };\n\n        // 并发search请求\n        final AtomicInteger counter = new AtomicInteger(esMultiSearchRequest.requests().size());\n        final AtomicArray<ESMultiSearchResponse.Item> responses = new AtomicArray<>(esMultiSearchRequest.requests().size());\n\n        for (int i = 0; i < esMultiSearchRequest.requests().size(); ++i) {\n            ESSearchRequest esSearchRequest = esMultiSearchRequest.requests().get(i);\n            esSearchRequest.putHeader(\"Authorization\", queryContext.getRequest().getHeader(\"Authorization\"));\n            esSearchRequest.putHeader(\"requestId\", queryContext.getRequestId());\n            esSearchRequest.setParams(params);\n\n            List<String> itemIndices = Arrays.asList(esSearchRequest.indices());\n            IndexTemplate indexTemplate = null;\n            if (isIndexType(queryContext, itemIndices)) {\n                if (itemIndices.size() == 1) {\n                    indexTemplate = getTemplateByIndex(itemIndices, queryContext);\n                }\n\n                if (indexTemplate != null) {\n                    if(!isAliasGet(indexTemplate, itemIndices)){\n                        String[] newIndices = getQueryIndices(indexTemplate, dateFrom, dateTo);\n                        esSearchRequest.indices(newIndices);\n                    }\n                } else {\n                    indexTemplate = getTemplateByIndexTire(itemIndices, queryContext);\n                }\n\n                // 该索引模板需要根据type名称进行映射到对应的索引模板\n                if (isNeedChangeIndexName(queryContext, indexTemplate)) {\n\n                    Tuple<IndexTemplate/*dest template*/, String[]/*dest indexNames*/> changeResult =\n                            handleChangeIndexName(queryContext, indexTemplate, esSearchRequest.indices(), esSearchRequest.types());\n\n                    // 替换查询语句中的索引名称\n                    esSearchRequest.indices(changeResult.v2());\n                    // 再替换索引模板对象\n                    indexTemplate = changeResult.v1();\n                }\n            }\n\n            long indexTemplateTime = System.currentTimeMillis();\n\n            if (esSearchRequest.indices().length == 1\n                    && indexTemplate != null\n                    && esSearchRequest.indices()[0].equals(indexTemplate.getName())) {\n                String[] newIndices = getQueryIndices(indexTemplate, dateFrom, dateTo);\n\n                esSearchRequest.indices(newIndices);\n            }\n\n            // 日期索引加上*号后缀，支持异常索引修复方案\n            Convert.convertIndices(esSearchRequest);\n\n            ESClient readClient = esClusterService.getClient(queryContext, indexTemplate, actionName);\n            queryContext.setClusterName(readClient.getClusterName());\n\n            long getClientTime = System.currentTimeMillis();\n\n            // pre process\n            preSearchProcess(queryContext, readClient, esSearchRequest);\n            long preProcessTime = System.currentTimeMillis();\n\n            FetchFields fetchFields = formFetchFields(esSearchRequest);\n            fetchFieldsList.add(fetchFields);\n\n            long currentTimeMillis = System.currentTimeMillis();\n            final int index = i;\n\n            ActionListener<ESSearchResponse> listener = new RestActionListenerImpl<ESSearchResponse>(queryContext) {\n                @Override\n                public void onResponse(ESSearchResponse esSearchResponse) {\n                    if (!Strings.isEmpty(esSearchResponse.getScrollId())\n                            && queryContext.getAppDetail().getSearchType() == AppDetail.RequestType.INDEX) {\n                        String encode = Base64.getEncoder().encodeToString(readClient.getClusterName().getBytes());\n                        esSearchResponse.setScrollId(encode + SCROLL_SPLIT + esSearchResponse.getScrollId());\n                    }\n\n                    ESMultiSearchResponse.Item item = new ESMultiSearchResponse.Item(esSearchResponse, null);\n                    item.setStatus(esSearchResponse.getRestStatus().getStatus());\n\n                    responses.set(index, item);\n                    if (counter.decrementAndGet() == 0) {\n                        finish(responses, multiListener);\n                    }\n                }\n\n                @Override\n                public void onFailure(Throwable e) {\n                    try {\n                        String strException = exceptionToJsonString(e);\n                        JSONObject err = JSON.parseObject(strException);\n                        ESMultiSearchResponse.Item item = new ESMultiSearchResponse.Item(null, err.get(\"error\"));\n                        item.setStatus(err.getIntValue(\"status\"));\n\n                        responses.set(index, item);\n                    } catch (Exception ex) {\n                        ESMultiSearchResponse.Item item = new ESMultiSearchResponse.Item(null, \"unknow\");\n                        item.setStatus(RestStatus.INTERNAL_SERVER_ERROR.getStatus());\n                        responses.set(index, item);\n                    }\n\n                    if (counter.decrementAndGet() == 0) {\n                        finish(responses, multiListener);\n                    }\n\n                    if (queryContext.isDetailLog()) {\n                        JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n                        joinLogContext.setSearchCost(System.currentTimeMillis() - currentTimeMillis);\n                        joinLogContext.setAriusType(\"error\");\n                        joinLogContext.setClusterName(queryContext.getClient().getClusterName());\n                        joinLogContext.setClientVersion(queryContext.getClient().getEsVersion());\n                        joinLogContext.setLogicId(queryContext.getIndexTemplate() != null ? queryContext.getIndexTemplate().getId() : -1);\n                        joinLogContext.setTotalCost(System.currentTimeMillis() - queryContext.getRequestTime());\n                        joinLogContext.setInternalCost( joinLogContext.getTotalCost() - joinLogContext.getEsCost());\n                        joinLogContext.setSinkTime(System.currentTimeMillis());\n                        joinLogContext.setExceptionName(e.getClass().getName());\n                        joinLogContext.setStack(Convert.logExceptionStack(e));\n                        String log = joinLogContext.toString();\n\n                        statLogger.error(log);\n                    }\n                }\n            };\n\n            JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n            joinLogContext.setParamCost(paramTime - start);\n            joinLogContext.setIndexTemplateCost(indexTemplateTime - paramTime);\n            joinLogContext.setGetClientCost(getClientTime - indexTemplateTime);\n            joinLogContext.setPreProcessCost(preProcessTime - getClientTime);\n\n            readClient.search(esSearchRequest, listener);\n        }\n    }\n\n    private boolean isTemplateRequest(String path) {\n        return (path != null && path.endsWith(\"/template\"));\n    }\n\n    private void finish(AtomicArray<ESMultiSearchResponse.Item> responses, ActionListener<ESMultiSearchResponse> listener) {\n        ESMultiSearchResponse esMultiSearchResponse = new ESMultiSearchResponse();\n        esMultiSearchResponse.setRestStatus(RestStatus.OK);\n        ESMultiSearchResponse.Item[] responseArr = responses.toArray(new ESMultiSearchResponse.Item[responses.length()]);\n        esMultiSearchResponse.setResponses(Arrays.asList(responseArr));\n        listener.onResponse(esMultiSearchResponse);\n    }\n\n    private void addIndices(QueryContext queryContext, ESMultiSearchRequest esMultiSearchRequest) {\n        for (ESSearchRequest request : esMultiSearchRequest.requests()) {\n            String[] indices = request.indices();\n            for (String index : indices) {\n                queryContext.addIndex(index);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/search/RestSearchAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.search;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\nimport com.didi.arius.gateway.common.consts.RestConsts;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport java.util.List;\nimport java.util.Map;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.collect.Tuple;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.elasticsearch.search.builder.SearchSourceBuilder;\nimport org.elasticsearch.search.fetch.source.FetchSourceContext;\nimport org.springframework.stereotype.Component;\n\n/**\n *\n */\n@Component(\"restSearchAction\")\npublic class RestSearchAction extends ESAction {\n\n    @Override\n    public String name() {\n        return \"search\";\n    }\n\n    @Override\n    public void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel)\n            throws Exception {\n        handle(queryContext, request, new ESSearchRequest());\n    }\n\n    private void handle(QueryContext queryContext, RestRequest request, ESSearchRequest esSearchRequest) {\n        long start = System.currentTimeMillis();\n        esSearchRequest.indices(Strings.splitStringByCommaToArray(request.param(\"index\")));\n        esSearchRequest.types(Strings.splitStringByCommaToArray(request.param(\"type\")));\n        esSearchRequest.setTemplateRequest(request.path().endsWith(\"/template\"));\n        esSearchRequest.source(RestActions.getRestContent(request));\n        Map<String, String> params = request.params();\n        params.remove(\"source\");\n        params.remove(\"index\");\n        params.remove(\"type\");\n        addFilterPathDefaultValue(params);\n        \n        esSearchRequest.setParams(params);\n\n        esSearchRequest.extraSource(parseSearchExtraSource(request));\n\n        FetchFields fetchFields = formFetchFields(esSearchRequest);\n        queryContext.setFetchFields(fetchFields);\n\n        esSearchRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        esSearchRequest.putHeader(\"Authorization\", request.getHeader(\"Authorization\"));\n\n        long paramTime = System.currentTimeMillis();\n\n        IndexTemplate indexTemplate = null;\n        if (isIndexType(queryContext)) {\n            List<String> indices = queryContext.getIndices();\n            if (indices.size() == 1) {\n                indexTemplate = getTemplateByIndex(indices, queryContext);\n            }\n\n            if (indexTemplate != null) {\n                if(!isAliasGet(indexTemplate, indices)){\n                    String dateFrom = queryContext.getRequest().param(RestConsts.SEARCH_DATE_FROM_PARAMS);\n                    String dateTo = queryContext.getRequest().param(RestConsts.SEARCH_DATE_TO_PARAMS);\n\n                    String[] newIndices = getQueryIndices(indexTemplate, dateFrom, dateTo);\n\n                    esSearchRequest.indices(newIndices);\n                }\n            } else {\n                indexTemplate = getTemplateByIndexTire(indices, queryContext);\n            }\n\n            // 该索引模板需要根据type名称进行映射到对应的索引模板\n            if (isNeedChangeIndexName(queryContext, indexTemplate)) {\n\n                Tuple<IndexTemplate/*dest template*/, String[]/*dest indexNames*/> changeResult =\n                        handleChangeIndexName(queryContext, indexTemplate, esSearchRequest.indices(), esSearchRequest.types());\n\n                // 替换查询语句中的索引名称\n                esSearchRequest.indices(changeResult.v2());\n                // 再替换索引模板对象\n                indexTemplate = changeResult.v1();\n            }\n        }\n\n        long indexTemplateTime = System.currentTimeMillis();\n\n        // 索引加上*号后缀，支持异常索引修复方案\n        Convert.convertIndices(esSearchRequest);\n\n        ESClient readClient = esClusterService.getClient(queryContext, indexTemplate, actionName);\n\n        long getClientTime = System.currentTimeMillis();\n\n        // pre process\n        preSearchProcess(queryContext, readClient, esSearchRequest);\n\n        long preProcessTime = System.currentTimeMillis();\n\n        ActionListener<ESSearchResponse> listener = newSearchListener(queryContext);\n        readClient.search(esSearchRequest, listener);\n\n        JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n        joinLogContext.setParamCost(paramTime - start);\n        joinLogContext.setIndexTemplateCost(indexTemplateTime - paramTime);\n        joinLogContext.setGetClientCost(getClientTime - indexTemplateTime);\n        joinLogContext.setPreProcessCost(preProcessTime - getClientTime);\n    }\n\n\n    public static SearchSourceBuilder parseSearchExtraSource(RestRequest request) {\n        SearchSourceBuilder searchSourceBuilder = null;\n\n        String sField = request.param(\"fields\");\n        if (sField != null) {\n            searchSourceBuilder = new SearchSourceBuilder();\n\n            if (!Strings.hasText(sField)) {\n                searchSourceBuilder.noFields();\n            } else {\n                String[] sFields = Strings.splitStringByCommaToArray(sField);\n                if (sFields != null) {\n                    for (String field : sFields) {\n                        searchSourceBuilder.field(field);\n                    }\n                }\n            }\n        }\n\n        FetchSourceContext fetchSourceContext = FetchSourceContext.parseFromRestRequest(request);\n        if (fetchSourceContext != null) {\n            if (searchSourceBuilder == null) {\n                searchSourceBuilder = new SearchSourceBuilder();\n            }\n            searchSourceBuilder.fetchSource(fetchSourceContext);\n        }\n\n        return searchSourceBuilder;\n    }\n\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/search/RestSearchScrollAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.search;\n\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchScrollRequest;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.search.SearchScrollRequest;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.unit.TimeValue;\nimport org.elasticsearch.common.xcontent.XContentFactory;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.elasticsearch.common.xcontent.XContentParser;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.elasticsearch.search.Scroll;\nimport org.springframework.stereotype.Component;\n\nimport java.io.IOException;\nimport java.util.Base64;\n\nimport static com.didi.arius.gateway.common.consts.RestConsts.SCROLL;\nimport static com.didi.arius.gateway.common.consts.RestConsts.SCROLL_SPLIT;\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\nimport static org.elasticsearch.common.unit.TimeValue.parseTimeValue;\n\n/**\n *\n */\n@Component(\"restSearchScrollAction\")\npublic class RestSearchScrollAction extends ESAction {\n\n\t@Override\n\tpublic String name() {\n\t\treturn \"searchScroll\";\n\t}\n\n    @Override\n    public void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        long start = System.currentTimeMillis();\n\n        String scrollId = request.param(\"scroll_id\");\n        SearchScrollRequest searchScrollRequest = new SearchScrollRequest();\n        searchScrollRequest.scrollId(scrollId);\n        String scroll = request.param(SCROLL);\n        if (scroll != null) {\n            searchScrollRequest.scroll(new Scroll(parseTimeValue(scroll, null, SCROLL)));\n        }\n\n        if (RestActions.hasBodyContent(request)) {\n            XContentType type = XContentFactory.xContentType(RestActions.getRestContent(request));\n            if (type == null) {\n                if (scrollId == null) {\n                    scrollId = RestActions.getRestContent(request).toUtf8();\n                    searchScrollRequest.scrollId(scrollId);\n                }\n            } else {\n                // NOTE: if rest request with xcontent body has request parameters, these parameters override xcontent values\n                buildFromContent(RestActions.getRestContent(request), searchScrollRequest);\n            }\n        }\n\n        long paramTime = System.currentTimeMillis();\n\n        ESClient readClient;\n        String realScrollId;\n        if (isIndexType(queryContext)) {\n            String scrollIdWrap = searchScrollRequest.scrollId();\n\n            int pos = scrollIdWrap.indexOf(SCROLL_SPLIT);\n            if (pos <= 0) {\n                throw new InvalidParameterException(\"scrollId format error, scrollId=\" +  scrollIdWrap);\n            }\n\n            String clusterEncode = scrollIdWrap.substring(0, pos);\n            byte[] bytes = Base64.getUrlDecoder().decode(clusterEncode);\n            String cluster = new String(bytes);\n\n            realScrollId = scrollIdWrap.substring(pos+1);\n            readClient = esClusterService.getClientFromCluster(queryContext, cluster, actionName);\n        } else {\n            realScrollId = searchScrollRequest.scrollId();\n            readClient = esClusterService.getClient(queryContext, actionName);\n        }\n\n        long getClientTime = System.currentTimeMillis();\n\n        ESSearchScrollRequest esSearchScrollRequest = new ESSearchScrollRequest();\n        esSearchScrollRequest.setScrollId(realScrollId);\n        if (searchScrollRequest.scroll() != null) {\n            esSearchScrollRequest.scroll(searchScrollRequest.scroll().keepAlive());\n        }\n\n        esSearchScrollRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        esSearchScrollRequest.putHeader(\"Authorization\", queryContext.getRequest().getHeader(\"Authorization\"));\n\n        FetchFields fetchFields = new FetchFields();\n        fetchFields.setHasMessageField(false);\n        queryContext.setFetchFields(fetchFields);\n\n        ActionListener<ESSearchResponse> listener = newSearchListener(queryContext);\n        readClient.searchScroll(esSearchScrollRequest, listener);\n\n        JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n        joinLogContext.setParamCost(paramTime - start);\n        joinLogContext.setGetClientCost(getClientTime - paramTime);\n    }\n\n    public static void buildFromContent(BytesReference content, SearchScrollRequest searchScrollRequest) {\n        try (XContentParser parser = XContentHelper.createParser(content)) {\n            if (parser.nextToken() != XContentParser.Token.START_OBJECT) {\n                throw new IllegalArgumentException(\"Malforrmed content, must start with an object\");\n            } else {\n                XContentParser.Token token;\n                String currentFieldName = null;\n                while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {\n                    if (token == XContentParser.Token.FIELD_NAME) {\n                        currentFieldName = parser.currentName();\n                    } else if (\"scroll_id\".equals(currentFieldName) && token == XContentParser.Token.VALUE_STRING) {\n                        searchScrollRequest.scrollId(parser.text());\n                    } else if (SCROLL.equals(currentFieldName) && token == XContentParser.Token.VALUE_STRING) {\n                        searchScrollRequest.scroll(new Scroll(TimeValue.parseTimeValue(parser.text(), null, SCROLL)));\n                    } else {\n                        throw new IllegalArgumentException(\"Unknown parameter [\" + currentFieldName + \"] in request body or parameter is of the wrong type[\" + token + \"] \");\n                    }\n                }\n            }\n        } catch (IOException e) {\n            throw new IllegalArgumentException(\"Failed to parse request body\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/search/RestSpatialMultiSearchAction.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.core.es.http.search;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESMultiSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESMultiSearchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.support.IndicesOptions;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.util.concurrent.AtomicArray;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.springframework.stereotype.Component;\n\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static com.didi.arius.gateway.common.consts.RestConsts.SCROLL_SPLIT;\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n/**\n *\n */\n@Component(\"restSpatialMultiSearchAction\")\npublic class RestSpatialMultiSearchAction extends ESAction {\n\n    private static final boolean ALLOW_EXPLICIT_INDEX = true;\n    private static final String TYPED_KEYS = \"typed_keys\";\n\n    @Override\n    public String name() {\n        return \"spatial_msearch\";\n    }\n\n    @Override\n    public void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) throws Exception {\n        handle(queryContext, request, new ESMultiSearchRequest(\"/_spatial_msearch\"));\n    }\n\n    private void handle(QueryContext queryContext, RestRequest request, ESMultiSearchRequest esMultiSearchRequest) throws Exception {\n        Map<String, String> params = new HashMap<>();\n        if (request.hasParam(TYPED_KEYS)) {\n            params.put(TYPED_KEYS, request.param(TYPED_KEYS));\n        }\n        params.put(QueryConsts.SEARCH_IGNORE_THROTTLED, \"false\");\n\n        String[] indices = Strings.splitStringByCommaToArray(request.param(\"index\"));\n        String[] types = Strings.splitStringByCommaToArray(request.param(\"type\"));\n        String path = request.path();\n        boolean isTemplateRequest = isTemplateRequest(path);\n        esMultiSearchRequest.setTemplateRequest(isTemplateRequest);\n\n        IndicesOptions indicesOptions = IndicesOptions.fromRequest(request, IndicesOptions.strictExpandOpenAndForbidClosed());\n        esMultiSearchRequest.add(RestActions.getRestContent(request), isTemplateRequest, indices, types, request.param(\"search_type\"), request.param(\"routing\"), indicesOptions, ALLOW_EXPLICIT_INDEX );\n\n        // multi search body may contain index, so this will check indices again\n        addIndices(queryContext, esMultiSearchRequest);\n        checkIndicesAndTemplateBlockRead(queryContext);\n\n        final List<FetchFields> fetchFieldsList = new ArrayList<>(esMultiSearchRequest.requests().size());\n\n        ActionListener<ESMultiSearchResponse> multiListener = new RestActionListenerImpl<ESMultiSearchResponse>(queryContext) {\n            @Override\n            public void onResponse(ESMultiSearchResponse esMultiSearchResponse) {\n                statLogger.info(QueryConsts.DLFLAG_PREFIX + \"query_search_query||requestId={}||cost={}\", queryContext.getRequestId(), (System.currentTimeMillis() - queryContext.getRequestTime()));\n\n                for (ESMultiSearchResponse.Item item : esMultiSearchResponse.getResponses()) {\n                    ESSearchResponse esSearchResponse = item.getResponse();\n\n                    if (esSearchResponse == null) {\n                        continue;\n                    }\n\n                    logSearchResponse(queryContext, esSearchResponse);\n                }\n                super.onResponse(esMultiSearchResponse);\n            }\n        };\n\n        // 并发search请求\n        final AtomicInteger counter = new AtomicInteger(esMultiSearchRequest.requests().size());\n        final AtomicArray<ESMultiSearchResponse.Item> responses = new AtomicArray<>(esMultiSearchRequest.requests().size());\n\n        for (int i = 0; i < esMultiSearchRequest.requests().size(); ++i) {\n            ESSearchRequest esSearchRequest = esMultiSearchRequest.requests().get(i);\n            esSearchRequest.putHeader(\"requestId\", queryContext.getRequestId());\n            esSearchRequest.putHeader(\"Authorization\", queryContext.getRequest().getHeader(\"Authorization\"));\n            esSearchRequest.setParams(params);\n\n            List<String> itemIndices = Arrays.asList(esSearchRequest.indices());\n            IndexTemplate indexTemplate = null;\n            if (isIndexType(queryContext, itemIndices)) {\n                if (itemIndices.size() == 1) {\n                    indexTemplate = getTemplateByIndex(itemIndices, queryContext);\n                }\n\n                if (indexTemplate == null) {\n                    indexTemplate = getTemplateByIndexTire(itemIndices, queryContext);\n                }\n            }\n\n            ESClient readClient = esClusterService.getClient(queryContext, indexTemplate, actionName);\n            queryContext.setClusterName(readClient.getClusterName());\n\n            // pre process\n            preSearchProcess(queryContext, readClient, esSearchRequest);\n\n            FetchFields fetchFields = formFetchFields(esSearchRequest);\n            fetchFieldsList.add(fetchFields);\n\n            final int index = i;\n\n            ActionListener<ESSearchResponse> listener = getEsSearchResponseActionListener(queryContext, multiListener, counter, responses, readClient, index);\n\n            readClient.search(esSearchRequest, listener);\n        }\n    }\n\n    private ActionListener<ESSearchResponse> getEsSearchResponseActionListener(QueryContext queryContext, ActionListener<ESMultiSearchResponse> multiListener, AtomicInteger counter, AtomicArray<ESMultiSearchResponse.Item> responses, ESClient readClient, int index) {\n        return new RestActionListenerImpl<ESSearchResponse>(queryContext) {\n            @Override\n            public void onResponse(ESSearchResponse esSearchResponse) {\n                if (!Strings.isEmpty(esSearchResponse.getScrollId())\n                        && queryContext.getAppDetail().getSearchType() == AppDetail.RequestType.INDEX) {\n                    String encode = Base64.getEncoder().encodeToString(readClient.getClusterName().getBytes());\n                    esSearchResponse.setScrollId(encode + SCROLL_SPLIT + esSearchResponse.getScrollId());\n                }\n\n                ESMultiSearchResponse.Item item = new ESMultiSearchResponse.Item(esSearchResponse, null);\n                item.setStatus(esSearchResponse.getRestStatus().getStatus());\n\n                responses.set(index, item);\n                if (counter.decrementAndGet() == 0) {\n                    finish(responses, multiListener);\n                }\n            }\n\n            @Override\n            public void onFailure(Throwable e) {\n                try {\n                    String strException = exceptionToJsonString(e);\n                    JSONObject err = JSON.parseObject(strException);\n                    ESMultiSearchResponse.Item item = new ESMultiSearchResponse.Item(null, err.get(\"error\"));\n                    item.setStatus(err.getIntValue(\"status\"));\n\n                    responses.set(index, item);\n                } catch (Exception ex) {\n                    ESMultiSearchResponse.Item item = new ESMultiSearchResponse.Item(null, \"unknow\");\n                    item.setStatus(RestStatus.INTERNAL_SERVER_ERROR.getStatus());\n                    responses.set(index, item);\n                }\n\n                if (counter.decrementAndGet() == 0) {\n                    finish(responses, multiListener);\n                }\n            }\n        };\n    }\n\n    private boolean isTemplateRequest(String path) {\n        return (path != null && path.endsWith(\"/template\"));\n    }\n\n    private void addIndices(QueryContext queryContext, ESMultiSearchRequest esMultiSearchRequest) {\n        for (ESSearchRequest request : esMultiSearchRequest.requests()) {\n            String[] indices = request.indices();\n            for (String index : indices) {\n                queryContext.addIndex(index);\n            }\n        }\n    }\n\n    private void finish(AtomicArray<ESMultiSearchResponse.Item> responses, ActionListener<ESMultiSearchResponse> listener) {\n        ESMultiSearchResponse esMultiSearchResponse = new ESMultiSearchResponse();\n        esMultiSearchResponse.setRestStatus(RestStatus.OK);\n        ESMultiSearchResponse.Item[] responseArr = responses.toArray(new ESMultiSearchResponse.Item[responses.length()]);\n        esMultiSearchResponse.setResponses(Arrays.asList(responseArr));\n        listener.onResponse(esMultiSearchResponse);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/search/RestSpatialSearchAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.search;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.ESAction;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport java.util.List;\nimport java.util.Map;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.action.support.RestActions;\nimport org.springframework.stereotype.Component;\n\n@Component(\"restSpatialSearchAction\")\npublic class RestSpatialSearchAction extends ESAction {\n\n    public static final String INDEX = \"index\";\n\n    @Override\n    public String name() {\n        return \"spatial_search\";\n    }\n\n    @Override\n    public void handleInterRequest(QueryContext queryContext, RestRequest request, RestChannel channel) {\n        String index = queryContext.getRequest().param(INDEX);\n        if (!Strings.hasText(index)) {\n            throw new IllegalArgumentException(\"index must not be null\");\n        }\n\n        if (index.endsWith(\"*\")) {\n            throw new IllegalArgumentException(\"index must not contain the following characters [ , \\\\\\\", *, \\\\\\\\, <, |, ,, >, /, ?]\");\n        }\n\n        String[] indicesArr = Strings.splitStringByCommaToArray(index);\n        if (indicesArr == null || indicesArr.length != 1) {\n            throw new IllegalArgumentException(\"only one index\");\n        }\n\n        handle(queryContext, request, new ESSearchRequest(\"/_spatial_search\"));\n    }\n\n    private void handle(QueryContext queryContext, RestRequest request, ESSearchRequest esSearchRequest) {\n        long start = System.currentTimeMillis();\n        esSearchRequest.indices(Strings.splitStringByCommaToArray(request.param(INDEX)));\n        esSearchRequest.types(Strings.splitStringByCommaToArray(request.param(\"type\")));\n        esSearchRequest.setTemplateRequest(request.path().endsWith(\"/template\"));\n        esSearchRequest.source(RestActions.getRestContent(request));\n        Map<String, String> params = request.params();\n        params.remove(\"source\");\n        params.remove(INDEX);\n        params.remove(\"type\");\n        addFilterPathDefaultValue(params);\n        params.put(QueryConsts.SEARCH_IGNORE_THROTTLED, \"false\");\n        esSearchRequest.setParams(params);\n\n        esSearchRequest.extraSource(RestSearchAction.parseSearchExtraSource(request));\n\n        FetchFields fetchFields = formFetchFields(esSearchRequest);\n        queryContext.setFetchFields(fetchFields);\n\n        esSearchRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        esSearchRequest.putHeader(\"Authorization\", request.getHeader(\"Authorization\"));\n\n        long paramTime = System.currentTimeMillis();\n\n        IndexTemplate indexTemplate = null;\n        if (isIndexType(queryContext)) {\n            List<String> indicesList = queryContext.getIndices();\n            if (indicesList.size() == 1) {\n                indexTemplate = getTemplateByIndex(indicesList, queryContext);\n            }\n\n            if (indexTemplate == null) {\n                indexTemplate = getTemplateByIndexTire(indicesList, queryContext);\n            }\n        }\n\n        long indexTemplateTime = System.currentTimeMillis();\n\n        ESClient readClient = esClusterService.getClient(queryContext, indexTemplate, actionName);\n\n        long getClientTime = System.currentTimeMillis();\n\n        // pre process\n        preSearchProcess(queryContext, readClient, esSearchRequest);\n\n        long preProcessTime = System.currentTimeMillis();\n\n        ActionListener<ESSearchResponse> listener = newSearchListener(queryContext);\n        readClient.search(esSearchRequest, listener);\n\n        JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n        joinLogContext.setParamCost(paramTime - start);\n        joinLogContext.setIndexTemplateCost(indexTemplateTime - paramTime);\n        joinLogContext.setGetClientCost(getClientTime - indexTemplateTime);\n        joinLogContext.setPreProcessCost(preProcessTime - getClientTime);\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/sql/SQLAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.sql;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.consts.RestConsts;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.es.http.HttpRestHandler;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport org.apache.commons.collections.CollectionUtils;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.search.SearchRequest;\nimport org.elasticsearch.common.collect.Tuple;\nimport org.nlpcn.es4sql.query.SqlElasticRequestBuilder;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n@Component(\"sqlAction\")\npublic class SQLAction extends HttpRestHandler {\n\n\t@Override\n\tpublic String name() {\n\t\treturn \"sql\";\n\t}\n\n\t@Override\n\tpublic void handleRequest(QueryContext queryContext) throws Exception {\n\n\t\tcheckFlowLimit(queryContext);\n\t\tSqlElasticRequestBuilder requestBuilder = buildRequest(queryContext.getPostBody());\n\t\tSearchRequest searchRequest = (SearchRequest) requestBuilder.request();\n\n\t\tList<String> indices = Arrays.asList(searchRequest.indices());\n\t\tqueryContext.setIndices(indices);\n\t\tqueryContext.setTypeNames(searchRequest.types());\n\t\tcheckIndicesAndTemplateBlockRead(queryContext);\n\n        ESSearchRequest esSearchRequest = new ESSearchRequest();\n        esSearchRequest.indices(searchRequest.indices());\n\n\t\tIndexTemplate indexTemplate = null;\n\t\tif (isIndexType(queryContext)) {\n\t\t    if (indices.size() == 1) {\n                indexTemplate = getTemplateByIndex(indices, queryContext);\n            }\n\n\t\t    if (indexTemplate != null) {\n\t\t\t\tif(!isAliasGet(indexTemplate, indices)){\n\t\t\t\t\tString dateFrom = queryContext.getRequest().param(RestConsts.SEARCH_DATE_FROM_PARAMS);\n\t\t\t\t\tString dateTo = queryContext.getRequest().param(RestConsts.SEARCH_DATE_TO_PARAMS);\n\n\t\t\t\t\tesSearchRequest.indices(getQueryIndices(indexTemplate, dateFrom, dateTo));\n\t\t\t\t}\n            } else {\n\t\t        indexTemplate = getTemplateByIndexTire(indices, queryContext);\n            }\n\n\t\t    // 该索引模板需要根据type名称进行映射到对应的索引模板\n\t\t    if (isNeedChangeIndexName(queryContext, indexTemplate)) {\n\t\t\t\tTuple<IndexTemplate/*dest template*/, String[]/*dest indexNames*/> changeResult =\n\t\t\t\t\t\thandleChangeIndexName(queryContext, indexTemplate, searchRequest.indices(), searchRequest.types());\n\n\t\t\t\t// 替换查询语句中的索引名称\n\t\t\t\tesSearchRequest.indices(changeResult.v2());\n\t\t\t\t// 再替换索引模板对象\n\t\t\t\tindexTemplate = changeResult.v1();\n\t\t\t}\n\n\t\t}\n\n        esSearchRequest.types(searchRequest.types());\n        esSearchRequest.source(searchRequest.source());\n\t\tMap<String, String> params = queryContext.getRequest().params();\n\t\tparams.remove(\"source\");\n\t\tparams.remove(\"index\");\n\t\tparams.remove(\"type\");\n\t\tparams.remove(\"filter_path\");\n\t\tparams.remove(RestConsts.SEARCH_DATE_FROM_PARAMS);\n\t\tparams.remove(RestConsts.SEARCH_DATE_TO_PARAMS);\n\t\tsetRouteAndScroll(searchRequest, params);\n\n\t\tesSearchRequest.setParams(params);\n\n        esSearchRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        esSearchRequest.putHeader(\"Authorization\", queryContext.getRequest().getHeader(\"Authorization\"));\n\n\t\t// 日期索引加上*号后缀，支持异常索引修复方案\n\t\tConvert.convertIndices(esSearchRequest);\n\n\t\tESClient client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n\n\t\t// pre process\n\t\tpreSearchProcess(queryContext, client, esSearchRequest);\n\n\t\tFetchFields fetchFields = formFetchFields(esSearchRequest);\n\t\tqueryContext.setFetchFields(fetchFields);\n\n\t\tif (queryContext.isDetailLog()) {\n\t\t\tJoinLogContext joinLogContext = queryContext.getJoinLogContext();\n\t\t\tjoinLogContext.setBeforeCost(System.currentTimeMillis() - queryContext.getRequestTime());\n\t\t}\n\n\t\tActionListener<ESSearchResponse> listener = newSearchListener(queryContext);\n\t\tclient.search(esSearchRequest, listener);\n\t}\n\n\tprivate void setRouteAndScroll(SearchRequest searchRequest, Map<String, String> params) {\n\t\tif (searchRequest.routing() != null && !params.containsKey(\"routing\")) {\n\t\t\tparams.put(\"routing\", searchRequest.routing());\n\t\t}\n\n\t\tif (searchRequest.scroll() != null && searchRequest.scroll().keepAlive() != null && !params.containsKey(\"scroll\")) {\n\t\t\tparams.put(\"scroll\", searchRequest.scroll().keepAlive().toString());\n\t\t}\n\t}\n\n\tprivate boolean isAliasGet(IndexTemplate indexTemplate, List<String> indexs){\n\t\tif(CollectionUtils.isEmpty(indexTemplate.getAliases())){\n\t\t\treturn false;\n\t\t}\n\n\t\tfor(String index : indexs){\n\t\t\tif(indexTemplate.getAliases().contains( index )){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/http/sql/SQLExplainAction.java",
    "content": "package com.didi.arius.gateway.core.es.http.sql;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.HttpRestHandler;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestStatus;\nimport org.nlpcn.es4sql.query.SqlElasticRequestBuilder;\nimport org.springframework.stereotype.Component;\n\n/**\n* @author weizijun\n* @date：2016年8月28日\n* \n*/\n@Component(\"sqlExplainAction\")\npublic class SQLExplainAction extends HttpRestHandler {\n\t\n\t@Override\n\tpublic String name() {\n\t\treturn \"sqlExplain\";\n\t}\n    \n\t@Override\n\tpublic void handleRequest(QueryContext queryContext) throws Exception {\n\t\tSqlElasticRequestBuilder requestBuilder = buildRequest(queryContext.getPostBody());\n\n\t\tString queryDSL = requestBuilder.explain();\n\n\t\tsendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, XContentType.JSON.restContentType(), queryDSL));\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/ActionController.java",
    "content": "package com.didi.arius.gateway.core.es.tcp;\n\nimport org.elasticsearch.transport.ActionNotFoundTransportException;\nimport org.springframework.stereotype.Component;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n\n/**\n* @author weizijun\n* @date：2016年9月19日\n* \n*/\n@Component(\"actionController\")\npublic class ActionController {\n\tprivate Map<String, ActionHandler> actionMap = new HashMap<>();\n\t\n\tpublic void registerHandler(String action, ActionHandler handler) {\n\t\tactionMap.put(action, handler);\n\t}\n\t\n\tpublic ActionHandler getHandler(String action) {\n\t\tActionHandler handler = actionMap.get(action);\n\t\tif (handler == null) {\n\t\t\tthrow new ActionNotFoundTransportException(action);\n\t\t}\n\t\t\n\t\treturn handler;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/ActionHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.exception.FlowLimitException;\nimport com.didi.arius.gateway.common.exception.ServerBusyException;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.es.http.ESBase;\nimport com.didi.arius.gateway.core.service.*;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.log.LogGather;\nimport org.elasticsearch.ExceptionsHelper;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.cluster.block.ClusterBlockException;\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.common.transport.TransportAddress;\nimport org.elasticsearch.rest.RestStatus;\nimport org.elasticsearch.transport.TransportChannel;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.concurrent.TimeUnit;\n\n/**\n* @author weizijun\n* @date：2016年9月18日\n* \n*/\n@Component(\"actionHandler\")\npublic abstract class ActionHandler extends ESBase {\n\tprotected static final ILog logger = LogFactory.getLog(ActionHandler.class);\n\tprotected static final Logger statLogger = LoggerFactory.getLogger(QueryConsts.STAT_LOGGER);\n\tprotected static final ILog traceLogger = LogFactory.getLog(QueryConsts.TRACE_LOGGER);\n\t\n\t@Autowired\n\tprotected ActionController controller;\n\t\n\t@Autowired\n\tprotected ESTcpClientService esTcpClientService;\n\t\n    @Autowired\n    protected RateLimitService rateLimitService;\n\n\t@Autowired\n\tprotected QueryConfig queryConfig;\n\n\t@Autowired\n\tprotected RequestStatsService requestStatsService;\n\t@Autowired\n\tprotected MetricsService metricsService;\n\t\n\tpublic void handleRequest(ActionContext actionContext) throws IOException {\n\t\ttry {\n\t\t\tif (!actionContext.getSemaphore().tryAcquire(10, TimeUnit.MILLISECONDS)) {\n\t\t\t\tthrow new ServerBusyException(\"too many block queries, please wait and retry\");\n\t\t\t}\n\t\t\t\n\t\t\tcheckToken(actionContext);\n\t\t\t\n\t\t\tcheckFlowLimit(actionContext);\n\t\t\t\n\t\t\tpreRequest(actionContext);\n\t\t\t\n\t        handleInterRequest(actionContext, 0);\n\t        \n\t        postRequest(actionContext);\n\t\t} catch (Exception e) {\n\t\t\tif (!(e instanceof ServerBusyException)) {\n\t\t\t\tactionContext.getSemaphore().release();\n\t\t\t}\n\n\t\t\tpreException(actionContext, e);\n\t\t\t\n\t\t\tTransportChannel channel = actionContext.getChannel();\n\t\t\tchannel.sendResponse(e);\n\n\t\t\trequestStatsService.removeActionContext(actionContext.getRequestId());\n\t\t}\n\t}\n\n\tprotected void checkToken(ActionContext actionContext) {\n\t\tappService.checkToken(actionContext);\n\t\tString encode = Base64.getEncoder().encodeToString(String.format(\"%s\", \"user_\" + actionContext.getAppid() + \":\" + actionContext.getAppDetail().getVerifyCode()).getBytes(StandardCharsets.UTF_8));\n\t\tactionContext.getRequest().putHeader(\"Authorization\", \"Basic \" + encode);\n\t}\n\t\n\tpublic abstract void handleInterRequest(ActionContext actionContext, int retryTimes) throws Exception;\n\n\tprotected abstract  Class<? extends TransportRequest> getRequestClass();\n\t\n\tpublic abstract String name();\n\t\n\tpublic TransportRequest parseRequest(TransportAddress remoteAddress, StreamInput buffer) throws InstantiationException, IllegalAccessException, IOException {\n        Class<? extends TransportRequest> cls = getRequestClass();\n\n        final TransportRequest request = cls.newInstance();\n        request.remoteAddress(remoteAddress);\n        request.readFrom(buffer);\n        \n        return request;\n\t}\n\t\n\tprotected void preRequest(ActionContext actionContext) {\n\t\tstatLogger.info(QueryConsts.DLFLAG_PREFIX + \"query_tcp_request||appid={}||requestId={}||action={}||group={}||clusterId={}||clusterName={}||user={}||remoteAddr={}||requestLen={}\",\n\t\t\t\tactionContext.getAppid(), actionContext.getRequestId(), actionContext.getActionName(), QueryConsts.GATEWAY_GROUP, actionContext.getClusterId(), actionContext.getCluster(), actionContext.getUser(),\n\t\t\t\tactionContext.getRemoteAddr(), actionContext.getRequestLength());\n\t\tactionContext.setRequestTime(System.currentTimeMillis());\n\t\t\n\n\t\ttraceLogger.info(\"_com_request_in||traceid={}||spanid={}||type=tcp||appid={}||requestId={}||action={}||remoteAddr={}||requestLen={}\",\n\t\t\t\tactionContext.getTraceid(), actionContext.getSpanid(), actionContext.getAppid(), actionContext.getRequestId(), actionContext.getActionName(), actionContext.getRemoteAddr(), actionContext.getRequestLength());\n\t}\n\t\n\tprotected void postRequest(ActionContext actionContext) {\n\t\tint appid = actionContext.getAppDetail() != null ? actionContext.getAppDetail().getId() : QueryConsts.TOTAL_APPID_ID;\n\t\trequestStatsService.statsAdd(name(), appid, actionContext.getSearchId(), actionContext.getCostTime(), RestStatus.OK);\n\n\t\tString searchId = actionContext.getSearchId() != null ? actionContext.getSearchId() : QueryConsts.TOTAL_SEARCH_ID;\n\t\ttry {\n\t\t\trateLimitService.addUp(appid, searchId, 0, 0);\n\t\t} catch (Exception e) {\n\t\t\tlogger.warn(\"rateLimitService.addUp exception\", e);\n\t\t}\n\t\t\n\t}\n\t\n\tprotected void preException(ActionContext actionContext, Throwable e) {\n\t\tactionContext.setResponseTime(System.currentTimeMillis());\n\t\tstatLogger.error(QueryConsts.DLFLAG_PREFIX + \"query_tcp_pre_exception||requestId={}||appid={}||action={}||name={}||stack={}\",\n\t\t\t\tactionContext.getRequestId(), actionContext.getAppid(), actionContext.getActionName(), e.getClass().getName(), Convert.logExceptionStack(e));\n\t\t\n\t\tactionContext.setResponseTime(System.currentTimeMillis());\n\t\ttraceLogger.info(\"_com_request_out||traceid={}||spanid={}||type=tcp||exception=pre||appid={}||requestId={}||action={}||proc_time={}||errname={}\",\n\t\t\t\tactionContext.getTraceid(), actionContext.getSpanid(), actionContext.getAppid(), actionContext.getRequestId(), actionContext.getActionName(), actionContext.getCostTime(), e.getClass().getName());\n\t\t\n\t\tLogGather.recordErrorLog(e.getClass().getName() + \"_\" + actionContext.getAppid(), \"tcp_pre_exception||appid=\" + actionContext.getAppid(), e);\n\t}\n\n\tprotected void checkFlowLimit(ActionContext actionContext) {\n\t\tif (rateLimitService.isTrafficDataOverflow(actionContext.getAppDetail().getId(), actionContext.getSearchId())) {\n\t\t\tthrow new FlowLimitException(\"query flow limit, please try again!\");\n\t\t}\n\t}\n\t\n    public static class RetryListener<Response> implements ActionListener<Response> {\n        private final ActionListener<Response> listener;\n        private final ActionContext actionContext;\n        private final ActionHandler actionHandler;\n\n        private int retryTimes;\n\n        public RetryListener(ActionHandler actionHandler, ActionContext actionContext, ActionListener<Response> listener, int retryTimes) {\n        \tthis.actionHandler = actionHandler;\n            this.listener = listener;\n            this.actionContext = actionContext;\n            this.retryTimes = retryTimes;\n        }\n\n        @Override\n        public void onResponse(Response response) {\n            listener.onResponse(response);\n        }\n\n        @Override\n        public void onFailure(Throwable e) {\n        \tThrowable ex = ExceptionsHelper.unwrapCause(e);\n            if (ex instanceof ClusterBlockException) {\n            \ttry {\n\t\t\t\t\tThread.sleep(QueryConsts.RETRY_SLEEP_MILLIS);\n\t\t\t\t} catch (Exception e1) {\n            \t\t// pass\n\t\t\t\t}\n\n                if (retryTimes >= QueryConsts.RETRY_COUNT) {\n                    listener.onFailure(e);\n                } else {\n                    try {\n                    \tactionHandler.handleInterRequest(actionContext, retryTimes+1);\n                    } catch(final Exception t) {\n                        // this exception can't come from the TransportService as it doesn't throw exceptions at all\n                        listener.onFailure(t);\n                    }\n                }\n            } else {\n                listener.onFailure(e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/ActionListenerImpl.java",
    "content": "package com.didi.arius.gateway.core.es.tcp;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.event.ActionPostResponseEvent;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.core.component.SpringTool;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.log.LogGather;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.ActionResponse;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年9月20日\n* \n*/\npublic class ActionListenerImpl<T extends ActionResponse> implements ActionListener<T> {\n\tprotected static final ILog logger = LogFactory.getLog(ActionListenerImpl.class);\n\tprotected static final Logger statLogger = LoggerFactory.getLogger(QueryConsts.STAT_LOGGER);\n\tprotected static final ILog traceLogger = LogFactory.getLog(QueryConsts.TRACE_LOGGER);\n\t\n\tprotected ActionContext actionContext;\n\t\n\tpublic ActionListenerImpl(ActionContext actionContext) {\n\t\tthis.actionContext = actionContext;\n\t}\n\t\n\t@Override\n\tpublic void onResponse(T response) {\n\t\ttry {\n\t\t\tactionContext.getSemaphore().release();\n\t\t\t\n\t\t\tactionContext.getChannel().sendResponse(response);\n\t\t\t\n\t\t\tpostResponse(actionContext);\n\t\t} catch (IOException e) {\n\t\t\tlogger.error(\"onResponse sendResponse error:\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onFailure(Throwable e) {\n\t\ttry {\n\t\t\tactionContext.getSemaphore().release();\n\t\t\t\n\t\t\tactionContext.getChannel().sendResponse(e);\n\t\t\t\n\t\t\tpostResponse(actionContext, e);\n\t\t} catch (IOException e1) {\n\t\t\tlogger.error(\"onFailure sendResponse error:\", e1);\n\t\t}\n\t}\n\t\n\tprotected void postResponse(ActionContext actionContext, Throwable e) {\n\t\tactionContext.setResponseTime(System.currentTimeMillis());\n\t\tstatLogger.error(QueryConsts.DLFLAG_PREFIX + \"query_tcp_exception||requestId={}||appid={}||action={}||name={}\", \n\t\t\t\tactionContext.getRequestId(), actionContext.getAppid(), actionContext.getActionName(), e.getClass().getName());\n\t\t\n\t\ttraceLogger.info(\"_com_request_out||traceid={}||spanid={}||type=tcp||exception=after||appid={}||requestId={}||action={}||proc_time={}||errname={}\",\n\t\t\t\tactionContext.getTraceid(), actionContext.getSpanid(), actionContext.getAppid(), actionContext.getRequestId(), actionContext.getActionName(), actionContext.getCostTime(), e.getClass().getName());\n\t\t\n\t\tLogGather.recordErrorLog(e.getClass().getName() + \"_\" + actionContext.getAppid(), \"tcp_exception||appid=\" + actionContext.getAppid(), e);\n\n\t\tSpringTool.publish(new ActionPostResponseEvent(this, actionContext));\n\t}\t\n\t\n\tprotected void postResponse(ActionContext actionContext) {\n\t\tactionContext.setResponseTime(System.currentTimeMillis());\n\t\tstatLogger.info(QueryConsts.DLFLAG_PREFIX + \"query_tcp_response||requestId={}||appid={}||action={}||cost={}\", \n\t\t\t\tactionContext.getRequestId(), actionContext.getAppid(), actionContext.getActionName(), actionContext.getCostTime());\n\n\t\ttraceLogger.info(\"_com_request_out||traceid={}||spanid={}||type=tcp||appid={}||requestId={}||action={}||proc_time={}\",\n\t\t\t\tactionContext.getTraceid(), actionContext.getSpanid(), actionContext.getAppid(), actionContext.getRequestId(), actionContext.getActionName(), actionContext.getCostTime());\n\n\t\tSpringTool.publish(new ActionPostResponseEvent(this, actionContext));\n\t}\n\t\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/ActionManager.java",
    "content": "package com.didi.arius.gateway.core.es.tcp;\n\nimport org.elasticsearch.action.admin.cluster.node.liveness.LivenessRequest;\nimport org.elasticsearch.action.admin.cluster.node.liveness.TransportLivenessAction;\nimport org.elasticsearch.action.get.GetAction;\nimport org.elasticsearch.action.get.GetRequest;\nimport org.elasticsearch.action.search.SearchAction;\nimport org.elasticsearch.action.search.SearchRequest;\nimport org.elasticsearch.transport.TransportRequest;\n\nimport java.util.HashMap;\n\n/**\n * @author weizijun @date：2016年9月18日\n * \n */\npublic class ActionManager {\n\tprivate static HashMap<String, Class<? extends TransportRequest>> actionRequestMap = new HashMap<>();\n\n\tprivate static HashMap<Class<? extends TransportRequest>, String> requestActionMap = new HashMap<>();\n\n\tstatic {\n\t\tActionManager.regist(GetAction.NAME, GetRequest.class);\n\t\tActionManager.regist(SearchAction.NAME, SearchRequest.class);\n\t\tActionManager.regist(TransportLivenessAction.NAME, LivenessRequest.class);\n\t}\n\n\tprivate ActionManager() {\n\t\t// pass\n\t}\n\n\tpublic static void regist(String action, Class<? extends TransportRequest> cls) {\n\t\tif (actionRequestMap.containsKey(action) || requestActionMap.containsKey(cls)){\n\t\t\tthrow new IllegalArgumentException(\"Action \" + action + \" already exists\");\n\t\t}\n\t\tactionRequestMap.put(action, cls);\n\t\trequestActionMap.put(cls, action);\n\t}\n\n\tpublic static String getAction(Class<? extends TransportRequest> cls) {\n\t\treturn requestActionMap.get(cls);\n\t}\n\n\tpublic static Class<? extends TransportRequest> getRequestClass(String action) {\n\t\treturn actionRequestMap.get(action);\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/count/CountHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp.count;\n\nimport com.didi.arius.gateway.core.es.tcp.ActionHandler;\nimport com.didi.arius.gateway.core.es.tcp.ActionListenerImpl;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.count.CountAction;\nimport org.elasticsearch.action.count.CountRequest;\nimport org.elasticsearch.action.count.CountResponse;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n* @author weizijun\n* @date：2016年9月21日\n* \n*/\n@Component(\"countHandler\")\npublic class CountHandler extends ActionHandler {\n\t@Override\n\tpublic String name() {\n\t\treturn CountAction.NAME;\n\t}\n\t\n    @PostConstruct\n    public void init() {\n        controller.registerHandler(CountAction.NAME, this);\n    }\n    \n\t@Override\n\tpublic void handleInterRequest(ActionContext actionContext, int retryTimes) {\n\t\tCountRequest countRequest = (CountRequest)actionContext.getRequest();\n\t\t\n\t\tList<String> indices = Arrays.asList(countRequest.indices());\n\t\tappService.checkIndices(actionContext, indices);\n\t\t\n\t\tString[] newIndices = Convert.convertIndices(countRequest.indices());\n\t\tcountRequest.indices(newIndices);\n\n        ActionListener<CountResponse> listener = new ActionListenerImpl<>(actionContext);\n        esTcpClientService.getClient(actionContext.getCluster()).count(countRequest, new RetryListener<>(this, actionContext, listener, retryTimes));\n\t}\n\n\t@Override\n\tprotected Class<? extends TransportRequest> getRequestClass() {\n\t\treturn CountRequest.class;\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/exists/ExistsHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp.exists;\n\nimport com.didi.arius.gateway.core.es.tcp.ActionHandler;\nimport com.didi.arius.gateway.core.es.tcp.ActionListenerImpl;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.exists.ExistsAction;\nimport org.elasticsearch.action.exists.ExistsRequest;\nimport org.elasticsearch.action.exists.ExistsResponse;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n* @author weizijun\n* @date：2016年9月21日\n* \n*/\n@Component(\"existsHandler\")\npublic class ExistsHandler extends ActionHandler {\n\n\t@Override\n\tpublic String name() {\n\t\treturn ExistsAction.NAME;\n\t}\n\t\n    @PostConstruct\n    public void init() {\n        controller.registerHandler(ExistsAction.NAME, this);\n    }\t\n\t\n\t@Override\n\tpublic void handleInterRequest(ActionContext actionContext, int retryTimes) {\n\t\tExistsRequest existsRequest = (ExistsRequest) actionContext.getRequest();\n\t\t\n\t\tList<String> indices = Arrays.asList(existsRequest.indices());\n\t\tappService.checkIndices(actionContext, indices);\n\t\t\n\t\tString[] newIndices = Convert.convertIndices(existsRequest.indices());\n\t\texistsRequest.indices(newIndices);\n\t\t\n\t\tActionListener<ExistsResponse> listener = new ActionListenerImpl<>(actionContext);\n\t\tesTcpClientService.getClient(actionContext.getCluster()).exists(existsRequest, new RetryListener<>(this, actionContext, listener, retryTimes));\n\t}\n\n\t@Override\n\tprotected Class<? extends TransportRequest> getRequestClass() {\n\t\treturn ExistsRequest.class;\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/get/GetHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp.get;\n\nimport com.didi.arius.gateway.core.es.tcp.ActionHandler;\nimport com.didi.arius.gateway.core.es.tcp.ActionListenerImpl;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.get.*;\nimport org.elasticsearch.index.get.GetResult;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n* @author weizijun\n* @date：2016年9月18日\n* \n*/\n@Component(\"getHandler\")\npublic class GetHandler extends ActionHandler {\n\t\n\t@Override\n\tpublic String name() {\n\t\treturn GetAction.NAME;\n\t}\n\t\n    @PostConstruct\n    public void init() {\n        controller.registerHandler(GetAction.NAME, this);\n    }\n\t\n\t@Override\n\tpublic void handleInterRequest(ActionContext actionContext, int retryTimes) {\n\t\tfinal GetRequest getRequest = (GetRequest)actionContext.getRequest();\n\t\t\n\t\tList<String> indices = Arrays.asList(getRequest.index());\n\t\tappService.checkIndices(actionContext, indices);\n\t\t\n\t\tfinal FetchFields fetchFields = new FetchFields();\n\t\tfetchFields.setFields(getRequest.fields());\n\t\tfetchFields.setFetchSourceContext(getRequest.fetchSourceContext());\n\t\tif (fetchFields.getFields() != null) {\n\t\t\tfor (String field : fetchFields.getFields()) {\n\t\t\t\tif (field.equals(QueryConsts.MESSAGE_FIELD)) {\n\t\t\t\t\tfetchFields.setHasMessageField(true);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\t\n\t\t}\n\t\t\n    \tString index = getRequest.index();\n    \tfinal int indexVersion = indexTemplateService.getIndexVersion(index, actionContext.getCluster());\n    \tif (indexVersion > 0) {\n    \t\tMultiGetRequest multiGetRequest = getVersionRequest(indexVersion, getRequest);\n\n\t\t\tActionListener<MultiGetResponse> listener = getListener(actionContext, getRequest);\n\n\t\t\tesTcpClientService.getClient(actionContext.getCluster()).multiGet(multiGetRequest, listener);\n    \t} else {\n    \t\tActionListener<GetResponse> listener = new ActionListenerImpl<>(actionContext);\n            esTcpClientService.getClient(actionContext.getCluster()).get(getRequest, new RetryListener<>(this, actionContext, listener, retryTimes));\n    \t}\n\t}\n\n\tprivate ActionListener<MultiGetResponse> getListener(ActionContext actionContext, GetRequest getRequest) {\n\t\treturn new ActionListenerImpl<MultiGetResponse>(actionContext) {\n\t\t\t@Override\n\t\t\tpublic void onResponse(MultiGetResponse response) {\n\t\t\t\tGetResponse getResponse = null;\n\t\t\t\tfor (MultiGetItemResponse itemResponse : response.getResponses()) {\n\t\t\t\t\tif (itemResponse == null) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (itemResponse.getResponse() != null && itemResponse.getResponse().isExists()) {\n\t\t\t\t\t\tgetResponse = itemResponse.getResponse();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tgetResponse = itemResponse.getResponse();\n\t\t\t\t}\n\n\t\t\t\tif (getResponse == null) {\n\t\t\t\t\tGetResult getResult = new GetResult(getRequest.index(), getRequest.type(), getRequest.id(), -1, false, null, null);\n\t\t\t\t\tgetResponse = new GetResponse(getResult);\n\t\t\t\t}\n\t\t\t\tActionListener<GetResponse> listener = new ActionListenerImpl<>(actionContext);\n\t\t\t\tlistener.onResponse(getResponse);\n\t\t\t}\n\t\t};\n\t}\n\n\t@Override\n\tprotected Class<? extends TransportRequest> getRequestClass() {\n\t\treturn GetRequest.class;\n\t}\n\n}\n\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/get/MultiGetHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp.get;\n\nimport com.didi.arius.gateway.core.es.tcp.ActionHandler;\nimport com.didi.arius.gateway.core.es.tcp.ActionListenerImpl;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.get.MultiGetAction;\nimport org.elasticsearch.action.get.MultiGetItemResponse;\nimport org.elasticsearch.action.get.MultiGetRequest;\nimport org.elasticsearch.action.get.MultiGetRequest.Item;\nimport org.elasticsearch.action.get.MultiGetResponse;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\n\n/**\n* @author weizijun\n* @date：2016年9月21日\n* \n*/\n@Component(\"multiGetHandler\")\npublic class MultiGetHandler extends ActionHandler {\n\n\t@Override\n\tpublic String name() {\n\t\treturn MultiGetAction.NAME;\n\t}\n\t\n    @PostConstruct\n    public void init() {\n        controller.registerHandler(MultiGetAction.NAME, this);\n    }\t\n\t\n\t@Override\n\tpublic void handleInterRequest(ActionContext actionContext, int retryTimes) {\n\t\tMultiGetRequest multiGetRequest = (MultiGetRequest)actionContext.getRequest();\n\t\t\n\t\tList<String> indices = new ArrayList<>();\n\t\tfor (Item item : multiGetRequest.getItems()) {\n\t\t\tindices.add(item.index());\n\t\t}\n\t\tappService.checkIndices(actionContext, indices);\n\t\t\n\t\tfinal List<FetchFields> fetchFieldsList = new ArrayList<>(multiGetRequest.getItems().size());\n        for (Item item : multiGetRequest.getItems()) {\n\t\t\tgetField(fetchFieldsList, item);\n\t\t}\n\n        boolean needGetVersion = false;\n        MultiGetRequest newMultiGetRequest = new MultiGetRequest();\n        final List<Integer> versionPos = new ArrayList<>();\n        final List<Integer> versionValue = new ArrayList<>();\n        int pos = 0;\n        for (Item item : multiGetRequest.getItems()) {\n        \tString index = item.index();\n        \tint indexVersion = indexTemplateService.getIndexVersion(index, actionContext.getCluster());\n        \tif (indexVersion > 0) {\n        \t\tversionPos.add(pos);\n        \t\tversionValue.add(indexVersion);\n        \t\tneedGetVersion = true;\n        \t\tfor (int i = indexVersion; i >= 0; i--) {\n                \tString inIndex = item.index();\n                \tif (i > 0) {\n                \t\tinIndex = index+\"_v\"+i;\n                \t}\n\n        \t\t\tItem newItem = new Item(inIndex, item.type(), item.id());\n\n        \t\t\tnewItem.version(item.version());\n        \t\t\tnewItem.fetchSourceContext(item.fetchSourceContext());\n        \t\t\tnewItem.fields(item.fields());\n        \t\t\tnewItem.routing(item.routing());\n        \t\t\tnewItem.versionType(item.versionType());\n        \t\t\t\n        \t\t\tnewMultiGetRequest.add(newItem);\n        \t\t\t\n        \t\t\t++pos;\n        \t\t}\n        \t} else {\n        \t\tnewMultiGetRequest.add(item);\n        \t\t\n        \t\t++pos;\n        \t}\n        }\n        \n        if (needGetVersion) {\n\t\t\tActionListener<MultiGetResponse> listener = getMultiGetResponseActionListener(actionContext, versionPos, versionValue);\n\n\t\t\tesTcpClientService.getClient(actionContext.getCluster()).multiGet(newMultiGetRequest, new RetryListener<>(this, actionContext, listener, retryTimes));\n        } else {\n        \tActionListener<MultiGetResponse> listener = new ActionListenerImpl<>(actionContext);\n            esTcpClientService.getClient(actionContext.getCluster()).multiGet(multiGetRequest, new RetryListener<>(this, actionContext, listener, retryTimes));\n        }\n\t}\n\n\tprivate ActionListener<MultiGetResponse> getMultiGetResponseActionListener(ActionContext actionContext, List<Integer> versionPos, List<Integer> versionValue) {\n\t\treturn new ActionListenerImpl<MultiGetResponse>(actionContext) {\n\t\t\t@Override\n\t\t\tpublic void onResponse(MultiGetResponse response) {\n\t\t\t\tList<MultiGetItemResponse> itemList = new ArrayList<>();\n\t\t\t\tIterator<Integer> posIter = versionPos.iterator();\n\t\t\t\tIterator<Integer> versionIter = versionValue.iterator();\n\t\t\t\tint itemPos = 0;\n\t\t\t\tint currentVersion = 0;\n\t\t\t\tif (posIter.hasNext()) {\n\t\t\t\t\titemPos = posIter.next();\n\t\t\t\t\tcurrentVersion = versionIter.next();\n\t\t\t\t}\n\n\t\t\t\tdealResponse(response, itemList, posIter, versionIter, itemPos, currentVersion);\n\n\t\t\t\tMultiGetResponse newResponse = new MultiGetResponse(itemList.toArray(new MultiGetItemResponse[itemList.size()]));\n\t\t\t\tsuper.onResponse(newResponse);\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate void getField(List<FetchFields> fetchFieldsList, Item item) {\n\t\tFetchFields fetchFields = new FetchFields();\n\t\tfetchFields.setFetchSourceContext(item.fetchSourceContext());\n\t\tfetchFields.setFields(item.fields());\n\t\tif (fetchFields.getFields() != null) {\n\t\t\tfor (String field : fetchFields.getFields()) {\n\t\t\t\tif (field.equals(QueryConsts.MESSAGE_FIELD)) {\n\t\t\t\t\tfetchFields.setHasMessageField(true);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfetchFieldsList.add(fetchFields);\n\t}\n\n\tprivate void dealResponse(MultiGetResponse response, List<MultiGetItemResponse> itemList, Iterator<Integer> posIter, Iterator<Integer> versionIter, int itemPos, int currentVersion) {\n\t\tfor (int i = 0; i < response.getResponses().length; ++i) {\n\t\t\tMultiGetItemResponse itemResponse = response.getResponses()[i];\n\t\t\tif (i == itemPos) {\n\t\t\t\tMultiGetItemResponse newGetItemResponse = getMultiGetItemResponse(response, currentVersion, i);\n\n\t\t\t\titemList.add(newGetItemResponse);\n\n\t\t\t\tfor (int p = 1; p <= currentVersion; p++) {\n\t\t\t\t\ti++;\n\t\t\t\t}\n\n\t\t\t\tif (posIter.hasNext()) {\n\t\t\t\t\titemPos = posIter.next();\n\t\t\t\t\tcurrentVersion = versionIter.next();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\titemList.add(itemResponse);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate MultiGetItemResponse getMultiGetItemResponse(MultiGetResponse response, int currentVersion, int i) {\n\t\tMultiGetItemResponse newGetItemResponse = null;\n\t\tfor (int p = 0; p <= currentVersion; p++) {\n\t\t\tnewGetItemResponse = response.getResponses()[i + p];\n\t\t\tif (newGetItemResponse.getResponse() != null && newGetItemResponse.getResponse().isExists()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn newGetItemResponse;\n\t}\n\n\t@Override\n\tprotected Class<? extends TransportRequest> getRequestClass() {\n\t\treturn MultiGetRequest.class;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/liveness/LivenessHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp.liveness;\n\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.core.es.tcp.ActionHandler;\nimport com.didi.arius.gateway.core.es.tcp.ActionListenerImpl;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.admin.cluster.node.liveness.LivenessRequest;\nimport org.elasticsearch.action.admin.cluster.node.liveness.LivenessResponse;\nimport org.elasticsearch.action.admin.cluster.node.liveness.TransportLivenessAction;\nimport org.elasticsearch.cluster.ClusterName;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\n\n/**\n* @author weizijun\n* @date：2016年9月19日\n* \n*/\n@Component(\"livenessHandler\")\npublic class LivenessHandler extends ActionHandler {\n\n\t@Value(\"${gateway.cluster.name}\")\n\tprivate String gatewayClusterName;\n\tprivate ClusterName clusterName;\n\n\tpublic LivenessHandler() {\n\t\t// pass\n\t}\n\n\t@Override\n\tpublic String name() {\n\t\treturn TransportLivenessAction.NAME;\n\t}\n\t\n    @PostConstruct\n    public void init() {\n        controller.registerHandler(TransportLivenessAction.NAME, this);\n\t\tthis.clusterName = new ClusterName(gatewayClusterName);\n    }\t\n\t\n\t@Override\n\tpublic void handleInterRequest(ActionContext actionContext, int retryTimes) {\n\t\tActionListener<LivenessResponse> listener = new ActionListenerImpl<>(actionContext);\n\t\tlistener.onResponse(new LivenessResponse(this.clusterName, null));\n\t}\n\n\t@Override\n\tprotected Class<? extends TransportRequest> getRequestClass() {\n\t\treturn LivenessRequest.class;\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/search/BaseSearchHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp.search;\n\nimport com.didi.arius.gateway.core.es.tcp.ActionHandler;\nimport com.didi.arius.gateway.core.es.tcp.ActionListenerImpl;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.search.SearchRequest;\nimport org.elasticsearch.action.search.SearchResponse;\nimport org.elasticsearch.action.search.SearchScrollRequest;\nimport org.elasticsearch.action.search.ShardSearchFailure;\nimport org.elasticsearch.common.xcontent.XContentHelper;\n\nimport java.io.IOException;\n\n/**\n* @author weizijun\n* @date：2016年9月21日\n* \n*/\npublic abstract class BaseSearchHandler extends ActionHandler {\n\tpublic static final String APP_ID = \"appid=\";\n\tpublic static final String REQUEST_ID = \"requestId=\";\n\tpublic static final String INDICES = \"||indices=\";\n\tpublic static final String TYPES = \"||types=\";\n\tpublic static final String SOURCE = \"||source=\";\n\tpublic static final String EXTRA_SOURCE = \"||extra_source=\";\n\tpublic static final String TOOK_MILLIS = \"tookInMillis=\";\n\tpublic static final String SCROLL_ID = \"scrollId=\";\n\tpublic static final String TOTAL_SHARDS = \"totalShards=\";\n\tpublic static final String FAILED_SHARDS = \"failedShards=\";\n\tpublic static final String IS_TIMEOUT = \"isTimedOut=\";\n\tpublic static final String TOTAL_HIT = \"totalHits=\";\n\n\tprotected String buildSearchRequestLog(ActionContext actionContext, SearchRequest searchRequest) {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tsb.append(QueryConsts.DLFLAG_PREFIX + \"query_tcp_search_request||\");\n\n\t\tsb.append(APP_ID).append(actionContext.getAppid())\n\t\t\t.append(\"||\");\n\n\t\tsb.append(REQUEST_ID).append(actionContext.getRequestId())\n\t\t\t.append(\"||\");\n\n\t\tif (searchRequest.indices() != null\n\t\t\t\t&& searchRequest.indices().length > 0) {\n\t\t\tString[] indices = searchRequest.indices();\n\t\t\tsb.append(INDICES);\n\t\t\tfor (String index : indices) {\n\t\t\t\tsb.append(index).append(\",\");\n\t\t\t}\n\t\t} else {\n\t\t\tsb.append(INDICES);\n\t\t}\n\t\tdealType(searchRequest, sb);\n\n\t\tsb.append(\"||routing=\");\n\t\tsb.append(searchRequest.routing());\n\n\t\tif (searchRequest.source() != null\n\t\t\t\t&& searchRequest.source().length() > 0) {\n\t\t\ttry {\n\t\t\t\tsb.append(SOURCE)\n\t\t\t\t\t\t.append(XContentHelper.convertToJson(\n\t\t\t\t\t\t\t\tsearchRequest.source(), true).replace(\"\\n\", \"\"));\n\t\t\t} catch (IOException e) {\n\t\t\t\tsb.append(\"||source=_failed_to_convert_\");\n\t\t\t}\n\t\t} else {\n\t\t\tsb.append(SOURCE);\n\t\t}\n\t\tif (searchRequest.extraSource() != null\n\t\t\t\t&& searchRequest.extraSource().length() > 0) {\n\t\t\ttry {\n\t\t\t\tsb.append(EXTRA_SOURCE).append(\n\t\t\t\t\t\tXContentHelper.convertToJson(\n\t\t\t\t\t\t\t\tsearchRequest.extraSource(), true).replaceAll(\"\\n\", \"\"));\n\t\t\t} catch (IOException e) {\n\t\t\t\tsb.append(\"||extra_source=_failed_to_convert_\");\n\t\t\t}\n\t\t} else {\n\t\t\tsb.append(EXTRA_SOURCE);\n\t\t}\n\n\t\treturn sb.toString();\n\t}\n\n\tprivate void dealType(SearchRequest searchRequest, StringBuilder sb) {\n\t\tif (searchRequest.types() != null && searchRequest.types().length > 0) {\n\t\t\tString[] types = searchRequest.types();\n\t\t\tsb.append(TYPES);\n\t\t\tfor (String type : types) {\n\t\t\t\tsb.append(type).append(\",\");\n\t\t\t}\n\t\t} else {\n\t\t\tsb.append(TYPES);\n\t\t}\n\t}\n\n\tprotected String buildSearchResponseLog(ActionContext actionContext, SearchResponse searchResponse) {\n\t\tmetricsService.addSearchResponseMetrics(actionContext.getAppid(), searchResponse.getTookInMillis(), searchResponse.getHits().getTotalHits(), searchResponse.getTotalShards(), searchResponse.getFailedShards());\n\t\t\n\t\tStringBuilder sb = new StringBuilder();\n\t\tsb.append(QueryConsts.DLFLAG_PREFIX + \"query_tcp_search_response||\");\n\n\t\tsb.append(APP_ID).append(actionContext.getAppid())\n\t\t\t\t.append(\"||\");\n\t\t\n\t\tsb.append(REQUEST_ID).append(actionContext.getRequestId())\n\t\t\t\t.append(\"||\");\n\n\t\tsb.append(TOOK_MILLIS).append(searchResponse.getTookInMillis())\n\t\t\t\t.append(\"||\");\n\n\t\tsb.append(SCROLL_ID).append(searchResponse.getScrollId())\n\t\t\t\t.append(\"||\");\n\n\t\tsb.append(TOTAL_SHARDS).append(searchResponse.getTotalShards())\n\t\t\t\t.append(\"||\");\n\n\t\tsb.append(FAILED_SHARDS)\n\t\t.append(searchResponse.getTotalShards()-searchResponse.getSuccessfulShards()).append(\"||\");\n\n\t\tsb.append(IS_TIMEOUT)\n\t\t\t\t.append(searchResponse.isTimedOut()).append(\"||\");\t\t\n\t\t\n\t\tsb.append(TOTAL_HIT).append(searchResponse.getHits().getTotalHits());\n\n\t\treturn sb.toString();\n\t}\n\t\n\tprotected String buildScrollSearchSlowlog(ActionContext actionContext, SearchResponse searchResponse) {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tsb.append(QueryConsts.DLFLAG_PREFIX + \"query_tcp_scroll_search_slowlog||\");\n\n\t\tsb.append(APP_ID).append(actionContext.getAppid())\n\t\t\t\t.append(\"||\");\n\t\t\n\t\tsb.append(REQUEST_ID).append(actionContext.getRequestId())\n\t\t\t\t.append(\"||\");\n\n\t\tsb.append(TOOK_MILLIS).append(searchResponse.getTookInMillis())\n\t\t\t\t.append(\"||\");\n\n\t\tsb.append(SCROLL_ID).append(searchResponse.getScrollId())\n\t\t\t\t.append(\"||\");\n\n\t\tsb.append(TOTAL_SHARDS).append(searchResponse.getTotalShards())\n\t\t\t\t.append(\"||\");\n\n\t\tsb.append(FAILED_SHARDS)\n\t\t.append(searchResponse.getTotalShards()-searchResponse.getSuccessfulShards()).append(\"||\");\n\n\t\tsb.append(IS_TIMEOUT)\n\t\t\t\t.append(searchResponse.isTimedOut()).append(\"||\");\t\t\n\t\t\n\t\tsb.append(TOTAL_HIT).append(searchResponse.getHits().getTotalHits());\n\n\t\treturn sb.toString();\n\t}\t\n\t\n    protected String buildSearchSlowlog(ActionContext actionContext, SearchRequest searchRequest, SearchResponse searchResponse) {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tsb.append(QueryConsts.DLFLAG_PREFIX + \"query_tcp_search_slowlog||\");    \n\t\t\n\t\tsb.append(APP_ID).append(actionContext.getAppid())\n\t\t\t.append(\"||\");\t\t\n\t\t\n\t\tsb.append(REQUEST_ID).append(actionContext.getRequestId());\n\n\t\tif (searchRequest.indices() != null\n\t\t\t\t&& searchRequest.indices().length > 0) {\n\t\t\tString[] indices = searchRequest.indices();\n\t\t\tsb.append(INDICES);\n\t\t\tfor (String index : indices) {\n\t\t\t\tsb.append(index).append(\",\");\n\t\t\t}\n\t\t} else {\n\t\t\tsb.append(INDICES);\n\t\t}\n\t\tdealType(searchRequest, sb);\n\n\t\tif (searchRequest.source() != null\n\t\t\t\t&& searchRequest.source().length() > 0) {\n\t\t\ttry {\n\t\t\t\tsb.append(SOURCE)\n\t\t\t\t\t\t.append(XContentHelper.convertToJson(\n\t\t\t\t\t\t\t\tsearchRequest.source(), true));\n\t\t\t} catch (IOException e) {\n\t\t\t\tsb.append(\"||source=_failed_to_convert_\");\n\t\t\t}\n\t\t} else {\n\t\t\tsb.append(SOURCE);\n\t\t}\n\t\tif (searchRequest.extraSource() != null\n\t\t\t\t&& searchRequest.extraSource().length() > 0) {\n\t\t\ttry {\n\t\t\t\tsb.append(EXTRA_SOURCE).append(\n\t\t\t\t\t\tXContentHelper.convertToJson(\n\t\t\t\t\t\t\t\tsearchRequest.extraSource(), true));\n\t\t\t} catch (IOException e) {\n\t\t\t\tsb.append(\"||extra_source=_failed_to_convert_\");\n\t\t\t}\n\t\t} else {\n\t\t\tsb.append(EXTRA_SOURCE);\n\t\t}\n\t\t\n\t\tsb.append(\"||\");\n\t\t\n\t\tsb.append(TOOK_MILLIS).append(searchResponse.getTookInMillis())\n\t\t\t\t.append(\"||\");\n\t\t\n\t\tsb.append(SCROLL_ID).append(searchResponse.getScrollId())\n\t\t\t\t.append(\"||\");\n\t\t\n\t\tsb.append(TOTAL_SHARDS).append(searchResponse.getTotalShards())\n\t\t\t\t.append(\"||\");\n\t\t\n\t\tsb.append(FAILED_SHARDS)\n\t\t.append(searchResponse.getTotalShards()-searchResponse.getSuccessfulShards()).append(\"||\");\n\t\t\n\t\tsb.append(IS_TIMEOUT)\n\t\t\t\t.append(searchResponse.isTimedOut()).append(\"||\");\t\t\n\t\t\n\t\tsb.append(TOTAL_HIT).append(searchResponse.getHits().getTotalHits());\n\t\t\n\t\treturn sb.toString();\n    }\t\n\t\n\tprotected ActionListener<SearchResponse> newListener(ActionContext actionContext) {\n\t\treturn new ActionListenerImpl<SearchResponse>(actionContext) {\n\t\t\t@Override\n\t\t\tpublic void onResponse(SearchResponse searchResponse) {\n\t\t\t\tstatLogger.info(QueryConsts.DLFLAG_PREFIX + \"query_tcp_search_query||appid={}||requestId={}||cost={}\", actionContext.getAppid(), actionContext.getRequestId(), (System.currentTimeMillis()-actionContext.getRequestTime()));\n\t\t\t\t\n\t\t\t\tif (searchResponse.getFailedShards() > 0) {\n\t\t\t\t\tStringBuilder stringBuilder = new StringBuilder(\"search response has some failed,appid=\"+actionContext.getAppid()+\",requestId=\"+actionContext.getRequestId()+\",number=\"+searchResponse.getFailedShards()+\" reasons:\\n\");\n\t\t\t\t\tint count = 0;\n\t\t\t\t\tfor (ShardSearchFailure shardSearchFailure : searchResponse.getShardFailures()) {\n\t\t\t\t\t\tstringBuilder.append(Convert.getPrefix(shardSearchFailure.reason()));\n\t\t\t\t\t\tstringBuilder.append(\"\\n\");\n\t\t\t\t\t\tcount++;\n\t\t\t\t\t\tif (count > 2) {\n\t\t\t\t\t\t\tstringBuilder.append(\"...\\n\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tlogger.warn(stringBuilder.toString());\n\t\t\t\t}\n\n\t\t\t\tstatLogger.info(buildSearchResponseLog(actionContext, searchResponse));\n\t\t\t\t\n\t\t\t\tif (searchResponse.getTookInMillis() > queryConfig.getSearchSlowlogThresholdMills()) {\n\t\t\t\t\tif (actionContext.getRequest() instanceof SearchRequest) {\n\t\t\t\t\t\tSearchRequest searchRequest = (SearchRequest) actionContext.getRequest();\n\t\t\t\t\t\tstatLogger.warn(buildSearchSlowlog(actionContext, searchRequest, searchResponse));\t\n\t\t\t\t\t} else if (actionContext.getRequest() instanceof SearchScrollRequest) {\n\t\t\t\t\t\tstatLogger.warn(buildScrollSearchSlowlog(actionContext, searchResponse));\t\t\t\t\t\t\n\t\t\t\t\t}\n\n\t\t\t\t\tmetricsService.addSlowlogCost(actionContext.getAppid(), actionContext.getCostTime());\n\t\t\t\t}\n\n\t\t\t\tsuper.onResponse(searchResponse);\n\t\t\t}\n\t\t};\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/search/ClearScrollHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp.search;\n\nimport com.didi.arius.gateway.core.es.tcp.ActionHandler;\nimport com.didi.arius.gateway.core.es.tcp.ActionListenerImpl;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.search.ClearScrollAction;\nimport org.elasticsearch.action.search.ClearScrollRequest;\nimport org.elasticsearch.action.search.ClearScrollResponse;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\n\n/**\n* @author weizijun\n* @date：2016年9月21日\n* \n*/\n@Component(\"clearScrollHandler\")\npublic class ClearScrollHandler extends ActionHandler {\n\t@Override\n\tpublic String name() {\n\t\treturn ClearScrollAction.NAME;\n\t}\n\t\n    @PostConstruct\n    public void init() {\n        controller.registerHandler(ClearScrollAction.NAME, this);\n    }\t\n    \n\t@Override\n\tpublic void handleInterRequest(ActionContext actionContext, int retryTimes) {\n\t\tClearScrollRequest clearScrollRequest = (ClearScrollRequest) actionContext.getRequest();\n\t\t\n\t\tActionListener<ClearScrollResponse> listener = new ActionListenerImpl<>(actionContext);\n\t\tesTcpClientService.getClient(actionContext.getCluster()).clearScroll(clearScrollRequest, new RetryListener<>(this, actionContext, listener, retryTimes));\n\t}\n\n\t@Override\n\tprotected Class<? extends TransportRequest> getRequestClass() {\n\t\treturn ClearScrollRequest.class;\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/search/MultiSearchHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp.search;\n\nimport com.didi.arius.gateway.core.es.tcp.ActionListenerImpl;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.exception.QueryDslLengthException;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.search.*;\nimport org.elasticsearch.action.search.MultiSearchResponse.Item;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\n\n/**\n* @author weizijun\n* @date：2016年9月21日\n* \n*/\n@Component(\"multiSearchHandler\")\npublic class MultiSearchHandler extends BaseSearchHandler {\n\n\t@Override\n\tpublic String name() {\n\t\treturn MultiSearchAction.NAME;\n\t}\n\t\n    @PostConstruct\n    public void init() {\n        controller.registerHandler(MultiSearchAction.NAME, this);\n    }\t\t\n\t\n\t@Override\n\tpublic void handleInterRequest(ActionContext actionContext, int retryTimes) {\n\t\tMultiSearchRequest multiSearchRequest = (MultiSearchRequest) actionContext.getRequest();\n\t\tfinal List<SearchRequest> requests = multiSearchRequest.requests();\n\t\tfinal List<FetchFields> fetchFieldsList = new ArrayList<>(multiSearchRequest.requests().size());\n\t\tList<String> indices = new ArrayList<>();\n\t\tfor (SearchRequest searchRequest : requests) {\n\t\t\tString log = buildSearchRequestLog(actionContext, searchRequest);\n\t\t\tstatLogger.info(log);\n\t\t\t\n\t\t\tif (searchRequest.source() != null && searchRequest.source().length() > queryConfig.getDslMaxLength()) {\n\t\t\t\tthrow new QueryDslLengthException(String.format(\"query length(%d) > %d exception\", searchRequest.source().length(), queryConfig.getDslMaxLength()));\n\t\t\t}\n\t\t\t\n\t\t\tList<String> inIndices = Arrays.asList(searchRequest.indices());\n\t\t\tindices.addAll(inIndices);\n\n\t\t\t// 日期索引加上*号后缀，支持异常索引修复方案\n\t\t\tConvert.convertIndices(searchRequest);\n\t\t\t\n\t\t\t// pre process\t\t\t\n\t\t\tdslAuditService.auditDSL(actionContext, searchRequest.source(), searchRequest.indices());\n\t\t\t\n\t\t\tdslAggsAnalyzerService.analyzeAggs(actionContext, searchRequest.source(), searchRequest.indices());\n\t\t\tdslAggsAnalyzerService.analyzeAggs(actionContext, searchRequest.extraSource(), searchRequest.indices());\n\t\t\t\n\t\t\tFetchFields fetchFields = formFetchFields(searchRequest);\n\t\t\tfetchFieldsList.add(fetchFields);\n\t\t}\n\t\tappService.checkIndices(actionContext, indices);\n\n\t\tActionListener<MultiSearchResponse> listener = getMultiSearchResponseActionListener(actionContext, requests);\n\n\t\tmultiSearchRequest.putHeader(\"requestId\", actionContext.getRequestId());\n        multiSearchRequest.putHeader(\"Authorization\", actionContext.getRequest().getHeader(\"Authorization\"));\n        \n\t\tesTcpClientService.getClient(actionContext.getCluster()).multiSearch(multiSearchRequest, new RetryListener<>(this, actionContext, listener, retryTimes));\n\t}\n\n\tprivate ActionListener<MultiSearchResponse> getMultiSearchResponseActionListener(ActionContext actionContext, List<SearchRequest> requests) {\n\t\treturn new ActionListenerImpl<MultiSearchResponse>(actionContext){\n        \t@Override\n        \tpublic void onResponse(MultiSearchResponse multiSearchResponse) {\n        \t\tstatLogger.info(QueryConsts.DLFLAG_PREFIX + \"query_tcp_search_query||appid={}||requestId={}||cost={}\", actionContext.getAppid(), actionContext.getRequestId(), (System.currentTimeMillis()-actionContext.getRequestTime()));\n\n\t\t\t\tItem[] items = multiSearchResponse.getResponses();\n\t\t\t\tfor (int i = 0; i < items.length; i++) {\n\t\t\t\t\tSearchResponse searchResponse = items[i].getResponse();\n\n\t\t\t\t\tif (searchResponse == null) {\n\t\t\t\t\t\tstatLogger.info(QueryConsts.DLFLAG_PREFIX + \"query_tcp_search_response||appid={}||requestId={}\", actionContext.getAppid(), actionContext.getRequestId());\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tString log = buildSearchResponseLog(actionContext, searchResponse);\n\t\t\t\t\tstatLogger.info(log);\n\n\t\t\t\t\tif (searchResponse.getTookInMillis() > queryConfig.getSearchSlowlogThresholdMills()) {\n\t\t\t\t\t\tSearchRequest searchRequest = requests.get(i);\n\t\t\t\t\t\tlog = buildSearchSlowlog(actionContext, searchRequest, searchResponse);\n\t\t\t\t\t\tstatLogger.warn(log);\n\t\t\t\t\t}\n\n\t    \t\t\tif (searchResponse.getFailedShards() > 0) {\n\t\t\t\t\t\tStringBuilder stringBuilder = new StringBuilder(\"search response has some failed,appid=\"+actionContext.getAppid()+\",requestId=\"+actionContext.getRequestId()+\",number=\"+searchResponse.getFailedShards()+\" reasons:\\n\");\n\t\t\t\t\t\tint count = 0;\n\t\t\t\t\t\tfor (ShardSearchFailure shardSearchFailure : searchResponse.getShardFailures()) {\n\t\t\t\t\t\t\tstringBuilder.append(Convert.getPrefix(shardSearchFailure.reason()));\n\t\t\t\t\t\t\tstringBuilder.append(\"\\n\");\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t\tif (count > 2) {\n\t\t\t\t\t\t\t\tstringBuilder.append(\"...\\n\");\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlog = stringBuilder.toString();\n\t\t\t\t\t\tlogger.warn(log);\n\t    \t\t\t}\n\n\t\t\t\t}\n\t\t\t\tsuper.onResponse(multiSearchResponse);\n        \t}\n        };\n\t}\n\n\t@Override\n\tprotected Class<? extends TransportRequest> getRequestClass() {\n\t\treturn MultiSearchRequest.class;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/search/SearchHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp.search;\n\nimport com.didi.arius.gateway.common.exception.QueryDslLengthException;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.search.SearchAction;\nimport org.elasticsearch.action.search.SearchRequest;\nimport org.elasticsearch.action.search.SearchResponse;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n* @author weizijun\n* @date：2016年9月19日\n* \n*/\n@Component(\"searchHandler\")\npublic class SearchHandler extends BaseSearchHandler {\n\n\t@Override\n\tpublic String name() {\n\t\treturn SearchAction.NAME;\n\t}\n\t\n    @PostConstruct\n    public void init() {\n        controller.registerHandler(SearchAction.NAME, this);\n    }\t\n\n\t@Override\n\tpublic void handleInterRequest(ActionContext actionContext, int retryTimes) {\n\t\tSearchRequest searchRequest = (SearchRequest) actionContext.getRequest();\n\t\t\n\t\tif (searchRequest.source() != null && searchRequest.source().length() > queryConfig.getDslMaxLength()) {\n\t\t\tthrow new QueryDslLengthException(String.format(\"query length(%d) > %d exception\", searchRequest.source().length(), queryConfig.getDslMaxLength()));\n\t\t}\n\n\t\tString log = buildSearchRequestLog(actionContext, searchRequest);\n\t\tstatLogger.info(log);\n\n\t\tList<String> indices = Arrays.asList(searchRequest.indices());\n\t\tappService.checkIndices(actionContext, indices);\n\t\t\n        ActionListener<SearchResponse> listener = newListener(actionContext);\n        \n        FetchFields fetchFields = formFetchFields(searchRequest);\n        actionContext.setFetchFields(fetchFields);\n        \n        searchRequest.putHeader(\"requestId\", actionContext.getRequestId());\n        searchRequest.putHeader(\"Authorization\", actionContext.getRequest().getHeader(\"Authorization\"));\n        \n\t\t// 日期索引加上*号后缀，支持异常索引修复方案\n\t\tConvert.convertIndices(searchRequest);\n\t\t\n\t\t// pre process\t\t\n\t\tdslAuditService.auditDSL(actionContext, searchRequest.source(), searchRequest.indices());\n\t\t\n\t\tdslAggsAnalyzerService.analyzeAggs(actionContext, searchRequest.source(), searchRequest.indices());\n\t\tdslAggsAnalyzerService.analyzeAggs(actionContext, searchRequest.extraSource(), searchRequest.indices());\n        \n\t\tesTcpClientService.getClient(actionContext.getCluster()).search(searchRequest, new RetryListener<>(this, actionContext, listener, retryTimes));\n\t}\n\n\t@Override\n\tprotected Class<? extends TransportRequest> getRequestClass() {\n\t\treturn SearchRequest.class;\n\t}\n\t\n\t\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/es/tcp/search/SearchScrollHandler.java",
    "content": "package com.didi.arius.gateway.core.es.tcp.search;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.metadata.FetchFields;\nimport org.elasticsearch.action.ActionListener;\nimport org.elasticsearch.action.search.SearchResponse;\nimport org.elasticsearch.action.search.SearchScrollAction;\nimport org.elasticsearch.action.search.SearchScrollRequest;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\n\n/**\n* @author weizijun\n* @date：2016年9月21日\n* \n*/\n@Component(\"searchScrollHandler\")\npublic class SearchScrollHandler extends BaseSearchHandler {\n\n\t@Override\n\tpublic String name() {\n\t\treturn SearchScrollAction.NAME;\n\t}\n\t\n    @PostConstruct\n    public void init() {\n        controller.registerHandler(SearchScrollAction.NAME, this);\n    }\t\n\t\n\t@Override\n\tpublic void handleInterRequest(ActionContext actionContext, int retryTimes) {\n\t\tSearchScrollRequest searchScrollRequest = (SearchScrollRequest) actionContext.getRequest();\n\t\t\n\t\tStringBuilder sb = new StringBuilder();\n\t\tsb.append(QueryConsts.DLFLAG_PREFIX + \"query_tcp_search_scroll_request||appid=\");\n\t\tsb.append(actionContext.getAppid());\n\t\tsb.append(\"||requestId=\");\n\t\tsb.append(actionContext.getRequestId()).append(\"||\");\n\t\tsb.append(\"scorllId=\").append(searchScrollRequest.scrollId());\n\t\tString log = sb.toString();\n\n\t\tstatLogger.info(log);\n\t\t\n\t\tActionListener<SearchResponse> listener = newListener(actionContext);\n\t\t\n        FetchFields fetchFields = new FetchFields();\n        fetchFields.setHasMessageField(false);\n        actionContext.setFetchFields(fetchFields);\n\t\t\n\t\tsearchScrollRequest.putHeader(\"requestId\", actionContext.getRequestId());\n\t\tsearchScrollRequest.putHeader(\"Authorization\", actionContext.getRequest().getHeader(\"Authorization\"));\n\t\t\n\t\tesTcpClientService.getClient(actionContext.getCluster()).searchScroll(searchScrollRequest, new RetryListener<>(this, actionContext, listener, retryTimes));\n\t}\n\n\t@Override\n\tprotected Class<? extends TransportRequest> getRequestClass() {\n\t\treturn SearchScrollRequest.class;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/ESRestClientService.java",
    "content": "package com.didi.arius.gateway.core.service;\n\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\n\nimport java.util.Map;\n\n/**\n * @author fitz\n * @date 2021/5/26 5:25 下午\n */\npublic interface ESRestClientService {\n    /**\n     * 根据cluster名字获取esClient\n     * @See getClientStrict\n     * @param clusterName\n     * @return\n     */\n    ESClient getClient(String clusterName, String actionName);\n\n    /**\n     *\n     * 根据cluster名字获取esClient\n     * @param clusterName\n     * @return\n     */\n    ESClient getClientStrict(String clusterName, String actionName);\n\n    /**\n     * 获取admin权限的esClient\n     * @return\n     */\n    ESClient getAdminClient(String actionName);\n\n    /**\n     * 更新Map中的esClient客户端，并关掉废弃的esClient\n     * @param newDataCenterMap\n     */\n    void resetClients(Map<String, ESCluster> newDataCenterMap);\n\n    /**\n     * 获取esClusterMap\n     * @return\n     */\n    Map<String, ESCluster> getESClusterMap();\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/ESTcpClientService.java",
    "content": "package com.didi.arius.gateway.core.service;\n\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport org.elasticsearch.client.Client;\n\nimport java.util.Map;\n\n/**\n * @author fitz\n * @date 2021/5/26 5:26 下午\n */\npublic interface ESTcpClientService {\n\n    /**\n     * 根据cluster名字获取esClient\n     * @param clusterName\n     * @return\n     */\n    Client getClient(String clusterName);\n\n    /**\n     * 获取admin权限的esClient\n     * @return\n     */\n    Client getAdminClient();\n\n    /**\n     * 更新 dataCenterMap\n     * @param newDataCenterMap\n     */\n    void resetClients(Map<String, ESCluster> newDataCenterMap);\n\n    /**\n     * 获取 dataCenterMap\n     * @return\n     */\n    Map<String, ESCluster> getDataCenterMap();\n\n    /**\n     * set dataCenterMap\n     * @param dataCenterMap\n     */\n    void setDataCenterMap(Map<String, ESCluster> dataCenterMap);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/MetricsService.java",
    "content": "package com.didi.arius.gateway.core.service;\n\n/**\n * @author fitz\n * @date 2021/5/31 12:04 下午\n */\npublic interface MetricsService {\n    /**\n     * 统计appid query cost\n     * @param appid\n     * @param cost\n     */\n    void addQueryCost(int appid, long cost);\n\n    /**\n     * 统计slowlog cost\n     * @param appid\n     * @param cost\n     */\n    void addSlowlogCost(int appid, long cost);\n\n    /**\n     * 统计查询返回的指标计数\n     * @param appid\n     * @param tookInMillis\n     * @param totalHits\n     * @param totalShards\n     * @param failedShards\n     */\n    void addSearchResponseMetrics(int appid, long tookInMillis, long totalHits, int totalShards, int failedShards);\n\n    /**\n     *\n     * 统计requestLength\n     * @param appid\n     * @param length\n     */\n    void addReqeustLength(int appid, long length);\n\n    /**\n     *\n     * 统计responseLength\n     * @param appid\n     * @param length\n     */\n    void addResponseLength(int appid, long length);\n\n    /**\n     *\n     * 统计QueryMetrics requestLength, responseLength\n     * @param appid\n     * @param cost\n     * @param requestLength\n     * @param responseLength\n     */\n    void addQueryMetrics(int appid, long cost, long requestLength, long responseLength);\n\n    /**\n     *\n     * IndexMetrics requestLength, responseLength\n     * @param index\n     * @param operation\n     * @param cost\n     * @param requestLength\n     * @param responseLength\n     */\n    void addIndexMetrics(String index, String operation, long cost, long requestLength, long responseLength);\n\n    /**\n     * 统计聚合查询\n     * @param appid\n     */\n    void incrQueryAggs(int appid);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/RateLimitService.java",
    "content": "package com.didi.arius.gateway.core.service;\n\nimport com.didi.arius.gateway.common.metadata.FlowThreshold;\nimport com.didi.arius.gateway.common.flowcontrol.FlowController;\nimport com.didi.arius.gateway.common.flowcontrol.FlowLimit;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentMap;\n\npublic interface RateLimitService {\n\n    /**\n     * totalByteIn 字节添加计数\n     * @param bytes\n     */\n    void addByteIn(long bytes);\n\n    /**\n     * totalByteIn 字节删除计数\n     * @param bytes\n     */\n    void removeByteIn(long bytes);\n\n    /**\n     * 判断是否超过限流阈值\n     * @param appid\n     * @param searchId\n     * @return\n     */\n    boolean isTrafficDataOverflow(int appid, String searchId);\n\n    /**\n     *\n     * 流控计算\n     * @param appid\n     * @param searchId\n     * @param in\n     * @param out\n     */\n    void addUp(int appid, String searchId, int in, int out);\n\n    /**\n     * 重置流控值\n     * @param appid\n     * @param flowThreshold\n     */\n    void resetAppAreaFlow(int appid, FlowThreshold flowThreshold);\n\n    /**\n     * 获取 flowControllerMap\n     * @return\n     */\n    Map<Integer, FlowController> getFlowControllerMap();\n\n    /**\n     * 获取 flowLimitMap\n     * @return\n     */\n    ConcurrentMap<String, FlowLimit> getFlowLimitMap();\n\n    /**\n     * 获取 flowSchedulePeriod\n     * @return\n     */\n    int getFlowSchedulePeriod();\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/RequestStatsService.java",
    "content": "package com.didi.arius.gateway.core.service;\n\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metrics.ActionMetric;\nimport com.didi.arius.gateway.common.metrics.AppMetric;\nimport org.elasticsearch.rest.RestStatus;\n\nimport java.util.List;\nimport java.util.concurrent.ConcurrentMap;\n\npublic interface RequestStatsService {\n\n    /**\n     * 处理统计 HttpRequest和TcpRequest\n     */\n    void dealRequest();\n\n    /**\n     * 缓存 QueryContext\n     * @param key\n     * @param value\n     */\n    void putQueryContext(String key, QueryContext value);\n\n    /**\n     * 从缓存中获取 QueryContext\n     * @param key\n     * @return\n     */\n    QueryContext getQueryContext(String key);\n\n    /**\n     * 获取QueryContext缓存中的所有key\n     * @return\n     */\n    List<String> getQueryKeys();\n\n    /**\n     * 删除缓存中为key的QueryContext\n     * @param key\n     */\n    void removeQueryContext(String key);\n\n    /**\n     * 缓存ActionContext\n     * @param key\n     * @param value\n     */\n    void putActionContext(String key, ActionContext value);\n\n    /**\n     * 获取缓存中key的ActionContext\n     * @param key\n     * @return\n     */\n    ActionContext getActionContext(String key);\n\n    /**\n     * 删除缓存中key的ActionContext\n     * @param key\n     */\n    void removeActionContext(String key);\n\n    /**\n     * 获取ActionContext缓存中的所有key\n     * @return\n     */\n    List<String> getActionKeys();\n\n    /**\n     * 统计app, action的访问耗时\n     * @param actionName\n     * @param appid\n     * @param searchId\n     * @param cost\n     * @param restStatus\n     */\n    void statsAdd(String actionName, int appid, String searchId, long cost, RestStatus restStatus);\n\n    /**\n     * 获取actionMetricMap\n     * @return\n     */\n    ConcurrentMap<String, ActionMetric> getActionMetricMap();\n\n    /**\n     * 获取appMetricMap\n     * @return\n     */\n    ConcurrentMap<Integer, AppMetric> getAppMetricMap();\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/AppService.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.BaseContext;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface AppService {\n\n    /**\n     * 根据appid获取app详情\n     * @param appid\n     * @return\n     */\n    AppDetail getAppDetail(int appid);\n\n    /**\n     * 获取所有的app详情map\n     * @return\n     */\n    Map<Integer, AppDetail> getAppDetails();\n\n    /**\n     * 通过ip获取app详情\n     * @param ip\n     * @return\n     */\n    AppDetail getAppDetailFromIp(String ip);\n\n    /**\n     * 更新app信息\n     */\n    void resetAppInfo();\n\n    /**\n     * 验证请求token信息\n     * @param baseContext\n     */\n    void checkToken(BaseContext baseContext);\n\n    /**\n     * 检查索引是否有app授权的写索引权限\n     * @param baseContext\n     * @param indices\n     */\n    void checkWriteIndices(BaseContext baseContext, List<String> indices);\n\n    /**\n     * 检查索引是否有app授权的索引权限\n     * @param baseContext\n     * @param indices\n     */\n    void checkIndices(BaseContext baseContext, List<String> indices);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/DslTemplateService.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\nimport com.didi.arius.gateway.common.metadata.DSLTemplate;\n\nimport java.util.List;\n\npublic interface DslTemplateService {\n\n    /**\n     * 缓存dslTemplate\n     * @param key\n     * @param dslTemplate\n     */\n    void putDSLTemplate(String key, DSLTemplate dslTemplate);\n\n    /**\n     * 删除key的dslTemplate缓存\n     * @param key\n     */\n    void removeDSLTemplate(String key);\n\n    /**\n     * 获取key的dslTemplate缓存\n     * @param key\n     * @return\n     */\n    DSLTemplate getDSLTemplate(String key);\n\n    /**\n     * 获取dslTemplate缓存的所有key\n     * @return\n     */\n    List<String> getDslTemplateKeys();\n\n    /**\n     * 缓存新的dslTemplate\n     * @param key\n     * @param dslTemplate\n     */\n    void putNewDSLTemplate(String key, DSLTemplate dslTemplate);\n\n    /**\n     * 获取key的新的dslTemplate缓存\n     * @param key\n     * @return\n     */\n    DSLTemplate getNewDSLTemplate(String key);\n\n    /**\n     * 获取新的dslTemplate缓存的所有key\n     * @return\n     */\n    List<String> getNewDslTemplateKeys();\n\n    /**\n     * 更新dsl模板，更新dsl模板限流值\n     */\n    void resetDslInfo();\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/DynamicConfigService.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\npublic interface DynamicConfigService {\n\n    /**\n     * 获取detailLogFlag\n     * @return\n     */\n    boolean getDetailLogFlag();\n\n    /**\n     * 是否可以跳过检查\n     *\n     * @param appid\n     * @return\n     */\n    boolean isWhiteAppid(int appid);\n\n    /**\n     * 从admin拉取gateway动态配置信息，并更新\n     */\n    void resetDynamicConfigInfo();\n\n    String getForbiddenSettings();\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/ESClusterService.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.MetaVersion;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\n\nimport java.util.Map;\n\npublic interface ESClusterService {\n    /**\n     * 获取 esClusterMap\n     * @return\n     */\n    Map<String, ESCluster> listESCluster();\n\n    /**\n     * 根据cluster 获取 MetaVersion\n     * @param cluster\n     * @return\n     */\n    MetaVersion getMetaVersionByCluster(String cluster);\n\n    /**\n     * 更新集群列表\n     */\n    void resetESClusaterInfo();\n\n    /**\n     * 根据请求上下文获取esClient\n     * @param queryContext\n     * @return\n     */\n    ESClient getClient(QueryContext queryContext, String actionName);\n\n    /**\n     * 根据请求上下文获取esClient, 会根据索引模版判定\n     * @param queryContext\n     * @param indexTemplate\n     * @return\n     */\n    ESClient getClient(QueryContext queryContext, IndexTemplate indexTemplate, String actionName);\n\n    /**\n     * 根据cluster获取esClient, 并且加入queryContext\n     * @param queryContext\n     * @param clusterName\n     * @return\n     */\n    ESClient getClientFromCluster(QueryContext queryContext, String clusterName, String actionName);\n\n    /**\n     * 获取具有写入权限的esClient\n     * @param indexTemplate\n     * @return\n     */\n    ESClient getWriteClient(IndexTemplate indexTemplate, String actionName);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/GateWayHeartBeatService.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\n/**\n * 心跳类，定期给admin发送心跳\n */\npublic interface GateWayHeartBeatService{\n\t/**\n\t * 给admin发送心跳\n\t * 从admin获取存活的节点数量，节点数量跟当前保存的节点数量不一致时，更新dsl限流值\n\t */\n\tvoid resetHeartBeatInfo();\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/IndexTemplateService.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\nimport com.didi.arius.gateway.common.enums.TemplateBlockTypeEnum;\nimport com.didi.arius.gateway.common.exception.IndexNotFoundException;\nimport com.didi.arius.gateway.common.exception.TooManyIndexException;\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.TemplateInfo;\n\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface IndexTemplateService {\n    /**\n     * 获取索引模版表达式map\n     */\n    Map<String, Map<String, TemplateInfo>> getTemplateExpressionMap();\n\n    /**\n     * 获取索引模版别名map\n     */\n    Map<String, Map<String, TemplateInfo>> getTemplateAliasMap();\n\n    /**\n     * 根据名字获取索引模版\n     */\n    IndexTemplate getIndexTemplate(String template);\n\n    /**\n     * 根据index名字搜索索引模版\n     */\n    IndexTemplate getIndexTemplateByTire(String index) throws TooManyIndexException ;\n\n    /**\n     * 获取所有索引模版map\n     */\n    Map<String, IndexTemplate> getIndexTemplateMap();\n\n    /**\n     * 更新各集群模板、大基数mapping等信息\n     * 更新逻辑索引模板列表\n     * 更新索引别名\n     */\n    void resetIndexTemplateInfo();\n\n    /**\n     * 获取索引别名\n     */\n    String getIndexAlias(String index);\n\n    /**\n     * 判断索引是否符合索引表达式\n     * @param index\n     * @param indexExps\n     * @return\n     */\n    boolean checkIndex(String index, List<String> indexExps);\n\n    /**\n     *\n     * 根据cluster, index获取索引的版本号\n     * @param indexName\n     * @param cluster\n     * @return\n     */\n    int getIndexVersion(String indexName, String cluster);\n\n    /**\n     * 获取索引模版\n     * @param indices\n     * @param queryContext\n     * @return\n     * @throws IndexNotFoundException\n     * @throws TooManyIndexException\n     */\n    IndexTemplate getTemplateByIndexTire(List<String> indices, QueryContext queryContext) throws IndexNotFoundException, TooManyIndexException;\n\n    /**\n     *  增加模板别名\n     * @param appid\n     * @param templateId\n     * @param templateName\n     * @param aliasName\n     * @return\n     */\n    public boolean addTemplateAlias(int appid, int templateId, String templateName, String aliasName);\n\n    /**\n     * 删除模板别名\n     * @param appid\n     * @param templateId\n     * @param templateName\n     * @param aliasName\n     * @return\n     */\n    public boolean delTemplateAlias(int appid, int templateId, String templateName, String aliasName);\n\n    /**\n     * 校验模板存在\n     * @param indices\n     * @throws Exception\n     */\n    public void checkTemplateExist(List<String> indices);\n\n    /**\n     * 检查模板是否block\n     * @param indices 索引\n     * @param appDetail app\n     * @param blockTypeEnum 类型\n     */\n    public void checkTemplateBlock(List<String> indices, AppDetail appDetail, TemplateBlockTypeEnum blockTypeEnum);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/impl/AppServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.arius.impl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.exception.IndexNotPermittedException;\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.didi.arius.gateway.common.exception.UnauthorizedException;\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.AuthRequest;\nimport com.didi.arius.gateway.common.metadata.BaseContext;\nimport com.didi.arius.gateway.common.metadata.FlowThreshold;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.common.utils.Regex;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.RateLimitService;\nimport com.didi.arius.gateway.core.service.arius.AppService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.AppDetailResponse;\nimport com.didi.arius.gateway.remote.response.AppListResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.NoArgsConstructor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n@Service\n@NoArgsConstructor\npublic class AppServiceImpl implements AppService {\n\n    protected static final Logger statLogger = LoggerFactory.getLogger(QueryConsts.STAT_LOGGER);\n    private static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n    private static final ILog logger = LogFactory.getLog(AppServiceImpl.class);\n\n    @Autowired\n    private AriusAdminRemoteService ariusAdminRemoteService;\n\n    @Autowired\n    private IndexTemplateService indexTemplateService;\n\n    @Autowired\n    private RateLimitService rateLimitService;\n\n    @Autowired\n    private ThreadPool threadPool;\n\n    @Value(\"${arius.gateway.adminSchedulePeriod}\")\n    private long schedulePeriod;\n\n    private Map<Integer, AppDetail> appDetails \t\t= new HashMap<>();\n    private Map<String, AppDetail> \tipToAppMap  \t= new HashMap<>();\n\n    @PostConstruct\n    public void init(){\n        threadPool.submitScheduleAtFixTask(this::resetAppInfo, 0, schedulePeriod);\n    }\n\n    @Override\n    public AppDetail getAppDetail(int appid) {\n        return appDetails.get(appid);\n    }\n\n    @Override\n    public Map<Integer, AppDetail> getAppDetails() {\n        return appDetails;\n    }\n\n    @Override\n    public AppDetail getAppDetailFromIp(String ip) {\n        for(Map.Entry<String, AppDetail> entry : ipToAppMap.entrySet()){\n            String mask = entry.getKey();\n            if (Regex.ipMaskMatch(ip, mask)) {\n                return ipToAppMap.get(mask);\n            }\n        }\n\n        return null;\n    }\n\n    @Override\n    public void resetAppInfo(){\n        try {\n            resetAppDetails();\n        } catch (Exception e) {\n            bootLogger.error(\"resetAppDetails error\", e);\n        }\n\n    }\n\n    @Override\n    public void checkToken(BaseContext baseContext) {\n        String authentication = baseContext.getAuthentication();\n        logger.debug(\"token is null, check authentication, authentication={}\", authentication);\n\n        if (authentication != null) {\n            AuthRequest authRequest = Convert.parseAuth(authentication);\n            if (authRequest == null) {\n                throw new UnauthorizedException(\"authentication format error!, authentication=\" + authentication);\n            }\n\n            int appid = authRequest.getAppid();\n            AppDetail appDetail = getAppDetail(appid);\n            if (appDetail == null) {\n                throw new UnauthorizedException(\"appid not find, appid=\" + appid);\n            }\n\n            if (!appDetail.getVerifyCode().equals(authRequest.getAppsecret())) {\n                throw new UnauthorizedException(\"auth pass error, appid=\" + authRequest.getAppid() + \", appsecret=\" + authRequest.getAppsecret());\n            }\n\n            baseContext.setAppDetail(appDetail);\n\n            return ;\n        }\n\n        logger.debug(\"token is null, check ip, ip={}\", baseContext.getRemoteAddr());\n\n        // check ip\n        AppDetail appDetail = getAppDetailFromIp(baseContext.getRemoteAddr());\n\n        if (appDetail == null) {\n            throw new UnauthorizedException(\"authentication exception, you need pass auth info(appid and appsecret)!\");\n        }\n\n        baseContext.setAppDetail(appDetail);\n    }\n\n    @Override\n\n    public void checkWriteIndices(BaseContext baseContext, List<String> indices) {\n        List<String> indexExps = baseContext.getAppDetail().getWindexExp();\n        checkIndicesPrivilege(baseContext, indices, indexExps);\n    }\n\n    @Override\n    public void checkIndices(BaseContext baseContext, List<String> indices) {\n        List<String> indexExps = baseContext.getAppDetail().getIndexExp();\n        checkIndicesPrivilege(baseContext, indices, indexExps);\n    }\n\n    /************************************************************** private method **************************************************************/\n    /**\n     * 更新appid信息\n     */\n    private void resetAppDetails() {\n        AppListResponse appListResponse = ariusAdminRemoteService.listApp();\n\n        Map<Integer, AppDetail> newAppDetails = new HashMap<>();\n        for (AppDetailResponse appDetailResponse : appListResponse.getData()) {\n            AppDetail appDetail = new AppDetail();\n            appDetail.setProjectId(appDetailResponse.getProjectId());\n            appDetail.setId(appDetailResponse.getId());\n            appDetail.setIndexExp(appDetailResponse.getIndexExp() == null ? new ArrayList<>() : appDetailResponse.getIndexExp());\n            appDetail.setWindexExp(appDetailResponse.getWindexExp() == null ? new ArrayList<>() : appDetailResponse.getWindexExp());\n            appDetail.setVerifyCode(appDetailResponse.getVerifyCode());\n            appDetail.setIp(appDetailResponse.getIp() == null ? new ArrayList<>(): appDetailResponse.getIp());\n            appDetail.setCluster(appDetailResponse.getCluster());\n            appDetail.setQueryThreshold(appDetailResponse.getQueryThreshold());\n            appDetail.setDslAnalyzeEnable(appDetailResponse.getDslAnalyzeEnable() == 1);\n\n            appDetail.setAggrAnalyzeEnable(appDetailResponse.getAggrAnalyzeEnable() == 1);\n            appDetail.setAnalyzeResponseEnable(appDetailResponse.getAnalyzeResponseEnable() == 1);\n            appDetail.setSearchType(AppDetail.RequestType.integerToType(appDetailResponse.getSearchType()));\n            appDetail.setIsRoot(appDetailResponse.getIsRoot());\n\n            FlowThreshold flowThreshold = new FlowThreshold();\n            if (appDetail.getQueryThreshold() > 0) {\n                flowThreshold.setOpsUpper(appDetail.getQueryThreshold());\n                flowThreshold.setOpsLower(appDetail.getQueryThreshold());\n            }\n\n            newAppDetails.put(appDetail.getId(), appDetail);\n\n            // set appid flow limit\n            rateLimitService.resetAppAreaFlow(appDetail.getId(), flowThreshold);\n        }\n\n        String appDetailLog = JSON.toJSONString(newAppDetails);\n        bootLogger.info(\"resetAppDetails done,old appDetails size={}, new appDetails size={}, detail={}\", appDetails.size(), newAppDetails.size(), appDetailLog);\n\n        appDetails = newAppDetails;\n\n        resetIpToAppMap();\n    }\n\n    /**\n     * 更新ip到appid的映射关系\n     */\n    private void resetIpToAppMap() {\n        Map<String, AppDetail> newIpToAppMap = new HashMap<>();\n        for (Map.Entry<Integer, AppDetail> entry : appDetails.entrySet()) {\n            AppDetail appDetail = entry.getValue();\n            for (String ip : appDetail.getIp()) {\n                newIpToAppMap.put(ip, appDetail);\n            }\n        }\n\n        ipToAppMap = newIpToAppMap;\n    }\n\n    private void checkIndicesPrivilege(BaseContext baseContext, List<String> indices, List<String> indexExps) {\n        if (indices == null || indices.isEmpty()) {\n            throw new InvalidParameterException(\"no index to query\");\n        }\n\n        StringBuilder buffer = new StringBuilder();\n        for (String index : indices) {\n            rejectAllIndexQuery(baseContext, index);\n\n            buffer.append(index);\n            buffer.append(\",\");\n            boolean matched = indexTemplateService.checkIndex(index, indexExps);\n            if (!matched) {\n                throw new IndexNotPermittedException(\"appid=\" + baseContext.getAppDetail().getId() + \" don't have permission to access \" + index);\n            }\n        }\n\n        String strIndices = buffer.toString();\n        if (strIndices.endsWith(\",\")) {\n            strIndices = strIndices.substring(0, strIndices.length() -1);\n        }\n\n        if (baseContext.isDetailLog()) {\n            statLogger.info(QueryConsts.DLFLAG_PREFIX + \"query_request_indices||appid={}||requestId={}||indices={}||types={}\",\n                    baseContext.getAppid(), baseContext.getRequestId(), strIndices, baseContext.getTypeNames());\n        }\n    }\n\n    private void rejectAllIndexQuery(BaseContext baseContext, String index) {\n        String tIndex= index.trim();\n        for (int i = 0; i < tIndex.length(); ++i) {\n            char c = tIndex.charAt(i);\n            if (c != '*') {\n                return ;\n            }\n        }\n\n        throw new IndexNotPermittedException(\"appid=\" + baseContext.getAppDetail().getId() + \" don't have permission to access \" + index);\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/impl/DslTemplateServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.arius.impl;\n\nimport java.util.List;\n\nimport javax.annotation.PostConstruct;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.DSLTemplate;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.arius.DslTemplateService;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.DSLTemplateListResponse;\nimport com.didi.arius.gateway.remote.response.DSLTemplateResponse;\n\nimport lombok.NoArgsConstructor;\nimport net.sf.ehcache.Cache;\nimport net.sf.ehcache.CacheManager;\nimport net.sf.ehcache.Element;\n\n@Service\n@NoArgsConstructor\npublic class DslTemplateServiceImpl implements DslTemplateService{\n\n    protected static final ILog bootLogger = LogFactory.getLog( QueryConsts.BOOT_LOGGER);\n\n    @Autowired\n    private AriusAdminRemoteService ariusAdminRemoteService;\n\n    @Autowired\n    private QueryConfig queryConfig;\n\n    @Autowired\n    private ThreadPool threadPool;\n\n    private Cache dslTemplateCache;\n\n    private Cache newDslTemplateCache;\n\n    private long lastModifyTime = 0;\n\n    @Value(\"${arius.gateway.adminSchedulePeriod}\")\n    private long adminSchedulePeriod;\n\n    @PostConstruct\n    public void init(){\n        CacheManager manager = CacheManager.create( DslTemplateService.class.getResourceAsStream(\"/ehcache.xml\"));\n\n        dslTemplateCache    = manager.getCache(\"dslTemplateCache\");\n        newDslTemplateCache = manager.getCache(\"newDslTemplateCache\");\n\n        threadPool.submitScheduleAtFixTask(this::resetDslInfo, 10, adminSchedulePeriod);\n    }\n\n    @Override\n    public void putDSLTemplate(String key, DSLTemplate dslTemplate) {\n        Element element = new Element(key, dslTemplate);\n        dslTemplateCache.put(element);\n    }\n\n    @Override\n    public void removeDSLTemplate(String key) {\n        dslTemplateCache.remove(key);\n    }\n\n    @Override\n    public DSLTemplate getDSLTemplate(String key) {\n        Element element = dslTemplateCache.get(key);\n        if (element != null) {\n            return (DSLTemplate) element.getObjectValue();\n        } else {\n            return null;\n        }\n    }\n\n    @Override\n    public List<String> getDslTemplateKeys() {\n        return dslTemplateCache.getKeys();\n    }\n\n    @Override\n    public void putNewDSLTemplate(String key, DSLTemplate dslTemplate) {\n        Element element = new Element(key, dslTemplate);\n        newDslTemplateCache.put(element);\n    }\n\n    @Override\n    public DSLTemplate getNewDSLTemplate(String key) {\n        Element element = newDslTemplateCache.get(key);\n        if (element != null) {\n            return (DSLTemplate) element.getObjectValue();\n        } else {\n            return null;\n        }\n    }\n\n    @Override\n    public List<String> getNewDslTemplateKeys() {\n        return newDslTemplateCache.getKeys();\n    }\n\n    @Override\n    public void resetDslInfo(){\n        resetDslTemplateInfo();\n        try {\n            resetDslRateLimit(1);\n        } catch (Exception e) {\n            bootLogger.error(\"resetDslRateLimit error\", e);\n        }\n    }\n\n    /************************************************************** private method **************************************************************/\n    /**\n     * 更新dsl模板\n     * @return\n     */\n    private synchronized boolean resetDslTemplateInfo() {\n        bootLogger.info(\"resetDSLInfo begin...\");\n\n        try {\n            DSLTemplateListResponse dslTemplateListResponse = ariusAdminRemoteService.listDslTemplates(lastModifyTime, null);\n            long runTime = System.currentTimeMillis() - QueryConsts.QUERY_DSL_MODIFY_TIME_EARLY;\n\n            bootLogger.info(\"resetDSLInfo new Dsl\");\n\n            int totalCount = 0;\n\n            do {\n                totalCount += dslTemplateListResponse.getData().getDslTemplatePoList().size();\n\n                for (DSLTemplateResponse response : dslTemplateListResponse.getData().getDslTemplatePoList()) {\n                    try {\n                        String key = response.getKey();\n\n                        boolean queryForbidden = isQueryForbidden(response);\n\n                        double queryLimit = queryConfig.getDslQPSLimit();\n                        if (response.getQueryLimit() != null) {\n                            queryLimit = response.getQueryLimit();\n                        }\n\n                        DSLTemplate dslTemplate = getDSLTemplate(key);\n                        initailTemplateValue(response, key, queryForbidden, queryLimit, dslTemplate);\n                    } catch (Exception e) {\n                        bootLogger.error(\"unexpect_exception||source={}||e={}\", response, Convert.logExceptionStack(e));\n                    }\n                }\n\n                dslTemplateListResponse = ariusAdminRemoteService.listDslTemplates(lastModifyTime, dslTemplateListResponse.getData().getScrollId());\n\n                //Zero hits mark the end of the scroll and the while loop.\n            } while(!dslTemplateListResponse.getData().getDslTemplatePoList().isEmpty());\n\n            lastModifyTime = runTime;\n\n            bootLogger.info(\"resetDSLInfo end successfully! totalCount={}\", totalCount);\n            return true;\n        } catch (Exception e) {\n            bootLogger.error(\"resetDSLInfo_error||e={}\", Convert.logExceptionStack(e));\n            return false;\n        }\n    }\n\n    private boolean isQueryForbidden(DSLTemplateResponse response) {\n        boolean queryForbidden = response.getEnable() != null && !response.getEnable();\n        if (response.getCheckMode() != null && QueryConsts.CHECK_MODE_BLACK.equals(response.getCheckMode())) {\n            queryForbidden = true;\n        }\n        return queryForbidden;\n    }\n\n    private void initailTemplateValue(DSLTemplateResponse response, String key, boolean queryForbidden, double queryLimit, DSLTemplate dslTemplate) {\n        if (dslTemplate == null) {\n            dslTemplate = new DSLTemplate(queryLimit, queryLimit, queryForbidden);\n            putDSLTemplate(key, dslTemplate);\n\n            bootLogger.info(\"new_dsl_add||key={}||dslTemplate={}\", key, dslTemplate);\n        } else {\n            dslTemplate.setQueryForbidden(queryForbidden);\n            if (queryLimit != dslTemplate.getQueryLimit()) {\n                dslTemplate.setTotalQueryLimit(queryLimit);\n                dslTemplate.setQueryLimit(queryLimit);\n                dslTemplate.updateRateLimiter(queryLimit);\n            }\n        }\n\n        if (response.getEsCostAvg() != null) {\n            dslTemplate.setEsCostAvg(response.getEsCostAvg());\n        }\n\n        if (response.getTotalHitsAvg() != null) {\n            dslTemplate.setTotalHitsAvg(response.getTotalHitsAvg());\n        }\n\n        if (response.getTotalShardsAvg() != null) {\n            dslTemplate.setTotalShardsAvg(response.getTotalShardsAvg());\n        }\n    }\n\n    /**\n     * 更新dsl模板限流值\n     * @param activeCount 存活节点数量\n     */\n    private void resetDslRateLimit(int activeCount) {\n        bootLogger.info(\"resetDslRateLimit start,activeCount={}\", activeCount);\n\n        List<String> dslKeys = getDslTemplateKeys();\n        for (String dslKey : dslKeys) {\n            DSLTemplate dslTemplate = getDSLTemplate(dslKey);\n            if (dslTemplate != null) {\n                double queryLimit = dslTemplate.getTotalQueryLimit() / activeCount;\n                queryLimit = Math.max(queryLimit, 1.0);\n\n                dslTemplate.setQueryLimit(queryLimit);\n                dslTemplate.updateRateLimiter(queryLimit);\n            }\n        }\n\n        bootLogger.info(\"resetDslRateLimit end...\");\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/impl/DynamicConfigServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.arius.impl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.MappingIndexNameWhiteAppIds;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.arius.DynamicConfigService;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.DynamicConfigListResponse;\nimport com.didi.arius.gateway.remote.response.DynamicConfigResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Service\n@NoArgsConstructor\npublic class DynamicConfigServiceImpl implements DynamicConfigService {\n\n    protected static final ILog bootLogger = LogFactory.getLog( QueryConsts.BOOT_LOGGER);\n\n    @Autowired\n    private AriusAdminRemoteService ariusAdminRemoteService;\n\n    @Autowired\n    private ThreadPool threadPool;\n\n    @Value(\"${arius.gateway.adminSchedulePeriod}\")\n    private long schedulePeriod;\n\n    private String host = Convert.getHostName();\n\n    private String forbiddenSettings;\n\n    private boolean detailLogFlag = false;\n\n    /**\n     * 可以跳过多type索引启用映射查询的appid列表\n     */\n    private MappingIndexNameWhiteAppIds whiteAppIds = new MappingIndexNameWhiteAppIds();\n\n    @PostConstruct\n    public void init(){\n        threadPool.submitScheduleAtFixTask(this::resetDynamicConfigInfo, 5, schedulePeriod);\n    }\n\n    @Override\n    public boolean getDetailLogFlag() {\n        return detailLogFlag;\n    }\n\n    /**\n     * 是否可以跳过检查\n     *\n     * @param appid\n     * @return\n     */\n    @Override\n    public boolean isWhiteAppid(int appid) {\n        return whiteAppIds.isWhiteAppid(appid);\n    }\n\n    @Override\n    public void resetDynamicConfigInfo(){\n        resetDynamicConfigInfoInner();\n    }\n\n    /************************************************************** private method **************************************************************/\n    /**\n     * 从admin拉取gateway动态配置信息，并更新\n     */\n    private void resetDynamicConfigInfoInner() {\n        try {\n            bootLogger.info(\"resetDynamicConfigInfo begin...\");\n            DynamicConfigListResponse response = ariusAdminRemoteService.listQueryConfig();\n            if (response.getCode() != 0) {\n                return ;\n            }\n\n            for (DynamicConfigResponse dynamicConfigResponse : response.getData()) {\n                if (dynamicConfigResponse.getValueName() == null) {\n                    bootLogger.warn(\"GateWayHeartBeatService dynamicConfig value null, id={}\", dynamicConfigResponse.getId());\n                    continue;\n                }\n\n                try {\n                    if (dynamicConfigResponse.getValueName().equals(QueryConsts.DETAIL_LOG_FLAG)) {\n                        bootLogger.info(\"resetDynamicConfigInfo reset {} begin...\", QueryConsts.DETAIL_LOG_FLAG);\n\n                        Map<String, Object> value = JSON.parseObject(dynamicConfigResponse.getValue());\n                        if (value.containsKey(host)) {\n                            detailLogFlag = (boolean) value.get(host);\n                        } else {\n                            detailLogFlag = false;\n                        }\n\n                        bootLogger.info(\"resetDynamicConfigInfo reset {} end, detailLogFlag={}\", QueryConsts.DETAIL_LOG_FLAG, detailLogFlag);\n                        // 动态配置项，可以跳过多type索引启用映射查询的appid列表\n                    } else if (QueryConsts.MAPPING_INDEXNAME_WHITE_APPIDS.equals(dynamicConfigResponse.getValueName())) {\n                        dealWhiteAppId(dynamicConfigResponse);\n                    }else if(QueryConsts.FORBIDDEN_SETTING_PATH.equals(dynamicConfigResponse.getValueName())){\n                        forbiddenSettings = dynamicConfigResponse.getValue();\n                    }\n\n                } catch (Exception e) {\n                    bootLogger.error(\"dynamicConfig process value||name={}||value={}||e={}\", dynamicConfigResponse.getValueName(), dynamicConfigResponse.getValue(), Convert.logExceptionStack(e));\n                }\n\n            }\n\n            bootLogger.info(\"resetDynamicConfigInfo end...\");\n        } catch (Exception e) {\n            bootLogger.error(\"resetDynamicConfigInfo_error||e={}\", Convert.logExceptionStack(e));\n        }\n\n    }\n\n    private void dealWhiteAppId(DynamicConfigResponse dynamicConfigResponse) {\n        MappingIndexNameWhiteAppIds appIdds = JSON.parseObject(dynamicConfigResponse.getValue(), MappingIndexNameWhiteAppIds.class);\n        if (!whiteAppIds.equals(appIdds)) {\n            whiteAppIds.setAppids(appIdds.getAppids());\n        }\n    }\n\n    public String getForbiddenSettings() {\n        return forbiddenSettings;\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/impl/ESClusterServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.arius.impl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.enums.RunModeEnum;\nimport com.didi.arius.gateway.common.exception.ClusterNotFoundException;\nimport com.didi.arius.gateway.common.metadata.*;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.core.service.ESTcpClientService;\nimport com.didi.arius.gateway.core.service.arius.ESClusterService;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.DataCenterListResponse;\nimport com.didi.arius.gateway.remote.response.DataCenterResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.base.Strings;\nimport com.google.common.collect.Sets;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\n\nimport static com.didi.arius.gateway.common.consts.RestConsts.DEFAULT_WRITE_ACTION;\n\n@Service\n@NoArgsConstructor\npublic class ESClusterServiceImpl implements ESClusterService {\n    protected static final ILog logger = LogFactory.getLog(ESClusterServiceImpl.class);\n    protected static final ILog bootLogger = LogFactory.getLog( QueryConsts.BOOT_LOGGER);\n    public static final String CLUSTER_NOT_FOUND = \"cluster not found:\";\n    public static final String COLON = \":\";\n    public static final String COMMA = \",\";\n\n    @Autowired\n    private AriusAdminRemoteService ariusAdminRemoteService;\n\n    @Autowired\n    private ThreadPool threadPool;\n\n    @Autowired\n    private ESTcpClientService esTcpClientService;\n\n    @Autowired\n    private ESRestClientService esRestClientService;\n\n    @Autowired\n    private QueryConfig queryConfig;\n\n    @Value(\"${arius.gateway.adminSchedulePeriod}\")\n    private long schedulePeriod;\n\n    private Map<String, ESCluster> esClusterMap = new HashMap<>();\n    private Map<String, MetaVersion> versionMap = new HashMap<>();\n\n    @PostConstruct\n    public void init(){\n        threadPool.submitScheduleAtFixTask(this::resetESClusaterInfo, 0, schedulePeriod);\n    }\n\n    @Override\n    public Map<String, ESCluster> listESCluster(){\n        return esClusterMap;\n    }\n\n    @Override\n    public MetaVersion getMetaVersionByCluster(String cluster){\n        return versionMap.computeIfAbsent( cluster, s -> new MetaVersion() );\n    }\n\n    @Override\n    public void resetESClusaterInfo(){\n        try {\n            resetESClusterMap();\n        } catch (Exception e) {\n            bootLogger.error(\"resetESClusterMap error\", e);\n        }\n    }\n\n    @Override\n    public ESClient getClient(QueryContext queryContext, String actionName) {\n        ESClient client = esRestClientService.getClient(queryContext.getCluster(), actionName);\n\n        if (queryContext.isFromKibana()) {\n            client = esRestClientService.getAdminClient(actionName);\n        } else if (queryContext.getClusterId() != null){\n            client = esRestClientService.getClientStrict(queryContext.getClusterId(), actionName);\n            validClient(client, queryContext.getClusterId());\n        }\n\n        queryContext.setClient(client);\n        if (client != null) {\n            queryContext.setClusterName(client.getClusterName());\n        }\n\n        return client;\n    }\n\n    @Override\n    public ESClient getClient(QueryContext queryContext, IndexTemplate indexTemplate, String actionName) {\n        ESClient client = esRestClientService.getClient(queryContext.getCluster(), actionName);\n        String clusterName = queryContext.getCluster();\n\n        if (queryContext.isFromKibana()) {\n            client = esRestClientService.getAdminClient(actionName);\n            clusterName = queryConfig.getAdminClusterName();\n        } else if (queryContext.getClusterId() != null){\n            client = esRestClientService.getClientStrict(queryContext.getClusterId(), actionName);\n            clusterName = queryContext.getClusterId();\n        } else if (indexTemplate != null) {\n            boolean findSlave = false;\n            if (indexTemplate.getSlaveInfos() != null && !indexTemplate.getSlaveInfos().isEmpty()) {\n                for (TemplateClusterInfo info : indexTemplate.getSlaveInfos()) {\n                    if (info.getAccessApps().contains(queryContext.getAppid())) {\n                        client = esRestClientService.getClient(info.getCluster(), actionName);\n                        clusterName = info.getCluster();\n                        findSlave = true;\n                        break;\n                    }\n                }\n            }\n\n            if (!findSlave) {\n                client = esRestClientService.getClient(indexTemplate.getMasterInfo().getCluster(), actionName);\n                clusterName = indexTemplate.getMasterInfo().getCluster();\n            }\n        }\n\n        validClient(client, clusterName);\n\n        queryContext.setClient(client);\n        queryContext.setClusterName(client.getClusterName());\n\n        return client;\n    }\n\n    private void validClient(ESClient client, String clusterName) {\n        if (client == null) {\n            throw new ClusterNotFoundException(CLUSTER_NOT_FOUND + clusterName);\n        }\n    }\n\n    @Override\n    public ESClient getClientFromCluster(QueryContext queryContext, String clusterName, String actionName) {\n        ESClient readClient = esRestClientService.getClient(clusterName, actionName);\n\n        validClient(readClient, clusterName);\n\n        queryContext.setClient(readClient);\n        queryContext.setClusterName(readClient.getClusterName());\n\n        return readClient;\n    }\n\n    @Override\n    public ESClient getWriteClient(IndexTemplate indexTemplate, String actionName) {\n        String masterCluster = indexTemplate.getMasterInfo().getCluster();\n        ESClient writeClient = esRestClientService.getClient(masterCluster, actionName);\n\n        validClient(writeClient, masterCluster);\n\n        return writeClient;\n    }\n\n    /************************************************************** private method **************************************************************/\n    /**\n     * 更新集群列表\n     */\n    private void resetESClusterMap() {\n        DataCenterListResponse response = ariusAdminRemoteService.listCluster();\n\n        Map<String, ESCluster> newESClusterMap = new HashMap<>();\n        for (DataCenterResponse dataCenterResponse : response.getData()) {\n            if (dataCenterResponse.getHttpAddress() == null || dataCenterResponse.getHttpAddress().isEmpty()) {\n                bootLogger.warn(\"ESCluster httpAddress is empty, ESCluster={}\", dataCenterResponse.getCluster());\n                continue;\n            }\n\n            ESCluster esCluster = new ESCluster();\n            esCluster.setCluster(dataCenterResponse.getCluster());\n            esCluster.setReadAddress(dataCenterResponse.getReadAddress());\n            esCluster.setHttpAddress(dataCenterResponse.getHttpAddress());\n            esCluster.setHttpWriteAddress(dataCenterResponse.getHttpWriteAddress());\n            esCluster.setRunMode(dataCenterResponse.getRunMode());\n            initWriteAction(dataCenterResponse, esCluster);\n            bootLogger.info(\"dataCenter httpAddress[{}] httpWriteAddress[{}] runMode[{}] writeAction[{}]\", esCluster.getHttpAddress(),\n                    esCluster.getHttpWriteAddress(), esCluster.getRunMode(), esCluster.getWriteAction());\n\n            esCluster.setType( ESCluster.Type.integerToType(dataCenterResponse.getType()));\n\n            if (dataCenterResponse.getEsVersion() == null || dataCenterResponse.getEsVersion().equals(\"\")) {\n                esCluster.setEsVersion(QueryConsts.DEFAULT_ES_VERSION);\n            } else {\n                esCluster.setEsVersion(dataCenterResponse.getEsVersion());\n            }\n            esCluster.setPassword(dataCenterResponse.getPassword());\n\n            newESClusterMap.put(esCluster.getCluster(), esCluster );\n\n            if (!versionMap.containsKey(dataCenterResponse.getCluster())) {\n                MetaVersion version = new MetaVersion();\n                versionMap.put(esCluster.getCluster(), version);\n            }\n        }\n\n        bootLogger.info(\"resetESClusterMap done,old esClusterMap size={}, new esClusterMap size={}\", esClusterMap.size(), newESClusterMap.size());\n\n        esClusterMap = newESClusterMap;\n\n        String esClusterLog = JSON.toJSONString(esClusterMap);\n        bootLogger.info(\"esClusterMap now {}\", esClusterLog);\n\n        initESClient(newESClusterMap);\n    }\n\n    private void initESClient(Map<String, ESCluster> newESClusterMap){\n        esTcpClientService.resetClients(newESClusterMap);\n        esRestClientService.resetClients(newESClusterMap);\n    }\n\n    /**\n     * 初始化读写分离的writeAction\n     * @param dataCenterResponse admin返回的response\n     * @param dataCenter 构建的数据中心\n     */\n    private void initWriteAction(DataCenterResponse dataCenterResponse, ESCluster dataCenter) {\n        if (dataCenterResponse.getRunMode() == RunModeEnum.READ_WRITE_SPLIT.getRunMode()) {\n            dataCenter.setWriteAction(Strings.isNullOrEmpty(dataCenterResponse.getWriteAction()) ?\n                    DEFAULT_WRITE_ACTION :\n                    Sets.newHashSet(dataCenterResponse.getWriteAction().split(COMMA)));\n        } else {\n            dataCenter.setWriteAction(new HashSet<>());\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/impl/GateWayHeartBeatServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.arius.impl;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.arius.GateWayHeartBeatService;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.ActiveCountResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\n\n@Service\n@NoArgsConstructor\npublic class GateWayHeartBeatServiceImpl implements GateWayHeartBeatService {\n\n    protected static final ILog bootLogger = LogFactory.getLog( QueryConsts.BOOT_LOGGER);\n\n    @Autowired\n    private AriusAdminRemoteService ariusAdminRemoteService;\n\n    @Autowired\n    private QueryConfig queryConfig;\n\n    @Value(\"${gateway.nettyTransport.port}\")\n    private Integer port;\n\n    @Value(\"${arius.gateway.adminSchedulePeriod}\")\n    private long adminSchedulePeriod;\n\n    @Autowired\n    private ThreadPool threadPool;\n\n    private int currentNodeCount = 1;\n\n    @PostConstruct\n    public void init() {\n        threadPool.submitScheduleAtFixTask(this::resetHeartBeatInfo, 15, adminSchedulePeriod);\n    }\n\n    @Override\n    public void resetHeartBeatInfo(){\n        try {\n            heartbeat();\n        } catch (Exception e) {\n            bootLogger.error(\"heartbeat error\", e);\n        }\n        try {\n            resetActiveCount();\n        } catch (Exception e) {\n            bootLogger.error(\"resetActiveCount error\", e);\n        }\n\n    }\n\n    /************************************************************** private method **************************************************************/\n    private void heartbeat(){\n        ariusAdminRemoteService.heartbeat(QueryConsts.GATEWAY_GROUP, Convert.getHostName(), port);\n    }\n\n    /**\n     * 从admin获取存活的节点数量\n     * 节点数量跟当前保存的节点数量不一致时，更新dsl限流值\n     */\n    private void resetActiveCount() {\n        ActiveCountResponse response = ariusAdminRemoteService.getAliveCount(QueryConsts.GATEWAY_GROUP);\n        int activeCount = response.getData();\n\n        if (activeCount < 1) {\n            bootLogger.error(\"GateWayHeartBeatService alivecount error, activeCount={}\", activeCount);\n            return ;\n        }\n\n        if (activeCount == currentNodeCount) {\n            bootLogger.info(\"resetActiveCount end, activeCount not change, activeCount={}\", activeCount);\n            return;\n        }\n\n        bootLogger.info(\"resetActiveCount activeCount changes, need resetDslRateLimit, activeCount={}, currentNodeCount={}\", activeCount, currentNodeCount);\n\n        currentNodeCount = activeCount;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/arius/impl/IndexTemplateServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.arius.impl;\n\nimport static com.didi.arius.gateway.common.utils.AppUtil.isAdminAppid;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.enums.TemplateBlockTypeEnum;\nimport com.didi.arius.gateway.common.exception.IndexNotFoundException;\nimport com.didi.arius.gateway.common.exception.InvalidParameterException;\nimport com.didi.arius.gateway.common.exception.TemplateBlockException;\nimport com.didi.arius.gateway.common.exception.TooManyIndexException;\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.TemplateAlias;\nimport com.didi.arius.gateway.common.metadata.TemplateClusterInfo;\nimport com.didi.arius.gateway.common.metadata.TemplateInfo;\nimport com.didi.arius.gateway.common.utils.IndexTire;\nimport com.didi.arius.gateway.common.utils.IndexTireBuilder;\nimport com.didi.arius.gateway.common.utils.Regex;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.core.service.arius.AppService;\nimport com.didi.arius.gateway.core.service.arius.ESClusterService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.AliasesInfoResponse;\nimport com.didi.arius.gateway.remote.response.IndexTemplateListResponse;\nimport com.didi.arius.gateway.remote.response.IndexTemplateResponse;\nimport com.didi.arius.gateway.remote.response.SlaveInfoResponse;\nimport com.didi.arius.gateway.remote.response.TempaletAliasResponse;\nimport com.didi.arius.gateway.remote.response.TemplateInfoListResponse;\nimport com.didi.arius.gateway.remote.response.TemplateInfoResponse;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.common.collect.Maps;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport javax.annotation.PostConstruct;\nimport lombok.NoArgsConstructor;\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.collections.MapUtils;\nimport org.elasticsearch.gateway.GatewayException;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\n@Service\n@NoArgsConstructor\npublic class IndexTemplateServiceImpl implements IndexTemplateService {\n\n    private static final ILog bootLogger = LogFactory.getLog( QueryConsts.BOOT_LOGGER);\n    private static final ILog logger = LogFactory.getLog(IndexTemplateServiceImpl.class);\n\n    @Autowired\n    private AriusAdminRemoteService ariusAdminRemoteService;\n\n    @Autowired\n    private AppService appService;\n\n    @Autowired\n    private ESClusterService esClusterService;\n\n    @Autowired\n    private ThreadPool threadPool;\n\n    @Value(\"${arius.gateway.adminSchedulePeriod}\")\n    private long schedulePeriod;\n\n    @Autowired\n    private ESRestClientService esRestClientService;\n\n    private IndexTire indexTire;\n\n    private Map<String, Map<String, TemplateInfo>> templateExpressionMap = new HashMap<>();\n    private Map<String, Map<String, TemplateInfo>> templateAliasesMap \t = new HashMap<>();\n\n    private Map<String, IndexTemplate>  indexTemplateMap = new HashMap<>();\n    private Map<String, String>         indexToAlias     = new HashMap<>();\n\n    @PostConstruct\n    public void init(){\n        threadPool.submitScheduleAtFixTask(this::resetIndexTemplateInfo, 20, schedulePeriod);\n    }\n\n    @Override\n    public Map<String, Map<String, TemplateInfo>> getTemplateExpressionMap() {\n        return templateExpressionMap;\n    }\n\n    @Override\n    public Map<String, Map<String, TemplateInfo>> getTemplateAliasMap() {\n        return templateAliasesMap;\n    }\n\n    @Override\n    public IndexTemplate getIndexTemplate(String template) {\n        return indexTemplateMap.get(template);\n    }\n\n    @Override\n    public IndexTemplate getIndexTemplateByTire(String index) throws TooManyIndexException {\n        if (indexTire == null) {\n            return null;\n        }\n\n        return indexTire.search(index);\n    }\n\n    @Override\n    public Map<String, IndexTemplate> getIndexTemplateMap() {\n        return indexTemplateMap;\n    }\n\n    @Override\n    public void resetIndexTemplateInfo(){\n        try {\n            resetTemplateDetail();\n        } catch (Exception e) {\n            bootLogger.error(\"resetTemplateDetail error\", e);\n        }\n\n        try {\n            resetTemplateInfo();\n        } catch (Exception e) {\n            bootLogger.error(\"resetTemplateInfo error\", e);\n        }\n\n        try {\n            resetIndexAlias();\n        } catch (Exception e) {\n            bootLogger.error(\"resetIndexAlias error\", e);\n        }\n\n    }\n\n    @Override\n    public String getIndexAlias(String index) {\n        return indexToAlias.get(index);\n    }\n\n    @Override\n    public boolean checkIndex(String index, List<String> indexExps) {\n        if (index.startsWith(\".\")) {\n            return true;\n        }\n\n        boolean matched = false;\n        for (String indexExp : indexExps) {\n            if (Regex.expContainIndex(index, indexExp)) {\n                logger.debug(\"index permitted, index={}, indexExp={}\", index, indexExp);\n                matched = true;\n                break ;\n            }\n        }\n\n        return matched;\n    }\n\n    @Override\n    public int getIndexVersion(String indexName, String cluster) {\n        if (indexName == null) {\n            return 0;\n        }\n\n        TemplateInfo templateInfo = getAliasesMatch(indexName, cluster);\n        if (templateInfo != null) {\n            return templateInfo.getVersion();\n        }\n\n        templateInfo = getExpressionMatch(indexName, cluster);\n        if (templateInfo != null) {\n            return templateInfo.getVersion();\n        }\n\n        return 0;\n    }\n\n    @Override\n    public IndexTemplate getTemplateByIndexTire(List<String> indices, QueryContext queryContext) throws IndexNotFoundException, TooManyIndexException{\n        String index = indices.get(0);\n\n        IndexTemplate indexTemplate = getIndexTemplateByTire(index);\n        if (indexTemplate == null) {\n            String alias = getIndexAlias(index);\n            if (alias != null) {\n                indexTemplate = getIndexTemplateByTire(alias);\n            }\n        }\n\n        if (indexTemplate == null) {\n            throw new IndexNotFoundException(\"query can't find index template exception,index=\" + index);\n        }\n\n        for (int i = 1; i < indices.size(); ++i) {\n            boolean check = IndexTire.checkIndexMatchTemplate(indices.get(i), indexTemplate);\n            if (!check) {\n                String alias = getIndexAlias(indices.get(i));\n                if (alias != null) {\n                    check = IndexTire.checkIndexMatchTemplate(alias, indexTemplate);\n                }\n            }\n\n            if (!check) {\n                throw new TooManyIndexException(String.format(\"search query indices don't have the same index template, index1=%s, index2=%s\", index, indices.get(i)));\n            }\n        }\n\n        queryContext.setIndexTemplate(indexTemplate);\n\n        return indexTemplate;\n    }\n\n    /************************************************************** private method **************************************************************/\n    /**\n     * 更新各集群模板、大基数mapping等信息\n     */\n    private void resetTemplateDetail() {\n        for (Map.Entry<String, ESCluster> entry : esClusterService.listESCluster().entrySet()) {\n            String cluster = entry.getKey();\n\n            TemplateInfoListResponse templateInfoListResponse = ariusAdminRemoteService.getTemplateInfoMap(cluster);\n\n            resetTemplateMap(cluster, templateInfoListResponse);\n        }\n    }\n\n    /**\n     * 更新索引模板\n     * @param cluster 集群名称\n     * @param response 索引模板接口数据\n     */\n    private void resetTemplateMap(String cluster, TemplateInfoListResponse response) {\n        Map<String, TemplateInfo> expressionMap = new HashMap<>();\n        Map<String, TemplateInfo> aliasesMap = new HashMap<>();\n\n        Map<String, TemplateInfo> oldExpressionMap = templateExpressionMap.get(cluster);\n\n        for (Map.Entry<String, TemplateInfoResponse> entry : response.getData().entrySet()) {\n            TemplateInfoResponse templateInfoResponse = entry.getValue();\n\n            boolean needSource = false;\n\n            TemplateInfo templateInfo = new TemplateInfo();\n            templateInfo.setNeedSource(needSource);\n            templateInfo.setVersion(templateInfoResponse.getVersion());\n\n            if (oldExpressionMap != null && oldExpressionMap.containsKey(templateInfoResponse.getExpression())) {\n                TemplateInfo oldTemplateInfo = oldExpressionMap.get(templateInfoResponse.getExpression());\n                templateInfo.setMappings(oldTemplateInfo.getMappings());\n            }\n\n            expressionMap.put(templateInfoResponse.getExpression(), templateInfo);\n\n            for (AliasesInfoResponse aliasesInfoResponse : templateInfoResponse.getAliases()) {\n                aliasesMap.put(aliasesInfoResponse.getName(), templateInfo);\n            }\n        }\n\n        templateExpressionMap.put(cluster, expressionMap);\n        templateAliasesMap.put(cluster, aliasesMap);\n\n        bootLogger.info(\"cluster={}||expressionMap size={}||aliasesMap size={}\", cluster, expressionMap.size(), aliasesMap.size());\n    }\n\n    /**\n     * 更新逻辑索引模板列表\n     */\n    private void resetTemplateInfo() {\n        bootLogger.info(\"resetTemplateInfo begin...\");\n\n        Map<String, IndexTemplate> newIndexTemplateMap = new HashMap<>();\n\n        IndexTemplateListResponse response = ariusAdminRemoteService.listDeployInfo();\n\n        for (Map.Entry<String, IndexTemplateResponse> entry : response.getData().entrySet()) {\n            IndexTemplateResponse indexTemplateResponse = entry.getValue();\n            IndexTemplate indexTemplate = new IndexTemplate();\n\n            indexTemplate.setName(entry.getKey());\n            indexTemplate.setId(indexTemplateResponse.getBaseInfo().getId());\n            indexTemplate.setDateField(indexTemplateResponse.getBaseInfo().getDateField());\n            indexTemplate.setDateFormat(indexTemplateResponse.getBaseInfo().getDateFormat());\n            indexTemplate.setExpireTime(indexTemplateResponse.getBaseInfo().getExpireTime());\n            indexTemplate.setExpression(indexTemplateResponse.getBaseInfo().getExpression());\n            indexTemplate.setIsDefaultRouting(indexTemplateResponse.getBaseInfo().getIsDefaultRouting());\n            indexTemplate.setVersion(indexTemplateResponse.getBaseInfo().getVersion());\n            indexTemplate.setDeployStatus(IndexTemplate.DeployStatus.integerToStatus(indexTemplateResponse.getBaseInfo().getDeployStatus()));\n            indexTemplate.setAliases(indexTemplateResponse.getBaseInfo().getAliases());\n            indexTemplate.setIngestPipeline(indexTemplateResponse.getBaseInfo().getIngestPipeline());\n            indexTemplate.setBlockRead(null != indexTemplateResponse.getBaseInfo().getBlockRead() && indexTemplateResponse.getBaseInfo().getBlockRead());\n            indexTemplate.setBlockWrite(null != indexTemplateResponse.getBaseInfo().getBlockWrite() && indexTemplateResponse.getBaseInfo().getBlockWrite());\n\n\n            TemplateClusterInfo masterInfo = new TemplateClusterInfo();\n\n            masterInfo.setAccessApps(indexTemplateResponse.getMasterInfo().getAccessApps() == null ? new HashSet<>() : new HashSet<>(indexTemplateResponse.getMasterInfo().getAccessApps()));\n            masterInfo.setCluster(indexTemplateResponse.getMasterInfo().getCluster());\n            masterInfo.setTopic(indexTemplateResponse.getMasterInfo().getTopic());\n            masterInfo.setMappingIndexNameEnable(!Objects.isNull(indexTemplateResponse.getMasterInfo().getMappingIndexNameEnable()) && indexTemplateResponse.getMasterInfo().getMappingIndexNameEnable());\n            masterInfo.setTypeIndexMapping( MapUtils.isEmpty(indexTemplateResponse.getMasterInfo().getTypeIndexMapping()) ? Maps.newHashMap() : indexTemplateResponse.getMasterInfo().getTypeIndexMapping());\n\n            indexTemplate.setMasterInfo(masterInfo);\n            List<TemplateClusterInfo> slaveInfos = new ArrayList<>();\n\n            dealSlaveInfos(indexTemplateResponse, slaveInfos);\n            indexTemplate.setSlaveInfos(slaveInfos);\n\n            String expression = indexTemplate.getExpression();\n            if (expression.endsWith(\"*\")) {\n                expression = expression.substring(0, expression.length()-1);\n            }\n\n            newIndexTemplateMap.put(expression, indexTemplate);\n\n            if(CollectionUtils.isNotEmpty(indexTemplate.getAliases())){\n                for(String alias : indexTemplate.getAliases()){\n                    newIndexTemplateMap.put(alias, indexTemplate);\n                }\n            }\n\n        }\n\n        bootLogger.info(\"resetTemplateInfo add indexTemplateMap size={}\", response.getData().size());\n\n        IndexTireBuilder builder = new IndexTireBuilder(indexTemplateMap);\n        indexTire = builder.build();\n        indexTemplateMap = newIndexTemplateMap;\n\n        String indexTemplateLog = JSON.toJSONString(indexTemplateMap);\n        bootLogger.info(\"resetTemplateInfo end, newIndexTemplateMap size={}, detail={}\", indexTemplateMap.size(), indexTemplateLog);\n    }\n\n    private void dealSlaveInfos(IndexTemplateResponse indexTemplateResponse, List<TemplateClusterInfo> slaveInfos) {\n        if (indexTemplateResponse.getSlaveInfos() != null && !indexTemplateResponse.getSlaveInfos().isEmpty()) {\n            for (SlaveInfoResponse slaveInfoResponse : indexTemplateResponse.getSlaveInfos()) {\n                TemplateClusterInfo slaveInfo = new TemplateClusterInfo();\n                slaveInfo.setAccessApps(slaveInfoResponse.getAccessProjects() == null ? new HashSet<>() : new HashSet<>(slaveInfoResponse.getAccessProjects()));\n                slaveInfo.setCluster(slaveInfoResponse.getCluster());\n                slaveInfo.setTopic(slaveInfoResponse.getTopic());\n                slaveInfo.setMappingIndexNameEnable(!Objects.isNull(slaveInfoResponse.getMappingIndexNameEnable()) && slaveInfoResponse.getMappingIndexNameEnable());\n                slaveInfo.setTypeIndexMapping(MapUtils.isEmpty(slaveInfoResponse.getTypeIndexMapping()) ? Maps.newHashMap() : slaveInfoResponse.getTypeIndexMapping());\n\n                slaveInfos.add(slaveInfo);\n            }\n        }\n    }\n\n    private void resetIndexAlias() {\n        if (MapUtils.isEmpty(esRestClientService.getESClusterMap())) {\n            return;\n        }\n        Map<String, String> newIndexToAlias = new HashMap<>();\n        for (Map.Entry<String, ESCluster> entry : esRestClientService.getESClusterMap().entrySet()) {\n            ESCluster esCluster = entry.getValue();\n            if (esCluster.getType() != ESCluster.Type.INDEX) {\n                continue;\n            }\n            try {\n                JSONArray alias = getAliasList(esCluster.getEsClient());\n\n                bootLogger.info(\"get_alias_list||cluster={}||alias_size={}\", esCluster.getCluster(), alias.size());\n\n                for (int i = 0; i < alias.size(); ++i) {\n                    JSONObject item = alias.getJSONObject(i);\n                    String strAlias = item.getString(\"alias\");\n                    String index = item.getString(\"index\");\n\n                    newIndexToAlias.put(index, strAlias);\n                }\n            } catch (Exception e) {\n                bootLogger.error(\"cluster={}\", esCluster.getCluster(), e);\n            }\n        }\n\n        this.indexToAlias = newIndexToAlias;\n        bootLogger.info(\"get_alias_list_done||alias_size={}\", indexToAlias.size());\n    }\n\n    private JSONArray getAliasList(ESClient esClient) {\n        DirectRequest directRequest = new DirectRequest(\"GET\", \"_cat/aliases\");\n        Map<String, String> params = new HashMap<>();\n        params.put(\"h\", \"alias,index\");\n        directRequest.setParams(params);\n        directRequest.putHeader(\"Accept\", \"application/json\");\n        if (esClient.getEsVersion().equals(QueryConsts.DEFAULT_ES_VERSION)) {\n            directRequest.putHeader(\"content-type\", \"application/json\");\n        }\n        DirectResponse directResponse = esClient.direct(directRequest).actionGet();\n        if (directResponse.getRestStatus() == RestStatus.OK && directResponse.getResponseContent() != null) {\n            try {\n                return JSON.parseArray(directResponse.getResponseContent());\n            } catch (Exception e) {\n                bootLogger.error(\"get_alias_list_parse_error||cluster={}||content={}\", esClient.getClusterName(), directResponse.getResponseContent(), e);\n                return new JSONArray();\n            }\n        } else {\n            throw new GatewayException(\"get client aliases error, status=\" + directResponse.getRestStatus());\n        }\n    }\n\n    private TemplateInfo getAliasesMatch(String indexName, String cluster) {\n        Map<String, Map<String, TemplateInfo>> templateAliasesMapInfo = getTemplateAliasMap();\n\n        if (templateAliasesMapInfo.get(cluster) != null) {\n            Map<String, TemplateInfo> aliasesMap = templateAliasesMapInfo.get(cluster);\n            TemplateInfo templateInfo = aliasesMap.get(indexName);\n            return templateInfo;\n        } else {\n            for(Map.Entry<String, Map<String, TemplateInfo>> entry : templateAliasesMapInfo.entrySet()) {\n                Map<String, TemplateInfo> aliasesMap = entry.getValue();\n                TemplateInfo templateInfo = aliasesMap.get(indexName);\n                if (templateInfo != null) {\n                    return templateInfo;\n                }\n            }\n        }\n\n        return null;\n    }\n\n    private TemplateInfo getExpressionMatch(String indexName, String cluster) {\n        Map<String, Map<String, TemplateInfo>> templateExpressionMapInfo = getTemplateExpressionMap();\n\n        if (templateExpressionMapInfo.get(cluster) != null) {\n            Map<String, TemplateInfo> expressionMap = templateExpressionMapInfo.get(cluster);\n            TemplateInfo templateInfo = expressionMap.get(indexName);\n            if (templateInfo != null) {\n                return templateInfo;\n            }\n            return getTemplateInfoByIndexName(indexName, expressionMap);\n        } else {\n            for(Map.Entry<String, Map<String, TemplateInfo>> entry : templateExpressionMapInfo.entrySet()) {\n                Map<String, TemplateInfo> expressionMap = entry.getValue();\n                TemplateInfo templateInfo = getTemplateInfoByIndexName(indexName, expressionMap);\n                if (null != templateInfo) {\n                    return templateInfo;\n                }\n            }\n        }\n\n        return null;\n    }\n\n    private TemplateInfo getTemplateInfoByIndexName(String indexName, Map<String, TemplateInfo> expressionMap) {\n        for (Map.Entry<String, TemplateInfo> entry : expressionMap.entrySet()) {\n            String expression = entry.getKey();\n            if (expression.endsWith(\"*\")) {\n                if (indexName.startsWith(expression.substring(0, expression.length() - 1))) {\n                    return entry.getValue();\n                }\n            } else if (expression.equals(indexName)) {\n                return entry.getValue();\n            }\n        }\n        return null;\n    }\n\n    @Override\n    public boolean addTemplateAlias(int appid, int templateId, String templateName, String aliasName){\n        //1、调admin接口增加模板别名\n        TemplateAlias templateAlias = new TemplateAlias();\n        templateAlias.setLogicId(templateId);\n        templateAlias.setName(aliasName);\n\n        TempaletAliasResponse response = ariusAdminRemoteService.addAdminTemplateAlias(templateAlias);\n        if (null == response || null == response.getData()) {\n            logger.error(\"addTemplateAlias error, response={}, templateAlias={}\", JSON.toJSONString(response),\n                    JSON.toJSONString(templateAlias));\n            return false;\n        } else if (!response.getData()) {\n            throw new IllegalArgumentException(response.getMessage());\n        }\n\n        AppDetail appDetail = appService.getAppDetail(appid);\n        if(null == appDetail){\n            return false;\n        }\n\n        IndexTemplate indexTemplate = indexTemplateMap.get(templateName);\n        if(null == indexTemplate){\n            return false;\n        }\n\n        //2、更新appDetails信息\n        if(null != appDetail.getIndexExp() &&\n                appDetail.getIndexExp().contains(templateName)){\n            appDetail.getIndexExp().add(aliasName);\n        }\n\n        if(null != appDetail.getWindexExp() &&\n                appDetail.getWindexExp().contains(templateName)){\n            appDetail.getWindexExp().add(aliasName);\n        }\n\n        //3、更新indexTemplateMap信息\n        if(null == indexTemplate.getAliases()){\n            List<String> aliass = new ArrayList<>();\n            aliass.add(aliasName);\n\n            indexTemplate.setAliases(aliass);\n        }else {\n            indexTemplate.getAliases().add(aliasName);\n        }\n\n        indexTemplateMap.put(aliasName, indexTemplate);\n\n        return true;\n    }\n\n    @Override\n    public boolean delTemplateAlias(int appid, int templateId, String templateName, String aliasName){\n        //1、调admin接口删除模板别名\n        TemplateAlias templateAlias = new TemplateAlias();\n        templateAlias.setLogicId(templateId);\n        templateAlias.setName(aliasName);\n\n        TempaletAliasResponse response = ariusAdminRemoteService.delAdminTemplateAlias(templateAlias);\n\t\tif(null == response || null == response.getData() || !response.getData()){\n            logger.error(\"deleteTemplateAlias error, response={}, templateAlias={}\", JSON.toJSONString(response),\n                    JSON.toJSONString(templateAlias));\n            return false;\n\t\t}\n\n        AppDetail appDetail = appService.getAppDetail(appid);\n        if(null == appDetail){\n            return false;\n        }\n\n        IndexTemplate indexTemplate = indexTemplateMap.get(templateName);\n        if(null == indexTemplate){\n            return false;\n        }\n\n        //2、更新appDetails信息\n        if(null != appDetail.getIndexExp() &&\n                appDetail.getIndexExp().contains(aliasName)){\n            appDetail.getIndexExp().remove(aliasName);\n        }\n\n        if(null != appDetail.getWindexExp() &&\n                appDetail.getWindexExp().contains(aliasName)){\n            appDetail.getWindexExp().remove(aliasName);\n        }\n\n        //3、更新indexTemplateMap信息\n        if(null != indexTemplate.getAliases()){\n            indexTemplate.getAliases().remove(aliasName);\n        }\n\n        indexTemplateMap.remove(aliasName);\n\n        return true;\n    }\n\n    @Override\n    public void checkTemplateExist(List<String> indices) {\n        if (indices == null || indices.isEmpty()) {\n            throw new InvalidParameterException(\"no index to query\");\n        }\n        for (String index : indices) {\n            if (index.startsWith(\".\")) {\n                continue;\n            }\n            IndexTemplate indexTemplate = getIndexTemplateByTire(index);\n            if (indexTemplate == null) {\n                String alias = getIndexAlias(index);\n                if (alias != null) {\n                    indexTemplate = getIndexTemplateByTire(alias);\n                }\n            }\n\n            if (indexTemplate == null) {\n                throw new IndexNotFoundException(\"query can't find index template exception,index=\" + index);\n            }\n        }\n    }\n\n    @Override\n    public void checkTemplateBlock(List<String> indices, AppDetail appDetail, TemplateBlockTypeEnum blockTypeEnum) throws IndexNotFoundException {\n        if (indices == null || indices.isEmpty()) {\n            throw new InvalidParameterException(\"no index to query\");\n        }\n        for (String index : indices) {\n            if (index.startsWith(\".\")) {\n                continue;\n            }\n            IndexTemplate indexTemplate = getIndexTemplateByTire(index);\n            if (indexTemplate == null) {\n                String alias = getIndexAlias(index);\n                if (alias != null) {\n                    indexTemplate = getIndexTemplateByTire(alias);\n                }\n            }\n\n            if (indexTemplate == null) {\n                throw new IndexNotFoundException(String.format(\"query can't find index template exception, index=%s\", index));\n            }\n\n            if (!isAdminAppid(appDetail)) {\n                checkBlockType(blockTypeEnum, index, indexTemplate);\n            }\n        }\n    }\n\n    private void checkBlockType(TemplateBlockTypeEnum blockTypeEnum, String index, IndexTemplate indexTemplate) {\n        switch (blockTypeEnum) {\n            case READ_BLOCK_TYPE:\n                if (indexTemplate.getBlockRead()) {\n                    throw new TemplateBlockException(String.format(\"index[%s] block read\", index));\n                }\n                break;\n            case WRITE_WRITE_TYPE:\n                if (indexTemplate.getBlockWrite()) {\n                    throw new TemplateBlockException(String.format(\"index[%s] block write\", index));\n                }\n                break;\n            default:\n        }\n    }\n\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/DslAggsAnalyzerService.java",
    "content": "package com.didi.arius.gateway.core.service.dsl;\n\nimport com.didi.arius.gateway.common.metadata.AggsAnalyzerContext;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.BaseContext;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport org.elasticsearch.common.bytes.BytesReference;\n\nimport java.util.Map;\n\n/**\n * @author fitz\n * @date 2021/5/25 7:23 下午\n * dsl结果聚合分析的，看看聚合计算的bucket有多大\n */\npublic interface DslAggsAnalyzerService {\n    /**\n     *\n     * dsl结果聚合分析，看看聚合计算的bucket有多大，是否满足需求\n     * @param baseContext\n     * @param source\n     * @param indices\n     * @param cluster\n     * @return\n     */\n    boolean analyze(BaseContext baseContext, BytesReference source, String[] indices, String cluster);\n\n    /**\n     * 同上， 聚合分析\n     * @param baseContext\n     * @param source\n     * @param indices\n     * @return\n     */\n    boolean analyzeAggs(BaseContext baseContext, BytesReference source, String[] indices);\n\n    /**\n     * 检测聚合查询bucket信息\n     * @param aggsObject\n     * @param level\n     * @param mergedMappings\n     * @param context\n     * @return\n     */\n    AggsBukcetInfo checkAggs(JsonObject aggsObject, int level, Map<String, FieldInfo> mergedMappings, AggsAnalyzerContext context);\n\n    /**\n     * 合并templateAliasesMap和templateExpressionMap\n     * @param indices\n     * @param cluster\n     * @return\n     */\n    Map<String, FieldInfo> mergeMappings(String[] indices, String cluster);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/DslAuditService.java",
    "content": "package com.didi.arius.gateway.core.service.dsl;\n\nimport com.didi.arius.gateway.common.metadata.BaseContext;\nimport org.elasticsearch.common.bytes.BytesReference;\n\n/**\n * @author fitz\n * @date 2021/5/25 7:38 下午\n * dsl模板解析，把dsl语句解析成dsl模板\n */\npublic interface DslAuditService {\n    /**\n     * dsl模板解析，把dsl语句解析成dsl模板, 并做访问和限流校验\n     * @param baseContext\n     * @param source\n     * @param indices\n     * @return\n     */\n    String auditDSL(BaseContext baseContext, BytesReference source, String[] indices);\n\n    /**\n     *\n     * 同上\n     * @param baseContext\n     * @param sql\n     * @param indices\n     * @return\n     */\n    String auditSQL(BaseContext baseContext, String sql, String[] indices);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/DslRewriterService.java",
    "content": "package com.didi.arius.gateway.core.service.dsl;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.metadata.BaseContext;\nimport org.elasticsearch.common.bytes.BytesReference;\n\n/**\n * @author fitz\n * @date 2021/5/25 7:44 下午\n * 做dsl兼容，兼容高低版本的dsl语法差异\n */\npublic interface DslRewriterService {\n\n    /**\n     * dsl兼容\n     * @param context\n     * @param esVersion\n     * @param source\n     * @return\n     * @throws Exception\n     */\n    BytesReference rewriteRequest(BaseContext context, String esVersion, JSONObject source) throws Exception;\n\n    /**\n     *\n     * 执行typed_key\n     * @param context\n     * @param source\n     */\n    void doTypedKey(BaseContext context, JSONObject source);\n\n    /**\n     * dsl兼容\n     * @param context\n     * @param esVersion\n     * @param source\n     * @return\n     */\n    BytesReference rewriteRequest(BaseContext context, String esVersion, BytesReference source);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/AggsType.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.enums.AggsTypeEnum;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\n\nimport java.util.Map;\n\npublic interface AggsType {\n\t/**\n\t *\n\t * @param item\n\t * @param mergedMappings\n\t * @return\n\t */\n\tAggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings);\n\n\t/**\n\t *\n\t * @return\n\t */\n\tAggsTypeEnum getType();\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/AggsTypes.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport org.springframework.stereotype.Component;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n@Component(\"aggsTypes\")\npublic class AggsTypes {\n\tprivate Map<String, AggsType> aggsTypeMap = new HashMap<>();\n\t\n\tpublic void putAggsType(String name, AggsType aggsType) {\n\t\taggsTypeMap.put(name, aggsType);\n\t}\n\t\n\tpublic AggsType getAggsType(String name) {\n\t\treturn aggsTypeMap.get(name);\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/BucketAggsType.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.enums.AggsTypeEnum;\n\npublic abstract class BucketAggsType implements AggsType {\n\tprotected AggsTypeEnum type = AggsTypeEnum.BUCKET;\n\t\n\tpublic AggsTypeEnum getType() {\n\t\treturn type;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/BucketScriptAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.exception.AggsParseException;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"bucketScriptAggs\")\npublic class BucketScriptAggs extends MetricsAggsType {\n\n\tprivate String name = \"bucket_script\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic BucketScriptAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tthrow new AggsParseException(\"bucket_script aggregation forbidden\");\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/CardinalityAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport org.elasticsearch.search.aggregations.metrics.cardinality.HyperLogLogPlusPlus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"cardinalityAggs\")\npublic class CardinalityAggs extends MetricsAggsType {\n\n\tprivate String name = \"cardinality\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic CardinalityAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tint iMemPrecision = 4;\n\t\tJsonElement precision = item.get(\"precision_threshold\");\n\t\tif (precision != null) {\n\t\t\tint iPrecision = precision.getAsInt();\n\t\t\tiMemPrecision = HyperLogLogPlusPlus.precisionFromThreshold(iPrecision);\n\t\t}\n\n\t\tlong memUsed = HyperLogLogPlusPlus.memoryUsage(iMemPrecision);\n\t\tAggsBukcetInfo aggsBukcetInfo = AggsBukcetInfo.createSingleMetrics();\n\t\taggsBukcetInfo.setMemUsed(memUsed);\n\t\n\t\treturn aggsBukcetInfo;\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/ChildrenAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"ChildrenAggs\")\npublic class ChildrenAggs extends BucketAggsType {\n\n\tprivate String name = \"children\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic ChildrenAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\treturn AggsBukcetInfo.createSingleBucket();\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/DateHistogramAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.common.collect.ImmutableMap;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport org.elasticsearch.common.collect.MapBuilder;\nimport org.elasticsearch.common.unit.TimeValue;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\n@Component(\"dateHistogramAggs\")\npublic class DateHistogramAggs extends BucketAggsType {\n\n\tprivate String name = \"date_histogram\";\n\t\n\tpublic static final ImmutableMap<String, TimeValue> DATE_FIELD_UNITS;\n\n\tprotected static final String DATE_AGG_INTERVAL = \"DateHistogramAggs.interval\";\n\n\tprotected static final long DAY_MILLS = 24 * 60 * 60 * 1000L;\n\t\n    static {\n        DATE_FIELD_UNITS = MapBuilder.<String, TimeValue>newMapBuilder()\n                .put(\"year\", new TimeValue(365 * DAY_MILLS, TimeUnit.MILLISECONDS))\n                .put(\"1y\", new TimeValue(365 * DAY_MILLS, TimeUnit.MILLISECONDS))\n                .put(\"quarter\", new TimeValue(90 * DAY_MILLS, TimeUnit.MILLISECONDS))\n                .put(\"1q\", new TimeValue(90 * DAY_MILLS, TimeUnit.MILLISECONDS))\n                .put(\"month\", new TimeValue(30 * DAY_MILLS, TimeUnit.MILLISECONDS))\n                .put(\"1M\", new TimeValue(30 * DAY_MILLS, TimeUnit.MILLISECONDS))\n                .put(\"week\", TimeValue.parseTimeValue(\"1w\", null, DATE_AGG_INTERVAL))\n                .put(\"1w\", TimeValue.parseTimeValue(\"1w\", null, DATE_AGG_INTERVAL))\n                .put(\"day\", TimeValue.parseTimeValue(\"1d\", null, DATE_AGG_INTERVAL))\n                .put(\"1d\", TimeValue.parseTimeValue(\"1d\", null, DATE_AGG_INTERVAL))\n                .put(\"hour\", TimeValue.parseTimeValue(\"1h\", null, DATE_AGG_INTERVAL))\n                .put(\"1h\", TimeValue.parseTimeValue(\"1h\", null, DATE_AGG_INTERVAL))\n                .put(\"minute\", TimeValue.parseTimeValue(\"1m\", null, DATE_AGG_INTERVAL))\n                .put(\"1m\", TimeValue.parseTimeValue(\"1m\", null, DATE_AGG_INTERVAL))\n                .put(\"second\", TimeValue.parseTimeValue(\"1s\", null, DATE_AGG_INTERVAL))\n                .put(\"1s\", TimeValue.parseTimeValue(\"1s\", null, DATE_AGG_INTERVAL))\n                .immutableMap();\n    }\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\t\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\n\tpublic DateHistogramAggs() {\n\t\t// pass\n\t}\n\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tJsonElement interval = item.get(\"interval\");\n\t\tif (interval == null) {\n\t\t\treturn AggsBukcetInfo.createSingleBucket();\n\t\t}\n\n\t\tString strInterval = interval.getAsString();\n\n\t\tif (strInterval == null) {\n\t\t\treturn AggsBukcetInfo.createSingleBucket();\n\t\t}\n\t\t\n\t\tTimeValue timeValue = DATE_FIELD_UNITS.get(strInterval);\n\t\tif (timeValue == null) {\n\t\t\ttimeValue = TimeValue.parseTimeValue(strInterval, null, getClass().getSimpleName() + \".interval\");\n\t\t}\n\n\t\tlong lInterval = timeValue.getMillis();\n\t\t\n\t\tif (lInterval <= 0) {\n\t\t\treturn AggsBukcetInfo.createSingleBucket(); \n\t\t}\n\t\t\n\t\tint bucket = (int) (QueryConsts.DATE_HISTOGRAM_DEFAUL_RANGE / lInterval);\n\t\t\n\t\tJsonElement extendedBounds = item.get(\"extended_bounds\");\n\t\tif (extendedBounds != null) {\n\t\t\tlong lMin = 0;\n\t\t\tlong lMax = 0;\n\t\t\tJsonObject jsonExtended = extendedBounds.getAsJsonObject();\n\t\t\tJsonElement min = jsonExtended.get(\"min\");\n\t\t\tif (min != null) {\n\t\t\t\tlMin = min.getAsLong();\n\t\t\t}\n\t\t\t\n\t\t\tJsonElement max = jsonExtended.get(\"max\");\n\t\t\tif (max != null) {\n\t\t\t\tlMax = max.getAsLong();\n\t\t\t}\n\t\t\t\n\t\t\tif (lMin > 0 && lMax >= lMin) {\n\t\t\t\tbucket = (int) ((lMax + 1 - lMin) / lInterval);\n\t\t\t}\n\t\t}\n\t\t\n\t\tAggsBukcetInfo aggsBukcetInfo = new AggsBukcetInfo();\n\t\t\n\t\taggsBukcetInfo.setBucketNumber(bucket);\n\t\taggsBukcetInfo.setLastBucketNumber(bucket);\n\t\taggsBukcetInfo.setMemUsed((long)bucket * QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\t\n\t\treturn aggsBukcetInfo;\t\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/DateRangeAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"dateRangeAggs\")\npublic class DateRangeAggs extends BucketAggsType {\n\n\tprivate String name = \"date_range\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic DateRangeAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tAggsBukcetInfo aggsBukcetInfo = new AggsBukcetInfo();\n\t\t\n\t\tJsonElement ranges = item.get(\"ranges\");\n\t\tif (ranges != null) {\n\t\t\tJsonArray rangesArr = ranges.getAsJsonArray();\n\t\t\taggsBukcetInfo.setBucketNumber(rangesArr.size());\n\t\t\taggsBukcetInfo.setLastBucketNumber(rangesArr.size());\n\t\t\taggsBukcetInfo.setMemUsed((long)rangesArr.size() * QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\t}\n\t\t\n\t\treturn aggsBukcetInfo;\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/FilterAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"filterAggs\")\npublic class FilterAggs extends BucketAggsType {\n\n\tprivate String name = \"filter\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic FilterAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\treturn AggsBukcetInfo.createSingleBucket();\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/FiltersAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"filtersAggs\")\npublic class FiltersAggs extends BucketAggsType {\n\n\tprivate String name = \"filters\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic FiltersAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tJsonElement filters = item.get(\"filters\");\n\t\tif (filters != null) {\n\t\t\tAggsBukcetInfo aggsBukcetInfo = new AggsBukcetInfo();\n\t\t\t\n\t\t\tif (filters.isJsonObject()) {\n\t\t\t\tJsonObject jsonFilters = filters.getAsJsonObject();\n\t\t\t\tint size = jsonFilters.entrySet().size();\n\t\t\t\taggsBukcetInfo.setBucketNumber(size);\n\t\t\t\taggsBukcetInfo.setLastBucketNumber(size);\n\t\t\t\taggsBukcetInfo.setMemUsed((long)size * QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\t\t\t\n\t\t\t\treturn aggsBukcetInfo;\n\t\t\t} else if (filters.isJsonArray()) {\n\t\t\t\tJsonArray jsonRanges = filters.getAsJsonArray();\n\t\t\t\tint size = jsonRanges.size();\n\t\t\t\taggsBukcetInfo.setBucketNumber(size);\n\t\t\t\taggsBukcetInfo.setLastBucketNumber(size);\n\t\t\t\taggsBukcetInfo.setMemUsed((long)size * QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\t\t\t\n\t\t\t\treturn aggsBukcetInfo;\n\t\t\t} else {\n\t\t\t\treturn AggsBukcetInfo.createSingleBucket();\n\t\t\t}\n\t\t} else {\n\t\t\treturn AggsBukcetInfo.createSingleBucket();\n\t\t}\n\t\t\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/GeoDistanceAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"geoDistanceAggs\")\npublic class GeoDistanceAggs extends BucketAggsType {\n\tprivate String name = \"geo_distance\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic GeoDistanceAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tJsonElement ranges = item.get(\"ranges\");\n\t\tif (ranges != null) {\n\t\t\tAggsBukcetInfo aggsBukcetInfo = new AggsBukcetInfo();\n\t\t\t\n\t\t\tJsonArray geoJsonRanges = ranges.getAsJsonArray();\n\t\t\tint size = geoJsonRanges.size();\n\t\t\taggsBukcetInfo.setBucketNumber(size);\n\t\t\taggsBukcetInfo.setLastBucketNumber(size);\n\t\t\taggsBukcetInfo.setMemUsed((long)size * QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\t\t\n\t\t\treturn aggsBukcetInfo;\n\t\t} else {\n\t\t\treturn AggsBukcetInfo.createSingleBucket();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/GeoHashGridAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"geoHashGridAggs\")\npublic class GeoHashGridAggs extends BucketAggsType {\n\tprivate String name = \"geohash_grid\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic GeoHashGridAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\treturn AggsBukcetInfo.createSingleBucket();\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/GlobalAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"globalAggs\")\npublic class GlobalAggs extends BucketAggsType {\n\tprivate String name = \"global\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic GlobalAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\treturn AggsBukcetInfo.createSingleBucket();\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/HistogramAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"histogramAggs\")\npublic class HistogramAggs extends BucketAggsType {\n\tprivate String name = \"histogram\";\n\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic HistogramAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tJsonElement field = item.get(\"field\");\n\t\tif (field == null) {\n\t\t\treturn AggsBukcetInfo.createSingleBucket();\n\t\t}\n\n\t\tString strField = field.getAsString();\n\n\t\tJsonElement interval = item.get(\"interval\");\n\t\tif (interval == null) {\n\t\t\treturn AggsBukcetInfo.createSingleBucket();\n\t\t}\n\n\t\tint iInterval = interval.getAsInt();\n\n\t\tif (iInterval <= 0) {\n\t\t\treturn AggsBukcetInfo.createSingleBucket();\n\t\t}\n\t\t\n\t\tif (mergedMappings.containsKey(strField)) {\n\t\t\tFieldInfo fieldInfo = mergedMappings.get(strField);\n\t\t\tif (fieldInfo.getCardinality() > 0) {\n\t\t\t\tAggsBukcetInfo aggsBukcetInfo = new AggsBukcetInfo();\n\t\t\t\tint bucket = (int) Math.ceil((double)fieldInfo.getCardinality() / iInterval);\n\t\t\t\taggsBukcetInfo.setBucketNumber(bucket);\n\t\t\t\taggsBukcetInfo.setLastBucketNumber(bucket);\n\t\t\t\taggsBukcetInfo.setMemUsed((long)bucket * QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\t\t\t\n\t\t\t\treturn aggsBukcetInfo;\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn AggsBukcetInfo.createSingleBucket();\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/IpRangeAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"ipRangeAggs\")\npublic class IpRangeAggs extends BucketAggsType {\n\tprivate String name = \"ip_range\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\tpublic IpRangeAggs() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tJsonElement ranges = item.get(\"ranges\");\n\t\tif (ranges != null) {\n\t\t\tAggsBukcetInfo aggsBukcetInfo = new AggsBukcetInfo();\n\t\t\t\n\t\t\tJsonArray ipJsonRanges = ranges.getAsJsonArray();\n\t\t\tint size = ipJsonRanges.size();\n\t\t\taggsBukcetInfo.setLastBucketNumber(size);\n\t\t\taggsBukcetInfo.setBucketNumber(size);\n\t\t\taggsBukcetInfo.setMemUsed((long)size * QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\t\t\n\t\t\treturn aggsBukcetInfo;\n\t\t} else {\n\t\t\treturn AggsBukcetInfo.createSingleBucket();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/MetricsAggsType.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.enums.AggsTypeEnum;\n\npublic abstract class MetricsAggsType implements AggsType {\n\tprotected AggsTypeEnum type = AggsTypeEnum.METRICS;\n\n\t@Override\n\tpublic AggsTypeEnum getType() {\n\t\treturn type;\n\t}\n\n\tprotected MetricsAggsType() {\n\t\t// pass\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/MissingAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"missingAggs\")\n@NoArgsConstructor\npublic class MissingAggs extends BucketAggsType {\n\tprivate String name = \"missing\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\treturn AggsBukcetInfo.createSingleBucket();\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/NestedAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"nestedAggs\")\n@NoArgsConstructor\npublic class NestedAggs extends BucketAggsType {\n\tprivate String name = \"nested\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\treturn AggsBukcetInfo.createSingleBucket();\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/RangeAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n\n@Component(\"rangeAggs\")\n@NoArgsConstructor\npublic class RangeAggs extends BucketAggsType {\n\tprivate String name = \"range\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tJsonElement ranges = item.get(\"ranges\");\n\t\tif (ranges != null) {\n\t\t\tAggsBukcetInfo aggsBukcetInfo = new AggsBukcetInfo();\n\t\t\t\n\t\t\tJsonArray jsonRanges = ranges.getAsJsonArray();\n\t\t\tint size = jsonRanges.size();\n\t\t\taggsBukcetInfo.setBucketNumber(size);\n\t\t\taggsBukcetInfo.setLastBucketNumber(size);\n\t\t\taggsBukcetInfo.setMemUsed((long)size * QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\t\t\n\t\t\treturn aggsBukcetInfo;\n\t\t} else {\n\t\t\treturn AggsBukcetInfo.createSingleBucket();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/ReverseNestedAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"reverseNestedAggs\")\n@NoArgsConstructor\npublic class ReverseNestedAggs extends BucketAggsType {\n\tprivate String name = \"reverse_nested\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\treturn AggsBukcetInfo.createSingleBucket();\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/SamplerAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"samplerAggs\")\n@NoArgsConstructor\npublic class SamplerAggs extends BucketAggsType {\n\n\tprivate String name = \"sampler\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\treturn AggsBukcetInfo.createSingleBucket();\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/ScriptedMetricAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.exception.AggsParseException;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"scriptedMetricAggs\")\n@NoArgsConstructor\npublic class ScriptedMetricAggs extends MetricsAggsType {\n\n\tprivate String name = \"scripted_metric\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tthrow new AggsParseException(\"scripted_metric aggregation forbidden\");\n\t}\n}\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/SignificantTermsAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonObject;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"significantTermsAggs\")\n@NoArgsConstructor\npublic class SignificantTermsAggs extends BucketAggsType {\n\n\tprivate String name = \"significant_terms\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\t\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\treturn AggsBukcetInfo.createSingleBucket();\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/aggregations/TermsAggs.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.aggregations;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.AggsBukcetInfo;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport lombok.NoArgsConstructor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\n\n@Component(\"termsAggs\")\n@NoArgsConstructor\npublic class TermsAggs extends BucketAggsType {\n\n\tprivate String name = \"terms\";\n\t\n\t@Autowired\n\tprivate AggsTypes aggsTypes;\n\n\t@PostConstruct\n\tpublic void init() {\n\t\taggsTypes.putAggsType(name, this);\n\t}\n\n\t@Override\n\tpublic AggsBukcetInfo computeAggsType(JsonObject item, Map<String, FieldInfo> mergedMappings) {\n\t\tAggsBukcetInfo aggsBukcetInfo = new AggsBukcetInfo();\n\t\t\n\t\t// check field\n\t\tJsonElement field = item.get(\"field\");\n\t\tif (field != null) {\n\t\t\tString strField = field.getAsString();\n\t\t\tif (mergedMappings.containsKey(strField)) {\n\t\t\t\tFieldInfo fieldInfo = mergedMappings.get(strField);\n\t\t\t\t\n\t\t\t\tint bucketNumber = Math.max(1, fieldInfo.getCardinality());\n\t\t\t\taggsBukcetInfo.setBucketNumber(bucketNumber);\n\t\t\t\t\n\t\t\t\taggsBukcetInfo.setMemUsed((long)bucketNumber * QueryConsts.AGGS_BUCKET_MEM_UNIT);\n\t\t\t}\n\t\t}\n\t\t\n\t\tJsonElement size = item.get(\"size\");\n\t\tif (size != null) {\n\t\t\tint iSize = size.getAsInt();\n\t\t\tif (iSize > 0) {\n\t\t\t\taggsBukcetInfo.setLastBucketNumber(Math.min(iSize, aggsBukcetInfo.getBucketNumber()));\n\t\t\t} else {\n\t\t\t\taggsBukcetInfo.setLastBucketNumber(aggsBukcetInfo.getBucketNumber());\n\t\t\t}\n\t\t\t\n\t\t} else {\n\t\t\taggsBukcetInfo.setLastBucketNumber(Math.min(10, aggsBukcetInfo.getBucketNumber()));\n\t\t}\n\n\t\treturn aggsBukcetInfo;\n\t}\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/impl/DslAggsAnalyzerServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.impl;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.enums.AggsTypeEnum;\nimport com.didi.arius.gateway.common.exception.AggsParseException;\nimport com.didi.arius.gateway.common.metadata.*;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.common.utils.Regex;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.service.MetricsService;\nimport com.didi.arius.gateway.core.service.arius.DslTemplateService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport com.didi.arius.gateway.core.service.dsl.DslAggsAnalyzerService;\nimport com.didi.arius.gateway.core.service.dsl.aggregations.AggsType;\nimport com.didi.arius.gateway.core.service.dsl.aggregations.AggsTypes;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport com.google.gson.JsonParseException;\nimport com.google.gson.JsonParser;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author fitz\n * @date 2021/5/25 7:26 下午\n */\n@Service\npublic class DslAggsAnalyzerServiceImpl implements DslAggsAnalyzerService {\n    protected static final ILog logger = LogFactory.getLog(DslAggsAnalyzerServiceImpl.class);\n    protected static final Logger statLogger = LoggerFactory.getLogger(QueryConsts.STAT_LOGGER);\n\n    @Autowired\n    private MetricsService metricsService;\n\n    @Autowired\n    private DslTemplateService dslTemplateService;\n\n    @Autowired\n    private IndexTemplateService templateService;\n\n    @Autowired\n    private QueryConfig queryConfig;\n\n    @Autowired\n    private AggsTypes aggsTypes;\n\n    public DslAggsAnalyzerServiceImpl() {\n        // pass\n    }\n\n    @Override\n    public boolean analyze(BaseContext baseContext, BytesReference source, String[] indices, String cluster) {\n        try {\n            // nothing to parse...\n            if (source == null || source.length() == 0) {\n                return true;\n            }\n\n            String strSource = XContentHelper.convertToJson(source, false);\n            JsonParser parser = new JsonParser();\n            JsonObject jsonSource = parser.parse(strSource).getAsJsonObject();\n\n            JsonObject aggsObject = getAggsObject(jsonSource);\n\n            if (aggsObject == null) {\n                // no aggs field\n                return true;\n            }\n\n            metricsService.incrQueryAggs(baseContext.getAppid());\n\n            Map<String, FieldInfo> mergedMappings = mergeMappings(indices, cluster);\n\n            if (mergedMappings.size() == 0) {\n                // no mapping fields\n                return true;\n            }\n\n            AggsAnalyzerContext context = new AggsAnalyzerContext();\n            AggsBukcetInfo aggsBukcetInfo;\n            aggsBukcetInfo = getAggsBukcetInfo(aggsObject, mergedMappings, context);\n\n            statLogger.info(QueryConsts.DLFLAG_PREFIX + \"aggs_detail||requestId={}||aggsLevel={}||aggsBukcetInfo={}\", baseContext.getRequestId(), context.getMaxLevel(), aggsBukcetInfo);\n\n            if (aggsBukcetInfo.getMemUsed() > queryConfig.getMaxAggsMemUsed()) {\n                throw new AggsParseException(String.format(\"aggregation buckets memory too large(%d) > %d\", aggsBukcetInfo.getMemUsed() , queryConfig.getMaxAggsMemUsed()));\n            }\n\n            if (baseContext.getDslTemplateKey() != null) {\n                DSLTemplate dslTemplate = dslTemplateService.getDSLTemplate(baseContext.getDslTemplateKey());\n                if (dslTemplate != null && dslTemplate.getTotalShardsAvg() > 0) {\n                    // 存在历史模板，则根据历史查询情况计算内存开销\n                    int bucket = (int) Math.min(aggsBukcetInfo.getBucketNumber(), dslTemplate.getTotalHitsAvg() / dslTemplate.getTotalShardsAvg());\n                    if (bucket > queryConfig.getMaxAggsBuckets()) {\n                        throw new AggsParseException(String.format(\"aggregation buckets number too large(%d) > %d\", bucket , queryConfig.getMaxAggsBuckets()));\n                    }\n\n                    if (bucket * dslTemplate.getTotalShardsAvg() > queryConfig.getMaxAggsBuckets() * QueryConsts.AGGS_DEFAULT_SHARD_NUMBER) {\n                        throw new AggsParseException(String.format(\"aggregation total buckets number too large(%d) > %d\", (int)(bucket * dslTemplate.getTotalShardsAvg()) , queryConfig.getMaxAggsBuckets() * QueryConsts.AGGS_DEFAULT_SHARD_NUMBER));\n                    }\n\n                    if (aggsBukcetInfo.getMemUsed() * dslTemplate.getTotalShardsAvg() > queryConfig.getMaxAggsMemUsed() * QueryConsts.AGGS_DEFAULT_SHARD_NUMBER) {\n                        throw new AggsParseException(String.format(\"aggregation total buckets memory too large(%d) > %d\", (long)(aggsBukcetInfo.getMemUsed() * dslTemplate.getTotalShardsAvg()) , queryConfig.getMaxAggsMemUsed() * QueryConsts.AGGS_DEFAULT_SHARD_NUMBER));\n                    }\n\n                    return true;\n                }\n            }\n\n            //不存在历史模板，则直接计算内存开销\n            if (aggsBukcetInfo.getBucketNumber() > queryConfig.getMaxAggsBuckets()) {\n                throw new AggsParseException(String.format(\"aggregation buckets number too large(%d) > %d\", aggsBukcetInfo.getBucketNumber() , queryConfig.getMaxAggsBuckets()));\n            }\n\n        } catch (IOException e) {\n            logger.warn(\"analyzeAggs convertToJson exception, {}\", Convert.logExceptionStack(e));\n        } catch (JsonParseException e) {\n            logger.warn(\"analyzeAggs json parse exception, {}\", Convert.logExceptionStack(e));\n        }\n\n        return true;\n    }\n\n    private AggsBukcetInfo getAggsBukcetInfo(JsonObject aggsObject, Map<String, FieldInfo> mergedMappings, AggsAnalyzerContext context) {\n        AggsBukcetInfo aggsBukcetInfo;\n        try {\n            aggsBukcetInfo = checkAggs(aggsObject, 0, mergedMappings, context);\n        } catch (Exception e) {\n            logger.warn(\"analyzeAggs unexcept exception, {}\", Convert.logExceptionStack(e));\n            aggsBukcetInfo = AggsBukcetInfo.createSingleBucket();\n        }\n        return aggsBukcetInfo;\n    }\n\n    @Override\n    public boolean analyzeAggs(BaseContext baseContext, BytesReference source, String[] indices) {\n        try {\n            if (baseContext.getAppDetail().isAggrAnalyzeEnable()) {\n                return analyze(baseContext, source, indices, baseContext.getCluster());\n            } else {\n                return true;\n            }\n        } catch (Exception e) {\n            if (e instanceof AggsParseException) {\n                logger.warn(QueryConsts.DLFLAG_PREFIX + \"anaylizeAggs_forbidden||appid={}||requestId={}||dslTemplateKey={}\", baseContext.getAppid(), baseContext.getRequestId(), baseContext.getDslTemplateKey());\n            }\n\n            if (!queryConfig.isCheckForbidden()) {\n                throw e;\n            } else {\n                return true;\n            }\n        }\n    }\n\n    @Override\n    public AggsBukcetInfo checkAggs(JsonObject aggsObject, int level, Map<String, FieldInfo> mergedMappings, AggsAnalyzerContext context) {\n        AggsBukcetInfo totalAggsBukcetInfo = new AggsBukcetInfo();\n\n        if (level > context.getMaxLevel()) {\n            context.setMaxLevel(level);\n        }\n\n        for (Map.Entry<String, JsonElement> entry : aggsObject.entrySet()) {\n            JsonObject aggsItem = entry.getValue().getAsJsonObject();\n            AggsBukcetInfo currentAggsBukcetInfo = checkBucketAggs(aggsItem, level+1, mergedMappings, context);\n\n            if (currentAggsBukcetInfo.isLastBucket()) {\n                totalAggsBukcetInfo.setBucketNumber(totalAggsBukcetInfo.getBucketNumber() + currentAggsBukcetInfo.getLastBucketNumber());\n            } else {\n                totalAggsBukcetInfo.setBucketNumber(totalAggsBukcetInfo.getBucketNumber() + currentAggsBukcetInfo.getBucketNumber());\n            }\n\n            totalAggsBukcetInfo.setMemUsed(totalAggsBukcetInfo.getMemUsed() + currentAggsBukcetInfo.getMemUsed());\n        }\n\n        return totalAggsBukcetInfo;\n    }\n\n    @Override\n    public Map<String, FieldInfo> mergeMappings(String[] indices, String cluster) {\n        Map<String, FieldInfo> mergedMappings = new HashMap<>();\n        Map<String, Map<String, TemplateInfo>> templateAliasesMap    = templateService.getTemplateAliasMap();\n        Map<String, Map<String, TemplateInfo>> templateExpressionMap = templateService.getTemplateExpressionMap();\n\n        Map<String, TemplateInfo> aliasMap = templateAliasesMap.get(cluster);\n        Map<String, TemplateInfo> expressionMap = templateExpressionMap.get(cluster);\n        if (aliasMap == null) {\n            logger.warn(\"getLargeFields alias map is null, cluster={}\", cluster);\n        } else if (expressionMap == null) {\n            logger.warn(\"getLargeFields expression map is null, cluster={}\", cluster);\n        } else {\n            for (Map.Entry<String, TemplateInfo> entry : aliasMap.entrySet()) {\n                String expression = entry.getKey();\n                for (String index : indices) {\n                    if (Regex.indexContainExp(index, expression)) {\n                        TemplateInfo templateInfo = entry.getValue();\n                        dealTemplateMappings(mergedMappings, templateInfo);\n                        break;\n                    }\n                }\n            }\n\n            for (Map.Entry<String, TemplateInfo> entry : expressionMap.entrySet()) {\n                String expression = entry.getKey();\n                for (String index : indices) {\n                    if (Regex.indexContainExp(index, expression)) {\n                        TemplateInfo templateInfo = entry.getValue();\n                        dealTemplateMappings(mergedMappings, templateInfo);\n                        break;\n                    }\n                }\n            }\n        }\n\n        return mergedMappings;\n    }\n\n\n\n    /************************************************************** private method **************************************************************/\n    private JsonObject getAggsObject(JsonObject parent) {\n        JsonElement aggs = parent.get(\"aggs\");\n        if (aggs == null) {\n            aggs = parent.get(\"aggregations\");\n        }\n\n        if (aggs == null) {\n            return null;\n        }\n\n        return aggs.getAsJsonObject();\n    }\n\n    private AggsBukcetInfo checkBucketAggs(JsonObject aggsItem, int level, Map<String, FieldInfo> mergedMappings, AggsAnalyzerContext context) {\n        if (level > context.getMaxLevel()) {\n            context.setMaxLevel(level);\n        }\n\n        AggsBukcetInfo currentAggsBukcetInfo = computeAggsType(aggsItem, mergedMappings);\n\n        JsonObject subItem = getAggsObject(aggsItem);\n        if (subItem != null) {\n            AggsBukcetInfo totalAggsBukcetInfo = new AggsBukcetInfo();\n\n            List<AggsBukcetInfo> subBukcetInfos = checktSubAggs(subItem, level, mergedMappings, context);\n\n            for (AggsBukcetInfo aggsBukcetInfo : subBukcetInfos) {\n                if (aggsBukcetInfo.getBucketType() == AggsTypeEnum.BUCKET) {\n                    totalAggsBukcetInfo.setLastBucket(false);\n\n                    // 如果是该bucket聚合关键字是最后一个bucket，则用来计算的bucket是lastBucketNumber，否则计算的是bucketNumber\n                    if (aggsBukcetInfo.isLastBucket()) {\n                        totalAggsBukcetInfo.setBucketNumber(totalAggsBukcetInfo.getBucketNumber() + currentAggsBukcetInfo.getBucketNumber() * aggsBukcetInfo.getLastBucketNumber());\n                        totalAggsBukcetInfo.setMemUsed(totalAggsBukcetInfo.getMemUsed() + currentAggsBukcetInfo.getBucketNumber() * aggsBukcetInfo.getMemUsed());\n                    } else {\n                        totalAggsBukcetInfo.setBucketNumber(totalAggsBukcetInfo.getBucketNumber() + currentAggsBukcetInfo.getBucketNumber() * aggsBukcetInfo.getBucketNumber());\n                        totalAggsBukcetInfo.setMemUsed(totalAggsBukcetInfo.getMemUsed() + currentAggsBukcetInfo.getBucketNumber() * aggsBukcetInfo.getMemUsed());\n                    }\n                } else {\n                    totalAggsBukcetInfo.setBucketNumber(totalAggsBukcetInfo.getBucketNumber() + currentAggsBukcetInfo.getBucketNumber());\n                    totalAggsBukcetInfo.setLastBucketNumber(totalAggsBukcetInfo.getLastBucketNumber() + currentAggsBukcetInfo.getLastBucketNumber());\n                    totalAggsBukcetInfo.setMemUsed(totalAggsBukcetInfo.getMemUsed() + currentAggsBukcetInfo.getBucketNumber() * aggsBukcetInfo.getMemUsed());\n                }\n            }\n\n            return totalAggsBukcetInfo;\n        } else {\n            return currentAggsBukcetInfo;\n        }\n    }\n\n    private AggsBukcetInfo computeAggsType(JsonObject aggsItem, Map<String, FieldInfo> mergedMappings) {\n        for (Map.Entry<String, JsonElement> entry : aggsItem.entrySet()) {\n            String field = entry.getKey();\n            switch (field) {\n                case \"meta\":\n                case \"aggregations\":\n                case \"aggs\":\n                    break;\n                default:\n                    AggsType aggsType = aggsTypes.getAggsType(field);\n                    if (aggsType != null) {\n                        JsonObject item = entry.getValue().getAsJsonObject();\n                        return aggsType.computeAggsType(item, mergedMappings);\n                    } else {\n                        logger.info(\"aggs_type_not_support||field={}||content={}\", field, aggsItem);\n                        return AggsBukcetInfo.createSingleMetrics();\n                    }\n            }\n        }\n\n        return AggsBukcetInfo.createSingleBucket();\n    }\n\n    private List<AggsBukcetInfo> checktSubAggs(JsonObject aggsObject, int level, Map<String, FieldInfo> mergedMappings, AggsAnalyzerContext context) {\n        List<AggsBukcetInfo> aggsBukcetInfos = new ArrayList<>();\n        for (Map.Entry<String, JsonElement> entry : aggsObject.entrySet()) {\n            JsonObject aggsItem = entry.getValue().getAsJsonObject();\n\n            AggsBukcetInfo aggsBukcetInfo = checkBucketAggs(aggsItem, level+1, mergedMappings, context);\n            aggsBukcetInfos.add(aggsBukcetInfo);\n        }\n\n        return aggsBukcetInfos;\n    }\n\n    private void dealTemplateMappings(Map<String, FieldInfo> mergedMappings, TemplateInfo templateInfo) {\n        Map<String, FieldInfo> mappings = templateInfo.getMappings();\n        for (Map.Entry<String, FieldInfo> inEntry : mappings.entrySet()) {\n            if (mergedMappings.containsKey(inEntry.getKey())) {\n                FieldInfo oldFieldInfo = mergedMappings.get(inEntry.getKey());\n                FieldInfo newFieldInfo = inEntry.getValue();\n                mergedMappings.put(inEntry.getKey(), Convert.fieldInfoMerge(oldFieldInfo, newFieldInfo));\n            } else {\n                mergedMappings.put(inEntry.getKey(), inEntry.getValue());\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/impl/DslAuditServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.impl;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.exception.DslForbiddenException;\nimport com.didi.arius.gateway.common.exception.DslRateLimitException;\nimport com.didi.arius.gateway.common.metadata.BaseContext;\nimport com.didi.arius.gateway.common.metadata.DSLTemplate;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.service.arius.DslTemplateService;\nimport com.didi.arius.gateway.core.service.dsl.DslAuditService;\nimport com.didiglobal.knowframework.dsl.parse.DslExtractionUtilV2;\nimport com.didiglobal.knowframework.dsl.parse.bean.ExtractResult;\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.NoArgsConstructor;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * @author fitz\n * @date 2021/5/25 7:40 下午\n */\n@Service\n@NoArgsConstructor\npublic class DslAuditServiceImpl implements DslAuditService {\n    protected static final ILog logger = LogFactory.getLog(DslAuditServiceImpl.class);\n\n    @Autowired\n    private DslTemplateService dslTemplateService;\n\n    @Autowired\n    private QueryConfig queryConfig;\n\n    @Override\n    public String auditDSL(BaseContext baseContext, BytesReference source, String[] indices) {\n        String strSource = \"\";\n\n        try {\n            if (source != null && source.length() > 0) {\n                strSource = XContentHelper.convertToJson(source, false);\n            }\n\n            return audit(baseContext, strSource);\n        } catch (IOException e) {\n            logger.error(\"dsl_audit_unexpect_error||appid={}||requestId={}||source={}||exception={}\", baseContext.getAppid(),\n                    baseContext.getRequestId(), source, Convert.logExceptionStack(e));\n            return \"\";\n        }\n    }\n\n    @Override\n    public String auditSQL(BaseContext baseContext, String sql, String[] indices) {\n        if (sql == null || sql.length() == 0) {\n            return \"\";\n        }\n\n        return audit(baseContext, sql);\n    }\n\n    /************************************************************** private method **************************************************************/\n    private String audit(BaseContext baseContext, String source) {\n        ExtractResult extractResult = DslExtractionUtilV2.extractDsl(source);\n        if (\"FAILED\".equals(extractResult.getDslTemplate())) {\n            logger.error(\"extractDsl_failed||projectId={}||appid={}||requestId={}||source={}\",\n                    baseContext.getProjectId(), baseContext.getAppid(), baseContext.getRequestId(), source);\n            return \"\";\n        }\n\n        String dslKey = baseContext.getProjectId() + \"_\" + extractResult.getDslTemplateMd5();\n        baseContext.setDslTemplateKey(dslKey);\n\n        if (baseContext.isDetailLog()) {\n            JoinLogContext joinLogContext = baseContext.getJoinLogContext();\n            joinLogContext.setDslTemplate(extractResult.getDslTemplate());\n            joinLogContext.setSearchType(extractResult.getSearchType());\n            joinLogContext.setDsl(extractResult.getDsl());\n            joinLogContext.setDslType(extractResult.getDslType());\n            joinLogContext.setDslTag(extractResult.getTags());\n            joinLogContext.setDslTemplateMd5(extractResult.getDslTemplateMd5());\n            joinLogContext.setSelectFields(extractResult.getSelectFields());\n            joinLogContext.setWhereFields(extractResult.getWhereFields());\n            joinLogContext.setGroupByFields(extractResult.getGroupByFields());\n            joinLogContext.setSortByFields(extractResult.getSortByFields());\n        }\n\n        DSLTemplate dslTemplate = dslTemplateService.getDSLTemplate(dslKey);\n        if (dslTemplate == null) {\n            dslTemplate = dslTemplateService.getNewDSLTemplate(dslKey);\n            if (dslTemplate == null) {\n                synchronized (this) {\n                    dslTemplate = new DSLTemplate(queryConfig.getDslQPSLimit(), queryConfig.getDslQPSLimit(), false);\n                    dslTemplateService.putNewDSLTemplate(dslKey, dslTemplate);\n                }\n            }\n        }\n\n        // 是否禁止访问\n        if (dslTemplate.isQueryForbidden()) {\n            logger.warn(\"dsl_forbidden||appid={}||requestId={}||dsl={}||dslTemplate={}\", baseContext.getAppid(), baseContext.getRequestId(),\n                    extractResult.getDslTemplateMd5(), dslTemplate);\n            throw new DslForbiddenException(\"dangerous query dsl forbidden, dsl=\" + extractResult.getDslTemplateMd5());\n        }\n\n        // 限流校验\n        if (!dslTemplate.getRateLimiter().tryAcquire(1, QueryConsts.QUERY_DSL_LIMIT_WAIT, TimeUnit.MILLISECONDS)) {\n            logger.warn(\"dsl_rateLimit||appid={}||requestId={}||dsl={}||dslTemplate={}\", baseContext.getAppid(), baseContext.getRequestId(),\n                    extractResult.getDslTemplateMd5(), dslTemplate);\n            throw new DslRateLimitException(\"query dsl flow limit, please wait and try again!, dsl=\" + extractResult.getDslTemplateMd5());\n        }\n\n        return extractResult.getDslTemplateMd5();\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/impl/DslRewriterServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.impl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.*;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.common.metadata.BaseContext;\nimport com.didi.arius.gateway.core.service.dsl.transform.RequestVisitorV2;\nimport com.didi.arius.gateway.core.service.dsl.transform.RequestVisitorV6;\nimport com.didi.arius.gateway.core.service.dsl.transform.RequestVisitorV7;\nimport com.didi.arius.gateway.core.service.dsl.DslRewriterService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.DslNode;\nimport com.didiglobal.knowframework.dsl.parse.dsl.parser.DslParser;\nimport com.didiglobal.knowframework.dsl.parse.dsl.visitor.basic.OutputVisitor;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.NoArgsConstructor;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * @author fitz\n * @date 2021/5/25 7:46 下午\n */\n@Service\n@NoArgsConstructor\npublic class DslRewriterServiceImpl implements DslRewriterService {\n    private static final ILog logger = LogFactory.getLog(DslRewriterServiceImpl.class);\n    protected static final Logger statLogger = LoggerFactory.getLogger(QueryConsts.STAT_LOGGER);\n    public static final String QUERY = \"query\";\n    public static final String POST_FILTER = \"post_filter\";\n    public static final String AGG = \"aggregations\";\n    public static final String ORDER = \"order\";\n    public static final String TERM = \"_term\";\n\n    private static final String TYPE_SPLIT = \"#\";\n\n    @Autowired\n    private IndexTemplateService indexTemplateService;\n\n    @Override\n    public BytesReference rewriteRequest(BaseContext context, String esVersion, JSONObject source) throws Exception {\n        if (statLogger.isTraceEnabled()) {\n            statLogger.trace(\"_arius_aggs_dSLRewriter||requestId={}||esVersion={}||userDsl={}\", context.getRequestId(), esVersion, source.toJSONString());\n        }\n\n        dealFirstLevel(source);\n\n        DslNode node = DslParser.parse(source);\n\n        OutputVisitor transformVisitor;\n        if (esVersion.startsWith(QueryConsts.ES_VERSION_2_PREFIX)) {\n            transformVisitor = new RequestVisitorV2();\n        } else if (esVersion.startsWith(QueryConsts.ES_VERSION_6_PREFIX)) {\n            transformVisitor = new RequestVisitorV6();\n        } else {\n            transformVisitor = new RequestVisitorV7();\n        }\n\n        // dsl转换\n        node.accept(transformVisitor);\n\n        // typed_key处理\n        if (esVersion.startsWith(QueryConsts.ES_VERSION_2_PREFIX)) {\n            doTypedKey(context, (JSONObject) transformVisitor.ret);\n        }\n\n        String formatDSL = transformVisitor.ret.toString();\n\n        if (statLogger.isTraceEnabled()) {\n            statLogger.trace(\"_arius_aggs_dSLRewriter||requestId={}||esVersion={}||reWriterDsl={}\", context.getRequestId(), esVersion, formatDSL);\n        }\n\n        return new BytesArray(formatDSL);\n    }\n\n    @Override\n    public void doTypedKey(BaseContext context, JSONObject source) {\n        if (!context.isTypedKeys()) {\n            return ;\n        }\n\n        JSONObject aggs = getAggsObject(source);\n        if (aggs == null) {\n            return ;\n        }\n\n        IndexTemplate indexTemplate = context.getIndexTemplate();\n        Map<String, FieldInfo> fieldInfoMap = new HashMap<>();\n        if (indexTemplate != null) {\n            try {\n                Map<String, Map<String, TemplateInfo>> templateExpressionMap = indexTemplateService.getTemplateExpressionMap();\n                Map<String, TemplateInfo> expressionMap = templateExpressionMap.get(indexTemplate.getMasterInfo().getCluster());\n                TemplateInfo templateInfo = Objects.requireNonNull(expressionMap).get(indexTemplate.getExpression());\n                fieldInfoMap = Objects.requireNonNull(templateInfo).getMappings();\n            } catch (Exception e) {\n                logger.warn(\"get mappings exception\", e);\n            }\n        }\n\n\n        AggsPath root = new AggsPath();\n        buildAggsPath(root, aggs, fieldInfoMap);\n        JSONObject newAggs = buildTypedKey(root, aggs);\n        putAggsObject(source, newAggs);\n    }\n\n    @Override\n    public BytesReference rewriteRequest(BaseContext context, String esVersion, BytesReference source) {\n        JSONObject jsonObject;\n        try {\n            if (source == null || source.length() <= 0) {\n                return source;\n            }\n\n            String strSource = XContentHelper.convertToJson(source, false);\n\n            jsonObject = JSON.parseObject(strSource);\n\n            return rewriteRequest(context, esVersion, jsonObject);\n        } catch (Exception e) {\n            logger.error(\"unexcept_error||type=rewriteRequest||e={}\", Convert.logExceptionStack(e));\n            return source;\n        }\n    }\n\n    /************************************************************** private method **************************************************************/\n    private void dealFirstLevel(JSONObject source) {\n        //第一层兼容性处理\n        if (source.containsKey(\"indicesBoost\") && !source.containsKey(\"indices_boost\")) {\n            Object obj = source.remove(\"indicesBoost\");\n            source.put(\"indices_boost\", obj);\n        }\n\n        if (source.containsKey(\"queryBinary\") && !source.containsKey(QUERY)) {\n            Object obj = source.remove(\"queryBinary\");\n            source.put(QUERY, obj);\n        }\n\n        if (source.containsKey(\"query_binary\") && !source.containsKey(QUERY)) {\n            Object obj = source.remove(\"query_binary\");\n            source.put(QUERY, obj);\n        }\n\n        if (source.containsKey(\"filter\") && !source.containsKey(POST_FILTER)) {\n            Object obj = source.remove(\"filter\");\n            source.put(POST_FILTER, obj);\n        }\n\n        if (source.containsKey(\"postFilter\") && !source.containsKey(POST_FILTER)) {\n            Object obj = source.remove(\"postFilter\");\n            source.put(POST_FILTER, obj);\n        }\n\n        if (source.containsKey(\"trackScores\") && !source.containsKey(\"track_scores\")) {\n            Object obj = source.remove(\"trackScores\");\n            source.put(\"track_scores\", obj);\n        }\n\n        if (source.containsKey(\"minScore\") && !source.containsKey(\"min_score\")) {\n            Object obj = source.remove(\"min_score\");\n            source.put(\"minScore\", obj);\n        }\n    }\n\n    /**\n     * 得到aggs的路径，路径上记录了aggs的名称，类型，aggs的字段，用作之后设置typed_key，\n     * 以及将order，bucket_path进行相应的设置\n     * @param parent 父path\n     * @param aggs 聚合对象\n     */\n    private void buildAggsPath(AggsPath parent, JSONObject aggs, Map<String, FieldInfo> fieldInfoMap) {\n        for (String key : aggs.keySet()) {\n            AggsPath path = new AggsPath();\n            path.setAggsName(key);\n\n            JSONObject aggsItem = aggs.getJSONObject(key);\n            for (String inKey : aggsItem.keySet()) {\n                switch (inKey) {\n                    case \"meta\":\n                        break;\n                    case AGG:\n                    case \"aggs\":\n                        buildAggsPath(path, aggsItem.getJSONObject(inKey), fieldInfoMap);\n                        break;\n                    default:\n                        buildField(path, inKey, aggsItem, fieldInfoMap);\n                }\n            }\n\n            parent.addItems(key, path);\n        }\n    }\n\n    /**\n     * 构建typed_key\n     * @param path\n     * @param type\n     * @param aggsItem\n     * @param fieldInfoMap\n     */\n    private void buildField(AggsPath path, String type, JSONObject aggsItem, Map<String, FieldInfo> fieldInfoMap) {\n        JSONObject item = aggsItem.getJSONObject(type);\n        switch (type.toLowerCase()) {\n            case \"significant_terms\" :\n                path.setAggsTypedKey(\"sigsterms\");\n                break;\n            case \"ranges\" :\n                break;\n            case \"terms\" :\n                path.setAggsTypedKey(\"sterms\");\n                if (item.containsKey(\"field\")) {\n                    String field = item.getString(\"field\");\n                    FieldInfo fieldInfo = fieldInfoMap.get(field);\n                    if (fieldInfo != null) {\n                        switch (fieldInfo.getType().toLowerCase()) {\n                            case \"double\" :\n                            case \"float\":\n                            case \"half_float\":\n                            case \"scaled_float\":\n                                path.setAggsTypedKey(\"dterms\");\n                                break;\n                            case \"long\" :\n                            case \"integer\":\n                            case \"short\":\n                                path.setAggsTypedKey(\"lterms\");\n                                break;\n                            default:\n                        }\n                    }\n                }\n                break;\n            case \"avg_bucket\" :\n            case \"max_bucket\":\n            case \"min_bucket\":\n            case \"sum_bucket\":\n                path.setAggsTypedKey(\"simple_value\");\n                break;\n            case \"percentile_ranks\" :\n                if (item.containsKey(\"hdr\")) {\n                    path.setAggsTypedKey(\"hdr_percentile_ranks\");\n                } else {\n                    path.setAggsTypedKey(\"tdigest_percentile_ranks\");\n                }\n                break;\n            case \"percentiles\" :\n                path.setAggsTypedKey(\"tdigest_percentiles\");\n                if (item.containsKey(\"hdr\")) {\n                    path.setAggsTypedKey(\"hdr_percentiles\");\n                }\n                break;\n            default:\n                path.setAggsTypedKey(type);\n                break;\n        }\n\n    }\n\n    private JSONObject buildTypedKey(AggsPath parent, JSONObject aggs) {\n        JSONObject newAggs = new JSONObject();\n        Iterator<Map.Entry<String, Object>> iter = aggs.entrySet().iterator();\n        while (iter.hasNext()) {\n            Map.Entry<String, Object> entry = iter.next();\n            String key = entry.getKey();\n            JSONObject aggsItem = (JSONObject) entry.getValue();\n            JSONObject newAggsItem = new JSONObject();\n\n            AggsPath path = parent.getItem(key);\n\n            for (Map.Entry<String,Object> aggEntry : aggsItem.entrySet()) {\n                String inKey = aggEntry.getKey();\n                switch (inKey) {\n                    case \"meta\":\n                        newAggsItem.put(inKey, aggsItem.get(inKey));\n                        break;\n                    case AGG:\n                    case \"aggs\":\n                        JSONObject newItem = buildTypedKey(path, aggsItem.getJSONObject(inKey));\n                        newAggsItem.put(inKey, newItem);\n                        break;\n                    default:\n                        JSONObject aggsType = aggsItem.getJSONObject(inKey);\n                        if (aggsType.containsKey(ORDER) && inKey.equals(\"terms\")) {\n                            if (aggsType.get(ORDER) instanceof JSONObject) {\n                                JSONObject order = aggsType.getJSONObject(ORDER);\n                                JSONObject newOrder = dealOrder(path, order);\n                                aggsType.put(ORDER, newOrder);\n                            } else if (aggsType.get(ORDER) instanceof JSONArray) {\n                                JSONArray newOrder = new JSONArray();\n                                for (Object o : (JSONArray) aggsType.get(ORDER)) {\n                                    JSONObject order = (JSONObject) o;\n                                    newOrder.add(dealOrder(path, order));\n                                }\n                                aggsType.put(ORDER, newOrder);\n                            }\n                        }\n                        newAggsItem.put(inKey, aggsType);\n                        break;\n                }\n            }\n\n            newAggs.put(path.getAggsTypedKey() + TYPE_SPLIT + key, newAggsItem);\n        }\n\n        return newAggs;\n    }\n\n    private JSONObject dealOrder(AggsPath path, JSONObject order) {\n        JSONObject newOrder = new JSONObject();\n        Iterator<Map.Entry<String, Object>> iter = order.entrySet().iterator();\n        while (iter.hasNext()) {\n            Map.Entry<String, Object> entryOrder = iter.next();\n            String key = entryOrder.getKey();\n            Object value = entryOrder.getValue();\n\n            if (key.equalsIgnoreCase(\"_key\")) {\n                newOrder.put(TERM, value);\n            } else if (key.equalsIgnoreCase(\"_count\")) {\n                newOrder.put(\"_count\", value);\n            } else if (key.equalsIgnoreCase(TERM)) {\n                newOrder.put(TERM, value);\n            } else {\n                String[] keys = key.split(\">\");\n                int i = 0;\n                StringBuilder builder = new StringBuilder();\n                while (i < keys.length) {\n                    String item = keys[i];\n                    boolean find = false;\n                    AggsPath aggsPath = null;\n                    if (path.getItems() != null) {\n                        for (Map.Entry<String, AggsPath> entry : path.getItems().entrySet()) {\n                            if (entry.getKey().equals(item)) {\n                                find = true;\n                                aggsPath = entry.getValue();\n                                break;\n                            }\n                        }\n                    }\n\n                    if (!find) {\n                        builder = new StringBuilder(key);\n                        break;\n                    }\n\n                    builder.append(aggsPath.getAggsTypedKey());\n                    builder.append(TYPE_SPLIT);\n                    builder.append(item);\n\n                    if (i < keys.length - 1) {\n                        builder.append(\">\");\n                    }\n\n                    i++;\n                }\n                newOrder.put(builder.toString(), value);\n            }\n        }\n\n        return newOrder;\n    }\n\n    private JSONObject getAggsObject(JSONObject parent) {\n        Object aggs = parent.get(\"aggs\");\n        if (aggs == null) {\n            aggs = parent.get(AGG);\n        }\n\n        if (aggs == null) {\n            return null;\n        }\n\n        return (JSONObject) aggs;\n    }\n\n    private void putAggsObject(JSONObject source, JSONObject aggs) {\n        if (source.containsKey(\"aggs\")) {\n            source.put(\"aggs\", aggs);\n        } else {\n            source.put(AGG, aggs);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/transform/BaseRequestVisitor.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.transform;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.DslNode;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.aggr.AggrTerms;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.aggr.SignificantTerms;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.common.KeyWord;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.common.Node;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.common.key.KeyNode;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.common.logic.*;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.common.multi.NodeList;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.common.multi.NodeMap;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.common.script.Script;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.common.value.ObjectNode;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.query.*;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.root.Sort;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.root.Timeout;\nimport com.didiglobal.knowframework.dsl.parse.dsl.visitor.basic.OutputVisitor;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.lang3.StringUtils;\nimport java.util.Map;\n\npublic class BaseRequestVisitor extends OutputVisitor {\n\n    protected static final ILog logger = LogFactory.getLog(BaseRequestVisitor.class);\n\n    protected static final String TYPE = \"_type\";\n\n    protected static final String MATCH_ALL = \"match_all\";\n\n    protected static final String ORDER = \"order\";\n\n    protected static final String QUERY = \"query\";\n\n    protected static final String QUERY_STRING = \"query_string\";\n\n\n    /**\n     * match不再支持type，旧版本的三种type中，phrase改为match_phrase查询，\n     * phrase_prefix改为match_phrase_prefix查询\n     * @param node\n     */\n    @Override\n    public void visit(Match node) {\n        super.visit(node);\n\n        JSONObject obj = (JSONObject) this.ret;\n        for (Map.Entry<String,Object> entry : obj.entrySet()) {\n            Object value = entry.getValue();\n            String key = entry.getKey();\n            if (value instanceof JSONObject) {\n                Object type = ((JSONObject) value).get(\"type\");\n                ((JSONObject) value).remove(\"type\");\n                if (type != null) {\n                    if (type.equals(\"phrase\")) {\n                        node.setName(\"match_phrase\");\n                    } else if (type.equals(\"phrase_prefix\") || type.equals(\"phrasePrefix\")) {\n                        node.setName(\"match_phrase_prefix\");\n                    }\n\n                }\n\n                if (key.equals(TYPE)) {\n                    node.setName(MATCH_ALL);\n                    obj.clear();\n                    break;\n                }\n            }\n        }\n    }\n\n    /**\n     * 处理排序中兼容\n     *\n     * @param node\n     */\n    @Override\n    public void visit(Sort node) {\n        super.visit(node);\n\n        if (this.ret instanceof JSONArray) {\n            JSONArray arr = (JSONArray) this.ret;\n            for (int i = 0 ; i < arr.size(); ++i) {\n                Object obj = arr.get(i);\n                if (obj instanceof JSONObject) {\n                    JSONObject jObj = (JSONObject) obj;\n                    transformSortItem(jObj);\n                }\n            }\n        } else if (this.ret instanceof JSONObject) {\n            transformSortItem((JSONObject) this.ret);\n        }\n    }\n\n    private void transformSortItem(JSONObject sortItem) {\n        for (Map.Entry<String,Object> entry : sortItem.entrySet()) {\n            String key = entry.getKey();\n            if (key.equals(\"_geo_distance\") || key.equals(\"_geoDistance\")) {\n                continue;\n            }\n\n            Object sObj = sortItem.get(key);\n            if (sObj instanceof JSONObject) {\n                JSONObject iObj = (JSONObject) sObj;\n                if (iObj.containsKey(\"ignore_unmapped\")) {\n                    iObj.remove(\"ignore_unmapped\");\n                }\n\n                // 对排序字段没有指定排序方式时，在低版本中默认为降序，则添加desc\n                if (iObj.containsKey(ORDER) && StringUtils.isBlank(iObj.getString(ORDER))) {\n                    iObj.put(ORDER, \"desc\");\n                }\n            }\n\n            // _score字段排序时去掉unmapped_type\n            if (\"_score\".equals(key) && sObj instanceof JSONObject) {\n                JSONObject iObj = (JSONObject) sObj;\n                if (iObj.containsKey(\"unmapped_type\")) {\n                    iObj.remove(\"unmapped_type\");\n                }\n            }\n        }\n    }\n\n    /**\n     * 不再支持Filtered关键字，改成bool查询\n     * @param node\n     */\n    @Override\n    public void visit(Filtered node) {\n        super.visit(node);\n\n        JSONObject obj = (JSONObject) this.ret;\n        node.setName(\"bool\");\n\n\n        if (obj.containsKey(QUERY)) {\n            Object query = obj.remove(QUERY);\n            obj.put(\"must\", query);\n        } else if (obj.containsKey(QUERY_STRING)) {\n            Object queryString = obj.remove(QUERY_STRING);\n            JSONObject query = new JSONObject();\n            query.put(QUERY_STRING, queryString);\n            obj.put(\"must\", query);\n        }\n    }\n\n    /**\n     * 不再支持fields和fielddata_fields关键字，直接过滤\n     * @param node\n     */\n    @Override\n    public void visit(DslNode node) {\n        super.visit(node);\n        JSONObject obj = (JSONObject) this.ret;\n\n        if (obj.containsKey(\"fields\")) {\n            obj.remove(\"fields\");\n        }\n\n        if (obj.containsKey(\"fielddata_fields\")) {\n            obj.remove(\"fielddata_fields\");\n        }\n    }\n\n    private static final int DEFAULT_TERMS_SIZE = 1000;\n\n    /**\n     * aggs的terms不再支持size=0，改成默认1000\n     * @param node\n     */\n    @Override\n    public void visit(AggrTerms node) {\n        super.visit(node);\n\n        JSONObject obj = (JSONObject) this.ret;\n        if (obj.containsKey(\"size\")) {\n            int size = obj.getIntValue(\"size\");\n            if (size == 0) {\n                obj.put(\"size\", DEFAULT_TERMS_SIZE);\n            }\n        }\n    }\n\n    /**\n     * aggs的SignificantTerms不再支持size=0，改成默认1000\n     *\n     * @param node\n     */\n    @Override\n    public void visit(SignificantTerms node) {\n        super.visit(node);\n\n        JSONObject obj = (JSONObject) this.ret;\n        if (obj.containsKey(\"size\")) {\n            int size = obj.getIntValue(\"size\");\n            if (size == 0) {\n                obj.put(\"size\", DEFAULT_TERMS_SIZE);\n            }\n        }\n    }\n\n    /**\n     * 不再支持missing，改成must_not和exists的组合\n     * @param node\n     */\n    @Override\n    public void visit(Missing node) {\n        super.visit(node);\n\n        JSONObject obj = (JSONObject) this.ret;\n        String value = obj.getString(\"field\");\n        if (value == null) {\n             return ;\n        }\n\n        node.setName(\"bool\");\n        this.ret = JSON.parseObject(String.format(\"{\\\"must_not\\\":[{\\\"exists\\\":{\\\"field\\\":\\\"%s\\\"}}]}\", value));\n    }\n\n    /**\n     * 对于dsl语句中timeout没有加单位的在6.x查询出错场景，加上单位ms\n     *\n     * @param node\n     */\n    @Override\n    public void visit(Timeout node) {\n        super.visit(node);\n\n        try {\n            // 为数值类型时，添加单位ms\n            if (this.ret instanceof Short || this.ret instanceof Integer || this.ret instanceof Long) {\n                String timeOutValue = String.format(\"%dms\", this.ret);\n                node.v = new ObjectNode(timeOutValue);\n                this.ret = timeOutValue;\n            }\n        } catch (Exception e) {\n            logger.warn(\"parse timeout exception\", e);\n        }\n    }\n\n    @Override\n    public void visit(Term node) {\n        super.visit(node);\n        JSONObject obj = (JSONObject) this.ret;\n        for (String key : obj.keySet()) {\n            if (key.equals(TYPE)) {\n                node.setName(MATCH_ALL);\n                obj.clear();\n                break;\n            }\n        }\n    }\n\n    @Override\n    public void visit(Terms node) {\n        super.visit(node);\n        JSONObject obj = (JSONObject) this.ret;\n        for (String key : obj.keySet()) {\n            if (key.equals(TYPE)) {\n                node.setName(MATCH_ALL);\n                obj.clear();\n                break;\n            }\n        }\n    }\n\n\n    /**\n     * 高版本不再支持not，改成must_not\n     * @param node\n     */\n    @Override\n    public void visit(Not node) {\n        super.visit(node);\n\n        JSONObject obj = (JSONObject) this.ret;\n        node.setName(\"bool\");\n        JSONObject boolNode = new JSONObject();\n        JSONArray mustNotNode = new JSONArray();\n        boolNode.put(\"must_not\", mustNotNode);\n\n        if (obj.size() == 1) {\n            if (obj.containsKey(\"filter\")) {\n                obj = obj.getJSONObject(\"filter\");\n            } else if (obj.containsKey(QUERY)) {\n                obj = obj.getJSONObject(QUERY);\n            }\n        }\n\n        mustNotNode.add(obj);\n        this.ret = boolNode;\n    }\n\n    /**\n     * 高版本不再支持not，改成must\n     * @param node\n     */\n    @Override\n    public void visit(And node) {\n        super.visit(node);\n        visitByConditionType(node, \"must\");\n    }\n\n    private void visitByConditionType(KeyWord node, String conditionType) {\n        node.setName(\"bool\");\n        if (this.ret instanceof JSONArray) {\n            JSONObject boolNode = new JSONObject();\n            boolNode.put(conditionType, this.ret);\n            this.ret = boolNode;\n        } else if (this.ret instanceof JSONObject){\n            JSONObject obj = (JSONObject) this.ret;\n\n            JSONArray allArr = new JSONArray();\n            for (Map.Entry<String,Object> entry : obj.entrySet()) {\n                if (entry.getValue() instanceof  JSONArray) {\n                    JSONArray arr = obj.getJSONArray(entry.getKey());\n                    allArr.addAll(arr);\n                }\n            }\n\n            JSONObject boolNode = new JSONObject();\n            boolNode.put(conditionType, allArr);\n            this.ret = boolNode;\n        }\n    }\n\n    /**\n     * 高版本不再支持not，改成should\n     * @param node\n     */\n    @Override\n    public void visit(Or node) {\n        super.visit(node);\n        visitByConditionType(node, \"should\");\n    }\n\n    @Override\n    public void visit(Script node) {\n        super.visit(node);\n\n        if (this.ret instanceof JSONObject) {\n            JSONObject obj = (JSONObject) this.ret;\n            if (obj.containsKey(\"script\")) {\n                JSONObject script = obj.getJSONObject(\"script\");\n                transformScript(script);\n            } else {\n                transformScript(obj);\n            }\n\n\n        }\n    }\n\n    @Override\n    public void visit(Queryquery node) {\n        super.visit(node);\n\n        if (this.ret instanceof JSONObject) {\n            JSONObject obj = (JSONObject) this.ret;\n            if (obj.size() == 1 && obj.containsKey(QUERY_STRING)) {\n                this.ret = obj.get(QUERY_STRING);\n                node.setName(QUERY_STRING);\n            }\n        }\n    }\n\n    @Override\n    public void visit(Must node) {\n        visitBoolLogic(node.n);\n    }\n\n    @Override\n    public void visit(MustNot node) {\n        visitBoolLogic(node.n);\n    }\n\n    @Override\n    public void visit(Should node) {\n        visitBoolLogic(node.n);\n    }\n\n    @Override\n    public void visit(Filter node) {\n        visitBoolLogic(node.n);\n    }\n\n    private void visitBoolLogic(Node n) {\n        if (n instanceof NodeList) {\n            JSONArray array = new JSONArray();\n            for (Node k : ((NodeList) n).l) {\n                if (k instanceof NodeMap) {\n                    NodeMap map = (NodeMap) k;\n                    array.add(parseBoolItem(map));\n                } else if (k instanceof NodeList) {\n                    NodeList nl = (NodeList)k;\n                    for (Node node : nl.l) {\n                        if (node instanceof NodeMap) {\n                            NodeMap map = (NodeMap) node;\n                            array.add(parseBoolItem(map));\n                        }\n                    }\n                }\n            }\n\n            this.ret = array;\n        } else if (n instanceof NodeMap) {\n            this.ret = parseBoolItem((NodeMap) n);\n        } else if (n instanceof ObjectNode && ((ObjectNode) n).value == null) {\n            this.ret = null;\n        }\n    }\n\n    /**\n     * bool item里出现query关键字，则直接去掉query，将query内容上提\n     * @param map\n     * @return\n     */\n    private JSONObject parseBoolItem(NodeMap map) {\n        JSONObject jsonMap = new JSONObject();\n        for (KeyNode kn : map.m.keySet()) {\n            Node valueNode = map.m.get(kn);\n\n            if (kn.getValue().equalsIgnoreCase(QUERY)) {\n                valueNode.accept(this);\n\n                JSONObject obj = (JSONObject) this.ret;\n\n                if (valueNode instanceof KeyWord\n                        && ((KeyWord) valueNode).getName().equals(QUERY_STRING)) {\n                    jsonMap.put(QUERY_STRING, obj);\n                } else if (obj.size() == 1) {\n                    Map.Entry<String, Object> entry = obj.entrySet().iterator().next();\n                    String key = entry.getKey();\n                    Object value = entry.getValue();\n\n                    jsonMap.put(key, value);\n                }\n            } else {\n                valueNode.accept(this);\n\n                if (valueNode instanceof KeyWord) {\n                    jsonMap.put(((KeyWord)valueNode).getName(), this.ret);\n                } else {\n                    jsonMap.put(kn.getValue(), this.ret);\n                }\n\n            }\n        }\n\n        return jsonMap;\n    }\n\n\n    private void transformScript(JSONObject script) {\n        if (script.containsKey(\"lang\")) {\n            String lang = script.getString(\"lang\");\n            if (lang.equalsIgnoreCase(\"inline\")\n                    || lang.equalsIgnoreCase(\"groovy\")) {\n                script.put(\"lang\", \"painless\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/transform/RequestVisitorV2.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.transform;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.aggr.AggrTerms;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.query.Match;\nimport com.didiglobal.knowframework.dsl.parse.dsl.visitor.basic.OutputVisitor;\n\nimport java.util.Iterator;\nimport java.util.Map;\n\npublic class RequestVisitorV2 extends OutputVisitor {\n\n    protected static final String ORDER = \"order\";\n\n    @Override\n    public void visit(Match node) {\n        super.visit(node);\n\n        JSONObject obj = (JSONObject) this.ret;\n        for (Map.Entry<String,Object> entry : obj.entrySet()) {\n            Object value = entry.getValue();\n            if (value instanceof JSONObject) {\n                ((JSONObject) value).remove(\"auto_generate_synonyms_phrase_query\");\n            }\n        }\n    }\n\n    @Override\n    public void visit(AggrTerms node) {\n        super.visit(node);\n\n        JSONObject obj = (JSONObject) this.ret;\n        if (obj.containsKey(ORDER)) {\n            if (obj.get(ORDER) instanceof JSONObject) {\n                JSONObject order = obj.getJSONObject(ORDER);\n                dealOrder(order);\n            } else if (obj.get(ORDER) instanceof JSONArray) {\n                for (Object o : (JSONArray) obj.get(ORDER)) {\n                    JSONObject order = (JSONObject) o;\n                    dealOrder(order);\n                }\n            }\n        }\n    }\n\n    private void dealOrder(JSONObject order) {\n        Iterator<String> iter = order.keySet().iterator();\n        while (iter.hasNext()) {\n            String key = iter.next();\n            if (key.equalsIgnoreCase(\"_key\")) {\n                Object k = order.remove(\"_key\");\n                order.put(\"_term\", k);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/transform/RequestVisitorV6.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.transform;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.didiglobal.knowframework.dsl.parse.dsl.ast.aggr.DateHistoGram;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.elasticsearch.common.unit.TimeValue;\n\npublic class RequestVisitorV6 extends BaseRequestVisitor {\n\n    protected static final ILog logger = LogFactory.getLog(RequestVisitorV6.class);\n\n    protected static final String FIXED_INTERVAL = \"fixed_interval\";\n    protected static final String INTERVAL = \"interval\";\n    protected static final String CALENDAR_INTERVAL = \"calendar_interval\";\n\n    /**\n     * interval不再支持小数，如果遇到小数，则转换成ms值\n     * @param node\n     */\n    @Override\n    public void visit(DateHistoGram node) {\n        super.visit(node);\n\n        try {\n            JSONObject obj = (JSONObject) this.ret;\n            if (obj.containsKey(FIXED_INTERVAL)) {\n                Object fixedInterval = obj.get(FIXED_INTERVAL);\n                obj.remove(FIXED_INTERVAL);\n                obj.put(INTERVAL, fixedInterval);\n            } else if (obj.containsKey(CALENDAR_INTERVAL)) {\n                Object calendarInterval = obj.get(CALENDAR_INTERVAL);\n                obj.remove(CALENDAR_INTERVAL);\n                obj.put(INTERVAL, calendarInterval);\n            }\n\n            String interval = obj.getString(INTERVAL);\n\n            //高版本不支持时间为小数\n            if (interval.contains(\".\")) {\n                TimeValue timeValue = TimeValue.parseTimeValue(interval, null, \"settings\");\n                obj.put(INTERVAL , timeValue.getMillis() + \"ms\");\n            }\n        } catch (Exception e) {\n            logger.warn(\"parse date histogram exception\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/dsl/transform/RequestVisitorV7.java",
    "content": "package com.didi.arius.gateway.core.service.dsl.transform;\n\npublic class RequestVisitorV7 extends BaseRequestVisitor {\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/impl/ESRestClientServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.impl;\n\nimport java.util.*;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.enums.RunModeEnum;\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.http.message.BasicHeader;\nimport org.apache.logging.log4j.util.Strings;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport static org.apache.commons.lang.StringUtils.*;\n\n/**\n * @author fitz\n * @date 2021/5/26 5:38 下午\n */\n@Service\npublic class ESRestClientServiceImpl implements ESRestClientService {\n    protected static final ILog logger = LogFactory.getLog( ESRestClientServiceImpl.class);\n    protected static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n\n    private static final int DEFAULT_MAX_CONN_PER_ROUTE = 500;\n    private static final int DEFAULT_MAX_CONN_TOTAL = 3000;\n\n    private static final String COLON = \":\";\n    private static final String COMMA = \",\";\n\n    private volatile Map<String, ESCluster> esClusterMap = new HashMap<>();\n\n    @Autowired\n    private QueryConfig queryConfig;\n\n    @Override\n    public ESClient getClient(String clusterName, String actionName) {\n        return getClientStrict(clusterName, actionName);\n    }\n\n    @Override\n    public ESClient getClientStrict(String clusterName, String actionName) {\n        ESCluster dataCenter = esClusterMap.get(clusterName);\n        if (dataCenter == null) {\n            return null;\n        }\n        ESClient esClient = dataCenter.getEsClient();\n        if (dataCenter.getWriteAction().contains(actionName)) {\n            esClient = dataCenter.getEsWriteClient();\n            bootLogger.debug(\"assign action[{}], request action[{}] is write, write client host:[{}]\",\n                    dataCenter.getWriteAction(), actionName, esClient.getNodes());\n        }\n        return esClient;\n\n    }\n\n    @Override\n    public ESClient getAdminClient(String actionName) {\n        Objects.requireNonNull(esClusterMap.get(queryConfig.getAdminClusterName()));\n        return getClient(queryConfig.getAdminClusterName(), actionName);\n\n    }\n\n    @Override\n    public void resetClients(Map<String, ESCluster> newDataCenterMap) {\n        if (newDataCenterMap == null || newDataCenterMap.isEmpty()) return;\n        List<String> noNeedClose = new ArrayList<>();\n        for (Map.Entry<String, ESCluster> entry : newDataCenterMap.entrySet()) {\n            String newClusterName = entry.getKey();\n            ESCluster newDataCenter = entry.getValue();\n            try {\n                if (this.esClusterMap.containsKey(newClusterName)) {\n                    if (alreadyInitialCenter(noNeedClose, newClusterName, newDataCenter)) {\n                        clientKeepalive(newDataCenter);\n                        continue;\n                    }\n                }\n                bootLogger.info(\"add http dateCenter, cluster={}||addr={}\", newDataCenter.getCluster(), newDataCenter.getHttpAddress());\n                initClient(newDataCenter);\n            } catch (Exception e) {\n                bootLogger.warn(\"add http dateCenter, cluster={}||addr={}\", newDataCenter.getCluster(), newDataCenter.getHttpAddress(), e);\n            }\n        }\n        final Map<String, ESCluster> oldDataCenterMap = this.esClusterMap;\n        this.esClusterMap = Collections.unmodifiableMap(newDataCenterMap);\n\n        for (Map.Entry<String, ESCluster> entry : oldDataCenterMap.entrySet()) {\n            if (noNeedClose.contains(entry.getKey()) == false) {\n                closeOldClient(entry);\n            }\n            /*entry.getValue().setEsClient(null);*/\n        }\n    }\n\n    /**\n     *  es client的报活\n     * @param newDataCenter 集群\n     */\n    private void clientKeepalive(ESCluster newDataCenter) {\n        ESClient esClient = newDataCenter.getEsClient();\n        ESClient esWriteClient = newDataCenter.getEsWriteClient();\n        if (null != esClient && !esClient.isActualRunning()) {\n            logger.warn(String.format(\"cluster[%s] client is stop, start rebuild\", esClient.getClusterName()));\n            esClient.start();\n        }\n        if (null != esWriteClient && !esWriteClient.isActualRunning()) {\n            logger.warn(String.format(\"cluster[%s] write client is stop, start rebuild\", esWriteClient.getClusterName()));\n            esWriteClient.start();\n        }\n    }\n\n    @Override\n    public Map<String, ESCluster> getESClusterMap() {\n        return esClusterMap;\n    }\n\n    private void closeOldClient(Map.Entry<String, ESCluster> entry) {\n        try {\n            entry.getValue().getEsClient().close();\n            if (null != entry.getValue().getEsWriteClient()) {\n                entry.getValue().getEsWriteClient().close();\n            }\n        } catch (Exception e) {\n            bootLogger.warn(\"delete http dateCenter, cluster={}||addr={}\", entry.getKey(), entry.getValue().getHttpAddress(), e);\n        }\n    }\n\n    private boolean alreadyInitialCenter(List<String> noNeedClose, String newClusterName, ESCluster newDataCenter) {\n        ESCluster oldDataCenter = this.esClusterMap.get(newClusterName);\n        ESClient esClient = oldDataCenter.getEsClient();\n        ESClient esWriteClient = oldDataCenter.getEsWriteClient();\n        if (isEqualAddress(oldDataCenter.getHttpAddress(), newDataCenter.getHttpAddress()) &&\n                isEqualAddress(oldDataCenter.getHttpWriteAddress(), newDataCenter.getHttpWriteAddress()) &&\n                oldDataCenter.getRunMode() == newDataCenter.getRunMode()) {\n            esClient.setEsVersion(newDataCenter.getEsVersion());\n            if (null != esWriteClient) {\n                esWriteClient.setEsVersion(newDataCenter.getEsVersion());\n            }\n            newDataCenter.setEsWriteClient(esWriteClient);\n            newDataCenter.setEsClient(esClient);\n            noNeedClose.add(newClusterName);\n            return true;\n        }\n        return false;\n    }\n\n    private void initClient(ESCluster dataCenter) {\n        initReadClient(dataCenter);\n        if (dataCenter.getRunMode() == RunModeEnum.READ_WRITE_SPLIT.getRunMode()) {\n            initWriteClient(dataCenter);\n        }\n    }\n\n    private void initReadClient(ESCluster dataCenter) {\n        ESClient esOldClient = dataCenter.getEsClient();\n        dataCenter.setEsClient(getEsClient(dataCenter, dataCenter.getHttpAddress()));\n        if (null != esOldClient) {\n            esOldClient.close();\n        }\n    }\n\n    private void initWriteClient(ESCluster dataCenter) {\n        ESClient esOldWriteClient = dataCenter.getEsWriteClient();\n        dataCenter.setEsWriteClient(getEsClient(dataCenter, dataCenter.getHttpWriteAddress()));\n        if (null != esOldWriteClient) {\n            esOldWriteClient.close();\n        }\n    }\n\n    private ESClient getEsClient(ESCluster dataCenter, String addr) {\n        ESClient client = new ESClient(dataCenter.getCluster(), dataCenter.getEsVersion());\n        client.setMax_conn_per_router(DEFAULT_MAX_CONN_PER_ROUTE);\n        client.setMax_conn_total(DEFAULT_MAX_CONN_TOTAL);\n\n        client.setSocket_timeout_millis(queryConfig.getEsSocketTimeout());\n        String[] hosts = split(addr, COMMA);\n        for (int i = 0; i < hosts.length; ++i) {\n            String clusterNode = hosts[i];\n\n            String hostName = substringBeforeLast(clusterNode, COLON);\n            String port = substringAfterLast(clusterNode, COLON);\n            bootLogger.info(\"adding http client node={}||clusterName={}\", clusterNode, dataCenter.getCluster());\n            try {\n                client.addHttpHost(hostName, Integer.valueOf(port));\n            } catch (Exception e) {\n                bootLogger.error(\"adding exception, http client node={}||clusterName={}\", clusterNode, dataCenter.getCluster(), e);\n            }\n        }\n\n        //开源gateway为了支持带认证的集群使用gateway访问\n\t\tif (!Strings.isEmpty(dataCenter.getPassword())) {\n\t\t\tclient.setBasicAuth(dataCenter.getPassword());\n\t\t}\n\n        if (!client.getEsVersion().startsWith(QueryConsts.ES_VERSION_2_PREFIX)) {\n            client.addHeader(new BasicHeader(\"content-type\", \"application/json\"));\n        }\n\n        client.start();\n        return client;\n    }\n\n    public boolean isEqualAddress(String oneAddress, String otherAddress) {\n        if (null == oneAddress && null == otherAddress) {\n            return true;\n        }\n        if (null == oneAddress || null == otherAddress) {\n            return false;\n        }\n        if (oneAddress.equals(otherAddress)) {\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/impl/ESTcpClientServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.impl;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.service.ESTcpClientService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.NoArgsConstructor;\nimport org.elasticsearch.client.Client;\nimport org.elasticsearch.client.transport.TransportClient;\nimport org.elasticsearch.common.settings.Settings;\nimport org.elasticsearch.common.transport.InetSocketTransportAddress;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport java.net.InetAddress;\nimport java.util.*;\n\nimport static org.apache.commons.lang.StringUtils.*;\n\n/**\n * @author fitz\n * @date 2021/5/26 5:34 下午\n */\n@Service\n@NoArgsConstructor\npublic class ESTcpClientServiceImpl implements ESTcpClientService {\n    protected static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n\n    private static final String COLON = \":\";\n    private static final String COMMA = \",\";\n\n    @Value(\"${elasticsearch.admin.cluster.name}\")\n    private String adminClusterName;\n\n    @Autowired\n    private QueryConfig queryConfig;\n\n    private Map<String, ESCluster> dataCenterMap = new HashMap<>();\n\n    @Override\n    public Client getClient(String clusterName) {\n        return Objects.requireNonNull(dataCenterMap.get(clusterName)).getClient();\n    }\n\n    @Override\n    public Client getAdminClient() {\n        return Objects.requireNonNull(dataCenterMap.get(adminClusterName)).getClient();\n    }\n\n    @Override\n    public void resetClients(Map<String, ESCluster> newDataCenterMap) {\n        List<ESCluster> adds = new ArrayList<>();\n        List<ESCluster> deletes = new ArrayList<>();\n\n        // check update and delete\n        for (Map.Entry<String, ESCluster> entry : dataCenterMap.entrySet()) {\n            String clusterName = entry.getKey();\n            ESCluster esCluster = entry.getValue();\n\n            if (!newDataCenterMap.containsKey(clusterName)) {\n                // delete\n                deletes.add( esCluster );\n                continue;\n            }\n\n            ESCluster newESCluster = newDataCenterMap.get(clusterName);\n            if (!esCluster.getReadAddress().equals( newESCluster.getReadAddress())) {\n                adds.add( newESCluster );\n            }\n        }\n\n        // check add\n        for (Map.Entry<String, ESCluster> entry : newDataCenterMap.entrySet()) {\n            String clusterName = entry.getKey();\n            ESCluster newESCluster = entry.getValue();\n\n            if (!newESCluster.getEsVersion().startsWith(QueryConsts.ES_VERSION_2_PREFIX)) {\n                bootLogger.info(\"tcp client reject high version, cluster={}, version={}\", clusterName, newESCluster.getEsVersion());\n                continue;\n            }\n\n            if (!dataCenterMap.containsKey(clusterName)) {\n                adds.add( newESCluster );\n            }\n        }\n\n        for (ESCluster esCluster : deletes) {\n            bootLogger.info(\"delete dateCenter, cluster={}||addr={}\", esCluster.getCluster(), esCluster.getReadAddress());\n            esCluster.getClient().close();\n            dataCenterMap.remove( esCluster.getCluster() );\n        }\n\n        for (ESCluster esCluster : adds) {\n            bootLogger.info(\"add dateCenter, cluster={}||addr={}\", esCluster.getCluster(), esCluster.getReadAddress());\n\n            //reset client\n            initClient( esCluster );\n\n            dataCenterMap.put( esCluster.getCluster(), esCluster );\n        }\n    }\n\n    @Override\n    public Map<String, ESCluster> getDataCenterMap() {\n        return dataCenterMap;\n    }\n\n    @Override\n    public void setDataCenterMap(Map<String, ESCluster> dataCenterMap) {\n        this.dataCenterMap = dataCenterMap;\n    }\n\n    /************************************************************** private method **************************************************************/\n    private void initClient(ESCluster esCluster) {\n        if (esCluster.getClient() != null) {\n            esCluster.getClient().close();\n        }\n\n        String addr = esCluster.getReadAddress();\n        Settings settings = Settings.builder()\n                .put(\"cluster.name\", esCluster.getCluster())\n                .put(\"transport.tcp.connect_timeout\", queryConfig.getConnectESTime())\n                .put(\"transport.netty.worker_count\", queryConfig.getClientWorkerCount())\n                .build();\n        TransportClient client = TransportClient.builder().settings(settings).build();\n\n        esCluster.setClient(client);\n        for (String clusterNode : split(addr, COMMA)) {\n            String hostName = substringBeforeLast(clusterNode, COLON);\n            String port = substringAfterLast(clusterNode, COLON);\n            bootLogger.info(\"adding transport node={}||clusterName={}\", clusterNode, esCluster.getCluster());\n            try {\n                client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(hostName), Integer.valueOf(port)));\n            } catch (Exception e) {\n                bootLogger.error(\"adding exception, transport node={}||clusterName={}\", clusterNode, esCluster.getCluster(), e);\n            }\n        }\n        client.connectedNodes();\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/impl/MetricsServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.impl;\n\nimport com.didi.arius.gateway.common.event.ActionPostResponseEvent;\nimport com.didi.arius.gateway.common.event.PostResponseEvent;\nimport com.didi.arius.gateway.common.event.QueryPostResponseEvent;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metrics.IndexMetrics;\nimport com.didi.arius.gateway.common.metrics.QueryMetrics;\nimport com.didi.arius.gateway.core.service.MetricsService;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Service;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n * @author fitz\n * @date 2021/5/31 12:08 下午\n */\n@Service\npublic class MetricsServiceImpl implements MetricsService, ApplicationListener<PostResponseEvent> {\n    private ConcurrentMap<Integer, QueryMetrics> appidMetricsMap = new ConcurrentHashMap<>();\n    private ConcurrentMap<String, IndexMetrics> indexMetricsMap = new ConcurrentHashMap<>();\n\n    @Override\n    public void addQueryCost(int appid, long cost) {\n        QueryMetrics queryMetrics = getQueryMetrics(appid);\n        queryMetrics.incrCost(cost);\n    }\n\n    @Override\n    public void addSlowlogCost(int appid, long cost) {\n        QueryMetrics queryMetrics = getQueryMetrics(appid);\n        queryMetrics.incrSlowlogCost(cost);\n    }\n\n    @Override\n    public void addSearchResponseMetrics(int appid, long tookInMillis, long totalHits, int totalShards, int failedShards) {\n        QueryMetrics queryMetrics = getQueryMetrics(appid);\n        queryMetrics.incrSearchResponseMetrics(tookInMillis, totalHits, totalShards, failedShards);\n    }\n\n    @Override\n    public void addReqeustLength(int appid, long length) {\n        QueryMetrics queryMetrics = getQueryMetrics(appid);\n        queryMetrics.incrReqeustLength(length);\n    }\n\n    @Override\n    public void addResponseLength(int appid, long length) {\n        QueryMetrics queryMetrics = getQueryMetrics(appid);\n        queryMetrics.incrResponseLength(length);\n    }\n\n    @Override\n    public void addQueryMetrics(int appid, long cost, long requestLength, long responseLength) {\n        QueryMetrics queryMetrics = getQueryMetrics(appid);\n        queryMetrics.incrCost(cost);\n        queryMetrics.incrReqeustLength(requestLength);\n        queryMetrics.incrResponseLength(responseLength);\n    }\n\n    @Override\n    public void addIndexMetrics(String index, String operation, long cost, long requestLength, long responseLength) {\n        IndexMetrics indexMetrics = getIndexMetrics(index, operation);\n        indexMetrics.incrCost(cost);\n        indexMetrics.incrReqeustLength(requestLength);\n        indexMetrics.incrResponseLength(responseLength);\n    }\n\n    @Override\n    public void incrQueryAggs(int appid) {\n        QueryMetrics queryMetrics = getQueryMetrics(appid);\n        queryMetrics.incrAggs();\n    }\n\n    @Override\n    public void onApplicationEvent(PostResponseEvent postResponseEvent) {\n        if(postResponseEvent instanceof ActionPostResponseEvent){\n            ActionPostResponseEvent actionPostResponseEvent = (ActionPostResponseEvent)postResponseEvent;\n            ActionContext actionContext = actionPostResponseEvent.getActionContext();\n\n            if (null != actionContext) {\n                addQueryMetrics(actionContext.getAppid(), actionContext.getCostTime(), actionContext.getRequestLength(), actionContext.getResponseLength());\n            }\n        }\n\n        if(postResponseEvent instanceof QueryPostResponseEvent){\n            QueryPostResponseEvent queryPostResponseEvent = (QueryPostResponseEvent)postResponseEvent;\n            QueryContext queryContext = queryPostResponseEvent.getQueryContext();\n\n            if(null != queryContext){\n                dealResponse(queryContext);\n            }\n        }\n\n    }\n\n    private void dealResponse(QueryContext queryContext) {\n        int responseBodyLen = queryContext.getResponse() != null ? queryContext.getResponse().content().length() : 0;\n        if (queryContext.isDetailLog()) {\n            if (queryContext.getCostTime() > queryContext.getRequestSlowlogThresholdMills()) {\n                addSlowlogCost(queryContext.getAppid(), queryContext.getCostTime());\n            }\n            addQueryMetrics(queryContext.getAppid(), queryContext.getCostTime(), queryContext.getPostBody().length(), responseBodyLen);\n        }\n    }\n\n    /************************************************************** private method **************************************************************/\n    private QueryMetrics getQueryMetrics(int appid) {\n        QueryMetrics queryMetrics = appidMetricsMap.get(appid);\n        if (queryMetrics == null) {\n            synchronized (appidMetricsMap) {\n                queryMetrics = appidMetricsMap.get(appid);\n                if (queryMetrics == null) {\n                    queryMetrics = new QueryMetrics(appid);\n                    appidMetricsMap.putIfAbsent(appid, queryMetrics);\n                }\n            }\n        }\n\n        return queryMetrics;\n    }\n\n    private IndexMetrics getIndexMetrics(String index, String operation) {\n        IndexMetrics indexMetrics = indexMetricsMap.get(index + operation);\n        if (indexMetrics == null) {\n            synchronized (indexMetricsMap) {\n                indexMetrics = indexMetricsMap.get(index + operation);\n                if (indexMetrics == null) {\n                    indexMetrics = new IndexMetrics(index, operation);\n                    indexMetricsMap.putIfAbsent(index+operation, indexMetrics);\n                }\n            }\n        }\n\n        return indexMetrics;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/impl/RateLimitServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.impl;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.enums.FlowStatus;\nimport com.didi.arius.gateway.common.event.PostResponseEvent;\nimport com.didi.arius.gateway.common.event.QueryPostResponseEvent;\nimport com.didi.arius.gateway.common.flowcontrol.*;\nimport com.didi.arius.gateway.common.metadata.FlowThreshold;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.RateLimitService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.NoArgsConstructor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.atomic.AtomicLong;\n\n@Service\n@NoArgsConstructor\npublic class RateLimitServiceImpl implements RateLimitService, ApplicationListener<PostResponseEvent> {\n\n    private static final ILog logger = LogFactory.getLog(RateLimitServiceImpl.class);\n    private static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n    protected static final Logger statLogger = LoggerFactory.getLogger(QueryConsts.STAT_LOGGER);\n\n    private AtomicLong totalByteIn = new AtomicLong();\n\n    /**\n     * 30MB/s\n     */\n    private static final int APPID_FLOW_LIMIT_IN_UPPER = 30 * 1024 * 1024;\n    private static final int APPID_FLOW_LIMIT_IN_LOWER = 15 * 1024 * 1024;\n    private static final int APPID_FLOW_LIMIT_OUT_UPPER = 100 * 1024 * 1024;\n    private static final int APPID_FLOW_LIMIT_OUT_LOWER = 80 * 1024 * 1024;\n    private static final int APPID_FLOW_LIMIT_OPS_UPPER = 10000;\n    private static final int APPID_FLOW_LIMIT_OPS_LOWER = 5000;\n\n    @Value(\"${arius.gateway.flowSchedulePeriod}\")\n    private int flowSchedulePeriod;\n\n    private ConcurrentMap<Integer, FlowController> flowControllerMap = new ConcurrentHashMap<>();\n    private ConcurrentMap<String, FlowLimit> flowLimitMap = new ConcurrentHashMap<>();\n\n    @Autowired\n    private QueryConfig queryConfig;\n\n    @Autowired\n    private ThreadPool threadPool;\n\n    @PostConstruct\n    public void init(){\n        cacheTotalAreaFlow();\n        threadPool.submitScheduleAtFixTask(this::calFlowLimit, flowSchedulePeriod, flowSchedulePeriod);\n    }\n\n    @Override\n    public void addByteIn(long bytes) {\n        long currentByteIn = totalByteIn.get();\n        if (currentByteIn >= queryConfig.getMaxByteIn()) {\n            bootLogger.error(\"totalByteIn overflow, currentByteIn is {}\", currentByteIn);\n        }\n\n        totalByteIn.addAndGet(bytes);\n    }\n\n    @Override\n    public void removeByteIn(long bytes) {\n        totalByteIn.addAndGet(-bytes);\n    }\n\n    @Override\n    public boolean isTrafficDataOverflow(int appid, String searchId) {\n        String areaId = FlowController.formAreaId(appid, searchId);\n        FlowLimit flowLimit = flowLimitMap.get(areaId);\n        if (flowLimit == null) {\n            return false;\n        }\n\n        boolean ret = flowLimit.isOverflow();\n        if (ret) {\n            statLogger.info(QueryConsts.DLFLAG_PREFIX + \"overflow||appid={}||searchId={}||threshold={}\", appid, searchId, flowLimit.getThreshold());\n        }\n\n        return ret;\n    }\n\n    @Override\n    public void addUp(int appid, String searchId, int in, int out) {\n        FlowController flowController = getFlowController(appid);\n        boolean isRelaxedIn = flowController.addUpIn(searchId, in);\n        boolean isRelaxedOut = flowController.addUpOut(searchId, out);\n        if (!isRelaxedIn || !isRelaxedOut) {\n            String areaId = FlowController.formAreaId(appid, searchId);\n            initFlowLimit(areaId);\n        }\n    }\n\n    @Override\n    public void resetAppAreaFlow(int appid, FlowThreshold flowThreshold) {\n        String areaId = FlowController.formAreaId(appid, QueryConsts.TOTAL_SEARCH_ID);\n        AreaFlow areaFlow = AreaFlowCache.getInstance().getAreaFlow(areaId);\n        if (areaFlow == null) {\n            cacheAppAreaFlow(appid, flowThreshold);\n        } else {\n            Flow in = areaFlow.getIn();\n            in.setLowerBound(flowThreshold.getInLower());\n            in.setUpperBound(flowThreshold.getInUpper());\n\n            Flow out = areaFlow.getOut();\n            out.setLowerBound(flowThreshold.getOutLower());\n            out.setUpperBound(flowThreshold.getOutUpper());\n\n            Flow ops = areaFlow.getOps();\n            ops.setLowerBound(flowThreshold.getOpsLower());\n            ops.setUpperBound(flowThreshold.getOpsUpper());\n        }\n    }\n\n    @Override\n    public Map<Integer, FlowController> getFlowControllerMap() {\n        return flowControllerMap;\n    }\n\n    @Override\n    public ConcurrentMap<String, FlowLimit> getFlowLimitMap() {\n        return flowLimitMap;\n    }\n\n    @Override\n    public int getFlowSchedulePeriod() {\n        return flowSchedulePeriod;\n    }\n\n    @Override\n    public void onApplicationEvent(PostResponseEvent postResponseEvent) {\n\n        if(postResponseEvent instanceof QueryPostResponseEvent){\n            QueryPostResponseEvent queryPostResponseEvent = (QueryPostResponseEvent)postResponseEvent;\n            QueryContext queryContext = queryPostResponseEvent.getQueryContext();\n            if(null != queryContext){\n                removeByteIn(queryContext.getPostBody().length());\n            }\n        }\n    }\n\n    /************************************************************** private method **************************************************************/\n    private void cacheTotalAreaFlow() {\n        Flow in = new Flow();\n        in.setLowerBound(APPID_FLOW_LIMIT_IN_LOWER * 10);\n        in.setUpperBound(APPID_FLOW_LIMIT_IN_UPPER * 10);\n\n        Flow out = new Flow();\n        out.setLowerBound(APPID_FLOW_LIMIT_OUT_LOWER * 10);\n        out.setUpperBound(APPID_FLOW_LIMIT_OUT_UPPER * 10);\n\n        Flow ops = new Flow();\n        ops.setLowerBound(APPID_FLOW_LIMIT_OPS_LOWER * 10);\n        ops.setUpperBound(APPID_FLOW_LIMIT_OPS_UPPER * 10);\n\n        AreaFlow areaFlow = new AreaFlow();\n        areaFlow.setIn(in);\n        areaFlow.setOut(out);\n        areaFlow.setOps(ops);\n        areaFlow.setStatus(FlowStatus.DOWN);\n\n        String areaId = FlowController.formAreaId(QueryConsts.TOTAL_APPID_ID, QueryConsts.TOTAL_SEARCH_ID);\n        AreaFlowCache.getInstance().setAreaFlow(areaId, areaFlow);\n    }\n\n    private FlowController getFlowController(int appid) {\n        if (!flowControllerMap.containsKey(appid)) {\n            synchronized (flowControllerMap) {\n                flowControllerMap.computeIfAbsent(appid, i -> new FlowController(appid, flowSchedulePeriod));\n            }\n        }\n\n        return flowControllerMap.get(appid);\n    }\n\n    private FlowLimit initFlowLimit(String areaId) {\n        FlowLimit flowLimit = flowLimitMap.get(areaId);\n        if (flowLimit == null) {\n            flowLimit = new FlowLimit(areaId);\n            flowLimit = flowLimitMap.putIfAbsent(areaId, flowLimit);\n        }\n\n        return flowLimit;\n    }\n\n    private void cacheAppAreaFlow(int appid, FlowThreshold flowThreshold) {\n        Flow in = new Flow();\n        in.setLowerBound(APPID_FLOW_LIMIT_IN_LOWER);\n        in.setUpperBound(APPID_FLOW_LIMIT_IN_UPPER);\n\n        Flow out = new Flow();\n        out.setLowerBound(APPID_FLOW_LIMIT_OUT_LOWER);\n        out.setUpperBound(APPID_FLOW_LIMIT_OUT_UPPER);\n\n        Flow ops = new Flow();\n        ops.setLowerBound(flowThreshold.getOpsLower());\n        ops.setUpperBound(flowThreshold.getOpsUpper());\n\n        AreaFlow areaFlow = new AreaFlow();\n        areaFlow.setIn(in);\n        areaFlow.setOut(out);\n        areaFlow.setOps(ops);\n        areaFlow.setStatus(FlowStatus.DOWN);\n\n        String areaId = FlowController.formAreaId(appid, QueryConsts.TOTAL_SEARCH_ID);\n        AreaFlowCache.getInstance().setAreaFlow(areaId, areaFlow);\n    }\n\n    private void calFlowLimit() {\n        for (Map.Entry<Integer, FlowController> entry : flowControllerMap.entrySet()) {\n            FlowController flowController = entry.getValue();\n\n            flowController.backgroundCalFlows();\n        }\n\n        for (Map.Entry<String, FlowLimit> entry : flowLimitMap.entrySet()) {\n            String areaId = entry.getKey();\n            FlowLimit flowLimit = entry.getValue();\n            AreaFlow areaFlow = AreaFlowCache.getInstance().getAreaFlow(areaId);\n\n            flowLimit.limitLevelTouch(areaFlow.getStatus());\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/main/java/com/didi/arius/gateway/core/service/impl/RequestStatsServiceImpl.java",
    "content": "package com.didi.arius.gateway.core.service.impl;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.event.ActionPostResponseEvent;\nimport com.didi.arius.gateway.common.event.PostResponseEvent;\nimport com.didi.arius.gateway.common.event.QueryPostResponseEvent;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metrics.ActionMetric;\nimport com.didi.arius.gateway.common.metrics.AppMetric;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.RequestStatsService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport lombok.NoArgsConstructor;\nimport net.sf.ehcache.Cache;\nimport net.sf.ehcache.CacheManager;\nimport net.sf.ehcache.Element;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\nimport java.util.List;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n@Service\n@NoArgsConstructor\npublic class RequestStatsServiceImpl implements RequestStatsService, ApplicationListener<PostResponseEvent> {\n    protected static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n    private ConcurrentMap<String, ActionMetric> actionMetricMap = new ConcurrentHashMap<>();\n    private ConcurrentMap<Integer, AppMetric> appMetricMap = new ConcurrentHashMap<>();\n\n    @Autowired\n    private QueryConfig queryConfig;\n\n    @Autowired\n    private ThreadPool threadPool;\n\n    @Value(\"${arius.gateway.adminSchedulePeriod}\")\n    private long schedulePeriod;\n\n    private Cache queryContextCache;\n    private Cache actionContextCache;\n\n    @PostConstruct\n    public void init(){\n        threadPool.submitScheduleAtFixTask(this::dealRequest, schedulePeriod, schedulePeriod);\n\n        CacheManager manager = CacheManager.create(RequestStatsServiceImpl.class.getResourceAsStream(\"/ehcache.xml\"));\n        queryContextCache = manager.getCache(\"queryContextCache\");\n        actionContextCache = manager.getCache(\"actionContextCache\");\n    }\n\n    @Override\n    public void dealRequest(){\n        try {\n            dealHttpRequest();\n            dealTcpRequest();\n        } catch (Exception e) {\n            bootLogger.error(\"longTimeContextSchedule exception\", e);\n        }\n    }\n\n    @Override\n    public void putQueryContext(String key, QueryContext value) {\n        Element element = new Element(key, value);\n        queryContextCache.put(element);\n    }\n\n    @Override\n    public QueryContext getQueryContext(String key) {\n        Element element = queryContextCache.get(key);\n        if (element != null) {\n            return (QueryContext) element.getObjectValue();\n        } else {\n            return null;\n        }\n    }\n\n    @Override\n    public List<String> getQueryKeys() {\n        return queryContextCache.getKeys();\n    }\n\n    @Override\n    public void removeQueryContext(String key) {\n        queryContextCache.remove(key);\n    }\n\n    @Override\n    public void putActionContext(String key, ActionContext value) {\n        Element element = new Element(key, value);\n        actionContextCache.put(element);\n    }\n\n    @Override\n    public ActionContext getActionContext(String key) {\n        Element element = actionContextCache.get(key);\n        if (element != null) {\n            return (ActionContext) element.getObjectValue();\n        } else {\n            return null;\n        }\n    }\n\n    @Override\n    public void removeActionContext(String key) {\n        actionContextCache.remove(key);\n    }\n\n    @Override\n    public List<String> getActionKeys() {\n        return actionContextCache.getKeys();\n    }\n\n    @Override\n    public void statsAdd(String actionName, int appid, String searchId, long cost, RestStatus restStatus) {\n        if (searchId == null) {\n            searchId = QueryConsts.TOTAL_SEARCH_ID;\n        }\n\n        appIncr(actionName, appid, searchId, cost, restStatus);\n        actionIncr(actionName, appid, searchId, cost, restStatus);\n    }\n\n    @Override\n    public ConcurrentMap<String, ActionMetric> getActionMetricMap() {\n        return actionMetricMap;\n    }\n\n    @Override\n    public ConcurrentMap<Integer, AppMetric> getAppMetricMap() {\n        return appMetricMap;\n    }\n\n    @Override\n    public void onApplicationEvent(PostResponseEvent postResponseEvent) {\n        if(postResponseEvent instanceof ActionPostResponseEvent){\n            ActionPostResponseEvent actionPostResponseEvent = (ActionPostResponseEvent)postResponseEvent;\n            ActionContext actionContext = actionPostResponseEvent.getActionContext();\n\n            if (null != actionContext) {\n                removeActionContext(actionContext.getRequestId());\n\t\t    }\n        }\n\n        if(postResponseEvent instanceof QueryPostResponseEvent){\n            QueryPostResponseEvent queryPostResponseEvent = (QueryPostResponseEvent)postResponseEvent;\n            QueryContext queryContext = queryPostResponseEvent.getQueryContext();\n\n            if(null != queryContext){\n                removeQueryContext(queryContext.getRequestId());\n            }\n        }\n    }\n\n    /************************************************************** private method **************************************************************/\n    private void dealHttpRequest() {\n        List<String> queryKeys = getQueryKeys();\n        int currentCount = 0;\n        int slowCount = 0;\n        long maxCost = 0;\n        for (String key : queryKeys) {\n            QueryContext queryContext = getQueryContext(key);\n            if (queryContext != null) {\n                currentCount++;\n\n                long cost = System.currentTimeMillis() - queryContext.getRequestTime();\n                if (cost > QueryConsts.SLOW_REQUEST_COST) {\n                    slowCount++;\n\n                    bootLogger.warn(\"slow request||appid={}||requestId={}||dslTemplateKey={}||cost={}\",\n                            queryContext.getAppid(), queryContext.getRequestId(), queryContext.getDslTemplateKey(), cost);\n                }\n\n                if (cost > maxCost) {\n                    maxCost = cost;\n                }\n            }\n        }\n\n        bootLogger.info(\"current http request stats, currentCount={}, slowCount={}, maxCost={}, semaphore={}\", currentCount, slowCount, maxCost, queryConfig.getHttpSemaphore().availablePermits());\n    }\n\n    private void dealTcpRequest() {\n        List<String> queryKeys = getActionKeys();\n        int currentCount = 0;\n        int slowCount = 0;\n        long maxCost = 0;\n        for (String key : queryKeys) {\n            ActionContext actionContext = getActionContext(key);\n            if (actionContext != null) {\n                currentCount++;\n\n                long cost = System.currentTimeMillis() - actionContext.getRequestTime();\n                if (cost > QueryConsts.SLOW_REQUEST_COST) {\n                    slowCount++;\n\n                    bootLogger.warn(\"slow request||appid={}||requestId={}||dslTemplateKey={}||cost={}\",\n                            actionContext.getAppid(), actionContext.getRequestId(), actionContext.getDslTemplateKey(), cost);\n                }\n\n                if (cost > maxCost) {\n                    maxCost = cost;\n                }\n            }\n        }\n\n        bootLogger.info(\"current tcp request stats, currentCount={}, slowCount={}, maxCost={}, semaphore={}\", currentCount, slowCount, maxCost, queryConfig.getTcpSemaphore().availablePermits());\n    }\n\n    private void appIncr(String actionName, int appid, String searchId, long cost, RestStatus restStatus) {\n        if (appid != QueryConsts.TOTAL_APPID_ID) {\n            appIncr(actionName, QueryConsts.TOTAL_APPID_ID, searchId, cost, restStatus);\n        }\n\n        AppMetric appMetric = appMetricMap.get(appid);\n        if (appMetric == null) {\n            synchronized (appMetricMap) {\n                appMetric = new AppMetric(appid);\n                appMetricMap.putIfAbsent(appid, appMetric);\n            }\n        }\n\n        appMetric.incr(searchId, actionName, restStatus, cost);\n    }\n\n    private void actionIncr(String actionName, int appid, String searchId, long cost, RestStatus restStatus) {\n        if (appid != QueryConsts.TOTAL_APPID_ID) {\n            actionIncr(actionName, QueryConsts.TOTAL_APPID_ID, searchId, cost, restStatus);\n        }\n\n        ActionMetric actionMetric = actionMetricMap.get(actionName);\n        if (actionMetric == null) {\n            synchronized (actionMetricMap) {\n                actionMetric = new ActionMetric(actionName);\n                actionMetricMap.putIfAbsent(actionName, actionMetric);\n            }\n        }\n\n        actionMetric.incr(appid, restStatus, cost);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-core/src/test/java/com/didi/arius/gateway/core/AriusGatewayCoreApplicationTests.java",
    "content": "package com.didi.arius.gateway.core;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@SpringBootTest\nclass AriusGatewayCoreApplicationTests {\n\n    @Test\n    void contextLoads() {\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.didi</groupId>\n        <artifactId>arius-gateway-v2</artifactId>\n        <version>0.0.1-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>arius-gateway-remote</artifactId>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.didi</groupId>\n            <artifactId>arius-gateway-common</artifactId>\n            <version>${project.version}</version>\n        </dependency>\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/AriusAdminRemoteService.java",
    "content": "package com.didi.arius.gateway.remote;\n\nimport com.didi.arius.gateway.common.metadata.TemplateAlias;\nimport com.didi.arius.gateway.remote.response.*;\n\n/**\n * @author fitz\n * @date 2021/5/8 11:43 上午\n * 调用Arius-admin第三方接口\n */\npublic interface AriusAdminRemoteService {\n    /**\n     *\n     * @return\n     */\n    AppListResponse listApp();\n\n    /**\n     *\n     * @return\n     */\n    DataCenterListResponse listCluster();\n\n    /**\n     *\n     * @param cluster\n     * @return\n     */\n    TemplateInfoListResponse getTemplateInfoMap(String cluster);\n\n    /**\n     *\n     * @param clusterName\n     * @return\n     */\n    ActiveCountResponse getAliveCount(String clusterName);\n\n    /**\n     *\n     * @return\n     */\n    IndexTemplateListResponse listDeployInfo();\n\n    /**\n     *\n     * @return\n     */\n    DynamicConfigListResponse listQueryConfig();\n\n    /**\n     *\n     * @param clusterName\n     * @param hostName\n     * @param port\n     */\n    void heartbeat(String clusterName, String hostName, Integer port);\n\n    /**\n     *\n     * @param lastModifyTime\n     * @param scrollId\n     * @return\n     */\n    DSLTemplateListResponse listDslTemplates(long lastModifyTime, String scrollId);\n\n    TempaletAliasResponse addAdminTemplateAlias(TemplateAlias templateAlias);\n\n    TempaletAliasResponse delAdminTemplateAlias(TemplateAlias templateAlias);\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/AriusAdminRemoteServiceImpl.java",
    "content": "package com.didi.arius.gateway.remote;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.exception.ServerException;\nimport com.didi.arius.gateway.common.metadata.TemplateAlias;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport com.didi.arius.gateway.remote.response.*;\n\nimport lombok.NoArgsConstructor;\n\n/**\n * @author fitz\n * @date 2021/5/20 11:53 上午\n */\n@Service\n@NoArgsConstructor\npublic class AriusAdminRemoteServiceImpl implements AriusAdminRemoteService {\n\n    private static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n\n    @Value(\"${arius.gateway.adminUrl}\")\n    private String adminUrl;\n    private static final Map<String, String> headerParams = new HashMap<>();\n\n    private static final String APPID_SUFFIX              = \"/v3/thirdpart/gateway/project\";\n    private static final String DATACENTER_SUFFIX         = \"/v3/thirdpart/common/cluster\";\n    private static final String SCHEMA_SUFFIX             = \"/v3/thirdpart/gateway/template\";\n    private static final String GATEWAY_NODES_SUFFIX      = \"/v3/thirdpart/gateway/alivecount\";\n    private static final String TEMPLATE_INFO_SUFFIX      = \"/v3/thirdpart/gateway/deploy-info\";\n    private static final String CONFIG_LIST_SUFFIX        = \"/v3/thirdpart/common/config/query\";\n    private static final String GATEWAY_HEARTBEAT_SUFFIX  = \"/v3/thirdpart/gateway/heartbeat\";\n    private static final String GET_DSL_TEMPLATES_SUFFIX  = \"/v3/thirdpart/gateway/dsl/scroll-dsl-template\";\n    private static final String ADD_TEMPLATE_ALIAS = \"/v3/thirdpart/gateway/alias\";\n    private static final String DEL_TEMPLATE_ALIAS = \"/v3/thirdpart/gateway/alias\";\n\n\n    private static final String SCHEMA_PARAME_CLUSTER         = \"cluster\";\n    private static final String SCHEMA_PARAME_CLUSTER_NAME    = \"clusterName\";\n    private static final String SCHEMA_DATACENTER_NAME        = \"dataCenter\";\n\n    private static final String DSL_QUERY_FIRST_PARAMS    = \"{\\\"dslTemplateVersion\\\":\\\"%s\\\",\\\"lastModifyTime\\\":%d,\\\"scrollSize\\\":1000}\";\n    private static final String DSL_QUERY_PARAMS          = \"{\\\"dslTemplateVersion\\\":\\\"%s\\\",\\\"lastModifyTime\\\":%d,\\\"scrollSize\\\":1000,\\\"scrollId\\\" : \\\"%s\\\"}\";\n    private static final String DSL_TEMPLATE_VERSION      = \"V2\";\n\n    private static final String GATEWAY_DYNAMIC_CONFIG    = \"{\\\"valueGroup\\\":\\\"arius.gateway.config\\\",\\\"status\\\":1}\";\n\n    static {\n        headerParams.put(QueryConsts.GATEWAY_GET_APP_TICKET_NAME, QueryConsts.GATEWAY_GET_APP_TICKET);\n    }\n\n    @Override\n    public AppListResponse listApp() {\n        AppListResponse appListResponse = HttpClient.forward(adminUrl + APPID_SUFFIX, \"GET\", null, headerParams, null, AppListResponse.class);\n\n        if (appListResponse.getCode() != 0) {\n            bootLogger.error(\"resetAppDetails get app list error, code={}, message={}\", appListResponse.getCode(), appListResponse.getMessage());\n            throw new ServerException(\"resetAppDetails get app list error\");\n        }\n\n        if (appListResponse.getData().size() < QueryConsts.MIN_APPID_NUMBER) {\n            bootLogger.error(\"resetAppDetails get app list exception, appid_size={}\", appListResponse.getData().size());\n            throw new ServerException(\"resetAppDetails get app list exception\");\n        }\n        return appListResponse;\n    }\n\n    @Override\n    public DataCenterListResponse listCluster() {\n        DataCenterListResponse response = HttpClient.forward(adminUrl + DATACENTER_SUFFIX, \"GET\", null, headerParams, null,DataCenterListResponse.class);\n        if (response.getCode() != 0) {\n            bootLogger.error(\"resetDataCenterMap get datacenter list error, code={}, message={}\", response.getCode(), response.getMessage());\n            throw new ServerException(\"resetDataCenterMap get datacenter list error\");\n        }\n        return response;\n    }\n\n    @Override\n    public TemplateInfoListResponse getTemplateInfoMap(String cluster) {\n        Map<String, String[]> requestParams = new HashMap<>(1);\n        requestParams.put(SCHEMA_PARAME_CLUSTER, new String[]{cluster});\n\n        TemplateInfoListResponse templateInfoListResponse = HttpClient.forward(adminUrl + SCHEMA_SUFFIX, \"GET\", null, headerParams, requestParams,TemplateInfoListResponse.class);\n        if (templateInfoListResponse.getCode() != 0) {\n            bootLogger.error(\"resetDataCenterDetail get template info list error, code={}, message={}\", templateInfoListResponse.getCode(), templateInfoListResponse.getMessage());\n            throw new ServerException(\"resetDataCenterDetail get template info list error\");\n        }\n        return templateInfoListResponse;\n    }\n\n    @Override\n    public ActiveCountResponse getAliveCount(String clusterName) {\n        Map<String, String[]> requestParams = new HashMap<>(1);\n        requestParams.put(SCHEMA_PARAME_CLUSTER_NAME, new String[]{clusterName});\n        ActiveCountResponse response = HttpClient.forward(adminUrl + GATEWAY_NODES_SUFFIX, \"GET\", null, headerParams, requestParams,ActiveCountResponse.class);\n        if (response.getCode() != 0) {\n            bootLogger.error(\"AdminSchedule alivecount error, code={}, message={}\", response.getCode(), response.getMessage());\n        }\n        return response;\n    }\n\n    @Override\n    public IndexTemplateListResponse listDeployInfo() {\n        Map<String, String[]> requestParams = new HashMap<>(1);\n        requestParams.put(SCHEMA_DATACENTER_NAME, new String[]{\"cn\"});\n        IndexTemplateListResponse response = HttpClient.forward(adminUrl + TEMPLATE_INFO_SUFFIX, \"GET\", null, headerParams, requestParams, IndexTemplateListResponse.class);\n\n        if (response.getCode() != 0) {\n            bootLogger.error(\"resetTemplateInfo error, code={}, message={}\", response.getCode(), response.getMessage());\n            throw new ServerException(\"resetTemplateInfo error\");\n        }\n\n        if (response.getData().size() < QueryConsts.MIN_TEMPLATE_NUMBER) {\n            bootLogger.error(\"resetTemplateInfo exception, template size={}\", response.getData().size());\n            throw new ServerException(\"resetTemplateInfo error\");\n        }\n        return response;\n    }\n\n    @Override\n    public DynamicConfigListResponse listQueryConfig() {\n        DynamicConfigListResponse response = HttpClient.forward(adminUrl + CONFIG_LIST_SUFFIX, \"POST\", GATEWAY_DYNAMIC_CONFIG, headerParams, null, DynamicConfigListResponse.class);\n        if (response.getCode() != 0) {\n            bootLogger.error(\"AdminSchedule resetDynamicConfigInfo error, code={}, message={}\", response.getCode(), response.getMessage());\n        }\n        return response;\n    }\n\n    @Override\n    public void heartbeat(String clusterName, String hostName, Integer port) {\n        String heartBeatBody = String.format(\"{\\\"clusterName\\\":\\\"%s\\\",\\\"hostName\\\":\\\"%s\\\",\\\"port\\\":%d}\", clusterName, hostName, port);\n        BaseAdminResponse response = HttpClient.forward(adminUrl + GATEWAY_HEARTBEAT_SUFFIX, \"PUT\", heartBeatBody, headerParams, null, BaseAdminResponse.class);\n        if (response.getCode() != 0) {\n            bootLogger.error(\"HeartBeatSchedule heartbeat error, code={}, message={}\", response.getCode(), response.getMessage());\n        }\n    }\n\n    @Override\n    public DSLTemplateListResponse listDslTemplates(long lastModifyTime, String scrollId) {\n        String queryStr = StringUtils.isBlank(scrollId) ?\n                String.format(DSL_QUERY_FIRST_PARAMS, DSL_TEMPLATE_VERSION, lastModifyTime) :\n                String.format(DSL_QUERY_PARAMS, DSL_TEMPLATE_VERSION, lastModifyTime, scrollId);\n        DSLTemplateListResponse dslTemplateListResponse = HttpClient.forward(adminUrl + GET_DSL_TEMPLATES_SUFFIX, \"POST\", queryStr, null, null,DSLTemplateListResponse.class);\n\n        if (dslTemplateListResponse.getCode() != 0) {\n            bootLogger.error(\"resetDSLInfo get dsl list error, code={}, message={}\", dslTemplateListResponse.getCode(), dslTemplateListResponse.getMessage());\n            throw new ServerException(\"resetDSLInfo get dsl list error\");\n        }\n        return dslTemplateListResponse;\n    }\n\n    @Override\n    public TempaletAliasResponse addAdminTemplateAlias(TemplateAlias templateAlias) {\n        return HttpClient.forward(adminUrl + ADD_TEMPLATE_ALIAS, \"POST\", JSON.toJSONString(templateAlias), headerParams, null,\n                TempaletAliasResponse.class);\n    }\n\n    @Override\n    public TempaletAliasResponse delAdminTemplateAlias(TemplateAlias templateAlias) {\n        return HttpClient.forward(adminUrl + DEL_TEMPLATE_ALIAS, \"DELETE\", JSON.toJSONString(templateAlias), headerParams, null,\n                TempaletAliasResponse.class);\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/ActiveCountResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class ActiveCountResponse extends BaseAdminResponse {\n\tprivate int data;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/AliasesInfoResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n* @author weizijun\n* @date：2017年2月13日\n* \n*/\n@Data\n@NoArgsConstructor\npublic class AliasesInfoResponse {\n\tprivate String name;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/AppDetailResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n* @author weizijun\n* @date：2016年8月18日\n* \n*/\n@Data\n@NoArgsConstructor\npublic class AppDetailResponse {\n\tprivate int id;\n\tprivate String name;\n\tprivate Integer projectId;\n\tprivate List<String> indexExp;\n\tprivate List<String> windexExp;\n\tprivate String verifyCode;\n\tprivate List<String> ip;\n\tprivate String cluster;\n\tprivate int queryThreshold;\n\tprivate int isRoot;\n\n\t/**\n\t * 是否生效DSL分析查询限流值 1为生效DSL分析查询限流值，0不生效DSL分析查询限流值\n\t */\n\tprivate int      dslAnalyzeEnable;\n\t\n\t/**\n\t * 是否索引存储分离，1为分离，0为不分离\n\t */\n\tprivate int      isSourceSeparated;\n\n\t/**\n\t * 是否生效聚合查询分析，0为不生效，1为生效\n\t */\n\tprivate int aggrAnalyzeEnable;\n\n\t/**\n\t * 是否生效记录响应结果的索引列表, 0为不生效，1为生效\n\t */\n\tprivate int analyzeResponseEnable;\n\n\t/**\n\t * appid查询方式，0为集群模式，1为索引模式\n\t */\n\tprivate int searchType;\n\t\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/AppListResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n* @author weizijun\n* @date：2016年8月18日\n* \n*/\n@Data\n@NoArgsConstructor\npublic class AppListResponse extends BaseAdminResponse {\n\tprivate List<AppDetailResponse> data;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/BaseAdminResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n* @author weizijun\n* @date：2016年8月18日\n* \n*/\n@Data\n@NoArgsConstructor\npublic class BaseAdminResponse {\n\tprotected int code;\n\tprotected String message;\n\tprivate String version;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/BaseInfoResponse.java",
    "content": "\npackage com.didi.arius.gateway.remote.response;\n\nimport com.google.gson.annotations.Expose;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\npublic class BaseInfoResponse {\n\n    /**\n     * 逻辑模板ID\n     */\n    @Expose\n    private Integer     id;\n\n    @Expose\n    private String dateField;\n    @Expose\n    private String dateFormat;\n    @Expose\n    private String department;\n    @Expose\n    private Long expireTime;\n    @Expose\n    private String expression;\n    @Expose\n    private Boolean isDefaultRouting;\n    @Expose\n    private String responsible;\n    @Expose\n    private Integer version;\n\n    private Integer deployStatus;\n\n    private String ingestPipeline;\n\n    private List<String> aliases;\n\n    private Boolean blockRead;\n\n    private Boolean blockWrite;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/DSLTemplateListResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class DSLTemplateListResponse extends BaseAdminResponse {\n    private DSLTemplateWrapResponse data;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/DSLTemplateResponse.java",
    "content": "\npackage com.didi.arius.gateway.remote.response;\n\n\nimport com.google.gson.Gson;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class DSLTemplateResponse {\n    /**\n     * es _id\n     */\n    private String key;\n\n    /**\n     * 查询模板创建时间\n     */\n    private String ariusCreateTime;\n    /**\n     * 查询模板修改时间\n     */\n    private String ariusModifyTime;\n    /**\n     * 平均响应长度\n     */\n    private Double responseLenAvg;\n    /**\n     * 请求类型\n     */\n    private String requestType;\n    /**\n     * 查询类型\n     */\n    private String searchType;\n    /**\n     * 查询次数(分钟级别)\n     */\n    private Long searchCount;\n    /**\n     * es查询耗时\n     */\n    private Double esCostAvg;\n    /**\n     * 平均查询语句长度\n     */\n    private Double dslLenAvg;\n    /**\n     * 平均命中记录数\n     */\n    private Double totalHitsAvg;\n    /**\n     * 平均查询shard成功个数\n     */\n    private Double successfulShardsAvg;\n    /**\n     * 平均shard成功个数\n     */\n    private Double totalShardsAvg;\n    /**\n     * 查询请求时刻\n     */\n    private String logTime;\n    /**\n     * 查询索引示例\n     */\n    private String indiceSample;\n    /**\n     * 查询模板\n     */\n    private String dslTemplate;\n    /**\n     * 查询请求时刻\n     */\n    private Long timeStamp;\n    /**\n     * 查询语句类型\n     */\n    private String dslType;\n    /**\n     * 查询索引名称\n     */\n    private String indices;\n    /**\n     * 查询模板MD5\n     */\n    private String dslTemplateMd5;\n    /**\n     * 平均查询总耗时\n     */\n    private Double totalCostAvg;\n    /**\n     * 查询shard失败个数\n     */\n    private Double failedShardsAvg;\n    /**\n     * dsink写入时间\n     */\n    private Long sinkTime;\n    /**\n     * appid\n     */\n    private Integer appid;\n    /**\n     * 查询语句\n     */\n    private String dsl;\n    /**\n     * 平均gateway处理耗时\n     */\n    private Double beforeCostAvg;\n    /**\n     * flink写入时刻\n     */\n    private String flinkTime;\n    /**\n     * 查询限流\n     */\n    private Double queryLimit;\n    /**\n     * 是否来自用户控制台\n     */\n    private Boolean isFromUserConsole;\n    /**\n     * 是否强制设置查询限流值\n     */\n    private Boolean forceSetQueryLimit;\n    /**\n     * 是否可用 null/true表示可用，false表示不可用\n     */\n    private Boolean enable;\n    /**\n     * 黑白名单 null/white表示白名单，black表示黑名单\n     */\n    private String checkMode;\n    /**\n     * 慢查dsl阈值，单位为ms\n     */\n    private Long slowDslThreshold;\n    /**\n     * 查询模板版本号\n     */\n    private String version;\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/DSLTemplateWrapResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\npublic class DSLTemplateWrapResponse {\n    private List<DSLTemplateResponse> dslTemplatePoList;\n\n    private String scrollId;\n\n    public List<DSLTemplateResponse> getData() {\n        return dslTemplatePoList;\n    }\n\n    public void setData(List<DSLTemplateResponse> data) {\n        this.dslTemplatePoList = data;\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/DataCenterListResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n* @author weizijun\n* @date：2016年10月31日\n* \n*/\n@Data\n@NoArgsConstructor\npublic class DataCenterListResponse extends BaseAdminResponse {\n\tprivate List<DataCenterResponse> data;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/DataCenterResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * @author weizijun\n * @date：2016年10月31日\n */\n@Data\n@NoArgsConstructor\npublic class DataCenterResponse {\n    /**\n     *\n     */\n    private long id;\n    /**\n     *\n     */\n    private String cluster;\n    /**\n     *\n     */\n    private String readAddress;\n    /**\n     *\n     */\n    private String httpAddress;\n    /**\n     *\n     */\n    private String writeAddress;\n    /**\n     *\n     */\n    private String httpWriteAddress;\n    /**\n     *\n     */\n    private String desc;\n    /**\n     *\n     */\n    private int type;\n    /**\n     *\n     */\n    private String esVersion;\n    /**\n     *\n     */\n    private String password;\n\n    private int runMode;\n    private String writeAction;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/DynamicConfigListResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\npublic class DynamicConfigListResponse extends BaseAdminResponse {\n    private List<DynamicConfigResponse> data;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/DynamicConfigResponse.java",
    "content": "\npackage com.didi.arius.gateway.remote.response;\n\nimport com.google.gson.annotations.Expose;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport javax.annotation.Generated;\n\n@Data\n@NoArgsConstructor\n@Generated(\"net.hexar.json2pojo\")\n@SuppressWarnings(\"unused\")\npublic class DynamicConfigResponse {\n\n    @Expose\n    private Long createTime;\n    @Expose\n    private Long dimension;\n    @Expose\n    private Long edit;\n    @Expose\n    private Long id;\n    @Expose\n    private String memo;\n    @Expose\n    private Long status;\n    @Expose\n    private Long updateTime;\n    @Expose\n    private String value;\n    @Expose\n    private String valueGroup;\n    @Expose\n    private String valueName;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/IndexTemplateListResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\n\n@Data\n@NoArgsConstructor\npublic class IndexTemplateListResponse extends BaseAdminResponse {\n    private Map<String, IndexTemplateResponse> data;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/IndexTemplateResponse.java",
    "content": "\npackage com.didi.arius.gateway.remote.response;\n\nimport com.google.gson.annotations.Expose;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n@Data\n@NoArgsConstructor\npublic class IndexTemplateResponse {\n\n    @Expose\n    private BaseInfoResponse baseInfo;\n    @Expose\n    private MasterInfoResponse masterInfo;\n    @Expose\n    private List<SlaveInfoResponse> slaveInfos;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/LargeFiledListResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\n\n@Data\n@NoArgsConstructor\npublic class LargeFiledListResponse extends BaseAdminResponse {\n\tprivate Map<String, Map<String, FieldInfo>> data;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/MasterInfoResponse.java",
    "content": "\npackage com.didi.arius.gateway.remote.response;\n\nimport com.google.gson.annotations.Expose;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\nimport java.util.Map;\n\n@Data\n@NoArgsConstructor\npublic class MasterInfoResponse {\n\n    @Expose\n    private List<Integer> accessApps;\n    @Expose\n    private String cluster;\n    @Expose\n    private String templateName;\n    @Expose\n    private Long templateId;\n    @Expose\n    private String topic;\n\n    /**\n     * 用于索引多type改造   是否启用索引名称映射 0 禁用 1 启用\n     */\n    @Expose\n    private Boolean mappingIndexNameEnable;\n\n    /**\n     * 多type索引type名称到单type索引模板名称的映射\n     */\n    @Expose\n    private Map<String/*typeName*/,String/*templateName*/> typeIndexMapping;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/SlaveInfoResponse.java",
    "content": "\npackage com.didi.arius.gateway.remote.response;\n\nimport com.google.gson.annotations.Expose;\nimport java.util.List;\nimport java.util.Map;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n@Data\n@NoArgsConstructor\npublic class SlaveInfoResponse {\n\n    @Expose\n    private List<Integer> accessProjects;\n    @Expose\n    private String        cluster;\n    @Expose\n    private Long templateId;\n    @Expose\n    private String templateName;\n    @Expose\n    private String topic;\n\n    /**\n     * 用于索引多type改造   是否启用索引名称映射 0 禁用 1 启用\n     */\n    @Expose\n    private Boolean mappingIndexNameEnable;\n\n    /**\n     * 多type索引type名称到单type索引模板名称的映射\n     */\n    @Expose\n    private Map<String/*typeName*/,String/*templateName*/> typeIndexMapping;\n\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/TempaletAliasResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\npublic class TempaletAliasResponse extends BaseAdminResponse {\n\n    private Boolean data;\n\n    public Boolean getData() {\n        return data;\n    }\n\n    public void setData(Boolean data) {\n        this.data = data;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/TemplateInfoListResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\n\n/**\n* @author weizijun\n* @date：2017年2月13日\n* \n*/\n@Data\n@NoArgsConstructor\npublic class TemplateInfoListResponse extends BaseAdminResponse {\n\tprivate Map<String, TemplateInfoResponse> data;\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/main/java/com/didi/arius/gateway/remote/response/TemplateInfoResponse.java",
    "content": "package com.didi.arius.gateway.remote.response;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.List;\n\n/**\n* @author weizijun\n* @date：2017年2月13日\n* \n*/\n@Data\n@NoArgsConstructor\npublic class TemplateInfoResponse {\n\tprivate int id;\n\tprivate String expression;\n\tprivate List<AliasesInfoResponse> aliases;\n\tprivate DataCenterResponse dataCluster;\n\tprivate int version;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-remote/src/test/java/com/didi/arius/gateway/remote/AriusGatewayRemoteApplicationTests.java",
    "content": "package com.didi.arius.gateway.remote;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@SpringBootTest\nclass AriusGatewayRemoteApplicationTests {\n\n    @Test\n    void contextLoads() {\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/APP_META/990-startapp.required.sh",
    "content": "#!/bin/bash\n\nSERVICE_PATH=\"/home/xiaoju/${APPNAME}\"\n\n#nginx logs ln\nif [ ! -L /home/xiaoju/nginx/logs ]; then\n    rm -rf /home/xiaoju/nginx/logs\n    mkdir -p /home/xiaoju/data1/nginx-logs && \\\n    ln -s /home/xiaoju/data1/nginx-logs /home/xiaoju/nginx/logs\nfi\n\nif [ -f \"/home/xiaoju/$APPNAME/.deploy/service.json\" ]; then\n    # cp service.json for nginx metric collect.\n    su xiaoju -c \"mkdir -p /home/xiaoju/nginx/.deploy && cp /home/xiaoju/$APPNAME/.deploy/service.json /home/xiaoju/nginx/.deploy\"\nfi\n\nif [[ \"x$env\" == \"xtest\" || \"x$env\" == \"xstable\" ]] && [ ! -f \"/home/xiaoju/$APPNAME/.deploy/service.cluster.txt\" ]; then\n    su xiaoju -c \"mkdir -p /home/xiaoju/$APPNAME/.deploy && touch /home/xiaoju/$APPNAME/.deploy/service.cluster.txt && echo $env >> /home/xiaoju/$APPNAME/.deploy/service.cluster.txt\"\n    su logger -c \"touch /home/logger/swan-log-collector/var/crtfile &&  sh /home/logger/swan-log-collector/bin/stop.sh\"\nfi\n\n#tomcat logs ln\nif [ ! -L /home/xiaoju/tomcat/logs ]; then\n    rm -rf /home/xiaoju/tomcat/logs\n    mkdir -p /home/xiaoju/data1/tomcat-logs && \\\n    ln -s /home/xiaoju/data1/tomcat-logs /home/xiaoju/tomcat/logs\nfi\n\n#application logs ln\nif [ ! -L /home/xiaoju/${APPNAME}/logs ]; then\n    mkdir -p /home/xiaoju/data1/${APPNAME}-logs && \\\n    ln -s /home/xiaoju/data1/${APPNAME}-logs /home/xiaoju/${APPNAME}/logs\nfi\n\nif [ ! -L /data1 ]; then\n    ln -s /home/xiaoju/data1 /data1\nfi\n\nchown -R  xiaoju.xiaoju /home/xiaoju/data1/\nchown -R  xiaoju.xiaoju /data1/\n\nmkdir -p '/etc/odin-super-agent/'; echo 'consul-client' >> /etc/odin-super-agent/agents.deny; chmod +x /home/odin/super-agent/data/install/consul-client/current/control &&  /home/odin/super-agent/data/install/consul-client/current/control stop\nsudo su - xiaoju -c \"cd $SERVICE_PATH && chmod +x control.sh && ./control.sh start\"\n\n/usr/bin/monit -c /etc/monitrc\n\nif [[ \"x$env\" == \"xtest\" || \"x$env\" == \"xstable\" ]]; then\n    /usr/sbin/sshd -D\nfi\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/APP_META/990-stopapp.sh",
    "content": "#!/bin/bash\n\nSERVICE_PATH=\"/home/xiaoju/${APPNAME}\"\n\n/usr/bin/monit stop all\n\nsu xiaoju -c \"cd $SERVICE_PATH && ./control.sh stop\"\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/APP_META/990-webterminal.sh",
    "content": "#!/bin/bash\n\n# start web-terminal\nif [[ \"x$env\" == \"xtest\" || \"x$env\" == \"xstable\" ]] ; then\n    # prepare web-terminal environment\n    mkdir -p /home/xiaoju/local\n    curl --connect-timeout 5 -m 30 -o /home/xiaoju/local/node-v8.9.4-linux-x64-web-terminal.tar.gz https://artifactory.intra.xiaojukeji.com:443/artifactory/oe-release-local/webterminal/node-v8.9.4-linux-x64-web-terminal.tar.gz\n    export PATH=/home/xiaoju/local/node-v8.9.4-linux-x64-web-terminal/bin:$PATH\n    cd /home/xiaoju/local && tar xvzf node-v8.9.4-linux-x64-web-terminal.tar.gz\n    cd /home/xiaoju/local/node-v8.9.4-linux-x64-web-terminal/web-terminal-client && pm2 start pm2_deploy.json\n    cd /home/xiaoju/local/node-v8.9.4-linux-x64-web-terminal/web-terminal-monit && pm2 start pm2_deploy.json\nelse\n    echo \"skip install web-terminal service on prod env\"\nfi\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/APP_META/Dockerfile",
    "content": "FROM registry.xiaojukeji.com/didionline/bigdatadatabus-didi-jdk8-tomcat-nginx-centos6:stable\nMAINTAINER zhuyefeng <zhuyefeng@didichuxing.com>\n\nENV JAVA_HOME /usr/local/jdk1.8.0_65\n# TODO 设置模块名字\nENV APPNAME arius-gateway-rest\n\nRUN mkdir -p /etc/container/prestop\nADD ./APP_META/nginx/conf/nginx.conf /home/xiaoju/nginx/conf/\nADD ./APP_META/monit/monitrc /etc/monitrc\nADD ./APP_META/monit/nginx.cfg /etc/monit.d/\nADD ./APP_META/990-startapp.required.sh /etc/container/init/990-startapp.required.sh\nADD ./APP_META/990-stopapp.sh /etc/container/prestop/990-stopapp.sh\n\nRUN mkdir -p /home/xiaoju/${APPNAME} && \\\n    # TODO 如果tomcat容器应用需要下面这步\n    # mkdir -p /home/xiaoju/tomcat/webapps && \\\n    chmod 0700 /etc/monitrc && \\\n    chmod a+x /etc/container/init/990-startapp.required.sh && \\\n    chmod a+x /etc/container/prestop/990-stopapp.sh\n\nCOPY ./home-xiaoju-${APPNAME} /home/xiaoju/${APPNAME}\n\nRUN yum install mysql\n\n# TODO 如果tomcat容器应用需要下面这步\n#RUN ln -s /home/xiaoju/${APPNAME} /home/xiaoju/tomcat/webapps/\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/APP_META/DockerfileOffline",
    "content": "FROM registry.xiaojukeji.com/didionline/bigdatadatabus-didi-jdk8-tomcat-nginx-centos7:stable\nMAINTAINER zhuyefeng <zhuyefeng@didichuxing.com>\n\nENV JAVA_HOME /usr/local/jdk1.8.0_65\n# TODO 设置模块名字\nENV APPNAME arius-gateway-rest\n\nRUN mkdir -p /etc/container/prestop\nADD ./APP_META/nginx/conf/nginx.conf /home/xiaoju/nginx/conf/ \nADD ./APP_META/990-startapp.required.sh /etc/container/init/990-startapp.required.sh\nADD ./APP_META/990-stopapp.sh /etc/container/prestop/990-stopapp.sh\nADD ./APP_META/990-webterminal.sh  /etc/container/init/990-webterminal.required.sh\n\nRUN rpm --rebuilddb && yum --enablerepo=didi_op_toa install -y openssh-server openssl-devel passwd\nRUN sed -i 's/#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config && \\\n    echo -e 'y\\n' | ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N '' && \\\n    echo -e 'y\\n' | ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' && \\\n    mkdir -p /var/run/sshd\n\nRUN mkdir -p /home/xiaoju/${APPNAME} && \\\n    # TODO 如果tomcat容器应用需要下面这步\n    # mkdir -p /home/xiaoju/tomcat/webapps && \\\n    chmod a+x /etc/container/init/990-startapp.required.sh && \\\n    chmod a+x /etc/container/prestop/990-stopapp.sh && \\\n    chmod a+x /etc/container/init/990-webterminal.required.sh\n\n#COPY ./home-xiaoju-${APPNAME} /home/xiaoju/${APPNAME}\nCOPY . /home/xiaoju/${APPNAME}\n\n# TODO 如果tomcat容器应用需要下面这步\n#RUN ln -s /home/xiaoju/${APPNAME} /home/xiaoju/tomcat/webapps/\n\nRUN echo -e 'diditest@bdt\\ndiditest@bdt' | passwd root\nexpose 22\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/APP_META/clean_nginx_log.sh",
    "content": "log_dir=\"/home/xiaoju/nginx/logs\"\ndate=`date +%Y%m%d`\ndate_rm=`date +%Y%m%d -d '3 days ago'`\nmv ${log_dir}/access.log  ${log_dir}/${date}_access.log\n/home/xiaoju/nginx/sbin/nginx -s reopen\nrm -f ${log_dir}/${date_rm}_access.log"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/APP_META/monit/monitrc",
    "content": "set daemon  10              # check services at 10 seconds intervals\nset log syslog\n\nset httpd port 2812 and\n    use address localhost  # only accept connection from localhost\n    allow localhost        # allow localhost to connect to the server and\n    allow admin:monit      # require user 'admin' with password 'monit'\n    #with ssl {            # enable SSL/TLS and set path to server certificate\n    #    pemfile: /etc/ssl/certs/monit.pem\n    #}\n\ninclude /etc/monit.d/*\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/APP_META/monit/nginx.cfg",
    "content": "check process nginx with pidfile /home/xiaoju/nginx/run/nginx.pid\n       start = \"/etc/container/init/990-startapp.required.sh\" with timeout 15 seconds\n       stop  = \"/etc/container/prestop/990-stopapp.sh\" with timeout 60 seconds\n       group xiaoju\n       if failed\n          host 127.0.0.1\n          port 8010\n          type tcp\n          then exec \"/home/xiaoju/nginx/load.sh stop\"\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/APP_META/nginx/conf/nginx-pre-v3-cn.conf",
    "content": "#user xiaoju xiaoju;\n\nworker_rlimit_nofile 204800;\nworker_processes 4;\nerror_log /home/xiaoju/nginx/logs/error.log;\npid /home/xiaoju/nginx/run/nginx.pid;\n\n# Load dynamic modules. See /usr/share/nginx/README.dynamic.\ninclude /home/xiaoju/nginx/modules/*.conf;\n\n\nevents {\n    use epoll;\n    worker_connections  204800;\n\n    accept_mutex on;\n    accept_mutex_delay 5ms;\n    multi_accept on;\n}\n\n\nhttp {\n    include       mime.types;\n    default_type  application/octet-stream;\n\n    server_names_hash_bucket_size 128;\n    #server_tag off;\n    #server_info off;\n    server_tokens off;\n\n    sendfile        on;\n    tcp_nopush      on;\n    tcp_nodelay     on;\n\n    fastcgi_connect_timeout 5;\n    fastcgi_send_timeout 10;\n    fastcgi_read_timeout 10;\n    fastcgi_buffer_size 64k;\n    fastcgi_buffers 4 64k;\n    fastcgi_busy_buffers_size 128k;\n    fastcgi_temp_file_write_size 128k;\n\n    keepalive_timeout  60;\n    keepalive_requests 1024;\n    client_header_buffer_size 4k;\n    large_client_header_buffers 4 32k;\n    client_max_body_size 100m;\n\n    client_body_buffer_size 512k;\n    client_body_timeout 45;\n    client_header_timeout 10;\n    send_timeout 240;\n\n    proxy_connect_timeout   10s;\n    proxy_send_timeout      120s;\n    proxy_read_timeout      120s;\n    proxy_buffers           64 8k;\n    proxy_busy_buffers_size    128k;\n    proxy_temp_file_write_size 64k;\n    proxy_redirect off;\n    # proxy_next_upstream_tries 1;\n    proxy_next_upstream error invalid_header timeout http_502 http_504;\n\n    gzip on;\n    gzip_min_length 1k;\n    gzip_buffers 4 16k;\n    gzip_http_version 1.0;\n    gzip_comp_level 4;\n    gzip_types text/plain application/x-javascript text/css text/xml application/xml+css application/json text/javascript;\n    gzip_vary on;\n\n    proxy_set_header X-Real-IP $remote_addr;\n    proxy_set_header X-Real-Port $remote_port;\n    proxy_set_header Host $http_host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    proxy_pass_header Server;\n\n    #operationid on;\n    #operationid_header didi-header-rid;\n    #operationid_eth eth0;\n    #proxy_set_header didi-header-rid $operationid;\n\n    log_format main '$server_addr\\t$host\\t'\n        '$remote_addr\\t$http_x_forwarded_for\\t'\n        '$time_local\\t'\n        '$scheme\\t$request\\t'\n        '$status\\t$upstream_status\\t'\n        '$request_time\\t$upstream_addr\\t$upstream_response_time\\t'\n        '$request_length\\t$bytes_sent\\t'\n        '$http_referer\\t$http_cookie\\t$http_user_agent\\t'\n        '$limit_rate\\t$http_didi_header_omgid\\t$remote_port';\n\n\n    set_real_ip_from 10.0.0.0/8;\n    set_real_ip_from 100.64.0.0/10;\n    real_ip_header X-Real-IP;\n\n    server {\n        listen       8080 backlog=4096;\n        underscores_in_headers on;\n        server_name  localhost;\n        access_log logs/access.log main;\n\n        location /index.html {\n            proxy_pass http://10.88.128.23:8002/static/bp_fe_pre/bigdata_cloud_logi_es_manager_fe/gn/index.html;\n            proxy_hide_header Cache-Control;\n            add_header Cache-Control  \"no-cache\";\n        }\n\n        location / {\n            rewrite ^.*$ /index.html;\n        }\n\n        # gateway\n        location ~ ^/_sql {\n          proxy_pass http://10.85.129.96:20055;\n        }   \n\n        # admin\n        location ~ ^/api/es/admin/ {\n           rewrite ^/api/es/admin/(.*)$ /admin/api/$1 break;\n           proxy_pass http://127.0.0.1:8010;\n        }\n\n        # kibana\n        location ^~ /console/arius/kibana7/ {\n            proxy_set_header Upgrade $http_upgrade;\n            proxy_set_header Connection 'upgrade';\n            proxy_set_header Host $host;\n            proxy_set_header X-Real-IP $remote_addr;\n            proxy_set_header X-NginX-Proxy true;\n            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n            proxy_set_header Authorization 'Basic $cookie_Authorization';\n            proxy_pass_request_headers on;\n            proxy_cache_bypass $http_upgrade $http_authorization;\n            proxy_pass http://10.88.128.149:31522/;\n            rewrite ^/console/arius/kibana7/(.*)$ /$1 break;\n        }\n\n        location = /status.do {\n            root /home/xiaoju/nginx/html;\n        }\n\n        error_page   500 502 503 504  /50x.html;\n        location = /50x.html {\n            root   html;\n        }\n    }\n\n    include conf.d/*.conf;\n    #   include servers/*.conf;\n    #   include server_conf/*.conf;\n    #   include upstream_conf/*.conf;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/APP_META/nginx/conf/nginx.conf",
    "content": "#user xiaoju xiaoju;\n\nworker_rlimit_nofile 204800;\nworker_processes 4;\nerror_log /home/xiaoju/nginx/logs/error.log;\npid /home/xiaoju/nginx/run/nginx.pid;\n\n# Load dynamic modules. See /usr/share/nginx/README.dynamic.\ninclude /home/xiaoju/nginx/modules/*.conf;\n\n\nevents {\n    use epoll;\n    worker_connections  204800;\n\n    accept_mutex on;\n    accept_mutex_delay 5ms;\n    multi_accept on;\n}\n\n\nhttp {\n    include       mime.types;\n    default_type  application/octet-stream;\n\n    server_names_hash_bucket_size 128;\n    #server_tag off;\n    #server_info off;\n    server_tokens off;\n\n    sendfile        on;\n    tcp_nopush      on;\n    tcp_nodelay     on;\n\n    fastcgi_connect_timeout 5;\n    fastcgi_send_timeout 10;\n    fastcgi_read_timeout 10;\n    fastcgi_buffer_size 64k;\n    fastcgi_buffers 4 64k;\n    fastcgi_busy_buffers_size 128k;\n    fastcgi_temp_file_write_size 128k;\n\n    keepalive_timeout  60;\n    keepalive_requests 1024;\n    client_header_buffer_size 4k;\n    large_client_header_buffers 4 32k;\n    client_max_body_size 200m;\n\n    client_body_buffer_size 512k;\n    client_body_timeout 45;\n    client_header_timeout 10;\n    send_timeout 240;\n\n    proxy_connect_timeout   10s;\n    proxy_send_timeout      120s;\n    proxy_read_timeout      120s;\n    proxy_buffers           64 8k;\n    proxy_busy_buffers_size    128k;\n    proxy_temp_file_write_size 64k;\n    proxy_redirect off;\n    # proxy_next_upstream_tries 1;\n    proxy_next_upstream error invalid_header timeout http_502 http_504;\n\n    gzip on;\n    gzip_min_length 1k;\n    gzip_buffers 4 16k;\n    gzip_http_version 1.0;\n    gzip_comp_level 2;\n    gzip_types text/plain application/x-javascript text/css text/xml application/xml+css application/json text/javascript;\n    gzip_vary on;\n\n    proxy_set_header X-Real-IP $remote_addr;\n    proxy_set_header X-Real-Port $remote_port;\n    proxy_set_header Host $http_host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    proxy_pass_header Server;\n\n    #operationid on;\n    #operationid_header didi-header-rid;\n    #operationid_eth eth0;\n    #proxy_set_header didi-header-rid $operationid;\n\n    log_format main '$server_addr\\t$host\\t'\n                 '$remote_addr\\t$http_x_forwarded_for\\t'\n                 '$time_local\\t'\n                 '$scheme\\t$request\\t'\n                 '$status\\t$upstream_status\\t'\n                 '$request_time\\t$upstream_addr\\t$upstream_response_time\\t'\n                 '$request_length\\t$bytes_sent\\t'\n                 '$http_referer\\t$http_cookie\\t$http_user_agent\\t'\n                 '$limit_rate\\t$http_didi_header_omgid\\t$remote_port';\n\n\n    set_real_ip_from 10.0.0.0/8;\n    set_real_ip_from 100.64.0.0/10;\n    real_ip_header X-Real-IP;\n\n    server {\n        listen       8080 backlog=4096;\n        server_name  localhost;\n        access_log logs/access.log main;\n\n        location = /status.do {\n          root /home/xiaoju/nginx/html;\n    }\n\n        location / {\n            proxy_pass http://127.0.0.1:8010;\n        }\n\n        error_page   500 502 503 504  /50x.html;\n        location = /50x.html {\n            root   html;\n        }\n    }\n\n     include conf.d/*.conf;\n #   include servers/*.conf;\n #   include server_conf/*.conf;\n #   include upstream_conf/*.conf;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/control.sh",
    "content": "#!/bin/bash\n#############################################\n## main\n## 非托管方式, 启动服务\n## control.sh脚本, 必须实现start和stop两个方法\n#############################################\nworkspace=$(cd $(dirname $0) && pwd -P)\ncd ${workspace}\n\n\n# TODO 设置模块名字\nmodule=arius-gateway-rest\napp=${module}\n\ncfgname=config\ncfg=\"$workspace/WEB-INF/classes/${cfgname}.properties\"\ncfgdir=\"$workspace/WEB-INF/classes\"\nlogfile=${workspace}/var/app.log\npidfile=${workspace}/var/app.pid\n#export CATALINA_PID=${pidfile}\n\n#nginx check\n# TODO 如果不需要nginx服务，请设置NGINX_CHECK=0\nNGINX_CHECK=1\nLOCAL_CHECK=0\nenv=online\nsource ./nginxfunc.sh\nnginx_conf=\"nginx.conf\"\n\n## function\nfunction start() {\n    # 创建日志目录\n    mkdir -p var &>/dev/null\n\n    rm -rf ${pidfile}\n\n    # check服务是否存活,如果存在则返回\n    check_pid\n    if [ $? -ne 0 ];then\n        local pid=$(get_pid)\n        echo \"${app} is started, pid=${pid}\"\n        return 0\n    fi\n\n    # XXX 如果各个机房节点级别有差异使用如下方式\n    # cfg\n    local clusterfile=\"$workspace/.deploy/service.cluster.txt\"\n    if [[ -f \"$clusterfile\" ]]; then\n        local cluster=`cat $clusterfile`\n        if [[ $cluster == \"hnc-pre-v\" ]]; then\n            env=pre\n        elif [[ \"x$cluster\" == \"xtest\" || \"x$cluster\" == \"xstable\" ]]; then\n            env=$cluster\n        fi\n    else\n        echo \"$clusterfile is not existed!!!\"\n        exit 1\n    fi\n\n    # 以后台方式 启动程序\n    echo -e \"Starting the $module in $env...\\c\"\n\n    ### XXX JAVA类程序启停\n    echo \"start application with env:$env\"\n\n    if [[ $cluster == \"test\" ]]; then\n        nohup java -Xmx8g -Xms8g -Xmn3g -XX:MaxDirectMemorySize=2G -XX:MaxMetaspaceSize=256M -Djdk.nio.maxCachedBufferSize=262144 -jar $module.jar --spring.profiles.active=$env &\n    else\n        nohup java -Xmx8g -Xms8g -Xmn3g -XX:MaxDirectMemorySize=2G -XX:MaxMetaspaceSize=256M -Djdk.nio.maxCachedBufferSize=262144 -jar $module.jar --spring.profiles.active=$env &\n    fi\n\n    # 保存pid到pidfile文件中\n    echo $! > ${pidfile}\n\n    # 检查服务是否启动成功\n    check_pid\n    if [ $? -eq 0 ];then\n        echo \"${app} start failed, please check!!!\"\n        exit 1\n    fi\n\n    echo \"${app} start ok, pid=${pid}\"\n    # 启动成功, 退出码为 0\n    return 0\n}\n\nfunction stop() {\n    local timeout=60\n    # 循环stop服务, 直至60s超时\n    for (( i = 0; i < $timeout; i++ )); do\n        # 检查服务是否停止,如果停止则直接返回\n        check_pid\n        if [ $? -eq 0 ];then\n            echo \"${app} is stopped\"\n            rm -rf ${pidfile}\n            return 0\n        fi\n        # 检查pid是否存在\n        local pid=$(get_pid)\n        if [ ${pid} == \"\" ];then\n            echo \"${app} is stopped, can't find pid on ${pidfile}\"\n            exit 0\n        fi\n\n        # 停止该服务\n        if [ $i -eq $((timeout-1)) ]; then\n            kill -9 ${pid} &>/dev/null\n        else\n            kill ${pid} &>/dev/null\n        fi\n        # 检查该服务是否停止ok\n        check_pid\n        if [ $? -eq 0 ];then\n            # stop服务成功, 返回码为 0\n            echo \"${app} stop ok\"\n            rm -rf ${pidfile}\n            exit 0\n        fi\n        # 服务未停止, 继续循环\n        sleep 1\n    done\n\n    rm -rf ${pidfile}\n\n    # stop服务失败, 返回码为 非0\n    echo \"stop timeout(${timeout}s)\"\n    return 1\n}\n\nfunction update() {\n    echo \"update service\"\n    exit 0\n}\n\nfunction status(){\n    check_pid\n    local running=$?\n    if [ ${running} -ne 0 ];then\n        local pid=$(get_pid)\n        echo \"${app} is started, pid=${pid}\"\n    else\n        echo \"${app} is stopped\"\n    fi\n    exit 0\n}\n\n## internals\nfunction get_pid() {\n    if [ -f $pidfile ];then\n        cat $pidfile\n        #pid=$(cat $pidfile | sed 's/ //g')\n        #(ps -fp $pid | grep $app &>/dev/null) && echo $pid\n    fi\n}\n\nfunction check_pid() {\n    pid=$(get_pid)\n    if [ \"x_\" != \"x_${pid}\" ]; then\n        running=$(ps -p ${pid}|grep -v \"PID TTY\" |wc -l)\n        return ${running}\n    fi\n    return 0\n}\n\nfunction filebeat_start(){\n    echo \"start filebeat\"\n\n    cd filebeat/filebeat\n\n    tar -xvf filebeat-7.6.2-linux-x86_64.tar.gz\n\n    if [[ $env == \"test\" ]]; then\n        cp filebeat-test.yml filebeat-7.6.2-linux-x86_64/filebeat.yml\n    elif [[ $env == \"pre\" ]]; then\n        cp filebeat-pre.yml filebeat-7.6.2-linux-x86_64/filebeat.yml\n    else\n        cp filebeat-online.yml filebeat-7.6.2-linux-x86_64/filebeat.yml\n    fi\n\n    cd filebeat-7.6.2-linux-x86_64\n\n    nohup ./filebeat -e -c filebeat.yml > filebeat.log &\n\n    echo \"start filebeat ok\"\n    return 0\n}\n\nfunction filebeat_stop(){\n    echo \"stop filebeat\"\n\n    pgrep filebeat | xargs kill -s 9\n\n    echo \"stop filebeat ok\"\n    return 0\n}\n\naction=$1\ncase $action in\n    \"start\" )\n        # 启动服务\n        start\n        cp -f ./nginx/conf/${nginx_conf} ~/nginx/conf/nginx.conf\n        http_start\n        filebeat_start\n        ;;\n    \"stop\" )\n        # 停止服务\n        http_stop\n        stop\n        filebeat_stop\n        ;;\n    \"status\" )\n        # 检查服务\n        status\n        ;;\n    \"update\" )\n        # 更新操作\n        update\n        ;;\n    * )\n        echo \"unknown command\"\n        exit 1\n        ;;\nesac\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/nginxfunc.sh",
    "content": "#!/usr/bin/env bash\n###########################################################################\n#  nginxfunc.sh\n#  实现http_start 、http_stop 方法用于启停nginx 以及 status.do文件rename\n##########################################################################\n\n\n\n#variables\nNGINX_PATH=\"/home/${USER}/nginx\"\nSTATUS_FILE=\"${NGINX_PATH}/html/status.do\"\nNGXPID_FILE=\"${NGINX_PATH}/run/nginx.pid\"\nNGXBIN_STOP=\"${NGINX_PATH}/load.sh stop\"\nNGXBIN_START=\"${NGINX_PATH}/load.sh start\"\nNGINX_URL=\"http://127.0.0.1:8080/status.do\"\nLOCAL_URL=\"http://1:azAWiJhxkho33ac@127.0.0.1:8200/_cluster/health\"\n\n\nfunction rm_status_do() {\n    if [ -f ${STATUS_FILE} ];then\n        rm -rf ${STATUS_FILE}\n        if [ $? == 0 ];then\n            return 0;\n        else\n            exit 1;\n        fi\n    fi\n}\n\nfunction http_stop() {\n    local timeout=20\n    if [ ! -f ${NGXPID_FILE} ];then\n        echo \"Nginx is stop!\"\n    else\n        rm -rf ${STATUS_FILE}\n        echo \"Sleep [ 20 ] sec. Wait Inrouter Remove RS!\"\n        for((i=1;i<=$timeout;i++));do\n            sleep 1;\n            echo \"Sleep [ $i ] \"\n        done\n\n        $NGXBIN_STOP\n        if [ $? != 0 ]; then\n            echo \"Nginx stop failed!!!\"\n            exit 1\n        else\n            echo \"Nginx is stop!\"\n        fi\n    fi\n}\n\nfunction http_start() {\n\n    local timeout=120\n    local health=0\n    for (( i = 0; i < $timeout; i++ )); do\n        echo \"check tomcat health [ $i ] \"\n\n        local_check=$(curl -s --connect-timeout 3 --max-time 5 ${LOCAL_URL} -o /dev/null -w %{http_code})\n        if [ \"${local_check}\" == \"200\" ];then\n            echo \"Tomcat ${LOCAL_URL} 200 OK\"\n            health=1\n            break\n        fi\n\n        sleep 1s\n    done\n\n    if [ \"x$health\" == \"x0\" ]; then\n        echo \"Tomcat ${LOCAL_URL} failed in $timeout sec.\"\n        exit 1\n    fi\n\n    echo \"200 OK\" > ${STATUS_FILE}\n    if [[ ! -f ${NGXPID_FILE} ]];then\n        echo \"Nginx server starting!\"\n        ${NGXBIN_START}\n    else\n        echo \"Nginx server Running...\"\n    fi\n\n    sleep 1\n    nginx_status=$(curl -s --max-time 5 --retry-delay 2 --retry 5 ${NGINX_URL} -o /dev/null -w %{http_code})\n    if [ \"${nginx_status}\" == \"200\" ];then\n        echo \"Nginx ${NGINX_URL} 200 OK\"\n    else\n        echo \"Nginx ${NGINX_URL} curl Faild!\"\n        rm_status_do\n    fi\n}\n\nif [ -z ${APPNAME} ];then\n    function http_start(){\n        return 0;\n    }\n    function http_stop(){\n        return 0;\n    }\nfi\n\nif [ $NGINX_CHECK == 0 ];then\n    function http_start(){\n        return 0\n    }\n    function http_stop(){\n        return 0\n    }\nfi\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.didi</groupId>\n        <artifactId>arius-gateway-v2</artifactId>\n        <version>0.0.1-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>arius-gateway-rest</artifactId>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.didi</groupId>\n            <artifactId>arius-gateway-core</artifactId>\n            <version>${project.version}</version>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <finalName>arius-gateway-rest</finalName>\n\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <goals>\n                            <goal>repackage</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/AriusGatewayApplication.java",
    "content": "package com.didi.arius.gateway.rest;\n\nimport com.didi.arius.gateway.common.utils.Convert;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;\n\n@SpringBootApplication(scanBasePackages = {\"com.didi.arius.gateway\", \"com.didiglobal.knowframework\"}, exclude={DataSourceAutoConfiguration.class})\npublic class AriusGatewayApplication {\n\n    public static void main(String[] args) {\n        System.setProperty(\"hostName\", Convert.getHostName());\n        SpringApplication.run(AriusGatewayApplication.class, args);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/AdminController.java",
    "content": "package com.didi.arius.gateway.rest.controller;\n\nimport com.didi.arius.gateway.common.exception.AccessForbiddenException;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.AppUtil;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\n\npublic abstract class AdminController extends BaseHttpRestController {\n\n    @Override\n    public void handleRequest(QueryContext queryContext) throws Exception {\n        if (!AppUtil.isAdminAppid(queryContext.getAppDetail())) {\n            throw new AccessForbiddenException(\"action(\" + queryContext.getUri() + \") forbidden\");\n        }\n\n        ESClient client = esClusterService.getClient(queryContext, actionName);\n\n        handleAriusRequest(queryContext, queryContext.getRequest(), queryContext.getChannel(), client);\n    }\n\n    protected abstract void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/BaseHttpRestController.java",
    "content": "package com.didi.arius.gateway.rest.controller;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.consts.RestConsts;\nimport com.didi.arius.gateway.common.exception.QueryDslLengthException;\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.JoinLogContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.AppUtil;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.es.http.RestActionListenerImpl;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.core.service.RateLimitService;\nimport com.didi.arius.gateway.core.service.RequestStatsService;\nimport com.didi.arius.gateway.core.service.arius.AppService;\nimport com.didi.arius.gateway.core.service.arius.DynamicConfigService;\nimport com.didi.arius.gateway.core.service.arius.ESClusterService;\nimport com.didi.arius.gateway.core.service.arius.IndexTemplateService;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.direct.DirectResponse;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport com.didi.arius.gateway.elasticsearch.client.model.ESActionRequest;\nimport com.didi.arius.gateway.rest.http.IRestHandler;\nimport com.didi.arius.gateway.rest.http.RestController;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.log.LogGather;\nimport com.didiglobal.knowframework.observability.Observability;\nimport com.didiglobal.knowframework.observability.common.constant.Constant;\nimport io.opentelemetry.api.trace.Span;\nimport io.opentelemetry.api.trace.SpanKind;\nimport io.opentelemetry.api.trace.StatusCode;\nimport io.opentelemetry.api.trace.Tracer;\nimport io.opentelemetry.context.Context;\nimport io.opentelemetry.context.Scope;\nimport io.opentelemetry.context.propagation.TextMapGetter;\nimport io.opentelemetry.context.propagation.TextMapPropagator;\nimport org.apache.commons.collections.CollectionUtils;\nimport org.apache.commons.httpclient.HttpStatus;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.rest.*;\nimport org.elasticsearch.rest.support.RestUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.annotation.PostConstruct;\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.*;\n\npublic abstract class BaseHttpRestController implements IRestHandler {\n\n    protected static final ILog logger = LogFactory.getLog(BaseHttpRestController.class);\n    protected static final Logger statLogger = LoggerFactory.getLogger(QueryConsts.STAT_LOGGER);\n    protected static final ILog traceLogger = LogFactory.getLog(QueryConsts.TRACE_LOGGER);\n    protected static final ILog auditLogger = LogFactory.getLog(QueryConsts.AUDIT_LOGGER);\n    protected static final String AUTHORIZATION = \"Authorization\";\n\n    private static final TextMapPropagator TEXT_MAP_PROPAGATOR = Observability.getTextMapPropagator();\n    private static final Tracer tracer = Observability.getTracer(BaseHttpRestController.class.getName());\n\n    private static Set<Integer> validHttpStatusCodeSet = new HashSet<>();\n\n    static {\n        validHttpStatusCodeSet.add(HttpStatus.SC_OK);\n    }\n\n    @Autowired\n    protected DynamicConfigService dynamicConfigService;\n\n    @Autowired\n    protected IndexTemplateService indexTemplateService;\n\n    @Autowired\n    protected RequestStatsService requestStatsService;\n\n    @Autowired\n    protected ESClusterService esClusterService;\n\n    @Autowired\n    protected AppService appService;\n\n    @Autowired\n    protected ESRestClientService esRestClientService;\n\n    @Autowired\n    protected QueryConfig queryConfig;\n\n    @Autowired\n    protected RestController controller;\n\n    @Autowired\n    protected RateLimitService rateLimitService;\n\n    protected String actionName = this.getClass().getSimpleName();\n\n    @PostConstruct\n    public void init() {\n        register();\n    }\n\n    @Override\n    public void dispatchRequest(RestRequest request, RestChannel channel) {\n        Span span = buildSpan(request);\n        QueryContext queryContext = parseContext(request, channel);\n        try (Scope scope = span.makeCurrent()) {\n            // Process the request\n            checkToken(queryContext);\n            preRequest(queryContext);\n            handleRequest(queryContext);\n            postRequest(queryContext);\n            //handle response status code\n            RestResponse response = queryContext.getResponse();\n            if(null == response || null == response.status()) {\n                //注：业务方表示 response 可能为 null 或 response.status 为空，此时，如未抛异常，表示成功\n                span.setStatus(StatusCode.OK);\n            } else {\n                //set span status\n                int httpStatus = response.status().getStatus();\n                setSpanStatus(span, httpStatus);\n            }\n        } catch (Exception ex) {\n            span.setStatus(StatusCode.ERROR, ex.getMessage());\n            preException(queryContext, ex);\n            try {\n                channel.sendResponse(new BytesRestResponse(channel, ex));\n            } catch (IOException ioe) {\n                BytesRestResponse response = new BytesRestResponse(RestStatus.INTERNAL_SERVER_ERROR);\n                channel.sendResponse(response);\n            }\n        } finally {\n            // Close the span\n            span.end();\n        }\n    }\n\n    /**\n     * 根据 http status 设置 span 状态\n     * @param span Span 对象\n     * @param httpStatus http status code\n     */\n    private void setSpanStatus(Span span, int httpStatus) {\n        if(!validHttpStatusCodeSet.contains(httpStatus)) {\n            span.setStatus(\n                    StatusCode.ERROR,\n                    String.format(\n                            \"http状态码%d不在合法http状态码集%s内\",\n                            httpStatus,\n                            JSON.toJSONString(validHttpStatusCodeSet)\n                    )\n            );\n        } else {\n            span.setStatus(StatusCode.OK);\n        }\n    }\n\n    /**\n     * 根据 request 对象，构建 span 对象，并注入 http 请求头相关信息\n     * @param request RestRequest 对象\n     * @return Span 对象\n     */\n    private Span buildSpan(RestRequest request) {\n        Context context = TEXT_MAP_PROPAGATOR.extract(Context.current(), request, getter);\n        Span span = tracer.spanBuilder(\n                String.format(\"%s.%s\", this.getClass().getName(), \"dispatchRequest\")\n        ).setParent(context).setSpanKind(SpanKind.SERVER).startSpan();\n        span.setAttribute(Constant.ATTRIBUTE_KEY_COMPONENT, Constant.ATTRIBUTE_VALUE_COMPONENT_HTTP);\n        span.setAttribute(Constant.ATTRIBUTE_KEY_HTTP_METHOD, request.method().name());\n        span.setAttribute(Constant.ATTRIBUTE_KEY_HTTP_SCHEMA, Constant.ATTRIBUTE_VALUE_COMPONENT_HTTP);\n        span.setAttribute(Constant.ATTRIBUTE_KEY_HTTP_HOST, request.getLocalAddress().toString());\n        span.setAttribute(Constant.ATTRIBUTE_KEY_HTTP_TARGET, request.uri());\n        return span;\n    }\n\n    /*\n     * extract the context from http headers\n     */\n    private static final TextMapGetter<RestRequest> getter =\n            new TextMapGetter<RestRequest>() {\n                @Override\n                public Iterable<String> keys(RestRequest carrier) {\n                    List<String> iterable = new ArrayList<>();\n                    Set<String> headers = carrier.getHeaders();\n                    if(CollectionUtils.isNotEmpty(headers)) {\n                        iterable.addAll(headers);\n                    }\n                    return iterable;\n                }\n                @Override\n                public String get(RestRequest carrier, String key) {\n                    String headerValue = carrier.getHeader(key);\n                    return headerValue == null ? StringUtils.EMPTY : headerValue;\n                }\n            };\n\n    /************************************************************** abstract method **************************************************************/\n    /**\n     *\n     */\n    protected abstract void register();\n\n    /**\n     * @return\n     */\n    protected abstract String name();\n\n    /**\n     * @param queryContext\n     * @throws Exception\n     */\n    protected abstract void handleRequest(QueryContext queryContext) throws Exception;\n\n    /************************************************************** protected method **************************************************************/\n    /**\n     * @param queryContext\n     * @param restResponse\n     */\n    protected void sendDirectResponse(QueryContext queryContext, RestResponse restResponse) {\n        RestActionListenerImpl<ESSearchResponse> listener = new RestActionListenerImpl<>(queryContext);\n        listener.onResponse(restResponse);\n    }\n\n    protected void checkIndices(QueryContext queryContext) {\n        List<String> indices = queryContext.getIndices();\n        appService.checkIndices(queryContext, indices);\n    }\n\n    protected void checkToken(QueryContext queryContext) {\n        appService.checkToken(queryContext);\n        String encode = Base64.getEncoder().encodeToString(String.format(\"%s\", \"user_\" + queryContext.getAppid() + \":\" + queryContext.getAppDetail().getVerifyCode()).getBytes(StandardCharsets.UTF_8));\n        queryContext.getRequest().putHeader(AUTHORIZATION, \"Basic \" + encode);\n    }\n\n    protected void preRequest(QueryContext queryContext) {\n        if (queryContext.isFromKibana() || (AppUtil.isAdminAppid(queryContext.getAppDetail())\n                                            && StringUtils.isNotBlank(queryContext.getClusterId()))) {\n            // 如果是来自 kibana 的请求，则设置为原生查询\n            queryContext.setSearchType(AppDetail.RequestType.ORIGIN_CLUSTER.getType());\n        }\n        if (queryContext.getPostBody() != null && queryContext.getPostBody().length() > queryConfig.getDslMaxLength()) {\n            throw new QueryDslLengthException(String.format(\"query length(%d) > %d exception\", queryContext.getPostBody().length(), queryConfig.getDslMaxLength()));\n        }\n\n        queryContext.setRequestTime(System.currentTimeMillis());\n\n        if (queryContext.isDetailLog()) {\n            JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n            joinLogContext.setAppid(queryContext.getAppid());\n            joinLogContext.setTraceid(queryContext.getTraceid());\n            joinLogContext.setRequestId(queryContext.getRequestId());\n            joinLogContext.setRequestType(queryContext.getAppDetail().getSearchType());\n            joinLogContext.setMethod(queryContext.getMethod());\n            joinLogContext.setClusterId(queryContext.getClusterId());\n            joinLogContext.setUser(queryContext.getUser());\n            joinLogContext.setUri(queryContext.getUri());\n            joinLogContext.setQueryString(queryContext.getQueryString());\n            joinLogContext.setRemoteAddr(queryContext.getRemoteAddr());\n            joinLogContext.setDslLen(queryContext.getPostBody().length());\n            joinLogContext.setDsl(queryContext.getPostBody().replaceAll(\"\\\\n\", \" \"));\n            joinLogContext.setTimeStamp(System.currentTimeMillis());\n            joinLogContext.setProjectId(queryContext.getProjectId());\n            traceLogger.info(\"_com_request_in||traceid={}||spanid={}||type=http||appid={}||projectId={}||requestId={}||uri={}||remoteAddr={}||requestLen={}||name={}\",\n                    queryContext.getTraceid(), queryContext.getSpanid(), queryContext.getAppid(), queryContext.getProjectId(),\n                    queryContext.getRequestId(), queryContext.getUri(), queryContext.getRemoteAddr(), queryContext.getPostBody().length(), name());\n        } else {\n            LogGather.recordInfoLog(QueryConsts.DLFLAG_PREFIX + \"query_request_\" + queryContext.getAppid() + \"_\" + name(), String.format(\"requestId=%s||method=%s||uri=%s||queryString=%s||remoteAddr=%s||postBodyLen=%d\",\n                    queryContext.getRequestId(), queryContext.getMethod(), queryContext.getUri(), queryContext.getQueryString(), queryContext.getRemoteAddr(), queryContext.getPostBody().length()));\n        }\n\n        if (queryContext.getXUserName() != null) {\n            auditLogger.info(\"auditlog||system=arius||hostIp=127.0.0.1||userName={}||url={}||getParams={}||postParams={}||userIp={}||timestamp=||respose=\",\n                    queryContext.getXUserName(), queryContext.getUri(), queryContext.getQueryString(), queryContext.getPostBody(), queryContext.getRemoteAddr());\n        }\n\n        rateLimitService.addByteIn(queryContext.getPostBody().length());\n    }\n\n    protected void preException(QueryContext queryContext, Throwable e) {\n        if (queryContext.isDetailLog()) {\n            JoinLogContext joinLogContext = queryContext.getJoinLogContext();\n            joinLogContext.setAriusType(\"error\");\n            joinLogContext.setExceptionName(e.getClass().getName());\n            joinLogContext.setStack(Convert.logExceptionStack(e));\n            joinLogContext.setTotalCost(System.currentTimeMillis() - queryContext.getRequestTime());\n            joinLogContext.setInternalCost(joinLogContext.getTotalCost() - joinLogContext.getEsCost());\n            joinLogContext.setSinkTime(System.currentTimeMillis());\n\n            String log = joinLogContext.toString();\n            statLogger.error(log);\n\n            traceLogger.info(\"_com_request_out||traceid={}||spanid={}||type=http||appid={}||requestId={}||errname={}\",\n                    queryContext.getTraceid(), queryContext.getSpanid(), queryContext.getAppid(), queryContext.getRequestId(), e.getClass().getName());\n        }\n\n        LogGather.recordErrorLog(e.getClass().getName() + \"_\" + queryContext.getAppid(), String.format(\"http_exception||requestId=%s||appid=%d||uri=%s||postBody=%s\",\n                queryContext.getRequestId(), queryContext.getAppid(), queryContext.getUri(), queryContext.getPostBody()), e);\n\n        requestStatsService.removeQueryContext(queryContext.getRequestId());\n\n        rateLimitService.removeByteIn(queryContext.getPostBody().length());\n    }\n\n    protected void postRequest(QueryContext queryContext) {\n        int appid = queryContext.getAppDetail() != null ? queryContext.getAppDetail().getId() : QueryConsts.TOTAL_APPID_ID;\n        requestStatsService.statsAdd(name(), appid, queryContext.getSearchId(), queryContext.getCostTime(), RestStatus.OK);\n\n        String searchId = queryContext.getSearchId() != null ? queryContext.getSearchId() : QueryConsts.TOTAL_SEARCH_ID;\n        try {\n            rateLimitService.addUp(appid, searchId, 0, 0);\n        } catch (Exception e) {\n            logger.warn(\"rateLimitService.addUp exception\", e);\n        }\n\n    }\n\n    protected void directRequest(ESClient client, QueryContext queryContext, RestActionListenerImpl<DirectResponse> listener) {\n        String uri = queryContext.getUri();\n        String queryString = queryContext.getQueryString() == null ? \"\" : queryContext.getQueryString();\n\n        Map<String, String> params = new HashMap<>();\n        RestUtils.decodeQueryString(queryString, 0, params);\n\n        DirectRequest directRequest = new DirectRequest(queryContext.getMethod().toString(), uri);\n        setSocketTimeout(params, directRequest);\n        directRequest.setPostContent(queryContext.getPostBody());\n        directRequest.setParams(params);\n\n        directRequest.putHeader(AUTHORIZATION, queryContext.getRequest().getHeader(AUTHORIZATION));\n        directRequest.putHeader(\"requestId\", queryContext.getRequestId());\n\n        client.direct(directRequest, listener);\n    }\n\n    protected void directRequest(ESClient client, QueryContext queryContext) {\n        RestActionListenerImpl<DirectResponse> listener = new RestActionListenerImpl<>(queryContext);\n        directRequest(client, queryContext, listener);\n    }\n\n    /************************************************************** private method **************************************************************/\n    private QueryContext parseContext(RestRequest request, RestChannel channel) {\n        QueryContext context = new QueryContext();\n        context.setRequestTime(System.currentTimeMillis());\n        context.setRestName(name());\n        context.setJoinLogContext(new JoinLogContext());\n\n        String searchId = request.header(QueryConsts.HEAD_SEARCH_ID);\n        String clusterId = request.header(QueryConsts.HEAD_CLUSTER_ID);\n        String user = request.header(QueryConsts.HEAD_USER);\n        String authentication = request.header(QueryConsts.HEAD_AUTHORIZATION);\n        String xUserName = request.header(QueryConsts.HEAD_USERNAME);\n        String ssoUserName = request.header(QueryConsts.HEAD_SSO_USERNAME);\n        String clientVersion = request.header(QueryConsts.HEAD_CLIENT_VERSION);\n\n        String traceid = request.header(QueryConsts.TRACE_ID);\n        String spanid = request.header(QueryConsts.SPAN_ID);\n\n        if (traceid == null) {\n            traceid = \"\";\n        }\n\n        if (spanid == null) {\n            spanid = \"\";\n        }\n\n        String postBody = request.content().toUtf8();\n\n        if (postBody == null) {\n            postBody = \"\";\n        }\n\n        String remoteAddr = Convert.getClientIP(request);\n\n        if (searchId == null) {\n            searchId = QueryConsts.TOTAL_SEARCH_ID;\n        }\n\n        if (clusterId == null) {\n            clusterId = request.param(QueryConsts.GET_CLUSTER_ID);\n            request.params().remove(QueryConsts.GET_CLUSTER_ID);\n        }\n\n        context.setTraceid(traceid);\n        context.setRequestId(UUID.randomUUID().toString());\n        context.setMethod(request.method());\n        context.setSearchId(searchId);\n        context.setClusterId(clusterId);\n        context.setUser(user);\n        context.setClientVersion(clientVersion);\n\n        String kibanaVersion = request.header(QueryConsts.HEAD_KIBANA_VERSION);\n\n        // 保存 kibana 数据的索引一般是：.kibana_task_manager、.reporting、.kibana_arius 等\n        context.setFromKibana(request.rawPath().startsWith(\"/.\") || request.rawPath().startsWith(\".\"));\n        context.setNewKibana(kibanaVersion != null && kibanaVersion.startsWith(QueryConsts.NEW_KIBANA_VERSION_START));\n\n        String uri = request.uri();\n        int pathEndPos = uri.indexOf('?');\n        if (pathEndPos > 0 && pathEndPos < uri.length()) {\n            context.setQueryString(uri.substring(pathEndPos + 1));\n        } else {\n            context.setQueryString(\"\");\n        }\n\n        context.setPostBody(postBody);\n        context.setRemoteAddr(remoteAddr);\n        context.setAuthentication(authentication);\n\n        if (user != null) {\n            context.setXUserName(user);\n        } else if (xUserName != null) {\n            context.setXUserName(xUserName);\n        } else if (ssoUserName != null) {\n            context.setXUserName(ssoUserName);\n        }\n\n        context.setTraceid(traceid);\n        context.setSpanid(spanid);\n\n        context.setRequest(request);\n        context.setChannel(channel);\n\n        context.setSemaphore(queryConfig.getHttpSemaphore());\n        context.setRequestSlowlogThresholdMills(queryConfig.getRequestSlowlogThresholdMills());\n        context.setMaxHttpResponseLength(queryConfig.getMaxHttpResponseLength());\n\n        requestStatsService.putQueryContext(context.getRequestId(), context);\n\n        context.setTypedKeys(request.paramAsBoolean(\"typed_keys\", false));\n\n        if (dynamicConfigService.getDetailLogFlag()\n                || context.isFromKibana()) {\n            context.setDetailLog(true);\n//        } else if (this instanceof RestBaseWriteAction) {\n//            context.setDetailLog(false);\n        } else {\n            context.setDetailLog(true);\n        }\n\n        return context;\n    }\n\n    private void setSocketTimeout(Map<String, String> params, ESActionRequest request) {\n        if (params.containsKey(RestConsts.SOCKET_TIMEOUT_PARAMS)) {\n            String strSocketTimeout = params.remove(RestConsts.SOCKET_TIMEOUT_PARAMS);\n            try {\n                int socketTimeout = Integer.parseInt(strSocketTimeout);\n                if (socketTimeout > 0 && socketTimeout <= QueryConsts.MAX_SOCKET_TIMEOUT) {\n                    request.setSocketTimeout(socketTimeout);\n                }\n            } catch (Exception e) {\n                // pass\n            }\n        }\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/StatController.java",
    "content": "package com.didi.arius.gateway.rest.controller;\n\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\n\nimport java.util.List;\n\nimport static com.didi.arius.gateway.common.utils.CommonUtil.isIndexType;\n\n/**\n * @author fitz\n * @date 2021/5/25 3:22 下午\n */\npublic abstract class StatController extends BaseHttpRestController {\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n\n        ESClient client = esClusterService.getClient(queryContext, actionName);\n\n        if (queryContext.getRequest().param(\"index\") != null) {\n            String index = queryContext.getRequest().param(\"index\");\n            String[] indicesArr = Strings.splitStringByCommaToArray(index);\n            List<String> indices = Lists.newArrayList(indicesArr);\n            queryContext.setIndices(indices);\n\n            checkIndices(queryContext);\n\n            if (isIndexType(queryContext)) {\n                IndexTemplate indexTemplate = indexTemplateService.getTemplateByIndexTire(indices, queryContext);\n\n                client = esClusterService.getClient(queryContext, indexTemplate, actionName);\n            }\n        }\n\n        handleAriusRequest(queryContext, queryContext.getRequest(), queryContext.getChannel(), client);\n\n    }\n\n    protected abstract  void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception;\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/check/CheckSearchAggsController.java",
    "content": "package com.didi.arius.gateway.rest.controller.check;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.service.dsl.DslAggsAnalyzerService;\nimport com.didi.arius.gateway.rest.controller.AdminController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didiglobal.knowframework.dsl.parse.DslExtractionUtilV2;\nimport com.didiglobal.knowframework.dsl.parse.bean.ExtractResult;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\n/**\n * @author fitz\n * @date 2021/5/25 2:26 下午\n */\n@Controller\npublic class CheckSearchAggsController extends AdminController {\n    public static final String NAME = \"checkSearchAggs\";\n\n    @Autowired\n    private DslAggsAnalyzerService dslAggsAnalyzerService;\n\n    public CheckSearchAggsController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.POST, \"/_check/search_aggs/{index}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        String[] indices = Strings.splitStringByCommaToArray(queryContext.getRequest().param(\"index\"));\n        BytesReference source = new BytesArray(queryContext.getPostBody());\n        String strSource = XContentHelper.convertToJson(source, false);\n\n        ExtractResult extractResult = DslExtractionUtilV2.extractDsl(strSource);\n\n        String dslKey = queryContext.getAppid() + \"_\" + extractResult.getDslTemplateMd5();\n        queryContext.setDslTemplateKey(dslKey);\n\n        dslAggsAnalyzerService.analyzeAggs(queryContext, source, indices);\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK));\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/check/GetMergeMappingController.java",
    "content": "package com.didi.arius.gateway.rest.controller.check;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.FieldInfo;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.service.dsl.DslAggsAnalyzerService;\nimport com.didi.arius.gateway.rest.controller.AdminController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.xcontent.XContentType;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.Map;\n\n/**\n * @author fitz\n * @date 2021/5/25 2:54 下午\n */\n@Controller\npublic class GetMergeMappingController extends AdminController {\n\n    public static final String NAME = \"getMergeMapping\";\n\n    @Autowired\n    private DslAggsAnalyzerService dslAggsAnalyzerService;\n\n    public GetMergeMappingController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_check/mergeMapping/{index}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        String[] indices = Strings.splitStringByCommaToArray(request.param(\"index\"));\n        Map<String, FieldInfo> mappings = dslAggsAnalyzerService.mergeMappings(indices, null);\n        String strMappings = JSON.toJSONString(mappings);\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, XContentType.JSON.restContentType(), strMappings));\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/ESBaseController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es;\n\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\n\npublic abstract class ESBaseController extends BaseHttpRestController {\n    protected static final ILog logger = LogFactory.getLog(ESBaseController.class);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/RestCommonController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.action.RestCommonAction;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.*;\n\n@Controller\npublic class RestCommonController extends ESBaseController {\n\n    @Autowired\n    private RestCommonAction restCommonAction;\n\n    public RestCommonController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(DELETE, \"/_ccr/auto_follow/{name}\", this);\n        controller.registerHandler(DELETE, \"/_cluster/voting_config_exclusions\", this);\n        controller.registerHandler(DELETE, \"/_data_frame/transforms/{id}/\", this);\n        controller.registerHandler(DELETE, \"/_dcdr/auto_replication/{name}\", this);\n        controller.registerHandler(DELETE, \"/_dcdr/{index}/replication/delete\", this);\n        controller.registerHandler(DELETE, \"/_enrich/policy/{name}\", this);\n        controller.registerHandler(DELETE, \"/_ilm/policy/{name}\", this);\n        controller.registerHandler(DELETE, \"/_ingest/pipeline/{id}\", this);\n        controller.registerHandler(DELETE, \"/_license\", this);\n        controller.registerHandler(DELETE, \"/_rollup/job/{id}\", this);\n        controller.registerHandler(DELETE, \"/_scripts/{id}\", this);\n        controller.registerHandler(DELETE, \"/_security/api_key\", this);\n        controller.registerHandler(DELETE, \"/_security/oauth2/token\", this);\n        controller.registerHandler(DELETE, \"/_security/privilege/{application}/{privilege}\", this);\n        controller.registerHandler(DELETE, \"/_security/role/{name}\", this);\n        controller.registerHandler(DELETE, \"/_security/role_mapping/{name}\", this);\n        controller.registerHandler(DELETE, \"/_security/user/{username}\", this);\n        controller.registerHandler(DELETE, \"/_slm/policy/{name}\", this);\n        controller.registerHandler(DELETE, \"/_snapshot/{repository}\", this);\n        controller.registerHandler(DELETE, \"/_snapshot/{repository}/{snapshot}\", this);\n        controller.registerHandler(DELETE, \"/_template/{index}\", this);\n        controller.registerHandler(DELETE, \"/_transform/{id}/\", this);\n        controller.registerHandler(DELETE, \"/_watcher/watch/{id}\", this);\n        controller.registerHandler(DELETE, \"/_xpack/license\", this);\n        controller.registerHandler(DELETE, \"/_xpack/rollup/job/{id}/\", this);\n        controller.registerHandler(DELETE, \"/_xpack/security/oauth2/token\", this);\n        controller.registerHandler(DELETE, \"/_xpack/security/privilege/{application}/{privilege}\", this);\n        controller.registerHandler(DELETE, \"/_xpack/security/role/{name}\", this);\n        controller.registerHandler(DELETE, \"/_xpack/security/role_mapping/{name}\", this);\n        controller.registerHandler(DELETE, \"/_xpack/security/user/{username}\", this);\n        controller.registerHandler(DELETE, \"/_xpack/watcher/watch/{id}\", this);\n        controller.registerHandler(GET, \"/_cache/clear\", this);\n        controller.registerHandler(GET, \"/_cat\", this);\n        controller.registerHandler(GET, \"/_cat/aliases\", this);\n        controller.registerHandler(GET, \"/_cat/aliases/{alias}\", this);\n        controller.registerHandler(GET, \"/_cat/allocation\", this);\n        controller.registerHandler(GET, \"/_cat/allocation/{nodes}\", this);\n        controller.registerHandler(GET, \"/_cat/count\", this);\n        controller.registerHandler(GET, \"/_cat/count/{index}\", this);\n        controller.registerHandler(GET, \"/_cat/example\", this);\n        controller.registerHandler(GET, \"/_cat/fielddata\", this);\n        controller.registerHandler(GET, \"/_cat/fielddata/{fields}\", this);\n        controller.registerHandler(GET, \"/_cat/group/factor\", this);\n        controller.registerHandler(GET, \"/_cat/group/factor/{group}\", this);\n        controller.registerHandler(GET, \"/_cat/health\", this);\n        controller.registerHandler(GET, \"/_cat/master\", this);\n        controller.registerHandler(GET, \"/_cat/node/group/factor/{node}\", this);\n        controller.registerHandler(GET, \"/_cat/node/group/factor/{node}/{group}\", this);\n        controller.registerHandler(GET, \"/_cat/nodeattrs\", this);\n        controller.registerHandler(GET, \"/_cat/nodes\", this);\n        controller.registerHandler(GET, \"/_cat/pending_tasks\", this);\n        controller.registerHandler(GET, \"/_cat/plugins\", this);\n        controller.registerHandler(GET, \"/_cat/recovery\", this);\n        controller.registerHandler(GET, \"/_cat/recovery/{index}\", this);\n        controller.registerHandler(GET, \"/_cat/repositories\", this);\n        controller.registerHandler(GET, \"/_cat/segments\", this);\n        controller.registerHandler(GET, \"/_cat/segments/{index}\", this);\n        controller.registerHandler(GET, \"/_cat/shards\", this);\n        controller.registerHandler(GET, \"/_cat/shards/{index}\", this);\n        controller.registerHandler(GET, \"/_cat/snapshots\", this);\n        controller.registerHandler(GET, \"/_cat/snapshots/{repository}\", this);\n        controller.registerHandler(GET, \"/_cat/tasks\", this);\n        controller.registerHandler(GET, \"/_cat/templates\", this);\n        controller.registerHandler(GET, \"/_cat/templates/{name}\", this);\n        controller.registerHandler(GET, \"/_cat/thread_pool\", this);\n        controller.registerHandler(GET, \"/_cat/thread_pool/{thread_pool_patterns}\", this);\n        controller.registerHandler(GET, \"/_ccr/auto_follow\", this);\n        controller.registerHandler(GET, \"/_ccr/auto_follow/{name}\", this);\n        controller.registerHandler(GET, \"/_ccr/stats\", this);\n        controller.registerHandler(GET, \"/_cluster/allocation/explain\", this);\n        controller.registerHandler(GET, \"/_cluster/nodes/hot_threads\", this);\n        controller.registerHandler(GET, \"/_cluster/nodes/hotthreads\", this);\n        controller.registerHandler(GET, \"/_cluster/nodes/{nodeId}/hot_threads\", this);\n        controller.registerHandler(GET, \"/_cluster/nodes/{nodeId}/hotthreads\", this);\n        controller.registerHandler(GET, \"/_cluster/pending_tasks\", this);\n        controller.registerHandler(GET, \"/_cluster/settings\", this);\n        controller.registerHandler(GET, \"/_cluster/state\", this);\n        controller.registerHandler(GET, \"/_cluster/state/{metric}\", this);\n        controller.registerHandler(GET, \"/_cluster/state/{metric}/{indices}\", this);\n        controller.registerHandler(GET, \"/_cluster/stats\", this);\n        controller.registerHandler(GET, \"/_cluster/stats/nodes/{nodeId}\", this);\n        controller.registerHandler(GET, \"/_data_frame/transforms/\", this);\n        controller.registerHandler(GET, \"/_data_frame/transforms/_stats\", this);\n        controller.registerHandler(GET, \"/_data_frame/transforms/{id}/\", this);\n        controller.registerHandler(GET, \"/_data_frame/transforms/{id}/_stats\", this);\n        controller.registerHandler(GET, \"/_dcdr/auto_replication\", this);\n        controller.registerHandler(GET, \"/_dcdr/auto_replication/{name}\", this);\n        controller.registerHandler(GET, \"/_dcdr/replication\", this);\n        controller.registerHandler(GET, \"/_dcdr/stats\", this);\n        controller.registerHandler(GET, \"/_dcdr/{index}/replication\", this);\n        controller.registerHandler(GET, \"/_dcdr/{index}/stats\", this);\n        controller.registerHandler(GET, \"/_dcdr/{index}/{shard}/fetch_shard_info\", this);\n        controller.registerHandler(GET, \"/_die_with_dignity\", this);\n        controller.registerHandler(GET, \"/_enrich/_stats\", this);\n        controller.registerHandler(GET, \"/_enrich/policy\", this);\n        controller.registerHandler(GET, \"/_enrich/policy/{name}\", this);\n        controller.registerHandler(GET, \"/_dummy\", this);\n        controller.registerHandler(GET, \"/_field_caps\", this);\n        controller.registerHandler(GET, \"/_flush\", this);\n        controller.registerHandler(GET, \"/_flush/synced\", this);\n        controller.registerHandler(GET, \"/_ilm/policy\", this);\n        controller.registerHandler(GET, \"/_ilm/policy/{name}\", this);\n        controller.registerHandler(GET, \"/_ilm/status\", this);\n        controller.registerHandler(GET, \"/_ingest/pipeline\", this);\n        controller.registerHandler(GET, \"/_ingest/pipeline/_simulate\", this);\n        controller.registerHandler(GET, \"/_ingest/pipeline/{id}\", this);\n        controller.registerHandler(GET, \"/_ingest/pipeline/{id}/_simulate\", this);\n        controller.registerHandler(GET, \"/_ingest/processor/grok\", this);\n        controller.registerHandler(GET, \"/_license\", this);\n        controller.registerHandler(GET, \"/_license/basic_status\", this);\n        controller.registerHandler(GET, \"/_license/trial_status\", this);\n        controller.registerHandler(GET, \"/_migration/deprecations\", this);\n        controller.registerHandler(GET, \"/_mtermvectors\", this);\n        controller.registerHandler(GET, \"/_nodes/hot_threads\", this);\n        controller.registerHandler(GET, \"/_nodes/hotthreads\", this);\n        controller.registerHandler(GET, \"/_nodes/stats\", this);\n        controller.registerHandler(GET, \"/_nodes/stats/{metric}\", this);\n        controller.registerHandler(GET, \"/_nodes/stats/{metric}/{index_metric}\", this);\n        controller.registerHandler(GET, \"/_nodes/usage\", this);\n        controller.registerHandler(GET, \"/_nodes/usage/{metric}\", this);\n        controller.registerHandler(GET, \"/_nodes/{nodeId}/hot_threads\", this);\n        controller.registerHandler(GET, \"/_nodes/{nodeId}/hotthreads\", this);\n        controller.registerHandler(GET, \"/_nodes/{nodeId}/stats\", this);\n        controller.registerHandler(GET, \"/_nodes/{nodeId}/stats/{metric}\", this);\n        controller.registerHandler(GET, \"/_nodes/{nodeId}/stats/{metric}/{index_metric}\", this);\n        controller.registerHandler(GET, \"/_nodes/{nodeId}/usage\", this);\n        controller.registerHandler(GET, \"/_nodes/{nodeId}/usage/{metric}\", this);\n        controller.registerHandler(GET, \"/_rank_eval\", this);\n        controller.registerHandler(GET, \"/_noop_search\", this);\n        controller.registerHandler(GET, \"/_protected\", this);\n        controller.registerHandler(GET, \"/_recovery\", this);\n        controller.registerHandler(GET, \"/_render/template\", this);\n        controller.registerHandler(GET, \"/_render/template/{id}\", this);\n        controller.registerHandler(GET, \"/_rollup/data/{id}\", this);\n        controller.registerHandler(GET, \"/_rollup/job/{id}\", this);\n        controller.registerHandler(GET, \"/_script_context\", this);\n        controller.registerHandler(GET, \"/_script_language\", this);\n        controller.registerHandler(GET, \"/_scripts/painless/_context\", this);\n        controller.registerHandler(GET, \"/_scripts/painless/_execute\", this);\n        controller.registerHandler(GET, \"/_scripts/{id}\", this);\n        controller.registerHandler(GET, \"/_search_shards\", this);\n        controller.registerHandler(GET, \"/_security/_authenticate\", this);\n        controller.registerHandler(GET, \"/_security/api_key\", this);\n        controller.registerHandler(GET, \"/_security/privilege/\", this);\n        controller.registerHandler(GET, \"/_security/privilege/_builtin\", this);\n        controller.registerHandler(GET, \"/_security/privilege/{application}\", this);\n        controller.registerHandler(GET, \"/_security/privilege/{application}/{privilege}\", this);\n        controller.registerHandler(GET, \"/_security/role/\", this);\n        controller.registerHandler(GET, \"/_security/role/{name}\", this);\n        controller.registerHandler(GET, \"/_security/role_mapping/\", this);\n        controller.registerHandler(GET, \"/_security/role_mapping/{name}\", this);\n        controller.registerHandler(GET, \"/_security/user/\", this);\n        controller.registerHandler(GET, \"/_security/user/_has_privileges\", this);\n        controller.registerHandler(GET, \"/_security/user/_privileges\", this);\n        controller.registerHandler(GET, \"/_security/user/{username}\", this);\n        controller.registerHandler(GET, \"/_security/user/{username}/_has_privileges\", this);\n        controller.registerHandler(GET, \"/_segments\", this);\n        controller.registerHandler(GET, \"/_shard_stores\", this);\n        controller.registerHandler(GET, \"/_slm/policy\", this);\n        controller.registerHandler(GET, \"/_slm/policy/{name}\", this);\n        controller.registerHandler(GET, \"/_slm/stats\", this);\n        controller.registerHandler(GET, \"/_slm/status\", this);\n        controller.registerHandler(GET, \"/_snapshot\", this);\n        controller.registerHandler(GET, \"/_snapshot/_status\", this);\n        controller.registerHandler(GET, \"/_snapshot/{repository}\", this);\n        controller.registerHandler(GET, \"/_snapshot/{repository}/_status\", this);\n        controller.registerHandler(GET, \"/_snapshot/{repository}/{snapshot}\", this);\n        controller.registerHandler(GET, \"/_snapshot/{repository}/{snapshot}/_status\", this);\n        controller.registerHandler(GET, \"/_ssl/certificates\", this);\n        controller.registerHandler(GET, \"/_stats\", this);\n        controller.registerHandler(GET, \"/_stats/{metric}\", this);\n        controller.registerHandler(GET, \"/_tasks\", this);\n        controller.registerHandler(GET, \"/_tasks/{task_id}\", this);\n        controller.registerHandler(GET, \"/_template\", this);\n        controller.registerHandler(GET, \"/_template/{index}\", this);\n        controller.registerHandler(GET, \"/_transform/\", this);\n        controller.registerHandler(GET, \"/_transform/_stats\", this);\n        controller.registerHandler(GET, \"/_transform/{id}/\", this);\n        controller.registerHandler(GET, \"/_transform/{id}/_stats\", this);\n        controller.registerHandler(GET, \"/_upgrade\", this);\n        controller.registerHandler(GET, \"/_validate/query\", this);\n        controller.registerHandler(GET, \"/_watcher/stats\", this);\n        controller.registerHandler(GET, \"/_watcher/stats/{metric}\", this);\n        controller.registerHandler(GET, \"/_watcher/watch/{id}\", this);\n        controller.registerHandler(GET, \"/_xpack\", this);\n        controller.registerHandler(GET, \"/_xpack/license\", this);\n        controller.registerHandler(GET, \"/_xpack/license/basic_status\", this);\n        controller.registerHandler(GET, \"/_xpack/license/trial_status\", this);\n        controller.registerHandler(GET, \"/_xpack/migration/assistance\", this);\n        controller.registerHandler(GET, \"/_xpack/migration/assistance/{index}\", this);\n        controller.registerHandler(GET, \"/_xpack/migration/deprecations\", this);\n        controller.registerHandler(GET, \"/_xpack/rollup/data/{id}/\", this);\n        controller.registerHandler(GET, \"/_xpack/rollup/job/{id}/\", this);\n        controller.registerHandler(GET, \"/_xpack/security/_authenticate\", this);\n        controller.registerHandler(GET, \"/_xpack/security/privilege/\", this);\n        controller.registerHandler(GET, \"/_xpack/security/privilege/{application}\", this);\n        controller.registerHandler(GET, \"/_xpack/security/privilege/{application}/{privilege}\", this);\n        controller.registerHandler(GET, \"/_xpack/security/role/\", this);\n        controller.registerHandler(GET, \"/_xpack/security/role/{name}\", this);\n        controller.registerHandler(GET, \"/_xpack/security/role_mapping/\", this);\n        controller.registerHandler(GET, \"/_xpack/security/role_mapping/{name}\", this);\n        controller.registerHandler(GET, \"/_xpack/security/user/\", this);\n        controller.registerHandler(GET, \"/_xpack/security/user/_has_privileges\", this);\n        controller.registerHandler(GET, \"/_xpack/security/user/_privileges\", this);\n        controller.registerHandler(GET, \"/_xpack/security/user/{username}\", this);\n        controller.registerHandler(GET, \"/_xpack/security/user/{username}/_has_privileges\", this);\n        controller.registerHandler(GET, \"/_xpack/sql\", this);\n        controller.registerHandler(GET, \"/_xpack/sql/stats\", this);\n        controller.registerHandler(GET, \"/_xpack/sql/translate\", this);\n        controller.registerHandler(GET, \"/_xpack/ssl/certificates\", this);\n        controller.registerHandler(GET, \"/_xpack/usage\", this);\n        controller.registerHandler(GET, \"/_xpack/watcher/stats\", this);\n        controller.registerHandler(GET, \"/_xpack/watcher/stats/{metric}\", this);\n        controller.registerHandler(GET, \"/_xpack/watcher/watch/{id}\", this);\n        controller.registerHandler(GET, \"/_all/_rollup/data\", this);\n        controller.registerHandler(GET, \"/{index}\", this);\n        controller.registerHandler(GET, \"/{index}/{type}\", this);\n        controller.registerHandler(GET, \"/{index}/_cache/clear\", this);\n        controller.registerHandler(GET, \"/{index}/_ccr/info\", this);\n        controller.registerHandler(GET, \"/{index}/_ccr/stats\", this);\n        controller.registerHandler(GET, \"/{index}/_explain/{id}\", this);\n        controller.registerHandler(GET, \"/{index}/_field_caps\", this);\n        controller.registerHandler(GET, \"/{index}/_flush\", this);\n        controller.registerHandler(GET, \"/{index}/_flush/synced\", this);\n        controller.registerHandler(GET, \"/{index}/_graph/explore\", this);\n        controller.registerHandler(GET, \"/{index}/_ilm/explain\", this);\n        controller.registerHandler(GET, \"/{index}/_migration/deprecations\", this);\n        controller.registerHandler(GET, \"/{index}/_mtermvectors\", this);\n        controller.registerHandler(GET, \"/{index}/_rank_eval\", this);\n        controller.registerHandler(GET, \"/{index}/_noop_search\", this);\n        controller.registerHandler(GET, \"/{index}/_recovery\", this);\n        controller.registerHandler(GET, \"/{index}/_reload_search_analyzers\", this);\n        controller.registerHandler(GET, \"/{index}/_rollup/data\", this);\n        controller.registerHandler(GET, \"/{index}/_search_shards\", this);\n        controller.registerHandler(GET, \"/{index}/_segments\", this);\n        controller.registerHandler(GET, \"/{index}/_shard_stores\", this);\n        controller.registerHandler(GET, \"/{index}/_stats\", this);\n        controller.registerHandler(GET, \"/{index}/_stats/{metric}\", this);\n        controller.registerHandler(GET, \"/{index}/_termvectors\", this);\n        controller.registerHandler(GET, \"/{index}/_termvectors/{id}\", this);\n        controller.registerHandler(GET, \"/{index}/_upgrade\", this);\n        controller.registerHandler(GET, \"/{index}/_validate/query\", this);\n        controller.registerHandler(GET, \"/{index}/_xpack/graph/_explore\", this);\n        controller.registerHandler(GET, \"/{index}/_xpack/migration/deprecations\", this);\n        controller.registerHandler(GET, \"/{index}/_xpack/rollup/data\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_graph/explore\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_mtermvectors\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_noop_search\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_termvector\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_termvectors\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_validate/query\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_xpack/graph/_explore\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/{id}/_explain\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/{id}/_termvector\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/{id}/_termvectors\", this);\n        controller.registerHandler(GET, \"_remote/info\", this);\n        controller.registerHandler(GET, \"_rollup_search\", this);\n        controller.registerHandler(GET, \"{index}/_rollup_search\", this);\n        controller.registerHandler(HEAD, \"/_template/{index}\", this);\n        controller.registerHandler(HEAD, \"/_xpack\", this);\n        controller.registerHandler(HEAD, \"/{index}\", this);\n        controller.registerHandler(POST, \"/_cache/clear\", this);\n        controller.registerHandler(POST, \"/_cat/example\", this);\n        controller.registerHandler(POST, \"/_ccr/auto_follow/{name}/pause\", this);\n        controller.registerHandler(POST, \"/_ccr/auto_follow/{name}/resume\", this);\n        controller.registerHandler(POST, \"/_close\", this);\n        controller.registerHandler(POST, \"/_cluster/allocation/explain\", this);\n        controller.registerHandler(POST, \"/_cluster/reroute\", this);\n        controller.registerHandler(POST, \"/_cluster/voting_config_exclusions/{node_name}\", this);\n        controller.registerHandler(POST, \"/_data_frame/transforms/_preview\", this);\n        controller.registerHandler(POST, \"/_data_frame/transforms/{id}/_start\", this);\n        controller.registerHandler(POST, \"/_data_frame/transforms/{id}/_stop\", this);\n        controller.registerHandler(POST, \"/_data_frame/transforms/{id}/_update\", this);\n        controller.registerHandler(POST, \"/_dcdr/{index}/recover\", this);\n        controller.registerHandler(POST, \"/_dcdr/{index}/recover/{shard}\", this);\n        controller.registerHandler(POST, \"/_dcdr/{index}/replication/pause\", this);\n        controller.registerHandler(POST, \"/_dcdr/{index}/replication/resume\", this);\n        controller.registerHandler(POST, \"/_delete_by_query/{taskId}/_rethrottle\", this);\n        controller.registerHandler(POST, \"/_enrich/policy/{name}/_execute\", this);\n        controller.registerHandler(POST, \"/_field_caps\", this);\n        controller.registerHandler(POST, \"/_flush\", this);\n        controller.registerHandler(POST, \"/_flush/synced\", this);\n        controller.registerHandler(POST, \"/_forcemerge\", this);\n        controller.registerHandler(POST, \"/_ilm/move/{name}\", this);\n        controller.registerHandler(POST, \"/_ilm/start\", this);\n        controller.registerHandler(POST, \"/_ilm/stop\", this);\n        controller.registerHandler(POST, \"/_ingest/pipeline/_simulate\", this);\n        controller.registerHandler(POST, \"/_ingest/pipeline/{id}/_simulate\", this);\n        controller.registerHandler(POST, \"/_license\", this);\n        controller.registerHandler(POST, \"/_license/start_basic\", this);\n        controller.registerHandler(POST, \"/_license/start_trial\", this);\n        controller.registerHandler(POST, \"/_monitoring/bulk\", this);\n        controller.registerHandler(POST, \"/_mtermvectors\", this);\n        controller.registerHandler(POST, \"/_nodes/reload_secure_settings\", this);\n        controller.registerHandler(POST, \"/_nodes/{nodeId}/reload_secure_settings\", this);\n        controller.registerHandler(POST, \"/_noop_bulk\", this);\n        controller.registerHandler(POST, \"/_noop_search\", this);\n        controller.registerHandler(POST, \"/_open\", this);\n        controller.registerHandler(POST, \"/_rank_eval\", this);\n        controller.registerHandler(POST, \"/_reindex\", this);\n        controller.registerHandler(POST, \"/_reindex/{taskId}/_rethrottle\", this);\n        controller.registerHandler(POST, \"/_render/template\", this);\n        controller.registerHandler(POST, \"/_render/template/{id}\", this);\n        controller.registerHandler(POST, \"/_rollup/job/{id}/_start\", this);\n        controller.registerHandler(POST, \"/_rollup/job/{id}/_stop\", this);\n        controller.registerHandler(POST, \"/_scripts/painless/_execute\", this);\n        controller.registerHandler(POST, \"/_scripts/{id}\", this);\n        controller.registerHandler(POST, \"/_scripts/{id}/{context}\", this);\n        controller.registerHandler(POST, \"/_search_shards\", this);\n        controller.registerHandler(POST, \"/_security/api_key\", this);\n        controller.registerHandler(POST, \"/_security/delegate_pki\", this);\n        controller.registerHandler(POST, \"/_security/oauth2/token\", this);\n        controller.registerHandler(POST, \"/_security/oidc/authenticate\", this);\n        controller.registerHandler(POST, \"/_security/oidc/logout\", this);\n        controller.registerHandler(POST, \"/_security/oidc/prepare\", this);\n        controller.registerHandler(POST, \"/_security/privilege/\", this);\n        controller.registerHandler(POST, \"/_security/realm/{realms}/_clear_cache\", this);\n        controller.registerHandler(POST, \"/_security/role/{name}\", this);\n        controller.registerHandler(POST, \"/_security/role/{name}/_clear_cache\", this);\n        controller.registerHandler(POST, \"/_security/role_mapping/{name}\", this);\n        controller.registerHandler(POST, \"/_security/saml/authenticate\", this);\n        controller.registerHandler(POST, \"/_security/saml/invalidate\", this);\n        controller.registerHandler(POST, \"/_security/saml/logout\", this);\n        controller.registerHandler(POST, \"/_security/saml/prepare\", this);\n        controller.registerHandler(POST, \"/_security/user/_has_privileges\", this);\n        controller.registerHandler(POST, \"/_security/user/_password\", this);\n        controller.registerHandler(POST, \"/_security/user/{username}\", this);\n        controller.registerHandler(POST, \"/_security/user/{username}/_disable\", this);\n        controller.registerHandler(POST, \"/_security/user/{username}/_enable\", this);\n        controller.registerHandler(POST, \"/_security/user/{username}/_has_privileges\", this);\n        controller.registerHandler(POST, \"/_security/user/{username}/_password\", this);\n        controller.registerHandler(POST, \"/_slm/_execute_retention\", this);\n        controller.registerHandler(POST, \"/_slm/policy/{name}/_execute\", this);\n        controller.registerHandler(POST, \"/_slm/start\", this);\n        controller.registerHandler(POST, \"/_slm/stop\", this);\n        controller.registerHandler(POST, \"/_snapshot/{repository}\", this);\n        controller.registerHandler(POST, \"/_snapshot/{repository}/_cleanup\", this);\n        controller.registerHandler(POST, \"/_snapshot/{repository}/_verify\", this);\n        controller.registerHandler(POST, \"/_snapshot/{repository}/{snapshot}\", this);\n        controller.registerHandler(POST, \"/_snapshot/{repository}/{snapshot}/_restore\", this);\n        controller.registerHandler(POST, \"/_tasks/_cancel\", this);\n        controller.registerHandler(POST, \"/_tasks/{task_id}/_cancel\", this);\n        controller.registerHandler(POST, \"/_template/{index}\", this);\n        controller.registerHandler(POST, \"/_transform/_preview\", this);\n        controller.registerHandler(POST, \"/_transform/{id}/_start\", this);\n        controller.registerHandler(POST, \"/_transform/{id}/_stop\", this);\n        controller.registerHandler(POST, \"/_transform/{id}/_update\", this);\n        controller.registerHandler(POST, \"/_update_by_query/{taskId}/_rethrottle\", this);\n        controller.registerHandler(POST, \"/_upgrade\", this);\n        controller.registerHandler(POST, \"/_validate/query\", this);\n        controller.registerHandler(POST, \"/_watcher/_start\", this);\n        controller.registerHandler(POST, \"/_watcher/_stop\", this);\n        controller.registerHandler(POST, \"/_watcher/watch/_execute\", this);\n        controller.registerHandler(POST, \"/_watcher/watch/{id}\", this);\n        controller.registerHandler(POST, \"/_watcher/watch/{id}/_ack\", this);\n        controller.registerHandler(POST, \"/_watcher/watch/{id}/_ack/{actions}\", this);\n        controller.registerHandler(POST, \"/_watcher/watch/{id}/_activate\", this);\n        controller.registerHandler(POST, \"/_watcher/watch/{id}/_deactivate\", this);\n        controller.registerHandler(POST, \"/_watcher/watch/{id}/_execute\", this);\n        controller.registerHandler(POST, \"/_xpack/license\", this);\n        controller.registerHandler(POST, \"/_xpack/license/start_basic\", this);\n        controller.registerHandler(POST, \"/_xpack/license/start_trial\", this);\n        controller.registerHandler(POST, \"/_xpack/monitoring/_bulk\", this);\n        controller.registerHandler(POST, \"/_xpack/rollup/job/{id}/_start\", this);\n        controller.registerHandler(POST, \"/_xpack/rollup/job/{id}/_stop\", this);\n        controller.registerHandler(POST, \"/_xpack/security/oauth2/token\", this);\n        controller.registerHandler(POST, \"/_xpack/security/privilege/\", this);\n        controller.registerHandler(POST, \"/_xpack/security/realm/{realms}/_clear_cache\", this);\n        controller.registerHandler(POST, \"/_xpack/security/role/{name}\", this);\n        controller.registerHandler(POST, \"/_xpack/security/role/{name}/_clear_cache\", this);\n        controller.registerHandler(POST, \"/_xpack/security/role_mapping/{name}\", this);\n        controller.registerHandler(POST, \"/_xpack/security/saml/authenticate\", this);\n        controller.registerHandler(POST, \"/_xpack/security/saml/invalidate\", this);\n        controller.registerHandler(POST, \"/_xpack/security/saml/logout\", this);\n        controller.registerHandler(POST, \"/_xpack/security/saml/prepare\", this);\n        controller.registerHandler(POST, \"/_xpack/security/user/_has_privileges\", this);\n        controller.registerHandler(POST, \"/_xpack/security/user/_password\", this);\n        controller.registerHandler(POST, \"/_xpack/security/user/{username}\", this);\n        controller.registerHandler(POST, \"/_xpack/security/user/{username}/_disable\", this);\n        controller.registerHandler(POST, \"/_xpack/security/user/{username}/_enable\", this);\n        controller.registerHandler(POST, \"/_xpack/security/user/{username}/_has_privileges\", this);\n        controller.registerHandler(POST, \"/_xpack/security/user/{username}/_password\", this);\n        controller.registerHandler(POST, \"/_xpack/sql\", this);\n        controller.registerHandler(POST, \"/_xpack/sql/close\", this);\n        controller.registerHandler(POST, \"/_xpack/sql/translate\", this);\n        controller.registerHandler(POST, \"/_xpack/watcher/_start\", this);\n        controller.registerHandler(POST, \"/_xpack/watcher/_stop\", this);\n        controller.registerHandler(POST, \"/_xpack/watcher/watch/_execute\", this);\n        controller.registerHandler(POST, \"/_xpack/watcher/watch/{id}\", this);\n        controller.registerHandler(POST, \"/_xpack/watcher/watch/{id}/_ack\", this);\n        controller.registerHandler(POST, \"/_xpack/watcher/watch/{id}/_ack/{actions}\", this);\n        controller.registerHandler(POST, \"/_xpack/watcher/watch/{id}/_activate\", this);\n        controller.registerHandler(POST, \"/_xpack/watcher/watch/{id}/_deactivate\", this);\n        controller.registerHandler(POST, \"/_xpack/watcher/watch/{id}/_execute\", this);\n        controller.registerHandler(POST, \"/{index}/_cache/clear\", this);\n        controller.registerHandler(POST, \"/{index}/_ccr/forget_follower\", this);\n        controller.registerHandler(POST, \"/{index}/_ccr/pause_follow\", this);\n        controller.registerHandler(POST, \"/{index}/_ccr/resume_follow\", this);\n        controller.registerHandler(POST, \"/{index}/_ccr/unfollow\", this);\n        controller.registerHandler(POST, \"/{index}/_clone/{target}\", this);\n        controller.registerHandler(POST, \"/{index}/_close\", this);\n        controller.registerHandler(POST, \"/{index}/_explain/{id}\", this);\n        controller.registerHandler(POST, \"/{index}/_field_caps\", this);\n        controller.registerHandler(POST, \"/{index}/_flush\", this);\n        controller.registerHandler(POST, \"/{index}/_flush/synced\", this);\n        controller.registerHandler(POST, \"/{index}/_forcemerge\", this);\n        controller.registerHandler(POST, \"/{index}/_freeze\", this);\n        controller.registerHandler(POST, \"/{index}/_graph/explore\", this);\n        controller.registerHandler(POST, \"/{index}/_ilm/remove\", this);\n        controller.registerHandler(POST, \"/{index}/_ilm/retry\", this);\n        controller.registerHandler(POST, \"/{index}/_mtermvectors\", this);\n        controller.registerHandler(POST, \"/{index}/_noop_bulk\", this);\n        controller.registerHandler(POST, \"/{index}/_noop_search\", this);\n        controller.registerHandler(POST, \"/{index}/_open\", this);\n        controller.registerHandler(POST, \"/{index}/_rank_eval\", this);\n        controller.registerHandler(POST, \"/{index}/_reload_search_analyzers\", this);\n        controller.registerHandler(POST, \"/{index}/_rollover\", this);\n        controller.registerHandler(POST, \"/{index}/_rollover/{new_index}\", this);\n        controller.registerHandler(POST, \"/{index}/_search_shards\", this);\n        controller.registerHandler(POST, \"/{index}/_shrink/{target}\", this);\n        controller.registerHandler(POST, \"/{index}/_split/{target}\", this);\n        controller.registerHandler(POST, \"/{index}/_termvectors\", this);\n        controller.registerHandler(POST, \"/{index}/_termvectors/{id}\", this);\n        controller.registerHandler(POST, \"/{index}/_unfreeze\", this);\n        controller.registerHandler(POST, \"/{index}/_upgrade\", this);\n        controller.registerHandler(POST, \"/{index}/_validate/query\", this);\n        controller.registerHandler(POST, \"/{index}/_xpack/graph/_explore\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_graph/explore\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_mtermvectors\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_noop_bulk\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_noop_search\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_termvector\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_termvectors\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_validate/query\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_xpack/graph/_explore\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/{id}/_explain\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/{id}/_termvector\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/{id}/_termvectors\", this);\n        controller.registerHandler(POST, \"_rollup_search\", this);\n        controller.registerHandler(POST, \"{index}/_rollup_search\", this);\n        controller.registerHandler(POST, \"_xpack/migration/upgrade/{index}\", this);\n        controller.registerHandler(PUT, \"/_ccr/auto_follow/{name}\", this);\n        controller.registerHandler(PUT, \"/_dcdr/auto_replication/{name}\", this);\n        controller.registerHandler(PUT, \"/_dcdr/{index}/replication/create\", this);\n        controller.registerHandler(PUT, \"/_enrich/policy/{name}\", this);\n        controller.registerHandler(PUT, \"/_enrich/policy/{name}/_execute\", this);\n        controller.registerHandler(PUT, \"/_ilm/policy/{name}\", this);\n        controller.registerHandler(PUT, \"/_ingest/pipeline/{id}\", this);\n        controller.registerHandler(PUT, \"/_license\", this);\n        controller.registerHandler(PUT, \"/_noop_bulk\", this);\n        controller.registerHandler(PUT, \"/_monitoring/bulk\", this);\n        controller.registerHandler(PUT, \"/_rollup/job/{id}\", this);\n        controller.registerHandler(PUT, \"/_scripts/{id}\", this);\n        controller.registerHandler(PUT, \"/_scripts/{id}/{context}\", this);\n        controller.registerHandler(PUT, \"/_security/api_key\", this);\n        controller.registerHandler(PUT, \"/_security/privilege/\", this);\n        controller.registerHandler(PUT, \"/_security/role/{name}\", this);\n        controller.registerHandler(PUT, \"/_security/role_mapping/{name}\", this);\n        controller.registerHandler(PUT, \"/_security/user/_password\", this);\n        controller.registerHandler(PUT, \"/_security/user/{username}\", this);\n        controller.registerHandler(PUT, \"/_security/user/{username}/_disable\", this);\n        controller.registerHandler(PUT, \"/_security/user/{username}/_enable\", this);\n        controller.registerHandler(PUT, \"/_security/user/{username}/_password\", this);\n        controller.registerHandler(PUT, \"/_settings\", this);\n        controller.registerHandler(PUT, \"/_slm/policy/{name}\", this);\n        controller.registerHandler(PUT, \"/_slm/policy/{name}/_execute\", this);\n        controller.registerHandler(PUT, \"/_snapshot/{repository}\", this);\n        controller.registerHandler(PUT, \"/_snapshot/{repository}/{snapshot}\", this);\n        controller.registerHandler(PUT, \"/_template/{index}\", this);\n        controller.registerHandler(PUT, \"/_transform/{id}/\", this);\n        controller.registerHandler(PUT, \"/_watcher/watch/_execute\", this);\n        controller.registerHandler(PUT, \"/_watcher/watch/{id}\", this);\n        controller.registerHandler(PUT, \"/_watcher/watch/{id}/_ack\", this);\n        controller.registerHandler(PUT, \"/_watcher/watch/{id}/_ack/{actions}\", this);\n        controller.registerHandler(PUT, \"/_watcher/watch/{id}/_activate\", this);\n        controller.registerHandler(PUT, \"/_watcher/watch/{id}/_deactivate\", this);\n        controller.registerHandler(PUT, \"/_watcher/watch/{id}/_execute\", this);\n        controller.registerHandler(PUT, \"/_xpack/license\", this);\n        controller.registerHandler(PUT, \"/_xpack/monitoring/_bulk\", this);\n        controller.registerHandler(PUT, \"/_xpack/rollup/job/{id}\", this);\n        controller.registerHandler(PUT, \"/_xpack/security/privilege/\", this);\n        controller.registerHandler(PUT, \"/_xpack/security/role/{name}\", this);\n        controller.registerHandler(PUT, \"/_xpack/security/role_mapping/{name}\", this);\n        controller.registerHandler(PUT, \"/_xpack/security/user/_password\", this);\n        controller.registerHandler(PUT, \"/_xpack/security/user/{username}\", this);\n        controller.registerHandler(PUT, \"/_xpack/security/user/{username}/_disable\", this);\n        controller.registerHandler(PUT, \"/_xpack/security/user/{username}/_enable\", this);\n        controller.registerHandler(PUT, \"/_xpack/security/user/{username}/_password\", this);\n        controller.registerHandler(PUT, \"/_xpack/watcher/watch/_execute\", this);\n        controller.registerHandler(PUT, \"/_xpack/watcher/watch/{id}\", this);\n        controller.registerHandler(PUT, \"/_xpack/watcher/watch/{id}/_ack\", this);\n        controller.registerHandler(PUT, \"/_xpack/watcher/watch/{id}/_ack/{actions}\", this);\n        controller.registerHandler(PUT, \"/_xpack/watcher/watch/{id}/_activate\", this);\n        controller.registerHandler(PUT, \"/_xpack/watcher/watch/{id}/_deactivate\", this);\n        controller.registerHandler(PUT, \"/_xpack/watcher/watch/{id}/_execute\", this);\n        controller.registerHandler(PUT, \"/{index}/_ccr/follow\", this);\n        controller.registerHandler(PUT, \"/{index}/_clone/{target}\", this);\n        controller.registerHandler(PUT, \"/{index}/_noop_bulk\", this);\n        controller.registerHandler(PUT, \"/{index}/_shrink/{target}\", this);\n        controller.registerHandler(PUT, \"/{index}/_split/{target}\", this);\n        controller.registerHandler(PUT, \"/{index}/{type}/_noop_bulk\", this);\n\n        controller.registerHandler(GET, \"/_analyze\", this);\n        controller.registerHandler(POST, \"/_analyze\", this);\n\n        controller.registerHandler(GET, \"/_settings\", this);\n        controller.registerHandler(GET, \"/_settings/{name}\", this);\n\n        controller.registerHandler(POST, \"/_mapping/check\", this);\n        controller.registerHandler(PUT, \"/_mapping/check\", this);\n\n        controller.registerHandler(GET, \"/_alias\", this);\n        controller.registerHandler(GET, \"/_alias/{name}\", this);\n        controller.registerHandler(GET, \"/_aliases\", this);\n\n        controller.registerHandler(PUT, \"/_alias\", this);\n        controller.registerHandler(PUT, \"/_alias/{name}\", this);\n        controller.registerHandler(PUT, \"/_aliases/{name}\", this);\n        controller.registerHandler(POST, \"/_alias/{name}\", this);\n        controller.registerHandler(POST, \"/_aliases\", this);\n        controller.registerHandler(POST, \"/_aliases/{name}\", this);\n        controller.registerHandler(HEAD, \"/_alias/{name}\", this);\n\n        controller.registerHandler(PUT, \"/_mapping/{type}\", this);\n        controller.registerHandler(PUT, \"/_mappings/{type}\", this);\n        controller.registerHandler(POST, \"/_mapping/{type}\", this);\n        controller.registerHandler(POST, \"/_mappings/{type}\", this);\n\n        controller.registerHandler(GET, \"/_refresh\", this);\n        controller.registerHandler(POST, \"/_refresh\", this);\n        \n        controller.registerHandler(GET, \"/_resolve/index/{name}\", this);\n\n//        controller.registerHandler(POST, \"/{index}/_analyze\", this);\n//        controller.registerHandler(GET, \"/{index}/_analyze\", this);\n//\n//        controller.registerHandler(GET, \"/{index}/_setting/{name}\", this);\n//        controller.registerHandler(GET, \"/{index}/_settings\", this);\n//        controller.registerHandler(GET, \"/{index}/_settings/{name}\", this);\n//\n//        controller.registerHandler(POST, \"/{index}/{type}/_mapping/check\", this);\n//        controller.registerHandler(PUT, \"/{index}/{type}/_mapping/check\", this);\n//        controller.registerHandler(DELETE, \"/{index}/_alias/{name}\", this);\n//        controller.registerHandler(DELETE, \"/{index}/_aliases/{name}\", this);\n//        controller.registerHandler(POST, \"/{index}/_alias/{name}\", this);\n//        controller.registerHandler(POST, \"/{index}/_aliases/{name}\", this);\n//        controller.registerHandler(PUT, \"/{index}/_alias\", this);\n//        controller.registerHandler(PUT, \"/{index}/_alias/{name}\", this);\n//        controller.registerHandler(PUT, \"/{index}/_aliases\", this);\n//        controller.registerHandler(PUT, \"/{index}/_aliases/{name}\", this);\n//\n//        controller.registerHandler(HEAD, \"/{index}/_alias\", this);\n//        controller.registerHandler(HEAD, \"/{index}/_alias/{name}\", this);\n//        controller.registerHandler(GET, \"/{index}/_alias\", this);\n//        controller.registerHandler(GET, \"/{index}/_alias/{name}\", this);\n//\n//        controller.registerHandler(PUT, \"/{index}/_mapping/\", this);\n//        controller.registerHandler(PUT, \"/{index}/_mapping/{type}\", this);\n//        controller.registerHandler(PUT, \"/{index}/_mappings/\", this);\n//        controller.registerHandler(PUT, \"/{index}/_mappings/{type}\", this);\n//        controller.registerHandler(PUT, \"/{index}/{type}/_mapping\", this);\n//        controller.registerHandler(PUT, \"/{index}/{type}/_mappings\", this);\n//        controller.registerHandler(POST, \"/{index}/{type}/_mapping\", this);\n//        controller.registerHandler(POST, \"/{index}/{type}/_mappings\", this);\n//        controller.registerHandler(POST, \"/{index}/_mapping/\", this);\n//        controller.registerHandler(POST, \"/{index}/_mapping/{type}\", this);\n//        controller.registerHandler(POST, \"/{index}/_mappings/\", this);\n//        controller.registerHandler(POST, \"/{index}/_mappings/{type}\", this);\n//        controller.registerHandler(HEAD, \"/{index}/_mapping/{type}\", this);\n//\n//        controller.registerHandler(GET, \"/{index}/_refresh\", this);\n//        controller.registerHandler(POST, \"/{index}/_refresh\", this);\n//\n//        controller.registerHandler(POST, \"/{index}/_delete_by_query\", this);\n//        controller.registerHandler(POST, \"/{index}/{type}/_delete_by_query\", this);\n//\n//        controller.registerHandler(POST, \"/{index}/_update_by_query\", this);\n//        controller.registerHandler(POST, \"/{index}/{type}/_update_by_query\", this);\n    }\n\n    @Override\n    public String name() {\n        return restCommonAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restCommonAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/RestMainController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.action.RestMainAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.HEAD;\n\n/**\n * @author fitz\n * @date 2021/5/26 3:49 下午\n */\n@Controller\npublic class RestMainController extends BaseHttpRestController {\n    @Autowired\n    private RestMainAction restMainAction;\n\n    public RestMainController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/\", this);\n        controller.registerHandler(HEAD, \"/\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restMainAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restMainAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/cat/RestIndicesController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.cat;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.action.cat.RestIndicesAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\n/**\n * @author fitz\n * @date 2021/5/26 3:23 下午\n */\n@Controller\npublic class RestIndicesController extends BaseHttpRestController {\n    @Autowired\n    private RestIndicesAction restIndicesAction;\n\n    public RestIndicesController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/_cat/indices\", this);\n        controller.registerHandler(GET, \"/_cat/indices/{index}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restIndicesAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restIndicesAction.handleRequest(queryContext);\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/cluster/RestClusterHealthController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.cluster;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.action.admin.cluster.health.RestClusterHealthAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\n@Controller\npublic class RestClusterHealthController extends BaseHttpRestController {\n\n    @Autowired\n    private RestClusterHealthAction restClusterHealthAction;\n\n    public RestClusterHealthController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler( RestRequest.Method.GET, \"/_cluster/health\", this);\n        controller.registerHandler(RestRequest.Method.GET, \"/_cluster/health/{index}\", this);\n    }\n\n    @Override\n    public String name() {\n        return restClusterHealthAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restClusterHealthAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/cluster/RestNodesInfoController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.cluster;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.action.admin.cluster.node.info.RestNodesInfoAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\n\n/**\n * @author fitz\n * @date 2021/5/26 3:07 下午\n */\n@Controller\npublic class RestNodesInfoController extends BaseHttpRestController {\n\n    @Autowired\n    private RestNodesInfoAction restNodesInfoAction;\n\n    public RestNodesInfoController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/_nodes\", this);\n        controller.registerHandler(GET, \"/_nodesclean\", this);\n        // this endpoint is used for metrics, not for nodeIds, like /_nodes/fs\n        controller.registerHandler(GET, \"/_nodes/{nodeId}\", this);\n        controller.registerHandler(GET, \"/_nodes/{nodeId}/{metrics}\", this);\n        // added this endpoint to be aligned with stats\n        controller.registerHandler(GET, \"/_nodes/{nodeId}/info/{metrics}\", this);\n\n    }\n\n    @Override\n    protected String name() {\n        return restNodesInfoAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restNodesInfoAction.handleRequest(queryContext);\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/cluster/RestPutClusterSettingsController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.cluster;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.rest.controller.AdminController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.stereotype.Controller;\n\n/**\n * @author fitz\n * @date 2021/5/26 12:54 下午\n */\n@Controller\npublic class RestPutClusterSettingsController extends AdminController {\n\n    public static final String NAME = \"restPutClusterSettings\";\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.PUT, \"/_cluster/settings\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        if (client == null) {\n            client = esRestClientService.getAdminClient(actionName);\n        }\n        directRequest(client, queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/fieldstats/RestFieldStatsController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.fieldstats;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.action.fieldstats.RestFieldStatsAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author fitz\n * @date 2021/5/26 3:35 下午\n */\n@Controller\npublic class RestFieldStatsController extends BaseHttpRestController {\n\n    @Autowired\n    private RestFieldStatsAction restFieldStatsAction;\n\n    public RestFieldStatsController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/_field_stats\", this);\n        controller.registerHandler(POST, \"/_field_stats\", this);\n        controller.registerHandler(GET, \"/{index}/_field_stats\", this);\n        controller.registerHandler(POST, \"/{index}/_field_stats\", this);\n\n    }\n\n    @Override\n    protected String name() {\n        return restFieldStatsAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restFieldStatsAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/RestAnalyzeController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.RestAnalyzeAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author zhaoqingrong\n * @date 2021/6/8\n * @desc 招行需求，开放 restAnalyzeAction 给普通账号\n */\n@Controller\npublic class RestAnalyzeController extends BaseHttpRestController {\n\n    @Autowired\n    RestAnalyzeAction restAnalyzeAction;\n\n    public RestAnalyzeController() {\n        //pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/{index}/_analyze\", this);\n        controller.registerHandler(POST, \"/{index}/_analyze\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restAnalyzeAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restAnalyzeAction.handleRequest(queryContext);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/RestCreateIndexController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.create.RestCreateIndexAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\n/**\n * @author fitz\n * @date 2021/5/26 1:16 下午\n */\n@Controller\npublic class RestCreateIndexController extends BaseHttpRestController {\n\n    @Autowired\n    RestCreateIndexAction restCreateIndexAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.PUT, \"/{index}\", this);\n        controller.registerHandler(RestRequest.Method.POST, \"/{index}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restCreateIndexAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restCreateIndexAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/RestDeleteIndexController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.delete.RestDeleteIndexAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\n/**\n * @author fitz\n * @date 2021/5/26 1:36 下午\n */\n@Controller\npublic class RestDeleteIndexController extends BaseHttpRestController {\n\n    @Autowired\n    RestDeleteIndexAction restDeleteIndexAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.DELETE, \"/{index}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restDeleteIndexAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restDeleteIndexAction.handleRequest(queryContext);\n    }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/RestGetAliasesController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.RestGetAliasesAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.HEAD;\n\n/**\n * @author didi\n * @date 2021-09-24 3:33 下午\n */\n@Controller\npublic class RestGetAliasesController extends BaseHttpRestController {\n    @Autowired\n    RestGetAliasesAction restGetAliasesAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/{index}/_alias\", this);\n        controller.registerHandler(HEAD, \"/{index}/_alias\", this);\n        controller.registerHandler(GET, \"/{index}/_alias/{name}\", this);\n        controller.registerHandler(HEAD, \"/{index}/_alias/{name}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restGetAliasesAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restGetAliasesAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/RestIndexDeleteAliasesController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.RestIndexDeleteAliasesAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.DELETE;\n\n/**\n * @author didi\n * @date 2021-09-24 3:36 下午\n */\n@Controller\npublic class RestIndexDeleteAliasesController extends BaseHttpRestController {\n\n    @Autowired\n    RestIndexDeleteAliasesAction restIndexDeleteAliasesAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(DELETE, \"/{index}/_alias/{name}\", this);\n        controller.registerHandler(DELETE, \"/{index}/_aliases/{name}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restIndexDeleteAliasesAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restIndexDeleteAliasesAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/RestIndexPutAliasController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.RestIndexPutAliasAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\nimport static org.elasticsearch.rest.RestRequest.Method.PUT;\n\n/**\n * @author didi\n * @date 2021-09-24 3:52 下午\n */\n@Controller\npublic class RestIndexPutAliasController extends BaseHttpRestController {\n\n    @Autowired\n    RestIndexPutAliasAction restIndexPutAliasAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(PUT, \"/{index}/_alias/{name}\", this);\n        controller.registerHandler(PUT, \"/{index}/_aliases/{name}\", this);\n        controller.registerHandler(PUT, \"/{index}/_alias\", this);\n        controller.registerHandler(POST, \"/{index}/_alias/{name}\", this);\n        controller.registerHandler(POST, \"/{index}/_aliases/{name}\", this);\n        controller.registerHandler(PUT, \"/{index}/_aliases\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restIndexPutAliasAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restIndexPutAliasAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/RestPutIndexSettingsController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.settings.RestPutIndexSettingsAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\n/**\n * @author fitz\n * @date 2021/5/26 1:41 下午\n */\n@Controller\npublic class RestPutIndexSettingsController extends BaseHttpRestController {\n\n    @Autowired\n    RestPutIndexSettingsAction restPutIndexSettingsAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.PUT, \"/{index}/_settings\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restPutIndexSettingsAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restPutIndexSettingsAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/RestRefreshController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.RestRefreshAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author didi\n * @date 2021-09-24 4:18 下午\n */\n@Controller\npublic class RestRefreshController extends BaseHttpRestController {\n\n    @Autowired\n    private RestRefreshAction restRefreshAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(POST, \"/{index}/_refresh\", this);\n        controller.registerHandler(GET, \"/{index}/_refresh\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restRefreshAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restRefreshAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/mapping/RestCheckMappingController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices.mapping;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.RestCheckMappingAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\nimport static org.elasticsearch.rest.RestRequest.Method.PUT;\n\n@Controller\npublic class RestCheckMappingController extends BaseHttpRestController {\n\n    @Autowired\n    RestCheckMappingAction restCheckMappingAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(PUT, \"/{index}/{type}/_mapping/check\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_mapping/check\", this);\n    }\n\n    @Override\n    public String name() {\n        return restCheckMappingAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restCheckMappingAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/mapping/RestGetFieldMappingController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices.mapping;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.mapping.get.RestGetFieldMappingAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\n\n/**\n * @author fitz\n * @date 2021/5/26 3:57 下午\n */\n@Controller\npublic class RestGetFieldMappingController extends BaseHttpRestController {\n    @Autowired\n    private RestGetFieldMappingAction restGetFieldMappingAction;\n\n    public RestGetFieldMappingController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/_mapping/field/{fields}\", this);\n        controller.registerHandler(GET, \"/_mapping/{type}/field/{fields}\", this);\n        controller.registerHandler(GET, \"/{index}/_mapping/field/{fields}\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_mapping/field/{fields}\", this);\n        controller.registerHandler(GET, \"/{index}/_mapping/{type}/field/{fields}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restGetFieldMappingAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restGetFieldMappingAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/mapping/RestGetMappingController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices.mapping;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.mapping.get.RestGetMappingAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\n\n/**\n * @author fitz\n * @date 2021/5/26 3:59 下午\n */\n@Controller\npublic class RestGetMappingController extends BaseHttpRestController {\n    @Autowired\n    private RestGetMappingAction restGetMappingAction;\n\n    public RestGetMappingController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/{index}/{type}/_mapping\", this);\n        controller.registerHandler(GET, \"/{index}/_mapping\", this);\n        controller.registerHandler(GET, \"/{index}/_mappings\", this);\n        controller.registerHandler(GET, \"/{index}/_mappings/{type}\", this);\n        controller.registerHandler(GET, \"/{index}/_mapping/{type}\", this);\n        controller.registerHandler(GET, \"/_mapping/{type}\", this);\n        controller.registerHandler(GET, \"/_mapping\", this);\n        controller.registerHandler(GET, \"/_mappings\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restGetMappingAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restGetMappingAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/admin/indices/mapping/RestPutMappingController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.admin.indices.mapping;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.RestPutMappingAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\nimport static org.elasticsearch.rest.RestRequest.Method.PUT;\n\n/**\n * @author didi\n * @date 2021-09-24 3:54 下午\n */\n@Controller\npublic class RestPutMappingController extends BaseHttpRestController {\n\n    @Autowired\n    RestPutMappingAction restPutMappingAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(PUT, \"/{index}/_mapping/\", this);\n        controller.registerHandler(PUT, \"/{index}/{type}/_mapping\", this);\n        controller.registerHandler(PUT, \"/{index}/_mapping/{type}\", this);\n\n        controller.registerHandler(POST, \"/{index}/_mapping/\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_mapping\", this);\n        controller.registerHandler(POST, \"/{index}/_mapping/{type}\", this);\n\n        controller.registerHandler(PUT, \"/{index}/_mappings/\", this);\n        controller.registerHandler(PUT, \"/{index}/{type}/_mappings\", this);\n        controller.registerHandler(PUT, \"/{index}/_mappings/{type}\", this);\n\n        controller.registerHandler(POST, \"/{index}/_mappings/\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_mappings\", this);\n        controller.registerHandler(POST, \"/{index}/_mappings/{type}\", this);\n\n    }\n\n    @Override\n    protected String name() {\n        return restPutMappingAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restPutMappingAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/bulk/RestBulkController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.bulk;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.bulk.RestBulkAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\nimport static org.elasticsearch.rest.RestRequest.Method.PUT;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:10 下午\n */\n@Controller\npublic class RestBulkController extends BaseHttpRestController {\n    @Autowired\n    private RestBulkAction restBulkAction;\n\n    public RestBulkController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(POST, \"/_bulk\", this);\n        controller.registerHandler(PUT, \"/_bulk\", this);\n        controller.registerHandler(POST, \"/{index}/_bulk\", this);\n        controller.registerHandler(PUT, \"/{index}/_bulk\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_bulk\", this);\n        controller.registerHandler(PUT, \"/{index}/{type}/_bulk\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restBulkAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restBulkAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/count/RestCountController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.count;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.count.RestCountAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:14 下午\n */\n@Controller\npublic class RestCountController extends BaseHttpRestController {\n    @Autowired\n    private RestCountAction restCountAction;\n\n    public RestCountController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(POST, \"/_count\", this);\n        controller.registerHandler(GET, \"/_count\", this);\n        controller.registerHandler(POST, \"/{index}/_count\", this);\n        controller.registerHandler(GET, \"/{index}/_count\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_count\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_count\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restCountAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restCountAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/document/RestDeleteController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.document;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.document.RestDeleteAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.DELETE;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:18 下午\n */\n@Controller\npublic class RestDeleteController extends BaseHttpRestController {\n    @Autowired\n    private RestDeleteAction restDeleteAction;\n\n    public RestDeleteController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(DELETE, \"/{index}/_doc/{id}\", this);\n        controller.registerHandler(DELETE, \"/{index}/{type}/{id}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restDeleteAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restDeleteAction.handleRequest(queryContext);\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/document/RestIndexController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.document;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.document.RestIndexAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\nimport static org.elasticsearch.rest.RestRequest.Method.PUT;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:18 下午\n */\n@Controller\npublic class RestIndexController extends BaseHttpRestController {\n    @Autowired\n    private RestIndexAction restIndexAction;\n\n    public RestIndexController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(POST, \"/{index}/_doc\", this); // auto id creation\n        controller.registerHandler(PUT, \"/{index}/_doc/{id}\", this);\n        controller.registerHandler(POST, \"/{index}/_doc/{id}\", this);\n        controller.registerHandler(PUT, \"/{index}/_create/{id}\", this);\n        controller.registerHandler(POST, \"/{index}/_create/{id}/\", this);\n        controller.registerHandler(POST, \"/{index}/{type}\", this); // auto id creation\n        controller.registerHandler(PUT, \"/{index}/{type}/{id}\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/{id}\", this);\n        controller.registerHandler(PUT, \"/{index}/{type}/{id}/_create\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/{id}/_create\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restIndexAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restIndexAction.handleRequest(queryContext);\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/document/RestUpdateController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.document;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.document.RestUpdateAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:18 下午\n */\n@Controller\npublic class RestUpdateController extends BaseHttpRestController {\n    @Autowired\n    private RestUpdateAction restUpdateAction;\n\n    public RestUpdateController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(POST, \"/{index}/_update/{id}\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/{id}/_update\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restUpdateAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restUpdateAction.handleRequest(queryContext);\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/get/RestGetController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.get;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.get.RestGetAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:27 下午\n */\n@Controller\npublic class RestGetController extends BaseHttpRestController {\n    @Autowired\n    private RestGetAction restGetAction;\n\n    public RestGetController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/{index}/_doc/{id}\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/{id}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restGetAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restGetAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/get/RestGetSourceController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.get;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.get.RestGetSourceAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:27 下午\n */\n@Controller\npublic class RestGetSourceController extends BaseHttpRestController {\n    @Autowired\n    private RestGetSourceAction restGetSourceAction;\n\n    public RestGetSourceController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/{index}/{type}/{id}/_source\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restGetSourceAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restGetSourceAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/get/RestHeadController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.get;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.get.RestHeadAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.HEAD;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:27 下午\n */\n@Controller\npublic class RestHeadController extends BaseHttpRestController {\n    @Autowired\n    private RestHeadAction restHeadAction;\n\n    public RestHeadController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(HEAD, \"/{index}/_doc/{id}\", this);\n        controller.registerHandler(HEAD, \"/{index}/{type}/{id}\", this);\n        controller.registerHandler(HEAD, \"/{index}/{type}/{id}/_source\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restHeadAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restHeadAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/get/RestMultiGetController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.get;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.get.RestMultiGetAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:27 下午\n */\n@Controller\npublic class RestMultiGetController extends BaseHttpRestController {\n    @Autowired\n    private RestMultiGetAction restMultiGetAction;\n\n    public RestMultiGetController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/_mget\", this);\n        controller.registerHandler(POST, \"/_mget\", this);\n        controller.registerHandler(POST, \"/{index}/_mget\", this);\n        controller.registerHandler(GET, \"/{index}/_mget\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_mget\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_mget\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restMultiGetAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restMultiGetAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/reindex/RestDeleteByQueryController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.reindex;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.action.reindex.RestDeleteByQueryAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n@Controller\npublic class RestDeleteByQueryController extends BaseHttpRestController {\n\n    @Autowired\n    private RestDeleteByQueryAction restDeleteByQueryAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(POST, \"/{index}/_delete_by_query\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_delete_by_query\", this);\n    }\n\n    @Override\n    public String name() {\n        return restDeleteByQueryAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restDeleteByQueryAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/reindex/RestUpdateByQueryController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.reindex;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.action.reindex.RestUpdateByQueryAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n@Controller\npublic class RestUpdateByQueryController extends BaseHttpRestController {\n\n    @Autowired\n    RestUpdateByQueryAction restUpdateByQueryAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(POST, \"/{index}/_update_by_query\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_update_by_query\", this);\n    }\n\n    @Override\n    public String name() {\n        return restUpdateByQueryAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restUpdateByQueryAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/search/RestClearScrollController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.search;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.search.RestClearScrollAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.DELETE;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:27 下午\n */\n@Controller\npublic class RestClearScrollController extends BaseHttpRestController {\n    @Autowired\n    private RestClearScrollAction restClearScrollAction;\n\n    public RestClearScrollController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(DELETE, \"/_search/scroll\", this);\n        controller.registerHandler(DELETE, \"/_search/scroll/{scroll_id}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restClearScrollAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restClearScrollAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/search/RestMultiSearchController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.search;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.search.RestMultiSearchAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:27 下午\n */\n@Controller\npublic class RestMultiSearchController extends BaseHttpRestController {\n    @Autowired\n    private RestMultiSearchAction restMultiSearchAction;\n\n    public RestMultiSearchController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/_msearch\", this);\n        controller.registerHandler(POST, \"/_msearch\", this);\n        controller.registerHandler(GET, \"/{index}/_msearch\", this);\n        controller.registerHandler(POST, \"/{index}/_msearch\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_msearch\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_msearch\", this);\n\n        controller.registerHandler(GET, \"/_msearch/template\", this);\n        controller.registerHandler(POST, \"/_msearch/template\", this);\n        controller.registerHandler(GET, \"/{index}/_msearch/template\", this);\n        controller.registerHandler(POST, \"/{index}/_msearch/template\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_msearch/template\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_msearch/template\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restMultiSearchAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restMultiSearchAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/search/RestSearchController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.search;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.search.RestSearchAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:27 下午\n */\n@Controller\npublic class RestSearchController extends BaseHttpRestController {\n    @Autowired\n    private RestSearchAction restSearchAction;\n\n    public RestSearchController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/_search\", this);\n        controller.registerHandler(POST, \"/_search\", this);\n        controller.registerHandler(GET, \"/{index}/_search\", this);\n        controller.registerHandler(POST, \"/{index}/_search\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_search\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_search\", this);\n        controller.registerHandler(GET, \"/{index}/_search/template\", this);\n        controller.registerHandler(POST, \"/{index}/_search/template\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_search/template\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_search/template\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restSearchAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restSearchAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/search/RestSearchScrollController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.search;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.search.RestSearchScrollAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:27 下午\n */\n@Controller\npublic class RestSearchScrollController extends BaseHttpRestController {\n    @Autowired\n    private RestSearchScrollAction restSearchScrollAction;\n\n    public RestSearchScrollController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/_search/scroll\", this);\n        controller.registerHandler(POST, \"/_search/scroll\", this);\n        controller.registerHandler(GET, \"/_search/scroll/{scroll_id}\", this);\n        controller.registerHandler(POST, \"/_search/scroll/{scroll_id}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restSearchScrollAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restSearchScrollAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/search/RestSpatialMultiSearchController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.search;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.search.RestSpatialMultiSearchAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:27 下午\n */\n@Controller\npublic class RestSpatialMultiSearchController extends BaseHttpRestController {\n    @Autowired\n    private RestSpatialMultiSearchAction restSpatialMultiSearchAction;\n\n    public RestSpatialMultiSearchController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/_spatial_msearch\", this);\n        controller.registerHandler(POST, \"/_spatial_msearch\", this);\n        controller.registerHandler(GET, \"/{index}/_spatial_msearch\", this);\n        controller.registerHandler(POST, \"/{index}/_spatial_msearch\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_spatial_msearch\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_spatial_msearch\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restSpatialMultiSearchAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restSpatialMultiSearchAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/search/RestSpatialSearchController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.search;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.search.RestSpatialSearchAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\nimport static org.elasticsearch.rest.RestRequest.Method.POST;\n\n/**\n * @author fitz\n * @date 2021/5/26 4:27 下午\n */\n@Controller\npublic class RestSpatialSearchController extends BaseHttpRestController {\n    @Autowired\n    private RestSpatialSearchAction restSpatialSearchAction;\n\n    public RestSpatialSearchController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/_spatial_search\", this);\n        controller.registerHandler(POST, \"/_spatial_search\", this);\n        controller.registerHandler(GET, \"/{index}/_spatial_search\", this);\n        controller.registerHandler(POST, \"/{index}/_spatial_search\", this);\n        controller.registerHandler(GET, \"/{index}/{type}/_spatial_search\", this);\n        controller.registerHandler(POST, \"/{index}/{type}/_spatial_search\", this);\n    }\n\n    @Override\n    protected String name() {\n        return restSpatialSearchAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restSpatialSearchAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/settings/RestGetSettingsController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.settings;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.admin.indices.settings.RestGetSettingsAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport static org.elasticsearch.rest.RestRequest.Method.GET;\n\n@Controller\npublic class RestGetSettingsController extends BaseHttpRestController {\n\n    @Autowired\n    RestGetSettingsAction restGetSettingsAction;\n\n    @Override\n    protected void register() {\n        controller.registerHandler(GET, \"/{index}/_settings\", this);\n        controller.registerHandler(GET, \"/{index}/_settings/{name}\", this);\n        controller.registerHandler(GET, \"/{index}/_setting/{name}\", this);\n    }\n\n    @Override\n    public String name() {\n        return restGetSettingsAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        restGetSettingsAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/sql/RestSQLController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.sql;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.sql.SQLAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\n@Controller\npublic class RestSQLController extends BaseHttpRestController {\n\n    @Autowired\n    private SQLAction sqlAction;\n\n    public RestSQLController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_sql\", this);\n\t\tcontroller.registerHandler(RestRequest.Method.POST, \"/_sql\", this);\n    }\n\n    @Override\n    public String name() {\n        return sqlAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        sqlAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/es/sql/RestSQLExplainController.java",
    "content": "package com.didi.arius.gateway.rest.controller.es.sql;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.es.http.sql.SQLExplainAction;\nimport com.didi.arius.gateway.rest.controller.BaseHttpRestController;\nimport org.elasticsearch.rest.RestRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\n@Controller\npublic class RestSQLExplainController extends BaseHttpRestController {\n\n    @Autowired\n    private SQLExplainAction sqlExplainAction;\n\n    public RestSQLExplainController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler( RestRequest.Method.GET, \"/_sql/explain\", this);\n        controller.registerHandler( RestRequest.Method.POST, \"/_sql/explain\", this);\n    }\n\n    @Override\n    protected String name() {\n        return sqlExplainAction.name();\n    }\n\n    @Override\n    protected void handleRequest(QueryContext queryContext) throws Exception {\n        sqlExplainAction.handleRequest(queryContext);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/gwadmin/AppInfoController.java",
    "content": "package com.didi.arius.gateway.rest.controller.gwadmin;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.rest.controller.AdminController;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.Map;\n\n@Controller\npublic class AppInfoController extends AdminController {\n\n    private static final String NAME = \"appInfo\";\n\n    public AppInfoController() {\n        // pass\n    }\n\n    @Override\n    public void register() {\n        controller.registerHandler( RestRequest.Method.GET, \"/_gwadmin/appinfo\", this);\n    }\n\n    @Override\n    public String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        Map<Integer, AppDetail> appDetails = appService.getAppDetails();\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, JSON.toJSONString(appDetails.values())));\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/gwadmin/CheckIndexModeController.java",
    "content": "package com.didi.arius.gateway.rest.controller.gwadmin;\n\nimport com.didi.arius.gateway.common.exception.TooManyIndexException;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.utils.IndexTire;\nimport com.didi.arius.gateway.rest.controller.AdminController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchRequest;\nimport com.didi.arius.gateway.elasticsearch.client.gateway.search.ESSearchResponse;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * @author fitz\n * @date 2021/5/25 2:10 下午\n */\n@Controller\npublic class CheckIndexModeController extends AdminController {\n    public static final String NAME = \"checkIndexMode\";\n\n    @Value(\"${gateway.log.index.name}\")\n    private String indexNames;\n\n    public CheckIndexModeController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwadmin/checkIndexMode/{appid}\", this);\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwadmin/checkIndexMode\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n\n        int appid = request.paramAsInt(\"appid\", 0);\n        Map<Integer, Map<String, AtomicInteger>> checkResult = new TreeMap<>();\n\n        if (appid == 0) {\n            for (int inAppid : appService.getAppDetails().keySet()) {\n                Map<String, AtomicInteger> appidCount = checkAppidResult(inAppid, client, queryContext, request);\n                checkResult.put(inAppid, appidCount);\n            }\n        } else {\n            Map<String, AtomicInteger> appidCount = checkAppidResult(appid, client, queryContext, request);\n            checkResult.put(appid, appidCount);\n        }\n\n        StringBuilder builder = new StringBuilder(\"final check result:\\n\");\n        builder.append(String.format(\"appid:%40s:count%n\", \"index\"));\n        for (Map.Entry<Integer, Map<String, AtomicInteger>> entry : checkResult.entrySet()) {\n            int outAppid = entry.getKey();\n            for (Map.Entry<String, AtomicInteger> inEntry : entry.getValue().entrySet()) {\n                builder.append(String.format(\"%5d:%40s:%d%n\", outAppid, inEntry.getKey(), inEntry.getValue().get()));\n            }\n        }\n\n        logger.info(builder.toString());\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, builder.toString()));\n\n    }\n\n    private Map<String, AtomicInteger> checkAppidResult(int inAppid, ESClient client, QueryContext queryContext, RestRequest request) {\n        ESSearchRequest esSearchRequest = new ESSearchRequest();\n        esSearchRequest.indices(indexNames);\n        esSearchRequest.putHeader(\"requestId\", queryContext.getRequestId());\n        esSearchRequest.putHeader(\"Authorization\", request.getHeader(\"Authorization\"));\n\n        esSearchRequest.source(String.format(\"{\\n\" +\n                \"  \\\"size\\\": 0, \\n\" +\n                \"  \\\"query\\\": {\\n\" +\n                \"    \\\"bool\\\": {\\n\" +\n                \"      \\\"must\\\": [\\n\" +\n                \"        {\\n\" +\n                \"          \\\"term\\\": {\\n\" +\n                \"            \\\"dltag\\\": {\\n\" +\n                \"              \\\"value\\\": \\\"_arius_query_request_indices\\\"\\n\" +\n                \"            }\\n\" +\n                \"          }\\n\" +\n                \"        },\\n\" +\n                \"        {\\n\" +\n                \"          \\\"term\\\": {\\n\" +\n                \"            \\\"appid\\\": {\\n\" +\n                \"              \\\"value\\\": \\\"%d\\\"\\n\" +\n                \"            }\\n\" +\n                \"          }\\n\" +\n                \"        }\\n\" +\n                \"      ],\\n\" +\n                \"      \\\"must_not\\\": [\\n\" +\n                \"        {\\n\" +\n                \"          \\\"terms\\\": {\\n\" +\n                \"            \\\"clientHost\\\": [\\n\" +\n                \"              \\\"bigdata-arius-ser207.gz01\\\",\\n\" +\n                \"              \\\"arius-gateway-pre-sf-cf92c-0.docker.ys\\\",\\n\" +\n                \"              \\\"arius-gateway-console-sf-cf92c-0.docker.ys\\\",\\n\" +\n                \"              \\\"arius-gateway-console-sf-cf92c-1.docker.ys\\\",\\n\" +\n                \"              \\\"arius-gateway-console-sf-cf92c-2.docker.ys\\\"\\n\" +\n                \"            ]\\n\" +\n                \"          }\\n\" +\n                \"        }\\n\" +\n                \"      ]\\n\" +\n                \"    }\\n\" +\n                \"  }, \\n\" +\n                \"  \\\"aggs\\\": {\\n\" +\n                \"    \\\"2\\\": {\\n\" +\n                \"      \\\"terms\\\": {\\n\" +\n                \"        \\\"field\\\": \\\"indices\\\",\\n\" +\n                \"        \\\"size\\\": 10000\\n\" +\n                \"      }\\n\" +\n                \"    }\\n\" +\n                \"  }\\n\" +\n                \"}\", inAppid));\n\n        ESSearchResponse response = client.search(esSearchRequest)\n                .actionGet();\n\n        List<Object> buckets = (List<Object>) ((Map<String, Object>)response.getAggregations().get(\"2\")).get(\"buckets\");\n        Map<String, AtomicInteger> appidCount = new LinkedHashMap<>();\n\n        for (Object obj : buckets) {\n            try {\n                Map<String, Object> bucket = (Map<String, Object>) obj;\n                String indices = (String) bucket.get(\"key\");\n                int count = Integer.parseInt(bucket.get(\"doc_count\").toString());\n\n                Set<String> indicesSet = Strings.splitStringToSet(indices, ',');\n                Iterator<String> it = indicesSet.iterator();\n                while (it.hasNext()) {\n                    String str = it.next();\n                    if(str.startsWith(\".\")){\n                        it.remove();\n                    }\n                }\n\n                if (indicesSet.isEmpty()) {\n                    continue;\n                }\n\n                Iterator<String> iter = indicesSet.iterator();\n                String checkIndex = iter.next();\n                try {\n                    IndexTemplate indexTemplate = indexTemplateService.getIndexTemplateByTire(checkIndex);\n                    if (indexTemplate == null) {\n                        String alias = indexTemplateService.getIndexAlias(checkIndex);\n                        if (alias != null) {\n                            indexTemplate = indexTemplateService.getIndexTemplateByTire(alias);\n                        }\n                    }\n\n                    if (indexTemplate == null) {\n                        AtomicInteger notFoundCount = appidCount.get(\"index_not_found_\" + checkIndex);\n                        if (notFoundCount == null) {\n                            notFoundCount = new AtomicInteger(0);\n                            appidCount.put(\"index_not_found_\" + checkIndex, notFoundCount);\n                        }\n\n                        notFoundCount.addAndGet(count);\n                        logger.warn(\"appid={} index_not_found, index={}\", inAppid, indices);\n                        continue;\n                    }\n\n                    boolean same = true;\n                    AtomicInteger moreCount = appidCount.get(\"index_more_then_one\");\n                    if (moreCount == null) {\n                        moreCount = new AtomicInteger(0);\n                        appidCount.put(\"index_more_then_one\", moreCount);\n                    }\n\n                    while (iter.hasNext()) {\n                        String otherIndex = iter.next();\n                        boolean check = IndexTire.checkIndexMatchTemplate(otherIndex, indexTemplate);\n                        if (!check) {\n                            String alias = indexTemplateService.getIndexAlias(otherIndex);\n                            if (alias != null) {\n                                check = IndexTire.checkIndexMatchTemplate(alias, indexTemplate);\n                            }\n                        }\n\n                        if (!check) {\n                            logger.warn(\"appid={} index_more_then_one, index={}, indices={}\", inAppid, otherIndex, indices);\n                            same = false;\n                            break;\n                        }\n                    }\n\n                    if (!same) {\n                        moreCount.addAndGet(count);\n                        continue;\n                    }\n\n                    AtomicInteger indexCount = appidCount.get(indexTemplate.getExpression());\n                    if (indexCount == null) {\n                        appidCount.put(indexTemplate.getExpression(), new AtomicInteger(count));\n                    } else {\n                        indexCount.addAndGet(count);\n                    }\n                } catch (TooManyIndexException e) {\n                    AtomicInteger moreCount = appidCount.get(\"index_more_then_one\");\n                    if (moreCount == null) {\n                        moreCount = new AtomicInteger(0);\n                        appidCount.put(\"index_more_then_one\", moreCount);\n                    }\n\n                    moreCount.addAndGet(count);\n\n                    logger.warn(\"appid={} index_more_then_one, indices={}\", inAppid, indices);\n                }\n            } catch (Exception e) {\n                logger.warn(\"appid={} exception obj={}\", inAppid, obj, e);\n            }\n        }\n\n        return appidCount;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/gwadmin/DataCenterInfoController.java",
    "content": "package com.didi.arius.gateway.rest.controller.gwadmin;\n\nimport com.alibaba.fastjson.JSONArray;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.rest.controller.AdminController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * @author fitz\n * @date 2021/5/25 2:40 下午\n */\n@Controller\npublic class DataCenterInfoController extends AdminController {\n    public static final String NAME = \"dataCenterInfo\";\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwadmin/datacenterinfo\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        Set<Map.Entry<String, ESCluster>> entries = esRestClientService.getESClusterMap().entrySet();\n        JSONArray jr = new JSONArray(entries.size());\n        for (Map.Entry<String, ESCluster> entry : entries) {\n            JSONObject json = new JSONObject();\n            ESCluster esCluster = entry.getValue();\n            json.put(\"cluster\", esCluster.getCluster());\n            json.put(\"readAddress\", esCluster.getHttpAddress());\n            jr.add(json);\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, jr.toJSONString()));\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/gwadmin/IndexTemplateController.java",
    "content": "package com.didi.arius.gateway.rest.controller.gwadmin;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.rest.controller.AdminController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\n@Controller\npublic class IndexTemplateController extends AdminController {\n\n    private static final String NAME = \"indextemplate\";\n\n    @Override\n    public void register() {\n        controller.registerHandler( RestRequest.Method.GET, \"/_gwadmin/indextemplate/{template}\", this);\n    }\n\n    @Override\n    public String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        String template = request.param(\"template\");\n\n        IndexTemplate indexTemplate = indexTemplateService.getIndexTemplate(template);\n        if (indexTemplate == null) {\n            sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK));\n            return;\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse( RestStatus.OK, JSON.toJSONString(indexTemplate)));\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/gwadmin/IndextemplateInfoController.java",
    "content": "package com.didi.arius.gateway.rest.controller.gwadmin;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.rest.controller.AdminController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.Map;\n\n/**\n * @author fitz\n * @date 2021/5/25 3:04 下午\n */\n@Controller\npublic class IndextemplateInfoController extends AdminController {\n\n    public static final String NAME = \"indextemplateInfo\";\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwadmin/indextemplateInfo\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        Map<String, IndexTemplate> indexTemplateMap = indexTemplateService.getIndexTemplateMap();\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, JSON.toJSONString(indexTemplateMap)));\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/gwadmin/SyncMetadataController.java",
    "content": "package com.didi.arius.gateway.rest.controller.gwadmin;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.service.arius.DslTemplateService;\nimport com.didi.arius.gateway.core.service.arius.GateWayHeartBeatService;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\n/**\n * @author fitz\n * @date 2021/5/25 3:50 下午\n */\n@Controller\npublic class SyncMetadataController extends StatController {\n    public static final String NAME = \"syncMetadata\";\n\n    @Autowired\n    private GateWayHeartBeatService gateWayHeartBeatService;\n\n    @Autowired\n    private DslTemplateService dslTemplateService;\n\n    public SyncMetadataController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwadmin/sync/metadata\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        appService.resetAppInfo();\n        dslTemplateService.resetDslInfo();\n        dynamicConfigService.resetDynamicConfigInfo();\n        esClusterService.resetESClusaterInfo();\n        gateWayHeartBeatService.resetHeartBeatInfo();\n        indexTemplateService.resetIndexTemplateInfo();\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK));\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/gwadmin/WriteClientInfoController.java",
    "content": "package com.didi.arius.gateway.rest.controller.gwadmin;\n\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.rest.controller.AdminController;\nimport org.elasticsearch.common.xcontent.XContentBuilder;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.Map;\n\n/**\n * @author didi\n * @date 2021-09-23 8:55 下午\n */\n@Controller\npublic class WriteClientInfoController extends AdminController {\n\n    public static final String NAME = \"writeClientInfo\";\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    protected static final String COMM = \",\";\n\n    @Override\n    public void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwadmin/writeAction\", this);\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        RestStatus status = RestStatus.OK;\n\n        XContentBuilder builder = channel.newBuilder();\n\n        builder.startArray();\n        for (Map.Entry<String, ESCluster> entry : esRestClientService.getESClusterMap().entrySet()) {\n            builder.startObject();\n            builder.field(\"cluster_name\", entry.getValue().getCluster());\n            builder.field(\"write_action\", String.join(COMM, entry.getValue().getWriteAction()));\n            builder.field(\"run_mode\", entry.getValue().getRunMode());\n            builder.endObject();\n        }\n\n        builder.endArray();\n        sendDirectResponse(queryContext, new BytesRestResponse(status, builder));\n    }\n}\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/stat/ActionRequestStatsController.java",
    "content": "package com.didi.arius.gateway.rest.controller.stat;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metrics.ActionMetric;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n * @author fitz\n * @date 2021/5/25 4:05 下午\n */\n@Controller\npublic class ActionRequestStatsController extends StatController {\n    public static final String NAME = \"actionRequestStats\";\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/action/request\", this);\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/action/request/{action}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return null;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        String action = request.param(\"action\");\n        String res = \"\";\n\n        if (action != null) {\n            ActionMetric actionMetric = requestStatsService.getActionMetricMap().get(action);\n            if (actionMetric != null) {\n                res = JSON.toJSONString(actionMetric);\n            }\n        } else {\n            ConcurrentMap<String, ActionMetric> actionMetricMap = requestStatsService.getActionMetricMap();\n            res = JSON.toJSONString(actionMetricMap);\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, res));\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/stat/AliasInfoController.java",
    "content": "package com.didi.arius.gateway.rest.controller.stat;\n\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.TemplateInfo;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.Map;\n\n/**\n * @author fitz\n * @date 2021/5/25 4:27 下午\n */\n@Controller\npublic class AliasInfoController extends StatController {\n    public static final String NAME = \"aliasInfo\";\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/alias/info\", this);\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/alias/info/{cluster}\", this);\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        String cluster = request.param(\"cluster\");\n        String res = \"\";\n\n        if (cluster == null) {\n            res = JSON.toJSONString(indexTemplateService.getTemplateAliasMap());\n        } else {\n            Map<String, TemplateInfo> templateInfoMap = indexTemplateService.getTemplateAliasMap().get(cluster);\n            if (templateInfoMap != null) {\n                res = JSON.toJSONString(templateInfoMap);\n            }\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, res));\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/stat/AppRequestStatsController.java",
    "content": "package com.didi.arius.gateway.rest.controller.stat;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metrics.AppMetric;\nimport com.didi.arius.gateway.common.metrics.SearchMetric;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\n/**\n * @author fitz\n * @date 2021/5/25 4:33 下午\n */\n@Controller\npublic class AppRequestStatsController extends StatController {\n    public static final String NAME = \"appRequestStats\";\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/app/request\", this);\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/app/request/{appid}\", this);\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/app/request/{appid}/{searchid}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        int appid = request.paramAsInt(\"appid\", QueryConsts.TOTAL_APPID_ID);\n        String searchId = request.param(\"searchid\");\n        String res = \"\";\n\n        if (appid > 0) {\n            AppMetric appMetric = requestStatsService.getAppMetricMap().get(appid);\n            if (appMetric != null) {\n                if (searchId != null) {\n                    SearchMetric searchMetric = appMetric.getSearchsMetricMap().get(searchId);\n                    if (searchMetric != null) {\n                        res = JSON.toJSONString(searchMetric);\n                    }\n                } else {\n                    res = JSON.toJSONString(appMetric);\n                }\n            }\n        } else {\n            res = JSON.toJSONString(requestStatsService.getAppMetricMap());\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, res));\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/stat/FlowRateController.java",
    "content": "package com.didi.arius.gateway.rest.controller.stat;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.flowcontrol.FlowController;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.Map;\n\n/**\n * @author fitz\n * @date 2021/5/25 4:53 下午\n */\n@Controller\npublic class FlowRateController extends StatController {\n    public static final String NAME = \"flowrate\";\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/flowrate\", this);\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/flowrate/{appid}\", this);\n\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        int appid = request.paramAsInt(\"appid\", QueryConsts.TOTAL_APPID_ID);\n        Map<Integer, FlowController> flowControllerMap = rateLimitService.getFlowControllerMap();\n        String res = \"\";\n        if (appid > 0) {\n            FlowController flowController = flowControllerMap.get(appid);\n            if (flowController != null) {\n                res = JSON.toJSONString(flowController);\n            }\n        } else {\n            res = JSON.toJSONString(flowControllerMap);\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, res));\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/stat/RateLimitDetailController.java",
    "content": "package com.didi.arius.gateway.rest.controller.stat;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.DSLTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.RateLimitDetail;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.service.arius.DslTemplateService;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TreeMap;\n\n/**\n * @author fitz\n * @date 2021/5/25 5:05 下午\n */\n@Controller\npublic class RateLimitDetailController extends StatController {\n\n    public static final String NAME = \"rateLimitDetail\";\n    @Autowired\n    private DslTemplateService dslTemplateService;\n\n    public RateLimitDetailController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/rateLimitDetail\", this);\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/rateLimitDetail/{appid}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        int rAppid = request.paramAsInt(\"appid\", QueryConsts.TOTAL_APPID_ID);\n        Map<Integer, List<RateLimitDetail>> appidDetail = new TreeMap<>();\n\n        List<String> dslKeys = dslTemplateService.getDslTemplateKeys();\n        for (String dslKey : dslKeys) {\n            try {\n                String[] keyArr = dslKey.split(\"_\");\n                int appid = Integer.parseInt(keyArr[0]);\n                if (rAppid != QueryConsts.TOTAL_APPID_ID && rAppid != appid) {\n                    continue;\n                }\n\n                DSLTemplate dslTemplate = dslTemplateService.getDSLTemplate(dslKey);\n\n                RateLimitDetail rateLimitDetail = new RateLimitDetail();\n                rateLimitDetail.setAppid(appid);\n                rateLimitDetail.setDslMd5(dslKey);\n\n                if (dslTemplate != null) {\n                    rateLimitDetail.setQueryLimit(dslTemplate.getQueryLimit());\n                    rateLimitDetail.setQueryForbidden(dslTemplate.isQueryForbidden());\n                    rateLimitDetail.setEsCostAvg(dslTemplate.getEsCostAvg());\n                    rateLimitDetail.setTotalHitsAvg(dslTemplate.getTotalHitsAvg());\n                    rateLimitDetail.setTotalShardsAvg(dslTemplate.getTotalShardsAvg());\n                }\n\n                if (appidDetail.containsKey(appid)) {\n                    List<RateLimitDetail> rateLimitDetails = appidDetail.get(appid);\n                    rateLimitDetails.add(rateLimitDetail);\n                } else {\n                    List<RateLimitDetail> rateLimitDetails = new ArrayList<>();\n                    rateLimitDetails.add(rateLimitDetail);\n                    appidDetail.put(appid, rateLimitDetails);\n                }\n            } catch (Exception e) {\n                logger.error(\"unexpect_exception||dslKey={}||e={}\", dslKey, Convert.logExceptionStack(e));\n            }\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, JSON.toJSONString(appidDetail)));\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/stat/RateLimitInfoController.java",
    "content": "package com.didi.arius.gateway.rest.controller.stat;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.DSLTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.RateLimitStat;\nimport com.didi.arius.gateway.common.utils.Convert;\nimport com.didi.arius.gateway.core.service.arius.DslTemplateService;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TreeMap;\n\n/**\n * @author fitz\n * @date 2021/5/25 5:16 下午\n */\n@Controller\npublic class RateLimitInfoController extends StatController {\n    public static final String NAME = \"rateLimitInfo\";\n    @Autowired\n    private DslTemplateService dslTemplateService;\n\n    public RateLimitInfoController() {\n        // pass\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/rateLimitInfo\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n\n        Map<Integer, RateLimitStat> appidStats = new TreeMap<>();\n\n        List<String> dslKeys = dslTemplateService.getDslTemplateKeys();\n        for (String dslKey : dslKeys) {\n            try {\n                int appid = Integer.parseInt(dslKey.split(\"_\")[0]);\n                if (appidStats.containsKey(appid)) {\n                    RateLimitStat rateLimitStat = appidStats.get(appid);\n                    rateLimitStat.setDslCount(rateLimitStat.getDslCount() + 1);\n                } else {\n                    RateLimitStat rateLimitStat = new RateLimitStat();\n                    rateLimitStat.setDslCount(1);\n                    appidStats.put(appid, rateLimitStat);\n                }\n\n                DSLTemplate dslTemplate = dslTemplateService.getDSLTemplate(dslKey);\n                if (dslTemplate != null && dslTemplate.isQueryForbidden()) {\n                    if (appidStats.containsKey(appid)) {\n                        RateLimitStat rateLimitStat = appidStats.get(appid);\n                        rateLimitStat.setDslForbiddenCount(rateLimitStat.getDslForbiddenCount() + 1);\n                    } else {\n                        RateLimitStat rateLimitStat = new RateLimitStat();\n                        rateLimitStat.setDslForbiddenCount(1);\n                        appidStats.put(appid, rateLimitStat);\n                    }\n                }\n            } catch (Exception e) {\n                logger.error(\"unexpect_exception||dslKey={}||e={}\", dslKey, Convert.logExceptionStack(e));\n            }\n        }\n\n        List<String> newDslKeys = dslTemplateService.getNewDslTemplateKeys();\n        for (String dslKey : newDslKeys) {\n            try {\n                int appid = Integer.parseInt(dslKey.split(\"_\")[0]);\n                if (appidStats.containsKey(appid)) {\n                    RateLimitStat rateLimitStat = appidStats.get(appid);\n                    rateLimitStat.setNewDslCount(rateLimitStat.getNewDslCount() + 1);\n                } else {\n                    RateLimitStat rateLimitStat = new RateLimitStat();\n                    rateLimitStat.setNewDslCount(1);\n                    appidStats.put(appid, rateLimitStat);\n                }\n\n                DSLTemplate dslTemplate = dslTemplateService.getNewDSLTemplate(dslKey);\n                if (dslTemplate != null && dslTemplate.isQueryForbidden()) {\n                    if (appidStats.containsKey(appid)) {\n                        RateLimitStat rateLimitStat = appidStats.get(appid);\n                        rateLimitStat.setNewDslForbiddenCount(rateLimitStat.getNewDslForbiddenCount() + 1);\n                    } else {\n                        RateLimitStat rateLimitStat = new RateLimitStat();\n                        rateLimitStat.setNewDslForbiddenCount(1);\n                        appidStats.put(appid, rateLimitStat);\n                    }\n                }\n            } catch (Exception e) {\n                logger.error(\"unexpect_exception||dslKey={}||e={}\", dslKey, Convert.logExceptionStack(e));\n            }\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, JSON.toJSONString(appidStats)));\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/stat/RequestingStatsController.java",
    "content": "package com.didi.arius.gateway.rest.controller.stat;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.List;\n\n/**\n * @author fitz\n * @date 2021/5/25 5:23 下午\n */\n@Controller\npublic class RequestingStatsController extends StatController {\n    public static final String NAME = \"requestingStats\";\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/requesting\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n\n        List<String> queryKeys = requestStatsService.getQueryKeys();\n        List<QueryContext> list = Lists.newArrayListWithCapacity(queryKeys.size());\n        for (String key : queryKeys) {\n            QueryContext contextItem = requestStatsService.getQueryContext(key);\n            if (contextItem != null) {\n                list.add(contextItem);\n            }\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, JSON.toJSONString(list)));\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/stat/RequestingTcpStatsController.java",
    "content": "package com.didi.arius.gateway.rest.controller.stat;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.google.common.collect.Lists;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.List;\n\n/**\n * @author fitz\n * @date 2021/5/25 5:32 下午\n */\n@Controller\npublic class RequestingTcpStatsController extends StatController {\n    public static final String NAME = \"requestingTcpStats\";\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/tcp/requesting\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n\n        List<String> queryKeys = requestStatsService.getActionKeys();\n        List<ActionContext> list = Lists.newArrayListWithCapacity(queryKeys.size());\n        for (String key : queryKeys) {\n            ActionContext actionContext = requestStatsService.getActionContext(key);\n            if (actionContext != null) {\n                list.add(actionContext);\n            }\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, JSON.toJSONString(list)));\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/stat/RestHotThreadsController.java",
    "content": "package com.didi.arius.gateway.rest.controller.stat;\n\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.action.admin.cluster.node.hotthreads.NodesHotThreadsRequest;\nimport org.elasticsearch.common.unit.TimeValue;\nimport org.elasticsearch.monitor.jvm.HotThreads;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\n/**\n * @author fitz\n * @date 2021/5/25 5:36 下午\n */\n@Controller\npublic class RestHotThreadsController extends StatController {\n    public static final String NAME = \"hotThreads\";\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/hotthreads\", this);\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/hot_threads\", this);\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        NodesHotThreadsRequest nodesHotThreadsRequest = new NodesHotThreadsRequest();\n        nodesHotThreadsRequest.threads(request.paramAsInt(\"threads\", nodesHotThreadsRequest.threads()));\n        nodesHotThreadsRequest.ignoreIdleThreads(request.paramAsBoolean(\"ignore_idle_threads\", nodesHotThreadsRequest.ignoreIdleThreads()));\n        nodesHotThreadsRequest.type(request.param(\"type\", nodesHotThreadsRequest.type()));\n        nodesHotThreadsRequest.interval(TimeValue.parseTimeValue(request.param(\"interval\"), nodesHotThreadsRequest.interval(), \"interval\"));\n        nodesHotThreadsRequest.snapshots(request.paramAsInt(\"snapshots\", nodesHotThreadsRequest.snapshots()));\n        nodesHotThreadsRequest.timeout(request.param(\"timeout\"));\n\n        HotThreads hotThreads = new HotThreads()\n                .busiestThreads(nodesHotThreadsRequest.threads())\n                .type(nodesHotThreadsRequest.type())\n                .interval(nodesHotThreadsRequest.interval())\n                .threadElementsSnapshotCount(nodesHotThreadsRequest.snapshots())\n                .ignoreIdleThreads(nodesHotThreadsRequest.ignoreIdleThreads());\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, hotThreads.detect()));\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/controller/stat/TemplateInfoController.java",
    "content": "package com.didi.arius.gateway.rest.controller.stat;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.TemplateInfo;\nimport com.didi.arius.gateway.rest.controller.StatController;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport org.elasticsearch.rest.BytesRestResponse;\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestStatus;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.Map;\n\n/**\n * @author fitz\n * @date 2021/5/25 5:40 下午\n */\n@Controller\npublic class TemplateInfoController extends StatController {\n    public static final String NAME = \"templateInfo\";\n    @Override\n    protected void register() {\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/template/info\", this);\n        controller.registerHandler(RestRequest.Method.GET, \"/_gwstat/template/info/{cluster}\", this);\n    }\n\n    @Override\n    protected String name() {\n        return NAME;\n    }\n\n    @Override\n    protected void handleAriusRequest(QueryContext queryContext, RestRequest request, RestChannel channel, ESClient client) throws Exception {\n        String cluster = request.param(\"cluster\");\n        String res = \"\";\n\n        if (cluster == null) {\n            res = JSON.toJSONString(indexTemplateService.getTemplateExpressionMap());\n        } else {\n            Map<String, TemplateInfo> templateInfoMap = indexTemplateService.getTemplateExpressionMap().get(cluster);\n            if (templateInfoMap != null) {\n                res = JSON.toJSONString(templateInfoMap);\n            }\n        }\n\n        sendDirectResponse(queryContext, new BytesRestResponse(RestStatus.OK, res));\n\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/http/HttpDeamondThreadFactory.java",
    "content": "package com.didi.arius.gateway.rest.http;\n\nimport org.jboss.netty.util.ThreadRenamingRunnable;\n\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class HttpDeamondThreadFactory implements ThreadFactory {\n    static final AtomicInteger poolNumber = new AtomicInteger(1);\n    final ThreadGroup group;\n    final AtomicInteger threadNumber = new AtomicInteger(1);\n    final String namePrefix;\n\n    static {\n        ThreadRenamingRunnable\n                .setThreadNameDeterminer((currentThreadName, proposedThreadName) -> currentThreadName);\n    }\n\n    public HttpDeamondThreadFactory(String prefix) {\n        SecurityManager s = System.getSecurityManager();\n        group = (s != null) ? s.getThreadGroup() : Thread.currentThread()\n                .getThreadGroup();\n        namePrefix = prefix + \"-pool-\" + poolNumber.getAndIncrement() + \"-\";\n    }\n\n    public Thread newThread(Runnable r) {\n        Thread t = new Thread(group, r, namePrefix\n                + threadNumber.getAndIncrement(), 0);\n        if (!t.isDaemon())\n            t.setDaemon(true);\n        if (t.getPriority() != Thread.NORM_PRIORITY)\n            t.setPriority(Thread.NORM_PRIORITY);\n        return t;\n    }\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/http/HttpRequestHandler.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.rest.http;\n\nimport org.elasticsearch.common.logging.ESLogger;\nimport org.elasticsearch.common.logging.Loggers;\nimport org.elasticsearch.http.netty.NettyHttpRequest;\nimport org.elasticsearch.http.netty.pipelining.OrderedUpstreamMessageEvent;\nimport org.jboss.netty.channel.*;\nimport org.jboss.netty.handler.codec.http.HttpRequest;\n\n/**\n *\n */\n@ChannelHandler.Sharable\npublic class HttpRequestHandler extends SimpleChannelUpstreamHandler {\n\n    private final NettyHttpServerTransport serverTransport;\n    private final boolean httpPipeliningEnabled;\n    private final boolean detailedErrorsEnabled;\n\n    protected final ESLogger logger = Loggers.getLogger(HttpRequestHandler.class);\n\n    public HttpRequestHandler(NettyHttpServerTransport serverTransport, boolean detailedErrorsEnabled) {\n        this.serverTransport = serverTransport;\n        this.httpPipeliningEnabled = serverTransport.pipelining;\n        this.detailedErrorsEnabled = detailedErrorsEnabled;\n    }\n\n    @Override\n    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {\n    \tlong start = System.currentTimeMillis();\n\n        HttpRequest request;\n        OrderedUpstreamMessageEvent oue = null;\n        if (this.httpPipeliningEnabled && e instanceof OrderedUpstreamMessageEvent) {\n            oue = (OrderedUpstreamMessageEvent) e;\n            request = (HttpRequest) oue.getMessage();\n        } else {\n            request = (HttpRequest) e.getMessage();\n        }\n\n        // the netty HTTP handling always copy over the buffer to its own buffer, either in NioWorker internally\n        // when reading, or using a cumalation buffer\n        NettyHttpRequest httpRequest = new NettyHttpRequest(request, e.getChannel());\n        if (oue != null) {\n            serverTransport.dispatchRequest(httpRequest, new NettyHttpChannel(serverTransport, httpRequest, oue, detailedErrorsEnabled));\n        } else {\n            serverTransport.dispatchRequest(httpRequest, new NettyHttpChannel(serverTransport, httpRequest, detailedErrorsEnabled));\n        }\n        super.messageReceived(ctx, e);\n        \n        long cost = System.currentTimeMillis() - start;\n        if (cost > 1000) {\n        \tlogger.warn(\"http messageReceived cost too long, cost={}, uri={}\", cost, httpRequest.uri());\n        }\n    }\n\n    @Override\n    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {\n        serverTransport.exceptionCaught(ctx, e);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/http/IRestHandler.java",
    "content": "package com.didi.arius.gateway.rest.http;\n\nimport org.elasticsearch.rest.RestChannel;\nimport org.elasticsearch.rest.RestRequest;\n\n/**\n* @author weizijun\n* @date：2016年8月16日\n* \n*/\npublic interface IRestHandler {\n\tpublic void dispatchRequest(RestRequest request, RestChannel channel);\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/http/MethodHandlers.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.rest.http;\n\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.rest.RestRequest;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Encapsulate multiple handlers for the same path, allowing different handlers for different HTTP verbs.\n */\nfinal class MethodHandlers {\n\n    private final String path;\n    private final Map<RestRequest.Method, IRestHandler> restHandlerMap;\n\n    MethodHandlers(String path, IRestHandler handler, RestRequest.Method... methods) {\n        this.path = path;\n        this.restHandlerMap = new HashMap<>(methods.length);\n        for (RestRequest.Method method : methods) {\n            restHandlerMap.put(method, handler);\n        }\n    }\n\n    /**\n     * Add a handler for an additional array of methods. Note that {@code MethodHandlers}\n     * does not allow replacing the handler for an already existing method.\n     */\n    MethodHandlers addMethods(IRestHandler handler, RestRequest.Method... methods) {\n        for (RestRequest.Method method : methods) {\n            IRestHandler existing = restHandlerMap.putIfAbsent(method, handler);\n            if (existing != null) {\n                throw new IllegalArgumentException(\"Cannot replace existing handler for [\" + path + \"] for method: \" + method);\n            }\n        }\n        return this;\n    }\n\n    /**\n     * Returns the handler for the given method or {@code null} if none exists.\n     */\n    @Nullable\n    IRestHandler getHandler(RestRequest.Method method) {\n        return restHandlerMap.get(method);\n    }\n\n    /**\n     * Return a set of all valid HTTP methods for the particular path\n     */\n    Set<RestRequest.Method> getValidMethods() {\n        return restHandlerMap.keySet();\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/http/NettyHttpChannel.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.rest.http;\n\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.io.stream.BytesStreamOutput;\nimport org.elasticsearch.common.io.stream.ReleasableBytesStreamOutput;\nimport org.elasticsearch.common.lease.Releasable;\nimport org.elasticsearch.common.netty.ReleaseChannelFutureListener;\nimport org.elasticsearch.http.HttpChannel;\nimport org.elasticsearch.http.netty.NettyHttpRequest;\nimport org.elasticsearch.http.netty.cors.CorsHandler;\nimport org.elasticsearch.http.netty.pipelining.OrderedDownstreamChannelEvent;\nimport org.elasticsearch.http.netty.pipelining.OrderedUpstreamMessageEvent;\nimport org.elasticsearch.rest.RestResponse;\nimport org.elasticsearch.rest.RestStatus;\nimport org.jboss.netty.buffer.ChannelBuffer;\nimport org.jboss.netty.channel.Channel;\nimport org.jboss.netty.channel.ChannelFuture;\nimport org.jboss.netty.channel.ChannelFutureListener;\nimport org.jboss.netty.handler.codec.http.*;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONNECTION;\nimport static org.jboss.netty.handler.codec.http.HttpHeaders.Values.CLOSE;\nimport static org.jboss.netty.handler.codec.http.HttpHeaders.Values.KEEP_ALIVE;\n\n/**\n *\n */\npublic class NettyHttpChannel extends HttpChannel {\n\n    private final NettyHttpServerTransport transport;\n    private final Channel channel;\n    private final HttpRequest nettyRequest;\n    private OrderedUpstreamMessageEvent orderedUpstreamMessageEvent = null;\n\n    public NettyHttpChannel(NettyHttpServerTransport transport, NettyHttpRequest request,\n                            boolean detailedErrorsEnabled) {\n        super(request, detailedErrorsEnabled);\n        this.transport = transport;\n        this.channel = request.getChannel();\n        this.nettyRequest = request.request();\n    }\n\n    public NettyHttpChannel(NettyHttpServerTransport transport, NettyHttpRequest request,\n                            OrderedUpstreamMessageEvent orderedUpstreamMessageEvent, boolean detailedErrorsEnabled) {\n        this(transport, request, detailedErrorsEnabled);\n        this.orderedUpstreamMessageEvent = orderedUpstreamMessageEvent;\n    }\n\n    @Override\n    public BytesStreamOutput newBytesOutput() {\n        return new ReleasableBytesStreamOutput(transport.bigArrays);\n    }\n\n\n    @Override\n    public void sendResponse(RestResponse response) {\n        // otherwise, create a new one\n        HttpResponse resp = newResponse();\n        resp.setStatus(getStatus(response.status()));\n\n        CorsHandler.setCorsResponseHeaders(nettyRequest, resp, transport.getCorsConfig());\n\n        String opaque = nettyRequest.headers().get(\"X-Opaque-Id\");\n        if (opaque != null) {\n            resp.headers().add(\"X-Opaque-Id\", opaque);\n        }\n\n        // Add all custom headers\n        Map<String, List<String>> customHeaders = response.getHeaders();\n        if (customHeaders != null) {\n            for (Map.Entry<String, List<String>> headerEntry : customHeaders.entrySet()) {\n                for (String headerValue : headerEntry.getValue()) {\n                    resp.headers().add(headerEntry.getKey(), headerValue);\n                }\n            }\n        }\n\n        BytesReference content = response.content();\n        ChannelBuffer buffer;\n        boolean addedReleaseListener = false;\n        try {\n            buffer = content.toChannelBuffer();\n            resp.setContent(buffer);\n\n            // If our response doesn't specify a content-type header, set one\n            if (!resp.headers().contains(HttpHeaders.Names.CONTENT_TYPE)) {\n                resp.headers().add(HttpHeaders.Names.CONTENT_TYPE, response.contentType());\n            }\n\n            // If our response has no content-length, calculate and set one\n            if (!resp.headers().contains(HttpHeaders.Names.CONTENT_LENGTH)) {\n                resp.headers().add(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buffer.readableBytes()));\n            }\n\n            if (transport.resetCookies) {\n                String cookieString = nettyRequest.headers().get(HttpHeaders.Names.COOKIE);\n                if (cookieString != null) {\n                    CookieDecoder cookieDecoder = new CookieDecoder();\n                    Set<Cookie> cookies = cookieDecoder.decode(cookieString);\n                    if (!cookies.isEmpty()) {\n                        // Reset the cookies if necessary.\n                        CookieEncoder cookieEncoder = new CookieEncoder(true);\n                        for (Cookie cookie : cookies) {\n                            cookieEncoder.addCookie(cookie);\n                        }\n                        resp.headers().add(HttpHeaders.Names.SET_COOKIE, cookieEncoder.encode());\n                    }\n                }\n            }\n\n            ChannelFuture future;\n\n            if (orderedUpstreamMessageEvent != null) {\n                OrderedDownstreamChannelEvent downstreamChannelEvent = new OrderedDownstreamChannelEvent(orderedUpstreamMessageEvent, 0, true, resp);\n                future = downstreamChannelEvent.getFuture();\n                channel.getPipeline().sendDownstream(downstreamChannelEvent);\n            } else {\n                future = channel.write(resp);\n            }\n\n            if (content instanceof Releasable) {\n                future.addListener(new ReleaseChannelFutureListener((Releasable) content));\n                addedReleaseListener = true;\n            }\n\n            if (isCloseConnection()) {\n                future.addListener(ChannelFutureListener.CLOSE);\n            }\n\n        } finally {\n            if (!addedReleaseListener && content instanceof Releasable) {\n                ((Releasable) content).close();\n            }\n        }\n    }\n\n    // Determine if the request protocol version is HTTP 1.0\n    private boolean isHttp10() {\n        return nettyRequest.getProtocolVersion().equals(HttpVersion.HTTP_1_0);\n    }\n\n    // Determine if the request connection should be closed on completion.\n    private boolean isCloseConnection() {\n        final boolean http10 = isHttp10();\n        return CLOSE.equalsIgnoreCase(nettyRequest.headers().get(CONNECTION)) ||\n                   (http10 && !KEEP_ALIVE.equalsIgnoreCase(nettyRequest.headers().get(CONNECTION)));\n    }\n\n    // Create a new {@link HttpResponse} to transmit the response for the netty request.\n    private HttpResponse newResponse() {\n        final boolean http10 = isHttp10();\n        final boolean close = isCloseConnection();\n        // Build the response object.\n        HttpResponseStatus status = HttpResponseStatus.OK; // default to initialize\n        HttpResponse resp;\n        if (http10) {\n            resp = new DefaultHttpResponse(HttpVersion.HTTP_1_0, status);\n            if (!close) {\n                resp.headers().add(CONNECTION, \"Keep-Alive\");\n            }\n        } else {\n            resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status);\n        }\n        return resp;\n    }\n\n    private static final HttpResponseStatus TOO_MANY_REQUESTS = new HttpResponseStatus(429, \"Too Many Requests\");\n\n    private HttpResponseStatus getStatus(RestStatus status) {\n        if (status == null) {\n            return HttpResponseStatus.OK;\n        }\n        switch (status) {\n            case CONTINUE:\n                return HttpResponseStatus.CONTINUE;\n            case SWITCHING_PROTOCOLS:\n                return HttpResponseStatus.SWITCHING_PROTOCOLS;\n            case OK:\n                return HttpResponseStatus.OK;\n            case CREATED:\n                return HttpResponseStatus.CREATED;\n            case ACCEPTED:\n                return HttpResponseStatus.ACCEPTED;\n            case NON_AUTHORITATIVE_INFORMATION:\n                return HttpResponseStatus.NON_AUTHORITATIVE_INFORMATION;\n            case NO_CONTENT:\n                return HttpResponseStatus.NO_CONTENT;\n            case RESET_CONTENT:\n                return HttpResponseStatus.RESET_CONTENT;\n            case PARTIAL_CONTENT:\n                return HttpResponseStatus.PARTIAL_CONTENT;\n            case MULTI_STATUS:\n                // no status for this??\n                return HttpResponseStatus.INTERNAL_SERVER_ERROR;\n            case MULTIPLE_CHOICES:\n                return HttpResponseStatus.MULTIPLE_CHOICES;\n            case MOVED_PERMANENTLY:\n                return HttpResponseStatus.MOVED_PERMANENTLY;\n            case FOUND:\n                return HttpResponseStatus.FOUND;\n            case SEE_OTHER:\n                return HttpResponseStatus.SEE_OTHER;\n            case NOT_MODIFIED:\n                return HttpResponseStatus.NOT_MODIFIED;\n            case USE_PROXY:\n                return HttpResponseStatus.USE_PROXY;\n            case TEMPORARY_REDIRECT:\n                return HttpResponseStatus.TEMPORARY_REDIRECT;\n            case BAD_REQUEST:\n                return HttpResponseStatus.BAD_REQUEST;\n            case UNAUTHORIZED:\n                return HttpResponseStatus.UNAUTHORIZED;\n            case PAYMENT_REQUIRED:\n                return HttpResponseStatus.PAYMENT_REQUIRED;\n            case FORBIDDEN:\n                return HttpResponseStatus.FORBIDDEN;\n            case NOT_FOUND:\n                return HttpResponseStatus.NOT_FOUND;\n            case METHOD_NOT_ALLOWED:\n                return HttpResponseStatus.METHOD_NOT_ALLOWED;\n            case NOT_ACCEPTABLE:\n                return HttpResponseStatus.NOT_ACCEPTABLE;\n            case PROXY_AUTHENTICATION:\n                return HttpResponseStatus.PROXY_AUTHENTICATION_REQUIRED;\n            case REQUEST_TIMEOUT:\n                return HttpResponseStatus.REQUEST_TIMEOUT;\n            case CONFLICT:\n                return HttpResponseStatus.CONFLICT;\n            case GONE:\n                return HttpResponseStatus.GONE;\n            case LENGTH_REQUIRED:\n                return HttpResponseStatus.LENGTH_REQUIRED;\n            case PRECONDITION_FAILED:\n                return HttpResponseStatus.PRECONDITION_FAILED;\n            case REQUEST_ENTITY_TOO_LARGE:\n                return HttpResponseStatus.REQUEST_ENTITY_TOO_LARGE;\n            case REQUEST_URI_TOO_LONG:\n                return HttpResponseStatus.REQUEST_URI_TOO_LONG;\n            case UNSUPPORTED_MEDIA_TYPE:\n                return HttpResponseStatus.UNSUPPORTED_MEDIA_TYPE;\n            case REQUESTED_RANGE_NOT_SATISFIED:\n                return HttpResponseStatus.REQUESTED_RANGE_NOT_SATISFIABLE;\n            case EXPECTATION_FAILED:\n                return HttpResponseStatus.EXPECTATION_FAILED;\n            case UNPROCESSABLE_ENTITY:\n                return HttpResponseStatus.BAD_REQUEST;\n            case LOCKED:\n                return HttpResponseStatus.BAD_REQUEST;\n            case FAILED_DEPENDENCY:\n                return HttpResponseStatus.BAD_REQUEST;\n            case TOO_MANY_REQUESTS:\n                return TOO_MANY_REQUESTS;\n            case INTERNAL_SERVER_ERROR:\n                return HttpResponseStatus.INTERNAL_SERVER_ERROR;\n            case NOT_IMPLEMENTED:\n                return HttpResponseStatus.NOT_IMPLEMENTED;\n            case BAD_GATEWAY:\n                return HttpResponseStatus.BAD_GATEWAY;\n            case SERVICE_UNAVAILABLE:\n                return HttpResponseStatus.SERVICE_UNAVAILABLE;\n            case GATEWAY_TIMEOUT:\n                return HttpResponseStatus.GATEWAY_TIMEOUT;\n            case HTTP_VERSION_NOT_SUPPORTED:\n                return HttpResponseStatus.HTTP_VERSION_NOT_SUPPORTED;\n            default:\n                return HttpResponseStatus.INTERNAL_SERVER_ERROR;\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/http/NettyHttpController.java",
    "content": "package com.didi.arius.gateway.rest.http;\n\nimport com.didi.arius.gateway.rest.controller.es.RestCommonController;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.elasticsearch.http.HttpChannel;\nimport org.elasticsearch.http.HttpRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n@Component(\"nettyHttpController\")\npublic class NettyHttpController {\n\n    @Autowired\n    private RestController restController;\n\n    @Autowired\n    private RestCommonController restCommonController;\n\n    public NettyHttpController() {\n        // pass\n    }\n\n    public void dispatchRequest(HttpRequest request, HttpChannel channel) {\n        try {\n            LogFactory.setUniqueFlag();\n            handleRequest(request, channel);\n        } finally {\n            LogFactory.removeFlag();\n        }\n    }\n\n    private void handleRequest(HttpRequest request, HttpChannel channel) {\n        IRestHandler restHandler;\n        if (request.rawPath().startsWith(\"/_xpack\")) {\n            restHandler = restCommonController;\n        } else {\n            restHandler = restController.tryAllHandlers(request);\n        }\n\n        if (restHandler == null) {\n            restHandler = restCommonController;\n        }\n\n        if(restHandler != null){\n            restHandler.dispatchRequest(request, channel);\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/http/NettyHttpServerTransport.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.rest.http;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.elasticsearch.common.Booleans;\nimport org.elasticsearch.common.Strings;\nimport org.elasticsearch.common.netty.NettyUtils;\nimport org.elasticsearch.common.network.NetworkUtils;\nimport org.elasticsearch.common.settings.Settings;\nimport org.elasticsearch.common.transport.BoundTransportAddress;\nimport org.elasticsearch.common.transport.NetworkExceptionHelper;\nimport org.elasticsearch.common.unit.ByteSizeUnit;\nimport org.elasticsearch.common.unit.ByteSizeValue;\nimport org.elasticsearch.common.util.BigArrays;\nimport org.elasticsearch.common.util.concurrent.EsExecutors;\nimport org.elasticsearch.http.HttpChannel;\nimport org.elasticsearch.http.HttpInfo;\nimport org.elasticsearch.http.HttpRequest;\nimport org.elasticsearch.http.HttpStats;\nimport org.elasticsearch.http.netty.ESHttpContentDecompressor;\nimport org.elasticsearch.http.netty.ESHttpResponseEncoder;\nimport org.elasticsearch.http.netty.cors.CorsConfig;\nimport org.elasticsearch.http.netty.cors.CorsConfigBuilder;\nimport org.elasticsearch.http.netty.cors.CorsHandler;\nimport org.elasticsearch.http.netty.pipelining.HttpPipeliningHandler;\nimport org.elasticsearch.monitor.jvm.JvmInfo;\nimport org.elasticsearch.rest.support.RestUtils;\nimport org.jboss.netty.bootstrap.ServerBootstrap;\nimport org.jboss.netty.channel.*;\nimport org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;\nimport org.jboss.netty.channel.socket.oio.OioServerSocketChannelFactory;\nimport org.jboss.netty.handler.codec.http.HttpChunkAggregator;\nimport org.jboss.netty.handler.codec.http.HttpContentCompressor;\nimport org.jboss.netty.handler.codec.http.HttpMethod;\nimport org.jboss.netty.handler.codec.http.HttpRequestDecoder;\nimport org.jboss.netty.handler.timeout.ReadTimeoutException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\nimport java.net.InetSocketAddress;\nimport java.util.concurrent.Executors;\nimport java.util.regex.Pattern;\n\nimport static org.elasticsearch.common.network.NetworkService.TcpSettings.*;\nimport static org.elasticsearch.http.netty.cors.CorsHandler.ANY_ORIGIN;\n\n/**\n *\n */\n@Component(\"nettyHttpServerTransport\")\npublic class NettyHttpServerTransport {\n    private static final ILog logger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n\n    @Value(\"${gateway.httpTransport.port}\")\n    private int httpPort;\n\n    static {\n        NettyUtils.setup();\n    }\n\n    public static final String SETTING_CORS_ENABLED = \"http.cors.enabled\";\n    public static final String SETTING_CORS_ALLOW_ORIGIN = \"http.cors.allow-origin\";\n    public static final String SETTING_CORS_MAX_AGE = \"http.cors.max-age\";\n    public static final String SETTING_CORS_ALLOW_METHODS = \"http.cors.allow-methods\";\n    public static final String SETTING_CORS_ALLOW_HEADERS = \"http.cors.allow-headers\";\n    public static final String SETTING_CORS_ALLOW_CREDENTIALS = \"http.cors.allow-credentials\";\n    public static final String SETTING_PIPELINING = \"http.pipelining\";\n    public static final String SETTING_PIPELINING_MAX_EVENTS = \"http.pipelining.max_events\";\n    public static final String SETTING_HTTP_COMPRESSION = \"http.compression\";\n    public static final String SETTING_HTTP_COMPRESSION_LEVEL = \"http.compression_level\";\n    public static final String SETTING_HTTP_DETAILED_ERRORS_ENABLED = \"http.detailed_errors.enabled\";\n\n    public static final boolean DEFAULT_SETTING_PIPELINING = true;\n    public static final int DEFAULT_SETTING_PIPELINING_MAX_EVENTS = 10000;\n    public static final String DEFAULT_PORT_RANGE = \"9200-9300\";\n\n    private static final String[] DEFAULT_CORS_METHODS = { \"OPTIONS\", \"HEAD\", \"GET\", \"POST\", \"PUT\", \"DELETE\" };\n    private static final String[] DEFAULT_CORS_HEADERS = { \"X-Requested-With\", \"Content-Type\", \"Content-Length\" };\n    private static final int DEFAULT_CORS_MAX_AGE = 1728000;\n\n    protected BigArrays bigArrays;\n\n    protected ByteSizeValue maxContentLength;\n    protected ByteSizeValue maxInitialLineLength;\n    protected ByteSizeValue maxHeaderSize;\n    protected ByteSizeValue maxChunkSize;\n\n    protected int workerCount;\n\n    protected boolean blockingServer;\n\n    protected boolean pipelining;\n\n    protected int pipeliningMaxEvents;\n\n    protected boolean compression;\n\n    protected int compressionLevel;\n\n    protected boolean resetCookies;\n\n    protected String port;\n\n    protected String[] publishHosts;\n\n    protected boolean detailedErrorsEnabled;\n\n    protected String tcpNoDelay;\n    protected String tcpKeepAlive;\n    protected boolean reuseAddress;\n\n    protected ByteSizeValue tcpSendBufferSize;\n    protected ByteSizeValue tcpReceiveBufferSize;\n    protected ReceiveBufferSizePredictorFactory receiveBufferSizePredictorFactory;\n\n    protected ByteSizeValue maxCumulationBufferCapacity;\n    protected int maxCompositeBufferComponents;\n\n    protected volatile ServerBootstrap serverBootstrap;\n\n    protected volatile BoundTransportAddress boundAddress;\n\n    private CorsConfig corsConfig;\n\n    private Settings settings;\n\n    @Autowired\n    private NettyHttpController nettyHttpController;\n\n    public NettyHttpServerTransport() {\n        // pass\n    }\n\n    public void init() {\n        this.settings = Settings.EMPTY;\n        this.bigArrays = BigArrays.NON_RECYCLING_INSTANCE;\n\n        if (settings.getAsBoolean(\"netty.epollBugWorkaround\", false).booleanValue()) {\n            System.setProperty(\"org.jboss.netty.epollBugWorkaround\", \"true\");\n        }\n\n        ByteSizeValue localMaxContentLength = settings.getAsBytesSize(\"http.netty.max_content_length\", settings.getAsBytesSize(\"http.max_content_length\", new ByteSizeValue(100, ByteSizeUnit.MB)));\n        this.maxChunkSize = settings.getAsBytesSize(\"http.netty.max_chunk_size\", settings.getAsBytesSize(\"http.max_chunk_size\", new ByteSizeValue(8, ByteSizeUnit.KB)));\n        this.maxHeaderSize = settings.getAsBytesSize(\"http.netty.max_header_size\", settings.getAsBytesSize(\"http.max_header_size\", new ByteSizeValue(8, ByteSizeUnit.KB)));\n        this.maxInitialLineLength = settings.getAsBytesSize(\"http.netty.max_initial_line_length\", settings.getAsBytesSize(\"http.max_initial_line_length\", new ByteSizeValue(8, ByteSizeUnit.KB)));\n        // don't reset cookies by default, since I don't think we really need to\n        // note, parsing cookies was fixed in netty 3.5.1 regarding stack allocation, but still, currently, we don't need cookies\n        this.resetCookies = settings.getAsBoolean(\"http.netty.reset_cookies\", settings.getAsBoolean(\"http.reset_cookies\", false));\n        this.maxCumulationBufferCapacity = settings.getAsBytesSize(\"http.netty.max_cumulation_buffer_capacity\", null);\n        this.maxCompositeBufferComponents = settings.getAsInt(\"http.netty.max_composite_buffer_components\", -1);\n        this.workerCount = settings.getAsInt(\"http.netty.worker_count\", EsExecutors.boundedNumberOfProcessors(settings) * 2);\n        this.blockingServer = settings.getAsBoolean(\"http.netty.http.blocking_server\", settings.getAsBoolean(TCP_BLOCKING_SERVER, settings.getAsBoolean(TCP_BLOCKING, false)));\n        this.port = settings.get(\"http.netty.port\", settings.get(\"http.port\", DEFAULT_PORT_RANGE));\n\n        this.publishHosts = settings.getAsArray(\"http.netty.publish_host\", settings.getAsArray(\"http.publish_host\", settings.getAsArray(\"http.host\", null)));\n        this.tcpNoDelay = settings.get(\"http.netty.tcp_no_delay\", settings.get(TCP_NO_DELAY, \"true\"));\n        this.tcpKeepAlive = settings.get(\"http.netty.tcp_keep_alive\", settings.get(TCP_KEEP_ALIVE, \"true\"));\n        this.reuseAddress = settings.getAsBoolean(\"http.netty.reuse_address\", settings.getAsBoolean(TCP_REUSE_ADDRESS, NetworkUtils.defaultReuseAddress()));\n        this.tcpSendBufferSize = settings.getAsBytesSize(\"http.netty.tcp_send_buffer_size\", settings.getAsBytesSize(TCP_SEND_BUFFER_SIZE, TCP_DEFAULT_SEND_BUFFER_SIZE));\n        this.tcpReceiveBufferSize = settings.getAsBytesSize(\"http.netty.tcp_receive_buffer_size\", settings.getAsBytesSize(TCP_RECEIVE_BUFFER_SIZE, TCP_DEFAULT_RECEIVE_BUFFER_SIZE));\n        this.detailedErrorsEnabled = settings.getAsBoolean(SETTING_HTTP_DETAILED_ERRORS_ENABLED, true);\n\n        long defaultReceiverPredictor = 512 * 1024L;\n        if (JvmInfo.jvmInfo().getMem().getDirectMemoryMax().bytes() > 0) {\n            // we can guess a better default...\n            long l = (long) ((0.3 * JvmInfo.jvmInfo().getMem().getDirectMemoryMax().bytes()) / workerCount);\n            defaultReceiverPredictor = Math.min(defaultReceiverPredictor, Math.max(l, 64 * 1024L));\n        }\n\n        // See AdaptiveReceiveBufferSizePredictor#DEFAULT_XXX for default values in netty..., we can use higher ones for us, even fixed one\n        ByteSizeValue receivePredictorMin = settings.getAsBytesSize(\"http.netty.receive_predictor_min\", settings.getAsBytesSize(\"http.netty.receive_predictor_size\", new ByteSizeValue(defaultReceiverPredictor)));\n        ByteSizeValue receivePredictorMax = settings.getAsBytesSize(\"http.netty.receive_predictor_max\", settings.getAsBytesSize(\"http.netty.receive_predictor_size\", new ByteSizeValue(defaultReceiverPredictor)));\n        if (receivePredictorMax.bytes() == receivePredictorMin.bytes()) {\n            receiveBufferSizePredictorFactory = new FixedReceiveBufferSizePredictorFactory((int) receivePredictorMax.bytes());\n        } else {\n            receiveBufferSizePredictorFactory = new AdaptiveReceiveBufferSizePredictorFactory((int) receivePredictorMin.bytes(), (int) receivePredictorMin.bytes(), (int) receivePredictorMax.bytes());\n        }\n\n        this.compression = settings.getAsBoolean(SETTING_HTTP_COMPRESSION, false);\n        this.compressionLevel = settings.getAsInt(SETTING_HTTP_COMPRESSION_LEVEL, 6);\n        this.pipelining = settings.getAsBoolean(SETTING_PIPELINING, DEFAULT_SETTING_PIPELINING);\n        this.pipeliningMaxEvents = settings.getAsInt(SETTING_PIPELINING_MAX_EVENTS, DEFAULT_SETTING_PIPELINING_MAX_EVENTS);\n        this.corsConfig = buildCorsConfig(settings);\n\n        // validate max content length\n        if (localMaxContentLength.bytes() > Integer.MAX_VALUE) {\n            logger.warn(\"maxContentLength[{}] set to high value, resetting it to [100mb]\", localMaxContentLength);\n            localMaxContentLength = new ByteSizeValue(100, ByteSizeUnit.MB);\n        }\n        this.maxContentLength = localMaxContentLength;\n\n        logger.debug(\"using max_chunk_size[{}], max_header_size[{}], max_initial_line_length[{}], max_content_length[{}], receive_predictor[{}->{}], pipelining[{}], pipelining_max_events[{}]\",\n                maxChunkSize, maxHeaderSize, maxInitialLineLength, this.maxContentLength, receivePredictorMin, receivePredictorMax, pipelining, pipeliningMaxEvents);\n\n        doStart();\n    }\n\n    public Settings settings() {\n        return this.settings;\n    }\n\n    protected void doStart() {\n        if (blockingServer) {\n            serverBootstrap = new ServerBootstrap(new OioServerSocketChannelFactory(\n                    Executors.newCachedThreadPool(new HttpDeamondThreadFactory(\"http_boss\")),\n                    Executors.newCachedThreadPool(new HttpDeamondThreadFactory(\"http_worker\"))\n            ));\n        } else {\n            serverBootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(\n                    Executors.newCachedThreadPool(new HttpDeamondThreadFactory(\"http_boss\")),\n                    Executors.newCachedThreadPool(new HttpDeamondThreadFactory(\"http_worker\")),\n                    workerCount));\n        }\n\n        serverBootstrap.setPipelineFactory(configureServerChannelPipelineFactory());\n\n        if (!\"default\".equals(tcpNoDelay)) {\n            serverBootstrap.setOption(\"child.tcpNoDelay\", Booleans.parseBoolean(tcpNoDelay, null));\n        }\n        if (!\"default\".equals(tcpKeepAlive)) {\n            serverBootstrap.setOption(\"child.keepAlive\", Booleans.parseBoolean(tcpKeepAlive, null));\n        }\n        if (tcpSendBufferSize != null && tcpSendBufferSize.bytes() > 0) {\n            serverBootstrap.setOption(\"child.sendBufferSize\", tcpSendBufferSize.bytes());\n        }\n        if (tcpReceiveBufferSize != null && tcpReceiveBufferSize.bytes() > 0) {\n            serverBootstrap.setOption(\"child.receiveBufferSize\", tcpReceiveBufferSize.bytes());\n        }\n        serverBootstrap.setOption(\"receiveBufferSizePredictorFactory\", receiveBufferSizePredictorFactory);\n        serverBootstrap.setOption(\"child.receiveBufferSizePredictorFactory\", receiveBufferSizePredictorFactory);\n        serverBootstrap.setOption(\"reuseAddress\", reuseAddress);\n        serverBootstrap.setOption(\"child.reuseAddress\", reuseAddress);\n\n        try {\n            serverBootstrap.bind(new InetSocketAddress(httpPort));\n        } catch (ChannelException e) {\n            logger.error(\"http port bind exception\", e);\n            System.exit(1);\n        }\n\n        logger.info(\"nettyHttpServerTransport init done\");\n    }\n\n    private CorsConfig buildCorsConfig(Settings settings) {\n        if (!settings.getAsBoolean(SETTING_CORS_ENABLED, false).booleanValue()) {\n            return CorsConfigBuilder.forOrigins().disable().build();\n        }\n        String origin = settings.get(SETTING_CORS_ALLOW_ORIGIN);\n        final CorsConfigBuilder builder;\n        if (Strings.isNullOrEmpty(origin)) {\n            builder = CorsConfigBuilder.forOrigins();\n        } else if (origin.equals(ANY_ORIGIN)) {\n            builder = CorsConfigBuilder.forAnyOrigin();\n        } else {\n            Pattern p = RestUtils.checkCorsSettingForRegex(origin);\n            if (p == null) {\n                builder = CorsConfigBuilder.forOrigins(RestUtils.corsSettingAsArray(origin));\n            } else {\n                builder = CorsConfigBuilder.forPattern(p);\n            }\n        }\n        if (settings.getAsBoolean(SETTING_CORS_ALLOW_CREDENTIALS, false).booleanValue()) {\n            builder.allowCredentials();\n        }\n        String[] strMethods = settings.getAsArray(SETTING_CORS_ALLOW_METHODS, DEFAULT_CORS_METHODS);\n        HttpMethod[] methods = new HttpMethod[strMethods.length];\n        for (int i = 0; i < methods.length; i++) {\n            methods[i] = HttpMethod.valueOf(strMethods[i]);\n        }\n        return builder.allowedRequestMethods(methods)\n                      .maxAge(settings.getAsInt(SETTING_CORS_MAX_AGE, DEFAULT_CORS_MAX_AGE))\n                      .allowedRequestHeaders(settings.getAsArray(SETTING_CORS_ALLOW_HEADERS, DEFAULT_CORS_HEADERS))\n                      .shortCircuit()\n                      .build();\n    }\n\n    public BoundTransportAddress boundAddress() {\n        return this.boundAddress;\n    }\n\n    public HttpInfo info() {\n        BoundTransportAddress boundTransportAddress = boundAddress();\n        if (boundTransportAddress == null) {\n            return null;\n        }\n        return new HttpInfo(boundTransportAddress, maxContentLength.bytes());\n    }\n\n    public HttpStats stats() {\n        return new HttpStats(0, 0);\n    }\n\n    public CorsConfig getCorsConfig() {\n        return corsConfig;\n    }\n\n    protected void dispatchRequest(HttpRequest request, HttpChannel channel) {\n        nettyHttpController.dispatchRequest(request, channel);\n    }\n\n    protected void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {\n        if (e.getCause() instanceof ReadTimeoutException) {\n            if (logger.isTraceEnabled()) {\n                logger.trace(\"Connection timeout [{}]\", ctx.getChannel().getRemoteAddress());\n            }\n            ctx.getChannel().close();\n        } else {\n            if (!NetworkExceptionHelper.isCloseConnectionException(e.getCause())) {\n                logger.warn(\"Caught exception while handling client http traffic, closing connection\", e.getCause());\n                ctx.getChannel().close();\n            } else {\n                logger.debug(\"Caught exception while handling client http traffic, closing connection\", e.getCause());\n                ctx.getChannel().close();\n            }\n        }\n    }\n\n    public HttpChannelPipelineFactory configureServerChannelPipelineFactory() {\n        return new HttpChannelPipelineFactory(this, detailedErrorsEnabled);\n    }\n\n    protected static class HttpChannelPipelineFactory implements ChannelPipelineFactory {\n\n        protected final NettyHttpServerTransport transport;\n        protected final HttpRequestHandler requestHandler;\n\n        public HttpChannelPipelineFactory(NettyHttpServerTransport transport, boolean detailedErrorsEnabled) {\n            this.transport = transport;\n            this.requestHandler = new HttpRequestHandler(transport, detailedErrorsEnabled);\n        }\n\n        @Override\n        public ChannelPipeline getPipeline() throws Exception {\n            ChannelPipeline pipeline = Channels.pipeline();\n            HttpRequestDecoder requestDecoder = new HttpRequestDecoder(\n                    (int) transport.maxInitialLineLength.bytes(),\n                    (int) transport.maxHeaderSize.bytes(),\n                    (int) transport.maxChunkSize.bytes()\n            );\n            if (transport.maxCumulationBufferCapacity != null) {\n                if (transport.maxCumulationBufferCapacity.bytes() > Integer.MAX_VALUE) {\n                    requestDecoder.setMaxCumulationBufferCapacity(Integer.MAX_VALUE);\n                } else {\n                    requestDecoder.setMaxCumulationBufferCapacity((int) transport.maxCumulationBufferCapacity.bytes());\n                }\n            }\n            if (transport.maxCompositeBufferComponents != -1) {\n                requestDecoder.setMaxCumulationBufferComponents(transport.maxCompositeBufferComponents);\n            }\n            pipeline.addLast(\"decoder\", requestDecoder);\n            pipeline.addLast(\"decoder_compress\", new ESHttpContentDecompressor(transport.compression));\n            HttpChunkAggregator httpChunkAggregator = new HttpChunkAggregator((int) transport.maxContentLength.bytes());\n            if (transport.maxCompositeBufferComponents != -1) {\n                httpChunkAggregator.setMaxCumulationBufferComponents(transport.maxCompositeBufferComponents);\n            }\n            pipeline.addLast(\"aggregator\", httpChunkAggregator);\n            pipeline.addLast(\"encoder\", new ESHttpResponseEncoder());\n            if (transport.compression) {\n                pipeline.addLast(\"encoder_compress\", new HttpContentCompressor(transport.compressionLevel));\n            }\n            if (transport.settings().getAsBoolean(SETTING_CORS_ENABLED, false).booleanValue()) {\n                pipeline.addLast(\"cors\", new CorsHandler(transport.getCorsConfig()));\n            }\n            if (transport.pipelining) {\n                pipeline.addLast(\"pipelining\", new HttpPipeliningHandler(transport.pipeliningMaxEvents));\n            }\n            pipeline.addLast(\"handler\", requestHandler);\n            return pipeline;\n        }\n    }\n}\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/http/RestController.java",
    "content": "package com.didi.arius.gateway.rest.http;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.utils.PathTrie;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.elasticsearch.common.Nullable;\nimport org.elasticsearch.rest.RestRequest;\nimport org.elasticsearch.rest.RestRequest.Method;\nimport org.elasticsearch.rest.support.RestUtils;\nimport org.springframework.stereotype.Component;\n\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.function.Supplier;\n\n/**\n* @author weizijun\n* @date：2016年8月16日\n* \n*/\n@Component(\"restController\")\npublic class RestController {\n\n    protected static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n\n    public static final PathTrie.Decoder REST_DECODER = value -> RestUtils.decodeComponent(value);\n\n    private final PathTrie<MethodHandlers> handlers = new PathTrie<>(REST_DECODER);\n    \n    public void registerHandler(Method method, String path, IRestHandler handler) {\n        handlers.insertOrUpdate(path, new MethodHandlers(path, handler, method),\n                (mHandlers, newMHandler) -> mHandlers.addMethods(handler, method));\n    }\n\n    public IRestHandler tryAllHandlers(final RestRequest request) {\n        final String rawPath = request.rawPath();\n        final String uri = request.uri();\n        final Method requestMethod;\n        try {\n            // Resolves the HTTP method and fails if the method is invalid\n            requestMethod = request.method();\n            // Loop through all possible handlers, attempting to dispatch the request\n            Iterator<MethodHandlers> allHandlers = getAllHandlers(request.params(), rawPath);\n            while (allHandlers.hasNext()) {\n                final IRestHandler handler;\n                final MethodHandlers methodHandlers = allHandlers.next();\n                if (methodHandlers == null) {\n                    handler = null;\n                } else {\n                    handler = methodHandlers.getHandler(requestMethod);\n                }\n                if (handler != null) {\n                    return handler;\n                }\n            }\n        } catch (Exception e) {\n            bootLogger.warn(\"find uri={}, rawPath={} handler throws exception: \", uri, rawPath);\n        }\n        return null;\n    }\n\n    Iterator<MethodHandlers> getAllHandlers(@Nullable Map<String, String> requestParamsRef, String rawPath) {\n        final Supplier<Map<String, String>> paramsSupplier;\n        if (requestParamsRef == null) {\n            paramsSupplier = () -> null;\n        } else {\n            // Between retrieving the correct path, we need to reset the parameters,\n            // otherwise parameters are parsed out of the URI that aren't actually handled.\n            final Map<String, String> originalParams = new HashMap<>(requestParamsRef);\n            paramsSupplier = () -> {\n                // PathTrie modifies the request, so reset the params between each iteration\n                requestParamsRef.clear();\n                requestParamsRef.putAll(originalParams);\n                return requestParamsRef;\n            };\n        }\n        // we use rawPath since we don't want to decode it while processing the path resolution\n        // so we can handle things like:\n        // my_index/my_type/http%3A%2F%2Fwww.google.com\n        return handlers.retrieveAll(rawPath, paramsSupplier);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/init/InitGateway.java",
    "content": "package com.didi.arius.gateway.rest.init;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.rest.http.NettyHttpServerTransport;\nimport com.didi.arius.gateway.rest.tcp.NettyTransport;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\n\n@Component(\"initGateway\")\npublic class InitGateway {\n\tprotected static final ILog bootLogger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n\n\t@Autowired\n\tprivate NettyTransport nettyTransport;\n\n\t@Autowired\n\tprivate NettyHttpServerTransport nettyHttpServerTransport;\n\n\tpublic InitGateway() {\n\t\t// pass\n\t}\n\n\t@PostConstruct\n\tpublic void init() {\n\t\t//启动tcp server\n\t\tnettyTransport.init();\n\t\t//启动http server\n\t\tnettyHttpServerTransport.init();\n\t\tbootLogger.info(\"nettyTransport init done\");\n\t}\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/tcp/Adapter.java",
    "content": "package com.didi.arius.gateway.rest.tcp;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.elasticsearch.cluster.node.DiscoveryNode;\nimport org.elasticsearch.common.metrics.MeanMetric;\nimport org.elasticsearch.transport.*;\nimport org.springframework.stereotype.Component;\n\n/**\n* @author weizijun\n* @date：2016年9月12日\n* \n*/\n@Component(\"adapter\")\npublic class Adapter implements TransportServiceAdapter {\n\tprotected static final ILog tracerLog = LogFactory.getLog(Adapter.class);\n\n    final MeanMetric rxMetric = new MeanMetric();\n    final MeanMetric txMetric = new MeanMetric();\t\n\t\n\t@Override\n\tpublic void received(long size) {\n\t\trxMetric.inc(size);\n\t}\n\n\t@Override\n\tpublic void sent(long size) {\n\t\ttxMetric.inc(size);\n\t}\n\n\t@Override\n\tpublic void onRequestSent(DiscoveryNode node, long requestId, String action, TransportRequest request,\n\t\t\tTransportRequestOptions options) {\n        if (traceEnabled()) {\n            traceRequestSent(node, requestId, action, options);\n        }\n\t}\n\t\n    protected boolean traceEnabled() {\n        return tracerLog.isTraceEnabled();\n    }\n\n\t@Override\n\tpublic void onResponseSent(long requestId, String action, TransportResponse response,\n\t\t\tTransportResponseOptions options) {\n        if (traceEnabled()) {\n            traceResponseSent(requestId, action);\n        }\n\t}\n\n\t@Override\n\tpublic void onResponseSent(long requestId, String action, Throwable t) {\n        if (traceEnabled()) {\n            traceResponseSent(requestId, action, t);\n        }\n\t}\n\t\n    protected void traceResponseSent(long requestId, String action, Throwable t) {\n        tracerLog.trace(\"[{}][{}] sent error response (error: [{}])\", requestId, action, t.getMessage());\n    }\n\n\t@Override\n\tpublic TransportResponseHandler onResponseReceived(long requestId) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void onRequestReceived(long requestId, String action) {\n        if (traceEnabled()) {\n            traceReceivedRequest(requestId, action);\n        }\n\t}\n\n\t@Override\n\tpublic RequestHandlerRegistry getRequestHandler(String action) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void raiseNodeConnected(DiscoveryNode node) {\n\t\t//pass\n\t}\n\n\t@Override\n\tpublic void raiseNodeDisconnected(DiscoveryNode node) {\n\t\t//pass\n\t}\n\t\n    protected void traceReceivedRequest(long requestId, String action) {\n        tracerLog.trace(\"[{}][{}] received request\", requestId, action);\n    }\n\n    protected void traceResponseSent(long requestId, String action) {\n        tracerLog.trace(\"[{}][{}] sent response\", requestId, action);\n    }\n\n    protected void traceUnresolvedResponse(long requestId) {\n        tracerLog.trace(\"[{}] received response but can't resolve it to a request\", requestId);\n    }\n\n    protected void traceRequestSent(DiscoveryNode node, long requestId, String action, TransportRequestOptions options) {\n        tracerLog.trace(\"[{}][{}] sent to [{}] (timeout: [{}])\", requestId, action, node, options.timeout());\n    }\t\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/tcp/MessageChannelHandler.java",
    "content": "package com.didi.arius.gateway.rest.tcp;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.es.tcp.ActionController;\nimport com.didi.arius.gateway.core.es.tcp.ActionHandler;\nimport com.didi.arius.gateway.core.service.RequestStatsService;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.apache.lucene.util.IOUtils;\nimport org.elasticsearch.Version;\nimport org.elasticsearch.cluster.node.DiscoveryNode;\nimport org.elasticsearch.common.compress.Compressor;\nimport org.elasticsearch.common.compress.CompressorFactory;\nimport org.elasticsearch.common.compress.NotCompressedException;\nimport org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;\nimport org.elasticsearch.common.io.stream.NamedWriteableRegistry;\nimport org.elasticsearch.common.io.stream.StreamInput;\nimport org.elasticsearch.common.transport.InetSocketTransportAddress;\nimport org.elasticsearch.common.util.concurrent.KeyedLock;\nimport org.elasticsearch.transport.TransportChannel;\nimport org.elasticsearch.transport.TransportRequest;\nimport org.elasticsearch.transport.netty.ChannelBufferStreamInputFactory;\nimport org.elasticsearch.transport.netty.NettyHeader;\nimport org.elasticsearch.transport.netty.NettyTransport.NodeChannels;\nimport org.elasticsearch.transport.netty.SizeHeaderFrameDecoder;\nimport org.elasticsearch.transport.support.TransportStatus;\nimport org.jboss.netty.buffer.ChannelBuffer;\nimport org.jboss.netty.buffer.ChannelBuffers;\nimport org.jboss.netty.channel.*;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport java.net.InetSocketAddress;\nimport java.nio.channels.CancelledKeyException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.UUID;\nimport java.util.concurrent.ConcurrentMap;\n\nimport static org.elasticsearch.common.transport.NetworkExceptionHelper.isCloseConnectionException;\nimport static org.elasticsearch.common.transport.NetworkExceptionHelper.isConnectException;\nimport static org.elasticsearch.common.util.concurrent.ConcurrentCollections.newConcurrentMap;\n\n/**\n * @author weizijun @date：2016年9月12日\n * \n */\n@Component(\"messageChannelHandler\")\npublic class MessageChannelHandler extends SimpleChannelUpstreamHandler {\n\n\t@Autowired\n\tprotected NettyTransport transport;\n\t\n\t@Autowired\n\tprotected Adapter transportServiceAdapter;\n\n\t@Autowired\n\tprotected ActionController actionController;\n\n\t@Autowired\n\tprotected RequestStatsService requestStatsService;\n\n\tprivate static final ILog logger = LogFactory.getLog(MessageChannelHandler.class);\n\t\n\t// node id to actual channel\n    protected final ConcurrentMap<DiscoveryNode, NodeChannels> connectedNodes = newConcurrentMap();\n    \n    protected final KeyedLock<String> connectionLock = new KeyedLock<>();\n    \n    protected final NamedWriteableRegistry namedWriteableRegistry = new NamedWriteableRegistry();\n    \n\t@Autowired\n\tprotected QueryConfig queryConfig;\n\n\t@Override\n\tpublic void writeComplete(ChannelHandlerContext ctx, WriteCompletionEvent e) throws Exception {\n\t\ttransportServiceAdapter.sent(e.getWrittenAmount());\n\t\tsuper.writeComplete(ctx, e);\n\t}\n\n\t@Override\n\tpublic void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {\n\t\tObject m = e.getMessage();\n\t\tif (!(m instanceof ChannelBuffer)) {\n\t\t\tctx.sendUpstream(e);\n\t\t\treturn;\n\t\t}\n\t\tChannelBuffer buffer = (ChannelBuffer) m;\n\t\tint size = buffer.getInt(buffer.readerIndex() - 4);\n\t\ttransportServiceAdapter.received((long)size + 6);\n\n\t\t// we have additional bytes to read, outside of the header\n\t\tboolean hasMessageBytesToRead = (size - (NettyHeader.HEADER_SIZE - 6)) != 0;\n\n\t\tint markedReaderIndex = buffer.readerIndex();\n\t\tint expectedIndexReader = markedReaderIndex + size;\n\n\t\t// netty always copies a buffer, either in NioWorker in its read\n\t\t// handler, where it copies to a fresh\n\t\t// buffer, or in the cumlation buffer, which is cleaned each time\n\t\tStreamInput streamIn = ChannelBufferStreamInputFactory.create(buffer, size);\n\t\ttry {\n\t\t\tlong requestId = streamIn.readLong();\n\t\t\tbyte status = streamIn.readByte();\n\t\t\tVersion version = Version.fromId(streamIn.readInt());\n\n\t\t\tif (TransportStatus.isCompress(status) && hasMessageBytesToRead && buffer.readable()) {\n\t\t\t\tCompressor compressor;\n\t\t\t\ttry {\n\t\t\t\t\tcompressor = CompressorFactory.compressor(buffer);\n\t\t\t\t} catch (NotCompressedException ex) {\n\t\t\t\t\tint maxToRead = Math.min(buffer.readableBytes(), 10);\n\t\t\t\t\tint offset = buffer.readerIndex();\n\t\t\t\t\tStringBuilder sb = new StringBuilder(\n\t\t\t\t\t\t\t\"stream marked as compressed, but no compressor found, first [\").append(maxToRead)\n\t\t\t\t\t\t\t\t\t.append(\"] content bytes out of [\").append(buffer.readableBytes())\n\t\t\t\t\t\t\t\t\t.append(\"] readable bytes with message size [\").append(size).append(\"] \")\n\t\t\t\t\t\t\t\t\t.append(\"] are [\");\n\t\t\t\t\tfor (int i = 0; i < maxToRead; i++) {\n\t\t\t\t\t\tsb.append(buffer.getByte(offset + i)).append(\",\");\n\t\t\t\t\t}\n\t\t\t\t\tsb.append(\"]\");\n\t\t\t\t\tthrow new IllegalStateException(sb.toString());\n\t\t\t\t}\n\t\t\t\tstreamIn = compressor.streamInput(streamIn);\n\t\t\t}\n\t\t\tstreamIn.setVersion(version);\n\n\t\t\tif (TransportStatus.isRequest(status)) {\n                String action = handleRequest(ctx.getChannel(), streamIn, requestId, version, size);\n\n                // Chek the entire message has been read\n                final int nextByte = streamIn.read();\n                // calling read() is useful to make sure the message is fully read, even if there some kind of EOS marker\n                if (nextByte != -1) {\n                    throw new IllegalStateException(\"Message not fully read (request) for requestId [\" + requestId + \"], action [\"\n                            + action + \"], readerIndex [\" + buffer.readerIndex() + \"] vs expected [\" + expectedIndexReader + \"]; resetting\");\n                }\n                if (buffer.readerIndex() < expectedIndexReader) {\n                    throw new IllegalStateException(\"Message is fully read (request), yet there are \" + (expectedIndexReader - buffer.readerIndex()) + \" remaining bytes; resetting\");\n                }\n                if (buffer.readerIndex() > expectedIndexReader) {\n                    throw new IllegalStateException(\"Message read past expected size (request) for requestId [\" + requestId + \"], action [\"\n                            + action + \"], readerIndex [\" + buffer.readerIndex() + \"] vs expected [\" + expectedIndexReader + \"]; resetting\");\n                }\n\t\t\t}\n\t\t} finally {\n\t\t\ttry {\n\t\t\t\tIOUtils.closeWhileHandlingException(streamIn);\n\t\t\t} finally {\n\t\t\t\t// Set the expected position of the buffer, no matter what\n\t\t\t\t// happened\n\t\t\t\tbuffer.readerIndex(expectedIndexReader);\n\t\t\t}\n\t\t}\n\t}\n\t\n    protected String handleRequest(Channel channel, StreamInput buffer, long requestId, Version version, int requestLength) throws Exception {\n        buffer = new NamedWriteableAwareStreamInput(buffer, namedWriteableRegistry);\n        final String action = buffer.readString();\n        transportServiceAdapter.onRequestReceived(requestId, action);\n        final NettyTransportChannel transportChannel = new NettyTransportChannel(transport, transportServiceAdapter, action, channel, requestId, version, \"\");        \n        ActionHandler handler = actionController.getHandler(action);\n        final TransportRequest request = handler.parseRequest(new InetSocketTransportAddress((InetSocketAddress) channel.getRemoteAddress()), buffer);\n        \n        ActionContext context = parseContext(action, request, channel, transportChannel, requestLength);\n        \n        transportChannel.setActionContext(context);\n        \n        handler.handleRequest(context);\n        \n        return action;\n    }\n    \n    private ActionContext parseContext(String action, final TransportRequest request, Channel channel, TransportChannel transportChannel, int requestLength) {\n    \tActionContext context = new ActionContext();\n\t\tString searchId = request.getHeader(QueryConsts.HEAD_SEARCH_ID);\n\t\tString clusterId = request.getHeader(QueryConsts.HEAD_CLUSTER_ID);\n\t\tString user = request.getHeader(QueryConsts.HEAD_USER);\n\t\tString authentication = request.getHeader(QueryConsts.HEAD_AUTHORIZATION);\n\t\t\n\t\tString traceid = request.getHeader(QueryConsts.TRACE_ID);\n\t\tString spanid = request.getHeader(QueryConsts.SPAN_ID);\n\t\t\n\t\tif (traceid == null) {\n\t\t\ttraceid = \"\";\n\t\t}\n\t\t\n\t\tif (spanid == null) {\n\t\t\tspanid = \"\";\n\t\t}\t\t\n\t\t\n\t\tString remoteAddr = ((InetSocketAddress)channel.getRemoteAddress()).getHostString();\n\t\t\n\t\tif (searchId == null) {\n\t\t\tsearchId = QueryConsts.TOTAL_SEARCH_ID;\n\t\t}\n\t\t\n\t\tcontext.setTraceid(traceid);\n\t\tcontext.setRequestId(UUID.randomUUID().toString());\n\t\tcontext.setSearchId(searchId);\n\t\tcontext.setClusterId(clusterId);\n\t\tcontext.setUser(user);\n\t\tcontext.setRemoteAddr(remoteAddr);\n\t\tcontext.setAuthentication(authentication);\n\t\t\n\t\tcontext.setTraceid(traceid);\n\t\tcontext.setSpanid(spanid);\n\n\t\tcontext.setRequest(request);\n\t\tcontext.setChannel(transportChannel);\t\t\n\t\tcontext.setActionName(action);\n\t\t\n\t\tcontext.setSemaphore(queryConfig.getTcpSemaphore());\n\t\tcontext.setRequestLength(requestLength);\n\t\tcontext.setDetailLog(true);\n\n\t\trequestStatsService.putActionContext(context.getRequestId(), context);\n\t\t\n\t\treturn context;\n    }\n\t\n\t@Override\n\tpublic void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)\n\t\t\tthrows Exception {\n\t\tlogger.info(\"client connect,client:{}\", ctx.getChannel().getRemoteAddress());\n\t}\n\t\n\t@Override\n\tpublic void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {\n\t\tlogger.info(\"client disconnect,clent:{}\", ctx.getChannel().getRemoteAddress());\n\t}\n\t\n    @Override\n    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {\n        if (isCloseConnectionException(e.getCause())) {\n            logger.trace(\"close connection exception caught on transport layer , disconnecting from relevant node\", e.getCause());\n            // close the channel, which will cause a node to be disconnected if relevant\n            ctx.getChannel().close();\n        } else if (isConnectException(e.getCause())) {\n            logger.trace(\"connect exception caught on transport layer\", e.getCause());\n            // close the channel as safe measure, which will cause a node to be disconnected if relevant\n            ctx.getChannel().close();\n        } else if (e.getCause() instanceof CancelledKeyException) {\n            logger.trace(\"cancelled key exception caught on transport layer, disconnecting from relevant node\", e.getCause());\n            // close the channel as safe measure, which will cause a node to be disconnected if relevant\n            ctx.getChannel().close();\n        } else if (e.getCause() instanceof SizeHeaderFrameDecoder.HttpOnTransportException) {\n            // in case we are able to return data, serialize the exception content and sent it back to the client\n            if (ctx.getChannel().isOpen()) {\n                ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(e.getCause().getMessage().getBytes(StandardCharsets.UTF_8));\n                ChannelFuture channelFuture = ctx.getChannel().write(buffer);\n                channelFuture.addListener(new ChannelFutureListener() {\n                    @Override\n                    public void operationComplete(ChannelFuture future) throws Exception {\n                        future.getChannel().close();\n                    }\n                });\n            }\n        } else {\n            logger.warn(\"exception caught on transport layer, closing connection\", e.getCause());\n            // close the channel, which will cause a node to be disconnected if relevant\n            ctx.getChannel().close();\n        }\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/tcp/NettyTransport.java",
    "content": "package com.didi.arius.gateway.rest.tcp;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport com.didiglobal.knowframework.observability.Observability;\nimport org.elasticsearch.common.network.NetworkUtils;\nimport org.elasticsearch.common.transport.InetSocketTransportAddress;\nimport org.elasticsearch.common.transport.TransportAddress;\nimport org.elasticsearch.common.unit.ByteSizeValue;\nimport org.elasticsearch.common.util.BigArrays;\nimport org.elasticsearch.monitor.jvm.JvmInfo;\nimport org.elasticsearch.transport.netty.SizeHeaderFrameDecoder;\nimport org.jboss.netty.bootstrap.ServerBootstrap;\nimport org.jboss.netty.channel.*;\nimport org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;\nimport org.jboss.netty.util.ThreadRenamingRunnable;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\nimport java.net.InetSocketAddress;\nimport java.net.SocketAddress;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n* @author weizijun\n* @date：2016年9月12日\n* \n*/\n@Component(\"nettyTransport\")\npublic class NettyTransport {\n\tprivate static final ILog logger = LogFactory.getLog(QueryConsts.BOOT_LOGGER);\n\t\n\t@Value(\"${gateway.nettyTransport.port}\")\n\tprivate short port;\n\n\t@Value(\"${gateway.nettyTransport.bossThreadCount}\")\n\tprivate int bossThreadCount;\n\n\t@Value(\"${gateway.nettyTransport.workerCount}\")\n\tprivate int workerCount;\n\n\t@Value(\"${gateway.nettyTransport.tcpNoDelay}\")\n\tprivate boolean tcpNoDelay;\n\n\t@Value(\"${gateway.nettyTransport.keepAlive}\")\n\tprivate boolean keepAlive;\n\t\n\tprotected static final boolean COMPRESS = false;\n\tprotected static final BigArrays bigArrays = BigArrays.NON_RECYCLING_INSTANCE;\n\t\n    @Autowired\n    private MessageChannelHandler messageChannelHandler;\n\n\tpublic NettyTransport() {\n\t\t// pass\n\t}\n\n\tpublic void init() {\n\t\tOpenChannelsHandler serverOpenChannels = new OpenChannelsHandler(logger);\n\n\t\tExecutorService bossThreadPool = Observability.wrap(Executors\n\t\t\t\t.newCachedThreadPool(new DeamondThreadFactory(\n\t\t\t\t\t\t\"boss\")));\n\t\tExecutorService workerThreadPool = Observability.wrap(Executors\n\t\t\t\t.newCachedThreadPool(new DeamondThreadFactory(\n\t\t\t\t\t\t\"worker\")));\n\t\tNioServerSocketChannelFactory serverNioFactory = new NioServerSocketChannelFactory(bossThreadPool,\n\t\t\t\tbossThreadCount, workerThreadPool,\n\t\t\t\tworkerCount);\n\n\t\tServerBootstrap serverBootstrap = new ServerBootstrap(serverNioFactory);\n        serverBootstrap.setPipelineFactory(() -> {\n\t\t\tChannelPipeline channelPipeline = Channels.pipeline();\n\t\t\tchannelPipeline.addLast(\"openChannels\", serverOpenChannels);\n\t\t\tSizeHeaderFrameDecoder sizeHeader = new SizeHeaderFrameDecoder();\n\t\t\tchannelPipeline.addLast(\"size\", sizeHeader);\n\t\t\tchannelPipeline.addLast(\"dispatcher\", messageChannelHandler);\n\t\t\treturn channelPipeline;\n\t\t});\n        \n        serverBootstrap.setOption(\"child.tcpNoDelay\", tcpNoDelay);\n        serverBootstrap.setOption(\"child.keepAlive\", keepAlive);\n\n        long defaultReceiverPredictor = 512 * 1024L;\n        if (JvmInfo.jvmInfo().getMem().getDirectMemoryMax().bytes() > 0) {\n            // we can guess a better default...\n            long l = (long) ((0.3 * JvmInfo.jvmInfo().getMem().getDirectMemoryMax().bytes()) / workerCount);\n            defaultReceiverPredictor = Math.min(defaultReceiverPredictor, Math.max(l, 64 * 1024L));\n        }\n        \n        // See AdaptiveReceiveBufferSizePredictor#DEFAULT_XXX for default values in netty..., we can use higher ones for us, even fixed one\n\t\tByteSizeValue receivePredictorMin = new ByteSizeValue(defaultReceiverPredictor);\n\t\tByteSizeValue receivePredictorMax = new ByteSizeValue(defaultReceiverPredictor);\n\n\t\tReceiveBufferSizePredictorFactory receiveBufferSizePredictorFactory;\n\n        if (receivePredictorMax.bytes() == receivePredictorMin.bytes()) {\n            receiveBufferSizePredictorFactory = new FixedReceiveBufferSizePredictorFactory((int) receivePredictorMax.bytes());\n        } else {\n            receiveBufferSizePredictorFactory = new AdaptiveReceiveBufferSizePredictorFactory((int) receivePredictorMin.bytes(), (int) receivePredictorMin.bytes(), (int) receivePredictorMax.bytes());\n        }\n        \n        boolean reuseAddress = NetworkUtils.defaultReuseAddress();\n        \n        serverBootstrap.setOption(\"receiveBufferSizePredictorFactory\", receiveBufferSizePredictorFactory);\n        serverBootstrap.setOption(\"child.receiveBufferSizePredictorFactory\", receiveBufferSizePredictorFactory);\n        serverBootstrap.setOption(\"reuseAddress\", reuseAddress);\n        serverBootstrap.setOption(\"child.reuseAddress\", reuseAddress);\n\n\t\ttry {\n\t\t\t// bind port\n\t\t\tserverBootstrap.bind(new InetSocketAddress(getPort()));\n\t\t} catch (ChannelException e) {\n\t\t\tlogger.error(\"tcp port bind exception\", e);\n\t\t\tSystem.exit(1);\n\t\t}\n\n\t\tlogger.info(\"nettyTransport init done\");\n\t}\n\t\n\n    TransportAddress wrapAddress(SocketAddress socketAddress) {\n        return new InetSocketTransportAddress((InetSocketAddress) socketAddress);\n    }\n\n\tpublic short getPort() {\n\t\treturn port;\n\t}\n}\n\n\nclass DeamondThreadFactory implements ThreadFactory {\n\tstatic final AtomicInteger poolNumber = new AtomicInteger(1);\n\tfinal ThreadGroup group;\n\tfinal AtomicInteger threadNumber = new AtomicInteger(1);\n\tfinal String namePrefix;\n\n\tstatic {\n\t\tThreadRenamingRunnable\n\t\t\t\t.setThreadNameDeterminer((currentThreadName, proposedThreadName) -> currentThreadName);\n\t}\n\n\tpublic DeamondThreadFactory(String prefix) {\n\t\tSecurityManager s = System.getSecurityManager();\n\t\tgroup = (s != null) ? s.getThreadGroup() : Thread.currentThread()\n\t\t\t\t.getThreadGroup();\n\t\tnamePrefix = prefix + \"-pool-\" + poolNumber.getAndIncrement() + \"-\";\n\t}\n\n\t@Override\n\tpublic Thread newThread(Runnable r) {\n\t\tThread t = new Thread(group, r, namePrefix\n\t\t\t\t+ threadNumber.getAndIncrement(), 0);\n\t\tif (!t.isDaemon())\n\t\t\tt.setDaemon(true);\n\t\tif (t.getPriority() != Thread.NORM_PRIORITY)\n\t\t\tt.setPriority(Thread.NORM_PRIORITY);\n\t\treturn t;\n\t}\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/tcp/NettyTransportChannel.java",
    "content": "package com.didi.arius.gateway.rest.tcp;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didiglobal.knowframework.log.ILog;\nimport com.didiglobal.knowframework.log.LogFactory;\nimport org.elasticsearch.Version;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.bytes.ReleasablePagedBytesReference;\nimport org.elasticsearch.common.compress.CompressorFactory;\nimport org.elasticsearch.common.io.stream.BytesStreamOutput;\nimport org.elasticsearch.common.io.stream.ReleasableBytesStreamOutput;\nimport org.elasticsearch.common.io.stream.StreamOutput;\nimport org.elasticsearch.common.lease.Releasables;\nimport org.elasticsearch.common.netty.ReleaseChannelFutureListener;\nimport org.elasticsearch.transport.*;\nimport org.elasticsearch.transport.netty.NettyHeader;\nimport org.elasticsearch.transport.support.TransportStatus;\nimport org.jboss.netty.buffer.ChannelBuffer;\nimport org.jboss.netty.channel.Channel;\nimport org.jboss.netty.channel.ChannelFuture;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.IOException;\n\n\n/**\n* @author weizijun\n* @date：2016年9月18日\n* \n*/\npublic class NettyTransportChannel implements TransportChannel {\n    protected static final Logger statLogger = LoggerFactory.getLogger(QueryConsts.STAT_LOGGER);\n\n    private final NettyTransport transport;\n    private final TransportServiceAdapter transportServiceAdapter;\n    private final Version version;\n    private final String action;\n    private final Channel channel;\n    private final long requestId;\n    private final String profileName;\n    private ActionContext actionContext;\n\n    public NettyTransportChannel(NettyTransport transport, TransportServiceAdapter transportServiceAdapter, String action, Channel channel, long requestId, Version version, String profileName) {\n        this.transportServiceAdapter = transportServiceAdapter;\n        this.version = version;\n        this.transport = transport;\n        this.action = action;\n        this.channel = channel;\n        this.requestId = requestId;\n        this.profileName = profileName;\n    }\n\n    @Override\n    public String getProfileName() {\n        return profileName;\n    }\n\n    @Override\n    public String action() {\n        return this.action;\n    }\n\n    @Override\n    public void sendResponse(TransportResponse response) throws IOException {\n        sendResponse(response, TransportResponseOptions.EMPTY);\n    }\n\n\t@Override\n    public void sendResponse(TransportResponse response, TransportResponseOptions options) throws IOException {\n\t\tif (NettyTransport.COMPRESS) {\n            options = TransportResponseOptions.builder(options).withCompress(transport.COMPRESS ).build();\n        }\n\n        byte status = 0;\n        status = TransportStatus.setResponse(status);\n\n        ReleasableBytesStreamOutput bStream = new ReleasableBytesStreamOutput(NettyTransport.bigArrays);\n        boolean addedReleaseListener = false;\n        try {\n            bStream.skip(NettyHeader.HEADER_SIZE);\n            StreamOutput stream = bStream;\n            if (options.compress()) {\n                status = TransportStatus.setCompress(status);\n                stream = CompressorFactory.defaultCompressor().streamOutput(stream);\n            }\n            stream.setVersion(version);\n            response.writeTo(stream);\n            stream.close();\n\n            ReleasablePagedBytesReference bytes = bStream.bytes();\n            \n            if (actionContext != null) {\n            \tactionContext.setResponseLength(bytes.length());\n            \tstatLogger.info(QueryConsts.DLFLAG_PREFIX + \"query_tcp_response_length||type=response||requestId={}||appid={}||responseLen={}\", actionContext.getRequestId(), actionContext.getAppid(), actionContext.getResponseLength());\n            }\n\n            ChannelBuffer buffer = bytes.toChannelBuffer();\n            NettyHeader.writeHeader(buffer, requestId, status, version);\n            ChannelFuture future = channel.write(buffer);\n            ReleaseChannelFutureListener listener = new ReleaseChannelFutureListener(bytes);\n            future.addListener(listener);\n            addedReleaseListener = true;\n            transportServiceAdapter.onResponseSent(requestId, action, response, options);\n        } finally {\n            if (!addedReleaseListener) {\n                Releasables.close(bStream.bytes());\n            }\n        }\n    }\n\n    @Override\n    public void sendResponse(Throwable error) throws IOException {\n        try (BytesStreamOutput stream = new BytesStreamOutput()){\n            stream.skip(NettyHeader.HEADER_SIZE);\n            RemoteTransportException tx = new RemoteTransportException(\"\", transport.wrapAddress(channel.getLocalAddress()), action, error);\n            stream.writeThrowable(tx);\n            byte status = 0;\n            status = TransportStatus.setResponse(status);\n            status = TransportStatus.setError(status);\n\n            BytesReference bytes = stream.bytes();\n\n            if (actionContext != null) {\n                statLogger.info(QueryConsts.DLFLAG_PREFIX + \"query_tcp_response_length||type=exception||requestId={}||appid={}||responseLen={}\", actionContext.getRequestId(), actionContext.getAppid(), bytes.length());\n            }\n\n            ChannelBuffer buffer = bytes.toChannelBuffer();\n            NettyHeader.writeHeader(buffer, requestId, status, version);\n            channel.write(buffer);\n            transportServiceAdapter.onResponseSent(requestId, action, error);\n        }\n    }\n\n    @Override\n    public long getRequestId() {\n        return requestId;\n    }\n\n    @Override\n    public String getChannelType() {\n        return \"netty\";\n    }\n\n    /**\n     * Returns the underlying netty channel. This method is intended be used for access to netty to get additional\n     * details when processing the request and may be used by plugins. Responses should be sent using the methods\n     * defined in this class and not directly on the channel.\n     * @return underlying netty channel\n     */\n    public Channel getChannel() {\n        return channel;\n    }\n\n\tpublic ActionContext getActionContext() {\n\t\treturn actionContext;\n\t}\n\n\tpublic void setActionContext(ActionContext actionContext) {\n\t\tthis.actionContext = actionContext;\n\t}\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/java/com/didi/arius/gateway/rest/tcp/OpenChannelsHandler.java",
    "content": "/*\n * Licensed to Elasticsearch under one or more contributor\n * license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright\n * ownership. Elasticsearch licenses this file to you under\n * the Apache License, Version 2.0 (the \"License\"); you may\n * not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\npackage com.didi.arius.gateway.rest.tcp;\n\nimport com.didiglobal.knowframework.log.ILog;\nimport org.elasticsearch.common.metrics.CounterMetric;\nimport org.elasticsearch.common.util.concurrent.ConcurrentCollections;\nimport org.jboss.netty.channel.*;\n\nimport java.util.Set;\n\n/**\n *\n */\n@ChannelHandler.Sharable\npublic class OpenChannelsHandler implements ChannelUpstreamHandler {\n\n    final Set<Channel> openChannels = ConcurrentCollections.newConcurrentSet();\n    final CounterMetric openChannelsMetric = new CounterMetric();\n    final CounterMetric totalChannelsMetric = new CounterMetric();\n\n    final ILog logger;\n\n    public OpenChannelsHandler(ILog logger) {\n        this.logger = logger;\n    }\n\n    final ChannelFutureListener remover = new ChannelFutureListener() {\n        @Override\n        public void operationComplete(ChannelFuture future) throws Exception {\n            boolean removed = openChannels.remove(future.getChannel());\n            if (removed) {\n                openChannelsMetric.dec();\n            }\n            if (logger.isTraceEnabled()) {\n                logger.trace(\"channel closed: {}\", future.getChannel());\n            }\n        }\n    };\n\n    @Override\n    public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {\n        if (e instanceof ChannelStateEvent) {\n            ChannelStateEvent evt = (ChannelStateEvent) e;\n            // OPEN is also sent to when closing channel, but with FALSE on it to indicate it closes\n            if (evt.getState() == ChannelState.OPEN && Boolean.TRUE.equals(evt.getValue())) {\n                if (logger.isTraceEnabled()) {\n                    logger.trace(\"channel opened: {}\", ctx.getChannel());\n                }\n                boolean added = openChannels.add(ctx.getChannel());\n                if (added) {\n                    openChannelsMetric.inc();\n                    totalChannelsMetric.inc();\n                    ctx.getChannel().getCloseFuture().addListener(remover);\n                }\n            }\n        }\n        ctx.sendUpstream(e);\n    }\n\n    public long numberOfOpenChannels() {\n        return openChannelsMetric.count();\n    }\n\n    public long totalChannels() {\n        return totalChannelsMetric.count();\n    }\n\n    public void close() {\n        for (Channel channel : openChannels) {\n            channel.close().awaitUninterruptibly();\n        }\n    }\n}\n\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/resources/application-dev.properties",
    "content": "# gateway 集群（一般和elasticsearch.admin.cluster.name配置一致）\ngateway.cluster.name=logi-elasticsearch-7.6.0\n# es 默认集群、kibana 元数据库保存集群（kibana 版本和该 es 版本一致）\nelasticsearch.admin.cluster.name=logi-elasticsearch-7.6.0\n# arius-admin 服务地址\narius.gateway.adminUrl=http://localhost:8010/admin/api\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/resources/application-online.properties",
    "content": "# gateway 集群（一般和elasticsearch.admin.cluster.name配置一致）\ngateway.cluster.name=dc-es02\n# es 默认集群、kibana 元数据库保存集群（kibana 版本和该 es 版本一致）\nelasticsearch.admin.cluster.name=dc-es02\n# arius-admin 服务地址\narius.gateway.adminUrl=http://localhost:8010/admin/api"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/resources/application-pre.properties",
    "content": "# gateway 集群（一般和elasticsearch.admin.cluster.name配置一致）\ngateway.cluster.name=dc-es02\n# es 默认集群、kibana 元数据库保存集群（kibana 版本和该 es 版本一致）\nelasticsearch.admin.cluster.name=dc-es02\n# arius-admin 服务地址\narius.gateway.adminUrl=http://10.85.129.96:20158/admin/api\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/resources/application-test.properties",
    "content": "# gateway 集群（一般和elasticsearch.admin.cluster.name配置一致）\ngateway.cluster.name=logi-elasticsearch-7.6.0\n# es 默认集群、kibana 元数据库保存集群（kibana 版本和该 es 版本一致）\nelasticsearch.admin.cluster.name=logi-elasticsearch-7.6.0\n# arius-admin 服务地址\narius.gateway.adminUrl=http://localhost:8010/admin/api\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/resources/application.properties",
    "content": "spring.profiles.active=dev\n\ngateway.queryConfig.dataCenterPath=\n\ngateway.queryConfig.kibanaSearchUri=/.kibana7_arius/_search\n\ngateway.queryConfig.esSocketTimeout=60000\n\ngateway.log.index.name=cn_record.arius.template.value\n\n# 暂未使用\ngateway.queryConfig.runMode=read\n\n#elasticsearch.admin.cluster.name=dc-es02\n\n# appid信息、dslTemplate信息、esCluster信息刷新任务调度周期\narius.gateway.adminSchedulePeriod=60\n\n# appid粒度限流刷新周期\narius.gateway.flowSchedulePeriod=10\n# dsl查询粒度默认限流值\ngateway.queryConfig.dslQPSLimit=100\n\n# 暂未使用\narius.gateway.indexAliasSchedulePeriod=600\n\n# dsl查询语句最大长度\ngateway.queryConfig.dslMaxLength=20971520\n\n# gateway server tcp port\ngateway.nettyTransport.port=8300\n# netty boss cnt\ngateway.nettyTransport.bossThreadCount=2\n# netty worker cnt\ngateway.nettyTransport.workerCount=10\n# netty 是否禁用 nagle\ngateway.nettyTransport.tcpNoDelay=true\n# netty 心跳检测\ngateway.nettyTransport.keepAlive=true\n\n# gateway server http port\ngateway.httpTransport.port=8200\n\n# es search slow 阈值\ngateway.queryConfig.searchSlowlogThresholdMills=1000\n# es request slow 阈值\ngateway.queryConfig.requestSlowlogThresholdMills=1000\n\n# gateway http 请求并发数\ngateway.queryConfig.tcpQueryLimit=5000\n# gateway tcp 请求并发数\ngateway.queryConfig.httpQueryLimit=5000\n\n# bucket的最大数量\ngateway.queryConfig.maxAggsBuckets=1000000\n# bucket的最大使用的内存数量\ngateway.queryConfig.maxAggsMemUsed=524288000\n# 是否开启maxAggsBuckets和maxAggsMemUsed校验\ngateway.queryConfig.checkForbidden=false\n\n# esClient 刷新时设置 es 的配置信息 transport.tcp.connect_timeout\ngateway.queryConfig.connectESTime=2s\n# esClient 刷新时设置 es 的配置信息 transport.netty.worker_count\ngateway.queryConfig.clientWorkerCount=8\n# esClient 刷新时设置 es 的配置信息\ngateway.queryConfig.fetchTimeout=5000\n\n# http response 最大值\ngateway.queryConfig.maxHttpResponseLength=314572800\n# 当前尚未响应的response body length总和最大值\ngateway.queryConfig.maxByteIn=2147483648\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/resources/ehcache.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ehcache>\n\t<cache name=\"queryContextCache\"\n\t\tmaxElementsInMemory=\"5000\"\n\t\teternal=\"true\"\n\t\toverflowToDisk=\"false\"\n\t\ttimeToIdleSeconds=\"0\"\n\t\ttimeToLiveSeconds=\"600\"\n\t\tmemoryStoreEvictionPolicy=\"LRU\" />\t\n\t\t\n\t<cache name=\"actionContextCache\"\n\t\tmaxElementsInMemory=\"5000\"\n\t\teternal=\"true\"\n\t\toverflowToDisk=\"false\"\n\t\ttimeToIdleSeconds=\"0\"\n\t\ttimeToLiveSeconds=\"600\"\n\t\tmemoryStoreEvictionPolicy=\"LRU\" />\t\t\t\n\t\t\n\t<cache name=\"dslTemplateCache\"\n\t\tmaxElementsInMemory=\"1000000\"\n\t\teternal=\"true\"\n\t\toverflowToDisk=\"false\"\n\t\tmemoryStoreEvictionPolicy=\"LRU\" />\n\t\t\n\t<cache name=\"newDslTemplateCache\"\n\t\tmaxElementsInMemory=\"1000\"\n\t\teternal=\"false\"\n\t\toverflowToDisk=\"false\"\n\t\ttimeToIdleSeconds=\"0\"\n\t\ttimeToLiveSeconds=\"3600\"\n\t\tmemoryStoreEvictionPolicy=\"LRU\" />\t\t\n\t\t\n</ehcache>"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/resources/log4j2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Configuration package=\"org.apache.logging.log4j.core,com.didiglobal.knowframework.log.log4j2.appender\"\n               status=\"error\" monitorInterval=\"60\">\n    <!--变量配置-->\n    <Properties>\n        <property name=\"gateway.queryConfig.logPath\" value=\".\" />\n        <Property name=\"address\" value=\"10.96.75.19\"/>\n        <Property name=\"port\" value=\"18938\"/>\n        <Property name=\"user\" value=\"\"/>\n        <Property name=\"password\" value=\"\"/>\n        <Property name=\"indexName\" value=\"index_observability\"/>\n        <Property name=\"typeName\" value=\"_doc\"/>\n    </Properties>\n\n\n    <Appenders>\n\n        <console name=\"console\" target=\"SYSTEM_OUT\">\n            <!--输出日志的格式-->\n            <PatternLayout pattern=\"[%-5level][%d{YYYY-MM-dd HH:mm:ss.SSS+0800}][%F:%line] %msg%n\"/>\n            <!--控制台只输出level及其以上级别的信息（onMatch），其他的直接拒绝（onMismatch）-->\n            <ThresholdFilter level=\"info\" onMatch=\"ACCEPT\" onMismatch=\"DENY\"/>\n        </console>\n\n        <ElasticsearchAppender name=\"esAppender\" address=\"${address}\" port=\"${port}\" user=\"${user}\"\n                               password=\"${password}\" indexName=\"${indexName}\" typeName=\"${typeName}\" threshold=\"all\"\n                               bufferSize=\"10000\" numberOfShards=\"5\" numberOfReplicas=\"0\" logExpire=\"3\"\n                               extendsMappingClass=\"\" requestTimeoutMillis=\"3000\" discardWhenBufferIsFull=\"true\">\n            <Filters>\n                <!--配置日志表达式，-->\n                <!-- 开启所有日志-->\n                <!--                <RegexFilter regex='.*\"logEventType\":\"(LOG|METRIC|TRACE)\".*' onMatch=\"ACCEPT\" onMismatch=\"DENY\"/>-->\n                <!-- 仅开启LOG和METRIC-->\n                <!-- <RegexFilter regex='.*\"logEventType\":\"(LOG|METRIC)\".*' onMatch=\"ACCEPT\" onMismatch=\"DENY\"/> -->\n                <!-- 开启LOG和METRIC，TRACE日志仅当traceId不为空时打印-->\n                <!--            <RegexFilter regex='.*\"logEventType\":\"(LOG|METRIC)\".*' onMatch=\"ACCEPT\" onMismatch=\"NEUTRAL\"/>-->\n                <!--            <RegexFilter regex='.*\"logEventType\":\"TRACE\".*' onMatch=\"NEUTRAL\" onMismatch=\"DENY\"/>-->\n                <!--            <RegexFilter regex='.*\"traceId\":\"[a-z0-9]+\".*' onMatch=\"NEUTRAL\" onMismatch=\"DENY\"/>-->\n            </Filters>\n        </ElasticsearchAppender>\n\n        <RollingFile name=\"file\" fileName=\"${gateway.queryConfig.logPath}/log/gateway.log\" filePattern=\"${gateway.queryConfig.logPath}/log/gateway.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <PatternLayout pattern=\"[%p][%d][%-4r][%t][%F:%L] %m%n\" />\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\" />\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n        <RollingFile name=\"bootLog\" fileName=\"${gateway.queryConfig.logPath}/log/boot.log\" filePattern=\"${gateway.queryConfig.logPath}/log/boot.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <PatternLayout pattern=\"[%p][%d][%-4r][%t] %m%n\" />\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\" />\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n        <RollingFile name=\"queryStats\" fileName=\"${gateway.queryConfig.logPath}/log/stats.log\" filePattern=\"${gateway.queryConfig.logPath}/log/stats.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <PatternLayout pattern=\"[%p][%d][%-4r][%t] %m%n\" />\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\" />\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n        <RollingFile name=\"metrics\" fileName=\"${gateway.queryConfig.logPath}/log/metrics.log\" filePattern=\"${gateway.queryConfig.logPath}/log/metrics.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <PatternLayout pattern=\"[%p][%d][%-4r][%t][%F:%L] %m%n\" />\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\" />\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n\n        <RollingFile name=\"traceLog\" fileName=\"${gateway.queryConfig.logPath}/log/didi.log\" filePattern=\"${gateway.queryConfig.logPath}/log/didi.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <PatternLayout pattern=\"[%p]%d{[yyyy-MM-dd'T'HH:mm:ss.SSSZ]} %m%n\" />\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\" />\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n        <RollingFile name=\"auditLog\" fileName=\"${gateway.queryConfig.logPath}/log/audit.log\" filePattern=\"${gateway.queryConfig.logPath}/log/audit.log.%d{yyyy-MM-dd}\"\n                     append=\"true\">\n            <PatternLayout pattern=\"[%p][%d}][%-4r][%t][%F:%L] %m%n\" />\n            <Policies>\n                <TimeBasedTriggeringPolicy modulate=\"true\"\n                                           interval=\"1\" />\n            </Policies>\n            <DefaultRolloverStrategy max=\"7\"/>\n        </RollingFile>\n\n        <RollingFile name=\"thirdReq\" fileName=\"${gateway.queryConfig.logPath}/log/thirdReq.log\"\n                     filePattern=\"${gateway.queryConfig.logPath}/log/thirdReq-%i.log\" append=\"false\">\n            <PatternLayout pattern=\"%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level - %msg%n\"/>\n            <SizeBasedTriggeringPolicy size=\"100MB\"/>\n            <DefaultRolloverStrategy max=\"2\"/>\n        </RollingFile>\n\n        <RollingFile name=\"gatherInfoLogger\" fileName=\"${gateway.queryConfig.logPath}/log/gather.log\"\n                     filePattern=\"${gateway.queryConfig.logPath}/log/gather.log.%i\" append=\"true\">\n            <PatternLayout pattern=\"%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %L - %msg%xEx%n\"/>\n            <SizeBasedTriggeringPolicy size=\"10MB\"/>\n            <DefaultRolloverStrategy max=\"9\"/>\n        </RollingFile>\n        <RollingFile name=\"gatherWarnLogger\" fileName=\"${gateway.queryConfig.logPath}/log/gather.log\"\n                     filePattern=\"${gateway.queryConfig.logPath}/log/gather.log.%i\" append=\"true\">\n            <PatternLayout pattern=\"%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %L - %msg%xEx%n\"/>\n            <SizeBasedTriggeringPolicy size=\"10MB\"/>\n            <DefaultRolloverStrategy max=\"9\"/>\n        </RollingFile>\n        <RollingFile name=\"gatherErrorLogger\" fileName=\"${gateway.queryConfig.logPath}/log/gather.log\"\n                     filePattern=\"${gateway.queryConfig.logPath}/log/gather.log.%i\" append=\"true\">\n            <PatternLayout pattern=\"%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %L - %msg%xEx%n\"/>\n            <SizeBasedTriggeringPolicy size=\"10MB\"/>\n            <DefaultRolloverStrategy max=\"9\"/>\n        </RollingFile>\n\n    </Appenders>\n    <Loggers>\n        <Root level=\"info\">\n<!--            <AppenderRef ref=\"console\" />-->\n            <AppenderRef ref=\"file\" />\n            <appender-ref ref=\"esAppender\" />\n        </Root>\n        <AsyncLogger level=\"info\" name=\"bootLog\" additivity=\"false\">\n            <AppenderRef ref=\"bootLog\"/>\n        </AsyncLogger>\n        <AsyncLogger level=\"info\" name=\"queryStats\" additivity=\"false\">\n            <AppenderRef ref=\"queryStats\"/>\n        </AsyncLogger>\n        <AsyncLogger level=\"info\" name=\"metrics\" additivity=\"false\">\n            <AppenderRef ref=\"metrics\"/>\n        </AsyncLogger>\n    </Loggers>\n</Configuration>"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/resources/metrics.properties",
    "content": "arius.sink.logger.class=com.didi.arius.gateway.common.metrics.LoggerMetric\n*.period=60\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/main/resources/observability.properties",
    "content": "application.name=arius-gateway\nmetric.export.interval.ms=60000\nobservability.initializer.classes=com.didiglobal.knowframework.log.log4j2.appender.ElasticsearchAppenderMetricsInitializer\n# ???????exporter?LoggingMetricExporter,LoggingSpanExporter\nobservability.exporter.names=LoggingMetricExporter,LoggingSpanExporter\npointcut=execution(* com.didiglobal..*.*(..)) || execution(* com.didichuxing..*.*(..)) || execution(* com.didi..*.*(..))"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/ESRestClientServiceTests.java",
    "content": "package com.didi.arius.gateway.core;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.consts.RestConsts;\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.rest.AriusGatewayApplication;\nimport com.google.common.collect.Maps;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = AriusGatewayApplication.class)\npublic class ESRestClientServiceTests {\n\n    private static String CLUSTER = \"dc-es02\";\n\n    @Autowired\n    private ESRestClientService esRestClientService;\n\n    @Before\n    public void setUp() {\n    }\n\n    @Test\n    public void testGetClient(){\n        ESClient client = esRestClientService.getClient(CLUSTER, RestConsts.NULL_ACTION);\n        System.out.println(JSON.toJSONString(client));\n        assertEquals(true, client != null);\n\n    }\n\n    @Test\n    public void testGetClientStrict(){\n        ESClient client = esRestClientService.getClientStrict(CLUSTER, RestConsts.NULL_ACTION);\n        System.out.println(JSON.toJSONString(client));\n        assertEquals(true, client != null);\n\n    }\n\n    @Test\n    public void testGetAdminClient(){\n        ESClient client = esRestClientService.getAdminClient(RestConsts.NULL_ACTION);\n        System.out.println(JSON.toJSONString(client));\n        assertEquals(true, client != null);\n\n    }\n\n    @Test\n    public void testGetESClusterMap(){\n        Map<String, ESCluster> esClusterMap = esRestClientService.getESClusterMap();\n        System.out.println(JSON.toJSONString(esClusterMap));\n        assertEquals(true, esClusterMap != null);\n\n    }\n\n    @Test\n    public void testResetClients(){\n        ESClient esClient = new ESClient(\"dc-es02\", \"7.6.1.302\");\n        ESCluster esCluster = new ESCluster();\n        esCluster.setCluster(\"dc-es02\");\n        esCluster.setReadAddress(\"10.168.56.135:8060\");\n        esCluster.setHttpAddress(\"10.168.56.135:8060,10.169.182.134:8060\");\n        esCluster.setHttpWriteAddress(\"\");\n        esCluster.setClient(null);\n        esCluster.setEsClient(esClient);\n        esCluster.setType(ESCluster.Type.INDEX);\n        esCluster.setDataCenter(\"cn\");\n        esCluster.setEsVersion(\"7.6.1.302\");\n        esCluster.setPassword(\"password\");\n        Map<String, ESCluster> map = Maps.newHashMap();\n        map.put(\"dc-es02\", esCluster);\n        esRestClientService.resetClients(map);\n\n\n    }\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/ESTcpClientServiceTests.java",
    "content": "package com.didi.arius.gateway.core;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.core.service.ESTcpClientService;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.rest.AriusGatewayApplication;\nimport com.google.common.collect.Maps;\nimport org.elasticsearch.client.Client;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = AriusGatewayApplication.class)\npublic class ESTcpClientServiceTests {\n\n    private static String CLUSTER = \"dc-es02\";\n\n    @Autowired\n    private ESTcpClientService esTcpClientService;\n\n    @Before\n    public void setUp() {\n    }\n\n    @Test\n    public void testGetClient() throws InterruptedException {\n        //这里发现获取的datacentermap 为空\n        Client client = esTcpClientService.getClient(CLUSTER);\n        System.out.println(JSON.toJSONString(client));\n        assertEquals(client != null, true);\n\n    }\n\n    @Test\n    public void testGetAdminClient(){\n        Client client = esTcpClientService.getAdminClient();\n        System.out.println(JSON.toJSONString(client));\n        assertEquals(true, client != null);\n\n    }\n\n    @Test\n    public void testGetESClusterMap(){\n        Map<String, ESCluster> esClusterMap = esTcpClientService.getDataCenterMap();\n        System.out.println(JSON.toJSONString(esClusterMap));\n        assertEquals(true, esClusterMap != null);\n\n    }\n\n    @Test\n    public void testResetClients(){\n        ESClient esClient = new ESClient(\"dc-es01\", \"7.6.1.302\");\n        ESCluster esCluster = new ESCluster();\n        esCluster.setCluster(\"dc-es01\");\n        esCluster.setReadAddress(\"10.168.56.135:8060\");\n        esCluster.setHttpAddress(\"10.168.56.135:8060,10.169.182.134:8060\");\n        esCluster.setHttpWriteAddress(\"\");\n        esCluster.setClient(null);\n        esCluster.setEsClient(esClient);\n        esCluster.setType(ESCluster.Type.INDEX);\n        esCluster.setDataCenter(\"cn\");\n        esCluster.setEsVersion(\"7.6.1.302\");\n        esCluster.setPassword(\"password\");\n        Map<String, ESCluster> map = Maps.newHashMap();\n        map.put(\"dc-es01\", esCluster);\n        esTcpClientService.resetClients(map);\n\n\n    }\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/MetricsServiceTests.java",
    "content": "package com.didi.arius.gateway.core;\n\nimport com.didi.arius.gateway.core.service.MetricsService;\nimport com.didi.arius.gateway.rest.AriusGatewayApplication;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = AriusGatewayApplication.class)\npublic class MetricsServiceTests {\n\n    private static String INDEX_NAME = \"cn_record.arius.template.value_2021-05\";\n\n    @Autowired\n    private MetricsService metricsService;\n\n    @Before\n    public void setUp() {\n    }\n\n    @Test\n    public void testAddQueryCost() {\n        metricsService.addQueryCost(5, 1);\n    }\n\n    @Test\n    public void testAddSlowlogCost() {\n        metricsService.addSlowlogCost(5, 1);\n    }\n\n    @Test\n    public void testAddSearchResponseMetrics() {\n        metricsService.addSearchResponseMetrics(5, 10, 2, 2, 1);\n    }\n\n    @Test\n    public void testAddQueryMetrics() {\n        metricsService.addQueryMetrics(5, 10, 20, 20);\n    }\n\n    @Test\n    public void testAddIndexMetrics() {\n        metricsService.addIndexMetrics(INDEX_NAME, \"root\", 10, 20, 20);\n    }\n\n    @Test\n    public void testIncrQueryAggs() {\n        metricsService.incrQueryAggs(5);\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/RateLimitServiceTests.java",
    "content": "package com.didi.arius.gateway.core;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.flowcontrol.FlowController;\nimport com.didi.arius.gateway.common.metadata.FlowThreshold;\nimport com.didi.arius.gateway.core.service.RateLimitService;\nimport com.didi.arius.gateway.rest.AriusGatewayApplication;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = AriusGatewayApplication.class)\npublic class RateLimitServiceTests {\n\n\n    @Autowired\n    private RateLimitService rateLimitService;\n\n    @Before\n    public void setUp() {\n    }\n\n    @Test\n    public void testAddByteIn() {\n        rateLimitService.addByteIn(50L);\n\n    }\n\n    @Test\n    public void testRemoveByteIn() {\n        rateLimitService.removeByteIn(50L);\n    }\n\n    @Test\n    public void testIsTrafficDataOverflow() {\n        final boolean all = rateLimitService.isTrafficDataOverflow(5, \"all\");\n        System.out.println(all);\n    }\n\n    @Test\n    public void testAddUp() {\n        rateLimitService.addUp(5, \"all\", 50, 45);\n    }\n\n    @Test\n    public void testResetAppAreaFlow() {\n        FlowThreshold flowThreshold = new FlowThreshold();\n        flowThreshold.setOpsUpper(1000);\n        flowThreshold.setOpsLower(100);\n        rateLimitService.resetAppAreaFlow(5, flowThreshold);\n    }\n\n    @Test\n    public void testGetFlowControllerMap() {\n        final Map<Integer, FlowController> flowControllerMap = rateLimitService.getFlowControllerMap();\n        System.out.println(JSON.toJSONString(flowControllerMap));\n    }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/RequestStatsServiceTests.java",
    "content": "package com.didi.arius.gateway.core;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.ActionContext;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.service.RequestStatsService;\nimport com.didi.arius.gateway.rest.AriusGatewayApplication;\nimport org.elasticsearch.rest.RestStatus;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.util.List;\n\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = AriusGatewayApplication.class)\npublic class RequestStatsServiceTests {\n\n\n    @Autowired\n    private RequestStatsService requestStatsService;\n\n    @Before\n    public void setUp() {\n    }\n\n    @Test\n    public void testDealRequest() {\n        requestStatsService.dealRequest();\n    }\n\n    @Test\n    public void testPutQueryContext() {\n        requestStatsService.putQueryContext(\"key1\", new QueryContext());\n    }\n\n    @Test\n    public void testGetQueryContext() {\n        requestStatsService.putQueryContext(\"key1\", new QueryContext());\n        final QueryContext key1 = requestStatsService.getQueryContext(\"key1\");\n        assertEquals(true, key1 != null);\n    }\n\n    @Test\n    public void testGetQueryKeys() {\n        final List<String> queryKeys = requestStatsService.getQueryKeys();\n        System.out.println(JSON.toJSONString(queryKeys));\n        assertEquals(true, queryKeys.size() >= 0);\n    }\n\n    @Test\n    public void testRemoveQueryContext() {\n        requestStatsService.putQueryContext(\"key1\", new QueryContext());\n        final QueryContext key1 = requestStatsService.getQueryContext(\"key1\");\n        assertEquals(true, key1 != null);\n        requestStatsService.removeQueryContext(\"key1\");\n        assertEquals(true, requestStatsService.getQueryContext(\"key1\") == null);\n    }\n\n    @Test\n    public void testPutActionContext() {\n        requestStatsService.putActionContext(\"key1\", new ActionContext());\n    }\n\n    @Test\n    public void testGetActionContext() {\n        requestStatsService.putActionContext(\"key1\", new ActionContext());\n        final ActionContext key1 = requestStatsService.getActionContext(\"key1\");\n        assertEquals(true, key1 != null);\n    }\n\n\n    @Test\n    public void testRemoveActionContext() {\n        requestStatsService.putActionContext(\"key1\", new ActionContext());\n        final ActionContext key1 = requestStatsService.getActionContext(\"key1\");\n        assertEquals(true, key1 != null);\n        requestStatsService.removeActionContext(\"key1\");\n        assertEquals(true, requestStatsService.getActionContext(\"key1\") == null);\n    }\n\n    @Test\n    public void testGetActionKeys() {\n        final List<String> queryKeys = requestStatsService.getActionKeys();\n        System.out.println(JSON.toJSONString(queryKeys));\n        assertEquals(true, queryKeys.size() >= 0);\n    }\n\n    @Test\n    public void testStatsAdd() {\n        requestStatsService.statsAdd(\"common\", 5, \"all\", 10L, RestStatus.OK);\n    }\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/dsl/DslAggsAnalyzerServiceTests.java",
    "content": "package com.didi.arius.gateway.core.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.common.metadata.*;\nimport com.didi.arius.gateway.core.service.dsl.DslAggsAnalyzerService;\nimport com.didi.arius.gateway.rest.AriusGatewayApplication;\nimport com.google.common.collect.Maps;\nimport com.google.gson.JsonElement;\nimport com.google.gson.JsonObject;\nimport com.google.gson.JsonParser;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.common.xcontent.XContentHelper;\nimport org.elasticsearch.rest.RestRequest;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = AriusGatewayApplication.class)\npublic class DslAggsAnalyzerServiceTests {\n\n    private static String CLUSTER = \"dc-es02\";\n    private static String INDEX_NAME = \"cn_record.arius.template.value_2021-05\";\n\n\n    @Autowired\n    private DslAggsAnalyzerService dslAggsAnalyzerService;\n\n    @Before\n    public void setUp() {\n    }\n\n    @Test\n    public void testAnalyze() {\n        String s = \"{\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[{\\\"term\\\":{\\\"name\\\":\\\"fitz4\\\"}},{\\\"term\\\":{\\\"age\\\":4}}]}}}\";\n        BytesReference bytesReference = new BytesArray(s);\n        final boolean analyze = dslAggsAnalyzerService.analyze(buildQueryContext(), bytesReference, new String[]{INDEX_NAME}, CLUSTER);\n        System.out.println(analyze);\n    }\n\n    @Test\n    public void testAnalyzeAggs() {\n        String s = \"{\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[{\\\"term\\\":{\\\"name\\\":\\\"fitz4\\\"}},{\\\"term\\\":{\\\"age\\\":4}}]}}}\";\n        BytesReference bytesReference = new BytesArray(s);\n        final boolean analyze = dslAggsAnalyzerService.analyzeAggs(buildQueryContext(), bytesReference, new String[]{INDEX_NAME});\n        System.out.println(analyze);\n    }\n\n    @Test\n    public void testCheckAggs() throws IOException {\n        String s = \"{\\\"size\\\":0,\\\"aggs\\\":{\\\"group_by_age\\\":{\\\"terms\\\":{\\\"field\\\":\\\"age\\\",\\\"order\\\":{\\\"_count\\\":\\\"asc\\\"}}}}}\";\n        BytesReference bytesReference = new BytesArray(s);\n        String strSource = XContentHelper.convertToJson(bytesReference, false);\n        JsonParser parser = new JsonParser();\n        JsonObject jsonSource = parser.parse(strSource).getAsJsonObject();\n\n        JsonObject aggsObject = getAggsObject(jsonSource);\n        final AggsBukcetInfo aggsBukcetInfo = dslAggsAnalyzerService.checkAggs(aggsObject, 0, Maps.newHashMap(), new AggsAnalyzerContext());\n        System.out.println(JSON.toJSONString(aggsBukcetInfo));\n        //{\"bucketNumber\":0,\"bucketType\":\"BUCKET\",\"lastBucket\":true,\"lastBucketNumber\":0,\"memUsed\":0}\n        assertEquals(true, aggsBukcetInfo != null);\n    }\n\n    @Test\n    public void testMergeMappings() {\n        final Map<String, FieldInfo> stringFieldInfoMap = dslAggsAnalyzerService.mergeMappings(new String[]{INDEX_NAME}, CLUSTER);\n        System.out.println(JSON.toJSONString(stringFieldInfoMap));\n    }\n\n    private JsonObject getAggsObject(JsonObject parent) {\n        JsonElement aggs = parent.get(\"aggs\");\n        if (aggs == null) {\n            aggs = parent.get(\"aggregations\");\n        }\n\n        if (aggs == null) {\n            return null;\n        }\n\n        return aggs.getAsJsonObject();\n    }\n\n    private QueryContext buildQueryContext() {\n        QueryContext queryContext = new QueryContext();\n        AppDetail appDetail = new AppDetail();\n        appDetail.setCluster(CLUSTER);\n        queryContext.setAppDetail(appDetail);\n        RestRequest request = new RestRequest() {\n            @Override\n            public Method method() {\n                return null;\n            }\n\n            @Override\n            public String uri() {\n                return null;\n            }\n\n            @Override\n            public String rawPath() {\n                return \"/_gwadmin/appinfo\";\n            }\n\n            @Override\n            public boolean hasContent() {\n                return false;\n            }\n\n            @Override\n            public BytesReference content() {\n                return null;\n            }\n\n            @Override\n            public String header(String s) {\n                return null;\n            }\n\n            @Override\n            public Iterable<Map.Entry<String, String>> headers() {\n                return null;\n            }\n\n            @Override\n            public boolean hasParam(String s) {\n                return false;\n            }\n\n            @Override\n            public String param(String s) {\n                return null;\n            }\n\n            @Override\n            public Map<String, String> params() {\n                return null;\n            }\n\n            @Override\n            public String param(String s, String s1) {\n                return null;\n            }\n        };\n        queryContext.setRequest(request);\n        return queryContext;\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/dsl/DslAuditServiceTests.java",
    "content": "package com.didi.arius.gateway.core.dsl;\n\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.service.dsl.DslAuditService;\nimport com.didi.arius.gateway.rest.AriusGatewayApplication;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.rest.RestRequest;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.util.Map;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = AriusGatewayApplication.class)\npublic class DslAuditServiceTests {\n\n    private static String CLUSTER = \"dc-es02\";\n    private static String INDEX_NAME = \"cn_record.arius.template.value_2021-05\";\n\n\n    @Autowired\n    private DslAuditService dslAuditService;\n\n    @Before\n    public void setUp() {\n    }\n\n    @Test\n    public void testAuditDSL() {\n        String s = \"{\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[{\\\"term\\\":{\\\"name\\\":\\\"fitz4\\\"}},{\\\"term\\\":{\\\"age\\\":4}}]}}}\";\n        BytesReference bytesReference = new BytesArray(s);\n        String auditDSL = dslAuditService.auditDSL(buildQueryContext(), bytesReference, new String[]{INDEX_NAME});\n        System.out.println(auditDSL);\n        //V2_60AEA6D86F11C54F7ED8E5FA07BDB4E1\n    }\n\n    @Test\n    public void testAuditSQL() {\n        String sql = String.format(\"SELECT * from %s limit 1\", INDEX_NAME);\n        final String s = dslAuditService.auditSQL(buildQueryContext(), sql, new String[]{INDEX_NAME});\n        System.out.println(s);\n        //V2_F6586E887287C2426F4DDF9C245820AC\n    }\n\n    private QueryContext buildQueryContext() {\n        QueryContext queryContext = new QueryContext();\n        AppDetail appDetail = new AppDetail();\n        appDetail.setCluster(CLUSTER);\n        queryContext.setAppDetail(appDetail);\n        RestRequest request = new RestRequest() {\n            @Override\n            public Method method() {\n                return null;\n            }\n\n            @Override\n            public String uri() {\n                return null;\n            }\n\n            @Override\n            public String rawPath() {\n                return \"/_gwadmin/appinfo\";\n            }\n\n            @Override\n            public boolean hasContent() {\n                return false;\n            }\n\n            @Override\n            public BytesReference content() {\n                return null;\n            }\n\n            @Override\n            public String header(String s) {\n                return null;\n            }\n\n            @Override\n            public Iterable<Map.Entry<String, String>> headers() {\n                return null;\n            }\n\n            @Override\n            public boolean hasParam(String s) {\n                return false;\n            }\n\n            @Override\n            public String param(String s) {\n                return null;\n            }\n\n            @Override\n            public Map<String, String> params() {\n                return null;\n            }\n\n            @Override\n            public String param(String s, String s1) {\n                return null;\n            }\n        };\n        queryContext.setRequest(request);\n        return queryContext;\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/dsl/DslRewriterServiceTests.java",
    "content": "package com.didi.arius.gateway.core.dsl;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.service.dsl.DslRewriterService;\nimport com.didi.arius.gateway.rest.AriusGatewayApplication;\nimport org.elasticsearch.common.bytes.BytesArray;\nimport org.elasticsearch.common.bytes.BytesReference;\nimport org.elasticsearch.rest.RestRequest;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.util.Map;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = AriusGatewayApplication.class)\npublic class DslRewriterServiceTests {\n\n    private static String CLUSTER = \"dc-es02\";\n\n\n    @Autowired\n    private DslRewriterService dslRewriterService;\n\n    @Before\n    public void setUp() {\n    }\n\n    @Test\n    public void testRewriteRequest() throws Exception {\n        String s = \"{\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[{\\\"term\\\":{\\\"name\\\":\\\"fitz4\\\"}},{\\\"term\\\":{\\\"age\\\":4}}]}}}\";\n        JSONObject source = JSON.parseObject(s);\n        final BytesReference bytesReference = dslRewriterService.rewriteRequest(buildQueryContext(), \"6\", source);\n        String dsl = new String(bytesReference.toBytes());\n        System.out.println(dsl);\n        //{\"query\":{\"bool\":{\"must\":[{\"term\":{\"name\":\"fitz4\"}},{\"term\":{\"age\":4}}]}}}\n    }\n\n    @Test\n    public void testDoTypedKey() {\n        String s = \"{\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[{\\\"term\\\":{\\\"name\\\":\\\"fitz4\\\"}},{\\\"term\\\":{\\\"age\\\":4}}]}}}\";\n        JSONObject source = JSON.parseObject(s);\n        dslRewriterService.doTypedKey(buildQueryContext(), source);\n    }\n\n    @Test\n    public void testRewriteRequest2() throws Exception {\n        String s = \"{\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[{\\\"term\\\":{\\\"name\\\":\\\"fitz4\\\"}},{\\\"term\\\":{\\\"age\\\":4}}]}}}\";\n        BytesReference bytesReference = new BytesArray(s);\n        final BytesReference res = dslRewriterService.rewriteRequest(buildQueryContext(), \"6\", bytesReference);\n        String dsl = new String(res.toBytes());\n        System.out.println(dsl);\n        //{\"query\":{\"bool\":{\"must\":[{\"term\":{\"name\":\"fitz4\"}},{\"term\":{\"age\":4}}]}}}\n    }\n\n\n    private QueryContext buildQueryContext() {\n        QueryContext queryContext = new QueryContext();\n        AppDetail appDetail = new AppDetail();\n        appDetail.setCluster(CLUSTER);\n        queryContext.setAppDetail(appDetail);\n        RestRequest request = new RestRequest() {\n            @Override\n            public Method method() {\n                return null;\n            }\n\n            @Override\n            public String uri() {\n                return null;\n            }\n\n            @Override\n            public String rawPath() {\n                return \"/_gwadmin/appinfo\";\n            }\n\n            @Override\n            public boolean hasContent() {\n                return false;\n            }\n\n            @Override\n            public BytesReference content() {\n                return null;\n            }\n\n            @Override\n            public String header(String s) {\n                return null;\n            }\n\n            @Override\n            public Iterable<Map.Entry<String, String>> headers() {\n                return null;\n            }\n\n            @Override\n            public boolean hasParam(String s) {\n                return false;\n            }\n\n            @Override\n            public String param(String s) {\n                return null;\n            }\n\n            @Override\n            public Map<String, String> params() {\n                return null;\n            }\n\n            @Override\n            public String param(String s, String s1) {\n                return null;\n            }\n        };\n        queryContext.setRequest(request);\n        return queryContext;\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/service/arius/AppServiceTest.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.RateLimitService;\nimport com.didi.arius.gateway.core.service.arius.impl.AppServiceImpl;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.AppListResponse;\nimport com.didi.arius.gateway.util.CustomDataSource;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.mockito.ArgumentMatchers.anyList;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\n/**\n * @author wuxuan\n * @Date 2022/6/23\n */\npublic class AppServiceTest {\n    @Mock\n    private AriusAdminRemoteService ariusAdminRemoteService;\n\n    @Mock\n    private IndexTemplateService indexTemplateService;\n\n    @Mock\n    private RateLimitService rateLimitService;\n\n    @Mock\n    private ThreadPool threadPool;\n\n    @InjectMocks\n    private AppServiceImpl appService;\n\n    @Before\n    public void setUp() {\n        initMocks(this);\n        appService.init();\n        AppListResponse appListResponse = CustomDataSource.appListResponseFactory();\n        when(ariusAdminRemoteService.listApp()).thenReturn(appListResponse);\n        when(indexTemplateService.checkIndex(anyString(),anyList())).thenReturn(true);\n    }\n\n    @Test\n    public void testGetAppDetail() {\n        appService.getAppDetail(CustomDataSource.appid);\n    }\n\n    @Test\n    public void testGetAppDetails() {\n        appService.getAppDetails();\n    }\n\n    @Test\n    public void testGetAppDetailFromIp() {\n        appService.resetAppInfo();\n        appService.getAppDetailFromIp(CustomDataSource.ip);\n    }\n\n    @Test\n    public void testResetAppInfo() {\n        appService.resetAppInfo();\n    }\n\n    @Test\n    public void testCheckToken() {\n        appService.resetAppInfo();\n        appService.checkToken(CustomDataSource.baseContextFactory());\n    }\n\n    @Test\n    public void testCheckWriteIndices() {\n        List<String> indices = new ArrayList<>();\n        indices.add(CustomDataSource.INDEX_NAME);\n        indices.add(CustomDataSource.INDEX_NAME2);\n        appService.checkWriteIndices(CustomDataSource.baseContextFactory(),indices);\n    }\n\n    @Test\n    public void testCheckIndices() {\n        List<String> indices = new ArrayList<>();\n        indices.add(CustomDataSource.INDEX_NAME);\n        indices.add(CustomDataSource.INDEX_NAME2);\n        appService.checkIndices(CustomDataSource.baseContextFactory(),indices);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/service/arius/DslTemplateServiceTest.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\nimport com.didi.arius.gateway.common.metadata.DSLTemplate;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.arius.impl.DslTemplateServiceImpl;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.util.CustomDataSource;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\n\nimport java.util.List;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\n/**\n * @author wuxuan\n * @Date 2022/6/14\n */\npublic class DslTemplateServiceTest {\n\n    @Mock\n    private ThreadPool threadPool;\n    @Mock\n    private AriusAdminRemoteService ariusAdminRemoteService;\n    @Mock\n    private QueryConfig queryConfig;\n\n    @InjectMocks\n    private DslTemplateServiceImpl dslTemplateService;\n\n    private  DSLTemplate dslTemplate = new DSLTemplate(1, 1, true);\n    @Before\n    public void setUp() {\n        initMocks(this);\n        dslTemplateService.init();\n    }\n\n\n\n    @Test\n    public void testPutDSLTemplate(){\n        dslTemplateService.putDSLTemplate(\"key\", dslTemplate);\n    }\n\n    @Test\n    public void testRemoveDSLTemplate() {\n        dslTemplateService.putDSLTemplate(\"key\", dslTemplate);\n        DSLTemplate dslTemplate = dslTemplateService.getDSLTemplate(\"key\");\n        assertEquals(true, dslTemplate != null);\n        dslTemplateService.removeDSLTemplate(\"key\");\n        assertEquals(true, dslTemplateService.getDSLTemplate(\"key1\") == null);\n    }\n\n    @Test\n    public void testGetDSLTemplate() {\n        dslTemplateService.putDSLTemplate(\"key\", dslTemplate);\n        DSLTemplate dslTemplate = dslTemplateService.getDSLTemplate(\"key\");\n        assertEquals(true, dslTemplate != null);\n        dslTemplate = dslTemplateService.getDSLTemplate(null);\n        assertEquals(true, dslTemplate == null);\n    }\n\n    @Test\n    public void testGetDslTemplateKeys() {\n        dslTemplateService.putDSLTemplate(\"key\", dslTemplate);\n        List<String> dslTemplateKeys = dslTemplateService.getDslTemplateKeys();\n        assertEquals(true, dslTemplateKeys.size() >= 0);\n    }\n\n    @Test\n    public void testPutNewDSLTemplate(){\n        dslTemplateService.putNewDSLTemplate(\"key\", dslTemplate);\n    }\n\n    @Test\n    public void testGetNewDSLTemplate(){\n        dslTemplateService.putNewDSLTemplate(\"key\", dslTemplate);\n        DSLTemplate dslTemplate = dslTemplateService.getNewDSLTemplate(\"key\");\n        assertEquals(true, dslTemplate != null);\n        dslTemplate = dslTemplateService.getNewDSLTemplate(null);\n        assertEquals(true,dslTemplate==null);\n    }\n\n    @Test\n    public void testGetNewDslTemplateKeys(){\n        dslTemplateService.putNewDSLTemplate(\"key1\",dslTemplate);\n        List<String> newDslTemplateKeys = dslTemplateService.getNewDslTemplateKeys();\n        assertEquals(true, newDslTemplateKeys.size() >= 0);\n    }\n\n    @Test\n    public void testResetDslInfo(){\n        dslTemplateService.resetDslInfo();\n        dslTemplateService.putDSLTemplate(\"key\", dslTemplate);\n        when(ariusAdminRemoteService.listDslTemplates(0,null)).thenReturn(CustomDataSource.dslTemplateListResponseFactory());\n        dslTemplateService.resetDslInfo();\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/service/arius/DynamicConfigServiceTest.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.arius.impl.DynamicConfigServiceImpl;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.DynamicConfigListResponse;\nimport com.didi.arius.gateway.util.CustomDataSource;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\n\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\n/**\n * @author wuxuan\n * @Date 2022/6/14\n */\npublic class DynamicConfigServiceTest {\n\n    @Mock\n    private ThreadPool threadPool;\n    @Mock\n    private AriusAdminRemoteService ariusAdminRemoteService;\n    @InjectMocks\n    private DynamicConfigServiceImpl dynamicConfigService;\n\n    @Before\n    public void setUp() {\n        initMocks(this);\n        dynamicConfigService.init();\n    }\n\n    @Test\n    public void testGetDetailLogFlag(){\n        dynamicConfigService.getDetailLogFlag();\n    }\n\n    @Test\n    public void testIsWhiteAppid(){\n        dynamicConfigService.isWhiteAppid(100000000);\n    }\n\n    @Test\n    public void testGetForbiddenSettings(){\n        dynamicConfigService.getForbiddenSettings();\n    }\n\n    @Test\n    public void testResetDynamicConfigInfo(){\n        //设置不同参数遍历不同分支。\n        dynamicConfigService.resetDynamicConfigInfo();\n        DynamicConfigListResponse dynamicConfigListResponse = CustomDataSource.dynamicConfigListResponseFactory();\n        when(ariusAdminRemoteService.listQueryConfig()).thenReturn(dynamicConfigListResponse);\n        dynamicConfigService.resetDynamicConfigInfo();\n        dynamicConfigListResponse.setCode(1);\n        dynamicConfigService.resetDynamicConfigInfo();\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/service/arius/ESClusterServiceTest.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.core.service.ESTcpClientService;\nimport com.didi.arius.gateway.core.service.arius.impl.ESClusterServiceImpl;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.DataCenterListResponse;\nimport com.didi.arius.gateway.util.CustomDataSource;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\n\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\n/**\n * @author wuxuan\n * @Date 2022/6/14\n */\npublic class ESClusterServiceTest {\n\n    @Mock\n    private AriusAdminRemoteService ariusAdminRemoteService;\n    @Mock\n    private ThreadPool threadPool;\n    @Mock\n    private ESTcpClientService esTcpClientService;\n    @Mock\n    private ESRestClientService esRestClientService;\n    @Mock\n    private QueryConfig queryConfig;\n\n    @InjectMocks\n    private ESClusterServiceImpl esClusterService;\n\n    private QueryContext queryContext = new QueryContext();\n    private IndexTemplate indexTemplate = new IndexTemplate();\n    private ESClient client = new ESClient();\n    private ESClient esClient = new ESClient();\n\n    @Before\n    public void setUp() {\n        initMocks(this);\n        esClusterService.init();\n        client = new ESClient(\"clusterName\", \"version\");\n        queryContext = CustomDataSource.queryContextFactory();\n        indexTemplate = CustomDataSource.indexTemplateFactory();\n        DataCenterListResponse dataCenterListResponse = CustomDataSource.dataCenterListResponseFactory();\n        when(ariusAdminRemoteService.listCluster()).thenReturn(dataCenterListResponse);\n        when(esRestClientService.getClient(anyString(),anyString())).thenReturn(client);\n        when(esRestClientService.getAdminClient(anyString())).thenReturn(client);\n        when(esRestClientService.getClientStrict(anyString(),anyString())).thenReturn(client);\n    }\n\n    @Test\n    public void testGetMetaVersionByCluster(){\n        esClusterService.getMetaVersionByCluster(CustomDataSource.CLUSTER_NAME);\n    }\n    @Test\n    public void testGetDetailLogFlag(){\n        Map<String, ESCluster> stringESClusterMap = esClusterService.listESCluster();\n        assertEquals(true, stringESClusterMap != null);\n    }\n\n    @Test\n    public void testResetESClusaterInfo(){\n        esClusterService.resetESClusaterInfo();\n    }\n\n    @Test\n    public void testGetClient(){\n        esClient = esClusterService.getClient(queryContext, \"action\");\n        assertEquals(true, esClient != null);\n        queryContext.setFromKibana(true);\n        esClient = esClusterService.getClient(queryContext, \"action\");\n        assertEquals(true, esClient != null);\n    }\n\n    @Test\n    public void testGetClient2(){\n        esClient = esClusterService.getClient(queryContext, indexTemplate, \"action\");\n        assertEquals(true, esClient != null);\n        queryContext.setFromKibana(true);\n        esClient = esClusterService.getClient(queryContext, indexTemplate, \"action\");\n        assertEquals(true, esClient != null);\n    }\n\n    @Test\n    public void testGetClient3(){\n        queryContext.setClusterId(null);\n        esClient = esClusterService.getClient(queryContext, indexTemplate, \"action\");\n        assertEquals(true, esClient != null);\n    }\n\n    @Test\n    public void testGetClient4(){\n        queryContext.setClusterId(null);\n        indexTemplate.setSlaveInfos(null);\n        esClient = esClusterService.getClient(queryContext, indexTemplate, \"action\");\n        assertEquals(true, esClient != null);\n    }\n\n    @Test\n    public void testGetClientFromCluster(){\n        esClient = esClusterService.getClientFromCluster(queryContext, CustomDataSource.CLUSTER_NAME, \"action\");\n        assertEquals(true, esClient != null);\n    }\n\n    @Test\n    public void testGetWriteClient(){\n        esClient = esClusterService.getWriteClient(indexTemplate, \"action\");\n        assertEquals(true, esClient != null);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/service/arius/GateWayHeartBeatServiceTest.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.core.component.QueryConfig;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.arius.impl.GateWayHeartBeatServiceImpl;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.ActiveCountResponse;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\n\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\n/**\n * @author wuxuan\n * @Date 2022/6/14\n */\npublic class GateWayHeartBeatServiceTest {\n\n    @Mock\n    private QueryConfig queryConfig;\n    @Mock\n    private ThreadPool threadPool;\n    @Mock\n    private AriusAdminRemoteService ariusAdminRemoteService;\n    @InjectMocks\n    private GateWayHeartBeatServiceImpl gateWayHeartBeatService;\n\n    @Before\n    public void setUp() {\n        initMocks(this);\n        gateWayHeartBeatService.init();\n    }\n\n    @Test\n    public void testResetHeartBeatInfo(){\n        ActiveCountResponse response = new ActiveCountResponse();\n        response.setData(0);\n        when(ariusAdminRemoteService.getAliveCount(QueryConsts.GATEWAY_GROUP)).thenReturn(response);\n        gateWayHeartBeatService.resetHeartBeatInfo();\n    }\n\n    @Test\n    public void testResetHeartBeatInfo2(){\n        ActiveCountResponse response = new ActiveCountResponse();\n        response.setData(1);\n        when(ariusAdminRemoteService.getAliveCount(QueryConsts.GATEWAY_GROUP)).thenReturn(response);\n        gateWayHeartBeatService.resetHeartBeatInfo();\n    }\n\n    @Test\n    public void testResetHeartBeatInfo3(){\n        ActiveCountResponse response = new ActiveCountResponse();\n        response.setData(2);\n        when(ariusAdminRemoteService.getAliveCount(QueryConsts.GATEWAY_GROUP)).thenReturn(response);\n        gateWayHeartBeatService.resetHeartBeatInfo();\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/core/service/arius/IndexTemplateServiceTest.java",
    "content": "package com.didi.arius.gateway.core.service.arius;\n\nimport com.didi.arius.gateway.common.enums.TemplateBlockTypeEnum;\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.common.metadata.TemplateInfo;\nimport com.didi.arius.gateway.core.component.ThreadPool;\nimport com.didi.arius.gateway.core.service.ESRestClientService;\nimport com.didi.arius.gateway.core.service.arius.impl.IndexTemplateServiceImpl;\nimport com.didi.arius.gateway.remote.AriusAdminRemoteService;\nimport com.didi.arius.gateway.remote.response.IndexTemplateListResponse;\nimport com.didi.arius.gateway.util.CustomDataSource;\nimport com.google.common.collect.Lists;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.didi.arius.gateway.common.enums.TemplateBlockTypeEnum.READ_BLOCK_TYPE;\nimport static com.didi.arius.gateway.common.enums.TemplateBlockTypeEnum.WRITE_WRITE_TYPE;\nimport static org.junit.Assert.assertEquals;\nimport static org.mockito.ArgumentMatchers.*;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.MockitoAnnotations.initMocks;\n\n/**\n * @author wuxuan\n * @Date 2022/6/14\n */\npublic class IndexTemplateServiceTest {\n    @Mock\n    private ESClusterService esClusterService;\n    @Mock\n    private AriusAdminRemoteService ariusAdminRemoteService;\n    @Mock\n    private ESRestClientService esRestClientService;\n    @Mock\n    private ThreadPool threadPool;\n    @Mock\n    private AppService appService;\n    @InjectMocks\n    private IndexTemplateServiceImpl indexTemplateService;\n\n    private Map<String, String>         indexToAlias     = new HashMap<>();\n    private Map<String, Map<String, TemplateInfo>> templateAliasesMap \t = new HashMap<>();\n    private Map<String, Map<String, TemplateInfo>> templateExpressionMap = new HashMap<>();\n\n    @Before\n    public void setUp() {\n        initMocks(this);\n        indexTemplateService.init();\n        when(esClusterService.listESCluster()).thenReturn(CustomDataSource.listESClusterFactory());\n        when(ariusAdminRemoteService.listDeployInfo()).thenReturn(CustomDataSource.indexTemplateListResponseFactory());\n        when(esRestClientService.getESClusterMap()).thenReturn(CustomDataSource.listESClusterFactory());\n        when(ariusAdminRemoteService.getTemplateInfoMap(anyString())).thenReturn(CustomDataSource.templateInfoListResponseFactory());\n        when(ariusAdminRemoteService.addAdminTemplateAlias(any())).thenReturn(CustomDataSource.tempaletAliasResponseFactory());\n        when(ariusAdminRemoteService.delAdminTemplateAlias(any())).thenReturn(CustomDataSource.tempaletAliasResponseFactory());\n        ReflectionTestUtils.setField(indexTemplateService,\"indexTemplateMap\",CustomDataSource.indexTemplateMapFactory());\n    }\n\n    @Test\n    public void testGetTemplateExpressionMap() {\n        indexTemplateService.getTemplateExpressionMap();\n    }\n\n    @Test\n    public void testGetTemplateAliasMap() {\n        indexTemplateService.getTemplateAliasMap();\n    }\n\n    @Test\n    public void testGetIndexTemplate() {\n        indexTemplateService.getIndexTemplate(CustomDataSource.INDEX_NAME);\n    }\n\n    @Test\n    public void testGetIndexTemplateByTire() {\n        indexTemplateService.getIndexTemplateByTire(CustomDataSource.INDEX_NAME);\n        indexTemplateService.resetIndexTemplateInfo();\n        indexTemplateService.getIndexTemplateByTire(CustomDataSource.INDEX_NAME);\n    }\n\n    @Test\n    public void testGetIndexTemplateMap() {\n        indexTemplateService.getIndexTemplateMap();\n    }\n\n    @Test\n    public void testResetIndexTemplateInfo() {\n        indexTemplateService.resetIndexTemplateInfo();\n        indexTemplateService.resetIndexTemplateInfo();\n    }\n\n    @Test\n    public void testGetIndexAlias() {\n        indexTemplateService.getIndexAlias(CustomDataSource.INDEX_NAME);\n    }\n\n    @Test\n    public void testCheckIndex() {\n        boolean b = indexTemplateService.checkIndex(CustomDataSource.INDEX_NAME+\"_2021-05\", Lists.newArrayList(CustomDataSource.INDEX_NAME+\"*\"));\n        assertEquals(true, b);\n        b = indexTemplateService.checkIndex(\".\",Lists.newArrayList(CustomDataSource.INDEX_NAME+\"asdf*\"));\n        assertEquals(true,b);\n        boolean b1 = indexTemplateService.checkIndex(CustomDataSource.INDEX_NAME+\"_2021-05\", Lists.newArrayList(CustomDataSource.INDEX_NAME+\"asdf*\"));\n        assertEquals(false, b1);\n    }\n\n    @Test\n    public void testGetIndexVersion() {\n        indexTemplateService.getIndexVersion(null,CustomDataSource.CLUSTER_NAME);\n        indexTemplateService.getIndexVersion(CustomDataSource.INDEX_NAME,null);\n        indexTemplateService.getIndexVersion(CustomDataSource.INDEX_NAME, CustomDataSource.CLUSTER_NAME);\n        Map<String, TemplateInfo> templateInfoMap = new HashMap<>();\n        templateInfoMap.put(CustomDataSource.INDEX_NAME,CustomDataSource.templateInfoFactory());\n        templateExpressionMap.put(CustomDataSource.CLUSTER_NAME,templateInfoMap);\n        ReflectionTestUtils.setField(indexTemplateService,\"templateExpressionMap\",templateExpressionMap);\n        indexTemplateService.getIndexVersion(CustomDataSource.INDEX_NAME, CustomDataSource.CLUSTER_NAME);\n        indexTemplateService.getIndexVersion(CustomDataSource.INDEX_NAME2+\"*\",CustomDataSource.CLUSTER_NAME);\n        templateAliasesMap.put(CustomDataSource.CLUSTER_NAME,templateInfoMap);\n        ReflectionTestUtils.setField(indexTemplateService,\"templateAliasesMap\",templateAliasesMap);\n        indexTemplateService.getIndexVersion(CustomDataSource.INDEX_NAME, CustomDataSource.CLUSTER_NAME);\n    }\n\n    @Test\n    public void testGetIndexVersion2() {\n        Map<String, TemplateInfo> templateInfoMap = new HashMap<>();\n        templateInfoMap.put(CustomDataSource.INDEX_NAME,CustomDataSource.templateInfoFactory());\n        templateAliasesMap.put(CustomDataSource.INDEX_NAME,templateInfoMap);\n        templateExpressionMap.put(CustomDataSource.INDEX_NAME,templateInfoMap);\n        ReflectionTestUtils.setField(indexTemplateService,\"templateExpressionMap\",templateExpressionMap);\n        indexTemplateService.getIndexVersion(CustomDataSource.INDEX_NAME, CustomDataSource.CLUSTER_NAME);\n        ReflectionTestUtils.setField(indexTemplateService,\"templateAliasesMap\",templateAliasesMap);\n        indexTemplateService.getIndexVersion(CustomDataSource.INDEX_NAME, CustomDataSource.CLUSTER_NAME);\n    }\n\n    @Test\n    public void testGetIndexVersion3() {\n        Map<String, TemplateInfo> templateInfoMap = new HashMap<>();\n        templateInfoMap.put(CustomDataSource.INDEX_NAME+\"*\",CustomDataSource.templateInfoFactory());\n        templateExpressionMap.put(CustomDataSource.INDEX_NAME,templateInfoMap);\n        ReflectionTestUtils.setField(indexTemplateService,\"templateExpressionMap\",templateExpressionMap);\n        indexTemplateService.getIndexVersion(CustomDataSource.INDEX_NAME, CustomDataSource.CLUSTER_NAME);\n    }\n\n    @Test\n    public void testGetTemplateByIndexTire() {\n        List<String> indices = new ArrayList<>();\n        indices.add(CustomDataSource.INDEX_NAME);\n        indices.add(CustomDataSource.INDEX_NAME2);\n        indices.add(CustomDataSource.INDEX_NAME3);\n        indexTemplateService.resetIndexTemplateInfo();\n        indexToAlias.put(CustomDataSource.INDEX_NAME3,CustomDataSource.INDEX_NAME);\n        ReflectionTestUtils.setField(indexTemplateService,\"indexToAlias\",indexToAlias);\n        indexTemplateService.getTemplateByIndexTire(indices,CustomDataSource.queryContextFactory());\n        indices.clear();\n        indices.add(CustomDataSource.INDEX_NAME3);\n        indexTemplateService.getTemplateByIndexTire(indices,CustomDataSource.queryContextFactory());\n    }\n\n    @Test\n    public void testAddTemplateAlias() {\n        when(appService.getAppDetail(anyInt())).thenReturn(null);\n        indexTemplateService.addTemplateAlias(CustomDataSource.appid,1,CustomDataSource.INDEX_NAME,CustomDataSource.INDEX_NAME2);\n    }\n\n    @Test\n    public void testAddTemplateAlias2() {\n        when(appService.getAppDetail(anyInt())).thenReturn(CustomDataSource.appDetailFactory() );\n        indexTemplateService.addTemplateAlias(CustomDataSource.appid,1,CustomDataSource.INDEX_NAME,CustomDataSource.INDEX_NAME2);\n        indexTemplateService.resetIndexTemplateInfo();\n        indexTemplateService.addTemplateAlias(CustomDataSource.appid,1,CustomDataSource.INDEX_NAME,CustomDataSource.INDEX_NAME2);\n        indexTemplateService.addTemplateAlias(CustomDataSource.appid,1,CustomDataSource.INDEX_NAME3,CustomDataSource.INDEX_NAME2);\n    }\n\n    @Test\n    public void testDelTemplateAlias() {\n        when(appService.getAppDetail(anyInt())).thenReturn(null);\n        indexTemplateService.delTemplateAlias(CustomDataSource.appid,1,CustomDataSource.INDEX_NAME,CustomDataSource.INDEX_NAME2);\n    }\n\n    @Test\n    public void testDelTemplateAlias2() {\n        when(appService.getAppDetail(anyInt())).thenReturn(CustomDataSource.appDetailFactory() );\n        indexTemplateService.resetIndexTemplateInfo();\n        indexTemplateService.addTemplateAlias(CustomDataSource.appid,1,CustomDataSource.INDEX_NAME,CustomDataSource.INDEX_NAME2);\n        indexTemplateService.delTemplateAlias(CustomDataSource.appid,1,CustomDataSource.INDEX_NAME,CustomDataSource.INDEX_NAME2);\n        indexTemplateService.delTemplateAlias(CustomDataSource.appid,1,CustomDataSource.INDEX_NAME3,CustomDataSource.INDEX_NAME2);\n    }\n\n    @Test\n    public void testCheckTemplateExist() {\n        List<String> indices = new ArrayList<>();\n        indices.add(CustomDataSource.INDEX_NAME);\n        indices.add(CustomDataSource.INDEX_NAME3);\n        indices.add(\".index\");\n        when(appService.getAppDetail(anyInt())).thenReturn(CustomDataSource.appDetailFactory() );\n        indexTemplateService.resetIndexTemplateInfo();\n        indexToAlias.put(CustomDataSource.INDEX_NAME3,CustomDataSource.INDEX_NAME);\n        ReflectionTestUtils.setField(indexTemplateService,\"indexToAlias\",indexToAlias);\n        indexTemplateService.checkTemplateExist(indices);\n    }\n\n    @Test\n    public void testCheckTemplateBlock() {\n        List<String> indices = new ArrayList<>();\n        indices.add(CustomDataSource.INDEX_NAME);\n        indices.add(CustomDataSource.INDEX_NAME3);\n        indices.add(\".index\");\n        TemplateBlockTypeEnum templateBlockTypeEnum = READ_BLOCK_TYPE;\n        indexTemplateService.resetIndexTemplateInfo();\n        indexToAlias.put(CustomDataSource.INDEX_NAME3,CustomDataSource.INDEX_NAME);\n        ReflectionTestUtils.setField(indexTemplateService,\"indexToAlias\",indexToAlias);\n        indexTemplateService.checkTemplateBlock(indices,CustomDataSource.appDetailFactory(),templateBlockTypeEnum);\n        templateBlockTypeEnum = WRITE_WRITE_TYPE;\n        indexTemplateService.checkTemplateBlock(indices,CustomDataSource.appDetailFactory(),templateBlockTypeEnum);\n    }\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/remote/AriusAdminRemoteServiceTests.java",
    "content": "package com.didi.arius.gateway.remote;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.remote.response.*;\nimport com.didi.arius.gateway.rest.AriusGatewayApplication;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = AriusGatewayApplication.class)\npublic class AriusAdminRemoteServiceTests {\n\n    private static String CLUSTER = \"logi-elasticsearch-7.6.0\";\n\n\n    @Autowired\n    private AriusAdminRemoteService ariusAdminRemoteService;\n\n    @Before\n    public void setUp() {\n    }\n\n    @Test\n    public void testListApp() {\n        AppListResponse appListResponse = ariusAdminRemoteService.listApp();\n        System.out.println(JSON.toJSONString(appListResponse));\n        assertEquals(true, appListResponse.getData().size() >= 0);\n        //{\"code\":0,\"data\":[{\"aggrAnalyzeEnable\":1,\"analyzeResponseEnable\":1,\"cluster\":\"\",\"dslAnalyzeEnable\":1,\"id\":100000003,\"indexExp\":[\"cn_arius_stats_node_info*\",\"dsink_error_metrics*\",\"us01_arius_stats_node_info*\",\"arius_stats_info*\",\"swan_agent_metrics*\",\"dsink_metrics*\",\"arius_info*\",\"latest_swan_agent_metrics*\",\"cn_arius_stats_index_node_info*\",\"cn_arius_stats_index_info*\",\"kafka_metrics*\"],\"ip\":[],\"isRoot\":0,\"isSourceSeparated\":0,\"name\":\"fqftest\",\"queryThreshold\":100,\"searchType\":1,\"verifyCode\":\"cVWLBbv6AS8rVju\",\"windexExp\":[]},{\"aggrAnalyzeEnable\":1,\"analyzeResponseEnable\":1,\"cluster\":\"\",\"dslAnalyzeEnable\":1,\"id\":100000001,\"indexExp\":[\"cn_arius_stats_node_info*\",\"dsink_error_metrics*\",\"us01_arius_stats_node_info*\",\"arius_stats_info*\",\"swan_agent_metrics*\",\"dsink_metrics*\",\"arius_info*\",\"latest_swan_agent_metrics*\",\"cn_arius_stats_index_node_info*\",\"cn_arius_stats_index_info*\",\"kafka_metrics*\"],\"ip\":[],\"isRoot\":0,\"isSourceSeparated\":0,\"name\":\"33888\",\"queryThreshold\":100,\"searchType\":1,\"verifyCode\":\"SNE8U2bkOFnSLNG\",\"windexExp\":[]},{\"aggrAnalyzeEnable\":1,\"analyzeResponseEnable\":1,\"cluster\":\"{clusterName}\",\"dslAnalyzeEnable\":1,\"id\":100000000,\"indexExp\":[\"*\"],\"ip\":[],\"isRoot\":1,\"isSourceSeparated\":0,\"name\":\"admin\",\"queryThreshold\":100,\"searchType\":1,\"verifyCode\":\"azAWiJhxkho33ac\",\"windexExp\":[\"*\"]},{\"aggrAnalyzeEnable\":1,\"analyzeResponseEnable\":1,\"cluster\":\"\",\"dslAnalyzeEnable\":1,\"id\":9,\"indexExp\":[\"*\"],\"ip\":[],\"isRoot\":1,\"isSourceSeparated\":0,\"name\":\"高版本ES查询回放\",\"queryThreshold\":100,\"searchType\":1,\"verifyCode\":\"helloworld\",\"windexExp\":[\"*\"]},{\"aggrAnalyzeEnable\":1,\"analyzeResponseEnable\":1,\"cluster\":\"\",\"dslAnalyzeEnable\":1,\"id\":7,\"indexExp\":[\"*\"],\"ip\":[],\"isRoot\":1,\"isSourceSeparated\":0,\"name\":\"低版本ES查询回放\",\"queryThreshold\":100,\"searchType\":1,\"verifyCode\":\"helloworld\",\"windexExp\":[\"*\"]},{\"aggrAnalyzeEnable\":1,\"analyzeResponseEnable\":1,\"cluster\":\"\",\"dslAnalyzeEnable\":1,\"id\":5,\"indexExp\":[\"test-dev-1\",\"us01_arius_stats_node_info*\",\"arius.master.slave.check\",\"cn_arius.indexname.access\",\"cn_arius_stats_ingest_info*\",\"cn_arius.appid.template.access\",\"cn_arius.template.access\",\"cn_arius_stats_index_node_info*\",\"cn_arius_stats_index_info*\",\"kafka_metrics*\",\"arius.dsl.template\",\"arius.template.mapping\",\"swan_agent_metrics*\",\"cn_arius_stats_node_index_info*\",\"dsink_metrics*\",\"cn_arius_template_quota_usage\",\"arius.index.size\",\"latest_swan_agent_metrics*\",\"cn_arius_stats_cluster_info*\",\"arius.template.hit\",\"arius.dsl.field.use\",\"cn_arius_stats_node_info*\",\"arius_stats_info*\",\"arius_info*\",\"cn_arius_meta_job_log*\",\"cn_v2.arius.template.label\",\"arius.template.field\",\"arius.dsl.metrics*\",\"arius.dsl.analyze.result\",\"cn_record.arius.template.value*\",\"dsink_error_metrics*\",\"cn_arius_stats_dcdr_info*\",\"cn_record_arius_template_quota_usage*\",\"cn_arius_meta_server_log*\",\"cn_arius.indexname.collect\",\"arius.gateway.join*\",\"cn_arius_template_qutoa_notiry_record*\"],\"ip\":[],\"isRoot\":0,\"isSourceSeparated\":0,\"name\":\"dsl审核\",\"queryThreshold\":100,\"searchType\":1,\"verifyCode\":\"helloworld\",\"windexExp\":[\"test-dev-1\",\"arius.master.slave.check\",\"cn_arius.indexname.access\",\"cn_arius_stats_ingest_info*\",\"cn_arius.appid.template.access\",\"cn_arius.template.access\",\"cn_arius_stats_index_node_info*\",\"cn_arius_stats_index_info*\",\"arius.dsl.template\",\"arius.template.mapping\",\"cn_arius_stats_node_index_info*\",\"cn_arius_template_quota_usage\",\"arius.index.size\",\"cn_arius_stats_cluster_info*\",\"arius.template.hit\",\"arius.dsl.field.use\",\"cn_arius_stats_node_info*\",\"cn_arius_meta_job_log*\",\"arius.template.field\",\"arius.dsl.metrics*\",\"arius.dsl.analyze.result\",\"cn_record.arius.template.value*\",\"cn_arius_stats_dcdr_info*\",\"cn_record_arius_template_quota_usage*\",\"cn_arius_meta_server_log*\",\"cn_arius.indexname.collect\",\"arius.gateway.join*\",\"cn_arius_template_qutoa_notiry_record*\"]},{\"aggrAnalyzeEnable\":1,\"analyzeResponseEnable\":1,\"cluster\":\"\",\"dslAnalyzeEnable\":1,\"id\":3,\"indexExp\":[\"*\"],\"ip\":[],\"isRoot\":1,\"isSourceSeparated\":0,\"name\":\"商业数据专用\",\"queryThreshold\":100,\"searchType\":1,\"verifyCode\":\"ocDk1kKl37NJRCG\",\"windexExp\":[\"*\"]},{\"aggrAnalyzeEnable\":1,\"analyzeResponseEnable\":0,\"cluster\":\"\",\"dslAnalyzeEnable\":0,\"id\":1,\"indexExp\":[\"*\"],\"ip\":[\"100.69.144.31\",\"127.0.0.1\",\"100.90.90.36\",\"100.90.89.31\",\"100.90.146.53\",\"100.70.179.19\",\"10.97.207.35\"],\"isRoot\":1,\"isSourceSeparated\":0,\"name\":\"admin\",\"queryThreshold\":100,\"searchType\":1,\"verifyCode\":\"admin\",\"windexExp\":[\"*\"]}],\"message\":\"操作成功\"}\n    }\n\n    @Test\n    public void testListCluster() {\n        DataCenterListResponse dataCenterListResponse = ariusAdminRemoteService.listCluster();\n        System.out.println(JSON.toJSONString(dataCenterListResponse));\n        assertEquals(true, dataCenterListResponse.getData().size() >= 0);\n        //{\"code\":0,\"data\":[{\"cluster\":\"dc-es02\",\"desc\":\"日常部署日常部署2222\",\"esVersion\":\"7.6.1.302\",\"httpAddress\":\"10.168.56.135:8060,10.169.182.134:8060\",\"httpWriteAddress\":\"10.169.182.134:8060\",\"id\":57,\"password\":\"\",\"readAddress\":\"\",\"type\":3,\"writeAddress\":\"\"},{\"cluster\":\"d1\",\"desc\":\"asadsasdasdasdasdasd\",\"esVersion\":\"7.6.0\",\"httpAddress\":\"10.86.119.55:8060,10.86.119.56:8060,10.86.119.57:8060\",\"httpWriteAddress\":\"10.86.119.55:8060,10.86.119.56:8060,10.86.119.57:8060\",\"id\":167,\"password\":\"\",\"readAddress\":\"\",\"type\":4,\"writeAddress\":\"\"},{\"cluster\":\"d3\",\"desc\":\"adadasd\",\"esVersion\":\"7.6.0\",\"httpAddress\":\"10.86.119.55:8060,10.86.119.56:8060,10.86.119.57:8060\",\"httpWriteAddress\":\"10.86.119.55:8060,10.86.119.56:8060,10.86.119.57:8060\",\"id\":169,\"password\":\"\",\"readAddress\":\"\",\"type\":4,\"writeAddress\":\"\"}],\"message\":\"操作成功\"}\n    }\n\n    @Test\n    public void testGetTemplateInfoMap() {\n        final TemplateInfoListResponse templateInfoMap = ariusAdminRemoteService.getTemplateInfoMap(CLUSTER);\n        System.out.println(JSON.toJSONString(templateInfoMap));\n        assertEquals(true, templateInfoMap.getData().size() >= 0);\n        //{\"code\":0,\"data\":{\"test-dev-1\":{\"aliases\":[],\"expression\":\"test-dev-1\",\"id\":1089,\"version\":0},\"arius.master.slave.check\":{\"aliases\":[],\"expression\":\"arius.master.slave.check\",\"id\":1043,\"version\":0},\"cn_arius.indexname.access\":{\"aliases\":[],\"expression\":\"cn_arius.indexname.access\",\"id\":1053,\"version\":0},\"cn_arius_stats_ingest_info*\":{\"aliases\":[],\"expression\":\"cn_arius_stats_ingest_info*\",\"id\":1071,\"version\":0},\"cn_arius.appid.template.access\":{\"aliases\":[],\"expression\":\"cn_arius.appid.template.access\",\"id\":1051,\"version\":0},\"cn_arius.template.access\":{\"aliases\":[],\"expression\":\"cn_arius.template.access\",\"id\":1057,\"version\":0},\"cn_arius_stats_index_info*\":{\"aliases\":[],\"expression\":\"cn_arius_stats_index_info*\",\"id\":1067,\"version\":0},\"arius.dsl.template\":{\"aliases\":[{\"name\":\"dsl_query_limit\"}],\"expression\":\"arius.dsl.template\",\"id\":1037,\"version\":0},\"arius.template.mapping\":{\"aliases\":[],\"expression\":\"arius.template.mapping\",\"id\":1049,\"version\":0},\"cn_arius_stats_node_index_info*\":{\"aliases\":[],\"expression\":\"cn_arius_stats_node_index_info*\",\"id\":1073,\"version\":0},\"arius.index.size\":{\"aliases\":[],\"expression\":\"arius.index.size\",\"id\":1041,\"version\":0},\"cn_arius_template_quota_usage\":{\"aliases\":[],\"expression\":\"cn_arius_template_quota_usage\",\"id\":1077,\"version\":0},\"arius.template.hit\":{\"aliases\":[],\"expression\":\"arius.template.hit\",\"id\":1047,\"version\":0},\"cn_arius_stats_cluster_info*\":{\"aliases\":[],\"expression\":\"cn_arius_stats_cluster_info*\",\"id\":1063,\"version\":0},\"arius.dsl.field.use\":{\"aliases\":[],\"expression\":\"arius.dsl.field.use\",\"id\":1033,\"version\":0},\"cn_arius_stats_node_info*\":{\"aliases\":[],\"expression\":\"cn_arius_stats_node_info*\",\"id\":1075,\"version\":0},\"cn_arius_meta_job_log*\":{\"aliases\":[],\"expression\":\"cn_arius_meta_job_log*\",\"id\":1059,\"version\":0},\"arius.dsl.metrics*\":{\"aliases\":[],\"expression\":\"arius.dsl.metrics*\",\"id\":1035,\"version\":0},\"arius.template.field\":{\"aliases\":[],\"expression\":\"arius.template.field\",\"id\":1045,\"version\":0},\"cn_v2.arius.template.label\":{\"aliases\":[],\"expression\":\"cn_v2.arius.template.label\",\"id\":1085,\"version\":0},\"arius.dsl.analyze.result\":{\"aliases\":[],\"expression\":\"arius.dsl.analyze.result\",\"id\":1031,\"version\":0},\"cn_record.arius.template.value*\":{\"aliases\":[],\"expression\":\"cn_record.arius.template.value*\",\"id\":1081,\"version\":0},\"cn_arius_stats_dcdr_info*\":{\"aliases\":[],\"expression\":\"cn_arius_stats_dcdr_info*\",\"id\":1065,\"version\":0},\"arius.gateway.join*\":{\"aliases\":[],\"expression\":\"arius.gateway.join*\",\"id\":1039,\"version\":0},\"cn_arius.indexname.collect\":{\"aliases\":[],\"expression\":\"cn_arius.indexname.collect\",\"id\":1055,\"version\":0},\"cn_arius_meta_server_log*\":{\"aliases\":[],\"expression\":\"cn_arius_meta_server_log*\",\"id\":1061,\"version\":0},\"cn_record_arius_template_quota_usage*\":{\"aliases\":[],\"expression\":\"cn_record_arius_template_quota_usage*\",\"id\":1083,\"version\":0},\"cn_arius_template_qutoa_notiry_record*\":{\"aliases\":[],\"expression\":\"cn_arius_template_qutoa_notiry_record*\",\"id\":1079,\"version\":0}},\"message\":\"操作成功\"}\n    }\n\n    @Test\n    public void testGetAliveCount() {\n        final ActiveCountResponse aliveCount = ariusAdminRemoteService.getAliveCount(CLUSTER);\n        System.out.println(JSON.toJSONString(aliveCount));\n        assertEquals(true, aliveCount.getData() >= 0);\n        //{\"code\":0,\"data\":0,\"message\":\"操作成功\"}\n    }\n\n    @Test\n    public void testListDeployInfo() {\n        final IndexTemplateListResponse indexTemplateListResponse = ariusAdminRemoteService.listDeployInfo();\n        System.out.println(JSON.toJSONString(indexTemplateListResponse));\n        assertEquals(true, indexTemplateListResponse.getData().size() >= 0);\n        //{\"code\":0,\"data\":{\"test-dev-1\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"test-dev-1\",\"id\":1091,\"ingestPipeline\":\"test-dev-1\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"test-dev-1\"},\"slaveInfos\":[]},\"arius.master.slave.check\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"arius.master.slave.check\",\"id\":1043,\"ingestPipeline\":\"arius.master.slave.check\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"arius.master.slave.check\"},\"slaveInfos\":[]},\"cn_arius.indexname.access\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"cn_arius.indexname.access\",\"id\":1053,\"ingestPipeline\":\"cn_arius.indexname.access\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius.indexname.access\"},\"slaveInfos\":[]},\"cn_arius.appid.template.access\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"cn_arius.appid.template.access\",\"id\":1051,\"ingestPipeline\":\"cn_arius.appid.template.access\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius.appid.template.access\"},\"slaveInfos\":[]},\"arius.dsl.metrics\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"timeStamp\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":150,\"expression\":\"arius.dsl.metrics*\",\"id\":1035,\"ingestPipeline\":\"arius.dsl.metrics\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"arius.dsl.metrics\"},\"slaveInfos\":[]},\"cn_arius.template.access\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"cn_arius.template.access\",\"id\":1057,\"ingestPipeline\":\"cn_arius.template.access\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius.template.access\"},\"slaveInfos\":[]},\"cn_arius_stats_node_index_info\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"timestamp\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":7,\"expression\":\"cn_arius_stats_node_index_info*\",\"id\":1073,\"ingestPipeline\":\"cn_arius_stats_node_index_info\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius_stats_node_index_info\"},\"slaveInfos\":[]},\"arius.dsl.template\":{\"baseInfo\":{\"aliases\":[\"dsl_query_limit\"],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"arius.dsl.template\",\"id\":1037,\"ingestPipeline\":\"arius.dsl.template\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"arius.dsl.template\"},\"slaveInfos\":[]},\"arius.template.mapping\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"arius.template.mapping\",\"id\":1049,\"ingestPipeline\":\"arius.template.mapping\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"arius.template.mapping\"},\"slaveInfos\":[]},\"cn_arius_stats_dcdr_info\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"timestamp\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":14,\"expression\":\"cn_arius_stats_dcdr_info*\",\"id\":1065,\"ingestPipeline\":\"cn_arius_stats_dcdr_info\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius_stats_dcdr_info\"},\"slaveInfos\":[]},\"arius.index.size\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"arius.index.size\",\"id\":1041,\"ingestPipeline\":\"arius.index.size\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"arius.index.size\"},\"slaveInfos\":[]},\"cn_arius_template_quota_usage\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"time\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"cn_arius_template_quota_usage\",\"id\":1077,\"ingestPipeline\":\"cn_arius_template_quota_usage\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius_template_quota_usage\"},\"slaveInfos\":[]},\"cn_arius_meta_server_log\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":6,\"expression\":\"cn_arius_meta_server_log*\",\"id\":1061,\"ingestPipeline\":\"cn_arius_meta_server_log\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius_meta_server_log\"},\"slaveInfos\":[]},\"cn_arius_stats_ingest_info\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"timestamp\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":7,\"expression\":\"cn_arius_stats_ingest_info*\",\"id\":1071,\"ingestPipeline\":\"cn_arius_stats_ingest_info\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius_stats_ingest_info\"},\"slaveInfos\":[]},\"arius.template.hit\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"arius.template.hit\",\"id\":1047,\"ingestPipeline\":\"arius.template.hit\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"arius.template.hit\"},\"slaveInfos\":[]},\"arius.dsl.field.use\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"arius.dsl.field.use\",\"id\":1033,\"ingestPipeline\":\"arius.dsl.field.use\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"arius.dsl.field.use\"},\"slaveInfos\":[]},\"cn_arius_template_qutoa_notiry_record\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"zeroDate\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":7,\"expression\":\"cn_arius_template_qutoa_notiry_record*\",\"id\":1079,\"ingestPipeline\":\"cn_arius_template_qutoa_notiry_record\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius_template_qutoa_notiry_record\"},\"slaveInfos\":[]},\"cn_arius_meta_job_log\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":2,\"expression\":\"cn_arius_meta_job_log*\",\"id\":1059,\"ingestPipeline\":\"cn_arius_meta_job_log\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius_meta_job_log\"},\"slaveInfos\":[]},\"arius.template.field\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"arius.template.field\",\"id\":1045,\"ingestPipeline\":\"arius.template.field\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"arius.template.field\"},\"slaveInfos\":[]},\"cn_v2.arius.template.label\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"cn_v2.arius.template.label\",\"id\":1085,\"ingestPipeline\":\"cn_v2.arius.template.label\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_v2.arius.template.label\"},\"slaveInfos\":[]},\"arius.dsl.analyze.result\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"logTime\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"arius.dsl.analyze.result\",\"id\":1031,\"ingestPipeline\":\"arius.dsl.analyze.result\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"arius.dsl.analyze.result\"},\"slaveInfos\":[]},\"cn_arius_stats_node_info\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"timestamp\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":180,\"expression\":\"cn_arius_stats_node_info*\",\"id\":1075,\"ingestPipeline\":\"cn_arius_stats_node_info\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius_stats_node_info\"},\"slaveInfos\":[]},\"cn_record_arius_template_quota_usage\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"timestamp\",\"dateFormat\":\"_yyyy-MM\",\"deployStatus\":3,\"expireTime\":360,\"expression\":\"cn_record_arius_template_quota_usage*\",\"id\":1083,\"ingestPipeline\":\"cn_record_arius_template_quota_usage\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_record_arius_template_quota_usage\"},\"slaveInfos\":[]},\"arius.gateway.join\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"timeStamp\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":23,\"expression\":\"arius.gateway.join*\",\"id\":1039,\"ingestPipeline\":\"arius.gateway.join\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"arius.gateway.join\"},\"slaveInfos\":[]},\"cn_arius_stats_cluster_info\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"timestamp\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":180,\"expression\":\"cn_arius_stats_cluster_info*\",\"id\":1063,\"ingestPipeline\":\"cn_arius_stats_cluster_info\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius_stats_cluster_info\"},\"slaveInfos\":[]},\"cn_arius.indexname.collect\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"\",\"dateFormat\":\"\",\"deployStatus\":3,\"expireTime\":-1,\"expression\":\"cn_arius.indexname.collect\",\"id\":1055,\"ingestPipeline\":\"cn_arius.indexname.collect\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius.indexname.collect\"},\"slaveInfos\":[]},\"cn_arius_stats_index_info\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"timestamp\",\"dateFormat\":\"_yyyy-MM-dd\",\"deployStatus\":3,\"expireTime\":180,\"expression\":\"cn_arius_stats_index_info*\",\"id\":1067,\"ingestPipeline\":\"cn_arius_stats_index_info\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_arius_stats_index_info\"},\"slaveInfos\":[]},\"cn_record.arius.template.value\":{\"baseInfo\":{\"aliases\":[],\"dateField\":\"timestamp\",\"dateFormat\":\"_yyyy-MM\",\"deployStatus\":3,\"expireTime\":180,\"expression\":\"cn_record.arius.template.value*\",\"id\":1081,\"ingestPipeline\":\"cn_record.arius.template.value\",\"version\":0},\"masterInfo\":{\"cluster\":\"dc-es02\",\"templateName\":\"cn_record.arius.template.value\"},\"slaveInfos\":[]}},\"message\":\"操作成功\"}\n    }\n\n    @Test\n    public void testListQueryConfig() {\n        final DynamicConfigListResponse dynamicConfigListResponse = ariusAdminRemoteService.listQueryConfig();\n        System.out.println(JSON.toJSONString(dynamicConfigListResponse));\n        assertEquals(true, dynamicConfigListResponse.getData().size() >= 0);\n        //{\"code\":0,\"data\":[],\"message\":\"操作成功\"}\n    }\n\n    @Test\n    public void testHeartbeat() {\n        ariusAdminRemoteService.heartbeat(CLUSTER, \"127.0.0.1\", 8200);\n    }\n\n    @Test\n    public void testListDslTemplates() {\n        final DSLTemplateListResponse dslTemplateListResponse = ariusAdminRemoteService.listDslTemplates(0L, \"\");\n        System.out.println(JSON.toJSONString(dslTemplateListResponse));\n        assertEquals(true, dslTemplateListResponse.getData() != null);\n        //TODO:houxiufeng 这里请求arius-admin 返回错误。\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/remote/ScheduleServiceTests.java",
    "content": "package com.didi.arius.gateway.remote;\n\nimport com.alibaba.fastjson.JSON;\nimport com.didi.arius.gateway.core.service.arius.*;\nimport com.didi.arius.gateway.remote.response.*;\nimport com.didi.arius.gateway.rest.AriusGatewayApplication;\nimport org.elasticsearch.gateway.GatewayService;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(classes = AriusGatewayApplication.class)\npublic class ScheduleServiceTests {\n\n    @Autowired\n    private AppService appService;\n\n    @Autowired\n    private DslTemplateService dslTemplateService;\n\n    @Autowired\n    private DynamicConfigService dynamicConfigService;\n\n    @Autowired\n    private ESClusterService esClusterService;\n\n    @Autowired\n    private GateWayHeartBeatService gateWayHeartBeatService;\n\n    @Autowired\n    private IndexTemplateService indexTemplateService;\n\n    @Before\n    public void setUp() {\n    }\n\n    @Test\n    public void testResetAppInfo() {\n        appService.resetAppInfo();\n    }\n\n    @Test\n    public void testResetDslInfo() {\n        dslTemplateService.resetDslInfo();\n    }\n\n    @Test\n    public void testResetDynamicConfigInfo() {\n        dynamicConfigService.resetDynamicConfigInfo();\n    }\n\n    @Test\n    public void testResetESClusaterInfo() {\n        esClusterService.resetESClusaterInfo();\n    }\n\n    @Test\n    public void testResetHeartBeatInfo() {\n        gateWayHeartBeatService.resetHeartBeatInfo();\n    }\n\n    @Test\n    public void testResetIndexTemplateInfo() {\n        indexTemplateService.resetIndexTemplateInfo();\n    }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/AriusGatewayApplicationTests.java",
    "content": "package com.didi.arius.gateway.rest;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@SpringBootTest\nclass AriusGatewayApplicationTests {\n\n    @Test\n    void contextLoads() {\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/CheckTests.java",
    "content": "package com.didi.arius.gateway.rest;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author fitz\n * @date 2021/6/2 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class CheckTests {\n\n    private Map<String, String> headerParams;\n    private static String INDEX_NAME = \"cn_record.arius.template.value\";\n\n    @Before\n    public void setUp() {\n        String appid = \"100000000\";\n        String appsecret = \"azAWiJhxkho33ac\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n    @Test\n    public void testCheckSearchAggsController() throws IOException {\n        //TODO:houxiufeng 这个怎么用？\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_check/search_aggs/\" + INDEX_NAME, \"POST\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    @Test\n    public void testGetMergeMappingController() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_check/mergeMapping/\" + INDEX_NAME, \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/GwadminTests.java",
    "content": "package com.didi.arius.gateway.rest;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author fitz\n * @date 2021/6/2 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class GwadminTests {\n\n    private Map<String, String> headerParams;\n    private static String indexName = \"cn_record.arius.template.value\";\n\n    @Before\n    public void setUp() {\n        String appid = \"100000000\";\n        String appsecret = \"azAWiJhxkho33ac\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n    @Test\n    public void testAppInfoController() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwadmin/appinfo\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n        JSONArray jr = JSON.parseArray(res);\n        assertEquals(true, jr.size() > 0);\n    }\n\n    @Test\n    public void testCheckIndexModeController() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwadmin/checkIndexMode\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    @Test\n    public void testCheckIndexModeController2() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwadmin/checkIndexMode/5\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    @Test\n    public void testDataCenterInfoController() throws IOException{\n        JSONArray jr = HttpClient.forward(\"http://127.0.0.1:8200/_gwadmin/datacenterinfo\", \"GET\", null, headerParams, null, JSONArray.class);\n        System.out.println(jr);\n        assertEquals(true, jr.size() >= 0);\n    }\n\n    @Test\n    public void testIndexTemplateController() throws IOException{\n        String s = HttpClient.forward(\"http://127.0.0.1:8200/_gwadmin/indextemplate/\" + indexName, \"GET\", null, headerParams, null);\n        System.out.println(s);\n    }\n\n    @Test\n    public void testIndextemplateInfoController() throws IOException{\n        String s = HttpClient.forward(\"http://127.0.0.1:8200/_gwadmin/indextemplateInfo\", \"GET\", null, headerParams, null);\n        System.out.println(s);\n    }\n\n    @Test\n    public void testSyncMetadataController() throws IOException{\n        String s = HttpClient.forward(\"http://127.0.0.1:8200/_gwadmin/sync/metadata\", \"GET\", null, headerParams, null);\n        System.out.println(s);\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/StatTests.java",
    "content": "package com.didi.arius.gateway.rest;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONArray;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author fitz\n * @date 2021/6/2 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class StatTests {\n\n    private Map<String, String> headerParams;\n    private static String INDEX_NAME = \"cn_record.arius.template.value\";\n\n    @Before\n    public void setUp() {\n        String appid = \"100000000\";\n        String appsecret = \"azAWiJhxkho33ac\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n\n    /**\n     * /_gwstat/action/request\n     * /_gwstat/action/request/{action}\n     */\n    @Test\n    public void testActionRequestStatsController() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/action/request\", \"GET\", null, headerParams, null);\n//        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/action/request/test\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /_gwstat/alias/info\n     * /_gwstat/alias/info/{cluster}\n     */\n    @Test\n    public void testAliasInfoController() throws IOException {\n//        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/alias/info\", \"GET\", null, headerParams, null);\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/alias/info/dc-es02\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /_gwstat/app/request\n     * /_gwstat/app/request/{appid}\n     * /_gwstat/app/request/{appid}/{searchid}\n     */\n    @Test\n    public void testAppRequestStatsController() throws IOException {\n//        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/app/request\", \"GET\", null, headerParams, null);\n//        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/app/request/5\", \"GET\", null, headerParams, null);\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/app/request/5/all\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /_gwstat/flowrate\n     * /_gwstat/flowrate/{appid}\n     */\n    @Test\n    public void testFlowRateController() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/flowrate\", \"GET\", null, headerParams, null);\n//        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/flowrate/5\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /_gwstat/rateLimitDetail\n     * /_gwstat/rateLimitDetail/{appid}\n     */\n    @Test\n    public void testRateLimitDetailController() throws IOException {\n//        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/rateLimitDetail\", \"GET\", null, headerParams, null);\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/rateLimitDetail/5\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /_gwstat/rateLimitInfo\n     */\n    @Test\n    public void testRateLimitInfoController() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/rateLimitInfo\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /_gwstat/requesting\n     */\n    @Test\n    public void testRequestingStatsController() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/requesting\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n        JSONArray jr = JSON.parseArray(res);\n        assertEquals(true, jr.size() > 0);\n    }\n\n\n    /**\n     * /_gwstat/tcp/requesting\n     */\n    @Test\n    public void testRequestingTcpStatsController() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/tcp/requesting\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n        JSONArray jr = JSON.parseArray(res);\n        assertEquals(true, jr.size() >= 0);\n    }\n\n    /**\n     * /_gwstat/hotthreads\n     * /_gwstat/hot_threads\n     */\n    @Test\n    public void testRestHotThreadsController() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/hotthreads\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /_gwstat/template/info\n     * /_gwstat/template/info/{cluster}\n     */\n    @Test\n    public void testTemplateInfoController() throws IOException {\n        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/template/info\", \"GET\", null, headerParams, null);\n//        String res = HttpClient.forward(\"http://127.0.0.1:8200/_gwstat/template/info/dc-es02\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/es/AdminTests.java",
    "content": "package com.didi.arius.gateway.rest.es;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author fitz\n * @date 2021/6/2 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class AdminTests {\n\n    private Map<String, String> headerParams;\n    private static String INDEX_NAME = \"cn_record.arius.template.value\";\n    private static String HOST = \"http://127.0.0.1:8200\";\n\n    @Before\n    public void setUp() {\n        String appid = \"1\";\n        String appsecret = \"azAWiJhxkho33ac\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n    /**\n     * /_cat/indices\n     * /_cat/indices/{index}\n     * @throws IOException\n     */\n    @Test\n    public void testRestIndicesController() throws IOException {\n        String res = HttpClient.forward(HOST+\"/_cat/indices\", \"GET\", null, headerParams, null);\n        assertEquals(\"not support!\", res);\n        String res2 = HttpClient.forward(HOST+\"/_cat/indices/\" + INDEX_NAME, \"GET\", null, headerParams, null);\n        System.out.println(res2);\n    }\n\n    /**\n     * /_cluster/health\n     * /_cluster/health/{index}\n     * @throws IOException\n     */\n    @Test\n    public void testRestClusterHealthController() throws IOException {\n        String res = HttpClient.forward(HOST+\"/_cluster/health\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getIntValue(\"active_shards\") > 0);\n\n\n        String res2 = HttpClient.forward(HOST+\"/_cluster/health/\" + INDEX_NAME, \"GET\", null, headerParams, null);\n        System.out.println(res2);\n        JSONObject jsonObject2 = JSON.parseObject(res2);\n        assertEquals(true, jsonObject2.getIntValue(\"active_shards\") > 0);\n    }\n\n    /**\n     * /_nodes\n     * /_nodesclean\n     * /_nodes/{nodeId}\n     * /_nodes/{nodeId}/{metrics}\n     * /_nodes/{nodeId}/info/{metrics}\n     * @throws IOException\n     */\n    @Test\n    public void testRestNodesInfoController() throws IOException {\n//        String res = HttpClient.forward(HOST+\"/_nodes\", \"GET\", null, headerParams, null);\n//        System.out.println(res);\n//        JSONObject jsonObject = JSON.parseObject(res);\n//        Integer total = jsonObject.getJSONObject(\"_nodes\").getInteger(\"total\");\n//        assertEquals(total > 0, true);\n\n//        String res = HttpClient.forward(HOST+\"/_nodes/QkU741SpRTKzJ5gRrUxEtw/jvm\", \"GET\", null, headerParams, null);\n        String res = HttpClient.forward(HOST+\"/_nodes/QkU741SpRTKzJ5gRrUxEtw/info/jvm\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n        JSONObject jsonObject = JSON.parseObject(res);\n        Integer total = jsonObject.getJSONObject(\"_nodes\").getInteger(\"total\");\n        assertEquals(true, total > 0);\n    }\n\n    /**\n     * /_cluster/settings\n     * @throws IOException\n     */\n    @Test\n    public void testRestPutClusterSettingsController() throws IOException {\n        String bodyform = \"{\\\"persistent\\\":{\\\"cluster.routing.allocation.enable\\\": \\\"all\\\"}}\";\n        String res = HttpClient.forward(HOST+\"/_cluster/settings\", \"PUT\", bodyform, headerParams, null);\n        System.out.println(res);\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getBoolean(\"acknowledged\"));\n    }\n\n    /**\n     * /_field_stats\n     * /{index}/_field_stats\n     * @throws IOException\n     */\n    @Test\n    public void testRestFieldStatsController() throws IOException {\n        //TODO:houxiufeng\n        //报错 GET {\"error\":{\"root_cause\":[{\"type\":\"index_out_of_bounds_exception\",\"reason\":\"Index: 0, Size: 0\"}],\"type\":\"index_out_of_bounds_exception\",\"reason\":\"Index: 0, Size: 0\"},\"status\":500}\n        //报错 POST {\"error\":{\"root_cause\":[{\"type\":\"invalid_type_name_exception\",\"reason\":\"Document mapping type name can't start with '_', found: [_field_stats]\"}],\"type\":\"invalid_type_name_exception\",\"reason\":\"Document mapping type name can't start with '_', found: [_field_stats]\"},\"status\":400}\n//        String bodyform = \"{\\\"fields\\\":[\\\"rating\\\"]}\";\n//        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_field_stats\", \"POST\", bodyform, headerParams, null);\n        String res = HttpClient.forward(HOST+\"/_field_stats?fields=rating\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /_mapping/field/{fields}\n     * /_mapping/{type}/field/{fields}\n     * /{index}/_mapping/field/{fields}\n     * /{index}/{type}/_mapping/field/{fields}\n     * /{index}/_mapping/{type}/field/{fields}\n     * @throws IOException\n     */\n    @Test\n    public void testRestGetFieldMappingController() throws IOException {\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME + \"/_mapping/field/name,age\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n        JSONObject jsonObject = JSON.parseObject(res);\n        JSONObject indexJson = jsonObject.getJSONObject(INDEX_NAME);\n        assertEquals(true, indexJson != null);\n\n    }\n\n    /**\n     * /{index}/{type}/_mapping\n     * /{index}/_mapping\n     * /{index}/_mappings\n     * /{index}/_mappings/{type}\n     * /{index}/_mapping/{type}\n     * /_mapping/{type}\n     * /_mapping\n     * /_mappings\n     * @throws IOException\n     */\n    @Test\n    public void testRestGetMappingController() throws IOException {\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME + \"/_mapping\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n        JSONObject jsonObject = JSON.parseObject(res);\n        JSONObject indexJson = jsonObject.getJSONObject(INDEX_NAME);\n        assertEquals(true, indexJson != null);\n\n    }\n\n    /**\n     * /{index}\n     * @throws IOException\n     */\n    @Test\n    public void testRestCreateIndexController() throws IOException {\n        //TODO:houxiufeng 这个为什么不能创建\n        String index = \"student\";\n        String bodyform = \"{\\\"mappings\\\":{\\\"properties\\\":{\\\"name\\\":{\\\"type\\\":\\\"text\\\"},\\\"age\\\":{\\\"type\\\":\\\"integer\\\"},\\\"birthday\\\":{\\\"type\\\":\\\"date\\\"}}}}\";\n        String res = HttpClient.forward(HOST+\"/\" + index, \"PUT\", bodyform, headerParams, null);\n        System.out.println(res);\n//        JSONObject jsonObject = JSON.parseObject(res);\n//        JSONObject indexJson = jsonObject.getJSONObject(INDEX_NAME);\n//        assertEquals(indexJson != null, true);\n\n    }\n\n    /**\n     * /{index}\n     * @throws IOException\n     */\n    @Test\n    public void testRestDeleteIndexController() throws IOException {\n        String index = \"cn_record.arius.template.value_2021-05\";\n        String res = HttpClient.forward(HOST+\"/\" + index, \"DELETE\", null, headerParams, null);\n        System.out.println(res);\n        JSONObject jsonObject = JSON.parseObject(res);\n        Boolean b = jsonObject.getBoolean(\"acknowledged\");\n        assertEquals(true, b);\n\n    }\n\n    /**\n     * /{index}/_settings\n     * @throws IOException\n     */\n    @Test\n    public void testRestPutIndexSettingsController() throws IOException {\n        //TODO:houxiufeng, 这个也失败了，为什么\n        String index = \"cn_record.arius.template.value_2021-05\";\n        String bodyform = \"{\\\"properties\\\":{\\\"age\\\":{\\\"type\\\":\\\"long\\\"},\\\"es_index_time\\\":{\\\"type\\\":\\\"long\\\"},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"type\\\":\\\"keyword\\\",\\\"ignore_above\\\":256}}},\\\"timestamp\\\":{\\\"type\\\":\\\"text\\\",\\\"fields\\\":{\\\"keyword\\\":{\\\"type\\\":\\\"keyword\\\",\\\"ignore_above\\\":256}}}}}\";\n        String res = HttpClient.forward(HOST+\"/\" + index + \"/_settings\", \"PUT\", bodyform, headerParams, null);\n        System.out.println(res);\n\n    }\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/es/BulkTests.java",
    "content": "package com.didi.arius.gateway.rest.es;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author fitz\n * @date 2021/6/2 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class BulkTests {\n\n    private Map<String, String> headerParams;\n    private static String INDEX_NAME = \"cn_record.arius.template.value_2021-05\";\n    private static String HOST = \"http://127.0.0.1:8200\";\n\n    @Before\n    public void setUp() {\n//        String appid = \"100000000\";\n//        String appsecret = \"azAWiJhxkho33ac\";\n        String appid = \"5\";\n        String appsecret = \"helloworld\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n    /**\n     * /_bulk\n     * @throws IOException\n     */\n    @Test\n    public void testRestBulkController() throws IOException {\n        String bodyform = \"{ \\\"index\\\" : { \\\"_index\\\" : \\\"cn_record.arius.template.value_2021-05\\\", \\\"_id\\\" : \\\"11\\\" } }\\n\" +\n                \"{ \\\"name\\\" : \\\"张三\\\" }\\n\" +\n                \"{ \\\"index\\\" : { \\\"_index\\\" : \\\"cn_record.arius.template.value_2021-05\\\", \\\"_id\\\" : \\\"12\\\" } }\\n\" +\n                \"{ \\\"name\\\" : \\\"李四\\\", \\\"age\\\": 10 }\\n\" +\n                \"{ \\\"index\\\" : { \\\"_index\\\" : \\\"cn_record.arius.template.value_2021-05\\\", \\\"_id\\\" : \\\"13\\\" } }\\n\" +\n                \"{ \\\"name\\\" : \\\"王五\\\", \\\"age\\\": 11 }\\n\";\n\n        String bodyform2 = \"{ \\\"index\\\" : { \\\"_index\\\" : \\\"cn_record.arius.template.value_2021-05\\\", \\\"_id\\\" : \\\"21\\\" } }\\n\" +\n                \"{ \\\"name\\\" : \\\"张三x\\\" }\\n\" +\n                \"{ \\\"delete\\\" : { \\\"_index\\\" : \\\"cn_record.arius.template.value_2021-05\\\", \\\"_id\\\" : \\\"12\\\" } }\\n\" +\n                \"{ \\\"create\\\" : { \\\"_index\\\" : \\\"cn_record.arius.template.value_2021-05\\\", \\\"_id\\\" : \\\"23\\\" } }\\n\" +\n                \"{ \\\"name\\\" : \\\"王五x\\\", \\\"age\\\": 11 }\\n\";\n        String res = HttpClient.forward(HOST+\"/_bulk\", \"POST\", bodyform2, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /{index}/_bulk\n     * @throws IOException\n     */\n    @Test\n    public void testRestBulkController2() throws IOException {\n        String bodyform = \"{ \\\"index\\\" : { \\\"_id\\\" : \\\"31\\\" } }\\n\" +\n                \"{ \\\"name\\\" : \\\"张三y\\\" }\\n\";\n\n        String res = HttpClient.forward(HOST+ \"/\" + INDEX_NAME + \"/_bulk\", \"POST\", bodyform, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /{index}/{type}/_bulk\n     * @throws IOException\n     */\n    @Test\n    public void testRestBulkController3() throws IOException {\n        String bodyform = \"{ \\\"index\\\" : { \\\"_id\\\" : \\\"41\\\" } }\\n\" +\n                \"{ \\\"name\\\" : \\\"张三z\\\" }\\n\";\n\n        String res = HttpClient.forward(HOST+ \"/\" + INDEX_NAME + \"/_doc/_bulk\", \"POST\", bodyform, headerParams, null);\n        System.out.println(res);\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(false, jsonObject.getBoolean(\"errors\"));\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/es/CountTests.java",
    "content": "package com.didi.arius.gateway.rest.es;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author fitz\n * @date 2021/6/2 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class CountTests {\n\n    private Map<String, String> headerParams;\n    private static String INDEX_NAME = \"cn_record.arius.template.value_2021-05\";\n    private static String HOST = \"http://127.0.0.1:8200\";\n\n    @Before\n    public void setUp() {\n//        String appid = \"100000000\";\n//        String appsecret = \"azAWiJhxkho33ac\";\n        String appid = \"5\";\n        String appsecret = \"helloworld\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n    /**\n     * /_count\n     * /{index}/_count\n     * /{index}/{type}/_count\n     * @throws IOException\n     */\n    @Test\n    public void testRestCountController() throws IOException {\n        String bodyform = \"{\\\"query\\\":{\\\"term\\\":{\\\"name\\\":\\\"fitz1\\\"}}}\";\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_count\", \"POST\", bodyform, headerParams, null);\n        //{\"_shards\":{\"failedShard\":0,\"skippedShard\":0,\"successfulShard\":16,\"totalShard\":16},\"count\":1}\n        System.out.println(res);\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getIntValue(\"count\") >= 0);\n    }\n\n    /**\n     * /_count\n     * /{index}/_count\n     * /{index}/{type}/_count\n     * @throws IOException\n     */\n    @Test\n    public void testRestCountController2() throws IOException {\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_count?q=name:fitz1%20AND%20age:1\", \"GET\", null, headerParams, null);\n        //{\"_shards\":{\"failedShard\":0,\"skippedShard\":0,\"successfulShard\":16,\"totalShard\":16},\"count\":1}\n        System.out.println(res);\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getIntValue(\"count\") >= 0);\n    }\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/es/DocumentTests.java",
    "content": "package com.didi.arius.gateway.rest.es;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author fitz\n * @date 2021/6/2 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class DocumentTests {\n\n    private Map<String, String> headerParams;\n    private static String INDEX_NAME = \"cn_record.arius.template.value_2021-05\";\n    private static String HOST = \"http://127.0.0.1:8200\";\n\n    @Before\n    public void setUp() {\n//        String appid = \"100000000\";\n//        String appsecret = \"azAWiJhxkho33ac\";\n        String appid = \"5\";\n        String appsecret = \"helloworld\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n    /**\n     * /{index}/_doc/{id}\n     * /{index}/{type}/{id}\n     * @throws IOException\n     */\n    @Test\n    public void testRestDeleteController() throws IOException {\n        /**\n         * 这里出现一个注册错误，但不影响执行结果，后面看看\n         * Error registering metric:service=arius,name=gateway_index_cn_record.arius.template.value*_delete\n         * javax.management.RuntimeOperationsException: null\n         */\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_doc/31\", \"DELETE\", null, headerParams, null);\n        System.out.println(res);\n        //{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"41\",\"_version\":3,\"_shards\":{\"total\":2,\"failed\":0,\"successful\":2},\"result\":\"deleted\",\"_seq_no\":2,\"_primary_term\":1,\"found\":true}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONObject(\"_shards\") != null);\n    }\n\n    /**\n     * /{index}/_doc\n     * /{index}/_doc/{id}\n     * /{index}/_create/{id}\n     * /{index}/{type}/{id}/_create\n     * @throws IOException\n     */\n    @Test\n    public void testRestIndexController() throws IOException {\n        /**\n         * 这里出现一个注册错误，但不影响执行结果，后面看看\n         * Error registering metric:service=arius,name=gateway_index_cn_record.arius.template.value*_index\n         * javax.management.RuntimeOperationsException: null\n         */\n        String bodyform = \"{\\\"name\\\":\\\"fitz2\\\",\\\"age\\\":22,\\\"timestamp\\\":\\\"2021-06-10 10:06:13\\\"}\";\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_doc\", \"POST\", bodyform, headerParams, null);\n        System.out.println(res);\n        //{\"_index\":\"cn_record.arius.template.value_2021-06\",\"_type\":\"_doc\",\"_id\":\"DKHM83kBmWfLM8BR_GVW\",\"_version\":1,\"_shards\":{\"total\":2,\"failed\":0,\"successful\":2},\"result\":\"created\",\"_seq_no\":0,\"_primary_term\":1,\"created\":true}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONObject(\"_shards\") != null);\n    }\n\n    /**\n     * /{index}/_doc\n     * /{index}/_doc/{id}\n     * /{index}/_create/{id}\n     * /{index}/{type}/{id}/_create\n     * @throws IOException\n     */\n    @Test\n    public void testRestIndexController2() throws IOException {\n        /**\n         * 这里出现一个注册错误，但不影响执行结果，后面看看\n         * Error registering metric:service=arius,name=gateway_index_cn_record.arius.template.value*_index\n         * javax.management.RuntimeOperationsException: null\n         */\n        String bodyform = \"{\\\"name\\\":\\\"fitz3\\\",\\\"age\\\":23,\\\"timestamp\\\":\\\"2021-06-10 10:16:13\\\"}\";\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_doc/14\", \"POST\", bodyform, headerParams, null);\n        System.out.println(res);\n        //{\"_index\":\"cn_record.arius.template.value_2021-06\",\"_type\":\"_doc\",\"_id\":\"DKHM83kBmWfLM8BR_GVW\",\"_version\":1,\"_shards\":{\"total\":2,\"failed\":0,\"successful\":2},\"result\":\"created\",\"_seq_no\":0,\"_primary_term\":1,\"created\":true}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONObject(\"_shards\") != null);\n    }\n\n    /**\n     * /{index}/_doc\n     * /{index}/_doc/{id}\n     * /{index}/_create/{id}\n     * /{index}/{type}/{id}/_create\n     * @throws IOException\n     */\n    @Test\n    public void testRestIndexController3() throws IOException {\n        /**\n         * 这里出现一个注册错误，但不影响执行结果，后面看看\n         * Error registering metric:service=arius,name=gateway_index_cn_record.arius.template.value*_index\n         * javax.management.RuntimeOperationsException: null\n         */\n        String bodyform = \"{\\\"name\\\":\\\"fitz4\\\",\\\"age\\\":24,\\\"timestamp\\\":\\\"2021-06-10 10:16:13\\\"}\";\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_create/15\", \"POST\", bodyform, headerParams, null);\n        System.out.println(res);\n        //{\"_index\":\"cn_record.arius.template.value_2021-06\",\"_type\":\"_doc\",\"_id\":\"15\",\"_version\":1,\"_shards\":{\"total\":2,\"failed\":0,\"successful\":2},\"result\":\"created\",\"_seq_no\":0,\"_primary_term\":1,\"created\":true}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONObject(\"_shards\") != null);\n    }\n\n    /**\n     * /{index}/_doc\n     * /{index}/_doc/{id}\n     * /{index}/_create/{id}\n     * /{index}/{type}/{id}/_create\n     * @throws IOException\n     */\n    @Test\n    public void testRestIndexController4() throws IOException {\n        /**\n         * 这里出现一个注册错误，但不影响执行结果，后面看看\n         * Error registering metric:service=arius,name=gateway_index_cn_record.arius.template.value*_index\n         * javax.management.RuntimeOperationsException: null\n         */\n        String bodyform = \"{\\\"name\\\":\\\"fitz5\\\",\\\"age\\\":25,\\\"timestamp\\\":\\\"2021-06-10 10:16:13\\\"}\";\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_doc/16/_create\", \"POST\", bodyform, headerParams, null);\n        System.out.println(res);\n        //{\"_index\":\"cn_record.arius.template.value_2021-06\",\"_type\":\"_doc\",\"_id\":\"16\",\"_version\":1,\"_shards\":{\"total\":2,\"failed\":0,\"successful\":2},\"result\":\"created\",\"_seq_no\":1,\"_primary_term\":1,\"created\":true}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONObject(\"_shards\") != null);\n    }\n\n    /**\n     * /{index}/_update/{id}\n     * /{index}/{type}/{id}/_update\n     * @throws IOException\n     */\n    @Test\n    public void testRestUpdateController() throws IOException {\n        /**\n         * 这里出现一个注册错误，但不影响执行结果，后面看看\n         * Error registering metric:service=arius,name=gateway_index_cn_record.arius.template.value*_update\n         * javax.management.RuntimeOperationsException: null\n         */\n        String bodyform = \"{\\\"doc\\\":{\\\"name\\\":\\\"法外狂徒张三 \\\",\\\"age\\\":24,\\\"timestamp\\\":\\\"2021-05-10 10:16:13\\\"}}\";\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_update/11\", \"POST\", bodyform, headerParams, null);\n        System.out.println(res);\n        //{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"11\",\"_version\":2,\"_shards\":{\"total\":2,\"failed\":0,\"successful\":2},\"result\":\"updated\",\"_seq_no\":2,\"_primary_term\":1}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONObject(\"_shards\") != null);\n    }\n\n    /**\n     * /{index}/_update/{id}\n     * /{index}/{type}/{id}/_update\n     * @throws IOException\n     */\n    @Test\n    public void testRestUpdateController2() throws IOException {\n        /**\n         * 这里出现一个注册错误，但不影响执行结果，后面看看\n         * Error registering metric:service=arius,name=gateway_index_cn_record.arius.template.value*_update\n         * javax.management.RuntimeOperationsException: null\n         */\n        String bodyform = \"{\\\"doc\\\":{\\\"name\\\":\\\"法外狂徒张三少 \\\",\\\"age\\\":25,\\\"timestamp\\\":\\\"2021-05-10 10:16:13\\\"}}\";\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_doc/11/_update\", \"POST\", bodyform, headerParams, null);\n        System.out.println(res);\n        //{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"11\",\"_version\":5,\"_shards\":{\"total\":2,\"failed\":0,\"successful\":2},\"result\":\"updated\",\"_seq_no\":5,\"_primary_term\":1}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONObject(\"_shards\") != null);\n    }\n\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/es/GetTests.java",
    "content": "package com.didi.arius.gateway.rest.es;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author fitz\n * @date 2021/6/10 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class GetTests {\n\n    private Map<String, String> headerParams;\n    private static String INDEX_NAME = \"cn_record.arius.template.value_2021-05\";\n    private static String HOST = \"http://127.0.0.1:8200\";\n\n    @Before\n    public void setUp() {\n//        String appid = \"100000000\";\n//        String appsecret = \"azAWiJhxkho33ac\";\n        String appid = \"5\";\n        String appsecret = \"helloworld\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n    /**\n     * /{index}/{type}/{id}\n     * @throws IOException\n     */\n    @Test\n    public void testRestGetController() throws IOException {\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_doc/11\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n        //{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"11\",\"_version\":3,\"_shards\":{\"total\":2,\"failed\":0,\"successful\":2},\"result\":\"deleted\",\"_seq_no\":2,\"_primary_term\":1,\"found\":true}\n        //{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"111\",\"found\":false}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getBoolean(\"found\") != null);\n    }\n\n    /**\n     * /{index}/{type}/{id}/_source\n     * @throws IOException\n     */\n    @Test\n    public void testRestGetSourceController() throws IOException {\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_doc/11/_source\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n        //{\"name\":\"法外狂徒张三少 \",\"es_index_time\":1623295368686,\"age\":25,\"timestamp\":\"2021-05-10 10:16:13\"}\n        //{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"111\",\"found\":false}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject != null);\n    }\n\n    /**\n     * /{index}/{type}/{id}\n     * /{index}/{type}/{id}/_source\n     * @throws IOException\n     */\n    @Test\n    public void testRestHeadController() throws IOException {\n        //这个一直返回null, 正常否？\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_doc/11\", \"HEAD\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /_mget\n     * /{index}/_mget\n     * /{index}/{type}/_mget\n     * @throws IOException\n     */\n    @Test\n    public void testRestMultiGetController() throws IOException {\n        String dodyform = \"{\\\"docs\\\":[{\\\"_type\\\":\\\"_doc\\\",\\\"_id\\\":1},{\\\"_type\\\":\\\"_doc\\\",\\\"_id\\\":11}]}\";\n        //GET 方式会报错，参数传的不对么\n//        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_mget\", \"POST\", dodyform, headerParams, null);\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME +\"/_doc/_mget\", \"POST\", dodyform, headerParams, null);\n        System.out.println(res);\n        //{\"docs\":[{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"1\",\"_version\":1,\"found\":true,\"_source\":{\"name\":\"fitz1\",\"age\":1,\"es_index_time\":1623132760300,\"timestamp\":\"2021-05-23 19:06:13\"},\"_seq_no\":0,\"_primary_term\":1},{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"11\",\"_version\":6,\"found\":true,\"_source\":{\"name\":\"法外狂徒张三少 \",\"es_index_time\":1623295368686,\"age\":25,\"timestamp\":\"2021-05-10 10:16:13\"},\"_seq_no\":6,\"_primary_term\":1}]}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONArray(\"docs\").size() >= 0);\n\n    }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/es/RestCommonTests.java",
    "content": "package com.didi.arius.gateway.rest.es;\n\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author fitz\n * @date 2021/6/10 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class RestCommonTests {\n\n    private Map<String, String> headerParams;\n    private static String INDEX_NAME = \"cn_record.arius.template.value_2021-05\";\n    private static String HOST = \"http://127.0.0.1:8200\";\n\n    @Before\n    public void setUp() {\n//        String appid = \"100000000\";\n//        String appsecret = \"azAWiJhxkho33ac\";\n        String appid = \"5\";\n        String appsecret = \"helloworld\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n    /**\n     * /{index}\n     * @throws IOException\n     */\n    @Test\n    public void testRestCommonController() throws IOException {\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME, \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /{index}/_settings\n     * @throws IOException\n     */\n    @Test\n    public void testRestCommonController2() throws IOException {\n        String res = HttpClient.forward(HOST+\"/\" + INDEX_NAME + \"/_settings\", \"GET\", null, headerParams, null);\n        System.out.println(res);\n    }\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/es/SearchTests.java",
    "content": "package com.didi.arius.gateway.rest.es;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author fitz\n * @date 2021/6/10 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class SearchTests {\n\n    private Map<String, String> headerParams;\n    private static String INDEX_NAME = \"cn_record.arius.template.value_2021-05\";\n    private static String HOST = \"http://127.0.0.1:8200\";\n\n    @Before\n    public void setUp() {\n//        String appid = \"100000000\";\n//        String appsecret = \"azAWiJhxkho33ac\";\n        String appid = \"5\";\n        String appsecret = \"helloworld\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n    /**\n     * /_search/scroll\n     * /_search/scroll/{scroll_id}\n     * @throws IOException\n     */\n    @Test\n    public void testRestClearScrollController() throws IOException {\n        String res = HttpClient.forward(HOST+ \"/_search/scroll/sdf\", \"DELETE\", null, headerParams, null);\n        System.out.println(res);\n//        JSONObject jsonObject = JSON.parseObject(res);\n//        assertEquals(jsonObject.getBoolean(\"found\") != null, true);\n    }\n\n\n    /**\n     * /_msearch\n     * /{index}/_msearch\n     * /{index}/{type}/_msearch\n     * /_msearch/template\n     * /{index}/_msearch/template\n     * /{index}/{type}/_msearch/template\n     * @throws IOException\n     */\n    @Test\n    public void testRestMultiSearchController() throws IOException, InterruptedException {\n        String formbody = \"{\\\"index\\\":\\\"cn_record.arius.template.value_2021-05\\\"}\\n\" +\n                \"{\\\"query\\\":{\\\"match_all\\\":{}}}\\n\" +\n                \"{\\\"index\\\":\\\"cn_record.arius.template.value_2021-05\\\"}\\n\" +\n                \"{\\\"query\\\":{\\\"match\\\":{\\\"name\\\":\\\"张三\\\"}}}\\n\";\n        String res = HttpClient.forward(HOST+ \"/_msearch\", \"POST\", formbody, headerParams, null);\n        System.out.println(res);\n        //{\"responses\":[{\"took\":2,\"timed_out\":false,\"_shards\":{\"total\":16,\"successful\":16,\"failed\":0},\"hits\":{\"total\":5,\"max_score\":\"1.0\",\"hits\":[{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"11\",\"_score\":\"1.0\",\"_source\":{\"name\":\"法外狂徒张三少 \",\"es_index_time\":1623295368686,\"age\":25,\"timestamp\":\"2021-05-10 10:16:13\"}},{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"1\",\"_score\":\"1.0\",\"_source\":{\"name\":\"fitz1\",\"age\":1,\"es_index_time\":1623132760300,\"timestamp\":\"2021-05-23 19:06:13\"}},{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"23\",\"_score\":\"1.0\",\"_source\":{\"name\":\"王五x\",\"age\":11}},{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"13\",\"_score\":\"1.0\",\"_source\":{\"name\":\"王五\",\"age\":11}},{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"21\",\"_score\":\"1.0\",\"_source\":{\"name\":\"张三x\"}}]},\"status\":200},{\"took\":2,\"timed_out\":false,\"_shards\":{\"total\":16,\"successful\":16,\"failed\":0},\"hits\":{\"total\":2,\"max_score\":1.0608165,\"hits\":[{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"11\",\"_score\":1.0608165,\"_source\":{\"name\":\"法外狂徒张三少 \",\"es_index_time\":1623295368686,\"age\":25,\"timestamp\":\"2021-05-10 10:16:13\"}},{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"21\",\"_score\":0.5753642,\"_source\":{\"name\":\"张三x\"}}]},\"status\":200}]}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONArray(\"responses\").size() >= 0);\n    }\n\n    /**\n     * /_search\n     * /{index}/_search\n     * /{index}/{type}/_search\n     * /{index}/_search/template\n     * /{index}/{type}/_search/template\n     * @throws IOException\n     */\n    @Test\n    public void testRestSearchController() throws IOException, InterruptedException {\n        //这里主要为了让定时器执行完毕， 刷新内存中的索引信息\n        Thread.sleep(1000L);\n        String formbody = \"{\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[{\\\"term\\\":{\\\"name\\\":\\\"fitz1\\\"}},{\\\"term\\\":{\\\"age\\\":1}}]}}}\";\n        String res = HttpClient.forward(HOST+ \"/\" + INDEX_NAME + \"/_search\", \"POST\", formbody, headerParams, null);\n        //{\"took\":1,\"timed_out\":false,\"_shards\":{\"total\":16,\"successful\":16,\"failed\":0},\"hits\":{\"total\":1,\"max_score\":1.9999499,\"hits\":[{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"1\",\"_score\":1.9999499,\"_source\":{\"name\":\"fitz1\",\"age\":1,\"es_index_time\":1623132760300,\"timestamp\":\"2021-05-23 19:06:13\"}}]}}\n        //{\"took\":1,\"timed_out\":false,\"_shards\":{\"total\":16,\"successful\":16,\"failed\":0},\"hits\":{\"total\":0,\"max_score\":0.0,\"hits\":[]}}\n        System.out.println(res);\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONObject(\"hits\") != null);\n    }\n\n\n    /**\n     * /_search/scroll\n     * /_search/scroll/{scroll_id}\n     * @throws IOException\n     */\n    @Test\n    public void testRestSearchScrollController() throws IOException, InterruptedException {\n        //这里主要为了让定时器执行完毕， 刷新内存中的索引信息\n        Thread.sleep(3000L);\n        //TODO:houxiufeng 这里怎么传？\n        String formbody = \"{\\\"scroll\\\":\\\"1m\\\",\\\"scroll_id\\\":\\\"ZGMtZXMwMg==!MTIz\\\"}\";\n        //{\"error\":{\"root_cause\":[{\"type\":\"illegal_argument_exception\",\"reason\":\"Cannot parse scroll id\"}],\"type\":\"illegal_argument_exception\",\"reason\":\"Cannot parse scroll id\",\"caused_by\":{\"type\":\"array_index_out_of_bounds_exception\",\"reason\":\"arraycopy: last source index 50 out of bounds for byte[3]\"}},\"status\":400}\n        String res = HttpClient.forward(HOST + \"/_search/scroll\", \"POST\", formbody, headerParams, null);\n        System.out.println(res);\n    }\n\n\n    /**\n     * /_spatial_msearch\n     * /{index}/_spatial_msearch\n     * /{index}/{type}/_spatial_msearch\n     * @throws IOException\n     */\n    @Test\n    public void testRestSpatialMultiSearchController() throws IOException {\n        //TODO:houxiufeng 这个卡死，为什么。\n        String formbody = \"{\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[{\\\"term\\\":{\\\"name\\\":\\\"fitz4\\\"}},{\\\"term\\\":{\\\"age\\\":4}}]}}}\";\n        String res = HttpClient.forward(HOST+ \"/\" + INDEX_NAME + \"/_spatial_msearch\", \"POST\", formbody, headerParams, null);\n        System.out.println(res);\n    }\n\n    /**\n     * /_spatial_search\n     * /{index}/_spatial_search\n     * /{index}/{type}/_spatial_search\n     * @throws IOException\n     */\n    @Test\n    public void testRestSpatialSearchController() throws IOException {\n        //TODO:houxiufeng 这个也报错\n        String formbody = \"{\\\"query\\\":{\\\"bool\\\":{\\\"must\\\":[{\\\"term\\\":{\\\"name\\\":\\\"fitz4\\\"}},{\\\"term\\\":{\\\"age\\\":4}}]}}}\";\n        String res = HttpClient.forward(HOST+ \"/\" + INDEX_NAME + \"/_spatial_search\", \"POST\", formbody, headerParams, null);\n        //{\"error\":{\"root_cause\":[{\"type\":\"runtime_exception\",\"reason\":\"index config(index.spatial.s2data) not set\"}],\"type\":\"runtime_exception\",\"reason\":\"index config(index.spatial.s2data) not set\"},\"status\":500}\n        System.out.println(res);\n    }\n\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/rest/es/SqlTests.java",
    "content": "package com.didi.arius.gateway.rest.es;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.didi.arius.gateway.common.utils.HttpClient;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author fitz\n * @date 2021/6/10 2:55 下午\n */\n@RunWith(SpringRunner.class)\n@SpringBootTest\npublic class SqlTests {\n\n    private Map<String, String> headerParams;\n    private static String INDEX_NAME = \"cn_record.arius.template.value_2021-05\";\n    private static String HOST = \"http://127.0.0.1:8200\";\n\n    @Before\n    public void setUp() {\n//        String appid = \"100000000\";\n//        String appsecret = \"azAWiJhxkho33ac\";\n        String appid = \"5\";\n        String appsecret = \"helloworld\";\n        String token = Base64.getEncoder().encodeToString((appid + \":\" + appsecret).getBytes(StandardCharsets.UTF_8));\n        headerParams = new HashMap<>();\n        headerParams.put(\"Authorization\", \"Basic \" + token);\n        headerParams.put(\"CLUSTER-ID\", \"dc-es02\");\n    }\n\n    /**\n     * /_sql\n     * @throws IOException\n     */\n    @Test\n    public void testRestSQLController() throws IOException, InterruptedException {\n        //这里主要为了让定时器执行完毕， 刷新内存中的索引信息\n        Thread.sleep(2000L);\n        String sql = String.format(\"SELECT * from %s limit 1\" ,INDEX_NAME);\n        String res = HttpClient.forward(HOST+\"/_sql\", \"POST\", sql, headerParams, null);\n        System.out.println(res);\n        //{\"took\":1,\"timed_out\":false,\"_shards\":{\"total\":16,\"successful\":16,\"failed\":0},\"hits\":{\"total\":5,\"max_score\":1.0,\"hits\":[{\"_index\":\"cn_record.arius.template.value_2021-05\",\"_type\":\"_doc\",\"_id\":\"1\",\"_score\":1.0,\"_source\":{\"name\":\"fitz1\",\"age\":1,\"es_index_time\":1623132760300,\"timestamp\":\"2021-05-23 19:06:13\"}}]}}\n        JSONObject jsonObject = JSON.parseObject(res);\n        assertEquals(true, jsonObject.getJSONObject(\"hits\") != null);\n    }\n\n    /**\n     * /_sql/explain\n     * @throws IOException\n     */\n    @Test\n    public void testRestSQLExplainController() throws IOException, InterruptedException {\n        //这里主要为了让定时器执行完毕， 刷新内存中的索引信息\n        Thread.sleep(2000L);\n        String sql = String.format(\"SELECT * from %s limit 1\" ,INDEX_NAME);\n        String res = HttpClient.forward(HOST+\"/_sql/explain\", \"POST\", sql, headerParams, null);\n        //{\n        //  \"from\" : 0,\n        //  \"size\" : 1\n        //}\n        System.out.println(res);\n    }\n\n\n}\n"
  },
  {
    "path": "arius-gateway/arius-gateway-rest/src/test/java/com/didi/arius/gateway/util/CustomDataSource.java",
    "content": "package com.didi.arius.gateway.util;\n\nimport static com.didi.arius.gateway.common.metadata.AppDetail.RequestType.CLUSTER;\n\nimport com.didi.arius.gateway.common.consts.QueryConsts;\nimport com.didi.arius.gateway.common.metadata.AppDetail;\nimport com.didi.arius.gateway.common.metadata.BaseContext;\nimport com.didi.arius.gateway.common.metadata.ESCluster;\nimport com.didi.arius.gateway.common.metadata.IndexTemplate;\nimport com.didi.arius.gateway.common.metadata.QueryContext;\nimport com.didi.arius.gateway.common.metadata.TemplateClusterInfo;\nimport com.didi.arius.gateway.common.metadata.TemplateInfo;\nimport com.didi.arius.gateway.elasticsearch.client.ESClient;\nimport com.didi.arius.gateway.remote.response.AliasesInfoResponse;\nimport com.didi.arius.gateway.remote.response.AppDetailResponse;\nimport com.didi.arius.gateway.remote.response.AppListResponse;\nimport com.didi.arius.gateway.remote.response.BaseInfoResponse;\nimport com.didi.arius.gateway.remote.response.DSLTemplateListResponse;\nimport com.didi.arius.gateway.remote.response.DSLTemplateResponse;\nimport com.didi.arius.gateway.remote.response.DSLTemplateWrapResponse;\nimport com.didi.arius.gateway.remote.response.DataCenterListResponse;\nimport com.didi.arius.gateway.remote.response.DataCenterResponse;\nimport com.didi.arius.gateway.remote.response.DynamicConfigListResponse;\nimport com.didi.arius.gateway.remote.response.DynamicConfigResponse;\nimport com.didi.arius.gateway.remote.response.IndexTemplateListResponse;\nimport com.didi.arius.gateway.remote.response.IndexTemplateResponse;\nimport com.didi.arius.gateway.remote.response.MasterInfoResponse;\nimport com.didi.arius.gateway.remote.response.SlaveInfoResponse;\nimport com.didi.arius.gateway.remote.response.TempaletAliasResponse;\nimport com.didi.arius.gateway.remote.response.TemplateInfoListResponse;\nimport com.didi.arius.gateway.remote.response.TemplateInfoResponse;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport org.apache.http.Header;\nimport org.apache.http.message.BasicHeader;\n\n/**\n * @author wuxuan\n * @Date 2022/6/6\n */\npublic class CustomDataSource {\n    public static final String PHY_CLUSTER_NAME = \"gateway_test_1\";\n    public static final String CLUSTER_NAME = \"dc-es02\";\n    public static final String ip = \"127.0.0.0\" ;\n    public static final String INDEX_NAME = \"cn_record.arius.template.value\";\n    public static final String INDEX_NAME2 = \"cn_record.arius.template.value_2021-05\";\n    public static final String INDEX_NAME3 = \"cn_record.arius.template.value_2022-06\";\n    public static final String ALIAS = \"ALIAS\";\n    public static final int appid = 1;\n\n    public static AppListResponse appListResponseFactory() {\n        AppListResponse appListResponse = new AppListResponse();\n        appListResponse.setCode(1);\n        appListResponse.setMessage(\"message\");\n        appListResponse.setVersion(\"1.2.2\");\n        List<AppDetailResponse> data = new ArrayList<>();\n        data.add(appDetailResponseFactory());\n        appListResponse.setData(data);\n        return appListResponse;\n    }\n\n    public static AppDetailResponse appDetailResponseFactory() {\n        AppDetailResponse appDetailResponse = new AppDetailResponse();\n        appDetailResponse.setCluster(CLUSTER_NAME);\n        appDetailResponse.setQueryThreshold(1);\n        appDetailResponse.setId(appid);\n        appDetailResponse.setVerifyCode(\"789\");\n        List<String> ips = new ArrayList<>();\n        ips.add(ip);\n        appDetailResponse.setIp(ips);\n        return appDetailResponse;\n    }\n\n    public static BaseContext baseContextFactory() {\n        BaseContext baseContext = queryContextFactory();\n        baseContext.setAuthentication(\"Basic MTo3ODk=\");\n        baseContext.setAppid(appid);\n        baseContext.setAppDetail(appDetailFactory());\n        return baseContext;\n    }\n    public static AppDetail appDetailFactory() {\n        AppDetail appDetail = new AppDetail();\n        appDetail.setId(appid);\n        appDetail.setCluster(PHY_CLUSTER_NAME);\n        appDetail.setSearchType(CLUSTER);\n        List<String> ips = new ArrayList<String>();\n        ips.add(ip);\n        appDetail.setIp(ips);\n        List<String> windexexp =new ArrayList<>();\n        windexexp.add(INDEX_NAME);\n        windexexp.add(INDEX_NAME2);\n        List<String> indexexp =new ArrayList<>();\n        indexexp.add(INDEX_NAME);\n        indexexp.add(INDEX_NAME2);\n        appDetail.setWindexExp(windexexp);\n        appDetail.setIndexExp(indexexp);\n        appDetail.setIsRoot(0);\n        return appDetail;\n    }\n\n    public static DSLTemplateResponse dslTemplateResponseFactory(){\n        final DSLTemplateResponse dslTemplateResponse = new DSLTemplateResponse();\n        dslTemplateResponse.setKey(\"key\");\n        dslTemplateResponse.setAriusCreateTime(\"ariusCreateTime\");\n        dslTemplateResponse.setAriusModifyTime(\"ariusModifyTime\");\n        dslTemplateResponse.setResponseLenAvg(1.0);\n        dslTemplateResponse.setRequestType(\"requestType\");\n        dslTemplateResponse.setSearchType(\"searchType\");\n        dslTemplateResponse.setEsCostAvg(1.0);\n        dslTemplateResponse.setTotalHitsAvg(1.0);\n        dslTemplateResponse.setTotalShardsAvg(1.0);\n        dslTemplateResponse.setQueryLimit(1.0);\n        dslTemplateResponse.setEnable(false);\n        dslTemplateResponse.setCheckMode(\"checkMode\");\n        return dslTemplateResponse;\n    }\n\n    public static DynamicConfigResponse dynamicConfigResponseFactory(){\n        DynamicConfigResponse dynamicConfigResponse = new DynamicConfigResponse();\n        dynamicConfigResponse.setCreateTime(0L);\n        dynamicConfigResponse.setDimension(0L);\n        dynamicConfigResponse.setEdit(0L);\n        dynamicConfigResponse.setId(0L);\n        dynamicConfigResponse.setMemo(\"memo\");\n        dynamicConfigResponse.setStatus(0L);\n        dynamicConfigResponse.setUpdateTime(0L);\n        dynamicConfigResponse.setValue(\"{\\n\" +\n                \"    \\\"appids\\\":[\\n\" +\n                \"        1,\\n\" +\n                \"        2,\\n\" +\n                \"        3,\\n\" +\n                \"        4\\n\" +\n                \"    ],\\n\" +\n                \"    \\\"didi-123deMacBook-Pro.local\\\":true\\n\" +\n                \"}\");\n        dynamicConfigResponse.setValueGroup(\"valueGroup\");\n        dynamicConfigResponse.setValueName(QueryConsts.DETAIL_LOG_FLAG);\n        return dynamicConfigResponse;\n    }\n\n    public static DynamicConfigListResponse dynamicConfigListResponseFactory() {\n        DynamicConfigListResponse dynamicConfigListResponse = new DynamicConfigListResponse();\n        dynamicConfigListResponse.setCode(0);\n        List<DynamicConfigResponse> data = new ArrayList<>();\n        DynamicConfigResponse dynamicConfigResponse = CustomDataSource.dynamicConfigResponseFactory();\n        data.add(dynamicConfigResponse);\n        DynamicConfigResponse dynamicConfigResponseOne = CustomDataSource.dynamicConfigResponseFactory();\n        dynamicConfigResponseOne.setValueName(null);\n        data.add(dynamicConfigResponseOne);\n        DynamicConfigResponse dynamicConfigResponseTwo = CustomDataSource.dynamicConfigResponseFactory();\n        dynamicConfigResponseTwo.setValueName(QueryConsts.MAPPING_INDEXNAME_WHITE_APPIDS);\n        data.add(dynamicConfigResponseTwo);\n        DynamicConfigResponse dynamicConfigResponseThree = CustomDataSource.dynamicConfigResponseFactory();\n        dynamicConfigResponseThree.setValueName(QueryConsts.FORBIDDEN_SETTING_PATH);\n        data.add(dynamicConfigResponseThree);\n        DynamicConfigResponse dynamicConfigResponseFour = CustomDataSource.dynamicConfigResponseFactory();\n        dynamicConfigResponseFour.setValue(\"value\");\n        data.add(dynamicConfigResponseFour);\n        DynamicConfigResponse dynamicConfigResponseFive = CustomDataSource.dynamicConfigResponseFactory();\n        dynamicConfigResponseFive.setValue(\"{\\n\" +\n                \"    \\\"appids\\\":[\\n\" +\n                \"\\n\" +\n                \"    ]\\n\" +\n                \"}\");\n        data.add(dynamicConfigResponseFive);\n        dynamicConfigListResponse.setData(data);\n        return dynamicConfigListResponse;\n    }\n\n    public static QueryContext queryContextFactory(){\n        QueryContext queryContext = new QueryContext();\n        queryContext.setClusterId(\"clusterId\");\n        queryContext.setAppid(0);\n        queryContext.setClusterName(CLUSTER_NAME);\n        queryContext.setRequest(null);\n        queryContext.setChannel(null);\n        queryContext.setResponse(null);\n        queryContext.setIndices(Arrays.asList(\"value\"));\n        queryContext.setXUserName(\"xUserName\");\n        queryContext.setRestName(\"restName\");\n        queryContext.setClient(new ESClient(CLUSTER_NAME, \"version\"));\n        queryContext.setClientVersion(\"clientVersion\");\n        queryContext.setFromKibana(false);\n        queryContext.setNewKibana(false);\n        queryContext.setPreQueryEsTime(0L);\n        return queryContext;\n    }\n\n    public static IndexTemplate indexTemplateFactory(){\n        IndexTemplate indexTemplate = new IndexTemplate();\n        indexTemplate.setId(0);\n        indexTemplate.setName(INDEX_NAME);\n        indexTemplate.setDateField(\"dateField\");\n        indexTemplate.setDateFormat(\"dateFormat\");\n        indexTemplate.setExpireTime(0L);\n        indexTemplate.setExpression(\"expression\");\n        indexTemplate.setIsDefaultRouting(false);\n        indexTemplate.setVersion(0);\n        indexTemplate.setDeployStatus(IndexTemplate.DeployStatus.MASTER_AND_SLAVE);\n        TemplateClusterInfo masterInfo = new TemplateClusterInfo();\n        masterInfo.setAccessApps(new HashSet<>(Arrays.asList(0)));\n        masterInfo.setCluster(CLUSTER_NAME);\n        indexTemplate.setMasterInfo(masterInfo);\n        TemplateClusterInfo templateClusterInfo = new TemplateClusterInfo();\n        templateClusterInfo.setAccessApps(new HashSet<>(Arrays.asList(0)));\n        templateClusterInfo.setCluster(CLUSTER_NAME);\n        indexTemplate.setSlaveInfos(Arrays.asList(templateClusterInfo));\n        return indexTemplate;\n    }\n\n    public static DataCenterResponse dataCenterResponseFactory(){\n        DataCenterResponse dataCenterResponse = new DataCenterResponse();\n        dataCenterResponse.setId(0L);\n        dataCenterResponse.setCluster(CLUSTER_NAME);\n        dataCenterResponse.setReadAddress(\"readAddress\");\n        dataCenterResponse.setHttpAddress(\"httpAddress\");\n        dataCenterResponse.setWriteAddress(\"writeAddress\");\n        dataCenterResponse.setHttpWriteAddress(\"httpWriteAddress\");\n        dataCenterResponse.setDesc(\"desc\");\n        dataCenterResponse.setType(0);\n        dataCenterResponse.setEsVersion(\"esVersion\");\n        dataCenterResponse.setPassword(\"password\");\n        dataCenterResponse.setRunMode(1);\n        dataCenterResponse.setWriteAction(\"writeAction\");\n        return dataCenterResponse;\n    }\n\n    public static DataCenterListResponse dataCenterListResponseFactory(){\n        DataCenterListResponse dataCenterListResponse = new DataCenterListResponse();\n        List<DataCenterResponse> dataCenterResponses = new ArrayList<>();\n        DataCenterResponse dataCenterResponse = dataCenterResponseFactory();\n        dataCenterResponses.add(dataCenterResponse);\n        DataCenterResponse dataCenterResponseOne = dataCenterResponseFactory();\n        dataCenterResponseOne.setHttpAddress(null);\n        dataCenterResponses.add(dataCenterResponseOne);\n        DataCenterResponse dataCenterResponseTwo = dataCenterResponseFactory();\n        dataCenterResponseTwo.setEsVersion(null);\n        dataCenterResponses.add(dataCenterResponseTwo);\n        DataCenterResponse dataCenterResponseThree = dataCenterResponseFactory();\n        dataCenterResponseThree.setRunMode(0);\n        dataCenterResponses.add(dataCenterResponseThree);\n        dataCenterListResponse.setData(dataCenterResponses);\n        return dataCenterListResponse;\n    }\n\n    public static BaseInfoResponse baseInfoResponseFactory() {\n        BaseInfoResponse baseInfoResponse = new BaseInfoResponse();\n        baseInfoResponse.setExpireTime(1L);\n        baseInfoResponse.setExpression(\"expression*\");\n        baseInfoResponse.setIsDefaultRouting(true);\n        baseInfoResponse.setDeployStatus(1);\n        List<String> aliases = new ArrayList<>();\n        aliases.add(INDEX_NAME);\n        aliases.add(INDEX_NAME2);\n        aliases.add(ALIAS);\n        baseInfoResponse.setAliases(aliases);\n        baseInfoResponse.setIngestPipeline(\"ingestpipeline\");\n        baseInfoResponse.setId(1);\n        baseInfoResponse.setBlockRead(false);\n        baseInfoResponse.setDateField(\"datafiled\");\n        baseInfoResponse.setBlockWrite(false);\n        baseInfoResponse.setDateFormat(\"dataformat\");\n        baseInfoResponse.setVersion(1);\n        return baseInfoResponse;\n    }\n\n    public static MasterInfoResponse masterInfoResponseFactory(){\n        MasterInfoResponse masterInfoResponse = new MasterInfoResponse();\n        masterInfoResponse.setCluster(CLUSTER_NAME);\n        List<Integer> accessApps = new ArrayList<>();\n        accessApps.add(1);\n        accessApps.add(2);\n        masterInfoResponse.setAccessApps(accessApps);\n        masterInfoResponse.setTopic(\"topic\");\n        masterInfoResponse.setMappingIndexNameEnable(true);\n        Map<String, String> typeIndexMapping = new HashMap<>();\n        typeIndexMapping.put(CLUSTER_NAME,INDEX_NAME);\n        masterInfoResponse.setTypeIndexMapping(typeIndexMapping);\n        masterInfoResponse.setTemplateId(1L);\n        masterInfoResponse.setTemplateName(\"templateName\");\n        return masterInfoResponse;\n    }\n\n    public static List<SlaveInfoResponse> slaveInfoResponsesFactory() {\n        List<SlaveInfoResponse> slaveInfoResponses = new ArrayList<>();\n        SlaveInfoResponse slaveInfoResponse = new SlaveInfoResponse();\n        List<Integer> accessApps = new ArrayList<>();\n        accessApps.add(1);\n        accessApps.add(2);\n        slaveInfoResponse.setAccessProjects(accessApps);\n        slaveInfoResponse.setCluster(CLUSTER_NAME);\n        slaveInfoResponse.setTopic(\"topic\");\n        slaveInfoResponse.setMappingIndexNameEnable(true);\n        slaveInfoResponse.setTemplateId(1L);\n        slaveInfoResponse.setTemplateName(\"templateName\");\n        Map<String, String> typeIndexMapping = new HashMap<>();\n        typeIndexMapping.put(CLUSTER_NAME,INDEX_NAME);\n        slaveInfoResponse.setTypeIndexMapping(typeIndexMapping);\n        slaveInfoResponses.add(slaveInfoResponse);\n        return slaveInfoResponses;\n    }\n\n    public static IndexTemplateResponse indexTemplateResponseFactory(){\n        IndexTemplateResponse indexTemplateResponse = new IndexTemplateResponse();\n        indexTemplateResponse.setBaseInfo(baseInfoResponseFactory());\n        indexTemplateResponse.setMasterInfo(masterInfoResponseFactory());\n        indexTemplateResponse.setSlaveInfos(slaveInfoResponsesFactory());\n        return indexTemplateResponse;\n    }\n\n    public static IndexTemplateListResponse indexTemplateListResponseFactory(){\n        IndexTemplateListResponse indexTemplateListResponse = new IndexTemplateListResponse();\n        indexTemplateListResponse.setMessage(\"message\");\n        Map<String, IndexTemplateResponse> data = new HashMap<>();\n        IndexTemplateResponse indexTemplateResponse = indexTemplateResponseFactory();\n        data.put(\"key\",indexTemplateResponseFactory());\n        indexTemplateListResponse.setData(data);\n        indexTemplateListResponse.setCode(1);\n        indexTemplateListResponse.setVersion(\"1.3.2\");\n        return indexTemplateListResponse;\n    }\n\n    public static TemplateInfoResponse templateInfoResponseFactory(){\n        TemplateInfoResponse templateInfoResponse = new TemplateInfoResponse();\n        templateInfoResponse.setExpression(\"expression\");\n        templateInfoResponse.setId(1);\n        templateInfoResponse.setVersion(1);\n        templateInfoResponse.setAliases(aliasesFactory());\n        return templateInfoResponse;\n    }\n\n    public static TemplateInfoListResponse templateInfoListResponseFactory(){\n        TemplateInfoListResponse templateInfoListResponse = new TemplateInfoListResponse();\n        templateInfoListResponse.setMessage(\"message\");\n        Map<String, TemplateInfoResponse> data = new HashMap<>();\n        data.put(\"key\",templateInfoResponseFactory());\n        templateInfoListResponse.setData(data);\n        return templateInfoListResponse;\n    }\n\n    public static TemplateInfo templateInfoFactory(){\n        TemplateInfo templateInfo = new TemplateInfo();\n        templateInfo.setNeedSource(true);\n        templateInfo.setVersion(1);\n        return templateInfo;\n    }\n\n    public static TempaletAliasResponse tempaletAliasResponseFactory() {\n        TempaletAliasResponse tempaletAliasResponse = new TempaletAliasResponse();\n        tempaletAliasResponse.setVersion(\"version\");\n        tempaletAliasResponse.setMessage(\"messgage\");\n        tempaletAliasResponse.setCode(1);\n        tempaletAliasResponse.setData(true);\n        return tempaletAliasResponse;\n    }\n\n    public static List<AliasesInfoResponse> aliasesFactory() {\n        List<AliasesInfoResponse> aliases = new ArrayList<>();\n        AliasesInfoResponse aliasesInfoResponse = new AliasesInfoResponse();\n        aliasesInfoResponse.setName(CLUSTER_NAME);\n        aliases.add(aliasesInfoResponse);\n        return aliases;\n    }\n\n    public static ESClient esClientFactory() {\n        ESClient esClient = new ESClient();\n        esClient.setClusterName(CLUSTER_NAME);\n        esClient.addHttpHost(\"127.0.0.0\",8080);\n        List<Header> headers = new ArrayList<>();\n        Header header = new BasicHeader(\"name\",\"value\");\n        headers.add(header);\n        esClient.setHeaders(headers);\n        esClient.start();\n        return esClient;\n    }\n\n    public static ESCluster esClusterFactory() {\n        ESCluster esCluster = new ESCluster();\n        esCluster.setCluster(CustomDataSource.CLUSTER_NAME);\n        esCluster.setType(ESCluster.Type.INDEX);\n        esCluster.setEsVersion(QueryConsts.DEFAULT_ES_VERSION);\n        esCluster.setEsClient(esClientFactory());\n        return esCluster;\n    }\n\n    public static DSLTemplateListResponse dslTemplateListResponseFactory() {\n        DSLTemplateListResponse dslTemplateListResponse = new DSLTemplateListResponse();\n        DSLTemplateWrapResponse data = new DSLTemplateWrapResponse();\n        DSLTemplateResponse dslTemplateResponse = CustomDataSource.dslTemplateResponseFactory();\n        DSLTemplateResponse dslTemplateResponseOne = CustomDataSource.dslTemplateResponseFactory();\n        dslTemplateResponseOne.setKey(\"key——key\");\n        List<DSLTemplateResponse> dslTemplatePoList = new ArrayList<>();\n        dslTemplatePoList.add(dslTemplateResponse);\n        dslTemplatePoList.add(dslTemplateResponseOne);\n        data.setDslTemplatePoList(dslTemplatePoList);\n        data.setScrollId(\"scrollId\");\n        dslTemplateListResponse.setData(data);\n        return dslTemplateListResponse;\n    }\n\n    public static Map<String, IndexTemplate> indexTemplateMapFactory() {\n        Map<String, IndexTemplate>  indexTemplateMap = new HashMap<>();\n        indexTemplateMap.put(CustomDataSource.INDEX_NAME,indexTemplateFactory());\n        indexTemplateMap.put(CustomDataSource.INDEX_NAME2,indexTemplateFactory());\n        return indexTemplateMap;\n    }\n\n    public static Map<String, ESCluster> listESClusterFactory() {\n        Map<String, ESCluster> listESCluster = new HashMap<>();\n        listESCluster.put(\"key\",CustomDataSource.esClusterFactory());\n        ESCluster esCluster = CustomDataSource.esClusterFactory();\n        esCluster.setType(ESCluster.Type.SOURCE);\n        listESCluster.put(CLUSTER_NAME,esCluster);\n        return listESCluster;\n    }\n\n}"
  },
  {
    "path": "arius-gateway/arius-gateway-task/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.didi</groupId>\n        <artifactId>arius-gateway-v2</artifactId>\n        <version>0.0.1-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>arius-gateway-task</artifactId>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>com.didi</groupId>\n            <artifactId>arius-gateway-core</artifactId>\n            <version>${project.version}</version>\n            <exclusions>\n                <exclusion>\n                    <artifactId>elasticsearch-didi</artifactId>\n                    <groupId>org.elasticsearch</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "arius-gateway/arius-gateway-task/src/test/java/com/didi/arius/gateway/task/AriusGatewayTaskApplicationTests.java",
    "content": "package com.didi.arius.gateway.task;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@SpringBootTest\nclass AriusGatewayTaskApplicationTests {\n\n    @Test\n    void contextLoads() {\n    }\n\n}\n"
  },
  {
    "path": "arius-gateway/build.sh",
    "content": "#!/bin/bash\nworkspace=$(cd $(dirname $0) && pwd -P)/arius-gateway-rest\ncd $workspace\n\n## TODO const\nmodule=arius-gateway-rest\napp=$module\n\n# OE不再支持直接传递参数，使用环境变量\n# env=$1\nif [[ $# -ne 0 ]];then\n  env=$1\nfi\n\necho \"env is $env\"\n\ngitversion=.gitversion\ncontrol=./control.sh\nngxfunc=./nginxfunc.sh\n\n## function\nfunction build() {\n    # 进行编译\n    # cmd\n    JVERSION=`java -version 2>&1 | awk 'NR==1{gsub(/\"/,\"\");print $3}'`\n    major=`echo $JVERSION | awk -F. '{print $1}'`\n    mijor=`echo $JVERSION | awk -F. '{print $2}'`\n    if [ $major -le 1 ] && [ $mijor -lt 8 ]; then\n        export JAVA_HOME=/usr/local/jdk1.8.0_65  #(使用jdk8请设置)\n        export PATH=$JAVA_HOME/bin:$PATH\n    fi\n    # XXX 编译命令\n    cd ..\n    mvn -U clean package -Dmaven.test.skip=true\n\n    local sc=$?\n    if [ $sc -ne 0 ];then\n    \t## 编译失败, 退出码为 非0\n        echo \"$app build error\"\n        exit $sc\n    else\n        echo -n \"$app build ok, vsn=\"\n        gitversion\n    fi\n\n     cd $module\n}\n\nfunction make_output() {\n\t# 新建output目录\n\tlocal output=\"./output\"\n\trm -rf $output &>/dev/null\n\tmkdir -p $output &>/dev/null\n\n\t# 填充output目录, output内的内容 即为 线上部署内容\n\t(\n        cp -rf $control $output &&         # 拷贝 control.sh脚本 至output目录\n        cp -rf $ngxfunc $output &&\n        cp -rf ./APP_META $output &&\n        cp -rf ./APP_META/Dockerfile $output &&\n        mkdir $output/nginx && cp -rf ./APP_META/nginx/conf $output/nginx &&\n        mkdir $output/filebeat && cp -rf ./../filebeat/ $output/filebeat &&\n        mv target/${module}.jar output  #拷贝目标war包或者jar包等 至output目录下\n        echo -e \"make output ok.\"\n\t) || { echo -e \"make output error\"; exit 2; } # 填充output目录失败后, 退出码为 非0\n\n        (\n            if [[ \"x$env\" == \"xtest\" || \"x$env\" == \"xstable\" ]];then\n            cp -rf ./APP_META/DockerfileOffline $output/Dockerfile\n        fi\n        ) || { echo -e \"make offline output error\"; exit 2; } # 填充output目录失败后, 退出码为 非0\n\n\t\tmv output ../\n}\n\n## internals\nfunction gitversion() {\n    git log -1 --pretty=%h > $gitversion\n    local gv=`cat $gitversion`\n    echo \"$gv\"\n}\n\n\n##########################################\n## main\n## 其中,\n## \t\t1.进行编译\n##\t\t2.生成部署包output\n##########################################\n\n# 1.进行编译\nbuild\n\n# 2.生成部署包output\nmake_output\n\n# 编译成功\necho -e \"build done\"\nexit 0\n\n"
  },
  {
    "path": "arius-gateway/filebeat/filebeat-online.yml",
    "content": "filebeat.inputs:\n  - type: log\n    enabled: true\n    paths:\n      - /home/xiaoju/arius-gateway-rest/log/stats.log\n    fields:\n      flag: 'arius.gateway.join'\n    fields_under_root: true\n    exclude_lines: ['_arius_query']\n\n  - type: log\n    enabled: true\n    paths:\n      - /home/xiaoju/arius-gateway-rest/log/metrics.log\n    fields:\n      flag: 'cn_arius_gateway_metrics'\n    fields_under_root: true\n\n\nprocessors:\n  - drop_fields:\n      fields: [\"host\", \"ecs\",\"agent\",\"log\", \"input\"]\n      ignore_missing: true\n\n\nsetup.template.enabled: false\nsetup.ilm.enabled: false\n\n\noutput.elasticsearch:\n  hosts: [\"10.96.64.13:8060\"]\n  bulk_max_size: 1000\n  indices:\n    - index: \"arius.gateway.join\"\n      when.contains:\n        flag: \"arius.gateway.join\"\n    - index: \"cn_arius_gateway_metrics\"\n      when.contains:\n        flag: \"cn_arius_gateway_metrics\"\n  pipelines:\n    - pipeline: \"arius.gateway.join\"\n      when.contains:\n        flag: \"arius.gateway.join\"\n    - pipeline: \"cn_arius_gateway_metrics\"\n      when.contains:\n        flag: \"cn_arius_gateway_metrics\""
  },
  {
    "path": "arius-gateway/filebeat/filebeat-pre.yml",
    "content": "filebeat.inputs:\n  - type: log\n    enabled: true\n    paths:\n      - /home/xiaoju/arius-gateway-rest/log/stats.log\n    fields:\n      flag: 'arius.gateway.join'\n    fields_under_root: true\n    exclude_lines: ['_arius_query']\n\n  - type: log\n    enabled: true\n    paths:\n      - /home/xiaoju/arius-gateway-rest/log/metrics.log\n    fields:\n      flag: 'cn_arius_gateway_metrics'\n    fields_under_root: true\n\n\nprocessors:\n  - drop_fields:\n      fields: [\"host\", \"ecs\",\"agent\",\"log\", \"input\"]\n      ignore_missing: true\n\n\nsetup.template.enabled: false\nsetup.ilm.enabled: false\n\n\noutput.elasticsearch:\n  hosts: [\"10.96.64.13:8060\"]\n  bulk_max_size: 1000\n  indices:\n    - index: \"arius.gateway.join\"\n      when.contains:\n        flag: \"arius.gateway.join\"\n    - index: \"cn_arius_gateway_metrics\"\n      when.contains:\n        flag: \"cn_arius_gateway_metrics\"\n  pipelines:\n    - pipeline: \"arius.gateway.join\"\n      when.contains:\n        flag: \"arius.gateway.join\"\n    - pipeline: \"cn_arius_gateway_metrics\"\n      when.contains:\n        flag: \"cn_arius_gateway_metrics\""
  },
  {
    "path": "arius-gateway/filebeat/filebeat-test.yml",
    "content": "filebeat.inputs:\n  - type: log\n    enabled: true\n    paths:\n      - /home/xiaoju/arius-gateway-rest/log/stats.log\n    fields:\n      flag: 'arius.gateway.join'\n    fields_under_root: true\n    exclude_lines: ['_arius_query']\n\n  - type: log\n    enabled: true\n    paths:\n      - /home/xiaoju/arius-gateway-rest/log/metrics.log\n    fields:\n      flag: 'cn_arius_gateway_metrics'\n    fields_under_root: true\n\n\nprocessors:\n  - drop_fields:\n      fields: [\"host\", \"ecs\",\"agent\",\"log\", \"input\"]\n      ignore_missing: true\n\n\nsetup.template.enabled: false\nsetup.ilm.enabled: false\n\n\noutput.elasticsearch:\n  hosts: [\"10.96.64.13:8060\"]\n  bulk_max_size: 1000\n  indices:\n    - index: \"arius.gateway.join\"\n      when.contains:\n        flag: \"arius.gateway.join\"\n    - index: \"cn_arius_gateway_metrics\"\n      when.contains:\n        flag: \"cn_arius_gateway_metrics\"\n  pipelines:\n    - pipeline: \"arius.gateway.join\"\n      when.contains:\n        flag: \"arius.gateway.join\"\n    - pipeline: \"cn_arius_gateway_metrics\"\n      when.contains:\n        flag: \"cn_arius_gateway_metrics\""
  },
  {
    "path": "arius-gateway/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <groupId>com.didi</groupId>\n    <artifactId>arius-gateway-v2</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <packaging>pom</packaging>\n    <name>arius-gateway-v2</name>\n\n    <modules>\n        <module>arius-gateway-common</module>\n        <module>arius-gateway-core</module>\n        <module>arius-gateway-remote</module>\n        <module>arius-gateway-rest</module>\n        <module>arius-gateway-task</module>\n    </modules>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.2.11.RELEASE</version>\n        <relativePath />\n    </parent>\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n        <java.version>1.8</java.version>\n        <lucene.version>5.5.0.0.0.2-SNAPSHOT</lucene.version>\n        <es.version>2.3.3</es.version>\n        <log4j2.version>2.17.1</log4j2.version>\n        <kf-log.version>2.0.4</kf-log.version>\n        <kf-elasticsearch-sql.version>1.0.1</kf-elasticsearch-sql.version>\n        <kf-dsl-prase.version>1.0.1</kf-dsl-prase.version>\n        <kf-metrices.version>1.0.1</kf-metrices.version>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.springframework.boot</groupId>\n                    <artifactId>spring-boot-starter-logging</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.springframework.boot</groupId>\n                    <artifactId>spring-boot-starter-logging</artifactId>\n                </exclusion>\n            </exclusions>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-log4j2</artifactId>\n            <exclusions>\n                <exclusion>\n                    <artifactId>log4j-to-slf4j</artifactId>\n                    <groupId>org.apache.logging.log4j</groupId>\n                </exclusion>\n                <exclusion>\n                    <artifactId>log4j-slf4j-impl</artifactId>\n                    <groupId>org.apache.logging.log4j</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.lmax</groupId>\n            <artifactId>disruptor</artifactId>\n            <version>3.3.4</version>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.httpcomponents</groupId>\n            <artifactId>httpasyncclient</artifactId>\n            <version>4.1.4</version>\n            <exclusions>\n                <exclusion>\n                    <groupId>org.apache.httpcomponents</groupId>\n                    <artifactId>httpclient</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <dependency>\n            <version>${kf-log.version}</version>\n            <groupId>io.github.knowstack</groupId>\n            <artifactId>kf-log</artifactId>\n        </dependency>\n    </dependencies>\n\n    <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <groupId>javax.servlet</groupId>\n                <artifactId>javax.servlet-api</artifactId>\n                <version>3.0.1</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.commons</groupId>\n                <artifactId>commons-io</artifactId>\n                <version>1.3.2</version>\n            </dependency>\n            <dependency>\n                <groupId>net.sf.ehcache</groupId>\n                <artifactId>ehcache</artifactId>\n                <version>2.10.1</version>\n            </dependency>\n            <dependency>\n                <groupId>io.dropwizard.metrics</groupId>\n                <artifactId>metrics-core</artifactId>\n                <version>3.1.0</version>\n            </dependency>\n            <dependency>\n                <groupId>com.google.code.gson</groupId>\n                <artifactId>gson</artifactId>\n                <version>2.8.9</version>\n            </dependency>\n            <dependency>\n                <groupId>com.google.guava</groupId>\n                <artifactId>guava</artifactId>\n                <version>23.0</version>\n            </dependency>\n            <dependency>\n                <groupId>commons-beanutils</groupId>\n                <artifactId>commons-beanutils</artifactId>\n                <version>1.9.4</version>\n            </dependency>\n            <dependency>\n                <groupId>commons-collections</groupId>\n                <artifactId>commons-collections</artifactId>\n                <version>3.2.2</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.commons</groupId>\n                <artifactId>commons-lang3</artifactId>\n                <version>3.4</version>\n            </dependency>\n            <dependency>\n                <groupId>commons-lang</groupId>\n                <artifactId>commons-lang</artifactId>\n                <version>2.6</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.httpcomponents</groupId>\n                <artifactId>httpclient</artifactId>\n                <version>4.5.13</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>commons-codec</groupId>\n                        <artifactId>commons-codec</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n            <dependency>\n                <groupId>commons-codec</groupId>\n                <artifactId>commons-codec</artifactId>\n                <version>1.13</version>\n            </dependency>\n            <dependency>\n                <groupId>com.alibaba</groupId>\n                <artifactId>fastjson</artifactId>\n                <version>1.2.70</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.elasticsearch</groupId>\n                <artifactId>elasticsearch</artifactId>\n                <version>${es.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>io.github.knowstack</groupId>\n                <artifactId>kf-elasticsearch-sql</artifactId>\n                <version>${kf-elasticsearch-sql.version}</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>org.elasticsearch</groupId>\n                        <artifactId>elasticsearch</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n            <dependency>\n                <groupId>org.elasticsearch.client</groupId>\n                <artifactId>elasticsearch-rest-client</artifactId>\n                <version>6.6.1</version>\n                <exclusions>\n                    <exclusion>\n                        <artifactId>commons-logging</artifactId>\n                        <groupId>commons-logging</groupId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <!-- 依赖DSL 解析模块 -->\n            <dependency>\n                <version>${kf-dsl-prase.version}</version>\n                <groupId>io.github.knowstack</groupId>\n                <artifactId>kf-dsl-prase</artifactId>\n                <exclusions>\n                    <exclusion>\n                        <artifactId>elasticsearch</artifactId>\n                        <groupId>org.elasticsearch</groupId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.nlpcn</groupId>\n                        <artifactId>elasticsearch-sql</artifactId>\n                    </exclusion>\n                    <!--如果不排除下面两个，日志打印不出来，有配置冲突 -->\n                    <exclusion>\n                        <groupId>org.slf4j</groupId>\n                        <artifactId>slf4j-api</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>org.slf4j</groupId>\n                        <artifactId>slf4j-log4j12</artifactId>\n                    </exclusion>\n\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <version>${kf-metrices.version}</version>\n                <groupId>io.github.knowstack</groupId>\n                <artifactId>kf-metrices</artifactId>\n                <exclusions>\n                    <exclusion>\n                        <artifactId>log4j</artifactId>\n                        <groupId>log4j</groupId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>commons-beanutils</groupId>\n                        <artifactId>commons-beanutils</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <groupId>commons-collections</groupId>\n                        <artifactId>commons-collections</artifactId>\n                    </exclusion>\n                    <exclusion>\n                        <artifactId>commons-logging</artifactId>\n                        <groupId>commons-logging</groupId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-1.2-api</artifactId>\n                <version>${log4j2.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-core</artifactId>\n                <version>${log4j2.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-api</artifactId>\n                <version>${log4j2.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-slf4j-impl</artifactId>\n                <version>${log4j2.version}</version>\n            </dependency>\n\n            <dependency>\n                <groupId>org.apache.logging.log4j</groupId>\n                <artifactId>log4j-jcl</artifactId>\n                <version>${log4j2.version}</version>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n\n\n</project>"
  },
  {
    "path": "doc/ElasticSearch最佳实践.md",
    "content": "结合滴滴内部对ES的使用经验，总结了一些最佳实践，主要分为：索引生成、mapping设置、查询优化、写入优化、集群运维。\n\n\n\n# 1.索引生成\n\n\n\n## 1.1 推荐使用索引模板\n\n日志检索&安全分析、交易明细数据多维度近实时检索场景，建议创建索引模板进行业务表达，采用时间进行分区， 一般按天、按月、按年创建。如A为用户申请时的索引模板名称，选择按月保存，实际存储的索引为A_202212。按时间分区创建可以避免单个索引过大、基于生命周期，提供索引预创建、索引快速恢复、历史数据快速删除等功能。\n\n## 1.2 禁止按天创建长期保存的索引\n\n对于保存周期在90天以上的索引，建议不按天分区创建，必须按月分区创建。长期保存索引，按天创建会导致集群中索引数量膨胀，间接导致集群 shard 过多，元数据膨胀，影响集群稳定性，拖慢集群重启恢复速度。\n\n## 1.3 不建议索引不分区\n\n建议索引实际保存时按照业务时间进行分区，不建议不分区。不分区索引随着数据写入的增加，超过预估容量之后会导致写入变慢，索引扩容迁移恢复均有很多问题，影响业务使用。\n\n\n\n# 2.Mapping设置\n\n\n\n## 2.1 不建议日志检索场景下对message做全文检索\n\n日志场景下 message 用于保存日志原文，一般可以对message做特定字段的清洗用于检索，如：traceId、actionName，不建议对message 进行全文索引，由于 message 字段的不确定性，全文索引情况下会导致相应的 Terms 膨胀，会耗费大量内存、存储空间，以及写入性能的快速下降。\n\n## 2.2 不建议随意增加mapping字段\n\nES 的free schema 特性支持动态修改mapping的能力，用户数据写入到 ES 场景下，将数据以json 的格式写入 ES 中，可以随意增加json的属性，自动的变更 mapping 信息，如果写入的json的属性不固定，会导致 ES 中索引 mapping 的属性字段膨胀，进一步影响集群稳定性。建议用户在自己写入数据到ES中时，要定义好自己的 mapping 信息，在动态 mapping 特性下，管理好写入ES的数据类型。\n\n## 2.3 建议对字段按需做分词检索\n\n写入 ES 的数据，建议用户根据实际需要对字段做分词检索，对于没有检索需要的字段建议在mappinbg 不设置分词和全文检索，对应字段的”index“设置为no，这样可以节省大量成本。\n\n## 2.4 建议对字段按需做聚合\n写入 ES 的数据，建议用户根据实际需要对字段做聚合，对于没有聚合需要的字段建议在mapping 中 \"doc_values\" 设置为false，这样可以节省大量成本。\n\n## 2.5 字段值为数值时索引类型的选择\nES的动态映射是根据字段值内容进行映射，例如status=1会自动映射为long类型，name=\"es\"会自动映射为keyword类型。\n\nES中不同的索引类型底层使用不同的数据结构。数值类型long，integer使用BKD作为底层存储数据结构，数值类型适合范围查询但不适合key=value的精确查询，如果对数值类型的字段进行精确查询会**消耗大量CPU进行bitset构建**。字符串类型keyword使用FST和SkipList作为底层存储数据结构，字符串类型适合key=value的精确查询，符合过滤条件的文档id集合已经存储到倒排链表中不需要实时构建bitset。\n\n**特别注意：mysql字段中用于存储可枚举值的数值类型，像字段名为status、xxx_type应该使用keyword作为ES的索引类型，而不是long类型**。\n\n\n\n\n\n# 3.查询优化\n\n\n\n## 3.1 不建议带\\*查询\n\nES 搜索时，支持索引的前缀带\\*匹配，如：abc\\*，会匹配的所有 abc 开头的索引，abc_201501~ abc_201901都会被查询到，如果再带上复杂查询条件，则会进行全表扫描，很容易把 ES 查挂。\n\n所以在查询的过程中不建议带\\*查询，直接\\*查询更是被 KnowSearch 网关直接禁止，建议在查询的过程中使用实际索引名称，如：select * from abc_201901; select * from abc_201901, abc_201902;\n\n## 3.2 不建议复杂的聚合查询\n\nES 的聚合查询需要在内存中将符合条件的文档进行排序或者聚合。在数据量非常大，聚合查询又很复杂的情况下，需要耗费大量内存，很容易直接把 ES 的内存撑爆。KnowSearch Gateway 和高版本的ES对聚合查询的内存都会做监控，如果发现耗费内存过大会直接禁止查询。请谨慎使用 ES 的 aggs(aggregations) 查询，对应sql是group by关键字，**尤其是cardinality高基数和script查询**，对内存消耗大，容易出现性能问题。\n\n## 3.3 不建议查询命中过多的数据\nES 每次查询都会返回该次查询的全部命中结果，这会导致需要命中全部的数据，有些情况下还要对这些数据进行打分排序，造成整体性能缓慢。\n\n比如不带过滤条件的查询，查询列表等，如何查询列表还带上排序条件，性能会下降的更加严重。这些查询即使加上 limit 条件，也会很慢，limit 只是返回的数据加了限制，并不影响查询过程。\n\n## 3.4 建议查询的条件中带上路由字段\nES 文档在写入的时候可以指定 routing 字段，查询的时候在查询条件中带上 routing，提升查询速度。\n如：可以使用 abc.id 作为 abc 索引的 routing 字段，查询条件中带 abc.id，select * from abc_201901 where abc.id=123 and abc.pasanger_id=123 group by abc.driver_id;\n\nES 在查询时会根据 routing 字段先定位到具体的 shard，然后在该 shard 上做具体的过滤和聚合，避免遍历索引所在的所有 shard，提升查询效率。\n\n## 3.5 不建议在大容量索引上进行复杂查询\n目前有些索引容量特别大，甚至超过了千亿条记录，在这样的索引上查询时，需要特别注意查询的复杂程度，过滤条件命中的数据很多时，会查询的特别慢，甚至超过默认超时时间，而且这样的索引shard会非常多，一个查询会需要很多资源开销。\n\n大容量索引的查询请注意查询语句的优化，选择最合理的查询方式，主要原则是尽量缩小查询范围，进行快速的数据裁剪\n\n## 3.6 查询语句建议选择合适的排序方式，默认建议按_doc排序\nES 默认按照 score 排序，会对每条记录计算分数，按分数从高到底排序。如果对排序没有依赖的用户，可以使用按内部 _doc 顺序排序，可以避免打分环节。按其他字段排序的话，查询会更慢，每条记录会去 DocValues 中获取记录对应的排序字段值，该次查询可能触发 IO 操作，造成更慢的性能。\n\n按照_doc排序的DSL和SQL语法如下：\n\nDSL：\n\n```\n\"sort\": [\n  {\n   \"_doc\": {\n    \"order\": \"asc\"\n   }\n  }\n ]\n```\n\nSQL：ORDER BY _doc\n\n## 3.7 关于timeout的设置\n\n1、ES 查询参数中的 timeout 关键字，作用于单个 shard 的超时。即单个 shard 的查询超过timeout 时间，则直接返回该时间段内的查询结果。这时候的结果可能是不完整的，用户需要关心查询是否触发了timeout。在查询的返回结果中，timed_out 告知了用户是否超时，false表示没有超时。true表示超时，此时需要注意查询结果是否不完整。如下示例，timed_out=false，表示查询没有超时。\n\n```\n{\n  \"took\": 9,\n  \"timed_out\": false,\n  \"_shards\": {\n    \"total\": 12,\n    \"successful\": 12,\n    \"failed\": 0\n  },\n  \"hits\": {\n\t...\n  }\n}\n```\n\nES 默认的 timeout 一般是5s-10s，在进行大规模查询的时候，可能触发 timeout，用户可以在查询参数中指定 timeout，具体见：https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html ，sql接口也支持timeout设置。\n\n2、KnowSearch 的 Gateway支持 timeout 设置，该 timeout 参数表示请求ES的超时时间，超过timeout 值，则直接返回客户端 timeout。Gateway 的具体参数名称为：socket_timeout ，最大为120s。\n\n3、客户端自行设置的 timeout，这个根据每个语言的sdk，用户可以自行设置，该 timeout 只作用于客户端，但是 Gateway 以及 ES 内部可能还未超时，还会继续计算，所以客户端超时请谨慎设置。建议根据查询复杂程度设置相应的超时时间。\n\n## 3.8 关于search结果是否完整的判断\n\nES search返回结果如下：\n\n```\n{\n  \"took\": 9,\n  \"timed_out\": false,\n  \"_shards\": {\n    \"total\": 12,\n    \"successful\": 12,\n    \"failed\": 0\n  },\n  \"hits\": {\n\t...\n  }\n}\n```\n\n要确认search结果正常，除了返回如上的查询结果，还需要确认以下两点：\n1、**timed_out是否为false，**关于timed_out说明，请参见：3.8 关于timeout的设置。\n2**、_shards里结果的failed是否为0**，如果不为0，说明有部分shard查询失败，不为0时，会附带上异常说明。\n\n## 3.9 关于terms查询个数\n\n建议terms查询语法如下，其中Value的个数建议在100个以内。\n\n## 3.11 关于wildcard查询建议\n\n1、限制 wildcard 字符串长度\n建议 wildcard 查询的字符串字符串长度进行限制，不能超过20个字。\n\n2、限制 wildcard 不要前缀传递\\*号。\n前缀传递\\*号，ES 会遍历全部索引匹配是否命中，这种方式效率非常低，消耗资源非常大，难以利用ES的高效索引查询，建议不要前缀带*查询。\n\n3、考虑用全文检索替代 wildcard 查询\nES支持全文检索，查询效率会 wildcard 查询效率高出非常多。全文检索的字段类型介绍见：https://www.elastic.co/guide/en/elasticsearch/reference/current/text.html\n\n## 3.12 关于滚动(scroll)查询建议\n\n由于滚动 (scroll) 查询时查询上下文 (SearchContext) 需要等到 scroll 完成或 scroll 超时才释放查询上下文占用 ES 内存资源，因此禁止将 scroll 超时时间设置得非常大(大于5分钟)，建议在1分钟左右或者在 scroll 用完后主动调用 clear 接口释放占用资源。\n\n## 3.13 精确匹配字段类型的建议\n精确匹配字段类型的建议设置成 keyword，范围查询字段类型设置成number(integer/long/double/float等)。\n\n## 3.14  查询抖动与GC建议\n\nLucene 并不是为低延迟而设计的系统，查询毛刺主要受 GC 和 IO 的影响，GC 层面在于合理的规划JVM内存，避免频繁 GC 和 FGC，IO 层面的可以考虑使用 SSD，RAMDISK 或预留足够的 pagecache来解决\n\n\n\n# 4.写入优化\n\n\n\n## 4.1 用bulk写入\n建议用bulk写入，一批bulk的数量不易太多，需要根据服务器配置以及doc大小给出一个合理的值，如不清楚可以暂时给个1000或者doc到2MB，bulk size 5-15M/s，如果数据节点配置很低，可以适当调低为1-10M/s\n\n1,000 到 5,000 个文档作为一个批次, 如果你的文档非常大，那么就减少批量的文档个数\n\n【避免】一个bulk里写多个索引\n\n## 4.2 多线程写入\n多线程能提高写入的性能，但线程不易太多\n\n## 4.3 唯一id\n不需要唯一id的，写入不要指定唯一id，让es自动生成id，这样可以避免version和id的检查，提升性能\n\n**version 号**来确保 应用中相互冲突的变更不会导致数据丢失。我们通过指定想要修改文档的 version 号来达到这个目的\n\n## 4.4 translog\n极端情况下比如断电允许丢点数据的，建议translog同步刷磁盘改异步\n\n## 4.5 刷新时间和写入buffer\n适当可以调大refresh_time和写入buffer\n\n\n\n\n\n# 5.集群运维\n\n\n## 5.1 容量预估\n\n1、每1GB堆内存对应集群分片在20-25之间，具有30GB堆内存的节点最多可以有600-750个分片，单集群Shard数不建议超过3万。\n\n2、10TB磁盘数据量，其对应的FST内存占用量在10GB~15GB，**原文与索引文件膨胀比一般在1:3。**\n\n3、**日志场景单Shard 50GB(内存磁盘比1:50)，搜索场景20GB(1:10)，单节点数据建议控制在2TB以内，最大不要超过5TB**。\n\n4、堆内存不足可能的因素比较多：Open 的索引过多导致 FST 占用空间过大（一般1TB的磁盘数据，需要 2- 5GB 左右的FST内存开销，这个只是FST常驻内存的开销）、聚合占用了大量内存、Netty 层占用大量内存，根据自己的业务特点，合理规划JVM 内存空间。\n\n5、当集群规模较大时（数据节点>5），建议预留独立实例用于承担Master/Client角色，当存在离线批量导入时，建议ClientNode进行读写分离\n\n## 5.2 节点问题\n\n1、节点负载不均：是否存在因为Routing导致的数据未均衡分配？是否存在大索引Shard个数较少且不是数据节点整数倍导致的Shard分配热点？是否存在大规模指定ID的写入或更新导致的负载过高？是否存在Shard数据搬迁导致的负载压力过高？\n\n2、节点丢失：是否存在复杂查询导致节点FullGC？通过KnowSearch观测下节点Segments内存占用情况，同时如果Master中有明确某个数据节点或者Client节点异常（搜索pending node、timeout等），访问该节点查看日志具体原因\n"
  },
  {
    "path": "doc/KnowSearch-GateWay设计文档.md",
    "content": "# \t\t\t\t\t\t\t\t\tGateway设计文档\n\n# 1.功能概述\n\n​\t\tGateway是ES的数据网关，它提供了完全适配原生 ES RestClient 的接口功能，同时还提供了一些附加功能，如：查询/写入限流、权限校验、ES 版本兼容、跨集群访问。通过统一网关的建设，用户对 ES 的查询写入行为得到了监控和有效的控制，从而为后续索引级权限校验、集群跨版本升级、版本兼容、DSL 分析、查询写入限流提供了基础。\n\n# 2.架构\n\n<img src=\"./file/KnowSearch-GateWay-Architecture.png\" style=\"zoom:50%;\" />\n\n# 3.前置概念\n\nGateway的三种访问模式\n\n- 索引模式：会检验ES_USER以及模板相关权限（请求得带上索引模板），然后根据模板对应的具体集群进行请求路由\n- 集群模式：会检验ES_USER以及模板相关权限（请求得带上索引模板），然后根据模板指定的集群进行请求路由\n\n- 原生模式：会检验ES_USER，然后会根据ES_USER指定的集群路由请求，除了要加上ES_USER外其他跟直接访问ES没区别\n\n\n\n三种模式的平台操作路径\n\n- 应用管理-访问设置-新增ES_USER-选择访问模式\n\n<img src=\"./file/KnowSearch-GateWay-Mode.png\" style=\"zoom:50%;\" />\n\n使用上面申请的ES_USER/ES_SECRET，在HTTP头域中增加ES_USER/ES_SECRET信息，即可按照指定模式访问Gateway。\n\n\n\nGateway中的特殊处理逻辑\n\n- Gateway通过filebeats将访问统计日志写入KnowSearch元数据集群，在Admin中对KnowSearch元数据集群Gateway访问日志进行统计分析，形成网关看板的指标数据\n\n- Gateway索引模式、集群模式下的bulk和index写都是采用DiDi-7.6.0-1400引擎的pipeline，注意📢：这里的bulk写的pipeline是bulk中的第一条数据为准，所以如果bulk中写不同的索引的话可能引发日期错乱的这种情况，所以索引模式下通过gateway bulk写的话，一批bulk必须是同一个索引\n\n- Gateway索引模式下、集群模式下并不是所有ES的命令都支持，但是原生模式是支持的\n\n- Gateway拉取admin的元数据，目前是全量拉取，每隔1分钟会拉取一次\n\n- Gateway索引模式、集群模式下的bulk和update以及delete对时间格式的处理上会有所不同，bulk使用pipeline处理的，update和delete是gateway里面处理的，pipeline只支持一种时间格式，update支持多种时间格式，有这么一个区别要注意下\n\n\n\n# 4.DiDi-7.6.0-1400引擎pipeline处理逻辑\n\narius平台的每一个模板，都会对应一个pipeline，这个pipeline主要做3件事\n\n- 对写入的索引，根据时间字段以及类型，加上对应的时间后缀【原索引admin，经过pipeline处理后变成admin_2020-01-10】\n- 对写入进行限流，例如下面就是限流每秒100万，注意这个限流是单机限流\n- 过期的数据丢掉，例如下面就是60天之前的数据丢弃，还有默认未来3天后的数据也会丢弃\n\n默认的逻辑\n\n- 写入的时间字段格式要和pipeline一一对应\n- 如果写入数据的时间字段格式和pipeline配置对不上，那么不会报错，会写入到当天索引\n\n```\n{\n  \"arius_stats_dashboard_info\" : {\n    \"description\" : \"arius_stats_dashboard_info\",\n    \"processors\" : [\n      {\n        \"throttle\" : {\n          \"rate_limit\" : 1000000\n        },\n        \"index_template\" : {\n          \"index_version\" : 0,\n          \"field\" : \"timestamp\",\n          \"index_name_format\" : \"_yyyy-MM\",\n          \"expire_day\" : 60,\n          \"field_format\" : \"UNIX_MS\"\n        }\n      }\n    ]\n  }\n}\n```\n\n\n\n# 5.层级代码\n\ngateway接受请求的方式，参考了es的代码，用的netty去处理的\n\ngateway的代码层级\n\n- Arius-gateway-common       通用层，一些工具实体类\n- Arius-gateway-core               业务处理层\n- Arius-gateway-remote          第三方服务，目前是空\n- Arius-gateway-rest                rest请求入口\n- Arius-gateway-task               目前是空\n\n\n\n# 6.gateway初始化\n\n![GateWay-初始化](./file/KnowSearch-GateWay-Initial.png)\n\n# 7.核心功能\n\n## 7.1dsl限流\n\n- 获取dsl模板元数据信息\n- 解析查询dsl模板，限流校验\n- 本地内存记录查询dsl模板的详细统计信息\n- 每隔一分钟上报dsl模板信息到元数据集群\n\n## 7.2日志上报\n\n- 查询写入请求过来\n- 把请求的日志串一起放到joincontext中\n- 请求结束，将日志打印到文件中\n- filebeat自动采集日志到元数据集群\n- Gateway指标相关就能展示了\n\n## 7.3管控限流\n\n- es_user层面的读取限流\n- es_user层面的模板管控\n\n# 8.读写流程\n\n## 8.1 读时序\n\n<img src=\"./file/KnowSearch-GateWay-Read-Sequence.png\" style=\"zoom:50%;\" />\n\n## 8.2 读流程\n\n<img src=\"./file/KnowSearch-GateWay-Read-Process.png\" style=\"zoom:50%;\" />\n\n## 8.3 写时序\n\n<img src=\"./file/KnowSearch-GateWay-Write-Sequence.png\" style=\"zoom:50%;\" />\n\n## 8.4 写流程\n\n<img src=\"./file/KnowSearch-GateWay-Write-Process.png\" style=\"zoom:50%;\" />\n\n\n\n# 9.异常\n\n## 9.1 Gateway查询相关的异常\n\n| 异常                       | http错误码 | 说明                                                         | 解决方法                                          |\n| :------------------------- | :--------- | :----------------------------------------------------------- | :------------------------------------------------ |\n| UriNotFoundException       | 404        | 查询gateway的uri不对，gateway仅支持ES查询相关的方法，其他方法会返回该错误 | 确认需求的合理性                                  |\n| UnauthorizedException      | 401        | 认证信息不正确                                               | 确认es_user对应的pass是否正确                     |\n| SQLNotPermittedException   | 403        | Gateway只支持SELECT的SQL，其他的SQL语句会返回该异常          | 确认是否需要其他SQL的支持，以及如何支持           |\n| QueryDslLengthException    | 400        | 查询的DSL语句超过指定长度，目前设置的长度上限是10M           | 应用方确认查询语句过长原因，调整需求              |\n| InvalidParameterException  | 400        | 传递的参数不合理，错误时会附加描述信息，告知是哪部分的错误   | 应用根据错误提示，结合Gateway文档确认参数异常问题 |\n| InvalidAppInfoException    | 400        | appid不存在                                                  | 确认认证信息是否有异常                            |\n| IndexNotPermittedException | 403        | 每个appid都只能访问该appid指定访问的索引列表，如果出现访问的索引不在允许的索引列表中，就会返回IndexNotPermittedException | 确认是否要增加该索引的访问权限                    |\n| IllegalArgumentException   | 400        | 例如java.lang.IllegalArgumentException: No feature for name [_search] 请求的uri=//_search，没有传入索引名称 | 修改索引名称                                      |\n| FlowLimitException         | 503        | 查询ES索引频率过高，被gateway限流，会出现部分访问失败，返回FlowLimitException，随着访问频率不断增高，限流概率会越来越大 | 讨论访问的qps，确认是否要增大限流参数             |\n| DslRateLimitException      | 400        | gateway dsl审核功能，会对用户的查询访问进行限流，用户查询时会报出DslRateLimitException | 确认需求的合理性                                  |\n| DslForbiddenException      | 403        | gateway dsl审核功能，会禁止某些异常的查询访问，用户查询时会报出DslForbiddenException | 确认需求的合理性                                  |\n| AggsParseException         | 400        | gateway会禁止掉对基数过大的字段做聚合查询，报出AggsParseException的异常， 复杂的聚合查询会导致ES数据节点、查询节点内存打满，而影响正常使用，需要禁止该复杂查询。 | 确认需求的合理性                                  |\n| AccessForbiddenException   | 403        | 禁止访问ES索引数据，一般是没带上认证信息导致的异常           | 申请认证信息，或者确认认证信息如何生效            |\n\n## 9.2 ES查询相关的异常\n\n| 异常                          | http错误码 | 说明                                                         | 失败范围                  | 解决方法                                                     |\n| :---------------------------- | :--------- | :----------------------------------------------------------- | :------------------------ | :----------------------------------------------------------- |\n| 异常                          | http错误码 | 说明                                                         | 失败范围                  | 解决方法                                                     |\n| EsRejectedExecutionException  | 429        | 查询过于频繁，es拒绝该查询请求                               | shard级别，会返回部分数据 | 应用方确认是否查询频率过大，或者查询语句过于复杂，阻塞了其他的查询 |\n| SearchParseException          | 400        | 查询的dsl语句不合法                                          | 整体失败                  | 应用方确认查询的语句异常                                     |\n| NoNodeAvailableException      | 503        | ES节点全部离线，持续出现该问题是非常严重的，应用需及时跟Arius团队联系 | 整体失败                  | 确认配置的节点信息，定位出现该异常的原因                     |\n| IndexNotFoundException        | 404        | 查询的索引不存在                                             | 整体失败                  |                                                              |\n| SearchPhaseExecutionException | 503        | 查询语句异常，例如NumberFormatException[For input string: \"210_28647510026308815217104323841494461\"]传入的参数不为数字 | 整体失败                  | 应用方确认查询的语句异常                                     |\n| ElasticsearchParseException   | 400        | 查询语句异常，ElasticsearchParseException[failed to parse date field [NaN-0NaN-0NaN 0NaN:0NaN:0NaN] with format [yyyy-MM-dd HH:mm:ss]] | 整体失败                  | 应用方确认查询的语句异常                                     |\n| QueryPhaseExecutionException  | 500        | QueryPhaseExecutionException[Result window is too large, from + size must be less than or equal to: [10000] but was [10050]查询语句中from+size的值大于最大窗口值1万条 | 整体失败                  | 如果要获取超过1万条之后的数据，需要使用scroll方式            |"
  },
  {
    "path": "doc/KnowSearch安装部署文档.md",
    "content": "# 前言\n\n + 本文以Centos7系统为例，系统基础配置要求：4核8G\n + 本文以0.3.1.2版本为例进行部署，按照本文可以快速部署一套单机模式的KnowSearch环境\n + 部署完成后可以通过浏览器输入IP:PORT进行访问，默认用户名密码: admin/admin123\n + shell部署方式支持分布式，具体方式可以参考安装包中的README文档\n + 安装完成后可以通过构造测试数据来体验产品功能（参考第三部分）\n\n# 软件版本及依赖\n| 软件名 | 版本要求 | 默认端口 |\n| ------ | ------ | ------ |\n| Mysql | v5.7+ | 3306 |\n| Elasticsearch | 软件包中的固定版本 | 8060 |\n| Grafana | v8.5.9 | 3000 |\n| JDK | v8+ | - |\n|  Centos| v6+ | - |\n| Ubuntu| v16+ | - |\n# 部署方式选择\n\n+ SHELL方式部署\n\n+ 根据文档手动部署\n\n# 一、SHELL部署\n## 1.1 快速体验单机版\n### 1.1.1 在线方式安装\n```\n#在服务器中下载安装脚本,脚本中会重新安装Mysql\nwget https://s3-gzpu.didistatic.com/pub/knowsearch/deploy_KnowSearch-0.3.1.2.sh\n\n#执行脚本\nsh deploy_KnowSearch-0.3.1.2.sh\n\n#访问测试(默认用户名密码：admin/admin123)\n127.0.0.1:8080\n\t\n```\n\n### 1.1.2 离线方式安装\n\n```\n#将安装包下载到本地且传输到目标服务器\nwget https://s3-gzpu.didistatic.com/pub/knowsearch/KnowSearch-0.3.1.2_offline.tar.gz\n\t\n#解压安装包\ntar -zxf KnowSearch-0.3.1.2_offline.tar.gz\n\t\n#执行安装脚本\ncd ./knowsearch\nsh deploy_KnowSearch-0.3.1.2_offline.sh\n\t\n#访问测试(默认用户名密码：admin/admin123)\n127.0.0.1:8080\n\t\n```\n\n## 1.2 分布式高可用版\n### 1.2.1 安装ansible\n```\n#ansible安装方法 \nyum -y install  ansible\n \n#修改配置文件，避免首访问的机器信息没写入known_hosts文件\nvim /etc/ansible/ansible.cfg\nhost_key_checking = False\n```\n\n### 1.2.2 操作步骤\n\n```\n#下载安装包\nwget https://s3-gzpu.didistatic.com/pub/knowsearch/deploy_KnowSeach.tar.gz\n\n#解压安装包\ntar -zxf deploy_KnowSeach.tar.gz\n\n#修改hosts.ini文件（根据注释和README文件修改）\ncd ./deploy_KnowSeach\nvim hosts.ini\n\n#修改完成后执行安装脚本\nsh install.sh\n\n```\n\n# 二、手动部署\n\n## 1. 部署流程\n\n基础依赖服务部署 ——>  KnowSearch各个模块部署\n\n## 2. 基础依赖服务部署\n ###如已经部署过相关服务，可跳过对其的安装，但配置需要按照文档修改\n \n### 2.1、安装Mysql服务\n ###版本需要5.7及以上\n#### 2.1.1 yum方式安装\n```\n#配置yum源\nwget https://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm\nrpm -ivh mysql57-community-release-el7-9.noarch.rpm\n\t\n#执行安装\nyum -y install mysql-server mysql-client\n\t\n#服务启动\nsystemctl start mysqld\n\t\n#获取初始密码并修改\nold_pass=`grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}' | tail -n 1`\nmysql -NBe \"alter user USER() identified by 'Didi_am_678';\" --connect-expired-password -uroot -p$old_pass\n```\n\t\n####2.1.2 rpm包方式安装（推荐此方式安装）\n```\n#下载安装包\nwget https://s3-gzpu.didistatic.com/knowsearch/mysql5.7.tar.gz\n\n#解压到指定目录\ntar -zxf mysql5.7.tar.gz -C /tmp/\n\t\n#执行安装\nyum -y localinstall /tmp/libaio-*.rpm /tmp/mysql-*.rpm\n\t\n#服务启动\nsystemctl start mysqld\n\t\n#获取初始密码并修改\nold_pass=`grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}' | tail -n 1`\nmysql -NBe \"alter user USER() identified by 'Didi_am_678';\" --connect-expired-password -uroot -p$old_pass\n```\n### 2.2 安装Nginx服务\n ###版本无要求\n\n```\n#yum方式安装\nyum -y install nginx\n\t\n#rpm包方式安装\nwget https://s3-gzpu.didistatic.com/knowsearch/nginx-1.8.1.rpm\n\nrpm -ivh nginx-1.8.1.rpm\n\t\n#服务启动\nsystemctl start nginx\n\n```\n### 2.3 配置JAVA环境\n ###版本要求11 \n \n```\n#下载安装包\nwget https://s3-gzpu.didistatic.com/knowsearch/jdk11.tar.gz\n\n#解压到指定目录\ntar -zxf jdk11.tar.gz -C /usr/local/\n\n#更改目录名\nmv  /usr/local/jdk-11.0.2 /usr/local/java11\n\n#添加到环境变量\necho \"export JAVA_HOME=/usr/local/java11\" >> ~/.bashrc\necho \"export CLASSPATH=/usr/java/java11/lib\" >> ~/.bashrc\necho \"export PATH=\\$JAVA_HOME/bin:\\$PATH:\\$HOME/bin\" >> ~/.bashrc\nsource ~/.bashrc\n```\n    \n### 2.4 Elasticsearch元数据实例搭建\n ###Elasticsearch元数据集群来支持平台核心指标数据的存储，如集群维度指标、节点维度指标等\n\n```\n#下载安装包\nwget https://s3-gzpu.didistatic.com/pub/knowsearch/elasticsearch-v7.6.0.1400.tar.gz\n\n#创建ES数据存储目录\nmkdir -p /data/es_data\n\t\n#创建ES所属用户\nuseradd arius\n\t\n#配置用户的打开文件数\necho \"arius soft nofile 655350\" >>/etc/security/limits.conf\necho \"arius hard nofile 655350\" >>/etc/security/limits.conf\necho \"vm.max_map_count = 655360\" >>/etc/sysctl.conf\nsysctl -p\n\t\n#解压安装包\ntar -zxf elasticsearch-v7.6.0.1400.tar.gz -C /data/\n\t\n#更改目录所属组\nchown -R arius:arius /data/\n\t\n#修改配置文件(参考一下配置)\nvim /data/elasticsearch-v7.6.0.1400/config/elasticsearch.yml\ncluster.name: logi-elasticsearch-meta\nnode.name: es-node1\nnode.master: true\nnode.data: true\npath.data: /data/es_data\nhttp.port: 8060\ndiscovery.seed_hosts: [\"127.0.0.1:9300\"]\n\t\n#修改内存配置\nvim /data/elasticsearch-v7.6.0.1400/config/jvm.options\n-Xms2g\n-Xmx2g\n\t\n#启动服务\nsu - arius\nexport JAVA_HOME=/usr/local/java11\nsh /data/elasticsearch-v7.6.0.1400/control.sh start\n\t\n\t\n#确认状态\nsu - arius\nexport JAVA_HOME=/usr/local/java11\nsh /data/elasticsearch-v7.6.0.1400/control.sh status\n```\n\n### 2.5 安装grafana服务\n\n```\n#下载安装包\nwget https://s3-gzpu.didistatic.com/pub/knowsearch/grafana-8.5.9.tar.gz\n\n#解压安装包\ntar -zxf grafana-8.5.9.tar.gz -C /data/\n\n#启动服务\ncd  /data/grafana-8.5.9/bin/\nnohup ./grafana-server &\n\n#添加数据源（其中url参数需要修改成真实的elasticsearch服务地址）\ncurl -X POST -H \"Content-Type: application/json\" \"http://127.0.0.1:3000/api/datasources\" -d '{\"name\":\"elasticsearch-observability\",\"type\":\"elasticsearch\",\"url\":\"http://127.0.0.1:8060\",\"access\":\"proxy\",\"basicAuth\":false,\"database\":\"index_observability\",\"jsonData\":{\"esVersion\":\"7.0.0\",\"includeFrozen\":false,\"logLevelField\":\"\",\"logMessageField\":\"\",\"maxConcurrentShardRequests\":5,\"timeField\":\"logMills\"},\"readOnly\":false}}' \n\n#导入大盘模版(示例是其中之一，七个模版都要导入)\ncd  /data/grafana-8.5.9/template/\ncurl  -H \"Content-Type: application/json\" -X POST \"http://127.0.0.1:3000/api/dashboards/db\" -d @metrics-process.json\n\n```   \n\n\t\n## 3、KnowSearch服务部署\n ###依赖JAVA11、服务器可用内存大于4G\n### 3.1 admin模块\n\n```\n#下载安装包\nwget https://s3-gzpu.didistatic.com/pub/knowsearch/KnowSearch-0.3.1.2.tar.gz\n\n#解压安装包到指定目录\ntar -zxf KnowSearch-0.3.1.2.tar.gz -C /data/\n\t\n#修改启动脚本并加入systemd管理\ncd  /data/KnowSearch-0.3.1.2/admin/\nsed -i '#dir_home#/data/KnowSearch-0.3.1.2#g' control.sh arius-admin.service\ncp arius-admin.service /usr/lib/systemd/system/\n\t\n#创建相应的库和导入初始化数据\nmysql -uroot -p -e \"CREATE DATABASE IF NOT EXISTS knowsearch;\"\nmysql -uroot -p knowsearch < /data/KnowSearch-0.3.1.2/admin/init/init.sql\n\t\n\t\n#修改配置文件\nvim application-full.yml\n\t\n#admin相关配置\nadmin.port.web: 8015 #admin服务端口\nadmin.contextPath: /admin/api \n\n#gateway相关配置\nes.gateway.url: 127.0.0.1\nes.gateway.port: 8200\n\n#ES元数据集群相关配置\nes.update.cluster.name: logi-elasticsearch-meta\n\n#ES客户端相关配置\nes.client.cluster.port: 8060\n\n#mysql服务相关配置(配置文件中有两部分mysql相关的，都需要修改)\n url: jdbc:mariadb://127.0.0.1:3306/knowsearch?useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=true&allowMultiQueries=true&useSSL=false&alwaysAutoGeneratedKeys=true&serverTimezone=GMT%2B8\n      username: root\n      password: pwd\n      \n#监控大盘ES地址\nelasticsearch-address: 127.0.0.1\nelasticsearch-port: 8060\t\n\n\n#启动服务\nsystemctl daemon-reload\nsystemctl start arius-admin\n\t\n#服务启动成功后执行元数据导入脚本\nsh /data/KnowSearch-0.3.1.2/admin/init/init_knowsearch_liunx.sh\n\n\n#重启服务\nsystemctl restart arius-admin\n\n``` \n\n### 3.2 gateway模块\n\n``` \n#修改启动脚本并加入systemd管理\ncd  /data/KnowSearch-0.3.1.2/gateway/\nsed -i '#dir_home#/data/KnowSearch-0.3.1.2#g' control.sh arius-gateway.service\ncp arius-gateway.service /usr/lib/systemd/system/\n\t\n#修改配置文件\ngateway.cluster.name=logi-elasticsearch-meta #ES集群名称\nelasticsearch.admin.cluster.name=logi-elasticsearch-meta\t\narius.gateway.adminUrl=http://127.0.0.1:8015/\t\nadmin/api/ #arius-admin模块服务地址和端口\ngateway.httpTransport.port=8200 #gateway监听端口\n\t\n#启动服务\nsystemctl daemon-reload\nsystemctl start arius-gateway\n\t\n#启动filebeats服务(IP地址和端口为ES集群地址)\nsh filebeats_start.sh \n```\t\n   \n### 3.3 前端代码部署及配置\n\n```\n#下载配置文件\nwget https://s3-gzpu.didistatic.com/knowsearch/nginx.conf\n\n#将配置文件放到etc目录\nmv nginx.conf /etc/nginx/conf.d/knowsearch_nginx.conf\n\t\n#修改配置文件(data目录是前端文件跟目录,$ip_addr需要换成本机访问IP)\nsed -i 's#c_path#data/KnowSearch-0.3.1.2#g' /etc/nginx/conf.d/knowsearch_nginx.conf\nsed -i 's#ups_admin#127.0.0.1:8015#g' /etc/nginx/conf.d/knowsearch_nginx.conf\nsed -i 's#ups_gateway#127.0.0.1:8200#g' /etc/nginx/conf.d/knowsearch_nginx.conf\nsed -i \"s#jumpToGrafana#http://$ip_addr:3000/dashboards#g\" /data/KnowSearch-0.3.1.2/es/es-*.js\n\n#重启Nginx服务\nsystemctl restart nginx\n```\n\n ###打开浏览器输入NginxIP地址测试，用户名密码（admin/admin123）\n \n# 三、构造测试数据\n \n```\n#下载脚本\nwget https://s3-gzpu.didistatic.com/pub/knowsearch/IndexTestTools.tar.gz\n\n```\n## 1. 目录结构\n  ```\n  IndexTestTools\n├── cluster_info.list\n├── index_name.list\n├── init_data #二级目录\n│ ├── create_index.json\n│ ├── create_template.json\n│ ├── delete_index.json\n│ ├── get_templateID.json\n│ ├── index_data.json\n│ ├── join_cluster.json\n│ ├── query.json\n│ └── template_data.json\n├── IndexTestTools.sh\n  ```\n## 2. 文件作用说明(附json压缩转义方法)\n \n![](https://s3-gzpu.didistatic.com/pub/knowsearch/image/文件作用.png)\n\n附：转义工具：https://www.bejson.com/\n\n压缩json\n\n![](https://s3-gzpu.didistatic.com/pub/knowsearch/image/压缩前.png)\n![](https://s3-gzpu.didistatic.com/pub/knowsearch/image/压缩后.png)\n\n转义json\n![](https://s3-gzpu-inter.didistatic.com/pub/knowsearch/image/转义.png)\n\n## 3. 脚本使用流程\n### 3.1 根据注释提示修改IndexTestTools.sh中的参数\n![](https://s3-gzpu.didistatic.com/pub/knowsearch/image/参数.png)\n\n### 3.2 自定义mapping或者setting \n + 无特殊需求可以使用默认,即不需修改\n + 修改init_data目录下的对应的json文件（参考文件作用说明）\n\n### 3.3 执行IndexTestTools.sh \n\n```\nsh IndexTestTools.sh -h 获取使用方法\n```\n![](https://s3-gzpu.didistatic.com/pub/knowsearch/image/使用方法.png)\n\n+ action参数释义：join 接入集群 ，create创建模版或索引，write写入数据，query查询数据，delete下线模版或索引，其他参考组合用法\n+ type参数释义：操作类型，索引或模版\ncount参数释义：写入或查询时指定的次数，不指定时默认为1，-1表示持续\n+ name参数为空时需要在IndexTestTools.sh脚本中指定cluster_name参数\n+ action参数为write/query可以指定次数（不指定默认为1次）\n\n### 3.4其他\n\n```\nsh IndexTestTools.sh -a=write -t=index -c=10 #表示往每个索引写入10次，指定为-1时 代表持续写入，在持续写入时可以使用nohup sh IndexTestTools.sh -a=write -c=-1 & 进行后台运行\nsh IndexTestTools.sh -a=query -t=index -c=10 #表示索引查询10次，指定为-1时 代表持续查询，在持续查询时可以使用 nohup sh IndexTestTools.sh -a=query -c=-1 & 进行后台运行\n\n组合用法1：接入集群+创建模版/索引+写入数据\nsh IndexTestTools.sh -a=joinANDcreateANDwrite -t=index\n\n组合用法2: 创建模版/索引+写入数据（集群需要已接入）\nsh IndexTestTools.sh -a=createANDwrite -t=index\n```\n"
  },
  {
    "path": "doc/KnowSearch常见FAQ.md",
    "content": "#  1.KnowSearch体验\n\n# 1.1 如何零门槛体验KnowSearch观测能力？\n<img src=\"./file/KnowSearch-ManagCluster.png\"  style=\"zoom:50%;\" />\n\n# 1.2 如何零侵入体验GateWay的DSL查询模板的观测与管控能力\n\n这里默认你已经是KnowSearch管理员，熟悉  [**应用、ES_USER、集群类型**] 平台基本概念，有疑问请查看[KnowSearch用户指南](./KnowSearch用户指南.md)中概念说明章节。\n\n<img src=\"./file/KnowSearch-AppAcess.png\"  style=\"zoom:50%;\" />\n\n这里默认你已经知悉GateWay的基本功能，熟读GateWay设计，熟悉其中的前置概念**[访问模式]**，零侵入体验GateWay，访问模式需要选择原生模式的ES_USER。\n\n- 原生模式：会检验ES_USER，根据ES_USER指定的集群路由请求，所有请求都会转发给目标ES集群，除了要加上(ES_USER/校验码)外其他跟直接访问ES没区别\n\n<img src=\"./file/KnowSearch-ESUser.png\"  style=\"zoom:50%;\" />\n\n- 代码访问改造样例，在HTTP头域中增加ES_USER/ES_SECRET\n\n```java\npublic void usingHttp() {\n    String url = \"http://10.88.128.149:30963/data-fd_es_gateway_stats_log/stats.log/_search?q=field:value\";\n    HttpGet get = new HttpGet(url);\n    //在请求头中加入Authorization，并且将Token用base64加密 Token为ES_USER/ES_SECRET\n    get.setHeader(\"Authorization\", \"Basic \" + new BASE64Encoder().encode(String.format(\"%s:%s\", ES_USER, ES_SECRET).getBytes(\"UTF-8\")));\n    CloseableHttpResponse response = null;\n    try {\n        response = httpClient.execute(get);//执行GET请求\n    } catch (IOException e) {\n        e.printStackTrace();\n    }\n    HttpEntity entity = response.getEntity();//获取结果\n}\n  \npublic void usingHttpSql() {\n    String url = \"http://10.88.128.149:30963/_sql\";\n    HttpPost httpPost = new HttpPost();\n    //在请求头中加入Authorization，并且将Token用base64加密 Token为ES_USER/ES_SECRET\n    httpPost.setHeader(\"Authorization\", \"Basic \" + new BASE64Encoder().encode(String.format(\"%s:%s\", ES_USER, ES_SECRET).getBytes(\"UTF-8\")));\n    httpPost.setURI(new URI(url)));\n    StringEntity stringEntity = new StringEntity(\"select * from xxx\", \"UTF-8\");\n    httpPost.setEntity(stringEntity);\n    CloseableHttpResponse response = null;\n    try {\n        response = httpClient.execute(httpPost);//执行POST请求\n    } catch (IOException e) {\n        e.printStackTrace();\n    }\n    HttpEntity entity = response.getEntity();//获取结果\n    if (entity != null) {\n       String result = EntityUtils.toString(entity);\n       EntityUtils.consume(entity);\n    }\n}\n```\n\n- CURL调用样例\n\n```java\ncurl -XGET \"http://ES_USER:ES_SECRET@10.88.128.149:30963/{index}/_search?pretty\"\ncurl -XPOST \"http://ES_USER/ES_SECRET@10.88.128.149:30963/_sql\" -d \"select * from index limit 1\"\ncurl -XPOST \"http://ES_USER/ES_SECRET@10.88.128.149:30963/{index}/id/_update\" -d'{\"doc\":{\"phone\":\"18515010454\", \"send_time\":\"2020-02-05 01:00:29\"}}'\n```\n\n\n\n# 2.索引写入\n\n## 2.1 ES_USER级别限流和查询模板级别限流的是什么？\n\nES_USER级别限流是针对整个用户每秒最多能查询多少次，如果触发到ES_USER级别限流，会接收到 FlowLimitException 错误。查询模板级别限流是针对相同结构的查询语句每秒最多能查询多少次，如果触发到查询模板级别限流，会接收到 DslRateLimitException 错误，这里的限流值GateWay单实例生效。\n\n## 2.2 mapping是什么？\n\n- mapping是Lucence存储与索引字段的方式和规则，如某个字段的数据类型、默认值、分析器、是否被索引等。\n- 参考官方文档：https://www.elastic.co/guide/en/elasticsearch/reference/master/mapping.html\n\n## 2.3 数据已经接放ES，现在想增加一些新的字段 ，该怎么做？\n\nES 会动态判断该字段类型并建立索引，并且会按照该字段首次出现的类型来定义该字段。例如: 新增字段 {\"name\":\"dididatabus\"} es会判断为 string 类型。\n\n## 2.4 时间字段起到什么作用？\n\n时间字段主要用于时间分区的作用，为了防止索引膨胀，ES 会根据时间字段写入索引名称，分区主要有按天、按月两种，例如（indexname_2018-08-08、indexname_201808），默认情况下保存天数超过一个月会按月建立索引，其它时间会按天进行建立。\n\n\n\n# 3.索引查询\n\n## 3.1 DSL查询语法如何编写？\n\n参考官网手册：https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html\n\n## 3.2 为什么不能查询排序在10000条以后的数据？\n\n很多用户都有疑问，ES 为什么不能查询 10000 条之后的数据。了解这个问题需要了解到es的分布式原理。ES 一个索引是对应到多个shard（数据分片），对于带size的查询，es是在每个shard上都会返回size条数据，如果索引有 100 个 shard，那就是得先汇聚 100*size 条数据，然后再排序选出size条数据。所以分页太深，ES 汇聚的数据量太大，会导致 ES 节点不堪重负。如果用户想查看深分页的数据，有两种方式，一种是带上 where 条件，让10000条之后的数据能通过查询条件，在前面被查出来。另一种是针对获取大量数据的场景，使用 ES 的 scroll 方式，可以批量捞取全量的数据。不过官方不再建议使用scroll API进行深度分页。如果要分页检索超过 Top 10,000+ 结果时，推荐使用：PIT + search_after。\n\n## 3.3 关于分页查询\n\n### 3.3.1 主要有三种分页查询方式\n\n- From + Size 查询：优点是支持随机翻页，受制于 max_result_window 设置，不能无限制翻页，存在深度翻页问题，越往后翻页越慢，深分页不推荐使用；\n- Search After 查询：查询本质是使用前一页中的一组排序值来检索匹配的下一页，并且不严格受制于 max_result_window，可以无限制往后翻页，但是不支持随机翻页；\n- Scroll 查询：相比于 From + Size 和 search_after 返回一页数据，Scroll API 可用于从单个搜索请求中检索大量结果（甚至所有结果），其方式与传统数据库中游标（cursor）类似，支持全量遍历，但是响应时间是非实时 ，并且保留上下文需要足够的堆内存空间。\n\n### 3.3.2 分别的使用场景\n\n- From + Size 查询：非常适合小型数据集或者大数据集返回 Top N（N <= 10000）结果集的业务场景，支持随机跳转分页的业务场景；\n\n- Search After 查询：不支持随机翻页，更适合手机端应用的场景（一直往下滑动刷新数据的场景）；\n\n- Scroll 查询：全量或数据量很大时遍历结果数据，而非分页查询，并且对实时性要求不高的场景。关于具体的使用方式请见官方文档。\n\n# 4.DSL无法切换集群\n修改nginx.conf配置\n```java\n   location ~ ^/api/es/gateway/ {\n   \n      rewrite ^/api/es/gateway/(.*)$ /$1 break; # 路径规则重写\n      \n      proxy_pass http://127.0.0.1:8060;  #这个地址需要改成网关地址\n      \n  }\n  ```\n"
  },
  {
    "path": "doc/KnowSearch源码编译运行文档.md",
    "content": "# 工程介绍\n\nKnowSearch采用前后端分离架构，前端工程包括arius-console，后端工程包括arius-admin(管控服务)、arius-gateway(网关服务)\n\n# 前端工程编译和运行\nclone 项目到本地，使用idea单独打开arius-console工程后，具体详细操作查看 [前端工程README.md](../arius-console/readme.md)\n\n# 后端工程编译和运行\nclone 项目到本地，使用idea分别单独打开arius-admin工程和arius-gateway工程\n\n具体编译、运行流程请查看  [arius-admin README](../arius-admin/README.md)  [arius-gateway工程README](../arius-gateway/README.md)\n"
  },
  {
    "path": "doc/KnowSearch用户手册.md",
    "content": "# 1.概述\n\n通过阅读此文档，您可以了解到KnowSearch的一些基于滴滴最佳实践的概念说明以及平台侧一些高频及重点操作的使用方法。以便您可以通过便捷的接入方式快速体验ES集群指标监控与运维管控的全流程。\n\n# 2.概念说明\n\n## 2.1 Region\n\n为解决物理资源利用率的问题及实现租户隔离，抽象出物理集群--逻辑集群的双层架构模型，将物理集群的节点资源以region的形式划分并与租户的逻辑集群进行绑定，这个概念会在后面的场景化介绍中进行详细阐述。\n\n## 2.2 租户\n\n### 2.2.1 应用\n\n为了保障租户的信息和数据安全，以应用为单元进行资源管理（这里的应用可以理解为不同的业务线，对资源的权限是相互隔离的），以ES_User作为媒介进行鉴权，实现多租户数据权限隔离，同时利用不同的应用去区分资源权限，KnowSearch会预置一个SuperApp提供给平台全部管理员进行物理集群的运维纳管；并且会预置一个元数据应用作为管理元数据集群的资源信息。\n\n### 2.2.2 角色\n\n基于标准租户权限模型，以不同角色实现页面资源的权限分配，提供预置两类角色：管理员、资源Owner，并支持自定义角色设置。其中管理员角色比较特殊，属于管理员角色的用户会成为平台全部应用的一员。\n\n### 2.2.3 责任人\n\n责任人作为应用资源的负责人，可用于对接监控告警或信息通知模块。可以理解为应用中的一类特殊成员。\n\n## 2.3 集群类型\n\n在物理集群侧定义了集群类型这个概念，用以区分物理集群到逻辑集群的划分关系，其中涵盖三种类型：独立集群、独享集群、共享集群；\n- 独立集群：支持集群层面的数据隔离（物理集群的全部节点划分为一个Region，并将此Region分配给一个逻辑集群，这样物理集群与逻辑集群是一对一的）\n- 独享集群：支持数据节点层面的隔离（物理集群下的数据节点会划分为多个Region，每个Region只会被一个逻辑集群绑定）\n- 共享集群：数据共享（物理集群下的数据节点会划分为多个Region，每个Region会进行多次分配，既每个Region会被多个逻辑集群绑定）\n\n## 2.4 ES_User\n\nES_User及校验码作为访问网关的用户名和密码，每个应用至少需要一个ES_User及校验码进行ES集群访问与查询\n访问模式分为三种：集群模式、索引模式和原生模式\n- 集群模式：会检验appid以及模板相关权限，然后根据appid指定的集群路由请求\n- 索引模式：会检验appid以及模板相关权限，然后根据模板对应的具体集群路由请求\n- 原生模式：会检验appid，然后会根据appid指定得集群路由请求，就充当路由功能，然后所有请求都会转发给es，除了要加上appid外其他跟直接访问es基本没区别\n\n## 2.5 工单\n\n工单模块分为资源申请及资源审批两部分组成，普通用户根据所需申请资源以及对自身资源的扩缩会生成对应工单，管理员通过审批流程完成资源的分配。针对平台普通用户对于资源的重大变更操作同样支持通过工单审批完成。\n\n# 3.重点场景介绍\n\n通过预置的两类角色：管理员、资源owner区分运维人员和普通用户，以下将通过两类角色的体验路径进行逐一介绍产品功能\n<img src=\"./file/KnowSearch-Experience path.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n## 3.1 运维管理员\n\n安装部署好KnowSearch后，管理员用户需要对物理资源进行统一接入管理，通过“应用”做好对应的资源分配与用户管理。\n\n### 3.1.1 接入集群\n\n如下图所示，进入集群管理-->物理集群，点击【接入集群】，填写集群基本信息。\n- 集群名称：支持大小写字母、数字、-、_、1-32位字符\n- 录入规则：自动获取可以通过添加单个可接入节点进行集群接入；全量录入可添加全量集群节点（包括离线节点）\n- 高级选项：集群类型默认独立集群；数据中心默认为空，可前往【平台配置】查看对应配置：cluster.data.center_list；IaaS平台类型默认为空，可前往【平台配置】查看对应配置：cluster.resource.type_list；账户名、密码默认为空，若集群设置了密码可自行添加。\n\n<img src=\"./file/KnowSearch-Physical cluster.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n### 3.1.2 集群运维\n\n物理集群接入后，可通过集群快捷命令进行快速运维\n\n<img src=\"./file/KnowSearch- Cluster Operations.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 快捷命令包含一些高频的集群运维指令，可实现集群的node_state分析、indices分析、shard分布、pending task分析、task任务分析、热点线程分析\n\n<img src=\"./file/KnowSearch-Shortcut Command.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 点击集群名称，进入集群详情，可进行集群基础信息的查询\n\n<img src=\"./file/KnowSearch-Cluster Particulars.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 除查看物理集群的基本信息外还包含对于物理集群的sense查询及动态配置变更\n\n<img src=\"./file/KnowSearch-Search.png\" alt=\"1001\" style=\"zoom:50%;\" />\n<img src=\"./file/KnowSearch-Configuration .png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n### 3.1.3 资源划分\n\n- 物理集群的region划分及扩缩容\n - Region划分：点击物理集群列表操作列中的【Region划分】，选择对应的数据节点并定义好Region名称完成对物理资源的划分，这里的操作需要为后续的逻辑集群划分做准备。\n\n <img src=\"./file/KnowSearch-Region.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n - Region管理：点击物理集群列表操作列中的【Region管理】，可选定对应Region并进行Region的扩缩容\n\n<img src=\"./file/KnowSearch-Region Management.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n### 3.1.4Dashboard与指标看板运维\n\nKnowSearch 提供了多种维度的指标采集和展现能力，针对集群、索引、节点提供全面的指标监控体系，实时掌握集群性能及业务情况。\n首页的Dashboard与菜单中的指标看板模块组合起来的指标运维体系是基于滴滴多年的运维经验进行提炼整合的一整套解决方案，其中指标含义及计算方式详见指标字典：（指标字典地址）。另外还提供了针对网关的指标监控体系，将用户通过网关访问ES的行为中提炼有运维价值的指标信息进行分类展示。\n\n- Dashboard模块是全平台纳管资源视角，根据典型运维场景，从集群、节点、索引三个维度整合出对应的风险预警指标，通过预警指标发现问题。\n- 每项指标均会注明指标价值及计算逻辑并支持选择Top5-Top50\n\n<img src=\"./file/KnowSearch-Dashboard Main.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 每项指标对象均支持跳转到对应的指标看板，以集群为例，点击某一集群对象，可跳转集群看板查看详细指标数据\n\n<img src=\"./file/KnowSearch-Dashboard click .png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 进入集群看板后，可以根据自身需要进行灵活的指标配置，我们也提供不同维度的指标聚合，支持Top级指标查看（举例：如选择Top5，则会展示当前时间点指标值为Top5的指标分布情况）、最长七天时间回溯展示、黄金指标一键配置。\n\n<img src=\"./file/KnowSearch-Cluster Board.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 同时我们也提供多维度的指标查看，其中包含总览视图、节点视图、索引视图\n总览视图是对选定集群概览信息的指标整合，如索引数、shard数、节点组成及状态、内存占用等集群基本信息；同时将指标细分为系统指标、性能指标及状态指标，见下图。\n\n<img src=\"./file/KnowSearch-Cluster Overview .png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n<img src=\"./file/KnowSearch-Cluster Overview Target .png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 节点视图是对选定集群节点指标信息的整合，细分为以下六类：系统指标、进本性能指标、高级性能指标、JVM指标、Breaker指标、内存大小指标\n\n<img src=\"./file/KnowSearch-Node Target 1.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n<img src=\"./file/KnowSearch-Node Target 2.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 索引视图是对选定集群索引指标信息的整合，细分为以下三类：索引基础指标、索引性能指标、索引内存指标\n\n<img src=\"./file/KnowSearch-Index Target 1.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n### 3.1.5网关指标查看\n\nKnowSearch将每一项通过网关进行访问的指标进行提炼整合，围绕网关的指标监控体系提供了多维度指标查看，其中分为节点视图、clientnode视图、索引视图、应用视图、查询模板、总览视图。支持Top级指标查看，最长七天时间回溯展示。\n\n<img src=\"./file/KnowSearch-Gateway.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n### 3.1.6多应用创建及租户分配\n\n以预置管理员账户（admin/admin123）登录KnowSearch平台后，该用户属于SuperApp，然后前往【租户管理】-->【应用管理】，点击【新建应用】进行应用创建。\n\n<img src=\"./file/KnowSearch-Create App.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 创建应用时，需要把相关用户绑定到新建的应用下，这样，应用下全部用户对于资源的权限都是一致的；或者在已有应用的列表中点击【编辑】进行用户添加。\n\n<img src=\"./file/KnowSearch-App List.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 应用创建好后，该应用下的用户就可以进行资源申请了\n\n### 3.1.7工单审批\n\n管理员用户接收到普通用户提交的资源申请工单后需要进行资源审批，以集群申请为例，集群类型与数据节点规格需要严格一致，节点数需要大于等于申请节点数\n\n<img src=\"./file/KnowSearch-Ticket System.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n## 3.2 普通用户\n\n普通用户登录KnowSearch后，如果没有应用，需要自己去创建应用，用于后续的资源管理。拥有应用的用户可以直接进行资源申请操作。（注：资源Owner为默认角色，用户注册后默认是资源Owner角色）\n\n### 3.2.1 申请集群资源\n\n- 普通用户登录平台，选择对应应用，前往【集群管理】-->【我的集群】\n- 点击【申请集群】，填写集群申请表单\n - 集群名称：支持大小写字母、数字、-、_、1-32位字符\n - 集群版本：平台纳管的全部物理集群的版本信息\n - 集群类型：根据所需进行选择\n - 业务等级：主要是为了标记承载业务的重要程度，这里分为核心、重要、一般\n - Datenode：平台纳管的全部物理集群的数据节点规格信息，根据所需进行选择\n\n <img src=\"./file/KnowSearch-Logic Cluster.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n### 3.2.2 集群资源管理\n\n集群资源申请成功后，会在我的集群侧新增一条数据项，可进行集群扩缩容的申请及集群下线。\n\n <img src=\"./file/KnowSearch-Logic Cluster List.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n点击集群名称可查看集群详情及绑定的节点信息。\n\n <img src=\"./file/KnowSearch-Logic Cluster Particulars .png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n### 3.2.3 索引资源管理\n\n进入索引管理，如下图所示，可进行索引创建、编辑Mapping、编辑Setting、设置别名、下线，此处的索引列表包括全平台全部的索引。\n\n <img src=\"./file/KnowSearch-Index List.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 索引创建需要定义好索引名称并选定创建的集群，设置好Mapping、Setting后即可完成创建（其中Mappign和Setting的内容提供填写示例及官方指导）\n\n <img src=\"./file/KnowSearch-Create Index .png\" alt=\"1001\" style=\"zoom:50%;\" />\n \n- 注：索引创建前应用内必须存在集群资源，若无集群资源需前往【我的集群】进行资源申请\n\n### 3.2.4查看集群指标信息\n\nKnowSearch为普通用户也提供了完善的指标观测体系，其中分为索引视图、总览视图、节点视图三个视角，用户可以根据自身需要进行灵活的指标配置，我们也提供不同维度的指标聚合，支持Top级指标查看（举例：如选择Top5，则会展示当前时间点指标值为Top5的指标分布情况）、最长七天时间回溯展示。\n\n<img src=\"./file/KnowSearch-Cluster Board For User.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n# 4.其他功能介绍\n\n## 4.1 索引管理与服务\n\n进入索引管理，如下图所示，可进行索引创建、编辑Mapping、编辑Setting、设置别名、下线，此处的索引列表包括全平台全部的索引。\n\n<img src=\"./file/KnowSearch-Index List.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 索引创建需要定义好索引名称并选定创建的集群，设置好Mapping、Setting后即可完成创建（其中Mappign和Setting的内容提供填写示例及官方指导）\n\n<img src=\"./file/KnowSearch-Creat Index .png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 编辑Mapping、Setting同上\n- 除基础信息变更外还提供别名设置能力，为后续的rollover等能力提供服务\n\n进入索引管理-->索引服务，如下图所示，可针对平台索引进行索引管控运维操作，这里包含Rollover、Shrink、Split、ForceMerge及对索引读写的启用/禁用等基础变更能力。\n\n<img src=\"./file/KnowSearch-Index Service .png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n## 4.2 检索查询\n\n为了在DSL语句级别保障查询公共资源的稳定性，KnowSearch 服务会进行DSL的分析、管控和限流。KnowSearch 会记录用户的查询语句，并对查询语句进行模板抽象，进而分析出用户查询特点(查询次数，查询耗时分位等信息)。进入检索查询-->DSL查询进行操作。\n- DSL查询会提供常用的默认查询语句，历史查询记录也会被记录，以便保留高频的查询语句。\n- 右上角可进行集群对象选择\n\n<img src=\"./file/KnowSearch-DSL.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 异常分析：如下图所示，提供DSL模板的异常查询和慢查询列表的查看以及异常原因的展示\n - 慢查询语句：查询请求到达gateway，gateway会记录一个请求时间，gateway处理完相关业务后请求响应前为当前时间，如果当前时间-请求时间大于一秒，则视为慢查询语句。\n\n <img src=\"./file/KnowSearch-Slow Search.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n - 注：慢查询时间阈值可在应用管理侧进行配置，支持应用级慢查设置。（应用管理-->编辑）\n\n  <img src=\"./file/KnowSearch-Time Setting.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n - 异常查询语句：这里分为触发ES查询异常和触发gateway异常，ES查询异常包括：查询不存在索引或文档、scroll查询上下文过大或json_parse_exception；触发gateway异常包括：appid粒度的限流触发、dsl查询模版粒度的限流触发、索引对应的模版不存在、appid不存在、appid权限校验失败等等。\n\n   <img src=\"./file/KnowSearch-Unusual Search.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n## 4.3 工单申请及审批\n\n普通用户的资源变更操作会生成对应工单，管理员通过工单进行资源的审批及分配。\n- 进入工单任务-->我的审批可查看全部可审批工单\n\n <img src=\"./file/KnowSearch-Examine And Approve.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 点击工单名称可查看工单详情并进行审批操作，以集群申请工单为例，通过该项工单需进行根据用户需要进行资源分配。\n\n <img src=\"./file/KnowSearch-Ticket System.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n## 4.4 租户管理\n\n租户管理分为用户管理、角色管理、应用管理\n- 用户管理：展示全平台全部的用户，可进行用户的增删及角色分配\n\n <img src=\"./file/KnowSearch-User List.png\" alt=\"1001\" style=\"zoom:50%;\" />\n \n- 角色管理：展示全平台全部角色，可进行角色的增删及用户分配。注：这里会预置两类默认角色：管理员和资源Owner作为区分运维管理员及普通用户；后续新增的角色也会基于资源Owner去做扩展。\n\n <img src=\"./file/KnowSearch-Role List.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n- 应用管理：展示全平台全部应用，可进行角色的增删及访问设置操作。注：这里会预置一个默认应用SuperApp，SuperApp默认与管理员角色的用户强绑定，既SuperApp下的用户仅为管理员用户。\n\n <img src=\"./file/KnowSearch-App Management.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n## 4.5 平台配置及调度任务\n\n平台配置说明：平台配置的功能主要用于对于整个平台而言相对重要通用，且需对外提供可选操作的属性，按照配置组和配置名称进行分类别的的配置，提供灵活的配置能力。例如常规配置组别下的黑名单控制权限，对于资源管控中cpu占用率的设置，冷热存的天数设置等等。\n\n<img src=\"./file/KnowSearch-Platform Configuration.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n调度任务说明：KnowSearch 中业务需要定时来调度执行，比如：定时提前创建模板对应的分区索引、定时清理过期的索引等操作。KnowSearch 中的调度任务是平台的核心依赖，建议在阅读该说明前，可以先仔细阅读 KnowSearch 的架构设计和业务说明。\n\n<img src=\"./file/KnowSearch-Task List.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n## 4.6 操作记录\n\n全平台数据变更操作记录，可用于后期审计。\n\n<img src=\"./file/KnowSearch-Operating Record .png\" alt=\"1001\" style=\"zoom:50%;\" />"
  },
  {
    "path": "doc/KnowSearch设计说明.md",
    "content": "# 1. 背景介绍\n\nElasticsearch广泛应用于交易明细数据多维度近实时检索、海量日志探查与安全分析、企业SKU搜索与推荐等场景。随着读写业务量和集群索引与存储规模的增长，ES 使用和运维面临一系列问题，主要分为以下两类：\n\n- 烟囱式集群构建\n  - **技术架构门槛高**：版本选择、容量预估、部署架构设计，需要结合业务特点与引擎能力，深度洞察与持续运营\n  - **数据建模门槛高**：数据建模需要深度ES索引原理掌控，结合业务特点，持续测试与数据探查，业界配套工具缺失\n  - **学习掌控门槛高**：DSL语法复杂，过于灵活，版本兼容性差\n- 探索式运维保障\n  - **高可用体系缺失**：多活高可用、多集群管理、跨集群数据迁移能力缺失\n  - **诊断体系缺失**：系统指标、日志指标、ES业务指标观测体系缺失**，**问题诊断低效\n\nKnowSearch针对上述痛点，依托滴滴Elasticsearch多年企业级服务经验，结合金融级商业客户近千套ES集群运维实践迭代而来。在开源 Elasticsearch 基础上滴滴提供**离线索引快速迁移**、**索引跨集群复制**、**集群运维管理**的商业特性。\n\n\n\n# 2.产品设计\n\n## 2.1 核心概念\n\n**我的集群与物理集群，解耦ES用户与ES运维**\n\n- 物理集群：基于真实保障能力(资源类型、高可用手段、故障恢复预案、引擎掌控能力)，基于Region匹配业务诉求，是持续精进与运营的核心依赖\n- 我的集群(逻辑集群)：表达业务场景（转化SLA需求）、资源规模诉求（资源规格澄清），将物理集群的节点资源以Region的形式划分并与租户的逻辑集群进行绑定\n- 集群类型：**共享集群、独享集群、独立集群**\n\n  - 共享、独享、独立是DataNode资源隔离、运维保障、高可用能力承载的解决方案层呈现，底层资源隔离类型变更对业务透明\n    - 共享：DataNode组成一个Region在多个逻辑集群之间复用\n    - 独享：一组DataNode组成一个Region被一个逻辑集群独占\n    - 独立：一个物理集群唯一对应一个逻辑集群、实现DataNode、MasterNode的隔离\n  - 用户参与度依次变高(感知业务监控，感知集群监控，参与资源变更，接收集群告警)，SLA逐级越高(99%->99.9%->99.95%)，自由与责任动态的均衡，随着平台能力越强，整体对用户的依赖与限制会逐渐降低\n\n**索引模板与索引，解耦ES用户与ES运维保障**\n\n- 索引模板是**资源治理的最小业务单元**，承载业务数据建模的核心抓手，平台资源管控的最小粒度\n- 索引是ES集群原生能力的最小单元呈现，是ES运维保障的最小粒度\n\n## 2.2 服务体系\n\n滴滴内部从平台建设、运维建设、引擎建设三个方面着手，相互配合，相互递进，打造了一整套可见、可管、可控ES服务治理体系\n\n\n\n<img src=\"./file/KnowSearch-ServiceArchitect.png\" alt=\"1001\" style=\"zoom:50%;\" />\n\n### 2.2.1 平台建设\n\n主要目标是降低用户使用门槛，沉淀用户最佳实践，以索引模板为核心，围绕企业级最佳实践构建整套服务体系\n\n- 读写网关：读写 ES 网关提供了100%适配原生 ES RestClient 的接口功能，零侵入、插件化的进行了企业特性增强：查询/写入限流、权限校验、跨集群访问、DSL分析与管控。\n- 索引模板：索引模板是用户索引需求表达的最小业务单元，规范用户使用，降低学习Mapping/Setting门槛，提供了 SQL/DSL数据探查、查询模板监控与诊断功能特性。\n\n### 2.2.2 运维建设\n\n主要目标是主动发现ES 集群潜在风险点，快速诊断ES线上问题，ES高频运维能力批量变更\n\n- 多集群管理：全面纳管5.X之后ES版本，高频运维命令GUI化(_nodes/_stat分析、indices分析、shard分布、task分析、hot_thread分析、动态配置)、Sense查询、SearchProfile能力深度集成、节点列表与Region管理。\n- 多集群监控：Dashboard围绕集群、节点、索引、网关维度，近30+高危风险点主动巡检；集群看板围绕集群、节点、索引、索引模板200+指标同环比多维度对比分析；网关看板围绕用户视角读写流量、查询语句流量与耗时，进行同环比多维度特征分析。\n- 索引/索引模板管理：围绕索引模板，构建了索引预创建、过期删除、冷热分离、RollOver、DCDR的最佳实践，并支持批量变更；围绕索引高频操作，构建了RollOver、ForceMerge、Translog、Shrink、Split、索引开关、索引禁用读写GUI能力，并支持批量变更。\n\n### 2.2.3 引擎建设\n\n主要目标是Master性能与稳定性提升、索引高可用、索引跨集群快速迁移能力\n\n- ES集群 master 节点性能优化：滴滴搜索团队针对 ES 集群 master 节点处理性能优化，使得单集群能支持大最大 shard 数从万级提升到十万级。\n- 滴滴跨集群同步( DCDR )：滴滴搜索团队自研的跨集群同步能力，类似于 ES 官方的 CCR能力。\n- 滴滴索引快速构建插件( FastIndex )：滴滴搜索团队自研的 TB 级别数据离线快速构建索引能力 。\n\n\n\n# 3.应用架构\n\nKnowSearch 的应用架构是一个典型的分层架构，在业务的具体设计和实现上我们分为以下几层：\n\n<img src=\"./file/KnowSearch-Architecture.png\" style=\"zoom:70%;\" />\n\n- KnowSearch-Console ：遵从前后端分离架构，基于多租户、内置资源Owner和管理员两种角色，面向ES用户、ES运维，基于业务场景提供了可见、可管、可控的产品功能。\n- KnowSearch-Admin：围绕资源管控（集群、索引、索引模板）、运维管理（安装、部署、升级、配置）、命令执行（zeus-agent）、通用安全（用户、角色、资源）进行领域进行建模。对外基于HTTP+Restful协议提供了核心领域服务。\n- KnowSearch-GateWay：提供一个兼容 ES Restclient 接口的数据网关 ，零侵入、插件化的进行了企业特性增强：查询/写入限流、权限校验、跨集群访问、DSL分析与管控，详细设计参见《GateWay工程架构》。\n- KnowSearch-AMS：围绕集群、节点、索引、索引模板，基于自研的分布式Job执行框架，对ES原生指标进行深度加工，产出了200+观测指标，详细设计参见[《KnowSearch指标系统详设》](./KnowSearch指标系统详设.md)\n\n"
  }
]